regina-4.96/admin/cmakelint.pl000755 000765 000024 00000072574 12234011536 016223 0ustar00babstaff000000 000000 #!/usr/bin/perl -w ############################################################################### # Sanity checks CMakeLists.txt files. # # Copyright (C) 2006-2009 by Allen Winter # # Copyright (C) 2008-2010 by Laurent Montel # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License along # # with this program; if not, write to the Free Software Foundation, Inc., # # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # # ############################################################################### # # A program to check KDE CMakeLists.txt files for common errors. # # This program needs a rewrite.. it assumes that each CMake command is # all on 1 line. So stuff can easily fall through the cracks -- Allen # Program options: # --help: display help message and exit # --version: display version information and exit # use strict; use Getopt::Long; use Cwd 'abs_path'; my($Prog) = 'cmakelint.pl'; my($Version) = '1.10'; my($help) = ''; my($version) = ''; my($verbose) = ''; exit 1 if (!GetOptions('help' => \$help, 'version' => \$version, 'verbose' => \$verbose)); &Help() if ($help); if ($#ARGV < 0){ &Help(); exit 0; } &Version() if ($version); my($f,$tot_issues); $tot_issues=0; for $f (@ARGV) { $tot_issues += &processFile($f); } exit $tot_issues; sub processFile() { my($in) = @_; print "Processing $in:\n"; open(IN,"$in") || die "Couldn't open $in"; my($apath) = abs_path($in); my($in_kdelibs)=0; $in_kdelibs=1 if ($apath =~ m+/kdelibs/+); my($in_kdepimlibs)=0; $in_kdepimlibs=1 if ($apath =~ m+/kdepimlibs/+); my($in_kdebase)=0; $in_kdebase=1 if ($apath =~ m+/kdebase/+); my($in_kdegames)=0; $in_kdegames=1 if ($apath =~ m+/kdegames/+); my($top_of_module)=0; $top_of_module=1 if ($apath =~ m+/koffice/CMakeLists.txt+); $top_of_module=1 if ($apath =~ m+/kdereview/CMakeLists.txt+); $top_of_module=1 if ($apath =~ m+/playground/[a-zA-Z_1-9]*/CMakeLists.txt+); $top_of_module=1 if ($apath =~ m+/extragear/[a-zA-Z_1-9]*/CMakeLists.txt+); $top_of_module=1 if ($apath =~ m+/kdebase/(apps|runtime|workspace)/CMakeLists.txt+); $top_of_module=1 if ($apath =~ m+/kde(libs|pimlibs|base|base-apps|base-runtime|base-workspace|accessibility|addons|admin|artwork|bindings|edu|games|graphics|multimedia|network|pim|sdk|toys|utils|develop|devplatform|webdev|plasma-addons)/CMakeLists.txt+); my($top_of_project)=0; $top_of_project=1 if ($apath =~ m+/koffice/[a-zA-Z_1-9]*/CMakeLists.txt+); $top_of_project=1 if ($apath =~ m+/kdereview/[a-zA-Z_1-9]*/CMakeLists.txt+); $top_of_project=1 if ($apath =~ m+/playground/[a-zA-Z_1-9]*/[a-zA-Z_1-9]*/CMakeLists.txt+); $top_of_project=1 if ($apath =~ m+/extragear/[a-zA-Z_1-9]*/[a-zA-Z_1-9]*/CMakeLists.txt+); $top_of_project=1 if ($apath =~ m+/kde(libs|pimlibs|base|accessibility|addons|admin|artwork|bindings|edu|games|graphics|multimedia|network|pim|sdk|toys|utils|develop|devplatform|webdev|plasma-addons)/[a-zA-Z_1-9]*/CMakeLists.txt+); $top_of_project=0 if ($apath =~ m+/(cmake|pics)/+); my(@lines) = ; my($line,$pline); my($linecnt)=0; my($issues)=0; my(@ch,$c); my($nob,$ncb)=(0,0); my($nop,$ncp)=(0,0); my($pack,%optpacks); #look for "bad" stuff my($prevline)=""; foreach $line (@lines) { $linecnt++; chomp($line); #pline is used for paren/brace matching only $pline = $line; $pline =~ s/".*"//g; $pline =~ s/#.*$//; $line =~ s/#.*$//; #remove comments next if (! $line); #skip empty lines next if ($line =~ m/^[[:space:]]$/); #skip blank lines @ch = split(//,$pline); $nob = $ncb = 0; foreach $c (@ch) { $nop++ if ($c eq '('); $ncp++ if ($c eq ')'); $nob++ if ($c eq '{'); $ncb++ if ($c eq '}'); } if ($in !~ m+kjsembed/qtonly/CMakeLists.txt+) { if ($line =~ m/macro_optional_find_package\s*\(\s*([a-zA-Z0-9]*).*\)/i || $line =~ m/find_package\s*\(\s*([a-zA-Z0-9]*).*\)/i || $line =~ m/find_program\s*\(\s*([a-zA-Z0-9_]*).*\)/i) { $pack = lc($1); $pack = "libusb" if ($pack eq "usb"); $pack = "mysql_embedded" if ($pack eq "mysql"); if ($pack !~ m/^(carbon|iokit|qt4|kde4internal|kde4|kdewin32|kdepimlibs|kdevplatform|gpgme|kdcraw|kexiv2)/) { $optpacks{$pack}{'name'} = $pack; $optpacks{$pack}{'log'} = 0; } } if ($line =~ m/macro_log_feature\(\s*([A-Z0-9_]*).*\)/i) { $pack = lc($1); if ($pack !~ m/^(compositing|strigiqtdbusclient|xsltproc|qt_qtopengl|ggzconfig)_/ && $pack !~ m/x11_.*_found/ && $pack !~ m/true/i && $pack !~ m/false/i) { $pack =~ s/_xcb//; $pack =~ s/have_//; $pack =~ s/_found//; $pack =~ s/_video//; $pack =~ s/shared_mime_info/sharedmimeinfo/; if (!defined($optpacks{$pack}{'name'})) { # if ($pack !~ m/^(kwin_compositing|current_alsa)/) { $issues++; &printIssue($line,$linecnt,"macro_log_feature($pack) used without a corresponding find_package"); } # } $optpacks{$pack}{'log'} = 1; } } } $issues += &checkLine($line,$linecnt, '[[:space:]]{\$', 'replace "{$" with "${", or garbage detected'); $issues += &checkLine($line,$linecnt, '[[^:print:]]{\$', 'non-printable characters detected'); $issues += &checkLine($line,$linecnt, '[Kk][Dd][Ee]4_[Aa][Uu][Tt][Oo][Mm][Oo][Cc]', 'KDE4_AUTOMOC() is obsolete. Remove it.'); $issues += &checkLine($line,$linecnt, '^[[:space:]]*[Qq][Tt]4_[Aa][Uu][Tt][Oo][Mm][Oo][Cc]', 'No need for QT4_AUTOMOC(). Remove it.'); #$issues += &checkLine($line,$linecnt, # '[Kk][Dd][Ee]3_[Aa][Dd][Dd]_[Kk][Pp][Aa][Rr][Tt]', # 'Use KDE4_ADD_PLUGIN() instead of KDE3_ADD_KPART()'); $issues += &checkLine($line,$linecnt, '^[[:space:]]*[Aa][Dd][Dd]_[Ll][Ii][Bb][Rr][Aa][Rr][Yy]', 'Use KDE4_ADD_LIBRARY() instead of ADD_LIBRARY()'); $issues += &checkLine($line,$linecnt, 'DESTINATION[[:space:]]\${APPLNK_INSTALL_DIR}', 'APPLNK_INSTALL_DIR is dead with kde4 replace "${APPLNK_INSTALL_DIR}" with "${XDG_APPS_INSTALL_DIR}" and convert desktop file to xdg format (add Categories)'); $issues += &checkLine($line,$linecnt, 'DESTINATION[[:space:]]\${MIME_INSTALL_DIR}', 'Files installed into MIME_INSTALL_DIR will not read. Port them on freedesktop xdg mimetypes.'); $issues += &checkLine($line,$linecnt, 'DESTINATION[[:space:]]/lib/kde[[:digit:]]', 'replace /lib/kde" with "${PLUGIN_INSTALL_DIR}"'); if ($line !~ m/kdeinit/ && $prevline !~ m/kdeinit/) { $issues += &checkLine($line,$linecnt, 'DESTINATION[[:space:]]\$\{LIB_INSTALL_DIR\}\s*\)', 'replace "DESTINATION ${LIB_INSTALL_DIR}" with "${INSTALL_TARGETS_DEFAULT_ARGS}"'); $issues += &checkLine($line,$linecnt, 'DESTINATION[[:space:]]lib', 'replace "DESTINATION lib" with "${INSTALL_TARGETS_DEFAULT_ARGS}"'); } $issues += &checkLine($line,$linecnt, 'DESTINATION[[:space:]]\${LIB_INSTALL_DIR}/\$', 'replace "${LIB_INSTALL_DIR}/${...}" with "${LIB_INSTALL_DIR}/realname"'); $issues += &checkLine($line,$linecnt, 'DESTINATION[[:space:]]/*include/*', 'replace "include" or "/include" with "${INCLUDE_INSTALL_DIR}"'); $issues += &checkLine($line,$linecnt, 'DESTINATION[[:space:]]\${INCLUDE_INSTALL_DIR}/\$', 'replace "${INCLUDE_INSTALL_DIR}/${...}" with "${INCLUDE_INSTALL_DIR}/realname"'); if ($line !~ m/PROGRAMS/ && $line !~ m/FILES/ && $line !~ m/PERMISSIONS/ && $line !~ m/OWNER/ && $line !~ m/GROUP/ && $line !~ m/WORLD/) { $issues += &checkLine($line,$linecnt, 'DESTINATION[[:space:]]\$\{BIN_INSTALL_DIR\}\s*\)', 'replace "DESTINATION ${BIN_INSTALL_DIR}" with "${INSTALL_TARGETS_DEFAULT_ARGS}"'); $issues += &checkLine($line,$linecnt, 'DESTINATION[[:space:]]/*bin/*', 'replace "DESTINATION bin" or "/bin" with "${INSTALL_TARGETS_DEFAULT_ARGS}"'); } $issues += &checkLine($line,$linecnt, 'DESTINATION[[:space:]]\${BIN_INSTALL_DIR}/\$', 'replace "${BIN_INSTALL_DIR}/${...}" with "${BIN_INSTALL_DIR}/realname"'); $issues += &checkLine($line,$linecnt, 'DESTINATION[[:space:]]/*share/doc/HTML/*', 'replace "share/doc/HTML/" or "/share/doc/HTML/" with "${HTML_INSTALL_DIR}"'); $issues += &checkLine($line,$linecnt, 'DESTINATION[[:space:]]/*share/apps/*', 'replace "share/apps" or "/share/apps" with "${DATA_INSTALL_DIR}"'); $issues += &checkLine($line,$linecnt, 'DESTINATION[[:space:]]\${DATA_INSTALL_DIR}/\$', 'replace "${DATA_INSTALL_DIR}/${...}" with "${DATA_INSTALL_DIR}/realname"'); $issues += &checkLine($line,$linecnt, 'DESTINATION[[:space:]]/*share/applications/*', 'replace "share/applications" or "/share/applications" with "${XDG_APPS_INSTALL_DIR}"'); $issues += &checkLine($line,$linecnt, 'DESTINATION[[:space:]]/*share/autostart/*', 'replace "share/autostart" or "/share/autostart" with "${AUTOSTART_INSTALL_DIR}"'); $issues += &checkLine($line,$linecnt, 'DESTINATION[[:space:]]\${AUTOSTART_INSTALL_DIR}/\$', 'replace "${AUTOSTART_INSTALL_DIR}/${...}" with "${AUTOSTART_INSTALL_DIR}/realname"'); $issues += &checkLine($line,$linecnt, 'DESTINATION[[:space:]]/*share/icons/*', 'replace "share/icons" or "/share/icons" with "${ICON_INSTALL_DIR}"'); if ($in !~ m/IconThemes/) { $issues += &checkLine($line,$linecnt, 'DESTINATION[[:space:]]\${ICON_INSTALL_DIR}/\$', 'replace "${ICON_INSTALL_DIR}/${...}" with "${ICON_INSTALL_DIR}/realname"'); } $issues += &checkLine($line,$linecnt, 'DESTINATION[[:space:]]/*share/locale/*', 'replace "share/locale" or "/share/locale" with "${LOCALE_INSTALL_DIR}"'); $issues += &checkLine($line,$linecnt, 'DESTINATION[[:space:]]\${LOCALE_INSTALL_DIR}/\$', 'replace "${LOCALE_INSTALL_DIR}/${...}" with "${LOCALE_INSTALL_DIR}/realname"'); $issues += &checkLine($line,$linecnt, 'DESTINATION[[:space:]]/*share/services/*', 'replace "share/services" or "/share/services" with "${SERVICES_INSTALL_DIR}"'); $issues += &checkLine($line,$linecnt, 'DESTINATION[[:space:]]\${SERVICES_INSTALL_DIR}/\$', 'replace "${SERVICES_INSTALL_DIR}/${...}" with "${SERVICES_INSTALL_DIR}/realname"'); $issues += &checkLine($line,$linecnt, 'DESTINATION[[:space:]]/*share/sounds/*', 'replace "share/sounds" or "/share/sounds" with "${SOUND_INSTALL_DIR}"'); $issues += &checkLine($line,$linecnt, 'DESTINATION[[:space:]]\${SOUND_INSTALL_DIR}/\$', 'replace "${SOUND_INSTALL_DIR}/${...}" with "${SOUND_INSTALL_DIR}/realname"'); $issues += &checkLine($line,$linecnt, 'install_targets[[:space:]]*\(', 'replace "install_targets" with "install(TARGETS...)'); $issues += &checkLine($line,$linecnt, 'INSTALL_TARGETS[[:space:]]*\(', 'replace "install_targets" with "install(TARGETS...)'); $issues += &checkLine($line,$linecnt, 'install_files[[:space:]]*\(', 'replace "install_files" with "install(FILES...)'); $issues += &checkLine($line,$linecnt, 'INSTALL_FILES[[:space:]]*\(', 'replace "install_files" with "install(FILES...)'); $issues += &checkLine($line,$linecnt, '\sFILES\sDESTINATION', 'missing list of files between FILES and DESTINATION'); $issues += &checkLine($line,$linecnt, '\sTARGETS\sDESTINATION', 'missing list of files between TARGETS and DESTINATION'); $issues += &checkLine($line,$linecnt, 'DESTINATION\s\$\{INSTALL_TARGETS_DEFAULT_ARGS\}', 'remove DESTINATION keyword before ${INSTALL_TARGETS_DEFAULT_ARGS}'); $issues += &checkLine($line,$linecnt, 'macro_bool_to_01[[:space:]]*\(.*[[:space:]][[:digit:]][[:space:]]*\)', 'do not use a digit as a variable'); $issues += &checkLine($line,$linecnt, 'MACRO_BOOL_TO_01[[:space:]]*\(.*[[:space:]][[:digit:]][[:space:]]*\)', 'do not use a digit as a variable'); $issues += &checkLine($line,$linecnt, '-fexceptions', 'replace "-fexceptions" with "${KDE4_ENABLE_EXCEPTIONS}"'); if ($in !~ m+/(phonon|okular|kopete|kdevelop|libkdegames)/+) { $issues += &checkLine($line,$linecnt, 'set_target_properties.*PROPERTIES.*[[:space:]]VERSION[[:space:]][[:digit:]]', 'replace a hard-coded VERSION with "${GENERIC_LIB_VERSION}"'); $issues += &checkLine($line,$linecnt, 'set_target_properties.*PROPERTIES.*[[:space:]]SOVERSION[[:space:]][[:digit:]]', 'replace a hard-coded SOVERSION with "${GENERIC_LIB_SOVERSION}"'); } #Qt variable $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]QtDBus[\s/)]', 'replace "QtDBus" with "${QT_QTDBUS_LIBRARY}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]Qt3Support[\s/)]', 'replace "Qt3Support" with "${QT_QT3SUPPORT_LIBRARY}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]QtGui[\s/)]', 'replace "QtGui" with "${QT_QTGUI_LIBRARY}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]QtNetwork[\s/)]', 'replace "QtNetwork" with "${QT_QTNETWORK_LIBRARY}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]QtCore[\s/)]', 'replace "QtCore" with "${QT_QTCORE_LIBRARY}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]QtSql[\s/)]', 'replace "QtSql" with "${QT_QTSQL_LIBRARY}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]QtSvg[\s/)]', 'replace "QtSvg" with "${QT_QTSVG_LIBRARY}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]QtSvg[\s/)]', 'replace "QtSvg" with "${QT_QTSVG_LIBRARY}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]QtTest[\s/)]', 'replace "QtTest" with "${QT_QTTEST_LIBRARY}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]QtXml[\s/)]', 'replace "QtXml" with "${QT_QTXML_LIBRARY}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]QtScript[\s/)]', 'replace "QtScript" with "${QT_QTSCRIPT_LIBRARY}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]QtAssistantClient[\s/)]', 'replace "QtAssistantClient" with "${QT_QTASSISTANTCLIENT_LIBRARY}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]QtHelp[\s/)]', 'replace "QtHelp" with "${QT_QTHELP_LIBRARY}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]QtWebKit[\s/)]', 'replace "QtWebKit" with "${QT_QTWEBKIT_LIBRARY}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]QtXmlPatterns[\s/)]', 'replace "QtXmlPatterns" with "${QT_QTXMLPATTERNS_LIBRARY}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]QtMultimedia[\s/)]', 'replace "QtMultimedia" with "${QT_QTMULTIMEDIA_LIBRARY}"'); # kdegames variables if (! $in_kdegames) { $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kdegames[\s/)]', 'replace "kdegames" with "${KDEGAMES_LIBRARY}"'); } # kdelibs variables if (! $in_kdelibs) { $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kdeui[\s/)]', 'replace "kdeui" with "${KDE4_KDEUI_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kio[\s/)]', 'replace "kio" with "${KDE4_KIO_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kdesu[\s/)]', 'replace "kdesu" with "${KDE4_KDESU_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]khtml[\s/)]', 'replace "khtml" with "${KDE4_KHTML_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kparts[\s/)]', 'replace "kparts" with "${KDE4_KPARTS_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kde3support[\s/)]', 'replace "kde3support" with "${KDE4_KDE3SUPPORT_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kutils[\s/)]', 'replace "kutils" with "${KDE4_KUTILS_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kdnssd[\s/)]', 'replace "kdnssd" with "${KDE4_KDNSSD_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]knewstuff2[\s/)]', 'replace "knewstuff2" with "${KDE4_KNEWSTUFF2_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]knewstuff3[\s/)]', 'replace "knewstuff3" with "${KDE4_KNEWSTUFF3_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]knotifyconfig[\s/)]', 'replace "knotifyconfig" with "${KDE4_KNOTIFYCONFIG_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]threadweaver[\s/)]', 'replace "threadweaver" with "${KDE4_THREADWEAVER_LIBRARIES}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]krosscore[\s/)]', 'replace "krosscore" with "${KDE4_KROSSCORE_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]krossui[\s/)]', 'replace "krossui" with "${KDE4_KROSSUI_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]phonon[\s/)]', 'replace "phonon" with "${PHONON_LIBRARY}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kaudiodevicelist[\s/)]', 'replace "kaudiodevicelist" with "${KDE4_KAUDIODEVICELIST_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]solidifaces[\s/)]', 'replace "solidifaces" with "${KDE4_SOLIDIFACES_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]solid[\s/)]', 'replace "solid" with "${KDE4_SOLID_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]ktexteditor[\s/)]', 'replace "ktexteditor" with "${KDE4_KTEXTEDITOR_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kfile[\s/)]', 'replace "kfile" with "${KDE4_KFILE_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]knepomuk[\s/)]', 'replace "knepomuk" with "${KDE4_KNEPOMUK_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kmetadata[\s/)]', 'replace "kmetadata" with "${KDE4_KMETADATA_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kjs[\s/)]', 'replace "kjs" with "${KDE4_KJS_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kjsapi[\s/)]', 'replace "kjsapi" with "${KDE4_KJSAPI_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kformula[\s/)]', 'replace "kformula" with "${KDE4_KFORMULA_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]plasma[\s/)]', 'replace "plasma" with "${KDE4_PLASMA_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kunitconversion[\s/)]', 'replace "kunitconversion" with "${KDE4_KUNITCONVERSION_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kdewebkit[\s/)]', 'replace "kdewebkit" with "${KDE4_KDEWEBKIT_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kprintutils[\s/)]', 'replace "kprintutils" with "${KDE4_KPRINTUTILS_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kcmutils[\s/)]', 'replace "kcmutils" with "${KDE4_KCMUTILS_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kemoticons[\s/)]', 'replace "kemoticons" with "${KDE4_KEMOTICONS_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kidletime[\s/)]', 'replace "kidletime" with "${KDE4_KIDLETIME_LIBS}"'); } # kdepimlibs variables if (! $in_kdelibs && ! $in_kdepimlibs) { $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]akonadi-kde[\s/)]', 'replace "akonadi-kde" with "${KDEPIMLIBS_AKONADI_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]akonadi-kmime[\s/)]', 'replace "akonadi-kmime" with "${KDEPIMLIBS_AKONADI_KMIME_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]gpgmepp[\s/)]', 'replace "gpgmepp" with "${KDEPIMLIBS_GPGMEPP_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kabc[\s/)]', 'replace "kabc" with "${KDEPIMLIBS_KABC_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kblog[\s/)]', 'replace "kblog" with "${KDEPIMLIBS_KBLOG_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kcal[\s/)]', 'replace "kcal" with "${KDEPIMLIBS_KCAL_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kholidays[\s/)]', 'replace "kholidays" with "${KDEPIMLIBS_KHOLIDAYS_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kimap[\s/)]', 'replace "kimap" with "${KDEPIMLIBS_KIMAP_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kldap[\s/)]', 'replace "kldap" with "${KDEPIMLIBS_KLDAP_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kmime[\s/)]', 'replace "kmime" with "${KDEPIMLIBS_KMIME_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kontactinterface[\s/)]', 'replace "kontactinterface" with "${KDEPIMLIBS_KONTACTINTERFACE_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kpimidentities[\s/)]', 'replace "kpimidentities" with "${KDEPIMLIBS_KPIMIDENTITIES_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kpimtextedit[\s/)]', 'replace "kpimtextedit" with "${KDEPIMLIBS_KPIMTEXTEDIT_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kpimutils[\s/)]', 'replace "kpimutils" with "${KDEPIMLIBS_KPIMUTILS_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kresources[\s/)]', 'replace "kresources" with "${KDEPIMLIBS_KRESOURCES_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]ktnef[\s/)]', 'replace "ktnef" with "${KDEPIMLIBS_KTNEF_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]kxmlrpcclient[\s/)]', 'replace "kxmlrpcclient" with "${KDEPIMLIBS_KXMLRPCCLIENT_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]mailtransport[\s/)]', 'replace "mailtransport" with "${KDEPIMLIBS_MAILTRANSPORT_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]microblog[\s/)]', 'replace "microblog" with "${KDEPIMLIBS_MICROBLOG_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]qgpgme[\s/)]', 'replace "qgpgme" with "${KDEPIMLIBS_QGPGME_LIBS}"'); $issues += &checkLine($line,$linecnt, 'target_link_libraries.*[[:space:]]syndication[\s/)]', 'replace "syndication" with "${KDEPIMLIBS_SYNDICATION_LIBS}"'); } if ($line !~ m+(Qt4|IOKit|KdeSubversion|KDE4|KDE4Internal|KDEWIN32|KdepimLibs|kdevplatform|Carbon|Gpgme)+ && $in !~ m+/(examples|qtonly)/+) { $issues += &checkLine($line,$linecnt, '^\s*[Ff][Ii][Nn][Dd]_[Pp][Aa][Cc][Kk][Aa][Gg][Ee]\s*\(\s*[A-Za-z0-9_]*\sREQUIRED\s*\)', 'Do not use the REQUIRED keyword with find_package()'); } my($subdir); if ($line =~ m+macro_optional_add_subdirectory\s*\(\s*(\S*)\s*\)+) { $subdir = $1; if (!&canBeOptional($subdir) || ($top_of_module && ($in_kdelibs || $in_kdepimlibs))) { if (!&mustBeOptional($subdir)) { $issues++; &printIssue($line,$linecnt,"Replace macro_optional_add_subdirectory($subdir) with add_subdirectory($subdir)"); } } } if ($line =~ m+^\s*add_subdirectory\s*\(\s*(\S*)\s*\)+) { $subdir = $1; if (&mustBeOptional($subdir)) { $issues++; &printIssue($line,$linecnt,"Replace add_subdirectory($subdir) with macro_optional_add_subdirectory($subdir)"); } } $prevline = $line; } #look for "missing" stuff my($in_exec)=0; my($has_project)=0; my($has_display_log)=0; foreach $line (@lines) { chomp($line); $line =~ s/#.*$//; #remove comments next if ($line =~ m/^[[:space:]]$/); #skip blank lines $in_exec = 1 if ($line =~ m/add_(|kdeinit_)executable[[:space:]]*\(/i); if ($line =~ m/[Pp][Rr][Oo][Jj][Ee][Cc][Tt]/) { $has_project=1; } if ($line =~ m/macro_display_feature_log/i) { $has_display_log=1; } } if (! $has_project && $top_of_project && $in_exec) { $issues++; &printIssue($line,$linecnt,"Missing a PROJECT() command"); } if ($top_of_module && $has_display_log == 0) { $issues++; &printIssue($line,$linecnt,"Missing macro_display_feature_log() command"); } #if (!$top_of_module && $has_display_log == 1 && $in !~ m+/qtonly/+) { # $issues++; # &printIssue($line,$linecnt,"Do not put macro_display_feature_log() in a subdir CMakeLists.txt"); #} if ($nop != $ncp) { $issues++; &printIssue($line,$linecnt,"Mismatched parens"); } if ($nob != $ncb) { $issues++; &printIssue($line,$linecnt,"Mismatched braces"); } #missing macro_log_feature() foreach $pack ( keys %optpacks ) { if ($optpacks{$pack}{'log'} == 0) { $issues++; &printIssue("","","Missing macro_log_feature($pack)"); } } close(IN); return $issues; } sub checkLine { my($line,$cnt,$regex,$explain) = @_; if ($line =~ m/$regex/i) { &printIssue($line,$cnt,$explain); return 1; } return 0; } sub printIssue { my($line,$cnt,$explain) = @_; if ($line) { print "\tline#$cnt: $explain\n"; print "\t=>$line\n" if ($verbose); } else { print "\t$explain\n"; } } sub canBeOptional { my($guy) = @_; my($ret) = 1; $ret = 0 if ($guy =~ m/^lib/ || $guy =~ m/lib$/ || $guy =~ m/^cmake$/ ); return $ret; } sub mustBeOptional { my($guy) = @_; my($ret) = 0; $ret = 1 if ($guy =~ m/^doc$/); return $ret; } #============================================================================== # Help function: print help message and exit. sub Help { &Version(); print "Check KDE CMakeLists.txt files for common errors.\n\n"; print "Usage: $Prog [OPTIONS] FILES\n"; print " --help display help message and exit\n"; print " --version display version information and exit\n"; print "\n"; exit 0 if $help; } # Version function: print the version number and exit. sub Version { print "$Prog, version $Version\n"; exit 0 if $version; } __END__ regina-4.96/admin/distcheck000755 000765 000024 00000010422 12400005660 015557 0ustar00babstaff000000 000000 #!/bin/bash # # Regina - A Normal Surface Theory Calculator # Source Distribution Verification # # Copyright (c) 2003-2014, Ben Burton # For further details contact Ben Burton (bab@debian.org). # # Usage: distcheck # # Verifies that a tarball formed using "make dist" contains all the # files it should. This script outputs a list of files contained in # the git source tree that are missing from the tarball. # # Files that are not necessary for inclusion in the tarball (such as # auto-generated files or the Regina website) are not included in this # output. # # This script must be run from either the top-level source directory within # the git source tree, or from the admin/ directory beneath it. # # Requires: diff, find, grep, mktemp, sed, sort, tar # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version. # # As an exception, when this program is distributed through (i) the # App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or # (iii) Google Play by Google Inc., then that store may impose any # digital rights management, device limits and/or redistribution # restrictions that are required by its terms of service. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public # License along with this program; if not, write to the Free # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, # MA 02110-1301, USA. # set -e # Command-line sanity check. if [ "$#" != 1 ]; then echo "Usage: distcheck " exit 1 fi # Locate the top of the git source tree. if [ -d admin -a -f HIGHLIGHTS.txt ]; then gittree=. elif [ -d ../admin -a -f ../HIGHLIGHTS.txt ]; then gittree=.. else echo "This script must be run from either the top-level source directory" echo "within the git source tree, or from the admin/ directory beneath it." exit 1 fi # Find any builddirs that should be ignored. builddirs=`find "$gittree" -mindepth 2 -name CMakeCache.txt | \ sed -e 's%^[^/]*/%%' -e 's%/CMakeCache.txt$%%'` display_builddirs= grep_builddirs= for i in $builddirs; do if [ -z "$grep_builddirs" ]; then display_builddirs="$i" grep_builddirs="$i" else display_builddirs="$display_builddirs $i" grep_builddirs="$grep_builddirs\\|$i" fi done if [ -z "$grep_builddirs" ]; then grep_builddirs="^$" else echo "Ignoring build directories: $display_builddirs" grep_builddirs="^\\($grep_builddirs\\)\\(/\\|$\\)" fi # Prepare the two temporary file lists. gitlist="`mktemp -t gitlist.XXXXXXXXXX`" || gitlist= distlist="`mktemp -t distlist.XXXXXXXXXX`" || distlist= if [ -z "$gitlist" -o -z "$distlist" ]; then echo "Error creating temporary files." exit 1 fi # Make a list of files in the distribution tarball. echo "Analysing distribution tarball..." if [ ! -f "$1" ]; then echo "The distribution tarball $1 does not exist or is not a regular file." exit 1 fi case "$1" in *.tar.gz ) taropts=-ztf ;; *.tgz ) taropts=-ztf ;; *.tar.bz2 ) taropts=-jtf ;; *.tar ) taropts=-tf ;; * ) echo "The distribution tarball $1 is not of the correct type." exit 1 ;; esac if ! tar "$taropts" "$1" | sed -e 's%^[^/]*/%%' -e 's%/$%%' | \ sort > "$distlist"; then echo "The contents of the distribution tarball $1 could not be listed." exit 1 fi # Make a list of files in the git source tree. echo "Analysing git source tree..." if ! find "$gittree" -type f | sed -e 's%^[^/]*/%%' | \ grep -v "$grep_builddirs" | \ grep -v '^\.' | \ grep -v '/\.' | \ grep -v '^engine/snappea/kernel/unused\(/\|$\)' | \ grep -v '^regina-[0-9.]\+\.tar\.gz$' | \ grep -v '^sfdist\(/\|$\)' | \ grep -v '^utils/local\(/\|$\)' | \ grep -v '^utils/snappea\(/\|$\)' | \ sort > "$gitlist" ; then echo "The contents of the git source tree could not be listed." exit 1 fi # Output the differences. diff -B "$distlist" "$gitlist" | grep -v '^[0-9]' # Clean up. rm "$gitlist" "$distlist" regina-4.96/admin/index2gloss000755 000765 000024 00000006103 12400000410 016044 0ustar00babstaff000000 000000 #!/usr/bin/perl -w # # Regina - A Normal Surface Theory Calculator # KDE DocBook Reformatting Utility # # Copyright (c) 2007-2014, Ben Burton # For further details contact Ben Burton (bab@debian.org). # # Usage: index2gloss < input.docbook > output.docbook # # Reads a docbook file containing an index using ... tags, # and reformats it using ... tags. # # This is necessary because recent KDE versions render the usual index # tags in a way that is virtually unreadable (e.g., lines joined together, # secondary entries appearing as primary entries, etc.). Using glossary # tags may be incorrect from docbook's point of view, but it at least # makes the document usable. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version. # # As an exception, when this program is distributed through (i) the # App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or # (iii) Google Play by Google Inc., then that store may impose any # digital rights management, device limits and/or redistribution # restrictions that are required by its terms of service. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public # License along with this program; if not, write to the Free # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, # MA 02110-1301, USA. # use strict; my $data; sub switchTag { my $tagOld = shift; my $tagNew = shift; my $found = 0; if ($data =~ /^<$tagOld[ >]/) { $data =~ s/^<$tagOld/<$tagNew/; $found = 1; } if ($data =~ /<\/$tagOld>$/) { $data =~ s/<\/$tagOld>$/<\/$tagNew>/; $found = 1; } return $found; } sub transform { switchTag('index', 'glossary'); switchTag('indexentry', 'glossentry'); switchTag('primaryie', 'glossterm'); if (switchTag('secondaryie', 'glossdef')) { $data =~ s/^()/$1/; $data =~ s/(<\/glossdef>)$/<\/para>$1/; } if (switchTag('seeie', 'glosssee')) { $data =~ s/^()\(see /$1/; $data =~ s/\)(<\/glosssee>)$/$1/; } } my $sHead; my $sTail; my $emptyEntry = 0; while (<>) { chomp; if (/^(\s*)(\S(.*\S)?)(\s*)$/) { $sHead = $1; $data = $2; $sTail = $4; transform(); $data =~ /^]/ and $emptyEntry = 1; $data =~ /^]/ and $emptyEntry = 0; $data =~ /^]/ and $emptyEntry = 0; if ($data =~ /<\/glossentry>$/ and $emptyEntry) { print "$sHead  \n"; } print $sHead . $data . $sTail . "\n"; } else { # Blank line or whitespace only. print "$_\n"; } } exit 0; regina-4.96/admin/Makefile000644 000765 000024 00000001130 12311266525 015336 0ustar00babstaff000000 000000 ## ## Regina - A Normal Surface Theory Calculator ## Auxiliary Makefile ## ## These tools should be used only by the core software maintainers. ## In fact, there are good arguments that they should not be used at all. ## Keeping them around though just in case. ## srcdir = .. all : tabs : cd $(srcdir); ./replacetabs `find .. -name "*.cpp" -o -name "*.h" -o -name "*.tcc"` cd $(srcdir); ./replacetabs `find .. -name "*.txt"` cd $(srcdir); ./replacetabs ../qtui/doc/regina/*.docbook cd $(srcdir); ./replacetabs ../qtui/doc/regina-xml/*.docbook cd $(srcdir); ./replacetabs ../pylib/*.py regina-4.96/admin/mksums000755 000765 000024 00000005763 12400000411 015136 0ustar00babstaff000000 000000 #!/bin/bash # # Regina - A Normal Surface Theory Calculator # Signed Md5sum Generation Utility # # Copyright (c) 2002-2014, Ben Burton # For further details contact Ben Burton (bab@debian.org). # # Usage: mksums [ ... ] # # Creates a GnuPG-signed set of md5sums for the given set of files. # # This script should only need to be used by the software author (and is # specifically tailored for said author's machine and personal details). # # Requires: gpg, md5sum, mktemp, sed # Example: mksums "Regina distribution files" *.tgz # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version. # # As an exception, when this program is distributed through (i) the # App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or # (iii) Google Play by Google Inc., then that store may impose any # digital rights management, device limits and/or redistribution # restrictions that are required by its terms of service. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public # License along with this program; if not, write to the Free # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, # MA 02110-1301, USA. # set -e # Details for person doing the GnuPG signing. signerid="Ben Burton " # Command-line sanity check. if [ -z "$1" -o -z "$2" ]; then echo "Usage: mksums [ ... ]" exit 1 fi # Extract the description string. desc="$1" shift # Check that the given files exist as regular files. for i; do if [ ! -e "$i" ]; then echo "File $i does not exist." exit 1 elif [ ! -f "$i" ]; then echo "File $i is not a regular file." exit 1 fi done # Create a temporary file to contain the entire md5sum message. plaintext="`mktemp -t md5sums.XXXXXXXXXX`" || plaintext= if [ -z "$plaintext" ]; then echo "Error creating temporary file." exit 1 fi # Build the md5sum message. echo > "$plaintext" echo "Below are md5sums for the $desc available from this site." >> "$plaintext" echo >> "$plaintext" md5sum "$@" | sed -e "s/^/ /" >> "$plaintext" cat >> "$plaintext" < and comparing the output with the md5sums listed above. These md5sums have been signed with my private GnuPG key; the matching public key is available from any of the pgp.net public keyservers (e.g., wwwkeys.au.pgp.net). END echo >> "$plaintext" echo " -- $signerid, `822-date`" >> "$plaintext" echo >> "$plaintext" # Sign the md5sum message. cat "$plaintext" | gpg --clearsign # Clean up. rm "$plaintext" regina-4.96/admin/README.txt000644 000765 000024 00000000572 12234011536 015377 0ustar00babstaff000000 000000 Regina Administrative Utilities ------------------------------- This directory contains utilities for housekeeping and making new releases. In general only the software author(s) should need to worry about the contents of this directory. For general information on building or running Regina, see README.txt in the top-level source directory (the directory above this one). regina-4.96/admin/RELEASE.txt000644 000765 000024 00000005431 12400002052 015505 0ustar00babstaff000000 000000 Below are locations of strings that may need changing for a new release. All locations are relative to the primary source directory. Program version: CHANGES.txt, HIGHLIGHTS.txt (version, date) CMakeLists.txt (PACKAGE_VERSION) qtui/doc/regina/about.docbook (plain citation, bibTeX citation) qtui/doc/regina/index.docbook (®version;, ®date;, date, releaseinfo, copyrightyears) qtui/doc/regina/manonly.docbook (®version;) qtui/doc/regina-xml/index.docbook (same as for .../regina/index.docbook) qtui/src/reginaabout.cpp (regReleased) preconfig/*/regina-config.h (PACKAGE_* macros) www/index.html (last updated, current version, contents, news, filenames, what's new) www/source.html (unpacking instructions: filename, directory) Plus copyright years in: engine/doxygen/doc-footer.html python/modulemain.cpp ... and the copyright statement in the license (see below) Full license details: LICENSE.txt engine/docs.h qtui/doc/regina/credits.docbook qtui/src/reginaabout.cpp (ReginaAbout constructor) www/index.html SnapPy version: engine/snappea/nsnappeatriangulation.h (class docs) qtui/doc/regina/trouble.docbook (SnapPy multiple interpreters) engine/snappea/kernel/README.txt engine/snappea/snappy/README.txt SnapPea / SnapPy copyright (in addition to full license locations above): engine/snappea/kernel/README.txt engine/snappea/snappy/README.txt engine/snappea/nsnappeatriangulation.h Acknowledgements (in addition to primary authors listed in the license): qtui/doc/regina/credits.docbook qtui/src/reginaabout.cpp (ReginaAbout constructor) Don't forget: changes & highlights what's this & tooltips documentation in handbook, feature set, index & file format any new tips of the day? journal references (www, KDE docs, example files, headers; search for arXiv and "to appear") check that all headers are installed correctly check for doxygen warnings check for docbook warnings/errors python bindings for new routines rebuild manpages website, including updated news, what's new and deprecation guide debian-based packages (debian/ubuntu) rpm-based packages (fedora/mandriva/suse) windows installer macos DMG (purge libiconv-dev, libxml2 from fink first) update tips for building on different platforms update debian/ubuntu/fink READMEs as required (both text and html) update census download file sizes if there have been changes tag the git repository upload new data files, both from examples/ and the large data repository update docs/ and engine-docs/ on the website update the citation years if necessary in private BibTeX databases mail regina-announce regina-4.96/admin/replacetabs000755 000765 000024 00000004017 12400000416 016100 0ustar00babstaff000000 000000 #!/bin/sh # # Regina - A Normal Surface Theory Calculator # Tab Conversion Utility # # Copyright (c) 1999-2014, Ben Burton # For further details contact Ben Burton (bab@debian.org). # # Usage: replacetabs [ ... ] # # Replaces each tab with four spaces in the given files. # # Requires: awk, diff # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version. # # As an exception, when this program is distributed through (i) the # App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or # (iii) Google Play by Google Inc., then that store may impose any # digital rights management, device limits and/or redistribution # restrictions that are required by its terms of service. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public # License along with this program; if not, write to the Free # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, # MA 02110-1301, USA. # set -e # Command-line sanity check. if [ -z "$1" ]; then echo "Usage: replacetabs [ ... ]" exit 1 fi for srcfile do tmpfile=$srcfile.tabs.tmp if (awk '{gsub("\t", " "); print }' $srcfile > $tmpfile); then if ! diff $srcfile $tmpfile > /dev/null; then if (test -s $tmpfile); then mv $tmpfile $srcfile echo "$srcfile: Tabs replaced" else rm $tmpfile echo "$srcfile: *** FAILURE ***" fi else rm $tmpfile # echo "$srcfile: Unchanged" fi else rm $tmpfile echo "$srcfile: *** FAILURE ***" fi done regina-4.96/admin/updateyear000755 000765 000024 00000006666 12400000417 015773 0ustar00babstaff000000 000000 #!/usr/bin/perl -w # # Regina - A Normal Surface Theory Calculator # Source Stub Year Update Utility # # Copyright (c) 1999-2014, Ben Burton # For further details contact Ben Burton (bab@debian.org). # # Usage: updateyear [ ... ] # # Replaces the old year with the new year in the copyright header at # the beginning of each given file. You will be asked to approve or # reject each change. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version. # # As an exception, when this program is distributed through (i) the # App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or # (iii) Google Play by Google Inc., then that store may impose any # digital rights management, device limits and/or redistribution # restrictions that are required by its terms of service. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public # License along with this program; if not, write to the Free # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, # MA 02110-1301, USA. # use strict; # --- Command-line sanity check. --- my $nArgs = @ARGV; if ($nArgs < 3) { print STDERR "Usage: updateyear [ ... ]\n"; exit(1); } my $oldYear; my $newYear; my @argFiles; ($oldYear, $newYear, @argFiles) = @ARGV; # --- Run through each file to process. --- foreach my $file (@argFiles) { # Read the file contents. if (! open(DATA, $file)) { print STDERR "ERROR: Could not open $file for reading.\n"; next; } my @lines = ; close(DATA); # Hunt for a sentry. my @newLines = (); my $edit; my $changed = 0; foreach my $line (@lines) { $edit = undef; if ($line =~ /Copyright \(c\) $oldYear,/) { $edit = $line; $edit =~ s/(Copyright \(c\) )$oldYear,/$1$newYear,/g; } elsif ($line =~ /Copyright \(c\) \d+-$oldYear,/) { $edit = $line; $edit =~ s/(Copyright \(c\) \d+-)$oldYear,/$1$newYear,/g; } if (not defined $edit) { push(@newLines, $line); next; } print "CHANGE:\n-$line+$edit"; print "Accept? [Y/n] "; my $response = ; $response =~ s/\s//g; $response =~ tr/A-Z/a-z/; $response eq '' and $response = 'y'; while (not ($response eq 'y' or $response eq 'n')) { print "Accept? [Y/n] "; $response = ; $response =~ s/\s//g; $response =~ tr/A-Z/a-z/; $response eq '' and $response = 'y'; } if ($response eq 'y') { push(@newLines, $edit); $changed = 1; } else { push(@newLines, $line); } } if ($changed) { if (! open(DATA, '>'.$file)) { print STDERR "ERROR: Could not open $file for writing.\n"; next; } print DATA $_ foreach (@newLines); close(DATA); print "REPLACED: $file.\n\n"; } else { # print "Unchanged: $file.\n"; } } regina-4.96/CHANGES.txt000644 000765 000024 00000562257 12377774125 014461 0ustar00babstaff000000 000000 Regina - A Normal Surface Theory Calculator This file gives a detailed list of changes between releases, including all changes to the C++/Python API. For just the key highlights, see the (far more readable) file HIGHLIGHTS.txt. Version 4.96 [ 29 August, 2014 ] ENGINE: Class BanConstraintBase (and subclasses): - Extended the tree traversal / linear programming machinery to work with angle structures. This is used for enumerating all taut angle structures, or finding a single strict angle structure. Class Dim2BoundaryComponent: - New convenience routine getComponent(). - New routine index(). Class Dim2Census: - Routines formCensus() and formPartialCensus() and the typedef AcceptTriangulation are now deprecated. To build a census you should call Dim2EdgePairing::findAllPairings() and Dim2GluingPermSearcher::findAllPerms() directly. Class Dim2Component: - New routine getNumberOfBoundaryEdges(). - New routine index(). Class Dim2Edge: - New routine index(). Class Dim2EdgeEmbedding: - New convenience operators == and !=. Class Dim2Triangle: - New routine index(). Class Dim2Triangulation: - New routine isIdenticalTo(). - New local modification oneThreeMove(). - New routine findAllIsomorphisms(). - New routine isEmpty(). - Several isomorphism-related routines have been moved into the dimension-agnostic NGenericTriangulation template, and isomorphism signature routines now inherit directly from NGenericTriangulation instead of using wrappers. See the NGenericTriangulation notes below for details. - New routines getNumberOfBoundaryEdges() and hasBoundaryEdges(). The latter is redundant, but is provided for compatibility with NTriangulation. Class Dim2Vertex: - New routine index(). Class Dim2VertexEmbedding: - New convenience operators == and !=. Class LPConstraintBase (and subclasses), LPData, LPInitialTableaux, LPMatrix: - Extended the tree traversal / linear programming machinery to work with angle structures. This is used for enumerating all taut angle structures, or finding a single strict angle structure. Class NAbelianGroup: - New convenience operator !=. Class NAngleStructure: - New convenience routine rawVector(). - Routine getTriangulation() now returns a const NTriangulation* (previously this was non-const). Likewise, many routines in this and related classes have NTriangulation* arguments changed from non-const to const. Class NAngleStructureList: - Enumeration of taut angle strutures now uses Regina's tree traversal / linear programming machinery, which is *much* faster than the old double description method. - The new routine enumerateTautDD() allows users to access the older (and much slower) double description method if required. Class NAngleStructureVector: - New routine makeAngleEquations() to build the angle structure equations independently of an angle structure list. Class NBoundaryComponent: - New convenience routine getComponent(). - New routine index(). - Renamed getEulerCharacteristic() to getEulerChar(), which is easier on the fingers. The old name has been kept as a deprecated alias for backward compatibility. Class NCensus: - New routine lookup() (in two variants) to quickly search for a given triangulation in Regina's various census databases. The databases themselves are now installed alongside the mathematical engine, and are much larger and richer than before. - Routine mightBeMinimal() is deprecated; you should call NTriangulation::simplifyToLocalMinimum(false) instead. - Routines formCensus() and formPartialCensus() and the typedef AcceptTriangulation are now deprecated. To build a census you should call NFacePairing::findAllPairings() and NGluingPermSearcher::findAllPerms() directly. - The PURGE_... constants have been moved to the NGluingPermSearcher class. The old flags in NCensus are deprecated, but have been kept for backward compatibility. Class NCensusDB, NCensusHit, NCensusHits: - New classes to support the new NCensus::lookup() routines. Class NComponent: - New routine getNumberOfBoundaryTriangles(). - New routine index(). Class NCusp: - New class to support NSnapPeaTriangulation. Class NEdge: - New routine index(). Class NExampleTriangulation: - New example trefoilKnotComplement(). - New example sphere600() (sourced from the 600-cell in the Benedetti-Lutz library of triangulations). Class NGenericTriangulation: - Moved isIdenticalTo(), isIsomorphicTo(), isContainedIn(), findAllSubcomplexesIn() and makeCanonical() from Dim2Triangulation and NTriangulation into this class. - New routine findAllIsomorphisms(). - New routine isEmpty(). - Made isoSig(), fromIsoSig() and isoSigComponentSize() public. Class NGluingPermSearcher: - New PurgeFlags enumeration, which is the new home for the PURGE_... constants that used to live in the NCensus class. This enumeration also contains new flags PURGE_NON_MINIMAL_HYP (for use in building a census of cusped finite volume hyperbolic 3-manifolds), and PURGE_NONE. - Removed protected routine mayPurge(), since this behaviour is already provided by specialised subclasses of NGluingPermSearcher. Class NHyperbolicMinSearcher: - New enumeration class for building a census of minimal ideal triangulations of cusped finite-volume hyperbolic 3-manifolds. Class NManifold: - New routine isHyperbolic(). Class NNormalSurface: - Renamed boundarySlopes() to boundaryIntersections(), to make it clear that it returns algebraic intersection numbers and not the usual (m, l) pairs. The old name has *not* been deprecated, but removed completely. - Furthermore, boundaryIntersections() now requires the underlying triangulation to be of type NSnapPeaTriangulation, and it takes the meridian and longitude directly from the SnapPea kernel. It also now orders its rows by SnapPea cusp indices (not Regina's vertex indices); this is identical to past behaviour, but now that SnapPea triangulations can be modified through the SnapPea kernel, it is possible for the numbering schemes to differ and so this distinction now matters. - Renamed getEulerCharacteristic() to getEulerChar(), which is easier on the fingers. The old name has been kept as a deprecated alias for backward compatibility. - Renamed the protected routine calculateEulerCharacteristic() to calculateEulerChar(). - Routine getTriangulation() now returns a const NTriangulation* (previously this was non-const). Likewise, many routines in this and related classes have NTriangulation* arguments changed from non-const to const. Class NNormalSurfaceList: - New routines saveCSVStandard() and saveCSVEdgeWeight(). These are now the preferred ways of exporting a normal surface list to CSV format. - Many routines in this and related classes have NTriangulation* arguments changed from non-const to const. This also applies to related global routines, such as makeMatchingEquations(). Enum NormalCoords: - New coordinate system NS_ANGLE for use with angle structures. Class NPacket: - New routine save(), which is now the preferred way of saving Regina data files. Class NPDF: - New constructor that reads a PDF document from a given file. - New routine isNull() to test if a PDF document is stored. - New routine savePDF(), which is now the preferred way of exporting a PDF packet to a PDF file. Class NPerm3, NPerm4, NPerm5: - New dimension-agnostic alias invSn. - Changed the type of NPerm3::invS3 from int to unsigned, for consistenty with NPerm4 and NPerm5. Class NScript: - Scripts are now stored as complete strings, not sequences of individual lines. This affects the member functions (see below) and also the XML file format. Whilst Regina has removed much of the functionality for working line-by-line, it can still read older files that were stored that way. - A script now fires a change event if one of its variables changes its packet label. - New routines getText(), setText() and append(). - New routine getVariableIndex(), setVariableName(), setVariableValue() and removeVariable(unsigned long). - Removed routines getLine(), getNumberOfLines(), addFirst(), addLast(), insertAtPosition(), replaceAtPosition(), removeLineAt(), and removeAllLines(). These are not deprecated, but removed entirely. Class NSnapPeaTriangulation: - Updated the SnapPea kernel to the one shipped with SnapPy 2.2 (standard precision). - NSnapPeaTriangulation is now a fully-fledged packet type, and derives from NTriangulation. The inherited NTriangulation must not be modified directly; instead this is automatically kept in sync with the SnapPea data. - Closed triangulations are now supported always by default (i.e., you do not need to explicitly pass allowClosed=true). The second argument (allowClosed) for the constructor NSnapPeaTriangulation(const NTriangulation&, bool) is deprecated, and is now ignored. - Many new routines: countCompleteCusps(), countCusps(), countFilledCusps(), cusp(), fill(), filledTriangulation(), fundamentalGroupFilled(), gluingEquations(), gluingEquationsRect(), homologyFilled(), minImaginaryShape(), name(), protoCanonize() and protoCanonise(), shape(), unfill(), volumeZero(), plus others (listed individually below). - Two new constructors: a default constructor that builds a null triangulation, and a string constructor that takes either the name or the contents of a native SnapPea data file. - The Regina-to-SnapPea constructor now doubles as another copy constructor: which behaviour you get now depends on whether you pass an object of Regina's own NTriangulation type or of the subclass NSnapPeaTriangulation. - If one of Regina's own NTriangulation objects is passed to the constructor, then the constructor now installs the (shortest, second-shortest) curves on each cusp as its (meridian, longitude) basis. This reverts a change in behaviour from the previous release caused by the recent sync with the SnapPy 2.0.3 kernel. - New output routines snapPea() and saveSnapPea(). These override the "lossy" conversion routines NTriangulation::snapPea() and NTriangulation::saveSnapPea() so that they output all SnapPea-specific data. - Renamed saveAsSnapPea() to saveSnapPea() (see above). The new routine now returns a boolean, and requires a non-empty filename. The old name is deprecated but kept for backward compatibility. - Routine dump() is deprecated. Instead, simply call snapPea() and write the resulting string to standard output. - Added synonym canonise() for canonize(). - Routine solutionType() now returns the filled solution type (not the complete solution type). - Routine slopeEquations() now orders rows by SnapPea cusp indices (not Regina's vertex indices). This is identical to past behaviour, but now that SnapPea triangulations can be modified through the SnapPea kernel, it is possible for the numbering schemes to differ and so this distinction now matters. - Routines toRegina() and verifyTriangulation() are deprecated, since they are obsolete now that NSnapPeaTriangulation inherits from NTriangulation. - The entire SnapPea kernel now lives within the namespace regina::snappea, which should ensure safety even if a conflicting SnapPy kernel is simultaneously loaded via Python. The SnapPea kernel is also linked as C++ now (no 'extern "C"'). - Fatal errors in the SnapPea kernel are now handled by throwing exceptions, instead of quitting abruptly. Class NTautEnumeration: - New class for enumerating taut angle structures that uses Regina's tree traversal / linear programming machinery. This is *much* faster than the old double description method. Class NTetrahedron: - New routine index(). Class NTreeTraversal: - Extended the tree traversal / linear programming machinery to work with angle structures. This is used for enumerating all taut angle structures, or finding a single strict angle structure. - Changed all NTriangulation types in this and related classes from non-const to const. Class NTriangle: - New routine index(). Class NTriangleEmbedding: - New convenience operators == and !=. Class NTriangulation: - New routines hasStrictAngleStructure(), findStrictAngleStructure() and knowsStrictAngleStructure(), which use fast linear programming machinery. - Routine connectedSumDecomposition() now works for non-orientable triangulations also (arXiv:1212.1441). There is a caveat if there are embedded two-sided projective planes (see the documentation for details), and so the return type is now a signed long to allow for error conditions to be returned. - New routine connectedSumWith() for building connected sums. - New routine isIdenticalTo(). - New routine isEmpty(). - New local modification oneFourMove(). - New routines findAllIsomorphisms() and makeCanonical(). - Several isomorphism-related routines have been moved into the dimension-agnostic NGenericTriangulation template, and isomorphism signature routines now inherit directly from NGenericTriangulation instead of using wrappers. See the NGenericTriangulation notes above for details. - New routine getNumberOfBoundaryTriangles(). - New routine puncture(). - New routines snapPea(std::ostream&) and saveSnapPea(). These (and the existing snapPea()) are now the preferred ways of exporting an NTriangulation to SnapPea's native file format. - New routines recogniser(), recogniser(std::ostream&), saveRecogniser(), plus US-spelled variants recognizer(), etc. These are now the preferred ways of exporting data for Matveev's 3-manifold recogniser. - Routines snapPea() and saveSnapPea() now do nothing if the triangulation is empty. Class NVertex: - Renamed getLinkEulerCharacteristic() to getLinkEulerChar(), which is easier on the fingers. The old name has been kept as a deprecated alias for backward compatibility. - New routine index(). Class NVertexEmbedding: - New convenience operators == and !=. Class NXMLSnapPeaReader: - New I/O class for the new SnapPea triangulation packet type. Class SnapPeaException, SnapPeaFatalError, SnapPeaMemoryFull: - New exceptions to be thrown by the SnapPea kernel. Enum SurfaceExportFields: - Moved from foreign/csvsurfacelist.h to surfaces/nnormalsurfacelist.h. Routine open(): - New routine which is now the preferred way to read a native Regina data file. Routine readFileMagic(), readXMLFile(): - Renamed to regina::open(), and now declared in npacket.h. The old names are deprecated but kept for backward compatibility. Routine readPDF(): - Deprecated, in favour of the new filename-based NPDF constructor. - Explicitly return 0 if the given file exists but is empty. Routine readSnapPea(): - Both variants of this routine are now deprecated, in favour of the new NSnapPeaTriangulation constructor which preserves additional SnapPea-specific data. The old routines have been kept for backward compatibility, and (unlike the new routines) retain their old "lossy" behaviour (i.e., returning an NTriangulation that drops any SnapPea-specific data, such as peripheral curves). Routine writeCSVStandard(), writeCSVEdgeWeight(): - Renamed to NNormalSurfaceList::saveCSVStandard() and NNormalSurfaceList::saveCSVEdgeWeight(). The old names are deprecated but have been kept for backward compatibility. Routine writePDF(): - Renamed to NPDF::savePDF(). The old name is deprecated but has been kept for backward compatibility. The new NPDF::savePDF() has a slight change in behaviour: if the PDF packet contains no data then the old routine created an empty file and returned true, whereas the new routine does nothing and returns false. Routine writeRecogniser(), writeRecognizer(): - Renamed to NTriangulation::saveRecogniser() / saveRecognizer(). The old names are deprecated but kept for backward compatibility. The new versions have a change in behaviour, in that they now require a non-empty filename (the old behaviour can be recreated by calling NTriangulation::recogniser() instead). Routine writeSnapPea(): - The two variants of this routine have been renamed as NTriangulation::snapPea(std::ostream&) and NTriangulation::saveSnapPea(const char*). The old names are deprecated but have been kept for backward compatibility. Routine writeXMLFile(): - Renamed to NPacket::save(). The old name is deprecated but has been kept for backward compatibility. Header csvsurfacelist.h: - Deprecated. The declaration of SurfaceExportFields is now in surfaces/nnormalsurfacelist.h instead. The old header now includes surfaces/nnormalsurfacelist.h automatically. Header nxmlcallback.h, nxmlelementreader.h: - Moved from file/ into utilities/. The old headers have been kept for backward compatibility. Header permconv.h: - New conversion routines perm3to5() and perm5to3(). USER INTERFACE: - The commit/refresh buttons are gone: changes are now committed automatically. - Many other changes that implement the engine updates listed above. UTILITIES: censuslookup: - New command-line utility for looking up triangulations in Regina's census databases. tricensus: - New argument -h/--minhyp for enumerating minimal ideal triangulations of cusped finite-volume hyperbolic 3-manifolds. TEST SUITE: - The test suite will no longer be covered by this changelog, since changes to the test suite have not been logged thoroughly for some years now (i.e., releases typically have many more new tests than are being listed here). If you ever want to see what is currently covered by the test suite, you can always run "make test ARGS=-V" and watch the tests scroll by. Version 4.95 [ 12 November, 2013 ] GENERAL: - Updated the bundled copy of Normaliz to version 2.10.1 (27 June 2013). - All 2-faces of a triangulation are now called "triangles" (not just "faces" as before). This is to avoid ambiguity in dimension. - Regina and SnapPy can now talk directly via python: on many systems, 'import snappy' from either a GUI python console or the command-line regina-python tool should work out of the box. - Packets in a data file are no longer required to have unique labels. ENGINE: Class Dim2BoundaryComponent: - Detailed string output (via detail() / toStringLong()) now outputs details of the constituent edges. Class Dim2Component: - New routines getNumberOfSimplices() and getSimplex(), which are dimension-agnostic aliases for getNumberOfTriangles() and getTriangle(). - New template routine getNumberOfFaces(), which is a dimension-agnostic routine for counting faces of any dimension. - Detailed string output (via detail() / toStringLong()) now outputs details of the constituent triangles. Class Dim2Edge: - Detailed string output (via detail() / toStringLong()) now outputs details of where the edge appears in each triangle. Class Dim2Triangulation: - Now inherits from the new helper class NGenericTriangulation<2>. - New routine isoSigComponentSize() for extracting the number of triangles from a signature (inherited from NGenericTriangulation). - New "magic constructor" that attempts to interpret a given string as a 2-manifold triangulation under several possible encodings (currently only isomorphism signatures are supported for 2-manifolds, but this list may grow in the future). - Routine isoSig() now takes an optional argument that returns the isomorphism with the reconstruction from fromIsoSig(). Class Dim2Vertex: - Detailed string output (via detail() / toStringLong()) now outputs details of where the vertex appears in each triangle. Class NBoundaryComponent: - Renamed getFace() and getNumberOfFaces() to getTriangle() and getNumberOfTriangles(). The old names are deprecated but have been kept for backward compatibility. - Detailed string output (via detail() / toStringLong()) now outputs details of the constituent triangles or vertex. Class NComponent: - Renamed getFace() and getNumberOfFaces() to getTriangle() and getNumberOfTriangles(). The old names are deprecated but have been kept for backward compatibility. - Detailed string output (via detail() / toStringLong()) now outputs details of the constituent tetrahedra. Class NEdge: - Detailed string output (via detail() / toStringLong()) now outputs details of where the edge appears in each tetrahedron. Class NEulerSearcher: - A new subclass of NGluingPermSearcher that can enforce an arbitrary fixed Euler characteristic on the vertex links. Struct NewNormalSurfaceVector: - Moved into registryutils.h and redesigned as the more general template struct NewFunction1<>. The old type is equivalent to NewFunction1, and a deprecated typedef has been kept for backward compatibility. Class NExampleTriangulation: - Routines weberSeifert() / seifertWeber(), bingsHouse(), weeks() and poincareHomologySphere() all now build oriented triangulations. Class NFace: - Renamed to NTriangle. The old name is deprecated but has been kept as a typedef for backward compatibility. Class NFaceEmbedding: - Renamed the class to NTriangleEmbedding, and renamed getFace() to getTriangle(). The old names are deprecated but have been kept for backward compatibility. Class NGenericFacetPairing: - Renamed toString() to the simpler-to-type str(). The old name has been kept as a deprecated alias. Class NGenericTriangulation: - New template helper class that allows different triangulation classes to share the same implementations of member functions. Currently this class implements isoSig() and fromIsoSig(). Class NGlobalDirs: - Routine pythonModule() now returns an empty string if the module is installed in the standard python site-packages directory (now the default for an XDG install). Class NGroupPresentation: - Renamed toStringCompact() to compact(). The old name has been kept as a deprecated alias. Class NInteger, NLargeInteger: - Fixed a (thankfully hard-to-trigger) error in the mod operators. The error was triggered on (x % m) or (x %= m) when: (i) x was negative and stored as a native integer; (ii) m could fit into a native integer but was unnecessarily stored as a large GMP integer; (iii) x <= m < |x|. The result was then reported as x (i.e., the mod operation did nothing). - Fixed a (thankfully even-harder-to-trigger) error in the GCD operation. This error was triggered only when computing gcd(LONG_MIN, 0), for either order of the operands. Class NNormalSurface, NNormalSurfaceVector: - Renamed getFaceArcs() to getTriangleArcs(). The old name is deprecated but has been kept for backward compatibility. - Incorporated the new fast branch-and-bound machinery into NNormalSurface::isIncompressible(). - All normal surface vector classes have now gained the enum constant coordType (representing the corresponding NormalCoords constant), and the typedef Info (representing the template specialisation NormalInfo). - The requirements for new vector subclasses have changed, since the old macro-based registry was replaced with the new template-based registry. See the NNormalSurfaceVector class notes for details. - Python users can now create a normal surface by hand, e.g.,: NNormalSurface(tri, NS_STANDARD, [ 1, 2, 0, ... ]). Class NNormalSurfaceList: - Re-enabled enumeration using NS_HILBERT_FULLCONE, which previously returned an empty list. Users will not be affected unless they were explicitly asking for this much slower algorithm. - Routine flavour() has been renamed to coords(). The old name remains for now as a deprecated alias. Class NNormalSurfaceSubset: - Routine getFlavour() has been renamed to coords(). The old name remains for now as a deprecated alias. Enum NormalCoords: - Renamed NS_FACE_ARCS to NS_TRIANGLE_ARCS. The old name is deprecated but has been kept for backward compatibility. Class NormalFlavour<...>, NormalInfo<...>: - This recently-added registry helper template has changed since the last release. Since this is a very new class whose primary role is in the redesign of the coordinate system registry, no backward compatibility aliases are provided. - The template itself has been renamed from NormalFlavour<...> to NormalInfo<...>. - The declaration has moved from flavourregistry.h to normalsurface.h, and the specialisations have moved to the corresponding coordinate system headers (nsstandard.h and so on). - The typedefs Vector, StandardFlavour and ReducedFlavour have been renamed to Class, Standard and Reduced. Class NPacket: - The requirements for new subclasses have changed, since the old macro-based registery was replaced with the new template-based registry. See the NPacket class notes for details. - The constant packetType is now a compile-time enum constant, not a static const int. - The new routine getHumanLabel() returns the packet label, but adjusted for human-readable output. In particular, an empty label will be replaced by "(no label)". - Routine getFullName() now makes labels more suitable for human-readable output as described above. - New routine internalID() to produce a string that uniquely identifies the packet (which nowadays the packet label does not). Class NPerm3, NPerm4, NPerm5: - New dimension-agnostic aliases orderedSn, SnIndex() and orderedSnIndex(). These all reference existing arrays/routines involving S3, S4 or S5 in NPerm3, NPerm4 and NPerm5 respectively. - Renamed toString() to the simper-to-type str(). The old name has been kept as a deprecated alias. Class NPillowTwoSphere: - Renamed getFace() and getFaceMapping() to getTriangle() and getTriangleMapping(). The old names are deprecated but have been kept for backward compatibility. Class NScript: - Variables are now stored as pointers to packets, not string-based packet labels. This affects the API (in a non-backward- compatible way), the behaviour (e.g., renaming a packet will not affect any script variable that references it), and the data file format (packets now have IDs that scripts can use to reference them). Class NSnapPeaTriangulation: - Updated the SnapPea kernel to the one shipped with SnapPy 2.0.3. - New routines randomize() / randomise() to randomly retriangulate. Class NSurfaceFilter: - The requirements for new subclasses have changed, since the old macro-based registry was replaced with the new template-based registry. See the NSurfaceFilter class notes for details. - The constant filterID has been renamed to filterType, and is now a compile-time enum constant (not a static const int). The old name has been kept as a deprecated alias. - Routines getFilterID() and getFilterName() have been renamed to getFilterType() and getFilterTypeName(). The old names have been kept as deprecated aliases. Class NTetrahedron: - Renamed getFace() and getFaceMapping() to getTriangle() and getTriangleMapping(). The old names are deprecated but have been kept for backward compatibility. Class NThread: - New routine join() to wait for threads to finish. Class NTriangle: - Detailed string output (via detail() / toStringLong()) now outputs details of where the triangle appears in each tetrahedron. Class NTriangulation: - New routines isIrreducible(), knowsIrreducible(), isHaken(), knowsHaken(), and knowsCompressingDisc(). - Routine hasCompressingDisc() has been updated to use the new fast branch-and-bound machinery. - New routines getNumberOfSimplices() and getSimplex(), which are dimension-agnostic aliases for getNumberOfTetrahedra() and getTetrahedron(). - New template routine getNumberOfFaces(), which is a dimension-agnostic routine for counting faces of any dimension. - Now inherits from the new helper class NGenericTriangulation<3>. - New routine isoSigComponentSize() for extracting the number of triangles from a signature (inherited from NGenericTriangulation). - Routine isoSig() now takes an optional argument that returns the isomorphism with the reconstruction from fromIsoSig(). - New routines snapPea() and fromSnapPea() to import and export SnapPea data using strings, without writing to the filesystem. - New "magic constructor" that attempts to interpret a given string as a 3-manifold triangulation under several possible encodings. - Routine isThreeSphere() now includes a fast check for an "obviously" trivial fundamental group. - Renamed FaceIterator, faceIndex(), getFace(), getFaces(), getNumberOfFaces() and hasBoundaryFaces(), where "face" now becomes "triangle". The old names are deprecated but have been kept for backward compatibility. - Results from hasCompressingDisc() and isHaken() are now stored in data files. - The output from getPacketTypeName() has changed from "Triangulation" to "3-Manifold Triangulation". Class NVertex: - Added buildLinkDetail(), which returns details of how triangles of the vertex link are embedded within individual tetrahedra. - Detailed string output (via detail() / toStringLong()) now outputs details of where the vertex appears in each tetrahedron. Class NXMLPacketReader, NXMLTreeResolver, NXMLTreeResolutionTask: - The API for reading packets from an XML data file has changed to incorporate the new NXMLTreeResolver class, which allows the resolution of dangling packet references after an entire data file has been read. Class PacketInfo: - Template classes that store traits of the various packet types. These are used with the new forPacket() template functions. Enum PacketType: - A new enumeration that contains constants representing different packet types. Include "packet/packettype.h". Struct Returns: - Moved into utilities/registry.h. However, its contents are still included from its previous header surfaces/filterregistry.h. Class ShareableObject: - Renamed toString() and toStringLong() to the simper-to-type str() and detail(). The old names have been kept as deprecated aliases. Class SurfaceFilterInfo: - Template classes that store traits of the various normal surface filter classes. These are used with the new forFilter() template functions. Enum SurfaceFilterType: - A new enumeration that contains constants for different types of normal surface filter. Include "surfaces/surfacefiltertype.h". Routine forFlavour(), forCoords(): - Renamed each variant of forFlavour() to forCoords(). The old names have been kept as deprecated aliases. Routine stringToToken(): - Moved from foreign/snappea.h into utilities/stringutils.h. Routine readSnapPea(), writeSnapPea(): - Added istream/ostream versions of these routines. - In writeSnapPea(), the NTriangulation& argument is now const. Headers dimtraits.h, nfacetspec.h, ngenericisomorphism.{h,tcc}: - Moved from triangulation/ to generic/. The old header locations are now deprecated. They have been kept for backward compatibility, but simply include the new headers instead. Header filterregistry.h: - The REGISTER_FILTER macros have been removed. To iterate through surface filter types, use the new forFilter() template functions. Header flavourregistry.h, coordregistry.h: - Renamed flavourregistry.h to coordregistry.h. The old header has been kept as a deprecated alias. - The REGISTER_FLAVOUR macros have been removed. To iterate through coordinate systems, use the forCoords() template functions. Header packetregistry.h: - The REGISTER_PACKET macros have been removed. To iterate through packet types, use the new forPacket() template functions. Headers *.tcc: - All *.tcc headers have been renamed as *-impl.h, to play better with development IDEs. The old header names are now deprecated but have likewise been kept for backward compatibility. USER INTERFACE: - The root container packet is now hidden from the user (it still exists internally within the packet tree). - The triangulation viewer now explicitly states "not oriented" for orientable-but-not-oriented triangulations. - The old regina-kde placeholder app (which did nothing but pop up a message directing the user to the new regina-gui) has been removed. - The boundary component viewer now displays more detailed information. PYTHON: - The python module 'regina' now has its own __init__.py, and loads 'regina.engine' as an extension submodule. All symbols from regina.engine are imported directly into 'regina', so users can continue to work directly with the 'regina' namespace as before. - For an XDG build (e.g., on GNU/Linux), the python module is now installed in the standard python site-packages directory, which means you can easily import the module from a normal python session. - Added a useful __repr__ for the core types NInteger, NLargeInteger, NRational, NPerm3, NPerm4 and NPerm5. TEST SUITE: - More NInteger / NLargeInteger tests, this time comparing operations when the same arguments are coerced from natives to GMP integers. - NBitmask tests for the bits() function. - Added python tests for the Orb import filter; thanks to Craig Hodgson for the sample files. Version 4.94 [ 24 September, 2013 ] GENERAL: - Old-style binary files are no longer supported. These have not been in use for over a decade. If you have an old-style binary file that you need to use, install Regina 4.93 and use the regconvert tool. - Widespread alignment of integer sizes throughout the code. Many integers have changed from int to long, or from unsigned to unsigned long (or size_t), throughout the API. - Fixed some minor memory leaks. ENGINE: Class NAbelianGroup, NGroupExpression, NGroupExpressionTerm, NGroupPresentation: - Removed writeToFile(NFile&) and readFromFile(NFile&, ...), which were used for old-style binary files. Class NAngleStructure: - Removed writeToFile(NFile&) and readFromFile(NFile&, ...), which were used for old-style binary files. Class NAngleStructureList: - More frequent and robust cancellation checking during enumeration of vertex angle structures. Class BanConstraintBase, BanNone, BanBoundary, BanTorusBoundary: - New constraint classes for use with the new tree traversal code for enumerating normal surfaces. See NTreeTraversal for details. Class Dim2Census, Dim2EdgePairing, Dim2GluingPerms, Dim2GluingPermSearcher: - New classes for building a census of 2-manifold triangulations. Class Dim2TriangleEdge: - New convenience typedef for NFacetSpec<2>. Class Dim2Triangulation: - New 2-manifold triangulation class. This is a new packet type that can be independently stored in data files. Class Dim2BoundaryComponent, Dim2Component, Dim2Edge, Dim2EdgeEmbedding, Dim2Isomorphism, Dim2Triangle, Dim2Vertex, Dim2VertexEmbedding, NXMLDim2TriangulationReader: - New classes to support Dim2Triangulation. Class Dim2ExampleTriangulation: - New class for building common 2-manifold triangulation. Includes support for every possible 2-manifold. Class DimTraits: - New template class to assist with dimension-agnostic code. Class Flags: - New template class for forming bitwise combinations of flags based on enumeration values. Class HashPointer, HashString: - Removed, after being deprecated for a very long time now. Class IntOfSize: - New template class for using native integer types whose sizes are not determined until compile time. Class LPConstraintBase, LPConstraintSubspace, LPConstraintNone, LPConstraintEuler, LPConstraintNonSpun: - New constraint classes for use with the new tree traversal code for enumerating normal surfaces. See NTreeTraversal for details. Class LPData, LPInitialTableaux, LPMatrix: - New classes that implement the dual simplex method, for use with the new tree traversal code for enumerating normal surfaces. See NTreeTraversal for details. Class NAbelianGroup: - New convenience routines isZ() and isZn(). Class NBlockedSFS: - Now supports Seifert fibred spaces with boundary. Class NCensus: - The NProgressManager* argument has been removed from formCensus(). If you are doing serious census generation, use the command-line utility tricensus (or tricensus-mpi) instead. Class NClosedPrimeMinSearcher, NCompactSearcher: - Improved the way in which cones and L(3,1) spines are detected and pruned during census enumeration. - Improved the way in which too many high degree edges are detected and pruned during census enumeration. Class NDoubleDescription: - More frequent polling for cancellation. - The progress tracker passed to enumerateExtremalRays() is now of class NProgresstracker, not NProgressNumber. Class NEdge: - New convenience routine getTriangulation(). Class NEnumConstraintList: - This now holds unsigned longs, not unsigned ints, for consistency with the integer types used for NVector indexing. Class NFace: - New convenience routine getTriangulation(). Class NFacePairing: - Now derives from the template base class NGenericFacetPairing<3>. - Renamed getNumberOfTetrahedra() to size(). The old name is deprecated, and will be removed in a future release. Class NFile, NFilePropertyReader: - Removed these classes, which were used for old-style binary files. Class NFileInfo: - Removed TYPE_BINARY, which was used for old-style binary files. Class NGenericFacetPairing: - New template base class that contains dimension-agnostic code for representing face/facet pairings. Class NGenericIsomorphism: - New template base class that contains dimension-agnostic code for representing isomorphisms between triangulations. Class NGroupExpression: - New routines wordLength(), erase(), cycleLeft(), cycleRight(), invert(), writeTeX(), and a version of writeText() that takes an extra argument to control the output style. Class NGroupPresentation: - Finally intelligentSimplify() really is intelligent. It now uses Dehn simplification / small cancellation theory. - New routine intelligentSimplify(NHomGroupPresentation*) for keeping track of how the group was simplified. - New routines relatorLength(), abelianlisation(), markedAbelianisation(), writeTeX(), toTeX(), writeTextCompact() and toStringCompact(). - More readable output from writeTextLong(). - New assignment operator (=). Class NHilbertCD: - The NProgressMessage* argument to enumerateHilbertBasis() has been removed, since in reality the current algorithm offers no sensible progress tracking or cancellation polling. Class NHilbertDual: - More frequent polling for cancellation. - The progress tracker passed to enumerateHilbertBasis() is now of class NProgressTracker, not NProgressNumber. Class NHilbertPrimal: - The progress tracker passed to enumerateHilbertBasis() is now of class NProgressTracker, not NProgressMessage. Class NHomGroupPresentation: - New class to represent homomorphisms between groups. Class NHomMarkedAbelianGroup: - New routine torsionSubgroup(). Class NHomologicalData: - Removed all dependencies on the old NIndexedArray. Class NIndexedArray: - Removed, after being deprecated for a very long time now. Class NInteger: - NInteger is a typedef for the new template class NIntegerBase, which offers fast arbitrary precision integers but does not support infinity. Class NIntegerBase: - This is a new template class that supercedes (and is based on) the old NLargeInteger. The boolean template argument indicates whether the class supports infinity as an allowed value. - Heavily rewritten from the old NLargeInteger: this class works with native C/C++ integers for as long as possible, and only switche to GMP when it becomes unavoidable. This makes the code enormously faster (rough testing suggests a roughly 7x speedup). - Made the destructor non-virtual to avoid the unwanted class overhead that comes with polymorphism. - Added new routines that were not in the old NLargeInteger, including isZero(), sign(), gcdWith(), lcmWith(), and nativeValue(). Class NIsomorphism: - Now a subclass of NGenericIsomorphism<3>, with inherited dimension-agnostic aliases for several routines. Class NLargeInteger: - NLargeInteger is now a typedef for the new template class NIntegerBase, and maintains backward compatibility. - Performance is much, much faster; see NIntegerBase for details. Class NLocalFileResource, NRandomAccessResource: - Removed these classes, which were used for old-style binary files. Class NMarkedAbelianGroup: - New routines torsionSubgroup() and torsionInclusion(). Class NMatrix: - New routine isZero(). Class NNativeInteger: - New template class that wraps native integer types with very little overhead and offers an interface compatible with NInteger. Class NNativeLong: - A convenience typedef for the new class NNativeInteger. Class NNormalSurface: - Routine boundarySlopes() now requires that the triangulation is oriented (otherwise SnapPea will relabel tetrahedron vertices and the matrix returned will be null). - Routines findNonTrivialSphere() and findVtxOctAlmostNormalSphere() are deprecated. Use NTriangulation::hasNonTrivialSphereOrDisc() and NTriangulation::hasOctagonalAlmostNormalSphere() instead. - Removed writeToFile(NFile&) and readFromFile(NFile&, ...), which were used for old-style binary files. Class NNormalSurfaceList: - New routines which() and algorithm() now retain details of which surfaces where enumerated and how this was done. - Now uses the new tree traversal method as a preferred enumeration algorithm where possible. This is a significant improvement upon the old double description method. See NTreeEnumeration and arXiv:1010.6200 for details. - The coordinate flavours (STANDARD, QUAD, etc.) are deprecated, and have changed from integers to NormalCoords enum types. Instead of these, use the NormalCoords enum values directly (NS_STANDARD, NS_QUAD, etc.). For both C++ and Python users, these enum values are available directly in the namespace scope. - More frequent and robust cancellation checking during enumeration of vertex surfaces. - The old enumeration routines have been deprecated. These include enumerate(NTriangulation*, int, bool, NProgressManager*), enumerateStandardDirect(), enumerateStandardANDirect(), enumerateFundPrimal(), enumerateFundDual(), enumerateFundCD() and enumerateFundFullCone(). Users should now use the "universal" enumeration routine enumerate(NTriangulation*, NormalCoords, NormalList, NormalAlg, NProgressTracker*), which offers sensible default as well as fine-grained control over the underlying algorithms. - In all enumeration routines that take progress trackers, the old-style NProgressManager* arguments have been replaced with NProgressTracker* arguments, which are more flexible and more streamlined. - The routine getFlavour() is now renamed to flavour(). The old getFlavour() is still available but deprected. - This class no longer inherits from NSurfaceSet (which has been removed). As a result, getShareableObject() is no longer necessary and has likewise been removed. Enum NormalCoords: - A new enumeration that contains constants for different normal surface coordinate systems. Include "surfaces/normalcoords.h". Class NormalFlavour: - Template classes that store traits of the various normal surface coordinate systems. These are used with the new forFlavour() template functions. Enum NormalListFlags, Class NormalList: - Flags that specify which normal surfaces a particular list represents within a given triangulation. Enum NormalAlgFlags, Class NormalAlg: - Flags that specify details and parameters of normal surface enumeration algorithms. Class NPacket: - Fix crash when sortChildren() is run on the root packet. - Removed writePacket(NFile&) and readPacket(NFile&), which were used for old-style binary files. Class NPerm3, NPerm4, NPerm5: - New dimension-agnostic alias Sn that refers to S3, S4 and S5 in NPerm3, NPerm4 and NPerm5 respectively. - New dimension-agnostic alias Sn_1 that refers to S2, S3 and S4 in NPerm3, NPerm4 and NPerm5 respectively. - New dimension-agnostic enum constants nPerms and nPerms_1 that contain the number of permutations in Sn and Sn_1 respectively. - New construtors that take an array of images. - NPerm3 and NPerm5 now have a copy of S2 (which NPerm4 already had). Likewise, NPerm5 now has a copy of S3, orderedS3, S4 and orderedS4 (which NPerm4 again already had). - NPerm4::invS2 and NPerm4::invS3 are deprecated: the former is unnecessary, and the latter is identical to NPerm3::invS3. - NPerm3 now has a transposition constructor: NPerm3(a,b). Class NProgress, NProgressFinished, NProgressManager, NProgressMessage, NProgressNumber, NProgressStateNumeric: - Deprecated in favour of the new NProgressTracker (see below). Class NProgressTracker: - A new unified and streamlined progress tracking mechanism that replaces the old suite of NProgress classes (i.e., NProgressManager and the NProgress class hierarchy). Class NQitmask1, NQitmask2: - Fast classes for working with 0/1/2/3 "qits", i.e., "base 4 bits". Class NSatBlock: - Routine nextBoundaryAnnulus() has acquired an extra boolean argument, which allows us to choose between "next" and "previous". Class NSatRegion: - Routine createSFS() no longer need to be given the number of boundary components, and now supports Klein bottle boundaries. The old two-argument version is now deprecated. Class NSnapPeaTriangulation: - Updated the SnapPea kernel to the one shipped with SnapPy 1.8.0. - New routine toRegina() to extract the underlying SnapPea triangulation, or to see exactly how SnapPea has relabelled and/or retriangulated. - New routine canonize() to produce the canonical retriangulation of the canonical cell decomposition. Class NSurfaceFilter: - Removed writeFilter(NFile&) and readFilter(NFile&, ...), which were used for old-style binary files. Class NSurfaceSet: - Removed. The corresponding functionality has been moved directly into the subclasses NNormalSurfaceList and NSurfaceSubset. Class NSurfaceSubset: - No longer inherits from NSurfaceSet (which has been removed). As a result, getShareableObject() is no longer necessary and has likewise been removed. - The constructor now takes a reference to an NNormalSurfaceList, not an NSurfaceSet. Class NTetrahedron: - New dimension-agnostic aliases adjacentSimplex() and adjacentFacet(). These are identical to adjacentTetrahedron() and adjacentFace() respectively, and can help with writing code that works with more than one dimension. Class NTreeTraversal, NTreeEnumeration, NTreeSingleSolution: - New class for enumerating vertex normal surfaces and locating a single vertex normal surface under some linear constraint (such as positive Euler characteristic). These are a significant improvement upon the old double description method. For details see arXiv:1010.6200 and arXiv:1211.1079 respectively. Class NTriangulation: - New routine drillEdge() to drill out a regular neighbourhood of an edge. - New optimised routines hasNonTrivialSphereOrDisc() and hasOctagonalAlmostNormalSphere() that use linear programming where possible to avoid a full enumeration of vertex surfaces. See arXiv:1211.1079 for details. - Some routines are now *much* faster for larger triangulations, thanks to the new linear programming code (arXiv:1211.1079). These include isZeroEfficient(), isThreeSphere(), isSolidTorus(), connectedSumDecomposition(), and makeZeroEfficient(). - Rewrote barycentricSubdivision(): the code is now clearer, but note that the precise labelling of the new tetrahedra has changed from earlier versions of Regina. - Routine insertTriangulation() now works in the case where a triangulation tries to insert itself. - New dimension-agnostic aliases getNumberOfSimplices(), getSimplices(), getSimplex(), simplexIndex(), newSimplex(), removeSimplex(), removeSimplexAt() and removeAllSimplices(). These are identical to the corresponding routines for operating on tetrahedra, and can help with writing code that works with more than one dimension. - Fixed isZeroEfficient(), which was reporting incorrect results for ideal triangulations. - Removed the old (and slow) getTetrahedronIndex(), getFaceIndex() and so on. Use tetrahedronIndex(), faceIndex(), etc. instead. - All routines that took stdhash::hash_set arguments now take std::set arguments instead. Class NTritmask1, NTritmask2: - Fast classes for working with 0/1/2 trits, i.e., "ternary bits". Class NTypeTrie: - A fast data structure for storing zero/non-zero patterns in vertex normal surfaces. This supports the new tree traversal enumeration code; see NTreeTraversal for details. Class NVertex: - New routine buildLink() to triangulate the vertex link. - New convenience routine getTriangulation(). Class ZBuffer: - Updated xsgetn() to support n larger than UINT_MAX. Routine base64Decode(), base64Encode(): - Replace the old GPL-licensed implementation with a different MIT-licensed implementation. Functionality is the same. Routine forFlavour(): - New template functions that offer a typesafe way of iterating through cases of different normal coordinate systems without abusing the C++ preprocessor. These should be used instead of the old (and now deprecated) REGISTER_FLAVOUR macros. Variants of forFlavour() are offered for different function types. Routine readFromFile(), writeToFile(): - Removed, since these were used with old-style binary files. Routine readOrb(): - Updated to correctly read the modern (and more verbose) Orb file format. Thanks to Lorenzo Losa for the patch. Typedef NFacePairingIsoList, UseFacePairing: - These typedefs have been renamed as NFacePairing::IsoList and NFacePairing::Use respectively. The old typedefs are deprecated, and will be removed in some future release. Header flavourregistry.h: - The old REGISTER_FLAVOUR macros are now deprecated, and will eventually be removed. The preferred way to iterate through coordinate flavours is the new forFlavour() template functions. Header hashmap.h, hashset.h, hashutils.h: - Removed, after being deprecated for a very long time now. Header nlargeinteger.h: - Deprecated in favour of the new ninteger.h. USER INTERFACE: In addition to incorporating the new mathematical changes above: - The preference dialog is somewhat simpler now. + Some preferences are gone, and instead Regina simply remembers your last selection (e.g., default tabs for various viewers). + Some preferences have just been removed from the dialog (e.g., the calculations thresholds), though users who really need these can still access them through the configuration file. - The elementary move dialog contains richer information about where the moves can take place, and stays open so that you can perform several moves one after another. UTILITIES: regconvert: - The option -b (for old-style binary files) is no longer supported. regina-python: - Enabled tab completion, courtesy of readline and rlcompleter. - The --quiet option no longer lists libraries as they are loaded. tricensus: - Now takes an optional argument -2/--dim2 to enumerate 2-manifold triangulations. - Now takes an optional argument -c/--subcontainers to store triangulations in subcontainers according to face pairings. TEST SUITE: - Greatly expanded the tests for NLargeInteger and NInteger, which are now extremely thorough. - New and more thorough NTriangulation tests for barycentric subdivision, drilling edges, 0-efficiency testing, 3-sphere recognition, connected sum decomposition, solid torus recognition, and comparing H1 with the abelianised fundamental group. - New NNormalSurfaceList tests for comparing the results of different vertex / fundamental surface enumeration algorithms. Also, exhaustive tests over census data now include ideal triangulations. - New enumeration tests for Dim2EdgePairing and Dim2Census. - New tests for permutation databases Sk and orderedSk. - New tests for base64 conversion. - Expanded tests for the NRational class. - Expanded enumeration tests for facet pairing classes to include pairings with boundary facets. Version 4.93 [ 30 May, 2012 ] ENGINE: Class NAngleStructure: - New routine isVeering() to test for veering structures. - Flags (taut/strict/veering) are no longer stored in data files. Class NBlockedSFSLoop, NBlockedSFSTriple, NPluggedTorusBundle: - Corrected an off-by-one error in computing the genus of certain non-orientable base orbifolds for Seifert fibred pieces. This only affects census manifolds with >= 12 tetrahedra; in particular, no existing census data is affected. Class NExampleTriangulation: - New routine weeks() to build the Weeks manifold. Class NNormalSurface: - Routines isOrientable(), isTwoSided() and isConnected() now return bool instead of NTriBool. This helps avoid unintended errors in scripts, but be warned: these properties can only be computed for compact surfaces (not spun normal surfaces). - Routines isIncompressible() and isCompressingDisc() likewise now return bool instead of NTriBool. Class NTriangulation: - New routines isSolidTorus() and knowsSolidTorus() for "one-click unknot recognition". - Routine hasCompressingDisc() now returns bool instead of NTriBool. Class NTriBool: - Deprecated. This class has been replaced with ordinary (two-way) bool throughout Regina, and will be removed in a future release. Routine writeRecogniser(): - Added to support sending triangulations to Matveev's 3-manifold recogniser software. USER INTERFACE: - Restored File -> Save and File ->Save As, which were missing from the main menu in version 4.92. - In the triangulation viewer, the old "Surfaces" tab has been renamed as the "Recognition" tab, and includes high-level algorithms such as 3-sphere recognition as well as "opportunistic" combinatorial recognition. - Replaced the python icon with a generic terminal icon. - GUI python consoles now set the variable "item", not "selected". This is easier to type, and avoids the misconception that selecting a different packet in the tree might change the variable (which it doesn't). The variable "selected" is also set for backward compability, though this will be removed in a future release. - GUI python consoles will now set item=None if there is nothing selected in the packet tree. - Simplified the cut/copy/paste behaviour in graphical Python consoles. - The knot/link census is now explicitly called the *hyperbolic* knot/link census, since non-hyperbolic knots or links are excluded. DOCUMENTATION: - Layout and navigation improvements in the user handbook. TEST SUITE: - Added several tests related to Hakenness testing. Version 4.92 [ 12 April, 2012 ] - The "hello Windows!" release. INSTALLATION: - Regina now builds and runs under Windows! - MacOS users now have a drag-and-drop app bundle, and do not need fink at runtime. - Linux (and indeed all) users no longer need KDE, since the user interface is now Qt-only. ENGINE: Class NBitmask: - Make NBitmask more suitable for use in containers. Specifically, the assignment operator can now be used to initialise an uninitialised bitmask or to reset an already-initialised bitmask to a different length, and one or both of its operands may be invalid. Class NBitmask, NBitmask1, NBitmask2: - New function lessThan() for lexicographical comparisons. Class NDoubleDescription: - Removed the inner class LexComp, and replaced it with the new global class NPosOrder (see below). A deprecated typedef NDoubleDescription::LexOrder is kept for backward compatibility. Class NFacePairing: - Function writeDot() can now optionally label graph vertices with the corresponding tetrahedron numbers. - Added graphviz export routines dot() and dotHeader(), which are like writeDot() and writeDotHeader() but return strings instead of writing to standard output. Class NFacetSpec: - New template class that generalises NTetFace to arbitrary dimensions. NTetFace is retained as a convenience typedef, but with changes; see the NTetFace notes below. Class NGlobalDirs: - New routine setDirs() to be used when an application has been moved from the cmake-configured installation directory. Class NHilbertCD: - New class that implements a modified Contejean-Devie algorithm for Hilbert basis enumeration, based on the original algorithm in "An efficient incremental algorithm for solving systems of linear Diophantine equations", Contejean and Devie, Inform. and Comput. 113 (1994), 143-172. Class NHilbertDual: - New class that implements a modified dual algorithm for Hilbert basis enumeration, based on the dual algorithm in "Normaliz: Algorithms for affine monoids and rational cones", W. Bruns and B. Ichim, J. Algebra 324 (2010), 1098-1113. Class NHilbertPrimal: - New class that enumerates Hilbert bases by decomposing into maximal admissible faces and running the primal algorithm from Normaliz on each such face. For details, see "Fundamental normal surfaces and the enumeration of Hilbert bases", B. Burton, arXiv:1111.7055, November 2011. Class NLargeInteger: - Made separate constructors and assignment operators for arguments of type int, unsigned int, long, and unsigned long. - Added ++ and -- operators. - Added (long + NLargeInteger) and (long * NLargeInteger) operators. - New routines setRaw() and rawData() for interacting directly with libgmp and libgmpxx. Class NMaxAdmissible: - New class for enumerating maximal admissible faces of the normal surface solution cone. Class NNormalSurface: - New routine boundarySlopes() that calculates boundary slopes for spun normal surfaces. - New routines getOrientedTriangleCoord() and getOrientedQuadCoord() for transversely oriented normal surfaces. Class NNormalSurfaceList: - New routines enumerateFundPrimal() and enumerateFundDual() to enumerate fundamental normal surfaces, as well as slower routines enumerateFundFullCone() and enumerateFundCD() for comparing different enumeration algorithms. - New coordinate systems ORIENTED and ORIENTED_QUAD to support transverse oriented normal surfaces. - New routines beginVectors() and endVectors() and new inner class VectorIterator for iterating through raw normal surface vectors. - New routine allowsOriented(), indicating whether the underlying coordinate system supports transverse orientations. Class NNormalSurfaceVector: - New routines getOrientedTriangleCoord() and getOrientedQuadCoord() for transversely oriented normal surfaces. - New routine allowsOriented(), indicating whether the underlying coordinate system supports transverse orientations. Class NNormalSurfaceVectorOriented, NNormalSurfaceVectorOrientedQuad: - New coordinate systems for transversely oriented normal surfaces. Class NPacket: - Fixed potential crash in fireDestructionEvent(). Class NPerm3: - New routine compareWith() for sorting permutations. Class NPerm5: - New class describing permutations of five elements. Class NPosOrder: - Class for sorting hyperplanes during vertex enumeration. This is the new name for the old NDoubleDescription::LexComp. Class NSnapPeaTriangulation: - New routine slopeEquations() that uses code from SnapPy to compute boundary slope matrices for cusps. - New routine verifyTriangulation() for ensuring that SnapPea has not retriangulated unexpectedly. Class NSurfaceSet: - New routine allowsOriented(), indicating whether the underlying coordinate system supports transverse orientations. Class NTetFace: - Now an instance of the arbitrary-dimension template class NFacetSpec. NTetFace is retained as a typedef, but the fields have been renamed from tet/face to the more general simp/facet. Class XMLPropertyDict: - Removed the optional defaultVal argument from lookup(); the default is now always the empty string. Routines perm4to5, perm5to4, perm3to4, perm4to3: - New routines for converting between permutation classes. Routine makeEmbeddedConstraints(): - Added to help generate admissibility constraints based on a flavour constant, instead of an NNormalSurfaceVector subclass. Routines writeCSVStandard, writeCSVEdgeWeight: - Included boundary slopes of spun-normal surfaces in CSV output. Macro REGISTER_FLAVOUR: - Now requires an additional argument, indicating whether the coordinate system supports transverse orientations. USER INTERFACE: - Ported from KDE to Qt-only. - Moved from a single monolithic window to lots of small windows (one for the tree, one for each open packets). The old interface can be re-enabled through Regina's preferences. - Continued the user interface overhaul, again with many more improvements that give cleaner and more sensible behaviour (too many changes to list individually). - Graphical Python consoles now execute "from regina import *" automatically. UTILITIES: regina-python: - Now executes "from regina import *" automatically. You can suppress this with the argument --noautoimport. - For MacOS users: make sure 32-bit python is called when running 32-bit fink on a 64-bit machine. tricensus: - Now outputs all face pairings as it runs, instead of periodic snapshots of where the census is up to. Version 4.91: Internal development version. Version 4.90 [ 12 September, 2011 ] - First prerelease for version 5.0. OVERALL: - The graphical user interface has been ported from KDE3 to KDE4. - The build system has been ported from autotools to cmake. - The built-in portions of the SnapPea kernel have been re-synced with the September 2009 version of SnapPea. DOCUMENTATION: - The users' handbook has undergone a thorough overhaul. It is cleaner, more streamlined, and now full of screenshots. - The data file format has been split out of the users' handbook and placed in its own separate reference manual. ENGINE: Typedef AcceptTriangulation: - This global typedef has been deprecated. Please use the class typedef NCensus::AcceptTriangulation instead. Class BitManipulator, GenericBitManipulator: - BitManipulator has new routines firstBit() and lastBit(), which return the positions of the first and last true bit respectively. This has required the addition of a new non-optimised base class GenericBitManipulator, which end users need never use directly. Class NAbelianGroup: - Routine addRank() now takes a signed integer, so that you can subtract from the rank as well as add to it. - Two new constructors to compute the homology of a chain complex with integer or mod-p coefficients. Thanks to Ryan Budney. Class NAngleStructureList: - There is now an option to enumerate only taut angle structures, which is significantly faster than enumerating all vertex angle structures. As a result, enumerate() now takes three arguments, there is a new routine isTautOnly(), and the data file format for angle structure lists contains a new element "angleparams". - Renamed allowsStrict() and allowsTaut() to spansStrict() and spansTaut(). The old routines are now deprecated but have been preserved (for now) for backward compatibility. Class NAngleStructureVector: - Removed clone(). Just use the copy constructor instead. Class NBitmask, NBitmask1, NBitmask2: - New operators ^= (XOR), -= (set difference) and = (assignment). - New routine truncate(), which truncates a bitmask to a given number of bits by setting all subsequent bits to zero. - New routines firstBit() and lastBit(), which return the positions of the first and last true bit respectively. - New convenience typedefs NBitmaskLen8, NBitmaskLen16, NBitmaskLen32 and NBitmaskLen64 for fast-and-small bitmasks of predetermined sizes. Class NCensus: - New class typedef NCensus::AcceptTriangulation to replace the old global typedef AcceptTriangulation. Class NDiscSetTetData: - Added assertions in data() to ensure that the given disc type and number are valid. These can be circumvented by compiling with -DNDEBUG. Class NDoubleDescription: - Method enumerateExtremalRays() no longer has the "base" argument (which was used for cloning vectors); instead the method takes a new template argument specifying a vector class, and new vectors are created using the corresponding class constructors. - Improved the speed of adjacency testing by using an NTrieSet instead of a linear search through all vertices. See the NNormalSurfaceList notes below for further information. - Method enumerateExtremalRays() now takes an optional argument initialRows, allowing the user to force certain hyperplanes to be processed first. Class NExampleTriangulation: - New routine bingsHouse() returning the dual triangulation to Bing's house with two rooms. - Renamed seifertWeber() to weberSeifert(), for consistency with the original paper. The old routine is now deprecated, but has being preserved (for the time being) for backward compatibility. Class NFacePairing: - Fixed the human-readable output for boundary faces in toString(). Previously boundary faces were displayed as "n:0"; now they are displayed as "bdry". Class NFastRay: - Merged into the NRay class; see the NRay and NVector changes for details. Because typedefs cannot be templated, there is no legacy typedef; instead NFastRay has been removed completely. Class NFastVector: - Merged into the NVector class; see the NVector changes for details. Because typedefs cannot be templated, there is no legacy typedef; instead NFastVector has been removed completely. Class NGlobalDirs: - New routine data() to return the internal data directory. Class NGroupPresentation: - Fixed a memory leak in intelligentSimplify(). Class NIsomorphism: - New routine applyInPlace() to directly modify a triangulation. - Routine apply() now copies tetrahedron descriptions as well as gluings (and so does the new routine applyInPlace()). Class NLayeredSurfaceBundle: - In isLayeredTorusBundle(), extend the search for possible cores to 11 and 12 tetrahedra. Class NLargeInteger: - New routines randomBoundedByThis(), randomBinary() and randomCornerBinary() for pseudo-random number generation. - Faster (GMP-native) implementation of swap(). Class NMarkedAbelianGroup, NHomMarkedAbelianGroup: - Both of these classes have much richer interfaces than before, and some old routines have now been deprecated. See the class documentation for full details. Thanks to Ryan Budney. Class NMarkedVector: - Added swap() to swap the contents of two vectors. Class NNormalSurface: - New routines isCompressingDisc() and isIncompressible() for testing incompressibility. - Fixed a memory leak in crush(). Class NNormalSurfaceList: - Sped up enumeration (again), this time by using a trie-like structure for adjacency testing. For the Weber-Seifert space this improves speed threefold (roughly). Many thanks to Jonathan Shewchuk for encouraging me to focus on the adjacency testing bottleneck. - New filtering routines filterForLocallyCompatiblePairs() and filterForDisjointPairs(). - New routine filterForPotentiallyIncompressible() to assist with bulk incompressibility testing; see arXiv:0909.4625 for details. - New routine allowsSpun() to easily identify coordinate systems that support spun normal surfaces. Class NNormalSurfaceVector: - Due to the changes in the NVector hierarchy, clone() is now introduced as a virtual function of NNormalSurfaceVector (not NVector), and it now returns an NNormalSurfaceVector*. Class NPacket: - In the python interface, makeOrphan() now returns the packet itself and the ownership becomes the responsibility of whoever takes this return value. If nobody takes this return value then the packet and its descendants are automatically destroyed. - ChangeEventBlock has been renamed to ChangeEventSpan, it fires both packetToBeChanged() and packetWasChanged() (on construction and destruction respectively), and the optional boolean argument is gone (events are now fired always). The old class name ChangeEventBlock remains as a deprecated typedef for ChangeEventSpan. - The protected routine fireChangedEvent() has been removed. The only way to fire a "packet changed" event now is to declare a local ChangeEventSpan. Class NPacketListener: - All events (except for destruction) now come with both future and past events: packetToBeChanged() and packetWasChanged(), childToBeAdded() and childrenWereAdded(), and so on. Class NPerm: - Renamed to NPerm4. The C++ header has also moved from triangulation/nperm.h to maths/nperm4.h . Both the old class name and the old header are now deprecated. - There are many other changes; see the NPerm4 notes below. Class NPerm3: - New class describing permutations of three elements. This is extremely fast, using lookup tables for all calculations. Class NPerm4: - This is the new name for the old class NPerm (see above). - New routines S4Index() and orderedS4Index() for reverse lookups into the arrays NPerm4::S4 and NPerm4::orderedS4. - The constructor that takes an internal permutation code is now private, and is replaced by a new static routine NPerm4::fromPermCode(). This new routine is easier to spot and grep for. - The internal permutation codes have changed. As a result, NPerm4 operations are significantly faster. The old codes are now referred to as "first-generation", and the new codes are referred to as "second-generation". - Routines getPermCode(), setPermCode(), isPermCode() and fromPermCode() continue to refer to first-generation codes. These old routines are not recommended, since they now incur additional overhead. To replace them, the new (and faster) routines getPermCode2(), setPermCode2(), isPermCode2() and fromPermCode2() work with second-generation codes instead. - The XML data file format continues to use first-generation permutation codes (for backward compatibility). Class NRational: - New STL-compatible routine swap(). Class NRay: - Like the vector hierarchy, NFastRay and NRay are now merged into a single NRay class. The result is that NRay is now cleaner and faster, but methods are no longer virtual. See the NVector class notes for full details of the changes (including important changes in the parent NVector class). - Removed the old intersect() function, which was based on virtual methods. Class NScript: - Fixed a bug that lost script variables when reading ancient binary files (i.e., files created before Regina 3.0, around mid-2002). This bug only showed up on some compilers. Class NSnapPeaCensusManifold, NSnapPeaCensusTri: - Routines getHomologyH1() (for both classes) and construct() (for NSnapPeaCensusManifold) are now implemented for all SnapPea census manifolds/triangulations, not just the smallest few. Class NSnapPeaTriangulation: - Kernel messages are now disabled by default. Class NSurfaceSet, NSurfaceSubset: - New routine allowsSpun() to easily identify coordinate systems that support spun normal surfaces. Class NTetrahedron: - Tetrahedra should now always belong to a triangulation, from creation until destruction. In particular: + Tetrahedra should be created by calling NTriangulation::newTetrahedron(), which will insert them into a triangulation immediately. There is no need to call NTriangulation::addTetrahedron() any more. + NTetrahedron::joinTo() now recursively adds adjacent tetrahedra to the relevant triangulation (but if you use NTriangulation::newTetrahedron() as described above then this is fast and changes nothing). - Users no longer need to call NTriangulation::gluingsHaveChanged() after gluing or ungluing tetrahedron faces; this is now handled automatically. - The NTetrahedron constructors are now deprecated in favour of NTriangulation::newTetrahedron(), as described above. - New routine getVertexMapping(), which facilitates a consistent orientation around the given vertex for the three remaining vertices in each tetrahedron. - Added assertions in joinTo() and unjoin() to ensure that the preconditions are met. These can be circumvented by compiling with -DNDEBUG. - Routines that need the triangulation skeleton (e.g., getVertex(), getEdgeMapping(), orientation(), etc.) will now compute the skeleton automatically if this has not already been done. - New routine getTriangulation() to return the enclosing triangulation. Class NTriangulation: - Add new routines newTetrahedron() and newTetrahedron(const std::string&). This is now the preferred way of creating tetrahedra (see the NTetrahedron notes above). The old addTetrahedron() is now deprecated. - Users no longer need to call gluingsHaveChanged(), which is likewise deprecated. Again, see the NTetrahedron notes above. - Routines removeTetrahedron() and removeTetrahedronAt() now destroy the tetrahedron immediately and return nothing. - New routines hasCompressingDisc() and hasSimpleCompressingDisc() to search for compressing discs; see arXiv:0909.4625 for details. - The "legality conditions" on closeBook() are now simpler, since some of the conditions were automatic consequences of others. Practically, nothing has changed (i.e., the new conditions will be satisfied if and only if the old conditions were satisfied). - The "legality conditions" on twoOneMove() were originally too conservative, and are now weaker. In particular, the endpoints of the edge may now both be boundary. Practically, this means that 2-1 moves may now be legal where they were not legal before. - New static routine rehydrate() to rehydrate a new triangulation from a Callahan-Hildebrand-Weeks dehydration string. This is a more convenient version of insertRehydration(). - New routines isoSig() and fromIsoSig() for detecting and hashing combinatorial isomorphism classes of triangulations. - New routines isOriented() and orient() to relabel tetrahedron vertices for consistent orientation. Thanks to Matthias Goerner. - New routines isOrdered() and order() to relabel tetrahedron vertices so that they are ordered consistently across adjacent faces. Thanks again to Matthias Goerner. - New routines swapContents() and moveContentsTo() for moving tetrahedra between triangulations. - Fixed a memory leak in shellBoundary(). Class NTrieSet: - A new class for storing and querying a large number of sets, where the elements of these sets are taken from a small universe. The underlying data structure is essentially a trie of bitmasks. Class NVector: - Streamlined the vector hierarchy by merging NFastVector and NVectorDense into a single NVector class, and removing NVectorUnit and NVectorMatrix entirely. The result is that NVector is now cleaner and faster, but methods are no longer virtual. See the NVector class notes for full details of the changes. - Removed the old virtual clone() and makeLinComb() methods. Class NVectorDense: - Merged into the NVector class; see the NVector changes for details. Because typedefs cannot be templated, there is no legacy typedef; instead NFastVector has been removed completely. Class NVectorMatrix, NVectorUnit: - Removed. Use NVector instead. Class NVertexEmbedding: - New routine getVertices(), which facilitates a consistent orientation for the three remaining vertices in each tetrahedron. Class XMLPropertyDict: - The interface for this class is now much more restricted. The class now derives from std::map instead of stdhash::hash_map, and it allows access to only a few inherited members of std::map. Routine metricalSmithNormalForm(): - New alternative Smith normal form routine that is better for working with extremely large matrices. Thanks to Ryan Budney. Routine readIsoSigList(): - New routine that reads a text file filled with isomorphism signatures and returns a container filled with triangulations. Routine readSnapPea(): - Allows additional text on the first line following the "% Triangulation" marker (thanks to Matthias Goerner). Routine torsionAutInverse(): - New routine for inverting automorphisms, thanks to Ryan Budney. Routines writeCSVStandard(), writeCSVEdgeWeight(): - Changed the text that is written to the "boundary" field, to be consistent with changes to the user interface. Possible values are now "spun", "real" or "none". File surfaces/flavourregistry.h: - The final "pre_test" argument (which is never used) has been removed. As a result, REGISTER_FLAVOUR now takes five arguments, not six. USER INTERFACE: - Ported from KDE3 to KDE4. Finally! - The user interface has had a thorough overhaul, and includes many usability updates to help new users find their way around. Overall, the behaviour is generally cleaner and more sensible. A full list of changes is omitted for reasons of space and sanity. - There is now an option to enable or disable diagnostic messages from the SnapPea kernel. UTILITIES: tricensus, tricensus-mpi: - New option -s to output lists of isomorphism signatures instead of the much larger Regina data files. tricensus-mpi-status: - Now finishes with a running total of all triangulations found. - Compressed logs (using gzip or bzip2) are now supported. Requires the perl module IO::Uncompress::AnyUncompress. tricensus-manager: - Removed, since tricensus-mpi is a much better alternative. TEST SUITE: - Some slower but more detailed tests are now optional, and are disabled by default. To switch these tests on, set the environment variable REGINA_DETAILED_TESTS to any non-empty value. - New tests for file I/O using both modern XML and legacy binary file formats. - More detailed tests for bitmask operations. BUILD ENVIRONMENT: - Dropped support for ancient hacks like std::ios::no_create and the boost.python make_constructor hack. - Iconv is now mandatory, not optional. Version 4.6 [ 16 May, 2009 ] OVERALL: - Deprecated everything relating to the non-standard STL/g++ classes hash_set and hash_map, for the sake of portability. - Added a "deprecation guide" to the website, with a table listing the outdated routines/classes/etc. to be removed in Regina 5.0 and the corresponding new routines/classes/etc. that replace them. ENGINE: Class HashPointer, HashString: - Deprecated, along with everything else relating to the hash_set and hash_map classes. See the "overall" notes above. Class NBoundaryComponent, NComponent, NEdge, NFace, NVertex: - All constructors for skeletal objects are now private, since only the triangulation skeletal routines should be creating them. - Cleaned up some of the more obscure parts of the documentation. Class NCensus: - Removed findAllCompletions(), which (as the documentation points out) is an empty shell of a routine that has never been implemented and quite possibly never will. Class NDiscType: - New class for specifying a normal or almost normal disc type. Class NDoubleDescription, NDoubleDescriptor: - The old NDoubleDescriptor class has been renamed, and is now called NDoubleDescription. This is merely for consistency with documentation and papers; the functionality of the class has not changed. The old name (NDoubleDescriptor) is deprecated, but for the time being a typedef is provided for backward compatibility. Class NEdge: - Added new static arrays NEdge::edgeNumber and NEdge::edgeVertex to replace the old global arrays regina::edgeNumber, regina::edgeStart end regina::edgeEnd. The old global arrays are now deprecated (see below). - Added a new static array NEdge::ordering to replace the old global routine regina::edgeOrdering(). The old routine is now deprecated (see below). Class NFace: - Added a new static array NFace::ordering to replace the old global routine regina::faceOrdering(). The old routine is now deprecated (see below). Class NFacePairing: - Added a missing precondition to isCanonical(), which requires that the face pairing be connected. - Changed the output format of toString() to make it clearer which faces are boundary faces. Class NFastRay: - New fast but inflexible ray class; this builds on NFastVector in the same way that the slower NRay builds on NVector. Class NGluingPermSearcher, NCompactSearcher, NClosedPrimeMinSearcher: - Overhauled the census code so that some of the optimisations used in the closed minimal irreducible / P^2-irreducible census can be made available to more general censuses. In particular, the modified union-find for vertex and edge links is now available to any census that insists on compact (finite) 3-manifolds. For details of these optimisations, see "Enumeration of non-orientable 3-manifolds using face-pairing graphs and union-find", B. A. Burton, Discrete Comput. Geom. 38 (2007), no. 3, 527--571. Class NIndexedArray: - Deprecated, along with everything else relating to the hash_set and hash_map classes. For a replacement, try the NMarkedVector class, which is smaller and faster but requires modification of the data type being stored. Class NIsomorphism, NIsomorphismDirect, NIsomorphismIndexed: - NIsomorphism has been enhanced to add all of the functionality of the old NIsomorphismDirect class, so NIsomorphism is now a fully-fledged isomorphism class in its own right. - NIsomorhpismDirect has been deprecated, since this is now an empty subclass of NIsomorphism with no extra functionality. Programmers can change their code to use NIsomorphism instead. - NIsomorphismIndexed has been removed entirely. Python users will not be affected, since this class was never available to them. C++ programmers can now use NIsomorphism in conjunction with the NPerm::S4 array instead. Class NLargeInteger: - The old header utilities/nmpi.h is now deprecated. Please use the new header maths/nlargeinteger.h instead. Class NMatrix2: - The old header utilities/nmatrix2.h is now deprecated. Please use the new header maths/nmatrix2.h instead. Class NNormalSurface: - Finally implemented cutAlong()! - New routine isEmpty() for identifying empty surfaces. - New routine sameSurface() for comparing two normal surfaces. - New routines locallyCompatible() and disjoint() for testing intersections between normal surfaces. - New routine getOctPosition() for locating the non-zero octagonal coordinate in an almost normal surface. - New routine rawVector() that gives direct read-only access to the underlying vector in case this is needed. - Removed canCrush() and knownCanCrush(), which are both placeholders for routines that have never been implemented. The corresponding element has been removed from the data file format (though old files that happen to contain it will load without problems). - Added an optional argument to findVtxOctAlmostNormalSphere() that lets the user choose between working in standard and quadrilateral-octagon coordinates. Class NNormalSurfaceList: - Implemented quadrilateral-octagon coordinates for almost normal surfaces (the relevant flavour constant is AN_QUAD_OCT). See arXiv:0904.3041 for details. - Added routines quadToStandard(), standardToQuad(), quadOctToStandardAN() and standardANToQuadOct() to convert between different solution sets. See arXiv:0901.2629 for details of the underlying algorithms. - Changed enumerate() in standard coordinates so that, if possible, it enumerates in quadrilateral coordinates first and then converts between solution sets (see above). This typically runs orders of magnitude faster. Similarly for standard almost normal coordinates. - New routines enumerateStandardDirect() and enumerateStandardANDirect() to allow people to circumvent the above changes to enumerate() and instead use the old direct enumeration from Regina 4.5.1. - Almost normal surface enumeration no longer strips out surfaces with more than one octagonal *disc* (though it still avoids surfaces with more than one octagonal disc *type*). This change is necessary for conversion between quad-oct and standard almost normal space, and is also necessary if we wish to enumerate *all* almost normal surfaces (as opposed to just all *vertex* almost normal surfaces). - Added a new coordinate flavour AN_LEGACY to reflect almost normal surface lists created with Regina 4.5.1 or earlier, where surfaces with more than one octagon were stripped out (see above). Class NPerm: - New routines trunc2() and trunc3() to build a truncated version of a permutation string. - New arrays NPerm::S4, NPerm::invS4, NPerm::orderedS4, NPerm::S3, NPerm::invS3, NPerm::orderedS3, NPerm::S2 and NPerm::invS2. These replace the old (and now deprecated) arrays regina::allPermsS4, regina::allPermsS4Inv, regina::orderedPermsS4, and so on. - Deprecated the setPerm() routines; these are unnecessary because NPerm objects are very small and can just be copied around using the assignment operator. Class NPermItS4: - Deprecated, since all this class does is wrap a trivial loop. Just loop through the elements of NPerm::S4 directly. Class NPillowTwoSphere, NSnappedTwoSphere: - Removed reduceTriangulation() and getReducedTriangulation(), both of which are empty shells of routines that have never been implemented and quite possibly never will. Class NRational: - Added new routines getTeX() and writeTeX() for TeX-friendly output (thanks Ryan!). - The old header utilities/nrational.h is now deprecated. Please use the new header maths/nrational.h instead. Class NTetrahedron: - Renamed getAdjacentTetrahedron(), getAdjacentTetrahedronGluing() and getAdjacentFace() to adjacentTetrahedron(), adjacentGluing() and adjacentFace(), which should be easier on the fingers. The old names are still available for backward compatibility, but they are now deprecated and will be removed in Regina 5.0. - Proofreading and clarification for some of the older and more opaque parts of the documentation. Class NTriangulation: - New routines isBall() and knowsBall() for recognising the 3-dimensional ball. - New elementary move closeBook(). - Completely overhauled collapseEdge(). The eligiblity checks for this routine are now correct and not overly conservative, which makes this routine both useful and safe. The big warning is now gone from the collapseEdge() documentation as a result. - Routine simplifyToLocalMinimum() now collapses edges, which makes a big difference for multiple-vertex triangulations. - Routine intelligentSimplify() now uses book opening moves to create new opportunities for collapsing edges (which makes a big difference for bounded triangulations), and also uses book closing moves to reduce the number of boundary faces once nothing else can be done. - Routine isThreeSphere() now works in quadrilateral-octagon coordinates instead of standard almost normal coordinates. See arXiv:0904.3041 for details. - Removed crushMaximalForest(), which (as the documentation has pointed out since the first release) has never worked properly, and which is therefore never actually used. - Fixed crashes in twoOneMove(), twoZeroMove(NVertex*, ...) and shellBoundary(). These crashes were triggered by certain types of non-minimal triangulations with boundary. - Fixed a couple of nasty bugs in shellBoundary(), which had the potential to give incorrect results when simplifying triangulations with boundary. - Fixed bugs in several simplification routines when working with invalid triangulations; these sometimes "simplified" invalid edges to become valid edges. - New routine reorderTetrahedraBFS() for renumbering tetrahedra in a more sensible fashion. - Routines isZeroEfficient() and hasSplittingSurface() now operate on a clone of the triangulation, to avoid triggering changes to the packet tree. Routine edgeOrdering(), faceOrdering(): - Deprecated these routines, in favour of the new NEdge::ordering[] and NFace::ordering[] lookup tables. Routine edgeDescription(), faceDescription(): - Deprecated these routines, in favour of the new NPerm::trunc2() and NPerm::trunc3() routines. Routine writeResUsage(): - New helper routine to assist with diagnostics and measurements of performance. Global arrays allPermsS4, allPermsS4Inv, orderedPermsS4, allPermsS3, allPermsS3Inv, orderedPermsS3, allPermsS2, allPermsS2Inv: - All of these arrays are now deprecated. Please use the new arrays NPerm::S4, NPerm::invS4, NPerm::orderedS4, and so on. Global arrays edgeNumber, edgeStart, edgeEnd: - Deprecated; users are advised to switch to the new arrays NEdge::edgeNumber and NEdge::edgeVertex instead. Namespace stdhash: - Deprecated, along with everything else relating to the hash_set and hash_map classes. See the "overall" notes above. USER INTERFACE: - The elementary moves dialog now has additional "Close book" and "Collapse edge" options. - Items in the triangulation composition list can now be copied into the clipboard via the right mouse button. Amongst other things, this makes extracting the dehydration string much simpler. - In the triangulation viewer, the Surfaces panel now has a new "3-ball?" entry beneath the current "3-sphere?" entry. - The normal surface list viewer now has two additional tabs: one to summarise all surfaces in the list (which is now the default tab), and one to list pairwise compatibilities between surfaces. - The normal surface list viewer now has an additional "Cut Along" menu item. The shortcut letter for "Crush" has changed as well. - Warn the user before enumerating immersed and/or singular normal surfaces, in case the "embedded surfaces only" box was unchecked by accident. Moreover, refuse to enumerate immersed and/or singular *almost* normal surfaces, since this feature was designed for use with normal surfaces only. - The surface coordinate viewer now lists the location of the almost normal disc(s) alongside the other high-level surface properties. - Normal surfaces are now individually numbered within surface lists, which should make it easier to keep track of which is which. - Added "Troubleshooting" and "Handbook won't open?" entries to the Help menu, to make it easier to find solutions if things break. - The "Python Reference" entry in the Help menu should now work even when konqueror is not installed. - Fixed a bug whereby small triangulations occasionally became read-only after a user visited the Surfaces panel. - Added a scrollbar to the Cellular Info pane in case the window is small. TEST SUITE: - Added very thorough tests for NPerm. - Additional tests for triangulation simplification and Euler characteristic. - New tests for the recognition of families of standard triangulations and manifolds. - New tests that enumerate automorphisms of triangulations and test for subcomplexes. - Added exhaustive testing for 3-sphere and 3-ball recognition. - Added exhaustive testing for conversions between normal surface solution sets in different coordinate systems. BUILD ENVIRONMENT: - Installing into a staging area (i.e., building packages) now works fine even if older versions of the Regina development libraries are installed (this used to cause relinking problems on some systems). Version 4.5.1 [ 28 October, 2008 ] CENSUS: - Replaced the old plain-text Notation packets with detailed PDF packets in the closed orientable / non-orientable censuses. These new Notation packets explain the manifold names and parameters precisely, and include supporting diagrams. - Renamed some census manifolds to avoid arbitrary (a), (b) suffixes. In the 11-tetrahedron closed orientable census: Hyp_2.13401634 (Z_14) (a) -> Hyp_2.13401634 (Z_14, geod = 0.4606) Hyp_2.13401634 (Z_14) (b) -> Hyp_2.13401634 (Z_14, geod = 0.3684) (These have also been reordered in the overall list of manifolds.) In the 11-tetrahedron closed non-orientable census: SFS [M] U m003 (a) -> SFS [M] U m003 (Z + Z_5) SFS [M] U m003 (b) -> SFS [M] U m003 (Z + Z_10) These changes are only stop-gaps until hyperbolic manfiolds are dealt with properly (i.e., expect the names to change again). ENGINE: Class NBitmask, NBitmask1, NBitmask2, BitManipulator: - New classes for manipulating bitmasks. NBitmask is for bitmasks of arbitrary length, whereas NBitmask1 and NBitmask2 are optimised for situations where the length is known to be small. BitManipulator makes it easier to offer optimised template specialisations. Class NCompConstraint, NCompConstraintSet: - Removed. Compatibility constraints now refer to facets of the original cone, not coordinate positions (hence the rename, since the semantics have changed in a fundamental way). Individual compatibility constraints are now straight sets of integers, and the deque-based NCompConstraintSet has been replaced with the new vector-based class NEnumConstraintList. Class NDoubleDescriptor: - Streamlined the vertex enumeration routine, which is now much, much faster. See arXiv:0808.4050 for a full list of improvements. - The vertex enumeration routine now takes its arguments in a different form, and more importantly now insists that the original cone is in fact the non-negative orthant. To ensure that python/C++ users notice that things have changed, this routine has been renamed from enumerateVertices() to enumerateExtremalRays(). - Major overhaul of the documentation, which is now (hopefully) much clearer. Class NEnumConstraintList: - Added to replace the old NCompConstraintSet class. See the notes above on NCompConstraintSet for details. Class NFastVector: - New vector class that is less flexible than NVector but more streamlined, largely because it has no virtual functions. Class NGraphTriple: - Fixed a bug in writeTeXName() that listed incorrect entries for the first matrix. This does not affect any census data that has been published or shipped with earlier versions of Regina. Class NLargeInteger: - Fixed lcm() to do the right thing in the case of lcm(0,0). Class NMatrixInt: - New integer-specific routines divRowExact(), divColExact(), gcdRow(), gcdCol(), reduceRow() and reduceCol(). Class NMatrixField: - Removed this class, since it is never used and since it does not actively address the accuracy problems raised by real numbers. Class NNormalSurfaceVector: - Removed createNonNegativeCone() from subclasses (which is no longer required after the vertex enumeration overhaul), and added makeZeroVector() (which is now required). Class NPDF: - A new packet type that allows PDF documents to be stored directly as packets inside Regina data files. Routines base64Length(), isBase64(), base64Encode(), base64Decode(): - New routines for base64 encoding and decoding, taken and modified from the gnulib library. Routines createNonNegativeCone(), makeZeroVector(): - Removed global routine createNonNegativeCone() and replaced it with the new global makeZeroVector(), in line with the changes to NNormalSurfaceVector listed above. Routine gcd(): - Now takes longs instead of unsigned longs, and guarantees that the gcd returned will be non-negative. Routine lcm(): - Added to the collection of basic number theory routines. Routines readPDF(), writePDF(): - New routines for importing and exporting PDF packets to real PDF files. Routines rowBasis(), rowBasisAndOrthComp(): - Added to find the rank of an integer matrix and bases for its row space and orthogonal complement. USER INTERFACE: - PDF documents can now be embedded within data files as PDF packets. Added import, export and creation facilities, plus a PDF packet viewer that uses either an embedded KPart (such as kpdf or kghostview's embedded viewer) or an external application (such as xpdf or evince) according to the user's preferences. TEST SUITE: - Added new tests for normal surfaces that exploit generic properties of layered loops; these tests push to 50 tetrahedra, and can easily be extended further as surface enumeration becomes faster. - Added additional tests for normal surfaces and angle strutures that compare solutions coordinate by coordinate (instead of counting solutions and looking for large-scale properties). Version 4.5 [ 17 May, 2008 ] OVERALL: - Regina finally pays attention to character encodings: + All strings in the calculation engine are assumed to be UTF-8, except for filenames which should be in whatever local encoding the operating system expects. + Regina's XML data files store their data in UTF-8, as does the python configuration file ~/.regina-libs. + The various user interfaces ensure that the correct character encodings are always used, and translate between encodings where required. + Users who pass strings directly to the calculation engine (through the python or C++ interface) must ensure that their strings are either UTF-8 or just plain ASCII. - Builds under gcc 4.3. - Supports building out-of-tree (e.g., making separate builds in debug/ and release/ subdirectories). ENGINE: Class Locale, IConvBuffer, IConvStream: - New classes in the regina::i18n namespace for working with internationalisation and character encodings. Class NExampleTriangulation: - New routine seifertWeber() to build the Seifert-Weber dodecahedral space. Class NFileInfo: - Made the XML identification routines more robust, so that they work even if extra parameters (such as encoding or standalone declarations) are present in the XML prologue. Class NGlobalDirs: - New class for easy access to system installation directories for various components of Regina. Class NMarkedVector, NMarkedElement: - New class for a vector with fast reverse lookups. This is more memory efficient than NIndexedArray, but requires modifications to the data type being stored. Class NPacket, NPacketListener: - Fires packetWasRenamed() when packet tags are added or removed. Note that packet tags still cannot be accessed through the GUI except for via the python bindings. - Made the event handling code more robust; this fixes a couple of crashes in the GUI that occured when packets were deleted from the tree while they were still in use elsewhere. Class NTriangulation: - Streamlined the implementation, cutting ~ 1/3 of the memory usage and improving speed also. As a result: + Tetrahedra and skeletal components are now stored using NMarkedVector, not NIndexedArray. As a result the return types of getTetrahedra(), getVertices(), etc. have changed. + The old reverse lookup routines getTetrahedronIndex(), getVertexIndex(), etc. are now deprecated. The new routines tetrahedronIndex(), vertexIndex(), etc. are even faster, but have new preconditions requiring the given tetrahedron, vertex, etc. to belong to the triangulation. Class NXMLElementReader: - New routine usingParser() that passes the current parser to the top-level element reader. Class XMLParserCallback: - Callback routine start_document() now takes a single argument that points to the current XMLParser. Routine readXMLFile(), readFileMagic(): - Assumes that any Regina data files created by version 4.4 or earlier use a LATIN-1 encoding (which is what the old GUI used by default), and that any data files created by version 4.5 or later use UTF-8. Routine versionUsesUTF8(): - Added to assist code that works with files on a low-level basis. Routines writeCSVStandard(), writeCSVEdgeWeight(): - New routines for exporting normal surface lists to plain-text CSV files (which can then be imported into a spreadsheet or database). USER INTERFACE: - Normal surface lists can now be exported to plain-text CSV files (which can then be imported into a spreadsheet or database). - The default SnapPea filename filter is now *.tri instead of just *. - Several imports and exports (e.g., to/from python scripts and C++ source) now allow the user to select an explicit character encoding. - Added the Seifert-Weber dodecahedral space to the list of example triangulations that can be created. - When adding a new library in Regina's python settings, the file dialog now opens in the pylib/ directory where sample libraries are installed. - Application icons are now listed under hicolor instead of crystalsvg, which should make them easier for other desktop environments to find. PYTHON: - Use docstrings for the helper routines in pylib/, so documentation for these routines can be accessed from within python at runtime. - Added loadCensus.py as a new collection of optional helper routines in pylib/. These make it easy to load census data files from within python. UTILITIES: regfiledump, trisetcmp: - Now respects the default locale; any international characters in packet labels or packet contents are displayed using the correct character set (e.g., LATIN-1 for Western European users). Version 4.4 [ 25 November, 2007 ] - The "hug a Mac today" release. OVERALL: - Builds and runs happily on MacOS! Requires Fink to be installed. - Tidied up the directory hierarchy a little. The old engine/engine/ is now just engine/, and the old engine/doc-files/ is now engine/doxygen/. - Thanks to Ryan Budney for his many contributions to this release! CENSUS: - Expanded the closed non-orientable census to 11 tetrahedra. - Expanded the closed orientable census to 11 tetrahedra, and split it into three data files. The 9-tetrahedron and 10-tetrahedron files are shipped with Regina as before (as closed-or-census.rga and closed-or-census-large.rga); the 11-tetrahedron file is extremely large and must be downloaded separately from the Regina website. - Modified the closed orientable census files to use more consistent choices of monodromy matrices for torus bundles. - Clarified the matrix notation used with graph manifolds. ENGINE: Class NClosedPrimeMinSearcher: - Census generation is much faster for larger numbers of tetrahedra, due to new tests for high-genus vertex links. - Also made census generation more efficient by pruning on high-degree edges (as well as the usual low-degree edges). Class NDoubleDescriptor: - Now a standalone class, since the base NVertexEnumerator has been removed. - Made all member functions static. Objects of this class can no longer be created. Class NFacePairing: - Modified writeDot() to behave well with ancient versions of Graphviz. Class NHomologicalData: - New class for computing all sorts of detailed homological information for a manifold; thanks to Ryan Budney for this. Class NLargeInteger: - New routine divisionAlg() for using the division algorithm. - New routine legendre() for calculating Legendre symbols. Class NMatrix: - New == and != operators for element-by-element comparison. Class NMatrixInt: - Added a set() routine to the python interface for setting matrix elements (which was previously not possible in python). - Made matrix multiplication available in the python interface. - Added a python-only variant of initialise() that fills a matrix given a complete list of elements. Class NMatrixRing: - New routine det() for fast calculation of matrix determinants. - New convenience routine isIdentity(). - Changed the return type of operator * from a raw pointer to a std::auto_ptr, to make it easier to multiply matrices inside temporary expressions. - Added a new multiplyAs() template routine that multiplies but (unlike operator *) returns a subclass of NMatrixRing. Class NMarkedAbelianGroup, NHomMarkedAbelianGroup: - New classes for working with groups defined by chain complexes; thanks to Ryan Budney for these. Class NPacket: - New routine reparent() to simplify ownership issues when using Python scripting. Class NPerm: - Micro-optimised routines that are called extremely frequently, such as sign(). Class NPrimes: - New class that provides a more sophisticated infrastructure for prime factorisation than the old factorise() and primesUpTo() routines. Class NRational: - New routine abs() for calculating absolute value. - New routine doubleApprox() for converting to a real number. Struct NSatAnnulus: - New routine attachLST() to help with Seifert fibred spaces. Class NSFSpace: - Updated reduce() to make the best possible decisions on whether to reflect all fibres in cases where this is possible (previously it made faster decisions but occasionally missed some more subtle reductions). - Enhanced construct() to support the triangulation of all Seifert fibred spaces over the 2-sphere without punctures or reflector boundaries. Class NTetrahedron: - New routine orientation() for tracking orientation. Class NTorusBundle: - Greatly improved monodromy matrix reduction, to the point where equivalent torus bundles should give equal matrices. - Fixed a bug in the matrix reduction for non-symmetric matrices in non-orientable manifolds (sometimes the transpose matrix was obtained instead of the correct matrix). Class NTriangulation: - New routine layerOn() for performing layerings. - New routine dehydrate() for extracting Callahan-Hildebrand-Weeks dehydration strings. - Optimised the skeletal calculations, which now run *much* faster. - Renamed getEulerCharacteristic() to getEulerCharTri(), since for ideal triangulations this differs from the Euler characteristic of the corresponding compact manifold. The old name is kept as an alias but is now deprecated. - Added a new routine getEulerCharManifold(), which *does* calculate the Euler characteristic of the corresponding compact manifold. - Fixed a crash in splitIntoComponents() that occurred when the triangulation skeleton had not yet been calculated. Class NVertexEnumerator: - Removed. This abstract class existed to support multiple vertex enumeration algorithms, but in reality we're only using double descriptor anyway. The virtual template member functions caused problems with g++-4.2, which was the final push. NDoubleDescriptor is now a standalone class. Routine smithNormalForm(): - New five-argument version that not only calculates the Smith normal form but also returns appropriate change of basis matrices; thanks to Ryan Budney. Routines columnEchelonForm() and preImageOfLattice(): - New routines for working with matrices and homomorphisms; thanks again to Ryan Bydney. Routines factorise(), primesUpTo(): - Deprecated in favour of routines from the new NPrimes class. Routine clonePtr(): - New routine to assist copy constructors for classes that compute data on demand. USER INTERFACE: - New Algebra -> Cellular Info tab containing a variety of new homological data for triangulations; thanks to Ryan Budney. - Graphs now look better when drawn using an old Graphviz 1.x (previously the graphs were only tested under Graphviz 2.x). - Better infrastructure for determining the status of the current Graphviz installation. For version 1.x, Regina now insists on using dot, since the old neato 1.x cannot handle multiple edges. - Removed the Crush column from normal surface lists, since it has never contained any information beyond "N/A" or "Unknown". - The Regina reference manual is now called the Regina handbook, for consistency with other KDE applications. PYTHON: - The regina-python tool has new options -i/--interactive (run a script and leave the interpreter open) and -n/--nolibs (do not load any of the normal user libraries). UTILITIES: trisetcmp: - Now outputs more appropriate messages when subcomplex testing (previously the same messages were used for both subcomplex testing and isomorphism testing). TEST SUITE: - Added a new test suite for python bindings, in addition to the usual C++ test suite that is already present. - Added tests for the NPerm class. - Added tests for vertex link calculations. - Added tests for the orientable double cover of a triangulation. - Added tests for the new NPrimes class. - Added division algorithm tests for NLargeInteger. - Added tests for the new NHomologicalData class. - Added tests for triangulation dehydrations and rehydrations. - Initial work on tests for the NRational class. BUILD ENVIRONMENT: - Updated libtool from version 1.5a to 1.5.22 with Debian patches (required for MacOS support). Version 4.3.1 [ 5 May, 2006 ] ENGINE: Class NClosedPrimeMinSearcher: - Improved speed by adding additional face pairing graph tests; see math.GT/0604584 for details. - Made a very slight improvement in speed by testing for extremely high degree edges. - Fixed memory leak (the destructor was not deallocating some internal arrays). - Minor changes to the behaviour of mergeEdgeClasses() (might return only some flags instead of all flags). Class NFacePairing: - New constructor for building the face pairing of an existing triangulation. - New routines hasOneEndedChainWithStrayBigon() and hasTripleOneEndedChain() for testing for more types of graphs that cannot appear in a closed census. - New routines hasSingleStar(), hasDoubleStar() and hasDoubleSquare() for investigating larger face pairing graphs. - New routines writeDot() and writeDotHeader() to assist with graph visualisation. Routine readOrb(): - New routine for importing Orb / Casson triangulations; thanks to Ryan Budney for contributing this import filter. Routine readSnapPea(): - Verifies that the first line of the file is "% Triangulation", instead of simply testing for the '%' and ignoring the rest. USER INTERFACE: - Now displays face pairing graphs in the triangulation viewer, using Graphviz for the rendering (see the Skeleton tab). This required splitting the main Skeleton tab into two smaller child tabs. - New configuration options for the Graphviz executable and the default Skeleton child tab. - No longer crashes when attempting to clone the root packet (it simply displays an error message instead). - Added a workaround for the icon problems that arise when using GNU/Linux distributions with buggy icon themes. - Added 48x48 and 64x64 icons for Regina and its data files. TEST SUITE: - New tests for recognising bad and otherwise interesting subgraphs within face pairing graphs. Version 4.3 [ 27 March, 2006 ] OVERALL: - Expanded the closed non-orientable census to 10 tetrahedra. - Expanded the closed orientable census to 10 tetrahedra, and split it into two data files (large and small). - Updated postal address for the Free Software Foundation. - Bibliographic updates for the reference manual. - Fixed some harmless compiler warnings, and tightened syntax to adhere to the requirements of gcc 4.1. ENGINE: Class LessDeref: - New utility class for working with pointers in the Standard Template Library. Class NGluingPerms, NGluingPermSearcher, NClosedPrimeMinSearcher: - Significant overhaul. - Moved gluing permutation search routines into new classes NGluingPermSearcher and NClosedPrimeMinSearcher. - Supports partial depth-based searching (by passing a non-negative depth parameter to the new runSearch() routine). - Tracks both vertex and edge links using a modified union find structure to prune more braches of the search tree where possible. This makes an incredible difference to the census running time. Pruning takes place on non-orientable vertex links, too many or too few vertices or edges, low degree or invalid edges, conical faces, and L(3,1) spines. Class NGraphLoop, NGraphPair, NGraphTriple: - New families of graph manifolds. Class NKnot: - Removed this unwritten placeholder class. Class NLayering: - New class to help follow through layerings of tetrahedra within a triangulation. Class NLayeredSolidTorus: - New routine formsLayeredSolidTorusTop() for finding an LST from the top end instead of the bottom. - New routine transform() for following through an isomorphism. Class NLayeredTorusBundle, NTxICore, NTxIDiagonalCore, NTxIParallelCore: - Added for recognition of layered surface bundles. Class NListOnCall: - New class for expensive and rarely used hard-coded lists. Class NManifold: - Routine writeTeXName() no longer provides wrapping dollar signs. - New operator < for ordering manifolds deterministically. Class NMatrix2: - New specialised class for working with 2-by-2 integer matrices. Class NPacket, NPacketListener: - New NPacket routine sortChildren(). - Packet listeners are now unregistered immediately *before* packetToBeDestroyed() is called. This avoids unpleasantries when a listener tries to unregister itself during this call. Class NPerm: - The assignment operator now returns a reference instead of void. Class NSatAnnulus, NSatBlock, NSatRegion, NBlockedSFS, NBlockedSFSLoop, NBlockedSFSPair, NBlockedSFSTriple, NPluggedTorusBundle, plus subclasses and other support structures: - New classes for recognising and describing Seifert fibred spaces and other graph manifolds that are built using saturated blocks. Class NSFS, NExceptionalFibre: - Removed; see below. Class NSFSpace, NSFSFibre: - Complete overhaul of the Seifert fibred space classes. - Now more general, supporting both orientable and non-orientable 3-manifolds as well as base orbifolds with reflector boundary components. - Classes have been renamed from the old NSFS / NExceptionalFibre to make it clear that large-scale changes have taken place. Class NSFSAltSet: - New class for finding alternative simple representations of the same bounded Seifert fibred space. Class NSnapPeaTriangulation: - Added a boolean argument to the constructor that permits the SnapPea kernel to work with closed triangulations if the user really wants to allow it. Class NStandardTri: - Routine writeTeXName() no longer provides wrapping dollar signs. Class NTorusBundle: - New class of 3-manifolds describing torus bundles over the circle. Class NTriangulation: - Combined isomorphism and subcomplex testing routines into a single all-in-one routine to avoid excessive code reuse. - Added new subcomplex testing routine findAllSubcomplexesIn(), in which all matches (not just the first) are returned. - Routines getTetrahedronIndex(), getComponentIndex(), getBoundaryComponentIndex(), getFaceIndex(), getEdgeIndex() and getVertexIndex() now returned signed instead of unsigned longs, so that -1 can be returned if the object could not be found. USER INTERFACE: - Added a configuration option that allows the SnapPea kernel to work with closed triangulations. - Fixed the crash when deleting a triangulation that is currently the target of an isomorphism/subcomplex test. - Fixed a crash that sometimes occurs in large files when deleting a triangulation that is currently being viewed. - Fixed extremely slow updates in the triangulation composition tab for very large data files. - Text and script packets now open with the cursor at the top instead of the bottom. PYTHON: Class NSnapPeaTriangulation: - Offers the additional zero-argument routine volumeWithPrecision() as a way of returning the precision of the volume calculation. UTILITIES: tricensus-mpi: - Significant overhaul. - Now supports finer-grained subsearches via --depth. - Better logging. - Only writes .rga data files for cases in which at least one triangulation was found. - New option --dryrun for a quick overview of the search space. tricensus-mpi-status: - New tool for parsing tricensus-mpi logs. trisetcmp: - Support subcomplex testing as well as isomorphism testing. TEST SUITE: - Don't enforce precision limits for degenerate snappea volume testing, to allow for flexibility in floating point behaviours of different chipsets. - Added tests for NIsomorphism. Version 4.2.1 [ 18 September, 2005 ] OVERALL: - Added a chapter on imports and exports to the reference manual. - Expanded the closed non-orientable census to eight tetrahedra. ENGINE: Overall structure: - Fixed "regina-engine-config --cflags", which wrote includes for Regina's dependencies but not for Regina itself (sigh). Class NIsomorphism: - New routine random() for generating random isomorphisms. - New routine apply() for permuting the tetrahedra and vertices/faces of an existing triangulation. - New routine isIdentity() for testing for identity isomorphisms. Routine writeSnapPea(): - Add a precondition that the triangulation has no boundary faces. USER INTERFACE: - Refuse to export a triangulation to SnapPea format if it has boundary faces. UTILITIES: trisetcmp: - New utility for comparing two different sets of triangulations. Version 4.2 [ 7 July, 2005 ] ENGINE: Overall structure: - Included portions of the SnapPea kernel! Thanks again to Jeff Weeks for his support. - Added a regina-engine-config script to make it easier to build Regina's calculation engine into other applications. Class NExampleTriangulation: - Added to facilitate construction of several different ready-made sample triangulations. Class NFacePairing: - New routine hasWedgedDoubleEndedChain. Class NLayeredSolidTorus: - New routine isLayeredSolidTorus for classifying an entire triangulation component. Class NPacketListener: - Added an extra boolean argument to childWasRemoved() to indicate the situation in which the parent is also being destroyed. Class NSnapPeaCensusManifold, NSnapPeaCensusTri: - Added to aid recognition of very small SnapPea census triangulations. Class NSnapPeaTriangulation: - Added to give Regina triangulations access to the SnapPea kernel. Class NTriangulation: - New routine finiteToIdeal() for extending a triangulation. - New routines insertConstruction() and dumpConstruction() to make it easier to hard-code triangulations in source code. - Fixed vertex link calculations, which were previously incorrect if a triangulation contained invalid edges. - Fixed bug in twoZeroMove() which caused a crash in some cases involving triangulations with boundary. Class NTrivialTri: - Added recognition of one-tetrahedron balls. USER INTERFACE: - Include several example triangulations in the triangulation creation dialog. - Allow exporting a triangulation to C++ source. - Renamed "Ideal to Finite" as "Truncate Ideal Vertices" in the menu. - Include a padlock in the corner of a packet icon if the packet is uneditable. - Tighter thread safety in the GUI. This is required because some calculations (such as surface enumeration) run in a separate thread. - Worked around a Qt bug that caused a crash when pressing a key in a table of normal surfaces or matching equations. - Fixed a bug in which GAP output was unparseable due to GAP inserting spaces where Regina was not expecting them. UTILITIES: tricensus-mpi: - New census manager for use on MPI-enabled clusters. TEST SUITE: - Added tests for SnapPea calculations. - Further additions to the triangulation tests, in particular involving invalid and non-standard triangulations. - Beginning of a series of tests for elementary moves. BUILD ENVIRONMENT: - Updated libtool to version 1.5a. Hopefully this will make things better for Darwin/Fink. - Requires KDE >= 3.2, so that the XDG applications directory can be used for the desktop file. - Verifies in the configure script that shared libraries are enabled where necessary (i.e., in the KDE and Python interfaces). - Better magic in the configure script for finding the correct boost.python libraries. - Fixed a bug in the configure script whereby -g stripping was too agressive, resulting in a compile failure for the python interface under some environments. Version 4.1.3 [ 25 July, 2004 ] OVERALL: - Included the closed hyperbolic census of Hodgson and Weeks. - Made explicit in the reference manual introduction where the example files can be found. PYTHON: - For most objects, == now works like C++ pointer equality instead of Python object equality. That is, it tests whether the Python wrappers point to the same C++ object, not whether the Python wrappers are in fact the same wrapper. - Fixed scripting in the GUI, which was broken with python 2.3 (indented blocks were treated as complete after just one line). - Added a sample python session illustrating progress reporting. USER INTERFACE: - Added an "Open Example" menu item for easy access to the sample files. - Allow the choice of text editor component to be configured. - Several fixes to make Regina work properly with the vimpart, including work-arounds for bugs in the vimpart itself. - Fixed the massive resource drain while editing a script's variable table in a heavily populated data file. - Fixed crashes that occured when deleting packets while a drop-down packet chooser is in use elsewhere. - Tightened up the handling of read-only mode for internal components. Also removed some loopholes that allowed editing of uneditable packets. - Improved handling of keyboard focus. - Changed "Python Reference" to point to the modules index instead of the title page. Version 4.1.2 [ 14 June, 2004 ] OVERALL: - Updated configure scripts so that the python interface builds out of the box on a larger number of platforms (specifically Red Hat and Fedora Core are now supported). Many thanks to Craig Macintyre for his patience and assistance with this. - More updates to the troubleshooting section; overhauled the README.txt and website to hopefully make everything clearer and the important information easier to find. - Added a suggested form for citing Regina. - Updated INSTALL.txt to reflect current --prefix guessing. ENGINE: Class NTriangulation: - Added simplifiedFundamentalGroup() to allow external bodies such as GAP to simplify group presentations. USER INTERFACE: - Allow users to simplify fundamental groups using GAP. - Added "Education" to the categories for the desktop file, since KDE seems adamant about having no separate maths/science menu. Anything is better than showing up in Lost & Found. :) - Fixed compile error when building against an STL-enabled Qt (thanks to Robert Myers for spotting this one). Version 4.1.1 [ 24 April, 2004 ] USER INTERFACE: - Fixed compile error when building against Python 2.3. - Added "What's This?" button to main/packet window decorations. Version 4.1 [ 7 March, 2004 ] OVERALL: - Further enhancements to the reference manual, including more detailed explanations in the main body as well as a new index. ENGINE: Class NNormalSurface: - New routine doubleSurface(). - Added findNonTrivialSphere() and findVtxOctAlmostNormalSphere() to support 0-efficiency algorithms. Class NProgress: - Added timing utilities getRealTime() and totalCPUTime(). Class NTriangulation: - New 0-efficiency / decomposition routines splitIntoComponents(), connectedSumDecomposition(), isThreeSphere(), knowsThreeSphere() and makeZeroEfficient(). - New Seifert fibred space constructions insertAugTriSolidTorus() and insertSFSOverSphere(). USER INTERFACE: - Actions specific to each packet type now appear in their own context-specific menus, i.e., a "Triangulation" menu appears when a triangulation is open, etc. - Added "Please Wait" dialogs during slow operations. - Thorough "What's This?" support and tooltips offered across the entire user interface. - New tip-of-the-day support. - More icons for triangulation actions. - Updated the .desktop file and mimetype tests to work correctly with KDE 3.2. UTILITIES: tricensus: - Fixed bug in which --genpairs created empty output files. TEST SUITE: - Added tests for connected sum decomposition. Version 4.0.1 [ 26 January, 2004 ] OVERALL: - The ./configure script now takes a guess at the correct --prefix, runs sanity tests upon it and insists upon Qt >= 3.2. - Regina now ships with pregenerated manpages to avoid the need for docbook-utils and its complicated dependencies. - The troubleshooting section of the reference manual now includes compile-time problems and discusses the test suite. USER INTERFACE: Class GridListViewItem: - Added to centralise support for list views with grids. - Fixed a compile error with Qt versions 3.1 and earlier. Version 4.0 [ 20 December, 2003 ] ENGINE: Class NAngleStructureList: - Enumeration routine now takes an optional progress manager and can run in a separate thread. Class NGroupPresentation: - Improved simplification of group presentations. Class NNormalSurface: - Using NProperty to store calculable properties. - Using NTriBool instead of 1/-1/0 for orientability, two-sidedness and connectedness. Class NNormalSurfaceList: - Enumeration routine now takes an optional progress manager and can run in a separate thread. Class NProgress: - Removed isCancellable() since this is not really necessary; an operation may simply choose not to poll for cancellation requests. - Removed isChanged() and made the changed flag protected so subclasses can modify it directly. - Requires subclasses to adjust the changed flag on all public access/update routines. - Made cancel() const so that reading threads can use it. Class NProgressNumber: - New convenience routine incCompleted(). - New lookup routine getNumericState(). Class NTriBool: - Added for representing three-way booleans. Class NVectorMatrix, NVectorUnit: - Modification routines throw exceptions if called. USER INTERFACE: Class NAngleStructureCreator: - Displays progress and allows cancellation. Class NNormalSurfaceCreator: - Displays progress and allows cancellation. Class ProgressDialogNumeric: - Added for displaying progress using regina::NProgressNumber. Class PythonConsole: - Added Help menu for displaying scripting documentation. Class ReginaMain: - Added Python reference to Help menu. Class PythonManager: - New static routine openPythonReference() for displaying calculation engine documentation. TEST SUITE: - Added tests for angle structure enumeration and analysis. - Expanded normal surface tests to include trivial triangulations. - Added tests for fundamental group calculation and recognition. Version 3.97 [ 24 November, 2003 ] - Final prerelease for version 4.0. OVERALL: - Ships with the 7-tetrahedron closed non-orientable census. - Compile-time configuration uses different tests for pthread, since the old tests were broken on some systems. - Added a Python caveats section to the reference manual. ENGINE: Class NEdge, NVertex: - Added getDegree() as an alias for getNumberOfEmbeddings(). Class NGluingPerms: - Incorporate new results that allow us to discard more face pairings in a non-orientable census (see math.GT/0307382:v2). Class NLayeredSolidTorus: - Added routine flatten() to flatten a layered solid torus to a Mobius band. Class NMutex::MutexLock: - Added reference constructor as well as a pointer constructor. Class NNormalSurface, NNormalSurfaceVector: - Added routine isCentral() to test for central surfaces. Class NSimpleSurfaceBundle, NTrivialTri: - Added for recognition of trivial non-orientable triangulations. USER INTERFACE: Overall structure: - Split out common shell/part material into the separate library libregina-kdecommon. - Integrated python scripting into the graphical user interface. This is contained within libregina-kdecommon and is accessible through the main menu/toolbar and through the script editor. - Avoid using flat buttons where possible. Class ExportDialog: - New routine validate() to detect when there are no packets suitable for export. Class ExtTabCtl, PacketTabbedUI, PacketTabbedViewerTab: - Allow changing the current tab (this required a new extension class to KTabCtl). Class ImportDialog, NewPacketDialog: - New routine validate() to detect when there are no suitable parent packets. Class NNormalSurfaceCreator: - Allow the default coordinate system to be configured. Class NScriptUI, NTextUI: - Fixed problems with word wrapping and line endings in the embedded text editor. Class NTriangulationUI, NTriAlgebraUI: - Allow the initially visible tabs to be configured. Class NTriGluingsUI: - Implemented census lookup for triangulations. - Fixed a bug in the updating of tetrahedron labels when other tetrahedra are removed from a triangulation. Class PacketChooser: - New routine hasPackets() to detect empty packet choosers. Class ReginaPart: - Make File/Save fall back to File/Save-As for new files. - Make File/Save-As respect the automatic file extension setting and also check whether the selected file already exists. Class ReginaPreferences, ReginaPrefSet: - Many new configuration options. In addition to those mentioned above, census data files and Python options can also be configured. TEST SUITE: - Added tests for normal surface enumeration and analysis. Version 3.96 [ 31 October, 2003 ] - Second prerelease for version 4.0. OVERALL: - Added surface filter documentation to the reference manual, which brings it completely up to date with the GUI. ENGINE: Overall structure: - Yet more routines made const. Class NAbelianGroup: - Added global comparisons isTrivial() and operator ==. Class NMutex: - Now uses inner class MutexLock for locking and unlocking. Class NProperty, NPropertyBase, StoreValue, StoreConstPtr, StoreManagedPtr: - New classes for management of calculable object properties. Class NPropertyHolder: - Moved most of its functionality directly into NFile and replaced what was left with the new class NFilePropertyReader. Class NTriangulation: - Turaev-Viro invariants are now cached; this includes a new routine allCalculatedTuraevViro(). Class ShareableObject: - Now derives from regina::boost::noncopyable. USER INTERFACE: Class NTriAlgebraUI: - Redesigned the algebra viewer to make it easier to read. - Incorporatd Turaev-Viro invariants into the UI. Class NTriCompositionUI: - Incorporated isomorphism / subcomplex testing into the UI. - Fixed crash when refreshing. Class PacketTabbedViewerTab: - Added to support tabbed UIs within tabbed UIs. Class ReginaPart: - Make the main window splitter remember its place when packet panes are changed. TEST SUITE: - Added tests for trivial triangulations and property handling. Version 3.95 [ 12 October, 2003 ] - Prelease for version 4.0. GRAPHICAL USER INTERFACE: - Rewrote the entire user interface in C++ using the KDE libraries. The result is much faster, cleaner and easier to maintain. The old Java user interface is gone! The user interface can be started by running "regina-kde". PYTHON: - Python scripting rewritten to use standard Python, not Jython. A python session can be started by running "regina-python". - The Python API has changed to be much more faithful to the C++ calculation engine, especially with respect to global and static routines and constants. - All classes now sit directly within the module regina. ENGINE: Overall structure: - Fixed minor memory leaks. - Made more routines const. - Beginning to incorporate std::auto_ptr. Class Engine: - Removed since this is no longer necessary with the new python bindings. Class NAngleStructureList: - Made the enumerating constructor private and added the public replacement enumerate(). Class NAugTriSolidTorus: - Changed to fit into the new NStandardTriangulation structure. Class NFacePairings: - Fixed bug in isCanonical(). Class NGluingPerms: - Further optimisations for non-orientable census generation. Class NGroupPresentation: - Slightly improved group recognition. Class NHandlebody: - Added as a new 3-manifold class. Class NIsomorphism: - Allows an isomorphism with 0 tetrahedra. - Now derives from ShareableObject. - Supports boundary incomplete isomorphisms as well as complete isomorphisms. - Changed return types of const lookup routines from const T& to just T. Class NL31Pillow: - New class for identifying particular L(3,1) triangulations. Class NLargeInteger: - Added constructor and assignment taking a const std::string&. - Routine stringValue() now returns a std::string, not a char*. Class NLensSpace: - Changed to fit into the new NManifold structure. Class NLayeredChain: - Changed to fit into the new NStandardTriangulation structure. Class NLayeredLensSpace: - Changed to fit into the new NStandardTriangulation structure. Class NLayeredLoop: - Changed to fit into the new NStandardTriangulation structure. Class NLayeredSolidTorus: - Changed to fit into the new NStandardTriangulation structure. - Renamed isLayeredSolidTorusBase() to formsLayeredSolidTorusBase(). Class NManifold: - New class to represent a 3-manifold irrespective of its triangulation. Class NNormalSurfaceList: - Made the enumerating constructor private and added the public replacement enumerate(). Class NPacket, NPacketListener: - The NPacket destructor now orphans the packet if this has not already been done. - Added event listening for packets, including new class NPacketListener, new routines NPacket::listen(), NPacket::isListening() and NPacket::unlisten() and new class NPacket::ChangeEventBlock. - New NPacket routines moveUp(), moveDown(), moveToFirst() and moveToLast(). - Reclassified member variables from protected to private. Class NPerm: - Routines edgeDescription() and faceDescription() implemented in the calculation engine. Class NPlugTriSolidTorus: - Changed to fit into the new NStandardTriangulation structure. Class NSFS: - Changed to fit into the new NManifold structure. - New overloaded routine insertFibre(long, long). - No longer allows illegal (0,k) fibres to be added. - More common names recognised. Class NSnappedBall: - Changed to fit into the new NStandardTriangulation structure. - Renamed isSnappedBall() to formsSnappedBall(). Class NSpiralSolidTorus: - Changed to fit into the new NStandardTriangulation structure. - Renamed isSpiralSolidTorus() to formsSpiralSolidTorus(). Class NStandardTriangulation: - New class to represent a standard triangulation. Class NTriSolidTorus: - Changed to fit into the new NStandardTriangulation structure. - Renamed isTriSolidTorus() to formsTriSolidTorus(). Class NTriangulation: - New routine turaevViro() to calculate Turaev-Viro invariants. - Changed isIsomorphicTo() to return an entire isomorphism, not just whether an isomorphism exists. - New routine isContainedIn() to test for boundary incomplete isomorphisms. Routine isKnownSFS(): - Removed in favour of NStandardTriangulation::isStandardTriangulation(). File dehydration.h: - New routine readDehydrationList(). File nsnappea.h: - Renamed to snappea.h. File stringutils.h: - Added routines startsWith() and stripWhitespace(). Version 3.2 [ 22 June, 2003 ] - The post-thesis release! OVERALL: - Added file format documentation to reference manual. - Calculation engine test suite is much enhanced. - Closed orientable census, closed non-orientable census and splitting surface signature census added to example files. - PhD thesis submitted on 30 May, 2003! ENGINE: Overall structure: - Using C++-style casts instead of C-style casts. - Signedness of chars is explicitly specified where it matters. Class NBoolSet: - Using unsigned chars for byte codes. Class NCensus: - New constant PRUNE_P2_REDUCIBLE. Class NFacePair: - New class for working with pairs of face numbers. Class NFacePairing: - Added convenience operator []. - Added hasTripleEdge(), hasBrokenDoubleEndedChain(), hasOneEndedChainWithDoubleHandle() and associated routines. - Renamed private routine isCanonical() to isCanonicalInternal(), added public routine isCanonical() with no preconditions. Class NGluingPerms: - Uses new NFacePairing routines to identify certain situations in which no solutions are possible. - Uses a completely redesigned algorithm in the closed prime minimal P2-irreducible case. - Added pruning during permutation generation to eliminate edges identified with themselves in reverse. - Added pruning using low-degree edges in the non-orientable P2-irreducible case. - Allows a null automorphism list in findAllPerms(). Class NLayeredLoop: - Renamed getIndex() to getLength(). Class NLayeredSolidTorus: - Fixed a bug in isLayeredSolidTorusBase() that generated false positives in ideal triangulations. Class NNormalSurface: - Added routine knownCanCrush(). Currently this routine is next to useless; it is expected to be enhanced with future releases. - Property queries are now const since internal cached properties are declared mutable. Class NPerm: - Using unsigned chars for permutation codes. Class NPrismSpec, NPrismSetSurface: - New classes for dealing with triangular prisms defined by slicing along normal quads in a tetrahedron. Currently these classes do very little. Class NSFS: - Better recognition of common names; now recognises all spaces with finite fundamental group. Class NTetFace: - Added routine setFirst(). - Added copy constructor. - Operators ++ and -- are now implemented in all forms (++x, x++, --x, x--) and all have return values. Class NTriangulation: - New routine insertLayeredLoop(). - 0-efficiency testing is done in quad space where possible. - Fixed a bug in which getHomologyH1Bdry() gave incorrect answers if the skeleton had not already been calculated. - New boundary queries hasTwoSphereBoundaryComponents() and hasNegativeIdealBoundaryComponents(). - Renamed insertLensSpace() to insertLayeredLensSpace(). - Interface-only skeletal query routines are now also implemented in the C++ calculation engine. Routine prior(), next(): - Copied from the Boost C++ libraries for easy access to prior and following iterators. JAVA USER INTERFACE: Overall structure: - Incorporated engine enhancements listed above. UTILITIES: regconcat: - New utility for combining several data files. tricensus: - New option --minprimep2 for P2-irreducibility. - Explicitly verifies that all face pairings supplied on standard input are in canonical form. Version 3.1 [ 18 October, 2002 ] OVERALL: - Added calculation engine test suite. - Environment variables now take precedence over configuration files when running the startup script. - Build process now uses standard autoconf/automake structure. ENGINE: Overall structure: - Added support for multiple vertex enumeration engines. Class NCensus: - Redesigned to do its work through classes NFacePairing and NGluingPerms. - Added support for arbitrary criterion functions. - Added support for splitting a census into pieces. Class NCompConstraint, NCompConstraintSet: - Added. Class NConeRay: - Removed in favour of new class NRay. Class NFacePairing, NGluingPerms: - Added to bear the brunt of census generation. - Massive optimisations and rewrites throughout census code. - Removed all thread yields, which were causing processes to have 0.0% CPU time on some systems. Class NIndexedArray: - Added routine validate(). Class NKnot: - New (but incomplete) knot/link class. Class NLensSpace, NSFS: - Added getCommonName(). Class NNormalSurfaceVector: - Replaced isCompatibleWith() with makeEmbeddedConstraints(). Class NPerm: - Routine isIdentity() now implemented in C++ engine. - New routine setPerm(int, int). Class NTriangulation: - Fixed idealToFinite() which was newly broken in Regina 3.0. - Routine intelligentSimplify() now tries random 4-4 moves. - New routine collapseEdge(). - Routine simplifyToLocalMinimum() now make boundary moves last and does not do book opening at all. - Fixed bug in 2-3, 3-2 and 4-4 moves that appears when faces of the old tetrahedra are glued to each other. Class NRay: - Added to replace old class NConeRay. Class NVector: - Added negate(). Class NVertexEnumerator, NDoubleDescriptor: - Added to bear the brunt of normal surface enumeration and to allow different enumeration engines to be plugged in. - Caches some frequent calculations, resulting in a startling performance increase. Routine getVersionString(), getVersionMajor(), getVersionMinor(), testEngine(): - Moved to engine.h and added to the C++ calculation engine. Routine reducedMod(): - Fixed bug in the midpoint case. File nfile.h: - New file format constants to replace the constants removed with regina.h. File nhashmap.h, nhashset.h: - Added to deal with differing STL extension installations. File nknownmanifold.h: - Added global 3-manifold recognition routines. File nperm.h: - New arrays allPermsS2Inv, allPermsS3Inv, allPermsS4Inv. File regina.h: - Removed along with the constants it defined. JAVA USER INTERFACE: normal.algorithm.Algorithm: - Fixed bug in which isPacketEditable() was enforced even for non-modifying algorithms. normal.console.JPythonPacketConsole: - Optionally creates an additional Jython variable for direct access to some preselected packet within the tree. normal.mainui.NormalFrame: - New Jython consoles create an additional variable for the packet currently selected in the visual tree. normal.packetui.surfaces.NSFPropertiesEditor: - Don't enforce Euler characteristic <= 2 (singular surfaces can give other values). UTILITIES: tricensus: - Completely redesigned interface (now command-line based). - Supports splitting a census into pieces. tricensus-manager: - New utility for distributing a census amongst several machines. Version 3.0 [ 28 June, 2002 ] - The "XML, about bloody time" release. OVERALL: - Moved from old impenetrable binary data files to new compressed XML data files. - Introduced various command-line utilities (see UTILITIES below). - Removed CORBA engine/interface. It was too much hassle to maintain, and with Regina building on more platforms it has lots much of its usefulness. - JNI engine no longer requires autogenerated JNI headers. - Reference manual much enhanced. ENGINE: Overall structure: - Moved entire calculation engine into namespace regina. - The Great STL Port: replaced hand-rolled container classes with Standard Template Library classes. - Added numerous XML-related routines and classes. - Modified to also build under gcc3. - Removed configuration macro __MUTE_WARNINGS. - Replaced configuration macros __NO_IOS_NOCREATE and __NO_RAW_CASTING with their negations __USE_IOS_NOCREATE and __USE_RAW_CASTING which are optional in all situations. - Added configuration macros __HASH_NAMESPACE and __NO_NAMESPACE_ALIASES. Class NBoolVector, NDoubleList, NDynamicArray, NHashSet, NInfiniteArray, NIntMap, NOrderedPair, NPointerSet, NQueue, NSet, NStack, NString, NStringPair and associates: - All removed in favour of Standard Template Library classes. Class NAngleStructureList, NNormalSurfaceList: - New nested classes StructureInserter / SurfaceInserter. Class NAugTriSolidTorus, NTriSolidTorus: - Supports multiple ways of attaching layered chains. Class NFileInfo: - Added. Class NGroupExpressionTerm: - Changed from simple ordered pair to its own full class. Class NIndexedArray: - Added. Class NJNIEnumeration: - Added to aid the Java-C++ link. Class NLargeInteger: - Added third error-detection parameter to constructor NLargeInteger(const char*, int). Class NLayeredChainPair, NPlugTriSolidTorus: - Added for further subcomplex recognition. Class NLayeredLoop: - Added routine getSeifertStructure(). Class NLensSpace: - Fixed bug causing reductions to be sometimes non-optimal (although still correct) - see modularInverse() notes below. Class NLocalFileResource: - Replaced static members MODE_READ, MODE_WRITE with static routines sysModeRead(), sysModeWrite(). Class NNormalSurface: - Added routines isVertexLink() and isThinEdgeLink(). Class NPacket: - Added routines to support arbitrary packet tags. - Finally changed getPacketName() to getPacketTypeName(). - Removed tidyReadPacket(). Class NPerm: - Added isPermCode(). Class NScript: - Changed list of variables to a proper map and removed routines getVariableIndex() and removeVariableAt(). - Insistance on unique variable names; in enforcing this routine addVariable() now returns bool. Class NSFS: - Added routine getHomologyH1(). Class NSignature, NSigCensus, NSigPartialIsomorphism: - Added to deal with splitting surface signatures. Class NTriangulation: - Uses NIndexedArrays for skeletal elements for fast index lookup. File boostutils.h: - Added utility classes from the Boost C++ libraries. File hashutils.h: - Added various hash functions. File memutils.h: - Added allocation/deallocation functions. File stlutils.h: - Added extension Standard Template Library utility classes. File stringutils.h: - Added miscellaneous string manipulation routines. File zstream.h: - Added compressing and decompressing I/O streams. Routine modularInverse(): - Fixed a rather nasty bug in gcdWithCoeffsInternal() that caused modularInverse() to sometimes give wrong answers. Routine readFileMagic(): - Added to provide a format-independent file reader. JAVA USER INTERFACE: Overall structure: - Incorporated engine enhancements listed above. normal.console: - Added class JPythonPacketConsole. normal.engine.implementation.jni.JNIShareableObject: - Added static method sameCppPtr() which is necessary with gcc3. normal.exports: - Now exports to three different Regina data file formats. normal.mainui: - File information dialog is somewhat more informative. normal.mainui.NormalFrame: - Now supports opening a Jython console linked to a packet tree. normal.mainui.PacketPane: - Renamed getUI() to getPacketUI() to avoid clashing with j2sdk1.4. normal.options.NormalOptionSet: - Default "Display Icon" option changed from true to false. normal.packetui: - Resizing one coordinate column in various coordinate viewers now resizes all coordinate columns. UTILITIES: regconvert, regfiledump, regfiletype, sigcensus, tricensus: - Added. Version 2.4 [ 4 April, 2002 ] OVERALL: - Much enhanced documentation. - Added SnapPea census and knot/link census to examples. - Added functionality changelog (HIGHLIGHTS.txt). - Added prepackaged Jython library directory. ENGINE: Overall structure: - Moved engine/imports to engine/foreign. Class NAngleStructure, NAngleStructureList, NAngleStructureVector: - Added. Class NConeRay: - Now a new class of its own accord, derived from NVectorDense and created to allow vertex solution routines to work in contexts outside normal surfaces. Class NNormalSurface: - Added getName() and setName(). Class NNormalSurfaceVector: - Now derives from NConeRay, to which some routines have moved. - Changed declaration of createNonNegativeCone() to return cone faces as well as extremal rays. Class NPerm: - Added toString(). Class NTriangulation: - Uses fewest possible tetrahedra in insertLensSpace(). - Added insertRehydration(), makeDoubleCover(). File nperm.h: - Added constant arrays orderedPermsS4, orderedPermsS3. Routine intersectCone(): - Works with more generic cones by requiring cone faces to be passed as well as extremal rays. Routine writeSnapPea(): - Added. JAVA USER INTERFACE: Overall structure: - Added readline/editline support using Bablok's wrapper classes. - Converted option REGINA_JNIDIR to a list of directories. - Option REGINA_OPTIONS_GLOBAL defaults to REGINA_HOME if /etc/regina does not exist. normal.ApplicationShell.CommandLineArguments: - Added. normal.Shell: - Allow filenames to be specified on the command-line. - Removed some arguments from getParameter(). - Added getFileParameters(). normal.exports: - Added class SnapPeaExporter. normal.imports: - Added class DehydrationImporter. normal.mainui: - Added more keyboard accelerators. normal.mainui.FilePane: - Added getFileType() and setFileType(). normal.mainui.NormalFrame: - Added File->Info menu item. - Made various routines public so outsiders can manipulate the primary frame. normal.packetui.surfaces.CoordinateViewer: - Inserted editable surface name as first column. normal.packetui.triangulation.TriangulationCreator: - Creates triangulations from dehydration strings. Version 2.3 [ 12 December, 2001 ] - The "Farewell Stillwater" release. OVERALL: - Makefile.options variables IDLTOJAVACLIENT and IDLTOCPPSERVER became IDLTOJAVA and IDLTOCPP with slightly more generic meanings. ENGINE: Overall structure: - Modified #includes to treat engine/engine, engine/jni and engine/corba as top-level include directories. - Removed config.h in favour of PD_MACROS in Makefile.options. - Removed configuration macros __NO_INCLUDE_PATHS and __BINARY_IO. - Introduced macro MY_ENGINE_OBJECT for CORBA wrapper classes. - Macros GET_ENGINE_OBJECT no longer crash when null is passed. Class NAugTriSolidTorus, NLayeredChain, NLayeredLoop, NLensSpace, NSFS, NSpiralSolidTorus, NTriSolidTorus: - New classes. Class NDiscSetSurface: - Modified parameters for adjacentDisc(). Class NFace: - Added getType(), getSubtype(), isMobiusBand(), isCone(). Class NHashSet, NHashSetIterator: - New classes. Class NNormalSurface: - Added crush(). - Added isConnected(), isVertexLink(), isSplitting(). - Fixed isOrientable() and added isTwoSided(). Class NPacket: - Added makeUniqueLabels(). Class NPerm: - Added operators = and != and constructor NPerm(const NPerm&). Class NTriangulation: - Added isZeroEfficient(), hasSplittingSurface(), knowsZeroEfficient() and knowsSplittingSurface(). - Added extra condition to shellBoundary() covering two boundary faces plus two identified faces. - Added extra condition to twoZeroMove(NEdge*, ...) covering two boundary faces plus two identified faces. - Added fourFourMove(). File ndisc.h: - Added routine discOrientationFollowsEdge(). File nnormalsurface.h: - Added arrays triDiscArcs, quadDiscArcs, octDiscArcs. Routine hashMap(T*), hashMap(NString): - Added to support new class NHashSet. Routine readSnapPea(): - Sets the new packet label to the SnapPea manifold name. JAVA USER INTERFACE: Overall structure: - Loading/saving local files is now possible even through CORBA! - Incorporated engine enhancements listed above. - Added Jython operator overloads to a number of classes. normal.engine.utilities: - Added NLargeInteger to replace java.math.BigInteger so Jython scripts can use native mathematical operators with arbitrary precision integers. normal.exports: - Created architecture for exporting to foreign file formats. - Added classes Exporter, ReginaExporter, ScriptExporter. normal.images: - A couple of new icons. normal.imports: - Redesigned import architecture; replaced old class ImportFilePane with new class Importer. - Imported packets now have appropriate packet labels (such as their names in the imported files). - The file dialog is now brought up before anything else is done. - Added classes ReginaImporter, ScriptImporter. normal.mainui.TopologyPane: - Fixed bug where icon was sometimes not displayed. normal.packetui: - Added a new TopologyPane argument to some routines to allow interfaces to manipulate the visual packet tree. normal.packetui.triangulation.CompositionViewer: - Displays more detailed information. normal.packetui.triangulation.SkeletonTableFrame: - Displays more details regarding face/vertex type. Version 2.2 [ 7 October, 2001 ] OVERALL: - Documentation now DocBook-based; generates HTML and man pages. - Documentation now in docs/, not docs/normal/docs/. - Builds and runs under windows! - Added support for both global and local configuration files; configuration files are now called regina.conf. - Vastly reworked runtime scripts. - Tidied up Makefiles and CVS. ENGINE: Overall structure: - Ported CORBA stuff to omniORB3. Class NDoubleList, NDynamicArray: - Added operator = to the iterator classes. Class NEdge, NFace: - Added extra skeletal query routines. Class NGroupExpression, NGroupPresentation: - New classes. Class NLayeredLensSpace, NLayeredSolidTorus, NPillowTwoSphere, NSnappedBall, NSnappedTwoSphere: - New classes. Class NPacket: - Changed meaning of second (boolean) parameter to clone(). - Added getNumberOfDescendants() and getNumberOfChildren(); renamed totalTreeSize() to getTotalTreeSize(). Class NTriangulation: - Added fundamental group as a new property. - Added a two-zero move about a vertex. File numbertheory.h: - Added modularInverse(). JAVA USER INTERFACE: Overall structure: - Reads Regina options from directory $REGINA_OPTIONS_LOCAL and reads runtime options from system properties (which should be set by startup scripts). - Ported from JPython 1.1 to Jython 2.1-alpha1. - Now supports custom Jython libraries. - Improved support for mnemonics and keyboard accelerators. - Fixed tooltips in tables. normal.Application: - Moved fileExtension member into normal.mainui.FilePane subclasses. normal.Shell: - Dynamically finds JavaHelp classes so JavaHelp is not necessary for compilation. - Cleanly handles missing runtime options file. - Added a registry of all open Jython consoles. normal.algorithm: - Added class ElementaryMove. normal.console: - Major rearrangements; new class JPythonUtils now does most of the Jython work. normal.console.JPythonConsoleFrame: - Stores the root of the associated packet tree. - Allows saving the contents of the console to a file. normal.engine.implementation.corba.CORBAEngine: - Better error handling. normal.mainui: - Renamed SystemPane to TopologyPane and moved generic file editing functionality into FilePane to allow for editing different file types. - Much all-round cleaning up. normal.mainui.LibraryPane: - New class; allows editing of Jython libraries. normal.mainui.NormalFrame: - Moved console ownership routines into normal.Shell. - More appropriate enabling/disabling of menu items and buttons. - Edit menu hooks into current working file. normal.mainui.TopologyPane: - Closing a file closes all associated consoles. - Fixed the bug where double clicking on a tree item opens it three times. - Fixed bugs in the various fire... routines. - Improved interaction with the packet rename dialog. - Fixed the packet renaming bug in the visual tree display. normal.mainui.PacketTreeNode: - Replaced insertUnwrappedDescendants() with verifyDescendants() which actually does what it should; thus the refresh button now works properly. - Added findChildNodeIndex(). normal.packetui.PacketUI: - Added subtreeWasDeleted(). normal.packetui.packet.NContainerViewer: - Displays tree size statistics. normal.packetui.surfaces: - Coordinate tables in edge weight space now flag boundary edges. normal.packetui.surfaces.Coordinates: - Some routines now require the triangulation to be passed. normal.packetui.triangulation: - Pulled SkeletonTableFrame out into its own standalone class and turned it into a dialog. normal.packetui.triangulation.NTriangulationEditor: - Added triangulation component recognition. Version 2.1.1a [ 8 March, 2001 ] OVERALL: - Set up system for creating distributions. - Final tidying up for proper release. Version 2.1.1 OVERALL: - Added a CORBA interface to the engine. - Rearranged Makefiles and directory structure for CVS and SourceForge. ENGINE: Overall structure: - Split config.h into config.h and regina.h. Class Engine: - Formalised and slightly rearranged. - Added getVersion...() routines. Class NBoolSet: - Now passed as characters to and from external interfaces. Added getByteCode(), setByteCode() and fromByteCode() for this purpose. Class NNormalSurfaceList: - Added coordinate system FACE_ARCS; renumbered EDGE_WEIGHT. Class NPerm: - Now passed as characters to and from external interfaces. Class NTriangulation: - Added routine isStandard(). JAVA USER INTERFACE: Overall structure: - Allows running as an applet as well as an application. - Class normal.Application now contains just global constants and a generic applet/application shell. Class normal.Shell contains top-level Regina runtime routines and routines specific to the shell type (applet or application). - Made miscellaneous optimisations. normal.packetui.census.NCensusCreator: - Altered the boundary combo box strings to avoid misinterpretation. normal.packetui.surfaces.NSurfaceFilterEditor: - Fixed the bug in which changes in the filter were not always being immediately reflected in the surface list. Version 2.1.0 [ 18 December, 2000 ] (Initial public release.) Ben Burton (bab@debian.org) http://regina.sourceforge.net/ regina-4.96/cmake/modules/FindGMP.cmake000644 000765 000024 00000001507 12234011536 017566 0ustar00babstaff000000 000000 # Taken from the KDE4 cmake modules directory. - Ben Burton, 22 August 2011. # Try to find the GMP librairies # GMP_FOUND - system has GMP lib # GMP_INCLUDE_DIR - the GMP include directory # GMP_LIBRARIES - Libraries needed to use GMP # Copyright (c) 2006, Laurent Montel, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. if (GMP_INCLUDE_DIR AND GMP_LIBRARIES) # Already in cache, be silent set(GMP_FIND_QUIETLY TRUE) endif (GMP_INCLUDE_DIR AND GMP_LIBRARIES) find_path(GMP_INCLUDE_DIR NAMES gmp.h ) find_library(GMP_LIBRARIES NAMES gmp libgmp) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(GMP DEFAULT_MSG GMP_INCLUDE_DIR GMP_LIBRARIES) mark_as_advanced(GMP_INCLUDE_DIR GMP_LIBRARIES) regina-4.96/cmake/modules/FindGMPXX.cmake000644 000765 000024 00000001605 12234011536 020045 0ustar00babstaff000000 000000 # Modified from FindGMP.cmake. - Ben Burton, 11 November 2011. # Try to find the GMPXX librairies # GMPXX_FOUND - system has GMPXX lib # GMPXX_INCLUDE_DIR - the GMPXX include directory # GMPXX_LIBRARIES - Libraries needed to use GMPXX # The original FindGMP.cmake is copyright (c) 2006, Laurent Montel, # # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. if (GMPXX_INCLUDE_DIR AND GMPXX_LIBRARIES) # Already in cache, be silent set(GMPXX_FIND_QUIETLY TRUE) endif (GMPXX_INCLUDE_DIR AND GMPXX_LIBRARIES) find_path(GMPXX_INCLUDE_DIR NAMES gmpxx.h ) find_library(GMPXX_LIBRARIES NAMES gmpxx libgmpxx) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(GMPXX DEFAULT_MSG GMPXX_INCLUDE_DIR GMPXX_LIBRARIES) mark_as_advanced(GMPXX_INCLUDE_DIR GMPXX_LIBRARIES) regina-4.96/cmake/modules/FindICONV.cmake000644 000765 000024 00000004514 12311266525 020030 0ustar00babstaff000000 000000 # Copyright (c) William Pettersson, 2011 # Licensed under the GNU General Public License, version 2 or later # # As an exception, when this program is distributed through (i) the # App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or # (iii) Google Play by Google Inc., then that store may impose any # digital rights management, device limits and/or redistribution # restrictions that are required by its terms of service. include (CheckFunctionExists) include (CheckCXXSourceCompiles) IF (APPLE) # Both /usr/include/iconv.h and /sw/include/iconv.h are highly likely # to turn up on the compile-time search path if we have fink installed. # # It is very difficult to push /usr/include to the front of the search path # when compiling, which raises the risk of compiling with /sw/include/iconv.h # but linking against /usr/lib/libiconv.dylib (which is incompatible). # # Our solution: make sure we use the iconv in /sw if it exists. FIND_PATH(ICONV_INCLUDE_DIR NAMES iconv.h PATHS /sw/include NO_DEFAULT_PATH) IF (NOT ICONV_INCLUDE_DIR) FIND_PATH(ICONV_INCLUDE_DIR NAMES iconv.h) ENDIF (NOT ICONV_INCLUDE_DIR) FIND_LIBRARY(ICONV_LIBRARY NAMES iconv libiconv PATHS /sw/lib NO_DEFAULT_PATH) IF (NOT ICONV_LIBRARY) FIND_LIBRARY(ICONV_LIBRARY NAMES iconv libiconv) ENDIF (NOT ICONV_LIBRARY) ELSE (APPLE) FIND_PATH(ICONV_INCLUDE_DIR NAMES iconv.h) FIND_LIBRARY(ICONV_LIBRARY NAMES iconv libiconv) ENDIF (APPLE) IF(NOT ICONV_LIBRARY) CHECK_FUNCTION_EXISTS (iconv ICONV_FOUND) ENDIF(NOT ICONV_LIBRARY) IF(ICONV_INCLUDE_DIR AND ICONV_LIBRARY) SET(ICONV_FOUND TRUE) ENDIF(ICONV_INCLUDE_DIR AND ICONV_LIBRARY) IF(ICONV_FOUND) IF (NOT ICONV_FIND_QUIETLY) MESSAGE(STATUS "Found iconv: ${ICONV_INCLUDE_DIR}") ENDIF (NOT ICONV_FIND_QUIETLY) IF (NOT ICONV_LIBRARY) SET (ICONV_LIBRARY "") ENDIF (NOT ICONV_LIBRARY) check_cxx_source_compiles(" #include extern \"C\" size_t iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft); int main(){return 0;} " ICONV_CONST) if(ICONV_CONST) message(STATUS "Setting const") set(ICONV_CONST "const") mark_as_advanced(ICONV_CONST) endif(ICONV_CONST) ELSE (ICONV_FOUND) IF (ICONV_FIND_REQUIRED) MESSAGE(FATAL_ERROR "Could not find iconv") ENDIF (ICONV_FIND_REQUIRED) ENDIF(ICONV_FOUND) regina-4.96/cmake/modules/FindPOPT.cmake000644 000765 000024 00000001670 12311266525 017734 0ustar00babstaff000000 000000 # Copyright (c) William Pettersson, 2011 # Licensed under the GNU General Public License, version 2 or later # # As an exception, when this program is distributed through (i) the # App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or # (iii) Google Play by Google Inc., then that store may impose any # digital rights management, device limits and/or redistribution # restrictions that are required by its terms of service. find_path(POPT_INCLUDE_DIR popt.h PATHS /usr/include /usr/local/lib) find_library(POPT_LIBRARY popt PATHS /usr/lib /usr/local/lib) IF(POPT_INCLUDE_DIR AND POPT_LIBRARY) SET(POPT_FOUND TRUE) ENDIF(POPT_INCLUDE_DIR AND POPT_LIBRARY) IF(POPT_FOUND) IF (NOT POPT_FIND_QUIETLY) MESSAGE(STATUS "Found popt: ${POPT_LIBRARY}") ENDIF (NOT POPT_FIND_QUIETLY) ELSE (POPT_FOUND) IF (POPT_FIND_REQUIRED) MESSAGE(FATAL_ERROR "Could not find the popt library.") ENDIF (POPT_FIND_REQUIRED) ENDIF(POPT_FOUND) regina-4.96/cmake/modules/FindSharedMimeInfo.cmake000644 000765 000024 00000005735 12234011536 022004 0ustar00babstaff000000 000000 # Taken from the KDE4 cmake modules directory. - Ben Burton, 11 February 2012. # - Try to find the shared-mime-info package # # SHARED_MIME_INFO_MINIMUM_VERSION - Set this to the minimum version you need, default is 0.18 # # Once done this will define # # SHARED_MIME_INFO_FOUND - system has the shared-mime-info package # UPDATE_MIME_DATABASE_EXECUTABLE - the update-mime-database executable # Copyright (c) 2007, Pino Toscano, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # the minimum version of shared-mime-database we require if (NOT SHARED_MIME_INFO_MINIMUM_VERSION) set(SHARED_MIME_INFO_MINIMUM_VERSION "0.18") endif (NOT SHARED_MIME_INFO_MINIMUM_VERSION) if (UPDATE_MIME_DATABASE_EXECUTABLE) # in cache already set(SHARED_MIME_INFO_FOUND TRUE) else (UPDATE_MIME_DATABASE_EXECUTABLE) include (MacroEnsureVersion) find_program (UPDATE_MIME_DATABASE_EXECUTABLE NAMES update-mime-database) if (UPDATE_MIME_DATABASE_EXECUTABLE) exec_program (${UPDATE_MIME_DATABASE_EXECUTABLE} ARGS -v RETURN_VALUE _null OUTPUT_VARIABLE _smiVersionRaw) string(REGEX REPLACE "update-mime-database \\([a-zA-Z\\-]+\\) ([0-9]\\.[0-9]+).*" "\\1" smiVersion "${_smiVersionRaw}") set (SHARED_MIME_INFO_FOUND TRUE) endif (UPDATE_MIME_DATABASE_EXECUTABLE) if (SHARED_MIME_INFO_FOUND) if (NOT SharedMimeInfo_FIND_QUIETLY) message(STATUS "Found shared-mime-info version: ${smiVersion}") macro_ensure_version(${SHARED_MIME_INFO_MINIMUM_VERSION} ${smiVersion} _smiVersion_OK) if (NOT _smiVersion_OK) message(FATAL_ERROR "The found version of shared-mime-info (${smiVersion}) is below the minimum required (${SHARED_MIME_INFO_MINIMUM_VERSION})") endif (NOT _smiVersion_OK) endif (NOT SharedMimeInfo_FIND_QUIETLY) else (SHARED_MIME_INFO_FOUND) if (SharedMimeInfo_FIND_REQUIRED) message(FATAL_ERROR "Could NOT find shared-mime-info. See http://freedesktop.org/wiki/Software/shared-mime-info.") endif (SharedMimeInfo_FIND_REQUIRED) endif (SHARED_MIME_INFO_FOUND) endif (UPDATE_MIME_DATABASE_EXECUTABLE) mark_as_advanced(UPDATE_MIME_DATABASE_EXECUTABLE) macro(UPDATE_XDG_MIMETYPES _path) get_filename_component(_xdgmimeDir "${_path}" NAME) if("${_xdgmimeDir}" STREQUAL packages ) get_filename_component(_xdgmimeDir "${_path}" PATH) else("${_xdgmimeDir}" STREQUAL packages ) set(_xdgmimeDir "${_path}") endif("${_xdgmimeDir}" STREQUAL packages ) install(CODE " set(DESTDIR_VALUE \"\$ENV{DESTDIR}\") if (NOT DESTDIR_VALUE) # under Windows relative paths are used, that's why it runs from CMAKE_INSTALL_PREFIX execute_process(COMMAND ${UPDATE_MIME_DATABASE_EXECUTABLE} ${_xdgmimeDir} WORKING_DIRECTORY \"${CMAKE_INSTALL_PREFIX}\") endif (NOT DESTDIR_VALUE) ") endmacro (UPDATE_XDG_MIMETYPES) regina-4.96/cmake/modules/FindSourceHighlight.cmake000644 000765 000024 00000002114 12311266525 022234 0ustar00babstaff000000 000000 # Copyright (c) William Pettersson and Ben Burton, 2011 # Licensed under the GNU General Public License, version 2 or later # # As an exception, when this program is distributed through (i) the # App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or # (iii) Google Play by Google Inc., then that store may impose any # digital rights management, device limits and/or redistribution # restrictions that are required by its terms of service. find_path(SRCHILITE_INCLUDE_DIR srchilite/sourcehighlight.h PATHS /usr/include /usr/local/lib) find_library(SRCHILITE_LIBRARY source-highlight PATHS /usr/lib /usr/local/lib) IF(SRCHILITE_INCLUDE_DIR AND SRCHILITE_LIBRARY) SET(SRCHILITE_FOUND TRUE) ENDIF(SRCHILITE_INCLUDE_DIR AND SRCHILITE_LIBRARY) IF(SRCHILITE_FOUND) IF (NOT SRCHILITE_FIND_QUIETLY) MESSAGE(STATUS "Found source-highlight: ${SRCHILITE_LIBRARY}") ENDIF (NOT SRCHILITE_FIND_QUIETLY) ELSE (SRCHILITE_FOUND) IF (SRCHILITE_FIND_REQUIRED) MESSAGE(FATAL_ERROR "Could not find the source-highlight library.") ENDIF (SRCHILITE_FIND_REQUIRED) ENDIF(SRCHILITE_FOUND) regina-4.96/cmake/modules/MacroEnsureVersion.cmake000644 000765 000024 00000012055 12234011536 022133 0ustar00babstaff000000 000000 # Taken from the KDE4 cmake modules directory. - Ben Burton, 11 February 2012. # This file defines the following macros for developers to use in ensuring # that installed software is of the right version: # # MACRO_ENSURE_VERSION - test that a version number is greater than # or equal to some minimum # MACRO_ENSURE_VERSION_RANGE - test that a version number is greater than # or equal to some minimum and less than some # maximum # MACRO_ENSURE_VERSION2 - deprecated, do not use in new code # # MACRO_ENSURE_VERSION # This macro compares version numbers of the form "x.y.z" or "x.y" # MACRO_ENSURE_VERSION( FOO_MIN_VERSION FOO_VERSION_FOUND FOO_VERSION_OK) # will set FOO_VERSION_OK to true if FOO_VERSION_FOUND >= FOO_MIN_VERSION # Leading and trailing text is ok, e.g. # MACRO_ENSURE_VERSION( "2.5.31" "flex 2.5.4a" VERSION_OK) # which means 2.5.31 is required and "flex 2.5.4a" is what was found on the system # Copyright (c) 2006, David Faure, # Copyright (c) 2007, Will Stephenson # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # MACRO_ENSURE_VERSION_RANGE # This macro ensures that a version number of the form # "x.y.z" or "x.y" falls within a range defined by # min_version <= found_version < max_version. # If this expression holds, FOO_VERSION_OK will be set TRUE # # Example: MACRO_ENSURE_VERSION_RANGE3( "0.1.0" ${FOOCODE_VERSION} "0.7.0" FOO_VERSION_OK ) # # This macro will break silently if any of x,y,z are greater than 100. # # Copyright (c) 2007, Will Stephenson # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # NORMALIZE_VERSION # Helper macro to convert version numbers of the form "x.y.z" # to an integer equal to 10^4 * x + 10^2 * y + z # # This macro will break silently if any of x,y,z are greater than 100. # # Copyright (c) 2006, David Faure, # Copyright (c) 2007, Will Stephenson # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # CHECK_RANGE_INCLUSIVE_LOWER # Helper macro to check whether x <= y < z # # Copyright (c) 2007, Will Stephenson # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. MACRO(NORMALIZE_VERSION _requested_version _normalized_version) STRING(REGEX MATCH "[^0-9]*[0-9]+\\.[0-9]+\\.[0-9]+.*" _threePartMatch "${_requested_version}") if (_threePartMatch) # parse the parts of the version string STRING(REGEX REPLACE "[^0-9]*([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" _major_vers "${_requested_version}") STRING(REGEX REPLACE "[^0-9]*[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" _minor_vers "${_requested_version}") STRING(REGEX REPLACE "[^0-9]*[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" _patch_vers "${_requested_version}") else (_threePartMatch) STRING(REGEX REPLACE "([0-9]+)\\.[0-9]+" "\\1" _major_vers "${_requested_version}") STRING(REGEX REPLACE "[0-9]+\\.([0-9]+)" "\\1" _minor_vers "${_requested_version}") set(_patch_vers "0") endif (_threePartMatch) # compute an overall version number which can be compared at once MATH(EXPR ${_normalized_version} "${_major_vers}*10000 + ${_minor_vers}*100 + ${_patch_vers}") ENDMACRO(NORMALIZE_VERSION) MACRO(MACRO_CHECK_RANGE_INCLUSIVE_LOWER _lower_limit _value _upper_limit _ok) if (${_value} LESS ${_lower_limit}) set( ${_ok} FALSE ) elseif (${_value} EQUAL ${_lower_limit}) set( ${_ok} TRUE ) elseif (${_value} EQUAL ${_upper_limit}) set( ${_ok} FALSE ) elseif (${_value} GREATER ${_upper_limit}) set( ${_ok} FALSE ) else (${_value} LESS ${_lower_limit}) set( ${_ok} TRUE ) endif (${_value} LESS ${_lower_limit}) ENDMACRO(MACRO_CHECK_RANGE_INCLUSIVE_LOWER) MACRO(MACRO_ENSURE_VERSION requested_version found_version var_too_old) NORMALIZE_VERSION( ${requested_version} req_vers_num ) NORMALIZE_VERSION( ${found_version} found_vers_num ) if (found_vers_num LESS req_vers_num) set( ${var_too_old} FALSE ) else (found_vers_num LESS req_vers_num) set( ${var_too_old} TRUE ) endif (found_vers_num LESS req_vers_num) ENDMACRO(MACRO_ENSURE_VERSION) MACRO(MACRO_ENSURE_VERSION2 requested_version2 found_version2 var_too_old2) MACRO_ENSURE_VERSION( ${requested_version2} ${found_version2} ${var_too_old2}) ENDMACRO(MACRO_ENSURE_VERSION2) MACRO(MACRO_ENSURE_VERSION_RANGE min_version found_version max_version var_ok) NORMALIZE_VERSION( ${min_version} req_vers_num ) NORMALIZE_VERSION( ${found_version} found_vers_num ) NORMALIZE_VERSION( ${max_version} max_vers_num ) MACRO_CHECK_RANGE_INCLUSIVE_LOWER( ${req_vers_num} ${found_vers_num} ${max_vers_num} ${var_ok}) ENDMACRO(MACRO_ENSURE_VERSION_RANGE) regina-4.96/cmake/modules/MacroLogFeature.cmake000644 000765 000024 00000013232 12234011536 021357 0ustar00babstaff000000 000000 # Taken from the KDE4 cmake modules directory. - Ben Burton, 25 August 2011. # This file defines the Feature Logging macros. # # MACRO_LOG_FEATURE(VAR FEATURE DESCRIPTION URL [REQUIRED [MIN_VERSION [COMMENTS]]]) # Logs the information so that it can be displayed at the end # of the configure run # VAR : TRUE or FALSE, indicating whether the feature is supported # FEATURE: name of the feature, e.g. "libjpeg" # DESCRIPTION: description what this feature provides # URL: home page # REQUIRED: TRUE or FALSE, indicating whether the featue is required # MIN_VERSION: minimum version number. empty string if unneeded # COMMENTS: More info you may want to provide. empty string if unnecessary # # MACRO_DISPLAY_FEATURE_LOG() # Call this to display the collected results. # Exits CMake with a FATAL error message if a required feature is missing # # Example: # # INCLUDE(MacroLogFeature) # # FIND_PACKAGE(JPEG) # MACRO_LOG_FEATURE(JPEG_FOUND "libjpeg" "Support JPEG images" "http://www.ijg.org" TRUE "3.2a" "") # ... # MACRO_DISPLAY_FEATURE_LOG() # Copyright (c) 2006, Alexander Neundorf, # Copyright (c) 2006, Allen Winter, # Copyright (c) 2009, Sebastian Trueg, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. IF (NOT _macroLogFeatureAlreadyIncluded) SET(_file ${CMAKE_BINARY_DIR}/MissingRequirements.txt) IF (EXISTS ${_file}) FILE(REMOVE ${_file}) ENDIF (EXISTS ${_file}) SET(_file ${CMAKE_BINARY_DIR}/EnabledFeatures.txt) IF (EXISTS ${_file}) FILE(REMOVE ${_file}) ENDIF (EXISTS ${_file}) SET(_file ${CMAKE_BINARY_DIR}/DisabledFeatures.txt) IF (EXISTS ${_file}) FILE(REMOVE ${_file}) ENDIF (EXISTS ${_file}) SET(_macroLogFeatureAlreadyIncluded TRUE) ENDIF (NOT _macroLogFeatureAlreadyIncluded) MACRO(MACRO_LOG_FEATURE _var _package _description _url ) # _required _minvers _comments) STRING(TOUPPER "${ARGV4}" _required) SET(_minvers "${ARGV5}") SET(_comments "${ARGV6}") IF (${_var}) SET(_LOGFILENAME ${CMAKE_BINARY_DIR}/EnabledFeatures.txt) ELSE (${_var}) IF ("${_required}" STREQUAL "TRUE") SET(_LOGFILENAME ${CMAKE_BINARY_DIR}/MissingRequirements.txt) ELSE ("${_required}" STREQUAL "TRUE") SET(_LOGFILENAME ${CMAKE_BINARY_DIR}/DisabledFeatures.txt) ENDIF ("${_required}" STREQUAL "TRUE") ENDIF (${_var}) SET(_logtext " * ${_package}") IF (NOT ${_var}) IF (${_minvers} MATCHES ".*") SET(_logtext "${_logtext} (${_minvers} or higher)") ENDIF (${_minvers} MATCHES ".*") SET(_logtext "${_logtext} <${_url}>\n ") ELSE (NOT ${_var}) SET(_logtext "${_logtext} - ") ENDIF (NOT ${_var}) SET(_logtext "${_logtext}${_description}") IF (NOT ${_var}) IF (${_comments} MATCHES ".*") SET(_logtext "${_logtext}\n ${_comments}") ENDIF (${_comments} MATCHES ".*") # SET(_logtext "${_logtext}\n") #double-space missing features? ENDIF (NOT ${_var}) FILE(APPEND "${_LOGFILENAME}" "${_logtext}\n") ENDMACRO(MACRO_LOG_FEATURE) MACRO(MACRO_DISPLAY_FEATURE_LOG) SET(_missingFile ${CMAKE_BINARY_DIR}/MissingRequirements.txt) SET(_enabledFile ${CMAKE_BINARY_DIR}/EnabledFeatures.txt) SET(_disabledFile ${CMAKE_BINARY_DIR}/DisabledFeatures.txt) IF (EXISTS ${_missingFile} OR EXISTS ${_enabledFile} OR EXISTS ${_disabledFile}) SET(_printSummary TRUE) ENDIF (EXISTS ${_missingFile} OR EXISTS ${_enabledFile} OR EXISTS ${_disabledFile}) IF(_printSummary) SET(_missingDeps 0) IF (EXISTS ${_enabledFile}) FILE(READ ${_enabledFile} _enabled) FILE(REMOVE ${_enabledFile}) SET(_summary "${_summary}\n-----------------------------------------------------------------------------\n-- The following external packages were located on your system.\n-- This installation will have the extra features provided by these packages.\n-----------------------------------------------------------------------------\n${_enabled}") ENDIF (EXISTS ${_enabledFile}) IF (EXISTS ${_disabledFile}) SET(_missingDeps 1) FILE(READ ${_disabledFile} _disabled) FILE(REMOVE ${_disabledFile}) SET(_summary "${_summary}\n-----------------------------------------------------------------------------\n-- The following OPTIONAL packages could NOT be located on your system.\n-- Consider installing them to enable more features from this software.\n-----------------------------------------------------------------------------\n${_disabled}") ENDIF (EXISTS ${_disabledFile}) IF (EXISTS ${_missingFile}) SET(_missingDeps 1) FILE(READ ${_missingFile} _requirements) SET(_summary "${_summary}\n-----------------------------------------------------------------------------\n-- The following REQUIRED packages could NOT be located on your system.\n-- You must install these packages before continuing.\n-----------------------------------------------------------------------------\n${_requirements}") FILE(REMOVE ${_missingFile}) SET(_haveMissingReq 1) ENDIF (EXISTS ${_missingFile}) IF (NOT ${_missingDeps}) SET(_summary "${_summary}\n-----------------------------------------------------------------------------\n-- Congratulations! All external packages have been found.") ENDIF (NOT ${_missingDeps}) MESSAGE(${_summary}) MESSAGE("-----------------------------------------------------------------------------\n") IF(_haveMissingReq) MESSAGE(FATAL_ERROR "Exiting: Missing Requirements") ENDIF(_haveMissingReq) ENDIF(_printSummary) ENDMACRO(MACRO_DISPLAY_FEATURE_LOG) regina-4.96/cmake/modules/ReginaMacros.cmake000644 000765 000024 00000004332 12400001204 020675 0ustar00babstaff000000 000000 # CMake macros specific to Regina. # # Copyright (c) Ben Burton, 2012-2014 # Licensed under the GNU General Public License, version 2 or later # # As an exception, when this program is distributed through (i) the # App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or # (iii) Google Play by Google Inc., then that store may impose any # digital rights management, device limits and/or redistribution # restrictions that are required by its terms of service. # Macro: REGINA_CREATE_HANDBOOK(lang) # # Builds an HTML manual from XML Docbook sources. # # Includes code from KDE4_CREATE_HANDBOOK from the KDE cmake scripts. # The KDE cmake scripts are licensed as follows: # # Copyright (c) 2006-2009 Alexander Neundorf, # Copyright (c) 2006, 2007, Laurent Montel, # Copyright (c) 2007 Matthias Kretz # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # macro (REGINA_CREATE_HANDBOOK _lang) # Build the docbook documentation. set(_input ${CMAKE_CURRENT_SOURCE_DIR}/index.docbook) set(_doc ${CMAKE_CURRENT_BINARY_DIR}/index.html) set(_custom ${CMAKE_CURRENT_SOURCE_DIR}/../ksgmltools2/customization) set(_dtd ${_custom}/dtd) set(_ssheet ${_custom}/regina.xsl) get_filename_component(_handbook ${CMAKE_CURRENT_SOURCE_DIR} NAME) file(GLOB _docs *.docbook) if (REGINA_DOCS) add_custom_command(OUTPUT ${_doc} COMMAND ${UNZIP_EXECUTABLE} -o -j -d ${CMAKE_CURRENT_BINARY_DIR} ${REGINA_DOCS_FILE} "docs/${_lang}/${_handbook}/\\*") else (REGINA_DOCS) add_custom_command(OUTPUT ${_doc} COMMAND ${XSLTPROC_EXECUTABLE} --path ${_dtd} -o ${CMAKE_CURRENT_BINARY_DIR}/ ${_ssheet} ${_input} DEPENDS ${_docs} ${_ssheet} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) endif (REGINA_DOCS) add_custom_target(${_handbook}-html ALL DEPENDS ${_doc}) file(GLOB _support *.png *.css *.html) install(FILES ${_support} DESTINATION ${HTMLDIR}/${_lang}/${_handbook}) install( DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DESTINATION ${HTMLDIR}/${_lang} FILES_MATCHING PATTERN CMakeFiles EXCLUDE PATTERN "*.html" ) endmacro (REGINA_CREATE_HANDBOOK) regina-4.96/CMakeLists.txt000644 000765 000024 00000041625 12377774125 015377 0ustar00babstaff000000 000000 CMAKE_MINIMUM_REQUIRED (VERSION 2.8.7) PROJECT (regina) # Let the user override the package name. IF(NOT PACKAGE_NAME) SET (PACKAGE_NAME regina CACHE STRING "The package name used for installation directories. On some platforms this is 'regina-normal', not 'regina', to avoid conflicts with other software with the same name." FORCE) ENDIF(NOT PACKAGE_NAME) SET (PACKAGE_PRETTY_NAME Regina) # Look here for Find___.cmake modules SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules") # Version SET (PACKAGE_VERSION 4.96) SET (PACKAGE_STRING "${PACKAGE_PRETTY_NAME} ${PACKAGE_VERSION}") # Extract major/minor version # Note: The PACKAGE_VERSION_MAJOR "output" is discarded, since it matches the # whole string STRING(REGEX MATCH "^([0-9]+).([0-9]+)" PACKAGE_VERSION_MAJOR "${PACKAGE_VERSION}") SET (PACKAGE_VERSION_MAJOR ${CMAKE_MATCH_1} ) SET (PACKAGE_VERSION_MINOR ${CMAKE_MATCH_2} ) # Bug report email SET (PACKAGE_BUGREPORT "regina-user@lists.sourceforge.net") # Make a release build by default. IF(NOT CMAKE_BUILD_TYPE) SET(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build. Options are: Debug Release RelWithDebInfo MinSizeRel." FORCE) ENDIF(NOT CMAKE_BUILD_TYPE) # Distinguish between the different Regina installation types: # XDG = standard freedesktop.org filesystem installation in a fixed location. # Bundle = self-contained app bundle for MacOS that users can drag and drop. # Windows = self-contained movable install directory for MS Windows. if (NOT REGINA_INSTALL_TYPE) if (APPLE) SET (REGINA_DEFAULT_INSTALL_TYPE Bundle) elseif (WIN32) SET (REGINA_DEFAULT_INSTALL_TYPE Windows) else () SET (REGINA_DEFAULT_INSTALL_TYPE XDG) endif () SET (REGINA_INSTALL_TYPE ${REGINA_DEFAULT_INSTALL_TYPE} CACHE STRING "Choose how Regina installs itself. Options are: XDG Bundle Windows." FORCE) ENDIF (NOT REGINA_INSTALL_TYPE) MESSAGE (STATUS "Regina install type: ${REGINA_INSTALL_TYPE}") # Sanity check the installation type: IF (${REGINA_INSTALL_TYPE} STREQUAL XDG) # No sanity checking needed here (yet). ELSEIF (${REGINA_INSTALL_TYPE} STREQUAL Bundle) IF (NOT APPLE) MESSAGE(FATAL_ERROR "REGINA_INSTALL_TYPE=Bundle is only supported on MacOSX.") ENDIF (NOT APPLE) ELSEIF (${REGINA_INSTALL_TYPE} STREQUAL Windows) IF (NOT WIN32) MESSAGE(FATAL_ERROR "REGINA_INSTALL_TYPE=Windows is only supported on MS Windows.") ENDIF (NOT WIN32) ELSE() MESSAGE(FATAL_ERROR "REGINA_INSTALL_TYPE must be one of: XDG Bundle Windows.") ENDIF() # Are we installing development files? IF (${REGINA_INSTALL_TYPE} STREQUAL Bundle) SET (REGINA_INSTALL_DEV OFF) ELSE (${REGINA_INSTALL_TYPE} STREQUAL Bundle) SET (REGINA_INSTALL_DEV ON) ENDIF (${REGINA_INSTALL_TYPE} STREQUAL Bundle) # Give packagers a way of insisting that every optional component is found. # Set PACKAGING_MODE=1 to make every component compulsory. # Set PACKAGING_MODE=1 and PACKAGING_NO_MPI=1 to make every component # compulsory except for the MPI utilities. IF(NOT PACKAGING_MODE) SET (PACKAGING_MODE OFF CACHE STRING "Makes all optional components mandatory, so that cmake will fail if any optional component is not found." FORCE) ENDIF(NOT PACKAGING_MODE) IF(NOT PACKAGING_NO_MPI) SET (PACKAGING_NO_MPI OFF CACHE STRING "Leaves MPI as an optional component, even if PACKAGING_MODE is ON." FORCE) ENDIF(NOT PACKAGING_NO_MPI) IF(PACKAGING_MODE) SET(REGINA_MANDATORY TRUE) IF(PACKAGING_NO_MPI) SET(REGINA_MANDATORY_MPI FALSE) ELSE(PACKAGING_NO_MPI) SET(REGINA_MANDATORY_MPI TRUE) ENDIF(PACKAGING_NO_MPI) ELSE(PACKAGING_MODE) SET(REGINA_MANDATORY FALSE) SET(REGINA_MANDATORY_MPI FALSE) ENDIF(PACKAGING_MODE) # For pretty logging of optional features at the end of the cmake run: INCLUDE(MacroLogFeature) # Modules needed for IOS check and function existence INCLUDE( CheckCXXSourceCompiles ) INCLUDE( CheckFunctionExists ) # All the user to exclude various pieces of third-party code that are # typically built directly into Regina's engine. IF (NOT EXCLUDE_NORMALIZ) SET (EXCLUDE_NORMALIZ OFF CACHE STRING "Exclude all Normaliz code from the build." FORCE) ENDIF (NOT EXCLUDE_NORMALIZ) IF (NOT EXCLUDE_SNAPPEA) SET (EXCLUDE_SNAPPEA OFF CACHE STRING "Exclude all SnapPea / SnapPy code from the build." FORCE) ENDIF (NOT EXCLUDE_SNAPPEA) IF (EXCLUDE_NORMALIZ) MESSAGE(STATUS "Excluding Normaliz from the build") ENDIF (EXCLUDE_NORMALIZ) IF (EXCLUDE_SNAPPEA) MESSAGE(STATUS "Excluding SnapPea / SnapPy from the build") ENDIF (EXCLUDE_SNAPPEA) # Regina's own cmake scripts: INCLUDE( ReginaMacros ) # Always include . in the header search path: set(CMAKE_INCLUDE_CURRENT_DIR ON) # Installation directories if (${REGINA_INSTALL_TYPE} STREQUAL Bundle) # MacOSX app bundle. SET (APPDIR ${CMAKE_INSTALL_PREFIX}) SET (BUNDLEDIR ${APPDIR}/Regina.app) SET (BUNDLEDIR_ESCAPED "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/Regina.app") SET (RESOURCEDIR ${BUNDLEDIR}/Contents/Resources) SET (BINDIR ${BUNDLEDIR}/Contents/MacOS) SET (LIBDIR ${BINDIR}) SET (DATADIR ${RESOURCEDIR}) SET (INCLUDEDIR ${RESOURCEDIR}/include) SET (PKGDATADIR ${DATADIR}) SET (PYLIBDIR ${LIBDIR}/python) elseif (${REGINA_INSTALL_TYPE} STREQUAL Windows) # MS Windows install. SET (APPDIR ${CMAKE_INSTALL_PREFIX}/bin) SET (BINDIR ${CMAKE_INSTALL_PREFIX}/bin) SET (LIBDIR ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}) SET (DATADIR ${CMAKE_INSTALL_PREFIX}/share) SET (INCLUDEDIR ${CMAKE_INSTALL_PREFIX}/include/${PACKAGE_NAME}) SET (PKGDATADIR ${DATADIR}/${PACKAGE_NAME}) SET (PYLIBDIR ${LIBDIR}/${PACKAGE_NAME}/python) else () # Full install. SET (APPDIR ${CMAKE_INSTALL_PREFIX}/bin) SET (BINDIR ${CMAKE_INSTALL_PREFIX}/bin) SET (LIBDIR ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}) SET (DATADIR ${CMAKE_INSTALL_PREFIX}/share) SET (INCLUDEDIR ${CMAKE_INSTALL_PREFIX}/include/${PACKAGE_NAME}) SET (PKGDATADIR ${DATADIR}/${PACKAGE_NAME}) UNSET (PYLIBDIR) endif () SET (HTMLDIR ${PKGDATADIR}/docs) SET (ICONDIR ${DATADIR}/icons) SET (MANDIR ${DATADIR}/man) SET (XDG_APPS_INSTALL_DIR ${DATADIR}/applications) SET (XDG_MIME_INSTALL_DIR ${DATADIR}/mime/packages) # Useful build directories SET (ENGINE_INCLUDES "${PROJECT_SOURCE_DIR}/engine" ) SET (ENGINE_LIBRARY regina-engine) # RPATH support. IF (NOT DISABLE_RPATH) SET(DISABLE_RPATH OFF CACHE BOOL "Do not build with rpath. This option may break installations in non-standard directories, since executables may be unable to find Regina's libraries. For installations in standard areas such as /usr however, this option is highly recommended." FORCE) ENDIF (NOT DISABLE_RPATH) IF (NOT DISABLE_RPATH) if (APPLE) set(CMAKE_INSTALL_NAME_DIR ${LIBDIR}) else (APPLE) set(CMAKE_INSTALL_RPATH ${LIBDIR} ) set(CMAKE_SKIP_BUILD_RPATH FALSE) set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) endif (APPLE) ENDIF (NOT DISABLE_RPATH) # i18n checks. CHECK_CXX_SOURCE_COMPILES(" #include \"langinfo.h\" int main() { nl_langinfo(CODESET); return 0; }" LANGINFO_FOUND ) if(NOT LANGINFO_FOUND) MESSAGE(WARNING "langinfo not found: UTF-8 will be used always, and the locale-specific encoding will be ignored.") endif(NOT LANGINFO_FOUND) # Large integer checks CHECK_CXX_SOURCE_COMPILES(" long long x; signed long long y; unsigned long long z; int main() { return 0; }" LONG_LONG_FOUND ) CHECK_CXX_SOURCE_COMPILES(" #include int128_t x; uint128_t y; int main() { return 0; }" INT128_T_FOUND ) CHECK_CXX_SOURCE_COMPILES(" #include __int128_t x; __uint128_t y; int main() { return 0; }" __INT128_T_FOUND ) IF (INT128_T_FOUND OR __INT128_T_FOUND) SET(INT128_AVAILABLE TRUE) ENDIF (INT128_T_FOUND OR __INT128_T_FOUND) IF(LONG_LONG_FOUND) CHECK_CXX_SOURCE_COMPILES(" unsigned long long x = 0xFFFFFFFFFFFFFFFF; int main() { return 0; }" NUMERIC_64_FOUND) CHECK_CXX_SOURCE_COMPILES(" unsigned long long x = 0xFFFFFFFFFFFFFFFFLL; int main() { return 0; }" NUMERIC_64_LL_FOUND) ENDIF(LONG_LONG_FOUND) # Dependencies used by all components of Regina FIND_PACKAGE(ZLIB) INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR}) MACRO_LOG_FEATURE(ZLIB_FOUND "zlib" "Essential: compression support" "http://www.gzip.org/zlib/" TRUE) FIND_PACKAGE(LibXml2) INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR}) MACRO_LOG_FEATURE(LIBXML2_FOUND "libxml2" "Essential: XML support" "ftp.gnome.org" TRUE) FIND_PACKAGE(GMP) INCLUDE_DIRECTORIES(${GMP_INCLUDE_DIR}) MACRO_LOG_FEATURE(GMP_FOUND "GMP/C" "Essential: large integer arithmetic support for C" "http://gmplib.org/" TRUE) FIND_PACKAGE(GMPXX) INCLUDE_DIRECTORIES(${GMPXX_INCLUDE_DIR}) MACRO_LOG_FEATURE(GMPXX_FOUND "GMP/C++" "Essential: large integer arithmetic support for C++" "http://gmplib.org/" TRUE) FIND_PACKAGE(ICONV) INCLUDE_DIRECTORIES(${ICONV_INCLUDE_DIR}) MACRO_LOG_FEATURE(ICONV_FOUND "iconv" "Essential: internationalisation support" "http://www.gnu.org/s/libiconv/" TRUE) FIND_PACKAGE(Boost COMPONENTS python regex) INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIR}) MACRO_LOG_FEATURE(Boost_FOUND "Boost" "Essential: C++ components (including Boost.Python and Boost.Regex)" "http://www.boost.org/" TRUE) FIND_PACKAGE(PkgConfig) IF(NOT PKG_CONFIG_FOUND) MESSAGE(FATAL_ERROR "Regina requires pkgconfig.") ENDIF(NOT PKG_CONFIG_FOUND) PKG_CHECK_MODULES(TOKYOCABINET tokyocabinet) MACRO_LOG_FEATURE(TOKYOCABINET_FOUND "Tokyo Cabinet" "Essential: database library for accessing census data" "http://fallabs.com/tokyocabinet/" TRUE) FIND_PACKAGE(Threads REQUIRED) IF(NOT CMAKE_USE_PTHREADS_INIT) MESSAGE(FATAL_ERROR "Regina requires pthread support.") ENDIF(NOT CMAKE_USE_PTHREADS_INIT) # Dependencies used by only some components of Regina FIND_PACKAGE(POPT) MACRO_LOG_FEATURE(POPT_FOUND "Popt" "Essential: command-line option processing" "http://rpm5.org/files/popt/" TRUE) # Optionals IF(NOT DISABLE_MPI) FIND_PACKAGE(MPI) MACRO_LOG_FEATURE(MPI_FOUND "MPI" "Build command-line tools for high-performance computing" "http://www.open-mpi.org/" REGINA_MANDATORY_MPI) ENDIF(NOT DISABLE_MPI) FIND_PACKAGE(Doxygen) MACRO_LOG_FEATURE(DOXYGEN_FOUND "Doxygen" "Generate C++/Python API docs" "http://www.doxygen.org/" REGINA_MANDATORY) IF (REGINA_DOCS) get_filename_component(REGINA_DOCS_FILE "${REGINA_DOCS}" ABSOLUTE) IF (NOT EXISTS ${REGINA_DOCS_FILE}) MESSAGE (FATAL_ERROR "The argument to REGINA_DOCS should be a zip file containing pre-built handbooks. The file you gave (${REGINA_DOCS}) does not exist.") ENDIF (NOT EXISTS ${REGINA_DOCS_FILE}) MESSAGE (STATUS "Using pre-built handbooks from ${REGINA_DOCS_FILE}") FIND_PROGRAM(UNZIP_EXECUTABLE NAMES unzip DOC "Command-line unzip tool") IF (UNZIP_EXECUTABLE) SET (UNZIP_FOUND TRUE) ENDIF (UNZIP_EXECUTABLE) SET (REGINA_BUILD_HANDBOOK ${UNZIP_FOUND}) MACRO_LOG_FEATURE(UNZIP_FOUND "unzip" "Extract the user handbook" "http://www.info-zip.org/pub/infozip/" REGINA_MANDATORY) ELSE (REGINA_DOCS) SET (REGINA_DOCS "" CACHE STRING "Extract handbooks from the given pre-built zip file instead of building them manually." FORCE) FIND_PROGRAM(XSLTPROC_EXECUTABLE NAMES xsltproc DOC "XSLT processor") IF (XSLTPROC_EXECUTABLE) SET (XSLTPROC_FOUND TRUE) ENDIF (XSLTPROC_EXECUTABLE) SET (REGINA_BUILD_HANDBOOK ${XSLTPROC_FOUND}) MACRO_LOG_FEATURE(XSLTPROC_FOUND "xsltproc" "Generate the user handbook" "http://xmlsoft.org/XSLT/" REGINA_MANDATORY) ENDIF (REGINA_DOCS) # Test suite ENABLE_TESTING() # This must appear before any calls to ADD_SUBDIRECTORY(). # Core directories ADD_SUBDIRECTORY(engine) ADD_SUBDIRECTORY(utils) # Python support if (WIN32 AND NOT CYGWIN) SET (REGINA_PYTHON_EXTENSION "pyd") SET (REGINA_PYTHON_EXTENSION_NONSTANDARD TRUE) else () SET (REGINA_PYTHON_EXTENSION "so") SET (REGINA_PYTHON_EXTENSION_NONSTANDARD FALSE) endif () IF(NOT DISABLE_PYTHON) FIND_PACKAGE(PythonInterp) FIND_PACKAGE(PythonLibs) ENDIF(NOT DISABLE_PYTHON) IF(Boost_FOUND AND PYTHONINTERP_FOUND AND PYTHONLIBS_FOUND) # We can support python. # Find the site-packages location in which the XDG build needs to put # the python module. EXECUTE_PROCESS(COMMAND "${PYTHON_EXECUTABLE}" -c "import distutils.sysconfig; print distutils.sysconfig.get_python_lib(True)" OUTPUT_VARIABLE SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE RESULT_VARIABLE DISTUTILS_RESULT) IF ((NOT DISTUTILS_RESULT) AND IS_DIRECTORY "${SITE_PACKAGES}") MESSAGE(STATUS "Python site-packages directory: ${SITE_PACKAGES}") ELSE () MESSAGE(FATAL_ERROR "Could not query the python site-packages directory. Please either set the correct python interpreter (-DPYTHON_EXECUTABLE=...), or else disable python bindings (-DDISABLE_PYTHON).") ENDIF () ADD_SUBDIRECTORY(pylib) ADD_SUBDIRECTORY(python) SET(BOOST_PYTHON_FOUND TRUE) MESSAGE(STATUS "Python bindings enabled") ELSEIF(Boost_FOUND) # Boost itself is mandatory - if it was not found then we have # bigger problems. MESSAGE(WARNING "Could not find Python interpreter and/or development files: Python bindings disabled.") ENDIF() MACRO_LOG_FEATURE(PYTHONINTERP_FOUND "Python interpreter" "Build Python bindings for Regina" "http://www.python.org/" REGINA_MANDATORY) MACRO_LOG_FEATURE(PYTHONLIBS_FOUND "Python development files" "Build Python bindings for Regina" "http://www.python.org/" REGINA_MANDATORY) # The Qt GUI IF(NOT DISABLE_GUI) SET (DISABLE_GUI OFF CACHE STRING "Disables the graphical user interface. The calculation engine, Python bindings and other command-line utilities will still be built. This option is suitable for use on high-performance clusters." FORCE) ENDIF(NOT DISABLE_GUI) IF(DISABLE_GUI) if (NOT ${REGINA_INSTALL_TYPE} STREQUAL XDG) MESSAGE(FATAL_ERROR "You can only set DISABLE_GUI=1 with REGINA_INSTALL_TYPE=XDG.") endif (NOT ${REGINA_INSTALL_TYPE} STREQUAL XDG) MESSAGE(WARNING "User set DISABLE_GUI=1: graphical user interface disabled.") ELSE(DISABLE_GUI) set(GUI_REQUIRED TRUE) FIND_PACKAGE(Qt4 COMPONENTS QtGui QtCore) FIND_PACKAGE(SourceHighlight) MACRO_LOG_FEATURE(SRCHILITE_FOUND "Source-highlight" "Syntax highlighting" "http://www.gnu.org/software/src-highlite/" REGINA_MANDATORY) if (${REGINA_INSTALL_TYPE} STREQUAL XDG) set(SHARED_MIME_INFO_MINIMUM_VERSION "0.30") find_package(SharedMimeInfo) MACRO_LOG_FEATURE(SHARED_MIME_INFO_FOUND "SharedMimeInfo" "Required for Regina's graphical user interface" "http://freedesktop.org/wiki/Software/shared-mime-info" TRUE "0.30") endif (${REGINA_INSTALL_TYPE} STREQUAL XDG) if (${REGINA_INSTALL_TYPE} STREQUAL Bundle) include(BundleUtilities) endif (${REGINA_INSTALL_TYPE} STREQUAL Bundle) # This must come after SharedMimeInfo is included, since the qtui/ # makefiles use SharedMimeInfo macros. if (QT4_FOUND) ADD_SUBDIRECTORY(qtui) endif (QT4_FOUND) MESSAGE(STATUS "Graphical user interface enabled") ENDIF(DISABLE_GUI) MACRO_LOG_FEATURE(QT4_FOUND "Qt4" "Required for Regina's graphical user interface" "http://qt.nokia.com/" GUI_REQUIRED "" "To disable the graphical user interface, run: cmake -DDISABLE_GUI=1") # Test suite, continued FIND_PATH(CPPUNIT_INCLUDE_DIR cppunit/Test.h) FIND_LIBRARY(CPPUNIT_LIBRARY NAMES cppunit) IF (CPPUNIT_INCLUDE_DIR AND CPPUNIT_LIBRARY) SET(CPPUNIT_FOUND TRUE) MESSAGE(STATUS "Found CppUnit: ${CPPUNIT_LIBRARY}") ADD_SUBDIRECTORY(testsuite) ELSE (CPPUNIT_INCLUDE_DIR AND CPPUNIT_LIBRARY) MESSAGE(WARNING "Could not find CppUnit: test suite disabled.") ENDIF (CPPUNIT_INCLUDE_DIR AND CPPUNIT_LIBRARY) MACRO_LOG_FEATURE(CPPUNIT_FOUND "CppUnit" "Build the full test suite for Regina" "http://sourceforge.net/projects/cppunit/" REGINA_MANDATORY) # Miscellaneous subdirectories ADD_SUBDIRECTORY(timing) ADD_SUBDIRECTORY(docs) ADD_SUBDIRECTORY(examples) # Configure file CONFIGURE_FILE ( "${PROJECT_SOURCE_DIR}/engine/regina-config.h.in" "${PROJECT_BINARY_DIR}/engine/regina-config.h" ) MACRO_DISPLAY_FEATURE_LOG() # CPack configuration to allow the developers to build a source tarball: set(CPACK_PACKAGE_VERSION_MAJOR ${PACKAGE_VERSION_MAJOR}) set(CPACK_PACKAGE_VERSION_MINOR ${PACKAGE_VERSION_MINOR}) set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Regina: Software for 3-manifold topology and normal surface theory") set(CPACK_PACKAGE_VENDOR "The Regina development team") set(CPACK_PACKAGE_DESCRIPTION_FILE ${CMAKE_CURRENT_SOURCE_DIR}/README.txt) set(CPACK_GENERATOR TGZ) set(CPACK_SOURCE_PACKAGE_FILE_NAME "regina-${PACKAGE_VERSION}") set(CPACK_SOURCE_GENERATOR TGZ) # The following regexes match anywhere: set(CPACK_SOURCE_IGNORE_FILES "~$" "^${PROJECT_BINARY_DIR}/" "^${PROJECT_SOURCE_DIR}/engine/snappea/kernel/unused/" "^${PROJECT_SOURCE_DIR}/icons/povray/" "^${PROJECT_SOURCE_DIR}/icons/src/" "^${PROJECT_SOURCE_DIR}/packaging/" "^${PROJECT_SOURCE_DIR}/utils/local/" "^${PROJECT_SOURCE_DIR}/utils/snappea/" "^${PROJECT_SOURCE_DIR}/www/" "^${PROJECT_SOURCE_DIR}/\\\\.git/" "^${PROJECT_SOURCE_DIR}.*/\\\\.svn/" "\\\\.DS_Store$" ) include(CPack) regina-4.96/docs/CMakeLists.txt000644 000765 000024 00000000133 12234011536 016272 0ustar00babstaff000000 000000 ADD_SUBDIRECTORY(man) IF(DOXYGEN_FOUND) ADD_SUBDIRECTORY(engine) ENDIF(DOXYGEN_FOUND) regina-4.96/docs/engine/CMakeLists.txt000644 000765 000024 00000001131 12234011536 017536 0ustar00babstaff000000 000000 # TODO: The doxygen files generated in the build tree are not removed # by "make clean". ADD_CUSTOM_COMMAND(OUTPUT index.html COMMAND ${DOXYGEN_EXECUTABLE} ${PROJECT_BINARY_DIR}/engine/doxygen/docs.conf COMMAND cp `find "${PROJECT_SOURCE_DIR}/engine" -name '*.png'` . ) ADD_CUSTOM_TARGET(docs ALL DEPENDS index.html) INSTALL( DIRECTORY ${PROJECT_BINARY_DIR}/docs/engine/ DESTINATION ${PKGDATADIR}/engine-docs FILES_MATCHING PATTERN CMakeFiles EXCLUDE PATTERN "*.css" PATTERN "*.dot" PATTERN "*.gif" PATTERN "*.html" PATTERN "*.jpg" PATTERN "*.png" PATTERN "*.txt" ) regina-4.96/docs/man/censuslookup.1000644 000765 000024 00000005025 12377774107 017150 0ustar00babstaff000000 000000 .\" This manpage has been automatically generated by docbook2man .\" from a DocBook document. This tool can be found at: .\" .\" Please send any bug reports, improvements, comments, patches, .\" etc. to Steve Cheng . .TH "CENSUSLOOKUP" "1" "23 August 2014" "" "The Regina Handbook" .SH NAME censuslookup \- Search for triangulations in Regina's census databases .SH SYNOPSIS \fBcensuslookup\fR \fB\fIisosig\fB\fR\fI ...\fR .SH "DESCRIPTION" .PP This utility searches for the given 3-manifold triangulations in the various census databases that are shipped withRegina. .PP You should present the trianguations using their \fIisomorphism signatures\fR\&. These are short text strings that identify the triangulation uniquely up to combinatorial isomorphism (i.e., up to relabellings of the tetrahedra and/or their vertices). .PP From the graphical user interface, you can view the isomorphism signature of a triangulation by switching to the Composition tab in the triangulation viewer. From Python you can fetch the isomorphism signature of the triangulation \fBx\fR by calling \fBx.isoSig()\fR\&. For a full and precise specification of isomorphism signatures, see \fBSimplification paths in the Pachner graphs of closed orientable 3-manifold triangulations\fR, Burton, 2011, arXiv:1110.6080. .PP All database matches (if any) will be written to standard output. .SH "EXAMPLE" .nf example$ \fBcensuslookup fvPQcdecedekrsnrs dLQbcccajqs cPcbbbiht\fR fvPQcdecedekrsnrs: 1 hit SFS [S2: (2,1) (3,1) (5,-4)] : #1 -- Closed census (orientable) dLQbcccajqs: 0 hits cPcbbbiht: 2 hits m004 : #1 -- Cusped hyperbolic census (orientable) L104001 -- Hyperbolic knot and link complements example$ .fi .SH "MACOS\\~X USERS" .PP If you downloaded a drag-and-drop app bundle, this utility is shipped inside it. If you dragged Regina to the main Applications folder, you can run it as /Applications/Regina.app/Contents/MacOS/censuslookup\&. .SH "WINDOWS USERS" .PP The command-line utilities are installed beneath the \fIProgram\~Files\fR directory; on some machines this directory is called \fIProgram\~Files\~(x86)\fR\&. You can start this utility by running c:\\Program\~Files\\Regina\\Regina\~4.96\\bin\\censuslookup.exe\&. .SH "SEE ALSO" .PP regina-gui\&. trisetcmp, .SH "AUTHOR" .PP This utility was written by Benjamin Burton \&. Many people have been involved in the development of Regina; see the users' handbook for a full list of credits. regina-4.96/docs/man/CMakeLists.txt000644 000765 000024 00000000453 12311266525 017060 0ustar00babstaff000000 000000 SET(man1dir ${MANDIR}/man1) SET(man1_files regconcat.1 regconvert.1 regfiledump.1 regfiletype.1 sigcensus.1 tricensus.1 tricensus-mpi.1 tricensus-mpi-status.1 trisetcmp.1 regina-gui.1 regina-python.1 ) INSTALL(FILES ${man1_files} DESTINATION ${man1dir} COMPONENT Runtime) regina-4.96/docs/man/Makefile.man000644 000765 000024 00000000472 12234011536 016525 0ustar00babstaff000000 000000 default: # This Makefile should only be used by the software authors. # To rebuild manpages, run "make -f Makefile.man man". # You will need a working docbook2man installation. # man: cd ../../qtui/doc/regina && \ docbook2man -o ../../../docs/man manonly.docbook clean: rm -f manpage.links manpage.refs regina-4.96/docs/man/regconcat.1000644 000765 000024 00000003532 12377774107 016364 0ustar00babstaff000000 000000 .\" This manpage has been automatically generated by docbook2man .\" from a DocBook document. This tool can be found at: .\" .\" Please send any bug reports, improvements, comments, patches, .\" etc. to Steve Cheng . .TH "REGCONCAT" "1" "23 August 2014" "" "The Regina Handbook" .SH NAME regconcat \- Combine several Regina data files .SH SYNOPSIS \fBregconcat\fR [ \fB-o \fIoutput-file\fB\fR ] \fB\fIinput-file\fB\fR\fI ...\fR .SH "DESCRIPTION" .PP This utility combines several individual Regina data files into a single larger data file. The new file will have a container as its top-level packet, and beneath this container will be the packet trees from each of the input files that you supply. .PP If an output file is specified through option \fB-o\fR, the new file will be written as compressed XML to this output file. Otherwise the new file will be written as uncompressed XML to standard output. .SH "OPTIONS" .TP \fB-o \fIoutput-file\fB\fR Specifies that the new combined data file should be written as compressed XML to the given output file. .SH "MACOS\\~X USERS" .PP If you downloaded a drag-and-drop app bundle, this utility is shipped inside it. If you dragged Regina to the main Applications folder, you can run it as /Applications/Regina.app/Contents/MacOS/regconcat\&. .SH "WINDOWS USERS" .PP The command-line utilities are installed beneath the \fIProgram\~Files\fR directory; on some machines this directory is called \fIProgram\~Files\~(x86)\fR\&. You can start this utility by running c:\\Program\~Files\\Regina\\Regina\~4.96\\bin\\regconcat.exe\&. .SH "SEE ALSO" .PP regina-gui\&. .SH "AUTHOR" .PP This utility was written by Benjamin Burton \&. Many people have been involved in the development of Regina; see the users' handbook for a full list of credits. regina-4.96/docs/man/regconvert.1000644 000765 000024 00000004242 12377774107 016574 0ustar00babstaff000000 000000 .\" This manpage has been automatically generated by docbook2man .\" from a DocBook document. This tool can be found at: .\" .\" Please send any bug reports, improvements, comments, patches, .\" etc. to Steve Cheng . .TH "REGCONVERT" "1" "23 August 2014" "" "The Regina Handbook" .SH NAME regconvert \- Convert between different Regina file formats .SH SYNOPSIS \fBregconvert\fR [ \fB-x\fR | \fB-u\fR ] \fB\fIold-file\fB\fR [ \fB\fInew-file\fB\fR ] .SH "DESCRIPTION" .PP This utility converts back and forth between different Regina file formats. .sp .RS .B "Note:" As of September\~2013, the ancient binary file format that was used with Regina\~2.x is no longer supported. This format has not been in use for over a decade now. If you still have files in this format, you will need to download Regina\~4.93 to convert them. .RE .PP The argument \fIold-file\fR should be the file to read and convert; the argument \fInew-file\fR should be the name of the new converted file to write. These two filenames may be the same, in which case the old file will be replaced with the new. .PP If the argument \fInew-file\fR is missing then the new file will be written to standard output, which forces the output to be uncompressed XML (see option \fB-u\fR). .SH "OPTIONS" .TP \fB-x (default)\fR Convert to compressed XML\&. .TP \fB-u\fR Convert to plain (uncompressed) XML\&. .SH "MACOS\\~X USERS" .PP If you downloaded a drag-and-drop app bundle, this utility is shipped inside it. If you dragged Regina to the main Applications folder, you can run it as /Applications/Regina.app/Contents/MacOS/regconvert\&. .SH "WINDOWS USERS" .PP The command-line utilities are installed beneath the \fIProgram\~Files\fR directory; on some machines this directory is called \fIProgram\~Files\~(x86)\fR\&. You can start this utility by running c:\\Program\~Files\\Regina\\Regina\~4.96\\bin\\regconvert.exe\&. .SH "SEE ALSO" .PP regfiletype, regina-gui\&. .SH "AUTHOR" .PP This utility was written by Benjamin Burton \&. Many people have been involved in the development of Regina; see the users' handbook for a full list of credits. regina-4.96/docs/man/regfiledump.1000644 000765 000024 00000005603 12377774107 016723 0ustar00babstaff000000 000000 .\" This manpage has been automatically generated by docbook2man .\" from a DocBook document. This tool can be found at: .\" .\" Please send any bug reports, improvements, comments, patches, .\" etc. to Steve Cheng . .TH "REGFILEDUMP" "1" "23 August 2014" "" "The Regina Handbook" .SH NAME regfiledump \- Dump the contents of a Regina data file .SH SYNOPSIS \fBregfiledump\fR [ \fB-f\fR | \fB-l\fR | \fB-n\fR ] [ \fB-c\fR ] \fB\fIfile\fB\fR [ \fB\fIpacket-label\fB\fR\fI ...\fR ] .SH "DESCRIPTION" .PP This utility dumps the contents of the given Regina data file to standard output in a human-readable format. .PP If a list of packet labels is given on the command-line, only those packets will be output. Otherwise all packets in the given file will be output. .SH "OPTIONS" .TP \fB-f (default)\fR Output full packet details. The output for each packet will cover several lines, beginning with basic details (such as the packet label and type) followed by the packet's long description. .TP \fB-l\fR Output a list of packet labels and types only, one packet per line. .TP \fB-n\fR Don't output any packets at all; this option forces a packet count (see option \fB-c\fR). .TP \fB-c\fR Finish the output with a total count of all packets in the file. .SH "INTERNATIONALISATION" .PP If any packets contain international characters, Regina will attempt to convert these to your local character encoding as it writes them to the output. .PP You can tell Regina what character encoding to use by setting standard locale-related environment variables, such as \fBLANG\fR, \fBLC_CTYPE\fR or \fBLC_ALL\fR\&. .PP For example, if \fBLANG\fR is set to en_AU then output will be written in the Western European character set ISO-8859-1, and if \fBLANG\fR is set to en_AU.UTF-8 then output will be written in the universal character set UTF-8\&. .PP Typically these environment variables will already be set for you when you install your \fBGNU/Linux\fR system, and Regina will just use the right character set out of the box. See your \fBGNU/Linux\fR system reference for further information on supporting different locales. .SH "MACOS\\~X USERS" .PP If you downloaded a drag-and-drop app bundle, this utility is shipped inside it. If you dragged Regina to the main Applications folder, you can run it as /Applications/Regina.app/Contents/MacOS/regfiledump\&. .SH "WINDOWS USERS" .PP The command-line utilities are installed beneath the \fIProgram\~Files\fR directory; on some machines this directory is called \fIProgram\~Files\~(x86)\fR\&. You can start this utility by running c:\\Program\~Files\\Regina\\Regina\~4.96\\bin\\regfiledump.exe\&. .SH "SEE ALSO" .PP regina-gui\&. .SH "AUTHOR" .PP This utility was written by Benjamin Burton \&. Many people have been involved in the development of Regina; see the users' handbook for a full list of credits. regina-4.96/docs/man/regfiletype.1000644 000765 000024 00000003127 12377774107 016736 0ustar00babstaff000000 000000 .\" This manpage has been automatically generated by docbook2man .\" from a DocBook document. This tool can be found at: .\" .\" Please send any bug reports, improvements, comments, patches, .\" etc. to Steve Cheng . .TH "REGFILETYPE" "1" "23 August 2014" "" "The Regina Handbook" .SH NAME regfiletype \- Identify the formats of Regina data files .SH SYNOPSIS \fBregfiletype\fR \fB\fIfile\fB\fR\fI ...\fR .SH "DESCRIPTION" .PP Between Regina versions 2.4 and 3.0, the data files changed from using an impenetrable and undocumented binary format to using (optionally compressed) XML\&. .PP This utility determines which of these formats a given Regina data file is in. .PP You may pass multiple files on the command line; the format of each file will be written to standard output. .SH "MACOS\\~X USERS" .PP If you downloaded a drag-and-drop app bundle, this utility is shipped inside it. If you dragged Regina to the main Applications folder, you can run it as /Applications/Regina.app/Contents/MacOS/regfiletype\&. .SH "WINDOWS USERS" .PP The command-line utilities are installed beneath the \fIProgram\~Files\fR directory; on some machines this directory is called \fIProgram\~Files\~(x86)\fR\&. You can start this utility by running c:\\Program\~Files\\Regina\\Regina\~4.96\\bin\\regfiletype.exe\&. .SH "SEE ALSO" .PP regconvert, regina-gui\&. .SH "AUTHOR" .PP This utility was written by Benjamin Burton \&. Many people have been involved in the development of Regina; see the users' handbook for a full list of credits. regina-4.96/docs/man/regina-gui.1000644 000765 000024 00000003136 12377774107 016446 0ustar00babstaff000000 000000 .\" This manpage has been automatically generated by docbook2man .\" from a DocBook document. This tool can be found at: .\" .\" Please send any bug reports, improvements, comments, patches, .\" etc. to Steve Cheng . .TH "REGINA-GUI" "1" "23 August 2014" "" "The Regina Handbook" .SH NAME regina-gui \- Regina's graphical user interface .SH SYNOPSIS \fBregina-gui\fR [ \fB\fIfile\fB\fR\fI ...\fR ] .SH "DESCRIPTION" .PP Regina is a software package for studying 3-manifold triangulations and normal surfaces. Other key features include angle structures, census enumeration, combinatorial recognition of triangulations, and high-level tasks such as 3-sphere recognition and connected sum decomposition. Regina comes with a full graphical user interface, and also offers Python bindings and a low-level C++ programming interface. .PP This starts the full graphical user interface, and is the usual way of starting Regina. Any files passed on the command-line will be opened on startup. .SH "MACOS\\~X USERS" .PP If you downloaded a drag-and-drop app bundle, this is the program that runs when you open it. The executable itself is simply called \fBRegina\fR, not \fBregina-gui\fR\&. .SH "SEE ALSO" .PP regina-python\&. .PP Regina comes with a rich users' handbook, which you can access via Help->Regina Handbook in the menu. You can also read the users' handbook online at \fBhttp://regina.sourceforge.net/docs/\fR\&. .SH "AUTHOR" .PP Many people have been involved in the development of Regina; see the users' handbook for a full list of credits. regina-4.96/docs/man/regina-python.1000644 000765 000024 00000017037 12377774107 017210 0ustar00babstaff000000 000000 .\" This manpage has been automatically generated by docbook2man .\" from a DocBook document. This tool can be found at: .\" .\" Please send any bug reports, improvements, comments, patches, .\" etc. to Steve Cheng . .TH "REGINA-PYTHON" "1" "23 August 2014" "" "The Regina Handbook" .SH NAME regina-python \- Regina's command-line Python interface .SH SYNOPSIS \fBregina-python\fR [ \fB-q, --quiet\fR | \fB-v, --verbose\fR ] [ \fB-n, --nolibs\fR ] [ \fB-a, --noautoimport\fR ] \fBregina-python\fR [ \fB-q, --quiet\fR | \fB-v, --verbose\fR ] [ \fB-n, --nolibs\fR ] [ \fB-a, --noautoimport\fR ] [ \fB-i, --interactive\fR ] \fB\fIscript\fB\fR [ \fB\fIscript-args\fB\fR ] .SH "DESCRIPTION" .PP Regina is a software package for studying 3-manifold triangulations and normal surfaces. Other key features include angle structures, census enumeration, combinatorial recognition of triangulations, and high-level tasks such as 3-sphere recognition and connected sum decomposition. Regina comes with a full graphical user interface, and also offers Python bindings and a low-level C++ programming interface. .PP This command starts an interactive Python session for Regina. This will be a command-line Python session, with direct text input/output and no graphical user interface. All of the objects, clases and methods from Regina's mathematical engine will be made available through the module \fIregina\fR, which will be imported on startup (effectively running import regina). Moreover, unless the option \fB--noautoimport\fR is passed, all of Regina's objects, classes and methods will be imported directly into the current namespace (effectively running from regina import\~*). .PP If you have frequently-used code, you can store it in a \fIuser library\fR\&. At the beginning of each Python session, Regina will automatically run all of the code in all of your user libraries. The list of user libraries will be read from the text file \fI~/.regina-libs\fR, which should contain one library filename per line. Blank lines and lines beginning with a hash (#) will be ignored. You can also configure this list of libraries through the graphical user interface: see the Python options page. .PP Instead of starting an interactive Python session, you can pass a Python script (with arguments if desired). In this case Regina will run the script (after first importing the \fIregina\fR module and loading any user libraries). If you pass \fB--interactive\fR, Regina will leave you at a Python prompt once the script finishes; otherwise it will exit Python and return you to the command line. .SH "OPTIONS" .TP \fB-q\fR .TP \fB--quiet\fR Start in quiet mode. No output will be produced except for serious errors. In particular, warnings will be suppressed. This is equivalent to setting the environment variable \fIREGINA_VERBOSITY\fR=0\&. .TP \fB-v\fR .TP \fB--verbose\fR Start in verbose mode. Additional diagnostic information will be output. This is equivalent to setting the environment variable \fIREGINA_VERBOSITY\fR=2\&. .TP \fB-n\fR .TP \fB--nolibs\fR Do not load any user libraries when the session starts. User libraries are discussed in the overview above. .TP \fB-a\fR .TP \fB--noautoimport\fR Still import the \fIregina\fR module, but do not automatically import all of Regina's objects, classes and methods into the current namespace (that is, do not run from regina import\~*). This means that (for example) the main 3-manifold triangulation class must be accessed as regina.NTriangulation, not just NTriangulation\&. .TP \fB-i\fR .TP \fB--interactive\fR Run the script in interactive mode. After executing the given script, Regina will leave you in the Python interpreter to run your own additional commands. This option is only available when a script is passed. If no script is passed, \fBregina-python\fR will always start in interactive mode. .SH "ENVIRONMENT VARIABLES" .PP The following environment variables influence the behaviour of this program. Each variable can also be set in the local configuration file \fI~/.regina-python\fR using a line of the form \fIoption\fR=\fIvalue\fR\&. Environment variables will take precedence over values in the configuration file. .TP \fB\fIREGINA_VERBOSITY\fB\fR Specifies how much output should be generated. Recognised values are: .RS .TP \fB0\fR Display errors only; this is equivalent to passing the option \fB--quiet\fR\&. .TP \fB1\fR Display errors and warnings; this is the default. .TP \fB2\fR Display errors, warnings and diagnostic output; this is equivalent to passing the option \fB--verbose\fR\&. .RE .TP \fB\fIREGINA_PYTHON\fB\fR The command used to start the Python interpreter. By default, Regina tries to run the same version of Python that it was built against. In general you should use the same version of Python that Regina was built against; otherwise Python might not be able to load the \fIregina\fR module. In normal situations you should never need to set this option yourself. .TP \fB\fIREGINA_HOME\fB\fR The directory in which Regina's data files are installed. This should be the directory containing the \fIicons/\fR subdirectory, the \fIexamples/\fR subdirectory and so on. If you are running Regina directly out of the source tree, this defaults to the top-level source directory. If you are running Regina from a proper installation, this defaults to the corresponding installation directory. In normal situations you should never need to set this option yourself. .sp .RS .B "Warning:" When running from a proper installation, the default \fIREGINA_HOME\fR is hard-wired into the startup script (it is set at compile time). If you install Regina into one directory but then move it by hand into another, the default \fIREGINA_HOME\fR will be incorrect. .RE .TP \fB\fIREGINA_PYLIBDIR\fB\fR The directory containing the Python module \fIregina.so\fR\&. If you are running Regina directly out of the source tree, this defaults to a directory within this source tree. If you are running Regina from a proper installation, this defaults to the corresponding installation directory. If you have installed Regina's Python module in a standard Python location (i.e., Python can import it directly without extending sys.path), then \fIREGINA_PYLIBDIR\fR should be left empty or undefined. In normal situations you should never need to set this option yourself. .sp .RS .B "Warning:" Like \fIREGINA_HOME\fR, when running from a proper installation the default \fIREGINA_PYLIBDIR\fR is hard-wired into the startup script. If you install Regina into one directory but then move it by hand into another, the default \fIREGINA_PYLIBDIR\fR will be incorrect. .RE .SH "MACOS\\~X USERS" .PP If you downloaded a drag-and-drop app bundle, this utility is shipped inside it. If you dragged Regina to the main Applications folder, you can run it as /Applications/Regina.app/Contents/MacOS/regina-python\&. .SH "WINDOWS USERS" .PP The command \fBregina-python\fR is not available under \fBWindows\fR\&. However, you can still use Python scripting in Regina's graphical user interface, by opening a graphical Python console or using script packets. .SH "SEE ALSO" .PP regina-gui\&. .PP Regina comes with thorough API documentation, which describes in detail all of the objects, classes and methods that Regina makes available to Python. You can access this documentation via Help->Python API Reference in the graphical user interface, or read it online at \fBhttp://regina.sourceforge.net/engine-docs/\fR\&. .SH "AUTHOR" .PP Many people have been involved in the development of Regina; see the users' handbook for a full list of credits. regina-4.96/docs/man/sigcensus.1000644 000765 000024 00000004331 12377774107 016420 0ustar00babstaff000000 000000 .\" This manpage has been automatically generated by docbook2man .\" from a DocBook document. This tool can be found at: .\" .\" Please send any bug reports, improvements, comments, patches, .\" etc. to Steve Cheng . .TH "SIGCENSUS" "1" "23 August 2014" "" "The Regina Handbook" .SH NAME sigcensus \- Form a census of splitting surface signatures .SH SYNOPSIS \fBsigcensus\fR \fB\fIorder\fB\fR .SH "DESCRIPTION" .PP Forms a census of all splitting surface signatures of the given order. The \fIorder\fR is the number of quadrilaterals in the resulting splitting surface. .PP The signatures will be written to standard output, one per line, followed by a count of the total number of signatures found. .PP Each signature will be output precisely once up to equivalence. Signatures are considered equivalent if they are related by some combination of: .TP 0.2i \(bu relabelling symbols; .TP 0.2i \(bu rotating an individual cycle; .TP 0.2i \(bu inverting an individual cycle (i.e., reversing the cycle and changing the case of each symbol in the cycle); .TP 0.2i \(bu reversing all cycles without changing the case of any symbols. .PP Upper-case symbols in signatures are not yet supported; this program will only output signatures whose symbols are all lower-case. .PP For more information on splitting surface signatures, see Burton's PhD thesis at \fBhttp://www.maths.uq.edu.au/~bab/papers/\fR\&. .SH "MACOS\\~X USERS" .PP If you downloaded a drag-and-drop app bundle, this utility is shipped inside it. If you dragged Regina to the main Applications folder, you can run it as /Applications/Regina.app/Contents/MacOS/sigcensus\&. .SH "WINDOWS USERS" .PP The command-line utilities are installed beneath the \fIProgram\~Files\fR directory; on some machines this directory is called \fIProgram\~Files\~(x86)\fR\&. You can start this utility by running c:\\Program\~Files\\Regina\\Regina\~4.96\\bin\\sigcensus.exe\&. .SH "SEE ALSO" .PP censuslookup, tricensus, tricensus-mpi, regina-gui\&. .SH "AUTHOR" .PP This utility was written by Benjamin Burton \&. Many people have been involved in the development of Regina; see the users' handbook for a full list of credits. regina-4.96/docs/man/tricensus-mpi-status.1000644 000765 000024 00000004475 12377774107 020551 0ustar00babstaff000000 000000 .\" This manpage has been automatically generated by docbook2man .\" from a DocBook document. This tool can be found at: .\" .\" Please send any bug reports, improvements, comments, patches, .\" etc. to Steve Cheng . .TH "TRICENSUS-MPI-STATUS" "1" "23 August 2014" "" "The Regina Handbook" .SH NAME tricensus-mpi-status \- Summarise the log file of an MPI census of triangulations .SH SYNOPSIS \fBtricensus-mpi-status\fR \fB\fIlog-file\fB\fR .SH "DESCRIPTION" .PP This utility reads a log file produced by a \fBtricensus-mpi\fR job, and writes a human-readable summary to standard output. It can be used for either jobs that have finished or jobs that are still running, and it can happily read logs that have been compressed using gzip or bzip2. .PP The logs produced by \fBtricensus-mpi\fR are very detailed, including timestamps, details of which slaves have taken which tasks, and how many triangulations each task has produced. This utility distills this detailed log into an easy-to-read summary, with one line for each face pairing. .PP Output will only appear for face pairings that have been examined so far (which includes face pairings still being processed). This output will include: .TP 0.2i \(bu whether processing for each face pairing has finished; .TP 0.2i \(bu the number of triangulations found so far for each face pairing; .TP 0.2i \(bu the number of subsearches generated and/or finished for each face pairing (only relevant when running in subsearch mode). .PP The final line of output will list the total number of triangulations found so far, whether the census has finished, and if not, when the last log entry was written. .PP For further explanation of the terminology used above, see the \fBtricensus-mpi\fR reference. .SH "EXAMPLES" .PP See the \fBtricensus-mpi\fR reference for a sample session in which \fBtricensus-mpi-status\fR is used. .SH "MACOS\\~X AND WINDOWS USERS" .PP This utility is not shipped with the drag-and-drop app bundle for \fBMacOS\~X\fR or with the \fBWindows\fR installer. .SH "SEE ALSO" .PP censuslookup, tricensus-mpi, regina-gui\&. .SH "AUTHOR" .PP This utility was written by Benjamin Burton \&. Many people have been involved in the development of Regina; see the users' handbook for a full list of credits. regina-4.96/docs/man/tricensus-mpi.1000644 000765 000024 00000025031 12377774107 017217 0ustar00babstaff000000 000000 .\" This manpage has been automatically generated by docbook2man .\" from a DocBook document. This tool can be found at: .\" .\" Please send any bug reports, improvements, comments, patches, .\" etc. to Steve Cheng . .TH "TRICENSUS-MPI" "1" "23 August 2014" "" "The Regina Handbook" .SH NAME tricensus-mpi \- Distribute a triangulation census amongst several machines using MPI .SH SYNOPSIS \fBtricensus-mpi\fR [ \fB-D, --depth=\fIlevels\fB\fR ] [ \fB-x, --dryrun\fR ] [ \fB-2, --dim2\fR ] [ \fB-o, --orientable\fR | \fB-n, --nonorientable\fR ] [ \fB-f, --finite\fR | \fB-d, --ideal\fR ] [ \fB-m, --minimal\fR | \fB-M, --minprime\fR | \fB-N, --minprimep2\fR | \fB-h, --minhyp\fR ] [ \fB-s, --sigs\fR ] \fB\fIpairs-file\fB\fR \fB\fIoutput-file-prefix\fB\fR .SH "DESCRIPTION" .PP Allows multiple processes, possibly running on a cluster of different machines, to collaborate in forming a census of 3-manifold or 2-manifold triangulations. Coordination is done through MPI (the Message Passing Interface), and the entire census is run as a single MPI job. This program is well suited for high-performance clusters. .PP The default behaviour is to enumerate 3-manifold triangulations. If you wish to enumerate 2-manifold triangulations instead, you must pass \fB--dim2\fR\&. .PP To prepare a census for distribution amongst several processes or machines, the census must be split into smaller pieces. Running \fBtricensus\fR with option \fB--genpairs\fR (which is very fast) will create a list of face pairings, each of which must be analysed in order to complete the census. .PP The full list of face pairings should be stored in a single file, which is passed on the command-line as \fIpairs-file\fR\&. This file must contain one face pairing per line, and each of these face pairings must be in canonical form (i.e., must be a minimal representative of its isomorphism class). The face pairings generated by \fBtricensus --genpairs\fR are guaranteed to satisfy these conditions. .PP The \fBtricensus-mpi\fR utility has two modes of operation: default mode, and subsearch mode. These are explained separately under modes of operation below. .PP In both modes, one MPI process acts as the controller and the remaining processes all act as slaves. The controller reads the list of face pairings from \fIpairs-file\fR, constructs a series of tasks based on these, and farms these tasks out to the slaves for processing. Each slave processes one task at a time, asking the controller for a new task when it is finished with the previous one. .PP At the end of each task, if any triangulations were found then the slave responsible will save these triangulations to an output file. The output file will have a name of the form \fIoutput-file-prefix_p\&.rga\fR in default mode or \fIoutput-file-prefix_p-s\&.rga\fR in subsearch mode. Here \fIoutput-file-prefix\fR is passed on the command line, \fIp\fR is the number of the face pairing being processed, and \fIs\fR is the number of the subsearch within that face pairing (both face pairings and subsearches are numbered from 1 upwards). If no triangulations were found then the slave will not write any output file at all. .PP The controller and slave processes all take the same \fBtricensus-mpi\fR options (excluding MPI-specific options, which are generally supplied by an MPI wrapper program such as \fBmpirun\fR or \fBmpiexec\fR). The different roles of the processes are determined solely by their MPI process rank (the controller is always the process with rank 0). It should therefore be possible to start all MPI processes by running a single command, as illustrated in the examples below. .PP As the census progresses, the controller keeps a detailed log of each slave's activities, including how long each slave task has taken and how many triangulations have been found. This log is written to the file \fIoutput-file-prefix\&.log\fR\&. The utility \fBtricensus-mpi-status\fR can parse this log and produce a shorter human-readable summary. .sp .RS .B "Important:" It is \fBhighly recommended\fR that you use the \fB--sigs\fR option. This will keep output files small, and will significantly reduce the memory footprint of \fBtricensus-mpi\fR itself. .RE .SH "MODES OF OPERATION" .PP As discussed above, there are two basic modes of operation. These are default mode (used when \fB--depth\fR is not passed), and subsearch mode (used when \fB--depth\fR is passed). .TP 0.2i \(bu In \fBdefault mode\fR, the controller simply reads the list of face pairings and gives each pairing to a slave for processing, one after another. .TP 0.2i \(bu In \fBsubsearch mode\fR, more work is pushed to the controller and the slave tasks are shorter. Here the controller reads one face pairing at a time and begins processing that face pairing. A fixed depth is supplied in the argument \fB--depth\fR; each time that depth is reached in the search tree, the subsearch from that point on is given as a task to the next idle slave. Meanwhile the controller backtracks (as though the subsearch had finished) and continues, farming the next subsearch out when the given depth is reached again, and so on. .PP The modes can be visualised as follows. For each face pairing, consider the corresponding recursive search as a large search tree. In default mode, the entire tree is processed at once as a single slave task. In subsearch mode, each subtree rooted at the given depth is processed as a separate slave task (and all processing between the root and the given depth is done by the controller). .PP The main difference between the different modes of operation is the lengths of the slave tasks, which can have a variety of effects. .TP 0.2i \(bu In default mode the slave tasks are quite long. This means the parallelisation can become very poor towards the end of the census, with some slaves sitting idle for a long time as they wait for the remaining slaves to finish. .TP 0.2i \(bu As we move to subsearch mode with increasing depth, the slave tasks become shorter and the slaves' finish times will be closer together (thus avoiding the idle slave inefficiency described above). Moreover, with a more refined subsearch, the progress information stored in the log will be more detailed, giving a better idea of how long the census has to go. On the other hand, more work is pushed to the single-process controller (risking a bottleneck if the depth is too great, with slaves now sitting idle as they wait for new tasks). In addition the MPI overhead is greater, and the number of output files can become extremely large. .PP In the end, experimentation is the best way to decide whether to run in subsearch mode and at what depth. Be aware of the option \fB--dryrun\fR, which can give a quick overview of the search space (and in particular, show how many subsearches are required for each face pairing at any given depth). .SH "OPTIONS" .PP The census options accepted by \fBtricensus-mpi\fR are identical to the options for \fBtricensus\fR See the \fBtricensus\fR reference for details. .PP Some options from \fBtricensus\fR are not available here (e.g., tetrahedra and boundary options), since these must be supplied earlier on when generating the initial list of face pairings. .PP There are new options specific to \fBtricensus-mpi\fR, which are as follows. .TP \fB-D, --depth=\fIlevels\fB\fR Indicates that subsearch mode should be used (instead of default mode). The argument \fIlevels\fR specifies at what depth in the search tree processing should pass from the controller to a new slave task. The given depth must be strictly positive (running at depth zero is equivalent to running in default mode). See the modes of operation section above for further information, as well as hints on choosing a good value for \fIlevels\fR\&. .TP \fB-x, --dryrun\fR Specifies that a fast dry run should be performed, instead of a full census. In a dry run, each time a slave accepts a task it will immediately mark it as finished with no triangulations found. The behaviour of the controller remains unchanged. The result will be an empty census. The benefit of a dry run is the log file it produces, which will show precisely how face pairings would be divided into subsearches in a real census run. In particular, the log file will show how many subsearches each face pairing produces (the utility \fBtricensus-mpi-status\fR can help extract this information from the log). At small subsearch depths, a dry run should be extremely fast. As the depth increases however, the dry run will become slower due to the extra work given to the controller. This option is only useful in subsearch mode (it can be used in default mode, but the results are uninteresting). See the modes of operation section above for further details. .SH "EXAMPLES" .PP Suppose we wish to form a census of all 6-tetrahedron closed non-orientable triangulations, optimised for prime minimal P2-irreducible triangulations (so some non-prime, non-minimal or non-P2-irreducible triangulations may be omitted). .PP We begin by using \fBtricensus\fR to generate a full list of face pairings. .nf example$ \fBtricensus --genpairs -t 6 -i > 6.pairs\fR Total face pairings: 97 example$ .fi .PP We now use \fBtricensus-mpi\fR to run the distributed census. A wrapper program such as \fBmpirun\fR or \fBmpiexec\fR can generally be used to start the MPI processes, though this depends on your specific MPI implementation. The following command runs a distributed census on 10 processors using the MPICH implementation of MPI\&. .nf example$ \fBmpirun -np 10 /usr/bin/tricensus-mpi -Nnf 6.pairs 6-nor\fR example$ .fi .PP The current state of processing is kept in the controller log \fI6-nor.log\fR\&. You can watch this log with the help of \fBtricensus-mpi-status\fR\&. .nf example$ \fBtricensus-mpi-status 6-nor.log\fR Pairing 1: done, 0 found ... Pairing 85: done, 0 found Pairing 86: done, 7 found Pairing 87: running Pairing 88: running Still running, 15 found, last activity: Wed Jun 10 05:57:34 2009 example$ .fi .PP Once the census is finished, the resulting triangulations will be saved in files such as \fI6-nor_8.rga\fR, \fI6-nor_86.rga\fR and so on. .SH "MACOS\\~X AND WINDOWS USERS" .PP This utility is not shipped with the drag-and-drop app bundle for \fBMacOS\~X\fR or with the \fBWindows\fR installer. .SH "SEE ALSO" .PP censuslookup, regconcat, sigcensus, tricensus, tricensus-mpi-status, regina-gui\&. .SH "AUTHOR" .PP This utility was written by Benjamin Burton \&. Many people have been involved in the development of Regina; see the users' handbook for a full list of credits. regina-4.96/docs/man/tricensus.1000644 000765 000024 00000032346 12377774107 016443 0ustar00babstaff000000 000000 .\" This manpage has been automatically generated by docbook2man .\" from a DocBook document. This tool can be found at: .\" .\" Please send any bug reports, improvements, comments, patches, .\" etc. to Steve Cheng . .TH "TRICENSUS" "1" "23 August 2014" "" "The Regina Handbook" .SH NAME tricensus \- Form a census of 3-manifold triangulations .SH SYNOPSIS \fBtricensus\fR [ \fB-t, --tetrahedra=\fItetrahedra\fB\fR ] [ \fB-2, --dim2\fR ] [ \fB-b, --boundary\fR | \fB-i, --internal\fR | \fB-B, --bdryfaces=\fItriangles\fB\fR ] [ \fB-o, --orientable\fR | \fB-n, --nonorientable\fR ] [ \fB-f, --finite\fR | \fB-d, --ideal\fR ] [ \fB-m, --minimal\fR | \fB-M, --minprime\fR | \fB-N, --minprimep2\fR | \fB-h, --minhyp\fR ] [ \fB-s, --sigs\fR | \fB-c, --subcontainers\fR ] [ \fB-p, --genpairs\fR | \fB-P, --usepairs\fR ] \fB\fIoutput-file\fB\fR \fBtricensus\fR \fB--help\fR .SH "DESCRIPTION" .PP Forms a census of all 3-manifold or 2-manifold triangulations that satisfy some set of conditions. .PP These conditions are specified using various command-line arguments. The only condition that you \fBmust\fR provide is the number of tetrahedra, but there are many other options available. .PP The default behaviour is to enumerate 3-manifold triangulations. If you wish to enumerate 2-manifold triangulations instead, you must pass \fB--dim2\fR\&. .PP Each triangulation will be output precisely once up to combinatorial isomorphism. Invalid 3-manifold triangulations (i.e., triangulations with edges identified to themselves in reverse, or vertices whose links have boundary but are not discs) will not be output at all. .PP As the census progresses, the state of progress will be written (slowly) to standard output. Once the census is complete, the full census will be saved to the given output file. .PP You can use the options \fB--genpairs\fR and \fB--usepairs\fR to split a census into smaller pieces. See also \fBtricensus-mpi\fR, a more powerful tool that allows you to distribute a census across a high-performance computing cluster. .sp .RS .B "Caution:" .PP A census with even a small number of tetrahedra can take an incredibly long time to run, and can chew up massive amounts of memory. It is recommended that you try very small censuses to begin with (such as 3 or 4 tetrahedra), and work upwards to establish the limits of your machine. .PP For very large census runs, it is \fBhighly recommended\fR that you use the \fB--sigs\fR option, which will keep the output file small and significantly reduce the memory footprint. .RE .SH "OPTIONS" .TP \fB-t, --tetrahedra=\fItetrahedra\fB\fR Specifies the number of tetrahedra used to build the triangulations. If \fB--dim2\fR is passed, this same option must be used to specify the number of triangles instead. .TP \fB-2, --dim2\fR Build a census of 2-manifold triangulations, not 3-manifold triangulations. This is incompatible with several options; for other options it simply translates the relevant constraint into two dimensions. See each individual option for details on how it interacts with \fB--dim2\fR\&. .TP \fB-b, --boundary\fR Only produce triangulations with at least one boundary triangle. If \fB--dim2\fR is passed, this specifies at least one boundary edge. .TP \fB-i, --internal\fR Only produce triangulations with all triangles internal (i.e., with no boundary triangles). If \fB--dim2\fR is passed, this indicates that all edges must be internal. .TP \fB-B, --bdryfaces=\fItriangles\fB\fR Only produce triangulations with the precise number of boundary triangles specified. If \fB--dim2\fR is passed, this specifies the number of boundary edges. .TP \fB-o, --orientable\fR Only produce orientable triangulations. .TP \fB-n, --nonorientable\fR Only produce non-orientable triangulations. .TP \fB-f, --finite\fR Only produce finite triangulations (triangulations with no ideal vertices). This option cannot be used with \fB--dim2\fR\&. .TP \fB-d, --ideal\fR Only produce triangulations with at least one ideal vertex. There might or might not be internal vertices (whose links are spheres) as well. This option cannot be used with \fB--dim2\fR\&. .TP \fB-m, --minimal\fR Do not include triangulations that are obviously non-minimal. This option uses a series of fast tests that try to eliminate non-minimal triangulations, but that are not always conclusive. If Regina cannot quickly tell whether a triangulation is non-minimal, it will place the triangulation in the census regardless. .TP \fB-M, --minprime\fR Do not include triangulations that are obviously non-minimal, non-prime and/or disc-reducible. This can significantly speed up the census and vastly reduce the final number of triangulations produced. As above, this option uses a series of fast tests that are not always conclusive. If Regina cannot quickly tell whether a triangulation is non-minimal, non-prime or disc-reducible, it will place the triangulation in the census regardless. This option cannot be used with \fB--dim2\fR\&. .TP \fB-N, --minprimep2\fR Do not include triangulations that are obviously non-minimal, non-prime, P2-reducible and/or disc-reducible. This can significantly speed up the census and vastly reduce the final number of triangulations produced, even more so than \fB--minprime\fR\&. As above, this option uses a series of fast tests that are not always conclusive. If Regina cannot quickly tell whether a triangulation is non-minimal, non-prime, P2-reducible or disc-reducible, it will place the triangulation in the census regardless. This option cannot be used with \fB--dim2\fR\&. .TP \fB-h, --minhyp\fR Do not include triangulations that are obviously not minimal ideal triangulations of cusped finite-volume hyperbolic 3-manifolds. This can significantly speed up the census and vastly reduce the final number of triangulations produced. As above, this option uses a series of fast tests that are not always conclusive. If Regina cannot quickly tell whether a triangulation is a minimal ideal triangulation of a cusped finite-volume hyperbolic 3-manifold, it will place the triangulation in the census regardless. This option is designed for use with ideal triangulations only (so, for instance, combining it with \fB--finite\fR or \fB--boundary\fR will produce an error message). This option also cannot be used with \fB--dim2\fR\&. .TP \fB-s, --sigs\fR Instead of writing a full Regina data file, just output a list of isomorphism signatures. The output file will be a plain text file. Each line will be a short string of letters, digits and punctuation that uniquely encodes a triangulation up to combinatorial isomorphism. You can import this text file from within Regina by selecting File->Import->Isomorphism Signature List from the menu. This option is highly recommended for large census enumerations. First, the output file will be considerably smaller. More importantly, the memory footprint of \fBtricensus\fR will also be much smaller: triangulations can be written to the output file and forgotten immediately, instead of being kept in memory to construct a final Regina data file. .TP \fB-c, --subcontainers\fR For each face pairing, a new container will be created, and resultant triangulations will be placed into these containers. These containers will be created even if the face pairing results in no triangulations. This option cannot be used with \fB--sigs\fR\&. .TP \fB-p, --genpairs\fR Only generate face pairings, not triangulations. The outermost layer of the census code involves pairing off the faces of individual tetrahedra without determining the corresponding gluing permutations. For each face pairing that is produced, Regina will try many different sets of gluing permutations and generated the corresponding triangulations. Face pairing generation consumes a very small fraction of the total census runtime, and effectively divides the census into multiple pieces. This option allows you to quickly generate a complete list of possible face pairings, so that you can feed subsets of this list to different machines to work on simultaneously. You can coordinate this manually, or you can use \fBtricensus-mpi\fR to coordinate it for you on a high-performance cluster. The list of all face pairings will be written to the given output file in text format (though you may omit the output file from the command line, in which case the face pairings will be written to standard output). If you are coordinating your sub-censuses manually, you can use the option \fB--usepairs\fR to generate triangulations from a subset of these face pairings. Options for orientability, finiteness or minimality cannot be used with \fB--genpairs\fR; instead you should use them later with \fB--usepairs\fR, or pass them to \fBtricensus-mpi\fR\&. This option does not come with progress reporting, though typically it runs fast enough that this does not matter. You can always track the state of progress by counting lines in the output file. If \fB--dim2\fR is passed, this generates edge pairings accordingly. .TP \fB-P, --usepairs\fR Use only the given subset of face pairings to build the triangulations. Each face pairing that is processed must be in canonical form, i.e., must be a minimal representative of its isomorphism class. All face pairings generated using \fB--genpairs\fR are guaranteed to satisfy this condition. Face pairings should be supplied on standard input, one per line. They should be listed in the format produced by the option \fB--genpairs\fR\&. This option effectively lets you run a subset of a larger census. See \fB--genpairs\fR for further details on how to split a census into subsets that can run simultaneously on different machines, or \fBtricensus-mpi\fR which can coordinate this process using MPI on a high-performance cluster. Options for tetrahedra or boundary triangles cannot be used with \fB--usepairs\fR; instead you should pass them earlier along with \fB--genpairs\fR when you split the original census into pieces. If \fB--dim2\fR is passed, this takes a list of edge pairings accordingly. .SH "EXAMPLES" .PP The following command forms a census of all 3-tetrahedron closed non-orientable triangulations and puts the results in the file \fIresults.rga\fR\&. To ensure that triangulations are closed we use the options \fB-i\fR (no boundary triangles) and \fB-f\fR (no ideal vertices). .nf example$ \fBtricensus -t 3 -nif results.rga\fR Starting census generation... 0:1 0:0 1:0 1:1 | 0:2 0:3 2:0 2:1 | 1:2 1:3 2:3 2:2 0:1 0:0 1:0 2:0 | 0:2 1:2 1:1 2:1 | 0:3 1:3 2:3 2:2 0:1 0:0 1:0 2:0 | 0:2 2:1 2:2 2:3 | 0:3 1:1 1:2 1:3 1:0 1:1 2:0 2:1 | 0:0 0:1 2:2 2:3 | 0:2 0:3 1:2 1:3 Finished. Total triangulations: 5 example$ .fi .PP The following command forms a census of 4-tetrahedron closed orientable triangulations, where the census creation is optimised for prime minimal triangulations. Although all prime minimal triangulations will be included, there may be some non-prime or non-minimal triangulations in the census also. .nf example$ \fBtricensus -t 4 -oifM results.rga\fR Starting census generation... 0:1 0:0 1:0 1:1 | 0:2 0:3 2:0 2:1 | 1:2 1:3 3:0 3:1 | 2:2 ... 0:1 0:0 1:0 1:1 | 0:2 0:3 2:0 3:0 | 1:2 2:2 2:1 3:1 | 1:3 ... ... 1:0 1:1 2:0 3:0 | 0:0 0:1 2:1 3:1 | 0:2 1:2 3:2 3:3 | 0:3 ... Finished. Total triangulations: 17 example$ .fi .PP The following command generates all face pairings for a 5-tetrahedron census in which all triangulations have precisely two boundary triangles. The face pairings will be written to \fIpairings.txt\fR, whereupon they can be broken up and distributed for processing at a later date. .nf example$ \fBtricensus --genpairs -t 5 -B 2 pairings.txt\fR Total face pairings: 118 example$ .fi .PP The face pairings generated in the previous example can then be fleshed out into a full census of all 3-manifold triangulations with five tetrahedra, precisely two boundary triangles and no ideal vertices as follows. The number of tetrahedra and boundary triangles were already specified in the previous command, and cannot be supplied here. The face pairings will be read from \fIpairings.txt\fR, and the final census will be written to \fIresults.rga\fR\&. .nf example$ \fBtricensus --usepairs -f results.rga < pairings.txt\fR Trying face pairings... 0:1 0:0 1:0 1:1 | 0:2 0:3 2:0 2:1 | 1:2 1:3 3:0 3:1 | 2:2 ... 0:1 0:0 1:0 1:1 | 0:2 0:3 2:0 2:1 | 1:2 1:3 3:0 3:1 | 2:2 ... ... ... (running through all 118 face pairings) ... 1:0 2:0 3:0 4:0 | 0:0 2:1 3:1 4:1 | 0:1 1:1 3:2 4:2 | 0:2 ... Total triangulations: 5817 example$ .fi .SH "MACOS\\~X USERS" .PP If you downloaded a drag-and-drop app bundle, this utility is shipped inside it. If you dragged Regina to the main Applications folder, you can run it as /Applications/Regina.app/Contents/MacOS/tricensus\&. .SH "WINDOWS USERS" .PP The command-line utilities are installed beneath the \fIProgram\~Files\fR directory; on some machines this directory is called \fIProgram\~Files\~(x86)\fR\&. You can start this utility by running c:\\Program\~Files\\Regina\\Regina\~4.96\\bin\\tricensus.exe\&. .SH "SEE ALSO" .PP censuslookup, sigcensus, tricensus-mpi, regina-gui\&. .SH "AUTHOR" .PP This utility was written by Benjamin Burton \&. Many people have been involved in the development of Regina; see the users' handbook for a full list of credits. regina-4.96/docs/man/trisetcmp.1000644 000765 000024 00000007303 12377774107 016431 0ustar00babstaff000000 000000 .\" This manpage has been automatically generated by docbook2man .\" from a DocBook document. This tool can be found at: .\" .\" Please send any bug reports, improvements, comments, patches, .\" etc. to Steve Cheng . .TH "TRISETCMP" "1" "23 August 2014" "" "The Regina Handbook" .SH NAME trisetcmp \- Compare triangulations between two Regina data files .SH SYNOPSIS \fBtrisetcmp\fR [ \fB-m\fR | \fB-n\fR ] [ \fB-s\fR ] \fB\fIfile1\fB\fR \fB\fIfile2\fB\fR .SH "DESCRIPTION" .PP Compares all triangulations in the first file against all triangulations in the second file, looking for pairs of triangulations that are combinatorially isomorphic. .PP The two given files must be Regina data files. A full list of matches (or a full list of non-matches if \fB-n\fR is passed) is written to standard output. A match occurs when some triangulation from \fIfile1\fR is combinatorially isomorphic to some triangulation from \fIfile2\fR (i.e., identical up to a relabelling of tetrahedra and their vertices). .PP This utility can also do subcomplex testing instead of full isomorphism testing. See the option \fB-s\fR for details. .SH "OPTIONS" .TP \fB-m (default)\fR Output matches only. All isomorphic matches between triangulations in \fIfile1\fR and triangulations in \fIfile2\fR will be listed. .TP \fB-n\fR Output non-matches only. All triangulations from \fIfile1\fR with no isomorphic match in \fIfile2\fR will be listed, and vice versa. If \fB-s\fR is passed then non-matches are tested in one direction only, not both; see below for details. .TP \fB-s\fR Instead of testing triangulations for isomorphism, test whether one triangulation is isomorphic to a subcomplex of the other. In the default case of \fB-m\fR (output matches only), this program outputs all instances where a triangulation from \fIfile1\fR is isomorphic to a subcomplex of a triangulation from \fIfile2\fR\&. In the case of \fB-n\fR (output non-matches only), this program outputs all triangulations from \fIfile1\fR that are not isomorphic to a subcomplex of any triangulation from \fIfile2\fR\&. .SH "INTERNATIONALISATION" .PP If any packets contain international characters, Regina will attempt to convert these to your local character encoding as it writes them to the output. .PP You can tell Regina what character encoding to use by setting standard locale-related environment variables, such as \fBLANG\fR, \fBLC_CTYPE\fR or \fBLC_ALL\fR\&. .PP For example, if \fBLANG\fR is set to en_AU then output will be written in the Western European character set ISO-8859-1, and if \fBLANG\fR is set to en_AU.UTF-8 then output will be written in the universal character set UTF-8\&. .PP Typically these environment variables will already be set for you when you install your \fBGNU/Linux\fR system, and Regina will just use the right character set out of the box. See your \fBGNU/Linux\fR system reference for further information on supporting different locales. .SH "MACOS\\~X USERS" .PP If you downloaded a drag-and-drop app bundle, this utility is shipped inside it. If you dragged Regina to the main Applications folder, you can run it as /Applications/Regina.app/Contents/MacOS/trisetcmp\&. .SH "WINDOWS USERS" .PP The command-line utilities are installed beneath the \fIProgram\~Files\fR directory; on some machines this directory is called \fIProgram\~Files\~(x86)\fR\&. You can start this utility by running c:\\Program\~Files\\Regina\\Regina\~4.96\\bin\\trisetcmp.exe\&. .SH "SEE ALSO" .PP censuslookup, regina-gui\&. .SH "AUTHOR" .PP This utility was written by Benjamin Burton \&. Many people have been involved in the development of Regina; see the users' handbook for a full list of credits. regina-4.96/docs/README.txt000644 000765 000024 00000000521 12234011536 015231 0ustar00babstaff000000 000000 Regina Documentation Directory ------------------------------ This directory tree is used to generate man pages and API documentation. The man pages are extracted from the Regina handbook, which is located in ../qtui/doc/regina/. The API documentation is generated via doxygen from the extensive comments throughout the source code. regina-4.96/engine/algebra/CMakeLists.txt000644 000765 000024 00000001077 12377772667 020247 0ustar00babstaff000000 000000 # algebra # Files to compile SET ( FILES nabeliangroup ngrouppresentation nhomgrouppresentation nmarkedabeliangroup nxmlalgebrareader ) # Prepend folder name FOREACH ( SOURCE_FILE ${FILES} ) SET ( SOURCES ${SOURCES} algebra/${SOURCE_FILE}) ENDFOREACH(SOURCE_FILE) SET(SOURCES ${SOURCES} PARENT_SCOPE) if (${REGINA_INSTALL_DEV}) INSTALL(FILES nabeliangroup.h ngrouppresentation.h nhomgrouppresentation.h nmarkedabeliangroup.h nxmlalgebrareader.h DESTINATION ${INCLUDEDIR}/algebra COMPONENT Development) endif (${REGINA_INSTALL_DEV}) regina-4.96/engine/algebra/nabeliangroup.cpp000644 000765 000024 00000025445 12377776527 021045 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "algebra/nabeliangroup.h" #include "maths/matrixops.h" namespace regina { const NLargeInteger& NAbelianGroup::getInvariantFactor( unsigned long index) const { std::multiset::const_iterator it = invariantFactors.begin(); advance(it, index); return *it; } void NAbelianGroup::addTorsionElement(const NLargeInteger& degree, unsigned mult) { // If there are no current torsion elements, just throw in the new // ones. if (invariantFactors.empty()) { for (unsigned j=0; j::const_iterator it; for (it = invariantFactors.begin(); it != invariantFactors.end(); it++) { a.entry(i,i) = *it; i++; } // Put the passed torsion elements beneath. for (unsigned j=0; j& torsion) { // Build a presentation matrix for the torsion. size_t len = invariantFactors.size() + torsion.size(); NMatrixInt a(len, len); // Put our own invariant factors in the top. unsigned i=0; std::multiset::const_iterator it; for (it = invariantFactors.begin(); it != invariantFactors.end(); it++) { a.entry(i,i) = *it; i++; } // Put the passed torsion elements beneath. for (it = torsion.begin(); it != torsion.end(); it++) { a.entry(i,i) = *it; i++; } // Go calculate! smithNormalForm(a); replaceTorsion(a); } void NAbelianGroup::addGroup(const NMatrixInt& presentation) { // Prepare to calculate invariant factors. size_t len = invariantFactors.size(); NMatrixInt a(len + presentation.rows(), len + presentation.columns()); // Fill in the complete presentation matrix. // Fill the bottom half of the matrix with the presentation. unsigned i,j; for (i=0; i::const_iterator it; for (it = invariantFactors.begin(); it != invariantFactors.end(); it++) { a.entry(i,i) = *it; i++; } // Go calculate! smithNormalForm(a); replaceTorsion(a); } void NAbelianGroup::addGroup(const NAbelianGroup& group) { rank += group.rank; // Work out the torsion elements. if (invariantFactors.empty()) { // Copy the other group's factors! invariantFactors = group.invariantFactors; return; } if (group.invariantFactors.empty()) return; // We will have to calculate the invariant factors ourselves. size_t len = invariantFactors.size() + group.invariantFactors.size(); NMatrixInt a(len, len); // Put our own invariant factors in the top. unsigned i = 0; std::multiset::const_iterator it; for (it = invariantFactors.begin(); it != invariantFactors.end(); it++) { a.entry(i,i) = *it; i++; } // Put the other group's invariant factors beneath. for (it = group.invariantFactors.begin(); it != group.invariantFactors.end(); it++) { a.entry(i,i) = *it; i++; } // Go calculate! smithNormalForm(a); replaceTorsion(a); } unsigned NAbelianGroup::getTorsionRank(const NLargeInteger& degree) const { std::multiset::const_reverse_iterator it; unsigned ans = 0; // Because we have SNF, we can bail as soon as we reach a factor // that is not divisible by degree. for (it = invariantFactors.rbegin(); it != invariantFactors.rend(); it++) if (((*it) % degree) == 0) ans++; else return ans; return ans; } void NAbelianGroup::writeTextShort(std::ostream& out) const { bool writtenSomething = false; if (rank > 0) { if (rank > 1) out << rank << ' '; out << 'Z'; writtenSomething = true; } std::multiset::const_iterator it = invariantFactors.begin(); NLargeInteger currDegree; unsigned currMult = 0; while(true) { if (it != invariantFactors.end()) { if ((*it) == currDegree) { currMult++; it++; continue; } } if (currMult > 0) { if (writtenSomething) out << " + "; if (currMult > 1) out << currMult << ' '; out << "Z_" << currDegree.stringValue(); writtenSomething = true; } if (it == invariantFactors.end()) break; currDegree = *it; currMult = 1; it++; } if (! writtenSomething) out << '0'; } void NAbelianGroup::replaceTorsion(const NMatrixInt& matrix) { // Delete any preexisting torsion. invariantFactors.clear(); // Run up the diagonal until we hit 1. // Hopefully this will be faster than running down the diagonal // looking for 0 because the SNF calculation should end up with // many 1s for a unnecessarily large presentation matrix such as // is produced for instance by homology calculations. unsigned long rows = matrix.rows(); unsigned long i = matrix.columns(); if (i > rows) { rank += (i - rows); i = rows; } while (i > 0) { if (matrix.entry(i-1, i-1) == 0) rank++; else if (matrix.entry(i-1, i-1) == 1) return; else invariantFactors.insert(invariantFactors.begin(), matrix.entry(i-1, i-1)); i--; } } void NAbelianGroup::writeXMLData(std::ostream& out) const { out << " "; for (std::multiset::const_iterator it = invariantFactors.begin(); it != invariantFactors.end(); it++) out << (*it) << ' '; out << ""; } // ---N--> CC --M--> ie: M*N = 0. NAbelianGroup::NAbelianGroup(const NMatrixInt& M, const NMatrixInt& N) { rank = N.rows(); NMatrixInt tempN(N); metricalSmithNormalForm(tempN); unsigned long lim = (tempN.rows() < tempN.columns() ? tempN.rows() : tempN.columns() ); std::multiset torsion; for (unsigned long i=0; i 1) torsion.insert(tempN.entry(i,i)); } } addTorsionElements(torsion); NMatrixInt tempM(M); metricalSmithNormalForm(tempM); lim = (tempM.rows() < tempM.columns() ? tempM.rows() : tempM.columns()); for (unsigned long i=0; i torsion; if (cof == 0) { for (unsigned long i=0; i 1) torsion.insert(tempN.entry(i,i)); } } else { for (unsigned long i=0; i 1) torsion.insert(g); } } NMatrixInt tempM(M); metricalSmithNormalForm(tempM); lim = (tempM.rows() < tempM.columns() ? tempM.rows() : tempM.columns() ); for (unsigned long i=0; i1) torsion.insert(g); } } } if (cof != 0) { for (unsigned long i=0; i #include "regina-core.h" #include "maths/ninteger.h" #include "shareableobject.h" namespace regina { class NMatrixInt; /** * \addtogroup algebra Algebraic Structures * Various algebraic structures. * @{ */ /** * Represents a finitely generated abelian group. * * The torsion elements of the group are stored in terms of their * invariant factors. For instance, Z_2+Z_3 will appear as * Z_6, and Z_2+Z_2+Z_3 will appear as Z_2+Z_6. * * In general the factors will appear as Z_d0+...+Z_dn, * where the invariant factors di are all greater than 1 and satisfy * d0|d1|...|dn. Note that this representation is * unique. * * \todo \optlong Look at using sparse matrices for storage of SNF and * the like. */ class REGINA_API NAbelianGroup : public ShareableObject { protected: unsigned rank; /**< The rank of the group (the number of Z components). */ std::multiset invariantFactors; /**< The invariant factors d0,...,dn as * described in the NAbelianGroup notes. */ public: /** * Creates a new trivial group. */ NAbelianGroup(); /** * Creates a clone of the given group. * * @param cloneMe the group to clone. */ NAbelianGroup(const NAbelianGroup& cloneMe); /** * Creates an abelian group as the homology of a chain complex. * * \pre M.columns() = N.rows(). * \pre The product M*N = 0. * * @param M the `right' matrix in the chain complex; that is, * the matrix that one takes the kernel of when computing homology. * @param N the `left' matrix in the chain complex; that is, the * matrix that one takes the image of when computing homology. * * @author Ryan Budney */ NAbelianGroup(const NMatrixInt& M, const NMatrixInt& N); /** * Creates an abelian group as the homology of a chain complex, * using mod-\a p coefficients. * * \pre M.columns() = N.rows(). * \pre The product M*N = 0. * * @param M the `right' matrix in the chain complex; that is, * the matrix that one takes the kernel of when computing homology. * @param N the `left' matrix in the chain complex; that is, the * matrix that one takes the image of when computing homology. * @param p the modulus, which may be any NLargeInteger. * Zero is interpreted as a request for integer coefficents, * which will give the same result as the * NAbelianGroup(const NMatrixInt&, const NMatrixInt&) constructor. * * @author Ryan Budney */ NAbelianGroup(const NMatrixInt& M, const NMatrixInt& N, const NLargeInteger &p); /** * Destroys the group. */ virtual ~NAbelianGroup(); /** * Increments the rank of the group by the given integer. * This integer may be positive, negative or zero. * * \pre The current rank plus the given integer is non-negative. * In other words, if we are subtracting rank then we are not * trying to subtract more rank than the group actually has. * * @param extraRank the extra rank to add; this defaults to 1. */ void addRank(int extraRank = 1); /** * Adds the given torsion element to the group. * Note that this routine might be slow since calculating the * new invariant factors is not trivial. If many different * torsion elements are to be added, consider using * addTorsionElements() instead so the invariant factors need * only be calculated once. * * In this routine we add a specified number of copies of * Z_d, where d is some given degree. * * \pre The given degree is at least 2 and the * given multiplicity is at least 1. * * @param degree d, where we are adding copies of * Z_d to the torsion. * @param mult the multiplicity m, where we are adding * precisely m copies of Z_d; this defaults to 1. */ void addTorsionElement(const NLargeInteger& degree, unsigned mult = 1); /** * Adds the given torsion element to the group. * Note that this routine might be slow since calculating the * new invariant factors is not trivial. If many different * torsion elements are to be added, consider using * addTorsionElements() instead so the invariant factors need * only be calculated once. * * In this routine we add a specified number of copies of * Z_d, where d is some given degree. * * \pre The given degree is at least 2 and the * given multiplicity is at least 1. * * @param degree d, where we are adding copies of * Z_d to the torsion. * @param mult the multiplicity m, where we are adding * precisely m copies of Z_d; this defaults to 1. */ void addTorsionElement(unsigned long degree, unsigned mult = 1); /** * Adds the given set of torsion elements to this group. * Note that this routine might be slow since calculating the * new invariant factors is not trivial. * * The torsion elements to add are described by a list of * integers k1,...,km, where we are adding * Z_k1,...,Z_km. Unlike invariant factors, the * ki are not required to divide each other. * * \pre Each integer in the given list is strictly greater than 1. * * \ifacespython This routine takes a python list as its argument. * * @param torsion a list containing the torsion elements to add, * as described above. */ void addTorsionElements(const std::multiset& torsion); /** * Adds the abelian group defined by the given presentation to this * group. * Note that this routine might be slow since calculating the * new invariant factors is not trivial. * * @param presentation a presentation matrix for the group to be * added to this group, where each column represents a generator * and each row a relation. */ void addGroup(const NMatrixInt& presentation); /** * Adds the given abelian group to this group. * Note that this routine might be slow since calculating the * new invariant factors is not trivial. * * @param group the group to add to this one. */ void addGroup(const NAbelianGroup& group); /** * Returns the rank of the group. * This is the number of included copies of Z. * * @return the rank of the group. */ unsigned getRank() const; /** * Returns the rank in the group of the torsion term of given degree. * If the given degree is d, this routine will return the * largest m for which mZ_d is a subgroup * of this group. * * For instance, if this group is Z_6+Z_12, the torsion term of * degree 2 has rank 2 (one occurrence in Z_6 and one in Z_12), * and the torsion term of degree 4 has rank 1 (one occurrence * in Z_12). * * \pre The given degree is at least 2. * * @param degree the degree of the torsion term to query. * @return the rank in the group of the given torsion term. */ unsigned getTorsionRank(const NLargeInteger& degree) const; /** * Returns the rank in the group of the torsion term of given degree. * If the given degree is d, this routine will return the * largest m for which mZ_d is a subgroup * of this group. * * For instance, if this group is Z_6+Z_12, the torsion term of * degree 2 has rank 2 (one occurrence in Z_6 and one in Z_12), * and the torsion term of degree 4 has rank 1 (one occurrence * in Z_12). * * \pre The given degree is at least 2. * * @param degree the degree of the torsion term to query. * @return the rank in the group of the given torsion term. */ unsigned getTorsionRank(unsigned long degree) const; /** * Returns the number of invariant factors that describe the * torsion elements of this group. * See the NAbelianGroup class notes for further details. * * @return the number of invariant factors. */ unsigned long getNumberOfInvariantFactors() const; /** * Returns the given invariant factor describing the torsion * elements of this group. * See the NAbelianGroup class notes for further details. * * If the invariant factors are d0|d1|...|dn, * this routine will return di where i is the * value of parameter \a index. * * @param index the index of the invariant factor to return; * this must be between 0 and getNumberOfInvariantFactors()-1 * inclusive. * @return the requested invariant factor. */ const NLargeInteger& getInvariantFactor(unsigned long index) const; /** * Determines whether this is the trivial (zero) group. * * @return \c true if and only if this is the trivial group. */ bool isTrivial() const; /** * Determines whether this is the infinite cyclic group (Z). * * @return \c true if and only if this is the infinite cyclic group. */ bool isZ() const; /** * Determines whether this is the non-trivial cyclic group on * the given number of elements. * * As a special case, if \a n = 0 then this routine will test for the * infinite cyclic group (i.e., it will behave the same as isZ()). * If \a n = 1, then this routine will test for the trivial group * (i.e., it will behave the same as isTrivial()). * * @param n the number of elements of the cyclic group in question. * @return \c true if and only if this is the cyclic group Z_n. */ bool isZn(unsigned long n) const; /** * Determines whether this and the given abelian group are * isomorphic. * * @param other the group with which this should be compared. * @return \c true if and only if the two groups are isomorphic. */ bool operator == (const NAbelianGroup& other) const; /** * Determines whether this and the given abelian group are * non-isomorphic. * * @param other the group with which this should be compared. * @return \c true if and only if the two groups are non-isomorphic. */ bool operator != (const NAbelianGroup& other) const; /** * Writes a chunk of XML containing this abelian group. * * \ifacespython Not present. * * @param out the output stream to which the XML should be written. */ void writeXMLData(std::ostream& out) const; /** * The text representation will be of the form * 3 Z + 4 Z_2 + Z_120. * The torsion elements will be written in terms of the * invariant factors of the group, as described in the * NAbelianGroup notes. */ virtual void writeTextShort(std::ostream& out) const; protected: /** * Replaces the torsion elements of this group with those * in the abelian group represented by the given Smith normal * form presentation matrix. Any zero columns in the matrix * will also be added to the rank as additional copies of Z. * Note that preexisting torsion elements will be deleted, but * preexisting rank will not. * * \pre The given matrix is in Smith normal * form, with the diagonal consisting of a series of positive, * non-decreasing integers followed by zeroes. * * @param matrix a matrix containing the Smith normal form * presentation matrix for the new torsion elements, * where each column represents a generator * and each row a relation. */ void replaceTorsion(const NMatrixInt& matrix); }; /*@}*/ // Inline functions for NAbelianGroup inline NAbelianGroup::NAbelianGroup() : rank(0) { } inline NAbelianGroup::NAbelianGroup(const NAbelianGroup& g) : ShareableObject(), rank(g.rank), invariantFactors(g.invariantFactors) { } inline NAbelianGroup::~NAbelianGroup() { } inline void NAbelianGroup::addRank(int extraRank) { rank += extraRank; } inline void NAbelianGroup::addTorsionElement(unsigned long degree, unsigned mult) { addTorsionElement(NLargeInteger(degree), mult); } inline unsigned NAbelianGroup::getRank() const { return rank; } inline unsigned NAbelianGroup::getTorsionRank(unsigned long degree) const { return getTorsionRank(NLargeInteger(degree)); } inline unsigned long NAbelianGroup::getNumberOfInvariantFactors() const { return invariantFactors.size(); } inline bool NAbelianGroup::isTrivial() const { return (rank == 0 && invariantFactors.empty()); } inline bool NAbelianGroup::isZ() const { return (rank == 1 && invariantFactors.empty()); } inline bool NAbelianGroup::isZn(unsigned long n) const { return (n == 0 ? isZ() : n == 1 ? isTrivial() : (rank == 0 && invariantFactors.size() == 1 && *invariantFactors.begin() == n)); } inline bool NAbelianGroup::operator == (const NAbelianGroup& other) const { return (rank == other.rank && invariantFactors == other.invariantFactors); } inline bool NAbelianGroup::operator != (const NAbelianGroup& other) const { return (rank != other.rank || invariantFactors != other.invariantFactors); } } // namespace regina #endif regina-4.96/engine/algebra/ngrouppresentation.cpp000644 000765 000024 00000311260 12377776530 022150 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include #include #include #include #include "algebra/ngrouppresentation.h" #include "algebra/nhomgrouppresentation.h" #include "algebra/nmarkedabeliangroup.h" #include "algebra/nabeliangroup.h" #include "maths/numbertheory.h" #include "utilities/boostutils.h" #include "utilities/stlutils.h" #include "maths/matrixops.h" namespace regina { typedef std::list::iterator TermIterator; typedef std::list::const_iterator TermIteratorConst; typedef std::vector::iterator RelIterator; typedef std::vector::const_iterator RelIteratorConst; typedef std::list::iterator TmpRelIterator; std::ostream& operator << (std::ostream& out, const NGroupExpressionTerm& term) { if (term.exponent == 0) out << '1'; else if (term.exponent == 1) out << 'g' << term.generator; else out << 'g' << term.generator << '^' << term.exponent; return out; } NGroupExpressionTerm& NGroupExpression::getTerm(unsigned long index) { TermIterator pos = terms.begin(); advance(pos, index); return *pos; } const NGroupExpressionTerm& NGroupExpression::getTerm( unsigned long index) const { TermIteratorConst pos = terms.begin(); advance(pos, index); return *pos; } NGroupExpression* NGroupExpression::inverse() const { NGroupExpression* ans = new NGroupExpression(); transform(terms.begin(), terms.end(), front_inserter(ans->terms), std::mem_fun_ref(&NGroupExpressionTerm::inverse)); return ans; } void NGroupExpression::invert() { reverse(terms.begin(), terms.end()); std::list< NGroupExpressionTerm >::iterator it; for (it = terms.begin(); it != terms.end(); it++) (*it).exponent = -(*it).exponent; } NGroupExpression* NGroupExpression::power(long exponent) const { NGroupExpression* ans = new NGroupExpression(); if (exponent == 0) return ans; long i; if (exponent > 0) for (i = 0; i < exponent; i++) ans->terms.insert(ans->terms.end(), terms.begin(), terms.end()); else for (i = 0; i > exponent; i--) transform(terms.begin(), terms.end(), front_inserter(ans->terms), std::mem_fun_ref(&NGroupExpressionTerm::inverse)); return ans; } bool NGroupExpression::simplify(bool cyclic) { bool changed = false; TermIterator next, tmpIt; for (next = terms.begin(); next != terms.end(); ) { // Take a look at merging next forwards. if ((*next).exponent == 0) { // Zero exponent. // Delete this term and step back to the previous term in // case we can now merge the previous and next terms. next = terms.erase(next); if (next != terms.begin()) next--; changed = true; continue; } tmpIt = next; tmpIt++; // Now tmpIt points to the term after next. if (tmpIt == terms.end()) { // No term to merge forwards with. next++; } else if ((*tmpIt) += (*next)) { // Successfully merged this with the following term. next = terms.erase(next); changed = true; // Look at this term again to see if it can be merged further. } else { // Different generators; cannot merge. next++; } } if (! cyclic) return changed; // Now trying merging front and back terms. // We shall do this by popping terms off the back and merging them // with the front term. while (terms.begin() != terms.end() && ++terms.begin() != terms.end()) { // Thus terms.size() > 1. The unusual test above is used to // avoid calling terms.size() which takes linear time. if (terms.front() += terms.back()) { // Merged! terms.pop_back(); changed = true; // Did we create an empty term? if (terms.front().exponent == 0) terms.pop_front(); } else break; } return changed; } bool NGroupExpression::substitute(unsigned long generator, const NGroupExpression& expansion, bool cyclic) { bool changed = false; NGroupExpression* inverse = 0; const NGroupExpression* use; long exponent, i; for (TermIterator current = terms.begin(); current != terms.end(); ) { if ((*current).generator != generator) current++; else { exponent = (*current).exponent; if (exponent != 0) { if (exponent > 0) use = &expansion; else { if (inverse == 0) inverse = expansion.inverse(); use = inverse; exponent = -exponent; } // Fill in exponent copies of use. // // Note that the following insertion will invalidate // current if the wrong type of data structure is being used! for (i = 0; i < exponent; i++) terms.insert(current, use->terms.begin(), use->terms.end()); } current = terms.erase(current); changed = true; } } if (inverse) delete inverse; if (changed) simplify(cyclic); return changed; } NGroupPresentation::NGroupPresentation(const NGroupPresentation& cloneMe) : ShareableObject(), nGenerators(cloneMe.nGenerators) { transform(cloneMe.relations.begin(), cloneMe.relations.end(), back_inserter(relations), FuncNewCopyPtr()); } // TODO: To add: platonic groups, octahedral/cubical, dihedral, // icosahedral/dodecahedral, tetrahedral and binary versions of them. // Also need to recognise circle bundles over surfaces. // Free products with amalgamation. Currently intelligentSimplify() // isn't smart enough for this. std::string NGroupPresentation::recogniseGroup() const { std::ostringstream out; // Run through cases. if (nGenerators == 0) { out << 0; return out.str(); } // Let's record the abelianisation. std::auto_ptr< NAbelianGroup > ab( abelianisation() ); // abelian test if (identifyAbelian()) { out << ab.get()->str(); return out.str(); } // not (clearly) abelian. Check if free. if (relations.size() == 0) { out << "Free(" << nGenerators << ")"; return out.str(); } // Check if its an extension over Z. // TODO: eventually look for extensions over at least fg abelian groups. // ??maybe?? some other finite groups but it's not clear how to look // for those. if (ab.get()->getRank()==1) { NGroupPresentation presCopy( *this ); std::auto_ptr< NHomGroupPresentation > AUT( presCopy.identifyExtensionOverZ() ); if (AUT.get() != NULL) { // Let's try to identify the fibre. std::string domStr( AUT.get()->getDomain().recogniseGroup() ); if (domStr.length()>0) { out<<"Z~"<getDomain().getNumberOfGenerators() ); for (unsigned long i=0; ievaluate(i).writeText(out, (numGen<27) ? true : false); } return out.str(); } // domain not recognised, but it is an extension // TODO: put in something here for this case. } } std::list< NGroupPresentation* > fpDecomp( identifyFreeProduct() ); if (fpDecomp.size()>1) { out<<"FreeProduct( "; for (std::list< NGroupPresentation* >::iterator i=fpDecomp.begin(); i!=fpDecomp.end(); i++) { std::string facStr( (*i)->recogniseGroup() ); if (facStr.length()>0) { if (i!=fpDecomp.begin()) out<<", "; out< NGroupPresentation::abelianisation() const { // create presentation matrices to pass to NAbelianGroup(M, N) NMatrixInt M(1, getNumberOfGenerators() ); // zero matrix NMatrixInt N(getNumberOfGenerators(), getNumberOfRelations() ); // run through rels, increment N entries appropriately for (unsigned long j=0; j(new NAbelianGroup(M,N)); } std::auto_ptr NGroupPresentation::markedAbelianisation() const { // create presentation matrices to pass to NMarkedAbelianGroup(M, N) NMatrixInt M(1, getNumberOfGenerators() ); // zero matrix NMatrixInt N(getNumberOfGenerators(), getNumberOfRelations() ); // run through rels, increment N entries appropriately for (unsigned long j=0; j(new NMarkedAbelianGroup(M,N)); } void NGroupPresentation::dehnAlgorithmSubMetric( const NGroupExpression &this_word, const NGroupExpression &that_word, std::set< NWordSubstitutionData > &sub_list, unsigned long step ) { unsigned long this_length ( this_word.wordLength() ); unsigned long that_length ( that_word.wordLength() ); // generic early exit strategy if ( (this_length < 2) || (that_length==0) ) return; // early exit strategy based on step. if ( (step==1) && ((step+1)*this_length < that_length) ) return; // TODO: should check to whatever extent the above is of much use... // this -> splayed to this_word, that_word -> reducer std::vector< NGroupExpressionTerm > this_word_vec( 0 ); std::vector< NGroupExpressionTerm > reducer( 0 ); this_word_vec.reserve( this_length ); reducer.reserve( that_length ); std::list::const_iterator it; for (it = this_word.getTerms().begin(); it!=this_word.getTerms().end(); it++) { for (unsigned long i=0; i0) ? 1 : -1 ) ); } for (it = that_word.getTerms().begin(); it!=that_word.getTerms().end(); it++) { for (unsigned long i=0; i0) ? 1 : -1 ) ); } std::vector< NGroupExpressionTerm > inv_reducer( that_length ); for (unsigned long i=0; i 0 ) { subData.score = 2*comp_length - that_length; if ( subData.score > -((long int)step) ) sub_list.insert(subData); } // and the corresponding search with the inverse of reducer. comp_length = 0; while ( (this_word_vec[(i+comp_length) % this_length] == inv_reducer[(j+comp_length) % that_length]) && (comp_length < that_length) && (comp_length < this_length) ) comp_length++; subData.invertB=true; subData.sub_length=comp_length; if (comp_length == that_length) { subData.score = that_length; unsigned long a=1; while ( (this_word_vec[( (i+this_length)-a )%this_length].inverse()== this_word_vec[( (i+comp_length)+(a-1) )%this_length]) && (2*a+that_length <= this_length ) ) { a++; subData.score++; } sub_list.insert(subData); } else if ( comp_length > 0 ) { subData.score = 2*comp_length - that_length; if ( subData.score > -((long int)step) ) sub_list.insert(subData); } } } /** * This applies a substitution generated by dehnAlgorithmSubMetric. */ void NGroupPresentation::applySubstitution( NGroupExpression& this_word, const NGroupExpression &that_word, const NWordSubstitutionData &sub_data ) { // okay, so let's do a quick cut-and-replace, reduce the word and hand it back. unsigned long this_length ( this_word.wordLength() ); unsigned long that_length ( that_word.wordLength() ); std::vector< NGroupExpressionTerm > this_word_vec( 0 ); std::vector< NGroupExpressionTerm > reducer( 0 ); // we'll splay-out *this and // that_word so that it's easier to search for commonalities. this_word_vec.reserve( this_length ); reducer.reserve( that_length ); std::list::const_iterator it; // start the splaying of terms for (it = this_word.getTerms().begin(); it!=this_word.getTerms().end(); it++) { for (unsigned long i=0; i0) ? 1 : -1 ) ); } // and that_word for (it = that_word.getTerms().begin(); it!=that_word.getTerms().end(); it++) { for (unsigned long i=0; i0) ? 1 : -1 ) ); } // done splaying, produce inv_reducer std::vector< NGroupExpressionTerm > inv_reducer( that_length ); for (unsigned long i=0; iwordLength() < second->wordLength() ); } /** * This routine takes a list of words, together with expVec. It's assumed * expVec is initialized to be zero and as long as the number of generators * in the group. What this routine does is, for each generator of the * group, it records the sum of the absolute value of the exponents of that * generator in word. For the i-th generator this number is recorded in * expVec[i]. */ void build_exponent_vec( const std::list< NGroupExpressionTerm > & word, std::vector &expVec ) { std::list::const_iterator tit; for ( tit = word.begin(); tit != word.end(); tit++) expVec[ (*tit).generator ] += abs( (*tit).exponent ); } /* * Commenting out since this is not used, and requires access to a * private struct. If you want to put it back, it should probably * be a member function of NWordSubstitutionData. - bab * // gives a string that describes the substitution std::string substitutionString( const NGroupExpression &word, const NGroupPresentation::NWordSubstitutionData &subData ) { std::string retval; // cut subData into bits, assemble what we're cutting // out and what we're pasting in. unsigned long word_length ( word.wordLength() ); std::vector< NGroupExpressionTerm > reducer( 0 ); reducer.reserve( word_length ); std::list::const_iterator it; // splay word for (it = word.getTerms().begin(); it!=word.getTerms().end(); it++) { for (unsigned long i=0; i0) ? 1 : -1 ) ); } // done splaying, produce inv_reducer std::vector< NGroupExpressionTerm > inv_reducer( word_length ); for (unsigned long i=0; i "+rep_word.str(); return retval; } */ } void NGroupExpression::addTermsLast(const NGroupExpression& word) { std::list< NGroupExpressionTerm >::const_iterator it; for (it = word.terms.begin(); it != word.terms.end(); it++) addTermLast( *it ); } void NGroupExpression::addTermsFirst(const NGroupExpression& word) { // traverse word's terms in reverse order. std::list< NGroupExpressionTerm >::const_reverse_iterator it; for (it = word.terms.rbegin(); it != word.terms.rend(); it++) addTermFirst( *it ); } /** * Given a word of the form g_i1^j1 g_i2^j2 ... g_in^jn * converts the word into g_i2^j2 ... g_in^jn g_i1^j1 */ void NGroupExpression::cycleRight() { if (terms.size() > 1) { NGroupExpressionTerm temp(terms.front()); terms.pop_front(); terms.push_back(temp); } } /** * Given a word of the form g_i1^j1 g_i2^j2 ... g_in^jn * converts the word into g_in^jn g_i1^j1 g_i1^j1 ... g_in-1^jn-1 */ void NGroupExpression::cycleLeft() { if (terms.size() > 1) { NGroupExpressionTerm temp(terms.back()); terms.pop_back(); terms.push_front(temp); } } NGroupExpression::NGroupExpression( const std::string &input, bool* valid ) { // interpret input as NGroupExpression as one of forms a^7b^-2, // a^7B^2, aaaaaaaBB, g0^7g1^-2. Initialize. If valid allocated set to true // or false depending on if operation is successful or not. // WSNULL - at start of word, nothing has been input. // WSVARLET - read a letter, but do not know if we're in an a^5 or g2^-2 sit. // WSVARNUM - gk situation read. // WSEXP - ^ read // WSEXPSIG ^- read // WSEXPNUM reading numbers after ^ or ^- // WSERR - an error occured. enum WORD_STATUS { WSNULL, WSVARLET, WSVARNUM, WSEXP, WSEXPSIG, WSEXPNUM, WSERR }; // a loop that goes through the entries of input. WORD_STATUS WS(WSNULL); NGroupExpressionTerm buildTerm; for (std::string::const_iterator i=input.begin(); i!=input.end(); i++) { // read *i, see what to do next. // case 1: it is a letter a..z or A..Z if ( ( (int(*i) >= int('a') ) && ( int(*i) <= int('z') ) ) || ( (int(*i) >= int('A') ) && ( int(*i) <= int('Z') ) ) ) { if (WS==WSNULL) { // fresh letter // build buildTerm. if ( (int(*i) >= int('a') ) && ( int(*i) <= int('z') ) ) { buildTerm.generator = (unsigned long)(*i) - (unsigned long)('a'); buildTerm.exponent = 1; } else if ( (int(*i) >= int('A') ) && ( int(*i) <= int('Z') ) ) { buildTerm.generator = (unsigned long)(*i) - (unsigned long)('A'); buildTerm.exponent = -1; } else { WS=WSERR; break; } WS=WSVARLET; continue; } else if ( (WS==WSVARLET) || (WS==WSVARNUM) || (WS==WSEXPNUM) ) { // new letter but previous letter to finish terms.push_back(buildTerm); if ( (int(*i) >= int('a') ) && ( int(*i) <= int('z') ) ) { buildTerm.generator = (unsigned long)(*i) - (unsigned long)('a'); buildTerm.exponent = 1; } else if ( (int(*i) >= int('A') ) && ( int(*i) <= int('Z') ) ) { buildTerm.generator = (unsigned long)(*i) - (unsigned long)('A'); buildTerm.exponent = -1; } else { WS=WSERR; break; } WS=WSVARLET; continue; } else { // anything else is a mistake. WS=WSERR; // end case 1 break; } } // case 2: it is a ^, can only occur after a generator if ( (*i) == '^' ) { if (!( (WS==WSVARLET) || (WS=WSVARNUM) ) ) { WS=WSERR; break; } WS=WSEXP; continue; } // end case 2 // case 3: it is a -, only valid after ^ if ( (*i) == '-' ) { if (!(WS==WSEXP)) { WS=WSERR; break; } buildTerm.exponent = -buildTerm.exponent; // ok with A^-1. WS=WSEXPSIG; continue; } // end case 3 // case 4: it is a number if ( ::isdigit(*i) ) { // subcase (a) this is to build a variable // buildTerm.generator == 'g' if ( (WS==WSVARLET) && (buildTerm.generator == ('g' - 'a') ) ) { buildTerm.generator=(*i - '0'); WS=WSVARNUM; continue; } else // we've already started building the variable number if ( WS==WSVARNUM ) { buildTerm.generator=10*buildTerm.generator + (*i - '0'); continue; } else // subcase (b) this is to build an exponent. if ( (WS==WSEXP) || (WS==WSEXPSIG) ) { // ^num or ^-num if (buildTerm.exponent<0) buildTerm.exponent = - static_cast(*i - '0'); else buildTerm.exponent = (*i - '0'); WS=WSEXPNUM; continue; } else if (WS==WSEXPNUM) { // blah[num] previously dealt with numbers if (buildTerm.exponent<0) buildTerm.exponent = 10*buildTerm.exponent - (*i - '0'); else buildTerm.exponent = 10*buildTerm.exponent + (*i - '0'); continue; } else { WS=WSERR; break; } } // end case 4 // now we've dealt will all important input. Let's deal with spaces next, // and any other input will fail. if ( ::isspace(*i) ) continue; else { WS=WSERR; break; } } // end i loop // did we reach the end of input without any errors? if so, append buildTerm if (WS!=WSERR) { terms.push_back(buildTerm); if (valid != NULL) (*valid) = true; } // if not, delete everything in this word else { if (valid != NULL) (*valid) = false; terms.clear(); } } bool NGroupExpression::addStringFirst( const std::string& input) { bool temp; NGroupExpression tword( input, &temp ); if (!temp) return false; addTermsFirst(tword); return true; } bool NGroupExpression::addStringLast( const std::string& input) { bool temp; NGroupExpression tword( input, &temp ); if (!temp) return false; addTermsLast(tword); return true; } // ********** NGroupPresentation below ************** NGroupPresentation::NGroupPresentation(unsigned long nGens, const std::vector &rels) { nGenerators = nGens; for (std::vector::const_iterator i=rels.begin(); i!=rels.end(); i++) relations.push_back( new NGroupExpression(*i) ); } bool NGroupPresentation::simplifyWord( NGroupExpression &input ) const { bool retval( input.simplify(false) ); if (input.isTrivial()) return retval; // now recursively apply relators until no reduction is possible. bool continueSimplify(true); while (continueSimplify) { continueSimplify = false; for (unsigned long i=0; i sub_list; // highest score is *first* dehnAlgorithmSubMetric( input, *relations[i], sub_list ); if (sub_list.size() != 0) if ( (*sub_list.begin()).score > 0 ) { applySubstitution( input, *relations[i], *sub_list.begin() ); if (input.isTrivial()) return true; continueSimplify = true; retval = true; } } } return retval; } // for now we iterate: // 1) Small Cancellation theory // 2) Nielsen moves until no reducing ones available // 3) Loop back to (1) until nothing happens in either (1) or (2). // TODO: consider a homological alignment call if the abelianization // has rank 1 or any other situation where we know it can be useful. std::auto_ptr NGroupPresentation::intelligentSimplifyDetail() { bool doRep(true), bool1(false), bool2(false); std::auto_ptr redHom; while (doRep) { doRep = false; bool1 = false; bool2 = false; std::auto_ptr tempHom( smallCancellationDetail() ); if (tempHom.get()) { bool1 = true; if (!redHom.get()) redHom.reset( tempHom.release() ); else redHom.reset( tempHom->composeWith( *redHom.get() ).release() ); } std::auto_ptr temp2Hom( intelligentNielsenDetail() ); if (temp2Hom.get()) { bool2 = true; if (!redHom.get()) redHom.reset( temp2Hom.release() ); else redHom.reset( temp2Hom->composeWith( *redHom.get() ).release() ); } if ( bool2 ) doRep = true; } std::auto_ptr temp3Hom( prettyRewritingDetail() ); if (temp3Hom.get()) { if (!redHom.get()) redHom.reset( temp3Hom.release() ); else redHom.reset( temp3Hom->composeWith( *redHom.get() ).release() ); } return std::auto_ptr( redHom.release() ); } bool NGroupPresentation::intelligentSimplify() { return intelligentSimplifyDetail().get(); } bool NGroupPresentation::smallCancellation() { return smallCancellationDetail().get(); } std::auto_ptr NGroupPresentation::smallCancellationDetail() { bool didSomething(false); // start by taking a copy of *this group, for construction of reductionMap NGroupPresentation oldGroup( *this ); std::list< NGroupExpression* >::iterator it; // relatorList will be the temporary relator table. std::list< NGroupExpression* > relatorList; for (unsigned long i=0; i substitutionTable( nGenerators ); for (unsigned long i=0; isimplify(true); relatorList.sort( compare_length ); // (1) it = relatorList.begin(); // start (2) deletion of 0-length relators while ( it != relatorList.end() ) { if ( (*it)->wordLength() == 0 ) { delete (*it); it = relatorList.erase(it); } else break; } // start (3) - apply shorter relators to longer. for (it = relatorList.begin(); it != relatorList.end(); it++) if ( (*it)->wordLength() > 0 ) { // don't bother if this is a trivial word. std::list< NGroupExpression* >::iterator tit; // target of it manips. tit = it; tit++; while (tit != relatorList.end()) { // attempt to apply *it to *tit std::set< NWordSubstitutionData > sub_list; dehnAlgorithmSubMetric( **tit, **it, sub_list ); // take first valid sub if (sub_list.size() != 0) if ( (*sub_list.begin()).score > 0 ) { applySubstitution( **tit, **it, *sub_list.begin() ); we_value_iteration = true; didSomething = true; } tit++; } } // end (3) - application of shorter to longer relators. // (4) Build and sort a list (by length) of generator-killing relations. relatorList.sort( compare_length ); for (it = relatorList.begin(); it!=relatorList.end(); it++) { bool word_length_3_trigger(false); unsigned long WL ( (*it)->wordLength() ); // build a table expressing number of times each generator is used in *it. std::vector< unsigned long > genUsage( nGenerators ); build_exponent_vec( (*it)->getTerms(), genUsage ); std::list::iterator tit; for (unsigned long i=0; igetTerms().begin(); ( tit != (*it)->getTerms().end() ); tit++) { if ( (*tit).generator == i ) { inv = ((*tit).exponent != 1); before_flag=false; } else { if (before_flag) prefix.addTermLast( (*tit) ); else complement.addTermLast( (*tit) ); } } complement.addTermsLast(prefix); if (!inv) complement.invert(); // sub gi --> complement, in both substitutionTable and relatorList for (unsigned long j=0; j::iterator pit = relatorList.begin(); pit != relatorList.end(); pit++) (*pit)->substitute( i, complement ); we_value_iteration = true; didSomething = true; if (WL>3) word_length_3_trigger=true; goto found_a_generator_killer; } } // the look through genUsage loop found_a_generator_killer: if (word_length_3_trigger) break; } // end (4) } // end of main_while_loop (6) nGenerators = 0; for (unsigned long i=0; i genReductionMapping( nGenerators ); unsigned long indx(0); for (unsigned long i=0; i i for (it = relatorList.begin(); it != relatorList.end(); it++) for (unsigned long i=0; isubstitute( genReductionMapping[i], gi ); } // and might as well do substitutionTable, too. for (unsigned long j=0; j revMap(nGenerators); for (unsigned long i=0; i(new NHomGroupPresentation( oldGroup, *this, substitutionTable, revMap)); } else return std::auto_ptr(); }// end smallCancellation() NGroupPresentation& NGroupPresentation::operator=( const NGroupPresentation& copyMe) { nGenerators = copyMe.nGenerators; for (unsigned long i=0; i NGroupPresentation::intelligentNielsenDetail() { if (nGenerators < 2) return std::auto_ptr(NULL); // let's keep a record of the best possible substitution, bool didSomething(true); std::auto_ptr retval(NULL); while (didSomething) { didSomething = false; unsigned long bSubi(0), bSubj(0), bSubType(0); // IJ IJi JI or JIi 0,1,2,3 signed long bSubScore(0); for (unsigned long i=0; i& terms( rel->getTerms() ); // now we run from front to back, cyclically keeping track of the // previous and next terms respectively. NGroupExpressionTerm prevTerm(terms.back()), thisTerm(terms.front()), nextTerm; for (std::list::iterator T=terms.begin(); T!=terms.end(); T++) { std::list::iterator Tn(T); Tn++; if (T!=terms.begin()) { prevTerm = thisTerm; thisTerm=nextTerm; } nextTerm = ( (Tn == terms.end()) ? terms.front() : *Tn ); // check IJ gigj -> gi i.e. gi -> gigj^-1 all other gens fixed if ( (thisTerm.generator == i) && (thisTerm.exponent>0) ) ( (nextTerm.generator == j) && (nextTerm.exponent>0) ) ? scrIJ += (2-thisTerm.exponent) : scrIJ -= thisTerm.exponent; if ( (thisTerm.generator == i) && (thisTerm.exponent<0) ) ( (prevTerm.generator == j) && (prevTerm.exponent<0) ) ? scrIJ += (2+thisTerm.exponent) : scrIJ += thisTerm.exponent; // check IJi gigj^-1 -> gi i.e. gi -> gigj if ( (thisTerm.generator == i) && (thisTerm.exponent>0) ) ( (nextTerm.generator == j) && (nextTerm.exponent<0) ) ? scrIJi += (2-thisTerm.exponent) : scrIJi -= thisTerm.exponent; if ( (thisTerm.generator == i) && (thisTerm.exponent<0) ) ( (prevTerm.generator == j) && (prevTerm.exponent>0) ) ? scrIJi += (2+thisTerm.exponent) : scrIJi += thisTerm.exponent; // check JI gjgi -> gi if ( (thisTerm.generator == i) && (thisTerm.exponent<0) ) ( (nextTerm.generator == j) && (nextTerm.exponent<0) ) ? scrJI += (2+thisTerm.exponent) : scrJI += thisTerm.exponent; if ( (thisTerm.generator == i) && (thisTerm.exponent>0) ) ( (prevTerm.generator == j) && (prevTerm.exponent>0) ) ? scrJI += (2-thisTerm.exponent) : scrJI -= thisTerm.exponent; // check JIi gj^-1gi -> gi if ( (thisTerm.generator == i) && (thisTerm.exponent<0) ) ( (nextTerm.generator == j) && (nextTerm.exponent>0) ) ? scrJIi += (2+thisTerm.exponent) : scrJIi += thisTerm.exponent; if ( (thisTerm.generator == i) && (thisTerm.exponent>0) ) ( (prevTerm.generator == j) && (prevTerm.exponent<0) ) ? scrJIi += (2-thisTerm.exponent) : scrJIi -= thisTerm.exponent; } } // end of relator loop // compare the IJ, IJi, JI, JIi subs to the best known one, if it exists if (scrIJ > bSubScore) { bSubScore = scrIJ; bSubi = i; bSubj = j; bSubType = 0; } if (scrIJi > bSubScore) { bSubScore = scrIJi; bSubi = i; bSubj = j; bSubType = 1; } if (scrJI > bSubScore) { bSubScore = scrJI; bSubi = i; bSubj = j; bSubType = 2; } if (scrJIi > bSubScore) { bSubScore = scrJIi; bSubi = i; bSubj = j; bSubType = 3; } } if (bSubScore > 0) { // perform sub! didSomething=true; NGroupPresentation oldPres(*this); std::vector DomToRan( oldPres.getNumberOfGenerators() ); std::vector RanToDom( oldPres.getNumberOfGenerators() ); for (unsigned long i=0; i tempHom(new NHomGroupPresentation(oldPres,newPres,DomToRan,RanToDom)); if (!retval.get()) retval.reset( tempHom.release() ); else retval.reset( tempHom->composeWith( *retval.get() ).release() ); // make the dom->ran and ran->dom vectors. } } // the while loop return std::auto_ptr(retval.release()); } bool NGroupPresentation::homologicalAlignment() { return homologicalAlignmentDetail().get(); } std::auto_ptr NGroupPresentation::homologicalAlignmentDetail() { std::auto_ptr retval; // only allocate if appropriate. // step 1: compute abelianization and how generators map to abelianization. std::auto_ptr< NMarkedAbelianGroup > abelianized( markedAbelianisation() ); NMatrixInt abMat( abelianized->minNumberOfGenerators(), getNumberOfGenerators() ); for (unsigned long j=0; j epsilon( getNumberOfGenerators() ); epsilon[j] = 1; std::vector temp( abelianized->snfRep(epsilon) ); for (unsigned long i=0; iminNumberOfGenerators(); i++) abMat.entry(i,j) = temp[i]; // columns are snfreps of abelianized gens. } unsigned long abNF( abelianized->getNumberOfInvariantFactors() ); unsigned long abNG( abelianized->minNumberOfGenerators() ); // step 2: we will mimic the simple smith normal form algorithm algorithm // using corresponding moves on the group presentation. // first the free generators. for (unsigned long i=abNF; i fVec( nGenerators ), bVec( nGenerators ); for (unsigned long l=0; l tempHom( new NHomGroupPresentation( oldPres, *this, fVec, bVec ) ); if (!retval.get()) retval.reset( tempHom.release() ); else retval.reset( tempHom->composeWith( *retval.get() ).release() ); } // j0==j1 is the column such that entry (i,j1) is +-1. nielsenTransposition(i, j1); abMat.swapColumns(i, j1); // NOTE: the matrix will have the form: // [ * * * ] // [ 0 D 0 ] At this point, with D a diagonal +-1 matrix. } for (unsigned long i=0; igetInvariantFactor(i)).isZero()) { j0++; continue; } if ((abMat.entry(i,j1) % abelianized->getInvariantFactor(i)).isZero()) { j1--; continue; } // column op! bool colFlag( (abMat.entry(i,j0) % abelianized->getInvariantFactor(i)).abs() < (abMat.entry(i,j1) % abelianized->getInvariantFactor(i)).abs() ); NLargeInteger q = abMat.entry(i,colFlag ? j1 : j0) / abMat.entry(i,colFlag ? j0 : j1); // subtract q times column j0 from column j1 for (unsigned long r=0; r fVec( nGenerators ), bVec( nGenerators ); for (unsigned long l=0; l tempHom( new NHomGroupPresentation( oldPres, *this, fVec, bVec ) ); if (!retval.get()) retval.reset( tempHom.release() ); else retval.reset( tempHom->composeWith( *retval.get() ).release() ); } // j0==j1 is the column such that entry (i,j1) is +-1. if (i!=j1) { nielsenTransposition(i, j1); abMat.swapColumns(i, j1); } } // now we're at [ P 0 0 ] // [ 0 D 0 ] so we're essentially done. // call prettify std::auto_ptr tempHom( prettyRewritingDetail() ); if (!retval.get() && tempHom.get()) retval.reset( tempHom.release() ); else if (retval.get() && tempHom.get()) retval.reset( tempHom->composeWith( *retval.get() ).release() ); return std::auto_ptr( retval.release() ); } // This algorithm has to be at least moderately sophisticated to ensure it // recognises that < a, b, a^2, abaB > is abelian. bool NGroupPresentation::identifyAbelian() const { // The idea will be to take all commutators of the generators, and see if // the relators can kill them. for (unsigned long i=0; i > NGroupExpression::relabellingsThisToOther( const NGroupExpression &other, bool cyclic ) const { // we'll handle the cyclic==true case as a repeated cyclic==false call. if (cyclic) { std::list< std::map< unsigned long, NGroupExpressionTerm > > retval; if (getNumberOfTerms() != other.getNumberOfTerms()) return retval; NGroupExpression tempW( *this ); for (unsigned long i=0; i > tempL( tempW.relabellingsThisToOther( other, false ) ); // append to retval for (std::list< std::map< unsigned long, NGroupExpressionTerm > >::iterator j=tempL.begin(); j!=tempL.end(); j++) retval.push_back( *j ); tempW.cycleRight(); } tempW.invert(); for (unsigned long i=0; i > tempL( tempW.relabellingsThisToOther( other, false ) ); // append to retval for (std::list< std::map< unsigned long, NGroupExpressionTerm > >::iterator j=tempL.begin(); j!=tempL.end(); j++) retval.push_back( *j ); tempW.cycleRight(); } return retval; // TODO: consider removing duplicates at this stage. Or make the return // value a set. } // cyclic==false std::map< unsigned long, NGroupExpressionTerm > tempMap; std::list::const_iterator j=other.getTerms().begin(); std::list::const_iterator i=getTerms().begin(); for ( ; ( (i!=getTerms().end()) && (j!=other.getTerms().end()) ); i++, j++) if (abs(i->exponent) == abs(j->exponent)) { // matching exponents, so check if generators have been used yet. std::map< unsigned long, NGroupExpressionTerm >::iterator k; k=tempMap.find( i->generator ); NGroupExpressionTerm MAPTO( j->generator, (i->exponent == j->exponent) ? 1 : -1 ); if (k!=tempMap.end()) { // previously defined, check consistency if (!(k->second == MAPTO)) // contradicting definition return std::list< std::map< unsigned long, NGroupExpressionTerm > >(); } else tempMap[i->generator] = MAPTO; } // check if words had different number of terms if ( (i!=getTerms().end()) || (j!=other.getTerms().end()) ) return std::list< std::map< unsigned long, NGroupExpressionTerm > >(); // okay, we have something. std::list< std::map< unsigned long, NGroupExpressionTerm > > retval; retval.push_back( tempMap ); return retval; } std::list< NGroupPresentation* > NGroupPresentation::identifyFreeProduct() const { // let's create a list of generators not used in the relators, then // generators that appear in a common generator, or recursively related std::set< unsigned long > unRelated; for (unsigned long i=0; i > equivRel; // determine which generators are used in the relators, to initialize // equivRel. { // forced scope std::set< unsigned long > usedRels; for (unsigned long i=0; i::const_iterator T=relations[i]->getTerms().begin(); T!=relations[i]->getTerms().end(); T++) usedRels.insert( T->generator ); for (std::set< unsigned long >::iterator i=usedRels.begin(); i!=usedRels.end(); i++) { std::set< unsigned long > singleton; singleton.insert( *i ); unRelated.erase( *i ); equivRel.push_back(singleton); } } // end forced scope // now we grow the equivalence relation. for (unsigned long i=0; i relSet; // related by relations[i] if ( (unRelated.size()==0) && (equivRel.size()==1) ) break; for (std::list::const_iterator T=relations[i]->getTerms().begin(); T!=relations[i]->getTerms().end(); T++) relSet.insert( T->generator ); if (relSet.size() < 2) continue; // in case of empty word for (std::set< unsigned long >::iterator I=relSet.begin(); I!=relSet.end(); I++) for (std::set< unsigned long >::iterator J=I; J!=relSet.end(); J++) { if (I==J) continue; std::list< std::set< unsigned long > >::iterator SI; std::list< std::set< unsigned long > >::iterator SJ; for (SI=equivRel.begin(); SI!=equivRel.end(); SI++) if (SI->find( *I )!=SI->end()) break; for (SJ=equivRel.begin(); SJ!=equivRel.end(); SJ++) if (SJ->find( *J )!=SJ->end()) break; if (SI==SJ) continue; // so we merge the sets SI and SJ are pointing to. SI->insert( SJ->begin(), SJ->end() ); equivRel.erase( SJ ); } // I J loop } // i loop if ( (equivRel.size()+unRelated.size()) < 2) return std::list< NGroupPresentation* >(); // build return value. We'll have subgroup free products, and a free group // provided unRelated is non-empty. std::list< NGroupPresentation* > retval; if (unRelated.size()>0) { NGroupPresentation* newGrp( new NGroupPresentation ); newGrp->addGenerator( unRelated.size() ); retval.push_back( newGrp ); } for (std::list< std::set< unsigned long > >::iterator I=equivRel.begin(); I!=equivRel.end(); I++) { NGroupPresentation* newGrp( new NGroupPresentation ); newGrp->addGenerator( I->size() ); std::map< unsigned long, unsigned long > downMap; // old to new map unsigned long count(0); for (std::set< unsigned long >::iterator J=I->begin(); J!=I->end(); J++) { downMap.insert( std::pair< unsigned long, unsigned long >(*J, count) ); count++; } // Build map from this groups generators to corresponding generators of *this // decide which relators from *this are relevant. for (unsigned long i=0; ifind( relations[i]->getTerm(0).generator)!=I->end()) { // yes! NGroupExpression* newRel( new NGroupExpression ); for (std::list::const_iterator ET=relations[i]->getTerms().begin(); ET!=relations[i]->getTerms().end(); ET++) newRel->addTermLast( downMap[ ET->generator ], ET->exponent ); newGrp->addRelation( newRel ); } } // end relations i loop retval.push_back( newGrp ); } return retval; } // end identifyFreeProduct() // Routine (at present) looks for isomorphism between *this group and other, // at present only maps of the form that send generators // g_i --> g_{sigma i}^{delta_i} where sigma is some permutation of the // generators, and delta is some function {0,1,...,ngens-1} --> {+1, -1} // // We do this by creating a routine that runs through the relators of this // group and checks if there are any partial permutations sigma that allow // that relator to be respected by a map. It builds up a big list of all // these partial subs, one list for every relator in *this group. As we // iterate through the relators we iteratively check compatibility of these // subsititions lists, winnowing-down the list of substitions as we go. // Once done, if non-empty that would define the map // on all generators other than free factors, so then we have to similarly // check for free factors in other. Then we check the inverse (in the free // group) descends to a map, if so we're done. // // To enable this we should probably carefully index the relations. And we // should handle 1-gen relations differently than multiple-gen relations, // otherwise there's a potential memory explosion. // // TODO: we can modify this to be a findHom routine. And if the target is // a finite group, find *all* homs up to conjugacy, etc. // bool NGroupPresentation::identifySimplyIsomorphicTo( const NGroupPresentation& other) const { // Check if presentations have the same number of generators. if (nGenerators != other.nGenerators) return false; // Check if relations empty if ( (relations.size()==0) && (other.relations.size()==0) ) return true; if ( (relations.size()==0) || (other.relations.size()==0) ) return false; // Both relations.size()>0, and have the same number of generators. // list of related by number of generators appearing std::map< unsigned long, std::list< NGroupExpression* > > domRelIdx, ranRelIdx; for (unsigned long i=0; i nget( relations[i]->getTerms() ); std::set< unsigned long > gensUsed; for (std::list::const_iterator j=nget.begin(); j!=nget.end(); j++) gensUsed.insert( j->generator ); domRelIdx[ gensUsed.size() ].push_back( relations[i] ); } for (unsigned long i=0; i nget( other.relations[i]->getTerms() ); std::set< unsigned long > gensUsed; for (std::list::const_iterator j=nget.begin(); j!=nget.end(); j++) gensUsed.insert( j->generator ); ranRelIdx[ gensUsed.size() ].push_back( other.relations[i] ); } // for each relator of this we have lists of potential substitutions // typedef std::list< partialSubType > pSubListType; std::list< std::map > allPartialSubs; allPartialSubs.push_back( std::map() ); for (std::map< unsigned long, std::list< NGroupExpression* > >::const_reverse_iterator i=domRelIdx.rbegin(); i!=domRelIdx.rend(); i++) { // currently we'll do the most simplistic thing possible -- look for relabellings // of these relators in the target presentation. unsigned long nGens = i->first; if (ranRelIdx.find(nGens)==ranRelIdx.end()) return false; const std::list< NGroupExpression* > DOMR( i->second ); const std::list< NGroupExpression* > RANR( ranRelIdx[nGens] ); // build list of subs for all DOMR -> RANR possibilities for (std::list< NGroupExpression* >::const_iterator DI=DOMR.begin(); DI!=DOMR.end(); DI++) { std::list< std::map > newPartialSubs; // for each DI, every extension or consistent hom with allPArtialSubs // we find using DI will be put in newPartialSubs, at the end, we replace // allPartialSubs with newPartialSubs. for (std::list< NGroupExpression* >::const_iterator RI=RANR.begin(); RI!=RANR.end(); RI++) { // built tempList // TODO: let's put the special case nGens==1 here, where instead of // looking making all possible maps, we just choose one. This is // because if we get here and its not defined on a torsion element, // is must have been a free factor Z_k * other stuff. So we only // need to choose a complementary map. std::list< std::map< unsigned long, NGroupExpressionTerm > > tempList( (*DI)->relabellingsThisToOther( *(*RI), true ) ); for (std::list< std::map< unsigned long, NGroupExpressionTerm > >::iterator X=tempList.begin(); X!=tempList.end(); X++) for (std::list< std::map< unsigned long, NGroupExpressionTerm > >::iterator Y=allPartialSubs.begin(); Y!=allPartialSubs.end(); Y++) { // newMap will be the potential extension of *X and *Y std::map< unsigned long, NGroupExpressionTerm > newMap; std::map< unsigned long, NGroupExpressionTerm >::iterator Xi=X->begin(); std::map< unsigned long, NGroupExpressionTerm >::iterator Yi=Y->begin(); while ( (Xi!=X->end()) || (Yi!=Y->end()) ) { if ( (Xi!=X->end()) && (Yi!=Y->end()) ) { if (Xi->first < Yi->first) { newMap.insert( *Xi ); Xi++; } else if (Xi->first > Yi->first) { newMap.insert( *Yi ); Yi++; } else if (Xi->second == Yi->second) { newMap.insert( *Xi ); Xi++; Yi++; } else // this does not extend goto get_out_of_while_loop_goto_tag; } else if (Xi!=X->end()) { newMap.insert( *Xi ); Xi++; } else if (Yi!=Y->end()) { newMap.insert( *Yi ); Yi++; } } newPartialSubs.push_back( newMap ); get_out_of_while_loop_goto_tag: { // this skips insertion } // goto tags apparently can't be at the end of while loops! } } // end RI loop if (newPartialSubs.empty()) return false; allPartialSubs.clear(); allPartialSubs.swap( newPartialSubs ); // TODO: Remove duplicates if they exist. This would help reduce time // wasted } // end DI and newPartialSubs loop } // TODO: if still undefined, there are some free factors. Count them on // both sides then define. for (std::list< std::map< unsigned long, NGroupExpressionTerm > >::iterator X=allPartialSubs.begin(); X!=allPartialSubs.end(); X++) { unsigned long gi=0; std::set< unsigned long > rGen; for (std::map::iterator GI=X->begin(); GI!=X->end(); GI++) { rGen.insert(GI->second.generator); if (GI->first!=gi) break; else gi++; } if ( (rGen.size()==nGenerators) && (gi==nGenerators) ) { std::vector< NGroupExpression > map(nGenerators); for (std::map::iterator GI=X->begin(); GI!=X->end(); GI++) { NGroupExpression let; let.addTermFirst( GI->first, GI->second.exponent ); map[GI->second.generator] = let; } NHomGroupPresentation invMap( other, *this, map ); if (invMap.verify()) { //std::cout<& terms( relations[l]->getTerms() ); for (std::list::iterator k=terms.begin(); k!=terms.end(); k++) { if (k->generator == i) { k->generator = j; retval = true; } else if (k->generator == j) { k->generator = i; retval = true; } } } return retval; } bool NGroupPresentation::nielsenInvert(unsigned long i) { bool retval=false; for (unsigned long l=0; l& terms(relations[l]->getTerms()); for (std::list::iterator k=terms.begin(); k!=terms.end(); k++) { if (k->generator == i) { k->exponent=(-k->exponent); retval = true; } } } return retval; } bool NGroupPresentation::nielsenCombine(unsigned long i, unsigned long j, long k, bool rightMult) { if (k == 0) return false; // replace ri with (ri)(rj)^(-k) bool retval(false); NGroupExpression let; if (rightMult) { let.addTermFirst(i, 1); let.addTermLast(j, -k); } else { let.addTermLast(i, 1); let.addTermFirst(j, -k); } for (unsigned long q=0; qsubstitute(i, let, true)) retval = true; return retval; } // these macros are used only in the identifyExtensionOverZ routine below. #define idx(gen, cov) ((unsigned long)((gen)-1)+nGm1*(cov)) #define unidx(dat) std::pair(((dat) % nGm1)+1, (dat)/nGm1) // if presentation is of a group that can bet written as an extension // 0 --> A --> G --> Z --> 0 // this routine is to change the presentation to appear to be such a split // extension. // // TODO: at present it will not declare presentations of the form: // < a, b | a^5, bab^-1=a^2 > extensions over Z, because of the // a^2 term. Should fix this. But how to do it in any generality? // Perhaps multiply conjugating automorphisms, to deduce // < a, b | a^5, bab^-1=a^2, ba^2b^-1=a^4=a^-1 > etc... // Short-term we can recognise the fibre as being abelian and check // invertibility using HomMarkedAbelianGroup routines. // std::auto_ptr< NHomGroupPresentation > NGroupPresentation::identifyExtensionOverZ() { // step 1: let's build the abelianization homomorphism. homologicalAlignment(); std::auto_ptr< NMarkedAbelianGroup > abelianized( markedAbelianisation() ); if (abelianized->getRank() != 1) return std::auto_ptr< NHomGroupPresentation >(NULL); if (abelianized->getNumberOfInvariantFactors()>0) // put Z generator at 0-th nielsenTransposition(0, abelianized->getNumberOfInvariantFactors() ); // We have the presentation of this group in the form // < a, g1, g2, ..., gn | r1, ..., rm > with a->1, gi->0 under abelianization // // step 2: An infinite presentation of the kernel of the map to Z is given // by < g1i, g2i, ..., gni | r1i, ..., rmi > for all lifts i of the generators // and relators above, after collapsing "a". We can collapse this to a finite // presentation if and only if unique max and minima (in the Z cover) exist // among the lifted relators. So we check for that. // lifts stores the lifts of the ri's, after crushing the lifts of the a's. std::vector< std::list< std::pair< NGroupExpressionTerm, signed long > > > lifts( relations.size() ); // the following max/minKiller give a list of the found pairs // (generator index, relator index) to keep track of which relators we can // use to kill generators (in the covering space). std::map< unsigned long, unsigned long > maxKiller; std::map< unsigned long, unsigned long > minKiller; std::map< unsigned long, unsigned long > cellWidth; // 2-cell width in cover for (unsigned long l=0; l& terms(relations[l]->getTerms()); for (std::list::reverse_iterator k=terms.rbegin(); k!=terms.rend(); k++) { // right to left through the relator if (k->generator > 0) { lifts[l].push_back( std::pair< NGroupExpressionTerm, signed long > ( *k, lift ) ); // special case if maxCell and minCell not yet initialized. if (maxCell==0) { maxLift = lift; minLift = lift; maxCell = k->generator; minCell = k->generator; dupMax = (labs(k->exponent)==1) ? false : true; dupMin = (labs(k->exponent)==1) ? false : true; } else { // back to regular case if (lift > maxLift) { maxLift = lift; dupMax = (labs(k->exponent)==1) ? false : true; maxCell = k->generator; } else if (lift==maxLift) { dupMax = true; } if (lift < minLift) { minLift = lift; dupMin = (labs(k->exponent)==1) ? false : true; minCell = k->generator; } else if (lift==minLift) { dupMin = true; } } } else lift += k->exponent; } // maxCell and minCell have to be non-zero at this point. cellWidth[l] = (unsigned long)(maxLift - minLift); if ( (maxCell!=0) && (!dupMax) ) { std::map< unsigned long, unsigned long>::iterator I=maxKiller.find(maxCell); if (I!=maxKiller.end()) { // compare the current maxKiller[maxCell] to l. if (cellWidth[l] > cellWidth[ I->second ]) maxKiller[maxCell]=l; } else maxKiller[maxCell]=l; } if ( (minCell!=0) && (!dupMin) ) { std::map< unsigned long, unsigned long>::iterator I=minKiller.find(minCell); if (I!=minKiller.end()) { // compare the current maxKiller[minCell] to l. if (cellWidth[l] > cellWidth[ I->second ]) minKiller[minCell]=l; } minKiller[minCell]=l; } // now let's readjust the relator so that its minLift is at level 0. if (minLift != 0) { relations[l]->addTermFirst(0, minLift); relations[l]->addTermLast(0, -minLift); relations[l]->simplify(); for (std::list >::iterator I=lifts[l].begin(); I!=lifts[l].end(); I++) I->second -= minLift; // adjust the lifts to have min lift 0 } // cyclically permute lifts so that the max-weight rep appears first while (lifts[l].front().second != cellWidth[l]) { std::pair< NGroupExpressionTerm, signed long > temp(lifts[l].front()); lifts[l].pop_front(); lifts[l].push_back( temp ); } // ensure word starts with highest-weight element as inverted. if (lifts[l].front().first.exponent == 1) { std::pair< NGroupExpressionTerm, signed long > temp(lifts[l].front()); lifts[l].pop_front(); lifts[l].reverse(); lifts[l].push_front(temp); // now run and change the exponents for (std::list< std::pair >::iterator I=lifts[l].begin(); I!=lifts[l].end(); I++) I->first.exponent = -I->first.exponent; } } // this is the test for whether or not we can find a finite collection of // generators unsigned long nGm1( nGenerators - 1 ); if ( (maxKiller.size() != nGm1) || (minKiller.size() != nGm1) ) return std::auto_ptr< NHomGroupPresentation >(NULL); unsigned long maxWidth(0); unsigned long liftCount(0); // how many lifts of our generators do we need? for (unsigned long i=0; iliftCount) liftCount = cellWidth[maxKiller[i]]; if (cellWidth[minKiller[i]]>liftCount) liftCount = cellWidth[minKiller[i]]; } for (std::map< unsigned long, unsigned long>::iterator I=cellWidth.begin(); I!=cellWidth.end(); I++) if (I->second > maxWidth) maxWidth = I->second; // we need liftCount lifts of our generators and relators. Perhaps we should // either cite something in Magnus-Karass-Solitar for this or put in a proof. // let's build a vector that describes the relationa a(gi)a^-1 = ... // build table of reductions of the liftCount==M lift of generators. // the indexing of the generators of the kernel of G --> Z will be handled // by the above idx and unidx macros. std::map genKiller; // start with the liftCount lift, i.e. the first order reducers a^-Mg_ia^M =... for (unsigned long i=1; i >::iterator I=lifts[maxKiller[i]].begin(); I!=lifts[maxKiller[i]].end(); I++) { if (I==lifts[maxKiller[i]].begin()) { // push up delta sheets so that it kills appropriately delta = (unsigned long)(liftCount - I->second); continue; } temp.addTermFirst( NGroupExpressionTerm( idx( I->first.generator, I->second + delta ), I->first.exponent ) ); } genKiller.insert( std::pair< unsigned long, NGroupExpression > (idx(i,liftCount),temp) ); } // extra genKillers -- sometimes there are wider words than the killing words. // like with presentations such as: // < a b | b a^-1 b a^-1 b^-1 a^2, a^-3 b^2 a^3 b^2 > // We could alternatively use the genKiller to reduce the width of the other // relators. But for now we use this less-sophisticated work-around. for (unsigned long j=liftCount; j::iterator I=tempW.getTerms().begin(); I!=tempW.getTerms().end(); I++) I->generator += nGm1; for (std::map::iterator J=genKiller.begin(); J!=genKiller.end(); J++) tempW.substitute( J->first, J->second, false ); genKiller.insert( std::pair< unsigned long, NGroupExpression > (idx(i,j+1), tempW) ); } } // initialize tempTable with the 0-th lifts of the relators. std::list< NGroupExpression > tempTable; NGroupPresentation kerPres; kerPres.addGenerator( liftCount * nGm1 ); for (unsigned long i=0; i >::iterator I=lifts[i].begin(); I!=lifts[i].end(); I++) temp.addTermFirst( NGroupExpressionTerm( idx( I->first.generator, I->second ), I->first.exponent ) ); for (std::map::iterator J=genKiller.begin(); J!=genKiller.end(); J++) temp.substitute( J->first, J->second, false ); temp.simplify(); if (temp.wordLength()>0) { tempTable.push_back(temp); kerPres.addRelation( new NGroupExpression(temp) ); } } if (!kerPres.isValid()) { std::cout<<"identifyExtensionOverZ() error:"<< " out of bounds relator in kerPres.\n"; std::cout.flush(); exit(1); } // build the reductions of the {0,1,...,liftCount-1} translates of **all** // the relators from the group, and assemble them into the relators of the // kernel. for (unsigned long M=0; M::iterator I=tempTable.begin(); I != tempTable.end(); I++) { std::list< NGroupExpressionTerm >& It(I->getTerms() ); for (std::list::iterator J=It.begin(); J!=It.end(); J++) J->generator += nGm1; // this depends on choice of idx function for (std::map::iterator J=genKiller.begin(); J!=genKiller.end(); J++) I->substitute( J->first, J->second, false ); // apply genKiller to reduce the words, and push to presentation kerPres.addRelation( new NGroupExpression( *I ) ); } } // replace this presentation by the semi-direct product presentation. std::vector autVec; autVec.resize( nGm1*liftCount ); for (unsigned long i=0; i= nGm1*(liftCount-1) ) autVec[i] = genKiller[i+nGm1]; else { NGroupExpression temp; temp.addTermFirst( i+nGm1, 1 ); autVec[i] = temp; } std::auto_ptr< NHomGroupPresentation > retval(new NHomGroupPresentation( kerPres, kerPres, autVec ) ); retval->intelligentSimplify(); // Modify this presentation to reflect the semi-direct product // structure we've discovered! // deallocate relations, and resize and repopulate with copies of kerPres's // relations. nGenerators = retval->getDomain().nGenerators + 1; for (unsigned long i=0; igetDomain().nGenerators + retval->getDomain().relations.size() ); for (unsigned long i=0; igetDomain().relations.size(); i++) relations[i] = new NGroupExpression( *retval->getDomain().relations[i] ); // And now all the b^-1g_ib = genKiller(i) and b^-1g_ib = g_{i+1} relations. for (unsigned long i=0; igetDomain().nGenerators; i++) { NGroupExpression* temp; temp = new NGroupExpression( retval->evaluate(i) ); temp->addTermFirst( retval->getDomain().nGenerators, 1); temp->addTermFirst( i, -1); temp->addTermFirst( retval->getDomain().nGenerators, -1); relations[ i+retval->getDomain().relations.size() ] = temp; } return std::auto_ptr< NHomGroupPresentation >( retval ); } bool NGroupPresentation::isValid() const { for (unsigned long i=0; i::const_iterator j=relations[i]->getTerms().begin(); j!=relations[i]->getTerms().end(); j++) if (j->generator >= nGenerators) return false; return true; } /* * This is an entirely cosmetic re-writing of the presentation, is * fast and superficial. * 1) It inverts relators if net sign of the generators is negative. * 2) It cyclically permutes relators to start with smallest gen. * 3) It sorts the relators by number of generator indices that * appear, followed by relator numbers (lexico) followed by * relator length. * 4) Makes elementary simplifications to aid in seeing standard * relators like commutators. */ namespace { // anonymous namespace bool compare_words(const NGroupExpression* first, const NGroupExpression* second) { // compute number of letters used std::set usedTermsF, usedTermsS; for (std::list::const_iterator j=first->getTerms().begin(); j!=first->getTerms().end(); j++) usedTermsF.insert( j->generator ); for (std::list::const_iterator j=second->getTerms().begin(); j!=second->getTerms().end(); j++) usedTermsS.insert( j->generator ); if (usedTermsF.size() < usedTermsS.size()) return true; if (usedTermsF.size() > usedTermsS.size()) return false; // have all the same terms, sort lexicographically on which terms used std::set::iterator i=usedTermsF.begin(); std::set::iterator j=usedTermsS.begin(); while (i != usedTermsF.end()) { if (*i < *j) return true; if (*i > *j) return false; i++; j++; } // the two words first and second use exactly the same letters. if (first->wordLength() < second->wordLength()) return true; if (first->wordLength() > second->wordLength()) return false; if (first->getNumberOfTerms() < second->getNumberOfTerms()) return true; if (first->getNumberOfTerms() > second->getNumberOfTerms()) return false; // now we can compare them lexicographically, letter by letter. // first we lay them out one letter at a time. std::vector< NGroupExpressionTerm > first_word_vec( 0 ); std::vector< NGroupExpressionTerm > second_word_vec( 0 ); first_word_vec.reserve( first->wordLength() ); second_word_vec.reserve( second->wordLength() ); std::list::const_iterator it; for (it = first->getTerms().begin(); it!=first->getTerms().end(); it++) { for (unsigned long I=0; I0) ? 1 : -1 ) ); } for (it = second->getTerms().begin(); it!=second->getTerms().end(); it++) { for (unsigned long I=0; I0) ? 1 : -1 ) ); } // now we compare termwise for (unsigned long I=0; I second_word_vec[I].generator) return false; if (first_word_vec[I].exponent < second_word_vec[I].exponent) return true; if (first_word_vec[I].exponent > second_word_vec[I].exponent) return false; } // exactly the same words. return false; } } // end anonymous namespace bool NGroupPresentation::prettyRewriting() { return prettyRewritingDetail().get(); } // this routine iteratively finds length 1 relators, and uses them to simplify // other relators. In the end it deletes all length 0 relators and re-indexes. std::auto_ptr NGroupPresentation::prettyRewritingDetail() { // keep the relators in a list for now. std::list relatorPile; for (unsigned long i=0; i::iterator it; for ( it = relatorPile.begin(); it != relatorPile.end(); it++ ) (*it)->simplify(true); std::set genToDel; // generators we've eliminated bool reloopFlag(true); while (reloopFlag) { reloopFlag=false; std::set newGenDel; for ( it = relatorPile.begin(); it != relatorPile.end(); it++ ) { if ((*it)->getNumberOfTerms() == 1) if ( abs( (*it)->getTerms().front().exponent ) == 1 ) { // a killer! newGenDel.insert( (*it)->getTerms().front().generator ); } } genToDel.insert( newGenDel.begin(), newGenDel.end() ); for (std::set::iterator i=newGenDel.begin(); i!=newGenDel.end(); i++) for (it=relatorPile.begin(); it!=relatorPile.end(); it++) if ((*it)->substitute(*i, NGroupExpression(), true )) reloopFlag=true; } relations.clear(); relations.reserve( relatorPile.size() - genToDel.size() ); for (it = relatorPile.begin(); it!=relatorPile.end(); it++) { if ( (*it)->getNumberOfTerms()>0 ) relations.push_back( *it ); else delete (*it); } relatorPile.clear(); for (unsigned long i=0; i redMap; if (genToDel.size()>0) { std::set< unsigned long > interval, compDelete; // complement for (unsigned long i=0; i1 subs on all // relators, and gk --> gk-1 for larger generators. std::vector< NGroupExpression > downSub(nGenerators); std::vector< NGroupExpression > upSub(nGenerators - genToDel.size()); unsigned long i=0; for (std::set::iterator I=compDelete.begin(); I!=compDelete.end(); I++) { upSub[i].addTermFirst( NGroupExpressionTerm( (*I), 1 ) ); downSub[*I].addTermFirst( NGroupExpressionTerm( i, 1 ) ); // might as well perform downSub now on all relators. for (it=relatorPile.begin(); it!=relatorPile.end(); it++) (*it)->substitute( *I, downSub[*I], true); i++; } nGenerators -= genToDel.size(); // assemble the reduction map redMap.reset( new NHomGroupPresentation( oldPres, *this, downSub, upSub ) ); } // step 2: sort by number of letters present, followed by word length // to do this, we build a list of relators and a sorting criterion. relatorPile.sort(compare_words); relations.clear(); relations.reserve(relatorPile.size()); for (it = relatorPile.begin(); it!=relatorPile.end(); it++) relations.push_back( *it ); // step 3: if there is a relator with net sign < 0, invert it for (unsigned long i=0; i::iterator j=relations[i]->getTerms().begin(); j!=relations[i]->getTerms().end(); j++) sig += j->exponent; if (sig < 0) relations[i]->invert(); } // step 4: for each generator find first relator where it appears with non-zero // weight, if negative, invert the generator. // TODO maybe... // step 5: cyclically permute to start with a lexicographically smallest // term for (unsigned long i=0; igetNumberOfTerms()>0) { // form list of all terms involved, find smallest, cyclically permute to // start with that one. std::set usedTerms; for (std::list::iterator j=relations[i]->getTerms().begin(); j!=relations[i]->getTerms().end(); j++) usedTerms.insert( j->generator ); unsigned long smallestGen( *usedTerms.begin() ); while ( relations[i]->getTerm(0).generator != smallestGen ) relations[i]->cycleRight(); } return std::auto_ptr( redMap.release() ); } ////////////////// ALL INPUT / OUTPUT routines below ////////////////////// // XML output void NGroupPresentation::writeXMLData(std::ostream& out) const { out << "\n"; for (RelIteratorConst it = relations.begin(); it != relations.end(); it++) { out << " "; (*it)->writeXMLData(out); out << '\n'; } out << "\n"; } void NGroupExpression::writeXMLData(std::ostream& out) const { out << " "; for (TermIteratorConst it = terms.begin(); it != terms.end(); it++) out << (*it).generator << '^' << (*it).exponent << ' '; out << ""; } // group expression output routines void NGroupExpression::writeText(std::ostream& out, bool shortword) const { if (terms.empty()) out << '1'; else { std::list::const_iterator i; for (i = terms.begin(); i!=terms.end(); i++) { if (i != terms.begin()) out << ' '; if (shortword) out << char('a' + i->generator); else out << "g_" << i->generator; if ( i->exponent != 1 ) out << '^' << i->exponent; } } } std::string NGroupExpression::toTeX() const { std::ostringstream out; writeTeX(out); return out.str(); } void NGroupExpression::writeTeX(std::ostream& out) const { if (terms.empty()) out << 'e'; else { std::list::const_iterator i; for (i = terms.begin(); i!=terms.end(); i++) { out << "g_{" << i->generator << '}'; if ( i->exponent != 1 ) out << "^{" << i->exponent << '}'; } } } void NGroupExpression::writeTextShort(std::ostream& out) const { if (terms.empty()) out << '1'; else { TermIteratorConst last = --terms.end(); copy(terms.begin(), last, std::ostream_iterator(out, " ")); out << *last; } } // presentation output routines below std::string NGroupPresentation::toTeX() const { std::ostringstream out; writeTeX(out); return out.str(); } void NGroupPresentation::writeTeX(std::ostream& out) const { out << "\\langle "; if (nGenerators == 0) out << "\\cdot"; else if (nGenerators == 1) out << "g_0"; else if (nGenerators == 2) out << "g_0, g_1"; else { out << "g0, \\cdots, g" <<(nGenerators - 1); } out << " | "; if (relations.empty()) out << "\\cdot"; else for (RelIteratorConst it = relations.begin(); it != relations.end(); it++) { if (it != relations.begin()) out << ", "; (*it)->writeTeX(out); } out << " \\rangle"; } void NGroupPresentation::writeTextLong(std::ostream& out) const { out << "Generators: "; if (nGenerators == 0) out << "(none)"; else if (nGenerators == 1) out << "a"; else if (nGenerators == 2) out << "a, b"; else if (nGenerators <= 26) out << "a .. " << char('a' + nGenerators - 1); else out << "g0 .. g" << (nGenerators - 1); out << std::endl; out << "Relations:\n"; if (relations.empty()) out << " (none)\n"; else for (RelIteratorConst it = relations.begin(); it != relations.end(); it++) { out << " "; (*it)->writeText(out, nGenerators <= 26); out << std::endl; } } std::string NGroupPresentation::toStringCompact() const { std::ostringstream out; writeTextCompact(out); return out.str(); } std::string NGroupPresentation::compact() const { std::ostringstream out; writeTextCompact(out); return out.str(); } void NGroupPresentation::writeTextCompact(std::ostream& out) const { if (nGenerators == 0) { out << "< >"; return; } out << "<"; if (nGenerators <= 26) { for (unsigned long i=0; i"; return; } out << " | "; for (RelIteratorConst it = relations.begin(); it != relations.end(); it++) { if (it != relations.begin()) out << ", "; (*it)->writeText(out, nGenerators <= 26); } out << " >"; } // We will go through, apply dehnAlgSubMetric look for substitutions, // then apply all of them within a reasonable length. // if user requests we will go further and do a 2nd iteration with more care... // depth==1 by default. void NGroupPresentation::proliferateRelators(unsigned long depth) { std::list< NGroupExpression* > newRels; for (unsigned long i=0; i sub_list; dehnAlgorithmSubMetric( *(relations[i]), *(relations[j]), sub_list, depth ); while (!sub_list.empty()) { NGroupExpression* newRel( new NGroupExpression( *(relations[i]) ) ); applySubstitution( *newRel, *(relations[j]), *sub_list.begin() ); sub_list.erase( sub_list.begin() ); newRels.push_back(newRel); } } depth--; while (depth>0) { std::list< NGroupExpression* > tempRels; for (unsigned long i=0; i::iterator j=newRels.begin(); j!=newRels.end(); j++) { // attempt to tack relation[i] to *j. To do this, we should perhaps // keep a record of how *j was created, as in where the two junction // points are so as to ensure what we're adding spans at least one // of the junctions. std::set< NWordSubstitutionData > sub_list; dehnAlgorithmSubMetric( **j, *(relations[i]), sub_list, depth ); while (!sub_list.empty()) { // TODO: we might want to avoid some obviously repetitive subs // as noted above? NGroupExpression* newRel( new NGroupExpression( *(*j) ) ); applySubstitution( *newRel, *(relations[i]), *sub_list.begin() ); sub_list.erase( sub_list.begin() ); tempRels.push_back(newRel); } } depth--; while (!tempRels.empty()) { newRels.push_back( *tempRels.begin() ); tempRels.erase( tempRels.begin() ); } } while (!newRels.empty()) { relations.push_back( newRels.front() ); newRels.pop_front(); } } } // namespace regina regina-4.96/engine/algebra/ngrouppresentation.h000644 000765 000024 00000175332 12400006716 021600 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file algebra/ngrouppresentation.h * \brief Deals with finite presentations of groups. */ #ifndef __NGROUPPRESENTATION_H #ifndef __DOXYGEN #define __NGROUPPRESENTATION_H #endif #include #include #include #include #include #include "regina-core.h" #include "shareableobject.h" #include "utilities/memutils.h" #include "utilities/ptrutils.h" #include "algebra/nmarkedabeliangroup.h" #include "algebra/nabeliangroup.h" namespace regina { class NAbelianGroup; class NHomGroupPresentation; class NMarkedAbelianGroup; /** * \weakgroup algebra * @{ */ /** * Represents a power of a generator in a group presentation. */ struct REGINA_API NGroupExpressionTerm { unsigned long generator; /**< The number that identifies the generator in this term. */ long exponent; /**< The exponent to which the generator is raised. */ /** * Creates a new uninitialised term. */ NGroupExpressionTerm(); /** * Creates a new term initialised to the given value. * * @param newGen the number that identifies the generator in the new term. * @param newExp the exponent to which this generator is raised. */ NGroupExpressionTerm(unsigned long newGen, long newExp); /** * Creates a new term initialised to the given value. * * @param cloneMe a term whose data will be copied to the new term. */ NGroupExpressionTerm(const NGroupExpressionTerm& cloneMe); /** * Makes this term identical to the given term. * * @param cloneMe the term whose data will be copied to this term. * @return a reference to this term. */ NGroupExpressionTerm& operator = (const NGroupExpressionTerm& cloneMe); /** * Determines whether this and the given term contain identical data. * * @param other the term with which this term will be compared. * @return \c true if and only if this and the given term have both the * same generator and exponent. */ bool operator == (const NGroupExpressionTerm& other) const; /** * Imposes an ordering on terms. * Terms are ordered lexigraphically as (generator, exponent) pairs. * * @param other the term to compare with this. * @return true if and only if this term is lexicographically * smaller than \a other. */ bool operator < (const NGroupExpressionTerm& other) const; /** * Returns the inverse of this term. The inverse has the same * generator but a negated exponent. * * Note that this term will remain unchanged. * * @return the inverse of this term. */ NGroupExpressionTerm inverse() const; /** * Attempts to merge this term with the given term. * If both terms have the same generator, the two exponents will be * added and stored in this term. If the generators are different, * this routine will do nothing. * * Note that this term might be changed but the given term will remain * unchanged. * * @param other the term to merge with this term. * @return \c true if the two terms were merged into this term, or * \c false if the two terms have different generators. */ bool operator += (const NGroupExpressionTerm& other); }; /** * Writes the given term to the given output stream. * The term will be written in the format g3^-7, where in this * example the term represents generator number 3 raised to the -7th power. * * If the term has exponent 0 or 1, the output format will be * appropriately simplified. * * @param out the output stream to which to write. * @param term the term to write. * @return a reference to the given output stream. */ REGINA_API std::ostream& operator << (std::ostream& out, const NGroupExpressionTerm& term); /** * Represents an expression involving generators from a group presentation * or a free group. An expression is represented as word, i.e, a sequence * of powers of generators all of which are multiplied in order. Each power * of a generator corresponds to an individual NGroupExpressionTerm. * * For instance, the expression g1^2 g3^-1 g6 contains the * three terms g1^2, g3^-1 and g6^1 in that * order. */ class REGINA_API NGroupExpression : public ShareableObject { private: std::list terms; /** The terms that make up this expression. */ public: /** * Creates a new expression with no terms. */ NGroupExpression(); /** * Creates a new expression that is a clone of the given * expression. * * @param cloneMe the expression to clone. */ NGroupExpression(const NGroupExpression& cloneMe); /** * Attempts to interpret the given input string as a word in a group. * Regina can recognise strings in the following four basic forms: * * - \c a^7b^-2 * - \c aaaaaaaBB * - \c a^7B^2 * - \c g0^7g1^-2 * * The string may contain whitespace, which will simply be ignored. * * The argument \a valid may be \c null, but if it is non-null * then the boolean it points to will be used for error reporting. * This routine sets valid to \c true if the string was successfully * interpreted, or \c false if the algorithm failed to interpret the * string. * * Regardless of whether \a valid is \c null, if the string * could not be interpreted then this expression will be initialised * to the trivial word. * * \ifacespython The second argument \a valid is not present, * and will be assumed to be \c null. * * @param input the input string that is to be interpreted. * @param valid used for error reporting as described above, or * \c null if no error reporting is required. */ NGroupExpression(const std::string &input, bool* valid=NULL); /** * Makes this expression a clone of the given expression. * * @param cloneMe the expression to clone. * @return a reference to this expression. */ NGroupExpression& operator = (const NGroupExpression& cloneMe); /** * Equality operator. Checks to see whether or not these two words * represent the same literal string. * * @param comp the expression to compare against this. * @return \c true if this and the given string literal are identical. */ bool operator == (const NGroupExpression& comp) const; /** * Returns the list of terms in this expression. * These are the actual terms stored internally; any * modifications made to this list will show up in the * expression itself. * * For instance, the expression g1^2 g3^-1 g6 has list * consisting of three terms g1^2, g3^-1 and * g6^1 in that order. * * \ifacespython Not present; only the const version of this * routine is available. * * @return the list of terms. */ std::list& getTerms(); /** * Returns a constant reference to the list of terms in this * expression. * * For instance, the expression g1^2 g3^-1 g6 has list * consisting of three terms g1^2, g3^-1 and * g6^1 in that order. * * \ifacespython This routine returns a python list of copied * NGroupExpressionTerm objects. In particular, modifying this * list or the terms within it will not modify the group * expression from which they came. * * @return the list of terms. */ const std::list& getTerms() const; /** * Returns the number of terms in this expression. * * For instance, the expression g1^2 g3^-1 g6 contains three * terms. See also getWordLength(). * * @return the number of terms. */ unsigned long getNumberOfTerms() const; /** * Returns the length of the word, i.e. the number of letters * with exponent +1 or -1 for which this word is expressable as a * product. * * For instance, the expression g1^2 g3^-1 g6 is a word of * length four. See also getNumberOfTerms(). * * No attempt is made to remove redundant terms (so the word * g g^-1 will count as length two). * * @return the length of the word. */ unsigned long wordLength() const; /** * Tests whether this is the trivial (unit) word. * * No attempt is made to remove redundant terms (so the word * g g^-1 will be treated as non-trivial). * * @return \c true if and only if this is the trivial word. */ bool isTrivial() const; /** * Erases all terms from this this word. * This effectively turns this word into the identity element. */ void erase(); /** * Returns the term at the given index in this expression. * Index 0 represents the first term, index 1 * represents the second term and so on. * * \warning This routine is O(n) where \a n is the number * of terms in this expression. * * @param index the index of the term to return; this must be * between 0 and getNumberOfTerms()-1 inclusive. * @return the requested term. */ NGroupExpressionTerm& getTerm(unsigned long index); /** * Returns a constant reference to the term at the given * index in this expression. * Index 0 represents the first term, index 1 * represents the second term and so on. * * \warning This routine is O(n) where \a n is the number * of terms in this expression. * * \ifacespython Not present; only the non-const version of this * routine is available. * * @param index the index of the term to return; this must be * between 0 and getNumberOfTerms()-1 inclusive. * @return the requested term. */ const NGroupExpressionTerm& getTerm(unsigned long index) const; /** * Returns the generator corresonding to the * term at the given index in this expression. * Index 0 represents the first term, index 1 * represents the second term and so on. * * \warning This routine is O(n) where \a n is the number * of terms in this expression. * * @param index the index of the term to return; this must be * between 0 and getNumberOfTerms()-1 inclusive. * @return the number of the requested generator. */ unsigned long getGenerator(unsigned long index) const; /** * Returns the exponent corresonding to the * term at the given index in this expression. * Index 0 represents the first term, index 1 * represents the second term and so on. * * \warning This routine is O(n) where \a n is the number * of terms in this expression. * * @param index the index of the term to return; this must be * between 0 and getNumberOfTerms()-1 inclusive. * @return the requested exponent. */ long getExponent(unsigned long index) const; /** * Adds the given term to the beginning of this expression. * * @param term the term to add. */ void addTermFirst(const NGroupExpressionTerm& term); /** * Adds the given term to the beginning of this expression. * * @param generator the number of the generator corresponding to * the new term. * @param exponent the exponent to which the given generator is * raised. */ void addTermFirst(unsigned long generator, long exponent); /** * Adds the given term to the end of this expression. * * @param term the term to add. */ void addTermLast(const NGroupExpressionTerm& term); /** * Adds the given term to the end of this expression. * * @param generator the number of the generator corresponding to * the new term. * @param exponent the exponent to which the given generator is * raised. */ void addTermLast(unsigned long generator, long exponent); /** * Multiplies this expression on the left by the given word. * This expression will be modified directly. * * @param word the word to multiply with this expression. */ void addTermsFirst(const NGroupExpression& word); /** * Multiplies this expression on the right by the given word. * This expression will be modified directly. * * @param word the word to multiply with this expression. */ void addTermsLast(const NGroupExpression& word); /** * Multiplies this expression on the left by the word * respresented by the given string. * * See the string-based constructor * NGroupExpression(const std::string&, bool*) for further * information on how this string should be formatted. * * If the given string cannot be interpreted as a word in a group, * then this expression will be left untouched. * * @param input a string representation of the word to multiply with * this expression. * @return \c true if the given string could interpreted * (and therefore the multiplication was completed successfully), or * \c false if the given string could not be interpreted * (in which case this expression will be left untouched). */ bool addStringFirst(const std::string& input); /** * Multiplies this expression on the right by the word * respresented by the given string. * * See the string-based constructor * NGroupExpression(const std::string&, bool*) for further * information on how this string should be formatted. * * If the given string cannot be interpreted as a word in a group, * then this expression will be left untouched. * * @param input a string representation of the word to multiply with * this expression. * @return \c true if the given string could interpreted * (and therefore the multiplication was completed successfully), or * \c false if the given string could not be interpreted * (in which case this expression will be left untouched). */ bool addStringLast(const std::string& input); /** * Cycles this word by moving the leftmost term around to the rightmost. * All other terms shift one step to the left. * * If the word is of the form * g_i1^j1 g_i2^j2 ... g_in^jn, * this converts it into the word * g_i2^j2 ... g_in^jn g_i1^j1. */ void cycleRight(); /** * Cycles this word by moving the rightmost term around to the leftmost. * All other terms shift one step to the right. * * If the word is of the form * g_i1^j1 g_i2^j2 ... g_in^jn, * this converts it into the word * g_in^jn g_i1^j1 g_i1^j1 ... g_in-1^jn-1. */ void cycleLeft(); /** * Returns a newly created expression that is the inverse of * this expression. The terms will be reversed and the * exponents negated. * * @return the inverse of this expression. */ NGroupExpression* inverse() const; /** * Inverts this expression. Does not allocate or deallocate anything. */ void invert(); /** * Returns a newly created expression that is * this expression raised to the given power. * Note that the given exponent may be positive, zero or negative. * * @param exponent the power to which this expression should be raised. * @return this expression raised to the given power. */ NGroupExpression* power(long exponent) const; /** * Simplifies this expression. * Adjacent powers of the same generator will be combined, and * terms with an exponent of zero will be removed. * Note that it is \e not assumed that the underlying group is * abelian. * * You may declare that the expression is cyclic, in which case * it is assumed that terms may be moved from the back to the * front and vice versa. Thus expression g1 g2 g1 g2 g1 * simplifies to g1^2 g2 g1 g2 if it is cyclic, but does not * simplify at all if it is not cyclic. * * @param cyclic \c true if and only if the expression may be * assumed to be cyclic. * @return \c true if and only if this expression was changed. */ bool simplify(bool cyclic = false); /** * Replaces every occurrence of the given generator with the * given substite expression. If the given generator was found, * the expression will be simplified once the substitution is * complete. * * @param generator the generator to be replaced. * @param expansion the substitute expression that will replace * every occurrence of the given generator. * @param cyclic \c true if and only if the expression may be * assumed to be cyclic; see simplify() for further details. * @return \c true if and only if any substitutions were made. */ bool substitute(unsigned long generator, const NGroupExpression& expansion, bool cyclic = false); /** * Determines whether or not one can relabel the generators in * this word to obtain the given other word. If so, returns a non-empty * list of all such relabellings. If not, returns an empty list. * * Relabellings are partially-defined permutations on the * generator set, also allowing for possible inversions if * cyclic is \c true. * * \apinotfinal * * \todo Change this to use less heavyweight types and less deep * copying. * * \pre If \a cyclic is \c true, then both this word and \a other * have been cyclically reduced. * * \ifacespython Not present. * * @param other the word to compare against this. * @param cyclic if \c false we get a list of exact relabellings from * this word to \a other. If \c true, it can be up to cyclic * permutation and inversion. * @return a list of permutations, implemented as maps from * generator indices of this word to generator indices of \a other. */ std::list< std::map< unsigned long, NGroupExpressionTerm > > relabellingsThisToOther( const NGroupExpression &other, bool cyclic=false ) const; /** * Writes a chunk of XML containing this expression. * * \ifacespython Not present. * * @param out the output stream to which the XML should be written. */ void writeXMLData(std::ostream& out) const; /** * Returns a TeX representation of this expression. * See writeTeX() for details on how this is formed. * * @return a TeX representation of this expression. */ std::string toTeX() const; /** * Writes a TeX represesentation of this expression to the given * output stream. * * The text representation will be of the form * g_2^4 g_{13}^{-5} g_4. * * \ifacespython The parameter \a out does not exist; * standard output will be used. * * @param out the output stream to which to write. */ void writeTeX(std::ostream& out) const; /** * Writes a text representation of this expression to the given * output stream, using either numbered generators or * alphabetic generators. * * The text representation will be of the form * g2^4 g13^-5 g4. If the shortword flag is * true, it will assume your word is in an alphabet of * no more than 26 letters, and will write the word using * lower-case ASCII, i.e. c^4 n^-5 e. * * \pre If \a shortword is \c true, the number of generators in * the corresponding group must be 26 or fewer. * * \ifacespython The parameter \a out does not exist; * standard output will be used. * * @param out the output stream to which to write. * @param shortword indicates whether to use numbered or * alphabetic generators, as described above. */ void writeText(std::ostream& out, bool shortword=false) const; /** * The text representation will be of the form * g2^4 g13^-5 g4. */ virtual void writeTextShort(std::ostream& out) const; }; /** * Represents a finite presentation of a group. * * A presentation consists of a number of generators and a set of * relations between these generators that together define the group. * * If there are \a g generators, they will be numbered 0, 1, ..., g-1. * * \todo Let's make intelligent simplify a tad more intelligent, and the GUI * call a bit more safe. Perhaps parallelize the GUI call, and give users * parameters to ensure it won't crash the computer. Also look at the FPGroup * package. We should also have a simple way of creating NGroupPresentation * objects directly from text strings. We would like to have something like * NGroupPresentation( numGens, "abAAB", "bccd" ) etc., with arbitrary * numbers of relators. Maybe std::tuple. Or "variadic templates"? */ class REGINA_API NGroupPresentation : public ShareableObject { protected: unsigned long nGenerators; /**< The number of generators. */ std::vector relations; /**< The relations between the generators. */ public: /** * Creates a new presentation with no generators and no * relations. */ NGroupPresentation(); /** * Creates a clone of the given group presentation. * * @param cloneMe the presentation to clone. */ NGroupPresentation(const NGroupPresentation& cloneMe); /** * Constructor that allows you to directly pass an arbitrary number * of relators in string format. * * The first argument \a nGens is the number of generators one wants * the group to have. The second argument \a rels is a vector * of strings, where each string gives a single relator. See * the NGroupExpression::NGroupExpression(const std::string&, bool*) * constructor notes for information on what format these strings * can take. * * If any of the given strings could not be interpreted as * words, this routine will insert the trivial (unit) word in * its place. * * If you are compiling Regina against C++11, you can use the * C++11 initializer_list construction to construct an * NGroupPresentation directly using syntax of the form * NGroupPresentation(nGens, { "rel1", "rel2", ... }). * * \ifacespython Not present. * * @param nGens the number of generators. * @param rels a vector of relations each given in string form, * as outlined above. */ NGroupPresentation(unsigned long nGens, const std::vector &rels); /** * Destroys the group presentation. * All relations that are stored will be deallocated. */ virtual ~NGroupPresentation(); /** * Assignment operator. * * @param cloneMe the group presentation that this will become a * copy of. * @return a reference to this group presentation. */ NGroupPresentation& operator=(const NGroupPresentation& cloneMe); /** * Adds one or more generators to the group presentation. * If the new presentation has \a g generators, the new * generators will be numbered g-1, g-2 and so on. * * @param numToAdd the number of generators to add. * @return the number of generators in the new presentation. */ unsigned long addGenerator(unsigned long numToAdd = 1); /** * Adds the given relation to the group presentation. * The relation must be of the form expression = 1. * * This presentation will take ownership of the given * expression, may change it and will be responsible for its * deallocation. * * \warning This routine does not check whether or not your relation * is a word only in the generators of this group. In other * words, it does not stop you from using generators beyond the * getNumberOfGenerators() bound. * * \ifacespython Since this group presentation takes ownership * of the given expression, the python object containing the * given expression becomes a null object and should no longer * be used. * * @param rel the expression that the relation sets to 1; for * instance, if the relation is g1^2 g2 = 1 then this * parameter should be the expression g1^2 g2. */ void addRelation(NGroupExpression* rel); /** * Returns the number of generators in this group presentation. * * @return the number of generators. */ unsigned long getNumberOfGenerators() const; /** * Returns the number of relations in this group presentation. * * @return the number of relations. */ unsigned long getNumberOfRelations() const; /** * Returns the relation at the given index in this group * presentation. The relation will be of the form expresson * = 1. * * @param index the index of the desired relation; this must be * between 0 and getNumberOfRelations()-1 inclusive. * * @return the expression that the requested relation sets to 1; * for instance, if the relation is g1^2 g2 = 1 then * this will be the expression g1^2 g2. */ const NGroupExpression& getRelation(unsigned long index) const; /** * Tests whether all of the relations for the group are indeed words * in the generators. This routine returns \c false if at least * one relator uses an out-of-bound generator, and \c true otherwise. * * This routine is intended only for sanity checking: you should * never have an invalid group presentation in the first place. * * @return \c true if and only if all of the relations are words * in the generators. */ bool isValid() const; /** * Attempts to simplify the group presentation as intelligently * as possible without further input. * * See intelligentSimplifyDetail() for further details on how * the simplification is done. * * @return \c true if and only if the group presentation was changed. * You can call intelligentSimplifyDetail() to get the isomorphism. */ bool intelligentSimplify(); /** * Attempts to simplify the group presentation as intelligently * as possible without further input. * * The current simplification method uses a combination of small * cancellation theory and Nielsen moves. * * If this routine does return a homomorphism (because the * presentation was changed), then this homomorphsm will in fact be * a declared isomorphism. See the NHomGroupPresentation class * notes for details on what this means. * * @return a newly allocated homomorphism describing the * reduction map from the original presentation to the new * presentation, or a null pointer if this presentation was not * changed. */ std::auto_ptr intelligentSimplifyDetail(); /** * Attempts to simplify the group presentation using only small * cancellation theory. * * See smallCancellationDetail() for further details on how * the simplification is done. * * @return \c true if and only if the group presentation was changed. * You can call smallCancellationDetail() to get the isomorphism. */ bool smallCancellation(); /** * Attempts to simplify the group presentation using small cancellation * theory. The simplification method is based on the Dehn algorithm * for hyperbolic groups, i.e. small cancellation theory. This means * we look to see if part of one relator can be used to simplify * others. If so, make the substitution and simplify. We continue * until no more presentation-shortening substitutions are available. * We follow that by killing any available generators using words * where generators appear a single time. * * If this routine does return a homomorphism (because the * presentation was changed), then this homomorphsm will in fact be * a declared isomorphism. See the NHomGroupPresentation class * notes for details on what this means. * * \todo \optlong This routine could use some small tweaks - * recognition of utility of some score==0 moves, such as * commutators, for example. * * @return a newly allocated homomorphism describing the * reduction map from the original presentation to the new * presentation, or a null pointer if this presentation was not * changed. */ std::auto_ptr smallCancellationDetail(); /** * Uses small cancellation theory to reduce the input word, * using the current presentation of the group. The input word * will be modified directly. * * \warning This routine is only as good as the relator table for the * group. You might want to consider running intelligentSimplify(), * possibly in concert with proliferateRelators(), before using this * routine for any significant tasks. * * @param input is the word you would like to simplify. * This must be a word in the generators of this group. * @return \c true if and only if the input word was modified. */ bool simplifyWord(NGroupExpression &input) const; /** * A routine to help escape local wells when simplifying * presentations, which may be useful when small cancellation theory * can't find the simplest relators. * * Given a presentation <g_i | r_i>, this routine appends * consequences of the relators {r_i} to the presentation that * are of the form ab, where both a and b are cyclic permutations * of relators from the collection {r_i}. * * Passing depth=1 means it will only form products of two * relators. Depth=2 means products of three, etc. Depth=4 is * typically the last depth before the exponential growth of * the operation grows out of hand. It also conveniently trivializes * all the complicated trivial group presentations that we've come * across so far. * * \warning Do not call this routine with depth n before having called * it at depth n-1 first. Depth=0 is invalid, and depth=1 should be * your first call to this routine. This routine gobbles up an * exponential amount of memory (exponential in your presentation * size times n). So do be careful when using it. * * @param depth controls the depth of the proliferation, as * described above; this must be strictly positive. */ void proliferateRelators(unsigned long depth=1); /** * Attempts to recognise the group corresponding to this * presentation. This routine is much more likely to be * successful if you have already called intelligentSimplify(). * * Currently, if successful the only groups this routine * recognises is: the trivial group, abelian groups, free groups, * extensions over the integers, and free products of any group * the algorithm can recognise (inductively). * * Return strings have the form: * * - 0 for the trivial group; * - Z_n for cyclic groups with \a n > 1; * - Free(n) for free groups with \a n > 1 generators - see * NAbelianGroup::str() for how abelian groups are presented; * - FreeProduct(G1, G2, ... , Gk) for free products, where * one replaces \a G1 through \a Gk by text strings representing the * free summands; * - Z~G w/ monodromy H for extensions over Z, * where \a G is a description of the kernel of the homomorphism * to the integers, and \a H is a text string representing the * monodromy - see NHomMarkedAbelianGroup.str() for details on * how these are presented. * * \todo \featurelong Make this recognition more effective. * * @return a simple string representation of the group if it is * recognised, or an empty string if the group is not * recognised. */ std::string recogniseGroup() const; /** * Writes a chunk of XML containing this group presentation. * * \ifacespython Not present. * * @param out the output stream to which the XML should be written. */ void writeXMLData(std::ostream& out) const; /** * The sum of the word lengths of the relators. * Word lengths are computing using NGroupExpression::wordLength(). * Used as a coarse measure of the complexity of the presentation. * * @return the sum of word lengths. */ unsigned long relatorLength() const; /** * Computes the abelianisation of this group. * * @return a newly allocated abelianisation of this group. */ std::auto_ptr abelianisation() const; /** * Computes the abelianisation of this group. * The coordinates in the chain complex correspond * to the generators and relators for this group. * * @return a newly allocated abelianisation of this group. */ std::auto_ptr markedAbelianisation() const; /** * Attempts to determine if the group is abelian. * * A return value of \c true indicates that this routine * successfully certified that the group is abelian. * A return value of \c false indicates an inconclusive result: * either the group is non-abelian, or the group * is abelian but this routine could not prove so. * * If the group is abelian, then markedAbelianization() is the easiest * way to see precisely * which abelian group it is, and how the generators sit in that group. * * You will have better results from this algorithm if the * presentation has been simplified, since this algorithm uses small * cancellation theory in an attempt to reduce the commutators of all * pairs of generators. * * \warning If you have not adequately simplified this presentation * this routine will most likely return \c false. Consider running * intelligentSimplify, possibly in concert with proliferateRelators(), * in order to discover adequately many commutators. * * @return \c true if the group is shown to be abelian, or * \c false if the result is inconclusive. */ bool identifyAbelian() const; /** * Switches the generators in the presentation indexed by \a i * and \a j respectively, and recomputes the appropriate presentation. * It is one of the standard Nielsen moves, which is the first of * three generator types of the automorphism group of a free group. * * \pre Both \a i and \a j are strictly less than * getNumberOfGenerators(). * * @param i indicates the first of the two generators to switch. * @param j indicates the second of the two generators to switch. * @return \c true if and only if the Nielsen automorphism had an * effect on at least one relation. */ bool nielsenTransposition(unsigned long i, unsigned long j); /** * Replaces a generator in a presentation by its inverse, and * recomputes the appropriate presentation. This is the second * generator type of the automorphism group of a free group. * * \pre \a i is strictly less than getNumberOfGenerators(). * * @param i indicates the generator to invert. * @return \c true if and only if the Nielsen automorphism had an * effect on at least one relation. */ bool nielsenInvert(unsigned long i); /** * Replaces a generator \c gi by either * (gi)(gj)^k or (gj)^k(gi) in the presentation. It * it is the third type of Nielsen move one can apply to a presentation. * * This means that, if the new generator \c Gi is the old * (gi)(gj)^k or (gj)^k(gi), then we can construct * the new presentation from the old by replacing occurrences of \c Gi * by (Gi)(gj)^(-k) or (gj)^(-k)(Gi) respectively. * * \pre Both \a i and \a j are strictly less than * getNumberOfGenerators(). * * @param i indicates the generator to replace. * @param j indicates the generator to combine with \c gi. * @param k indicates the power to which we raise \c gj when * performing the replacement; this may be positive or negative * (or zero, but this will have no effect). * @param rightMult \c true if we should replace \c gi by * (gi)(gj)^k, or \c false if we should replace \c gi by * (gj)^k(gi). * @return \c true if and only if the nielsen automorphism had an * effect on at least one relation. */ bool nielsenCombine(unsigned long i, unsigned long j, long k, bool rightMult=true); /** * Looks for Nielsen moves that will simplify the presentation. * Performs one of the most-effective moves, if it can find any. * * @return \c true if and only if it performed a Nielsen move. * You can call intelligentNielsen() to get the isomorphism. */ bool intelligentNielsen(); /** * Looks for Nielsen moves that will simplify the presentation. * Performs one of the most-effective moves, if it can find any. * * If this routine does return a homomorphism (because some * move was performed), then this homomorphsm will in fact be * a declared isomorphism. See the NHomGroupPresentation class * notes for details on what this means. * * @return a newly allocated homomorphism describing the * map from the original presentation to the new presentation, * or a null pointer if no move was performed. */ std::auto_ptr intelligentNielsenDetail(); /** * Rewrites the presentation so that generators * of the group map to generators of the abelianisation, with any * left-over generators mapping to zero (if possible). Consider this a * \e homological-alignment of the presentation. * * See homologicalAlignmentDetail() for further details on what * this routine does. * * @return \c true if presentation was changed, or \c false if * the presentation was already homologically aligned. * See homologicalAlignmentDetail() if you wish to get the isomorphism. */ bool homologicalAlignment(); /** * Rewrites the presentation so that generators * of the group map to generators of the abelianisation, with any * left-over generators mapping to zero (if possible). Consider this a * \e homological-alignment of the presentation. * * If the abelianisation of this group has rank \a N and \a M invariant * factors d0 | d2 | ... | d(M-1), * this routine applies Nielsen moves * to the presentation to ensure that under the markedAbelianisation() * routine, generators 0 through \a M-1 are mapped to generators of the * relevant \c Z_di group. Similarly, generators \a M through * M+N-1 are mapped to +/-1 in the appropriate factor. * All further generators will be mapped to zero. * * If this routine does return a homomorphism (because the * presentation was changed), then this homomorphsm will in fact be * a declared isomorphism. See the NHomGroupPresentation class * notes for details on what this means. * * @return a newly allocated homomorphism giving the reduction map * from the old presentation to the new, or a null pointer if * this presentation was not changed. */ std::auto_ptr homologicalAlignmentDetail(); /** * An entirely cosmetic re-writing of the presentation, which is * fast and superficial. * * See prettyRewritingDetail() for further details on what * this routine does. * * @return \c true if and only if the choice of generators for the * group has changed. You can call prettyRewritingDetail() to get the * the isomorphism. */ bool prettyRewriting(); /** * An entirely cosmetic re-writing of the presentation, which is * fast and superficial. * * 1. If there are any length 1 relators, those generators are * deleted, and the remaining relators simplified. * 2. It sorts the relators by number of generator indices that * appear, followed by relator numbers (lexico) followed by * relator length. * 3. inverts relators if net sign of the generators is negative. * 4. Given each generator, it looks for the smallest word where that * generator appears with non-zero weight. If negative weight, * it inverts that generator. * 5. It cyclically permutes relators to start with smallest gen. * * If this routine does return a homomorphism (because the choice of * generators was changed), then this homomorphsm will in fact be * a declared isomorphism. See the NHomGroupPresentation class * notes for details on what this means. * * \todo As a final step, make elementary simplifications to aid in * seeing standard relators like commutators. * * @return a newly allocated homomorphism describing the * map from the original presentation to the new presentation, * or a null pointer if the choice of generators did not change. */ std::auto_ptr prettyRewritingDetail(); /** * Attempts to prove that this and the given group presentation are * simply isomorphic. * * A simple isomorphism is an isomorphism where each generator * gi of this presentation is sent to * some generator gj+/-1 of the * other presentation. Moreover, at present this routine only * looks for maps where both presentations have the same number * of generators, and where distinct generators gi * of this presentation correspond to distinct generators * gj of the other presentation (possibly with * inversion, as noted above). * * If this routine returns \c true, it means that the two * presentations are indeed simply isomorphic. * * If this routine returns \c false, it could mean one of many * things: * * - The groups are not isomorphic; * - The groups are isomorphic, but not simply isomorphic; * - The groups are simply isomorphic but this routine could not * prove it, due to difficulties with the word problem. * * @param other the group presentation to compare with this. * @return \c true if this routine could certify that the two group * presentations are simply isomorphic, or \c false if it could not. */ bool identifySimplyIsomorphicTo(const NGroupPresentation& other) const; /** * Returns a TeX representation of this group presentation. * See writeTeX() for details on how this is formed. * * @return a TeX representation of this group presentation. */ std::string toTeX() const; /** * Writes a TeX represesentation of this group presentation * to the given output stream. * * The output will be of the form < generators | relators >. * There will be no final newline. * * \ifacespython The parameter \a out does not exist; * standard output will be used. * * @param out the output stream to which to write. */ void writeTeX(std::ostream& out) const; /** * A deprecated alias for compact(), which returns a * compact one-line representation of this group presentation. * * \deprecated This routine has been deprecated; use the * simpler-to-type compact() instead. * * @return a compact representation of this group presentation. */ std::string toStringCompact() const; /** * Returns a compact one-line representation of this group presentation, * including details of all generators and relations. * See writeTextCompact() for details on how this is formed. * * @return a compact representation of this group presentation. */ std::string compact() const; /** * Writes a compact represesentation of this group to the given * output stream. * * The output will be of the form < generators | relators >. * The full relations will be included, and the entire output * will be written on a single line. There will be no final newline. * * \ifacespython The parameter \a out does not exist; * standard output will be used. * * @param out the output stream to which to write. */ void writeTextCompact(std::ostream& out) const; virtual void writeTextShort(std::ostream& out) const; virtual void writeTextLong(std::ostream& out) const; private: /** * Attempts to rewrite the presentation as a group extension. * In particular, this routine attempts to rewrite this group * as a semi-direct product of the integers and another * finitely-presented group, i.e., an extension of the form: * * < a, r1,...,rn | R1,...,RM, ar1a^-1 = w1, ... arna^-1 = wn > * * This is an algorithmic * implementation of the Reidemeister-Schrier algorithm, which isn't * actually an algorithm. So sometimes this procedure works, and * sometimes it does not. The return value is an allocated auto_ptr * if and only if the algorithm is successful. Even if the algorithm * is unsuccessful, its application will likely result in a * modification of the presentation. * * \apinotfinal This routine may very well either be eliminated * in future versions of this software, perhaps incorporated into a * bigger-and-better future algorithm. * * @return a newly allocated homomorphism if and only * if the algorithm is successful. When this pointer is allocated * it will be an automorphism of a presentation of the kernel of the * map this to the integers. */ std::auto_ptr< NHomGroupPresentation > identifyExtensionOverZ(); /** * Attempts to determine if this group is clearly a free * product of other groups. This is an unsophisticated algorithm * and will likely only have success if one has pre-processed the * presentation with simplification routines beforehand. * * If this routine succeeds then the group is definitely a free * product. If this routine fails (by returning an empty list) * then the result is inconclusive: the group might not be a * free product, or it might be a free product but this routine * could not prove so. * * \apinotfinal Reconsider how the end-user should see this routine. * * @return a list of newly allocated group presentations giving * the factors of this free product, or an empty list if this * routine fails (i.e., the result is inconclusive). */ std::list< NGroupPresentation* > identifyFreeProduct() const; /** * A structure internal to the small cancellation simplification * algorithm. * * Given two words, A and B, one wants to know how one can make * substitutions into A using variants of the word B. This * structure holds that data. For example, if: * * A == a^5b^2abababa^4b^1 and B == bababa^-1 * == aaaaabbabababaaaab * start_sub_at == 6, start_from == 0, sub_length == 5 makes sense, * this singles out the subword aaaaab[babab]abaaaab. Since it would * reduce the length by four, the score is 4. * * Similarly, if A == baba^4b^1a^5b^2aba == babaaaabaaaaabbaba * and B == baba^-1ba start_sub_at == 14, start_from == 5, * sub_length == 5 makes sense, and is a cyclic variation * on the above substitution, so the score is also 4. */ struct NWordSubstitutionData { unsigned long start_sub_at; /**< Where in A do we start? */ unsigned long start_from; /**< Where in B do we start? */ unsigned long sub_length; /**< The number of letters from B to use. */ bool invertB; /**< Invert B before making the substitution? */ long int score; /**< The score, i.e., the decrease in the word letter count provided this substitution is made. */ bool operator<( const NWordSubstitutionData &other ) const { if (score < other.score) return false; if (score > other.score) return true; if (sub_length < other.sub_length) return false; if (sub_length > other.sub_length) return true; if ( (invertB == true) && (other.invertB == false) ) return false; if ( (invertB == false) && (other.invertB == true) ) return true; if (start_from < other.start_from) return false; if (start_from > other.start_from) return true; if (start_sub_at < other.start_sub_at) return false; if (start_sub_at > other.start_sub_at) return true; return false; } void writeTextShort(std::ostream& out) const { out<<"Target position "<1 * is used primarily when building relator tables for group * recognition. */ static void dehnAlgorithmSubMetric( const NGroupExpression &this_word, const NGroupExpression &that_word, std::set< NWordSubstitutionData > &sub_list, unsigned long step=1 ); /** * A routine internal to the small cancellation simplification * algorithm. * * Given a word this_word and that_word, apply the substitution * specified by sub_data to *this. See dehnAlgorithm() and struct * NWordSubstitutionData. In particular sub_data needs to be a * valid substitution, usually it will be generated by * dehnAlgorithmSubMetric. */ static void applySubstitution( NGroupExpression& this_word, const NGroupExpression &that_word, const NWordSubstitutionData &sub_data ); }; /*@}*/ // Inline functions for NGroupExpressionTerm inline NGroupExpressionTerm::NGroupExpressionTerm() { } inline NGroupExpressionTerm::NGroupExpressionTerm(unsigned long newGen, long newExp) : generator(newGen), exponent(newExp) { } inline NGroupExpressionTerm::NGroupExpressionTerm( const NGroupExpressionTerm& cloneMe) : generator(cloneMe.generator), exponent(cloneMe.exponent) { } inline NGroupExpressionTerm& NGroupExpressionTerm::operator = ( const NGroupExpressionTerm& cloneMe) { generator = cloneMe.generator; exponent = cloneMe.exponent; return *this; } inline bool NGroupExpressionTerm::operator == ( const NGroupExpressionTerm& other) const { return (generator == other.generator) && (exponent == other.exponent); } inline NGroupExpressionTerm NGroupExpressionTerm::inverse() const { return NGroupExpressionTerm(generator, -exponent); } inline bool NGroupExpressionTerm::operator += ( const NGroupExpressionTerm& other) { if (generator == other.generator) { exponent += other.exponent; return true; } else return false; } inline bool NGroupExpressionTerm::operator < ( const NGroupExpressionTerm& other) const { return ( (generator < other.generator) || ( (generator == other.generator) && ( exponent < other.exponent ) ) ); } // Inline functions for NGroupExpression inline NGroupExpression::NGroupExpression() { } inline NGroupExpression::NGroupExpression(const NGroupExpression& cloneMe) : ShareableObject(), terms(cloneMe.terms) { } inline bool NGroupExpression::operator==(const NGroupExpression& comp) const { return terms == comp.terms; } inline NGroupExpression& NGroupExpression::operator=( const NGroupExpression& cloneMe) { terms = cloneMe.terms; return *this; } inline std::list& NGroupExpression::getTerms() { return terms; } inline const std::list& NGroupExpression::getTerms() const { return terms; } inline unsigned long NGroupExpression::getNumberOfTerms() const { return terms.size(); } inline bool NGroupExpression::isTrivial() const { return terms.empty(); } inline unsigned long NGroupExpression::wordLength() const { unsigned long retval(0); std::list::const_iterator it; for (it = terms.begin(); it!=terms.end(); it++) retval += labs((*it).exponent); return retval; } inline unsigned long NGroupExpression::getGenerator(unsigned long index) const { return getTerm(index).generator; } inline long NGroupExpression::getExponent(unsigned long index) const { return getTerm(index).exponent; } inline void NGroupExpression::addTermFirst(const NGroupExpressionTerm& term) { terms.push_front(term); } inline void NGroupExpression::addTermFirst(unsigned long generator, long exponent) { terms.push_front(NGroupExpressionTerm(generator, exponent)); } inline void NGroupExpression::addTermLast(const NGroupExpressionTerm& term) { terms.push_back(term); } inline void NGroupExpression::addTermLast(unsigned long generator, long exponent) { terms.push_back(NGroupExpressionTerm(generator, exponent)); } inline void NGroupExpression::erase() { terms.clear(); } // Inline functions for NGroupPresentation inline NGroupPresentation::NGroupPresentation() : nGenerators(0) { } inline NGroupPresentation::~NGroupPresentation() { for_each(relations.begin(), relations.end(), FuncDelete()); } inline unsigned long NGroupPresentation::addGenerator(unsigned long num) { return (nGenerators += num); } inline void NGroupPresentation::addRelation(NGroupExpression* rel) { relations.push_back(rel); } inline unsigned long NGroupPresentation::getNumberOfGenerators() const { return nGenerators; } inline unsigned long NGroupPresentation::getNumberOfRelations() const { return relations.size(); } inline const NGroupExpression& NGroupPresentation::getRelation( unsigned long index) const { return *relations[index]; } inline void NGroupPresentation::writeTextShort(std::ostream& out) const { out << "Group presentation: " << nGenerators << " generators, " << relations.size() << " relations"; } inline unsigned long NGroupPresentation::relatorLength() const { unsigned long retval(0); for (unsigned long i=0; iwordLength(); return retval; } } // namespace regina #endif regina-4.96/engine/algebra/nhomgrouppresentation.cpp000644 000765 000024 00000032221 12377776531 022652 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include "algebra/ngrouppresentation.h" #include "algebra/nhomgrouppresentation.h" #include "maths/numbertheory.h" #include "utilities/boostutils.h" #include "utilities/stlutils.h" namespace regina { NHomGroupPresentation::NHomGroupPresentation( const NGroupPresentation& groupForIdentity) : domain_(new NGroupPresentation(groupForIdentity)), range_(new NGroupPresentation(groupForIdentity)), map_(groupForIdentity.getNumberOfGenerators()), inv_(new std::vector( groupForIdentity.getNumberOfGenerators())) { for (unsigned long i=0; iaddTermFirst(i, 1); (*inv_)[i]->addTermFirst(i,1); } } NGroupExpression NHomGroupPresentation::evaluate( const NGroupExpression &arg) const { // evaluate at arg NGroupExpression retval(arg); unsigned long N( range_->getNumberOfGenerators() ); for (unsigned long i=0; igetNumberOfGenerators() ); for (unsigned long i=0; isize(); i++) retval.substitute( N+i, *(*inv_)[i] ); return retval; } std::auto_ptr< NHomMarkedAbelianGroup > NHomGroupPresentation::markedAbelianisation() const { std::auto_ptr DOM( domain_->markedAbelianisation() ); std::auto_ptr RAN( range_->markedAbelianisation() ); NMatrixInt ccMat( RAN->getRankCC(), DOM->getRankCC() ); for (unsigned long j=0; j( new NHomMarkedAbelianGroup( *DOM, *RAN, ccMat ) ); } void NHomGroupPresentation::writeTextShort(std::ostream& out) const { if (inv_) out << "Isomorphism from "; else out << "Homomorphism from "; domain_->writeTextShort(out); out << " to "; range_->writeTextShort(out); } void NHomGroupPresentation::writeTextLong(std::ostream& out) const { if (inv_) out << "Isomorphism with "; else out << "Homomorphism with "; out<<"domain "; domain_->writeTextCompact(out); out<<" "; // std::endl; out<<"map["; for (unsigned long i=0; igetNumberOfGenerators(); i++) { if (i!=0) out<<", "; if (domain_->getNumberOfGenerators()<=26) out< "; else out<<"g"< "; if (range_->getNumberOfGenerators()<=26) map_[i]->writeText(out, true); else map_[i]->writeText(out, false); } out<<"] "; out<<"range "; range_->writeTextCompact(out); out< rangeMap = range_->smallCancellationDetail(); std::auto_ptr domainMap = domain_->smallCancellationDetail(); if (! domainMap.get()) domainMap.reset(new NHomGroupPresentation(*domain_)); if (! rangeMap.get()) rangeMap.reset(new NHomGroupPresentation(*range_)); NGroupPresentation *oldDom(domainMap->domain_), *oldRan(rangeMap->domain_), *newDom(domain_), *newRan(range_); domain_ = oldDom; range_ = oldRan;// we need to call this->evaluate but our map bool retval = rangeMap.get() || domainMap.get(); std::vector< NGroupExpression > newMap( newDom->getNumberOfGenerators() ); for (unsigned long i=0; ievaluate( evaluate( domainMap->invEvaluate(i) ) ) ); std::vector< NGroupExpression > newInvMap; if (inv_) { newInvMap.resize( newRan->getNumberOfGenerators() ); for (unsigned long i=0; ievaluate( invEvaluate( rangeMap->invEvaluate(i) ) ) ); } domain_ = newDom; range_ = newRan; for (unsigned long i=0; isize(); i++) delete (*inv_)[i]; inv_->resize( newInvMap.size() ); } for (unsigned long i=0; isimplifyWord(*map_[i]); } if (inv_) for (unsigned long i=0; isize(); i++) { (*inv_)[i] = new NGroupExpression(newInvMap[i]); domain_->simplifyWord(*(*inv_)[i]); } return retval; } std::auto_ptr NHomGroupPresentation::composeWith( const NHomGroupPresentation& input) const { std::vector evalVec(input.domain_->getNumberOfGenerators()); for (unsigned long i=0; i(new NHomGroupPresentation( *input.domain_, *range_, evalVec) ); else { std::vector invVec( range_->getNumberOfGenerators()); for (unsigned long i=0; i(new NHomGroupPresentation( *input.domain_, *range_, evalVec, invVec ) ); } } bool NHomGroupPresentation::intelligentNielsen() { // modelled on intelligentSimplify std::auto_ptr rangeMap = range_->intelligentNielsenDetail(); std::auto_ptr domainMap = domain_->intelligentNielsenDetail(); if (! domainMap.get()) domainMap.reset(new NHomGroupPresentation(*domain_)); if (! rangeMap.get()) rangeMap.reset(new NHomGroupPresentation(*range_)); NGroupPresentation *oldDom(domainMap->domain_), *oldRan(rangeMap->domain_), *newDom(domain_), *newRan(range_); domain_ = oldDom; range_ = oldRan;// we need to call this->evaluate but our map bool retval = rangeMap.get() || domainMap.get(); std::vector< NGroupExpression > newMap( newDom->getNumberOfGenerators() ); for (unsigned long i=0; ievaluate( evaluate( domainMap->invEvaluate(i) ) ) ); std::vector< NGroupExpression > newInvMap; if (inv_) { newInvMap.resize( newRan->getNumberOfGenerators() ); for (unsigned long i=0; ievaluate( invEvaluate( rangeMap->invEvaluate(i) ) ) ); } domain_ = newDom; range_ = newRan; for (unsigned long i=0; isize(); i++) delete (*inv_)[i]; inv_->resize( newInvMap.size() ); } for (unsigned long i=0; isimplifyWord(*map_[i]); } if (inv_) for (unsigned long i=0; isize(); i++) { (*inv_)[i] = new NGroupExpression(newInvMap[i]); domain_->simplifyWord(*(*inv_)[i]); } return retval; } bool NHomGroupPresentation::intelligentSimplify() { // step 1: simplify presentation of domain and range std::auto_ptr rangeMap = range_->intelligentSimplifyDetail(); std::auto_ptr domainMap = domain_->intelligentSimplifyDetail(); // build identity maps if either of the above is null. if (! domainMap.get()) domainMap.reset(new NHomGroupPresentation(*domain_)); if (! rangeMap.get()) rangeMap.reset(new NHomGroupPresentation(*range_)); NGroupPresentation *oldDom(domainMap->domain_), *oldRan(rangeMap->domain_), *newDom(domain_), *newRan(range_); domain_ = oldDom; range_ = oldRan;// we need to call this->evaluate but our map // step 2: compute rangeMap*(*oldthis)*domainMap.inverse() // and replace "map" appropriately. Simplify the words in the range. // Do the same for the inverse map if we have one. bool retval = rangeMap.get() || domainMap.get(); std::vector< NGroupExpression > newMap( newDom->getNumberOfGenerators() ); for (unsigned long i=0; ievaluate( evaluate( domainMap->invEvaluate(i) ) ) ); std::vector< NGroupExpression > newInvMap; if (inv_) { newInvMap.resize( newRan->getNumberOfGenerators() ); for (unsigned long i=0; ievaluate( invEvaluate( rangeMap->invEvaluate(i) ) ) ); } domain_ = newDom; range_ = newRan; // step 3: rewrite this map, and simplify for (unsigned long i=0; isize(); i++) delete (*inv_)[i]; inv_->resize( newInvMap.size() ); } for (unsigned long i=0; isimplifyWord(*map_[i]); } if (inv_) for (unsigned long i=0; isize(); i++) { (*inv_)[i] = new NGroupExpression(newInvMap[i]); domain_->simplifyWord(*(*inv_)[i]); } return retval; } bool NHomGroupPresentation::invert() { if (inv_) { NGroupPresentation* temp( domain_ ); domain_ = range_; range_ = temp; map_.swap( *inv_ ); return true; } return false; } bool NHomGroupPresentation::verify() const { for (unsigned long i=0; igetNumberOfRelations(); i++) { const NGroupExpression& reli( domain_->getRelation(i) ); NGroupExpression imgRel( evaluate(reli) ); range_->simplifyWord(imgRel); if (!imgRel.isTrivial()) return false; } return true; } bool NHomGroupPresentation::verifyIsomorphism() const { if (! inv_) return false; if (inv_->size() != range_->getNumberOfGenerators()) return false; // for every generator in the domain compute f^-1(f(x))x^-1 and reduce for (unsigned long i=0; igetNumberOfGenerators(); i++) { NGroupExpression tempW( invEvaluate(evaluate(i)) ); tempW.addTermLast( i, -1 ); domain_->simplifyWord(tempW); if (tempW.getNumberOfTerms()>0) return false; } // for every generator in the range compute f(f^-1(x))x^-1 and reduce for (unsigned long i=0; igetNumberOfGenerators(); i++) { NGroupExpression tempW( evaluate(invEvaluate(i)) ); tempW.addTermLast( i, -1 ); range_->simplifyWord(tempW); if (tempW.getNumberOfTerms()>0) return false; } return true; } } // namespace regina regina-4.96/engine/algebra/nhomgrouppresentation.h000644 000765 000024 00000041430 12377774614 022321 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file algebra/nhomgrouppresentation.h * \brief Deals with finite presentations of groups. */ #ifndef __NHOMGROUPPRESENTATION_H #ifndef __DOXYGEN #define __NHOMGROUPPRESENTATION_H #endif #include #include "regina-core.h" #include "shareableobject.h" namespace regina { class NGroupPresentation; /** * \weakgroup algebra * @{ */ /** * Represents a homomorphism between groups which are described via finite * presentations. * * Some homomorphisms may be declared isomorphisms. This means * that the user (or some other function in Regina) has proven that this * is an isomorphism and has explicitly provided the inverse map. * To provide the inverse map, you should call the four-argument constructor * NHomGroupPresentation(const NGroupPresentation&, const NGroupPresentation&, * const std::vector&, const std::vector&). * * You can test for a declared isomorphism by calling knowsInverse(). Even * if a homomorphism is not a declared isomorphism, it might still be an * isomorphism; this just means that no inverse map was explicitly provided. * * \apinotfinal * * \todo Add a routine to attempt to verify validity of homomorphism. */ class REGINA_API NHomGroupPresentation : public ShareableObject { private: NGroupPresentation* domain_; /**< The domain of the homomorphism. */ NGroupPresentation* range_; /**< The range of the homomorphism. */ std::vector map_; /**< A map whose ith element is the image in the range of the ith generator from the domain. */ std::vector* inv_; /**< Null unless this is a declared isomorphism, in which case this will be a map whose ith element is the image in the domain of the ith generator from the range. */ public: /** * Creates a new homomorphism from the given data. * * \ifacespython Not present. * * @param domain the domain of the homomorphism. * @param range the range of the homomorphism. * @param map a vector of length \a g, where \a g is the number * of generators of the domain, and where this homomorphism * sends the ith generator of the domain to the * element map[i] of the range. * * \ifacespython Not present. */ NHomGroupPresentation(const NGroupPresentation &domain, const NGroupPresentation &range, const std::vector &map); /** * Creates a declared isomorphism from the given data. * Here you must provide both a map from the domain to range, * and the inverse map from the range to domain. * * \pre The argument \a inv is indeed the inverse of \a map. * * \ifacespython Not present. * * @param domain the domain of the homomorphism. * @param range the range of the homomorphism. * @param map a vector of length \a g, where \a g is the number * of generators of the domain, and where this homomorphism * sends the ith generator of the domain to the * element map[i] of the range. * @param inv a vector of length \a k where \a k is the number * of generators of the range, and where the inverse homomorphism * sends the ith generator of the range to the * element inv[i] of the domain. */ NHomGroupPresentation(const NGroupPresentation &domain, const NGroupPresentation &range, const std::vector &map, const std::vector &inv); /** * Creates a new identity homomorphism for the given group. * * This will be a declared isomorphism (see the * NHomGroupPresentation class notes for details). * * @param groupForIdentity both the range and domain of the * new identity homomorphism. */ NHomGroupPresentation(const NGroupPresentation& groupForIdentity); /** * Creates a clone of the given group presentation. * * @param cloneMe the presentation to clone. */ NHomGroupPresentation(const NHomGroupPresentation& cloneMe); /** * Destroys the group homomorphism. */ ~NHomGroupPresentation(); /** * The domain of the map. * * @return a reference to the domain. */ const NGroupPresentation& getDomain() const; /** * The range of the map. * * @return a reference to the range. */ const NGroupPresentation& getRange() const; /** * Returns whether or not this is a declared isomorphism. * * A declared isomorphism is a isomorphism for which the * user has explicitly provided the inverse map. See the * NHomGroupPresentation class notes for details. * * @return \c true if and only if this is a declared * isomorphism, i.e, the inverse map was explicitly provided. */ bool knowsInverse() const; /** * Evaluate the homomorphism at an element of the domain. * * @param arg an element of the domain. * @return the image of this element in the range. */ NGroupExpression evaluate(const NGroupExpression &arg) const; /** * Evaluate the homomorphism at a generator of the domain. * * @param i the index of a generator in the domain. * @return the image of the ith generator in the range. */ NGroupExpression evaluate(unsigned long i) const; /** * Evaluate the isomorphisms's inverse at an element of the range. * * \pre This homomorphism is in fact a declared isomorphism. * See the NHomGroupPresentation class notes for details * on what this means. * * @param arg an element of the range. * @return the image of this element in the domain. */ NGroupExpression invEvaluate(const NGroupExpression &arg) const; /** * Evaluate the isomorphism at a generator of the range. * * \pre This homomorphism is in fact a declared isomorphism. * See the NHomGroupPresentation class notes for details * on what this means. * * @param i the index of a generator in the range. * @return the image of this generator in the domain. */ NGroupExpression invEvaluate(unsigned long i) const; /** * Simultaneously simplifies: * * - the presentation of the domain; * - the presentation of the range; * - the description of the map. * * Uses the underlying NGroupPresentation::intelligentSimplify(). * See that routine for details. * * @return \c true if the presentations or map have changed. */ bool intelligentSimplify(); /** * Simplifies the domain and range using only Nielsen moves, keeping * track of the resulting map in the progress. * * @return \c true if and only if either presentation was changed. */ bool intelligentNielsen(); /** * Simplifies the domain and range using only small cancellation * theory. * * @return \c true if and only if either presentation was changed. */ bool smallCancellation(); /** * Composes this homomorphism with the given input homomorphism. * * Evaluating the composition on some group element \a x is the * same as evaluating this(input(x)). * In other words, in this composition, \a input is evaluated first * and then the output of that is evaluated by this homomorphism. * * If both of the given homomorphisms are declared isomorphisms, * then the return value will be a declared isomoprhism also. * * \pre the range of \a input must be the same as the domain of this * homomorphism. * * @param input the homomorphism to compose with this. * @return the composition of both homomorphisms. */ std::auto_ptr composeWith( const NHomGroupPresentation& input) const; /** * Inverts the homomorphism. * * This is only possible if the homomorphism is in fact a * declared isomorphism (which means that the inverse map is * already stored internally). See the NHomGroupPresentation * class notes for further details on declared isomorphisms. * * If this is not a declared isomorphism then this routine * will do nothing and simply return \c false. * * This operation is (very) fast constant time. * * @return \c true if and only if the inversion operation was * successful (i.e., if this is a declared isomorphism). */ bool invert(); /** * Verifies the map is a valid homomorphism. Specifically, this * routine runs through all the relators in the domain, evaluates * the homomorphism on the relators and checks that they simplify * to 1 in the range. * * This routine does not guarantee a conclusive result (since * the word problem is, in general, undecidable). If this * routine returns \c true then this proves that the * homomorphism is indeed valid. If this routine returns \c false, * then the result is inconclusive (i.e., it might still be * valid but Regina was not able to prove this). * * This routine is intended for sanity checking only: any homomorphism * that you construct in Regina should always be valid in this sense. * * @return \c true if Regina is able to verify that this is a * homomorphism, or \c false if the result is inconclusive. */ bool verify() const; /** * Attempts to verify that a declared isomorphism is, indeed, * an isomorphism. * * This routine works by attempting to verify that * f^-1(f(x))x^-1 simplifes to 1 for all generators \a x * in the domain, and likewise for the range. * * This routine does not guarantee a conclusive result. If this * routine returns \c true then this proves that this is indeed * an isomorphism. If this routine returns \c false then the result * is inconclusive (i.e., it might still be an isomorphism * but Regina was not able to prove this). * * You probably only want to run this on good presentations for small * cancellation theory - an automorphism of a poorly-presented group * likely will not be noticed. * * This routine is intended for sanity checking only: any homomorphism * that you construct as a declared isomorphism should always be * an isomorphism. * * \pre This homomorphism is in fact a declared isomorphism. * See the NHomGroupPresentation class notes for details * on what this means. * * @return \c true if it is verified that this is an * isomorphism, or \c false if the result is inconclusive. */ bool verifyIsomorphism() const; /** * Computes the induced map on the abelianizations of the domain * and range. * * @return the induced map on the abelianizations. */ std::auto_ptr< NHomMarkedAbelianGroup > markedAbelianisation() const; void writeTextShort(std::ostream& out) const; void writeTextLong(std::ostream& out) const; }; /*@}*/ inline NHomGroupPresentation::NHomGroupPresentation( const NGroupPresentation &domain, const NGroupPresentation &range, const std::vector &map ) : domain_(new NGroupPresentation(domain)), range_(new NGroupPresentation(range)), inv_(0) { map_.resize(map.size()); for (unsigned long i=0; i &map, const std::vector &inv ) : domain_(new NGroupPresentation(domain)), range_(new NGroupPresentation(range)), inv_(new std::vector) { map_.resize(map.size()); inv_->resize(inv.size()); for (unsigned long i=0; isize(); i++) (*inv_)[i] = new NGroupExpression(inv[i]); } inline NHomGroupPresentation::NHomGroupPresentation( const NHomGroupPresentation& cloneMe) : domain_(new NGroupPresentation(*cloneMe.domain_)), range_(new NGroupPresentation(*cloneMe.range_)) { map_.resize(cloneMe.map_.size()); for (unsigned long i=0; i; inv_->resize(cloneMe.inv_->size()); for (unsigned long i=0; isize(); i++) (*inv_)[i] = new NGroupExpression(*((*cloneMe.inv_)[i])); } else inv_ = 0; } inline NHomGroupPresentation::~NHomGroupPresentation() { for (unsigned long i=0; isize(); i++) delete (*inv_)[i]; delete inv_; } delete domain_; delete range_; } inline const NGroupPresentation& NHomGroupPresentation::getDomain() const { return *domain_; } inline const NGroupPresentation& NHomGroupPresentation::getRange() const { return *range_; } inline bool NHomGroupPresentation::knowsInverse() const { return inv_; } inline NGroupExpression NHomGroupPresentation::evaluate(unsigned long i) const { return *(map_[i]); } inline NGroupExpression NHomGroupPresentation::invEvaluate(unsigned long i) const { return *((*inv_)[i]); } } // namespace regina #endif regina-4.96/engine/algebra/nmarkedabeliangroup.cpp000644 000765 000024 00000151026 12377776531 022217 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "algebra/nmarkedabeliangroup.h" #include "maths/matrixops.h" #include namespace regina { NMarkedAbelianGroup::NMarkedAbelianGroup(unsigned long rk, const NLargeInteger &p) : OM(rk, rk), ON(rk,rk), OMR(rk,rk), OMC(rk,rk), OMRi(rk, rk), OMCi(rk, rk), rankOM(0), ornR(0), ornC(0), ornRi(0), ornCi(0), otR(0), otC(0), otRi(0), otCi(0), InvFacList(0), snfrank(0), snffreeindex(0), ifNum(0), ifLoc(0), coeff(NLargeInteger::zero), TORLoc(0), TORVec(0), tensorIfLoc(0), tensorIfNum(0), tensorInvFacList(0) { // special case p==1 trivial group ornR.reset(new NMatrixInt(rk, rk)); ornRi.reset(new NMatrixInt(rk, rk)); ornC.reset(new NMatrixInt(rk, rk)); ornCi.reset(new NMatrixInt(rk, rk)); for (unsigned long i=0; imakeIdentity(); ornRi->makeIdentity(); ornC->makeIdentity(); ornCi->makeIdentity(); if ( (p != 0 ) && ( p != 1 ) ) ifNum=rk; if (ifNum != 0) InvFacList.resize(ifNum); for (unsigned long i=0; i > prod=OMRi*ON; NMatrixInt ORN(N.rows()-rankOM, N.columns()); ornR.reset( new NMatrixInt( ORN.columns(), ORN.columns() ) ); ornRi.reset(new NMatrixInt( ORN.columns(), ORN.columns() ) ); ornC.reset( new NMatrixInt( ORN.rows(), ORN.rows() ) ); ornCi.reset(new NMatrixInt( ORN.rows(), ORN.rows() ) ); for (unsigned long i=0;ientry(i+rankOM,j); // put the presentation matrix in Smith normal form, and // build the list of invariant factors and their row indexes // now compute the rank and column indexes ... metricalSmithNormalForm(ORN, &(*ornR), &(*ornRi), &(*ornC), &(*ornCi)); for (unsigned long i=0; ( (i1) InvFacList.push_back(ORN.entry(i,i)); } ifNum = InvFacList.size(); snfrank = ORN.rows() - ifLoc - ifNum; snffreeindex = ifLoc + InvFacList.size(); } // We'll store H_k(M;Z_p) internally in two different ways. The reason boils // down to the pleasant version of the universal coefficient theorem that you // see using Smith normal forms. Summary: if Z^a --N--> Z^b --M--> Z^c is a // chain complex for H_k(M;Z) and p>0 an integer, put M into SNF(M), this gives // SNF(M) == OMC*M*OMR. Let SNF(M) == diag[s_0, ..., s_{k-1}, 0, ... 0] and // suppose only entries s_i, ..., s_{k-1} share common factors with p. Then // you immediately get the presentation matrix for H_k(M;Z_p) which is a // product of the two matrices: [ trunc_top_k_rows[OMRi*N], diag(p,p,...,p) ] // \times [ diag(gcd(s_i,p), ..., gcd(s_{k-1},p) ] here trunc_top_k_rows means // remove the first k rows from [OMRi*N]. The left matrix is basically by // design the presentation matrix for H_k(M;Z)\times Z_p, and the right matrix // the presentation matrix for TOR(H_{k-1}(M;Z), Z_p). The 2nd matrix is // already in SNF. We apply SNF to the first, and store the change-of-basis // matrices in otR, otC, otRi, otCi. We then concatenate these two diagonal // matrices and apply SNF to them to get a situation NMarkedAbelianGroup will // be happy with. This has the added advantage of us being able to later easily // implement the NHomMarkedAbelianGroup maps for UCT later when we're interested // in that kind of stuff. NMarkedAbelianGroup::NMarkedAbelianGroup(const NMatrixInt& M, const NMatrixInt& N, const NLargeInteger &pcoeff): OM(M), ON(N), OMR(M.columns(),M.columns()), OMC(M.rows(),M.rows()), OMRi(M.columns(),M.columns()), OMCi(M.rows(),M.rows()), rankOM(0), ornR(0), ornC(0), ornRi(0), ornCi(0), otR(0), otC(0), otRi(0), otCi(0), InvFacList(0), snfrank(0), snffreeindex(0), ifNum(0), ifLoc(0), coeff(pcoeff), TORLoc(0), TORVec(0), tensorIfLoc(0), tensorInvFacList(0) { // find SNF(M). NMatrixInt tM(M); metricalSmithNormalForm(tM, &OMR, &OMRi, &OMC, &OMCi); for (unsigned i=0; ( (i 0 we need to consider the TOR part of homology. if (coeff > 0) for (unsigned i=0; i 1) { TORVec.push_back(tM.entry(i,i)); } TORLoc = rankOM - TORVec.size(); // okay, lets get a presentation matrix for H_*(M;Z) \otimes Z_p // starting by computing the trunc[OMRi*N] matrix and padding with // a diagonal p matrix std::auto_ptr > OMRiN = OMRi*ON; // hmm, if we're using p == 0 coefficients, lets keep it simple if (coeff > 0) { NMatrixInt tensorPres( OMRiN->rows() - rankOM, OMRiN->columns() + OMRiN->rows() - rankOM ); for (unsigned long i=0; icolumns(); j++) tensorPres.entry(i,j) = OMRiN->entry(i+rankOM, j); for (unsigned long i=0; i< OMRiN->rows() - rankOM; i++) tensorPres.entry(i, OMRiN->columns() + i) = coeff; // initialize coordinate-change matrices for the SNF computation. otR.reset(new NMatrixInt(tensorPres.columns(), tensorPres.columns() )); otRi.reset(new NMatrixInt(tensorPres.columns(), tensorPres.columns() )); otC.reset(new NMatrixInt(tensorPres.rows(), tensorPres.rows() )); otCi.reset(new NMatrixInt(tensorPres.rows(), tensorPres.rows() )); metricalSmithNormalForm(tensorPres, &(*otR), &(*otRi), &(*otC), &(*otCi)); // this group is a direct sum of groups of the form Z_q where q = // gcd(p, TORVec[i]), and groups Z_q where q is on the diagonal of // tensorPres, and either q=0 or q>1. unfortunately in rare occurances // these are not the invariant factors of the group, so we assemble these // numbers into a diagonal presentation matrix and apply SNF! Determine // the size of the matrix we'll need. for (unsigned long i=0; ( (i 1) tensorInvFacList.push_back(tensorPres.entry(i,i)); else if (tensorPres.entry(i,i) == 0) snfrank++; // should always be zero. } tensorIfNum = tensorInvFacList.size(); NMatrixInt diagPres( TORVec.size() + tensorIfNum + snfrank, TORVec.size() + tensorIfNum + snfrank); for (unsigned long i=0; i 1 or == 0. if (diagPres.entry(i,i) > 1) InvFacList.push_back(diagPres.entry(i,i)); } snffreeindex = InvFacList.size(); ifNum = InvFacList.size(); ifLoc = diagPres.rows() - ifNum; } else { // coeff == p == 0 case NMatrixInt tensorPres( OMRiN->rows() - rankOM, OMRiN->columns() ); for (unsigned long i=0; icolumns(); j++) tensorPres.entry(i,j) = OMRiN->entry(i+rankOM, j); // initialize coordinate-change matrices for the SNF computation. ornR.reset(new NMatrixInt(tensorPres.columns(), tensorPres.columns() )); ornRi.reset(new NMatrixInt(tensorPres.columns(), tensorPres.columns() )); ornC.reset(new NMatrixInt(tensorPres.rows(), tensorPres.rows() )); ornCi.reset(new NMatrixInt(tensorPres.rows(), tensorPres.rows() )); metricalSmithNormalForm(tensorPres, &(*ornR), &(*ornRi), &(*ornC), &(*ornCi)); for (unsigned long i=0; ( (i 1) InvFacList.push_back(tensorPres.entry(i,i)); } snffreeindex = ifLoc + InvFacList.size(); ifNum = InvFacList.size(); snfrank = tensorPres.rows() - ifLoc - ifNum; } } bool NMarkedAbelianGroup::isChainComplex() const { if (OM.columns() != ON.rows()) return false; std::auto_ptr > prod = OM*ON; for (unsigned long i=0; irows(); i++) for (unsigned long j=0; jcolumns(); j++) if (prod->entry(i,j) != 0) return false; return true; } unsigned long NMarkedAbelianGroup::getTorsionRank(const NLargeInteger& degree) const { unsigned long ans = 0; for (unsigned long i=0;i 0) { if (snfrank > 1) out << snfrank << ' '; out << 'Z'; writtenSomething = true; } std::vector::const_iterator it = InvFacList.begin(); NLargeInteger currDegree; unsigned currMult = 0; while(true) { if (it != InvFacList.end()) { if ((*it) == currDegree) { currMult++; it++; continue; } } if (currMult > 0) { if (writtenSomething) out << " + "; if (currMult > 1) out << currMult << ' '; out << "Z_" << currDegree.stringValue(); writtenSomething = true; } if (it == InvFacList.end()) break; currDegree = *it; currMult = 1; it++; } if (! writtenSomething) out << '0'; } /* * The marked abelian group was defined by matrices M and N * with M*N==0. Think of M as m by l and N as l by n. Then * this routine returns the index-th free generator of the * ker(M)/img(N) in Z^l. */ std::vector NMarkedAbelianGroup::getFreeRep(unsigned long index) const { static const std::vector nullvec; if (index >= snfrank) return nullvec; std::vector retval(OM.columns(),NLargeInteger::zero); // index corresponds to the (index+snffreeindex)-th column of ornCi // we then pad this vector (at the front) with rankOM 0's // and apply OMR to it. std::vector temp(ornCi->rows()+rankOM,NLargeInteger::zero); for (unsigned long i=0;irows();i++) temp[i+rankOM]=ornCi->entry(i,index+snffreeindex); // the above line takes the index+snffreeindex-th column of ornCi and // pads it. for (unsigned long i=0;i NMarkedAbelianGroup::getTorsionRep( unsigned long index) const { static const std::vector nullvec; if (index >= ifNum) return nullvec; std::vector retval(OM.columns(),NLargeInteger::zero); if (coeff == 0) { std::vector temp(ornCi->rows()+rankOM, NLargeInteger::zero); for (unsigned long i=0;irows();i++) temp[i+TORLoc] = ornCi->entry(i,ifLoc+index); // the above line takes the index+snffreeindex-th column of ornCi and // pads it suitably for (unsigned long i=0;i 0 with coefficients there's the extra step of dealing with the // UCT splitting start with column column index + ifLoc of matrix ornCi, /// split into two vectors // 1) first TORVec.size() entries and 2) remaining entries. std::vector firstV(TORVec.size(), NLargeInteger::zero); std::vector secondV(ornC->rows()-TORVec.size(), NLargeInteger::zero); for (unsigned long i=0; ientry( i, index + ifLoc ); for (unsigned long i=0; ientry( i + firstV.size(), index + ifLoc ); // 1st vec needs coords scaled appropriately by p/gcd(p,q) and // multiplied by appropriate OMR columns for (unsigned long i=0; i otCiSecondV(otCi->rows(), NLargeInteger::zero); for (unsigned long i=0; irows(); i++) for (unsigned long j=tensorIfLoc; jcolumns(); j++) otCiSecondV[i] += otCi->entry(i,j) * secondV[j-tensorIfLoc]; // 2nd vec needs be multiplied by otCi, padded, then have OMR applied. for (unsigned long i=0; i NMarkedAbelianGroup::ccRep(const std::vector& SNFRep) const { static const std::vector nullV; if (SNFRep.size() != snfrank + ifNum) return nullV; std::vector retval(OM.columns(),NLargeInteger::zero); std::vector temp(ornCi->rows()+TORLoc,NLargeInteger::zero); if (coeff == 0) { for (unsigned long j=0; jrows(); i++) temp[i+TORLoc] += ornCi->entry(i,ifLoc+j) * SNFRep[j]; for (unsigned long i=0;i 0 std::vector firstV(TORVec.size(), NLargeInteger::zero); std::vector secondV(ornC->rows()-TORVec.size(), NLargeInteger::zero); for (unsigned long i=0; ientry( i, j + ifLoc ) * SNFRep[j]; for (unsigned long i=0; ientry( i + firstV.size(), j + ifLoc ) * SNFRep[j]; // 1st vec needs coords scaled appropriately by p/gcd(p,q) and // multiplied by appropriate OMR columns for (unsigned long i=0; i otCiSecondV(otCi->rows(), NLargeInteger::zero); for (unsigned long i=0; irows(); i++) for (unsigned long j=tensorIfLoc; jcolumns(); j++) otCiSecondV[i] += otCi->entry(i,j) * secondV[j-tensorIfLoc]; // 2nd vec needs be multiplied by otCi, padded, then have OMR applied. for (unsigned long i=0; i NMarkedAbelianGroup::ccRep( unsigned long SNFRep) const { static const std::vector nullV; if (SNFRep >= snfrank + ifNum) return nullV; std::vector retval(OM.columns(),NLargeInteger::zero); std::vector temp(ornCi->rows()+TORLoc,NLargeInteger::zero); if (coeff == 0) { for (unsigned long i=0; irows(); i++) temp[i+TORLoc] = ornCi->entry(i,ifLoc+SNFRep); for (unsigned long i=0;i 0 std::vector firstV(TORVec.size(), NLargeInteger::zero); std::vector secondV(ornC->rows()-TORVec.size(), NLargeInteger::zero); for (unsigned long i=0; ientry( i, SNFRep + ifLoc ); for (unsigned long i=0; ientry( i + firstV.size(), SNFRep + ifLoc ); // 1st vec needs coords scaled appropriately by p/gcd(p,q) // and multiplied by appropriate OMR columns for (unsigned long i=0; i otCiSecondV(otCi->rows(), NLargeInteger::zero); for (unsigned long i=0; irows(); i++) for (unsigned long j=tensorIfLoc; jcolumns(); j++) otCiSecondV[i] += otCi->entry(i,j) * secondV[j-tensorIfLoc]; // 2nd vec needs be multiplied by otCi, padded, then have OMR applied. for (unsigned long i=0; i NMarkedAbelianGroup::snfRep( const std::vector& element) const { std::vector retval(snfrank+ifNum, NLargeInteger::zero); // apply OMRi, crop, then apply ornC, tidy up and return. static const std::vector nullvec; // this is returned if // element not in ker(M) // first, does element have the right dimensions? if not, abort. if (element.size() != OM.columns()) return nullvec; // this holds OMRi * element which we will use to check first if // element is in the kernel, and then to construct its SNF rep. std::vector temp(ON.rows(), NLargeInteger::zero); for (unsigned long i=0;ientry(i+snffreeindex,j-rankOM)*temp[j]; for (unsigned long i=0;ientry(i+ifLoc,j-rankOM)*temp[j]; // redundant for loops } else { std::vector diagPresV( ornC->rows(), NLargeInteger::zero); for (unsigned long i=0; icolumns(); j++) diagPresV[i] += otC->entry( i - TORVec.size() + tensorIfLoc, j) * temp[ j + rankOM ]; } // assemble to a diagPres vector, apply ornC for (unsigned long i=0; ientry(i,j) * diagPresV[j]; } // do modular reduction to make things look nice... for (unsigned long i=0; i &input) const { if (input.size() != OM.columns()) return false; for (unsigned long i=0; i &input) const { if (input.size() != OM.columns()) return false; std::vector snF(snfRep(input)); if (snF.size() != getNumberOfInvariantFactors() + getRank()) return false; for (unsigned long i=0; i NMarkedAbelianGroup::boundaryMap( const std::vector &CCrep) const { std::vector retval(OM.rows(), NLargeInteger::zero); if (CCrep.size() == OM.columns()) for (unsigned long i=0; i 0) { retval[i] %= coeff; if (retval[i] < 0) retval[i] += coeff; } } return retval; } // routine checks to see if an object in the CC coords for our group is a // boundary, and if so it returns CC coords of what an object that it is a // boundary of. Null vector is returned if not boundary. std::vector NMarkedAbelianGroup::writeAsBoundary( const std::vector &input) const { static const std::vector nullvec; if ( !isCycle(input) ) return nullvec; // okay, it's a cycle so lets determine whether or not it is a boundary. std::vector temp(ON.rows(), NLargeInteger::zero); for (unsigned long i=0; i retval(ON.columns(), NLargeInteger::zero); if (coeff == 0) { std::vector snfV(ornC->rows(), NLargeInteger::zero); for (unsigned long i=0;irows();i++) for (unsigned long j=0;jcolumns();j++) snfV[i] += ornC->entry(i,j)*temp[j+rankOM]; // check divisibility in the invFac coords for (unsigned long i=0; irows(); i++) for (unsigned long j=0; jentry(i, j) * snfV[j]; } else {// find tensorV -- apply otC. std::vector tensorV( otC->rows(), NLargeInteger::zero); for (unsigned long i=0; irows(); i++) for (unsigned long j=0; jcolumns(); j++) tensorV[i] += otC->entry(i, j) * temp[ j + rankOM ]; for (unsigned long i=0; ientry(i,j) * tensorV[j]; // ah! the other coefficients of otR gives the relevant congruence. } return retval; } // returns the j+TORLoc -th column of the matrix OMR, rescaled appropriately // if it corresponds to a TOR vector. std::vector NMarkedAbelianGroup::cycleGen(unsigned long j) const { static const std::vector nullv; if (j >= minNumberCycleGens()) return nullv; std::vector retval( OM.columns(), NLargeInteger::zero); for (unsigned long i=0; i NMarkedAbelianGroup::cycleProjection( const std::vector &ccelt ) const { // multiply by OMRi, truncate, multiply by OMR static const std::vector nullv; if (ccelt.size() != OMRi.columns()) return nullv; std::vector retval( OMRi.columns(), NLargeInteger::zero ); for (unsigned long i=0; i NMarkedAbelianGroup::cycleProjection( unsigned long ccindx ) const { // truncate column cyclenum of OMRi, multiply by OMR static const std::vector nullv; if (ccindx >= OMRi.columns()) return nullv; std::vector retval( OMRi.columns(), NLargeInteger::zero ); for (unsigned long i=0; i NMarkedAbelianGroup::torsionSubgroup() const { NMatrixInt dM(1, getNumberOfInvariantFactors() ); NMatrixInt dN(getNumberOfInvariantFactors(), getNumberOfInvariantFactors() ); for (unsigned long i=0; i(new NMarkedAbelianGroup(dM, dN)); } // and its canonical inclusion map std::auto_ptr NMarkedAbelianGroup::torsionInclusion() const { NMatrixInt iM( getRankCC(), getNumberOfInvariantFactors() ); for (unsigned long j=0; j jtor( getTorsionRep(j) ); for (unsigned long i=0; i(new NHomMarkedAbelianGroup( *torsionSubgroup(), (*this), iM)); } NHomMarkedAbelianGroup::NHomMarkedAbelianGroup(const NMatrixInt &tobeRedMat, const NMarkedAbelianGroup &dom, const NMarkedAbelianGroup &ran) : domain(dom), range(ran), matrix(ran.getM().columns(), dom.getM().columns()), reducedMatrix(0), kernel(0), coKernel(0), image(0), reducedKernelLattice(0) { reducedMatrix = new NMatrixInt(tobeRedMat); // If using mod p coeff, p != 0: // // we build up the CC map in reverse from the way we computed // the structure of the domain/range groups. // which was: 3) SNF(M,M'), truncate off first TORLoc coords. // 2) SNF the tensorPres matrix, TOR coords fixed. // Truncate off first tensorIfLoc terms. // 1) SNF the combined matrix, truncate off ifLoc terms. // // Step 1: ran.ornCi*[incl tobeRedMat]*[trunc dom.ornC] puts us in // diagPres coords ran.ornCi.rows()-by-dom.ornC.rows() // Step 2: ran.otCi*(step 1)*[trunc dom.otC] puts us in trunc(SNF(M,M')) // coords // Step 3: OMR*(step 2)*[trunc OMRi] // If using integer coefficients: // // we build up the CC map in reverse of the process for which we found // the structure of the domain/range // groups, which was: 2) SNF(M,M'), truncate off the first // rankOM==TORLoc coords // 1) SNF(N,N'), truncate off the first ifLoc terms. // // Step 1: ran.ornCi*[incl tobeRedMat]*[trunc dom.ornC] puts us // in trunc(SNF(M,M')) coords // Step 2: --void-- // Step 3: OMR*(step 1)*[trunc OMRi] // so we have a common Step 1. NMatrixInt step1Mat(ran.ornCi->rows(), dom.ornC->rows()); for (unsigned long i=0; iornCi.entry(i, k)*tobeRedMat.entry(k, l)*dom->ornC.entry(l, j) for (unsigned long k=0; kentry(i,k+ran.ifLoc)*tobeRedMat.entry(k,l)* dom.ornC->entry(l+dom.ifLoc,j); } // with mod p coefficients we have this fiddly middle step 2. NMatrixInt step2Mat( step1Mat.rows()+ran.tensorIfLoc, step1Mat.columns()+dom.tensorIfLoc ); // if coeff==0, we'll just copy the step1Mat, if coeff>0 we multiply // the tensor part by ran.otCi, dom.otC resp. if (dom.coeff == 0) for (unsigned long i=0; iotCi.entry(i,k)*incl_tensorIfLoc)*step1Mat.entry(k,l)* // ID_TOR x trunc_tensorIfLoc*dom->otC.entry(l, j)) app shifted... if (i < ran.TORVec.size()) { if (j < dom.TORVec.size()) { step2Mat.entry(i,j) = step1Mat.entry(i,j); } else { // [step1 UR corner] * [dom->otC first tensorIfLoc rows cropped] for (unsigned long k=dom.tensorIfLoc; krows(); k++) step2Mat.entry(i,j) += step1Mat.entry(i,k-dom.tensorIfLoc+dom.TORVec.size())* dom.otC->entry(k,j-dom.TORVec.size()); } } else if (j < dom.TORVec.size()) { for (unsigned long k=ran.tensorIfLoc; kcolumns(); k++) step2Mat.entry(i,j) += ran.otCi->entry(i-ran.TORVec.size(),k)* step1Mat.entry(k-ran.tensorIfLoc+ran.TORVec.size(),j); } else { for (unsigned long k=ran.tensorIfLoc; krows(); k++) for (unsigned long l=dom.tensorIfLoc; lrows(); l++) step2Mat.entry(i,j) += ran.otCi->entry(i-ran.TORVec.size(),k)* step1Mat.entry(k-ran.tensorIfLoc+ran.TORVec.size(), l-dom.tensorIfLoc+dom.TORVec.size())* dom.otC->entry(l,j-dom.TORVec.size()); } } // now we rescale the TOR components appropriately, various row/column // mult and divisions. multiply first ran.TORLoc rows by p/gcd(p,q) // divide first dom.TORLoc rows by p/gcd(p,q) for (unsigned long i=0; icolumns(); j++) { std::vector colV( (j icv( matrix.rows(), NLargeInteger::zero); for (unsigned long i=0; i midge( range.snfRep(icv) ); for (unsigned long i=0; ientry(i,j) = midge[i]; } } } void NHomMarkedAbelianGroup::computeReducedKernelLattice() { if (!reducedKernelLattice) { computeReducedMatrix(); const NMatrixInt& redMatrix(*reducedMatrix); std::vector dcL(range.getRank() + range.getNumberOfInvariantFactors() ); for (unsigned long i=0; irows(), reducedMatrix->columns() + range.getNumberOfInvariantFactors() ); unsigned i,j; for (i=0;irows();i++) for (j=0;jcolumns();j++) ccrelators.entry(i,j)=reducedMatrix->entry(i,j); for (i=0;icolumns())= range.getInvariantFactor(i); NMatrixInt ccgenerators( 1, reducedMatrix->rows() ); coKernel = new NMarkedAbelianGroup(ccgenerators, ccrelators); } } void NHomMarkedAbelianGroup::computeImage() { if (!image) { computeReducedKernelLattice(); const NMatrixInt& dcLpreimage( *reducedKernelLattice ); NMatrixInt imgCCm(1, dcLpreimage.rows() ); NMatrixInt imgCCn(dcLpreimage.rows(), dcLpreimage.columns() + domain.getNumberOfInvariantFactors() ); for (unsigned long i=0;i NHomMarkedAbelianGroup::operator * (const NHomMarkedAbelianGroup &X) const { std::auto_ptr > prod=matrix*X.matrix; NMatrixInt compMat(matrix.rows(), X.matrix.columns() ); for (unsigned long i=0;irows();i++) for (unsigned long j=0;jcolumns();j++) compMat.entry(i,j) = prod->entry(i, j); return std::auto_ptr(new NHomMarkedAbelianGroup(X.domain, range, compMat)); } std::vector NHomMarkedAbelianGroup::evalCC( const std::vector &input) const { std::vector retval(matrix.rows(), NLargeInteger::zero); for (unsigned long i=0; i NHomMarkedAbelianGroup::evalSNF( const std::vector &input) const { const_cast(this)->computeReducedMatrix(); static const std::vector nullV; if (input.size() != domain.minNumberOfGenerators() ) return nullV; std::vector retval( range.minNumberOfGenerators(), NLargeInteger::zero ); for (unsigned long i=0; i(this)->computeReducedMatrix(); out<<"Reduced Matrix is "<rows()<<" by " <columns()<<" corresponding to domain "; domain.writeTextShort(out); out<<" and range "; range.writeTextShort(out); out<<"\n"; for (unsigned long i=0;irows();i++) { out<<"["; for (unsigned long j=0;jcolumns();j++) { out<entry(i,j); if (j+1 < reducedMatrix->columns()) out<<" "; } out<<"]\n"; } } void NHomMarkedAbelianGroup::writeTextShort(std::ostream& out) const { if (isIsomorphism()) out<<"isomorphism"; else if (isZero()) out<<"zero map"; else if (isMonic()) { // monic not epic out<<"monic, with cokernel "; getCokernel().writeTextShort(out); } else if (isEpic()) { // epic not monic out<<"epic, with kernel "; getKernel().writeTextShort(out); } else { // nontrivial not epic, not monic out<<"kernel "; getKernel().writeTextShort(out); out<<" | cokernel "; getCokernel().writeTextShort(out); out<<" | image "; getImage().writeTextShort(out); } } void NHomMarkedAbelianGroup::writeTextLong(std::ostream& out) const { out<<"hom[ "; domain.writeTextShort(out); out<<" --> "; range.writeTextShort(out); out<<" ] "; writeTextShort(out); } bool NHomMarkedAbelianGroup::isIdentity() const { if (!(domain.equalTo(range))) return false; const_cast(this)->computeReducedMatrix(); if (!reducedMatrix->isIdentity()) return false; return true; } bool NHomMarkedAbelianGroup::isCycleMap() const { for (unsigned long j=0; j cycJ( domain.cycleGen(j) ); std::vector FcycJ( range.getRankCC(), NLargeInteger::zero ); for (unsigned long i=0; i NHomMarkedAbelianGroup::torsionSubgroup() const { std::auto_ptr dom = domain.torsionSubgroup(); std::auto_ptr ran = range.torsionSubgroup(); NMatrixInt mat(range.getNumberOfInvariantFactors(), domain.getNumberOfInvariantFactors() ); for (unsigned long j=0; j in range's snfRep coords std::vector temp(range.snfRep(evalCC( domain.getTorsionRep(j)))); for (unsigned long i=0; i(new NHomMarkedAbelianGroup( *dom, *ran, mat)); } /** * Given two NHomMarkedAbelianGroups, you have two diagrams: * Z^a --N1--> Z^b --M1--> Z^c Z^g --N3--> Z^h --M3--> Z^i * ^ ^ * | this | other * Z^d --N2--> Z^e --M2--> Z^f Z^j --N4--> Z^k --M4--> Z^l * @return true if and only if M1 == N3, M2 == N4 and diagram commutes * commutes. */ bool NHomMarkedAbelianGroup::isChainMap( const NHomMarkedAbelianGroup &other) const { if ( (getRange().getM().rows() != other.getRange().getN().rows()) || (getRange().getM().columns() != other.getRange().getN().columns()) || (getDomain().getM().rows() != other.getDomain().getN().rows()) || (getDomain().getM().columns() != other.getDomain().getN().columns()) ) return false; if ( (getRange().getM() != other.getRange().getN()) || (getDomain().getM() != other.getDomain().getN()) ) return false; std::auto_ptr< NMatrixRing > prodLU = range.getM() * getDefiningMatrix(); std::auto_ptr< NMatrixRing > prodBR = other.getDefiningMatrix() * domain.getM(); if ( (*prodLU) != (*prodBR) ) return false; return true; } // Start with the reduced matrix which is a 2x2 block matrix: // // [A|B] // [---] where D is an inveritble square matrix, 0 is a zero matrix, // [0|D] A a square matrix and B maybe not square. // the columns of D represent the free factors of the domain, // the rows of D the free factors of the range, // the columns/rows of A represent the torsion factors of the domain/range // respectively. So the inverse matrix must have the form // [A'|B'] // [-----] // [0 |D'] where D' is the inverse of D, A' represents the inverse // automorphism of // Z_p1 + Z_p2 + ... Z_pk, etc. And so B' must equal -A'BD', which is readily //computable. So it all boils down to computing A'. So we need a routine which //makes a matrix A representing an automorphism of Z_p1 + ... Z_pk and then // computes the matrix representing the inverse automorphism. // So to do this we'll need a new matrixops.cpp command -- call it // torsionAutInverse. std::auto_ptr NHomMarkedAbelianGroup::inverseHom() const { const_cast(this)->computeReducedMatrix(); NMatrixInt invMat( reducedMatrix->columns(), reducedMatrix->rows() ); if (!isIsomorphism()) return std::auto_ptr( new NHomMarkedAbelianGroup( invMat, range, domain )); // get A, B, D from reducedMatrix // A must be square with domain/range.getNumberOfInvariantFactors() columns // D must be square with domain/range.getRank() columns // B may not be square with domain.getRank() columns and // range.getNumberOfInvariantFactors() rows. NMatrixInt A(range.getNumberOfInvariantFactors(), domain.getNumberOfInvariantFactors()); NMatrixInt B(range.getNumberOfInvariantFactors(), domain.getRank()); NMatrixInt D(range.getRank(), domain.getRank()); for (unsigned long i=0; ientry(i,j); for (unsigned long i=0; ientry(i, j + A.columns()); for (unsigned long i=0; ientry( i + A.rows(), j + A.columns() ); // compute A', B', D' // use void columnEchelonForm(NMatrixInt &M, NMatrixInt &R, NMatrixInt &Ri, // const std::vector &rowList); // from matrixOps to compute the inverse of D. NMatrixInt Di(D.rows(), D.columns()); Di.makeIdentity(); NMatrixInt Dold(D.rows(), D.columns()); Dold.makeIdentity(); std::vector rowList(D.rows()); for (unsigned i=0; i invF(domain.getNumberOfInvariantFactors()); for (unsigned long i=0; i Ai = torsionAutInverse( A, invF); // then Bi is given by Bi = -AiBDi NMatrixInt Bi(range.getNumberOfInvariantFactors(), domain.getRank()); NMatrixInt Btemp(range.getNumberOfInvariantFactors(), domain.getRank()); // Btemp will give -BDi // Bi will be AiBtemp for (unsigned long i=0; icolumns(); k++) Bi.entry(i,j) += Ai->entry(i,k)*Btemp.entry(k,j); // reduce Ai and Bi respectively. for (unsigned long i=0; irows(); i++) { for (unsigned long j=0; jcolumns(); j++) { Ai->entry(i,j) %= domain.getInvariantFactor(i); if (Ai->entry(i,j) < 0) Ai->entry(i,j) += domain.getInvariantFactor(i); } for (unsigned long j=0; jrows(); i++) for (unsigned long j=0; jcolumns(); j++) invMat.entry(i,j) = Ai->entry(i,j); for (unsigned long i=0; irows(),j+Ai->columns()) = Di.entry(i,j); for (unsigned long i=0; icolumns()) = Bi.entry(i,j); return std::auto_ptr( new NHomMarkedAbelianGroup( invMat, range, domain )); } } // namespace regina regina-4.96/engine/algebra/nmarkedabeliangroup.h000644 000765 000024 00000170555 12377774624 021675 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file algebra/nmarkedabeliangroup.h * \brief Deals with abelian groups given by chain complexes. */ #ifndef __NMARKEDABELIANGROUP_H #ifndef __DOXYGEN #define __NMARKEDABELIANGROUP_H #endif #include #include #include "regina-core.h" #include "maths/nmatrixint.h" #include "utilities/ptrutils.h" namespace regina { class NHomMarkedAbelianGroup; /** * \weakgroup algebra * @{ */ /** * Represents a finitely generated abelian group given by a chain complex. * * This class is initialized with a chain complex. The chain complex is given * in terms of two integer matrices \a M and \a N such that M*N=0. The abelian * group is the kernel of \a M mod the image of \a N. * * In other words, we are computing the homology of the chain complex * Z^a --N--> Z^b --M--> Z^c * where a=N.columns(), M.columns()=b=N.rows(), and c=M.rows(). An additional * constructor allows one to take the homology with coefficients in an arbitrary * cyclic group. * * This class allows one to retrieve the invariant factors, the rank, and * the corresponding vectors in the kernel of \a M. Moreover, given a * vector in the kernel of \a M, it decribes the homology class of the * vector (the free part, and its position in the invariant factors). * * The purpose of this class is to allow one to not only * represent homology groups, but it gives coordinates on the group allowing * for the construction of homomorphisms, and keeping track of subgroups. * * Some routines in this class refer to the internal presentation * matrix. This is a proper presentation matrix for the abelian group, * and is created by constructing the product getMRBi() * \a N, and then * removing the first getRankM() rows. * * @author Ryan Budney * * \todo \optlong Look at using sparse matrices for storage of SNF and the like. * \todo Testsuite additions: isBoundary(), boundaryMap(), writeAsBdry(), * cycleGen(). */ class REGINA_API NMarkedAbelianGroup : public ShareableObject { private: /** Internal original M */ NMatrixInt OM; // copy of initializing M /** Internal original N */ NMatrixInt ON; // copy of initializing N assumes M*N == 0 /** Internal change of basis. SNF(OM) == OMC*OM*OMR */ NMatrixInt OMR, OMC; /** Internal change of basis. OM = OMCi*SNF(OM)*OMRi */ NMatrixInt OMRi, OMCi; /** Internal rank of M */ unsigned long rankOM; // this is the index of the first zero entry // in SNF(OM) /* Internal reduced N matrix: */ // In the notes below, ORN refers to the internal presentation // matrix [OMRi * ON], where the brackets indicate removal of the // first rankOM rows. /** Internal change of basis. ornC * ORN * ornR is the SNF(ORN). */ std::auto_ptr ornR, ornC; /** Internal change of basis. These are the inverses of ornR and ornC respectively. */ std::auto_ptr ornRi, ornCi; /** Internal change of basis matrix for homology with coefficents. otC * tensorPres * otR == SNF(tensorPres) */ std::auto_ptr otR, otC, otRi, otCi; /** Internal list of invariant factors. */ std::vector InvFacList; /** The number of free generators, from SNF(ORN) */ unsigned long snfrank; /** The row index of the first zero along the diagonal in SNF(ORN). */ unsigned long snffreeindex; /** Number of invariant factors. */ unsigned long ifNum; /** Row index of first invariant factor (ie entry > 1) in SNF(ORN) */ unsigned long ifLoc; // These variables store information for mod-p homology computations. /** coefficients to use in homology computation **/ NLargeInteger coeff; /** TORLoc stores the location of the first TOR entry from the SNF of OM: TORLoc == rankOM-TORVec.size() */ unsigned long TORLoc; /** TORVec's i-th entry stores the entries q where Z_p --q-->Z_p is the i-th TOR entry from the SNF of OM */ std::vector TORVec; /** invariant factor data in the tensor product presentation matrix SNF */ unsigned long tensorIfLoc; unsigned long tensorIfNum; std::vector tensorInvFacList; // and NHomMarkedAbelianGroup at present needs to see some of the // internals of NMarkedAbelianGroup // at present this is only used for inverseHom(). friend class NHomMarkedAbelianGroup; public: /** * Creates a marked abelian group from a chain complex. This constructor * assumes you're interested in homology with integer coefficents of * the chain complex. Creates a marked abelian group given by * the quotient of the kernel of \a M modulo the image of \a N. * * See the class notes for further details. * * \pre M.columns() = N.rows(). * \pre The product M*N = 0. * * @param M the `right' matrix in the chain complex; that is, * the matrix that one takes the kernel of when computing homology. * @param N the `left' matrix in the chain complex; that is, the * matrix that one takes the image of when computing homology. */ NMarkedAbelianGroup(const NMatrixInt& M, const NMatrixInt& N); /** * Creates a marked abelian group from a chain complex with * coefficients in Z_p. * * \pre M.columns() = N.rows(). * \pre The product M*N = 0. * * @param M the `right' matrix in the chain complex; that is, * the matrix that one takes the kernel of when computing homology. * @param N the `left' matrix in the chain complex; that is, the * matrix that one takes the image of when computing homology. * @param pcoeff specifies the coefficient ring, Z_pcoeff. We require * \a pcoeff >= 0. If you know beforehand that \a pcoeff=0, it's * more efficient to use the previous constructor. */ NMarkedAbelianGroup(const NMatrixInt& M, const NMatrixInt& N, const NLargeInteger &pcoeff); /** * Creates a free Z_p-module of a given rank using the direct sum * of the standard chain complex 0 --> Z --p--> Z --> 0. * So this group is isomorphic to n Z_p. Moreover, if * constructed using the previous constructor, \a M would be zero * and \a N would be diagonal and square with \a p down the diagonal. * * @param rk the rank of the group as a Z_p-module. That is, if the * group is n Z_p, then \a rk should be \a n. * @param p describes the type of ring that we use to talk about * the "free" module. */ NMarkedAbelianGroup(unsigned long rk, const NLargeInteger &p); /** * Creates a clone of the given group. * * @param cloneMe the group to clone. */ NMarkedAbelianGroup(const NMarkedAbelianGroup& cloneMe); /** * Determines whether or not the defining maps for this group * actually give a chain complex. This is helpful for debugging. * * Specifically, this routine returns \c true if and only if * M*N = 0 where M and N are the definining matrices. * * @return \c true if and only if M*N = 0. */ bool isChainComplex() const; /** * Destroys the group. */ ~NMarkedAbelianGroup(); /** * Returns the rank of the group. * This is the number of included copies of Z. * * @return the rank of the group. */ unsigned long getRank() const; /** * Returns the rank in the group of the torsion term of given degree. * If the given degree is d, this routine will return the * largest m for which mZ_d is a subgroup * of this group. * * For instance, if this group is Z_6+Z_12, the torsion term of * degree 2 has rank 2 (one occurrence in Z_6 and one in Z_12), * and the torsion term of degree 4 has rank 1 (one occurrence * in Z_12). * * \pre The given degree is at least 2. * * @param degree the degree of the torsion term to query. * @return the rank in the group of the given torsion term. */ unsigned long getTorsionRank(const NLargeInteger& degree) const; /** * Returns the rank in the group of the torsion term of given degree. * If the given degree is d, this routine will return the * largest m for which mZ_d is a subgroup * of this group. * * For instance, if this group is Z_6+Z_12, the torsion term of * degree 2 has rank 2 (one occurrence in Z_6 and one in Z_12), * and the torsion term of degree 4 has rank 1 (one occurrence * in Z_12). * * \pre The given degree is at least 2. * * @param degree the degree of the torsion term to query. * @return the rank in the group of the given torsion term. */ unsigned long getTorsionRank(unsigned long degree) const; /** * Returns the number of invariant factors that describe the * torsion elements of this group. This is the minimal number * of torsion generators. * See the NMarkedAbelianGroup class notes for further details. * * @return the number of invariant factors. */ unsigned long getNumberOfInvariantFactors() const; /** * Returns the minimum number of generators for the group. * * @return the minimum number of generators. */ unsigned long minNumberOfGenerators() const; /** * Returns the given invariant factor describing the torsion * elements of this group. * See the NMarkedAbelianGroup class notes for further details. * * If the invariant factors are d0|d1|...|dn, * this routine will return di where i is the * value of parameter \a index. * * @param index the index of the invariant factor to return; * this must be between 0 and getNumberOfInvariantFactors()-1 * inclusive. * @return the requested invariant factor. */ const NLargeInteger& getInvariantFactor(unsigned long index) const; /** * Determines whether this is the trivial (zero) group. * * @return \c true if and only if this is the trivial group. */ bool isTrivial() const; /** * Determines whether this and the given abelian group are * isomorphic. * * \deprecated This routine will be removed in a future version * of Regina. Users should switch to the less ambiguously named * routine isIsomorphicTo() instead. * * @param other the group with which this should be compared. * @return \c true if and only if the two groups are isomorphic. */ bool operator == (const NMarkedAbelianGroup &other) const; /** * Determines whether this and the given abelian group are * isomorphic. * * @param other the group with which this should be compared. * @return \c true if and only if the two groups are isomorphic. */ bool isIsomorphicTo(const NMarkedAbelianGroup &other) const; /** * Determines whether or not the two NMarkedAbelianGroups are * identical, which means they have exactly the same presentation * matrices. This is useful for determining if two * NHomMarkedAbelianGroups are composable. See isIsomorphicTo() if * all you care about is the isomorphism relation among groups * defined by presentation matrices. * * @param other the NMarkedAbelianGroup with which this should be * compared. * @return \c true if and only if the two groups have identical * chain-complex definitions. */ bool equalTo(const NMarkedAbelianGroup& other) const; /** * The text representation will be of the form * 3 Z + 4 Z_2 + Z_120. * The torsion elements will be written in terms of the * invariant factors of the group, as described in the * NMarkedAbelianGroup notes. * * @param out the stream to write to. */ void writeTextShort(std::ostream& out) const; /** * Returns the requested free generator in the original chain * complex defining the group. * * As described in the class overview, this marked abelian group * is defined by matrices \a M and \a N where M*N = 0. * If \a M is an \a m by \a l matrix and \a N is an \a l by \a n * matrix, then this routine returns the (\a index)th free * generator of ker(M)/img(N) in \a Z^l. * * \warning The return value may change from version to version * of Regina, since it depends on the choice of Smith normal form. * * \ifacespython The return value will be a python list. * * @param index specifies which free generator to look up; * this must be between 0 and getRank()-1 inclusive. * @return the coordinates of the free generator in the nullspace of * \a M; this vector will have length M.columns() (or * equivalently, N.rows()). If this generator does not exist, * you will receive an empty vector. */ std::vector getFreeRep(unsigned long index) const; /** * Returns the requested generator of the torsion subgroup but * represented in the original chain complex defining the group. * * As described in the class overview, this marked abelian group * is defined by matrices \a M and \a N where M*N = 0. * If \a M is an \a m by \a l matrix and \a N is an \a l by \a n * matrix, then this routine returns the (\a index)th torsion * generator of ker(M)/img(N) in \a Z^l. * * \ifacespython The return value will be a python list. * * \warning The return value may change from version to version * of Regina, since it depends on the choice of Smith normal form. * * @param index specifies which generator in the torsion subgroup; * this must be at least 0 and strictly less than the number of * non-trivial invariant factors. If not, you receive an empty * vector. * @return the coordinates of the generator in the nullspace of * \a M; this vector will have length M.columns() (or * equivalently, N.rows()). */ std::vector getTorsionRep(unsigned long index) const; /** * A combination of getFreeRep and getTorsion rep, this routine takes * a vector which represents an element in the group in the SNF * coordinates and returns a corresponding vector in the original * chain complex. * * This routine is the inverse to snfRep() described below. * * \warning The return value may change from version to version * of Regina, since it depends on the choice of Smith normal form. * * \ifacespython Not available yet. This routine will be made * accessible to Python in a future release. * * @param SNFRep a vector of size the number of generators of * the group, i.e., it must be valid in the SNF coordinates. If not, * an empty vector is returned. * @return a corresponding vector whose length is M.columns(), * where \a M is one of the matrices that defines the chain * complex; see the class notes for details. */ std::vector ccRep( const std::vector& SNFRep) const; /** * Same as ccRep(const std::vector&), but we assume you * only want the chain complex representation of a standard basis * vector from SNF coordinates. * * \warning The return value may change from version to version * of Regina, since it depends on the choice of Smith normal form. * * \ifacespython Not available yet. This routine will be made * accessible to Python in a future release. * * @param SNFRep specifies which standard basis vector from SNF * coordinates; this must be between 0 and * minNumberOfGenerators()-1 inclusive. * @return a corresponding vector whose length is M.columns(), * where \a M is one of the matrices that defines the chain * complex; see the class notes for details. */ std::vector ccRep(unsigned long SNFRep) const; /** * Projects an element of the chain complex to the subspace of cycles. * Returns an empty vector if the input element does not have * dimensions of the chain complex. * * \warning The return value may change from version to version * of Regina, since it depends on the choice of Smith normal form. * * \ifacespython Not available yet. This routine will be made * accessible to Python in a future release. * * @param ccelt a vector whose length is M.columns(), * where \a M is one of the matrices that defines the chain * complex (see the class notes for details). * @return a corresponding vector, also in the chain complex * coordinates. */ std::vector cycleProjection( const std::vector &ccelt) const; /** * Projects an element of the chain complex to the subspace of cycles. * Returns an empty vector if the input index is out of bounds. * * \warning The return value may change from version to version * of Regina, since it depends on the choice of Smith normal form. * * \ifacespython Not available yet. This routine will be made * accessible to Python in a future release. * * @param ccindx the index of the standard basis vector in chain * complex coordinates. * @return the resulting projection, in the chain complex * coordinates. */ std::vector cycleProjection(unsigned long ccindx) const; /** * Given a vector, determines if it represents a cycle in the chain * complex. * * \ifacespython Not available yet. This routine will be made * accessible to Python in a future release. * * @param input an input vector in chain complex coordinates. * @return \c true if and only if the given vector represents a cycle. */ bool isCycle(const std::vector &input) const; /** * Computes the differential of the given vector in the chain * complex whose kernel is the cycles. In other words, this * routine returns M*CCrep. * * \ifacespython Not available yet. This routine will be made * accessible to Python in a future release. * * @param CCrep a vector whose length is M.columns(), * where \a M is one of the matrices that defines the chain * complex (see the class notes for details). * @return the differential, expressed as a vector of length M.rows(). */ std::vector boundaryMap( const std::vector &CCrep) const; /** * Given a vector, determines if it represents a boundary in the chain * complex. * * \ifacespython Not available yet. This routine will be made * accessible to Python in a future release. * * @param input a vector whose length is M.columns(), * where \a M is one of the matrices that defines the chain * complex (see the class notes for details). * @return \c true if and only if the given vector represents a * boundary. */ bool isBoundary(const std::vector &input) const; /** * Expresses the given vector as a boundary in the chain complex * (if the vector is indeed a boundary at all). This routine * uses chain complex coordinates for both the input and the * return value. * * \warning If you're using mod-p coefficients and if your element * projects to a non-trivial element of TOR, then Nv != input as * elements of TOR aren't in the image of N. In this case, * input-Nv represents the projection to TOR. * * \warning The return value may change from version to version * of Regina, since it depends on the choice of Smith normal form. * * \ifacespython Not available yet. This routine will be made * accessible to Python in a future release. * * @return a length zero vector if the input is not a boundary; * otherwise a vector \a v such that Nv=input. */ std::vector writeAsBoundary( const std::vector &input) const; /** * Returns the rank of the chain complex supporting the homology * computation. In the description of this class, this is also given * by M.columns() and N.rows() from the constructor that takes as * input two matrices, M and N. * * @return the rank of the chain complex. */ unsigned long getRankCC() const; /** * Expresses the given vector as a combination of free and torsion * generators. This answer is coordinate dependant, meaning the answer * may change depending on how the Smith Normal Form is computed. * * Recall that this marked abelian was defined by matrices \a M * and \a N with M*N=0; suppose that \a M is an \a m by \a l matrix * and \a N is an \a l by \a n matrix. This abelian group is then * the quotient ker(M)/img(N) in \a Z^l. * * When it is constructed, this group is computed to be isomorphic to * some Z_{d0} + ... + Z_{dk} + Z^d, where: * * - \a d is the number of free generators, as returned by getRank(); * - \a d1, ..., \a dk are the invariant factors that describe the * torsion elements of the group, where * 1 < \a d1 | \a d2 | ... | \a dk. * * This routine takes a single argument \a v, which must be a * vector in \a Z^l. * * If \a v belongs to ker(M), this routine describes how it * projects onto the group ker(M)/img(N). Specifically, it * returns a vector of length \a d + \a k, where: * * - The first \a k elements describe the projection of \a v * to the torsion component Z_{d1} + ... + Z_{dk}. These * elements are returned as non-negative integers modulo * \a d1, ..., \a dk respectively. * - The remaining \a d elements describe the projection of \a v * to the free component \a Z^d. * * In other words, suppose \a v belongs to ker(M) and snfRep(v) * returns the vector (\a b1, ..., \a bk, \a a1, ..., \a ad). * Suppose furthermore that the free generators returned * by getFreeRep(0..(d-1)) are \a f1, ..., \a fd respectively, and * that the torsion generators returned by getTorsionRep(0..(k-1)) * are \a t1, ..., \a tk respectively. Then * \a v = \a b1.t1 + ... + \a bk.tk + \a a1.f1 + ... + \a ad.fd * modulo img(N). * * If \a v does not belong to ker(M), this routine simply returns * the empty vector. * * \warning The return value may change from version to version * of Regina, as it depends on the choice of Smith normal form. * * \pre Vector \a v has length M.columns(), or equivalently N.rows(). * * \ifacespython Both \a v and the return value are python lists. * * @param v a vector of length M.columns(). M.columns() is also * getRankCC(). * * @return a vector that describes \a v in the standard * Z_{d1} + ... + Z_{dk} + Z^d form, or the empty vector if * \a v is not in the kernel of \a M. k+d is equal to * minNumberOfGenerators(). * */ std::vector snfRep( const std::vector& v) const; /** * A deprecated alternative to snfRep(). * * \deprecated This routine has been renamed to snfRep(). See * snfRep() for details, preconditions and warnings. * * \ifacespython Both \a v and the return value are python lists. * * @param v a vector of length M.columns(). * @return a vector that describes \a v in the standard * Z_{d1} + ... + Z_{dk} + Z^d form, or the empty vector if * \a v is not in the kernel of \a M. */ std::vector getSNFIsoRep( const std::vector& v) const; /** * Returns the number of generators of ker(M), where M is one of * the defining matrices of the chain complex. * * @return the number of generators of ker(M). */ unsigned long minNumberCycleGens() const; /** * Returns the ith generator of the cycles, i.e., the kernel of * M in the chain complex. * * \warning The return value may change from version to version * of Regina, as it depends on the choice of Smith normal form. * * \ifacespython Not available yet. This routine will be made * accessible to Python in a future release. * * @param i between 0 and minNumCycleGens()-1. * @return the corresponding generator in chain complex coordinates. */ std::vector cycleGen(unsigned long i) const; /** * Returns a change-of-basis matrix for the Smith normal form of \a M. * * This is one of several routines that returns information on * how we determine the isomorphism-class of this group. * * Recall from the class overview that this marked abelian group * is defined by matrices \a M and \a N, where M*N = 0. * * - getMCB() * M * getMRB() is the Smith normal form of \a M; * - getMCBi() and getMRBi() are the inverses of getMCB() and getMRB() * respectively. * * \deprecated This routine will be removed in Regina 5.0. * * @return the matrix getMRB() as described above. */ const NMatrixInt& getMRB() const; /** * Returns an inverse change-of-basis matrix for the Smith normal * form of \a M. * * This is one of several routines that returns information on * how we determine the isomorphism-class of this group. * * Recall from the class overview that this marked abelian group * is defined by matrices \a M and \a N, where M*N = 0. * * - getMCB() * M * getMRB() is the Smith normal form of \a M; * - getMCBi() and getMRBi() are the inverses of getMCB() and getMRB() * respectively. * * \deprecated This routine will be removed in Regina 5.0. * * @return the matrix getMRBi() as described above. */ const NMatrixInt& getMRBi() const; /** * Returns a change-of-basis matrix for the Smith normal form of \a M. * * This is one of several routines that returns information on * how we determine the isomorphism-class of this group. * * Recall from the class overview that this marked abelian group * is defined by matrices \a M and \a N, where M*N = 0. * * - getMCB() * M * getMRB() is the Smith normal form of \a M; * - getMCBi() and getMRBi() are the inverses of getMCB() and getMRB() * respectively. * * \deprecated This routine will be removed in Regina 5.0. * * @return the matrix getMCB() as described above. */ const NMatrixInt& getMCB() const; /** * Returns an inverse change-of-basis matrix for the Smith normal * form of \a M. * * This is one of several routines that returns information on * how we determine the isomorphism-class of this group. * * Recall from the class overview that this marked abelian group * is defined by matrices \a M and \a N, where M*N = 0. * * - getMCB() * M * getMRB() is the Smith normal form of \a M; * - getMCBi() and getMRBi() are the inverses of getMCB() and getMRB() * respectively. * * \deprecated This routine will be removed in Regina 5.0. * * @return the matrix getMCBi() as described above. */ const NMatrixInt& getMCBi() const; /** * Returns a change-of-basis matrix for the Smith normal form of * the internal presentation matrix. * * This is one of several routines that returns information on * how we determine the isomorphism-class of this group. * * For details on the internal presentation matrix, see the class * overview. If \a P is the internal presentation matrix, then: * * - getNCB() * P * getNRB() is the Smith normal form of \a P; * - getNCBi() and getNRBi() are the inverses of getNCB() and getNRB() * respectively. * * \deprecated This routine will be removed in Regina 5.0. * * @return the matrix getNRB() as described above. */ const NMatrixInt& getNRB() const; /** * Returns an inverse change-of-basis matrix for the Smith normal * form of the internal presentation matrix. * * This is one of several routines that returns information on * how we determine the isomorphism-class of this group. * * For details on the internal presentation matrix, see the class * overview. If \a P is the internal presentation matrix, then: * * - getNCB() * P * getNRB() is the Smith normal form of \a P; * - getNCBi() and getNRBi() are the inverses of getNCB() and getNRB() * respectively. * * \deprecated This routine will be removed in Regina 5.0. * * @return the matrix getNRBi() as described above. */ const NMatrixInt& getNRBi() const; /** * Returns a change-of-basis matrix for the Smith normal form of * the internal presentation matrix. * * This is one of several routines that returns information on * how we determine the isomorphism-class of this group. * * For details on the internal presentation matrix, see the class * overview. If \a P is the internal presentation matrix, then: * * - getNCB() * P * getNRB() is the Smith normal form of \a P; * - getNCBi() and getNRBi() are the inverses of getNCB() and getNRB() * respectively. * * \deprecated This routine will be removed in Regina 5.0. * * @return the matrix getNCB() as described above. */ const NMatrixInt& getNCB() const; /** * Returns an inverse change-of-basis matrix for the Smith normal * form of the internal presentation matrix. * * This is one of several routines that returns information on * how we determine the isomorphism-class of this group. * * For details on the internal presentation matrix, see the class * overview. If \a P is the internal presentation matrix, then: * * - getNCB() * P * getNRB() is the Smith normal form of \a P; * - getNCBi() and getNRBi() are the inverses of getNCB() and getNRB() * respectively. * * \deprecated This routine will be removed in Regina 5.0. * * @return the matrix getNCBi() as described above. */ const NMatrixInt& getNCBi() const; /** * Returns the rank of the defining matrix \a M. * * The matrix \a M is the `right' matrix used in defining the chain * complex. See the class overview for further details. * * \deprecated This routine will be removed in Regina 5.0. * * @return the rank of the defining matrix \a M. */ unsigned long getRankM() const; /** * Returns the index of the first free generator in the Smith * normal form of the internal presentation matrix. See the class * overview for details. * * \deprecated This routine will be removed in Regina 5.0. * * @return the index of the first free generator. */ unsigned long getFreeLoc() const; /** * Returns the index of the first torsion generator in the Smith * normal form of the internal presentation matrix. See the class * overview for details. * * \deprecated This routine will be removed in Regina 5.0. * * @return the index of the first torsion generator. */ unsigned long getTorsionLoc() const; /** * Returns the `right' matrix used in defining the chain complex. * Our group was defined as the kernel of \a M mod the image of \a N. * This is the matrix \a M. * * This is a copy of the matrix \a M that was originally passed to the * class constructor. See the class overview for further details on * matrices \a M and \a N and their roles in defining the chain complex. * * @return a reference to the defining matrix M. */ const NMatrixInt& getM() const; /** * Returns the `left' matrix used in defining the chain complex. * Our group was defined as the kernel of \a M mod the image of \a N. * This is the matrix \a N. * * This is a copy of the matrix \a N that was originally passed to the * class constructor. See the class overview for further details on * matrices \a M and \a N and their roles in defining the chain complex. * * @return a reference to the defining matrix N. */ const NMatrixInt& getN() const; /** * Returns the coefficients used for the computation of homology. * That is, this routine returns the integer \a p where we use * coefficients in Z_p. If we use coefficients in the integers Z, * then this routine returns 0. * * @return the coefficients used in the homology calculation. */ const NLargeInteger& coefficients() const; /** * Returns an NMarkedAbelianGroup representing the torsion subgroup * of this group. */ std::auto_ptr torsionSubgroup() const; /** * Returns an NHomMarkedAbelianGroup representing the inclusion of the * torsion subgroup into this group. */ std::auto_ptr torsionInclusion() const; }; /** * Represents a homomorphism of finitely generated abelian groups. * * One initializes such a homomorphism by providing: * * - two finitely generated abelian groups, which act as domain and range; * - a matrix describing the linear map between the free abelian * groups in the centres of the respective chain complexes that were * used to define the domain and range. If the abelian groups are computed * via homology with coefficients, the range coefficients must be a quotient * of the domain coefficients. * * So for example, if the domain was initialized by the chain complex * Z^a --A--> Z^b --B--> Z^c with mod p coefficients, and the range * was initialized by Z^d --D--> Z^e --E--> Z^f with mod q * coefficients, then the matrix needs to be an e-by-b matrix. * Furthermore, you only obtain a well-defined * homomorphism if this matrix extends to a cycle map, which this class * assumes but which the user can confirm with isCycleMap(). Moreover, * \a q should divide \a p: this allows for \a q > 0 and \a p = 0, * which means the domain has Z coefficients and the range has mod \a q * coefficients. * * \todo \optlong preImageOf in CC and SNF coordinates. This routine would * return a generating list of elements in the preimage, thought of as an * affine subspace. Or maybe just one element together with the kernel * inclusion. IMO smarter to be a list because that way there's a more * pleasant way to make it empty. Or we could have a variety of routines * among these themes. Store some minimal data for efficient computations of * preImage, eventually replacing the internals of inverseHom() with a more * flexible set of tools. Also add an isInImage() in various coordinates. * * \todo \optlong writeTextShort() have completely different set of * descriptors if an endomorphism domain = range (not so important at the * moment though). New descriptors would include things like automorphism, * projection, differential, finite order, etc. * * \todo \optlong Add map factorization, so that every homomorphism can be * split as a composite of a projection followed by an inclusion. Add * kernelInclusion(), coKerMap(), etc. Add a liftMap() call, i.e., a * procedure to find a lift of a map if one exists. * * @author Ryan Budney */ class REGINA_API NHomMarkedAbelianGroup : public ShareableObject { private: /** internal rep of domain of the homomorphism */ NMarkedAbelianGroup domain; /** internal rep of range of the homomorphism */ NMarkedAbelianGroup range; /** matrix describing map from domain to range, in the coordinates of the chain complexes used to construct domain and range, see above description */ NMatrixInt matrix; /** short description of matrix in SNF coordinates -- this means we've conjugated matrix by the relevant change-of-basis maps in both the domain and range so that we are using the coordinates of Smith Normal form. We also truncate off the trivial Z/Z factors so that reducedMatrix will not have the same dimensions as matrix. This means the torsion factors appear first, followed by the free factors. */ NMatrixInt* reducedMatrix; /** pointer to kernel of map */ NMarkedAbelianGroup* kernel; /** pointer to coKernel of map */ NMarkedAbelianGroup* coKernel; /** pointer to image */ NMarkedAbelianGroup* image; /** pointer to a lattice which describes the kernel of the homomorphism. */ NMatrixInt* reducedKernelLattice; /** compute the ReducedKernelLattice */ void computeReducedKernelLattice(); /** compute the ReducedMatrix */ void computeReducedMatrix(); /** compute the Kernel */ void computeKernel(); /** compute the Cokernel */ void computeCokernel(); /** compute the Image */ void computeImage(); public: /** * Constructs a homomorphism from two marked abelian groups and * a matrix that indicates where the generators are sent. * The roles of the two groups and the matrix are described in * detail in the NHomMarkedAbelianGroup class overview. * * The matrix must be given in the chain-complex coordinates. * Specifically, if the domain was defined via the chain complex * Z^a --N1--> Z^b --M1--> Z^c and the range was * defined via Z^d --N2--> Z^e --M2--> Z^f, then \a mat is * an e-by-b matrix that describes a homomorphism from Z^b to Z^e. * * In order for this to make sense as a homomorphism of the groups * represented by the domain and range respectively, one requires * img(mat*N1) to be a subset of img(N2). Similarly, ker(M1) must * be sent into ker(M2). These facts are not checked, but are * assumed as preconditions of this constructor. * * \pre The matrix \a mat has the required dimensions e-by-b, * gives img(mat*N1) as a subset of img(N2), and sends ker(M1) * into ker(M2), as explained in the detailed notes above. * * @param dom the domain group. * @param ran the range group. * @param mat the matrix that describes the homomorphism from * \a dom to \a ran. */ NHomMarkedAbelianGroup(const NMarkedAbelianGroup& dom, const NMarkedAbelianGroup& ran, const NMatrixInt &mat); /** * Copy constructor. * * @param h the homomorphism to clone. */ NHomMarkedAbelianGroup(const NHomMarkedAbelianGroup& h); /** * Destructor. */ ~NHomMarkedAbelianGroup(); /** * Determines whether this and the given homomorphism together * form a chain map. * * Given two NHomMarkedAbelianGroups, you have two diagrams: *
         * Z^a --N1--> Z^b --M1--> Z^c   Z^g --N3--> Z^h --M3--> Z^i
         *                   ^                             ^
         *                   |this.matrix                  |other.matrix
         * Z^d --N2--> Z^e --M2--> Z^f   Z^j --N4--> Z^k --M4--> Z^l
         * 
* If c=g and f=j and M1=N3 and M2=N4, you can ask if these maps * commute, i.e., whether you have a map of chain complexes. * * @param other the other homomorphism to analyse in conjunction * with this. * @return true if and only if c=g, M1=N3, f=j, M2=N4, * and the diagram commutes. */ bool isChainMap(const NHomMarkedAbelianGroup &other) const; /** * Is this at least a cycle map? If not, pretty much any further * computations you try with this class will be give you nothing * more than carefully-crafted garbage. Technically, this routine * only checks that cycles are sent to cycles, since it only has access * to three of the four maps you need to verify you have a cycle map. * * @return \c true if and only if this is a chain map. */ bool isCycleMap() const; /** * Is this an epic homomorphism? * * @return true if this homomorphism is epic. */ bool isEpic() const; /** * Is this a monic homomorphism? * * @return true if this homomorphism is monic. */ bool isMonic() const; /** * A deprecated alternative to isIsomorphism(). * * \deprecated This routine will be removed in a future version * of Regina; please use the identical routine isIsomorphism() instead. * * @return true if this homomorphism is an isomorphism. */ bool isIso() const; /** * Is this an isomorphism? * * @return true if this homomorphism is an isomorphism. */ bool isIsomorphism() const; /** * Is this the zero map? * * @return true if this homomorphism is the zero map. */ bool isZero() const; /** * Is this the identity automorphism? * * @return true if and only if the domain and range are defined via * the same chain complexes and the induced map on homology is the * identity. */ bool isIdentity() const; /** * Returns the kernel of this homomorphism. * * @return the kernel of the homomorphism, as a marked abelian group. */ const NMarkedAbelianGroup& getKernel() const; /** * Returns the cokernel of this homomorphism. * * @return the cokernel of the homomorphism, as a marked abelian group. */ const NMarkedAbelianGroup& getCokernel() const; /** * Returns the image of this homomorphism. * * @return the image of the homomorphism, as a marked abelian group. */ const NMarkedAbelianGroup& getImage() const; /** * Short text representation. This will state some basic * properties of the homomorphism, such as: * * - whether the map is the identity; * - whether the map is an isomorphism; * - whether the map is monic or epic; * - if it is not monic, describes the kernel; * - if it is not epic, describes the co-kernel; * - if it is neither monic nor epic, describes the image. * * @param out the stream to write to. */ void writeTextShort(std::ostream& out) const; /** * A more detailed text representation of the homomorphism. * * @param out the stream to write to. */ void writeTextLong(std::ostream& out) const; /** * Returns the domain of this homomorphism. * * @return the domain that was used to define the homomorphism. */ const NMarkedAbelianGroup& getDomain() const; /** * Returns the range of this homomorphism. * * @return the range that was used to define the homomorphism. */ const NMarkedAbelianGroup& getRange() const; /** * Returns the defining matrix for the homomorphism. * * @return the matrix that was used to define the homomorphism. */ const NMatrixInt& getDefiningMatrix() const; /** * Returns the internal reduced matrix representing the homomorphism. * This is where the rows/columns of the matrix represent * first the free generators, then the torsion summands in the order * of the invariant factors: * * Z^d + Z_{d0} + ... + Z_{dk} * where: * * - \a d is the number of free generators, as returned by getRank(); * - \a d1, ..., \a dk are the invariant factors that describe the * torsion elements of the group, where * 1 < \a d1 | \a d2 | ... | \a dk. * * @return a copy of the internal representation of the homomorphism. */ const NMatrixInt& getReducedMatrix() const; /** * Evaluate the image of a vector under this homomorphism, using * the original chain complexes' coordinates. This involves * multiplication by the defining matrix. * * \ifacespython Not available yet. This routine will be made * accessible to Python in a future release. * * @param input an input vector in the domain chain complex's * coordinates, of length getDomain().getM().columns(). * @return the image of this vector in the range chain complex's * coordinates, of length getRange().getM().columns(). */ std::vector evalCC( const std::vector &input) const; /** * Evaluate the image of a vector under this homomorphism, using * the Smith normal form coordinates. This is just multiplication by * the reduced matrix, returning the empty vector if the input vector * has the wrong dimensions. * * \warning Smith normal form coordinates are sensitive to the * implementation of the Smith Normal Form, i.e., they are not * canonical. * * \ifacespython Not available yet. This routine will be made * accessible to Python in a future release. * * @param input an input vector in the domain SNF coordinates, * of length getDomain().minNumberOfGenerators(). * @return the image of this vector in the range chain complex's * coordinates, of length getRange().minNumberOfGenerators(). */ std::vector evalSNF( const std::vector &input) const; /** * Returns the inverse to an NHomMarkedAbelianGroup. If this * homomorphism is not invertible, this routine returns the zero * homomorphism. * * If you are computing with mod-p coefficients, this routine will * further require that this invertible map preserves the UCT * splitting of the group, i.e., it gives an isomorphism of the * tensor product parts and the TOR parts. At present this suffices * since we're only using this to construct maps between * homology groups in different coordinate systems. * * @return the inverse homomorphism, or the zero homomorphism if * this is not invertible. */ std::auto_ptr inverseHom() const; /** * Returns the composition of two homomorphisms. * * \pre the homomorphisms must be composable, meaning that the * range of X must have the same presentation matrices as the * domain of this homomorphism. * * @param X the homomorphism to compose this with. * @return a newly created composite homomorphism. */ std::auto_ptr operator * ( const NHomMarkedAbelianGroup &X) const; /** * Returns an NHomMarkedAbelianGroup representing the induced map * on the torsion subgroups. */ std::auto_ptr torsionSubgroup() const; /** * Writes a human-readable version of the reduced matrix to the * given output stream. This is a description of the homomorphism * in some specific coordinates at present only meant to be * internal to NHomMarkedAbelianGroup. At present, these coordinates * have the torsion factors of the group appearing first, followed by * the free factors. * * \ifacespython The \a out argument is missing; instead this is * assumed to be standard output. * * @param out the output stream. */ void writeReducedMatrix(std::ostream& out) const; private: /** * For those situations where you want to define an * NHomMarkedAbelianGroup from its reduced matrix, not from a chain * map. This is in the situation where the SNF coordinates have * particular meaning to the user. At present I only use this * for NHomMarkedAbelianGroup::inverseHom(). Moreover, this routine * assumes tebeRedMat actually can be the reduced matrix of some * chain map -- this is not a restriction in * the coeff==0 case, but it is if coeff > 0. * * \todo Erase completely once made obsolete by right/left inverse. */ NHomMarkedAbelianGroup(const NMatrixInt &tobeRedMat, const NMarkedAbelianGroup &dom, const NMarkedAbelianGroup &ran); }; /*@}*/ // Inline functions for NMarkedAbelianGroup // copy constructor inline NMarkedAbelianGroup::NMarkedAbelianGroup(const NMarkedAbelianGroup& g) : ShareableObject(), OM(g.OM), ON(g.ON), OMR(g.OMR), OMC(g.OMC), OMRi(g.OMRi), OMCi(g.OMCi), rankOM(g.rankOM), ornR(clonePtr(g.ornR)), ornC(clonePtr(g.ornC)), ornRi(clonePtr(g.ornRi)), ornCi(clonePtr(g.ornCi)), otR(clonePtr(g.otR)), otC(clonePtr(g.otC)), otRi(clonePtr(g.otRi)), otCi(clonePtr(g.otCi)), InvFacList(g.InvFacList), snfrank(g.snfrank), snffreeindex(g.snffreeindex), ifNum(g.ifNum), ifLoc(g.ifLoc), coeff(g.coeff), TORLoc(g.TORLoc), TORVec(g.TORVec), tensorIfLoc(g.tensorIfLoc), tensorIfNum(g.tensorIfNum), tensorInvFacList(g.tensorInvFacList) { } // destructor inline NMarkedAbelianGroup::~NMarkedAbelianGroup() { } inline unsigned long NMarkedAbelianGroup::getTorsionRank(unsigned long degree) const { return getTorsionRank(NLargeInteger(degree)); } inline unsigned long NMarkedAbelianGroup::getNumberOfInvariantFactors() const { return ifNum; } inline const NLargeInteger& NMarkedAbelianGroup::getInvariantFactor( unsigned long index) const { return InvFacList[index]; } inline unsigned long NMarkedAbelianGroup::getRank() const { return snfrank; } inline unsigned long NMarkedAbelianGroup::minNumberOfGenerators() const { return snfrank + ifNum; } inline unsigned long NMarkedAbelianGroup::getRankCC() const { return OM.columns(); } inline std::vector NMarkedAbelianGroup::getSNFIsoRep( const std::vector& v) const { return snfRep(v); } inline unsigned long NMarkedAbelianGroup::minNumberCycleGens() const { return OM.columns() - TORLoc; } inline bool NMarkedAbelianGroup::isTrivial() const { return ( (snfrank==0) && (InvFacList.size()==0) ); } inline bool NMarkedAbelianGroup::equalTo(const NMarkedAbelianGroup& other) const { return ( (OM == other.OM) && (ON == other.ON) && (coeff == other.coeff) ); } inline bool NMarkedAbelianGroup::operator == ( const NMarkedAbelianGroup &other) const { return isIsomorphicTo(other); } inline bool NMarkedAbelianGroup::isIsomorphicTo( const NMarkedAbelianGroup &other) const { return ((InvFacList == other.InvFacList) && (snfrank == other.snfrank)); } inline const NMatrixInt& NMarkedAbelianGroup::getMRB() const { return OMR; } inline const NMatrixInt& NMarkedAbelianGroup::getMRBi() const { return OMRi; } inline const NMatrixInt& NMarkedAbelianGroup::getMCB() const { return OMC; } inline const NMatrixInt& NMarkedAbelianGroup::getMCBi() const { return OMCi; } inline const NMatrixInt& NMarkedAbelianGroup::getNRB() const { return *ornR; } inline const NMatrixInt& NMarkedAbelianGroup::getNRBi() const { return *ornRi; } inline const NMatrixInt& NMarkedAbelianGroup::getNCB() const { return *ornC; } inline const NMatrixInt& NMarkedAbelianGroup::getNCBi() const { return *ornCi; } inline unsigned long NMarkedAbelianGroup::getRankM() const { return rankOM; } inline unsigned long NMarkedAbelianGroup::getFreeLoc() const { return snffreeindex; } inline unsigned long NMarkedAbelianGroup::getTorsionLoc() const { return ifLoc; } inline const NMatrixInt& NMarkedAbelianGroup::getM() const { return OM; } inline const NMatrixInt& NMarkedAbelianGroup::getN() const { return ON; } inline const NLargeInteger& NMarkedAbelianGroup::coefficients() const { return coeff; } // Inline functions for NHomMarkedAbelianGroup inline NHomMarkedAbelianGroup::NHomMarkedAbelianGroup( const NMarkedAbelianGroup& dom, const NMarkedAbelianGroup& ran, const NMatrixInt &mat) : domain(dom), range(ran), matrix(mat), reducedMatrix(0), kernel(0), coKernel(0), image(0), reducedKernelLattice(0) { } inline NHomMarkedAbelianGroup::~NHomMarkedAbelianGroup() { if (reducedMatrix) delete reducedMatrix; if (kernel) delete kernel; if (coKernel) delete coKernel; if (image) delete image; if (reducedKernelLattice) delete reducedKernelLattice; } inline const NMarkedAbelianGroup& NHomMarkedAbelianGroup::getDomain() const { return domain; } inline const NMarkedAbelianGroup& NHomMarkedAbelianGroup::getRange() const { return range; } inline const NMatrixInt& NHomMarkedAbelianGroup::getDefiningMatrix() const { return matrix; } inline const NMatrixInt& NHomMarkedAbelianGroup::getReducedMatrix() const { // Cast away const to compute the reduced matrix -- the only reason we're // changing data members now is because we delayed calculations // until they were really required. const_cast(this)->computeReducedMatrix(); return *reducedMatrix; } inline bool NHomMarkedAbelianGroup::isEpic() const { return getCokernel().isTrivial(); } inline bool NHomMarkedAbelianGroup::isMonic() const { return getKernel().isTrivial(); } inline bool NHomMarkedAbelianGroup::isIso() const { return isIsomorphism(); } inline bool NHomMarkedAbelianGroup::isIsomorphism() const { return (getCokernel().isTrivial() && getKernel().isTrivial()); } inline bool NHomMarkedAbelianGroup::isZero() const { return getImage().isTrivial(); } inline const NMarkedAbelianGroup& NHomMarkedAbelianGroup::getKernel() const { // Cast away const to compute the kernel -- the only reason we're // changing data members now is because we delayed calculations // until they were really required. const_cast(this)->computeKernel(); return *kernel; } inline const NMarkedAbelianGroup& NHomMarkedAbelianGroup::getImage() const { // Cast away const to compute the kernel -- the only reason we're // changing data members now is because we delayed calculations // until they were really required. const_cast(this)->computeImage(); return *image; } inline const NMarkedAbelianGroup& NHomMarkedAbelianGroup::getCokernel() const { // Cast away const to compute the kernel -- the only reason we're // changing data members now is because we delayed calculations // until they were really required. const_cast(this)->computeCokernel(); return *coKernel; } } // namespace regina #endif regina-4.96/engine/algebra/nxmlalgebrareader.cpp000644 000765 000024 00000014112 12377776532 021657 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "algebra/nxmlalgebrareader.h" #include "utilities/stringutils.h" namespace regina { /** * A unique namespace containing various task-specific packet readers. */ namespace { /** * Reads a single relation in a group presentation. */ class NExpressionReader : public NXMLElementReader { private: NGroupExpression* exp; long nGens; public: NExpressionReader(long newNGens) : exp(new NGroupExpression()), nGens(newNGens) { } NGroupExpression* getExpression() { return exp; } virtual void initialChars(const std::string& chars) { std::list tokens; basicTokenise(back_inserter(tokens), chars); std::string genStr, powStr; long gen, pow; std::string::size_type split; for (std::list::const_iterator it = tokens.begin(); it != tokens.end(); it++) { split = (*it).find('^'); if (split == (*it).length()) { delete exp; exp = 0; break; } genStr = (*it).substr(0, split); powStr = (*it).substr(split + 1, (*it).length() - split - 1); if ((! valueOf(genStr, gen)) || (! valueOf(powStr, pow))) { delete exp; exp = 0; break; } if (gen < 0 || gen >= nGens) { delete exp; exp = 0; break; } exp->addTermLast(gen, pow); } } }; } void NXMLAbelianGroupReader::startElement(const std::string&, const regina::xml::XMLPropertyDict& tagProps, NXMLElementReader*) { long rank; if (valueOf(tagProps.lookup("rank"), rank)) if (rank >= 0) { group = new NAbelianGroup(); if (rank) group->addRank(rank); } } void NXMLAbelianGroupReader::initialChars(const std::string& chars) { if (group) { std::list tokens; if (basicTokenise(back_inserter(tokens), chars) > 0) { std::multiset torsion; NLargeInteger val; for (std::list::const_iterator it = tokens.begin(); it != tokens.end(); it++) if (valueOf(*it, val)) torsion.insert(val); if (! torsion.empty()) group->addTorsionElements(torsion); } } } void NXMLGroupPresentationReader::startElement(const std::string&, const regina::xml::XMLPropertyDict& tagProps, NXMLElementReader*) { long nGen; if (valueOf(tagProps.lookup("generators"), nGen)) if (nGen >= 0) { group = new NGroupPresentation(); if (nGen) group->addGenerator(nGen); } } NXMLElementReader* NXMLGroupPresentationReader::startSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict& /* subTagProps */) { if (group) if (subTagName == "reln") return new NExpressionReader(group->getNumberOfGenerators()); return new NXMLElementReader(); } void NXMLGroupPresentationReader::endSubElement(const std::string& subTagName, NXMLElementReader* subReader) { if (group) if (subTagName == "reln") { NGroupExpression* exp = dynamic_cast(subReader)->getExpression(); if (exp) group->addRelation(exp); } } } // namespace regina regina-4.96/engine/algebra/nxmlalgebrareader.h000644 000765 000024 00000012436 12377774633 021333 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file algebra/nxmlalgebrareader.h * \brief Deals with parsing XML data for various algebraic structures. */ #ifndef __NXMLALGEBRAREADER_H #ifndef __DOXYGEN #define __NXMLALGEBRAREADER_H #endif #include "regina-core.h" #include "algebra/nabeliangroup.h" #include "algebra/ngrouppresentation.h" #include "utilities/nxmlelementreader.h" namespace regina { /** * \weakgroup algebra * @{ */ /** * An XML element reader that reads a single abelian group. * An abelian group is generally contained within an * \ ... \ pair. * * \ifacespython Not present. */ class REGINA_API NXMLAbelianGroupReader : public NXMLElementReader { private: NAbelianGroup* group; /**< The abelian group currently being read. */ public: /** * Creates a new abelian group reader. */ NXMLAbelianGroupReader(); /** * Returns the newly allocated abelian group that has been read by * this element reader. * * @return the group that has been read, or 0 if an error occurred. */ virtual NAbelianGroup* getGroup(); virtual void startElement(const std::string& tagName, const regina::xml::XMLPropertyDict& tagProps, NXMLElementReader* parentReader); virtual void initialChars(const std::string& chars); }; /** * An XML element reader that reads a single group presentation. * A group presentation is generally contained within a * \ ... \ pair. * * \ifacespython Not present. */ class REGINA_API NXMLGroupPresentationReader : public NXMLElementReader { private: NGroupPresentation* group; /**< The group presentation currently being read. */ public: /** * Creates a new group presentation reader. */ NXMLGroupPresentationReader(); /** * Returns the newly allocated group presentation that has been read by * this element reader. * * @return the group that has been read, or 0 if an error occurred. */ virtual NGroupPresentation* getGroup(); virtual void startElement(const std::string& tagName, const regina::xml::XMLPropertyDict& tagProps, NXMLElementReader* parentReader); virtual NXMLElementReader* startSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict& subTagProps); virtual void endSubElement(const std::string& subTagName, NXMLElementReader* subReader); }; /*@}*/ // Inline functions for NXMLAbelianGroupReader inline NXMLAbelianGroupReader::NXMLAbelianGroupReader() : group(0) { } inline NAbelianGroup* NXMLAbelianGroupReader::getGroup() { return group; } // Inline functions for NXMLGroupPresentationReader inline NXMLGroupPresentationReader::NXMLGroupPresentationReader() : group(0) { } inline NGroupPresentation* NXMLGroupPresentationReader::getGroup() { return group; } } // namespace regina #endif regina-4.96/engine/angle/CMakeLists.txt000644 000765 000024 00000000743 12311266525 017712 0ustar00babstaff000000 000000 # angle # Files to compile SET ( FILES nanglestructure nanglestructurelist nxmlanglestructreader ) # Prepend folder name FOREACH ( SOURCE_FILE ${FILES} ) SET ( SOURCES ${SOURCES} angle/${SOURCE_FILE}) ENDFOREACH(SOURCE_FILE) SET(SOURCES ${SOURCES} PARENT_SCOPE) if (${REGINA_INSTALL_DEV}) INSTALL(FILES nanglestructure.h nanglestructurelist.h nxmlanglestructreader.h DESTINATION ${INCLUDEDIR}/angle COMPONENT Development) endif (${REGINA_INSTALL_DEV}) regina-4.96/engine/angle/nanglestructure.cpp000644 000765 000024 00000026717 12377776533 021135 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "angle/nanglestructure.h" #include "maths/nmatrixint.h" #include "surfaces/nnormalsurface.h" // For vertexSplit. #include "triangulation/ntriangulation.h" #include "utilities/xmlutils.h" namespace regina { const unsigned long NAngleStructure::flagStrict = 1; const unsigned long NAngleStructure::flagTaut = 2; const unsigned long NAngleStructure::flagCalculatedType = 4; const unsigned long NAngleStructure::flagVeering = 8; NMatrixInt* NAngleStructureVector::makeAngleEquations( const NTriangulation* tri) { unsigned long n = tri->getNumberOfTetrahedra(); unsigned long cols = 3 * n + 1; // We have one equation per non-boundary edge plus one per tetrahedron. long rows = long(tri->getNumberOfEdges()) + long(tri->getNumberOfTetrahedra()); for (NTriangulation::BoundaryComponentIterator bit = tri->getBoundaryComponents().begin(); bit != tri->getBoundaryComponents().end(); bit++) rows -= (*bit)->getNumberOfEdges(); NMatrixInt* eqns = new NMatrixInt(rows, cols); unsigned long row = 0; std::deque::const_iterator embit; NPerm4 perm; unsigned long index; for (NTriangulation::EdgeIterator eit = tri->getEdges().begin(); eit != tri->getEdges().end(); eit++) { if ((*eit)->isBoundary()) continue; for (embit = (*eit)->getEmbeddings().begin(); embit != (*eit)->getEmbeddings().end(); embit++) { index = tri->tetrahedronIndex((*embit).getTetrahedron()); perm = (*embit).getVertices(); eqns->entry(row, 3 * index + vertexSplit[perm[0]][perm[1]]) += 1; } eqns->entry(row, cols - 1) = -2; ++row; } for (index = 0; index < n; index++) { eqns->entry(row, 3 * index) = 1; eqns->entry(row, 3 * index + 1) = 1; eqns->entry(row, 3 * index + 2) = 1; eqns->entry(row, cols - 1) = -1; ++row; } return eqns; } NAngleStructure* NAngleStructure::clone() const { NAngleStructure* ans = new NAngleStructure(triangulation, new NAngleStructureVector(*vector)); ans->flags = flags; return ans; } NRational NAngleStructure::getAngle(unsigned long tetIndex, int edgePair) const { const NLargeInteger& num = (*vector)[3 * tetIndex + edgePair]; const NLargeInteger& den = (*vector)[3 * triangulation->getNumberOfTetrahedra()]; NLargeInteger gcd = den.gcd(num); if (gcd < 0) gcd.negate(); return NRational(num.divExact(gcd), den.divExact(gcd)); } void NAngleStructure::writeTextShort(std::ostream& out) const { unsigned long nTets = triangulation->getNumberOfTetrahedra(); unsigned j; for (unsigned long tet = 0; tet < nTets; tet++) { if (tet > 0) out << " ; "; for (j=0; j<3; j++) { if (j > 0) out << ' '; out << getAngle(tet, j); } } } void NAngleStructure::writeXMLData(std::ostream& out) const { // Write the vector length. size_t vecLen = vector->size(); out << " "; // Write the non-zero elements. NLargeInteger entry; for (size_t i = 0; i < vecLen; i++) { entry = (*vector)[i]; if (entry != 0) out << i << ' ' << entry << ' '; } // Write properties. /** Flags in data files are deprecated as of Regina 4.93. out << regina::xml::xmlValueTag("flags", flags); */ // Write the closing tag. out << "\n"; } void NAngleStructure::calculateType() const { unsigned long size = vector->size(); if (size == 1) { // We have no tetrahedra, which means this angle structure has it all: // strict, taut and veering. flags |= flagStrict; flags |= flagTaut; flags |= flagVeering; flags |= flagCalculatedType; return; } bool taut = true; bool strict = true; // Run through the tetrahedra one by one. const NLargeInteger& scale = (*vector)[size - 1]; unsigned long pair; for (unsigned long base = 0; base < size - 1; base += 3) { for (pair = 0; pair < 3; pair++) { if ((*vector)[base + pair] == scale) { // We have a pi; thus all three angles in this // tetrahedron are pi or zero. strict = false; break; } else if ((*vector)[base + pair] == NLargeInteger::zero) strict = false; else taut = false; } if ((! strict) && (! taut)) break; } // Update the flags as appropriate. if (strict) flags |= flagStrict; else flags &= (~flagStrict); if (taut) { // This structure is taut. flags |= flagTaut; // Is it veering also? bool veering = true; if (triangulation->isOrientable()) { long nEdges = triangulation->getNumberOfEdges(); int* edgeColour = new int[nEdges]; std::fill(edgeColour, edgeColour + nEdges, (int)0); const NTetrahedron* tet; int orient; long e; for (unsigned i = 0; i < triangulation->getNumberOfTetrahedra(); ++i) { tet = triangulation->getTetrahedron(i); orient = tet->orientation(); if ((*vector)[3 * i] > 0) { // Edges 0,5 are marked as pi. // For a positively oriented tetrahedron: // Edges 1,4 vs 2,3 are of colour +1 vs -1. e = triangulation->edgeIndex(tet->getEdge(1)); if (edgeColour[e] == -orient) veering = false; else edgeColour[e] = orient; e = triangulation->edgeIndex(tet->getEdge(4)); if (edgeColour[e] == -orient) veering = false; else edgeColour[e] = orient; e = triangulation->edgeIndex(tet->getEdge(2)); if (edgeColour[e] == orient) veering = false; else edgeColour[e] = -orient; e = triangulation->edgeIndex(tet->getEdge(3)); if (edgeColour[e] == orient) veering = false; else edgeColour[e] = -orient; } else if ((*vector)[3 * i + 1] > 0) { // Edges 1,4 are marked as pi. // For a positively oriented tetrahedron: // Edges 2,3 vs 0,5 are of colour +1 vs -1. e = triangulation->edgeIndex(tet->getEdge(2)); if (edgeColour[e] == -orient) veering = false; else edgeColour[e] = orient; e = triangulation->edgeIndex(tet->getEdge(3)); if (edgeColour[e] == -orient) veering = false; else edgeColour[e] = orient; e = triangulation->edgeIndex(tet->getEdge(0)); if (edgeColour[e] == orient) veering = false; else edgeColour[e] = -orient; e = triangulation->edgeIndex(tet->getEdge(5)); if (edgeColour[e] == orient) veering = false; else edgeColour[e] = -orient; } else if ((*vector)[3 * i + 2] > 0) { // Edges 2,3 are marked as pi. // For a positively oriented tetrahedron: // Edges 0,5 vs 1,4 are of colour +1 vs -1. e = triangulation->edgeIndex(tet->getEdge(0)); if (edgeColour[e] == -orient) veering = false; else edgeColour[e] = orient; e = triangulation->edgeIndex(tet->getEdge(5)); if (edgeColour[e] == -orient) veering = false; else edgeColour[e] = orient; e = triangulation->edgeIndex(tet->getEdge(1)); if (edgeColour[e] == orient) veering = false; else edgeColour[e] = -orient; e = triangulation->edgeIndex(tet->getEdge(4)); if (edgeColour[e] == orient) veering = false; else edgeColour[e] = -orient; } if (! veering) break; } delete[] edgeColour; } else { // Only orientable triangulations can be veering. veering = false; } if (veering) flags |= flagVeering; else flags &= (~flagVeering); } else { // Not taut, and therefore not veering either. flags &= (~flagTaut); flags &= (~flagVeering); } flags |= flagCalculatedType; } } // namespace regina regina-4.96/engine/angle/nanglestructure.h000644 000765 000024 00000032356 12377774636 020600 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file angle/nanglestructure.h * \brief Deals with angle structures on triangulations. */ #ifndef __NANGLESTRUCTURE_H #ifndef __DOXYGEN #define __NANGLESTRUCTURE_H #endif #include "regina-core.h" #include "shareableobject.h" #include "maths/nrational.h" #include "maths/nray.h" namespace regina { class NMatrixInt; class NTriangulation; class NXMLAngleStructureReader; /** * \addtogroup angle Angle Structures * Angle structures on triangulations. * @{ */ /** * A vector of integers used to indirectly store the individual angles * in an angle structure. * * This vector will contain one member per angle plus a final scaling * member; to obtain the actual angle in the angle structure one should * divide the corresonding angle member by the scaling member and then * multiply by pi. * * The reason for using this obfuscated representation is so we can * use the NDoubleDescription vertex enumeration routines to * calculate vertex angle structures. * * If there are \a t tetrahedra in the underlying triangulation, there * will be precisely 3t+1 elements in this vector. The first * three elements will be the angle members for the first tetrahedron, * the next three for the second tetrahedron and so on. For each * tetraheron, the three individual elements are the angle members * for vertex splittings 0, 1 and 2 (see NAngleStructure::getAngle()). * The final element of the vector is the scaling member as described * above. * * \ifacespython Not present. */ class REGINA_API NAngleStructureVector : public NRay { public: /** * Creates a new vector all of whose entries are initialised to * zero. * * @param length the number of elements in the new vector. */ NAngleStructureVector(size_t length); /** * Creates a new vector that is a clone of the given vector. * * @param cloneMe the vector to clone. */ NAngleStructureVector(const NVector& cloneMe); /** * Creates a new set of angle structure equations for the given * triangulation. * * Each equation will be represented as a row of the matrix, and * each column will represent a coordinate in the underlying * coordinate system (which is described in the NAngleStructureVector * class notes). * * The returned matrix will be newly allocated and its destruction * will be the responsibility of the caller of this routine. * * @param tri the triangulation upon which these angle structure * equations will be based. * @return a newly allocated set of equations. */ static NMatrixInt* makeAngleEquations(const NTriangulation* tri); }; /** * Represents an angle structure on a triangulation. * Once the underlying triangulation changes, this angle structure * is no longer valid. */ class REGINA_API NAngleStructure : public ShareableObject { private: NAngleStructureVector* vector; /**< Stores (indirectly) the individual angles in this angle * structure. */ const NTriangulation* triangulation; /**< The triangulation on which this angle structure is placed. */ mutable unsigned long flags; /**< Stores a variety of angle structure properties as * described by the flag constants in this class. * Flags can be combined using bitwise OR. */ static const unsigned long flagStrict; /**< Signals that this angle structure is strict. */ static const unsigned long flagTaut; /**< Signals that this angle structure is taut. A taut structure might also be veering, in which case the flag \a flagVeering will be set also. */ static const unsigned long flagVeering; /**< Signals that this angle structure is veering (in which case that the \a flagTaut flag must be set also). */ static const unsigned long flagCalculatedType; /**< Signals that the type (strict/taut/veering) has been calculated. */ public: /** * Creates a new angle structure on the given triangulation with * the given coordinate vector. * * \ifacespython Not present. * * @param triang the triangulation on which this angle structure lies. * @param newVector a vector containing the individual angles in the * angle structure. */ NAngleStructure(const NTriangulation* triang, NAngleStructureVector* newVector); /** * Destroys this angle structure. * The underlying vector of angles will also be deallocated. */ virtual ~NAngleStructure(); /** * Creates a newly allocated clone of this angle structure. * * @return a clone of this angle structure. */ NAngleStructure* clone() const; /** * Returns the requested angle in this angle structure. * The angle returned will be scaled down; the actual angle is * the returned value multiplied by pi. * * @param tetIndex the index in the triangulation of the * tetrahedron in which the requested angle lives; this should * be between 0 and NTriangulation::getNumberOfTetrahedra()-1 * inclusive. * @param edgePair the number of the vertex splitting * representing the pair of edges holding the requested angle; * this should be between 0 and 2 inclusive. See regina::vertexSplit * and regina::vertexSplitDefn for details regarding vertex splittings. * @return the requested angle scaled down by pi. */ NRational getAngle(unsigned long tetIndex, int edgePair) const; /** * Returns the triangulation on which this angle structure lies. * * @return the underlying triangulation. */ const NTriangulation* getTriangulation() const; /** * Determines whether this is a strict angle structure. * A strict angle structure has all angles strictly between (not * including) 0 and pi. * * @return \c true if and only if this is a strict angle structure. */ bool isStrict() const; /** * Determines whether this is a taut angle structure. * A taut angle structure contains only angles 0 and pi. * * Here we use the Kang-Rubinstein definition of a taut * angle structure [1], which is based on the angles alone. * In his original paper [2], Lackenby has an extra condition * whereby 2-faces of the triangulation must have consistent * coorientations, which we do not enforce here. * * [1] E. Kang and J. H. Rubinstein, "Ideal triangulations of * 3-manifolds II; Taut and angle structures", Algebr. Geom. Topol. * 5 (2005), pp. 1505-1533. * * [2] M. Lackenby, "Taut ideal triangulations of 3-manifolds", * Geom. Topol. 4 (2000), pp. 369-395. * * @return \c true if and only if this is a taut structure. */ bool isTaut() const; /** * Determines whether this is a veering structure. * A veering structure is taut angle structure with additional * strong combinatorial constraints, which we do not outline here. * For a definition, see C. D. Hodgson, J. H. Rubinstein, * H. Segerman, and S. Tillmann, "Veering triangulations admit * strict angle structures", Geom. Topol., 15 (2011), pp. 2073-2089. * * Note that the Hodgson et al. definition is slightly more general * than Agol's veering taut triangulations from his original paper: * I. Agol, " Ideal triangulations of pseudo-Anosov mapping tori", * in "Topology and Geometry in Dimension Three", volume 560 of * Contemp. Math., pp. 1-17, Amer. Math. Soc., 2011. * This mirrors the way in which the Kang-Rubinstein definition of * taut angle structure is slightly more general than Lackenby's. * See the Hodgson et al. paper for full details and comparisons * between the two settings. * * If this angle structure is not taut, or if the underlying * triangulation is non-orientable, then this routine will * return \c false. * * @return \c true if and only if this is a veering structure. */ bool isVeering() const; /** * Gives read-only access to the raw vector that sits beneath this * angle structure. * * Generally users should not need this function. However, it is * provided here in case the need should arise (e.g., for reasons * of efficiency). * * \ifacespython Not present. * * @return the underlying raw vector. */ const NAngleStructureVector* rawVector() const; void writeTextShort(std::ostream& out) const; /** * Writes a chunk of XML containing this angle structure and all * of its properties. This routine will be called from within * NAngleStructureList::writeXMLPacketData(). * * \ifacespython Not present. * * @param out the output stream to which the XML should be written. */ void writeXMLData(std::ostream& out) const; protected: /** * Calculates the structure type (strict or taut) and stores it * as a property. */ void calculateType() const; friend class regina::NXMLAngleStructureReader; }; /*@}*/ // Inline functions for NAngleStructureVector inline NAngleStructureVector::NAngleStructureVector(size_t length) : NRay(length) { } inline NAngleStructureVector::NAngleStructureVector( const NVector& cloneMe) : NRay(cloneMe) { } // Inline functions for NAngleStructure inline NAngleStructure::NAngleStructure(const NTriangulation* triang, NAngleStructureVector* newVector) : vector(newVector), triangulation(triang), flags(0) { } inline NAngleStructure::~NAngleStructure() { delete vector; } inline const NTriangulation* NAngleStructure::getTriangulation() const { return triangulation; } inline bool NAngleStructure::isStrict() const { if ((flags & flagCalculatedType) == 0) calculateType(); return ((flags & flagStrict) != 0); } inline bool NAngleStructure::isTaut() const { if ((flags & flagCalculatedType) == 0) calculateType(); return ((flags & flagTaut) != 0); } inline bool NAngleStructure::isVeering() const { if ((flags & flagCalculatedType) == 0) calculateType(); return ((flags & flagVeering) != 0); } inline const NAngleStructureVector* NAngleStructure::rawVector() const { return vector; } } // namespace regina #endif regina-4.96/engine/angle/nanglestructurelist.cpp000644 000765 000024 00000023462 12377776533 022023 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "angle/nanglestructurelist.h" #include "enumerate/ndoubledescription.h" #include "enumerate/ntreetraversal.h" #include "maths/nmatrixint.h" #include "progress/nprogresstracker.h" #include "surfaces/nnormalsurface.h" #include "triangulation/ntriangulation.h" #include "utilities/xmlutils.h" namespace regina { typedef std::vector::const_iterator StructureIteratorConst; void* NAngleStructureList::Enumerator::run(void*) { // Form the matching equations. NMatrixInt* eqns = NAngleStructureVector::makeAngleEquations(triang); if (list->tautOnly_ && triang->getNumberOfTetrahedra() > 0) { // For now just stick to arbitrary precision arithmetic. // TODO: Use native integer types when the angle equation matrix // is sufficiently small / simple. if (tracker) tracker->newStage("Enumerating taut angle structures"); NTautEnumeration search(triang); while (search.next(tracker)) { list->structures.push_back(search.buildStructure()); if (tracker && tracker->isCancelled()) break; } if (! (tracker && tracker->isCancelled())) triang->insertChildLast(list); if (tracker) tracker->setFinished(); } else { // For the empty triangulation, we fall through here regardless // of whether we want taut or all vertex angle structures (but // either way, the answer is the same - just one empty structure). // // For all other triangulations, we fall through here if we are // after all vertex angle structures. if (tracker) tracker->newStage("Enumerating vertex angle structures"); // Find the angle structures. NDoubleDescription::enumerateExtremalRays( StructureInserter(*list, triang), *eqns, 0 /* constraints */, tracker); // All done! if (! (tracker && tracker->isCancelled())) triang->insertChildLast(list); if (tracker) tracker->setFinished(); } delete eqns; return 0; } NAngleStructureList* NAngleStructureList::enumerate(NTriangulation* owner, bool tautOnly, NProgressTracker* tracker) { NAngleStructureList* ans = new NAngleStructureList(tautOnly); Enumerator* e = new Enumerator(ans, owner, tracker); if (tracker) { if (! e->start(0, true)) { delete ans; return 0; } return ans; } else { e->run(0); delete e; return ans; } } NAngleStructureList* NAngleStructureList::enumerateTautDD( NTriangulation* owner) { NAngleStructureList* ans = new NAngleStructureList(true /* taut only */); // Form the matching equations. NMatrixInt* eqns = NAngleStructureVector::makeAngleEquations(owner); // Form the taut constraints. NEnumConstraintList* constraints = new NEnumConstraintList( owner->getNumberOfTetrahedra()); unsigned base = 0; for (unsigned c = 0; c < constraints->size(); ++c) { (*constraints)[c].insert((*constraints)[c].end(), base++); (*constraints)[c].insert((*constraints)[c].end(), base++); (*constraints)[c].insert((*constraints)[c].end(), base++); } // Find the angle structures. NDoubleDescription::enumerateExtremalRays( StructureInserter(*ans, owner), *eqns, constraints, 0 /* tracker */); // All done! owner->insertChildLast(ans); delete eqns; delete constraints; return ans; } NTriangulation* NAngleStructureList::getTriangulation() const { return dynamic_cast(getTreeParent()); } void NAngleStructureList::writeTextShort(std::ostream& o) const { o << structures.size() << " vertex angle structure"; if (structures.size() != 1) o << 's'; o << " (" << (tautOnly_ ? "taut only" : "no restrictions") << ')'; } void NAngleStructureList::writeTextLong(std::ostream& o) const { writeTextShort(o); o << ":\n"; for (StructureIteratorConst it = structures.begin(); it != structures.end(); it++) { (*it)->writeTextShort(o); o << '\n'; } } void NAngleStructureList::writeXMLPacketData(std::ostream& out) const { using regina::xml::xmlValueTag; // Write the enumeration parameters. out << " \n"; // Write the individual structures. for (StructureIteratorConst it = structures.begin(); it != structures.end(); it++) (*it)->writeXMLData(out); // Write the properties. if (doesSpanStrict.known()) out << " " << xmlValueTag("spanstrict", doesSpanStrict.value()) << '\n'; if (doesSpanTaut.known()) out << " " << xmlValueTag("spantaut", doesSpanTaut.value()) << '\n'; } NPacket* NAngleStructureList::internalClonePacket(NPacket* /* parent */) const { NAngleStructureList* ans = new NAngleStructureList(tautOnly_); transform(structures.begin(), structures.end(), back_inserter(ans->structures), FuncNewClonePtr()); if (doesSpanStrict.known()) ans->doesSpanStrict = doesSpanStrict; if (doesSpanTaut.known()) ans->doesSpanTaut = doesSpanTaut; return ans; } void NAngleStructureList::calculateSpanStrict() const { if (structures.empty()) { doesSpanStrict = false; return; } unsigned long nTets = getTriangulation()->getNumberOfTetrahedra(); if (nTets == 0) { doesSpanStrict = true; return; } // We run into trouble if there's a 0 or pi angle that never changes. NRational* fixedAngles = new NRational[nTets * 3]; unsigned long nFixed = 0; // Get the list of bad unchanging angles from the first structure. StructureIteratorConst it = structures.begin(); const NAngleStructure* s = *it; NRational angle; unsigned long tet; int edges; for (tet = 0; tet < nTets; tet++) for (edges = 0; edges < 3; edges++) { angle = s->getAngle(tet, edges); if (angle == NRational::zero || angle == NRational::one) { fixedAngles[3 * tet + edges] = angle; nFixed++; } else fixedAngles[3 * tet + edges] = NRational::undefined; } if (nFixed == 0) { doesSpanStrict = true; delete[] fixedAngles; return; } // Run through the rest of the structures to see if these bad angles // do ever change. for (it++; it != structures.end(); it++) { s = *it; for (tet = 0; tet < nTets; tet++) for (edges = 0; edges < 3; edges++) { if (fixedAngles[3 * tet + edges] == NRational::undefined) continue; if (s->getAngle(tet, edges) != fixedAngles[3 * tet + edges]) { // Here's a bad angle that finally changed. fixedAngles[3 * tet + edges] = NRational::undefined; nFixed--; if (nFixed == 0) { doesSpanStrict = true; delete[] fixedAngles; return; } } } } // Some of the bad angles never changed. doesSpanStrict = false; delete[] fixedAngles; } void NAngleStructureList::calculateSpanTaut() const { doesSpanTaut = (find_if(structures.begin(), structures.end(), std::mem_fun(&NAngleStructure::isTaut)) != structures.end()); } } // namespace regina regina-4.96/engine/angle/nanglestructurelist.h000644 000765 000024 00000051471 12377774640 021466 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file angle/nanglestructurelist.h * \brief Contains a packet representing a collection of angle * structures on a triangulation. */ #ifndef __NANGLESTRUCTURELIST_H #ifndef __DOXYGEN #define __NANGLESTRUCTURELIST_H #endif #include #include #include #include "regina-core.h" #include "angle/nanglestructure.h" #include "packet/npacket.h" #include "utilities/memutils.h" #include "utilities/nproperty.h" #include "utilities/nthread.h" namespace regina { class NAngleStructureList; class NProgressTracker; class NXMLPacketReader; class NXMLAngleStructureListReader; /** * \weakgroup angle * @{ */ /** * Stores information about the angle structure list packet. * See the general PacketInfo template notes for further details. * * \ifacespython Not present. */ template <> struct PacketInfo { typedef NAngleStructureList Class; inline static const char* name() { return "Angle Structure List"; } }; /** * A packet representing a collection of angle structures on a triangulation. * Such a packet must always be a child packet of the triangulation on * which the angle structures lie. If this triangulation changes, the * information contained in this packet will become invalid. * * Angle structure lists should be created using the routine enumerate(), * which is new as of Regina 3.95. */ class REGINA_API NAngleStructureList : public NPacket { REGINA_PACKET(NAngleStructureList, PACKET_ANGLESTRUCTURELIST) private: std::vector structures; /**< Contains the angle structures stored in this packet. */ bool tautOnly_; /**< Stores whether we are only interested in taut structures. This is an option selected by the user before enumeration takes place. */ mutable NProperty doesSpanStrict; /**< Does the convex span of this list include a strict angle structure? This is determined by looking at the output angle structues after enumeration has taken place. */ mutable NProperty doesSpanTaut; /**< Does this list include a taut structure? This is determined by looking at the output angle structues after enumeration has taken place. */ public: /** * Destroys this list and all the angle structures within. */ virtual ~NAngleStructureList(); /** * Returns the triangulation on which these angle structures * lie. * * @return the corresponding triangulation. */ NTriangulation* getTriangulation() const; /** * Returns whether this list was produced by enumerating taut angle * structures only. * * @return \c true if this list was produced by enumerating * taut angle structures only, or \c false if the enumeration * procedure allowed for any angle structures. */ bool isTautOnly() const; /** * Returns the number of angle structures stored in this list. * * @return the number of angle structures. */ unsigned long getNumberOfStructures() const; /** * Returns the angle structure at the requested index in this * list. * * @param index the index of the requested angle structure in * this list; this must be between 0 and * getNumberOfStructures()-1 inclusive. * @return the angle structure at the requested index. */ const NAngleStructure* getStructure(unsigned long index) const; /** * Determines whether any convex combination of the angle * structures in this list is a strict angle structure. * See NAngleStructure::isStrict() for details on strict angle * structures. * * @return \c true if and only if a strict angle structure can * be produced. */ bool spansStrict() const; /** * Determines whether any angle structure in this list is a * taut structure. Because taut structures always appear as * vertices of the angle structure solution space, this routine * is equivalent to testing whether any convex combination of * the angle structures in this list is a taut structure. * * See NAngleStructure::isTaut() for details on taut * structures. * * @return \c true if and only if a taut structure can be produced. */ bool spansTaut() const; /** * Determines whether any convex combination of the angle * structures in this list is a strict angle structure. * * \deprecated This routine will be removed in a future version * of Regina. Users should switch to the identical routine * spansStrict() instead. * * @return \c true if and only if a strict angle structure can * be produced. */ bool allowsStrict() const; /** * Determines whether any angle structure in this list is a * taut structure. * * \deprecated This routine will be removed in a future version * of Regina. Users should switch to the identical routine * spansTaut() instead. * * @return \c true if and only if a taut angle structure can * be produced. */ bool allowsTaut() const; /** * Enumerates all angle structures on the given triangulation. * A list containing all vertices of the angle structure solution * space will be returned. * * The option is offered to find only taut structures (which are * considerably faster to enumerate) instead of enumerating all * vertex angle structures. See the \a tautOnly argument below. * * The angle structure list that is created will be inserted as the * last child of the given triangulation. This triangulation \b must * remain the parent of this angle structure list, and must not * change while this angle structure list remains in existence. * * If a progress tracker is passed, the angle structure * enumeration will take place in a new thread and this routine * will return immediately. If the user cancels the operation * from another thread, then the angle structure list will \e not * be inserted into the packet tree (but the caller of this * routine will still need to delete it). Regarding progress tracking, * this routine will declare and work through a series of stages * whose combined weights sum to 1; typically this means that the * given tracker must not have been used before. * * If no progress tracker is passed, the enumeration will run * in the current thread and this routine will return only when * the enumeration is complete. Note that this enumeration can * be extremely slow for larger triangulations. * * @param owner the triangulation for which the vertex * angle structures will be enumerated. * @param tautOnly \c true if only taut structures are to be * enuemrated, or \c false if we should enumerate all vertices * of the angle structure solution space; this defaults to \c false. * @param tracker a progress tracker through which progress will * be reported, or 0 if no progress reporting is required. * @return the newly created angle structure list. Note that if * a progress tracker is passed then this list may not be completely * filled when this routine returns. If a progress tracker is * passed and a new thread could not be started, this routine * returns 0 (and no angle structure list is created). */ static NAngleStructureList* enumerate(NTriangulation* owner, bool tautOnly = false, NProgressTracker* tracker = 0); /** * A slower, alternative method to enumerate all taut angle structures * on the given triangulation. A list containing all taut angle * structures will be returned. * * The algorithm used by this routine is based on the double * description method. The algorithm used by enumerate() (the * preferred method) is instead based on linear programming, and is * typically \e much faster than this routine for larger triangulations. * * The angle structure list that is created will be inserted as the * last child of the given triangulation. This triangulation \b must * remain the parent of this angle structure list, and must not * change while this angle structure list remains in existence. * * \warning This routine is slow, and users will not want to call it * unless they have some specialised need. * * @param owner the triangulation for which the taut angle structures * will be enumerated. * @return the newly created angle structure list. */ static NAngleStructureList* enumerateTautDD(NTriangulation* owner); virtual void writeTextShort(std::ostream& out) const; virtual void writeTextLong(std::ostream& out) const; static NXMLPacketReader* getXMLReader(NPacket* parent, NXMLTreeResolver& resolver); virtual bool dependsOnParent() const; protected: /** * Creates a new empty angle structure list. * All properties are marked as unknown. * * @param tautOnly \c true if only taut structures are to be * enuemrated (when the time comes for enumeration to be performed), * or \c false if we should enumerate all vertices of the angle * structure solution space. */ NAngleStructureList(bool tautOnly); virtual NPacket* internalClonePacket(NPacket* parent) const; virtual void writeXMLPacketData(std::ostream& out) const; /** * Calculate whether the convex span of this list includes a * strict angle structure. */ void calculateSpanStrict() const; /** * Calculate whether the convex span of this list includes a * taut structure. */ void calculateSpanTaut() const; /** * An output iterator used to insert angle structures into an * NAngleStructureList. * * Objects of type NAngleStructure* and * NAngleStructureVector* can be assigned to this * iterator. In the latter case, a surrounding NAngleStructure * will be automatically created. */ struct StructureInserter : public std::iterator< std::output_iterator_tag, NAngleStructureVector*> { NAngleStructureList* list; /**< The list into which angle structures will be inserted. */ NTriangulation* owner; /**< The triangulation on which the angle structures to * be inserted lie. */ /** * Creates a new uninitialised output iterator. * * \warning This iterator must not be used until its * structure list and triangulation have been initialised. */ StructureInserter(); /** * Creates a new output iterator. The member variables of * this iterator will be initialised according to the * parameters passed to this constructor. * * @param newList the list into which angle structures will * be inserted. * @param newOwner the triangulation on which the structures * to be inserted lie. */ StructureInserter(NAngleStructureList& newList, NTriangulation* newOwner); /** * Creates a new output iterator that is a clone of the * given iterator. * * @param cloneMe the output iterator to clone. */ StructureInserter(const StructureInserter& cloneMe); /** * Sets this iterator to be a clone of the given output iterator. * * @param cloneMe the output iterator to clone. * @return this output iterator. */ StructureInserter& operator =(const StructureInserter& cloneMe); /** * Appends an angle structure to the end of the appropriate * structure list. * * The given angle structure will be deallocated with the * other angle structures in this list when the list is * eventually destroyed. * * @param structure the angle structure to insert. * @return this output iterator. */ StructureInserter& operator =(NAngleStructure* structure); /** * Appends the angle structure corresponding to the given * vector to the end of the appropriate structure list. * * The given vector will be owned by the newly created * angle structure and will be deallocated with the * other angle structures in this list when the list is * eventually destroyed. * * @param vector the vector of the angle structure to insert. * @return this output iterator. */ StructureInserter& operator =(NAngleStructureVector* vector); /** * Returns a reference to this output iterator. * * @return this output iterator. */ StructureInserter& operator *(); /** * Returns a reference to this output iterator. * * @return this output iterator. */ StructureInserter& operator ++(); /** * Returns a reference to this output iterator. * * @return this output iterator. */ StructureInserter& operator ++(int); }; private: /** * A thread class that actually performs the angle structure * enumeration. */ class Enumerator : public NThread { private: NAngleStructureList* list; /**< The angle structure list to be filled. */ NTriangulation* triang; /**< The triangulation upon which this angle structure list will be based. */ NProgressTracker* tracker; /**< The progress tracker through which progress is reported, or 0 if no progress tracker is in use. */ public: /** * Creates a new enumerator thread with the given * parameters. * * @param newList the angle structure list to be filled. * @param useTriang the triangulation upon which this * angle structure list will be based. * @param useTracker the progress tracker to use for * progress reporting, or 0 if progress reporting is not * required. */ Enumerator(NAngleStructureList* newList, NTriangulation* useTriang, NProgressTracker* useTracker); void* run(void*); }; friend class regina::NXMLAngleStructureListReader; }; /*@}*/ // Inline functions for NAngleStructureList inline NAngleStructureList::~NAngleStructureList() { for_each(structures.begin(), structures.end(), FuncDelete()); } inline bool NAngleStructureList::isTautOnly() const { return tautOnly_; } inline unsigned long NAngleStructureList::getNumberOfStructures() const { return structures.size(); } inline const NAngleStructure* NAngleStructureList::getStructure( unsigned long index) const { return structures[index]; } inline bool NAngleStructureList::spansStrict() const { if (! doesSpanStrict.known()) calculateSpanStrict(); return doesSpanStrict.value(); } inline bool NAngleStructureList::spansTaut() const { if (! doesSpanTaut.known()) calculateSpanTaut(); return doesSpanTaut.value(); } inline bool NAngleStructureList::allowsStrict() const { return spansStrict(); } inline bool NAngleStructureList::allowsTaut() const { return spansTaut(); } inline bool NAngleStructureList::dependsOnParent() const { return true; } inline NAngleStructureList::NAngleStructureList(bool tautOnly) : tautOnly_(tautOnly) { } inline NAngleStructureList::StructureInserter::StructureInserter() : list(0), owner(0) { } inline NAngleStructureList::StructureInserter::StructureInserter( NAngleStructureList& newList, NTriangulation* newOwner) : list(&newList), owner(newOwner) { } inline NAngleStructureList::StructureInserter::StructureInserter( const StructureInserter& cloneMe) : list(cloneMe.list), owner(cloneMe.owner) { } inline NAngleStructureList::StructureInserter& NAngleStructureList::StructureInserter::operator =( const StructureInserter& cloneMe) { list = cloneMe.list; owner = cloneMe.owner; return *this; } inline NAngleStructureList::StructureInserter& NAngleStructureList::StructureInserter::operator =( NAngleStructure* structure) { list->structures.push_back(structure); return *this; } inline NAngleStructureList::StructureInserter& NAngleStructureList::StructureInserter::operator =( NAngleStructureVector* vector) { list->structures.push_back(new NAngleStructure(owner, vector)); return *this; } inline NAngleStructureList::StructureInserter& NAngleStructureList::StructureInserter::operator *() { return *this; } inline NAngleStructureList::StructureInserter& NAngleStructureList::StructureInserter::operator ++() { return *this; } inline NAngleStructureList::StructureInserter& NAngleStructureList::StructureInserter::operator ++(int) { return *this; } inline NAngleStructureList::Enumerator::Enumerator(NAngleStructureList* newList, NTriangulation* useTriang, NProgressTracker* useTracker) : list(newList), triang(useTriang), tracker(useTracker) { } } // namespace regina #endif regina-4.96/engine/angle/nxmlanglestructreader.cpp000644 000765 000024 00000012614 12377776534 022315 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "angle/nxmlanglestructreader.h" #include "triangulation/ntriangulation.h" #include "utilities/stringutils.h" namespace regina { void NXMLAngleStructureReader::startElement(const std::string&, const regina::xml::XMLPropertyDict& props, NXMLElementReader*) { if (! valueOf(props.lookup("len"), vecLen)) vecLen = -1; } void NXMLAngleStructureReader::initialChars(const std::string& chars) { if (vecLen < 0 || tri == 0) return; std::vector tokens; if (basicTokenise(back_inserter(tokens), chars) % 2 != 0) return; // Create a new vector and read all non-zero entries. NAngleStructureVector* vec = new NAngleStructureVector(vecLen); long pos; NLargeInteger value; for (unsigned long i = 0; i < tokens.size(); i += 2) { if (valueOf(tokens[i], pos)) if (valueOf(tokens[i + 1], value)) if (pos >= 0 && pos < vecLen) { // All looks valid. vec->setElement(pos, value); continue; } // Found something invalid. delete vec; return; } angles = new NAngleStructure(tri, vec); } NXMLElementReader* NXMLAngleStructureReader::startSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict& props) { if (! angles) return new NXMLElementReader(); /** Flags in data files are deprecated as of Regina 4.93. if (subTagName == "flags") { if (! valueOf(props.lookup("value"), angles->flags)) angles->flags = 0; } */ return new NXMLElementReader(); } NXMLElementReader* NXMLAngleStructureListReader::startContentSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict& props) { bool b; if (subTagName == "angleparams") { if (valueOf(props.lookup("tautonly"), b)) list->tautOnly_ = b; } else if (subTagName == "struct") { return new NXMLAngleStructureReader(tri); } else if (subTagName == "spanstrict") { if (valueOf(props.lookup("value"), b)) list->doesSpanStrict = b; } else if (subTagName == "spantaut") { if (valueOf(props.lookup("value"), b)) list->doesSpanTaut = b; } else if (subTagName == "allowstrict") { if (valueOf(props.lookup("value"), b)) list->doesSpanStrict = b; } else if (subTagName == "allowtaut") { if (valueOf(props.lookup("value"), b)) list->doesSpanTaut = b; } return new NXMLElementReader(); } void NXMLAngleStructureListReader::endContentSubElement( const std::string& subTagName, NXMLElementReader* subReader) { if (subTagName == "struct") if (NAngleStructure* s = dynamic_cast(subReader)-> getStructure()) list->structures.push_back(s); } NXMLPacketReader* NAngleStructureList::getXMLReader(NPacket* parent, NXMLTreeResolver& resolver) { return new NXMLAngleStructureListReader( dynamic_cast(parent), resolver); } } // namespace regina regina-4.96/engine/angle/nxmlanglestructreader.h000644 000765 000024 00000013501 12377774642 021754 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file angle/nxmlanglestructreader.h * \brief Deals with parsing XML data for angle structure lists. */ #ifndef __NXMLANGLESTRUCTREADER_H #ifndef __DOXYGEN #define __NXMLANGLESTRUCTREADER_H #endif #include "regina-core.h" #include "packet/nxmlpacketreader.h" #include "angle/nanglestructurelist.h" namespace regina { /** * \weakgroup angle * @{ */ /** * An XML element reader that reads a single angle structure. * * \ifacespython Not present. */ class REGINA_API NXMLAngleStructureReader : public NXMLElementReader { private: NAngleStructure* angles; /**< The angle structure currently being read. */ NTriangulation* tri; /**< The triangulation on which this angle structure is placed. */ long vecLen; /**< The length of corresponding angle structure vector. */ public: /** * Creates a new angle structure reader. * * @param newTri the triangulation on which this angle structure lies. */ NXMLAngleStructureReader(NTriangulation* newTri); /** * Returns the angle structure that has been read. * * @return the newly allocated angle structure, or 0 if an error * occurred. */ NAngleStructure* getStructure(); virtual void startElement(const std::string& tagName, const regina::xml::XMLPropertyDict& tagProps, NXMLElementReader* parentReader); virtual void initialChars(const std::string& chars); virtual NXMLElementReader* startSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict& subTagProps); }; /** * An XML packet reader that reads a single angle structure list. * * \pre The parent XML element reader is in fact an * NXMLTriangulationReader. * * \ifacespython Not present. */ class REGINA_API NXMLAngleStructureListReader : public NXMLPacketReader { private: NAngleStructureList* list; /**< The angle structure list currently being read. */ NTriangulation* tri; /**< The triangulation on which these angle structures are placed. */ public: /** * Creates a new angle structure list reader. * * @param newTri the triangulation on which these angle * structures are placed. * @param resolver the master resolver that will be used to fix * dangling packet references after the entire XML file has been read. */ NXMLAngleStructureListReader(NTriangulation* newTri, NXMLTreeResolver& resolver); virtual NPacket* getPacket(); virtual NXMLElementReader* startContentSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict& subTagProps); virtual void endContentSubElement(const std::string& subTagName, NXMLElementReader* subReader); }; /*@}*/ // Inline functions for NXMLAngleStructureReader inline NXMLAngleStructureReader::NXMLAngleStructureReader( NTriangulation* newTri) : angles(0), tri(newTri), vecLen(-1) { } inline NAngleStructure* NXMLAngleStructureReader::getStructure() { return angles; } // Inline functions for NXMLAngleStructureListReader inline NXMLAngleStructureListReader::NXMLAngleStructureListReader( NTriangulation* newTri, NXMLTreeResolver& resolver) : NXMLPacketReader(resolver), list(new NAngleStructureList(false)), tri(newTri) { } inline NPacket* NXMLAngleStructureListReader::getPacket() { return list; } } // namespace regina #endif regina-4.96/engine/census/closedprimemin.cpp000644 000765 000024 00000111774 12377776535 021134 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "census/ngluingpermsearcher.h" #include "triangulation/nedge.h" #include "triangulation/nfacepair.h" #include "triangulation/ntriangulation.h" #include "utilities/boostutils.h" #include "utilities/memutils.h" namespace regina { const unsigned NClosedPrimeMinSearcher::EDGE_CHAIN_END = 1; const unsigned NClosedPrimeMinSearcher::EDGE_CHAIN_INTERNAL_FIRST = 2; const unsigned NClosedPrimeMinSearcher::EDGE_CHAIN_INTERNAL_SECOND = 3; const unsigned NClosedPrimeMinSearcher::EDGE_DOUBLE_FIRST = 4; const unsigned NClosedPrimeMinSearcher::EDGE_DOUBLE_SECOND = 5; const unsigned NClosedPrimeMinSearcher::EDGE_MISC = 6; const char NClosedPrimeMinSearcher::ECLASS_TWISTED = 1; const char NClosedPrimeMinSearcher::ECLASS_LOWDEG = 2; const char NClosedPrimeMinSearcher::ECLASS_HIGHDEG = 4; const char NClosedPrimeMinSearcher::ECLASS_CONE = 8; const char NClosedPrimeMinSearcher::ECLASS_L31 = 16; const unsigned NClosedPrimeMinSearcher::coneEdge[12][2] = { { 0, 1 }, { 0, 2 }, { 1, 2 }, { 0, 3 }, { 0, 4 }, { 3, 4 }, { 1, 3 }, { 1, 5 }, { 3, 5 }, { 2, 4 }, { 2, 5 }, { 4, 5 }, }; const char NClosedPrimeMinSearcher::coneNoTwist[12] = { 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1 }; const char NClosedPrimeMinSearcher::dataTag_ = 'c'; NClosedPrimeMinSearcher::NClosedPrimeMinSearcher(const NFacePairing* pairing, const NFacePairing::IsoList* autos, bool orientableOnly, UseGluingPerms use, void* useArgs) : NCompactSearcher(pairing, autos, orientableOnly, PURGE_NON_MINIMAL_PRIME | PURGE_P2_REDUCIBLE, use, useArgs) { // Initialise internal arrays, specifically those relating to face // orderings and properties of chains, to accurately reflect the // underlying face pairing. // // Although the NGluingPermSearcher constructor initialises the order[] // array in a vanilla fashion (front to back), we reorder things now // to match specific structures that are found in the face pairing graph. // Preconditions: // Only closed prime minimal P2-irreducible triangulations are needed. // The given face pairing is closed with order >= 3. // ---------- Selecting an ordering of faces ---------- // We fill permutations in the order: // 1. One-ended chains (== layered solid tori) from loop to // boundary, though chains may be interlaced in the // processing order; // 2. Everything else ordered by tetrahedron faces. // // Both permutations for each double edge will be processed // consecutively, the permutation for the smallest face involved // in the double edge being processed first. // // Note from the tests above that there are no triple edges. unsigned nTets = getNumberOfTetrahedra(); orderType = new unsigned[nTets * 2]; bool* orderAssigned = new bool[nTets * 4]; /**< Have we placed a tetrahedron face or its partner in the order[] array yet? */ // Hunt for structures within the face pairing graph. NTetFace face, adj; unsigned orderDone = 0; std::fill(orderAssigned, orderAssigned + 4 * nTets, false); // Begin by searching for tetrahedra that are joined to themselves. // Note that each tetrahedra can be joined to itself at most once, // since we are guaranteed that the face pairing is connected with // order >= 3. for (face.setFirst(); ! face.isPastEnd(nTets, true); face++) { if (orderAssigned[face.simp * 4 + face.facet]) continue; adj = (*pairing)[face]; if (adj.simp != face.simp) continue; order[orderDone] = face; orderType[orderDone] = EDGE_CHAIN_END; orderAssigned[face.simp * 4 + face.facet] = true; orderAssigned[adj.simp * 4 + adj.facet] = true; orderDone++; } // Record the number of one-ended chains. unsigned nChains = orderDone; // Continue by following each one-ended chain whose base was // identified in the previous loop. unsigned i; int tet; NTetFace dest1, dest2; NFacePair faces; for (i = 0; i < nChains; i++) { tet = order[i].simp; faces = NFacePair(order[i].facet, (*pairing)[order[i]].facet).complement(); dest1 = pairing->dest(tet, faces.lower()); dest2 = pairing->dest(tet, faces.upper()); // Currently tet and faces refer to the two faces of the base // tetrahedron that are pointing outwards. while (dest1.simp == dest2.simp && dest1.simp != tet && (! orderAssigned[tet * 4 + faces.lower()]) && (! orderAssigned[tet * 4 + faces.upper()])) { // Insert this pair of edges into the ordering and follow // the chain. orderType[orderDone] = EDGE_CHAIN_INTERNAL_FIRST; orderType[orderDone + 1] = EDGE_CHAIN_INTERNAL_SECOND; if (tet < dest1.simp) { order[orderDone] = NTetFace(tet, faces.lower()); order[orderDone + 1] = NTetFace(tet, faces.upper()); } orderAssigned[tet * 4 + faces.lower()] = true; orderAssigned[tet * 4 + faces.upper()] = true; orderAssigned[dest1.simp * 4 + dest1.facet] = true; orderAssigned[dest2.simp * 4 + dest2.facet] = true; faces = NFacePair(dest1.facet, dest2.facet); if (dest1.simp < tet) { order[orderDone] = NTetFace(dest1.simp, faces.lower()); order[orderDone + 1] = NTetFace(dest1.simp, faces.upper()); } faces = faces.complement(); tet = dest1.simp; dest1 = pairing->dest(tet, faces.lower()); dest2 = pairing->dest(tet, faces.upper()); orderDone += 2; } } // Record the number of edges in the face pairing graph // belonging to one-ended chains. nChainEdges = orderDone; // Run through the remaining faces. for (face.setFirst(); ! face.isPastEnd(nTets, true); face++) if (! orderAssigned[face.simp * 4 + face.facet]) { order[orderDone] = face; if (face.facet < 3 && pairing->dest(boost::next(face)).simp == pairing->dest(face).simp) orderType[orderDone] = EDGE_DOUBLE_FIRST; else if (face.facet > 0 && pairing->dest(boost::prior(face)).simp == pairing->dest(face).simp) orderType[orderDone] = EDGE_DOUBLE_SECOND; else orderType[orderDone] = EDGE_MISC; orderDone++; adj = (*pairing)[face]; orderAssigned[face.simp * 4 + face.facet] = true; orderAssigned[adj.simp * 4 + adj.facet] = true; } // All done for the order[] array. Tidy up. delete[] orderAssigned; // ---------- Calculating the possible gluing permutations ---------- // For each face in the order[] array of type EDGE_CHAIN_END or // EDGE_CHAIN_INTERNAL_FIRST, we calculate the two gluing permutations // that must be tried. // // For the remaining faces we try all possible permutations. chainPermIndices = (nChainEdges == 0 ? 0 : new int[nChainEdges * 2]); NFacePair facesAdj, comp, compAdj; NPerm4 trial1, trial2; for (i = 0; i < nChainEdges; i++) { if (orderType[i] == EDGE_CHAIN_END) { faces = NFacePair(order[i].facet, pairing->dest(order[i]).facet); comp = faces.complement(); // order[i].facet == faces.lower(), // pairing->dest(order[i]).facet == faces.upper(). chainPermIndices[2 * i] = gluingToIndex(order[i], NPerm4(faces.lower(), faces.upper(), faces.upper(), comp.lower(), comp.lower(), comp.upper(), comp.upper(), faces.lower())); chainPermIndices[2 * i + 1] = gluingToIndex(order[i], NPerm4(faces.lower(), faces.upper(), faces.upper(), comp.upper(), comp.upper(), comp.lower(), comp.lower(), faces.lower())); } else if (orderType[i] == EDGE_CHAIN_INTERNAL_FIRST) { faces = NFacePair(order[i].facet, order[i + 1].facet); comp = faces.complement(); facesAdj = NFacePair(pairing->dest(order[i]).facet, pairing->dest(order[i + 1]).facet); compAdj = facesAdj.complement(); // order[i].facet == faces.lower(), // order[i + 1].facet == faces.upper(), // pairing->dest(order[i]).facet == facesAdj.lower(). // pairing->dest(order[i + 1]).facet == facesAdj.upper(). trial1 = NPerm4(faces.lower(), facesAdj.lower(), faces.upper(), compAdj.lower(), comp.lower(), compAdj.upper(), comp.upper(), facesAdj.upper()); trial2 = NPerm4(faces.lower(), facesAdj.lower(), faces.upper(), compAdj.upper(), comp.lower(), compAdj.lower(), comp.upper(), facesAdj.upper()); if (trial1.compareWith(trial2) < 0) { chainPermIndices[2 * i] = gluingToIndex(order[i], trial1); chainPermIndices[2 * i + 2] = gluingToIndex(order[i + 1], NPerm4(faces.lower(), compAdj.upper(), faces.upper(), facesAdj.upper(), comp.lower(), facesAdj.lower(), comp.upper(), compAdj.lower())); } else { chainPermIndices[2 * i] = gluingToIndex(order[i], trial2); chainPermIndices[2 * i + 2] = gluingToIndex(order[i + 1], NPerm4(faces.lower(), compAdj.lower(), faces.upper(), facesAdj.upper(), comp.lower(), facesAdj.lower(), comp.upper(), compAdj.upper())); } trial1 = NPerm4(faces.lower(), facesAdj.lower(), faces.upper(), compAdj.lower(), comp.lower(), facesAdj.upper(), comp.upper(), compAdj.upper()); trial2 = NPerm4(faces.lower(), facesAdj.lower(), faces.upper(), compAdj.upper(), comp.lower(), facesAdj.upper(), comp.upper(), compAdj.lower()); if (trial1.compareWith(trial2) < 0) { chainPermIndices[2 * i + 1] = gluingToIndex(order[i], trial1); chainPermIndices[2 * i + 3] = gluingToIndex(order[i + 1], NPerm4(faces.lower(), compAdj.upper(), faces.upper(), facesAdj.upper(), comp.lower(), compAdj.lower(), comp.upper(), facesAdj.lower())); } else { chainPermIndices[2 * i + 1] = gluingToIndex(order[i], trial2); chainPermIndices[2 * i + 3] = gluingToIndex(order[i + 1], NPerm4(faces.lower(), compAdj.lower(), faces.upper(), facesAdj.upper(), comp.lower(), compAdj.upper(), comp.upper(), facesAdj.lower())); } } } // ---------- Tracking of vertex / edge equivalence classes ---------- #if PRUNE_HIGH_DEG_EDGE_SET // Only allow degree three edges if the face pairing graph supports // a (1,3,4) layered solid torus. We can test this easily using the // precondition that the face pairing graph must be in canonical form. if (pairing->dest(0, 0).simp == 0 && pairing->dest(0, 2).simp == 1 && pairing->dest(0, 3).simp == 1) highDegLimit = 3; else highDegLimit = 4; highDegSum = 0; highDegBound = (6 - highDegLimit) * nTets - highDegLimit; #endif } // TODO (net): See what was removed when we brought in vertex link checking. void NClosedPrimeMinSearcher::runSearch(long maxDepth) { // Preconditions: // Only closed prime minimal P2-irreducible triangulations are needed. // The given face pairing is closed with order >= 3. unsigned nTets = getNumberOfTetrahedra(); if (maxDepth < 0) { // Larger than we will ever see (and in fact grossly so). maxDepth = nTets * 4 + 1; } if (! started) { // Search initialisation. started = true; // Begin by testing for face pairings that can never lead to such a // triangulation. if (pairing_->hasTripleEdge() || pairing_->hasBrokenDoubleEndedChain() || pairing_->hasOneEndedChainWithDoubleHandle() || pairing_->hasOneEndedChainWithStrayBigon() || pairing_->hasWedgedDoubleEndedChain() || pairing_->hasTripleOneEndedChain()) { use_(0, useArgs_); return; } orderElt = 0; if (nChainEdges < nTets * 2) orientation[order[nChainEdges].simp] = 1; } // Is it a partial search that has already finished? if (orderElt == static_cast(nTets) * 2) { if (isCanonical()) use_(this, useArgs_); use_(0, useArgs_); return; } // ---------- Selecting the individual gluing permutations ---------- // Observe that in a canonical face pairing, one-ended chains always // follow an increasing sequence of tetrahedra from boundary to end, // or follow the sequence of tetrahedra 0, 1, ..., k from end to // boundary. // // In particular, this means that for any tetrahedron not internal // to a one-ended chain (with the possible exception of tetrahedron // order[nChainEdges].simp), face 0 of this tetrahedron is not // involved in a one-ended chain. // In this generation algorithm, each orientation is simply +/-1. // We won't bother assigning orientations to the tetrahedra internal // to the one-ended chains. int minOrder = orderElt; int maxOrder = orderElt + maxDepth; NTetFace face, adj; bool generic; int mergeResult; while (orderElt >= minOrder) { face = order[orderElt]; adj = (*pairing_)[face]; // TODO (long-term): Check for cancellation. // Move to the next permutation. if (orderType[orderElt] == EDGE_CHAIN_END || orderType[orderElt] == EDGE_CHAIN_INTERNAL_FIRST) { // Choose from one of the two permutations stored in array // chainPermIndices[]. generic = false; if (permIndex(face) < 0) permIndex(face) = chainPermIndices[2 * orderElt]; else if (permIndex(face) == chainPermIndices[2 * orderElt]) permIndex(face) = chainPermIndices[2 * orderElt + 1]; else permIndex(face) = 6; } else if (orderType[orderElt] == EDGE_CHAIN_INTERNAL_SECOND) { // The permutation is predetermined. generic = false; if (permIndex(face) < 0) { if (permIndex(order[orderElt - 1]) == chainPermIndices[2 * orderElt - 2]) permIndex(face) = chainPermIndices[2 * orderElt]; else permIndex(face) = chainPermIndices[2 * orderElt + 1]; } else permIndex(face) = 6; } else { // Generic case. generic = true; // Be sure to preserve the orientation of the permutation if // necessary. if ((! orientableOnly_) || adj.facet == 0) permIndex(face)++; else permIndex(face) += 2; } // Are we out of ideas for this face? if (permIndex(face) >= 6) { // Head back down to the previous face. permIndex(face) = -1; permIndex(adj) = -1; orderElt--; // Pull apart vertex and edge links at the previous level. if (orderElt >= minOrder) { splitVertexClasses(); splitEdgeClasses(); } continue; } // We are sitting on a new permutation to try. permIndex(adj) = NPerm4::invS3[permIndex(face)]; // In the following code we use several results from // "Face pairing graphs and 3-manifold enumeration", B. A. Burton, // J. Knot Theory Ramifications 13 (2004). // // These include: // // - We cannot have an edge of degree <= 2, or an edge of degree 3 // meeting three distinct tetrahedra (section 2.1); // - We must have exactly one vertex (lemma 2.6); // - We cannot have a face with two edges identified to form a // cone (lemma 2.8); // - We cannot have a face with all three edges identified to // form an L(3,1) spine (lemma 2.5). // Merge edge links and run corresponding tests. if (mergeEdgeClasses()) { // We created a structure that should not appear in a final // census triangulation (e.g., a low-degree or invalid edge, // or a face whose edges are identified in certain ways). splitEdgeClasses(); continue; } // The final triangulation should have precisely (nTets + 1) edges // (since it must have precisely one vertex). if (nEdgeClasses < nTets + 1) { // We already have too few edge classes, and the count can // only get smaller. // Note that the triangulations we are pruning include ideal // triangulations (with vertex links of Euler characteristic < 2). splitEdgeClasses(); continue; } // In general, one can prove that (assuming no invalid edges or // boundary faces) we will end up with (<= nTets + nVertices) edges // (with strictly fewer edges if some vertex links are non-spherical). // If we must end up with (> nTets + 1) edges we can therefore // prune since we won't have a one-vertex triangulation. if (nEdgeClasses > nTets + 1 + 3 * (nTets * 2 - orderElt - 1)) { // We have (2n - orderElt - 1) more gluings to choose. // Since each merge can reduce the number of edge classes // by at most 3, there is no way we can end up with just // (nTets + 1) edges at the end. splitEdgeClasses(); continue; } // Merge vertex links and run corresponding tests. mergeResult = mergeVertexClasses(); if (mergeResult & VLINK_CLOSED) { // We closed off a vertex link, which means we will end up // with more than one vertex (unless this was our very last // gluing). if (orderElt + 1 < static_cast(nTets) * 2) { splitVertexClasses(); splitEdgeClasses(); continue; } } if (mergeResult & VLINK_NON_SPHERE) { // Our vertex link will never be a 2-sphere. Stop now. splitVertexClasses(); splitEdgeClasses(); continue; } if (nVertexClasses > 1 + 3 * (nTets * 2 - orderElt - 1)) { // We have (2n - orderElt - 1) more gluings to choose. // Since each merge can reduce the number of vertex classes // by at most 3, there is no way we can end up with just one // vertex at the end. splitVertexClasses(); splitEdgeClasses(); continue; } // Fix the orientation if appropriate. if (generic && adj.facet == 0 && orientableOnly_) { // It's the first time we've hit this tetrahedron. if ((permIndex(face) + (face.facet == 3 ? 0 : 1) + (adj.facet == 3 ? 0 : 1)) % 2 == 0) orientation[adj.simp] = -orientation[face.simp]; else orientation[adj.simp] = orientation[face.simp]; } // Move on to the next face. orderElt++; // If we're at the end, try the solution and step back. if (orderElt == static_cast(nTets) * 2) { // We in fact have an entire triangulation. // Run through the automorphisms and check whether our // permutations are in canonical form. if (isCanonical()) use_(this, useArgs_); // Back to the previous face. orderElt--; // Pull apart vertex and edge links at the previous level. if (orderElt >= minOrder) { splitVertexClasses(); splitEdgeClasses(); } } else { // Not a full triangulation; just one level deeper. // We've moved onto a new face. // Be sure to get the orientation right. face = order[orderElt]; if (orientableOnly_ && pairing_->dest(face).facet > 0) { // permIndex(face) will be set to -1 or -2 as appropriate. adj = (*pairing_)[face]; if (orientation[face.simp] == orientation[adj.simp]) permIndex(face) = 1; else permIndex(face) = 0; if ((face.facet == 3 ? 0 : 1) + (adj.facet == 3 ? 0 : 1) == 1) permIndex(face) = (permIndex(face) + 1) % 2; permIndex(face) -= 2; } if (orderElt == maxOrder) { // We haven't found an entire triangulation, but we've // gone as far as we need to. // Process it, then step back. use_(this, useArgs_); // Back to the previous face. permIndex(face) = -1; orderElt--; // Pull apart vertex links at the previous level. if (orderElt >= minOrder) { splitVertexClasses(); splitEdgeClasses(); } } } } // And the search is over. // Some extra sanity checking. if (minOrder == 0) { // Our vertex classes had better be 4n standalone vertices. if (nVertexClasses != 4 * nTets) std::cerr << "ERROR: nVertexClasses == " << nVertexClasses << " at end of search!" << std::endl; for (int i = 0; i < static_cast(nTets) * 4; i++) { if (vertexState[i].parent != -1) std::cerr << "ERROR: vertexState[" << i << "].parent == " << vertexState[i].parent << " at end of search!" << std::endl; if (vertexState[i].rank != 0) std::cerr << "ERROR: vertexState[" << i << "].rank == " << vertexState[i].rank << " at end of search!" << std::endl; if (vertexState[i].bdry != 3) std::cerr << "ERROR: vertexState[" << i << "].bdry == " << vertexState[i].bdry << " at end of search!" << std::endl; if (vertexState[i].hadEqualRank) std::cerr << "ERROR: vertexState[" << i << "].hadEqualRank == " "true at end of search!" << std::endl; if (vertexState[i].bdryEdges != 3) std::cerr << "ERROR: vertexState[" << i << "].bdryEdges == " << static_cast(vertexState[i].bdryEdges) << " at end of search!" << std::endl; if (vertexState[i].bdryNext[0] != i) std::cerr << "ERROR: vertexState[" << i << "].bdryNext[0] == " << vertexState[i].bdryNext[0] << " at end of search!" << std::endl; if (vertexState[i].bdryNext[1] != i) std::cerr << "ERROR: vertexState[" << i << "].bdryNext[1] == " << vertexState[i].bdryNext[1] << " at end of search!" << std::endl; if (vertexState[i].bdryTwist[0]) std::cerr << "ERROR: vertexState[" << i << "].bdryTwist == " "true at end of search!" << std::endl; if (vertexState[i].bdryTwist[1]) std::cerr << "ERROR: vertexState[" << i << "].bdryTwist == " "true at end of search!" << std::endl; } for (unsigned i = 0; i < nTets * 8; i++) if (vertexStateChanged[i] != -1) std::cerr << "ERROR: vertexStateChanged[" << i << "] == " << vertexStateChanged[i] << " at end of search!" << std::endl; // And our edge classes had better be 6n standalone edges. if (nEdgeClasses != 6 * nTets) std::cerr << "ERROR: nEdgeClasses == " << nEdgeClasses << " at end of search!" << std::endl; for (unsigned i = 0; i < nTets * 6; i++) { if (edgeState[i].parent != -1) std::cerr << "ERROR: edgeState[" << i << "].parent == " << edgeState[i].parent << " at end of search!" << std::endl; if (edgeState[i].rank != 0) std::cerr << "ERROR: edgeState[" << i << "].rank == " << edgeState[i].rank << " at end of search!" << std::endl; if (edgeState[i].size != 1) std::cerr << "ERROR: edgeState[" << i << "].size == " << edgeState[i].size << " at end of search!" << std::endl; if (! edgeState[i].bounded) std::cerr << "ERROR: edgeState[" << i << "].bounded == " "false at end of search!" << std::endl; if (edgeState[i].hadEqualRank) std::cerr << "ERROR: edgeState[" << i << "].hadEqualRank == " "true at end of search!" << std::endl; } for (unsigned i = 0; i < nTets * 8; i++) if (edgeStateChanged[i] != -1) std::cerr << "ERROR: edgeStateChanged[" << i << "] == " << edgeStateChanged[i] << " at end of search!" << std::endl; #if PRUNE_HIGH_DEG_EDGE_SET if (highDegSum != 0) std::cerr << "ERROR: highDegSum == " << highDegSum << " at end of search!" << std::endl; #endif } use_(0, useArgs_); } void NClosedPrimeMinSearcher::dumpData(std::ostream& out) const { NCompactSearcher::dumpData(out); int i; for (i = 0; i < orderSize; i++) { if (i) out << ' '; out << orderType[i]; } out << std::endl; out << nChainEdges << std::endl; if (nChainEdges) { for (i = 0; i < 2 * static_cast(nChainEdges); i++) { if (i) out << ' '; out << chainPermIndices[i]; } out << std::endl; } #if PRUNE_HIGH_DEG_EDGE_SET out << highDegLimit << ' ' << highDegSum << ' ' << highDegBound << std::endl; #endif } NClosedPrimeMinSearcher::NClosedPrimeMinSearcher(std::istream& in, UseGluingPerms use, void* useArgs) : NCompactSearcher(in, use, useArgs), orderType(0), nChainEdges(0), chainPermIndices(0) { if (inputError_) return; unsigned nTets = getNumberOfTetrahedra(); int i; orderType = new unsigned[2 * nTets]; for (i = 0; i < orderSize; i++) in >> orderType[i]; in >> nChainEdges; /* Unnecessary since nChainEdges is unsigned. if (nChainEdges < 0) { inputError_ = true; return; } */ if (nChainEdges) { chainPermIndices = new int[nChainEdges * 2]; for (i = 0; i < 2 * static_cast(nChainEdges); i++) { in >> chainPermIndices[i]; if (chainPermIndices[i] < 0 || chainPermIndices[i] >= 6) { inputError_ = true; return; } } } #if PRUNE_HIGH_DEG_EDGE_SET in >> highDegLimit >> highDegSum >> highDegBound; if (highDegLimit < 3 || highDegLimit > 4 || highDegSum < 0 || highDegSum > 6 * static_cast(nTets) || highDegBound != (6 - highDegLimit) * static_cast(nTets) - highDegLimit) { inputError_ = true; return; } #endif // Did we hit an unexpected EOF? if (in.eof()) inputError_ = true; } int NClosedPrimeMinSearcher::mergeEdgeClasses() { NTetFace face = order[orderElt]; NTetFace adj = (*pairing_)[face]; int retVal = 0; NPerm4 p = gluingPerm(face); int v1, w1, v2, w2; int e, f; int orderIdx; int eRep, fRep; int middleTet; v1 = face.facet; w1 = p[v1]; char parentTwists, hasTwist; for (v2 = 0; v2 < 4; v2++) { if (v2 == v1) continue; w2 = p[v2]; // Look at the edge opposite v1-v2. e = 5 - NEdge::edgeNumber[v1][v2]; f = 5 - NEdge::edgeNumber[w1][w2]; orderIdx = v2 + 4 * orderElt; // We declare the natural orientation of an edge to be smaller // vertex to larger vertex. hasTwist = (p[NEdge::edgeVertex[e][0]] > p[NEdge::edgeVertex[e][1]] ? 1 : 0); parentTwists = 0; eRep = findEdgeClass(e + 6 * face.simp, parentTwists); fRep = findEdgeClass(f + 6 * adj.simp, parentTwists); if (eRep == fRep) { edgeState[eRep].bounded = false; if (edgeState[eRep].size <= 2) retVal |= ECLASS_LOWDEG; else if (edgeState[eRep].size == 3) { // Flag as LOWDEG only if three distinct tetrahedra are used. middleTet = pairing_->dest(face.simp, v2).simp; if (face.simp != adj.simp && adj.simp != middleTet && middleTet != face.simp) retVal |= ECLASS_LOWDEG; } if (hasTwist ^ parentTwists) retVal |= ECLASS_TWISTED; edgeStateChanged[orderIdx] = -1; } else { #if PRUNE_HIGH_DEG_EDGE_SET if (edgeState[eRep].size >= highDegLimit) { if (edgeState[fRep].size >= highDegLimit) highDegSum += highDegLimit; else highDegSum += edgeState[fRep].size; } else if (edgeState[fRep].size >= highDegLimit) highDegSum += edgeState[eRep].size; else if (edgeState[eRep].size + edgeState[fRep].size > highDegLimit) highDegSum += (edgeState[eRep].size + edgeState[fRep].size - highDegLimit); #endif if (edgeState[eRep].rank < edgeState[fRep].rank) { // Join eRep beneath fRep. edgeState[eRep].parent = fRep; edgeState[eRep].twistUp = hasTwist ^ parentTwists; edgeState[fRep].size += edgeState[eRep].size; #if PRUNE_HIGH_DEG_EDGE_SET #else if (edgeState[fRep].size > 3 * getNumberOfTetrahedra()) retVal |= ECLASS_HIGHDEG; #endif if (edgeState[eRep].twistUp) { edgeState[fRep].facesPos += edgeState[eRep].facesNeg; edgeState[fRep].facesNeg += edgeState[eRep].facesPos; } else { edgeState[fRep].facesPos += edgeState[eRep].facesPos; edgeState[fRep].facesNeg += edgeState[eRep].facesNeg; } if (edgeState[fRep].facesPos.hasNonZeroMatch( edgeState[fRep].facesNeg)) retVal |= ECLASS_CONE; if (edgeState[fRep].facesPos.has3() || edgeState[fRep].facesNeg.has3()) retVal |= ECLASS_L31; edgeStateChanged[orderIdx] = eRep; } else { // Join fRep beneath eRep. edgeState[fRep].parent = eRep; edgeState[fRep].twistUp = hasTwist ^ parentTwists; if (edgeState[eRep].rank == edgeState[fRep].rank) { edgeState[eRep].rank++; edgeState[fRep].hadEqualRank = true; } edgeState[eRep].size += edgeState[fRep].size; #if PRUNE_HIGH_DEG_EDGE_SET #else if (edgeState[eRep].size > 3 * getNumberOfTetrahedra()) retVal |= ECLASS_HIGHDEG; #endif if (edgeState[fRep].twistUp) { edgeState[eRep].facesPos += edgeState[fRep].facesNeg; edgeState[eRep].facesNeg += edgeState[fRep].facesPos; } else { edgeState[eRep].facesPos += edgeState[fRep].facesPos; edgeState[eRep].facesNeg += edgeState[fRep].facesNeg; } if (edgeState[eRep].facesPos.hasNonZeroMatch( edgeState[eRep].facesNeg)) retVal |= ECLASS_CONE; if (edgeState[eRep].facesPos.has3() || edgeState[eRep].facesNeg.has3()) retVal |= ECLASS_L31; edgeStateChanged[orderIdx] = fRep; } #if PRUNE_HIGH_DEG_EDGE_SET if (highDegSum > highDegBound) retVal |= ECLASS_HIGHDEG; #endif nEdgeClasses--; } } return retVal; } void NClosedPrimeMinSearcher::splitEdgeClasses() { NTetFace face = order[orderElt]; int v1, v2; int e; int eIdx, orderIdx; int rep, subRep; v1 = face.facet; for (v2 = 3; v2 >= 0; v2--) { if (v2 == v1) continue; // Look at the edge opposite v1-v2. e = 5 - NEdge::edgeNumber[v1][v2]; eIdx = e + 6 * face.simp; orderIdx = v2 + 4 * orderElt; if (edgeStateChanged[orderIdx] < 0) edgeState[findEdgeClass(eIdx)].bounded = true; else { subRep = edgeStateChanged[orderIdx]; rep = edgeState[subRep].parent; edgeState[subRep].parent = -1; if (edgeState[subRep].hadEqualRank) { edgeState[subRep].hadEqualRank = false; edgeState[rep].rank--; } edgeState[rep].size -= edgeState[subRep].size; #if PRUNE_HIGH_DEG_EDGE_SET if (edgeState[rep].size >= highDegLimit) { if (edgeState[subRep].size >= highDegLimit) highDegSum -= highDegLimit; else highDegSum -= edgeState[subRep].size; } else if (edgeState[subRep].size >= highDegLimit) highDegSum -= edgeState[rep].size; else if (edgeState[rep].size + edgeState[subRep].size > highDegLimit) highDegSum -= (edgeState[rep].size + edgeState[subRep].size - highDegLimit); #endif if (edgeState[subRep].twistUp) { edgeState[rep].facesPos -= edgeState[subRep].facesNeg; edgeState[rep].facesNeg -= edgeState[subRep].facesPos; } else { edgeState[rep].facesPos -= edgeState[subRep].facesPos; edgeState[rep].facesNeg -= edgeState[subRep].facesNeg; } edgeStateChanged[orderIdx] = -1; nEdgeClasses++; } } } } // namespace regina regina-4.96/engine/census/CMakeLists.txt000644 000765 000024 00000001547 12377774125 020143 0ustar00babstaff000000 000000 # census # Files to compile SET ( FILES closedprimemin compact dim2census dim2edgepairing dim2gluingperms dim2gluingpermsearcher euler hyperbolic ncensus nfacepairing ngluingperms ngluingpermsearcher ) # Prepend folder name FOREACH ( SOURCE_FILE ${FILES} ) SET ( SOURCES ${SOURCES} census/${SOURCE_FILE}) ENDFOREACH(SOURCE_FILE) SET(SOURCES ${SOURCES} PARENT_SCOPE) if (${REGINA_INSTALL_DEV}) INSTALL(FILES dim2census.h dim2edgepairing.h dim2gluingperms.h dim2gluingpermsearcher.h ncensus.h nfacepairing.h ngenericfacetpairing.h ngenericfacetpairing-impl.h ngenericfacetpairing.tcc ngenericgluingperms.h ngenericgluingperms-impl.h ngenericgluingperms.tcc ngluingperms.h ngluingpermsearcher.h DESTINATION ${INCLUDEDIR}/census COMPONENT Development) endif (${REGINA_INSTALL_DEV}) regina-4.96/engine/census/compact.cpp000644 000765 000024 00000120126 12377776535 017537 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "census/ngluingpermsearcher.h" #include "triangulation/nedge.h" #include "triangulation/nfacepair.h" #include "triangulation/ntriangulation.h" #include "utilities/boostutils.h" #include "utilities/memutils.h" namespace regina { const char NCompactSearcher::VLINK_CLOSED = 1; const char NCompactSearcher::VLINK_NON_SPHERE = 2; const int NCompactSearcher::vertexLinkNextFace[4][4] = { { -1, 2, 3, 1}, { 3, -1, 0, 2}, { 1, 3, -1, 0}, { 1, 2, 0, -1} }; const int NCompactSearcher::vertexLinkPrevFace[4][4] = { { -1, 3, 1, 2}, { 2, -1, 3, 0}, { 3, 0, -1, 1}, { 2, 0, 1, -1} }; const char NCompactSearcher::dataTag_ = 'f'; void NCompactSearcher::TetVertexState::dumpData(std::ostream& out) const { // Be careful with twistUp, which is a char but which should be // written as an int. out << parent << ' ' << rank << ' ' << bdry << ' ' << (twistUp ? 1 : 0) << ' ' << (hadEqualRank ? 1 : 0) << ' ' << static_cast(bdryEdges) << ' ' << bdryNext[0] << ' ' << bdryNext[1] << ' ' << static_cast(bdryTwist[0]) << ' ' << static_cast(bdryTwist[1]) << ' ' << bdryNextOld[0] << ' ' << bdryNextOld[1] << ' ' << static_cast(bdryTwistOld[0]) << ' ' << static_cast(bdryTwistOld[1]); } bool NCompactSearcher::TetVertexState::readData(std::istream& in, unsigned long nStates) { in >> parent >> rank >> bdry; // twistUp is a char, but we need to read it as an int. int twist; in >> twist; twistUp = twist; // hadEqualRank is a bool, but we need to read it as an int. int bRank; in >> bRank; hadEqualRank = bRank; // More chars to ints coming. int bVal; in >> bVal; bdryEdges = bVal; in >> bdryNext[0] >> bdryNext[1]; in >> bVal; bdryTwist[0] = bVal; in >> bVal; bdryTwist[1] = bVal; in >> bdryNextOld[0] >> bdryNextOld[1]; in >> bVal; bdryTwistOld[0] = bVal; in >> bVal; bdryTwistOld[1] = bVal; if (parent < -1 || parent >= static_cast(nStates)) return false; if (rank >= nStates) return false; if (bdry > 3 * nStates) return false; if (twist != 1 && twist != 0) return false; if (bRank != 1 && bRank != 0) return false; if (bdryEdges > 3) /* Never < 0 since this is unsigned. */ return false; if (bdryNext[0] < 0 || bdryNext[0] >= static_cast(nStates)) return false; if (bdryNext[1] < 0 || bdryNext[1] >= static_cast(nStates)) return false; if (bdryNextOld[0] < -1 || bdryNext[0] >= static_cast(nStates)) return false; if (bdryNextOld[1] < -1 || bdryNextOld[1] >= static_cast(nStates)) return false; if (bdryTwist[0] < 0 || bdryTwist[0] > 1) return false; if (bdryTwist[1] < 0 || bdryTwist[1] > 1) return false; if (bdryTwistOld[0] < 0 || bdryTwistOld[0] > 1) return false; if (bdryTwistOld[1] < 0 || bdryTwistOld[1] > 1) return false; return true; } void NCompactSearcher::TetEdgeState::dumpData(std::ostream& out, unsigned nTets) const { // Be careful with twistUp, which is a char but which should be // written as an int. out << parent << ' ' << rank << ' ' << size << ' ' << (bounded ? 1 : 0) << ' ' << (twistUp ? 1 : 0) << ' ' << (hadEqualRank ? 1 : 0) << ' '; unsigned i; for (i = 0; i < nTets * 4 && i < 64; ++i) out << char(facesPos.get(i) + '0'); out << ' '; for (i = 0; i < nTets * 4 && i < 64; ++i) out << char(facesNeg.get(i) + '0'); } bool NCompactSearcher::TetEdgeState::readData(std::istream& in, unsigned nTets) { in >> parent >> rank >> size; // bounded is a bool, but we need to read it as an int. int bBounded; in >> bBounded; bounded = bBounded; // twistUp is a char, but we need to read it as an int. int twist; in >> twist; twistUp = twist; // hadEqualRank is a bool, but we need to read it as an int. int bRank; in >> bRank; hadEqualRank = bRank; char cFaces; bool facesBroken = false; unsigned i; for (i = 0; i < nTets * 4 && i < 64; ++i) { in >> cFaces; if (cFaces >= '0' && cFaces <= '3') facesPos.set(i, cFaces - '0'); else facesBroken = true; } for (i = 0; i < nTets * 4 && i < 64; ++i) { in >> cFaces; if (cFaces >= '0' && cFaces <= '3') facesNeg.set(i, cFaces - '0'); else facesBroken = true; } if (parent < -1 || parent >= static_cast(6 * nTets)) return false; if (rank >= 6 * nTets) return false; if (size >= 6 * nTets) return false; if (bBounded != 1 && bBounded != 0) return false; if (twist != 1 && twist != 0) return false; if (bRank != 1 && bRank != 0) return false; if (facesBroken) return false; return true; } NCompactSearcher::NCompactSearcher(const NFacePairing* pairing, const NFacePairing::IsoList* autos, bool orientableOnly, int whichPurge, UseGluingPerms use, void* useArgs) : NGluingPermSearcher(pairing, autos, orientableOnly, true /* finiteOnly */, whichPurge, use, useArgs) { // Initialise the internal arrays to accurately reflect the underlying // face pairing. unsigned nTets = getNumberOfTetrahedra(); // ---------- Tracking of vertex / edge equivalence classes ---------- unsigned i; nVertexClasses = nTets * 4; vertexState = new TetVertexState[nTets * 4]; vertexStateChanged = new int[nTets * 8]; std::fill(vertexStateChanged, vertexStateChanged + nTets * 8, -1); for (i = 0; i < nTets * 4; i++) { vertexState[i].bdryEdges = 3; vertexState[i].bdryNext[0] = vertexState[i].bdryNext[1] = i; vertexState[i].bdryTwist[0] = vertexState[i].bdryTwist[1] = 0; // Initialise the backup members also so we're not writing // uninitialised data via dumpData(). vertexState[i].bdryNextOld[0] = vertexState[i].bdryNextOld[1] = -1; vertexState[i].bdryTwistOld[0] = vertexState[i].bdryTwistOld[1] = 0; } nEdgeClasses = nTets * 6; edgeState = new TetEdgeState[nTets * 6]; edgeStateChanged = new int[nTets * 8]; std::fill(edgeStateChanged, edgeStateChanged + nTets * 8, -1); // Since NQitmaskLen64 only supports 64 faces, only work with // the first 16 tetrahedra. If n > 16, this just weakens the // optimisation; however, this is no great loss since for n > 16 the // census code is at present infeasibly slow anyway. for (i = 0; i < nTets && i < 16; ++i) { /* 01 on +012, +013 */ edgeState[6 * i ].facesPos.set(4 * i + 3, 1); edgeState[6 * i ].facesPos.set(4 * i + 2, 1); /* 02 on -012 +023 */ edgeState[6 * i + 1].facesNeg.set(4 * i + 3, 1); edgeState[6 * i + 1].facesPos.set(4 * i + 1, 1); /* 03 on -013, -023 */ edgeState[6 * i + 2].facesNeg.set(4 * i + 2, 1); edgeState[6 * i + 2].facesNeg.set(4 * i + 1, 1); /* 12 on +012, +123 */ edgeState[6 * i + 3].facesPos.set(4 * i + 3, 1); edgeState[6 * i + 3].facesPos.set(4 * i + 0, 1); /* 13 on +013 -123 */ edgeState[6 * i + 4].facesPos.set(4 * i + 2, 1); edgeState[6 * i + 4].facesNeg.set(4 * i + 0, 1); /* 23 on +023, +123 */ edgeState[6 * i + 5].facesPos.set(4 * i + 1, 1); edgeState[6 * i + 5].facesPos.set(4 * i + 0, 1); } } // TODO (net): See what was removed when we brought in vertex link checking. void NCompactSearcher::runSearch(long maxDepth) { unsigned nTets = getNumberOfTetrahedra(); if (maxDepth < 0) { // Larger than we will ever see (and in fact grossly so). maxDepth = nTets * 4 + 1; } if (! started) { // Search initialisation. started = true; // Do we in fact have no permutation at all to choose? if (maxDepth == 0 || pairing_->dest(0, 0).isBoundary(nTets)) { use_(this, useArgs_); use_(0, useArgs_); return; } orderElt = 0; orientation[0] = 1; } // Is it a partial search that has already finished? if (orderElt == orderSize) { if (isCanonical()) use_(this, useArgs_); use_(0, useArgs_); return; } // ---------- Selecting the individual gluing permutations ---------- int minOrder = orderElt; int maxOrder = orderElt + maxDepth; NTetFace face, adj; int mergeResult; while (orderElt >= minOrder) { face = order[orderElt]; adj = (*pairing_)[face]; // TODO (long-term): Check for cancellation. // Move to the next permutation. // Be sure to preserve the orientation of the permutation if necessary. if ((! orientableOnly_) || adj.facet == 0) permIndex(face)++; else permIndex(face) += 2; // Are we out of ideas for this face? if (permIndex(face) >= 6) { // Yep. Head back down to the previous face. permIndex(face) = -1; permIndex(adj) = -1; orderElt--; // Pull apart vertex and edge links at the previous level. if (orderElt >= minOrder) { splitVertexClasses(); splitEdgeClasses(); } continue; } // We are sitting on a new permutation to try. permIndex(adj) = NPerm4::invS3[permIndex(face)]; // Merge edge links and run corresponding tests. if (mergeEdgeClasses()) { // We created an invalid edge. splitEdgeClasses(); continue; } // Merge vertex links and run corresponding tests. mergeResult = mergeVertexClasses(); if (mergeResult & VLINK_NON_SPHERE) { // Our vertex link will never be a 2-sphere. Stop now. splitVertexClasses(); splitEdgeClasses(); continue; } // Fix the orientation if appropriate. if (adj.facet == 0 && orientableOnly_) { // It's the first time we've hit this tetrahedron. if ((permIndex(face) + (face.facet == 3 ? 0 : 1) + (adj.facet == 3 ? 0 : 1)) % 2 == 0) orientation[adj.simp] = -orientation[face.simp]; else orientation[adj.simp] = orientation[face.simp]; } // Move on to the next face. orderElt++; // If we're at the end, try the solution and step back. if (orderElt == orderSize) { // We in fact have an entire triangulation. // Run through the automorphisms and check whether our // permutations are in canonical form. if (isCanonical()) use_(this, useArgs_); // Back to the previous face. orderElt--; // Pull apart vertex and edge links at the previous level. if (orderElt >= minOrder) { splitVertexClasses(); splitEdgeClasses(); } } else { // Not a full triangulation; just one level deeper. // We've moved onto a new face. // Be sure to get the orientation right. face = order[orderElt]; if (orientableOnly_ && pairing_->dest(face).facet > 0) { // permIndex(face) will be set to -1 or -2 as appropriate. adj = (*pairing_)[face]; if (orientation[face.simp] == orientation[adj.simp]) permIndex(face) = 1; else permIndex(face) = 0; if ((face.facet == 3 ? 0 : 1) + (adj.facet == 3 ? 0 : 1) == 1) permIndex(face) = (permIndex(face) + 1) % 2; permIndex(face) -= 2; } if (orderElt == maxOrder) { // We haven't found an entire triangulation, but we've // gone as far as we need to. // Process it, then step back. use_(this, useArgs_); // Back to the previous face. permIndex(face) = -1; orderElt--; // Pull apart vertex and edge links at the previous level. if (orderElt >= minOrder) { splitVertexClasses(); splitEdgeClasses(); } } } } // And the search is over. // Some extra sanity checking. if (minOrder == 0) { // Our vertex classes had better be 4n standalone vertices. if (nVertexClasses != 4 * nTets) std::cerr << "ERROR: nVertexClasses == " << nVertexClasses << " at end of search!" << std::endl; for (int i = 0; i < static_cast(nTets) * 4; i++) { if (vertexState[i].parent != -1) std::cerr << "ERROR: vertexState[" << i << "].parent == " << vertexState[i].parent << " at end of search!" << std::endl; if (vertexState[i].rank != 0) std::cerr << "ERROR: vertexState[" << i << "].rank == " << vertexState[i].rank << " at end of search!" << std::endl; if (vertexState[i].bdry != 3) std::cerr << "ERROR: vertexState[" << i << "].bdry == " << vertexState[i].bdry << " at end of search!" << std::endl; if (vertexState[i].hadEqualRank) std::cerr << "ERROR: vertexState[" << i << "].hadEqualRank == " "true at end of search!" << std::endl; if (vertexState[i].bdryEdges != 3) std::cerr << "ERROR: vertexState[" << i << "].bdryEdges == " << static_cast(vertexState[i].bdryEdges) << " at end of search!" << std::endl; if (vertexState[i].bdryNext[0] != i) std::cerr << "ERROR: vertexState[" << i << "].bdryNext[0] == " << vertexState[i].bdryNext[0] << " at end of search!" << std::endl; if (vertexState[i].bdryNext[1] != i) std::cerr << "ERROR: vertexState[" << i << "].bdryNext[1] == " << vertexState[i].bdryNext[1] << " at end of search!" << std::endl; if (vertexState[i].bdryTwist[0]) std::cerr << "ERROR: vertexState[" << i << "].bdryTwist == " "true at end of search!" << std::endl; if (vertexState[i].bdryTwist[1]) std::cerr << "ERROR: vertexState[" << i << "].bdryTwist == " "true at end of search!" << std::endl; } for (unsigned i = 0; i < nTets * 8; i++) if (vertexStateChanged[i] != -1) std::cerr << "ERROR: vertexStateChanged[" << i << "] == " << vertexStateChanged[i] << " at end of search!" << std::endl; // And our edge classes had better be 6n standalone edges. if (nEdgeClasses != 6 * nTets) std::cerr << "ERROR: nEdgeClasses == " << nEdgeClasses << " at end of search!" << std::endl; for (unsigned i = 0; i < nTets * 6; i++) { if (edgeState[i].parent != -1) std::cerr << "ERROR: edgeState[" << i << "].parent == " << edgeState[i].parent << " at end of search!" << std::endl; if (edgeState[i].rank != 0) std::cerr << "ERROR: edgeState[" << i << "].rank == " << edgeState[i].rank << " at end of search!" << std::endl; if (edgeState[i].size != 1) std::cerr << "ERROR: edgeState[" << i << "].size == " << edgeState[i].size << " at end of search!" << std::endl; if (! edgeState[i].bounded) std::cerr << "ERROR: edgeState[" << i << "].bounded == " "false at end of search!" << std::endl; if (edgeState[i].hadEqualRank) std::cerr << "ERROR: edgeState[" << i << "].hadEqualRank == " "true at end of search!" << std::endl; } for (unsigned i = 0; i < nTets * 8; i++) if (edgeStateChanged[i] != -1) std::cerr << "ERROR: edgeStateChanged[" << i << "] == " << edgeStateChanged[i] << " at end of search!" << std::endl; } use_(0, useArgs_); } void NCompactSearcher::dumpData(std::ostream& out) const { NGluingPermSearcher::dumpData(out); unsigned nTets = getNumberOfTetrahedra(); unsigned i; out << nVertexClasses << std::endl; for (i = 0; i < 4 * nTets; i++) { vertexState[i].dumpData(out); out << std::endl; } for (i = 0; i < 8 * nTets; i++) { if (i) out << ' '; out << vertexStateChanged[i]; } out << std::endl; out << nEdgeClasses << std::endl; for (i = 0; i < 6 * nTets; i++) { edgeState[i].dumpData(out, nTets); out << std::endl; } for (i = 0; i < 8 * nTets; i++) { if (i) out << ' '; out << edgeStateChanged[i]; } out << std::endl; } NCompactSearcher::NCompactSearcher(std::istream& in, UseGluingPerms use, void* useArgs) : NGluingPermSearcher(in, use, useArgs), nVertexClasses(0), vertexState(0), vertexStateChanged(0), nEdgeClasses(0), edgeState(0), edgeStateChanged(0) { if (inputError_) return; unsigned nTets = getNumberOfTetrahedra(); unsigned i; in >> nVertexClasses; if (nVertexClasses > 4 * nTets) { inputError_ = true; return; } vertexState = new TetVertexState[4 * nTets]; for (i = 0; i < 4 * nTets; i++) if (! vertexState[i].readData(in, 4 * nTets)) { inputError_ = true; return; } vertexStateChanged = new int[8 * nTets]; for (i = 0; i < 8 * nTets; i++) { in >> vertexStateChanged[i]; if (vertexStateChanged[i] < -1 || vertexStateChanged[i] >= 4 * static_cast(nTets)) { inputError_ = true; return; } } in >> nEdgeClasses; if (nEdgeClasses > 6 * nTets) { inputError_ = true; return; } edgeState = new TetEdgeState[6 * nTets]; for (i = 0; i < 6 * nTets; i++) if (! edgeState[i].readData(in, nTets)) { inputError_ = true; return; } edgeStateChanged = new int[8 * nTets]; for (i = 0; i < 8 * nTets; i++) { in >> edgeStateChanged[i]; if (edgeStateChanged[i] < -1 || edgeStateChanged[i] >= 6 * static_cast(nTets)) { inputError_ = true; return; } } // Did we hit an unexpected EOF? if (in.eof()) inputError_ = true; } int NCompactSearcher::mergeVertexClasses() { // Merge all three vertex pairs for the current face. NTetFace face = order[orderElt]; NTetFace adj = (*pairing_)[face]; int retVal = 0; int v, w; int vIdx, wIdx, tmpIdx, nextIdx; unsigned orderIdx; int vRep, wRep; int vNext[2], wNext[2]; char vTwist[2], wTwist[2]; NPerm4 p = gluingPerm(face); char parentTwists, hasTwist, tmpTwist; for (v = 0; v < 4; v++) { if (v == face.facet) continue; w = p[v]; vIdx = v + 4 * face.simp; wIdx = w + 4 * adj.simp; orderIdx = v + 4 * orderElt; // Are the natural 012 representations of the two faces joined // with reversed orientations? // Here we combine the sign of permutation p with the mappings // from 012 to the native tetrahedron vertices, i.e., v <-> 3 and // w <-> 3. hasTwist = (p.sign() < 0 ? 0 : 1); if ((v == 3 && w != 3) || (v != 3 && w == 3)) hasTwist ^= 1; parentTwists = 0; for (vRep = vIdx; vertexState[vRep].parent >= 0; vRep = vertexState[vRep].parent) parentTwists ^= vertexState[vRep].twistUp; for (wRep = wIdx; vertexState[wRep].parent >= 0; wRep = vertexState[wRep].parent) parentTwists ^= vertexState[wRep].twistUp; if (vRep == wRep) { vertexState[vRep].bdry -= 2; if (vertexState[vRep].bdry == 0) retVal |= VLINK_CLOSED; // Have we made the vertex link non-orientable? if (hasTwist ^ parentTwists) retVal |= VLINK_NON_SPHERE; vertexStateChanged[orderIdx] = -1; // Examine the cycles of boundary components. if (vIdx == wIdx) { // Either we are folding together two adjacent edges of the // vertex link, or we are making the vertex link // non-orientable. // The possible cases are: // // 1) hasTwist is true. The vertex becomes // non-orientable, but we should already have flagged // this above. Don't touch anything. // // 2) hasTwist is false, and vertexState[vIdx].bdryEdges is 3. // Here we are taking a stand-alone triangle and folding // two of its edges together. Nothing needs to change. // // 3) hasTwist is false, and vertexState[vIdx].bdryEdges is 2. // This means we are folding together two edges of a // triangle whose third edge is already joined elsewhere. // We deal with this as follows: // if ((! hasTwist) && vertexState[vIdx].bdryEdges < 3) { // Although bdryEdges is 2, we don't bother keeping // a backup in bdryTwistOld[]. This is because // bdryEdges jumps straight from 2 to 0, and the // neighbours in bdryNext[] / bdryTwist[] never get // overwritten. if (vertexState[vIdx].bdryNext[0] == vIdx) { // We are closing off a single boundary of length // two. All good. } else { // Adjust each neighbour to point to the other. vtxBdryJoin(vertexState[vIdx].bdryNext[0], 1 ^ vertexState[vIdx].bdryTwist[0], vertexState[vIdx].bdryNext[1], vertexState[vIdx].bdryTwist[1] ^ vertexState[vIdx].bdryTwist[0]); } } vertexState[vIdx].bdryEdges -= 2; } else { // We are joining two distinct tetrahedron vertices that // already contribute to the same vertex link. if (vertexState[vIdx].bdryEdges == 2) vtxBdryBackup(vIdx); if (vertexState[wIdx].bdryEdges == 2) vtxBdryBackup(wIdx); if (vtxBdryLength1(vIdx) && vtxBdryLength1(wIdx)) { // We are joining together two boundaries of length one. // Do nothing and mark the non-trivial genus. // std::cerr << "NON-SPHERE: 1 >-< 1" << std::endl; retVal |= VLINK_NON_SPHERE; } else if (vtxBdryLength2(vIdx, wIdx)) { // We are closing off a single boundary of length two. // All good. } else { vtxBdryNext(vIdx, face.simp, v, face.facet, vNext, vTwist); vtxBdryNext(wIdx, adj.simp, w, adj.facet, wNext, wTwist); if (vNext[0] == wIdx && wNext[1 ^ vTwist[0]] == vIdx) { // We are joining two adjacent edges of the vertex link. // Simply eliminate them. vtxBdryJoin(vNext[1], 0 ^ vTwist[1], wNext[0 ^ vTwist[0]], (vTwist[0] ^ wTwist[0 ^ vTwist[0]]) ^ vTwist[1]); } else if (vNext[1] == wIdx && wNext[0 ^ vTwist[1]] == vIdx) { // Again, joining two adjacent edges of the vertex link. vtxBdryJoin(vNext[0], 1 ^ vTwist[0], wNext[1 ^ vTwist[1]], (vTwist[1] ^ wTwist[1 ^ vTwist[1]]) ^ vTwist[0]); } else { // See if we are joining two different boundary cycles // together; if so, we have created non-trivial genus in // the vertex link. tmpIdx = vertexState[vIdx].bdryNext[0]; tmpTwist = vertexState[vIdx].bdryTwist[0]; while (tmpIdx != vIdx && tmpIdx != wIdx) { nextIdx = vertexState[tmpIdx]. bdryNext[0 ^ tmpTwist]; tmpTwist ^= vertexState[tmpIdx]. bdryTwist[0 ^ tmpTwist]; tmpIdx = nextIdx; } if (tmpIdx == vIdx) { // Different boundary cycles. // Don't touch anything; just flag a // high genus error. // std::cerr << "NON-SPHERE: (X)" << std::endl; retVal |= VLINK_NON_SPHERE; } else { // Same boundary cycle. vtxBdryJoin(vNext[0], 1 ^ vTwist[0], wNext[1 ^ hasTwist], vTwist[0] ^ (hasTwist ^ wTwist[1 ^ hasTwist])); vtxBdryJoin(vNext[1], 0 ^ vTwist[1], wNext[0 ^ hasTwist], vTwist[1] ^ (hasTwist ^ wTwist[0 ^ hasTwist])); } } } vertexState[vIdx].bdryEdges--; vertexState[wIdx].bdryEdges--; } } else { // We are joining two distinct vertices together and merging // their vertex links. if (vertexState[vRep].rank < vertexState[wRep].rank) { // Join vRep beneath wRep. vertexState[vRep].parent = wRep; vertexState[vRep].twistUp = hasTwist ^ parentTwists; vertexState[wRep].bdry = vertexState[wRep].bdry + vertexState[vRep].bdry - 2; if (vertexState[wRep].bdry == 0) retVal |= VLINK_CLOSED; vertexStateChanged[orderIdx] = vRep; } else { // Join wRep beneath vRep. vertexState[wRep].parent = vRep; vertexState[wRep].twistUp = hasTwist ^ parentTwists; if (vertexState[vRep].rank == vertexState[wRep].rank) { vertexState[vRep].rank++; vertexState[wRep].hadEqualRank = true; } vertexState[vRep].bdry = vertexState[vRep].bdry + vertexState[wRep].bdry - 2; if (vertexState[vRep].bdry == 0) retVal |= VLINK_CLOSED; vertexStateChanged[orderIdx] = wRep; } nVertexClasses--; // Adjust the cycles of boundary components. if (vertexState[vIdx].bdryEdges == 2) vtxBdryBackup(vIdx); if (vertexState[wIdx].bdryEdges == 2) vtxBdryBackup(wIdx); if (vtxBdryLength1(vIdx)) { if (vtxBdryLength1(wIdx)) { // Both vIdx and wIdx form entire boundary components of // length one; these are joined together and the vertex // link is closed off. // No changes to make for the boundary cycles. } else { // Here vIdx forms a boundary component of length one, // and wIdx does not. Ignore vIdx, and simply excise the // relevant edge from wIdx. // There is nothing to do here unless wIdx only has one // boundary edge remaining (in which case we know it // joins to some different tetrahedron vertex). if (vertexState[wIdx].bdryEdges == 1) { wNext[0] = vertexState[wIdx].bdryNext[0]; wNext[1] = vertexState[wIdx].bdryNext[1]; wTwist[0] = vertexState[wIdx].bdryTwist[0]; wTwist[1] = vertexState[wIdx].bdryTwist[1]; vtxBdryJoin(wNext[0], 1 ^ wTwist[0], wNext[1], wTwist[0] ^ wTwist[1]); } } } else if (vtxBdryLength1(wIdx)) { // As above, but with the two vertices the other way around. if (vertexState[vIdx].bdryEdges == 1) { vNext[0] = vertexState[vIdx].bdryNext[0]; vNext[1] = vertexState[vIdx].bdryNext[1]; vTwist[0] = vertexState[vIdx].bdryTwist[0]; vTwist[1] = vertexState[vIdx].bdryTwist[1]; vtxBdryJoin(vNext[0], 1 ^ vTwist[0], vNext[1], vTwist[0] ^ vTwist[1]); } } else { // Each vertex belongs to a boundary component of length // at least two. Merge the components together. vtxBdryNext(vIdx, face.simp, v, face.facet, vNext, vTwist); vtxBdryNext(wIdx, adj.simp, w, adj.facet, wNext, wTwist); vtxBdryJoin(vNext[0], 1 ^ vTwist[0], wNext[1 ^ hasTwist], vTwist[0] ^ (hasTwist ^ wTwist[1 ^ hasTwist])); vtxBdryJoin(vNext[1], 0 ^ vTwist[1], wNext[0 ^ hasTwist], vTwist[1] ^ (hasTwist ^ wTwist[0 ^ hasTwist])); } vertexState[vIdx].bdryEdges--; vertexState[wIdx].bdryEdges--; } } return retVal; } void NCompactSearcher::splitVertexClasses() { // Split all three vertex pairs for the current face. NTetFace face = order[orderElt]; NTetFace adj = (*pairing_)[face]; int v, w; int vIdx, wIdx; unsigned orderIdx; int rep, subRep; NPerm4 p = gluingPerm(face); // Do everything in reverse. This includes the loop over vertices. for (v = 3; v >= 0; v--) { if (v == face.facet) continue; w = p[v]; vIdx = v + 4 * face.simp; wIdx = w + 4 * adj.simp; orderIdx = v + 4 * orderElt; if (vertexStateChanged[orderIdx] < 0) { for (rep = vIdx; vertexState[rep].parent >= 0; rep = vertexState[rep].parent) ; vertexState[rep].bdry += 2; } else { subRep = vertexStateChanged[orderIdx]; rep = vertexState[subRep].parent; vertexState[subRep].parent = -1; if (vertexState[subRep].hadEqualRank) { vertexState[subRep].hadEqualRank = false; vertexState[rep].rank--; } vertexState[rep].bdry = vertexState[rep].bdry + 2 - vertexState[subRep].bdry; vertexStateChanged[orderIdx] = -1; nVertexClasses++; } // Restore cycles of boundary components. if (vIdx == wIdx) { vertexState[vIdx].bdryEdges += 2; // Adjust neighbours to point back to vIdx if required. if (vertexState[vIdx].bdryEdges == 2) vtxBdryFixAdj(vIdx); } else { vertexState[wIdx].bdryEdges++; vertexState[vIdx].bdryEdges++; switch (vertexState[wIdx].bdryEdges) { case 3: vertexState[wIdx].bdryNext[0] = vertexState[wIdx].bdryNext[1] = wIdx; vertexState[wIdx].bdryTwist[0] = vertexState[wIdx].bdryTwist[1] = 0; break; case 2: vtxBdryRestore(wIdx); // Fall through to the next case, so we can // adjust the neighbours. case 1: // Nothing was changed for wIdx during the merge, // so there is nothing there to restore. // Adjust neighbours to point back to wIdx. vtxBdryFixAdj(wIdx); } switch (vertexState[vIdx].bdryEdges) { case 3: vertexState[vIdx].bdryNext[0] = vertexState[vIdx].bdryNext[1] = vIdx; vertexState[vIdx].bdryTwist[0] = vertexState[vIdx].bdryTwist[1] = 0; break; case 2: vtxBdryRestore(vIdx); // Fall through to the next case, so we can // adjust the neighbours. case 1: // Nothing was changed for vIdx during the merge, // so there is nothing there to restore. // Adjust neighbours to point back to vIdx. vtxBdryFixAdj(vIdx); } } } } bool NCompactSearcher::mergeEdgeClasses() { NTetFace face = order[orderElt]; NTetFace adj = (*pairing_)[face]; bool retVal = false; NPerm4 p = gluingPerm(face); int v1, w1, v2, w2; int e, f; int orderIdx; int eRep, fRep; v1 = face.facet; w1 = p[v1]; char parentTwists, hasTwist; for (v2 = 0; v2 < 4; v2++) { if (v2 == v1) continue; w2 = p[v2]; // Look at the edge opposite v1-v2. e = 5 - NEdge::edgeNumber[v1][v2]; f = 5 - NEdge::edgeNumber[w1][w2]; orderIdx = v2 + 4 * orderElt; // We declare the natural orientation of an edge to be smaller // vertex to larger vertex. hasTwist = (p[NEdge::edgeVertex[e][0]] > p[NEdge::edgeVertex[e][1]] ? 1 : 0); parentTwists = 0; eRep = findEdgeClass(e + 6 * face.simp, parentTwists); fRep = findEdgeClass(f + 6 * adj.simp, parentTwists); if (eRep == fRep) { edgeState[eRep].bounded = false; if (hasTwist ^ parentTwists) retVal = true; edgeStateChanged[orderIdx] = -1; } else { if (edgeState[eRep].rank < edgeState[fRep].rank) { // Join eRep beneath fRep. edgeState[eRep].parent = fRep; edgeState[eRep].twistUp = hasTwist ^ parentTwists; edgeState[fRep].size += edgeState[eRep].size; edgeStateChanged[orderIdx] = eRep; } else { // Join fRep beneath eRep. edgeState[fRep].parent = eRep; edgeState[fRep].twistUp = hasTwist ^ parentTwists; if (edgeState[eRep].rank == edgeState[fRep].rank) { edgeState[eRep].rank++; edgeState[fRep].hadEqualRank = true; } edgeState[eRep].size += edgeState[fRep].size; edgeStateChanged[orderIdx] = fRep; } nEdgeClasses--; } } return retVal; } void NCompactSearcher::splitEdgeClasses() { NTetFace face = order[orderElt]; int v1, v2; int e; int eIdx, orderIdx; int rep, subRep; v1 = face.facet; for (v2 = 3; v2 >= 0; v2--) { if (v2 == v1) continue; // Look at the edge opposite v1-v2. e = 5 - NEdge::edgeNumber[v1][v2]; eIdx = e + 6 * face.simp; orderIdx = v2 + 4 * orderElt; if (edgeStateChanged[orderIdx] < 0) edgeState[findEdgeClass(eIdx)].bounded = true; else { subRep = edgeStateChanged[orderIdx]; rep = edgeState[subRep].parent; edgeState[subRep].parent = -1; if (edgeState[subRep].hadEqualRank) { edgeState[subRep].hadEqualRank = false; edgeState[rep].rank--; } edgeState[rep].size -= edgeState[subRep].size; edgeStateChanged[orderIdx] = -1; nEdgeClasses++; } } } void NCompactSearcher::vtxBdryConsistencyCheck() { int adj, id, end; for (id = 0; id < static_cast(getNumberOfTetrahedra()) * 4; id++) if (vertexState[id].bdryEdges > 0) for (end = 0; end < 2; end++) { adj = vertexState[id].bdryNext[end]; if (vertexState[adj].bdryEdges == 0) std::cerr << "CONSISTENCY ERROR: Vertex link boundary " << id << '/' << end << " runs into an internal vertex." << std::endl; if (vertexState[adj].bdryNext[(1 ^ end) ^ vertexState[id].bdryTwist[end]] != id) std::cerr << "CONSISTENCY ERROR: Vertex link boundary " << id << '/' << end << " has a mismatched adjacency." << std::endl; if (vertexState[adj].bdryTwist[(1 ^ end) ^ vertexState[id].bdryTwist[end]] != vertexState[id].bdryTwist[end]) std::cerr << "CONSISTENCY ERROR: Vertex link boundary " << id << '/' << end << " has a mismatched twist." << std::endl; } } void NCompactSearcher::vtxBdryDump(std::ostream& out) { for (unsigned id = 0; id < getNumberOfTetrahedra() * 4; id++) { if (id > 0) out << ' '; out << vertexState[id].bdryNext[0] << (vertexState[id].bdryTwist[0] ? '~' : '-') << id << (vertexState[id].bdryTwist[1] ? '~' : '-') << vertexState[id].bdryNext[1] << " [" << int(vertexState[id].bdryEdges) << ']'; } out << std::endl; } } // namespace regina regina-4.96/engine/census/dim2census.cpp000644 000765 000024 00000014003 12377776536 020162 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include "census/dim2census.h" #include "census/dim2gluingpermsearcher.h" #include "dim2/dim2triangulation.h" #include "utilities/memutils.h" namespace regina { unsigned long Dim2Census::formCensus(NPacket* parent, unsigned nTriangles, NBoolSet orientability, NBoolSet boundary, int nBdryEdges, AcceptTriangulation sieve, void* sieveArgs) { // If obviously nothing is going to happen but we won't realise // it until we've actually generated the facet pairings, change // nTriangles to 0 so we'll realise it immediately once the new // thread starts. if (orientability == NBoolSet::sNone) nTriangles = 0; // Start the census! Dim2Census* census = new Dim2Census(parent, orientability, sieve, sieveArgs); Dim2EdgePairing::findAllPairings(nTriangles, boundary, nBdryEdges, Dim2Census::foundEdgePairing, census, false); unsigned long ans = census->whichSoln_ - 1; delete census; return ans; } unsigned long Dim2Census::formPartialCensus(const Dim2EdgePairing* pairing, NPacket* parent, NBoolSet orientability, AcceptTriangulation sieve, void* sieveArgs) { // Is it obvious that nothing will happen? if (orientability == NBoolSet::sNone) return 0; // Make a list of automorphisms. Dim2EdgePairing::IsoList autos; pairing->findAutomorphisms(autos); // Select the individual gluing permutations. Dim2Census census(parent, orientability, sieve, sieveArgs); Dim2GluingPermSearcher::findAllPerms(pairing, &autos, ! census.orientability_.hasFalse(), Dim2Census::foundGluingPerms, &census); // Clean up. std::for_each(autos.begin(), autos.end(), FuncDelete()); return census.whichSoln_ - 1; } Dim2Census::Dim2Census(NPacket* parent, const NBoolSet& orientability, AcceptTriangulation sieve, void* sieveArgs) : parent_(parent), orientability_(orientability), sieve_(sieve), sieveArgs_(sieveArgs), whichSoln_(1) { } void Dim2Census::foundEdgePairing(const Dim2EdgePairing* pairing, const Dim2EdgePairing::IsoList* autos, void* census) { Dim2Census* realCensus = static_cast(census); if (pairing) { // We've found another edge pairing. // Select the individual gluing permutations. Dim2GluingPermSearcher::findAllPerms(pairing, autos, ! realCensus->orientability_.hasFalse(), Dim2Census::foundGluingPerms, census); } else { // Census generation has finished. } } void Dim2Census::foundGluingPerms(const Dim2GluingPermSearcher* perms, void* census) { if (perms) { // We've found another permutation set. // Triangulate and see what we've got. Dim2Triangulation* tri = perms->triangulate(); Dim2Census* realCensus = static_cast(census); bool ok = true; if ((! realCensus->orientability_.hasTrue()) && tri->isOrientable()) ok = false; else if (realCensus->sieve_ && ! realCensus->sieve_(tri, realCensus->sieveArgs_)) ok = false; if (ok) { // Put it in the census! // Make sure it has a charming label. // Don't insist on unique labels, since this requirement // will soon be dropped and it multiplies the running time // by a factor of #triangulations. std::ostringstream out; out << "Item " << realCensus->whichSoln_; tri->setPacketLabel(out.str()); realCensus->parent_->insertChildLast(tri); realCensus->whichSoln_++; } else { // Bad triangulation. delete tri; } } } } // namespace regina regina-4.96/engine/census/dim2census.h000644 000765 000024 00000036611 12377774644 017636 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file census/dim2census.h * \brief Deals with forming a census of all 2-manifold triangulations * of a given size. */ #ifndef __DIM2CENSUS_H #ifndef __DOXYGEN #define __DIM2CENSUS_H #endif #include "regina-core.h" #include "census/dim2edgepairing.h" #include "utilities/nbooleans.h" namespace regina { class Dim2GluingPerms; class Dim2GluingPermSearcher; class Dim2Triangulation; class NPacket; /** * \weakgroup census * @{ */ /** * A utility class used to search for triangulations across one or more * 2-manifold census databases. */ class REGINA_API Dim2Census { public: /** * A routine used to determine whether a particular 2-manifold * triangulation should be included in a census. Routines of this * type are used by Dim2Census::formCensus(). * * The first parameter passed should be a triangulation currently * under consideration. * The second parameter may contain arbitrary data as passed to * Dim2Census::formCensus(). * * The return value should be \c true if the triangulation passed * should be included in the census, or \c false otherwise. * * \deprecated The Dim2Census enumeration facilities are on their * way out of Regina, and in the future the Dim2Census class will be * used purely for census lookups. If you wish to build a census * yourself, you should call Dim2EdgePairing::findAllPairings() and * Dim2GluingPermSearcher::findAllPerms() directly. */ typedef bool (*AcceptTriangulation)(Dim2Triangulation*, void*); private: NPacket* parent_; /**< The argument passed to formCensus(). */ NBoolSet orientability_; /**< The argument passed to formCensus(). */ AcceptTriangulation sieve_; /**< The arbitrary constraint function to run triangulations through. */ void* sieveArgs_; /**< The second argument to pass to function \a sieve. */ unsigned long whichSoln_; /**< The number of the solution we are up to. */ public: /** * Deprecated routine that fills the given packet with all * triangulations in a census of 2-manifold triangulations satisfying * the given constraints. Each triangulation in the census will * appear as a child of the given packet. * * This routine will conduct a census of all valid triangulations * containing a given number of triangles. All such triangulations * are included in the census up to combinatorial isomorphism; given * any isomorphism class, exactly one representative will appear in * the census. * * The census can be optionally restricted to only include * triangulations satisfying further constraints (such as * orientability); see the individual parameter * descriptions for further details. In particular, parameter * \a sieve can be used to impose arbitrary restrictions that are * not hard-coded into this class. * * Note that if constraints may be imposed using the hard-coded * parameters (such as orientability), it is * generally better to do this than to use the arbitrary * constraint parameter \a sieve. Hard-coded parameters will be * tested earlier, and some (such as orientability) can be * incorporated directly into the census algorithm to give a vast * performance increase. * * Note that this routine should only be used if the census * contains a small enough total number of triangulations to * avoid any memory disasters. * * \deprecated The Dim2Census enumeration facilities are on their * way out of Regina, and in the future the Dim2Census class will be * used purely for census lookups. To perform the kind of * enumeration that is described here, you should call * Dim2EdgePairing::findAllPairings() and * Dim2GluingPermSearcher::findAllPerms() directly. * * \ifacespython Parameters \a sieve and \a sieveArgs * are not present (and will be treated as 0). * * @param parent the packet beneath which members of the census will * be placed. * @param nTriangles the number of triangles in each triangulation * in the census. * @param orientability determines whether to include orientable * and/or non-orientable triangulations. The set should contain \c true * if orientable triangulations are to be included, and should contain * \c false if non-orientable triangulations are to be included. * @param boundary determines whether to include triangulations with * and/or without boundary edges. The set should contain \c true * if triangulations with boundary edges are to be included, and * should contain \c false if triangulations with only internal * edges are to be included. * @param nBdryEdges specifies the precise number of boundary edges * that should be present in the triangulations produced. If this * parameter is negative, it is ignored and no additional restriction * is imposed. See the documentation for routine * Dim2EdgePairing::findAllPairings() for details regarding this * parameter and how it interacts with parameter \a boundary. * @param sieve an additional constraint function that may be * used to exclude certain triangulations from the census. If * this parameter is non-zero, each triangulation produced (after * passing all other criteria) will be passed through this * function. If this function returns \c true then the triangulation * will be included in the census; otherwise it will not. * When this function is called, the first (triangulation) * argument will be a triangulation under consideration for * inclusion in the census. The second argument will be * parameter \a sieveArgs as passed to formCensus(). * Parameter \a sieve may be passed as \c null (in which case no * additional constraint function will be used). * @param sieveArgs the pointer to pass as the final parameter * for the function \a sieve which will be called upon each * triangulation found. If \a sieve is \c null then \a sieveArgs * will be ignored. * @return the number of triangulations produced in the census. */ static unsigned long formCensus(NPacket* parent, unsigned nTriangles, NBoolSet orientability, NBoolSet boundary, int nBdryEdges, AcceptTriangulation sieve = 0, void* sieveArgs = 0); /** * Deprecated routine that fills the given packet with all * triangulations in a partial census of 2-manifold triangulations * satisfying the given constraints. Each triangulation in the * partial census will appear as a child of the given packet. * * This routine will conduct a census of all valid 2-manifold * triangulations that are modelled by the given triangle edge * pairing. All such triangulations are included in the census up to * combinatorial isomorphism; given any isomorphism class, exactly * one representative will appear in the census. * * The census can be optionally restricted to only include * triangulations satisfying further constraints (such as * orientability); see the individual parameter * descriptions for further details. In particular, parameter * \a sieve can be used to impose arbitrary restrictions that are * not hard-coded into this class. * * Note that if constraints may be imposed using the hard-coded * parameters (such as orientability), it is * generally better to do this than to use the arbitrary * constraint parameter \a sieve. Hard-coded parameters will be * tested earlier, and some (such as orientability) can be * incorporated directly into the census algorithm to give a vast * performance increase. * * Note that this routine should only be used if the partial census * contains a small enough total number of triangulations to * avoid any memory disasters. * * The partial census will run in the current thread. This * routine will only return once the partial census is complete. * * \deprecated The Dim2Census enumeration facilities are on their * way out of Regina, and in the future the Dim2Census class will be * used purely for census lookups (if at all). To perform the kind of * enumeration that is described here, you should call * Dim2GluingPermSearcher::findAllPerms() directly. * * \pre The given edge pairing is connected, i.e., it is possible * to reach any triangle from any other triangle via a * series of matched edge pairs. * \pre The given edge pairing is in canonical form as described * by Dim2EdgePairing::isCanonical(). Note that all facet pairings * constructed by Dim2EdgePairing::findAllPairings() are of this form. * * \ifacespython Parameters \a sieve and \a sieveArgs * are not present (and will be treated as 0). * * @param pairing the edge pairing that * triangulations in this partial census must be modelled by. * @param parent the packet beneath which members of the partial * census will be placed. * @param orientability determines whether to include orientable * and/or non-orientable triangulations. The set should contain \c true * if orientable triangulations are to be included, and should contain * \c false if non-orientable triangulations are to be included. * @param sieve an additional constraint function that may be * used to exclude certain triangulations from the census. If * this parameter is non-zero, each triangulation produced (after * passing all other criteria) will be passed through this * function. If this function returns \c true then the triangulation * will be included in the census; otherwise it will not. * When this function is called, the first (triangulation) * argument will be a triangulation under consideration for * inclusion in the census. The second argument will be * parameter \a sieveArgs as passed to formPartialCensus(). * Parameter \a sieve may be passed as \c null (in which case no * additional constraint function will be used). * @param sieveArgs the pointer to pass as the final parameter * for the function \a sieve which will be called upon each * triangulation found. If \a sieve is \c null then \a sieveArgs * will be ignored. * @return the number of triangulations produced in the partial census. */ static unsigned long formPartialCensus(const Dim2EdgePairing* pairing, NPacket* parent, NBoolSet orientability, AcceptTriangulation sieve = 0, void* sieveArgs = 0); private: /** * Creates a new structure to hold the given information. * All parameters not explained are taken directly from * formCensus(). */ Dim2Census(NPacket* parent, const NBoolSet& orientability, AcceptTriangulation sieve, void* sieveArgs); /** * Called when a particular triangle edge pairing has been * found. This routine hooks up the edge pairing generation with * the gluing permutation generation. * * @param pairing the edge pairing that has been found. * @param autos the set of all automorphisms of the given edge * pairing. * @param census the census currently being generated; * this must really be of class Dim2Census. */ static void foundEdgePairing(const Dim2EdgePairing* pairing, const Dim2EdgePairing::IsoList* autos, void* census); /** * Called when a particular set of gluing permutations has been * found. This routine generates the corresponding triangulation * and decides whether it really belongs in the census. * * \pre The given set of gluing permutations is complete, i.e., * it is not just a partially-complete search state. Partial * searches are formed by calling Dim2GluingPermSearcher::runSearch() * with a non-negative depth argument. * * @param perms the gluing permutation set that has been found. * @param census the census currently being generated; * this must really be of class Dim2Census. */ static void foundGluingPerms(const Dim2GluingPermSearcher* perms, void* census); }; /*@}*/ } // namespace regina #endif regina-4.96/engine/census/dim2edgepairing.cpp000644 000765 000024 00000007313 12377776537 021147 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "census/dim2edgepairing.h" #include "census/ngenericfacetpairing-impl.h" #include "dim2/dim2triangle.h" #include "dim2/dim2triangulation.h" namespace regina { // Instantiate all templates from the -impl.h file. template NGenericFacetPairing<2>::NGenericFacetPairing( const NGenericFacetPairing<2>&); template NGenericFacetPairing<2>::NGenericFacetPairing( const Dim2Triangulation&); template bool NGenericFacetPairing<2>::isClosed() const; template std::string NGenericFacetPairing<2>::str() const; template std::string NGenericFacetPairing<2>::dotHeader(const char*); template void NGenericFacetPairing<2>::writeDotHeader(std::ostream&, const char*); template std::string NGenericFacetPairing<2>::dot(const char*, bool, bool) const; template void NGenericFacetPairing<2>::writeDot(std::ostream&, const char*, bool, bool) const; template std::string NGenericFacetPairing<2>::toTextRep() const; template Dim2EdgePairing* NGenericFacetPairing<2>::fromTextRep( const std::string&); template bool NGenericFacetPairing<2>::isCanonical() const; template bool NGenericFacetPairing<2>::isCanonicalInternal( NGenericFacetPairing<2>::IsoList&) const; template void NGenericFacetPairing<2>::findAutomorphisms( NGenericFacetPairing<2>::IsoList&) const; template bool NGenericFacetPairing<2>::findAllPairings(unsigned, NBoolSet, int, NGenericFacetPairing<2>::Use, void*, bool); template void* NGenericFacetPairing<2>::run(void*); } // namespace regina regina-4.96/engine/census/dim2edgepairing.h000644 000765 000024 00000012034 12377774646 020607 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file census/dim2edgepairing.h * \brief Deals with pairing off edges of triangles in a census of * 2-manifold triangulations. */ #ifndef __DIM2EDGEPAIRING_H #ifndef __DOXYGEN #define __DIM2EDGEPAIRING_H #endif #include "regina-core.h" #include "census/ngenericfacetpairing.h" #include "dim2/dim2isomorphism.h" namespace regina { /** * \weakgroup census * @{ */ /** * Represents a specific pairwise matching of edges of triangles. * Given a fixed number of triangles, each triangle edge is either * paired with some other triangle edge (which is in turn paired with * it) or remains unmatched. A triangle edge cannot be paired with itself. * * Such a matching models part of the structure of a 2-manifold triangulation, * in which each triangle edge is either glued to some other triangle edge * facet (which is in turn glued to it) or is an unglued boundary edge. * * Note that if this pairing is used to construct an actual 2-manifold * triangulation, the individual gluing orientations will still need to * be specified; they are not a part of this structure. */ class REGINA_API Dim2EdgePairing : public NGenericFacetPairing<2> { public: /** * Creates a new edge pairing that is a clone of the given edge * pairing. * * @param cloneMe the facet pairing to clone. */ Dim2EdgePairing(const Dim2EdgePairing& cloneMe); /** * Creates the edge pairing of the given 2-manifold triangulation. * This is the edge pairing that describes how the triangle edges of * the given 2-manifold triangulation are joined together, as * described in the class notes. * * \pre The given triangulation is not empty. * * @param tri the 2-manifold triangulation whose edge pairing should * be constructed. */ Dim2EdgePairing(const Dim2Triangulation& tri); private: /** * Creates a new edge pairing. All internal arrays will be * allocated but not initialised. * * \pre \a nTriangles is at least 1. * * @param nTriangles the number of triangles under * consideration in this new edge pairing. */ Dim2EdgePairing(unsigned nTriangles); // Make sure the parent class can call the private constructor. friend class NGenericFacetPairing<2>; }; /*@}*/ // Inline functions for Dim2EdgePairing inline Dim2EdgePairing::Dim2EdgePairing(const Dim2EdgePairing& cloneMe) : NGenericFacetPairing<2>(cloneMe) { } inline Dim2EdgePairing::Dim2EdgePairing(unsigned nTriangles) : NGenericFacetPairing<2>(nTriangles) { } inline Dim2EdgePairing::Dim2EdgePairing(const Dim2Triangulation& tri) : NGenericFacetPairing<2>(tri) { } } // namespace regina #endif regina-4.96/engine/census/dim2gluingperms.cpp000644 000765 000024 00000005723 12377776537 021230 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "census/dim2gluingperms.h" #include "census/ngenericgluingperms-impl.h" #include "dim2/dim2triangulation.h" namespace regina { // Instantiate all templates from the -impl.h file. template NGenericGluingPerms<2>::NGenericGluingPerms( const NGenericGluingPerms<2>&); template NGenericGluingPerms<2>::NGenericGluingPerms(std::istream&); template Dim2Triangulation* NGenericGluingPerms<2>::triangulate() const; template int NGenericGluingPerms<2>::gluingToIndex( const Dim2TriangleEdge&, const NPerm3&) const; template int NGenericGluingPerms<2>::gluingToIndex( unsigned, unsigned, const NPerm3&) const; template void NGenericGluingPerms<2>::dumpData(std::ostream&) const; } // namespace regina regina-4.96/engine/census/dim2gluingperms.h000644 000765 000024 00000013226 12377774647 020672 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file census/dim2gluingperms.h * \brief Deals with selecting gluing permutations to complement a * particular pairing of triangle edges. */ #ifndef __DIM2GLUINGPERMS_H #ifndef __DOXYGEN #define __DIM2GLUINGPERMS_H #endif #include "regina-core.h" #include "census/dim2edgepairing.h" #include "census/ngenericgluingperms.h" namespace regina { /** * \weakgroup census * @{ */ /** * Represents a specific set of gluing permutations to complement a * particular pairwise matching of triangle edges. Given a * pairwise matching of edges (as described by class Dim2EdgePairing), each * edge that is matched with some other edge will have an associated * permutation of three elements (as described by class NPerm3). * * If an edge is matched with some other edge, the two associated * permutations in this set will be inverses. If an edge is left * deliberately unmatched, it will have no associated permutation in this set. * * Such a set of permutations models part of the structure of a 2-manifold * triangulation, in which each triangle edge that is glued to another * edge has a corresponding gluing permutation (and the matched edge has * the inverse gluing permutation). * * \ifacespython Not present. */ class REGINA_API Dim2GluingPerms : public NGenericGluingPerms<2> { public: /** * Creates a new set of gluing permutations that is a clone of * the given permutation set. * * @param cloneMe the gluing permutations to clone. */ Dim2GluingPerms(const Dim2GluingPerms& cloneMe); /** * Reads a new set of gluing permutations from the given input * stream. This routine reads data in the format written by * dumpData(). * * If the data found in the input stream is invalid or * incorrectly formatted, the routine inputError() will return * \c true but the contents of this object will be otherwise * undefined. * * \warning The data format is liable to change between * Regina releases. Data in this format should be used on a * short-term temporary basis only. * * @param in the input stream from which to read. */ Dim2GluingPerms(std::istream& in); protected: /** * Creates a new permutation set. All internal arrays will be * allocated but not initialised. * * \pre The given edge pairing is connected, i.e., it is possible * to reach any triangle from any other triangle via a * series of matched edge pairs. * \pre The given edge pairing is in canonical form as described * by Dim2EdgePairing::isCanonical(). Note that all edge pairings * constructed by Dim2EdgePairing::findAllPairings() are of this form. * * @param pairing the specific pairing of triangle edges * that this permutation set will complement. */ Dim2GluingPerms(const Dim2EdgePairing* pairing); }; /*@}*/ // Inline functions for Dim2GluingPerms inline Dim2GluingPerms::Dim2GluingPerms(const Dim2GluingPerms& cloneMe) : NGenericGluingPerms<2>(cloneMe) { } inline Dim2GluingPerms::Dim2GluingPerms(std::istream& in) : NGenericGluingPerms<2>(in) { } inline Dim2GluingPerms::Dim2GluingPerms(const Dim2EdgePairing* pairing) : NGenericGluingPerms<2>(pairing) { } } // namespace regina #endif regina-4.96/engine/census/dim2gluingpermsearcher.cpp000644 000765 000024 00000031474 12377776540 022556 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include "census/dim2gluingpermsearcher.h" #include "dim2/dim2triangulation.h" #include "utilities/memutils.h" namespace regina { const char Dim2GluingPermSearcher::dataTag_ = 'g'; Dim2GluingPermSearcher::Dim2GluingPermSearcher( const Dim2EdgePairing* pairing, const Dim2EdgePairing::IsoList* autos, bool orientableOnly, UseDim2GluingPerms use, void* useArgs) : Dim2GluingPerms(pairing), autos_(autos), autosNew(autos == 0), orientableOnly_(orientableOnly), use_(use), useArgs_(useArgs), started(false), orientation(new int[pairing->size()]) { // Generate the list of edge pairing automorphisms if necessary. // This will require us to remove the const for a wee moment. if (autosNew) { const_cast(this)->autos_ = new Dim2EdgePairing::IsoList(); pairing->findAutomorphisms( const_cast(*autos_)); } // Initialise arrays. unsigned nTris = size(); std::fill(orientation, orientation + nTris, 0); std::fill(permIndices_, permIndices_ + nTris* 3, -1); // Just fill the order[] array in a default left-to-right fashion. // Subclasses can rearrange things if they choose. order = new Dim2TriangleEdge[(nTris * 3) / 2]; orderElt = orderSize = 0; Dim2TriangleEdge edge, adj; for (edge.setFirst(); ! edge.isPastEnd(nTris, true); edge++) if (! pairing->isUnmatched(edge)) if (edge < pairing->dest(edge)) order[orderSize++] = edge; } Dim2GluingPermSearcher::~Dim2GluingPermSearcher() { delete[] orientation; delete[] order; if (autosNew) { // We made them, so we'd better remove the const again and // delete them. Dim2EdgePairing::IsoList* autos = const_cast(autos_); std::for_each(autos->begin(), autos->end(), FuncDelete()); delete autos; } } Dim2GluingPermSearcher* Dim2GluingPermSearcher::bestSearcher( const Dim2EdgePairing* pairing, const Dim2EdgePairing::IsoList* autos, bool orientableOnly, UseDim2GluingPerms use, void* useArgs) { // We only have one algorithm for now. return new Dim2GluingPermSearcher(pairing, autos, orientableOnly, use, useArgs); } void Dim2GluingPermSearcher::findAllPerms(const Dim2EdgePairing* pairing, const Dim2EdgePairing::IsoList* autos, bool orientableOnly, UseDim2GluingPerms use, void* useArgs) { Dim2GluingPermSearcher* searcher = bestSearcher(pairing, autos, orientableOnly, use, useArgs); searcher->runSearch(); delete searcher; } void Dim2GluingPermSearcher::runSearch(long maxDepth) { // In this generation algorithm, each orientation is simply +/-1. unsigned nTriangles = size(); if (maxDepth < 0) { // Larger than we will ever see (and in fact grossly so). maxDepth = nTriangles * 3 + 1; } if (! started) { // Search initialisation. started = true; // Do we in fact have no permutation at all to choose? if (maxDepth == 0 || pairing_->dest(0, 0).isBoundary(nTriangles)) { use_(this, useArgs_); use_(0, useArgs_); return; } orderElt = 0; orientation[0] = 1; } // Is it a partial search that has already finished? if (orderElt == orderSize) { if (isCanonical()) use_(this, useArgs_); use_(0, useArgs_); return; } // ---------- Selecting the individual gluing permutations ---------- int minOrder = orderElt; int maxOrder = orderElt + maxDepth; Dim2TriangleEdge edge, adj; while (orderElt >= minOrder) { edge = order[orderElt]; adj = (*pairing_)[edge]; // TODO: Check for cancellation. // Move to the next permutation. // Be sure to preserve the orientation of the permutation if necessary. if ((! orientableOnly_) || adj.facet == 0) permIndex(edge)++; else permIndex(edge) += 2; // Are we out of ideas for this edge? if (permIndex(edge) >= 2) { // Yep. Head back down to the previous edge. permIndex(edge) = -1; permIndex(adj) = -1; orderElt--; continue; } // We are sitting on a new permutation to try. permIndex(adj) = permIndex(edge); // S2 elements are their own inverses. // Fix the orientation if appropriate. if (adj.facet == 0 && orientableOnly_) { // It's the first time we've hit this triangle. if ((permIndex(edge) + (edge.facet == 2 ? 0 : 1) + (adj.facet == 2 ? 0 : 1)) % 2 == 0) orientation[adj.simp] = -orientation[edge.simp]; else orientation[adj.simp] = orientation[edge.simp]; } // Move on to the next edge. orderElt++; // If we're at the end, try the solution and step back. if (orderElt == orderSize) { // We in fact have an entire triangulation. // Run through the automorphisms and check whether our // permutations are in canonical form. if (isCanonical()) use_(this, useArgs_); // Back to the previous face. orderElt--; } else { // Not a full triangulation; just one level deeper. // We've moved onto a new edge. // Be sure to get the orientation right. edge = order[orderElt]; if (orientableOnly_ && pairing_->dest(edge).facet > 0) { // permIndex(edge) will be set to -1 or -2 as appropriate. adj = (*pairing_)[edge]; if (orientation[edge.simp] == orientation[adj.simp]) permIndex(edge) = 1; else permIndex(edge) = 0; if ((edge.facet == 2 ? 0 : 1) + (adj.facet == 2 ? 0 : 1) == 1) permIndex(edge) = (permIndex(edge) + 1) % 2; permIndex(edge) -= 2; } if (orderElt == maxOrder) { // We haven't found an entire triangulation, but we've // gone as far as we need to. // Process it, then step back. use_(this, useArgs_); // Back to the previous edge. permIndex(edge) = -1; orderElt--; } } } // And the search is over. use_(0, useArgs_); } void Dim2GluingPermSearcher::dumpTaggedData(std::ostream& out) const { out << dataTag() << std::endl; dumpData(out); } Dim2GluingPermSearcher* Dim2GluingPermSearcher::readTaggedData(std::istream& in, UseDim2GluingPerms use, void* useArgs) { // Read the class marker. char c; in >> c; if (in.eof()) return 0; Dim2GluingPermSearcher* ans; if (c == Dim2GluingPermSearcher::dataTag_) ans = new Dim2GluingPermSearcher(in, use, useArgs); else return 0; if (ans->inputError()) { delete ans; return 0; } return ans; } void Dim2GluingPermSearcher::dumpData(std::ostream& out) const { Dim2GluingPerms::dumpData(out); out << (orientableOnly_ ? 'o' : '.'); out << (started ? 's' : '.'); out << std::endl; int nTris = size(); int i; for (i = 0; i < nTris; i++) { if (i) out << ' '; out << orientation[i]; } out << std::endl; out << orderElt << ' ' << orderSize << std::endl; for (i = 0; i < orderSize; i++) { if (i) out << ' '; out << order[i].simp << ' ' << order[i].facet; } out << std::endl; } Dim2GluingPermSearcher::Dim2GluingPermSearcher(std::istream& in, UseDim2GluingPerms use, void* useArgs) : Dim2GluingPerms(in), autos_(0), autosNew(false), use_(use), useArgs_(useArgs), orientation(0), order(0), orderSize(0), orderElt(0) { if (inputError_) return; // Recontruct the face pairing automorphisms. const_cast(this)->autos_ = new Dim2EdgePairing::IsoList(); pairing_->findAutomorphisms(const_cast(*autos_)); autosNew = true; // Keep reading. char c; in >> c; if (c == 'o') orientableOnly_ = true; else if (c == '.') orientableOnly_ = false; else { inputError_ = true; return; } in >> c; if (c == 's') started = true; else if (c == '.') started = false; else { inputError_ = true; return; } int nTris = pairing_->size(); int t; orientation = new int[nTris]; for (t = 0; t < nTris; t++) in >> orientation[t]; order = new Dim2TriangleEdge[(nTris * 3) / 2]; in >> orderElt >> orderSize; for (t = 0; t < orderSize; t++) { in >> order[t].simp >> order[t].facet; if (order[t].simp >= nTris || order[t].simp < 0 || order[t].facet >= 3 || order[t].facet < 0) { inputError_ = true; return; } } // Did we hit an unexpected EOF? if (in.eof()) inputError_ = true; } bool Dim2GluingPermSearcher::isCanonical() const { Dim2TriangleEdge edge, edgeDest, edgeImage; int ordering; for (Dim2EdgePairing::IsoList::const_iterator it = autos_->begin(); it != autos_->end(); it++) { // Compare the current set of gluing permutations with its // preimage under each edge pairing automorphism, to see whether // our current permutation set is closest to canonical form. for (edge.setFirst(); edge.simp < static_cast(pairing_->size()); edge++) { edgeDest = pairing_->dest(edge); if (pairing_->isUnmatched(edge) || edgeDest < edge) continue; edgeImage = (**it)[edge]; ordering = gluingPerm(edge).compareWith( (*it)->edgePerm(edgeDest.simp).inverse() * gluingPerm(edgeImage) * (*it)->edgePerm(edge.simp)); if (ordering < 0) { // This permutation set is closer. break; } else if (ordering > 0) { // The transformed permutation set is closer. return false; } // So far it's an automorphism of gluing permutations also. // Keep running through edges. } // Nothing broke with this automorphism. On to the next one. } // Nothing broke at all. return true; } } // namespace regina regina-4.96/engine/census/dim2gluingpermsearcher.h000644 000765 000024 00000047761 12377774651 022232 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file census/dim2gluingpermsearcher.h * \brief Supports searching through all possible sets of triangle * gluing permutations for a given triangle edge pairing. */ #ifndef __DIM2GLUINGPERMSEARCHER_H #ifndef __DOXYGEN #define __DIM2GLUINGPERMSEARCHER_H #endif #include "regina-core.h" #include "census/dim2gluingperms.h" namespace regina { /** * \weakgroup census * @{ */ class Dim2GluingPermSearcher; /** * A routine used to do arbitrary processing upon a particular set of * triangle gluing permutations. Such routines are used to process * permutation sets found when running Dim2GluingPermSearcher::findAllPerms(). * * The first parameter passed will be a set of gluing permutations * (in fact it will be of the subclass Dim2GluingPermSearcher in order to * support partial searches as well as full searches). This set of * gluing permutations must not be deallocated by this routine, since it * may be used again later by the caller. The second parameter may contain * arbitrary data as passed to either Dim2GluingPerms::findAllPerms() or * the Dim2GluingPermSearcher class constructor. * * Note that the first parameter passed might be \c null to signal that * gluing permutation generation has finished. */ typedef void (*UseDim2GluingPerms)(const Dim2GluingPermSearcher*, void*); /** * A utility class for searching through all possible gluing permutation * sets that correspond to a given triangle edge pairing. In the future, * there may be subclasses of Dim2GluingPermSearcher that correspond to * specialised search algorithms for use in certain scenarios. * The main class Dim2GluingPermSearcher offers a default search * algorithm that may be used in a general context. * * The simplest way of performing a search through all possible gluing * permutations is by calling the static method findAllPerms(). This will * examine the search parameters and ensure that the best possible algorithm * is used. For finer control over the program flow, the static method * bestSearcher() can be used to create a search manager of the most * suitable class and then runSearch() can be called on this object directly. * For absolute control, a specific algorithm can be forced by explicitly * constructing an object of the corresponding class (and again * calling runSearch() on that object directly). * * Note that this class derives from Dim2GluingPerms. The search will * involve building and repeatedly modifying the inherited Dim2GluingPerms * data in-place. * * \ifacespython Not present. */ class REGINA_API Dim2GluingPermSearcher : public Dim2GluingPerms { public: static const char dataTag_; /**< A character used to identify this class when reading and writing tagged data in text format. */ protected: const Dim2EdgePairing::IsoList* autos_; /**< The set of isomorphisms that define equivalence of gluing permutation sets. Generally this is the set of all automorphisms of the underlying edge pairing. */ bool autosNew; /**< Did we create the isomorphism list autos_ ourselves (in which case we must destroy it also)? */ bool orientableOnly_; /**< Are we only searching for gluing permutations that correspond to orientable triangulations? */ UseDim2GluingPerms use_; /**< A routine to call each time a gluing permutation set is found during the search. */ void* useArgs_; /**< Additional user-supplied data to be passed as the second argument to the \a use_ routine. */ bool started; /**< Has the search started yet? This helps distinguish between a new search and the resumption of a partially completed search. */ int* orientation; /**< Keeps track of the orientation of each triangle in the underlying triangulation. Orientation is positive/negative, or 0 if unknown. Note that in some algorithms the orientation is simply +/-1, and in some algorithms the orientation counts forwards or backwards from 0 according to how many times the orientation has been set or verified. */ protected: Dim2TriangleEdge* order; /**< Describes the order in which gluing permutations are assigned to edges. Specifically, this order is order[0], order[1], ..., order[orderSize-1]. Note that each element of this array corresponds to a single edge of the underlying edge pairing graph, which in turn represents a triangle edge and its image under the given edge pairing. The specific triangle edge stored in this array for each edge of the underlying edge pairing graph will be the smaller of the two identified triangle edges (unless otherwise specified by a subclass that uses a specialised search algorithm. */ int orderSize; /**< The total number of edges in the edge pairing graph, i.e., the number of elements of interest in the order[] array. */ int orderElt; /**< Marks which element of order[] we are currently examining at this stage of the search. */ public: /** * Initialises a new search for gluing permutation sets. The * search is started by calling runSearch(). Note that the * static method findAllPerms() handles both construction and * searching, and is the preferred entry point for end users. * * The arguments to this constructor describe the search * parameters in detail, as well as what should be done with * each gluing permutation set that is found. * * \pre The given edge pairing is connected, i.e., it is possible * to reach any triangle from any other triangle via a * series of matched edge pairs. * \pre The given edge pairing is in canonical form as described * by Dim2EdgePairing::isCanonical(). Note that all edge pairings * constructed by Dim2EdgePairing::findAllPairings() are of this form. * * @param pairing the specific pairing of triangle edges * that the generated permutation sets will complement. * @param autos the collection of isomorphisms that define equivalence * of permutation sets. These are used by runSearch(), which produces * each permutation set precisely once up to equivalence. These * isomorphisms must all be automorphisms of the given edge pairing, * and will generally be the set of all such automorphisms. This * parameter may be 0, in which case the set of all automorphisms * of the given edge pairing will be generated and used. * @param orientableOnly \c true if only gluing permutations * corresponding to orientable triangulations should be * generated, or \c false if no such restriction should be imposed. * @param use the function to call upon each permutation set that * is found. The first parameter passed to this function will be * a gluing permutation set. The second parameter will be * parameter \a useArgs as was passed to this routine. * @param useArgs the pointer to pass as the final parameter for * the function \a use which will be called upon each permutation * set found. */ Dim2GluingPermSearcher(const Dim2EdgePairing* pairing, const Dim2EdgePairing::IsoList* autos, bool orientableOnly, UseDim2GluingPerms use, void* useArgs = 0); /** * Initialises a new search manager based on data read from the * given input stream. This may be a new search or a partially * completed search. * * This routine reads data in the format written by dumpData(). * If you wish to read data whose precise class is unknown, * consider using dumpTaggedData() and readTaggedData() instead. * * If the data found in the input stream is invalid or incorrectly * formatted, the routine inputError() will return \c true but * the contents of this object will be otherwise undefined. * * \warning The data format is liable to change between Regina * releases. Data in this format should be used on a short-term * temporary basis only. * * @param in the input stream from which to read. * @param use as for the main Dim2GluingPermSearcher constructor. * @param useArgs as for the main Dim2GluingPermSearcher constructor. */ Dim2GluingPermSearcher(std::istream& in, UseDim2GluingPerms use, void* useArgs = 0); /** * Destroys this search manager and all supporting data * structures. */ virtual ~Dim2GluingPermSearcher(); /** * Generates all possible gluing permutation sets that satisfy * the current search criteria. The search criteria are * specified in the class constructor, or through the static * method findAllPerms(). * * Each set of gluing permutations will be produced precisely * once up to equivalence, where equivalence is defined by the * given set of automorphisms of the given edge pairing. * * For each permutation set that is generated, routine \a use_ (as * passed to the class constructor) will be called with that * permutation set as an argument. * * Once the generation of permutation sets has finished, routine * \a use_ will be called once more, this time with \c null as its * first (permutation set) argument. * * Subclasses corresponding to more specialised search criteria * should override this routine to use a better optimised algorithm * where possible. * * It is possible to run only a partial search, branching to a * given depth but no further. In this case, rather than * producing complete gluing permutation sets, the search will * produce a series of partially-complete Dim2GluingPermSearcher * objects. These partial searches may then be restarted by * calling runSearch() once more (usually after being frozen or * passed on to a different processor). If necessary, the \a use_ * routine may call completePermSet() to distinguish between * a complete set of gluing permutations and a partial search state. * * Note that a restarted search will never drop below its * initial depth. That is, calling runSearch() with a fixed * depth can be used to subdivide the overall search space into * many branches, and then calling runSearch() on each resulting * partial search will complete each of these branches without overlap. * * \todo \feature Allow cancellation of permutation set generation. * * @param maxDepth the depth of the partial search to run, or a * negative number if a full search should be run (the default). */ virtual void runSearch(long maxDepth = -1); /** * Determines whether this search manager holds a complete * gluing permutation set or just a partially completed search * state. * * This may assist the \a use_ routine when running partial * depth-based searches. See runSearch() for further details. * * @return \c true if a complete gluing permutation set is held, * or \c false otherwise. */ bool completePermSet() const; /** * Dumps all internal data in a plain text format, along with a * marker to signify which precise class the data belongs to. * This routine can be used with readTaggedData() to transport * objects from place to place whose precise class is unknown. * * \warning The data format is liable to change between Regina * releases. Data in this format should be used on a short-term * temporary basis only. * * @param out the output stream to which the data should be * written. */ void dumpTaggedData(std::ostream& out) const; // Overridden methods: virtual void dumpData(std::ostream& out) const; /** * The main entry routine for running a search for all gluing * permutation sets that complement a given edge pairing. * * This routine examines the search parameters, chooses the best * possible search algorithm, constructs an object of the * corresponding subclass of Dim2GluingPermSearcher and then calls * runSearch(). * * See the Dim2GluingPermSearcher constructor for documentation on * the arguments to this routine. See the runSearch() method * for documentation on how the search runs and returns its * results. * * \pre The given edge pairing is connected, i.e., it is possible * to reach any triangle from any other triangle via a * series of matched edge pairs. * \pre The given edge pairing is in canonical form as described * by Dim2EdgePairing::isCanonical(). Note that all edge pairings * constructed by Dim2EdgePairing::findAllPairings() are of this form. */ static void findAllPerms(const Dim2EdgePairing* pairing, const Dim2EdgePairing::IsoList* autos, bool orientableOnly, UseDim2GluingPerms use, void* useArgs = 0); /** * Constructs a search manager of the best possible class for the * given search parameters. Different subclasses of * Dim2GluingPermSearcher provide optimised search algorithms for * different types of search. * * Calling this routine and then calling runSearch() on the * result has the same effect as the all-in-one routine * findAllPerms(). Unless you have specialised requirements * (such as partial searching), you are probably better calling * findAllPerms() instead. * * The resulting object is newly created, and must be destroyed * by the caller of this routine. * * See the Dim2GluingPermSearcher constructor for documentation on * the arguments to this routine. * * \pre The given edge pairing is connected, i.e., it is possible * to reach any triangle from any other triangle via a * series of matched edge pairs. * \pre The given edge pairing is in canonical form as described * by Dim2EdgePairing::isCanonical(). Note that all edge pairings * constructed by Dim2EdgePairing::findAllPairings() are of this form. * * @return the newly created search manager. */ static Dim2GluingPermSearcher* bestSearcher( const Dim2EdgePairing* pairing, const Dim2EdgePairing::IsoList* autos, bool orientableOnly, UseDim2GluingPerms use, void* useArgs = 0); /** * Creates a new search manager based on tagged data read from * the given input stream. This may be a new search or a * partially completed search. * * The tagged data should be in the format written by * dumpTaggedData(). The precise class of the search manager * will be determined from the tagged data, and does not need to * be known in advance. This is in contrast to dumpData() and * the input stream constructors, where the class of the data being * read must be known at compile time. * * If the data found in the input stream is invalid or * incorrectly formatted, a null pointer will be returned. * Otherwise a newly constructed search manager will be returned, * and it is the responsibility of the caller of this routine to * destroy it after use. * * The arguments \a use and \a useArgs are the same as for the * Dim2GluingPermSearcher constructor. * * \warning The data format is liable to change between Regina * releases. Data in this format should be used on a short-term * temporary basis only. * * @param in the input stream from which to read. */ static Dim2GluingPermSearcher* readTaggedData(std::istream& in, UseDim2GluingPerms use, void* useArgs = 0); protected: /** * Compares the current set of gluing permutations with its * preimage under each automorphism of the underlying edge pairing, * in order to see whether the current set is in canonical form * (i.e., is lexicographically smallest). * * @return \c true if the current set is in canonical form, * or \c false otherwise. */ bool isCanonical() const; /** * Returns the character used to identify this class when * storing tagged data in text format. * * @return the class tag. */ virtual char dataTag() const; }; /*@}*/ // Inline functions for Dim2GluingPermSearcher inline bool Dim2GluingPermSearcher::completePermSet() const { return (orderElt == orderSize); } inline char Dim2GluingPermSearcher::dataTag() const { return Dim2GluingPermSearcher::dataTag_; } } // namespace regina #endif regina-4.96/engine/census/euler.cpp000644 000765 000024 00000130175 12377776541 017227 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "census/ngluingpermsearcher.h" #include "triangulation/nedge.h" #include "triangulation/nfacepair.h" #include "triangulation/ntriangulation.h" #include "utilities/boostutils.h" #include "utilities/memutils.h" namespace regina { const char NEulerSearcher::VLINK_CLOSED = 1; const char NEulerSearcher::VLINK_BAD_EULER = 2; const int NEulerSearcher::vertexLinkNextFace[4][4] = { { -1, 2, 3, 1}, { 3, -1, 0, 2}, { 1, 3, -1, 0}, { 1, 2, 0, -1} }; const int NEulerSearcher::vertexLinkPrevFace[4][4] = { { -1, 3, 1, 2}, { 2, -1, 3, 0}, { 3, 0, -1, 1}, { 2, 0, 1, -1} }; const char NEulerSearcher::dataTag_ = 'e'; void NEulerSearcher::TetVertexState::dumpData(std::ostream& out) const { // Be careful with twistUp, which is a char but which should be // written as an int. out << parent << ' ' << rank << ' ' << bdry << ' ' << euler << ' ' << (twistUp ? 1 : 0) << ' ' << (hadEqualRank ? 1 : 0) << ' ' << static_cast(bdryEdges) << ' ' << bdryNext[0] << ' ' << bdryNext[1] << ' ' << static_cast(bdryTwist[0]) << ' ' << static_cast(bdryTwist[1]) << ' ' << bdryNextOld[0] << ' ' << bdryNextOld[1] << ' ' << static_cast(bdryTwistOld[0]) << ' ' << static_cast(bdryTwistOld[1]); } bool NEulerSearcher::TetVertexState::readData(std::istream& in, unsigned long nStates) { in >> parent >> rank >> bdry >> euler; // twistUp is a char, but we need to read it as an int. int twist; in >> twist; twistUp = twist; // hadEqualRank is a bool, but we need to read it as an int. int bRank; in >> bRank; hadEqualRank = bRank; // More chars to ints coming. int bVal; in >> bVal; bdryEdges = bVal; in >> bdryNext[0] >> bdryNext[1]; in >> bVal; bdryTwist[0] = bVal; in >> bVal; bdryTwist[1] = bVal; in >> bdryNextOld[0] >> bdryNextOld[1]; in >> bVal; bdryTwistOld[0] = bVal; in >> bVal; bdryTwistOld[1] = bVal; if (parent < -1 || parent >= static_cast(nStates)) return false; if (rank >= nStates) return false; if (bdry > 3 * nStates) return false; if (euler > 2) return false; if (twist != 1 && twist != 0) return false; if (bRank != 1 && bRank != 0) return false; if (bdryEdges > 3) /* Never < 0 since this is unsigned. */ return false; if (bdryNext[0] < 0 || bdryNext[0] >= static_cast(nStates)) return false; if (bdryNext[1] < 0 || bdryNext[1] >= static_cast(nStates)) return false; if (bdryNextOld[0] < -1 || bdryNext[0] >= static_cast(nStates)) return false; if (bdryNextOld[1] < -1 || bdryNextOld[1] >= static_cast(nStates)) return false; if (bdryTwist[0] < 0 || bdryTwist[0] > 1) return false; if (bdryTwist[1] < 0 || bdryTwist[1] > 1) return false; if (bdryTwistOld[0] < 0 || bdryTwistOld[0] > 1) return false; if (bdryTwistOld[1] < 0 || bdryTwistOld[1] > 1) return false; return true; } void NEulerSearcher::TetEdgeState::dumpData(std::ostream& out, unsigned nTets) const { // Be careful with twistUp, which is a char but which should be // written as an int. out << parent << ' ' << rank << ' ' << size << ' ' << (bounded ? 1 : 0) << ' ' << (twistUp ? 1 : 0) << ' ' << (hadEqualRank ? 1 : 0) << ' '; unsigned i; for (i = 0; i < nTets * 4 && i < 64; ++i) out << char(facesPos.get(i) + '0'); out << ' '; for (i = 0; i < nTets * 4 && i < 64; ++i) out << char(facesNeg.get(i) + '0'); } bool NEulerSearcher::TetEdgeState::readData(std::istream& in, unsigned nTets) { in >> parent >> rank >> size; // bounded is a bool, but we need to read it as an int. int bBounded; in >> bBounded; bounded = bBounded; // twistUp is a char, but we need to read it as an int. int twist; in >> twist; twistUp = twist; // hadEqualRank is a bool, but we need to read it as an int. int bRank; in >> bRank; hadEqualRank = bRank; char cFaces; bool facesBroken = false; unsigned i; for (i = 0; i < nTets * 4 && i < 64; ++i) { in >> cFaces; if (cFaces >= '0' && cFaces <= '3') facesPos.set(i, cFaces - '0'); else facesBroken = true; } for (i = 0; i < nTets * 4 && i < 64; ++i) { in >> cFaces; if (cFaces >= '0' && cFaces <= '3') facesNeg.set(i, cFaces - '0'); else facesBroken = true; } if (parent < -1 || parent >= static_cast(6 * nTets)) return false; if (rank >= 6 * nTets) return false; if (size >= 6 * nTets) return false; if (bBounded != 1 && bBounded != 0) return false; if (twist != 1 && twist != 0) return false; if (bRank != 1 && bRank != 0) return false; if (facesBroken) return false; return true; } NEulerSearcher::NEulerSearcher(int useEuler, const NFacePairing* pairing, const NFacePairing::IsoList* autos, bool orientableOnly, int whichPurge, UseGluingPerms use, void* useArgs) : NGluingPermSearcher(pairing, autos, orientableOnly, true /* finiteOnly */, whichPurge, use, useArgs), euler_(useEuler) { // Initialise the internal arrays to accurately reflect the underlying // face pairing. unsigned nTets = getNumberOfTetrahedra(); // ---------- Tracking of vertex / edge equivalence classes ---------- unsigned i; nVertexClasses = nTets * 4; vertexState = new TetVertexState[nTets * 4]; vertexStateChanged = new int[nTets * 8]; std::fill(vertexStateChanged, vertexStateChanged + nTets * 8, static_cast(VLINK_JOIN_INIT)); for (i = 0; i < nTets * 4; i++) { vertexState[i].bdryEdges = 3; vertexState[i].bdryNext[0] = vertexState[i].bdryNext[1] = i; vertexState[i].bdryTwist[0] = vertexState[i].bdryTwist[1] = 0; // Initialise the backup members also so we're not writing // uninitialised data via dumpData(). vertexState[i].bdryNextOld[0] = vertexState[i].bdryNextOld[1] = -1; vertexState[i].bdryTwistOld[0] = vertexState[i].bdryTwistOld[1] = 0; } nEdgeClasses = nTets * 6; edgeState = new TetEdgeState[nTets * 6]; edgeStateChanged = new int[nTets * 8]; std::fill(edgeStateChanged, edgeStateChanged + nTets * 8, -1); // Since NQitmaskLen64 only supports 64 faces, only work with // the first 16 tetrahedra. If n > 16, this just weakens the // optimisation; however, this is no great loss since for n > 16 the // census code is at present infeasibly slow anyway. for (i = 0; i < nTets && i < 16; ++i) { /* 01 on +012, +013 */ edgeState[6 * i ].facesPos.set(4 * i + 3, 1); edgeState[6 * i ].facesPos.set(4 * i + 2, 1); /* 02 on -012 +023 */ edgeState[6 * i + 1].facesNeg.set(4 * i + 3, 1); edgeState[6 * i + 1].facesPos.set(4 * i + 1, 1); /* 03 on -013, -023 */ edgeState[6 * i + 2].facesNeg.set(4 * i + 2, 1); edgeState[6 * i + 2].facesNeg.set(4 * i + 1, 1); /* 12 on +012, +123 */ edgeState[6 * i + 3].facesPos.set(4 * i + 3, 1); edgeState[6 * i + 3].facesPos.set(4 * i + 0, 1); /* 13 on +013 -123 */ edgeState[6 * i + 4].facesPos.set(4 * i + 2, 1); edgeState[6 * i + 4].facesNeg.set(4 * i + 0, 1); /* 23 on +023, +123 */ edgeState[6 * i + 5].facesPos.set(4 * i + 1, 1); edgeState[6 * i + 5].facesPos.set(4 * i + 0, 1); } } void NEulerSearcher::runSearch(long maxDepth) { unsigned nTets = getNumberOfTetrahedra(); if (maxDepth < 0) { // Larger than we will ever see (and in fact grossly so). maxDepth = nTets * 4 + 1; } if (! started) { // Search initialisation. started = true; // Do we in fact have no permutation at all to choose? if (maxDepth == 0 || pairing_->dest(0, 0).isBoundary(nTets)) { use_(this, useArgs_); use_(0, useArgs_); return; } orderElt = 0; orientation[0] = 1; } // Is it a partial search that has already finished? if (orderElt == orderSize) { if (isCanonical()) use_(this, useArgs_); use_(0, useArgs_); return; } // ---------- Selecting the individual gluing permutations ---------- int minOrder = orderElt; int maxOrder = orderElt + maxDepth; NTetFace face, adj; int mergeResult; while (orderElt >= minOrder) { face = order[orderElt]; adj = (*pairing_)[face]; // TODO (long-term): Check for cancellation. // Move to the next permutation. // Be sure to preserve the orientation of the permutation if necessary. if ((! orientableOnly_) || adj.facet == 0) permIndex(face)++; else permIndex(face) += 2; // Are we out of ideas for this face? if (permIndex(face) >= 6) { // Yep. Head back down to the previous face. permIndex(face) = -1; permIndex(adj) = -1; orderElt--; // Pull apart vertex and edge links at the previous level. if (orderElt >= minOrder) { splitVertexClasses(); splitEdgeClasses(); } continue; } // We are sitting on a new permutation to try. permIndex(adj) = NPerm4::invS3[permIndex(face)]; // Merge edge links and run corresponding tests. if (mergeEdgeClasses()) { // We created an invalid edge. splitEdgeClasses(); continue; } // Merge vertex links and run corresponding tests. mergeResult = mergeVertexClasses(); if (mergeResult & VLINK_BAD_EULER) { // Our vertex link can never obtain the correct // Euler characteristic. Stop now. splitVertexClasses(); splitEdgeClasses(); continue; } // Fix the orientation if appropriate. if (adj.facet == 0 && orientableOnly_) { // It's the first time we've hit this tetrahedron. if ((permIndex(face) + (face.facet == 3 ? 0 : 1) + (adj.facet == 3 ? 0 : 1)) % 2 == 0) orientation[adj.simp] = -orientation[face.simp]; else orientation[adj.simp] = orientation[face.simp]; } // Move on to the next face. orderElt++; // If we're at the end, try the solution and step back. if (orderElt == orderSize) { // We in fact have an entire triangulation. // Run through the automorphisms and check whether our // permutations are in canonical form. if (isCanonical()) use_(this, useArgs_); // Back to the previous face. orderElt--; // Pull apart vertex and edge links at the previous level. if (orderElt >= minOrder) { splitVertexClasses(); splitEdgeClasses(); } } else { // Not a full triangulation; just one level deeper. // We've moved onto a new face. // Be sure to get the orientation right. face = order[orderElt]; if (orientableOnly_ && pairing_->dest(face).facet > 0) { // permIndex(face) will be set to -1 or -2 as appropriate. adj = (*pairing_)[face]; if (orientation[face.simp] == orientation[adj.simp]) permIndex(face) = 1; else permIndex(face) = 0; if ((face.facet == 3 ? 0 : 1) + (adj.facet == 3 ? 0 : 1) == 1) permIndex(face) = (permIndex(face) + 1) % 2; permIndex(face) -= 2; } if (orderElt == maxOrder) { // We haven't found an entire triangulation, but we've // gone as far as we need to. // Process it, then step back. use_(this, useArgs_); // Back to the previous face. permIndex(face) = -1; orderElt--; // Pull apart vertex and edge links at the previous level. if (orderElt >= minOrder) { splitVertexClasses(); splitEdgeClasses(); } } } } // And the search is over. // Some extra sanity checking. if (minOrder == 0) { // Our vertex classes had better be 4n standalone vertices. if (nVertexClasses != 4 * nTets) std::cerr << "ERROR: nVertexClasses == " << nVertexClasses << " at end of search!" << std::endl; for (int i = 0; i < static_cast(nTets) * 4; i++) { if (vertexState[i].parent != -1) std::cerr << "ERROR: vertexState[" << i << "].parent == " << vertexState[i].parent << " at end of search!" << std::endl; if (vertexState[i].rank != 0) std::cerr << "ERROR: vertexState[" << i << "].rank == " << vertexState[i].rank << " at end of search!" << std::endl; if (vertexState[i].bdry != 3) std::cerr << "ERROR: vertexState[" << i << "].bdry == " << vertexState[i].bdry << " at end of search!" << std::endl; if (vertexState[i].euler != 2) std::cerr << "ERROR: vertexState[" << i << "].euler == " << vertexState[i].euler << " at end of search!" << std::endl; if (vertexState[i].hadEqualRank) std::cerr << "ERROR: vertexState[" << i << "].hadEqualRank == " "true at end of search!" << std::endl; if (vertexState[i].bdryEdges != 3) std::cerr << "ERROR: vertexState[" << i << "].bdryEdges == " << static_cast(vertexState[i].bdryEdges) << " at end of search!" << std::endl; if (vertexState[i].bdryNext[0] != i) std::cerr << "ERROR: vertexState[" << i << "].bdryNext[0] == " << vertexState[i].bdryNext[0] << " at end of search!" << std::endl; if (vertexState[i].bdryNext[1] != i) std::cerr << "ERROR: vertexState[" << i << "].bdryNext[1] == " << vertexState[i].bdryNext[1] << " at end of search!" << std::endl; if (vertexState[i].bdryTwist[0]) std::cerr << "ERROR: vertexState[" << i << "].bdryTwist == " "true at end of search!" << std::endl; if (vertexState[i].bdryTwist[1]) std::cerr << "ERROR: vertexState[" << i << "].bdryTwist == " "true at end of search!" << std::endl; } for (unsigned i = 0; i < nTets * 8; i++) if (vertexStateChanged[i] != VLINK_JOIN_INIT) std::cerr << "ERROR: vertexStateChanged[" << i << "] == " << vertexStateChanged[i] << " at end of search!" << std::endl; // And our edge classes had better be 6n standalone edges. if (nEdgeClasses != 6 * nTets) std::cerr << "ERROR: nEdgeClasses == " << nEdgeClasses << " at end of search!" << std::endl; for (unsigned i = 0; i < nTets * 6; i++) { if (edgeState[i].parent != -1) std::cerr << "ERROR: edgeState[" << i << "].parent == " << edgeState[i].parent << " at end of search!" << std::endl; if (edgeState[i].rank != 0) std::cerr << "ERROR: edgeState[" << i << "].rank == " << edgeState[i].rank << " at end of search!" << std::endl; if (edgeState[i].size != 1) std::cerr << "ERROR: edgeState[" << i << "].size == " << edgeState[i].size << " at end of search!" << std::endl; if (! edgeState[i].bounded) std::cerr << "ERROR: edgeState[" << i << "].bounded == " "false at end of search!" << std::endl; if (edgeState[i].hadEqualRank) std::cerr << "ERROR: edgeState[" << i << "].hadEqualRank == " "true at end of search!" << std::endl; } for (unsigned i = 0; i < nTets * 8; i++) if (edgeStateChanged[i] != -1) std::cerr << "ERROR: edgeStateChanged[" << i << "] == " << edgeStateChanged[i] << " at end of search!" << std::endl; } use_(0, useArgs_); } void NEulerSearcher::dumpData(std::ostream& out) const { NGluingPermSearcher::dumpData(out); out << euler_ << std::endl; unsigned nTets = getNumberOfTetrahedra(); unsigned i; out << nVertexClasses << std::endl; for (i = 0; i < 4 * nTets; i++) { vertexState[i].dumpData(out); out << std::endl; } for (i = 0; i < 8 * nTets; i++) { if (i) out << ' '; out << vertexStateChanged[i]; } out << std::endl; out << nEdgeClasses << std::endl; for (i = 0; i < 6 * nTets; i++) { edgeState[i].dumpData(out, nTets); out << std::endl; } for (i = 0; i < 8 * nTets; i++) { if (i) out << ' '; out << edgeStateChanged[i]; } out << std::endl; } NEulerSearcher::NEulerSearcher(std::istream& in, UseGluingPerms use, void* useArgs) : NGluingPermSearcher(in, use, useArgs), nVertexClasses(0), vertexState(0), vertexStateChanged(0), nEdgeClasses(0), edgeState(0), edgeStateChanged(0) { if (inputError_) return; in >> euler_; if (euler_ > 2) { inputError_ = true; return; } unsigned nTets = getNumberOfTetrahedra(); unsigned i; in >> nVertexClasses; if (nVertexClasses > 4 * nTets) { inputError_ = true; return; } vertexState = new TetVertexState[4 * nTets]; for (i = 0; i < 4 * nTets; i++) if (! vertexState[i].readData(in, 4 * nTets)) { inputError_ = true; return; } vertexStateChanged = new int[8 * nTets]; for (i = 0; i < 8 * nTets; i++) { in >> vertexStateChanged[i]; if (vertexStateChanged[i] >= 4 * static_cast(nTets)) { inputError_ = true; return; } } in >> nEdgeClasses; if (nEdgeClasses > 6 * nTets) { inputError_ = true; return; } edgeState = new TetEdgeState[6 * nTets]; for (i = 0; i < 6 * nTets; i++) if (! edgeState[i].readData(in, nTets)) { inputError_ = true; return; } edgeStateChanged = new int[8 * nTets]; for (i = 0; i < 8 * nTets; i++) { in >> edgeStateChanged[i]; if (edgeStateChanged[i] < -1 || edgeStateChanged[i] >= 6 * static_cast(nTets)) { inputError_ = true; return; } } // Did we hit an unexpected EOF? if (in.eof()) inputError_ = true; } int NEulerSearcher::mergeVertexClasses() { // Merge all three vertex pairs for the current face. NTetFace face = order[orderElt]; NTetFace adj = (*pairing_)[face]; int retVal = 0; int v, w; int vIdx, wIdx, tmpIdx, nextIdx; unsigned orderIdx; int vRep, wRep; int vNext[2], wNext[2]; char vTwist[2], wTwist[2]; NPerm4 p = gluingPerm(face); char parentTwists, hasTwist, tmpTwist; for (v = 0; v < 4; v++) { if (v == face.facet) continue; w = p[v]; vIdx = v + 4 * face.simp; wIdx = w + 4 * adj.simp; orderIdx = v + 4 * orderElt; // Are the natural 012 representations of the two faces joined // with reversed orientations? // Here we combine the sign of permutation p with the mappings // from 012 to the native tetrahedron vertices, i.e., v <-> 3 and // w <-> 3. hasTwist = (p.sign() < 0 ? 0 : 1); if ((v == 3 && w != 3) || (v != 3 && w == 3)) hasTwist ^= 1; parentTwists = 0; for (vRep = vIdx; vertexState[vRep].parent >= 0; vRep = vertexState[vRep].parent) parentTwists ^= vertexState[vRep].twistUp; for (wRep = wIdx; vertexState[wRep].parent >= 0; wRep = vertexState[wRep].parent) parentTwists ^= vertexState[wRep].twistUp; if (vRep == wRep) { vertexState[vRep].bdry -= 2; // Examine the cycles of boundary components. if (vIdx == wIdx) { // We are folding together two adjacent edges of the // vertex link (possibly with a non-orientable twist). if (hasTwist) { vertexStateChanged[orderIdx] = VLINK_JOIN_TWIST; --vertexState[vRep].euler; } else vertexStateChanged[orderIdx] = VLINK_JOIN_BRIDGE; if (vertexState[vIdx].bdryEdges < 3) { // We are folding together (possibly with a twist) // two edges of a triangle whose third edge is already // joined elsewhere. // Although bdryEdges is 2, we don't bother keeping // a backup in bdryTwistOld[]. This is because // bdryEdges jumps straight from 2 to 0, and the // neighbours in bdryNext[] / bdryTwist[] never get // overwritten. if (vertexState[vIdx].bdryNext[0] == vIdx) { // We are closing off a single boundary of length // two. All good. } else { // Adjust each neighbour to point to the other. vtxBdryJoin(vertexState[vIdx].bdryNext[0], 1 ^ vertexState[vIdx].bdryTwist[0], vertexState[vIdx].bdryNext[1], vertexState[vIdx].bdryTwist[1] ^ vertexState[vIdx].bdryTwist[0]); } } vertexState[vIdx].bdryEdges -= 2; } else { // We are joining two distinct tetrahedron vertices that // already contribute to the same vertex link. if (vertexState[vIdx].bdryEdges == 2) vtxBdryBackup(vIdx); if (vertexState[wIdx].bdryEdges == 2) vtxBdryBackup(wIdx); if (vtxBdryLength1(vIdx)) { if (vtxBdryLength1(wIdx)) { // We are joining together two boundaries of length one. vertexStateChanged[orderIdx] = VLINK_JOIN_HANDLE; vertexState[vRep].euler -= 2; // The join closes off both boundary curves. // No changes to make for the boundary cycles. } else { // We are joining a length one loop at vIdx // with a different, longer boundary curve at wIdx. vertexStateChanged[orderIdx] = VLINK_JOIN_HANDLE; vertexState[vRep].euler -= 2; // Ignore vIdx (which will be closed off), and simply // excise the relevant edge from wIdx. // There is nothing to do here unless wIdx only has one // boundary edge remaining (in which case we know it // joins to some different tetrahedron vertex). if (vertexState[wIdx].bdryEdges == 1) { wNext[0] = vertexState[wIdx].bdryNext[0]; wNext[1] = vertexState[wIdx].bdryNext[1]; wTwist[0] = vertexState[wIdx].bdryTwist[0]; wTwist[1] = vertexState[wIdx].bdryTwist[1]; vtxBdryJoin(wNext[0], 1 ^ wTwist[0], wNext[1], wTwist[0] ^ wTwist[1]); } } } else if (vtxBdryLength1(wIdx)) { // As above, but with the two vertices the other way around. vertexStateChanged[orderIdx] = VLINK_JOIN_HANDLE; vertexState[vRep].euler -= 2; if (vertexState[vIdx].bdryEdges == 1) { vNext[0] = vertexState[vIdx].bdryNext[0]; vNext[1] = vertexState[vIdx].bdryNext[1]; vTwist[0] = vertexState[vIdx].bdryTwist[0]; vTwist[1] = vertexState[vIdx].bdryTwist[1]; vtxBdryJoin(vNext[0], 1 ^ vTwist[0], vNext[1], vTwist[0] ^ vTwist[1]); } } else if (vtxBdryLength2(vIdx, wIdx)) { // We are closing off a single boundary curve of length two. if (hasTwist ^ vertexState[vIdx].bdryTwist[0]) { vertexStateChanged[orderIdx] = VLINK_JOIN_TWIST; --vertexState[vRep].euler; } else vertexStateChanged[orderIdx] = VLINK_JOIN_BRIDGE; } else { vtxBdryNext(vIdx, face.simp, v, face.facet, vNext, vTwist); vtxBdryNext(wIdx, adj.simp, w, adj.facet, wNext, wTwist); if (vNext[0] == wIdx && wNext[1 ^ vTwist[0]] == vIdx) { // We are joining two adjacent edges of the vertex link. // Simply eliminate them. if (hasTwist ^ vTwist[0]) { vertexStateChanged[orderIdx] = VLINK_JOIN_TWIST; --vertexState[vRep].euler; } else vertexStateChanged[orderIdx] = VLINK_JOIN_BRIDGE; vtxBdryJoin(vNext[1], 0 ^ vTwist[1], wNext[0 ^ vTwist[0]], (vTwist[0] ^ wTwist[0 ^ vTwist[0]]) ^ vTwist[1]); } else if (vNext[1] == wIdx && wNext[0 ^ vTwist[1]] == vIdx) { // Again, joining two adjacent edges of the vertex link. if (hasTwist ^ vTwist[1]) { vertexStateChanged[orderIdx] = VLINK_JOIN_TWIST; --vertexState[vRep].euler; } else vertexStateChanged[orderIdx] = VLINK_JOIN_BRIDGE; vtxBdryJoin(vNext[0], 1 ^ vTwist[0], wNext[1 ^ vTwist[1]], (vTwist[1] ^ wTwist[1 ^ vTwist[1]]) ^ vTwist[0]); } else { // See if we are joining two different boundary cycles // together; if so, we have created a new handle in // the vertex link. tmpIdx = vertexState[vIdx].bdryNext[0]; tmpTwist = vertexState[vIdx].bdryTwist[0]; while (tmpIdx != vIdx && tmpIdx != wIdx) { nextIdx = vertexState[tmpIdx]. bdryNext[0 ^ tmpTwist]; tmpTwist ^= vertexState[tmpIdx]. bdryTwist[0 ^ tmpTwist]; tmpIdx = nextIdx; } if (tmpIdx == vIdx) { // Different boundary cycles. vertexStateChanged[orderIdx] = VLINK_JOIN_HANDLE; vertexState[vRep].euler -= 2; } else { // Same boundary cycle. if (hasTwist ^ tmpTwist) { vertexStateChanged[orderIdx] = VLINK_JOIN_TWIST; --vertexState[vRep].euler; } else vertexStateChanged[orderIdx] = VLINK_JOIN_BRIDGE; } vtxBdryJoin(vNext[0], 1 ^ vTwist[0], wNext[1 ^ hasTwist], vTwist[0] ^ (hasTwist ^ wTwist[1 ^ hasTwist])); vtxBdryJoin(vNext[1], 0 ^ vTwist[1], wNext[0 ^ hasTwist], vTwist[1] ^ (hasTwist ^ wTwist[0 ^ hasTwist])); } } vertexState[vIdx].bdryEdges--; vertexState[wIdx].bdryEdges--; } // See what actually happened to the vertex. if (vertexState[vRep].bdry == 0) { retVal |= VLINK_CLOSED; if (vertexState[vRep].euler != euler_) retVal |= VLINK_BAD_EULER; } else if (vertexState[vRep].euler < euler_) retVal |= VLINK_BAD_EULER; } else { // We are joining two distinct vertices together and merging // their vertex links. if (vertexState[vRep].rank < vertexState[wRep].rank) { // Join vRep beneath wRep. vertexState[vRep].parent = wRep; vertexState[vRep].twistUp = hasTwist ^ parentTwists; vertexState[wRep].bdry = vertexState[wRep].bdry + vertexState[vRep].bdry - 2; vertexState[wRep].euler = vertexState[wRep].euler + vertexState[vRep].euler - 2; if (vertexState[wRep].bdry == 0) { retVal |= VLINK_CLOSED; if (vertexState[wRep].euler != euler_) retVal |= VLINK_BAD_EULER; } else if (vertexState[wRep].euler < euler_) retVal |= VLINK_BAD_EULER; vertexStateChanged[orderIdx] = vRep; } else { // Join wRep beneath vRep. vertexState[wRep].parent = vRep; vertexState[wRep].twistUp = hasTwist ^ parentTwists; if (vertexState[vRep].rank == vertexState[wRep].rank) { vertexState[vRep].rank++; vertexState[wRep].hadEqualRank = true; } vertexState[vRep].bdry = vertexState[vRep].bdry + vertexState[wRep].bdry - 2; vertexState[vRep].euler = vertexState[vRep].euler + vertexState[wRep].euler - 2; if (vertexState[vRep].bdry == 0) { retVal |= VLINK_CLOSED; if (vertexState[vRep].euler != euler_) retVal |= VLINK_BAD_EULER; } else if (vertexState[vRep].euler < euler_) retVal |= VLINK_BAD_EULER; vertexStateChanged[orderIdx] = wRep; } nVertexClasses--; // Adjust the cycles of boundary components. if (vertexState[vIdx].bdryEdges == 2) vtxBdryBackup(vIdx); if (vertexState[wIdx].bdryEdges == 2) vtxBdryBackup(wIdx); if (vtxBdryLength1(vIdx)) { if (vtxBdryLength1(wIdx)) { // Both vIdx and wIdx form entire boundary components of // length one; these are joined together and the vertex // link is closed off. // No changes to make for the boundary cycles. } else { // Here vIdx forms a boundary component of length one, // and wIdx does not. Ignore vIdx, and simply excise the // relevant edge from wIdx. // There is nothing to do here unless wIdx only has one // boundary edge remaining (in which case we know it // joins to some different tetrahedron vertex). if (vertexState[wIdx].bdryEdges == 1) { wNext[0] = vertexState[wIdx].bdryNext[0]; wNext[1] = vertexState[wIdx].bdryNext[1]; wTwist[0] = vertexState[wIdx].bdryTwist[0]; wTwist[1] = vertexState[wIdx].bdryTwist[1]; vtxBdryJoin(wNext[0], 1 ^ wTwist[0], wNext[1], wTwist[0] ^ wTwist[1]); } } } else if (vtxBdryLength1(wIdx)) { // As above, but with the two vertices the other way around. if (vertexState[vIdx].bdryEdges == 1) { vNext[0] = vertexState[vIdx].bdryNext[0]; vNext[1] = vertexState[vIdx].bdryNext[1]; vTwist[0] = vertexState[vIdx].bdryTwist[0]; vTwist[1] = vertexState[vIdx].bdryTwist[1]; vtxBdryJoin(vNext[0], 1 ^ vTwist[0], vNext[1], vTwist[0] ^ vTwist[1]); } } else { // Each vertex belongs to a boundary component of length // at least two. Merge the components together. vtxBdryNext(vIdx, face.simp, v, face.facet, vNext, vTwist); vtxBdryNext(wIdx, adj.simp, w, adj.facet, wNext, wTwist); vtxBdryJoin(vNext[0], 1 ^ vTwist[0], wNext[1 ^ hasTwist], vTwist[0] ^ (hasTwist ^ wTwist[1 ^ hasTwist])); vtxBdryJoin(vNext[1], 0 ^ vTwist[1], wNext[0 ^ hasTwist], vTwist[1] ^ (hasTwist ^ wTwist[0 ^ hasTwist])); } vertexState[vIdx].bdryEdges--; vertexState[wIdx].bdryEdges--; } } return retVal; } void NEulerSearcher::splitVertexClasses() { // Split all three vertex pairs for the current face. NTetFace face = order[orderElt]; NTetFace adj = (*pairing_)[face]; int v, w; int vIdx, wIdx; unsigned orderIdx; int rep, subRep; NPerm4 p = gluingPerm(face); // Do everything in reverse. This includes the loop over vertices. for (v = 3; v >= 0; v--) { if (v == face.facet) continue; w = p[v]; vIdx = v + 4 * face.simp; wIdx = w + 4 * adj.simp; orderIdx = v + 4 * orderElt; if (vertexStateChanged[orderIdx] < 0) { for (rep = vIdx; vertexState[rep].parent >= 0; rep = vertexState[rep].parent) ; vertexState[rep].bdry += 2; if (vertexStateChanged[orderIdx] == VLINK_JOIN_HANDLE) vertexState[rep].euler += 2; else if (vertexStateChanged[orderIdx] == VLINK_JOIN_TWIST) ++vertexState[rep].euler; } else { subRep = vertexStateChanged[orderIdx]; rep = vertexState[subRep].parent; vertexState[subRep].parent = -1; if (vertexState[subRep].hadEqualRank) { vertexState[subRep].hadEqualRank = false; vertexState[rep].rank--; } vertexState[rep].bdry = vertexState[rep].bdry + 2 - vertexState[subRep].bdry; vertexState[rep].euler = vertexState[rep].euler + 2 - vertexState[subRep].euler; nVertexClasses++; } vertexStateChanged[orderIdx] = VLINK_JOIN_INIT; // Restore cycles of boundary components. if (vIdx == wIdx) { vertexState[vIdx].bdryEdges += 2; // Adjust neighbours to point back to vIdx if required. if (vertexState[vIdx].bdryEdges == 2) vtxBdryFixAdj(vIdx); } else { vertexState[wIdx].bdryEdges++; vertexState[vIdx].bdryEdges++; switch (vertexState[wIdx].bdryEdges) { case 3: vertexState[wIdx].bdryNext[0] = vertexState[wIdx].bdryNext[1] = wIdx; vertexState[wIdx].bdryTwist[0] = vertexState[wIdx].bdryTwist[1] = 0; break; case 2: vtxBdryRestore(wIdx); // Fall through to the next case, so we can // adjust the neighbours. case 1: // Nothing was changed for wIdx during the merge, // so there is nothing there to restore. // Adjust neighbours to point back to wIdx. vtxBdryFixAdj(wIdx); } switch (vertexState[vIdx].bdryEdges) { case 3: vertexState[vIdx].bdryNext[0] = vertexState[vIdx].bdryNext[1] = vIdx; vertexState[vIdx].bdryTwist[0] = vertexState[vIdx].bdryTwist[1] = 0; break; case 2: vtxBdryRestore(vIdx); // Fall through to the next case, so we can // adjust the neighbours. case 1: // Nothing was changed for vIdx during the merge, // so there is nothing there to restore. // Adjust neighbours to point back to vIdx. vtxBdryFixAdj(vIdx); } } } } bool NEulerSearcher::mergeEdgeClasses() { NTetFace face = order[orderElt]; NTetFace adj = (*pairing_)[face]; bool retVal = false; NPerm4 p = gluingPerm(face); int v1, w1, v2, w2; int e, f; int orderIdx; int eRep, fRep; v1 = face.facet; w1 = p[v1]; char parentTwists, hasTwist; for (v2 = 0; v2 < 4; v2++) { if (v2 == v1) continue; w2 = p[v2]; // Look at the edge opposite v1-v2. e = 5 - NEdge::edgeNumber[v1][v2]; f = 5 - NEdge::edgeNumber[w1][w2]; orderIdx = v2 + 4 * orderElt; // We declare the natural orientation of an edge to be smaller // vertex to larger vertex. hasTwist = (p[NEdge::edgeVertex[e][0]] > p[NEdge::edgeVertex[e][1]] ? 1 : 0); parentTwists = 0; eRep = findEdgeClass(e + 6 * face.simp, parentTwists); fRep = findEdgeClass(f + 6 * adj.simp, parentTwists); if (eRep == fRep) { edgeState[eRep].bounded = false; if (hasTwist ^ parentTwists) retVal = true; edgeStateChanged[orderIdx] = -1; } else { if (edgeState[eRep].rank < edgeState[fRep].rank) { // Join eRep beneath fRep. edgeState[eRep].parent = fRep; edgeState[eRep].twistUp = hasTwist ^ parentTwists; edgeState[fRep].size += edgeState[eRep].size; edgeStateChanged[orderIdx] = eRep; } else { // Join fRep beneath eRep. edgeState[fRep].parent = eRep; edgeState[fRep].twistUp = hasTwist ^ parentTwists; if (edgeState[eRep].rank == edgeState[fRep].rank) { edgeState[eRep].rank++; edgeState[fRep].hadEqualRank = true; } edgeState[eRep].size += edgeState[fRep].size; edgeStateChanged[orderIdx] = fRep; } nEdgeClasses--; } } return retVal; } void NEulerSearcher::splitEdgeClasses() { NTetFace face = order[orderElt]; int v1, v2; int e; int eIdx, orderIdx; int rep, subRep; v1 = face.facet; for (v2 = 3; v2 >= 0; v2--) { if (v2 == v1) continue; // Look at the edge opposite v1-v2. e = 5 - NEdge::edgeNumber[v1][v2]; eIdx = e + 6 * face.simp; orderIdx = v2 + 4 * orderElt; if (edgeStateChanged[orderIdx] < 0) edgeState[findEdgeClass(eIdx)].bounded = true; else { subRep = edgeStateChanged[orderIdx]; rep = edgeState[subRep].parent; edgeState[subRep].parent = -1; if (edgeState[subRep].hadEqualRank) { edgeState[subRep].hadEqualRank = false; edgeState[rep].rank--; } edgeState[rep].size -= edgeState[subRep].size; edgeStateChanged[orderIdx] = -1; nEdgeClasses++; } } } void NEulerSearcher::vtxBdryConsistencyCheck() { int adj, id, end; for (id = 0; id < static_cast(getNumberOfTetrahedra()) * 4; id++) if (vertexState[id].bdryEdges > 0) for (end = 0; end < 2; end++) { adj = vertexState[id].bdryNext[end]; if (vertexState[adj].bdryEdges == 0) std::cerr << "CONSISTENCY ERROR: Vertex link boundary " << id << '/' << end << " runs into an internal vertex." << std::endl; if (vertexState[adj].bdryNext[(1 ^ end) ^ vertexState[id].bdryTwist[end]] != id) std::cerr << "CONSISTENCY ERROR: Vertex link boundary " << id << '/' << end << " has a mismatched adjacency." << std::endl; if (vertexState[adj].bdryTwist[(1 ^ end) ^ vertexState[id].bdryTwist[end]] != vertexState[id].bdryTwist[end]) std::cerr << "CONSISTENCY ERROR: Vertex link boundary " << id << '/' << end << " has a mismatched twist." << std::endl; } } void NEulerSearcher::vtxBdryDump(std::ostream& out) { for (unsigned id = 0; id < getNumberOfTetrahedra() * 4; id++) { if (id > 0) out << ' '; out << vertexState[id].bdryNext[0] << (vertexState[id].bdryTwist[0] ? '~' : '-') << id << (vertexState[id].bdryTwist[1] ? '~' : '-') << vertexState[id].bdryNext[1] << " [" << int(vertexState[id].bdryEdges) << ']'; } out << std::endl; } } // namespace regina regina-4.96/engine/census/hyperbolic.cpp000644 000765 000024 00000040463 12377776541 020253 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "census/ngluingpermsearcher.h" #include "triangulation/nedge.h" #include "triangulation/nfacepair.h" #include "triangulation/ntriangulation.h" #include "utilities/boostutils.h" #include "utilities/memutils.h" namespace regina { const char NHyperbolicMinSearcher::ECLASS_TWISTED = 1; const char NHyperbolicMinSearcher::ECLASS_LOWDEG = 2; const char NHyperbolicMinSearcher::dataTag_ = 'h'; NHyperbolicMinSearcher::NHyperbolicMinSearcher(const NFacePairing* pairing, const NFacePairing::IsoList* autos, bool orientableOnly, UseGluingPerms use, void* useArgs) : NEulerSearcher(0, pairing, autos, orientableOnly, PURGE_NON_MINIMAL_HYP, use, useArgs) { } void NHyperbolicMinSearcher::runSearch(long maxDepth) { unsigned nTets = getNumberOfTetrahedra(); if (maxDepth < 0) { // Larger than we will ever see (and in fact grossly so). maxDepth = nTets * 4 + 1; } if (! started) { // Search initialisation. started = true; // Do we in fact have no permutation at all to choose? if (maxDepth == 0 || pairing_->dest(0, 0).isBoundary(nTets)) { use_(this, useArgs_); use_(0, useArgs_); return; } orderElt = 0; orientation[0] = 1; } // Is it a partial search that has already finished? if (orderElt == orderSize) { if (isCanonical()) use_(this, useArgs_); use_(0, useArgs_); return; } // ---------- Selecting the individual gluing permutations ---------- int minOrder = orderElt; int maxOrder = orderElt + maxDepth; NTetFace face, adj; int mergeResult; while (orderElt >= minOrder) { face = order[orderElt]; adj = (*pairing_)[face]; // TODO (long-term): Check for cancellation. // Move to the next permutation. // Be sure to preserve the orientation of the permutation if necessary. if ((! orientableOnly_) || adj.facet == 0) permIndex(face)++; else permIndex(face) += 2; // Are we out of ideas for this face? if (permIndex(face) >= 6) { // Yep. Head back down to the previous face. permIndex(face) = -1; permIndex(adj) = -1; orderElt--; // Pull apart vertex and edge links at the previous level. if (orderElt >= minOrder) { splitVertexClasses(); splitEdgeClasses(); } continue; } // We are sitting on a new permutation to try. permIndex(adj) = NPerm4::invS3[permIndex(face)]; // Merge edge links and run corresponding tests. if (mergeEdgeClasses()) { // We created an invalid edge. splitEdgeClasses(); continue; } // Merge vertex links and run corresponding tests. mergeResult = mergeVertexClasses(); if (mergeResult & VLINK_BAD_EULER) { // Our vertex link can never obtain the correct // Euler characteristic. Stop now. splitVertexClasses(); splitEdgeClasses(); continue; } // Fix the orientation if appropriate. if (adj.facet == 0 && orientableOnly_) { // It's the first time we've hit this tetrahedron. if ((permIndex(face) + (face.facet == 3 ? 0 : 1) + (adj.facet == 3 ? 0 : 1)) % 2 == 0) orientation[adj.simp] = -orientation[face.simp]; else orientation[adj.simp] = orientation[face.simp]; } // Move on to the next face. orderElt++; // If we're at the end, try the solution and step back. if (orderElt == orderSize) { // We in fact have an entire triangulation. // Run through the automorphisms and check whether our // permutations are in canonical form. if (isCanonical()) use_(this, useArgs_); // Back to the previous face. orderElt--; // Pull apart vertex and edge links at the previous level. if (orderElt >= minOrder) { splitVertexClasses(); splitEdgeClasses(); } } else { // Not a full triangulation; just one level deeper. // We've moved onto a new face. // Be sure to get the orientation right. face = order[orderElt]; if (orientableOnly_ && pairing_->dest(face).facet > 0) { // permIndex(face) will be set to -1 or -2 as appropriate. adj = (*pairing_)[face]; if (orientation[face.simp] == orientation[adj.simp]) permIndex(face) = 1; else permIndex(face) = 0; if ((face.facet == 3 ? 0 : 1) + (adj.facet == 3 ? 0 : 1) == 1) permIndex(face) = (permIndex(face) + 1) % 2; permIndex(face) -= 2; } if (orderElt == maxOrder) { // We haven't found an entire triangulation, but we've // gone as far as we need to. // Process it, then step back. use_(this, useArgs_); // Back to the previous face. permIndex(face) = -1; orderElt--; // Pull apart vertex and edge links at the previous level. if (orderElt >= minOrder) { splitVertexClasses(); splitEdgeClasses(); } } } } // And the search is over. // Some extra sanity checking. if (minOrder == 0) { // Our vertex classes had better be 4n standalone vertices. if (nVertexClasses != 4 * nTets) std::cerr << "ERROR: nVertexClasses == " << nVertexClasses << " at end of search!" << std::endl; for (int i = 0; i < static_cast(nTets) * 4; i++) { if (vertexState[i].parent != -1) std::cerr << "ERROR: vertexState[" << i << "].parent == " << vertexState[i].parent << " at end of search!" << std::endl; if (vertexState[i].rank != 0) std::cerr << "ERROR: vertexState[" << i << "].rank == " << vertexState[i].rank << " at end of search!" << std::endl; if (vertexState[i].bdry != 3) std::cerr << "ERROR: vertexState[" << i << "].bdry == " << vertexState[i].bdry << " at end of search!" << std::endl; if (vertexState[i].euler != 2) std::cerr << "ERROR: vertexState[" << i << "].euler == " << vertexState[i].euler << " at end of search!" << std::endl; if (vertexState[i].hadEqualRank) std::cerr << "ERROR: vertexState[" << i << "].hadEqualRank == " "true at end of search!" << std::endl; if (vertexState[i].bdryEdges != 3) std::cerr << "ERROR: vertexState[" << i << "].bdryEdges == " << static_cast(vertexState[i].bdryEdges) << " at end of search!" << std::endl; if (vertexState[i].bdryNext[0] != i) std::cerr << "ERROR: vertexState[" << i << "].bdryNext[0] == " << vertexState[i].bdryNext[0] << " at end of search!" << std::endl; if (vertexState[i].bdryNext[1] != i) std::cerr << "ERROR: vertexState[" << i << "].bdryNext[1] == " << vertexState[i].bdryNext[1] << " at end of search!" << std::endl; if (vertexState[i].bdryTwist[0]) std::cerr << "ERROR: vertexState[" << i << "].bdryTwist == " "true at end of search!" << std::endl; if (vertexState[i].bdryTwist[1]) std::cerr << "ERROR: vertexState[" << i << "].bdryTwist == " "true at end of search!" << std::endl; } for (unsigned i = 0; i < nTets * 8; i++) if (vertexStateChanged[i] != VLINK_JOIN_INIT) std::cerr << "ERROR: vertexStateChanged[" << i << "] == " << vertexStateChanged[i] << " at end of search!" << std::endl; // And our edge classes had better be 6n standalone edges. if (nEdgeClasses != 6 * nTets) std::cerr << "ERROR: nEdgeClasses == " << nEdgeClasses << " at end of search!" << std::endl; for (unsigned i = 0; i < nTets * 6; i++) { if (edgeState[i].parent != -1) std::cerr << "ERROR: edgeState[" << i << "].parent == " << edgeState[i].parent << " at end of search!" << std::endl; if (edgeState[i].rank != 0) std::cerr << "ERROR: edgeState[" << i << "].rank == " << edgeState[i].rank << " at end of search!" << std::endl; if (edgeState[i].size != 1) std::cerr << "ERROR: edgeState[" << i << "].size == " << edgeState[i].size << " at end of search!" << std::endl; if (! edgeState[i].bounded) std::cerr << "ERROR: edgeState[" << i << "].bounded == " "false at end of search!" << std::endl; if (edgeState[i].hadEqualRank) std::cerr << "ERROR: edgeState[" << i << "].hadEqualRank == " "true at end of search!" << std::endl; } for (unsigned i = 0; i < nTets * 8; i++) if (edgeStateChanged[i] != -1) std::cerr << "ERROR: edgeStateChanged[" << i << "] == " << edgeStateChanged[i] << " at end of search!" << std::endl; } use_(0, useArgs_); } void NHyperbolicMinSearcher::dumpData(std::ostream& out) const { NEulerSearcher::dumpData(out); } NHyperbolicMinSearcher::NHyperbolicMinSearcher(std::istream& in, UseGluingPerms use, void* useArgs) : NEulerSearcher(in, use, useArgs) { if (inputError_) return; // Did we hit an unexpected EOF? if (in.eof()) inputError_ = true; } int NHyperbolicMinSearcher::mergeEdgeClasses() { /** * As well as detecting edges that are self-identified in reverse, * we strip out low-degree edges here. Although we are also interested * in non-geometric triangulations, we can still ignore triangulations * with low-degree edges because (with a little work) they can be * proven to be non-minimal. For details see: * "The cusped hyperbolic census is complete", B.B. */ NTetFace face = order[orderElt]; NTetFace adj = (*pairing_)[face]; int retVal = 0; NPerm4 p = gluingPerm(face); int v1, w1, v2, w2; int e, f; int orderIdx; int eRep, fRep; int middleTet; v1 = face.facet; w1 = p[v1]; char parentTwists, hasTwist; for (v2 = 0; v2 < 4; v2++) { if (v2 == v1) continue; w2 = p[v2]; // Look at the edge opposite v1-v2. e = 5 - NEdge::edgeNumber[v1][v2]; f = 5 - NEdge::edgeNumber[w1][w2]; orderIdx = v2 + 4 * orderElt; // We declare the natural orientation of an edge to be smaller // vertex to larger vertex. hasTwist = (p[NEdge::edgeVertex[e][0]] > p[NEdge::edgeVertex[e][1]] ? 1 : 0); parentTwists = 0; eRep = findEdgeClass(e + 6 * face.simp, parentTwists); fRep = findEdgeClass(f + 6 * adj.simp, parentTwists); if (eRep == fRep) { edgeState[eRep].bounded = false; if (edgeState[eRep].size <= 2) retVal |= ECLASS_LOWDEG; else if (edgeState[eRep].size == 3) { // Flag as LOWDEG only if three distinct tetrahedra are used. middleTet = pairing_->dest(face.simp, v2).simp; if (face.simp != adj.simp && adj.simp != middleTet && middleTet != face.simp) retVal |= ECLASS_LOWDEG; } if (hasTwist ^ parentTwists) retVal |= ECLASS_TWISTED; edgeStateChanged[orderIdx] = -1; } else { if (edgeState[eRep].rank < edgeState[fRep].rank) { // Join eRep beneath fRep. edgeState[eRep].parent = fRep; edgeState[eRep].twistUp = hasTwist ^ parentTwists; edgeState[fRep].size += edgeState[eRep].size; edgeStateChanged[orderIdx] = eRep; } else { // Join fRep beneath eRep. edgeState[fRep].parent = eRep; edgeState[fRep].twistUp = hasTwist ^ parentTwists; if (edgeState[eRep].rank == edgeState[fRep].rank) { edgeState[eRep].rank++; edgeState[fRep].hadEqualRank = true; } edgeState[eRep].size += edgeState[fRep].size; edgeStateChanged[orderIdx] = fRep; } nEdgeClasses--; } } return retVal; } void NHyperbolicMinSearcher::splitEdgeClasses() { NTetFace face = order[orderElt]; int v1, v2; int e; int eIdx, orderIdx; int rep, subRep; v1 = face.facet; for (v2 = 3; v2 >= 0; v2--) { if (v2 == v1) continue; // Look at the edge opposite v1-v2. e = 5 - NEdge::edgeNumber[v1][v2]; eIdx = e + 6 * face.simp; orderIdx = v2 + 4 * orderElt; if (edgeStateChanged[orderIdx] < 0) edgeState[findEdgeClass(eIdx)].bounded = true; else { subRep = edgeStateChanged[orderIdx]; rep = edgeState[subRep].parent; edgeState[subRep].parent = -1; if (edgeState[subRep].hadEqualRank) { edgeState[subRep].hadEqualRank = false; edgeState[rep].rank--; } edgeState[rep].size -= edgeState[subRep].size; edgeStateChanged[orderIdx] = -1; nEdgeClasses++; } } } } // namespace regina regina-4.96/engine/census/ncensus.cpp000644 000765 000024 00000023556 12377776542 017576 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include #include // cstdbool needs c++11 #include // cstdint needs c++11 #include #include #include "census/ncensus.h" #include "census/ngluingpermsearcher.h" #include "file/nglobaldirs.h" #include "triangulation/ntriangulation.h" #include "utilities/memutils.h" namespace regina { NCensusDB* NCensus::closedOr_ = 0; NCensusDB* NCensus::closedNor_ = 0; NCensusDB* NCensus::closedHyp_ = 0; NCensusDB* NCensus::cuspedHypOr_ = 0; NCensusDB* NCensus::cuspedHypNor_ = 0; NCensusDB* NCensus::hypKnotLink_ = 0; bool NCensus::dbInit_ = false; bool NCensusDB::lookup(const std::string& isoSig, NCensusHits* hits) const { TCBDB* db = tcbdbnew(); if (! tcbdbopen(db, filename_.c_str(), BDBOREADER)) { std::cerr << "ERROR: Could not open census database: " << filename_ << std::endl; return false; } TCLIST* records = tcbdbget4(db, isoSig.c_str(), isoSig.length()); if (records) { int n = tclistnum(records); for (int i = 0; i < n; ++i) hits->append(new NCensusHit(tclistval2(records, i), this)); tclistdel(records); } tcbdbclose(db); tcbdbdel(db); return true; } NCensusHits* NCensus::lookup(const NTriangulation& tri) { return lookup(tri.isoSig()); } NCensusHits* NCensus::lookup(const std::string& isoSig) { if (! dbInit_) { closedOr_ = standardDB("closed-or-census-11.tdb", "Closed census (orientable)"); closedNor_ = standardDB("closed-nor-census-11.tdb", "Closed census (non-orientable)"); closedHyp_ = standardDB("closed-hyp-census-full.tdb", "Hodgson-Weeks closed hyperbolic census"); cuspedHypOr_ = standardDB("cusped-hyp-or-census-9.tdb", "Cusped hyperbolic census (orientable)"); cuspedHypNor_ = standardDB("cusped-hyp-nor-census-9.tdb", "Cusped hyperbolic census (non-orientable)"); hypKnotLink_ = standardDB("hyp-knot-link-census.tdb", "Hyperbolic knot and link complements"); dbInit_ = true; } NCensusHits* hits = new NCensusHits; closedOr_->lookup(isoSig, hits); closedNor_->lookup(isoSig, hits); closedHyp_->lookup(isoSig, hits); cuspedHypOr_->lookup(isoSig, hits); cuspedHypNor_->lookup(isoSig, hits); hypKnotLink_->lookup(isoSig, hits); return hits; } NCensusDB* NCensus::standardDB(const char* filename, const char* desc) { return new NCensusDB(NGlobalDirs::data() + "/census/" + filename, desc); } const int NCensus::PURGE_NON_MINIMAL = NGluingPermSearcher::PURGE_NON_MINIMAL; const int NCensus::PURGE_NON_PRIME = NGluingPermSearcher::PURGE_NON_PRIME; const int NCensus::PURGE_NON_MINIMAL_PRIME = NGluingPermSearcher::PURGE_NON_MINIMAL_PRIME; const int NCensus::PURGE_P2_REDUCIBLE = NGluingPermSearcher::PURGE_P2_REDUCIBLE; unsigned long NCensus::formCensus(NPacket* parent, unsigned nTetrahedra, NBoolSet finiteness, NBoolSet orientability, NBoolSet boundary, int nBdryFaces, int whichPurge, AcceptTriangulation sieve, void* sieveArgs) { // If obviously nothing is going to happen but we won't realise // it until we've actually generated the face pairings, change // nTetrahedra to 0 so we'll realise it immediately once the new // thread starts. if (finiteness == NBoolSet::sNone || orientability == NBoolSet::sNone) nTetrahedra = 0; // Start the census! NCensus* census = new NCensus(parent, finiteness, orientability, whichPurge, sieve, sieveArgs); NFacePairing::findAllPairings(nTetrahedra, boundary, nBdryFaces, NCensus::foundFacePairing, census, false /* separate thread */); unsigned long ans = census->whichSoln - 1; delete census; return ans; } unsigned long NCensus::formPartialCensus(const NFacePairing* pairing, NPacket* parent, NBoolSet finiteness, NBoolSet orientability, int whichPurge, AcceptTriangulation sieve, void* sieveArgs) { // Is it obvious that nothing will happen? if (finiteness == NBoolSet::sNone || orientability == NBoolSet::sNone) return 0; // Make a list of automorphisms. NFacePairing::IsoList autos; pairing->findAutomorphisms(autos); // Select the individual gluing permutations. NCensus census(parent, finiteness, orientability, whichPurge, sieve, sieveArgs); NGluingPermSearcher::findAllPerms(pairing, &autos, ! census.orientability.hasFalse(), ! census.finiteness.hasFalse(), census.whichPurge, NCensus::foundGluingPerms, &census); // Clean up. std::for_each(autos.begin(), autos.end(), FuncDelete()); return census.whichSoln - 1; } NCensus::NCensus(NPacket* newParent, const NBoolSet& newFiniteness, const NBoolSet& newOrientability, int newWhichPurge, AcceptTriangulation newSieve, void* newSieveArgs) : parent(newParent), finiteness(newFiniteness), orientability(newOrientability), whichPurge(newWhichPurge), sieve(newSieve), sieveArgs(newSieveArgs), whichSoln(1) { } void NCensus::foundFacePairing(const NFacePairing* pairing, const NFacePairing::IsoList* autos, void* census) { NCensus* realCensus = static_cast(census); if (pairing) { // We've found another face pairing. // Select the individual gluing permutations. NGluingPermSearcher::findAllPerms(pairing, autos, ! realCensus->orientability.hasFalse(), ! realCensus->finiteness.hasFalse(), realCensus->whichPurge, NCensus::foundGluingPerms, census); } else { // Census generation has finished. } } void NCensus::foundGluingPerms(const NGluingPermSearcher* perms, void* census) { if (perms) { // We've found another permutation set. // Triangulate and see what we've got. NTriangulation* tri = perms->triangulate(); NCensus* realCensus = static_cast(census); bool ok = true; if (! tri->isValid()) ok = false; else if ((! realCensus->finiteness.hasFalse()) && tri->isIdeal()) ok = false; else if ((! realCensus->finiteness.hasTrue()) && (! tri->isIdeal())) ok = false; else if ((! realCensus->orientability.hasTrue()) && tri->isOrientable()) ok = false; else if (realCensus->sieve && ! realCensus->sieve(tri, realCensus->sieveArgs)) ok = false; if (ok) { // Put it in the census! // Make sure it has a charming label. // Don't insist on unique labels, since this requirement // will soon be dropped and it multiplies the running time // by a factor of #triangulations. std::ostringstream out; out << "Item " << realCensus->whichSoln; tri->setPacketLabel(out.str()); realCensus->parent->insertChildLast(tri); realCensus->whichSoln++; } else { // Bad triangulation. delete tri; } } } bool NCensus::mightBeMinimal(NTriangulation* tri, void*) { if (! tri->hasBoundaryTriangles()) { // No boundary faces. // Tests specific to closed finite orientable triangulations: if (tri->isOrientable() && (! tri->isIdeal())) { // Check for too many vertices. if (tri->getNumberOfVertices() > 1 && tri->getNumberOfTetrahedra() > 2) return false; } // Check for obvious simplifications. if (tri->simplifyToLocalMinimum(false)) return false; } return true; } } // namespace regina regina-4.96/engine/census/ncensus.h000644 000765 000024 00000113404 12377774652 017233 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file census/ncensus.h * \brief Provides facilities for looking up 3-manifold triangulations in * Regina's in-built census databases. */ #ifndef __NCENSUS_H #ifndef __DOXYGEN #define __NCENSUS_H #endif #include "regina-core.h" #include "census/nfacepairing.h" #include "utilities/nbooleans.h" namespace regina { class NCensusHits; class NGluingPerms; class NGluingPermSearcher; class NPacket; class NTriangulation; /** * \addtogroup census Census of Triangulations * Census lookup and enumeration for triangulations of various dimensions. * @{ */ /** * A legacy typedef that is identical to NCensus::AcceptTriangulation. * See NCensus::AcceptTriangulation for further details. * * \deprecated This global typedef is now deprecated. Please use the * identical class typedef NCensus::AcceptTriangulation instead. However, * be aware that the NCensus enumeration facilities are on their * way out of Regina, and in the future the NCensus class will be * used purely for census lookups. If you wish to build a census * yourself, you should call NFacePairing::findAllPairings() and * NGluingPermSearcher::findAllPerms() directly. */ typedef bool (*AcceptTriangulation)(NTriangulation*, void*); /** * Stores the location and description of one of Regina's in-built census * databases. * * A census database stores a list of key-value pairs. The keys are * isomorphism signatures of triangulations (as returned by * NTriangulation::isoSig(), for instance), and the values are * human-readable names (typically the names of the triangulations * and/or the names of the underlying manifolds). An isomorphism * signature may appear multiple times (with different names) * within the same database. * * The format used to store census databases is an internal implementation * detail that may change in future releases of Regina. End users * should only search census databases using high-level routines such as * NCensus::lookup() and NCensusDB::lookup(). */ class NCensusDB { private: std::string filename_; /**< The filename where the database is stored. */ std::string desc_; /**< A human-readable description of this database. */ public: /** * Creates a new reference to one of Regina's census databases. * * This constructor will not run any checks (e.g., it will not * verify that the database exists, or that it is stored in the correct * format). Note that even if the database does not exist, the * lookup() routine will fail gracefully. * * @param filename the filename where the database is stored. * @param desc a human-readable description of the database. * See the desc() routine for further information on how this * description might be used. */ NCensusDB(const std::string& filename, const std::string& desc); /** * Returns the filename where this database is stored. * * @return the database filename. */ const std::string& filename() const; /** * Returns a human-readable description of this database. * * The description could (for instance) be shown to users when * giving a list of all available databases, or when identifying * in which particular database a match was found. * * @return the database description. */ const std::string& desc() const; /** * Searches for the given isomorphism signature in this database. * All matches (if any) will be appended to the given list of hits. * * Note that the database will be opened and closed every time * this routine is called. * * @param isoSig the isomorphism signature to search for. * @param hits the list of hits to which all matches will be appended. * @return \c true if the lookup was correctly performed, or \c false * if some error occurred (e.g., the database could not be opened). * Note in particular that if there were no matches but no errors, * then the return value will be \c true. */ bool lookup(const std::string& isoSig, NCensusHits* hits) const; }; /** * Stores a single "hit" indicating that some given triangulation has * been located in one of Regina's in-built census databases. * * Note that a given triangulation might have several hits across Regina's * databases. Therefore hits are typically returned using the separate * NCensusHits class, which essentially represents a list of individual * NCensusHit objects. */ class NCensusHit : public regina::boost::noncopyable { private: const std::string name_; /**< The human-readable name associated with the triangulation in the database. */ const NCensusDB* db_; /**< The database in which the triangulation was found. */ NCensusHit* next_; /**< A pointer to the next hit in the list that was found for the same triangulation, or 0 if this is the last hit. */ public: /** * Returns the human-readable name associated with the * triangulation in the database. This typically contains the name of * the triangulation and/or the name of the underlying manifold. * * @return the human-readable name for this hit. */ const std::string& name() const; /** * Returns details of the census database in which the * triangulation was found. * * @return the database for this hit. */ const NCensusDB* db() const; /** * Returns the next hit for the same triangulation, or 0 if * there are no more hits. * * Recall that hits are typically returned using the NCensusHits * class, which stores a list of individual NCensusHit objects. * To iterate through this list, you should begin by calling * NCensusHits::first() to retrieve the first hit, and then for each * hit call NCensusHit::next() (this function) to retrieve the next hit. * * @return the next hit after this in the list, or 0 if this is the * last hit. */ const NCensusHit* next() const; private: /** * Constructs a hit with the given details. The pointer \a next_ * will be set to null. */ NCensusHit(const char* name, const NCensusDB* db); /** * Constructs a hit with the given details. The pointer \a next_ * will be set to null. */ NCensusHit(const std::string& name, const NCensusDB* db); friend class NCensusDB; friend class NCensusHits; }; /** * Stores a list of "hits" indicating all the places in which a given * triangulation has been located in Regina's various in-built census databases. * * A given triangulation might have several hits across Regina's databases * (or even in the same database). The complete set of hits for a given * triangulation is represented by a single NCensusHits object (which is * essentially a linked list of individual NCensusHit objects). To iterate * through this list, you begin by calling NCensusHits::first(), which will * return the first hit (or 0 if there are no hits at all). Then, for each * individual hit, you can call NCensusHit::next() to retrieve the next hit * in the list (this will return 0 if no more hits were found). */ class NCensusHits : public regina::boost::noncopyable { private: NCensusHit* first_; /**< The first hit in the list, or 0 if there are no hits. */ NCensusHit* last_; /**< The last hit in the list, or 0 if there are no hits. */ size_t count_; /**< The total number of hits in the list. */ public: /** * Constructs an empty set of hits. */ NCensusHits(); /** * Destroys this object and all of the individual NCensusHit objects * that it contains. */ ~NCensusHits(); /** * Returns the first hit in this list. * * To continue iterating, you can call NCensusHit::next() upon each * individual hit to retrieve the next hit in the list. * * @return the first hit, or 0 if there are no hits at all. */ NCensusHit* first() const; /** * Returns the total number of hits in this list. * * This routine is fast, since the number of hits is cached (it * does not need to walk through the entire list to count). * * @return the total number of hits. */ size_t count() const; /** * Returns whether there are any hits at all. * * @return \c true if this list is empty (i.e., there are no hits), * or \c false if the list is non-empty (i.e., there are one or * more hits). */ bool empty() const; /** * Appends a new hit to the end of this list. This list will * take ownership of the given object. * * @param hit the hit to append to this list. */ void append(NCensusHit* hit); }; /** * A utility class used to search for triangulations across one or more * 3-manifold census databases. */ class REGINA_API NCensus { public: /** * This constant indicates that non-minimal triangulations * may be ignored. * * \deprecated This constant is deprecated; please use * NGluingPermSearcher::PURGE_NON_MINIMAL instead. */ static const int PURGE_NON_MINIMAL; /** * This constant indicates that any triangulation that is not * prime (i.e., can be written as a non-trivial connected sum) * and any bounded triangulation that is reducible over a disc * may be ignored. * * \deprecated This constant is deprecated; please use * NGluingPermSearcher::PURGE_NON_PRIME instead. */ static const int PURGE_NON_PRIME; /** * This constant indicates that any triangulation that is not * prime (i.e., can be written as a non-trivial connected sum), * any bounded triangulation that is reducible over a disc and * any triangulation that is non-minimal may be ignored. * Note that this is simply a combination of the constants * \a PURGE_NON_MINIMAL and \a PURGE_NON_PRIME. * * \deprecated This constant is deprecated; please use * NGluingPermSearcher::PURGE_NON_MINIMAL_PRIME instead. */ static const int PURGE_NON_MINIMAL_PRIME; /** * This constant indicates that any triangulation containing an * embedded two-sided projective plane may be ignored. * * \deprecated This constant is deprecated; please use * NGluingPermSearcher::PURGE_NON_MINIMAL instead. */ static const int PURGE_P2_REDUCIBLE; /** * A routine used to determine whether a particular triangulation * should be included in a census. Routines of this type are used by * NCensus::formCensus(). * * The first parameter passed should be a triangulation currently * under consideration. * The second parameter may contain arbitrary data as passed to * NCensus::formCensus(). * * The return value should be \c true if the triangulation passed * should be included in the census, or \c false otherwise. * * \deprecated The NCensus enumeration facilities are on their * way out of Regina, and in the future the NCensus class will be * used purely for census lookups. If you wish to build a census * yourself, you should call NFacePairing::findAllPairings() and * NGluingPermSearcher::findAllPerms() directly. */ typedef bool (*AcceptTriangulation)(NTriangulation*, void*); private: static NCensusDB* closedOr_; /**< The census of closed orientable prime 3-manifold triangulations that are shipped with Regina. This will only be initialised when lookup() is first called. */ static NCensusDB* closedNor_; /**< The census of closed non-orientable P^2-irreducible 3-manifold triangulations that are shipped with Regina. This will only be initialised when lookup() is first called. */ static NCensusDB* closedHyp_; /**< The census of closed hyperbolic 3-manifold triangulations that are shipped with Regina. This will only be initialised when lookup() is first called. */ static NCensusDB* cuspedHypOr_; /**< The census of cusped hyperbolic orientable 3-manifold triangulations that are shipped with Regina. This will only be initialised when lookup() is first called. */ static NCensusDB* cuspedHypNor_; /**< The census of cusped hyperbolic non-orientable 3-manifold triangulations that are shipped with Regina. This will only be initialised when lookup() is first called. */ static NCensusDB* hypKnotLink_; /**< The census of cusped hyperbolic knot and link complements that are shipped with Regina. This will only be initialised when lookup() is first called. */ static bool dbInit_; /**< Have the census databases been initialised yet? */ NPacket* parent; /**< The argument passed to formCensus(). */ NBoolSet finiteness; /**< The argument passed to formCensus(). */ NBoolSet orientability; /**< The argument passed to formCensus(). */ int whichPurge; /**< The argument passed to formCensus(). */ AcceptTriangulation sieve; /**< The arbitrary constraint function to run triangulations through. */ void* sieveArgs; /**< The second argument to pass to function \a sieve. */ unsigned long whichSoln; /**< The number of the solution we are up to. */ public: /** * Searches for the given triangulation through all of Regina's * in-built census databases. * * Internally, the census databases store isomorphism signatures * as opposed to fully fleshed-out triangulations. If you already * have the isomorphism signature of the triangulation, then you * can call the variant lookup(const std::string&) instead, which * will be faster since it avoids some extra overhead. * * Note that there may be many hits (possibly from multiple databases, * and in some cases possibly even within the same database). * The list of hits will be returned as an NCensusHits object, * which you can use to iterate through the individual matches. * Even if there are no matches at all, an NCensusHits object will * still be returned; you can call NCensusHits::empty() to test * whether any matches were found. * * The NCensusHits object that is returned will be newly * allocated, and it is the caller's responsibility to destroy it. * * This routine is fast: it first computes the isomorphism * signature of the triangulation, and then performs a * logarithmic-time lookup in each database (here "logarithmic" * means logarithmic in the size of the database). * * @param tri the triangulation that you wish to search for. * @return a newly created list of all database matches. */ static NCensusHits* lookup(const NTriangulation& tri); /** * Searches for the given triangulation through all of Regina's * in-built census databases. * * For this routine you specify the triangulation by giving its * isomorphism signature, as returned by NTriangulation::isoSig(). * This is faster than the variant lookup(const NTriangulation&), * since Regina's census databases store isomorphism signatures * internally. If you do not already know the isomorphism signature, * it is fine to just call lookup(const NTriangulation&) instead. * * Note that there may be many hits (possibly from multiple databases, * and in some cases possibly even within the same database). * The list of hits will be returned as an NCensusHits object, * which you can use to iterate through the individual matches. * Even if there are no matches at all, an NCensusHits object will * still be returned; you can call NCensusHits::empty() to test * whether any matches were found. * * The NCensusHits object that is returned will be newly * allocated, and it is the caller's responsibility to destroy it. * * This routine is fast: it first computes the isomorphism * signature of the triangulation, and then performs a * logarithmic-time lookup in each database (here "logarithmic" * means logarithmic in the size of the database). * * @param isoSig the isomorphism signature of the triangulation * that you wish to search for. * @return a newly created list of all database matches. */ static NCensusHits* lookup(const std::string& isoSig); /** * Deprecated routine that fills the given packet with all * triangulations in a census of 3-manifold triangulations satisfying * the given constraints. Each triangulation in the census will * appear as a child of the given packet. * * This routine will conduct a census of all valid triangulations * containing a given number of tetrahedra. All such triangulations * are included in the census up to combinatorial isomorphism; given * any isomorphism class, exactly one representative will appear in * the census. * * The census can be optionally restricted to only include * triangulations satisfying further constraints (such as * orientability and finiteness); see the individual parameter * descriptions for further details. In particular, parameter * \a sieve can be used to impose arbitrary restrictions that are * not hard-coded into this class. * * Note that if constraints may be imposed using the hard-coded * parameters (such as orientability and finiteness), it is * generally better to do this than to use the arbitrary * constraint parameter \a sieve. Hard-coded parameters will be * tested earlier, and some (such as orientability) can be * incorporated directly into the census algorithm to give a vast * performance increase. * * Parameter \a whichPurge may be used to further avoid constructing * triangulations satisfying particular constraints (such as * non-minimality). This can significantly speed up the census. * In this case however not all such triangulations will be * avoided, but it is guaranteed that every triangulation that * does \e not satisfy the constraints defined by \a whichPurge * will be produced. * * Only valid triangulations will be produced; see * NTriangulation::isValid() for further details. * * Note that this routine should only be used if the census * contains a small enough total number of triangulations to * avoid any memory disasters. * * \deprecated The NCensus enumeration facilities are on their * way out of Regina, and in the future the NCensus class will be * used purely for census lookups. To perform the kind of * enumeration that is described here, you should call * NFacePairing::findAllPairings() and * NGluingPermSearcher::findAllPerms() directly. * * \ifacespython Parameters \a sieve and \a sieveArgs * are not present (and will be treated as 0). * * @param parent the packet beneath which members of the census will * be placed. * @param nTetrahedra the number of tetrahedra in each triangulation * in the census. * @param finiteness determines whether to include finite and/or ideal * triangulations. The set should contain \c true if finite (non-ideal) * triangulations are to be included, and should contain \c false if * ideal triangulations are to be included. * @param orientability determines whether to include orientable * and/or non-orientable triangulations. The set should contain \c true * if orientable triangulations are to be included, and should contain * \c false if non-orientable triangulations are to be included. * @param boundary determines whether to include triangulations with * and/or without boundary triangles. The set should contain \c true * if triangulations with boundary triangles are to be included, and * should contain \c false if triangulations with only internal * triangles are to be included. * @param nBdryTris specifies the precise number of boundary triangles * that should be present in the triangulations produced. If this * parameter is negative, it is ignored and no additional restriction * is imposed. See the documentation for routine * NFacePairing::findAllPairings() for details regarding this * parameter and how it interacts with parameter \a boundary. * @param whichPurge specifies which triangulations we may further * avoid constructing (see the function notes above for details). * This should be a bitwise OR of purge constants defined in this * class, or 0 if no additional pruning should take place. * If a variety of purge constants are bitwise ORed together, a * triangulation satisfying \e any of these constraints may be * avoided. Note that not all such triangulations will be * avoided, but enough are avoided that the performance increase * is noticeable. * @param sieve an additional constraint function that may be * used to exclude certain triangulations from the census. If * this parameter is non-zero, each triangulation produced (after * passing all other criteria) will be passed through this * function. If this function returns \c true then the triangulation * will be included in the census; otherwise it will not. * When this function is called, the first (triangulation) * argument will be a triangulation under consideration for * inclusion in the census. The second argument will be * parameter \a sieveArgs as passed to formCensus(). * Parameter \a sieve may be passed as \c null (in which case no * additional constraint function will be used). * @param sieveArgs the pointer to pass as the final parameter * for the function \a sieve which will be called upon each * triangulation found. If \a sieve is \c null then \a sieveArgs * will be ignored. * @return the number of triangulations produced in the census. */ static unsigned long formCensus(NPacket* parent, unsigned nTetrahedra, NBoolSet finiteness, NBoolSet orientability, NBoolSet boundary, int nBdryTris, int whichPurge, AcceptTriangulation sieve = 0, void* sieveArgs = 0); /** * Deprecated routine that fills the given packet with all * triangulations in a partial census * of 3-manifold triangulations satisfying the given constraints. * Each triangulation in the partial census will appear as a child of * the given packet. * * This routine will conduct a census of all valid triangulations * that are modelled by the given tetrahedron face pairing. * All such triangulations are included in the census up to * combinatorial isomorphism; given any isomorphism class, exactly * one representative will appear in the census. * * The census can be optionally restricted to only include * triangulations satisfying further constraints (such as * orientability and finiteness); see the individual parameter * descriptions for further details. In particular, parameter * \a sieve can be used to impose arbitrary restrictions that are * not hard-coded into this class. * * Note that if constraints may be imposed using the hard-coded * parameters (such as orientability and finiteness), it is * generally better to do this than to use the arbitrary * constraint parameter \a sieve. Hard-coded parameters will be * tested earlier, and some (such as orientability) can be * incorporated directly into the census algorithm to give a vast * performance increase. * * Parameter \a whichPurge may be used to further avoid constructing * triangulations satisfying particular constraints (such as * non-minimality). The use of this parameter, combined with * parameters \a finiteness and \a orientability, can significantly * speed up the census. For some combinations of these * parameters entirely different algorithms are used. * * Note however that not all triangulations described by * parameter \a whichPurge will be avoided. It is guaranteed * however that every triangulation that does \e not satisfy the * constraints defined by \a whichPurge will be produced. * * Only valid triangulations will be produced; see * NTriangulation::isValid() for further details. * * Note that this routine should only be used if the partial census * contains a small enough total number of triangulations to * avoid any memory disasters. * * The partial census will run in the current thread. This * routine will only return once the partial census is complete. * * \deprecated The NCensus enumeration facilities are on their * way out of Regina, and in the future the NCensus class will be * used purely for census lookups. To perform the kind of * enumeration that is described here, you should call * NGluingPermSearcher::findAllPerms() directly. * * \pre The given face pairing is connected, i.e., it is possible * to reach any tetrahedron from any other tetrahedron via a * series of matched face pairs. * \pre The given face pairing is in canonical form as described * by NFacePairing::isCanonical(). Note that all face pairings * constructed by NFacePairing::findAllPairings() are of this form. * * \ifacespython Parameters \a sieve and \a sieveArgs * are not present (and will be treated as 0). * * @param pairing the tetrahedron face pairing that * triangulations in this partial census must be modelled by. * @param parent the packet beneath which members of the partial * census will be placed. * @param finiteness determines whether to include finite and/or ideal * triangulations. The set should contain \c true if finite (non-ideal) * triangulations are to be included, and should contain \c false if * ideal triangulations are to be included. * @param orientability determines whether to include orientable * and/or non-orientable triangulations. The set should contain \c true * if orientable triangulations are to be included, and should contain * \c false if non-orientable triangulations are to be included. * @param whichPurge specifies which triangulations we may further * avoid constructing (see the function notes above for details). * This should be a bitwise OR of purge constants defined in this * class, or 0 if no additional pruning should take place. * If a variety of purge constants are bitwise ORed together, a * triangulation satisfying \e any of these constraints may be * avoided. Note that not all such triangulations will be * avoided, but enough are avoided that the performance increase * is noticeable. * @param sieve an additional constraint function that may be * used to exclude certain triangulations from the census. If * this parameter is non-zero, each triangulation produced (after * passing all other criteria) will be passed through this * function. If this function returns \c true then the triangulation * will be included in the census; otherwise it will not. * When this function is called, the first (triangulation) * argument will be a triangulation under consideration for * inclusion in the census. The second argument will be * parameter \a sieveArgs as passed to formPartialCensus(). * Parameter \a sieve may be passed as \c null (in which case no * additional constraint function will be used). * @param sieveArgs the pointer to pass as the final parameter * for the function \a sieve which will be called upon each * triangulation found. If \a sieve is \c null then \a sieveArgs * will be ignored. * @return the number of triangulations produced in the partial census. */ static unsigned long formPartialCensus(const NFacePairing* pairing, NPacket* parent, NBoolSet finiteness, NBoolSet orientability, int whichPurge, AcceptTriangulation sieve = 0, void* sieveArgs = 0); /** * Deprecated routine to determine whether the given triangulation * even has a chance at being minimal. This routine can be passed as * parameter \a sieve to routine NCensus::formCensus() to exclude * obviously non-minimal triangulations from a census. * * A variety of tests will be performed; these tests are subject * to change between Regina releases. Currently this routine * counts vertices and also tries to simplify the triangulation using * NTriangulation::simplifyToLocalMinimum(). * * Currently this routine is only useful for triangulations whose * triangles are all internal; if the given triangulation has * boundary triangles then this routine will simply return \c true. * * \deprecated The NCensus enumeration facilities are on their way * out of Regina, and so this routine is no longer necessary. * For a fast test as to whether a triangulation might be minimal, * you should simply call NTriangulation::simplifyToLocalMinimum(false). * * \ifacespython Parameter \a ignore is not present. * * @param tri the triangulation to examine. * @param ignore a parameter that is ignored. * @return \c false if the given triangulation is known to be * non-minimal, or \c true if minimality of the given * triangulation has not been determined. */ static bool mightBeMinimal(NTriangulation* tri, void* ignore = 0); private: /** * Constructs a NCensusDB object for one of Regina's in-built * census databases, stored in the standard census database * location on the filesystem. * * @param filename the filename for the database, without directory * information. This routine will build the full pathname by joining * the given filename with the standard census database directory. * @param desc a human-readable description for the database. * @return the new database specifier. */ static NCensusDB* standardDB(const char* filename, const char* desc); /** * Creates a new structure to hold the given information. * All parameters not explained are taken directly from * formCensus(). */ NCensus(NPacket* newParent, const NBoolSet& newFiniteness, const NBoolSet& newOrientability, int newWhichPurge, AcceptTriangulation newSieve, void* newSieveArgs); /** * Called when a particular tetrahedron face pairing has been * found. This routine hooks up the face pairing generation with * the gluing permutation generation. * * @param pairing the face pairing that has been found. * @param autos the set of all automorphisms of the given face * pairing. * @param census the census currently being generated; * this must really be of class NCensus. */ static void foundFacePairing(const NFacePairing* pairing, const NFacePairing::IsoList* autos, void* census); /** * Called when a particular set of gluing permutations has been * found. This routine generates the corresponding triangulation * and decides whether it really belongs in the census. * * \pre The given set of gluing permutations is complete, i.e., * it is not just a partially-complete search state. Partial * searches are formed by calling NGluingPermSearcher::runSearch() * with a non-negative depth argument. * * @param perms the gluing permutation set that has been found. * @param census the census currently being generated; * this must really be of class NCensus. */ static void foundGluingPerms(const NGluingPermSearcher* perms, void* census); }; /*@}*/ // Inline functions for NCensusDB: inline NCensusDB::NCensusDB(const std::string& filename, const std::string& desc) : filename_(filename), desc_(desc) { } inline const std::string& NCensusDB::filename() const { return filename_; } inline const std::string& NCensusDB::desc() const { return desc_; } // Inline functions for NCensusHit: inline NCensusHit::NCensusHit(const char* name, const NCensusDB* db) : name_(name), db_(db), next_(0) { } inline NCensusHit::NCensusHit(const std::string& name, const NCensusDB* db) : name_(name), db_(db), next_(0) { } inline const std::string& NCensusHit::name() const { return name_; } inline const NCensusDB* NCensusHit::db() const { return db_; } inline const NCensusHit* NCensusHit::next() const { return next_; } // Inline functions for NCensusHits: inline NCensusHits::NCensusHits() : first_(0), last_(0), count_(0) { } inline NCensusHits::~NCensusHits() { NCensusHit* tmp; while (first_) { tmp = first_; first_ = first_->next_; delete tmp; } } inline NCensusHit* NCensusHits::first() const { return first_; } inline size_t NCensusHits::count() const { return count_; } inline bool NCensusHits::empty() const { return ! first_; } inline void NCensusHits::append(NCensusHit* hit) { if (! first_) last_ = first_ = hit; else last_ = last_->next_ = hit; // Assigns last_->next_, then last_. ++count_; } } // namespace regina #endif regina-4.96/engine/census/nfacepairing.cpp000644 000765 000024 00000065442 12377776543 020547 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include #include "census/nfacepairing.h" #include "census/ngenericfacetpairing-impl.h" #include "triangulation/nfacepair.h" #include "triangulation/ntetrahedron.h" #include "triangulation/ntriangulation.h" #include "utilities/memutils.h" #include "utilities/stringutils.h" namespace regina { // Instantiate all templates from the -impl.h file. template NGenericFacetPairing<3>::NGenericFacetPairing( const NGenericFacetPairing<3>&); template NGenericFacetPairing<3>::NGenericFacetPairing(const NTriangulation&); template bool NGenericFacetPairing<3>::isClosed() const; template std::string NGenericFacetPairing<3>::str() const; template std::string NGenericFacetPairing<3>::dotHeader(const char*); template void NGenericFacetPairing<3>::writeDotHeader(std::ostream&, const char*); template std::string NGenericFacetPairing<3>::dot(const char*, bool, bool) const; template void NGenericFacetPairing<3>::writeDot(std::ostream&, const char*, bool, bool) const; template std::string NGenericFacetPairing<3>::toTextRep() const; template NFacePairing* NGenericFacetPairing<3>::fromTextRep(const std::string&); template bool NGenericFacetPairing<3>::isCanonical() const; template bool NGenericFacetPairing<3>::isCanonicalInternal( NGenericFacetPairing<3>::IsoList&) const; template void NGenericFacetPairing<3>::findAutomorphisms( NGenericFacetPairing<3>::IsoList&) const; template bool NGenericFacetPairing<3>::findAllPairings(unsigned, NBoolSet, int, NGenericFacetPairing<3>::Use, void*, bool); template void* NGenericFacetPairing<3>::run(void*); bool NFacePairing::hasTripleEdge() const { unsigned equal, i, j; for (unsigned tet = 0; tet < size_; tet++) { // Is there a triple edge coming from this tetrahedron? equal = 0; for (i = 0; i < 4; i++) if ((! isUnmatched(tet, i)) && dest(tet, i).simp > static_cast(tet)) { // This face joins to a real face of a later tetrahedron. for (j = i + 1; j < 4; j++) if (dest(tet, i).simp == dest(tet, j).simp) equal++; } // Did we find at least three pairs (i,j) joining to the same // real later tetrahedron? A little case analysis shows that the // only way we can achieve this is through a triple edge. if (equal >= 3) return true; } return false; } void NFacePairing::followChain(unsigned& tet, NFacePair& faces) const { NTetFace dest1, dest2; while (true) { // Does the first face lead to a real tetrahedron? if (isUnmatched(tet, faces.lower())) return; // Does the second face lead to the same tetrahedron as the first? dest1 = dest(tet, faces.lower()); dest2 = dest(tet, faces.upper()); if (dest1.simp != dest2.simp) return; // Do the two faces lead to a *different* tetrahedron? if (dest1.simp == static_cast(tet)) return; // Follow the chain along. tet = dest1.simp; faces = NFacePair(dest1.facet, dest2.facet).complement(); } } bool NFacePairing::hasBrokenDoubleEndedChain() const { // Search for the end edge of the first chain. unsigned baseTet; unsigned baseFace; // Skip the last tetrahedron -- any of the two ends will do. for (baseTet = 0; baseTet + 1 < size_; baseTet++) for (baseFace = 0; baseFace < 3; baseFace++) if (dest(baseTet, baseFace).simp == static_cast(baseTet)) { // Here's a face that matches to the same tetrahedron. if (hasBrokenDoubleEndedChain(baseTet, baseFace)) return true; // There's no sense in looking for more // self-identifications in this tetrahedron, since if // there's another (different) one it must be a // one-tetrahedron component (and so not applicable). break; } // Nothing found. Boring. return false; } bool NFacePairing::hasBrokenDoubleEndedChain(unsigned baseTet, unsigned baseFace) const { // Follow the chain along and see how far we get. NFacePair bdryFaces = NFacePair(baseFace, dest(baseTet, baseFace).facet).complement(); unsigned bdryTet = baseTet; followChain(bdryTet, bdryFaces); // Here's where we must diverge and move into the second chain. // We cannot glue the working pair of faces to each other. if (dest(bdryTet, bdryFaces.lower()).simp == static_cast(bdryTet)) return false; // Try each possible direction away from the working faces into the // second chain. NFacePair chainFaces; unsigned chainTet; NTetFace destFace; unsigned ignoreFace; int i; for (i = 0; i < 2; i++) { destFace = dest(bdryTet, i == 0 ? bdryFaces.lower() : bdryFaces.upper()); if (destFace.isBoundary(size_)) continue; for (ignoreFace = 0; ignoreFace < 4; ignoreFace++) { if (destFace.facet == static_cast(ignoreFace)) continue; // Try to follow the chain along from tetrahedron // destFace.simp, using the two faces that are *not* // destFace.facet or ignoreFace. chainTet = destFace.simp; chainFaces = NFacePair(destFace.facet, ignoreFace).complement(); followChain(chainTet, chainFaces); // Did we reach an end edge of the second chain? if (dest(chainTet, chainFaces.lower()).simp == static_cast(chainTet)) return true; } } // Nup. Nothing found. return false; } bool NFacePairing::hasOneEndedChainWithDoubleHandle() const { // Search for the end edge of the chain. unsigned baseTet; unsigned baseFace; for (baseTet = 0; baseTet < size_; baseTet++) for (baseFace = 0; baseFace < 3; baseFace++) if (dest(baseTet, baseFace).simp == static_cast(baseTet)) { // Here's a face that matches to the same tetrahedron. if (hasOneEndedChainWithDoubleHandle(baseTet, baseFace)) return true; // There's no sense in looking for more // self-identifications in this tetrahedron, since if // there's another (different) one it must be a // one-tetrahedron component (and so not applicable). break; } // Nothing found. Boring. return false; } bool NFacePairing::hasOneEndedChainWithDoubleHandle(unsigned baseTet, unsigned baseFace) const { // Follow the chain along and see how far we get. NFacePair bdryFaces = NFacePair(baseFace, dest(baseTet, baseFace).facet).complement(); unsigned bdryTet = baseTet; followChain(bdryTet, bdryFaces); // Here's where we must diverge and create the double handle. NTetFace dest1 = dest(bdryTet, bdryFaces.lower()); NTetFace dest2 = dest(bdryTet, bdryFaces.upper()); // These two faces must be joined to two distinct tetrahedra. if (dest1.simp == dest2.simp) return false; // They also cannot be boundary. if (dest1.isBoundary(size_) || dest2.isBoundary(size_)) return false; // Since they're joined to two distinct tetrahedra, they cannot be // joined to each other. So we can start hunting for the double handle. int handle = 0; for (int i = 0; i < 4; i++) if (dest(dest1.simp, i).simp == dest2.simp) handle++; // Did we find our double handle? return (handle >= 2); } bool NFacePairing::hasWedgedDoubleEndedChain() const { // Search for the end edge of the first chain. unsigned baseTet; unsigned baseFace; // Skip the last tetrahedron -- any of the two ends will do. for (baseTet = 0; baseTet + 1 < size_; baseTet++) for (baseFace = 0; baseFace < 3; baseFace++) if (dest(baseTet, baseFace).simp == static_cast(baseTet)) { // Here's a face that matches to the same tetrahedron. if (hasWedgedDoubleEndedChain(baseTet, baseFace)) return true; // There's no sense in looking for more // self-identifications in this tetrahedron, since if // there's another (different) one it must be a // one-tetrahedron component (and so not applicable). break; } // Nothing found. Boring. return false; } bool NFacePairing::hasWedgedDoubleEndedChain(unsigned baseTet, unsigned baseFace) const { // Follow the chain along and see how far we get. NFacePair bdryFaces = NFacePair(baseFace, dest(baseTet, baseFace).facet).complement(); unsigned bdryTet = baseTet; followChain(bdryTet, bdryFaces); // Here we expect to find the wedge. NTetFace dest1 = dest(bdryTet, bdryFaces.lower()); NTetFace dest2 = dest(bdryTet, bdryFaces.upper()); if (dest1.isBoundary(size_) || dest2.isBoundary(size_) || dest1.simp == dest2.simp) return false; // We are joined to two new and distinct graph vertices. // Hunt for the edge joining them, and also see where they follow // through to beyond these two new vertices. // Drawing a diagram whilst reading this code will certainly help. :) NTetFace throughFace[2][3]; int nThroughFaces[2]; nThroughFaces[0] = nThroughFaces[1] = 0; int i, j; NTetFace nextDest; bool foundCrossEdge = false; for (i = 0; i < 4; i++) { if (i != dest1.facet) { nextDest = dest(dest1.simp, i); if (nextDest.simp == dest2.simp) foundCrossEdge = true; else if (nextDest.simp != dest1.simp && ! nextDest.isBoundary(size_)) throughFace[0][nThroughFaces[0]++] = nextDest; } if (i != dest2.facet) { nextDest = dest(dest2.simp, i); if (nextDest.simp != dest1.simp && nextDest.simp != dest2.simp && ! nextDest.isBoundary(size_)) throughFace[1][nThroughFaces[1]++] = nextDest; } } if (! foundCrossEdge) return false; // We have our cross edge. // Moreover, all of the faces in throughFace[] belong to previously // unseen tetrahedra. // Hunt for the other half of the double-ended chain. NFacePair chainFaces; unsigned chainTet; for (i = 0; i < nThroughFaces[0]; i++) for (j = 0; j < nThroughFaces[1]; j++) if (throughFace[0][i].simp == throughFace[1][j].simp) { // Bingo. // Follow the chain and see if it ends in a loop. chainTet = throughFace[0][i].simp; chainFaces = NFacePair(throughFace[0][i].facet, throughFace[1][j].facet).complement(); followChain(chainTet, chainFaces); if (dest(chainTet, chainFaces.lower()).simp == static_cast(chainTet)) return true; } // Nothing found. return false; } bool NFacePairing::hasOneEndedChainWithStrayBigon() const { // Search for the end edge of the chain. unsigned baseTet; unsigned baseFace; for (baseTet = 0; baseTet < size_; baseTet++) for (baseFace = 0; baseFace < 3; baseFace++) if (dest(baseTet, baseFace).simp == static_cast(baseTet)) { // Here's a face that matches to the same tetrahedron. if (hasOneEndedChainWithStrayBigon(baseTet, baseFace)) return true; // There's no sense in looking for more // self-identifications in this tetrahedron, since if // there's another (different) one it must be a // one-tetrahedron component (and so not applicable). break; } // Nothing found. Boring. return false; } bool NFacePairing::hasOneEndedChainWithStrayBigon(unsigned baseTet, unsigned baseFace) const { // Follow the chain along and see how far we get. NFacePair bdryFaces = NFacePair(baseFace, dest(baseTet, baseFace).facet).complement(); unsigned bdryTet = baseTet; followChain(bdryTet, bdryFaces); // Here's where we must diverge and create the stray bigon. // We cannot glue the working pair of faces to each other. if (dest(bdryTet, bdryFaces.lower()).simp == static_cast(bdryTet)) return false; // Try each possible direction away from the working faces into the bigon. NFacePair bigonFaces; int bigonTet, farTet, extraTet; NTetFace destFace; unsigned ignoreFace; int i; for (i = 0; i < 2; i++) { destFace = dest(bdryTet, i == 0 ? bdryFaces.lower() : bdryFaces.upper()); if (destFace.isBoundary(size_)) continue; bigonTet = destFace.simp; for (ignoreFace = 0; ignoreFace < 4; ignoreFace++) { if (destFace.facet == static_cast(ignoreFace)) continue; // Look for a bigon running away from tetrahedron // destFace.simp, using the two faces that are *not* // destFace.facet or ignoreFace. bigonFaces = NFacePair(destFace.facet, ignoreFace).complement(); farTet = dest(bigonTet, bigonFaces.upper()).simp; if (farTet != bigonTet && farTet < static_cast(size_) /* non-bdry */ && farTet == dest(bigonTet, bigonFaces.lower()).simp) { // We have the bigon! // We know that bdryTet != bigonTet != farTet, and we // can prove that bdryTet != farTet using 4-valency. // Ensure that we don't have one of our special exceptions. extraTet = dest(bdryTet, i == 0 ? bdryFaces.upper() : bdryFaces.lower()).simp; // We know extraTet != bigonTet, since otherwise our // one-ended chain would not have stopped when it did. // We also know extraTet != bdryTet by 4-valency. if (extraTet == farTet || extraTet >= static_cast(size_) /* bdry */) return true; if (extraTet == dest(bigonTet, ignoreFace).simp) { // Could be the special case where extraTet joins to // all of bdryTet, bigonTet and farTet. // We already have it joined to bdryTet and bigonTet. // Check farTet. if (extraTet != dest(farTet, 0).simp && extraTet != dest(farTet, 1).simp && extraTet != dest(farTet, 2).simp && extraTet != dest(farTet, 3).simp) return true; } else { // Could be the special case where extraTet joins // twice to farTet. If not, we have the type of // graph we're looking for. bigonFaces = NFacePair( dest(bigonTet, bigonFaces.upper()).facet, dest(bigonTet, bigonFaces.lower()).facet).complement(); if (extraTet != dest(farTet, bigonFaces.upper()).simp || extraTet != dest(farTet, bigonFaces.lower()).simp) return true; } } } } // Nup. Nothing found. return false; } bool NFacePairing::hasTripleOneEndedChain() const { // Search for the end edge of the first chain. unsigned baseTet; unsigned baseFace; // Skip the last two tetrahedra -- any of the three chains will do. for (baseTet = 0; baseTet + 2 < size_; baseTet++) for (baseFace = 0; baseFace < 3; baseFace++) if (dest(baseTet, baseFace).simp == static_cast(baseTet)) { // Here's a face that matches to the same tetrahedron. if (hasTripleOneEndedChain(baseTet, baseFace)) return true; // There's no sense in looking for more // self-identifications in this tetrahedron, since if // there's another (different) one it must be a // one-tetrahedron component (and so not applicable). break; } // Nothing found. Boring. return false; } bool NFacePairing::hasTripleOneEndedChain(unsigned baseTet, unsigned baseFace) const { // Follow the chain along and see how far we get. NFacePair bdryFaces = NFacePair(baseFace, dest(baseTet, baseFace).facet).complement(); unsigned bdryTet = baseTet; followChain(bdryTet, bdryFaces); // Here's where we must diverge and hunt for the other two chains. // We cannot glue the working pair of faces to each other. if (dest(bdryTet, bdryFaces.lower()).simp == static_cast(bdryTet)) return false; NTetFace axis1 = dest(bdryTet, bdryFaces.lower()); NTetFace axis2 = dest(bdryTet, bdryFaces.upper()); if (axis1.isBoundary(size_) || axis2.isBoundary(size_)) return false; // We know axis1.simp != axis2.simp because the chain stopped, but // just in case.. if (axis1.simp == axis2.simp) return false; // Count the number of other chains coming from axis1 and axis2. int exit1, exit2; NTetFace arrive1, arrive2; int nChains = 1; unsigned newChainTet; NFacePair newChainFaces; for (exit1 = 0; exit1 < 4; exit1++) { if (exit1 == axis1.facet) continue; arrive1 = dest(axis1.simp, exit1); if (arrive1.simp == static_cast(bdryTet) || arrive1.simp == axis1.simp || arrive1.simp == axis2.simp || arrive1.isBoundary(size_)) continue; for (exit2 = 0; exit2 < 4; exit2++) { if (exit2 == axis2.facet) continue; arrive2 = dest(axis2.simp, exit2); if (arrive2.simp != arrive1.simp) continue; // We have graph edges from axis1 and axis2 to a common vertex, // which is not part of our original chain and is neither axis1 // nor axis2. // See if there's a (possibly zero-length) chain we can // follow to a loop. newChainTet = arrive1.simp; newChainFaces = NFacePair(arrive1.facet, arrive2.facet). complement(); followChain(newChainTet, newChainFaces); if (dest(newChainTet, newChainFaces.lower()).simp == static_cast(newChainTet)) { // Got one! if (++nChains == 3) return true; } } } // Nope. Not enough chains were found. return false; } bool NFacePairing::hasSingleStar() const { int half[4], all[8]; unsigned first, second; unsigned f1, f2; int i; // Skip the last tetrahedron, since we're already testing every // possibility from both sides. for (first = 0; first + 1 < size_; first++) { // All four neighbours must be non-boundary and distinct. for (f1 = 0; f1 < 4; f1++) { half[f1] = dest(first, f1).simp; if (half[f1] >= static_cast(size_) /* bdry */) break; } if (f1 < 4) continue; std::sort(half, half + 4); if (half[0] == half[1] || half[1] == half[2] || half[2] == half[3]) continue; // Look for the adjacent neighbour. for (f1 = 0; f1 < 4; f1++) { second = dest(first, f1).simp; // Now ensure that all eight faces are non-boundary and distinct. for (f2 = 0; f2 < 4; f2++) { all[f2 + 4] = dest(second, f2).simp; if (all[f2 + 4] >= static_cast(size_) /* bdry */) break; } if (f2 < 4) continue; // We have to refresh the first half of the all[] array each // time, since every time we sort all[] we mix the first // tetrahedron's neighbours in with the second tetrahedron's // neighbours. std::copy(half, half + 4, all); std::sort(all, all + 8); for (i = 0; i < 7; i++) if (all[i] == all[i + 1]) break; if (i >= 7) return true; } } return false; } bool NFacePairing::hasDoubleStar() const { int all[7]; unsigned first, second; int f, i; // Skip the last tetrahedron, since we're already testing every // possibility from both sides. for (first = 0; first + 1 < size_; first++) { // All four neighbours must be non-boundary, and three must be // distinct. for (f = 0; f < 4; f++) { all[f] = dest(first, f).simp; if (all[f] >= static_cast(size_) /* bdry */) break; } if (f < 4) continue; std::sort(all, all + 4); // Find the double edge, and move the three distinct tetrahedra // to the beginning of the array. if (all[0] == all[1] && all[1] != all[2] && all[2] != all[3]) { second = all[0]; all[0] = all[3]; } else if (all[0] != all[1] && all[1] == all[2] && all[2] != all[3]) { second = all[1]; all[1] = all[3]; } else if (all[0] != all[1] && all[1] != all[2] && all[2] == all[3]) { second = all[2]; } else continue; // Now look at the edges coming out from the second tetrahedron. for (f = 0; f < 4; f++) { all[f + 3] = dest(second, f).simp; if (all[f + 3] >= static_cast(size_) /* bdry */) break; } if (f < 4) continue; // Look for duplicates. We should only have a single duplicate // pair, this being two copies of first. std::sort(all, all + 7); for (i = 0; i < 6; i++) if (all[i] == all[i + 1]) { if (all[i] != static_cast(first)) break; if (i < 5 && all[i] == all[i + 2]) break; } if (i >= 6) return true; } return false; } bool NFacePairing::hasDoubleSquare() const { unsigned t1; NTetFace t2; int join, fa, fb; int adj1 = 0, adj2 = 0; bool found; // Skip the last three tetrahedra -- any of the four starting points // will do. for (t1 = 0; t1 + 3 < size_; t1++) for (join = 0; join < 4; join++) { t2 = dest(t1, join); if (t2.simp == static_cast(t1) || t2.isBoundary(size_)) continue; // We have distinct t1, t2 adjacent. // Search for double edges leaving t1 and t2 for two new // tetrahedra. found = false; for (fa = 0; fa < 3 && ! found; fa++) { if (fa == join) continue; adj1 = dest(t1, fa).simp; if (adj1 >= static_cast(size_) /* bdry */) continue; if (adj1 == static_cast(t1) || adj1 == t2.simp) continue; for (fb = fa + 1; fb < 4; fb++) { if (fb == join) continue; if (adj1 == dest(t1, fb).simp) { found = true; break; } } } if (! found) continue; found = false; for (fa = 0; fa < 3 && ! found; fa++) { if (fa == t2.facet) continue; adj2 = dest(t2.simp, fa).simp; if (adj2 >= static_cast(size_) /* bdry */) continue; if (adj2 == static_cast(t1) || adj2 == t2.simp || adj2 == adj1) continue; for (fb = fa + 1; fb < 4; fb++) { if (fb == t2.facet) continue; if (adj2 == dest(t2.simp, fb).simp) { found = true; break; } } } if (! found) continue; // All we need now is a link between adj1 and adj2. for (fa = 0; fa < 4; fa++) if (dest(adj1, fa).simp == adj2) return true; } // Nothing found. return false; } } // namespace regina regina-4.96/engine/census/nfacepairing.h000644 000765 000024 00000063621 12377774654 020212 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file census/nfacepairing.h * \brief Deals with pairing off tetrahedron faces in a census of * 3-manifold triangulations. */ #ifndef __NFACEPAIRING_H #ifndef __DOXYGEN #define __NFACEPAIRING_H #endif #include "regina-core.h" #include "census/ngenericfacetpairing.h" #include "triangulation/nisomorphism.h" namespace regina { class NFacePair; /** * \weakgroup census * @{ */ /** * A legacy typedef provided for backward compatibility only. * * \deprecated As of Regina 4.94, this typedef is now available as * NFacePairing::IsoList. The old typedef NFacePairingIsoList is * provided for backward compatibility, but will be removed in some * future version of Regina. */ typedef std::list NFacePairingIsoList; /** * A legacy typedef provided for backward compatibility only. * * \deprecated As of Regina 4.94, this typedef is now available as * NFacePairing::Use. The old typedef UseFacePairing is * provided for backward compatibility, but will be removed in some * future version of Regina. */ typedef void (*UseFacePairing)(const NFacePairing*, const NFacePairingIsoList*, void*); /** * Represents a specific pairwise matching of tetrahedron faces. * Given a fixed number of tetrahedra, each tetrahedron face is either * paired with some other tetrahedron face (which is in turn paired with * it) or remains unmatched. A tetrahedron face cannot be paired with * itself. * * Such a matching models part of the structure of a triangulation, in * which each tetrahedron face is either glued to some other tetrahedron * face (which is in turn glued to it) or is an unglued boundary face. * * Note that if this pairing is used to construct an actual * triangulation, the individual gluing permutations will still need to * be specified; they are not a part of this structure. */ class REGINA_API NFacePairing : public NGenericFacetPairing<3> { public: /** * Creates a new face pairing that is a clone of the given face * pairing. * * @param cloneMe the face pairing to clone. */ NFacePairing(const NFacePairing& cloneMe); /** * Creates the face pairing of the given 3-manifold triangulation. * This is the face pairing that describes how the tetrahedron faces * of the given triangulation are joined together, as described in the * class notes. * * \pre The given triangulation is not empty. * * @param tri the triangulation whose face pairing should be * constructed. */ NFacePairing(const NTriangulation& tri); /** * A legacy alias for size(), provided for backward * compatibility only. * * This routine returns the number of tetrahedra whose faces are * described by this face pairing. * * \deprecated As of Regina 4.94, this routine has been renamed * to size(). The old name getNumberOfTetrahedra() is provided * for backward compatibility, but will be removed in some future * version of Regina. * * @return the number of tetrahedra under consideration. */ unsigned getNumberOfTetrahedra() const; /** * Follows a chain as far as possible from the given point. * * A chain is the underlying face pairing for a layered chain; * specifically it involves one tetrahedron joined to a second * along two faces, the remaining two faces of the second * tetrahedron joined to a third and so on. A chain can involve * as few as one tetrahedron or as many as we like. Note that * the remaining two faces of the first tetrahedron and the * remaining two faces of the final tetrahedron remain * unaccounted for by this structure. * * This routine begins with two faces of a given tetrahedron, * described by parameters \a tet and \a faces. * If these two faces are both joined to some different * tetrahedron, parameter \a tet will be changed to this new * tetrahedron and parameter \a faces will be changed to the * remaining faces of this new tetrahedron (i.e., the two faces * that were not joined to the original faces of the original * tetrahedron). * * This procedure is repeated as far as possible until either * the two faces in question join to two different tetrahedra, * the two faces join to each other, or at least one of the * two faces is unmatched. * * Thus, given one end of a chain, this procedure can be used to * follow the face pairings through to the other end of the chain. * * \warning You must be sure when calling this routine that you * are not inside a chain that loops back onto itself! * If the face pairing forms a * large loop with each tetrahedron joined by two faces to the * next, this routine will cycle around the loop forever and * never return. * * @param tet the index in the underlying triangulation of the * tetrahedron to begin at. This parameter will be modified * directly by this routine as a way of returning the results. * @param faces the pair of face numbers in the given * tetrahedron at which we begin. This parameter will also be * modified directly by this routine as a way of returning results. */ void followChain(unsigned& tet, NFacePair& faces) const; /** * Determines whether this face pairing contains a triple edge. * A triple edge is where two different tetrahedra are joined * along three of their faces. * * A face pairing containing a triple edge cannot model a closed * minimal irreducible P^2-irreducible 3-manifold triangulation on * more than two tetrahedra. See "Face pairing graphs and 3-manifold * enumeration", Benjamin A. Burton, J. Knot Theory Ramifications * 13 (2004), 1057--1101. * * @return \c true if and only if this face pairing contains a * triple edge. */ bool hasTripleEdge() const; /** * Determines whether this face pairing contains a broken * double-ended chain. * * A chain involves a sequence of tetrahedra, each joined to the * next along two faces, and is described in detail in the * documentation for followChain(). * * A one-ended chain is a chain in which the first tetrahedron * is also joined to itself along one face (i.e., the underlying * face pairing for a layered solid torus). A double-ended * chain is a chain in which the first tetrahedron is joined to * itself along one face and the final tetrahedron is also * joined to itself along one face (i.e., the underlying * face pairing for a layered lens space). * * A broken double-ended chain consists of two one-ended chains * (using distinct sets of tetrahedra) joined together along one * face. The remaining two faces (one from each chain) * that were unaccounted for by the individual one-ended chains * remain unaccounted for by this broken double-ended chain. * * In this routine we are interested specifically in finding a * broken double-ended chain that is not a part of a complete * double-ended chain, i.e., the final two unaccounted faces are * not joined together. * * A face pairing containing a broken double-ended chain cannot * model a closed minimal irreducible P^2-irreducible 3-manifold * triangulation on more than two tetrahedra. See "Face pairing * graphs and 3-manifold enumeration", Benjamin A. Burton, * J. Knot Theory Ramifications 13 (2004), 1057--1101. * * @return \c true if and only if this face pairing contains a * broken double-ended chain that is not part of a complete * double-ended chain. */ bool hasBrokenDoubleEndedChain() const; /** * Determines whether this face pairing contains a one-ended chain * with a double handle. * * A chain involves a sequence of tetrahedra, each joined to the * next along two faces, and is described in detail in the * documentation for followChain(). * * A one-ended chain is a chain in which the first tetrahedron * is also joined to itself along one face (i.e., the underlying * face pairing for a layered solid torus). * * A one-ended chain with a double handle begins with a one-ended * chain. The two faces that are unaccounted for by this * one-ended chain must be joined * to two different tetrahedra, and these two tetrahedra must be * joined to each other along two faces. The remaining two * faces of these two tetrahedra remain unaccounted for by this * structure. * * A face pairing containing a one-ended chain with a double handle * cannot model a closed minimal irreducible P^2-irreducible * 3-manifold triangulation on more than two tetrahedra. See * "Face pairing graphs and 3-manifold enumeration", * Benjamin A. Burton, J. Knot Theory Ramifications 13 (2004), * 1057--1101. * * @return \c true if and only if this face pairing contains a * one-ended chain with a double handle. */ bool hasOneEndedChainWithDoubleHandle() const; /** * Determines whether this face pairing contains a wedged * double-ended chain. * * A chain involves a sequence of tetrahedra, each joined to the * next along two faces, and is described in detail in the * documentation for followChain(). * * A one-ended chain is a chain in which the first tetrahedron * is also joined to itself along one face (i.e., the underlying * face pairing for a layered solid torus). A double-ended * chain is a chain in which the first tetrahedron is joined to * itself along one face and the final tetrahedron is also * joined to itself along one face (i.e., the underlying * face pairing for a layered lens space). * * A wedged double-ended chain is created from two one-ended * chains as follows. Two new tetrahedra are added, and each * one-ended chain is joined to each of the new tetrahedra along * a single face. In addition, the two new tetrahedra are * joined to each other along a single face. The remaining two * faces (one from each of the new tetrahedra) remain * unaccounted for by this structure. * * An alternative way of viewing a wedged double-ended chain is * as an ordinary double-ended chain, where one of the internal * tetrahedra is removed and replaced with a pair of tetrahedra * joined to each other. Whereas the original tetrahedron met its * two neighbouring tetrahedra along two faces each (giving a * total of four face identifications), the two new tetrahedra now * meet each of the two neighbouring tetrahedra along a single * face each (again giving four face identifications). * * Note that if this alternate construction is used to replace * one of the end tetrahedra of the double-ended chain (not an * internal tetrahedron), the resulting structure will either be * a triple edge or a one-ended chain with a double handle * (according to whether the original chain has zero or positive * length). See hasTripleEdge() and * hasOneEndedChainWithDoubleHandle() for further details. * * A face pairing containing a wedged double-ended chain * cannot model a closed minimal irreducible P^2-irreducible * 3-manifold triangulation on more than two tetrahedra. See * "Enumeration of non-orientable 3-manifolds using face-pairing * graphs and union-find", Benjamin A. Burton, * Discrete Comput. Geom. 38 (2007), no. 3, 527--571. * * @return \c true if and only if this face pairing contains a * wedged double-ended chain. */ bool hasWedgedDoubleEndedChain() const; /** * Determines whether this face pairing contains a one-ended * chain with a stray bigon. * * A chain involves a sequence of tetrahedra, each joined to the * next along two faces, and is described in detail in the * documentation for followChain(). * * A one-ended chain is a chain in which the first tetrahedron * is also joined to itself along one face (i.e., the underlying * face pairing for a layered solid torus). * * A one-ended chain with a stray bigon describes the following * structure. We begin with a one-ended chain. Two new * tetrahedra are added; these are joined to each other along * two pairs of faces, and one of the new tetrahedra is joined * to the end of the one-ended chain. We then ensure that: * - This configuration is not part of a longer one-ended chain * that encompasses all of the aforementioned tetrahedra; * - There is no extra tetrahedron that is joined to both the * two new tetrahedra and the end of the chain; * - There is no extra tetrahedron that is joined to the end of * the chain along one face and the far new tetrahedron along * two additional faces (where by "the far new tetrahedron" * we mean the new tetrahedron that was not originally joined to * the chain). * * Aside from these constraints, the remaining four tetrahedron faces * (two faces of the far new tetrahedron, one face of the other new * tetrahedron, and one face at the end of the chain) remain * unaccounted for by this structure. * * A face pairing containing a structure of this type * cannot model a closed minimal irreducible P^2-irreducible * 3-manifold triangulation on more than two tetrahedra. See * "Enumeration of non-orientable 3-manifolds using face-pairing * graphs and union-find", Benjamin A. Burton, * Discrete Comput. Geom. 38 (2007), no. 3, 527--571. * * @return \c true if and only if this face pairing contains a * one-ended chain with a stray bigon. */ bool hasOneEndedChainWithStrayBigon() const; /** * Determines whether this face pairing contains a triple * one-ended chain. * * A chain involves a sequence of tetrahedra, each joined to the * next along two faces, and is described in detail in the * documentation for followChain(). * * A one-ended chain is a chain in which the first tetrahedron * is also joined to itself along one face (i.e., the underlying * face pairing for a layered solid torus). * * A triple one-ended chain is created from three one-ended * chains as follows. Two new tetrahedra are added, and each * one-ended chain is joined to each of the new tetrahedra along * a single face. The remaining two faces (one from each of the * new tetrahedra) remain unaccounted for by this structure. * * A face pairing containing a triple one-ended chain * cannot model a closed minimal irreducible P^2-irreducible * 3-manifold triangulation on more than two tetrahedra. See * "Enumeration of non-orientable 3-manifolds using face-pairing * graphs and union-find", Benjamin A. Burton, * Discrete Comput. Geom. 38 (2007), no. 3, 527--571. * * @return \c true if and only if this face pairing contains a * triple one-ended chain. */ bool hasTripleOneEndedChain() const; /** * Determines whether this face pairing contains a single-edged * star. * * A single-edged star involves two tetrahedra that are adjacent * along a single face, where the six remaining faces of these * tetrahedra are joined to six entirely new tetrahedra (so that * none of the eight tetrahedra described in this structure are * the same). * * @return \c true if and only if this face pairing contains a * single-edged star. */ bool hasSingleStar() const; /** * Determines whether this face pairing contains a double-edged * star. * * A double-edged star involves two tetrahedra that are adjacent * along two separate pairs of faces, where the four remaining * faces of these tetrahedra are joined to four entirely new * tetrahedra (so that none of the six tetrahedra described in * this structure are the same). * * @return \c true if and only if this face pairing contains a * double-edged star. */ bool hasDoubleStar() const; /** * Determines whether this face pairing contains a double-edged * square. * * A double-edged square involves four distinct tetrahedra that * meet each other as follows. Two pairs of tetrahedra are * joined along two pairs of faces each. Then each tetrahedron * is joined along a single face to one tetrahedron of the other * pair. The four tetrahedron faces not yet joined to anything * (one from each tetrahedron) remain unaccounted for by this * structure. * * @return \c true if and only if this face pairing contains a * double-edged square. */ bool hasDoubleSquare() const; private: /** * Creates a new face pairing. All internal arrays will be * allocated but not initialised. * * \pre \a nTetrahedra is at least 1. * * @param nTetrahedra the number of tetrahedra under * consideration in this new face pairing. */ NFacePairing(unsigned nTetrahedra); /** * Internal to hasBrokenDoubleEndedChain(). This routine assumes * that the give face of the given tetrahedron is glued to this * same tetrahedron, and attempts to find a broken double-ended * chain for which this tetrahedron is at the end of one of the * one-ended chains therein. * * \pre The given face of the given tetrahedron is paired with * another face of the same tetrahedron under this face pairing. * * @param tet the index in the triangulation of the given * tetrahedron. * @param face the number of the given face in the tetrahedron; * this must be between 0 and 3 inclusive. * * @return \c true if and only if this face pairing contains a * broken double-ended chain as described above. */ bool hasBrokenDoubleEndedChain(unsigned tet, unsigned face) const; /** * Internal to hasOneEndedChainWithDoubleHandle(). This routine * assumes that the give face of the given tetrahedron is glued * to this same tetrahedron, and attempts to find a one-ended * chain with a double handle for which this tetrahedron is at * the end of the chain contained therein. * * \pre The given face of the given tetrahedron is paired with * another face of the same tetrahedron under this face pairing. * * @param tet the index in the triangulation of the given * tetrahedron. * @param face the number of the given face in the tetrahedron; * this must be between 0 and 3 inclusive. * * @return \c true if and only if this face pairing contains a * one-ended chain with a double handle as described above. */ bool hasOneEndedChainWithDoubleHandle(unsigned tet, unsigned face) const; /** * Internal to hasWedgedDoubleEndedChain(). This routine assumes * that the give face of the given tetrahedron is glued to this * same tetrahedron, and attempts to find a wedged double-ended * chain for which this tetrahedron is at one end of the * double-ended chain. * * \pre The given face of the given tetrahedron is paired with * another face of the same tetrahedron under this face pairing. * * @param tet the index in the triangulation of the given * tetrahedron. * @param face the number of the given face in the tetrahedron; * this must be between 0 and 3 inclusive. * * @return \c true if and only if this face pairing contains a * wedged double-ended chain as described above. */ bool hasWedgedDoubleEndedChain(unsigned tet, unsigned face) const; /** * Internal to hasOneEndedChainWithStrayBigon(). This routine assumes * that the give face of the given tetrahedron is glued to this * same tetrahedron, and attempts to find a one-ended chain with * stray bigon for which this tetrahedron is at the end of the * one-ended chain. * * \pre The given face of the given tetrahedron is paired with * another face of the same tetrahedron under this face pairing. * * @param tet the index in the triangulation of the given * tetrahedron. * @param face the number of the given face in the tetrahedron; * this must be between 0 and 3 inclusive. * * @return \c true if and only if this face pairing contains a * one-ended chain with stray bigon as described above. */ bool hasOneEndedChainWithStrayBigon(unsigned tet, unsigned face) const; /** * Internal to hasTripleOneEndedChain(). This routine assumes * that the give face of the given tetrahedron is glued to this * same tetrahedron, and attempts to find a triple one-ended * chain for which this tetrahedron is at the end of one of the * individual one-ended chains. * * \pre The given face of the given tetrahedron is paired with * another face of the same tetrahedron under this face pairing. * * @param tet the index in the triangulation of the given * tetrahedron. * @param face the number of the given face in the tetrahedron; * this must be between 0 and 3 inclusive. * * @return \c true if and only if this face pairing contains a * triple one-ended chain as described above. */ bool hasTripleOneEndedChain(unsigned tet, unsigned face) const; // Make sure the parent class can call the private constructor. friend class NGenericFacetPairing<3>; }; /*@}*/ // Inline functions for NFacePairing inline NFacePairing::NFacePairing(const NFacePairing& cloneMe) : NGenericFacetPairing<3>(cloneMe) { } inline NFacePairing::NFacePairing(const NTriangulation& tri) : NGenericFacetPairing<3>(tri) { } inline NFacePairing::NFacePairing(unsigned nTetrahedra) : NGenericFacetPairing<3>(nTetrahedra) { } inline unsigned NFacePairing::getNumberOfTetrahedra() const { return size_; } } // namespace regina #endif regina-4.96/engine/census/ngenericfacetpairing-impl.h000644 000765 000024 00000077056 12377774656 022703 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /* Template definitions for ngenericfacetpairing.h. */ #include #include #include #include "census/ngenericfacetpairing.h" #include "utilities/memutils.h" #include "utilities/stringutils.h" namespace regina { template NGenericFacetPairing::NGenericFacetPairing( const NGenericFacetPairing& cloneMe) : NThread(), size_(cloneMe.size_), pairs_(new NFacetSpec[cloneMe.size_ * (dim + 1)]) { std::copy(cloneMe.pairs_, cloneMe.pairs_ + (size_ * (dim + 1)), pairs_); } template NGenericFacetPairing::NGenericFacetPairing( const typename NGenericFacetPairing::Triangulation& tri) : size_(tri.getNumberOfSimplices()), pairs_(new NFacetSpec[tri.getNumberOfSimplices() * (dim + 1)]) { unsigned p, f, index; const Simplex *simp, *adj; for (index = 0, p = 0; p < size_; ++p) { simp = tri.getSimplex(p); for (f = 0; f <= dim; ++f) { adj = simp->adjacentSimplex(f); if (adj) { pairs_[index].simp = tri.simplexIndex(adj); pairs_[index].facet = simp->adjacentFacet(f); } else pairs_[index].setBoundary(size_); ++index; } } } template bool NGenericFacetPairing::isClosed() const { for (NFacetSpec f(0, 0); ! f.isPastEnd(size_, true); ++f) if (isUnmatched(f)) return false; return true; } template std::string NGenericFacetPairing::str() const { std::ostringstream ans; for (NFacetSpec f(0, 0); ! f.isPastEnd(size_, true); ++f) { if (f.facet == 0 && f.simp > 0) ans << " | "; else if (f.simp || f.facet) ans << ' '; if (dest(f).isBoundary(size_)) ans << "bdry"; else ans << dest(f).simp << ':' << dest(f).facet; } return ans.str(); } template std::string NGenericFacetPairing::dotHeader(const char* graphName) { std::ostringstream ans; writeDotHeader(ans, graphName); return ans.str(); } template void NGenericFacetPairing::writeDotHeader( std::ostream& out, const char* graphName) { static const char defaultGraphName[] = "G"; if ((! graphName) || (! *graphName)) graphName = defaultGraphName; out << "graph " << graphName << " {" << std::endl; out << "graph [bgcolor=white];" << std::endl; out << "edge [color=black];" << std::endl; out << "node [shape=circle,style=filled,height=0.15,fixedsize=true,label=\"\",fontsize=9,fontcolor=\"#751010\"];" << std::endl; } template std::string NGenericFacetPairing::dot( const char* prefix, bool subgraph, bool labels) const { std::ostringstream ans; writeDot(ans, prefix, subgraph, labels); return ans.str(); } template void NGenericFacetPairing::writeDot(std::ostream& out, const char* prefix, bool subgraph, bool labels) const { static const char defaultPrefix[] = "g"; if ((! prefix) || (! *prefix)) prefix = defaultPrefix; // We are guaranteed that prefix is a non-empty string. if (subgraph) out << "subgraph pairing_" << prefix << " {" << std::endl; else writeDotHeader(out, (prefix + std::string("_graph")).c_str()); // Ancient versions of graphviz seem to ignore the default label="". // Make this explicit for each node. unsigned p; for (p = 0; p < size_; ++p) { out << prefix << '_' << p << " [label=\""; if (labels) out << p; out << "\"]" << std::endl; } int f; NFacetSpec adj; for (p = 0; p < size_; ++p) for (f = 0; f < (dim + 1); ++f) { adj = dest(p, f); if (adj.isBoundary(size_) || adj.simp < static_cast(p) || (adj.simp == static_cast(p) && adj.facet < f)) continue; out << prefix << '_' << p << " -- " << prefix << '_' << adj.simp << ';' << std::endl; } out << '}' << std::endl; } template std::string NGenericFacetPairing::toTextRep() const { std::ostringstream ans; for (NFacetSpec f(0, 0); ! f.isPastEnd(size_, true); ++f) { if (f.simp || f.facet) ans << ' '; ans << dest(f).simp << ' ' << dest(f).facet; } return ans.str(); } template typename NGenericFacetPairing::FacetPairing* NGenericFacetPairing::fromTextRep(const std::string& rep) { std::vector tokens; unsigned nTokens = basicTokenise(back_inserter(tokens), rep); if (nTokens == 0 || nTokens % (2 * (dim + 1)) != 0) return 0; long nSimp = nTokens / (2 * (dim + 1)); FacetPairing* ans = new FacetPairing(nSimp); // Read the raw values. // Check the range of each value while we're at it. long val; for (long i = 0; i < nSimp * (dim + 1); ++i) { if (! valueOf(tokens[2 * i], val)) { delete ans; return 0; } if (val < 0 || val > nSimp) { delete ans; return 0; } ans->pairs_[i].simp = val; if (! valueOf(tokens[2 * i + 1], val)) { delete ans; return 0; } if (val < 0 || val >= (dim + 1)) { delete ans; return 0; } ans->pairs_[i].facet = val; } // Run a sanity check. NFacetSpec destFacet; bool broken = false; for (NFacetSpec f(0, 0); ! f.isPastEnd(nSimp, true); ++f) { destFacet = ans->dest(f); if (destFacet.simp == nSimp && destFacet.facet != 0) broken = true; else if (destFacet.simp < nSimp && ! (ans->dest(destFacet) == f)) broken = true; else continue; break; } if (broken) { delete ans; return 0; } // All is well. return ans; } template bool NGenericFacetPairing::isCanonical() const { // Check the preconditions for isCanonicalInternal(). unsigned simp, facet; for (simp = 0; simp < size_; ++simp) { for (facet = 0; facet < dim; ++facet) if (dest(simp, facet + 1) < dest(simp, facet)) if (! (dest(simp, facet + 1) == NFacetSpec(simp, facet))) return false; if (simp > 0) if (dest(simp, 0).simp >= static_cast(simp)) return false; if (simp > 1) if (dest(simp, 0) <= dest(simp - 1, 0)) return false; } // We've met all the preconditions, so we can now run // isCanonicalInternal(). IsoList list; return isCanonicalInternal(list); } template bool NGenericFacetPairing::isCanonicalInternal( typename NGenericFacetPairing::IsoList& list) const { // Create the automorphisms one simplex at a time, selecting the // preimage of 0 first, then the preimage of 1 and so on. // We want to cycle through all possible first facet gluings, so we'll // special-case the situation in which there are no facet gluings at all. if (isUnmatched(0, 0)) { // We must have just one simplex with no facet gluings at all. Isomorphism* ans; for (int i = 0; i < Perm::nPerms; ++i) { ans = new Isomorphism(1); ans->simpImage(0) = 0; ans->facetPerm(0) = Perm::Sn[i]; list.push_back(ans); } return true; } // Now we know that facet 0 of simplex 0 is glued to something. NFacetSpec* image = new NFacetSpec[size_ * (dim + 1)]; /**< The automorphism currently under construction. */ NFacetSpec* preImage = new NFacetSpec[size_ * (dim + 1)]; /**< The inverse of this automorphism. */ unsigned i, j; for (i = 0; i < size_ * (dim + 1); ++i) { image[i].setBeforeStart(); preImage[i].setBeforeStart(); } // Note that we know size_ >= 1. // For the preimage of facet 0 of simplex 0 we simply cycle // through all possibilities. const NFacetSpec firstFace(0, 0); const NFacetSpec firstFaceDest(dest(firstFace)); NFacetSpec firstDestPre; NFacetSpec trying; NFacetSpec fImg, fPre; bool stepDown; int simp, facet; int permImg[dim + 1]; for (preImage[0] = firstFace ; ! preImage[0].isPastEnd(size_, true); ++preImage[0]) { // Note that we know firstFace is not unmatched. if (isUnmatched(preImage[0])) continue; // If firstFace glues to the same simplex and this facet // doesn't, we can ignore this permutation. firstDestPre = dest(preImage[0]); if (firstFaceDest.simp == 0 && firstDestPre.simp != preImage[0].simp) continue; // If firstFace doesn't glue to the same simplex but this // facet does, we're not in canonical form. if (firstFaceDest.simp != 0 && firstDestPre.simp == preImage[0].simp) { for_each(list.begin(), list.end(), FuncDelete()); list.clear(); delete[] image; delete[] preImage; return false; } // We can use this facet. Set the corresponding reverse mapping // and off we go. image[preImage[0].simp * (dim + 1) + preImage[0].facet] = firstFace; preImage[firstFaceDest.simp * (dim + 1) + firstFaceDest.facet] = firstDestPre; image[firstDestPre.simp * (dim + 1) + firstDestPre.facet] = firstFaceDest; // Step forwards to the next facet whose preimage is undetermined. trying = firstFace; ++trying; if (trying == firstFaceDest) ++trying; while (! (trying == firstFace)) { // INV: We've successfully selected preimages for all facets // before trying. We're currently looking at the last // attempted candidate for the preimage of trying. // Note that if preimage facet A is glued to preimage facet B // and the image of A is earlier than the image of B, then // the image of A will be selected whereas the image of B // will be automatically derived. stepDown = false; NFacetSpec& pre = preImage[trying.simp * (dim + 1) + trying.facet]; if (trying.isPastEnd(size_, true)) { // We have a complete automorphism! Isomorphism* ans = new Isomorphism(size_); for (i = 0; i < size_; i++) { ans->simpImage(i) = image[i * (dim + 1)].simp; for (j = 0; j <= dim; ++j) permImg[j] = image[i * (dim + 1) + j].facet; ans->facetPerm(i) = Perm(permImg); } list.push_back(ans); stepDown = true; } else { // Move to the next candidate. if (pre.simp >= 0 && pre.facet == dim) { // We're all out of candidates. pre.setBeforeStart(); stepDown = true; } else { if (pre.isBeforeStart()) { // Which simplex must we look in? // Note that this simplex will already have been // determined. pre.simp = preImage[trying.simp * (dim + 1)].simp; pre.facet = 0; } else ++pre.facet; // Step forwards until we have a preimage whose image // has not already been set. // If the preimage is unmatched and trying isn't, // we'll also skip it. // If trying is unmatched and the preimage isn't, // we're not in canonical form. for ( ; pre.facet <= dim; ++pre.facet) { if (! image[pre.simp * (dim + 1) + pre.facet]. isBeforeStart()) continue; if ((! isUnmatched(trying)) && isUnmatched(pre)) continue; if (isUnmatched(trying) && (! isUnmatched(pre))) { // We're not in canonical form. for_each(list.begin(), list.end(), FuncDelete()); list.clear(); delete[] image; delete[] preImage; return false; } break; } while (pre.facet <= dim && ! image[pre.simp * (dim + 1) + pre.facet]. isBeforeStart()) ++pre.facet; if (pre.facet == (dim + 1)) { pre.setBeforeStart(); stepDown = true; } } } if (! stepDown) { // We found a candidate. // We also know that trying is unmatched iff the preimage // is unmatched. image[pre.simp * (dim + 1) + pre.facet] = trying; if (! isUnmatched(pre)) { fPre = dest(pre); if (image[fPre.simp * (dim + 1) + fPre.facet]. isBeforeStart()) { // The image of fPre (the partner of the preimage // facet) can be determined at this point. // Specifically, it should go into the next // available slot. // Do we already know which simplex we should // be looking into? for (i = 0; i <= dim; i++) if (! image[fPre.simp * (dim + 1) + i]. isBeforeStart()) { // Here's the simplex! // Find the first available facet. simp = image[fPre.simp * (dim + 1) + i].simp; for (facet = 0; ! preImage[simp * (dim + 1) + facet]. isBeforeStart(); ++facet) ; image[fPre.simp * (dim + 1) + fPre.facet].simp = simp; image[fPre.simp * (dim + 1) + fPre.facet].facet = facet; break; } if (i == (dim + 1)) { // We need to map to a new simplex. // Find the first available simplex. for (simp = trying.simp + 1; ! preImage[simp * (dim + 1)]. isBeforeStart(); ++simp) ; image[fPre.simp * (dim + 1) + fPre.facet].simp = simp; image[fPre.simp * (dim + 1) + fPre.facet].facet = 0; } // Set the corresponding preimage. fImg = image[fPre.simp * (dim + 1) + fPre.facet]; preImage[fImg.simp * (dim + 1) + fImg.facet] = fPre; } } // Do a lexicographical comparison and shunt trying up // if need be. do { fImg = dest(trying); fPre = dest(preImage[trying.simp * (dim + 1) + trying.facet]); if (! fPre.isBoundary(size_)) fPre = image[fPre.simp * (dim + 1) + fPre.facet]; // Currently trying is glued to fImg. // After applying our isomorphism, trying will be // glued to fPre. if (fImg < fPre) { // This isomorphism will lead to a // lexicographically greater representation. // Ignore it. stepDown = true; } else if (fPre < fImg) { // Whapow, we're not in canonical form. for_each(list.begin(), list.end(), FuncDelete()); list.clear(); delete[] image; delete[] preImage; return false; } // What we have so far is consistent with an automorphism. ++trying; } while (! (stepDown || trying.isPastEnd(size_, true) || preImage[trying.simp * (dim + 1) + trying.facet]. isBeforeStart())); } if (stepDown) { // We're shunting trying back down. --trying; while (true) { fPre = preImage[trying.simp * (dim + 1) + trying.facet]; if (! isUnmatched(fPre)) { fPre = dest(fPre); if (image[fPre.simp * (dim + 1) + fPre.facet] < trying) { // This preimage/image was automatically derived. --trying; continue; } } break; } // Note that this resetting of facets that follows will // also take place when trying makes it all the way back // down to firstFace. fPre = preImage[trying.simp * (dim + 1) + trying.facet]; image[fPre.simp * (dim + 1) + fPre.facet].setBeforeStart(); if (! isUnmatched(fPre)) { fPre = dest(fPre); fImg = image[fPre.simp * (dim + 1) + fPre.facet]; preImage[fImg.simp * (dim + 1) + fImg.facet]. setBeforeStart(); image[fPre.simp * (dim + 1) + fPre.facet].setBeforeStart(); } } } } // The pairing is in canonical form and we have all our automorphisms. // Tidy up and return. delete[] image; delete[] preImage; return true; } template bool NGenericFacetPairing::findAllPairings(unsigned nSimplices, NBoolSet boundary, int nBdryFacets, typename NGenericFacetPairing::Use use, void* useArgs, bool newThread) { // Create a set of arguments. Args* args = new Args; args->boundary = boundary; args->nBdryFacets = nBdryFacets; args->use = use; args->useArgs = useArgs; // Start the facet pairing generation. FacetPairing* pairing = new FacetPairing(nSimplices); if (newThread) return pairing->start(args, true); else { pairing->run(args); delete pairing; return true; } } template void* NGenericFacetPairing::run(void* param) { Args* args = static_cast(param); // Bail if it's obvious that nothing will happen. if (args->boundary == NBoolSet::sNone || size_ == 0) { args->use(0, 0, args->useArgs); delete args; return 0; } if (args->boundary.hasTrue() && args->nBdryFacets >= 0 && (args->nBdryFacets % 2 != ((dim+1) * static_cast(size_)) % 2 || args->nBdryFacets > (dim - 1) * static_cast(size_) + 2 || (args->nBdryFacets == 0 && ! args->boundary.hasFalse()))) { args->use(0, 0, args->useArgs); delete args; return 0; } // Initialise the pairings to unspecified (i.e., facet -> itself). for (NFacetSpec f(0,0); f.simp < static_cast(size_); ++f) dest(f) = f; // Note that we have at least one simplex. NFacetSpec trying(0, 0); /**< The facet we're currently trying to match. */ int boundaryFacets = 0; /**< How many (deliberately) unmatched facets do we currently have? */ int usedFacets = 0; /**< How many facets have we already determined matchings for? */ IsoList allAutomorphisms; /**< The set of all automorphisms of the current facet pairing. */ // Run through and find all possible matchings. NFacetSpec oldTrying, tmpFacet; while (true) { // TODO: Check for cancellation, // INVARIANT: Facet trying needs to be joined to something. // dest(trying) represents the last tried destination for the // join, and there is no reciprocal join from dest(trying) back // to trying. // The current value of dest(trying) is >= trying. // Move to the next destination. ++dest(trying); // If we're about to close off the current set of simplices // and it's not all the simplices, we will have something // disconnected! // We will now avoid tying the last two facets in a set together, // and later we will avoid sending the last facet of a set to the // boundary. if (usedFacets % (dim + 1) == (dim - 1) && usedFacets < (dim + 1) * static_cast(size_) - 2 && noDest((usedFacets / (dim + 1)) + 1, 0) && dest(trying).simp <= (usedFacets / (dim + 1))) { // Move to the first unused simplex. dest(trying).simp = (usedFacets / (dim + 1)) + 1; dest(trying).facet = 0; } // We'd better make sure we're not going to glue together so // many facets that there is no room for the required number of // boundary facets. if (args->boundary.hasTrue()) { // We're interested in triangulations with boundary. if (args->nBdryFacets < 0) { // We don't care how many boundary facets. if (! args->boundary.hasFalse()) { // We must have some boundary though. if (boundaryFacets == 0 && usedFacets == (dim + 1) * static_cast(size_) - 2 && dest(trying).simp < static_cast(size_)) dest(trying).setBoundary(size_); } } else { // We're specific about the number of boundary facets. if (usedFacets - boundaryFacets + args->nBdryFacets == (dim + 1) * static_cast(size_) && dest(trying).simp < static_cast(size_)) // We've used our entire quota of non-boundary facets. dest(trying).setBoundary(size_); } } // dest(trying) is now the first remaining candidate destination. // We still don't know whether this destination is valid however. while(true) { // Move onwards to the next free destination. while (dest(trying).simp < static_cast(size_) && ! noDest(dest(trying))) ++dest(trying); // If we are past facet 0 of a simplex and the previous facet // was not used, we can't do anything with this simplex. // Move to the next simplex. if (dest(trying).simp < static_cast(size_) && dest(trying).facet > 0 && noDest(dest(trying).simp, dest(trying).facet - 1)) { ++dest(trying).simp; dest(trying).facet = 0; continue; } break; } // If we're still at an illegitimate destination, it must be // facet 0 of a simplex where the previous simplex is // unused. Note that facet == 0 implies simp > 0. // In this case, we've passed the last sane choice; head // straight to the boundary. if (dest(trying).simp < static_cast(size_) && dest(trying).facet == 0 && noDest(dest(trying).simp - 1, 0)) dest(trying).setBoundary(size_); // Finally, return to the issue of prematurely closing off a // set of simplices. This time we will avoid sending the last // facet of a set of simplices to the boundary. if (usedFacets % (dim + 1) == dim && usedFacets < (dim + 1) * static_cast(size_) - 1 && noDest((usedFacets / (dim + 1)) + 1, 0) && isUnmatched(trying)) { // Can't use the boundary; all we can do is push past the // end. ++dest(trying); } // And so we're finally looking at the next real candidate for // dest(trying) that we know we're actually allowed to use. // Check if after all that we've been pushed past the end. if (dest(trying).isPastEnd(size_, (! args->boundary.hasTrue()) || boundaryFacets == args->nBdryFacets)) { // We can't join trying to anything else. Step back. dest(trying) = trying; --trying; // Keep heading back until we find a facet that joins // forwards or to the boundary. while (! trying.isBeforeStart()) { if (dest(trying) < trying) --trying; else break; } // Is the search over? if (trying.isBeforeStart()) break; // Otherwise undo the previous gluing and prepare to loop // again trying the next option. if (isUnmatched(trying)) { --usedFacets; --boundaryFacets; } else { usedFacets -= 2; dest(dest(trying)) = dest(trying); } continue; } // Let's match it up and head to the next free facet! if (isUnmatched(trying)) { ++usedFacets; ++boundaryFacets; } else { usedFacets += 2; dest(dest(trying)) = trying; } // Now we increment trying to move to the next unmatched facet. oldTrying = trying; ++trying; while (trying.simp < static_cast(size_) && ! noDest(trying)) ++trying; // Have we got a solution? if (trying.simp == static_cast(size_)) { // Deal with the solution! if (isCanonicalInternal(allAutomorphisms)) { args->use(static_cast(this), &allAutomorphisms, args->useArgs); for_each(allAutomorphisms.begin(), allAutomorphisms.end(), FuncDelete()); allAutomorphisms.clear(); } // Head back down to the previous gluing and undo it, ready // for the next loop. trying = oldTrying; if (isUnmatched(trying)) { --usedFacets; --boundaryFacets; } else { usedFacets -= 2; dest(dest(trying)) = dest(trying); } } else { // We're about to start working on a new unmatched facet. // Set dest(trying) to one step *before* the first feasible // destination. // Note that currently the destination is set to trying. // Ensure the destination is at least the // previous forward destination from an earlier facet of this // simplex. if (trying.facet > 0) { tmpFacet = trying; for (--tmpFacet; tmpFacet.simp == trying.simp; --tmpFacet) if (tmpFacet < dest(tmpFacet)) { // Here is the previous forward destination in // this simplex. if (dest(trying) < dest(tmpFacet)) { dest(trying) = dest(tmpFacet); // Remember that dest(trying) will be // incremented before it is used. This // should not happen if we're already on the // boundary, so we need to move back one // step so we will be pushed back onto the // boundary. if (isUnmatched(trying)) --dest(trying); } break; } } // If the first simplex doesn't glue to itself and this // is not the first simplex, it can't glue to itself either. // (Note that we already know there is at least 1 simplex.) if (dest(trying).simp == trying.simp && dest(trying).facet < dim && trying.simp > 0) if (dest(0, 0).simp != 0) dest(trying).facet = dim; } } args->use(0, 0, args->useArgs); delete args; return 0; } } // namespace regina regina-4.96/engine/census/ngenericfacetpairing.h000644 000765 000024 00000105216 12377774660 021725 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file census/ngenericfacetpairing.h * \brief Deals with pairing off facets of simplices in a census of * \a n-dimensional triangulations. */ #ifndef __NGENERALFACETPAIRING_H #ifndef __DOXYGEN #define __NGENERALFACETPAIRING_H #endif #include #include #include "regina-core.h" #include "generic/dimtraits.h" #include "generic/nfacetspec.h" #include "utilities/nbooleans.h" #include "utilities/nthread.h" namespace regina { /** * \weakgroup census * @{ */ /** * A dimension-agnostic base class that represents a pairwise * matching of facets of \a dim-dimensional simplices. * Each dimension that Regina works with (2 and 3) offers its own subclass * with richer functionality; users typically do not need to work with this * template base class directly. * * Given a fixed number of \a dim-dimensional simplices, * each facet of each simplex is either paired with some other simplex facet * (which is in turn paired with it) or remains unmatched. * A simplex facet cannot be paired with itself. * * Such a matching models part of the structure of a \a dim-manifold * triangulation, in which each simplex facet is either glued to some * other simplex facet (which is in turn glued to it) or is an unglued * boundary facet. * * Note that if this pairing is used to construct an actual * triangulation, the individual gluing permutations will still need to * be specified; they are not a part of this structure. * * \pre The dimension argument \a dim is either 2 or 3. * * \ifacespython Not present, though the dimension-specific subclasses * (such as NFacePairing) are available for Python users. */ template class REGINA_API NGenericFacetPairing : public NThread { public: typedef typename DimTraits::FacetPairing FacetPairing; /**< The facet pairing class specific to this dimension. This is typically a subclass of NGenericFacetPairing. */ typedef typename DimTraits::Isomorphism Isomorphism; /**< The isomorphism class used for triangulations in this dimension. */ typedef typename DimTraits::Perm Perm; /**< The permutation class used to glue together facets of simplices when building triangulations in this dimension. */ typedef typename DimTraits::Simplex Simplex; /**< The class that represents a top-level simplex of a triangulation in this dimension. */ typedef typename DimTraits::Triangulation Triangulation; /**< The triangulation class specific to this dimension. */ /** * A list of isomorphisms on pairwise matchings of simplex facets. * * Specifically, such an isomorphism can be used to convert one * pairwise matching of simplex facets (as described by class * NGenericFacetPairing) into another. */ typedef std::list IsoList; /** * A routine that can do arbitrary processing upon a facet pairing * and its automorphisms. Such routines are used to process * pairings that are found when running findAllPairings(). * * The first parameter passed should be a facet pairing * (this should not be deallocated by this routine). * The second parameter should be a list of all automorphisms of * this pairing (this should not be deallocated either). * The third parameter may contain arbitrary data as passed to * findAllPairings(). * * It may be assumed that the pairing is of the appropriate * dimension-specific subclass (such as NFacePairing for * dimension three, or Dim2EdgePairing for dimension two). * * Note that the first two parameters passed might be \c null to * signal that facet pairing generation has finished. */ typedef void (*Use)(const FacetPairing*, const IsoList*, void*); protected: unsigned size_; /**< The number of simplices under consideration. */ NFacetSpec* pairs_; /**< The other facet to which each simplex facet is paired. If a simplex facet is left unmatched, the corresponding element of this array will be boundary (as returned by NFacetSpec::isBoundary()). If the destination for a particular facet has not yet been decided, the facet will be paired to itself. */ public: /** * \name Constructors and Destructors */ /*@{*/ /** * Creates a new facet pairing that is a clone of the given * facet pairing. * * @param cloneMe the facet pairing to clone. */ NGenericFacetPairing(const NGenericFacetPairing& cloneMe); /** * Creates the facet pairing of given triangulation. This * is the facet pairing that describes how the facets of * simplices in the given triangulation are joined together, as * described in the class notes. * * \pre The given triangulation is not empty. * * @param tri the triangulation whose facet pairing should * be constructed. */ NGenericFacetPairing(const Triangulation& tri); /** * Deallocates any memory used by this structure. */ virtual ~NGenericFacetPairing(); /*@}*/ /** * \name Basic Queries */ /*@{*/ /** * Returns the number of simplices whose facets are described by * this facet pairing. * * @return the number of simplices under consideration. */ unsigned size() const; /** * Returns the other facet to which the given simplex facet is * paired. If the given facet is left deliberately unmatched, * the value returned will be boundary (as returned by * NFacetSpec::isBoundary()). * * \pre The given facet is a real simplex facet (not boundary, * before-the-start or past-the-end). * * @param source the facet under investigation. * @return the other facet to which the given facet is paired. */ const NFacetSpec& dest(const NFacetSpec& source) const; /** * Returns the other facet to which the given simplex facet is * paired. If the given facet is left deliberately unmatched, * the value returned will be boundary (as returned by * NFacetSpec::isBoundary()). * * @param simp the simplex under investigation (this must be * strictly less than the total number of simplices under * consideration). * @param facet the facet of the given simplex under * investigation (between 0 and \a dim inclusive). * @return the other facet to which the given facet is paired. */ const NFacetSpec& dest(unsigned simp, unsigned facet) const; /** * Returns the other facet to which the given simplex facet is * paired. This is a convenience operator whose behaviour is * identical to that of dest(const NFacetSpec&). * * If the given facet is left deliberately unmatched, the value * returned will be boundary (as returned by * NFacetSpec::isBoundary()). * * \pre The given facet is a real simplex facet (not boundary, * before-the-start or past-the-end). * * @param source the facet under investigation. * @return the other facet to which the given facet is paired. */ const NFacetSpec& operator [](const NFacetSpec& source) const; /** * Determines whether the given simplex facet has been left * deliberately unmatched. * * \pre The given facet is a real simplex facet (not boundary, * before-the-start or past-the-end). * * @param source the facet under investigation. * @return \c true if the given facet has been left unmatched, or * \c false if the given facet is paired with some other facet. */ bool isUnmatched(const NFacetSpec& source) const; /** * Determines whether the given simplex facet has been left * deliberately unmatched. * * @param simp the simplex under investigation (this must be * strictly less than the total number of simplices under * consideration). * @param facet the facet of the given simplex under * investigation (between 0 and \a dim inclusive). * @return \c true if the given facet has been left unmatched, or * \c false if the given facet is paired with some other facet. */ bool isUnmatched(unsigned simp, unsigned facet) const; /** * Determines whether this facet pairing is closed. * A closed facet pairing has no unmatched facets. */ bool isClosed() const; /*@}*/ /** * \name Isomorphic Representations */ /*@{*/ /** * Determines whether this facet pairing is in canonical form, * i.e., is a lexicographically minimal representative of its * isomorphism class. * * Isomorphisms of facet pairings correspond to relabellings of * simplices and relabellings of the (\a dim + 1) facets within each * simplex. * * Facet pairings are ordered by lexicographical comparison of * dest(0,0), dest(0,1), ..., * dest(size()-1,\a dim). * * \pre This facet pairing is connected, i.e., it is possible * to reach any simplex from any other simplex via a * series of matched facet pairs. * * @return \c true if and only if this facet pairing is in * canonical form. */ bool isCanonical() const; /** * Fills the given list with the set of all combinatorial * automorphisms of this facet pairing. * * An automorphism is a relabelling of the simplices and/or a * renumbering of the (\a dim + 1) facets of each simplex resulting * in precisely the same facet pairing. * * This routine uses optimisations that can cause unpredictable * breakages if this facet pairing is not in canonical form. * * The automorphisms placed in the given list will be newly * created; it is the responsibility of the caller of this * routine to deallocate them. * * \pre The given list is empty. * \pre This facet pairing is connected, i.e., it is possible * to reach any simplex from any other simplex via a * series of matched facet pairs. * \pre This facet pairing is in canonical form as described by * isCanonical(). * * \ifacespython Not present, even in the dimension-specific * subclasses. * * @param list the list into which the newly created automorphisms * will be placed. */ void findAutomorphisms(IsoList& list) const; /*@}*/ /** * \name Input and Output */ /*@{*/ /** * A deprecated alias for str(), which returns a human-readable * representation of this facet pairing. * * \deprecated This routine has (at long last) been deprecated; * use the simpler-to-type str() instead. * * @return a string representation of this pairing. */ std::string toString() const; /** * Returns a human-readable representation of this facet pairing. * * The string returned will contain no newlines. * * \ifacespython This implements the __str__() function. * * @return a string representation of this pairing. */ std::string str() const; /** * Returns a text-based representation of this facet pairing that can be * used to reconstruct the facet pairing. This reconstruction is * done through routine fromTextRep(). * * The text produced is not particularly readable; for a * human-readable text representation, see routine str() instead. * * The string returned will contain no newlines. * * @return a text-based representation of this facet pairing. */ std::string toTextRep() const; /** * Writes the graph corresponding to this facet pairing in * the Graphviz DOT language. Every vertex of this graph * represents a simplex, and every edge represents a pair of * simplex facets that are joined together. Note that for a * closed triangulation this graph will be entirely (\a dim + 1)-valent; * for triangulations with boundary facets, some graph vertices * will have degree \a dim or less. * * The graph can either be written as a complete DOT graph, or * as a clustered subgraph within some larger DOT graph * (according to whether the argument \a subgraph is passed as * \c false or \c true). * * If a complete DOT graph is being written, the output may be * used as a standalone DOT file ready for use with Graphviz. * * If a subgraph is being written, the output will contain a * single \c subgraph section that should be inserted into some * larger DOT file. Note that the output generated by * writeDotHeader(), followed by one or more subgraphs and then * a closing curly brace will suffice. The subgraph name will * begin with the string \c pairing_. * * The argument \a prefix will be prepended to the name of each * graph vertex, and will also be used in the name of the graph * or subgraph. Using unique prefixes becomes important if you * are calling writeDot() several times to generate several * subgraphs for use in a single DOT file. If the \a prefix * argument is null or empty then a default prefix will be used. * * Note that this routine generates undirected graphs, not * directed graphs. The final DOT file should be used with * either the \a neato or \a fdp programs shipped with Graphviz. * * \ifacespython The \a out argument is not present; instead * standard output is assumed. * * @param out the output stream to which to write. * @param prefix a string to prepend to the name of each graph * vertex, and to include in the graph or subgraph name; see * above for details. * @param subgraph \c false if a complete standalone DOT graph * should be output, or \c true if a clustered subgraph should * be output for use in some larger DOT file. * @param labels indicates whether graph vertices will be * labelled with the corresponding simplex numbers. * This feature is currently experimental, and the default is * \c false. * * @see http://www.graphviz.org/ */ void writeDot(std::ostream& out, const char* prefix = 0, bool subgraph = false, bool labels = false) const; /** * Returns a Graphviz DOT representation of the graph that * describes this facet pairing. * * This routine simply returns the output of writeDot() as a * string, instead of dumping it to an output stream. * * All arguments are the same as for writeDot(); see the * writeDot() notes for further details. * * @return the output of writeDot(), as outlined above. */ std::string dot(const char* prefix = 0, bool subgraph = false, bool labels = false) const; /*@}*/ /** * \name Internal Routines */ /*@{*/ /** * Internal to findAllPairings(). This routine should never be * called directly. * * Performs the actual generation of facet pairings, possibly as a * separate thread. At most one copy of this routine should be * running at any given time for a particular NGenericFacetPairing * instance. * * \ifacespython Not present, even in the dimension-specific * subclasses. * * \pre This object is known to be of the dimension-specific subclass * FacetPairing, not an instance of the parent class * NGenericFacetPairing. * * @param param a structure containing the parameters that were * passed to findAllPairings(). * @return the value 0. */ void* run(void* param); /*@}*/ /** * Reconstructs a facet pairing from a text-based representation. * This text-based representation must be in the format produced * by routine toTextRep(). * * The facet pairing returned will be newly constructed; it is the * responsibility of the caller of this routine to deallocate it. * * \pre The facet pairing to be reconstructed involves at least * one simplex. * * @param rep a text-based representation of a facet pairing, as * produced by routine toTextRep(). * @return the corresponding newly constructed facet pairing, or * \c null if the given text-based representation was invalid. */ static FacetPairing* fromTextRep(const std::string& rep); /** * Writes header information for a Graphviz DOT file that will * describe the graphs for one or more facet pairings. See * the writeDot() documentation for further information on such * graphs. * * The output will be in the Graphviz DOT language, and will * include appropriate display settings for graphs, edges and * nodes. The opening brace for a \c graph section of the DOT * file is included. * * This routine may be used with writeDot() to generate a single * DOT file containing the graphs for several different facet * pairings. A complete DOT file can be produced by calling * this routine, then calling writeDot() in subgraph mode for * each facet pairing, then outputting a final closing curly brace. * * Note that if you require a DOT file containing the graph for * only a single facet pairing, this routine is unnecessary; you * may simply call writeDot() in full graph mode instead. * * This routine is suitable for generating undirected graphs, not * directed graphs. The final DOT file should be used with * either the \a neato or \a fdp programs shipped with Graphviz. * * \ifacespython The \a out argument is not present; instead * standard output is assumed. * * @param out the output stream to which to write. * @param graphName the name of the graph in the DOT file. * If this is null or empty then a default graph name will be used. * * @see http://www.graphviz.org/ */ static void writeDotHeader(std::ostream& out, const char* graphName = 0); /** * Returns header information for a Graphviz DOT file that will * describe the graphs for one or more facet pairings. * * This routine simply returns the output of writeDotHeader() as * a string, instead of dumping it to an output stream. * * All arguments are the same as for writeDotHeader(); see the * writeDotHeader() notes for further details. * * @return the output of writeDotHeader(), as outlined above. */ static std::string dotHeader(const char* graphName = 0); /** * Generates all possible facet pairings satisfying the given * constraints. Only connected facet pairings (pairings in which * each simplex can be reached from each other via a series of * individual matched facets) will be produced. * * Each facet pairing will be produced precisely once up to * isomorphism. Facet pairings are considered isomorphic if they * are related by a relabelling of the simplices and/or a * renumbering of the (\a dim + 1) facets of each simplex. Each facet * pairing that is generated will be a lexicographically minimal * representative of its isomorphism class, i.e., will be in * canonical form as described by isCanonical(). * * For each facet pairing that is generated, routine \a use (as * passed to this function) will be called with that pairing and * its automorphisms as arguments. Each pairing will be of the * appropriate dimension-specific subclass (for instance, * NFacePairing for dimension three, or Dim2EdgePairing for * dimension two). * * Once the generation of facet pairings has finished, routine * \a use will be called once more, this time with \c null as its * first two arguments (for the facet pairing and its automorphisms). * * The facet pairing generation may be run in the current thread * or as a separate thread. * * Because this class cannot represent an empty facet pairing, * if the argument \a nSimplices is zero then no facet pairings * will be generated at all. * * \todo \optlong When generating facet pairings, do some checking to * eliminate cases in which simplex (\a k > 0) can be swapped * with simplex 0 to produce a smaller representation of the same * pairing. * \todo \feature Allow cancellation of facet pairing generation. * * \ifacespython Not present, even in the dimension-specific * subclasses. * * @param nSimplices the number of simplices whose facets should * be (potentially) matched. * @param boundary determines whether any facets may be left * unmatched. This set should contain \c true if pairings with at * least one unmatched facet are to be generated, and should contain * \c false if pairings with no unmatched facets are to be generated. * @param nBdryFacets specifies the precise number of facets that * should be left unmatched. If this parameter is negative, it * is ignored and no additional restriction is imposed. If * parameter \a boundary does not contain \c true, this parameter * is likewise ignored. If parameter \a boundary does contain * true and this parameter is non-negative, only pairings with * precisely this many unmatched facets will be generated. * In particular, if this parameter is positive then pairings * with no unmatched facets will not be produced irrespective of * whether \c false is contained in parameter \a boundary. * Note that, in order to produce any pairings at all, this parameter * must be of the same parity as nSimplices * (dim+1), * and can be at most (dim-1) * nSimplices + 2. * @param use the function to call upon each facet pairing that is * found. The first parameter passed to this function will be a * facet pairing. The second parameter will be a list of all its * automorphisms (relabellings of simplices and individual * simplex facets that produce the exact same pairing). * The third parameter will be parameter \a useArgs as was passed * to this routine. * @param useArgs the pointer to pass as the final parameter for * the function \a use which will be called upon each pairing found. * @param newThread \c true if facet pairing generation should be * performed in a separate thread, or \c false if generation * should take place in the current thread. If this parameter is * \c true, this routine will exit immediately (after spawning * the new thread). * @return \c true if the new thread was successfully started (or * if facet pairing generation has taken place in the current thread), * or \c false if the new thread could not be started. */ static bool findAllPairings(unsigned nSimplices, NBoolSet boundary, int nBdryFacets, Use use, void* useArgs = 0, bool newThread = false); protected: /** * Creates a new facet pairing. All internal arrays will be * allocated but not initialised. * * \pre \a size is at least 1. * * @param size the number of simplices under * consideration in this new facet pairing. */ NGenericFacetPairing(unsigned size); /** * Returns the other facet to which the given simplex facet is * paired. If the given facet is left deliberately unmatched, the * value returned will be boundary (as returned by * NFacetSpec::isBoundary()). * * \pre The given facet is a real simplex facet (not boundary, * before-the-start or past-the-end). * * @param source the facet under investigation. * @return the other facet to which the given facet is paired. */ NFacetSpec& dest(const NFacetSpec& source); /** * Returns the other facet to which the given simplex facet is * paired. If the given facet is left deliberately unmatched, the * value returned will be boundary (as returned by * NFacetSpec::isBoundary()). * * @param simp the simplex under investigation (this must be * strictly less than the total number of simplices under * consideration). * @param facet the facet of the given simplex under * investigation (between 0 and \a dim inclusive). * @return the other facet to which the given facet is paired. */ NFacetSpec& dest(unsigned simp, unsigned facet); /** * Returns the other facet to which the given simplex facet is * paired. This is a convenience operator whose behaviour is * identical to that of dest(const NFacetSpec&). * * If the given facet is left deliberately unmatched, the value * returned will be boundary (as returned by * NFacetSpec::isBoundary()). * * \pre The given facet is a real simplex facet (not boundary, * before-the-start or past-the-end). * * @param source the facet under investigation. * @return the other facet to which the given facet is paired. */ NFacetSpec& operator [](const NFacetSpec& source); /** * Determines whether the matching for the given simplex facet * has not yet been determined. This is signalled by a facet * matched to itself. * * \pre The given facet is a real simplex facet (not boundary, * before-the-start or past-the-end). * * @param source the facet under investigation. * @return \c true if the matching for the given facet has not yet * been determined, or \c false otherwise. */ bool noDest(const NFacetSpec& source) const; /** * Determines whether the matching for the given simplex facet * has not yet been determined. This is signalled by a facet * matched to itself. * * @param simp the simplex under investigation (this must be * strictly less than the total number of simplices under * consideration). * @param facet the facet of the given simplex under * investigation (between 0 and \a dim inclusive). * @return \c true if the matching for the given facet has not yet * been determined, or \c false otherwise. */ bool noDest(unsigned simp, unsigned facet) const; /** * Determines whether this facet pairing is in canonical * (smallest lexicographical) form, given a small set of * assumptions. * * If this facet pairing is in canonical form, the given list * will be filled with the set of all combinatorial automorphisms * of this facet pairing. If not, the given list will be left empty. * * \pre The given list is empty. * \pre For each simplex \a t, the only case in which * dest(t,i) is greater than dest(t,i+1) is where * facets (t,i) and (t,i+1) are paired together. * \pre For each simplex \a t > 0, it is true that * dest(t,0).simp < t. * \pre The sequence dest(1,0), dest(2,0), * ..., dest(n-1,0) is strictly increasing, where * \a n is the total number of simplices under investigation. * * @param list the list into which automorphisms will be placed * if appropriate. * @return \c true if and only if this facet pairing is in * canonical form. */ bool isCanonicalInternal(IsoList& list) const; private: /** * Holds the arguments passed to findAllPairings(). */ struct Args { NBoolSet boundary; int nBdryFacets; Use use; void* useArgs; }; }; /*@}*/ // Inline functions for NGenericFacetPairing template inline NGenericFacetPairing::NGenericFacetPairing(unsigned size) : size_(size), pairs_(new NFacetSpec[size * (dim + 1)]) { } template inline NGenericFacetPairing::~NGenericFacetPairing() { delete[] pairs_; } template inline unsigned NGenericFacetPairing::size() const { return size_; } template inline const NFacetSpec& NGenericFacetPairing::dest( const NFacetSpec& source) const { return pairs_[(dim + 1) * source.simp + source.facet]; } template inline const NFacetSpec& NGenericFacetPairing::dest( unsigned simp, unsigned facet) const { return pairs_[(dim + 1) * simp + facet]; } template inline const NFacetSpec& NGenericFacetPairing::operator []( const NFacetSpec& source) const { return pairs_[(dim + 1) * source.simp + source.facet]; } template inline bool NGenericFacetPairing::isUnmatched( const NFacetSpec& source) const { return pairs_[(dim + 1) * source.simp + source.facet].isBoundary(size_); } template inline bool NGenericFacetPairing::isUnmatched( unsigned simp, unsigned facet) const { return pairs_[(dim + 1) * simp + facet].isBoundary(size_); } template inline NFacetSpec& NGenericFacetPairing::dest( const NFacetSpec& source) { return pairs_[(dim + 1) * source.simp + source.facet]; } template inline NFacetSpec& NGenericFacetPairing::dest( unsigned simp, unsigned facet) { return pairs_[(dim + 1) * simp + facet]; } template inline NFacetSpec& NGenericFacetPairing::operator []( const NFacetSpec& source) { return pairs_[(dim + 1) * source.simp + source.facet]; } template inline bool NGenericFacetPairing::noDest( const NFacetSpec& source) const { return dest(source) == source; } template inline bool NGenericFacetPairing::noDest( unsigned simp, unsigned facet) const { NFacetSpec& f = pairs_[(dim + 1) * simp + facet]; return (f.simp == static_cast(simp) && f.facet == static_cast(facet)); } template inline void NGenericFacetPairing::findAutomorphisms( typename NGenericFacetPairing::IsoList& list) const { isCanonicalInternal(list); } template inline std::string NGenericFacetPairing::toString() const { return str(); } } // namespace regina #endif regina-4.96/engine/census/ngenericfacetpairing.tcc000644 000765 000024 00000004714 12400001225 022207 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file census/ngenericfacetpairing.tcc * \brief Deprecated header. */ #warning This header is deprecated; please use ngenericfacetpairing-impl.h instead. #include "census/ngenericfacetpairing-impl.h" regina-4.96/engine/census/ngenericgluingperms-impl.h000644 000765 000024 00000013326 12377774661 022565 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /* Template definitions for ngenericgluingperms.h. */ #include #include #include "census/ngenericgluingperms.h" #include "utilities/stringutils.h" namespace regina { template NGenericGluingPerms::NGenericGluingPerms( const NGenericGluingPerms& cloneMe) : pairing_(cloneMe.pairing_), inputError_(false) { unsigned nSimp = cloneMe.size(); permIndices_ = new int[nSimp * (dim + 1)]; std::copy(cloneMe.permIndices_, cloneMe.permIndices_ + nSimp * (dim + 1), permIndices_); } template typename NGenericGluingPerms::Triangulation* NGenericGluingPerms::triangulate() const { unsigned nSimp = size(); Triangulation* ans = new Triangulation; Simplex** simp = new Simplex*[nSimp]; unsigned t, facet; for (t = 0; t < nSimp; ++t) simp[t] = ans->newSimplex(); for (t = 0; t < nSimp; ++t) for (facet = 0; facet <= dim; ++facet) if ((! pairing_->isUnmatched(t, facet)) && (! simp[t]->adjacentSimplex(facet))) simp[t]->joinTo(facet, simp[pairing_->dest(t, facet).simp], gluingPerm(t, facet)); delete[] simp; return ans; } template int NGenericGluingPerms::gluingToIndex(const NFacetSpec& source, const Perm& gluing) const { Perm permSn_1 = Perm(pairing_->dest(source).facet, dim) * gluing * Perm(source.facet, dim); return (std::find(Perm::Sn_1, Perm::Sn_1 + Perm::nPerms_1, permSn_1) - Perm::Sn_1); } template int NGenericGluingPerms::gluingToIndex(unsigned simp, unsigned facet, const Perm& gluing) const { Perm permSn_1 = Perm(pairing_->dest(simp, facet).facet, dim) * gluing * Perm(facet, dim); return (std::find(Perm::Sn_1, Perm::Sn_1 + Perm::nPerms_1, permSn_1) - Perm::Sn_1); } template void NGenericGluingPerms::dumpData(std::ostream& out) const { out << pairing_->toTextRep() << std::endl; unsigned simp, facet; for (simp = 0; simp < size(); ++simp) for (facet = 0; facet <= dim; ++facet) { if (simp || facet) out << ' '; out << permIndex(simp, facet); } out << std::endl; } template NGenericGluingPerms::NGenericGluingPerms(std::istream& in) : pairing_(0), permIndices_(0), inputError_(false) { // Remember that we can safely abort before allocating arrays, since C++ // delete tests for nullness. std::string line; // Skip initial whitespace to find the facet pairing. while (true) { std::getline(in, line); if (in.eof()) { inputError_ = true; return; } line = regina::stripWhitespace(line); if (line.length() > 0) break; } pairing_ = FacetPairing::fromTextRep(line); if (! pairing_) { inputError_ = true; return; } unsigned nSimps = pairing_->size(); if (nSimps == 0) { inputError_ = true; return; } permIndices_ = new int[nSimps * (dim + 1)]; unsigned simp, facet; for (simp = 0; simp < nSimps; ++simp) for (facet = 0; facet <= dim; ++facet) { in >> permIndex(simp, facet); // Don't test the range of permIndex(simp, facet) since the // gluing permutation set could still be under construction. } // Did we hit an unexpected EOF? if (in.eof()) inputError_ = true; } } // namespace regina regina-4.96/engine/census/ngenericgluingperms.h000644 000765 000024 00000053412 12377774663 021630 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file census/ngenericgluingperms.h * \brief Deals with selecting gluing permutations to complement a * particular pairing of facets of simplices in an n-manifold triangulation. */ #ifndef __NGENERICGLUINGPERMS_H #ifndef __DOXYGEN #define __NGENERICGLUINGPERMS_H #endif #include "regina-core.h" #include "generic/dimtraits.h" #include "generic/nfacetspec.h" namespace regina { /** * \weakgroup census * @{ */ /** * A dimension-agnostic base class that represents a specific set * of gluing permutations to complement a particular pairwise matching of * simplex facets. Each dimension that Regina works with (2, 3 and 4) * offers its own subclass, in some cases with richer functionality. * Users should not need to work with this template base class directly. * * Given a pairwise * matching of facets (as described by class NGenericFacetPairing), * each facet that is matched with some other facet will have an associated * permutation of (\a dim + 1) elements. * * If a facet is matched with some other facet, the two associated * permutations in this set will be inverses. If a facet is left * deliberately unmatched, it will have no associated permutation in this set. * * Such a set of permutations models part of the structure of a * triangulation, in which each simplex facet that is glued to another * facet has a corresponding gluing permutation (and the matched facet has * the inverse gluing permutation). * * \pre The dimension argument \a dim is either 2, 3 or 4. * * \ifacespython Not present. */ template class REGINA_API NGenericGluingPerms { public: typedef typename DimTraits::FacetPairing FacetPairing; typedef typename DimTraits::Perm Perm; typedef typename DimTraits::Simplex Simplex; typedef typename DimTraits::Triangulation Triangulation; protected: const FacetPairing* pairing_; /**< The facet pairing that this permutation set complements. This is guaranteed to be the minimal representative of its facet pairing isomorphism class. */ int* permIndices_; /**< The index into array Perm::Sn_1 describing how each simplex facet is glued to its partner. Note that this is not a gluing permutation as such but rather a permutation of 0,...,\a dim-1 only (see the routines gluingToIndex() and indexToGluing() for conversions). If a permutation has not yet been selected (e.g., if this permutation set is still under construction) then this index is -1. */ bool inputError_; /**< Has an error occurred during construction from an input stream? */ public: /** * Creates a new set of gluing permutations that is a clone of * the given permutation set. * * @param cloneMe the gluing permutations to clone. */ NGenericGluingPerms(const NGenericGluingPerms& cloneMe); /** * Reads a new set of gluing permutations from the given input * stream. This routine reads data in the format written by * dumpData(). * * If the data found in the input stream is invalid or * incorrectly formatted, the routine inputError() will return * \c true but the contents of this object will be otherwise * undefined. * * \warning The data format is liable to change between * Regina releases. Data in this format should be used on a * short-term temporary basis only. * * @param in the input stream from which to read. */ NGenericGluingPerms(std::istream& in); /** * Deallocates any memory used by this structure. */ virtual ~NGenericGluingPerms(); /** * Was an error found during construction from an input stream? * * This routine returns \c true if an input stream constructor was * used to create this object but the data in the input stream * was invalid or incorrectly formatted. * * If a different constructor was called (i.e., no input stream * was used), then this routine will always return \c false. * * @return \c true if an error occurred during construction from * an input stream, or \c false otherwise. */ bool inputError() const; /** * Returns the total number of simplices under consideration. * * @return the number of simplices under consideration. */ unsigned size() const; /** * Returns the specific pairing of simplex facets that this * set of gluing permutations complements. * * @return the corresponding simplex facet pairing. */ const FacetPairing* getFacetPairing() const; /** * Returns the gluing permutation associated with the given * simplex facet. * * \pre The given facet is actually paired with some other facet in * the underlying pairwise matching (see routine getFacetPairing()). * \pre The given facet is a real simplex * facet (not boundary, before-the-start or past-the-end). * * @param source the simplex facet under investigation. * @return the associated gluing permutation. */ Perm gluingPerm(const NFacetSpec& source) const; /** * Returns the gluing permutation associated with the given * simplex facet. * * \pre The given facet is actually paired with some other facet in * the underlying pairwise matching (see routine getFacetPairing()). * * @param simp the simplex under investigation (this must be * strictly less than the total number of simplices under * consideration). * @param facet the facet of the given simplex under * investigation (between 0 and \a dim inclusive). * @return the associated gluing permutation. */ Perm gluingPerm(unsigned simp, unsigned facet) const; /** * Returns a newly created triangulation as modelled by this set * of gluing permutations and the associated simplex facet * pairing. * * Each matched pair of facets and their associated permutations * will be realised as two simplex facets in the triangulation glued * together with the corresponding gluing permutation. Each * unmatched facet will be realised as a boundary facet in the * triangulation. * * It is the responsibility of the caller of this routine to * delete this triangulation once it is no longer required. * * @return a newly created triangulation modelled by this structure. */ Triangulation* triangulate() const; /** * Dumps all internal data in a plain text format to the given * output stream. This object can be recreated from this text * data by calling the input stream constructor for this class. * * This routine may be useful for transferring objects from * one processor to another. * * Note that subclass data is written after superclass data, so * it is safe to dump data from a subclass and then recreate a * new superclass object from that data (though subclass-specific * information will of course be lost). * * \warning The data format is liable to change between * Regina releases. Data in this format should be used on a * short-term temporary basis only. * * @param out the output stream to which the data should be * written. */ virtual void dumpData(std::ostream& out) const; protected: /** * Creates a new permutation set. All internal arrays will be * allocated but not initialised. * * \pre The given facet pairing is connected, i.e., it is possible * to reach any simplex from any other simplex via a * series of matched facet pairs. * \pre The given facet pairing is in canonical form as described * by NGenericFacetPairing::isCanonical(). Note that all facet pairings * constructed by NGenericFacetPairing::findAllPairings() are of this * form. * * @param pairing the specific pairing of simplex facets * that this permutation set will complement. */ NGenericGluingPerms(const FacetPairing* pairing); /** * Returns the index into array Perm::Sn_1 describing how the * the given facet is joined to its partner. * * Note that this permutation is not a gluing permutation as such, * but rather a permutation of 0,...,\a dim-1 only. For a real facet * gluing permutation, see routine gluingPerm(). * * \pre The given facet is a real simplex * facet (not boundary, before-the-start or past-the-end). * * @param source the simplex facet under investigation. * @return a reference to the corresponding array index. */ int& permIndex(const NFacetSpec& source); /** * Returns the index into array Perm::Sn_1 describing how the * the given facet is joined to its partner. * * Note that this permutation is not a gluing permutation as such, * but rather a permutation of 0,...,\a dim-1 only. For a real facet * gluing permutation, see routine gluingPerm(). * * @param simp the simplex under investigation (this must be * strictly less than the total number of simplices under * consideration). * @param facet the facet of the given simplex under * investigation (between 0 and \a dim inclusive). * @return a reference to the corresponding array index. */ int& permIndex(unsigned simp, unsigned facet); /** * Returns the index into array Perm::Sn_1 describing how the * the given facet is joined to its partner. * * Note that this permutation is not a gluing permutation as such, * but rather a permutation of 0,...,\a dim-1 only. For a real facet * gluing permutation, see routine gluingPerm(). * * \pre The given facet is a real simplex * facet (not boundary, before-the-start or past-the-end). * * @param source the simplex facet under investigation. * @return a reference to the corresponding array index. */ const int& permIndex(const NFacetSpec& source) const; /** * Returns the index into array Perm::Sn_1 describing how the * the given facet is joined to its partner. * * Note that this permutation is not a gluing permutation as such, * but rather a permutation of 0,...,\a dim-1 only. For a real facet * gluing permutation, see routine gluingPerm(). * * @param simp the simplex under investigation (this must be * strictly less than the total number of simplices under * consideration). * @param facet the facet of the given simplex under * investigation (between 0 and \a dim inclusive). * @return a reference to the corresponding array index. */ const int& permIndex(unsigned simp, unsigned facet) const; /** * Returns the index into array Perm::Sn_1 corresponding to * the given gluing permutation from the given facet to its * partner. This need not be the index into Perm::Sn_1 that * is currently stored for the given facet. * * Indices into array Perm::Sn_1 are stored internally in the * array \a permIndices_. Full gluing permutations on the other * hand are used in constructing triangulations. * * \pre The given simplex facet has a partner according to * the underlying facet pairing, i.e., is not a boundary facet. * \pre If the given simplex facet and its partner are facets * \a x and \a y of their respective simplices, then the * given gluing permutation maps \a x to \a y. * * @param source the simplex facet under investigation. * @param gluing a possible gluing permutation from the given * simplex facet to its partner according to the underlying * facet pairing. * @return the index into Perm::Sn_1 corresponding to the * given gluing permutation; this will be between 0 and \a dim!-1 * inclusive. */ int gluingToIndex(const NFacetSpec& source, const Perm& gluing) const; /** * Returns the index into array Perm::Sn_1 corresponding to * the given gluing permutation from the given facet to its * partner. This need not be the index into Perm::Sn_1 that * is currently stored for the given facet. * * Indices into array Perm::Sn_1 are stored internally in the * array \a permIndices_. Full gluing permutations on the other * hand are used in constructing triangulations. * * \pre The given simplex facet has a partner according to * the underlying facet pairing, i.e., is not a boundary facet. * \pre If the given simplex facet and its partner are facets * \a x and \a y of their respective simplices, then the * given gluing permutation maps \a x to \a y. * * @param simp the simplex under investigation; this must be * strictly less than the total number of simplices under * consideration. * @param facet the facet of the given simplex under * investigation; this must be between 0 and \a dim inclusive. * @param gluing a possible gluing permutation from the given * simplex facet to its partner according to the underlying * facet pairing. * @return the index into Perm::Sn_1 corresponding to the * given gluing permutation; this will be between 0 and \a dim!-1 * inclusive. */ int gluingToIndex(unsigned simp, unsigned facet, const Perm& gluing) const; /** * Returns the gluing permutation from the given facet to its * partner that corresponds to the given index into array * Perm::Sn_1. This index into Perm::Sn_1 need not * be the index that is currently stored for the given facet. * * Indices into array Perm::Sn_1 are stored internally in the * array \a permIndices_. Full gluing permutations on the other * hand are used in constructing triangulations. * * If the given simplex facet and its partner according to * the underlying facet pairing are facets \a x and \a y of their * respective simplices, then the resulting gluing permutation * will map \a x to \a y. * * \pre The given simplex facet has a partner according to * the underlying facet pairing, i.e., is not a boundary facet. * * @param source the simplex facet under investigation. * @param index an index into Perm::Sn_1; this must be * between 0 and \a dim!-1 inclusive. * @return the gluing permutation corresponding to the given * index into Perm::Sn_1. */ Perm indexToGluing(const NFacetSpec& source, int index) const; /** * Returns the gluing permutation from the given facet to its * partner that corresponds to the given index into array * Perm::Sn_1. This index into Perm::Sn_1 need not * be the index that is currently stored for the given facet. * * Indices into array Perm::Sn_1 are stored internally in the * array \a permIndices_. Full gluing permutations on the other * hand are used in constructing triangulations. * * If the given simplex facet and its partner according to * the underlying facet pairing are facets \a x and \a y of their * respective simplices, then the resulting gluing permutation * will map \a x to \a y. * * \pre The given simplex facet has a partner according to * the underlying facet pairing, i.e., is not a boundary facet. * * @param simp the simplex under investigation; this must be * strictly less than the total number of simplices under * consideration. * @param facet the facet of the given simplex under * investigation; this must be between 0 and \a dim inclusive. * @param index an index into Perm::Sn_1; this must be * between 0 and \a dim!-1 inclusive. * @return the gluing permutation corresponding to the given * index into Perm::Sn_1. */ Perm indexToGluing(unsigned simp, unsigned facet, int index) const; }; /*@}*/ // Inline functions for NGenericGluingPerms template inline NGenericGluingPerms::NGenericGluingPerms( const FacetPairing* pairing) : pairing_(pairing), permIndices_(new int[pairing->size() * (dim + 1)]), inputError_(false) { } template inline NGenericGluingPerms::~NGenericGluingPerms() { delete[] permIndices_; } template inline bool NGenericGluingPerms::inputError() const { return inputError_; } template inline unsigned NGenericGluingPerms::size() const { return pairing_->size(); } template inline const typename NGenericGluingPerms::FacetPairing* NGenericGluingPerms::getFacetPairing() const { return pairing_; } template inline typename NGenericGluingPerms::Perm NGenericGluingPerms::gluingPerm(const NFacetSpec& source) const { return indexToGluing(source, permIndex(source)); } template inline typename NGenericGluingPerms::Perm NGenericGluingPerms::gluingPerm( unsigned simp, unsigned facet) const { return indexToGluing(simp, facet, permIndex(simp, facet)); } template inline int& NGenericGluingPerms::permIndex(const NFacetSpec& source) { return permIndices_[(dim + 1) * source.simp + source.facet]; } template inline int& NGenericGluingPerms::permIndex(unsigned simp, unsigned facet) { return permIndices_[(dim + 1) * simp + facet]; } template inline const int& NGenericGluingPerms::permIndex( const NFacetSpec& source) const { return permIndices_[(dim + 1) * source.simp + source.facet]; } template inline const int& NGenericGluingPerms::permIndex( unsigned simp, unsigned facet) const { return permIndices_[(dim + 1) * simp + facet]; } template inline typename NGenericGluingPerms::Perm NGenericGluingPerms::indexToGluing( const NFacetSpec& source, int index) const { return Perm(pairing_->dest(source).facet, dim) * Perm::Sn_1[index] * Perm(source.facet, dim); } template inline typename NGenericGluingPerms::Perm NGenericGluingPerms::indexToGluing( unsigned simp, unsigned facet, int index) const { return Perm(pairing_->dest(simp, facet).facet, dim) * Perm::Sn_1[index] * Perm(facet, dim); } } // namespace regina #endif regina-4.96/engine/census/ngenericgluingperms.tcc000644 000765 000024 00000004711 12400001227 022106 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file census/ngenericgluingperms.tcc * \brief Deprecated header. */ #warning This header is deprecated; please use ngenericgluingperms-impl.h instead. #include "census/ngenericgluingperms-impl.h" regina-4.96/engine/census/ngluingperms.cpp000644 000765 000024 00000005713 12377776544 020627 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "census/ngluingperms.h" #include "census/ngenericgluingperms-impl.h" #include "triangulation/ntriangulation.h" namespace regina { // Instantiate all templates from the -impl.h file. template NGenericGluingPerms<3>::NGenericGluingPerms( const NGenericGluingPerms<3>&); template NGenericGluingPerms<3>::NGenericGluingPerms(std::istream&); template NTriangulation* NGenericGluingPerms<3>::triangulate() const; template int NGenericGluingPerms<3>::gluingToIndex( const NTetFace&, const NPerm4&) const; template int NGenericGluingPerms<3>::gluingToIndex( unsigned, unsigned, const NPerm4&) const; template void NGenericGluingPerms<3>::dumpData(std::ostream&) const; } // namespace regina regina-4.96/engine/census/ngluingperms.h000644 000765 000024 00000015267 12377774665 020303 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file census/ngluingperms.h * \brief Deals with selecting gluing permutations to complement a * particular pairing of tetrahedron faces. */ #ifndef __NGLUINGPERMS_H #ifndef __DOXYGEN #define __NGLUINGPERMS_H #endif #include "regina-core.h" #include "census/nfacepairing.h" #include "census/ngenericgluingperms.h" namespace regina { /** * \weakgroup census * @{ */ /** * Represents a specific set of gluing permutations to complement a * particular pairwise matching of tetrahedron faces. Given a * pairwise matching of faces (as described by class NFacePairing), each * face that is matched with some other face will have an associated * permutation of four elements (as described by class NPerm4). * * If a face is matched with some other face, the two associated * permutations in this set will be inverses. If a face is left * deliberately unmatched, it will have no associated permutation in this set. * * Such a set of permutations models part of the structure of a * triangulation, in which each tetrahedron face that is glued to another * face has a corresponding gluing permutation (and the matched face has * the inverse gluing permutation). * * \ifacespython Not present. */ class REGINA_API NGluingPerms : public NGenericGluingPerms<3> { public: /** * Creates a new set of gluing permutations that is a clone of * the given permutation set. * * @param cloneMe the gluing permutations to clone. */ NGluingPerms(const NGluingPerms& cloneMe); /** * Reads a new set of gluing permutations from the given input * stream. This routine reads data in the format written by * dumpData(). * * If the data found in the input stream is invalid or * incorrectly formatted, the routine inputError() will return * \c true but the contents of this object will be otherwise * undefined. * * \warning The data format is liable to change between * Regina releases. Data in this format should be used on a * short-term temporary basis only. * * @param in the input stream from which to read. */ NGluingPerms(std::istream& in); /** * Returns the total number of tetrahedra under consideration. * * \deprecated This routine has been renamed to size(). * This old name has been kept for backward compatibility, but * will be removed in some future version of Regina. * * @return the number of tetrahedra under consideration. */ unsigned getNumberOfTetrahedra() const; /** * Returns the specific pairing of tetrahedron faces that this * set of gluing permutations complements. * * \deprecated This routine has been renamed to getFacetPairing(). * This old name has been kept for backward compatibility, but * will be removed in some future version of Regina. * * @return the corresponding tetrahedron face pairing. */ const NFacePairing* getFacePairing() const; protected: /** * Creates a new permutation set. All internal arrays will be * allocated but not initialised. * * \pre The given face pairing is connected, i.e., it is possible * to reach any tetrahedron from any other tetrahedron via a * series of matched face pairs. * \pre The given face pairing is in canonical form as described * by NFacePairing::isCanonical(). Note that all face pairings * constructed by NFacePairing::findAllPairings() are of this form. * * @param pairing the specific pairing of tetrahedron faces * that this permutation set will complement. */ NGluingPerms(const NFacePairing* pairing); }; /*@}*/ // Inline functions for NGluingPerms inline NGluingPerms::NGluingPerms(const NGluingPerms& cloneMe) : NGenericGluingPerms<3>(cloneMe) { } inline NGluingPerms::NGluingPerms(std::istream& in) : NGenericGluingPerms<3>(in) { } inline NGluingPerms::NGluingPerms(const NFacePairing* pairing) : NGenericGluingPerms<3>(pairing) { } inline unsigned NGluingPerms::getNumberOfTetrahedra() const { return pairing_->getNumberOfTetrahedra(); } inline const NFacePairing* NGluingPerms::getFacePairing() const { return pairing_; } } // namespace regina #endif regina-4.96/engine/census/ngluingpermsearcher.cpp000644 000765 000024 00000046635 12377776544 022171 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include "census/ngluingpermsearcher.h" #include "triangulation/ntriangulation.h" #include "utilities/memutils.h" namespace regina { const char NGluingPermSearcher::dataTag_ = 'g'; NGluingPermSearcher::NGluingPermSearcher( const NFacePairing* pairing, const NFacePairing::IsoList* autos, bool orientableOnly, bool finiteOnly, int whichPurge, UseGluingPerms use, void* useArgs) : NGluingPerms(pairing), autos_(autos), autosNew(autos == 0), orientableOnly_(orientableOnly), finiteOnly_(finiteOnly), whichPurge_(whichPurge), use_(use), useArgs_(useArgs), started(false), orientation(new int[pairing->getNumberOfTetrahedra()]) { // Generate the list of face pairing automorphisms if necessary. // This will require us to remove the const for a wee moment. if (autosNew) { const_cast(this)->autos_ = new NFacePairing::IsoList(); pairing->findAutomorphisms(const_cast(*autos_)); } // Initialise arrays. unsigned nTets = getNumberOfTetrahedra(); std::fill(orientation, orientation + nTets, 0); std::fill(permIndices_, permIndices_ + nTets* 4, -1); // Just fill the order[] array in a default left-to-right fashion. // Subclasses can rearrange things if they choose. order = new NTetFace[nTets * 2]; orderElt = orderSize = 0; NTetFace face, adj; for (face.setFirst(); ! face.isPastEnd(nTets, true); face++) if (! pairing->isUnmatched(face)) if (face < pairing->dest(face)) order[orderSize++] = face; } NGluingPermSearcher::~NGluingPermSearcher() { delete[] orientation; delete[] order; if (autosNew) { // We made them, so we'd better remove the const again and // delete them. NFacePairing::IsoList* autos = const_cast(autos_); std::for_each(autos->begin(), autos->end(), FuncDelete()); delete autos; } } NGluingPermSearcher* NGluingPermSearcher::bestSearcher( const NFacePairing* pairing, const NFacePairing::IsoList* autos, bool orientableOnly, bool finiteOnly, int whichPurge, UseGluingPerms use, void* useArgs) { // Use an optimised algorithm if possible. if (finiteOnly) { if (pairing->isClosed() && pairing->getNumberOfTetrahedra() >= 3 && (whichPurge & PURGE_NON_MINIMAL) && (whichPurge & PURGE_NON_PRIME) && (orientableOnly || (whichPurge & PURGE_P2_REDUCIBLE))) { // Closed prime minimal P2-irreducible triangulations with >= 3 // tetrahedra. return new NClosedPrimeMinSearcher(pairing, autos, orientableOnly, use, useArgs); } return new NCompactSearcher(pairing, autos, orientableOnly, whichPurge, use, useArgs); } if (pairing->isClosed() && ((whichPurge & PURGE_NON_MINIMAL_HYP) == PURGE_NON_MINIMAL_HYP)) return new NHyperbolicMinSearcher(pairing, autos, orientableOnly, use, useArgs); return new NGluingPermSearcher(pairing, autos, orientableOnly, finiteOnly, whichPurge, use, useArgs); } void NGluingPermSearcher::findAllPerms(const NFacePairing* pairing, const NFacePairing::IsoList* autos, bool orientableOnly, bool finiteOnly, int whichPurge, UseGluingPerms use, void* useArgs) { NGluingPermSearcher* searcher = bestSearcher(pairing, autos, orientableOnly, finiteOnly, whichPurge, use, useArgs); searcher->runSearch(); delete searcher; } void NGluingPermSearcher::runSearch(long maxDepth) { // In this generation algorithm, each orientation is simply +/-1. unsigned nTetrahedra = getNumberOfTetrahedra(); if (maxDepth < 0) { // Larger than we will ever see (and in fact grossly so). maxDepth = nTetrahedra * 4 + 1; } if (! started) { // Search initialisation. started = true; // Do we in fact have no permutation at all to choose? if (maxDepth == 0 || pairing_->dest(0, 0).isBoundary(nTetrahedra)) { use_(this, useArgs_); use_(0, useArgs_); return; } orderElt = 0; orientation[0] = 1; } // Is it a partial search that has already finished? if (orderElt == orderSize) { if (isCanonical()) use_(this, useArgs_); use_(0, useArgs_); return; } // ---------- Selecting the individual gluing permutations ---------- int minOrder = orderElt; int maxOrder = orderElt + maxDepth; NTetFace face, adj; while (orderElt >= minOrder) { face = order[orderElt]; adj = (*pairing_)[face]; // TODO: Check for cancellation. // Move to the next permutation. // Be sure to preserve the orientation of the permutation if necessary. if ((! orientableOnly_) || adj.facet == 0) permIndex(face)++; else permIndex(face) += 2; // Are we out of ideas for this face? if (permIndex(face) >= 6) { // Yep. Head back down to the previous face. permIndex(face) = -1; permIndex(adj) = -1; orderElt--; continue; } // We are sitting on a new permutation to try. permIndex(adj) = NPerm4::invS3[permIndex(face)]; // Is this going to lead to an unwanted triangulation? // // Don't test for degree 1 or 2 edges here - for situations // where these can be purged, we will be using a specialised // subclass of NGluingPermSearcher with its own custom // implementation of runSearch(). if (lowDegreeEdge(face, false /* degree 1,2 */, whichPurge_ & PURGE_NON_MINIMAL)) continue; if (! orientableOnly_) if (badEdgeLink(face)) continue; // Fix the orientation if appropriate. if (adj.facet == 0 && orientableOnly_) { // It's the first time we've hit this tetrahedron. if ((permIndex(face) + (face.facet == 3 ? 0 : 1) + (adj.facet == 3 ? 0 : 1)) % 2 == 0) orientation[adj.simp] = -orientation[face.simp]; else orientation[adj.simp] = orientation[face.simp]; } // Move on to the next face. orderElt++; // If we're at the end, try the solution and step back. if (orderElt == orderSize) { // We in fact have an entire triangulation. // Run through the automorphisms and check whether our // permutations are in canonical form. if (isCanonical()) use_(this, useArgs_); // Back to the previous face. orderElt--; } else { // Not a full triangulation; just one level deeper. // We've moved onto a new face. // Be sure to get the orientation right. face = order[orderElt]; if (orientableOnly_ && pairing_->dest(face).facet > 0) { // permIndex(face) will be set to -1 or -2 as appropriate. adj = (*pairing_)[face]; if (orientation[face.simp] == orientation[adj.simp]) permIndex(face) = 1; else permIndex(face) = 0; if ((face.facet == 3 ? 0 : 1) + (adj.facet == 3 ? 0 : 1) == 1) permIndex(face) = (permIndex(face) + 1) % 2; permIndex(face) -= 2; } if (orderElt == maxOrder) { // We haven't found an entire triangulation, but we've // gone as far as we need to. // Process it, then step back. use_(this, useArgs_); // Back to the previous face. permIndex(face) = -1; orderElt--; } } } // And the search is over. use_(0, useArgs_); } void NGluingPermSearcher::dumpTaggedData(std::ostream& out) const { out << dataTag() << std::endl; dumpData(out); } NGluingPermSearcher* NGluingPermSearcher::readTaggedData(std::istream& in, UseGluingPerms use, void* useArgs) { // Read the class marker. char c; in >> c; if (in.eof()) return 0; NGluingPermSearcher* ans; if (c == NGluingPermSearcher::dataTag_) ans = new NGluingPermSearcher(in, use, useArgs); else if (c == NCompactSearcher::dataTag_) ans = new NCompactSearcher(in, use, useArgs); else if (c == NClosedPrimeMinSearcher::dataTag_) ans = new NClosedPrimeMinSearcher(in, use, useArgs); else if (c == NHyperbolicMinSearcher::dataTag_) ans = new NHyperbolicMinSearcher(in, use, useArgs); else return 0; if (ans->inputError()) { delete ans; return 0; } return ans; } void NGluingPermSearcher::dumpData(std::ostream& out) const { NGluingPerms::dumpData(out); out << (orientableOnly_ ? 'o' : '.'); out << (finiteOnly_ ? 'f' : '.'); out << (started ? 's' : '.'); out << ' ' << whichPurge_ << std::endl; int nTets = getNumberOfTetrahedra(); int i; for (i = 0; i < nTets; i++) { if (i) out << ' '; out << orientation[i]; } out << std::endl; out << orderElt << ' ' << orderSize << std::endl; for (i = 0; i < orderSize; i++) { if (i) out << ' '; out << order[i].simp << ' ' << order[i].facet; } out << std::endl; } NGluingPermSearcher::NGluingPermSearcher(std::istream& in, UseGluingPerms use, void* useArgs) : NGluingPerms(in), autos_(0), autosNew(false), use_(use), useArgs_(useArgs), orientation(0), order(0), orderSize(0), orderElt(0) { if (inputError_) return; // Recontruct the face pairing automorphisms. const_cast(this)->autos_ = new NFacePairing::IsoList(); pairing_->findAutomorphisms(const_cast(*autos_)); autosNew = true; // Keep reading. char c; in >> c; if (c == 'o') orientableOnly_ = true; else if (c == '.') orientableOnly_ = false; else { inputError_ = true; return; } in >> c; if (c == 'f') finiteOnly_ = true; else if (c == '.') finiteOnly_ = false; else { inputError_ = true; return; } in >> c; if (c == 's') started = true; else if (c == '.') started = false; else { inputError_ = true; return; } in >> whichPurge_; int nTets = pairing_->getNumberOfTetrahedra(); int t; orientation = new int[nTets]; for (t = 0; t < nTets; t++) in >> orientation[t]; order = new NTetFace[2 * nTets]; in >> orderElt >> orderSize; for (t = 0; t < orderSize; t++) { in >> order[t].simp >> order[t].facet; if (order[t].simp >= nTets || order[t].simp < 0 || order[t].facet >= 4 || order[t].facet < 0) { inputError_ = true; return; } } // Did we hit an unexpected EOF? if (in.eof()) inputError_ = true; } bool NGluingPermSearcher::isCanonical() const { NTetFace face, faceDest, faceImage; int ordering; for (NFacePairing::IsoList::const_iterator it = autos_->begin(); it != autos_->end(); it++) { // Compare the current set of gluing permutations with its // preimage under each face pairing automorphism, to see whether // our current permutation set is closest to canonical form. for (face.setFirst(); face.simp < static_cast(pairing_->getNumberOfTetrahedra()); face++) { faceDest = pairing_->dest(face); if (pairing_->isUnmatched(face) || faceDest < face) continue; faceImage = (**it)[face]; ordering = gluingPerm(face).compareWith( (*it)->facePerm(faceDest.simp).inverse() * gluingPerm(faceImage) * (*it)->facePerm(face.simp)); if (ordering < 0) { // This permutation set is closer. break; } else if (ordering > 0) { // The transformed permutation set is closer. return false; } // So far it's an automorphism of gluing permutations also. // Keep running through faces. } // Nothing broke with this automorphism. On to the next one. } // Nothing broke at all. return true; } bool NGluingPermSearcher::badEdgeLink(const NTetFace& face) const { // Run around all three edges bounding the face. NTetFace adj; unsigned tet; NPerm4 current; NPerm4 start(face.facet, 3); bool started, incomplete; for (unsigned permIdx = 0; permIdx < 3; permIdx++) { start = start * NPerm4(1, 2, 0, 3); // start maps (0,1,2) to the three vertices of face, with // (0,1) mapped to the edge that we wish to examine. // Continue to push through a tetrahedron and then across a // face, until either we hit a boundary or we return to the // original face. current = start; tet = face.simp; started = false; incomplete = false; while ((! started) || (static_cast(tet) != face.simp) || (start[2] != current[2]) || (start[3] != current[3])) { // Test for a return to the original tetrahedron with the // orientation reversed; this either means a bad edge link // or a bad vertex link. if (started && finiteOnly_ && static_cast(tet) == face.simp) if (start[3] == current[3] && start.sign() != current.sign()) return true; // Push through the current tetrahedron. started = true; current = current * NPerm4(2, 3); // Push across a face. if (pairing_->isUnmatched(tet, current[3])) { incomplete = true; break; } adj = pairing_->dest(tet, current[3]); if (permIndex(tet, current[3]) >= 0) { current = gluingPerm(tet, current[3]) * current; } else if (permIndex(adj) >= 0) { current = gluingPerm(adj).inverse() * current; } else { incomplete = true; break; } tet = adj.simp; } // Did we meet the original edge in reverse? if ((! incomplete) && (start != current)) return true; } // No bad edge links were found. return false; } bool NGluingPermSearcher::lowDegreeEdge(const NTetFace& face, bool testDegree12, bool testDegree3) const { // Run around all three edges bounding the face. NTetFace adj; unsigned tet; NPerm4 current; NPerm4 start(face.facet, 3); bool started, incomplete; unsigned size; for (unsigned permIdx = 0; permIdx < 3; permIdx++) { start = start * NPerm4(1, 2, 0, 3); // start maps (0,1,2) to the three vertices of face, with // (0,1) mapped to the edge that we wish to examine. // Continue to push through a tetrahedron and then across a // face, until either we hit a boundary or we return to the // original face. current = start; tet = face.simp; started = false; incomplete = false; size = 0; while ((! started) || (static_cast(tet) != face.simp) || (start[2] != current[2]) || (start[3] != current[3])) { started = true; // We're about to push through the current tetrahedron; see // if we've already exceeded the size of edge links that we // care about. if (size >= 3) { incomplete = true; break; } // Push through the current tetrahedron. current = current * NPerm4(2, 3); // Push across a face. if (pairing_->isUnmatched(tet, current[3])) { incomplete = true; break; } adj = pairing_->dest(tet, current[3]); if (permIndex(tet, current[3]) >= 0) { current = gluingPerm(tet, current[3]) * current; } else if (permIndex(adj) >= 0) { current = gluingPerm(adj).inverse() * current; } else { incomplete = true; break; } tet = adj.simp; size++; } if (! incomplete) { if (testDegree12 && size < 3) return true; if (testDegree3 && size == 3) { // Only throw away a degree three edge if it involves // three distinct tetrahedra. int tet1 = pairing_->dest(face.simp, start[2]).simp; int tet2 = pairing_->dest(face.simp, start[3]).simp; if (face.simp != tet1 && tet1 != tet2 && tet2 != face.simp) return true; } } } // No bad low-degree edges were found. return false; } } // namespace regina regina-4.96/engine/census/ngluingpermsearcher.h000644 000765 000024 00000424333 12377774667 021635 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file census/ngluingpermsearcher.h * \brief Supports searching through all possible sets of tetrahedron * gluing permutations for a given tetrahedron face pairing. */ #ifndef __NGLUINGPERMSEARCHER_H #ifndef __DOXYGEN #define __NGLUINGPERMSEARCHER_H #endif #include "regina-core.h" #include "census/ngluingperms.h" #include "utilities/nqitmask.h" /** * Specifies whether the NClosedPrimeMinSearcher census generation code * should prune on high-degree edges. * * It is well known that a closed prime minimal P^2-irreducible triangulation * formed from at least three tetrahedra can never have an edge of degree * one or two. Combining this with the fact that such a triangulation * must always have one vertex, a simple Euler characteristic * calculation shows that there must be precisely n+1 edges, where \a n * is the number of tetrahedra. * * A little arithmetic then shows that, for any \a k edges, the sum of * their edge degrees can be no more than 3(n+k-1); otherwise one of the * remaining edges will be forced to have degree one or two. This * observation is the basis behind the high-degree edge pruning that * this option controls. * * To enable pruning on high-degree edges, set this macro to 1 (the default * for Regina's main source distribution); to disable it, set it to 0. */ #define PRUNE_HIGH_DEG_EDGE_SET 1 namespace regina { /** * \weakgroup census * @{ */ class NGluingPermSearcher; /** * A routine used to do arbitrary processing upon a particular set of * tetrahedron gluing permutations. Such routines are used to process * permutation sets found when running NGluingPermSearcher::findAllPerms(). * * The first parameter passed will be a set of gluing permutations * (in fact it will be of the subclass NGluingPermSearcher in order to * support partial searches as well as full searches). This set of * gluing permutations must not be deallocated by this routine, since it * may be used again later by the caller. The second parameter may contain * arbitrary data as passed to either NGluingPerms::findAllPerms() or * the NGluingPermSearcher class constructor. * * Note that the first parameter passed might be \c null to signal that * gluing permutation generation has finished. */ typedef void (*UseGluingPerms)(const NGluingPermSearcher*, void*); /** * A utility class for searching through all possible gluing permutation * sets that correspond to a given tetrahedron face pairing. Subclasses of * NGluingPermSearcher correspond to specialised (and heavily optimised) * search algorithms that may be used in sufficiently constrained scenarios. * The main class NGluingPermSearcher offers a default (but slower) search * algorithm that may be used in more general contexts. * * The simplest way of performing a search through all possible gluing * permutations is by calling the static method findAllPerms(). This will * examine the search parameters and ensure that the best possible algorithm * is used. For finer control over the program flow, the static method * bestSearcher() can be used to create a search manager of the most * suitable class and then runSearch() can be called on this object directly. * For absolute control, a specific algorithm can be forced by explicitly * constructing an object of the corresponding class (and again * calling runSearch() on that object directly). * * Note that this class derives from NGluingPerms. The search will * involve building and repeatedly modifying the inherited NGluingPerms * data in-place. * * \ifacespython Only the PurgeFlags enumeration from this class is * present, and the PurgeFlags constants are also made directly * available through the regina namespace. Therefore there is no need * to explicitly access the NGluingPermSearcher through Python. */ class REGINA_API NGluingPermSearcher : public NGluingPerms { public: static const char dataTag_; /**< A character used to identify this class when reading and writing tagged data in text format. */ /** * Flags to indicate that our enumeration may (at the discretion of * the enumeration algorithm) ignore certain classes of triangulations. * These flags can be combined using bitwise OR. * * See the NGluingPermSearcher constructor documentation for further * details on how these flags are used. * * \ifacespython For convenience, these constants are also made * available directly in Python's regina namespace. */ enum PurgeFlags { /** * Indicates that no triangulations should be ignored. */ PURGE_NONE = 0, /** * Indicates that non-minimal triangulations may be ignored. */ PURGE_NON_MINIMAL = 1, /** * Indicates that any triangulation that is not prime (i.e., * can be written as a non-trivial connected sum) and any bounded * triangulation that is reducible over a disc may be ignored. */ PURGE_NON_PRIME = 2, /** * Indicates that any triangulation that is not prime (i.e., * can be written as a non-trivial connected sum), any * bounded triangulation that is reducible over a disc and * any triangulation that is non-minimal may be ignored. * Note that this is simply a combination of the constants * \a PURGE_NON_MINIMAL and \a PURGE_NON_PRIME. */ PURGE_NON_MINIMAL_PRIME = 3, /** * Indicates that any triangulation that is not a minimal ideal * triangulation of a cusped finite-volume hyperbolic 3-manifold * may be ignored. */ PURGE_NON_MINIMAL_HYP = 9, /** * Indicates that any triangulation containing an embedded * two-sided projective plane may be ignored. */ PURGE_P2_REDUCIBLE = 4 }; protected: const NFacePairing::IsoList* autos_; /**< The set of isomorphisms that define equivalence of gluing permutation sets. Generally this is the set of all automorphisms of the underlying face pairing. */ bool autosNew; /**< Did we create the isomorphism list autos_ ourselves (in which case we must destroy it also)? */ bool orientableOnly_; /**< Are we only searching for gluing permutations that correspond to orientable triangulations? */ bool finiteOnly_; /**< Are we only searching for gluing permutations that correspond to finite triangulations? */ int whichPurge_; /**< Are there any types of triangulation that we may optionally avoid constructing? This should be a bitwise OR of constants from the PurgeFlags enumeration. See the constructor documentation for further details on this search parameter. */ UseGluingPerms use_; /**< A routine to call each time a gluing permutation set is found during the search. */ void* useArgs_; /**< Additional user-supplied data to be passed as the second argument to the \a use_ routine. */ bool started; /**< Has the search started yet? This helps distinguish between a new search and the resumption of a partially completed search. */ int* orientation; /**< Keeps track of the orientation of each tetrahedron in the underlying triangulation. Orientation is positive/negative, or 0 if unknown. Note that in some algorithms the orientation is simply +/-1, and in some algorithms the orientation counts forwards or backwards from 0 according to how many times the orientation has been set or verified. */ protected: NTetFace* order; /**< Describes the order in which gluing permutations are assigned to faces. Specifically, this order is order[0], order[1], ..., order[orderSize-1]. Note that each element of this array corresponds to a single edge of the underlying face pairing graph, which in turn represents a tetrahedron face and its image under the given face pairing. The specific tetrahedron face stored in this array for each edge of the underlying face pairing graph will be the smaller of the two identified tetrahedron faces (unless otherwise specified for a particular edge type; see NClosedPrimeMinSearcher for examples). */ int orderSize; /**< The total number of edges in the face pairing graph, i.e., the number of elements of interest in the order[] array. */ int orderElt; /**< Marks which element of order[] we are currently examining at this stage of the search. */ public: /** * Initialises a new search for gluing permutation sets. The * search is started by calling runSearch(). Note that the * static method findAllPerms() handles both construction and * searching, and is the preferred entry point for end users. * * The arguments to this constructor describe the search * parameters in detail, as well as what should be done with * each gluing permutation set that is found. * * Parameter \a whichPurge may be used to avoid constructing * permutation sets that correspond to triangulations satisfying * certain constraints (such as non-minimality). The use of * this parameter, combined with parameters \a orientableOnly * and \a finiteOnly, can significantly speed up the permutation * set generation. For some combinations of these parameters * entirely different algorithms are used. * * Note that not all permutation sets described by parameter * \a whichPurge will be avoided (i.e., you may get gluing * permutation sets that you did not want). It is guaranteed however * that every permutation set whose corresonding triangulation does * \e not satisfy the \a whichPurge constraints will be generated. * * Similarly, even if \a finiteOnly is set to \c true, some * non-finite triangulations might still slip through the net * (since the full vertex links are not always constructed). * However, like \a whichPurge, setting \a finiteOnly to \c true * allow the census algorithm to take shortcuts and therefore * run faster. The resulting triangulations may be tested for * finiteness (and other properties) by calling triangulate(). * * \pre The given face pairing is connected, i.e., it is possible * to reach any tetrahedron from any other tetrahedron via a * series of matched face pairs. * \pre The given face pairing is in canonical form as described * by NFacePairing::isCanonical(). Note that all face pairings * constructed by NFacePairing::findAllPairings() are of this form. * * @param pairing the specific pairing of tetrahedron faces * that the generated permutation sets will complement. * @param autos the collection of isomorphisms that define equivalence * of permutation sets. These are used by runSearch(), which produces * each permutation set precisely once up to equivalence. These * isomorphisms must all be automorphisms of the given face pairing, * and will generally be the set of all such automorphisms. This * parameter may be 0, in which case the set of all automorphisms * of the given face pairing will be generated and used. * @param orientableOnly \c true if only gluing permutations * corresponding to orientable triangulations should be * generated, or \c false if no such restriction should be imposed. * @param finiteOnly \c true if only gluing permutations * corresponding to finite triangulations are required, or * \c false if there is no such requirement. Note that * regardless of this value, some non-finite triangulations * might still be produced; see the notes above for details. * @param whichPurge specifies which permutation sets we may avoid * constructing (see the function notes above for details). This * should be a bitwise OR of constants from the PurgeFlags enumeration, * or 0 if we should simply generate every possible permutation set. * If a variety of purge constants are bitwise ORed together, a * permutation set whose triangulation satisfies \e any of these * constraints may be avoided. Note that not all such * permutation sets will be avoided, but enough are avoided that * the performance increase is noticeable. * @param use the function to call upon each permutation set that * is found. The first parameter passed to this function will be * a gluing permutation set. The second parameter will be * parameter \a useArgs as was passed to this routine. * @param useArgs the pointer to pass as the final parameter for * the function \a use which will be called upon each permutation * set found. */ NGluingPermSearcher(const NFacePairing* pairing, const NFacePairing::IsoList* autos, bool orientableOnly, bool finiteOnly, int whichPurge, UseGluingPerms use, void* useArgs = 0); /** * Initialises a new search manager based on data read from the * given input stream. This may be a new search or a partially * completed search. * * This routine reads data in the format written by dumpData(). * If you wish to read data whose precise class is unknown, * consider using dumpTaggedData() and readTaggedData() instead. * * If the data found in the input stream is invalid or incorrectly * formatted, the routine inputError() will return \c true but * the contents of this object will be otherwise undefined. * * \warning The data format is liable to change between Regina * releases. Data in this format should be used on a short-term * temporary basis only. * * @param in the input stream from which to read. * @param use as for the main NGluingPermSearcher constructor. * @param useArgs as for the main NGluingPermSearcher constructor. */ NGluingPermSearcher(std::istream& in, UseGluingPerms use, void* useArgs = 0); /** * Destroys this search manager and all supporting data * structures. */ virtual ~NGluingPermSearcher(); /** * Generates all possible gluing permutation sets that satisfy * the current search criteria. The search criteria are * specified in the class constructor, or through the static * method findAllPerms(). * * Each set of gluing permutations will be produced precisely * once up to equivalence, where equivalence is defined by the * given set of automorphisms of the given face pairing. * * For each permutation set that is generated, routine \a use_ (as * passed to the class constructor) will be called with that * permutation set as an argument. * * Once the generation of permutation sets has finished, routine * \a use_ will be called once more, this time with \c null as its * first (permutation set) argument. * * Subclasses corresponding to more specialised search criteria * should override this routine to use a better optimised algorithm * where possible. * * It is possible to run only a partial search, branching to a * given depth but no further. In this case, rather than * producing complete gluing permutation sets, the search will * produce a series of partially-complete NGluingPermSearcher * objects. These partial searches may then be restarted by * calling runSearch() once more (usually after being frozen or * passed on to a different processor). If necessary, the \a use_ * routine may call completePermSet() to distinguish between * a complete set of gluing permutations and a partial search state. * * Note that a restarted search will never drop below its * initial depth. That is, calling runSearch() with a fixed * depth can be used to subdivide the overall search space into * many branches, and then calling runSearch() on each resulting * partial search will complete each of these branches without overlap. * * \todo \feature Allow cancellation of permutation set generation. * * @param maxDepth the depth of the partial search to run, or a * negative number if a full search should be run (the default). */ virtual void runSearch(long maxDepth = -1); /** * Determines whether this search manager holds a complete * gluing permutation set or just a partially completed search * state. * * This may assist the \a use_ routine when running partial * depth-based searches. See runSearch() for further details. * * @return \c true if a complete gluing permutation set is held, * or \c false otherwise. */ bool completePermSet() const; /** * Dumps all internal data in a plain text format, along with a * marker to signify which precise class the data belongs to. * This routine can be used with readTaggedData() to transport * objects from place to place whose precise class is unknown. * * \warning The data format is liable to change between Regina * releases. Data in this format should be used on a short-term * temporary basis only. * * @param out the output stream to which the data should be * written. */ void dumpTaggedData(std::ostream& out) const; // Overridden methods: virtual void dumpData(std::ostream& out) const; /** * The main entry routine for running a search for all gluing * permutation sets that complement a given face pairing. * * This routine examines the search parameters, chooses the best * possible search algorithm, constructs an object of the * corresponding subclass of NGluingPermSearcher and then calls * runSearch(). * * See the NGluingPermSearcher constructor for documentation on * the arguments to this routine. See the runSearch() method * for documentation on how the search runs and returns its * results. * * \pre The given face pairing is connected, i.e., it is possible * to reach any tetrahedron from any other tetrahedron via a * series of matched face pairs. * \pre The given face pairing is in canonical form as described * by NFacePairing::isCanonical(). Note that all face pairings * constructed by NFacePairing::findAllPairings() are of this form. */ static void findAllPerms(const NFacePairing* pairing, const NFacePairing::IsoList* autos, bool orientableOnly, bool finiteOnly, int whichPurge, UseGluingPerms use, void* useArgs = 0); /** * Constructs a search manager of the best possible class for the * given search parameters. Different subclasses of * NGluingPermSearcher provide optimised search algorithms for * different types of search. * * Calling this routine and then calling runSearch() on the * result has the same effect as the all-in-one routine * findAllPerms(). Unless you have specialised requirements * (such as partial searching), you are probably better calling * findAllPerms() instead. * * The resulting object is newly created, and must be destroyed * by the caller of this routine. * * See the NGluingPermSearcher constructor for documentation on * the arguments to this routine. * * \pre The given face pairing is connected, i.e., it is possible * to reach any tetrahedron from any other tetrahedron via a * series of matched face pairs. * \pre The given face pairing is in canonical form as described * by NFacePairing::isCanonical(). Note that all face pairings * constructed by NFacePairing::findAllPairings() are of this form. * * @return the newly created search manager. */ static NGluingPermSearcher* bestSearcher(const NFacePairing* pairing, const NFacePairing::IsoList* autos, bool orientableOnly, bool finiteOnly, int whichPurge, UseGluingPerms use, void* useArgs = 0); /** * Creates a new search manager based on tagged data read from * the given input stream. This may be a new search or a * partially completed search. * * The tagged data should be in the format written by * dumpTaggedData(). The precise class of the search manager * will be determined from the tagged data, and does not need to * be known in advance. This is in contrast to dumpData() and * the input stream constructors, where the class of the data being * read must be known at compile time. * * If the data found in the input stream is invalid or * incorrectly formatted, a null pointer will be returned. * Otherwise a newly constructed search manager will be returned, * and it is the responsibility of the caller of this routine to * destroy it after use. * * The arguments \a use and \a useArgs are the same as for the * NGluingPermSearcher constructor. * * \warning The data format is liable to change between Regina * releases. Data in this format should be used on a short-term * temporary basis only. * * @param in the input stream from which to read. */ static NGluingPermSearcher* readTaggedData(std::istream& in, UseGluingPerms use, void* useArgs = 0); protected: /** * Compares the current set of gluing permutations with its * preimage under each automorphism of the underlying face pairing, * in order to see whether the current set is in canonical form * (i.e., is lexicographically smallest). * * @return \c true if the current set is in canonical form, * or \c false otherwise. */ bool isCanonical() const; /** * Determines whether the permutations already constructed model * a triangulation with an edge identified with itself in reverse. * Note that such edges can only occur in non-orientable * triangulations. * * Tests that do not refer to the gluing permutation for the * given face will not be run. * * This routine is not fussy about the order in which gluing * permutations are selected, as long as permutations not yet * selected have the corresponding element of permIndices[] set * to -1. * * If \a finiteOnly_ is \c true in the search criteria, additional * tests will be run that can eliminate triangulations with * non-orientable vertex links. Although these tests are not * searching for bad edge links per se, they can be performed within * this routine with very little additional work needing to be done. * * @param face the specific tetrahedron face upon which tests * will be based. * @return \c true if the permutations under construction will * lead to an edge identified with itself in reverse, or \c false * if no such edge is found. */ bool badEdgeLink(const NTetFace& face) const; /** * Determines whether the permutations already constructed model * a triangulation with a low degree edge. Precisely which * types of low degree edges are identified must be specified * through parameters \a testDegree12 and \a testDegree3. * * Tests that do not refer to the gluing permutation for the * given face will not be run. * * This routine is not fussy about the order in which gluing * permutations are selected, as long as permutations not yet * selected have the corresponding element of permIndices[] set * to -1. * * @param face the specific tetrahedron face upon which tests * will be based. * @param testDegree12 \c true if we should test for * non-boundary edges of degree 1 or 2. * @param testDegree3 \c true if we should test for non-boundary * edges of degree 3 involving three distinct tetrahedra. * @return \c true if the permutations under construction will * lead to a low-degree edge as specified by parameters * \a testDegree12 and \a testDegree3, or \c false if no such * edge is found. */ bool lowDegreeEdge(const NTetFace& face, bool testDegree12, bool testDegree3) const; /** * Returns the character used to identify this class when * storing tagged data in text format. * * @return the class tag. */ virtual char dataTag() const; }; /** * A gluing permutation search class that offers a specialised search algorithm * for when all vertex links must all have a given fixed Euler characteristic. * Examples might be Euler characteristic 2 (for closed manifolds), * or Euler characteristic 0 (for manifolds with torus and/or Klein * bottle cusps). In addition, we require that every edge must be valid * (i.e., not identified with itself in reverse). * * Vertices on boundary triangles are treated a little differently. * If the underlying face pairing includes boundary triangles and the * given Euler characteristic is \a E, then boundary vertex links must have * Euler characteristic \a E-1, and must have exactly one puncture. * For instance, if \a E is 2 and the face pairing includes boundary faces, * then all vertex links must be either spheres (for internal vertices) * or discs (for boundary vertices). * * The search algorithm uses modified union-find structures on both * edge and vertex equivalence classes to prune searches that are * guaranteed to lead to bad edge or vertex links. For details see * "Enumeration of non-orientable 3-manifolds using face-pairing graphs and * union-find", Benjamin A. Burton, Discrete Comput. Geom. 38 (2007), no. 3, * 527--571; and "Detecting genus in vertex links for the fast enumeration * of 3-manifold triangulations", Benjamin A. Burton, in "ISSAC 2011: * Proceedings of the 36th International Symposium on Symbolic and * Algebraic Computation", ACM, 2011, pp. 59-66. * * No additional unwanted triangulations will be produced by this search * (in contrast to other search classes, such as NClosedPrimeMinSearcher). * That is, \e only 3-manifolds with the required vertex links will be produced. * * \ifacespython Not present. */ class REGINA_API NEulerSearcher : public NGluingPermSearcher { protected: static const char VLINK_CLOSED; /**< Signifies that a vertex link has been closed off (i.e., the link has no remaining boundary edges). */ static const char VLINK_BAD_EULER; /**< Signifies that a vertex link has either (i) accumulated too high a genus (so when its punctures are filled the Euler characteristic will be too low), or has (ii) been closed off with too low a genus (so its final Euler characteristic is too high). */ /** * Constants used in the \a vertexStateChanged array to indicate * how a partial vertex link becomes glued to itself along two * of its boundary edges. See \a vertexStateChanged for details. */ enum { VLINK_JOIN_INIT = -1, /**< A placeholder value for a join that has not yet been made. */ VLINK_JOIN_HANDLE = -2, /**< Signifies that two distinct boundary components of a vertex link have been connected, forming a handle (either orientable or non-orientable). */ VLINK_JOIN_BRIDGE = -3, /**< Signifies that a single boundary component of the vertex link has had two edges joined together in an orientation-preserving fashion. */ VLINK_JOIN_TWIST = -4 /**< Signifies that a single boundary component of the vertex link has had two edges joined together in an orientation-reversing fashion. */ }; protected: static const int vertexLinkNextFace[4][4]; /**< Maintains an ordering of the three tetrahedron faces surrounding a vertex in a tetrahedron. This ordering is consistent with the orientations of triangles in the vertex link used by TetVertexState::twistUp. For vertex v (0..3), the tetrahedron face that follows f (0..3) in this ordering is \a vertexLinkNextFace[v][f]. The remaining array elements \a vertexLinkNextFace[v][v] are all -1. */ static const int vertexLinkPrevFace[4][4]; /**< Provides backwards links for the ordering described by \a vertexLinkNextFace. For vertex v (0..3), the tetrahedron face that precedes f (0..3) in this ordering is \a vertexLinkPrevFace[v][f]. The remaining array elements \a vertexLinkPrevFace[v][v] are all -1. */ protected: /** * A structure used to track equivalence classes of tetrahedron * vertices as the gluing permutation set is constructed. Two * vertices are considered equivalent if they are identified * within the triangulation. * * Tetrahedron vertices are indexed linearly by tetrahedron and * then vertex number. Specifically, vertex v (0..3) of * tetrahedron t (0..nTets-1) has index 4t+v. * * Each equivalence class of vertices corresponds to a tree of * TetVertexState objects, arranged to form a modified union-find * structure. * * Note that a single tetrahedron vertex (as described by this * structure) provides a single triangular piece of the overall * vertex link. This triangle piece is referred to in several * of the data members below. */ struct TetVertexState { int parent; /**< The index of the parent object in the current tree, or -1 if this object is the root of the tree. */ unsigned rank; /**< The depth of the subtree beneath this object (where a leaf node has depth zero). */ unsigned bdry; /**< The number of boundary edges in the vertex link for this equivalence class of vertices. Any face whose gluing permutation has not yet been decided is treated as a boundary face. This value is only maintained correctly for the root of the corresponding object tree; other objects in the tree will have older values to facilitate backtracking. */ int euler; /**< The Euler characteristic that the vertex link would have if its punctures were all filled. As above, this value is only maintained correctly for the root of the corresponding object tree. */ char twistUp; /**< The identification of this object and its parent in the tree corresponds to a gluing of two triangles in the vertex link. Each of these triangles in the vertex link can be labelled with its own vertices 0, 1 and 2 and thereby be assigned a clockwise or anticlockwise orientation. The parameter \a twistUp is 0 if these two triangles in the vertex link are joined in a way that preserves orientation, or 1 if the gluing does not preserve orientation. If this object has no parent, the value of \a twistUp is undefined. */ bool hadEqualRank; /**< Did this tree have rank equal to its parent immediately before it was grafted beneath its parent? This information is used to maintain the ranks correctly when grafting operations are undone. If this object is still the root of its tree, this value is set to false. */ unsigned char bdryEdges; /**< The number of edges of the triangular piece of vertex link that are in fact boundary edges of the vertex link. Equivalently, this measures the number of faces of this tetrahedron meeting this vertex that are not yet joined to their partner faces. This always takes the value 0, 1, 2 or 3. */ int bdryNext[2]; /**< If the corresponding triangular piece of vertex link has any boundary edges, \a bdryNext stores the indices of the tetrahedron vertices that provide the boundary edges following on from either end of this boundary segment. Note that in most cases (see below) this is not the present vertex. For instance, if this vertex provides two boundary edges, then this array describes the boundary before the first edge and after the second. The boundary segment described by \a bdryNext[1] follows on from this segment in the direction described by the \a vertexLinkNextFace array. The boundary segment in the other direction is described by \a bdryNext[0]. If the vertex link is just this one triangle (i.e., all three faces of this tetrahedron surrounding this vertex are boundary faces, or one is a boundary and the other two are joined together), then both elements of \a bdryNext refer to this vertex itself. These are the only situations in which \a bdryNext refers back to this vertex. If the triangle is internal to the vertex link (i.e., \a bdryEdges is zero), then this array maintains the last values it had when there was at least one boundary edge earlier in the search. Each element of this array lies between 0 and 4t-1 inclusive, where \a t is the total number of tetrahedra. */ char bdryTwist[2]; /**< Describes whether the orientation of this boundary segment of the vertex link is consistent with the orientation of the adjacent segments on either side. See \a bdryNext for further discussion of boundary segments. The \a bdryNext array defines an orientation for this section of vertex link, pointing from the end described by \a bdryNext[0] to the end described by \a bdryNext[1]. For each \a i, the value \a bdryTwist[i] is 0 if the orientation of the adjacent segment described by \a bdryNext[i] is the same as this segment (as defined by the \a bdryNext values stored with the adjacent vertex), or 1 if the orientations differ. If the triangle supplied by this vertex is internal to the vertex link, this array maintains the last values it had when there was at least one boundary edge earlier in the search (just like the \a bdryNext array). */ int bdryNextOld[2]; /**< Stores a snapshot of the values in the \a bdryNext array from the last point in the search when \a bdryEdges was precisely two. If \a bdryEdges is still two or three, then this array is undefined. */ char bdryTwistOld[2]; /**< Stores a snapshot of the values in the \a bdryTwist array from the last point in the search when \a bdryEdges was precisely two. If \a bdryEdges is still two or three, then this array is undefined. */ /** * Constructor for a standalone tetrahedron vertex in an * equivalence class all of its own. Note that the vertex * link will be a single triangle with three boundary edges. */ TetVertexState(); /** * Dumps all internal data in a plain text format to the * given output stream. This state can be recreated from * this text data by calling readData(). * * This routine may be useful for transferring objects from * one processor to another. * * \warning The data format is liable to change between Regina * releases. Data in this format should be used on a short-term * temporary basis only. * * @param out the output stream to which the data should be * written. */ void dumpData(std::ostream& out) const; /** * Fills this state with data read from the given input stream. * This routine reads data in the format written by dumpData(). * * \warning The data format is liable to change between Regina * releases. Data in this format should be used on a short-term * temporary basis only. * * This routine does test for bad input data, but it * does \e not test for end-of-file. * * @param in the input stream from which to read. * @param nStates the total number of vertex states under * consideration (this must be four times the number of * tetrahedra). * @return \c false if any errors were encountered during * reading, or \c true otherwise. */ bool readData(std::istream& in, unsigned long nStates); }; /** * A structure used to track equivalence classes of tetrahedron * edges as the gluing permutation set is constructed. Two edges * are considered equivalent if they are identified within the * triangulation. * * Tetrahedron edges are indexed linearly by tetrahedron and * then edge number. Specifically, edge e (0..5) of * tetrahedron t (0..nTets-1) has index 6t+e. * * Each equivalence class of edges corresponds to a tree of * TetEdgeState objects, arranged to form a modified union-find * structure. */ struct TetEdgeState { int parent; /**< The index of the parent object in the current tree, or -1 if this object is the root of the tree. */ unsigned rank; /**< The depth of the subtree beneath this object (where a leaf node has depth zero). */ unsigned size; /**< The total number of objects in the subtree descending from this object (where this object is counted also). */ bool bounded; /**< Does this equivalence class of tetrahedron edges represent a boundary edge? If this equivalence class describes a complete loop of tetrahedron edges then the value of \a bounded is \c false. If this equivalence class describes a string of tetrahedron edges with two endpoints, the value of \a bounded is \c true. Here we treat any face whose gluing permutation has not yet been decided as a boundary face. This value is only maintained correctly for the root of the corresponding object tree; other objects in the tree will have older values to facilitate backtracking. */ char twistUp; /**< Each tetrahedron edge can be assigned an orientation pointing from the lower numbered tetrahedron vertex to the higher. The parameter \a twistUp is 0 if the identification of this object and its parent in the tree preserves this orientation, or 1 if it does not. If this object has no parent, the value of \a twistUp is undefined. */ bool hadEqualRank; /**< Did this tree have rank equal to its parent immediately before it was grafted beneath its parent? This information is used to maintain the ranks correctly when grafting operations are undone. If this object is still the root of its tree, this value is set to false. */ NQitmaskLen64 facesPos; /**< Indicates how many times this edge runs along the boundary of each tetrahedron face in the positive direction. Specifically, the (4t+i)th trit counts how many times it runs in the positive direction around the boundary of face \a i of tetrahedron \a t. Which direction is "positive" is chosen arbitrarily for each face; for details see the implementation of the NEulerSearcher constructor. Because of the fixed-size data type, this only stores information for the faces of the first 16 tetrahedra. Currently this data member is initialised by the NEulerSearcher constructors (since it belongs to TetEdgeState), but it is only used and updated in the subclass NClosedPrimeMinSearcher (where it allows us to optimise the census algorithm). */ NQitmaskLen64 facesNeg; /**< Indicates how many times this edge runs along the boundary of each tetrahedron face in the negative direction. Specifically, the (4t+i)th trit counts how many times it runs in the negative direction around the boundary of face \a i of tetrahedron \a t. Which direction is "negative" is chosen arbitrarily for each face; for details see the implementation of the NEulerSearcher constructor. Because of the fixed-size data type, this only stores information for the faces of the first 16 tetrahedra. Currently this data member is initialised by the NEulerSearcher constructors (since it belongs to TetEdgeState), but it is only used and updated in the subclass NClosedPrimeMinSearcher (where it allows us to optimise the census algorithm). */ /** * Constructor for a standalone tetrahedron edge in an * equivalence class all of its own. */ TetEdgeState(); /** * Dumps all internal data in a plain text format to the * given output stream. This state can be recreated from * this text data by calling readData(). * * This routine may be useful for transferring objects from * one processor to another. * * \warning The data format is liable to change between Regina * releases. Data in this format should be used on a short-term * temporary basis only. * * @param nTets the number of tetrahedra under consideration * in the census. * @param out the output stream to which the data should be * written. */ void dumpData(std::ostream& out, unsigned nTets) const; /** * Fills this state with data read from the given input stream. * This routine reads data in the format written by dumpData(). * * \warning The data format is liable to change between Regina * releases. Data in this format should be used on a short-term * temporary basis only. * * This routine does test for bad input data, but it * does \e not test for end-of-file. * * @param in the input stream from which to read. * @param nTets the number of tetrahedra under consideration * in the census. * @return \c false if any errors were encountered during * reading, or \c true otherwise. */ bool readData(std::istream& in, unsigned nTets); }; public: static const char dataTag_; /**< A character used to identify this class when reading and writing tagged data in text format. */ protected: int euler_; /**< The Euler characteristic that vertex links must have. For boundary vertices, this is the Euler characteristic of the closed surface that would be obtained if the puncture in the vertex link were filled. */ unsigned nVertexClasses; /**< The number of equivalence classes of identified tetrahedron vertices. */ TetVertexState* vertexState; /**< Used for tracking equivalence classes of identified tetrahedron vertices. See the TetVertexState description for details. This array has size 4n, where vertex v of tetrahedron t has index 4t+v. */ int* vertexStateChanged; /**< Tracks the way in which the vertexState[] array has been updated over time. This array has size 8n, where element 4i+v describes how the gluing for order[i] affects vertex v of the corresponding tetrahedron (thus a quarter of this array will remain unused, since only three vertices are affected for each gluing). If this identification of vertices results in the tree with root vertexState[p] being grafted beneath the tree with root vertexState[q] (so two distinct vertex links become joined together), this array will store the value p. Otherwise it will store one of the values \a VLINK_JOIN_HANDLE, \a VLINK_JOIN_BRIDGE or \a VLINK_JOIN_TWIST, indicating how the corresponding partial link is glued to itself. The value \a VLINK_JOIN_INIT will be stored for positions in the array that correspond to gluings that have not yet been made. */ unsigned nEdgeClasses; /**< The number of equivalence classes of identified tetrahedron edges. */ TetEdgeState* edgeState; /**< Used for tracking equivalence classes of identified tetrahedron edges. See the TetEdgeState description for details. This array has size 6n, where edge e of tetrahedron t has index 6t+e. */ int* edgeStateChanged; /**< Tracks the way in which the edgeState[] array has been updated over time. This array has size 8n. Suppose the gluing for order[i] affects face f of tetrahedron t. Then element 4i+v of this array describes how the gluing for order[i] affects the edge of tetrahedron t opposite vertices f and v (note that a quarter of this array will remain unused, since f and v are never equal). If this identification of edges results in the tree with root edgeState[p] being grafted beneath the tree with root edgeState[q], this array will store the value p. Otherwise it will store the value -1. */ public: /** * Creates a new search manager that restricts Euler characteristic * on the vertex links, as described in the class overview. * * For details on how a search manager is used, see the * NGluingPermSearcher documentation. Note in particular that * this class will be automatically used by * NGluingPermSearcher::findAllPerms() if possible, so there is * often no need for an end user to instantiate this class * directly. * * All constructor arguments except for \a euler are the same as for * the NGluingPermSearcher constructor, though some arguments (such as * \a finiteOnly) are not needed here since they are already implied * by the specialised search context. * * \pre The given Euler characteristic is at most 2. * \pre The given face pairing is connected, i.e., it is possible * to reach any tetrahedron from any other tetrahedron via a * series of matched face pairs. * \pre The given face pairing is in canonical form as described * by NFacePairing::isCanonical(). Note that all face pairings * constructed by NFacePairing::findAllPairings() are of this form. * * @param useEuler the Euler characteristic that vertex links must * have. For boundary vertices, this is the Euler characteristic * of the closed surface that would be obtained if the puncture in * the vertex link were filled. */ NEulerSearcher(int useEuler, const NFacePairing* pairing, const NFacePairing::IsoList* autos, bool orientableOnly, int whichPurge, UseGluingPerms use, void* useArgs = 0); /** * Initialises a new search manager based on data read from the * given input stream. This may be a new search or a partially * completed search. * * This routine reads data in the format written by dumpData(). * If you wish to read data whose precise class is unknown, * consider using dumpTaggedData() and readTaggedData() instead. * * If the data found in the input stream is invalid or incorrectly * formatted, the routine inputError() will return \c true but * the contents of this object will be otherwise undefined. * * The arguments \a use and \a useArgs are the same as for the * NGluingPermSearcher constructor. * * \warning The data format is liable to change between Regina * releases. Data in this format should be used on a short-term * temporary basis only. * * @param in the input stream from which to read. */ NEulerSearcher(std::istream& in, UseGluingPerms use, void* useArgs = 0); /** * Destroys this search manager and all supporting data * structures. */ virtual ~NEulerSearcher(); // Overridden methods: virtual void dumpData(std::ostream& out) const; virtual void runSearch(long maxDepth = -1); protected: // Overridden methods: virtual char dataTag() const; protected: /** * Returns the representative of the equivalence class containing * the given tetrahedron edge. The class representative is * defined to be the root of the corresponding union-find tree. * * See the TetEdgeState class for further details. See also the * other variant of findEdgeClass(), which is slightly slower * but which also tracks edge orientation. * * @param edgeID the index of a single tetrahedron edge; this * must be between 0 and 6t-1 inclusive, where \a t is the * number of tetrahedra. See the TetEdgeState class notes for * details on edge indexing. * @return the index of the tetrahedron edge at the root of the * union-find tree, i.e., the representative of the equivalence * class. */ int findEdgeClass(int edgeID) const; /** * Returns the representative of the equivalence class containing * the given tetrahedron edge. The class representative is * defined to be the root of the corresponding union-find tree. * * The argument \a twisted is also modified to indicate whether * or not the identification of the given edge with the class * representative preserves orientation. Note that this arugment * is \e not initialised. Instead, if the identification * is orientation-preserving then \a twisted will be left * unmodified, and if it is orientation-reversing then \a twisted * will be changed from 0 to 1 or vice-versa. * * See the TetEdgeState class for further details. See also the * other variant of findEdgeClass(), which is slightly faster * but which does not track edge orientation. * * @param edgeID the index of a single tetrahedron edge; this * must be between 0 and 6t-1 inclusive, where \a t is the * number of tetrahedra. See the TetEdgeState class notes for * details on edge indexing. * @param twisted used to track edge orientation, as described * above. This must be either 0 or 1 as it is passed into the * function, and it will also be either 0 or 1 upon returning * from the function. * @return the index of the tetrahedron edge at the root of the * union-find tree, i.e., the representative of the equivalence * class. */ int findEdgeClass(int edgeID, char& twisted) const; /** * Merge the classes of tetrahedron vertices as required by the * new gluing made at stage \a orderElt of the search. * * See the TetVertexState class for details. * * This routine returns a bitwise (OR) combination of the * VLINK_... flags defined earlier in this class. These * flags describe what happened to the vertex links during * this particular merge. In particular, they note when a * vertex link is closed off, or enters a state where it will be * forced to have the wrong Euler characteristic. * * @return a combination of VLINK_... flags describing how * the vertex links were changed, or 0 if none of the changes * described by these flags were observed. */ int mergeVertexClasses(); /** * Merge the classes of tetrahedron edges as required by the * new gluing made at stage \a orderElt of the search. * * See the TetEdgeState class for details. * * This routine returns a boolean that indicates whether this * merge creates an invalid edge (i.e., an edge identified with * itself in reverse). * * @return \c true if this merge creates an invalid edge, or * \c false if not. */ bool mergeEdgeClasses(); /** * Split the classes of tetrahedron vertices to mirror the * undoing of the gluing at stage \a orderElt of the search. * * See the TetVertexState class for details. */ void splitVertexClasses(); /** * Split the classes of tetrahedron edges to mirror the undoing * of the gluing at stage \a orderElt of the search. * * See the TetEdgeState class for details. */ void splitEdgeClasses(); /** * Signifies that the boundary edges supplied by the vertex * linking triangles for the two given tetrahedron vertices * should be marked as adjacent. The \a bdryNext and \a bdryTwist * arrays for each vertex will be adjusted to point to the other. * * See the TetVertexState class for details. * * @param vertexID the first tetrahedron vertex on which to operate; * this must be between 0 and 4n-1 inclusive, where \a n is the number * of tetrahedra. * @param end specifies in which direction the adjacent boundary * edges lie. This must be either 0 or 1, and its value should * correspond to the relevant index in the \a bdryNext and \a bdryTwist * arrays for vertex \a vertexID. * @param adjVertexID the tetrahedron vertex whose boundary edges are * adjacent to the boundary edges supplied by \a vertexID; this must * be between 0 and 4n-1 inclusive, where \a n is the number of * tetrahedra. * @param twist 0 if the orientations of the two boundary segments of * vertex link are oriented in the same direction, or 1 if they are * oriented in opposite directions; see the \a bdryTwist * documentation for details. */ void vtxBdryJoin(int vertexID, char end, int adjVertexID, char twist); /** * Adjusts the \a bdryNext and \a bdryTwist arrays for * nearby tetrahedron vertices, to ensure that these arrays * are consistent with the \a bdryNext and \a bdryTwist arrays * stored with the given vertex. * * It is assumed that the vertex linking triangle for the given * tetrahedron vertex contributes at least one boundary edge to * the vertex link. Recall from the TetVertexState class notes * that the \a bdryNext and \a bdryTwist arrays for the given * vertex describe the boundary edges that follow on in either * direction from the boundary edges supplied by this triangle. * * This routine locates the tetrahedron vertices that provide * the neighbouring boundary edges, and adjusts the \a bdryNext * and \a bdryTwist arrays for these neighbouring vertices to * point back to the given vertex. * * This routine is intended to assist with backtracking. This * routine is safe to use if the given tetrahedron vertex points * to itself (i.e., it provides a complete boundary cycle of * three edges in the vertex link). * * See the TetVertexState class for further information. * * \pre The vertex linking triangle for the given tetrahedron * vertex contributes at least one boundary edge to the vertex link. * * @param vertexID the tetrahedron vertex to examine; this must * be between 0 and 4n-1 inclusive, where \a n is the number of * tetrahedra. */ void vtxBdryFixAdj(int vertexID); /** * Copies the \a bdryNext and \a bdryTwist arrays to the * \a bdryNextOld and \a bdryTwistOld arrays for the given * tetrahedron vertex. * * See the TetVertexState class for further information. * * @param vertexID the tetrahedron vertex on which to operate; this * must be between 0 and 4n-1 inclusive, where \a n is the number of * tetrahedra. */ void vtxBdryBackup(int vertexID); /** * Copies the \a bdryNextOld and \a bdryTwistOld arrays to the * \a bdryNext and \a bdryTwist arrays for the given tetrahedron * vertex. * * See the TetVertexState class for further information. * * @param vertexID the tetrahedron vertex on which to operate; this * must be between 0 and 4n-1 inclusive, where \a n is the number of * tetrahedra. */ void vtxBdryRestore(int vertexID); /** * Assuming the given edge of the vertex linking triangle for the * given tetrahedron vertex lies on the boundary of the vertex link, * this routine identifies the adjacent boundary edges of the vertex * link in each direction. The given edge of the vertex linking * triangle must belong to one of the two tetrahedron faces * currently being joined. * * The tetrahedron vertex to examine is passed in \a vertexID, * \a tet and \a vertex, and the particular edge of the vertex * linking triangle to examine is specified by \a bdryFace. * Details of the adjacent boundary edges are returned in the * arrays \a next and \a twist. * * Note that the values returned might or might not correspond * to the \a bdryNext and \a bdryTwist arrays of the * TetVertexState class, since the TetVertexState arrays skip * over adjacent edges belonging to the same vertex linking triangle. * * If the given edge of the vertex linking triangle is not a * boundary edge of the vertex link, the behaviour of this * routine is undefined. * * See the TetVertexState class for further information. * * \pre The tetrahedron face (\a tet, \a bdryFace) is one of the * two faces that are currently being joined together. That is, * this face is either order[orderElt] or its partner in the * underlying face pairing. * * @param vertexID the tetrahedron vertex to examine; this must * be between 0 and 4n-1 inclusive, where \a n is the number of * tetrahedra. * @param tet the tetrahedron described by \a vertexID; this * must be (vertexID / 4). It is passed separately to avoid a * slow division operation. * @param vertex the tetrahedron vertex number described by \a vertexID; * this must be (vertexID % 4). It is passed separately to * avoid a slow modulus operation. * @param bdryFace the face number of the given tetrahedron * containing the edge of the vertex linking triangle that is * under consideration. This must be between 0 and 3 inclusive, * and it may not be equal to \a vertex. * @param next returns the tetrahedron vertex supplying each * adjacent boundary edge; see the TetVertexState::bdryNext * notes for details on which directions correspond to array * indices 0 and 1. * @param twist returns whether the orientations of the adjacent * boundary edges are consistent with the orientation of this * boundary edge; see the TetVertexState::bdryTwist notes for * further information on orientations in the vertex link. */ void vtxBdryNext(int vertexID, int tet, int vertex, int bdryFace, int next[2], char twist[2]); /** * Determines whether one of the edges of the vertex linking * triangle for the given tetrahedron vertex in fact forms an * entire one-edge boundary component of the overall vertex link. * * See the TetVertexState class for further information. * * @param vertexID the tetrahedron vertex to examine; this must * be between 0 and 4n-1 inclusive, where \a n is the number of * tetrahedra. * @return \c true if a one-edge boundary component is formed as * described above, or \c false otherwise. */ bool vtxBdryLength1(int vertexID); /** * Determines whether edges of the vertex linking triangles for each * of the given tetrahedron vertices combine to form an entire * two-edge boundary component of the overall vertex link, with one * edge from each triangle. * * See the TetVertexState class for further information. * * @param vertexID1 the first tetrahedron vertex to examine; this * must be between 0 and 4n-1 inclusive, where \a n is the number of * tetrahedra. * @param vertexID2 the second tetrahedron vertex to examine; this * must be between 0 and 4n-1 inclusive, where \a n is the number of * tetrahedra. * @return \c true if a two-edge boundary component is formed as * described above, or \c false otherwise. */ bool vtxBdryLength2(int vertexID1, int vertexID2); /** * Runs a number of tests on all tetrahedron vertices to locate * consistency errors in the \a bdryEdges, \a bdryNext and * \a bdryTwist members of the TetVertexState class. * * Any errors that are identified will be written to standard error. * Note that some errors might be harmless (for instance, when * a call to mergeVertexClasses() leaves processing incomplete * because it has located a bad vertex link and expects the * merge to be immediately undone). */ void vtxBdryConsistencyCheck(); /** * Dumps a summary of \a bdryNext, \a bdryTwist and \a bdryEdges * for every vertex of every tetrahedron to the given output stream. * The output format is relatively compact, and is subject to change * in future versions of Regina. The output uses one line only, and * a final newline is written. * * See the TetVertexState class for further information. * * @param out the output stream to which to write. */ void vtxBdryDump(std::ostream& out); }; /** * A gluing permutation search class that offers a specialised search * algorithm for when only compact (finite) 3-manifold triangulations are * required. The only constraints placed upon a triangulation are that * every edge must be valid (i.e., not identified with itself in reverse), * and that the link of every vertex must be a disk or a sphere. * * The search algorithm uses modified union-find structures on both * edge and vertex equivalence classes to prune searches that are * guaranteed to lead to bad edge or vertex links. For details see * "Enumeration of non-orientable 3-manifolds using face-pairing graphs and * union-find", Benjamin A. Burton, Discrete Comput. Geom. 38 (2007), no. 3, * 527--571; and "Detecting genus in vertex links for the fast enumeration * of 3-manifold triangulations", Benjamin A. Burton, in "ISSAC 2011: * Proceedings of the 36th International Symposium on Symbolic and * Algebraic Computation", ACM, 2011, pp. 59-66. * * No additional unwanted triangulations will be produced by this search * (in contrast to other search classes, such as NClosedPrimeMinSearcher). * That is, \e only compact 3-manifolds will be produced. * * \ifacespython Not present. */ class REGINA_API NCompactSearcher : public NGluingPermSearcher { protected: static const char VLINK_CLOSED; /**< Signifies that a vertex link has been closed off (i.e., the link has no remaining boundary edges). */ static const char VLINK_NON_SPHERE; /**< Signifies that a vertex link has been made into something other than a 2-sphere with zero or more punctures. */ protected: static const int vertexLinkNextFace[4][4]; /**< Maintains an ordering of the three tetrahedron faces surrounding a vertex in a tetrahedron. This ordering is consistent with the orientations of triangles in the vertex link used by TetVertexState::twistUp. For vertex v (0..3), the tetrahedron face that follows f (0..3) in this ordering is \a vertexLinkNextFace[v][f]. The remaining array elements \a vertexLinkNextFace[v][v] are all -1. */ static const int vertexLinkPrevFace[4][4]; /**< Provides backwards links for the ordering described by \a vertexLinkNextFace. For vertex v (0..3), the tetrahedron face that precedes f (0..3) in this ordering is \a vertexLinkPrevFace[v][f]. The remaining array elements \a vertexLinkPrevFace[v][v] are all -1. */ protected: /** * A structure used to track equivalence classes of tetrahedron * vertices as the gluing permutation set is constructed. Two * vertices are considered equivalent if they are identified * within the triangulation. * * Tetrahedron vertices are indexed linearly by tetrahedron and * then vertex number. Specifically, vertex v (0..3) of * tetrahedron t (0..nTets-1) has index 4t+v. * * Each equivalence class of vertices corresponds to a tree of * TetVertexState objects, arranged to form a modified union-find * structure. * * Note that a single tetrahedron vertex (as described by this * structure) provides a single triangular piece of the overall * vertex link. This triangle piece is referred to in several * of the data members below. */ struct TetVertexState { int parent; /**< The index of the parent object in the current tree, or -1 if this object is the root of the tree. */ unsigned rank; /**< The depth of the subtree beneath this object (where a leaf node has depth zero). */ unsigned bdry; /**< The number of boundary edges in the vertex link for this equivalence class of vertices. Any face whose gluing permutation has not yet been decided is treated as a boundary face. This value is only maintained correctly for the root of the corresponding object tree; other objects in the tree will have older values to facilitate backtracking. */ char twistUp; /**< The identification of this object and its parent in the tree corresponds to a gluing of two triangles in the vertex link. Each of these triangles in the vertex link can be labelled with its own vertices 0, 1 and 2 and thereby be assigned a clockwise or anticlockwise orientation. The parameter \a twistUp is 0 if these two triangles in the vertex link are joined in a way that preserves orientation, or 1 if the gluing does not preserve orientation. If this object has no parent, the value of \a twistUp is undefined. */ bool hadEqualRank; /**< Did this tree have rank equal to its parent immediately before it was grafted beneath its parent? This information is used to maintain the ranks correctly when grafting operations are undone. If this object is still the root of its tree, this value is set to false. */ unsigned char bdryEdges; /**< The number of edges of the triangular piece of vertex link that are in fact boundary edges of the vertex link. Equivalently, this measures the number of faces of this tetrahedron meeting this vertex that are not yet joined to their partner faces. This always takes the value 0, 1, 2 or 3. */ int bdryNext[2]; /**< If the corresponding triangular piece of vertex link has any boundary edges, \a bdryNext stores the indices of the tetrahedron vertices that provide the boundary edges following on from either end of this boundary segment. Note that in most cases (see below) this is not the present vertex. For instance, if this vertex provides two boundary edges, then this array describes the boundary before the first edge and after the second. The boundary segment described by \a bdryNext[1] follows on from this segment in the direction described by the \a vertexLinkNextFace array. The boundary segment in the other direction is described by \a bdryNext[0]. If the vertex link is just this one triangle (i.e., all three faces of this tetrahedron surrounding this vertex are boundary faces, or one is a boundary and the other two are joined together), then both elements of \a bdryNext refer to this vertex itself. These are the only situations in which \a bdryNext refers back to this vertex. If the triangle is internal to the vertex link (i.e., \a bdryEdges is zero), then this array maintains the last values it had when there was at least one boundary edge earlier in the search. Each element of this array lies between 0 and 4t-1 inclusive, where \a t is the total number of tetrahedra. */ char bdryTwist[2]; /**< Describes whether the orientation of this boundary segment of the vertex link is consistent with the orientation of the adjacent segments on either side. See \a bdryNext for further discussion of boundary segments. The \a bdryNext array defines an orientation for this section of vertex link, pointing from the end described by \a bdryNext[0] to the end described by \a bdryNext[1]. For each \a i, the value \a bdryTwist[i] is 0 if the orientation of the adjacent segment described by \a bdryNext[i] is the same as this segment (as defined by the \a bdryNext values stored with the adjacent vertex), or 1 if the orientations differ. If the triangle supplied by this vertex is internal to the vertex link, this array maintains the last values it had when there was at least one boundary edge earlier in the search (just like the \a bdryNext array). */ int bdryNextOld[2]; /**< Stores a snapshot of the values in the \a bdryNext array from the last point in the search when \a bdryEdges was precisely two. If \a bdryEdges is still two or three, then this array is undefined. */ char bdryTwistOld[2]; /**< Stores a snapshot of the values in the \a bdryTwist array from the last point in the search when \a bdryEdges was precisely two. If \a bdryEdges is still two or three, then this array is undefined. */ /** * Constructor for a standalone tetrahedron vertex in an * equivalence class all of its own. Note that the vertex * link will be a single triangle with three boundary edges. */ TetVertexState(); /** * Dumps all internal data in a plain text format to the * given output stream. This state can be recreated from * this text data by calling readData(). * * This routine may be useful for transferring objects from * one processor to another. * * \warning The data format is liable to change between Regina * releases. Data in this format should be used on a short-term * temporary basis only. * * @param out the output stream to which the data should be * written. */ void dumpData(std::ostream& out) const; /** * Fills this state with data read from the given input stream. * This routine reads data in the format written by dumpData(). * * \warning The data format is liable to change between Regina * releases. Data in this format should be used on a short-term * temporary basis only. * * This routine does test for bad input data, but it * does \e not test for end-of-file. * * @param in the input stream from which to read. * @param nStates the total number of vertex states under * consideration (this must be four times the number of * tetrahedra). * @return \c false if any errors were encountered during * reading, or \c true otherwise. */ bool readData(std::istream& in, unsigned long nStates); }; /** * A structure used to track equivalence classes of tetrahedron * edges as the gluing permutation set is constructed. Two edges * are considered equivalent if they are identified within the * triangulation. * * Tetrahedron edges are indexed linearly by tetrahedron and * then edge number. Specifically, edge e (0..5) of * tetrahedron t (0..nTets-1) has index 6t+e. * * Each equivalence class of edges corresponds to a tree of * TetEdgeState objects, arranged to form a modified union-find * structure. */ struct TetEdgeState { int parent; /**< The index of the parent object in the current tree, or -1 if this object is the root of the tree. */ unsigned rank; /**< The depth of the subtree beneath this object (where a leaf node has depth zero). */ unsigned size; /**< The total number of objects in the subtree descending from this object (where this object is counted also). */ bool bounded; /**< Does this equivalence class of tetrahedron edges represent a boundary edge? If this equivalence class describes a complete loop of tetrahedron edges then the value of \a bounded is \c false. If this equivalence class describes a string of tetrahedron edges with two endpoints, the value of \a bounded is \c true. Here we treat any face whose gluing permutation has not yet been decided as a boundary face. This value is only maintained correctly for the root of the corresponding object tree; other objects in the tree will have older values to facilitate backtracking. */ char twistUp; /**< Each tetrahedron edge can be assigned an orientation pointing from the lower numbered tetrahedron vertex to the higher. The parameter \a twistUp is 0 if the identification of this object and its parent in the tree preserves this orientation, or 1 if it does not. If this object has no parent, the value of \a twistUp is undefined. */ bool hadEqualRank; /**< Did this tree have rank equal to its parent immediately before it was grafted beneath its parent? This information is used to maintain the ranks correctly when grafting operations are undone. If this object is still the root of its tree, this value is set to false. */ NQitmaskLen64 facesPos; /**< Indicates how many times this edge runs along the boundary of each tetrahedron face in the positive direction. Specifically, the (4t+i)th trit counts how many times it runs in the positive direction around the boundary of face \a i of tetrahedron \a t. Which direction is "positive" is chosen arbitrarily for each face; for details see the implementation of the NCompactSearcher constructor. Because of the fixed-size data type, this only stores information for the faces of the first 16 tetrahedra. Currently this data member is initialised by the NCompactSearcher constructors (since it belongs to TetEdgeState), but it is only used and updated in the subclass NClosedPrimeMinSearcher (where it allows us to optimise the census algorithm). */ NQitmaskLen64 facesNeg; /**< Indicates how many times this edge runs along the boundary of each tetrahedron face in the negative direction. Specifically, the (4t+i)th trit counts how many times it runs in the negative direction around the boundary of face \a i of tetrahedron \a t. Which direction is "negative" is chosen arbitrarily for each face; for details see the implementation of the NCompactSearcher constructor. Because of the fixed-size data type, this only stores information for the faces of the first 16 tetrahedra. Currently this data member is initialised by the NCompactSearcher constructors (since it belongs to TetEdgeState), but it is only used and updated in the subclass NClosedPrimeMinSearcher (where it allows us to optimise the census algorithm). */ /** * Constructor for a standalone tetrahedron edge in an * equivalence class all of its own. */ TetEdgeState(); /** * Dumps all internal data in a plain text format to the * given output stream. This state can be recreated from * this text data by calling readData(). * * This routine may be useful for transferring objects from * one processor to another. * * \warning The data format is liable to change between Regina * releases. Data in this format should be used on a short-term * temporary basis only. * * @param nTets the number of tetrahedra under consideration * in the census. * @param out the output stream to which the data should be * written. */ void dumpData(std::ostream& out, unsigned nTets) const; /** * Fills this state with data read from the given input stream. * This routine reads data in the format written by dumpData(). * * \warning The data format is liable to change between Regina * releases. Data in this format should be used on a short-term * temporary basis only. * * This routine does test for bad input data, but it * does \e not test for end-of-file. * * @param in the input stream from which to read. * @param nTets the number of tetrahedra under consideration * in the census. * @return \c false if any errors were encountered during * reading, or \c true otherwise. */ bool readData(std::istream& in, unsigned nTets); }; public: static const char dataTag_; /**< A character used to identify this class when reading and writing tagged data in text format. */ protected: unsigned nVertexClasses; /**< The number of equivalence classes of identified tetrahedron vertices. */ TetVertexState* vertexState; /**< Used for tracking equivalence classes of identified tetrahedron vertices. See the TetVertexState description for details. This array has size 4n, where vertex v of tetrahedron t has index 4t+v. */ int* vertexStateChanged; /**< Tracks the way in which the vertexState[] array has been updated over time. This array has size 8n, where element 4i+v describes how the gluing for order[i] affects vertex v of the corresponding tetrahedron (thus a quarter of this array will remain unused, since only three vertices are affected for each gluing). If this identification of vertices results in the tree with root vertexState[p] being grafted beneath the tree with root vertexState[q], this array will store the value p. Otherwise it will store the value -1. */ unsigned nEdgeClasses; /**< The number of equivalence classes of identified tetrahedron edges. */ TetEdgeState* edgeState; /**< Used for tracking equivalence classes of identified tetrahedron edges. See the TetEdgeState description for details. This array has size 6n, where edge e of tetrahedron t has index 6t+e. */ int* edgeStateChanged; /**< Tracks the way in which the edgeState[] array has been updated over time. This array has size 8n. Suppose the gluing for order[i] affects face f of tetrahedron t. Then element 4i+v of this array describes how the gluing for order[i] affects the edge of tetrahedron t opposite vertices f and v (note that a quarter of this array will remain unused, since f and v are never equal). If this identification of edges results in the tree with root edgeState[p] being grafted beneath the tree with root edgeState[q], this array will store the value p. Otherwise it will store the value -1. */ public: /** * Creates a new search manager for use when only compact 3-manifold * triangulations are required. * * For details on how a search manager is used, see the * NGluingPermSearcher documentation. Note in particular that * this class will be automatically used by * NGluingPermSearcher::findAllPerms() if possible, so there is * often no need for an end user to instantiate this class * directly. * * All constructor arguments are the same as for the * NGluingPermSearcher constructor, though some arguments (such as * \a finiteOnly) are not needed here since they are already implied * by the specialised search context. * * \pre The given face pairing is connected, i.e., it is possible * to reach any tetrahedron from any other tetrahedron via a * series of matched face pairs. * \pre The given face pairing is in canonical form as described * by NFacePairing::isCanonical(). Note that all face pairings * constructed by NFacePairing::findAllPairings() are of this form. */ NCompactSearcher(const NFacePairing* pairing, const NFacePairing::IsoList* autos, bool orientableOnly, int whichPurge, UseGluingPerms use, void* useArgs = 0); /** * Initialises a new search manager based on data read from the * given input stream. This may be a new search or a partially * completed search. * * This routine reads data in the format written by dumpData(). * If you wish to read data whose precise class is unknown, * consider using dumpTaggedData() and readTaggedData() instead. * * If the data found in the input stream is invalid or incorrectly * formatted, the routine inputError() will return \c true but * the contents of this object will be otherwise undefined. * * The arguments \a use and \a useArgs are the same as for the * NGluingPermSearcher constructor. * * \warning The data format is liable to change between Regina * releases. Data in this format should be used on a short-term * temporary basis only. * * @param in the input stream from which to read. */ NCompactSearcher(std::istream& in, UseGluingPerms use, void* useArgs = 0); /** * Destroys this search manager and all supporting data * structures. */ virtual ~NCompactSearcher(); // Overridden methods: virtual void dumpData(std::ostream& out) const; virtual void runSearch(long maxDepth = -1); protected: // Overridden methods: virtual char dataTag() const; protected: /** * Returns the representative of the equivalence class containing * the given tetrahedron edge. The class representative is * defined to be the root of the corresponding union-find tree. * * See the TetEdgeState class for further details. See also the * other variant of findEdgeClass(), which is slightly slower * but which also tracks edge orientation. * * @param edgeID the index of a single tetrahedron edge; this * must be between 0 and 6t-1 inclusive, where \a t is the * number of tetrahedra. See the TetEdgeState class notes for * details on edge indexing. * @return the index of the tetrahedron edge at the root of the * union-find tree, i.e., the representative of the equivalence * class. */ int findEdgeClass(int edgeID) const; /** * Returns the representative of the equivalence class containing * the given tetrahedron edge. The class representative is * defined to be the root of the corresponding union-find tree. * * The argument \a twisted is also modified to indicate whether * or not the identification of the given edge with the class * representative preserves orientation. Note that this arugment * is \e not initialised. Instead, if the identification * is orientation-preserving then \a twisted will be left * unmodified, and if it is orientation-reversing then \a twisted * will be changed from 0 to 1 or vice-versa. * * See the TetEdgeState class for further details. See also the * other variant of findEdgeClass(), which is slightly faster * but which does not track edge orientation. * * @param edgeID the index of a single tetrahedron edge; this * must be between 0 and 6t-1 inclusive, where \a t is the * number of tetrahedra. See the TetEdgeState class notes for * details on edge indexing. * @param twisted used to track edge orientation, as described * above. This must be either 0 or 1 as it is passed into the * function, and it will also be either 0 or 1 upon returning * from the function. * @return the index of the tetrahedron edge at the root of the * union-find tree, i.e., the representative of the equivalence * class. */ int findEdgeClass(int edgeID, char& twisted) const; /** * Merge the classes of tetrahedron vertices as required by the * new gluing made at stage \a orderElt of the search. * * See the TetVertexState class for details. * * This routine returns a bitwise (OR) combination of the * VLINK_... flags defined earlier in this class. These * flags describe what happened to the vertex links during * this particular merge. In particular, they note when a * vertex link is closed off, or is made into something other * than a punctured 2-sphere. * * @return a combination of VLINK_... flags describing how * the vertex links were changed, or 0 if none of the changes * described by these flags were observed. */ int mergeVertexClasses(); /** * Merge the classes of tetrahedron edges as required by the * new gluing made at stage \a orderElt of the search. * * See the TetEdgeState class for details. * * This routine returns a boolean that indicates whether this * merge creates an invalid edge (i.e., an edge identified with * itself in reverse). * * @return \c true if this merge creates an invalid edge, or * \c false if not. */ bool mergeEdgeClasses(); /** * Split the classes of tetrahedron vertices to mirror the * undoing of the gluing at stage \a orderElt of the search. * * See the TetVertexState class for details. */ void splitVertexClasses(); /** * Split the classes of tetrahedron edges to mirror the undoing * of the gluing at stage \a orderElt of the search. * * See the TetEdgeState class for details. */ void splitEdgeClasses(); /** * Signifies that the boundary edges supplied by the vertex * linking triangles for the two given tetrahedron vertices * should be marked as adjacent. The \a bdryNext and \a bdryTwist * arrays for each vertex will be adjusted to point to the other. * * See the TetVertexState class for details. * * @param vertexID the first tetrahedron vertex on which to operate; * this must be between 0 and 4n-1 inclusive, where \a n is the number * of tetrahedra. * @param end specifies in which direction the adjacent boundary * edges lie. This must be either 0 or 1, and its value should * correspond to the relevant index in the \a bdryNext and \a bdryTwist * arrays for vertex \a vertexID. * @param adjVertexID the tetrahedron vertex whose boundary edges are * adjacent to the boundary edges supplied by \a vertexID; this must * be between 0 and 4n-1 inclusive, where \a n is the number of * tetrahedra. * @param twist 0 if the orientations of the two boundary segments of * vertex link are oriented in the same direction, or 1 if they are * oriented in opposite directions; see the \a bdryTwist * documentation for details. */ void vtxBdryJoin(int vertexID, char end, int adjVertexID, char twist); /** * Adjusts the \a bdryNext and \a bdryTwist arrays for * nearby tetrahedron vertices, to ensure that these arrays * are consistent with the \a bdryNext and \a bdryTwist arrays * stored with the given vertex. * * It is assumed that the vertex linking triangle for the given * tetrahedron vertex contributes at least one boundary edge to * the vertex link. Recall from the TetVertexState class notes * that the \a bdryNext and \a bdryTwist arrays for the given * vertex describe the boundary edges that follow on in either * direction from the boundary edges supplied by this triangle. * * This routine locates the tetrahedron vertices that provide * the neighbouring boundary edges, and adjusts the \a bdryNext * and \a bdryTwist arrays for these neighbouring vertices to * point back to the given vertex. * * This routine is intended to assist with backtracking. This * routine is safe to use if the given tetrahedron vertex points * to itself (i.e., it provides a complete boundary cycle of * three edges in the vertex link). * * See the TetVertexState class for further information. * * \pre The vertex linking triangle for the given tetrahedron * vertex contributes at least one boundary edge to the vertex link. * * @param vertexID the tetrahedron vertex to examine; this must * be between 0 and 4n-1 inclusive, where \a n is the number of * tetrahedra. */ void vtxBdryFixAdj(int vertexID); /** * Copies the \a bdryNext and \a bdryTwist arrays to the * \a bdryNextOld and \a bdryTwistOld arrays for the given * tetrahedron vertex. * * See the TetVertexState class for further information. * * @param vertexID the tetrahedron vertex on which to operate; this * must be between 0 and 4n-1 inclusive, where \a n is the number of * tetrahedra. */ void vtxBdryBackup(int vertexID); /** * Copies the \a bdryNextOld and \a bdryTwistOld arrays to the * \a bdryNext and \a bdryTwist arrays for the given tetrahedron * vertex. * * See the TetVertexState class for further information. * * @param vertexID the tetrahedron vertex on which to operate; this * must be between 0 and 4n-1 inclusive, where \a n is the number of * tetrahedra. */ void vtxBdryRestore(int vertexID); /** * Assuming the given edge of the vertex linking triangle for the * given tetrahedron vertex lies on the boundary of the vertex link, * this routine identifies the adjacent boundary edges of the vertex * link in each direction. The given edge of the vertex linking * triangle must belong to one of the two tetrahedron faces * currently being joined. * * The tetrahedron vertex to examine is passed in \a vertexID, * \a tet and \a vertex, and the particular edge of the vertex * linking triangle to examine is specified by \a bdryFace. * Details of the adjacent boundary edges are returned in the * arrays \a next and \a twist. * * Note that the values returned might or might not correspond * to the \a bdryNext and \a bdryTwist arrays of the * TetVertexState class, since the TetVertexState arrays skip * over adjacent edges belonging to the same vertex linking triangle. * * If the given edge of the vertex linking triangle is not a * boundary edge of the vertex link, the behaviour of this * routine is undefined. * * See the TetVertexState class for further information. * * \pre The tetrahedron face (\a tet, \a bdryFace) is one of the * two faces that are currently being joined together. That is, * this face is either order[orderElt] or its partner in the * underlying face pairing. * * @param vertexID the tetrahedron vertex to examine; this must * be between 0 and 4n-1 inclusive, where \a n is the number of * tetrahedra. * @param tet the tetrahedron described by \a vertexID; this * must be (vertexID / 4). It is passed separately to avoid a * slow division operation. * @param vertex the tetrahedron vertex number described by \a vertexID; * this must be (vertexID % 4). It is passed separately to * avoid a slow modulus operation. * @param bdryFace the face number of the given tetrahedron * containing the edge of the vertex linking triangle that is * under consideration. This must be between 0 and 3 inclusive, * and it may not be equal to \a vertex. * @param next returns the tetrahedron vertex supplying each * adjacent boundary edge; see the TetVertexState::bdryNext * notes for details on which directions correspond to array * indices 0 and 1. * @param twist returns whether the orientations of the adjacent * boundary edges are consistent with the orientation of this * boundary edge; see the TetVertexState::bdryTwist notes for * further information on orientations in the vertex link. */ void vtxBdryNext(int vertexID, int tet, int vertex, int bdryFace, int next[2], char twist[2]); /** * Determines whether one of the edges of the vertex linking * triangle for the given tetrahedron vertex in fact forms an * entire one-edge boundary component of the overall vertex link. * * See the TetVertexState class for further information. * * @param vertexID the tetrahedron vertex to examine; this must * be between 0 and 4n-1 inclusive, where \a n is the number of * tetrahedra. * @return \c true if a one-edge boundary component is formed as * described above, or \c false otherwise. */ bool vtxBdryLength1(int vertexID); /** * Determines whether edges of the vertex linking triangles for each * of the given tetrahedron vertices combine to form an entire * two-edge boundary component of the overall vertex link, with one * edge from each triangle. * * See the TetVertexState class for further information. * * @param vertexID1 the first tetrahedron vertex to examine; this * must be between 0 and 4n-1 inclusive, where \a n is the number of * tetrahedra. * @param vertexID2 the second tetrahedron vertex to examine; this * must be between 0 and 4n-1 inclusive, where \a n is the number of * tetrahedra. * @return \c true if a two-edge boundary component is formed as * described above, or \c false otherwise. */ bool vtxBdryLength2(int vertexID1, int vertexID2); /** * Runs a number of tests on all tetrahedron vertices to locate * consistency errors in the \a bdryEdges, \a bdryNext and * \a bdryTwist members of the TetVertexState class. * * Any errors that are identified will be written to standard error. * Note that some errors might be harmless (for instance, when * a call to mergeVertexClasses() leaves processing incomplete * because it has located a bad vertex link and expects the * merge to be immediately undone). */ void vtxBdryConsistencyCheck(); /** * Dumps a summary of \a bdryNext, \a bdryTwist and \a bdryEdges * for every vertex of every tetrahedron to the given output stream. * The output format is relatively compact, and is subject to change * in future versions of Regina. The output uses one line only, and * a final newline is written. * * See the TetVertexState class for further information. * * @param out the output stream to which to write. */ void vtxBdryDump(std::ostream& out); }; /** * A gluing permutation search class that offers a specialised search * algorithm for when (i) only closed prime minimal P2-irreducible * triangulations are required, and (ii) the given face pairing has * order at least three. * * The search algorithm is significantly different from the default * algorithm provided by NGluingPermSearcher. It is heavily optimised * and takes advantage of a number of results regarding the underlying * face pairing graph. * * Note that additional unwanted triangulations (e.g., non-prime or * non-minimal triangulations) may still be produced by this search. * However, significantly fewer unwanted triangulations will be produced * when using this class instead of NGluingPermSearcher. * * \ifacespython Not present. */ class REGINA_API NClosedPrimeMinSearcher : public NCompactSearcher { private: static const unsigned EDGE_CHAIN_END; /**< Represents the end of a one-ended chain in a face pairing graph. */ static const unsigned EDGE_CHAIN_INTERNAL_FIRST; /**< Represents the first edge of a double edge within a one-ended chain in a face pairing graph. The corresponding element of order[] stores the face closest to the loop at the end of this chain. */ static const unsigned EDGE_CHAIN_INTERNAL_SECOND; /**< Represents the second edge of a double edge within a one-ended chain in a face pairing graph. The corresponding element of order[] stores the face closest to the loop at the end of this chain. */ static const unsigned EDGE_DOUBLE_FIRST; /**< Represents the first edge of a miscellaneous double edge in a face pairing graph. The corresponding element of order[] stores the face belonging to the lower numbered tetrahedron. */ static const unsigned EDGE_DOUBLE_SECOND; /**< Represents the second edge of a miscellaneous double edge in a face pairing graph. The corresponding element of order[] stores the face belonging to the lower numbered tetrahedron. */ static const unsigned EDGE_MISC; /**< Represents a miscellaneous edge in a face pairing graph. */ private: static const char ECLASS_TWISTED; /**< Signifies that an edge has been identified with itself in reverse. */ static const char ECLASS_LOWDEG; /**< Signifies that a set of tetrahedron edges have been identified to form an internal edge of low degree (degree 1 or 2 of any type, or degree 3 with three distinct tetrahedra). */ static const char ECLASS_HIGHDEG; /**< Signifies that a set of tetrahedron edges have been identified to form an edge of such a high degree that either a degree 1 or 2 edge must be formed elsewhere, or else the final number of edges must be too low. */ static const char ECLASS_CONE; /**< Signifies that two edges of a face have been identified to form a cone (with no constraints on any additional identifications that might be taking place). */ static const char ECLASS_L31; /**< Signifies that all three edges of a face have been identified to form an L(3,1) spine. */ private: static const unsigned coneEdge[12][2]; /**< Lists all twelve possible ways in which two edges of a tetrahedron could be identified to create a conical face. For the ith such method, tetrahedron edges coneEdge[i][0] and coneEdge[i][1] are identified. Every element of this array is between 0 and 5 inclusive. */ static const char coneNoTwist[12]; /**< Combines with the \a coneEdge array to list all twelve possible ways in which two edges of a tetrahedron could be identified to create a conical face. For the ith such method, coneNoTwist[i] is 1 if tetrahedron edges coneEdge[i][0,1] should be identified according to their natural orientations, and coneNoTwist[i] is 0 if one of these two edges must be reversed. The natural orientation of a tetrahedron edge is defined to point from the lower-numbered tetrahedron vertex to the higher. This is consistent with the orientation used in the TetEdgeState class. */ public: static const char dataTag_; /**< A character used to identify this class when reading and writing tagged data in text format. */ private: unsigned* orderType; /**< For each edge in the face pairing graph stored in the order[] array, a corresponding category for this edge is stored in the orderType[] array. Categories are described by the EDGE_... constants defined in this class. */ unsigned nChainEdges; /**< The number of edges in the face pairing graph belonging to one-ended chains. */ int* chainPermIndices; /**< Stores the two possible gluing permutations that must be tried for each face in the order[] array of type EDGE_CHAIN_END or EDGE_CHAIN_INTERNAL_FIRST. These two possible permutations can be derived using theoretical results regarding the underlying face pairing graph. Note that for each face of type EDGE_CHAIN_INTERNAL_SECOND, the gluing permutation can be derived from the permutation chosen for the previous face (of type EDGE_CHAIN_INTERNAL_FIRST). In this case we store the two permutations for this face that correspond to the two possible permutations for the previous face. */ #if PRUNE_HIGH_DEG_EDGE_SET int highDegLimit; /**< The lowest allowable edge degree. If the underlying face pairing graph supports a (1,3,4) layered solid torus, this will be 3. Otherwise it will be 4. */ int highDegSum; /**< The sum of (\a degree - \a highDegLimit) over all edges whose degree is \a highDegLimit or higher. This sum is updated throughout the search as part of the high-degree edge pruning code. See the PRUNE_HIGH_DEG_EDGE_SET macro for further details. */ int highDegBound; /**< The maximum allowable value of \a highDegSum. If the sum \a highDegSum exceeds this bound then it can be proven that some edge of the final triangulation must have degree less than \a highDegLimit. This is part of the high-degree edge pruning code; see the PRUNE_HIGH_DEG_EDGE_SET macro for further details. */ #endif public: /** * Creates a new search manager for use when (i) only closed prime * minimal P2-irreducible triangulations are required, and (ii) the * given face pairing has order at least three. Note that other * unwanted triangulations may still be produced (e.g., * non-prime or non-minimal triangulations), but there will be * far fewer of these than when using the NGluingPermSearcher * class directly. * * For details on how a search manager is used, see the * NGluingPermSearcher documentation. Note in particular that * this class will be automatically used by * NGluingPermSearcher::findAllPerms() if possible, so there is * often no need for an end user to instantiate this class * directly. * * All constructor arguments are the same as for the * NGluingPermSearcher constructor, though some arguments (such as * \a finiteOnly and \a whichPurge) are not needed here since they * are already implied by the specialised search context. * * \pre The given face pairing is connected, i.e., it is possible * to reach any tetrahedron from any other tetrahedron via a * series of matched face pairs. * \pre The given face pairing is in canonical form as described * by NFacePairing::isCanonical(). Note that all face pairings * constructed by NFacePairing::findAllPairings() are of this form. * \pre The given face pairing has no boundary faces and has at * least three tetrahedra. */ NClosedPrimeMinSearcher(const NFacePairing* pairing, const NFacePairing::IsoList* autos, bool orientableOnly, UseGluingPerms use, void* useArgs = 0); /** * Initialises a new search manager based on data read from the * given input stream. This may be a new search or a partially * completed search. * * This routine reads data in the format written by dumpData(). * If you wish to read data whose precise class is unknown, * consider using dumpTaggedData() and readTaggedData() instead. * * If the data found in the input stream is invalid or incorrectly * formatted, the routine inputError() will return \c true but * the contents of this object will be otherwise undefined. * * The arguments \a use and \a useArgs are the same as for the * NGluingPermSearcher constructor. * * \warning The data format is liable to change between Regina * releases. Data in this format should be used on a short-term * temporary basis only. * * @param in the input stream from which to read. */ NClosedPrimeMinSearcher(std::istream& in, UseGluingPerms use, void* useArgs = 0); /** * Destroys this search manager and all supporting data * structures. */ virtual ~NClosedPrimeMinSearcher(); // Overridden methods: virtual void dumpData(std::ostream& out) const; virtual void runSearch(long maxDepth = -1); protected: // Overridden methods: virtual char dataTag() const; private: /** * Merge the classes of tetrahedron edges as required by the * new gluing made at stage \a orderElt of the search. * * This overrides NCompactSearcher::mergeEdgeClasses(), and * tests for additional structures that, whilst valid, cannot * appear in a closed prime minimal P2-irreducible triangulation. * * This routine returns a bitwise (OR) combination of the * ECLASS_... flags defined earlier in this class. These * flags describe what happened to the edge classes during * this particular merge. In particular, they note when edge * identifications form a structure that cannot possibly appear * in a closed prime minimal P2-irreducible triangulation. * * Note that, if multiple ECLASS_... flags are appropriate, only * a subset of these flags might be returned. This is because * this routine might exit early after one bad structure has been * detected, without spending time testing for others. It is * guaranteed that if at least one such flag is appropriate then * at least one such flag will be returned. * * @return a combination of ECLASS_... flags describing how * the edge links were changed, or 0 if none of the changes * described by these flags were observed. */ int mergeEdgeClasses(); /** * Split the classes of tetrahedron edges to mirror the undoing * of the gluing at stage \a orderElt of the search. * * This overrides NCompactSearcher::splitEdgeClasses(), so that * we can undo the additional work performed in the overridden * mergeEdgeClasses(). */ void splitEdgeClasses(); }; /** * A gluing permutation search class that offers a specialised search * algorithm for when only minimal ideal triangulations of cusped * finite-volume hyperbolic 3-manifolds are required. Here every vertex * link will be a torus or Klein bottle. * * Note that this searches for \e any triangulations of such hyperbolic * manifolds, not just \e geometric triangulations. * * Note that additional unwanted triangulations (e.g., non-hyperbolic or * non-minimal triangulations) may still be produced by this search. * However, significantly fewer unwanted triangulations will be produced * when using this class instead of NGluingPermSearcher. * * \ifacespython Not present. */ class REGINA_API NHyperbolicMinSearcher : public NEulerSearcher { private: static const char ECLASS_TWISTED; /**< Signifies that an edge has been identified with itself in reverse. */ static const char ECLASS_LOWDEG; /**< Signifies that a set of tetrahedron edges have been identified to form an internal edge of low degree (degree 1 or 2 of any type, or degree 3 with three distinct tetrahedra). */ public: static const char dataTag_; /**< A character used to identify this class when reading and writing tagged data in text format. */ public: /** * Creates a new search manager for use when only minimal ideal * triangulations of cusped finite-volume hyperbolic 3-manifolds are * required. Here every vertex link will be a torus or Klein bottle. * Note that other unwanted triangulations may still be produced * (e.g., non-hyperbolic or non-minimal triangulations), but there * will be far fewer of these than when using the NGluingPermSearcher * class directly. * * For details on how a search manager is used, see the * NGluingPermSearcher documentation. * * All constructor arguments are the same as for the * NGluingPermSearcher constructor, though some arguments (such as * \a finiteOnly and \a whichPurge) are not needed here since they * are already implied by the specialised search context. * * \pre The given face pairing is connected, i.e., it is possible * to reach any tetrahedron from any other tetrahedron via a * series of matched face pairs. * \pre The given face pairing is in canonical form as described * by NFacePairing::isCanonical(). Note that all face pairings * constructed by NFacePairing::findAllPairings() are of this form. * \pre The given face pairing has no boundary faces. */ NHyperbolicMinSearcher(const NFacePairing* pairing, const NFacePairing::IsoList* autos, bool orientableOnly, UseGluingPerms use, void* useArgs = 0); /** * Initialises a new search manager based on data read from the * given input stream. This may be a new search or a partially * completed search. * * This routine reads data in the format written by dumpData(). * If you wish to read data whose precise class is unknown, * consider using dumpTaggedData() and readTaggedData() instead. * * If the data found in the input stream is invalid or incorrectly * formatted, the routine inputError() will return \c true but * the contents of this object will be otherwise undefined. * * The arguments \a use and \a useArgs are the same as for the * NGluingPermSearcher constructor. * * \warning The data format is liable to change between Regina * releases. Data in this format should be used on a short-term * temporary basis only. * * @param in the input stream from which to read. */ NHyperbolicMinSearcher(std::istream& in, UseGluingPerms use, void* useArgs = 0); // Overridden methods: virtual void dumpData(std::ostream& out) const; virtual void runSearch(long maxDepth = -1); protected: // Overridden methods: virtual char dataTag() const; private: /** * Merge the classes of tetrahedron edges as required by the * new gluing made at stage \a orderElt of the search. * * This overrides NEulerSearcher::mergeEdgeClasses(), and * tests for additional structures that, whilst valid, cannot * appear in a minimal ideal triangulation of a finite-volume * hyperbolic manifold. * * This routine returns a bitwise (OR) combination of the * ECLASS_... flags defined earlier in this class. These * flags describe what happened to the edge classes during * this particular merge. In particular, they note when edge * identifications form a structure that cannot possibly appear * in the types of triangulations for which we are searching. * * Note that, if multiple ECLASS_... flags are appropriate, only * a subset of these flags might be returned. This is because * this routine might exit early after one bad structure has been * detected, without spending time testing for others. It is * guaranteed that if at least one such flag is appropriate then * at least one such flag will be returned. * * @return a combination of ECLASS_... flags describing how * the edge links were changed, or 0 if none of the changes * described by these flags were observed. */ int mergeEdgeClasses(); /** * Split the classes of tetrahedron edges to mirror the undoing * of the gluing at stage \a orderElt of the search. * * This overrides NEulerSearcher::splitEdgeClasses(), so that * we can undo the additional work performed in the overridden * mergeEdgeClasses(). */ void splitEdgeClasses(); }; /*@}*/ // Inline functions for NGluingPermSearcher inline bool NGluingPermSearcher::completePermSet() const { return (orderElt == orderSize); } inline char NGluingPermSearcher::dataTag() const { return NGluingPermSearcher::dataTag_; } // Inline functions for NEulerSearcher inline NEulerSearcher::TetVertexState::TetVertexState() : parent(-1), rank(0), bdry(3), euler(2), twistUp(0), hadEqualRank(false) { } inline NEulerSearcher::TetEdgeState::TetEdgeState() : parent(-1), rank(0), size(1), bounded(true), twistUp(0), hadEqualRank(false) { } inline NEulerSearcher::~NEulerSearcher() { delete[] vertexState; delete[] vertexStateChanged; delete[] edgeState; delete[] edgeStateChanged; } inline char NEulerSearcher::dataTag() const { return NEulerSearcher::dataTag_; } inline int NEulerSearcher::findEdgeClass(int edgeID) const { while (edgeState[edgeID].parent >= 0) edgeID = edgeState[edgeID].parent; return edgeID; } inline int NEulerSearcher::findEdgeClass(int edgeID, char& twisted) const { for ( ; edgeState[edgeID].parent >= 0; edgeID = edgeState[edgeID].parent) twisted ^= edgeState[edgeID].twistUp; return edgeID; } inline void NEulerSearcher::vtxBdryJoin(int vertexID, char end, int adjVertexID, char twist) { vertexState[vertexID].bdryNext[static_cast(end)] = adjVertexID; vertexState[vertexID].bdryTwist[static_cast(end)] = twist; vertexState[adjVertexID].bdryNext[(end ^ 1) ^ twist] = vertexID; vertexState[adjVertexID].bdryTwist[(end ^ 1) ^ twist] = twist; } inline void NEulerSearcher::vtxBdryFixAdj(int vertexID) { if (vertexState[vertexID].bdryNext[0] != vertexID) { vertexState[vertexState[vertexID].bdryNext[0]]. bdryNext[1 ^ vertexState[vertexID].bdryTwist[0]] = vertexID; vertexState[vertexState[vertexID].bdryNext[0]]. bdryTwist[1 ^ vertexState[vertexID].bdryTwist[0]] = vertexState[vertexID].bdryTwist[0]; vertexState[vertexState[vertexID].bdryNext[1]]. bdryNext[0 ^ vertexState[vertexID].bdryTwist[1]] = vertexID; vertexState[vertexState[vertexID].bdryNext[1]]. bdryTwist[0 ^ vertexState[vertexID].bdryTwist[1]] = vertexState[vertexID].bdryTwist[1]; } } inline void NEulerSearcher::vtxBdryBackup(int vertexID) { vertexState[vertexID].bdryNextOld[0] = vertexState[vertexID].bdryNext[0]; vertexState[vertexID].bdryNextOld[1] = vertexState[vertexID].bdryNext[1]; vertexState[vertexID].bdryTwistOld[0] = vertexState[vertexID].bdryTwist[0]; vertexState[vertexID].bdryTwistOld[1] = vertexState[vertexID].bdryTwist[1]; } inline void NEulerSearcher::vtxBdryRestore(int vertexID) { vertexState[vertexID].bdryNext[0] = vertexState[vertexID].bdryNextOld[0]; vertexState[vertexID].bdryNext[1] = vertexState[vertexID].bdryNextOld[1]; vertexState[vertexID].bdryTwist[0] = vertexState[vertexID].bdryTwistOld[0]; vertexState[vertexID].bdryTwist[1] = vertexState[vertexID].bdryTwistOld[1]; } inline void NEulerSearcher::vtxBdryNext(int vertexID, int tet, int vertex, int bdryFace, int next[2], char twist[2]) { switch (vertexState[vertexID].bdryEdges) { case 3: next[0] = next[1] = vertexID; twist[0] = twist[1] = 0; break; case 2: if (permIndex(tet, vertexLinkNextFace[vertex][bdryFace]) < 0) { next[0] = vertexState[vertexID].bdryNext[0]; twist[0] = vertexState[vertexID].bdryTwist[0]; next[1] = vertexID; twist[1] = 0; } else if (permIndex(tet, vertexLinkPrevFace[vertex][bdryFace]) < 0) { next[0] = vertexID; twist[0] = 0; next[1] = vertexState[vertexID].bdryNext[1]; twist[1] = vertexState[vertexID].bdryTwist[1]; } else { // We must be in the process of gluing a tetrahedron // to itself, and one of the gluings hasn't happened // yet (hence bdryEdges == 2 but only one boundary // edge shows up in the gluing permutations). // The boundary that we're not seeing must belong // to either the tetrahedron face we are currently // working with or its adjacent partner. int ghostFace = (bdryFace == order[orderElt].facet ? (*pairing_)[order[orderElt]].facet : order[orderElt].facet); if (vertexLinkNextFace[vertex][bdryFace] == ghostFace) { next[0] = vertexState[vertexID].bdryNext[0]; twist[0] = vertexState[vertexID].bdryTwist[0]; next[1] = vertexID; twist[1] = 0; } else { // Sanity check. if (vertexLinkPrevFace[vertex][bdryFace] != ghostFace) std::cerr << "ERROR: Inconsistent vertex link " "boundary information!" << std::endl; next[0] = vertexID; twist[0] = 0; next[1] = vertexState[vertexID].bdryNext[1]; twist[1] = vertexState[vertexID].bdryTwist[1]; } } break; case 1: next[0] = vertexState[vertexID].bdryNext[0]; next[1] = vertexState[vertexID].bdryNext[1]; twist[0] = vertexState[vertexID].bdryTwist[0]; twist[1] = vertexState[vertexID].bdryTwist[1]; break; } } inline bool NEulerSearcher::vtxBdryLength1(int vertexID) { return (vertexState[vertexID].bdryNext[0] == vertexID && vertexState[vertexID].bdryEdges == 1); } inline bool NEulerSearcher::vtxBdryLength2( int vertexID1, int vertexID2) { return (vertexState[vertexID1].bdryNext[0] == vertexID2 && vertexState[vertexID1].bdryNext[1] == vertexID2 && vertexState[vertexID1].bdryEdges == 1 && vertexState[vertexID2].bdryEdges == 1); } // Inline functions for NCompactSearcher inline NCompactSearcher::TetVertexState::TetVertexState() : parent(-1), rank(0), bdry(3), twistUp(0), hadEqualRank(false) { } inline NCompactSearcher::TetEdgeState::TetEdgeState() : parent(-1), rank(0), size(1), bounded(true), twistUp(0), hadEqualRank(false) { } inline NCompactSearcher::~NCompactSearcher() { delete[] vertexState; delete[] vertexStateChanged; delete[] edgeState; delete[] edgeStateChanged; } inline char NCompactSearcher::dataTag() const { return NCompactSearcher::dataTag_; } inline int NCompactSearcher::findEdgeClass(int edgeID) const { while (edgeState[edgeID].parent >= 0) edgeID = edgeState[edgeID].parent; return edgeID; } inline int NCompactSearcher::findEdgeClass(int edgeID, char& twisted) const { for ( ; edgeState[edgeID].parent >= 0; edgeID = edgeState[edgeID].parent) twisted ^= edgeState[edgeID].twistUp; return edgeID; } inline void NCompactSearcher::vtxBdryJoin(int vertexID, char end, int adjVertexID, char twist) { vertexState[vertexID].bdryNext[static_cast(end)] = adjVertexID; vertexState[vertexID].bdryTwist[static_cast(end)] = twist; vertexState[adjVertexID].bdryNext[(end ^ 1) ^ twist] = vertexID; vertexState[adjVertexID].bdryTwist[(end ^ 1) ^ twist] = twist; } inline void NCompactSearcher::vtxBdryFixAdj(int vertexID) { if (vertexState[vertexID].bdryNext[0] != vertexID) { vertexState[vertexState[vertexID].bdryNext[0]]. bdryNext[1 ^ vertexState[vertexID].bdryTwist[0]] = vertexID; vertexState[vertexState[vertexID].bdryNext[0]]. bdryTwist[1 ^ vertexState[vertexID].bdryTwist[0]] = vertexState[vertexID].bdryTwist[0]; vertexState[vertexState[vertexID].bdryNext[1]]. bdryNext[0 ^ vertexState[vertexID].bdryTwist[1]] = vertexID; vertexState[vertexState[vertexID].bdryNext[1]]. bdryTwist[0 ^ vertexState[vertexID].bdryTwist[1]] = vertexState[vertexID].bdryTwist[1]; } } inline void NCompactSearcher::vtxBdryBackup(int vertexID) { vertexState[vertexID].bdryNextOld[0] = vertexState[vertexID].bdryNext[0]; vertexState[vertexID].bdryNextOld[1] = vertexState[vertexID].bdryNext[1]; vertexState[vertexID].bdryTwistOld[0] = vertexState[vertexID].bdryTwist[0]; vertexState[vertexID].bdryTwistOld[1] = vertexState[vertexID].bdryTwist[1]; } inline void NCompactSearcher::vtxBdryRestore(int vertexID) { vertexState[vertexID].bdryNext[0] = vertexState[vertexID].bdryNextOld[0]; vertexState[vertexID].bdryNext[1] = vertexState[vertexID].bdryNextOld[1]; vertexState[vertexID].bdryTwist[0] = vertexState[vertexID].bdryTwistOld[0]; vertexState[vertexID].bdryTwist[1] = vertexState[vertexID].bdryTwistOld[1]; } inline void NCompactSearcher::vtxBdryNext(int vertexID, int tet, int vertex, int bdryFace, int next[2], char twist[2]) { switch (vertexState[vertexID].bdryEdges) { case 3: next[0] = next[1] = vertexID; twist[0] = twist[1] = 0; break; case 2: if (permIndex(tet, vertexLinkNextFace[vertex][bdryFace]) < 0) { next[0] = vertexState[vertexID].bdryNext[0]; twist[0] = vertexState[vertexID].bdryTwist[0]; next[1] = vertexID; twist[1] = 0; } else if (permIndex(tet, vertexLinkPrevFace[vertex][bdryFace]) < 0) { next[0] = vertexID; twist[0] = 0; next[1] = vertexState[vertexID].bdryNext[1]; twist[1] = vertexState[vertexID].bdryTwist[1]; } else { // We must be in the process of gluing a tetrahedron // to itself, and one of the gluings hasn't happened // yet (hence bdryEdges == 2 but only one boundary // edge shows up in the gluing permutations). // The boundary that we're not seeing must belong // to either the tetrahedron face we are currently // working with or its adjacent partner. int ghostFace = (bdryFace == order[orderElt].facet ? (*pairing_)[order[orderElt]].facet : order[orderElt].facet); if (vertexLinkNextFace[vertex][bdryFace] == ghostFace) { next[0] = vertexState[vertexID].bdryNext[0]; twist[0] = vertexState[vertexID].bdryTwist[0]; next[1] = vertexID; twist[1] = 0; } else { // Sanity check. if (vertexLinkPrevFace[vertex][bdryFace] != ghostFace) std::cerr << "ERROR: Inconsistent vertex link " "boundary information!" << std::endl; next[0] = vertexID; twist[0] = 0; next[1] = vertexState[vertexID].bdryNext[1]; twist[1] = vertexState[vertexID].bdryTwist[1]; } } break; case 1: next[0] = vertexState[vertexID].bdryNext[0]; next[1] = vertexState[vertexID].bdryNext[1]; twist[0] = vertexState[vertexID].bdryTwist[0]; twist[1] = vertexState[vertexID].bdryTwist[1]; break; } } inline bool NCompactSearcher::vtxBdryLength1(int vertexID) { return (vertexState[vertexID].bdryNext[0] == vertexID && vertexState[vertexID].bdryEdges == 1); } inline bool NCompactSearcher::vtxBdryLength2( int vertexID1, int vertexID2) { return (vertexState[vertexID1].bdryNext[0] == vertexID2 && vertexState[vertexID1].bdryNext[1] == vertexID2 && vertexState[vertexID1].bdryEdges == 1 && vertexState[vertexID2].bdryEdges == 1); } // Inline functions for NClosedPrimeMinSearcher inline NClosedPrimeMinSearcher::~NClosedPrimeMinSearcher() { delete[] orderType; if (chainPermIndices) delete[] chainPermIndices; } inline char NClosedPrimeMinSearcher::dataTag() const { return NClosedPrimeMinSearcher::dataTag_; } // Inline functions for NHyperbolicMinSearcher inline char NHyperbolicMinSearcher::dataTag() const { return NHyperbolicMinSearcher::dataTag_; } } // namespace regina #endif regina-4.96/engine/checkdocs000755 000765 000024 00000000453 12234011536 015730 0ustar00babstaff000000 000000 #!/bin/sh for i in `find . -name "*.h"`; do if ! grep -r "@{\$" $i > /dev/null; then case "$i" in *registry.h ) ;; * ) echo "$i : No group opening tag." ;; esac elif ! grep -r "@}\*/\$" $i > /dev/null; then echo "$i : No group closing tag." fi done regina-4.96/engine/CMakeLists.txt000644 000765 000024 00000006520 12377774125 016637 0ustar00babstaff000000 000000 # Engine # The tokyocabinet library is only used internally by the engine (i.e., it # never appears in the engine headers, only the .cpp sources). # Therefore we include it only here within engine/, not globally. INCLUDE_DIRECTORIES(${TOKYOCABINET_INCLUDE_DIRS}) LINK_DIRECTORIES(${TOKYOCABINET_LIBRARY_DIRS}) SET ( SOURCES engine shareableobject ) # Each of these subdirectories modifies the SOURCE variable, # adding more source files ADD_SUBDIRECTORY("algebra") ADD_SUBDIRECTORY("angle") ADD_SUBDIRECTORY("census") ADD_SUBDIRECTORY("data") ADD_SUBDIRECTORY("dim2") ADD_SUBDIRECTORY("enumerate") ADD_SUBDIRECTORY("file") ADD_SUBDIRECTORY("foreign") ADD_SUBDIRECTORY("generic") ADD_SUBDIRECTORY("manifold") ADD_SUBDIRECTORY("maths") ADD_SUBDIRECTORY("packet") ADD_SUBDIRECTORY("progress") IF (NOT EXCLUDE_SNAPPEA) ADD_SUBDIRECTORY("snappea") ENDIF (NOT EXCLUDE_SNAPPEA) ADD_SUBDIRECTORY("split") ADD_SUBDIRECTORY("subcomplex") ADD_SUBDIRECTORY("surfaces") ADD_SUBDIRECTORY("triangulation") ADD_SUBDIRECTORY("utilities") # Some C files need to be compiled using the C++ compiler (e.g., snappea, # where we have added C++ namespaces). SET_SOURCE_FILES_PROPERTIES( ${SOURCES_C_AS_CPP} PROPERTIES LANGUAGE CXX ) ADD_DEFINITIONS(-DREGINA_DLL_EXPORTS=1) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/engine) INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/engine) ADD_LIBRARY("regina-engine" SHARED ${SOURCES} ) # All of the libraries that appear in ENGINE_LINK_LIBRARIES feature in # the engine headers, which means they may be expose to third-party apps # that build against libregina-engine. # Note: PUBLIC and PRIVATE only appeard in CMake 2.8.12. # For compatibility back to 2.8.7 we use LINK_PUBLIC and LINK_PRIVATE instead. SET(ENGINE_LINK_LIBRARIES ${LIBXML2_LIBRARIES} ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} ${ZLIB_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) TARGET_LINK_LIBRARIES(regina-engine LINK_PUBLIC ${ENGINE_LINK_LIBRARIES} LINK_PRIVATE ${ICONV_LIBRARY} ${TOKYOCABINET_LIBRARIES}) SET_TARGET_PROPERTIES(regina-engine PROPERTIES VERSION ${PACKAGE_VERSION}) SET_TARGET_PROPERTIES(regina-engine PROPERTIES SOVERSION ${PACKAGE_VERSION}) SET( HEADERS ${HEADERS} docs.h engine.h regina-core.h shareableobject.h ) SET( MANS ${MANS} regina-engine-config.1 ) # Build space-separated lists of flags for regine-engine-config: GET_DIRECTORY_PROPERTY(ENGINE_INCLUDE_DIRECTORIES DIRECTORY .. INCLUDE_DIRECTORIES) foreach(arg ${ENGINE_INCLUDE_DIRECTORIES}) SET(RECONFIG_INCLUDE_FLAGS "${RECONFIG_INCLUDE_FLAGS} -I${arg}") endforeach(arg ${ENGINE_INCLUDE_DIRECTORIES}) foreach(arg ${ENGINE_LINK_LIBRARIES}) SET(RECONFIG_LINK_FLAGS "${RECONFIG_LINK_FLAGS} ${arg}") endforeach(arg ${ENGINE_LINK_LIBRARIES}) CONFIGURE_FILE ( regina-engine-config.in "${PROJECT_BINARY_DIR}/engine/regina-engine-config" @ONLY ) INSTALL(TARGETS regina-engine LIBRARY DESTINATION ${LIBDIR} RUNTIME DESTINATION ${BINDIR} COMPONENT Runtime) if (${REGINA_INSTALL_DEV}) INSTALL(FILES ${HEADERS} DESTINATION ${INCLUDEDIR} COMPONENT Development) INSTALL(FILES ${CMAKE_BINARY_DIR}/engine/regina-config.h DESTINATION ${INCLUDEDIR} COMPONENT Development) INSTALL(PROGRAMS ${PROJECT_BINARY_DIR}/engine/regina-engine-config DESTINATION bin COMPONENT Development) INSTALL(FILES regina-engine-config.1 DESTINATION ${MANDIR}/man1 COMPONENT Development) endif (${REGINA_INSTALL_DEV}) # Miscellaneous extras: ADD_SUBDIRECTORY("doxygen") regina-4.96/engine/data/census/closed-hyp-census-full.dat.gz000644 000765 000024 00001434766 12400005715 023723 0ustar00babstaff000000 000000 ‹ÌæSclosed-hyp-census-full.dat”ýÇ’$×’- Îû+jˆ¹(1NÞÌßía¸ˆÇ'眞øúÖ¥ºÍÜ<ញà(”„ƶM”.]Z~­÷¯ïï0MÒ¬È󢨋~^×5ëÒÿÑþ×· WsMÇp]ǧ¿ýÏÿó?¦™ýmþŸÿÑÿ¿ÿŸòk]¿é‡³¼À_E/Ã’US+?ìé¦ãy†çù†aúùÃÆÿù“øöC?|üâ|Ÿç`*×.ÿGÿ_M·|Kw4ÇÒ|Ç6ùa÷/ùÅÕýqÿ®‚ˆ~¸,é§Ë¶ÊÊbî“&kéÇ Çt5ß0=Çö4Ë|.ÜâßM?¿ÒWWQ\ÒOÑÏÓŸS:vkWfm†Ÿ÷,˳MM³Ï´-K~ÞúËyþúï{FYN‹§”óÔ´]ÛVq\Ó›¾gkžçY:ýCsœãÇõÿó?Æõ·çøíôôÛ'üö¬"úqK·4G×,ÚÛôuõãþ_ÖñÛùǃ(/ñË‹œ>¾ßû îë¤ùøãrj–ZýC6/'´|Þ¼¥Ž››g¦£ë¾¦¾á¶qÝ¼ËæÓ×§¯_Ÿu{šNË€Ÿ§_ïÓ;®AwÇò¯7ùëkúéýþ(г4¡ÅWUYåSÄùPõÕVAÐÍS4‘Ûð-×5éïtˆt öq¿ÞŸòåþØ–i;ž¯ë–«{¶ý¼»öq¾èæÓ$~:Ç,YP­kÇÞ½\€ïÇ£ “,Où——yž}ÌERáÇ=SwèÍ1,O7¼ãÇX¿nt€8¿ë/‹º†nêŠ=hóãç¬ôñ|e‘V´}8€¬[· ³°a žc9ŽéÓî鎩‰G=?’ðóóÃ"\áOí¶Ö}‘ÌSúQ‚ì õ<(ÆóÇ'Ðسq÷¾Â {ãh¾«Óûõè&èÇ þ6Õ®_ìÔG‰;HÚ'oÒzZgÞ×vuá+¬Ó3´uyÁº  îðíöà;œäÇ .ú<(²5¤÷ Ë´,Ó0 ˆ0´c ÿ~·‡YY¼Y»Vô¦=€S÷M~=ˆéiÇ+~®àçû†  [ÀW(Ÿš8¥åoãøéÇuíPŸòŒ¾òŒð UÅϨXè†`øÍ þ¶Õ1’¾Ñ;"Lk( ¼Ä8ˆ‹vKÂe)>¯BÇE–E¬÷Ià‡DO2Új-ó ˆ×²û(ò”ðõCÚ,ÂIüeEG]ÓìùÆè1y¶OšÀp×õϳ8>CE‘€ªd!¤¢hÇ´í÷"üó=®· —‘¬`(Ë¥YŠ)L÷°îñãžMJÕ5lÛ6é9«Ëä\n]fVH°e¢è,¢iÍ#:Šò“úˆó6¬ß÷ûy ”è³l˜i[?þ8­@? Úã†çS “Röó2gÙ’¶Cðñ Ü—/¸=D¥fê R»,æ¨KE„¯[†íhd;èã÷:Í×5:—ôçûäœ÷ù¸+Y\%ÒøìaK{×ÕJv!d†¡k†­i6=OåQÐe|¾ˆ¯MÞ$½‡¬½–SšîAÀ²’'bRÑ|Û¢ ©ZÅ: Ëm…„„ÞTU±Yȇ<؇½Éë”?6¾ÁÒ ×r\ï<ˆó2~ñgDx¤ðudkÔo{½·EøÏü| }›|zU¶eè 8W`|~“åë›ôÉ£3]Çv]òsË8D\6òþ}§ÅïŽj'5×¥tœÛ' ¸Oçi®·Þ$ìC%«Èó¥Ìò6+Æqÿ.ži’SïѽbÆéfÈNÊ•„ŽgKW²êš¡ˆ“u…Ãö-Ûðt²5žXyWYùš­ôƒu (ÅÐlm0§[—,ÁƒŸGÛ%gÃx9N%bãE`+d'è8÷bŸÚaÈRY]gº´ ºÜ®,Â|QÊX&)ôÎ#Ÿâf Ц§…|AÆÊ9ô4T=h’e9&®e»gi5×I¿O¡¿\ ò¹p)r܉*мÆ>Š:©Çé£í𙱊¯ï¬ERb.ª¹™·5š¶2_Š"ü‹ãq'¿GÝLèYX‹”\Ï hÚ¼ü§ãxâ*âX¾nwºZ0¢ñÃ8Éšºë»¡ûqš¦yÞ÷’þªë8Ë,›"º´ûø›ï“ëÖˆö¸³[[àë꺆cK·õ}I^ É ýIO–”¹ºs†%;Ï;û}ç/Ìs¾tx{Ù¤Y\æuÌ"<‹¡Ã«0MëXÆó¶¬w>¨\b—È=oæ!Þãµ›>JpއÃ_‚ NY#úÚ R„é´tÜCÆ»A¾¡­;ô€4Ó3=ýPBÎ)ãçÏH ‘ÚŽ}Ïó5Zçz¯¦é72.»ANÖ=zzYüþ”›UˆÛ6ó =ͽÚvCÖñ¸s´@°ŸuMµAµy±E[‰ç£“6õÉã×\Lœ¯ÏGéäùë¶áòÞ¬VQÆiÕµMÝŽÝÐÃ0Mù@·¯/‚~Ö¶³´Ë+–ë9 Q䑽óÏ£zº._ìºÄ¬øóâ­Èºvj‹zÃu¦€¾Ï¤‘é1Ž£2_}|Ÿ¼`íP0Ð+?K°•„ºåv'ðÄý+®Å0US8Š W7éš&¢iû|Ù›õ%wïšíBÂ$IšqëxdpI¿Û.Ip=×9ÞåEWß”ÍI Ž(pïËtÙ«4­&–ài$…"KürϽ.âð@~d7ÉfÈ^ÄÛ^Ž{3U}‘A„i!– ›O¶C{îæu7±ÿ©Ü|Øÿmk£m ªí“寮d³•³7J‘ýÞŽe=æ¿ñüŒû×MvâøŒ¶Ú6òÇš5OfH°i=œªi»¾ã¶ó—k?²`'"‹—¾¨›ˆUõ{ ú56 5<àÇÍ‘Ø`è‡a\˲ÙY“éžå’2smzÄ«ÉÝ6­ë^nêJ¤9loÉ:’¢ÞÒ_‡O›@n˜fë¦ohæõ@Íûr~HŽcGŠoúdã‹éÛ>Åvd¾}ÚJË>¡4î¶ŠÙ9îØöm3´]פîó¼ÚK2£AUeaG-cUoP¨½äiŽn¦~.M2 8æÛŸ,Ç)±¢¥’ ¦F¾i$ æõŠ~mwåá‚B |¢4ˆ›=¨{¨US§ý°-n˜IïÎ=…<íäÏCR.쌨o‰×hž{zmEç–®l'É­Jø–×üTŠ9[§h^Êe©>É ýPËàWO ñ! [Îç2÷59»s¼mÁвσb¥ ±ÿ3@;…ü¬Þ‘r]¼!íÚ/ÅR Y4}â<…`!_ßö h :šd†j£Ào¯d%P¥tÃÉk¶ R¨GP`ý«Må !ÏŒ®N"fß?6Uÿ5¶yÞôVnú nºÉÞ‹N÷KÓÍãz(—ùq“ÀÿØÒòÜÑ1?Šp´Û÷×ýö ’Á‰¢£-)n/«"¬=1Ó6èvúšM“ “s®C^ oè„<7”„ÄM2dSd3}ÝG!îSY·-» ˆ8±’¶Z«5ØÉ}">x2õ– Ýq*"£ågûà Zèt\±ªiVêÓL.¹ñðeP¢7G ±-äe-ä½ú…ÊᔌrDê$î×OÌgµ€vä~ãØWS8Ü=kIÍ…,ÁÒ}2Ò&êE¶*öЧ(o¨U÷ãTKèG¡Ró‰Ôy CÛgt»é’“oXŠNšû|»öa¡¾øŽÄd'a\ Z̶ä¸%á6eK@Á÷5ßt µ©ºu¤ß+Ôò…JwÝ$…LGìë¤ókžÑÞËãò^8ºS&pEè¡Yäÿè0sôwëò)j!Û·ÜXJ vé†ìy°ìM›-Ë ›@Ûé‘„BÞ%˜·Îu|}ó: %ƒ×±äóÜMUõI­ãô_°#¼ò_JQíä¥I¼7cÜ=dК ?Fyb¢?”ŒÇм Mj? Ú‚üBùR§0Ș!z¬C¥«IÞåpqMü#ƒ;FM/È{f‘±4}“Äè:ù¼Þa¹ŸŠl{|K´ËÁœD»ÃäÕ0ï|,އJ¨ïPðà1á¿x„’ˆ«OB”'b(_õñ¸ÝªKzÎê™ %]0}”sú-œd½ª¡PÙeC«i¦)h²tŸÖ:¯æô£ã¯Ë=!q]7W^à4MU¾-åÇm1OPmËFFœ¬8G­P'¬¢étvXÎ=â365úÓðPcô|U4µS»"ׄG(ù÷šÕ<]ürÊ‚ž"è‚ÏØÒI3RPª‘ ŠG®¾æSq@Ä~3 §h$rœódI³­c!¾m9ŽF¾‘©[æyëŸïïëñÃURØŠª))žjê!†uš—¬Eíh;ŽkZ®ç#®òUþÌp®ï˜®-#2$eÝ@'ÐjÚ½ ú IÚ‘‡Â\Šu52H꩘ù%§ø#>8Y RõpÃYS/y\dU:~”q kÖï”=”GJ ±Ê}Ø÷|]Ã=+?Šx†5ëmE<¥I™!£³ÌKÎiVU~Anßñ|Økå ‹r$¹7åI™fŸDÚKšVR¬ˆóŠº’ë°WU—×M—­„­ ñ-®’Ö ÒtU<@Š(¦&šË XÊìã–x—]Eô=+ Uu–@ûiû(âRaX×§Îìa7œv$ϳq£›×û§q´§{DÚz>‰±Ùžìg3Žùºµ’¼•¡Üp]9{ß÷û­`Q¦TÒ¾“ë»))É4ÿxI çÈŠa°5áâÓ™Žè›®mâ:>­Ä’‚&+Çõ±}±ÛIf ~+ýÖ¯ ò€^à 9g™ß¯ÄU+¾TÌø@m•ËXeKʤm»¾'}½¶}› ÁR•]±·o®sfI~Ò¼Å. Y@Û¥ðïˆÇ«³ôûwÜ~b\±¿}ÇÕÇuhg®å„ö äëy¦FöÜv|爤~ƒÐâgcc Ÿ¾àäùÖV1Ùöp_ZN”Ú¾m’¦§Ý¤8Ø’¢3.í5³ð@òKt,¬E]*–<‹ ïÏ!gÞÓ “ØgÉÆp^´ý*ŽpÂÁ´}YeÓ°“Æ“f!¶E"àÖSh\­¨²Æ7ÄôCBèù`)p·€­Z×t" P}”cÊ@U¾â_pñ–³ôMÑ$Ѷ|bþuÆ\??äqáÎF*À ÕÔ 2‘S´ÓÔkËÑŽ£¤Î,ËÓ}Ë<ó—ç éAXjŸ5¹tûéß‚¹†WÚ¥Ë!¿O·]²¦+Ì›á^ ú¤o ‘‰´ËœÇYØÆáFÏ‘ɰ(h²È¤O¢{s¸]/1Âã[bY|m‹³Ã¾Ä}Ö² ©yÀ?÷ÈrÒ]\Èû]Ëœ#óZÐsaô»\ŠTÜÛ†ç™þáâ_‚·Ÿí¶Áý£e@Xsx¿¯y°¶QžsÊÄ15™†©ºm:öqó/ûñ…ý€—ƒ@AùÃk;¼Œ%Ÿ cØŸ¤q]íê¯uÆɬ£ÎØukWÄq›ñÇvB>±m“Oí*$„èÏöCÂêªÈ$u $Õ^mS4E³+è´I’qõÓ™}s¼õ¯ÇûFŽ÷šš»qj®ä9¶•ëÛÓ¶gMÑC8t&& ±ôŽuCÜGz™“þ€÷ÝÊY$~9õVq¶MKÉ2L¨Pƒ\7ÓPÓ¹\3VJ|LÍ2(6OË:¦2mxCP‡æäCÌsWO7Žùƒ>&ÎT ¾½¹8Øó1âê‹ãXôüèo¾a{äúB.÷ý‡uR–¥; ¸gQYíÅÑãã…ëHûêÑu£wç{§Nz^´ûªlEÊfôpcÛz Óh>aKj=c•—9Ø%‡g€-zaO’hä é­8Ž—‹†+OBrºeÈ‹AÈõ^ÑÆIõOBôC«q‚_áœUé#hØqÝ›$^æ2?íŠuB)$¥Í»’ÃE)Ž®×uèéŽd˺ퟶVÝ5õúnÈ{ÀÏI«¢ÍÉòð-èÏßììscI=¾(pÍ`¥j-÷ n†l*«Gì¾Ô ä— GU’i˜¦YÒˆ z1ˆ¼Mj–‡5žï†= òüö`´A?íºu{½´iÇ2|zÀžFnù%²æ¼6d»I%+‡ÇUW-ü$†f“ $Ç` ‚AêÕ(ÓÐ-Ïs}çP°îÅþý&¾–Ç}KÊÚ;ð­ŽA“¬w‘Q(Ëhfqt¿“qq´?w•È=Rle5’£´Q¸²äëÑÙ˜ºf“¶ 댞)6I8d•ì,âü¸Œ§`˜ƒbÆB\ݰlÏÃv ©'s¨rñq~ø¦(‹C MIþM­gqèl|2;&¹IdÈ ¢ë§ÛØ~)m5Œ_Í9åœÔ|T¶e²ìËÔ~=m]³0wNå0"¤*%•mé¼ÏÕÄäØteÑ`ÐΈw¢?áP¼³]§ÈLjWzÖql[ÅB\dPMî ™QÍ?òü ¢0J >è3JÄõ(Â7}¸Žæª9ÏŠ'¨G§#*šŠtŠºq{3FYØq1øý÷ƒò¥¼fIưÂVõKòã> 1µ«CÊwŸ3ˆ%ËÈöh˷ö72.ªöþP÷–s(µR+y$k¾­"Äñ4r ÈA ¿yâ¡xÆÕúÜQΓE?e8(B§¢ FÆ”xša »L¯ÙCûôÍŸ6éorNØÃSlP-t÷ÉÓÇ1{>ÒµgkHßc‰Ž´¯ ù‡6(ɶ‘o4»O׎n‹È8²mGJèJšÐãAC<”(ëË,()Úÿ „4ÔP¾×)åS§LWâœ)æVtÊíQqôÆ(¾F‚„bZ2#ƒD,pét´¤­iw U*w½KóÐú8áòçÓ6FÑ< mðZÈ%7ègé²Ðš†$/ôgòâ|²‡¨ØÃœ"FÚ`›¦bH–¾ÍÛb°¹g¹‹YÜÐ4á®àAÂfiUaôA†núÊù›!vÿùfp&EÓ6]=´}?Ž#¾œ£¤©Ó*Ϧ´>¯ë¥NûOëZ*ëJbÊö㮪—›=èë `{ŒÆe/›2žƒOB,ãš0æF-¨Ì:—I¼ [LKMÚjü(ãÀ%~:¬ürXÃÇMqüçaýpò-àJku訂¹0"(,?ÉðŒ«âÝØ SÈ™º©q‰IMmsßluÙÖYþñ“Ž&²Içõ.»Fa‚ÄJÓЉ7Ý0 y¾Më<õ8ÕMZyùñ´œËF?¾¤Bì6ë=Räyžµýµ%×_>môˉóÓ"ý‹Œ‚ÖÒt]ÛfÙƒ¤þô´4çL¥­ÛJ2‚4ÉTz’Ö1ìÙ:'e˜‘Ö ––,ˆf’Ge{Ç6?ó¤Ç»i’ SÄ2zzUÝ:6äv‡üÄ-Ç&×Ã"5®9¶ÒY䤯ÑÝQšW…F®Í£4?Ê:\à448ɰ÷}q09³(µyQâRœçÚ|ùQ†s ¥uÿ––«²(Øõ¨›}oÊqÛšxȃ– Šc“f˜ô‡£“÷ çë¾”€~ëòp€po*á^¬’ô.ÁsG`Æ÷„‚³=Š»}ªÒ!Þ> q®Em6·êj šæâbNò]“|)2qddÉj»§œ§ó/b9ç'±œÓÀ}–ã¾d³ïQU,ÄXÈ4<Çp‡×Ó_væûò $œS€¢ ú (š­b †ç–o˜gëTH‚SÓþºTûQd§* 9kÉ y…iåÜ %©IŽoZ Û¶aX§ÿT¾?/yJºÖ¸&xJÍ>ÒÂÒ2e¨-깎ëz‚ÒOââV¡Š`Mº9Ei=<ô ݦ1<ßðMOê[üIæSÍ!U 5—R¬5·×ÓÔåu­„¸6#b«VP¨¨‹1Á!UÈ•ˆ·Z³j£ÏèÛ"^‹iÑAÓz,ÝEu÷´ö—¼ ëþèV»¶I£² Yi'ÝC{0Z4­3в“é(Étø&ðrš…{ƒ¤ò™é0~“é(Ét|òT/õGJ~IŠ‹‹â=ÜļP–ÌQײÚͲÈ7P…б­‹žú£öæƒû L ð=úá¾x/AÎÁÐrêœ3²¤P6nªjê)ÀVà´²Õº¦{žo:gŒn¿"ÐqÈÀ„èôº}›bL²2L÷­ÝUö$:Ô÷F^ÐHaóÜLã*b| Q—vÂQmRî%ôÇÄ_*ßä’©Öè«4r5í’ø;€0ÿNþ ŠV¨K–¸xe0ìyÁ¸årñ\Oñkø¾æ*-e×üáouùI†}U˜wz’Dû;wsÀsHM ¢<å"Ë&¿Î2mí8éçS"1_ß§˜²¾ŠI³mÌXez  0<ÃG¢Øz" Îþ64EþÜî7¦åàžÈ ø€nìÆaš&i‰ŒC ÛÖ*N‡.Ø·OrÏb%דè&2”B¹WXj ØqÒÁð›å]P€ß?7‰ÖS‰/$ˆªx_§$ßcV<(’ÓI±$ÚÔÏPòRäæE„Å|‹‰Öqê¢O³ÿ1ÿ—îŽï Øoƒ{BRû‡ö‘/Ñ÷õÕ—+4ŒBn¯‹ê«Nž«¡{Ç ºÆo¬K™Õ¬Ò§nêÒ©Üz[ŸdøoSêy©ü<&!©Ik‘g/B~³ACAêK;]šóþKËy8jV[tÆnƒz(Ó±g1¦¡™Ž :—‚7íP—ÊÉ£FE*É…€_DŽÀHû@O}ª6äí%5A'íûäó¹®bš.G -b›à¤+h㡊Òn {³‹¡ © …ûY*x"ȳ$¿PèZêlóLŽD¼U,‡¢sѹ ºs“·ŽÆý—Æ2,C¦MÒŒÝôIˆç=ÝÏÆlêUóZÈP5Õ–ÖtÚ‡}CWàZþ¸}ÿ00)h¡ØMzN©¤˜Êüãr,ýRQý}Vq? ±ýç7=€»&U ¸‰ „¡J鸃!Øó’ÜüòãZœ°Õ—–Hj8(:§,¢ø¶É ùZd#,Ƕ]×B7È‘ˆ»bÚ¹ï2NPa' Eª†Ü£~Æ•7Ej ( Ø¿!Ÿée17@EpiR~Ph¢Å”e¾ y6Än@ކZ‹KU-Ò|©6£«ŽÙy n¨j:&¨ˆ¡êö²ú³}b¥{·ñCÈs†o6rØA×5Á´ãúq-öµÞ| €½ (¬Ø+ÁÓ v”4÷òãjޤk§r3ª³–“ÓÖ´m \ÅK^Óž¯íøIç&¯_ú¨*Žò™×èÖ ª­ '®H>­ÈtÍ 8îÆ7xUœÔæ.7ŠQëbÌ7H)‚rÀ¥|Pø8®¥ ñÙ±'—“¶)Ò¤´ÏtuÊ•Ä6ZH±¢pÈ¿&¿ÏÑHå˜Òi(p€Ò¤ëȉ d4àâî´Ë,ó0ŒSÊçåŸÛ¢€×4¯ ëóx‘#w°mš I†a¢Øã7rž<¿ù›\ݵ\Ý"še<— èûŽ÷æ‚al8„§°!ë>ÈGyœïäœ]Õȱ¬ÈV’ª(ó£É”4ÅRKÓfd}Y)sÓ oÖ$“­9—Æ—³†v»ÖYg‘É’ IÕ'gk%.ñÊûw™7¬@CY©!¢}­ Ò¢k7‰Ú"5£‘å%»éxŽe_ÍË¡)°€ÊJòö:'i=}SKW{…Eu X,×ò4ãŠ5=Ã2®Í¤™@´ÙÉÞ³mï{òjêñ“ûªóä( ©_Ý Å<…"íÈ`Ts C7®y#ã_ˆ£¬Ù'“ž¤áÐ ´ãsÞä$¸+ˆ“i0,9_º:þ$Ã:! @Å_Böµ"EC «Ù·f’}ŒÚ¨Qhê|—Œ£ò5¦{…!þ¾Ü)BÀlà zsuM]^ÿ}߀õŽ‹ÄŒÎÌ'¦ÈZ.ãHÀê¯Õ3 ´©‚8@˜®MU¸{o×á]ƒïU•øóC†dÙ‘=­¶¶» –$›69KýY‹¾dë¶»ð¦% ìÂàÀn â8L×,9Ò\¾Õ=çåg}ܲP}¨ù„\e;ÄE“¦,Äáþu›”§çŠÕ6 ã¯ËZžù´ ù4կѦÂkÑѹi“–1mÅŒÃÆ]ÔÔí$ã˹õC%ŸŠ¢ º¿ÓÀb8³'­iÇ;³½2Ý…àÔãæËºšóz­Öaâ-É?1<ûrÔ¿-b°éGàn[¼·šmëÚá =zCÿoK\v­|×dH¦¶í:1Iàóð|²GÈ5:‚®ä'}ËÜࣱ;C.LUHó9ÓÖU>¥Èq—¦'iù– ¤’ÕqõÈíÄ1Åh`°YÓôÕ˜FCWd]šö"à*‹^µk»Î±¿Æ8€gp¯.ëòv¯è¾i¾«ÙLne £ ^Â¥ÞW¤r©Ð z©®öaŽXþ$æÀW±ža²"Ê)jNñ¡y) fº>ÛZniÀ÷49ù¯…a¾@rq¯ð ¢À¸—\_,àDÐåã@þHÝ•˜î *ËòE~=÷ßùj9ùj˜¡“GC‘®¦“¶0œÃÃ:?ŒÃ´ßq"²V ARì)² Ÿ%=Õ~‡£P·‘”íÐ0×{¸­i·•Ÿä8Ú5 l:.¢™ ÂLºÐY35U°oãg1¶~ñG>D«í­¶ÉG9 ]¤|kØ©{uñŽXaœîÑ^Ž¿‘s9ö»Ð°Æà½€®ùØÛ6î²u¬Ä=Ò ÓpMÔÛMd ‡zU9‘EI#… o¢ Ú m’8Ûòƒ.ó]“ð7•&Áõ¡èEÊså²,Y4Le³Û÷@ý¤;ÈOéÇ6[—œÒùã¸ÅþÚ‘Sj‹~éÑʆ‹Š£e¡Íâ?«Ÿ‹[òÑêUU×ÊÞ°âa( Åœã­_꿳àòÐ?ÈxÉŠéÌriîGŠ«ÂŒ!(»ŽŸ§z‚CvÊÒlË:Å›ÿF·‡›¶‰hƒKi ëÐíOôkîD¢”¡‘Ù»ªa«š©Ÿ»4 ×í£$ïéݼs«Û_Üê÷BŽ0žaÄwºzÐ7JqÕõÖäKNÚ8'ðd¸.¡ò¡raò´dh$!·þ"¯-k–C† JËÆµ;S?—¦ ÷ÒÀ9Ϲ´f×|­æµ%Ï„eødš|ÐÙøh]¼t³ïó¡2’¥£F&@GÊ÷-ÐëÜ®|w§A”é]ÙÞ¡dÞÀ©®âa‰—~eÿž€AV†,ƒm“çuVÌŸ6Æe2kcèÛšUq[}½7a·mkñ½±,|  |îÝ?ü¶ §Ëöý¥8—+R6ï°jÉ6½á·€ Lû Ö1ŠÈÎýyf8þBJÅÄP8çÒ÷Ðé`Ý8SHOÃpÛî·;SÌ$¹$L—í°a0O|ý,ú"ß34à*ohGþü²H¿à§>H¼ô>¬†Ñ£`œ§x)Ö¤7V´MY‡ÍoVõ AÖüÒ;xmO’AÈ{Þ rðÚ¤*\̾åª*Š­Ÿ–G6驸¦.ö%ØÃu,âyí~ë6Ýj‡b}´š}d®¯–† ØŠÓˆ öœ˜Õ¯ê(gÍnÛ¦¥“ci´.ݾÀÕ¤1ÿ$ÕäÍ&w»¬Ûšó§µèãdh§q Y’o€©Í¡àW×|ýÈÛ] Ø ¼BŠfê}„a¸çñ0Óé}ãŸbÖŸ;ØŽ*¦¯C›“8C›oc·ÖÁÖm¢™tÀüdûË{îÏô,ßý`n…ié"µ\iꆼаge˜*¥ãÎNg÷ú𵀈œrV ’“Ñ©³‘ˆc¢hxžgâé^*ÆE7+q¥‹Øt=]íq ?ó|ÌKŠœ–˜LXFÏ.N?É”bŠè¶måúL7 9$ªèçÓ”ãÌq°þfi/‘¾ä„EÿffU‹“mcuä8&ƒŠ Òügߦ§ó̺úÎP•ä™ràîe¤ËtŠ>Êð^ÜæM…´d µURcO÷¦LÇqL?­…Oß|ÙÏý[ysÒ[Јۣš À5ñAŒí_;Y¾îÒL–{þ(¤[ƒ ïÒaàèú Cs.27ƒ”d]™Qµ“Öȳ=ìRú·2Žši˜žûƒï29,xê5E}hŒ[»=¨ã5L{ÑŽéïks;)â •Ýä §œ—…Lü:¬ãøq—Ÿ^á{ M{"qòH|xÇGÇ­£Óë.í´æÓ÷¦›s«®ÕœÖ³eH¾Ì`Ëc %‚ÿ3áÿ´@pÆî×Ö ~¨g¨­b.‚ )5Žõ<7è¾¢G-:aJe ÕÁ.C޳}n£á£$íâ Ë]f!A¿mQÖdkl;g£ß 1®ü> [PïJ%áø]ek“„m6~ø¤ÉP~ª¢;C‡69uKÔŸê±)Òu h“²B,÷Ò ^@ü$*•ÏN;èôe;f·Ä¹&??Ü{ A%e{<ͬëQR^ƒ%ü$Çó.-Ç}H æiS0‚]ìVQUž&óR|ÜvÈœ6¸œÊò— å{'H Â?¤Ý§ßZfRïC?ôS?ó<3ÓM^¥t%çj›×b òö“hRñÎó¹~É` ° æ—²‹º­¹]9óonãaÇÖ ç÷ À*4t!–µ Ê®ªã“B²O 2…Í8wþ[Þõ×´Ô—Œù)3+ÒþyØŽm‘“h·›e¾ý4àÏÀ8ZÝí´¶5>œ¡]€tþ§_%\AœTا-`¿j*Ëß\€Ëù?~kžqQ 7Žp™÷ÁÔmc™Üûûþ£2IÂ=V©ÊVž¯AÞ“{Ö–,‡"1Ó± 4ùšvÂoþ‹’üÎÏÌC×8¿—ùG& Vñ’b}#u˜ó÷@¸”ÅRlal Û _Ól ¹2ê¨xÓÑ.Õ*ÁG$•Þb8°ä#ömÙ­Y·N¢&}ú,÷;Ä<‡+ÒûtWû ô\[¾Ïâ7Ñ8Dm´Müi¾i‘£©‘¶mG;+óç%üùºýð—qž¼ŠŠÂ§e²¼Oê]ž—ˆµÏD¾ùr™õç—­ÙGž'lhƒœôë@ñK“$,‡\ÛnÊÄóÄ]Àç_ß?ròYYŽò Ú}«°C3éÄM´Ù{`7:j?9ë}ý÷£iX4 —AÔC½VãZ±(ôæz@Êéä]iG^éðdÖ=y†Ã§e^g doš„‘ Ûôýœ‹Çw- $rŽt•ýo‚»j*9¸37Ñôþõg³×¥ºI×eÒ<•tãœã< ’:?Vä,Ôˆ<tcçÑ[t[¿À_B»R)`<8L@“yr¾Yõ0©‡všn¸u¬Èþ·i yöळmÏ÷(†6-˸>³ üV]ÑäMs…“3‚q«6¹8}ûÒÐi "_RýEb\îb[•3‹|Y“&ïXŒN?ïøˆŽšDõÏvæ‡ä%k6Ñ _"“,cÉ´ª,°†ÞÌÓ;úûWšù¾ÊnÊ·$X¶¾Ò‰w‡´3]º®ék$ѺºÔ¬óˆϲL¦Ý& ¢Êqî%M¿ 5írzº¦âخݫ¦нÏÓhëDŽm?my†kª\žvÁ`¯Ò¸XE³n$¢É¼†Ù:¡œÃØ–AåÑý¡/óÌÓ‡1ÎËÃyR.b4•¸LÐ^4EUÅ8ð¶¸:’žM«‘íq¯º•b…GðÍJn­àmnÇu?|;‹¤ò|°š;º® w¶{‘óò”0äiEŽc˜.rìôÌNtÆ‹rDoBH (Á4.u^wG@¡¢ÌHÚìlÖ•~Èz¢ž”ZSJn€§ù¬?t‘:­Ê1^ðEoSË審eR9ŽƒMòÉöí’cØÔ¡Ã묭XPPïíÖ¦U5²²d:=Z"Ó=ýŧüu»CV…™cß= öܗzjCã¡ï¬8¢þOÚŒÛÏ{å©ê#çÔÀ2/A˜-IÒdY­H·Ï„ãiSŒ .¦Sγ?íw»6ÄIn¡fÚëÊyW!˹_å0xæSœbºD©·n‚ÑúŒ6¬ßÞÁá×;h äëëø^z¯Uåo»Ý75ý¡àlÙa–Ë“„ÖÕ¶,ÉÖÐ6j¡ÛVvǸä^ojÔÏCe^i†ÅHÔ©œ"T¶:–äb µÇ=1ž‚"‡wQ@äÜ9iš…2÷P@ù^M{¸# @í²ïR dè†ë+ £?Mr¥ÈñLÎJ!Ûmèâ¡לsoÅØÏQ ¿ïFí¦T«±y “®@ŸйÙ??èÜWc{‹¢BŸ¸{ÛÚ/+¹ á–NJt³æùš¯†ï²#s…Ìm°@ÿSÉL´úr§/Ù"–CãÊ€Wèÿ“ð—É=ï×De‚@?13'¦ :ž¦`ZD )z÷tƒ@#wÆ@Ï|³{¨¬ëAï#+žüƒì5XÎ(P´ äO0êÅEß– †UÉ£‹¦ö*iyƒ, Íó€™;tvçs½Äô/Á&À¨Ï`“ÂªŽƒÍwbp©_R jJr] ’ÆÉ¶ Úv‚`Îe5º†n]Ís1Ô9P­×TòMå'#ªB=3? A´ÛÚ ,ÇDÔêi.=VÅ”9æa楡àGÆ$TÒ E>gÇ…ú} “}(÷}w²èôþäSå/>µiÙìæQ_ó/WñÉ’¹”‚›cü0J€È*/ˆ<Öi_¹ükHŠñ¤Kºvÿ¨ö>¦(nÊVUêÁ]KþË^#-iI´7 óNAò½CëwâR«ÙíÐâ àoC Í6‡i/"ÉóÑɉ6ýBjr !ÙªDºÑUÖ+.«d̃=ž¾‘× dìO>ž|™ey(ØZqýÓÇ»&„o«"Œf TT”i çz†2 øÑ’nDæÕ2˜Ä=nöƒòûu¾UühÌ©r‘Ìu)HW¥$í¹×?¤b%VŒà‚𑉶^Ó&‰ª),ˬS’È–ÓÕ”$¸çÖåÙÒ·ñ³EQ’Ë êÙ‚·4N†˜ž-'—ßÉÒýȶ*¤)è2ÍUÕ¾©Ç­.â–þCÄÙ'1¦åFÿÃ#Ù•Ms žY‡üÌ1^w_³_Üœ)•æ(©ZU»P 02ÓdTçÛŽ§“ßg_-ï6²ø2ù ¤êAJ—{êrJ÷~§÷?E²$\G©J¸|ÏÆ5½,ÊüCôaœJ+™(_éÙ®­,ÉóŸ.7š§uÿi®/F !Õ³5¸E¸£Úê´ëhO‚HŒš âkºßè>¸\<ïòly2ßí 0ŸñÝÎÈM¯’ h—žŸ-èƒù×uϽ|œyV;ÐP{«®µäÎ^ZjeEÜÞëÙès#GýL=]rÕ_#8Ò¦©•}Ü—¶ße2ÄK›CGO9~ÿŒðz¥$¡6·ÃС!æÁ{H{µ“yã„„‘õM‡k]"Ìó/z›ÏHƒ’, 6¶ÜšwaÙŒôAŒá½¸+w‡?[}DIJ¯÷IŒ¥l²B"NÀ± WWýw—î‘Ï÷LÍ(œRøØå?Ï ¤t2ÞžU-ïu]×EÒ-Y0Y+ªôäYë:T’R#žó~¦/k£²©eŸ”Q•nRð€Ñàì!Éó_/Œ†«”¤‹´Ì;è5ÔqoËÖîužuôvE˜gXŸù.t­JÇ{æe·™ ðqѬæB¸× ´o“¯s§#Æ¥Š‚ßx"ž,ü ‚Àk%ø¯| "ÄV6êx¶£">Óþ'›+ßmî-¬¸E+_Éa›Šzضñ£ëšuXUkk† 8g°¤½*Jöžâ‡|ú$‡ñݲžAÀœç”Æ«13»ï‘3ªš!ÚvÑ&Åò<Ѭn6Èàï§ @R& cY1:eÜš­¢/ÌF¸N,Çg—ÄÇèS5`×éĦô%ìE O‰lŠôå¸ð¥K’È EíÌY¡qؤ¿ÿ1æÓ¸SÕ‚ú¬·¸Þçzma'-MÃÔlWÓ)ÑMýlº¦g·¯ÝŸêábÏÓmê4ŒÒ®\Y”J.=: ‘-uxƵây$ ¥»Ž,#’}d‚c?h1tlú±U‘Ÿ{QÜôR8­Æ¹•RÁw0)n_É@¦CÜw5ߦw’ í 9ûw’âmû$óòi›jÇÈi)Z ¬ƒ9!Di·ŸæÏL¿JDÈË=2ìߊ~ ².£ð~—®ÜŽ¿í­ìÆê·[ôŒÿÅŠò+bQ]òU‰Š7«’ê+«€¼æh,ÓQÎC¾TÒ|²o桺ÿ]J IŸ]öšütCP¨D–R¿&}¨¿2@¬ÙQ;Gþ øaz&:“¬Ëöbƒx›¥a‘€sc¯ÅRZàò²þÜú—Ë=l.Éñª’}¤-ÛÚR¾ž¾ojšiSàu8—'‡¦'Ö\‹G~¬RÐï}›Á2#™-’äƒs„\ÒPî3 Tú’'ö@ | W´ädÂX¤ž¦šþsË%( ¼K.Ì7Y]_øÒMÏ¿†î+›ˆ#å µÁÆw{“ïÍÜÉx'F³¯ÊDf3c¸;OÿikÎc#å_Tà“ZÚ©>ˆ2œK¬g™Ÿ—Šk®2œ³­ö! Ø­eßý½ã¥7ûwà  l©úÓG߯§¸$½®}TŸîòTÑY‚R‚ƒî Þ¦r"ŧ$b͉ ¹ÎΙ͖§2ñ¸Áí¡°/aŒÒQÝ“9Ý ÌËC° Aº-åд3Û(̱Ó0YDE¼žþ¬ý¡ºÎó1H1•±g@ÓЗncTôA0äi$çH›eóÔN×4UÛ«8Ç=ß¾•§ŠËPXÓ¾Ç{Ð'{…$• ˜W·Ãã½ ––¹ r.ŒÓ~ y’'ãFnj/r@^ä£aš¼yçjëHçö%hEQ·yË;@<Ó·1²Bɨ¾Ìó`2]Ýð4ïiîž…6K“†žH*xØë Ê4RFV¼—c¾´‡þ^ýŽü~Á‰9žh–1ÌÓ-Ô¯ñîQŒF?œÀNÚ”J9yaÓÔv“H¢«Þ3—|CMˆ` SŒÓ¿¼=Z{3+8”?ËS»ÖÙ8nâ<[à¡%Š=r—‹®ž¦— Nå‚}É]d6ƒŠîE…c6ŠÚ!И©=Á0¯Iªoy/§ï,@þÃy^cl¡ó01ùÌÓ{¾Æßjò<êÜI"y¡ Nö&‹–HúƒA(‹Å6ˆÜ}í´›—„0RF9sÌäÊ.X;¯IScÖø6—Ey/×{câ§H†Kf€‡/nùÝ6±601[“Œn'ë¨ú:㎠âªmYÅA²âKÇ6b'ÅN ¹EÌ·õN³r•s“*2‚pp„³š¦,k“ ¯¸ Ö"§9 út<ôÁNø¥ $½½¬å0ò³b\ÌÞÙL9©~"âÛÓ@*@Ÿw<ãé}!%$–Î>XçrHÕµqOvФÎ<Ò’&¹Þ@CYg¾ërüL âYxµžk`ê½£Øý܃àø_8ÛþYŒw£¶ˆÃŽ-÷cŸDù¼'}Îb(ph—Ñ„oú¶]XŽW´Gáåi¦j¬ÌÚ<­ ¢ÚOrÿYR°¢z‰*š3¨ ÀÙ·wbXÏ^ábèmãB_D•2/I[ŽSõQøA ×™'â&‹—½Vû ã-Š•¼¤•]R÷ÊÙôÊ4×8á/¡É¸ò—ä4ûIÏì4×G¹ŒäiŽN 3T3"D]ñ ÒŠš¥R¬84)Ó`¦cßÇ!1&·×’ÓE!“BüxDZsøöutBKéFM žò}MújÛ¶påÊ 4éQ“ôϼµñ(&a®6?1ö¸¢”@ž¦LMõVŽsm GÜ ì7½0u8<·¾ÎÖ©GWõ"•Ü#þøù|íEw˜ÿÐe5héÛX—ͤËÈ…"ˆ œ/´KñJh¿fW#cøÈêFÍ](ò¸ Ûô£ý xƒ3-Å™’˜N ÚU uÏ».g»ÉDw.µ2ýñÁKÒ6kÙµßhææõÐK*H yG?þ?†Áfµ´J°G4¦{¢–Ä÷rü+Äï‡{´™s°PpU6Ñܱ—eµýS w&ØÏìEZ_ ¹ ää9ªt)´!§ãÃ¥OF rÒOâ¤åî’QäÁ…ß/\ˆ]×½!æœ ú´U/ô¡ ®  ²\$1Oçµæ2ØÉQÞ¦_iºÏB)§Ë¿8`ÞʲVéò•›~³ðóf¹öm­p‹9ËZ ÷–q€;7Y¹víÔ'}YÅZ®áù¶+غŸWÔòør l Á¹ÞUsóµ¿~µ÷ã‘Ú\áœÖ‘\켉GÈó èÁ'˜Fç m®ÓîB"TòˆˆFôl¶ÌñžŒñ” ËqÈ;Ó€d$Ÿß9¹íËpEUš˜V¸&²u›“ Ó38/maf3Ïçã­fœ¹DS¡´Ô ÷ǃ~â£ÑÁsÉeZ§©XÒ5í[qA]ði®GöÞVEr˜¢Ó„<¸U¡ d¨;?[ 6ö­¢y©—Fò6.ù2|ð`BK\+ÓtëŽD*\©ÀtJÑØÛ–çÍ0ToDM¯Ð`Zäâ¢ÕvCáÕZ‚,ž˜ëÝ’p¯û&Ì;ÏQ'sÎ:©ÃOŸ¦†œ;$E nø—Ä=vhì÷¶ö9–;ýv‡¼—"Ûøó­’`s#)G2‚œ½aWȺ÷;t…ÖÂÿ¤o‹Ø­ÇWy {ÓŽM¸u˶õ§!¹ñݶïûAÄ'\"ⶵߑbX Ô]DXäîŸÓ«íg·Ê@wÁúqX$HNA´olê‘øäe¡†ü5xÓ0K#ð É–ÄÓ*áh±¤=§ð‘TvÕ¥"‰\5ð@3ˆ*ynÎÊô_7î-d-æäªŒdlÛŽìIPB+Ñíè:‰g(B³P2'çÏ=0vþ1EºGPK7ŠiQ"Œ%E«Ë"Ï? kÙ4C·ôÅÂ> ‡¶kî‰k3ë<ïùÇ2>Ÿ yëpÅ5Ç|6 jÿÝ0œÙ}@rE¾ EZ.Háµb{´¢ ¶ezý¢¢›Ö! kR‘CVÜ­¤6]Á¡Ó=2n«bB®q´ !¦Ï–ºVLõ£x’u·OêŒöÙ¨ô˜M®'DŠÇmLÍÏWxPAçýT Cl鯵W ”JÇu4ÅHáûgzKU§)ƾ”§™Åð‰¹R16E¡¦Éx ßwg‡åý:‹8d™ç‡·¨_ŠkÊ>®Wc ÕP9ÓÕV›¯ÙÄÇ‘'UÃE (‘㡈³mP+¡a1IÜ3”x>¶ÜRx9M·^NÛÍO…L7ü íñmßñ.Æ[——‚âûíû’CŠ©À®‹œoëºÐžo­¯l°p6ÝÜ£Y—²¹§·Ó=½pÿ{Z/ëÐOÈñ}['•‚Ô;SäLºk¾r&È-ˆx,8Pn5÷4Yеñ0–¥4ÒÑJŒÊ)xåãà\ ø„„š­\®p¶bå0ƒ}ê²Ûù.®B~›OÎÆ Ù.ٰ؀nb˜'EqtŒç›;”ÀúsÿúAøqöô8¨Pµy›oEôMê;Þp°L€&yºo^ˆ*ŽnÛ„:‹ðMÅ$9m_c›,}WUc”6J††&Î3%yC¨,è»\KÔÒóDÑuZEuùA’iš`ÇNxe Õ ™uMÕ÷S·ÌË8oÛ¼®[¾—í4’Ö#1Æ f;íÝ"×쟿A ³q=Ô߻ӧoÖžd´pìW¹eÙbÎ0¶*Ì[î çéŸUËâÓ}Ö/†o_´•ybEn<Ò‹Sð¹?dŽ‘„Ÿ›q ÇdÌ3Yfbms¾/£àé?½faowekà)Ò£n8 Ÿ·{ŒÜp1IŠCºÉœ“nǘÂxúþ¯þÛôy+ésˆAS™Cn§í¨ ¬÷"æ 8£üœa’©{ ±´<Ë~IÀš‡#õøº)5ïuÕJ |@¢>dC—Š( ðIˆã¬Žß4®{tûÙø'ÏÁ¸2@Cá@ÒQè@G(cÈê1Ï'šÐ¹Se•ÑMSÈÆ÷’´K|Û~ãÁ ôJ*Ää´Ý¹¾Ø±<£Ç2Nk/7 @(îSq ç/ë{aJà‡‡µÃuGݲ0 Íר ÖŒ´Õ&+³€¨"gÑ¡ð\Ñ>GóýdœgÈ¿#½×r̈ÌC7Ìs0FSÔñ˜ †:ƒO6.ã‰a¿0‘ü0qpQ¥*Ñ×< ;£ 1(úqì6ùF['ÊÂõ:XM G»fŸ8-‹±l%b¾¥(¢ƒl‡ )¸ªJAµOr@¹éY†ôÐŽöß~db,™åJZ„:xÂyV„u1aÛ²ïôY>n©fäËš¬Â0Ø®“ \fŽH5™Ï&¢ÙHc``›‡Ø?#kMôñsH+Û“AbyP¬cV²GZÞÐ3픞r´—Äs3 “7‡2•°vKA¾Ð>mp‡q¥P¸$ ø€uµýÛö&rD´þAšöZ*<‹N÷Çý gü¼„³Ã0O§(ÝÖPq\ºÞ©£þþµÆÇ›ÎóÃù\öx â8墸m›äSáNj®­¦Á±ïy±¾5Q¨Ì˜ëYqSW’n!¹²EŽÉ}¢ø%EOøKx­\}åjfÉe[7’c·Y°lY)Kr)ŠÑxüŽækŠŸ‚cïŽä–Ìœ«Н+šÖ¨袷 ÷PÛ6 ŽŽ‰†uŠfÏLqÑàZ…—c¿áp …åä6†I5³Sà ZÓmLÍS£ÅMØ{˜<ÕËŸ(˜­äjãf š„B½vd½é¤åøà~vmÓ=áóÕýÀJýà뢨æ ÔƒüuÌÔCœRè Ϣ݄i}®Û—W·qŽ •ǘ¼© -8ìö¾]Û9(Gº¤T,z&ÀH‰(ëyÅá„1F6¡žËlÁ¦.wºU±¦ešVá'9Æ9#ÛÆ„so!¥ƒ–³µåN'Wìa˜5M(ßç“WàêPÁ˜%rv1^ßïj˜›ÈÁP›.Å ºZ”–ŸÑwüýu¬I ñsM朵QGnÈrl“BcÏ‹{†Ø—òvË£FÇÄ¡{ém,q6’ÛÊ[äë;©Lº´t…þÐÍcÏqÓï?éÞ`z2îÍ8´ãÜ×Ó@N"ç[ß ÃÆ_ Œt]\“Á„®þO»÷{Çw¼u¡º±Ô£³T#(¡–Jçe·¢ëHÐ%LŒŸ+9å°ÇͤäG<ÁÈÆd“u)çœ9ÉÕ"øÝLúþ ®´‘@¯8ÎÖ’l_ ;.|.ˆjÉȘ‡E·~;„°|B1à&Bk-ùÓ¶ªÿXþ Dêv üvÙcrV5©;ªô÷ÂNµÞ¿%‹@Ú)S»ÄYÉ~I×6í›9ãžqåËH/ CÙTVò‚'D%á 6 ´ü*êò&v’°Œ ÈZéÛtKAÁ±K— ôÄK6ªå ”*Aá°ç{Nâªx¤/éÅ9Jài'òö™µY1ÕÓ·¹Å ®ëÒ— Žk9-Á̵)’„†×õt씨_Û¹ÄR?ŸíñV9ì:]f£Un-ª´èª ŠE”«Q˜M&Ë3Õ ãÉtØsRêÁe¦¦1Bö®8Ǚڲmcоv”Œÿ†\²ü(Ë!­bNâcðc›còH1¯­èàkzå?—&5t„åÒ HJeMƒzÚƒ²›¶r(r¸ìùöÅ®&Ì‹àx¥ƒ“ÌK´SW·ío>íBµª@$1†ð”2Z’äìôt×*Z#n}{tšóºÛ7p,(¾ŽÈ;öî™±cD*i[¹QÈ*[^𢵣úrɽß0JO’RŠ•}ž–,¨Ö5Þ³´1Èý˜)í`ÂÚi£žô¢Ûm“Nû,å9 Â3¾t¿‚ %‡a–I†–'×G#žêG×+hgS^š†ÙÑÉÕMPÄõ†©øö=7‡—þf«oS¯…6êç‹VDÜA»Œš Ä ’§MšÇmZ×å?ûþ³ï2TÁvi2ÔC¸ík<÷9=Q¹±äõi&w皊 ˆ\­KÆŠÇ>¢ë<Âg<É )6eI..Š3@ pÁ~ѵ„ý­*!< ‡Ù탢‰H1o«œ†ëan(Å· ·rÄÁ ‡Pà, r0¾ïŵͼÔëÖÆrÜtêÙ™zMH—LËÿ?xù+?8x |r¨A©Š@äRO9'+SÆ“RlW4åna[Œ" ³G n£)sQß½è÷¯›Ê¥#•^ÉÀ0¸ük¿Äd'欓pÆGÇ:S‚dï€w¼ºU( ¿ü1u\øåÛhX‚qØg–c p°mŒšs§a¾R+2¿ äT*͘¯`ƒÊŠ[=@[Möƒ^HÏg6ý¤õ¾­fV÷>¢8å²ÔK—–k2k+ù-Tì>:¡] À“Ðá…Òãq¿MЭɪ¸i8’¡Œ« `Y¦n¹9ŒôÓ9Ùxœ§‹ê¶*Š𦕏#Ÿ¶< -ØU>HbÙç}Ze^ô ÛúÈ)®Ó>E_NÝ”~Z”y ûá=’Éá²­*™®8Ç@ŸÛT°ãB’À0ã¾ì*?Ò¯¹ŠŽ-Š\M$«ªËëŽb‡Räx64™¦RÝŒÎ9Ô·ÊàÓc¹¤ðù÷nP9ü‘Ëäf˜Àœê:è-UÂÔµ/cº7ti©†O™Ûw4|Ös@‘c#b\²k®‡ÎzÅÚ¡+ÿÖÿ=’VäPä½€¢€ ®Ýc¯U3#{OfUvœF”f¶5è—z »¶lY«@œ‡Ñì.Z-ÿÄÀ;­"¨sL—aEÇŽ>i–!†" KZqøA”i=‹¡|îŒ:OA¦„>F€l9mö)m‚a’íÛeéd6ÉÚdY)ÂYîk…3œ'ùœ­ÑP¦´¨öÓšîÔò9ž 8žÝŽx–½;Œ¢G¯µnë—Híe@‘ä”ó'{3éã± ªt­2ƒq>Üòã 3õÒwf”YmrF|ZÊ(¯kKv¡(&Y ¹æÀh¨h O”á½’©­ #Ù8êªÝª(F¡ër&õlAÐxþ!ºïñ´Ì|x GpÉÀ¸@ÜÈ®›ú¥~‚ø½òˆûÉë–Ë'RÌ~%&p d¸]Œº÷QÑ>,ß5áöO²•òW²ôJ ¼Õ| |2²:Aø n·{uâ¶hæWIu'ä•b&q Ÿœyƒœ r=_¢GãÚÀ½ÞT# *DuyÆþùDál3Ð \ÅÆ`ä¹á 4#%eWôR¸Tžï'Õ\aR ßtãgLx¿Ž¥H’ÔÔóþü„£¢Ÿ`ö=ËÜç(2T`b¦/¤Kê?a$WÖÇ÷1‰¦°\óÉUO¥’ƒ‘ÏtfÌÜdœU´K’ì®­&67´Gì‹O<4*φzËÂô£(ýÝCåÙ,?IùÓA÷ Š&šm‘[è©­‹RyÜ&!FÇ H’ü”¾oÖ<åÄL¼_.O¶ÑpüKÃ-Ï~ޏq¾˜ øØŽþØÉA÷J¶ÈC)s¬è_¬§0~Éþ½Eƒá°á(‡ï{–åP^"õtŸ¥¶x·û×YóCp.pÖ–î¶<9º‹Å@qï œÔ Ýmª†Åýl¯ $wåG§bÊcØÎˆ²P_¥íÌK#7\ó"€Ëñ‡ò÷…W‚©‚Y·’×jÔ ˜<‹º,"Q²[–Aj³^‘ßpOj¼Kí“ñ{L §uÙq:‘ÓÕ4åAXNÛØqB„î ÂT?ËQA‡£_§Ý¿¶ï m}á  H›Fœ{Gç.ž Ù+ŒL1ÏA/óÄ2ø½ᣂÉí唯i[ÐEhßËaWú„Š|]Y¹†WÐõ;I¦s¥Š^…¢"ŠËœÞH~ *Âlãvî— ù´"Ó=ÍÁÇ¢òè!j"Ø£ÚLS£Gã•ØKcžÝ#º¾;îF:^(-ÓÀ-èäXhLRàŸ/ï×®‚Ïz@üC2K6®Ž€S]$Ó¿RÜy‹ØN€À'àÆ9“xØ›X6Lr ûºÂÉM†e½f­ß‡®T}v¬+6»Jm8ÆÑІ>n•·x¾’?Ë©¥Krn‚’ôÏ8åØÿE½j 8:<ÏŽ^¯æÐ=Pƒä¬+oŽêK 15§.To *‚{uiž÷LÎí MÆvÑ`nÙŠŸ0ë·ÇvE¯pòâ­Ó{ÃÇÏÅXPsžTÉ\o ; æÍBŠ8R [ PÞÝKžˆüK~ :¸K¾’è˜i‚$[ÇmY‡]D¡ívÜE½Ä½N…VÐUdwŒªm¥ÙŽV•·yT}#î`¶,-ÍÁÝäŒãØÉÄq&@™«(˜2on_×jÙ÷…6}gŽâr ñ}O÷éz* uM;¡b}t¦•ºåiêi2ÆÕõµl9F(øàݳ˜;¼&Ùq``~Vp´ß¿¡ÐYbNÑ Ã4õc7,ëLëÚþ³ÿü<äûΠÉÊnl¶4XÊ¢ãÂ1‚Z.cÊhåbr,í,u—>SN(ÕÂÑÆÀܱCM4sîYvÇklpË¡éži ëhòØUÅ„µä[œ»êd)§¨³¸çyé&6w\À+ì[Æ Vøëëûà!ÿEª´2!#£5ì²oß‹jÈU{‰lŸN&„·r4óÂ_ÞRò†“4æ,äIÓ9²¸M×%«åI¾û´'C0óºþÀñH8û…"ûËFzDk¶õs“JVã²ÌnÆO°Ä½T°ÄòÃg!ñ¼÷ëMúÕIçESïH;×Ñ´…ÅØ&uÝ‹oöfAŽe?©y‰L-rO‘ò«E¶á°®]–4ôŸ¾ÙÒ3J“QoU”ätâMø¦zÒl£kOæ½È›b\×ÿëz¸Aj³¹PºË5Z‚bÜ‚©Öǯ_H†×ÇígÃlœTz¼jð {Fá_»OC[•?̽^£×ãýMkŒã÷&­Ò_öÚ óøQd8/ÛðP©ðîk?×Á)çîíÍ>÷š§ÔòÅŽAÑ•×bkÒ*éÇpÜÇ4^–OçoûöÉŸõçÆ#Úâ}‡p7•Ø®s?÷iUQ||´šuñ60¨íQ“Ú¸S´9FµmmYßxΖօs!ÙQ¨š‘^Yµ”ÁÖ÷ú|ÜìójKéú›ÁØtfúäÚg]wS¿víÐc,çøI”f_F~=î ÏVä`_Üû$ÅÓ”Öa×ôŸÞ›gœÞæª&@W(n8TsA)ªëlm£1 Û0 ÷qæ/ÓxMýtfŒ^¸:›*OìQ™ œ”Ž H½¨“9)ðnIÀ™¿4 Ü¥…)}^î©§‚\ò©ÿ~³.ùQò¤¿¸–”Ò&€…tH’“0דϽ[‘åÇ6(?Š|é§'…´C×wýéou5¹ú€ji0ìäÃZòžýú'+jÕ0Cs{L€ÚÇj̺|äÉ¡²QrÁÌGKåŽô«D^çz ÚÀÏRIË™ò"Ïš`ŠëºÈY”cùhQ~QÜæ9™‰90O{k…Zݵ"æÀH†!ÏB™=‹†P«Êâ™t¿Nzý-¸¼ §Ob<ñæDùi½%Q~Vƒr¥åþ)‰í÷µ ðutÄãëTÏ ÃÐÓû%UÉ¢<Ðc¢G×ÒMñ;M÷Å…½ S3oN®R|ÆäŸç<cÔ£!ÇK£¿Q r°"©9ÖÉŒü¸~uÁüÚ‡ÛOPqÌoÆEÈ@Q¸ ßýë…ïûÆt‰j.N`¼ÃZ§kÞuÏ]ú@ÆRtN¯Í6È'vΈAÿ-N«ý§å …¬k(ÙɈ…ïÅÈ$Õ˽G6,qT¯QÛá§Ý±^Z¯o?ÒT“sIÊ´=sTE§ITXœò‹ÀP+´?*wkŒ›y\Ë(ȶ*>-Ç{™t¼>„ÁNbž ¸mã­ø«©ó®~Íž¯‘åÓIóé¶¥ƒ üõsW0‘Tu,´Çü|Èó&h3î¼v|Pö8†î‚`Ҙݳ.’~~Žº|’ o[¡ØŒ®“¾ ¿loEéù¶G¢lî¢08w3ϸl¸8XpÍj)ü- ú>g­*wA ¬ÓçišŒ·¯œõ;¸$P[¸ä(™å7’`A­gÕkE{Wr0f’¼Þ® k^NË,ó0¶U*%˜·²¬—òŠï‘Ó<*ƒ6+"eFmÔ ß!¦m8ÀT™( i×ùÉçðìû÷vûV¼À5——Áü.¸â}ÜÙò¹° dCAè.lÁx½²‚~¦_©OúW£gêš „q|KÐ0¦e_âàûcSéÙ¤f¤àMuÛ§„Å N`ߣ›­üú“õö›MÃKi¬ÌQ[€rÞn”réNú¤'m24¾W|*o§OV7ªå’|² Cm°l¸ÔìbY+z~ rÒ zy7€÷HŸÿüܾÅ}aô™šv '·.Ë6ÿìûÏ϶ÿü'Ï·¡ û¡ÌÖ´ê‡:é¶qÿsbÞå¦2 0Ò[r¨À34ÝØíœ?Ñ­”µ)~ëVòÿH›VKß±$T…ïb° f«Ü•g¿0šo R¢¦_•ÌÊG•,CµGãÏßÈšžó†Ø8¢+{ò¼!R]#Åß=¤È+\†½ 9÷H{È÷×õ žÑt¤æ.›B‚ÄÀ•Á¹<õVve··}·±$²ýddmt¢«¾ñ£á4„÷gWÎC ήtÂ0‹*%Ê!›í£Í×q÷Jù[Ö—ú¬/Мî;¨¯¬/"ê® åtÉø‡9QrºÊaÈÆl!O"‹E”khž~F_µ4ªÿ¡tP^K›\a[£˜ü¦äÈ)¬¢cþÚ†ðg:“,\ÚÐ÷v’Ä|>ÛDýœKÿð?®5ŸÅGÃYB ²$i;Ì[ª«Î¦êi¦ÐRKãÍeNíí®zV ´Ë|œh   ÓªÆDäÐS±1£Ï·5vß)PõÿºšÅ‡àÐcfF¨¤œ¹ŒA0ÌÅT*Ö’ä»èÕ7]´ËèïV„}åæH*¹Ù‚=íÉù¨ ¹¤»P±eçä½Äà°>l[» 7o±C°F{?öK\«·B˜Éõ&›ï€¾£°Éþ-é0U¶o€J褴‰g<å[°¦Ý¶‘,e¬ÓIÂKuò5ŠçþÄãÄÞ |Ûe@ë;QŒ »`iÑlŒ*JžÈðãZ2{û\ý^DÛ4%Ç÷Ù:x1ÉPú[d]p¢GÓ«pÁµ—±[-éÞv ÕÉ(Åâìà]!Q+fоwqüVx‚ìÙPÜi×®W²«…|¡Ã¡¼Í¤ÒŽudP®9+L•’œØm!Hå*âfÒ HŽUý*izæ*zÎn2ñ"ÁÄ£šsVðÚ…,²um˜í%»@‘õÔɽ%Õyb§ž>é Z…»øEÃ!N×**¯vO’ï#ÏÊ#Y.ú²uÏ¢×ÃEnö5žïoûú0„\Riœè%a®›…±8«Žé††¡‘±"cÎŒg\Tï}fÞ;4Ì< *}O»5ô#ó‰Bû¶Ê«8ŸÇ´Ú“= °b)æ¶ÈËÕÁ7(pÏ QÿÕ<Y )u××0Ÿ…¼5âÅô^k‘ÒüÀy´m­tÏ4sEÓDá 7®¹&3ª›h>µM×>³*Ï&*øòP\qœÖ耱 C CX%steÕÄ\ s1ûެ²íyHü؇´Uªõ c9 ¤Š¥'a!KB–|‹h‚ŽYž‰;ÂwMsþ LU'JÇ$ÇØ÷xˆ¼ãMíÖ%¹ñª"ÅñÇh8áʶ&!Ç*UÐf’ô‹m€SÛVŒ"¶y÷ù!ñhÇ踲H Š–#rêp%FDŸô ãƒDœcï¥QæÍà°ò×Áa¿ˆÑ.ƒÃŒõm[šï¥ì’ÇóŠ Ò€Žõ†o3~3ª~@5’GÃ’|××éq[ˆÌÝgo´ýÛA¥dPƒ h€þqäûŽÝ¶¬×6{!‹RéCF3š†u²“›Ž™, DÿØ$V±©öKæ×$ϸ1‰3<]¼½¦ Ïjej¬˜áKç÷e ‰ˆ:²ÑÐûxÃìÈdSYÎý§½’ Œc@¿è<³ÝÓS7þ DOæ+ð#¶ÐNÛEî‚i(dì9Eû3qõ  J’(ÈL¶{îÓ“Uëµi–cCÑ!“ì{®¢‰G—ý/U’?¡øØE÷¾azºmzj ê*²p^”ùn*„¨ª{Š÷¦ygògÉ{[Â^qnÙÔYÀ% —é7`ö=Ý9.ªsí»Ç°ga»È2ÐËJYXzL[Oú>ˆkÑ£ ýrt°ŸÇëœ>÷UÉ6†Q(¸§…Ä M×òó!õ‰Ö{Ï0ɪYæabïO’Tá:ê)­¡£õ ôÉ3êmäeÆm˜s œÁ·’Ÿ_íE'J*‰DŸ“b)“yi¦&躂{¥\‡b }%—‚¼ßgˆfý{Üuí=.Ë)Ëdh' ;?4’õÏQ-O2‹?‚xøó‡,à§ä º{‚x 5°GÌ÷]a«¡$ȉl†¾§ô¼G[;†c?$u“ŒïE6æ…nûÏ(µ¶ú$F3¯+Ûnëãë >K¦5õÐñ,! [¦¿šà¯ät üBŠe ßm#´îY{&nÖ‡"B´ÍʪµŠ“zLFrЯa®œaˆ÷Qu½ÕhøŠsî4DOOaÑÙj˜ä#·Ê޹6ý0MÌ9;™¯ÜK’ùÆñ(ãm……§=ñ¶S1áV ­–‡qÑ…ê‹lmÛl“•1!ˆF† q¨s6À=vŒœ¿KŒ†Z®pp^ަáŠüÀ-‘í2™ÓÙÒ|ª=!ŸO/‡ÃÕÄ1(US ƒyóy>ìâØ»fqðþ«öZ"¾N1â—¹·AÐßñÔ*ßûtŸçpØGöB¸Ãs]þLïéGµ ‹ÛÇä9ÜÊØX2>=Xs”†É0le<©E"1˜‰kh¶ð¢Ñꜳ)Ä×Ѭ†J72}ÓÚÕ í¡lY ̯ Îê¬eɇþWÈ¥táÿ{ÕHâ¬e_ö}š×ÿügÛþƒrq^Fkž¶á<Ó=¦‹ÜFÕ}ú=Ü~I\$¸)4·‘ýodªxºGéJþ@:I=áU”qôÿqbϵÛ&ÕªèMP<®c¦«®Uý+E$ø&™¼‰\ThÁ$L.AÇa4u9PÜÜà"šôÀ$nú—Çíû—•®ò¨t^fƒ"ÙCÎá¤R¹vn|=¾U÷{ Z±²Ué™6= Ûna-¢È§ 3‰>eÝó®%㤃Wú4(u)OÒDUÐï+ý÷$f"aFaO`4¼3Y~¸¤ZÓ²¼’BÐ+™”¤Z£jݪuQt@—…4nœvòj’Þy­å?½Öw¢ ç¿Ð‰¸%tfä­ÒJžM7ÆK[ ôFÄÙ•Úð4UäxÍS9Iõx7À,&Cy h=cԜ҂MA\»NÑ·QÓìeÊÁ]!J0º—îÂþ}ÕA<ñPÍhЙ€6]Î}‚Ä?£²o¾®“?®Û>ú©Ïì Q™L¤Ç ò4–Dô¾Že˜-õ²Å"Ëk3®FóñF~-Ï/—A ¬úiUñLÿG´GcÀ]×·x4ÚO<]% »u´bŠï%­˜%ûH:Îo+š0û ‡!y#—¥;º~t˜YO.ï;æÖ2—w® ºÈà·ù–ekÐWyWwìú‚©NÛ½jÍ<ù0Í—•@ÀQ“»£¾Áœ$tåËQž39áHg“‡OׂṲ ƒˆÊÜá¢Ú…»§Ø$ÁÈúG>%ñ{1ü”Oþ‰ÛÑJ113ÚTÌCÔ'PUÙ¶ec—É‚@ÆGÔC)]85M×»|ÚöPLlèvbŸâg%£0 = åN¹¦gˆô`—èZwŸƒ¹¼´*6~RyÙ5Šèüzij˜ÈÑËx-»ý½<±E—¶êK.<'F;V1݉Øêj,¹ýÑ¥ÈÅ⺄‹dŸvú_p£›X ´Š£o£lÙàÄq@×4ÜÚ|eܨG~ŽÍ-°>†ë(ÆŽk‰þ7^Eyõ*{ã«}àÚ ‡ísÝ|æéù^öê{•¤>0oÔh\žbX,MUûPF"Ê£ !Wdzs‰9¾î‡Ï@!U^ò°OžÔǘ´×5#£HÁ¤ŠÉzyL˜{攞e3ÚõÛí¨d—9Þ±£* [Ä…O÷]Z•ÍÅ.ß}ZŠçª6‰7>Ö¦”nÖxúfÈã2˶’)ÈÖgE›On½áÎu:žñ¯[U¸’íÓ— L‰{iU&•ixÒ^˜ÕET=‚*áÎÉ‹uA{«”³•ïÄ¡‹üzˆëáù=[V¸^/•!r›·öÓÊÐØþR÷úÞ$QŸ¡g©TÜeÙZõMÖgA»qÁò¤É>!•BUùav;xIË) HcõAQ~’Äùó·©¼ö×TÞ»áÙ<}ö•.úƒÝ¢:™7âtðÙ—`袎c¸Å\Õ{‚æË(„Mº^0Æ]µ½pßZŒAÕŽÙ.‹²x¬¸$ªÉÄ$Ò·v±Ï_ªÁD¦m"  Ýò-O—~ÊÚí³‡NÄÖºFÁ¬eeþ§¸ñ?±6ð‰dY™=붠ˢ®ä¡i V òÖ<Œr<=µ§¨Çj\Îákòþ2‚”ƒrv¤]Q™B×3€äÖíÔ ™©r‘<Å4Gó˜Pç¿–‰3AUñ<0©Êfå\7ÝÝÈ:|5`0Á-ì?=móCü+$±2Ìä&ú Yµ™óæD?Ìúõ-ÑMÞäÌÎȘr’0ÍÞDí¼-SÏ¢˜jÞuH$It˜ëbL‘af¢g+•U¡$™É@ˆe¦«i‚ù„NüYýŠJ>S?G_V^È4éË*Ç)Kš`ÈÕÆ›˜ab€\Ø´MEŸìëÏÈðPph3<4g¢[@GZ šy Ã1aÈk‘ÏNfYö³î‰jVø6ß„¯»|)À ƒ M§!wÙ{ßBtCî iwep\ûµ¨x(P0Ää•"Ù£ÐdÙ—-"Ÿ&ŠùASdby­º6ÒÓù¸Ä»÷/áO€›\´¥„Lh; š-Ãb¤µ²( ½Á9eضíkµy!Ã:ø|¿¢« ÜÑŽ¬D×Fou0g´{›˜Ìÿ°LLJ†-lmÈ}8§Çýsgº6¨Xòî¶Ô†Ô^G¡WPR$7ïj÷-ÌB5tvØd¬"瑞$ ÂÈòÍ)؉fß³u"+=gÍ>sS*+>ŠÁmÒUbQž¢e>Y‹U[ÚMow›Ôyœu²ñ ÍÄÉ<á™Ï¶Îé>¸x”Äq¡ ÃEoé¦Ñ°ÖÁ¾îÜ$òF§‡Ï¾}T¡h“¯€èHÈlc×wuÔïaÒ§ÓG1çŠzžŸ„ åwL· h$i’o»i µœâ8¬û¹ˆ§OŸ§_£¥iÞˆ2ÎqÓÌOÊp_é¦Iá,üMŠ€5_Èõ“k€Ä©ëøºIG×wóÇEuy¾•Jú… “‚ _1¢{Úk*åçvT.ÀR ”2 Fr:¦t)Õª(â%wÔG#¯q"@ÌK^ø.9}9}{1ô¡I1S;TmÉ…,’DA «Ùh”´lí¨\Öôs;,EQ嵂oÁRÔC²UuÐ Ç$<·Ãåy¿˜|tå°9 3Œƒ„‹ÆÕÏÜãÒÃG[ªq5ŠP¦ÉF^sUߦëü¦â*ÌXÐ0óÜ7i;FqÈL¾Z#Õ!§V?Èž<ûªÜo|Ce¼ÓË–œ’Áx½bÒqlž“á1" ã|\22cÈÒŽŠù ˜û¸äs —¶½LÿMÃeo·0M—TvÞæ9ª’Gã˜æÁ ñÂTr0Z˜jО€ `¯×hKˬoæ(8¢ßáŽy <®1•9t ÝòêÚ˜yDí{Y’>—õ³~©ltÒ'FÚðØã¬Z£šÖÕDÍGQök–Ð_©vcÃjéu¥wHÚ!_Æ­JË(ü¼® ôq}P”sç^Þ¢¢­Šg.4yÐ/m^e¾•ã¾Ð•Þ¹ÒŠGˆº‚8²„sdádQPEÂZòvÛ}뵪ùg+ë¨+î8E–˜l £ûûÚ Õþˆbž2# ±:†až“(ªÚHb/Û6] e1ÏHìpôH¦Z;î€û8àÝ6zEkÂ:Ϧ× ˆÅ âšâë(s¯‚4[PºeŸ&.ª¡íFúkêgZÖ2/¤1iš¬ Ã*îÒ|ŽË÷Â'æazéWŒG2H¹V)x5IyJ‹XWãÖLO£ ´_ëÌ—ð³ ™Äî¼hÕ´y:N[VJhΆšÔ9úáÏëþŸ.Zû‹ö*Ç:/Úµ,ð­F’uÍ,Òð @Ñš[”"2ÛÊ¢^=®ox‚L¨\Tá†j‚&X–}]ÉôV"Ê#ï”\z—c³¯lŠW?•¬#Ŧ¸ß›)ªâ4>ŠrN{¦øq1ÖQÀÍðã6Ј nFúa]»´-FùJà>éê’ÿLo@?©Kßꃒҷ Hó<2§í8 i¼/å ’lî²Ã\]%Ï8ø„½±.«)+ž²Š“ ^Ú”áqŒZž\ d?¦ˆ! O¦%Jß|¦„xêkÃŒÙûKFÿ”Õ^d[4uU]DU!’<²ú–”¬%-‰Ïû·ÈVÅ^F1"ªh¾ |‡yôvëWX%æª y BùZAE`Ђª‚¾Ó´žw…d‡±šb¹7¯›(^Ñ7Dº0aCÓ1çc7õP¥dÒ3Þ¦ JÏÔ òì+ÔÐPM ‰ùæÉ»s‚¦ï›n&ò˜ómZç¹¨Ç „<ù{¹BÓPmŽG <>ëeRÇÞ´QÕE`‹Ž}»B÷šÝºq§Æ¥‘U:Q(-ò,kI™7çÄ29#oO‚ø—aÒ’¾ã2³dȈDA½¡ RÏ]P—D¡äwe>©Á™÷H.÷ÿÄ}@¡^Ú¦r¦Ž±p˜[5¥ÝëXêí~ßRþ’g•©æ˜†6{ˆ³D’ · úÙ8^¢y™‚ù/T "N¸æñÜ^_KMC»æ£?wë Ë‚ÔdÇ“8©E{3ïUšN¢\°÷"Ó]2kç„kÕâ{UØGp;5Ljǩ›è1Çô¬)ÐfW•|^ß§  -ò¦*ayþ¥]„âWžööwŠÝó ’tï–iï«÷²hs¥b¹Ó+ªœæê׺ۛzϺL,Ï[QDz ñ%p7†¨{ô–6Xwwº\m8[WFe3ÂC‹fè¤zlÓ7ü#ˆ}ÞøõˆÔs®f3"ÖŸ÷5 »0.t’ä“®7áêŠ-X¼'Êz{0Y-’x<‘¹Ç(H(çx(Ë,Ý¥¯÷¤é5â ·sìWZË(àZQh4ÍÈRWŸÖdhÿUÃÛ°‰ËÄ®ƒé“ÏD¾ˆ~6¼]3ûÿ‰Ô“Ki>ÊÉ9¬¢Ÿÿ)é¨&ÇD6´hÈD6¡º`´Od:yÈö-“ãó˜ É#½åçyßí_ÇK+Æ·R.;rq€™4k´0Ï´çaä«Ë4*¾áœÌìbõ'öã$;òÍ4*EUö]ÓRìI®yŸWK>&ýR‹L“ÂHS`t‘~¹\Ïj)Ù [˸k:°Æ€ l¾Æ8>HöS) õM[.¾¢#<*GŒŸ“á6å·IœÌd3ö=˜¶ÁïD)ŽÃ%ß~¾•,r5K&“ m½láºìÓü^ÒJÿú:Ý{“;´¼ýG@Kß Ù§´¼—ÆÚûÊóV؇Q1Ÿ*#ûö ßÓn¥'½Ɖ®K³ïÆXC<ÄFæå–™dä6û²-Œ{+Æ=1™#îÒ•G ’•(P÷Ý@úùÊ"˲@ot;’8¹ »àઊó:*·¼vY¦¾ép -ú2íB”Ѷ¶—ÕŠ=O¡Œl$ëUò}Ûß6ØL΋ý_°ÇŒI½e¸O§Ì\óæJ9FHÓ÷ܱ8å;I«¶m ‡!aÞî7ò¤¤è>G.ò r%žžÂöŽnYÙMÞ¬å\枬têà “ƒw_Ïâ,«0ü|·I¾l„çP\€º© a¸YþY×z|©H<ú“±ÂǸ7A8•#ƒ3ßÈYA|ñr@숖¤ƒÙQÕÿjǾMƲä_RƒÊP?Ö²ÖBz7溣p»"ý½%=üÖe6Ȇ A”•y)T &¯º9¨÷rÚËdx cŠ1@>}SZ ˜oö…»ð¦pŒõD>ˆqõ¬çž\%ÊÑ\Еº"d1ÏAHŸ;‘Út"y˜á¨ÓÓA»µf>;‘.ü’ïÝô^‡œ×Ižw5õ¢DÕ¶jÔ  †¢ ú>µ&’ei`ߦh̸6ÌŸåÅÜÞA£WA3RIß6¹GšFñŽ•ì¸']°h˜ÿVtÿÙ6€¿(<»34V¹¬]?Lû¼þgÿÙo?ÿïíÿÞþïÿe­?†*£'^¤iŸ4q³fYÓ&‹üF]Ó-Ÿ¼ÌËI»ó·{})J:0­°ÚæÌmÌq“ïã òN¸ÈíCyî%‡ÿoZäu!¾%¯ÇÁàtÿÙ2pITÜ6@رhuêú#Q‘­ë†]3wCÃÖÜw1ê˜ÐÄ£™[çRª•Þ)d›ZgÙÕ”‘‚,ãØ™¸y/‹ÓšÎåµþp™)¦ Xç´šãâtíZ´AôøÅõ|+˺ÎR»ÉT¶8ÒöWÈb’—×Ì9æU‹»è“G¨nÛÐ$GªûB—òÅ$~bÆš0‚§œôIwÙJ×Hò1>[:” Aäa·Â{i5ÆQ"r•¶LK·,Mé]ïÜe‰S¶‚Ÿ.´êëõ^É͘:J†qgão*l×HÎÀ8Sà½•áÆ¢èëÂ"Ãb™×–qÅ=דáµãS|R¼[Ÿ°,ÃÄ0L‹ÓEO Çëut2sHvG N\Ý‚!Ùé+«jå,…šuÜXCöñf_|ýFhK¶£{N°Ïe4ûÖ’hA…òš…"ò…wøìHý¸d0ªdŠ˜Ï'îæ¥ 7©ø¾—t #ë‡$œrÜ9Âä¼FkZ,ë¾tï%TØÏ†•í>¬¬µ-WEË’g}R„LÁFù[.SŽYSÆÛ}È¢€ŸªJÎc2˜ èû½Ùò6жI‰âQ,Èâ;Šð:S “ŠÅÏa<¥‘æÄaâ½\ÛUxS| °lx›êY'Åß—KE±íü|¤;cj;ñóÉÒѧ°¨ÂMöʲ†DÏV3ÂMý…„åëëv•R3GÊöj8ëi80…±l7ŽqÉÛ­en’¬¶i{†íÚ'“Ã϶Ý.„ÖºLÌ,ôj ]¸tkW­%Å 21e”t¢Kä$⾜¡0q¿q_PÝÛY4Çvcž ©†c}¯%DîÔøæ.^vÔQ¢æž.§‘®Ø(naØp¾§Pþ›^¹n¹ë£–!ð 7"N]“,õÞFÂG’PÄgð™Zy™ЊÌ*¼‰v¥ø^v+ÕHŠÚz$m󵿨Û7lÒцG.6&MZ§v½²ƒ¿Oà¿$ðß‹rÿz¹ïß&QFÊõÚ´¬!ÃJAvÑýæ8õ'î•+†Âú﹃ÛÛÖ¨z´M.äáÕúyÓ̶LJtð0iÃÙLäk)rÙƒ ˜ ZâºG‡0L7€¾ÑT 5r¿gaýþºo·2Ž9vŒ8ds * ëLå- Y<”Óèaª¢þõmƒöK¥k¼|Œ\(Ö¨ ¿­ ]LÒ¦¤!tÓ£µOð¹õϦç(üµéyÈ«6=snÜ{²e \=K1¶/EÝÊŒ«ås{»/m¿cØÁ±$—öG ˜€äòÚ|ë:t½+*/ºI³ü0orñq¬’‚A$˜‹úã‰.¸´ÀqŸø½zm§ðÚ).9 ’çSða8à¥ÒÍ3ºtÀm\h“©mU§:àÈf»Øl1Ú&í­L·5W÷ÄØ <¸ƒäZäAˆ²ŸìAëˆë `µ1c¹Eå{ú =ô×÷]zÄ0ü„¡9¤/J™~2fÙÚ{P*Y(,XðS8Û¾ÆVtÅ„ò\’ ÿ¯”¯´ýÞûÜ“K¾ÅeKQ§ü¶–œïÛ?kɾ…Ø ,fä®ÞµÜ÷LQŸ%Ò€ÅFè$Q"]ÒqK‡‰3ç>Ymtð’ Ç5 8j¤0¹7ÖYÁ ˆõ1#"j—5 â2Ø™3Â@¹Ž™á†îœ=Y¿þK–]¨7ð,/Üœpä±·ÀÕ<æÙ=’Á×Ä9ÚèjáT#<Õ´fMHª@ï,çWv½/%×ÈòÄ:Ÿè,Û6Øb8²[&&Í:¦•ÙM÷eöôÏ1®6‹å)WVcÙïØp[R@,ÊBß4ZzÈb(ÒS[{¦¼~„Î…§Zeä^’’F¸A›ÕRØÁÒ¥2“–m‘ÎA ¡¬u²®ââïUr qž¤¥èU¦ôŸö¹Û°k²=èÙzŒéf KÂ/»µ]ÚÞ¡Z9/DŽá^MFA…í²[—ù€ %ážwëʰ„² XÆçÁ•2`eª<ú=YÛM–…oÍå~Ëc²Ñ‹;÷[TÀ®êßIº´ŠQØÿ8Ip1•Pˆ]¤,½×ÛTÃ8³$¨g×Ö@:`8B‚kk¯$¸_Û‰ ­ª˜OÊ8Þ"Ò_]Å$Y>fVRD·Á±uE°äX—I¸·ŸÀs$žâ šà`8 "e6e r3…¶,¤_ÈdÛºb±°^ö ll÷è…ŽMFaœ|l\ù%IžîÙ:°i5ç¿+ëmEBî‰_E KØ\À:¬I¹‰0àöÀ¾J›/ãhÈÖ^™aÈ Q=jE ,ÕÐôcX&A_%¼õ6 è0QÙ=˸ÞÒoAYÇ2A\è è£.Šš$ó&âI²1–ÈÇ„‹K¿“íû®vd÷λ jaU¦ß´ØCÛ†=Ù¢¼í¶nê I»¥ÛHðÙÂ/)S¸ì—Rݯͩ{Ä1ùvhN塟>øS|—n;GÙÈÖ¯aÚýjZÒô¬áÌÁœi‹µ–Ý·]A‚–˜ µKìñ£Zÿà`Vœ~Faö,˜³tú:ŠÃ䣤+cí A&™sùJP¹CZPTa’$Á‡5±Ó{-µ®ßÇ£.°ER_ê¸Ù¢v-Éÿâü†•Ù0e¤š…£A—Ëõý#)¸D˜¹]ƒˆ”uU©Ü?… DäÕ‘ø¾?$v¬ÕxG¾©¥ 0´1ñœs b|.¡Ùœ«SÉ{A-s¥äÓj#ï@ÊÏäAhÔ2Lï$+ºÔ+NC†¦g:=Ç&‹ªnY#ž«=êxº‰ÞKº’d|Aµ¯B#DY´ÒˆÊ† ¢(]džÝ\’ãb,4ð ïÙ´b]òAwŽŠ)–ªOä†!ÉqÓuЦkQ¾ƱºõÔ?ŠóegéžUY‰ êÖ)Ú«€qmï—uõk;»«äKÍ8’%É—!@³1û ¡¬.K]'óÏÝcY϶¢vâ TÍôô:qGz?{°÷á&”SodÉÂ.Âha’¤g>rÔÖýJH`‘Eí´ñ¨ä÷®œõ+º$K_7LKÊö"Ÿèåôi?ÅýÐd|íÉR4liø«a„“뙇‰ý÷36¦SÈnÏëYš&i<ù ¹Ï‘sBI,ó>x%˸[Ýœe}Ñg"Êð (< fmûìó–tøDîöë!1vÆ ù®š±Æ¡)NXKŠ4š2ÊÆ.'žÓõNæÑˆtt)<ŽìBm¦"{3­íÈhà7¢¤ÍJ¿ø„÷ž›É9öJ—Nù„YNº'9³m¾ö’ý¹1B4J8ZK¯ ÚÒhué’.*Ö¿•t! 7bû|Mšðàf§‹QôÓ”wkP"ýA,Ú§îe³^ÝËcº%ûXͶ;øÎ½úáùÇHF´5Ç,2®,íZ ƒ =O¥{/ì™*üý½þ»{¡?Y8`àŽŒŒ‘dÀ;f6ä†ôz­÷&Z¥7Þ®ñŀ߾“Š¢èg%ûäè'§'È>§ë¼6°þžçlž3’„HõFåœ ÏÙ-õu§T_j©)¤ä¬ÖëFŠv’;FÁ‹cÙ¾gze”Á¯ìrBDÖˆ *Aœ}ÜÍs9Ž•$r\LKs]Ìú¾m_‘ég别oEÀÀ‰ØyÎ ÕII±G“’Ât- Œÿ<{ãÄûš×„ô;Î`îV¸pK ßÅ,TÃ2<ËRdºÿ‚Ð^LVšvþˆ$·Û êz ‰E³²vò|ôúšú1¬Î}eÊ/I¦ŎЉd‘šrܶ=ÊMÍ,ËõÉ 3é˜Ë烮™¯Ûtl#«]ñ$S¶DKÒU=‚®ÈÙ.ÄÇê{ä@1Úwrl÷&|±A"­ƒ;ÊUö–©Î ³Ó´«f¨äM‚­¬iô7Ï}ή¹D¢j?^CmñÉÏX;‘ô‡1k“ÕEu¬ëv}ß~0“€LHÆc0›åLÇ¢›¢lä‹gè&§ko©©Ó¥+ýÈ­>ÔŒ-ºöPS–bziäiP†{X o…0òêtP=jÖ‰_²Ÿ°•í&tzYZe¹£›ÏI“2wrÖƒª£aÃëÙœ*÷ÀÀé ],ë_/L=w!iA)€55'š}kÈv$ã$tl>Uôu–ajºŠ¯@²|¥){üœšºäБ{ïèiÇÍœ6ÛB«I.0à†«i¨Ë]^¶Po ŠÛtËc´ÙR×}–R0Ã1Ÿ"púã÷<çœÐø‚ÉQ†9há9(iºÒëL’v’-€ò& …C~í øù¹ËÐP †²*k÷bk÷j\‹`ˆD˜Ãƒ‘!×$Ýkù×qFÛ×÷Ïí$|A£¢Bhms¿7k¿$eěމ¦PÉHåŽyíTËÂ4¹;׳qrÔ>Ê c2ëˆ)Ξ‡¾¶õ#íõ¼¦??·Uñm£ÊGÇ×w= (¯xÍÉÒNË/íÀIŒFÅ(8›b¿#à"Ê}Ö`)Ê@iÆäRt/u0íE¹Ôœ E9Áõ1Ò±]3Œ+ÿ'¹‡ÛQ`¥p[xÈá¤û lM%¢<€Òiç}Ã>H›²²áKBnjDHÁnf×· Œlžgíg]5䨕yô€À ©‘ãêGù:(äOYGI†‚lÓò1fÐFѱýWƒö‡Ö´HZÓ@y†¾\†ÏH¶W.ë³ÿK ˆŽÐ¡#uÄ 3=ë¬Þû9ˆ¦0bÝåC©Z)zÚ.âð÷]A=\u<òXÜ-Fª¸Ž«<8ÛxI~1[6Ðçr½‚ëe 4݆¶'ϼ+a­! |–…ÉŶ/ÓÜH[¼ ÀQ-Ñ1ÆÑæŠQMƇö]¥Q›Ë'ú ï4<¹h¤ÚÚ´5§)ÝBþJ]³MРÇÓQHZK{Ø£’ú‘òeØ¥‚²ïý¶ïqšÑæ-3KÒ¹²çXP¬Â—c»ÆÅO3¡;9̘v옓å¢uCÃe 5JïIÌç1 ¯Ú¼j¥´OV⦢ÞT[Ëb̉«{:ÀÇúsÜó©éîASp• y¦žµùV¯AØWÑÔf|óA—Iγaˤê%†ñ2î’ðå‚1kŠ/r‹²vEš–oªNªìMìºw¦Ž_8ÒÕ@JD0¥0:Õ]4Á°,ÝʪÈÓ55&\ƒã︧<¹ ÷7fbEb×19oÓö@]î`†Ø²5ÜVaqLÇàè¦úÇ~]áÁ7Ù{žKUвáSIQc³Ñ§fÓ6ÈW¢qlÔŸ«úÒuã2kì ÙU¦\DgZ ÷ ܺI‚%®Œ‹9žêZ•£¸ti•׉<çL>ŠsÀvŸ¾x«ë±ìç2P’3’ £Óã’%W>ù/CÆ@iz¦Ýìç¦êÂu+††%Ñå455P_¸SëzIÇÁøü Ä@ÉÕ3Å¥[}Д[¸…ô äŽ’âêó;„å çéí¢¬$€ýä`¬•Ñuû²c®R·4MÀ/Ç K ŸÑ©Ö¨Ÿšþ󪡶¤$Γ\TËjµæ}¼U]•ÇëCÇ%{F*ÚUzËô^ ·ƒôôeË…347ôKUû0…[õQ’û:ääëv€öŠKŠè~Èód¤«>ökÏ¢L¸ÌkØÇtá´>'P~ƒ,ŒÍ£ÙJÄéª÷‰S¡CYÒ¿µ|Ý Ë!ïˆ ,HÌÊØp^!*›*é¡}ž‚¨lý-õÒpÌQé-Ì5Èf5ï0Œ—Lûω´K²S€´k9Òhã m£n]ú.aaž05èhè5Êõº€²e`­ôp›©pc×RTÝÙ–ÄËI®vI¦"T”Æc„Œs”^‰1È·©™²&l§yQä‹`¬6ÝTÏÖ.TéÞâçKá-x½´ƒþB¦Ð“ÓôAÇ>hÉI˜çòÀÿȘY/ð'•ŠÈ™ö¥e˜12JJ2ˆû°ŠQü§,®5^ʃ_éÅjÃVÙÚ‹* †}ê¶hÜ2H2…ó]ËÃ)*Þë µaeÊ  ž«Í$ç5Nèî>›{_’ƒšîŸ¢I® ù"Žç¢ØîÜK×Ö:RΪªPËg4„¶,‡U´)ZÍL#²<ŒC:›W¯ƒ\ߢëOÒà±®¶}*EÅd¾Žf 4ž—U„Í_b7¾™Þ†+tëûna?ö ·™ò ´ oSôÛ•ùÌÏÓDãX€}Í#óâ^3÷fîKÉÜwk»Ö{Z‰$ Ò|„Ù Î3޽{r­ÈÈæÇëÈfî¹ÌlV[ç8®‹¹çë—AÄ`±`6Z4‡ªqO·}ÞÒ6HÅB‚Ç”MÈZUÔnýÒÆñ£®î9Ö©a t,g¥l¨k{@9ª+p» 3àƒaíŒA¦gPVÍIÕŒS7ËÈ7úHs{ïè Àøu†Äïќі7Ÿ\Ïu 3hÏ@ôÊ}øõ}Ð(‚ø UÙ`CR]_õ¥H€_‹ñ=M”ë]ÛšH‰:s("3¾gÛ äñ÷á$%9×xè·Àï Àoñ/-²Ž†“Wøèxñ¯ÍÍ›PN1OTÉä/|IK ËÎÖuúŒ7ÝÂänÐãúhÓÏŽKJb“Aî1Ôtÿ™ñ¸Ó<¥Á˜¤eQ¨eQÀéä¢Ê>œóJh{'•y+®%·,­É6×{]EÕ”’Ï·LÎéÙ'‹©}mäÿRÉ猻–[é ÂÇíI›5Ë>´E½ºûKp *„³(wÍ} Æó4Éóf°ñŸ’dÂÜIöú¥,ù• Zê†Çû’…ÓÐ÷u}ż±ö•JãKõÙ=q*í LEÝsT"H9ƒzY”Œ TôwÜ9'Ä|–ƒ‚!Š ê²,ÝÞ‹ôÌåVÝÔl?Ű«ø/²1MÓ$AY(”$5¥cµ…~IïHm\’÷ÛÏ16 W]Ș\¥[ÆbÈ£J¼%²€¯!ÈC›t7>1 ÿ2ôTwb~Ç׿%Ÿ÷%ô4%ød”wÕ@=òO£±ëºµãoyd|4ç¹ðÀ}|!>GÖ Wèöª<pŸ“`'ÝÞv䜰$zxŒ‘¢: šÝ<é!nœuÚ«’r}[- æ>öÍ.»åcŸ,[à(×¼`ŸÏ4Ðíçèc¯ |˜ržŠ î0Ö8I®MJØv|Ò€¼I§:-{ õÊB„Y:gã¢àƒœcxì—™>¿óOI÷ŒôÑ"Œ¢t´Œa&Ÿ JM4ߦ9?R_ÒŒõÐN%¦“É3¢¨Ø£Å9>ü]ý”÷Ì3‚eê®Ðð´EEÃäÞÝPmU4/}:ÌCZí„ÉôŽ«ªÿRs Ïà¿xÖûEõI”ã]œšûQ1ìã?û%†lc7yаN¶•ŽÒÃC1Ò2þtKï#Å…$­#õÑø×Ð^åiOеaXÒaþùÀ—¼àAæ„‹Ñ¥–dk›0ãx s%ÊÑ äÄÏЄWÈÓýKt†Àô6à'®™Ö3‡k2f% = ÿ¾Åûn>së")¤wTÓö)²’´êÔ'E­¼‘w’œ Û¬†t,¥<Š `gk@j¾ª²‘\ÛE*ˆbOçô¤¢{åÅÝŽ.P¡ˆ2[ŠcÉêE³e‚n¨K[v -/î×÷1.•Y¯+a'ʺ¥‚=¤PVt¡ëÒáa¢(fc¹—¶§³¸ÞŽ~Rºê{¥(Ùdé:ä[’G* IžMö.ƒcÑmðOh÷©¿¸ÎB:¢RH½²e¶7 ‰ª·ç´{ŸW˜& yhîÒ1£Â&Ç?›à/ø: AˆÉÀBeßñ5Ý×¶è—%L·E|f›‰Xh×™^?Òy—ÐíKèñúKfÆEf0ò  èÃÓµå!b.øfxÎ[_7þÒž»·/®¶ÄÒGú í@ÁPÅP6K°Õíø^RC¡Á5&µóh-?xk„ÂÌ,òq{/ŠÞŽaÿeýNhb|%ÿ›U¡ë…ÐI*E‘I‚€ýÇ(jË%Ï)à >ìGó¿hQšöO[…¥gÌúyÀOÄ=}g¤ü|æx/ÕŸ?ªø ­ÄÙ}»²+VceÞŽË)®SÏMžgaH2¶yöí£$ÇÊ|BÀdP9g@Ê Ûq*ƒ»EŽy¥z_oOcßø:&2Ì´^úºØÓOgèúªdæØ)C%Ú=®u1g`7 –:­(þ(Ìø…ØEH*I×”˜«TKFê~蓼 ?ˆòt÷ÅñúA£¸êü¬%íÉv§æfæ&?Šbwðy„Ûí¡ –Íá&‰gTc‘1¦ë¶~\•÷²ªc$YFÆ FvÂãv¾ž‡ ^³tì>î•÷—~1aÃ’Ǧu]°êæm‘ly¶%Ù=‡§HÞƒ&,*ƒ¹-û`ê羟£ß¬éb 1O”&2åNZëš !8ƒö"¯Çð7÷êùy·/&Ó ’Œ¹)k!¹,÷l­ê¤OÃm«æíÓ³yáY%/«rÔµ€ÛEOkSÅÕP÷K3ŒcùqYžûùýƒŒ©dÆ­3/^%mt®ãÖÑœ–{ùé^Y§ó·poøvÿ¹q% Ϩ§ôt¦yœÉ‰§!ç4‡a§<ö.NÅ+q4 $ —ö-Wìÿ•AsUÀH$#d4m{$#BR8y‘–¥T”Ô<…DÀŠ•õ^y©þ4ww“Š@šäûé:îY ±ÿ4ºð ;¯ª`hùLA|ê0ÛŒ†6CÖsøÖµØ;Óg£ ¤PØzÍeô2ÇS9*>Ú~ÃÁêPRlRŽùÒ¬tã  ÞåÀM£ Á¸mX¤¹åLÀètƒ¼pž8ðŠ`ªÜZ ,ne¼`0ïhæ©¶ì|, tYˆ\lã@Ë8¯„•Ø{vì=„]7Ÿ¼~äŽCNy`t+ȳ/»ÿ,Á} (ŸÊ„h6óPtÑ6ÆÓ®’ƒqe¸Àc_©/ì4âƒT ?%$sà1•s “ºh‡@²±3ÐR r7{Ò¯°Èû××Ñš¢çùIDNNR¤yWîa/’xl5 Ôj$ceíçì³Up‹РV%ìÔÏÐDô~æjH²2â‡î€_L·]a÷MŽõ+{9]ˆ2Õp–tsy¹4ý’ì»äÀèÊp¼¹ºvéîR¨ &Ó¤û§œ­¬9ÍO[ {ÐÀ)ìï…èÜ@ì®yþ™å¿òÜŽ‘Ì¢VX¬r^–*ªò¦¯ùa» H®ËüjÓ~íÑC­‹›Iá˜TG%ƒKØ{ea\æÃÞŠ0Z•ãû…ždL{™ÒÂd`’Kh ’C¦ˆßP3ï%Ú@§n Ø-Å»€8]VM¼§[ȉ391}$œáÐwNSÐ,$ƒ,n•ä²õà3°›ö ÆGÉÒú²«ý'² #°1Óˆjæœù:açù>„}ñJël[ K0s'gh™¦±g(IINˆqŒȆLnýIf¥PÑÙ^ïJ÷©ºè|²0A’  ôáÅ%|(ö:rTñi†ÃùI0}\ô#ç]Gw0BÙ3È q%còÿÒ$= 0Ÿ)¤”æÚÊ~N¢1(“f*å:€XTÓ~àPºÑýµþlôXõuƒpCQ%×APÇñPÝ @Ïu]\TÐõP„|õº¦\d˜ún[žbÓVÒ÷\"™ZEÅ8ÅÕ:‹0nšó}Í8“——Áÿ*#÷ óЀt—š%ï¾N.ûC)©ªT)é(çBA àWø{'~ Ü$ú§,©É>7ì¶qË,o›œ{Ϙ/߃ló|Ã1a$‹q©t˜Xq¼íC嬷˜ãÙ§co‚ý°º]†eº¾ŠÒ¨_ªE$Y2ÉÓ+…mî>}rÎ1çOY¨Â·Âï9-®îÖL`OžŽ4/]2õªÁüR÷°­hŸRN«©jØh ±ÎF®Þk£q<ì+bóKñâLw&A¦.¬S‘$5@à ÏDÎßô}Ï´].uNžF¤ÿ®تj`ÊÕ@¾ñž…»ÍÓìÎäýuájø]{ŤÚ+$5‹Y’.©häÈ9þu$¶²×;»¸× ­Ý èg Ùk2Atê}_–±SòȤxÃMóäuùû¿š\É)’NÖMx_t)na¿Œ6ä ÷!§h¨ªR¸©K¶Õœ&ùF¬žÉ‡ #ä[†æž.MŽþ¢¾þEÊx ‡g[¤¶lL 2PåLñ®êúÍ£Þ¸—mðB†kÉägÈrL4ÓÕФ3˜ÓAúe·6U–ÀȘZ`3Ø-Š×–…œ“-?ƒóàE»ºp„„×5Ža4#\¸¶e6tÔÁŒ“jHÑ“O¿>pg<å\Q…ë¯d諨T ,Ëމ¨ûe è-EéÓ& ’žnÁ[u ëÒØ¢v_%ˆA|œÃI…Ävë´õÒVÖàᆡÙ<0Ñ;Xí—fÿÛ{P42âÀ”c™¯$½<òT1ŠÃvèV¨†Û¿Däׯߪ« z¤Át´NiGËìßæ¿îˆÀ8A~Õ>|%ºì¨Sù Ϩ̢ño + ¨|Ý¢8O³9: ©ÆSáð¼+FC;ÖÝ#úø¶Ê)Òk(˜M0¥Zàp>y6Hõb·a*Aôô-72?Òw#óðêö(G”¤¼â,Kê5E–Ao=ÛRƒ—Ì+އɄåËdÂMDQ˜ˆ!óŽƒùÛP£2Aú#­Ræ˜U„`tÛöxΣJ=lðûÐÒ]2DÂ>$vñê[þ¹H(‹‚C'‰†ºÿ³HxG¤p)k.Ó“¬¥YÂ1Ý—:(ŠHòØä06™Xº¯$Î?`$›O<ð†¼W¸òÈMT5ØÜ)ÒÃdÞ0žö<‰³hªf‘GÏP§K±ÿÙ3h/Z•S ×T‚‚p¶ íÄ8Wƒ‚3ô·èÖñˆÎ ô¿á“$»®eV¥Bí¹Ð§òú]*ËLéÒÆ’vù§¬“¦ì$§T,Þ5ÅþEÁMXPös vÄfØ‹8c³á{ä"ÙÌ›n›öu¼žqyØ\樴 t;ë.˜ƒlšÒ%žE©S²ØhýTÓ$Asñ÷™³â¨øç5H¯$K¼Ÿ¼ ƒm«hM] zXëÑLïÐåyàÆÑÒõÂÊڸÌ6ÊAZ[ ¡^?“*­ÉܪNÒª:ºÈ^èxŠŽâÉòük»“P0{^ ×=ErOÓj„5K9qüF–Ì3Ÿ2¢9c^˜|áìÔa9iŸe̲ô£0ÿ¯ë½“Pqÿ!ÒA]‡©ï˜Ì£I³´)²Š9½úö;­³7¯ç4_Jᓦ`‚„ºæ6å–ll0Mc؆ Ì@ Ç"Å>†…˜þu×ÛѸå/£qY’c¡µÈ¼R·Õh\…¢B2îÎÆÉà!GLÜ@¯»È¦µ$×7œdM¾‹¾Q³5•vq/eY¾_ g¡ú}-ÂÙ,ŽÍ^E]P²$ ,±;ⱞwbåp èJòo Æ#઒¬rïÓaWnï…ñ¸Ö„ô<&ç¹høöL_Á´ïé2ÔqûYÒë²$þdh ׫:5Eu ‚>†´MÓnú$ Õõ'“Ç×I$I®8wÓ!z!‡p (Š¢ÞYuéàÁ§÷¨YÆzKvÃéf8Iu!*ãæ³eh¢“qÖuú —áïc„3ÐÊ$–¸6[`P8°£6»—ÁDV»Y£iK[%ÏÁ|tNû ígÏ©jPõ’ôB^;+Ð‹Õ -&hÞµÊÉô6õ’ÙÛ|P§àé˜cè:YLqÌWàƒÙèÊft;2;<á×cÛÀÚ#° eF 7 ešfaΧŽÄ6º ,ÓNd°úÐUHÚ·…údƒ.‰®»Ì¡…”(ô‘amDè6m á# Ñ…¹šÃ‘Ó9x¬?ªŒH:·V'Åä€ù´Ñ4¬w$CÕ®‰ì…4ˆØ®q5÷·{£b‘qC'ætv5f™oeÊÖ>î«Èë(RxX–÷2=ô͸Ö"¤ÙRÉ£"Óu© з®:/c¿˜©M‘9– ë”霌䴴S·å²WŽO>1lGs$éd;Î_/“¬ø}& O4-…0l(†v ›aj†¨«¢÷’VÃÜø3¢ #uŠìð’‚<«¶ú´,íÊþÏÄ = :9y^êm&sŽ4ÆE½“D®»:Âÿc9¸.ö772‡!¸Pjò¤¦aß·ùç¶ügÛ~nÿ¹ý ù:¸¼ÙèµôCÐ C„ñSIÓ­~9ª×rÿM¼tÈ4€ºµÌ’Uפfæ¾Ý„bå§Ý4MëéMò¼&'Cc9³Yò,…®®‹:‹ò&ÎÊ!«úþÓžey¸]p;†“4eÑWm7u3&3¤šò2ÞÓ•Þo™§{½¤´c½Ý__{Q §WA 0Ɉy5c¸w}´øfÆ=9®Ô º$NSpT25>mƒ„‚Ÿ¦M“b»ønûŒË@Ïõ¸Œ˜ÝHÚn6“,¶ãFQlŠÊ&Á§äù/~ýöظO6fŽóT<…D}¥-ÙW1®€á’ Óy”º¡w…\nGç ‰ô6¨Áò•.¨a0}¼<ÞI"ýôR™YO±QÌzdŸÄzâ- 8q}ÏGk£å_x2Œƒ'Nÿƒ•àh–sªÕ]=¤(bIdevv-ÔÈ'Q¡¯=€¡ó-ÂS¬j®wŠ;J BÓ}ahê2)Ð#¿^õ[Ïè á †'O†óþô…mt3Å}ÌÒ%K’0 å3ÏpUβ_bÿ·\å/\e’)%uŽ7•­²_‹«Òä*Ú2SÃ13¥+Èíe¨Ó)9&0ÿ†zžÝ ÿè›'¦q× O¤ª ø8†iÐClÕþC”t3¼Œ‘ø˜1}ZóÜdÿ(î÷fŠª:M#qi °vÐN“wD"Ï"ÉßÖ“ö¶©‰¸jb ¼†³ÇȺ° š™.o¦Då ܸëH3Ъ¹¶©2{ƒLÌ@oƒt¯¡'¸G:ŽaÕ9&žåÁ0ft_çâ“<ŠÀ¯Ãæ~ßÛ]¡·[¶Î#ãÂùlò¦ èþ KÙýaG¥}’œ¸ï¹ÒÞéÐUÙúò£¼ç0¶_ k,L=™‘0Ïó™“t£J„¡ Þ¢àÜUží„}w „ûêû®‘mCG4Y’µQTRäš­£ €!‰Úñœ+ÖARî8à…¨‰F[l–Ò’‰œ”,€9 ÃEº{/Sú žá†Dº¼³Ùbi¼¶}Û’m'c¸ïù äY $¢˜Áõ“Aع~*PÕù°:È#?úG4ÔÕ¸ )n’÷Lï]÷L¸pþ•ø‰¯^¸*øêF˜ñ|uÙ§CÒ¥£30мJÆàæ\SÀGƒ]Y`Âí1Φ\šhÇ©vÖÜßC! xG´'"àÙ”  ˆŠ£²S…€‘§À(Ò 0ÓÈqچ帆n"`;(L/-¦ÌáÀ ŸäÞƒj¬©„,iécºþSßä8:åm`}]ÐAéjv&C.Y›Êö1¤¶mÔ¡½&ï°Ü†ºQމnoòë OÅ0¶s!öæ¤rë‚‘Ší‘1Ï—4Ò}˜Zµ,2$ô¤HsÛ¦}zÎÖuÌ·š-q±¿íÅü.Y(7‚¢ tbØ(F* ݽæ o‡ãœ'¨5W”6&ŠýZrZcù@Ççœg›&ÊÀ‡ãüÒPp?(ª›¼VˆÌÕCnS2 Iò1ÿ4Išj9¶.ƒí¡ÅʈcüÏó¥ÓÛ‘Ä'!©ÅZ¾‘p±K÷ƒœŠyç˜r†¯è@á9k8ìŠÑîX¬ÃLŒð•œ´|¦ÚÐ~î\ñ`Râó2["O–—^_äYPHUˆ0ÛrÉy%SŽòÇqGŸ]Ð?2À"@L%g帕7^†b¯Ú©ÙâH-̦7íugÓž¬©]ØT~0šåÁÓ¡#n‚¦ø¢‘IªS»¦=99]žË1zÐ… ÖSJjÌb˜/•½Šã2oeÜtθÕYeÞ¥}Xȳfú:´ô‚MÍ8Ûö/sƶT{<´¼CžVrã}ËE¡Â6È;ˆ µ—v×?L# öQ’ó2±lûù…÷ÿx’|—ðoÇXjŒ5$ÑÕ"3ëàKÕ¼56Îø·­mÕT–´ƒ²mèѧ=ÇDÇ:»Ù¯“në·*Ž\Ð…2^¢\ IY€ùè½3ÃxÇ"³È»î¤”iVý§-CÊü.¨±À«^ó䂬û$Êgô|ÊK`lÓÂhsóÒäw)éng‹?rdjœ°tu½d˜ÂWNÓ?E9G/ùßõñH­âŸ²¤çYöøc g!!Z‰ƒÂIò„ü¦ap·p3dU¢ˆû¡‚6d Žj.Fjy–¥Ÿ4)Ï &’£$ÌVX ±ií½)ª"(‚¡Öšá6ºC~†á#L%Ô;ÛZþ¾° ɺ¸}„Çʪ¾ƒ2 ›Fc­âb;¬ÿm²š@©g©ù’œùâV[yC*^©|[¸.}„Uºe鲉<2$>œF“\>ÿ(5_cçŸï/&>Rlë’«Åp^‘s6dÛÎÅoDÉýºö}â~=^ï8/LÜÿwÂÿÚ Ä~M]GÎÊ4/dP†¦‚Ÿfsߥ[ž/dp½Ô|Çã©ÙæQ}vBÝî›ê§ÍªØk‘[¬‚¦ó4g\ÝÕMÒ2¨ˆ¤3ξ6L3õók;ñøº!}ämY$]Tsÿÿ;Ižk]˜OWÎ|ƒ—ì(K1ÂA±×aR¼1•ÌLýN0´Ïž±MðÙIœ²YáS¨1½³Ü£1§iÌÊß·’Ÿì½\[ô%p°Z ž"óN³uœê¥‹tÜÄ ¼‘¦k¶uEÇ1éùŰü#(¼TãÀL$UÀéÐöõu¿ ­¸¿õz/ÿÄí0ЃCk²ÜÔš¶÷v a€‹ã§”݇ámÙ¤¡`IIF™N•x/ÐZ6½®Ã”÷ÚzïÿçK,!  È–Ðu׉¢Ì¾ö;×hÊ2Ỹ.mØiÍ×~·.ÙK@2 öAi+VøîfŠ•jé·zϺªÞe×Rø¡IIUszØá_ˆÃ¢™sÿchrãuU|ÿÒêº3«<w¹M~ZËû0röÐU¾¢’@«Wt“4TZÉòþ¬Æˆúb½¥h™lµ]”eã¥éÏ+qZ|»²Hžžsz¡ûþC>ç =W^Ör|Ûħ„/ªy}®1Œ[ÙÌþ¢ø_¢(?Pnû6ŒÈXDñõ‡µ„ìó.Hž_oq\î<¼Ï÷ᚤõÄ!˜T²åRÕ0E— ¥«‰4ë¡ÅðnÖ ÁýÝ­ß+Öù¤ÉöMbÞØÙ®·ÿ¿ëЉ÷Œ!ÀZÚÒrÇÿ×ßqË 'p¬~YI§Þ_ñùõb¼uRÉY8B6tÇuuŬ~óBRDÛ§šætq¸öiþ®®l«]ƒ¢±A÷ Âs 0õb{µà“ýÒü&ÆþŠzZožûf+¥ƒR+ä4(ŽŸZC׃9 t¯ep`è@aë¿zª<^êxZ;éà1§Æ'“¾¦NOë Ë[½WìÆOõÞpŠ„î 3h:: éÂÑÎü˜‘ÿÉž Ÿ2oªæ­¬5¶CLÿT?ÖŸÖ’nÏ• óÍ•xÌ2…œð T+_ÛFå ,Ì)Å<ôŸ¨bŸL³®Í†—Vð­Æ¾Ðu«ýªKE)…Ä5aF7ˆ¢oz\þÅÏæÎÍ;qþ ÅÚƒj‡ZäË]a´7dû– ,@…õlú†„TÀ‰ú•m¢MèNaÚNÆz§2í^¥V!ŒbC³È¡ûV‡0ïZRây× )|¦Ü+ÊênE¥+ù,å ÁxW–¼K0|½D#’³€²:<…‡qÖc*JÍæ8’µ íSVgÓ²ÞI t.žÂßߌð?Vv tgâ½)»h˜+ýòs,ºÖèíÛÞú÷ÿO8{õWpvSý“×1E N8û•qÃqé‚':ŠDºšjÚ×a‰Yø‘s)Eh(.O§'6Å„Â2ú7CĪ œjP«Šæ6Ë&y20R4<ÿɶ>\(Ž?^ß?€“*á1A kkÚ…ì žƒCF%´uí#G¾;^ßZÂëzªÀö9M6–kŽUÊ+Ñf À–µ oy; ÎŒ‹rÀKúÚe¹‚HÅ!øNkÚæ}Çû*©;}eà À³¡|Û;ñ#ï'H'¦3˜¡èD‘0AÚ ’â%e/“,Fù§áݤÜ?mÜ.Y2K¹#K¦»Š•ªCÒ¸œ¢(ïó¦è²©e¢–;1oy= †|ç¡|a"[;ý¶”ûfwÇÊ:šå8 §ÇóPk“ÓU•…)ÇKófÛÀÒ ³\W¸pþ©d'ïkÕβ=OÁŠ`5Ó?W5÷CÛBY?e-׺ÁÝÌÐò9=ÿðTÒÞ ^|¢‚ËKa|V´O“<Ÿ×j’_h{€½Aš*ºàÌ_. í_'V9«©j^Œï÷·HÌ ÓUÄY!$WÄ—Ó˜ö{?LÑ(gˆ¢¤ƒßˆÛO <óJ;­ð»ÝI'A Ó!‘¹^ç^©m]WçJ¿~˜§¤lž¶hð¬OtØO9m{ÍiYÊqÙ3ͤÃdhÊO$Ô&gçÊF’¤¡Ç•JÙtŒªªì~YŒNùñ\Ópìtc E5ŒÑJ­Û±£N±œ9’å–Ee©²ºŒ–ºxQ—ª~‡6.Ó³v@ÓK™X4̪Æ3"ûa{6V*]ŠžW£ZØ÷ `Ç \qÏ€Q=yÚ¹únÑU MœlE5,³l8ÐWíG¢£ñæESèKH¦HgÐu§‡ëYˆ†.èQíùmá^Žr|LÄꛞüùG±ÂÝ=JÝ ·ûý-|º›nj‡i—eœæFvé0(”ö>΋eKCù:ð±ãu©ê³d â¹—øßE¹]¢\ùób²o®¢&ÍÔf[yaê¬ë0÷I½¶z>cÞ(Ǥý|£ÍbojíûØ>údý$¿ÕaM8ªNmiRù¸²Ï¡ @òè&Ý2Ú×vþ¬îÅ‹ñøYa·¦`¾t}³Ó­DÛN ôuµäT`]›æ/H¼t˜£L®Ð¼0sy’ Ù'Å"VÕJÊ– Ôu3ÿõ¡½§ñÞ5P-Çn.ã=“)ÛEé•àþ™M*N±â÷ðO„"Xúó‡¥8Ä]ä+žO´ßió™X˜0ôxßûhÚ÷%íU6f-9ãÆp}Ó¦šÃ>ºšŸqýd–òiJÔ׌B™È&›¢²o£í%MÀ¼ÙiçêUyÞîχÖÕ(?Ð^¯%ë†ïëVn[•ËíZî æ£5áº@— ùþzÜEyª`gÜ’•§JîkÂù·JqÀb0Ÿ…̉O±ˆ jàÿgVÉДuMÖuª‡4›ª¬ÒÏå¨7h¬(ÚZWÜ>-…»*dÌ$ιhAޱK›fH£qISÓ° ‘”§ÑI²NÔ%‰¾o@Fp:^Hý(‚ûž…U¯¢m\ký-ÜSì÷q Þà`ÄßHXëÄêÏ+1úàº'pµ?qëÃÔV[Žª² Š”a&Aâ§µÜàsXÊstƶÃ(OÃ(ÊU•®ùÀ ²A+Qè2-ÔÛZ]D5ÍÊ­.äVÓÊž {€$lÏ8F’o‹´ ’ƒ‚kKKTêX$@Õçq=fEÛÄŠ¹óXÎw)¾.8X§×ÍÒð⹺bj*ÊÑO›L5Ò’uÝb½ßn¢wk UŠžÍÿà¯oíTÌ~æò1تxË·x«—H¶4\Ñ9d,ÿ]|Ûµ‡FõÔœ“²;wÃ(F@%}]­?¯5y¾ñ¡°üâŽfˆ).új5Nïž®{o}ZL:ùq©›ù¡ùÒ3-èRÀfÙgèP¬S;GyžÛ¯+ùî{:ƒ‡“î™3œVtïÒrQ ]'EQ2šü§•lû“¹õxR…Ëmsˆ’”…ô‰xOteå”jWJ¯ÀÖǧÒçfkZ+T­®7ï_émW!=uÍ‚Ñ0í°ÛÑX{gw(w°ŽxÔl©€¦í¾Ó·÷•áà  º¹‰¤"ÅZS‹+ùW ýÌÇÙLkœ…‚u3¹¨Ã1Ý3C¿Ïß“~¤á›:M3/ÖZЫ9EÀèVbòš»tÅ>m¸Sü¯~^‰#ÞDç'£ù£$Ž™ŒÊcÎ¶ÙÆJМÑÖ­a(+™@åÂØ¶Ì¯AØoP)ž”˜•bb%¢]û)¸NÝ’ÃK‘›Läƒ=ܬt“ÈvŒCºMT1®*›r²ß2›C%‹ˆ °’æ´{”PWQ廟´Š~w †YF¿¢ä2ú²– CR ã9z{™ŸÈ§ª?%Gh-¶Ý¨y Ã)®“qà`hº&x 0d¦säŸś˂Aв¥ŒnYžC¨»=@qts®[¤¿ É|ãâ§SçSoûW2 À2̈¨|rÑö<í!%n[G^ðؤ‘qK8<ÿ(sª›¦*_˽d%>ÙÜEðõèÏ3>maŽFPÎN"•¶P,•Š»mŒÖ­“@ýÓRîÅ óª×·?¯%¨×wJöØ¾Ä ,Ö²Ò‰¢f±²—rYLšF„¶F·LßµíCæOv‹[â•÷^7—Æsߨz\ÃT.o*©-à£÷¢Å}ì"{#Ô À3T¦nÕ¿s­¹P®îWº(óý›*ÿ›úy)çêT÷xiF}ž™ êÀT÷¬ÛvíqÉ\ßWúä°~ñÀ˜í|‘Îa’H‘Œõ\Ïk±L¿¬Ågû’ ¯ƒÎÚEMÇuý.ªÿÕ†”èlS-‹Ùt¨éô¸F`·#øðyiv¼+4?9ìÔõŒlÜ*'·°ým1ïC~ð _Ù˰1ÏŸþÕ³Ð<º=pŸ)å)ÊßÖ3üŠÂƒiÜO¤±IN\UAwÀ_0ùÍ[µFy›Gù°ÿ²¤ýazѯ§…Àr#ž¼Œ=Þ÷|2ºzÛì·Å,óÝAø_l¿ !Õ–%¥=š¡´ÛŠj¦le·¥"Ö³è6qá<ç[~ X¸¹¿AlàÒm8žÌÞ…a+ì^Fƒ*ÚeÙ±±½¢ç@ SqŽ˜¯> _‡O&‹©°êü9êÄŠRÅéç¥^úïKg…ÇèÒ(!¨Ö* à ²5ýy5L:g"öëö}רí†Rõa(_„ùð8/ k¨¼Éò0›Ò}ÌU‘²¸÷ Ï$ó„¬O6t…Òµ«jAÐHš8£ØÛ­Q÷Û“z·]u9ùrW1øˆÚ´´+ÔNeܶtÚ»ñ·•\ÿÃÏäP)IGæ–”t¨<Ÿª±ª7Éiéòt<8:nq³Žœö,:Ñæz}m.ÀEb£èë­Æ4,;ù‰`e³®ð-ð´72”>œ‹ÞÖßΞU!4±Ú)«p’9ÏŸ×ç=Ñ[ÑT¾óDµuË*²­Lôè܆…гräJ¶½áÚ ã~pí‡Ä:Ÿ°^§‘—fÐÀ¸´;ºA§­“˜ÐrkT ¬#_§L ¥†xüm%ÿ<¨‚§ý:ízáSÔ–R‡ë Ÿ¢bêx”ýãô>ûÓÐ’y|kÏ#ÊEa—(UNû²ÔK"¸ý¸˜{Ñç·›A^~…<À]Øä£—RÁ´ë~{[œÃ\xN/.üûot?•ÑR+›ÄÍÀ?‘ŽýžjJ»)/ý†WŠ$žJ+öä¨ñþrN’l[³¨‰bY´·)ç»Æ)†b\QŠ:{I[~¯ºFeÞÏ”‡RMÙ¯kYWòÕö _ïE!ÈIÑÀ̺u­ÕÖeñ,—¨e¡`²üÈÀÐÍÿ¼*ŠÀ¥€•i-*Xýƒ±ŒóDE“^ʶ8YÀ Ýz·W® ùUó\E„£Óš}‚xl0°j)¡ºpƒj5ÆÚìÀq?аƒhsñ¢åöJÔ³m]Žé.ñÐÁ2àæ`Ù³düÞåÖvòí›ï³½-ð g„0ÿÆa­ü“ÃÚ+Iexy[¯§ôQ³Œ-Q*Ým«ˆŠ1Š»fGå*‹–8 {–çùGª}mðÞű‚b Ñ íX‘«éÊìãaló_Ö’c}íEý]òü})ϸE `_ßX­xÐÅ“}Ôï ð:ЛW«Ñb|¥?bY*pPòqj6µ÷­(g/doÙšã º†5úþÅÉôúç'½¾ë>ùõúzômÖ„¸A¬õ`+[Ÿ5¹v`¢Û1guum<¢Š9îò¶‹òLz[VࢉíÐÏ´ÃAƾT„aÖzá5#^µ™c: ª,‡¢ÞÖg-öÍAœ Ë–t:Aí{ò€¥èq"š?š;RjGõí]v¬ä:Êq/0mÝ‚ýàrü 0¥š•l÷48‡žs ȹ‚ª|õ3â;å Ìp8:ÐÝ´çqѨžî^É4| º›x_¶wô%ÿý!ÂÁ $P¢ÐX±ºÞ«0k«"Ϋ]$rXŒ¥ Þ8㯧q' «Äº„^|1¯ã¤’=‰ÕÊê?¬´Âû_ŸÂ‡ &ÍX¼¾”Ñ;=Ö0iŸkZê^?-Xò¦`¬vŒYÞSÙíÏÏÝÎ1þ½Ý“c-'€©ÄbL=z÷ß}£•ªJ†Gè¨Ðrz‡ÒÞÌ·±[ë,Ò2éøÒ·-ºx(Á \(¼AT—ûâ¾é`Ê--yaù“#TJyIWÒÆ€ FΨDœÓåè}%> $í‚q@òbš‹)M×!*7y÷ô,$L¿Ôv×p>æß:ÂõÀšÉë˜iS4ÙÚ«~ôJtf ØA*ó¼€I¹á‹:¸:Ó‡ríçB•”ø Ô„ÊžMÑ݃ž¨®Ø\û_ÿ£°ÛE§øz Äì«°ÝÙâÔ~) Á6bÿlÓ4aA7ì­þ‘.´Á=ôØLmDÅ€«·ÄO¦*XK˜¿ÌU§!÷¥Ž£Û•bÅÃ~{¡Ë†Ø¤uÇÌù›%c ¤S”ýÐtcGÅÕ4­ó²¶U«¹¦°±Ò/®v•–;ý²¼oø®ÁÁÌÓ q­¶B=³ú4˜/¶¶Ö3 pZT­Ò-[×µ‘OLJ _t‹E í(¢ÍÎ8ÜeNhûÎÍômËðªCÎàÈÜ·þ°Ôæ9ô¡’¯(¶¶qËBéaÛ¾ËnE. BGu ëJÇCËç§¡%ŠÉ‹£e/½7ŠÑ>Ô{ AféönpˆÇn ®´¨eîSÎ9ôãÔÍ};ŒÃ2Ñ U°h‘¥ç1ÐÖe©¦<ãæ½JTø¬›gð 5ú[{yñÆÅMšCÒú ¶ÌuF?¸ëT º˜G½DÏñ5ÅÏw®äŒSŽŒžD”Û$£ÔÒÐ ¤?,z% ‚~˜èÜÄÆ˜€‹ºå ¢Çg"o´§å7å®FÚ{Ã$»Ä¹Ñ Ðd²àrŸ–;*l[=*Ë ª~ÒunDïçMYd›9ìÒX©!L£v=¯r 3+‹^—ë;gwܺÐbÄÏ “8"ñmÅçcµd©ê—~•ßhŽÁVË–^6[ÃJÆr9åE.gÔicAÐ6æCšKývML–8º O@_븇¾ùP ù´§ÉÚ¤‘¬G÷ JtPñº}±þn PÚ Ô¤ßç;`ÁA‹Ï·ŽWv™to<éùõ‚¼ÄÐ¥‹°ùdšù¼³(&Ø5.äµí£Xz)¶¯'#ÅâY±Öqljÿxhèêɲ5ûe-Ïó>õºþ ˆ8ÖÕ&ퟞÊ:%!†óeA}òú¶zv¯‹vÚ¾Év¥R—Že †kZÈ:‘ø/®Uù4®N7óÔ´U6¬)0º¹¿7Æ­tØ/hÐÓÜ’bdBÙp?œQÍ;ç9«QEA~ªO÷Œ{>܃Ңu?l©Oûàb§üÒÀ§®÷ w|ÕÄtœä[R¼2@–ò©šm çŒ'¡`¼Êš¢äv‡nªâTJ7 gSõk]eGÎܶP¡|›rÛ´œèB¬U¥ómDàO†îµu–rNe` b Ó”.׌‚w“äQÉ(íÏ‹qWöœ•¯¯ Øy¨œ²É/wéX²Ëâ´«"Ž©¸  ¦YÎ1üîÏé[•HfÖ¿’&j£b*ëú·_ù!šÏ"&­´,2Ä<ÞfüÖ[: ú‘Òg;Æ&ŒÃã Ǩah):ìC¨ò!ª-MewíÔ\Xl­iìx2V_‚xб是Äf*TójËTÙ•Çbp£´ÈÓzQ|]£þ[Œs,¶ðH5çXͯŸpÜ?™{ówuÚbNp¢ð.Õ×sã >z¢`?íõ¡Y‹4ú¬S~]®‰¡#Ua6ˆÙŒ[¤mª‘ý…aÕøðO“ÐJ‹(,ˆƒ;GeaÿëêÁ½6îçV--<•—TÕí;鬜Ƥ’å|$@7ϳèĤkcëq¼=Å犠<§øÊN¾‘0©uaÚH©@ iÜkÔ_Ÿ‡ê-,ÔÊêâ/€z©ÈŸ‡BVrÅ—ú[÷¨Þ3Ñôd)J“ Ë£ æã ÜÍ* ­¯Ãʸd0Jü¡èïhN›¥Ñ/VApÔó`ÝÁÛ~·àú¹2~Væ¢P÷æŒHm-v—Ê ŠûC9jsûC"˜{Õ)òw€†ø±¢d[Ë%®Õ:æÍ"+!zÝe”ˆIVá8ï¡Òëõ\O+#h¯ l±•ѪŠt˜!O·ÈîÂ÷£‚Õ¯tN׎w |§œâÅ"°©¦ÆO¤ûR%!4Òv:ãÒ>r=IÝ&hÙ§¥îU ŽIÏŒw@¶*CQÔ¡êûsÍ)ä Q¬Áv®kMÓwÞY-Sm™/Ñ”r„º¾›"ê ©xÏôb´»À­§|ÚÖó.û““À(7îl!¨ëZCñ¢(*ê¸ÃlK^‹Uå® Î4¥x…æv…‹»•âµ/ê$MUT¿¬åŠ‘”¥ ³¸aÃ,´*Ñ”ëboYšíK‡´¦x,,Ùôæ€ö¦«?Âé™,D_–ø¸¨ ·Fa Dp»U!g/týÀ³ÏZWSMë@)òC!ƒ‚¡¨ç¾y»dÙ§…¢fƒ\ÑÀÒ÷yÃw½Và°‘,•ƒü.îYLF’„ŒÅ¦xÓq’ÐÖ=­¡;Öi1)C,Õµ!îäYgq‘ùÚÉ1ß :9Ò&®†X‹RÏ›ãØ.|>¼·ÜÈu,§“;±‘I-‰P65mFaM¥Í.ÅmØ €¶ M„¸äþáK¢“J©#eÇ¥¨¡×ëgÐ%0 ˰,q®FÆjú´Ç|Ó†¦ý/ãÐÚ¿ =žºG 4Ì)´VvEjÒÃUßp(Ò>m.GØ¿Rœ X„Ðþ§ïç¨|5ý=²zk·0¬Ã|-¤_Lß ¨"¤Ïè*Žó!+ú`š½Nµ~g«³ã¢šmœ"½sÆ|×Çó£˜fÈ]û%˜¹4|0ÆD¢×ÎTw¥üD0y¨¬§5©´w> `Gj|<»dÌŒeÚª{4¨h-¶}`á…Ö:jæ?×JØ~{,\™»Š/í9Å·oËHMLݳa¦1N0ÖŒ~^ê„§±=@_Ïõ°+bwH–fìÁòD‚¦†|í²,ëë|VJ–¤ól±V«V:à«E±ÅpVñ,LçÚQ¤JºÊiO—\6ƒêB ežážˆŽÞöÜPÝ¿E¹°bU{ÌœÊaÏŠ‚2ªqžç¡•FY =Ùíf›T’è.ì…È ÷žçã~—9Nμw´t%¼NëÐ`øRçµ:‰–OGD-áÚ­°Æ¼B^ßóaö ËæÉµTîS¶·t–ât;£{‰9Ð÷ñ£÷ ^‰Áðr£L”;Û=Cn•·é…,é…¸‚ÀƒÏ–qŒ¦ß’¢ÜŒz²vÛÑê`žÐK?jG?Š®8 zð}ãæ öÑÈt3.ôwnÈò&GÒÈ ·‚¢aéˆ6;”²sis˜¦GÍ›ö)äó¢Ãú||i‡I°ƒ*QõCí”…P"NG(ÑËRH‚»wó$ÕcÅYë¢ZÂŽ¥zH©j}œJŽrHÿÊRcK y[ öh7Ó;·‹¥†õöø’µ´p^×°T <èxªvÍÚŒÓP]X8Õ’ìvFë–ùóq $,Ça)h½Ô*Ëp`uðçM"9”h;¦vþ>夨 ©¯»(¸%s7jÔt¨ö{2lS¹ÆýKÚ´ —AOçŒÇ‹ã„çrÌF7£¨Åªž~8®sY§¡MºÜPCà?g£å’j ^4ädÍ;Ê´i1J{¢¼ÝéŒSØ¥Ø>½.¦‡K‡sÑñÐèñ{jç9ÙÅ*PËQ>É[»È¿ ïApg·úŠõµÜêóvSC½„Ó‘úÐ:`=bNâ8©êcDõØô\#« n£ÖÂöÝ×¢ë&Š×ÕÖéµ\JY\Áz¸Z†Ì7/DGJ îÎ*ÉïJ±]ky‚“•{A ãöü îÐøÑ”ß9{ïÔøÅÈLÛ(Gë†až-ÛvëcEY|š 4ne=£aQöi‹™!7þ?t›Æ²"@ ¾Œ¹htÑ%¹7JIOáÕ·¸¦ÀçvLíÿAkac­ëÉ¡½öÃ!ø8OäÄ|:ÕÕø}oö}kŠ$YÇ¢›c-Šbl„t{㥮¶w÷<šê‚6äQèÞ¶ëZ­iÊu„u3o¤mØQ Î éâEkÓæ-*šHbñZ`¢ò M*“åà -(˜WÙG¨Ì²ã½,ø(ƒAÀâmKTç¬ÜôSÑ›§Ôóæú–¾â<ûʼ¸¯,hü­Äbó·4 å,;‹j˜¶¦Lx1ZCÜÌ1`TÎ *óv1Az<^Øû¸/™‡,*™¸0³¼R}ÆY—0¿Ä¢|Û>€6©+@O}ŒI~%ÍBšß„4µ`ðìù†y p°¶,L7b¿Yc$ºW'-Ë4¥r‚!m¯nûe-ϵ¯fCwžm°¾KÊžQŒ7¤k<åžSnÍ(K9p$Ç`jûüº,÷z| r?t™V%ãAè(öýY2ï¼”CÙ¾…SmÑÝ$bÁt2/ÝOéÔ?ÑHÍ8NTZ(¢ŸF:Þ*Ž‹nÌåÕ»&ÝÝ·•nþÍ÷Ž{Dó]õ¬¯û·(2¤@B¾ŠvTã§I5s8©eP}·-ãB~X‘yUç%·2+É,„’D§d ôn]§<¯‡9ëÕúËRtë}‚üþÑy.'É3}ÌÇ]NÝàjtnýã°ë¥lhŒÓÕdšíîØÖyEëŸ5OÀ>g q%F0”ȪaPÛ´{¹ÉæðežM×´è|“õ&õËt‰ïK±¡äò÷eWó0ó*mvëð›D–Q;iØo¾<7gfäæ,úÚòþ ïÂacV!_æ©^NaŠd•­ZVÞˆB;¸¾¼êÈÝe#Y†ÌÀD¢dÊÚ¹Ó.ì2ù˜.4Ö(‡J_P5@^ý4¶CÞŽ[Õ 7)Œ`¢ Oz%;pa/ ͈7 ðþkI•Ü’ÚŽ–ÔKé–Ôe*ñ½j¦g?µ8ͶÕZîTVÖÄÛÏkIKêâer0-’Œ•ìWz¬~DÓMÑsf‰þ…®ÍÚ}¡À9kè+1E„Âbz Êø ‘t·ªPS<Ão*f`ìÍ cLkŽcY§è£Ä¯ÿ v¢Yè7?Øf¢)‡©ë—víúu\ém- P,í0¬˜·0 ª)mWC—†òm=Û÷n{P2s{ÉwÅÀöCDîÑ¢•!‚î¾ãÖo;Åñ!ÓÞÞ-ê'€áªJôóÊøH ß jl5Ö‹ÚÚ0X×z170¨&v¨0!s×¹ @1Ïy7Ò÷V85šÇe™4I®zUÏÃmÓÄ/¤Lž¢› ­}ǾŽO¾6ö°`¿>êËû1Y«Œã™ Wª:y1:]:Lô…tx³ýËxÝ¥í¡K˜‚Š Ä<’Ò.Oò.ÛÖPß¾m˜T÷P½£måYÖòÃXìÔÁ@©+ÜYeOÂmW}$|@I=zaèL‹yê Þù2fµW¡Àó̯Üë¸YWzo•°1,¨ÉÝPõPåêjNÀ‡ùµ—nDPq#8:pÃumæß)|n™^*¸ÁØAåŸÓµK½Áæýν84â´(&ß{î(ŸèÊÆAn„Xª7%¹2ƒkå ¹×C¯å^ùéµ×±6Æ™YPȼÁv4@#Î?ÀÙŸ8e¶0œ²´.Oœr›¯t·ó3A&̰x…Ûâ} ]¥w†ð  ùÔPM4U[N(ÞΔ…{ªzÊ¥Ü4Mô¨()ƒ5:gÜ+8×|ï $¿.8K  ›ÚtyºÓsNô×rí¶P¯x7h”š‡ìUàWCŒ¹Ëƒ 8ŽÜ?¬$í®÷ûÚž_bù„XQŠzÞWÝ$É’ÔÙ:-ÉðËCôï«ú÷—еÎ: ÓÚ.ºØòøx_ŒÔ§o鎻h]æB§ã8š&[ Ôu +€úy_ŸßÇ4³d‹¦æ°‡^èÿn·%ë¢F²ZHTºÏEÉÌ=?¦sC<¶û‘î•UÎÒÄüptMåCµçÃJ- !zÄjÓ6|Ë?©[×B1L¿6ä{·Båµõã”QbEyŒ|NÛ¢íÀe’.,ó`c^uO¾îoÀÓ à¿À7´YW JV¢´ÐHúÿwߎ>>qxîÕe¤<¨:ÆçÀ2Ží²µâ#´ö<øl¸TÙ¾¶V5>(§ß¢‡AŠmèV°(ÙZõMÖgªÝ†Q¦ã =£B‘¢½VÄq. ËÌÓø:ŠÐÍ£ Øµ3¨P¤c^vݱ–‡ Ýcǿݎpña·%Ò ©(ŒHéDG„̤œÊ1 åLº6œ1”†ý±¦5¸ØÏ×Q7Áܾd@0,)ê/鸥ù$È" ñÙGÀ¸9v –so© ÎŸè Vø*ôÆJÁôýÜ×Y¶¶{ÚäíÔσì1—E¾ Ìm ­ýi}2.žw6üŽãýT™°»s¾+5'=à¤r%Ñ~õPçØPçöœë†=j:€®4^­(é¸HßJ\â™'•…²ÓÞq²!3xæD¯u¯¥OPòÖ3’mLš9QQ¡†eË:YÉd=Mè°:’öÉ]œ¾4 =vž¦/Yö¸9ÃØl=­’d†¦Mˆ´È¢tñZlTyÔ‰îzG{! îžB­¬–¹^ÒRíã”°íºUHÉOÛåÂÆÁT‡…q`‘Wb˜K.Z[ ëç|Î$W±nüùð ²]ãhŸJ…p-޹€”(!-T;5è¸ou”„Yûô h¬™ÒZ·ý(ƒïwæ#ˆ«UU‹(C××lkÕÏMµÖ™še1‹aSÀôzZÎÕþev{ß໋w•²îI%—oã°¨q˜õoaã[ŽoA1[ldÐzɹÿ”TõGFPU’ð¶¢Õn]EŠ…goYœ¿¯ÁÊ£³P1!uáÇü®Á΂ŽRw ÔÐéå"m|ÈÕ@Wï05Ë^ÖÂp£Å€´éRü ̳qö¦ßaÒô”±­Hb°EŠÐïªV…téeac-à‰pÒÌü$‰r¯IžêÍ’”a6ÁÚIYN[#ËÕ”÷eSëŠÃ €µöÙ¢:/&ªUP¤P@‹ÅoA£bž=è:)J¨òªç´Ÿþ‚=w@9±o‰r>€ —¾ÌFÙHªdøl-ˆñ[¬ ×­Y ²¦Kª{s ×ÞÞ±ëQCì¹®$ú³€M¿ôªÂ< »\ÉZ"?]h›§p¾}½È¡Éu\äõ¡„CäPAEhS»ä°^Œín.ŸVHÛ 1¶½VOS+]Ê·;Y6†e›þ *µÆ ktß¶£p;–È(vÇ(;û®CØS‘«„n•‚niûþyE1<~/¹=Öû!w’¦Â™à-ªŸÓD¹éJIÚ %€~^òbµýã½®ÍúÎ{]0X¥+ý&;ýe÷ºN^ØLïbz´$cÑ/O5¿«ªŠ­õJiØp„:±âFýèäë²)…ðmÉ?všQ[9îa·äµÄh=â„ÝŽæêŠV¡?)O{²'bò†fP=RðØûxcÑw‹"=›mCÊäÙ¡¸eýû°°†°ý}C?4<0ÑB7e¢IœÔëÚ4TïS^+sWËB+š’*Vö½£ûu½ØEÊXn§–­µæÌZôùP']Gw|ËÀ¤Èí@èc6~d / ºüÖ*QíWÍC²®Ë´]'Á-À`Àö1b°óbù‰Ý¥YE¥yƒIIøºi-¶<Ú´M¥Î·o>°¥\ß,1v e?¨+÷û—fgƒdÈK «†Y†sAÙš<”AèÙ,xÍká<×ñŽaîC¯âœç$¿•¾'Àî†G' "×ó>x‡¾T"܆X Ù¯•ê‹z»2åÁLÌynúRiì»ãe~håÎÓý²DǼn÷<ìÍTî; ¾Yp&Œ•M€@®PæS%D€¾”Þ²»†F¥Ìy…iLA|ËÊ*Zõb”ÀXÐZü„¿Ág× ç“²¡Œý5Dì1Þ†~‹êa+Ú|QÕÏKq€|£7ÑJô#f4¢È&tÜèjsú™ý:õ”B¦¿®u>Öt(Km:¢±e_[µ”ŠŽÀ) Œ—ºˆ¦†?‹}Ðb–o¶ãÁîÓ8™oožÓ‹ëÅo–Å»ãtà"ö…ò7ô¼ö^ -Ûƒ‹V÷¦ëþàªwúͦւîe>C_™œ± iº5s—Écy(¡mgRzj£yë]y¢ƒðÄÀîÝé ýØ_Twö*Ë¥cû¦èCÑ¿¨h9Úö‡÷‚ÝàÇ”]­}œXj‡<Ô8ʤJ0ש¦ÀaŸ}íÎ)¡ûùÒ¡‘‰ae LzÇçi\›>VӦ汜XÝr |„„¸‚àñÌÿ2Ò*J½ô˸Œ´ÎÁ5s3xp]²GjÏ <¸žw×*Óˆn?Y΃ »1Z޶µv?îõMdÅéÎTÛÅ›Šã$®³L$ c°þ°¡Ï.P; JŒ«þ¹MÑ…aÝŠ ˆø{ª<Ú¢to$r€Ç2áƒS÷t‡¹t…î캧ÂKh r?sŒÆ]ÕjH‡U„’‡ö}ÃöéÒ [g|?SºLßh2|Ù}œªµÑŸÀ¤ÝMÓ¸Ýôò¼ËZÅ4ˆiÈѪ bª ;14UØF%€a%ï Câj Ã÷ u©ßï‚ãxV1³Õ#u*­¨¥„7L¤Ðsè ¸9À78tàï¸Ý埸ÝhDø¶ '*¦4h8xëXþ#sÎqüy%~[oüÓCkÓÅ ¥Å”ŸY;ù¤Â~žsUWiÕfÛokùW+Ɖ4ðkC©¸î¤Ë-W}œÇ v©~XÎq½«X 3Se>¬mé=.Ç)Kh ZpœãFoߣ"ÅÖàûO™´Ïb4b ×zÉ8ã›,í˶­‹^˰hŠÚº öÿ ë­©©,‚ ‰Ë»Ÿ±zªKTµFû$ØXÝÒ®7adé ”bå‡háý!°¸ a–Ñ—ô Êj+‡$ªG5©|–|Š at51m½6jŸ¢¤Ú⦨Ù~O@Æi¥Tˆªûs^̇•\@/ ¬lëÐ/ºB†¡è÷ø¾*úuZjðôÛ§²Ô‹aàIaÛönÇ•y¥ÃpÓ`6"mYSÃÅ>PX÷½ÜbYË¢Ë NäðÎ-.Ö‡8ß e¤MŽË„ÑŒ$,ö¤¡Š“2 JòlÚZP£bo‚›®O¼·ô*3JYÕ/Õ†Œ\ÕAO¬¢Ò5ìÛ‘2©UoØÀò}à\¨âtoö™XW×?±Ø›ö“Å^Jç˽A¡È÷`sàzþ%¹À%W LÌØ ‰5D¥‰¦ö¾P}£²­íRY‹J&›{nš˜í]¯¡I= &Ì éâ0ú ÚuC5XXËÌoŒ }6TîÀÑî0±Î|m÷çi=É,ƒ¾ùmìa‚¼NÝNÅS“-}ž'{(kº.¾€ã@êHöZ`\/”òƒMkȃeÃ-QÝ•«È=u¯…‰I²¹Ð¡ªÚiª(âþ÷Å®hyt¥E)~`^4RH­M—9åœk×ECRÿºÖuеr%ަê0Ηb¶¢\[ôK©ò—¼€Þx]=›ÎôMâ"ú6o,è‰8´¹àøÜh«ÐQ{³©1í @¿,¦eõŽ$±ì.©g r0нv›(§A—˜­Ô˜P÷¥¸è´¿ ãŒößh"_Í•+æÊb%ÊÕÅOÉ÷ƒ´z ÐîœÝ½îÌï )†1»µk¹O µæ~i7ú_U;¤¢Q€Ù‰A1‡I$нï€Ç é'Þ«7¶°¨‘Í1a‚²Snï1Ÿ$Ȇ1Þˆþó¦'é–ýáz?.'º„š¢ª:Ý1h땞±ÌŒQY̹Q~gjc&ÿÓ%ëþÔÎi…È'i¦=ÌÎÆ2+ªuÛm‹ÍÉ æ?cötìÚ·gå?|2¥ùëN¬9é¢Ëhó²)ƒ¸2ü¼˜{Y ïìK^×%Ì"•Bsßç£b^ëè×Å‚k÷2+Zªˆ"57à4‰—>ƶ–[m,E † ¸p5 \Ó<ò ûDþáÁ9—Oi[žÏ ~.âSxP_H¸ÌWîáoŒÃÂ^]–óÒOó8ÎÓBnHÂ}Íóv\Ð0ÌÂE*u@zºŒ!€ik{ÍàÌÚÄüms†Rñ×à‘ÛХѸRv«Çê”t¸@d>òóœ4[oî‰re -úºÓÌk™ïj¬J*22‰ß?.|Z‰È…$Ø“´ÜÝ€ºÌ¢èç)•§S´Åã/kQ`¹(“±À‹4@Íp‘ \4MFç+Zób~^‹ù^ŠòL«É žß±ºbçõ•å–WÃþëSùÿºhl,ìS‰oh××8WÛ¤Åݪ„²ä(ûæ··çPÝ#\E¥O<ø¿‘‹ênë1Ë ™²õs•¿¬åQ¥¿÷·…÷{€×QÑ¥iÓ9é"«Œ£´šîŒ:Ñz”y§á*u…ç@!¬vç-»ûÉþÒ,aŒ!,ÚHø^JBÁ^WN§šp7Eõ1«óÌ÷[£[ï{åNû½¡Â±Ãï} ÷},ö>VÒ£‚€Ž èÁPaøRõ¯¸çK²GÔ"o" —j-ê>Ó5‹>ƒä‘j˜BWO²Œl·pÄ`Ïû÷ÉZØ*mµ¾zªˆ§yf¡úB]ºN-e†s,Ü蟖vNe0=>ZGÓ°B­Çf,†ót±nŠXÅÃBax–!:Lß„²š›-DL@£.XʯûëõÔ5 Ô”>ÔG ÔŽ[®Â*£´)Íå;hBš\$[‚ù‡¹ÝuŒ·­b‡€ìVœÕçSO1¥I“¢ »Ù§D:o`6¸šÙpó.Y‚ïwí)f·­(AEHu¥a³åk'Ë¡~‡ßÔ ƒ.i º×Ižô"?€±'FJuU—‡•(õÀ)ŠdÙˆÁd{*9=€O`Ò :·Ðeôœ “²z :Y¦PWö—b `ÀgkÁ¸Â`þÐîÓØzÊ-sµ qÖâüñbhß:ÕU”.9:S½@œé–þ~ñ9‹é\ O:LÖålÝ5*.”Ô ¾žx@kÜ„gŸ”´Ÿ^X{B‰ósXì³×†¡Oz>ïØh­ÖE«•uw«Zkµ¦I3NEÔ‡E++QZäÚÆÍôÐY8Æ ÿþ`OŠ^vÞ  ª´Õ ˆóÃÞ`¨XíÓÒÿ²[M]J¡×v×mñMatyûöM Ò‰~[Ìÿì(¿¾´£V ¶ºì¸wÅŒ—œ*÷¸Û¶)YÌõþ7xˆÚÔÎòñÖEÿžŒ1TºW•˜dgôDu¶«²ÓI–6Ó¶¦ G–u%£ážgÑî¬hl­Q•LúÊû¼Ïº.9ç,ôàÛ®¸Ü àù Ü“– x'S¤è6zþ£h4ÉFѤ»1³_E$ºÒ_2‚.óŒyô|Gƒ—ÜVe‚ɰEÃïþ¹Øn@øùš{s®ù?‘ê†Hí xãØÚHwM”‹|+2´.Å謉’}Û(AL|“µwè@ÐLß¡â}k8mÜÕ 2h%o U5¹êº4+€À¶ÚM`ïš ¸jœ‹j±H?hm¶zTCÓ…ˆ¢µâWЉÁº¬8¼vÃx€O^ Ú´0 ›&,y\ìõ’Ñ®e1H טF¾£ï]p&¬ H·À¦Ûlƒs0è¶ÀÞô5Õmà ÝÜÀ¤\ÐÁ®° W%¯í"ʵ~mÛ˜Á£®du4L¥¼–±è‡¼ËÚ4VÉ.zÐû£[ïæê­f[R‚ذԋ€rœ±0´}Ç0Þ“-‹(¢ÇÒ ) ‘w ¬›Ö®‡ðù%ý}Ú'´ç* á²|®ól¢8 ñ Y.>tîÀ9Øþ×=&¤æ‚)oÙsÑ ¡/ú¼ù&A tí ¸–š%xI›ŒN F˜` £“ô”äw]&1 š%Và›Œ»º½1:W¾-æS,iÀp%ŸQ8jÑõ‡eZ*njY ÃÍ€î] ¬J®N\ Y¾}¾µ`tê!ï‹,Õ=æ?/xÙ‡l-Ú3Oi*bÎ(Íi*îT.T.÷ß“ç²Oϼ‹0GŸåä¸3ß$q²—ëž×Sšé!ÐKùÎUüŸ©5ëµ hãA¥ß?ÔƒàSêå[T«pÞó¦b;D>ï3ýâˆné>åTà¹eD6åÞÀƒ ëÆÃ‘KýÞ±uÀ»€/†]Î’Ï*Ùh¤S~fw˰Ïó·+0¥G-È“³Uí\˜çAz‡ý´\pýÛ&bø‚ü¬:âaúœRÞ¡€'ýh¦ ¶øôÒþý8’¿BsÒrª> 9€9€ò‚Ȩí÷2ê•Ú©ÂGqßùQ]äúÙ(A–ê@ÛJ|´ù©òAH”Êè"ª¼úÃ0O防炅dÊ5,]È»oK\ N@ Ò¥šª(žCíkÖu˜ËrJÛ°êåÙÀEs€E‚¨tpòú½ ›€S ܼ«•¥²ëÆ‘•Jk˜ËUs–ôݪÃP€¹#Žè¢êE­¾ÿ]ìU# ‘Áèðí^æºÑõŽ{Ô\–®­bÏ÷/ªŠ‡7ôÀêÀ¢ˆ‡:ˆ=NC܆-]}CØU­^xÇÐæCÓ=–†oªŸV»çX€NøëYI¿|ª»{&8•±*To{IE½ôzÁÍw™=® Õ€ý²@®ô¯ @ àÐg»Á) töz‘\¢ʦ¤—t%5ä…»qš—eá+zÚ4ÇpÚ¸ÈF·ü¸¸u2Ag¦!ƒ·‰œELk@rHàD¸*äÛVæ{¯’´º2Ìd6´ )_w -êØÒ56ÿ„4*ÿ„4¢•(s¢Ê=¦Í'ÒèŸrøÂE‰Iq|•Q¡ÔPFñª†”ƒÏ*­HW‡ïøÆq•éF-+ý0Å ¥E%d†öÍ>‚´濬8ñf¤OBáÆ°ª à‰»šBB]Ô¡,Ñ üx¥ÃB_|j»¿x¶¤ºVGÊØÄ[w1øÊ.Ú-ª(€Åi%kaB –—¢éœ¼;¬¬ƒäþ¯9™à@¼dD—.ÿ<§bGƒ˜2¼]€¥7.Æe@ ÿ¦39 „:} Áî$Þ›|†vZ•^Œ½Ò8¢LE!úx²Q7knPZÁ(¸ì4êzȆQ y£æ±»¡3^’ö…A,SAD§„íçÝ·£ôz¿U6¼-0 ¤»h@†ÍŽ·)ÅÂy¢”Œ 9sŽËµ9ú£÷nj^Ì‘ÿÇ‘ ŽC~²‹þ̽C´Ÿ¥Ý}Í„ÿ‰ÀÈ(‹QNm‡àÓÙ} Œ\E–7’f 3È;Š`åÅKC©kÔNe¤d1h\Ó瀭e›GãLïŒð¾ÀX2¥=M+WPZÆt§•ÓÜÏôh‘|`(“Ò_øLq*lú†w¼A.ã°ŽR·dÐËe$3ŽyÚÚH‡x :0j”ø×k÷SÙû÷ÇTVúƒ2–…:{^ÊðoÐØÄƒ¡+i磯úýÂ÷Ôª˜Ü[¢ÃÔjw³jÅØžþÞØ}Ö3ü›e³ê°'\ çÆÓléDä‚‚ èós6¶…¸!-]êöò @ò%:G)Ë9!‹ÒÊ<ËüËS¥ò0“Ë̇2½8ð$vùÛ…•™=÷/VófO¡±-0{ðC—8nše¯dÍ€R(‹R=g|þ[µõ¾6N@çK$›Yƒ²U€ôs·eòkÑÖǃâ¹a[‡Ü¿/”­¿6ùÈÅ䃿ªqCよ*«{­ѧŽq¥ Ç™ÕP2dt CUæÛ"I€a°7ý7ýu |nŸ‹=7Ý^-ëœñ§˜((möa*ó•Û«´ˆÏ³ ß½A"ü´Þj³l¦÷”‚?g{ˆ¦µJ ~ ¾ ÝÏí0Ä s°iÅcÚ#7ÿTEÐ;Ž—|®Òýbƒ¹cÈ¢C\N׸j¦0Ûl`/GÈR˜Ðß[ȶ"íz9OÜìK¨Fg™õcÚwkÞÇ]/Q6 zø€1z|fØWñý2ïš7y…0K¶ÀV¡˜xZP"“4Ô¨RyqL:ÿ®§[B7ÔúpW ÌÛµGAÖ¤³A‘ÞC2€¹ê7ïð)˜0ð}*.c‘L {]«i §°šD Å60Rñ|à¯L®0cð‚gî3×Rb$¶o[ÞÐn.éÁâZÖ¢À‰ê€?=¨1ü+_ó[t{«k¹cûE:®ô×IÏ}¸¶° ºhÅÆEÑðÁ”+vcƒîˆN%Ô@™çžŒtƒÕj,]ì"«Çµ±€SáÚˆh×ÍQÖ/î“¡Ý’_ÖØsR³²Ý ë#²r]]‰:bG¬¢¤}ϳ±˜iý_žÌó»“YnÕ'ƒ Ø\ж}׌í4‚k8¶ àSä9ê(ïÒô—‡„š_×G",ô&žËµ†ë´Rº™Öžça7þúˆíÍûƒÕ•€ÉëR\TÚ2S‘®jmE?ðÇWGÑåjî"ÚôÌ{Cž)¸j@»*5ÏÅ¢TJáþÓc"c\@_‚µ‡Üt'ÊÉ ·QËŽ¶+• aÉ–Ã?ÿDó²?îÐ;{1H̤rƇnŸù@Wáöëëò¯ûÃ@"ζÌ5|Êö™òiÚpªiûˆP8¹qoö!Î ââ¯-ØYÕ Ù´ÁÄcúõ'¾E^åhÞu'ê/(«éÁ¢¾WYím“G”?üö\q»8جb”ˆæ#kC µ•ýÝê½N"§ØQþú+Nç/1X¹`°&Æ`ý¼˜{5"ú’¹sÃFÍxnÅS‚ToáÜöK·aú»þr1?eÞ å@ˆŒb*j¼dª ×=‰÷ø/Nù‡Â.ðì8)+„Š0÷¾'{ît Œô?–¿øŽv”h|pJ‰Ùi ŠI×7ÜæŠ> 邉(b”±óÿ}m¾PÂp‚^>H0Ãé…mÕŒ… :žcóûzÖÇ,„©ñŒOe7_øõ!ì TãÒm¦q¿ž#÷#f?4¡ m~érÏeÛ˜lÍHA|]uŠðÓZºtiâ¹*Ž×ŒÛìÄL$k×6Iê¡ )ÍêºßN€kŸòè«(&3y”ïs8ãƒfËPdSVPÆÚ›ß—zßM<ÇF6ÂF„O\À „Ž»n…Qv“&”|ý{à\p%mQn ©H´rkÒ¦-ØâUQ‹"ÿ—'£lõ£˜‡ ¿†SW-ã–Tc-rJ*ôŽÙ Á†!V®Ó›{¦ào¼•1ãsdY%÷È%” CÙÛ"5šáNàY·›áÜ´p)†2ú”‹΋9l„Su\¤Á‡ÒRº7Ë’2©¦qݲ­Ü¢_EVïüÒQ]³Ú­e>+u¾îw;W3„׋c­4âðC 1‘FœjT?M冕®\ B‚&\œŽ>ƒá_%•$r3y =•ÓCY-…¤w*¥î6à}é0ŽÖŒô#íñ©6ä<oùWÆ*ηº\(Õ Ë%•ÅàLHàâPÂúLz³éÞ·§ÙƒWA;PyKÔOhá•ù¸ui¾7ÓZ¦]8rX}4¤ÅùÚlX‰wE„üꨈDDä]µÃ´SE¤ŸÑ¦Ãä± ‰mz‡7ó%YF®üø¨æ»æ£š†QÊQ*áÁ"EÞ ¸žü^ë»Z)‚¿ YqššS‹V<•S=Å7µ‡Û¶ï •ÍUzEvéôʘñx1ãs0ÂF $´k†–̇mœfUÕã:UYûÛjT½EÆt÷NÁI^!É­Ñõf©Û½RƒZò%™¢|ÈõÝàôhÛGuðOKÓ%—ÒT?(–7ßt\ß7ícçI(™¥Ž|±Á=Ãõʼûa7Se5åTVÕ0¬UÞVQ—¶ë2Øæ Õ.@ùžíº_vЉº/ X,VÔ%·Ð¥€i«‘>K“Ã6A·•õèz°îAá«»„ölÍ74COƒ–ýyOƒ|Xª- §]rAО¼ІëÞÜ£asi`òm¨AJ¸-\˜¤ïSº•aZÒv0!“7ª¨´N ïGߣT;~w¿à*…ú—Æ&[ô·è½w»Î @ñôÅj„®ÖÓ‡YC¾ óPît…ËzÁͲáñd7 ]°oLÇì‰/HìÉD¹}–$}1 YV† &–oú°ú0O¡qëàURϳ弯èOøxGVZ¯þÜðî¾ÙMõ_ÕO#×óÃ0Ï3 C=SÑvT„ÓŸÐÄ^2LÐA@·û˜£]M¾O*; ˆ± '5jOÔ ±ìÜmÏAGÉóNu´ ©ƒ›—@n˜Õh©’©£©ÞãÉ¤× |P¶AywLÿ"ûný¥p©EóJ6–P ×qX´S95ð¼âKF7¦)Ý—ž¯B­µVzÍ´(C¢<Â÷ ²æÔÿ&‹)¿Ðò\¸ãZ ÿ‚Só26°@‰0j»¦ñ±N3j§ª›Êr+õcù6XvÐ=¦f7ï*ÐNñ÷.VbôæóúdY‡ëÖ¬iLŒœ)]Ô±›¯G«ÂM¹ÐX*®Àm5£¯F5÷ݼð˜eãÚè1š8ð)8fæ›­×C*]ä¨÷œ‡¬Üã¦o Ü!+A‰†Ä5 šï[jÿ¾¾8µ‰Ò‚ò¸†Oæ2/]Ö§ÉK¢#D#>”©EFçHçHN’ªqà$Iv½ãA9’oÙÞ™%]C#ä\`¬EÒ`èZ‹ufá:µù¬éØé±1ÝWÓuàŸ]1çÃÞƒ'†¶ÉRci­Êá̤O’‹Úô hKk=@û¢×¹Þ_wžÅ(ª&°Zs7‘b-í9k».„‘áªÐÔÁ!ÊñR2XúÅÍ¡‡PHâ20ªú±é&ÊQ)F2N¬)0  |}Òê1Á:rL–Š1-­¶vû0¦Ýà¾«Í ª¢++A£°Yê)‹›**”Œ>°ž@S¢Á¡Æª#¤î^Pã´ÎJ1wCËaÜš°\A;Œë"ÉWY‹ûÙn¦„ß=«¤«L,ýÞ8§ENµÑ\õx£7õ-ý“xT:ýy1@â.”†×{”…ÖQylâ<Šš9¦­†£4Šé“ZÐŽtlH7Ë™ÅñCÌ"lÆöV²óº^’$¯Ó°¤¿Ø¥US3˜ïÞ ®«è'ÊrãmUý®×Põ^Ç1ŽTãJ牋ûÕ¬¬ÐhU´¹Î)L eS™¬å|bR`³tr ëRM®<¥c0… Š[–ì@˜aµ‹Ž¶nZ«®l•qXtK)!‡u3NZÏE ýïý:ô1YÜ…V‚î£w„÷}…ÚàþàT‘×n䟻nsBÕËRSÞ!ûƒ¶%Ì.m]WËë¸Ág{íþïv„ãÏ~ȼ-yûûbgo÷ÿQÒ—÷|m/úOÌÿN3ž¶éÛqØ·×2ïûúŸûÿóŸûÿý½Ì}Ötª÷¸ŽúU•häPx‰ëMé?Ò¶àE÷†ckûªAÙÉ*¦$‡ L-¸Ý²;EÕð2Ï{¼¨\Ö¢š-pD:ÄzÛÇ¿_ìöõº! a/z&ø4…ZÇ*.ç[­¬ è?n¶sÓÆBà€Då §\Žyy Cö,ûB©xïä':Ti —^ªû`·£‹Qû×—ÈåÒ'"V»—£¢ÙòBÍe›†©þÞ•Ѐ%£/$ׄgÝ®zé?T4¢—~V4’6!»dü:œ ÜÓ„Û¼æ÷§¿ï©ìß]ø8ö—Lš@ư°r5¥hóì?Œ²µ8 (!ò ÅeZ§"Ij4nnضç;l: »G9iî' ±E´™°õr×kLAy¯æ*lö.’OéCJßÇ­o‰6€‹²'G—'¨´s¿˜ÅT*QÝHß¼²¤¬Jì,Ø?ñý*,‰ÞºÉI!ÞU·oNÆYeíDYÓ®×¢J׃¶Î¿\÷ÊV¹ßaì}”â3°rOM÷,ª¼Ë!žÃr7¶(´>(àió6ǽ@P¿¶'kŠoÉ}QýltßöyÚBÈZǨÀÅüÕ„õ†6· ¬ÿr.ÅÖìùikÆÂu_3Ù°_‚Ú%]ئ8Ik!È÷%¶½Ñ{jiþŃ{µkúÛ%|ä7÷õø>$NÚ²hë²gÚ,0,;²Í}Ë(òH†o{mƒŽ+•¬Á™Y|º?†èu° /ðCgJ9©¸Ÿ×y“ò—Sà¢ÂºNgèžõ>úHÑQþ¾X=—ýïØ0®¡.ê½PËB»%Ý÷ßÖóOG«/­"Ø2[? °·µŒhÛ%^C[[ðC±®3YMӬУÓ- ¤¥§_™…ñ´zk8& súj8·+êÇ<}G,‰mn´y¾åY;¨Žži±,†fàF>T[oþWTèdhõód‹ÊqÛ2¿Ø”sP „ÇœˆòoCAF\n_ÃO;ÊFOÇ xxA\n;‚4©ÂN%‡EÑëÒ±GqhÓÃü E,?ˆ“0€chpª^ö l›|ö䦢낟|„Oôàú”ù'àú`ðVÜïepÎ÷y=¶]UEò[©²¤$†Šs(6ù§Óú5"‡÷<•­OQ_­lMŒ65·mX¶£¡aÀpú­1pó>aÉÄõè5‡ÌU¶.@ÆäµÜ§€ ß Êî`ÔåžøÁKk›=˜Q6 &í¸ó< Ç*O§¥Ž)Iøð]“TMøÇ$édò @˜üДE‡ŠI‘=Ó•AJEð< šƒò¿ùtoÝŒÀ;ï­Ë‰½Vž‚º×§b¦ €.UN·ýF§¼¸ÀgŒ`}Ùû· Pò… õõç*s˜‘ÐwâÜR­ùoÅ”ÌTœpcĹÑݵfØú¸§¬ó¶-¿?e]W¢ˆÖ øR.ººkš!êd9Ç4]JÚ° ù8r.ÆëO°¤´&¥Ž:‘|§ZóË8Wi¯× ¥ÒÆ.ö=ëÒ[BIÇEµør¶¬J÷ö妱 Ô=|mÀÞ 4—,ÏÐâ¦þÙòßc*èî‘$Ålº“P÷³}êkEeBQ9^³c˜£‚èRÎ2?Öo U/A\‘RXŠê,¢³5Nû*³(R¬õØÞÙ:íQÿ}i)^óý rÖ–}¬é¬¦}¿¨,ê!‰‡m•¯ 3ðaqn8‡]ú5¬…?éÁÊ®èX\„aïeѵQ™®rËÿ°–w;E]Vñd`í„*o€Óã¸mÁlª¢u(e˜õóJÀXšDØOMlï/œ„vWm¿«p˜"&^Ù,Í*—óA‘òû°!9€ME]´9Þ~ÅF5å\m4«¸o«T¯Då>øž§å @Ï~kÒ}p €.«Eƒu‡wUUƒê{JŠ*Ó~]Ëÿ¤z?¾tÞFÁ«âàÍZ‘´ñ1&RÕJᣑÅ,JÄ‘ÔÓŠG º*ŸÕ£ÐGè$±XÍkåcÙFk&š\?-åÝÌ+J¾"yC C0H2ñ}ÙÃÞÕjŽºI2ñßžë­øz® ìí(C’ ‘e^TÎt/—C]¦±,FãíI‡R†›†•]ÑÐPªï¬HKöÏÁ誃re¥¢9N¨\Þ×è—ÕPÅ*–œÑ1*êŽe¡%ËÇ%žÚÚm…jöo† û}Jzõ”ìŠýápŽ:I®f€å·q”2ÎõÍ0¡ÚæÛn`¹•õ¹ÖÒÍ©¦ëéR ÙFt³=óá—µ<ÿ¾²MFèÍJm€â€®ú’yEIžTãñ`æ þÚpj•Å¿rÊR¼2RiÂ9Q%Y_;ìÙ˜«bÚš^$ñ±5´ÊÍ1$V€/r™8¡ÇG˜k£÷,0µyjv*~rÕä3Ýtú±7Ç¥ËS!MÿCZùI‡gÅòH¬éÐp´}¤hRõNÿ1„ãïëyo츊wa@’ª ýÿ/€¾PM­¶mWq%é·rÛº”-Ze6ø»óåÄ·Âõ)¦ð””eÞnuœg±*å“ú” ù°so޶4LݼD&9LõC%Æ®tqÖª.!5‘ ŽPH‘åÐc„ÞÊ v·§†Î…‘½¡ŸÇd›Š»½"L²Í^6TŸmÓ¤Byuô=M ‰®ÇµÇ§¸ÔyOMJù·®ìøv‚k4÷ÞRmÐêƒ39ºÑŒo¬#1q@1}º ‚Ÿ[‚Ü=î;É )M´ã¢pJ—PT~^Ñ8S˜;ô0T¤1’#4]{ /ÕÛ¸«¦Ì~}@˺6hlQdª&Úá0Ìy\gk˜§á6f¡„ÉÀ È#ÓG´ý÷q>fmçìCôÊðŽsþœam5h8C«£RÛ¸±©Ãí„3Ø—)Ï—À^ŠêvEǶ¨<åÉ÷©œÊj¤TZÿT—~,ÐO»:øÆ•E7Ù®•%¾ÚŽý Ù½p‡”ªƒ^Ä!l¸4û786S.…m`žÉ‚€µÓ[ÂÎÏuu‚²¦Wϧ{%KÁ×6K¾+A\HƇ‰àƒsp °?4>퓱›Âjï3Î;\±°ãѱ´/›óq#¯Ï»¾^0aã™E–j:ò,¹ROí4äÅ…ÀÍ€à-¸ð“>Ìw¿´q"Äo(‚è €v‘ì mzÝ:uùhR펱¸õ®uhû?úQp[_ßjÛ‡0v«¶§5Ö±Ÿÿûßûz¿oûþúÏ^¯ÿ ¾Oýµ§i•õ³Êй«‹¢Ÿ ¡R†Šh߃i …hÙÝö•­ñýZ'"¼¨j=%Ü÷Bí{?¶c;…ËÕÓZôJ}ÖºÐ#ã‡ÿ£ø(ª·'‹‚»P0)ŠÅG‹]Q»¤.e&Tîš7èl[·Ó­ë-`EiØý~‚X«Zleh3«tív…²”ëø( mlIêúƇÆ9…øí=8®dz¦Ç}Ü,cS¡úe1Šªï¢rEÛá›ï²ºP qô¹!M帚‹¸hç"_†¿XîRnL4DËb„,À‹5ËNÉ>Ìe´FY4e¿,Î'"ü[ŒA.8îöÆ-èæVb÷{ôAßòqà‘¡} GVˆß§@•'” Çe½Mõ¯‹TÿЦF×r}a%vÐ@‡R?wü-Ëüßu‡8ÄýþßWžy>DE²6‰ñVÖuê£.¯·ß>6 Œ'á•-ŸDSßÅXsìB¥Š ëô׿?UÁÒ¹…x# +Ž;A( Mˆj'–ßaejº5(t$Q:l”¹Dñ¯…Ø·\E×”œ–Å·Q<5joஇ½+ÿb^áŒÏ××ö­5+! Ös‹C”Â÷µ§b6ݶZbYÙ$Ñ}ÇÔŽqš•›tÐy5öqïma¡ú¤È¢hƒÒ$kAuäå.ž6QûC‹Côâx@Žã1ÈŒeUv²e,¤@$;hœ§Z£_Gl/ÐÙõCKYhL¹(-X×ý–ô×§ß ¶¬u3oÝ;³Ðkûq}òO…Æ[Ã’q˜¬¶sg£RSQ/aÊ,Ôõèkº¾ ÁO[Ö))zk¿Öç*#q”UPZ¦ãÅv˜9[aÒÕÕ‘è·=Ω’3 €9½?|+8ëvódßš}ïAMÅ‚<¡eX¶ûÁ¾?€ë¯×ÊèzÖ1‚r3§£M/BFŠuŒÆpÝø¬‚H@‚Îv,áT¯†ë}Ú?±Ë,sü*æ, øS³3UØÐ¿–ŸW;†ÒæßÚ? ‡(‹~.×q€*lßp¥ÆH— Áïoµw¡µþ¸Tp,%€#qÄxT"›_¶cßcÎØu“„ߢ éRGº_×´Þš¡j^Ôö=™¶Þ”´XÖ&dÉÃBoüââÒdM–rNæ„óØÉn\'ªõ‚4À<ÿ›‘T¯Ô˜N±Z8JmŠmŠ*y_¢ªyJ[} á!äªE‘Ͼnaö¡x~úPÐÁ¿QÐÞÓkÁ6§‡“(78/ä±mßZ\¤DXki—ªŠãeݶi• SM*†]Èxض^ë¢>þ-PiÚ6¸.ês8…h^Öa­Ö&›Å ‡–ÃU¦Núý+ßrÝžZÑè;6%eE»ºSQ/K·–2üa-ófø—j„öˆØ7AÑ«@×» üRp[啚†=úy1ŠHöµþ\5=RÜN*Í}ÛfOm(-"- ]ƒªu(2žYà:éT=øE—w³w^ > rÆZcÙ³?Œƒ¿^š±†I ÏÌÕ°yÜTQrRýTËmêÁ€Û9¶{8>œÊVlòè‹ë¹Óg¥{ŸÊˆp“­æ?¾{3MçMW¹Ü[tð_|×䉦Ý×\GìsTC )‰jéÄPžïIa@^N•|–^­¹‘_47èGú¸|ŠÀ¾æúÙö¿ÞW="¡èª)f9«ÇuìV˜ÍóNÁ£ê»–N©^.0JO)VzaÍ1?PÉ‘2F”|×C²k$ T´l+ª'¸á)jÃê~®ºEa~hJÃF‹é~È¥•¶±¤¥Öq›’^Û¶Íz5@[°Á¼ƒ¥Ï”õÏÇÑ‘ 4¼€QɆ4·xR8Î6àƒOÙpyÉq踳y›“Zµ°F‹eÞC¹} £SNÌþàœ×UÑ ÑŠÃèºjöŽa5»|Ù¾'-b¬†!(eß2SŠÄacN4eW ’å`„oº/Ty„ñ¶¯•JJ®±|hDщ ÷FÇAJ}Ûø#òéW(ð62#G ÀPÀEÞF‹ùÎMÓB>ü"¿5 AØ#WâbŽ[kIgz¶ajzy*XÜyÌ|B¬ªòI?¯ƒŽ³åÃK7) ûÒ‰ùM.¯,å~´6²E¥ «¨PYÓ±'úÖ”í㊦I(6ŒG¹Ì‡VI—Jø¨B¬¨A¶ô‰JŠªÛ¶A€¬>];®k‚a¢Â £”½ü›ô×K‚ê›ÎíÐÌ+(Äû2ÿ÷¿ôë×í¿{žÝ<äûn-a«ÊÇtiCiÚIÈ‚´0†h¡Øî{¨H/áÎRå) †VzÎßÑ=2gk?7e5.ãÐÿ²˜‰¢âÚæ @ó’WšƒS,<´9R57S:°6‘}îp/šÒ»¹Ùc´®@•ïï×÷‡û«VË-Šm£5×DÌ5°å&Ué6|x¶ïe6Æ.x®¬©:$ìÜR,é¹²¶Ý¢v«è¯²8Ä0M¤õdþäúŸf_ºƒŸjÚtW×"ã·0˜lŒËml ž£TÍ™@"2ßÁ íý`Ï×cåê•"CÆÍ¯Fc¢¢(jXŒ™’wy05Å-ÖÑš÷Xùâ±Ý·4· \ÀVší—¦+â¹£24)º°ãnÕš!Í Õêí^ÁŸß2X¬yZ¯Õ†òiì§¶Íú¾.Ë©—CG·£å;ª;Ó¾ÿIEû'ŒByw=™sƒ ­è™\°sH£Ä=§™±Y^õ Ã¸˜çU¯…I `³”¸Çá²q·Ãœ¶`Ü t±5ÀR>[:Mi)zK&ݲnöQ<]£ÞYN `rÚòĪ¯ÉºGÕŠÝVýº–õ%”}È<äV;‡BæMu\÷ý­•^‰ò‰d&àªvö6.¸¶¡ûÖÖÀµviê´3ð FJz–<—µ˜Üß÷ ¢~úq\šÍw–DqœC3GᆵÆ)ÊãyÚ‡–’EYÌ ÙÇ<ÎÖG¹5 ùQç¹eç&jß:Ïv`á’¥çrèsHvrõ6‰MÑ$×›µ&›k®¥%Ë…×¹C¡ÆâïÙΑ¿‚˜®íƒI7`>U ÎäÒ«ÊDz˛º ³°” €µíÒ£y¬›~¤ÃÌâöu?6YÉp‹Z7Õd¡èUnØ—8.¥®œ¼Ç…sÙd/1€ËXË^5z|àÀƱjŠBu/*‘s£¼–BïFÙÁç[»¿6ôª8N÷ãsµQ–RŽ\ch;ú7®¾¤\u.ðs …7Á3uÜøtrç@fêÅ\m¶ƒª*ùªtŸÜ,¤rýOòÄÇ÷b]Å+3ä(u­å»óEý…Û¸–T`kAÀ_›%xï±×gw Ì?v7†|ü±»¸ôÓ]›ŠWw÷…õþƒ€HÅ„GÞÉIœäk_3nÅ,Õ¿ö@V_:í?Ì »öº%BŠè ÑÑÇΫ…^>á˜F”oëi@ÿ¯®SÈ©kqï" ¾²IÐÞ_‘Ò>Îe²Ëï.Òhkû:Ê7YÎ[žgYp:g»Y²ÜXp[² ÌÃ×¼oú¶L£ªŠd1ª' ×ciá˜Ã¦CÖú/sl·Çƒ³ä§¶Íc0ä° ÃºÍÛNiβRI¼íK¤âtÉ‹,¬ó¥Lª¤,Kuü¾A±Š ï›dS®u¥×Sn&$MdóÈ$X9;ŸêUEËP/é–JŸ>ð ’,‚ŠFÇ8[ë—‹â¾=߃œBè(r†ó>«Ú)ªÆ^Ûð(@G ¬äBÕ¾‚¿yVE•Æ=°ˆ2]`cµtêÒ<,Dú8€0Œˆà;£yÔ¾|¿Ž| Ôs—ê„C2Ôc´MS§b™lü¶Ú%¼ÐÝúxÏ«Œr´“¤ªÓ2mçjË£¿|´·TÛÆòûü;›Jt^µÉ"ýoµwå2vá²ÿåï¼b ¾¿Ò¨TŒï€ê>PEŒT;ŽÒ @## K‹\ý³(­´Øn£åÂZöÏJû êÚéNi5@¸ÎíFŒþM…#ݵ’ݸ扊aØÔKþ6•‰“Ÿ(¤ë˜«!Çu*Ù©Š–sÙF äOëŸ.H§û“5¦XR§¨8 `° Î¨Ú|¶Pôb6 ³-Òñ–ðŪ}¸ËœۃћòêVµÉ^EŸuÕ˜f²b åV_Hâ¯û¹=K@曌*´a Å¥ŸŒÒh†VßK<Ƚ3ÅÑH8“‡X¶Q‘Wö²Ú0`ïfQ»v ©5œ8¾óŠTÓdCižâK—ÊÊ¿•ûNEÙW”×½–¡š(®–p­Šme²ƒ‰‹ ·?ºÐt\÷ŒàÙ苩^¢+Š"Ïüåþ)ÈÐbœÓP%ëqoýFhJ8–ÊÓ¸ŽÀ¸‡É»\KÞa«ôû÷½ëëiW³Ài±…d‹.IfeJ†~u:úkÍ/JTþ¬ùE‹¢X2›;òvQšÒû屉ô  9ÏÜA`è7:úTiŽ…h½EI*fmdJþÁ O)!]ÐFnµ¾Yïã¶Ÿ¢O½Ê»³PuQí€îŒ¤ý¡Fùb†§¸AZI‘çɺÔC2dU5òÞ,4RX½„žÓè*“©ËœõÛX'“Áð?CèdN‚rw@1ö!ÌC)¢/-@h \ãï_ç±ã;Åb”‡Å |)Gü-Ðï¯Ã™™åÝR i®!ÙËt¨ò~.e÷Ò#Ñ3€¯snÁÁZ¸pb·õ®á÷)|z*6üâ[šŽÕXÑSµ{¤×¢wfÙ EvNvç?ä²ÕÂeÓïžRhrQôö$e­ó­­É×÷éqД˜Ž}×Ó8(µEóÇE½R¨¢JÎ>|œXϼéôÓ4ÿ`@['¦òÐE¨Ç%ù´®uºæ­ª§¶üm)ðÙ.-v䓾?൉Hß¿jC¥ººRI?Èw€l ¸T&U9¾négß_TIC2z{}«A¤c ð¬ÿzËCª¥£IÞ¡íAǶ,ß·´C”ÐÚNTíãë˜2UÐ.8 ˜2ÑšíBieb…©tfn]°¦Ô®aüË>S¤þõJ®éƒT}ž7øïÂl‘¢U¢/ }'­0Úr͕ۨÆJ*ù±…7TNtñ_æÞ×ÛXi EE†¹÷‘ÙÄ[4F{’RñS¶®ôj8YžçÙ–¡ûÍ7óCÙ‹.|ÖDÓW—Ð>Xًª¬KnâîƒmyаòùQ†9—bçëûÁ¨7ñ˜¤uÝûA[ÌíûØvÕ>›|"ñ€†Àè„ÈsI®¹“øýÙHääúÝG[y¢6#£ÛõCý/k£ĆPù£<Ñ¥Õn3¨e\ÖiÙ×êÄT¥y¢"Z™ªã.œÊ4,2ý¹ 0 ´c?í½¯FÉ×yB©é€ÿin{9ŠmÉh¹q“´'0A/†V9hßúÞþØçñýࢬÌ:ýÍ>Uå4mQ¼Î¡dw´LƒŠxpÎ>â%½Ã»„°Yž@H v˜zÞg xèÓ½ÐA£PR)…Ò‹áC_&m ãâX ÿ†Im#F°ñ«8^W -ƒlB*:¡ YÝ/uß>H’ñˆ !š~PÚi))ƒ¹ ÖKò>I†¥+©4æ¬+€ŽNïèñûfݾ8úVñÛ5‘µUY-) ªÙ¥×ò1A¥þù¤‹^ùi‰{–¡ç9+eãBƒ6nGµÇkÖ¢oѳÙ–£Ï€*Ä@‡׿4Ðÿø¾óÕ!2Aìãæ^ê%ŠÇ¨hváüü°ž°a.ëm@ Ãô_$Á1½£¸–û–ôT½wK-šaÞl}bªëMˆ¹ŒëŸ¯‡´sœ`vÒ¬ÔZ׃Šè.)¥‚ÓÞœƒ<çœ4h> _!&qœ2Ò²•4v+ú¸”oÝ:…Ìâ§µ,(~Ú¡ðe-ÿf\ïÙ?ŽœÙú=rŽ×(nõ/d—oH¥P&vb‡ŒcÔC[í…ZG°ƒ€›åØtc³ôó2l3ÝÜ˺å{ÙS8­Ö4ËÓ¦˜ú~jš¸Ó? v:]ìJµÄýíçü×»X\T²Xà¤àÑùÕ³AHþûÚº?žw1Y+l+€Œ!¢‹ƒÒ©6 ë¶NsYϲ„mÒqÓwÇûÀÚœòŸèFýQþsÈ«Ÿä?i]¨5€›‹oäžòŸÖÅÇóïe=rý6åjøH\ÙG|9A ìæó¼M=Γ«r—Neö~·m/§.âž”cлƒî^¾Öð{ƒ¨ºã&fàÓy×l]O×0mÇ‘KHYÊç4p4Ž^Ù5QûÝ@œdXÌ¿GšÖJCjN’z¥ÓK‘lm*ç§ü‡J´àpª»Ž¤·»ö¶b¥ô®>-L⸬BäWu,;Ï…½GSÈú‚™šó.¶éÜ?à¯M¬òˆk„è—µ¸mi¼åžQŒø6Ã7Eàƒ‰ Ð! ‹œ’ù*3Ù#®ÏW$d”µVöÈ•š{ˆXC]¾:ÀÒ ƒïª_ò¤­ÒhÕk=öúoíbƒ¿Äå@b =Qœ‹P#÷ð"W”ÛFÛøÛbÖºþÁÁºÒ°Ÿ/¡W iN’èð+è<í[¨(Go¿XëÃ?ñÇ»¡üán0møES–åÑ–F,î†+¢½™¯fç•§WŶÈþ êÆxϺy2ì“LÿÕùW¾-­µ/ÒM¤ú¥~`¸`¬HVéºp>Ð(!Ò[vzQª¾çn[nrogvb¬ª£ïŸçCCÇ|󒵉P°= 5ª&½à¬%ßaˆe%çͳ‚[UHT÷=i£±Êë=]§Mv/ô*€`ÇÑxdÀ®|î‡> ô`¥¼29 “¢s—Ѹ­Œ»t´Ž ´q©ØÐ¨&ëÊ9”Ž0Å^-šŒ¬R©$Iö5Æx£Ò‹yÁv/à¦PqüÓŸ‰ë„û ]ˆJìÁ‹èpMñ4˜î§²Gåžå*Ëa¤é9>Õ§·ã ØþGEÈ'#’éX¡ŒéÄÒ­ÉʱPuWÓTô¼PùTèÒE\;ÉÚ×.¸Ê0C+Ù<°–› ›ÖvOP+l­þ¥°?0Ò!XÎ$v¹á/6“ìù§á`ÅSšÇk[ ¡¬fAwÄ‚¨¬¡éÎU¨oûâVÏo!¤Ä†¸‘·¹ßëi.aÍa%, ŸëûGýb]-Óßò ¦ß1èEÄå׬ÝûcÌnèä `oX0[(ó5ÎÔã’<³>“å3XLZ¬¬Ÿ×j³ŒÞG5ú&>¤û×;Å’¯‡Åò‹ æhJFÙWc®Ô0ý¸ ƒÞ¸¶ABÃÂcÞbß®¬ž'¬|¸1á>½±J:ózº¿Ët¿d=Z*ôŸ©š ]LïÓ›"º q­ v£j¤æˆÊ¹ £.ߢa‘1E5zgt![ôúÌ·Óòµbþ:ŒÔò’Ã7Ô_F3¯jïU½¯ã¥¡„ Û‹ý½Z¹’í«ZLˆ_2ªÊ¼-à¥ÒP:Ä Œ{ÑC«ºµÚsù±@Bò*ç®'{ÞÅmH¤»d”Vp„~éÐôl§‹B¹à˜UýÍY¯—¤NH_88܆®ö㘘²cb¥OÕ00å <“*q­Ù|‰#¯õ[\Áš‰šõÉ­œã¡£H—6bæHËQ˜¤Ô(ÀóÝ‚Sýû*—þÒBF)ßXÌîg6Y–¢*×qÊó]ó¨ÂEÛÁq5ËíèÒ\à–O.éÓ 4³øZh Ú'U¹¤}ÝËùòN7è¾ Ê?/úwjÿ|wvøîH£Æ‚þœ¤€ü÷¬“ÈtþRˆœ‹ÐJ”Ñ£lß*zëÞÏC5í[5±^–ƒlòf¡§ Ò‰¹HÔPRó8°=5b/å£KZV•j9J§¨ u,a©ÊÇ=­\·Á•T¶n˜å7WŠe(B9Þ\Z×i6%eßWì†B»Œ®@˜i[p4¿$ëâzñxitVdˆ%ýÉqͶ-ÙÊŒêû$–L®ÆÍ¼! ß4 çvµ“¹üós.¯µˆÁü<èG£[ž%‡×ódþš\þ2!-šÒÏ´£eÇ}~h:^•®Ø(ç©y©5Ê?:_}+z<Ù:T{3î#Äy™´€ URƒ‹£@w¹üO5â` Õî reŸª¸¡ªhL»J5…¬Ehƒ%Nmód|JS &-ÞåÄËÄeê¸^“8;½˜oˆ#tÏK+ß×î·ÇáÚ6Í´â„/hÔ/Õ°•áØ† zlJH-÷0qÝ«ûC£Isn[6?mß({€`Y‰|¦=]3t×SXf”oÞŽš­ª¡Bó-â÷À2T-f>ˆš˜SïQK©oA5}:é³ g8ªá|™o蜾pÄ=ê¾>´ì!ôAÊ¢ë§q¦Ž.èašYkº,ó|*÷´ ;*-'½tÁBÚϼ{®Ù¦ñ¦Õ ‘µègüC¶ŽU¥/Z`Þè#@AŸ’Nçhþ¾½‚þ 5R^"}^J=˜s[šø\5 4ø/¢-{”ÄÉ^®tMLcY–‹üFÛLÜZþ ÜÍ#Û¿ rî›ØC0©f ÿĵDȬÂ9Ì:I¨m¶1òéôs´;ÉG—)ƒÈ Â[ KV@¤¬U‡¡|¸VíÈîÈcT¼°ß7ücÄï|ø×òÔˆBIź¥tñû‘êÔBÑ Î4ä…j5JÁ ç‡©™s´j.-ß»5Q¾ê²xÔwÌT›ª¨hTZnÝ*ÇCd*§ãJkÛÿ|ûì}È%³ËRSejÊEŠj/Š‘Êñq”  ;¥¿À®­e/V¬×Dj—ª’qàçRÖÑ$xc‹ŸÐ*ÒÀˆª‰^!g蜺2©öá÷‡2?ËÜOù‰†‰‡§üD¿Ì«$Ò?<•¯9¤çg<.+`™:ÕhΧڡ«Ð«ÎO‹ÞsG[BdÝ·…†£ÑÛB£§Ù&Šy¾è×=ÚTíZÚCzd'oá!b?RŠÞ]#ŠÒLÂQvŠ¢©ÕkAjÊ5|€îø¹‚ó#ž©ÌýûýDúϰ/¡/¸TãPkïìÀ‹ÂÐ@×ùp{B ðy¦2ÜëAˉHe °žça&Û•¥']j…Á1Y;näE2è7ß·²º‰ŽäHõË<Î3'Ò}\•ñv?Tëê•}ߢB ׌fp§fáÊŠÐèöbTÂfÇâ"_îE«–y_R*áŽ÷ʧ[ßߺÀ ¡RY yŽÏ ‰Ý•³FݾøÒ¢/ÃÇ®q|©vêê!WëÖÉNÁxÍ¿Ùì>«U÷XìÒ(8ÂÚ¦¥ý¤E¥½Hk< dÅè͵.¾V@.Ý_Òû:¡ô¸:‹Î}U†õÔw±ä½6å½!$£,$8æÅ “ͨŽâÊP\@uÝc*Þâ¼ß§5ÞÇ­üe9(<èûN˜{¬iÉJÕð‘¢ëyÀ'FˆÍQ²ª¶P“¢Ä¦d-,¹ú|ž×£³zxãºÖ¥ìZµà:+ŸÑí\ömœ„Èói¤tÙ—9ɶJ>ˆvß¿yÚZؾ}ø‰~±ª…ÌÙ)]¹­gÐóeG^RU+‹ŸÑz>`÷ §»¦¶ òÍKÖ;ºg*DÉš‹L:²à¾Ž§rÂJt= ’ÖCœÂÐÂóíÏÝsf|:KÔê+™2È4{êö"â©wé‰Ú*S¤1]K‘cpn°å6áfÀ‚6Ò=Û³µRõÐUE±—’ÈoR(`¹=•qËñƒÝŒòÔf”•LÚÀA€ä+öý=1O™¯£¨añ¿Ó©ZÚ|³§­Ê„YE×2ýíš7ÈD{ŽF´½Ý‘ÉC²r!’§%«ÙõšZáØA¥E8„EÒÊ‚®ïY°?DJr;¡íÖÕéÎ䟱¤ë>ƒ‰ Ú1i§*•JBŸRçˆ&ï–ÆãuIޤgŸ‡a÷Jªš<)Û)‹929&; zTL[B¨^ Û»]ÁÞø¤š¹ÁãJüº¹‰œS²³®j‹ã¹úy5nü^ÙÞë·îSA¼èÖ?å·–ì*®U•FS#µ%æm@wØÐ}ÐÀBë­7_áùäæ/®~˜FµGó—>*4¶Æ:.÷mÔ¿¤p‹ ªÎo§×¡ÅÈ\|‚p¦¹Ó0¨³qËÚ¸NÕд«,X6ìò`é*È_O&Ç&ÌŒ^l+Ň´j(…ûf¤;k˜†±­v¸ê†Ñ¬ªµ¢P²ŠpЦcEà«Í*¬ÿÑò\ %@)£<ƒ²ómy~œ/ÖÅ:˜--«>à¿èÇ&Ù2«a_¶%)õR³Q=cp;’ß7ÝöÎŒ¬HˆLU$) _Q®ÚuhbY zª8Ï”t•ñí—ƒ;ÝBK5ð˜©l}æt,Gú©2-Fm‰Æ|AuUކÁÕzàÉôÝ„c Q꜋: ב6FN¡À¸ø <Rhh%ñ÷ 'aeFV̸ enAyHC%ÛÒ¥ô_TÆý¾šùÙzdò4úSmM÷ K6ÜŸ¢XÏ”*â˜ý¼ é¿å¿W–x‰xD ò(K`B7ª‰§j‹†nøm%Ïù8ð_:Õ„=SÞ6ÚT)ŸÒµ+Ú8¡õ˜3üô#ç“ùx¦&¥ˆ¯ñ,pÔÜ«p‰ãaéÚ_Íÿô*Ò*•YQ4¬âÚÞÁ3í½uÝæu]–_ .ú™t!°aB©CZ0 ú.Ý6ªyØbEé`µ’&ý°U¼W¬ý™îP4²¦ÔarA¢³Vy³e°Ñî}²‰ ¥ý–—97Ë¡ ˆ°~^‚¥^¿-æ{èI?¿Ÿº'] F©}éI÷É\P=Ó®ÙöÛ/uàr˜KÛ#†«ÿÈ}0Õª¤ä#Z¢e–dÿm{@¼êRŠP®ÿó 0lyœ¢ ¼FŠåQÞ'Ó6ÿ¶;üÛeÚùÛ(ÿù¸ÊsØGÖÕFUs8ª¨½³l¶®~]Ï»vÞî_/Í`Ï4Äk³ÅØ9§Ã>ªm,3–jýuß¾ ú•Q›Òàb°`Ç^ ”Øom½PJ=4Tù–µÕÎÅžÐVIïé¬×Œ @²@/MQªÁ4WQúWÇóÜ·Õ_î[ó-o{ßlâD2kD‹Dÿ†Š@4õ’¢„ î/ûŒªÌk)ŽÈaå LKÿPboâ0Rݾ,Ròr¡K—§еbÛUê]^ŠÁlÛPñ\²í¸u¡šžî»±,éî’µ,&Õ[h¸ß¼Y§N˜ÅIì›EQ ìÇŒp–FÉÖºŒÇf‘D[Ï`g^ü×<ܧ†ÇÆbŸ-*Š¢6*‡¤<ÖrLº†@+qƒÓÒîß|›ãé“!þÒÐoù^ð½ç†>}Üp 0Ý¥ƒÚú÷’´Ùnt…[Î)y}a9›û|Ê ¿X;)‚©ªâ:¥ý“¯q)mBºc¡²l‚òú.žt¸3†J7âJ•ì0@Ù`7-¡À³0ê—ãhˆ—cþëbùõ:À1ܪ)ƒÌI«(óI†JUŘZžã†‹×»Q<Õ®¢ÆµG(Xeä°¬©N‡ ó.KÇrê²\N=åv&ÄM1UÒY”}•H{ L\θ÷æHkSÓr¯‹p”L%ð<ÃÆ¯M ”¥Ù"IëS¦yàŒ± ¦tB-Öw J·]*˜wÈ|97É…y7ÿªýõJ19À¡¢Q'¬õZÍI¹oÕR•£Ìî=…z|gØ'@÷TÀúÏ×ýÅ0<Ìz²î$œ±IŠíÓ¼ïÛ·ÿ¾î¯;àê{žÄûNÕT³ qnËØÓÕÊŸFY3¥£v-kóhF¾}aVq¥•i~ÜÌZ‡yoײÛNRIϸ!÷öx§¬öEò{½C‡…÷5†À˜(KSbhEO˜ k­†tÊø#ÑÝ2rªöa6ç]uX¨f¡R[üAѦÀÇ¡lý*Ta6êåOÚ>!›kMá‹ÈÞëK›°0D¨.;fñœÓ掻m›XO•Vs¡cËä}i0×zв‚$²ƒ¥Pí8ŽS©~[ â³ó—¶ qsm/ëÀ5‹-KéHg|J »R™úÞÅu;ä‰Q·ÓΖÙ.4U¯Y“Q°êË,•Iš‡¸w£äÀômóbûø¢újuóŠm¸pÉÙÕcOòŽ>jXUúá<ºèöq[IjÚÁÕ{÷ Ê„¸ ŠZH"ÞÍQ­óÜŒi7Ñ¡~Y pï}èˆ /1Ô쟩Û:Ë@Oº.ûºÅgh˜Uƒ”§§aÏÁÇ´Z´Ô”"™ÄíT[YÑý½Má$?„pƒé9Øug½g„¤%æ¹EJZÌ1»n&$•i”4]Øæ!%Ï"îàaªáAUË6À[Ã?+ô— ý­ì5×À¶5Paǵ`|º”?DîJïíþÀîÕ¯ÌÌ¢3J;ؾ{Í$¿S¥åï±”ê©"c ’#ì^T‡¿¸)ƒµV‚µ•*z´1š×yMe-])Q¢ãjü‚ï^ÍL_Ìs`ìy]æ ¿4¢¸šÇÍÒ•ã˜c/×Å0‹h?º‹‚èá\HZí¶@ZÝ1m‚ó¹XÕ ¥¡c8U•è^y¾i@NÂuX¡ó;¿ì‰4ý[ˆØ!á—‹¿›´I£AÃXi- A.Z”5اtÐ „x¡HÄdõ!¾4<Žîš¢×TlçÓHg`Ypä‡nN»T’ôs!YC©§ åšCøâª *¦Ò0P6 ä~ ߥJµ]«›´"<pÃFÑY¢qH! ¸”,¬PÑŸ€MaMÄÛ¦z©ê,mš)ëºH«L±$°B”{:ZË8xǃˆ@2ÔžeÓ)pPáÞô ¡Âµ¨æx‹ÖqŽÊÄ£jÎâÖq×’}b^;G”Ñ0G!+Ù0´>X"Ù8ue6 uµçúÄû¬šib—ÚZéÕ$žA€«†üp§Õ b¢ò½ßâ—sÀ¿¬t*¬-÷_¢$=šv!hÊ\Pd’©Ïj»ŽbÒvr äá+ØþÍ2éê%D "ü²¦aÐ(ÜîT5ÕrmÖæ”‚ñ ´dÂU RÜ:NšGÐe#¯—¶ïÎØO •²ªy ÕDqÞT¶ê¥,hɹ¸_|Ó:ªý©#¨jÏOªZ×]¹jÓ2lÇbTžßn@ÜhFà½írP<¥¥™oÑ6Bo‚ÂõPÍhGUGK׿Ý,ñkõO}û’"5cHR5ÇMCM§G­¾AŸ5€üËíLUíáKù{=àÈüÁ#¬‡ð¥ýí- zFþçxD¾Yvð¦ _!Zúe›jÝmªÅ:äÝnªò6Y⤺ȼ38)¡ŽNßß—àÄ@e˜]Vs²EåX…•hTù‚KŠéŸŽ Ç|ü7ïqjÝ U5j§Ë:¥Ùîú§ÒÑG¿ú¨–€Ç|ûvõ!áDÿ)f°q M®ÝÚµI†2ZUNC¬8ñÀC™ˆ† «q}(¹=8½%7JX»¾ *!JnžӅ¶Î{5£, ³_¹AÃÕ;úÐÎE•“>b;U×eÁUïÀCˆì”ñcXSõùi-_‡k,po”ÿÃÃ9ºuïHõ·X2J›Jýøß mL™ºsMÏ:NHT)ÂKÛ2Ë ŠF­ã¸ôûÞwãÊff38’@#Í:l×à~J›S¢¤Q' Q±7kuÛ¤þu­àÒÊYÃ{õ]þ?„ c6” êã y‚ªž–k1®Z냷0ä¸è+ˆ´Íè”MmjY6ªAJ¶~ã~ÎÍ¢ƒ:=̵nWý¯3Ó‡qÕ “ÖjÛ]5yØafÉZŒ\¢PgZŸ}¬¿œeq`âYVJuN5W^Ìf™D¸}-ˆÂ,›+:}–¨…Q뙢•Áƒþ‚n°AµmšÆ„v*`¨îõ!š%f\Ò|˜Ì|I‚”:‡ä¢¾ûÓt-Ú¼¡:“rD96|=(4iT°ÐÄ®jÒÇó©aصšeBѼ4ªÍ–º¸‘ñª—e!OÂΩšMeÛóuׄ ]ñÚ|»µV%Œ‹är>%­`sÜ €o8‡PË;C¿?Dä6#®’'ý-ð±{Ö廊ö˜¶ðþëZG^8‹D°íâýžäÀfV ðÞý4A%¤œV5Ô[–Q%AW¤fçOË:×™óÊ0ψ ’€œZ8ĪRó\PúJžÌÙ~|Äad!ìð.aNxÙ l»¤^'ú'Y”®ôŲ ŸÁŒó}ß;oµ!dšŖðr=crzi™6yšÎý¤ÔÆN¬zéB¢Î^Ù>ÉܪØz¿³¯ R!K‡éëЉDjÓ>VsØ€äË/Æ™`RV`k)h2ï*÷ `eÅ2 <482¡a8(¥r4úªz«„y åÁÛ -]º{¬3!»x\ƒÐ½iï¼L»ª9pÕ× %yÒÎðá3‚±8¥PÂdª³qQ~â‘D%Ä‘…~ÏA¡Ž4ýŽVë®DeÅ÷œ mëð3³ƒ«dË“á4‚Y”y­­¼ó–pßlá°…ÅÌ‹±#8„Q¨³ôbþÕpvÉúÐr’œ˜àbhDú¶Y‹B%ñT¥cTËW€ZžK©§iúªq®Ü6½¿ë‚“eÐøø‹éý@Uú´B¸If9+1gÚ¶Yý“k¨Ûž÷íK: ­ p@–ÕÐÓ•?l}Ù®:“ÀG5Ç€Y®ÄôwÆIÙá n_Pâ) H(F )©4 ÔPæý{æñ œå87ßu´ö±û¶4X™@ÅÓ]ZëФ/;Î@õ Ë´ïèKПE['Îëxo;ÕìÙ’Ë8Éí¦ a׬aÎ’å"þ{ie9ØÁòØC{0d©¢C×NÛ”¤rEw= †c‰ÙDpûЮþ%a}áÊû„:Zp3Œ¶µ®©qÍ·ÿ¾EYÄß:€Z2TzL4Ö̳æ\Å>ߢeÓÀp@Õ*öylCz—Å.…^@:€ÂLCƒÛ¡”n_ÌSb®.(;†¢ÒíN¸¨T¯”*¥Ø<·£Ð¿\DEµ¨ â²ô‹Œ+ËÂPSˆ¬®‚ú`×k°X½¬ÝºG¥ ?Hs™0ëñéĘMåÈß1çùB’Ì^q˜@ïƒ;v5Jæ!®\ßkÐ6iÑÇ]~ÓÂëæ§+p‰"]_sC«‘#<íëR­ÕÚ*­*˜ôamÛsé·Œ7CÛ~£ÙßÿÇ SŠ‹â̸Q^å*M–podÞ˜tl¼›‰é{  ß8íu‡ùŸ0´+xâ°¢?½LÕe!:Ä…Ün”ŲSªãQ¡gèÞÿEµ Òðß/í. ßàºí$nÔ8l3½Óº¯÷UƒŒ+ÕÞ´‰MQ73oþÛMFn\¬°Ïh ÚN#ŽÕ\7q–Ë.PÇ€Jt;]߆n² :÷þúz=¥±ž+qvZ\`oU ED÷x!2‹´–¯&hÉÔ5Õ¾koYöu%{^óùbƒ¥Žªpgƒ>Õô5)<ºñjû‚”Ù¨=”3Ññ‡p˜VÎLSEP; c½LúÙ‚úlí\ÉE÷âÙ¶½Ä* N‡ì{¥% á3£ª±ÝʰgCªgß šäËÞeµ*ç#ÕPGˆˆ[ä°Ë:QašnÕ²tçfÈØ ”{©Ê™Î^ܸWèôý» 0¬IµI3—HsèaûºƒjYŸ®•š]™3¦°”QæBsC{¶­Âº9Õë‰ixÉ}fŸãÿçã)Y£ä MÅ4­Ãÿ6^hÿçCnR!ì±|Ãc™z¯ïüï+;þ~? ¢ø¨Ú›CÏ «qà¹áöëböë%DY ÂÈ`†ÂM#0iCG5ÕœC¹W‚¦ àÜbߘ:~ tÛÃ=•6ÄzIp×YZ‰¯ «J– ¥vªŠÓd/—VPO‹Ã8ÏÊP$vhŸ<×"Ö(²©nÙÛYdÿyUæÍ]7Œ* {ª`½jéàÑ£mÄ¢Ó1ž»å¯Ñ8ì?Ÿæ 3”*g·_YŽ¡T›‚RüVî{!ÓôŸÎð¯C…û<„(= ¢¯šÕ0Ó׈RJja“Yâõ1ºþ„J¤4¦¸r¼=飲]÷Q)9î¥ÐKu† °¶!äZå§õ<óöÁùÙ³Q䉯5ÙÙ\ÚEž ‚¾·œä§¤9@†¸ü+S(Àh×¶©ÕZ©~_UÇ}1*¹ XÐ|¡àã³þc9ô:VÑúKQ«€Ö²¢M_×TBE*NêfIºV?¬´n®E&CÛVùöµ«ðý+˜hWbËÇ€%£ÂL-ô1h—èµÀ‰é?1¿ÒúÅÎÇ~û;"sM‘‰É¤.|‘ ïyNÇÑÖí¦wYl½sQe"gðt'¢uU›Ók‹W`G™òI‹9†+³Ç~O.ñ‚‘ÕKQâ ¼Ñ--Ùê}bd¡1÷­;\Ëv¬+‚LQe— SÛmc#{ÍfC#—{¯ü@÷7&D9+Hz5оTÃkN |þHïÁA$¦/ i Ò˧yUã´'E’iÖOf£‰ E 4àÖ=kãÁ‡º?´ÓG‡Åtèap»/TS«mÌúñ(a¥LN}·›}éa¿§¥ÏcZ Ú|+;ÌNæ"›Ö*›Æµ?ÖBÕéCÜ‘¬ X¢£ïœä¦E`Á$íؚîûºã¦¼~cëqÀÁ¨Z¤.%;ØÏßçeÁ¾ð¿b@<ýä±Ë£i*¢¸Ï&–§toŽƒv¤x.”‚5‰Æ½†#«¿t²Ê^5-kyc‹€‹º ÅöqN‹XôaÝb›¦>ö¹{ßëMDË…ÄË«‰¾5åÒ[SGmÚÝ:¼E#*´04¥4GkT^å×<Íø—×Âo€`‡jè„C¼*Î[ë"þñ`}UUÐ%cµø#Ã:©¹˜Ê2 UùËZ_» óúŵz Úå"ìcL÷J‰‡zH㳿AÖ£ãŽØKu‚sؽZ‡¤÷Áï›hc ‹Eé*P—=WÃ=zXÙºviØÍææY>ƒ‡ûÊ5\Ê[(ˆí| áþA K´nÑð§sïlz( \©!rc±eÔ\¸DÙѹ^vŠlé0–úÁ~ZëÃXæ×öŸÚ3è> ý×rûïçÅÜÏób¡åeð—Ç:îRºEE›ˆ¸çk½aãcï¡/ÑÛÏ©ÔâðFŸ€>¥…s”¶a2¨,Ž—¸”cï%/t§ä0xþUÊûð`"}ÏCR’òÂÀ÷ )-ˆøÀÅz×þuÉòžˆ½œæïyJWLBç«\Ó_Ö‚´²ù“[î[Zþ[JkkCwÔöoZoÆ1¯ŽÀ¿N«Š?L«(7õaØŠ.ó-ñºi®¶t‚ |Dræûd'»½ÑÕçR¶O÷³ý†ÚÿÛ¬ÀQÄXØÃÈÏ´µB”oþ…´ÑO•^ ú &F’‡´ÑEÐâ뎞ºFá:ß…Ý m>Õf¹šòžâq~<F&díË?Û¤Îÿh-¯Þ°ô`®vA„eôUk{i¹ý2cË7nRvŽiº{—RESý²[(\Ä¿y… g&¤+vû:Ë։ބZ[nMý°ÔjRštæõÒYyʘªŒ™qŒ©Ô¾¬M³w <6YÏ1¬›Eë7O2°Ø/ÊýOèµÞ5£Mh„ÀÑSÕ1ÒµÜ˹P{¶=8qަ}ä¿`^Úó2N•`^~XmÊ/à zkh­ ïT^¸- ÌM»jvµO{ZêêQ>o>Yõ 4/pœx†øÀ;¥'JQÝNbàF\€C©)eõœâéµéCo|˜)R ˆßNŠ¡2®?öÿà‘w‘¨¦«zJ÷Z– nT‰;P…3´ë›íÿËù4{Ye«ßš(++¸ulÕº ¯EÉ Q(·5æÂ¾}è?¾Ñ(wäG]«¹•Ú©ªWùšvI!‹±ÑÛ OhO@˹¾6øEÉÀ»Ì(›§›´×Vm³ªš Ž©I§¬Ox9ˤŒÜ¡<ÐGÅpb©¯ƒ¥ÇÉñk dZk1Ÿ–~Sjì¢nÝdXå¶:¶b™ñêªH|Ò’†H­6òI×6 Ó5©WzÊ¡”³e›tèß}NФ¶?Èö8¦p+FâÆjy­¨úz•F™DPnw9õÀ ùt°ØäÒ¿U<Ô=húîIÒM®·÷ï+¬ ‘D?ж‰Á0[—nÚªåG:ûë¾ý÷¿{^´kèÂX×8íÒ¥¢wšöM&±Ê¹Ù”f}à°ÜSä 6Ù¾ïdAhQkï4ä·lY—VÞ(øœ¸x 瞀á3OG¦ÃO,6‡ž¼0ºr•gãç±ÊèÐ¥òB]º«&c_{ª§9åp"TEÞôQyÓ7FµÊåwz³0má#ëBî>÷/­šX9'‡GÌÊyY¢ŠÖìkö2GŽcÀ„× °`j¶ip»ÎEØREŽ|)'®å=À3}’p©åSÃt‹~¬ [ûFW4œ¹»°ê¢"k뮪X¶Cº±XUC¹É´æCUqÂiø7<˜…|Ç×#Ãù´Bؾ_ÌL„j~Ùð­n<Ð̪_(MìרÙô=ë#ŠZËÁ’&Þ•6I;{Õn`ñEÂYÊe(ûa¡tJQ™™Ëb¬uo€g"RÚÒñþÐÒ>œ5`»«…½EË‚º5)¶4’¯ê{0Cc&æöÐG ,„…DM²´q–¦sžÒË‹»-–ï Ä»n8z²˜w˜¾¬3ùÀ±Š((*( Ê £_G5¬e·6I”˜órPò ¶±¬·²Ø}žµøy“hŽ]t Ô>wM<2þÕ…H%•5·À:æ¸Ò‡¸|SD‚§pstâÏlØþù›â}”‹“®›ãz0ó<Ù˜ÆuûàÌSµ¨p˜pÀ¨Ëd[Eå':¬”Š3j6t’opYÔ1ÄþÔ¾^@„iœܧ†ºŸºqê©(Äíë5ËætÊÑ—ÖLÖ¥w‡A‹ÍΜ§wã…½~—8+ ±vuËlxʕڇ"ß«´Ú*y…tÜmHåx>ŠÙ3y¹Úžð?Ó _LGˆ$… ;Z¨šÚté{Y`Ó„¾)D70®.H:0 wu´ºîÚ¨$®‡p…OÓBGzJž/3XzÜÄ_êçp1Y×Ú€ù¯ ÚöµÓêŸ|#¥âêÃá:óe¾1Õl)¸±iÚôC™Ÿ%šäéì«îú¸ßYG#£w.’EkÑ­cf˲ÏÅž1T‹ÁÜÎ+4ðnçeys?V¯2*¬ä>Û±+ÕíKÓǺ£ÅÉwx¾çx§mƒ,ö|S®Û‘ë‘Ë Ã¸7žn?ÿ÷¿w¨Òîûë?ÿy½þ3äÕ0ôמ¦UÖÏ*+æ®.Š~BÙ•TÞR& ­5Jen‡ÙçÕAቴ¡:ÀûQDèýeSf=.öIwVßãðžìD,¹—²=M›½î)8D*”êóÏë­T‡úŸv¯hüe&¼aúBóDÕC¦s•Äc^þº–uï½^Ì™+£´(Œø[5ª®‹H«aiYΪÇìÑPü£Ph£Ñßhïœ5Ù».ê¡Ê“Á"ì—Å,ôOÌ#wý Ç™ÿÇùógp.z5‰ã>¹?®uX)wë1Ú§*S3­y™Ã0+¢&]æfþe%”ÇlZæšž¡¬¾À„±ÑC¯§‚vÖ8Ùd„`@çÃ@ÇÏÓræîÇÔ‹¯gÑ7 ÑñÌ Fs?ìMQ4Üù  |áÌæcT"-… ÁiÏ!ÀÝÈÚ–y4ôæXì­ÊóFµp}Ê~^k…yÜUcAðÌ¢aùçáhp¨óTжîôÃùeBIPïç±/in æî Hf5‚Ì÷©œ(¥É²JÖ¢ˆ‰^Ü}<-Ìro?.r€,>/rD“.rß`ä¼N™çŸùÅ7àÁÔ`Ylv]ê½gŒä£úŽËd&zc¾X–ùï:nËw­×@¹ë&·Üc‰ž¤ÙÖ‘—eoTûëzþ‡¶Ô?é¿êçS)wÖö:û¯®ÕƒB<·O°RS0od:\'5Tk^émr¼èc㯠C¬¤@)¹Š:ߟ_bíäú%T{¡g $º¦á,¨ƒa OwóOolûÚ–o€Ö0´É»Jô¸º©íT2$y[ê¾u£$գРRøMü›äÅÔ}VÌÈd7”j›Æ5¦‚=íò2ùu-ç ä°‹Ðu-œHöì\ÔçË¢ª6cÊÁÏk®C/½X–±µo4,F1¼PsÖuÛ&7쟣_—åæ¡zÈ󳘫ŽnÌÁ)ã$KÃh®RºÃç<úåÑüàCdûÞ¤UÊWÖ–U:ÇMëå%ÔŸÒ  ‚¬@Û8‡æ'òñN¹•DTF')ŒÙÁ>ìe=d圵éL·êªc:•8õžA—¼/qÒ?uAD†æÁNÉhôSY..ìÒ蟊tU+ƒðç•V8J\Ar,–ÊîxtÒK@î@6â+µïSG4ƒæy='0ÑÈ0 Ë>}S¯æš˜~ŸÖÆÈ¯ëæmmLåN91âνt¨ž\šÚ§:]ʯ;Ý acŽ>éõ˜~œ&Ε(¾5{G•ï­ÛÔý¶0†U×É&Ü¥Œ9Õ‡É ü Ã=OòyJ×Aîz‹@*qœƒmï_m½ „²1”_˜”®Ñ²UIiH˜FjnéÙR½œÅ|„_ÍJs­?üæu;ÓcJ’ú¡¡[µºašXÿ W˜—´ÕºõãVH¤£ Uß ú-©!jÎ¥8“Ԯ¬6ÔQþ)eþNI;t (Ó¤4LÞ¡¯Vÿ¦Þ:eÜ.3Ìæ5zcµ>k‘ÅK]G{4åt­ÑÏ뉒۹ޓG ˜…ffy’ŒTÝUª«æ”bé*£~ ÈÛ¦› rz§üÉÇÈúë[Òad*·!²uØEE8ÀHòp`º[@ƒÐÖ1CQáJ@âÙ+N }]:nPÁkDOå‹Jê9¥¼¦úÙ(i¢:à@©.{lÓülâ|éÆUƾ- HˆÆöJ%¯Gz™UÅPWZŠ<°¾º’wö^¯jkÏC»”Š2–{¨µefA¹Ý ªh¬:žÅX@V¾Ee¯5õxxò3ÝY7K8 #ÝØ@ÿÚ¾ÝÆ^©½íXŽÂµX¾Ì€&ÞáÙ{½œ6Ve»sºeYðO³7(‡Ø•¢| "a¹6t©è?@б [kƒàÜn›ÎaÁÉ/pý°òx‡´ßÊ\ÅK}Q )AÐ…g Í2–‘¶¹ŽÚ*>¥×Ç­f ííÀKó|¦[h’K76t¿Q6Þ„ûXÇ¡cqÉ/Ö²ÎRú¬ØG‡‚óHN’”ä I”nz%- k¦m®ô˜oá]ÆIp' _RW•¸Âô mÃuÌâ˜ÂbŸêçãpù¾ëÀÏðÂ^a`O­÷R7ôº’çN-\S†8‰–-Ríž—?¯Æz/ï$Œ¢ú¸OÅ$V¦ªEšJÕKuÛ"® |,Ê‘n¼ci“8'²A’€ñ Ð?y<ïóèJúfœ»¥[Öaœ–i^‡¡£9QY”Wð¡/£N2p³<ÓFÚuE7é;ÿëÚÎ……´nç‚.ÚøÜÎr5(ºÔ§jûy1ºz?TRE{Êy%KûÊý–Óõ–tYn:+ƒ°]”¸Ž;Qƒ'‰–M×80 pf”‰#n7æÔmU3„e8Ò?)t À¢`‡Ù§exÞíØÌoD’0t¯½Gwz}C¯r™¦m›÷‘r¸½T{UÍT?6RjÛébÞIÜ@íb}GÞ§ á»5°aØO„Î €Tt¬ÍÖ£¢û*_·½/`-ëAþ7¸qËïp=´.ª¾XË9L¨¼‚ñKßsé׋cdW$q2u(åHû.ã é†?\ÔXã½§\§ôRÁΜÙô‘S•0ä[R„Ë Ÿ “bµO÷ÔÍ:%uÞ•éýÁƒxž²³àÑ:®ZúîYUužét´T¬ÝnU·atíCÿ#›Þö—ÅØ¦÷B™x± ç2u.òWš¶[õ)¥ÐU‘mù,‹yè{¬W¥_ÛÍ~{èXDÛ´e[P(·‹5 p=LÓ6JÉePAZ7˜ºÒ&×¾–qAPRÖ˃”Œ}iÛßÖÉœ­ÓÒJNÒz´èíSö×§,oÍÿÔ¡}ò-|ª€Bšµ»ª€†c:EÚÛê‡õ(,xîEré/(òO 2Z”.ç °®. ø¥{R¡Ž¡0Ó “Š·¨Ü(ÄlªêúF¯‡K5=*J©eß½Úõò”ç¡çúðA’U„(‚È4nUµ³z­‡8±>Ü1õ Ͼ}¨Ë=Å}VÈf- Pîa´·/!ä…û5¬[þ´6ðºŽIy‘‰4ú ?½¤W¼‡ \ê˜Û7‚†%]DWS4wòö Â‰a(ž¥îGÆ-Ì×SÛYV @¥%Zux”‰JÃy›åÓR*N•%E®oÖÕ†÷A¦/«_ çÄŽ½v’™˜•Žl[²n’ L]é0Ä6޾ÔÙ™‡A¯ŽÑhaj1SAÜåQ (ŸÓTöøÁÉ*OHo ´°Ñ2µÔãý€ TÀÃiD>‰aUTå}ê×gb›Ð‰µ(Öi÷¸7Ãq8t6ýmÁƒÃ$_¦´YAføkDôŸ9~¤IVç%¸ÉSRž«hΖ¨ÎTÑÉ'DÔ¥+ö«ëÊ« ŒK±÷bÑi=ÏzGc°9DÂuëÂnŠÂ²Óèu€³Ôö¨.ôº—å`)m²(!—Ã[Fµ´öeÚ•uC+ÑÈ¢ÂÌ£žŽUàKèuÌ gìðURÑàÓª«È‚Al<ª±  ¥Ð‡“.d:H¶MÕ™§q"7燦RL«§:J“™>$½ZÔV-Ûš»oq Ï¥šmë÷æ~pÂè6ýzi–>º©Tï ]¯I´Õ´ÓmßT”WU7ý²¤{Šþhjˆþpµê9Çã©(SCÔÞäãÔŽQ™•?/'u÷2ú:¬žà~ÄÕ†m*òjÈÖ´gö4Y›4’õèÕÁ–~rð¾·K).0v$É)/c$µö³mЏKéÁÊ´ZåÅÁðг@w…à­$UÁ§SÀC7;èµ_VéfǪö^Õûºm{âÑZ¨> |I!ÊðÜU:ð´c+ùF``âIgŽG™úÙ®Ó0vl¶RóSé \–†î›Œ2ç(æÓ]`Ц‰1ªFÿûòCâÞð1­ÈÝ‹”y½¨zÎÂu29&4Ñ(œÐé\ûÂsл"T….”`ࣆI·Ã¾t]4†KÔ ñr¬ÅüTÓÈÔ8ìꢹ ø¦rôeôa§’­ËWª[3¹jÓ¢tÍÌtµV†k|;]öÊi5š¶ÊˇÀ˜‰}X€MQº ¨î4X¾S’L/×;'ÎA™ÁkxiŽýã| e?M˸ Û°®3½ƒmÿ/F·Ã@™$ÝP“ ÷mž§º§ä5•?†ò{ü8T·àŲ/¦ë<•Ó reÇÞ¡o†yçiš™ Úï”nŽcÚ-u\Ô«¼/sü¦@»µÁûÚ¼B‹_‡›k Ã8G)C¶dÙz…;# ›E/Ðu),Ñ9}gÔpƒ‡Å¥FÆJÉl¨Ø›Æq:â9Î%pT䟓WÓº°^úö|†¹x;@÷ˆ/Áb_×½ˆ·>­‡P(ú™6DŠè"t¬Û1ؼ’é¾xÂÌM7l#V R9Çãvá®¶Bz¾hÍÒτҀ%‚ÞŒ’ºtÌ¿Ÿ\=cvÃŽ…}Ç^õù´¦ìUÖvx‰‰¬è‚na¸¬üpŽ™/­ŒÀ"š§¬\^s“·t6çË5ÞÒ]<_ÊáXܹ¢kôÁaõ»¤–{ùtìsˆä4Ã7Mâ¶ŸØ éçõœËŒ†‹Ë;#ècä]#Tübô*주£# Iýûrî‡Ò*DkJGÚ#‰*nmW !`í­•ðÉÜ›iÂ=ìÁ›åöíÎáñÏõhO©†|°¦¹ùJ×S*çê¹N[Õ•ÏŠU«+Ÿ%+¥b¼[p"|æËÝÚº(üÀÔmë÷K#k8Ÿ¶¦¬ÒÕ²7ëBáZ ¦Î¥R•Ž«AIh×gè³¾¶Ç&Š ûh^D>5ñ„bpZ³¢™d-*àóDŸ"8Œ$|™;>vÿ«Oú$káÇlÐ 6û¤_’«…6fQɤ†CS¯Ò´É£)¦ðœ?¯Æ“·wÍwÑ-© öïªÄ'‹5߇1§|N¥›ùÆŸa@9o¾}¼á4ÐúªCž¥º©8o5êqPÜ$÷-¡¼!Žør¤Ã0J†½§{zgž$‡OÚ$_¢2„Ž2´Z{ÝΩVS¯hÁ]£#4-¯à\΂„ÒÖ¡Ð7Œ1¿ÔJ‘êû²šm4YEHô(‰€ŸuÔÐ/ì”Užà°¨0©ü5'ÕíNYqªöJwÑP™d_JôàQi8 žw‘¥§»ú ÓcÖn3²ä˜Ô´¢Ý@1¸ì×~ž‹>SÂØB© ·ß{ ßa_pIˆ˜Ê*+ØÄLƒÄ/TVÔ8YŸ¨}lÍ0ëQ©ŠÏ=¤ìðK¤céÃï¿(vï‡ó±V¿Àv\µ”½â\FÈ܉ ú®¬ÿ¢™œ_73[=/T!jÙ%®Lô—]i!–H_éƒgDØË‘Z¿E~öÀ(K¦ž*‰enÏ?)SûóÉåÄÐ'í¥]7FªV=]éy+¥EÐ{ÑÑ’†î™³þçÒtbùGúMÒDlÀp¶y©§©Ü³bUUK…ŒùìQL1þÀ:“íë]ô0%7d´Œb £w’½nâÂz`"† 2Ò)X»‰×}sÐc}/†BîS/lH}z°«”MëIž'y^€YØÝh§yªü±ÙÆÂüQZ5ƒ‚…âXTgŠ™NÞT.›‰^ô¸‚;^ÕsO¸¬ûoÀñ´NµU ޝ޵(ç£`ãÜmÉšç2´d{@¹&ÅYAÄ×ârEù£®÷-׎6¹y0*ÿ!Ûè EéÍ…‹’È¿ðóÚáçe–óÙŠ4áÓæœJÄÿ¹Æéõ€Ò»R е趡Ŷ=†“…®âE¾+ݹ…._Ú2÷Lþ8§ÞoJF é*Z¡F6΂Y/ÕéšQpÓ]5?¯‰{Jt§éGünúÑ^¥¶DN…N1U^(Dooªü'–Ç'‡N)òž¶¬‡œ*Ú4š+ë¡à ð€m§”7u(ã…{•ƒ'ÈS’Š.Ò@ÁÔ…Æ4¤¿}ShºodýURR‘¾,!ߨBé ß\n{W5ãºæ½¬åQËÞ4Rì‚?}°ÖfX"±Ú ›Ç£­“©½Þ³uì6³VH€•œo·à$£]ÙŸëáÁ\h³½60ím²<’>%Eg›Œ–s*&„ç\geÈx i’Öìеy®Æ²žÛ|.÷¥J—_Ö _D¬Ã\â°¾M)2 ì(O;ϘKÔu¶uØ\ìÃ~¼ðZpŠá˜°“C=Ú0õ¡¢¨¤6EQ¥£KÓ¬åßÑ—¥ü%ßBpG®zNt•?ÏîbÉÚf¬¤‡îb“­•J @*‹Q iZLWƒºØM¯˜å>x˜›•̈ëgBžFeüJŸfYÐ5JcAnx¡}‡k¡Û 3J°û¢³•ùïï§6Jœ¶0è¹)4¦aÎv©ø¨œ  @V+ôì׬S^ö'R2 tÿFJ¦ºèŸIÉôòH~í›Ï‰ðAJ¾5ÿÊ€ž ð«vÃ;ÅD¹•‚¿ lžÄñâ²µB§¤x,ú¹PÊ,:wp.09…ýå½¹º¢×Êþ5—æb ÙR¢?'iJ¥PK3ÉZô›úÑ”sù'Ðãzú¾‘!I˜Î¹o[}Ñhí¦=š¢Hm¥ŒU}4ŠîÐ8†ÓÎÑŒ¿¢¿¶O)ßàÅŠ|º> 5`26‰Že1ö „é©x7ë\ìõ£6[û¦Í&©9€£”où.‹9ß‘Ókf q0LQfÅœÞußç½[) ¶#Õø«Ô–>:*¢ÃÀaG›SüàtðýøbOSúžêË ‰f5é¬ÔÔÆÃ¸YgÖȾšsÀ®+ú–kh†uå2e4?Ü:gkÓP@]‡…ãPÚ6í H[XFãʺ_Û*’ *NÐ.è §‚ˆQY»jÕE½êjQò ÷ÝC r{ ™˜%÷7ó )ÕdKÓ†UÒÛdkÛlŸêD•ÉÄö$XÊAËÔAïÆñtÌiŽÊVC_¾Áª®› úQ í<ÚÕ/k÷à:ü M6a¨Yk…«Gù4Ç…*¶x›_Ë¿Ò3Öía 6,7yqèÀ÷Šæi¬²*–îÊO˹Î_T¦¿Í|]àXÄÍ´¢4r;úx8~~ô~BºÍlÛøæzï:YŸ«áfdeSʨ¬–Ì]©=¦Ï ào Ö:™Ì9¤\_è7ÅÛÇ©ÕÁRßšµ:dº €–ÖûKGÏV. $ôãETW·‹¾ nLkm¸²ž[ÏÉu¿7cœNa6.]*M]ß÷Ïd´¶Ÿ3d=(%´’eèÃ^=°†î’$§xI‹ËÌ‚¥mGé<¾œÿ˱’ ÙâÝÁ\зQ¯ï_k(ñ `uyîrË#Ò8ªI“]õCo›|W¨#gG7-ýûPp¿ò‹Ðé2vi¨¡ãJ1nÈu–oy•o¢÷K‹1`mðQϩ奺{|JÉÌÂ$Z£Éb¢ßK7e½M[U.ƒ,æ£×s4Ç9ÁýÚLúwj{ZÊyº¥îDCªhOÄÙÛï&í¤ï¿t“Xùz)»±@;¿i·ŸWcÕõëZ´űNÔ嫯¨ËW3‹aªŠa”‘¤~ï>RiMCñ~ƒþýEÏíº3@ ŠG´WF: Òí¥kó£ÙàzIúá_½>Y§š)ûàÆŸ¨¨mÝ—óõm-ˆ*J·¦ûÊDöµó~TÛè ¨:‘ý—b‰ÀUçªöaQìú¨ûu1÷¢¼­M8Ç<ÎFDª¤q¼ô{­ô*(Œ×ò^k­rœ¾a«ÜT%={uÉ–Oô%æ:í»mŒd_„`ˆy`FPùž=·‹>2šd(­Ÿg Œf5§}ÐE”ûãoeÓ¢,ô þ¶ÿjýwÌ@•áßP0cµÁÀ²Ï±oî¥k´}~qdŒímÜ2ª=×;$ñÖõñšÔ²–“Ì¡\¹VëÀ¿2,¼*æ<õá°À ­1SÙØFe¶N¹À:è—Bo-òÀðQ³^ÈuȰ>¥‡@k±*Ä™}§rx÷u+i»DBn î0smªo HvÛ®=„í ®C9χÑH<ÍE©Ö¬Ê²Xt0¨Àd£5@B*p]ûmÁ•JôOXm¸ûÉí!FÔ*JÀÕ\ÌzîçI´î@vØ ‡þÁrº^¦°0¸ 5;ÓÓ¡Y³m[GU éǵ‚·‹žÅ–5Èç ¼|àI^RàõZŠ@mòemºŠ©–³á³êÚg9wɳ(=> XDÔùDù3¯R6ú+¦¨ÉäÃR2ékC þµØk S6¹‰|\ȶƒp ’Ðmê,¥kz]ä@×•Æ ‡lmøž;Cúš«ŽšÒ.Œîd>t».ÀÛ[ëB0ÜïëYGÍÿ.®!‚e ³À楎Sgk[ÔýL©—´Õh«Áp0ÄàÍ?D’ß°`€Q±†‡£8Î8(i c#‰“¡¦°9¤}"Ö¡xä„®K „ot}ë~uizJÇ#-MI80@´‡8¥h’uý+ŸŽÀjÀ‚R/ά tÝÀ}©ý±î2º~qžÖº¬Yt‚ É0«¢«¯HöLâ­FÉ›ãGèY'ðäMlìû/x×kZ”ôüx°ÈFÒ½¿ÝÜÝd—Ų6´ž-Ä€ØÌm”ï›ðˆÿ¾ØÞn¯hN-_&…_™Ýõ ek:Œô’8ü¿<™m߃—fÍÇ Î h£W¥¡‰©‡ªãº_TQ$ÍDÖÅ»ãßÞÓ²Þø¾˜±}JÝA„9ºÌ'ëMQù§Ëy©:ýëj7û²Õ>ðpñŸª*…ã ÐîX( Ù—2Þ(ž~ýax®Æ€ô¾™zW1¬‰SHæç]ÑmÙÜU»ýº×.u<`+Ü9ÙBÁV›E²EŸ9ncEÁ=ûm1ŸåKTAœ—RRaªÓ!€–ÑÒfÅžTÉÕ¿½¦sûÑÖiÍ pŒ“Ô T]æ%ËûLsO)êòû'p·Šƒýl—µõZ£&OWi•ï] ðŠl‰òÀÛ ;¾¢K?âº!`?} Lw:˜ñZnûPÅ«,IOPË ¢ÕW•fto2ˆ¸ÐÕÌzW€­Ô)zÝÚ­2‹ù(¬| VXpnØžF€?«jX÷j º)×E_ª²À ã×ÅÞ|há* qX¯Ê¸³Îe“ÓµŒ±RSÊbðe4²´þÁ‚zô熯)¬¨®ÔE1Ð?•Ú6ÚzFŠêŒš”žzwƒµ´_±UrtÚR´}Kø©ò\³ïÇdΨ€Ï”ç¿)eßiÉ$TãRññú‘ô_¿ÌL2$¸è_Bc×)I¦1WmžÌƒ£¼lÔÿö9•÷®Èï¯Ç‰ÀÍV-oF4tšlR¿¬ÇÈ«€Ð'÷r pTÒ¡ª˜ëÀ—n™ÊÓ2f1­Àb¸Ú`w¨£ÿ’;¾üã|a l*T_è²8ZP$¬(IQQ£Ò"ß2™K…¸½À€¡w!¨'?|oÉÞ%.HfTˆ¸@bki•Ù`¤!`47 qï®1ÕÀUyÅ„|m(6ÑB¡^7¢,Oõ¢Úš£¼¬ã‡¡?´{`Ž=eÆ×Ùü?Úp‡ ÷²¯”Ð é%©ÒôјpÓÝË]ȸ§HI” ;EáÙ9Ý)éÛÚ¡O2†pU„iDÂ×O÷ŠÀ_tw}~›i#ŽÙÑäËrÚš4î…wá» ¤˜ŒBéݯÓt L°OxÚÔÆ¡qJÖI5=-9ÙœÊbìÍJÛ.8„yØ=ò:¹|p•ž”ÜõæáƒôÕ¶q¬’2i¢J•Zìª>ýüÚD­–aôžš±%´•Ö­J楙¢bNøš€Ük¶ó¢Kxÿ›Ô0Þi1ÉS2uG)ñüMÅØC°ÓTWâ7‡€I³©jJ*‹8{­ù Ê÷Cëäpb÷Üš1O½@9À¦$ìd6щf»Ú‹DàØ”@:Yxð°lÏ{ãp²àƒÇ#yɽF”dÔÞFC_Ïtï !d‡aŠ{@rÜ^°Çãû·¸+YŒ¶®º´þ}?8n°kh_‚Æ•õ’®fRcžtQ ÕVèAÄB7ƒÑ0uøÖ\Ájß+´AŒæ’d7ìÃWTý+†j¢üdÍrh¼ºpS†¯ò¡Ç±áƒ¯ÇJE¸üY­²pEÏ4mÛ˜uf-‡ò‡{p§ØiS÷ O†\¨)—ÿZèÛ ÚóC¿Åõ7…jêûõ¨~ôØ´¤á7϶õ0+ œâЄ£¿u´W2®Æa‰ÞÁø‘‰4>ç•"ÂiÓd¦ª—›š• ×zP‰Ä±d9×Pñ È…õŸ·Fî¿há‡ÖóŸ”…¾º‚Ýý?^˜X)ÍÄÏŒnf‰pù N¾UU%`LH¹OG+"7ÄK£óoH,·«e]¯Ï'¢ †^9'®¼"k“1Õ@E¤öyg¡Mà=~£|Ç ¦p_5'¸‘— *n›Ã—CÏÉ,QE?ËjŽEꆡÁƒQÖùÇ¥¯ Ê#L(9¬Xý`µYÕ”K¯*-ÇymX–àð]×½3üß? /s¯­˜êF/ÔMÕWõ˜óZÐ\¤Duhh²}ÇvÞß’ÛDÆ<ºóÇèÚ,sëŽÓV ¯Æ–a}Q:Q‡¿ŸÿûeàñmÄÌèÎÖ]?3DG>–?·ç`» ™ U¿¨µîU?­[´Å«Šî^ùÓ,—bpÆtŸÕý¢Æ¶ç¿'ÿ1¤Ó5ß»Ã0²ìf§Š‚CÞQ!ÓÇ­YöÒR‚i,çÆz]"øRß,ðƒ·èDŒgøKUq\ïE:S´Ê©±¡"ïß\øÌšé‡}•IZ¿×cÔS¤PA³“nŸód/£¹Us“´›Y²A7*Y°ðŹýèg¬@íý ÌØL—ûCªÚ¨Ûëtèx-‚p”AÀF°“Œd»ºdïüõÊ‚ Þ-rùdö ø‹±5ëÑ1‰Ý…*Ž„Uë%á´~l_Ÿ0ecnkÆ®šÀ!!«RCÖa¦7¦Œ %Y¸ö¸ZTº•¯‹ þ ,|ݬ`¢÷Àç^ÚC3ä{’Íô}sù]pQÚ›Žk]„#ÝKªöÍIÒe`¯±NÚ¶mT›ª<ÛçÍDYBPßö¡œ&W°uÅKÑðEù/˜Bù¤aÓYi[¤›j›}Ù¢]¬‚é"±YÇ#¸9§.Ãk½Çó ‘3¡N–ºïXñz¨5/[ª“-Ï2^· wèç<}î›*̬°“R*к`ãj=.C7zÔzÚ§N›õàÀÇÇ5ÃPËzyFAºŽe÷µå3¦‹Q"ÃJùÃ:­ÝÖ§ª™Ìz>Sf1PøG/ý“OV æ’„7\í5—º•¦0¶ïÛ\ݰKoŸ³oP{¡ò™þjÌüÞ–ƒ#À,ðJ(§â=ÌÒ·¶MÓ([éf(ÌÓyȬ`ÔFÙ9e^–V¼1®äŒ¹ÁUW . v­¢.N£¸‰t-; Y(x`œ"æ¤g& $.Ѭυ ž‚#ÐÞ9e–u2ím>Æ]a.æ¿-Jض/ê‘èúÑ_Y²ˆu)«ªoÚq×mêûyÞ¦mY÷”:= ‰Ú:UÆ]Öe{<·‰¹\)Y¢Ãíön@kß~—?ƒ^ÈiR…LÇ0£+´Ô:[ÇbHÌj¡ kÚ’Þá¬Üß•Òј!Æö¬X¿C{˜ªM:Ùû$B””V‚™ÄJtíX ä25ùZ?¤‹“¡ Ù,-‰ùV Íž,‰Îº­3‹Q)hSvRÄ–_Ó9·GúÞÐâ„m@Œ/βv îW‡¾yÞnUVEY¼ôÙ2TfIˆÀÐ…r÷lûub®*ˆt£< YàhfJÈiªüSª‡‡:Ê$ä„–Ë b $LÿätD%(xTòP»95}™eUð‰Òçßïw¸BZ°¹M¥XWjÒÇCZM±7@žªaòßnhvè‰E9fɳWJR`}{%îÿ yÿ/€fè ;jo’¯F´÷?Ø¥åSäÓ¾¿OŠe0ôgÍËŸ°`^—uãž7«o”Y/*תŒº<Ÿ¢nÒÊüZÎÍ‚„^Ïö®ýÂû p$€\Ô”5g5ML°®‡:“Åè@⊲/Ûp‘ÃÛÕ|oûúx ~&YÙjkj5Mý\Pª°Nm¦'³¨ý7‚Á]°= g½ê§>VçŒwéködýTè ?²ÆkË,8Zä²àθû8 —BcOØùi¨Ö9¤9ľª@èTd ýÍdFNE=ß:Ô <çØk3—qŸßL;ã>ű×5'kÓ_ÚÂtD!Âü .ò(âÐÄJ>$—íP<„èAÿóŸFÊMH«BS°ïŠùy\ ÛoëuÐy ;3Nésª©Mœ‚ÒºNõå“Î…^ë㮵)8?gltq½½œÚPƒ}=äÙÄû‚Íäz– ZØü"žÐI”g£Z„,Eb˜ÜT+|#ê?¥ÃQ¢¡Æds(!RWÜJ˜áp/‹¹¶‡Ò$g±1 çåÇ1’Ç÷ö6³.H °çMŸ¨„Þ3]Óe˜Ó9¶_Öã|½" ?‰¨ŽÔY×¢~®ùÞîz_êdoç¾ýu±7dzqØ ¦*Y¼—Ç׳ÞëbVT¡·Y.R?,¶ÚNøFÚXO5øœò”‡#­ïyX•¨ZÑ-ÙN•܆?>œuéõ#ÏÅ‹b ”|%è†yZ¶-–}NÛ½¨ã_ž|ç×Wøú||bDisÊK&‚$ÌXíõº+µ§Uƾ™?®ç‡‡‘‘é3Qü×>“h…¡Ï¤Ñgª¢¹)bf×þ´$Ú°oääv5¦—€²í Nªˆà”F:)´þúóÁIýKy/ýÛ+»o)€ôÂyÎŽ¯Á±ä¤ÈD£1.÷Ý\`?=]ðQýï#ŽxâÇO‹arx>Ø“²yA g`Ö6ì¸OÞ,q<äeC{xPÛ¯_Ö/zHGOX:Ÿ~ð¬ZHÄEK'bÐÃoo‰ÇUÁéy¬Åˆ¦ ~Æ\¼[«q¨¹ê¿ÃÑØ£ȵ€®¾\Z‡ÑýãÓt硵۱?2wÔF]ª¸ßâ²ÇTƒµ4÷ûQI:wÕ~üäÞ†xÑg„i"4¹Š)§ §(2UÏë&M&Z çÛð¼¾Ç+ïQ£÷Kp&ò`úp/ÝsM €Òm<¨e˜~Y,¼oªƒ´e^±ábžÑ4ý€ÊGçû¬šnժʬ§aй0p0:7xyJaªñ„*¢L5Dæ’Õ*öœ¾€¢ò/]öúx×"Êô9Ád–4øfýñ2¬Y¿7!šH—)u«&MR:TŠÒ¸b(’øKÅ"Ïm}ÿfíoÿ͸ø¿Ãø³i—ø Å&*œ0ôï·à„ñ_]ÿ›¾L;m<РÅ\Ú©k»;¾ä¬<5¼àlG4‚éˆL•zÌsʤU7mùÞškÐEþå„8G;Ø}óÌûW”^-”^ZÏwn°Zp¡ w Ù_úG<ñÆw(Ùc…¯hîMÙÞïý0Q¦¸ÊZ¥ è¬Ð°H­7"³ƒ¹§‚Ð‹Ž¼L¼Õ@ËS³€—:Jçâ¢ÞÝ£h å,ïüªW`$ó4£ðôxl© gÉ–ŠÏ)›“¤Õ£¹U=‹BÛeL÷CÀÙº¶Rè鸀, ¾¦—Z[յЇe \œªøY–ÉÆ”Ú¶¼Ó‰ë8‚™ë%»è+»ÞŠ’êB^Ìá°FY×Ϊ%‡5¼Š±‹ŸÑN§¯ÚCÚ]\¼‡t×zT{ÛÎ:•ÃDx ß}× Žá²ÿÇ_ôº¿§—+쫈§[è^(hË­Ù#0s\ pÇóâ¥0a4{4.9íª©\§·Ò£méP}•K Dq„޾ChÙÆöæÞ¯3>¤7\˜h6kÕ»qioºxÓY_ ËùÁÝ·˜¡XòÓ9áËf—²ÖÇ5aŽÖ O {dêûNÿsø…Y_Œ™| Šq>m40Ú„* žÀW÷Ôû’ãR•¹¡xSK!J¥ëÐæÔÔ´ 0¾¾ƒ.­c_8½QäHDœzèõSµÔ¬©2OµE²å£*¶q0ñ=ô `zé¾s6RÎg4:œ˜ ¿ qâ¿)q²F‡Ú7Äšð˜FòU 8w\ýt8ŒwK‡ƒ»¦ëÕ”4‘Êât¡ ½[ËsîÞ)blÞwÊö†™ðö)$÷cߌ-NÓ<ÏÌÛ^Ò|+²­æ¸Ú‡Õ¬ â—Ëb'Žmª¤LéºbVàÏ‹¹?/´†Þ”Gk°MRsÓRÁ¹ë™ù¢?/váµ±.•±ë€àÜ<áoD?ùÔB4vm·iƒÉøërÖBö\e΄õà«R#Ë×’ µ=Õ¼°àÜÆ,cžíÏë½SŸÛÇÇ© OñîT¥O±/Kmûï¿~ˆà iôùM‚„%r5ë 6 ­ª†f¦Ÿ/»ªŠ~]̽,ü¹_€c›¡_РER·6‰Àý躨ê~ýÁý ”&\`+P¿UÂWÜÑxœ³²Ïvº>ó_·ox±ùAMþX k†m’L…´×”¡ê‘‚²ÿe±Õ¾Ÿòer›ƒ5Ã;í! ðöu‘·Y–.u¢þiû^¸»ŸâvΊÛx,±Þ­ë1_©ÖZšD©’åØz0 d† Ûî‹Å(ÓíÍ@j–•§º󶘻ÞmÿpÌçœ_üøä8Œžú?T?SfŠÔ›’í‘ÅÐ^UÙ ]–ýöëQ~yiPãò1ªg0=¨j##Üwu9¯ãTíôøÓÖUñoß–ÉwÎ;ZðÞº`Y#†'À¢·l\<•Ký¡é¿v [t ªJÆýÛé¿ ™ÀËŠ]ˆ£llÆä™Ɩç¨.Ûö·ìÚ·kÁú›Þfli‘£RË<ŒyuYÛþÑ=7ÝÜ752ÆV³Ñ+ÒR éë/eSìžò_¿ë=¸:²|‰–$k²iÖµgÌ\Áƒª,¥²rœ²î×Ì4·«LþcI^ð¥ÆÈds‘­ªIè‡k_ͺú4o繄8Ûë°Oó:5µ¢Êw2o‰ò> Â¥¸¨X¹®w–l«´©0¬å¨™kVëÇih)GHIÓÿÜâÒM‹]­]¹M‰TEnp¡Ý ¨¦öƒÔñ?i,‘4ç,¨ÙÏc‡T ù‡ÆòE®q/Çv¼‹Ùj¸.ò¼¯‡B•Å·rÂ*{0{ežö „mß¾ºÀ¤[ó`*N3ÔZãzô¦2õ\*¤¬ð|šÉfmëM‡åŸ i´ôø‚¦Yžý&ïN$0ÉÖ¤(Œ=£cV›sÆØ35¨)×1‘žëO«13òuÍæ")lÉ£ô¹¬VQ}5—Ûhîì¿­F)§cÊŠîÔCŽOMAèÿˆÜáRªÃe­~[ÉwNز¥þüzMÙéM£;(P B´{4ôóLeÌËR‘eõ»mŠ2Iׯ*æÞMƒ™N+îGæVÄö¢_=nÝcS’Áíý4÷îÜÿtg¾˜F­ß’:·”cVT9ú80_#5©”'”ì£W@ÛØ7ßvLãkáb”²;º-¾±T£ôqû†*ÜQzKRI­¥Š;ª-Ò}7á?¬ LпŒãxٲ߫Í% 5í%ly±¾gw fM^ðR0xƒ4ƒ<¯ÏxÐK<èO¬ê A‚}h‡·0¼£t·.`ÕK>Àˆ C¡é ªÅD:/×?f=lf°š}ƒŠ¾ëÀ·Ìß´M_]Ó•bòãhgÐuÛh¦ uƒ8„ÏE?÷9Õ¡}»H™G+Ò—önìyzˆ´Êw¾ï×ã“Å23¨]PÁ˜”ÐJª$i¨Zé=Òõ²oü` `St1À!ëbû×ñM´½ÊÌ;{ö lŠ­¡Ñr¼ûev‚Lž~Aîëæº{²²1CžµyŸ¦Ý˜Åã.¯Œn½ÁQ?0?†Ó_t«1/}œ –ªÚ°îÄBÿPE·Wc§d=€ƒlÐ8‚›X+Aì*XÿØ¾ŽŠ¯¬šNŒüè îj®5”³ž'ùùîPBe5ày¥Hvß ªÏ/‘!ÀdçHèY¢{šiŒ*=öK#sf›q&`{a`Ù'–ãê\ø ¢JìXöI²ª£Ý'*\â)_h£¯²&mjN‡§ÒSmåÍuìûðÒa=¤Š‡!È8ìe¯Ò$鶉¥.i1›§DÎ}¥ðć8Xˆ»>¿1©ø2–:t%M·Ú̶. }¾ô˜÷Š6Ͷª,+¡K¶u¿ýü‡P’ïx/©³ÍñÈ)ÞqnÚÞªâEÍܘòõ—ÕLqiºóœ†ÁÛ"Œ‚BÛ¥IZ¬}ÕÏqž yfÍ»¡¡ˆ9y`¿†oJç§èDČՄŽy4*]RUýùd2B!Šøý)±Lb)T[µi> jiº¡Èé¶QæË„€©{°Ô;¸á›îæTñ_n‹ÍÉkoŠRå:Ë¢ªoâc1ø«„´ù|ãùÓ©7o>¶À’Io ~îá™4&ûPê”2iãÒMb S×¥ŒÍ‘¬× þ°ßîõÿ.8(À†Üò=cRWu"¾×Ùä‹»ôôûoûÚ jƒH’þ}-ÿMúÿ_0¥³V%¶t·ÝNjÍÅ/èóëk3†žUnL&:áéô¥.*JëE\|(Dеƒ1/è!gƒÕz5CÐ7ž‚ÕnÁg§VÚÁãH5ù²GhŠJX­jHŒM×äѰ½úÈ>?¾4šF9ÀkÚcãW½}6—ŠîIAíÁ’Ù§ØçÂòË\’Ä:Wio1HCê‚§«’Ã’(RÝ'n³X€Þ%4Ì-û ¡Ws©¯o.Õò‚¥E›Úø/TjVõHŸ3SÍ(~ý»ËmP;pîG¨³®x‡ïÞ1ã ïP(Á;lÝá§s @àô`Ë¿À17]EFŽÞÁÈqxJ9®Ú6*Êš‡Ê<^à+z£"Áð}xç‘<…ñ(ß•=Î;ý­øº-ªi*h¶V©‰‘]¶w¿Ý˜O3ÍYH°—/Ë"ëG“¥åm"*ëÁ¡o1!zBfm |櫆¨!ŠMÖùe¯žÛŸO1#‹³zžpÎm„jÓíØÅy\lY7s†B¯E奧 ‰‰¶‘õⓜÐiýWätwN·NËóaânc¸v¿û/"Î…¤‹äìa$ïYŽ3ü®gÉû–.š}†6‹hÿ¼Üýê¯ütòë2ï„ Öµ(ë-o§ª«¢DŽø˜3@çgƒõä$®Ü2?O-ò„`X­ªÚr.æœ2‚Øìæ– î‘£J’)ˆ,l­# ”\eb 5wºÿúxÁEL™’z–½f·V%’1"jÒ)m‹(«oSh Ùë’ª CòÜK½±®&¨kªÖ*JÅD·á—ÍÖªñlYf½3ñ Ì—´m`âe.¾‰Ò²ú8T˲i‹ã@µ7šBӜLj «„O q©Gºã‰¼*ge¯"÷— ¼ú¡ÃÁãØhœwVàÖµáð%T.0ªJ,+Æw©No48Íbs±`‚v;„™½·±°®.æ}±öåbZ5¢WW(›%± ®ƒ¼_pý…Öuúº>¿Ð•–’O—,™×28a¦ ßg ZÛ¯æj…h[ˆb²·SàbÁýÄ~C§«Âþ­Æ_ÝÒÙRí°×ÝvàØþ¾˜H\Ô¶7)ÌØª’_¶–K‡½*gÕôSGánJøä;·Ü>îwÜÕFäϾ½i†ü ÝÒB•lD»…¡‘”æßlÐ`Ï&~¹“wÍ÷ë70уu.JPѺǀ@ënØfØ»¤¢Ÿ—\ïÌå>‚;Û8Škû8VÐåă±€0rŒPñìѾ䩂ºAr8¼ÆÆüþÇuToÌV“ª¢šËD;*ï†n.ó(‹ËZÖµøéW¼;fÜx{»Ë0[D[RŠ»:{³¤o¢†eÉWº)FÀ¤õØX‡6ˆÞM™g¿¹ë !‰XVŠÛ*?¾îJ;G­U›MR…þ}1Ù,çÜ5Œ*fþÖh96lNß1>9Ÿ©flè:ëªmÛ¹ãXt4ņlÇ|Àº€Y¥Pþ~¯“{)“'ó|4i7c)+<«äW^ñ4ëãCGY*¾D<£Æ=Q×T4 ãUÕµ¤aP…µÛ˜ yÎ;9°}­E©£=l%†&R*!šÈ²ã°gb»ç‰e­ÿ¯_‰§=+ˆÔiÃ1Žì\&I]GëZ,ªVÑß•®ÏeZø¯LÌÉÀŽ îw:OÍÔæÚÅüï–Æ“±4¦µè<ÐYõ=ŽÍ‡ºý¥ x~~HEGq€“ú ±Uªº³£¸ÍcY ¢œ”à…Pp±þq•×[ÍÔ‘Cwµáwœ‡º\‹¡V[nÃky†ð] M2Ëìúwƒonß0[î¸a ¾³¨kfº¾– .Á¾Ùy™ô^X~ThO55ͬ氘ß>÷4T¸‚=ázÁ!…~5žQu ö¤ïOù²Ï ÝdPàø”»ŽͱîF•äИÅ·åëÛ4£ŠÊ7ˆÀÄ‹!0HiZ8z&Í"Q€Î»}X~è¼”f_ú:+Lç>DÇÇ¢jÄvTtÌ÷F^Y6)spÁüG?0hƒO²í+Zàã“¡4°Nd⎨'¶E1(Ue»ª X€É‰ÆA•Ù¢vÞü·N#ÅQâZ§\jì’Ðz¨cºÝ²Ü,²Þ=€v­éƒúo!…ÕéÙ*î*OÏi;ëÓkѧ7ŸöïËù—…ã¹e’—<ÚGÎCeÔ¶Ò]Ô7yûûZ+•obŒ\£ðaE•Òp €Ò“Ñ Æßã‘ÕPô”–*Åõšío™¤P·*Ÿ÷i¤@¢·™¥k~\Í¿¿f9ëüBÊCÛ£àïÉjm7niB©ú˜ìI‰éÔ/«Q`q¯9,jvÚ¾ôhÝT¤{–®ÄRí”âéx¥‰¾@èX—µ6‘øViŽÿÿ®Òb×îy²7C3Æc‡;ü·¯é‡WZ!†HÂç!R²icP¬s¿7¢=¢ûaùu=ëÂí`9±â²ÆÎ•^å®ó®2Êú—±1·ÍO‹¹W¢ÈÇ*ÍCå›ùfxÓ,E1•Q9¿îÛw¢Èç‡ÁÙÓž-Û—Ùú®vhk\ý¶Vp±ïX1à†db\ÃÛ¢å+ï9lS´Q4O³±(æò×}ÎU}|åÆ=¼dƒ¯ÇäE¿YºµÛFgažÿá7»æ6¬äÏa ÍZ¾î;ÚiЪ)õÓ“±Šs½LŦ$b¿€“éìTðï#]}TÏÆq´þÃV{}€ßIóIêÓàß¶™}ùý?øbf ¸Š®}ŽuÂ$%ŠÊf—Vë/ó¥TûødèKËâ ˆº:*Á}ÎûjRÉžµQûÛ9· uå8œ_Ï>èyA…—‘ôFÀUù¶l U ]´È ú§ß?ð¯°›í ¿$&ü s« 2fªòi[zµOÿ°ÿ/‰ô×¶}oìÀå³h&U]Bô£¨½íy­ã¹§Ëµ2G nòtSyï‹ /ÿ;  {”ttŒ*ÄíR ;&¼-X–y×€U¸Ò·nþÁG>´XÿþÚD7;JE+Œ+‘µYªiÍš^©$MÚ1ÏŽcÞœ»ÏîÝQw qN7ð|âj–æû]ó¹Ú·!ÞzŠoóº”÷^Ù„¯]÷~7µWj꤉ðãrÖ_íØLYAþÓ6߯tkFÚ8ëºÿúžÁý yKwõá(Á·7aÆ;PÜ[÷•òéaùu1ïjí¶²_µPêAöòÙÐý£]A÷¾]èÞö_—ó_þ{_h6¡‹(X’SøcWDð¹ª+ÖÿûóãÏÿ{~°ÿÞPìcBç²ìËë*nèT.ù6üú³ÚW9ž'ÓÚ‘¼gè`o×½øúUp;üÕ*Ìx ذ6QI¶ëV¶`ùi1H&ÿ=;࣌f¥ˆÝ ׈Õ\öi:R~,èÍ_ŽÊ1üØž2Šåq9ÔÓD Ý÷8êuâd/ÿá 8ÿÝ_v`YôsCÞÿé-ƒðÊïþµÎH}À'b½†îû€¯(ÆívÏÙ `ˆr½/Ñ©ÄÅz€ F/©c[Fu’PíU­þ‡ƒwåʉt"optîÅMÄ¡§tîAhÏ«i¬ÕOï{¯“(=é&1‚Ø$\aˆ @ŽZ[åmSE{Wüòˆ+¦poëãaüÅ”½=œIàGU|©Ê5Æ_п~x¤þ”˜·êÕz Oê²ÊŠí×Å‚7Ì ÈèÒ«ÌYc¤«Í 7ßöM-ô‹ê¸Le± ´ÚÂìÞÌfíÛE W Æ••àÞŽGŸ—kïÅÊU»k97‹²*ˆM‡¦Åã¿Ù¥¼RoV¹[¶è~_óÊö:å^À2ÇÐöè!ÃÃ{é?o–ôdâW VPw¢8«æ”NX§ãv¨©]iã¢ã³ N¿Oñj–¥HÓàÖ­eî¡Ê}Çhß¶Yài®åÃ~ó"€ ó3¡+nçlV]‰U„l·þÝSººåСÑŒ…ï#å-ŠÌ½7þ8ËEa‡êVÒVã\€*¥–œv[RlÒ>óR×*ûR¢k’pç}d§¯Ç!.›Pš6ŒRK²6‘Ùo_íÿŸ=ÔD3XÅ£ßÁ­€jßtAW›êâª+ºá石sÙ¼L?1–ôØÌøÀXÆSÅëØèßÞÓs¯Â¿€7Ó„­ò²Þ$7a«=O(¢×I·éñ·Ån§ùãOªNHJUu‚VÖ?ª:¹6Ê|ÝÐ OT®Åý¿‘,7Û‡ÎÈ͇Ç*Zz‡dù –Þ°1H D…¨«TVeZ5TrmªLTË t?¸9·—vô ÃðËU„Ú¾ «h’¼üªŽí„”é¨ëçMÊ`}~l‚ M*Ø·­I<÷ITé)›¢déÍzŽ…&ã `Çz ¦."ÛÊ]‘˜g5mA¹Q=ð€`@¬öªˆŠq_£µYä×sèý `ƒgûö å+Ü0¯;QCɳtóhφi‹Ìóáwó s»‚¦óÖÿù¡ò‹m0J®›Ã÷%ÏAó›>I{™:‚ˆZ®|Ü^Ôàë ó)¼Û³áËéÏ¥ßÛ®ë`^JÊŽY%÷˜9ÚWD=]âë7—ù)´‹*I}êz†)äB·Y²v‰¤”ؽÅR*W}1ø™û)§ŽRx#d´å:n›qqŽv~±­Ë úŠÊ« ôiMˆ–Ó™£ ì+>åPÃ4]ÔÓš^/A&ï}»Ìýµ]4 FãËõ@%¼ß1 °Ì=‚ë ‚ÈD 59üðœ"j mLÉ$¥E•Ɉü @i³„Þ‘¸ç†™D†—þõõÄLE ¤ßºÇ‘ö U˜]3TÛšõPÔ’Xæ;7ÐóC×ó\ÓŒNƒ )n¾ ¤ÅÅ •™¥Ÿ8'ײWC;ue™®?ìNi'º7Ç;(ÛÐeuÿ³±"‹ÌZTIøæöÍ3€«ð/#9¤/_Fk‚J`øáÓæ}òuÔz0#9—â,³naAk¦·öUdn=¬Ôs¬V·†$Ë b•”s’uylr] 'ÁýޱÃÍXž†÷«qÉsýܶƒ¦H/Ú#«ï;q¸£ŠuȪik«hH¨°)ñ¡˜\§ÙôÈs½M¨±±Z!çh¡ÊŠ»]õ¸ß»’’¥DçË )‰‘5d6Cùbc"¾ÚAÆ1fpÚs먊©Jöb›´ °j¬…§Z¾‰¬ÃÙëù0c%6Ç­€onå§$)’¤/«¤i£›5é¶€¶4l‰Â†ä½yú} ©ú…Em»¾ |££h˜çvœ¨4Ëôpx° Ûæå;0t®¥š. –ƒµ:x£ z‹ôº›¸ðÃz¾ý^Zÿ÷:]›¼þ§‡»_A!–¬`'àj§F[uPe?èn/Fó¢Ð4¢ÆRð/KæWŠ*R¬è•”K×ÔÜ+é)FkµCRÛ8©yQ¸T~ÀL÷×·½ºLÁRëE9zÇjëpBÝÊé€%ã&ì,S7dv¿ˆ 3ãù"uVºEÕaøˆ†¿2Êí)Up¬~[ë^KzÆå}ý‚¥H˜ÞMÑ®Se9 »žªÑ(ÿ¸ÜA™XEÔúkûd j–µ®„ùv¦a—e^XÙºOûx;¯Àè~ÛkS×'gqë¶±o+?p”€ú¹.Ý´-ôÎ㾬ë¾ýùç^´À¬Ã°®o²E«±ËúF9ðEF5á„pIv®B™gæÃô¢À>diKvaÉÓ=Q³§­ÊµÜSÞÍ£Ìßq e2¼¾õæÁ $ÑQ¬àb!$é2æ0í+fJC:Ñõõn!L·,ˆVû·›Ñv·Þ`—˜}"½–qB½V ò€·¤ÈêRá¸wÓS ß„•žpð‚ ‘A¹/gÖÀ†ït;ì’Q [.`¨~JZh»§^ù•w#6exaº˜P‘#5¦àK+k¢’$‡ç|5™ƒ»…»Y¨u63®#î<´©y)ÕîšÚÈ3¯ íøzˆÖ±˜DúÕ @3b%D/4XO ›Žc7à0„b Ø ÍïŒóȽ&`7æu®=ŽÅÞíbõÓªžw¥¤`dÁ^ÈÀkU,ÙØHR2—åÞç[ß(-Š?”#3[ؾöŒþ…lMψ‰Ö—±Î­„‚×*ó8»R­2ô#äö‚i=¤ÝCÐyÃ,‹—nLÐÔ è¨¢P[5™›:ÿ ÜrÊ»lÓÈß•f¾>¥frdzjÛÜ-eýûbWzfŒFð–ò UX“ˆÃì Õ5išqÜÔVëÑej;V†V›y½V¹P¬WÙŠèg§oÌÊ2ȱKŽ.Ëž¯u?dë¸vé•»Y¥¡d’k¬E‚àmúÀlðãœ"ƒ¯Ã£@daNYĺʻãçóC è2¡[Þ6Þ©/#›‰¿Å“óü¦ƒ›ÈÊ^ãXí±.“&ÏãIÓ¥H.?"•4p¡»Óå|$îE†~ýx¬Fô¼=¡+ÃyZ$ârˆÛ.Ïu,ˆ•¿/'·èÞ ã¾>'ˆ­a£ä‹*›&WËP6Rúž 48xÑÕw;õÝß,ŠEQ‰2WNس„©-išîk¢ËaÉ,ÄÀ~@cÎ}ö‹ Ì–‚_”gjuWÃ]ŒÁØ~Ž‘Øìô‡HH„{ÕEHšôÐsßI› ì "…™‡\ BÚ®±ÎpPäKø¸Rn®Âí~Ñ•v+}ˆ/¶‡4 تIà•†iϺ‰vÍôëz÷Ækÿ7³Úá÷Åî\]P_"VÔK¸ÊÔ±âžYwC=×ã R^h¿¸X ò-®wÝ烶òƒ)ü,|if¿<Ä„€”š‡6_ê\ä1|(S¢CqànHìwÿ»}VVÀ&#îq½›hÿ¦­¸,:´‹YàýÞr¼7œÐ¯ÓΪҘþáe‹t§è2FûÚÝt¬‡ü"4ÜXÇö®„ö/ö'ÆĦ*И’š©*fÊø9ÿ¿OEbú·»žk{¿{å´å@øb÷)½JQv¤ÛM·É®…ŽéÃ6Ѿö£ZólWüÇó)r†IŽB„‚7¯sP®Û—+=ò¬–\ J(­±<#èÞ®hÿÆËNv\ÀÚl óø˜ó^vö˲Ø€òX^ŸkzÌt;‘+k×½èÓAoù%sY1´à4âR¡ä‹_|‡·”­ˆ‡~ëE°¿4#*4#Pqx îãÒ͆÷ÛÝ$b—y¼Ï¨äÿ³Ÿ×-ÒUJÌ—m]7®‹FMQ>.ªè¡ =hmþÛ ,úIwæÕeÜhSšù`ÃÚÅ{É€©Öà7†lX(2ÒbºÎø¡òÁqÑy‚Ï…Q¨³^Œt¸ 5É 5ñ­ÖôOV=ïéšR: NZ‹ÁÝ¢’ûæØ"9ËXÔ7J¤1`½24ÒkAeÏÙL6Kµ‰‚8<Ôa©J×›íXb;ÝY~=?Œl¥† M/ªß\~Ís;¤{ª†Šî²  óXó†Þí%®r~y: ¼ÛŽŸ%ÄóuÉ÷"§»’’Sóªð’²ü›E»ŒÂx€?a4tFžÌÄ¢*)•îÅë Ü<_·:+¢8^'³žgÛÀ[…èU™ßqÞzl_6êf=çZƒþÆìv¾ÙÊrWzX›fîÅ 1°‚À‡£”Ïrhò|þ;ã~\2ƒ(˶ª:ãT¥«qÑQÛÎ#=ûÒËj!9 Ö*ŽgÝ~»óÚ$iñ$lú-ý:ô‹Ô0×éÞ¤•ª‡¥âÞ=eñÞͦ²ÐBƒÃþâ•÷eD/W9œyT¦e:ÍÒý `\v“Ê?ônýǯçC¸ãU £ }8>î:Ñzß ¯ÛdÌù¼¿E:îʈ2‹/—ÑÙB—]ù"ñ%o¶ê[{·n©h«¼KiÃÑy¥N†Wl~~= •‚Í;×eî?•²É{®­È+ÒÕuz@^çºÝk@×eOêNùžÄè«ÛƒRÜi˜ ÌÖ˜­©Ñ,éÀvw× O¦ûÿÆ?¢ZûŸùGh$;/@±Ç?sûJA fö§µ‚û5ŸaïÇÁ¤aŽ1œ“fWôùõùCü}1ïò`ÛSzð¨9~‰b•Õ1ëÚ©‹HÎ ƒÇ·BÇ­gVȽ$G ËŠÖƒPdkœ[^gÁÊ:Þ|Kµ–ÐÚQW äªô¤×AÚ e0tñÑOöðD\ŒO¹œ–fr+vš˜šÆSÙRñžÖ{6ˆLBàݽûÍv(B@2éŽB£þÅle,fö‡ƒ0ýq\ ­W[ $`-¨ (n›óèþóœ­:_׬îYÌ»A™‹N å.Hà\TCþ›!RÛÅ'€,,ú©–y½ëa1ßuXÞ5“J¦® ¬HZµ¨z¦ƒÐˆ¹R%}§CmÆ¢R`«Ñ^üxi/¶Üãa¹YÑ^¤Dxì—([d=/@SÇ0´Nñ{6s| ®ÄTS$MÊh*Óz¤Ò:•J0ðC¸$Ý©¶¤š¡„˽ØÌ®Û‡Ñ-!ôƒ©RyJ(ÂÌ:¶“¨ý›o0»o”$³•+Hñ@…WœÍy›ö(eºâFUSÌ¥'hLZοÈ„\_6Kçm\ö4ד»Í$Y§R}ô…ZÑæ@&E*¥©>ÅÓÐhsœÍí'ótÙí€7ÆTPº1ýØns?l˸N˾þ¹ïC¦²"UqLqWo]TeQ™÷¦ï-ChÃÒýé¹§YøEv2†Ag=ƒ:ð#T™ zŽ)Âã&šqAH?Ã.¯›ã:¾熇°Ý?XŽ_ˆîÜGú±)-ev°«¡šbJ t™.¥C( Hèç5E;Zdç¯ûƒ”‡ŠSX\j±]BÀ¡Å†nm׺¦¡e1*Šéwõ(Ú<ïÞþ¸¸­ˆƒ»­•G¡‹s%v[Qj©“(/6ú­Çß–s®fÀ ™é5œ^©{¦Ò&_Š^%Éçc>IæõÃrí¿Uì³80×€›'èÁ‡(¨¢%·®ÊÔ¯Ï/ývÉ€ŸªsV|Ç]Où?#gJ=ËØÅeß‚>…榉!ðƒP€îæETyÛ¾?¼X䢣Ï@Ä.¹f×K[Õ¨ð`üjQ†n{Ö yzµQc' #ºI_¶oyVúY?7q7UµôéÂcÎðwÕ»Eo ð<¾M^ãÿª[Sª)_ãz@%ÀpÏó.ÆŠÖËšµbê]ðÈŽë›ºŽ²œ Æ}ï“8‹íA+Š ÷[àÜÍØß¹]½²ÿÙ´X‹i±¤Æ9Œ­)ü”ÊaQËŒê÷ºŠ‹¾®–Zúm!%ÕôA¨Tº‡7(ç>74sKž¦óA[°cEJi÷6eÞ”zŸ“"m²šO¿—´;¤þs{â2B 䊶IÍ”–õ㢸ŬNgkž›§£<Pwñ6CQ÷šY±Uáã[ ‚€A£µ¤u“.i½äý°’)„®M—IÛ è†ÈÏç¾›É~ÊQŠˆÊµ‚×Ç ±8®¨ÞSyQÏ¥RÓbë‰rÔ‹;òô‚±ÚË¡ò„½,>}‹vZûŒr™vm—>)ÍšîCGo~ùRåø÷í%Ÿé)(²fq> úXŒuP©|òlï”¶².( |Õ€9Û’²?H!SöÜÌYL½¢#·”FE?¯Ç6ÆW5þç7=ÂÊ)0$¤ÚÑkYôe»f¯öVB ­$ïµٰÿì«“'p@ƒ{Cq'j¨\sª~dcTÎ[fVó°™1œsÅfÙ÷xå@ÅqžŠÎ’¶cŠà¢»ô›Þš…Þ¾d›@b ¾ ê4:rv-ÿjFò`¢,Ø¥ŒÓ¸Ã˜leë©„FøšJß(¤£Kµ0½'±÷“vx1ÒbÞŒ2g%?AšÒ{öi¯ÒY+Sðd”³Ý(àYîÙÑ~¥”_ë“¡‘ô`y”9##[|Ö¡ßꢋáAAZâq}<þ'e©R"ÞΡáÆÂ-Ü›`5VnáþSÛOã2Œë<ÏËÊÚ-¦H{ºë=÷~«Ñ¬O{™Ò%ÏE÷\>òÍ~kÔn’²²÷¼˜˜>Ä×o×®]2µã¸%‹4RÂÀEK ð\8 I›çîÛo.âô ¢Ä[û¶bËVذFe¶èuŒö"+3A¡¼Èò,ǹÈ8O¼®}#€ÅF[¼¹›NîôŒÂvš¦]æaº”y1·‘ø.€Kîpéh–43%뜩¾YÓ2i«q•Åhú0#§OÎ@ûÛ›Îêçjl»8œ–G8­$šRÓMe±-7Ê0ì›ñW îMø#±›ðA5¬‘•™ý&hù%·¬˜†½•ý븡 ‹bØÄù*é~¡ŸI=j éŒå×¢ %àg*ZŠ]EÓ0%M«Ìš^hÆTüùç´Ö»ÜŠŸæ¾Î1›1²#ô]㪉â¸k³Q§EÁ‹Qr0¨Ÿ¬@¬KÔcß‹§4Á˜ZONú‘ź¯KI‡VZÎ*G%Á ¼¶ÓõëjR›ç)õ2OŽL{š•jo(šÌ뼕»¼ª'š„âÀý~¶kÞ\}ÁËì·¬j×­Š[5l‰žò-ÙS^ͧâ‘p -ë~ÎW¯P¦ŸUÛ‹Šà<˜W¥Óàa¸ø³Ñ.²Ã7ýOVó2ÓÐ^ Â6—ièoûÔ”™Ê™ Ä–!qà’š¶5{¶¿Ê½Çç*˜Qd¥ˆšâùôHww¼Å»Rå2Êy… ÅwÐ*¼à5¿»Â _Ÿ+Dc¸Õ, ÛµJVºÌ†¹ Êê:³šG•']>÷%ßç´çÅecÉÄçÑrV¬¢7½Ùâ¦Qä¦eAè&ÀÄ…ŠŸ»o´ONLëá¢úqº¨Î47ÄE5ÏòqžJ£Ä3kºÕ¤wƨ0~×`I.Oå[j¡½‡¹*¡ý´ë²çµ/tíîÕ0Ok]řޣ²™Çf[ö9—[M^XÐÑýq7SuïÏap25Ú@ù!E!Ê#‚Q>ŸÔC?vòÅaæbÓåA%›ëz‡³ÆõG¥ d~T0Ýà]ÞµÂÁeª[Ûï:MÛ©•péìQÑfýúQ/Ì!À?źE%«ÃsÒÁÌ¡¼‡Öƒî‡-íeAh %¥c°uÿVöþ[æÆ¾™´#@ãÁ} Ïø¨½ySC¢ÆìKLT4 ·¢êÞÑq¶(L’…¹màÂ’ínŸ»¼Û¼}}<çl–ׯ»CaMUÓ×C¼uR’fA³…>0¥¾Ñ|å øMDÌP(¨j]CZF ”æ!Ù«.u³3uvˆ…6l'¼Cgôe¯ sêON°6»…±‹¦IÑ}YeðM4¢~Xl¥ó}ûãâÁù|lÆùUƒ`-± ‰µ©úÞ4ÏÖqüu±{øÆ¨§Èµ¡Ž¦ïš³ì®`ÿ’®Ï­©“íüd3뺌âܵÑüb®ëý…çe±Ü#ò3­!VLèEXoï—¶5ŽJgæpЖ³@ÄŬ5°‘³sÈÀ€Ù Iß̦1€Ù¶^†žÞr¦ƒ¼-ëþç&€Ù¾Z"ÝŽ*žÖF•uœ‹D¢û®öç´,ï0¸`nd¦ô ËÂ妾ns:Pè¨+qËÉRKÐtlË ^íÓ àîƒGì”$QÖQJ!Õ/åµj÷(9 …´šc£êÏA67#xœÿ%áZÄa0T§B‘(Ä”ïH¸Ž{y}lO Øí :&híBi¼‡ÛSI6Ûç9…²¿,GÙ8ÅíìnΑFÛ×6ñ?Ý£ãå½Ó¥ àLz[ùîÕG÷û±B+@ÁmÆpû¾¨}ZÖI·i¢I-ï÷ÀÅö÷Äsƒ3|µ\àBŽõ8eÈõÒé)ÅWôiË)Ó” R¡)û㇠ôˆÑï¿:´­2œþf85¬XÆ !¦˜Ö)ÆU:q•W™<:ˆs9>;NS‹'‚yÆZ‰˜hXÂ’ˆû­1©`ïjcdð3e4¡¹GOL_£&`á­Ú¦3±††")g¬9­ã”¥]²$³B`@ÛèayÖ{‚BøÈCJg¼å!I\SiÝå+ÛR¦[æ(µûPÌÅÀ=ÊöŸ›-À³Æ·àûÔ|y |K“tíö*ÝÓ:ŠöQ›_¼:›¾ ¤Énœëò¢_«‘„¼OÅ|zžÛQÂ¥öx_š>Ñ…ù°]Bt£CõÐdÎU̳O–aвÕ0ë8Ñß÷ž¾èN±pÍ×dŸ 9¶¥jûN7¤e ÷®ü¥3÷/ð±æ»RD *pîþ]n#öç~Y <7°¦Xâµd}Lq£ÀÔW´ûv5q®uGyïÒAðéÞ‘ÅÓÂZf"WpiÚ¬ ­;ŽÛ/‹Ý=ï¬zWþí  íÙ :}p¶£'ËŠtДUeíR }Ôþþdö»ÚæÇiÌÝhœ2–†ZŒšë½É·X'uV§£YLÂûTG1ßbcîFôÄgݾI£i  Ñâ„ ¬ËÕS 7PÜÛ:a°Ñ’>+wúh´†öI*¾„cqâej :c #Fôéë¸Úº…ž™Õѱž‡ÖKÜn–éºÎɦáDã`fÌL@ærq_ƒž°Úsé9Ëâvö¢0'Ã!"J9ª1-Wn÷+UŒ)@zDßÞWÎ*éâ¼Þã’›¥Ø«°õ Äb Pƒ¿x¹oÜ-•4R#J l„L£ŠtÌ0}—Ež2HŒÅ<ÊðoGýp! ÙÓKÜaé¥YÓ…s«¾‚£—nómÛãblÌGö|Ú%²àj| £á©%˜—ˆ¾7ü«J×CÓÏݼŒÓ¶N˶nÈ4ZµÅRR¤Þ©ÈS]=ÅòÍéÐQªa]ç¾ô²}ÿ‚Ðô€wð Š+x¦Á8ÏÉ ]Ô<Ó©¹7ÿ¾à=ôì¿h~Ó“fšk+.5ÑJõS;÷K•eSûËbÉ®vÓð•¤2–Æ$*6I£DCüÓ]:îm: !‹– ¡Ü3Šø¯ñï— oÝØG‹‡ I‡áú“%‹Âk>McV˜»=°m7¸ƒ¦y§dðœw_Ð P–ÈNÁ'‘}úQ4Q–ªt-Ú¼3?a:”ûYØ¡ˆ”õ.Ý…‡¸3Åb+ۃǧ¢¨Ê2§+/cþ xÐt¯ß¼ÐS#ß.ªEBn¨&âÅs‚û}›¢½c÷tZ ’\üdt±ßNK×ÇýzlÂÜ $†UØ;“–fÕ¢Ò­-Óri˜-€°å¸k‡wJ¶¼³wwŰ¡‰o@ï¯.¾€ÞM¿hj‘£ €ÎƒÄ¨eûÆxÂôñ/€teðRæ TwkؽVIÚM]›Ö¥dD˜ÉøTÊX€ÞÚ§fõñê÷C’4pŸ%×Ò3R´ð¶V[o»T˜”ÆÃzѾÙ.ÃKË;öŒÐ]Dµ,!h4Q'*Aæ jÆ7´)Þ@KÇðèpÔ¥zý¢ ôM%ld@ÄixÃr‡Òãû ”ÖkµÊt&@÷À¥œ"ÕÎ î—¬žùÀ«³ev¼>·USž°R&9÷…,F…ƒF‰†ÒÐrëê]óõ\9d%™ˆÀwLN‡4E^¥ÅPwc ƒ7Â8D®m'<ýNÌjŽú4ÒÍQ”Ò%§¡"Ñ7-XÆàG =+¥/SÞÒ…,;™®O†¨ ¦ÜÅ?íþ®€œe/'[*5rJT¹BB oáÅÜôÓXVë8O :uŨJ ‡{9ÍôË'³ù(Y O«é»±ý ï‡^¤0«1…gU—(å!6›|t&@ZZÖÒSJ!=¢‡Eâo~@º'mâQ¢`À»®»nÁÿbÿY½ì?iµ'ÃrL»N‰å‹^3ƒmi?³ç7ÏZè4M3©¬¦ˆcÙÏÞ ¦zÌsÅÄ=0:äö`ëZÍðïâ[è(U@7S´¬ñ2$udֳўu ÅwàY}ïJlZÁ¨ùüæá4 Û4f¸•®I¶kMWIQ˜a!H§ æØ÷ÛÑ,¿ˆ^|ÐæÃéÍé÷†Ò•ôª‡}ˆ•…<Í<¼ìÉ"˜ãÜ!¸K;tÍ2|'ôp1£dw•Zl>טrë½ö©ea\Z’sÜ`ú…Ý3ox†O)yh§9èÐ-cn¹lÝÕµ1}µ8ÙÄ–Ö£„T€åE‘jõ«“Ì'[RÃvrÉfàÿÆhŽÍbîíæa|£¸áH+Ú~S  .™CÁŽ>ø™ÂY$M÷¦+â6«úåXÌ¢t׆ñ¨íŸzÇ— éñ%7)+`jư‰äˆVõRÍ…RÃRg²–Eáú!D°de-÷ €ùobC/§Å¥3èCFÍ£kÀ>cÃýò ÖÑ ’Ý­qT°\Ku˜ÚI¯ÓÖurZè©B—£ƒŠìç÷W­c6X‡ S :…Nž§½«:Õ ÅÖ—Mÿ¼Øj?þ&4ð„ù–tøJAiÞ3Õ¯™U×Åq5Ž)oëÁˆ%*¢ázx—3ÓF\¡Ø¾ _)5ü`‚‰¬²y—.nªI’<›"ëì>´ß­•kžO4û2 bX •‰¥«Î,i'+ pOûÅðÜ‹,ÑÑëG‚W«·e••³Ó«öª/Ô=Õ t‹ÞïÆ—Þ7G‚ÿV¬NZŠU:ùA¡-J|3+snï­œÿbvÝŠÙu!o çK'„> bì!|&±záðvøÉsÜ¢„˜Ævì†Æš“ ‹fŽªm³dE`Bª¼è*ÜÎd#èJœ8Ŷ5ÕéI1ˆ«K– U×[EÛq_º­‹Í“B»’”©LGßu¯ê#è}™ì+ƒˆ-éXþÉõ<ªÉ³1Š&)^mZ îè¬?+åœâDÕˆÒMÆQJ1×¶ZЉZÕU—õõ0×ÍJç…/yŒ¥}4M)%öŒqÇÙèäöîÆÂ_€H@ã,dÊ@Žª*•OšNÖí­¬HÛåF»x ƒ”óoöÛ˜,E‘¾ÈŠº>Xoþ:ž£l›·.•} ” ÚÅPrrì—ÂÅ3ðóÓØç„݉¥‹ –½î¢8£<$Þ:Y C  V(.˜‚3¯˜6ʶ>ØF4OKW`Eµ6Ã:ͪ•Žöˆ9ƒÝ›ö C  ½7îëÈIò¹J›(Od5}# zÓaÓjH(µÓT ¤ý`–ôŠ«Î •§}¢³¼WòúøÂ¡¬ 6òi¸5‘le¬Ú©©ã¾MÚAƸuérVgðØ-§»0]ðŸ˜í=Y§=ç^6ø§¬rŸ&i½®M£†v†½ÝÌ[S¤¡¸OEE˜—IÂ… ö3‹ºz±¨+â¦B TÇØéØ~7÷RKPX€$5M[Öò¶kù%i´Åó6W´¥¹=AU¬ƒ“á°’å‚7± Ê ŽÎí ”Nó,ë û°Â£”rÍ7 %!ÕwÀ~Ò….O÷f_g3ŸL“üàÓ‹Ì•;¢4ŸÞªéÓ9߯‰rCù0*ò)´Òß7÷{{¹=#°W ¹AÈ-°¡ ƒ)wÝÆx˜ÔJ3sÞþ¶¤»½\Ö/ñ¬€K_©QŸ0¡®£H­°©ë¬Ý¦c1@Ý©b´BǸÍù÷7ë16,6ò0ÍêžóBhªöµŸë ZÊü‡Kk‚zï|3mØ™yÿ³;]NÒíuؤâÞ•kEï~1ÿ͵<ƒk¹^%,`bˆ:þîb y@®’÷Ÿß¦]4%²S¦ÀaG—Ý6Vô÷ZíŒÔv¨Ƶ ®·@¼û;Ò‡ ¨JdXá#ÀÜ#º“öVo£8¦䥩” èÔÙ"[ OšWÀz>6̬ÑWÄÈ¢a!À4Í>ƪ_·ªN¼û(5½9(ðŒ>Ä›Ã7é*@?¿^꣕hj‹úhÓ mÞÍbÆ`ŠšÔõ\۱ë*ôª9ÉBJ0Ìå&YR§SBÿD “å\ASüsnæô áyʪ7h+){×Äm…}nÈ:v"€€Ò?ô\ú¨¶ƒ!îÅãê[y²î¾Q{oy„‡zSÕÛ–$”Á¨y‹ÚHÖB®Ëè-_„(¦Ð¹š „³Š47-§+øV ‡i÷ªOÚ·ãT•qü¼ž8{\Ñ¢Ÿ_<žÉ*-ÞØã'ëzŒ(õ£]Ò¤išT¿­f¨8ÿ£œ‚´´~XåÎ1Ra¾óèÙ@…`Þk­ª–j@­söøi16¿_ÔážbÒÆ‡ŸnôÈèþAgª.šx‹bMYùÞýö5ë~ÁÇÆFð%CPdgTX°XÙÿöãQJþ.¶ôõ«”¦Ó.Ô¥Ù¶º[ºzï~y2˜%Ÿ´uÈdlŒ†þJsn6²/¥ä‰.‹)£¿oÛX:î?®I7¸ÿC'º†,¦.!á5¹«y3½ÿºXøÇuŠòߢæxDÍײ^k=7PA±K“ŽCÁÓÅ4”jh’êrD€_× mMsÍ~~ŸNS”4= ]‹ù0R0UÞÒfãoëþ5n²`Ÿp¢DýÄ–uì×hÖÛœEG,ùá¼z§ë*"Á‚C⟬j‡ˆìšGôI‡<^Êñ·aû§#ÈÊn¡¸mègkrD&05pÃì‰Ö«ÞõõºÞõïÇë}Êö± ,gT)Ås-\žJÑÃQɧÛxj§Øæ3¬ÒpÆãÛÈLtc3Õ‘ê[Ø–³Ç%âI”¥yÓíÉTu¿þˆ·« (;Q®€š¶LàFtZ§ôÒMÚ õEmVýÃþ»ê±~òëEÆš/<Ö‚üz¢Ë<ã©Oúß"òisnã£Ç—ã˜3ÈeѳÎ÷€®{­T¶vc¯¶ØÐ×Ñ÷´á6Ç Üd­´»Ô®âÉå¢ÿ´™Í³ý{jïjïn~;Ûî¾Íîa¾ÿ¢öÞ/*€ß˜2(3Œ¸Î(±ÙA•T”Œ¢?y¬é@îFw®R§ð—1wÛ$—G>,I#ZéKÓf‹“­ØšMˆ*.ˆQ'¬»k„æ C~í1­Ï¯£ÇT·e×T\‹×¦|š¿j ZÐΚڪ4UÍDñ¥¤òoüu±wW­/nYK‹™Á¢•gÙ\d«j’n3·%¼©rv¸>0£…«ÞúçÆÀ n:0ïF3”[ Ä법ÆhÖ ]7„oO`Ah½Ñ¸ \ ÞÚGD¢„ñ¬K5WrMB, Ú1°™g1­åª‰sßuÉýj6XâÁÛÜME×ÈôM&©È‚–³Û2°#àÍ/Ö¿ÏŸ =×ù“ëØ.í1®/ ±”çOÿïvyQ.¢|hžú¹–ÙÉe*-’džᇣй?~[LÁ¯+ÒB@–®ƒ‘d·¡„y?‘Ö̉ž²9@ÎÒ†åO‹ei1&TçU•šÌZ~ÈÖD>­Bã2hûz"®E–ç`¹±ºÎaX½4i6M™¼¨{ƒÞÕfè1ØfÐæ_­êàú!GžvmEõp+°*J}"MÙFr¶é8ûyÁ)´­?ì7ÐÇCî Œjº"š£föfÈÛ"Ž—.3˹6¤ä`–nd4Ä„ë~^ÝDÒÝ-H¥¢Õˆb`¨æ¦UIÖmTr·¿­†nÏý•@øí““¶\”:ÒÆ¶Xõº¬ƒžû™nî_ŸÎû4ö!(}Ä#àt0Ò¤û0Šé„,ë´üþªW_úß°’cø½µ€Å¢TUEªZ);+ä»z7ŠD7÷{‡¤Nè¼ÚZ¿}<¹vÇÙ¢jQœZ–¿Eda­u+„8ˆÁÉ 0Á›xÄе#ø¬—•Øã°¯*¼26Ÿ:_fP›ÛˆvŠð5]ÈÃ}°^Ó¦@+à:.x>xxÊXï ïAVrz±4B&tc…ôú‡z•ŠÆ”?ÆàrNš`‚7E±–ižOr/øLÆ`¨qsœsë¼+ À´¤{æzâV¥K=é"Ž(”ÊofPèCh§º?äÚNý=éª< õñ°@ˆ¸§Ò*KgY óÜ0 Ãï‡ßù‹as£¬•²ì0~¤GK¶nÛÔ”õ}¶Ñ§Û4€Gcyh¯È޳^¬ü6n&º`¸hH©Õª¶Iæ6‹”©cYí-HÛ˜0zâ–$x§¬ 5 ØÂàv‡5½çÄSìÐÿム6¬‘|X·«ZÒ´F(Ú$•°xo¹™äËs¬·³Ê©Hœlˆ‹P ²u؇¡Ÿ›z»ì÷Å.¥ÎÇú4 £,¥ëATÓÙL~™—nΩÎ)TÓGÇqýûzéâŸ÷ouÙ¿Qn²8A,ÓöQ!6H‚ëTy“Ćޖj¿X¸QUB×t×–õº§r ²r‡ñE#Óµ8ºÉk¶õû`¯AîdÃ;ìõ4—kzÌ0]ˆKÝàé@AÉèGRÒ~úÁÛª' !…ULâé³VB Û!ÛјÊ=DáÚsÍ„>Ò›]Ý*¬ïîæF“ŠÓ¬ß‹fž ²šÅX%Òq=ïf…§Ù%,=Öû@kïZ(˜ÙÎe>Òú1Ec¬GŸ@:ý”èȤ Ø¥+2ëãs£;G0ä¹Ü< èÐßmÆ~_«zÏ£M°´`èßC é7Z0ÎÛ}}HM µ¯²aP°@ªUº7Û¶Pö» ¿®æÞý?.—ÄúýÁ`Z)ˆ—¼T A5å´YÆ>ÒÛ8¶æuaº†‡E9Žföeº>6˜h1¦‡ä•€ùzv¦ï“ºÏÕ¤uªõÏëáTÜ®ëaçFù&=!cläÒ™émÇjŽÆ´Hd5Ú÷ö‰…¹osF6‚R]¡¢ hqßÇ9ÓY\5óL%m&kY&2˜’1Q+ þ"ºþø2Ae^=2ˆ"@&=ÏTÞ§k;”³€“¼;fÀ‡¥¢É9šÙ‡f¿ˆ“ ü^h묇'ƒág%z4ñ8—±Þ Yѽ….$¿-ÛvýSÙüì@ÿKÅz>eóp8`c ‚+äëòkš*p’•þ3§u£ÊfH—.Êè_²ôh=Lñn/^Jð6Zx~ŸX,Šï¥d×=*†f‹¶¨U©ÒTÖ£ÛÐeÃÀfX‡õ~m/>Ïö"kÂCþ 7íÅfŸ‡.·x•DÑ£¯ÉzPTÔyF]€êe½çƲ\Zd®éux[?Äé0hÕæSÖa¶¿ýºžõ††åcÀ³á~œ'¡Œg£bl' úÕ0ÏFÐ<øOÊàš± wÂ*Åaïü'“˜4D BÒAs„JJÑÆP!¨V†É, ï( º5€ÙÓÛ9ʃ½є鉧Áž¦yZ×¢L‡R–DW‹ò2צ¿µÎ2û¢„÷dßS™^`â3·„‰ã¢/ë€ëÓð±ÜvU’#WZ 0Hú ¼Šƒ çò/U7ôA¿¤àƒöue¡(øâ•Â_QE]¾‹ùTÂÓµv‡øáI°.žsŸFç¹-TIÅTçü¹Ûnm—Z£ó‹Y£Me”u?³oðVªX>,‚p?Àˆ`}B©å ·s^ϵpQÞ u˜Û©[uù´ÏO¨Þ åß– ¦åÓ®³ª‡zž¨Žl„ŒrûFa߃ÿ¬ñš íKCzýFDËA³…iÏf¦å+tq”ªÓ¾ iˆÃÝÙ»Z‡F Ô=t8¦O‘8ûF“G$G‹ Ž’R±´œJ XÍ¢ZÊ0ó]Zdž6ƒ‡KΠØWq[BžŸÒKÖ`ÒP>´cOиïå>¶UµÔtiíóÜT«¬Šzâ¶.’­Áýš)±¸[4°×2@þÊ@çq¡TZgÑ.$í÷Å®:gìÇH™9„×™2sÏ¡r Ê,çÜ(GïÔuÍÜÖ>ÄzÄ>ˆT$eðï…³28Õ|ÜÚ½è J›)ó-J“¡a Ÿ`ÏÞŸo]¿L$U»@°uºGÜbµÂ~̵Zigêq3Ås!LA/ yÌcR}U+\ŸfæeÙrn8éÓDÅ~Bkgk6ÈÆ5Ýté$vz“_ù>ÐÑC¨s”=Ͼúî Q¶Ð†TÝofÓüm=¶‰¿*é|x†]äþr‚g˜÷YÇc^ÅÝ’H|fvžbhßܳ¤|q›(:z…UiF6¡ÏK©L7ê"jè§¹ ñ|ŽëÕ•¶_ÅÑŠpÊ-¥’G#ZP}¢è“ïݨɶæ«pæá› -+ª“8G|†³å7Ó³EaH–þ§ƒ'Ž‘]Õ}Eëºçæ{PQC…‡ã£y;~¿«aé—±©ÊÙý®ÔÒåÆ £ïU•eY«÷Xlª~XÎXÏ»W@Ü? ¶ÌÛbt’ ðFñÀïq5çCÔ2(W¢iÇ:!õš­ñBéÕ”ò®Pkf°4Õ,S2¼)©~~¯†f”¦Z“Cgs4ƒÒ¸’‘ÍÏ‹Ý.êϬS†¯aà„5 û¶½)Ì«ª(¶!É·=ZãZ ÉX‹Ô9äàj¤cä#^kˆÕ·=›B8’ éJSzÛ‹Ÿ×ã*äêyAy_NÝÚæ@¯ÍË¢c]ôuÖ™g³‘§Qud9†œôÚ›ÓõÇ&xº-Q®vÜTf§kµÕe¾Ntlf1ïF ,¯sjë éÈ]}Z¬ÖmA~Uˆz«¹M)ªj•›¤€ÎÊ@‘iÜZNÿ°ß4þ›AL¼›×ôÇ…ø!ÐV/ƒ˜—6Íú`Ü€h–}Õ³@8>ƒ¦Ô´,7•Ïà ™™ßÖóí·x ¨2ç¡…Ô¢{^ÁƒŒ’Ç¡Ì˘Š£aôãóy¯õ¸›ùñ!f^Òla‘ ükÏõ°KGë^¬£ä!ÂÅ’üÇɾ±ÿ´¯L Ì/(¤Ð?ü*Ýà25ã”êÃüzbÈW3N´e×»}—i_#mžm€Ñ)NÀ‰»žîç·´Ðé§câ/pÔ j#¿ݪqo½3$ºpÖÍr@à åv´|÷v…8RVÿ`íœ]—š³îÉ'[Ù÷)eÍC¶/”BV² ZËæàíŸlØøÁJ™°±\¶J¥ ÃpÓ¾œÈSŽ27ƒ½Ä|]ÚÎÇUÚüë©Íx™Ú`-ø˜["ç©'õÒ2”¬ Òv@qÀl Õ†ªzЫ^×:ªf¹È°–í9èLCzèè|]dóF.øúP„3vÅ4NcÒP6JÑ%b=ë€ÉƒÀüRJaÄ`b¿ˆëcÛDà5Ê€êîêKhfT{›ì»Š£)Цµ (ßòn.}WÀé#rú¯·>7> ¦Aà4±ûmÇ”XµÒo9lñ·TöÊzpG´àÖæ7ë`ˆ__ø¿XArÑÂw"•+”&»wZaŽ{Rn.ò|â'CQÁ<£cʆ'h Ý­¹¦ (‚¨¬Œ) wûÕ º_î빉ˆ2Ü!í$«,+ZxÖfk+GŒ·}ç¾êFï~)\žÏ/†ý²:³‰»Sò¹ÝšFM”dUg`ì›ç²ëÑ!'õŸ«½ÇóëÓH™1ýI3wØ®"ÕE’m-••·”íPJ (ö]2 ºrY€//$‰(ÛêRä­»ijÓ•BÂ4dkš¬œàÁk°ó[xw¿Ò–ñ.e@ìfD;¹«¹^n%z–zN¶x7®e=ûv§“OäÕÞ÷¬—+d,<¶L /¦®7‚1ûÖ1(=Fc'3jŠî`@QaEk€Pð.ùñ§ˆû#?FwP Áöû¡ñ¡o2:mòó9.Õ* "†–ÑÉeé±ËÁ€Xçq0ÀPnMû†F¹R<ð¦aøy=Q;_ÔÁoÓ0ôZ ¤Èèh5÷{·lPI–hLÔl¼¶cF`W„(«zsUÏ8âº5¬ýe^¢fC_ ¼@J3ý/–ýÔ”¯¨´B4)“’r¨hÊ3iý´ž¼C¹¾D50…ò] üeͳ~Ú2…NÕ@¹^D…‹ŒÔ~Zϱ®caXÓ?¥ŸÆAX–0¥¸Ê¾ˆ£>î²=ùý}ïW(ÒÇó/®‚  2¥*Ö­.•?”¾ÛP)  Í>zT–t ¾àB¥{ShøC7BÊÈÛM©ZRÊj{©÷~\.øãÅø‚ ¯±+Ž/®!n¢mEÞe¤æ´Œ6£I+úÚ°˜Cƒçò\ëÚQÂx˜ã_]&¨I¾×I’4‘R”,˜‹Îqw|Qǧ$iü_64E—ÝkcÉ Ú†-E° ÉéÖ-¦Jå[4ÔIõÛšwÏ»hŸ¼x<¦B€Ó  œ¥ˆá%‘ÓSËé@hA(†¡NxdÖU*çñ}ÏK yð5—rÕ£C±ËÙÀV±é·ØüÂ@±_ˆø¯ï"žv²<š°­Î;mú¸ èR0€ .…Àdòš¾åŒå¾N}SDQ7ËÍ^lœèêõø‘ Ã6FÝhj~p[¬n´¥ÄÇ~*ûuJ ºØú²ËLÅztõÚÞ O À›' »Jp5ÊÖALÞé ¹-§°Ÿª¬ˆòºP’ËS)f íd( Úf’`]äÐè q]òíx<­‰Þ”¨SkÜpù>dq¼êIPSuÜ|ÍGœkD褑‰}! „þ…µ6ØÓá00\ª®£Üo?¤àºŒBlë»wÚ“½92ƒa`äêPb@†`±öY©NoE¤‹áxÈоa6aÁ¢Ì:I_W¹úc]½l£aÌžœ 'æÛAµ ßåþ… ½ ‹á‡åà®té&–äžíe.¥øú”ê9 ¾0{=ª~V%eÍ:Û²Õ,æGey”’î_z^†? «8xÚ7f~§«~YÖmÔÕBËJãúïë þäÕ¢P5´Nµ0[€Qj uÚôû0Wñçñ”ÿÃÃ]^ô_Édë_Ld²_ÕäÇ×ÊþóˆlÀz>=\ÓtÓeˆ»¹ƒŽ²,hѽFY }ÕÐ>]Lß0¶,;Ë#òz°M:lf:½{6iÀFÌz îº÷Рž˜cù‚Ú1êãC”ŠZ“sªÒR¯Q¾÷¥ ÕNHI9\w‰ ëMØç±I¼?À‡Ã„€¢j¬×BR]Ú·ð¹…wÍu¯Ízù´ (K "Í2DnºlåWÓtÊA ±¥„-nº¨h_†hY²°£Qµn· ÄX®s?¡ÿqÿŠ„”¾§¹õÑ^ç4­1YŒEÐç‡Õðzç¯Ï—O›BKiÄñTiÈì}·ëZ²Ê´¯ö‡(qT0NÐE¶E /œ–½Ú—±]§¥®^.#ïÒÛüz®ÆÃõ—óh𮲵N÷\—ǯçR6éÝ¡V“ñ¿¸Yaºa§ÌdÙÙr¥ä™¢Þ¸ª.•ãëÁ>Ï…8/@B!tÎ$ÙP‘JT°ó¹ E EsßtŸYY–¹Úb‹AaªMUâHõv¼rC‘q`¾PBòÙb;É8H;6Ô*K3±O7…M»ä9…ÃF•[™Ä[aÖ ˜*M7;¥§Á‰’¼ >™| e03cJÁ™ÞƒX­7J éWÞÛa4ëQ v1r¢“œ3cûâ²ÊúW¬¾ÓPâÑéc Ó/”{U{R¯£ ô[2-J¢ž¤mð2¶O>âóƒ«i6F@Þ¬y+v1Û¾ÚÓE5åm1†¥oÍ'"cnßß@ƒ”ÅHë9ÕÚ4Øe¾ïݘRE˜ Ý-¹Düòz>Õ3ô5L†ñÄKˆ!aðx²ä “‡ÙÚŠªþgG‹˜OH÷¤ÞA8 =‘›° >Ú:¡txVe^q¯©mXØ‘vM¶¶EM¡o$P:ZªKÿ Û¶NÇ¢ wãßÚùñ ‡Ð·©~áWw½§«¸Þ-ÈêÌ™Ž%'zF!6ë:Ž”†¨¬§c9ªéjÐ}–ð3óòËezRq犩%3Å쨭ÔX¢¼Cù#*֛Þˆ§/÷]Eg¤²Ð(†ÕS#³l*a¦–ñ=]+•¤²á=YˆØeŸ•Ì¥““‡À²PVÛ1!„gžCÑ/sµéZuBhœÞÀÊóè HÏeÔΞæµ¥X73‡÷Gb=Õè«ËUêÞІ@é⥤&aÃýq™,~@ˆUGŠ5LLS¢=¯)ÖLY6m²žÝkß}X»çmn½ª^n[!!Oó´•ìu/:aË0Iš¨‘rÕªÊÄHÅ¡ ÝNߺh0\„žÿ ¿Ä…áÍ ‡8Àö ®¦¹ppÁ1ý&ÎÅádÌùi ºO•«yÔ[Og^Ž L¡)ºå¬Ð³ þ£jZ°4S¼6Œ¬ô Ú5¥h°L±ˆþ¾ ²\ÌÆXY÷yÁ¸\NÂ^¿ª’Šº—×BF•¡s§lÒotH<#¤î[WÓuñAã³!Fh|Ÿs¶aœÐâ¥éc½H(p ½YÖ€ªàÛéÌq ¶.S7ºþ:u†ö§©-JÕ–ÍZžfòÎS·Ëå¹aÔóõˆYM•íÍ1(ÃŽfL>j™¦|Ê!idIzÝ€/7Ï=°ºöuò¹}2ªB‚` ÂÖáiÙ6÷{³öiWûñŒB\Å$Ù±}—s ù0Ø>™$–R–•3Ý%šÊrk³qØ‹1ŽsQ¡’KECO¦{xFèK»dû<¤¨®Ë´æVÚ÷ýB{°.4”îµ2 ú˜©¢+d{ÖQ¿yj³ÂÐa.V3{8—TXÇíÅÕD+¯è¢¶¦`CûqºÎKjªÅqs¾¥¹­È’È·Y…º ”åñ<Ôƒ S󹘓Ûm¤Á¿7h£±:Q0MŽ]ÓnÑÒ«tt¼å¹ÙŠžÌ£{kÞ_Ò×{ä_X¾Gä¨ðó0HbJ‘jºˆãcÁУì͆x›+÷pÆ[á­™ÊÖ5e¶àøxNT5 *4ô0C¦K“²LÛ˜`ÜíS–VîLFº ÊóU–ca 4R)é¯TÔ*ÔÜÙ(í`FBº‡Ôw[÷OÖχÔmŠàÕ2‡YK®³¢Ÿ)™®f™ÿ†>ü¦€Ü@AwpEÝWvþï VÒÔf²Ø,¸â Y×qN:æuôÆ~ºçèÍØé^Go![HØ”l„`žž£·k‹ˆÑ¹®Álˆ5ƒ¸Æ„ùÔHWó¦[ϱßt@ÙšBz“èØ5”½ƒëu[Å­ªVµ§Id´hŸ`^ öÙ«é~b¶€Çûf¿ùX%àQÕ|Ô…C¥xØjØ]î•hhÍ0ôo +ÝŒ6}h¹oªYjà/¹†a[ýøñDPœU“Ö‘žé«R¥R HvS{ÁÎàø||rŒ9å”Öm/°2zݸíºF–nÏ$€¨HŸr÷®¡S¼i©®°1RU]4Ðéj#UPâ ç5dÌËJ6L öë´<ÉŠè}Ã+R˜ÊOýª2Ó)ÁUÖÂU6úïaHµ4F4ØÏŽázºþ›1κ}±Þ=N\UÁ8é¶ç Á¡ÚönÝÒ*3kÒL'Ù²hïNEptá®Cj¡ÑQ&éÄ w2©.[¨V_§2•)ôïÁÖÈçl˜ÿ ¶me¥+”!à-PE—å­n¦e‡iÿs[·eÞžÏçÇG1T;FheLi­öu£Íf2ç1¤ŒÈBç î°OˆñÊ}Ño!"w„‚$±3•9y¬vÈiJ(j³žÇM$ÊÙmƒXoomÖ/ŒÖë]*¾4z*Ý1šÖªQj¨Gº¦eÔDKúûçÀ5†1Þ›èÛŠÁæ)p ¬Í¡p;@ávQìBitÜ!eàþ)qû“?VÁ?â4¦eÝ0´âˆöTû j¨&ëX¦ÄP™† ¸ÅÈåc*t¿fÛP“ýš†%›” MG'‰šëdM’%k+óhF…t‚îHïNÁŠ‹OÁÊxüoHîCO¸u°žÔQ“¬ª­*¤XÖ‰V£r÷üè¯HùŸ×•õíô0âIh~ g4úé’Y£¾Þ™ÎõãjŽ{ŒIŒB4¸&‰(àEÓ¶‡æ~ÑMk‘FY>ícö,‰ÌÓƒ€.Ô÷Ï;Ú{[aÙlÚ"²¢¼®oê¡•îüÚI=äѺíÕ4š/B§Òƒºìíæ›âö~ëþâR½y 0‚«¡‹/·»á3§àÀjÆ>͸ùÝÊÕEQWé©¥pÖÍ6d·@Bºo¸¢é>¤ÞÜÐnx…A­öfuŒÁ1aeöF5é0[\OuÿÓ‚'Nóù¥÷/ÆÝ¤º.¡6Ú3 mh‹a¡d5ö…ôŸÖ{{¾¯ãù nâ (ñ|T[ Û6Nqßqb÷û Ÿåã‚{/Á}圻AíΚ:K{ˆwió Rˆ¤{ZŠÖ‰ü>ÍÈVc B˜`C7à1¿¤k¡Ÿ7Yܤi’”óâ°âÁÝ o)ÏØ*L^xæ”iûbØ!+Ƴ@Má–î?ŠU`uÑ]±,ª¦ŠjGº$µY×E:•FË´éCÛ¿Zñ°f+‹yQ9q’ÚXTõÓ:öɶÒ+™„ÚÎ>Ý<:z¢Âº,¾uá>~`|½ø]õC>®cYgÍ0ÆÝÓoËy·?.ÊÂçb°GÕ•ìMÁV‡yÅð„Ò:[Ù¬þ§µ¹€*V”\[À(ŒN¯¦j-Éd×i®+t ¦½Ú7-ÛТ҂Ý=œ›º€}°i«ô/IÝ‹Úèžð9úAÙ4q—Õ3žM¾Nœ¶ßµ<Ö»Ì×6„òB>¥ z"ÜžÚšZélŠRB%w@’1 ÿ&P7ÛvÞÒE6d0sÃc82²,´ÎË=טÒâeÙÌBU ÐZh†máûoëáÛ~²´FX”ËVgj·¦]“&õRQÉg.:;„â¨ïº·»å™àýØÒ0ØC1úE53gÜœF@{D¤^çözë¶AIK±L]•oMYoÅrj("XC’r4ÛÝ«÷5 ÿ§÷µ–ò´;½¯s^ÑÉ~„ž$Ïwßñlã#yó­Ë̸ZCˆ)Í3]!n¥¹RUNá·Û›º3ëÁ@(¤ºôzÖ5V›|oº?1tÓ<‘¦Õ( ™vUëÖ§ÂÜÛ  ø FåAðþ½·êCÅŠý-¥]ZĽ¢‡Í7*îÅ+ ˆ_̪Ô<ƒm íðÍ߬6¹ 0ZÐÕɱ¦P½uÙº®sQÉ—$Bw;8©AÖŸ•ýŠ*÷[”̘_سݰQ2‹áNÒ¯TxèJ6¸g3öׂëÜ¡æÝvÚtž¾/–Ï‘ãbWƒj|<à@^e™| ] ãjÓù1ôIü¤Ñ‹ªÁ‹F_î‘Y˃ÀztÁývR1ÞZºÞÚÍQ»74È<‰“¡Vm;¤}"rxºUnhZx莙üõÖëê{n Û5¤pˆ÷ýF—'™}{Îësþùg±Wm’ª¨We•c<êzЇ¸>~^JÙ¾£¦ChãD8°X![Ç|',Ì{ òÇ–PÕÇó”íy¥Ìýï~†î'RòÃ\åÊ5z<áÉγ̂µqÍ ¤ ýØôj¤Ô;2‘íï‹Yl#yé<8]TÆ;E.-™¥ïy2%PÚ«¶ê·Õ >géR 9à¬5ÏF¹V(‡j(x üÃztlÞ$…¹õoÚ’‘b­ˆfÎÐtUÒSC)è/‹±sÃˈ…vã“áCw¯ (Ìž«{©éDm5ÅUTu¿-æ_µuxžòÁäE ~UË:}"â6ek¶¹Z¢n«¶aúí—s ›ç”6ƒ‹‰°¶jyÊÀêÉs}ú¨©2¹ ½ÐÂÜ 2èŽ}¶^hì Ñ©ã=]æ;T0šùåùºY¤ÊdîjýYûçŽíë™B€µ .*íXÏl,c“±Jj_Q …°^½ª¡ú.Ï"™ù`M–d€ø4§Þ¥î°GÑÂïS×qÓ]W7ª­×JN¸w۲ЀùE,â~ÔÒ_O\ÂþC…í)”5”²oe°Ë6¯®¢–,aßõ6oUþ{—ÑÑú¶¤ýùO“í½på+†<) }Æ4IGŒ&gðýÆv5‹¡md‡ðJ3a2 ¯£4èo< ܦ¢ G7§à[3CG²Ú)LVçr4íà-Ce¨y½òyú%ho"·HYGã\ÀÔšjüq^óyTÕšïãïëÝß“â2X®Ô y@¦g´œ.UMѶ «ùñ@ã ‹îJÆÛÅußå• ÛüxÙ¥²Q/ƒ•Ø-5Îv„f1Jã¦?ìÔjºúk|ÈÒŽ Z•ÎK35ª+×¥Ùe-*H]${°—ô»’ÿÝ 3›M‚a«íÐCÕ³að sâÐ{@ñ¬2˜›–‡ƒC×{¾ÖÓíªOk[C\Ñ!mj ±Sí¢Pþ —2¯®Òø6­ë îzU³$ISçòl´s)A¾;Tà»Gc;¸Îƒ?0ûæN å\ƒf/àL X²J ¥Ž'úkª[/8Un&®À¡±.Ϋ¢ï ¡M?Žýˆ²^õSMUŸ©©(’H.'´ƒ`úáÓ¾ñ.&"\»hzãºJZ€1ïÃ66+Yp[xB‡¶ÊÍŒåÐn»¤°Oˆü›ºâÆ€ 1e/s z«¸gv(;šRFÌY±oO7ïì½3C´sÛ†x“÷Z»v^æae8‡š:›é«Næ&Úµ²[ýð샵Üñn‡ªäåœV†A fxÇSž×ËÎ9í¸µù¯kÝÿ¸šuBÆÌC†æ "[¤€¹ß ¹dÓÁ£/nÂ-Ý8æÙXã!HiyìGêˆýÓ.CO®eZPlì]ºRÙV•«¦”D'm*‹0¹¿è-4”;úoª,ÈEL-`Pó©~!µÚâMçõZç ûE°œó”ÈÌzÇøþ?êÉÂx|€Ü»ì{–peÀêÞäë˜,mÞVé*ëYì·iƒºFßóØ«Éë7Dz5ë}ÖÀ²Z"oWs‡Œ}^VÍN´œ¼ÁlóíC±ëî_d5׸£ E­Ùu“Îaaµ·åªŽ¢Rvuƒä]ÖøÐö(.¤@„‘ýsY%nyÓö£Úõs,ëÑdžáš&Þ ²u ÿð>a>A‚˜èpË‚ScÑïeN×k;˜ZõN{màel“J„ök´Ëóâ/1Ï‹yîW£)Û² òÞ®}TÔLëÇ}%é÷£Ú×ÉÍdcÖ•ü)Šg¸+Q¯äiwÚïTM+ÊÖÕ,›Û¢ÔÉÂ\’ýÑÊ…¢IuÐSüÂJ”¦šÙ²¸Ÿ²]¥Å÷]ܲ\Öò€ÍÀâ3:‡àX/5̯š%"‰]²kG/‰b[l9§ÝœK#Í«;PE¨Z|Αg·øu |}²¡2ûSÑ«VÕ‘Åæ±žË<îÖ(Š{‰`ô*#)vÛ¡HDòÔʺT}b+ð_®Ü 3É¡y$Y÷jVã”!ÕÓ’/PTPÔ{GFðÌ ÞÝ^`¿)𑚪çºg^›Ö$eÑ«nŠZƒ5B%ýÕµ}QŠj”MOq¯YŒžÏƒ‚e²Ýcvè­ßßß§Q××蜶éCÔÅÓ”÷èºÿ¼â ³¥¿`U?¬j^f<(cU›…Îݨ!h÷Ûj7ûÂÞÁ…ò)È¥œýÇ4<š™©+Èžó]]ìERÿÓz—!ˆéüÆÒ¹©tO¹UÇýö}GÂ:®óÖ· Õâ£ìAcz>œ}霘‹ôM YE„ã!A:¸š”ÃÕuÑùØ ­òR$½Qaa3ÙFö¡í†o“: _¯Ïe í›ÏRGcÖSôk ƒ PúÅÍóÏ]s…Ð#Šï=ÏîÅÙ„Á>Ý›~êÕ^¬ƒœPbà¡¶ñ”:¸¤§0óóãÐ-5º×ÀsJå½–uŸì„ÚªQ¢>,½éw¤¶§‘ùÿRzãœHZ N†˜%SAßgÝwºax5ÒU.œª,?0«]y¸BžÆ¹U|ÉK1KuhÕF_Y]VuªÛÌzäy(ò¶1Ö{9üÎè(rKh38Ó¬(q‰Ð瘦qÙŽêeUŽ[5W}]§&ÂËÓi‰»•'ôíÕ$‡uÓʺ,¥¯RÔ­0–(Sù Ú‘ŽcšÇ“Y- kØfrßÈ.Xoí ªæ˜OÅrLRäV]dü ‹ö·ÕnW}q0¤Ÿ¢ƒ\&ÎøPý­½ÆUÔë¢ÿy5n\ì5™á&cäë@åÌy›ªäèlŒÇ±“·o"¸š®}òá…,üÁÙ°1&l°[:¡SÁ˜`¦¬ÝãcwYãg—Î:ºîAŒ|1Œ(_§ôŸ.õ,…#òÓÓÑž¡8¡òhˆÆµÖætI×úã3#ösÕ^’ü’Ÿ£Û¢f9Ò€ëÐ Ù˜Uq>fò]!¨á`ŒÔ‚æ†/• Na>’a¡ÙŒÏP‹—„V° ­i·yñ J"oðÒ†‰í—æ¾¹Ò‘¦³ráwï”M°ã¡+ÕWÑ«J•Zw‰YÌ¡ƒë€†{—ZDZ÷¨Pˆ}1Çðao¹À0·ê–4Ù³¨“.u”$p3Á:¤¿DÍ[ nëöñü±$Ë*öºbypñ5ŸŠ}§8ÚecYÒ6+`mOפ€wñ¿cÏ# OÇ9ß ÉSc'ëAªÂTÅŒR‚ý&¾Â ´ttÙÔ•Á¿¢0왚·ªËôÜC,6HȽkp·-óy-÷*\Á9 Â¥Y[B¨2ª¨;UKq™Õû¸PÒ!ºô¼ @#ôq©þ”àzöu†Î˜FŠ¥À2œèííë^n{ÝÔC¤#ŽQÀ@ùîÛ- MT¹vX‘q”yÁL*ÍšD ùÇi2/jŠÆ‰ù1(9)"Ñõˆ€ïH/Ý´Š,s¦’¬©X… […ò!*²û}Кªã…µ®e=ËÅMI'XNèÒ‰Zÿø|~¢6J“¯J ‹Ñf£ÿRj‹2ÊÆ»Xƒ´*@<(º$ây¶uE ü ÄW½1Á«a§X”ßzâiÈAàJøü—Þ%L¥¢õ(€z”êR¹î›Á/{—\ú¿VéÁÓQ*TÕ’ê҇اm ÍRçÓ°´i‡ùÎeŽÐ 0­n÷ÚÇz<Ÿ“¤"mˆÑ”¬ÛŒc©§©’jÙ6|Ê™½Ã>ÏŽ2•ÓççÇÊö® —Wy ¼úØäò}ß6Œë©0„’U©4¥“æ3íØ1³F÷MwŽUª9- ¯QµF„€ŽZ«(”sžo«ûÒ7ŸbÊ UJôñÈ+¦ôÃh-gtG°3nÓÉKõ“.T<®Ç&³_þ¶œè{_üq·C#Ëë¶*Iköp«kU mœÐ×SWÑï Þß(Ötç>O5èò±BÞ×6kÛgc;ÅÑÀÖŸ?-HwÓ‘öÍ22x2JUVd±Ìq`yÕišX×¼o–ŽÂt¶ŽU7HþyÝðÍøùëkû0U!,ÎØ”;#ÄùwŽC¥Íj®}‡™-U¬ž‘Ivî/@òÝ¡x %®¿ù6¬{íJ-{'—#WªBåôú£ˆ×³æÕFôöê‚õùãI1ðÍsö ê%I(îoušt9Åý:¯ä&´F9Êú<ë…ý¿Xv~¯†8oúRwbº„^jÖš¾DÕÅ«<8¯ kÚT †rkÒ=u™Ø|‰”ã±—]ß‹%°  qI2åq½Èါ‡"e¸æ"Ápíš=@cL‹‹3{c©•RR-c“-Óªù ¡¹7ªSév·oçÛ^•v¾¾?¸Ýr Síå¬)5Ó9‹5°|›Ù(!´(áÀMåHP½ ׆]ê×”ÕÐ6ЇIaÑ•I1 6ÁåÀœ¶Üàn9ö)”õŸ«—%x‘ßâeIwHu_4d6²UÍÆ)o±S¥)Á ´!hŒ½âß$²{å+ýÛa¬|zÁ!’|pL_ÃØ+GzáÚÐE>·?œ‰æ2ŠË%Ó%]Í‚>ºv`Àû¡1n÷oWK§íãÃtd3 Sø\˜ŽìXîQ«ãTïj­ÌëRFî²Æ>¥õþ+ñ¸(»(l>8\3ãKvùD‹¶MÏZþ&TàSú Œ£u1‰ƒl?8¾”ç•dÐ<h°óušÖ9oö9Ö‘¤F6|vC½OÛ2ö½Žÿ®Ìd-ª$ËÝršyÅš™ªÖªŽÍ‚9æ£Iy Xxþý„¼|0ùÉ ²(Ê4ˆŸà4÷WIíÞ/m4ÌQ6…¨Ž†0xô+ @9ñï›æû±~æSÜ ƒ1_ã CºŒn€17ëÝ-›…«a.;çŠg‚óÁ—PÌuQšÔ²•<¦ŒèßCÞÅYT,J–³àS®3OÁà‹ª‹ôeò…4.LSW=Å´²Úã-÷„ç¶íA*Ôu\*i ÜìÈ|ÅM#›xŒˆE8—­Ûá~Ä2Ù÷sUÒ|±àuïyt„/Ò+ nÛ÷§Ødà8rœžÆ»”O”´u“LÏl)(cÊøMFäZoÄ_Æ%«Á¨6Q•«‘zŽãjÛÓ$d5ÖƒÞ²‡ÐúšFþË+d-ªëB‹AÉg¯Ë:¯—ï+Õ"°¶@e“ ˆ‡k›>o–8’¶hVJ®åû:Tôâë¢Æ4!Õ·ßô äê•^'ê.¤Ge3ï”wz³h5Ç—Ê}Š tcÒÅä»'s¹b1?ÍzyYj3k–õ²¤¡SQ±Y.,=ˆ¬ Ù kÚ–éï†×‚úþ +¥ƒqXµFi±n‹"/út‹¾e¼˜{óÀâÃX‡•ZcBæÂ¬e šæ ¤ƒ$ÄŒ!i¼«A25Ôø´Õš$W_2O‡*&RâˆèR•+l[ÂL‘v×ô˜Jk½F]&p[Ûå)3”>ï·[x–ÂWXÒ0O¤àÒµiMo7ŽcUÏm”«-“ö t%䀂q_öl€¶ @À‰I \“4o~Z‡qšÇ–’ûÇÇŸ>ј-ÆbiË-¡:1‡­ÎRäm—·Ó/Ð( ¼¯ÇóS(o8Ù¬EÁ’¬:«E©V¦‹¨,ý°¦Uö›B鬜æêƒ*W+ðw‘Æn2°¦‡¨²ÄÏ Z×ñ#Â8[³@AÝŠûM1ýÔ¶9U¢U5•EõÛÛÎËñãó±~<Äiº*Œ}©y¨ËªCùçºýíe1Y»?ŸüÍÑR¥ˆƒ).SÞê¶§Ì7í÷œþ÷z¬}Qû5ô¢”K<ÈúÚhò  €=4쳚Ó5‰ÔZG,²ûó7õßÚmÂPÈ*»-«O‹ÉüEqKY"åü¯_ ¾ð>Øûé.p½:%Ü0 3 ÉQÝǽȆfOçikóxМõáCD×’N˜¯ØN‚q¼©¡æÃÕ’¡ëT›|št©s`èRG.ƒÎ–Q®¼[ö›«¬z„¨;1Rª­Úq3M®b/¤Ø é&ö|C¤}Y˜>æ±1±ÌÒ‡=@u›æfšúaÙæe_ÿüóÏRP{[«lÂn²=ï€1¿ªR'ö)?ºW˜“_¢ÒUäÒAb¦ßuƒIùžR=–ŠJCtÉXh5Ð};uƒ®iØéâ’· | Ö‹ÅB¾/*/h/•y·Joû•³·?†o`Ìî_öÑÇÃè@B¬…3&²D¬GKQ¼Hç"šÖ6þm=ë…TÀÓ}Êãee(Yó‰sHOj¾TKÑEäe©ˆbßøV„ýÚµWTóèµ[U9í?/È›+S꺃ņ÷}ÃŽ<”:PƤ² :ë.:?¬^iatçm ÓŒ#Ã9ï(Šn-!µ_Ô}$å -G'Ù£Ï ËTãR÷W_>̶·Ð@zké1n-É“‰¢ =iªÌ"³é¨>¶[Š˜IÙÝ«måce¥hq¤gبSÑ,k!ЖlÑWJ oؽÝX˜‰õMoœêÒ«cËcÑ÷…¬8%ìµPH!->'M’ô es™Y RÑ–ï1˜Ë‘O7¸ªh~0YV¿Ü›zvoê_ž³E·ñÖë bÓµrxy;ޛλ´Ð"…›†Kþ&ãZ$e\tϬñ(ë9Œr‚ñgh|$Â×ÐÚ°‚cMûØAuh·k2îQI)qbž®;,ã óåAÓð…Øà¦XYŽ©«ydCöƒSCWYTYÔv² ëÃoéŠkx{‘ê/Ht:¨Èböâ@VSµì2 ˆJÓ4tL­TT”"®‚+Ã¥ˆdM?¸µ!}²p ‹)Ž-~ÙóN—ÍuqÝ׉yÀ€ömzÄÐDkVy¸–¡ß0!z~§‹RÚö½)CóQ/QIÅh™V…8H‡ìãèÚÌ×÷¼ÃDÂûãr!_”7Š®À©6Ê?×Ù8RÐѲØî½ß¶{€€MøgÚß Ÿ"·7¥Æ…<ÂÐh˜&Ö‹¶XÖy‰6KæY«bê8/t›ÒÇa –ƒnvz¯"Zi4BúC#„û!Q tÅ"!²ï6ì=lÇ÷éó„Çæ~+—y*¿%®¢^6åw®G•ezì¥GàRÕD);­Ð¸DzÕÊ'íÇC¥FS˜.k®lùèµý¢Ê!*¦8Z(9æå,ªÝ1Yu!/#øöÛ;ï]€lütuËÄcØšàá†<†E3&Üú¡ÜØØ,€v„Ö×¥ü|r{wk&ž'îU5M©¦¸HçúçµÌb_œÿ¾Á'1žòƈšÍ`òq¶=W`òõ÷Õ®Ö«&#AbúVB‚È!Ò)ÔýHeDñËkâ6ºš ˜\² ºÌ¥ÑTOTÝPúÐF“¦ëͬeÃóîvµ¢u¹}žYG µ`^P?ô Lm”Ðg©Æ²VQþóŠâÂqiØ>¾žÏ£a[•9?Ð;Õ^¨nÜóŠêúÝl8~s”«Ò^ ‚Ã<̺¢OqÉYãÏeLòd<Ë´—ÕR—²Ì&oŽí¹ðù9M/AgÈrâvàã,°‚ ‹Û5ªž×˜r *á%¬Àéž &ù¹1i¼‹Ô×'£™VF‘®ï47>Xj›W¥¦mÊÚvˆëÀ0ƒÇ”!ìÁqÊ­²—(ã+$1‡†+7ö1ÿÄÌd¨²¡ëº¢ê¥2+ÒÁLš‚•amÑM÷-΃P” —s5®Ö¸™š¥ˆ§n\ã,Ò¿-é½+}c?£ÐuÝkY…¾§C_¶L£µ“-HgŸ½T¹fÁ+¥‚•Ò>žß‡)Ê)v˜¢äj¢ d[)F~Zïö®:-¸qî8bä 8ÌoPޤûÚ ºË·yœ¦ß„Rï^ å ã‡By Mäúg¶×iž¯{e»Š¥ùa5›n¼K¦ûùÅÀÒîgUÌlqes‘Q¤Jº¨–ÃAwù Õ"¾ˆËÊþ…jÂQ] kyÕ4èv³Ä%hi™,…*Ò*J·jXd=ª41©‚ö­ÁcáRØ@òiÆ8ôÆÀ+æ"©×H5uQ¯Cݘ/½`]\P|úÉ^ZÅuñøþ”™~ŠÒ«kƦŸ‡~¤kr†:e´¤]Ô-k;Ä[“6&p¹8{!¸Q¾m:pºìë/fZIŸ?/EzºòÛ¶UõÔízk”6 =×£ktµàX;å¤÷:T£÷þ-¨‚ÇjÍ‘æSW eÚ¤õ^9Twè;{7ý²CÅàey¸QJô5Á2½ÀN2”a–!Êš¹è»¥Xf9s>0fTp?úû9Ò¦ic0kä³[ÛŠâoD§‹)ñ¨c³g|Àä=ëÖ›4äíÛͺ8ºÓ¥f× Q4CF æz_u\ªŠ$ópn€ž ¾ñÍñßCæéXã [öhkƒ”¯ë9×Û¨Š.¸j2«y”ŸT‘IÚæx\¸qòÉ*Y‘ç,þ òY[>,{µMí¼˜T2çàfãt@”îEßx¿c¢vµ¸ý»lCÐß§ì×ÃÜàëmõ‚òl¦áü`»axäÒ—üo”r_1Ga5µTR¶j¬ë’ª¸T»`L[ôaB8L›¦*fj§v÷‡û¢í½,L­˜T'*·E5¡ _tŽ+ðeM›•z¸ }‡å:G|~ýÿ9û³-בcKü½¨A̬~X‹ñ ŽpÌsòëÛ¶™S'¤¼R¦Tª*? ànnÃ@¬C>ç(½h+Òg¦5+ØùQ¼ßኚÓus¬ˆù.úÈ¡I¨|u®ö=<ÄÓ¤È9]Õ§§É*^Ëmª}W² ¥Ýt`_xtÆÜ·[¨³S…™Pkpý•Vý°7Ûç;ÅÇBVrGTðÞYO¿“_¨½K[Z‹jF±ši(¶–~6„ ¾{®ÕÑûº×»øK¬ªÅŽs;‡]Óªx Ü&1§„Â)¥1´¬|ï]:|XU™j‰ÉŽ“U›D·$-j¨õäkdžÏµ¼ðÎ"Á‰s?°Þ_GÛòUÈUÛS½SQxèc]Mm,óÃÿ\s%ÿÃ;ˆ»Æ?QZ뢥DôdžŠïc6'Y>—ºÏ÷üËÃ}ÎìY …û85ÐÀ×B9Çéx,ædé~{:L_¯Ú TZ›¦l)ÐÐ’ë$jEÑZ0u*º%YdI´)-ÈÎ’í»§^)ð±b7 êèWÓÐLKßTç-ó¼ntöŠ}×5«ˆSüšá±£…G «}¿‡ -tÀ—kþik%Á¥fU0”Ÿ(Ɔ}Ñ%#co$2=ˆ&h í¬«óÔ×Èð•õQ87´±Æ¹·^~¿wã)'@\¡uŠ–]Õ¿©îä€XàÔ‡6E1A#¸U”®ei„ T@:ÒU`YáI·˜DéõbŠk1µ=À —O[~Þ“}ZéóCÄÀ,Øð.s0ûå#Ý‚Ò÷ׇo=gÖ¸Mñ‹y/ „™¶”ÇB,†¦oh.ÿ~™LþWÙ·á};9ÖÒ¹y'=â²+ÒÁ¨[ÌÄâe‚Å_ò±’]é*†6…~.82yÝ3Q7„[13Í2HÇBÛW §s½S]·ý¶6«„:+wŸ#ôýDw9c)è6C|,QÄh±*¦rUK¼ý”ÆM=Èïô)ñ‘]Bp@ªKÄÏü>dl_½ÛÇ|˜wÚ‡:3½¶›Y϶aeE•Xýõæ,CÐݵåuÙ–ôlt :Ú.Üã†é<¥ãPGm!P&™–¦…}—wx¶á™‹I{…Uì¹-MQ¬†©Y¦yéG –®Qº©â6Éö}hº©Òé›Å§£wàâþ;'ˆoåŠÆoèÞÕ0.c‡!Ö½K‹|¥\=í—&2³jàqåÉûä‚öâ„ 1ÃCÅ¥â¶UPµ(ûN(£e"Uk0§êmªQ<º{o¸ƒoÌùmcq1œ½¶ì ï°»žß>ÕóNO¼·Ó®Z=¢Â›­è117F‰ô«ï×øõ…Ò[<€ËÌxÙôæ’É×U¥e7íC7«Y~5„&i«–rŽõ¯¬Ôó„æÀ£B’+ÖuM’dm²vÎD ÆÇ‰¡ðåão£fZ,פîK8hU À#“Ëñ"§uPñÕhWïf=`š`>xÓút'yk¯|‰èð‰eÙqˆuÆöÀï9q$×ìXÌAOÉÅ!4H$÷ÿýØŒ‚C ÚÄW@](ëDÃHo”Å WiÓRh¬ ëýÓF=tJÛ9Aï–=é¥9š«zß6Ý©LC™s/ŠÒˆ„8zá¡~m[îGÌÜѤ×(, Tãµ×۴Ѫçܬ†ð@5*e÷üµ—ëdý>JøšÊmÍ ,N#–&ß¶ªˆ(¶²Ö»Ó!¡£ìÒ±Þ(ƒ7×]‚½> `.¯¦ðZ*ÌéŠ~ ;Y`í¾u‡©=ÂZ6§ÆUÙöK¦#̳îÙaåšvT’LÛuZÃü0¸9H„ýÛ÷üÎ3) ~‰â¬Úš@È ì±/á¯Ç­ù¡~x»9lvg›ëýö¦,CØî‹¥”³4+ÑS63ñ¹QeÛfJmm<”Çb¼)¾zôqƒs6÷žŸýÑ•r«÷BæTþß}ÇÂ7€Î)ºr U, QpS¬ê™nðÉe¹5CÚõ”6›YÏ¥·g{Ð2)ˆÀ»N¼ÄàßýMõáPiìM÷r™š* ø›´¸Vx³OÞ̵°š±:˜.xé~1îC“!ʳI(G”šS :îft?í)|³Búª= êvFû_ÝNeqŸ7òtT-Ü`KD?T,Z¨Þ¼}ÄNÔÄ‚u`wÊ–í)ßž²*ZÒM^MW&ˆ÷÷íbƒ=·¯Æç—ŒT–‚ŽÓtÆî²öN©®*Æ)kÒZâ €ö )ؘ5‡o%×û»ÿbk”"ƒ_71*¹:Ì ÜJMkI/Q¦Ì ÞßQãÀ8Tæ|,™y6ŽV¨§ñ/¦ü¼©Xž¹c îRÑ#®Y¶êM%uµ›õ¼{èR5wql¼¡'¾è Ù©,e<641jéá>´îóÔís¯Ôü経â5´?xÖ—§pnK£1>t}MÙžaFˆŠ«°¯)@aYY§k+«T­YŠT€v0Çc&F}–©©Í¦±iþ¼ÕJnćd'*¼Ð ¡Ÿ˜²¾déë=Ï×Qÿò`,qqâa ^Ÿkþ²ÀïÔ=d<‘S´¾@MïÉÖÉ›¯Àª‘’]+´O¿_÷ƒ™(òôOgáÇ |ŒîöÖ¦Škɳ˜nH%Ð}Ö£6Zð!ÚçR¨_Õ—iEéuàÓRÞ\2/ƒ½¡)ê%õeñRd¿.fØÔÒ.þfbqÆIEÍAÜ]픕ÒÙXºuÈ3sÐÜ;üñÀ!}£ÜÛUi`ÝØÛ8N0Fg¬“(Š)›((R@ŠÖÊ,‚<  n$–Û<\*ŽQ¯E]q%h,ø¢ÎiJdL)µÒ -è»òúà~tLn®Ù.+°Íxº&ÓŒ…o‰ÞfPSLæÕyŽKQÖ¡á1æj<Ï7LB!« ‡š u˜ŽækÕ'eÙÄT„ÈÏõÛ½ÑáaRv;º‹î•.r´µÙÚ­oAЂÏÞe¿ïu_­Z& ˜‚`Êà§à¦Ðq®dÆ'Û"½„pÍÐú­M¯[ ½#¥Åè?×ZïÞ͹¨¿€gðÇ%#» änA\'‰ª—duÚ®… —iÁy±oáJ“—žÉ,ôÜþq‘güUFÚuU~3åÛj•Zsyq”‹U:Õãm÷~¿>1ÖóàƒËhVhmP+˜ëz£“2hîó‚h°%ª^ñÁ޹¢>Wö"‘‘‚'ä,ÍÍM·¥'èÓŽk4ÈzhÐP*€hÁ©ÅhPc€ô0¢¥Eºyà2t”€–y´êzQj/ºÚ¤ ,Û=žŒ„,IAô4Ûy PŠ‹ }îé˜Ĩ*Y¦,+†aK?à¹Þ½r×èºÎÕlLjҲÿkp:Ûê­¢ì§5èñ½d´Ílú!|Z `* n×Ê⩟ƒßM (Lû Ä.BFôxy¬1 ŠdAz8Û¤ëÍtñí+(óõd•.ö£ÂIcÔÊòbj©>ÙªûTè1Ö7oϵ)Ñ3b2 ÷CºÄeÔð K#ØÇ®™*þ1ÞKUR§\ÖB@)ÿŽkï§é¡pÄô°ÓC9.ô\ˆéá>Uf9ÐbØžî0¸ á1§Ã8–æòl@5uü)†´‰÷E k“G²,$oß¡yÉ”æ÷Fê·³*dB e„Kë8lë’4Í8fû8£uÅ«Z`îCž âþ;›ºL1¿b®ä˜ÿô G+Mï.ŸÖ9ÛóBF˜TP½åk¸·ZFï-`°Ä‘ ~£`_ׯeYÇ~­3½e©€ò‹y|Ô\S‹Þ=÷}B˜¹wèñò*ZÕ MŠ2KK Xl£G•}?pêx:ùÊ/îp½,60 ÓvÓõD6ný°þ5/ó¾þµÿ ±Z–v«:íSW.Tõ¶™?¤KPéÒ»Ÿ—û•—÷¿t«‹N#–ÃxÀ‚§in°Nã»Úz!í}Õ©šmšn®!ÞRl]3F”£;çϼ?¼ ¢>á¹*ØhH4CYèvÝûyОéi`{ÏVÄ•p²ý2ê£OßD>†i¡áÚ-ö jÕ£ƒª;ªôåö ¨˜qÙã"„ÆÇñæÞ?ô{{q/:¡>2{íj½çºÝç,Ët›‹¸Ç®PëíÝ&ÔRi=瘄°3ªŒ¬7ˆ)µÌæ«ÚT)Xh¾{žeêq;t/x´×ŽøOÁ‰Â€ªw`udÊ<öBA¿»Ê§È, À±ž,ÃÞÔð7ÊŠt.Ç&*Eu‰ê7Ê+$T™¾ÇÊ<8yð\ç 2ô¬ K1 ~—µ¬gºæò52SZÒ¦ ƒB þãt¤–QÌ_â¶þпyŽ`ü¿è"ûyYél-äx÷‚=0u‘«ŽçBÇm3%ã”Ix ( ¸®å;6 Üç4Ê»P²¶§™ÓÇa¹‘UËÚÅFJ±²?/&£úK¾13ãᔕbƒÑg)Ú¡toP$çÿ¸žwÁʽè&ùÜc?[زBø‘oWõ” ˤê²6]Åß~ì¥sǼaN±ê’iÈèqŠUS¼Ú»îÏÑö_~íG³íÇXu±Äõ™ŠPÑFœâ.î:U ÜäkÁÆãšÿß-7ÚÓrã¿’-2Þj¼'Ò vÈÈÙ¡6Ntt–‚*â¡êq­’Rý¶¤íxŸà÷p÷Ä@PW©eÚVO–uJààòßžñì? …ûÛà™™eΪ£»æ´Q¿§ý¶ôë¶)á;(°)Iðï>E†Àœã!ÅÇ÷ÉûåÉ}è\bÈ Ê² ÒW5=åeq»{t|±=0E€Ý”UƒûVô%”±NmëÕ‰mUVÓž.“¦.rѽ `·îRx¾ù¨îdji{¯Sôz87Ârt¹Ón¦ôˆ[åx¢ßûtjÛlÉ*Rôt$|X5ßîo‘ïÃ>U|r™u ( ^b*i“ZÁÛUõq»í²$Ýs ù6Dñþ‘£Ý m0¥,¦d‚rÄ¡¢~å4¿^_O#ˆ¢™_×Ì»ã5ýà"ïºhn¢Z|P‚зn ×Û¸äìw ý›œ»¢¨iÁ!‹›3ÜÝÖqˆ×]Ü´ZàûhѲhË)šs ~›ÁÓ^Æ4£•R¯´[êºTSlæ§ðåò} *Á¡fqEý;Ë4–(Où^ûmƺœón­“f.ó1‡Œ?®vRĵxA” ñ½‘¡*ål£šû”jÂyßE¡û?ͽ‹¤â“ç âO ô6Xþ­`¦-ÏTýS ‘ο=\pu{ùUЭúƒ Ûž.xOTþÆM¥‘ ûÓ#º÷àÂ6f~ÈÓ(ÿU2“f< ”ÿ¨Èn·¹®6ýÛb¬üw?=oEÝæ'IËÏz0ÎÄ–T„¡1äƒJ~Û(8n@à?•@àŸŸîãþx=‘C®~»ÖpaËÜé…n·AdT›Cç‹¢†Ü–sÎó®ê›xmBû¾Š,­´ó¹Üû|ë£^Ýx¬çºthÁ¶+ë[ø×€½x»UÙ5  zÖÍUIÔ¶Ð.jdÞ@å ìˆr®à ¶z÷‹°Ô«_¢8(/­Ñ‚׬ÛÜ Y'i>(+7‡ c§ÚKè\©·H£ö^²t[ÕŠÞÕž—MÓ MÜÆ1}Y‹ªz:*[é’³Ìí‚°`l9Ó0ol€ÁeëM–BÒkYÐ/ÏÖbï1¤ œƒ$C‹.K*­]ïÐ;kôÖÀC˜ý9lˆëŠ›¾Âfëç„îâzΫj:žÛ:hú^àžéïÇÌûuØ”Ðá`}9:¿KŸà³ ã8É'¦ôž"1í™&A'¤Ä¹Þ”Ü]ÄPbýŒm¢]Ó3J…Nnœµ[Õ&ÃZïfIˆëÓ7âZ$ym¦ø_h߯§@Ä/C³F+ºj_éµÎíyóѲƒ;ñŽÜà~z°ïýÓÀƒëý$«ù@‘ºTkó~bA죩ú½šF­Ñ8„**íÄ ž÷Ó¸-­;„·¿è E:fÉØ­C¥m3ºYRQ)dõx¨ÚCÉÉ` ½¿³ ho> C¦âŽžq£: ×û–MåbDK Ã ì„{ß;ó®Ëø€âìóè-`Pß0–î©UÅ%ýþjZsÓ…t}8ó@î%4Ã+{š%‡°%…š%Lª‚°O½7ùë¤ÎêTž9‚.ܦ \„}Þ”/6¾ÿ†[M^u0d¡múèj¨úA畦Ri4ìwø$9P: ßv/Ãù±"1òÂMÀÂ<Å.«±éFJÒçeØf˜¤²ÄHO)¬^éæÉšrêû©i’îø3\¥žŸØûù}.ÆlŠ˜Æðƒn‡‚{£VjK²8‹’EJæ]×½ïn…‡ßàýÊ\ÿþ‚ó™ùœÅè1‰ç¯c[ìu•Éü ÓXz§Á äìSEíjÈ)„#Ì’>OE‘™õ8—ˆoYdÓ´F“Yϳm Œ5ªì‘óÑ»ýÆ Aà-EI97¨D×hZ§¬.:•¤Ã¾Éz™¦Ç¼ÙÆâ~·®…À׎«G ’nÄ¡CÓ‘Ó‰jφzŸ¶j‹¢¨™:YÕÆ°œœ ,ÞY¼X€ŒäZœQuÕtÇ´S7Mœ¥4yBiTí{¾·ƒª¤‰ˆ-}߇|x€¶¬«±ÆÆ -&%²êHeÄš÷\7û’Ä[×Ç«°/Cz‡ br|œ^O&5#.ª¾…‰$m ;˜H:SË\Б\aI §Ò¿CÀìº×î'éÿhÀµfä’…’²ø›u{òwUp 7y¤PJ›¥¬X–®¬i¢Ô{²<Ý0‡IÆòoe¿·Ú‹¶7ÁÖªdç¼£@mU¯êž¾µ5p{€#¬„y<Ûñ…uà:ï:íµ¾—U<Ý¡WXƒíÂuZ»ÎtEjˆÝ-û ]ÓЇ6"½AJ.œ[|Ô$àU+}ìd¶nZêbŒ»¹YÌû ൿ\º¦å\ígþ™‰í>æç¢þV†u³Œ8§y:s‘½Àú“6tÀ*!ÖQÙîíÜïq±G«¡žbÞx¿.ØQžh€q¼`’ׯSk”à|Q5K³ é›4]©ž¤Ò>6ëA‰ÎÉuWó€SŸ!RV/-èú)ê>‹¶\4eÀ³B’/×Рhœû…Ç'v'Ab‘€vÔõš»¹m7Ð%³7ÑJ|(ØRµfMèPÂÃ0ÿì8ÿû*ò G¥úG% ¨¶ee6Å89*—œòG#6’±î „j:á*èe§ ?UýZ&À¶Ø’Žôø¤>0÷AK) Ôª\™£njïaÇUÓv¼CŽm7º÷]ÏPh{y±[aôù HCÆò4Ñ5p]Å ÊØÁz–ïñÀé?ª•$Íè€,ý¸ô”ÿîók[ÿúk‡ÍFUßküI”½Qn ‚œšÅû¿Y†kÙ–Ð=?ð?ôÞðù7ÿãñd>Ü)UßèÌ­ªD0nõ¦eA°¡‘ÃÂÔ4y=÷s¶“° “ù’ãÙçu¦†1™›,ËÚÝl$ ¹mÅë»H{Ç»4A }Ƈ0ƒoˆë¼GJý«mZky8\Ìw̽CPKÞÅÊuhöuPâ*€!!UÆtr +󸫲‰ö€W³ 4ý¨rDŠs7ü”ûÕìuý6“~ÖJÖ ¢Bt÷¦/U_Ìù”GòYø¦OAÇÅóß6}— þz}=ÞÍûª†‚¨áÉZô%m–Y×TÞ›õ<ØdÃëf4­nî{ŸÀÕûix~BCI$·†=VÉÚoyM™Èÿ¾˜ue»ñZlj̤´˜ä.Õ2(ºø(]­ô2ì¿-ØÞúý`¡²§ñ”j´#x¥IJE=]"åF#/†UÝAàPªïžj #8ÄCºPÌÓ©ãgˆeGýL7{«§©”èJ•åÓNèZŽÌe(ºzçî&<  ø„«`øÆ®—~š–y[1a®`µ©÷=¥Qnk\v}ÔÆæÏðÝ»ܽ€RÅà„Fzoãïç&äUÁªhrRÚ}-4¥8S…âª0/€ÊE›Më)ÌZ'lø‚søb$ØkàhFœ íœkÀT[$*i§)Ž~[Ïõ.…lÁzÚAMÙ×f< ƒÖxÈÖlŒ´ÎªhØ~[Ò»piAVáû4G¢XŸš¤e?©„R›¼P5I^®ZŽýÛ¸Œú÷·~/——QEÀºî%lA(¼UÛHÁlŒ«qÿd=ØIߨ* (^ÛGܺª¢AíùŒÙ†M—0±Àí2ô±Ñÿ:ì©Ê‡rh%2Þ}J$L¬¶ýúÅßpªM+†ËN5šõ6g&P»tÝ ¯ÇÛÁ†ó®xO¶œ0’šˆªâ@ÈeÔ>+Õé­ˆÖmYÏ œ(¢öýÈÛoáµæ»`q­ªX‹êíZUÖÉÈ®U²ý\›.7ëæ;èÌÝ ÚuÜϤî¿ëªitmÌX*5ïYTÅ+í™bùe-̻ΎÏsB ƒ¬Æs)1C£ê¨ä‰×¶úóZ2™º ¾ÑÖökñQíA€”tžes¶jU©-ª§ªý}É“0ù’éüj¤ß›VÃÐÌݶw€žüµì‘úë¯b¯Ú^ç«^U߃NúÖçTÂÈä@ˆ†.eߪ£T¯µÀ¶ç3Ö§FÙ'©;}¯¼Í ÝQ¾H% ùDŽï€Àw‡º’á[öûîÃhøÛ(:Ö%+ 1²Âü«‰³8¦ÿ–g¼˜ KÏ…H÷€÷†ñûë¹mOãbŠÝnÙÅt#JmâxZ“Œ¹à)[v@¹ÍͽŸjë'³žKŸ×ö-­ý :/hzõÓ0ÂM€=QâbØP%CÊëBà ×4ÕãöE×ñÿÜœÛ[y‹>½EH¦Þ؇ôÝœûO?,‘jOÝ!“t-t‡Ö®Ó…kßÝØeRªÑÆ¼Ž†Ö׃Ï5Ë•¤TëÙÅZäJ†S:j‡i¨ä®@¨@ÊMK›Ó|8]¢;릀/; ub×U¯í%ëÞoõÞ§òxÏ¡ Ëÿü]E‹¿ÇC‚YíÌÆ‘Åë±PËPRZ¢25f¹é]ú6Èù§þÝ¿¯ìÈùpÿ5G—˜Uwy’ë~Þ›¹³¹”]CõK‰ˆs£“xžÞ­+FíÅôf²{Ѓ•ª‘‚¸JÔ(Ç-¤ò=€ø‚E·Êí¼¡r\OThÜ#(0æì݇ YNLyÿ®”¼kLžyIÛ èr‡¾ˆ!»m¿û¤<‡Žç=‡ekÙVæ°ƒZjÈAm+äÜ….½?º ˜1È•BÅä‡Áó[° <^i˜úÙO8$ÃÈ4ÁvPÑÔÆñ° ª­LBå˵¡Ú„¦ÅéL(W¹ª¸ †ÐªM=+â5£ÎÊ=·H÷}ÌÕš…£'s÷Aõå2§Á€Ò ÝšJ„à;Q‚/(„ªƱګ¾6ë‰ÿP:w£¶„Á;råú'ÏÉAQc›Ô^„iº©S ʉå8´õÆ¿™N8)XXÒWC@¼*ñ@ôgC@–e1_ÐË"¨Þ)<䛬\(|pû´Õuÿv=?Œ]ø²Ǫ"[˺²8£t2OçQ6è³"£¾áx’Ð-2ÓæBï.XÖY5Ž…Ĺç¹…›ÚpÅîMѤû6vXÚy#ý¼¿ó†þ;¶SkYÍ|Ôäwz—·Û9Ü–}°¼€§à˜=ŸšÄ!Sß¶ôþ×_¯ÝLgé\ĺöª©‹4퓾ÊäÁm˜ºÒ{¾Ã£Ï$TApé¹Mžgü·.ãH¯mžmÍš0,¥z½SbrŸÇ9‘¤Ø[Lðk$iÞP©0t브ý¸m°õ£¿ZÎö£ªËèÉ;úë”Eã( í…›6 ýQ÷ó•¿ýd¿¡Èo0( ×Äyp›Z©,«‹aoÌ÷£3d0o¦ÎÚåoD÷3Ÿ‚i©[4I)1hcaΘ4žæYe;šBÿeU÷R~BÂ÷ÉyÈàG3ž²ÞBðRmÜD»,f± 6||î¡} ‘ßÓPëLUÁÈg…0 (5hÖé’ìÉ0PØ’¸g9wüífxxÝì¿É™ÞÍ5$½HÝ#"T´æ‰Ù³¬ cSmyÎ!/ü©›µ}o߯oãê^q§µïÄT›Jùñ¬¯©•ÓïxšmŒŽ1Ý‘FëÉ ãP ë ¡v0æTkÑ/õÒvY”iI2-ÇÇíM¹¨OÖ1éwß(ý'ÚÀ”d¤æH@mŸõ8«²Õñ¦¶Nz2\Œ]PŠÀ„1¥¦{´úÚ #¥Sü $ÛÜ7kEÉP¯%§†õýncÚë݃‘ÎƒÅøÅ+Ìzç2€£û×SP¹f‘vÈ6š¢jBµG¯’hmeã„Òü ·›ý(9‡’À55㙡%ZèCÓ¡ÚÔ®2„Õišrg(Õó`Ñw£´OêÛú˜…Áƒ/ –Çxf:ÄùZP±¿ì ¥Ì²˜G‘ 0½mÇ€ðvMÙ$®õsÍ‚šE0÷}£’2^E´˜”çØÏàûÓ3ÒudÚ—Îísî÷ÃÍ"èç|¿±É2î·|ȳ6/h_wÒ² G_c º‰Ý7OéË>Ð[7æ$DQÁ°!bú@ Át |TSaž¥ùP¤²j@I}P¥ÊÃI9~“Ñø&ùþ¸I8ø_o’=¢›DžÒ‚¶ßè=›Rùã&y×¾¶ÓÑH [fæ°ÈàΰJMgePÒ°äåP°ÞZ3Fÿûmp>÷$(‹ÑÈÁ+Ó¥®ëy,òm)W'k—ìfAð0àFH ˆ‘=³>q OÒrh…2>3S]!µÛ,Mž¨u¯’fåÐJg–>ô ôa¼3Ò\JX„¡*:,Âx¬x±KºXMRëß¡JƒuÝÃVðž¶\T­¾W¤Áx¼Tzo2€¦ÈOÅ…Ú7J€—±jäR¢ã†höl:ŧ äå{bï 4²xŒFAééX³•.âb¤-/ÏÆlÏ ð“E8ŽÂÁýƒ¼B_‚_sa‘¬¡á°_±|cœQè§¥—Ef},Ýeàë[Ç¡³¯>"_ÂÈz~‹–² Sg°iZ/=ý£[§´dAàè()‚~£ïŸ>óî6¼¡/ÜòÆš•NìÊ„™UL!µ†>}—O™,éZØ©v@ØÉó÷NÕlUCžÿ¡ªF'ä"«¦ÊÊ9*Áp7ƒäÁ)·qòIá@ûúúÓÅŒ¹uÇ8 *ð&_ø²ëaN’TJXáKÐU÷{”ã~Èï±RÆ:ÊlÊÊJ>ûªö¡Ÿë}ÓÃRËjyHÚîapÁƒùÞ$—'?Ü)v(iõÞry÷‹Üî×¶=Œ8 yŒhl“|Õ{_ÇzÙ“jŠeÓhMc”Ïzw'ûý*½AÂxq³ÒU'2Rc†¢§1š³uiy̳ÃÐâ#»Ð¿]îá/4†¨´ÿŽcJÐh3ø7zFº@‘Ñ”SL™; ûrø(?ð=„,”7†îØÖ»âÔö-¢ p­¨„Šß ¶¹Rs—MzÒû¹&}ŸÍàÝäh4€Oâõz˜î@\¥qcº3è¹q•ã@SÁ ß>›–åú°(Ýw_2.F!‘„ o0¬8Ò‘Þ·¾P}jM7àÚnfUPð0ò ·qx:çÓÈ÷m[©ÑǧC¯<€ûQe_ýD— h>*,eË6¯õã,Þ‹5çµhãÁ*&Ó›>µR_B¾Ï­º+™²©{QìPtNÖv¶q[%Ä–„ùèçÚ±ð íkö†Mc^¡åŠ‘C0ñ…)ä÷ËŒ­Ó-”ðŠ6F~>í›;_,gr,‰”€¡ÇwÌšèôc«N‚ mDºíè™Óµ¨‡b8Z–¤¢Ø¦¢ÓƒŠ“w& híïÇÑW ßŒã|ÜÇ;]ÏÛN9ö¸§é.ëy”À±”«o±Æ¹}¼þ³ªN@>´žws(±Q̺eù“ µ®æÀ¼0ûŸ—&TF£§ý5æ ÒYÆÜ9Bövvßßᆮwž­1dMÔJÀAxá0/Õµ%EØ|fZÒu)‘³2(ç±»TïÓ’¤?ã=È ©Þ35'ÚµëVÑ6D)…£‰R3_ G‘oˆ•0` *sLœ“¾q¾®ÝÖï…ît‘Õ‰¬,5ÔàÝ›o2á›óáòMË1è;Ž8GÒHºz©#¨pï·­.pÔ:Ö2BšO¯ ¾C~p&÷wÿ£g–˜G®‹TÄ×0¢œ ÇkT4ùPv¿¯f}²¿¿DÔ‚}0éZîXÁ­w:!¢k¡*(hó•lÃãwèt™ëÚWA܇0ÍEü³0wrgÄ?Û=Ê¢i™% n¥‹ûîS)c•c[ï0ˆÞ(Ú=œ5ä[`Š„ý0‡µQ[FG2o“¥h—\Vuq?QÈÓ“gt®c/Ô³|òä,Ö’¢-ë2Lk“.}ÓPUKG~2aP®e6ËÛõúÒGÇñ›ñu@ÝÖ,ÑŠŠL¾õªoêmšØm˜ è-Â{]Âàl \uEÿÙ‚ƒ‰5€BŽQí¾¼ÈÈ<¾Ùv-)ªsrÓ„+&ú#b=«ºŽ·BKd°¡ –8íÛ>z4ÿÆ'ËÊkÉØe£3 ­>_ó¸¯×~÷º?–ƒÚ!eˆpå–cL—Þ5{ýfÅXñøf5)t”[ãñM©?åÝÈIÉïµ]NÒ6»b¼‹»Kò áÓoc ÇøD6ºñí1W O“j’=’õ(õDÇè™s& îeZ³2ã—§5º’õŽiM©&Ý®C›‡  <Ç®E–ãžÔÆE¨%zƒ¦¼ÀÔz#Ê¿®j¢­±<Ž›)Üô)îTTHd(ë­Aýý G3ô0éÀ•lÄÅ Ö*QóP&›N’-Úþ¼Ò?ÚûûiÆx†Êàñ†'®n)¯¦JVÕU™ÖÒ¡Æ.Ê?ýnOŠ'l?ÿcòúdú5Žj…â¸fU:x*ß·RÍí´uc<šÕ µ@ùÝHÐR.{¿šv˜~”QÉæÃËFR"’SêŸ5°´˜d=ŽŸ¨µ}Û:ìù>a/±ÓÃÍUþ ®¡9íåÔTgwk­ä&¦Ëè¸ÀÛ€Êy4TLØ J!¶IU1†Ciçq^×yÚÒx½^€DnªxNçzN¦l£ÿçTé®!=ˆ¦aj «)¬³¿9›w±>¥=—2ÏqäÑä4 S¯Ç¶MzøyÖIº,c^ÉŽ÷ò€Óï.¨þE»@䯹¢‹ Ñ'òW”s=1&Š(—ìó?WÄízû×§’Þóèš].Í4Vºƒ’=@a1Ä ÅƒÑ‘w¨:‘ Ú¥ß"W›bŠ\N‰‘ލ¼mT[E{«ÍŠôÕœûûºFûî_ý›?‚—*òZ#iSáOTÏJ•Pb¶(]>XÁTQʽ*•‹ÛÓM¡êJº¶ŒÅ-^mPzر‹[^r;¦”‘ ä%|Ï ¬éôn!1+‹;j=4ªIãqìtÒÔ‹YBÌ¡øZ„G³êmEµøKvˆhàÆjÝ0q‚9 +}ét/û.¯6mî,ôoB¶ùñŒŠ8šaW ¯çöd®`œæ 7lòÓCùlÏ·©¡ÇÜGªZFùt=ß p|瀈·¸,mì§ EÍ4Ð$2Úd+ç$ã ä^Ìs=ëæˆX¥H&¿EfÍbâ0B OX˜÷v¥SÒ­mi~)tÅ À µðôa»Šþƒox] 7Òñ¼²¢{t.ˆpèfÝÔï«Y—«êñÚ6ÖÇã»Wì;.—¢Ÿs¥é¢ˆV‰µQؘÄ@ÍÝ@Ë?šõ¨™¥YŸÒä¯`èvëÖÏUUé1ÙšæÏËQ†h]mñŒÑ7ó÷èRBïÕ4Ò¦l•¼¬—jƒp¥,ˆŽµë@ÈÏ3 ºþ †^.»û²“v¥Y¤¿9œ´‡2jǨìÊA8VË ¡¾|?¥¡õ¾ç1{Èô$…‹6Ä=kÞs2‹”Zú„Rœhì~[Ïuîù0Eî§€5ÒW cxAúŠr°´N•ÖÓ&8m‡ÊЀ‡•tÇ`03§°)ß\—ýð-Ðw]ЃÙ7ôtèÌŽ[ õêv‹³ªK#Ž]sc1­íý•7¶#ÇGá ²./)8•u¹öK\t‚g妒çRn}ƒZÖ™’\3ØÌT¡}9׺6^£ÐsmëFé5£ŒÛ,H‡ßƒm\àXn%§ÒñÓk•à‹ÃœÆT ÖìT”)=í{£Ìzø¹.]÷}€Ò¾©õÖçÉm.@ð)íH4‡ãj„7Æ$·}ʰO·’©¾›}SmFŤç¥6«jDÚ)µÙÐÆC½Ìɬ%‘pîÐg£ã;¶c”îþýƒÀoœŒÆ[ LˆžÅ›ï%²é´jCéÒvèñ|x²ùoòìe:ˆ¶3+duXÓT¢  à$i"ºá¨àÓ-wîìFŠ|pZ-¹þ•ÂþëÅÔòÅ4êY.¦Ì,è£F dÏ[øÆ­q›ý)‰f ½†`(È¸Ý ââsEu}Veãqu!ýbø¹Û7£¸Í¶·ïôîÁÃÁ§Dø¹7†É1§¸O5¤îK;hð´›2ÆCÿÜu?Ü—Wö =’÷Ïpd§”˜b‹JÄück߃«%Ô—>ÎY–»‡oœ,KCg\Íq&ÛвDHaÚ&Ý>ñÆ@Ò0Ìÿ'IañÕ2ÜÆ­ÈG:ÆjÞÆX:rÕ&h®„ôC}ÿýæ.êâð93 )€kE>B«eo²¬m‡¥ÎŽõ\ Ð [¸Ò¼%®\ðŸÕ¸[”T)³»Eg¢¢µ›öhŠ¢a+ôƘ<(sÜn°A4ò²ö5„b(7ë2×MÙ´†.ܵ+جž×bÛYŒ–ñ@h³a˜vR]ß)⯄aQS )„þ¤]5M2S9©'ú÷ïëݯbê,Ýú%G£fìªPøh U¼FkT®‰á"Ñ‚(ºï ¨ ¦_¨Â—˜úܨ }I{Š'Z"×Ð<å.”*ôEKùUb¾‡ G® ¸ûìésŒ Þ-¤¼›¯@”Ÿª…¨È³µï§q­²c9ß¿Y‹qŠzfø13¢ÈÂ=\îÇa"݈=kcqÇÅÔ$~‘ï ë>TÈð¨²ß-¾wü{±E•éã–uÙï›G<ÅÔR=dë´ý3ÉuL¥‚kAˆê» ºâîgˆþHW"u™£ÉAcxME©rÍ1[Ǹ>Öðܹ™LSvA†{&D\«XËpß‘^¡#Z{VѦ‘õB*¢¡#8‡Xèx}G6÷ø‰ÚÉeÛ`r‚’lºT”ÿeCTÝ–›Õ|ëÆÙôçñ‰¯™fgf€€Z p’3ƒ^åEÑîÑœSnîy®X´Ÿ¨3ôw>üÌ0ü6¯¯áª°1H•yÔiÞSÙß Å&wÅ{¸ó„›¤ߘ×êëñ2z%°R`­Á§7Šöˆ*¥V'mÖ+Yƒ¼E)¯¼»Å½¶ö6¡ïÊfiDU÷˜GÔ…î(˜òë£8…9F&¶xÞˆQüÕ€}{`GÅêE²›ÁŽ‹jã¶ ­½~‹{ -B¹*ÿj¶m @pnšçº­§1€œ²ç}U¥î³ˆª<³äƒ)$øTÛ˜«äBo噇 °Ñ9š¶ŒÚ_»’²ü1ëXëQ8¦={"½ÜÞ03w¿ù†£Æ7¬¬Ý=+™ªª-çyϧ1ÚÛ½–5-H$Àâv>,÷³¦¢AHè3ìešN\»©¤¬mPmÖnY6É‚¶‡J“Ö3~&+»?ËÂóI8úò €våÉüŠâŠ €‹l¤$ïa¶¦ŸRˆ~ _˜Þ»ã€ÐsMJyš÷hÆ[Í «Øtší ê|Ì—m¯—e¤ˆËj`ÊzàœRñáÀâsšÃî߬EÇ]»4ÿ¾Uã8JÛnˆJª»lXöDZ;Ðl l‡J¹QÜq¼ÛÇ4‡?2ðÊ´$<âÑlìÛ]°ŠßiW«ªèŸ{ÇE²7´íÞNߪ³§À~¾œXf ÜÈ5d´ðÃ>¾îª­³¦ôÉ'¦2=€Ñ!%—7ëmù®?^è= 2,‡µhe¸À×Ñ2ôaò\ü™“"ôÒ)ô#²¥V?‡bÖ›…ÿó}°ðq1qíß _7E?n€+ øžÓèÛÀžÛ1ÈÛ?ÇW_<êe]3à½/2_”¹4àžº]’Ú,¹+>3–š±ïÜ; ¾˜Þ‚'L¦)0°I$õ´×Í\äqQM&Pú´¯Qp9ÎíÈÍÃàb:Çš’èÊð8Ç,šŠ]¿Ï{”îzÙgÅJÌZÖ£ Žî7  Ø¿ìùË)†ÜÄS.(Âu¨Ó׸í`Ø'ú‡¼Aø3X¶{²»e‘ðS³QÄì(­Æ™GVY!­¤ØéýXÏõq”},žð¿¯ÇªlܦÑHᵨ¾YšAM™V’"/¿#‘¶,LôM(¼]¡Ã×øZBc»ç [ÇSÞª,éÿ˜çãÕ&YàbZÕÆÄóhžÜ¯ãµ×•qéüÝ3.*z54me]'¹Û®'*³ïïAYÇÃè§ ÑëõL~©3ú(YGå«Î{>Ö„½ÜÃßOÀ µ0o1$êS çU6ÙªŠ.Š)çü}ÁûUÿã‘ÕTÂðZfNÙq7-•ÇqÜEiSüòƒYô÷¯}AièpžBÃW,Ôp„ ˆìC¾év—bøÏw?Ä• 4NÓMsâÞ®›Å’öæ*ùà >µ{0T|H”5‹:6îâNÖPàxÐS9}ä_о}¨¤n?¯Ã4޲Íš°µ@+Фhú¢.¢­ÚäbrBHÔYÀå܌ɰ^aŒ:¼ª‚Íae¤Ÿ†µÈG@ü§*îV³¤w§Ü¦{xíæïêuý:½[À²@çQt¨kô‹’¹Oœe^sEªoÅ¿ùoƒËDÐþ§ñUÅ ƒtÏ¢1U3SÝÐíË<­"‹@w:%¿”Àfb*Ë”Ãošß¡Ø]@ôƒÎqmº¾Õš½RŘcU(Y{ Pegú1Áudó¿óéòéýÈXŒÝ a@åûo=Ë‹uýŸ½jªÃ«¦5^5f1DAÛtïWV¿v‹¾R±½ WÖcZPPÍeJêz–Ü<\韙ÿúþÔ¤œÕC§½oŠlç™±8$Q²Šg³Lí@ ö±¡W¹3%²—;>*‚jÛocÓ¨ˆ~gõ˘U’%Pž`8‚nªm ¼ó±¡¿Y±ø éoÛ ì½ÇÊÄ(q\Мfæ†þ4mBcøÜÅýìëâÝOqsb6æ/™¦“êS5¥m;ú•‹[ÝqA­ƒàÚIÕ}S}V5ã«ðL¸Ek„ý2éé'SöQ J(=ä0ô|N(¼ƒÐù¤¿^FÎ:h¹DWÖˆJèjQS«Ò=’½9ÖƒØÅ=šé~9À—C–E£–6ˆºÌaZxñVÐÞÙåñʨ=›êCׯeèð¾ç¶õÐvÆTDhµµL1òm`îÚšê>&&-è²xÚ¦%èáßPä"È •+ö¸k¥áAyƬ¶<2‹ÁÍØsà‹|#ÁÎVþë…9ÚóÉnƒÜ>‘f 7Û¶B5õ:åE¾«Â<-çØ·;…ópbsvU!ù‚³¡ŒSdLZ‚,Ý=âVÃ(¹•†W7¸[ÃCòèÓoZ;Ü’¦ÂÍr>%àõBO¾ó°›ýøh§ú¼kŽŠÝ»*ænëÏúmÆuY@j»y½V4¥ËÏäæáÍÃ_ðqö=ã:W6×ó{û~ˆplž~ ¢îÓ >úÝѸMf=°ÊvÑæ¶ÍŽ þuIÍð¹x±0ýº:pÀ}®–¼SCWÂs ß%ï¡*çÞFX ……ùüþå¶yLÉÿð'[Ɔž-ÒV^`x` ¡¹K¢»ÿÎÜ€öûÚXeÐÎà^ ášb+ (—$-JÞ„î_~œ®s÷-“ÝÞÆÁ_lJôuÀ:‹ ç®9`aMu”/ƒŠŠx6³&>0nNzNy‰nà\³·Öç)̽äÑÜYÈÑ~÷y.ù*{_êKÍÕ J’µ¹^‘´—^æÝ ÛŒŸ »´Î?Õ@-aºE’ÕT÷§‘bÔ(CR¼¡¨$£Œ‡2$˳]ÁÒý ‡Ò²H(¡×ro†åµç:×xo“!Ýã*Š'YZâÕ%T€¹§Îý{=Tˆ+W ©«Wnù9‹Vmj®©Œˆ:ÊIâAÖ£Ò"¯à.߬£ˆ½Aƒ,u$ü¨`9ëoŠ1Eˆ|ÛâiÜVYÎ {àX4L¯ç ƒüYá œïÇöúþyJa‘+Py»a[&ªÿõ×ÿ{íÿï¯Çãÿû^ m”DË·:ÛDzê„nB#ÑõÇ?/x“OXºâ‹­XX¹‚ÞF 8SÛ{ë6‰Ê²º¨ê¶AÉ’ÖÀ¼ê)¦]å^Sä×ûÄ”Òâ(Õuú­]Ç;O\×Hxº¹À<ÄeTX¯GE…nÙå{D—™Á×y”ÞÁ!Ä2”ç­Šj:°O¶àÍM ¬ã~}„yÚÌc‚Ì"me5Öm¿™ rïÄúÜ?<ƒ®Ñþj4«ìQW,UQ¨jdPþçÅ®Î1t5 ¹þ-ß—++_ñÀF*M[dmIÇS”ö˜>ÀóÀ:úg—ÀÄr1{ÍRò;ªP );´íxØ4å hðh£hÙm£4Ù¡P=Û¥”ÇÞ*êWKLœ<8µ%<ª‘3vbq[ÇeVïã¢Ûv“¹ªŸXÇ î> ´þ)zQA‚äÇ—Q¡Ä¹6¢ù¬¶Z«ªÉ»<ŠÆJú_´ aŒ;ÐÖ"î‰ÖÕµ¡Ó™kA$“á½ò„lËÄQOjIµ9$ ñ,LÊîF4Yhö?g–`–Ê}èÚ74–|Fœ`½KUõÜ7Yjqø2ÄaM¿¶š¨ëµê?Ö¢”@"Îóö¦íÝ+úÆ%Ìa¡u%Îò0$Ûöœ®®÷YsЇô„†Þh©÷ÈmcCÈo MθÙ#7]Ìs=ÖÕØæ{iVs jé`æf˜õȶÏô÷Š;úŬ4d+>ƒè$÷ºç\o[´R¼.û-2K _ÚžÿÖI¾êÀ"¾<¤oÓñåãÞZç4­Wúsâv˜~]ðžË_uJÚ?蔒쟄¨!Ïúì þ™“´Ù$Á͇ è;£ ÂNÒWÍ*¾×ÍôDªG7LýÔã<Ïh´è¶è÷:£ËtÏû6‚8 Û6{½ÒMbÊLR$èË,te~–0c(Ë¡À0¶í4ŒXž#CMÔ$›§°tBéëL¯.­ë¢Î‚áH+¦‹ô¢Ô„®•_dÜ}!Á™³†¢m;0–pÒÛB[…ÇеäOÃÚ‘5Z¿«aÖñÅf5˃&—u4×ä¡îe^¶æÉ$‚ŒŠS a Ñ(¨r¦{8]R*:⨒×@Bâ´€{ÞÏvË%`SZû³1ÈÎÄך8³ìM5¥ƒ^6éxø‘À„ «X'†írßAxãñmš`àî@®œµ‚) ¥Ò4oJí¹©PƒJ7 æ<ëÔÎñ>Œúž,,ÎF}˜~hHŒ§Q…³jU–¥Ò·¢5C46lˆS5‡w¥;SúÅs)Fi²6ˆîIm³rX¨šQ3Ý=¢éß DáÂ‚Ž‘{Ðû.ƒBä 2x䢲¬  «â¢²‰G**K:’Z–sÙ—’®Ð¹Ÿ¶k òcnxh-×LªeÛ:X–6Q¼-K¦–_Ö‚¸±­C…úzÈ_³PîˆÖ‰6k¿ÌtHFNGÎáñÆ¢F‰çæ¼aÚœ¶>Ÿ±.Í*xAÑ쯂´uJ—¨®(.‚ Ë’>̹‹žÊ5¯¸=/ù ­wEDaåD¯Ñ·mòJ5µé«ù7z6˜Èz7(¶œšoƒ0öAÜA‘†A”Ñ#2_)%^TYoÚüX¸][wÓ±Þº¼Ws.¸@ "I˜¾F …ûUQÓ«ºP[”%e/ƒ#ƽPz koÇhý‚ý†¡JGò¡ÿÖ’dÁij'™RÉ6Éz¾‰· ¡Ÿƒseîaø÷78xû†9K¥´[ú~„•V×çüÛºwc±vc™u*ÉeQ8ñÚ¬Yu²ïö§ÿ×ëa惙|–Ž'é-ä]±«x……hèЂþ>²oC !8Ò™+"é|¹CýeÑÛ´ßmº+'DòÖ†6NÇÜaiâTJÇãN¡q[ŠZ> ¥Gö‡Ž 쌪ñËu<Ÿ5T¢ÈÓ›åªaPÍ­½‚q'Ëql{“W3/þ-ö÷õÍfBÜ+ÞhÐs¬¦|0‹×¼\öH‹°%ªíbŠ>¬ao\Éc€QY?·ýXi¹CÖÏiS¨t¦"Ѭå3å‡îy÷~èû·¿!µ²&ûJty6X¯Ù/ônPI9ý¾ u™ n_?¯ÍŒÊ`0S±§‰ŒÊ¶™Ò…©§}M)§q>…=-qßñCƒÔ6Úö‡Åû1>Y+ì6À kð‘¾B²µè‡¬3ÊêÅ„h€)mtÃÐe2­]*¶ý«9ÝFªÄ<´o,•ÚÍØs ÇaÙÒèaVÒjäÓïÖÇ–9dçsø(Vì‡pP¥§¶Í0¬&#€ûH"@l瘖]°¾¶—(»g0ÉB"׉ÏZ>Mjh§5†QœY È?ÀÜÝ$ ªÊ€íüÍg’Lx•²4ʇB§j˜ö*в¥2ïŽÂ4ÌXíÛ:ÕF.]qôœ_|~¡5£KÀ(Ñ\ǵÓEÓ”C½×"—û‡õ(ýøÄtCJ§Ë ª±ˆ/”`îsC‡F%M7fÙï«ÙŸÖ ãðRâ‚ã` ¤ëlÝ(ÐY— íÒÿ¾àíÍ/ù‡îÕoïŽÊä‹Êɇ¶4î6ö6ÚÒÅXµñª)€¿~ˆwnp¸ý°WsÌŠ9µ‘6Ãè«-É'5oÉ®RY ¿]ŸðfÙo.øõzÛ¾eP•€iñ_âw7QÆš7j¥h «Î‡ûK`‹V³áaߌ‹mâKà>I‚¡–aa ÁÝ^õyÅ]6Ê!cŸ.Xè0&áç!ÛÖ—d}ŠžhàŽu'ù̪½ÍÇ|ïf5•åöËrbu}mâ¾Öƒº Å{Iæ¬$H5p {]ÓŽü}=÷í~Ê:â ÏèV£åÚpr•lCWi”GÙ´©.®Óß–t®0°¬öY²¥_{ØYÄc·URŒQ•æâ€ÃŠsÐê±B‰{é„£C |'}à4‡—E>ƒIïkÚàÑ\w9´g‡.’Ðw6 ôÏ{ËÎ~D¾çdé¶Ó½xZéví¨Ž˜ÌKþ€~xJÿß/ àׯõpœRùÆHÑK‡Ný S3ÄÝXIC‹Ö¢¼Ï‚v"½>Ó8yàl ùc·Ê†Â±‘/HH‰Jê­^fiUÕl’5ÞsÄÇ)¿°OªËù!¶•ñFœê¦¶ËÓ>wÞÆæS„éw?òIˆc%³@Ä·È—¾©G´h{.1›"©‡hÝö„²òQ¶¡PÈÉ=SVø!<ô¿jÂö£& î7Ðy¦\Ú>ý³í‹¶´|쬠o*$øš+›ºvºàÔÜ×[žýy1S^pÆ?‡ôZ…2’C\éš>´*ÖAÓE²*!Ò@m(ÌáoöEï,_ëj¼h“MxÜo £Ó!˜Ó,ä^ã,ÎYM p¨T–¶mD‹S¶¡õù|É7á¶ #†JÀRŠšÖª*VºÛÓMNLà¹!HA±µªºú¿?Uoïã–,]IæPÆ«>t>Ôáþ‰”~=bAûÅÅ‘öâÝ ÝsØý[²/åÁ~¡#§À¼®TªXº)^ÇiU²dX0]ÆwVÀ’Pø1µØÀä5âV×°ž,jw¨&4‰Ê§¢5‰4ÚÇ0Lõ)æ»á±Þ{ÀB¨¢²QU5…-êf n¤KºäUVM³!–ø!ÊŸÑJ8„ÞÅ&c=7v|©YëËXª´»¦šfÞ»8ÊòIX ô)è¬Aï6 øäAuཟ7Dj›³ã79¤ûtÁ€q¬ŠNð‰ÿ¹œ PÏ´ãµ>_N³à>?¾æºJïjY›q](…éEÓæ—gû¤ð®Ç¬²f9U}˜“«‚ÜN5ÅtÏIø§‡ãzõº÷P¿{O³å(OÍeïÑí[îkõYÐúŸÀ O‡‹•2Žš)f(9-kQÿcÜ ¯h‹çm®†¹.e½¥9J×7ã†àƒø²þ¼ FåKŸ" ¬kªçòmÙT±¾4‹éð—°Žôù|”ÿUʬÐóø!eès@нç Ä‚¥Ì>´GÞVTðÙµ™®ä Ïël„[è˜nfAŸý~Y’Û}3w/:“l! —°ú ŒŒ(,`Û¤Oʼ¯35à Ê á è–KR¢Ë+„6+;e9|LÑGedNQ ù6îX¬qµ™Å¨psAv-ëfæI®}•¬Ìyaa/‡U؆±†qšS=±mXmÖ£‹—>­L±¥!a_Ò"” "·ƒ¦vY˜)æ|K’ëuÌ“„bNŸIRÜQøÂIHš÷òÃR@r¥ÃÇ[K“œH>O»ÏgŽÊjü}ÁÛ8€õgýL)j —Çž'¯@?ïÍN%bRWI•Éz¬’!Œ`9&Eü ˆ=ü×f(pœÀ`9ÐT(•Ú‡nNéñzi,RfàP¡p½"‰|~ð™e=e Æ<×,(å(³j[Á¨äÚ$]Ï:˸3kbÊçv„·x’•lÙT³©13‡²jëK]§b)FÛbíSf–øïNïû|Cqøqi˜€ß2ͶUC³F¹òjÙÍzΰƒ£vð×n†xõn­?²©düw± Ïšw-•„cÛ-ëPËKðžÎÛˆ)!zp1‚ý‚ç#Ï.¾©!îÑA0’­g ÖºM†½< DõéóZÜ{²O$×ñ‹Y¨š v •¢Ô·DˆfÌw–©zŒ—-Zú8Ó™ 0af³$FyŒ}âœÓ¼õIÝ&‰"§¨PÑeNfd­0úÌ”½öñDÌFÙBÕ›U©ø²ÃŠ\fvÀ•<¾1ßt -é¯0t4Õ9ý¾'R“@&… h+$§Ûý-8¿‚îh^/g¸C'‡\[‘Í3eY´¥Öc½6n.Úùf=ç~5|½Öï1ˆÙس*ˆ ‡^-Ë”,ªîEÂ3`MUÐ G†^ÂV¹zø¬?ÒiãŽ9_ ¼oØbHéªF½¯Fe4€dk»6¸'ÁëÃç„•…-Ù58bœH·@x69|ûöiœ•,æ2E¦ìw÷tÚûPýyBÌ]T ¯€ÖvÏó.ЇJÊ;ú²^Åxç+W\?å½&te Z°".c Õzï鯫ú±½´ò¾TÈ +­zÚ’ò›=xºÝ]Êà pÚG~ØŒžéB -¡¾kp#‹·^·QQÅT(­Çz`Çb¸NoÒ9M½.0^iñ<ã¿õxy…´ M“g+¤…Ì|½Ða^ï˜ó½…‡ÿaùU¢ü’.•†ñ(ÔøFË/Û<#'™tP¾¿c“ev’ebvms“fšú†r`F=:”$¹·‹dî‡_(ÀÊÖ¥h-´,"«WŠ õ4+ªf³ {»Ã"# )õºŸyÒåðaþ|ñ¼y{ÓÒ_UÃC‘-yš™ïüÇõn‡ï›Å@‚+¤—ã‚êÌf»­[Ç}ÙeÁàN‰Õ‰öidêÞ‚OãQÑĿ굴á™ÌÍj˜©fÏWÚÛ¢±"„ú€;ŸðzÇÿ<Ÿ‡‚l0ãyè¤Äy¿Ä­ûth·Ôdš\ï#ixÀèáô fÕÉžíU˜©8 jÌ»j]µð«áÓ²0¼ß¤Á®<nO ÀâQekdŠX³b^)áoꭢϭé|Hýo€¼QºidËîâôð¿ÀZƒµÒ-®Æ!Ê+ézÀÄN pVî!_s3ÊÍŽ¸¤!ÜH¥[ж!g†Í0õã0LÓ¾Wt nͼ¨¼Ú·jlçTv]êÒÒ[Á)È~zÓÓþþ6Z;IžÒe7RVÜŒ£v$ôJ›´hâR÷e$œ§˜X´[Ðnç|Ü»´\§—t„SíN4J€Ì¨×5YŠ=^éÄ› &…Ê÷ #u3¦ T£}X¹±Þ9ëHQÄšØ32Ý p‰¦ý´ffA›V¼Ù‹vŸr”WjùCf`VQãV'ª^(¨¢Iëµ4HŠEuÅýNâvöõ®}®¾E×BV©rŽŒôk7rjÐouAnƒI…<¢õ&þ¡÷»hl@Öʾu;]öØìþ†Ø~±þ&î¨NÀfsÜûœgñ ¨PœD¦^¦‚Ö†ã4ä¿D“í~ Ñ憰Fß§†ªƒéà6ͤê›"^Í©¦[êÎ>¶ï¿=¶ÏŒn}±Fˆ)rƒ¸Ø²R;ìI£(u¿³Q™Å¨âöyp""Ó+ŒM.x™§@4Ä+šÚ»FEìÄ<ŒY2íÕ6ÿ¾Úí*GÅ–å¨ à«™†@eÝ}u½¯™j“>å~Á(}Ú”{Ñ^¦ü+´O?¢·é—=߆CÕ÷ËÓÓ†…q5ä}R4cN?¿”éò£¯ì ‹d–SÛ iUÿü­SÝý ¼´ÉbTéQ„psÕ<¢ɯ«QèãŸ1Œ~ì_Ý…Ñuzmû²îí/Úßðg”àîÕwTmÛ¦;ŠQ£üI!rE%d¦Nÿ† Œ5\ͬ‚j\cÐÑwB'ËÛ}¯“)cUUR¥†ðï£X‰^Kxñ-ü?›ËÒ6§¢zþaÍäUÍãebEÎÜ´ZCHÜQ÷&¯p ³®Ë]†»Á£ß6“”Ðÿpø<Çú…à‘ÃÖÊõVÏSUå:«ß{O/ÙQñ!®jUó’!¬RP+ú_÷2WѾ´æÕÝ1D¡Òʽû¾cŽ7Œ ¶d°€ûù2ÒÉ(aª†éâÜ>š¥ß—x ÷iÞâݲ\øA1ÍxR8úT×}EʤÂDªiå)6®ÉЕY– ©.•ùåо³¶ºw|æÐþœa~ó‚¢ÀÖ ©zÒÛ!©[z̺K²o œoQ®o]Cqß Ep9qÒ°-³9½¨HFÍÒ” UpC>Q .*’¡ —Èö¿G*êûî§wŠCY!¼GÔh{ÓÓc§âX-«ÀŽ™»â;|¤ ñ]Â\XTá N¶ìµ.;C‘¿ɲ S¶´ŸäÃuÔ³#F8TçœᎡ²Îy܃¨ËË­,u§¾¨F8­ÉrTë†è¶@üÆ: ”ßr²bñ÷2N×Ä+–è3Q=ÕT!DÙ8í²m@(¹¥:˽å¸V'áîbê p;ˆfÄ-#\„j_‹:‚ÍšéϚ̢6&.&¢[ƒVþ[Ÿqc…™÷œàâP)ý¤Ö6ª)’OÍ–èó!©.‚¡c‡§$̇T|ÑIå>%Æ ¸ è¨ó(_ÛaRIGF‰ƒvËÍöARÂè'8;ù—R•±+"D *f·#ÄѪt¨©Ì¢]T8Chý @¾mÝïü†<¿)À¾~ ÛNò¡Áö›èÇÖS¡)ÖF²žG•‹Syû 7zW‹ Ƨ¡sÖuÅN¢Ì(æì®ÞãxÓKLû[u¿¯gÿ-]4Ø=éภ¥My¤‹K[ ”ŒVæOˆy>"·'Õ ±þ2  :8,èzlT“+µOU‘ë1§ø-_˜¶4lI( â„î§*àÿœ^dzm+ÉÆX·¶r•ÒF¸ pýÏøzjg”Œ×†p5j_¨î}YîYÞfk&Ýíз]cJ0:ÅVÞuÁ×ö ]Åo>(\™C:Ÿï”vT…êÛ˜r³n©…8ú0lw|•ÞLÐÆÈ¿¤Ý8ÜíåEMÈæ&L TôÐo7„r¾m\L¿Ö: šWÞÓš:0l/KÖ3,¯t£}Øë1¡JR8w–€á¤D/x§Œÿu,«Aœ¹]xǸá:¾¤ÛÏ—‚*Ù7½æ†ÕíZö…ý,ªºÉĘªX`Iº”‰˜†gø©¿ü:¤QèÄ1ýœ¹?¬25Ýïñܘcãh¸H·æµ$T;·T †…/âàÈÚòföÔ>Ï:£ÿF7è®ÔŸ×ÃøªÍE¾€ouÅ Çm}84%{3Å”vqadÓ‘q;®ÏÍ!ºôÞ>ux“ÿÞóìÐóÜöãÓ5‚y¦JF›ÇºÀQq~= ÞEà‰’”SÜöTôïc9Ê·\X2¿Ö0¼ÝO±î'›+'bÕ²x×%[¾M=šOõÖ“?ª¾}:µž ³5#1š†çýð@‡¨ÂËx 7eK»yèZXcÓP~:õQ¹7Û˜ÖyZæ­Y˜’9hIÜËÌkîÖ™]OÜ÷DÞõýü‰2\¡T$ÂF'c1ù@©R5 cUïUº˜Þp–ð/aÑæüWðž²~+÷6Š 1èmAJ·Ýi/í*[˱hÛ¥l]îªTnúC¼u¨*¸[Þ ‹:Ù¡ Hñ{Ea–ƒ5°Mÿq·Óçû•ÅRrÝ"ˆÀN6—‹'P©šiÌ£¨ÁóYð×´¡jâÀsÍ5>,ÇÞÙùãl/¶iú’ZˆÂ![ªþš¹·eža^ãЭÅË6‰ôìsº1Þö8mvÏŠBÆ»b¹$鑟ìu ¨‚u·ÅÌx¦ÈÝç[ß(ÍÄ>Z ¾å¸_|_è|=_ˆÏÆßF•£bÒ`¼Áˆl­–ºË Y$<½·`' ŸÊ><œr‹ß?†Ë+j4<»I÷u‹“­Íf]óbwˇ™î˜¸î!ÃÈPqÅ÷¡CÅßEˆj(¼Þ!e%ŽPŽ|x¿ZÇ.ÜûâœéÅCÔèÄлŽÐ<Îs±W9Ý #mN “³aX»L–¦[ÐC‹ê¢ÃOëf]ìûVa¶ÀÓ fefÖŠmP] åº}®×hÓ…¼NÊFè1©`G>q{3b/ö}ϧì(™~£›C°£U âüÝ–‹à.Vsl„ÂÄÁS°‚+0àßokP²1dEÁÀ‘mK‹¹O{†[7öS¡õ(|{†¶Êd·SZt2¨>À)ª\KjBwÿ8 ©ªSË\q\4‰a±jha"áz®¾5š¯„ç¶Å Q4m™­ QúCÝQA#ÏHOäq=Cbç¸÷¯Ø!W‰Ü8îÌ41¯–&¡VT,ÛØšõ< U¶ø‡ûG;ðë[æWtÙн’Ùçe“®EL™,tä×ÚwˆF£z¡h Ÿœ‚Ë$›ßJ§‡BNKųڪ¼è“‰bØ654æ@Ã`‰!RâŸlWÕÎõçû`^%:H†a[ô”ŽY“Mj6ëÁ *Àdû Ü£Oò¶LÛžGX”Ÿ ƒN–G,ÔNùM©š”жߗô/)Ï÷ÊèÍBÿ<…î{îJ³ÎÿPñLÿh)»7ëÁ?…c½#¥°ïלŒ¥ŸšWàÜp¨ÆÔÙ%”GåEG÷¶æ!)O RâÚ–}ìê÷+|È­ÅU_Z° ™õü‚‡¡¤=3®S—K tè/z6Z“¼³²{•FÿŠÝ«mË]þ&}¶´”<éFWS¹®¥2 ÿß 0®¨ïe(»ò½ºªñqœnUâÝÚR$¤[uÁÔ®i–>mÆmͺ­Tå:éßGÃé:’^Y¾3†Ñ%†•L‚†ÏqKå H?€ ½’3§»O·lfÌߘ+Úçû{ªâX“vP [çfšØäö‡4íóØä¬«oÆŸLh*ë~ÈâlšÊM~3…V Õo£ýàœ}ˆ ‡ëÁÍ;Q†c*& Fj¾,£Fc¬£×J6¬(Ç…(™{à'­«< ëJȇô?£¹xG&[“·SO™E¬òi4ÏG!)TYPSSZâvyÔk¯Ó.¬’ÆXP[(hgëº.Ó”4²XàùžcA£Ú1Þ"öÛÝóA»{/ðqH°$袷Ó4ã²þµnm¯¿¶ýõ¢;ph£hH—vÛèŦ °ð¾ÉLà!pc/-ÿ’B¡“¤çß<ü†³<˲5bå%"*ÅBm×.#Š(Û±¨ç Ž3j¤ÞìOcÍÇ—@©°ÚºÍAæ¶9-^Ìcš®ÝX³Q'¢%]¯·ð]Óã|†îG^õž£˜kQ¦‚–Q=ˆh Ðss°.’úÓ¦²Æâtå;õëÇB5C¨–\•…¢B¨ËòQŽ.Ð@[†Å›!lCË÷ò ÈÁJšG?wn©0Û¦~\Æmš—i[qŠwUl+Øštþº‚þ92.Í¢˜í†÷0>ÆX¹Ût{Ÿ~oŒ`j´¾ÊV³R ¨Œ5eDc­¦´_šdÈ~[ìvª6q$›žuaë†ÙTAl¶Ÿë¢ÈÕÞ&uFóÖ®²Æ“Þͺôaº{bÜ tóõýsHæÑÇA謎S\=æcÊÎçjšeÉÆ®¨)7êÜ/FüàKè,TZ¶¿Ðm“õÓ0e„Û*z§/i¡6°XÞÏ39XëoŸ6Èå÷ºä—…–ꚢëºdi2×”©È÷°?ÑŠ˜Ô‰@vè„WýUº›0K•ùPÑÔÌQ`Î2žYEk§3Õ·SË}[+z7`Up¯œTKçož»â¢ÊHÚFDpŸP<¬óDíIžokµ¤…,Ècƒ½e[,×1¼‚1ÏTÀ§‚ˆ×Ðì䳨nLYÛEÝ4E²&e FÒ1ô·ÚâÑÔ{`º±½¸Å°x¢S Zôt1VkÝc5”S%7³ugˆ³à¢?pdÞµ~Á2ð!@7Ø2ÑmÏ`{føíùZ΃ž†Jôo¶+Q'ô‹ ´{ޱ¶•/*ô A陿n(Š6Lok¤×ˆgÈXM±nE·@Zànp›olÎ)ÚÛ´Á?”ì±˦‹>¶y”µù‚Ñ+ Þé ñÑ¿ex$¸¥fm½$ÓÚ¥òƒá@Ø¥Ûþ~èT^äMéý6ÂôÐ"ú+ešt±Œ*jå[`‘æùÜx>|äÃâı®>Ÿ°˜þÄiÂÞ—ÜÅãÍT—ÖªžûjÈú-ý}±Ãgxd}=ZýYžE  ªÀoF“«=Q3…Äœn¨FËÏuY€ßAÜœ qö<Îj-ž`\볎E=ÐÍXõÍ0µÚ¬‡©•ذØG ýŠg{A˜=ÕTœÐì«k¨ö¡yPé½ *bžâyKá£'ïÝœBFሠýOUª¡D4‡2/ŒtÌ4‰288÷Í6ëßô>LD¾Ÿr•À£ˆót¦”Õ5Õ7ë‹ê¡Ž'¹=]ú,t3Ñ}|3Œ :ÂîÅp}®tÕ‰žD™!S >hs\çK<ô€[-Å_¼cÄvuðb½³x6˜€î,žúöTíšãpcp鹯Õʽ]€È”ÚP2ü|˜©;O[Ñìeݽ û]S2H5Ni>p-Y–ï†$oI©'`RL¤E?£:Œ­`Ï–‰šª2êÆ,æcJ€‰¶c•¥Ðw>çÏía”È4«¾kOI¼Aô)Ö©ªÚØ,H…“ow”Ü¡†¬7ÆiúS…ADLà~]_ŒTî[¹®T„eâë‡õ|Ї>R$÷lRÞ¯€\×§´ûê¶‚YQ«"vQ:¦[®»EÖÃlÒƒ=84ÂS¦gô‘(¿B.‡Î‡f o¼½dÕõPôyÖæ±ô³.£O@b9³vqGÿæñé‹ýÔÊ¢C™ßäõÑ’JMçã@É0|Ì¢~Ú¶ ýrï-nsZ‚­þÃäŸL†ŒâŽögLá±*‡FVó!±1 óÍ„2ŠW} —€Âà 13TÅ úi*_š~O¦v­Öu“ó?ø›k£PtoÖRÿ}‰©@T<0@­ c¬†k)ÙJÕN e[S-Iùûj÷ëéý~¬¦•–k%4Q“*s=t‹¤í¾çµœ¶À½ß1ÿ€ðÁa k_Dú^L02–ƒuDx ¬£þ ÚÍk»M[µ‰‚7­ç¡Ç%A#ø*–ƒ—ýýÚØ\‡o$\nšÄ•n¤’é)-ãDvLIp FˆÓ²ýBÿC‚òù\¿ ELA¡Ó 4Óu÷J ÕírÞB0ÍmÀ>¬Ð䔘š¾ƒéŸ$7è HnlU.‹Y,bE›æ­ÆpuÕ¥ºÁÌS*ͱ´oDWiU5 ÷UMÃXIÂÚè&Ðö¥jɾŸÔækOá?Àƒ¸Ï?Àƒôu, Ë#XuÆÂ0êf5l±´¬g±{!F¥¶!±ÀòýÚmþ‡#•„…øiMäÏp—‚{ðÎ(?äÊE‰÷`ÄCŠ453–&E7pSGc×V¤JÁõö)ô®bïõž?‡~ M1¿–¾JÚ¥”³uUÖǺt‡÷„Õðâ}ÙÓðÿ1L˜Ç# ýðjúÅÑBùGœ˜ Gõ«ô8öe胯üü~>E¹T`꘎Š%x}K±×c<bÅGK†ïS¤ÇåaÒrÛw?ÍR_ÌrNó´â¾m- ]H‘-Ù¬:,½Ìαn'ÄäÞMÐ}Ówþ¨)£ÿ·N¤2µD²ïãÃ9ȳõËdô·6ÎKþó`]ÂB½•I´Ã2äb› J2ÈcøÇI6eˆèÓpb~Hûb†fÃÖ¦¸™ò¬TEž¦…ŠxØA„u9ÐàF1ÑÚ 4¬#õ`Ÿ" ó1˜Ö¿e‰Ú¤É÷¦Ö4«›}4«AœÖs]üÓq Þ ]öû:åëR÷˜r´ãв¯PÕªÁ“6¡çg JZ•Ò8aP^sxº"ä¼úJð]b¨‹V"B,6¶VÛǽ٧àŒ¦7J/#37ËáDh¿þOˆÅ >6ÃÖan2v–£j}OÊ!™Ì#Â/Ńkªmö)‰w[CSáÁªéY™áË´œP³^F4-ÅPÌÑÐ%â¼hqß`ò»eŒô ­b‚¸þ‰?Ø.C´â,ß©ÑóÃ7ÎábJ)![§¢•‰;ªã ÖîTh•ĪiTßff1‚Pý>(ɰ=º¿Õ‚_šAÕ—@ÓÝ0Á9u„À¾Ñ‡ÞÆz¥6iSüyÝ«»°)L8,Þ…‹Ž= Ø\³XŠ…rP='#7Íx/Þ @œ™ëI6}`V$ȘÁ&L|þИ¢LGÑ?WX\QÞ4°x$­ygºÃ*ÄKÑ÷ˆhw6QAðFÉHé&;Ý0H³´,f0jm03”YÛ7Xʶ/Ê-Œq/š¼(_˜i³ ~÷AE6®w=º€¬s,Ýu» £ðÀÜ1tó›ÎÔ?éú—‘.@b– í´ýëH÷ð¡-À^FbàQ1)½åÀ»ïå¼·M1öó¢3ÝæÞ¨‡8X£ïxiÿÍ€í!>(eÅD÷VòNËè¢H •El®D`ýñáÁM4Ìy^ûí'Pªl˜ NTÃ0’¤‰×²«F-.]wtÈC` îë§¢›s,׬±xHÒSU{€ŽÒ”y,%ëáÍQá±)ù™Ó^B«8PF°A°`„4Y†©;X•y·JEi%½¼Àc¶Ÿ{Ö|æºfaðã¹ÝŒUm®ëm)zªWòf.ª¼êÖɬú€DQ5Óú¿]ÿ˜°K92ëË®>*Ý·NoM—©Là0J%®ÆÜ±_€9ºä;O(¸>O¾c®.<é8*ô«¬„7|×j¤÷Ó…çBè œŒ  6Ÿ†ò î9T´IRWY”$i×,»Ø‡Ð‚¹!‰CÑ6h•¨ÖåDÕò-%8ŠîñQ Ô˜š¥Æ¨¶ÙSÙ.žß fdÇÏÅç}VÇäo¬¬×¬–¨dÛj]¨dÒº‹Í5 {3ËE×25ªý®ßë!ø‘%¬m¤©ÅœRoƒîõ×f9*Îèþ£*ífyWÖÀûó> ÎSÌ1lŒØ*}ޭݨ0]´àe F‡àeQ…8Ö Ë¼l—îgñ©àT‡}¾Ñ©çT§N¨`+ÕÐìu#ëùÖšÄr¼ð•w,È×é·1Ö«¥#ÒwÇrÎàÁ5:F³`èÀ’›j ;tÎY³¡¢ڪīªè 't‡¢yH)óY‡]íÅVé, ?ºTQ6«lúÌß&Aæq(oçU)Ý\Ó6äéU5VúÄr>=#Z-Î!‰ã¹î§‘]*_ÆøªåüX„ ÑUªxÖ¨\Q Ä‚,“hn|‰þ@æ=^¦M€—Ø ë¹ïÐ&ˆ·¢¤½uÙÐHLð¡5”•Ù9ê¸(7ð5%îÃEÓ 0íëIpž©˜Ì¡5Vg6³f`ÁBÖBj°ê“«øf¬¿‘¿„^jËýz¾JƬâlÝt•0õÒ2 ?ceß Þj)—½í¼(¡FfˈVÚ;tëï:ÖéQE©ÍC˜Éƒïå[FšØrÜ]p¿A«Hâ`v0pbƒÛ‚c;Ç„šPÆHt93¨Ç~ZÆe]ÿÚ–¿Ö}ÿ‹žøwK$ü9>ÏêÀ6§P™Ë`åŸ5Æ$¦Q·0?’‘ýÙ³.àÛçö-¢: Z¤^a½C×E}Ú7¶g' ‹hüˆÏuÚ€Š›«›?è’.Àû¦ï?pŸwF°yö¦b½ÔuIYekÞ®WöÑKµ¾ìePú%í' ù*ʘJÄÞieTij=µÙ2W«Ú¢¶Ü¤x¥*"&íTÊ\÷˜f_ÌÊDFÖ(U ßÔ¢ÁKiýP¨-^u5ÖE¶™åBvð 5ã=Ç»_5_%¹Ç¸YKó˜C9…ô¹F6ÞîÐó©«©“ŸºØQ·NºglÚÃSÓ÷ÿ}=¾y‚M[jûÆ>ýa«-Š!u?uÙ–yÛ—×Fg÷¯¿^à/ìU‘.øŠù2PJ]êqNçx͆6¦ëZÜ’»íÃ’‚ ÿ¾… (Ž€ƒ‚{l,ÿš¸ˆºt/ªM€*÷ÐC¥ƒ›œ^ÉÚtÁ_}ÿ|‰B9»Á1·7¾õ™š*òUP$¡*„­#}/ËhÞÙºè•ý@íuD æ,:JÒðŸ§%WzU*Ëô¦JI¯ì|á}?¸Ã§Ç9©¸ÿ¾R|}Aû²5ž µÉÿ𽉫uœ#]î*“òàÑDä[\ìZÒn`FRŽÿmÆDûz_{‡„«C\¸¹Á‡éõ›Yþóýf9¼6¡Á®„¬W®öy.w:2*ë~]оN£Ÿ_/é†gD>WùØUøî±ÚRÚL²å¨!Ýc€>š"Ó½6¼ ±1Wýð!ÇuÓÌÐhož"—²+y‹64œ;Lìïf‚gC1ßû¿ë#ÊcÚp£;Ñ¡arAÖGdËŒÛ8nJf=J…èv…½ÎѬ¸‡—)7…××f 9U+m(¦6†¯kÞ–Emt'è¹úuMÛúh9cðLœE>y¬f¨=w]5Æk¬(Vtú÷%o'jšË:œTuœ};6ŠogU¯õ° 5ÝÚsIøBuèPÁÒ]g=…wɾrýð£1-á<…Ìÿ¸ù˜PÕ9$»’T>‰CÎÞœŠÑè´íÓA¬ýX~ÉTŽ¢ê@Ä¡¼ º:Ó<ÎT[/[½Q´PfQ{à0êë÷à\ʪÛúómlºán®Çߨ,jE9Z1îxÕ÷úXHk—öÎÍ€Ïà]?ÍÏA‹»ê†ºf¿n,:­E’ŒMµes\"éÏkz—3Ã*ªB¾Ê©\‡ QË-S!47“Ž+=dƒÐriA‡òHèOxÐùZo½:›À­Ù‡šAmã~TSe”1eqOz4ßÉ.•cŠÐàíy{Z=ñ^±±‚UÝ ‚¯¨¦víÚëSÔöÅÒ˜5)uFkÊBJq꡼·8Œb²$X븎çVd5©.Ë£eTZ­ÚüìF¢´%mªNìwöÄáôá(c—û…v%³›,ˆ·Øgî]6Š]Ìûc³üÖPžËÚ¬«®ºUc›4·ÛÃê)„$¨ùØnp3¿{߀_'Û˜±±,€JÃ4÷ÝÒ Ó8Ïëºr¢Ç ý/Ù¸G]^ÕK-•“íYk‡Ü¿qo'ÑнØEþÁh È·‡\8e´#Ûá ºŸ €ÏÞ¸ª  Îu ¾Ú¦ÛY4êq’mÖ]GŸÉ²‚“¾ñi­ßÐ3¢Y~/l ÊÎj´MuUµÖÒϵ=– ¹C“Ê5ÌJ;t?†â0—‹±.tÓ¡…à ÄÂ{…=UÛëÞÈ6¢kƹÁXÊ "4 .7÷óõbm=¾iá5Îèii1­ÛœúP‰SÉhÉö¡íˆÏt‹Ù—^øï'‡¾;vQÊ:ص(ƒØEEGÛ(ªJ GuŸš%i%j:Z×»ù§ÞÚÅ`c¨›[²í&ÛÂa(’ë?º³&$Túôÿ›À÷D±_ZÄ×–éè¾"yÄ›qi|n–<ÊŠt.Ç&*sã;ÕETp€ús;EpÜÿó9”~í»pŒ®ã¡ð}Ï€öMù2UˆìÖ’¨ŠÁ=ÒåŽöLÛ¯9º`ÍZŠ~ -H ¡Çq¤ßvð}‰J—›%0Ø É¡,îæ)Ž÷,kšyó.3?7t0k@4ô Ûó. ”£_nFU‹\$NH1Ek4ÏÅ€nî–µÿmµ ¢ŽÏÔàÿkÍ çŸB¯™Jò¨Ÿ“ó‡þÇbîýP«îjžl‰œB‘0?ð ]·ôî¶>R‰Êö­,YŒî„Ûûwb"õ‹…6ľ!5Ï<ÚtÊ&ó^%Ão¿“åZ>†?¨ª§èWâÉØÄ¢×B M’¦Mý——ÜÞ²§Ì|ÐEX ‰—Ñ~©wª#{•ÇQÿ¶ËaÊ‹û ®²ž¿ @´Œe¦7GÔ²þ¾ƒZ8MÉ8M{ÒFãT®9奆àû§WÓ _¤“¨ܸ6OsFpò´‡sú q[SZNëYðŠÆcž £‰R!Ľ÷y'ݸ踦ƮÆIïI0ö,SÐB!Ý2ûjC‘·˜@ÒF›–П^*%÷ÿº˜i}qžLa–+xlÝ3@mžt»WTÀ ›ëö×_Ëtfë­pĬnFᓃ 7£òUµå«û*6‰ØŸ¾úýj_·ÏØ–-=6+}颈¢Y—Ù°ÔðPûõÓ6º"˜ØMFÈyÈãÑ'©–U¾vM‘ª}™ó©þõÛÌt±/ŠÑåÙ 4UÙˆ²çNf¥ºP§(®šqØâßBÄÝõìM˜ÿÉ‘nßéßöà;±£M-Ü ±ÐAá2è¦EYhÕF[Û&UÔÿíœ\rEh@Z[ =0±£a0´ë•þÙCü[cQ®ÿeo¿u8cÜ>}è‚]µºÎyÒîý¬úxÌ~ w°ýœË €#cĉ1꣎BÏòÛçm[ m"Øó?‡Çû¿ÞüC\LhªQõrã–/x­Òîùœ6¿/f˜û~½ŒPmßt>ËŠªdW]¯e¼ªIÿö‘í»uê®t¿ÃçñÅ„I“O#Ž¡*¶i[ûvŒÖ5*~½¨î–\äF˜$tò[„8ÐΡ|›ù-àé±§ÌJÛï?ú’ ÓÙc±Ç‚¤¡È‰s⺕ÃN'r雩›~_ïî}L2¿à½yÈ“sã 7o]òt«Ò^¤‚@Ò†àC1ŒqA`äÄ¿?ŠüÆDq«„ªèZ¸VÆ€ñϾwãmƒx.cIØlóDŠíÿË{3H`ž!o1Æ øøfèùìMm¯°«1KËvRZÑŽKI&”Ð̸Ú>]e9ÑüÆ|Tà¿l'î ì—´ÞÆl-ó=‘Åî–ïï‡6‘iæÜ?‹ @y<Iª¨j™ÞÒ/îöEõuŸ—ÑDïÂ,p2Õi–{·ngÉwh/úÃ÷ñƒ‹85ö,6! koM«¦ÈJÓ{ ŒèxQnhü°üsÄÁè“']ýì–Äè8bÍ<´S7tÿ‹ ¥-s¾ UôàÉ$ãf;€Ä¦‹ÃB•¯–gŸŠRê]´¨)M©ŸW3Åp­ûµŽl‘v£EïÜœ³ó!ØF…9¸ÝˆF3O–_h¾í›Z4øõC,ë…ô«mŠÿwè%§ÔÓE↠wžrž•ÕR«ˆÁì¨(ÍR5Gj˜97¡çö‚WEp(õÜ? Q/iG°Æ&à"]+ÖĬ±™ìÙ·}-á˜ÙPI¶ˆ]aPxZŸJ3ýÑàX”tlÈ¢Q±é›q‘3®oÎÙâB†ÿiZümÞ3ržA£ëRÖT,K™"%¤²äØÚÛî]°ÕÂùbM²2g·E†Á¡¬—©.÷e\â´ „Œ^€¢ÏL†îÎ) ù×·ÑöÏ,èÙ› A|¯U¾µôµË¥šÚH¤2ȵ)\@°Ü ¡‚«¼±A¡þ|‚P›îƒZñDZ,*ê½À¶(ű.Tù*POB¡‹Žò7Ë[ÐÒ£Ï2ŒÝÔÏ3¥ÌÌ)ìò}Nò½S*õ•àG)îÒ›„à=¨óxµ{ªP³÷ñ&mŒit¤ µ+º°õ"¸|è=X࿇@ö8‡¡ÍßdÕ²êModÕ#«¾º’‰c¹ÐØöuñ 1ÎùÐHÁ€YD±³V<•ZQ#ähÏã.Û¬…Eš¬ç…ðþuA´óìCøçCíÀožWç5K‹Û*Y^^Q.ÇC§ôs)KbxBÖ1<$¼[x5ÿD“šÏ éQ÷¦I}¶¨cÓ£æõµ<vº´'ík‡ú”¹…¬3«£Ñr­Ø¿‰ÀA¶Ò%Ñ—õRm96뱂 Áðˆ;®or .Ü5UöC…[˜Uzê2¥×døe=!b½ÁÁ_Ðn~Élƒ/k©£HÉR`£âÝ8Ðj6l+¬[ˆ«æöæy^ôsÂù®Æ÷¨p¯Òéø®Sº³Çl ÛVÉ]í°yž‹Qÿ=4~ð!/ œ­1»RL·}™\©-•ÎÅ>µ¿­Fð‡±æ‹³x¦ÅUô0Â:41˦ª¦©ªô2ˆ€€C40[>ÿlï8!‡O,©€1þâ‹*e¦8ý0ã0R¨¦M½µÍ>—ɲ y´F­Y–B ; ëž`¦«ñ,‹ŸA&ªYOHä–õ²Ì©Ž¦,O õß±-—rÔ„nFþÚ  ð̾©u…ÞOß¹ùW×@ûQ¥ºì©ì›ƒç³Q€H1\è…ëÏ×CÌ0K¸e̪[™²©R©=ÔV)MÛŸ×þÞµ·ö Í­oða(}Ý­Ùœ­ZÑ>Š£ºýmÁ»¸øÆÅÆÝP¡v)›ÒÜ¥Ü ÛaÚÑ«,.Õ¾m¿¯g_øÕúÉL¹SI¦Ù’°7è­ŠÞÛ<s¶ÄJ¥KŸÿòƒ7ASTn亖ƒvNÿsJ …²e ”„êµËu6±hµ…Ä!€廾É!軂påS ´ârCèÇÈóöYQYÔÒǧ÷aÿŽMß²<ÐÊ=£Qîœ(8)*i‡óe+F:&°&ÈÐ:¨ò¥>ª1i”y—aÐ…6œ^ŽyôéWktVÛð³ Ñ‚7É®1©Ž#ª,v9_S¤öÝãZ¹¸<޽qÿE×üe:-¡Z£(æ$™º­Ëå¾ÇìáSˆÛļLG°kFW–Û„KŠåæiÝkYr=GEÞKPÄzݤKÀ<žç~tK`Žðíº¯ |Èý ëay å]ŒO ‘¼RÓ¤õ¢Ç­ÝM’èÝ(3†Ôª[‡Ÿ†¼C¨Ym8~ëÊÄÆr!£’`™7(Xþõ×>O¯mÝÿ‚šì‹Òªû<éÒH' Žr½Ê«ð0µ<“Ûð_\"åã+ð × ²2ÎÖ)WEZÖj LÈ|}vØ=¼·—óþ\Tk¢zåZ®¬KVq9º9=¢Éüܾ9§(baãÀ™8ÒpªŒÚxéû8Ù*Ú8OÃ%âÉàb춃>¿㥊!,†ÿÖ­By¦].ò}Ìh©,v æ}ˆ˜úCËïU¸V²b£k¹ÅЧ›Ö"² DïÂäß"ï°J¥ãt ±¦lûYvéöÃZè™×}RmDñ4±w“'ýR'Ѿç{;¨M·fÝxWªb­ÛQmÞÎiЧ¸ëòì„N=·T`Œ‚eÛµ¥Û{iãx*ú6oÏUöhÙÞaa{w>¸8ÿ¡`UÅ‚]n û¡¨b“ ùCqôýûóªø÷Eëò·nÑt»(Ðy°L½C9ó,{ÁÕ äMW ¢­b<Ú4Xª&›š¥.»83ë9”¬¹°†®ÉÙšº¸°bæKiU„SÇ:Ü­ØöÖÍÜ*µmõ>DíË$Ý ¡- »JìLƒ9·ß4m4¿Ÿ_߆æ.òe-óŒ¥ýXêTÊÁ8ÚóÐ#›¼¨—q»õÇh>ÁŠ™ŠJô[‘êM’2)ÕFSžMæöÆ4Ú¦ZÓÙ$~Á!÷¢\,>@!¢Uß¹eYT÷U†ƒ %iI‡®Z!ùòòÿ6<©þ0<Áj!Õê´m¬»²>”Û!Ìôc¢„n`¨‚š•‡È;šÁ™ŠÇ¡LËhúózxr~“çú%ÔyJ 4´êŽ fm_ {A?ñºÓ§ù}AïSŠrã¦p,ú· ñ ýˆë‘pÛVAŸ’ƒ¥­~[Óuük• ´1'»ùƒù©èR•*§#œ³Üú±#£AUuhÄ%îá§Ì*$øÒˆf²€aÙ—†Òf•¦ƒ¦Ú:1\cZÏ«7Ün§þíÙe~­/«IÝ lr¸7²j ¢M_omÕTsÔu³6Ñ €‡†ƒe<Àî—..w=8Ë€ÆP´™m-аn˜®ÍÓˆ’—n…“,ÉÌ”…ü™x{Å®<¡­â¦¡`£™¥>ÐÁÇVÏC³ç+?+ÊfäÀ¸7ö¯DÅožS'òÒn¦ÝózH v6špfˆRª…JöiªU¾úŸÖd®ËUoœmÆ“ 9SBŠsÞâV¯UœÑ¯—Õ íR>=÷ì‡_úeŒ}ð‰©j–báZ8o-81ÕPê5.ÌÓÙ ªû0g³í‹TÌÇ4VlmØþaÒES96å|2Áþ¼à§(!ÝßÒ½ÎÀ,Ó õŽg5‰*©ÄÛ§![dAÊB`èúÁþAU» ”‘?CŠŠÍl™-^[ÅVÚšcÞÍô™y-8øm…DÓ›;à\ÆéߢР_ùÞ–Õ€ +Æ*`}³Ô²äRn~2¹ëœ6o×nÂóÛøì ¦¢GXÑ©kVÊ#E!Aù»”„y‚h?ñ]R;ú´ç¹£H3°è€>=ÎÝ@&OÎ=AÈ/׳\ùС~|ÿä…š3É ¥Šnx+†AIUí"±qp„Qsã ÿjtúìg—}åK; íò˜¬mŠËq?„Ð__Û÷·Qàe?6T±æQã¸&}ŸVY&:9®s¿|¯øöQ«3˜ÿˆÔ˜®n|Ñ<¡HÃ; °TPgÓ¬(d)Ê:¥ôs¡¦Äè_犜4s>€Ò¬ÅWAÜ£ÝhÔm×õO]Û– ?ëëQ\õ>”hŠqðl5îyt:èÉ;xɬj‰ÆÊüVö \¥\̈dºÎµ2}0Ÿä˜èZàâô™÷]Qñ¸óŽî‰Ñët–צû‰ŽÞí-Òt²ÑÙ{[ƒRC Åpoâ’§2QŒÞû--öMÆ® ë+Š×@±™1¨~òð¿~`£Éw±. hì}G“JË®‹Æ5JÍýN‰5 xžÔt:BϺ…GÎù6ÂàÚLŒÁ_ R´Ç€V:”Ê´³=ÈÜÄÜ픘›x„¾B 5s Y#ÑÚ|¨©Ý›"ïò¨ê[• ±¬z¼×£(F9˜{Î}ýS M/éÓ‘©Øß£Ê®RÃ\§üû¼BÍqYtñ Éœwj7}¸ þÀ¥ëÈc5Á+"o¥gUcÊ‚x6úá°C6Õ™ï\•ø1¢5?ö›¯EŠß€rÓ|‹æµŽ´ÑWx×ßîT«„~7LF÷Ã?óÁ!‡»W$ÄùCƒq“,c4FÉ2›Åœ0ƒ]Aók­O4ÇWñÆ+XJêî ®MÑ7Û]"ã:Z­nR‡ 6»8\úŒ×·[(âpƒ@d›zŽ8ëºÏùØn]¬fIèØÇ=@ë—>°wR´ÝwÏjýùùzÛ^Œƒ(„|äÞäyLÉz×Ìå*¼bZ‰:æøt?‡§5óGºôØÞ*°­hî9Êú©Ê¦J'K7ÈšØ.a¨ë¥vw®µ£Ÿ,Z`²„ †ötש¢JŠdîâ©,¤²yØtÍ•xÖõÿa¸ÍF—ávÛf1ŸÂ<ƒƒ=ãÞnŸs¦/3ïÄæë*@êÎÐÃT“ô5¯-7®.44à1´n ìð-Ðý†¿²r,of8qåØ"Uª.º,6«QÔ‚è•·,!U¹Ÿ¾¨"ÚÌ }ÊýK´øJFîJY¦¦ `n+½Ê÷ }‡.<øN…÷9€þ†òC$‘c«½`ø€¸¦D å[Wüˆ¼» nÊeŒr"c]/ pÈ"0Á.¡Ï ¿¯º“C9ÿÜ5Y•ÑáÍ"™ÉþqÁÛG½€êà+J‡tÌ¡ìV’vå´ê,kËbˆþ¼ tlN‘ª/–Ò>Ü…Ð,F‰ÒŒ#Ý&œaS‚MÑqí·zéL†ýǧ¤+Ê»êw~õ•\×P_*K#P)¢û¨0T߃ñöÍ¡HmßïFãÑ Â÷‡ép‡i=òh¯ˆ» å¯Ù>×SF5ßâNÖ£¿<›‡²7³!¤ýn‰KÃ;›²L Y;¬md²¶OJÍ=Eë4×±¤" W{à+º^è™9t_ߥÙ?‚W ¼Âƒú5œ¤)ŒŒàö™-½6ÁWJC>¦pÕ=&uô"T^å™.örëòcIŸîcnˆKCßéªØ³}? ]Ò¶xÖ‚Ó›*JA‹ª¢¬[Ös¼;V€™Á¡ùÖÕÕƒÙ‘½¦ “m4${Y°›è jëÕ|Üîóñ튲°À\O´ò庣åä`÷5`ì-.>ͤÊ5‹›fÎÆz•õ\¤4¡ÌS„P)»»¨†Ìþ%θß¡ÚÈzt E9oÝ4R¾Éz°ò@œ óÆ^_¸ô/èÈ —¾ÌÀÙó5©—{½§C¯Òen:Ã*üãšïÔk1WÀszEk¯à6Æ0õS?PŒ˜Q^Ðwé÷:+†mÏû6äbvá…|]9‡/³å_µ!v.24xG˜ò0µni“Ó’GÛÒASÖ ákPžcŽÙ ¥^.´?duUþ’H9(vµÔPe†Ú%¯G×3zA·Ð¦ï}TÎáL¿üûÛè÷iÖ,b•36Þ›!/W Åui =h¬ú¶I9eZn½ï–ÿIoú;}¨ì;[ãGcÄ9ÔŠ(1<,C3éÁÐ>ËÔœÃi‘ÊÇqŒ•Ké¥!=íùÞ³7ø„°óÄó;OΖߘ@ØU·Q2²Òïדôn°&í/ðÓ˜c°Ê¿¯–Ñ@0º™ïT¤¬O—Õ²×]gCL¹¡u#:ôúègÓa–®ƒí\÷6œ„èŠÅJøàc¦ûfÛtKa41̹ùôxH¿î‡ Šúk#ƒ%HDË´©˜ZÎíHî¨ÍNæTUåRJ£{ÙØe¼w; ‹¥s”R¢±×´EÛ…© tDvÜÖ¥¢¬{3ŠoªyÐÚ¤ýg²áÐÿ;„ÝÜ}¨ê½hÍÂ>§sè…òÄtT³Ä0ÈìSéß Sn ÃÞýo\YæSˆ³B….ô%FT3¨·ã°–¥j*³¦ú²} Á£tÎVÁ…½‚ïù}Ôö-8ucØÛÛNaVåEÔæÜaXH¥øÍƒï¡sàa)c,OÃeÙÖ=ÛõâSeeÍ2$[ÇÃzìß½ yºTêޘŵ~žæÉ³=ôNköx2‚ sÒäë \.:CP«ómËR3<ÄàÂÓKèoxdÌþ¼ï¿á‘=¶k@eNˆç_é¢'”–u‘ô©‹T÷*G‡e‘⪡ª?Ìz6•”‡yìÆr <_˜ç×·q1OK¶}ÔÁ檥UÑfz¬w3²i.¹ÐJõoïaÈ{œýBš÷ýÞ1cì›50Œ£˜è{)zEœQq ÅÈÀƒq&ÕjtÇúÖ!é&'^óËÈ2ÓËÒU¯—‹vâTìC_ª‚¶}7eÓx¬Ç’ÛP*0¥Fè9ÿºz>?ŸâFÒP"Ú‰¢ ¸9yµ”-G…¢lYnV ‹”’Ð% ·}Ö÷öY)ò™ˆ°0çà ($·òsºøÛQ·»Îåá|¨Ú¤¹‚c;^{M¼Å¿Åy”6†ÂnĵX}Nå_> žÏúñ0žò9xÇÇí‹]©Ÿbƒ¨õƒ0P”Ü®+ë%©äµÇÖµ¸ü Å+žrFak`øÚð9<ŽÍ í¾¶Ù¶§Efô‘1B–>4ó»óáü¼¾žG¹k4{U BfsÚ¬ûtQOp?t-ÈQ;tSê•å^Ü8EÊ[Ð)§–7K>a„AoQļ÷m›dºé…eˆàì‰+I¨÷žó þ%*ÀträŒTE¶ÝáÙªDÓ¾&ɲMm™(s¿†H¾éËÀÇÏñN®ìe0þ|¾DâžÜt_C½OÔ( Î“l¹jUc4ɘ—¤(Äâ¸Æb~öÛ|ì¹þKÂV ™dA+Æù0–s­•ÞZ³ƒB¤þ-ð-Ç´‡èÓŒ«Ä—áªÆŸŠ­\‘Ìu“Wª©sQÙýójom ‘;x`±¢`z@T<¸§à¦Û:ñº¯½,æØwŸ‚8UnTR¿qHpÝý«Àî˜òRõ¬;Žö1ýØvOÀƒ×¹–ÔÓ›bç&¤t‹}ÈŽÃ]PRÅš3y¶ºÙqÕÓùKr`qâQÖCÿ˜N eP¡1qìq46¾ŸÐ#:T[T8l²¹ÈÐè¢Ú,FÇä?sÀ‡s›ë_Å#Åøî'Ju™×àik´!())“H›~׃¢¢ò÷Õ‚‹Æò!Á¸Fs;vô“ÉÚ©vÞÓdÐËB—éüÛ’HŒ?,!®Èpį†åþDÃ3­ºhM_0¸,ÈŸã‹q†ÏëµÑâﻬqID=me/ )ÚvÅ­BÃ-8üAÔÓ0†‡;³ÒL›¦éžÓ]¢öÞhöaüÍvëàø‡~rp¥e¬?¬Õ" `E-®ðÂW:[¦h7*dÌjS(í¤HxßE•uQø_% Žå7™"Û²ãBQi¹uíÚVíøëzVxñ—ÞÏ_ʪ„ÝXÉ0®*ǪiÙ–eª¦Í¤ï´d`»!|Ë)`› xŸHøbd}< ¼þ(_`šFpL.€¦ìKðE‰´³9å}«]ѾGc²Z ºJ4=Zö~wÚñvm<™ Eh\£Ý.5(ïS·§zÚ‡]ý¾ÞÅíq,Àg¦` öLV$l£=U[´eq¤Ê¶øóšŒº¾6O©eÖ ôlÃýnžîŠêó~™×½è¦_– Þ5ìw¾ìpóøúèY¼Â¶ž—qèéRš¶e§›®˜Æ¡î¦®ÓzëÖaÆí5éµûõ‘ÃK‘JQìõñ) *£sÐê¬ZTZÐeš4ãÉZ6zÃfMúàùç”å%Öíl>FÛH„Uª²švêçu§m^—õ¯}ÿ‹þn£¶¤CÙFqܵ`gíÁBTÍVºÁÇ2WMx æÛÏ‹Í`tYi~Ë-C@`tÙ&K±Ðë^kAaÑ……7`;¬žJ4 쫱Û×÷‹%baªh¨ÙvH¹¹Ö¬²´ Û$“Úê­–5qMã¶‚ÐÈ|{oÉóÆ9ò¦©Ä¯ÑX*dI’P¹Ek/ÉBÑåS`ÿ†”^4ðÖ— ’ؤ¡b½:Ë3L³È‘…«qʨÔé ÜŸ¤šm¸M…æ >ég/1 ®{ÍCP>öER¯ª’6[õ&²2ðU|Êú(o¾‰\mß>œ—þQݵÀÂEônHs|×±o‡»‡÷©÷ý k ¡ÔèºdæžK£*¡ç+“¦J’m“žºOm[ðs]CbcágÓògæŠSŸ$tÅ`¯%ç·¢˜¶bÑc©ÚÌÄu›ÊJV<ÊÂ]ÃÀ¶ïþ5®ÿ3$z!2:´fªß(ý1OŒD¿Ü:ëÓ`¹Z–¥Æ´„Â¥îãQÇ\­Ìj°”¥{7®”ÜOx«¶¡oÄÀ Œ4ôïZ¶Òa.D¦R0‰òf¥âZ^loZük”Ç þJFÉÆ}tÐáaÒ¨;#1¬(#ȳ(Ös]ªÜ¬‡:Ý¥ËqÂCõŠ»ÇøE4~€á‡Ô¸ ¢11gãØF鶘2Õ•m¡˜òy›.&ÜhL|_ ÇܬmzNËØ4»¨†}¨bÙ}ŽíE¼&û°ÕúTí|²K¨(GÈËzQ‘F?¹]‹,Ú-ƒÄLMQ úÁÍuîçï½ Å4ND¹nKú˜‡Ñvþj¨‡zžt–åS/—òcË €Fr\#ûï„×VíBÀ€n( Œ‡aì©nЪ-XÔ±(:U¨Š*ô‚ÊiYš -ÚÊ@“‡2X`]Ã×ëûõŒÌËZ3“­kYéPQ¾Æeƒ!µlF÷v¿Ózwø…MïŠRD,7M]ƒ²†qv9–ÚBÍI5½,f¹vg´…óî­ÚoÍ‘ïç·àÎá¤[†°ÓÆT¸q«!‹(Hñ‚+DÜCß|h÷þiÜòO@b­YŒ)R)zoÒ‡n¶L‡¹2ŠÆX+²–]Utµ6X˜Ò®9B´ãÛ7ÉÏÚF˜±‰ÄušH{ë1+2ÕoKÊ~Ì:nù…x×δÈsëpQ6ÚF©=o¯@)®æ»RÎhߨ·~™«ÓÏëû”WaYdòÇ!)k5wQÕΔžñ‚Kaù¤ÖA\˜ÿ»¹X ¹¸™æ"¼Ø@€bòý ´¸W¶ããõzlÆ]+e-§Vh´õâu½Ò牌˜ïA¡¦*õOëŠKyxb¤å5Ë/Ñ#r«ž ]îÙï&õ(Ðö ôt.¼†û‡×ûá<…m ™£ÇËLY²*#*††F#>—CPÌ……Ça¯a]­Ï76‹FÒ:€ôô1¡œêl äc§œ`y‰>¨¢ãÖìöµqþø:çôŒ,NƒîZµnòzšúÒi)Y§‰N\à×:ó/∴e^œ'dü0´àFùgóÞdk¦Š2ªÅÅôÏ Þ¯b‹LÒ{ ?Êû†ž òF}ÚsEïA™üë Õ¹àüŸ/ÁùWe£K ä’­v€ m³ÂN}‰Êî·õ˜ù6áü¥ $ÅþùÝ?Õ“2Ÿh½€{³·Cð?/©Ñ5¯8…RÈý ŒùîãÞÑçHWª´ÖMâL%QöÛ¦“l8K¾s%7°™Ó“tžW „®YM?Zë9S«RÑ@ vþß”õV!~m({¿Eò¾™z\PÄ»ÄAfì5­ 3·Õ„åjžìh0ê!ŠbŸ=óËð…ŽµÌà©fsú– êTÜó¨SJ­ë4i™°ù¡¤ Öµ®_9á…ÛÊæXvÀm-áq¬J5&´×"WKÔmÕvì!(Ûw†p’9Ùôÿ¾€í(–q‡`;8±Ÿ1šÖ´âvŠ·8ÄrûOkÞßUÅδùá†3ÒÑWû|ž‘Ò¸iWÊ…'cµöýWETuù($¤î.ÄG¬[à¸þq€éd`ù¢¦»Ê5Œ{êX½¬Ì›¼ló­ìÌU¢½ïaªAïö¢ñw12y¬/CŸHõꮇmÆ©Tíô™"-Îè>X³èæÁ©Æ  Ñe¼\7P"~®&Ê¢ µ„ómØÇyØÒ5Õ¹¿þ¸àÕzU»ÁA¯f1“ã¥õÒÖwê\Ï·mß±œiÍ@¦õÚ`½[™1‚%œF* Lت©.»Mgk"ë¹7¨ý#~3<:ºÎL7o6S(é£H '¢v„Þ8Mêkã¡©ãŒþo³nL÷ʬë:0O î·Ûý­ÓzæeÇõiaÒÏ.kÖ¢ ·Â°˜9DèçC5˜E=&àÐBÿû´<“<ô}^Fë—Âf©;†ÌµÐÏÚB§E\u¦¡Li'*r/¤lÊP‡©Týàç=¾×o“Geº€äicœ"sP †¤È»ˆê!³ÞÎìâ™uðÖRgõåÇ®nNh(Jòe^².ï3=ëvL×VV €î†/8wö¥RûþªGƹ-²2ióÞ®zléðI÷’£oP!,Ÿ¡fXW ó¯ úOùùqÝHó<ßæ¾Y«9N)Ùã¯XÐM½Ù0s¨×Œþ{•Õ ed¢©ض0¬ ¨õ¶2|ëÁø)ø2þwHkÀG•2&J›—-Ù³áè UŠ &¢ºaxµr1—¿Â @‰¢Ã¼ù¢(‹:èˆk³dàÀËâ¶uz_ùVÖÖüæV,8â$ÖœˆáZRyÜQf¦Ç´#ã;°6ÁPüÇ™Ûí!>^()vWÖ…Ðn˜y›,5 ]#ªéô;hE›ž° eð„“"Zs|…²2¦9-»ïQD\U¼(ºô¨»Ö<eº9CªÚ¬ÃbÙ¿_/:Úˆ›É‘è³àÊhƒ2Ù-of*ˆ"ÝQ<3ï2W‡’ú¾tnŒ{Ü1d´Ø&¯H± 8=ˆ-Hº¶±ZªL•Ë2mëZÅf[‡!°Þó\‰À±_ººÂ0}2å²(º{§f2UWq¬š²ìòiL‡‘K|¶@¸O¤w*$þû _ž»ràý e•ŠÜ®¥ªÅØ™# ¼ÛƒöÛ²ëš(l_GÃ…ªÓ^"¬ÈjeÕTìµÒ]ÞÆ¢‚㳪 Àωd»j1 àSÌþD%œ¥UÅîDcµó *Õö!d¿\×`¥ø2¾Ÿ¨ø\Ò‰ žûɦµö’ÒÞ=Ùú&ŠÖldph¤2ÒN²}»]ÐôT–>ŒŽ’5fD×ù SP› (˜"`A†Û>bßz _ß×<¢”cØORƒïy^¤ô㨫Ö]h‚”ÚA‚éÙvÐ+¸ú)CøÒtFè))'2Ò;8¸h_ëjO§RšÐøô(—Äûóï¦+÷aÃ*‡M}î>†ñдïËf‰Û.)4Ë1 ”ÞàýæºÆ\8¼ÊSÃñiºÃ£¬›Æt¯ãa_ãbßÖxŸ„s ýJ5Ã?ؼÀàþ!³nO6ÈCîA»„Ñô­Ñ"afG'D§ªå€tÒ`bêÙ&®àu^%¿6\HP¸ ¨‚6FÛjnUÕí8©v É]oÆÂ/€ŽOHª ‹Ó›süË8ÎÍZű•$µ¢Ýæ¶oÂ=Ë)úï±îF©CóÙmK cÀÛ:½À´Ž2#ÁСÄ}çhGÞïo [aErC<ÉØ™²×¹ý;ÙòqJöYÕ”QÍ$´ôÑègLù••u5“ÜÖ/~ äƒkaqk„! &·zÛÚ¸^dA8I†˜ØžmH1þõþ€Îå—p&ª"‡2 ìÆ”(kkÊ”ª[ÝN²3vnð+3h^>É—ßü8j0¥£ AÊR¶šw0¡ÂsWæf§çaž çÙžA¾{öGZýu|^°·(º%»Žz[ ü& 8ð° oB§ÂûÕ ìõ|½ØF9‘ñjËè:)9âxÈ›&×Ah;¬c ðm©½ÐølýMx“±LÊœ}.‰¥¾©×5^ØYE—Zõ²ž‰ n#ȸž÷ï;br¡ }~ÑÁç¥ÊÌ[µÔE7VQ+&QrÿŸíû¿.à¨v¢ãé<ÑP§¦â:yžaòò‰¾ŸH1žd06ü!H±<×}· ;"û¼-!¶´m³¬+"ծݶ5Ý2v•ä¬!Áö=Í <˜•u_o$Þãed5K±G•®ôà”!;ŠºÈ°’B˜4Aåp×eHvrUpE|¿Øä“n¸0 “*¶çª©ö!ß«nH‡Tps¿­ùÖ „ê—×u©Å`nŠ&MÔP¡(k¤¸£ë-VêP<¾µÉ{«n_̆À8‹®Â–…! 駘T?©¤èó<žâ)’. «=ÈÛùH…bâj²‹m"Ga­¡ÓH ‚bwqSUݘʜ)¤’ƒo|›Ðä„ö‡ ÁÿPá¡Â¯Û¡ÜEˆ¦#åF¬\yw϶÷õæ1Xæë³’lÍCjî<ÙŒ®£^æ,¥7JKðæ¤mä¶ývøºþн³²æ4ÀºG]30˜»¬j&Ê TÖ¯qF-«z¸lJQ-È„õ>¡Â:±ÕnJ©dªwÿ,w™¤Ä,”ªªlZº”Xð¢®ó._Ëy*¥âNî#@ÀogÝ¡‹ uPxJ—­R¤QØ·¦äþTÃÍ ‚RQ=My"ŽAZÌþ0±XMOŽÅäufg0-wØÓVA|fôhB/ ] i^ßS£vqq÷ùâ9­Œ´ÊŠo¡CNÀå.£ `.*óSÒÄ%þ¹92–ýO_ÕŸ_ÂÌEžÏ.ˆGké€0ŠNصI^*½S×ÒGçšjÕÕ,g»`3Ð¤èø¾fÞæö°@ÁXÆòÑM¿Û°shÍ,M𥋷¸m¢*öw¬zTnxô0zSô?óFЛŒ¶ö|­½©õ<+Q²=ø âH[”üÝNÏÝgNÈ ±Xp^Ë—µ"¹;&݃L{CЮ™“ì@õí}#üÒxÕ7^;Óx­ª"êDwôØ&§¤ÊænA¼Ü¿_žÞ0¯÷à[ÔðM6ø€öó4ìõLF&¬;þ©¸é Ò·6]xÌÞ„ÊþýØ0ºÄ4¡- ˜Ð¡í¡ ?Ís«éí-K£hw/ë˜çí6LfiûfûÈù½ |û©\ʺ'³AE<¶„70¦l†XétÚWWjÓ]Ž]©~M‰CyiX'ab}1éžgfqÉ{h=O£Šq›ÖŒÈdÉšVM¬B–Gé>}rƒÆ­ÛET‚y&¥Î10¢²©oe‡ÏÞ/ª®÷1Þèic³& †¬öÁñz#XðØ0¾}‰M.wk G; ˜¹75ݯû@ia•˜ÍÜnwàà ­q˜Û:þß™‡"ù_ÔìVÙ ›‘Nd?ƒ¿£hÞ“Ò,hÁHÛ| f-çTómX Ô{d)_Š,Œ’q)—>ó¥m·lj’íXÎ7oXVšŽŠì"èÌRÛ›E¨QîГu‡þE ÷³EMe[¥s/A æŽ}Ãl%4ýmëtFwƒéŒÄŸ ]rw#Ãû\aq¸ÐgŸÐßxqwƒ>ÛN9R:vm»ê9š*ŠYý\ŠâþaFúÅ;ˆŽ,2®¯Ìwa€‹®âBcÂË2ì妵NÒf3݈?®ê¾W•¦ú“·Î=ÏF Í9Aš*U¨µÒ eõ{µäfÕ„cÏÃÆ0µåý23_Eç‡!‹m˹Ž"©Z‹¬¨{œ‡j5D.: À½ZÖéx¹ÚVî뀘Cu ÿÐ#…d¨.²º/Ó"ÝGº§_׳NcÊÉL&¤&гf3 yEƒZÕC:ÏÛ¨³*®epþç§<ÕAî ¥ì5e¬ÂBÍY¦²Lá M.•ý—_}¿$¯À2@_å›u½!H ²ˆUŽ8¢º]©"߯¸ª2ýmUW˜Ñ¨,XËýT…rDsÝ1»°Õe¾ë|)}ö­Ýòî·%o¾ÕÁ`¼JõÍSó^d<¨î“J`î¢_Ö»‡nø™Ê€ÒËÂ]ì¶5Óoç¾^Õ§å2ô[7­Ç‚KæQ­¶¢ýö\Îö5óé¯ýë¾_òYÅq‘7MçÃq·€Ã{”·‡žÞÎtæj.d™œ#¹dÎN¤ýªµO躟¶)˜ÛgQBU¤í›ækp ÞnÄÿÐÊfkÿs5ÿv:¦=ÂŽûf!¢ESõ0¹¤ªãŽCªc=QEŽÜ¿4‹‚®m#JÜCj×}'48ÖÛ!h^QmE£³‚ ù\dÙ·«:Êžåÿø¢[&ÿ`ì•¥ÿý#$ÒŒÊfJ© ½$á²ÛǬÖ8.K#¼SÎïctDŸW ¯òÞÂøaBŠø‚ kcàß6^µ®Rî_Ój–{£ô€Šð›khÌŽåÔÌÿC¬ºJ‚aAºˆîôQî²`¢ c›¿14:EÙ0”MŽcU´qJjµ³P8~+åZŽ”j˜‰æ—ï‰_º/¡Ñû«àlBÉÑh €sCq¡Ëu¹Òm´³¨ùNŸOþ¥¾»4¿Ï1k]O½6ÍÚm`,Ûš¢²7?Ζí9UOòƒ{Œã÷dô8j%î=Ñá›§>ϲ­¯ÖHgJí/ ÚÎÝ¿vŸCõ]¤tÝ5œùcR×uEQ†J¦~ض<Ë{@Ïÿô˜ãÛàqÔß%{³·2¢ÌkYÕíñæ»ø¶ëÜ=X‹;†ðÁ¼|ëðE2È„¨XU£¾ð„h/åJ•ãuºý}ÁÛEjƒ©<ßìpœ‰—ºÇ5P¢¢XËî8f½Ðb ;äZî'+ïjöþ’ö4íê½ m„*éîKŠ*éË¾Žºdç²ë´åñpù˜„îEë‡)ëOÛ¥âº~7CøR¡½éÆ©­f5.‚ýÓ@Iƒã@öÆóNBøåè=Ö;ÿ¡ š1Ú“­Ìº®(H穉î|Ø®Ž² =œC'ƲáÕwŽDÿ}ðqy…Qáã! Û Ïu3B·~\—uŸ·r^ôF MK‘Ìq–ÁvvSuµÉn‡‰˜ËÕ›kF¸ ¯&ÜÍ1¾¦›]‘7Ÿv ug½­Ú”,ˆ©ì,°VÎ>ý§÷ÕS˜ñPRÀpˆŠbxRPPÓû¶uV™ëû7 m -ö“ÈuÞ›>Á!‚OÅ"²FÊ(TYÑa—õ†} ­6¼¿ßõF#z„:ßž©û¸ [£OD©ÿÐä혥t«\ñ]+‹}NÝ䟞YÌ.±$،ฦµTBƒ¨sÝä œ©:­ö¹Ú&Ù ßBqÅÇ?•ûi4ð T1`áÆI_À¡À*k‹\er˜îèŠ0•:EæŽÊâS|?Œ«KYR]^1µ…4/ÀzïU´­€º˜QêߺýïÒ^´­¿ÊzɵØT ïÉ–®Å´]¢,Þû¸[—Bÿ²àÝ?囿yÝ {бΠ廥­gôðânÑÑPþ¾˜ÿqiƒÁÔ$ˆË55›ÎK"ÏÚMùš~÷ZWÿíéÞ8¦e¤Å (\áAwBýK–Òmt÷eÂJÛfÞ·|ÿ*£PÁ­Œû R5!¦ Pè3< /¸*„Z²%¥Ž .‡ží½6™{ •sò‹÷îB¬öÔþ¡t{ÿו˼=¶Ãèºb¶,CHf«47=ìû<ì‹Yϳ)µî!¼çÂóþºÖ0Û!ÅT@ºYLŠ1“ˆ·lW:î§^v¡Ã  ªs.wöþ ðÛÓèw‚EB÷>GD+x* e©)^çM¾ :ã˜þB@É,É–½ïÂíûråÉ+XÔþ`û#¯PM‘VmÞ×£yFª°(uÁ1ÜÈA_¸ðî;øå< êd sïy/èR-¦j¯;`y¶sCûÔsû@Y—›êÁs†(Éð4ꬶO¶<]û]õe“L$Ñó lŠv¢ï^ 4lcÔðõ¶Œ€û»EpGm±©µzÑѬ‡«Ý h¹»0]P÷ï¿ÙP?Øï&CáØ:Žc4ÇÕ’˜-k§;;Ö‡ý(eáLR8†^›aÝÌ‚éz ÂÛ¡kM/Ö\‹ ¸ØeJšhÖC;OZ¯Ó WÖîÅOżUQ¤gÙôÀe‚+ï‡ýœså¬>¡?þŒ?`ÿ*nBÓ®¦m-ušL…9”@…¹ðD¦H~$kžû¯k û¹=žOiˤ›ˆ÷¢˜¦–ô÷qn©þ™“w· |CkPlï¼Ñ¯’Ïè9Ég¸ãõNéŒçÒ²·q·”sé±+YÛ忨T\8î]ìÝ ÂeÙà=L1¢?Ùš©Šà¤Y,F7$Õ\.Š?<ùÎÛEæû!úå¬âûQGšfÏg•gŠVÎê(2(7®6@„-Cøðg¡ð°o9ÓƒDU‘vb·wËWC¢ÆlêÌ‚T¨Ò˃´gŒ <ë\ð.t –óv'i9tó¼v­û6mË_Ë®_Ûëµï]Ÿ©R=]møiRY’©Ln7‹¾à1h*ÚSê¼ûaR'3J•Ù*¼›äpÓÕ3ŒïÒ½Ëb-í|ZЦSŽ‘Òoâègóýi¤¾Ø.ªfó<Ó|WS5ÖìžWšô ëißöŒoåÕ•“I#LS@n¾a®±Ø ì‹R]WEc¼öãšÉz,¸q£Oät;Óþ.]ÊÇ7½ØçK🫒âÚàë­(ʼ£oÅÖVp!‘5ƒ› 'J‹\3²ý«Íöç×÷áÊZòŠ5£nÚò±ßÓ|¤4F÷y¾Ë& ’‡Ò~ þÉÐÞ>ìýn²ë¢U[µ­i¨±¦Š;H²vfI@ nð’÷ÌÅî\-E_oŸ¸ÌM‡›ñ2¦Ó8RÕÎc¡äUÚø07,ÁaÈáZòÜO"²xG.Î"]°L½eí2Âá¯fÓ‚;41(%¸”dq\h}`¿ž¦”*K8œXÂqÙ)™öºKMw‰o¥8ÚÞvp;ÈÒö YÑSį¸a.zÜó¸´@L$ÅN{G–³QÙB-:Ú¦d_Щ¥±ÕÎ äö s~Î`ò­¡›nUTõTé"¥œÚ]ÔʨǼcÐr733BfK°këùªd8O‡qÚÚæS•wtÃe™Y0€„çÁPÞ|ÿ~‚rG-rl?_?5ëIwl­9ˆ(wš6ºPÕÒgô+‰‹˜…ÀlÝaeì.Äqø~ºCJj™Bm~nCÏÈ æmº÷ÝÖMàïq.`¹^h‡”ê{@´Ü˜ãý’ý¼Î,°j{º €aG‚Áx#ÊÓ`V‘g´sf9*´ À ¬lØþÖ…a¸¡«$ö¤,†û‹5ÎÔ°wSZF‰¢¨“É æa@Ü=¹”k¨Ú!÷ÿÕa#hÇË‚tÞ<×â¬ÏØ–Ý?Bìs£ððd]ü *I˜R±é dÊÍ㨠t%™(ÇH´¬H»Ps(s®š‘Þu4þxO8 Æêœp¶Së´ NÖ£¼‘Ä {H÷;R>Âæ¯'ë>Ÿv:sÍYש"ú¥åU³›·ˆØåcv-µóÞ–}ý`Enà÷Ñà Ø=MË´Ïé鵬û_ú¯bXQ#å-ª_ûuU¾+¢Óa—Åv¨žkÓ‚Cðü=mùç’ Óo«AäÜ ¬¤ÀŸ‹…êF¦½ì^J÷$ ^ÆnÁc:²ìŠšŽËZôž7%Ô9D`¡Ew»6cƒ,¥ÏÜoô:6½îë¶ê½˜ç~„ˆ|6Ó^+(¥i9MµD!RÙÆ§à~ !O "Æz—ßÌ|j.DntŒ5 Ýí¨»8ÏÇf5oƒ®ã;ääA>5w¼!˜AHèëèsĸãiÝ–ã9¿ºHšq†·d¦Æª3kz–㢥‘¸7¡õÚµeI%cEŠý&öd̦êÚ|Ks]mU7›÷ëA,Å»ßa³¾¦«K F? Ûì Ú¶°++ä™>kKggdè`ú¬ã²4½é!š~ûÑIwdÙBC›H]3/ oFÇ  +Ô€r§h…k©þuIËúãzý3"+¡ÇÍÃy&W·NÃ먶ù÷õÂËzxªUJ%Ï; o,C£}iT·ÓþU9gæ';èºÀU©æ©ýøÞ‹ãF³±Sƒ,nìFL@Óуš"j#5STnÍ’0(ͲAÒ~È:|™´2á’Ý>+¾¶Ôå8.ªk¶ˆ®IÉ­Œ ò!üCÔæöqE~³œ@úÅ…HÚ KK¥˜¦z‹Móûjö‡öè7P´Q –ŠFvØê—9ŽwÊq Bk“±ôþ(Yà**8î[ÿ*LžäC”QÙ–%}ß<Ée ¢¬XÒ}ÜyÁ-,ëÆ²ÿ÷£§~ˆÁ= Ñ´iY}”ß+:,ªi¦x_ú¶hãí÷õ‚ ïRSq0»èf óQÃCÚ /èëKÕ/Q´c#[0ùv÷asjPüÞí «3ƒäŸ?ºvÈ2 öNhÁQ†ì/¶uK: 0 çׂÀá' çôß m˜1ÏØ€û¢¦Üg+s˜³5,ò%ê@3½‡®[‹nÞÚµ”EÉ::BàjGê ÀëÁ²œ’U5hsE°á|3,c’á[ ËÐËš ‚øT‹ºP‡“„Ý}sJXF“ñjRÃA(^HØîk®·¤KUܶõðëZ*Z„úÄ<v[x±vw!ÒÝÙ¼MÓüçåYÒMŸ /¬R-z÷ ²gcñã;éð}†¼’@ª Ÿ4¯³¬VM2沞E•6ºÇe¡÷“iv–IˆÍ”¨? k9úÒÅ&æU]FcËf2w@/঳kÇÈÂú¶û Ûýúþ1>ôc¹_.µ•R©Þãz«µ6pD,È"¸”#[Vl;ïKöet}ð=Rº»–âØ±—áÞ¨|ëúm]jŒ£ø,ß-0ñã$êö5ÿúg²4ó(}¾;(Ùp— nÖý"Ksš7°ñ:†ߌ§¦—xl5'þ¨Æ¨I÷ª‰uÑά'/²ŒöN5÷½ÛJÞ§ãÈ7¥ñIžc–Á  ž÷Ö}•­E›Lj饌†C¢Ëºaè¾üää~Úå k$ ìQM‡%Ò”ÎeU–ÍY<˧ƒ€ãðåvÂ3B»ïðxPEô€ÔN×ËD¨«uAOÚ×ÅšŒqg^¥oßmn¶ï(Œ·ï$Ù³ù ‰ÆŠáÙ˃,Ѹx¸.ššQíµùÙÀ*[Žç¸žgâî§:óÊÕËsÛà£Ê݆´-!ÃF;rš—y™ºÄªnÚ4ßtœïê©’„‰­«x(ÝNå·m.`¨Lîá<¹„ŽUÃ*V|‰÷TSÕÞwÅÛLžC taØrŽ4¼w\EMÄKR`@šêƒª…ÈëPTuR'z/20ƤÁ{gITÏ·-Ë>PÎýjìÎ ÑÇ$jì˜Þ ÑhVJÇæ¢{ax ß¿Š¸ áû±ÆœöÙ¬çS ì`>AØSeþ2™Gý°8o¸“  -s›ìeCµt’Méš$²¨¸€æêfE‡°®õáp'ÓäË#ö(’d¯*‘CQ¶6ŒY/ ÚàJÜl˽CîíP>¹ ¾›ä¢“QtÒMÄO†©o×ñÒ«Uú'ðömÐT4ºÐý°Ö~²Á÷´YÂRøÁh̶@ž”•š8œ²  TÕùoÙ›õ¡tü­ŒrL‚ 7Œ·;•íªÆ6š§H·³YÏÈææßhw»o‡›+Ô× º;eß”Aí%ýînŸFIBïÐi èùn¬~Ž/ÐQÞ“ùÈ;@Ù”mxÖ¸£Xz/»Î<$ä’B´óm4°·ðsÀòÈÙ^ 5ü"!dÍý;Üýîï¡ÍÛ@?/ùát§å° fcN)æ½o÷t¤¿ee$;DZƒgY>N¶}":/’©`=¥šŽ‹¼2—¸™Ñ5¹4[[ƪ-²réÌš÷;3d\×2N/øt0ÊÛìËP1 Hœsà”Ñõ˜SíqŸË‚´LÉuت¾g6— FâÃ2c% —o{W¹*㥂'•¹4wh{øÅÌE¼w{óp_ Qv_\ \S?pXǹ×t·¬[ºhdUL¤aWBqÑtx€Y»b^bn,+€þhaŒ.÷¢RʨªX›ûÑñAM¥î†¶I¨ìÏÿE±Ãò³"‡´ë—ñáY·-FÊõŠbœ'³ æ’GÛŒ’!n}9<Ïomœ’2ctÑÞ7SOos«ö½Ÿª¸•ëòX´…ë¤É\oÜŸÇãox½Œ¬ÄOOýÒ¦ñT™õÀC€Œw` à]<ÜÄGP îbXÀßÛ@ÝW]BÁ¿'úBæìº”öogœ}3Ô6ýóÙϼ¡ åªFî³mÜ›y)uJy‘ì"±7Ï¡sãY˽nŸhLQ‚…° `Ù¢Ä8«a_«D—ƒÉù\ïæyAzp¨ò…Ö‡ƒàÿ²ÊKÈBp±=Žêî! á_úŒ_—fªtÌ”²êAñë´JAqoª1N›²v%x¶_ægzö–†7î†<œ“)€urä¼#<¶êEN‰ ßt c=ÿfEþ‡ª–Þ6Q⎓,ƒnv/L·žÝè÷jÜ‹yË5e/艞¡ Ü é)‡ï€*|2 F,RÒ@jAöΈ¥hº¿†!šç~ÑÍ$#0kŽ?\§ÚÍ5ß¾69yÒe5sŒ‰U­ö,§-³ì*ÊŠ$‘€.ðµ >_¢û9£ãYvYSîÔ6ŒáÖªVE7¦CI×m.ÆF´^Hù²gß»kœEy{E~¡ÀŒÐü¥ì„6¶LÇ—¹Œ÷š>÷2Ïi¶Êä’àÜ(q á|À+âyÎ8àGÛˆH$ô0æ%å™Î6¡Ý1›ãjУôÉ:›ÉלøÓ`û¹OÖ (–±ý”'[Z›ÀŒiÆPs]^;ìÖý‚J:œ 6oaO6Îi‹º˜¦~_ë¾¢y+ä:ôéÓj¬Ÿq\öíSÝ(3—„8+Ûm¶f.9´z­¦f-ºÝ,ˆ©AHÙåÞfrj_Þ¿·Ãƒ)-3:¼ƒ:á¶Y¥Š&šª)Ó“pBîÐ¥¦·æ{è[†oÔw§“wNp˜…~EI¡o.ª¶˜ “—üÏ)Ø—ŠšÊ,®72ØŸ² Û‹6MÝ´.QÍ^wÒfüóÓÍÜUÝžrî(ó¬Q¬öŒ[¥¼mmÛ&mZt">÷çÕ¬ûµ·¯Å E”Â1sijbBÀ÷hãºèÒnû¹öÙ@˜žñ‚v1Ýt´ŠÅщõ¨ò!Yæ¦ÈšehÊéø$tÜ(Ÿ½¡Ó}++^šEFCâ1‹ ªvF‚Ž3;:q–m¼íû.„{ಳ˜M{Ñ9úOèŒH³>Ó–d úûL–cT[=Õi?æñTo úþrg€â€/@ÿ¹½åخⱯƒ‹Î.£´¥[ñm¦Ó§wµP È¡4/·,áiMp”]÷p»}hc›žTàòjȧ-ï~É)3î»8žcùÉ!in1äJî1m¿xEèípèæ‰µ8“3w•²¤²jTåq¶™ÜÍ×½Á²ñ°Å »ö_Ïhå>M!Í츺åœa |º©¶í¦¬Ï§¥¤ùèƒP‰}R÷ïÅtìÅÐ}mã×Z¶u÷­Säj>n ‘Š’B¨ËØîm¬uWºnØ änQ r}ƒs±¼O:óVÌðªmVÜÓ|ßé4§³®ÁeƒéÂGæÒÎ)àþ7(ú:Ò³ljHÿtÆ”†ª z±eõóPl² m9€ ôyü.B=¯ï§ÌÁ*º]Õ)þÊs?Ìs’¨yަ)3¿m °©<=üò.ï Í,©œ)a½î “ÛGÕîh‰î"m‹é}aÈ{RâÜ>ü''ð{{þˆ2K°k‚ñ‰§-š¯õ¤§Hÿ± š#†½àP0óë§Œh¾¾Åе*1ßFÀ[ç £e ™ÊIMmÂF#lH™hŸ'>Å'm{Ho,|kËqwz€ÙK’&Šj }JVó«ÝIÏ>\Õ‚ó$›gÔ"ÛfÜrê ­!ºgÚ‘zsÓ$yŸEé@SÜo[&KÂz³môC µÝºÈ6ÿofF£˜™HGÅAï—2ƒlvÿÑi´Dá(? zåQ‘/ñÖ×Û8Tݘ µ$<þÜC€¾wÑýãž%Œ(è´–É2}øÔ”¸·Ë¦1bRùÎ*®û8^ÌþvÑldßx7¼ù§JãGbõ2­K\¥ñ«cùÔWI¼ÑmD¯5ŸŽÚÞ¾¡Sr¹î•w'-NƒjÊN;¡&IB@¹E§öyMÆ-*r³ ‹{þ곑\A\é•z¸@žÏÓ4PÙq¨á®ÝÔomQDk›uÑk„¸˜±¦S¼ûÔÜô‡,;Óå,ÚAN ÃAÚ«š¥“m—ʈ%Ù`ò!‚–1þeÑÐižïÃ^¯D›ôâÎ\IÇSUÓŸaÀØX™êÝÂ,ü~ÞW+ Ê£_O£ÆÂ<мa¶©¨&i™O+¨\6¡Œ²Sà ºÆ×rÿº ž¼›‹à XTœ³¥Y aûBevJ ps,G ¯eÜŽiuï:¼„9ñ—ZÙh2´n÷•.M•õëVý§õ.yå¬ÁÃÓ˜¶’­,H—l2ö[Vg{Þhó™dp`s˽9ÿ_P¬æ‡\z­_P¬oÕœ'{ÒðÞ)óÞHM}ìz4*óDwãÖ÷Ò'´Áäò]J'áà _ÅûèÑyÑõi¸Ð ‡®ÏF©JB·ãZþ¶œûÁ 15n/tq¢kS‹,zš÷<›2Š‘•`%ÿ¸ž÷Y6@5š‚K cZÜßFÕf,Ç.K£¹Ü)I‹‡ýX™Êæ¹&õû R’‘Û3£qd{Ìr7Ì…Hí”äÒ—Ž§MF^Òº6Jº‘™Ô·èá3ÐôŤ‡2)¤´¡í·WŠ.PØ|›^g¶ç&jPh-0z‚Ï3ÏlwøªÔYÙÍmûû‚÷ÏVÅ÷×vx±ºqk¯j­Ô²6KÝëuY0d¯W6"F•ªä«Xl¼¿dì”±j{ê¼u’멨Ç}lE,.Pp ‚,v`Y'ŸäÚ›ùùz{–ã(£æ4ê@;]܃ZÓ¨ëu-,UŒ-pC¥½)Äá £™‹À„HvÁ4$V¡Ùõøk{ì¯×ƒ‘]”Dëwt¾§r›$iÒIÌ´} Iõ(UËvð&|_Êe¢Èä1)€ÙëX»tþaO‘qHâ=a gùÁ݃íÏÍ ÛÌ?Ð%¸N¬Ò'0…¢b›o¾ÝP€—eÔÖ•VZf®´ ]ïÀ!˜Tï4$’úƒ1Í_C}{HX±ò@ŸkVÅåGqKQ¦epF´¬Ã©÷Z0ƒÇúüzý\#Ù ÐmÉV5«ªÚ¹:Óµ9sñ)¥<¤÷­¾)| e¼‡~ M$Ñ<íR”§–‹RÛjÞ£gY–GkA%åpÚ¸NU^â&Ç'³ç1’¸ÉõšòýB5ºÏ"Ý›oÍò.Ècöá!ã\Z#ðâ{<Ÿß°Åàny¨ê¡52îz)ö‰þ/u¢G3°’ ˜$xŽä¼ðþ¦# ú Ååx‰À¸‚/G{?ê¢VcQ´ŒÉo«¡šÿŸää +èÃ3PJ`=õ¤šeÑùFp<›¸@EðrгÝÓÄë~¡ ±h)®ÌM*‘[V½•aýÞEåžÔ°¼™£Là”P7ºQ:@õR蓟ûGc„–×f:%wFÀŒäÑÀGµj§­U%e«yz¬é £èxöÍñýóA¯ ÁÅY‚ŽÌ§³Ä rœ%:³1iûѵÀ‡ Ìã4¨ŒLCÛª¤¢QQ‘ØFQ!¤dÏ÷ÖcÆ{Њ¿´&_l4ÿd©ø¦„º£Í,¯¦¶jöTÑW˜:Ø æwÁ™õÙoÃJ:~ßßÈò³’ýØu ,0p‚ƽ™ÒxÍÍó6è ³¿=?ƒ¾Øf7îàJàþ|kÜÁ)å¹}O•ˆYУ€×=Ò©ûTÈVÙŸSwÞÈÎ÷§î<÷$)“6Ÿ#ibPãëðk»1JKY‚Ûs][Ù¹ÃQw*ÛkxÅd±ùÉ0Y‡‰}Ö£ýX§I'7j´Á%Ô5S;–±§\ KÚ*]ªÞD°?.vû”ý6ÎHh(@#ª‘VRÅn9QQwQV«Jd¶(­óo6¼a(á;€ ïí<S)~¼’.|Ô€7BF¯Ò½Ý¶•NÉ*wõŸVŒçâ¤ðx>x€au+³vUoši®÷ijʤ¡ó[G²8Lé߇~Œ{Q3¢pCsõ—(ùE«”{†‹¢:Ðezn£ÍË XjA«Â2“=ÿ♊ñ#þ¬Ù@w5Ý‚@ùw¬Ù UY³ï¿.æžú6³0¯™5ü¤ÓAÙÄ@åÆÈiè8M8n{F?]ëÙˆ‹"ÉÍr@ºèåɉãÊ: Ð fæ èUÏP(º 1ˆSª_òmïÕ²(“>Bœ# $å ÓÏuëãÞzéçÑÈ.M¤LûžÖÝÊKâHÇ’ÑÓ#Q…އC\`Û`ùÙ vÎC<Ãì±â|™­Âs­š–ÂÔ¾¯IË–¬ø ËE*„mÿæžZAï1½Êó€8Cƒf®´Èö­Š«©îw&d=Š6.´¼ÃÇLýïò7žÅÉ „¾kèw¬P^(º¥ë,î§fë«h]dUä`ß½Kàÿ,ù2žNA-¨òÜ”-S§’¶ ë!eH(  :p§–ïbC Ëz»o<F&’Öµ«ª…Dd7µÆó²×q#‹yÐu¡J$òf_Í&^”ÎÁ>ÍÓ‚«Õ£'ºçS^/QDe4½LÉi½¾òÌUü·ÑÁ¿/cnåIüDq‰*áÌçØO¹ï¶ºŒ›v$«sgÎîM\üLßíæ_ëÕ§6~‹)#n ÿ wH¢)AÒ;6úZ°µõn®w(—ë'W x²ŽàUW©¨êL÷4§eÌdMÈWØwüd÷š…Ä“xã|ÐÜ tdò¥ªå™èahE‹%cGÛœ›íÓb¤Cº¼s²|%¬>Ñd” À¿ø"ifmѤI6ìE §Áñ]¦]°ïÖííÍý l|ˆ•+*z´-»îDsRî­c[ÔM’Ë®ñ=ˆScŒ{ÌL?ªz(sвŠÕ ¬kÏ|"*G«­SqÓ†Ù*°@t”Cˆ¤ŒGx-/„,ø#3UØ–UŒ}ÆÀ`ÝÓ©ª§.íedçÀ,ü Ïrîªu k1¤~ŠK5B2û¤ƒ• ØM²§[ÑmI—M¹5ÊF(%¹YáQz;—®ÍfbhÉsö2í¸ù•P-°FñµšÎsf–£ÝBÏçÒ4è9ï-#-åo¶ÖeŒ2Z Z“ç‘1ÊJEyÞ¼tûj.˜9²{'¥bŽuÚD^zU/y„Yßõ· €Û¼Þše®ªœ2÷ã%vܳG§åãöÂ‹Ž¢F§ûÉÈFT´%€)Åž,åy!Ìö?/yõØùÚÐÁøæG¤WÙ¡ËÒ›F2Å“U¡+¯ŠLØI^/ø¥"ûbXS±òs-}ZÙ6z,ù0)A`@*êWö’s€KúEáö8Ó/¸õÒ–…¥ÓéqPãD¨_×qÖfŀΠQôÖ)ã~í+i¡ôñ´—ö"U´¡¯€dd\ÕJwvÕÃi8ú}É¿uÔž§†¿òÅi³U¡–uAaÞËð·g¼4¿4¤ÿŸ'Ç›ö£ØÏ =0ë:µ«¸Õ¨³y~yHç-õñ-h¨¨X(Y+}²Ð^̪l]Ö:ž(Mùe=Ûº{ÿú¦ÛaøDgzhø«@Þñ¸éQutÉö0žÏÍÏᙂÝQîg ìÂ$Œã!ó°²€G ëTwÌØ­FµÒ‰Üó>Õdjg¤Å*}×vL0uoÖÇ=»AÔSTûKõ³ã-ò©uɳyŒ¢jQ}s€·érôƒ›Ôº”…Y—9O^„£ÌölÖ³’WW-iE5_³o Èšå|ôÀ\‡ÅœL y¿€ÔÀ•CñÌ=+Nße¸;’Bec³öQ®3LddAŒË1P ©„¶ÞZCÑ&A„?§dÑ&–ù€{ÛÕë߉2§.*ÌuÂÎËSŒÌ´á:š¥oý#0|ŒØ`ÎÐs‘O÷-:aykªñk]˜§d¿ú;OŒ ¥{ÿ”T~‰À+`´B~…‰HzâPNq•Ò×[ÃÏ肃]wñš—_n}vŒé<P"Zlt¬Î3 Dº.ÕX&c<Çò6]„¸%¼l9t¡íËc¾Ç’ì :ÈÙà~äÇÜ7M|L÷±J&³$òZ¬tÇ3ÙÀOg5„:ã›Û9qT ï®pÿH~B ¥µŽ*UTmÄsWkBÙýZ0 ±ÞÏ«9›xùÓÚÀ„`™1 ɪ¡(u7‹^™+ˆjšUžÁ>œm]ˆ+OÀn Á”ÇUB¢;J#ÅÝ6jË¥X-DK1¨r¯B¯3’î w,hr#ÐSA+f+$ȸLPÝ;Û­Ø÷õô–‘~=¹÷"Œ,¦Üaœ 5Êá‹"žö6ž©‹½0+‚ÔfÓ݈ž“é.:÷ËöÁ] žëC'v7ÏS—%ß»iË5.SDZYÏ ý€wöíâsûž #ýU’8g‹`ºæ^ù¤Õ:öQ”¥&æTtàþÉÕîÝ}ãñO/gÍÊ“ ·À쳂¦c;Ó7Y¦eÙËy¯ª)‰šfÜèž ²²ß2a¹– LhÑwÁt;ü—õž;À“ƒ3G=“%hƒcû4m Ûš¨´ùé\¬A‚umƒMéÜ<¢1úýŸ5F1E4w¿¡D—£gYÎíüå}LH îM \U)â~˜½ÖjU˲D™ž†h4 RØ7‹Ovpe/Þ¨à7Ͽ̵S4¢î'Q zÞíFiT»SÔ–FÈçS½aù&q¤WyÅkSü6Ô±"gPg×V)½Ål]Ñ,rIDÁ<·šÃì@ëxî§øÛ rw¿dl–qähš¤*5—CSÇE$HJ–iû¸ÿÀQËÔ¨W£çö€‘SΚaËùIí>µk­ö~*t¼›×|Û„àDgÙW­1ù€ÖIQ¶- ŽA Ø’m›ÔÚ{¹ny>ËÐÔ½S´‚×—CyÊ1áœíqI@CKì“*¨Úà‹4G›¦mš†¢ËòªÏ'Ù‡6¤ö¨" ì»›bö!mö‘LƒÔ†B`‚­@Bó©N–¡Ð%¤Å°˜5}ÌMAñ¢-þf¶àè¿¿¿¹´ª‡Âbc(s30!ªÝ¶}Ò•ÞÊAÖÄ‘R;~¹où=özÑFæŒC9«æàÊv÷s·i¥ÆŒðR-™Ïáâ·cPݬ“²*'f3Òa%äר=‚£Ý:lõÖ®¥¸ÍRm›Yâ4.HJÿ~œ˜·/ž¬¼“b’Èòò\½54ÁG k¥rÙ¤R¥Œ*T°bà¤tô‚Ëãñ‰~0°–³¶p… ÄÒ4ýÐ1)†„òFѧÅ1±(óî–xU×ûÔ"3ÂfØØìšÑôÒ,Y×¶Ë~®Ó½—ÅË£bŸ}¼ p=óËlDTêSÍa))¥X¨iè Uæá¨l“ûfŸ\_–Ï|9¿Ñ.asKH4–èJwvß—=©éÛjª}«L°D®X쉌Ý1ûÚ ?Pr\²Éð¼'´›ŒH=¦u?EóV¶Ùt¬‡Û5€ Û!Mj|·`Š>îüš¡ÂmÍÞ–ØÑ»Z5es6RÔ(]x×Ü( õ °Ôõ?Ü?ðy7ŠLk~>içPñ©vQm! B*².taþ Wµ>ùÀ§,?2ÙŽ•b09M(Öuõqa:%hXôDAˆžÒkÿÐIoD”“^Ref=Vî&t‡›œû7×xˆVÃ%°›!Ék”cÓEº‹º1)Ç|Z&ã8ê‚ØìBUàæ»G†^¬ŽE¢e8syBØÔ ÚÛu#d ®Õ–¡¦÷¡7Mß*—£ª!aXdêß΄‚òG¿ p`è9¢šíÈLC;MÖ”? $-"zT›yJ‡IèÕüöö?‹õPšÎP_ Ž‹‰c¯~Æs»Ÿ¾ö¯‡`…’²®Ù©æ$Uã˜éºìK•iS]üi=ïÚf£ÕÇÁ[($²c2VÊ|œò¸RTK×"Fÿ§%=ë_WJÀ?T5FanR’ i{›€Õx«š\ZÜÓÑP*`œ¹£t€ÈfôËBy:SzïæE‚³à¡QDù»w¢T¯ÍÊo³s÷“bTÁ²­t?‹mƒLö´åýºˆàœKIÕw`ÍŽàß;£TÌÖÎF©¸MŠqœÆa:U) J¡£ÁˆbQ/¼ÝˆÙ˜JbëµíKQêõ6/’.Yºz|P¬ðíšui}ý¼^BhL15Fxa÷6¨{šætb†&]é ’9E“›95Ͼº¢Ëèá¹aN¬Á ­˜KÖxA/@Ñ_rUø  †S¢|?5fO”¼ÆðÊÉ'kÓýØ‚ªé Ðú:ù\ÿÜgQ¹ÏæóPVÇ »àŽô¦•\¸òß<±CÜ*q°EÀ\ù©Òí:C3–2„€š Ýh.0¡®%ªŠNø¯û‡ê£ñ¥ú ‰1NK¾çUÓ»¤ýé\(N´å‰ÎÛ:vx@Í®f¨çƒñ¹TQIÀãD!¡LBUÝgÆ›p0 z€þf]Øâ×CøÄ,L$ß©øæt›!{|ßã<ÏÔN…І¦ŽùÅ®ÃÞ 8»Ó@ÒS¿s„”MeH D ø[£¦T­éÏfAyË`*xB)/1ACêJ Ó|èš@díX—~›èÎÜÕ¾ù´í£Äê€6ø-€s°oHç¯×7ëáÄ ¸‡eeÄ$¹w ë´Mº,‡t3o y„jÞ ÏãõßD7bASeìaFuFû)?™~JSï±£ŸÒŒu¦Úf޵¬wg£X»ŸÁå5rù°‰ƒ_Æúv„r~åN™Ö¾60-ê:©7ÿ¼¤õ©Í d£L‘Z¤èpf2x¥Ö…Zñn%£Æ‚´ï>zRw£úâÝfCx{=˜Î™$Z¤¢[|2`yã®–&Þ&:PËRn½,ÊS(Ê„Aðß÷.‰°ÆÒ_µØ÷vÃѤIóh\æ-Ÿ·(‹ÍCº"ŠIÍ1mR+´Þ,ë'÷~xº‡º¸å²D K¬Rœ¡8Ñ}›öFÒð98œR6í j÷mMd„η£SÚ"D[EZ¹PÈ@—|ªÆrJÌ‚¨é<Ú?(îÂS£õþ¡ÄgôÀûgÁ×îÄ&TK¬ãjuI‰ÂlöcbÄ îÜÇà:ô>4i_ÏíçÐëj V›ê̲+†lYònÜ¢ºåzÜ':Æ>œÐ2V;8‰iÐ|夨RU0x§mš¦JT¾OÃÖMX™Ú­3k‰ɦº$ïþ©›û7²AuUv‘Œ†uAo”îᘒ¯XÖs ¢ÂÛ¶üÃùö©á¼}sOEÌÀ³mÁXî¥ÔɵRt3U£a” TÕúô6ÃÈáLjæñ0¤X:3”°¡+Ð ãfiÛœ¢Ï[%’Ú€¼aÇšáIBü›çîãçÃsw@½sõÜݵézp„ñBú™ÜÉ=Í•®òÍcW£ª QÍN,::QÕ„1Ø:TYd/É4÷n&ö¾‘×:¿Ék3:ÝYØ7 ¨•F•gsÜGæÇ­R­ä@­Óñ‚0ü ‚lìÕÀ"=ÔPÚ¡Ù³¼îÚ…MNéð¶1tУíìC¥Ì¥ssÎÉãÕÎõ‰9·H¡t;&¸wIѬñXmE9î•dl¥“ØŠ¶yÃܸ9Ò¤ÚŒ’$«8טh©JÞ’*’&ªé‚ømÁC»ñ.d•M|NÐiÈÁhkö å9s§Š†nš~ý¬«^ú¸·¨˜¡Ìâ€ùÁxúOõ—¦‚þóÃ=V¶ `¤sXºÞà Õ/Š’Þe#ÞDÌ”RiUÕÓF»r<Ö£êÐE§û¶Ï9[O ûUY4&䨠èìù”% }¡]¸ýŽdàè~úœ¸×Ö¢àÓ(”¢¡ ¯y:Ó½¹DJU¶}KåciŽÛ¡±ˆ¿³¾ÙU¼Ð–׸©ÀQs«Ê½I‡&Ï(O‘Y!êæPøwÅå‘þé°Ýš¹Kõe?Ä—œµo¸€ˆË¢¶y,J5ìc·¹°°¨‡Æ«mÃUμIç"=Ñe:ÖFP¼nÄ&”YÅM³7¹ž‡|– èq߃¨/Ðþ9¦p¯Æ`Ïïà ˜#vÉ2“U¬í¤à T«Y/„ÿ”úÓ:¯°‹nìÇÃÇiFÒ£¥ˆ‚©ÕOÃêïÄç‰oƒ´¼ ÷=ªŽõ¾¥&ò\‹j\[¶íš{:2SuV 8 ³¨E‹>)÷Öq¹*ï#¹\LQÕvÏDŒ ]Þž¿812¶?‰jàh5ŒmÇ¥H§FeÝºŠµáŸW³/i†<߀+Çi&èbÙ8 SÂÓ….Ó(ŸLX¡¨¡2Œ«zªk0V¡÷¢ÊÍ…'÷Î \4éÌ &w6²ÏoYN1J#‹¿ÉR*ª´ÊFm=Îóf¾IHõ •ühñfŽö¿>涬»O×F= >K¾M×C­Ö`‡)J“|0ë¹>¨:°Ü›‘ ‚Oö=ÕâzA%F]µoØ|¡·u(š=/¶®ØÌ¦ë? £GUÆíhÂ…Î'd 2âšU²«IKÃyÖm—e/â]ºì¤…)+¦ÿ‡™’sּ㻠¬ÿ^O/'Íz&ôŒµ= çŽjòÜ×Ï‘ýà—LÇ rÇdI÷¶WyJ…Kÿûj·«0â×<]œ#‡Î”+jŸ5U>ªè Jæ€Á„O ;(š–F¹åÝ2_?¦ü¦³o%  ¾Wû6DT²ÅS&–! ”ŠP.ìÞ[,ýB’cÃSXrP8…»e òdë(µ™Ú3I7™hBi’ÒÖƒ ÖÁpº]UðæžÇ×å®çQ™|Ý‚>j9D3ý5n¥44@wÝòï¾U].|Äh°¤0)€¥I/²lK‘¨HuëÖms•í±Y/D‚Ö´•ΡÑ{˜,XoÖX¤`D§·fõèaH“T—ÕJFÁ³ÝäØþíî±E0lJÝ7÷ìêþc”0°`°cÍFv§¤fËËzé8–Ç‚¬|„€lô¹ìÏ&LmŒBxMán`Q2ðÄŠ(+2ªí‹*Jb!Ðz nÐËs¬›é7·ËŠíNÜŸ§k°CÎÐcŒñy£ê@ïQ¸"øzy^Ü@ Ž>ØaØüÙ~·1žs´Õ(¥##ôžŽSµ75Eº¤]MÛJlXÚ9àEáÅhÓúiDCªJÞÓÜY¤—ØõºWU É‹RÄ™ÿ´KïÉ[+´Ô Í=Àv¨&*¥è Ë4/ w©`æ)Ï(£Ž$0ûN¦€ ›éCílô×)3„‘™ˆöŒdâL/¬ed=ŠQ”ÎÑßlû"3$Ïúÿ ú¡Ÿ^à'‘é&h g9m£i5lJ÷¿^¿^ÿçõþïÿý¿¬gÏmáµ)ú*šÇ®\ÖuH Õió¸´ÆÆ¥ûÝ~K}=Å y_ÊažÏqcf‘gTšânKÛ¬keI8´'|Jp­SèýC¡ï‡ÅO÷zf+w’R¡}[ÓÙ]ºašMt„(½PœÅfýëŠRü›.zÍð2â)]ß2 %ic]öÕT }œ£áÁʈ^tx l. «o„ž/ÑiÂH#ÂË|7±û¨j˜7¨Qp€€py7Víòï¦þðB÷£]¦Ÿ¦PU"Ž;¬Í·Eœ aœ\EÇ‚!%i.æSâ@¤m+Ž&…ô×È\j7˜?÷Æ·éT–ujjš2_Ç46yi~ö jw”êºo,×[…ʼ6Ò¼nÙžD$ýÙî¬Êâê´œµy‘è ÈWnþ‘ûW¾ É%ÃÇ ª/™ŸÁdŠjéN¥|¥Ž¨À[г?t¶˜ÀÄOˆ¡e-M-3¡j«.®ªV-[ýû†ÎÓ,èuV „Ú09€äŒpƒµ©¨iè·~œÛ}MŽUÁÝ èN9TÜ:FîDÈD+´G»še~0œ¬ó¶ØÑz¦O¾Ó•%‡êÍ@¤Øïi®¿ï=t YlaÆ³ÆØå ]3æÕ2v)]Ï{½˜}¿;déÑûÞþPKh²«§`yÇN,}˜«PÍ•¢½ãÚ˜!no£KºÖ[}òßÜs1b«¡ÆÇªÓFØ0ßÓi¡Œ£®u­ņ…6Sàx÷ÃÑ×µÿ†Çý:ºÌF¼c<.Nvª)úb0YæEL0詚ƒŒUxºÆ^Ft@“ Y437"‹%’SíMu½GU¢+³ž ’Y9Œ»û®®š›PdE¾¼Â˜k…hnvÑ–sC©¾ÞR³ A>Ø=‹d^{Ö§DµÉ)´¥GéU'½ÎÛ¸©”^ %ëÙak½ÿàjÃzZ•½Ð2KäJŽXÀudÑ¥š­«²<í›reIÇæúNÅ3@û…—(˜Æ‡µ(:”›½lmQ?+†µY(S 4)‰dE­ŸÖ9šph0_»h0e2™‚ò¬6ÉÊ]@T&é´ÇTy¦f߸^B$°hŸ›.¸s1† +üõõ©c€ë;$‚ãÔ´ù÷hX©n̶b…O±þyUŠ GA¢…©ð|ðÐã‡Õއ’ŒP¨Y)¬.T¾¯E‘Q‰ØçzH³²möFËÚ^ˆ>¤ÀÎÛ7 W(N#⃭Q±HF÷fk”ãµûÔH®ð‡ïljþ®Çèãílü*zåªdÿº”Ôœ%MYôïA§êÄóƒ­¾ 䇤mÝ-Ètö,ûŒ¥HmA[ªŠª\›YS…àpås½‹Vë?ÕLss©ž€žz¾wUm?m6¾´(ø™ùÀ©aWs5ÖÎɶ UÕäçzÕ°wäÄö›Ir…Šð½L›¡eÔ˜uÔ5ôäèöê¶—gÁs Sa“¤ÜNYUŸøÚ„Ù”°!VßMÝ =`‰ >QŒÕ<æj—ƒMI«‚D kúÙ§J¯Ñž˜™ öýÂï~2*ÏYÕÎx Ôñ¨ Jà‹¬Ž+ú:³hù!‹N¥s.î×Zв•C´­æÖ+C¦[PÆ·OE‘$ëº5f=8"*|cd»«±ØIÓ¨€mÁß64Bõk®³9Šë¥IÌrP3¢øç¢áwœÄ_¥º~¾Ñ BR*ôGÓ jº•Ú¾GÝÐLÉØÿy=¹/ÌzZ®q|iú,ýa¯Ys)5Tû¢û½³¸ÚÛ}̶_Ö£làcœ¢!%DÈ£ 8^ÚÉçÔØTùЧ­,ˆâÖ (‡ÂÍøuÈ)A¡=©”ZÆòü´m&—@WµÚ)Ï­'Y¤Í¢´•T?íe]÷«s t3-+–1Ç<…3{:?I««YÇsU• ûØ„–oã{ßÏ-~ÿ"Â0N0¿Ç0®ùû0.j«\Äèh9týž±·õàã©7Ø;|Ã|9@ø5Ìè!ÕØ-jRÓ¸]Y˜†Ÿ4Å ¦<>½Ò7“ô"ÿúÙ³ùZ0ü›¿Ã©°uDë­gt– ]B¹ÅdôѲçÊqŽéúÍ¿zÈa^Á+qÒ‚³Ö;´¶“M5ÅжTÔMKl2zotݲ²Œuˆy‰Åp¸¿ÅÉÉ ãáÈ€_Ü¡“–eq½®íŸ×2ñõ*^ò|J§¬¡šw\Ù €q))ŠQ¥‹ÚÍ— ÉAšB놧°Åµ+N÷’Ô~b Ø\â K©^š¶zj{5î“\ßÀÇÝɲ¨Ž;xá÷«Øè ¢WJû†òÛ ãGqY„ªåj‰íîr4K‚U4À‡ÌNÁÒž2N-*,;À8é[ËO¶ÁV 0´¸9–\c®ý†e 5û’„YDÿÁÓçɵýß(Ã諌þšJ¹géØ9èۇᘋÌ;QÉ«ØÛ1úˆÉ$Qq‹®kÐÐçqY\{ÜR¨i5NýPS^aÖ¶Á7€ôVphç@N‹ß$mò„•±ÑrgþG?CI@wÓ²osY/•Y LEÌ)šŠo„w?ê×Åh–=Ï‘3€ã5}ši†«øðâc”Ó°¦"b 1À÷Àv<3½ý«?$ݻ߯§éP9Xæ’CÒÙ)ho;mø¸m ÒÔ‡{žï·‰oÏ•w>ÅÖô\qf)Ü;‘´âWÚ&…JÔ6E}¼ŽÒðõÝD¢Aú¡½dbí×{\têZ[ÐwÆ0[0yµ–í¤ªjLaT/ AbÝ`¬c™Noó} _è<³ˆ|[öÐjà –>L4PUCÇžJœ¦Ó™Y’2¨;0ps9aM¾Õ OÃàlž[ª&‡Ü›}Ô”`è¬1˜Pö8 Q„¸ðJ4½³ÛGäñz”$*‡V†‡y¶ù®4•½ìÐq°¥|cò ŠmWJ.§Íû,ÊR4DV!Y›uSsY­IY™bCí×ÂàÞ7×xèXWòþ ¶eOƒ?âê—à>ëy’¶ÖK¥Êy0¿™Êa ëèf AÇþ—íçûë¤4ºQ&Eû}¯ÚlV‹ùÔü ËàW›Qo_,6ú‹·mouq›ñÝ I¡¢Œ¦,Ï«i‹ºÞ¬8!BXh‡Vûæ;W tgŸ‡ö”þQϸHýÇs­ IoÊç†!íG×7Œ}²¼ G@ØörK`ÖÒ ßjm¶ˆî iX"µ+Òq¦¯Mu¡Žð?Xì¯C<[³áùHÏP’˜²³6Ž»2È´ }èBz‹{ç´-¿ H©Ð~ "jTÐM‡çˆ”ôìm—T%¼˜ºOfI"æ§e§í^<¾õ¡´Ie+Ëyõ<èÄŒnÙ˹Þê¾×K¶î²œÏ¬'Ü÷»ÑY «\´‰2<¶¢çZá,<·Ê¨hŠ^S/Úƒ«Žåƒr%kž5œÖ$ U\6´û’6¸5ÓˆáÀ2¶ôØ*B§”B«¼FŸ~®‹´*ðÃCÇ,°.?Z£›+nTT ±>Å¡WªwJ%w*‡÷¬:Ö³è{TÀR–f¿õJÏ4ü©5=åÃ\µ5%:hìðRÌå0¨¦Ô*iöi6}3Àgà=ì±àŒ‰YÁ‡¢*z{rí0§ÆèÓóö{¢’vͺ>Q•ôRp ¡HfM`„,ïª<³‘‡I}ðU®‹*–¶‹æM—æ[è?:~xsŒ¬f>:…âW‹€`…Êà¶=IJ²!Û—bûh–޽ïü@ïðæy‡˜Bà»-㣥RWðÅè˜i‹5Më¥cZîÑTÿqÁ ×ðõñóíZÃå;ü|«©ÓiSJ¿Õ÷Ñ0£X…ìêç{éeŠQVÍ2£øÉt‹ñOf‘QÚÛ{²Tq?Ë|×÷Q­Þ|H¬ÝLæÄlÈû[>bCüE‡9­X<d¾–G=ÕŽîò>Ò“oÛ¨êÚüh<,¸dÝÅåó[´ô¿0})k^XcßÑì ÊÐ?Ù9Î[†ä±Ñ»dWÚ(ƒ„MÍ(\^é­¢¿EÅT$´v$8@,JûÆ^q3qÕ¹Ñw}#@×kñ#™5Åø£š—ÙteˆÒµxsúé'só=CB„ì'§E+¥3ö“ðF£D­/û™®ÆcÉ0AãæžÊ.d~½«}¼\eT~Àw¬a—0ã?L9ó¸åõ¨·6.eA*$Žs áLxJó_H‚ßÛv8Q>\0ä³E‰42D ÎbÊçhç¤ù}IëÃ) BÎâçU0¡¹ï‘g¾¬K^g[uiZÈ’Ž ÛDz{áí@ 8þÇ>ðû¼ÌÀqÆ@N"Â^õÙ>¦åd‘±µúÂr—]ô°iû˜ü›Å€¸Vo†ÁÐiëé\Í[]E«Y3 t™²2.¼Â³Ø¼x¾ÃZT•ªèp4[[CèË!·’·JÓŸ“ªc›‡ì|ïÈPî·«Í?UBPúhë…þTdƒ”}h ÚÞõ1_@J?MAVëÁLÑÌæ5ÝGÕ×騙%á°íÂv÷ž}ÐÂDHì Ÿ­ŒgX®™{Õ¦m:®Q<÷RebxRüÇÝ!Z Îpç[ Kâb“TµíÒ-ÞæaZ§êAŠ x§;ÈzÛwÚ s_ÐO&Vüá¸èS"Íß¾¤ŽGc @Ú×è·Zè@âtt›”…ê$ôæPtڇ߱|ø=~ßbÂÑBþ½é¸¢AWdj¨ãnN‹N›õl~Ü¿î{ìu…Ë=ÄÀĽ2¢1@ƒ¢û³f‹Zǹ¦Nš”“:`ä9lë$#] âoà‹&3›¢¹žw{‘Ä:ÎÆ!{ók—‰øwÆÒÜ´½û…ÅùØ8b™ U(däE…!•MK¡'n¼y(ã¹ éÐaßÜsZzíÆ!…|òÔ™nÞšÕŽöܪ«¾™K]**8æ·•®m±¿mÌQƒƒH*>ë³áTEà•…ë=kÚýݾ˜õ<ú¶–ÔHÖ›êrQ”z@áL¦¹¨‘u3þH¯‚R¾IíÚêLæ† ¬Ò,j®&o¶ÍÄëÝÙLÙ%Ð1ÆæGXÆŽmjܤþnð-§›*"ÎíÄTœp¾¹$é– ì÷Ø¥Iš”C§hÑtΪÈ< ¦Á”3‚–cÝOÆå¥ûdY tØ3X&µ±§÷Ïñ¨T7OM• ô.¸9TeBg'ÄÄùÄ]Dà¹'hQ¾s[uƤ®iò>×mY¯ªl6s“¬Â o#çn ñÛÙ^8Ã…»Æ—Ö)ÔCZ†ã <<]¸{o]»/e²nEŽø Ã/šLHeö)?à\Æ›z÷´£ó2ÔÏlî¼#û¸Ê¢jÜSµš%¡húv`ÝO$ûÙ7œŒIÛ[ód×n…ÞëpLƳt]–zX—qÌÌ÷Æ%×{èr…'×î:c®éƒ§g% .ô­p©é#íÃâb=šSƒêõ¿ºû‰  ý RMøbD^$D ào¹/T¹¶q±Ò®—dAF“¢xb‡`‡ç_ˆ€•Žb®jA‡ÐòaŠò!ÊRU:¨#Y„˜&ý胹@GûØE‹ää,÷lV¤‹‚Öœé*Ó`Fbžµ{±ÄÓ>o ¡æAaúG×O[ïj}ʺþ|ýV`UvâÕ"ý{EYFÜÇQ5ÒêB†Jî TÍ»éµ_ ¹{ÿ³qü¢D²€öN7‚™!H½«N é’ÎõÔÍ!| ¸q˦ÿÌO/mº„`BÊÎz0øøtØí¢û\(:”EºåY¬e\Ãüv0GºÍÝðüÝ×ÚqÖ<âœèMâƒB&ô`®øöé0|¥¿ãȪ4‚q¬êÊ8Ãs#÷ÚÞ×Ûš”“XÃÓgq!ßNwzxš)üý»YúdåFnƒP™\!¢ ‚ÛXç}U4k#ãHÅÂí6fþdµ¯ð¸ p   ègtòG–ó«Õ¾FYœmÃíÓ–Ëš½¼]AT™XÆ‘;¸@WëK,8Ë*oAªé؇i*]w»÷¡ {)6/’jCÐ6Ù5S]÷‚í¤sóÃy@1i=t[†ôk»æTÆ–mÜMÙÔ›é„lyH—¯u¿÷ª$s5¨©Š·A >ôÒMô' º+‘Ρê‹Ç´$ZÏRØ]0øz;­Öpƒ/æFÃRïíïe™ô”e¹`mñ\àkÒEI œ hyìë=¼_Þ3R²á‚D†÷}Ýmk•ì2kÿÂÀÂ\dwéûIŒ _ 3Üqä‰)øÈTyŽÊúFíóRýº*t;® oMñp ˜²«:£Ó2¬ùV«©ØÔºè‰îžß·uùÝÇ ÇÆÈ—”·7ÔE„»Ñ&yK—xÞ$ÃT·õïOxIE9 Ô¶ÁùCÙÉÀtþZJ!èPàx›}ƒq3X%Aú…=•3R˜eb¢ÌjaŸ¡T‚Wó¼÷ÙBy`±‹¤$%Ê…ÃPI“Á~ó-þÞÎ- >уŠ¡›¤—A5:c|oùÙ x!±÷íðЛýãy|ëÇZ–R ì<tûu\ÇeÈʾǤÈä7{!š4ô|ÐXgÏþ@¿ÿ5nÜh'ÓM4H)€Ëg߉nà_†âJÍšøp¨ÀZaª¡ ÏŠvêbÒÖ7ñÚ‡fší8'tßãÒ«ñßAžz‹kõ"•~Škme1˜ãß¹UÞ Wb Sÿ·¬y#wɚˎçÈš3Κ§¬¶F¦…Œs¥›0°]Oü~Ñ'=f)ÆÁô‡]¶ŒƒiWµìÂ=Ñ–™Œƒé-[ŸºIÖ]Dß¡„®µwø˜Äôö)oÎ\"îD¶u#@ ützи\Šu/›"Ê"À Òö=ĺ›I¤-.”&X?5#+äc—t™µ£¤’tZ’}¯³JçIÞmQ/Ò":i`ØyÄßü´/Ndƒ•‰ÄÕBL*¥Wˆ4§ëÌ•—TgcÙõTšÒO”…‡.¬Cã^&×ð0sÑœ? îÃ^ÆË„´RþéàãxÎÑtç­¢±m›áŒSÒɈƒèiÞ+E§<š(ý6ó‹!cï¹0¯¶ÿ5»â¾é ‡ž Ó¹ t%˜OQzE{Û«.öbŸžZ¬AÉ¡ú <)gWL34Í’¼\νzŠûQwºoªHÎPh¹Pt±ïTZûæWÃ#ù _ÆG0ƒ¦B#‰Ù •oÕüåZÍU$ëÁž©rx–‚ÀÌ\{dÿ¬ukDÍ ™ppƒ%£ÿnÝž2ÕOÔÜ<¡ÐE¿·1ƒÂ¡‹bjE¿¹«¢¢fF(ôM(1¹òèÃO|X&!±¾PÉî¹FƘ^j´Èjrµ+@ÛëÇ‘¡aÌW%Tn¶·XÖ´å/#E÷t§8%}ðd¯ (°´B¿ê#]7J œwK¡J«QåëÓîs€±;.¯XÍëC„—j{€<—aœæe^ 8×´:.•¦XGyÏfi21ÐNàžõåUÄQ‚kõ¦Q³7Ê•0ê÷‚ÞA®{ªÚå*cW +„²¶u¿p¯.òÐ cÐ^Z²GèÀKrï¿Ñ:^›¬Ó'¢Òf-Êqm9ˆ6¹—)ážR¦„ ¬Á€¡‚ž‘jé>ß+:QÂÆ 1Ïc—{zùÍ7ÿBxýo¤«¤¢ÂdC ¨†§¸‹õѬ¦œþ×fuÛ׳ZSÎ a,úé-snì¿õªµxº`/µFó²Ó*I6z‰c>$Z(ôT¸ù |{ˆe†ÿ×9—<åóGæ™t–©®†ãïØQu4ÍѬ{ªbúsª‰n“xÍœai—¢J’–ÂýjŠ®ÿ÷90¬©Öì%ý`M×(EµVmÖCíêzeþÕÛó½àë ~O®®é·cjÖó*æQ·*+Æ*›·½›Í/=ë†ö£w?ÍB}난}¼6tþÃ]D#YøkyžÏU[‘ £Bx±ønTÀÞûý_Ï9¶2…TGÛV•Aœµ¸ÑÚr×1ÙªGY %0íDèWxî‡ÓÇ{`´‰kQÖ´”Ž÷ÛŠÙ˜¤ñºÅª ÉKiAô-é P‚o$|x$ñÕÈupÿ¸Þ†ï³N´÷éz5ë^±¡Z bËŽã@Öæ~ÊV›#ÍÚ±Œg~±Ÿ"ßiQ’Rˆ:=SŒþkÞôòØö¿ö×ãA~¤?"SÉÚS±öãsµåqšuJÞv‚ÃaãªgÍ¥¶t`Îöf3 ¬Îrãûw¹wMyœÇ´$xÉNˆmhGxW[¿/¦d=D4¯b>i2¢SWEž,“®²n0ŸŸ¶ejÔYÝSáîâàŽê‰ËÅ"…ö frF$ ÃMÊ`ªjT¥Á–چÂä¢7ö©%sô§\¾x‚ †.äâÜÍÍiêwµÖ=嫹Ž<úRpFò(‰ñÓmâr ÿ¼à#ýQ1µ’‰’“.Õ†‰¥­’Cìâ°ÃôÅ8W]}•\5þŠIÓ×};6#œâ\¯UU OÛfžÖ—›´'øÛAü¼¤uØ€Yv­y“ÉÓÏ•ëmYÿ¡ÿQ“ñæÏ¥úP›ª`)€&Õ´“ ×BEmp¶Ô¨ü°HÀ%­„­“ª¢Ãyè¼r_nî×yN5Sá=eû±¦úŽm¹ð6òN©•KM3¿‚Ç t}°A<¦âHu­*7©lŠ Qþ !ÔNI›Oi›x|³låûz䛕ËQEóÜu‡=b;$YÏe’´Cf–£Ú)À)>>˧m 2&z‡–îÀÍ$ñ8ȧ¡+)uCqD‚)¼Û†Ú?ÅŠÓ›-ü×Åâà‡s,V³K>ô­K*U5ûÕæ銠:êrÿBñç~­—¶Ç‹¯8&yÃÔNDÕ±oÔLå=_?Æ}!Š@3A¬Ê~úÅ÷ ªqØ¥ Ù'ú*ÕbÎ)yŽÃyÄ®Y3/É0&eÍjŸSùO㘷*;U·‰Y0¤o8°\:¸CÞ5Á@1òu€ÌôäšÓŠ5ŸºuQ™®»9‘£‚’6„i”z ;´þuQ«øb|å“Õ*yi ÊèV«X£UõUTiÊ Rñ<xßE-`p;;›—TâÀ¨•c΃Z¨)tl¢Ý¬LDõW\#ên[e¾Mˆš LçðhV—2v>ûBß&ŠÓ ËŠ¥¶xw¯yÕÜUµLÒì Qû>ttlÛ}K“XWËù'«tH8è™ÕY[Qµ]‡T¥e¿íÛ8 Aìx¤VÅ2!oÖš›ÛJŒÄeÙ01|›¹ZJBøD"#! 4çìUÝ®Â_|I÷YÀK|L¯Ø`fW­ªÊê1y!Ô9\‡=iMDpïÖU^âeT xÚ±H`N<÷)¤›bUZÅF’ªmm]¶ør7RÍã^þó˜}ÿ³³N b¿ãaŠf¦†áõÖy¢ƒøâ»6Í€þd²s'À×¢/Ó" «>­M9†[D›ÛœB×½”ðP7,¦E–q„äÈJÿÚºBQ|ÝGU°¶=È$ÀcSÆv :ƒ¡í—‚icLWýÐiÐM§(A-‡•ê¥>š87åõ\·ÐÓ­·`Å›¨yZÊÕ Ô*ªŠ3ž¡ï!Žíy¦)ÿáüDtX‹^§¦†÷–V{=_/H"ÓÍÈ•'8ü|OäíÇtë´y¬G®æl(tÞÁ„`—CEr?&(ßÅY²*à$VQŸA]ÓjÝÇUµélo´:–¤)¿ èeþHyô{˜{m|ó„Ø0ð}Ç®WÃÜŽóÞ÷s–ÕÎ|(à°Ç]º"­s*þ‘ñ‰ºïøïu~ˆÔQJ¼›7 ,䠲߯g­ì¬ÿ®×9üM®³=„Hܺg[îÒ‚Öž7ƒfAÙ —ú$–4Ë{[¨Z SŒÖ г Ÿ‰ZÄÀgÝO3QýÍ‘‹2rºx ¯Ù‰ÚÉ8&ÛH7XY$TÍö™RÇ~ r”æ]î.Õ/ÆŠ‹ÛBVr¨…K #ΊnJÒTMršqXdM®Ð«³OýXƆ½±.'·7\ÀY³%½ƒ¥¤¦¹ë)oNZÙ—Tcho[ÿ]!^ü@Xa…ÛtìVðNFJy”å”Ó·ûXŽæ ˆLÓ–×Ð~ËK]Õ|L?2.`[sשcW/j)Û-£uãafY0¼cUvš84;ý“¡:³êÅS³42¦^L¡ûv.l¹KojQ©jè#Mzê;Ù@÷;ÅBߥ‹"8”6é8]79íMÒQ äAŸ’ëG8t«ïí0ÍsKáðXÞ4P·ý£RpîWöÔƒéX§â+ ¾vÅW¾vYÔTf=Ç…0¦ÍÔqc¸ŸÎÕߛɘÊé´pš¡Ô{Ÿ&‘(ŠÃ£Û£:›q7<ë7t³s§é'A“$ý)fzLÓ¦‚ ­­âmÝdµJ¼(›ÇÌ™uº.bŒ¬GÂø‚2/ÐKb!îÓ•¾&E’RìÌãáÌð¿<ë´XpüKB¼Â)“ß²ku+*ù¢æðÖg{ª¶Î,)S>*†àÚ·O:2Rkg7¼‘™1/i.T”yÏm’îrhì{"d`‡7÷ˆ\áÕ@3Ù©„®:ØŠ·"U¡Ê–J°d‰ã<e‹Û.˜rtª©Ø°Ž2áŠt…Ô­¹sÖ'ç6·¼(»k©†ÙÖaY³ÕühÏEæe {ðÆg^ÆÎÎÃkpJdd†8ã¨õ¸ÔóeõÒI¤±:$T²zh·ßNœâU U5S!“¢È¡†qå髸òxouÖc¿•ÃBÙG) z ¡Ch°ÔÛ£5ºˆFVwpÿkØÌÚpª}ÞV'Ã^ÿ² 0îW$ÿüÓP0‘gÿnqi§íºï Uñíž.U7ý¶¤w³¯5Ý÷ó ÅkuPôn5DÃrôö>—zïãx›[зë©ì“½#E³l¸7…;1›¬ª *G[óI|´¸Ü¿¡ÁÝqgû-†Îé3è‘ E_ ºCƒ Z6jó­.ǨŽ{XѪ!¤¬!ì¹–sÚ.Zhð@‹Gܵ߷7 ¿dÄEi-¨»¾öGeÔ¬å4åÝZ”‘Dkëv»ß²<×<=°.o¨?è1[I›ØøÚøå%*Y¶f¥Ð’AËg“_Îú®ÿ°@ò½ŸÆâöÅX\ä T $t E¿2ŠZiAÁ2›§9‹jYNܱy ÝÓðå­ ÁÈeÇVx‚âr€ã;ûŸ4M^ëvM’e¥ÍÞWL:³á³ÂÒ:Àž”†8ókjÿC©é=Rüh”†]{8DTµÊ³µ["]t…ùÉàu£Å…røíqóïïÅçã£Ç“J[F `˜¦¥i¢\÷c¹Uq1 ù,­ÚŠTw„>çz‡PGè_Dʘ+u_á l¼Ô!e\«½‰T UM·ý¶$´þýaºô(¦xUõ7d=*žeº8™fö-°¨`p Œ-å«ãð¯µé€uÖÀ”]¾æq7Í•NGáB`=]àDM©ÞýÔºŠù@úŠ%ÔrØ•FZ{m1ÑëªhŠySó›©ú·éþ¢³è­*ß”Ãò¿5·‘ž&%téÒŽÄ×fS(×kÝ÷ ùÄØj4k†ß1 ¼]ìË/Ö­”æ>Åå9Gò„þÇíúÑèwqQÌk©—ÊœE GjT7Ì4N[ƒ’ë(G¤1`à¸Ú” Eè*]›ñLÖ³î0ýÅ%~L}no›ìÝj0Å Ä I3õËH•ô­ËhžËÝ<àÝFιìrïî]¯4}JBgw_£9Ìi–¾u]ÑÝÔ—y) ÒÛslº%Þ¸Ÿ®¢ï±†…/ÞŒ%l*˜Š6"ÖPµì[¯özÏ䊤糠+E!6¸Û‡–sMj7œìS¡ ]Fzì”>Qllèdo˶®Rqbä0æ—þ˺øF.à“¼¹PÀŒ.TÄ‹G8¡ï£šÌ÷×l{ÿæô‰ª¸@ÑGy%V*ÞMÛ $P•}>÷[¾ÐJe=8`†°©tmÏ?%¯@Óó×(a3.T=ú¦±îjð\tjž‚_@{ŽŸ}¤u®÷AC~}½LY„‰u Ò]:ì¬QDTƒ]95}æÒ¬Iõ¿z” ŒòåßåÞ?&‰§B˜Âj=Àÿý°PÓ[So{¼Gà k ‹b  ¸¡s¨^ØŸºß´’òYÚzí`ºÀB¢*p(i[ë¬6ñŶi³ànÏ×Àq>õü)›øF~Ó% Å»±ÌC–e„ÁÜXTñ6ÄCÄjºy ¸ÎKï)8äC¾„×fE–-ä)x¯ՌþëJWÙöû’·«Õö‘ئȓÁêYók,){ŠÆ¹ã~ªÙpƒVcÉfJà7lXñ—n«Å‰±rîž]ŒQHk­Ú$]›xƒW;¯.%“£Ð4Ü0q¾ðÞ!˜Â’@!äÓ8 ýLùÎÌÔÙ1U{TÔc™ìU.©}aˆ§BzúÊg%ýaDôúz;·`ŠÛpºlœ[@×ôÙ¶]Ö_;ß»ÑowNu…k#ü kä¥Èr Ù. E`¿Å945¶½ªÍzçÓ' ‚næ؀Ý gY^p>Æ%]Ý[3•Ò™$ôæ`™Ê#Ç»wÞ8Ö‡"ðvts™©sC;„3•¨]•L•ê̳…ôÊè³àoF™‚À¥B…~Ïè°ƒHÒS+ìmT¨©ÒAé1›kú·Is`ìê#‡Â4ÜTo‹2ãsòx}º…ÜŠ@%Š»E=3SjªçµŸ³Ø¬ ÿÂû²—f RêU£áë@îQÙRô%reˆUs¤(˜÷}i–¤c _Zh3Gà÷¦$ ¼û [?„~L¿¼m ÑP ƒzø®èz,”¢Ô.“}è‚JI•¯ƒ }{‹œ]1ì2GâÍjMÌf¦Mm¥a𰔥USýŸ¼®÷uºwà`úØXžöô¦§²F9ЬÐÁĨÌ6÷ð®WÆÍ ¬YøN5Æï£U‹ZwÊA£dŸ•|f/ l…È?½v¿}ºiò½-n~å0öàö2H†nY½`QzÂfmM#ÂòBÂÅw0ÑPïê¦ù.<ˆMLTdä#KÙUjÌÊ]ÏC[DQ¿ìæCÊCpyNi£‰‹qãTR€-ýNȺA3:`µ'M]ÅY/ïпß-ZÏ£èKyÅháÃóa˜”×lEÖƒ¹6´Ìè¼@×§ªÌ÷<*ò¥7Å‹íVÊqÀ(q.Òwœþ’ÄŽÛ—”؉þ3¦Ṗ۩´JÛ1šzºne&cQy…CxÇßîïø§7ýÃÂ\Ä@* Ž8½mãÞêU-ÅXÓn–¤ÂÂd‹®‹ÃsË> fáH?aqÂ~¬áGO”ÁWÉ^ls]ÏN8š0Îý€qWâÀýñó`Š AŒШF iÜ5¯ë‚òž2'z“DÌN(“wÑ »÷íjó_Êä µLzhÕ€r‰;ˆçó–É»ø±õ·Ã ™±='¸`™!¡AG»Ÿ!BǦX’±£¸)íSRÓ¹:Ñ}±¡‘ )EŽlìE¹è5N#mÖ´ªÄVãKŠˆ÷_G™ºÞéÔð{¥Uï‘ÂÑárŸSš²PXÓÂ¥»§kÊ!O›µÎ²˜e¾° ƒ.&ÔçìcŽ`YÐì/æÆEÄô 耷ÃLzÓ´íøk§dK÷zÈU·i:FÉô0§ò§8þ2#(•ú··xõÕ|ˆ¾Öó!d = ¾1$^*f2ꈶ‚àIî¿ï!eZ¸Í¦§,á 3ä]ÿsVM%j`‡èû£”WJTéJª³~“õB‡öexÃñ<˜Y®ÿ¾X÷Ë tyòX—<ÄgáÊj§ëmÙ7HûFSWÔ՟לCûþ‰(E‹»í°«­ºŠëE1!¬TçëÓvêŸW´¯è!žíý˜Q\Õs#®o&ä 1ÊÞ¦fZ§ªÔ0È–¢ZÑu)‡fï²ðÄ`¿aXt ³M lM6Ͳùø6-ýÏùXäCUÕQ%±c3–R·=@UßW±il¦ïcRãFºBòy§ _‹Û-HߘR úàÅ]¡o5M!ö‹qys™ƒd™ZÚl_"¥ÆM`]w¸$Q¦êø,/~`í¦æƒ•IŒ\”·e= ¬žUQTŪËeiÆ.ב’FÈýÎ]/èñÒY¿_V´Œ6fL"ÏRØêÂ!ÁðrhéÑÊmÞÚtnåBÏ¥TÚØÎ~GÇ»Ñ(}|¿è³¼Ãò˜ }šš»ÃÅÄU/zÓ–Òëloº¨®7­ÓrKãÈü6|"€ n‡v\'üK?㥃LÏH&ƒôB¦¯ê­ ´(놥–Ü…(è»T”ºoÍû«¦Š¡a¾ÃX…³ÝHM•2ž¶mŸôÖOû>Këý«ˆ­h©þ9¼ÇOfÄÿïâ[3ºXßbò$ž¤E3®Ãºüµo”Jìÿçÿþõú?ÿïÿûÿþßÿçÿaWÒfnjŸâHOÕ¬(±Ÿ &Uå•yAðì¦<%ðƒûá±è½üÿÉtpª8Œ›õ܉Ÿ wïjöÅJä,8î7RÓPŠOÕmuMGîX/DIEÇzãE®z!Ðî˜P NT)[ƒ’)›|ÞÔN÷N2˜“  v†gû‡4%3Îß•&Ë…ý=¡fJ CJz@OPë¨)¦.cYKu„}JK<àþM¥É¥ë‡îá·œ4%Ôv)×)»Ûjî—1ZéxÜá4ŽºåÛaèžõÁÿú9`¨ô©vmxn22 U—~}ŸeYÒŽæ!3‹¦¿ï …bÆ ýôi mõQQN_ɲÑ[뻼ëqYJºbûqkgYΆàªùЈ?Ó&z+H2ž-Q½ ¡«Ùv†ªátJ]¤i3æCWŒ]¢ŠôX7ÄHËâ’}jiŸ.lTsÙ-ª„ŠÅž¨Ú‚:#’2Øûè´jfÅ^Fú÷E­ë‡¸Ø"Â]sÿ£òè; JºOI¶ôf¹t—PBKß(<Švÿp´ž4_ýšu•ùx6í84ã(Hø ”á:kSüCšÔZ.klÆÀ¢!RܳzûðñÖ?Âa![ºüa˜2HC…I´Ý–ïM‘w¹y•Tõî}ùÛ‰Ø3ÛüŸ7ø Óà3ûȧ*˜ol:Dþ»Áw)²Qº¾~¸­Ie\Aw_§ hW`b¿–m\Óçr•¬Ênî½ÓsšìžÙ!ƒ|½¾åYÑ7„¢íÊviGÍ èqçEµùToñ˜ekµ¶“>–íèuû0vüt÷3gÆä"ë$$'(pGê訧Ѫª¼ÎMz*4/°\º2ÌŒÿ)Ðò„x0º3 ¤x­`¯Dzðù÷¨ß2Ú›’‘¹7iÂBÚ;Ì5¬¶îc3¢ì,æ‡ éroÄüè<&0»N@´ˆ\à r7ÀBûCû¿H–M0ûÓ’öuÉãq˜åä ®Ä‹fd‚w>¨Nu{Õõ»ÒÙØxt9àTz&õNO‘E$!ž,‘‹ßÝU=ÖýÔ 8ô Ês®\$ë”%z³9ßY×v|ÿƒíódK#*(Œ£ }!4:i—fí¾-mJóÛ1†³VhÄSáÍê~RÏoêÄ|‘3³œ¨g{­Æ½ÓEÝšSãzcu|о®ƒD½u5…Úž²!ñ½Ûªl¤ëÞË÷.ò©I’!)•\kÀ‘ÜPC“ÝÌÄ=烒ûdIv†¦Öx8î GûLIA©³˜Â¹¬ö-°amž/|síŒ/}—‡`› S*aåHc%i)1¦j»›©˜•—è1Ùœaü¶‰ù)—´a iúI)hSÀ¤ RÆx¤úr,—2ôÜçQ&k:`BVHÐ~Àôùb±±é/3Öå…c8ûÒ ±2+:ÜñÇéÍ<¤‹2†Ç!¡ÿ&žY'¨ðOÓM º®ÓÍ5†m8ºÝpå {¯Cï e‡ð’±ÎX ‹¿ŠÞ§ _FZöhëÌz0à»y7 øaHð‘ }½¶ïCK¾•-x³íe DZ­ºr'ôý|±™âué[3s DÞ»}Ê_~ǰ.Kph¹öÇ[¤¨¢µÙ£Ž‚˜¤•pZÂ$Û³ð2O¤ÔUh‘>ʳ?«²ê dîpºõê0rÑD£ThÌ“¤¢Ã³Ñ/$s¡ƒ ò÷6’tÖ{€Á0×ïò«ª`/Éæ'"¶¨‡Â'}UÍcQ›%iÿ „ѪGGÉý[„‘üË´R #‡sÓ–j•-E¦UÑSüjä£ÃÍÁHÄ=U¦|áP{ý§@8çæ,ìÃBâ€Íê&ûI%:Å[Öƒk÷펙Àíf&Ý«r…—Íï:J꼘pø†!ÙÔ¦Š©š%É礑Û6@‡¤\x®™šú×qÕë°ÎA· ó4æ/"÷ëéËPM½iÊN†m*ö~7Ø8([.ع üœ­™÷†|~î>EžÑЦIÁ-ü¼+“…gœ-ŠÀƈm>zf^ç¦ÿ{Ú3˜´GÞ"} LTý›z“ ´ü…4úР¥3òWéX iÙ÷‘"̬õ4Ï5[ óŠ †¡ïœN÷Ž})H`I#µXѪ¶B/›>3OýæbbëÞÎQÖS¾jr)H.…à”@_íÍ™¾²‘Xú¾5¢ Gl±»O¶VusÛ$ª¦$Ø T„ç ü¶"ìsë\ Pøcp²rÚ<âöV,T‡Ñ~T]Ñ *ÕÚ,h…ôï0œ0³Jý.µËU7ì2o‹V¨)Höp®õ¶ÓKXTžç•®Å0˜Våî8pª'ÑЭa'¢çâ1f3Ëj<™„\7.À™6]ÖϦQ¬€!皟°ˆ¿%«õŒÅºü ¯;z“ë²f}”³‚ú6›køzçæbÖif¼€r¾´N±;=æ’´E—Ù>{–ÒK"=oEVÈu¥nŸõ)+OÍÜËüdÞèeÑÕ‡í€^R–RÄuÚæE·V½YxÊt}¨ÎþÅ•CÓuí!Û²`nÁÄÊdÕÁ’>óúx> ~(0Rrq8ÜìÓ L‹ì)&Uæd¶Ä ©ž¡²Žn´¢¦2)Û‹(Ù‹©2÷xh£N„í$tPMpð?¶ù&Îj€òeÁ RV#Tû:–€ð÷y.^ú¾M ”œã…o ˆu*½>¨î ²EËú8Ø•`7Uu›gMík’›Õîê7´í¥’e%,ëªÎv$øgCÛÂåž›6:mãd‰t_¯Û±w(?qÏF¿Ñ¥Â»{õìHL\O“ºDß«çq«žRz]={¶–yb¾J1v¸Xw÷‚¿ª÷ ¯ô4jç$«±séÎÕLCÝŽ“tÓÀ@·èú²nÀñÙGwîÒ§z¼˜Õ‡ ÊoÙ A‹´Á·©lÕ0‚§Ù ›IÝ·BH.Y‡§¯ÿF‰ù°¨A¼ö)½Áq¡Ô»žº^ÓSËj_bè׸¦LAæ’ž|ƒ}-aäTºjùð± }LÏEÉèVR謱Ðplú¼®…ÍSÑüÁ~>YèC:µuSÂê tŠžÂO…ê›q£wQ›LâKrpÉÊ]`"{ ;¢‹):–¡¡L÷tŸú\›ŸíZ–Be›,îÈOúõ·aT`bIJä-[UõªRÕFZ•j©4úuÁ›÷·AûÏã=hoyÒþ´+µõ„VÍz”ÝBüÙ£zø`†ÿ»B'+7ŠB'ý½^;ͪ&6ˆ3̳ âoÆZ–w=y¸´¿MuñÍ?˜%‡«jkšš-§m@ùÀ‡#‡uHúÞ¬K.&&ÊŪ¢e£¯Žíí‡j/êE¡þ¯Š,å ¬w·Ä/%]ü6MǪßc7¨‡1/ÕºfàífM/@\<Ÿ*ÌC0îê .âøÑR d±î±t-…¶Óq¡.*Ì±ý ÿJé=~6æ‚i£¦n¤´¿*þ}‰»¨¨â¡ Pñs¦§ Á¡ø-À™ÿͬßÔΫY€€dŠ .d íá xi kÖ¸`©”„vNAUjMÙ1Ì€Q°Q½Ö©!ÙÇ~¯ÕuǪ]cÐU´ÎÄ)ÿ¢öbÉ=ºÁʾ[¦(p8¨fœ¢"Îâ¸ê¥AˆÁ v¨°t}£ûäžõà{ôKPûÌa/ šÂ˜~wÅ”q•;’Ù6ÆSл£rsÞ<ÙkÈ»o¨lÁR3ב6z34y>—™Z7”2“µm8*yìÉfŒ¡Þ>:¢TmÈÍH9"äÓ[ ÐÜEH—T-U7nsÛþ¶ÞýRhÀ8ì¶’zW˜`5N©ªi'6…j³y¶á—õ¨ <ÅšWÃx|}™F}\‚c6C‹~$ã¼,Pq£O3ômª^•ÁE\èÏjÝè>+]¼D ¥ ’èE§©÷ž®³¾QY[ÒëøÓ“²pãÅ…—> +S(YŽ•AÐØ{UI›O͈L4Λ§vêxИ†6TƒûBtÍŠyÒ ëbH)©Ø†â÷/Ô5ø›˜“XÀ߬©…V€KR%»êãX—±Vs½üþ úÊ©_Ï#Ô”%‹×üÙKç$é|oiÜO{?ýº…¬k­ÊÄ”ï—khä6ü f U¬ëHf/%ú×süËgæt‡‡g…Lb VÍEV–/CšÂöU/ÝïÆ÷?6Í?’G™Û4Þßì\Þ¦8”ƒ LÁaßBú±CÚa¸ÕõAËøóËó.;¦œ’q3V¯d}4‰@bªöA+MË’%Sôû‚08½‰cé)ï¬Z”ÌSÏ÷³©^¨zÑ2yûó >ô€%@â3Ÿ@Â$´JÚbþõ!­ÛUí)˜é ‚F8ÉÙ¹Ö´-‡DU4Eõ¯?Úq¯N©šrxY¯Ìˆ½{·ó\çƒJʦ Ø?×ýïëÙ×sü<‚ÇÌa¸K„¹A¢ÆF*ê Ý–Óïçî$w¢«®?ÊŒ´­¼)…$ |Æ4 SiºÔ4R3ÿz׸7÷ƒÈ„eL™áÎ ŒÅL–"it¤ºzÞ²5«{Aýñ1½‹±„~n/£¾YäTaA'¾±ž|ÞjÕgNÒ¥êß—¼|š×óë`¥diÎÖ̦ý>²RZÇcLµ–Ióþ´?fxú›Ìf’ô§»º?>® •·¥Þ§r]Ûî×#ý–²8‡µë0ÜLë<8ã’Ñ„†Þ¡ÎöªÕ¿Æ×ÿ ¤À¦úipÂEU1ÓÐ) µJ§PÓ´®}õû‚î'pðeâOM‰£€Q‡}Wj¢ÿ*ºzš¶ú×<êWò¤¦ n|q¡Þ¥,ŽUH¿§ro)—Ru¹ú2UÕ0ÿ»ßôûnÿmtð-ø„‚Ê ’[Ö¶„H˜*ËnÛǼ_ÔhÊJ\Ö _ ‡™d̺Ï|½‘B•èH†S_.{Ö!$R<ÌMÐJ.åKTeÑ’[à]s'ýõmÒZ¬Vb¹æ=•äÉSTŘ¢k¹»ýy°Œ.ª{õ ÿGùçˆü³îãÎ,I?Ùgce+4s±÷Dgfä­~<™ö€Í/  Gà&"Œ¼PUžÕ}ð~bŠíÞ©ÆëÁ…4¬ar½!\ð,þ–Û,áGUö:5;}:ûMJËzðvlè[†–épÜ‹!h«ü˜ÙFŽ5š&K‚Ôô»ÕÔ¶QÓéÕ,èz.™z@ìK<ð?fßÛ“­¤yøR² p׺:«²,úž’ïœ\è:wë`·BÆìÔoÕ¢u̬™CZDéSЉåª®ŒÖf_‹©ÓÛ8Hòä¡Ä¤l6.ãYŒmq>1.0GöO£Sçâ¨ùbER0!+d»pbïcè¹ËÖa©³ž°¬GU&»¿@|Îz“i®ó(H›`ÖCiKÃÎ]-³ž2Rk—iÙ(}ÛžÏ|M£®ÃøËè Þÿ;‘ÊÈ.`Mß ÊMÕœÙù©¼°¦¿}Ër´\ÇŠyã¶4š²Œq‡†¬yŒôèBbWñࢄøî·>Àã·J r$BLÍåѰê·=¯òHÇzéÌ‚Ð5±n,\lŸ£áÏøopsrÚÃaâš|wÀ@u?Ög¿ Þ©†¦!·š‘ÅìæBïã0îuuª›F)7}Ç·=J ýp4ؽ™Ø£Ý%Ê8][á!¿ÎèŠÕ–©]Q%¿›Ÿ ¶4‹{èÜîF)Ì ?A†,1‰h 7uí4"¨IDÓE©šyfWH壬Rܳ‹Nâíà)XW©ÿ⃛û‡î \ÅËoüÀܽpÚÙǸŽpoÕbÝòĬ\ºBm[³SWÄI¡l#p|îý›s܇î¶2 ?]`Q{fS˜}^mõ6*Ú"Af£ÑÙº&§17üàŸIõ޼wcE÷mÃó ä•´Lg[Y@)t`aòKà…V(Úønð¯ T[Y§Xm‰„óÌ®aØ¿yŽÊ½óïYüvó›OqÒ`š‹é·÷›>°=”2’ ºkó-Õy^Í›4úhß ÂÜou-³ àfÿþoY÷t¿ ‚MëÔÜOOí¡Ù×·tùPÛÑÙ®á2ÀÂ!‘Ž’¥X†&‹A¦pÎ &´¡Ìè$Býûqi_lQçé(Ö‰rßi†¯f×Q5gíÐÍMÅv¬ëѽkƒ/g”)ãzÃ’EÈ— –IÎEDe¬‚ÊõU1Ôõ<õõ´­¬Ø 7Ý014êpNðᦂ^ÈS¼Šœ[^‚tżuÛ6º‹¶%YèØÈ§¶@xdòJîÛ á"Û'8ѤoMá™™¯\ÀÔ2ì­Ê#ŠTØŠ-­é"©FŽî¢â{Bå‡Ú3Ûvfêª(TäZWt$óêxF¨?PÒž)Ï?fa¸†¯ŸSæ¼EÄá\pg u½+ÃÉò(C)ÚPŒõQíÜîᡎã¿Sjö1¢xEÞH˜eï®j¯ëŽjõÞMªcŸ`ÛAü¢/cAd(´]ÚÐ6c“)¸äK ðÎ3=G‘YÊNׇgµc¿]. °íë 0YËZ¢¨1ÖãVK1µÓÇ™lCþ4…»oÐQA^ðžßÃZ°©Ø/WvM™×SѺšÛ=~¢Cižå@Ê.o_{Ù6}ÿÚXÑy¼6›Á`G½lûª·mGKM¯i”é¡\R*wƽØ(|OæOAÑ &Uà¸\ßÿä>X7ºvzï­˜y²®tÞ»n›³xbƒv,H§Ñ±@¿Ì̘ÑÒö•›¼ý¼åâ@[hQô ¥ ¾‚(ùÛÍ‚Pwwñåé OA­¿Q¹¿Àqº?Àq×½áņP •Zާä÷‹ %äß&¡Ã8TÌ“ï û=!;mãr£}?Ò]žª=û}ÑàÃáïùõ0î‡Ïë;gùPà©AtŒ°v>Ôiœ×k¼¨rRsÂCGðr+ ÎTä¡ýbáTEKD;²ï§~Æa§eÕë¾ÿõ×_ô’>Úéts—SM¥OÞeJt‡ä§ðC‰ }êb¸ö‡ÞôèE$±® Åj §Ôm4d]2Ìk´ŠŠÇžŸnxç[fnúÙÑÌ­Ä1*i`d2°%CkžÓ¥T4m[ê¹ëg³ ÝOޏÉÝ\ÇhYosBŒ¿Ï¶ ÔyXlº7mA°Þº&K(A(ŽgäŒ Ö‡3*$s¯è °“yJ”d ”1Ú» ¥<)†hÉ’tÜóÚ, 0Úª´K ÚÐs?ŠGVÅ„¶8Œ(Áx$’eôÃ< ‰J6Ï(ÐÌï´<'¨coÆ[hƒ§õ62æ½U­Ìïh_­ËºDYÒ¨A§M›uõ?­ QÌë4ëù|éœçC÷ž{Àkºƒ"€ud~¸ë78ÊÁ -8{À׿Y°´>htÐbú©Ô;}¯ó¼íe™áÈHyµŠ)™­X Qlɶå2õ–;i|ížëxTè°ŽÇ‚Éf? ué až‹r7”uË9ñ/†uièÔg½¦Z×,H9اȎ *¼æmôa¶+¶•Á¤ÙŸØö-®“ãCôê웾÷ðuœÃ‡ ±BÏ’ ÝœðåaRQ%ü‚ªúe-DRÎAvnÑSùwÊܳü6%½‘¼ýÖ‡çVÁè.Ì`¢Í’·S”¤Uïã^Žm"w'ëòCn$„ÍÊ»aw&êOàðbÙKŠ¸Ñ›nÜ{5Ðk,FP¨sÙ‘àuÃà>B¦C˜3™ar#RÖ¼F§í$Yè긢 ÷Òâ(F}Ý_›¶Ý?Áù„—ë╚Ç÷éeÚtÙ l©Ó#Õd”ËÐmZæÔøb8´¼ T/Ÿç4BpÉñžhé=Ö˜uB±®Š­ŠºJMuTzœEãÊÓ2¼³ xU©yÑ)yö­lÙ¡¶(‡¢Óe3+ÚØ” [hbÙöa^º€ÂØaV‘( ²Xé(È˦]¨4’%ërzÉF–ŸÖ¤"Ïqû†ÁÛ6û2%{R±gÒÿœjGÔC÷s‰›|§QUÛ¬›u3 ÉÄ žcæÀ´ ‹¶IvìxÙÃIPý°B‹x¤¢9›£ª×ÙïëÝÿuµÖý_udÇCG¶ûeIÖ‘½Ìñ¾r"Ì"ìo,1TR§Û°îTUÑÿž ÝYïCÈ ¢h®ñ up¨±Yæ®Û»rj§xÛú´àV½/‹iÐõ<(n€qv[ÆÂ¿™!1µ”ÊøÉ{«æhßfµ›ìšmYÍÞmç€(__Æb O#ým.&ªá×µ‰ª!Ž·…S >ÔB üh£Ú¹dCÂÍú3Pô ÒK$,* oÃ8›ã>êeo»7:Í.æ”eòá‡YÛö„ ªh@"šQã2ïïêÖ‰RÎ6'"¸˜S®J—¤KºuÎW?_¿Ó;Ú‹CË,“Ž6ò€N:c\èu3KzŒu£¸à,e ß`74ož?§GòóÁÜdܺ©ã<Ú÷1°› +PÖˆ¶ Rorß¶î7kÔò|•Õ»ÐëíØó._—Jù¬Œtžtò-+ iËÐC‚¨~6;ÏÐ 'Ùígc”…hÙ6¦D‰ªãAÅqÜU#•N•lã@t1 „}ÈÊW wÔ¶•“Ñ%.ˆÚè0ºl¨È«ô¬= ;’2Cs¬>ÄÅ­Ûý>Àñå‹QýE ÔƒæG±têÕ§Y4·m¤§<–5=%»©‚<üiA.¿¿AŒ8¶dV6¨ÂºÃëOEóšG…aÉÈN¹T:@›²ÆÓŸ–âÃ¥•ˆùßA@¤¬™2©§ÝS1’¬j̺hÖU¤e½®Ñ7Jr)€…'æ:üÛ â¾/ ¥Ž5Û ˜¶ìT×Q¤ØçZGòï[ôÑ ‡IëÛ¨¢çíek¾ºy:9GªQªkÖ}®d6ú”Ea>¦‡ø¿>7Ä;êBFoåZ\´šæ=Í2@q¤Ó鲆‹ÝRðÏ4ïÃ#Áèûç”î èÒ‹–O¥Ú¤Šâº_×zÜgYϾ{6LÌÛvo§ÂèýÒy§P%FÜðCû°Ÿé°H[¦‹aÌèÚæf-EzBÎÔʨ” œû©dpÕ²yÒ‹|¦nYŸÖq4ÐþN‹ž‹®ow4kÂ¥„ªxßÝY Qæ&_†‡-_gÌ æVNám ‡Ú á¤»X¿…ö';‚+y“UI‡‘Q’¬Ü›Ã²ßêL'² 塜†Û”ЛËÖú°›ÐÏ×Ñ¢£ŸR%”ðœÛ6M\Qö4o ¤YÏ¥bò§ü;|cë@“ùòøÐBuíže_ÊIǪ¤xµ”rø ‡íbÿQÎh`ä~à^(‚ žƒÏ3\'1{‡¹ü$1¦hÚÛû<”…HK·¶ƒî6§Õæýz¢a‚ú-;œ’$€$Å䯘÷yîÔ˜Ó!¤.£%zy6’QºÎ Ilj̃ûË:\yÁžDQBÕQÍâ¥`¬ëº,Ð…¨âbí{]eE2em²‹í&W„KàyóÕ÷ÒfÑüŒÇ<”[FAóØ\Íu’QÁ5Å]¤—Ú¬ùi¡ë.ø ©6ËüÞEO¦C”ˆm"è»Zq™ yÚ6ó4eÛbîr  ¯õ.†[ï4w{½ú ø[šSƒê(ßå8“M›®éšWYÕ/{Q™u=˜YC=)<¤n·Kùù­™U&È-þÝœüL= p›ªX¦#ÀÉÐQ„údxįðPÎzìàu¨—3ŸQêW/<-²‰®'+ÈjÝ0|0óð£ô ,ñ`(¹ìbO\èêçù¸·sÜŽ 8ˆ²&èw´Ù-ð'Âs8r¥$°z2ǯùd‰_WýäÂ<&¥‘\½[÷C „”/ o6‚åiFÍjž-qfîꩆl/÷1­ µöŸÖ¼N¦E§†'ÓeÇ­¤=ž{žLÏÅʬ÷r,UÛ±Ä8 Ò­ ÏÚÛ»v÷.ºúÈA‡öl<0…x»êìª 3U˜5áp„Y“}LT¬wÖ}‰ã±\ hÚÌ‚A¨ˆãbhFJ×b*I§ô÷5Ý+µeû~¾¾½–el‚ƒ0Ñ"XÀ'|†r*¦z«‡Rç²&}oø ºT}šš.¸}ºÌrÈÅ {Ÿ) É×|ŠèöÝ ß9à‡FÑóbÅœ÷R!C™ýnvÂáÄwÃ1Ïw"ªìÂ=°}8Þ ÔnÊW±â—ÑM(¥8îYÆ(nM[ *ZËÓr½¬G·ekd.ò–—­ —ØpØ* „ë_ïí°Â¨ éó¼¯ÿ¹ž(p^­1fcåÚ¢ÌOçCé dš²ƒ\­Q¿UÛhê?d#*·)¼¿Õ/ºkßßðä °@êËb/Š~ÖÝ®¢.iŠm–/7Ê^À= M¿†¾úÛ-ãnh=Ü2.nh»I‡þ°˜k]Ì#¡H-‚k"HM™_sRm¡GMÑ–²ŒŠRT³Zû|ÿP¾¸oBg |§ÎfÝŠ¦ß©³©(ì¶cd²ØýPêG5ƒM)• ŽgEÇ(=-³ø/?äm;ÁÏ›öͼ¬Ë:­ 7÷£b‚w©ÓvmÛjodu ÒÑ?„‹«àÁUÍÂÌò¹óCô¶­»ÃÛÜ ¢ÝÕJ÷^¶›P†1£‡î×Í9ô×ÝOñ~™¹=E¼&Jô.¹«tˆ×&M£`›QÃÕ«ÞaŸ%×9‹Ð϶ñ‡°ËØ5lØÃ/ Þúz+†ª³Ê<©»EÑ‘ö¥–yýöds!*©ŸÙL7{Ö«±îæiQǾôB¶+¾y·»‰Aðáö„})„Šœ ­*i`@"lï1Æ£¿e¥´ÊÝ ˆøAØæ£õ ¿5šïñyrÄSOðá|t²®ŽMؤÀ ¨8¡7Ãß$åò _BÃÀ ÆýÜ H¶œ’–¡Ir]iÝUUdÖ¤º‘"®ƒ=U3ܺNEE< $Ü n`è…ñ®*Ó¶˜{Šn›h>ÿiÁ›su(z<6àx¨RF7Ÿ¯ ñŒìv­u­’¸mÕÐeÇ‹üë‰É»æ¡Ò{;Óàªàʛҕ ¦ú^†YÕ°"ù«žúõç{ˆ¢CÁÖw ¿¨…mÚ0'é÷Õì½½ßêß?0.hµAì=°"<ç³¾8EÚ-j›~_Ô:Ë2-5ƒ‘ÁO)xóàeŽÜÚËm´®S97ê·cÎÇÜò´Å)ÀNa±šÆ´ý†r§íÓÃI»Ó¿­w¿Ý>ã,%¾Æþ•u]³ötzŒHeÐeëùÌ£íÓöøÂó€íhH@D±kEÆœyº-ëU•ÍÖI&IëA:éf1ZßTÉ7ïÃÉçøIS{VŒÇ„äº4£'ÝÃ6G}Õ'•Œ\¼;[ÃÞ¹V´Þ°?ï²ÑL5¥CÕ΋á—kÛë’ýÒ˜Å|Ø\ºPx íSOá~%²A½Cæ6F«ohŠ$GI£Æ-§o"¹ÖƒÄÑrqJù ÷ópñ¡Êý}€yåî‰J»!•5.Ó gF²hVyª¢t髲½ŸÊuÈ´¬OŸÀBßA 8ÉX×&-ŠO@#6¡]„•|SÐY—bnéÝHƒ€Ñ>ŒÎ(š–h.W5ůÇ×ɉ„ ¢P 8Î.)•Ý{†&Š3X/¤¨máV?11 æ‘·€Ròî”LŽgj[ßï]Z¨f™Gúz2K¥0‹>­K··%øH_p½úyð’1Ñ ´ö5nô’/q\/²h¤žJôÃÓÈï=K}ÒÅû”!I ?H}@A7o=êx¤:yŠê:«"!Ez¶± ,¡Hyþ3úuº›¶âà·$=%oÇžÉ(´¢<Û =n:Ÿ ™ÂÓ‚€¿”™€ça2Èð*9ƒî;›f ¯]@¸3¾½y5]6–mQOƼ€J-Œy1ëµ Û])€ |Ë@¬b¦¸ÐFPÆ¥»î)%Í·ešÍ/†7D”o·Ê#g·VyÄp–e¤ßÕtuÜÕݘ4I]ÄEW˜5½ì ǧÔñ°}vîŸe×k“c Rû‘·}èÏiÕSEeCu<³}½Àöïoü5=h(B”+ÃàOÓ–ªëŽ*%Cÿj•ò“0ðà3m.ëC ˆRðíðÑ ¬¾Þ¨Ì=DZâai—bØ{YÒP*Ýn‡¾,]D—¼Lä`Ÿ\x€ýG9DÉ„^N¿Ñu¥CÑZÏ™4¬GŰy‰uýÍ/D)¯)sdQ³Ö´ÎF•%m›*wó<ÈÕˆ•í­KÉ”qœ»»×üû¹±A:Rl+ )j1^ok…1t’nš²e¹Èè‹ÂÚŒîÙððÙëﲿ€{ý¤ÓÁÀ¹$\×uò.ªâQŽ ¸\z@Ö®ϾëÅ×û±mßσ"ƒð‚¶ 8ÂnÍ«f‰"­ó´®…Eè±UÖððsìÓ¤çìr=؆‹Å[qP¶Æ}.x}ÖETŒj(Ô¢öTD*(žbHgƒ¨à:ÊÔý˜š¿¾~¤óQ¢î`dí!,Tïí’ ª)¢-šd÷Ðiñ˜ÍC;Ò7ÂTwë_Ö»«ð`eøÒ d«p6ÐB‡¦Ö#o¨"œ·ù?¬¼»Ð cwAÁÕ@'¦éD:¤ÚAXêˆr±i§øÈ †7 W¾GùÚ͆ysÿRú‡3ó‹)LA#HúÀP?ÝÂ5¼‰Xº=cl !­h .›L©=@ðÏëÉŒæržõÓhØðhèDö¨šé«+5VU–™>Þ­ TRÞlsXÂSgçeYÍ”ú¯†3`ßPE@›GÓ‘[ÿúkÑû¦ÿ¢ ³˜öhIÒ–ö'ý_(·ÌfµõK»š?šÅ0Ópè|}/lÊŸ=9|®Ò íȶ6¶c1j=wª]T%…8“ÐzC šêm÷\ïR+0ÍìÉðvù±ãI”ªl^Ó}T}"Úä…üŽŸîààÐ쵘8Ë t8ª‹)·GµÐ1jwé~¢†vl¦iÌT‘t… œDB’ž× XÁQ¸Lf¿$Û} *¯®Q¬g]U«)îâz_èîEÙm>›Ëz›çšgGr2¸*#ݘ}5˜·ñèbUi½ÕS=cËšp¶§»,C-¤ñ• AZ»-½Ož5Övq9ÄõÖìs–ÒÇ÷owˆ÷Ûô¹]˨}Úö‡ ‚Ö§J|Õ35•ªÅ̸¥ ¡’¨Ïd: úBô6=”ˆ¦Ms°|ê€Ð—-<ÙÅ™œö)®âuTÝž´¿¯þÍ’ýñ-:#HÚ3ø«7(’¬HjÈQ´&%j`À°kx÷¦.Léo àß'—©(Œbn„+b1§t¤Cit¡@kA›Å?cÙP¶ý¼Ì†^N9šÁÐËéÚ¤N÷.Þ¢_Ö£¤Ü¹ ËbzãLìÀ–8pKªâ:Ê6Š´ýñ}˜eøPÇ=ú žuéƒà#?¾ô“Œ,}嬞UÓ¬+å‘㦸 súй†2¾!î_°ÏO^ÐÔ†E¼E+”ª ‹WOÍyºd‹¬GÑÁÅ1„rø$»¦?H›Åª éû¶jFÎcW/K[i‘*¥k1/ò- Ÿ¸ŒƒaÁé‹ì¼KM4rjÓ‚%F‘ iÓÐF·¯î¶y£+s£BߢDÚ³÷÷ÎΙ9Ì/f PFðø–î+š?¬@GWÏv<ýiç6ɪõ7É©‚™1jÑu˜Í²Q» ÝÝQá#¹%Ôa€Ô—©lá9¡¾a‰ø4Žåu_r*!¸BY¥šm«&™ ûw .v°U@—ÎXA\¡ê.Na䊡LîFj¤p„†˜}<"n«J*7†¾gÒ×Ê„ë;#^ cQÙS<´*† ôÜn› ¥õaƒF u÷~¨\.¶_lâ7Xw%DZVJ§6IÒDÑ.»n¯Íovà nNàÆþÂz󤻱q,85 ø»H(Óñ^–ëªz*¬Òº1kºÀ^àú xúÍ ¬1`ƒßçíÎqië=îÚ)íuRýyAÊcì¬Éë°U3Ö½q>çJ+8_DYJ§U‘ù—LBª¹O¿LÀlÓTÞSaÐÅh}›EáÓ ý6ÿ~¨É„ŸÆA__?úûa ´2^e±žRôï™®€iÛ;³&=²„}ËËëÚ;à숩Äÿ`«Ú¶â])•ê2¤ZkeÆ— ï9ÐUÎqìùuU!å”e‰ <R²|yÒ¨˜v¼^ÇzÎÌŠ0~»£sâ  ãÏ`÷z²¨§ÊÅr«“žå·k”µ¶º¤?AÒLÛwadNé›uÈXùvx}“œÎZ?eÅr%-Ë„#C‚GÝJõdNï‘òâÿ¹æÁ®xŸ~'! üÛbÆÈLe*ØhË#Aêã*«šU.c TçCqÂóLYÁ˜–‹Dá7ƒqá¢Ç7C2¬»bØóD'tIu‘ù,Ax³Bªy‘û”…ð“YñWJãø¸‹m‰ËOQ©‰­Íéž*RA»ÂÎéà‚F¸}λ8×/Öoe‡gzS;Á3 ÒS(Î÷.Za(­Ù²M8¥ÈÀp¿qÖ~ˆNX-jöM:r›š»ŒÜF‚¤*m֮ϪLÈ ´`¢ òF!‹cïµÕ›y”T‡Ï<* vè± ÊU/Õ¶O£ÔÓH4,ëÍì›s{ûÇ^õÛõã\…À”, BÚŸú"t˜âºùdÓþÀ…fÒíÌ\çb— ®Hä5$M¡ÐÏ9;7cŠF×#4æÓv›õhº`ÁÍõ ·î½÷ø‘ÑA,é‹á瀱2Åy`ÒÒATÛ¼ïëšE{4Ñ´ýº¦õáÃøýï”*˜Qw?š¡wÞlK“5½JbÚ bíéSI ‰!(xÐýÌÛŸú%î9»ê¾@Æ2·•Z²¼‹3Ý÷fÁRhæ±mï¼yã¶ôëûðI¡ vèÃî©èFk¨ šç.ï$ÔÈs‡ÜL­“¡z¹!7 Õhó » =ªI‘oÐæiºi¦ÂlTmÒlEdš1>^ „å EtàQmï³$}™–º«` ç HóQ£ÚmSe:Tó$` )*@î1 Žƒô+‡ïðÎàëØ3£Ý´¨è`¥»Ê”á\ß2nF(–ÙGÎvA½ØºU¾0Й#Î_8Š–A-Û%²åt{cº¬EÏå £• ·~è×0˜lú}ònꊥZŠd6oR^Çrîá-¸€Yßÿ†B9*ñRÒ(>}ü“Uº×¹ÑÒ©|¶‹h®RA⇧ÈÄ…à„RêÁîb9‹TÔcÄ ÖË„ví˜ÖéRc¶SPI\õþ†Cå)¦/"Í%™F«éeºòÓ)Dª.`tRš=/ÔØè¼3 jãÛ°W½ãè~Èo?(;ÁT3”Cê†ÂHPrÆ ã¤H€^5½ö¥ÉOüð£ïðõú>ì²+hŸ5FEŽçmïËìu#ÍŸ[ǹÝÃ;H¯'"ñÍŒ{~½Xi*FÓ §¡á$ŠB*¶¹Û†2€bÕÑï º†bFøÒ0¦ZhMý<Íc7!•4›kø‹Q:^§Åf^%”$<žGÛŠÎÏ¿> ­ç¬ éDÕ½D±Ê(Æb¢[7cµÈ] o1À0B(X½;•ó ç«1…u-$HVœ§xšÔUyNI:Ê‚wØYZ(Û¡àzt½{1CPÈÑp©{aV¢Ðû,ß6Ê&"­k£mDKàæÞà›9Qà…Ÿ|¶$N·›ƒ@ îaX÷«8Ý´ôÍNm¿3ç1£ÿµy‰¶‡ÙyèÜœðÂ\|§·Øá‡¦7Ì1[  .â»ì‹j(¶F£R]¾¿ÙO¶…¾‘ëåÌì:’ÿ>¼`2>2 7|y ˜¥MSÌ•jöy2)­çÑK¤£cŸdMÛ¹šZÀ}ƒ *’[Ö팳!¿©[–-n‡"ëÌ+„j'xQ”‡›¨÷†©Ï ÓχT³M>?M熽V­“ÎÚ"é”ùÕAâüto†B *ÊUUáLåÂÝ€ §ôè&EÓÆUše±™ä$D.ÆG†Ê„#©w>@6”Ó?Œs=\þ E"ØAôÔJ·úž÷é¨&¡Iù”Þ%{s­ 8žû횕ѧٞ£­«¼åA-F¬CE»z§Ô9iר?ònsÃ.¸b%…æý ‰ùÚØÏ‚¡Ju-xcÐE{‘mÔê±l"³þîð•±o·Snéßç üâÆþK¨aiAe‚‰3‚&+ªA5*Ë‹¥]·R¾ ŠL¸ÈZïN*ÌLáqN~~„Ϙ­©kg*h=mÛ¢Wý×_û_ž*]TšR)·÷Ý®(ÉŸTizÊ!Õ¸|)N:F¼ “ú@ 4ÁëPô¢ÂˆîẪjzÁ¯7yAÄt(Çh2Oï£ND÷;ðO <çB°…ê°ç•ªÒôU¥ üeÈU½7¹Ùü”ŸB´7ÀÒ8Þ5ç}¼àé‚{8…[/sxp†¢»)TJÏ—EMµÌ]›Þ §×K›ÿp¾6Úôöü2¶Ç…¸ÄÔ'§¢i35%GšlJåGÓeÉHø‡Ö‘ëŸÀç—á*@pšŒ]`p¯Z×¢KŠnó\¥Ç‚!C÷i9§Ùê£Há!Y‡Ú³l„gÉýÔ%›¦)J·Õð僬æav²Oþ̨ ?›¶Ôs¨-5§æC½·y½oK[¯}¤–v–!AC‘2KW®aÛ=µ¾ENX4ëXN¸ ® T{NÙjœOuîY«ÌuM%v•¡¼ÿýé‚+á  £  x-B­}f9˜BãåŨêí×õ¬ûe=3_¢“Q­]kìÖtU›·ÅJÕN.ë5G9@@…‡cýÇËðûEYóÃJáNh{É›!(•ôª›«(ëÔ4¬f9¦P°¦EMÿѾèIýâ÷Š™ñû‹ë¹^;*áe9Èàx®G§÷v;N¾£ ¾<@Q«ëºm ðdiò¹ÔK—&{“dý±ùä>¥etänæk¼'@»aE>lHê«Z°”ó‚rò,T²¶¢w…ßÂIôI·ð"úôT¤ª?©H«€ @4ľ¨H]À¡”–ñA’Çv¼-kçMÓı¦/\6[Ü'É" R¼¿ACÃöüàì/ ‹~pÜDd‡j—䯮´Ð+ëtÌÚ92§-´Êé)Ó¡'=,"oŸÆe_O#xœ‘îS™þqÉ_(ÓæTµåÎãIʘíf¡7zæºîõâˆü<¾ñ éË®e ‹Ì¡wë,ëëb41äO ~8˜ð|òi$H“:¦ˆpâ­–uÝ÷%Î5®"3My íš;ú;”@Ùqâ~X1} Š+F5Â7á+°Í÷µé¶™ Ω—H}‘׆ÁíùMÎSòbª4DÑÏ‚JЍGuõ¾–yN+çM?u2ò f…(äÜ |tª³_~0] Ò(¢®:NA¤ÍØëB•CÔyw½„ ä¬ò±¶¼G¨oä!e/iKHÅ"•½»F™ůßÌï Áy ¨éÛG~&´("¹«²².˜tñvKÔªŽ»t1n‰r@ V„–u|”è FѤ¨Ù"~(”Ì yÒô·b¨Ç¢U²$b§z˜ß arâÞ¿ÀÊQB‘¼Îié³$Û¸õóZF[8ÈüyÁ£›µ±ÙÈ‹=·X†+ŠÊ’öÈØÌý2Œë0/3¥§E1U}¡Šf¯·>Û M5§™ÁÜ7ðï6>ØÝ½²œ”¼×Ks“ÿ¢WyT ã4Ìo!öÿpþ‡5ÃSô¿Z0äëç’=D[ÕÆµÚ(s†ma},I߯£t”Ê'ïZÐÚó)_ÆõVåiºSÕt,{«ãdÑ”bÈY¥Z; ì×' ð~QZ§ƒ°=0Iûæ²;ç±$Äíº¡²»W먨¢¢|Ù„7‚°æûTÐí|÷ܳ‘xå3=˜‹ƒH‰8T‹’=æJ߆2Ý^í %q®à„†l¬ð ¼a2¯/>D¸ôÖËÂßu£º^44ˆ¤( àmqcMHר„°[á;-}}mOi×äiÎÔ”oB7Ob ”ÛDQ­5ÚÑTªùè]Ø7ú燜 k#‘P^ ³ç¶9¤?Õ¼.ÈfêqEÞ–jAˆ±¡ì¦oa½o»÷WF&ôepŠu]ÈaA!SÌY—ª®TcAEr]ËHƇ{´GaÒÜÁ•žðÜðE¾9ÊîÕ|<¦8Þtï°‰ÿ}AÿCûþëõ4;›6  ž,‹(rÄÕ’Æû’«F/eßoÿiÉ‹cē޴ˆ#Azº…¿CߤI®égoS¤ûnÝ—_´ïÒ?Å– mÌŽÙ}w&wCj8(º鿇î?½Äûhò€±áýáJìYÿòàýåqƒÞa'KÒÙeõ*îíž¾kçùñ‚“9‡eÕ0¦·6;±Ÿ»²UÓVº‹•ùДW¹6•÷À U(´>:›?Lì$”üY>½FèS(L‚ÅŠ_öó²ÀÌÙïC)WfؘjV”RR…^ PCaѪrO6Õ7ËRSÍ€êt Ž.%ç^ÈøKÖ‚t®.×Ì Ã=$• ëñOîUçiSNÈrЂö(Ó Åd½öýz9ÐÝ Y4ˆy(¬42Ânhµeß販÷LØXÊ$hä§’þ[Æp¶~^†<‰±L Þ[ßË;×ER´Càv±MæPóa±âÎ~hýëMÑ1ëÜÛ¹à ¶5çmSå‘Ê[AðÒ’6xáT?Ð_ÞÉßþAçö‡– ÖÙâÅŒµW=m“š`ÞR°šÎ:ñ®‚Ÿß&ïe’~Ë&5’˜WÉ¢ú.NëhíÕb~1å"taÛÛúÁ)Aw­mXüHj›vàÆêmÚ9©âdžu+µpƒðàéNÚØk‰`1¡ä†Â­,‰À@¹1}˜Ûá3xŸ1ÌÎN¶?hoÜý©î_ƒ»Um-¥Éùh>´u ÛÐÐ÷ObÐUYòŸñ¿LAq…ph{fÃÿëCzCØ>J¦CmÖÈÇm5WcÓÔ øÌ•I>QÙØøî­ƒãøEzÛXíû”ŠE¥84‚¦VKºï}Ýéµ¢3Ã?:„ΞEI‡n@ÿຒ&i{SZÇ– p¦©[Ó_€%ȤÍÒSƒH,†¹Ûô/×òîîGeøªâ ëZS'¢ASF·QXê{‘V{\ÏUŸô…Y’w•ضé°rÇâƒÙ£DG˜Yp3ðL1-–|YÔœÍu4M‚˜¡õoãÓP´ñNyÜkCùþ`æii厹þr[u]Ðéº&ñ¾Gæ7;H" ‰QûSCô ÅÂQ’9U7îwcŒÜ› $XѲ&]Înȃ¶A…ùöWgþœrM×)-ˆA!]@+x'§ì¼õHKÞoÅÅQFɰ(£ý€¸RUWVURî“Ú…ƒIáÖh#ÂÒéžÀû/ñVÌßå¶ŠØG1,åÓ®šæŠê×߯wÿÂèRô#Ý3v~kYnC4I—&i!á?Ëj>5åI¸=¸EZ§ ÑW˜@({^ìœ@áÑõÇΩÛ;†[Õ²¤åÐmuw¨:èó°)þüf*¢ßrgqÍ,ëIoKSé~W£¬Ô#•å!•÷~pÂõ®—4›Cø€ ©Àû;–ÝÚëhŸ³†’0º^ó|Ày†¦¢×ðboW­  šû ÎK}E5­Ñ<£oB•dU“îÌ+„£½DçŽ^éÙ!½h-°¨XªSÈÄŽŒÝ±G*Ôè-¶IS¦…4]CªÇýGåÚÍÝ+î¡¢ …Jð(,²Ô%=bïUÖí§¤Xd½Ð¢}âSàLrǺbf wxþæÁÁHãb:ª²¥‰ ]6O[üûí+´ˆê¡ÊdËZ£èþEZGPš£^UùÊ“±Ð湺Cß–nƒÛéôá]›š&Y§áábÛʬžjüX×ñ2ÆÛ2D²ž…މåx4Ìh¾Ú®˜cñUP·8 Úš¶ë¾Ç”“@uŠöõ& Ò…j±Ø}7¼7hñòDe¼Ý,E[³Åv[UªUIq‡NfŽÇXƧϧ÷òz¿€å³G{».¹>®{ÑÓ¶)úJmcg¼­1š@ŬͻPü/ñ´Sî`å`¸¡CÔ›ÙSµ¶ª¥rm*ʽ&³ ÑÊh©>¸Ÿ~µë‡f5éÔPb,´Ú°ÒmØ/´Ï‹-Ë"Ñ,udê pwïg¼¹:$b6¦Y9‡¾r‡ ïÄ!ÑyÖÌE“)•`âa0„ª‹6²Ê|ûý<Œw%½-®BÁ•w"²;*«ãY—Vµj8‰qžÅpÍ2éØíb,]6ã¨ZT˜ù²Õ#ŽóZµ”nç[¾EIÛÈ‚Œ?¡{Š·ô¯yÊsI㟇áÄ–p÷åf³ä‹ó'§dœ¦~éR9ÏôÊg+¤ áØ9axöšª 8PõHqঠ™ï°zÅœ`¨¿í“4KB´­¡æÀ2é2vs¿D7¹²z;Þª@7§=ŒW–uŸõ€âXJA w. Z ß*T9.¡ÿ?ØWf9WËnpø=/•kÀy.Âæ#y@.2îØgT„äk=mS4©Ñ<â6Žw‡f€}À1Â/U(DnSMÂ˾ÇešWY›åé\Ù<™ñ— úWð;¾F0"Q°cç`d™÷½¤¶§[¾÷Y½Œûß<ä—W¼Û,À˜¢•NᥩÇ9òШ¨÷V¥KVgu,#V¨µºp‡ PòûŸý}­á° ÏX9½ceµ¦Ûã¸O÷Fë4ÝšA¨ 0wôÂ¥Pk™Ácp³¿èð…”k0§‚ ê†#cÿÆ]FÁ¶ØÖ¦Þ¤¯ªCá ºXÁíð°þÒaÜÞˆ>ôFÕÓ²OÓü0šIçf(’¥·=§,J~=TþX³$°-Ó–@õæ^tО<Ÿ¢ƒÆº*@ÿKÀкj·Hé•r¨l•Ù-º”,SÔ Í~Ȧ߯š„ì¡÷zºéT½q@‡zà¡|Ù@ï¢ÈÛOæAáÝézx§¾}?¨.W­UÌiXE‡B/K% R;¾šó©K…J‘î mV¤‚†“ÒvÏŽÌuî%ɤa­Bk €e(3M{½luµæ·sÎ|ƒ”€*Û_s/CoHsÙ708>(7E¡DWeM™}2˜Ç €4ƒ:ïxáQ^ŸG}êCj Ž_5†ØæUõ¾ª¼¦c:¦å¾B˜ =JJ¹Æ¶ßhŸdT(/–¦Cð8}T»+]•{ÞE™6nã!=tEÐElJ î§*cH‰kCÞÀW‚çâ·mó!.v=”ØiÊ,·ˆ×9Ìûuø!ð]±5€È´ÆuHÓ½Ì3:®i•üfI ¾`®Ÿo "XúÚ£Xø¨.êâm¬â¥Þ[ù0ðlãÔ `ð'—Ä)‡²‚vJá•&K‚E)eöðŠ`¸ó áýjÞU£ã.ž¡–V·êøB!L©ò¤t4Âo™Ð_°™-˜¦ÂXì„E-e¹¹0ᕾu®6¦Å”î[Ƕ¼}±xaÁ(-᦭ ’UR0íó¶Íë9¦ {MÇè²Ãt‹»ŸÉÛ%z”PV3Œh0$›&êò=Ú}I›8]Z0D'A: `èyßnCOƱÃÁ€r!t 9%çL(›[56pJj¦õïüòÄİuRUWÒaf窓tšïôaötÞj™vPÌ!JYè›si ¿%¦1Nºï+™Ñüç–pSDmY”qÛM¥l ^9À’¸§-¯ïz_*cº¹Ó…+·†Xod™ÕH—d<¬Ó˜f½À†©, oqpS„g“ôê4NÕ—°´2 ãÅè-®±çUe{e”¬õµyFÊ4÷Æ£VÌÙ ôÚ džø¿96Œ6lApfüª<˜Êy7¶€GÎKÁÄ JZž,·û¸oñVg›îÅ%ïw ^Ö^hœ…5ˆn5mbNÖvµs7ƒøÞÏB¼ 1·ué[@˜04Bßûÿ ˜-Ìñ’Öeúwh·¸Áìë—fPþÒMOùšÙãÜ‹Ë Ý E‘}?÷E.f>ÔÇá9žð§òæ?IÍG“š› ŽA:ôÁ,p¼Ã35·ŒÆæ(Û‹ÍÑ—B‰å@&¶DcJçQ£Êl¬Ó¦ID#¤Õ…½³xŠž]¯”Eì__ÿÍþušþìÿ:ïÓ±*àöÁ=Ä鬹 B& Ÿ0î_EÉö1ݼÌ˸LÓŒ`>¶S¤Òbkš=Ê(±3 å ÷îûnxªáÙþ·(Ê“göH®Ë\„³†®_2β}JÔF9VZ0²™îÝv?¶,cw„þ—ÞÜ>|Æú¸BšÑ@$umóv(¥»‘RøóȪPn±lؾ>?žV6d˜¿ä.3 &ã5q—™ü²Ö­Ê²Ö<&"1‹[ض`¯¶ºì’øxVݲý™@ÑÏÊ£|Ê©öiw{ÁkàæãK×Äa¸@Ú…ÔöüîÚÙóXN¢Ñ¾0Û›6êékU²ؤ¾1<ç~H˜|Ïŵf{j†^Q#p4:Fè/U{ªÚhì{%µYÒ­…/;8ç‘—xù~?>ˆ/‘}2Ó}‰U×eÑ@ý¦åZw׆߱ žó‰—WñÕ×ÓØÛpç`…/C䣋q¬¶QmÙ y‰,Å…®'´p-ƒVÿd†‰„’ç¥1Ð(oqOæÚŒt‡—Õ÷•ÕæhI Ehrºr9rvu-Ê~¡|”ë¶b­+Vp¿5e™ñ¢u¿—KÇ2Åk®…ðã»á´懲æ¬öM£›ñëÅó* b³¬ºy\ÖMOË®ßë¶þñÇþ~S¶ž Þé©aOJ†çm£jþ,ˆx6Û‰ ÿ"òöÒZ¿e°X"k’HìêÆ"ÛóªHT‘!’N[ÖýnEïöe—e.¤8«: ï)†¶8óôÅhtÕD¹+e™ µýët¯*tTGj#Ki´èn Þ+ÈÑýQw[³N­Yу½{èƒtz6Y§úÃ-ŒO€x£õC3rô˜Œ7Z“uuÖî:+³U²pµ†:ZŸFèûçÁœ|àÚÊ’uÙŸ‰¶œè·ï-»bä,Qˆ§úÞõ}h²Ωí|õÜ€x\Ćm´\X)Ê>âZeÍR³t¯!Ôä€`dî8†Ü^Љñ,ÌN;µ)c–ý¦ó^]sùœGÛ¬ÇÊ, ÷MŠî·Ð –û×ùü§ù¿Y’œÈÿ)Æ™›ù¿}I?„?˜Õ ·“¨„ó¹#À«½RsŸ›¸n;ø½´²}?)ù·û¿¾NFhQN]ó!ž&E³Æ#Nã^É†Ä :°|Š™¹‚ŽA7áãÀ£ã&Ê߽ѫ޷n/ÍûºêZŽ ¦K€·ÞœÛ9‹°î— éù~¿žbÀ‰×æ@ÊŒŸÑ…Y[™FQ7šõ»Ó§ c˜dL.¹_ä`çmÀ|US–uϰVÑÿY”j§¸¡¢/ß¶JÖ¤—GÙ›ÝaeÃÃ+Zç©ÚLã tj¾Çq°“D•M›Të@­“,}wÆÁÜ-“°CúÚR>UÃ07Þ´æÄµ¸†\% f£ÌÝ¥õ|×Íãºî…ñ­/ŠÎ3ƒ¸´ãnªCÒ68œìýL•Ó â*œú#ÀÀ¤*ª®ä­ÝËà|ÎæqΆŠê²­îÍz°1@ß,h#(í8²Í< ïœ~lÐé›Côš¾{:¬ËB:šu>ÿ~MïKÚ º×a˜²¶ìâ0Ì7µ÷s³OU×™¢¨wnt¯ùaø‘©ºŸÊFùšÓвñ&r ¦7ë¼Ê²<šêü7 ò¿rWÞ,8ÇíU”=RõÀœ¯ ³¼‚ “Ïs›´¿_ïS2ÿrXõÊaôµ¨p°O ÊËF¤­Åèдù Ο"¤góv¬#¥Û~7Ë…wèÃ@Ïð.¸­/LÖë}˜0Cˆ§†Ëh"÷’@1ª_Ši& ‹à'»ž ÃÈМ7üÒg¯ #ߥé-„iý¢5þÞ¾/JGªÚ'³¦G‰®}so§e¢ï|3ÉiÑ—a`À–¸ì )†2›|Öj§è– !¨ ÷oh[À4˜:ÏùÀsMZþüJË)úsZ^lœ–›¬×…Y4ʼn nö'-?;é¬#óþ%|C¶LÄü€78¨¦óºÑµ5¦u=%"gzÃÍr@ea ”Á*]Í[^?o± 1Q(üˆD7¢ºÏ†¾ÚrUÓô»õ,ßþnÐr¥÷„ÝRÝ”<‰Ç@k`»¥a˜•RƒJªi›÷ß­iwû3ƒ²´€ÒèŽêxµAœé:9_ÇÙ¶ÑÅȰäßüæû5<*쇫A8³!«¼RÐR³ qO~?!;Á£ß‚’“ú¸dŠ®Ðí¶«Jh@%MzîZ%P7+Di‘»~pñÌÂo3žÙ¬ËÓŽp êZÍL§¦+“±Ù·¼®+³¨{olãàEïTæ> ~ˆ8ãÓj¶è‡n‚ÞÔ¨°Ÿûzï{¥“$2«Bƒßƒ‡»w‘¾ût6¹»Ÿ2ºÌ5†c5½jµ®}7F]_È'€ ²’BéGMÏùÿÐVÝsùñq Ç›àæžmUçRˆæ0H uÏ@ÐðµµmÜOñTÍf½€ªÍçi¾!}_¥ ŸÐ”û1i„šV¸uøèôo¶¹X†Roó(å\hÁ)šò5ÊŸƒÏŒñÃs‡“çûuqòd‘Üþtò¬T½TCÚg1BWÐ÷؃à|—l’Ф÷AjòÍÄóZ‡6¯öqÚ1—MÞêÈŠŸnÅõþ 3PÀò:– ˜íN™¤*öuÜ»>]L_T9ðŒý°#&¤Y_›0Ä|°jâéˆÙ³'Ýx±Ä\[z=F놦4ðoT»ÛÁG"Ã=´Åáiô|¦VƵQ”Brvê;½-£^·?æå?èŠ Z¹IùV­1¥ë»žÔI¦EàÑ´hû›ïß. êsô¤´æé°ké?JIQÖo}VÑ›¡  R Á‚”µ‡†xs?j“™^_O®v ó‹hÙwçèuj ƒDÑ®™À;Ò›Yˆ ¦Ñ,IßµˆË æ$_aÇÜx~ÿº6žÅw`§”Ü4žwŠ›sÛÃïåáåíhÌ_j<з§Íj´KÙF Z#PEUÅz›y@J©à> ?Ô%óU„ýs-u-Zê»ÞˆiÜϤU·Kf¡_?(p¸„/+úÕFއ¾ eù{3ŒÛX7i-Í>¨ÈÀc ´êÀ NÔkyü#úû¬ %ƒŒbÐ^ש®©«óì÷ ~x WƒŸ(†ÏoI¥«¶ ”ûôý®(ÙPªÚ«rÏ'§Á‹î« oû_GEU .¨d‘¾Ží°è£ŒÙ\l{YdËVÈz!+˜ «îšÁŸÚT ˆÐ1zÎÜm:˜j¢.¦¾VÑVKÏóXö ²h`æe8Í}Jø"”ÆtüPÚ åÐã”è=«½(ôT K›,J¡Á†Œã²óÄø—ݨ [MØÓZ@ Ú›(ÊâlŸ«­7ëAÑÿN‘"œg[÷ÊÍ{RÄÄ¡ïØtt÷5 -m~3 .„¡çdàåþÕ&ð—¦ç£ã¼_ %ÝÆl"…P”E(5±_±&ò„.û#Ò)ôÔ?EÌ/™ø‹Jã©mÊ^É ¤³cßÕËÒ(Tž “I!W½=ütˆÂ¸"#,á—å[Ãý¢„º‘Œf1)ò<Ÿ«¶("“?ü·¤°d8hþˆbe¥µdŒ+ßTS¡ç­Ý‡*o"*‹g³}TJë |QnÎã÷cTÖá~Qñiîô®{[÷i}»µÑï×»_%¨èS1¾©zBèɵŒª›âqÜT!AÌ…œžg³Ž½Ïa]TÛùj~±uϨ‹~¤ q0¢–ÍLÿRÕ0GM£d–dyØ6¢ô¦Ég]Ë8”ÙRÆåð"«Ø«xt±-Y 5ƹê²Vf?–çÁüÁ @Äô¬Öaž"ò›œ!3iý® ïqj‘ÏŽt›Ò}J•á ò¹­³y(MD놸ß»‡§§Äí‚Kdñ•_L{(é2F•Wœ›Ru77eWu±®ÌÑñ :âÛlJL£³]³'g™Æ?„`F¹WÙÒ•@SþÝÓ³r›ªÙ–Òü¬ò±ͪ”5âV€d¦Ñ;¶Âo˜4Ì/ž¦3СF¨Ù„gd„øšÇéÐÌ)“Ùútoƒ@¹‡¡là_%q wÀÕꆙ­HmYÂ=Ï»z¯Fª;ã¥6Kz”mOqøv¢/.ÐxÄ5#KP€UwµšuæÙ_mO; pºŠÊÍÌ ñ!”y èl¸}à\oî÷ÆCǦ@ˆtµaèr2&ùÖdôF‡>îr³ ]ªtS@­ÅNªk> ‰}ñ¾-xä×cv)’f‹]j³ÎÖªI~³8ëjå´=ž¸•·fÞZ+ôÖjQmÖN{¡ªLEõ×KŠíÖW×âù’o.cIö©ïŒ”ùº¶%ÑyoÛi2KzT¿ùt+ðõT:¸ F.<á2HÀF÷¬ƒ”]’F-e?y¦Ùý/×cåñû§û Ø!̘ÂbÃJ³ 5Ç6o·´õœvt2-Ç‘ÒæìV*K-”+€û#‡›C¶¸VÄ#yžµ "z¢ÿŸün0­oXצ=y4•¾õØ™ò%ÈP±ð/1':fî·q§gÛ×7:üñ.Ø¡¸HWLÕóu\‹µ¬'ªc-‡º+tÚφà¬ä/ß žL_‡Jo«‘#ŠX¡”¥ˆ­ygªÀ£dý¢;à–Rà9_Ì(½>¥{!b¢¬jÇþ}™ZÛ¨·5mÌ ñîÈ…}**‚ÃRøãéfâ³f ?d…uIíUÆx#-L³tXtMUw¦âAd¢ê{ÐÊ ?ÓçØä¥ö‹eèYås¬™Å€»³S…‚Cü¤õDÿÅtE(7Qjáv2*Ó^ð'Q%j¹/öŪeÚø—x¬´-¾Öï¸OVxQ=“9ʇ7”ßÎìáס9ç„nhOá¹Sº+ãNw]9 ¼*Ÿ ¥ÐX²ù_Î < `t,*tw u èÃ<¯5 ,袗eÁdænØunðó½òÄö­)ºj4;Ø9ašðŒëÖuŘ®Û”·™$¦´(Å&ÿ~s"¿Ús¯D惥mÏ=ŠåÔŒL5Í`·½YÒƒä!íÙ›sسcÂyÑ ÞŒÖ1wÉôØß#*:Ã^ìJå[ÜË‚¦ÄXÎŒ`Ë—¦¸áñ°h=Ýúu'˜@äsOHw²q4ëAŠhæ`ëÊíñð7C©ú±í³ZÃ%eØ»1“ z”}×voZÿté™Ù› {fF)Ä «NfHœG W×$­´]$S²#)µhetöì£ok…ßæâÊx®~lŽ-dæI—Ù¶<.opŸ6>Ç‘®Šà¾9läuÁV ;PØXZ=PÁTiEëŲ °æ·I…ØÇhõ´ª=\©0£(«º,åwŸ¤ÆfQi’ÑÙÔ´žùHœÇ(¥7äôÜÃkÖL/’S%î’bÖ ù²"îãr#r^K¨œÊ’`íÃÒ déc*ùÕb8ÄkŒ¢P/R,>8}\ ÚæÎiu­¬I¡_ž“žw¶ãå«]P- €@/šÂU½(ÕÊjÌûErx€üÆLÁ‚f–w2áŽCϰ×ã)s*±…÷vý;MRª ó¶)§)Wp­7Kúá= únŸÀ;€®pÕÃt;‹™;ì¢Ãˆ€Þ´ÀC´he^£Ow,E[Ì;Ž,üCuxîõÃŽ1G hƒQ¥m¤$(hDû°k½ÛÖïÜŒ6t…<@téušgÊd‹ƒ[ïƒxކäíü2úÖ¦BF¦²‹ $êКP{ZJßónšç,Úd“C¯ÇÂÜ’‚CFð"¦ÄÍH& ÕI’UyÛ³+&=¬Q±ôÕI]6ç¹YšÔtqÓšSãßíÍ—™¥0ŵ¬ú¡0a¸ÎÚ0\e=‹µÕo€û–Bý5‡ÅUË^eVºÁMC.Ⲋ ×&)ò4Q«|jx¸Ø˜ûÆ6C,€®Šz?¿€WáÝ9KÐ/¤«@õÊS­öX§ô>L~)8 ™TàN¼Á¿¿e®ŸÇµ«[Èà´" £Új®ç¦ìum‰,ÚqÀcÂ+žÞ×öÐ?lÑš2¢é”8=¡\ϳh© ›¡s'Þ}þ0´è„ÿúèmŠÉŽP˜ò’•ÖèôÝ0MÈQ·m¥º%î·©‹LaEéŒ@.åÚGšék(ÅóŠ˜êò¦,ùE"ßNÉu×ÕëºÏûXHgʆv †ÙP‘:‚¶ý2TÙ–ý¡1 `AKhúÊÉí˜/˜Û(Ü3 ]ûÇ< ¦„ —"z IAÕ)KI‹ÃUU«vj#èxÖ³J A.Ø\Ï‚Á> F[žx>*¥~^L=ÎRz¢žY5³Ör£}-‡F sQI±K †¬ÜëBÃÝù4NxÁó!MãÐÓAJ·Gù?˜„%ZÇ­…fCÚŽ›LHaS’ %½÷Ójο2?VC5¢T¬ÚÔv~\é vù¼«¢]u¥Ïm:7‡³ ɈÛã×îóçmÔ°eÎô8ï:,ô¢m(Ú¨ïŽ/åƒ|X &ð,¼)áìY³ ,Ÿ(B¢;AWµ â4ëÓrŠ»hÈÒ5cµjZ؆Â,e½”ûz•åûí£7&P-€PWO ÔëÐŒD±«q×”IW0Ș ^׆ ’K£¯ð•Iÿ€ûhà PùÛd“ùŽm’C¨,³Íü|ƹPp=ë0ï¢>ó~ü¼õSàcÜ7SZ–XsÊTÊ¢èzØ¢\fI×gcJ¦’ÞGÿÂù_9Óéw zÒåsNL:Ú0L4ùêÃ0ÑäÓˆiÒ¦0Kúœ @88 *ç ´wÁ§˜À÷ÁªÌr$!­ötWŽ.’}2G’£ìù<Ï9e£/?N_útÜ®[c˜aról«1¤KûY®D'ô\x {È­ÜSJüªïþzkq1ÁÏÿ‡cxø ¶fÙ¢n÷#fºJ§ÑìÅà)ì?Y*þ)aÈ’tаãô”×Û²¤((!RÕžG¿_ïk° ?cñp†<+¶†‰;ªŒBZª¶¼›gaëØ.àÞ”ê:h?ÝNÏrûBÎb0ŽÌ©¸ÙÌ­14±YÄgOuÑ館ëq–íB"Ú·(ºÙB– íêýþøH^À“1ʇB5%”WëÎ|€X¬ÀÄ7<ÚÙfx`¹ÇÑaI ûL“Ða™³"¡û°¢$+­S³¤t¿¼Œ;üýYë Œúš-—ûsº°ÎÕ6ê5•é"Oñ© s|Ï2ÍÈ{\5èññ£A>®a·ÂDüêˆRÊb™UOiu·ÉšÞv”çzÖáÿà}K†°å½\ŠÌöj©ÑË¥¸QIÖ®x³ž óµéÄÝXÝÃuÏl ¸‚³Öx>O“ 0ye?B˜¹Pe>¯…ÚkÝIWÀ»Á/ô ÒÃ~-´¯ôzÍ~“À­¶×e´; [’ÖËB_¼Œåc{€ ¹ŠkÑ€Lƒ«0’R£šŠ ”úÁ€B³ek ·Š¹3kBA™./(‘šÞêíš”þ lAЏIQtª¨ŒÎÀPO•ê—œ¢÷‚V‰IüöݼÚie]í.íÏ,*nýr—#÷lDï’öT¬WŠe¥©làKOJ$­ƒyº×°x¦1³5Íyð,µ1³eM6•nÓTöÅb./³¸ºÂëì,¹Až?FŽ” . àÚnÍF™ÌVç­ääž„©Ïä˜lgE³ˆ¼™¥Ò¼íèÌí„¶ÆÔÑNÓÖÅQ¶ÍýïuÿuõÇÓ‚µ‹™ŒG<Ô€‚6àÍúvÛã¿}È«FË#-Ø ÚfMŽ^ÜçV5ÒÇ™­aÎeveOIÇA–ê‡EŽkaü40¶¼È›ŠÀâC9@6 ÙŸ¤MÓ˜RÉ CìK×ÂEcÚs×™—~Gé¢hŠjà,.ƒcW´ÚµŽ‡4Õó*ô¸ô;&iáݾ{‰é-b2Áø’ZÓU ®É¡˜Í3¥ÑU¾G͸«)ÞrJMÔ€a#Ýþ7 <¡oùWÁÏ÷w= m @.m44вTy= ª^ö²àeðÉqy‚b¹ç”çK é—dÂBâËØ ¨†x­›l+û©ÈF-hw´Ð<ȇ0#Xθ\]:Ñ™eÿY Ÿa®T1ïDŠÅv[Ô#Û–ÇSè ¡u§:ŒR~ÊM­³tÝ“ãgÆæJ&9—õ ÑVäUÚ ucÚt’}ŒËqEاíÞÙfØØ¦“}`+ݰ>`/~ì*¨¨((Ó­rÝÈo¦À0£,D6mZ“îWŸá‡Ò©—´ÒÊðÊ^¬ÉY¨jSU·EWT:ÙM&¸>¸¬T„{w­«Õ0º“Ï·qa;d@ÇDvÛ(J6Í\ë,ê¢ê· Þ«“DM£·„À2pÑZdƒådÌaYŒÅºçrÝÂfÑñ!†Õ¢³ßwù6@?Ÿ´jœnÎûC«n»’åÖΦÝÞi÷„÷{póOt›k]ú‡¯ áâÍ×"øÿ´\ÓtÄ]íjVÕÜï‹èÑñ‚@¯Ð.¿›>œŒ¿Ðó€•^²*6Z¼&U±6r´¡í ïûWa®OgÅä+%˜ìãÆVnÅ3ºÍ¨hRÝJ›Þ<ŸÒUíÑþ>‰»_%݆|åôcÎv0°Ü%˨†é×J 1dq2Z',÷Òªùµ½B*¯šmØÙA"ϳ®ØÓ"®ú|“~)+ØÐåPby?ø8Ï?Dþ‰RÂÊ-³‡¯íJñ¬Q…š(XYMë9à†ÓÞí½ïÃÙyCEÊH*¥¥ñ8ºÎE¹¥j³²Ý+“™5CJMîð16öut?´Ç[óí*²Å3•&6ZÈDñ{Ú K»xþíª{ÎIÎôÆ ’(g_io"µ›tÉ·9š(®;ª‘%³¸ßòkLf5é.à WALE`Ñ™1O´«ÛÞï®yDou_ò"êÊùX/tÑ,ö ÃñIw¯‚Wï—9¬žJ¹·¬G§{R¥¦ŒtQÙÇæMú! dî;oÃããlÛC?5ãa, —lF‘˜¤ÛJÇ”YíËWÖ…y!´(Çz§Õðí:HÄÐÿõ“SpÓ;§âA"íö¤ƒS6ºõè«À Ú=u¤‚Û…¶ò~ow0P¦©¥ÕZzk5ŒU”U[_Õ³`jaVdBýs­B>ëÊÞEV*²¶[îug¨­æ¼èÒaQsUÍ"å‡xJÄé&¥—hÔSéK]Àû ?K»"£k•R¼¯Ô—ÓÔ]¦Ë´K³žç A3÷nДZ|é?cËŽ&M_ÂÂÎ4°ñž^—"£¸4h@ó’¶…,"°h3zGK÷*Ë Õm&§LTFWÁ ºè¶Zöb¢špÙ'¡¦€¢‹9Àë8ëäT\-ïçI›Ëà'€«ˆ¾P벜Rxä6Ûž‰^Ðu¨ˆ}>°&{rîWï1ÖÆ0‚0 ó™æXçόϿ:(q÷èa:†uSHƒÏè»&KѬU¬ zºÚ<=å:.ìÂCƒÐ Ü’å±ÞwJ3øäQy…H ¾ÌÞEû¸v{¶éùa ÓSXªÌ¥z ÈjÙøsC[øg^Å›¬a«ïrì÷Ù,GÇ´ó£5|4ffº<^ú ÔbWÝâ1-ÓY“¦(ý»TÃV'ºÝÌ¢”ØBmß¹Q ž´¬«‘Žñ8»‘ONCלò¼6YgÇzZYëåæÝNã âçÅa§ŽÓ<…ZÚÃÜAÖ¸­c’ÒW‰Ëf.eÁØS¤ð?6•ŸâúÍÒ'BèKÑ”ªkžÒtBÏfÁï¸D\™à ë`ž=:†Yâ»á¿þÖ¿«Xÿv©YÏ ïIJ¶ÞÇú÷:™íÊ™0ÄÐÐÄÞ÷}‰’üqUíô•Ì‚˜‡Ã”ƒŠŒƒ“î~ û }}˜=U‡hº8rÌ1ÝªŠ²»q-Ûîïü¤'t²3“ô‘1u¡—þÑX©}ì—t‰ÊÁ@iî ¯!ý1ç@Cµ—Óúá)öE¤_Mçš^£NjYÊ”bŨ‡ÅD\èàQ¦ q\*‡ÏNʧàx²´àKd–Á|}i‘YN÷=iÚFe]µ†ÄFÂb¶LÎOsëð‹q HùÇ/ìHºÿ¡§Â>WÓ81v#Stmiçª+JyŸ@c{hµƒ×eÐ%¡w¡ìŠ"£Ô¢gªcÜŽd´2EIZåñ>îå(¯¹*ka_F›0Ø£‡Å E¶DçTm,@]ÔýVǹ,H[â«•š†i\èv2z}¹¢W·í+TÖ7>ö†ª,=Í­É;röùŠ…?éUÃwÃKˆ¡t¼Xͱr $æö¸U÷U t|Ìšn@W <ûÂàÈÍ©ßü×1R†æ& ~” lt`Un3ÕG™¤}˜Q[ž}Â’|ëëbø‡ðÎάçA-ά7ûHMÁÉÜàrÛ 'ôÂQh•Thªe¤Ò=‹ŠžI³¦†.^‡©ã¿/Ê '¬w<˜×8ެГ©·bIƹìó¹žfùÐNpCc<wþ½øÖ—ÄÜaЊ$SÉ«µãMSÝTÄ"„L_ü_h°2˜ÈdS÷oæ" i{ç%‰2BP1Î5(îã¨çj2E‚‹´‚Òíf“MùW“8hýȨ¢ÄÙ†à7c=ûá©’Ê™"ßk=­‡‚ÉØãF*ÿæ‹9‰ )ž¡5ÁÑøÅ†ÊóJѯ7sÓüå‚ ͆°Èã˜IÕ à Ë12QE’@* )«ï®oaPWïƒíô³JŸÂ‡ñ)„Mh—jÑ*É×m›&ÕoS¹æRcÁhQJï˜ÆÄïòÆíúb¸T û$·,ÉwïNÏÍÔñH—uWr!¾OU«OïîÀ§Pbz)dP ¾£”G À§°TIµ÷õ¨è«TÓ6DYϸ»»Ûz$hî9îÞ‡Ãpè'nCd)¯ÐÛÂeMQq‚úÉ®(¯/Ú)§äb/å=rÃÞáÑ}…s1”äiDߊ ûš6ŽŒžÖvR1]³¥ÆF÷²&Ý177¤šÁ NÊ¡u%ù'˜`àäÌ3Ò†ôÁáXá¸ËíþÈ\ å Ô<éÈpýуÐïi>¶m¶Í¹t¡¸gk*mêKþ`dš~óËH ÊÁ™ªE#œ§Øð-ª˜²ˆ>šÚ“1–üÞ·é7;~€î‘ñ¬pO ,'T¯×†©&ÏIË ‚­ñ$+жŒTMÿÈëfOæÉ<*Diwú¸oüLåÂKfr|mÑÙ·KÈ„–¥¦‘6ÍÝ÷\+ô=¸Yá¡ê}`%ÌÁ{Rö,ÈÖ»î 1Mœw‘ÚéÃÇ]µÅc+„лOÿ²€cDká€|·\¬Î¯“£*¤n±jÌaˆ0ͨ']×ýï×ó¿¤Ý¡¿)°ZNLY ¶=¨YjJ’1Ч¶ÒKo^d@•+1è……ë @øçbÖ½xtÍDIx5¶)…ºqÊu/ùx`y°ø¢Ã[ñ$Ö~jlúÔ¸Ã×-~–ÆM¾ÆjRYÕé¡”¹”ÞQX¼Ãçäc'yŸ} "©ZGæ#\\±óHu‰èdCÀ,‰ûÚ‡–g0Ô¶k]?‹†½Ä‹»­85<º­ÍÒæÙ´ÓU¸ìMnÖó©:„A‰eú9÷ëAÄ^üeµM!zN‡©0¼$é @ŵ6I!Q+Xì¦<‡0 ¾|=5÷¬Á™*p2Ãçqßç®óH¯=Õʲ`ˆbÛ6“sü3uþ¼DÔ ¿Þ‡”2¥:p¸9À#ŽQµÕzŽÆ¦˜RùÑ 7ùô¤3LRñmHýós:TRô´åûš» åúz¨†ºÌ‚=â"®u7"%ÜÑ´.Ø!ÍV9|Á§E–GÑ-Hœ@ºTWUÑTT]eŽuè#?Á¢*ävò0Îüþý·åèr@ÝÀL ¸Ed>zHÕ”Ab®˜KÓD ©ê¢¢Ý÷lÃèamÝ3—é×C8‡9xŒ-ýƶ73Í|N© ™©¶ÑÙ›’ò[ÚÛÀM9‡9‰o\lïGáæ—$‘oQ¢ÞIÖÆs™$í :·”­ï@ºÜŽžóÕF½©élö•¡Ö&è\lIªÞž^×J :H3‡w3Ó+5.À¢,@ùpv–ã^¹µ®î¾ç†pÓ¨–r/ÌzÀ${>.ÚâÞ¯ $|ÄÞ¯3¤*ìØÈ8K±×»Þèʤò‚:¦ÏÁÇÙò¬²?ŸÝ_pŽ]5zm-ªî˜´O=Õœñ¾µ9Æq7o’RgËñCÚîÖasb‡ßºÿÀ6U¡c, ÂÙ5úÝoÞé¶{äÈûo²ŠÍÛåN`-ârët\WÝfR”áÞ}DÈ€ªãûÑtý¢Cš¬€vÈv Üa=˜J¶éH•G§£lÎŽõüd”m¶c2¾ÛU‡*mOiUÔP0c\Ù‹kUi¾T1å@»¬g‹ÞU3·À8ÝÝ«½‰~û&N)¾¥Q"±ç3}‘:©†v‹Û¬Û4놞°ûIR.Š´‡dvK™YÎzKŒ—.ŠU) ªÚö½ˆÝãÀžjdá®};%"Í Ü¸Ä|Ð0Dz >˜P:é!ﺬHº½ö.›e=ðk Ìßı»{¿˜Îb–ÇzPÀfP%iQ³ 츨L§_CŒ!Ê0 S Šï¦\>¢WY^å‘ùÕŒ(ªb‚sÖsþè·ðø0°N¡àØ~Ý Òs§Š-†¦R·,ƒPîªÓ=ŠEu¤Ç2ÒJ-õïWµ.Iïv¨°Îs Õz¨•ð\:ÏeÒÇu¦ã*ÒÑï·ua‚½"†¼iNÁ˜uÇ¿е£RcÔuqݯ³yBÈž¹sójß|¡} ^‡¦Å HrÀŽ :¢? †‘ù0!åwÜ‘”›q¬stn¢ÈÌ*« ÐCTsbÒ9ŠJxª†tP[‘Í5ýÛ$–ž ç30–ݳæÜ¾Zù¿çìg¿ºröÒˆ=$t Üs}…YRrù˜n•Ld0-„ ï2Éé·óš «þÀZÈñBÊ~©ø ½Fúqr0‹Æ¶$ðz`²)Sñ@YÁhÆ.ß"5ÉíA(Up+»ȼk_|ý\$å¨\ÄG2óìçÝX• =Ò&ÃÃ]èÐ2ëtiÿr‡”ÂýSô¶Ed•ÍAa(Ï”ˆP¹SlL‚(OÀ…G½ÞNBs¾·#O`’IW¶ Üyôªz=µm¾gq£U1©Z†"Ð=¡¤—2Ì;Ê;ÙçöQëüÁO¸ZÂϿTšRáMwP·ô«Þõ²/Ó¼n»®š2A£ ŸÖ¾l(?Žk½ÅÓvü!E{ Æ`AèÆýB`þØå¾¨~»¢{Q û~;ã—ßÎ_­èÝ.è Zómdݪº1*Úù %ñnêdÌMý@߉r/È †¥Š“WÆ×…¨øG„#h‹Ö´áGtg)+†uÊvŠL ËfV`ÐõP8wŠÚPoÓ$¡Œ©§èi||°¡ö¶Ê¨n.ëijÆTn^*šA4¶À42 ]¨3\:‹‘#çb—¾LÙˆ ¤#ÇBå[µÑ‡o˽5ëùw³EÛöõ›/Aª%ÙŠñÄ^·fã^ăÞuY§}A–Åœ£€ŽºÅ`ß=üCû2 ”ÆÝAÝîª ùûس:‘j)¯KÖ5Ѫ45A’€Œ˜dÖ÷Ü+ɼ¥×Kºb0‹)áaʼn‘çcU}’QÔˆä-é×» ÝXé~Ì‹LÒý#Ó¸â·IÇ“I2èZꙊüq(“5k;%¸ü¿^óömÓG9ítС¬Ü´<¾å9s4øËDE:tE¡dÍ;kªÜà 7‚/9Î_PܯŽ"g|£¶Šyßæyéï¸S£icQx°¾»–0ïöë»üaÒŸ)*‹£¦”¢²XwïÕ”©6‰7•©}s:Ö0Ñ6b<þ—¦üyÈ1Ð}iØèIБYsÝ×ѶC©Kº7 +ÒÅ Ù§Kÿ׺Ó?bm“¢±Z6Ì·fÓ{«(U e³LZð@Ê•Í||c:j}&éÈXê›ç‚\£¢hkS:RÍŒàLS]#ë¡* h̦>RÀ¸Îý«Ó&vî’S‰„Ìéµ—}>M±Ê²F^â_-4â'IÐï÷ë¡Y–9e³ti'ã(æD IC[@OTÉPð/å]~r[Qs¨ŒJ”ûHàx¬LWðšç ÷©¡ÞzAÛþõz·/UÀŒ ’¼¢Ú¼78h¦o·•®–xÐu3˜¯BYü¡cJßð›yò9ë…X,!€µåýæ½û —ší±þÄ "ÊÔØL£çþXI¥Ö@o‘ŠÃ8H>: ¿ cÔ‘h}Û¯¿^V~¤(‰A:{󼤺‚2ê•j Um™Y2À½¤sãø ûç‡A©Ñ‡¦94,)Ì“»5ïòv®û,ËÌg¶X@“Ò¡Ð1Ò°ŒR;š‚¸À?rÇFQ¶ zëcf-y=ÑY¡#³¤OYÒ?(žÞóLkˆÃ>Edާ[ƒ¨‡!„·ô'•e/}5JâïB§¨ $ƒþíC¿xtQGÿWxey}Û½Ë\ee ý9Šî­ ¶\›Î5\×]€÷sá~$»^âñòâÆíB:Ó ëek!HtUæ9pñ{ƒ7ï8Ù[8¦E}\Œ…YÏlŒ¯,ž¿ʪ‹P¯×M,”µuº4?™^í jþÉ2 ¬/i8Kùš³¶ÑiÃy{LÔÔéiЬçBÃÁ )ÚÞq£Xº"žÒ¥)%¦6âNX“ ëž©:Òºè•Y“m\%PZÿ°Ð.-dÍø!|·¬˜š¾ÇL⠓0 €ŽBÝnvþq¸Þ¯òÏ|)óh6÷]$„ ïôù) !­¤×ûGZIàþ@X•k6|ä,K‹)ŠHǵ¹–é CŠ{À1ÜÌÝûüƒr™ðtàÏ(ò-ót¦jkבÂÈXýrGÂz4ÀM·Ù— ¥2Çø” –E‚šÇ§ë¨ò:÷6M¥Ùã^Šj€6v`šR<²úljž = ¨[iЦiò^eUÖ§IS™ÜË…²³EkÐegôÙ„‡g‡è7йKKˆµó¨ÚP4“$÷*Ï©DË›h‘%!ÕÎþQwcÎ.dCÛÑzc‚;pŒ˰ƒ ÂÛ/þ{=ϾiIÖNèt¾£:4W;†àNF&~?'þr]ù{Aê"èáÂ2æàð‰ýô¸Ì¡úà –L'Ž˜7¦i>-TwK»Gçpè- ’k¶mT™BÛýÌ_ÄûY '¥»6¼ %k¼¦=Õ7ãÒ—k—›t ¬<:æÈàtÞûàa0 XÉa©kÛšaˆt}{•¶iSftÚMµî¹^àxÐö¤£$=CËþyBâõ<ÍjcËÅpò¶(U9×YTTI£Ì‚ÐèG‘ؤÞaè]ÒäßÊ—ŒýŸåKF<=¶³ƒ‚?e-ö)_r¿ÌE~c]Sý•u ¦,À`lNáŸÖ5çœú¥MS†uœKgv#h"â ã\ŒtÙvKD¹â¼È’¾qK †=‡‚@ê_Ö¶ü†ÛLN¯±b<9… m»½P‹“®1†G¹ uû¶×y>Œ6Úo8ÛŠ6ÆRPþÞª*÷±ýýzß‚Øï‡p‡áwIú*¢¶°[¬»¼Tûží[ôû5ÿÔ/{1ƒó S&¼3by.’%IÚ&ÉçŠ6•þfI›JÑ›®pcìnvTÕ±„‡—¶½H“Š‚ú¼Â2þë%ï×%ßMì@}+¹l ±c—-KFÚ•*é^3ÇÁT zСï˜òà‚0~¼©"Ò/Q@ÏDP‡ŸQ„ÑßÌ©B„\‘’pë»!EHËØ7cҦȅO>ÔÓX`2G¦¹Z‘—ÙMÛØdm•UU>š}NÏBhŽY–Òßkn/ñd"®pŽÅu&òDŠp¹ŒK…ȹ”ê`R®‡ÑÕý««A$ pþ1Z7Ü e—ÔI-ÑØ&²à³’­ƒ"_Æ/dZü.ÛsørÀ0r£x¡Ö¨ÍTÒwñ¦k5- Cv—Uª3™u>æ^”lÆ,, µkˆóX©q§û:¢úq,#%f.Ú̀ݔ¡Ûuê«6Ñû-‚×ÌI ]Ù‰5•°xŠeD†Ø¬m”›Ê?€Ù2<ÒØóÄÊ|¦ L:åè-,ÊëÜ;ìÙòäjÞÅŸÔ B¸[.h­KîÇ] ïø_èÌ5¨eF Œ:Ê6쮊UÍ•”å¸l¼Ð¢/B…îQ/†W¯ÎŸí„D¹æN‡Iy ¹æb¨áO*o3¤êÉv@â¾<ËØ+Ygkó»⌃Ó!þz‚”(fݪvUÑ/ò¨6kúÐà7:Cîç1ÿ}õ}¢àAHG2Ø–9ÆÈôV£(MK k gqƒej0ë¢ÕÝû©Eq½0§’çÌK,ÚRj}ºbç=Ù³y¤“¹Jà £Ó0åÁ$ôë|Ôó”>'~u†Ûâé<¢»qê¢|¥O´£\)¹ ðn7tfl›U]?Lá+'Õ/óPš7}„ß2gÙË×iΪÎ,2cs¿ƒ·î»§`ß&M6»GšÞ—M?RÃÞ„Bl¾5S¶¦k4lTµÌ™¬ °z€ì#_(=]$àÔi&~ƒéÛ–{g†[Ç\Õô–ÛY"­Gg2B*<59ƒ D Àm#ôTÖÿèF¼Ý*Ô&TXEõ¶4k>岞ËCn AîÍ$’<¸¼Cž¿d=`:{Äóñzã^t¤SÍóù6|7ð½à(—ï_=`[ÅšÄæZc—ï{¹ëvOiߨµÊ„ÉŒz)ïŸïðgô¯DýçωäÀ¬««†Ö@Âò"Ýëœg]K%iŸ1\$¤€×ÿ¶8Ó?-bnq +òPÔŔLËÖUYâä˜HÚ›<Òþ²${¢/ÆXYЬ*.› Ä,Ÿ!uHÁ§§l²–Å\è—°¦s܈Îí«‰ ­Yi³CAîQßèÍ´´P‘¢Š7]ST÷À 4ðo€œý»oƒ¡M†ø´dÇ¿{ĈoŸÆb B‰z–ÌK÷»%ƒ _ío|Ï«¿ò=ÿëõ¼/øí“%8)Û…Èn ®¬ˆŽt{3è1zÛ²´Ç"¸ÑJSlZß¾ÕÛáÿÄ?Ï–3Û Ðnò<žº=^E®ø{M3ž²¼yWW%žVð’tTl† *†F—ɧm3OS¦Óú7)~ö·­Ì/ÃPáÀb5@ð‡îᘵIRÍy6OÒòè¬Øð0}*…„ 3Á~ŽV¢ô\zŒtQ{ZåZQ–šo£9†”P°']Ö®’oî×íóx_¶ ƒ£<"˜eô&‡Žªâº®ãÕØ!Ð>wpý8Óû󞤟]àpƒÍÌYä?M]ïÙ°íÃR§»®$Ú²åGH'zé·³Hüܰï¶äÏË@ª(@WvèMvÑmiÛŽô]–B/ɬeÍ;Ý[!ìHow÷#uÍõlÁ—vÏŸ¡YÀ_Hu˨ÆxÚs]Tâ(â„cÝ¡¸b—‚å_¥"û6ÈK—<ĹIB°ŸR­û Zß,”åàðÐf::áªT}£Ï f„ ܰÜ=¨y¨y4n,pº·`QC×ËA@$¿ªõ°ü²Që±±~×i¾Ó‰ÜÓy«÷Ú,ÒÕO[È…Lþ©)x¡Pþ¦À‡Æ'šT€³²e=lµ×uÙR’gSwѱ $$0IrEâJIlCWÛ §v¦sA¡OùadAYt×À—…ÕúèÚVWÕl=UL²ËÑ„¶nw†ýƒL|•ñ{2"¶ ®íÖŸ†×³«¡Tô ]¿å‘$´¥´€ï,)'¸¨ŸyÁ‹aËlg—–»°µ2$Y×qKjºµ³®yæ¡êåBÜ뀌ÝÝ{ˆ„ïúÍÝ×o®EõÀCBo¹ˆ5¾ñD£üç˺Ð[ŸñŸÙ­¬_{¥·Æ£Y“´í@ôuâÉo•O­'¨ŒÕü±)È`Ý×ÓÔŽK¿¬óJuǶUI×í§I4¨ªHò¹Öm"Wˆ°„- |]èŸÙ£|x²ÄÛc‹öÅÕ³6ë êˆâSVm^ÄÃÔɶ¨®ƒå‚óéÈ^°?ï÷¡R%Ê&Tص‡Žï¢ê©îòVmq›Ž«Yà±37ët5v¾ ~áÄcðàtI¨l5í,ù<¦ª6jÌýè€"^úF1•‡Oÿ¾R›_¿´¡6W@·R1!ûM’¤Ì³¾©©œ×ÙÀ,´ÁLµ¼Ãa‚µ÷¯ð`ÛŒbƒ©0<ýZ®Áòl)ò¤œ·¹«E™ÒsB# ^`S42ÈšS™r¢½~h$Àìý‡ÚŸó8 Û²Žó¢×Uk\ó°,S±UõC·ÑÛ±Jú3h¿R) Ö¡)íƒðO±îÐÏ)vRAF×/ ñZ•šwJ57­§!U¿_0¸2ηÎ\ ¤¾À™UT|Mc,Ž„Ý˜Bñ€­à#dü¹~‘fˆQ\deºŽŽ”ÆUU7·IÚÌ›<Æ…|ê -AŒË›õ¿…Nõ¡/‘ÃÞÇ\jƒð²(󧟬tU'Õú›¹cyÕüdö¦Ze]¬«Õuò·QuÍ>*kÕ¿}B/üzBnä<™£„A EÑ0¤'œÖ¥¥T#Æz2À_=¡å}¹¼˜šRKO•ùl &5&Ö5l £ß=áÝùîñoL(3Pßõ8Öff]WK›SÜ,]˜!ûíC nýbÒËd<$e*Å”öUÔP™5I¯hÝ}ŸómîtY!¨¦–IZ)œ~Ê”ƒõ{4î>b"Ò¸»: Žæe²ØË^­FíM,¯"´Lrãš‚á;‡_hUw»¢´hiÕ¸5iÙË‚.Ä4øQƒcq³¾@Á?lf TùÐ/zœC‚§mŠ¡UeÙ¤mªDöÔãKˆòÿ;ìÖÌÆû¶D:eL…mA†í%b¶ñª’”’£®èwB]Ú§2Šj)×·Lªn{_*Æÿœû Ñ£GfY–!7Y_~d æÓ>pñ“=‹z ]™XáAÃàfÓ­«µ“æ#_æÿÇQá7iȪýÒ&rÂlƒµTæi[·í?ûþëñþ¯ÿûÿþßÿû¯ÿûþ¯ø5t<Lj¶ð°åëF_N!Š*ÃL(vVÝ€3Ñ»áõ†¾ý]ÊPC©£8^ÁÌ–óoüªêhŸ³f)Ì®µÉ¿ñ†à XkŸãÒh‡¤—˜\ä%ËYj¥?´z»Že¾{Á­xì hSÕ@$ý„p\6 Ø^ „Ç)Ƶ!ŠðaëÆ~Usm(Ü ¶Zîœ^û¸õÛ|Aþ<ÁqR}f&z„xWYO–(–Î$§Å¨™[q•*U…¨B÷J%ð$ö(¾Ë7¾ÿë/ý §6 îiŸŠ9Coô(ª5j½²}³Êp ÃRºÛw*®}ƒÊ ì+­ Åf&^¬@ UæVö ½„µLÓ™Ò1)a|lÿ:sxÿXIÙWʬ xe Õ_lšÖˆêjiã:£-ßÉ;|÷æCÂûÎF{'Hñ£ñ¼ñá|b:í„¶9ÜÔH±)¦Š²ӥ׿†ðö²©¦¤³w¿ê¬Ú¿“‚¦  ¶á”‚+â,YúIÉΠ.‹‘œžåÆÍù`Øß`s>…è—9å¼oè*êquÍÖè<««´¦L¬Ñ1x Ü8•…½ëáIzûº9Oý ÎnŸÀS°SƒÜ\fj¥ÄCO¦“@ÙÅÇG{Bš¸'ººgñ› …r”˜y ](=WÕ´E»%i’l[#´^/„À¶mfŽí;ŸÉÙg„¯Ø l`ǺDŒ½ÛëaU˲DÙ6•‘郇Àx ÇL¿šËÙ°­Š-Ëô¾Du£ªÙ'yD½P6Ø0©q0mzzsp‡‡Ñu(! ŸéK)êç—!|ò*~ˆéPúë=/×Ñ„ÄÕ¬<8 9‡<8†™×ž#4#DâD#ñm›Î×zÚ¦hÚŸìRrÜü[Ø()üÆu}T@]“5cNG‘lYÊ8¢oL÷šZw“Ç„>f—vG…ÿ¡Óë\úŽÿ\²ÅþÓBÕÔqî0þùH¶|¦[oã X*òc²t{„Ы¤,Rz |²ýTæîw0Ö* )]ŠE>Ï]§Òª–%!GáQñCMyN·œ«Ušt8Ç*[¶ “@%‚ccWz‹ûVÇ´IeQ7îàG‚ËéŸf3׎..“5X¸be¾g@nÂäQGS^I÷ ‚pÐm£' ‚CrÕ¾ ŠŒÝÃ¥fñÍÞˆÌçͺ§*†²ÙÔÅ«,P-Žê<´ƒ»Ùé¶g®Bæ¾ßÌÓ6(ôµè‹3ÚÀh °K÷d M|^Ô—Ó†„œ…€ÿ%õødq"" ˆ“ë}G*O‹¡©TÕ­]eÖsÃ8y ƒ³`4„ú sz‹\X€UÍ>ãy¿×E®’-Ëú¤6Þ³ô¦8IW …_ƒ­€a†{€Y~„ERØ$޳õ†jy¦W:3øP£Úé-LÅ^m±âsé³)i€7Š ÍœËÏær5OAE¬ä`ðg¬ðÝ,ã–-ÅSáWÓ>eûBÎ>Ðb·?M“–]e¼;™w'\Û%ózí’²MV™‚àöåo—¼] Ÿ§(Is·ÌQïöÜcE±«ž‚:Cb¨¥Ë’Ö (4ÀôÍ8’YП «Œ#Y磬Ù*„;t£ÑMK%=íÜjcÅAKZtiÓf ¾sí’>¶7Æ4”«ŒA¥–‚H©òbNн˜Í#Ú˜SÜÙæÌtß,ÿö¥m®~ñÄ‹³S@êL¹3;ÖtŸTÞQ¾V®Ú¿³Ÿ›…îkxˆìyÞ¥¬zñbºSƆ“5 ø¦ØcS•ºNù¾+Y’ž ŽW²"÷Œn²ä Ø †¾Û†š•ôõØv”¡ÍÓ¼¼ÿXßzïú? J´š¸ØG=Etè-WE›N%0ßp Ð>tÎ1÷UíE2š‡¹ß{.:V—ûcµ®Ïе®×߯wÑeýy>1§4gž'†úÅgžÂ@ZÐmœ§É¸Š+-éÓ͉C¤ö®Õ@xm Æ²Žj¢V[á¦ïÆ} !7 ¥5CZDµ9õÈ5a®A»‰yèSüûÚ¨xÿ<Ì`1k›7ÓŒºKZ/®¶i®æM;TV µMu)Õìî¹ð¾ÍZõ¯÷)YÙµìéì"Y kSDÚ8«Ò‚I Ôøõô÷^ÌrÞ?fÐ ¯Êv`È>Fãž´*ÑtGôfËFÖ 1ZòP cHÈ%_õÆ_“IÛ_›Øªß›æØ;7ß1M aÜaÒ×/›D3ŸÅBƒ¢©{ég²ìùFˆRФRƒ,h3mÙöP›žMŠ Ì„J½Ã ”_³‚*j=ÊßÚ~,ò~•Éf ¹›VŒoeps/ù°†–Òk¾/XT»=¨-zxìµQ<£J ÒÈÈŽçH<ë[0ÿŸ)jšõ,—Ê ŠÇ”Ó{VÔ¼F÷KûÓ4ú$ÆÈE¡Š¥Ÿ«lšú,îeMª”QñPÉç( º÷W h]2­0ÂÕcIK²6í>Ïs:—‘Fë¹T}{ÞÃs,y¥¶0틱Ó}V•ܽmQ'Z)z¸²M“i¦ða¤ªÇµ¡{8‡”ß #p`ãñ9húÂ#–Ø]ƒ¶vÞSÈÉú%î£6Ë fÈœNÇLË)ð|oDXå<¯V9<†N«œ‰m6sQŒ:4„#üã̯ö <Ô\’ú©Oñü‚¥Ö-°+LåœÕœvªØéö(Ò$䮀‰#ØQw¬ž–CÞšáDœÈ€òê âtÆ%Žú(jªfn»¤õÕp¥d] G2G× 6œZ£«Wj)£x*›fª•tõ|H§#pƒï‡#y¬äòdH0Ì0(¿nO52Û¶Pû°”¹î Ç£Ü3ˆŒôÕ)ðØÖ©üy±fð†– Œ SÔ[CD)”Ú˼˲¸î—ú÷ë9WôÓ?Ƽï‘YÒI_ þi›\ó¬ÍØÝÝ èAp5…nئVJj¶jŸû*’èèQµ~1z€†„ÁE|ð…Á‚”gœh¡s?xª$¯i i— Ùdƨ VCןª3×ng â2ñ)Öˆ0`”ÆSÔ‘IêU½ÑßèI·¥óZx¶>•wÐD$äÐîhѵþK"†HžÆÁ‰å€(dP~¹·õ6vëÏýlÖôÀYfÅWC^ûË›U¯¸çVlo¨»è9QÔÐÙØUã¸,±6 ÂkéK¿Ûí##wôRYøœ/ì:M²šZˆ»ýÕé0EI’íco•´*!YMU„ÕhE|[ŸÚ??\“FhÍÒ†üc®ó}Y’!ÖU‘ Bx×ÎøpoWFÜEw˜ên ñÚöhS&M's¢3Õæ‡Ü»]ϦÔÒ=ñ×Íð8ûõ`4=0ÐI­û:T=©NúW>¬ýð†ûË÷ü³Òû÷•ŒúdÁ+iAe³–Õ¡ QËÚ¬E¯š}#ó¡)tÜ€•x óK´z{¼nŒ0ÏDZÁÒaE’Fm[PHÖyü»õ(q¹‚ªõö}? g†¾ØX7)q»¤Xæ±É§Yo“Òæ!]çÆ è;Ý\_çâäôÃdf§c€„ `ÂNoÛÒ Z']#RqÐmÖŸéUžáñá÷ï~Ê,7«ª¢é͆t5C.­UY”WÕ$·6moºÂ(;»CVÕà#¾}5_|) "Öƒ! ³ª  œ>TI§p+Ró€ôi‘™ÁúÔ0*ƒÐÿ3üùúõ5ïÀµ2öç¼c&$@"˹±KTø°< `Ïc\ðàR´äÆ9ìcE0Ÿöõ¼-E÷˦(lÊÏéS3—ÔBÔ,éþëÚ»{Ë.g”%èß ÆZlen¢m^ G-ôÙ÷Á¡¿Œýü/âÇ[Hv¡ºÁ¹v›~Se¹R:µÆI-ƒZ“Å£ºO…û/´ +Ükñø)Á)(»g2Öì·l¥Z|Ðy–MJ”¦ö‚)¶í¹¡u·Oßé+‚÷ç[•D1Åq È_0¡mɪvº\i:XZ– @=*8Œé,ç•ZûÑ •cÇ›ØèzXÒ6®ZUQPª•k17 7 £Çhù×tà‡eßxNØAͲpú[Cèp¥ ÝãûÞ #!°nØÐËs ç³7Å£•kNÖqä±É8°G몢ü“ à-Y W*>èš¹CûË£ÿoI®ŠN–¸ÁDî ª}O†¹a>¯wYÓ0çÆ–mÓº;¬ÿ-¶qÇ+¶‘„R†EUÜí°eÔà5Q’ †[ÊMÙõÜê¬Sï%…¹Bõí¸v±y—d‚ãDŤҾâDE“—oQ~t^¾Uùe GðÐ… \@)zpÊò_»þÀÿˆûm¡’;/¨ ëy³f˜¶n3Æò¦Ø¡åÝ9ú~<ƒ­+„EΓ!tUÅ%‰HÉRç0ny5's_Ò¶î7%Yš§{¿ÈÇë‡ÓTÃèÍñ½Y¼QzX‘Ò»ZÊW3‹ l@c=ð¡ÎÖEÄð„íçùKúb½ñ}kÖ f/ ªóŠv• ƸçQ¾ûpñ<Wç`Ðëøƒó¦Ä§¡39ò¬ÒtŸ)³‚WýÞÉLã_*ð<cС1?=üÖ%f`0Ëò‹¿*ÌoÄc$/V*£j›·HX…XðŽ¹­Ï ÌO3ä3§þ‡xÄZÄ ·¬ÁÍ¡Tõ«»á—·üëõ&D`Àñ``ýÛ|ˇ¸™ó†þcÊC2ƒ Ÿîñ#KýbGSd{ºgE{¨îj ¾¡0·ª.ö±\šnɳ¤–õʬB>‹HùÆTö£yJ7ωKÍBu×1臲Œ2jºl,ÛÂOæGs~eQ΄7÷\ðò›5Ow`I”5×UVºéDæ}§—¬Žævnwñiá%m΢KÜ>äÍFüDØ`h) qvh'잉Ÿê­ ‹#ÊŠ4N³*e©?.:k†æa;_6™bâÁ=–6}ÝaI\)x¬QºìÓÔë¡Xt &꜆ÛÖ¶¼± <„a[Ò€ˆ"™ EË-ô¹TC‘Œ›y“>½GËÁ?oÎa„ömnM®Ù‘¸@.[Œ>M£vÕt#F]ÅÞ´fA4Ð/ð|#x¿ßܯž¼1X¤¼„†W_ó§Ò$­ú2­F•Î[§ÖQ¤ÒÓ§ǽcuÚxþûÌReºÁ¨àÄpß:Cr ؉U­ë p:³y(eº ?eWoy®{ÞŠ·«V=%Ú@Ê!šRnÌ<Òy»d •³”ö‘^7Ç l “ìûî³îÝhñ–Å8¯¦ uj)ãŸúyœgžçíi¯Û-ŽèM'I.àY“áÛ‰â]ý'žÒ¨£‹±`»yâl©§m°®ÉÚ›)íײ)‰qNŒÂÅúxëí—ñb‚ÙÕNâ—ÉpzúKÁ±­§43]9ôïÛJQç€ßøÖåyŒû’æ_Q‹JIk8ky±0gmM“I›áQ†N¥˜E—ƒQîÞ•8Ë.Ѹ¥­M¢‚àÃhú§Í<Í±Ž©üVM"×4=+¼;7ï Áù®ó¯ÿ¡N‚«[΢‘“Ð ®s…ƒBAòÉcŒ­–›æüº¬Qž¥eJ)f7Æ7ÂÃàê®:öaÈ|¿Ç<(¡W€´ªlåj@6]hÆü«.‹‹´Õ‹y‹@Ñ[´!dgŸÿe\o,8Ÿÿ³g½›ŸíÑ7þÈûXpžRì7ðÓ¡‡5ö œhÑx/ǽXƒË‘‚‰¬êƒê G8ˆäÞ[—=þ:€«UÁÖò¸ge8Ba(ÕS”è¾ß£m9Ö£ š6#m$OwÿôXù« ïðqï!"ãt÷ÐrëØë}š—ù½£5úÇûñ€‚ûªBœÍÒ˜yI Ô›÷¢Ç°ƒ Œ4Bº×ܤuaŒQ2¬¥¼ÞSÃsÃ\P4ä*ª·µ—n:ì¸(Ý¢ˆܹ9¼ðzsP`~𛣅ë5f½ˆþ¬E¾m³Ž×^—æ³Ñ^ÀT@§û1á³Ýãæøçat6aôX•Y/›)uwÎ0ú‘³bîçŒm >0¾ºY‡*‹dЛtÂ;2*δп{\˜OräRž»7Ý$€Qð¼'*a²$©GËW° ` eJ<Óe¥¼æ Ýx?~Œ:M­´LBC+¦ª÷dRq­U¹t•ôê„öÕûÐù=S¤+§–i$£A(é-ÍÖ¦ÅJyÎTåÒ BæbhDGÀ;…kj{ý:½4¡·ÞÀ2–›ô*cz²¥‹‹lË3ñ½‚…1Uü· íÂCÂÝþà¿=:à ºÕä;Ï"ˆ‡3‚ÿÁ$¿)±‰ÁrîÞQm1Ò-WQæ9MÓªdM­KÖ¡ÁÍÁ-Ws ×/ ØŒjkL_'üüe^Š"ê{]dc[L{¢)ô)±Á1÷=ßqhÝ£kàà…®ðЬÁú<Æ]mÄæê½©› Ú:†«·,HWúª¡ϰϾޗéË‘¼gØu7œDò”‚ð4æÃnÖ£º×µÀésM_ò»ëާ( ‰pºí²"ÏÑÞb1oîžQ•µjªâ¸+ÇRêÔ)"¨Ú° †Õ脈)>Ðm®}\þa5$Îí E¦æ°þËÈ“8³­{$´}¦ê\^¤"]BÊ,ç pià©E,*§œ2#BYÆå³¥}šÒݘu³é3cAÊ—ÀOpŒÙ ë üÛù¹1øa„;Q\ÑñaåJE!nÞh#Õ[F§¼¥‡–…ûOùÓ?m¬.rÌpÅ.OéBCÚ kÈŽu¦a›óA-Y²Ç…8~„6…vËÁÍö•lÛýbù §÷’ü÷ :æ*‡0ØN’^»$)å—Û.´?”çÌÒ¸ŠRB åIõyV1Ï*ÂÂã\UÑùA¾Uf=¦ûëvˆl ~ªµ½xœr8w-C縬ƽnó9§Ä½ŽŠa•8 ·Ox©cüæt“>H— ³aFˆ¦”– ø\°G1°+ïEëv©´´8þzÉ»Yº¤°ŸùÁÕ5£KŠ4Ó‡ÖËÌ˪÷Çûý‡¤‡EVgcRôs ŸÚ­J•DÆC&¤ ±‰ÒÏNÖ¸ªÍ=!lf\Qµ·â PÕºRË¢õ¼§y¾É(¤TÀ<úþÖ©*|ÿõåmõ÷4ðâÚ*¥MÄ~´¬eyB¿ÀRÒõ;/º1ÆxÙ£J eÆj[¦*E”P­°wC)kÒ× ÿȺ®lXƒn_Â1 (G†„ L8.uWwe°}­Ìs†hÂà ª=§†ýWÿKU¨=“îZâ`¸­u%(ŽÐ›„ÅòÖaén©DùEÖ|‚»Í°^ì!Vµ¥_?MìØÌ|XU䪮ã=ÚöDU&ÔT)“}æ%á¿®1” ~¯Ce&Ý &  C7ºåš"˶*_"³£Ø5<ð, vŽé…¨/8Zæ@š¸éDߪZ²¢ßñ>,­èW†^€å)ñC¸óþ•qÿâä²T¸Û¢—….ÐÙC¼°¾^oÍÀL q«’uU; óÀáNU_´M•G*o;ó6˜$á˜C¼çsŽÜÃ@?äeR:CI<4”ùnÇxqÏ©nÕÞìGå¡rÇ;„·ëŒ…‹·¸nï_B.€oeÄcÏ®'À,ÍË0ê>Öý§cÖ›UélZDšîÇ‚aØç*ÖˆO®Ú’¢‚Ô/%§Q´zWÓ´$K%pª èXÒ‰¿ÙŽñ÷dèõeÖý€ôû¬Q®JŸá¹Ž;½ÆMuñ&h-X c(£Âð¨Cëk ¨ÙOºTè2Œ€²w`'®¦!Ûú(ž;¹G\:ºnàÝH3¦{ à.Ì&=7ý8—£ëcÛTSt{½ozÊ&³°´±É_Ë>Ñܘ"oìx‚ž§P6Aà È8SÂ]–ã˜îj¯§¨›»¤W&„üź¶u»ÜwZôÙYö툌›U#›e¥cÝÓšèÒš…ü—KÞþd.bùÆNŒš©³eoãmÔK>ÏI_u¿[Òúºƒ°ò#p„ºkK–%fp:e:-*iÊ­®ªþ÷?ûËCÛý×Aåí„Í^L¬ˆ„9–ît6U& ýå‚Wf½=q›ÀÞr9 ¹öž7K‰ RW;•Iê÷ëùçrGéî$ï ×D¿¬–ó=é"Š»zÓ¨Tåú»];¼¢D飰w¡ð펾×tó¦*šiÍÅõn~3”5¥TÃ÷OG£Sj^¬ú~Dá,ÎiA|â†::t<\#º>èL%e6öRYy¶ búëTx½Ë¹&ïúðû$¨±*DŒX•´{†uªé¿!ôp±,û‹s÷DrÛ×/mRâŒ}ŸÁcªªulu׫jÝ’D)³žíú>ÕèR£Ï¥{áó„ÒèÄA§ª3#JÚ:c6’Šç)ÏdÐB º÷r„Ÿ-üVQø1Þœ9è®%x… Z•*ïè/*µ¨‘èypå´nþb¤hx»÷/8}ºþeTüÐuƒ}à YU`Šž$CR?؇“OÞ¬»AÐ tþõÍí¢½øb|q <07¡>Ï•Ús•ï}œ¦Ñ^ˆ² %-Žã³¥0&ɰìã®æø=$J°( Àw¡­•ú¯Hž|³aZÚʼòÕu>c´º¥›6µïCºÑf.^ð™w:ÎÿLû?ŸMI) µ0Tq®¿Ú¾*‹?¿•Å9 ¼*‹ëÂô9ü2ô¹¡ûúaH^ ‰€_¼Ä5Ÿ¹‘9.Å(¢«aY†4ë·YëÁè³~ä(>^â`= ¶ …žƒ8HR°¤ÈVôY·)PJ&óáÉpYþîÜL´¼_X±_O‘²ÌÒ JÙ˜€%C9F9 Š26JÛŠi®D@8 á¤~§uÑоŸÇçj{£0ûa0eÑpn)ýG:‘´Ý“½ìãe^Ë,6h»Å¡FT¾¡,xÎGà]å~± lå´õ È_¾Úk’¬ž—¬˜³²”Òíxð`½4ènÿ©(½ÈDö›¦Š,o™ÈlަY™nÌš.lC0¶ n·Só3ó~o€hr“æ¸+‘w42üÚ›¼[ ݤ¶nÿ¿^ð»Â} ŽÉ %E­ø‰Žì¢úy£â¾ÚWÑA C¦ѾßoøÄèvœIÿ¯Ó”E<·×9»ä¤LZM½UC÷¹Y“ 3 ©ÜÓ—ƒâïÕšú¡ÐF'¼Dî!ŒÜïmÑ,š‹8‹ó:¯Í’³Cðò?dmçKôñ ´|ªEK–Ú@êIТn‚R5f±qK ™X`N/Ô9}g?Ð1xÓr\cCÃp5ùÕjÜÛf­\µÕë*u8¾‡åƒ¤ùäiþ¥/Ï‚.BXªŽý\¤ÙŒöõÚ”MAÉe4æÑñ³Ã¸vlÌëÄœñ´ŸF©hêŠ>x÷qé[T›éb/Š~ïŽõ`;‹ašg{Ÿcø%Rûz ‡ëUÅÖ½ˆËç]ÝåQWuÚ'GJ¿Û¥M9:š÷'_÷"þôÒ&K¯ N_f8`Òâ©|¼öû¦D4÷Fÿ²1« Üß6(w+øøÄP¾ÆÞ‰ÐH¤£l†ª’²Ö%¯¶*ÞÚ-Zéöžòùo—¼~™7‰Ê É@#ƒáæºËÐp·N'ulÖô,J‘¯9¦8Á÷Ìgïk:6e ¾b# Ì|Úx¤b²£['nVYÐfY£&îçA¼è$>ør0¢%t‘A‰®?¦äeÔÖS5i²™íZžm…p\½²¶m¯>75ä&kÆ2£áJ‡õ¾–i\3ôk†TXt 1ç;åô?­«ç“«ùÚI¡ç(ú9à’ŽuZÅQª,]Îõè-Z”§ÝÁzaßTêüiŤgD\#°)Ì‚ô¨Ç™pµÆÞ†Ú†wÌÝÛ70œóŸ—ñ÷‚µe[uì{Í  Eu}LoJ’[´&`¶…Q¹{€Í/-*J ~ÿx°xÊ]W“¼]ãxÌK(OŒjüízþýKO8(#âÁOX ÙŽOu³6jªÔX'Co^#tTÛR­ã8áéHx­keÄÅm›¢A¬æÆþc˾ë(ß2‰*³^@ ‚㆞wõx{ ‰nZu D°PË î<¥êòBÍàËQ'¿™òªê\4ÿ¼3ËÿÖÚƒ æØƒT¬z#Ž?H'µÚ‡NÑg—"ÙdA—þBkÝôC»ñ#¨Î„&ÍÎOYZävbÝð\x]Ö,¢\<…fF¯çÓ#ÂÂ?”Ò¼Ë8¶2/ö;6Œyz‘¬S l'æì#™ †«IËáÛEñåÜï83%/V‘6J:æȑ㈡;ØóÞ·{:Òd¥ø&¸èÃåн¡Qi²HçÚQæí­:±.™r6˜À£—aoæŽg4§%/hß],aD=Ûñ Rá¿Ëð*ëË»çù>ò=T›#Ð:™מf(|Q7ïæ‡cPK5,€4‡D´umÙ.æQ\·­”°–™j’f™ÔR,]6kÉ©Ä À¿qÁ@6ȔоxhnO#ÌO &ߘÿqI °]ÖE´Sù1G›ùÍôÊŒ¨†>>¯ö¥ yjó]Š–¹]OÿlX‰‡îÂ=“®ŽUEYze–ô,nšSü5¥¦oÊÎ)ÎaRàUöc+Z/²ul–<šËHµ¼ úïžOµÝ9⮆õǽ ·°3ÞV&€T -ÙP¶ÓTLu-®œ´$l²)ÅõÂÀ±?·á%BjÖÏgÁD7-îÄ»o‹Tíë’ÏM'{ÑáMèÜÀô5}…›I}!_)â2ÌkàíF–€1ç0èNC2P­4Er α‚›¡1Qùñß(GÏ}U¢Ü[žQR—¨¥Yk­’hK›U׿[Òú ™8üè÷¯‡0ÙcP4[îï2ÎA$ÿÊfÜrú•Î÷˜À¿|õa_ï‡)_¡ŒE›¨[Μaì;+(¢¥T*Ñ®—·é:€«TcoS”*¬%ãëçÁŸ€ÿ\0°ßÚ²^é—ëÚ$SL9ô5´mpó¾ª8FI“³ÌÖUuÚâŠFåªK»jjdAzt!Ú΢ýÅb:Ò€÷ãÇå#uF¹ÐH¢‚Ô®ŸC®ê²ª\ŸkzÞÈW÷à„÷Ï´ŽG¨o¨¦üBÝoœC¨xNãÔí”튂ÆÞªëvsºÝ,‡,Eû4Àù*”(âÂBȶBµJ<éª(RDªÚö½ÈçQ.EϲB+€àNèÆIÎÇÃýM±p󺯻‰Ž”x[ΰóÆÈvΚtß7³h€^4åÎýHZÿ\ô±mÏ·~•(Ìj0}'ÀRWUjÝÇ=Š¡§8—ü~Ñð‹“ ]¤ÃÍ£g:öÐŒGé¹ðOÈÀhWY¿þ݃~õw_?P£‰Í§”k§—6ܶ' gFÿ‹ú»ç¼6€Ð¹8fª=ÿ|ƒâªÔ@%•ŒõÚmæ«SDÇ"ÆþÑe°¼`ŒF€Æ?ŒÜÚ 9 ÞåT±“›*ŠjlÛf›V6(´-€µÍ?nîWzêAÓ(-°G*ã~¹ž¥ƒ™e 4tÕÖ¦²À´h®ø0qù jMtÛØ’Sž"e«ƒa÷QÓ'™h¿' ÄeS5›îPá„©wèfµß“‚ë‚ɤ©Bp; ÅyßkµT›Ìz¯£5úÍš"ËUQ¡+üý05-´Œäç#zPB0¤ƒJ*•M’A% ®‹.ÝÛÁÓ ¾èÈŽkCÅ¡ôªÂ}&8tóU‘ìIÕÖû’Å…ùá®ù&dmGV pò'ŸÀÒýbz—ÏóR5URùÇQžÐ›–õ ?jQä³g@"ön¤7´$Ñaá¾RÍZ´Þ42ÜHÍEÒê¹ ’¶¢ºYΣO·ŽuþIíù2bžüKÚ6%´ÄAÙ¶ŠÞ¥êrˆÉ«­d“‹ý ÁýþÁèþû @ðë žˆgXz†UK7åfÚ’ÉçíˆIWÛñUÏ_ªŒ`¤–Lòm„ÏÞ•^Ó4šÀäÓø0=‡¶…Ooìœ/,‹fNéù5eÁBüÇWK:Q¹¼§Û0”’€µç·Ðµ]“øBÊöZÊÿ¼7Ó“Ìaq…«¬ëz!—cYO Ò‘ô·¬÷±{`q Ãð¼àó­‹þI76ÂË„“‘AÞ €Û£¾ÝâiŠ¢h:ÚiGU4RË9v¹sIÕH¥%w)ÑD7mä¢r™š\D0Þ¨S³$äBýû2˜à°#µïç’˜u3qIÔÙÿÅÞa9‘GÝy± U†-P¨Þ,I™Æ *îÝñN¦æ—zÜÏ¡¤VtM‹h}€;”êuÜC÷ºÞkóqÀʵaœ–æ±{.M¿ˆç/cÐÎò¶å3´S¡[ºT“üdFwøÔ®oP™”}¹>çgXøvèõ†tPMkuÓT¯YZŒÓoô¿Þ¿ÞÆ# FÐba™2Êþ½C“®ôûìwx¿ŸŽ}Æ"áiT€á/BÕ4ÖùŠíêuió8Žë±Ïè‹›žö_-éÚWM–7·ªØü9cÿìºgŒ<ÄA{ óº,¢ ñ»ëÙ8]1ÃÜ›Ãø‚Á_Ð&Û·-Ž5íð=n·žm}”÷ëe:6\ÆV,½#/±œÇ¶˜U¡·96mSô =`W(fÛÆíú\ýÖ¶MøxF4†’‰†åÙ¤'Ç}­Û^§›^vÞØèßCÁT2ëÀ]»Öì›j¦_ÚL瀓o`_'fÀè\@ýkL(z4Í* c:#7× < ìÃxõÓ“œYcõ—æºI% S‰ó32¿nD/[ûX°ólQìBŸÃªhCAŽŠä‹kÇU‹æçyhk5U ‰”³Æ/}ÙËXO¥×­IØ k†]o ¨°ìÍýRõ-ä åûØJlNÉÒJúÕëÒç /hÝ|FsÔi8¤öG¼~’œ÷y8Í\bšV3×pf3b|Žº9JèÍ´ØÜÎ(Ê&öC)T;ÍY¾Õ}–Aã€×…\OKRby;œ ï›jñ¢ÅP-PáS 5 —Îç¶§K:V{Ò$Y\efÍ jÿîÜo‡B¨ÁêÙiBY¸¯¨ÐC•o¤ Ëj˜#½O]ÞEò>ï.¦Ø‚wlxnÓ+Vï6‹Áêt?LðEömž·PÈNÍUmô¬¬¦=蕜ƒ¢«Ö!rÃì…×`ÍtyC… 4ª|µ­›Í3b£ßCyŽÙøÌæxþÁAäÉP ü I^–-}¥®_–m›&½ã¯NîÖoC®:MÅ~ Ü˰ s* ÔKn°øEdý8¨}žœªó'êIÎÛsÜóìý$z:êÆªK«4­S]×r®¸Ö…¬+m¯ƒ¡y·/ˆìØä•=ZÌLÚ§¦ÖÙ乺Dè°Z²ßC(ÐÙ!`Œ<è˜åÉÉ’.PPNpL›‡Û„ d¾D¹Y–ätrXÒ••Ô…rQC÷1…ç=® ³SÝ;}|ÚýȱoŸîEÃã(öÙRÇ´6?œö~·—c>”é”e™ P®ÃzG÷oöÝ:Ó¥Ã>ï±É/<”|¬"ý2oðZ·û««£¥ó|kƲ™K5³é­ïaÈn§FÂPÿ}jô3fÅÒM($¸33¡äPmTOÅÚ–-¸ò¹ècQïâ8 ~pBüž Y}1!÷Ò¬b¶p­ôào<~©Ÿ,_ #¬ÀìÐÀ „-Ó\ï[­©°–oïÙu¹ ¿úÎíÚäúLÛ½“C¥^Y°ÒJ+P¶<Ù³è£>.“CëÝÿîÛ7vN´OÜÐ…W÷׈±Ó&B¦0X`]Nïq¬´´ -õšáCç‰\ìY¥­a:ô“@×µüù£¯•Žc^MYZvb¨ã¢ûŒ.Îg¼ ?š’ìïöóvŒ6!4_,~–3]˜í’û0"9Ö£Ÿ ‘ϳM3ÆÜœöÿ¦q²ÏÒä`&àJ:ÙóÑ:;Ìê ¿`œ{ÛLˆŸFJ¾alÑAßcNR³j€ÙGˆïsÈð*’ûÞ`C'_¦FOBì§`¶Òí´‹^­¥V‰ô‹,øó87¤Ý”Œ}ü¬¾LŸé1à§ ð閭.ýD™’Íò­Ð£ÛøŽÎ›1«¹Y_Î{´u~dLÊœoF«"¥ÉTš²ºé,š¤6ð¡ ä«{?d|øL¥ž¾Æð–j@Ø9°¶4È0y=DS”N}4Öll€õ(¢Q0oÔ¸É_rö¯‡8x!åbàžŒ‘rq=›J¸Ëò”˜ ÃYÕÝk9ô¿ ŒŽÇ’tOºPj Ω~ü:y&þ’¹GÖ6 ø•ÀgðøºiT»et3.íGõ,€3ZÓç É‚N˜10´¿Å¯)ÑüÁ‰1@×VECÓÅ[w”#ÅY•¥ìÄ€’bß½Cr×—éÔ×®†ã˜‘˜«Û–•gôL¾3¿û>šbYÛ ¦Û—~ÛeŒ¦ñ/ïKà4ÖueýÌ"wUP²©ûŠÎŽ”B´q0­Ù¾Ü ý‹J&ÃÐ=ät˜eÉÇzVuÅ4EÕc“Íq¤õ¸õY[ÜF(;N m¥¯ùõã-T› F&âIiÑPÖI2åÅrÇ­G‡ØF›Õ ?£á«ÀÓ›Ïtœ¤Ó•”àØ Û¤†¦ÔÝÙ«ô¾éàQòFçú~‡Ì½/¸¤XP™õ([ Ð_½YÆx ë]Ý>ßÜ‘€Ûg rcb-Ü>Õ¼NåØÀ²M†ë´U䈲\ ›á£s-RŒºÓëVwÚL%IkÒUJµ„å 8e‹E&HàÂ8íè-â3Sî#Hié”m½jÊf2OJ©ŠÃ?èf8Èœ_>ðˆâ¿Žz­üòæpAQ°€lòIOµ>êÉðnù× `$ëž Êçófå¡·xµ€¼‹VµL^Y wU#•æ[4$ý˜šÇ„U ®}7m2£]À *P´Lœ–bÇàƒ8wåHá¢ÓñxDªÊ)סDÍC÷èºv©©à}ã‹SÍÁ¢ägÓQ7uc©¨Éd}!ôM@Ñ‚ú˜k@šþwÓvc—q&þ”å¯à ò;½âm/FÊx4…¢åù7Û¿"â 8ô4#mÂSc,æê­))iQÍñjÍšžuzÈÃÁün]½Ìp‹izKxeBGc ¢ž·RXY¬Ma~¹ï†.Rq ¾îGØþŒô˙Π–²`liœ2w@Su—mi[/íjÖƒnÐwÛúˆiüû:hç;±fêeÝñgt%Á|‹ÊyM“†ò¡nþÍ‚w'/ %t«†ûB›¼-Á×ÒpûTÚ5ZèŠ4Û_?äýO¾‘ÂPBÍ\ªÑqâÜïÃÞmõØïc¶Ð­Î`®š¢ä6ìÑìÓãõs9¼8µçü,ÃØ ŠšÁ‹ ½´JÑQœõ:vR*.t pƒXÙ™N]%F—è…f(JVဉ"k5iÑÇ1ýž&ó˜zÃís r™°û/ÿÓ|¼7îàr®‹®0Œ­ËQr]M‘]ç³!Ùè¸jF¼7Ó"bEöÏùÖP6} „Má`œÔ&òjHXK¾ïû*†EÖ ͵o!%½G¨¼_„#Îná°íjø7´3Äw¦YüGº}´Ö{·ìª—g¥ÄênC—2 :Ì=¥.sö7°òô¨Àƒ©‹ú«“ö:.[–P-«ŒbpÑ™%ÃÐo.å0ÆÚ‡ý®ìKÔÞ/鎶pr­kC^Î×eÑT?÷xÞF>’íAæ>hŒ}2—Ï,î¹1ò—3ÉTûÎÌ{´®Ú-Rz–5kåÁ}+D/Ë¥jäcòùoûÖ_oJ]2‹c¯z/F­Í¦pÓÔïkU‘nÖBn›.GÇË‚Åâ©vpQ£xþ¼5w…S ïè&LjxHIaXÇγ1[YB6”O{3M:í~]gÿô~œÌ‚“·\ÓÜÔþÖ±‘Ìú_ì )´žõ¿ö=Åìq£¯dÞc't.Àf6E{" 0ªÐ/™Kei[³È;äL¦uYó5-U:tsÍTÆç¿_Ô¿öï~Ñöјㆠš`­ éÒ¤¿ãN• éÆàaÅ£¶»Zë±7ýSèK4ÂGn¯ rdƒÚ›5«ö*¼iƒFË6Ï÷\#1tóìoOž_›°ðhè]pîÛóH³,[Ýi5m“ì÷†‚„2+ïv´Á +vu}3 †m_ á Žp€U0ýrËÆf]Ó­žô.cCª˜B*›n[ª˜ á9ßï‡Êç·cùp5,¯év7‰^ €mŽëÈÍÛå$2â3kRªJ@=h8Ç@QÛ¶Ù†fŸ“¦ˆvó„ ûÃúÒ°FMÍû*jag mº‚U ÚJQ@JZªû>®3³ÅD¸*›âÎ ¾u ¸‰ÆRÚˆe,ñ€%¤´÷”‚šZªN7,¯L †6«{ š!—kM5_‹§ô¼c"¤‰ÎéÆN’¦Ý¶¬ÞX.ÞcÕ¹û>dfŒÌ(•;îW±4-ö"WvÕAv>š¢R”O'­âQÅ‚W¥5C2+ÊûäéüÉ ãïN.ìdÒ?¾Ùäzèà8¤ÿU¨È9T˜g¤|ŠÎ÷éÃÜ3T³¸o°å~©4-0+ä¹t"§©Ú)ûSKW¤õªš¦Ú²ì÷‹úÿŒ ÛªeüfÂÒzp×ð|`)lƒÇAÒ{y‘ÛS¤p!Ú:¶]‹ÉÀ·UóqŸDuÒ™%™ç~çNìÁ¹ß?I†EÊp‡Ê‡¦Gg@Ü‚ÐlÈU¹äQ6oõÖ›÷ˆtà8ì”~;]Í/ûbB¿~Ì3bðÈ8>$ RíÇj)èZâcM׌#GœÕ¢‘ªý%v¦8†ÞÛÞ@S¨‹AÙ¾õÙ\Pª*«&Î!, нg ÊJ_/cÞ€'­Y5~`“Ÿ±SE[$#ô‰Ú>éM gÙtˆ Qíth’}<&Ä€T S0É (§óLÆÇŠn†™JûJÌv!‚FáÁ›k˜ùÞ5^yU°è}[tŒEç.ì:öe\º.ëÍ‚´ æïÚ'Ýþ_§½í±^ˆ¹›æÈAQò­kѤ‘–oá·T´c/äˆ&›Õ”ìY¾žÊ“²=sŒ<íSÉñ¿µ1þ‰Hµù0æL”÷z°Û½ˆTß?äyp8ž¦Ǫa¥}l¡bh—’ ¨Ž*¿A¦M9°¹¹Ý!$|ÌFƒ«®›§L› ¸X‰Ž‡–Nû¨’‚>¹öh8—DE »a×ÄJ¾?×ìóGV*{â2,˜túD” ÌTÕ®zk§b-w³fÈfÕ>¡ÿ9“8m¢×AlE³Sû|¡PYëR«iJó6yh Ï2Ï81Š“ø‡SõÔ"Š)V£U qnHŒ,H•é¸ÇѦò.óÑQÖ†øw+üd§ÎÛ´oúÝœòŽ;æô³éâèòq¥”·ŠãÕ,ú<å£7(ðûf§»_ZJú×Gµäd—EžÅßÁ¨®¸Ìm•Ë’!ºù÷À†ÍþØ_`Ô´Ù™6ˆ®U«£»®Õ®rô®¢hO¦½2)oX©²æàq‘9·OKZ[·søýÕb4j”2ö½íc]gC¼×±)pBLÔCÝ)Ý>œNçˉèÇÜè|âG²¸Ûñl´xU3%½H±°æý„Švz`åíýn®ž7Ï·í×›I"–Aç§»i€Ïß8éUïÛ¾ýñUzUTê2Ÿ§*Ÿwíz—±tý9‹Â T3ÏäöŸø=žOÞ‘ µ…œ@Ïšd3„Z7U$ Ð.ý¨èÿmb}qÏ 1„sQjx[}ú¡P6g¿ Õ`Útlf†.ã’oK[eõÔ­ôÝy=ûUôØ(A2y»ý)t)qe è“)ö¸-!½ÎÍPìó!£ÏpºKÌ3œRV¨î&g¿›{íh‡>YŠsö,+0q]A˜:0—¥íÙyÑŒ”Àªï¶:ÞÌz඘#@æí„ˆ^›$ç›'zUF¡¼B/‡E.X…LÕq—ö]ÙZ†H¸ƒJ>ß$AH±xüF’Ìéè† ²‘$¸€SCyŒI…ï6W nƒûQo¼dE{ššðøÆ“Áœv{A·s ²olJ7(g )>Ä”\Ûþˆ)I-õbGAºl =ÂNä dLt©èm6E’O”pëY6ù$t½Â 4_%°þÔP}pSÑRêxÌÁ UwT?FÅ–(ùÕíwáïÚ‡e(@±×õëa`-9zt_Ó‰kG#¥Yª"ÇŒ>©‹E–„QsêÐ;ZM¶{J³¹'Žä(*¨‡™}7¯ ~TìŽi=¦KED¥³Izé€:Øì¨ƒT88ôßd–çϯ#ͬ`…UÚŽ…µ”yLùqÖ­[™Ê%†¦ã½{L2)hžm±ÿ÷C[Rk:>ï÷´í8s‡3»-·Í4®óª×Çã¿Þü×ÿý?ÿçÿü×ÿýÏÿ‹z튬èšfÛú¥Q]_ŒEº¦‘–I¿àˆã\­"õSyýÓn;zÐòc©8†Ý¼ütÛÏW”Ôà¡ôˆ{^DZJ£ô¸×Õ ÃÄ;å]A¸G‚ë_à_OÄ#cÁD¹N|'ÅŠ…ÞE«²3Ï8hYxèH¹º{xÐŒX(% ñDÉùÑÁ0‹—MMóÎEšíÃ’ÈzìêàŸtèûÐÿr%h?ŸœÙˆd$ä®E]8ùš2Î]Ou¼6i±®«\ó Q¤òÃ1ºFPx¼ôsÁí7šñ Í—5룲dä»ÑŬºJÄspØ}Ù¾®ÜLþõ¶£K §öÉ5“sÚÎøR WgõºD#%ÙK•H·ôî¿a`C%Wh`â'ñn•qô/-ªS g‡;ȫà Ayˆn Ÿú²ùcÝñŒ(€#C®ƒFbš¤IBHÙ¦t ® ²½P%¸aüyCÿK¾Lÿ¡üh;Uøñ]´â­‘¹¤%ÂD¶ÏPVƒ( ¯cy•i­äì–ݱ+OnæN©1Š2¨ØjéÏÝTÚˆG!®Àkiiÿ–½ “½±2{#‡*Ó$ê™XFºtSÃrÞþ4·/i‰dËü.˶‚ÊûÀ–ë´Dc¦Õºm:Ê'³ M5r D8ç#üç^Lž¿—M‹Ftƒ·àD)ƒ©zȦ¸Ú{é…@|ö-´\ÎKÿ8Žð¼^¬JΔrpaÆvjÀ?Ñ'ßt¦è²˜(Ïçx’ì$ð©Èò,€¸OŸÿbhN•ǯ©ÞÒœµ2êkß´éL?»RT²O¦Â ¹îÀ` (0óÃoWµ¬Eb^/Ë1=ÇÈŠ«#|ïe:M A³þÍzÜú÷xÿ‰DYd#Û†ÇÇÆ¥v.¢m¥SXƳRôÍ'³&l(Cè(àü/òáÆŠþ˜Ôµôµ;ÜgÆ*±*‡<ó¸ÖTÊ jéNå/f.”€Âzýc}%¦½Ma^EÉrY­Éjǹ‹—½(µ”ùÕ\ÜáÃMù·w"àÏ­81z# #šQ„-qU×s5—ó’ÍC™gdç[ Ρ!AvôBL{›Ä¢äU Ü7ÕZŒîœ+J•ÆnÞ³¶ÝꥊeÉÐu¬jÿpfº_yÛb™OîÃ}¸¬Ü+ m)†tÉ‹º^gi¤Ñ’Þ—¹GoÔ >PãϧÁ‡Í™ÎNßi¢ÖH™ªyO&¦¯6ZywzŸÝ/EO¨ ñˆì»5¾* €÷t¡L~¡Ã]Éz€ÝRˆômÊíÓHƾbxEq”1¼ÈhåñzºÁ§ºÈãmª—Œ®^mÖƒh g³1 ³Ü/YnؾÀ³æÁe³õÚ´¿Û¬Êº¥©‹~‰iƒf²&I¸iû˜ÌWì¥fûÅCY.Ê¢çþ …XC¨ƺÚ&Jƒ¦1’õBˆm9P³ÜàüÍ×ëG•áJédG©PÍW6ƒ‹ò®Óq]ëF·|ec×Ü1H¤_l$õ¤î¿~•ÆÅF‚ÃŒ.l“‹ñyÀ‡ÖâÚ™¢òeœ¨‰bE±Ó½3¨©Ë벦–c96¤Ù¬þ¸®¿Õ wç*µdöQ 6ŸDÅmVm›(zÀ\o‹p@‘§ŸJE%\d dÙþ»k¤Ï/É%%ßm[€‹¶ž§hɶµMŽaÔ~ƒˆ~ð¢‰>©nŒ³42|„̺4D7é&R[+kŒCÆ¢'z÷‹’ýÊ‚†PóŒð}šÃCQ„„HýŠrxNÃÃl²nšRÊÀ“.]F ëtÇd¹t)^@ŽñNÉžãÛÖéôøÑy¤£¨Ÿn %ô5ø.YJ&©èRC5'Ù¤¤3 €€íR#*4Mãìz€Œ7n\ P ç{9&þ:£*²Œ.Å"î¶:—ÇŽ –®®Gûò#˜}Isß<<’¬¢¢4}VÉ»‘åXÇm[ômÒ£ÎE[—nX)ºóŒ»õbó"lŒœ’ÒB­s¶—ëVÊç¡ý ¯ œûAó÷¿´ŸFÃέY›§ü*—AéºÎ‹(KöE¢‹þ 0òñ>\—Z{{°90gã%cÀ]hœæôºõJIº|ײ‡B©kNLùÕs—MDðm¨L*YŒ¨–{U®ªŽöº¦>mãs=æ³6ÈÓáHç-9&¨ÇÅÀéòvÈ„ó/–BÛXÀëÓN--»Š+Îqž†y.¸ë¢5íá ÓW{šÈÂÌŸ¦Û›î Ãsä0t…Ó f’æ¬4 iÇAˆ“@Ó÷qž¦UÒîÊ,èCDZ’¢*IÈ2¾Œb/6×§ýC)~9ŒIª7h3ëYP'„µ@=úr㼩Ò~³í0qÞ€jí8·*©ºl]ézÐæ[{ôIn”Q¡$ÎþíÇ\] ˜¹•¦HØmáaÙU· *b g´I« žCÿbJÆAç ¯iÕ<&Mu‹†yê Ýcv©Ø¢aßó›Ã›Ké)eÁ‘±`”^ŠoŒ®_lrGEvÉc=`ÜzKê–QÑÖÉꩆ+i#éap8¬lŒŒX‚éKªïeÚ?U™£o£(úÌóF·WW4ô,¯Í Ë“šÉgªfM–üï~íyýÉVk`Àò`lµŠ^gqåR;>Ïp}£ÿb@’¶û'3ÚŽÚô;kžœõìÇÝ<h)!ïG½Óý#⌰-P;B×ó‚³r¿Î†mÏCã’¶b3Ö£èp#±ZÆdŽÇšbÈ4”ìqøÍÞájR‘xh8„W,ðÊGJI™d þ)eÚc‚¨÷6¬tàHå~ÇH¤ƒñøïëÚ^úúÐØeí Q{¡ôe•–!»C )ý {Û·n'Wö«B33øšV«ÕF¬ÚiKª½Íg­u¬zss˜`C„>ºí}`5W‰f´c¹¢+Aª£t æ´ ×ìÓCÙKZÕY¯¥?i#ŸŠi~ÜO›æK¥ýƒÒÛØHTåˆ>=·ær*‹‡<®’t¦‡ˆœB@BÙy°„á@sù¿Þ€R±@!C¾0Ë•_¾ïíw”öR&°×ãd~9C*\à è~´Î.ÚeîÀ¬GÎ[„ž4¦Nü((í*iÖ9Zõ*ÉZ艉øÖÊFþØ¿Ì «9.ª›jîšÍ-è:å¸rº|Þ…ÓëÞ@¨¿C'“þÓ?->új,$ýbá~ “9\–N±ÇiŒÕØÅtE(ºÛ.–Ö¬Þ,¤½T8Xh_CRN0bLw{Ÿ¸ í 1¥[÷õÖW²Õ‹.Æ×PÀ±ÐQxUÛ~Žé^ÞÂ×I‚ƒw§©š–©Põ"h—hªé¬ÐúÛ4-®Æú~8p“ïf¤á?Ô@%å‘¢7:WÕ&KÂmÒFw°p?NäÎgt¿=…ªÒ²,1¬áÜ:°Èw[ªrl󸮢²R=l¸ÊÂÀ9¿-®ñ㯡Ð1 ‡»*Ùœ Gh–tÉ´é>ê9Êã¹–õìh³6º ‡ ²sû>5oLk¸l‚¹50 ˜¥â4mֺ߷xajZ’»‘ fC÷ãbs¿~ýC—¢Á¹a¥4ÉáMÖÆùXê³Þ¬‰ÓBω:ö˜…ÖIäû•7íÈ åmÇÊ[l€;Ó<'zÚ‡Œªädî¦yŠ"qDrÁ°‡àlÓýƒ1|»b%) ³lTlLª‘S2* %»T¯EFµDݘѢ ¾§EÑ “†£{s¿ï»èÑšô‘,Öô Ó¹—yèv•éyë:Ý¥ƒäû”œÚ7è;ѱ4–­Ì¾¾"~¯—)ÇÚª0û–ò}ˆéQ\O÷‚n¡Ú¬gù0ëÒØ2³\Èô]­¹Yì…ÇA-óë  bà œpû›ËÔ¬‡öÕ›âmƒ«¸ùë [îÝö’ ¹%9õ•ÚuµïýTÅ¢’E Rq;:,z?«î‹ ÀlvæHè“@þ×b eJ[fUv”[«}ß¶)k³*>6… ªÏ|òj¡/¼ãh±ÏÀÃʇ½¤•öDm:ª®+ŽAs½ÑëîÍi]!m¿Fæû"ð8Š _µ@µ¦HG_kYZ‘8Œ0=3¿ü~û†-üšyÎælѫ쪮ŠÕ’SÊ‚%yAœEö#v!whÆŸ÷]ɸ ëÅjÒõ$(¬­¨OÖuW}\RÚ/n€QUøÐ³9Øû_:I ýN Ú{á 6å’¦m¾õôV×)OFAÙ=ô!©pÂTœÿ¥ùbš/º˜'ßPÁuÀx~0óæ’°=Ù-ðipøâ}{>šåm=ݺÖYaÞ'}£À£K6û# ÷|㻿ðGrŽK‘ªëe.žÕKD{)½¶ À–±°‚*â—ÑP2Èøë%ïWÁ!Š)½!8ð&î2|ôeî«^URÌS±•[ÕÈ’ÀæÛhùÞl3¹‡Î)8„mDQíà|R!t×4ÀÊ‘EwP@w¥KÊ0—FÉ'G¹ãÝ`=yíûÇòä[™œíIDtc¦ÚŒûY Ãõ„”Ió“’+Lé¼;%ÎQ;&2ËгzšŠ0ÅŒ‘‡kZEѶ—Y™”±Ž…ƒÃ\+ÊR¡ˆÀ»¸K|”/ô 3~Î\ÒD8V­ b„@y³ï.ò‚ô"Ñe -xB™;'¸]Þ)V>XSQ|^À(ëyl€>|^Æ1ÞvúX©RBxpab²+€Ç¥sÿö¡þdL”íA̬D<³ã„:ß–eÉ—r§—™u¢KâÂó kRyâ›K‡•è¿oçÃ$–¨Ÿú–{Ÿè2j¥*rÏ{* ¥"£<Èe[$©†sZ¡^rß'> Fh ý©;X|ì‰*²z¯Ói¬§f4ï’ ‡m+ÐìÿÆk'ì ûAú85ÊØŠvísʉª¾PßeYg„¤:òwìÍ9uÅ­2™ÖK3 /š¾¹kJèåQÀ¬¶j™+ʹ%”d€!KbnZØU|ô®7Ö9ÿuP<†fšÌGÿ$¥ÓmòzŽ&‘©£U»÷d×q [ç_FŽl2Xê®bIåÎØ¨Q¹\ *²¤š3.ùë5ƒ/•óe?Få¼*¸Fýh@ªŠ)jŶtCV‰þ¾‹J”n2&¦cËþèr ‘‹a¼/;`·¤÷ l”LCKod§fÕ"ûÿAªÇ¨b¤À”¡\àmÜ´3-UöIDõ8öÌÝÃ;¥Ÿ?` C'+^›ß­é‡W:ׯÝJˆ§‹E€ ™ ¸vµJ©H‰(KœÒbÍ´ FÎw1:ðp­ìA/ BIõ³8*™Õîe ¦` ˆÊ=67`¯-Ç…B¹eŸÔ«‹z !CêÎx²ƒc.BŠy¶4 ª«#“h¡§Š*öÝý:@çÍžë§I›Ør²N¯˜MÜÇq7婌.]Fа…¥Ãóþõíí-†º#V·ºXHʯe™KÙâYôC`ÎP¿:Χ…ðfÿp¡ß¥îššMqÁABAMuo¼Åe[ÅUu¬éStî½ÃÊ-¼ß¾lvŸOèN¿g¨*=¦ Ïè@Q¤Ë¦!O¢-™Až3kÒ]D{À¦¥ï”A¹êšþ¼M3³,Ë‚‰ÍÁŸ¡<©kËfœ)¾L…d6p¡Š…¢Sç~â þ}EX¾'fYòk7¹£Vµù¨Rg½IdiÍ5ôáEz¢”ƒ¯²_/õ¢hY°¯bol€†*‰§ZµiOª+âÎ,Æj• zºÔ¥kÒ!è€q’P´(AÒFK­½zŠ‹X•}¯ê]Q5'ï’¢’ ø‚mAÖË„P÷[uâ‡ñqؘ‹ôí¹1÷6®¶i‰êrW™,èX<•r@ µN­Çêð&ÎGfüÑe@°Ú£¬ÜÛÔº¶›.„¼ ëyð)¨šÝS>Ò¹º)¾Ȥ³2hb˜Š{¼S]Euzm¤hIÿ°Q¦_;ü.ü³ô}2o1ÄìÑ¿;papN*Î…ÈÆ. ×¨Û êufãlC…š.æAA> ¯ÎC—‘e#¤(¨)à5ÃÑ1EJ² <Ø›ì'DqSÍsšÒ¥1ÇÃRŽ£ôš!Ìãc KWùéÃnùŸ\óÁìu€lQê„s3¡»…ùk­e•mmÞ­é™UY ÅÐ¥sýÞWQðÚ˜1ÀEÊþ†±þàÊ·•R¥‰ÿm+k«  –¯=»ìì›ý©Œ¶<®€ÎÅb“A­èT{ÕuÔGòÍaÍ N—ÍúCQѺn"ñ¯ÿŒðþðof³ çÓ‚ž«kÀ ŒïÿäØcÄ zà´µ™à E ˆé@ò!VÕï4 þûŸá”v}µY3ëêUµ ¥\Q¿©zÜÆß.h9ÔøãE%(׉“°ízq³"Uªvö1]›ºþí’žý%#¹‰H1}kŠ=U+²IB:Sk³«¢Éªª‹%{ýëg<ãÏ"mǧ>xl‚t/Î@Жœ¹ªT…j"¤…– (UÀ²)þºÎ1#wü/94อ{Œ’n332E4)š6ž*],…6C4Ú‹6ms玘~ æ¬ðO¶¤F¡9Çd—žµíkF¥VÕQ¹2©r+M¬„Ô¥n æ|þ)utQ¶ËünÐçAú*ð$nëFYQ”GÑ”+ÁYxÕ¾”:·;•òrv(£xá’(r:(‹ôãÜϽRi›6å´wÀyItŽè1íû%p\.ñlç™Ûª(”XQOYçícç{m8Cóþðìo׉\¶ ÓÕÒRâI.§7*PéopÇORÐåß8%äglrV“fS,Ty–)wó­3øv'¤›‡®Fãúg{ë?ÒµÞž›~½_QOˆ(ߦ cši¦oúýxìì¼èiÓ¡WuÚ.e1æôÇ«¡÷ÒˆJyº¥eÁ~:´NÕ¸_­6/äoóç¿ë ôv£’£Šu_r]‹™¬Ç‚ 64ö£óÌþÚTÂîz½ÀœÈÊÒ0ßö=Ýãhß›iÊ’}låY,ødÿ~¾aï:Òï_ƾ»Ä…Tò€àpShòY«JŽD°ùžëwˆ¾¢a|? YN :Toc) b­×N”3Zm[‹}išr²Mdn=ï™rfàn5ÝÉÞ¥kÊ‘¥Íò¶`JB={ l&Œ¹©ä˜Öi5 Â:ïà,»wë¢YIåÛóHg dX1˜ òاuÄc¥Æ&T27’ÒaË  `m¦j_Ú¾èHB— qâL. »=…ZÕ¸TÇ‚®‹!]ïwÛ`w,÷:µBi½Á”—Kë  Nüè þÆ\[·P3†C±'µY•>8T–@s¬kéö)[…è@e+íWŠ  ¨•zŽ¢HÅq—uq÷±,2—ÓƒÚ­eš)îEN¶÷&¶_)[WµÈ‘u ûS¨šJ%ŠÞmËã ȱ4k@÷äí~ʰ]æ‰Ï'œHj£ÎU³û2Öq®v«(Þ·"Kd=èÐóT³hzϽµ~ p¦ž_A¦\ö7<ÝMô\z*ÈYäfÁÍ8€ZÓ6³CÿBáy `\ZÓ ã*#™Ï^ ãªè#ˆ}‡>,¼äaby?Éœ«xðOü|¬Þѳõ;†ty¹Rí]™Î©–ãâyÇrôõmxÿúùÿ0ü‘àŽŒ1¼WEÖF&ªW#‹è‡‚ðmw㸇Žý¥ß÷Gÿüœòì-̪jcýˆd¬âIÓÕMÂí¥ƒ›@Üà¿8û¤žé¶ñdcP'ž”âz[:í›—?öeýC¿éßï± 4d+÷‚Þ@4ÍÙ’Îq¯{”T¿ÿ£>Æ“Œzdµ.ι! Iï¶í1 5˜G:í}^mu3u‘øÐТ!]wÔmìƒoæºWÅñïÇ/`PF1ˆÂt4¥èIÚ@—°Œ]–Lµj…ß.¸ÏÓÚ/s˜×b ßñ$'ÏTžn3¿KW™§to Ë÷xpŽ,'¬UHk¦r„ >wÜÉzJT®¶9V”ÔÓ•\›×é¹¾…º–Ò¹@”YÔ!¢bIK¢€ËêˆFä!›D5VS•홪z³¨I Ë7ÏðTËþ*aÞ?ìÃLÈ­× —ŽB³mñÚdm”Q›ˆ™Ë_¯ùåùüøy¾7¹-´\q.òŒ²¦|ÐñfyñÛ%o¡õ}úÿ‘tÏhÞ¥ï°Am¡óy‘|8?¿‡ÏX5`N0JÊbXS:Õ™×hË•œ¬ê´ªgÁ'ëDá\Oê?Qt©¢ h´ðÞ€ëRhYE—OŒÿ§ÓL€( \Ð’ /Ï‚]#³Ù€eÀ8/j=îí6,õ–dzT0ÐH ]4Ž(}=†Éwë¢JAÕ¯¦0*è^èÿKO†¤å°µiJY,•4½(áû·; »Ø *46@ŽQÐ=ážpË`) º-Ðßeþ‚r¢Õ2­” 6IßŰ:”5}h†0ç3pÏ»cߎ5g#ÂA.Ò©Fo'P†QÌK·uàã•O±.FìùÖ¶Ä=ÀBÏ®ÙE_H¼V AJ?k¬jó¼Ó±¦7Wr¸)LÜ! µÃÖ ÃšKëEé´(>vÍ5À¢è‚Ë{µgÓ®ª<^´ôiIúÔ7úç-°½ƒ‹u³†ô¤(þR˜zº…ûÅå4#Sé¢T•m”4C^›uƒÀ‡š}£|Ó>]¤ÝƒÜÿÃ7ȯw!Ø«©©Ò§~žÆeY8´§Ý\õÕFám¥keŠÌÒá 1ü>Ή¨÷5‚€WŠA÷4kÔ5"æŽÒ(Ùâ­¢#4å&íMŸm Y]ÓÚUk¨°HÂɹ'" ê6«ž«(k¢ê¸çÀ¬üM†í¯ö \Δ ÄÁp"©[Õ[¤e¶¨TÕæ !?T2ÔV¶áE"‡lžøÕ"îÝA ¶9^#›a¢>J×®šÛEV½Sœ´(ŸƒŠÞa/æØßÔ4ŒÒ>ÝŠl/bÔÀMïU—u»GRaA C¬ùw7·¹õˆ‰QÛf²â"¡€Ÿ» 1$«9Öiܯ3ÝK¿[Ó¶¾Ô‰9az•X¦4Æ 0Q˾×ÉLuÑÖùïô¿(’F'%R³1¤Ž­>¶BÑõ›ìi‘Jô»õ/üòŽä±¡àÃM‚kz@Pð³aHçeÐy¿ Nè¯ðƒ cšP¿^€ñ—ý^œäÙFY¶uIÛÌY4OSÕËÌû/½…_ +äD¯Ç%_a.†; «%Ièÿ ¯Uí’üÍš§.ÈÊZïçûçhEB¨ž©¼úiœÇ3§nT3SD7‰*©‚ͣ߿„ÛeäÀóê_σö]â›Ó9GiÉ[©¡¬fž«¬ª×Vx¢ý¼Á×;xü¼Dµ ŸŠ9ùÜ’DÑ• `“‹µt¿UÇ×·¡6 ¼êíhþ8÷/ÍMo ÉÐô™‘aðPOµ(7ÌzZ;E3“Ö„³í¢îŒgþ’x<6Ä•#½»NfÁ\ºÑ¦_sŠù\æS…7ˆÙpe7 ¶°lv®ž”ÚÈ$¥Da©Û ’ÂÍñºæ¤ÚæAdf| *^à j¼³¼ÌÇö@G¦f7vβ[öy£ƒ´CRh§-º®K :0†  û .uœÌçÏ/£ˆUüÿ9û³eÇ‘$KýxIÄøÈªêû´·÷'æy†Á¯¿ºT èåžy"3#¢»¥ÍAÀÌtZ«íc†Ê{»'UÕÕºÖÇR™ esø_ØoEî÷µþxIO;æ[¸à®_ÃtœÊ¤¥ »(S­C*ë¹nàƒPOÛƒùtû°x{nKUS@ö¹æxÞ1Z~Vû0åSÝoñüÇõ¬ð­‚èË0.~r®Fc;±Êëº}Ô®v;uqn…}8ð,074׿(X¢”ë ðT è ®´ÍÇšª‰mÓÆUÁôî+ºñ[Tæ£b}°(:‡àÚö}ÅC5žùïC9(* (û€¦¸YÓ¶å[áí€ Ù§”Žæ_þ½½¾ØŽTé0úžgúÝë4¯ËJUƬça‹²¬hš±I–:—ÚÂÇ€$ô ù„‡µ=%ÿÖã VoÁÒ¤´Û>—zßg1/  µ"ÌHnw£i;gÊù·ùP_+åë~ZÛv¤¼pÓ;DÁ6XfîU—¨¾¡d)QÝØ.±žÒ>3YÈoÿ”ƒ1¢¹øõÙuRr<ø„ñ4/ó:-Ë åü¢ÈЏîõœOKµÓ›“óïÝh*R©À)‰ôÑ<=ÝieŠSòFøh5{›o1EÿlLÍzÜž¼1úô„ß?¤$ÿ$ÇϼŒrü\”ËéXнÝ)½·Ù|Wœúßll€.][6³‘YMž2ä}ê<®Ëq‡¤3â$xšßÎ[ûëréqàÐË=ûr}=T³ô¼!ŠÑ*ç¸î]ÿ0‹ékhFQ~ ænjÆiFÌ»ªƒ¦«J)Fe”<š Ô#@u@ß3šŠ7ë~íáœö–iÑ”˜UÆŽ²ÛëF•é8S&'tך]8|Qü Ô6|“¯9­f{Æf¹¡Žë8VkÏ µ&K—”³*µY0´P]ûȕͩòýîoYú[ ϺÑ.ræžÊÝ5pùÅOIHGOQ?-=ãm-’½œÌšÐ[öý¹ß’‹ûÑ‚ÿ'’Šj];óU(lžZìGë~¹ãcóø>¨…5äÅ¡€Õ‹úÕ‚ƒƒïÃG6%´íºî-P~ÍÔÄs?—!!ò`ó1yQ©•z v*—´lÓ&ŽAE’d‰Þ ú7&›§;øH6TA[¶,$Ʀ}ø:j颱ڢ¾®Ç±”K4´€ ÅpË3 p*³+çþ'H+†G+N ûÃn^gx·é„Û KÝM(±¬_F¸Om*bze Õ{n~¢ _–sœÓË,†zodA*0á‘ÿ>ãbg…·Ë ú‹{ eVI Òó%TÌÛÖÅ[74ÅX.¸O R§úÚïáÍsßâ$WvüëÉI2*AJ70ƃ¶àbsÊ…:*V÷Ù|ï)Ø0ø¾}èJ¹'uDº©ê@g~ÝTºÚ)Ø-£ž†iy½ö¿õö7ý’ž}F”ÛU“jÛ"NËM€Ð}s<߆´šõÄŸ(Ê ˜sQªäëN´‹6˘w[%]NæñqN=vEþ p­+‰HêéËè@T¦jdª‹T4ÍWÚ¥y±æí`öjÈVhy÷ƒ©áû׿¾ÑÈÈA€É4FÃ*¯²¥È´*úˆÂ‘ÙUáö)úç!ŠåúÿØæŠ&ÛBŒ`n}0JTn'nò $z¾˜ n O_…ËveSj*G×VÆÎíùÀFcÚƒVç I¼|X,çô¸>e쌟].zQ[äûl–ÄQ á€äz‡r·ýV˜‡ª7-¸˜):f"…’DÕöªÓ&¥RIMÒa n!*$p’ëv˜ìܯÚÿ„jˆJÿ†²+µåSÞÕt,‹&ùó‚¾¾Æ ³þÕ søÅS¸´ ä©@¢ìËñOE™7Tò±ŒMb“‚2ç&ØbƒèOõ3áñ¾ì‹”t hªCF?<n÷Û_—4#8w*«–ª$äq£A êœj Àéö‹Y¸±*í»{t•ÂðẆh¸²}O ´W+© ]‘ã>¦KWÎ:-dA¶J0¡ yÝó÷Dµ0w-PQ«£0»‚ª7M5{3Gû:äfApºÂTç胰¦ÕZ³ÏX–ɉv˜´AŠëó À(„×]Q:+Ôb¸€“Ø7ôO ÎYÌàHÊ>æ”3šÚŒìÇe¬è}ƒZ*55±lB7:å ö‘hÛÞíÚ]úB#à FOÃ)"̤1™†ënQ 6åºËSB Ru0]©¡ oç·’÷¡„òº :íR±4Œ¢J¶¼-ËuJÖuLæÎÉácíXT­L†§ƒÑÉNy°àxi–5" .ˆ ôGìi¢2ºÚ—­”õB ëAÂ54ëÑ6º˜tÑwþ—èÑ­Zè©êˆr«Ö(ŒünÉ›Øæ¦8oý-öÐô›Y£˜åˆ˜å2¢êISª|²­ßöãgÓîÀ³š·ÑŽ{•}¸y)âÙlÜ8Š8X³éhΧ¬ŽûŬ X4ÇXUßÄîàRšþÚ€iÊ_0]}iÀƒCw¸Y˜u”ÏÖ‡‘(ú›"DÎ3+°Øx²z̬†&‹&¼ácA—JØØ'ÑÛ ?²^ýÐ?™ÒЕS-O»GF¯³R*˪9ƒº¥ühˆ8¨‚ÀŠÎy'i×ú™eP”PHh :tF‘h;ûÁ)žóQÈ‹1aª }²“íkŽú€<¿ôðÙ[¦¢’|`SM4Èâ²æh*¦.ï"ó˜Ž(8‡¬wJ‚ü÷m Íî HÖPÿ‰„~ Å–qŸW*¿¶I¿¶ýïÇã¿þë¿h«îE¥[*wÊ1»>êr5©2îGµÈHaôX¸.™¾Âí¶6¬ú‡á÷e%Xn@T<ªŽb…¢+¥Ët]ob¥x‹E­é=UvîºpnŸOmà‘túAíP&¥¤pŠ.ë¶>Ÿ†Bt…RψjÛÞUƒd{é/3>„ “Õ¹í[Tsž÷Eö”R~¶Þ¬jRÁgݯ£Ûm{‰w)}:|;Øs’=6EÒä‘*2œ«b…«øTUQÂhœÞè‰A½¾HÇè_ ñ’Œ:.㩬۩*–Ö„^*âÀ-8Ð~ 7L‰¸'S"„ߎ ØÒ<ê(›‹µè * }KkÒ€D$s£„—‹£‰´$¼Ü«V¬AûžR­mËT§¨þ«¶>“Ȇo (LˆŒ­#6PÇÔéûT<£¢ZáÖë¹7Ãi̶Ñ5Óm”¿Óï$xàP±çº‹^ÅéDð¶mÒ°žÑ\Pôu˜IÒGºIómÊ‹!®¶l¬ró.á(-¦¢pÛ÷F?ng‰é_F¦Š;rL€—ì®êEQIý’êF¤\V0´Abv &œJ>ÂOö¢«´aõˆ®1 ûª.Õ:î-í…H sÝË‚¡®$8öÑ5 ‚kÉŠ§Òy>Tµ1Þ9eµ»z¬«jJR•F‡Ñ³Y–öì<_~öÖ‰ü³ë¢dŸ%6Ÿ¼k_kµ¶kFÇ;ëZ„Yi»@A̾ÁñÀ?ûáéirq’ löm5´#ÛÔ õ´ªeòj׫¦!»(¤Ôˆ.!'ô¨<?ôøè8ÿâ¶:R¹/n«[Æ_œÞ#Ós,($Ú=ž½òŸ›\¤¸òa3K‡±²ÏXd{^Q’=êJë¬ß"³æb‹ÒQ·¹4÷®g\•RzJVêX‚Ž¢U"cm貌êaÞ¥ù»]ï½â‹½ºäôÄUárÍc¹~ÕŒzË!)µÇBýøÃŠWË p¬Pêó¦Áˆ‘] …„ÖaJ;]mÛ^G{;Ê6 oÜ-¢í q ïÌm.ÂùßZlÏèÚ è9vm7 ¬!;B8?Óc¡öbÇp¹2Ex£BÄ» °È%OZ.~c !²¶%ž•-REý|ºrÌg5ÞzQ²f/0L ÝCÖ´íû›Š¡ÞxЪSBVQ«.—fìrQ`–Ò7d(Jø3‘ UcÓŒæåò/(ÀmÐ*(iÚ»­ªú‚Å¢¤ À’þíæ€ÁkÒ3NøÑ+|&ÍY‰ªªåJ³¦¾+•*·y¢ìNêI à”ß ·ãùfy·\¨¨†2¨C”¾é’WªE“¶öu=VfIævQòé„öí]¢^lœÀ…[º TKvQÞ'c‘¯IÒhºëÄ ]e† V/LÆš67Ÿ Ãîn©§‚ÊbÝM±–9RÈnG6„Ù¼òáÞ/#Jãûö}'V}Ó°Í…J“z«.šR!ºxJ*s¼#o»y’†LUŽ$XæûˆâR¢`XÄ”«‚ùÝî½> ³áI¦¾¢K·Cä!kËŠMØG²!½xàÈÑ¢2ÿôeÝ'Š”±Žt;KŒp(йì 0“²úôÀ8DA}èãx; ÌE$ÛýDù¼^ÂKa&sƒ—Þp’•S–Ú×Ý—™®”XÕbMh`….tíÆvuifé¸úWå¸áá8éFÑëóHÜÑŽ ‚à­÷‹Wí¿ÙC<’žyÉ\.„$/D (ôÜnÁ‰ç¸>ããûuXGÔUwNñŒTJŒ±Ž‹¦,MèJîY®íA0Ðäá/¸˜ƒû8ŠÃ¯'Q~4ÕdtA:@½‡ÆÆ2¼ººë/áH±ÕUdà(³ö‚X,ôŒ»ÚÓJW&™†\Ž–þ‘¹‚ç¯ÜùeZZš_|è÷²T“…”ié¥|‚ æ—ˆ²"pKœKã%²$Y·-ý˜gu.פë@cÜ 0õ0½(°C®ZcÞ è| KGæŽËgIÕõ©îÓmÐYÐ…—¥¹Žo>‹(#Z§øÄ³Î:êëŒÎ†šÊ´»dŒ'sý0QƒÝb@û~¥ÌÿÑQ§û£,Í©Äcùn×sÞŽ:ÂóÆŒ§€¼P¹jŒPã¦Æ1¯ ‰“'Y¶ŒfUÀÑ-˜…Üíc’ðQã!ã•a6ÓÜ)†uð\U®iöbêXéX›ààÝ1s…1%½Öi<“}Ÿ½Ì¸ÃîæWÜζ&f y¬~·À/<¼?<Y)€¡ÉÈÎOVøZЇ\æúÁx'ø“Þ£ÍÊ·‹(ÆEÖ‚%oþà”]ugäEð³ûN—ݘ®kï{d>¸OwÏòrª¿½.ïÙŸ÷$d9àÔ¼d)}ÎÌ!B]ä]Ú õšÊQ¤Ø†ºG"mÌÔíöýòTˆãÈRGß(§š|í²Be±Žh+&±òÑT£:‡ŒC´Ï·fª[zÎgl1-‰‹r¬!‡Œ­€yÒ´ûkØ×íɺÊg‚ᚆAp·½À`¼Ogfýý0ļ۲§ÈÈÝ{ ;zYÛ¼^v]tZ¥}.kt|n!®#ë€:»JgðÍ’Nh bF]£¬ •Œu9LiÞGsŸð„3 à‘nÁ¨É;,ÒÙ¨ñ ɆN¸Ý±Ð/Ð$j9DCü‹–âcS©¬.êÙ¬‰A û 7ÿ&`\ =îjH¡GL fí` =Õo1däúšª#JôÝ}çæòÖG'uÞO* à˜ñÜ‚G‘3Få<¡ŸÌ’¶eÑÉ„ ÒÍh˜„îrEÂD@ R…SZ?µ-m&>íE5owç’~w¼L‘ð’ÀmMÊœ›eŸ!è*ÎôOÔí*£nÒfÇ5L+Ò£ú×ë矞UQ µ(á·â̬ǴMòIçóT™çóÑ\ CÚœÁéÌ|»ælF„Ó :lvÆõ#¦­e;)€a91ÐQG{ıŒ5s3¯²Ð.82ž¢ÐŸ§ÞXq'…Êç™"æFeU•0! ‘¦a¸ ¨–ÿFøW…ÞŸM4Š@*k°ÂXù–eÖ|ZÚt/²£ YÓ]ú ½ž´°³mûübßg¤—³31|nć·BÕ§âˆòôh_÷Øä!\ñ”}Ýà*^o€î‚ñ%8Ê2}V‹brò¢¶µ0ë4{§ôŸG|'YOF¿ÉØ´a@+sÆtÇÅÓ¨ªmÖÍj²ßrT@¹Ñn7j`ïÿ_Æs¬•íÝnÀ2S½G_`¿'ÅWÆ•£›Q®§Š‡…¸øi“oÕØê>­æ  :€fY@~¬Îýæ|P7 úÎ%{Ø·Æ€Na=e¿Õ™NdAö óïð’8pý¡ÿ‹IÖ«(8ãç9'ëU «8gÍ>V]¹2×»YtŸÁÜ#„r”wJQ9ïD§1<Ïs´½Á£Äz ÏbÌb¢©›9}ñ`fâ;EYºyŽaöíÝùxýhö™OŠ´@Ê,¶0‰Uf]WI6›a»b³$œéˆgÆ•ôöMw9tü±cåk¬ý)ùŠö1šx“ïl_ãAS†öôÍÝóÀʾm|¥Wù`s^•v7ä_‡mœi»4ÝAy¤@¬Æþß­ê^¤Ü#y0ñ3Ih#PÓ‹’@ǪM§(ã¬ØdY°¾7¤|æPwÿºö”õSËð‰Z|žzÂŒp¢‹ iiT’wjš³9‰æÖ,êÙ€ª@iÞ OÒ‰‘¹2FC0{<£¡²DÜy¦»MŒ†FÝ.šöRJé;Ïz~¿0H´ÞÅ¥KÃUSšO,Ôy h>¥IºO]–e{=íj©xMz/ìlàÊ~N ÿSmø‚ö•YІ¨›Oõ£çÞ›´ôûæÙ€7b-|ý·øÛ›R8®rc”S@þ°Tã›fÏÇÇQ¿Wæý€d°Ð¸]ÃÉõ2áÞdÂ},iÝ<—ícÍÙ” ÷ýØJ/úÊ4QÍkX Ðl„R8Ý™T%[6eƒMYMǪ¥˜d Cÿ-wîznmFF¹ÁË즎ç2¼ëó¡Ë‡²™tUOñ¦·cUœó Àu|HLz—Ñ&2˜§˜ÀgMË96j?‘ȃ·ßZTTC]U›YÒqï”uP\;ÁE¡‰ˆõÓôE‹¼ià7¶¬ ˜Ð/¯F¨yLy½u[d3¼ÃžòAá!Ïó‰§0ô4¦ttݵl§16¬2Qd0šRÛ\gK7®›Ò¼& ßh¯Û”®ÆÔǵlÞCÞ'tÓ bhf»%ûí Öý8ïzþ{û{}½ö×ßè?ëÐÌYºÍ}D©ø²K’nëôÇ?êv ­^| B[úñÃrX¸ ²¾[&ˆÇ÷³õ¶¯ÿý÷¾íc1íÅ0ª¼ÖÓÔ-Z Cqñ)3N ª½Ð$ð¿r¿™‡Â3aÆÀ²è}S$¹Ž’¢H]åÅRÉ‘£°O¥*ÅÝÀ,ë*Ã3ÿ§‘Æ*°—#ǽ¯¥Iã¶-Ó²íòͬç„wžá)d¿ííß('ª0¾’È `BÃÂ60a]ýÖHUzß‹Èì`zùwÀÏlÇqNWeçð-ƒéƒô©¨P”.¼Ø‡¢Q¥ãjuYR"P˜_M?›êí.qÞí$©¿› ‚•iXÖ‚7¢ü@<«}Ô©^©ª¦QnlŽf”6»”>J\Í®ƒºf–Lê‘¢¦Ú<ª({ÔTƒ˜¦Us¸»<ãŽäþÒ“E_ÿHƹs,åc¤ Ã]tèºr2§—u«,¼Bÿ~L¾Ïûpa6ìödg*@ÈŽÁÁtð!φ§[FQKe$[ø;ãPêLƯˆ'³ßc–­kÒíê*§Û!iŠ%Ê7]6Ñ!Jy3GêvÒM'6u{~è3½NHÎ©ËÆsÅ<Å‹ë(‹©lXÚQу“/EÔ*xÖiÅà~˜± W=)1 © œÉ3’zRé²o1†¢[ÖKðàRèÀ ˆ–qÏӞό! ‹wà°ëE6^Û˜þ‘EæÓx8Ú7Ü RM¯á´– …îè0;íÉŠM®0KÞU;$Ë–m]B•ü±( xPFBa‰Cáa1?úa¾w#Mž´ug'(¾æb „Jwé¦TÒîK$ë:0¯ÁŒÞ NïËð/ÿR'nÏÍ š`DÖ°ës0ýÍ úðº—*’õXjSð¡õ<£Ïè¸W5'éq›Ö~SõlLÞ²“(hùV«!ËÚ.]t*Kz· Ñvïæ9·¤xvÇPhïÞ@‰ù)uÒŠylt’ò‚º{ƒ} ë~~õ SD)ˆ 1¡«£îaû‰+,65ª¦i²¨«º±h“ãùP*COzÚ‘]éO6Ä1Æ\Ò8ÍÍ¡µJÛ1Þ–}Òz6“?ö•¤ÝîògݵÖŠ7{=dh¨ãïþnÅ¿} õ·fÎ~vÅjÀœ‘â<Ò‚tÌ«ªZãh^Ƹ—4‚ŒP¸GBv»|^Õ俯3Ëœ‰nÌôªq?»”Ê›uNã:®#³¦ÍT*ë¼£ó~ñÖF+Î+V"àÇ`ð*«“dî«yÕ}¾ÈG™n56 >t†œ“d%™™àMŸ²×k~•<)†DOKºîMA÷Q•îµÜ퀘5ÂvÅ2õçPpÅà`£Àû”ïžÃ¶¨®h«CˆaXè¼/]>Ws2ìS©ë1Q‘Z+“'P†FÂýYŸÃYÝ¿˜È ˆ^4¦'ßx˜‡}®§9§lîß$À¤üæÝ„ÚsŠ€_ÆE¯—æ6ëß—ð\dø8°Qྥ©Öˆ‘Í$o €d5T}((…¹›|(‹AY$xÎÜ´f›h Â’›vÃ&SLZÒ mÇs ]ݬwÀd!Áçë,ÊŽ¹›Œ¥ˆ¹ÍZ'Ížu[MUÉ,»”~%ì¶}&$Úý€Èn_ì ‰ûÓÁ£Èá&SVÍEݨºïât7³¤ Ø ­zÁíLiÞø úò_ˆ gz‘FÙTïM­è3ëºÎ²ÂÔ8ß!Ãj…‡Š‡} ô£ÑL†<0ºŸ 8 ®ç‹Ž6>=k2mºY“$5¹Gx£ Ý¢RÙLÊDK÷Œ–€‰¡ÿðäL Í̦3=P\&h"S:[I@-[ é ýݳA{ÕöxÀôa0°%[jõ¢5„ˆ1wÊå’*½ÂD`º-mV}@GÙ¨”9ïàÆlÐçãñœ;AÇvè #›a™Ôxß«t×>íT•Êù ÙoJö©adÝ®$*ñ†Ø‚Äb½¨É-1eت,+ºê‹}QhŒ9Bª–ý¾ãöÑ€¹L\ß}s$fµ [kªpèIg3’Z·±Ó<ŠÆˆÒž6{È owºJØ•™qÜ'„ó¼æa¤C`ÞÔ%I´ŠT·w1´CÔÊàH¹»À¦Ì¥ël½óâ¼àkð+{!²,¿ŽkÝiº“µ¬çÓò@”²nÇö¼Ù}ôÚ¾·£ éÌÁTˆEÍÚ굘×qm˜ Fë… ,RfìÒñ1rwÞýªË÷€a½1zÈjuÑçðŠ6’Ê»Re}¡c.3ðhæëôÅï‡)ñýöQýCO:y‰¬­Kù0ŽuzÒ½Ïä ô”t_B1”›•Pp‚îP±,‘êÇ|*(!ÎÇZj ,€úzc~”yÈû5ª?ôHLAÐnÑ„šªî6×Dêõf¶Že9.ôßœÀ¾ÑÒ=·giÌ£'Æ)'S´›‘Ê  7'¤œUAùQ>oQ¥gzN³ªÃ¥UòË%ü†oŠÁÁ·ôï¸bè÷1¾™/3(¾e¬ºÌª”!AvæªèÓs?õbÄ UÜU;Èý ¡÷¨aOÇ6]Šhî™úàñBè¢Ètÿж¶%žY‰: ‡I¯5]ës»–»8Ð’t ùwßgàî½}1?(¿ìé(þ~Ç\«;æZMÔñ\+Òé~¬Ø,LÂÖ?ö§Á’1Dƒ›€|6®gD›$kNQ|ª³(3?=€ý¤HW±|&IÏ×iãƒ|pLD“ìõVS¡úi–¦3UY_Ø]S¼Ø÷_]Åžâ*†ÑxÓˆC/=ägÙ6T:ª3¥¦?®G¥Ögq%fºt—Ê?f©öC²åÝ\fÍ’l›žDXì÷ëy×”èÉî‡xƒ¤ì6Ò1üƒ1þm¢è¿”åÕ: gq @¾Ò‚‹‘ɉµß¦¿Ì¬Œ28 Œ†`EõßD¿—öÖÖÕ“Y“3Ê3ï®ÿ¶Vu®JÈíL`px.€Øusªò¸Ëè–bî Äèºð©°¼Ýî®}&0ÎEF÷L»’>2¨Îèñ)5ï Оª!U²^`Á§Ê£¼èvX¢„Á[uN_Zlr^!KÕqS&C¡UD“¹/ Öb#S `AhâÃUCîë›ÉŠŒO) véD;¯®UL]Úì}½ë%ýózáÕÝY›¹-œU;X˜Óë&–Àý3ª}h•**Ã}ûxJZß.}lÇ><¥®&–æËdnqGfvT:§m;dtP’)­- ZZèݽÀh ³´îUëž"÷f*^*øaçÝB$…pa_Mi—¶ªQfMÅšÛI÷<;×kòG,H„ˆ´ÎÛ貘g¥FªÓæm›Y±ŠÖs •H¡ fM·shpùØïI‹Æ ÿa†Âtñµ™g:ˆjݪz›LrAi´ã;cÖàsîá´ÉOø#Á¾vx>È_MŠHÃZQî›%³*:óèãÁc…)§ †ú·k&ÞóÜV ,߀!*É5¯sÚåù^&ù¤¡YÒuè7ûwXcÞÞéw¬}½ÐÞæŽG=-Ù5³9¶mV´ƒÊcT² ÚŠšÇÝÌ6ÜKô…joc°<|­«–‰aBPÌM›Rv¶Vj)šd“IÒ9ÜKìãC[]f-N_/!kašUv˜Cˆ1/-5VÝ”Ó57î¹Ùww€¹Ñt1æ5ƒ NPeÎÊ™UMÉôˆY^Kÿ&úrÔe©ö²M¦˜"¤¬J¹d|;&Ö·³½tŠ^.Éc6/áÈÐ&Ô¸Ž‹Î’QDZÊöB ¨iIÈă+`ßn·ô\ë[ýú~õ-Ø•ÓöNC ¨ÓÔek¼T£üvÌ„]‡ÒhÛ?É îý»ÈåmÇ0`¥ŽÆÈÛÅ:M[ºÅו"ÏdÖ»»Ðކ%ÀÍPTh;ìa:Á¼˜¤¬éV!ÞÀV\BZÑh’¦ˆi³gE÷ÇUí7>Û¬¬«aÚ¬UÇà–¡‡ZE§ëZ ºõYõÇÇôÂóMÒkÔFÄ@|ÁèQ™UtÅÖ”[Qê·”•÷fIÏŸ¶·K‚^=ô·ñ–È+FY2Œo@_´HÕžªRÅ]§³9ÿß Zo¶À.¤Ù_“±=uÑó¼‰òI! D =sª º,¢,Šú??äíôú¥làû…5ñuâ V €u‰&@]š¶J¯3~YýñAoþ_'Pv øa@zNwFÕ`|@ÿzULûTµÐÊÛ÷¶2O dÏ ö28ž*×§æ Tž0q0‚º“¶:!ÍŒž‰pgö‘š‹nKâÑ3´.ðµ@öÁ{Á=¸ÿò¯öƒ_ü sÙ€°6@@¤ jWã>fY•ç{Ô~ÒÇø ýÞÎŒè*#–Øë0ˆ¡)FÒÉš6k×g]­Žõç~‡:‚{˜Óz¢ç×7W÷*ÉjžˆVX úÙ€êîÅ”d»ª†$’K݇¬2¯ÌôÅ(ãºvØ·êÆç“[”J,¾>ô¢L]̓j²~îâ(êÄÇcŸy0«¨wŽNxx5ÁAækt¢¸áØÒ)¯…µTÌgçެž²¾1Å( À¿Þoáíf²ÀàC ôõüÆ,€ƒO%6ÂLõDð¡NÁÆtît2.fA áT›Àlóf¢¸óΦY³‚Û²†Ø‚ÀIpm I€«µ´ƒaŠxÎίáv â]å%%eX½&)C+=kèôvk_ìkD•t=™xæ!ýZ*Nh€†öù­·Ãð–í·ŒmBòÒOã2¬ô"a£5¨z(‡x,zý˜l³øÔÒú¡õèbxžsúÔ^ºZ*]äZj)ñB[ƒ‹Í÷%î¨ŠŠ—..´´´,X ÞOų=±C•;^4kPò¹1.Ìdï&EÔ]•ŽÇšLKèóNKêK›ˆù™/TÏ´ës M[ut§‹i§¹ŠéF-’=¯¨¶èË}ŒX-‚¶á|¸¥†¶Iäü~2Ä©±ÓÏîÛ©g§7´Êúe—}ÛÆ.~€XÈãØ@ jpb$ß'þ%bSAª¦šuû’îE¯ÖrSÉÉz¤ÎáQ SáGeÊ]£ ‰"š3ØÚ*s7ãj¼bF—¬êÒ´Y ø­ã©Þr9¥£v4ÖwN‰‡÷ç¼6ý³H†sš¸%Ï®bÈä£Fª°c³$EMªõ©’/ïšÝùÛ)Fô,1‰Îç_M[n}S–K"maúðwÐÚýÐsONÀý=ÿcºã*~TJ%/ã³€ `„Rµç5ç-£6Þú©×r•„€üЮ¢˜a`OT JeÀÿGàåðH¤\©3Ú7Piú¸Jºµ?{¬k]ÛÅ£yö™'ýëb2Aíç¡5Ë``J¦9"P±Õ¨še×cÚôk)p7+„>zzŽe…·÷g—wùß´êëE[ e D†à;r?•XÓÚëq]¶mýûï׬ÿú¯bßÀ½Sô×gqá™uWiÖG…y-ð<ÇýE äõmS&í±Áó˧¨tÈÝ/ë ‚À¼ÌÛºm8ª]æ=î{ºk\hɶIÚ%“¶è`~Sxÿ@Gq]æÍš!(–ñêeÞL;n¦’•±Ü!*Ozñ˜8[î›o{mYéV6  ÿk4RUîë\õpž®w¹nÀõ}€ÃC¤ÑÀ‘ÿBLg1Xϵ0¦CØoBÌ•U$e“4ùáÜÕlÈ#žÆš"NgsÜGûl>Uà€¤†7æÏøzAll’Ym £'¼Eno b*»¤Nê%‰7*OdÉîWñ†ºÛÀð šFýexE%ÛÏ ï•"9¯@r(ÓŸ…Aö‡õ.E·žÒÿè®H±Ø‰ô?k$×é4pÎGU œ#hwÂÅʰ/O tƒóÁ`”ã Pâp‰•%x¦˜T·6•Ñ¿Â7‰º½PË6RªWÓ´®òMúp‡A‹³ƒÐf{˜¹ä å{›ÎûªŸ&öxºõ8auö‹¯§ÐÅâ2+ ¾AßX¼G÷}ÜãbTYÜg…ê åÚTrÒ]  7ôߎÅVšáži‰ž’`›HÕS•ä]^l‰˜”y”„Üpü Õ~7 h×p`NFþ×÷·±¤+k q¶ 'péâjÎÇùO †ïC³êx‹y²½jM#VùJOt˜u[³k-h;´£i3bA“ˆúö'žU1Y–¢˜0¹„k¹ª¥m©íc k, Þ!LîÂ²Ç Ü‘ó)u F–HVÕ|˜ÛÆ@pÅ2"Û—‚nðh¯wPûíÀ !ÕCuÌýj¾ôñ7¦Ž‰ &u=´ºŽ55-™Ži¹GSUüû5M0`Á P.|™ª`jŽ1HÜ&JBÛ=^•Ázq—õà BVç˜æ³+jgFÿø:2zv­íŒ’ì:T9[%4ûJŇä ð¢³Bf¦CWˈNð¼êMd-#dˆ!7÷²Y3`I¦:žë-É×Î|8¼CôØ,ïbh_AD^3¡§`¤6}€„všéÛ]Gµ$Û¶-’´Ðc3Æ lUóADbw3’Åi©Ø1ÏКV§kÑï]ËTIÆ…ÐŒ-îPÙêÖá…â£5ª~ŒcLà˜h‡ö,ª£€š·s÷fÕàn“ öSe2¼\µÿvr>ÖKõ19§õ¼;†§6ZSþ{r~60Yv|† ù º?HYÚ^Mð2\Ói–D¾ƒõëÀ4Ü ½7¤áZ·ÐMk†!IÕòö0nYÚ¸PÃRyšàäô³Y3´™jAœéT'»xq3Z¹8ØE#b™¯ÔyJ‘¡P…®ñZÍc¢/<éÂÓƒìMÆyA»*hN«HA™ñŽÖZõ¨Š±Ô4KsÊÆÏvX?Úqü <õC¥ççyÒž[¨ôtæ·3âu¢¢¢Ï†u£ºs3k¢;CñÊGWÁÿP‡ÂOȸ3WÀ6B^øB¯s2Öó–dc%g£Êóh+Ò;5$÷–éëõ/mCož{hÝhô%©p雌BÏžfeIº|îwÊ?ytò/ …/ÁIðµÛÐ3Ö†_[A)pÜË>VóžLygÖ>"ð«gíqûš¡p1yd(ÈY"‚EÒ‘¡P¬ÁeÙ˜Õ»c!îe!÷7s÷?fj°Gstz@ú&¡íwË€åûµ1É=2ÒŸ}ÇMØÃüVáY=§elª40¥ØòE8ëTø ®BrÞ¨«ÐÖÃÀ¨zzHˆ:Ó?ëºs²`ˆ*Á…fç=00(ëCcýç¡ÞæÈ¼~AŦÚaªf ‚:™ÚØÐ®¼ƒTI±ÖÀõ¨êý@3p˽@ë[ÑŠ¢=®3¥ŽYÝP‘³Ÿë¡x¡ *¥&±x+ó Úü° ^ á\ì#èÌÄŒ$ên-`xLÿýiIÇyn-R”31œìŠ†Â rHäã´/K>íÝNI Ê¦(Ÿþø˜·¾¬ç~Œn_] QÚŠ4k1ÃW4ðeÖUlnÊß-h…¿,x¸Ÿ4`¤pÚŒt…2ûdÝÛ:£Dÿ6/2 ¨åº0-< ×|ÿÜÌAª¹ªEÂMvO»ïíÑ- ”ˆÜ»®Å’±à©ÞO£ð¡Q?œHµ \Ò{nãJO³o•JÕ6G°2;#eÎÅ:Ü€žd©‹ÈóëõÔá4XÁ‡ ÆÀú±øïªrUÉ8çZn5x£Ã&vƒ[Èw~•šC ‘š;,oé§‹Ô\œGC³öõ± E‡XŽY¹u+=º¹ñÿêæŽ¿6s¥¶ñ]<þب‹ÏZÓy‹`°ô4t¶’EŽÆ±™¦‰›ÕÞµëH©©ž÷¡ÌôüçEƒK>°1ˆ¥  U?Ô¸ÕŒqªÄÙL÷šY/°ôcÈá¤Þ®xªmŒæ*PTEÐ ð"¨Ÿ*µ×]W {¿›M€àáj$ûî–sv… ûz äýSV¦ ÔsÜ‹Z—ÅdÅPôéT‹ëõaÌÀ]ÝûÑwNN€_Âh¡ 7è m¯m\÷•Úê¾Ô¥ùá¡ïØ,ÒâØÆd》 “ܼ¢¨½zEQÿ¸{º{ ùàH¤^8”µØïË÷2³Ñß_Lâ@Vöh㥅AE2M—o¦æºŒwÝ'£$çŠc0Ü)­2bkÎÕÏš-™xŒª¨¨Š O. *5VTe¹ÖkU•Ù™œé†táÿiô,ü«†Ð²_ȬOfký ¯¦…p{’[ÜE»tjúbLå²¢¤Y0 >ÅUPkÌ{LZ1R»Ž·ºÊŠÞßçäÄÚýV³-]Ûyû~Bz£³ó’dºª‚út•ûáumö†ÒiH&lyeV Ð^}Ó9ø*WÂ<÷Bê_[!ï‰l\îxˆaÕµr*?b¹ç7ç¾uMU2Ƈ­Èã°åS¦“©’·¤^ñûì5õctS+ÞB=˶°n꘦‰¦Tuߪ*—JܺlmÙòÁT&áÛ5šÒ Æî÷ö%{º‡©ea8 ÛÓ¶¯úõ·Þ_¿ X°ÃW•m2%cÞ *^è–‘?Š}£)ÿ°Á³:çóª©Ø *Ò×–í˜;éÙiÕÁ bju²&žŸj@LÆœÃÖ½LB™wU;¦rPÎU52!m-ûÒõ[¤:z5élJhŸê*iŒAÝå-Cò y8õiyy[N:ò y0šª@†pËr ³yÔ¶w5NÂÝgT;ór¥e=+GðÏ&ìÞ¥ÉKýÛpOñ¨vñàwþ†Â} ?¤}÷)Ö$÷”QkÚho »Y“5έÃ\ò\—^2e ÆN¸uâ$œOåSMêvWÑv®†U—°àŒWˆï׿ѡØ3eƒªŒs8’(…u]£–~ûôç8œ@Ž ÛJôÒØQË@™ã÷1QržƒgŸ ÛⲯÇkc~ÆÓpk`‹,–#)Si¤²¨™£%î àÐ!ƒyæ·à¢‚AúÆâaBNlpøùèc´*5`'Ö 'š>hðYõàÜhlnöaBMUÐ Yâ·Œ² ®Vë2 zþ{ÿ[¿ÖmÝö׋>~24[?«&è©mÛM×s=›¾B`qA´÷ÎCÜÌO²‡U°«ÐÏlE¥l™ãJ¸€âÂþûåÜK0…×õÓˆ8Á4œi ¬Ô;޹¢=ŸM]¯·IW‘‰Q¿YÑ»v3¡qmZ\)«qtMkÌ©Û$•Ïy—'cg0dá Ä9ë¨Y½cÈltCè"4i £ øÏi„VâÄiI¯‹¡é³xØëjIRÂL®<—çáÇÅ{’à«ûóô+;?w­Èêò‘ßUB¥p«}˜»­ËeIöùÁÞ7@jH?_%±¾Ø”êMAO¡®YCC,‰Ö<®)‹ˆÕªJó}B[~=PIðÃ/JʬVûälÔ5£rÏ<:RÍ™û©^›¦VæAl´xsMÓþ¼AM×À×ËX¦SU®—…«R§b­¢&jáÕ"mÊäm*,CÌÿð›óáÂü 9åe[ ÍÞ°HŠJU§¢¤Úû7ÓÇ­éÝíÀ4Çô»ná_—xô-ÄJžÔ³1÷0'Šë²O[­Ê•*›$•“a5´iÜðÔs¿9ŸñЛ,§P@аFM…éäç ¬ZÇ~Î#Õ®æ1´o`üCã*µôk#`ƒòDÀ÷´0&J MG%Ƕ—+lz±C¤J Û´½ànm´²/-SúÕ›1g§òp>a[øãe9•Ãͬ7Y¾ŠÑI£jCüìÞ?XÁÔ°LhX‰MݦɳL¯=mVݦ²  C4ˆÃû)"l}¶*¾~^Ò¢¡¨ÑA|q@·]:SÉžÖõÖ/ýkÓ¢¹[–u6Å‚üÁ[ÀèRÅšm:IT±¹(°è£Œ÷FEw²J“µªªXË’ ’Þà7áY¾AÉyW:TH2…4%n¶ö8á\#uõRvpò.-ÈóºT#€a¦¹Žuʇ@>eãé‘O©aÉ3¢,œ#Ÿ’ä1mô%«û¤kxQ› £ŒÀ??­ t Î×Ó4#é‹ÃÍ‹¯LñŒ2=GY£×tªL4ávcJ²só®árÄ‘9j®? ú€ž$;ä!z6h׬Ì —åï×ëõ÷ߘ]%&íýT©(ˆq«Ó%•™½TVP‘ôOs%ì>_ÛóÛˆ6à‚‘^ÀêðAVjmÖ­ŽWØìŒ²$˾PyëZ§¦“û©§ýwì Ó±ÛÍ+X} ú·ûíݱ»X!³ØŸ«ªª =nñì [ÊMÒb­•Y0 ÌëÜê=dzWE§ d;U"dëAˈÒ0Ïr`mèžx=UÛ‹>b²Q‚÷Ý2ŽD,ò¦yXT™'S\ï“9UTc¶³C1dLý§;ä[uª/áÐSdÒÕ7õÔdã:¦^0¼Ž¤”ô<%MňB,ioy4íj.Óv“#u÷è€`ÝφÐiØ#U"8ûlxÝ6Ç”›@GES’çmÒ™+ÔA‹…ʺóNª.•ó÷·ÈÏ÷Si¦sõLZ•EYÌ5-&xxlzÔ]›È¢ä|aÛ:ã‘)þ­Tõÿ(,H™Õ´þ*ïдÿo³§ê7fO î ZÎÍq­ë,^tÓkŠ´uÙ”OîZµåͼƒlÙöÛÜ›sMñ̇†BÙDõàÀ. *øèHÃàªhÑùk…ó:VÅÖê’ÒÖ¨Žê<²7… ¨XP– .8y Š[ÿ[ï‘ =W½Ç¹½G^ÐÃz.Á[ïñJŒ‚©ú(€³ *@A Ý{ÉqÏò¤ß&*<æ?®ù)¬ƒ(q€Œ€IhjQÇ⛊œŽÁ6/Z•~ÈûGýbÍ:>?)Del¦Œ±^ƱIFÕÃdTv&Ͼ)ñãÃo;TSÞ¯&#Þ&èt4,ar˜LЃ›jƒÅ¸sÊ¿QJx;œðC×óûñ<œÌë¶ài-ªÒŸ¡¢½wº”F¥c³$]è!\Ü)é4O‰~÷Å’LRAŒ€<\5lÄí™}Ÿ”.²¢öq(+mâŽcIª­`}°oÞÕ¹Bó˜YË¡ñˆO#ȼi‡®àìmEZF0¿]Òº}j2¸X O馄*;žò0´«ØO¦ÒTÊ‚áÍ÷n0;ºùE«l37åŒX„)WA&„/)ãmîJ›°4iMÏ¥7I…Õ½‡%ÑUêk{è§1€¤H!rÃ0Íe}•nRɸåZ—ºKW.¥awêP9à;€e8§ Ì¿®b‘.A]ŽPñcÆéX—c—E:Z«]€åwhezÝD€p™}~ÿÐè~b›£qžû¿¶©Çtßãhl´Žh¿ŠVÙøW•¡µkÄ–m_F°´z2s‚n¢¬fgyðÏ™ÞLEt 犱®Š´JgÃó¥"ÚÈFÕ‡"%ŒJ.ðtй߿N¯Š®êy`Àe½É]ešôý´Í“*åƒû>`Ô凶œ‘…x#Þojs6Ä´¥åÐ3Š#†ê *+‹mš¤%ðxˆÜ….Ê»!xÜ.^?Øæ¯Ÿ/~J€;QXQÔmF kò=ßòUiµLc2WŒƒžŒãÞ}x;Ý܃ß^u9m{“fèsOãÀšœ²-mÑÓéNš-™6ó6½.|òüÛí~E{Ÿà?‘$]5OŒQrI7z-VY¼‡hë·tõqÔef=ŒYoð*t“IÛý°+y=Y‚'UYtlV2RmÂì°zoëTe²ª19ê}|¡¬4âFDÑÞÅ:Ûu"Z®ż}øŸî4×P¶=¾7&€Â?½fé‚Ú©¹StêÕXMºJã„*G‡~:Öö¨«ãžú4ì[i,6éP¢w"¾•«p®z7J ·ýï¿wªþë¿Fºæ Eïw‰£vÞÔTEƒjsº³V6£ ?ÈÇDêR~pðbíàRÐo€l 2ã´°§Œ“ ¤ÿU¾é‰vÞ² ;kÀe*…yû "W/Œ7¸ÑAélÕ &T|QËr§¿k«d IëQ=`ÑŽ¢,þ´Lsÿ—IÈvV ÷`rÁbg¬½ØÆõ´•¥øl¶Èk†P›¤”+<ô½ëšàË=A]抨 c7¢"ŠÒ$‹Ó]o}¼ ïÐAëÐâ¬3| ?f¸6}´‹‡é$Ô‡G 0À±l¸B?õ¿[׺ Ä÷ƒ5¦QÏb¹2ÄZ®)Í¥Šî\ÙRù'×Û™8¿h%Êôð4á6Õ¤é÷ƒ÷&¸÷ €C¿¾¹Úü®Åò¬À†’î~1[<ë!Ïš³—\ô¥5o8'”õЏýGeLJeŒÙ¡”'µŒ•ƒÃ#þæ]‹­k­Z¢ž4_ë]e U1éROy,•Ño—´nŸÃp\Jß¿30Š÷Ó˜aÜ'ó*}Œ »b[î›txñkz‰37´fØI»o¹Ì+åbغ*g£h …YÇ4æPe}Æ'Öö¨ñˆy=g¤ÞÜ›Ò:Ó]ÑÌ¢UäÜãÂA̹¹ç8ð}űÒa –²å ]¥êòBÍ0÷£êX’JÎ3÷Sèþ!I†¾æÁ ‚dmÍbWÉÚXëµ›!à8¦¸×]@Z‹ð â}ðôN@~q”å%eÁˆb¤ÑwyéºOtB!C–¤±rÃ…åæÿu±ÞX kx’Ãúºf(+d¯è%6z¯Uut™ôè%ºtaPàö²Àô¯Ü]gà ‰²ø쥞§NŒ-KJ"T7ë,¥T×ļžr:––mô¹@繪m£ãõYáC>£îY(Hqà!ëF%Cڙř×ú71³‘üð“ý±ŒE2Sñ§ä[z4c·çm½l*ŽjÝgfo:ôŒÁÍĉ:oüÓE˜Bm€¦Bz8ûQPZ(QX¦r(Y0 0± 1 u¬w÷ðE'2ãœ1BBz¸&c2SR;ÆS_¬£’ —%èŠS‰$™IýFu!NbÊp½g–F™0Óš«8¦ÄžnÓXɺw ë¸ä0ѲÎÉhü? CÛÙØ‘é.?œ”ahïéµ­¯ýñ?¿þç¿ÿûñßÿó_ÿU T«1džú\Ge[EåºÃÙ¶6*½#HŒØ¾}”Qþ4Îö«?75289Ð……=‡l}İ=ß;Õ%ú©Òr,\×0΂d¡o¢”åȱ~=ŽØY 2‘ä¸Í³±*ǵžÖTÖCÝ K ˜ûgˆ²®µ‰þù9ÅР…Ör0áúvWM²dq”›–²;qÚjtzmǸC܂ۇ°øëû±I}[¢®G;b^±Rt~“v£tobÉ) … ’c÷x·ïö50kTÌßœ¢çàó¼ˆáÝ”¢çc»4K¿mù²uMc–´q^aHäÀïýþá-ýmºM¬‡J‡–ê:ÉFé=. å3]Ws­z©CoÞ±N¾¹å «3F°¸£=1Ú7q—¤nÖU,µ±$ðÓ¾Þ,3ƒbè¤EċŰe^ °D5-†² ­»ÀÆ8ÎÈ-Û2Ý»ó/¡"\üRÅ¢nøòç·¹ï岫Ro%å9eMú:¡8ôáýÐ<§ëÐ×Y¬ÎðX|·g^-ßÙÖkªñbµgêÏë}V¿„ÄÊ»(fj8Íq€Â®\v:=K<Íy¼™ûÔ§J£ !–÷öë;µOÀ ÿª Š1e°©§~즓Æ‚h¹š«¤_§d4`Z‡VÌõï\7ü4¡°÷uêQâ4Qˆj[ ý0ð(è­cª<¹éúÃù¹c†t?µáG ÐÏã 5%äl8ǵPhý×ýù(Ça‰S/ X¼½.¥øÀJœê@Θ²Fæh÷œê¨ZgEhº;DÅ _æv÷ÙÛÔ?„@î×1®X]Ô¢ÃëôÓì’^F"Ͻn?dÍ£%È?÷ê‚fÛëGü…ö@IÒ,Û2M­¤*_Ë´) @…ôn¸”ÌÂÿ?ÁnÛ·†4Àë)àB¾þ)U¡ý5ë¼nëãñ߯¿ÿûÿýÏÿüÏÿ¿ÿúc1¡Ö)J~éZѺ_ÕõÅX¤kmæagܨ`¡·åÛgø€¹`äðúùE™X´µ®ÊÄcU™5¾ 0ΰ]º¯Ó«?é¨Áš.?tÔfƒ9¦[Ú»Ó-cÁR÷ ÏÜÃkøÖOÓáÄ,Œ5óX÷:oTF©±ŠæNG½D¨y‹ƒÚÄ:PÀh¿'V_š°ݤãÂà”-#ßn‡•w;B¬4ŽToRº¦ïw0A²´ß*6—¨÷ýM‰:ß0«¢ "¸¤.™J[¨º”t˜µ¼C4!]˜üQl½;rÿ©gé6TÝhæK”SY8eô"ñ:Ï.Ì»–x°óØ©|®HÅ·€UAT©ævSí^H×ëùtñÃðÛÐa»„½üòÌ#‚*¥I¨w(SϺ1¥qe =‰†[ƒEÚ? nتøÍÈ”%†W0šî=Z䘲t=Ø-[×Aõ龘5±}nTáz®g'dà-$ö8T!!çÞ2œc&zã\ÍÛ1ù‡XÏSt죢¬Çª=g÷Šzª¬’½ª²x¥ªÔü|XÆ…TòÁfá|Z”°~ð·I áÑ SYA¸†‚ðÞµ•yR=Êüá ûŽPÿˆÔÕªuø…ÔåZ”%;6LkO½IœŸ÷>ziî’8Œ_´IÄ£¤ÞÕ”GÝ5”—5‚?r57´‹gÙÀùš»ÃºƹÁ…Ñšæ¤öJé¦Q3U§²¦ÀXnß}ƒÔÄÍöϿĻ“G”tg”<¢Ô6¡Š1És] à{ÈzЃ¿ácÜÿ ËûPÈ~¦2ºhÙ™‹/J]DÕÔh kµY¾†u÷¨?|‚Ðþ ß³íx-74P6aD5øŽ†FJqBí±8ú¹j<ßC/Ô=LíëÍ‹¯ÂîilÇBÙ|ÉÆðdc—Àr-Æ9íSºŠËÚ¼DÏ…•ûäCCìî|¸d3i„þ8c¹£H–Ö¸•–#:%…ʧ)/̹¡ÂÖ†1OÕÂSjür¸·Œ[¨ü‹bNÏ€WtÀk•îéØ+ú_·Év´o˜õb‚ ¶ÄB{­–¿Xµ^ú õ–Ù,â¸R-Õ¹ôW]›:ˆäø¦ üëê>ôõý-/3©KLmš“‹íEµôkN>Zé=DJÖ¼Û7r\@mÙç.¿Rþ¡ýé¸ ³·¯G¡‡2dbWi¯Sd“öø·dÓ¦ä†zÇ Ý‘Ýhªq\·|éF+Êd1¹ñaeèºïÞÃÑË +M6-…±†›XôuFöcŽ‹:¢hÛf=ô¿CÚ6wûPF°­kŒüøeì·+𺗹cÚô¸­©Üìås³Øëí‡ÖEiá‰4~À$ÃIÄžä¢Qq“x›èÆU™pÝæÞoôñ7÷¨ûïöíÚJ<µ§yQå”j7º{îRšÚ$Å”Q´mæy5ïÈU`ñL7<ëŒ+úëÁæUh†Õ¸z*i ´ªŒJÔÊt‰º­5¬ß/|ˆzQhx™p“–š¾:Þbb¨†y®Ê9QzW©Y5„:ÔåíSÒ'ü€4lúç‡ œÎ˜ekM¹PN­Ú¶~)ÿ¼¤ÿÑ üfC¾Ì î|G¬bÙ§zÚu—Vå$¼d÷ÙN€‚,ÀÛ .Æÿpüf|Ša×A± [kó.žVÚäºgüo ÍÛÂÃë‚Ú/Æõ¿÷…£²²€•Yâv`•íYfAÿ:’=Þ×÷ã¸aÛÅþ¢âèÒi¢¾¯ªyÜ¥³H)4Tya E±Ñt@¯ ÍåªÐ§K€ÏEž…™o@ÈNÓ¬$϶±7KÚ®ºwMKcü ˜„õ*aîßˆÒ +¤ 3ˆÒ }6 ìÂÐâ•`QŸ¢4‡†.oKŒcŸ²-[.ÃxhW2£4Rû°MqW阶\FøpV£+È~áþum|Âò-B¼‘¸ÃçÞUÇ}•¦µáæý~ÁàƒnÀc½o±ˆ¡4¨!xQ¦ÉsÕ%¥j“aÎjÈš0Ë KŸÜL4ïî/`­íçñ:$ú! U‰¦¨d¿M›g”cdMYÎæö¥Ûz¨þ±Ü­«ˆ—é¸8 VÙ0f•Iz£Îµêʽ ì¿:4.eÓ¾ ÷ˆ;ܦLU{Nwvv`ùz=/swÄåãu3¶ÃÒ/ë4ošJt½ÅVtuÖk9lÞW‰ê›9–8ïÚã8n¬7?õªäuªµ?±)w¬{nv–-å2]_õÆ € ‡Š4ÏcÁëCÃý\ðä¥7U…‚}?!SÒ ’Nu¶Ík¤sõ§-ÇýE]õqˆ2£e<ðúgZϵÃý^0ý3Óì²þãç€kÑLS|a*óS'œk©±yÄôužUÏm»ª¦×Ó £Yz^¿ÿåÎÑ ñ˜ÂP®ãmc âyN¹¡ÚØg “QÿñÛ°à†uÑ"xä?yN\Ó±OçFQb‹zûÓÂ7ç~%ЂåÃgÙD54¾Y‹‘7Ñšªm)ñ*ºù›Èµ®:öš [o˜BFÓ³Ú3ÃÖ’¸Êû„ò¦¤K 'ÿ·‹Ÿ¦1 Е­ršãfjiÿÄSJ{5Ç?~žû)÷‹Eo¹»!b äñ}ö}ß’lÕÞRpëMÎþÛ£sñ~0mƒ‡i´˜¶3­l¶AoÙ¶m¥ êÏ úŸ®P¦_B¹0kà±s6×Ï” ëlTP¬—5Ú ³ÛïÜ'§Œ “_؉U+ ï„.,+…AÙ€ªº)vüÛP™ïtÏarCé¾/øý"~woî½O »k¡ÆÏçqìç-¢â Š²Ê|lêÉ”ÐPÆyiÁEqÞ¯K¡KÁ·bÙ:Á«í*Fºq¹6‘ùÙ sS5…™™åœ ˜kÈ âϬŠBœC† C{G±R­iÔÑE¹f—³gfh9@F½7®¥Ê¿Í·Æe¯%ßÚÒÍä[`Û[6 G;á1mÿÄR²¡ p ”eÃȇ'˜P È!õ¨ú¾ŒçJeæUB~+„1ún§vô[ ¶è?+@`:p,jÉÛ»Ö©|œ¶(*ö\^%PY.a×p7<ûÊŽ‡d‹‘=„„Ã_X¯¥…„[­F*ùf*É3z™² }èzÁÍȬީªº|›ëðšü­¢xðK+óÊߥƬŸæ¬Wy¶ \ÓºêéðÀáÛX÷Âe¦kDà’£ÄZnšJ=–ôÿ, Þ=ßq<Ìqë^°_.¿Ï\úm8ˆU_ B…ޤÒ客uk%’Ïâû€j7"‡FáÅ|j:Ç¡Û_ G†‘q”Ñ]›Ž°aɳië%C~.v`Vw¨øïoé7U¬905‰'©J-ûÞïu¹o*Þ“?/¾¿ n´i3BÉ´ T–xI, DA•ª…²‹®ŸD\¦@à$AìnÛ'aìͲÁœÕ·²2ï¨ÁÔ6ˆêV€î7 Ý•c$"7``eüT”ÝÀÀûäNýèCž4Ë’³êíp§TŽF?Ý’&Î/åZ APAu×'׿¿YAa¼†sÈ \Š>q¡ªr%m_×G¥{Qo½Šü3õÖzûã‚ÖíbŸ&ÊêT‹3ú6H\°‰™xš¨Úr,—yÊÆ©Ø Y4¼`ÝÐ5Ä;üÿû]ÿ—®ã\ÓqQIE+‹=Ýwv´ñlÛ9,šýà*%üÜž_óÃÙG›±H-…Â~Xt¾·I'.õ7 [7˜ó½Ð}›ÛaÃ(¸ø=78é„ÁA’F×[£‡]“©&BÚP=ðúÞöî•và3~ÌMÑÜïGeÆq[ m*xêɼHº$ yóˆðÝG¿¦Þ*fОAYß´ÂEªÀÅ¢;XeºM›-„F6GÂû©&ìZ—{hÿ½~~Õþ£têÿËEü¯Ø…„æÝlvf€ZVèøo}þk‰ûó_vn•L­Î!f©¦p۹Ϋ>:³& b`ýSÑcænÖí kø†¹°<.Z1ù6q\ŠªÞ7­š½¿*ØP…‹¼‡6‘ujP}˜–~=Ï/* xjÞ²K1<¿¢(Rq Œt÷±,IÅ(Æða`y‡*‰û‰^}=Ì(:/Ú6K jcXC¥Êa¢0F©~=™A™gëlQ&@‹éÄí^¹l(H‰ò[€È 7þ ªÝÚ"ÒÉÚŒ2+£dÊ %§²‚Ûý ‰<æû"¿ ôŃ'ÇPÍhqÌ Ådr¼¦‹ªt¶é<ŸöAðwžå»Ò+úÑþ¡NéyW’ïí0Á”c`s÷A*ÆRÞ4ݸ Sg²áÀÜx˜ìù~á]úý8“£ÓŒbÒbn^$ ¥jª€M¼Ìz~ȳ[J[‚÷ðö_÷7Ñô›1""0\  ¾E»(MR›Œ[FG­{9ã`7ùІO¢œ£)Ìá7ü¥ ä°¨Åâú`E©èvcÄaɧõصÚÐûwn§_Æçú~˜[‰µ]'*¼…TÇ¥™r³¤eß9MƒnøQ†Þ¯þ8¯/ã6¶X[÷paŸÍ° #õsՕèú=5‹ÂZ r~>;ßWÔhŒÒe,©ìF“s‹÷Z´sF:%ÃVÈ’>x$.äîÎ å½ ‚ß_’¡ÀÓðw‘Ño¢”eŸ«ªž(.mÆÖúH>¼µ`.¼ÇÌ—«èñ¢Ÿ¾à¦l:¯sÖ \}›5C ’׿‹¡m³­Èh¦Z´>¤ÑXޝuZð†·9®õamã¨ÙóªSÚÜmè¥:ãCµ.¼íô]%g¾`ÏEidñ¹c«•ª»¹ÛK¼U‹YÓ‡¶yÁû´uÿWçRÚŒ"yÉMAsƒá?κÏt’ÌF‚•ִТ{“ÒƒðR½;Y˜cÂç9æþHAѬf.M„^š÷´aU v:,7’ʽA(ý½â+×oþÅÞLX–{ÍBsò˜u¬“aXWŠï úUfIJ£éÚNïØFŸØ²ï·¾d†ÊîôB@!šîó6•j¯›e”zÌXn2 ‡òàµîU)‚Íç…%ž)x#ƒPúh³0tTs6UCBGT–¼Jè£rô lïö‹«Äã[ÌÔò"kX¸ Ca9@ÛÖŽÍDÙÒ¤*5²&®]‡þ½ãì~»][¬€?Ë€´HamO$¾`I7ªÐñ¢úQ›­î¸à"Q)qsŠǾ]ÍYÁ<#”qà>Ïsk%ÌC1æ¸H¶Ê€&t¡3DGǹƒæ«öÊãAÇÓÈ Vx3Yzzt«LÔîT!°2Š8ða̤nïŠþÖ‚¾ÒѨd¹üZd¹Ç4—ûÐçSÝÏ’ ­wg¶ Vð~4r¡9©´héè î "ÃZíõJq‡qkÆx\¥€Â<œaé&[¦cÞ/ùË7ýðÍä/ ú—˹ÖóÊ{Q1š·Å æ-‡Û´wlÓš.½u³®ì›ÿÛØ[mWcoL°ÑƸñšÎ¹äåj£ üëq¶p¤AÛ½;Ø“Õ[]ŽÛ¨ÇÕ,H}gŽ/Ö‰$<'\ÄùzðÐ’œT†aG0+ø@“sÌbèG»ÞÇÎÄHT¥ÀvÒ5?$˜~¿àµIš…j´bãÀct´°"i5èm4$!¤T†Jç„÷ðLß• &ܤ-0³ïEÙÐV\‹‘ªº‰WºñÌSóy¾uȃþ_×qó|>3³ I0 ¸x™f®*VUds¼­u}.é„PcƒþM½¹W†þ†ê0»eÃOê[þ<å½U<ƒWLO*ëÑÅ®!Wáf Ù¾}ÅŽ‚ ÷m$°û ®ãõÈAœ]j¡ÍתMåSQIV–ððaÓkeáãù¢;ˆåáðW¢6ô >ìSšû@U˶€pœ&côçEƒsч¤È6Äü‚Zm#T)l~¤ ÕlÓÔdù:PÒôÇE­«k¤–Þt8‹àëôe©uU-Ó¶™_Nߘf†¹'ÆóL.)½¸v%¬¬ŠºJN_`è£*Z°WÙÞÉ%Û$¡Í ”wCìÍyGÙÃ,FµðY£ü¨ÏíülßÓºlŠ©3«‚‚/&„ßS8ÿ¼‹^/½mFø<¡–Þ&Š)qÎë6¨MY¤ûªOEÝÕó-¸$ZÀKûG9îïq®$™Þ –l€s7h9™¾|²ÇÅÔ£j¦½1—&íKÜ Pbð Ÿõq‚@¥—qq˺gNT'R3ËNuYÝok¹æjÙÍ’÷ÀA–íú¶žþ9醈z ¥™ú΢|§ˆ1¦L—ˆf³$Õøøò°_:"¹ÿQî>©ê{²mIÁyd[I øJ7Ê>'TCÏJA%äBhŒAÏÃ=<Î\ÿÍÎKýõÍJ&”½¡îi 1Ù³¨/Ò·"m¶NÑšÚ%1u9®8´bhËÓ=oê÷¯O†ÇƒÞR–‡rѲ캑N”ùí!’"h‡çœCü ×CF5 ,£˜Úá0c˨–¬Ç5[Ååš„á1lçÝCk"Ûÿ:Ô'î$þè :¦r¥i&4‹f†5ƒW¾3MÕÔ+H%s«Ìc7\ýi mÏfžwÅ~}ÙåœM2Pë7FƳŒ¦µžÒ¨­§QJ}h@³ßèJ¶ß­“+Ÿ–{ÕOáÓR¥Ã0`@”˜O«³±Y×T×ô”ýëèÀF“ÐsÅ4ÂsΆúvô¿ 4|dÈhvºð‡hŠÒ©ÆºgܤG@áq(U8ÆÙöi1K'˜Å,Ø„|€/5nâ~êÙ‘;‹|(’)K4=d.G(Äi¤"Òåá¡1ä¿ÛËP†þÚ p»–/ż¬Sݲ×{Tî]eBŽ¢ÚŒvè´Ø 1ø-ÚÏ×ãÔ3êt`)dQVêã"WY\ºR"…üÛ%Ň꭬ô%4 @,£°.ý¸ìš*É•¯–^DÈÚx(Ë-ÚBf\u#Ä˜Ú AhëŒì^‚ãÃHtëú6QÚÍ+ßî¸ÜÙNú:úý¼‹®‚8Àq¡ÂÚ½ðšþÍDßû:žÕ¼¦u?™%-ÚFCeŸuÃ\»œh2q\°? ‰¦úÀ­”¹¦z.ç¦O³$|¼è†À›y‘ôå?Zÿ€¨?»lW¡Ðgó(VkšœjÉ:›§IL2ØûÇ9‰êsÄïפƒpç›,,fÝIÊbžô²lô¾‹Ö¾ž³$|­èRçùÖy¸¯Ý`fëÁä›.àŠ‘DÊ‹y˜õ4$³®‹tʺDÖcÅRx4ÃæÜWÏ1Œx¾E^|þt©|u˜‹ºPEÄœØþÑ·v^Oy«´€©ÂP8ãjˆµÊ)¬›­Ýþ°&esÎ@ö¤ÿ-Ìî"/XïŸe8ÄøxîÕÒ&ë¾EÓ"@èß/yT§ÿÙéÙ‹ep™í%)]ë°h ¿—×kß·¿ûãÁꥊjÕÊŒ*ϪÕ'I+ê¿ÿÃŽkïoé>3ìÛKq»­tèuØô>Ïó²mû>R ¼R¦óDuc»ÄzJûÌ\„¿ýCÞI™,'Pðm(‹š‡Ý¬g:NJ-S«j¡º.Ÿ²þ/67{‰'Ð<¦{ŒöW/SP0íÆ¦5PÓåk]^üiP&e¿;Ò†òô”|ÍǘwœiïPÊÚ¶TeTÏ۟׼½ !˜\I•'†x) ÀY{Éã¾—ñ´íCZDóç¸ØÌ“†¬0oû‡ÿÒQ×ým€7ZPߌÇ((¿‡Àà4Ì˺m«Þéë¡õ;©*Ú¦nŠúªÇDWãq±§—®¸ñ§Î[æ°ÂH²j¬TÝ Æ€SQÔŠ ¥š¢q”ÊÄ·]X¸ƒ¾ÙF‰6ž{ Q&½qHLàbZ#Äv¸€„sXíÙR%QGP¢Ÿ{³(­IfðŠ½³ywm~3 ŒÕ/X!}]b) ³­jæ-Σ<ß÷F–ôèZƒQvø†ÀÄ⟗!)ÿäa-\ûáhڸꫩ–ɱ¦ Õˆe{§ïúý¯*(‚Iì~ж€Ê' OûmäzDPäCWâëû ±£OÝ ™§@^Ñéz­TIùªDÛ;hpÝá^à;ï<èí¥¤·Çë!.v ý6VÓPæò¨¹Øé²Éúy¢|—6°ƒ4èocŒrø{¡Mÿá¯ñA8)!Þ’h0wwÚÚ=M“T÷ý¾%…¬ ­y -ŸŠJ㓉Іý‡æFkRsÛ©´H–­rפB ÃZAHyld½0¸jSQn……ª™R PW)äLfüš/tVë8ÏÕÔ4)}v³(LìÏå6‘ì¤3­”Ì÷ùoœ[ö6Ó™ÚËÈhŠRuçÂuâÖ¡®àþê`.ÞàâÎDÅíÔñ0ï“jïÊh¥Fg¤â¨Èx¿Ë-ÂC.t?˜pç×—ÁÈ•y)X€‡ÕTsU©n~Îç\¤‚ÌcçŸ{hðªÝ]#Û‘Mc‚_CçWþé(Òmq1¯¥^ŠÜ<#$:!p4ÍáRtJd:.d0 Õ½4Jz#VÑF ð[×ôJé4¬Ðk˜ a‘ÛÛúĽŒ¹Û÷1æ‚,"ê¼Þ`»\u7Õã>«á\ÓÁh< »ÿîÞO¿½«˜;œâP‹Æ¢'ÂÒÆ@³N^®Òq‰f½jzòÈ,‚*Š›ïy½“!ôCÅv7OyÀ×ù˜alRÊXçxh¢¸Þã9“i‚ïŒ-q ìtrÖ‚7«šG›ô>t×bšÌFÇÚNÃ^îZïÉ6´)ò7é’øTÝB æV™%k÷"Òèì°ÕÛ‚!Àu× +‡«[³*Ú]D¾kß  úGxÐ3o¿ˆt\%á˜v;ùöUyîg{³$vlÆ¡%é-æ~§è½RõÔ¶‰xiúž£\P,ÇwÞ¬oŸÓ‡6¡ =ÿÆsö9¥³ŽJ¨|ÑTª˜5ØñÀÅ9?÷_pr̪% ¿p„„0L ¢§nAfü¤]pº›>@þTÐw£…µâpžlµns¦û|.†U–:ЦcèY†¥x§òùcIÚ>OqøI)ìTìLJ‘ x[¥â¹Ü(œ Ý#@ãƒ|j,^GâçH JÓ°÷ƒàz¢‹¬)u\Œkk¾ f< [ßãÛBùûU/áù¥¾Ž†P¢g#SaA,è‚*“¾Ëbº&Í›.…> Y¸Ôþ—aj,YÀ‹„ªŠá—A·«ÐI¯šb½éß/|ŠC½NŽkS–˜Ôè[ *ièp/U¿¬C•$ z#“zo@¿œN•ÎÛ0ž.‹/!5d ±w‡îÐR^¡—~]‹6žbû`¤å =Ù\ïvŽäàhá4l`(5”©§°¸,ë¸ÎóŠ”}H›4ÊÚNëtoê¼ë$Õ@„¼1ªØ¦¬èÌׯZðÏ'ºl,¸E1Ì=¸Zîjo!¾<Ñ)Ø¥èû.Бeì¡s¨¬‡Wú£Ö°‰“Û NêU;H+‚_éÚFý–¡ñÝÕôï²dD¬ãØ7×1ó\×¶?DÑ5湆~]ÍCl´ïd†B¶hz¦‚Ã6“¦™'oH\εP£Wãh¡NÇF£:Qɶ5u¡’±¯û83* úX”˜36Ë¿®yÛ‹.¸Ï^¡Jxìy³’J”¶ž«(éR%ð‚Æï(uFûVòýd 0!X» UÌ&Uîy4¨ºMkúRZÖ )ds¢·AS—Ú/ÖD T½(éà<¦¥S«­Ž‹…¾%1 ¥í«ZÖ¥ þ¸•‹Y“JÛºÁ v¾{^œ+¼o Èe U@B“ÓjAOBY,¶h/ÇtNç(7‹R8?÷gaRÖµcûÍv¼Fb¨â|+Yh]í˾×YWUsÝ&RJ†”UQB¬vx€œw *.GÓ%-+Ê2G€Ü¦þ €¢0ÎõF›U Ýá0 þ[Iå Qâ÷YÑ:¶[kE„5ëtª×)¶\ž”ð°ƒ-¼S²î_WV2ä ›¿àrªcèÅõ!Þv·­í¾š £qEšuV¼à‹œÖ>â]¾ýäת­Ø+èB~mÖ4×E?îÍ*)Z4à BƒÛ9}y¯·<ŒlPòbª[Óo§­šUCÔÕ@¿{^–e4M‰ú\€æÓþ9vßùëuç×ÏUÝ™ÒõÆ´hª¥ƒºó´AfšÐ/phÑŽ·¼à½æ™tÍoâó›sõÓ°t(ûüæó4g+]#qºN£pža`°µ¾AHôHmÑí)}Ÿƒ³Z¤ªÔ)ƒ3ÈÓä}FiD9Ƚ@‚ÞjxÝù~~úëVb,ÙJ ¬E™ˆb¶vR]­àë&²ÄC›î¦ðL»BÛ\ð›øö}ÑNb:îc ÚH× é‘J¶€È‹ú©ó¶ÇjN¶uM´Ì̃›{¨ ´O³½x¡òø‘a@Ë(à±ùÙ)^>=ÊÌKuy¼{sÜ2 fßûÀˆàÛ£Ý+Ru]_϶“@†#h‘ÕÈ]TY¢’žñ#’9 »@/Üì=ÐâmO‘ut8óxžaSYšEíO[>°›ÀÙáý¢ÄËtØsºF ¥¶ÌM¢ïT×e6M[Z§Ñ6­fAèà̳{f_ à*ÒO¤%sL¢;¶›3äN i§û¡§È|zzŸ7&ѽgp`lÊmø*4aƒÈt, KØN@Û ÃŒ ‡§K™ŠÖlïwµîñªÅÒAÎFç¸ÜÃÈ˽Lm€‹bö33Ñ(`Ö@bÓŽ¾€Î0æ)]£sQÆ…Ùú!rÔî‘„2Vâj‚FŸ'Ì÷i“6(=x’šosAß¾¨¦(ÚâNv*åL(µ- ï¿öþ‹Þíÿ’BŽ×&w`ù'ªV:ú²¦‡B,[?:^æ…¡òÃÌâ œ'Fø2`Zï*ÙÛœ¢]²U[/ zdlŸ¶Ô¹¿ùT!2»€p?hN±mÏ ´ÐilÊ%§¤,Qz›T—eJjÎ߯¼IÕ'„IäòË`iC3»&¡»jã& (Ew˜ýÜ|Ö(8<üy¡Ç÷—QÞF÷½d>£±Þ‚šw…æ{¢Šq’õ hâ2ÈÌ=ndËùÿ¸Çztuà!|€ï`èkZh¶ÿ×Eæö…4BEws(Èš~E7e2P£Šh]pZ/°áMx°‹N¥ëoÖÌed϶ºfç€ù®E5Ìiè=þy½ÏL‰Šv0@…ø(C±D«øsvº©u36imÞcˆTÖ÷˜œ4¼Käϲõ°™O¢ÿdxÃ×Dí¼ÛHµý$À{y¼ F-b&ïÓÍ^ÍY¢–Uõk´Jk“.]Jhßx´±½C·ð63½`µôÎÄ"ªí¸µ°oÈ:ÓA)ÌøeMê#|Io‡ãxè~šV|3$5Žâ², mÖÕíaò9‚b —õfMÊÝmz—`¹ï=~ éßúqÔëT¶–HµP¬60RâÖϺY%¾ŒU”0é0R‚l\}é‚û¿ÿ°z‘t+áþAa‡oÁísÀ„jýŦN2ÁvšD|ÄL0ÖqYc˜tvq¦ç?¯ê_ôêé›oODЧpÖDPðØ*Ÿ«bÈ÷¦Îú­šs áûâÂFhë¤iŸáhCù`¬kY ¯ÀT[Œ,uÝôßäã*É ÿ¬ém®ŽÛÇÐáù%xBCЍÙ»÷Zí-¥cÉ>ŽTÅlæIá¹QÒI‰ïÓ‘]È¢Ü}§÷¡û…Ô£Eƒa‚ ñ2¯{”ë’gÙ^ã2Ɇrý›ÇQÝ·Œð6Œ ¯A #àMZð%ZÑàãaúF™®{ ŠZ­t:ÖæI¡;eø;Ýs®Ž‹Â÷Yú>:æMÅ<ôË#iH?>¢¢èΗ6Z”ÁR!GëGì½ÿÒ1?H@9°Ã5Z”­ÀH+•¶ZÓ^¢¤K™KÉ ùŽ]#ïSèzÏÑfzp.S”eΡ®ÅÒ+›u\4TWõØ$$\tz,6ƶ7 Ý-¸¶U`&à‚7À ?¯Ò̺mÝפ”¢= ¯ƒâ-À(ð T]Ú*ìÇû…ˆqøñbžL‡‰‘©âÇ»[ÇC™«Íd†> /:á1ªµ.ÀН×ëK$\ñAéGÜ©&ž{ªaÖAéH–´Ù§’J,ÊÜ­·féØõWíM{Ví±TíU7fÇo‡±ë@OíàSÁõ!òu*7S Í óîPnV•®â-ª§vÏÚ?­Ç"ïüUØÖêÙÿ``82ðòµRí\õ¦pÒ$Q]üiMWÜ/"K°û(µîØI”øv”“,m÷¾Ï3é§üþƒ«”‰þ>’¢v¶p²æê—öy£–=nt^wºÎÛ?þhÈ'\‚Ëé•Õï@;¿¿Kˆ±<¬ ƒC>Î ÿr.¤õ‡@†¡XBK€Î÷×ú‰e¥¡^“ÍY¶Pm´ï²¨CÅn¢ïÛíW3â ú)~zNWZ¼è4ø˫}éÕª3­(û(†hWfaÀÅmHÉ÷È1^®M ÷߸;ðrþD#zT¨×€®· ýÓy«£$u€’CÀ*oj;tÛôÎâêÁéF.oÀJu˜î™$É}se–ãÀè@¢ß7&i§+3çz+¶¦Ô"†D7H ¶¬¶eÀ€ö;‚QD¼“»ðøî ¶B‘g%U2îy¼Ï]ßÄÃ\Éæä‰ž°O3ö¦$ìÓ‹V?‚}úv¬PÌbUo5ÝìŠNgUU)C*¦~t¿9‡­uåý[ªRÅ>W[=AV­4©ÙÑ íx÷D ?ò™nÐ-w½áž1æKœÆt±)*Raa'Fظ$}ª+Ø£âpÒô/¯÷åö8 •Rˆ¨‚nJÍsµGQ=G½ždIÊ]a…íCìëýŒG3`hh †žý‡ve£-A<0£3DsZT 74ö½wá÷æ+}ë¥R0jÌ*Œ éRJ£¢‰²Ê’tiÒ×±}J Ú~è\r¸—ÆšO “èÇTPƒ1¡U:t™ÃRJ“/´0£OOGû@Ç±ÓØ%ÁlŒëµï”%%W5EÛ¶ó~X­F†±…"ý–Íýäù¿Ì«Ÿœjñ¼}íZˆ²ƒ86ö˘ÏI¶4I-Ì *Öl»g¶tL7ønHjÌqÁ£ì÷–ªÞ’>ËTÓM,_Üvʃ(±¾‘¸Ñ~=øEX\kq‘åÅgk€ye]õÃ6ˆX^ˆ9ËÇÀðôéݯ]/͈K–*ɼ3JÂòïªn†}Èsºšd‘=úÌ– /¼À }ç#ž2PÏó½Eßä´¸É×xUµ¡ªÚ¶?¯wûë£uðÑQ£à'~·äí »†vËÊãâˆLÏùî¤ëÔHÇ¥ìJ8ä ²}Ú6üAzƤÞ9¯ ºïo åXRØ Õ|gö*ëô^¤j¢Cº'ûuæA}È®SôaîÁ‰ô>H­† "¤ÖpCQÅXkzѬ´Y/@ÿGžîÛ‡N uQÒ9ë!èϤƸ²§Ër†z¢’|¶6×THƒù<¡oÝC†óßÜðã²ÿ3åR‰¶ B[Œ‚`ðV.µ¯Þ@úñ0Cº‚:(QÓeN÷…¼L5Ñ4ƒk­šy(¢Ì,ìwƒ¸îÑD¸Æîs:šdÏÿIÁqjT§f#©AÅIºUC½'M.KÒ=fYÁ ðbsW:÷+Ø’~GmšQ™‚7ɳtŽâ5"™J÷¼Ü“\Ì1BÚÜ>E f›òÌ?‡éÿ^k2a­É1Òy* Ò– A.Á˜öàLÞ®¹ÿ7§Cx™txºªxÊÀRP=¥ù^dšòu¡FðŒ®¾°&5i°ãXŸ¶â?Ûa+Ý´Nò€jI’½GJWÓi€s‡rˆÍò&Þ¡enïÆÛ‹ö$mr4ò2œœÁ3 y»ÆñH zëq”TQ²À éHúÎ)eã}è<›é-—¬·c,zø’ÔsFIkÎÞ”ù±$2˜¡ûþAÛF üê$¯Lý½Î^ΡÈ,.m6ÍñTQ¥=º x¡a8€ÃÅŒc{ÞŒI_ŽŒ²••'}½jS•ŽºßöÈlX°Âù% Œ÷@FÑF´¯7Úãq¤¼lÕÍg²i”¢4ZCŒ¡–Q=âÌÎ O}ùkÃô]žíÏÎf¶Å4$[¾Íó¨ÒDçs•–c;+ÈJÑY M—šÅ´®b!ðwb3‚9±3ÕÅæH­{Kï1îõFS¸mÿaÕ l·¼Hǰ8ßø‹—¸ :À !ÌÈ#:Tñ¢q‘T…yNÊuJ.Þ[<íª[$ü»ÇÑpBÿÄ1˜”W¿€?ð¼ëÔô\hIúâð¡ÂÅ;=‘/ìwÎU¸-(?ÚÕÍö¬¦¥KêdŠ–¸ÞÍ#‚@÷ÙtÔ$ÖUç ¼ÄGTšbÂÙ4ÇŒsìö^Õ°Žèù‹÷ÇφjrŒ-íÆÀ—-ôážQ‘½ˆ ø:Õ7c©ÛV­²Ç®Š€Gç0 9’Ÿ×AùÏÊFN @ÁßcÄuœv¥c#’GGƳ ^øñ¸[Ÿõ÷Q; º= Dé‚’©*š*M)ŒY)9ÝcìïoÌ´É)ÀM œè‹es±¨fÙ²z£¢Y¤C¥,Õ4p¶3=P÷ŽöC!î˜D“ŽÑ‰#ýþ}QÓ fМǢmR%ygZ¾‘w*<¸ÿ„ž_ý–žOKB‡ÂÇÔí:³ýàjÂñÅꤸÃûš­;nURò ~Twu\Äc-°0Ï|*Ân”é[æ¾ SþI/?§$a‹(lq¾Â)­ d]Š|ÖºM³Ù¬ç…ªN .¼S²þ½¿¨Tü†Ü&®YÁ¦ƒTKÕžS„X»8JU“¬™ùÉÞ-¼±e¼øa²ä§ ¬(OãgkVxàèEI/½ÿ=÷ëü÷üÚô¶ÿ½¿^ðjÞKµiüq“®ÖhÈçz)© aÝK <:ÂC)Ýw®Cý½™â¤*ššµ¸ùz0ù¡Ä:϶¬\uYÆfA¨¾‚a¤ .Lýý³±ˆe K¨X \qè(G§¼m¨U¥cEïå¯gë]¡&-ÎÓÞq»m07RYFí¤é\%­6o×¥—"¼Q ì•¥@¯‘C2iÆìŠ\îH3âµÈ‡2-7Õ‘YÐ\*Út!'üÒlÒ<áÞUÅsÔ›~‚KwUtŠêÆU©lŒòBIœdá+ùdçM¿ö~I¨Ù¥Ù$WÀ…€ܘKn)ÒhΊm™ô X½S;½J îþ†ãàÁ|³WÌCÀzE_Áo mœ †œê&®`j6«xo¤n„i)½G°9Ý£]ë† xË,’Ýϳ×F°÷Œ7@ͥ͜m3˜ï>x·û5 v÷C~)%ØÕTñP‡ïÝšïÝtEÔMeÖts¶JÔ6Cߥ;§Þ‚øëÛñù-¶'Àß’À07À””À´iº69]IùºË #O…-¹¿> î]˜:›`¤;_bn‰LñîÎG{Ó\vºLVD7ˆ)$-ÃX¶þËýÐàöB'L•\@<Ά”uZë1ÅØì mD›èä$)>OÉ4,»ÑŽŠô”îÉL/ô¾)£²0·`cà*®žN hn™Þ. ¢=ãÏéà4t¶75ºƒ Ç–tqü§E¡Éf€³¡!þ>Y⸡[—çî¬É/Sœ©¹Öz¥¬ÝDŽß¬j½åÁWñ,x¼4[à"jPö_Íð÷†4в, QÔE\Ñ ¦ »Ž6M”¬ÚÞ£| Þ9<»¶ÆPZa?¦Zª-Q\©aœ;¥Úv¤û£J£½H¥5)d2™Rv ¬«”Â?F ”Ç+YA·òiGkûŸÒÑL(Q 4Lð-wÛòuÙ(_Е+JüI¨u©j¤%镚F0„z9Òì‡QQnKªºÑ‚iù‡ïû¾Lð¹¡êoêú|–-ÂØÜ­Ñý@ëX7ÿ3I6wÔ¼`ÏY)ˆ5tÔ3h)ÿyÁ‹˜Â²› ¬¥•Àw£0å³>ĪéëQõK¶¨lN÷ãÁ *ßuÀkS®Ç÷ë@™À:¦o[!’1ÞmsEwt²Ö‘YϹ05¿Ý10ßú~E™lèÏkΊ 4kyÄ%“RºŠ³YMÉžåû^ì«é:Ñ_ Æú}ã#{q®‰¶ù[|YQîÒ‡A FÀm¥¦Q¡a–ôGâJ¢Køî£ë@ ͪÄÁ'©È¯ê‡;%,ôŒ.=eÆ|0뽤*?íݤS«†p;Aæ~”åÁýÇËrätéGSÝ;¶‚¾/f=¦tv:.™®eMÇuhIMìÛÍs?»`X`Œ¸He¹.`=9ƒß—AMU¾-«¹yPÇ¿–ÏŽA–}²óÞqèµmÚó2è©õ= @öKÆÚj]ãzÚ—] 㱤 h=pÕÜ7|åBg~0jÚÀ2©Ô¡ºÎÈYÆdÒ™*¢mª£¼‹Ìo‡µ Ù©,8Mï:3'®"näT?Bz`š€ôëF¶-X÷TÅ”{Vt{LñjVõè¯[@wÝipi{×.‘˜ÝT,ý çàžÅb úÐω¢:kž§%Íû¤ú…~u¡œƒnYWÈåÃF(öØ@Žrz42/¦,Ú|Ûª"j›}g"!-‰V&_òvx8_X¾˜ðA ý°žáƒÉÞ¢TêlX&nÞ²Mˆ››ËýþëÄøW÷QѼ'Æ£Þ2ΰ$:·>0¾wË?/âÿØÞWÍf=÷FñN×ûýÈ9ÎÁ0ú_’ÀíüVÒ‚2°?JZ@‡œ8p é\½%-.“ø¯ocfÎ` íÙm¡i¸­ã<Ú÷1Ö?¯wW;fsHaǪâÞ\ÇZª…Wµ±ïï(;î«Ã ®Ö4-Ó<ìD·=ˆˆäa]±M½F“³ÕCÒÊ–²ˆB"xo°ç¥äF.›%çÇUcN!»®M3 e“PŠ+Û ÎÖ7ÙÀ (!û÷~ w(k¤æcùÓåRï €s–Õu®‹lûãz·«µ3?—F×@wrkDêŠ.J=u_EùŸÑ ßÀ'ú¾Å¯¯õô†&ðëšmšÓlÞÖu‰þüˆÁÕ¯oÛ^?߇Žv[±×KêhEQáÒ̓Üp¶º°§ãh›TÛ¹…Wí¡/õ¤Ê*ƒwL˽f~À}« Gš¸”GË‚s®mŠÁÞÑ®÷\$ß|<¾¾eÞU6u‹ûm˜à“4ò°¢NÊbPiÔi²P}%GØe+`}­›aÏ¢Ìø—wV @çÐV1‹ñá=w»ò¸êòrÝæªºê°fH/œbq}ž 4ûm\–î—¡þѽ‰ÔÌyõ¯†:ìØÍ1-Ëû¤KÃg‹]>ƒSËéôÂF®A¢¤d?'1¦¬vÊ^÷aÌ·ˆŠ":Cæ—cBNÉ Èç7÷ÄÆß?áO_ë¸4Ƕ†KsïÆ¬–%ésßa` 1ö£ÍçùW+§ +Q”Q»ÉÁv0­¸iBë^ ÌÏ7ùú†Ëü—ð¯i5zæÅTlÖWÕÖ”²Wå( ]g›…Õ Iw&íËfºÙŸâÇç5$5Ø"V”λ¹Aß©dí´9Œ¨W¼Rh½­H? ûž/a”%´ÑÇŒJôÊâe)ÌÏò%­Z³fè„kŽçCÛº4æ6N¬4Å}CI3:`ϧeãzœr•·Zå^2¸ÎXœè›z ÝlqLÅ57^ey[‰’°KW;@í;¬b™¶r¥–<Œòýtør6”½õŠ )Ù¨ÆlÛ%™¶¼ÂIªdÁ¦‚/ô{7ÎÞ½z}±!Èá5Æu=(Û¢!CꨊŸ)R´ETÕõ$_ŠvºC©¼ÂÝ;éEx³¤]bĨ8°â‡S5wë UDõÔoû±dpG›Â»í½}o®°Ù ¹Ü1…ïqÜÙ¥°Ù¦­*«Êf,M®~³m£µà¹÷÷ÉüØOÛÁÚ ÿ%±L³ÒO1gZuI:6]>G}ÕËQrý€¥nè x&µ¯²A‹ãNtÌÑ}´ŽÇ§³Zõ‘Nÿ¼àggSŸóÓ¢ }“,ΑÅ5º*QF¬çâ Zö‰îß! DT_É™€)ïy®-•7âêµ|6ßËšÉDÐ柬š½¡kÒ7|¥]„²²çÃì~»8©ÛŸýSð×Ãè÷6">E?^J”ÖiÊ`¦B¾ l¼0(§:ð<@·Oe#þð5ÉjxêáWÓî™DÙhÀü}hó,¥ Ü›hI¥ëXt4CÇ96¥ãüuá©|Þ“^eš£dal†/E“ë$£X9Ò¥?šðÁxdž̋}3˜†\_’v*&Jæ| µç«#ÊG5Ž{¶i5ʬI¼,:ŠÇL߯Ç?äS06”c3qc½úàs7©<ß:•'Ód–·1ðC&ò›|ðÑ;p˜”\ò7 ‡‹‘$Í’hôÁ¢u`ö5­IG`!ó@òvdºxF}s0ç‘ Àé5²Y. ûíQUÍ‘)|=ÔX·îAóº]6´Î%SÙè]X“3<Åú0•©J™„ƒª2I.t `ô“€û}h²Ó—iX3 >Ûé®i?%Û’®µºÒ àt³q·ÝN›,ë*n¹QÿrlñtÐ6ZÇk“­QF''Ù$ÆÜ3xÙ‚ô”ÙAŒV #ž§Âƨ#ˆ*ƒ£"Õº“›×gB ÒVdâ^ñ§_ß<<¦½ûÅvïiï ¦¨]ö¬5 zTŠ>¬õÔ…‡G ´±eûĸM°\/£&íDpÏÆ}ÜdûøÁeãw)Êàg+¨÷[¢†QZ½ôxpg¬Ížgº^ÓdR;ÛÁùÀvºh:Þ0í¶O•æ‹&Ø·aþ˜z‚¾ ™@Š?„ hcÖó66m”›Eѱ‚‚:–i¾:×Éâ?E6È0ü8˜2ì£ww>eì\R$0­¡¼ÔÅUðxJ‚UµC)ID§(dùpÿpÕóí_ù'¸ÞÀÉú¶;¬­*J:»‘ÒÖøß,xÿpæîýãÛXp—×ìtXÆ¢Uû¶Í]aúo”ø]}³ïþi¤ã:ã•2^A:öƒLÓx¼R¦Í8µË6QÎ>IqBGÄåÎðÁ8½¿•*×/X{¿Yº¸qR_ÓÎ];-Ó²ùVìU•LQ“Œó¯]SNQ/Ÿ= Á£òmß‚ÛÆùÙÿå\&2>˜ã:"Ã-³Šòõ¬ÈbUÃ,‚2X3„²äàŽãÊ´oWÑ­l½Æ_Êbp´oSvBͼçªÔüú> U%’ah¡5‚â)àÛ×Lq=Ï”uG²ž ÛZŠÅyЃ¿®gòK¦ (T(½‚•äÈÙà67ÐWMZé¦US/KB ޹»¾ã½£o¤ÈƒÞ/~ÐkF¬b ­F؇éUÍ‹jFÍbßXÓ¥ÄÅ\(˜#äÜþ².ÞïÛ®ìiPWÕ8LíÄ#{´û˜Äí¶Ïý:NYXs‹žð 7]ò°~?5g1Âڇߥp¼: ’}¯©zÖ¹J»m“Äè÷kúWvŽÞÞhóüzÞõ,ù »J³²*Ž«¨×Œîýpp½h7ˆL;¸dêÿ{ Œ»HK¶nfEmN÷¥QªŒöx§Ó¿öfIzô€t4øÀùT¦ÙDða.㺆ˆÊ€×‰™bF™:]  ë«|$˦…0£½³ðv|J¡C7ú蔓ãv6›ë¸›ê¥‹©@7K#M ×ÎÁï¨ö‘± Td߇‹‡H>PA®ë±ß÷l‰³v2…Ö¤g2¼™ÏlÑË`I°#Œ+ð:‘ʆéUñ¢Ódåj’> Z­íFãU½”T,«DuuÒnrý:´³)«¦KjAï–ýÙ†¡ëZVhdè7û'ã}:Œi±äc’¨jΫu\•y•ÐÌd®Ox ß`TçCÏÉ8Mä”43s8  ±^sEBÐ —ûš-C6ë~ªªf•ë’Ò Úâìéš$Á¾ÛWà,J sePi†äˆ{­òÛwQ\÷õ¶«=‘ä²Ê‰ F§{8kûÁ‡Y.}¤o£< âÍv@õuÖ‹Z*­ Az´2[4ÝçªçyñV‰Y6…ýûD³šh†}É‹¨+ç]ÎgÛ cFqî¤ÐúëJyÁ1 Æ s/|¡A:}2ùš$ÞÕ4šõ7¤„ˆƒk@[ å¶/í[:“Ò° 6ª˜Má -” Î %ŠjÛôÔ eք㘠,Øí0zr,ûC`ú›gh"H`ŠÆ–¹ì¨ò¥ *!3ôaôn–tà|I›èv;âŽ#hº“RòzJÊ~í¶<’}·»*Q² s»ƒcL—º}»ˆÚœ÷åͱçÓÚRI±Y/²t›¦”s5½ÁÄÓ‚®Ëêß>l¾òýí›>ôëeœ!ÐUõ!'Ê4ôž.é^A’ÅU&kúP¦´ÍÇFßßÇññÚ¶ç÷aYÖ,CÊæ}b¹­ÀŽw±žÚv•5‹þ¢kó~Ð(~.:ðTM 0žfT¢õ#F@›aiV× ÚzÍ’O­ùéa8”Ãfãp ÜDýÿšCgï9´¬éßèF‡,²ïÞŽÁYpÿ{ŠGf0±h*|ð^Tgêj߇:ïêrÜã!1É ®·Ý•>Û–œÁâƒð2*6YYÒr l,;½Ñ¢£=C‡—Aò´$-G¹Æb’§š÷Fñë'%ìÂ0¦]Ä„ú>ljL©Æ6LuÕI„^kýï¼~šm}Řg€i7OJÑ]Ç ¶Ìâ6-Š(ЦÝìLÊ×n@´;t(ûí³}e“³Ï6 ,_¶iÍ_œ¶Ç©ûãš¿8cý|²R]^° «€¬èˆïqÏ0*N;Ê eRnpÓ Q£8G#϶?‰¦ÿ°U$s °Ì^õ\º2ôù ÝçØ×ƒ}ßM5Q2u Þ–°ÍÒ½ÚÖ=ík“Ä”iÁrŽù^Ç[à¯çB/Pì£#]ú”(µÄy<å‘É‹B*”ÂÖÑ»¥´ðZó‰5ÃC}BÁwNì² ?TÃR©,Ûºq®$/ aözçpážÑì Eë’í‡áü¬yØ¢š'‚9Y Œ‰Ê}¤ÔUïQ\6ÓfÖõ}X¬{7ÜÞI„~³2÷%¥p€R‚iÛ Y§8Î µéFus”™’‚ª|ç`r{3Ìû §”¿½Žž0Ž &O"L7Æã¦(ËLcº87­ÞîSD)-À–?2M8 Éw×u싇TÜå I;·ì9-ë²"ÏNÚ)Öº¨ÇE×µV¢ÙƋӖrˆ‹]¦“÷O•ƃa•Fñ„”-A;ŠjwÛ¾2ìSšV|OHô yÂü®ˤP[–Çô.6É=`›E‰æ òÆÞ1ûºßÞèFÕGk”ÃÖœj3¹áÐfýVj«G¦}ùlyt¿#ã‚ËäÉrŽÉ¹~<Ð>y°Ž>üTiÓ‡ÌÝ\°ûਠ`ež"›«Å‰ëRqzCH¦Òò~I]eÀØÝ™ÑkUÒ$„4ùóã< ‘Jªù'MGÖ¼NÚK”#q'Û:.<ïB17ÌÁç“Í=À]ê}O_Ÿâæ>Âm~cUª~,dOQôAwâîúþ1e ÷7y}1„šÉ¸Û\§R,.¶xÖCž5s´¯,ÚE R¼ôC¨éû‡”õíæjňc˜ J‹Çfd™B&nï-½0áå‡[ ìP’HÅÆÝK Ü/F _Œ³•èš§sŒ.aÕ×)ÕÒjkU)K:”Å”Ü ë4=.ûƒŽøeÆSóéýQzŒ»ë¿Õr¯ ær¾ œ\Gï±d¾ÖX[«aÈë=®—²NŠI~ú®7º†}8™ŸN¥`–Ɖߌv…ÍXËÁµaiªšµ¥4lK‡ØD •[³õî®ûVö¼ªe¢Ìà5ó¼kúט³žoTU–ÉÚ¬t±ÒÝg$Ç£÷i¿9'÷Ç·H LB&4sQddî£J‡vÙbØQ›¬ƒJ—b¼ƒ¿_í^8–A›B½¸1¢]üÙwÕm›¦Ò?“œn%YÆ®8ÛóNxÈÇz;©«D LÂŒñ«Úó¸Ï§ šðàË~·äý¢3Åýá'ÓR¥?L¡œ+é7%œ‡9Û“2úó#›]Z\‚Ao+3]‘VLºÚµ 5ê‰éƒ¿_°ù£ÛŸ´?žq;õô©¤m ã(^З¡Ü’¢ºZS5ÐÅg^#­“ÄŒwþuµ{øï v%KvS0ç³iòI—k׎K£ú,–“ÃH€v;Z>íÎ>4By¸ðËÄ‚Ñü ª26ó»amK4fîï‰ÅýêÃü|à=öDZXi™ýCÕ̤Ú|¦[J+´æõÔ)Á¶‚£‘m]tG5ÈáßFþÓ/i¼ŠüÁ0îíTΉBÒÀë¹èoy€¤†Öéiý!ÂŽEO*®¤ø-M(Æ3¦‡ù1­…(}%ô1ú@áÝ7Q2üð »HJŒ|”€XoŒ­‹EHéÒØ›Ñ¼QF_X¢ƒÁpŽ®Ù5P'%Ï£ä¡3°2 ä)ɤ4SE%¨:Z’2v÷ˆà›}S˦Í-Ê;¨ØpÃûµëé*J ±iµª`Ñš”‡ÎcxHvÝ-ç£íD+å°¾Ž%Zî˜ü¡ ÙíûºÎu>fñ®ÍsBhÊÐÌqßøðK^¨É$÷Çé!êòåþx“oûUqUZÊjXƒ}N;Èñ%J/|w¥~EvÀg6•ËstJ©uŒæq©ÊR˜zXÒ¡â'@ w:¯{¿ù°3ÕTT4ÕîE¼éb] R¦m“u™9éåì)»Ýs’Ü.]©ß<›áבg§Î‘'¬¬è•áÝåïû/² úx•fjRW˜WI W'[ݦ#åROÒϽqÖÚ#ãr?¶øÖkÊj9I0ѽ™4jŽ·ŒnÕJÂErO”Ú¨^±OžÉ{âÉ#iβhg7æ†5Q›{©ÖŽŠáb*§a‘ö´š$ô ›y"Ž/óCJØo…=çD_g†®ë8PbXtô¤mVçqUG[—g].¿º‘´Ý©¶rCß=ç”À'¼ 5‚²HŠ‹fEvQqLYòšoÝñ¨T ¡î§Ë/÷=K}Ÿ¢oMI—‘æ¹ÀÌðŠ¸±U­ŽÔ¶k¶Ææ•úHÙÙæ‚§ub§/.9¯çvØØ˜Š6R;¶’$À•yÚ éqÞ¦i3KRun3¹êæÝß-èkåëí+V‰t$+-‹bæØÆS”Ž5Õ•bEJkúìòqGç̱NêŽýÑÕ~>Ž®6¾’ø1¹«­ÆrÛ£±«²¨‘’- ‡¢£î@îàž»ÞÛ*hšµ!~è°3 (.Ö»ªSÍRm@ Ñ«¦Ú_4 <øNáj©Ù×±~åþ<Ž^ù)­= ^þÖ³Ú¬@øSJ*„ýS®ä_$ׯàa U‹þ‹îö«=Ͷ¾*ŠbŒ†bXŽU8+Ã>ñx¥~ðוѠFˆdŠÅ z}ü•Õ4tÿnGɃ‰FPA»û,^`ÿÝò/P;s?&7|<1û$«½Éò8ÛK½”rˆ(¦;!dœÃðfÄ’Xá-´°éç—Qú§‡CÔdù fÞŸ÷QM¾ùO Ê›ÔFäÉÌiaWÑy¤d{šÇu§eYWf¨\êÜÓïCÿÓ¼Ÿ#WæID¥V•ת²T…™, —ðÕèh:YoœØ?U¸*Ž·I+QåÆTŃNêzWºÀÔE¾ÅÌ CõÍ$£\N³ikJk”›ÒS€.Fy.´ÖL¦ŒtÞº–ì/#ŽF¿šÕRÁk™QI%ûØÔjìöXÓfeIÊlÙ9Ó£ËþúÁÜÃ÷CcdÀÃðÕŒÕ_/ƒÜË `Ü‚…z@¨@Ú§z*ÓD%@ ÚItùCȆ…gy1ƒrõ‘Ç•Ta2©¿7KfI ¡…U®dK¢vépCfâ`m½¹â Ê:àÜBªã’.µ’1îÓØ óDÿé¨Òy§›q@‡wÖ“50Œn°ï牼ùþ_Ù0)ÙQ ã„ãÒ©:OÐ:̳hªéòÁñ ¾>ÚF ƒ’Ú cí¡Ÿì.†B F–r;Fª† ÕhóeÚ̾RÎuó<.… ŒâÓæ8HbäuQ3/U|Th¤}š®}•u³’6 4φ®xq׳ó~‘G@£ü™6„j0©‘{0¾e‚RMV*úbÛœ%ÉØWfUHòû!EÌ/¿Èî¢býyœN]]rrÄd=¼ÌõôXM‹ntk~zˆÉg“a×T/Œyp?Ä!žÉ“²ý©e¾PYàæ;×µRõDõRùïÖtÅÏ–Ù7âÁò*)ÕÍ44<[–e^xºœV5]mÑ4G{U¨•‹aÐE`ÂâÙ,ºŸÚW+õï×[y®p>î§7ý¶4z¯(ø4 Œ eM°x€(ýSãͳ¯Ì×c{<߆¾À뎃Ñ3(p¯{<—jZª1—%á¦nÛñðž}UxÃà6œÀÒ‚ŹwŠ—Š{nRt7Aõ¬I+iÃò:„á𠈊ûY\°îîPk¨R‚ RØNdU7ç[-Zw4)oY.y÷$±ž9„ Rƒ krIUÇY¤èßè¡í KÒäTe¸ôõ­S™ôÂ1æã“UcoÚ²(ÈÀ’̾Ya µ-øÛ¨ä¼Óigõ?Dcíœÿþ/=ðç/zà_Ÿzàôg˜ ÔË…ò´kŸ—ÒÇøA‹ýÛ!®^5eßqõª•ÚÛ¹NK·ëÂüüÐç²à†0iŸøÒÛ~¾žßâq‘Õ |€WÛhX{Å ²zªãªXÆÊdqTgøèVp7]} óß-ÔÇëÅÂaèÀs¹^ú0vì•2תœáp\.é(’Ó>H2ÖÒÿ0;l®+FF©>)!¥ßÕä2(² áP­½X HæJöØy…¾“ 3çs0xž ü ._±~æMfž>2Rë•þž¤í Å- ËCZ+§RòŨ œJ†Â&—®Èb° j¦Æ)AO…2¼Y>Žw_‚.cÊN'Ÿðƒõ) 5 )Q«¶¢:=tìr9¬Ãº®U=ÅB¯»{ŽËÛó(+ýÜ×<‚™#âqQFYÙ|äd½›C©:çtUÁüùnYZoËÏ8˜îA“îQŒ½®Ú46ëAMØlÛ>”ŒýàÚ4‚g€uc²ÔP–ÅÞÊÜ)ÕÝB±f¡*jª;ÓÞ¹ûlzöB¹™V¹· ÿŸ›:ˆã– ƒ¤#HÉÿÅÔÁº²Í¥¾g‰vèkÆf:…ô­5PUDQ,v>”–áR !:P ¾÷¡™û`ê’‘a5~N0y’Z,%UVÕ®R due–„Ü+›ÝÛ‡gœLŽnû0ä÷µàPŠK•i— ‘*Õ~)*¹}£>—ò ºÏÂ+4蘴|›ÖFýf(N”[–i¾P÷ƒ¢(—ä/¶ã²8lÙlçc=.ú6°¾–ÈÈú6Ã^¦s2E±j‹]Ö웟Ãډ蓙w `˜Ó…{<ï2ZÛ°9bLŸU¾M? ðéf,5ÐiŸZ4Ú›¥$5-:Æ=÷S;ø«¾XÖÙFèÖ% oõr}tŠ]2æe¢h–ÎÓ]”¢!÷oã:×zS4A(üÉSLÂ*\!ÓØöóÜ/ÃBuÚRL[§×1ç¬H¢"j7U7²6ôÆ©ºráógv@W™8°Ÿ,ZQÐ{E©Ê@K\#;½=]·-ƒ)¬Búñ¸¹nà~3ŽûiFø½‰k¸=°ª5†ÊC“çs™©u£ã>™öNÈSPᨠ8¸ØáÒÄ"Ô¡ AÀ–‰Q\íµšóV·]ñ#ëAùóÆ¢NT¦¾£?쯿M˜3P¸ÝÙïãÞŽ1Ïʲ+Ì‚ø©Eåf3õ¯¿â ’7<`«èª°ídpµ/ttºhã¾ìvá SÊïaÐr£ýR;Š7|3¤˜$Ž¥ÑÀv´c:´ëRÇó"Ù tn|ØŒ²Ï›wç/ÁœenYϘnr B<üdŽóX(ÚUu\ÔºÖìƒúÀt£ct0àìð)!úñ’Y”¡e%Rð‚†¸Ø·¡ÆlÆ-—%C+ôÀAç ý‰h9CÐK?žèÄ#¯KÊ(øòk¤ÓiÚŒôéÕ´Í}›%£[flæDúW ;ã¨MÛ¦5m°uZi›,ã¾ÆTжÅPg’¡kA@›uÈ6}rÍb˜»ô6Çdc˜Âpƒ~ߎ”R³í²$ýnÊ¥=Ç¥278Ñp† ¬E¹/nôt$1mO»§P‹šç Ç~®Ì3Òa &H[U„ûÁfÑÜtãW‰†ÉᬓœlºÌéN¢$ë³yÎzYÓ ÊóM=xu7û¯k³Qÿ< UÓx´È8½½jHúeo‹9›:)!` éÚ¨EoT¹çPúºþh([]¦^0”•¼@ª•aÙêY¡{6Š®yÑóëûM9¯0£è¾”f­ÚzϪ}l×5ËÌ«d(¥ÂË/x÷‚ß“IJ5û–²• `Ó§qxE9]—§M“w)_˜Á; à†t“¿»w%J£áø8˜½ <Ö­o…%NEsßm”ü÷MŸn 5}‹“-ÓÁiÏÿ¼Öðy?Çl­àAšõ<›kÑ™¢ýº™¬ Ô }(N›äˆÊËš În2/›¯SL3øZÓM¦»¢Yò(¯ÀÍ–5=›~,\ üÃâ Ò×lãT¶Åí[3›°e`!~z»mñVÌð›·p…xPt <ûö¶›yKÖ‰v½àÁ('Ÿ‰üjã<©Ë¨]ëeà!(ÎÒe°¤xK¢ö5šuTÌyÌêÔ-”‚á¾7ÎÎéT²lU9%3Õi”$›uéuZ@–;á'þ{€Úâ…Yœf¢~Ò_.°nænS*Âs 9Yƒ½;~<þkz¸Wdˆ©‡U:ºõª©Ž[t,÷=i)#.’msAvPnú.¨eØ÷·ÆÂd}§ç!£Y@ÈÐ¥“½í&Ñâ¬1:à²;žUO= xfŸÅEÑUãNJ9ûTO»îÒ*­´ÜìK˜òs¤¼ùìS Bÿ¦ÇeÉW„3*NÓ}£Fë(ë»d/e=LÊaëîS®eŸ(ô‹‘ÄC¿~^ߌé`Ív /BÛt"᜵y›Uùfr`º4,A˜hÆ~q§Qø`k×[»ß®ÊBDrÅm0›D Þ°¸ÄCÚ©ëgºßÖaW½,ZƒsQ-q;.º›—>¡ŸÅÂeùÝ@¥Ñ'<ìûÀk²_-Ž»ÃŒ_m·”{MuË¥KÙ¾A0+8™\ð«}GŽï7‡exÚŠ/I'¿2ŸŠ¥)⨚ú~7èS‚ ÙôÊs¤t*žj4Ÿ4ÌÍLžÒØÎýôi]'½ìû¶ë­Ø+U­I>M:.ç]M+ç=ùF KônŽã„DZÓ/v_ÀÂk„~¦Ÿ Æ¡§ž³™²í¡š)_ªE{í÷ :×ÛôñE™¬¸¦9Ÿý R~ᤷJõðZ7Ó8dUV™5‘ÐaJ`pN…®:áì²k¨ºµHº³°vm>e¢:JÁ2º¨Ìï¶èj¦„–‚^`—Ô ‘ãI7½Øg|ŽºE:k³nuw…‰ôÐI€ï$ߪBÿz7ÇAŠ|‰ä ¸ hÑ€ÉñŽ’xµkF»)+wúý²&2mªˆpâó͹$v<¦ ÐSñ¿ÀXÀT­:«›=köÒsºLeI—=:åÝ䢢øèQÁrõSSIÒÅŠ³ž]Èñ‰t´,”„íÓ–uJ=ï”zÒw‡{Ã9bºÇohÙÕ°o8AýÓ9Ž÷,k—ežò(3Ï÷‡õ.âP¦ýáV;´jñaĈaâ@¬UÑP†²6ñ FëùÓªÞ©§Ä9“6PØ(ã‹iº…t‚¨”š¢}mu®;E©÷ÛøoØ3p™/ÉE_Ïç!]É#¦#¶·t¥JÕµÐCºÒ¡ýÚ´ó=Ï>”Öûë/ q‚BFM _#%´Ífæ fÕfý¬ÖzTMœÆcbJX†Ù­ë@c÷œÎ^†Î&QÎÃ|hpmñªŠ1+¢Áäzðá s7ôNˆä¿þs9áE¶E*6]0§nf›²œð•ŸÀn¥Òádùßá]e¹ j]òÚX&¿÷*è,¨Ž„ÁïNû:óŒ†ïò3RZ‹Â¸;ŸqT…mÜÖr<f¸¸±úÄ霢y¢P̪ÑOÖ£+(lÌD7=Ó,©&Ìw•å;s=føTãÈØ”+²:Žë•¬ë½ÉКõ/Þ¬<&JÊtEy‘6+4{®æ½Þ›¬‹u5™"°ƒÀ½Ù€žZ&:#ïy÷»{¨éM_ìCÇñÓ?´© ³dϰ1ÿP{pÞ(93º|ž^Ëh^ ͈­AtÅ]E©Ú^gmt^•J`—‡?Þ=¸ªÒý3öQøï•…E‚Çú3ö)Ãþ®¸e{q­”f)]t ‚W/ö±ÈFµoi]¨|2å,-éøT‹P¢s4¥i§¾¯Pªâ¾Äb`Ø ´F¡MýWOs^µã&{ÎÀ,ÓCÞNÞÇg!,¹~¾Ä•“>7ûjw†æRíƒV*‰—,™Ì‡'ÈG०DwûÃðýuø¾AlT›q;¹cWÕæ/L¤c î2`Dý`tê w¥)ÒÇz "Ë¢KB‚Þ[Ið]pèïô¸à(JžÄñ¾çÚ!äÛ°å2¶2ðÇTsC½x&ºé—2Û])%–ëÛ(zazDÓԀᢡy€-»²J(Ø«,ŸPÌúM Ýö.?–¤Ÿ|sùï¶"½þuz ‡á4üîÎn2: -@ûîÜ9I8ïnŸ)úë_kþá£ä_Wi"¸˜5c”{£šÃÈ_9÷d-eÝ?F’~½°™Ä;©hÛ¤MštÞÚ>ŠD¶"C(5´!;c(\ÎüˆM#Äo—J5f¨`øï¦Äõt³ò&KtÁÔ»íÙ[rÝ¢IÕc©uÜS 4®x@ßTNSª] s&~½x1Ôz|)  ”¹UQLq¡’%Ût7ìIÛ›5™ •g¨kö‡šÖ‹GoO™¸æ „qÄù‡»Û©8×k½u³÷âÁå‚•@Ç›MñN;ÕË}ñB7f}¶(´®ìŽC©Š†R¬­©Seâ7-†ÐH ÿÂoùP9ü¿øQ&äŒYgÖôá¯áÝ‚À;̓½ðƒd§·Ÿ£ÿXU,bJ'§íEU¹ÍúñËÖ¬u.07 lõæADÏzºEÿ'2ÍZdš%q-ȇÁØë”i¾Bl·×±^IQlUl!^/É]×±Î*ÇzwÀ4|„GëLß–Û_?ÚÀؤ+„¿‡‡œêÈ:-¶sö‰ ³¨gߨî:jhŸ˜ôs¾þКnò–…Šxl?€Ö7#U¼í°lÑ&ªR¼ºã`l,yŠä_kTL×yØ@ü©f ЧêòqÝתŠãU¶cH8 {Ò$Š95áGÍ ~îÏw-b_ô«ÙUOd©§•"ìvÔ“¸þÃZ!0÷Û9T¿˜”¼ôÏKùÁ¸¤ì‚b4‹vŒâku9ly<Ïͪú„Ã6%Øj ¬7Çû—oÇËPû‹2”¢—/ÍWnMÿ‡¢i? ÊM £®³elbIQ©ÂÃ+…®}ˆ*Aßí2 ç-ôÅ©…ÀÒ¹qĩھïyc¼¥øSÚã-õ<ëq™—¥Ûçj4KÒíAE…õãç{uXѵÜx ³,”R»<õ`÷4TŸhµ·ÍVLs¯ÍÀJ° ×y»8<>ï¬r ìñ¼3ÜœèK-0C½4K7Gќײ$L-Ïçû¦G½éq/ –Å DÎÔ†àÀês·h šÙ)¥è‰kÙX6ìÖ¡¼âQej&¶nxÕ Ýž_ºŒÏÐíî;Ï×Aµ²iÓš~|e–tÁª‰14ÜMDõ’ÔólÅÀ帧˭a"·b€Ú.º¡Ö›^Ž%Y˜Ý÷àxÇWŸµÑïEÔãuîMàHÑïëõ%Û‡¶L(Ï1ãUT” Cé.p¯'ÇùÅìöŸÉøŒ†ªKkRyµuÜ·ŒÏÕ”÷)¢ÍœuQúÁlïAâz>ï]Ñ–ªÔ«îV!Tx6â#´l‘½Y×/†_§Á3„†lkJzìšt_ãêÈ,›ÿ¼¦å×òèÖÈÀ$ž1%Rªý3íkQNSß7»AR bÞ,¨zPªd”)ÅùÐ ßÓÏhüô¬ìÚ¦Ù±;}øÜRþf£š>K }ÇÓŽ¸ÁdnìFq€¤I[­U³•c2¤ç’60¯w cÈñ>6üK˜qH9‹^W0/­ÝNuTW¬y—v£îöeúã’'BVÚ;èîH/¶îË¡ÆÌº£Ý) ÍTúß”Å*WMô§E)”~44 À‘q) å@î½;´›Æ¤,“ Â8u©³dèÝl*+铇í¦‹è_Æ©l(*S„£çìRWD@mÑ2g™YyÈ Rü¾íÞ9YÔ §ÒßLVøæØ”•íÌÀ ã²ÎP÷¨‹*N·-ï«©×´)ŠN| €/cà#»wÕ»ô¹_€š±iŒW1&Âü{š†¸ÑªÕ±VœOph­ãëÛ¶™CDÞÌbñå%/=€»¹‰-â„Ò¦©©™)žVº‹ rڲŒSVš¦sJ!®þüŠNÈQ&øm­¨fxò¸*§)¥:¹ãE¶*û6Ô¡LË;‚“mÝ áØþØ[¯sû³[ψÎýŸÓþo·¬ŽU®*ÍŽ›Ô î q1ü{1E­„K%PL¦ìÐMšµ {žêðD_߶ѤD*~`R?Õr¾ß?ÛH|°lX½NRG KU:V{¬†dÓï’6¾µ s'ëÍÐzÁÿ}R¼ïí1)n?&ÅhÜø¸ý ®ùx|9—ÀâK+C®¢bc5Q´¦Ý5osRG[š¥UTŠüÐ^Pêÿ¬KGå†Êª+è„–,à[À½ –,¨+E÷}ыַ¼p®Y ÐÇ¥\xMŸëÏöÔÂÛÌ&„Ú«èÜB¦”3£šO…kÖkRBêЯu<nÕøõñß›v<v %U@²;!`$™âEeYV¥ÙQ»p›ÅíüÀ}rIü^m—•º…D u_(™µPA-·¨H÷*é ©é¹.Xñ4<Îć‚ì)‰‡A>L“èßN—]µ4u<,£Ð†]ÐfY†ž»æu’®N2!º9ÐÇpÔ¨ìôö W‰,ˆÎ¢PŒÂmr™Rþ{sÏ‚™³ÛÝÜ7ïÆ& 3º>]6s™¨,±Nó-9Q‹ÌÞx_ ]†rÒ{­"žÂ>–NLPöm]ºf××§ðÿ@o>,ïòÌúûLõßï7+º?ùd-»p11»ëø¬å4ŽªËy:Ql³±…öÙƒŠ©°ñÒ; ôûPœÀÓ"ªt'Óp/aÞ°¥C¸ê Ÿ6¾ËÓC–T: r7 ÂûgÕ–T&…øÔ÷K÷9ªU‘¶mžÇé¤_jà@wÎ`«½gMÿÄo0%}RÔÿ-¥JÕÀ”gÊ–¬ÚžÓN]¹R19β0ÄPÐ -×:ZFÁU<‰U 6,-ƒ™äszî±´ŒJ÷6¥”¢XJí,C‹ÒN¥‹ÿ់¢&·î=SŸ>¥gÚ–Âíš±cv÷L—8éª5šêRå™´$è^F×Äçh}0¿­óTB½­GähÝ\Ec~1Mª¦d>†)zäÙ&K$í\пõâXw†ú!†ûú?b¸’º©á.º]ȼt Y€á9rjøDÞtC?µôQKQwlCÝKo»PõQòÛÏe“²&¥¿À¾B˹Ñöfø¢pÁ yK‰¿sY ]ûtÌ:šy"sOHß\0Ã{ê[TF)úÈ  ±Š9FÏ­kž6ª È.®°•%}zÛà7r¨‘çŸ<´8š|xhiAÌß®iœcï×¶ë| iÃËðÚƒG ý'ã"8Ð> ‡s‰~=T,V+¨_ò^ÑNm˜¯I!‹p@¦AÝrõo-oé"¿GŸ¬F:Æ\eÎï Y£rÖ‚.i j ŠŒ¶£mdù˜wmÑ·ôI˜ø]Âé‹·$¨\“C5MÞQ=2é%¹f¦¨i‡s‰aÞZ;È9{‘õ¬˜ÏÔՌ‰›‰²Ó)ªR½¤ÃìƒÂ‡ön´ÿÃèöß¶ ô3Ú(’ TÜ’¾Š/[Ñ/ìy=K ¸Á¤3ΖÞ•áQX´{§&Q{ò tJÀÁ®öÏÖÛ‡dÊŧˆ:P–ƒº®;lešuQɦŠ8¾ðø>`*ÛÊmlïÈKL÷>ø~½¹¸G!ŽñZ-Pz›(Äé*^ê|«(5ÙEÖá÷K~T t½½µ8LÅ$"è6sM·ôqSà ³ U«Ø1޾ÌînTÖËÔ¸Cð1WÿižÎrk¨e—@aNÙ…CÙmôšeºÄ&Btÿ˜ök)vÛ4îþàHÂu¡@+6%ËÈö|#OÃhWk¯7à‘à9ܦ“~UBoæjãàFä1˜Q çà6ËÙ9¸BéA,ÁÁÔ»I ™ÁÇÿY¥›°#žë‰;mÌr¢~ÊÖu²MHï°4€Q)œOM³±OÁAý²3«Gg`­Ñj5œ&Åx Œ£’ª-Jyã6ÉCý ¯;`]^-_só”aI‚§óJ¿±‹Øw›‰k3½Í,Mãº\ÚVO~!ph1ÂóqnÌ'¨;Àe£ÁPµª+q<ʧu==¡³©ö(ÑëAÅ ªf ';ݼ¡_O]#Ĕƶ‚ÊìĬDAá+\!¥ †AxÊžEW„óJß;úÖáßM1.ý¬„AÏ…œˆf—…šÛŒ¢èßN!r€+-;ÛIû˜Ð7! †ªÉ¢¢ÏÐk/?PüÈÂ’Ò£mÒæ/ CýéáSsLÓëC0 ò\ºÔ²gg# hN·†< t_cqü3$@„Ë@‰™Êbél]qBè‰6PÝÖ#ƒ\Ùæ©­òNmegE<éÇ´¨ÒtÑp¤2é°Ðµ>Â0¥[ŠCF­Ðuk5ÄŠŠŒRÍe´—m1Ʋ ÝgT½>`Ktè¿ZÎ_×`¢í™J {–“; «²SËua™Íã´é§¤2DОOËó†_¥àD?³+*>4œ ʵÛj,#°–Ö]˜zís&vÒ×c0kÿªfòóþT3©´˜?«™TP3iû][w)M©Û#`0ÆÕZûû$ós’ôÊ‚ íNþ ’™(…§ry«ÒUšŠ˹lé :ƒw‚¯¯iÂQ¹½œÑ}Ñ4p–é¹M_îY—"éH«.éó¥àö2šÁ˜÷àèj…¦»÷øöõÒºl%… éÕ¢KŒÉäÚQÍ¥šuXéôïË—<'½üÙ¹ÉÀcî°¤@\³ª*Ýçð6(äÅaÏqµô_ë/„¦õÊ·k„zžÌÄgÂGø7øLÊààºn €žÊvp—œ¡Ãþüþ¹Pa%7Ö;þõy¸R.·ƒ+ÑgtaÊ’ ÑMI_Ê;¸öMƒd}á½…:Ž[£Þ#[ê­Ú¦a\ª´ìË¢ßYÓ{‘ 50žON¶ùlœ¹¯’J#¼lš¹ëzúq×i^¦•çÈ*ßÖ±ÜÛ‰jœþy,ô¢ªb õ{ð>Óø2 6* ò å&WY€Ñ¬ lÝmóVΟ״þúCþáL•7… ‰þO]À°éÄ èn:¹w?)mÛ£»7Û^òríÙwMÀcÒ¶z æ?Žn éÜ$©ÄFùyYÊ<éâeÃ^þ^ížey5!•¯ra ¡µPe tçéRØ7~5ìÕJzðËëDî‚¢=~·ÚÇ$«út9ÔÃáÁ 9à+OƒMëföýFçÿ%yHІ'`ÜAXÜÓ¥Sµ,îQc µ*ªÚÁì9Qw`òó…‹ŽË6VCű?Ê6ÚºŠ>÷: {‹–çC’RÖJ:eîZ]ßoz•ï§öÉ Ôâ^B—fž¯#|β$ÚÛBfè”zÝÄn@§T§!Pa9Ó%vaG¾ô#RF”kÒ p÷áàQTÛ®bÕVq³éò͵†x©æÉó¿©ý "R´usá±ÑUßs[ «6e™MSYVKNÙ¢|uƒPɤ†ÃWÖ·n²bN~iùDÊ¡AÑ2§¦@ñULU,O O :ôˆQî‘ÇÛÆ‡”ò?^Iùy%å¥NhéÔ ¶4L°ø>Z‡¼A3üÖ´RhTº.+J—â½è¢yZŠTÚ´LŸ½\k\Ë?æ§ö§/Ù¿–|ÓÕ?äȺä-<­}I¾Ùÿ^Ì4a1Ó%\3¥Ÿ“%M,n¦òûöM òȸrKð” »Å7 kâ¸ßU–©0ϲQ†'DíQ²béC‡ÒÿÅ"€%-`šË/çÑ.wÚéQÔ•IRõº„F&ÄÔXh+8©{—#¨ _?êîI€™Ê–¦£ƒCîbM§¡ÝúZó`àÔ3È›¦w¡oöªŒŒcÝÀþá]W‰\ïÜ×T´¦ùž ,WÆÉ§O'bä0Ã8§q¿€BŸ˜È Y½Þ¦Òá­*cU M—CÔµR½Ðz6ÔoégS ÷8±fÆÅg êÿ­ù yST A‰Q £ª‡xж¶Z×sIPS¦˜zgÀü¸Î¨$úšM{Òl&¡Ù aÊä‘ÜCSøÄR†ÑôÑqýïPa½¾g†°^‹j5¬…5«z/JÕvY8†ë[(`Ob4ëÐ+vŒ»å/jõoÎe¸[Þ4ðm¹¼äfy¾F³Âˆ¯Ò úP/òѦÐ#WûÞÙ”æÌiâˆA;-8`%<Jí†Níùºj){h"@#Ó±q2Ìžÿ×ǺµBYëÓ¨•žö=QJaåg^ÐI„x o(㓉ñS×ð/ªSq¦Õm±­Ã¬¥@XòŒ ßôOÆ€é™pEðQE!>GeÇàÂF+d¶{ßä_/Û| Ò§{ÇðûÁŸvNå«_úbçyf½Q2XHÿˆð² T¬”iš²þó¦×óüàA5µóx\†¿¨è]¾ĕ¬ÕÓLmÝ–YÊx ëx˜¶hiëb »TÖFÓB™çÅàþÿÌ êeTè›6¬Ü^r}Ã;yA7zÕó…ƒNß(!5{^›ŒÐ…F›(QûšG­´ä ëZ°v­ÓÄó> „6&¤J•ÁܪšK¢,ywS•*®:%K¢Z¥üeÑó¥ÃŸŸ·V:¤û§‚j¯U¥1éè…ݼçÛ¨?;9ïH ¿ùÙüx~ë¾6åMÉ ‡¾ÓÂ=+ÛK=OY¶ÕËÀÕ k$ Xó”î½a¾Ö/Í-Ã^’§h±ƒ„ÎlÂrØŠB>8¬\ú8°:MͿРߧmEÝH&ž´‚M.“(-·z¬÷xÍEÛ€Ö¤ü 08Ȇ-þ9â«÷)Ø%ܼ„ºÆè òǸxCú?DZ¬'µ¤Bh§ôÀ†eë”@ïñák.ÚO•(U3~üÈKX¯K>Ñk¬ûcAϵP9î¡~ã˜ö©ÿÂÖc ‘ hRè!\ûêª^5[Tuùça¢?³„ÑPOódüûRÀYÙ T«æò-J9¨F¥„E¾æË·SJÍžM›$î´°‡˜L{Ó9³8 ¨ýkœñz£¶~j¾Lu.\Cbè——{Úõ>e!¾„y` ,¦C(58“sùênìxŒANS—¹Àj˜ê:ë÷­]ö$ßû:ÊôzàÈS6ü€¬ÃãòÕýøùtÔߘZbÂ^4@µ3†úLøùÃT`p7¤ELw¦h¾±ìÕyðÐMªçA4©Þ"~”7,rWAåNféÎ*wñÜ»FØùÔy<|€ò-­)Í2w7ðÆ* |z¥ “‘›ºE„•^鼫Yme:åyªÊ´ü‡UOùÄ…O°j/a‘$U7.M3¬K¿­û4Mó¶í;NA¬º:]3ª¶†fŽÖ1éRÑÿýŸrä@Ž÷bU9ˆþe €ïzé0Õ›:57ñ’o!¥>ÿðäÖ +Íè+X¯Š5S„Ñ·NaU•¡šg½$šŠ6Ë~z×~¸ü<Ð]ûQã Ж7D/²! Œ1˜ŽŒTÌæ¥„+€u¡_î Ž=¤Î]Á¢ÆOÆZ¢‚x5£ 6w*ö>Þ›- ×c'8T¾ÚtíiÒ¿?”êžL+¦¯UÒ¢P¯Åz•8WEJq¬Iæ×¿]óqóÍû¬ÁA º‹3n#AÌu©N¨×2´%-)R¯TS6®³pó güF¦“ „S¦s™NÚ³é,™Nßå2ƦJÉ ŽÁÄãìíܰ\ßÛÏתù‡%„©¡`fø¢NÛº¬Þn¦}«eÝë¤ÇЗ>œ^ x¨ OÖ?¥@ÏÖ­È9½X.Ô¼H¡‰ÚÔgiºõåV©RYû§©p¾‘ÿ-CV禮gH%fÁËz¾ù¡Å³b ýÉèR$3P{r×2é•«®J£xà.0t Fû¨˜®@x'“ü¬Úl¬ÿºdµKöJE¸mT6¬!ÕQU(m0iÐ=mPÞcü1ÛüOо3\ÇÇ/¸Û@e<Ðm97k2G² ýÏ º]°U8Ùnw©×’õGªá.QÙÒ©^>GaŽ®¥„Ê].™ôóÀûÈéÒ§/-€Ìÿ1¡‡zÆfŽã=¬ÔRíÛ¶äzMx,ûPùô¬‹9u1x!ó©;ÊQNåÂþÀÙxÏh%:DÃ>mž‘þÝíûôÛlã$¢½Ÿêço “D[öG—%ßVU÷EIô:§ƒþ6 9YiÔ!”ý0?lßßÛSRÒD“{tS[Ýï]£¥N—0¥"'–î­éX”<çªÛ†ñÁà=LwxÜQÂìSžvP žr=íÐë†C)A#8Ù]¤)ÆCHeQ`ªj-’]N ´õªVû¦tOC#ªéÎ÷ýàÐ1÷î#.ªf°jÅ! —(æ,Ô–S ·XæC™—Jÿh”ïÈoM@©O3õkmßϳÞÎ*èP´ð±Eè~nÊ}/›- 7õ¥ýhЊˆv')á`Ÿ²8 Ü#xøÊ˜–ŸEМ8%ké<ÖÕš5µ £°NóX¯ëÂÕcw)ç<·ttýúLeVî[ñ°Tȼ‹jh?vûÔ,TÔËz°9¤ßŽ &O¾:±dAoóYàËŒ”2‹Õ*ƒ,舧ý²- ËÈ@æ÷‹ÝPTp¿:MßkvWî…ˆB¿¼Võyý1íÕš§zIÌ ØVÀÐàóCž@žR€4Bº=u=ýîp¢¤¿Jôíû›õ,3øp«Z__G§ѼâÎÜ÷l)š&êºZõE¬e@…‚IA#0,_w«8Yü˜“®¬¹|ÌIy¤‰O®ç¤‘æ,-våö¥¨ ò40)90–ý ïÿ{"ÃÕiõš–Ðy<ö :{"Ö¿š½¶2{-™½´Ì¡,ÂZî9ÔùÔ'xŸ”PN¬††§ã\Ï-YÔ.Ó¾Û’ˆÄtEtއVð¨—ù3}r:@h®Á«à Ö2 Õ19å·{ÔdY¸ôK²v²ªk ¬Ù–¯ó*.&Žx??ãZ³ý&ú€‡7T?µù uèrké¿ÖKz ÏíêfÜg&'ŸOÆ y57¦™-ÑDTÑ kE›^­­¬b‚”§dû 7úµ1¿çù”Fr y¥ŠU¥(|Œó¶súìCÎÓ0·u!Z˜§ÇŽ¡Æa>ÀÅ­ç°žX%05·ZVp9«¨ éq1‘„01I…òáÊxça•*$óõ}pí)ï„B.Xñ°šd^/1Õ!ÛÚ ¡*³E¦{Øu©&,Âèê €~3ÎSuïhHº‰á3ßD‰ð‘pŽƒ^ü Ü[;8ð6¦÷ÙÑ`Œ¢t4JÀ«(œôÒÓ@GcP åÎ …–v8â@4PuPuû8å ܻ̿ÂÖIƨ¡fÌJ Ú #›*("¨a´û.´ ›Ñe ñ?'HO|~ʘ¾æ@z²ü4Õ˜Îc«â&_»-Qú}Z¦ïÚÌãCð1ìûPÛeŸ,¥pß³iE;0Ù:§tIõsVFã¸$³}øYù@ÀY¾}(9?¼Û9eôÁS+WdìçÛWœ!W*g¶±©¬Ò\ýyÍàcÀ÷Þ~ô0»Æl“gR >fpÙ•I«Ö:ORýËmC¹6”wuzãÞiÜÆB‚W„ïñÁèúxSë6©¦F[ LD½žg =äºðÖÀLëä¶6í+r¨8óV_Û°_ò%êÒ$)Æ?/ißn^Úß 7K¢³:Ÿ(ÜPE³û.Ÿº‰JYÒ³@@ ‹}¨¨œ$6­^õ#Ä µ°ØeBd Fiœ6ªÎ£i+GžÌð°åä|ç\ã®æ ÇHRM,.¾7;:eŲC¯sŒÓAÛ3¬d2Ó‡†yp¦È8èp:9Ò¹ƒáãžv%t¡‚†æ$k W;%­Þ¿ù/Ñk|½´žòíšÇØìy€¢2šG•fТ¡Ì¶ÔKBÉ h”ë é}:a#鋸¤“ Ðç^¸ˆÃ¨íè–¯5'u#K"Iò.¬äÍög}ê´ý÷Yî¸ó,W?% -X©ƒtuÎr?æ2ÿEA/“Ñ]Iú]Âüg¨åclçêNeð-0\v>oÐIÀˆ›é;-W¨tÌ£¶™=C ƒM•ÛÆçŸyy€ß*,º×tEfE†þŸ0 ±Ñ›,ššz¤”¦ @¯ÏºÔ€l ¥~Èú:ÉØ¯¯ç·( аïD3þ*É{*‡šu¤ˆ)ÙgЬ åD´ÿíë¾ÑA^"—ùbk§š!U/‚ýìí4VUÚ£Ô¢¶°VØ>@->•Úï …·(´a²68ïæE»qIÇDÅK·Ç^Óƒ†ü œŸéßö å ûpõ>\h·Ùî±a߇w7ëñ¸¨;ÚòîÕ8ÌqVQ¹Ìq¿ˆá0- W"´ÖÑ¢<…H/Âîk;€qžA~µ¦$¹cýtÀ³©Ô4äQ”­Q«¿–û€Û´êÝ<Ùµþ±­&æ~½P,€²Î½$Ðà±·ðµÔ\,uñ²$ݘ m=pÙ±Þ t¬ ±tL~}½ÞzB•Ve#5È $󴤄1ViRö‰Æ?Òš´¡`gŒÖEpzÓœ*J0{ÚDá˜Íž ’M÷ú8u"®³§i©‡*Ü”êÊtjâcaþÝôÀ§å]œÚìi8µTxÕ¶dÙ—Ši1t¬º¢j§^åM:-j”åZ>v<&¶VªpŒ}u1D“1Q?„µ]):£U5Žô¹WÕt¹Šû9_)gØõ+u1Y \œý¯uwfz®âÛ®ªt7|¬Î†jž×k1ïÝ2kÂLÁG‚¯Vh¨Þý€CˆÒ¦d/ðwZAÛP±<‡t×õÕ¦Å$È{ùTÍR%k›þÉæ°/*Ë[–ë% ½À¼“·SVÍ[5Ò×/×"Ý46ªx”ÖYŸñù/ùí;ÖMòH\£ÎV³>G67Ë>·íÔ­¡ŒhA8BŠ”ui˜æãp¹úÿ¡¢ùf¶þ“]~¸L޳ž.£v˜(3|/óÞû¶A ,ßË}W´¥FÊNÆ"O[UìE1Ô£ˆ1C÷”w<(`*]ö zÕnÏtÁ@q¡nj‘d¢ üõ´ZۭЯÃuеd—¿ãu87··UJQw¦@Ûµ³%JR”ª):Æm˜½1Yz~Žo£zÖ ÀÙ£ eÄ*J +D+ôÝLß0]GÕoášÒ-êÑ÷÷|4Xuq Ç¿ŽßVѳok]± ÌÀü#ñmͦ²O§DMJ ¶bg• &É3áÓó꿹DV‡K¤80¾m< ¬@'Ö;4î ëSík}Š¡9Õ6u È.ÁÈ#Š'ª›Ê´‹Q:±ð¡üò <Í ¦}õ«oå ‹ý>«Õ~1>ä~‡n‹ôï÷éÍ>(£‚`QpéýÞDÄ( 0Š„÷¦€ ZFRU×IF;t‰éÓo”W–Ü«GÓö%ÔÃuÞ~ü¿¡ê«I†it°0£ò]@¶ƒ‹¾y'›"`}I\ÍÊ®+ñ‘(bM:ZSI; õMå˜+%°²¯l#JSlàMͨàÞq ß§-a‹êž{ý!VCiåD‡ªˆJ^*UŸVmB®w—û-µÝöõ’Ô*‡b{:ôl„’d]«ÔVuôïÔ¶Êe $t<ÀòÏÜ÷^/}soƒ^j’×PDmZ£YPN+–̪)¥}Ew„,êÛ>…U“‚}!=¡¼u\Wþ’Î#K›WõáÔ$Òæé¦½*Ë]}e²þ/wô‚ÓãvèWÐ1G¢›ö¬ôz¶k¦Œ%[ªåÃ%_«–é.´ %èp%·|°å.y•Sxžg¨0Ày©Dvg$V+¤Ã€Ç¢yÿÀÄeߨHúÁs ‘kÿ>L‚YóSDâ¨Â•ݶO›ZÕ«švд¯}2ž˜C'€7dŒ y¿§~¶Š¢¤Äxz-ºýX·ûÞªv +@ÑVÝg%@ @:0¡80œÞÅ„‡½ås•½I,Œªª†ó3ìÍaÏTÑfa[ïÅ^ËÞ‡_€ªpÁÃ7Î6>ªv©bž"g÷+&–K"5­”™Öi?4}Òö›,Pâ5 X4]CùŸîiï7¥J°brd׊;°Å´5—&‘(’OdRò±Z—!s'ïá#;1‚¤ËÛRpž×+ÔçãqžFEoA¯i˜‘1‘¨Ûç%íÞÞ&p9Oá=°XÕLJµÕMžÌY´®eXé·ib@EŸP½iºßêÇ÷7·q1¦Ês¸ÁôõÀÙ©¢¥ ü,]Új*'y&3ˆØŒñ˜Ø6 Ác4J(ô¡ÂXR¥Óž\ó¼,ËN¥”4ìyÕµ{7W3U(ÓŸ÷®É1œéëo”ù`G±ö ð^y>¯(ÎU—å*ŽÁ @—<„0ìï½ø9´ëKFNˆ·!—|{¿7ªŠÖDC°òÅP›N„¯ôõc2 áЯ_áÐ3=›¾¿}Ø©ûÁ­$ýÞÞRêsއ¹HÃòÀÂn¤:4+Š8NSÊýË$—(J'Ò‘KßÎvëí·CNT­~ƒ™è’ãå3ˆ3y>Uk’·›^’žññ`aÓníã½¾¿Þ_›æzÿß¡'£¬7sûðÁ F¬6‹:¬›†‘ŽúĆZ}Ýå”#wKœÓI’ Õתï4jgDËýë°c£èqZƒ€,q¡­5i4íýª8hCè¿<0:·ú =ðU¦&Îp+úþu–q‡å„Ùê8é5MÀYL¨%ZÓ' I¾6Ëc° ß™&¦Ù‚Ó¢–¸É†µSUI<²]ƒ¥7Q‚N ®qa;ØMçɰi­ÙŠ·åÀR÷uE5GÔ†qQ–Ýê}éÙì-ÖMî9¦¼p§¯õµ}½¾Åݘ[øo2Ú(ŸŠ~m’„vTÝMÝ& :°Ä ÂÐ ð¸g÷cFó߬ÅËkq`mÒxA•#Ýõ>ÝZ^Û딑hêÇÜ'_›¢N†),ÒuêòZÖt\ÏèÛTÆÙW {¾ÌÔ ,|Ž1VUWêˆIùåGÕ.å:¤ËžOzM ·ê.z_‚~c¾Þ_²À:Ҫѥ»¨Ö}R§e[Ô Ñ,ú…ByÍd]û°{òüËòÂÊÈ%„öȈ_>B⋽ ³®ÚòqH–¢YªHV Þ±&ëÙ]ôí3÷Ü .ÎÐ# +Xü5Ì ôâЮëªÊ:¦ì{ÌdM Ñ!UMÙbptÆÏ•6B¯‘!\F~_ëëyvF©s% ÈBº%bU¬Ó†þl&zIÍ>º}_“ìÓ®U{??éûà}†Q˜c×Z –0…T™Óëœ•Š¶2‹›!ž+Ég|ÀO(¿¦§‚àT]úû®$ *#žP2¹šE/´v#9:JT²¯Ó2”S«WõSQH66ëî÷DÞÑ¡nH·þ_7ªˆëh®|¬õ®÷¡éØL§›ïà ¿÷\µbf”-Xœâeˆ µJÆ8Û–­JÖY®6´PÑ4¦ÐÒcnG¦ ÇQ‡² xÖæ,ÓPžf!y9d‹ª‹)ª(×õzƒàmÿ\ïïûHú[&³8ê?äØ1 ,¥:dqÞôHä"µ¯•܇ 0gزkJ’yòi+Áv’ •èF‡Ifœ!ßèK³tªO÷¢˜ë±Êöã=ÒµkBÔ‚ZÛ9D½³ó7Ô©¯Jç”a—MSkìôÚ5êø4úw¥J?ž* û°³°½àÃHêçõ%Ý®S+g`­œáË™çb9£œ¡À†Œ2ª?JcSé>=}Â)„kªŒÕèYἤ õxªò°£Û7Ï÷A¯‰™´…­ižR懚џë´òV§•k²²Ï¦7”vø§èŸyWgÕ"N¼dÅKX‘  ×ùžDÑ6ŒK½Œy©— Œà‚L]NÁtû.5õ›vô9À`m¥ÇfóËô|ò¹ ¡ÕË›ÈxÐõ#2ÚaÙöÇÛ|3î)΀PMé[vbà^Gå_Ò¨š­©’Brô|€æa^kzš¬ý„´»&kS„dQRªúÃ"f^’U­S6sT—ë±® &8‹7öÿ÷‰/kè\ÖØHm{8ÆEÕX%t’ªµ`ü8x¡LtJ¹õµ‚ǧ«N¦Ö€—4ðP캱‡lW}¾nUºÕ”éßoCɉ.ŽÃÓÓ4àVõÔ—Q æ–É<Œ)›¡É²(\•¨yLeIÇ“ ÆqÁù·ü>w'¾eþ’Af ShnuÕðwÕNGv[‡%Éõcú”º[@ì¹ Ž­|ìËáý¹¾à>øµß’Þ\Ý b !Nžr¸rÚ×h¦ºÛ“Y/€cnX8^Æ,ø@ÂÝ€)N ªTéû÷ Ùcp\²œîãaË4Íw%E‘A·¦¡±G¡ô@ƒ:L¶Žg’—%‘þŽÞ!(Ýœ¢-¡DvêÆ^åV<7ýIzÎEœ *þ‹Lg ãŒSÄ Ž‰G;@jï3½wa6×SÖ\ø\UŒ<Œ!´9L¢FŠ\A–†a[©¼£?¯úa´úýÆ8^{ä0¼Ùù7:³õɮұ,»h’5A#€—¬«ƒStínr¿½D÷î”=àŠ¯dËÊV³êµ§’’ÆZ–ùxM?ŽÈçß,ÕðÒ…{ÂŒH¨Bç¢,TdN´owŠúc­seº¦@\ŒƒŒé~ôz¿ÞÛF(ësBŒ ù<ÐlLëjò"ïçLUq9 k-kztáuæÙwïó#¡ô„]ä×ëÛ” ÃZà,ÈöžUµ¢jS {8ïå0êUá.íÀŠJÌ#«wï}DVªx‰,K[ÒÑîïè\u" ¢ ûñ²Ä“*éö —åΡ¨aÜîú_õ² ,YÐ&X1˜ÊUà?TqCŸI"¿ W(‡Š9Û9ý[Í›¯å÷ƒ¼ªö1¶œË×bÊ·<ŠûvaJ t] ôiZk1bÓºÛ;|}bð£qbE®R-´ÜédA]¡ÜÃ8ÇL¢ŒÐ¼À§ødÓ\ÿpÊÒøÂ!úba‰2B¬aK(xA[¢I禄I}J÷×&iŽÁÚ6`zà!_ÀÚKŽZº“Ó|\Ém¶1¢ï>'T$uiI•l¶zMè¹p-6ù%ßùË?µb|#˜ôg­]GyMß+\ÓZE]"k:”"û®Cñôäï»Î‡Ä7óíYíõtHaþ>•‡”Ói›fÑ*Ø0̈́؋¡QŒv`}hU®"r ‘:˜]ÕÞïeÓ5"f8UãZ´ÛŸ–¤3znw4éÞOy—)Ú_p}…s:CuekS¶×Toƒ$:¿_ô2Ò^a óÅ*ôÛ×Ò¹¬Ù#µoY;<_(W¦«~.û?ÿîÃÕ)‘( cݳŠ9Ȳdc5F]H_YI&Bw°ƒ$Ü@­TiÙÞxNöÃf}*ÁŒªŸâ†ƒ £ó¦Ù¦9ݧ´(äÛУák°yNqíûÿ¯­ßöµ“Î1ŒQA1·¡¢r œO4%Lë—V°cíñ¶Õ,Ú”‘¢ªc‡üz8æ{®×t`ÁiÙtx#ÏûëÓZKC³éìÐÇA.0eN¿»-â{”b¦Ìš)ñ‚T…é`Bt2Ïn£N¿^OÁƒÕ%Ã,Ñ™ã=ÔîQ3{]oCß ,éEé¢@ j£5mždÃÛeùõ–þ>€Å,eÍé<(Œ]žç*WTwFjÝ·rÐçS,ŒÉ€V>º½†ÿI‘ã̶b¬2&¹Ì-E]Ž\U J­[¸/€”ˆKQ†]Þ)öòñÃWI:tÐöí¸2d¿â&µÊtý(Øí±<¤c²ˆ”Ñ8š!¶íx ½ÞÇœÛà ôúªœÒt͇¶VÓ¶¶m¥#¦Cß#ð\üöSa¾Χ.ú›ùõ9Ð¥€ûuу®íºª©¨wüòAICÍpØZÉa«*-Wé|´XX6=O`è³nÈ€l´ÒBk¨Õ>UíX©òÏk^ýªYôTÞ__šÜRòÍ6õLÄ赚ÊÖC<@…}Û¶±“ËÈqÐD}ØôRÝà ~*£=)Uübê ´Ð†§0ƒF—ÒÎ_–®‰³.¢´“ºœ¦Oå1}´Ëœñq{±P¡æÎÕV¡¦1ƒBûFd¨k˜·lm«º$+½*ºžð®±Ÿ˼§ŸüdU ù yýÈ3gØ-µ½šé;…ݵ“ŽPŽo{tÉS¥H…ˆy‘NïGÿ¹žK@BdWËA‘ ÊEQÉšýƒ-ßv.—)=(dÔ›]¦bÀ•pJ+¾àÚ~Üú0ÜÚ4o¡P5Ó¤–&žBØ-µ‰,éÆ%芗£’}GÖÈ8¥{²kªAÏ^ûŠ¢q2·eš§t˹¯Hçé»?<ƒÎçãrp.½Ê ʯ, #ÔvX·á”M㣩ž§Tvdúb¢çƒ6© Ó×¼èCöe›LOz'v–¨†€ÉqR±º¬N»´íR]¿úP‡g%»àè0š†ýøBìIúLiU@™Åk+ì³qnÆV•0%MÚU¾;å‹® 7fºéí¸Žùe.DÞV/‰f˜ížuàg™È{)ÿ»2;ç2[¿N—ê"XËÙhU_eö‰÷±&cÞ1‰«K ÓYO„—RÛ6Ú¨ ÷jß[åPÊ@)£C—'¥xÇðùíçû’Cï‚9e‡’¸ÛÊy˜(Ópx*yžå¢èZzøì»wp€lzt¿Ù¸–E ó8 Ëòµ›>®ç­í¬c ­³\àSgàöÍó‹­0¾Å‚Júè¬ÅB¿XrË×yßëbWS² Äâýc…›ãl2ˆÔ¼zlÛú–ÚƒA]=b„4È—:œ¦5¥wݺ©iŠÊhîõ†Í^JøO¦—ý—{£ï—v Œ¡:“>qšX§2’½+Ë(%i@_ÉsâMëì:öÍç(ŠY¤C9$O¹‰ºhЦ ÷‰´ÿMð[<”Út-‚4¶óY@ÝMw—E»šËCÝ]Úãbé;ºBÖm`¢-;®3ŒÖÃ@ß>AÓÎMò š˜OHC\– ö¡V€4dîá¢æ-‡ÊÑÖ̲(rÆG@Å’ÀùÀþÀ⟚˜(@øºãD¸xT$dI:¬‹ÚY‹º~ÈAîßéfÝ'>óç{ýÑÌeJn!þjß‹—”ªÒ¥ ‡vŠz 'ƒ»-`ØT}‚v¡o¦àC·`“®¸°øâõÐ5âó™QȪ6§w¹­ƒÔ²l,b›h2P=«[ËeïM20”IYÚP`FZÇaÒV•Ú“(e55„žÒϤ}̇uF‘ÛœÕÇ÷K°‰•tÖx.…`ÏÉBÇ©*÷ g²“ ðš0çBKȺª¹»¢Õ×ëûÄÄ5k È<³©„ò‡,ëbúraΕ,]ðM @ð{¦©žó 5yo_ ZÂ8–{ÿè¦KÇš~”-&]:¯C[ôS³ÈªTvÂÇŠ­Ú3.M¿êÎË%™ÂTÄ~‰–„¢~´Ît –Uz!¦IIËïA"IOS\çƒgüb6¹65txªNƒ#hý8ÞšeHÖ¸…,éãêÓéž’¿'Iç‹"%‚V+@p†¾'å†}£¯]å¡‚ù§|uúļx3•¬•ñò,àY²ÆÛ¬»ÈghŠª*KñªÇãA=¸ÏR|жwNç°k»£ÜÀ`—oͬbgGöòÅE¼QáÞP¡5¤`àÈd—ÎL>à³î ë·o2y I²÷(›Ê°$n-í|Bév‹Ú(Ïõñ‡1nañ9ñJgÛºÞbÿÂD˜é 5‚%ómÍörÛö5k—p8–„²ª+~ÖGׯ¿‰C±*ñ×!ŽØ´Š"¶G.òo®=…„ ÛΓŽwøÄ™Á‡½<ÊÁŸSÉ¿ÐmºAkl6õ°¥©±.% SFDÇ›Šbnªé¼ÛúÕ¹üb£05°îÎåy_¶Úž–ü*;ôn:×þYß›XOþˆÍ¸Nñ«¤Û.{’RZ6®”Èë¨aÝ(‘2ÞüùþÒ£Ö©E¹ŠÃ£å#ö¤ÈêˆnÌ$oe[ZlG\ëì¸æ­ÕûÏà¢éWp¢Æ€sº{a|ó›×ͯ'tÜÓ´dËöN¸+Œå®Š¨­ö2‰†z¢HÒˆl=Xü×8` ì |á®_ÐtúÑ0†”at\ÿ‹#lÆFTãSñ=m˟׼£ªþ­pYz<#ðƒàWš†–;fá2ó®[ÉÙ¦–íÚf‚feC¥6±ËU½ ÕcµçãÞÈÂ.Uðwvã¡á#ׂ-Žƒ`î´e%íxÔÃEXyV$sØnÂ5øý‚þ]l;¡Z…ÀבÂêcgkh—¥f„ün=F1\¶¨€l<Œ£²·‚‚ؘxÆ’ÔCY‡u>©b–9‘ N¦n:é–{å1·ä †%/¤K²fNÕ14(Õd¡òŽ®¶¼ÔßȇÎE`@Ë˸H°7V1à:\µ¥ÌWÀÛÅÏrƒ‰âI’ÖQU¦Q8²ç-<è‡?\*-LÓ<±½Hܶ~G¿¢+:´þZ†¤B†¤ßÛ!ƒ­]YnÅñFƒ‡g9t‹YTùçEišG=oæQE­û‡yT»EsÚ‚eµê%)nRÎaú€íëôø(Xß:$ j–® l8ß‚UKŸÓ}–B.©‹[Yò”œÌ¨Ò°–tÿ¸0^ÛuaàIOÙy5Ó¯ªqñI£=¦À.â#ÇÖœ ýà øf¿VðóK&+5u'T­![ë:à-š¶‹¾Ëf*Œ0ŽRÈöïsƒ éž2ezE…ŒVˆZ‘¼Ò}œ§Ìãâ%ÝG`"™¡-ï7†gÂvP=5d¶nÐéD ÜiBÕu9¥Ú¢dï5ZýZÏ ü˄̽yžÕûÅ ù´vYDbHº×õš-©j÷%žkDQÙí.Î0½†&µwž › ÷“ ÷dˆYa#± G¸Xõ»jr ðkUJ¢Ei5€²ØJÖã裹÷ë|IZþÕôq Ð‡Rz&0ù/»@V(…±éD‚x›b󈙚L&Z¿%—u7NãúkýÖ}2–c»+5—ó–Ⱥ0<±-ª}†eœP˜¿ïuêÆ.ê<À¡Y,­‘ÌÍDùÖXĽ•S¬i¡;çzÐñ/Uwã6(ûbŽ3Ê(9ÂA¯ÛC‰v.vz™QÕv€TzMа'±uü˜o˜Z>ƒ.¯›|FÝC3wS7Ì=Lóv£_À—§Ã-) ëµéýR5ôx¸Ç…dyŸ€5P…¬$• „/k9LYµÖ”•Ì*Ò1×Iˆgz,°’õV¼Ýî<ÑæÇðÑðår¨¥åÆn¢k¤6Ê¢ d{ϰŽ1œ}`ÏZÃíèS¶ F:¥±p†œ¦aP¼(SJ[*±©‚­õƒ ‹ó>РS”âÚ‚üÑUkÉ0ƒzW‘ʇ(œ(?ÙTU¬Q+Yƒ¥BøvkÂÒ½^)>½xÈ2v#;¢ ãAò=TÓ®–~àI×þiMÓ²>Œ¾ø9OŽ{ÏÆâ(1ç<®×PµÕ´¥KZvK,Kú°OÌ–ú\}ÕhsÈmøÚ¦¤+¹gwHt¼+@¡ªšÎ~žÅúmBŠÆs@2:€öÍ”I@¹ïC‹}z‡4VÕùFŸm®{ùð`wzM@ KžŽâhÌK"‚ö€¤Úú¦lTß”QX¯õRêû RèŒQ ?Mea}sÛžOô…ÃQTTZ7C™=™Gdû<¬Q7¬tî‡q›äR‚¨‰õ ƒdÂúü´f>Ž(ºò°Q¡±v(=[=²×q?Ìó4ƒC=À—)¶µ‹Çµ(¤‹L5œïû×húgoúšn\ÄŠ t3ësd†{®òmIrÕ¶ÑZ5‹4hÑ€©V.¼ÞgJïÞY[OýVóºhÀ©X‹…/å~Ê(LM,Åd=Ûà# ܼmžâþ7v&4<aÃ:4 ÁïÙ¢•QY›¨lÝô/‡¶T^Çž×*ï§\ö÷,Q¯J¥ 5Sª¹Úvèg‡aÊŽB>¼ç( ‡ í|ÿnŠbžŽ,[÷%Ž ;wÍHW3ÂÈ<Ï]0˜Áñ@w—ŠÓ¢¿,m"{ò¡zúáXÞÕPä"Q  (!00³s¡÷»Ö*)†’þØ,nã]ÖäSX¶íüü+\ýÛ+§½Ë©=4Ö]&þã4ÊÀ•3ÄA+UÜ©+ÈɲJšTðÙ¾Óݪ´öª•oOw=ŠC*dLçÀ øîÍWèM•«zÄ9%°ëèÖB[ö\¥y¯º¸ªÇm–õ<”H8¤pÏ;,æR{bò.jYeAÏFŶô;yƒqÙ<iNi°"¥³(ü—µù¡:O•— ûQ5ÍÁ1Ë©öR}¡è$L*S“dT ƒpƒ$8äá,ócCE’¨¤±¿…:n+q¼C¹œçzšº•vCT zM¤t”á¶wÎãÜ@éÏçŒ!ñ½éU ;}F­B•ÆqÓ8P”¨Ê’p1¥›8¸ÍM—ú˜HJŠü'ÛSUè¯ ,ì0ŠIÆ’´iW†ëFǾ—Md¹”,CTÂ.zÙþ§@ £Œ"aÂñôµb Wˆ¡‚~ «.Œ‡¼•ÈŒ%]ÏÇ Ö;T*ËÆD_Hâ’ÉöÜh ±Š e»s«º^Ú² ǰJõš°*ˆ‚ÈÁë8wÓë×{{ ˆƒödJQÇö:½×qêó0šÆ­Ú„ÏCŸ‡÷¹ ¦Ì!àgÙWÌÂïÓÏBˆL*l9ÜaHž÷Ô¨-Ÿ»rTúÁ¶„yzÌCoÏô?Äñ¸•ús¤Í”{Ô‡W ²<ªèöh«­Ø4ƒ–´0t`MvSC”¿}kø¸´Rʼn¾€iüÐÎÜYæ™*HF¦7´ùפ¨Â° ³•î)‰MåŽ>d­¼Ç¡EŽ\÷Öo»ô%rÆ%ʰzÐJ†«J(ç¥B¬-4År,}5f¾‡GŒïœGŸ C_ì–Ét!$cÕ€æƒÜuåoc(2Ju õ}ÔÞCÿË6¢SpYî`M6XÐb?˜M‡åÎ%Gðóó­“ÜŽµ|(ybYiãôI²,{GA¥Qñ$«ÒZ&J'ª•ãl Þ9'_÷³Ñ&‚KªÔ]ËEñDi3íÏ>ôqîjnÛ[‹?_´bn¶Q¤„Q ]£”9A}É›¼Ü0AÕ ¨›<mÏ,ß;í|ÅC‘Šj¨ˆV÷5‹9Ž#ÔŒöv÷b‰¨ÆM†}‘ãJŸÖ;èCøæ%‘tgQlïïïŸÃÕ¶‚¹%TA5 ­cÕ¦k¶±0¶~PnX‡Á LgNzG11°²&ïPˆ·uuˆ'´”æÖž î©Ûñ^¶6~ð8’æÃþ0Iý~n?Gó¶èªª}™}¶—PâÉó¾o2Y AÏD±k=.=†éùý£=!‘XÖ¬ÓÛÈ×W*ß)GIŠ Šú:w„6¼‘à†î›çŒâf8ò;2=|}?Éôe »Œö-ÏC¹³Ç!îáX> ©ßZNý”¸ͬv…ƒê)^åcC¹i£×Ä5a;áDA×úÛ}s–¯›ð`ú 9’Í´¸t‰`p:´IñéO5ák°Y¨;qä<„oµKO…Ã8.*„Ö܇ s×µMƒ ±d!ËÕðODõö“¨®ô'‚¥Åipÿ£çfÝ%%—ŽÉ‘‹CxH·09o«‚Š’:ÔŸŠpè3{.lzŽt¤{TûGڱ $Ÿá 36  a&±9@K “mÃðµâ0†÷d‰~{WÄïÊö° 7µ©|LÇ>¦s´Åú·´7)/¤'Ðå"¿Ï»Õö.ÎSÿv쥪c„”þíYEÛ½_Ë!Т … ø¡Á$äøìëÞ|nëSóXi{µ fÛë¾ge;×éQ'u¥×„{pù®s V½à££qמ©J\øÖžA¶CµÉ\B8d¤m+¨ûmd{pó8dëÌëòï1ø4ª`<°Éìt_§iÀ‘mÕT¿ÝF¥@§ˆ¾Õ©`Ѹ{]âþànB2r2L9¹ o†¤o–¹Š¦yeAŠp,÷mJ¥¼Ó^æâM¬Ï·`c0õ¢t”ª%ÜœÐÁØ<Û¡Ù7×Y™‰¾&–tAÔ§2 ô.ýŒÞÙpü< õoæy${!ö(4n «ØšrϺ£­£>†‘·s«yÓl™“R²Fû0ª\ªãŽ’ÛýÅ‚¸ÊCC •BC«Sz“U^ôƒš)µ(Xköʉ£mÔPë*ãã–¯Ÿ_[XhI;·4âÜ¢q¬OËI—uË ì¹…è†èÞvZÔc4ø]Ò•™é% >ÊéçüížñÙ¯¿“ô Ö§lÛfÌ(UÎÔV­C/ z~”Èxî¡$`8—‰$}pªŒ™ŽÇLÒÊûe{TÜ#=àžEñåUÜoQ8…}Ѳ6à•ôxpo¶A¢õÁ×Ðì`]–U7è ö<³ri"5Uq>4q2–ÚFhwÔšþaI ±Ö;ì]¤.4Dµ'®])T5M¢ÖŒyx›¬i˜}x`R£; Cßbü[»EDQÎt[àˆe4Y·”/ÑݱC]QÚ$©2•¸®˜Ö™Þ£ª»ªäU¤°Ÿ¨ªÉywö¥÷cOû‰’ï¶ëz³,Mw)åmz‹žAçˆBˆäJ¾û‰áÙž"¥1^³jpo2?´nUVÍq²§ýò¥W‘¬I?:ª&Sß»Ú×_2FZIo,Å<±Ÿº±ñçže”PÂ×gi˜öé¾íú½B B6ì|ζÛ%ýùæy·–÷/A:ìØ1€ÁQSÓœvã”v*K½fÓMIe %µ8°æ…°¼£yÞ‚Ú}ÿ¶l$,ëÒ¶nÊ0*# §@&üiMËûE5çûëšõÓ%80PÕFºØeã¨($Ö»Œ¿¦ÿ úT^* cEÿà>gLq´TVs%,±ß.è»Ýéó½iÓ€ˆRªàÉÚ ÁßTçª!‚t=$Ù¤%]˜Ù8T͘G›ñ®tÂíO8¨Ì†î%ý\±Ý³´Júi¬²°(¯—= j-,s1]8º‚qk࢑ó„,ÿOdi1Íš:zTs´•jOç…Jš‚vÖôÇUÝOÝóõù­wRVS¨Ô}fáš«*Ïúy«±Š"¥Ÿ`EÚ¢@[j"Žy3ÈFtþÑŽ´>Ä/{)çŧj )—_–-Ôb6„€ÞC n^r§WÝùBÓ^$ïã4áœEB«õúŠ~êU8ŰtÊ»|Ô?™ÃƒuJà·eß(m~³&1='½Í¼)Ì÷ÑcWƒjöf¦¦€Í–ì$¨Ç#óÏÐ?öß•ߌr Ï^<ù¨ktr y²/ªéó4Ö2-Ã1Œþ¼æ§eým¡—%kû4rÕq+gšòxV¬ÉÔè·‰ÒØt(Œ2d\^ð70àó{{jÎ2œÏ˜_¯×Ì“6®b !cDÉX©O‘MÑÓ1YÓÈÖðtÛó?J™'cD×(-X{J‹“B´ Åv‡ÓTWĹ~N:ALCû Ãb.Ãq}¿ŸÛãö¨Ä›äžhÞæ[Aõ*$•MãVè%!r‹Ù íÍCŒÝ¿in½Ÿëú%¸«ˆ#rÇŠ±ÌAÚ*§b& + È%;­ÿ²¦®y»åœÐ,S@1óP(”)æY²TQ¸Ñ§—#DÉ,Åw“Š#ó ¤˜bqžuP«ém‚TŽ!­øÈ±XåtÑm*-§®*(~ÎÇ¢Ðz <¸O»'Jê’6þÇB›¶9Ú¬·«m•nˆí@«Â±Ì·<ç”KúP¿øÖäUA9Tíá°Ä¸8UneVÅISçë±$ÔÌA"q $Џ[‡a{ë™oJ_½Åä¹È0ðUÜ&q™eûa*gÈA²€ù&d ¬ë*¾O§¿6i¯ i€ªˆÚ-»á¬j€7Ô’–k–ù"çÉP»¤›ø Ãšw_˜÷úÚƒ¾†Ðìu7 ÝúD+HñIÜĹ,iy²¢Ìžr;Øÿ¿×¿·Ã*$ü¸ :@ üÞ‰lÙeÍ©ÍÏÁsÈ‹†fY§eÞ¦q¡º•Û¡C¥š­žêaÙ¶!\£°Oô› ä îÁHKò”ñéòoÅ£š&ÖkbîO‡ß ã_ÊÑ÷–àóõ>¥%ö¬kÄB2²ûÒ/uDõìž…;Ã#m°ÛNÿ”  êC…#”H ÐŽªÁÀ»a:$P–"I™¯ù%›èCÑ–Þ5¨8ö/ðá%YÂèÓoÓª)˜ÔÚ¢ºÃi¥4:ŽT[ÇK\Ç阋qVÿÐôº˜í‹AtB¿¨ Yµ¾}‘× ã¨ ¼¼k×|^)?é‡hв·¶ æ­aºD8z¦ñ×¥…õ¥Û·iÞ‹Îm'B¥°vOó|UÑçsn^Ô¿e£Z^áWi;Z”¯‰ ýòhª·Ì€Q¯ Oj¼X€/sH·Ž$÷ ñ,m ôØiQÎuÀ(È–jXè2Ý·<é{ ТæH…JGݽœOC¸×‹ã@ˆÌ¤èú<ºlŠ·¬ÜÓdžãu[Çr„µ‚Ñe qúýÚÊõn–xkÌàNÜcÎËNI­‚›¦ši§%£@¨¸q(H[”ã[hûÖqz³îŸ'L*‘•Ôƒ ˜«jo²¨[é*YTÔëNŽÅ_@)cC´ªé›ÁÔÙUM°}Âå¥%º0À §Y‹û}*Ú¯/ è¥ô›ëÏV‡ º…û97ªkúhÚU3Ê’¶átÊ@í“áf:7ïzAîküaÉ»˜.i‡ÏM:NÑXn!Lý³ˆwaòÏ œ¹÷mé(Š»\S´y>úÂ:óº™êäaOC*ÂÚMÊÇ‚Ò7ø ng\üõ#Ÿeè÷š8 µuÙ7À‚xJ«¶ùÚïC w±6 )óÎdUÔí%ßdç®ËýÍ‚ N©öÈ)8B”5 aßDÚîó¾'q1K¡üû5o d Âá ¤jò¢=”'9‰çtÜ“pj£¼J”¬‰O÷ñ*oû9=þZ¿Ž6T ; î<ìûN5\Ú,û”NE’AÖÄkÂnάgภ(÷›ˆE7)Ã9‡ê`æùÐt-¶«µ³cI‡ÊÚ Ö¡hÞmÃ,•r.m±n§z09Óõ“/ëK߯›^Ò²é“пñÃ6Çr>fñС?¤[á,©á]â<)º9ö$’ tzMª ¿ÇÆ‹°qâ¡YÝLèò ÖëhÙr;pVK–RaÔ¤S^‡i{,8PU¦wyø²!;6oÙÜó륃0P»lfÐñâl®Š¨x݇X-² ô³ý¡Ø<c׿çYOÔnÜT¦T¸}Æ5áG·` ÚU^î¹hØÑû3À»¤Ö9D¸A¦Ìô}É]Så^÷êÐCŸ<£+i‡èÏTv©0é'ƒg M…ÇCûêØ¶q4{¾¶m;fSðÿ)Y=Hè)•-ÉÖ&ªÉ¨Rv…c›|®¨‚7Œ“szƒl¯\ ŠôGŽŽ<àúìp‹¹dW¤ }o5waÙ:6p‘ !Ò?ñÕrap»äqëÍuEU!ßõyè æýV†ëØÀåVÿrP-3σfLÅÜ_²+ÿtóeKћݙ‹'͸ÎÿÖé= óײlÛúõþÏ×;ÏéúÍÔ¢ö5£Í¿VjB7oÈ£F®dª2Á‚¢:àû®*eÖÃxE2Q® WˆN”ÕP¥ 2¦<™þ¼äÜCÕÜëùÒóJx„”,È&ÌÌ•²<]ç9iTž%…, D‡ßþáulÙw[ m0%–Ìe›€[7Œ˜Ê§i†¶&ÊfCºCõ§ƒ  ƒ\žt ãæcò³>µ H}%B‰ì}»ïÍ–LiEeÃ.çÊA ¾wt^5ü̱Aá\O)ÆûÚ‚‚É£×OéL‘Ï?’Ðj´‘jVOô½«tZÆen¶?¯é_ãŸo豽ʛ&);Ÿ5¬àJ?~_â%U¯c• í¬ôO÷Сà™g:ëÛ÷ÇüzãuJ˜JòºÚ ÐåMжfÔ4ªÓH6Ç <Š)ýàÄxØlª~6­ÑSÕz);˜½.R‡ŒRœ,ËF §ü1 ~xÈsÙ[Ûþ‹ 0ܶgjb^×2Ž“oä8]Gú[Xn9eQ²(A¾g²-¥Î½Y=í¬cÖç&6/èÑ¥¹¸\ s¥¶*Êç´jèJ™ÛA—¿[Õ0>¤0¾¿/zYs8Ťñ'5ÚÀ)å½S(kâ΃HÿðÛSá>™Å…ÿÀ¨¦¼Ã\¶• OQ¤ö¢Ø7úçR¯GGÓ€Œuv­(¹‘gÁ€®NáJæ)`±aœ(mm£’¹ƒÑµ~J—/y× Œ#ÊÙö]Àææ‡^Gδ2¨ŸüsJq†–ÞçØïé¸ê—é!Åýû‡u,iÿus`}¿Þ/,–RÍ ¶lž2‡­/×°J•Ì™ã=àˆã pà)uº¯X[÷).·t+çeÙ›æp¹¥­SUs_Ñ¡ÚÊToøß,jäpi@³‚þS×ÃyÁ1sìúVÛqw+ýcJË„ÉDÛ<8äò|ŽIþA$3?õŸÛ×*Í_øºå(=â_èZnš¥Ï˦Éé{ÉšD ^÷\Ç¿Я»MûF"ÿ4ŽD~:GîpŽÜån†;.à°ðÔ-@ëq—`ÌÝë}y@îf?h̹X·(Ž«f¥Ð¬ŸÎpᆥsö~»O®0¦i#u<“*0uèÎu—ªc Lí˜V¥~ªu\…7¡Ž îÝárƒq0c“¬¡Š³šµ;KSÆÐS¡¿Ö–Žæ:1–*C wÕ›ô¥‚‹tgW¼¾BQÁ;á–´t4Õ¾GžÜ«}ÝV½$°«><¸Ï¶…ý¸ËÖJDÜÞî}¡ß!»Þ È¿‘×9öóÏNÈe›±JëWf ÑN?™^eßOS2Y^Ñî åKѶQU¡^š¿®ùthVq1D¢ õûç¼G¨ ýÒMe8QÅPÊÜ –6¯)àåöEéÐî:«ûíš'~á6ØóûlU³Wr3¡›:O0ÌgqKÎ×=YêIíi·v©œ*´¬Ô<蹚ªþU)‹Æ!4w6îbá ¤Œ%í&µä ] sZP]¢ßª8†kB<õ‡ÒŸuɲ}=¿Ž1hÞ¶ìý0ôÇt̪ SÐ!¶+‘8˜­ºøƒszǾÞëøÆ$[’¶<e§iP”‰ ã‡D[*ŸŠòEä9¬Õt(;xÞ]Ç„-$õsÀCqXØ®ôœtß%ÑF±jNÊVw  ÒÎØƒê::±ôìî É×S˜UyÛ45¨¹Ü&ÀÔk躚Ãa/ÚT°mE~1Ùy\£TçÒ¶„QÝó4·-zKúNDšÚ=WCšNåNÕG'MHκˆ¤‚Q¨_§Ü6þ¿wzŒ‡„ây ¼×‹îú!ï÷ý¥‹F1ûè17jÅØ'O¨¤¥i_ÁÕá—IeøÀõÌßsöm^‘”9ZI¾©P%Àu™!CP/vÄÐmÛâʇcQÄ/Û„fäãê0Úÿ»üw% š6Õ>KêÞ<ä¿oÕïç1;¥¸T±‹ýsÍ Ú—tÌãvTYæRÚþnIëaÜÕîW^ñ[8:ì×¢ù-åŒ>ó\«¢ÞÇqÊ ¹B~·¨Ü`wÿ ÿ]þNÿû÷?ü>çÐÝ~Æ´ûÙû£ßŸë€ùæÀàÆ³®†ÿËöo¥‹÷J–4!!OI(ŒHDì~ ׯ;AÁ¸ì­< šÊ6ª15]ÓtéEÈÓ5ÙЕ6%d=ÞµïWüE“ýš<3›?xò¡Þ˜,‘A×=må,믛2N„ž—QjG'í ±aº.ä!ÏÂ"ꪽíÖVÚC.rëAÕ}#'¸ø)÷ŒžæŠw¶ ‚¶6ðô>ñBózZ±ßK½ Š##€õîayh»î‡#øKƒV<5’<™òovÏÖ0k¥ò~§4•)AGÞ§~Pÿ®Ü»~=N_Zã’ÝXĉŠe4™<×g§Kº6Œ³8úÄ«ÿ¶AßþÒ ?Öt2@Ö4´Ì«ve Ó‹mÚÝVÕD#oËò»Š)?ÚÃ|Ü6Ý œEÁ­ßÓ.ôqrçUp2å‰Ó¶): CààÂreÜÆFíє̀ÖY±ç„vj!)ô /A÷l„Oà½f³ØTf5*ìfÝ ïYt^/¦MÑ=„ܵŠyHœM[¥º´]ãdî¶\?¥g[ŽkR!ç¸'‘ÆüëÒrüþÚ(nJ¥]¤°#ÄõKë “Mežg{Ó6MÔØêE©Ø‚`‘ë¡n×Z°¯7q¬ª]±‰UwµÿT>U)íÓiÍ»0‘9Šë.ú“\Ü£µtNºDé]H/1‹m6½,ƒ›•lغ5F‰e²  kuª‚¸× 3îåÑ÷:‚R‰;³(ÀÈÉ ð¾Dû\ä"EïâdZLë‚aùUPÐØHQr™²¯9Ì1Û–ÛTù¢Umé„J[´Ù»ê#8w¦( j9” ÚY™ñRØÛ´¤‹ ‰µUìïõõ¢/|®/Öfg7¬B› öÝ4!Ñ‚ý›qêÊl])­Eºß¿ó|X”îta ¥`ò×]%šÂ-¨œÃZ¶å2§‰Z©&ŽÊýxXàkaþŽê7ÜüÕ‘žöÿ82Сÿ­#ƒë`÷Àø= Zþrd¸E½/Æ‚J[1ÕôÓAó h“†Š>דת–ÚÀ£Ë˜ª,Ûf„¥>óÁMJŸ©·˜u ­ ½Ñ†¹(?ãNeÖ·q²FSTµy%ž)®çÂ′‡n/ŽÓÍCjMO–@ÁQ¶Hg‘ÈC´wÞ‡­Ji·®‰C\ªX˜"Ñ+ðÎf¥ý¡kùßý +ñ•éÂÁ y§é9g?Ù{|æ ßß:ý!”ÂH˜Z¿µœÕЕÑ8¤daYíþq×aÞd1XFÿKLÛjæø´¸CDk`Z‡%ߢhjÓšêý º9aòO™¦Sõmù>Ð^/®úmÕ–CКXqaoÃ]•y™±ê'¥¸ÁY¬ËìCZ sK3ùWHªƒ9×€Àº¸ýD[µÜÅþ®ìÖ´[Ë(Ü)›Ðë¢-æAé0ÁHþf•ýþ¾\>ªcE&kb A UÓk]Ó>Á§Zÿ¼¨}.ŠþÍ7êÆEá^ª{ÚCÛ€¾¢“¡Z—*Ao Ð÷a}<‚Ãö6°ï^_¢þb-¤¢f£=t/F ÔýdŠj¯u Ã-Û«­üóªþe_Ïí)?Tåí„)NÏKùÞT¤jÙ Ž3L«ÎJ)Åe×N D¹«µ?Yh™¢ ÄÊZq¹vŸŽWž­{‘FÝU«{ÀN &Œ*Nµ çC@óÍJ},cÌ.£Úš¡Àìh>„á–i8&¡®–NæùaªúÍsf £» ègÏœFQ%ŸÏcFëJâQåÐý`;ÀËîã¦bðÂzê©‚(c0ah¦J5e¹•eZîk¾«Q¯‰N˜ËÅçÙ^þð>ýÀ6-Ð…=ÔÒ-¸7QF1íèÚßÖ]ÖZ×FÕàÚZTmð;qtÛDgàZPj°•[L‘t÷¥.ºqо”^҅݇<ê OÚÎçc>!3ÂÙ4U^ÊÕ³M1×{ÜaÀ¾«: °÷p~®qšƒ1CÉúЙøºˆƒN«¡†¼+蹄kÙD‘þæDKhYÀ!=·?…«¿¶£¯˜Uìµv Wg®^C5¤Y“káj`¿Ù<„üixð°ï…›dq!RUC èÖ@Úd€(Ävý÷ :ŸÄÞÓü\¹ù)¿‚®˜{0rä’ì¸ó3þ›Ek~Z´bM cÍ"ðöeÑzwtzaêó­ó*¼é‹#¢ gB¶“Mõ²ª¼ÖuRC®ôâµH¹(4å¬ÃTõsœ$*ÜéÁBæ·Ö”§_@ÿ¢T{*Ò/ v@(•¿ÝôÇ’ì™SÀ>…7^¥â{7™êiÚèòÐëùžƒãƒÛλªÅó-ô9ØI¦e-e2ôeZ¶“¬hÅ|Ïó=-—ºšôSb~h³ÍÉ‘°êÛ}ËSõ-<Ô3¿¦a9FDϾ•êr šyÚV1Uc²&PªlÎê h!}§þ¼ÅSQ·ç‘@÷⩨Ûó(¼QœÊcš@GyŽõ)¢²äRÕB–ËøE¤9ög×4àP.F¤Te»À‡DcÒ—âNëv9µæAº«¿J½O„21ÀLc‚ý^µÐ>(UšVC2É0Ú3Q€¡ëàÞ¡­r $ü{8ñR†ú—û°¹fP“á]}»»S’ÀAߦfw¦gáÒ¨‹¤˜Ûª]§ª a !7ð0@ð¸ qwtÌ¿¾ƒw)h=*)a²aùkY‘$¼o¢±ETßÕ”{À¾O“¦§H•®•žò 6u¼GJNÛs/RÞîë9ü»Ð_l:Ô6°L)×½^¢vng¨%,RÓÒ~§×À|èö*ÃȽpàûy‚²ËÊg8p/©UóÒ/M§4àyïñp]ëhæx÷Ž: /IB ‡^´ —àŽÒñ½®Ô^-Q«<®ÿ¸$ÀÖ]'@rJô‘êÆá‚Ñ޼¯ÛH—Rª—¤ÚA”^«o½jï“ëíç`¸å¨½ÁÄÉ ·5¯—m*Ãt¥l§ÑkbUˆQ¢ûtjm\׺¡öMå7†¾*¿‹l‹¦fY›jj…ÜäÙaÑC¢D:PÀè 7Ð.ñ[<)Ðñ/)ˆˆ¢-Z8ÅÞ¤FOÃP4˱—ÛqÀn0ÎN5ý!çýâÁ û;£Ý”¡=À¬ ¥šzöbÆ™þ¹7;»Ã¥Ûãp€øî½õÏ6A\(¡!2NÏn <ÝÏ:ªæ:JÓ¢ëcY’ ×ARg\بÛá|ÊGÜ„LìaË­9e;k–®°å–þM@¹m`Ð! ìAoP¶å¾áÊ)*³X&íP™Ñò@ãÊéÞØÛ0f¡TAßÐoÇTÁxÀµÁ.\¹„¼?]Ç?,>+£ JûÝØOCOYꬫôÙë)œº!®ߪVCè=áñ „ÇÒ4 L¿¯÷@qú©uÚDŒ²¬{¦2㙓L%*_ÐÇ¢ËI`‡^`Cý̀غ}˜‘—Œýoá‘cóà‘{)ðÈ?/úø0êy£7öyB'yVV` ¶ÜOý:ªž²Ó5ʇ¥)õz `>ˆ\w¨y…(_‚ÅWó‚uw•¨NRK‹FáXP"-Y0Ћ¦ã»G&îW€Çt2Õµg ÷!£.>ó½ë¶tßÂ=—"B8®kMŠ{®{žÏ;*ã_zSWú)¡¨D1/°1»¼©o„7v•ùÂúª”EX Ýkª‡µ²q*³I@¾a¦Á¹®c\ŽG7ÚÌ¹á €?~àE¿ïy¾Ž;åŠæ…h|ƒê$ ¨—í“É|›QAu–^gýˆkPþщ¶Æ Aº„í¶–`u·r$Ù…Ý­*ÞÙü¿µ^”Bh_î WL¢A·©¥ÛXmeñÈX¢oÐ¥£kÊàö)Ts¹´® óx1« ü syn3«@5MXR66&嘎’Á«/ÓdIôƒèüõ?#Ä*Q¾‚Ó",oA³?œèóß 8/ÁJ üª„ #Dpw¬5<¨l¦3)€-k½¦ ™*^{ý“sØÙmÒº£GËÖ•Ìf7””ôqSÎQ³„Q'k­˜ÝÞaXp7æÖˆV¾Bk¤âÎÓÚ· tOÙŽÚ*%Çf5]š0ÿ0´è…í?>9×,®%H› t¾ó3°Ððª­M±Õ z&Î"d”|ë’¹kÇ=7qOã©2;Ì÷X»8ÙTyëhg¶¡°y}’ý;Éõ ÷¤¦ÜÚªëe¶oÎlYà e.ãÄ@wMÃp¥GÉ}é[p5,€7m×93ÛÿU¢dßÛ?K”@"øuŸ±h§DÉÿNÅí—?¯÷K̀αRª¾ ©Ñv‡_Ųɨ–¹«²nOD:Jñ‡OÕÍÉ0ƒc Æ”ãýPRÆÎÔ%”èÌ7uS*Noе¯öyÏÕ>uj¡µódOfùÀ÷õ¬:h®žMSMïÝe@„ˆÍžBô¸GÆJu­ø´8ª¨Ë¸úó’Æ›ö~£ŸÅj=qÄ®tmWñ4@ÛZ×ÓX·”¨!›ô›ÀMGi¸ãÀ]çÊ %¨H …@ýþyi4MÙ”@ò.ô¦Ú©H¡¶)Wñ:Q~Ö(Õ§}/RžMÍ •<÷qêç^æJ« ª0®Š‚áëâ/ÓÇ›Z·‰n–z)v‰¾TAtÀYê%øˆY_B/H‘Eb&¢ÍÏzĬeÉšq]+Š‹EþyIûžE<ß\î±Ý=X”€$ŠþB–Î{º†i¯Ê*lô#¢gP­dùçÐ1nlt$ŽïÃÌ´æZDBmf:wƒ¥éÌ$°ÿºX‡è„ù¸Ó8 IÂí ¸ºE£0«Ó-.öp£§\Ħ<-Ç6(çq½ÏË€/ïÆÎƒë“îe²+ÐëZ~,û}ªÔ4ÌQÞ­‚böQá-ãÛ§¢àm°ö/M¿Û>Ñ·3\ ¸TÛ÷ì6÷¾ØOl§ ±d\(æl;ñz¯›T E–·õ”Ï¥˜J£þ6)Ñó1ªÓ+GLÄÎÀöº4ˆs(‹+4â¬m—…þ«6§¬O0½>FɨCl øc™œôþI£ç„@™d ¸–0AF!ÖS¶HÙXŸ4)• Y6¬*k¸Á@Oìj{g÷o㲂y¿¿EØv™˜ÿÑŒÒõ Éè÷p¨ê´Ú“‰~‚^Ô^?€öß)%é?în»ZÙ¹Òvïm)“ ´òØí=ÌÖR…¼O*“ƒ€¡ïœTÞ{0ÿª7¸£7(;ÞƒŠÜÎ7FÞ²‰ÔSƒÓ¼›ªz‚2e·N [Õн·WCÒdc–Ž]Zpµ›ê†L¥°¥ºu)©Ý8Ûë뢺æpñeR¥‹J’ ªUK½¬\×”ð™cië0jB_üºùÐÂ~j-M´°©ëxÌ‚óÄìeÈ£5 1°VZÓ´oj_ â?–ldI‰îÄ"·W9-o´æ?.y2¾X‹Š‡÷·&S²w‚ät÷á?cÞû¼PbñŸõ?C^!iB$Ã0*dp‹êþ,W?>ÅÀm£? í>nìãCÆi ƒJJ0†eß(Þþ³­ÿùUýC«’Š„n[‹dî(‡Ý»m ÿüç\#V~rO ËR ¬ñ5©¨@?ÙÚhÝÒ(l»?­uî›×ñ7cÕ*ÄïªE7ªf½*„öaÏ·¥¡êûnúózí·4~$,`1*¦æÃT®ùPlÑ”k‘Æ­>tp¥;€sw©ܬð1ù>HJ8+Ö(® &@_iWµŠã¡Ëº”²ì-–<ˆÏUj¾ñpýC7çŽÕzQ!ôüÙxô ­—Þ¯\öÃ-  Féܵs¶…ÒŸ¥¿Üö®K¯À8u´ï›ÝBÌ!tÎe¥æ¯1Á¶¶¹ƒé­þå(ˆ=œcBÌ=ä÷è)übÁ¥à©£où|ÖfXWU•ЋZ ¼&ì¡Vi@Í=ñÙw¡ûÕÜðJ²ÍÉªé´Ø9Ò•u¦x(fŠ‘ÖaMˆE= Ë1ÌÇi}{·Dû~2u/„ÃC]–¬Ã=´xÛ&®)ÔÒ2¥µðtŠ(rÙ+8@ùÎE¬;êýÖ!ø@’kyýæ¡êâ<‹:Ý8Ætœh”Z§¢ {hQÄ3èfeÆNØê2ÂoÇJµY2dQi'^2 $òAI¦™ÞÁT5ïâÇÀ.Й ŸÊ~°“‰èqm–÷*£ÒzN:!óÉ«oySWÓÎÃú€:?¡~L7ƒˆÑó@š†Ö [®PÍ‹û¥œ s’·zUªÐ1Œ ËƲ®ý¦ŠFá7ç’0—‚]D-¹•BãB‡j*Š}c£8žÑ„Š®qøÂ ­¸“➢ËM f¼{Xœ@æÍm Ç‘4n6—Ѧ—t!á? ºcƒÇ]í@cÓÍú%æŒ5ÊÊË;aÒå_ûAè¶úª×Ìûäq8Ø÷°´Ÿ®’´ÌAö‰/©rßTµÙÖ¶I·É~<¢oBšš[Ƈ~°}aÞ„ Èš•hÆæ©ÇŽë2dQU-KRåÓVä¥ÄÍ€eÁ«ÂhÃ:‘_7ÄP³ˆqag˜Ø @­ŒÚ®Ó½çP­N©­œýkR+9îhÔð÷…^ŽÞò"ù0xþb÷HFhÖµtayðXµ{Zª¾œâtTÒD(“2M ýýRå¸ú‘LÎ?´ã™2Pò(“™Û¼Xš¥&ÊãÂpZ9È`Ý™pÛªyùsÞ´æ¸3!=XOÔh@ dºÜY6%lí*·J‰ž]•þfX<£´’÷ñÅ@óu¸ã U7ÃA<+cÚN€ ¹*Ä÷/ м6íøÃÌ÷o®wëóKÈ-Œú«ð˜ç©ÌÀ(U™«šÖ/!5· "@ìÄœC¨£aì=þú4ùÒ¶?ãR?R~il…:ÚNžxö=çÿßÛ‘í± ‹ ‰øîÕŽüHj`ø'IMÁ„bhsµ#¶—õVMí¢fÎËyU=t·©2£|A÷ìÀ¿ïÎ×s=lD ôÐX±çTVó\£Vm=×½¨Ãœé×ÇêÖãDt}áqùD'³‚¿ôv)‚{1ìYQ¼ŽEéõÚë0&3ìSØåqH£úÖfYfÍ]ìYÛ¡¢ý8V{œô9b5¯IÉ‘éB\Ò·ÝCßÀu®&Ä*xIa›¢…œ îªzEùCT1†RAïEG•¨Nj¶ñá“ÀèAÄt³¡ªoáòÇîRñ–M{³,ËÃ|zÛÅi…‡ì,1F±ž;@Íç.>ÿý>™<|¿Á†ñÒ|€Ša¬"ªð…n™¬éÃÔÕ…ü¥yh›¸Æ‡T6XÅZ|'¢1dìµòzF®V[Xû˜&½<©g؆g¸íƶoþâ óbË.y@jù|.÷ˆ²¯NõQT,å<‹Œ¥ð6ºæ w²ÿþcx3EH¸¹ rT²±¯í¼%:ûÜÈÔ*í#epœO' fÊa¯ Çˆ:mœK)£ì¸ŠªDtàÊßMÚR¬k¢w¨ýá—ÀõÐ÷#Г¡´¹P•…#]¦E_Š€qÊá)*ÑIzœÒ —N Lnןõä½B;©‡®{æ%u¬vÚº}QhÙyZ”2% 2xÿä¯9§ÍÌ÷¶þ°:Ä¡Þp~Ü'q²D³*–n\Uf=(ñ´ C@¥ÏÔIüÝ0SÏÙX~ãcÐÆÒ;“6}µS"c({ç#šŸçý~i… 4…X]ÏÄb1¢Ìª¢)ž„ýJ÷½¾3ª\PeØ&¨Oe¨;^úÉjº/ñ2›^ÏÖó|£=¥:4¡»R4ŠH#€PßãáŸ|Õ/þúÖOYáÆ ¡ìø)‡}¤d£tÝËRÂìÀ-Xë@mÞ>µsïâ+kDs¢©ºvÖâõÇR·ÙÁ|R©Õk&fb¾ç<Ž!ã]}™ù¿‡a]‡+Ü"©” ýµ­SDÕ?­Go‘¢°£To2ãŒë=èE¼þr2‹²Ôc;ì”(VQÙª¸H¢‰Q*XÓ{P †MÙ±‰,÷s&vú7Šà$†È8Õÿ ÓvèbŸGª¬çIýïè±óšìTZZ(…Sgüj7bý¼¾Ÿ:È• À¶¬+ŠÛtÌg¥T8gU2l\ b)—ÎŽc:6ô ® w3¦Cý"r3(/)SaTÆtI¢ê¥é“‘’Ùf—5͇kÃÿȧ¿4rÛÿpñefçE5 ´dψY «¼£ OEGµf#ý?L²(*Ax͸Î!Ј\áЯ‚  (ÿZS/²³ìc¦a ª‚yÝPN“A,}›ò¥KdißDBºú!ýj»ÎИ›ž„Wœ#7|!a®–E©¢NÛ5ÚU?§²d@WÚ÷píЈ²àc¡õô¦8ßCG6Á_¤è÷5Ü»lØrÚúž…6\ã|q¶ä| ¾þ¥N£~«\ôpQÎp¸+Ýe/ióo¯ç›¥4ióïÇJóòáͯâ&ëò&:JqFYÓ‚ +ýeÚΩ‰ôYÀþ[™¥²ÕKB‰ Ûq ÜDwsÄ3LrZ³„Ÿ­.€†àe¯–élQ¬õ¸©âÓ¿qŽªØq?oÍ·à¥a-U™Ø6Íùà‰Ó¨,‚\YÊÖ§/ŽÙºA/•²EÝýúÉùÖîl¼dg¬ª…Û¢%Ïú")6º<ÂAb‰ )˜GcÕÁ•0œÍHs4Qj GsÐÍlª@Ñì[–ö¦5)£KøÁJ¢ÆewwŠÐ’(ß•– 2u—ZÊ%.cMŒx©Ç?µ–.€ë7h~Eðjà(Ò0A›ê7H®3Õ[Q6ÅU\ÿyÉ;’†',Ûa‘ 0' Ý8j‹ÜuÇRÕí2%uÕñ¢<ƒeCgJ ð>È _—5rSÔlÜR…ûÞÓ\ùõñ&?ö$è™>­ü0ýsvÏWNéPeÓFÊeÍÙ’·IA±9/Ót½2Z2ñôÝ- “B|#&‹Š²‰òj`ñ;ÊÂGô.hU*e(:Õy´m¬ƒúçUí‹.X_ŒÉ„ø%ø’[KL+…ªlâ8K†>®ô’A€&‹ë Ñr|^V ŸÕ€§ŠÞgß”Y!:ãbÚ%Ëõ·tpUºg²¨å@vŸ"“w_ùæàé¹}}}É€ Ê—TÐt|‹”0Лë&nQz-Eªô]p@©twVå%ºÿ?Z°îBP·ÚTS©dšW“ò`Ïãh~½™ÇP dŽMXÛ ß}'œÎ¡_¢pB š ãÊŠŠÐ¡±Aßà¡gô0¸q ¢ª{€)”ËØúF«ß•T…¦Q8ĹZú¤hdIÓS‘">ÿE‰:l\Í1Õ¿b»Tý¡|ÉHiB=W/òIJ”~„ŽO>ã|zq6ï´ ôí^¬–&TÈÖhÝ55´ú‘…ò÷,å2a-§¼”‹ zþö_GËß3NNöëõÅßþ%DÐØ¿í°iªëbÉ2Õ¹Êéê+Ú|‘½ê39̦šÑ}‡2oðRX7HBJÙ1Û¿×Ú$R¶©n·M¡b\Öÿ³¨.lóñy“ðŒMê/J!ªB\Ìu³%Yš¨\© Í÷j›Ä‡d¶K;Ìu¥FÓûTÅs®²fŽB±¨ØÚYÆ‹ñD…•«RñRêÛ>€Wðã„×òø—e|D”—¨£Ñ¯/Sdºká¥_?T*ÎÛ¨@'3m·NV YôŽãšçÔU¼5ÀW¶…GœÊ¤²ç¬Ý §q6VcÔ…ÝØ–Õª×ó ¼ZÊó4¾í}Œfàðú# lÍæÿrÓ’ˆ0ÜC QÛ¶„tG+YòKT0QÔ{Éó©G2ëjv;T­0ž`w¢"S,WÊÉNYÓv\¨°—¯@J}p°o^Ñ·“ rØ‚ DרE“D(5|1¶½Xú: »i—¯}gÊó‘å]ƒkÃþÅß–ã>÷†ò¦›š=‹çWEJ·_%a;0="þð><,N¹F÷Ö°~2øíõâû>o„É÷ Y:Äuž†t>#!ó`I䌘FRfv˜nÜh›¹¾Þ/Æè%L®-«¶9doñ:wÊœâmoʰneIˆ;QQKUÓ¢â&»FéyùìDÐßbþ^-Ë>,©,ð Åç.¨wÅüûVúÔ Ÿm6–^k‚^·yØŽíPlõ«q’k™JY.ï ´w800”âB§ü°vîŒàFb÷ Ê¡¼v¥áR4_ßÉ #>6©;͆TM6ÐãªrˇM¯é{¾Œç!?…*O@…ô,_·ž%ö%ëǶҳŒ¦4ç9T|#Ó±ÙÙ‘9Ð&º‹Ÿ¢ÄEFu ÅÃïé·öC±”â¤JrFÃt@c ¿=¬ƒìϲ>7%t^®œ…h{3í «nÒع²›&Ù—`ܸtqÀ2ópœ6?h+Ó‰¥¢¥¼ –Ô¶aS§TÒ$u1–í¢¿9¾Cw’wç4Ϻ ××)òPvEÇÖÃìo€ôç6Ò5K79‘£¿Ú©HTÕî’‰‚c# ;Ÿ1/ƒ£Ið%mÿHï ‡`¤k\¢¾•†K<åFo ‹fÙJ”vBEÀu ãžwÑm½¾Ž.NZ–y…Ìž©Ï|½-ûUô±Â±ŠG œߨìò0L zÎ_Æ߯ÃöR9€P ]w¾1óˆ*º|ëqÛV‰›T½{¸1Lûq4›Œ“yðè9~ü¼*í¯S0{ ìhUY¼ÔK©šÚŠr¾]¦wê2Ù?9GtÁy7w!´ÚŠåo*¶éÀ2L(i퉩w–­kŸÎévò)M2,¤¶8Ÿæ©¤{T}k}¨‡Ü.Nt:TQ1£æaÜV*À¶=Ó?žb>Ši8{*/9w©Müæ1Èa?ŠúPL‘úÀaÍ7ºï¶T·[iQJm Ç¢êè±[p*s×Ñ·Ï«¾,{1ÑßáµßûDµaZMc]ô²¦ëúp4¶COã›0³P˜~Vf“L­tÒ¿Vj äg¥Wç”OÿyI廉üÆ<‰»N¨k‘Û=& ݨ½AjJs†yTûÔ†e¨W….Ô‚Lïtœ§[ô^ÑÃvú‹‘2(h`ê}¸Þjn¶¼JÆd*•l%ß„¿¥ÅÐàˆºÁ×^¬ È8”<“°t”HûTA*(Ššll“´.õšf`ãb†ùå:ñᨄôŒ~Åí±ëÛ¸·íÇ’.Ta7ojï3 ÷΃Éý;­E‚þªkôWuÿ.›èokš©4Ïÿ¼¤w¯bÀa1nÐàZ¸öb„ÏÓOc¡(GkÚ1 ‹IŸvŸõ‘| ZcGÝaÚgÉͼ€MÈœ;4%÷Úèc÷Ó¨¥;ûd+©.LFÕõ*V²®ãà{@J?vµR*Wàž‚“é3@¯“%‘|Vƒ¢Wš©qß yc«—ôà^ ¿qs?ñûGD®~ È=âqÄ㥮ôO÷L`¨’w.Ïiü/®â0*»\kT?°æ[×dœã|ÔKRiMy8\‡âTà\êP8•oö¯À©¬9Ê•ZÆ¿äSI7ñP®Cº7KRÅá3®ô~7/Û«õµ y‹—LÙ œ»ËËÚìåTFjލœÛã]ßCÕW=)¼î,ëD†]Zº_´7E.ljÊ“†c´9«¥«¤]Ù03½Þ'n¡iÚû´èz£ØZÒ­¦Ud|´Â¿¿Ç]²í›«8ɀУ¿·<ç•!Ŭ0R~ÛµÙÊ‚˜žB”õƒOëaŸªÌ·v% ú³;«äWZåk6q6õC6dEµmÝ~­i=tÁ²C'ßÖ_†WëÏixÕN XZ…ë6m#Å–ˆ—ÁD3Äu,=›rŒÉOR ðƒT3W ä=ïeA¶½`æ¦Î0cïÜ7–yä-eð@šN'œsŸUY5ök9¤Ò¬1Íít`?é«ÌŸàYÆ©rrXáM6,]&ß'+Â)ɇ¤ØÇªêåPÒC¢aE¤•|tEÆï²ÆËD¸„I=¿Ë=–%Û¨ö5‘%:‘ùSó°Á~¼uýŸ«(ã 0‚FËß„º†¯_TõôeI¸]Ù0*‚©üÙP¾]k´‹¾±TÉã™VäÒåZ«‡r¢Ìk/—|àÃ]ˆR×6NNïœÈ-z}±“-ã°3Aø…¶Á@µŠž.5º˜ÚUMñPÎÃ*» [“E’ÀÐ}œü<Í}b‘'îa1˜_CÏ'ÆÙ©|ˆëj¤´fSeÊÂ`‚˜–Ç‚§ÎYÅ|Èë⤴õ™ûÕ"•„V5E´Rþ®ª—?*´âYÕs¿Kˆý¨ÆšGC¯µW<Í–çmÚ­ËZ‰­ QŠ!¾í¹Á°4þßÚ7Òâån¶&ΡžýazÆÜ<™ü¤ô£é8Áãndé\X8«¹ ]°N[_´ì]‚Á¹IÅ&]!´Åï6ùù Êö7”´ )6bôKOiœ>éÿÀ'›d>Êà#=èöÔ-ÿÇã(c–ÿN>7©kָƈZÄsg*æ’µöX?)Äs)¤8hà8g´wÿwÕàa¯d+¹Ü´ƒw8hÅBÚl›/pjÐ;[³IÒ°4KA/AÁ§.¶Uvø: VY®}tØlûÞ¦ýÇôk¹Ò/J(ŽÀFÞu(>fS{¹ËáŠb£k`®2è|¶ÝÕ>lÓÞ¥ô¶hôª¶ ÈÝôTÎÌ×&¾…˜ž2@ÕV+®øBE¾ Èži]ïúmÚÎ&襳G.8ŸÆŽ¢½dÒÓ`(ÓÜèIϰ/Q®–f£ÊN‡{—jB ÐlI]ÃøÛ ¾Œ ûè‹3w¢…ƒ¾­ú9Iš,l›fг%]F•%àª7Î×÷öì8ªªšî%¨øð¢à|-ª"5…qÙ-µ~›ðÝ´ ´ì×9ý‘ïZS`%¾5X¢Îùš“v?lâ¡]â¸Î'xuÉË¿tG'çñô2¾_ðÿÒn¢•gô0…¤PD/òPAb#ç|ùþÚ ~HÇK(i˜pA\¬Ÿ¦y€R:ÀG¥JŠ­‹»b¯‡µË6‰ò”zЛBŠsXºŸ A›Ö–S@2 jü¡!I0gÛFeQ„k'#øí´óal¸¾VoûULRŸ”ˆŠd]Z Ý즹Ÿ‡yY¦ ¦©“ŒâüyˆÒVæ3t ÊàZ½`Ï8QM×ÃÜAö%ö”:le"²}s¼7TuÎEÞ)J•¬I?ž²'Û€Õ›u#°6ÐHVMšÊaUÕVƒR¸o×¶Ù2º°†°‰£O ¨¤(¶wHøæg#X*ÙO#­v3r)æúÒÇÅË¥Ëù$¾iã2VÏèW+>÷—U¸u’æÁvý*<Á¥9•¬î„‡½7Î…v]%z¢Hɲ¬jó}‡½N‹]füÐÅÛú¨á‘1߽ɾ^Úµ(gA'sC&µ)5ʵeVï³4D,:I@u@Í9"Þãñ¡“þÍMe–±jè¡jòë1_£TAѳ¡-µ•£t¬ ûÀƒRÀ&úEôÕþÍß_×…²1¨UQÐktÒ\ä%ÚÿôšGÁ+ÓšðíÁpóaÇ \@`qzа m1õ€Ré . ”´S6”åÔ…«~P`ßa•€ŒÌ9¿ºs›ìChîÉh™²CYNûÙr 2ç Ñ]5 Û(‹Zì4à8,}jžó]ûæcþ­ ä$n.yÖxg„òÖ–…´l.KÚ˜E;ê:óæ7pÿHŒâäÞ/hÓua°ÊOÚŽëDÏÙ'yŽ[XnÕŸ×tîÕ××ó[&l‰ScßÈ„hÃi§J>ú‘þåTu¹‹ƒd`mϾµ? ”æZ £é¢ášaDSuªa¥ãªÚº­Ë^í"´`7:4mlÚøæ)õ{ÏAÁù9Red7üF4oªš¢¶ÛrªéÒuÎÿ´¤}Ó˜[Y:ù‰ 9öVãßW„-̦²ú½ŽÇ}T”¬mŸ¶( ›Î¥|J®'.¶w+a¸òŽõ›úØþÑîá¢6Ê%lV¢uKÆfd)Hß± RõÖucÚvY¸ ’uƒv9í! .üÓ·Á¹:èOýÁ!V4}uÀ;ôêâ&‹«¨Œ†t§ê‹‹ ¾2”1Ñ‚ÞYpßÄáŸ?´-kº×J@u™"Y×TafkD‡tªö.ÓŸX/àîd:Ø7«Þê«…è("íÖ²±À…(ŠmÃÞQÄŒÔØ²>„¨´B+•ÉÐW¡iiðÐP+ƒ¢4ÏRúÎ%ÒDpwë:·6Ví¾Š*ÙFÀV0„Ų ¥nÜ#&‹9bÖªL€wx¼ƒ´'´+»µ ›|‘Ë×õM¾Î}4A5ëŽ/V»/"€ƒ3¢^•æÒ0ÑO»1òqªdøhAšòèðÃ>¡!þÙ¤Dö¼£bÝ7ÔY5£ŒðÝ÷A Û¦*Uwa3Ô^ïæ*ýå'Ovè:Ç„œßáȹÑXBÍ»éé¶q«r×aã(ä: òÑ%ì^ÀÒ;ž1˜ùö²%ì´0@Þ®ñ˜g”×”éT •^Ó(¤ ܦ}A–n]0¨+iåí†ï*Øhì éÀ6Ú¶8§;S¶¦Gõ‹ÞZkÆEg;2ïõÍû]óéÿ¥Z¸YÕÖÒô÷vËÖePM· ÓÚíK r8=øPø§©Šå݈±¨<(41¹ Žòm 7±ad, â×UME½ïKÞRÅ ŸßÇ8–ÍS47ÑÇ[À×âz†íLµU÷¦g;Ó%‡]³ªiüãš»uÅ÷¶‚J"V¶<[žCÂ:޳uJÒ5îÖq’Ó‚tÆ®>…(=~¦ ïÃr€Ò¯ËÄgôã+haõŒ«†°\©†¦¢¶É«½XÓMŽ\þhGAÿðp±O~¬”4½‹~ÑI /’îtʨˆ§ŠaZgdb²&6Z-æAж?lþ½‚‹|#*ä_”{ºðáܤÿ Ù¥‹#T‡ •‡ÌBfˆ†M©˜"!e ûž)#¾kCIÂ0‚CH¸â»Ðé÷kûÒB§e!9 ¨4@è´HszÄt¬ÕZ°t&'>@Y>…Ní‹‚F_Å´¨ŒÅ¶Ã½ Ðâ<ÔŰæ*#ÞXF‘Öó¹mãA•õh‡œ. GKù­Õáë:o é(s(Êú…|¯êi ÷nü‡%? å19zÊÐm%€IYðBz”3•ØU>-}ï??%<‹í“°fºU2çN¢èÈû¤!• Ê’w—íʘ=ØìN÷‡©Q!€jÞ*ío”Òô]ÊäegölÌ´¨¦‰¢ 𹩤dW÷0(~Ч>dcOg€YÌ­?5ci­Æ2ÚP‚±[NUTWU’ äæ÷ëz÷~ýþ×—vž¥§Á5Òg_kÜDóg—OÏÙ·Øf'(C*ß%4æÃ3HëU™©-Û‹¢%4™”.:>tÏàç{±(n•á›SFn¯¤Z–åÒ^¡ŽS9´k¾åͨ×ÄD³©ÇE= .dºH%}éÌžj®žr$%èµí•šç$ª!HŸPbÏó)†-.ýnF„gçâ&°²¸Ñ7€K!K¾4ðÍ •*Š|휮¸kùF8–cÓO·òÆ»ÞË÷áñF‰#˜¢Àï4Ip/jQç÷0Ò‰j½ª ñ/ª -øð¥Îµë7L޹àî™AÏlr: K± -m`³M©_*XÊ€ó‡þ‰áŸ]†µ9°6ëòUèûCN­…~$iŸ&=íY•†aÑwú¸SÊÇaŸNÑIò±Í3sg DQ¹@Îb<ôOñ–eû´Ó5—mjšé‘%a?ˆT$ðZîŒÑ·ô/…þ¢^÷ÐK7Œ÷)Þ ýÝm¶ÿ ÉZþF“•4ACñ½ÅÎ3ÌݳšMŠtü žuúO:þi¬f zº(‡˜—ÂÆ„Õ_§»¸Óõý~±Gìë…Ÿ­eC;VyÜgﺎʅ™ÂŦ]u×Ä 6¸Ô[—ØÉÇhâK›B6fͦ~!‚0¶t¿Q嵫µ;Öô£ÐʧZƒuö•üÇãC¾¦€Dy2ŠãQKÃ'.âÓÙ0g`¡M• ´#ƒÓRÉý ³¶}ËnbX-b«ýœò[u5MË^-{¤Bùò0È Ì`&Þ‡'™ù/ëÎñ^wÚð@›Þ½.8ón ösè²Ô<æê{í@ˆ€\gÛ6©ž~ý¬X<kÂ܄۴qÔöm7½(¯Ú˜ xLŒýسPV5ª.ß•€Dlªß YÐ?ŒtìOËåoL7ϱ!tn ¡Â*Ñ26Ü‹a×5ìâa_dÒ•ù°Pu.aÇø°\þÚX;G²›j¨qoyÒK?µè·–’Щ›ê¥Ó‹šôh6¸}Þ±(>Ñ]§TÁš„-êA›%RVß©ÔÜ6Ø"ta²ÔÑ1=3ŽB~9žsû‘ŠÎoÅÃÍ^³ÆûÜûí³¬+Ëaª“"¢ %K{,±§`'¸€¿—:Z om´Ñ”p~ÀøpDj´æ0}_æì(»PPÚ6c× `Q–DXU®ænÉkÕEC©¿:ú‹to¸âqxL¸WgèÏ–ío, `AÍ Ç‡Ρ´ïšçT’]¿^Ûë0V $ Í&4°(0ϵ´+Ž5¤Xªâ†rú¬ÕKsgcIp3ÎTì=Ù˜ÓÊjŠ%}‹–;ÆRUKî²ea» e½Ë’”oC#ž%¸ç,þ‚B¢Åz&õ9qx÷jò¢‡m™¶nÚ&¶Ê“Oµ‡Kù%Á PþûÓîký:쾪ªDëƒ0(†}˜&c©úQ4ƒ¶ùÃE§…Îý•4Ý–Å#’®`[¶•åä·WužÅ*kÇ©„%ÇJ}xÄ ûbÞø‹®ºíù£qÈmØ îE?õù¶NSªŠp”Ç¡´ûa{ìðø°Ýs˜pR„)c5sAK¤iÁM òP&+tð«•rÕFz]Œ”‡÷p gx1îeòûëàSàlÙ]çŸ-Õã}#º•‡Šµò(™øì…A×Èá׃ø|%/-0Á¿¸ª¡ Ùk2£*§!‰ëršúOüìSìSrþù†Øä‡TÜ[“#xi5%º¬Èì¹ÛX¨¹…ÌÎ^Íõ Mkz>RÛïÓÇÞãô_Ï>ä!©Å!õ™ŠvÎ>îÂY¯§Î*èA=I¨Œô\9lvÇ­NÃmÍ—?®ç òÿ&X~È­‚î6‹-\:<+6\ø &!Éç¦/ >t#å;ü'“yo¦)!«»&rýNÀ.¥`‡çaWúNÄ!¥“Æt(Ù¶­ëç•¢}Ü B×LzŽÞš}×N]äKÓE9 ²yb'ì\ïMFb\§C"ÁØ>»MDº‡õ}IÉÃ}·‚Ñ%³|Í„‡šl/³ü,\Å8ToÝ*rŽ‹ÉR˜Uû§ÙÓ­y=W¦ìÊÏ.+-“&KB’f¦ šrˆ¢Õ_Ç…¸éd9‡c³w‡Wþ—!äz !ó#nxìAä\ ¬“^ûaˆû<†5_¿â¢.D‘>‡Àx6ÕšN‘üpØÇ±f¹`BŸÄê»–ìû%\e4ì*°êÛö€ðäëÞÇ eß[;Ò'×OI·%ÚtTq<ŽtÆ·nA¶Q_b(ͶQCu­ÏlÕk–fó 1’JA:8ô¬>•ØîeŸcüâÚûü¯¸1ß+ýÃÑ /N%«qbàŒsÈõë^qe€Ÿ¾Ñ£xä }õˆ;Ÿùð4äyÇŸÔþÿL.`²'Ä‹vpØ lýЊގ2¸£â΢ôfSàk°`ŸéõœÀÍÈD'íS½D} ˜}¸¼äT³T|/p1îA²­x¹Ñ÷j¶Ä#ò:{W/årLøwФÓ_Ã\º2÷ÎÙ¡¸—k߬Ãð ìG†PwØO^J¨pd><”ÀÆ!鸷¾]´_šSS ˆÊª¸V˜h2w[J7/m¥­Yôš6óÎSh~ÀÚõ@‡“ †:ѪµøÂåËDg&+kŸ:vw§%ºèLcˆ}òÜ»C/«c±IÒ©ŽÅu:0³Z+Þ§-E+ZPž´¨ïÓ^Dp;C¬Ç 9Me{‡ j<±'Ëcú%C6ucX/˜H&<€£ÏM!Ý ¦—žõÿ ù¶²nÞA FFºôbEoV{9@Øg϶q”Q‘k€Àí!Ç9m´Í[¢…OõzIK!NK¸ßBh)k=}ªy/£-ÇpÙöZ’7Jf†  =iD×ühz½ÖƒF—Z¨=7¨paЩº¥©TµªŸÕ*k<‰kòúFÜí»k[?¿^2,á|=oæÛpñOQòëùNù]¹I·Ï¥ÈÀ™œÅÌÜSÞâ6(bE^©)Ë\¤—XL´bG[™Ôõ4­QXi0 @ôwJ¸€[ñ.^ú|ò‡§daT5E‘ú ‡8mGYœÚôL–}çpUe­×ô}È„’ÎVï]ùâÒ÷ëGë®ðÛÔ^s-ë®äé˜Gm3/ƒd.ÔlÓsÆ;ž™ÇIé„Õ*0ËÙ¾¢ HåÙïM&y¾%*Ÿ„¼æR¶£ZhÍyÖÁ{ NhðïoV¥@®ŒlNFEP—A‰6ý2FH‹õ¢®íQJC=%ÞåÝwâ‚vK‹ëª£3-Îç(Ì‘7é°ä±×œ f÷Þ5€ùbb¶ˆzÓÿ<+@Æ1ÔéÙ¬µÊÇ.÷,NC„­Iv(xãÀçñ˜ì²€¼Ù|ÿ³¢½–Gõ\2á±@Y§u’Í®ÿd˜Å×Ï-Š ú‘=EÂrÚ"5H5MWÅeªá¿vƒÞ±£‡nÕÒ=(,õ@õjÄJQ:'YÛE›0¨)£ì§ëÞ…¦¶PÌeá‰VÙäô»;z£èÇóoÏâ0°f+l[ýBqÞaªi7|zLü}#l~³~Ûg—…`b6¥ŸãtØ+M5r(W™p-ÃäùlKý !êö7BÔ´žç ¶ràÞf>N üÍoà”å9Ï0y$Ü2”p¤?fËUtÜcü¹”ÌÀ²‘b§a˜‡dÀc¡ç·\ªæUW ÙW0\ëJ@Æ*—q[TÅXŠtÃéÚ¸d~Íx"ƒjeP7Œ˜ ”ÑÓ?ÐÜ®)#š¦©ê×t®da øxŠÆ¦{Ø7XÞM‰€=U¾Ÿ"üZ 0a܈.'³cò0\ó¾ U•ä¦JeQà¯]6Õô4=“·?ÄÕ֕;¹T  T¢®™g¶Õ2ï´A›¨K×~N¼¦uÚ¦ÏPô¹&ÃÆé|´Ý/Qâ<,©M:çô¬–g^{÷¯”ñ£V¯G™‚‰–‚v¶m¿~Y"ƒLæ*‚Á£›¬i Ï{¸mj¶ª(Gö`tþ8‡DçÄíߣ”JYÏ€¿3«Ó¹‡ o`Þ~ò¿$-r«ý~½ÇGÓì¿A”ªOˆÒï–´ ç—ùòYXSÜ „¸4 [2ÆÑJ9èXÍÕñŒqÃëW·ŽÜ‰¦û²²qŠwÎBݲ!#[&5õ2ìÅs±7zQŠ‘ìFä¸öMïÍ8;Ä¢ƒóÔ„ù®lY~—ƒÆ(@ª¼®ëm«ºA­¥‹¬ë¸„äÐë:ú\¦÷ùùĵÊ?¯éªÁ&\¯™×9éõÐkwš v7U7R¦I¤7&íH C $—§÷ùR58ëu°AÕÑí‡vÔlz£J¸ÌÊx ûB/ê;TRa`šGâe{¼ù'L£WZæ³MÇЉ+íPì{5îmR&­„L B”ÆP¾ ó(ï².¸%¥*z *›TïÖ`7îS–t Ç|ã¯ÄÛYÕ¥àqY^D‹š¬Ý¢mNªeÚ‰ş̌JcéiüÝBõk;µé§— ™´z’‘;À¨Ý6MÝ¡mìb`„cxOѹÀÈय”ÃË\9eS€^ÔŒý<.Ó2ÍŠ÷²l¶=ìé´j­»<šw%«£¹`¹tüS¹Éº“.Ø”ôG¾h•À‚ðñÒ×|‹)º’VT S´[(EóÊkœÛóý>ˆôÏZµßF´[•ÊÓ’âëÒÉ,‹RdÇ·0ȤPp\pPÇ¿t¥g.OJ<¿99LXS@¤‡ß`ZîKªŠH­kѳOð–´?–|n§$e &-˜áÒÏš¹†xM[§©~JðLüKp\-ϸét±ž÷“åg¡ˆO?z„ãúJ#Úi šiy<¥qE‘^v¥K‡†Ò8Jo\÷á]ý´ìœscÚB ÓÁÈÙ’ʽ:Ú<ùNUð·™ÜG.0¸.²NÃ?‡9wk xQ=lVÍn{­¶‚~(çjQ‰¢ª+Cv+KºÐÈ0CzïÞê6J¾(‰7²¯‚2÷šY1€KÏ”¥ ‹p ©rʉ%©º6(;¦¤„*͉èŸ#àíGû"fÇe,Nq¢g¢¨¶)ÉæR”áiMHíIÈœÈËDýžÉk©È+•×V߀]@sæã°D¶=óÓ¤×Á¬{¨¯RÖ1œîp¤âw¤ld©‚È >¸Xiø…I(-[4‚Ïßýj|1¨-Šd¢¥½$àЪ}Ï” ¡à¢¯ 27<%r<ýußDëúÒ\0(&ÊÀøÕi´VcTnJ¶Uð>Ô´zNˆk1Sª\ï0¹UCïÐÅkdRÐÔƒ–@Úkʱê—1l¥ÇGKzÆ’ šÖiÒpÓ€Y(A®-Î"¯DÌRÎN—vìi“ŽŠ0ýŒT´a>d¹tÿ8W¿øö»Ÿ?«€ã€‹ä·;ú¡Îãl Û8_³0¥¥pñÙâÓ4ç ç®Vžú'%œÌé§¥Y:Õ§{QÌõXe¹¨¾Ó6‡à%ÿeÄÞÉǼÍÑ2|ËçÛ¬.µQ>8%îs1ÇyªÂ<œå—[ì @µ€h쉌ýC^íbôÕÙ=ká3·ç{UÉ^7S,Ç‘Jty0ÇyÜç#·p¹'7J‚á1¨±†±bî_çC¯ÊtL×)Õ"Ë>݈KnÚ†sH/úÆçÜÞ*”ÖL÷‚ÎO ͯ2ªba# Æ8ÎdÍ2–Ð}zØúIáæu#Ï­ÜÙd ;Ì.)ú6ðRÐvEž.}Ãr®[s)‚}J(¡ Fé`úAƒAX&h½DjÌ4¾~ºö@=Ôôû‡r¬éOÐØ±€¶ \æ[7¥òS}'ýÍ(’JæÂÚ q˜FÈSñ`¸W}ÞL[—©<ûN¦@Äüxª ïr":ÉÍ(«@¢c#]·ì£ËñxönŸ[Š$[¹eÝ:¡^jZËWØÁy[Þ6ØWóò†ƒSpÃ_¼á¢vÞ†p¬š(ÒKz€²CQÛ?õ”ì«©/‚WèFFtUTÓõÛh‘6QõE“š£r¢A¢ˆãS¥àî‚¥f^øÛÈõÀÛ"9*Q«éžÒ@•uH9ÒPõµÆ’PUíeP|r÷Np† Òù´ RS7loÔ÷‡ }¦~-–:饕æ»Lj]¤°†é_UÐf@…ÕÏ÷V,&]¥ˆX±d¨ÕPÏÕTÅõñœ6€Á”ÑÐØïã9×÷×ëû¥K9Uv’Oâdšâ"VpJëºh•÷É£FÔ-ô¡tÄ1ì©ý z…г”J+fáuvàvS}µ'[’„aWPb+KRÝF&UDÁI ÌH8}¡ç:ÍZ€ [ŸNP|ÚBœ Ë…ÃR§jK YšõÀÁÏò¼£Y‡á½«T¥¾)L½žâ΂̳Ɔ¢ãÄýø©]‹¤ž²)¬—yn†4œô› :ìÕpœ]) ç¥"“íEA€BÐWc•Ìý6¥ÓÔ©n(SYbô"¨¶Ã8Ǻ·*h«ŠE ÆfU-¨ýLUâ`'ÙDEG4–#·?`‚ SŠÕT¿ù' ñcú¶r@E·&+Š®—FÞæy™¯«¢; K×0-ÃrýãªÞã.Ú´d!fÒ˜gB)µãž* á„Þª´‡©ŸlTñ¸oçšnÁ'scÞüU-“öÜüMRÌQ;uëT 6‚Ͱ‰óðˆG÷Ëòïµ+=#̨X¬©-ÀYu”Œ b¸¸¡ú%ÞEÅ÷‚¦+&äþÕLúȾ‡m×I©¢Çz”–XgªüÑó:LcJrm¤“ĺ-´‘ÔÜuSUctŒÚÙ•{È…Þl“D<«ê?Ùá—=…fA`뺮÷lÝUÞŒá@¹Îœðî 0P•…485€® îßÊíŠ@å8åž6^CÇÃp/:.Î< ~¢ã‘• [¯yð&z¾å´&y=T[ÛÇÛóû ˜?±Tädýã½O°¨p!X¥ ÊOl¢Åµ1~SK9EÉ^&½^Òq}O€{*ëø7Íê-u×êõ0ˆ±~4æŒÇÇnjÙLÝ—† §ˆ/tG_z¢"v£{_t8¦ 6##qo–º÷V OŸ^Ñ/ã'žºéùSÊÎ̹@`Ó¡ûëÀ?Ô”`6x4s¨‡êÔ_(éѧcȪ©‡ˆ"5e·Ò• , ÈŽ ñ§Çáñ w¼3"añ†gÌÏ Hÿ¥^ËT·g*â½Ù[ú[œ¶rŠË51(€B\þt5º6áep”‚î\M/Ù”>›¢˜ ‡…Þ ö€JË2 ¾k¹Ç%oø§Ð (ô>áË7÷@€wìÙô€oŽ~žC*ª©ïé_ÂUÖuú m óðŽSÚUÕlsÕë»öIŽº¼_ßÏMp ôJ¤·Ã!ÜGVUœ’Â}Ñ:¡ V°†d¬m^ì»x ·£Ó{kGsWIºÑ»t£Gá©ñðXÚŽ*nólF4™Ié rº¹È)ÔÞ${CÕ—‚Ìô(ä6¯çûzÈ›cÉCÖõTmiØj#L$ˆ¸é㘺DrÁMr•!/Ï(.(x@ȸîGFÐÑ÷)WU¶Q“·ù°ÅûÐþyUãW!×íK“Ä󜭳‡E7ݘhý­tM)ÝcÝí‚™…{¶k± ôÎ|î¦yO?ã91×9>’X "ù^ã9†$œÚ(¯Ž%-ðpé Yþ©s÷)fæèYÈXQ„Õ!dÒ{­Ö¶Ú¶U­©X­l‘D¿›î¸SkC§_…ƒ©$÷ÂgbÝU”r’{¥É\–)Õ^z˜Ik:Ä€ÐyÞ-í¾N&ªcT²WuŒèùY—t½¥m#˜YäÇŽçƒê#Ë:;©wÿ¥×v2éU–`É:•RÕÖW‘ÆLš7tÙ¡éà·nÃ]j‚ŠxÆ Ç9œ’J Å «t\qî3% E¸G{;«¥“–/îMônè»{î‘[Ö§Õ÷sÓãÁ$‡ï/!Y@gŠ("§ÍÑó.úIélÒµP+ùWOè>ÊÝ z\Ô=D÷Õ4P–XÓý¶Uc:µí6KÞ껦 8úiõ}ýxžŒ2†3úéÔÚ| CŽ8*³.Ϋ>n“]äÙø3ùÐÓ‡‡_p¦_¬öoVØÖ…ªôëÛh^¨ØZU_ÕÅœè5¹à° Ût ï”FØ¿¿ž,$‡AÔSCÛ©F¬‡vœ×a¡û’öû²lÈ hw…K¸¥Ó:eéXÇt7ú3lÓ¿ PÐ1åJyÉ|ü#]à:X_çúfWQõn!êLŸ…èuªÈçvö±Šj½¦ipÐrl÷` Ý¿‘Ó)Ùß ɾ*ò³[AK`8¶±0 ·a‹Z^”‚ (¯lîˆã|ð|V6îî î+ :-eTæk_,ËÀHØ0,FY‰£i]óDÂ^ª¬Ïue‹†)Ó¥Z23htie-Ý[3%ZS_ ÐáÆ¢”ïೂfÉŠíÜÚùôûòÿ„(üíàQ„`5²ÆIÓhëwIæc)‡ß® ¬@p’.)'ç³›¸Xl ÔÄ ;ZY_ÏY8QáS—]üÇ%àWP×—fU[€eÙÔµh&gÍÜuQTNS×Òç’oï0¬ M(ÌWu˜v.Ù~ί'$}*æxIÉØ›€BZdy_ÌÅé&î‹f ya—‚´C×,eÔÖ©„i®˜³=Äöˆªdè;ãî>½ÓÔΨ®9¥ë|ßWY2€ú]+TQˆr×þ˜Ý1úLúE‘­Y0½—ÆcÜÍm8UT†m_Ë+…ó¦ã}òcB¦4/ØùˆÓÖLVÕÒï”cŒjG?N?¥cLD‚‘y>å ¾­ÍKB?؉J8´d§àqÖeXD¥ŠfY’îR`j ƒ®(ãìiwÓûÍ¢¢_l9gȨDÃINR»­5}üV¥ÕÜç{/Ç¢.ÛÛ¹Þa…l;—¶x±±<\Ÿ hK|v48¨Æ¥Ì/Û²:+Ƽ«ô@"Ÿ|Ķ{Êœ7ÞÆE>®º™â¢iTÍÇs‚¯%%Tt5-ÝrΞ¹Òë²Q“ãSÀ?È»æç-²ŠÔ³‡ C"zöôµ˜=4÷Y§†nÚÇp” ÐC@EœÉ ól]þ£7á9Ìé¶h]*ÒFÖaaÆÇïU[Žýfër¬ ßî0üjš97B:I›&ûäÌPèê–·È>]º7C­²¬ ³Iî;JV)ÚQjR œ‰¥qC‚6Æó‘0)*Æ(P©Ïo•‡û¬Æ5\£&mYÔx ©¶]Ðì£Nñ¹ë¿¥Pa¨>zFTç üŒ¥£—º^¦2Ý)i+½¦c{Á2Óiļ:‡…qu:7˜ßu`Þjã©NJÊG8Ú†ŸP@Ž¡Ë¡¸õ!˜ý%@•°¢y “&ž` a óÞGUN)Yy ,‰a•ü°¤»æWšž•?™ö¡éÚÒ3V¬M—ÇÞçªIæ¬Ú®,e=×2¡áå3~[w¤×~\Èh>â)Åe£ÖãØEÀf(JFÚ*özÞÚPÿppÔ-ÃÄ<ðÀY;ç aþûªæ.–jè²éÆy ü{[Vºê–mÃÝ4¡C5Ï%…û|höd «Žÿ “îš½ Šaþåß¾ÿÏ*Ã,(h°Ëcn{žß—S8$Ë´otDó®ÕKB¥¼^÷°ô…‚ÆYöSEE@^I–U Ä„/ZVQº©¥8i—–²MMÓ†76åÍðc¼f7û‹W•SZb26…×±P-N鸫eÀüs‰ûT™3nÖÁYð˜w1š'û¹Bt®àd”s¶“â-£2UM¹•Í–‰^Ýr`Dá~ÓI»ÁÍ…§ñŠ~‘¨+ø»FÅPÉ60ãæ9èõUãf¼P•Z1´„·?4½ºjˆVJ#êxõ÷ñ¨|¤dÏv݇ïžáOS±áU]T <, ]IÚ>´WOaìÔ»ûÓ÷÷ótïp1U_Ê-+þ–ÙN;KQ–+½¤ ³€y`šNö'hî‹“qí}†äáн•ÇL£bû$N›mÔk"Á 0óÍ+½¾]¡Ú¥ w(õ–ÕÁxJ€+TÕé´QR2W]ØÉ©,n*ÍàËæÕ*>?ÏèWä¤4> ?j—/€áÐÝé<Œ`[”Ö•õXø·w ¾Òpž¯‚á–M%e8#K%J*f0ª‚n¢ ú&Xù ¢XÜq„´mÅkW¤*úñùXÏS²ÄÉ:Ê uà°ã˜®Ðӫɼ5 Wîn¾^¯0¡sŽñëHžP2„ªœË´Žó¥®Ö’JYTðÚ;ÕÙ§ŠÝ>Åšù|,¡‰WƒÒA Ruuºô5}õ0])´Ê’éZòد޹š27»ÿgo’,9rd^¥—ÜT‹c–¿zû]Äÿ ó<úé[Ÿ*&ÏŒ #‹d%™"–pÀLM‡7<åÞ#n9FÕ\²šÖ¼&*AšeíR9˜® @+Ož®$ï&3øÒúûLGŠöÕ=o&!3ÏuŸNQ=ɃbøÏ®£Ty ßø£bq/¤X¬p1ኩsÀ*hɬîjùöØGÈè=ø·»3°y´‹d((í¢8Äfä®ñ8p»¨ÝhÝ,‰F:[óþ¨Ì­úÅ´ŽÔѳ®ÔñÏ[rIÜ&tñóª8EPò¢5x…ïÝ'/oh¾ì*Yx¥5E¾cñ†9ª×H-qeª,'5Ɇò ß1 ˜Â‡²±;éüO‰Âi.?Þ÷º’­B‹¶…ïêFh†“ÏjLª\ÈÚ@<^f8ŸNïû…=…Pég0Z¥ÂWS¨t1h. 4¸Me§c^¾È'Ž›©×_õ*f¡^ÛE½–c%Œþ´¼Ü‹z}1À8k<,SÓ¹HwèÖ­9%Szj(õ]Êu•Wû‡R™òC.øÔ{±} Ãf HwÂ1¶o¥§W6jØ"Ú`kÒ÷á¶?¬ã`tïÒÆ Ži«ñÁLÔú-àkˆóÑoä¾€xŸ§áDDÿ±$°ž w„o™ÙvÝûϧ#/þùuYí¾]Ò'Ì»pž—zÞº$ÛÖhà$ÞÐ,ŠêÀáq©ÞûæÏ—Þ'í,9‡¯Ïv!ا9µeQÔeT‘iY3pa“ áÒ“Uö)Êô~ÙcŒ[¾aV7u¢â¹§`¢§tLª¸à%M*@ FR:§màüë.·p¿ë+0ʘ§îìÕåíÒ¶¥êèoô¾¤ •caÒl_“WþÍþ»ßRg0¢¥/Ï]ÚùE•©aê(#›¦©åm‚dðð\Ì Ü£EæÿcŒA¹¶)} J¾;³P{öñ ¹Z‡KÝt˜GjQoÌÁ¶@župı©/zº°(cŒ–¦ª*Yšf;ê9çþt>í8ÑÊc–eË`¨Uü2ó—$STµ‘¦ ²&…¼PŸ:&ð¦|×üS}‹È&Ù ñ-ß1Õ\D¦­}\Ù(kbœgºpÕ \ë„Ü¥e(Y~ËL«ÈDÉ£¢]í[-ËÖl}UrÞMØ0.+@6~Ý!ö]¼q=†â9üM˧¸tš0v¬úFÛÔ–:šÂ}M.—h:=¬s’éÞ|x¦Ã“á¬@¹X1Qšž³®7olôÖ*u(ëñ¬b-H‚‹½qÃ:J³U€Ø·f+ecéµN:’5=–iõð(¯Vë}ؼk¥‰ŽtËé2ÀÝâ–Ú”QÔvù¶ëƒom!mZÔ…(&Á)â|¸îêÓ"7KáÃI×E-˜úìk´%E¬š™ ía¿Û\× =œ}jÊx7ýBÈÛEE ¯‡@^{È+!7Mi#/‹Tq‚Åï×¥o|‚~ÖŸïS<¼,iMô˜D@*£ÔuM5&m2L‰¼Oh~²læÃ:˜ywaºý¼Ec¢Êˆ)C/t`Ä°æ Š[`ÐëM T³Û0ǰap”Ú®ñ{ é®…Š1Š61ö>¤Û2•Ð&2ü¨„GµÍíú[û ÛS´@(h‚pv=ƒÊ­Qª¶*Ò#%óáËš&|à¤+ο,{NNï‘Ó\F¤GN#N¤hÈ8 k:”Ö¡aéØþÅø;›¶ÜeøÒl7ô“íà;Lj§q€WY®rU6ù’§E“b¼(ñ“."Àv|tó*i¼ )ÿþz‹†vŒ¼„¶’[³]‡>×Ù˜tăÞ ìvßÙÅã¯s –¾Ÿú-JŽq^Y»ÓöQm:­Q>÷y9ê*­jÙüÖÇ4¤…†Þ©“è<>½=Ÿ_¡ƒÒ墴“«8+¶ZS?5]ÅrmÂrÁô|B#ȼ+÷¤a}Êî‡XBMé'ýr uvË|YjºäãtÉæTÕ¼ª ñŸ‡mb vÌjܻ Ýï êqí•W5—Ýu5t{íEEl‹Jªh·z˜x÷Êë2aþœ~mÞGá-*µPÓý”©…šî©S›B§6—_Žk˜6}ý³cï}|2û› >)e€ÇRËj„ÈÂæUUá× ËM¿]Óý0øÄ0ùàÁѽÔã¶زmA(Ùê±­¢DçÕ˜í?(B Ít5gÏÒ¸[Õ±PÆá7ár³!÷¦ð·Rv³ÕQ˜–e$µòNZJKèQE´ûî(D9PT8‡*áß.*Àº±+Ö„T,£^=ˆÐ~° Ö߯ë ›¤˜R‹å%8j¨ÚRÇ[ßOI&ùCÀ`tÏ„ÐÒÁäy|œ(hÓ±ÌNT 44B›±?NTç×¼]#º¤ÒãZØ Ô‡õ©ëÝL×oÉ#KÔKéÞf9àz ÚqÞCk)ÓÙÖ¦}!a:ð}t)VS5z`3ùz8—½Ö}c!}ÇpæyFˆ-QAÚ·cÖ÷ºUS¼ %%¦òzmÃä…þâœSêÿñONðÏj÷Ö8<[L…øN-©x®¨, ë° ·¥—\… DÈP,ïÒ¿õpaÄ"V,°Ž`¹:N"G³V´_“ˆ«.›B§²h ©ýóÕso-6y2ú™ $’\ðõR—Öõ¦³5k—¼íRÊ,ÖŒK(øN9€±dôãâK]$§ŒÍ£ oæ–½¢Æ^Ì‚¶žÒèz¦¤/¥]±Œå¾ªÉ£ƒV÷oZÑ7¼/¸æû„•²È‚¶ÂÀÍaîÆ4Ùˆ8\Uºö²f¹ú«‡¾ÙÙŒ¹…,Lš8=‹3üÑñª‡½Cº­y1Ócêv˜»%–/ePã° 9šØ8°÷ØBðafsQF€Â>ª¯¨€¦]»BÓ[–4auíCæ$pí³¿#—ê*±e÷‚8M‰FÌÒóÒ Ó `„—¤ÊqY!Ó-ÉRÈçÂ'7Àu± Yyæ¨ÞýÆúz_z<%%h^z<´þW]Åa%KºªiP®ÎïR¼ÿ__ [ˆxa,Ö‹{)žvIfU®©^é’ÝúöX؆È5åÕÞáöbÝM³NRAt#`2Ê Ç“SЪ¹_:¾a šc˜^npÖ|ÖU÷pWW35Y(·u3°¬ q”V¨ië ¦öÅËÁ¡ul÷`üxî^÷¼wzªù¿Þ¯Ý0²Ìt¬æe¥¢dû÷¼êåß›þw>”y§*icÔm®òfé—dšVùçPYá¾Å~çÄì.ÓüsäÙEÍ~»"-+yvÍyöœ…YíJ 6,(0>À¯±OÛ’°É þ¯Ÿ7“óŠ¢Äœ¸iê‰Ýl–+UÁñR‡ôW=/M$ÁÆ}x˜@zÐD=õí>U“ž’1Ù´,é£Ä€sÆã¬ÜOiÇï÷i R@Õ»¾‘yv£èüDëiÃSšÂKº|‰˜çÒgˆ¡7}v»‹¸T71éjq­.K²&É—zMe¼çP"MŸÅD¹æl_û“í«¯,è÷Œ&çGd d¡] kú'¥²&=!+Ò÷9°ŽùiððüÚ'¦l&V@Ìa`T…º9ÞJ“NmS-©”š³ Ï8*×ë\ÚwÇ.²ÂwGËÃ8þ:ûÝ1Ltw¬ó´I2í •æ{6.Û·Î%ï?ý¥¹TçŸÎÀgà[Æ•[Ø-¬É¼)î¦ Š*‹|gúo:ë¼*-çÑCÚÀ•øS{àÈľ¤¥P4Üñ¬«ºß/ÎuC&–ô@ÓCƒ— (3}¸Jz±îYòÜãœfw6.O¨"§3^ÀB °iòF%“nº”RÓ¢–E)E ‹9£³ïwˆ 972&­ús1¹ß;@eÙ ëÊ"k×µšq‹Æ²¨ë@Œ´SÎâaß%ôß߯o™QF÷F525¤”)³u …‡dI禌~£.jS˜e>063/êø½!/=:ס5[ sŠ{i xÖtÚÓn™oýrÍÇ}ùÇ ómã±&dôº%Û4>#òîéÉvºjhN)WÕé¨]»š’-(j¬°e mWbû©Úó³S±(³+yº%ÈlkkÒ¬/§fNÅþœˆñø¢†u ëlãæ×¾2͇y>q‰‘)fpðlïyª¿¶ëVÎTáLc•·YZɪT£JšÕ ‚³‹ü—!ôóu÷1.»†u°¤|Ô¬SQ¥Sî?ÞÁX‹2qË?ô¼mžâœ¹Ìƒ®üJS i•ò­PcR~_ ™¬‰ Æú]pX¹‚Ûuµ¼ÐDÚ wÐñu\bz~ÊT×–T'MY&Z– = Îλ¸(#ë0×äfoµ™ž1ù£8GlTËÕtG[nRÓ¸†I‰^ë—üÕðrïõø-µ¥`ßÃh NküBUXTªc*!âX^(mPøW£uz†xmº> í°ûF9Dúö‹Hé—çsÝ…kšêzÿñž –(쌭CZÚ°>£(@¥OžIäŒËïY¿·ÒB¹Ó¨º¬Kâr”’Æ5Ðå{¸°ß9>žqïv~Q Ž¡WøyÑǺ›TøQ­¨øŠÊC6é º&œ#m¬k:Ç5wÙ"îõaI–¢ÚìHUÊCŠh U¨!­¶6ßö%€Â ôǬÐù(»oäCÆÓòËíÐjN6úÞuªu_¦ý±¤c³`Eûq£v]=Y¦á¿v+øTPâ[VJEeH5xOGIˆ·.0ó6ä¯PШÂLJ Ëóºdåb`°1òÙ:¿QeFúŠþXã‘Ùb-—n‘kÛpͰXpùPÄqo6Fâ-ϲœˆu5£êσŽ4P.»fe2×U<9ž.$ž¸ûp,<ÊøÀ¿AnÞ¬\t9pÖÑ)B’)“j­Ò¼u³”S'«²’¢ažópo³¨‹Ï}X4b+a8±c{7t»Ž$³›ÚÓT¬E½äM( >ÕI0÷ƒJo~ºIЋ¥BI„«j”‚=Àô¹Ê‹~Põ\Òû età‚w56<þÙä>»»/ ÷@2½~TÊ#}¦J5-Ç{ÚR™*–ÊþSê.öý½'dOÅn 4 Çûv ©Rž“¹Z3‰ÍØQ¦¬ªáœ]½ÇGÇÊbçþm¡É/S³5_ô¦*iÓZ AØÅweŽK/ëüõ—¸·¾>`¥°D¿TtS>Bõ/¢Ð4ª¨(Š^VuaŽ…ˆ XÇ™7ßá¯ÿ}°= NWn.Ô1LüÀ#®üá”_ù¥9VUÿÕ«*Å kB»v÷à]çÔûüˆÎ?+Ë-à9s¤,´·¶ÃumÃ~Î˵̊bŸî¢Çˆíî"…8ÄN½ÃøT6ÿ—d¤¼ù‘@ànš&Œä&ÁO¹ש‹›¦Mæ6’uy¾ÅÎ’çý|tHV€nèqéaaž#ê¬íÞ!ÁK¥0E•]KA: EÇÜá)¯}Ôíô©RWã¾&C\ŸV=úN–ó¯û4pC¾óìÔmÉÈ †qIßi¥5¬E¡š2ßÔ…‘]€>ôñ­¬àC¦P³¯¦p&[Ôv­È¨ršÛlTÕeQ4Fa'FÏ ;Ä2|pç‚Ý+ËùÐÉù.¿ƒ„°¦ËŽxpœóΦþ‘ì@Uð%Ž˜“ÀžBênÈx¡p(Û8lâ:®£6Ô…ÜÍ´¨gÃÁñ‚ÀÛéú;;½^â°ƒ ôóÙDeG`DÙ’ÍEܨ,íÚ(”%!ñë@EÔ¹ GÁßÄÌŸç¦ä£$Fµ,fÞÓm°ny¥¶yLÓ¢Ûžj1H­yÁ•@ÝS|½{ß²å8Få½ÌH¸ñ0DÑZ­y”¬ÉÖ4²¦Mõ<¶å¹Á5€¿E= ®ðNžB!BuôÑûÀ¾„ÔLHß=é¡ÙŸÔ`tãØlmuÕõÎÕÿ¯³Çásö¯1Ÿ1±PAqÏKϺÒÜ÷·~âÓSuG¹s)ÏÝ~<ëu–:]´­è~–®0€ß@…QˆzÎãô•¸‘rÞÂ{ÉEÊ3覑 ôNÊ Ã¥Vu6´!¥æS¸*zNÕìÁéöÎá«q3Iÿùú>LÒÇESÏ.*3qQVãò/%çñˆèzÛØðL£®¢‘…v ¹]B;8÷K :;Tà¡-'|I /‚‡oÑɺï(FC3%Ki ð±Z> »"­¦ÌlÓcžE(}ò÷áSÑר3%¿ê»—ô D½¤¨êötœ[>dëC¾©¥Òá¸/ ½Fº÷ àìÎFó½ÏüúÖgŸ¹†â®{l(ô™‹b(² :sé(Lñ_/éÝ" ‹½‚ÆÍH‚ž³«Eú·r+«„¾yVFKg©{( [DÅØÃ1O.óýbþú~_ž²T†!Š[ÇÜ-ê*t`¿tñ\Hº#kÒúÚ÷§÷% )I†óô»ÿ«šûµÔZ§Tàítf²RÀá=8Ùa8~OÉ¿„0Èm7f3ãþè8}Rð ËÆˆò¼~J•,éQÄ„ìÃ&–yga¾×d?÷L—Þ'ðQÈñGÉt×f«‡¸¡4w¨çZ°´*(~p‹¢hïž³ñ›°9Výb|mšÔE]Av kw¦p9¬ª¥ _SAVÃñ¤ ¾0†ÏÜñ0àyâ%]ó¬¬Â ÍŽ‚è†Þ:Õ#ýúRxhpÑu”Ì Tæ5¿½i­ýItj$:í€;ϧøt2yã³ 9ÌË 4ʰ/·EW{ò€[ )…Ìùño=@,;+-™‚¸ß è=Uq[­´Ú’ÅjI÷¥äŽ-¤}Ç9½mÝÝ“þY+Ÿ= |‰ª8߇ô™ÿqÓÁÙŒQå\3±Å7‹òJ`¢’‰îç,¥¿¡ª¾Qƒ¬ ~:>ôzŽ êÞ±ÿÿ½ïÏ_-é=>ºƒÏï¯]ïøoXé°O EzÁ÷ÅP/í8¦¥@a÷˜ÊÉGzQÂŒ¹^|Aè9£5WCž$M=¤iÛÄÿé9k•Sû©bÉ3ÖèG³µ_–¸Éª^…i/צÿ€–惊qƒvü4n‰ÚÒu¬ J•³yÇ¡Z(˜” FjšeI´Xa ¹p÷bóšg¹À­Á×óù’+žkšÙrÇ¿& Å<ÑæÒ±,L·0O´K1W¿ðUÆMpàûµ #”(À2 ÊlJ†í6÷[¥:Õ£L´¦‰xgB æ°·ƒ„ÆQ<Œ ‘}Sh‚|²cˆ¥Gpe8, ðüzCIRÕ¶F« ÓXOÓÖ§E¿äqÒæ]Tuò¨ÕJ¶'u<(ÔéöÂv¡Œ¶þ×[`[Pl¬áÞˆ†ó8ÏÑa•ó…t7EÉ”ô²6D—Çêç€íhä/¢¥‡cµ‹|l"œÃ4ÏÓ õ¸È{•…mžöT—¯BÆ*3Å(éÇú œÞí†aøµçÐ p•f¯¢Ãu­*Ç%©¤ó=ôcºŒjæ[ÿº–h -%~‡ÔJ »vX¬âœ¢ÌÔ+½,Ѿ(\ÄÀÈõ¼#\¹æ_2‰×%åqJ7 »¥VQEíÒEùÖ7Â釣Ú¯èNœÎlîgxý¬ mÏÃHQ×DkµCÞFiE"ÛÀ5qGÁÅ4˜Ë´ÉØÅ*wÕ„ø#X{¢W¡¡?¶ÓÀß*/éw×s¥³TkÝÍiÇA †®lesìŸh÷êr½ß+–ÎÇ1ÀÐñ›(÷ ÇÔ¬éÔuÕ¯c(ëZ0ÆÇ+”ÏÄÿs,ßÞŽ6ÕŽ.\œì³Ö;#Ìt­ïiHDtl+•&ÆÅ÷ˆ0í´é0õy߬M“'¹Þ×õàµäÁÑÈ8FOBS+ÌŒvÏ¥ª«¨8«`±¶¤0ߦU™F•¬ §CXéΉð5©ÚûÚéz´­p¿ m<¯p¶¦Ê¼/útÌ5_®OA; Œú^{Á]ñ¿Ë%‡X[²Ä"|Ç´à"x»PÔ<Ÿ >@€¡Úa ŸR|ØE4|(&vÅ2e­T;ÀF3 ßz˜ÄlÙ7*ú)Öˆ¾I *v=¶»ú&aT-]ãCBY ðü€ÎWù&•îÉ™¿+@¾v¿qô¡+«ìªüø®^T³MÓfÃÔʇEO°)³:²´àn[FÀ‹/WÎüJz§”úu»ögµÑuÛŽé˜ftfKÕþ~ÍÏQÉsÕOÁWd’©ÐFE­+œE…¾Š4EÕu‰µ}®ê†Îwãnúô¯ÃŽ”uÙï½Êu·&Óc4m!ýcò>ÿý“žÜWMGž¡¦¯½3#â$ã€Ú#¢Ð¥µ¬€—–˜÷‹ZÃv-–r­†)äÀBIºCe„Hóàm>ü»jã,ÔßË* Y7Â¥•ݳø‹»þyý³¢m€¸`íB…[;:öƒn󰆯i@‹Â†^ΩvÖ>‡™7Dú?ݼiœvÞ-Ûy “^¤”ÙT¨Ø'} ëþ˜ßªX ±3G +™^¦Ô–/Û ¦RMñï×||Њ¿EX™''}5ÐѤ˜2¶2ƒËæ(ª©LM§lY³iÙdU ù霠lï«zÞ¿>•»¿¿.ån¤Œa¾”»óeÝèìûURkZÔ‚SdÁ߿ʴӀ ‡àɳ#ì«„¯@Ì˺‘¯ÜUíÚCµP©aÒ]%LZ×´CCy x†OñÂ]‡†¶TÁ‹Ð˜( 0£þ¾”lo5«dÀ‚=,¶5öYH\wÊæ*€=¡ãA_Ÿ±šb½Ì[“ŽMÔQõ¬µ,IçÈ0 ÚOþa%LåNŒz¾õ!,M¿žÇ·¹ƒ¨’¦Œ‹x®’ºM#Y“¿ ½ƒü­N]À»Ô{jbGÁ•¶¡¤½g¿à®›§¥Ìú¥Î4R‚~ošSH¥]Ÿ4 —ýÖ ®Gõù<+ û³Õ•g«Z%Á]NãRîkú”ðÙtïoz:ü¯ƒ_È=„R ED¥šFëHUU¯RýzÉ›Uø—0u1ˆâÝDËB%ajœmͧeiÓIÍó2Ó.“ÝYJÿ°W@1jß C_duÙ9ÖÁró¬ÜWæ:[©R­Â©êrÕI4±\€UMÙÇedx×Lánü×íÆgÃÎ~†QØ#€´ì8³³ÓRxj¸#²ôPZì½i@2=.sE/´Ÿ‹yùN”=š®m"æùGƒß4îÊ•¯ƒº Ùœhrb»{–w:0¹æ'cQ=÷{ ª6ôË1ÐnvÚó«>+ÓÛJø*™wr—2hû²²ÿ°'d :í(|©ØcŒj¦§¾Pu1Fív¢ý T`#L ÒΙ’ß]ܵØFcÉœ±+´1Ôü±t׫P:šºpd+OLE?`†sÙ¿Ú§O²gT9ÏjOŸa>>²†ú$ž”?/ù6nq»Ñ‘—–9dhpѱ·N\þ‡LíÙé‹þÖéÃýhô ¼0@1ÏlŒ¶N‹ë¿fè>?Å’ÕîÂ`Œb‰æ!®ÇN/JfÌo@š‡ÞÏãŒKŸ²púK°¯ÕôYÍ€ZDd …–ÒÒ$Ϫš„Mt¨þpE½2'ÃúœåkÍpJRœÐŠ‘6¨Iƪ‘q[ŠqaI½dC«²žeØøÍîõ¥>n84‰w€@žéA›~¸£8Ô…&¥dAhúÀbÓ3 ç&9u=æûùFžßκ¿@&<×áNwfKK%ÛF¿€ÑKxHPê,lz×3Îj¬B)œß?rÀ±§fœèûeÆ¿¡#P7ÓLYi4vÐúX˜Å×5Ûz' Å0oIÉŸò@óHiy^G“ˆCâÈ6nbQÿ(Ïä1mÓ¤ßìcq®˜=Ô•dž‡0;¤›¿06 Âìa:¤c8´9—ã¿YóÞ—Õ”“þìC½˜êG$y ÜãäIÕÉHÁµ ÝU·Ó(Ïé”Áñ†£×Õô!ïô„\PÀEQ¶,•Õ(àmkxf”÷3ey•¬Ê&“lí¬‡wùw4ä.R°Ó•éIÙìAúÙº¨<-ÓÝQN©ÀKšJÊGwª:Ò§¿¼Ðló€ ª,ýÞâŸë­ ’IgÑT@þ~ÍEi½CQºÄô R ìKŽJ¤)T¢æ2¬¦*šöõ(è»aÑ¥(ý—‘û¯92r‡&\<0çQ–„ê–ƒ­eï)>äD‚jÅœT ‹ßÞ¨’±-ä“»®û›îCêûn¤ý¥ßbÙŠ%Ó¢­Ù„ߦ««­®ÔV¦UCõM׿_Ò0þõO~ïÙHŠžÇùVz:eÅrxJ-ɲ¬¬¶Æüq—òZÈu:»¯*Rл®æ‹}íJ[µ—¬ïŸUK½DQ©kÇÑ"»’RôŠØ÷ðÊøôwú~TùÙlº9ê ¨•–ïUNC×å4/*YÒ¥Ðö D 4ûº;®†ùŸ²;’NŠôŒî­9|zÁî8¯£7ó÷ÏNË™MߦAn¢Xù}š?ºã%}Êë<ljÜ;±ŸÎÕzùcÁüȩ̂UÁî¤îP´4×@ë¦ÇÁh½—HõlÐÎxbÞÆX³{BõG´ìà@‡Ù+ëh‹”ݰm9ÔÈ–¦aT--jÃÏŒž—™­ Ü½)´ñ¿$HÁ(¦çˆ:]ç¶m£z© Iö 7¨Äñg:`ÿ–ó&ù_ H Èpx cY>ô¼Îšþ6ya4Â)c 7ŠŠqÕ\/A®‡7=Ù:Vq#Ÿ9eÃSEûf³J%ý÷. É<l¦f¯”…G°F³ê†µÊå+QhòP|Ó!?"ÌkDŒb °/f¤°Eò™©¼C™•+¥ýÚéP·[·Ÿw fÍT-BÎ ¸‡>p…_?€î°‹|V¡Ïá™6è¶m)Uˆ©Ú¢±Xûš eê?²ôVÛY¼Gñzÿ|sn>´ç ðÛÅ[«Z©VJ¨©Ëšç\†ÿ><ß9;÷îåÊ` ™‡Õ=àŠbŠš}žõC‘ƒ©’¾qNã.1ºÓ»ž¥w‰yëÞUµûgw _(ÃVï@|[þ€2i÷—£ÏÞ•Z/÷Gf5SìùP,›O!É0<Úû0ÁµŽ¬Ì¶®{^îN¾@€ é 7` >1m¢¥¢\Íu^Q œÒh…=˜Â>¸Nî¥;wöo1g\ò~ø¡² r˜ìçUõbtÖ„TŽ¿_Õºº*ÒL `( Z´Ùê¨]ïE?Ÿ7<¾+Š¡²ó™p]lk4!Uò½IËhUœ Ÿ‘!ÖbϼQP5Ò“‚:ðxíNA@A­öêÓÆw\Û< W+µÈ•7ŧª SÚ°*|¼XeÔC:ô¸E³ÑîåEÁI€,;„¥³óîõákBy.—LÍ¡²IåÈ1׬êÒª,“¶üý’Çî_X"~üžE)xí053@ó8õsÞæTØÖYVET{waÞMÓxÚk$À˜Å`^ŒY¤wÚ•§;€í´XFz¥r¾[¶z‘£e² ÇÃ2Á¢9Sè3'[`ðýd‚fw´FÆü7SƶæBÛ@E´m»hꪢècº¥v6-”@ÆØ9äfÍÝfm¬Eö<´È(Ù…) [] "¿.ñ4EáŠ>]W•¬kzPǤʔò)ïÌ}œý¡ñ&XÏ`w]dÙ…±žç–\úq¶šN\ØäK‘+¦ÏzêæB·èyÁ!ƤðvoÝ¥úqcÉ}P°&:|=;ú•jk£ˆÞÓZÄ”³&²&%°÷¢\Èô¯|úÃÅ\`"Œ]1ûCîÖ ˆ¢µr5Vk"m8ó0 Zt^)[5>ÚúÖ]Á›QÖQF5ŽÒá”aBl¬Ò.­“¹j^UÚÅŽ†+g~|1 —¿ŽHKÏJÙNÏrÓ>ÏÒkë‰2 4ŽUTÉNp ïø&KFgãô®¹ó$‹¨ÁCå ­ejÔà×°ó5 Ó4×Ü5§%ß܆%bŒsšeþ“Š:9*jÁœÐ¢¾ ‹Hœã–¸Î‡¹J”÷Ï®ŽÃtFHê8-Äqò‰NBº?'…kº¹¡­o{7uûÎ*´1“uð£GäA ¨eBU[)µÎé÷§C™Êçw-Ì`èm&±†ïöÛï|@ÓLqP²Ž‰+O^7=díÓ0òeaW3ZÓñ,¤|”ÆÙ¤¸½Q)þ“&0 ,€=ÅR”ƒ²®‹Š˜6W!lj®Vân® ÌÅ ºu€eÝiĬjEùUÍ- -)}ý5R[NA=’*Ú„ñr+8!3Ï»+Åþ·#¿rŒ\¾XÄ–‹ù8­íœ9ÆÝKãûGó¤(O 7^²Ý&³uêb^!àTÏc¹¦ëĈyZQ̼㙤šÚ»…m[–}WC*Žq)c›û\ÕùœÅSœNYÿÛ5àÖçÓôÍD¥dYõ=¯¬Ç!ƬëU>§­ôùLŸ*|º8…ûc:ÿ‡ndžÇµ| ¢{&8à8»‘æë™Â?ç³gZ•Ò3ýå’?¡@¾Y"H-f\LKí³4¥u «T©qÏS|PÈ(å÷¨œ8ø¾ÂԸл‚Ù¤³ÞµT+‚ïwhögI²ÍÙ–( ùS¤å:…›ÅxʦÑ<:Ñ%·i8— D(÷ÙÝ`«’äÝf¥©‰”ÊéÂ.–4LÃV6»Ï³¶À àZë\Jø÷2JÚ†b{ô‹cM[³,ÍS>Ñi-»=}ã`ƒŠÑ[ÏìjñT…×ߨ hñýEvEFƒÐ”ç‹Îv!sp‘ìÌÍúô"X’N+¿–M¸&w-]ÅqÞ|ßÕËÜ3h10Á *ˆ‚þÁM5EÏ/¨]c>ùg¬;™¶±E÷¢”§\'••¢a„„Ç;¥ùAOtŒ›J.zgϧ~]½³}©a7„žÚš ŠŽ|Fu<È.×Óð!›GÏà*|/NÕS³vÂpªrŽÍ"?+Ne;×x¨ú8MSøš•ÓT`QTñOØæõz¿_úëð‡,ö;d#:øCvÝ,½JÕ²°Ö8-ê#73(Ø›§ó‹Ü Û_,¼)yu’¥IQöõ„©æ< ó8Oùœ«¤Nê’2l5¬a¹]–å[T¥Ó­`í_2æw‚®þÙÝ|éÍRr†+ý>LŠ)7+{/š.ª\Oí¾ª‹ðçàÚ¿ÖŸÍõ$jÖèNqœFÚÃÝ9HØëôºFFD&l-Ù_Æ<;~7Ot4PåsIµ¥3[‹ÕøÑ@­èúËúlPñ¾¨‰Î¤X˜m1Ðú'*^c¾«xµ¬âÅÖŽ´*m)ß¼Ní©ö0Ëàè‹©*®¬€:E0g —‹æOœn”@S$ÐÛÄk¨2@ëî5W·Â1?U•ñ±®ÓGÆ·u{Æ‘dx­ÓÏwܳº·ˆ ‘>ý¡éÖ/{¶maOÛ¬iåÿMÜusÞd²&F3ì6â íyÎî‘ðu¸™¦P¦èèö«{þú Û©¦t¯i*Ê1ælæ%MP´ Iרy»çÏ/IÍ’2‡&`UuƒÐ³Ûö%{]4nÕ°•’žØ ï{æÉ.s탛¿S—~ ø Ô¥:ÑŒVÝ­×)tEÛ©è"Y•l*þ¨¢´ÏDê>>‚ û;R º êÉø °©Ê6j¨dÍ(`RS¢O[SXºLþ¹ñ™“çûçæS˜Iì e»9¥,I³¶q“d_Ò8Õ’N pQt@¿wx} —®ëFX`²ÂÈ( ž lÌé_s(ëÚx±À×RŠêœšk˜Í¯ý³Ã€¡ðSÞôSÔ\l ´@7¥«B*j>ë¦ï@×Pê–E#7ßKÓ~_•˜’!ª"‹n‹Š»m–µjÚ_ª‹*iÊú(g~¨zñü€Á¥Kp^+xåf¢÷¼¦eYÇa•Ë’>eŽ´ó)2Þ‰ùÀF1 ä% ÌlNª4]ÓºÈÚ4k£^ª<*r¬ô`!§2Îe|š¶ü0”‚ˆ})~Û<å ¸‰P„Æ®òaá’Ôv]v©6¬8 ÿ±I¡‡ßN'´kŠ2 #Š(º¨èˆR€Jæ9^õJÙy5ÊŽ‚y}zˆcŸ?÷ÎÒe‹$ÿ Ä2å‘åÃ{(›è–ºöá í|Œà¿Á±Ú÷w#ÂN€ðP׬'ºî‡fšÊ6•‹–Oy•I žb­0º‹ãéà J…Èq0c¡­æyëÓ(ËÆZé"Þ YÓø×õVJ¿d >Ħ¿œa„ ѶAâÃ.wy6Œ¥Úšµl(úí«Rªæ»O1ëËüø]È=‚é™´»ùAijVSµ^BѬû’ôÁé).:”wrá§Vj5º” `/QI—²ÖÅ÷¬¸÷ë%…ªiž[ œ²ƒŒ]Cl,Ë ¨U•7ù¬h·VcYFòÝé¼›€îø¬rŽ5ïØ?Ô•1‡íÃÌ“ž*ëcÏþôÕù¯7ÈF7H~»AàЄHÿ€tÎ%<öqÜ–Ÿ» I¾ ±ìÒ[P!©ë©Ò("beþŽÃØî¦íœaùÒ â„D¬â TºV¶hìêÆ8£|©ËbŒòm‹û8n~¿®Ãè3÷ƒA–èBQH†rÂØ6í4õô!ò±4áPSÐ…]©»ñ÷lÜ•çXðÉ/v×Dcº;Öðßõ)HºE3É¢½êa%ü·o´¦q73¥€’Çj»fê;Ð߸kâŸUšª2TÑì£ò£Ý8%ìÑé¸ÍNQõ¾÷¾w^ƒ°Œ¦¦Ü÷ÖqJ‡«€OxÓÈ ÞÁüÌì¢x°ÿÃø­_<çe á5ûuIœË~‹¦Aoý¬eUÈ™6?íÁÕs?yeRÿñô´)1Gã¼·‘éi±­cu“šÒ*a%OƒkIJM=èÅл+49wp]üMQ¶<ò{)*éÞô„iß–ÐYظ“î 3·<ˆ^`ä}Vé'«†]'dà—Òñ*:˜V10°ƒÂYN‡+ÊÔõažHÑø"DiL6eGj~É) 9Oéî.(üjÑãÚN©Ô¦JÝ÷zž’AÕ|EQÍ Åp€Œ“¶lÞüÿÖ÷¼Â†S¡}]±pâÅ:lS[¥é¢SÁ¯:ì“ Á*ý÷v¿cßÙ/l‘þÜ!wa-‰jh§†N%üÌ,Xñ½²uÑáÒ®á,- ¨8ÅûûÅAï…7_bdSÕ¢¼a7²Ù²®£+zmÓNuqÿû…?²ëkw÷¥’¹)ÀرDÎϧü~ùË‹uÀV¢¿‚´`_S¯›{ê>¢áYwÞ4£k%åŸáeO‰ç±l[ªYäç»¶XBSâH|,ÿÓíôõóÖò­ò²Î!KÔ3Š£¤Œî”"YJ•ô…H÷cMÓE§QÛ<ï?û“¯¿c+ÔOÜÛe n·f UÑ«ºÊõývI÷ƒ¬Aé„~ú½t¯à:IwËdnèlFªXšu³}I˳èÀSÖú½Á½ãàîS ÛY&¶]À tb<žXA¼×Ã:ú÷K^šL}y½Ø‚î æz–eXãªLÓ4¬Úª• Õˆ GhØúZ„Û¦—(îÏ·ž`óÊ,EV’à<_”èwѼ4*ëöOîyžûð…¦kôòìÔì…¡¸Òš<”ÊœIŠUG9ù¿G=mt¥êMÿ›*—¯/a*†_6c£”Zâu¢)±PÆx–êh ‡àìm0 Òî±õ«éªiy',KHa•žÿTþqþ<0çaX¸Aj€ýEÙp"k7Jã¶­–¼h(Ö3ðáaCÓØºp÷Ÿ™õ_Eä` ø)"7éˆ~½¼ê€Š¿àaQ:„ùï™Y_°$ ëŽrLq²º¶åŒsD °â hº1IÔœ´÷+]˜x°m§-œëçßGÊo´Ÿ|µBo”Ûªh~Aæ-Õ[‘¯q¡<ª ±X¨TuP9pÜY,TR¯üóÏì3tVë6GrE•ö\ÄI9HëÛe˜F= uÕþ÷LêÐà¥cÛ•í1î '§P ‡)ÖJ;@r £3¸AœʼW±ßpœl6MÐõâ§ßUKTÓ å”6Y“–Y$é  ÂžáÑeý€CÞŽôÙÊì%Ìt¢`±Ð7T@uªôRÆœ²k%(7× Ðìq`ºeûñ›=Û|_ÁݼjE'y”ëª/(&P2ÜvaXphu-Š~ô¡\°ƒN=RãF«e'ˆ¯]þ€{ž¤w\V©aÙ(÷‡ßÚ¢U½Œ²¤å8Ò§RÀ=§(wùv}õd,΄PÀÉ ª€-Oòxkê9+á;%KºPy°šù±í}÷N²ZEçŽÑh-( PpöϾ%kTé*ªªEl…Ä©ÀÁ;e5Ëþׇ#%ÖÜE*—„E‡– ®Jt#ë<8ÁŸR¤ö(¢Ó ù ï²V¸àß ì”ŽGIéøˆI?»BqÇ#\(ã«ÖríÊ´åa¤KÇÆ¥›Ä10‰Uë¶O•i[#GærVºÒeŽ5ýd\eUºýéRòÑ¡::ŽyM’Àû~ƒžÿƒ‹©,r wodd/%geYÂT¹-ò+…¯I«ú‰)Ýw™ubÞsWzT:õ_T­&´èYÙ´¡g0 UtŒJE@:Îi¿ÅÂ4£ËÃóÄ ÒuÓnD3\y»/\Z—D{Ÿõ]Ù¦§œrE;ª,Ç,·NÉ¢ þ»| -û"þßgSïçztiRÀ0¤] ´QéÒë6zÚ¢i¨V›ºcÕ}“ͶN%¤O<Î,w<-ËmDȦx„Äh]›JõÑ P†‰kÚ:;ÞwE†"‹tÕ¸Êv-©f*ù²*+' €Šì¶õðòµmëñ¹ƒÈnô-ôe™jÇÂ'´&K[wyj]ö‹Ú×t`}ì0ãlw8*iý~2®>UBOÊDËá£Í›2§%,U=çcW•Ǫlµ$óÒ}pîåÿë­÷9˜´Pfû ¥Uÿ#Ëß`è§·’J­U<³Î­y›ê€vàÓþÛ&øþÒ"r š-ÓZèƒ5ƒ°&òU-ù’e]6A½Y~»¨ùøÔûw~³&R” y,óp¿³B×çÍž¢jt\S4ý“iŒ(°ls2ûÌÁÁµê=Üs–~\³ôÕèæ>¿*¶Ü¨Ù §ftíV æŠ"îÚ°¯ ª³Ú†•êh]Û %€é†k_*šwã ´ž»ñ‹J4ìÉÄÐR•[>¨<[“hìu9Ë¢”õB@­Gеo²e,÷Åd©$g¥šàÖ@ÙàÂPd¸¬£¦¦T‹—´x£Ò‰‚±´yŽ|?^éëöJahÐwBp‰_Í}1J­Ór_\XèSÒÒ6× î´Ž/úÏ>š.àyª svè¦4k¯Û¢Žê©›ê¥‹eQ´=à©îÀ²þ#==£Ê×÷“TìÊôűky8#è\(ËLÓÖ¥K­!¢“n[†IuåiîE8¼uþùi_ÒüjK†¸:ÕK²åÝJmÓTu`ž½ªýq¦Þ?«¼*«Û¼™-!ùLÍS®çÞiTÆŠ~‹,Ši§·®3í?à{¥:oo'5»€ÑIeë¶£³4bê] ýVr^ᡟfztXþ¡­Ç•Äÿ H-w ç8Œö„K„sË©®)âÊ|cÑ¢Ï 8dpø‘O³X^ôa‘GSµQ:-#TU®Pîc½kŠfßÔ¾Ù±Ã?kÿ =Sc‡á£w0 ªŒÒaÆŒ·ÃÛúÍyÖ­ùß'µ‘³–±ô.ÄÞ,›NË> çm_Òwéò÷¾eúæÅëùŸ¿J¦ó€æ¦ÃÍ„ÆÉô¢jµ(Ö̆׎x®}Ê›ßÒ¢x~Ê^õ”¬Þ±`»1Ò§Ï2=UÓ°µÙ¾$N>¤Dm÷ ®›Ÿ>Pë÷ÏÁFèt)@hÔ O[U«Û**3:øl/JÑΠÝz€<³xÏú#}s“€lzÊΚ¬ªØâ—+:¢£|b®(Ö„+¡÷ ”ºã”V0îsóÿЗ«¶¿õå|¨*Ðíìh§÷™œ¹Oy© g+Oyq‰ †ã®gÃÇvÍûzm%Q U¨"zGëšT™ù˜¨@ûïTl¸g'è÷}íúTœOå>ˆ‘ •eUE‘t^û\³ÿ8Ë,lÖ}û ¤æó– ¿w碸#Z¡Œ$çišg<,UÑ•)é Û~IrVý3|ŽLT¡@æüÔ¬pnò„è è×÷ ºíÞbY iÞ¾V[v“TѨñ¡>OQßôkßû(ûÖçóHþñõGÉü§ª‘²Ôv(rdQe]ÀZAw9¡ãÒ?YXVD3{[&žiI/¡§–Â~7°ú#%¾ýUq±¤`Þi%”1¦ò>³O}×vÏwàŸÿëýúZ+T¼¼mšAÀÍÌC£*}ÌÚi¦{:dÇ‚ÇìÁ1þàöILù¿é´Ê+ Çu Ï;GO—ù»Ø3X> Áîv¾ù¼¡F§×÷Pâ¹æ_—dÞ-Ñ”C»Ó¦M›¨¥D:«&ŠÚ}MÞ&:•GÊg?.An*{ßzw`¯Ü!:÷Œ¡Ã½¯U¯Ævâ|xbP PÁóq­ƒ}ɲªw x§»]zu¶ÆcJQºl³î÷kÚ·júK|ÆÐNΛÕX!½¾V‰nTÒ§pµÊý»{”?>Ý3å¹ëiézÇaäÄєŒ’¾x–­c´–I+í3ôK}HÑÓCÎá.pŽÒ‹µ%¢4áFzU³¤Žˆ`”'Þæ­ËÐòÙ—¤ôX*ü¼“‹åÝ÷’FÃ×=JÙ/€Û‘Ò•Êã¶YT–ÖóRi#¡¹±”˜Bíì8›¦õa}øg ¼ö`àÌS^âBQÆz\ ¼;‹ñw‡¥6í#ô‹w,µ³¨Œæ¨¬ª¬à„9ŠJžè@:—þË 8zXwål%ÉŽX<ZºŒ_ãxÛ’!ªJÙü>}x“›=O[ÀýÇF>ÙnäcP÷–õ]ÿêH|X:<Æq ¦"E€q²YQvÂñXlâ]FW¼‰ü"æ%ñg\•ã áé)ÞÁÀ‹®X-³ã¤è'Ê'½,[7äÛ´/JY)¬^-®ƒ«q|¤_zÕ<8ç_†tªJVýjÅä›_ë tšÄ:èîËBŠ\£¬ šËgëq$“è]®Kè ýhÉ!R€§›oÅÌkÛŠMÇ W¡fÂ$äð-/xœ¥Î§-zò{¤ê†WTŒÒ•¿»ä`U##Çôo3ÖG Ú»6Bè$ˆcìØî)ßÐåXªISåߥ}/«ZSs)—€‹áYÜ{‘i˜O®õ! ƒ¶$…s¸Öï{UGY;§kÚ©¡ždameá6ø8´!|ë<‚‹J4$ë‚5å ¹Ò³Eܲ…é0gåØnx±í¾&U<­×¾¾ëVÑl¢yYBè»é¨H9&‘ æQ”X¶a«êvL´ÈÝûgïìñø”[¿žwÿxY±'¢ÿ†!eÀ£Ráº%r Ì `<·ÎÌ¿'Ï'›Y!¦ `±‘ÝŒ>E(Sû~ãEÅ2U]“5r«uaióµÛÕÐ\ [õèÈ–´›2Ý©J/­BÙ§–øÂ¡Dóýàlö5Ï—¸‹jŽ+tX3¼Q€…Ñ;vµ÷¤Ë"µŒðg) ¥t&Ç “.€…›3{ð—ÒüϦgzŸžñœ‡rTÊP™g\=_뛥)Ÿ;r­“/U:ÿÐi'¥†LÕY3¨iPì(‡*Uƒ2¿K•Ùù§ªúRøÍ¢;Àõ‹Ièonʤ°×­!…ÕJG*+Ë<£$x*KåÃþµlH)ÂÊÏ Ó»rª›Ô „I¹ÍCT,§”Ed#9*LkÛ6¦XÓÅí"ÆôéÑÇiÂAõ//³ÛÕòÄ,Z:ý9´sÁée;ZèBɪfްi™uHkÂ1y ‚gŸ×øèô¿XН+J|‘±$)“c+EõþJ¥¥RERÄѾ¦ç`̰wñ¥tm}¬ ³MY“=cÚºÛg§•Ú6=Ža¥USˆîoÖ4> ^6'ͳ\–Û‘@Ï"WéVú¿)-“²ì’¦–Óï>(W3- S¦u åæG7^#ž²½ ­Évï€;à<¶6]†èÏSN¥dMßva¨m!¡>¢tàßaØúÍ.'/¶åhkئsßX¸Ó–+0³ÊiS‹èÍТ˜É™.èý'-Ú¿)Òrä™ $@D0ˆÀuÂBçF)íIC]d**(•áEÁíÂpNÝ|ïSÀ ÛôÉ‚H”ÿötõ•ë~Ä“ú;•Æy#Q:€Þ”Í­nó¼û½OúÏ{·qÌ;º/àV)ÏxxZ-u;¬a5†öG €ì ÐHó<ïªË›&ÔNlM((Mcœûá¶¥)ÝÒ«^Ë,ÂtüíÂÞãzì”öÇï‡Òª¢d¼Óȹ”Öªì~ܨpËB~†aÃ:j•¶é^¢ôñæ‰ï>–„¶ÞÀtÞqKÖj)§$kú­—¨b0ߨ5 ãõ8„±hgÝ¥| ÈÍFÃÃØ>‚—¥EG:TYOÙTRåO²¨ ñlú^”SØî¥Òz7Æa=€ó”UAÛà "¤k®¢|‹“0ͪžgG&¦†¾É"'ç’úóýMƒºªûÛ*â]‰Q1osžlkËþ°&º'È$<×ýú¼Qîºß/}êÄ@æþ¡ôòœ Ë’«:@ì>8¢´õ–¯—C!«.ñá+ÄÚ­ÚòYeY[e˜sÍkRšnáÃÓ]j|Þ‡ýÑ@þS ·Îe3¹@ `ž ž@ïã½ÿj«>m‡­úøÛEÇmÑF?œNPÞC!.à³âÙŒIå” RºÛv´IçãI-–&ÔN7hçv—¾˜',™¼,°ZDÀ`d+Ó­Ÿ…cB¹¯à¥é]ZðËð¸XßXŽ(ïQxEC°F…VI…“©lŒÖÒeU²ÉgÉ|çÛîilâ™—ž W>침ĽiD»Èî²R}£K°.aÚ–:r”@Û´çl(Z6øÜ}‡gÄëožãøWÓˆM~½‰‹‰ÊGÓ†O wÝ¥öÐúúúâ :ŽP U•ÀPGÁ`÷¥ùŒ{®¦¤®Â߯j|¸F`dø%8Á¢.óf×=åS®*k‹Fåå Çšg´¦Ã$vŒ÷¦yæ<ö½¸Lž"´@©`¶aÒ%Ló–.Ñm[Ã!ïŽEa²M™©møÆiHå|¬_ß_šÉx³¤sOõ9ÓöEÌg€W@U6ôÛýAiaº Á:… ÏÁ“õ¿:#øõ”öõôoàqá”eµSÕ•ƒÐİ&h ‹Àqùª%¯xò‡ØÙØYÞª¦X©õ14>±ÍÁõ¥Àë~pyXB?[Ú>Pš¨T mÔ„yµmL½Ž30è…Â(ñà50Iú¤(¿UÖƒ·G7~@*)œÛ’w”ü&õ kRt†é*½ƒÇqæ¿îâé°W?Üi—6C½C‘ð¯q½´Ó–ÖI¯æå?-jÝê¨?ޝ=´¿_òq>§ø×ŠìP–E‡]jLõËV…yçñZ©1Ãß/ztæNÆÌ×(í0c†Ê’†jQØ ?cÆÌ¦œRÍŸNò°ðÈ2]´“(<]J7”ì¯Ë0?Ë­—£ŒøåªÏ2©ô91®0.m¸åÑñĸèëf.ÇM zn6Y“ßpqrp9ƒÛÄ‘_ÌBð¥hë”lCÁª[øRkDÁºM·>ZÕþ~Iã\òŸ©RË…ùG)ûòØ>[Ý(u/±9£Ñš> ó¹‰FJKZŠ±ËØþ~ÍÇåoÇ À¦Ã„¢„Ã8òÇ~:å¨àü*îûT6•³—ª Ï‹*xÇJ¼žÌÄg‚‰-ñÐ0£Õw«¨–JºÓ*]%žÀa<`ì¼çœT™ÇÝ8A °oÓC3ÚL +×´|›–c7ÏsÕèuQ²$Dm£Aê²Éº·ÐØ€œ)ÝÄ@Š%:îö“zÜ(±Œ"•¯ªf“ÓäQ,e¨îUš}˜¥ýa#yï£Z`Û%ŽÆÄ14{ܰà ¤”¾T šÐÀ˜.€F·$§ì$M”.tW‹¬€ÈKµ„±Œ3)¿¶Ôßú"1)·~ssŠª)‡S<äº X^c°3ûˆòýÇy˜.³Ýotù8»Gx²OæÕº—z/l}‰Q­×3aZ†¥§­¹Hµ%M¾©µi¢9]¶Bj^–†°1•ò­“$m>þukLëƒØÊª#5.©”äÎ,å½ZS JŠ®»dbiˆ_/jín {€ñàܧ¦‹¥¸Ý=JîSP"5@ÀihÂRÊ=ºž]¶…gž«9á^¤®ï÷û öiLáó‘NêÄÝ^4¼Ô’U¹Á¥ Ù_gWÌ&nÐ øøfÌEeuL“ò‰€¾•k;Àã|pQ÷°K½~>%‡àî6~jåm!éÔ¯õoFÖ‡4ÒëoÒHãø7¥öí÷‹ÆmÑï£\ž@£óÊÓøa§4fÃ:µQÞér*¢MåÕï}Ü~¾þù›…y^3ÑtlI²›W]ª².IÓ)žÃM sû¹AËelóIê¾;»ý'X[ù+XÅSß (Í…ŒÕaêë<ì¿@&^ß{1•#õã|JЧÿÅX…P]ÕsÁXa¬@$ÉÂÛ7/vÔM[칇öáçÈ=´›¡cÛåòÛ-‡.U!(®ÜeË®bÿûlôçTš…„4ú£¼¢Ôj­æ¦Ç´ÌV÷égæ";ô7g¨Â•Ãóà ®Q”£¦Ñ²ÐÒ|–m¾qL½Û¶çÚó¹¯]¡M ö‹B²âBÑ€´Q†^ÈìZ…@7nä,Q#¸êÈõ ×ÔÏÀÏÛaôÏQG&q¢Wzb•€ 5êPRŸ_®j>näû{ÿzQ¹S‡Q᎒¾\K' Âëõ²‹dÿL.0ý³Ž;ú€¿ díž ´8I'˜)^¢«5ó¸R«â&?ŒM,Ê%è A¸û¢G7ä-¾ý×>,07jk‘Fû”r^ŠNE§¡åÇÓ Âè”~ÿ`‰PxºšÇ»ÔÊ÷§ÔÊØþMjeЇÔʯW5>ÆQHæï×9⪠öJ†Â#. m=åŤå€úT–šõ'ìøñøÄÄÞ[”¢P,Lë.Œ°òÖe—á*!æèð90[<ñ\ÖÁöO0mçšžõÀlÏ=É<¾÷Ñæú­Jgù+•N]MÛ`'CJúíSüò®¨~áX©ØéZ“ç» èžSÝÚVzÑ+A¡’Ìu!ˆ{@/1óù¾&ôÐ|ÊKݼϋÌV;Oz¯½¤yB/wb÷8v¡V´6›vb»iï/ÛP•ãªJuòˆç0<.ÂÌr+§¥qStÇ“K¨¬¬ ®!v{¸<¢ºèÆ<´ÜJ,+F•Ù'ß¾af.;o`1X·ºbJ} :·0/"§µ›vË«NÇ‹b·0ˆ R"iƒÊ˜g­kß5J…Á.|;ÌKZÆâPÐï¨ØÙÆ°¨Ö.Jãr­ îÈiþÀȈުs díK‡¥køVþQ {u†m½NÀµàP?µåÎ]¬8Õ°s++D¦v°m¹Úòx®ºrU*ÉŽ %]ëÁìºóÐ?¬ÏIîãèÐW‚¸ªåt‘™Û°MJE %R|ê)‚8×ÅõIwIpò Œ;èôwûò€ØëÄÞô Í,–4îã?îÕ ØZ¯½U·p¨àiÐ~%Õé0ÆM6nt”ÚioÃy”ØÑÎÂÆ½6éÑ+xgm³Žf[l2K«¶¹Vy­B=Åt-§:ádÕ"XËÿ=¼Ü¿ _ì<¨×ßxPãø9¥“«åVò ¥Hi˜€m`ÞÿÞÕØ+n@|T"Ò€¸•"s¹µòû]—ED%>yçì;,þœ>•Ò)¢ó‰KÙD±ý‹~¢N¹]®E[`ï—³>/»ö†9ú]^¯êS©œÁ¥=ec#œb†}å»ÿhþ&oà0ƒ1-(ŸÜù›õ‹¼´bƒ¯ÿé`œ•mÑJ;U+.Õ*MSŸö©e{»÷MëFÜ¿AdV:VÌ.eI&ØuÝ(­VµÛc­+¥úƒ–Uᜯ'J“;¦.7oÜïï×½€â6Ìú‡<ª†• ¨2œ¶z 5m Ûp"síK¤ù *À±¼^LÙðˆÄ6+Üꡯ5×[5–b#D‹Â2³sÊÎnÔ•»âï·>Ã_‹á;ű;/²p*: S½JÊ1qvDõžkÛʲ>½T„[ u‰¼Û±îw½BV—èæ:¥à7¦ÝfYÄ“ *tŽO¡Ï~ØÖã6Ù¸ôµpâWŠ~©y¤?TJWQ>£9ls5ì¿ß¦Ä6 MïÒ{\-È3¼Væ[¼ÍÝŠdS…LjGsSbJ[V†Ï¿]ôqðWÖýçS^ „–*ï‹ÍâÎó¼P©3Ñ=«ÒBQ,LK€:›P@‚¾GU4nÀu‚#ÀÖJT;Þ<‡_)?Ê$>N°qû™¶é2­ó´êíßÿÞþ ¼lžW½kúÿÚÂ-Œâq‚ì˜üƒàKAþwÞE¿ ÎóÍ€t:Ã*N³Š•¢P®3*…îºÒ!æ¦T¯5£äƒ>í6—2W`èþ­¡fÜ9H;Ä/Ê ú–‹öŽ­°ÂªØt…ÍVÖ‰»¦ù¸’ îU  ð¬åV°Ü˜ìÐr˜›ŽÊlÌÒŽr£\I¸ñÑ¢|¸>2Ë´®w›$¼×ï]>SËМî¤Wc¥úL§šò˜‘ŠìcUæ²Ó=fšþ9ra'QòÐ&3TVR72_R:@j«¢,Ìó¥ê‹RíÛ8ph3`žæÁ0þ‚fÜP4tç®" ƒuÑ/fMÓÒ·•ǃ¢›—·Zð0ÁA×UÛÃoŒ”õûõu†Ûœ5×èK5ÒÚ ¾1GsÚBÉn“%¡À<‘å¡.£»i8(¨¯=06¬: .cÑR]‡fVýÊ>[¬îÐW¢ë–Þ€u©þHpø•:  ®mSöæ¡h~¨¾ /Zs¯ÿÁkC›Žyr›]Ë|Seµ KZ®åšÉšRuÊÝÐ]=ᑀ •EÆ¢¿‰Œ Õ“4; ˜È5 Pc^Eõ¡Y¾Šx„G+ÖAï(OÁ¥€ eˆºÞ2V+ŠêiX uÈr6fàÀc‚nEú«qŽ»œ»<ÂûÊý— HÈA ``wNÎÞ)܆ÕÚ­ª˜5Ê¢t¢ì€Êz±Á%¹tWÛxî¨A ü*Æ v óNKª°T¾4Š®Ã,«úE^€kÂÑþáÃ:Ü÷®ùäEi¤ôõ-NÌx©ð?Æ´¦®`-§º±+ól+&YÓõ؈Ò]ã|9ÓÿvÿžƒWþŠƒkÛ†ˆeoÞ!†f¹ûK`¹îSÕ%»ÏO=_ #÷©ÔP'”ÀmS3,[³0.!¾»“÷««òQ}‚¢e¢éÎÛ{Û¨ ꪪϷ~å•BÄ×zP%Œd+8I·¢õI·üqwÁ¡ ‰_µèâNQÚ¦­êçE><¥B–OŸÉóëaA\£ ÙMœd”U×Áí¸vÓ§$[)†hÕtó I@WõºyE¼Ç‡]üÞ§}í2ðèÐ5ýîLË3$ºUÝæao97>- amªH—O뢠­/üÄ ˜äX¨B2ÀK5Mµ•€w‡MÝ„²¤î>Ý×T\å€yÞx;‘¹"¯J„õ{J\ëaÜ9ˆ"­¯Ne}-©Ûoö?•ׯÝJq¯À\Ž=O%<ӻܨXë%Vœ\X°Ÿ§<˜5(½0®.õM ñý½ ˜%t¯µE £>Ô.½¸Ëmɘ$É:Në”j–„ùÒ²™2 ZÛ8§ ÿsS™{-°¿NÑz¢m×­å5)µ¤Ua,Fâyé›7Vë*Í*úR 䀙ÔÃDúR]Og” ¤hÿþvIãÞW”m/ð>ñœ-'Ø!Òõ9T’´«!oåÇ»h¤ÂK,€ÁÜ™¶ßèó‡uæ€ë/Kʰ+N£d:3'[¶®‘nçe+GY’®O BÀ6sÎ/ÿ©…¾í”ø†‰Í\)hõoMu’ƪ Šd=àñí°¼ó8;éÁ¡‡ò Ç7$:_’H…aœ‰~mRMiå¢igR^IO= ã:§Q–FS¬(&ÛO\ÈS±3ÌÕœëyèwš·vè®AÙ™–çû]¹,FºÊRJUh£u²&X®>Å7kp–î¾bßG¿å/cJ¡y|Ì)šgl§æÓÕ§‰[›ñOµ·ó_koÿzaønmÆ=~=×cá¢jY,•vÅê D½Û•VîÖˆì5mÓè÷ ?nøäp´ŒS`n*˜>À»ªWÑO½ §¸¦[\uÂMýÍ{ð?€Z0Ùƒ"ÖDÙ9°l‚b:L@ñNù¥Fjl瘶W—ëef^¢9,¬è¸Ö)òé²þ@Ýü CÅ"ÞÒ)Õ’¥]Z-a¿®[ÁŸŸqj˜Œ¹ ®©Ëm,H•Ë“¦á߇´;–ôÅ•RN´¼Â¥TqkYàtÚ”·ç;½Ò·N(äœ;œqE74ajYÒ6|ZÍð1y;x4ö͉’Šï£¯DI›BwrI ÜZËÕR nUº¤ýÒǼªoaš”žo]°S+V‹…ß *TcW¬ÕÀjzyzž§i¥ŠQ*o¢’[ú\éþØ>Ä¢ ‹!öKͺßL~z¾w—ݲ¨e»`'?ÍtÊNMSURÀáÀEž‡z›Ç`ãzÎ)¶ÂBÝSOÉÀÔ!b2q_ÇíÚ¹V¥ŠC.»ª™àWPÈ:j˽é3¬,}P2„E¨àî˜ C2q², U›–,ühµ S3ÈF;ÿ|Ïw5 ´^æ62Í~h0/ oÇÍí"˪qHÃE§Š,LÇ12 ÛðqŸž0Cøp04ä…K6gË ºÝXº¾(įZÓœ31¥¡kÂ%ÎІÆyÈngì¹î77€›´iaê9ôâ*)oãL/zNÖYrA¸Ø 7–G`œ{à0õ>t£_Â8”£Y8zbÊK;𥣷xÝÂ}i\¶t)ºcû¦DþŸ:9í¯:9T Œ"¬[…|á£Ø”éKźlU_A{l'6q÷wSTÒN©êK:mÛÈi&dÉà™@ɸg™,{ëÿÛ[ð/Jß¾ô‘Æ£ |{¤5Oã¿õ[¿ÿ÷ëÿ÷ëkïçuŒê^õQHŸrÒI‹NUàœØ®JÏ?)Ì\4¹؇_v <¨Ò¥l‘²±ƒno[7ú]ý’0¢ýzh+ž*Þ(_JÛh«Æeä[úbPZÎC'ÛxAÙoAä‰&ʤKý5@JA—–~Ȧ&Ï&éÍ`]ߦyŠ""TܘR»wô.œ¡êf/Ü’²²è{©•ÝôÀ¹£¼†j}ÛóÌ0öÜ'|Œµ•>V¢M íºi’¶\˜h*íÖ(„8JÌšÕ¸ØMZ—÷³áÝ2G÷PBÖ+k µ ´ ŠÅc3L”Ít:æ™Yc‘&šÂ%ãm˜åûÚ›³`ƒ@¡Â;7õQá` øOÑâŒvk[²J/]ùrVùª×¤¡g˜¤=ãxºmÈ™g¨°?ѳú}Ia7l*ñÚ¡½”1}\ÕH5¯‰i2},ÇqüÓöÓ²?À™_+Ûrïúº%§"ôû'(!‹¾î@P„@Ÿt«¤¨oZ8Lgæxw”f’¨BÕÐR‚ƒÂØqÕØT]öK]©eµ<,:4¡ôùàõbÑ[S‚. ÎqÐèèÊ¢onû2è)'ÊoÛ±J¶uP½Ü— <ÏFÍ<Éö‡ÎúuæM0dÇ´}y´Dip uªªqþPp¾0m@Ñ¡‰ .ö}\û#ä†8ë+æ_=Î4qÈîôb¨fÔ*žjœVœRÚAXÑDæx}þ{ßëK²yRz<($àayÒ¹ŒÖ¹J×p«;^ÒP–iBqÁ83ûãrÅ,¬f4¾ X úuÇZ¥ª¢'gzÉ…ÛF‹RLq\YÞùàO—ò¦·ÌB˜@š®ÌÔÏl«œS¼†$×]½uÚ,·ÒmÜc®ËXoïdx ›êýS û÷`Ø(¥;ù ïîßcþw+¬ñÃ.$¢Љèú:Æ¥æ÷?·õÝ—ð…«®/hÉ’QY Uj«±ÚVzMSñª%‰ #²ö‚nÿ;¹ñûëu8,,XAÔ!&7Ö™§d¦#•3D‘¢žKËB\ˆçàzŸæIŽ¿2´™áF%“Ís‚dýëÓÄðÉ;ʪ" ¤ :y7˜Ê§í)4gÛÓµwáÆÃöt ‡OÇ2]û W«íü€ÉŒa™çÕj´þ|¯ûõW"ÕÀ@²îö>rQáÄ•J‹"–¾)…ºüá«BU“ç\µyç_Ô>X`Ul!-¾?Ü…Œ—°ÈóµíÂ2ã~7 &%ˆô¬P»~½$ô5›^‰Ý5p/ô`ô¯Vé†n¨žþóÿ}˜”]‚ÂÉCæaða|ð^0 à .´Û²ÔéÒP¦ÚÐv ðù‚¿§1Dì†þpÃÿdýÃwÐcÁȶ ŸBl6®º‹é».&u Ñ:üÇëöÇ9 #ùu]ÖóÔ$°Ÿ•šúã>¦Å”lû ¥?îî¼e‰z-E ˰%n(zVk•§ÛB½¦?0Ló ôe®0&‚%GB¿ V9¯*UÕåÖmªƒñ”Å6œp ¡·Æ’ÞÒþ 1Ó3Ð+^QƒiCÕ¦kSmôJô’b*ö]:>+Ó=VxžRó”`®ÅˆË´k5´)Æ,¦,À‚†·Éã)îÅ6Æ™#·hÆVYA(!ãvT¹íaËâ4NCÒøû –aÝÞÇÀÝòkÊœ¿'Þ‡†ø_M¹ªŽ5­€Ø Ä”%;ÂtVÖœÅ*Æ×:´EšrQ]§å¸týŒ7j Xt»¼‚íÝÞ¨Z¾*@ÜO¦5Êm¦W¢ª¹H: ]´‚a|ÆÓË7¹=ƒç*\a-1Û¦™jÀQ¶zKÃ5N°Bày.Ĭ,y†à¾³0<}V°;ðæ?xqEvR”ª·-­àº”ç€ÈÊÕ0­p쬎÷&+àágT%ÕM ÖQ¹Q D5 ªÒxüÅ"žs[äû úmú ô&0n„afñ\öE® - -Ô3ÜXÿ㛾䛲#Xqý–bÒÑRe¹¤x 4y‘]›Œ£hlãö[ gõ-ÆZ Ÿó‘°Í'âØ¤”¯µê—‹åÿmâ³z„› regina-4.96/engine/data/census/closed-nor-census-11.dat.gz000644 000765 000024 00000130066 12400005715 023161 0ustar00babstaff000000 000000 ‹]´åSclosed-nor-census.dat¤[oó8’†ïûWØ›ÝÅ7èØ²-§¹È`±Àb Ù™½ ’u (‹1%Ë$‚ùñKR’upUQè}¸ÒâX/«Š¤Ìä··ÏÏSšdYšÉÆüÛ§¿ý÷ßžþñ¿Ûßžþ}ûcóÝÿÿùôÛÓ¿m~ÉÝóI–¦YËHæŒÏo»ç“43ÿfµŒ”&Ÿ~ÉßÞ>>ã4³ÿpÎcñüÎ>ÿú'¶ù,Q]$ñüÞ>ÿþÛȲkSUuA=0Ï¿¾™çO¶ýó¥,›öD<ΞO«2nê‚xþ8Œ§}ÝLœ.üDŽÿËlü™6ŒçýºkÒQ QF|{Üö¦®c«<˜µ^׬½ª |7{×X%—¢,ñÇ÷wéXqj#:ÏŸþþ¤Ÿþçé×§<=ÿØ<ýëióãùi®ÌÔ*Yh!„ÖøãۥЌôüñÇWmTŠ?>U‘ˆ8åDgö³Ç/…à%'Z?Ì&•i'Õø¸}ð_úÓæi¡‚έL1ãVüùí¼÷¦;Ŭ;ËçƒÙó‰—3›?¿ð{»}|–Q–æi–ç\jD¤~”}0êxDÌ¿©I‚QËÌD†÷² yîbƒl80"dg‘·Oƒ¤¦[¹yù¦´•=ŒPVy}{-;æ¹ÕŸqaC !Œ(9:ä½ìDÞ!i“–ò#5åÊgÇ|”§ø”YF)V×QÎ"ÁÌûý»Ü­\URâÄ&Æ÷7J› sC˜HY«´Pod¼$L䡈­%^ ‘X'¿T—'î½J¬³üÚ4 /KÂÆî—âíöm&£õ{ÎÌÄbÂÌ-¦åíÑ)»q„'s˜¡NìDR[C™ùò~ê' cýŒÑ5A%AÙ÷2³ÆRnÚXÊÍÒÖ£H[Cõª›<Œõ³‡•b”utÔ»£ºÑèçkê£4§¼üü(ŽÇþÇGŠãNáâ( GCP¸8([¸8([¸8j‚ÂÅÁ ‡"(\‚ò²ÇÇÇç)²µ¥në ©£Yƒel©Ä‰ÃP\2Í"‚râøøø8E§ÁV©Û4ª/”-'Ž÷•´ªeÅñz{ýì†ÃöÐ Su$‚ÚcT­ªÇ[GåÃÐçœ'5A…èȃïµ%F^ #¿ÅF^P#?– ¿¨îü%(M§%èeª‡ÔËŠ BÔ_%AaJ!^žMË÷S_ø˜Þu•Ï‹&eÉ,1qcœË¦”¡ - ¹‚´{UÓ,5ÀÝ# ¼{%u‰áÛŒyj fÕÎ…æ¯õ‚ÓëÛw/ –;Q´¦ä%m1¨ä8„vO@ÝÛúºÇqÈMà›ÍÆÉÛHžÏÒ8w¬ ƒe­:ºn ¶µI …`K:* Cf LûþéfaæÊO]«Ø”â8´{„Je9íAKqRt˜¿S7BÊ´!Þ)t…‚µ”¸Ôm!i–Ž®{¯]÷R ¹¨‹„°ô2…îïTs•ËÜsGIã¨ôr>óµ5”]. ’€ÆüÔ,Æ|má&Êšµ~|ŠóŒ¬(Lx&JÈûDœr…‡‘÷¹Èm¤µv±éfo¯‘E”– ÁŽûžrZ›¹XDW%n7·g°Þ^RÄ”½ýÜžå:{ç"£ìçöfb»Ÿ×s•ÖÆïÜ)8)…Ÿ;vÜ÷—ò[Ep/·ì§‡3Ò£PÁ„ch£PÁ„ct£PÁ„cz#PÁ„c‰F¡‚ Ç"Œ@Že ÜñáXè‚á~ îøp,vÁ? F&ü ‚ÑD„¹s€`4aî FD˜;FæÎ‚aD„¹s€`˜¦à‚a¥Ÿƒã8Ìñ*¦¹ŸƒƒoyIÁà›^GR0Ì‘ŒBs$#PÁIÁ(T0GR0 uü‘Líç@ÁÔ¨ã¤`”Ÿs‚±ëæaµ]Ãr[ë·Ý´†¹}Á®p5´å´[pSœŒ]; ëYc¯_<“ö‚GnXªKEp;ǽ/íÙ4Éí¹a¹NöÓ æfŠÖ~åm”Ý/½Yà .D9­(®Œ=»³«ïÂT®…[~3³ü÷‚pÒ,ö)Ž < %éCq[Üñ°#T0œL€ F‚ PÁpR0W0°ã¯`Š#;>𠦦82ÂûJûiÑ‹EŠ£" ÅQ¦!8*ÂPa¨~RFaÁQ¦&8*ÂpÊïT„tE„¡8*”GEÊa(ŽŠ0T?©£ŽŠ0‚à¨Sa8å÷®èýp õ»)~Òª¼¦L6__ðçC³¯‚î¥ïÉngÚ˜­sQ¦—‹—ÞÎl»ÂÒÙÖº9'^ÚIèönl'©±l'ªÑò¢ê¢ðÒNH·Ûó¬pþa׆'2IÎ÷Òû±´=õ%£ýB+­¢FúéIalðlßáùYzépN÷¶“2Zeû8ï¹µm¿E»¶ür^º“Ùw/³A-ñµH’ìæWËó¸’˜áQ5µßLñn!bûÞž“ói¾ãë·gO~ÜéííýÝ}âÈÜÈ].ud2¸Ñ»ß xœ¸øãäš^Z%êÂ/ö `on¦åÝÅèµÊ¯×¢Š3?~XtÞô¾ï|óµbèÂÁúÉÎc»`gE¢hÌÿýxÕl4Œ³~…Ÿ0ËcópR3.ãBÐŽx·ÇXW"űí|Ý9lÙú°ê¤Â:9ß_\vµ¶Ø^\tRx1 “ÉùžÖ¢“n/± dš{1°“ëä‘ìdY;’T^ÌMç×oÓÉîœÍpýA›Ö‡f»¹&¿ûÄnóNÑµé²Æ±-ŠI®p ï$;x;Ék#:Y*£FR<`ûùÄG²Ä1j$9ŽQ#©lÅH–8F$DZ`R¹å0û©H¤ào³—µ˜-í±»)§Ì¬³çîæ_Æ”î:üá¾Dè§lwh©ê“«¡î^\uåƒwpWD¥>x?Ö€¶Š³%A¢¾ »ÔêÏ¿ÿú5$¦û0M®llÍb§V²"]¡j­¨ZË¡F^"fHnv«õӔſlTº*K–ëò #»GDè:W)n0², \[åfI·Œä’¦ ‚„¤p…EXÑ09ˆ2Ö±‰‹&FßÅÕ“cYâŠxS–Ä¢IE,f2L˜tÈ0f‹,s˜¼/sþú—ßÐuQÎ@ë4W°Å3R‹™9À2ff§W˜.xXwh`<_v™7,xæÀÞêñµûߎ’aD!T¦úTBÀÁ øµpÖU¸JÖ:º|1±uç\B@WG¾/MÚÜìg 0_Žksn–yè¸çñ0`X]u}Rµ‚‰Íx¬2³qK¢´‰NN¯ýB„õïÍÔ)ã TÇ&˜}¯ q t^¿Ü¸ËÜJ°›ZÄ >f+ŒÂžc™e& 40ƒ‰ÃĆÕlg#oŒ ÓPbÞF.MÀBláxeÖ=—!ø,8D×&Bˆ-F"¡ËûêfA`ó{²ïñ׿ü*‚ßVì•Ünéµ@˜iàéwgLr#Á]_‹“QOÞ§yÊŒ^Sé4ʰîm»àðî¾Tî¡¶àÂnÆ)lblïkóÄ‹"ph÷˜F­sÏ:IðîíÁ d --Ø ƒÄÃÄ63+Mµ™¡Ð†¤…Ðî½À¯5ÝK0KÁ3i‘`–‚ ’)MŽv/ØÂPi!´{šaëSD°ƒ¡üvºàÐÌÌyÞät@Ó9ѽÉèßîüá¶{&vû£M2­ÚŸlØÄéÚN„úY_ö§Ý ôå u+Ty+<¿þ¾ffBÅi›]ªŸm|‹5nÂçO7>ÝR(26ÿ ûsÒ~%ýz¯v»k©þÔ±ËLåEëXÙv›ÓfP_®Ã‘-Ý@í:—gU·ÕºÀó¶ø«œ·Ñ ì¡ÄW±ºÃl›¹Û›NÿjÛD”k@-NÆ…8­ià84`/6ê¾SµâŒ«k³êî ÓðiÿÛM!Ê[*/Ñu•žï§ê®±~¼pÝHÖä×vU ›ñ%’þœ£Vé©Lku]×`ë^òÌÕP_ÕªÆú9sb6oqýÒ\~Eyq^ÕzXˆxÝ8ì±ëU-àÆÖž0®ë¼Óë>ÈÖõáˆY‚¯ëà ւ™[«ú0ž7š·`EÖÍ쪪šê¼2ºmÀ’¶I’•-lÁmÕT5éýšLO ØBkVÖmº®…üɇÕÃu] ð޲;³ÖëZ8`ŸH«Z±Î+gÖvªIÖmÛ›q-E²®SMöÛöؤhJÁÒUéîl!ºš¢Ëª¦Ö°.ØÛ·hM I²ª…-Ø‚™¥¨VE¹þ,ÃÞEaïîtÅžYÚFZ^u¯ja7oÁî8t-$ú¼®pØÃ‡0­ýÆÖÃæ±ø™4`¿êò¹ÍtßG‡¬¢ƒ¸&…':lë·±J\ªt]³ã¡nUm_¡ÒÑy]È—mv¯«@¾s³_šèU „PÙò¢ªU+¡6î‚“ç/žìÁ¶›Öe™”7YÄ÷¤ÿŸ¿~mÿ _A À±óô+÷ÁÛ_Ê·Weº^Ƨ810/ìíÇÜ~eÁ¤~-p·ªç(·l‡~±/í¬¾}Øë8íO졲áJÆåõþ®å0wXT½¿w¨q•»®¹dÊ,H¢RèniµèQcõÊUJ ûÞê‡{W³¢†©6rio5,j‚Ä÷p)ªý˜x¸¼Aw;Æ£•ºàñ0žˆ”î6¾ïá2Òµ×ø1è–ÇÃx0‚£ZCW=&Ÿ¸€rR¸œ^ÆO¼A9)\N/ãgÞ œj\N/ã§Þ œj\N/ãïQA9Õ¸œ^ÆŸ¤‚rR¸œ^Æ_¥’r¢Pœ8zäD “GN‚’D/§×et’R3Ét ±»™œ^—ÑÉ ¹ÌIt{÷NçXÖÇ ³†ªÎQÍ 4X:¶C¹ô£»¥Õî]Õêz£P,:I?JÊIëš@I9q⎒r’R()'0&Ž’€£“æN›çñÇPxr,žFŽORàñidáeX4@,¡:»p„YPSšÊx#KÇ(ÈG#K)(]Ž,¥ EŽ,¦ „9Ñ",Ekã–"„µñ‹ÂÚx„Å am<Ââ„°6a BX›•Ââëi×#,A±a‘ã '@M%@SPSpdá(žGÌšÊ# 'ÁÎ.œÉF‹XrK§A©(–΃`䨬K„º¦X:‚‘r³L…ËÊJÂÚþØ“¥•"„ug‘Úª&„ug‘âJÉ,R]Õ„°î,V­Ë¬§¾*)ÖS` ŠõTX ÅzJ,ò}±ˆ%a¤°:V@ KrBX),kw‹D,N+ …ÕÛõ±žˆÕP¬'b)ŠõD¬’b=«&µá„u{û´^¥¿r±Û‚qw.FàÅ5Ó*÷7Pº[-Ø£Ú–´êdõööî¬vŸI8«ÝÍ‹eÕ©êí{ŽÞï&ÑÝÂ*+îV“".îVz¿¸( ôУjºËz´ŒJ®vвag5ï×½ä\6MD Çíþl޻ލ…»øŠQÃô‚¢öî+I “ON »[#'ÅÔ#'ʪGN%zäÄ Ô#' %åTÂrÚyå¤09íVÈ©dT‡I9Õ’”"'…G§p¶ñù('…G§p¶ñù('…G§p¶ñù('G§p¶ñù('…G§p¶ñù('G§p¾ñù 'G§p¾ñù '…G§p¾ñ‰F'ê]=Ñ©¡$ÊISÉ.œí',天dζ–rÒT² g» K91*Ù…³Í„¥œ4•ìÂÙ^ÂRNŒJvá|+a!'F%»p¾“°“¦’]8ßHÀ䤩a¢å]}ηp9C¼[#'ÅÔ#'ʪGN%zäÄ Ô#' %åTÂrÚyå¤09­Jvšê0ì`9­Lv c÷k’,§ýªdGYõ$»’@=ÉŽ¨'ÙQ(™ì9í½É•Ó~UíD°§vj(I ÑIàÉîèIvOvGO²x²;z’“ÝÑ“ìžìŽžd§ðdwô$;…'»£'Ù <ÙW&;ʪ'ÙQïê“8Äû5rRŒ@=r¢¬zäT¨GNœ@=r¢PRN%ìØ½WN “ÓªèDZõ$;j„œìß!ý.‡?_jÇiP›™Ý-ï´èëç{‡n3Ô¢Ìn³i µr²w«‰»ÐYmD§&Òj0GíÏÛzÔJBR¨“ÓíõµÿÓÊÖhÁ‡;¬/ tO ZrÊê¡÷ÎûÝ;ê«'Ðtü®Á çHM¡´sH«„JÚ¯“Ôû•D÷*iILS& į‹Ôú•ÍÿênùÇ0T¢’˜¤b¾Öè~ºCÌW E$Qã~ÝOwbˆ©NYE$Qã~ÝOwbˆ(Á ô@G ªÃ!%(«G2JÔúBj˜<á§u†B=†B‘Ã)%®‹05"†SJ\a…†tpúÖ®m7zG¿ÊÿÝè”ì:5ÐìÍb Ì^-—’\.KF0¿–%»l—H;QÐ…ü¤(’¢dŠÂÔtƒ“@ g48¡\s*ÑIájt*Ñi]‰NÔÁC C x6!0®x6‘a\ñlbþ„ÎzD'ÇúŠg,C g½™”û݉³ß9Èöy.ôž³øö `«úåý£ß1éŒé§OÒ€®ppëCp'»byLJéI+cQäI¾N`?— ‰e™¢~9¦m]%p%`Û$8¢ðu ¤ ½Ýße•fª>ŒõmOe×Ój}Î8lÝ^æ”z ¬¥­Ö)ì@ ÙF }¬’ @:=ö÷Y÷««þ)œkÄÖÕ°sp |B¹^û‚Ù ðeI¤&KV´ðCDΤÿ(L{È™4#]PHèH!I†ö´…# C¶y'„¶QœQd[GAz›ü¸üÍå[YºÚK>²%J¿Ëtóu ;ö jý¼ÿÝSˆ™¼¿×ËñË¥#²îYÄ1Q`_¡ Îá^?_ùØ©e¨¨iã¯(¢ŽãÞßôÊÑGmT]Õ· tE˜¢ :ä2¤ò¨v‚Zbß?ÆQ„Õ½¶¬U'\d8ãzذܽàzXפ³Ãõ°‚: ~½ÿý¬–n™ ÇÑ2| 2t9´V–Ý'×) 6ù1ÈÀtÖÓÍERo…¶I5йª¦æë±Ú9àzØ Ã×ÃN¨¶ÈpÆõ°>n'_ßÄåä02ÞÈW +¿Z…»›QP9wOÁ xäñu‹rÉB†>Ú+ªÜBÁYÊÀè(ƒ¶ŒÂ5é}E{Ó(ØWFq0i’}E“G“ØWô Öî·7= ú˜‹Æ«X¶!'Wk÷›üÓ­Ý‘…Ì@ü4ô<¶¾fíµM~êQÐÞ/úÙÌyåm°êýn6Š)…†Çß°1 &=°/èaïzÈ6ëÁ5é}E{“ØWôp˜|Œó‡O€ãƒƒÞºMî3 z1>˜X¬¯›ûÓHA¶{×e¿÷œ†Txô âäçdz òÍÇ|Ý//¸Ö5yØázØ Áõ°nQ×Ãú\z›” yߊu¿8¹ø(6PØã£Ø 'åádßäö)ˆŒQWšyi»NÇqªM܃BÕQÈ6hò4•Aµî)tªìþl‘áŒb]†ó >ŠuÎ;|dPqòãý“«×ú"ê9„¸KLÞˆœw3îÄMï¦Õ"À‘A¶c ÒÁ¥­žóf9°´rEZ#Qi“„îiQ$*íØ<É„Äuk˜•E«P¹(×®ÁŠ>`Ÿ‡ºh! ŒAW®(n-3A7 Å-¢ÈèŠ&g~å¶` ºbÂ%]Ѱa¬Î6Q芆ÕI¦èëg;åY~½½ûy¦·“gá÷mQRÚ_‚¸r–G0R§Æ¯z˨ΔÆWž‹ F®Hkz{ÙÝ ­0Jën–¥uQi¨ÛùÃgi¨ÛÅýBP· F¥mK˜ß_[JÛ"–°¸¾I›d0rEZÓ8Ý Ò £´›,Á(í6K0I»ß` fi÷›ìá è6-á´b h §–PÂÈi™¹ß ­0J»I·Fi'º•,»ÍK¨ ;:(癟Ha³© JÓ›ØH}w^«/J# ‚,ZQÂHLÚÄ,­³.m—› Ip ±'ä~5! q#q ±F®hȄܦ!#Qi &`$n}å”§¡”Ñ-‚\Ñ-‡‘¸nËҀܤ[Æ`äP»¥>‡ë ­z9°ôDüœJ‹Ç>ÞÔçÓþü“*|OØe ¯/%uøþAAwÁ¬O …`ñøÌŒ× èÛ+ÐüZ†| ïâøÕñï§Ç}òÍ©ù4碉D“F«ü8~•ÿqZÎ0ýð[Ër†¸Zßp¼Xß§¥ s|V_ï«øÝP ña Ð^Ùºîp V5°#Ó¯ï 44[—ÀÁ ¬ÚÀÎÅu°N`o:tVþïQž­ë@›áüÌYŸœ‹¢W 1 Ø N b›ý­šù Ó§¤ý9+ë"®|Ü£\¿ðòOõ2å,~=¡²¢åªlS¥ ºÞ>Ær,õq¼½ßEÙMcF9s”:ÀdU´mq¿›Qî’—.ýÊ›.Æ ˆ×~ŠJhÜÇåNBÏÏÛ4Ö¯%ê0Eu|úv²X.¬o”å—KÔq΋Å#¯úÆ)Ǫ“IB&Q÷–'êl’PãEõªÊÔ¥ˆ=³ºI¤UŽj‚õ-GÖG“)FES”,›f ELF•FEŒ¦8V$FES ØhödÍMVLÑ<ÑdÕMóLŒ¦ø@™§™LqfÀF#&SœZ°ÙÇÈš)šŒL·GqœŒÅým‹!ëþŸüù|!ÀXË~I.„Ñ&ÿ®·ÿNÖÇÑRx—¶¹›0`ðaǤ(‡ˆ=ǸH9ï%»ä&Ì~^<;ÆÝŒm’ ųsÌŒº—K)® £ïz½YøPÖ™?b"7ò9-0Ãüt?cyiÂè³6šøx×!ßXÌéËü‚ùÄ‚ ½ÍŽRõýSj›ÕMȆìrÒéUYjLc=E^&û" o¾,@ÎDõõéYÈÛº2‹çÎÅ‹ûâ byÛí Ìâí‘2ƒ,.#è0Ÿ¦xøÞís2QÛ”èˆ}DÁÍcQVW<çfí¡Hµc1‚ˆ!)•WuÅòª6‚vÈM›§Ø@ŒŒ–1Ȉ1ÆÄ‚Ä“ ˆ'‰' ˆ'‰'OO2 ž,šÂ.ËM˜JæŒÇ-#F÷0—Q C<™{yx9™Ç“¹—g€—“y<™G.D.2'óÈÅ€ÈE¦ñÄʧÐ@fû- ÎhÈ"ž˜ ƒž"1Ç“Göe ÄO†Ð¡˜âÉ4C1E.òOüËxõ¯éØÕEqMóÑÆÿÈœ?7ÝY¼ßkúHk0‚D¯0 s¦°áVZ'\zeÖ0ˆa´³ O49ÛiÑ­ó—¶¹èW–©ÀŽHôÆÇòž`§LÝ’í·E+awv^ÞcÒ¡³NE9 Ëé~7Ü—K[<Âç·ïM‰2Ža~ܪ{^[À8e)ïê8s¨ÕêÌ9«ëö&8hÎÓ.Ió°F^yqûù½á ®‚¸(!œÊgÞ__µœñ(' QCþ3† %®³µÐ5ä@;8Í•5'PŸðÒÔÖ”] ñ‘—é±òdº¸R—‚ƒ8xŠäB8%Ê´¾…ã¦îç@¹ríS1v`}ƹàšxo;-¸=”f×ß^No2¾#¸¢úÝŠZ´îeöôÞ†ÈøŒu«²ú6íþ>Íô<`=¦Aáv¦%¹ç×-ÉI…Auû®³ë!i`tÜO æç «y:Þ zƹîZ·é…Cóàì‘D€æ¸` \]_éí‘@,qG(‡¸Ö×.ãå3ÊæâaÂì§>3TÀtã©DX‰ñèsÀ1¥ s4]Üí+RïÖFÆñœ˜±0C¤~zª{æ˜3ÎLjٽàŒÌ†°Cj.ØÝ ² 5“¯ßr0N à䂜ÌizÄ¥½ø##ÛœBxåÄ)0Ì/’hxÙô ¹FÝÅ¥ÆËsq46£ƒ„W^•´*Cš°+ì&‘w-SÀ`O‰hgÂÐØÎ87pº_pv”»É&õBK«àátQçÇÇâ¿éÖË,ô®Îù ”Ÿ ó㿽.g|Lºváu¿Á}^ÿzò)¯á³‚üJ±« C` ‡0ŽY¶‹”- ×_ÿ2ThX]zñê+C‰ãL¹ö«¬Á â(TˤJ¼¨‰“2 ýóWûë¿ýñëÿ~íÛýúϯÝo/¿F9»-†Ü›Ò»ûX"‘a!¢êVÂHò¸¾/‘шìÕãu#•´â]!#š ÒVþÕ+Ë Fºc£=?Pý1å=‹Ê+аò³ng "÷*å`ðXÙ‚×kóîOÒÂȤÛ"§ oyD÷<yBy¦)Œ<£<“±„”iR Ð… Úm=‘W—KÀ(1C "ê Ð2F¡î:Œµƒ \à=e …ö¦t÷æ1ý4DåU‰tÒÓðqUoYH¨4üè†@u‹Í%”µ«Ð3 ½EHtx™ <ªÉëöe–fÈXÕyÂTvëI«ìR_0¨ê£ùшFj •TEU5q‡ˆË©S…tˆ-4¥eVbPК‚¼ †˜­‰æ,.ôAC 1èqG™d©8ZWU|ËnH%skJF(»Vñ%»`&qžrBƒ*îf‡!+›ZÖò|u;¨û›3]àÈ¢*2D ¥ÒA¥¥Fº(OZÃHÝoã³·†0‘Eu§]zÁÈéèDv. HØÏø"Î'²PHŽ"Ïf«ï‘wC~Ÿ£Y!£Y#Ð KºI‰jWÖF‘‡@!)ÖP¾ç#›ò`P0$y28d˜šö›&UÜ ö‚@ˆ³%üz@Oè?¿º qSí2-÷ZIPgKé ÒÒE¥-iŒ÷ÚðÙmf¾ äÁŒ, ÙÎyDœ-ª0äÉZb> äÙ̳0$XKKÀÝôÆ(î¦ì†@‰É×ú埖üz÷¨còðZ—iæcP×l‚­Nôç&¸ï ûùº¶˜šBM_-¦f†$cwjÏÕ´Ÿ1îÑŒó;¾Bþ×ìÊÒ¿~ýïÃö]ÿýöëú믎ü®_«_fžl&_´‰×Z’_J¯É{éÛ±#Ó·Éë[qo†FË~Xß¿MÞÕ]˜_Ÿ;ÞŠk-lÉï-š§ÒÓÂg–ä‹ÒSé›Äšüqz¡pÞPØOš¡%ñ·ÉŸ´ôék¯²%^J?Ñ}þ¸{ým·zYŠ?h§? ¢²¥¯üVåXÑоףuÖ”MžØÒWŽÛ7ÿ‚AýÈYëj?±ÖnX+Îy:Ô_P „¨ü&õ™×ØÒw—ôUCÜž~Ê„m\Ó'<ôϨluÖ‘g…-ýƒÖÿÇ ¥Ÿ^ÿ1¾ö}ŸþqÔO/¿Ò”?åB”UdKÿ´¤Ï´~:ú~ÉlÝWUMˆþÑßÖ­4çMR$÷·]UuÅ„~¿piú­ßÚÎ/ÑÍõÅœÇÃ÷° Ë4Iméë çbˆo#ýDxUÓX˯ó‹ƒü< ­ó}]]¼äumßÔCB½À:ÆŸðÊìM³[m-ÿቾºjÞÓOKÛø¦©XÊ/퓵ÏRëù=-éëJ’~ÍDhKÿñ芌þUø>ÿ¦ý¾û˜óZE_í¿ýïć%}2Æ7ÿ±¾HúßÔÏ’¾³¤Ï´~¾9¿Kúî¸~õôõ9GG_$u^³Ì–þ~¹~©õ·_¿* [úSüïü‹þÐüMñ_Óÿ ûÌ÷ üËèc²ð[^ÄŸT°`àjïjЬ¾î ³v²Ý~dð<‚apxÚå±Ç./¼UÖ žw©}^âùÜšÁ AH`gd^a?]H<ÜП—dªB›&a향̙2xy®Y÷^yu¸Ø“O‚äZ3KòÄTV.ë=› È’¼´$ïÌî:ëRÙ2ˆ¦^î×Ü’¼‹UÊ][Ýï ÷Ê)³†WÔ’üÁTš¯tµMžY’?Î*ê£ñÉÎN÷mZÕ¶S{š´ª {òbRÚømòg¬4±ilu¯/ǃ~µÍ2ÉšÛš£ßî¶°_•–ä<*d–ä]دÊÍ~Ep·…LgkT ¸ÛÂ~ek9G<*ØNí ™[ýЬ¹­9*”£YqÛI3Húèfž'e²Fÿõß>èL[ÒGßò&ºF¥-}2ýä2§DôÂlé;Ó·§絈ºÀ#lé»Kú>ˆQ~Öú×Õ±âcèV/ÍSw«gW/µ¥˜nì¦Û¢Nÿ?Aÿ¸¤Ïó[sÚÒWîûqÿ{l†:ê'‰Ååëöi:ù' ñk›Ÿ`à Ss/´fðäQˆ‹5ƒ= ¸þƒÃ4JO.ˆ;÷šnŠB«› ^½ sW[ú:ý™×Þ÷« ãiu¡¶ô\?|}òýðíú!ßÑÛ®tV6Õõ˜É'Eëe­%ùiU…$?¾›Ê»ÿ²–[’Ç«*„-y¼ªâbK¯ª¸Û’Ç«*î™%yCU…z蹯ªÈlÉãUŒY’Ç«*¬¥7UU Ï`‹€Z‹¯«*ä®T:V_¶§+/£Ú{>•ÿ*ýùãÓÑãù꼬y†¶ô™ü²gÈðÀ6«»ì§´¥ïŽÏ ?Ó¯ùÍ·¥¿_è‡Q7ó2¯ªÊZÿ‡™ü}î9Ð÷ó²JléÏŸÄNôæu9¨µü§}Õ·§ï³ZP[úçqÝ’ÏH'q¯ùœvÚð„·_žßßÍÕ†&ú´¢Ìš>™¯»ÿâEáöô@þì‡ôãÂôD?{“~ØÏéç°ÈÆÃ¤Û‚ÙÒW«ãû§!u¸Ó[Ó^ª0äâúxåÛôÏ‹ÔgÔOXåÕõnM|é˜nÍ`‡Ï€=‚O=ŸƒÌšÁlw=Oá˜G+k#Õ°ß? IÜ=¼–šÁaúØÈbOØ›©öãé!ßÇUaÁíçà„Ï=ƒ3>Ö“¬»K‚s`=‚¡šûI hª4U²%¨ï%µ5gɀёe×ÄšNw_ƒø1_½8l­ì— †t ªëÕžÁÁ4ìçàhšöƒsp2ÍûÁ98›æ€ýܨ۰¯oŸzS?6"ãev³f°[2x8Z•‘õzàÌ·­qéØú4 ó$·ž÷=ƒ>k¹êÞä{¿Á û'V©Ü`Vm‘—-¥ÖÙµ«nW¾Ë®µ=ƒXí`%A jU¸.>{{|ö*: ÞZvýüqÌømúB¿š9®Ò'h…AeM¯ÖúÁ+JkúC¬wÃsŸA°/ÓÿÝXâ2Ö –5Ó·"Cï3ð»¹Èãóýÿk{»ÞæueMð¾źœ>³ÞÞ±dùã}‘A=ƒI€dÐ禲e‰¢,Úú°© ÎI¤lK"«Ê¡;ȬzŠ,‹õA±LÝ,ká.¢%<áÌ €gàÎ`5í×yß"ª¹»ˆÖÓŽ¢w2Œ^0ƒ 8é>ƒ-8ƒÒ}úŽåýÉÇûK‘Ýã©»pXÀ^`,…qW|8 ãÎãG¢0gù÷ûKª¶(QrØè˜Æù^žtÛ‚÷¥zéíï? Ã{ðmŒe‡Á(ÞcÐãðØ”}Vç ߆!ÓÓ>KŒåC÷ÎÑò8È#°bdùžÑ0V# ž*Ã×bìÛqd Iꉴþá°¨8¬…8geæçS¥ŒãÐa4Œíë^Ñð0ç¹ËǶƒ8]Hú!ß9ÈA\H ‹ñlÒ^®ýl*ÞM‡âYA®?íw$ß Â£ò´Û“@–V½$OG=Þ÷£AºóI”¬E9 M•DìN'A™èk·ÄZך2>‰„²±ƒÈÓé*I Û Hÿ„×’&õX°Dìø•Òkìg×]k×}f¥Ê uUäU,ö­Dñ& ½¢@²kÓ@´ÆöYý¾-ëAòäÒÄq™‘¬«~TØ’¶ ‚Üš7t ©úö¬ ‹d CY=‚ ö¤ÉÅùpŠ÷$eSeÝÎJG"ê(meK2Þf$“‡éä᱌‰z²ôDßV§ÝÄ$Áê‰ ²)Îñð²°ƒÔ-'x6¢‰u:¾}$i;’ÚûK;HØ‚ôÄ@™ˆ˜²²ƒœ[Útî6¶Q/lv ¬ˆª²¤­Îf:’Tïâº9VQ°#eÝ™¡¦‰°ÙÅÉÆ.G›vÞ·a"oÏŒŒ´w– »y”2ÛŒ?‹¿ÿx=Êã]³¡ÞíÄ•âÙ—øØ.± jµ {ˆòƒ¾¦¾t½OK±ojÈÔµèXíœö’“@VH|MN$­ö}—ÐNÙ˜Vû¨µÔÕéD“Éflí9Ój/ÎaXefLÔþ¶s‘Ú󜢽áa(÷(ºN%ûŒ6ý²ð{§³Q|Ð:ÉË¥l]¥Ä¼>‹þ±ßñUu3DR^¯‚áÝžæn!R¦Fµ<-«29GÿöDr¡дƒÈËä"’‚±œLD¿´ÙM¤ªv¥MWÆ‹4@vRX÷ïäñòA+þ‹’G.ÃKq"ø#¡&w¡²’—ÒÌ@––n·ý‹ÊMó`]ý¹u}Hð1ø)<55 ó4´-câZì)þ£ÿfFaTUQQ0–&Œv—ãt ÃÖÓ7Ld #aØüf«â&%a¬-òh7 »^$ylÆ=uo½x“²hŽÇ½ `l§ºp·cIiÖ¦Àå®]œüJSÔÅD„ŸŠæ\A<[ÛØêpª›ª$ø6äÐÚ"ˆµ/ýþÜ“„´À k—Xyn *ÈÊÖúµŠNu_H Öþ±IkÕ²¸&Œšƒö­ªÕŸã¸)ez&lm Õ©©I#ñÆÛùd_ï[ûÌH ˆ¨¯¥lˆgkËëË?Ækˆµ­¬/ÄÚš6ª%;>}H0é,›ÉXš¥$qÓZ¦è@ʺÌòŒ¤±ÞÚ"ë]e d¬±ëÕþ¼—­²]hz²µˆ] ’“ôij5òíMm‰ý… „Ÿ›d¬±*ÁÞƒ”qÓ®iëä@ד³+«Ô’Ö‰›":Žò„ÈrÒ{ó ¤NwW’yô[Çð}}9rÄÆ>:ž&Œ~ÿÑ0Æî;Ÿb°kõ®µk÷aÄuÙØ c9ïà¬ær¨åñÈHs lY}‰ˆòw:O´‡Ôb”õ•çUCÁX[|Šó%î,´QU õÌhav ½gœpavä=ª®_“íQp=“#ï=é„›Wê„kç×äÈ{Ï8áÂì„{T'|À0Þ3N87;áÞ3N87;áÞSN87;áÞSN87;áÉ |Eav8=’þbp8=Ä {òÜxˆ>1„â„=yn<Ä ŸƒÂæ„koD˜]æ„?€\ä„Þˆ0»4É 1¸4Í ×.0»4É nŽn<’þbˆn<’>&ÜÝx$'üÄÝx4'\ÇÜÝx$'üÄÝx$'üÄÝxD'\E7ÜÝx4'\&ÜÝxD'übˆn¼_:á4ŸqÂ% Äè„s³î=ã„s³î=ã„s³î=ã„s³î=ã„s³î=ã„s³î=ã„s³î=ã„s³îÙpõP`w ’©>5Ý5HÙÈ²Ø /5þË-Ÿþoý÷´ïÀ ’;}wý¿£Wõ´ž¾=«Ëñ‚Ñë‡þ>4=¿}Ët‘9Ëw1FïèuŸÍ~üR–¬I0úå„þ>ÿý¾dy†Ñ«¯?úî×IÚ$ÚŸ&Ù‹kݰSƒÑ¯軪µºfÜ0_ãK~{îÖJ¿¾UÝÔ¡Æ»oF³L®eÈ/·Vú‡[E=}_çêè­Élõ£¨úõóç] µ¢?³ºJk èÏý2Ñàx9æU*(ÀõŒ®<¨‹ìÝ~ÌŽ¢ßPÏp9v}{1ÿ?[+Ý}ÜêÐ.ê,BÖ7 oš¢éÆèmôÿ|y·û¬ëªßASê¬#×ÔI‘€Ô^OÝ)°¢îô/Ó¼y‘§»¡‘Ú¿Sïwwê¢ES/ç¼oón©EÎ/u0çÝQ¼êUGÝ7(Üëþ3¬[0Ý€†uá.@½©‹öGÔ›žúSSwôÞ¨[µèxgõ¤nÚŸÒ–7›² @Ù‹ÞþCÚ&m»“[ÕMêv'·êôíNnU8(Üܪqи;9®r"Çu®‚Èq¥+!r\ë2Pm,j×]jÕ.ÕN“ÛÕ.Õ®'‡ô&ծݧ¬ [ÔnànÕ›T»;Fލ]»r"GÔÎlnîäˆÚµZ+ rDí̆öAmlj­ ÿoV;ðl½“{sÅ2È\ÝÈ}‹Ö‚gó|i1Wš»EonäEkÁÓùN¾ÂÌ•QonäkÌXµöF¾ÁÌ•Qonä[ÌXµö®6ÖC–w·«Ýsé:r»Ú-Aµk F»YYš—1ƒÈ}«KkíV»BÀz³ÕnàŽ‘c‡laYø%í5º…wrìm,J¿¤²FÇðAm¬ÖNBÖn‰Z; Y»%jíJHo–¨µ“µ[¢Ö®„ôf‰Z; ií’ní2ˆ·v"Ç­]‘ãÖŽƒj3¨Ý×Ì·k•®)XÑÄFú‰o÷5óí:ò;Áävß®¬ÝÒàÛM­#›|»að-yV¦5D˜Éî9æÛ™½«%Õ·3Û›%Õ·3{–Kªog¶µK‚o²rÈ2ø ‡ìÄ9ƒ¬]`8dGgtwJÚÕ.0²ç ²vḆµ h‡l{J> ²­¹1ž’ímOI£Ò´C¶5µF!@Y&¡Hvõ÷‰d%ÉÞÈ­ÖNB‘ìÜÉ–P${#·F²ŠdoäÖH¶„"Ù9É ˆd3ˆd9DŽG²¨6ö¼díÖHE“ÛÔn²=¹]oÖh¥„¬ÝI  Ü-z³F(--díÖ´C¶‹ $DŽZ;ã¯i‡l”9jíŒJ¿ÆÙÎÛ­k×Ày»µÁÚMNIªÝöíà´ßÚ`íFæJs·êÍŽdá´ßšfí K cM³víº³ "ß`æª)!ò-f,Yª=’…¬ÝK+r›Úm°¢#·ëͳv½±[» –.ÖÜ-z³Á¬]gk ä¸o' rÜ·Ë rÜ·ã9îÛU ÚØ"Ù.³G²›©µûš‡ÌÉn0ßE7¸µ+¹-’…CÑ d픥‡á ÕÚ™ú ÕÚ™í͆jíÌ͆jí̶v3³v³Š„([Lí¹Mí¶ˆÚuÞ v[Dízîò¥-" µÛ"j7pÇÈQµ3zW[²ÚÍÕ–¬vFÏrKV;£©Þ¢!o·ý{ƒøvòínäVߎC¾ÝÜjíäÛÝÈ­¾‡|»¹Õ·ow#Ç}» "Ç}; ‘ã¾]‘ã¾] ªõ•À!ë-¦j÷5÷íì‡ìðíìÖîNnW;ÀÚÝÉ­‡¬¬ÝÜzÈ ÀÚÝÉñC–Cäø![Bäø!+ rü• Úôj'»ç#ú¯®Ìªk©kŠp´çüž~5ºe'»w#zÉwŸšd©ºÃÑ™ù6$du¯t²{¤¯ç÷×do^ÔûcQC¼{“òSÛª¸»ÏÞŸq“¬¥D½œñîokÞµ<Ô 4ï¯Ï~ÞªA“šw«péåš–u¯p×÷÷w½fÝûäj͘,CVµ0õ¤î+sµR·/MÝ=¿©©/í$¢DÔ[€ºàQ6©¬LµW6£Ðš²•fe ¨ÊñF•MV5®l5®l F”MZ”- )[eQ¶€¤l™EÙ’²•e 0e+˶Ýè4)›,Ûvt¡Ó¤l%`Ù¶£ûœ&e+˶]ç4)[ X¶íè6§IÙ$`Ù¶£Ëœ eƒxã–MÔ¸eƒFŽ[6i‹V¶÷ïO­.Âs˜ 3ùr¤lïsËÖQ³îj@íÝ—L-8¬KçtÃ2çµ?[pMÍ M |9ã=XÕŽw^_Aj»e+454rLÙ&—š&Ô˜²­Ëv\mµ+ÛäJÓ„S6£UÝŽk­ ²Éš²q³²TeËj\Ù ‘ãÊQãÊ;F-ÊFfí Y;±vw@k}ÌÚ)î6½ñk§¹Û´Ö'[»䎇%DއDއT\í̲ÛÐÔŽ[ÔnCU» "ÇÕ<®v 9®vààñ$ÇCŠ"ÇCŠ "ÇC ªM¯v×ïž~—Äý;¤êBN3=_kYöôÁèÎÜõãýûKQ÷>9×ÔÝ—k µ§Æþ©xº·!5ïªHÃC–‚Ô½Î}üL©›†‹& k™Ž#Á õrÊ›¥wÞQºK ˆw0å­¨ïc§ã8pB½ÒÔ?ߊº7çŠ: ;¿¹º£ù!ßÇÔýÈyXµ›ù nŸw}áé]_Úp(¨·u«¬eŽ+›YèKš² ¢F• ä*›yÁ—DeGŽ*›YèK’²€FŽ([aQ¶%®lÌ®lK\Ù »²-1e“€e[îÌ™”M–m=º3gR6 X¶õèΜIÙ`ÙÖ£;s&e“€e[îÌ™”M–m=~Ñ .°Mëñû‡U€]\OïÌÙ-D[¶ Ò‹²5à1ºU¿æÊÖ€ÇèzTüš+[£ëQík®l FA™£Ç((sü53hǨEÙâ1 òFQóÄâ1 Ž=FÍÊ >›•-@|6 *[@õÙ ‘ã>[i‹Õ² àݠǨŽÑ zŒ àݠǨŽÑ zŒ àݠǨŽÑÍø5X6 „›ñ1j°l8„7ôc”Ôø1ZAÚ‚*›YèMÙ Q£ÊòF•ͼàQÙÀ‘£ÊfVôñÙ`›&OXUÕl7dËfV6ªe3+[@γÄè`Ö£æÙ j<ÏQãy¶  Æól Æólõ Í”Aó^£Y:hÞ˜eã ¢Æ,[Ù€Ú‚çÙŒbó©y6ˆϳAÔxž ¢Æól%@çÙ2€ϳA#Çól5fÙJ³l¼¤FȳMȽçòl5žgƒ¨ñ<[Pãy6Pãy6ˆϳAóÆólмqËñÆ-Ä›g32'çÙ j<ÏQãy¶  Æól Æólõ Í”A#_£Y:Hj¨²ýä 5ªlc?yª-xžÍ(6rž ¢Æól5žgƒ¨ñ<[ Pãy¶  ^¡™2häk4KQ£Ç¨YÙˆy6nV6zžÍ8trž ¢Æól5žgƒ¨ñ<[ Pãy¶  ^¡™2häk4KQã>4oÜgƒæMȳ˜?‘gƒ¨ñ<DçÙ2€ϳq€ϳAÔ+4SÍ{fé yãÇ(4rü­ mÁólFæä<DçÙ j<ÏQãy¶ Æól@çÙ ‘ãy6ˆ?F!jü­ m”­¿ ¸OSÝn[ò2Ùù,M¯Ìª¿ËÉ­6;Ã1zÅ»~}) –èå;äY}hšc”Æác„q,Õ\>û·÷Ýk‚ýg7ý\Xqfg‰cFAÄP—,¿Ô›Ží\4F?V\Ø%Å1ÖFAÄè”ó£ûê³{]‘%zm#Y5…,Ó´2½z>ÁØb¦wÛ§:ö¦@ä÷·Éxá·)š´H+Èiz|6 ¯iÕ½IûwN[”äÌØ¹8TuL‰4a$²vy}~ï÷Ña?<üYT¹(âê”DŽƒ H«%deaOd=Qï´+&n8dŽ„8­y$왑x½Æþ¼+ý!Ž(R‘Uí‰Ôà 3{ ¤×ØÙ©}Ò¤vBÝHªý¾:ÔUŒƒøföˆ:ãßÞ‡SYz0U/{Ó«äSuÔ~|ïžÖU}¢œ7úåW ÒŽ$}xºõØÊ†pàxêàÿü¹ä>Cu­#Êéém0™P@¶˜L(çç&Âêø L&„Õñ•ú~ý6É„I«ãûZ°__çwÁ²ZR¦³ÔÓùºMçÒN‡¥¥é%û)ˆÖX=‰LªK™^ÓŸ‚¬0™P¦³Æ¦CÉ›E&[luK¼ìmìûçÇ6Ô­Ëw;2ÎqžË7ÔË…é6`ÝöN{ó°8çâLìÒÓ ŸKï Å%9S¦ãc#¡€(¯à몯ÛKì­’ .ÂCuÈ8H`,{J°+ÛHÚ°Š<’5&XÊêl4ÈÇm:ý3áZO2Ye¸Ï¶Üêé¼ß¦“>¶®WûàÍ0’»ÆfrwÅÑ`ÐØ¯›Lú½£e²çœàQžy$ì©‘øfÁ²g,m‚íõ„(Ø“ !R V÷,Bk•nY„KÊù9=¤2d¸y Ö©ˆý- r<·@ǰ¨BÂ.6c!hjƒ·]FaUP–x‹„°wVÊ+øù2$¢øLìj¦³ò0™PFâcKL8W½Æ~´‘u ²ï> l•­õË"LšR\ AI¯±m4Ú‚¢˜iËv>—aT–‰8Pd²š‚¨%V Õ©àÓ¹•0æÅŽåüï x ƒ0 „!ÂÁÄ^Â(éÓJ’<¼„AXâµpÀ±týdk­ƒp,] Þ¬9ÿ’²°S’ó¿ƒxh„âÛ«’<’¥µ˜R’W‡PÂÀ=êdž¥ú€oÀi ÃP} €lÐÂa:[´"ƒ+ÛPÂrþø¹3”0€b !&ÆK¸L†PLÁW‡P Œ$@«ZÁ7 ¡„AÁK„éà% BÞ/aà#!”0#ñÐê®öº„åüñ ¨KP1… u‚`Wh„ Ø5Z}À-›.a@uÂH¶hõÉæ ­ƒà‚%”0 Z} $ }´B ^ Œ/aàj?”0€t=a:x ƒ0’ ZL!Œd‹ÖAð‘lßÐ:/aàÓÙªìVd|ïÃ>Pi1ZÑ:û,÷âlÐÿö÷VÂ0`ðg0<C >:CyÓ×¾tEûþ ¨Þæâ1v¨/8F`ÅàdŒÕ#é3±j¢Ë¶_PŒ5:|]6¨>;;×å^Ü—CœW­»Ÿêââ% 9Ewu Ì„"ž@Ѻ{Uõçî"f‹‘ª•Î’(á‚2£õ¥Kž(UØÕ+ (3 ek]#A_#ïÍ,þ”\¼&BBdáy¨¾PÆ‚ë.A_¼%¦/œ2–“. e…î ÊÕŠ\'÷ãÛän'Í%£¬ôÛ}ñ7Weâµwß|äâ~®¼Ï¨³»C‘ áÝBÅÞ?å},Õ"V¢ï…ï£3¢ ,ÑQ¤`3"e…ê EºkH.%u¥7€\8y¥·\JâJ/ß¹pê>Z.P¹PÆâ¡r¡ŒÅÇäBË• a–þŽKÝÄí¿ãzøhU²¤Œeø.íóûö!W3ê>䪳 ex[ïãûþ‰\zûD.-3J4±Ô_¦é±Ä‡‡±0Ùe$a,·¨\(Á:#‚\‚*]‚\• e,>,IÒ—`‰Íˆ$—›ÅÖéï}ìkTR´NðÉ…2– :Š\¶¨t 3Òßü@Ò%ŒEW̾¯êBÁ¡3»L½ÙP‰"ä‚ñ­ôwjÝ'f·»Òáî<Îø…2:žÞÇrèoéP¾T›¥à\„„•^( eF+T.”±¬Q¹N]8ƒVš2£-<AZ£õ"AÑ—õY#NYi]<³Ê…“vÀÚGQ(3Z¢r¡Ì(@׈ /ë*]ÊŒ”Ýýúüé¿LŒãîÓÄv,­É-Ë0)Ú­/ÿíŸ7õ¨ñB;†ŸáûóäöØA-#„؉›æö””‰ØG‡='^,F¯-ㆨñ €ù½éõ˜: ¡FFÞRW5*óá1ÏGjÔ„’š‰·?nB¬È¹IÕZê%M[`jL[L{äN˼œS/é2—5.sˆ7¦çMc¤&ê9LéùííZ#5ª-&M hÚÒ®·ISš¶`¼qÛbÚêï5Õ¶@Ô¸m‘5¾C »dMÓ–nq€•9È•ya¤&ɼ•ZÃj[17®ç†ÛenÒ– Yæ oÔ¶Fj¢Ì‹¦¨1™Ã¼q«h°[òÈ‹  FGòÆõœ›¨7T=5®ço\[æRóÔ‘©Ý©qmx÷#—]Òu¿ÛEI)¨.¡Ë®Ev Gº¦|ûÕØ9ÿyž aIet¬eÄ›l|„Nˆ=¸àÄve HÃææa¤agæaȰK»´·ã’vf'Æ¥]Ù‰Õ°ÞUó?5ì¾!+/ʤiCn ^Ò†ÍXf'ƆÍÀ¶‰3QIÌÃ&*‰yØd%1-ÕšªÛ™×m€³mØ…°ëöâmGÊ R£ÚmØÑwj|䕉š*qóÈ©"7“9d¾ Ë¼¨q™gµeo6Ii©©6eä•N©Q£Ò@¼ñ‘çMÔËȉÚb9Y[Œë½¡ê9DëyP[-¹´Å#šòluN©ñ#HÔøÈ35U[Ì#§j‹yäkDÏ sŸ,ó¢Æw¨¨ñ‘g&ê u‡r€ß¡ ÖŸ3Èþóí]Gð>áÞº b_´¿áÈ:,õ;#oücÖ¢™uõ‹Ü¢£ÀM`‰AlQó…«ÖjFÑa &0_ø8<ÔŒ¢‹B0ø8pˆ#@ÍޱBÌ(·š¯q'AÈ– Üâ2Õ&P÷èíW:˜ÀÖ~ñ]2Ç0¼LÞB\¿5D+t/ß*+ÊÚEÙ•ÄCmeûN Úò¤Ì†A _ è–YÿÀrÿAy<•ÇËI`K+„Ш,øó}³_Ý’hûUn_„Û!VD†Žbhï3<‘ÂÔmüA1xe¸cx’¼ÓÏû++·Ï÷Z‰vLb["ë ÐQ,Þà™dUc14öù¸mÆï\T®â:Òúúù6Î¥µ=èº.|pY;c ƒwãÀç2þ¦ò0(Ø`ŠÁq™®´)þ0aˆüÊ3|mר8l„¹à&о.ÍrÀz4ÈèQM Ç p(0Ü¢£X¡–Cb¸ D!6èžG'²EÍW…ªÖj‰q Üâ*î¡æ Ç`ó…c‰šte &—é 5_ø8Ö¨ùÂÇÑ©éõçýK½ë{HûîNYVV„ÍU²,Ѷçüãäýë${g dŠð’±ÔB8iÖܹïYT¢8±ât: }–§„“Íig&¹"ÌE–§©pi&dG‘ì„"ü¹öSì9†§"nšAi§„+Eø1ª~=azNvÇcl!\O8¦§âÐã³™p¦ÅîzµnÍ„LqÜ5Ö¡ª÷®æÒé(Ûð!¾–•…¥zãj.¦Äs8ZgÙ›«Öu¯e̴Χ¨«IÏ}³º>hEy|P]™]]}³ºê ÂìÄÇÕÕ¼ >E]MëáSÔÕ¤<þH]ºcÞY¾Y]ǪcÚYþX]-ŠnÚZ¾E])Í{ˇյà­%MêZZ¬ë(hTWnÖºQÐh–¹YëF©?£ž—æ 2JøÕ•›u`”æ3ª+7ëÀ(¹gTWnVQJÏFhÒ€Q"Ϩç¥yKŽÓwFE/Í{rœ´3ªkiÞ”ãT]ëLêêÔÕ`–Ôºr›òø ºöZgVWUWËñqu5/¥OQWÓJúu5-$f]KÛάkiÛY¨u-m[Ë'¨«yo=Z×÷ëÇ÷—nÙ“Ü2ºeÒ4I3êpóÿþ?þuVwÖàï»^Üi÷_OÆŠÛI#Ùls´MOYH¶6ǘ̇}$Xm$SjÚÆÒJ*ºUMÖŸ9"«ât¿7‘cínY¥Ã\±¢ºo‹1Ù p­÷ûüP›Ét“ÚáEæ¡ÕtÿJ×5 s1\3“éئªÕã^Qt< W˜ÆdÛÉûÏ,e·§›÷1—gf$[LŸÁf75iéö‚ŸÍìÅìô¤—¥Þ ½,ÓâPÅ»³‘NÛ´÷O]xŽâJtþlóuÃTK~ΫòŒtÚ¢½OÆÉz~ETU»ÂH§_öûš˜ Ãîof¤[ e5¬4Ëji\u- £¶,6wZ–ù%6óÛî0/xxëÃ<Ùç£È‹2´ðó˜9*ÆvÅÇÍQa0G>hŽ˜Íù 9*læÈÍQa3G>hŽ˜Íù 9b6sôp^‚b²ÑNKÐ>0#Ù3~fn:#X¿‰Ñô­Aso ›yð'æÈdÆLæÁ›£O“Y1™?bŽ>MæÈ`þüQVÍjšÛSRºlÆ fÞ?3s41cŒ•æu€2-&óàÃæˆÙÌ‘o1G£ˆ×`þ|ª9b;}r%òŽŒd`è0³+£¨ÓäTq£›Äœï¨4™£iÄ9÷ޏÉMãMcL=7Gã«$ ¿"MdÔ©2’mQ§J—÷ŽÌtVÌÃ8Æ4zGÜdÆW@ŒÞQi2ãkFï¨4™¿éUÈ[1.fŽºWptkÔ«2¯ÃKçfe|uÕÎÌÊ}ŸCÞÜüÝépïhLGöŽŒd`âÍ`Ž|Ð)+f0G˜wÄÍæóŽJ³9¼£ÒlŽÈÞ‘0‘áÞ‘4‘áÞ‘‘Á;2²³{GÜlPÍê•fó‡zG¥Ùüѽ#³%dô–X¬÷"ŠK¶Ÿûáä-±³gyKá®ÈjÏRæ3ø<>èó0ÀçñAŸ‡>oôy›÷á›}žÑ}(‹÷áã>Í]ò->Ïã(‹“æ|À°kýóì¤æÌ]ìóØ=-fSßÁç±»Ö}ºØ`N³Îu‹y•V1yo˜g“—g‡¹?öyLŽ‹í0÷Ç>Å]2zþØç1y6'Íû<–’²Ñ…ðÇ>Å]2úw>îóØü;÷ylþû<ƒãòX&žžo°÷ÑðÒ¦ˆCû?›§Ånµæ¤ä.5FwÉ·ø<ÓÒ¶ÁûðÇ>µºmð>ü±Ïc$µxþØç1Øì}øcŸÇXV·øw¾Åç™Vä1¡>Ï=Ÿ¨H§…0 [SZ(=4CÄ-”xžÇF¹DÞ3ÿcT³ç¼ yžQ]Ì~]Ð[š\ÄæSÏerÓçáŸgzsîóp‹÷1»‹i¼kô>fe2ãíX£»4«”ÍÝ¥Òâ¤M¿—†’56=R>˜¬6ÒÍ.Y÷Ú MÖXI×hŠÈ:`<ÏcåºE“5Vëð†¦ˆl|KµÂp"ßI={½Öì}ÜI}¨¶br!î¤K°LbpÒPlv!î¤+°Èbp—î¤k¨Ìlòïî¤{¥ÙìUÞIñ%äy¬\ñјäyLNšÍ˜äyLî’ÍIóqŸÇæ.ù$ŸÇèßù¸ÏcsHéy›Jò<61ò“ì(´}Œdøö‘&2tû˜E‚nVšÈÐícæ¶A÷Af"Û¢›ÕHFØ>f5Á·™¶}øH§ùOhû˜Ç‰mŸÒÂÚ>»fW<#ÿÞ¿Á–aùxnM(ÁMtmÿî™…Ò²y;Á´*éýšP.1Jf£´ï¦:¢õPï§Ê„r…Q2%´§â0/÷CbB¹Á(­ë LqÚî»&¼a¤Öá.£çßn^m^UQÌ*«tLZ¤z—ÉwÓ.;FÍ©´x “§Ò*¦Ý1œžVÀ.µQ"{­œí5ìÌzØkÂB‰ï5i¡Ä÷šmžø^+-”kTïm<ѽv?‹&”[t—Z5ßk6¦ÃYh½•ÔC·©M¼CEئֹâ{ÍJ:¼Æø ƒÃŽ‘aû{;×ÞÿëìP{äÈÓ;DznNQi"ó`²â¹ùè ùÙ¤y4ÈÌD†ÒÈÍ:È]7Ȥï’4<´gd¸ëÆÂ4¼´P>ÊÓðԦĥzmf¡ÄGkãé+ë¬òãI—ÑÌúN‘ £sÕ°¿þÇ_Í_ÿ×_ÿøëÿýkõ÷â¯ÿøkñ÷Û_·[ˆÓ3g;سZâ$VÃÖɾdx½±'®ªk(džÛ‰—šó˜wOÆöļ:…1gÌNL‰ïœyU…œ‡¡¸?#®ŸjØ1‹Õ£¤-qXWÕIœBv°¯ñ—"^4íˆy^íÄ.dG;ñfÄyDU‰HBv±÷¥÷î!ÔnÎ6”_XXœÛu ù P’7ºÈÂS P/0Þ‰¨=Œ:®j£Þ•õ¡nv @Ø·‡l7f”]€[¬@ê"Ê -íK$ ï¢Þ`Ô¬¨·õÐrõI#4ohk«rɇ®´{»;ì»BlÕ„Û·>Ñâíiê¯)uk“Xy:9 5U4ùè²n©[e¹Ù•¢Jåµ c@ÏUÝä‘:KïÔû¡lóîF¾ãÇâØÔ+m‹?§æ´•Z·î(󵺳äû}QÕ5@­tíK~êyǪ^ÚÏ»êl1‡d¾ÕÔ_&êø6˜·ÿ6=ƒG~½Õ0æþ’ù9=žŽ{€Zž?jÞ Ô>Bçõ9LÝëÚU~¿Qÿ–uwUuU Wg€z5¦N4uÑR+±Û]3àÜ÷‡ôSQóT_@hÁ¦=Ã8Jê B}Š õžÚ5ÆïîN!Ù©ŒÛ²ÎиëF @æK­kª6”ĽÐôŠ]ª¸Ýe%pŽ-µ®é]Òz-7Û¦Ëê(vÉÒÿ#gêÛìas®k’@=×5]^ítMdG™@~p††­‹)¦.fÐR/ÇÎí££§ŒCëèíÂ]-R;±gw·XµûpbGÄ·£S•ÃÔ$¥x‰y[û«8À\le#nÎÂN¼Æ†ÄlØÐœ­G£]†óPµ1¿~†ˆ=Û×V×ãKP/0wåñö°‘§€†jçù±¨—ØÈÓ ÌÎNQ5­»Âw3weL½2@E零c1‰¢ÆÔk³«¤xË ámq8zêjŸµfZ±­ÙÙéG^ɲ¨¢°)ofwEñήáóÖέùÐowÉ1iöµ‡P—!DíÛ΢;:Ë(¨—u]ê±,ckºXüí·äËö$y8ê˜Ôh›,¬b€;Ʀ|J½ÄÌ18ïùø$˜R[ÂÏBY¦fb¦ÔkЮµÔaPo0«xŒê-h‹4fÐÈo¶‰&ƒ>#_€ämðAcׂ% ”ñÄ´ÍÈ}›e,Zr±ÃÈ—¶¶3¬× # `ì:µn3ò•Í8¶ƒo‚ùÚHv¶5)ȃ’ß æ‘b¢ù±p§Ò:ï Û껉ä—-¹š¸a«OÍ̈Úà ¤ÜÔ>F}ªê%f^O 0ó:r9§Ô+ÌÌä€z™™ð Po0+35¯#ê-fdF¹ó™¶¼a¶ý ÝîòäƒÈ­&®32q672cr0ËÆŒ|ió[; Y¢Ü­&®32;ù"_AÉ®ý>¬9´ì6§,ä)%™¸Óe‘c&Žr/3+ó†©Qaái'ÐMœÞêlj(&Ô¶aÆ*;¡ö1ê±73¡Õd¦qê:ÕâÙ’O¨WˆÔ&> ÷÷º¥^ó'öC©™Ê|DíÙx7CéEÔ>6òñ‘6¡^‚¼›iÄ0¡°yJNSjØsfÓceBm=V}¬œ!ꙺ7}F gõùØïžjË6ô$_`cˆÜƒûj¾ÍÆä>”3ïqJ®zþ¨&¦‡èÐUï[©«°E«m’ HGݤÿý¯ûG®¯Ÿèÿãßÿþ+ÿë¿v<ÚMü½|<;‡¦Øí9xs]jcàÀXÑ8rP+>¥Z6Þ[XªCÉòá.ί9è—R5üŒ˜ «¼¨„#ÝþRÏaÊA¦·÷ÍA7Ç”Ÿ_6™#‡µ^‡¡-êx²Ö@º®ÃFsøùþ_Åa«9 ŸãMt)¿50øýŽ{Ó ñómS&×…PFï½]‰Ï®gðm‘ËÍÓÂ}-ÖšÅq¹E“»kÔæ¾z¹ûµÐËý’µèw÷çõC}múP£ÿ<òR´gQ‘4ΧÝÛŒEÿ•ŸfÁ æÎB]|ÿü¸Yò¾†¨ +ìèÊBÝüü¼Þ íEk5‘+ œEÁÏÅÙ•El~è^ÎíÖS—úµàEžîxáÊ"Ђúø2 ŠÉºvõÐúk4“YÜ4ªk@š/BýžÅú΢åqÔ%íú¸½FP›9‹ŒßY¼b} ñÙ{šag@ôc< ÏT3ãgYx†{­#½-ך&™#½ñ> -Ì•¬eõüiáÍoÈv Îoî‡ú2]í»=+³½+‡q;øŽÃm-‡bßþGz×=4i¿Í¡•R*oO8ÿšƒ>Rn皃:ïÎñY W)éõçãÆ¡ŸƒæÀ+yvƒ Û¿¯çѧÉÀ¡j#¯ö¯ …#‡­æðyã ¥Ôs(C)*×÷¦¼‚¯!|TׄZ÷‰·[Z4bI3}®Y°fß®,ï] ­º(3Ž¿ºµâ¯s뀸²P±ð—:TG*’Õçš;Ï"˜±èã/Íâ|¬ŽÎ5ÄÂ_ƵQtrÔzžúxX …î‚v÷-/ÁÒÇÝ}©wγÐÞ²ºÆÚ²è> k×✱RÎ,)›ÄÕÓ|Yð¼ä¹+‹ÅŒEvk—¢,"Wžvgß?oîìƒÃ|¨o{ýž…Î` _Î>°hýÙ¼–î,–šÅ§‘Å…í ×SÏ×9ìO£ Òâ,Vz·s{êÝg¥·gÀ~Ïb­gqËõßYtñÑ%s_‹Í0 ãZÔaÕ¸šAõtS7 ãZœ‹¬p5 êÓƒ6€yÿ¼…HLŸµÔyìŸO#‹zÏœ5JÄðÝo½>„Qß»«¦Žø±q5æúK‡ï~_ÌX¤m˜ä¾K-¨Û©§”V *áÒE c½î‰Mò‡hR¼€Åj`ñy 'Öª”îk1DÝ_FŠÅ XlÌIæCžš_&™§,¶æ$³fñ«$ó4Ãò&6›ß¤g§,†<öõÛ˜Çn]s×Ð>ð@ÅoòØS>˜*gmTìš=tûú~˦Cz–I–G¡pµ´A`N2÷õËôì”Åê> ÅB—óÎÙ…•ìC˜`mNø³øM{Ê¢÷Ì¿¯úÝàÛÖ+öûì·õ?êÚîøNƈEo@4‹_) ÏPÎËÊyÅóë”…>õ‹Î˜,ª¾5Õ+X, 5èì¡Ý<ëMYèSO±˜Íâ%,VÚ˜i¥Õ¹Áv_‹_æ§,Ö3}”4°øM†sÊbƒT ó&we±Eêž9sf1\ΰV%Ó"uæ±@j†iÊœyxÚØ~ÞŒm÷èkg ÓÞØÊºtæá› úÇ/ úŒÇÒZ™L›’¥y»ËjvöݦcñËÄ׌‡)éü:gÅóÙùµá\öp®IÜ×Üp+{Ȧ¶¦$sæ±5$…*{¾Ì0;ÿÞÔ«îuÞ-bwÆ2Öã§ço%þñz-«ñ9þÀ£O <âS;óP¹T‘@{@éË÷MÖŽ¥Ì2gþœG§XÆÄÞ™ÇöŠð<Øéy ì’4Ý‹H®<Ö°OòSý;{¨GGgÛyüo$;»ïA•¥’êõÙþVYϤW^¶?N"rg¢òTòóΤ¿ºÖ3I³h·« w&ž5¯þ:,˜1ñ­™…ô×áÍŒÉ üÓôÆ7@¿ñäfLVHðŸç/Xø5’Äøk=c²±Þ•;þÚÑš1ÙZãóô·òæ'â›5•‘þö¾ÜœÉÂÀDGT¸²2­Ý™xókNÙÃ5'Qí¥;ßtã,{¸qÆ_à¥,ç—β‡¢J’íÜ^/0Ý;Ëî^0“ì‡lïîpyˆ'ß„eâÎd‡$!ûEH2c‚øòa‘¸«°j]#¯Ÿ:MÞ'HûÌb{b5EHaâï–.¦)¹ŽÃçÀA¹òšCÑ„²qä ù~á>ºÍga*ZO¢ûÊ‘ƒ¯9|Ý9d7ת¸’J‡¥æð9pPRRÚ…åÕ‘ÃÐ u¨ÿ&·Ë™CÙ]((9l´;úùÙ¯Ãð–^·µ¨.!í{ˆÃvÒ×\Jý Úqæºã´ã.¿¿ô$XzŸÄ¥l͇ë†ÐnûÇWä죸Küôˆ¬ö—ãQ6µ3 oÆBßÁíYìÃKílšü{ð¡W[µì%÷œUÎ,–÷Yô,ô,:Ǭe‘]œèåþºÍâÆ¢\òÂ}«Ù,nÕÎBVñřŰ·ï`bŸÎ…³õú+¿kSÕ:Î[o;Ÿ…¾•Ù[(v)]Y ½ g1\üì HxtÞÝÊE—jëíï[¯;³yQï…óÖSºZÛÜ4ª«7Šæx,/GWSîé^ï·µ`,»iT(Ïâììy,‡>’Ú˜'ì_&<*e…®,‚™ úµÐ‚:ÕÍÑY£V³åî×B/w-ÎÆÜ[OúÞ×¢TÖu+te¡;‰¾ßœÛZtË]•ixve±½{š]Zzð4û´ô/½å?ÆW®ŸŸ‹‡Ì÷/Ýå?†g >_|R³¨\Yøf§_³hgQ9Ïbi0æÙÝŠŽ'çYcþàn²pŸ¹²X³èޤÈ}khbî³ØÜ݃ýƒ«Ö)íoÏ‹?†×Æ,ÔCzŠÅ¯lÔÓóÚìyhw°ã!Y; !Ýy,îΚæq•dÝ-þðÎVe oþ—aËšË!,Ï™‡¯y|öÍÎo<ºêrË#ºÈ‹;%|hù±pæ §Fœy¬îëaU·Ü™Çú¾†5ïÖÃÇv¨jQ;[õÅñ¨Ž—ÐùüÓ^´=èý>éE<ÿ<‡¤—täàc)©êêÈa ¦Õ$9­æÁI/K²E>‘lñग-%%è))NzYÒjü‰´š&½¬©Á’žôÀ¤œ.rÕV}xCé"çM½@“ƒÎ,<,#%å£ÙAgxÒË™E€f¤œ×b…æÕœY¬¡t‘ §‹¼ß%½øI/IzY2Rò‰Œ”‡$½lÙÁ’žôð¤—=#å*¨[ÒËžWs”úO9#å!I/«X‘ójžKÒËõT%$½\m”·c IÎHyHÒË"•会ç’ôzZiŸNz=ï.?Ÿô’®,Ф—tžÅÎH‘s9’ô²çÕÈ)IzÙ3R会‡$½ìy5rvÐÃ’^@¶¨rf±E“EÎJûè7[kî<h~ÐÝ„àI/îÌOz¹óX"‡5!åaI/û©AN¬y„¤—=!%œy¬ÑÄš; âPQR–ô²{TäÄš‡%½®ßꡌþ1ñÁ¥JYÄòº¡¸TËÇÄÚÛü‰¿–ûҪ$NUc÷žÃåÒž±WºaýçðGr›Ã.=†ç}Í*Gºf|ãÀÔGî­ÖV—(ìÜpGz kÍ””zqX6íŠ;rл[;χ¤õuºÖ”½Æ¶º›‹ËÁ‘ƒ®Z}®è×Ô:4Ǫv–Òzº)»¯CÜ\ÎÌ•ÃRÑú9â’:rÐañçd¥{)É3ZþÜqoð–+šƒ$±ð±Mm7…+ÛrÄ¥öáM ™Æ•ÃV&ò–óáMm7-kqXa[ÎYJkÌlÍ·mjÛ–kŠÊu[ظ’͆njद„GÁ£7ðôIíÊ?©¥#ü¤Žð“ÚUJØI]’ÌÄ?©]¥„ŸÔ®+Ôœ´å øIí:ÂIÍI,\NjWøI-9à'µpä€Ôœ¸å\Nj×uÀOjW)á'µëJã'µë°“º$š ì¤þø’ê‰xxrYJV–a’]š›Äû? ]¦º¯À>æ¯:×2z oÔ¢iôÌoË‚_"ÔµDYø£榳àç­¢,–³YܶoYœ³CYº²PÇõW÷5±^î>¤—»!¼º†²X>X}ÝÎâ%,ÖsÙ]P¡d„²P›ûK¿ºÇjwkAµÿ˜x~¹ ý$Þ;+8ïcPËø’ɘ»²ÐûB?tf¡Yä2®JWþÜ€t[o0 a*œg1~y~º/ê,ÌœYóÝýh@Â#zÅe±š›Á/Ôz&¨Ñ,ò;ÏBï‹îÅTµÜêàVË}f%+œg±½$|X¨Y\âŰ¿¿çÏwû›á¯â<† þ=L¸åqÎå æ¡wx÷–†áÌ(÷1pËÑËkÓCã5<GC蜅óX¬á]VYÑ\Ÿ_sÓ ‘ÐŽ? ‚óðCü<|ø'”ðpKƒ]¿Ï£õÑO•3À`Øï<^³æˆ^……¸>ÏÃôdÙÌçÉ|ž:ugâ!Ö/F˜øÈVÇ‹$0ÁlÖKf˜<¸ìÁƒËöîLVsO4{8©v²ŒÝ™¬á­6¿ÙЦ—Ë€½øš}²U5ûO}µ/Iº[EêÓˆìZd×° 9(Ø“#ýÃ<êâîÀ¢ÿ® ÉD³Ï*Wj#þ|ݯýß¼êîzQëqWþÀâËÀ‚w®\éÊb©Y|Ì®w³h½¬Ìy-‚9 ~ŸEçd9¯…Ú€?·Ûì~¶[ƒ·!NêÊb=g1쌖EÖGW›»Òvw¤¥íîHýz_˜îYö^wCQó¨œyxzXð(—;g>Ä£ÕÛè<–È’_ÂÈ™Gkî9Cïzáâ÷ÞGç³³{àëÝýÓ?v8 ½=Dvi„hŽâX^\YZcvË=t‰:‡ÎÎî/å䢾]Ð`£$;wßÄ»²Zc~×BDw5 ~0›E»èYÛæ=ËÂÐMëa-xV®§ž¿ÖõyÓ¨~ƒFŽÎžßî½ ò>úZAu±pÖ%êš’Î,)›Ä•ÅdÁó’ç®QÞÛŒE°j—¢,"W‹Ñ•¼iÓúC½k\ Èrh©ó>¿-ׯy-ÝYø£Ë‹ÓY¤Å¾q5æË!äþ4ÎâÂ^Àbˆ¹¿¾îñêCÞà’¹ jº¿Œ³¨Ãªp=X—CÔýe\‹s‘¹ j»¿æw<ÛYDiU¸åÐ(ïÓØ´¾Þ3çYôíÞ[KÞï‹>¾P·aU|QGüÈ\—;âîwã,Òøì¬QŽ»û}1›EÚ†IÌ9¥ÛZ÷Wz‡pò!´Ò…>»ng÷À¢TÂ_À"fñy 'U)Ý—{5̸ܱx }vwÙSë¥}óÓÖ©ª¢Išb·{–…ùQ/+‹VPÌ•…7g‘ò; ÆŠÆ•…?ú¬h%åÅ󱞹ò9nYöë±üùˆ¹ð9Š’ãҕÅÐÝí˱fió|Üm~Ôë]ÅÿKfahÒüêY áä§1œ,sæ¾ÜÊWkí –7+5Ž“òæùhÏø¨W»ÁåçC¸7lp^D—KåÎÃ×<º‹Ûª­êa.²Fðâ|8gîë±4ô6~ˆï‹´r_Sæ‡õhò¬ÇU~ל§Å æ±¾¯Ç$8îÖü5ë±¹ëÕþ¡ë°^ó×èÕvæÝ>t¢”õ¡IÏÎçßÈ㾂ÇbΤ·ºû°(òÈ™‡ò`á+xø3ßð¡¿ø9®šüèÌcùÐÍú Zfwó`LÔ‡¸¹D‘Ü;óÀyT¼9æÎ<Ô>ï?fÙº=¨ª Ms‘¹ëú(*gjŸË¾Üp¸_èeÕ„¬îöÊÛÌxô²Ò<šF4¡3ícƒÃ¡{ö•ëÄjׇ¡ÉEV>rß«ÿÀäsàÐ×ázÝ»²â*9èn_},ÚwÁŸÊr~‰:eîÈÁÇú$ÈÌ‘ÃëõÀ]¥`H|ìa=¨ÃÕUJk}íõSécÉM[/¼^¸r.Ö~9ÔÙéÀ9l‡9|õ†> ‡s×a^ ×§_Å•zË /‹*uV—zxWêô9cÊ8)9ík™ÖÎvÛ²Pïî*¡ì’¶®,üÇ»ÿýZô¹m%¨ý¾:VγÐÝ$ä×Åm粪ª\:ÏÂÔéMUuá¬Q+S“U¨TM¸ë¶X¬±Vî,6XwAmï§]w±[#Η¢.ÎÑÓ[ïñƒ ñ*úD}×'*ë f‘¦EÉŽ®,tƒ¦÷¯…ÚzŠ ›"Ë]Y,­³¯šE`…xÕ,†­÷ilLÎÓè$\YÜ^Á3vW—yX:kÔ…3‹-:‹Ìyë½ÍÁá¾hgA"IîÌc1sÔnwR[ >'†FMOóðPÒ™‡ÊÊ}=†^M_Ú™z_Î2݇µpŸG`æÁ_ÉchQ®ÝÎX_ÕóHy.Ü×\;ÏïšGòÀ#Ìò*ÏKwÝݘçÁ_9íl·5oç&÷}®/,ÎdÅ_(+}cq6þÊyhz¸75ôÇPz%âX¦î¾‚?ãñ »"§Ôù€Ò©©Ù<ø+ç˜çÁ_9½Ï¥æÑ›Ä›î–q^çîóXÏx<ìó2,¹û<6æyðWÎckžá<ü7}Êo£[¥³m÷(g[âÛÊo£ï…Òy=|åá¾C‹¨S([òVj‚y ‰°C,Ëy3÷y¬Ðy¸óX£óp—U¿Ï¿®_ßÊ÷a7ÛÞ\d¹ÅyçÎc«y yžÛÕóáyç|.‡¬¿ÔÖ,Éú[Œ­¬ÊD4¬É¤³_Òßb„çá,«þ#¼î²òQY9ÛDu‘±åñ©yÄ]M ¿[_&¼`‡Ý Ö#@y¸Ïc…–Oh<<‡òIåÈ-Ÿsè§ÍÆÒƒ|¢ô€v;0—½ôàa£›K@%½„v;0–€ø% /ŸXK®ë°A+‘Ã-q×÷†Ö€\—z±À ÒuWßÊ'öƒ3 -9[¿%ZržEä…)ŸØ ‚^xðò‰­TÒ‹@R>±øE Ï¥|òô,ž/Ÿ8³ÀÊ'‚Xxððò‰­¶ñK¬BÃsWhùÄÅ ÊB zÆÞCÊ'–dº|"aï!åp™+‹-: é¼õÞ€*¢–åaå[¨¤³w>:ç%NW í¼9†ò ®wç±BKî²Z£%w´œålI†ò PjrÞçCù(™9Ïc(Ÿ¥&÷yxhºÞÝWðÑt½³-Ê'@ºÞ}š®wŸÇ -g¹Ïc–³Üç±AËYîóØ¢å,çyøoPš[ÐÓõ¡|òa¼zFO×{„ò‰}î<|tî²Z¥&þD9ËÃÊ'¶2PI/5yXùœ‡»¬Öè<Ü×|c. ðgK¡|2) ðgK4R>çáÎcÎÃYVêKI@>Qvðå;ç=x+ŸØJ4å x(wY­V{!úÒœ©›ßÂЂÒÞj5í( ¬Õ^å·Y”qé,¨%,(YÆÜ•E€5 D?šBY¬°†Ây-ÖXÃ@î,¨ ÖÍý.e±Åzº¯ÅÐaÖÞ1¹óX`íüwâam ç_øXË@æ¼äC«={ËÀ¬G`ê*œñ{Wáìù øÇÒVØÚó7áÎ<ÞaÁÞn†æøh‡ ÝŒtfácífh.þÑ-ÐnF:³PY1ÙÕL‡ ™.ôó¬nËçe®hÎxðáÎc¾à«!á/DõÇÜÃèVäjw»58 Ï<;fÎ<–0,;rg$+ÞÉÊ}=t£¯có;ÕÜ}ºÑ-+ÆRvã…œã ÎcòhÏÂÊÇ’oe%Ýe¥¿ ûúPZß´3‰-Yʰ`|÷& „I¶sß!ÃÅ!à„’4&~BÙPRwˆ‡ŸP¶”•3 k@Iµ‰Þ3'Ô¸eéÌ"ÀNòyAO(ñô å¡'pzpg>z ºÏc‰ž¥3=3g+ìô Zvôæ p J÷5ß`§wç±ÅNAé.+ å¾è„Ê]Z ÏÞŸ©´v€ò^Ôª´v€ò^Ôª´v€ò;@:qÓ­{ï… $—®¬ó©è9v€5Ò•ÃíÄåÊaƒvârå°E;q¹®´©Ô¤—3‹Òu(;»ÊÉÔjÔu(3uò^Ùê\º¯Åë:dºÑê¹v€štãržÅ íÆå¼Ük´—3‹ ÚËõ €:@Ik(ïU ¤µ”÷ªPÒÚÊ{q(×ÝMèåªQ„PγÀ;@9Ïïåº/ðP•tew€ržÞÊu- \eëÅÁPÞk;@9¯ÔJZ;@y/îåz°B ¤µ”÷ÚPÒÕ±u€â`(ïU „µ”÷ªPÂÚÊ{U(aí彸”ëZ:@9³À;@¹înB(gx(gAá \$B(gAá œgw€r¡”ëÙMèåªQ„PΩ(¼”3 ¼”3 ¼”órã œY ¤µ”÷ªPÒÚÊ{U(iíåýª”½wwe±D›LIWÚdJ¸²X¡M‡œg±F›L•®,6h“)çåÞ¢M¦œg1ä‚.SÎë}ëeïj”9óðÐ.SÎËu€*­‡¼ßt€2v5’¯âØ»eIkW#ïÕ Üy¬ÑNVîkt€*_%+Kgv†ñ^Іƒa¼×t†öÎ0Þk;ÃpGxg×uÀ;ÃGxg˜Ò‘ƒ¥3 ;Ãx/è ÃÁÎ0Þ :Ãp°3Œ÷ŠÎ0ì ã½¢3 ;Ãx¯è ÃÁÎ0Þ+:Ãp°3Œ÷ŠÎ0ì 㽸3Œ«Î:Ã8+-ÞÆYPxgç}Ÿ§´YxçiåÈ=O³Ü‘þT¨pä€?Z:rÀŸ åŽð§B]WzžE®RÚ G‘ëJoQŸÀulO…rð©PïO…rð©PïO…rð©PïO…rð©PïO…rð©PïÅO…:Ï*Ôuãž uÞøS¡®›[w(†ÞŽÀX¸¾ÁO"x¯|;¢ŒÑå&¿aÙÅ}ÃYPøÛγX¡;HWkôy çYlЇœYlÑç)œEx;Ây··#ìï:¸›}Ÿ"sæ¿á¾øÛîë¿ñ¼yþíáÌÃCß\pŸ‡¾OáÎc‰¾Oá.«Àúµ©°¿‡à½ø=îÊ¡te¿‡ \Y ï!pçYàË-i,\>..]YàsWèÇÅÜyøÇÅ•…þ¸¸»á°ûáv"«rQTœ…ENY,çÈyhÉÆŸ ~räàÍ8ô¸æPÅ<ð$¹ý( éÈa‰\~Ü9s»×y¹ðI+äê㕹®Ã¹–È™pä°™ÝJß­Îë°Eî= g)ݾԻ‹i|ï‘ÏŸ\{–…ÞÕÝÝì~Ïé»ÙýžË«ãîxŽ\YxÈÕÊÂYa‡/õúE?‹ô>‹3?îììÊBß쟬2°Ø…yãÊBÛðŸÛ,Ô—z-®âZºêìb~cp|ï±lœ•V_˸Þ4J%Qµ ‰Lœ×b3cÁ³;‹k$“Ü•…JiK}èÒ,íyWt,b~.åééÓÎòV‡ES¤©+ o΢ÕÀ‚±*veá›Y°²XšÅ^¸Ìâk±šú÷ü“]c™çO$ó+êú÷ìX½¦‡ÌÅfêßÜgq¨ÎUþ ßÀüFÇûÑÁéÚ±<^Xúã’zþdý?˜jXððð0Y5ÎË¡“^À’¿€Ç8é5q׺¶îš«“^ê웯ù!/Ÿw:ýqºõ0:…ÝS÷îÛCßÒø|H>x…Õ¡x…în0/X-¶æîóðÞ°5/œ×Ü[`kî¾?tµg>të†îë¡û㨰¯ç1|ÙÓñ¨óêânwuÙås½èÞ!ÉãKv Î<>ší¿¢ÔÞa5‚‹æ’–÷y¬0Y½`Í×fY±WÊjƒéÕ öàÖ¶LT/Zá»xõ±ÕtùµÊÜ×C/¿>¢~Ó]y"tæáÍeÕU´î¦ç³tŸÇ°Ï_ÕŽ»ÛDi–{¥¬›¬z½z¬V˜^¹ÛDýy<°î~‰¯®]~|ª³6é¯ì¨Ç·Ê$;çó Ö|«û˜ <:{5ðè>Â?Ͻ:ì÷ùõSõ”íZ×°~‘¬šâ\6iên¯Ô'ò¬^0“•ûzôÉ·²úþd¥6ˆ’•L‹WÈj‰ñp÷KúÏäÁ5r "DÏyÖX-³ßOÀC”Ö>¢P¦÷ HV”•v¢t_ }ÿ¡Ôp¥ía¹#ÏÏâñNÀƒ¹ó˜ÝyyU÷‚í/tÊüïb˜ð—ZüB©ÌOñóhÜç`ó@Í!Îc5zÑc²;DTîq<Íc=„›&2Œá.« ƒ½€Ç‘{¬nOñêCÂnQvÿØî‹~{Š×Êä;da)Ž`qÜA¿ ü¾[ÿ‘ƒå’‚ÿÒ¿i½ý—ø9 þÆu¥Ñ¿3‡5V~w–Ò»B`:Âý—ø¥„øM–ÃÿE¨¾»ÏÂ3ß!(À;þ¯ ü߆¼¡µúîÿªÀ?¹CP€wüWø °Àï¿¶ÀoJXø¯(ð`ßE¿ üþÓ~0âcؾpøghćÚY爕•ñ¹¯…ý~disnä!òýÈÒæÜ<ÉÁ~?²´¹€OrÀïGºrÀïGºrÀïGJGøýHW¨ûTTŽP÷iþ•É“ðû‘®R"ÜÌ\Y î“û,<ëÌÒæ>=Ë·^^,mîÓ³,–Ö+˜¥Í}z–…ý~disŸžeß®,ì÷#K›ûô, ûýÈÒæ>=ËÂ~?’ÛîäøÃXÄû‘Üv'ïYöû‘ÜvyñY¾õfaù*A-a¯T`½åY¾JPøýHîÊ¿éÌbƒ^^”®,¶èLgúd…î.fÎ<èLwøýHáÌ¿éοY9óÀïG–Î<ðû‘ßt׫ zwÑǽ»èl­ôýHèîêû‘Ð]Rgݽݴß]tÖ+}?Òtw‘Ûîã=Íc‰Þót_sà~¤°ÜÇ{š~?Ò]¯ì÷#Ë—­~?ÒyŸC÷#å‹ÖCß4Ý]ä¶ûxOóX w0׺),wþžæßtça¿Y¾l=ôMÔ÷#w0å«Ö¿éì—îGºÏ¿é<åzwÑǽ»è,«þ~$|ÏÓÙîâ÷#_0%zwÑG€Þót—~?³íäj™ýòbåÊÂC¯`JWøýHîÊ¿é¼øýÈçgñüýÈÒ™~?R:óÀïGVÎ<ðû‘™~?2sæßt×+ü~¤»¬6èÝEwÝÝ¢w0Ýu—p?Ò}Ñ ÷#ÝwÈÂ~·Û ü/ºÉí~ÿ~ÍÁRàñýÈÌ‘~?Ò•~?R8rÀïGºrÀïGºJ ¿éªKøýHW)îGV®,ðû‘γ°ßäöÿ«îGr{ÿU÷#¹½Àÿªû‘Ü^àõýHgöû‘Ü^àÕýHn/ð¿ú~$&(÷ˆ5‚_p?²teßt^‹~ë}õ®G÷¦¤ÞÏDÖd¢ýÓžGÄ×OT>ÿ~äˆC¿-4‡°óŸ9 ‹ýñ};ºnmú@*®-Gƒûtë]©¿ ǶWWƒûôsà}˜CwlïÚÿvä0ô¥í^©ºë¦÷îºåH™~ÅapŸ>îïàRjçrþØïýW´‰ýùø¾[ñôfÅyY¦®RÒöçÖ\P­ÃÐZ7-¥+‡­^‡ÏÛ:hý:”¬||=÷w;îMm¹ݨ#⪋o·ß v®›ó³,Œ—´F,tÓ”žÅ¾¨‹Ì•…gfÑŽ±ðÍ‚Ò,^"(½±ŒûzÈJî<‹`ÔbbxX‰Ê™ÅpÃhbeXJáÌb¸¾ñn²Õ!ã'áÊbƒ­ÅcÕêw,¶ÈZðÊ™ÅpI˾eéÌc¬†8¹ó.ommQ…\:+Õ-@ú¼óPÏ¡÷ÅÐ*»”î<–Ó¾õ|(ö´ý ²Ñÿä1;½S=ŽG«VÅ dµÂd•¹¯ù›w—ÕYÑE°_òØbºë>Ou¿USö¤ï}¦"Œ2Ùa·{l‘ùK Œ‡”Î<†¢î×·.T¶–$åºPÙ¤E»6Î<|ŒÇ Öc 7Ä’!ê¹QCc[+)YV•Ö«*Yø:‡pk3£f¡sI™äÓ,leD ,;pgÞ(웬†ˆ$¿ gþè0ŸðQ)wKxœ_Kg<!÷õXé‚Ò×·.(ÝT·uy$Ûí¸;µ9!ÂÁ„ˆ÷‚„"Ï0jåpͮ•–ᦄˆ÷Ò„ˆtå`i£Ò•–¦„ȯ>µ'¦¸#‡ š˜rå°EÓF¥ëŽ{C3„Î,Hj*K]µIÅKPæˆ;ÏÂG’„™)Iø«Fí6î,¨Mâ¹êì­ždÏD:¯ÅMØ:Ïbƒæ"×bkÏEÚSlžc.ò‘¿Öüêʳ§;í¹Èç?……Ü•ÅM:³ÐDaéÊb…& Y¬Ñ,žóroЛpe±EÓγ ä"Ýy,Ð<¡³Ú¹H Oè¬T·ÃÕž't—ÕͺË*@ó„îóX¡ù5wk4Oè.« šïtŸÇÍJçóï Íá9ËŠ‹¬œy ¹H÷õð|,OXa¶Ä5OÈyBïµyBáÌÂG³Î‚Z¢ÙNîÊ"@3‘òiæl'”%äÎ<ðlgéÌÃG3‘™ÇÍDºóÐL¤;4Û)Ü×ÈvrC¶Ó{i¶“²Þï²p.’;rðÑ\¤+‡%š‹,9h.ҕà ͹JiæØ\ç€^ÿâ®s@¯ï×ÙNÈÿ ²ÿaw¸+ uqJWÿCµ€ßµ,êK^˜fñ/ÿj(%ýãä=ï¦=2`Î ¼ùYwg yžC7þ|¡³~úä—ó¥vc°Ä4Ž ‚¹Ëq‘à,¼eÉ`¯Áå(7kxù1:º1^5ú¨WÞƒ Ï›fçÆ`k`p›AË`WŽímî„gÚ O‘ä‡ËÅ‘ÃbfU8°"˜£¢êG˾:))<½s(š¤(—A=Y6v)õfë\Êc‘«”–&§õÎa·;9èpKÞV:é=V%¥¤ ï/ ÿ–ƒÞÐò¶¡¥­¼ã 9¬Q®sèÙZÕÎíŽ:_L,Âcœï¯û¤ÔÚú> ýõæÂñ¼w3L©`" Œ§`¾ßLªü¶F¦§}z­ ÃÓ~8=̾Ïi0Ëñ¤ºïv²Þ )ß®a^R`ó®a¸LsÍ÷ÇT„$˜Õ¦ŸW“:µ"¾QBYÛa²¦¸H0;LšïyŠs Ì„9·0!IýÞ@œ´ÅiH8 'lqHš³ð°yqFÂñAœC‹C›—Våï¯9N’î›:?–kŒ·D‡ÃÓ›Öat¤­×j²µÔ`ÔÖÚïëëñHÚ ƒ6s½·’|iDAÃéÕùóúÕ×m£CšÜæ%Êü&Y˜‘p¶vœLáÆ£ÒèŸ×5¯Cr«#‡"¿Ö"’¤?}ªÜŠv84»ìMqÔ´ZœvZ"Í#êú­çœ5Í„³T8?wœ¨Ãéµ3e!m^ˆÃòŒ]H8«Ù¼n8ù•‰:ã@pÖN]'Y]p6sœ”8"ç,'Ù o ç,Bâ¼ü7§(’¬ é¿çñ""Ùß Ï=Â9‡Ù™$ßqÒ"KIûT½÷×zôýûÙû8eÃÓõ]e ¾¤Ù‰æøŽØ]ŽÙ)%á¬ÎÏ·ÂésO©Â¹Èãµ”´óB½ÍgÁÙ³RžióÚŒqRÖ«šW}ÜYFòZü-ˆSˆ8ªÏðN qÉ»¬ÎHût©®,ôú³Û¢$Kû]Qw…ë°ä"Ihžªá\;Úxü)N/®pâçB“Ïr†Óo …S\ËIûB½]gʼnDHó7–+N'Ÿ¢Ã©«Ëo­ÏwœH4»N>‚„ã#ã´øb³´ã ¯ûFëó×»ÆQCõ8¬ˆª2¯Iûk3Óçþ6dÓz 2«bÚxÖ#9§q2u@-­>ï³+MÎZŸ•ß;‘O±ïô”gÛ(}îó=Nš*ÿ9ySÆÙ.!åý¶oãñ¤÷y%‡¢l§ÉIãÙ.Æ8-FÿŠh‡ÓÄUœe´¼èÖƒpd;"Žá$qEÅY8a³„†Àóг#)µ]A8»n^4¥Ï_ê鯍=9Óçò! Ãî`&éóv3ÖÃÖùÆ#¦[÷Œ¦‡[ëxÂ~<ÚxoZ¡•£Ù:L5nèq-ãÛ÷ÐCDØyv7µ*òöXŽãô\Ñ€”Jÿ| #âi—ËîFT†{yJ2Ú–_¼ù“©¥ÊvôS“§ÓõDÚƒRw@i'l®€ZÛqj‡Ó€‚Ɉt6©Q”žª‹8Ó€VÓUËú@U­Z¶;%Ô©­'@™*ô@I|Êb*ОZr¡9®‹·­ H¨—Ñ6¢Å<¢ÓE¤4 <"y9GäÁ#â—Œ8"ªYŸþí²ÕìXRdž—§º…¤ä§z—VÓÝ“QŠä$¯D…\¬§ö(Õ™·Îí«*­4 ©f§Y_Åì§VîO‚º×ÛɈ8Ó±o;¢vÓ¦UQÐjÎs›ÝF$DÌ©2ò=Êømj;µT=ò¦6;Kûc­_µÓîtD›íMmö( ãó)Œˆ é- k”ÓH/€Âò´Û5Û[A@ü´ßQ§¶€NÝÔˆÒÛ@¢ºe´Å„M´þÛH¥•[ 8í©Þˆ¿F”õS#y³“6½HìOUF‘?Ùýú C¿û³L¦#Þ™z#§H1¶öˆ¸iU ñaÓÞO‘2ŒË6H£Nm4&ʧÕɋփ ± mJ›ÖF’6³ô©*ßtjXw/̘ü³øûß#y­&8ª%_‹#–ë3I‰ëŽ„ãcé¦ g~­"Uá„YÚ†ÔaMœ—áZEÊo8,»\ δlÇÕ‚ÕUXeaS‹(H8e»½žW7­£h6Ö²Ô gcJãw[£éÒøLŠ g;ù•ÉZÞDŒ6/}ïíçk~a²Þ§¥h’¨ÐêâÛÏÇèBV¿buÊEx­9MB‹é‘ß§Šô‘/âëõd>òç@J§ ›ªÏ:z Ö™ü6¥=(ugaû©¥Ê㫤 ó½ù.Õ(€²k˜Çmõ« þÖMíÂ8¯Ž4 µHU‡™<Ÿi@›©°U¡] {'9UØÛéò«©©å߉¤2sËø¦+_CF-l¾8·»?;Å‚4¤ˆßuj÷žÍE~¨ª¼¡-¿vfo9šÁ½îs4aUÙr4s øRçEž¸uռț\º¶à[œ g~*Õ—1»KyeÝZ(Ž㤗󅄳4¥••=jÐêp‚Ùé1\Ö¨0«?ÂYÁ8¶Ë3œµ©x«+·^C. û©8ÂÙ€ò9 ËeÞÎÏQ4QCÓC¬šsªv4 ¬<ó„„9V§Š„txLœÚÒ”ò2Û§’¶ø (5ñQìK˜ßÇÒ’Ÿ­áü•¸Ú>[l ÜÌN\SIÛh‹-<¢ëEЀ¼7 ^Üuñ"4 äÙeq*sšMó<`DI7¢8"(ð”Y•Ê#ÍZîbóáŽyëì§Ýe6PùñL³kÞôöj3Ü:³º”DC«[È_¥áú¡da;¬&¥mL¿ºÔ:ü2O‰Gš·…ŽuM¶¯¿˜ùþ¼9ivû"„g×üHÛ´þbú•T¿k•rj²ô˜ÓNß›~£r >2Í['¢¤-¿ïºÜÌð1Ú>½´ç[I”Ñrâ÷’ !ÈîtJì^ñ(˜äfôó*7#vòšV“õ‰0í§ïå)–Ô­g#Ên¥q-“Œ:¢iäКÚ!ÅËö§SœQG´ŽH¹YjD§§Êhù6ê/׉°2¦NM]Î~6g÷ (>qjÃíl[Úér0ßjìWÿ¡á(i§´(Î$Ì;J䎄ƒ¥²= I;5gâ¼à´S˜Ef‡v†§¬ö g ¦‹Q›³33œ œ¾² 3$íæm^CÚécôe¬ÎIÑ\œ&è!íô5ÿ.±¾¦"Ï9È›dBôge}&Dìüªh*´ð Ý.̯f?}´œ¥TÒ›©ñ5±Æ9P0˨e÷Òç)³Õâç@«YF-»™êÖ0&'êˆfi'5"•v’aUÐf:µ,½ÕE¹—Üœ,œm #º%ªPÈÍÂÿ÷Ïp±• Ù¢HÔQuÊCÚòë´Ó=[”ÞóWaZí³ŠÓVmH;}Ï¯Þ V§l¿4 ßdÕú›8U³Þõ_ü½œ=¢ü>»YßA­KUEq! x3éµ'b‹Âà E5syïgŇ᫧H^.2,¯—«8P– åG£0íRw(eW7•<% íuô(åùšð#e,«ÉŒ”Ç¡f””—“H)cY«Ç+û”gÔØßkQxZVe#£œ€²Q(_%áI½©C9 YǬ& lŠžQÊî3âeR&ç$*)Z÷*¯õÙ?Ϋúޝ9²# Ç·A^1"Ž?Q›T…˜½ÚTç*,­¹à1Îrºx¯Æj+HqA &8*¾P ¸+/•8ÓÆ³šm‡”ß·ƒØñË…„£Uù}På$éÍh¯Ê¹ ‹k¹#ál&j˜ OµjÈËL„QIÂÑêÜ»¼Ý¦`ꥇ•¥ O£éáÛÌ§ë Æ±ë)6Ǻ=mL@ÞßÁìÝ•©:«ïZ5”ùá@Añ`”ãÙœ¸Ÿ ø ˜ñaÉ«k(ÊØ»³ …Ù¦OPÀ¦'ç2¼ ÊŒLJ|ŸÑIæ4âem*ôÞRgº¬ß2þ`þøÀÉ«¢È>u0Ó6Ãñ@œBØŠüSðô=%i1]S£épªÝ¥4Ÿ¿3ÈtUååÊYCÂÎàSy¼ ­W¿î?}tîi’¨#¢Ýà—䚟+În>ûó[+A¿¦*Ï9ÆS0êe’C²¥L·°=Çuk¸Z•¦Àøæ]FÝ ìG#ë}븅{ ÌRÁ¨òrýLS_yÞDMC F0ÝÑЯy7©zɨŽR Ìj2}I½M«ÆIõX"¶Ã¬YY5< Ãl°Ñ<Áv˜íF¹L=LÆ.GâhÔA ç1"pNJZ«…á´Nêè€ãc8aHÂѪü5ìO$îpʺ…lRÒŽX#œ.ÎtësU7²ŒÎ\™ûÍÕÏ«*xÕ g=ÏØíÆ³¯C™–Úx6cûkï¢OvjCjžœH8ZŸ¥žWÿ¸eªLFVqªŠŒdµ>~Æ“5‡{ÏgŒçØ'¥áx÷bU÷ðµ¾mÙ½ªÕGÁ"¶'­— ï-8¹è 3 g9šWëc´[÷¬”ù±ihó f8ƒ‰ïp¢KëM‘pV9§rŽ:9Ÿi8ë N¦)=ÎùÌŠQBÀÙãiºñå3ÕçnsÝôùXœ‰ãñߦã¹Û±Œ‡M]Õ4œ„“çEÕТ°b4Â)XJÜ_¶§•ŠJžVpgö´€cyZ©Ã™?­à¬œÙÓJŽåi¥~^³'‘œ-ˆ3y¢ ð -O+õ8³§•œv¾?> àϪw‹QÂÂÉ$œ©×Oöö™ùÁlŸg8>„Õ—šˆÛù4ÍÍÁ ¶óui8–K½>Ï.m8ëQ„Ò:ýÅåGíÊsÒÆ³™Æi6øcu×¶1jhrÞNýºtX¯.ðŠÒ&ºÐôðm2 ö0 }y(m@ÊÿºÊAƒÔg«½]ú¢äÞhYUEaÒMñŽÂ²›¿qéK‰$o,G)_Ú`» Í^æEŸ?¢d|Ù—ax~,´ZQ–ÐŒº;ùæý`þX$ó(ßþ"Ž7Öd®.i(ÙÄ×òÜ„WŽ?‘ñƒâ\veT¶= giÎDpKBÃ{.¡Á- NhLcn‰ý=$¡1É‹pK^ăÓ¼·äEpÒÓ)/š˜6¯€Ãã< ‰8ë)ŽZ¯G‡cóØÄÀÙ8Yq8Ÿ›ø8['-²ë5&éNhØpª‡¤Ï:¡qÇyX÷´5õé&gÐ0ã심®‰8êóÏ÷ϯϾ7ig€ú¢GÖ}‘O×Bp–SýDOS§»ëcB À™ê³~1ªŸ×9ÏÊk|qFññ#Ì}¹LDñÀÑìJlÕG¾îÃbÝåt_æ9¶X£àØ #’ü˜Ò`P6uRS‹¡ ‹ð@ÍÚî°ä»Ö€åfCØ¥T&qŸÁ}/,Q€ÿ\PX¢Ÿ(µ°¸¨þsQ@a‰|jð3Iü碀ÂøÏE…% ðéQÀCL2 mü碀ÂøÏE…% 🌠Kà?–(ÀG¢€OS`ðº}, ø4Es/×2 (,Þ»D¦ñ˜¼w‹LQ‰!Jò±(À•¢$Ÿ|¢“7è#Q€q^/×G¢ãx ^®Dù˜¼8Ÿ<ŒÇàåúä(`„3ór}jð8/ƒ—ë#QÀÁë6E‘>HŽ):ö‘(ÀˆcˆŽ}$ °ÌkÕúHðcˆLQ­OަÞû8 ðÉQÀ4šGþ“Q@a‰|rð3sß}bðpššÜwŸh‡¹°8ÌþsQ@a‰ü碀Â!ùÔ(`SQE¼¶;,¦(À'F:m^šæ`^¥Ej¥)˜°ÃxÌ4˜°ÃøÐ¤¦î»fiI›—&¿Ûc‹¸Éï¶Ã¬,î{i &ì0khRÓ@Ëc­”†(À³µÃÌ£@ý¬µ€Ò8 ;Î< p¬µnðrߎ3÷rœ¥-g^¼wÇZ ( Ñ €³²ãÌ£gm˽sƒwàlìò™G[ÎÏÌkì µÀ ^€³q&^€c­pƒ×àXk¥!ºp–Î,jp¬µ€ÒÝ8+gý8ÖZ@iˆ&œ €3‹¶œ-€3‹"ù œ×$Úp¬µ€Ò%8€3‹"¼@ÃÁk4ÇÇZ ( Q€Ž4Ì$ °Ãx¶´yip˜í0ÖZ@i&ì0KfØapRU6ÖZ@imì0k»Ã2‚‡S¤Z7»ïÏÖ¸Ù}¶ÀÍ.ê³µnmž­ps0áÿ* ˜¹ïÏÖ¸9&y¶Pšc’§kÜ<] àÆ(àùZ7FÏ׸1 x¾ÀÞ2V 0ᘼeÿÉ(@Eó(àùZ7zËÏ×Jc”ô|- 4FIÏ׸ѫô©QÀ#ŽÁËÅjóÜ;7z•ôZÀŽÁË¥×îфɫ|¾À^.¹ðˆcðNŸ¯p£wŠÕ¤ÁË5EÏ׸ÑËõ©QÀ#ŽÁËÅj?oÙý=_ (Ñúóµ€Ò“kcœYtìÿ: `4‡ šœ­µnŒ¨µ€‡cÐäwûÏÝÒ£™äZ¿oRƒßýt-€£€§kÜÚøÏE f<] àÆ(¨è·»»…Óî ñÎÏDzI¢úrºœþú?ÿ¿ó?½ÿòæm7ß[Ü©úï†úφ¸zu¹¥ªEXÆe¸¯ Têyï÷«¦:è‡r[ªb_wqsœ¨ÔFûÒT‡¸ûYQÉî–åÑ@õØü¸¥bém„É5>Ç')ϪàÞåAVÅ4¯8¹æY³ã±J=6¯\‘–Šé¯±ºy¥áåXšç¥Ú’¼ÿ|ii¨WÓ[ªð°“g~ڙ楞‘ÿøÔ2Ô_Âö2,Šâz=™Ök;¡žZè¨ÂcÙú&´Êê…ø/ù©E¯Ûö¢Ï—°É¥‰ì±§¶’½úô%ëÉÔ—¼]2™÷ðé!N†– Ïós%uTV&2Ý™ãýs~2 2+ËSÖFŽ™¶»ïŠ,î¬nªÄ/sv•û£‘›Ö/ͳD[k‹kR°su0‘éd_ï·A‹e‡SÉÚˆÛD¶¾7tœÅÍ%©/‡Ì¤ÅC¿öa¬ûîQ-@|©“v6ÆØŽÖ­{}I7Æ"g3íê·)™zƸç–ÔÕõRÉF–'¾½™e;q=í¹< ™Ò’wEÆÓd8vãD&,‹¯!7‘)-ùüèÃ…V¹†/&›Z$»ürÉ3ÓÕ=Ôµ­Ž“tx2¥%"ÌóKš›È”–Èþ{ãnn‰ÚpÝ˺ç´Î#™7&2mH~îÜÔ3 Í5g,L/WaR.å:ª£–[öY&weV³c¹3.€z'üc0ýíùÁ´vχkºOË dêYðïN'#žÄªq]xí"vMwa!MÊ¥üÀk+ÿެ•¢ë³Ur¸äY6#ÙBÍM©2ëtRÏ­ÜE2cÇ«qèžå}¿Ð^’™:¬[Iž¹Û³™@;uê\ëÉ”íj—;Éä!¯Cf²%ʇÓ:¥ñ°Ü¼¹\Žñ%9hI°Úl×o«·á}¿~uFy·ßwËÝ4[–L–‡âÂØÐöõóßÿú·¿ò·7ÿ¯ÿíþõ¿ÿõ?ÿüç;}oøZú„é§9Zú2ÙÎLŠ ¤÷ýç@Ÿ¨Žº=}|(Žñï!’îÁùBb+tƒX££¨0ˆÍTœÝ3_ý3…mL_šÛ[avˆítQû!:ˆR„u÷®ZoÈ0$>ŒÅ'ŒC=ÝÿÓùg»Cߪá‰ó²áqå4§Åðm‚ޱ|hiÐb0ÝÛªÃÈÙ¹ ;†b6Œ’Ž¡µ}µæ²Ãhý¥¾]7Žö„9‹*Æ1Ö6Œ’ޱÑ2Õ]§Èƒ‡]«‡kŽblm‚Œ¡¼Îãë{À¸¯mXTUÁеU.¨ £¤cx^TÔÐY×"®;û“ý•Õ ;5¨ñPÎéà?t\Æ{¯ªIÒ¦äy̺_¼%ŠŸ Áúÿ,Nîa5regina-4.96/engine/data/census/closed-or-census-11.dat.gz000644 000765 000024 00001624320 12400015142 023000 0ustar00babstaff000000 000000 ‹ÿ³åSclosed-or-census-11.dat´ý[oå:ÓÞçS407 àþ?u‹‚Áÿ6Ð÷ÍU –×IKò’-É65Á|öIIKVýèeMï ?Ïn³ªÈbY"Ÿ‹ÝîüüãßüÿùÇÿÃûÏê?óþ?…þÏ<ÿñû?ÞºÈËî¯ÂÑÿÕþi¿{~ÎwœøÑþø7¯ÿë?ûççç]–ýøüéÈs%‡¿èݥCéTú»|ò·b$TLþÖþ¶­õ¤æòŽÔïÿ/§Z5Ýß&þšÎ´j³ÿöÿü·ÿëßÄþñ…Â4þüéý§ÿmÆ~ÿ}Þ?ï³,W8¢‘ÞíïÅt¤8ü}«ùè=ŽDo¿PÜô¼Õ/2©0yâ!\BH áϱï jI¬Àø)†ÿ*:<‡C7׬Ðì1ûUm¦%,¿«ú ø¶ßéu–ßµf7¼ð!XÃIC/zˆ-¿3ôâqÁ3œj¼Äò»NÏ%µàl¥†ÞC2ûÝþp8^‹cIJ‚7g£Éi¾Oþt‡îO-_ :€'eYÕÁÃOE!«ë²Xø+Q8ýþõ´W 9ÕŽgF-iXþVšMö_·¹Ù?Ÿøu¿…ö_WF2âQ2¿ÖÊÝm¤õ×ÒLM<>¤r½Õ7EZ"WJ |û¯¥YX÷ëØòë6o5ÓD@üºÒ&Bë¯òÒüÚ:siÖ-"’¶^w<Ê𒶆N­¿î¶¤žmG[i°ûžGLNÛa‚7äýÎuÜöü÷ßýN©Ì1/v—2'µÌ_Hè¾QzÙ–D,©©jA%ËÈšJM‚ŠŠD brÉJÚ LcfÖ”EÕ~bEç©ó¦36™¤V>ü ì˹T9 ã[æÖq­*?!LÏé~n²¸\*ã¯øÆ¬GXçÆðí3JArÈ‹¶(i£;ߟçãAkÑkñq…0bSmKÀL½ÁéóÏßý^Ãtî ±HèF˜Ã±ƒ:uSÖ 3—ƒ9r ŒXðàÜíÏm)N'í[´™LG׳þ}m"A 0!B:ú—õ€Üøj@kl­7ú˜Õí£:G@ ¨Zã)‚Ñ‘ÌÈ~ÝÏ#'Q‹’“ÐF;¡ihFtV=%fYiFtf=¦d½]Iyoø=ŠÚ)ú‚¤Ñj¿çûög3ÌîxÄ,ú½PãÂÑý­ièYFÜ:4˜BQÝ °O³s¢=‘N´j!Æv#"‚Š A‚Gb¢z G@n‰ìw5˜xë5C›~DDà0ÛøhÑ&>…Cï|Ð%j)9SÅÓ Û–˜ä‡ÆTºÐ£çGÇÓ„\‹ÚÚ𑘇 _4•°³97žþ~ú«<ÄéxêÜWYätÞLÝï_]zv>*ä/§WÇÔôª²D@Â)“ß•ÍÏJ‰€üÙšÚ.}¦×4ë5ÕôšBzMh¾¦¬)´¯©d×NÖ4^Ó’!$ªjr†ó 'Q¤¿Jf5Weš ÉùœáF2ãüÜû”L‚çͼÏÄ9¶eŽ€l”jHØ(倒 |w[–È_ݪûGÒÙä’Ú¨©RDõò¡ÄŠVÛtêÛh©ÒBõñ¡Zmž²j>òBÙ¸‘ÓPÂ>CŽÓ Ãùó÷ß¿F.Ne猛7*÷Ÿ;†…8Õ5™•3âT" ËnIŠR°Ü-UÏÐŽëµhóWµ¦UIICyöhPͰ  Vò4£•ÓP7Nv+—å[žWPÁªR£Ó³:vÜèRFËIT°ªÕh(µ]¥]mQζË'Jþf† æxú,šË¡¹@¨9­Ñš‡B¨Ü % T>ƒTEIŸ‚)í:^‹çãõœáÌÏô4OºMSªY×;)³žÿÿãøW9…_Àô|<5§.ñE0b6Ç—·¢8~´f°5m5òõe÷Z˜`Å‹÷— ãÍ Fç‹ÕjÞ›×ëuˆ‚(Þ2)ýèxPˬ;®ýûäüwf¹:](]ø÷›÷`ç~çÿþ¯Ñíÿ÷†lÁº÷ÝrÐÂVîËlŸµËAcü #ÓGóÑOK´L­GøÜ-áœQcÅÈ~ÿzú§0õƒóÙ-u½Ä{ËšÖ1ýÉ—`Ƙ¢k—Ö1¥©N2cÌ)›¸¿®Ç´}3 Œ6<¦T“xä°.‘Üj4bÕP¬äˆU}-‘Paª…!3!½0?¼•Ȭ«/M=/æõc¸•õЄD¤ ±U?&e8”õÅÁ˜ãb_dhQ iZÓJ„)½x³õ ¹¨êª}PISLLè™Òh7&e¸hf4©[ÙX›ªcÂÍZö•É€™‘V¡ f¨UCõ1fD­Šº ÍI9Î)¹ÕBW¯†ÒnJ³[jÔ Œh} =zârP¶n‡É“CÁ³ÀÔ`'õdëêê~mmz½í Ÿ“ïÚt)r“–]5(¢çÔŠ<Òà ‚FäÞ)й½ë€DΩíí[ȉJÛëA8©‹ÛÈi{Ò !'*jPôHN\Õéø7K÷ûéWaòøóÙ9Uô™S<Ä­Ü/Õ;Ö…æçÓY×]Ûº@p:†5r]¼«gÞ||œ%‚óÇÅìõbt£NË´êÄC¢b[_KwÒLÖ7§9L:K'ÖôŠ¢¨rçÛøYÕ^`å§„ôB+?³ÁEv~ÒýO ÅÏ’çgÂð³fø™°ülÁO¸>‚Ÿp}6~–9ÙÜ Õ<ŸnüT‡h‡W§ùùëW¡pÔúškY5äþ·cHËúTjàëúZzž±}}Z_l__…ÖÇÙ¸A^öÏfžKÊ+}ØÞòþ5½.íËœ°Ë‹$ábJ^JŽŸ!ÅÏN^j†Ÿ!ÏÏ Ò#ä…î“K(y‘üúR^rv} +/5‚[ÚsæËÈKÀÈ‹ªµ8±†»trVÒ¿SÕ½ÞÏdz ÈæD+š” ³ßOÿè®rEð¬Ošé¯⇟ÑÜEÜT‰eM|;T°ª’DpbI/+xz>G4iñí°áZZ°>vë['V¢VòôBVÔ·ægÍÑK?K·æ§äé±ë#U>™­o¡JmÒÒ‡Ÿ1¥J²aޝo€ƒq2ç×Ýê–’37À1úÑŠbÕYT²ü̦sÖ_Þ `hcNÛ2Ì ×ÌQ•A¬våZ™ST%ôm&±mæôTÛj_B@Â3-9ŒN'§i6Y%Ãï‘V•ø0Â:´Kkæi×Òa¶•³¤(HŸ^'ÃÚ $Á[j7=ïágBÑ,YÞÞ ÞJ Ið6ÇU¥3n¶±]Q2^§'v¥&Õ ¤]«+ŽC=[F­'v½®8Þú´$pÒçñÒGBWlbæésÅ&fž>7OR^ÂY¦»*âó §™îºˆSAz?iz>WŒÉ!œ½ÃÌÓ'ì„ά ¦¥Ó›žbt€Gc¶³¬|?¶ ÁI‘ãó÷¯¿…jf:wš›Ë]þöBjļÈñû·<žtDßvÇ’Tù ¦øt£XÊ·âøñr†€¾µ¬B2'žù—sv™„€¢_£úF[Mµ-/‡·O™C@cÿh{¨˜£ìaÓ40¸Q<é`¡ì<¾üÄ€á¸?kÈ÷æzÉÎ%fNd-q\ 8®¶9œsõ|2\m0 o­;qSõ9í Ýh<©ž4ÎêNë–ž'žÔŽOç[Ï´ ¦7=X4¨¦{]ú-Úìú…}% ÈD5‚#¢Á;X’p|@T#8" j1;èqg0$`¼HFWþ ìY‹(úDGA[@AMµæ“Õ–›\Xî™ÁÈ-UÊ`õy“Q¨]–¦?pÊ,7š«/œú0óx>)ÿ”UÙ®µ]¹¬®ÚãÓóÉÄ§ÕµÌ h5ŠyÆPôíkÔVeŸ%ÝÌÁœUèo«èÏZ¦WY·#§5Uv;ÂYx²²Ävð-°0T4`HŠœ¶, à(Zö1\}ÎdjN vª6@ËTWå¨6'¿ò踆…ãé•NØàÊY–é÷ë Êx:«2qÖtâv–%´SœEî>ñ=¥uª ¸Øý5Å‚\iÝ ÁmFNo†à6#§7C¬7chå©`yšÓ<,Osš§Â…§%ù‰·äpäM¾äpäM¾äpäM¾ä xcœø^;qóß©òMã#ù¤«õʨÞú²{sƒV²÷ùço±;)·ÜMºjϵ|~f¡}Küa¦n¾QÛKGpaoÁ}+ãš³|or¾ÊÕÔGuzò‡æ}¨)­> œJÉ“îEÒPú«C¹+x(aÛä÷Ý‘‡2¹.^©½UYïõíü|â¡‚ñg¯õ§”Ç@e«Þ1äñíðY× –VÃCé"ó•6tô_–ÅÇõx‘Óoj§úüù×ìÓYO«y¹Êçå·«‚4œùò±#†O&¢ËäÝD^ãDVÃý±o²–Ïsyl»†¬±W•®>-þï?þõãýèóãÿüðºŸÃôoõ~¥:ªÞ}c ,¬Üíæ4~ªï©;˜Ÿžúß?“…4ͱýø(y¨¥ªi#ryî¥ø¿->¬þŸÿºZñðãúã¿t ~ïáñ‡uëÔÍòzØmƒ}â•ñþh>šú>ìÞÃzê ëz¼œšM _F‘þ&rߢ^/ƒz}y'+ˆŒ7ÝS͘CϘËKþRm„Þ¾©§Â½?˦.¥]ÖßC>eÌzæù‹¯Î¼øòqæÕHÒ_Ž|Ò}×úÛýa§çPÃúë¯?¬ê/“öÁ°þ ~XêíÎmb˜¹†Óã‡UæKÿnXH“ãJ}qû°ÖŽÎÜRàܰ¶2øáC–Z˜/úC°Ôþ{}°½Tu¦Æåý‡ë!`]§fÌ3_‡`Xÿm~Ä SW¢“»Q©è¯â䨶Çüñø!¿}X6|ÉÎë/3™arÍð‘ÛùÚ|ОPÃôõ=ºÉý¨”ÐõŸ¾§`#úßžsÕðü#³aíí xzÃúUèÙ·o¤ 0ßœ‡,óÔÇÛæ³óˆgr;| 3ëÐôó‹o· P|iúÏÝ=^¤Ì•);®¯˜ÜÓK•¹ý ³Å‡¯7ŸgôíÕ8.ÂÜô_ɼn˜oà¿ÞᎎHà}+úoêyþõøÞšµý'ÜÑäëüú»j¢ÙžE?.6cøz^¾ ãX9è d7N¤ü8­GQŠä¹ÿÖœ7Vê[ú¬ÿâžã³úzß|*äªß·Øãæ'G{Oni°ï‡‘¿XÜî ä´ÿÞŸ_o;4à‹ùõã|ÞNöû1¹‚àsÕß6ÀÒ츺pÀ|®ûq1Ð7or„•nïºq~ÀóÙì[‚ø×Ï/áä^Û?³Þ”™Ÿ¾£ç_ÊðE_ÈÑß4ÑKxý07-<2ëÐ÷d˜õ&‚ÝÑMwã|·WÚŽ'>·Æ/ý¸”•£—Ý8Zßz¹êÇù@Nõz–îè§»q"vH üõþ·ÇÊýàԸȋ^Gæ×ß'’ÄÌz{{Õ>ðGz~ À×ëyÂŽü•ý¸³C½Ü«q¬}éínêñø¤ÆÅ@ÕzSq» …Ú7iÆù>»^#W©Ïí›ãnœðr¥å/ ü”åŸás²~zôÝ8?z®ç#¾ô|Ž9y–£²¤û9ÁC8eøï?f ×–m›¿Uô)úŸÆìï§§?{Ó –3}=R.æT(ªê‘+Õ•x>ŸTœ—»2/!¨¯AÍ«xª¬¬Y .WÊj(Pi¨:š ¶ÎòÝEBªázÂYÁNX——n¥ê9ÙªdÉÞ`Áã6¯!¬âÔï?Šîa:eªA¹©wM–;À+.÷W‚evÎ+«7·(xQ»[•6^ðY1Zooƒé&+5б£7ØÔ"5’ –Ɇ‡d£€°¤l0¯.z-%’ •ºpà-––ÂÚdC"Ùð²¡?}?ë»èyCLÍë/ùdL¸þ¦UÏý¾¿“ßÍSóº’Œ¢ÈªR5æõiº¹æ.² R ˆý‘m@Ã5‹õ ¶ïïVÎ ‡çÚ7eqYÌj_Q´´÷ fÚ7gr™Lk_ÏåJBØ5›[Èæ¹öõ|6£óUÓômeÑŒÍ&lVa3ï bXmÿù‚²ú^'æ¸hÂä¥LeœÚŽ EkKV¦tñTÛ’•©,©·Óµ)nÉÊÔ –ÖÜÂÚTW²2uƒµé®D|öiÝ•ˆÏ>Ð]º6Ý•ˆÏ>Ò]Lצ»%â³?åó?ÝÕ—9•¶7lØ”ÑÝ*{Û—T¬ãs£»)£»]žú’½ Ðyo&\dùKEFEÑÃÔ¬,Fư8z˜xƒ…4*wÍjú Á¢ÚêwÈ9ªá"šØdÉÚä˜ÛW™ñoÐ¥´Mæ÷5æöU²69žGÓµ¶ÀÿÄ‹ lºØ8 x–-VknNdV;ÍÀVþ,wžMu6:/ãšùzY¥gqÍÂFµhwgqÍ*¾àÔ6^Ä5sU¢õ F˜Ñzm¥J´^Áˆ3ZïÔçZŒÍå’Ñw‡Ú³ÆÁÆu©ã ªõ>ýÓ¿Mêï+Õ½S-ý|_<¡»ÐÁ’ÕÁ„•É’ÕÁd-“¬Ù=JX™,YL™Ô·N12™,ã“ùzY™LfñÉR%Z¯Ï¬—•ÉdŸ,|gÍúÎôAоS²¾3} ß9õØm~±] 5€Œïì¼½¹éí–.‹Ç®xªœÇî$’fq:óØ ª’Ò‡˜¦Z¶<‡ã Õ•â@½ÇßfkôŒUõ’‘‰¬°VÕݘ̣@DuƒDQûR]˜+SÚ¸ªRQvÊ1𢰠…íÓk‰uQî—Z²¹½R[eu“-{óå$>R/Îé÷£~ñ¸Év²ijàÐPV S‰t°æ*\þ¶ÎifeaÙ]ö8éÊyéòXéb•_…-¤k*լ͹Á ¢°ÀK׬"ÿöbÝ×í®>càe¼Ÿ 5˜²ÀÀ>‘gЇÙigí¹ÆÀöâìeÌ™ lTLÓ•-Ì„¦[òæÇ»Ý²o÷…<§k~˜Ønl5|¼Jˆ™W[¸ášW ñrtÙôëà§s†UEõ‘í#Éj}0ÇXú ´ÅÔë#AÆÔO I[ߺОûÓ±7öyÎû 4UmgäÓ_¸ÇÁdñĮ:K ,æ¿l8áyÜcY9Pl¶€× ŸÑŒ*ç5Ã`lŸä5ÃgmPè&´F*çÈkFÀSÁ&/]>«’œõó'÷€Øê˜5«»è¤ZÅ2Ö`m³5/ÙhÚ¸@Ö d¬Á:$j­×ìÊ@§L\Ð)ÇÎòúø X,Òël(KËûDÆO;d§]µ¯9D¼ËxÀ xÎ xÀx‹ w¸ð©VgÈr‡Mw†Lwˆ¼$φ§Ðé3Š2Æ,CÆ,dŒ™)X3”#V9$ëGvWÙÇ’õ#V9J>ÖæU¾õ´¹X?š\žo?d(«Ú¤ OÉ‹èÚ]”¼ˆN éð"w€ˆR?#(ñ2²¼EYal‰Dov¥…ñ<µiø‹Ù‰s²3²b²žg!+*œZǼ ç¥4é8æÓEòR:¶RÉKéš6¤…t@Ð0N3¡ÈÍ:ûdé@¦Þ>CÞ>™;[ ŸyÌNœs÷ gÑtæÀHiÂH©NJ®n¢—˜5§”- ÙÝJ—¶t›•ün¥s[j;tax–òrVòÖ0%•Þ–¼5Ly9“¼5L'/ªX'ÎYÃtò¨Š½†ÂïvÌn6'á)g‡õ‘MYx”5 99›BÛ¬‚dål íÙ5?ó„8Ã3áÍvËÒ|Û¶5ýîÊòõÖ« GÖþhùÞ²µm·ÊÉ×&&O.]Ù Öͳ¦½©>ò R(4‡–Ã5ÇáÄ–ÇGÍüæ$lOu•3N&¼u_!U²Û³)"÷NØÒOmúÖ8á„ šR眰÷8 »†n4ncƒiýÏÖ–Ù655 ûçÉl¬¶PÝÆvÛÚBPŸêÿÆTª‰S¥VbÐhÅá r8f9ܶy@I3Ň3Èá˜âp9 L¢Ä&z°ó¦ÈÉ7|<Ѓ]HJö`·ªoQº’‰ˆDçßkJ+]@}ª{»Tª»… ´ÒÁ Û”N'@éÊÒJ©úTßv©Tëu Ai¥ƒ&š§‹²¦7'ÍÓÌæ yº… >Õ‹LjN4ï,ìv¶'So²Êö(²¿z ÝÚÌX§øA€näB"P²¹…T}{K1;at3öACq ©úöž`FcZ[ Š1-ŠY‹8PÖUvÂ!èée&‚–Þ‚vþì$Bâ™yuJÖ;y=Ö¯{úá©©Ç2Çpƒø7‡Ý)—Í ÂŠÙžNƒ›l×±©(!¬oïÊeÄ8áĸdÅ8áĸf™œpb,Y©Hh©è»jË’Mµ-õ©¾Ø¦!@•™…E•Í.£-jºŠ¿Oú~Ó¬]|¼é@&IÅï'ù×xw%Q:}ÞíJ k”ýÝ÷/ ªë.Uû™_r«[ åM×ìmG÷ôþR]%„Õ)ÿ/%ÉÇÃálμÊB^OíÂÆ#ìþxȰjal›·ó9Ñëý£´ïéõ¾õs!åþ¦سþ‚»ƒ­‹²l0¬NJ £÷gup¯&}½¼ušÅÀ£½QÏ9ö+¾^žËçâŒÅ8í}GX-ù¥Ü½íKYî1°?«igjÕålÿÚìO8Mì±.åËËåò~®1pHõŠ7Œd†M< ÍGÕ.;^ ìTç^#Ô ˆm a}ªÓœ›sÀ͹­Ø9 ×\2sœÕââÀtÞ„hë'­¥÷ȘK“qærLÚK2µžk¡þG®£Uì¨zc‰I‹y¬1p8Tÿ:Ê'­ÈYùñv880,¢úä%GÙç¸ÍmóXL­@ß4~ÍίÍ+eÈ.ûIã7-$‹ÊýbÚ%/$‹ÊýlŸs´ÏÞäýzJÂr L I×B’#!¹GT»{ÃM;¦lPìæ˜4œ´JzóÈÖÖüÍN;à¦Í™Î ° Ú¿i­òX­*y­òæ=^¶6lzÍ‚Ù*•ù°[%ðV‘Ñæاº¸Ùi‡Ü´Ù­óSr[w.MÙ·[’ÓÐŒÁ2ÌŸ[«l7اš{Ùi‡Ü´Y†ùóXÆz°F¿=̬ÕäÁšX¬ÙOÇ ¨O]TÔ4 Ï©J’‡Mp‘ý¬‰a“ÃYS@‰¢li?kngM%¥Ïšà„)Kk*(qÖĈ„ÃYS@i¥ƒ ôYS‰@é³&H•V:Jœ5±†gM¥•R¥ÏšJJŸ5Á ÓJ'LŸ5Ñ ð¬I"Pú¬©D >uÛNCQfAŒùèøxzÖ^‹6³õ_-aÉûvdIÃzÔ-Ã9•$_S‡çT9¥Ï©JJŸSцçT9¥Ï©JJŸSÑTá9•D ô9U‰@és*zÂðœJ"PúœªD ô™EÕáÌ'G ô™O‰@é3š*<ó‘”>ó)(}æCQ]vãÚªÔ ÒŸC›š0ŸR³V1%¾;ŸVm©õ.«¶Ö"dÉ£; hÊË&^[e«`€Ñå,pn ×¼(Y«<$eÁL{¨µpÀècfØ_s{U´à€ÙÔ¶ì¹µ ÆŸ—½N2;1A ‚ Ú2T}@µ… ‚ÈÙ¸ O¿ð±²I á,<±¤4ÕpžØ8 ©ú$‡K”ä°‰²¹ û`Â-¤êñnQÑkº†¯¯ÙQ~¬ÚW](·/1l_/ü£O>ú;í*Ûé*ØE°Ü7ˆ‡‘£·û2‡°ŸkXŸšÙ9û¬.ts®!,û²tÒÁÂR!,M7AºÐ­·„°ôÖ'¢XvÎp K¸ÎÎXÚäÊç]gƸNí:×%À¢­ Ðù·þº¤°.·Tï!tëýx°d  sù݂҂D >¹=% Šü.3aÙ´*éw¹E€FÂ.>·Ùe6XÀ.í#ëS°½ã`=çš…MÖë]Ú Ö_ÆæäZŒlWååà;⛵ëËÃYs¨®y‡Â’Zo)šŽ°>¥õ"TÖ¿|@X1!ý͇Y5p5Ö'-UAà zΔ¥ZÂR–*“Ò+Ü2JÛÇ’õ‘}„ ‚Ì$¥Ãüœ…憄u07,27,27,27$¬ƒ¹á`}¶& &nuôaTލ A±#¢`]   ëâˆØ©dÌúEª¦\}êîϾõ ÀöU4¤'œƒ ‡ôGçÅên+¨O}¯Ž'P_D“ ³zÜüLV±iùY³TP_ 3T}@u–YAÑÍ0ÿÀÞŸ}N7kþ˜ÒKv2¥—Î×ʽ„°‚ú–\íÌUÛy\ PA}ÊP…<Ψ ¯‹‚ž0:“¥÷giU×Ç£,ìÌT¬O*é9/­êúÐ…ìK Ìœ—Vu}”FÓå­jNÚ7áfßr*¨û8¬öM¸Ù7JÛ7 Ù·ÒnßÄê¼aš“¦qꓦ‘õÁ„­¦Q,M£uÂÔ'­*º¸–ÑjkV Ý)(½;Ô'*=a¸;9¥w‚ú”=Îéµb{Lí¬‹=f`‘=&çì`9Xh©9;Øc’îÒÿù£?FQŸÃ©OŠª¬äšîpNˆ`ç7d,`=@·¡è†t Vp°m9¿6ËŸÕ…Ñœç×ðøóò¡è ¬@¼jV°cñª)hXÄ«Âk›³ÍÏÏ͆°ûykÿ‚U‚ñó˾w”õ¸¹Å㠻ǵö‚3T}@uáû„ÝmZ}Ÿ¤@¡ïcfÌú¾Üâû„Ý÷YÛwªO9%³‚œ…^ˆä±ƒâ`¡ÊiXè…Xä…È9»x¡œ†%­TnõBÂÉ åV/$œ¼PnõBÂÉ åV/$œ¼PnõBÂÉ åV/$œ¼PnõBÂÉ åV/$œ¼PnõBÂÉ åV/$(/¤ïd8ìÍëö)›ý ýžñðÓ_ ØíA^ì./û×¼vC0±>{óÂðñZ<¿7å³#‚± ´C`fðòV|介ë&oþîM TÍàx=‘z-LÞgØ›;N;GîÂh± ٹ߅†_‚?リ8,á=ÏýYNlÛÆZº!XîBvîwÁu ä.´ŽB’‰%@ X&JÌD˜XH74—@3Ñbâç?‡KGTcV™Uûb_~²‚ÅÎÓ)tk(Þ?öYáˆAPªÒƒO°¡©$ÂàS«è1´5Â0QÉ'kN†‹/Ÿm|È1œÌjG 4'á ' „a¢—ŸÔu§ãIßǯ.Ä—ÏÏ;J†L~y ÌÍC†¼znŸwŽÄÐìh®¤Ðw&}´Ç]ý–;bðoÆ¡óÒÙÉ`Ø•eÑ8b¦öIÇj7?ö¹3†Â@>WµÄ0ñT]žaŒlžsžjÄ VÃñh.êøðÑäMáˆAPÎNºbðI‰‚«‰*$*@U:bðWJW™ &m¸™t¨`átG ¥«T«*2éŠ!&erÒ£d2w•IÉdîˆÁ·­¢äW!œVQ2«.«Ü*ÄzO&:i ]´¿ÖסÑùüÿ*§X¦ÉñçÓ„t'͵ œÜeµ7¼|\òKw!Šþäµy}>Ò¿Ýu:Mâ||;dmý JÒ š³¦«n}Ö< ©" èÏ-Š®owåtÊP«È“ù6Ä8XÅ×·óéCò€!¥[˜*©"-`©"XcbßǼ&,Öü˜ÞºHïcÍ®÷1û¢}k¤÷Òû˜Cï£ä{Ê[î »Už'‰#¤¹ µƒü,?!ä¤gv’˜ÛgBè‚EG³²Íd0¾Kv8ȃ|}ÙÕWBCn!YIIí&½NoÖuºÚͬ*y@AQ$ùãŠYÁ {¢OÊOÈÉOÍÉOè ?@ÒòSHZ~ IËO iù¡Ö)üä< -? üÔ< °%£ç³¬wKжTÚRÖ8·ç€œ4Þ|Wñ"ó} };d—oÕ2˜Sô oû¹ßu C»§•õ‰šíì$èi–!·Ÿ§ñþ Þ pVö[¸=ñØ=É™=™&]V΢ٮ÷¤D{â±{’Ó{"¨=ÉÁžLeÖJq-yÂbÉ uö/ý¥•‰Ó²²Ü½_—çþ+åï`¼™øÔ ~ ÙUEqøÙèùj²Q¦å¹·‰ÿ÷5sšáŸ§dÄËä ÀÄ"^̆x±JÐ+þ@‚^Cµ+ö§fO@Œ%¤ý¡Ï÷ªý¾˜ä{+ˆpÊ'ãõ:>}~¾]ø+ˆHïC—kµŸì@Šú¥øØÃáÔ "¶îÜÇár¦Ö‘¬fUu³z~þ,òÿþ£ýñßüëÇÿúщÆÿóÃ{ð~¬·|\J~’²¦lRÕª¹É= 䯊NÙ3XvS=wQ4 P8a¶Ilkõ$Á®)J(ZɾâÞù\î§Üû©LzöS½IqPåéTò€vÝÜ.ùž$8yx€M¿§SÑ€©†ÅCÇQýuBÓì^‡KSó€ÑÔ#èÒ¨ªˆ\ž›¡÷ßfÕ¸ÿýãþëjýÅÃëÿÒÑxT¨—ò;™žu`&›ýûÇÐù]óÑóPc«‹ºÜ†ÀüÄô<”›^ª­V¬º T!¬Ü]·ZA¸ ÈuÙëò<Çß%ÙüÆGV_voÛˆ‡ð~¶Éïo2»“E óÿ1d×NÅ4¹<çÛ+)Ò›üÞ–ð­åÔL^»mŒÉÙ~`‘rÃò壸{„&0Ù‚‡.ßг~±*ëÈÚ!Tù&~j^>v›à7EÝ_½©>›&¤æC6CÏÙWñ‹£c?lmVƒ!-‹úyüÂfG_&§(ßÄ?í#Óêæ£ùoâìÇ]ºÚh ¾«ûx?š…уþ~[¿¼•þêT@¹1 |´u¹ ~±U²!T+ú&~ßnvÙç6ólöáRÝZø¾‰ß”Àä"M’YUŸïÃß…‰>c {-ªö^- +‡²ú}w܆€oÏ$ïWáŸBø9W‚‰‘Î#}¯“YQö]¸eÜߦàÛsúoìó’¥ ãÑï·)„D^3~§ê@Á·F¤«¼Få\:`Ìó¯å5,1;PSÉ >Íóz#ëNÐ>íøB<Ǩ´£­·!R¹eÓÜG`y=[D4I-¥Ü¿ 2Ëæï߈é/rÒpÌ/›à&oul®I|;?ŸŸO›à¿]èÌЩo€(ê}]o‚?¢²ÊÝ·ö×QZÔ ¿Õw«°‡"ê>§,¶Áo—Ÿãå›ò37댦nê» „ÁÿÓ³l€î½émèé´ 2§)ŠmIM›oC ˜Ëhßáùv–ç;÷à'•Ö÷iAvîÓ‚{ÝÌO[^ÿù÷Ï<äz¹VÇ·m˜7!uûtîoÝ=˺Ûïm{PŸëïøéÁÚʽžfEÁ¾ /ÕÛq# >Ò_QñÅ®üjH'¾Òåw„tâžn#Ñ!ÝF+ C:yç®Ù?Òm3Ÿ Y¾5&dÉïYÄ!K½ ~Ÿ )Êú^E!E~GH!î )6ZR”ÛX»³üŽBÜRäÛö|Ñ!‹»²Üˆ‚ ¶ùT¹Sl‘ãÄRØ\üBdjÅ?åmþ_¨èʯÎ?k¾‡Í¿rçOhS3Èÿò{ø!ÿ‹/࿇ÿò{ø‰Jìà NNžÌ§3§ÙüWá¨Ìì4ƒÍ¿üÊüÅ×çŸ×ßÃçŸ;áwÏ¿øþ™£ÿóÔ_yÑ'e/oå[mÍ[œ3o"Ò:÷I_¾..Þ…_Pêæ›ømÐøqé[!e½ ~1åÿøééeW¬íïšPZR)¼'oC`Eœ»B–õ6ü²'PnC ÐÆ¿t§ñY÷ΕU{®ŸÛçX®ä=69Ziq~‡‹/hq~‡‹;´¸ù~R‹Ë;´X|A‹ó;´X -¶)Y¹ AŠh¾ Ÿ*;5ò[Zêr‚T²ÒŠg3%³qHl¤d%¡dbK%+7Á/þCÞêÿ<ýQ2ªXërQ!ë?ÍßêáÇ…ž=Pv…§Â"~`ç»êIW4°TS8°ªi_}ô v™_70DÛVÏÑBz ¼­ºèÅ,ʪê'?D€vU©eû)G[aì&©VxcG\ía F…³P}¼lÍŸ ~ððHµš E R\¹4#Å#?ÏÊf°Ü”œÑƒð“´!Šb°¢j\{72BBlö2qРåp¾Ciì é#y׺Ö R!m·âGžºY»šgì±vKÞŒf7’¥®P݈tm¦×û˜KfßÕÈ€‘:½"-ójd %DÏ3@Ô;&~"{ØŽÔC4²í½¹@ƒ¨Gvò)nVÃÈr©6#yÝÔ&QLyêÊÚG­FHæ —RÞrëijÎ'Èz¶ÃЧ®$ÞXÅË|ï´º‘~9¯d)Á2_™H!ñ¡¾÷Ö¦)0Òð3 ÑÈÁ_w#}è µMN",óý<#>JºYÚn¤ˆ¡U’œð6YÞ‚šn¤™ïç™ß¡ý¦žgÊ{¥™ý¥M=42ë×Þä,ƒ¼ùŽn¤/Ðnj-Nvß¡ø™v2/˜HàfÁÒàÁÇz$û‘!ÚwÃ¥hñ¸›jdÂk\/u#tSkGÚiG ý‘žg çÙÇÈjd$Ùø£n¤Ð&÷ÔËù1^êFúЂéy&œëÝó3å¨w7foÞã#dhf§÷èA>õñš*tñº¨ð(€ÖU·¹ hœ*#ÎÞ£ÏÏÕè]9 M[«+ëCn>YeM®Ž‡ ˆéI?NM=(VãÐÙ=-WÞcĺ½Í5r=F÷j(ïFµI1ÌŠ åí£L5”À-ÐSC}Fef®1–f‡Ð—Êa(0€£¸Äœ ;LÀ÷€ët xsE¾í±¦ü²Ú1|WCY¾ª—å=ò†ÈhÁ0”_V5rÀó¸¹al= ec¤Û²º¡~†Úi,Ü‚¶†@c‡ øÈŒB¨†‚ÒÊÈ,ŸõìòŸ«¡Á#´f·´CÊóB°c²©†ÀõÕÏ‹° X#`Š«!¶ñ< [Ƭ –^¹ÕЩa6b‘É0Ö¥ pµ·„^ÊmÁ Üu?Ô€d Z²FÞòNO<>>rœfYjh LF¿,Á×Êha£qÕ³›}톬ͪ†ÐÍÅ×£!ꆆP\zø¬ÂôÎHK–øèM+Œ±."ä%ë–©¡>Ü­v¤¼yˆeEa¦™kÌçÀ:ÒÌÆ¡)Âa·bÎÀwyÓÍuCƒzîršÂìÁL AsÒ[O¤¡ÏV{GÝò;…‰A:Ø$ÝЇì^¡Í2X=Îo)C2ßÖå>ª¡)´ÚšY¾@%¨lô|Ÿ³ŒrË~¨!Ñ6^ M¡ç†; òêóÊ-'‰I7”eV{‹µ»¡Çbó-uFêÁ„Ï pb2Èkĉöà8µnù10oÕPyWCÙˆHó*‡òñÀmcQÊ­í«YVÊGo“B M‘ŽChAÈ=dƒ‹ë†²hÇÃ/ð€dÝÒÈ€õ±Cìb& ÀÆfcüª†â4ÒLÀGòZM††H {£ÜPgõÖ%èt+`’ÑvCC#"ÈK6ÆAìbÊ~hè#Éê'?Dˆvo³‚ÄÁºô|MYÏ­e`¬”Ëa´‡Œ¦@?` ChŠ5Bï!Œ`œ•CS°½Æ†‚ß­I髦мée…¾‹ÆæýÐ0’Õ›Œ0Áþ-;VCAÕam54æ™5ج°Ó­Ú×¼ÆÐ¾òáco4‡¡p}@Ò "6z’0áæªµ`äkÊ[—IðÔ å…ð–FFxc{Çy|=Éaº¡öÜzY‘5¶7šÝÐH@Kh°²âb‚Ò^a¢ONÛ[-#ŠøÌh’ÃD¬¸¨ÄdtqÝÐèm—(yˆr¾ êdàdFÃÒ‡(@6kƒ¼`—˜Ïa´nõ»{Ü\; 9‹‡"ÍØç—5)ü¨¡°¯ÖOÍ&&#Ž¢*·Á£ ÉèaâS󧘯}°ß  Y½)Nðn Ìê†Æ¼%üVÒmÏ×Q “ð!J€ÆöÌJ"àäo‰I»è––×$yˆ°}ÕsM=ޝZ ¬©Àèã×ÔH<àa¬ÁCB›e†FÜÐA¹ÍØàI›·^´ÅcÇ×pÀÈ«xìÌ[ Œ¦ÙXñ˜>$P^Mç²Ì—%ºL>™Nà÷ï¿zèù¢F¶eÛæ‡]Î<:Þï õЧì2ûÇc ¡UÓöï?êy'õšzv¾d—¬©wMÖdu ¡}EÛÜô|´º%š±pA‹ºd0¢žCQQ—PÔFÔk(êõB[E=‡¢`Q/ 4#ê5^7'ê˜çœ¨ã™³¢Ž™nõŠz0u)Ÿ4¸™|'k•Ü5’õ`nÕ犢«Pr7~BÇ@‹aÓÛͦu´ya fVÝ*¬yKzñ`fÕÉ'ª¨Ãúu¿¿¿’_s«nî_œ‰[‘¹Ì<"Å­ª0×b#/ê¾/-/£¸]èç˃¹U_FNª$^Ú„N×Ò’9HKHJKë -!)-™ƒ´„HZªÓ¶HKæ -!–δahFZ¸ý¡´Tx݉ÕBi gÒò§—–ìlúAê]]Ô”a 1þܪnΆ³ÿ—zÂUsÍìw–7UÓ´%¦í›ýþ3Ýo5ó——}‹i“1¾rã:´ð\Wsƒ.bü…=/y ÕÝÉ´=—¼†Þ ­ö¼ä5ôÍÙóB[íyÉkè š³çxÝœ=Çëæì9^·ÕžK^CoÐV{.¡´$Œ=/¡´$Œ=—PZlÏsmµçJK‚íy ¡9{^@hΞc®Yíy ¥%áìy•wö˜[wÀÙó·wœ~OÓ¢ßÿLí¹Š;ó’ÕBÛíy•¿½í[L›¶çU…×m·çêK› B÷5›?&;8›ì PsÏ ŠvôÀ™ó. æt3IëyÖQ~©r’g#°o 3U+-h#p0³JÆ2(ï›Õ5i":nÈŒÿä=‹–AѾf5i¢yÜ`ñÝü²gqÃmæ™ÉI”°\H/?Ð%Q Ü2aCü0[õB³%©é/éhÍ–|¤vƒ¶Fj’ÔnÐVÍ–|¤vƒæ"5 mÕì’ÔnÐÑšç-ŠŽc:R늎ãe¤6³¦(:Žg‘Ú‚ç-ŠŽãy¤fçyÖ@h Ï3ÇóHmÅsÞƒÅt¼£yÎ{°xïÌ‹LéœÆ#9˜uK>‹Lç9%¯r>Íi,gß´÷È鵨f0ë¢ú8ë2÷-BsbÙZ;S/A¥ƒ ¸XK\‹êpßRÂF¥‡ x`—¶ >õ¶{¤¬‡æj7hAB³|÷h#“p–ïÞÂÊ,d.2ç-Šƒ ™ËÌys;c9#Ëx¾“‡¢ºµ‰w,pañjUÉ{µ ¸oqL œ3ÐðÀ^æC2’2gNøx™ I™3_›3ÞÁó"FÞ•ª3Ò ZØ÷œõLžÇ2äT'àv;SÁ=O8;SÁ=O+[¨ë)cce u=eÖ^ë-“¼§e’ÇÚXožåYl,¹”‘w™!™Ky—Àζ`Ø–ÀΈµo›FÏ5°3bíÛf?°3‚óm¦™ã»`Ë ª˜Âê›àdN×ÐÚi™Óàhí)·vÕàEgšžß%‹\®©<{»Ë_àż½í2ö§=ŸÉî•)üª%ñ2öKW;xÝ”ØÿÙΧ³Éò›lW7²¡Ù7 ¼:)>Ÿzþuð²i²Ê…*ÓWÐñïx0Ùö{³ëMÖ^Þàc{LÊûHÿÁ§m:ºA ûÙcÅÚ+u8ãŸ«ŠµW#´ Κ3~ݬ”À^ùk9‹r`¯üµœÅ„À^ù¬49ص½22CØê±|»«Îƒ¯âáËxfLÖA'à>Yÿ½^¡ùÉW;ùˆÞÔû\5SWõXSïÏË™«ð¢Bb³¨g>-ë™@lfM‹ºS‘r!m§1¼©` Tõ÷ôíÞ$qtâ0dòÊ;9|SO€ {HË›è€5јè€1ÑæB.œøªjëìJ¶AÝ  ÷Ú¼¼e€vÊ󜕷€ªCg} ÏË[0/D¯4yÇ2ޱ…Ž1dcµ<äVžA5¹•÷ŸÆ0šuáŒOªš H¸pro 'õQ\89·…“ýÇ\t89gÂI²™k ? 'OÇ!œÌs.œœÀGd{/à?Λ¢ â?Ñês›²?÷µ¼¿esJÎæLà#ò£&‰I›A.‰—6l3¿Œ™ä« ¼¿l¿ŒŠñüŸÛü?†ê°Üð¯mjòÀ| O4ãðÑBÌÆhD 1£µÜ;Ü»¾ì•]ÆfÜ&w€÷íñoïcÆÞ·ðˆ fì} b.§ÉàAÌå4ý“GÇ\m6ŽË£c6V2 øî±ç ʼӅ'~í08`íÊçxãwÃy»˜óvæú(NêÆZ˜j8¡K8k³É„×6M&\t³Éå5 ÎftÈ{Bµ=dÃ=/¬¼'‹ *lJ2V:í¬dH+;ô°x‹‡Í ‡À[;ÀÛ³"ÕBù¹Ïàýeäeü<©u™?uÀÅêNÊgE@oSÖK–ÀC«—¹B ï¡GhŠ6k+SÞfHà¡S¶¢Î×ÌÛÙWþx›‘ÏÚsÁé ¯q0Xœ‡NYmZ9鵋G6ªíÛPi{9…·‘ÔüÉÞ'hî)øLŸáÞ\ØcVß…7רõ 'õ7haw” =÷³ë®k@Üóù&VnD·oÜÉšäýìޚɖ¼ŸÂ[3Ù’÷³Sx.“-àC²•˜ŽŒ5¼Ï5®waS‰™Â¯Že/cv-à}ò„ŒŸ ¦ÏDöpAÖ­”ž §õ‚³ØýÇÛŒì«F„„1Ù%ý ¼5Æ”@ö'ðÖSÙŸÀs1fãO®ÉÈŽ‚‡+ùÊûÞcJ¾ò>…·VÞ%_yŸÂd;=#½>c›ó>&ÆžÂÛ+I¯ûþ"ƶ6¶ù÷¹Ä þêäj3ô­ítÌà³¶+C}þÌŸ3xú´—ç_ ¶Ÿ‰7'à‚<÷áµ/ÊÇYîEKŒµ&Ãó>¦°ž?}á-O@F-c“µ<Á*j™ZžùMá-–§Eg~Sø€¬óëGËçö>à÷ÔDHúͱ¦ÆÚ½på7Üçk SxKm!Cµ…)|@~NÄè}Hú½ËxîÉÙÍpå÷æv_ò'SxŸü¸ÌŸKUË Ï?`ì~ì~Èú­¾ÓÈŸæÏŸp‘ëZO½yú)Ø~@>Ei~÷b |œ× 9Ýï?£gÖ®ºRÎíÝŸÀÛc> ûxk]±º?§?Nb,oDÖ¥Ç*ëy"K]z’ïõŸ'Ñ1_´¨K[{¥Àü=0ÎuDHw€ôF jÒ¨Ä 1+½¦6Ëí^ÌJo™7ÄKé]Ä %ˆbVz3tö­á™j:ûžÂ[yþÌXŸ˜ø3t<…§+û¼ü$@|8å¹ ò‚fõéÃOáqäíÀÛ¥ØÞ ¼5î’ÀöNàò#A~ýLÜ™Á|;¥ê5c‰ž·½é"î´~pÆHOÊg-º…€³>©Eû¦µÂºÅóç¾c(ïPðÌŸÿ <}ÎX¯ú.>áNYßÕ×ùyú P?@>á}g»ýGÒw]Æ£=ÆvOá­Ò_ò¶{ ï“'“´öúà„JÏŸ±Ýþ#Ž<8ëá{¼ïׇ“Œõ˜ÂÛ³6ÞzLá}òó/Zû4ù´­Ú7h΃šs!xæ‘ýqVµoМÁ3OèG‰2 ͹Ìs»‘PØ|ÆH(l>ö#%„öÉ—Xaó±É!4çGðÌ#û]ÚHØ|ìGðºúM#NØ|ìG04áGª.#i˜ ŸÅŶ·}Ú:GÀÔÃ@E™Ûýˆ¾û\Bà€~T¨‚À´±½)´¦j JP¢þ]½Œ“ÑèÁƒ‘k}ò]YÓÓ¹‹¨[0í¾êCêÆìÛd[ò1R¼Èù,¯ÛÐ1RüòOãp1RÌʶäc¤˜•mÉÇH1–í–̱ãûcã-È<·uSËÃ6»gçåhžß³ºéúælÀðYÝÔþ¨N†¡–;@ÛyÎ[ïx‘rÚ¶¡Íw¼H9×МýŽO¬ž”e x¼xÀú¨N…¡-ù*N“ÓÀ÷Ô¦¾£·i0ó&)f#°O>jÃM;d§qÊ•ò©D¦2Ó–|”>°7¸·@Hbø" ™¥³×\­ºÐ²í=>øìS•ì¼oЂ~†”î´O>ÉB3¼ƒŽ¹wZ4sšå-J:oÐ>ù¨ Ãsåy xî±<ÏϽÏWO’кÙAÜ<¼M¹A ú=R;oÐ>ý ÙGÑAÏnì’òW/lãÕší®º¼cðÙƒè½ïÓ¹ë[q¹bpŸ~ѤfØ>ûÄÑ2ù¬­Þ/œ~“„Ýtöá%Þ"ß ý  ·é1c"J`"¼öšú)ZÂ̼&b„öé÷DØL>SóùÌœ~„ÙqÁúਹX9áõs"ôŽ Þ Whæ1;s^Vï‡+4ó‰¬þ–ÿüý»Ûº SÐy±«^vÕuÿIA/Þéd^²“Îߊú¹Ø5ÕëÅÞØ¿ÿvk?ëžÌìòÞ\ϯåëùT8Àû3øÌ¼¥ÑÁ7¯%­-þòò`ëk´^~B¿y}Â’µïGø¾±ò9[2Á6e'±»Ù„3…7ëÿõ÷jIíõ½¼Tíg~ÉJxs¶õùWÓ7üWôÏoÙáP;À‡C!Àœn)þ›†¹ÓÁò–ÉÞ¼…¢à]’dø_Õ2—oo¹ ýx€>ç¾èUòz:Ô.û§Î¸~ÿó[Éÿñb’ê²h?ŠêC:ñ?Áëùkø¶- x}Î¥7p8zlÚÝ{ó²ËЛ̠[¿’Àn»¬z{“… qËÕéæ¹ŸÁsS>¿;-ÁŸÏ 3 iw×cõ‘;Í@ áç…@q@‡)eÕ/oo.JdšèìïÊÐ~kqÅ© wí©klÚ—+× üçïo¥CÇóÉ”JUI«Xš«üþGþ5àÙ^^/o™ÃäÒÛƒ‡ÓJÞy¸„+pºh@Y½ŠÃx>ŸñÙÓ¥Uhæ —ë›EYŸðÒ^eíõƒ ú]V×|Þa²1¢¿¸ ×ú4 ½ö`ñÕ’|üu°ŒWìþ¶v€÷mþ>þ>X¼]¶ô×9ð×Áüí²•¿®ºË·Ëìþºt€çüuáoñ×9ô×x‹¿Î¡¿žÊ篥 q·NÄÚÝ–ÐÝNøëˆ!‡ÃÅ_çÐ_O„ô#C’“┫,¨ù²ëïR†²H6^­+/Ç+÷éWШɇüä«6û¸bpA?STsâãóö5¿g~[h-ož™ûž FZ¡‹ù=’gSxªU0T æw«U0V -æ÷me0Ú çæ—xª‰v!çú3èúÙë§*˜d);¼µ´ñd^zš¼µCÏ>âÕ^‚jh´PûE5T‚jhÄ«} ª¡‹‹[,“g«¡ó‹[¬Ï!ë™o&O†Ð³ÿ.ƒÆ(n<ÿø—ÊRJxk’TÅ›À¶­Š?·¦I%PÜ |D?;B‹þòâ–¹ø´ð$`yqË\ø[xÏëLÄË%¬üÄüôYé×Yßa¹òÂËš½¸\ ;ÉÂì-­®º“Ì?ü^9­Èn2¿&”rš.ó·:½è^²xìhéô$ÐdùÀõ:àJ¨ c¼ñ“ÅÅóx1ƒñb²¼ÚÝú ;ÿ˜Ÿ>0&œî ïк“pº£…—Õ„Óá! zí)åwÆûÎø½[^™³ŒõK°wéÜïQÐÜKì•Àn/¯ÜYÚíØíÈžv{qeeú¬Ý^^Ùc}Ï‚Ýý˜ß|VòSÖkôÔ…GÙíñ¾"VöÄò•¥Ý¼ìMá}úavþ ?}Ž{pÁ\a«ˆõÄ%š¹nÄz("Ü. .q« $¨kðÌéëFJ®EÌExÝ1}‘Äë¶^7RÒ÷Ëök (h§k lý2°¦¯1Ž×Ô˜ùÕzv)¯1À”#Ûw}9}X]c@ܹÍ]c)§¤ˆÙ¯1Î×Ð"ærA¡I!#®1®×0{ípA.!4óùigÎZ…iÇÌ%˜çÜ55„fd­ÅÐô5$§îtAŽ€™k $¤Ì\c@º§k $)~××k JØåƒBsþCBh惺МÁ3ç\ž9çC0혹Cs×Ôšs#˜çì5Œ°9\cP@hÎ`ÚÌ5œ°ák òBs~Ïœó#xæ1s æ9wA ¡9?‚iÓ×ȆÙp‡k 0sc×ð5 æ®1h0íGì××k ¨i;]cP `îƒ3×” ìpA€¹k jL| kcåùkäê>UÝ 2w^‹¶Smkue-¨+˜øÌé …3W(HH™¹BŒÏœ®P˜‹ÏJL^¡ÀrÛå …B3W(HL›¹Ba¸Ë B3,Ï0mò Æs¸]¡€¡™+r ¡™+ Í]¡Ð@hî …B“W(ð Ûçøßðçø †æ>ÇÏ!4ó9~Éì™Ãçø„æ>ǯ!4÷9>·eb±eëïéé-sùžžu§ïésÍ|OÏÍOß`hî{úBûÌ÷䤸ÐO²Ï¾dÍø”ÞòþsLšq.ŸcÒ[îô9f¡™Ï1¹™ãÏ1 Í}Ž™ChîsLnËéÎüå¿Ëï)‰"Iêý&àôS¬’O9¯bzÔ8ðY| p‹o¡¶„üâáÖ…ÜÖß³àÏ»xdú)àé'$xL¿ç6ý$¡àà9æéÇÜôÇž~Ž<+9`õ û-R å>¢“!ø˜S[°ú„[ýØVMROÁÞ—`ïS°z öž~ tÚÌM?f÷ž]½ðøïІÆZ>™U ÿ,›í‡Aÿs²s¿ÿü³<…ïüdk¹°flª_O³º]Gùpxµ5Ù,€}²u¯ÁÀµfkÜ“ Ë0æ_¾YÖ…²FÀ>ÙCÆ­9ž®ùiy–¸O­ÜÎ pD5å™å͈`x;aÚÚ¸Š ‹¡J©Ú<Ìš«ªTUʶ­°o’’ßç’Q«$´V5öÉn$ZHBFHF•,0#$8²i•DÜF6ÌÚˆ´fT²©°O¶ãpÜN•”¼JŽÀœJJQ½8EUÓÀ§’êä ÌJ,,‡5æH“Sɀ涩J’aÑüt­Ûi#%ý“Ñy“UmöÚ@hóÍïßþª¯G ]e»6Ë2’e‹þþòäãxyòQž›¶z‡ÐT—gAãÙy‰µÑ‚¶ ñì¼diAÁvÅóvÒu«;mŸœv‹ <«ª.¦hÚ³ÆDK·£1£-RŽ˜Qެ…ÜÈi›{vÚ!'$hÚ!£Ó%švÈIÉ I IÉ I IÍO;a…DòÜNn÷g¯4·†ÛýÑ+7íYØl;ÿl,7ªÃ%î1cAe³Ë :ÿ‚Ñ|¹}<*Òg%&Õõz~.³B›»=/îö|y©®¤¿A÷÷Ê©›šŽç!Ål³¶–r‡¡•¯ýýôûIÑ>êÙí.?ÏŠ=æZË”ŠNŽMùòÞtÑÜ[Õ¾e:fn®Ý?÷×î¿·òÍçÉp£èþpèŸx+ê¢üh¯o:݇ª ‘ú>Tyy³Ü‡º’–GòÔºi™ -Âvïò«vYUî!4)lué@Û'®Ù™ìÌÛŠŸy€NŸé '“¬U” rÒťŶdÚÞÞÈ´iΘ2 ž€‡Ã Ý–‡¯~:¶¿žl¬À#òœÞug·}NŸB3û¾¬!-¨—`߽Ż$ö}Ï1¸ÏlœxÀlœÄàáZêr(u7ðˆN¹jÌ¥\ ö©à°°]·1ÿœ½þöËñ”}Ž2/'1#'’“y¡ÖöK9äßâ)‡ÌšKžÛ Ëí’çvÂr»äל0kîßd¡×<¯xÚ6a´rY´´¼/ÒM;§¡é;íÍ3œaKš‚ñŽ pG7mŸüÐUO{ùŽ˜ºž"$€Y¿h¦ç.Â$ë^I,è½*jì“ßsÓöÑ )¶P2â ŽŒJ‘ëv<2*p|dDSw:2"çvdÄ‚;• 8>2¢©;±àøÈˆw:2bÁñ‘‘%¤u92ÊmGFâKGF–ÀÒýȈ™6WOÉmGFâKGF²$€ŽŒÈy»Y‚C—#£Üvd$¾tdÄLÕ%föª©0SûÊi†9Ô¾Èvª}qиöEÎÜ©öÅAãÚ9s§ÚIÛéÈÈjð‘Qn;2_:2²®ÚùȈœ·Ë‘Q-0gÌ Ì1ÓvØ«ÓÓ®‰€™#£¼¦÷ ×)ÉvªSrиNIÎÜ©NÉAã:%9s§:%IÛéÈÈâr¿pddÉd¾pddQ/—#£Üvd$¾tddÑ÷##fÚn³@ÀœÛÌI`·YÐnn“vp›9 íà6h·IÍÜÍmæ44>2² >2ÊmGFâKGFyA»˜bŠ´›)f LqAC;˜bÚÁS3w3Å =Ýîþþ£¶[?W­nà-•˜f³d9˜5Ìa芃ö0횀hç4´Ð•}æ¾ãÌ«š‚v˜y5ïÖX@ ȵz͵Ñc®Õ9 ¹–Û áÌ+;Ï}Wž×<4»nuÃ*‚€öj¿}Wž×¶ýöÝx>ÌÜ í:ó¹´„sïíãuç4´Àë¶AûÎëžC“ëþõûIÝVÝW¬óbwyÙçõËú¾¯ùÏÙ…×ÿüшÕñ™~D¬Ìw™»¡0ªüó÷F¡g¡QòÃÙqã^Ïû}¿—·â#ßÉwÜNå¥ëZ8•wÜX»Ê—n*ÎU¾ !€i•×Ö´GHB’%­›Tñh+¨ŸRpZGšÁ¬Í¿ˆ„aIV"$ëG)–’|¤õ‰†•´ÂyfkJ—­I:†ø¤´š· W'HlÒª?ø nkj„$Ä[#ßZ7Rߘܾ¡óÐÛm›¨ôTH7‚.€‘¥§ŠUzɆÒSḦôDÖ5(y¨b§ñ ]zZ ˆÈj ]¡X ˆ‰¢OÕeoŽ(èÒ“tÝÔ”‘‹ H:K(b!Z3¥“€‹©hY -P:Ŭpo+÷@vÎ#(«Žn(¢µŽä®:"¦¢e­ÕÔŽ³HqD‘’…¬#”8\”D G%sÇmõ£ïŽÒåùŒÂ»âwUW%£ŸþtÒq:žŽú‘¹¼jkùü¼«x~³¶ûÏ?£ïp\:ët8Úê¹}ÞÕŽ8 O;$ûƒ:ðSAú»~Æø°+ G¾ GV6 Gîˆ#¸él§o*¾Ö2¶+«¢qåG¸ÆQjmѸò#ºu–ìûÎ’NåŠý¢+“Ó8æÝõŽä–jY]Sóm*?²óÀ¦¥K“KtLÝ¿áð­rZi9…< §²nÕÌËz“õÂG@É©‹¬‡¤¬çβ"Yoqв>ï8çp$”œVMqx«"ÔR_*WtÍÃAÖ½©¬Ûí:ïÂÙM”]/q»œJ,ë7>c“]×06Ùu-¡]oK¬s7œ]wåg×]ç‘06â𡬷®88»^;â`dσaŒohqÆžºâðËqŒÎ¹òƒ³ë®88»îŠƒ³ë®üH{ qÃt¾¡qÄ!ßàŠÃgÒR‡À)z RtaMÑ-ùuá†Âg2ÛÜ Ó…P;¢ «?e㸈ÉJg3ɱ# ¦ú“;ÊEjÏ„ú…ú9õ…k¨Ÿ—Ž8|jl('B¹„rÂ5”Ãk™ÕIíûÂËhè´/®8¸}©q0k©„C€µ°¦X¬L1µ/¹#Ž>ìø£B†ƒZÉY… Ý¿»,_w˜ÌŸ­ý.d̸ÙS_Àî|}aÑ9;±Æa\uYXÎjì8|úPÁ¢/ b–/øQ*~”‡#ÿAñ´tài°Ó%Osw³/®8BF>JG³W1ÃSW #c ÂáÁã,§<_pÆá3ó ×"ÖR‚µ絸ÎÃgæaÃ!ˆµüR9XgOUötÑ›ïÇÃë+è©7?®|Õiß_¼¼¼Áï æ˜&òû.1ÌÌœÅn÷^ä_ÂäÏçÔcz>^Ý1-÷|º^«ý¾˜~Qò?þˆ•Slñê‚É}/ÐÇ%¿]N7¸, TKÉ“ÖÞÃq ×Ë×÷ëù¨jáxúGGúÇóúv¼ÖCNKêã‰Ï§?“´ÛÉæ*ÛfØI 4œLøt>õT÷×úZV`­Ñâˡ᳟|—¨å—nÂ/m}Ü 'eh2Oˆ.cðåX¿ð c¿¿šðyüNé5˳‰Gç_:Ó7ûVdµ|})ÀbÍ',¿iXÕŠ &ÝT»÷ý[µ¯ìx¶;¯ß¾ä!aÇv,#ÇjÎFŽ/poõ‰×ï§.>èxÕWz:^]ßΧk DÊ4óþþûô§Û¡£¡ûVÔ—¢3XâsD~vt(žl<»žU±J·JíäûçõÀ.^/c#ôóé¼—RŸ9½ä/°sMè Þ±ÍÛN0l/WÔCä'3ç¬ÉvïÇ·—ȆË,ö2~§ö~°¾¡«ÜØé|Ô.è o‡¬>Ö`E0ÕÁ.‡ï?7lùá‚Ö{û.DÁjºöÒiÃ'€(›^„þúSw@x’€ Ú¦¿Ö<¨O{’7@5 mzVò !åI²&oxЈtB§PÍUªôm gí²¦Þ§÷] @“õGƒ'‘’Mu±¡¥©ÜeŸ€êÐ 1Dr—±1¡9å{ëÑn艢 ÝДçÓn®7 ]I‹è†¤ «rD7¢ÝPäQ» µˆÏ ùå†ü¹;X¸!õì'í†ü¹;°›©ššs‚ÍTÁƒ2Qëe¢Ö×’ ­k i[Sªcá$3vµæAFçÁ„SÚÂ5`½™š™¸™¸dùáõÌÄ•¬‰K¦fŠ05HŒ}ÆÄadÍ‚åÌš3g¦Ðqf íQb355oj’™™²}¶G›¸dj¦F%ÒE]­DUM%œ³— ìJôIXå`qK²ew Â̲WUµýø‰M¿¹ á¿foØ÷§ª$’bñQ6E³«éõÎê Dé f÷Gü~Ò­ï§ã©ÿÞ÷мËq8!ö5cö5†ûJnN¼(#¯7‡äp¼øâh-äZc¸¯¤HÄp_3À&˾fh_c¸¯ˆÃ õc¹/ì™ÓâšÏÖÌXÁ~–Ÿ–þ`ñP¾XŸü`ÃNúu;Øó =í~÷Yl8Ý!«/^|ݲÛW/þYÍùøöy&`=Ë[zs{²Ï—ã*kœ Xk ç3{óƒ²Æ’å¬qÁƒŒIk C@­Ö¸ä´6tÐZÄaÎ×h‚­±äA™}%'œÀ}­”Ù× ¬•ÙWRšf=‚v“ ØÛ ¹äE"™vtVbi+1¿Àqj%Œa;]Þ<¨ >i%}õígï$çâÙ¡¹ý+XʎdzÃò•-–œ-Žg=×ög1ÝÐæ?JÎÄ‹ë…!—œ!_¼R³p¬`Ìߨ±}Ëí.íá[ÞÃÇœ‡ÏZÄå€ÜÝ–÷´ñÂÃÛ>$Æt-»›ñÑA¼ðð³Ýmy7½x h¾»zÊÌîÎXÿYq™¥-FÆ[Œù@K;UòTCÆN•<Ց䒓䄳S––䄳Sý÷Ï”D% ;eûìÃ6i”œ4& ;µÐ ’Ó da§âXs»»|ei®%§ +É’§2’,9™Z¾¯d)«–«³ ßryàÓsÊNæÃçV~ïÍ*jô‰Kûpè<„CÍúàÈ·\øj’ß/t°ÕârYŸÃøëKíÎS@ÃuEV=¤j=‡ñ­—Z×Z ÓŠÐ|­9Z«Ã¾Ö<¨¿Þ×ík9\ƒ sT#hÎoδ"Dˆ„äAë糬w•tÞ¢lûªéÜžw5€<#0É}Š—*ß,šˆÖ°Y¾¯¬9”èþ¨Š¹I&:±øÜïªO¸Þp [ö°-ZoDæð'r½³©ž–dOí+IvR9 v—ž±ÇÇ£vWXAï½»Ó&:;—+D7 ¥ªFtCZ2 ¯"z‹È9O}­µ@ †?Ý]»þÙmr¸Ð]»Þ7–Ùݺ°>£÷9€ ýCëev®—Ù]’®àwW©}΃rºK®V`Ým,§»5€åtÑåt7°œî"^qºKÍÙAwk”‰l,:$¬wß®B±ÒЉշDP$yPŸŽâʆ ˜È&çAC&f<®ÅàqsÚãŠÕ£v‘ ©ú*±9ó›8‰µÚ9¼x ʾւåÖZ kmxP1k:*g ò«.Áuëx_EZìUÇŵ,žëÚ ƒÖ£Ï§ƒîé4þ×Z¾Êšì&cð‰6ÿÏÏæä†AkÕçµ ó5ï%{oÞò"ÏOŽÂ[®>oÆ¿~Ô'' ùaÀ±t›CL}¤px;•Nfßkš‰þ®ù´+Û«†ù¥ÑÃ^<¿ŸO»cë&QóId—aòÅ…éö}ê̺j‹Ñœx{«wûúZ¿»­£oËy2»gÕ}«w?;ѼÜP˜&B­+Oª¶ýÞ\Ïçæüúì&‹Ë”²±õ¸¼Ôï, ÏúáÊä#$USõü­ Óœû÷šlØž!˜r¡ïQ×\øÜ#.Ì”³3‡¾ôÏY5;Ùœ›}Ù7Wý{ëͪPC«÷qlõ®Þ.‡Caß­ðS½µÕÏz¡ïâB¹«¥Úbgãý›Á:]Œ½9È\ÖÍz½ŸnÁ§*þÝëOÔ”4–m›UY&‡Bël¼XˆM¦ŒÑõY6ÏÏÍÉ2~dpg7.æeî—r÷Ü0å³m>ÁbC þ³ìLöÿ42›·Ý›¦ºvW÷eÈÿû¿šý›ínóW!™1f*$«ªò:’Ì*Œ»ŒŸ^ TôÃÙôÎé½®»xèº#`V%©ËøÐ 5·p'^Ɔ·Û'+˜h!‡Ùe×—‚€‰g²n6Sɺ̋’‚Ñý’?uHØ[¤æ–MW0é„N'b6Zï©îü-ÿêNE?êNÅý[s®(Æy©]Ï’”1‹*F‘›FÐÌÒMâsÅ<ŽXÁ"zùü|^cZÁê>×rPŸŒ=¾xUQÖ‰š[82N™ µG—S—v¶íîõõLÀD æ×o½CJv:Rå¾l«¢È÷Ó7] qGïbºdäp)¨¹%Ãû„ªö^¾SÕüòºß Ç +˜tBgÛ·÷WŠ×^ß<9õZW_/¯í 49r™/¯—òƒs+ªÛ´ÍËçO hæáÕœúBçú\t¦úDJçË@éÜt”r(´:KÔ¤Ô™VÛ•g8—19“@½<ü3‰CMŸG{y~]MSÁ¥¨¶k͇sg³,|˜çY *ß_Ÿkòí±ÄÀ…Ͻ… ÓJ×Ò ·Ê gYñãß´?þûýø_?ºðÇÿùá=x?¬QÄÍzß01hºÒÀÁ°VEó)óòDƒù »¯l¸²Ç§"ï  ¬Á´/:›÷Jƒ…0eÃŒõÏ˽¶þ$Xd5åõ{½—{,"ÈþÓ»ž“åë[yx§Á›·9ìòæ|8Ò`©-úÓÛ½ÛM÷í§:Oèz]´MnyÕù·ôý@Å"F6âó\ŸÔŸHÌÐkÔTŸèk @ƒ5U-5ù>ï"Wt&Ù… hDzôOùɃÆöÐü𑽿ƒ 'Óˆ¥ïnjv§Ó¾hÎ%š’ûúñ1Ý×ðAt€‚²7Iz¹2`b®èMyî¬nIƒùö y>/6dØ6#S›qîÂ+,\¯­gÉu¶¶Ÿª¶«¸)8-éÙrø bÝjÖœOêî}Ô·›¬{, Ýlíº|mf[- V6éµ¶»¹(‘ó;OBÑ›J{n>óü³¤Á„MN5µ*[rV‹¸ºåfM1Ó¾^Q<7Ÿ'ø± býä™úªºÜÕåðæòûÏó¤üþëjýÅÃëÿÒQyT T6y2»þ9ëáº~›ù]Áüšˆl¼&⥞:û.‰p‘ÍgÃGôÕeø¦ï»$¢„NþõEÙ½Meý. só®yCÍ{wy¿ì߇ޔï’0Ÿ!ª~çÃÐÛ­%êú’g1*]¿(gTïš•‘è«©c«ÞÐüññV ÷}›†7¿Ôa¼˜¡-ŽCÅöÛ4Ä }ŠÄ±ÏšŠ]þVë;ÜÓ>ñqîÙF´¯)óƒ”ÛsÕÈÌoßѾ% ½ꆪêö¼Ú†Dÿéè#·çQnÛ²ÌïÔ>ãt—ù—2èý+]ç^ÃË.E,7¢1^=¼ç­ÒÉÎFÉì½.6¢Ñ_ûçϤ˗b«uÖÏž?²ú%käF4¿‘ÉîÞjÏ£Áä.¬ú›?ïý6Ñs,ÌúËåy8-ý6dö¶Ûy ©ÞÛ²ÚŠW©ÝæfUyh[éà£5äiÊo]•—‰¥¢/KÛ«o˜Ä AØÄo8¨ mõ­HUžß­èžÙyJjnõ=ô4ô…^EýRnEcaoëо¤áÛ÷<«wor«u³—"GEß¿äm±ÉE˜SƒõRu»Õ:¢µ1ÑrÕ¥›­#¶×½}˘,i˜xúŸ§A®.CtÕV¯Í½q‰¯ã»%nÊ«¾áΖáÛe ßÚ×| tôv½V›P0z!Íq¡É”Õq¡ÜÝÎɾJÁ0nãñÇüNÈ™%|™Þ ùM æìàׯ±EÄtK}Ȧª·¡àS6fU~Ú„B`µ´ÞogÂ!ÔÙPïôu'«m(DÖö2½qñ›b*}=VÍó&êVÁûuzA!%ÓãË¥ÝFãÇò—ÊŽuÐvAÁË¥x–ß2®³žÕ|ïÚ×m(»B´uv­óM(øË:äe¬C/›PÖWcšŠÎóùÞmA!¤\ÐíÌoRˆ¬âzù^Á_Wï:YÒµÓÞ¡j9ßÄúôv‘«5|'#ëƒÞuW”J[î6b}&lÙ‡.¾;(–ããIå2ÖXªìý{–Vc¹Ó÷[ ­†–Öo¤Âb5¦‰Ýe¬v5ù&J–î×ia³¶jÁØ÷M Ñ Kó/)dV÷¦tþúP°ª:^¾“`/(,ëcê›UC§ã7)øviýNâ»  5´EÐ÷òQ´ÛP×AŸï?Ú»O-"»>du›·¡!Ù7Ò¬…ñK³ã‰ß–V±ÒÝ/›—µõøA÷7)ˆe¹é2–›ªl >¥qÕî¼Í‚uQÀø‡û#}K/Åx“Ó¨qß)Ð,(Œi–Ùéñ·okܼ4÷qCñ²Üf ¥Ó»ö¼ÍRkéä¥Íî[—÷hZ­ŸúVk}H·ÕUÙVûûë}WÄË÷û % aoÎoÛûƒ% ‘ªËVL>º¿7îûék?ç'„¶Í¨vCû·i¬ M—±Ð4´›†¿,—]ÆrÙéu#%U÷ÛÙúN$k7£Aç¦wûíxé¹/£ç¾×v4BÓYæOeWeñ3ÙýŽ5\Ñóøà2xVÖ›­Ã·Ï.ßÉ\V4Ò®gÏç4ÂEör³—ñÕ«{iÌsaÛžßÕ®hk®zÙBvçù°mÏï¯|¬hv[èȉ/Õ7ʲ+‘}Ï¿Å+a‘++¯¾!WÂ&WÖZÔý!ƒ°É•½µp—]ßÚEæ¡FÔ¯´p²$AB6Ù²2–„OöºÊz#EâµÎ7Ú‹pþÞB6>)óÞ–ù6$¢¡}åö³&ñ^nF"^öºf—¡×µi¶!‘н®ÙFB›Ò½®íFŒòÉf×Í6ÃóÖ§…æ)š/5»ò4Ùç3>ôûUž>Íû9;@×Ïkè·„3uÍ‹~Ö=ïö]nCBDåF«ð)òE–Û†òц|­œÊ’év(YoC"¢»¡ê¶;¦•²| ÝoUm´Š”n…ÚŠÄðZYÿx¿Œ<ÿbÛOcö¾v6ú¥N¿ëÍhªG»(‹oíø²_ÞÚ¢ý&·!!æ$FßW6Í{¹ nC”76äKGÅ,‰ÀÖÞù‹¯õ€³$˜öìÇéwŸTwv¶‘D1ÍÙíF«`z³·"‘Ò]Óç»·[,‹Ä+ UÓ|­/›£ è®ì&ß„Âíèç8(EÛ~ÈkyØÛ¬!˜Gœçáà>k¿R¼å(„·–Gc•íx«ëbw'—ĺ—rö‰J6I¿K¹ A ²ß†‚oíËÕŸ§Ü+­bÝKÙ­áI;Ôóip¨/oåW>ä(„S—mžk1;¥Ó›£Ý‚þC/­:D+‹öð± …x­:|ʪöø¾ …„ê-®¿òî"ÿ2¦_:[›‹o—Ý]œÕÅ6$|ŠÄ©ÚjõdoÖ–ŸÛéf¹ÑvGtóýÅ9‰˜lbþFQpN"¡ê_êbfI¤óŒ‘Q™”÷§Â?WQ‡½ë•Ÿ«°cšÐ_†„þKµl–Ó‚UoD‚éÁº?Rþ¹Š<ìMXwWÓ–$"úsèó·B@oÆ®¿éþ^ ì=àï­›mÖÐã—nû½Øg×M(Paì.«^>6¡N/L3§ŸæX¤|9¼lB!ºÕýmN:|ê"ƒ{φЃK‰Ìí÷â}9ÇF|únŽ&ß„ÂX‰˜Ê×n#¾Æz¶@ùÐãi0ŸèÝÖ®høƒ­êËCÓî7j›+ÁLÿnÔgË—4Âe¢t¥—ëwipŸrw9Ì&{Ž?æ¾·4¸¢áû±«î>ßYÑ_†G“ªcsÙˆFHÈî7Bõ[du8÷§Ög™ŸžŸ·Úí;þÑ1œ†ë¹›Ã±óå‡ón#Éð˜Æq¼è´.šËUæòUnDC¥NŸêÂØçŽÄÙ\Åû‘}œËÏs~ÚJ‡[ig†ª…\?Þ/çúu+"¤¦Û›“íǽ†è[w¤ÜˆF"³x—¨ùŸY» ʡǚxk¢‹…sM—Õ®z¿lD#dÚ¨¿âmÅ×Û¨ÕY½ Átjo´ ŸéqÞˆD@wj—1ÊÒFßÓF-¾ÔFßÓF-îj£–Í6$¸6êö‚k£.7R=®z+Ö6êòëmÔâÎ6jy ‡6êüž6jqGµ|iÊmHøL§öF«°´Qç÷´Q‹ûÚ¨7"ÁµQçÛàÚ¨7Ú ®z£U¤ÖçòË-ÎÂ¥úÖâœßÓâ,@5Õ¾«¸6êï ÙF}ëq–_ëqÎmÔ³Níf–6êüž6jñå6jùÕ6jq_õF$¸6êŵQÛàÚ¨7"‘Ú›œåW›œÅ×Ú¨ûFí| \u± Ý‚œßÓ‚,îiA¾W³¿Ð‚ÜlBkA.6¡`iAÎïiA_iAÎïiA ÙÞ¾[Ü÷;·ïÖù6$Ý[›oDÂg:„ëmHXÚwó{ÚwÅ}í»å6$¸öÝŵïn´Ý •±}WÜѾÛÈû÷ö]¹ Kûn~Oû®¸¯}7߆×¾»Ñ*¸öݶ›kß-¿z8µïæ›PàÚw‹M(øëÆÔüžÆTqWcªÜ„טº ®1u.YSó{SÅWSó{SjLµö}ݹ_êûÊ7¢aéûÊïéû_ëûÊïéû÷õ}Ý{¨ð¥¾¯­öƒëû*7¢Aô}Õ_=)÷õ}Û뎩üžŽ)ñõŽ©ú«Ý3âÎŽ©b#þºÓ(¿§ÓH|½ÓHnÂ+‡N£r#>µŽok‡SE#7¢Ažªçí¾Ï ¬÷#ͪE¶cÖ·/\%Å’0Zþ¤.Õ;î §²æZVoçü œbIø³òf–M×¢Úˆ„öN¿ŸfIe›—‡Ã¡}}Þ†DHž%5Yq‰¡H;Îr &«r ‚<äÙj æU˜?ÿ˜¿ÓøË1k›Ó&‚Û7çÞÔVoUUïOûf.…#…ÃÙ<­Þ©DVÖ²øÊý¥…ˆöò½önGôÓvFõù÷ŸÅç/ת•ÏÛðgæÉt+óô\œËEíö÷ZžÄOoµ3ûqÙ`¿—7ίvãã¥jŸåF4|2 ¬ò¯Ððï ¿¤àþ—ÂÀêž0п+ ü’ ñ¿f÷„¾C¸Ò¾$¶>׿—”Ï¿' ܈‚O‡ßãÒZ'Ö!Ô—R#ÿžg# >~du~¯¸Âð£º'üðï ?ÚVÁ„ÕF«`Â{uâ áǽÐ~Žû^½ûŠãþ&§Ž[mÇþy0äUU–×öíZºòÐoNßU^Cw®âÚ¯_øšÀJÝŸ·_8 ­ßõ¡röúPýÅÀ€%ÁÕ‡šmHXëCåW–Wªï#ñ…úP¾ ®>´Í˜Àà{kp 2¹ ®ò± Ÿ©KÜ­×.u‰ú‹K‚«KlD‚«KÛàêwêÄWêÍ6$˜Àà^½ûRF_oDC0ÙöWÖqg¶-·!a϶ó/;Õ;³íbÖl[~Ý©úw9ÕêÎívwª_Úû²ímÖÀeÛßZƒS¶]nB˶·¡ÀeÛw+K¶Ù©Þ™m—Ûà²íf\¶}§N|%Û.¶!ÁeÛõ·H¸eÛùF4• 1Ûp¶½Ì翘m Û^Pøòb[$ÈU ¾¼+f Yñõ5ø_YCöõª‡•‚(|q _“%Í¥/®!øÊÌNq á×ôáŽ}¿&KõW×|U–äW×|U–ä××ðµ}Ð\úâÀ>ÜnQ À&/Üâô™WôÑ 2•Ó§¼$y½‹¬7Z…OÝaÑ4NKúô[BóPßr¿Ä‡Ü†ý{qïf[që^NÏ„a ‚ünÑíATŸy^ÁCß-–÷ ¬%L¶~·˜Ý¯vž¥ëÞò…ÂýKİà Êx˜ ·‹iHú©‹Z~‹Ä*†],÷mN-bX«Í¿´áâ.;[—ÛŒ)Ï·!á3¦|#ôƒÇ²Üh/BÆ[ÈûH¸{‹/ -ÚBù£mÖà3þ¨þìä×ü‘@þÈêñšM(ø´Ç+ë{ÅÕÝãmD‚ñxy± Ÿqª­"`œêòäîTó²Ü†„ ?@¯¿· 7§º J¦êSûwÀ6 ‹ÃË«/p*@mÖ5d_ZƒÇÚ/DÌJ„‰}pÙ·ìû‚Ã>È/P¸oŠïQ€É|î(Kâ;AæF$˜d¾Üˆ“Ì;†6âáÙ6˜dÞQ­Å7‚§f L2o„6÷²é+¡ÍF$˜dþ^ýJÜ‘oC‚‹;šo‘pŠ;¾É)§¸#wgÕqG!¿Gû»/­á.WÔߣ€ã޼t¦pgÜñzgÜ‘Ë/P¸oŠïQX„ìûc ý%äõpyv?žüš[ɧ~2l¯¾-ë]Þå³þ”Åtìëé¿Ë*Þ?v—/ô7b:‚¤s”[Òñ©ýùè„àûtÆ×²AE]À zúW)þóWö?ë×q¼<ïŸË Ћ[ÃØt;ŽíÇu/¿¾ßýµßé8 ÿh>>pHè€>˜=ìz6ùrÚÕÇë÷ч³g9²ñ[Å<¯à“õè£ ïoÌ94ïÅ}̱æ-O“O- wò—k»þù«%ÙøjIþ.Ù7ØóÓb’f“÷¯àëûóû÷ÿŠuïøj¹­qÕB¢iÖWôßGB¬/·ï_´¼÷} ßz¡z®ïl߈D°¾O½ß‹z+!õFsVçw’ àÅ+Ж#ù»(ˆõk(eÿJ± ýJÙ?†²ææõ§ÓwQ`ÞhÎÊM(Œo4k蟣í4âå`yÒì. ÌÍÛH+óFs¹ÍN§ë»»û‹u3æW(,íë@aÜéZÊ]¾ ±¼÷ÿ’•ý½ÿõ6kðí×þ7ªgUnB!X߬]ö7kOã–ÏŸ<-tZÝþ=[ÜݽָÇåÌ»(ÄÖë^[}[þkøÉ^È?luÓ¨;kómHÌ‚šÓø¨ñÛYZž`»„o¸ ù>£–·®—QŸ«ËûF4Èø¯‘_ ÎÄñ_bÛô+P_ŠbaŠ…Ä£XØŸbb7ZEH¿Uo´Šˆ~¨ÚˆDL?n´‰„ ÷7Ú‹” ÷7"1<Ñ´¾úú‹ñ¾øJ¼Ÿßï£~${4^oBÁg2Šm(0W_)ú_‰÷ó{â}â}Û+4Ù·¸ÄE²ù=‘¬¸+’-6¡ÀE²Í&ú˜l !ýÎÍ÷dié$Ö9Ks÷NÛ?z´'^å6$,ҔߓÁ`ë{h{¹ .3Úˆ—mÄ({nT~97bHÄti«¼Ûxüt«žuþºÙ†„ _ú-6Z…O¿W¼ ®€&·!ÁUÐêmHPBûÕC"f*\ù6$¦L·‰”)ÜiÌɺ„¥ô‘oCÂR—Èï©Kˆ/×%äWëÖ%ìµ|#«¾ZûàŠT»W²\cïéöàGkgâZ-W§ßEAyjó] ë›HæijSoDa £:ÅŸìb´¦lßÊ;)ü´f© m™w$êHˆ)ŸÎ£»Ø²ÌòmHøkyO¢Ýˆ„ò«Ÿ)ÿ³;Ï¡UQsÕžëçö¹­·!®Iä=‰/ToX™ Ëo2jyõÌ?Ã*Ùpúû¾ª·!!hë‘_ áûdµ€_’YÛ§µõøîÖ÷/-àFÍnïä’“}2&ðKöÉGöÉjËH0ö)ÛˆQŒ}ú’ñðï²O_2þ]ö雌âìSu}òï²O_(`£6\*B+7¡Àاï®Û§(&,¸“KŽñSù5ûÄ’ ¢@ù5ûÄ’ð™MnC"`‚›|!¢Ûˆ¬ÁMýEãa#±L¬!Z¹ .~úÊ*ä&˜üî»kÀùÝFÍþ’ñ€ñ“=DÛˆ„ M`¹ .~’Ûàâ§|\üTlC‚‹Ÿ¾Ç(?å_68~²5î9isl½–N­7 Û)ÛYÆd¯Ó»;)º=%‘÷$œÚbH-²¿ÿþíDötÉÔaa'²²Ê²]¾Ñ*ÈGÈ3éÔyC“À Í×ä Åãv‰-7¡Àô£Uù÷(xðs„/éŒÇm:QßIá :QæÛŒÚm´ Ÿ1­" 5{+ášD9HD´ñ(å·H,UÛjŸšmHÆ>¹YáfŸ¬ºöwõ¾¢ÛÅ6$8·Ñ*W6ß"ÁívÎô.‹mz—s¦wYÜÝ»loÉÍ·!á3ý²‘˜®ßH„t§iyç^¸ö²Ú»oÄ&½¬9ÓË*6éeÍ™^Vqo/«½Ót !Ó-+7¡Q¦öþCñí^ÖY·l¹ ®û°Ø„×|ØlB!`:MëM(„L·¬Ü„Bdoª‰vñÞ¤yû“$ÚŸÄݽIöÆ¡ï­bÙ8dÛmkÃØ¤á&gnÄ7n–ŽÎÞ#¾Ñp³òÖÍFÙÙ(ï݇¯´GÛô^g_!ñ¥ò~δGˆo´G¬÷ú»k Ëû9Ó€!îm°Ÿ4ßIÁá°¨dÎËÅ݇ÙvÛä®u¡krº°Mù&iú.,MQàlÓûàf›ê/ ìWsæèQlrô˜3Gb«£Ç’:z›=æÌÑ£¸÷èÑ~ŠSÜGá+¶InCBÐßÅ9ñ鮃¢œ9(wY¾l±žˆmÎ?rætBlrþ‘3',b“óœ9›œäÌ ‹¸ûüöե¼‚CµºdªÕb›juÎT«Å&ÕꜩV‹»«ÕÖhî£`Û‰Ååyꂵ÷ËËÇó\Pöë?ßþÊ~ï¡…s?Jðì×^µ‡‹Òº|ùõÿŸóðçñq¬·œÇO† ~e摲÷.,ïþÍiIï_üço.Uð‡WÙ¼¾žrøN>Õí£çÓQ_ ™5/ÅËñµ8ð¾‚ïø¨\·‚î¦PæåáÚ4ûrïLÖQ—Rfê«´gÙŸº9ºôAð¥õgùúê„Á_ëA~½ÇÓçké„a*É'³j'e·“”$/0„VY*_›òäÈÉhªMz3†B6Eóì†!¶bx~íôñÓ C2×H…Áhd]>Nì2­LbYºaè¥úºgü¨]¶ÚŒ·ª,ÛnMn(¬–5{}…–urµ)o0”oí[uÙ 'bb[•m•ååíùY–… Ÿ2޲|n\ÖYIÃÉ AH™×}™KS‰Öô}lšW`_.¿¬V<л Å±S‰òùÙÁTž3c”…m:{§mLçÆIIôAVgY+Qâeq&IO½$)¥º|^Ú÷*{?6NÄÍĺ9Ô²3t§Z6n|ûF¼æ'hœlÂt3-iz–nB+†¦[BQ¸aˆ(ãt"Ã…»<Ï8œk' vêÌ|gÞÜV1“¨sf$ê#/óZ>[•õ¤jí«TÔôZ¬\ô…Êz/˦³ 'Â÷Ý 0°S8—ù ¤°D 76MÝ6 zúÿÇ çðùë©ËÜôëê*xÊwÕ9¯Ú˵ùñÿúÿ¼ý¿ÿ¯4ñcìGãœÿùóë¯züÂ[Ysm÷õþúr°Œ×@JmÕûÂZR.ÇÃñ=ÿü,N'Ëxß4uÿQCýìªoüó¥}ßÙæ£ûîžþSŸx^ÚËÛûçççùÕ†?œÌÇô<]Þw//²¬÷§Ú2>ÒãUpÙÍǮ꣓õg)mãcËø÷Ýéõù\|ZÆ+Uú4.VíßI¯/»ã¹–²(-ãÓaþj¿Œëö+ÿühÛã~Ÿx~”$þ-»ú«v1–Wí—&tº-ãÅÉá×Fõϧöðƒ5ivm+÷™Ì,ãµ ýTë=¨(Õ<Ѳ«ª]ïä¿zý”öñ:îû4žÒtstÖùåòr>?Ÿ÷… À³d/ç¢97¥ @ "÷|D¢Ív×ÏO¹¯k€ÖÉߟ€‰Á.‡êx¹œÏoUe¦J¦u,ëý±o>_OV ¡¡ðkBáø±»\Ô[6€hJÁøòn>>»¸ÒNAïs'¦ŸVv@‡ëµ3tåg~²$€Nó;¶–¯V€T(¿´¦Mv:í.²(Î¥mJâqŒ‰&YRE³÷··.Ú/l¢-Æp\YFí1.uÇŸÃñp®m²$ÆÒÈñt8ŸÍ”Þê·Ýõ|z¶NÉS郖V­Çª3¿Å‡Ùiïÿzô‚4ð"ïæÁnãµö_§Ï÷¶ìx>õÎïüѾ\ß.å§m|<Žï6ÀXÇÓûù£:îU佟ký4ãgÕÅfÕ{yéÇ‹ÈSþêÔééŸâyÿ|ÐÊ–çYÖý«ÿ?~ÿGO— ñغ+tŽ­Ên¬ï=ø.cs5V¸Œm[5?~ÆVRMù±r²¶ ‹ßRˆ¸ªôâï!DcÛÖL8ð"Œ·m#‚ãU˜ÕƱúùJ36raZ£Æ&o¥Ö–›±±ƒ5ÏÂNМ+Äaè¸z0˜E?V‹{˜ºŒm3ʼnèÑil«Vy`leþ¨ùF]¼í$>jÂQøb®y"ÀâJ.£ø!Á“0F¢ v£mÇ Çž33,NâìÆ¶äÁó\öN³"eW׿fÂU?VUR3ŽfÜÛÖØÃ3îækX ~ð8å~°ðDH¯/î4ï‘Nƒºì;é¿‚9ËéœÃ¬P«7[Žœ¤¨Ò&6Žáõ³))0-rbd»Á¾p᳚sòè  Jis˜¸ÈÆ0g5Øw± çÜ!6<Ï7EI:Ùˆ\ø\›ÁâÑÁ˜i.¬ë&­¹ÂÁjÆÆõ©Á«VfÎZºÁÐT µÞACwãF78pP+m ’ÄqS†Á®§ßîäA¸ˆ¨™s§)Xú¸L ðœaTƒc—Mé '‡¢¶;õàœ•™9«Á‘ƒaÔ›’ ’tÆÜH]êcnŒR—Bµ2 k¦¸ÙgÃLCN¨npàd¾ô`lŸ•n©K#75 ŒÐv÷›¢##'±ŸœàM1î8Mb)µDe ÒÔƒ<§)Ĭ×W ˜±·X—â¶Cèå=>ºtkxç=zHî´­3Š¥FóvFN<²Í{,9‰´ÕèÀw ÁÌLrÉI°­FÞÂ8-ï1x1ٌƨѾï J=:DóžøZï1zðcŸo8c}c5Zü® néVªÞï| ePùŒa&) )4ÿ¦ü¼[9q2j´ïbÌÎ{NjÙïN7YÖ¶çíyx•í¨—j´‹TõóتiKlfÒéNâZ”ýhü!R£ÃG—PËÌ;p)Œóœ,„ j=/D«ì#—º BDí}«·¬O?ºÓâÐÅOšÑÈÉI¦¦F‡ …¸úž—8Ø“n•ÆÚ{©‡ž‚ì‰Õ.òÝöš&<8²Ãè”·ß·ú•í‡.vÐÌ[8X¶QÎç•…è¥JÕaö &(P£¡w½ùb5ïeŸNx"àçÝùK“™£yÊIR¯GÇ.–ÍìNèæIªa4 2«›î¨Ñ©‹î4ýè pIÌèÏ[¥fçcÝ9=·Þ÷Þ²u£ýG—اFóöd’;©ÑÁ£‹GGþ²—ªÉ`{+,«Ñ~Œ—ª—“ËÉÄB¤PNn 5Y{-TfÞþ#ð®Cbku<ùc6uVã¹hñ8:vÈ2Ìîøe b¶ÛèÔÅVÕýè v‰Ù̼}§½ì½T7Út‰!´Äú¬«è  ßËðDNR\5¬²ͼC”jÿ7ÈIÈïüÕ¿£F l¿‡½ ädÔK?ÂrÒV## '½6ôóƌɋÇѰÊ9Fx>°šCfì :½0cr5Úwñ—ÃèðÑÅV&`çå¤B¥F¾K1Rä‹'U]5:tÐa&¾OF Ph²£^ÓßAwÆ86‘i¯;¿ý‡úá´É dMüm¤*p8Éj‡ª£÷räIg5… –MNø¸IìÓªrƒ6„HNtÑgAåûV¥W£#'ëc8ØY6‡œ»÷;AâäÓž$8'ëéjtè»T·Œœ¤¼œôqÕ UeK],[ÑB—PÏ;|„{© ›Ñùž šHÉÈ €øû–_v£ÙyëÛÿF«Ù]ŽŒ……C=vÔ†Ð!z¼Ù“ÐG‡©û˜½ }§az´CM£Q%þV¯êFóq•œæ®ÝèÈ!Z¤ Æš}Œ<Œv‰zûh&Œ1î[}°íGØV »£Ø§¯Tšy'p/«[9DY´œžÁt££ïü0ïãÎnz™ò{©­æ˜_FAêâ¹õ¼#倕A>Žv²ƒÃè q©øé݉„‹œ '{ÝhÖžèâÆ³Œ[|ÒŽ=‡ú‰ÙËÈÇ•³Û©J7š‰j'ºyÀnt˜8DFNºÑQìW‚å¹oÕ-5:tˆíûø™Œñ·á °>£lúÑAèR½5<‰a¤dâªq´KDm¬}äb«Æ T7:H¡çuƃ}žfx’¸Äöƒß‰Rg’¢UNëlÝèÀÉÚëyÇ|WÎ&óöe“Ójy7: ]ÎÌ*§ˆzXe€}Ã-šQ£¡ý#Ó$|¢°^¾»ÑqâR‡0óŽÜ,D;Æ;ËIºÑaŒ2Ñv£#—l´pGµ°ƒ‰ƒo¸ñ$<‘ÓÓ|5W[¿“¤ f3ñà°—)´>ÕdÞ)èYÓ3ÝntˆOÜG[•"¿3='éF£èQ'f&)¶±ÕØ«G»ÄU†'©C>«Ít£C§L ïGÇ.1›áIê;¬r´šjt€ãª~wRßÅú 6¶=ºD½Ã¼c\å$¶.±¦á`€<`;9ûOÑY†œöät£ýå`!ÒÆU“ÓåntâÍ »Ã:DuË]S«*è­VÐŽ]ü|>Œö\*9å0:vñÅ7žV}ë.}ZôèÉàPmQ£]¬á‰GzÙóËIÝ^†QA;DâÑGÙø´~&>ê¬ëcäzOßzMS£Q\u;cÔ£S—h¦ìGè ½É`ýå­/C|’:žÏ«Ñ±K<ØË ЇSC3X{45êvâØÑ»ªÑ‘N Û› F.2X £cûLN'ÔèêΪѩ‡cŸA‹~çLj£éGG¶±S<ï±gAŽ>¥¤ª³±)Ö~•žÛYt¿;²šrÒ­¢F‡p&Ãù¥X‹‡y `!úÈ´Ÿ·ƒõ™ÌØ“1¢®ûÑ<í­O7:Ž]*"Z/½WâGïªFG¡KdjV"Ü}ÕbÂbˆzõ蟾 R¿õ³©Ñ‰p¨Ä÷2#ÏÝÞ:JÔh0“É)­ |4ìe⟌›òýƒcÄQô£Ñ¹ë­—_pý{‚;vÉFË~tâ;X£;âñ!u‰5 O„çÀ“ÑVu£#á’Ïë½{À±J¤F㎩!'¢³ä÷8ïntââ‹Ü Ϊa&!æI6Úkë&À31„€]d“I=:u©,h©±‹­êkjtô}ñ`íÕh[ûawb~/Çxp˜·‹6 üŽAÎ-'Ý*jt¸ä®†'NödˆðDêd‡Uv::duý¼S0o99Óþ£C†>ÚßÁBLp;Dã9·ð¿Ê±’cFûÀÆÊiôèƒjKïç{Oâ(ûŸœª?ÑúyÕÃh)ùŽˆCNN;…#žLêjt:ăՀ;M`6ØX?yHbl¿{ á§XçÇ « *9“SZ=Úsð;ý*S°Ê¼½s‹à‘Çmú‘ùîF'.ñ‰ÑùÀCÙQýèÈÅB˜Uv£S½lÇ™xVú^ÁOEwŽa7:‰]+³LXb/«Ñ©p)D4ÃèÀŽÜ]œ¸$jy?:……¶¡Ø+”ÐËÉa††Øñôê îÆK\+³; ŸÐ÷Õ0“”/·Œ)ºæwøˆÂÞÉa†=¬ô·½ Ô¸Pô¼CÞŽÈÔèØ).úÑiâ’Lé¨ôÙ-| ÜԪѰ}”ï0ĺ36å¨ÑÞ#Vãq™‘ÃTF! €÷ŠÙÛäœwc5x‡0v0(Ù¤PW/z¸1°0í˜òè’òèᑆ÷¿÷‘ï°ù£ Ô¥x©K£ÀäQ =—‚†˜OµxÐóQ…ºEï1ü`Ó —œF}ê†7/Â&×ì‘ÿèñ9“AÞ›EÿÑ…/cIÒW—¥¡[ÇnÕ:_ÝQæ —@Dß®®óR7gæ®Ä+†¶®g»ï© UC0ØÕMX>–aîê*,/uq0fx·Tá¹^ÍH!à¦ÞL€ïwl>ßa¸šK‚=©Q%ßïØ.RUÒØ»$óñ¶Råf§­¿?ÿšáê呼˞ʶÍwy™÷Ïüü›˜½<©úÿéOüþ5"¸ »¼- a&< Pï ß—Çãð؃ÀŸ¬x?¬øx-ŽÃuØA üþýôTìŸŸê †üÒ¹ž¼Ü•UY W1ÂÁ¯AÇÄA><ßÊ ˆÙ#0oÀ(ÔY¾“ÝÿÁ<ˆõ ~™]WøôBÒ||œõ§qA²”ƒlÜÆ]Ór ïutƒJB¼ÔDàÛDY×XQ¾!l3hõ£œ$Þ„Öm¬J°7‘U³Hâ AlÛÃNo«(÷3 Eù† 唩m0¼GF›ŠÒa žÇjCå Ì‚UH þCv14N²à¶Utâtz‚!d-£ƒNzc$kb'³Ð@À,äa$6 1kJlbÖ,äØ,ĬY¨±YˆY³ ±YˆY³Pc³;™<Þ,ÔS@fÁ0 8³PºÈeJlb7³€Åi0 ¿ŸlZÝdÔn+³ðgjWôQ“Ü5R6Á`žæfAõ”‡Ãk˜OF%ú­ìæo&Pa·¨QíC/Ñ ”ÁÜ,h¥T¢0(eV´m}ÜÕm D£F 3б; ;ƒ¹Y ”²ÈŒ á4JÝᇤœB5z³ð´P‡Ž è!S‡ÌE˜«³“)£­‹:¤Œ:´.ê2깨CʨCæ¢)§s€ê2깨Cê mƒðê@Æ[7¼:8 °«C梩“:¸³°F\ê».6â ¹ä2âÒ…o.â 繤”iî½lç_wuAËR8Ï%;Y4Ò¬rTÒÜÅÞ$·mQ@5âÒ<à"®pžKvð¿Æ&ê”KˆaÔ/è!·š‚R‡AX^ÛR_Dƒ$Œ$釂”3h9‚ 3$°«7D˜!]½! ÂŒØÕ"Ì(]½! ÂŒØÕ"Ì(]½!a†„@˜Q@ ÌÀ¨0£vu‚„  f#|6Ì(±:øl˜QbuðÙ0CbuðÙ0CbuðÙ0#Çêà³a†Äêà;…x ÌÀ<a†ƒ a†Äêà»…s£4÷;™õù’æyÔ½3Ô n+%D@…•Žs8'?ºÿ33TòÒ–nCñ ¨0£BÒ<‹º;®«*EÛ-¡†Ø0C]K‹X.`˜‘:„ê2>„ %ŠqN¢Åغ¡jÍŒYŒæg`²ß…ƒ~Ž]‹²¥¼ )ZœÝ¬ZÖëB§Ô»7IÊA´8³n£léL>šŸÙwÁ¼rDV礂~´ 1³ Ú…x¦Îƒsê-»Ê²º¦-{´,5¯*:9ã‚þhQS²ï1G‹š’}˜ ?š×”&»Ðù&m‘”YÌsÒ"©gŒùÔ­ Ó˜Ôm„ ƒ– RÐÑ¿ÐõÑž> ÖwÏÂùöÜU‚Ü5^ÄX+” wç1ÖÚ©H»Æók»J»ÆókíT$È]ãyŒµÎ]%È]ãEŒEæ®9D@ä®È©Äó‹Î]ˆ µ6VÀ"ˆ~$ƒ¤ An¬‚ÔÂ"È UZX¹!° R ‹ 7VAja䆀¤ ÏÀ.HY)p¤ocj s«„¹±z1‚$æÞP‚ÂÜk˜›Á0÷†€$æÞðan…gÀ‡¹Þ{‡Në`‘B—0·Í!» e5$¾,[bAâ˲ RÄæK%$¾,+± ENù^È—ð ˆ|©Ä‚9åKÁRtŒØ—øÑóQXñ‚4ï\D‰&c»d’a"îÔWª4A@¦|Yqi J“îçÿ^¶iÎ& ßÝÈJ/ìáE ‹D½,Áy ‹Â+” ¼¸! ‹„7„W(AxqC@„%/n@x™H„5Pæ^`áE¼B¢.Äg x…J€W¸!  ¼Â %HÀ+Ü€ð3„x Dx!± 9UÑxRå—N—Y‹#‹¨3÷Á â¬Tñôkæ\O‚*Þ QÅ«A¨âÕ ŠwCªxx ŠWC‘ý{¥ œ_JG¶«~Ou ç—Òù‘­®â™]è«x…)`eooYUKàÜJº8²%v.…¦‹#[bèbl:?²]õN‡Z¨ >Ø…–5ê鲊µª¥Vp|° k“ÓÅI!QKíf°µTúd#W±Öm‡]ÙŠvÙB‹²» AE;gî–æ êBèTÑÆ<m¼„ˆ@p1‘6àçráeÒ›ûKs²él²á;`¼¹·YÛ‡ÙoQ(&íƒÃ*"6x«yàë¬0ž`ħ Ÿ`ð‰ A<ÁXãð.å#À v/¯çÍ‹­„}`º”fE| œaû1öÁt#û1ö¡ÇìC„샾¨„Ñn/F|`K¶ ÂV56͈1k'•×㪾 Ògœv§@7ùÄh‚ÁÚ¶Öiv‹íd t“O&(ß]aÝL|wÆIÔ¬äEÇQÌ|¶`£ï>Ëdã(‰÷Âdã¨<ƒvÒd÷¢DqÔ ˆ£æñÇ!œT?¢8 ÙñÈØu¤íú|6³“2ƒöaV?£ /$'¨†ë{IX!–öau#òÝ‚·+“Âbf5´ùnád˜n÷ †ˆ/¿0|ð=°ÀVß0Ømuó¬r/€­¾aˆN÷bÀÀÛêÌZIÎÁ¨¶Î—Þ6Ók™ð‘ìLô|ÉÁÞHÏ‘ìnô|—H®bš=Ÿäty›·Ô>Œäº€Z¹,‡9PmUñ–ÚwŠä˜o <Ÿ·ú[– ȃï±Y–D–Úç­ƒÁÀZjßbfYVŽ,µïd˜1&ëÐrY–ÿ€’¬.»¶%F è³Ã–Ëoü‡•Rh‘fP¨{ÍøÄÈ>õ7Ò\ €<ouÃ@d5òV7 ¤<ouÃ@E³–ÇÀ)³p˜ÍÒ=àÊÙd#‘¯˜8ºî£GѬOCÙ®ÂÀûŠÙ9$ÕsZÁÂF­ {TŸ|`«£°×k‚!à; >x8ˆã{&@üBZúT`Z‰â—Àâ·gñ‹DñKü¶ÁÀÉdàà·õuœRþc+•pYÿò²ŒuE®ñËâ¶ [üÒa¸Òwy‹ë2¨ŠÝíÒaàOôô•–€Â6*C|àuÓ`àùusx¹‘Æ"½àmT`9¹˜Ù¨Ù¨Àrr1³Q%²QÁ¢ÃÝrJ]ñ'YáÃÏåQÖâœZçX»Œ<§ž¢XG´ùí6ÐÏ}¿àJþí¿-Îoß«Ètç€Ârçí:Íêôê€B¿»ItñÜá|:]ŒP4ٮɚÎÎÔ("âéדF¡ä*7(dÓt\uA¡šòô®vì<úƒÿ÷f׉g÷ϫ˦&l¾×2;â¥àóï…{9Í÷ôÍ<¬y{Ùâ|/„öò¢ü–Û„Q¾?¨GBÚËüömd-1ŸìEiÙ<¥ÃãU0Í( ‚Ž9NŠI‰„ËóÉU%YÜ<ŸÌÆãùH$\| Böq»)°Á{ªZz t=À¶¾®6"àfÀtÝvBôÕ5šAˆ#c¦gµCš%:£øHÈ|ñÊÊcÄGB=N#§H¨eê݈„ô“¬¥øHÈ´û!>„ —DBŒ„Žú)ªŒ‘6[ëÏìy‘„ÙšÎÙ9ø Ç ÏÁw² $†؆Ù†ØÅ60mÈêé]ÔËÍ×õF‚¯vK¨ä”(ú‰-•œ¹N è'æ+9æ2V'b\ÉÑO»TÌ*àzh'"+ÍÍ@ðõMØI³ø }•¯âNšÅí¶Z°ÒËOÚ)+qÒ#>@‰ŒùxYéØÒý¹8‡Ê DÆÐJ·Ì”êI)¹«¯HAÉ=v©©™÷AéU¤È:@™LùîÏ ïEÊ{LÉÆ‹Ï×oÅd¶rçÇ*î{á;yLCºy€Ç¼aà½-Õ ªwKä-¾Þm®—c½E‚êÝ%ò‰K$Yq}“ ê†5Ö„ìlu…ù‚š¨±&8’Þø¥1¤|‡j¬ o2\cMxûák‚íÃð (‰ï¤Ñ¯\±v2±tÒÌÏLȳòl|i‹·“Éü¬œ¬±Òñ¬ú’'âÊ/&ßæŠHÖëðL Sc °×Xõ;3lu‚Â^c^š¡k¬|•63óëé8ÖX󜭱NPÄl’B¦éC€ºíùÐ8…IŠ~ø·e64ÞΔP.{›…f#ux`¾QÓ-Õ®Ü; X5Óæ·kOòU: èûÏÓøýF~»±s](À#ÃÌeysuç3p~)(oê[fX£Ÿ‚ò¦ÁÀý–7û„›Ÿ¨”(aKÉÏÔú  D [Ê'*=Îè§8QÞ'1øˆ|P˜ZÚÌçA!JØRK›ùâà$lé¼Íœ>pf$ÊM(Jù À4ý`ƒ€¯0ÐõnÎ_üŒ°©l«}‰1pÉWXKWÉÒ/Kï2`²¤“FÎgx¬ÛRÇ‚pÈo™£¹PÈÇñwsà ø |=ò±s9왜)´2AáJNQAa‚Â) "(¬AP8E‚B—…ÐAaÉ…S1}ZÌ]F¬Qøè µjvôÙý…Åìç·{ÒÈóâ) Ÿ|ýŽ ;)¼gŒ}uD ìÁi :c;¼êLŸÝ—m'Zîj ÅÈïfV±»;Ù*n>6Œ­š``mç ±U½óRldâü) *ÎW¯H0qþEÿ ÄŸ?Ã+xyŸñtÖ®Û” ËC·ÇÏ[å-mÕ“š…±U†‹64mÃtBLQDÌŽ0m)EDx•ú»†ïá-K r̼43”`ʬ«jç€"Xßç—OÞL*P„DÂ'áñ; RÅúûÜUý•O½Äòû\²þê€! ªe⃪é XŸ`T½-C|˜M@Ö_kŒëÑaú¥”H…X»8£{ÃÀ~:aPls™„a‚A_•òa€X”˜¨£ü" ßÛd› :.’‰ö‰CÓuÆÏ`ÒÙ&Œ°½U?†@Ê£0¸ÜrÈCbùò)Ð:áwf6e²ÅAÀ…5hq0AaÔ!|0Aa 2LPÐA€Š [—…Dä—„¼vúnÚIÖên¸0g'}ö"H&¸À°ÁÉÄâUÞ§ñó±üöKç<Pä¥y¼¥òñE¤wãœX~ ¸êlÍ6[ÉÅùþ:i[ßöÆÏÀ{tÉ+‰1¢<„GßÍ^·Öözý ˜C€çÀyYh[úÎ÷5ˆÕ—ëTGd101 ›¦ø|ѳ7\ ã/‹žKyÈ‘ïìV‘¸øÎLb |,Çò!À®ð!Àþ› „Æç·‡ë¸ÚT`óßý·Âùíñ<ÎV6ÿÝßÛß^¿ãüw°ôßÿÌSÆñý»Úe!y™"oî7sÏí ÈZ¶ÄÀbc ¾M™¢ >N)ÁÇ)Sàë”’Cáá…péÖõ”9²—SŒÍ|U!cëxŒÃ€òN¥¢\Á1XæëãU†N‚͸ÏpǬ¯ægàÇÐ š7‚:z…3ÀÅgÇ4å·P:ÅÌôQÂ8&t‰!Zæk'.cËÍwpþ›iÕ™` óo ‘›NÐ&.ZêÄ“ånNÎ:EnÉX§Õ×)ë®DP ‰–G·D%„öyÑòèÖr·V vÂK]¤¡-0pBÊSüðS¶4'Q%d‚‚8‘¨2AA‡Ô¨2AA‡”¨2AŽC y##¯ËçC©`¬†ùj"o!b§Ì—é`àB¦ÅD1’=ê?aãÂxu(4Ç{gk—Yp!ÓW¨Qxx!\@¯¹óË äüb—€°eúL&¨‡ïQP»™;æP(ÆæÎDp»bkÇ%¯1> ©ØO,DÒÙŸÍ Kdr'(ˆâs‰LîQ|Αɠ ŠÏ™Ü P|nPDL« ב€þ¥þng®œØJ¿“V—ñrçZ: `Œ ÷ݯFáá…pIW²26T…ˆ›Eˆå›S²e~9ŠrS'/Ê$éCâÔPÎ ø¹¼xik@CùY†ò) ¢¡¼ åSá~PD‘:Eü܉] "~s«0ç~: ÂéøµÆø2WÅíÕÀ+XDŠ¢x‹HÝ¢îX!EW-Á[XÄêk K75HâR§¨†éèž`äËÐ-íÄåx¤uÀ ø~ln7Rli8ƒ{à ȫ7„çTÚh0Áw’Q"å?2‘U~;ùdÔkŠ‚è$“ “lŠ‚è$«A'ÙÑI&A'ÙEH>oËZmÿÑÍjW܆ÀXB—ý2n?<зª4ƒ ÍüGš™/’›Ük1éÓwh§V aB3ÿqm1ޏÖJmHê”–ƒàÒ8NÄXI×á;t"WìU¾×iGü°ö«aÏé…ÝRT%²VKÑžÓ)Š‹u+žüE`º(ŒØ)؛͋M€bÙ;3oáÕ‘Q'á(þ»‰šCñˆNy‹åÙâþÙw9ønbŠÂ'Lù÷œf¦¸<Á@ÕŒ@Ðî{ 0ú¨ÀÚ¹Ýà«æ^ ÜÌÅÃùíâavC\P›±(¼ÎòNPª«šÚÕ†$N'/5Æ@Ê"7è¹¹ÁŠ ì[îFmÍJÛ . ðœj5Üç0 EŠ 7 §€€CŒ}1˜ƒK@@Ÿ(ú¢³—!? ÐQ4Eaï(R)[­™¢°vµ°£hŠÂÚQ”ÁŽ¢) . à¢]2±þùlÄNŸagÿ„7b§Ï7ÓV ‹LŒjdRU¬ea&øfv1–n0'£Í¶ß±’ÿΫD*6AA4íÕHÅ&(ˆ¦=‰Tl‚‚hÚ+‘ŠMP°17]Õ(øc$taÉõ ¨/OQØëËýƒÔt}yŠ‚»Ùšóbè{Žþ6À æM„üö&B“; `O‹™DÊgB´ÉB˜RÞ_Ol9Mõ±h¡Y<:5r쌱¹àl–ïb³ØZEÀ„Ã{@É[X0û(ú±`,ý˜…LQ‡85ʧ\Œ9ùž`àË·lãw†ËLã÷øÕPôÀMÑ9‡¬P„x!œtOPêN:.Eû–9ë`ßUpœH±†q¶&ÀáQÅ^ôä«[èQŠÊD9°DåÀ ¢˜£ràQ,Q9p‚"äJ`ô§2…@µî²SðOM X¸(R9:ýM ºíùŠÉêE2?æ’`á“pêf Mw„¡iDça„¡~#ˆu„ÑÒ®¢ÍE›ÑÊÞŠå<üæPD'·¦Â;¼ WK¬x3N(r9ÅçPä$ÞÜíQ…‡E‹ó‘C!¬b/œðUç.YH”NP e§D¨DÙéQ’(; ` @LM/f<êpÉ+°ñÊ£.ºŸà×ÔSÖÀ¹…_SOQìéícTøÀ§cñªð±º3ŽÅ«ÂÇÓò°ŽÅ‹ÂÕjÉxÔU-LÇ ’ „ÀÇn¶“‹qb©÷ á¬V옩g,;ùC\¿Ý¸ÓôÔ 2ømô¨qr;’`Î9³Ø!Lj¹gü#H¤ô1BÔ(4Haýý; ô–"8ôLžŽoJñ ññB¸ªs s‘U R[.2k ªQÅ uÊE¸VE…‹ñB8ùN—ÇÐäç,ÜŽ€ïr$øœÅ_u°’+·©ø$ó"p(ÒásðBÆrMQعTo5ãLQP18䚢à¹ÈœH¡€Žˆ?嚢à˵¤tÞÃOŸwDDSDÔ)ÑŽLP;R‚¨sŠ‚:I ®Pð i™g,øõ.ˆ:§(ˆž¬DSlÆN(E„ª­-äè»nyŠÂç¿TbÙ"óËz³) Ê›e qŠ/Èð9@ ˜-ü¾3X7`.òø}g°lÀ¤O$ØñAØYáñÙ‰ÄSàD‚Û/Á á,ø_´ÜBÀUâèsÙÀsŠr¸Û¢Ï%ÊÁ¼p‰rèŠFb«…x:uˆq:â ìGÐ,„SŠÉòÂÞI1Ï1¾`̯߹eðD|D[ªjMQPÇÁ(â› à{.ZŽàDõ\LQPô\LQð=´+òÃ7Y'Z¾‹á˸î(B`ÑâLŽï fûÌYï[¶9·¬|õ’ ›€ÏBQÐ8 8w©™B! +â={`+aÏ{ P¬,Jؤ7£s³ÀŧòÞ,pñ©wíA¯x3¢Åù‘Àá°ÉtŠ‘ì ™L`¸X­eÃãV´Õ 2Ó)Ö0(@Ë›DV+\vÂ'ýäŽD¨b>âåìEd+ÌïíC‰U´H2é|„z¦Š‰YoV¢|$rRvîû<…‚¿Ó,„S³ÈA.Lã;‹ËšEìT #}jÜ9˜®MPº…kT9…küÁ[Æ-D¤ü 8x b ©ݘÝÞóÎ- ÿA°X‚nœ3KhrÛK»KáúñÈË8ƒ¶Á"+‚J=æÒmEÄ вÂÛ˜Xy n Sª¾ 3¨ZY@!¹„ÎGå3ˆˆg[>âº!ˆGAP:Ù B§ ê¢kgÞ=îÔrÀÅ7\eÀzMÿJíA£þ%œßMD@%ð/7DÐXÿrC@%ð/7DÐXÿrC‚F Ä ÿrC‚F<4â] ‚F üË4–À¿L0€ Ñ4ÖÀ¿L0€ Ñ“DÐXb¥Nœ‚Æ" ‚F‰•:aƒF‰•:aƒF‰•:aƒF‰•:q Kˆ fxÀ+uâ4†π K¬Ô 4J¬Ô‰[Ðè° "ẖR'nA£†pÙ4“ÝÞÖå•:àƒFÕBZ²ÑF0 ÿ¬‹žE[æ-ž4V:ìå,[@^Ãp_öme„Ö%((Ú¢tXBD¾ýu[é0ƒØ*Ý`ÐðAce1p[‡PA£¾âÅù{™²ß}ãLfÞuRM%)‰óç2íð\¬1ÂûDyJU¬£4 sõªØYÆÝ›ÌrÒ; [º,4ÂGVÿn.ñ`ù¿ÈçØ{–þ Ú». %Húü#šçë‡jôíìÌòGKq®³Ê\î-òGû&XßS\"ˆÖ ÚéûÇ›œB?,Z Vùgã1ùç/† ¤ £¡ÏFxûi¦y•…©BÄó××E‚*D<üwÂKP…¸! ŠUˆ¢ !A↠$—ÀV!n"ò9ì HAÄV!C¹! ŠUˆP…À3Ê¢7Äoq.E±…±ÅSœË}laA,žW!–¢ØÂ‚X<¯B,E±…±xY…°,‰b̈b bñ¢ ±Å.@„¢3¢ØÂ‚X<¯B¢˜á%Lb›i˜m.œg|k¼È×¢Âìxž;“a¶JA˜Ïsçe˜Á0;^æÎD˜í°„ˆ|CŽ ³ãEîük}ÔE1áE„Ùñ›;[×’Î;GWê¨yÀy†tÑ9JìB–áD6ÇпÍÅëBÀWu+¸ _Õ­à.`ZÖª¦Ë$Ö»±F1]ðUÝ,Ã3 jë»±» Am=WE Lm=}X «us(ë"Ûí Œj ¶Ã°ø,`á!û×Èh;Á h œ`ð‰ÞSàd'ì^¶*—`àݬ ¬¶%ƒçv CÌ—ÜM0c]&ì<º›`ˆ\`_&xÓ:p’8½+Áéç=¶¤Q‚ã»âü®çw7>Ñæ…TÛ[~R¹TÌ©¶·ü¦Ò†Umo3<­>|âÅɳ 3ÕΑj{NQCKwçL0Dħ¡ „VB.†îŸ’•Á``· ŸøŒ DÑ ñ1£'ø8Ú…VÕÎú;lYÕÕÎÌ}©<BP®„ª.U{Ro5Ý ` Z[p½! » øŠë oMgÌ-ìÀ:%¼³«°F$¼³«°F$@#øŒf‚Ô>¥™`àsšÖaDà!ö"e÷¢DÇâuwxx‹"—‡l±§HÙÀ#ϰuJ>Dö£”¼‚ª¢À©vÊZ'™AÕN¹Ós…=çì„%ŽÕ{jäì„%Ž]càT[¬âØ_«ï xg',qì¬ZQ"g'œâXë·+ DÕæ‚Wíáæc~/R¾bQá½HÁ^3+,ª½Ø `f…›jg™ÄììôüŸóÚ°%ð†À®Ú°'ð†€ <ôµù²nhÒ«Ê>ÜNŽ¨Ø©ªxë4" ni‘È:ù–ÀcHçÈ:ù–ÀcÓ%²N> <$²N¾SàÑÒwsL0DTª_È.˜UÌ_,Ÿ|¼aîe×õ«ª}¹b CŠúgHQóËØmþRß1ßöηî÷nÑ*"¸Š.‚»¾` ÂN×ÈÎûËsãUVA©ÂUPª…¤Øy~tl“j`çýÅÙ1N;ðêüF!œB8ý¯Ü)Ÿ©ðv>eìüðV.»„åû„k_… ½÷È-6õL0'ü¶R+Áž`—à{‚AؾDN?N_"§§/‘ÓÖN^0©€Ó–“Õ}/'¹Ì,@5ƒka>¥’ZBÊ,¡z”_RÉ -WÉ©dðàyH’x• æÝk•,‘J³vˆßOŸþ»ýáx9çÚÝ»òåúyz-È“»Åñ¿åç_âœ+Ô(^vÕ5ÿ¤÷rñ@ü Åå¬ÏîŠKuÝžjz!ÔBö‡ý©sØZ$›z÷–í—¼p@¡Oï~}>©HôxÈÎúó½Ùå/ùî%uáEhØiPœú…t(®í©ÉÞ*æ,õ·^Èá”›Èá­¨‹]óöš]\ÏP¨MíQ|4ÕëÇÅ…‰9 Õ'º‡ìÔmi¦QÖ8dç¶êìè‚Þ«é«lX›²¹Z†sµÍÕZœ«…‹\m•1#›"›C©·yŽ¥B‡36 ‰–Oq-âsbÐî²ë‡Š>:ÿó4ô…(ê]ýùr9: èo]øõgèË4©’ù©Û}—ñÓ€âÒÏ¢Cñv©²“о¹ó÷ßÅ8‹òzy£ 1ÄDG@óO”-)t4ÿFÙVdAÙâ#åU%¦FG@›dôïíqÚˆ¦DG@ÑC ¾³áy·‘!T 6<¿aT·žƒÏÍ6¹N0²9‘¯‚¬žÆXÔ•.\dù4ÆíÉ”Ì<™¢¯Ñ;ÉwÚÄÄó˜¨ÓLù·¿‘¤9@](RîvEé€bnÎæí—þzËêÅ…sû ÷£¿£óõX½¼ä(tLôK}ʰ?vâÐ2PË\¾½å­ ŠxDñ|<ÎçMe!¯§CM· Ä‹˜èŸ_: Ù Éš²j.×ìô,P¤ ùeDQU§ÏÆE´LLôëï?ŽÓi0UM»{o^vy沫}Lô¤ú@:Ùù<àxnÊç÷ÌIÄuLôüeÖ¢ÚõT‰«[Ëû.«Ž¯Nkñ8ú†¹²jwo—¬p¡DôóŸ_*ÚÝŸŽ ¾cªêNÚµWyysѵÕm-ƒõF±YÌö ô/ÓsÖ;)µD±YüÀ6ƒ˜>/dµ<ÆjõU «å-­V‘ñ…ê‡-_ÞßPØk¸$fƒ÷ƒÄl0Ðâ~˜ú7Ù%°åº7„Ä|¹.Ã!ñª\7«£«¯A=æëèF Ø:zl©£Ïûþ*ÌI4Iƒ:ÿPÆqÃ@HtQ âd ÄÉ€¬$ЬbYIYÅ‹Èj¥92³ ßêeèæÔ"aͬ¹kÕŠ„¯\ââk²´N«{yAñ5AÖ _“µuZdñZÂ2‹Z}ïÖ³ø -‚uãmŒeH< o’å‹=«R>² ɬSþ÷?ª°´Û/'S0,‹ö£ø(I>¯á¥ó‡Úo(ú(_¡ÈÞÚsóüì€Â„r¿ÿ—\W ŠÃûÇsÞ|: °Ö_»hÕ_'(²•`ÒåsñK‡ƒó®tñ\ü2ïÊpÞ5AaÍ»2œwMPXó® ç]Ö¼+Ãyןwe.(ø¼‹nk˜ °æ]λ&(¬yW…ó®©h=²9S岫}ÞEånn8„-gªpÎ4ÅáÛr· çnSÖ¼+Ãy×GHF*ð5§Î¶»êò*Åê×Úß®~ÿ‰üŸÛ'òùpÕe`•(ú¯ìÇ:jÞ'peÛ…&Çkã€Â¨ü?òï´škfq9¶Õ§ ª‹â›”oúG¹¹Ø E¥Xߤl|3H˜`ò–!iZ'oën `£Bh¢ºíx¿` Âj'ÕÙ!œC##6Lg ä*TÍa¨*çO¢¯âÌÆ™SÂíæ0Ú¢ BÕ„ªSuXÃÛ4 Íè%蔜¢ Z%kÐ*9EAT&jÐ+)æ_nëàK,¾ÜþG>­‹À—·*{¥Î …7,›É^«C‘°Yy ¼Ö YXà½Ö ™Ïfh Ë|öiuIZÌg3´p±‡9œë½\ Èá¦(ˆ³³äpSÄÙY r¸) âì¬9ÜqvV‚nŠœ¹,$¶|Õ ›¢Høã7^gg5Èáf¢ÅçpdKô ŸÃ¹á ÎÎrÍpgg5Èg8ìgg9Êáf8Bòõ@¶Fãðù‹©Ô‡QL;ÍÅ òƒ/ì»Pô•D×úã ê Rõ@°®ƒ«O0ƒ@Oa¡ùdý±˜›+\a쯟·ÿeyG„[†B‘°k‰ÜÀQÊ“È LP¥<‰ÜÀQÊ“È LP¥<‰ÜÀ(åI ”ç2 ¢”—#O2AA”òr䦢Jy.+A¥<'D)/G&|Šƒ(åÕÈ•LqØKy5tS!yïüùI†%O– «rŠ‚(åIÐU9EAtUJÐU9EAtUJÐU9EAtUJÐU9Eç÷ #D£€CËØâêÅÍ1÷_¡å—ñ–:Î1û‹âªõ¹n¼Ÿ/ lÛ_FËlÛ\¬ÅeÛþ:ÂX–qP¶­P<Â…°î}‚B"ÁY¤P,¸‚Öƒ ®áä»ý¥éÄX°±ÖâKÓõnä(ÖòùXËÄ(h3P¿+°š/›Í€½èSÂfòZØH>EáÛ o ÛÙ§(›Éka#ùEh3¼-lgŸ¢ˆ¨»ë€d¼d¶° z‚,÷‚ð9¤ÃçaàXlŠB[ ŽÅ¦(¬Çb<›¢lgZ<Óš¢m'kvbA/bq!äòóþĶt@`}ÛÌ !žjŸ#°>Õ>ÜÃØæD’Kè‚é0ƒÈúÒzUöÏ[c1y{²ÝXßÇ6rÀE7\àªT Ò#42Û³A£þ%¤^k‚Æø—ðañÕÑ2`* çoܬƒÆø—ðaÙAµKà_Âù 7tÐ(!‚˜áã_n@Јg‚FA"‚Æø— 4bI ‚F üË4ÖÀ¿L0€ Ñ hd¤!aƒÆ+uÂ+uÂ+uÂ+uÂ+uâ4b&Æ x¥Nœ‚F<4:4J¬Ô‰[Ðè0AÖÒ‘R'|Иc¥NÜ‚Æcm¯ãèk_N|Ш¦K6ÚfAãŸu¡®hÕsß4V:ìå„a~Ýˤw@]- é[ß:mÇGÖiþ{ûâðÆz ,I£9¼'¶Àó¸wNõóÁ\î-òGû&tžABÔYæU$2dŽ<þ…¬þQ¤Á“Ï› “ ¼ýAý1W…èà#Ö¡HP…¸! ªT!n‡"Aↀ¨BHP…¸!É%°Uˆ¢ Ê AL~e‘1ŠX‡"Aâ†T!𠇲8É…±xùØî\[X‹–_sÍö±…±øaù-×¼Œ bñÃâK®El bñ² aYŘŬÀ¢3¢˜Á‚X<¯B¬^¸…±x^… E1ÃLœÄ6Ó0[}FÆúÖxù²êJA˜Ïsg2Ì®$D@‰"³ã‡Åçc «Ãìx™;a¶Ã¬avÖ:XÅ„EfÇóÜÙ"Š ÌŽç¹3fgXQTß!QLyE1uÊø ˆ€rÐXS6ã+±(¦Nž‘ñ•XSÞAcQLyE1uÊøéÑúpcÕ?)ÀĺŠu+žÿxfÿh#¤Og|º’J7’Ù‡H Ó¾Çå4|ˆôZ´Y÷ÏkØ›Õô\ˆ“ðÊÜÿÄ8ÉR™—ñA Bœ„Wf3.ÄI–-Bœ„8ÉR™-K`CœÄ¢Ì³§ÊœðÊÜ Æ„8 ¯ÌF¸'qSæ*«± !NüJ²|f{%ŠÀ¯$óW¶é# Dø•äañ}Ì2Ä‘À¯$‹'¶É/q$Eáñ¢üÊ %ŠÀ¯Ü€#èEÑR2_ž1vÙãŸA)rqçóº–XƒZäâÊg;®™ò¥°þ^\¦–’¥°Þ9Ö ™:•ÂÚÖa ‘½[éçÜÒyë©®'ö˜z¢¾‰0§OëRKëéASd5D@ÞX]±†=·ž®´Ió€3ìé¢õ”Ø…,+ ‚Èf×õÝUH¾,\Á]ø²pw!@÷†³6-ŸÙv!cmZº8!"ÊÂY†y@çv!bwA‚â|ú°¼ñĆ€)Χ^Ä$ØB‹±Åù:ƒº9ç1‚ˆh{~Á{\˜¤¥]7W—1Ža‚AÐ8Ï0ÁàS÷*ñ1Á`÷ êö4Ö7L0ðΡrÀ`Ý‹ W) 1£-<¯š` F'&|òÖ1¸1§ú…CN+&xµhæ@Z•àÐÊóÀÓ€àÔꆀ|r™?¶º!ð‰æ$¤ÚÞò»¯¥bæHµ½‡å]L ¬j{+O÷d¹SŠ'Ïâêfª#Õöœ|]Ûºð!²‡?…!ä"?sÙ sL0tL0øä#jéÙ' ëï¿Pð7ÁÀG•'‰Wˆú7`9ÕfŠ߀Í!²JU;d„/² -!BK`ëŒ7ä¡:_h¼!ð­A¸ºòZ§„wvÖˆ„wvÖˆh‡O0Áâ |$Þ:ð<¤Ã^¤ì^”(ðð–wØ0p‡÷À^Ð_?–÷2šBŒ÷¦ÎãÊl»a‹êÀµèÕ´P¡¹™{Z¡nõÎ]‚oæŠuŠbO«ÿÐ÷¡\:º ´Y4ù¸°BoeM?.¬Ð[YÓ +üVvϯÄPõ³¦_V¸ú™ÑÏ «‰úi6¨+«ne±êÆOÀ½u¢©½\À”°zRš°ç}#2l¢­Á Vƒšœ(A±†5þâV+Š5¬QÖ  u çikÁ´"¿6ïõ‡¥‘¦¯©{M)òëé½6”¯Œš‚©|}XÊ‘ãs •¯ŒšÄT 6ZÙ·r=ieÿn©´ŒÝÊ5ÝÊž¸•k<в¦åí›Ù@Çr±$\…¤õz¨ûÆ5Øx£THêP¿¡‡ºo¨‡·ÿÖx7iJÞ@ÃŽ·@Þ JÞ¾áFQ÷ 8{|£î¥¢äí~/û²ßøYZD¨M$)îòFKËŒ:MSi9u·— ½–­•NRH£×B£I‡€iÇ4¥ݒxCõXI°†haÞ«KÓd7Ÿ@‘³†'PRdÔP+½/ߎϔ5 "Þ^’"ŠÌŽ*¶ ¿¨}Ø‘ ü}wŒÄ~$‰{ÑRHq.G­Dl¶zûˆ—‰%2gãkô+”ÄoÂÉIÜR³÷ØöüˆIÛ;°OFAÏi%FbE(ÊÄÁšô&‹¡!Œêl¾Y6ÄÚÓ låñÛv6­Ý´Pâ¾bA2 Iìé´ Øþ %ÞFb-¶cam¼’HlWÄÚò#1šˆ½³G[MeJ"éí‹ãö*%=>Bz›X[“ãûš¼ŸÓr²yÆŸ@•+› Üߟb]E2KEcüëdá®”½‹¾@ÙDc3š@Œma]Ѥº‡FÙ}û!à|ÁÝEÆ"®Ðc„ƒÅ‚(íDÃqÙ} FÆø‚¾ì>ÐÀAY²}4…t”çôo($=>»/ˆªÎrr|l-ÊÜj³µç1Æ'È!°V@5ƧXï[ñNcük:tìÔƒy¹$ ଀A Fš 7ùI ÁÅ" ¤¸<  ,¡ÂVøE|ÀYc׸H¡§ð†5-€YÁËAú•ÊG!F¥’"¤RÊkÛVb‹#GñQ¨=Š1ã(ÚJ囩DXBµpÈ£³¤½ˆøQ¬é)¼a¥öÑ£R©«ëTeð'¼Nâç”)âñXÞ=o¸ºRÔx°aµ‰o ©”!R M¥é«VbRi¤ Úë¢W9ˆ¿üÏÒ™ôÊÐù/G¥íóoƒÉñ1\\•ÁO‘ïï뚣ߟÒß_×ôø+h ke+ãü[ëY#ZÙÊ0Ð,Õ¨Q­ležÿ[%gX+[±Î¿­”1>ÅjYÃçehö*ÎØúœi@gtFñYÖ"ÌČóŒ-¨IÅøIßd R¬ŠsÁ °Ä ÃR`ešÉ€À¾`ÈŒ”«É£ý¤É.V†™ I‚‚^ƒ+`\0Ö`‰ÕîEw!b ãœ$¥w©]ˆPq\Ò»±äqIH±Ú½è.ʨîl‰œƒ_ãò‚ïV\ºnl#Ò³¢Î‚$ÐîŸ?ÿ5öÇÃ~¯ ÏÙ¦Y€¬¡0*×6‹ø™owÇf[ÍXdU¶WÇ*»•Š$a…ga®¼6ùµð,•דn•Óº±(Wž×}ØŠ®Â\yÍã¶J9&+< ŸÄ5Î5Wa~°6ÍDˆ+W$,™Šò38ÐÒE çkÃL¹2M Åj®¢»£zIhèoÿE¨†® ýmT< ÖÐ5>†Ëd¶u«Jp¼Yùa+rY!óOßoÀÛ naÔ÷O,Œ—#Ø—ÈDןca +{3, [iFÌB2S§åÈï_±,$I‘¢ˆÈù_üþ/Æ&@š¨Oø `ˆáJ€Ø4°=ÈH+õIßÐQó$c%ô*ð,ãX”©ZÒ6vÌšµ8Т^­øhÕŠÃþЄV­Ø¨ê¦êCESˆ; Ÿþæ_ûF¯9 íô+ŠLnÔ®”4…Vüùøùø›o¶»ýISùFn.Õá˜3¾!Õ>šIh çK^Êü›¦°tíyìô3Ýcó°Ë*…U·ï­z´ß³ÎêR©MÍX‡ÖuØ,dGá°¸vø}¨6 ªÿB᭣ЮÃv·mö²ßÍrsÍv»›àœ¨ßzêow ôûxw nÍž~WŒ#µÐMþ´'b»ßµ·jÓ°ÖzÃZË®×g{7>:‡NÕìHduUÕEÆ ÑË÷öTu_q¾â,Ngñ}dx̆D{5ÚÏhH\êòr-÷œ‰ô'ó½'¡OfGB6?ãT,–H™KŒY/f-)f½`2kIˆáÚŽ˜¼o` KF*,O¸ÆÂø‚+Šˆ3ëqAh­x?{4«Þ4_p¤)DÃóH7‰BcÉ ~±–¨Èщ‹%zSjYMÌ"%ˇa…iº6#~ž9’»ÀNÓ U>$¥|éÓR4ôÖ,åC‘b¬Œ~"Jù@}"/*xèIˆL;àÃVÂa ÇÈ Ðš~ˆáâqÄÐÃ\jhÄ;ÌM ÆJ¦!œÍ ÖŸ…ÖžÀõÐÑT§AC¯$:‰ÿïO§GîO‡c§Fʼ¾ç÷¼*eÅ ‘ŒÔáÃ~P‡¹©Ã/$ÒñW4‹™õ_QK¡òœA®Œf9¥Œ¾ÀµQð 𕮎‚Fþ+ «>Ú+J}=Z¿±rx£2Až"KŸNQÔ…:ÒÆžË~Ct`µ!#+ ØŒ3‹ÛDhÅc+éŸúèvcŸ´è®dQŸ®—Ë·¢),áª~(·‹Q†ý(ÉWa“`1ìš&Ã…èˆ)¬Qí£¤vÌÝEFAŒUpÃvB݈¢Ñ⎊¦€`ÃoeLÉ \}xR@ËŸ!ëÑõÓ”àz!A.Á ƒRG¢Rç…Db“:‚–:/$R›ø´ø|!®’â“/$Á¥$ÁÅ™ ¸%¸^Öo¬´ª±ƒñ†ÛZ ÃÝX»UN(ô=ŸýcO·§](–TÅe+i 1VÝŸEJÍ¢¹çµø¦) Åéf“PÌFPÌ&Á™MM«!fî¡Éu3ZIÇÌf¢ˆd´"’šÌÒD2ÎDpU„µV]¤ u‘Ô`6P¥<„ý§¸Ìh1˜âbðQcù†%uÇåZšÊ©éR”WhIÝqIy…ŒF³Ÿ­<6žd_ƒÙÛ‰Ÿ";doÇdöu†æ>ÇÓìk0}¼FFö5\Éþ4û¾FDöu†f_ÇüìëZÑ_°DS—kšÀ ¯£@/âÍÿ/2‘}¡éÛ1+ûË}ާÙ×`ú6vcÎQd|š}ŘqíÉÓ17ûº 4%šº\ÓSÀ"c×hþ7vcÎQ¬é5 ²¯®Œe_ghöuÌξ®9>F³ŸiüÍÞF¶à!•ìÙÛ1?û\fö5øýxöu†f_Çüìkd<+ûùþ”þ~ û:žd_ÛB ;˱€îð¸±A{þ>º`î^=—yQYóç|' Dhþ7¨×1ó¿éñhþ7¬®¦7Ж ÞÀ•yíùã‰Oè…95ÏÿFÖ—ÿÍ €æc;0rƒÙ×ÈŒò¿Áò‚þ|kÄËÿƾ`ÁDØpò¿aIdäƒÙ×5M AÈA^hæCˆ±ˆxþ7F b©9IÍÿFw!BIïB„j%½ K% ¿ÏÿFÊ8ÿJž p“§Ðäi˜¥­-—É–º nãzr™ìÙ×ýK«Hxò4ö1‹¥U$4y¾LFò4˜º\Ó4û:£§@°4AÀ“§Á]`&Oƒ3À“§34y:æ'OðxVò42ÿ„ñý'O#ãYÉÓÈús „™?+y4p˜ÉÓÈ÷¯XޤÆãÉÓàü¹ÉÓàˆäé MžŽ’§3„+y›kðäiðL“§¼Jx™y•ðÌ}¤¿Ï«Ä•W‰­‹™òŒ›W‰îãÒ¾ ãœÆ ™ƒñîd$bßÀÊHÄNç: Ó‹›‘ßhfF"6…5ëF+’ž‘ˆîãä=É–Oï#3Ÿ¾G6ù„±C>!6V>aV‘ñ.Hx>!<…Ió(ç > “œ/ S ûV¦R!IgÌIx¦6V¦|bÖ•.@»››©„…cî¤ånæYBð7$Ó®ÉöL˜¹&“~uö, ”BŠ.„¤"Á¢¦/UJ-½Ÿ)¾ŸCÀbã#¼±<~ÅjìAŽ'{”Ôx¢±9>ÁsTÔø J²†–ã‰Ð>xüšÚGŽ'Bû5_ÿ‚¯¿Ey4ƧH$ºþëq"¯íþ5çWãóþMƒHÐû7r+÷׿c4Æ#¡•92ÿåøÁçÏç¿>˜ê0”ZjóEëÓ•$ÐÖ{׳l(øÛœ Æ$…VЃh¦Ð&…7Ž}Rø®¸ˆzSgI Ây(ü‹‡Jj|„„1 g`õß86ø~d|Ìùþ¬¢ÆGH úý1ýý…Ïàjz‡lw Ë©ñòzŽ~Âùþ^¿”óý… ÆGÈ»3úý)ëü@çwÍÚD.’LçsµeAóͦ®sIЉ†þvL|ÊŽÇn ‹âç§r#HÉKÕöFnË?ŠSËÄ¿D~?Wô¤ººHûHÑ•}×~¬*»ÉŸ5°Ù$°ìs%ûÚ"}N[WÏS]9‹¸ÒÕ<Û¨àf™.…q–rSìê]-s’ÀZÁg»‡vôÔûý^JÉXƒ7MàÏ_M@WòìÈæ4VŒƒô;ŠY†ìcj;Їg¨bÓÈôÓž$ÁûX«²P$T£É2db ]\åþDˆp ù‚ˆ¸Ï¸Nõ6®rP¢.~ã,¥ ÄYÊ …n#ÞÛ‚®­a›º”ºn˜J.sPª¼PÀ™ ‡‚…«œÄÀU„ )àl¥fPX¢§<Ð-…˜Ø ü8¼P Ît"¦Ÿaò ’:ãT@ä<šqJš~ãˆó i K”Å¢ë°BTFòØ 8“EWrÅá²¶ 1 œÍ¾PÀù,¨7µbâT7kÁ»Y¨v,"|7[íØÍˆ¹› ýðB™%B!%fAìf4®ß ðDÅ:< f+y|/ršq/B!%fA¬d Õ6›ýÚV2â4û•`¶¨I Â{õ*’Þz]ѼO-M Å{õÒk€·\ƾ€•i‰}ži©èmŒYI¿4o”K¯‘ôKžiÉØ…ž5L‘ôKÁÞª—þ‚Þª›´Â’`¦äƒÂÔÿì“KŽ'úÜ j<žiiô?ÓYÁ7Æ#ݤŒúÜBëÇís+©ñüýöLKc<ÑçÆçõ¹%Çcß8Ø"~¦e í‘i)òMÑeZÞÏ$h Ðà?*©ìTQÝ‹ÖÃ'HD«^˜¯U/9žhÕ[RãñTMð 3S53ŸxgÍ©ñD«^xý˜­ziD«Þ’$€§j"[ÀKÕÌè/À7¡P$¢U/òx«^ ¦jšˆV½‚$€§jb»ÀJÕ™)‘ª9H³‚&@´êEv!âìr™­zIOÕÄv•ª‰íBÄÒ)èE$Zõ""…•ª `÷¹¥ }nK’žª n#7U3£¿€`iô}n‘/ˆY,­" }nIOÕd|žª ^&"UóÉÒè)}n¡]àö¹•ÔxBCWÔx¢ÏmŽçõ¹-©ñè÷…¢Æ}náïçõ¹•ÔxÔÂ( r<ÑçÏësKŽ',$r<ÑçÚvŸ[IÀohã±ûÜ"_ÀësKÀ7!«HDŸ[è°S5á}ä¶À”$biD Ldx-0K’ÎÌjšÑÛGVª&(ÐØ©šØ7ðšGJ’ÎS3ú ˆæ‘ÈðšGÒˆ­HDóHlY©šð>r[?–$B¶W$¢õ#2^ëGI Ä» ­Á)°S5áoà¦jbÁk*W’ÎHÑT!Àk*'IW*IDS9ì(°R5Ñ“ÀJÕ„¿ª /$7U¥ÀJÕ„‚›ª S`§jÂkÉMÕ„)pS5áipS5a ìTMxìTMô+X©šèG°R5áo`§jÂ'›ª‰’`¥jÂ+ÁMÕ„¿ª ;UÞnª&:Vª&HŸª‰’X³*gÛ”IKém0žƒA Â+gK’Þ AÒ¼ð5M ÅëVÓk°´W¶SH,DÌ…°g—ªÓ95ž¨:MŽ'ªN+j<š0i…p©: ­·ê´¢ÆGð÷C±.U§a|^Õir<öý@,„KÕih< WNݪN— ^ÕirQu^?fÕišQuZˆªÓ9I€¨:M¾ …" U§‘/À«N+$”Á©êtN ªNÓˆªÓôpaTH’QuÙ…ˆ³ ØðªNÓˆªÓ4¢ê´" *AI ªNØU§!ìªÓ4¢ê´ U§s’Qušþ‚¥U$¢ê4ò1‹¥U$¢êtN ªNÓˆªÓŠ$@°4z‰ªÓnÕiE'lrYuù^ÕiEÀy*èôbWF¾€Wuš&@ÜhšQuÛG^Õip¹U§i„l¯HDÕiä xU§I€ïôU§AüªÓ%B‚Wuù^ÕišÁs’Quù^ÕiE ¸RI ªNcGWu; ¼ªÓà7ð«N+„¯ê4FWuºD(ðªNƒøU§B‚Wu¤À®:]"xU§A üªÓ#Á«:}¯ê4ö¼ªÓà7ð«N+Œ¯ê4F‚WuZ xU§ÁoàW ^Õé!Á«:̓Wu¢àPu#1ª´òÏp—¶O2¯íU±vÕ[»"±W½Œo+&*`ürtžZoígWìoß o&PlÛbRY¡¶’$€}P77±Ô͵¾bB…ƒ{ÑYká`IG‹ÎÂ[€­ÑÂlj½è¬íû­†„]tûþ‘§×8Ây„W¼#l5 vÑYìûäûŸWŸ²®  Æ£Eg±ïOÑó#‰ó³fžrˆ˜BLiéÍJl 1©¤_1ì„ û‚ˆT3°/X3.SË™Á/Xs.S»‚$€ÄDSàlcŽM!¦9’ÕØj£]MŽ]&œ&ß²šñ¸x“4´Éˆ>H5.ÜúmÄ Ä´Åjm“²ê ÎàmR`‹Õ¡ø=ç1>æà[,Nc<ÑæDRãcÔâ·lÀc|Âø~›ÅiŒ'ÚœHj<þý¼~)çû A'ÚœHj|ŒŸhüšy~5žhsBâç'dzÖ?+©ñD›Iq½:?6‹ÓBÀfqè°[œ„A ®c Ȭ§í …PˆYßMÂjqÚ6äÄV‹Ó¶…D(°¶Æ÷_ã ¹økà÷¯yz•õƤ\¬‘ö_ñ´bŒ?ký³’ã–>„OÉÅž€].Æ ¹Ø›Gx(¹8ØWˆ1…ä¤\||B¡ 1ë Irñ± '%åâc' ‰P`mxšH¹8'p%#æ,ÀAÊÅa%ÁuˆY{ÈÅØ&¡B+_HØrÉ.W,/„à ¥Çsä †Ÿ²^(5á³Þé„-Wàï·È«^ ¨ñø 12ž#W°ïg­VRã ÷+t~‰¾¬Æì-Æ _Vcöã…/«1{‹ñ—՘½ÅyáËjÌÞâ¼ðe5foq^ø²³·8/|YÙ[œ¾¬Æì-Î _Vcöç…/«1{‹ó—՘½ÅyáËjÌÞJr¥ËøùzÊçëÖ/H§|Œ¼¨€ñL¾ âã|ùiï(j<y!Áñ,¾Œ|?+òÅz SFä…Dørʉ¼_N9‘áË)'òB"|9åD^H„/§¬È ‰ðå”y!¾œ²"/$—SVä…DørÊŠ¼_NY‘áË)+òB"|9eE^H„/§¬È ‰ðå”å“ díäQÔxœ/[ÎãÚÉ¡¨ñxDœe×,?F òµ5ÏQ‚|mÍóc” _[óü%È×ÖH‹—&½ðA¢ <šô~ùèÙ#%~S–à$ã²²À9ªjr¼Ùó[×ÞªE¯À%LÆE-'­ž±‚ɨ¨å´e¸ nb2.ji?CyV jüÒ¶þ5cýY¹*IÀºcÆà&Õ™é-]äi}hz8¹QI`ie%]Þ5ÆJÒÿ–ö:~ÇÇør£ÔøÉÍ:(íª+“JQã;]˜TÐø‰ (â¦ãr’0ÈIÄ)Lr’ÖžïØ)LÇå$§œ@§05ÊI‚¬@‘^ é]ˆY¼@^ è]ˆQ^ è]ˆQ^ è]ˆY¼@’ž»ð(o’ …ÆÑ]xÃyAѲQ(j<\h]¶UÈ5>ŠQš*A^ç²&¿à]9dþãBçöBé˜@:ŸÜ]ÅǪnéB祂•²q¡òüæüœ…Æ› „Öß(4þçS§ì³C{ÛªL©mó£ÐøT)B­ˆ¨iÄ(4ŽJ#£Ð¸-à•Ff¡ññükR…¾Í¨IqÌ)ôM¬€aàYbûˆ%0 }¹.1ܣ̶e 6Ä)³ò!³Ì6Ĉ_`_]à_ƒ¿ôE®©5ˆXÌ8' ˜kÐq£¢èŠñàÜh8;tùì2­©ƒ$‰ËÄ)1^&³Ä´í ½Lkâ éâÆÈA2 <[Ö€8HœÏèAZO:Ø—©" @*>!ÖÇå•íå™1±>.¯<9‡]/ìŽË#ÛË+‹ ö7Ë#›g /OŒÎŸP+ ?EÕ…â+B­—'¶8ˆý7Ê ÛëcÀ(/<9¤bgT¶—Æ–À¨Æc»$5>Á^Ëšœj_"±a£ñK,6 ^^l˜×Ç–UÔø‹-þŸ[&ÁK8Ž-ƒcÓHüMƒðWæËZ¦@th¦Ö­ˆ ¤µnZfMäø MSô÷§xh‰¿ÄCÛàñŒÐ6|F¡mplý1'h §SHñà:ú –XpÌXÁu˜Y™IPt^Eˆñè‰ÂA¦$~Œ™ÂßÏ 2…/€d G©V$‹RE§À‰R…÷ÀˆR…Ã\é/ˆñ0Wð ˜a®È"ðÂ\‘}\û(¨}\ûÅÉ"_À‰“…y' Ú ’@ŒÚbûÈ ´Å(pmÑ“À ´E—‘¸¹Œ+ôF+z œH]äF#uáP_ú b<ÔÛG^¨/xx¡¾È>FSÙh$‹Fö‘+ŒN9Œ3g¤ÿŽl,K„/ØXÁ8ÁÆÈ:ÆøQ¢•I Æ¢•‘£À‹VF§@\邜ÂwåRWšîŒQà…;ƒØáÎðqä†;£xáÎØ4XáÎð7ðÃs„/ܤÀwÆ(°Âá…à‡;ç ^¸3F‚îŒQ`…;Ã+ÁwÆI°ÂQ¼pç¡À w†¿îœc$xáÎ V¸3:V¸3HгF)¶ß©äIú_»cåYÒã#$ÊÓåhŒd2OãòÆ0©Èñh€ öý+dý2Æú­ËÊŒU,³Ææã$¾]ÿÕØÉi]ÿº"Ç/±ÈÅï/9~‰…Raë¿Fï¯"îo hîæýUÔx¬ÄºþkÆúÛ¢ ŒñÄý%Ç/±¦*ƒÇ Ùþùœž †È×·jFÛÛŒñ1Ô|Œ_õc­A8JÁp9~ñ„‚X`h4”¶‘ pÒPzƒrÀÕãÀ\{öý1Õx“øþ˜ª®D|Œ?q‚W¼\(j<\ =ÁãÆ›PØöý)ëæÔx¸ªñý)ºþ’8?kâüHâü¬‰ó#‰ó³&Î$ÖÍ[ËÛ„1.„®ÿ¸aðÊ‹p@ÃŽ±?³6¦ÈÂßHZò¡ãÁFazàY³0½ý™ û³0=ðF…}ƒ™ºj}"ÂÖÑ,Lo¡($äëºFaz»gý†Ÿ…v¬ShŸ4J!¶ìÅÄ£KQÀ,ë µ c¾ešUÔø³ í–el±Lmše3^ãÔ2´òÕ˜oÒãQ˰Päø÷,ÀãW¨gEûŸšûx&H|Ô2„÷?ez5·L‰¿ÄFïŸ"×ÍYµ ±õ_3ÖßnÆL˰½¿äxÜ2,àñ˜^¡–a̶ kAŽÇ-Cðû¹–!x€¸–!ÈÁ˜–!=µ aÈ´ |–eHG-CìûY–agàBQãQË>ÁLËùþ”usjÁ»6‘ø)Ú "Ôø%ºþ…ÇC56ŒžG’$á=J’@Œ·,ÊI Þ²ˆþtjdŒú³Ö~AÈEæö "ÇGx¿ŸŠãý~H|‚ äàx¨DŠÑnG’"¼ÝNIˆñn9ô¼[ý+P$‚˜@Œ¾¤w!Fy¢w!¦“Hð]ˆQ^ è]ˆY¼€^ƒ%Þ¥&ÀëÒRQã#´ËŠ$ñc¬ tY—Ôøï’ás»¤TÔøïrãóºœ”ÔøíRa^—D˜p»”ã#¼ËHEñ.#$~‚t AçÏìBˆð&I Æ›|Ð_à=:$L€×££" Dh‹ IÎG EHðÈð:dT$mp!é/ xiNHÐþ3aô§@.»?M ÂÛKT$o/AA‚w‡0^wˆŠ$¡Í$ýÄe¢¿ Á{3@_ÀíÍPQã#¤·r¹½5>Â{#ÀóçõFÔøïmãóz”ÔøïMá³{T$o-€|¯µ@IˆÐÎ 3åw0^g€Š$!…ý‘{Ä.ì/HZ—]EV]~”¯.?²¼ºü‚$áeõ‘/à•Õ/IZ]EFU|ì,q«â ’@„µ—0^Q{AˆÐšôð*òkÒK„£&=¶Üšô‚$á%å‘9ðJÊ ’@„V„G7‚U¥ÀªSàW„— ^ExŒ«"<: ^ExðØááàV„‡)p+£xáÁ…`W„‡?‚]%ÁªRàU„W‚_%Á«‘`U„‡W‚]üvExø#ØáQ¼ŠðØ'ǹ¥µ"|äVý~NÝ=ÆxôÞ¬“¹V„ÏÉñxÝ6z|Š­]‘ã—ØÛ­Y6r¬Ï§äx¬"<²ÿ¼ŠðfWäVž3¯Ÿ“ßW„·<»ò*—֊ð‘[Extý9¹[ŒñÄýUÔx¼"|NâãásI'î/9~‰½·šõ#ÇŠð¶÷R§ŠðRQãÑÜ1•åÀxfî˜+w 〼Ü1Æx¼* ÇÇØ{!†ÏÉcŒÇ«r|Œ½õÁ'˜WÞöRçT^’ãcìûþ”usj<^•ù~:w ;?¼Ü1Æx¼* ÇÇØó¼þ¼Šð¶Ç)§ŠðàúórÇ`ÈÌËAÎÌC prÇ`Ì̃׀›;7w ùfÜÜ1œ'w Yfîò ÌÜ1œ'w ¡ÀÌÃ)0*–!¿"|™UÔx¼"|Nâ#–ù´"|äT¾šÔƒ+Â3Æãeÿ9>Æ= ðxFExdÿyáøx½´œÄ'< Š[&ŠÄ_â÷ÆgÔ«CןSžW„ÏI|¼"|.©ñ)~Éñ¸eXÀã9õ´í–¡CUIŽÇ-Cðû¹–!x€¸–!ÈÁ˜–!=¯*"Èñ¸eˆà³,Cz<^UDãq˰€Ç³Np¡¨ñxUð3-CäûSÖ Ì©ñxUäûY–!¸ÿLËWäxÜ2,àñ¬õ/*j<^U\¦e~?×2/×2İ,Cs-Cp Ø–!ø lËþ®e®#Û2D)°,Cx¸–!ü \Ë¥À² a \Ë¥À)ç­,+éP¾š+Â3Æn%5>ÆMCx|Ì2 Éñ„i(¨ñhExe9NámAýNáU-`œŠðª.aœŠð¶X^§ŠðÊbß:U„WõÆ¥"¼ÕÂv©ÏW„Ï5Päø÷PÀãY62NExÆxÂÃAŽÇ+Âçäü ‰V„/­w[^MêàF®ᥠÆo¯>ûíUÂxo¯Ð ¸o¯äxâíµ¤Æo¯0>ïí•O¼½–ÔxâíÏ©_ŠO¼½ j<ñö ?§"yiAá‘ïç½½Bã¹o¯äxâíµ¤Æo¯ðxÖú[•‡ŠðRP㉷WèûÙo¯9L€÷öŠཽJ˜ïíZþÛ«D(ðÞ^Áo`¿½æÞÛ+F÷ö* ¼·WðØo¯ÞÛ+HýöŠQHYo?6¹Â¯ÏW„·j¦œŠð¥µ"|äXÞ®YÆ|ÍÒ*\Þnrj<ñvá³ßnL€÷v­ ÷í†O¼Ýj<ñvãóÞnÈñÄÛ Æo7ðxNEx»féòv“S㉷øû9É횥ËÛ 9žx»öŸûvCŽ'Þn5žx»Ç³ÖߪYº¼ÝäÔxâíú~öÛ B€÷vƒà½Ý(˜ïíúþÛB(ðÞnÀo`¿Ý`xo7ÞÛB(ðÞnÀo`¿Ý`xo7 öÛ FS^XïáíoáQœŠðð˜á…ÕNq(! OYž³"¼íÆ©"¼íÆ©"¼íÆ©"¼íÆ©"¼íÆ©"¼íÆ©"¼}*ÂÛÑ¡"¼}*ÂÛÑ¡"¼}*‹Ì6‡ŠðÂ:—ël݇ŠðÂz*ÂÛ§ºp¤ ÀæH&À©o;HNámÉ©"¼mÖö)|Ns'¹Ü,âÇ/=¾FÆcøŸ hþgäuyŸšìèsú ‰~€—- ¢ÆGöP$~ÌÚIGÜ>yQ(øûMåÈâõÀv`*–-n‚€¡Yì~l Snj1¼ :ILaÊŠ,¦'ö¬{lf~Æî1öý¼ ”Ôøß@r|ŒñzÔ(ÚØ@€O“ 8|ž“ 8|ž“À_0UIy8%0„¹qŒŸW K * ˆ/P9>‰ÇãœP‘ߣøÂad^ÄBÀøL\Ø!ÀÈà¸#ÀÈиüB ?åí8ÈIŽp~žƒã™ü\Øü!Àãç9L€ÇÏ<~MÍÏs˜­—MõºÔë¬ì¼0%R즗a€³ó ÐËb¶^¦H|ÞJjn ˆÏh%ô\†` 4p \†` 4p \~K/‚Ž¡?—äxœŸç%8žÇÏÁ pù9F€ÅÏÁ)pù9F€ÅÏÁ)pù9ø\;w$Ò±•Ä&±‚@ì`(z:Jåà  Žgº>Ësl,@äl¨{9ªž¡*`?óÍv·ß·!œ'!ò—uyO£N*Ž_âÎþ¼·T¾¶ûG{‘[µRl”L*Q÷-?m“’ýátlNé¥r©—¼M¡wßÒæ43zD¥63:·¢<¢b*É@åk·}PÙ)UmÏJlG¡•´£òÞµ]ÙïûLˆnF"kØõ¥dRYj*Þ{*Ãêfò*¯GæŒV/-`¶,ûK¾¯E»OÌoYëuù£g”v¥gÔP9å#«¡ò¦©ţ¡rê :*;±ËÜS÷{hGÜN©ß¤ó5¿w§Ž»Õ }‰šÍÖ—ètyu¿Ÿ._'î×<ŸTuBÉ¡=w­vÝ\¦ûå°e’‰û¯ù´|ÍÏ—äNJ·ãû÷G¯Msk“eͳ—8ÕwòïG'Ûö úN~ŒümŒLw„›ïi¯Óá¸×q/;µ¿î²r¯Ø;µÒì®ËùÙ>„Vs†¿nUýÅÿšußâ}¸ §ÇUØ5gÉhoz§Ôc§Ú¨~§ŽÍ“ëýÖd>þu“:ºSÜNj9dYÆežºÏÅ?õÑox÷5ݤ©|-®L2 òœ!â©@Øl÷û^ ÈüÞª©¥$q<¯båÁ&±RQb% H8U‚G%„SÑ '•󨤨p*$ÊNsF+DÜÊuRÕÌÕíuµÏS2§Ã•ÐŽždþP«"ç’yð‡¨²œIFó‡ƒ?t+ü-wõŽIåEÁ”•?lþ°2ùƒíf“³2ùƒË <ò»Onv-kŽq³G±.ÓRáp™‡?p×ÅÊ26X!ü!có‡Â26ùÝ‹]°/öØïn°™‚ÍfVþ0Ž2ÄÈàü¡à~•?dlþ°bñ‡š;©^ þ׿yìw‹©÷§Ÿ=¾ßF÷÷æÔL©ü”„ÅlûÖÇŽýÃgs‘ª¼97’G婟éoé̓ö[d¾ß×<*Øò¶/Ÿ<*vVr¸oÊ㾄g$åqßBð¨Ä ^¥hî›Ü·¥Bsß”Ç}¹ëhg’Å}Ó1÷èU’Å7Ó1÷èx’ÅÃS”ûêSGsßç¾ýá%¹oÊã¾EÎ\J;ã^%@;“,î›2¹/aK¦ã0‹v&xüaÍÒÎ ¡1¿%õ*ɹÙkÔzk©p¸Ìš¥1×ÐΓ?¬þÐSað‡5ÂtqbXãÚ™àñ‡5¡ X󴳜I†ÐΘ igŠÉÖ<íŒ;©§vfXë<í,1µ³)†v6.«Û•UmöétÌt ç×­_eÁ¤b÷žußÂÑΆvV’GEóý†öÕ¾ô©;YVWßâ€RiëMµßñ×4|&¿Ý·YFص/t"„NAÍê…N ¯NUP®£7@¦QKòsƧϰ0xgØ(Ê=±0xgxeO~, Ų0ƺ§ï T ƒù-vû-Ë™«c««©0V7FV·fÚoãòá“Õí¾…³º1gu³ŠGÅʳš{v1þ›ÕܳËâ¿Äu\¡ü7«¹g—Å Ž·ñß©t“ÌÕMQé&™«›²¤[Å£H7É\Ý”%ݘëp†’µºk{Zßp§%ëN%á'ü¥díÑšà %ku×LÎÀü€3(æêŽó¬ ;ó¨Dvþ¢˜«›¢œA1W—uv +r=~w›hfŠ¥™½5ªÇ’¥™•\:„f&¸tͬ¢èŒê±ÿ¼›ŠkQÔGu,¿ÈÏIËCix/tÐ塜¥/tÐåÉ2’Gq¥ôq£ ¬ÿ’dF­̳\7L”q–Ûv‹ç0æÁ+!ü4ëóJ?ÎÄù1{=€+M,“Ž“¥V¼¥^4{£—º ¸Ø+¡ß3Á&D,uNZ#¬£f²ŽîƒÖŒ%¢ìWBè‘›ÿBç5½ÖœÓHÞ³“ô Å(·W¼-‹x§:£Ú+!‚ßK6!‚á+’k˨ûj¶)™ÜÉ[ê¸áù—¹÷/„ð¥¦Vè…q;$Ihͺ‚¤“âÚ„ÐòRB‹ûß„®3Pî@·ºAMNÝUL*±™ðÐF;öÉ©9œð`PIÐWÐnPIÑWHª‚„ƒ™ *+˜Ê=/s§×h*gÁ¤ò†fr‚¼ÝzK¥—RõV2©Ä˜Ê f“¼¦—€‚N•5¨ ’Žý-Ëi°uÃ÷©²9“Ê MÛ-™;½Æ¸^Å]—74áöÊ=u¿Ñ\Yî±[Œ«ñŸ!¯þð$¡É²µ`’‰ÑÔÝŒK㪠œºO2hz*}³c„?l.Óü¡ØJÅ££7»`RAUa8UÖ ‚ó.•%š*[2©¬ì\¦OÛ%¹LÌáÜÕ}Cn¯ÌÙùCÆæ1Æ26ˆ1þP°ùCŒñ‡‚Íb¨ÙkÓiÁ?ôƒìñÐ-p¢_l·ú™¡dÒÿ~½¾|ÿüùûÞ“Ét»û–L¾•Å$ópQ[Ò1ê‹ÜH&™x 3É–mÉ”L2É ¾NÉÈ¡“?ɤV-XOª!“3É,û@ÑÏIònóQ—ê‹IfõÒÉ|ûèdÞ¾wß·Í),¸K¼FÓšOä'œ¼æJ0ÉÀ‰ÍB A´&™É&&Åܨ_ ˜“L‰ÜQ1D™f~ .,k&\X‚G…P¦™T`eZÑbn ²Bó£KæºÊ4“Êš}垺ßh‚4÷ØAÊ´d Ë'™M‘®™› *Ó%GX>ÉÊ4— –MÌà„2-xü§LW<*„2-xTeš9#B™fRY‚j°äð‡å}–uÉÜiB™f®îš}垺ßh‚4÷ØAÊ´bòC™r›3æÒ<øi]sÉÊ4w‰S\ &µ™åH™tr•1ÉÊtÉ$C(Ó’I&Áµ`îÚ¤¸Nž3É,1-XÜI­`\qtò¥©LÛ²ÐiezÁIC§•é©§òB1ÉÄöS¬X–åª!¡¦¥b™–/t€ëÀ;Ç/t€ûÀ»V/të’w!^èæ%ïF¼ÐìKŲ/_è&{^k4­ýD®sÊÉk¯“ œØÎ°0ŸdbÛa®™~’•QÁ¼\5Óm³šTDøcÉ¿æ]Šv)ºœrÞ¥X`—BÓa]Šr)2¦Ïå…*'ªŒ½>VAQ37/tÖh5úR$œrô¥H¨z¼K‘°.½é¿9—Be\:Ä¥(¹tˆK!¹tü0³×'Å/WÎ¥ƒ+O{^È¥P¬KñQŸ²š-)bN úRÄõ©æ~MŒ«=ä×¼¡¶„âÞ‰7–òT2Éĸ®ÂT‚«`’I&Å5°œI†°%¸“ZÁúë6¼¡¶„ä^†ˆSôƒ¾ Ë–¨˜d !YjÓºá1*!$Kmz¡HÅ:€/t Q²®Õ @m*Y÷ê… 6)Öx¡³´svÉRw^èà¶DÆ^Ÿ5ZªåDÒAm‰G••J0ÉD`Ɇڴ¦l É’kÒ–,±&m Å>Ì Ö¥\: ~˜Ùë“â—+çÒ!Ô&öú¬àË¥X—kªMŠ{)pµIq/OmÊ™db< &±2°J"w*be`•DWDf` FVDf` FVdÏÀ²æN1×e‰ç0g´ÂÓN˜TÖhÒwFoxÎó[¿á¤<&²e`A©Sܯ‰ðÔ)æñ]ÄHšš»¹d`q¿&ÅÓ<¸K¼Ä“N¸“Z¡Þ*î¤Öxb÷kÞðÄ .×ûg‹0”õ,ÉÄŠh’…ä p¿&sˆÄŠhšç p'…f=KöãYÏì¯Y¡Ù—-¬„“’‚G ‹TBdÏA°ðs,{ ²ç XX–=qs$›ÊÏ`®î Ïd`RÁÂ"dÅ]]"{êˆæò"9 þÀÎAà~ ‘ƒ ˜dð°©ŠKÏA ù/Að¨DèÍ.JŒp4“!âä H*!âæ H6•%ž=À\ÝžÉÀ¤‚óî9ÜSGä H&8Ř9ܯ!r˜+L„MUÜ%Æ[dðI±cÉs&$–\¡Þ¹ˆKN2=V,9Éô&±ä€:“ó¨Ä¸jŤ’àê sF)®Z1©±äL*D,9“ ¡1W—ˆ%çž:"–\2ÉÀ±ä ¦7‰%‡‚À“LŒ‡¤s'E(EÌí¦bÉ)2¬Xr’Ëð”"æ·JQÅ£‚ó‡Œ9#œ?p©,ñ(p溬ðˆt&B)bRyÃÀ%óÔýÆCҙˋdzø¥ ÞŦ”"Ác3L¥(g’Á;SÑJ/&8g’A_gD¡˜db<¦Ÿ;¦3g’Ab:iMψé„còH2¼˜¼œI‰ÉcM*1'e©"Éðbªr&üø##¦ Ž!'ŋədˆ;U1ÉÄxl>)vlCÎ$ƒÄ6ÐÇom¹SÖ·i’ ïm:g’!Ž—L;©Ÿÿ6rjÛ¨ÇN„ñ '7é_k±ÿü{ÿûÑ‘i¾¦+WßÉ7²† ›d´Ôüì•›^ܵfK%w ¡’IFKÍÏ2çMÎ&ÓKÍ÷!8¢™TQ%wR)B¦ÈÀ',“ÌsÞ@q71´s«¶¤7Ü8~Ãñ{h™P…ä~ ~ü2òkRÆñ+j.üøÑK<ŠŽ˜©¥àâQxtŠÙ_“ÚÉ´_ú é8RÈzŠ Å]âzŠé¯YpN1}nŒS\Kî×Ä8÷Ãɤ£. /L2Í™dbˆŒbœâ'ü³¿&…È(Æ)~’Y¢,=—L2+”¥ î¤Ö8K'7œÇÒ¹d–Î%㼘$³â\†¬d’!X:÷k–ž3É$8/æ’IqÉP1É,»6èeh `&ü2Ðk±$CÉ$CHî×ÄØÛ&îbZÜ q3Å]‹»x"î@§55)šm•œI1ÙV]r¿õ´1¾f|üì~?ÆÚDœ\2võº¤4Šôá"[cêuIé7&™×(r&™W¸d\†s'•âw‰—è¢wŠu§ØdpU ä’Á_F.ñŠqü`Â$ƒ¿‚KT$ﯽX¡2Ü$Zw’wXª€à®Í — ä×D,ÉP2É’û51ÎÒa21=©§€)™dÉÀýšëçcë¡¿/s‚ºßYÒ¬T"$÷Bæ–²ÂV*1Ú‚,cÎ(Aû¡ÌoIñÕ¥Ö%bô\²un²RA3~èŽ8}s&¼çRÎ\—ísÄ¥²ÄOsFX¿)ȳYû}f &•7´? —ʤÏḱKÆ\˜QŸÃi+6œ9TÜIá} î×à}3î×´'øçóO3©MÁÑß¶ëlQ7ÚÌ&_%JÆxuùüÓ(F™c×»¶#óU-v2½bÔƒô;ÚÐÜ'!˜db;™Ö¹Ñ^Kî׌9ð1vj#Enë+o'óˆ¶ùèÉt!šLÛÌB;™¥íkDGFæuÆýš•ík4™"¯wmÖX>J©rŠÌÈJêøæªd’‰°Ë`˱“‰S\t§˜^›tt&wªÐwJ1ÉDè)¦/CŠ^†þNåÜI%èñ«¹_“¢w*ã’YÂwª=Å%“ rÚ«É]›5–|Á¸ ú2”ö9ö­Á—!ã~MŒ²tâÜXÀäL2 dPŒË0ñØLï”d\ó) ” \2)ÎÒ“Ì0yÉ$ƒK†Š;©5”O]†”+¸dÉ ˜dbœ¥WBMÒ†^â!$ï2¬É x—¥&ѧxŹ 5÷k–(KgOj… ˜ªd’YcqìŒË±$CÅ$CH†’I&Fíxı| %ᙈX>…¨hb¥ãÞæŒð*"9ó[Ÿó[–¸7€Ie…–Ü@ìøÈâSj\dÌoyÃÍoî©û.LÅœÒbûI¸_áŽ.¼nÆT‚;J¸dPŸ‚D| ‘ͧ`—¹òK1ÉD¸Q'˜dŸ—L‚[c\2)nJ&™%îoá’YÁ¢w”DŸD&ã’yƒõéð5ƒ÷0ÙÇx~{ZCÅ!ÀsÃþž÷Gq7}à€ Φƒ6i-ENщRJúž3:ÇÔyU2É óHÉ$XVq®¸_“bŒÿ5KÔÏAïÔ‚Q«‚±SŒ†ºE^)&41óºŒÉ$è†gܵÁwŠMf‰‹`œÌÄyÙ«‚I&Â%yÅ$C8o¸_“àf/—LŠá’If‰;¶¸dÌ%³Æe'—Ì.É÷øýÆE'›Îw ”\:îiã.] †wÁ ƒ‹àŠý=)ê³$»ˆõ8(Æž’"XR®¿ÈG Jr.œ±ÜI"˜Kf‰:”èŠèÊœŠX"¸b’!D0— !‚K&BsÉ,q/™m§"ÀKû”J„;=˜TbÜĤ’àÞ Å£B ø·ÐïÏÖö#Äh°ÎÉ®_G Ñê×ä¤ô¤Å8Bôkû¤²œI&Æe >©”»S9“ ±SܯÁ9–•ñEÎl˜^›ˆµS%“Œ~äúü|oÕô]Ã"FÑjû¢{ä9*bKHÑkøÃŸOõOWÿÝ=XV‹:ÏÇê12‘&óñùJF¶ZÖm+Ä¨ŠŠ•Lôj€“"¿&aLJl¸d"ˆŒä­Íkù4smmøÚÈÎ.C6<𬠏ÄY∷6z‰K&™_b.™#ƒmø˜Lj##>&³Ä7œ$³b;y-™d"ˆŒ Žß˜LŒ“±M*r™”è&5&¡dµ·jm8ûþ²¹ °±†ù;¢õi¡• °4¬•VfÿþÙWL:´J—®˜$w7qt¡ÕQïêÜ9ú»Wy­]hi=®Ó)¡Ój·™Ö¶Ï;¡Êïo­±ÌxoyHûa]zŽþ°Û^æßß'åD,2‰ ˜Ð«ëüäD,~=‡ý°•»|Ó 0WÇN¬oºòÏrÆ.çÃÝXúÒ f voþ»\ï§F¿r"¶|=±Æ4s!ܾlõÒÆü²*—Ò‰Øú¥J¹f_éöeo£ì¢¾¦Zw™„¸·_n‡öw_̬ÿ´æ =kÚ6•5œqOZÄá@˜Á‚F«ÆdA±aìOù†tâ ‹o'b8ß''bßPNľáFŒà҉ؿꥱ~Õs'bkœ£¹{ÃnºâÞôdÌ7,\H9p¡„Ç7˜‡ƒ¥¹pWmAñ åÀ7^u—×n0}ƒ°s]nÊü/öÿøŒþùJðí5ÚL·¤Ùµ-iÚOi;_åÍO!ðÑÚ¦t ØýáÑeªÝ&? %h´Ž—k«¾µ£3ͤÚÑŦmu¥ðÑZÏRªwçGl}u^žÏ§ŸS•óÖ½PÔßÎÃÐ}xÛ(µ*6ÛkU¨m‰^eU›Û½;t íí>u Wó^ n‰mW¬¶+3[l·ù¤Úìk|´î=¥½»ý³ì®ü¾]Ž{j´Žû×ïØñ9úº¿”õåý Úh¥»-!²‘â~®¶Äð¾tëç{?|(Á¹Ù–ûMI¡w÷æãߟnÙ÷S=…Üí¾©áñPR·íTÔ–Ô=éNE™”›ìGÃõÓ¦9p}ÇöÀmÛÿ¨‹Ö»ÏÕß¾\²x–K.Êó–B_šÝšú@¢›Ó ÆívÃõ]ë†ŸÄæGwM÷ŠjO]sd[~Õº½šë’mÊkuQyE Ó‡úám³È~øíz>—Ô]ízCýùlEsaÚê]AƪÜä‡Û&ψ×=¡~>>GµuÙ|y]’øø(2WþÑàªYù,?+õüùÏûÀŸOþÜùšØ÷¨gs]ÿÇŽÍeSwºüœÈáý©ëŠPîwý}o?þ»ÙÂÅ-"ýXÓœz]…Z¿æY©nßçœbºÇS3ºÞ˜Õ}™€bsÛ^‹-¹që³¼-Ä9”Ú½ßÕåRÃßÌ&^í}×ÃOÇ/êÆÅ=¯ûø|0+ñ`Vòû¾h#àðž×µg¾.ºS× oôæâBÉF­#||üëÕ´nå›c³«nª( âÐÆq/¡:FÝþÖKWfbsÈ÷›31<ÑœV}èC;h(ûºUø‹1<íõçƒQ ͨ¯Y–o2ŠUÆË‰J#†wâgK-ÝJÏ]ý틞‹l(zÞ² 1|=-Åýp,Õ_™8Ã{^÷ù©y]‹}Ò¼nÍTIhTÉoƒU¶QA=«,êœâ´ÉbÒÔïôß±tI4iæ'z^·»ïêH ¾iuöø”°õ÷Yž¯ÄðÄÖØ°We•TÙø¿Åo\—Í›@]ö9Wf I }t_办 ÊðNÃ}¶ÑG}ö9Whkj8®Ñ’K‡«´äp\§ÍÈcóž|sr jé_ê(lŸÍ'ôì+PŸ¯Ÿ :^ݨ7­·êMu¼ž.$~F­ rÿâÄff´Í/03ãe|j³3ôxØÎx¿´ÿƒ —ñ+«¥ÑŽG,—ñkÔÔ …§ñNmB¢¶Æ‹æóQû*Dí[Pj_‰ª} –ÚWà µ¯"†j5wTíË·ÔÇj…¾Â§VœfþëTo’ˆÞ´ÓCJ'…Þg¼‚Z'9~«m’áj+5}Jí#¿VûJTí[ðÔ>rþ€ÚWRjßWûJJí[¼ú4MµMÐjÛâEíCÔFjÿ(µÂ·«}‚VûcµRÛ¨ËÿPû µ‘Ú\íËIÎI¨}‚ü~Bí#¿Wûùý„Ú§¨ñ¨ÚW‘ç—Rû(|Jí#ñ µ¼„ÚGí¤öIJí[àjŸ¤Ô¾®ö•”Ú·ÀÕ¾’Rû<µº?Ú'(µoñªöʇÀãq2z¸†¤(­ÉøáýWjtŒIîïšøòdÜ¿R˽¶¹"&÷’ׇk-õôè¡5#&õ’ׇë–ç½ÛxÞÐ? p¼úiÉëõæw¼Ô÷µ“—j·QÔª½Mú¡>ú%Wðãm2z¸62 †¦Wµ;ÃQ^÷M—Êê¶ÔÔ(§û¡v­Wô> F×5£ÿ–—úB OÍî¯âô~ú>©¹?Ù\`Ã16—Œ®5—ë†k.× G¸\2z¸™\–GVëxJéð¸½P›c~Þœ.ƒ³8pß ÷}lÙBLŽŽs¹Œúx+›ËH6÷jÙNø\Fò¹WËftà…Y¶§«%…޳:ré^WËÀxÝØ²5™]A2»±e r;òàì¼tcËäwäæÙ^F2<ò58^Fr<Ó²³¼Œdy¦e;æyÉóF–-Ìôh¶cåzÉõF–­¥Eròªüz;د~úßò5ÔR÷,ÿÚ?ü*íèï¯Ó°+‡ÑÑ Õ뎴½W£m³+óÓ©ÆGÇ“~¶Ãèý"̆ÑÉh߇ ‹vÞòt=ü࣯­=zôýzì±aôÙóºîÌ0Z{òÔçcÇuÐBsÛ˸^¾®øè5®ÉC_¾ˆXª|N 'tyj8¡ÌKb8 ÍKTÌ=‡ê¼DÅÜs8¡ÏWÄpB¡§6ŽÐè©¥ƒUz‹¹—céô%&æ^ÆJ=up(­žü~B­§6Òë%*æ^ÆнDÅÜËx@³—¨˜{¨ös/ã Ýžd;€r/Q1÷ÂwíÜÿ˜¥Ý b8¡ÝSà í^Ãí^Ql/Fµ{E±½˜¥ÝçÄpB»§6ŽÐî©¥ƒµ{‰²½˜ÐîÁöbžv_Qã ížš>¥ÝS›i÷Šb{1®Ý+ŠíŸv¯(¶ãÚ½¢Ø^ÌÓîÉóh÷Šb{ñH»ÿ7Öî[L-ËýõçŒ{Õîÿµûnôöpº*Ç›©Ý®,\»3µû~矣1í~ä·ý7èçÙsÞjÿÞâ£û.”êoot¶}º]w?øhT»Ï² i÷…Ø”çÓáŒÖÚ½.’ôÕ½3õ¶AVª½§°¿ ?é(ün¸hÃGqð»Ð3Ï÷õW9ð–Fšº}x]¦ðrœ˜ÞÜ•ÇG Þ¬w¦²¯ãæTÃS­!|~êá“.o–þpØÕÔpd×±¹¿¦,¾‚ë]ïÀO»ãä` 7ÚôÇô<²µ'›ðs=ã£#»ÿ@¡þƒÕ˜ÃLü õ¬¦fä?À9ÌjÊaFþœÃ¬Œ—!Ó PÿÁÊ|2ü õ¬X¦¤òŠà0 õ¬FÆÜïšð­Fqÿ“ ¯ ‡Ñj÷?Ýñ,'vü5îºåÝplË_ãþ'{^>£Õ(î²é5á4ZãþÁ]/¨áÖm¯ ·Ñj÷?Ñ$2B“XžG&ªDF¨«ÑóÈ4»¬¦núb(YM]õñóˆ¡Md„6±2žG u"#Ô‰Õ8ðÔ' I ‡öU(Vãç‘©)©}PRRû¡:¤¤ö=B•HIí{„j‘’Ú÷U#%µïK,‰á›§ö=Bù¼DùüÚ¸ï>/Q>¿¶Ü÷Ÿ/Ñ}_[îûˆÏ—辯ÍçP“ÏK”ϯ'Ï¡Ÿ—(Ÿ_óî{ Øükê¾K”ϯñûÞZ¼Ø}_e>¯Ðû¾9Ê,|^Qû£|^Qû£|^¡÷}m8Ê&|^¡÷}=r”!|žúxhßÑû¾;ʦ¦ŸBM¿·Q£‹á©PÃómÔà±1œ°%1°KÔr|5²±XŽ%j9¾Ø –#4÷µKÔr|{-ªÜlÛ»é/(ŠúK}•_Чý樂 ^6ˆáè®…"†£»^’ž˜voÿ†[ˆâû°©¯Äðt®¾ž×¼áè®ÃsOL›½× ß_~ÎW|4ê/€Žð8vÊòU@Ø+[¡¾ŠatdeRuÃ%&µø 2¹S+Rc<òe<Îå?ÍËxœÍ>¦—ñv>WH”ϽŒ·3º6y at/ãqNÏ?ÆX†YÝs8~òàÕÃŽ^M¸ÉžÃ#ûÙQøÙYŒÚØXήÂÏîbÔ¿9{’Oœ=EΞÀÏÞbÔªÆrö~ö£5ÈÙçŸ=Ÿ½Åèì™r¶&älûõ+DÐÖ„ }KZ âèe<.j7—ñVY[²öe¼]زfŽÇ¥-<TÜjxPä=‡ãò^=‚óúŠÅ÷À›»FÑ%Î÷†á€†©ð“á'¿Ÿüˆyòkúe<¡d j< e*üäGÄÉÏÊš9žÐ3Áù§¨¢Yâ'?bi{Èêê^A ¯P®+ñ³›2×äº?{1OæBY[/ã ®[Rã®+ñ³2wÂuEÍOp]pþèÙÓððîǼ³¯Á÷ ýuïÁúXÊäºæ«×~m¾b×àЗ©©s™Ûв£»¨Ÿ]3‹6[Zc7£e^üÈŸ‚VI‚øò.Søç㽘:´tÄЦ X“ÓL]c4^뇽D‹CM¤¼1z…–†*ìµ­Â@QI 0”1úÍV m- ež–ßÖòmUkU(sø-ʤˆu{ÔÄ'g·o¯Éc±Üì¡‘ 8<±]A^•×[Ö3¯éË%G»ÀGǶk*Èkº¦k*7×´ÂGørô¢•àE[ÓMÂmͺhÄhâ¢ó&ÊÏÕÔaëÏzdŸº xÌ+BÒ G™Ì­AÒr‰c2k´ÉÀdˆ}3+<_q·f Qĉ]¬í,N,nýÆ ³8bå±àõ†ÍdvôäU]\Öä¿Q ³¾aâ!ÓZTÃÛÔ=¿UE&ñÑšÅéº]øs?[É¢:ÝîE`ëÏRlχÑxö=…m [µiö½1«7rȪ ½F÷»†ö{ÅÙoðËWœý.$>ں߹ß+d¿3r¿Wœ,d ßïšîw];Öí÷ÏŸ¿Ý—Õ¡šÅkõ€|cß±Ôh óG›©ÇGqnøOë &†G/ëÖ|ûé˜õ}AΙؖwI&1¶á…Øæõñ‰(ò˜{U|oÙ75<5â ºá:D}óSÚ_j´~±e¿ a‰ry _p²_Áoq¹:4šuËëMpõ põ½å)zË»T2ä–§è-’0)l‚«Wøh‚«;Fpu Œ^³¸ºÀG\ puAì÷åêŠØï5'ûŒÂ&¸zŽ&¸:±ck”-+-/F\ ‚al¹„Ùò‚âêPÈ3 =ÁÙ25<Å…5| f=å¹%†í1<ád=ß>jÀ6Ùu… ã•ÑDr²ë UVFD (Ë©á„,¯ˆá€,W¨,_Í '‡F¢²|eDÔØ2QY¾ÅQ™(à·GȮׄ ¶25¸ñ®×„¸bjp€½°bjp€ê»Â5¸šÐàV¸—Ü ×àjBƒ[žõÁtðÛãÑ®CÛ®{Œèí5! V£6ð0‡‡·-æpøšúøß6jxŠjøÌFA8ü åðÁáW‡‡X4øéj­)j×#–\¯ˆá„\WÄðgÑÔÜS\@P×`. ºë)'üöåðåðk\®ëá0‡_3å:`;¬™rPƒ×¸\×É0‡_ãr]çÀ~Ëõáðk‚ÃK”ï /Ñ»¾¦8¼DïúšËásb8Áá%1<Á·š{ŠjøÌCAîú½ëC øí)ýv_)5™OŠÖIlÏjÑäIyØ"¾z»@aus8þv¯ˆu×OŠKÌæzޏ[Òö°‘[yØŠø[‚À†¶=ç>l_¸Äø°ñ¶Ã{Ø*kh¿Wœý¿|ÅÙïBâ£ñ‡-p¿É‡-t¿y[Ä—ãû]_Ž»@±ckøyEYU·ÈáyEà£#œ·(`4ë¬%嵬ÄGãÏ+‚ ?¯ gû¼"ñÑo©ðÑo!vlsè´Œ¢=AÎ$ñÑo!°ñçp¿Éçt¿yÏ+ļ ޒ㣠ÞB`¯a'¿°‘ƒ“?ÇGÃE¾Æu5 |t;<1lžÃSà£#Øí¯9×í–ã£#Øùƒaóœ?9>:‚]ðšs]Á†0:B×=· e%Ä Íáø¶‘胤Р©ˆáø¶Ïãp MÜô)¶ÃM·÷ÉMoËÆô©¿ÙiHý­o‡‹=ñøñ;²ÚtéùކÐ_ÐÒÈ•âÐx¶íÝlw¢'"ßœÎÛìk´ü6hÄÏÖ¿Ú¯ÕÚ;¥ªíùðµ?ß84tûÞ?Ÿí³àñМœN·êr<ïÊì³¾£Å¼&ëÄûKþuÛv·-k=úGÝ÷ÏÞãÓu¢èhTr·ÿ>rh¬ô\>ô\Žídô\òúz(xsYk?:ÍZèv¼—ãñgûÍ<o}kƒ®¥t›^ÞÎå~{y)ŵ¸²ÎØï—z‡]†¿èu9Üä­fY Í]Ûçêþ„4'õŽ5w5‰D/r·N úK6m"‘ØØß칿‡lwøbé㺞 ÛGÏ…ŽÈi÷u>³6xÑ7œn«!îÇýéØÞÞÚ_wEùó-¿YD–££Ö9éNÝ1©êë×!¿³ˆ¬†Ö×Ý—è:Ý—”·F‚ñ¦£Û]õ§ÝnÛ|E{`wªÙæP¥‘x$ GD²Ó ‘ïo‘ù’ã¨ceÑ™¨?Ÿº{{Lt:ÂOQoòøÃ"Ò1µ?;"í1i¿¤!r;o6ªz:›DÒ!B§¹ÅYÏÕZ¿ÿ­J]s‘Ž­ý|v¥7"͉½í~â¤XDVc"ÇNÞtDš9Õù‰Eä5ç !rè*ž´‘+U”YygyÓa Ý·sºéìÔ¥TíQ»0Ûï1ý)•¶l’¸ð¨tgöçÏßvBY Óìr³7¹‡ïƒàíOÏÜ>tûö†Ww!ÍÚÞóÓù”ïyÔs·?=‹<=˱ÜnêÄ\—ä•Êã[´^ÑRa~Kß§m,ôÕ±ëþÜŠ]q‘l†ÐhÑN=I¯Ë)?TÊêõ[T´$l¿…9£þýNižÐîµh¯ó½¾6–i€ÊÛˆŠV:;*›m^lrÞŒ¢ß&ÂÕQÙí˜ßõoÈúi~ÛÍ辩Îo]¢^‡ü×Ë©ã ÝŒ®y¶9•<*ñè[z*ÝŒîùeÇ/Û\}?‡Dã¹t¬g·ëTØfÐ5/óM½»~ov–!Ñh纜ýZ¥êÃõŸ-CttŸOó åz/êRýü<‡Œ?ŸÝCŸ«Ð¾ë×y–µ%½·–!Ñ+JóMÝXƒ²ÙÝîy£P[†Äã!Ç.%B´C® w°I^‡4óèZt4(÷ýí.ızò>™¾°O?B¦/íÓ¬Ó×s‘ö¹DÖéëö‹é ûô_cÃ?þ)ýn¼ö¹®ëò’õ†Òÿýÿ¢oé¦u÷îs×Y®E!‹ÜÃ&IÕZ¹)±“añð¸ýHÌęŦ…îGÏ>Oöñ-¯Ùæ‘™2–NSRDŸ’RW…:Ö(³z¤É°Õ ¿tÊR'¿tÊRËS ¹­G|®W©[´òZ].hno{üjÙã¦íé×q]‚f«çó§­ÝŒq·ïÏI—‹¾-ëM ­¥NIþûïG¯Ê^G"´«ÒØT›Æœ‡ÆYrßÅ#÷ýTÕÐjê⣼uñÈ[o~2è<ëPv€'SG ã´8èÆ©ê&oe[ ~m§¤?ªªãIž2hœvÍ|¼k«çéi’·ï¯Ý`õ<Æ%ÐShû7°Fhí/[õý ‹z4Ó ¨.¹ºžZ ‰ÈÛ¥‘G K° œSq†õͤ>>{¦ÒñJÍT¶×Ky†-û¹}>ô¼Þªh¸ƒºf_`ØÊTuû%iU]u<*`X¿o8}N:´K£Ý>ü5“aoƒB»}Æ‹i¦ò 4ÝîßcCgãuGÙ*[h¢©\n߈§Õ•ÏݸÇqnÆmóÍîô}ÿÆÅ†‚Ú}§VP‡"ñú÷Ÿ¿Ÿ¥T<•Ò¢QÓ¡q©”‰!¨ÜA@ÓqKXûnÔ1èŒékÄÆ|É/c]Fz™]•ÛlJµ•À° ¢)êãƒÞëïïcyÍa žò•}Ýa©Vº>z¥«3Ã;³.6›úZ’% ªn7`.ò-0¬/?á—âô½ÝÜ* [«íèaÚýqØ¿¡%y”†7‡Uñµ9—ÐvÿÖûý®õ½–i­ò~ÛŸ”ªÀq£srê´Q­&Ÿ®õáx¬ qò |ÍJðXƯßÙÌîØ¿¸ln»“Ê ^‚=Ÿ¶àüRÈØ¸Ü.ùwâ-!‹ãr«ó/xÜ •®ÓÓb3=N'í[ê¶¡MùžnCBIWUN¥ë0,žýa¹]Ä7ø‘ òZfcE¯q†Ö÷1;O±ÙI#kÌÎÁ"+*a ò`ecEшMxÊwcÿÕõô8G#V4æ`æ`Ñ8C`90Œ`EÐ’¼áŒO@ÛýÛvÅ%|Å#Œ ˜½FóMXŸ€Yß8~pP[XJd°"›3ÙÆú";+zþK‰ì¬èiý,,â±¢Éþ¥+0+"}aeE)ŠÌŠÆöüÃÕÝí[#ô»Ë½üßÿóõÿþoÿû?þ÷ÿþ_ú_ò¿ÿïÿÿ-þ÷âISzäái-W{¹¹\*xdd7 wqo~2Œíþ€ºõ¹@F&ˆ'¡È¿¾à‘)êƒxäòE?îõûD;²¨~N»Û ¹²»êÖ5e»¹Fœ û6ò 2»‹Öì>í‘“ÐG|šCE7ôrF†. £];%ÔC%²CV Cµù³;€ûSßH°h>·:ʽÚo¡1ä²9´.›+²J‹ðT ìE^®ÈPð$®EçzýÕ¶ÒhÿZü÷ktߺÇÄö›€lGo«Ëæ~SøèhôÙ­Ê¡?ûph‹¼ìðÑø½ûþÆGãwïxÄGã÷¯"°'w°ÝÞÁÓyt-£WösÒÝÃÍfGìØy79]©Ñoè¥:_ˆÓòÛ¸ÎÝÌÛ‹•m…º«‚¾_.­3v—ë«”·Û†9ÚYRµ-5D³r:x?·W±ÛeÔMÝÑ—§$!«ãFnˆÃÝÓî´×¹”/ÃWÿÅÍàh,‘ͪY¤Œ12BïÈöi]«³9e×Óè”#›¬èGÞïØÈ¹ç 6r êº=Õ» âÇöˆSËö8染c~¬Ž{=²Öº×Ë_mõi3¸1èècžåß<2Bõ £‚GÆv=¤nõs6ÒCŒ‘‰ýpvG»ë ÆÈÔ†Ù̳żÞ1Ì%ª{\OðÈ•cvzƒ)±G®Ñýë˜mûö8´Iœ==|4¾¯å>:¶ÛyÝÞnÆëlØF÷»tÙS£S;ÛìNG1¶-£ñ}>]ñÑ+óéöú êì°ÁG¯‡¸….Üáxê+ƒ^kÑFïýÿ×QÓÿçÿ¯ÿãbý‹ÿþwùßÿ¹úÝ2ˆÖèŠ_ÎÅ»zTyÐf[åAœEY<²Ùæ¢D=Êû€’‰E<èUôHV¸gÙY¡îË[òþŠÒž±,»Êë± t+Ç1Íí!ëkQ´‡¬xùš ÓìêS–Ž:`²Q®š%˃ñ˜gDs< 0âÜÀ:ÌÚÏþÑ óôà˜»+LÒW,éK›†2º÷{cNžCÁ¤/…Q:˜6P¹‡Q‡P·¦ÏˆyW}™×ÃPRø~?ªÛ- ÓÇ¢|ü{œÉ¡Ê§¯¢(Bè5ZØ0¬´¾­Æ¦Î÷ÜóÞ,:cõ÷ØÜìPÆÜ¹ªeyÉ|™€‰Ùø¦æh3¸³‰Û6F£dê²Û„AIzЇˆj©©9@!„ò”ÍZ)3ŸvÞÿ©¿½p~´¶aL£Ó„‚‰z¹ù8eZ¢u§l'vÇP0ñc(…”—樂IÉùßí¹sV„„I ýȹ7L¦ei`–ƒälQzÉÙíÍ5ßWe¨Ù¬ÉÙÁ´i' “ß몔`Ö†ä̲ArmÑÂ@0o0¨Ÿ¥Ëæ_ÏßÐ!ßèÎ@6MÙÀ¶ üî§Á¢)«ÏU!°hÊ ™V‹¼™\&îgV`Íê³Yš­ÐÁ–ˆnîg>÷~F˜èéUÝp›¼ 5›'èïÍÄ*B°ˆfE]ž³s¨ëùÛÈüèØ@‡£6Ï>8‹)hºØfצ-¶y“¢µ¢Á<|(Ÿ˜>R½…©‡d¿Ù0½å³w¢è†4¥–zS‚IÿÆöÙ0PóÎþ LګЦ ]HuÙ¨PG`i·ä&›cL`V†ªþ¨;°oëôÕy¨Ù¬!˜FSÛí¾CÁ<+ ¼³­BÒXê*»åe¨#°øýÌ´5¼íÞÛ]ÕäžšÝì6eŒÝD†ÿahf|¿ï‹êl>:lQ;{Ä©Ç)Ž[Q†ÂI^jÑ~=jÑjukø[(œ;…¿§cгܳm†#²}Ú‹§FèÓ«úâ˜Ã L˜ÈÆ z{êRT¡fÛôµžçÌP M˜òE6Cõ0aRÀã݈ G 2ÀTeq"êÔ!abpoêlÆý4a:ÍããŸÖ£šG£GIѦkªÊfÑ=×¾\ω ÚÉêY6¨ A¦nVnJ%e ˜¾ZÅg¯ãû‰Í霗géëZŸÀ$Œ~'ÌNý;áö.¶y!Á¤6·+\^t ³ÁhAðùÇÐqåFÝmþû÷ðFv¯ó·®{v;P0ëžÙ|>äMûÑ» ¯joÞ±ÖÂÌP>'×ó7$pêY‚ Îb`žS·gÈùtæáÇO—WÔ:ñ»$áfÝ.u•‹KŒ­uœà£;Ô»áaúšg;I%CñµEbx>Oƒƒµá:U°ã¦ƒYß»Fä†#·Ñ=«<β_·÷Ǻuµ®ôºíTê–>Êþ·á mÙž°S§ë.Ë7* ¶?kÈÚ™ç2žà˜Vâ‹õ¶Ûäe¨ý‰žVâè¼ÉMQž6þžö Îò±5ûîDO+qûõõ¨º˜eåU^ïõW8œ‰•ø| /ÄW¸u›X‰Ïwj%.›s(œ|A®ëyÂGóƒ] ±îñ ×¨54¯äi¶ÔÐgõ›çqË*5ÿú¼vªNÿ"ú¸¥Ree®d ˜ØnðÈÆà "L_M„NÕéaºq&„ª!o õTiÂô’§«k3¼VkÉs­¨¡ÑøâcòFÑÒ<µhk –¨ª½ ¶7o½¸þx,ÚiX´†M¡`úñ÷.2²¬íÅõå¾k)êP›óâœ4^x3uÊâD0û,æñcœø¥È“6ēվêû¢ËHü=¶á§ˆçbŽSÊéWìÁ¡‡Xû,“Y-‚€ á7çû&ˆö¬´ªÀ¦çκëœÌE^Ô?žg,ùOÇ^ý¶ ´‡Ãã\ÌyÔ3@ú·¶Ïw]ËHÇ+·µŒ:Œ" ˆ®È`g4÷dÆk”yO‚TŸ±°êø¨É8eŨžNY”ÞbÒ!ª½ùèªîUË&àÄfKñÄYžÕÛ< ôÎÑH®bØDÑ÷þ£ PÝïwƒíW4üÿvU™œ#UŒ «Ë9ž†rŽs¢`“i‚Š]xÖŒœ §êÄ$=å%sà™žRøÞH¤w «¿}¦xfÚ´,d9I€Ï¨Ÿ­²B´¯Möæ¯í«ÙøÂ?îÑy3°x†ºd…ïާEm¬G¸ž½OëßhùP»‡‡zY[ÒˆubƞĖª:ï]•ŽAöN¸–A^ÏùyÖL"ƒAv/&ƒœñ•ŸöV1ÇGi€Dæ+i¯H´Ï—þ¼Ë‰7Å– û»A ÉœàŠºú 3“Ô°RNƒ‡Ee·²² Ç_gɼ'u#㇊Ð3AÖC ð×3ã@—ÏUušµñãòÀeôW‰ (nå\—YYŠ*H<¸¤Q+âµRË<Hò’žaŠ_ÿ@$EØŠ?«7@–À{ÄiVꔲzèß½žG¸±PÂ,׿]›¢š'OFOVKs„/3<,ñä`¢®ÍnZTdÞw‹®èËäb¤âõ/þ¢ËD‰`[(+o›}”x@ö Xö÷|EÈbüÞ=­q.æd3 U†™É |CËf8ñ ÞýÞ›zOºåºe?Y =yƒ¹}±É.ãoÛ „¾(3Šš( „ß7ìþ+ J„åHÜÍ›ç¢XUâ!³µ ³ù‹+þ:±‰’‚‘õŒŠT&J¯ÿ›p|)fi`±E+gzh½eF¦GjiÃðjØu&ªÎŒð÷G¦ÓŽ VÃ.›ó¼™Zš;¼æˆ! ±º~ÂÌäñ¼ùa2—¶Ø€wA:ma󷵂í ò¼™ù[©¥Eþ¦Ï›Ù¶lô¯9 æó¦õ2ΑÂôó¦–*3²ÿSÛóæóåñÅ•3#":µ?oÚn¼ÿ›M:}Þ´¿<ÎIÆN§Ï›íéz¾<Êýö;“a–k³•M‘û¾<¦ÓçM«‰:«N[j}Þ|Ê“ç“`&†n‡s/ão„y;^vëñ‘•4Ãzœ>oBçýs’~%‹í—Qø§kë­£®Å3꺱!¿ÁDú³K=pf™È ß,… L<͸ÏŒ _9<é­Èó½K¶)ŠM kÜßôjіȳ°ÿ­™À¬€÷úÓ¼×g ö~‹šÀ¼½ ñ/Ь“¡¿ˆï˜ÀýE±éX»‡‰Ñ6&¥ “˜0½qÖÂ(l6Ï¢a½[«•Ñ­îTË2z³4ÜZƒ÷¬–3Ž Ì í–¢BÁ¬íÝRZ±æÖ-‡yƒÚ˜´íÍT°½y4?žveiÛ›©<Îí—’c7Ú/%«BáÄh¿”,غ%æqkçÓ7çiLèPÇM»QÁ&@Û`ë¶DÛóäÁÎÞm(ܺ­¡þªÅ‹½‘Ó¿¢i3çVZoŸÒºÕÙÅwÝ&2a¦˜ã¯›ÀĆ+í¥ýñ ‡Ýæé±› §ÊO8 ì²›c„N`Ì›ÓyÓ´D¸×Ê×›6YUqÍ÷ª µhk¨Ía1ÇžšÀ¼Ùºõu¶ËR̘5< o¬ˆÛB²7ÙX»™óÌéèaz'd Sܤ Uê* ‹:Ô¢%Æ¢³aѪêVË@0)²hõUå`–ð¢å2/ª@0«áÅ{Ô3ºåÐ3^¼'0kÆÿý~óöRVeô¦RHuÙ”Á®çåäß­Œ%³*ì»fÎ"Nd–>Yßk[e7U†Úž¾‹žÎŠ?®7˦­[yײ¶U '5Þ½uF|÷R¼/ªK0œå¤œKÜáÇm8±³²UðÒ8ªÑsO¡pÖÀë—§Ÿ}¥fÎ/Ü÷¨2]*&ÊR=ʾgϲï²P`žÕ¯¾žÕ¯ÚØ´í]ló,Ôl›àyσÍ&…MU‚Y‹Vm«B‚YÁ‹V‰*ØlÖË^ÿ:Ù¾èu¯“*j6oƒ¿p$­åF”¥d¨#ЋQ;NÀû¹˜„îB‹Ö1™‡Ú—€»±úÑâÌבá,šöc¹Q "ÃYdyÖ)ª\\T 'µ?íµÎ¢ÛNe¡ŽµvYßöêFÍ‚ëô€T—§MYÛð=¬í¹éR‚‹À:OÜ»¥Áö'ÞÅ»s Kj¢‚³õw†Op"è¾u†W2˜þC/ð­s¿ Æß¢ÄúbYHýbY›Oj{²ìÕ]ñìþDK[ýÂ^Ý—Í9Î3DfPxn„Ê7¤,6[wØ„OOxª¥ u=hà /…A@âçLöC±,“·½' ’ ¥òú—g·Ï¢Îî— ½’ûÑû ´¯Õ×®eÙî¾H<íPÞ‚|>@!k H½ñÕb[‡ò©§n0¼YL<íPnqßÍ·ª¸ȳÉ£ÀÜI çL¨ó}«‚€¤ã¦®g\ÆxÚ¡ÜêM©['T ™¬¦®¡Ó£ú-Wa@Ö6ÿÆ£<ù¶ òfsÖh}QÝÀ<\ƒ-ŠÉ¼Ú—Â@W~ñŒèØϸu}WYçBByDÁ¼(§åê탎­ÊŸEK‡¶¢³8qléP>ê2Ø—áÌ›ŠúÇ;áF£üŠíáIC›ÁbÎû‰Ò¿Û uл,Å®WD«õgæbäu>®„¨Í%Aæ¢ÊB„AIá¹´ûeÙ§¨µ©6_û£vŸ… Èù*íËjŒržE³,W`æ“ú3w0+T¨5[DP#ÈbÎëÆ&ždÛ=“úÔÑ¡“`Ùv.Åp˜Þ¦ÔÙv‡¾ðgk¹T÷ªíAf 4³ÍeîÖYÚ0+~ÅÓ6/Užž'`F@§‰ô–îr.œ ; (xsiì.Ý–_/¡àí¥³* ÊÒnÁ´å fÑ·~ŽÆeE-é‰å%SeÈÖ=S§ŽßE6»6n-:1äYU«1âYÐãtû¹I‡"UúÍì$.ÛÛewÿ ²„#õ&»Üƒ€ôïeŸ}ŒîñOWÀø’×ó%ÈzP”úŠ}Ñ ¶b@sš« ÚªÔöñ¶ç^=Èy·?}‡¹Œ:WDkÛ®’Ïc*òœegeaø)ÆR‹^‹hÜSÞôS¾kÎp† °Ÿ²7“±ô™5­©/î;ÿÌšØ :XÇ}`£¿ul€¤€ƒº.æT ‰¬e’(ZÕ•[ÿL $‚²6²B^¼%JK”á·~‘Íe†D‰¬å³/xÔ)ùZ¢ìÊòœm‚€¤CU¥>˜±÷Št ×*ÌL¡ŒŸF‘Ý6þ³ºÝÏA@Vð=™!¶¢©Dy­ì÷½³¢sµ«M)êYnÝhÌ ÛWÃHäÑ‚ó<ˆFÌÒ¤ÒQÃçûóˆ%íÖÅCdRÞê@ O:¤’mÞïðõZX¨n0ò@ +¨¾Q-ÎÁ@¬õ€´«ý´Ëïaް¥ÐãÑà¤6ñçoÜÍ¢(‹á•EóáNî¢á¶ûr_}‡A‰^^ ;”vÅ4Ê©¾Ÿ¿Â è[¯Zx?<v+vÈÕ¼##6©¹“ÊÒñ¯®Òõµ(/×Ky>\í~ªQÚ&]A#P.§Ch÷u\ÒŸfÅVª´ú„<©Ÿ<r¥»ù>ÑE\[1¬­Çû÷ùòýs ´/ëç\¶Çá‹$?ݪËñ«.»P+ÖE(þùèüùÇ}?—åt”ma³0sÑñH «ìPm]r”2Õ&ÊB£|v»8ê\Ÿ¬¼Åw^n6×0(ÝÝW?;s™îE’oÎ÷Ýeëý2e¢Äz.ïz.§ã0%òr߇AÑwÿ£ êmî‹vîT}ÍË›ðÎ[2QôÝWï­Ë°“aÚ(ºœÄ×µmxeùlm«¹å _·ìBéî~£·ö÷E+úÍI¾¿Ž‡K Å5ZîKŸÕÝý2?xW5QÞà÷âš¾©ºþ¶y¨ºˆîÍ—ØÝNaPtq޽÷è8ÌåëV}Ýn"Œ6ë>½ÿzï‘Vù4J¶ûºíܱ8£hí¢C»ý&‹{¹ß¢´1¼­O¯u´î¯»rŸ«@w?Öwÿ³-h×(J½b {i}aßõ-y¤ïþχÖÅûÝouñJ\…ªÍeeè0¢‹vít˜¢þ:šËz4—ÓQô¥s›™lN¢ú ƒòÖk}Ÿ}¬=cz.çìû° cQþPqâë¥9c ÛÏ}ßqM”Å +;g¾ÞýæŒåJ}_7ò%2ô±làÉíÞŸÂhIüÜ—ö}½o ÔÈÊØÅ1о¼Üýf.}“ŽVë»Ê{£“…‘bI:èc:1Ièl„f_¶×ïk M)Ñ:ÿÇŸ‡Î/t=óF‡¹ÝËl†ó'«ÑkCC3=)³Ý÷W {ÈýÏþ$wïRú$ïÏûk˜»Ÿ¼=uË­¶÷:ÏÅeûý]ݧ0r?ýýÜý}3Ñ…Š\o-ç—ßuFƒM#”¬sñu(?R¾ë@s‰ž–Es_ÚÈÍ.vór<絛Cæî§ñˆÃ4Ë•é}9VõñëpÞ„AI^Qº:vÝßÖâPšK:šK+*ûû®¯? » ƒ²ª¯Ô]±dë5²½³EQÚ`j·nÝHd”J~¼Ö]cïØ¤¼‹µ JVÏxÓ1@¨NI›setZs¥Ë³¯Ú Æydix,_Ÿ%/f¹´ù³oÙ;ùthðFæe˜_ñÇY6Äï63ìI[I—éÃQVÖY}¾„¹Œ¿íõÑÛ÷–ÙW>‚®ükþéÜ‹AWþå­x6_‰¦W~šál& Tµ¼-MTÍ»òÑôÊEËÅIçæÝë*òzåéY‘ååèóâÔé,}ýóצ²@ú²§s^^³Cäí¬µÊ’iŸ[]ÉC˜ÓÕ_ù®—P2xöê‹wMea>®÷-2Ûr ç| ƒÁLrS×—s”Øl˜=ZãeÛRþEöô#þ¯×@”¶ã«‘ Ò®M}T`" øþi^)?æµøÝð@©û Î)~gÂ$fq×vÑúâwN­ñp˜ˆß9Í+~gÂ,ŸÁ5}aÂg»ÏïZ†Z´Éc»xV]-”o4øf ”;:Í+~g¼°MãzžrUí˹0‹Ñõ´†Ðo²&ŠuÝìUY‚±´­϶‡P0‰ÁtʼîþâÞLJËëµü&[‹FlMó›ÖÔ³µ6G0¯K™×"L Ïf>[‹Æiâ/³éDŽžM£ãf¡mõRMe¬æóŠáŽaÖ“.6ÇP0oÀ#À¹Î樄“ëùûÕ®š>jݪݲŸ,ØQ{‰øHƒb£‚-Û$Yü4¨Òs:ÀNqbD4Òà+N‚Õìºov¡pRÄITgGÿu›ú¢¬|z^?£…ÅyoüS¹'01Pöè”Õó SÚ|QV·JQ«ŸP0©áô®NVž3ÿ3 «/ª=iê¤ÏªW³´ÜdZ2`ú¢Ò¦Ùû¿¨˜(¦Ÿø5Ù&ÀÅéå%¯¨áε|L”dš‡õLö*”ï¾ÄJgVOí ÏÍŒDû Ldž²ÞsSÕUYoÊP³îNÅœ‡» L³7?íAkãš:@ï$¢®n‡íë&Õ0ÿÚ0}ÛÒ®š”å­>ÛŸë=̲…ipºÙû¨FUÞöY™¶fÕÁüù«a2ÿ!óËiw???¡öf­góù7ß·³².B·,îmFCYBè·—Ùd¢‹;'Uî.ÙÏñ«ÜnC]ÏßÀÓ×¹nî?K›à,†CÐ/[ëï*÷÷rsÌŽÞÅo'8ÑØÞYC}‡S¾‘‡Ûî §ã?pð6úL×\ºûê|©Bá$N3ŸG}3y+åíŒêBÏùè Ý|Žû]]›ÏÒnbH8œóü1Á™8¿[ñ¦ßÛŸÚ70xŠÓÚ‡Ÿ?mâQ{ÜDÿj$¥Ü¨›¼í~Bá¼ ÉÚõÙͧ3Þç$lLå¨ýÔ»Y_„%+ïõñPÜö—C(œ…‘J•õ8G%~vå~ 'z¦9í:-§S¦ªb³½‹ó.˜þÓÜ´,íÒܧ¼,ŠP8Úö£Rî¨qªÍÏÏ÷N–×`ëÖòƒŸŽ_µÇ ?"»oî-æ½ ÅG£å´¼¯x–÷«¸Y˲˜ˆþS&0bìÌð™01è-ª¨¡dq–öÉ­.æò#lôµÚ«xV{õwæš0KĬÚò'Ì ±D²z†ç«‡‰Mƒ×8ó,±x‹ÿ0aâq:âó¤ÍÓÚL­L½?ªYé,.](³¸gõW ˜´¯Çùù¬Ç)õ8ïwê,5ÌP5ëÔÇÆUwy-ö™ ³B46ÿš˜õ·}–˜ë+åžn‡] ˜7БϨ.ØpÔæöø3u•o²m*Ö>ø7,˜À@5¬O³ªM`’!ØS¿uÌF¿)y½ïÁ¤/zØN<ÏIM·‡†+ža¸ÛŸC ˜gÜòö·Ü¿QúGÈN`Ö†õ‡9£DÐfREíó‘q#ž7óï X™ó5s–:8†AîÍŒêv˜gðêD³™óèn¤ӤñLŠù:‚Y"G «·þ±~Ó“f ›•v5‰ #0+ÿf#G`FÔZŸ´‰X ±7†rû1 YšQôlƒìÍŒ°ÿ LlËaèƒãfph&AÄÚ =Í„yÖTÜ> 7ö…ò|»‚Y/ǺN爫¹6,M¹…ÑkAs{'òG]ãl¨kü]ºéOJ£ÇR;JüLÈy¶šèQ”tŠ»APűF$‚b4´Ð1Dº€r.‚Íei ³¥l[ކAy4´xÔiî£I¿NªÊÊPsYƒ(_Ul_Þìu57•ìú©šË#Ô #„Sz fa6Ñ%ãº& çB„‚yöMÕ0ÚÝÁ¸–Æ`b ÙÈ>ëâ|ñ²>BéÏ£ÙHÖ½<Z]†Z´ªZ´æF°E[BõBÑÜÀ„šÍjSë¥Ùifm˜ZÆZ˜´9fº0é9Ôl,¥IÅ©‡QJjþ¶·N‘]ë”Û- £#°?t딦¿7_·ÓWQÔ-z&dõZžÖwdÞ¬Söýg—Mñ[ÎY¨ª’aP"åQMB¶üLšK äûW]õ _†f¢$@Âÿ¦m‚i%…Š|蔯@(K(å¿«òá«hš(«iÎÿ©Oøº×y茭 –™= €6ë3Ðîw ÍÇ?]3øQÍ·ƒ-O?§Jy2樫ˆókÔÃԖ쵟u÷M”¾þñûû#óØë÷vFYÅ’ñyz Ôß“l¢$Û`‹2ì˽–å¦TR†AÑJÆ¿>Ö=¡´Ò_†Ü—%‚R h.«‰kF´ÅwІïËëÆW(›(k ËE‹²Û}ByƒÚ\Ôõ Î?¹•@Cöº1þnÒ­Ø&£s¢~ºÊn­ZÞ9€šý¿ÔU)/y(0].¶†ÉÅ=tÌ1Ôõ½k›‡Ú›jú^ç›Sê8÷ym ¦þèjˆÝØ©:Ô¢érˆï­uÞ—Üì¼&§ë.Ë7á`V@rä~–ÌœÀ˜©ž/™w›<CBÞ>ÆG@nŠò´ &›fF§h|†ec4ßë¯P‹Ö›/DϦ…ø 6ÍþéV *ø—┫æ??˜_ÑÜY ‰=ºbN›Ø &z†½…P]þº ›0&+Rµ³ “ØgÓÁ”yY‚IÍl¨V:Ê_˜À, ·Öà=k`üU Ì ÔæXN˜µ?{Apz ‚kå­pN`Þì0Y£Ó60[êzþ6qteܧ- çÙÍɨ+Y4Ú@•‡:Þ.?][jèT;ÓífŠÓ©y 'Ö­Ó¢d0œ¾ÃK÷\s< ŠÇå¾ËÔFeÁÎÛ²×£>†ó6œë¶,C°ù¬ ¯@¦NYÀù¬òI÷bŽeø«K‹œT±–Ê݈9îº LdÂ<”i1Ç_7‰í5yÛÞ—3\i˜§Çn*x.µ÷Ý1a`—Ý#t³œÍ=õœíÞˆ`VPà®hjÑÖ@•¦{1Ç™À¼êçàPk¸ZYŠ'ÍðÞw;fŽÄRU·Z‚‰ Ý‘A·©”·L‚‰‡€ÄÍ£\þéS_«P‹– 0ÅMV` "M{Y7ò³³„ad³l¡m5¼xoŸ~hÍ¡g¼xO`ÖL5K¬YÂtm–ÑËM!ÛÚ,Á®çï!˜{ò€¯ÎÞ.¯)ÎmÛîîv¢ …™USúêm ­[nÝâÁ³b¾z7ËV…[·òGej·)³`ë–ïÞ:8¹{)ÞÕ%Ø|–“*0m­§8nÕ½(X‹£ûà g ¼~IqúÙWjæºE†³hªLwµE(˜è¥}ñîÁªuqmu®æ²j£í¯¦<˹‚gR¾ýh—²G=òj«æhR KwŒØæs¯è¨„ûDŒê:Þ•PÁöfôÛBíÍzxÑë_'»Ô«öu²Ó BíÍÛà/Ik¹åF)j6½µã¼Ÿ‹iRTÿZ´ŽÉ2Ô!x ¸›6Š˜/®ÇݵZ0mã'^öŠ*—*Ø9Híï¡­ç¶U2Øþ,Y  g=UvÎIlÖÐ[eçœÌƒá¼Ù+»uÛ©,Ôºõ5 l¯•u£„ÃY@ïˆE£Ve(6EÐCb]ž6yLÿˆ!燮MlÝë‹e!ô‹el>©íɲWwÅW¸u[Ú‹vꮸlΡpVƒ\˜„úµAÅÞa‹±Y‰Î&|ڨœ·wÒò~ÛpÂK!ÂÌäa%¾?Js<âÉ®eÙ®™ˆî7 3êœ õÆW÷0@"ÀíQ—b#ª<ÛEU(uÙ¨0Ë• QG:¹ÉD›¾^I!wG]Ï8ÂÈrêë8õA$Ù-÷½ŒÈ rtÔ­(Ðr­mÞÙ±/ª{˜³¹úð‘ã6³\æÏæ$CùîÒµôä(~aë}0öÞë¢"3¼÷&JïUÊ]w™j}A % %FPJ‘•aP’q¦Ú`מ»­ 5—F‘¹¨í˲O j!¾öGíÜ* ! ð|ÎØjŒr Nú­õ^Wf²Ä;µûg3p;µ—®Ú#ïNíy(¢S{ÆÚ©]xujü;µ‹@0D§víÔ^ù:\\;µ‡Z4¢SûìE#;µ—®u‚#ïNí² cíÔ.¼:µGþÚE ˜ñº…à¼Níy ¢S{¨EC;µçó¹¯S{êzÂÚKך·‘w§öÑ‘x§ö—Þæ•Ru(˜o¯Á$X õ9ñ¾ìNíóâ}Ú…W§öÈ¿S»ƒvj¯‚͆èÔê¤AÚ¥G§öÈ£S»ôèÔùwj/ç͇ө½t-yvj÷¯ãìÒ©}>¿wjG‡Z´ojѰNí"ŸyCÙÚCíÍaÒŽ½·"ÿNí¡fCujuðNíU°e£:µ‡º:P§véÑ©=òèÔ.=:µG~ÚK×Ní‘§ö<L„xoü£%\;µ—`ÐNíÕO¨ÙÚCÍîÔ®æi¹.ÚE”ÈÖÝ\xu7ü»›Ë@0pwsåÚ$3òïn.Á$¶–ŸÂ«ågäßò³ !·f†ÚáØòS‚I“æØ½2òï^)ÁDx³¿Ê{ѸÍþ”kӲȿٟ ãÞfÂ0:½•Ûé­ #³qlŒù7-`"ä@‡˜ ¯ÍW&‚[}·Á(l˜äµcÕoKET¨É“ªœw(J„µ,ÊCÍ%Fš ÁV é$#ê¡*Š’>ƒ(wÏ¡<“›ª9d2о<›Kk*Ò¡È[0”Õ`XÚÈTYE¡}üw‘©Ec9Îê^†AyëQÆMd4Šø)Í¥÷‰Ì·¸×@0h™, t–H‰›ò.}ÀÂÒ®ª “絃!µZª<Ô\´`þÐsÛû5}IWQ©k ¹hµ¹½2%{¢Ü¶YQ…AѬìC³²mý5ÊQ¸”BQ–¯ sÛëJåV×Ey¶«èQÚëߣ8©FQÖXE†²aPzVöçcT~¬ã1»úëåÁÊŒêcLT %{°2㫃i+LÔ`Т—×y[cöÃRV¦Q:­lWæßY%BŠDæ"Ê3Ànz1êÞ¢(‰y1_PêK(”« ¨æ‰˜q?¬öb¾O/æ¹þ®U”•y/ŸúRý}y”5¬Èˆò´¹†Ay3´åA­+qoî/Jd+‘òùéê€ik¡ª V‰¸ªË }4ÍûÇ£@pÿ8Ó0±ÆPö—•‘™•Ùpm'=@:î’Õ…K"’Q½Ócݵ¿4ÜExÎ$²{é9˜qº.ߛي½¼œ®͹ ¯³Ýri;¼[®Û¥uÆI^jKŒµÊËO%@Ù¸÷öq©¬Ã€ôZÓ{Ò%:|•A@V¶{ÒYQg‡03YÃõ>ÊRÔÞ†þbú Tâ" „ 52Z‘Ò×ÈhEŠk %ËJ”U %10âé€q*)€¢¤XQ j÷—×ÈÓ#¾ÈP”æ9§0(k¬¢DQÚý7,ªu†÷k¢·@Ѧs<¿"{A‰‡.ž ¸KˆŠcÑ™ÁV,™¨Æâ© ‡Z/(JŠ©Æ7‡ÈLÅô‹<=IÂ-ߢ†™ÖwÕ‹õ%ÜZÒc ÖZw¦j¼ Uã|›Õâ;¬o²"óåú‹iBë{[xµ§èر~§õùPy¦š~ÊË¡”9OyYXôïñvË5Å@"ó‹‡%!Äæ¤DxÈ›{¸BsåPf2ÌLzýû￉’½H—ö/HŠõìô¾Œ¬o™â‰t.Ý?þ6{²?v1W­¾E¹=lå&ÌÆ¯5ÈG{ºŽ‡ÓQ´2«2Y¶EêT˜åz-‰MÖ¨¬‡0—Qûsÿ}hÅø¨› uoF•ØßPº˜s›aÚs­tÝÕåµ.²0(‘Þ–¶Dù¾MýîªyfY½o}Sy~ ƒ?7¿¹ò‡vó [v—mÏŠb¥»ö>;VÜž±SËÀ®y[ôö\_³S”I%ðW&Ÿé$Õ’J }õï Ld>³‰ç3[­²k ˜ÑÒ>q˜ ¸-æ¼³O`RD;_‡Åf‰<èÜ9f5ñ»‰Áïæ”ŽiÂX‹ú½Ûb¡½ÝU¿lõµŸ@³æÎÿRÔþzå/kíVEîS>[mµEíkç›(O/¢™\œm¿½C†útÜi¸­mûòÉp˜+1à­.M`âátlS€ŽmÎ:&L2èeÆ ˜å²œÀ¤Ï¸i~¹˜¿h`¼Š§ñº 0›Ùéò˽pí·üè;>Ô¦õ[^TÜý&OÚ¦ðÝ™À¤àI›£ÒN`–ƒ†öÕ†Ûê<¬)êo¹9ì«[ ˜ÕÔ O+`³ Ó?þ¶³iOóQϦþþ>ˆêg[‚yCîSi›0ƒ‡§nŸÓ¼{³°]O«ìœu –ëižÅf¶ð4®çÏûÇãõbàwuÿ)ªP‹–bÑÙSôpLÇ(Û#¡ä@ì£ Q…‚Å(n¡ 1£lF×r#\£‡c2FÙŒ„nQ\#¡cße§‡…Ø1F9óŠQŽc”3¯åØ5F9óŠQ޽c”ëP<Qö=n1ÊYQ5kŒrá£;Æ(^1ʱcŒrá£;Æ(^1ʱcŒrá£ûÆ(gΘ5F9óŠQŽ]c”3¯åØ5F9óŠQ޽c”³| 7F¹aPðåP(ÖåÂ+F9vŒQ.¼b”cßå,ЊYc”3¯åØ1F9óŠQŽc”3¯嘎Q6‡kY ×ðᘌQþ0UòÄ1:öŒQ.€ĶÈÞÂ+²7vìí–Ë1²7vìí@#{c·ÈÞÂ+²7v‹ì-¼"{cÏÈ^_ÙÙ ÅÃfÞ²K<¬¿éˆ‡Í¼âac¿xØÌ-6vއí\ Žñ°±oÄd-ÏÓõd-ùUÊ “Óõ¼ó¹¸lÎA@ÀÓµ?Í>]_щ–_:žµÝoEÕH°»,¾|e1µa^9ñs½ö2wHLEQ"Œ_²K”ñ&6œX„AI&Çx˜Ë%ÿùòd’¿,/n—tꯃ¢tûòó÷ß‹÷]Çsž/E]\¡Äc>™tlÃ'¿Ž £Ü„AÁöEæY6”±]2—N8 ¸3÷s³3ûk ˜¯Óë“#ßHÛB„A!ªB!ªWaPðjÀy ¸°r‹EQàjÀÊ-žE!ª—aP€jÀÒ9ÒEªKçH[üVÕ€¥s¤-CTV`ˆjÀž[ãX X†A!ªš T ¸t´EQ jÀ¥k¤-ŠU.]#mQ”%P§·tEQV@ÍáÒ5žE!ªBªKçH[üVÕ€¥s¤-T–Α¶8 Q xÖlØÕ€U¢p ¨péi‹¢@Õ€K×H[…¨,àՀ¥s¤-ŠT–Α¶(ÊVdÜ"mQ¸°r ‚5P˜Õ€•[8/BT΃€Ä@ ÝÒ5Òv®¡«Ü"m1¸†®r‹´Å@ º¥k¤-ÕÐ-]#m1¢†® ‚GÚÖÞŽ §Ê³* PyV:GÚ¢(xåYh.påYåi‹¢•g­PyV:GÚ¢(+Ì w‰´EQˆÊ³U¢ò¬·âêTy¶ ƒUž-]#mQ¢òl *ÏJçH[%ÅÔ°›Ó›Eä^y¶t ‚µ(/dåÙÒ5œ!*φ‰Rª¥k¤­UCË%ºžc,õZK×p^ $ªœ–®‘¶HÔk-]#m1¢”j´õeÅ®u«@0PÝÆÒ5Ò‡‰Éâi‹ÃuCíMŠÈ§H[f‰¸Þœ"mq¸n£r‹´M-Ýå¹ue<ÒÖûÖðk*·H[†¨u˜‚Á#mçÃÕK×H[†¨(ÁÄÈlœ"mmç™]³M‚‰ðòc.âÙ¿üX…(?…(?/?&ª0()XLºEÄÎA-ŠkP„ù±@(@ù1åá^~LyEx”SA3ÊÉ@0Dù1ÏàX~L…A!Êš T~L¸Ex”îAåÇ„{P„Gù1á®àQ~L¸‡^ø—+àåÇ”GP„Gù1åáQ~LyEÌ(?6kkØåÇd¢üX ¨ü˜pŠð(?&܃"üË©0(@ù1åá^~LyE¸—SA^åǤk¼‚Où1éyá]~LÊ ÷ ŸòcÒ5(§ü˜t Šp/?&܃"ÜË ÷ ïòc*Q~ÌÛqáT~L†AÊ) ïòc*ЊÁåǤkP„ù±@sÊ) ÷òcÊ#(¿üX…(?æ­ 9•aP òcÂ=(¿üX Ê) ÷òcÊ#("v ŠèöÅ9("v ŠÐ ®AÞåÇD¨ü˜pŠp/?&ÜãÜË ÷È ÷òcÂ=(½ü˜pŠð.?f¹ˆòcž ®åÇò@0Pù1ááS~L¸EÌ(?joRD¶8Ex”SA~åǤkP„ù1…(?æ{køåǤkPÄŒòc" Q~lölˆòcÂ=(bFù1&Ffã1£ü˜ ƒ•k›‹pÊòÅ„Gù±„S~l”_/<Ê%œòc£pháQ~,ñ,?–eVìY~l”-(<Ê%Œòc£$^áQ~,a”3ú?»—Kˆòcïfr¥ð¨§•0êiMîŠk=­„QOkrˆ]ëi%D=­Ÿ=ÈqØ“æ¢4ëõå{†¡RWFƒq÷RW §Ô•åÖ»•ºJ¶±÷ëAh.Ö׃¬ö±_²ÚÇ6v|=ÈjÛØñõ «}lcÇ׃¬ö±_²ÚÇ6v|=È<^VίYíc»¾dµmìýzåaP¬¯Yíc»¾dµmìúzÕ>¶±óëAVûØÆ‰·4vˆYÝᬷ|é!Sç·|é!Sç·|é!Sï·ü2 ð–/=¤qêú–/=¤qêú–/=¤qêú–/=¤qêú–/=¤qêú–/=¤qêú–/=¤qêü–/=¤qêü–/=¤qêý–/ oùÒC§ÎoùÒC§ÎoùÒC§îoùÒC§þžj>?^{xªKgi¼öðT—ÎÒxíá©.¥ñz†§º ƒxªKgi¼v÷T—ÎÒxíî©.¥ñÚÝS]:Kãµ»§ºt–ÆkwOué,×îžjéì©^{xªKgi¼öðT—ÎÒx=ÃS­Â žêÒY¯=<Õ¥³4^{xªKgi¼öñT—ÎÒx=ÇSí²3 ÛxRÌÌ]N2lã³Ðˆ»ÌO=ÕÊC{ÛÆZòÚÙ6îWÌQ§®žjå!SWOµòÆ©«§ZyHãÔÕS­<¤qêê©VÒ8uõT+gÛxíl÷gØQ§Îžjå!½mcnÌòT+iœ:{ª•‡4N=ÕÊC§îžjå!Sÿ8w¾ öf‹âãŹËy Œ8÷"Ë„Hâ7—´+'bß%ãìÍ7bß%ÁáŒØs\f²òÍ=Pó@8§«pÈ¢Xü¶™-¬‹âÅcGaíŠÃÖ7(¾ÛâÜbGáí ÿ„-þû¢f¢°8˜ËŠ-¼YX–ÏDañ0FÙ xž1§[¹ðþt¾·®fʳZÖ¦ª*Î\âî/âqЦ½U…¥!Æw™å2 J7άÍ%6btÕøtCŒ\ÊP( èETU–‡BÑõÝÿuÞý}[úCœNâVm*Ùì¾`5Ä` ,á¶UÁ+#Í@éj }´sÙt%fº¹ˆ|#Åég/„'Š­SA[,åóQú¥Eé뻫’Uï“Áýªm•É0(1ÜÛAUh. Üu¡U(}’?ÛrIÏÝ?K¹!÷¥+ÌöñÙeêQ®yV*yÛ–J„AY <ùåŒéRå›R•³Nò¤PýP¿“/º~UÝ2åÁ“?E÷û[ÙÝ/®óöe\¨(‡ŸË¼´bÉÀ-Gg,߈9Ü*T?á0Esa*á½/–‚èÿÔß~*§îRvS)𙄉4Gn@4G>õ'¬áÈy³=ž{o©UþzYNö’•YÙÜ– ÑÀ]´œÔ-ª*Sª 3“X3—¾Ès?Í\®e¹­‚€tgø³-+·Ùî÷;]S¬íã%ó<«·¹¯,¶Tø69˜®$=ƒƒÙ*|ÕÊ›MÉd”®VžçÞ¼ÅVá[W+o§Ïœ°„Y­œ’‚ÕÊ­²ÎE”¥>cÿ†3Ö^{}ÆÊ¬>zscK½j“Oö5žçH|[½êgím]¹¶«½­”ò—’–zÕöÚÛ³t$K½ênÅúBíŠõ•‘çJ–ÅT²ô¬²Š6)fK–…!YþM%ËEªr'æ±Jâ€íg-—µür;“Þkod'YZª ¢%ËÏ{r8eíTZK]IyÏË ÉЙD—øìf¢ë¢þä…¯o-Z 1—zÃjÀ‰LµâYu†_(Zl­ô<ãâÛ‹¿Tzî|ºÒs«‡šM îMsšëo[™ß±Æ§ÿ *óû9T¬Í†2¿¹,|³µÌ/°dõ†kÁ‰ a9˨ËüN­ÓøË¹0ÑhÑþX[ê›–X[æWyk±ö2¿Àl˜-1àó<-óûùÊÑ´N>Ʊ—ù…Ê.0‘¯CÙI]Ž<Ên®ÞÈÏ¡,‚¡$¸ ¾ ƒ’â.ø@û²Ä]ðPV˜ ¾ µ/kÜÑh.o¸£?Ô­ü¨*Ì}PÎò"Â_<·ÆíEÁwkà‹¯ßMÑŒ8/ –w •Z1ôEA…šKŠ¿ŽTaP–øKOe…¿ÁšË}ƒ u’ßð—ž@sѬ ~êÉÁ,P!ÁDè“’œuÌXOJÊñI)ò}RªTôI©¬­X‚?šKŠ?ÂUaP–ø#\e…>Â…šËê ´/oøSŸ÷ŠñŸúd%‚€Dø{¢ ã3qyOÌU{O¬Ülñˆè} >ZVA@ìÑ2߆Iñ—Ñ0˵´½Œ ¯—ÑÈ÷eT–aPЗQ™É0(è˨·ˆ´÷>_y¡¤ø+o Ý_‚¯¼¥ë+oDõ>ž ”oÉÑû~K„òfó ¯·äÈ÷-Ù_ܳߒ+Ç·äÈó-y†u<}KFÞÅ¡¤ø»xe‰¿‹ÏRøïâ2H„ÌÔõŒ×dûã»p{||ßó Äã» £ ª ’à/ü2H ƒ”ŽaÑû #ð<]¼0áFù‡¨@0h7Ïw #yjoR<(¢ ³Äƒ"d ˜xÒœƒ""Ï o³Õ)(B¾KÆ Š^A‘PD†Š˜½hXP„𠊈¼ƒ"| X^P„𠊈<ƒ"ü1Ö èñ]¹ÄÝ&Ö ¨ß¦û}òøþ­J)€¢DØã{ %FžÅ‹`( ü,êÚ!ÂEÁ^ï*ËýP,5¡ ‡Ä¼ªEyG¬ª@3‰±7‘«ƒ±€˜wå±\¤»+ÍÏwV‰‘<Ãþ±Ò)ë5±Æô¿ê€LæY ”hð\µEŽÏN¾®ž+%=WeÕ€šK‚h±þwÅZ Rb¥/Ÿüe}Þ¼=¥ï•´×„Ü=³—ì×$¬Ï*3'iûJ㺠ƒ‚KãP(¸4…‚Iã¢VPpiìt–cOiìÄùcOih&¸4vº“±§4®E\Á¥±ïÆ»IãZ„A±JãÌKÇ~Ò8s“Ʊ¯4ö½+nÒØ—OºIcß+é(g.Ù¤^²Ù™ZT…¸Ü«Â¸†ImÚØ¨˜ŽU€‰ÂE±‚0’”Ë‹hŠõ‰'¬|…°ò¡V~·òÞ-PÂÊ÷Dq³òeÂÊ3ÂÊs@¸V¾ BXùa@+ß›·8Yù* `åKg½EÁ­|) V¾ç]q´ò«0(„•/f¡°­ü2 a廜e+?ƒBXùP+? nå‹2 JŠàž»Jc«+A!¬ü0 „•_ÎáZù2aå‡!¬|oÞâdåË0(€•¯<¤±·•¯DÂÊ÷Dq´òó0(„•_ÎBa[ù"Ldïê)Ú[Éì\ò€I¼¬üÚå),%+OüÊÙ_±";J€þ 1›IíáyY‘¥å¡™8¤"¬ÈÊò¶kå}º\»+òtÙºß:Ï$õ½'r~º¤óéZûŸ®r~º”󞬽÷ÄA¥XS{gQÜpÔhfq–2 QœE†A!гBIðR#Pðjß*ÐîãÕ¾™Q•§8 \›#÷\1ÇÚU”¯šQ†A‰ñ æBÔæ„‚Wûµ/xµoß“ìVí[ÎBa—fPaPˆÒ U¢4C ë}«@+†WûνçâR@Áª}+nv~4/;?BdçWA@b„)k—Æ@piì»ñnÒ¸aPàÄVgiìŸØ—ƾwÅMûòI7iì{%¥ñÌ%c&¶*f\4'±5w˜‹b«p‰¼­|…°ò¡V~…HlÍàV~é‡âfåË „•f&1n€«9 –»bu%ˆ „•f&„•ïÍ[œ¬|NluÔ+æ$¶B!¬|Ï»âhåWaP+_ÌBa[ùe ÂÊw9ËþV~…°ò¡V~ "±5 aå ?7+_!¬ü03!¬ür×Ê—A@+? aå{ó'+_†A[¥±bk ÂÊ÷¼+ŽV~…°òËY(l+_‚A[;9,š“Øš×b'±ÕÅ_áØêb~{'¶ºÍÄ3õ0Ïä<:±Õíty'¶æ®]ÏÄV×™¤¾÷DÎá$¶ºœ®µÿé*çЉ­n{âØš;¨db«] ê‚e%pIgc&S_µÏxbc&™ÛLb¿™d¬žDoOøË•2ä‰}Oæ‚°öD)ï=™ ™ ¯øR»åþ§«ÎÊjïž6ˆ÷éÊD5„·'¹ˆïžäÕ<Ög•ÜKaÏ$ïÆËy ¼ï2ßÏbõët±bOÒ¹§KÍi+Í Ò(^ÚWøµ¿lö’•ôü‹þ¯1ïg‹õùÀBœz¬ªdå5±±´ÙÄ=Vkt÷ó:”§Í5$–ö„~üû0×ðvÊnß»<$VÒc½¬áéµ-« û•êøù8åÞ*•ÝÔwH,]àâC}šûu;}É]½ ‰µêÏác¿‰IÍÙhý2b–ÅçÛ@éD›ñõjn1K'äB=Nü°‚b€ªnùæ*6˜ÆËîN_çr>”É3ž ø8ïÍ~rj²€O–Q‰Ëæ*ƸÓm³ŸwÚ-~á?ÿÞõ´ŽÇÃã\Ü*¹+¶ÇXÑëÍ:ìõqo_ª{à 3+~•&ÖÏ÷\N8õ%×SJV‡ê+}=†Í¼º{¬çU]嵉µDxÆ5Ÿw­~ðÑM~²ÂJ¨¯XÚþóÑ%7ïNǾDÃæ$Û¶ó›:ÄUŽªÙ®üvßìÕN„Š^¡ûíîòM0¶Y.׃íö³Ê«25¹[/ XÊ<äêÎçí±h_/úcÑ:)äÜþ„ZÚ„‰žÕ¶ºß‹€P+›0é¡Ôí–„Zc"ò¾Ù¸Ã¿†q¨‚0 3þ£=íûY4Ú÷³GãÖf­¾¼¢ç°K¿þÿX„ÄË¥ cgñtÊ‚‚Y¥òƒIm·yP°ÛÊÀ`˱Îö”Ë7!ÞNµ£ps*eÈY­QW×Y͇2åÿÈե݅««,CbE «KWŠƒÌ]ù1÷È—¹«€PsÏBÅÇ—z²åH*Â9nH¨—#* ÂÜs/æù2÷³"˜{ eî¹s|™{(6sÏCb!Ì=÷bîÎÜ!ÏÓ&ßl¬ÿCFÿ'úIaŒ N=‚¬7²ž`zÏD6Ì!Ûn7Å|„ظªƒÏg_ßïù¦œÐ¿“ýù° \Ô]ÌGx°›‰‹¬A8ȧÂÒDx™ÃVUù|„®àû{wãw»ÂN}Ÿ7å÷éü`•Ö}Œõç#ã¥=J:éáçgWßç#¼õsø´Ì!;“†sã~“Ðé!']^¬Mi ë±0]B"\“ùv» 1‹ñ~nåv¢¿×ê¡o>8í=?ý0\‘ˆäâÕô¯¿Êsv‘öAîŸ}ûI<ò§êŸëO€Ã.–&D?‹»(‡]€Å.V½„5•¼]u«O_µ²õ$„¸ñõíuõ€†$ÃÕäémû})¾Uˆ—Š‹: D<ÎÇSYœ@L¢6žÑ ÙWy 1‹G°Æç3$é¬!³Ýá'Dß„DýTÑ^?<}/Íf€XÙˆ>QJ\‹kˆuŸ'õñÈŽìj/7?Õ}s ñÖëìÏð°ÇBĹþ rõ~cÁ9'u±À‚r.õ%Fôª ŽyÈBŒÝ ‡{ùÞësH1Þäp¯#ß{í·Óì{»ÜëÈë^K—{yßë2DtšÏóÓOó&:A …äÄÔû$„²¯T¥÷«½¿wÍDz¬Û™ßë{‹5­î‡Ò»ÿß?(í\z”b3­d⇒Às©ªMhÅRd.u1õCY}A[”¾›f‹"e-óP(«¡¯uò˜‹,ÛÊöe ”¥ tÆÞË-©xž·R²ï}+ðþ{»UmEyÝä6f±èa>0§®ãx³Û‰@k¦½n¶Î° Œ¼¨P¬¬omÞvîZ›w'àš×¥7Y†ºÿ]x ³U2ÔHEkY@¿h¹¸‡âÌ‹eo¦7æm3ìÔ•I;Ë|SßòM)CÍþüù«atÏÎ&ßœÊ`zÝïÍûcoZ¹ÜïÍNe¡ö¦ãÍÅi ïŽ{][n§N×]3Q‚‰ú º¾Ëu6t¹…Ú5œ3”pî«.|Œ÷Fnêò´ vo¢gnööëë‘›ò*¯÷ú«¿äÄ~=‚Û"œ÷{!¾‚ÍFs¶ù¸9x£8å ³ö<жWôJ_u»E©ä^…A‰ÑÙwSÏz1P©L)_ÑiKAѧ¹C)ó2Ð\’Ar¶º—œ­€n$´¿ä´½¨kÁÙ£œz%°AñœÖGõÏŸ¿=7ëVLs³kéÍ›M”•‰òä™×Jm«0(ëAŒyYU4@…Ú—·Ašu(Zšu(4S¡VL«g˜ù6fX²ÍÕÒWÑf¡ÅL× áxÄÌ徫ÕFdv¦m™ÌöÉÊÙ\ËFÐT•ð…±Do¼€ô @ Ò°4$ê¯å{¯Ï>Yóg×,\˜™ÄÈôî_jÿ“l{=®K#)ÅI_—{­r$}†ä·åšïÕ1 Èò¹'ÍUéÁ²LÞöµ¸lª*Hob¶B?èäu}WÙðü2ÌLæû$ëJI· »M^‡9]=ûèO—®…ßž®†ãç›Ìs&‘­qÄŸÏÈÃVn@²¯o)š:u_gÒÅ[k¥6…#3©³2ÌréËØ:ɶO'™æ]ÍÎÃ,WŠ€´:_þ2þ3 þæºlÊ2Ȫ™0ÈLªó}«‚€¬£ebï*È›a€µOO=HvS* H\¥¥Ö×#+W[,û¢ºBY˜vQ«÷vÑq[B‰ n¯¼ŽÛ7˜ ľ^L‰ý ²jNÜa†µhGÏ ¿ï´¼åji퇒ŠÑØ,j¯ÙŠÑbª}-¼d®Š·˜j_-뵯–ƒr¶öµ˜j_S—å\íka‰]1œbbTÎSŒLÿàëT<í»×eäUû4âö o.ׯˆ ³\½sïýãñXѺBúÇŠó¾ü òš&»Û9hBlïâü5-XèòöLtÛ¦PǾµ‡0Ë5„©½?PNO”KUºò‹—Žmû}ßS«SÔ¦ô¶#[‹ÞÖà~€ôî–$Ëe™‰²ôíò‰á™de¡D§&©ùp§äi>@É[˜šäd¾ºj0–‡ì” JÞ¹ít¤×$þN5Iqy¦ñ{n…c7ÀÔÅY™h’/¾ïÓ.¿‡9Ë×wC“<©Cæ#šäf†ä2Qâaó;Ñ¥ýëèªoÕn%£hÙÕÇ ìÎU }Ñ÷^µJÞ~° µXÉÞš¤‰²ì’¹f.]J˵(/×Ky>Ü¡¬4Jë.ìP´SºC¹œ2оtWÿÏŸ6©iåJ{_äIýämãÁ0‚E¿~ö⫽“§N|Õê~½}U›0sÑ…z.ÛãáÐi“§[u9~ÕÅahÅô[acu·æøˆkPNG)v›@'¹{*ü£~þvÏ^Çæ w)lùæ|ß]¶eæŒu/…Í?]\ãñÐòè¹¥ÌEUšK¢Q>»3v8jå8+ïÇê»*7Ó6~(©Fy×(§ã€ÒÈ–r߇AÑw_½·&K'^´…w9‰¯k™i{úîtmm›[©•ðjl¯ò&nÛ@û¢Å¾z(áÙSÕ¿e‡"Ð\t¤Àç{_tú@sƮǯãáH Nrïjíî~™¼=Ó&Š-ôòº2Cåûµø/ž>µ(Ú‹ cvYËüTûzL”è9—ɫĽa9aP~ªÁO%¤l“]oaPcÅ^ü.sö%êP~-¦cøŽëjÎÆ˜0¯;cx,nÒÛÁ3‰ð⨼æûc¨Ù$ƒY¿OˆÓðRÜ6·m ˜tð†÷Ï ̵,O烳„Ïse·k ˜ç‚ÁŠ9O˜ht ÿ½OtyÉ|ë&0xÒ6At4ò_ô‘©}u#í¿(Ï—ïC ˜ä¥ÆÊ~ß§õõ¾˜Óíj6½-óñ18âÄC:o²lwÓè­™±;4:`§gfÕn/ËÝqsø³Bcù<2‘w,¿ ƒ‚ÄòWÊ-þ=¢cùŒ%A£ì®fäË_lT ¹,ñ(û@gl…FÙ‹@glm‹²^y ‘c,¿ðŠå±ü@}  3ÄòÛSÊ@kÖÇòƒÑï¡`ðX~'_VDÅòÃÑï¡ö&Å£ßCÁ,ñè÷P‹¶Â¢ßeêެѬ‘*”Ð|Có,ª@{ƒÇò»%ÚE¾±ü¹ t X~á˹ÇòKXþˆŽåŸ*N¥sd„×X„P:#²ÌâXq^©–Yiq¬Ò¯TË/¶ÌÅ5Õ2Âë-BsqLµŒð’‹pâ`) ¬ð„Î@+fMµ^©–Ê‚â˜6ŠÝJ8ÕR¹&Œ`0pª¥rÍÁ`"aPˆÊGVì *R¡æ{àJrj¾_„Q £œí²àVÂBTÂBT²´^å"·r«BäVAx•CˆÜÊ!¯r‘{9›@•CP!ü"¼r*Q! ȯTä ¯¹„*‡/‡P†9_‹¯æâ9—_ »ÏÂ^jEúò– L„[ñõ˜¯NS‚Ið‚+¡ö&E‹Çøjú˜¥Ë¯¢+ÌÊÆ1…W ­îRƒA뻄ƒXšô¨ð‚âLMzÔxAqˆ*/ÁæÛ*°¯ ,(Nb«'#¼êÉ 8)^…%Ø|–hM™`¬ª÷l>DÅ—`8Öš/«æ *G‰ª/¡æCÕ} 6Ÿ¯É '†«²(Ǫ,(N‚V² v°ú/ʱþ гÄk³ÛŸ^i&ع&ªÀÃ!êÀ„:T%˜Pú{L”õÇ™6ø‹ãz;ê­=~‘ʵy Øc§f8Ñ­~AwZž‡Ú›s æÇP0D[ÆZÃVxÕ°Å` *¶Ò½Š-ƒÕ±UnulÑëIT²­BáE¡ü y ô”µÀ• ƒB”ž’aPb¼Z“ïŠÁE¡¬µ§T ¢(T¨ÙĶjM«ZSD…Wk^Õš"²(XF©š Ã+£$Áe”Ê@0±­¾‘ðªoÑe”ÆÕš„Wµ¦ˆ,£d»žå<'›õX˜r- ‡ÁDxÍ6­=T8ô}H¨÷@U *Û8èœ Õã¾QjtîÄö¡TY\E¥NPb¥U{”²¼Š0(úÎ|ü{ïQ²ç\nÛ,Ô¾è+ó¡St¶•¦C9 —Þn(Êó½°Cé•€űó.в²Úz”–™õ(NYm(ʺót·ÿPW‹f"»úëT…AyÓ(¯ñtâ¤QêüP:cöósra.‡R:¼&¶ž{#­éd¸/—C./2H4¼ã ›/Nˆ›“ï‚ O“Vƒ<—K¸Eº` úâ«¿ÿ4ˆvjè+y‘·, H_qðóyïw¥ÙøZ†YVfgþi+³kbrÞÕ™8Yõ> ömàØ½z6(ŵ(Êíaëò†‹<éÛÝñp:Š–ƒeU&˼±É|Å—Ò›±ÿr%{îI%bb;H~ÉEè•RžÉº›³2ºŒˆS«E $<¦æe¼]ªK&ƒ€<.ãTÔ_~*Y‡Ùxø2îîuv³'+,Õ$«½ÅÖÂâ'}®/éªØø« ÈM:QZœü—(Jl*-/(õ%JÒ+-ïS¥å\gö%5•–Ó€R«* ÊÒPY;cRËÇJÔçK”L£j>ùË¢Y²R2 Jôª~ž¾†Sn*·šÌ(Jüª½òãM%oÁPú“üï}zÆNgµ „ÒŸäã€"~” ƒ‚œäCU_ÎaPVØcÜ=Ô[cOq²´bo¦–?pKá­•-" )ƒ©æ»ù‘P”hôsxö¼UQ—Ç0(±YZ¼Ó÷ú7‹ÌWVþ²æú?9Ì«.æÔ`†2õ¿zekäõ0×B„‚w¦<ÎÞÓÿä™x_™ L‚:øœ`b?_±Q2 ŠÕÁWx9øbG_áåà‹|…—ƒ/vtð^¾ØÑÁWx9øbG_áåà‹|™—ƒ/vtðe^¾ØÕÁWx9øb7_áåà‹)ߨ÷VxùÞbÊÁ7ö"^^ÄØÍÁWx9øb7_áåà‹ ŸáL*¼äÏ)ÏwôWb ZYºzÃ1qò†c Z©Ü¼áH ‰*7o8‚ûko¡â( D@¨`éêÝEQb ì±tõT£(@@¢töî¢(@@¢töT£(PWéêCFQˆ€Do>é( D`¨ ró!£(1ö¨Ü|È(Jb”ÎÞ]%µ‡=JgO5Š‚œd72ŠB$:cD@b ( ±tõ’d@béê©FQ"éêñŠá“®þ÷>åáqáS^>áî‰}ý/¡N2î©í Ã'Ü=#1|ÂÝËãÃ' Ä`ptuŒpbø>,Ú…£›gF _&¶vQìb¬\cøF ß$\Ì5†/¡bø†È·—hD×𺄊á{F#>ƒ’\ß>Ï™8ÆðÉ0(]ç×pbøl‘‚y "†/Њ1|vÿÃ7Ù}×¾„Ã7Ù×¾á³Ä!»ó°•í™CvçaHdvçaVÀïz®< ‰ìÜŇ­,ì-zmKBÜ%о¤8§ ´/V[2«}4$W[2«}´=Ú–œÖº³—”âaÓawF™ºúÃ|ô°ÔÕ棇¥®þ0=,¥y˜Ýþrâ.)ÍûX†A‰Q‹54—·òíKŠ[¬V ð‡I–:ûäK9û}iµŠS·/µº_o_U¥ãùÿþ|vì¸s†Û}©S%*ES·¬²çbí\ô¾ͶxÎÅlï=/Äw%æ¢ï~7}÷çÏÅ ÚmyrMÛ2}ù7¹÷å·íŸ UMDÉË0(He¼J¹é•d59H¯ÌU”בE”ב¡,QYZ±®‰WaPÖ¸&ž‡AyCQBí‹Îf†~ϱ)üˆp³*¨jrUQæA@bÜt)ƒ€$¸é"ƒ€¤0HéhÕä`ûhÖÆ›’Å ¢ÜŒ0ªšœÝ«ÜŒ0ªšhéUA@ÜÒ 3“É·af²„ÍÉÊÑœŒ|ÍIY…A‰pÓ¸ ƒ㦱 ƒ’ ¦± ´b)n€šË7ÀíË 3Àeæ}]\ ðJ†A‰pg‚ ƒã΄2 J‚;Í%EQT Ý_â.‹@»¿²¹,„—Ë‚ª&gº,„—Ë‚¬&º,ÿ|4Ǹ­`¢­VYÔEQ7™ „’ÚPDQ׊ƒ+!¡:’L%¡UUrŠyñÇŠÒ¥ž¹bæÍxXæ‚{ñ°Ìm[bOætóc/–yçaN÷>¦y˜»ø®Äìœ2" ÊÃê<Jp—ž‡åaPR€Sö<,Ð\p–Í› ‡¹qýØ—‡Õ|~œ=L!ô°™ <=, ¡‡å~ Žz˜ ƒBèa" ¡‡©0(¸V𠮇åvŸÐÃæÍ…«‡É0(®"•(¤){*¡‡åó@xzX„ÐĈ£–‡A!ô0…ÐÃd\«­®‡åvŸÐÃÊY(\=L…AÁ㑘»±â‘àH!@Ï¡àè̘LjG¤äaPR€G¼ðiÚûB²Û©µÏì* ®¡àè¹ ƒ’àϹæ’bϹ² „²ÄZ=WÌ%]qZ#Þs.øÐ:o.Üt!ÁDWæ¾€F³^@¥ ‚Y­Uáp_ü_@… ‚z«Jß™°¬Váøzq_@í>1! Ĩ1„’à~ý< JŠ¿Qš jµÊBÎBazÞ*ça™ Šï ¨Ìƒ€à<ÌéNúzÞDça¾3qãaNœ2öäaµaPP–åP<¾"JŠÇŠäaPp–ÍCazÞ*…ÐÃøüØÿTŠ „6„§‡…!ô0OG=,ƒBèa* ¡‡É0(ÄëA }!^í ¡‡Í› W“aP=ÌåŒyëaeBËçðô°2¡‡y΄Å!£8"î ( í‰0(„¦Â Qö…ˆâ´b„VÎBáêa* ÊkÁí£0Þþ’í/»Ó×…_íùË©&¸}ÓP§Ã*Bé›Ó¾‡µkw:vPíýÌ¥¬7²µ˜ÖªÞöÃîòÍÿ·oirT×Öü+gx;âdŸ2Øù¸³œõ 2"÷´'70/!XtýúÖ0IHX•™»jP±Ÿ¤õ^Z’¼-àAÍ+q÷Û¥B¨í¢”vØ#Ôüb¾x|F}€B ö u\BÍfE°W¨Ó$ç$‰¹b¿ …øÒ¡Áø(Ý5Š%§•TÙsÌÒ\ÖøçA0¤f•‰ˆO¬p!ï#“÷(ÅÏÉ»òâÆáÊI ;†WV]ž9ñ±4ãSðŸöU{í¡ˆ;>Ë;;T$lňˆÓBõÆY0½à³@ î–|á'uyn …z“2ȵ[.TAoˆ÷ù,F6 òY`ƒ1ÿú<óIh+š÷Qîb´æC6¿cD(Ž@ìC¤‡%,ÆšfÌ-/ƒ±Z®³|òJ­ëËæ.¹Æ£µÍóÉÚF¨ŽÒúæã¸Ä(¦µª/i™ùÀ˜¿¼óº?··LÇ/%>“íkº¬0^%Æ×C *0й&~0DÀvû~#•ò‚û’Ð+é!ôa«ïãŸï#—¾‰cPXûÁøX˜õy¸ódxþrЄ;3ˆ'£çÅs÷M«ÉZ‘üÒ"âby¿Ü]ÉIY•}ãbp±¡g_œë=³Pµ‰s/úóu—jè.I›<ǘ´2ÏQ¸ñ. îÝ9Õí%½z€8êNj‘â–6ª.ºT¡>tظ9š¡,Âõƒ¢Üm…ãy0ÕþÑ”PÂf¤Ú=܃rTmê(½òz‘=('JQOsQÞ ‡³m{âþ›…èI’ßUÇΠÁ´ÌÙ`_0ãõñŸ£ð(i„_" ¬S'%YÎWÍ&¡E•ˆº»'îÅF®ž`ï·Úg F—BŸ÷À‡µsäú8ø-®5yÚotÎq^QzÖ/K°ßß«bó[(÷rZF„–…Þ`çÄp°""<)æ›yàx3O½€†Ã¤n P€ˆí»4Ô‡ßÚz–†úðÀÒuÏ… 0ù­ ¬? ƒs¼ý³vŽðâ D—=2Ì0<|hÂaXóÕò²r޳úT‘ ÎÊaÖ,¾pŽ͈!>‹ýƒY*ô„€½þ®SGŽ"—Ü2fŽ«'¨è÷&õK”`2sÏÌ%(Ë[ŸÖ[.MOŸ™Ì&˜BÖ )ÁÞbÛ&x˜ÍŸÏ%kjòDd¼‚ L;»Ê[S40Ç­®XÍžk"ÃÜnŒý’å¶x(AS⺂UÐJ¸DÅv‰ÒÐÂÓŠIWÉûE$ ¸£´1è=­˜ô•_² e0‰’C—2˜åî,Š´Ë¥q+QÞ¦Âñ€Âíò€âT86¢¼Ï:@Ïc“)?¦$=Êò #ʼsëžæ ”¤?Ô“VÊ]0úý½å2#¸köÁ(»°g “V–‚%ö2ËÀóï3n˜ $œâ±IÂ`!A`T4~fr–ë®’£3žô؈Ô{úÏ "‹zRïKÜêdÈÀ>¿Dû}&«“ü„l|Iz3/ BëYôÊ–+ÍEÞÂéWuMâ,Æ{ý—¢'›ý|qÆç? Æ/-m&¨ÇˆB/ 2F¦F¿îŒoPIžY8b5î òÌ-ñ!!€ûFH½€„s_€”QãdPÆÏÏ•ž´eSâdPÆïµ«/o îýðD¯Œ Ë'3?Òõ¦º_wdEp·sT_S­ÜöP^»ºeéQæA‹S¹í¸Ýy< Zf(}é å8;|³'.ý ?(§ehTL(ý5o¨Ó…)Ö»ý£Å›Ócao7÷ÕíÔC@1·aQƒÛ?(á<üžJ ¥ÅÞPæ î îšxZ±Ó¬Çý^|‘(ð¶ßꫮܾ',³hÒ­`±¼zU±o? ''݇nå=#J0þaÿ–K!É92÷ƒ.]>o\Õ{-¿æbï»(Ï~—ä¾`ôkFò§×ìÅ®«^yë¶&ÜW{©#Šý (k/õ®ÚKèX{©wÕ^ÂÍÚËcU¤ÞU 7k/žzW…'t¬½Ô»j/¡cí¥ÞU{ 7k/U°«*nÖ^+<`W…'t­½Ô»j/¡[í¥ÞU{ Ýj/õ®ÚKèV{©wÕ^­ÚËcY¤ÞU ·j/žzW'ܨ½,òüzW1!t+&Ô»Š áf1a‘ç÷¸‡®y~¸YLøV€8V,B·bB½«˜ºê]Å„p«˜ ÉÀÁng¯Ìó•ÕAä%Peàõ® <ÜÎó?(ŽÕ„Ð1Ï»òüÐ1Ï»òüpožv ²Cžôƒ¢Éó{AהŨLš¢^@Æ›a¿ÖË•Vy¿Ds?æŸïE¤’劚ÆÊFÛ r@ v·½?(º¶âZz9m?Ö»n{!®¥—Óæc½Š¶âZ9m>Ö«h{!®#Ê«¦!…¸EŒ(ošæâZà1¢¼«R°séňò¡n®ÁÎ¥³VþÒt¤תÈió­æuo q­ïœ¶ÞjV´½×ÒËië­fEÛ q-½˜@tm/ĵ*bѵ½×úŽ äUÓbA\K/§Í§­Õ N¥—ÓÖÓÖÊ êVz9m>m­j¡n¥ˆ®ƒ¸–^L º>âZz1˜K/ýni_z©#ý šæâZz9m¿¾nä ®¥—ÓÖKàŠ ì\z1¢hZ,°séň²Ñb±Û‚9µX`?(ú êVz9m¿j®j± n¥—ÓÖ«æŠ ì\z9m½j®h±ÀÎ¥—Óö«æë âZz9m¿j¾n± ®¥—Óö«æª®êVz9Y¼j®ê± n¥—“Í«æº~)³èJÐô>xBÑu%@÷ÔxGWtOwt%@÷¤uGWtOÀwt%@÷¤uGWtOÀCÇ! §;’ÖÐñDˆDqMÀ÷t%@÷¬Õ½+ºçßî] Ð=5vïJ€î©±{WtÏZÝ» {þíÞ•ÝSc÷®èžïéJÀ®©ñž®ìš»w%@÷ÔØ½+º§Æ›] º~ÝNÅåô ~PM¿tOZCÇÓŠcîÞ•@w¤Æî] tGj¼¿+a·¶8u%P?(ú®ìšïêJÀ®©±{WÝ‘»w%ЩñŽ®èžïèJ€î©ñ®®ìšïëJÀ®©±]WÂj/ßµ+áhõ´ñÃA÷®„£EWª¿Âµ+áhÑ•°ÚÊwíJ8nv%|¯[\ûŽÛ] _k¦¸ö>mÐ~àŠ»|½©Ê»æ®wù2hº^ÜåK bîzq—/ˆ¦ëÅóo‹ª›M׋»QÔòÐù åK€¸ÊWè&_`GW•Ä$_`GW• $Pr^,—+çCûµbŠ«‡6òµâŠ«|9úGÐï±_®þQ®—£|¹úG©)Žòu´°_«åråüÑÆ~­TÅUŠŽò% ¾«|\ã/¼C¾N®ñ×ûur¿öد“›| žÞQ¾NŽò5 8Ê×ÉÙ?gùzw÷ÄY¾ÞÝý#u–¯wwÿHåëÝÂ?~­—ËM¾Þmüã gùz·ðë•;ë7í×ºÜæ.Ä®öK®—£|¹Ú/©)Žòurõt‡|œý#Ý!_öKû°!´ª€‡÷GwlÝ7Mdu‹J`z¦¯¶Úü°@ MÏôê åhz¥XµTX ÈgÍäz/•˜’d'ŠrïVóJ²z£q$Ð?Іq×/ ¡á(Sú ÈBWÔ/3QJü€¦g†ˆÕU±Û ¡þJ#°[ëÕ»kʇ@iü ¦G: ô„š.‡'`7[¬÷б»ŽØ%0]ª¾{ÅÔ{Eš!`³Ó‚½¸¼—ô,Ê‹Õû¿Ì»0f눙?(æW†kOs .Q?(Gsøý œÌá‹'ã+ÃzZ±7sÔøAy7IÈʇÅ_d&ƒn±ØÆ3}ÀG½€æ€x y9š£JìÄø¶°[èºqÄLûviúã—žEC/ ñåRâg&¡9o¼€ÍA¸Ÿ™œŒŠÆ~fòj|ñìvö.‘>nü 欅øA ÍY õƒr4g-žPNFê‰/¯Æ‡³ÀnAvÉö[|Un¤Íó¨”Мç?(Gsžçi.Æ'ºv˘ºN›Mîä¾>›T½bØ@?(ñß'Q^–©1ö˜ŽbsܸÝGkúí®‰ß1&ÆvWø@7øÖ{QZ1,í %õNe=taÅF”žB?(F¯ow?a¨¿¡î—Åõ„À!g9nìãêå«'ÏXȨòb–/°ÄI¾…~PÌòÕÛëÊi£OÓ`$¡ ûõ$ˆýò²a¿v‚8Ú/ìeÃ~Q”Ýö‹xÙ°_è9;ûE¼€lد Žö‹úA1÷ XÕÖ„~ÓúA1÷ O(æ>Ëý¯ÀjkB_œF~PNæÚ4݇âÔ'`i]›Ú´¾ØŠ½€„æb+|ĪO ±-Q6ÅV}õz ÍÕC²W†ª‡ÔйO€zB ͵°Ýlqª…?(æ>êi.¡¹æ²SïúžEYÖ\4 c[§ìŠ!šdc/ ¦`¯±-†OC öb öp½Ä-™h ”À(_Àeo2‘³|õä9«d"/ fù;AÜ’‰úA1ËWo¯+û‹!zÙ°_O‚ØÙ/? ök'ˆ£ýÂ~P6ìu@Ùm¿ˆ û…ž±³_Ä È†ýÚ âh¿¨”ù¡Âx<Ê’–蜖Iq.í¯¹ÿms´0OH¨"»9ÜP´ %9ÄSc¾vE. ¸ –€G¸÷uX8ŠÇ4— ¡¶‹RÚP#¯¾P,‹õ Îg•¥“X$(ò&—×ÌfÅo/f…ìê4‰œö›P¶ˆjŒŸzQ”€VŠ%§•TÙsrñ¢¨ñóU2(5«ìH„}b-%cÄb’¥ø9ÉxQô,Jшϓht ¯¬º<Ã^çušQ[X§²ÁÄ+Öë\ä³tÂâkØèu yûòçíû·°º"|(V›¢¦¾^ŸXïëûsÀÊÙhSŒš¦òŠõ¡²»’_¾äpu¨T!¾ø¥<»¼pÈLò+FþEy„y±†…ÏÉüké’áXC¨GÛ.ùë?8øïíø‚!|Ýþ`¢8®q_?` +¢GÏ#„³Û\|ÚwÚ,‡Y gWé.Jšç†{âÖ!äÙfÊáu‰0›CL7ûô,Þ†´k|?‡Œ¨Î£¼yáýÜ_Yï`è‹¬Ž›P©ú¾Ï=hܯq¯é˜nEIß_=@æ1ÆŒ×IÓî׈…yÿš»c!°b·À*÷i¿¾Ün/רD¸à¼§¾EÒö> Žšø_º¸‰áˆåÎédb…HI›eqÝ' ý,DY„ ¡ƒ&QU{Ý%´êØøk_¤=‡@ NsW1K;T$lÅ|@Ü-9‹ðGÕcq‹àÊs},ÔÛbžD$5‡À æ—àO³ UÐ[ãâã¡°•Ëà†Wƒ"³…øP½ÁšÛÊù¤{Íû(÷1Ãa9ƒÍ#±—y<6Xç²(ת¾¤eæc°¶C‡G–Ož¯¢u}©©Œãr£EgóˆÒúæCèøí÷×CzÈÌÈ…e5!ŒW‰ñ9`ÈÛõ>àCl,ög>œo¼¹4ê%¡WqàÁƻĎƒcˆ2¹Ä =ôƒñ±°¹ópçÉðüå  wfOFÏ/º#“%!ù¥E>f±”“ ¥QÖ]ûP^*é´b[ûß:ãâ¤-áN½ÄJïŸ].½wÓ•p¯Þ÷žP£®8Iq¸¥÷ëwåvØüÍŽóë]F³ãIë‰í­ËvÇ“ÖS/ žøÉ™ØybêdÃ{휉F#uþžúA ÌþÞʆ'ö´bžúAQ{bènÃŒ(¯m!®6Ì¢«n­.ÄÕ†YtÕi£ îïŽ*¨¨âI»¨{ÑFÔ1ª8YDºØûAÑÚ0껜¶£ m„äi.jFöX—ÐцÝã0âåU!Aw벇©_®ŸäþÒ†=¾ô)mXƒ:d³b†k\§òø„´Ô|HPñ$ÈayüoÐÉ»/î Þ;æ/P„æcŒ°‘O|ÿfr‰3ނ̘ßÓ€ÖÔJ¨yCó7„q÷Šù-Ù»„!”ÍH_BˆÀ,ÆOÎä`¡+¤ ^@ƒ®`7] œueÔHì%0k¤§¹„s9šô;éýV¤¿DÁ»¬K°]sSZØ=‡²Jñ56¬ñƒbö’ÄNó+¦Õü'A,ü—µ— žÑ|k/Øh¾ÞKöžæšå¸y ÅœæÕ¦âq¸»Bý½. êÊàáî µ¦~ø,ÈÁëËàáÞ õ:õ&®<ÙS£$®˜2ÕÐW¦Z›’ÈÐS¦Z›ÒáÐS¦Z›2ÕÐS¦Z›2Õpo¦ªá~ì:‘Ï `Ô3Ž  ™?÷5Sî]öëûkxû%‘S v1!—'AæëõM¿GÁy1“£h®ô. ʨe‰"¦ÂQôƒ"£–o~>K0\¦\÷ì¿_s U¼‡»x¸ó;ó>pãýÄ´Äš÷îìå=ô„šT]ž[1³u‘(öì‘0ì(aÁs†ö¨$ÌÀ{è%0óþ¹¹ló^Zª¤ÖE¢Z°½5=½ CÏ,ì¤R!÷Öôôl'ˆ›$ÈŠÎNb­ öÛI³°§,˜-ïƒç íq³ø*?æy½Ðs ‹+®V—C·Å¥<_ êþâÈçßÿ +ÿ_Åäþý/lºâéñ²Úa,gÔ Ÿ‹¼\ú‹Ž—ÿŠkHåX(¹€ËOŽEùÄÀ¥B]Ó%i¾¾éÌïXäP^Ta²Ë±¤ Bô'Ç2\NÇ+ÁäX2XF—ŸKhK%w,â=…‹&qI›Œžp(ÁJ£á]£éúJ}ÏZ(DW£Ò%(t0IÙõ'˜´¼Ûþ.º÷¡dŠÒŠ\~Ÿ`Q>±¨hè¥;LJò²Ëtÿ¯My9ê®~t0Áü†ÅGß à&œßŸ Í(þÑÁWƒ÷ÁœsúW£|þB#2E]üäXÕó3R­A_~t]Âõ3.âÞx>–Œ6ø'Çr4Ù˜òŒ~r,ÃS:ôk54¤ˆªŸË«ÁWSâÕW¿Ø;ëo…³FEÑÿìh„.Ý>¿&™\dÓц…àWï.’mÌ\—îz5Mö“c LòÛþ…ÐÁ0–Ð$1iêObÿÖø¤Õ3_ŠD¶‹kòƒC ÖOÌãP®„6?8”Ðg¶(òç_Ú°a¥E_뜺K¯)üÑÁ¬’»«NÉÕ#“l…<å«Ãt@£Gï#M á%0ÊK‹þþP^Ôσ®Ä…ŸËø â×z,]Gù =æ±¾×¥©.V¼ø‡,thzš®-ª"?9”pþâÊ£7Šàå8Ý"Ï ñN/JZÜn¤ÿÑ¡ yüó5 ElÞÈ¡Ð[ý£Cy5æiÝ_Šæ%V…±4 þäPcÍ»C(zsûPò¦ä‡wkJŸvåÅÙ9?ìÖxËJW‹~f]T•¬ŠcþäXsõäº{b9MX p(±ùûC±ŽåðOŽe#–C?Á"«XŽàÊF,p(±ÜO®ÊF,÷“²²ËýäP6b¹¿:§XŽÂJ`   ùûCY•}4a%üÁ¡lÄr>WåÙXŽþäX6b¹ŸY»XŽþäXô{ãYî‡{·éUâ¢Ü!Är;$|®ñf!¹ÊU–»yá“[Ñvc±åPð·9„­9üm!kþ8Äâ§o’ïݶM]6Y’€ñ)Ì»ÚþgÖÒ4ß™d?âØ\ì¾1Ò6eN{Xe¸´ù†èP¦¾yÿh’C±°åˆÚ¤¨p s›oˆžÝßüq’d…üH…îÒúbó ñVäïÛ?Ã\„7äsÁÍùÚ¤)°ùÆi¾…X±g÷ @Vßx]ðE­Z°o@LÀ¹Vß¼áÒúÈ›KT$1º]Uߘ6ŽÃÙ8¦oã¯Ñ¥¨Ë˜^±Í7¹¨{a.rÆ^5Õ5J Í7¤ˆ|‹œ c È¿qFQR\»ÆæÇ…˜ A“b–Öפ°ùÆI¯yuŸ¦Ôæ¯ë!–£ëÑãºSKêòoÊ›Ëpi¿öYV¡‹Í7Þå7øËÖBcÄš KÔœ‹,*m¾ñ¡7"y•©­ÙJÆ~=˜U> 0h]t-3dµ ƒ9ÃÌœ¥V æFdfàsŠÏM]'V 'þÊŒF$oPÝ”Èj]åí*åí‹2Fq¦þÈËP¡Rk/Î]0íM˸¡W«,Ô·²&ĵ,¸þZ}$Ôë^]»Öê#GíHªärM"«œ Ú•-°úÈ«>0bj©ÕGÞ£‰Ib1ŒâN«;‹¼ëÅž2ì­>¢ÕbÔgL/vÂöë1²a+ œó*Fg÷ƒߘÛIʨÈ_+EÎcÒô½åŒÂ…'l–ž¼,£«cµ—pß¾¸™®\¸PîÊQC*uV äG¾§xȘæäBêÛÅê#¡>0}UACP!bUdóq$¨¥\«ú…ê¶…†é¼ð`x>’ÏqMòa:Cu¸³úHð0 ¢¹°=“>±úˆXØ?ÒΦܧèÊ´î!Œñ2yþ:Õº}søý“¼æWð«µÐ¥‹ª¾¹Y|b¸Õè{øÏ>R@Û’Æâr"âqZ0îŠÚ#껾êIžÛ|â(?ñ)>ÁdL¤ÒõHêÊl&ršbd,E™vÍ­!Ÿx}˜g+ûEW·…Vy› !ŸHßV#jñ‰÷ù'Ä©G)UÚ¦„æg‹O|<ŽBøpþ‰¨f²Á¢xцùûö%¾!úåu´ªãó Û Cšåi*w¿Tumnšq¼¬wï$TÜÆ!%´+Ilõ¥˜sM)A™öÐî# AçVLÊGßvD+/ë£J ©Û”ñælõ‘ÓÃG„ÊÉ$}Ѹ³ñ‘W µmE(¥VyøBZv.jEÛeA«¼ëä•ý¢é·|,GÂ%…$ik”£ÜNØÅ^ˆ‰XYRõ·øŒíØ3þ̶iÏW@d¶í/ƒqg–UEÔõôfó@£;ˆëN‡›o„*ÃÊ¥¤õ­1Ö‡ØÒEðo$U6\ÄC lé#8ˤkPFm¾ñ(ò\õäqï*IzB¯Ðæ_ Y–´=Ä_6^$%ÒÆ×l¹Õ7>–Æu1fIúÞ2®ƒqeBvåî¿Êb«èbÔ‚öÒçv U†DzNf\· ‰JÎæü-;¶®Mcõ‘“ÊãÚ2voW•¤I)c‰ƱÝHÞtbÒFl:[}ä]å+„…®ú,·\Ø…°ÉWt J¥Y|Qœ™VºÏ¤íÐFxõHÜ Á¤À-[‘´ùF ûFÙF„n±F5y¬xi»x3PŽd¾ª óÀW¥ISžâZåXGƪ:®YL @v½i åðçïЙ±C5¨ã®NS¬%”}_$"Í­lUA”]k«Ÿ£ÐÙÛ÷§¸¼B3Ð ºÕYI-á»Ü&„£-f„Q’¡ ®oúÅùx$,FÂU%nkýâÈ`GìÌqÊ!ØáD¦ zJ¹÷ûN sÁHöÛdäz»ÂçzÊ`F™AéÇe|ãb˜é)ÃùÊ!>œ²@èVÅik <»²üñ:&¯"þàóDÍ5Ï‹ºÒSž¦CN)Ó N7qIKrÑS¾N›¸ŒRØn¹Vy›õz:¼M[S¨¥ l® ‡ýUOÉEèö[`f¢_‰+æå.¨)¥zJ.C·/±…ÎUZšfÕ ?£6z© ~IÌO‰)"»B`樊nè)EìñûóKPŽ m/Eš“s…ýhpüþ”“›¿\Ò4¿–·<ÑËmÎF›§ÃÆ-ˆo9-z½$âÑ¥Û'oààò#»ãÒ²DjΔêÍlpz …hòMÊ2‡øiCõ”¯Â^rë•òáJÏMf~pÞ%çv  ?ÞO¿Þßßÿõ_¿î†ý77Ìtåb“[¦©Q™³äð¬!“fÖ`l ¢,HÀg£ëÈB‰ÆÉÒ€aˆB&˜àXGvœ¼Ošdc³!%}ªìrë.²ÓäBRáBÄ Ù’ôŠ BDC&Vò7·:ižfPöˆKS´9¹BJ5d÷®˜¡ Má†Â¨$©†ì}b@šg¢cˆ{Ö>mÓ(»e×\Cö!Èc#¤Z,IÝ—·³XÇî_8ܶk™R‘<×ÒºhóL8Þxm@Ö £“ý6߿Ū€\6t°U©sæT@:ºpN—3:cæS-ÝqA' …¤«Ò(Ñ-§4Þ÷ãÜÃG ¨tt¯šqV9›cZAݽO“Ñù„wfxUS:ºwÝ8o1Žh’èè;¹Ç/úBQ—5]§Óó_‹~RPLý¤gR߃ý›îaœ9›_ÝTºqÁ|]ætMŒz‰tt³>`ÆPŒt .ã´.tºuãdëYS­\òRŒ®Œ‰JƒR¶¯÷~ǘN1P./E]ë¤ÔÑIyù3õ­ GÏø(3g…V^‚÷9“¥.!g”vç3¨utƒ¼ˆÃ Ü˜M'®£$Ñ™Üð×CD†Ïƒ ŒV¸Ô­gx˜÷s»4ö²H¦Î@¯£ æ½’…„§c™Â5.3\‡½¸R\€l-ÆiÞe:9 s:ºss¾i¦s³áƒ¼HÇ8èµÀ ¤tt¯sùät@Êgœ—8Žkíº<ØA'å,nŽ/P;Î÷Þ@Çñ*¨³ƒáÇr~|ŠÃüÎÉYÇ÷ã¯GùœèδÇç⬓ÏãF&;ÚÝãáøëõðë¸Êd¿e^™IÇ ¯Q×^Ïg8EXkBòÈ,oj’ä!O㪚f¸& eÐÃ3Y擲¬9k ÷h‰±…ÂøÞ ÔGðF(Œµ„§{L‘±€I:Á¦…m5í­ïµ„2ôáavšW"<: Ìfñ”p­ ßîa>e ÌìŠò¬iÎú9áÓ{þ„·Ìš;ªKÑ’èÜ—ZÂ)Jà¼ÝÊô’CBÖ À¯e3.s¼z*ž\Ñé)wÊtà#[[fYüJ3Øè)ƒûÂÊõ>¹>ðz&zÊp6Z^°u]šÓÛ5Ó¯ìá8ãI"l#—;¦ÃÌ™^s¢gæá4a2^ð’äiH[wm~…™^ðóØdCþ‚¢ªê[„3dXÛ·™è‰†[®_M“ ªI‚ï÷Ñòœ)“ô%ŠºŽycrÓSJ£Ee•`ÔÐ$rQ^ô+ÜO¦ÄÉ”U2JxCmž×‘žò`.Ýè%! ˜ö^QPª!]ÌL¦žÒ\ )+=¥¬†P©Ÿc`Å(!¡4ºFzs)C¤¡ê#ò!Qœ`YåõvÍ™ÓÓS¾Í(¹jærmá9¿QÊ¬Šžò}FÉ‚\ž¦ðµå¢Çr˜ë)«!ÃV"ccl†ú›~…Â_ª L»ªÀ((ª:J»ª£((9ÚÏ¡v3H-¥=Bm«§ U˜Ëª£ <Þ)sîS„ä‚¶yÄrhÀ<©*0íª£ |UU}ÚUÕGAù&G+J¹b©<¡z«)§ð,RègÏ~X>ˆúZ/ "€0¹™–…"’š“›^ËŽÁŒr؈àq"?^qÅ9Ñ[°c¨ÁÌi~¦y£Ú޵aw‹×ÅòøÖd¦z¬¨‰ ŠZÜ5on¹!Þ;¾N¡i$"EÔ`ÄB†¶/³›Êš¦¢ÚPÏeqópÒQRî /YÞè)&i£Sª§” ý(GLžß÷Un¼f”`yFÙe]Q–Y¦§Ó6E•AdðÈA£”§.ÂhÃþv»±™G™a‰‡{„ÃSaVŠË%JaÍ‚ÀÈÀ—ƒÜLûäéç ¿¯Ž )Å 1ÊøQDØUîõ9¤èF¡a•»"j‘<Ä–Å…¾Oû[Ÿ£úb •[@ŸÌš±/Ô”e줃´Ïû± }dZúññë He"¾å”KGÌ·œ*’Å·{Ú½"”¦—ßÄãÇTÆ QÉ¥¢W-ax·žœPõ‚\ZpW„LJ-(ׇo €˜ÉQ´„§‡Ú÷0ï)†MUi ‡†‡/qr9ÏÁp^˜ù$Ú^ŠD¿8oS§Óõ%UM¢’зXKøþPÞŸo³Ð´N‹›–ðãaŽ÷]9ùÁ:š6åðku“ưcB{˜Ñ©â® <è(ùMWë)ƒiwàñtzÒD×’E7zÊðáŒýÐJÂëÒôÜŸÕ Á¨]C¥8¿W˜1`ÉvÕê)O{5@ö5ñµ¥=F÷½åCèjÉ]‚ó…Ò3žvA”÷›ÌëöWÌ/1Ìó}¾S ¯Í”W!p3Q~,ö 8í K—éWhÜ=û^îNœ›î§™^ú†ý3eér&@?Ú`v-èVöà2c93)¯ÓŽ‚2œÝ€‘ŽÒÇ0ñ QZ$!8.mW1=r)ÁTH;Ç··0䔳ˆfn-¤´–]„¨–ðñB–Ù~&ÅuF§ýÅ5áß~ßm—¸a€Ù®\.E¬%Ôé Æ=“ƒIÚׄZ5É™‚‘iYׄ¯w;;ˆZ rÃ×~ò{k‡V!:@nN‚ GêgviH’Šlq˜]¿¢¦Ó>˜Ùb8½Á·qz‚ÏhêšRÀ¯¥¸òIâJ@­_Ãl‹ù~Chúóù‚ÏLîô”wáá{Ù(è=¥9¥u©_ØÑ̲P„çÊ@^ÂÑÿ§ìOzäF¶­Qð¯ÜáûP‘'=à 4©‘Pâ›ÕÃC!¤h,è Jt—D"}ÑØIÛ{-å¹7Ï—[³m÷Í[ÿôúö\ßWBÏL^T69ê4ÿ×·ÙL¾üv}îû×?_å/ÓÐ^˜\š>xðv}þýóýû·»ü¥ÙyÆÇ/ë÷_?_>ÖdÈ—ÙùKŸ4h࿾ÿx»É_æk ×[ösW“áËïÝ ö?wµüåÎßâÖZõ·ß?=?¼ü¿,c¸»5ðÈ—ULëw·£ÖùrÒÝG‹*쌷þãwÿC¹•Iwó’†OÝr¡OíïŸ?Ÿž?~)G´èî£ÚïÓ…&_MÿööÖµoíþÒÕ û4ÅfüéŸ~ýqý>låx÷ºû‹[u÷î¶ÓÝcŸî•Ó÷%/㹄çS³z"bŸnêé×AÍE û{ûý£¹7ïß•O‹ö>-ØK‡º4°ßʧ寯aô£}þó×í­{{í¾ýT>ÝFÝv "¼vÊ­»½)ŸÎ>nŒ,ŽlÅ‹3÷üûû›{nŸ¾)Üa¢&ŸïìÓ–geüåùåçï×ßï 5ͱ¨1.äË(¦ôöŸßÿz{ûýÚ¬Q¬Ø§iøé°^OüWyúþözu/ï ù‡Ñ¨àW […¿„4_æ´·º~½u¿†3~ûÓÄžkš؇£qsIPwûñÓÝ_¿ ¶üe “­âgw÷ûûëÓÛõ㵕¿4«™4ÎÑ›¬áR‡Cúúâ~|•¿ ³L^&.êé·÷ñé×Þý’¿ÌÃ/ßVÛãç ¥¼¾v¿Ê_No¦[Ô”ÉÊDø³Ÿ@èÞoò—a¿²µ4á×ý÷ÛÓõÏŸ×gål«U´}U£yµ¿ûlí›üåô`—/{gÐ]ÿµýuW(ár2‘‚×U®з§'åÓ]«×Uy|»5oýŸ^¡…$ÝiHsB•×ɾþùsß¿bŸš:÷¶æ¶}½6×§îç‹òé.½Í½®Ÿv÷{çº'åj‚ŒÈ¯ßVõj8áúúôöu¸åÓbMVû6«‘þr¾½|wí§ŸßµOË-Ÿr,P˜ÝÏ+þýüó»v9Aª›«ãz‡Oݾu¯·ïÏÚ§AöÒ,ÌGUòן×?¯O÷÷^á—.éÞæâ_?îï¾<9åÓÍ;Ú[³Õtw?^´÷×'å­ÎYísjÐBß?>ê·Ýo™Iqyœ³Š&®ôûý÷ûýëkÿõ»ö«Ù¦¼¸×å¡¿ÿÚ|½ÿ¹]ö&¶OC.ü«ëŸ~¿þiþöª|ZļÞõÉëW&)†ü§Y‡;zÚë“§=òeÔ_^Ÿüå‘/£þòúä/|õ—×'yäË\úͽ¿<òeÔ_^Ÿüå‘/£:w[Ÿtîó—Q»­O:÷ùK+y®›ç:F ÕÕ¾æ5Æ>Mb®öæäj} üåÊVey³×¹#Ÿ†ýŒß^f¶ýÖ¶¾7?ÛØ1mZRøåä-8ÒóŸo¿~ý\…"_Næ_ïV™¬‹)´ïž~þxúõþr•¿4‡¨áû«û’¼ÞÈ_f›7ùùeVuÞÝýûÇËËýiàhò—ÓƒùoNšŸZûíe8¢«{ÿ©œPØ£ùÕÍ%²^ÈܺövûùSþ² ¿\´¤áËAqx½Ý*«Ýú1û2A7;Éî?ïÓ½¿oîŠó—v÷›«\ûðY/{R(á3Í+¾¿5·×¯÷ÀÓùtÓµ½Kçu²ã_o>νúnøçOÍÿü¿þçÿûÿ³ªî…ñ˘•7>óAUÿèºõúø|«8}y^Už··§¾¹5ƒÒ>7kî¬÷HÎQ®mÿô~}yºõàó TéÛóû”uY¿]ÿ´O†süþ|ž¯YÏSטÝàú¦oþ Lç>/B“ÙÍù©ÏÝpr¿»ß÷7ôë[xf.2˜ªííÉ]Û_ø¼ j^–ZßïÏFúõëöñ >·¡»óuÎ0{îÚ·îþµ½¶ïˆlŽÝ£¿¾=} Løý.lãfå~,%¸_]÷û7ú>Ôð_–Òªaûßî¾æeÍç¿7kJÁ·çÉZô¿ÿíé{ݵO¿"Â]JŸ¾<®)ñõ¬:ÿq¿?zt{a8gÔdWÖö­{òóhÐ÷ÅäÖš 剿×ý¯_ïÝ×÷ûú¾Ü¾¸Ää¬ü>H??›×›Ÿ\ú¾Úr_Wòëßþº^ß›æé }oü¶·‘|¼>4Ð_w»½]¯ˆï\vÚÉäÈöÚIûãþã½j'»ï“ þüùmî@>¼¾oŸúûæ «ª"+Š1¥Ä\þçíåÇóÿü_ÿsù›KV„A•SN;huO¯5”ªEÝå& ß“‘ôöºJ0÷íöíÛíùù7 ”†;¯sÈz`0ƒ@zýúãÇÈìâk«düþcXÐÓ·~EYÜ=ôqtA \¶|ÛÐò…@…dß÷v0*c)…õ)¥Ðç7¶LQ½cþc}Ê<M¬Oéçôá>Wóüa4ù±>%?ž?ÌcŒõ)ƒñüaK`¬O ŒçËX¶e}ʶ<M|¬O‰çmüÃcÞc„âi·cîbäËxÖcM|yèØ¾´}ø÷{ÛÿX|"Ef‹‹-Sÿer§síáá”_×ZÇó‡»a³ù1†÷¯_{×½¾‹šð‰¾M9(×ýÛµûÖÿ\­ó‡“àßÇMÆL¢}z{k½÷×ȇɎqÖ¹Ž÷Ý;£¿»?_ŸnõwùË9£éÓX úú²Pzÿéqroä/Ã"Kßcvc¿»ïÜØ‘/³£ë|üÍÙuþýëùË|´ãÉŽG{ûó«ÿyíä/÷Êóô|îúúvï?î×gùËruF›Òv&/ëÇû@ˆƒÔUn¥ZãÉ߯²úñ„¾7ïßšú[óþ¢ÜŠ= Õ¨gm÷úõÚ¿Þ×ÀZŒNY)o“¢{½º¦ùú[¹–dó¨}›RñÆ1GîùùûŸ{}Wh!œ¼áu€I½|ÕÍïûõC9ÞÙòe¦Ýµ&Ã}¼~¿šÈò«e^&iq1Ç—ý_Pà5jBÏõŸ§÷­ ÌùÃ…æ¿DhþýmÖWif²Ì ‹Mÿ'È܈c9ÇÞº5ݵy¹¯Í*bŸ¦›¡ïÏÅ‚øxˆá¶QCìS£ªjkQÆ {Z“$v4×Gå3I‘=›û¯3{Ìý?·×ßî«Õ,~ŸªŒÉ-QȪʳ$+ÍÑI ‚Û—~ÓÛõž]ÙGWvø£Æþ/Üë¶¼X›\ªÌ”vÒ‘‚åŠ]ø‹ÍMy©LºËùî뇇ÿ|ûúíëLÛóFÆôÏý>ÿIöÞ žæ)÷ç}=ü¹É ùçÿóœüó¶õ‹É’‡ŒûóþæÿÜ ?ï­fÙCJ·üßÔÁ÷më÷šYêÏÛvÞ«}(ðŸûR¬q1ùå¡$OÒSAžrkNòêÿÜpks›þœY»ßª?™¨¢ ÿ¼uþ(‹’ýóÖo¶¨àŸ·ó?~1åå!)I*ÿ>{àŽrzQߣ£_ÏÆq™?TÔj&ÞT–<Êq5%‡Þ»ñä‡?‡èýôO3ýy¢}_Ï>-¾zHÙG2.Ç2›Ý–3P=¦âª ¹|UÕðJ(†3Ë‘*eÖ3®h$Ê<¬Õ‹*SpÓmù¿Gøí¼åïKâ|9Xeð|ºÝù Òß—§µyý9Âߘ èUAžgßò¡*‰óì'zñ+DÎÓú×ó´pý](Q†¿7Iß&ÄýNÿŒô3ü}š’¬jÆ'×3IËÑóúÜmFݯ§ˆQÈÙœÅo׿7äù\§¿O I?ãú!½õ þH϶$Ø[ÀmňŠà~z㔆IáI.òÚI½K.ť܋w<~`H’X!cö<ëIãy ËiAʼéÃmºŸUìñƒŒ¼çåƒôBêl€\2FPn”\r޵o¿PPZÐ k–{(©‹óos>¥Së,ÖÒ”OýBÞ«ÉMZnr±´À™IÃ2›9Òü,-BæM3oz:¤vÙRÕ»PU÷d%ó ‹õ›\c ßØ^’$¤µ1ó=ÿIIÁ0Þt’œ~¦¥ûüAʉ†I´”Œî2dI‚•©.4jüĦÛñ"¦rúæSÊ2Ëɇù žZ×Ð’BÄ`J’–¦JÌ*gF6_%D'¥||q %Eý–{°Ä/L´·~rvŲéA1¬(7_\zy0 i)Œ¿& ›Åô‡”ðÌ+Ú>ÈIÒX>Èmu±ÖüyFÑÒ,Ò”òjŒ¼uú CäÝw;]cø 3o…¢÷fðX7‡ÛøA…Oiµýyɽ‡ù” –ÍÌÚÌð(“‘·_ ÷0«³JÉ7=üýÄŒSK©?ãE¬XÒîæ_êBÇKb.43ž.Î$œF¶r ÿAEšÛ˘·öýF|þƒŒ»ó±úZZ<þƒ¼"Þôªœ˜”²áüŠ& d qJ}»QëðñD'Uº›?À‚½¸·ÉàºÐ/”˜áÅqì~Ö*MI‘F°B÷^ô¥fþÀRט~ÁR÷ЮÇðA c5í?Ȉ`ÆêNò$-M(»ÐšÀô ÃiÉ< …óùHmfº‡,aÙ,2è$”“ ”d)C|id“÷N÷>0%Éî§2ÎàXþƒÌÖîÈ—²œ:V µPÆëÊù2Æ*‰Ô%qvï5óøâFJšõ¥¬ ¸wè×ðὄ²Øg£)+±f¼(ºÝü©89=ï¡"ˆ/ô: d¤ê0߃åP3N…›™ÀðAAʇëüAŽ9_`–ånÓ+-å #vGòžŽ5'T‡éE·Û/a¼Õùî?@Qý.ô^ûFæ5‡ùƒ” ÖùÅ-lfò‘7gXEVž±òa&<'ì¸éIOä=|`(M`½‡rïnç›>È3RYŸ6]0Μ@d ˜œ3ñgâ£<÷Ӯ׿†[½¡9cÍ^¸ås¡dܶÆ N©¢ÂuíêIÌ->¥Ùðk—à=Ì´4Ÿt„lŒì:¤&p_>¨HUzü ¸Ðh¢Öáòûnþ /9®1qï‚á­³Pl–rÎj×,~q›×aøÀ0I«ié?¨Y°‡<áÐDÞEÊøÈ&Öt¬†õrâ?¨¨73ásáœjó= XΤ™¼pÃù…ìÓ)e\Ìruª â=¬Iã oÝh)§ˆoS° BíÃyJ:û§MÔ)m¾Êá“pÊÉLKÅCAÚq3()ju«…R`²ø*·RÒ¼|]¨7=sïნӗ–7]ñhù€ˆ?ô-Y‚kŒFÙr¬–9%0FÆ…á„ú5ü±†äm«ì»…â?°¤v?’wyaü|A˜sø '}nù àLü™ø†Ê„³Øç%Qy£”›Ì²2åt¾•øÊ”£¥Õ¿ä?ÀaN·&,”dXg:%R­»ÿ€ M-ªÃðA–SêÏL­þƒ‚äÞÓ²‡"!à ÓMç«\MËᎠ,/΀2åv–âðÚC·ó·úXM`:¥‚pnŽbw¹émz±v—T‹›› yCf<ʇÍB>ÈsNNÏ÷`©'P+ÇîÝö,á÷žºó= á„-J3|@ÄE÷i <6ù°üBž‘ž“eÓ…%í¸ñ¦« ²E—@ê¬JW$÷îïJ8Ïúz¬U‚=‰³i"ï ǧgV9ë­þÎõ8Ÿÿ^\è¶«ÊÏ·¹Z†ŠŒt„Œ´T¥Œîø[+Æå5Ffõ§¢¢eáç?È963Ÿ’!|Æ£ëq6iªŒ‰eBqb3a¡Ì±¬yÓ9µéµˆ`ü £¨Õ­Kʘœ“• äé_ªçÊ„Œ4MÄW°vܲé’ÊÙò—†ò gZÎT÷^«-Æ8â[ÞC-öÕÄ_>Èr¨`aÎáÂÒnrºÂ¨ÛeHÙËCeÈà×H|6¡=‰ó/$Œ-:1×å é(ŸÈ›ÉmŸØØ,؇² eZÎÇj¡|ظ÷²‡œU–%å– XL¤aS†/õ[b5D@h±["T»´»ùƒìBŠÝig?¬ ÖðA•“N„éXIî½½‚Ï:_»üãuØ™-˜cu›È²DFÈì ]`3“f¼üv"„Z¥e(8Ão&¾4¡hi- ?(Is ›?€^é0ÛÎP1öt¸[pRtÒ—RXÿ°é|õüAnIgÿ´$ë[]-ãç«Ü~ÁRÑåÌCyáDÖL­æÁf¤ý0RF½é5õÙ'œ7/)ãÌãmÓAKAŽ®ÿÀ–¤ƒvú€ ëLBn~@9Wkٯ䓜¯ß~!·¤êPÏ”–ô:4ó•!Uéé "-lÎÁšöP’¶è„?¨ÈÐÔò y¹íff\rÞÐUuH+†ÍlÉþƒ"á"¯“V™Z¬ÝÏrz& Ë©n(ØhêÂtÿAI8™ⳄƒvλÕ\H‘µHQ¢n· +]ü'ØgÝÛ$¬ï~¾Ãøù‚ÔgÿAQ’^‡åƒ*'R÷僂sÏKJq9ô^»Ïpì~ö·Ž䔿uû…’ô·NbwøÀæ\²Ð|q†k°J ÿAÆyCgZ20(ß……+þË9¤fÞê?¨È<²é2ÖÊšR&cØý¤¬O{È9}iÉ(÷ä  >`ü|«“yø H‰´½‡œº¸Íb7Œ7´ÝjËRS`×c˜ðä?(qÒÖCñT†³æ_(q&óì„›7]âc sÖSS!Î7û—íÞ@Ù¢‹Œ3TÅQàçóUæTS‘•[ñëÂ*BÿAráŠ-ç]gBašLËé\³„âÆ¯ô°Q—ëòAIšìÍüAÁùâç›Ëp2\¦æølBEågÖ—¥˜môA¥¯ÿ€eßÓ“Ë4êlg†ádAÔeø ÈÉ(d=`ÑÊ\3ßæ´$“n§ŸÈ7óÄæsÍh†¿}S.©mI˜\ç$Úé"`÷’¥»\uŽÙ>§<ˆÓ T©}7Ëœ½Û®¿@1švû¢ Ízs”í7j}3g‚2eKéë– Î ¼þÅñ·s-¾iûlFj¦S"²HÂÔJÿA‘sRË-$—œô“Mçj¹r€%QŧœFÓ¯TTÝr®Ð纔e,çj /V»uXMó  öà›Ð“eÓ)ù®¤lŸ¨/O(f¹‘kŽÍËEÌM¬ÌãÌÇM³Ì™˜\PO3~PÚq=P1æåÏ kq~@ëPT‡ièãœv<+йa|}ýšvë?È —ãêÖؘÜmþ ¸6Ä}þÀ^H¶^> Ëùƒ ÇFÓì>P’zËÈ Ó,Ìé?((êò Æ?¤$åQýÔùù’$!}ÓT5—ÛLÞœ‹a ªÿ º6r3` ÐZ~ÁV õ-ZÜðA’2iu:&NÊmñ&ßp"çânýÀRŒfv% ”¬ÕÑ-¤‹ó>` .=yºjÜÒbRvWÚ>(-e×ÌÇZ©Œ³Âî–Š„’Ôó±0Ǻé‰%´¶Ê&ÿ-É…iI)·ém)Wfº2š"%Š|æ ó´Ãøuû-3Ñw¨à²¾g}ÝP0hñU†ÒÉ6þ=|PV\ Ý|¬ÕR{í:3~`)±83×áƒ2¡”¸åârÂH *_ý%W|¸ÜtN=Ñ5:- ‚ø‚ZÿA’2x9íºDaêÑ¡Øno´$Œê0˜?|€½Aå^ê§%¤r|_> ø}°‡ ¹]'‡âÊï‡lIF '^iYúž¥¢o Á$®> ÿ[ð²~`I«}ÙC‘pŽÝíÎ翼 ËÜôÖ8yü "ÒúVkø J)«fv·ø6–ŒPW&Äŵ[m ÿ H »iÝCIHÅ]"íðAe+9VÿAF†©§SJ)âÛ´“ËÝ.ì8á?H’œSçc2Ø·1ZóÍÈÉV³fý  ò+g†?|På”HYöÁ·n—d]âü™.¬ê?°¤wp|Ô%1aqwóEJV¼¬d”‰¼ÐwN„ƒšKÿÞYmä² Ô DØÀ”ZlÊ@YìxòmÌ¿PRž„-xø’ëâ`¿-Æßú UJÐ÷ÆJÈhº°›‚ÿ;QçXø¤Y–îÚ2§ÆÎkb»Aɯÿ€ÌÖ]^„%EÄÊ™,n:±øu¯Ë9úÛ> žÐªìT†tnŒÇZÁÔØ™YT%Y†3kEJÞ•÷½<º°¨Ø@¸¥‚’®ŠÈ ›°ø gêviÓ~$â… Mœ¦2„×|Àr®„‰5ù2&¼0Žáƒ’‹xT”¦¸í¡JIÿɲ‡ŠpAnNNÿAÅ ÷~ù IIUqâeU†Ÿu¦@V0ÿv³æ¦5A“tsÑ,T†tâ/$.ø7«àþ‹¤"3J¦/°7xnO—eé’†??ì’zC›û¸"ònv…`ã¨Í”³gîTa»äÕó%ã_M?Î3å’§—s²ŒôÝzOŒ ®¼ÆbbWÉâgŒ&™æ2~a/8è¹s<¹ÝZ ¤vE<ëæ*¢gþæ·P¹h[.ƒŸ•z1Œµ°'›Ì#,È>`ò²6açç¥^JÎ~Ÿ”3kÕ)þƒ‚Øõv°†ð6…ÉøÖ@vv7­WÁä÷ÌQô‰X"Dׇ} |ÏKZðÓUäœNºú›,‘®3gÏW—“æÇ"PýôÚ4%ÄÓ® .f½QlA©½[Α-)úÛò-ýœÑµ\uÉh6‡jøÀ¦œ'|ÞtEøñ\rd9Á²¹´†,Ó)s£ ÈõÇ"æÍ'ì'ý^Xw~½|‘Þö™Â-Ž}v» {ÿEÊ´¼Z²œÍå¼Ó~M;2¢aᬩŒ"{ü 'C“ÝòAAÌ×ùƒäR‘ÉVëIEÙ§E™KÊ襛3Ïyl6ø˜¾°”wnæbP¼~a7Ë]¡tâò@7iö[¿H™lŽÅic.Ö$B/½ÿ I åÛró9$©%)w>¨œK:ß*Ç¡†9;µ¿Í0WÑn4›s4»ÖHŒ_Cú¸§«(˜·Ú¯v³Á½M¦h]¿þ‚Ïç¸>zý"á|Ûo€vÒSg´íéUÌo=¼¦/ ’žnƒI3™üUóÙZÂêl· þƒ’:Úvû›’^ºzþ€xyíVul’ •ªµÆÕýiáMOÕ·I(>;ï:I /xy~zvz!ÓÇîë)ç ì›õ Kù3ç»HRš ë&MbpØnΘXTb˜tõ­GƒÿÀÒ±7SFpMî!ãÜC9aá2.Û’,W”5+DÃIj¹RyM96Îû S¼ÿÀ¦drÊ}þ[.s¶í|°DoÈ%ez%‘´Ùné‹þƒ*£ÔºeI%QòT°úlIÔ*¯Â(ñ¢%#¨ëxÊpÐfüÂ\8lf%ÛcRü¦k&Í–ga”‰‹Wâ6PQùÞsâ¦ÿ 1–ô¼g›^÷˜k–5 $‰%]šãËK¡[lõ7Î?‘]6‚^$þ›ÉEKHgü€Ñ~WkÇŠO 2 f¼Š4ÅÛá‹<¥Ò#ɘ ¤ ÖjüÂä¤ kÚyN*`‹vTäŒÉ·5añ@J_ãmÓILFe`gø2gjŠÌÜ/JÖÃ9ëþËÐàbÉ%e—y5þ‹$å$øº‹„è°Û¢âh7uÊW̲&ÜøAÉð©°!ÓøEfÈèç¸q_ Êf)Üç’,c¢ï —8»kóøM_Bl,&\³~AeV.œmü"cÞÆb&Ž_X2_¾È2²qú"#¤6ÈK>`|[šÿøEBU7¬4’“‡»§!!ÿ…±¤×eÚóÈùñ S‰#ÍòÑÌ.ÈŽ*+bKbÇôŒÆÓMëÇ/’„ò>Ï2vü‚ÔX·ßÈJ¢ãîÊ­*Ï­JÒç¹~‘%œûoû‚jm¹ÒîXX’n°ûòEv!’Ö8Ž/4%c'¯;OáÎg*Y^­/qöx™ñ_dNËÏÊÀÓ]$Ô,hÇÒ*Ê»Hÿñ‹’È7_meÿ…±da:]°éÂ!ãçÚšu±Š{µ'ºÂopÉ]vn±E°Æ±Æû°*}a­‘0c}•¥$íòEB°ö°ÂoúÂ2Í»ç¿Èr2Þ2­*Å΋5–:>(kˆ2†°*pü"azé­ö–õ¢¶$£eÝòm¼‹ØúRjòðjÌÚ‚¸ó>>cl‰oº]ðÜ‘dH¤Y¾È2<µþFž’Þ¤ñAÙŠ*D X»ÿ"3¤ÃÿFv¹À;_”¥‰J²±$#¡2¦O_X2^Ý_¤Œàl·•] YZ²¼óñ‹„j/Õ.û0p‹[l¢’ñ‹Ô>õ7²Šô“Ogåß !£’Óçäé.JFv)8¾»*–Ù…TwWßéô) æU _éùžÎª‚vójþo_̪¶}øÒ®„“8ÓY%Ã,Ù ÂH%IBä˜-2²$…?±ÅÛÆm$ÜóØÂŒã)‘3²êJã™%ãgÓQåŒP 2×Ç/ÛíÂàÅôEÆ(³¨Í’‚°WÂ’‘,ážÇVñ3~‘gT(z9]ÿå ÅGæÓ“s.¡9üÂRjɲsËdźÍS9}Q’®õ j`ËÊÒá}·¤ÕÌgc&Ts€eU)ÉvWý8KYºZÜDÓ–ôÒNû(¡-±ÙvãªÌ…ƒA†[6&ÑU¤#ú”«M4~At0Ù|™Ï?K+2‚q]¾(*ÎâœîÜQZÒÑ7í<Ã\tÆ/_LERP,šùd¬ÔÙ}‹Ãrü"/Icâº|A´)ÛR¦/8Q;S»©HQ»r8ÿE‘P~‰yU>1©(Þ>{³ Ç”–ÜÉå7 Üù"qf.ê3tRfÂÔªèû/ Ãñ’~ýªd:‡,§ëhŠœ2?fÚÓB&Š¿îÃÂߨœã>|¦@™’^ŸfýÂJ߸*•/JÒͰ~QNâL§ë£ò6!Uêé7J†®Ú@ø {jHŸÚ¸ª"¥8\ð Ìwg-cÙ‡ÿ¢LH×ö…%Ý ÓªrNFm7X0|wqF”X”L:r2~a©w¾îc¸A*ie}…¥bà[01ó¢ŠrL,NÅ1”m°Hg™(sÆóº|á½ÔÌŒšÍšð_ýŸCØ·$#úÏšeE$×u;}×Q²:õ¸ï­X5þ†Å7¸8î‚/Hî3Ÿ•wõUiMû¨ µoZø´* W5ËÚùsï`© Šû,_ û°)Gíëi’R–ðòþg¤î3~ámg[:ƒ?Ýmëð›YÖQ{ž€0ì´ŽOư÷îÆ{ñëþ§·q!]tBÖ#]®g%¡*Ä~¯¯#{ïjDì†AÄÞàudˆØûbä1b¿Ö±_ˆQÄ÷ÒûkÕî†Q ®mУÛ0ªøÝŽ1 ‘mVx0Ã:Àƒ h쿘ù@4.€$èÙõÄJR‡¸+â!ˆÑQß´7$C‚ Ö$ÎdގŠðÄ– µ¤ToçÚP+©Wl‰•ظ¨™'Øk¢&àh˜µÊÛI/$kí®Cd­ f­ f­5ÄÀ¬µ˜µâuˆ¬µÁ¬uÁYkYë‚!²Ö³ÖCd­5f­+‰¬µÁ¬uÁ¬ïFf­7ÌZWÄZ¯ f­ø‚eÖzìuÁ¬•Ø`­7j%˜µ+Yk‡YëÊÑÖúe‹w'?l0êBóêñćw÷üü£;!Œ°´[ÛAŒ…µ~ÞØ‘'שUÌp;uƒ×±˜W«ú^oãd»_¿~Ü!ÆÄZ?¯ëXØ‘Ç螺¶»ãuL´Ú}ù²Ðªyã:q´þŠïef­Ÿg:ž‡¿¼d^ù!ÄÃnlÄÓÇÂF<}^ÐØeù²ñ¢á@–w7¼9Z‚ÊVÖúiÛŽ«·í(¼(1x<ݯç÷^7HØHß ¢3`¤xOòƒ:.©‘AŒÊFÅF ÉF´1*é)6bT6ÒSlĨl¤§ØˆÑÙHÛlĨl¤§Øˆ!ÙH÷"°G±ñ‘^e#†e#•IlÄQlÄPldÐ];b%h\ÑèlÄQlÄ„ld:X;ËÁdÖ|ô£¯EÚN¾×F"FÉúV’ü¨t_ŽZ€ÏT«þüÖ@ #%C7Jò½62<ßÇùzgjöá0èš"µæmäl“Lç¡Ù$ù^‘žoß(‚&ßk#Ÿ‡eÌÆ g:ig÷ö~ïûkÏ´Òž¿ˆ1³‘OŸ¶uLÔ>­£é{|/ŸL;Ð<ÞL’Of¢2MÏÚˆªÀ+WS¾A’wÃÀ <ÆøIÞ CTà;$y7 QïäÝ0Dþ†$ï†!*ð’¼Và;ˆ!*ð ’¼A¾#@°ODVà$y¨À_‰w‡xL$²ß É€`^¹ (ðÁF*V¿B Qo6R¾!ØHø†`#Pàk‚T@o6R± |1D¾#ØHÅ*ð ¡bŸª¬Àw©Xþ~à X'V"*ðÁFª³tb>Û+ðkD`ц˅Ï7;(ðkTaÒ<z¾ÙN_×±j|¾Ù^ÿ2êv½u‹Ÿo†øÖ¹‘^ñ™"~ØÄ(ÕŒkïñ:¯êÍYÈFþ;*ðžÆ îãW¦1¤À«–Døq>Yý³ý‰ARÑkíKÚ4r/y#1¯õèÓTȽØçD½ÖÎéä^ìóFºÏ›½êow²W‚÷êÌbd¢×ÚŸ‡&­Š}ÞÈçÏ_bä~uš×ºØçˆ¤:²Dˆ1'8ýûßLeo Æpß=‘õø<*Ñ?Û÷:_.öy#hL–4¶sÏF4¢©ØH§±½{ö¬y Dc;÷l×=ξ™Í'Ro÷¦ùDŠ£{ö¤Mç¡ÓØÎ=+ÑØèÁë4ÖË~•bïž hl±ï'»«tºsÏ žDc;÷lÜï6¹æw+÷‰šq¿›OÁQünå!Qs¸˜ùn‡­¼Ï´Þ{&Ô9¼#û̆½h>³rŸ¨)Ýí¢­!F.ß‹¯¶PÕùTÃ>U|1²JÖ!Ÿj’ OÆ]‰'£‡!Cl“éqbÞLÆôdÚ†x2zÂá0ĆŸL‹1„'Óã0ĆŸŒ¨^n“éq" 1ød"<™‡!!5ÒõŒ”Iuÿmá¿aH†ÿˆ¡j©†dø{ ]KÝ0ÿdžÿ†!?døoÐðoˆ íÙ¥¤áïðy†¿Ã†@cÐðw˜@”'ƒ ÿDÊ&îâÉà+»OÆ_Ùx2øÊnÄ“1ÀWÖOÆ ÅŒx2†õ•a ì+Ã{Á¾2|¦¢¯¬!žŒ¡}e ‘3âɘ³¯ìàöiÄ:¹ï b®á±¹Jî»B€ÉÆœÈ}²1‡'7\ °1…1³¤º+mLï£j †fc¶àbŽ…›ióºëðpE±z \˜Ã~”kY!RÅsè®ïýµ…Fq¶õ½æY!2Éx¸!¶^=˜26 Ñxhñ°aˆÆCƒŒ‡ C4jdì=vñe W,³²BŒåv(–kR¤u(–»aˆ±ÜÅr7 1–{C±Ü CŒåv(–»aàXn1p,¯CŒåÞP,wè”ÆzœmðR±oî®ê†öèœ>é†SLM7´çt¤ Ú;êUÝÐîÓS,÷ß>†êœ\e÷ÎéXÆàxšnh÷Îi…Æäª=8§e“sìÞ9-Çr{9MÇîÓB=—®‘Ù½sú¬L ŠTùØÁ›{T¦& ÀÇöÞÜ“25b >¶óæFóZLc)¤±^W¦ìÞ›«ä ȶº=xså|•>R._@¥ÓÒ˜ÓU»÷æÆrRË€ÃÐXrRËu('eÃsRšÊJ“±9) ÄÀ9)WˆsRð^*%’‹d¥Év4áAc6ú ±Ë|½b´ÂV%õ}N{´о“ärôôG*J‘Z€¤bi+ÒO#Öƒ"¥.ÉÄâV¤¡ ¹ ¢úvHºŠ€@ÝPÌÁ @J¤¤öÄv*AÃôÛÑ5ÌÄ*Ñ\Ll¥nƒà\¿D2†pÒa"›Ã™zˆ@l§ yœÇ÷8ï0ÌUT4qyGœI…X´Jö¥Jl«Éüá>dÆHØ(0Ý]ßüÁ žØÆ¾’~%k_Éaúç&l2€\³ïP¾Ý€’f ‰±CIŒH*gÜlÊÄÈij 1ɤ|ÊåS 9L†$ΤPÞÖ–<˜ÈÑÊÑ D”£ ”£ˆ(G(G7QŽ6PŽn ¢­¡Ý@°%@°m0ˆ(Gk(G7«ô3è+8ÉÑ/G9Šü,H*6°DŸÄˆM‘—$ÉÄ–Èå€ä‚ÏÇ·$Ñíñ:[úƒ bSD`ÂÊÑ^N° @¬v&äN‰œz=!wJÐæØ'B¹S‚>Ç#’;¥*w¦þPî””Üq²³#)”ÛÑ3$ž‹¡1XâÔG\:ZS#Žjh –ûÔGÍl ¢2jn'Åb”WÆ {OÆ È‹+c…½a^Ü\Œu…U ̨ Ô:«7¹ tVo šjuZ ´Ålªq&…¦ #Š50“šêe,Ñý Zx P¬™œ^{k.L2 0š ®É%Î$/ÊS2Ìc4M°1Ó ¼RÊ{¡5fÚ@R¹Û52U*äuc3]VÈ:è°ÂÁ¯š*t‡ú•S¥b?¥)z¢5OÉ0U¬®ðš$n¶&l‰Û­ aªRuª+<«å-q;lªRà …2f ßìåµÇ*–£~èåµÇꔣþ™g†o§„c‡o‡MU’ɪ}ŽºÀÙ€¦4€ ’ÀjJˆœ„ 5¥ Dãl@SÚ@ä$L¨)m 8¬O¬DKê©JöÁè©JmS•VŒTé#œA:ƒ÷¥…Î Â}i¡3ˆp_Zä šdu-ÖÆRºOýÅ›Ûâ”îqÄ¢ªÅÚX›Å£KœIÜxÇÚ™Äh3³ºÝ!Fªt2Ç>d°øjˆÛ)5²SÒËÁÖ‰{QU{iÃH•¤ýVÕ?ŒR_ÇÔ«À)\zÃßM‡:/ )Nø$•³'Aì<1êÔ°^¿šã(¶Xñªþnüýâ´Të @RÉ\º¡ö ˆz&*C @2M\8@¯‰Áb¦Cq$••>ÀÏ•*ŠA*}ˆ2’ÔxøíX8¥ÇkݡވQ{ !ùeÕ8ÚR«¬ëIÉ(N§“¤D8О4°ùÎh ¢ÛÉ@”sª6o'KÍñ“Lr:Â÷}šˆ ¨åèv,ª‚–­Á–m -[s´lãÝuuK%ÃÑÅvn´á †Òðiî]ƒíÍÒ zìpg²4ƒ;Ü­-ÍPT~nø­Òkö$àrÔƒ2I•Ù‰zóGb˜•¨FSv̈5äCR'CsG{ܶ*Iå®~Hêd˜¯Á.\H¦ô`v¼aÀ×fF1âk‡Uí·üáŸcšsÃD³ß”X¾Â¤lžš× bb3]g”qˆì› P&?Y÷åËâ'›¢ž³Mζ?ß”ÀOæãÙ‹Ÿl8]è' P&?Ùã—ˆŸ¬îÕfQ!J©NB72ðMËM:ë-ñÞô!z¹içðM¢·_ÖIT³ÿÐ]ý´èáp®ÌZr9·Tã (Àk0ξÒ0G^o§#¿]½¸Ì)­ÁµðI#­®¿œí à58·ºŽÌïuøL2ì/^ƒc«ë˜×g‚«`ˆ3)×g‚¼]OœI<)ô¤ä0’æÓ{øv,²| '%Gvé´øv,ˆ‡wŸI†hã3ÖàÜŠœ ÒšÆí 39hM±*PPSàAp=*¨n@d/$*L@T‹ÞNf¸ÚKÅ»4H¯‚êšwiIA款’ŒR$ÁJ2´‡b¿…ªÓ(jŽMqÖi#96(ö[œtÚSìwl·¦Ç~‹³N»›¹9i:ƒº4ðÉWfG³NûiÖi_Ýz.ž-y[Ù(…œ=ô¥"6hè4èKE,¢pÌž@úR" ÓvtþV ˆBOä@p¼‘Uœ¼ç‘f$(ª€Þs"ª8zÏ£5S=:“ z™ nP ï#r  ${"ª@rp. Wå`q®s?çU"9XœêÜ?EKÔÁÛÉrâíèr°8Ô¹Ëõ:ÏÏ)–¯å…m z× ÕÎö­§Œð!<*Š`g÷„G%@ììžð¨(’Ge°zG%@<*Žð¨(šGÅgu²G%@)µ.ĺ'¾žø)3YÏK)r¨ïÌ 2ïÚn.8)rx…ýÓí@‰Uï_×Çâ.§œâµòþ:l9Åå!×-nW¢E‰òg']v”(v^‰*;J”?;uœÐeGyÌŸ=ÉÜVÙƒ”h ôÉ”(BïpoæD‹ÚÿCyÔ1â3vô¨M‰¢6ó` §¯Fm®cYç( êh^ `)I£6Àÿ»ÿŽír{ôv²L÷?LÝdA'º~~ìþ,€"Y‘þ²ç=>“èç ŒdúË y?Ùw°‘kÞum§¤Dëßn$•Û› \ò!Mq ^qÊŒxÔ=!%ò„ô„'¤[ÛǸ éN ärf#òõÚ˜_ó˜Ùˆì0³9Ž™È×k±_³ƒ¾^³9NùY@2Û”Ô¡¾›†¬çÃjû]à8êÞMvAz>´7£µFw“]Pìúá-ô9 ðLP-rýðúœÇ9ºžoaÆjZØoO×N-ê74•‡¶h%³ðt’W÷N Ø•ÙÈÚƒÓJH‘„±‰cGÓ˜ V€Øsß÷óÀpTbO}ß?E[¶#~RüD÷/ÙCß÷hɪ1°Çш³oG®D^«K{x;§ŽPçêRo'¿ÀêÒÞN~!$1ºü‚#GÀZ·(ƒbQý4óÉ¢ Š5+_×BsÊPÐ|)öÊù¨ÜÞànˆ ê`f`7ı+±J¯½7õVé5¹I‡´“DóàëÞê$Sšœè¾sÁ™ýcSTÍÆ6ÑÎçÎT­„éLÕ£•”pä+ðVûƒµhRòV ¢{CR'QéDÕbÅÂ$5Ì#nõ•¤€Np?D“nâp?Ä C£W¸\tÑÂuXÈ]7tÀ`ª„À NŽÞИ¥¬¿$3p/°t9Ëò×fTŽÛÑßMr̨Œðdýy vÍ$Î$CQdý Z¦ný ™6—½œ´VæÔ§“Àˆ²þ î†8­¤Õé„©×í!Xؿɜä$s£ã@™ƒ¬¿D®ø@ÖŸI }1 ;PõµÚ=(jh_L+éuŠ=ØqëÏnOY=àöë/ÚÙÁ•¤Œoç!&´è§£ •dpfÈÖ3éÃ?i‰¢g([/D«â:”­¢ˆUqÊÖ QÄúÇÊÖ QÄúÇeë…(¨þñ*fë…(¥6êQ׺R¬…¢ºù CÑB\Qú ×+§Ò-9cÖ¤j=h€¢UIµ›oP€âå†zà 1;}2HÕjGJpˆ¢ui¼6ÅÖ×H*àšõåp­¹Éa¯å©v(/ÆŸlN±ZÅÓ€¤j[:•ëûž )Ï” rýEÌÑn ×PÄírýEÌÑ®!×PÄírýåhßež ”Ú8?ÛìÉ„\ß<”8jב\Ð+DßDåûNËG1f‹/óG”|c¢Ùâ§Ž}£ß®¹(Fi¶×³͈nðl3,Ûuj¸¾j¤ÇÀ~EëhÃQ²ÐiÁ„E–@(þ5 À\,8d-QrD‘,@ ˜#Šdá’‚¬Jýæ”Òd¡‰ÅzÎEâºo'úèÔ_A<ÌDi /2‹M ?&¼"¿[‹|øÐ™áÈq}‘Œ±žì!ɡтb=Hªubsh%L'¶­Ä¢˜ ô1eç¹9çÙåÈÇ”ææDÇŽ#Svœ›#L«Q}LÙ~nޝ6ƒ:þôˆ¾’dzOEJêJò‡ ºgQ¬gÅHµ¬hµ€É‰¬ÛÍÙQÄ š³¢ˆs64g#DÑ¢ÇÝ=îÑ%†™&¤Ú`¸Õ¦ò óÄËmuÙ^"“Ã2ÍZÀ+I°µÔÀÕûÍrCÕ2JUÜ48]Ë(£ÕW{oWƒæS„(š·ËÁ³ÍˆÈ¼eªÏ<Û§Î:|¶ ô$" ®<öÙ’¦FÁ][Æ1;¾ÑijÜѦ"t@IJjGšN ¤`*XKAÑ ZKAÄçZðŠ¨ø\ 8¨]›lƒS1‡B§kk`†H‰ü£=‘!Rý£ÑœÑÞOÉÈ2t?¸’Øá3±°’ùŒ7dÔëº`I©‚š!uêµ 4ËWµÒjЛt›®ÇCA+u¸Ãbˆ"h¥=î°¢HZé !­4@´ÒwX Q -AXq(©Å}@Œ;@‘3›P¿ïEÎlBý¾C±ß÷ õûQrM–Á–0¾†ü‹Õ9oìø¦¹èóÆþũǨî_¬ycâ<x. :—18†Î%AYEó,E9ƒ Â:á2>FßQRR;ÒØn5¨µÉXKBQZ aYæ€Â±MmÙ@RP¢ŸJI #p(P.¢^Æœ;EKA½>B©×Ç4@幊Ôëãž ½>zÜë#Dz}8Üë#D)Ôö2莔ܯÝQ$÷+¼#ßçtK Q„n‰c×8À¹í!÷K¨ñ~`KÕx?°ÅY4 êÇgp…ÿ4§NÕýOþÑ&øLpúX‹Ï„énæÀJ¨îf=X ÊÝë áJ s;ªh9/=\ 㥇g‚;°‚.xþ2rYoƒ¢¤ G]_KI‰ °”æûi˜]~mÁФaˆ"v¾º!i¢ˆ¯nH†(bç«IÃEì|Õ i¢ZˆWµcFB_×-ùE¶c|½£fÇ„(’%ï×¢[ò!JÐùê0+a2†œh;„(¹’{¯G†"Š=•CµèžSƒ¤ëvYˆ"ØeýÚƒX=Û\˜{úŽ’’Ú‘¢ö‡(©R[¤ûà#t¸Ú#IA}º~*–zÎàP ·É!RRÌ_‘CHª–Ѩr(ÁVÙü–59”@«lžé®Ê¡Ze# CÉÉ*‹t÷kKV™Ô6CÕÖ3ØÍ`j¯¢Æ#³f²LÎÐJY: ©6„®„ÈÛíáJrlKéŒ!l)Ý‚ @RmÔ/<“f÷ôøL·nUçApÂF‹Ï¤"ºÔ:°ªKmV’¢"®$cn¼â4ý§ðJ˜\fx&9 mŦóŠÑ™ lΊËzËp6´‹ó»[t&æÂp{ðŠÍ÷UúEÂh:è ô?OÍTý"…6ÔÒHÓ/Ò³ u¶sÑü•Eœ¿R£ù+!J¦åCë¶eªF ÕæHÏÈH”ÄÈB)FæQð¹¤VŸÙˆcd# °ÅpŒ,D‘l1# QŒ:ñÀ^ÇȲs/±É,X‹¡¨­…ÈíÑý‚# Ç4&•B¿à\™£RÞtÎ¥A9!Šø;”³¢ˆ9 ÊÙQÄœål„(bÎFƒr6B”B1­ålŒ(8[äl„(bzl©(bzl©(¢¥Ú¡>ô!J®)àÓ5¸>‡8]8™Ï1§ 'ó9ætž3èþ #&DÉ•Újàë4Œõ|æh} -EU}Ì5Sí­¦™sÍDdâFßã{¾ ¯WR‡Ð;E‘Ù#ú‡½®F#ÑZ‚Ù7µ¹ð!ŠQ´æ*¢·î{2GK^èÝŒhÔ›Î(ˆæ`A=ÏÛh®ŠQçÖ8@-‰¥v¤é.æ¤ÓÅ{éV§ázéV§¡"½z¶ö¸Ÿ‚zCJÚSˆ’‚&Îà† ÅçÐ ˜)<æÁ$¸Ñˆ€l )h’nèBIytCœ±×b)u,YEÊ‘ó ¥ükFÑ¢ù<—>ƒèS]õ-gL½)òg”Gø3쑆sÓªÚ¡+ÁuÉÐÓ˜Áw<ÝŽ*Q3üŽ˜=’:Jdi`öH€"æRÖ0{$@s)k˜= ˆ¹” Ì PÄ\Êf(…V]¦ûr¢¤¾œ¨é ‡/z>÷¾zørÖó©jÚ9®½˜()è ßQE‰EpEÎŽý‚ÊŽý‚˜ö s ܬ¹Eì-Ÿ;ÌèúS4¹y%*W) &7ÆŒ[p&©en­ÄâjQàw-UMn­ó~×2ªÉí*ñtÕEªDÄÓUCÁ«Ýãéª!J®•\àÓ-p…?qºêeì˜Ó-P/cÇœn¼Ú5ôj(¹Rý ¼Ú%c­"¯vùc‰£ Þ3šó=:Áà=PÏëQð=TqÚ"¯vyˆ^ˆ^0U3Å’–YfšfZF½ýGÏk 4ÓS‡$aœ®.ÍJœŸ;¼ j^s VBå5ëšiIå5Í´$«puÍ´dªpÛ¹=˜FqIF½DM3-OÚ`´÷ð×”&Ãͧ€ßuIA3:p* %‡Ð©$¸"˜XË…Ò8ÐZ.° UØTÐåˆ ›ê¬ý;¸6ÕIû9up#*lª¨ösè•+l*¬ýL™ÖðtñÐÔÖáÓÍA<GøtsÐççÞU‡¬Ñ3§j z‡–ͧ¦{ ªhNâÞÕAÔ©C‹<´MyÓìdµìH{ÓÓɪm? â"oÀPá3¢â÷„pDÉOEä˜Õ0Öª¶H€¢êb6j‹úÀLX{¶EŽ™°î _£=Ø"bãsx.,Êm‰sÉ`_ˆž8—LÏHñ(@w·‡¼.iL¦®éZªøm,Q‰c–ò X E“;æ¾MªD³8kzž9¯I4«eMíYôì` cóŒ=¸#¤»70ßÙj½’‚ñQxG% ‰ò=JJíH㹊އ®åBÑ ZË…¨qàQÕ!=xEæBı[ÀYLÂpÕ†¶(Žíˆ,ßÕ!§x¿f¹()hÓ Öb(ùŒÖb ðþü9î˜1¤z9…V@$pI¢Ã#ZIš½&[p&T¯IÕß’_P×2„W_ •Ï…VB¼P½'ÿd¨ß‚êíEªÞvW=Q¤êm¢û·C9z€ª·C”\«¢S½ÊÄfæF¸š¢ˆ5ꆢ(ö³Ó5Ó%S+wÕÁ¾( š’¢h}Ãu¯rˆbÔ™—šæQPÇ„¢ia!ŠXuÖ -,D1ê 5‡vd¨)šOˆ’‚Ýú;¢´0Õ?¢¤ ¹»N»IF½iÅS¢¤ y~.„w”é†(Zœ)ÍÓcbŸˆ”†(bºƒ’$@ãД$Š(I‡Qr5>©ò—vûZ&hjü%=Ç'#_û^ç/é1>)âÔwDU@èü…©jíPD#Oate¡]íM•¤SŸõ¦úŽõ¦Íùz†u(¢¢ˆ=ÃÑQÄža7ÑQrµ!¡ªyøZ/‹sÍt_aˆ"ç=#jˆ"úPoȇ¢¨UóžKFÔ˜;x.Ê©EqþüT+õÞSå‘Á1šÉÿ¯Ê#ƒc4SdP‹Ñ„(FVwtÁ/ÄŽ.PkvÄŽ.Èw‰f–x”ÔP;Òø®!tÌy°XKJÑ ZKŠ£N@ß5dÇ]ß5”l^­%£8&ZK{ž‚h܈’R²QÓ”T-§S9f>È#ׂ<'ŠØ÷æ]†(bß;˜w¢ÈÝ ç$@É5ΠkA9–Ós¯kM ÊÏrú¬¡ !Š˜×¡ !J¦àÖýº9ò¦NIº75?zS…QˆþAßÇѤïãÉ"Ñk²C£ÎÝQåkNduÀ‰kyNduÀ‰kyNx¥àL°<‡óùž –Ÿç4 }B8]Ü#w¤MŽä'YÏëkÁ+¢òútÿ{ŽòúÖFú:ŸK ŠÏi¨ÃYÚƒè7DHWäMʱtÅ™gy­`œy¢ÈÝÍPæYˆ"w7ƒvZq°‚Å!*×- \\&/h\·Àö«¯ökí×D Æ~Ey# ìú†ò:B¹ëÊëQŒÚiÁ¥ÜŽ4ÎP@Ûh²¡p†‚¨\ìP”=DIAã^ý\˜ˆ?à˜ñï ¯®Þt†c$ÀW ˆÙÇ ôÕ(böq}uŠ˜}\C_]€’«mfU^W2žP4K(D‘-,=-£2àÀëÐ,¡%S³²U=µT³²·|j]O-ÏYÙ±š=û8D1êTtÓÈ–ÀýBÅûú;…(FUæÀ¥9µ#c(z>u Nx¶zѬ€’ʧCÞ¤’Ów$)q‡§¥ÍνCqoM’”0ÏÜ቗yyÃ/C¹Žú;*¨ïöxâeˆ’–ôú¹$%u.Úu S+x•KYÂ&i îm¡<30<²Xy {[,¦¼Gt. .aFAç"×Ho)@ìèT— uŠU_#®(˜QÔש(ø/iÖ„%¢a ”°–Èh „µZ}óFÖù”°>§º v¤I’EïDç½ i?Ó‹Æ¥,–öSþ0<C½Ft.ÛG@Úû\æŠâ˜`- ‡è\†«½€â2ðºJ{¯ QÄL׊ׄ(b¦ë ÅkB9? ÅkB=ÓUã˜Å”„wWå˜!Š<ÍÛjÇ QŒšççÀŽ(µú¦‹ ö¿,-.äwäQMxfCµú[G áó€~C9cYå!Š\m‡¬ò%ÓlX5ÿqDýÏQ‘EîŽ:ˆ„(²:ˆ„(™ê;Dô‚#¹(³(DQ4Y¢µ'ÊëBßí¯9D‘s½‘¯9D1jw v½ò5‡()£¬¿#ªúOÕ_B”4/×iWÑ_Â7­xNB”´ÂÕÏ…±„u]*DIÕì •×¥ê›Þò*Tdˆ"Æþ;Ôë>D1êü¸£g;¼£vt±ÿŨ=©UÚMñ<‚yGí¦§º`q 9X‹¡è­Å9dª§­ðyÄŽeéž¶EìiÒ Èrˆ"Öd5(²¢dj'õ\«†óeCINã|ÙŨ½;Tª3ª‡ Ü‘Fu†ñ ¨¥Ga"¨º3DQgëšj6ÐKŽ^#ÔT±×]5ÕEέƒšj€’©Þ USÍ|5ÕL«`Úâ°@SÍŽþ])wíe‹L(hGHN(pGPNÃIë#J kì‘îA?ƒÃ“ÖC£vSs`G)·#3dPNÏYÚpÊÐuïŒðc6ÐÈÈúS¼¬3 ; SóñCŽ©I’ æã÷¸¦¼ÈU?æåÜ;ú1ý~¡ÿ%?û1#™q ¦¢Tgç‚¢-Sž‡ªyàüÝeZ¹¦yX—QtÍ£`t)Aõ(†ˆ9¸#`M(pGÐ>jPÕ£¤–Ú‘&a‹S/4q¤ÒýRŠzÓ¿T¤Ï8²N~)Éë§J{ËD[ }d£¾æ“.ì#{ô5Ë#V.eIkB—öZë¸ ^¨ŸþŽ,ŽæQ]Ô›Þ"bªœQ´ü:]óQ a#Ó®GÁs‘l QtµÆªs†y2‰Âªs†Éc­q†*a8²< ”j ²BE¯v@ˆbÀ(Xå$ĤºÙ!J ÆÇèôBÙ$*g¨¬cNzJ»VÕë•víY¯û/’[h×õ:¹9 ¾#ê¦õÓ=u8ôtª§¹õSÝÞ#ÝÍòï½½æ!xEuœÀá®OM¡ÿ#ƸŽÏŸ?½K_ÞÞÞ›&ó êrÛøªBˆaâ{ëÒý^êï%;ïå}éÏ6ìåv%ö2Ö;wŸ»çW÷žL|Íhý4œM{k F¡ï¥¿×xå|¦Û™ú{Yδ½;ŒQ ÷2æ€qm˜{±Ú:–rkkLcáPžV?µÃ¡6øP“D¥²a7탤ÓJ>M ÃJÜX?]ïð?‡ÿAFZ¹€¿ß—×ÌtvÿýûmLà ±~z\ÙQ@¬//o È\ß­9oÞȬÇi­Î5OWb;b#òôvÂXcEwˆ‘VTkÏ7Ä1"¹¬(L8VÙ^GÙ>‘tK,6¢²ÄbTFC°Õ2`#*[ÅëÙH[¼¹ وƜ;¼›$Õ¯FçðåŽh,Ój’é<þÆüÄFTAAl§’âÚW,н!n ‰›š «‹››*nŽvQÙY H"ɬšY H*ɬ†Y |ÄJ°à#@r ¤!¤çR@éI€”HMˆà¤šùÉcT|ÞÌO²ƒÞù­ß— %mót•Y}¶Á½ú ^èuXŸÙ^Ÿ÷23Ø»“Åx¶ÁÇ mõ´—î©sÝcä@Œ;w‡…¾ŽövÃgZNÏ÷ñ˺•ÉgìA¾l’b8’…?ï1*½kü9;ˆàÈâf¸`Y-É"869ؿ޶ûõ뎩dÁŠuÓÏwÁ'&?œÉóó_]IÐI˜ü­í0ˆA÷ 3GClgÁ²Ìj‰•¤‰ÎŸóF¹b«òçžâÏVåÏŽâÏ–âÏÃKÆ{øsOñgKòçŸG¡¯CçÏ–áσïð™Jü¹mþlUþì(þlYþLªÄŸÅŸ-ÇŸ{•?[?;Š?[Š?·uÛ7—&Ë0üÙ²üYãEVçÏŽâÏ–åÏ#‘øsOñgËòg$\ÓT%ÍE‘ï=áŸÇË⦆™µø0ÐÀéÅËÉ÷žðˆ_`ì­ºlò½'\â‹}£ñüà סø'òƒ'¼û²›õ0Ꜿ ém ÚbÌ>OÛ™N.½éLû«¨.æ'Ox”¥õ׆9J]GÛw¢Í™=áQú¨ï^z4vYØÈ—£š7öªýù“8Ô$QÙÈÀÐZ¼›$pøc]ÞÝðmóÑ{˜1™Þf†çO¸Ìü¹`ZÐ2•z ž-èih†hA7HCÛ0°1D ºCÚ†-èbú: mÀôŸ‡hA߆¶aˆtƒ4´€Æ°U¶ ¤¡ Ђî£Ò»¦¡ Ђ¾6D´ ;¤¡ Ø‚&®X´ ¤¡ Ø‚&nG´ ;¤¡ [ÐøŠ ZÙŽtCðg,èŽàφµ ñ:D º!ø³a-èbú:tþlH úŽÏT´ k‚?`Aw6´U¶ ;‚?Ö‚&ÈL¶ ;‚?Ö‚¾g’˳Y16´MlG´ ;‚?Ú‚&@D º!ø³¡-h¼’49wã˜$Å@gˆ·î<œŸÿ;ZHÞs<ˆ>ŸÀˆ1ÒØì‹)ÒùâÎéXÐÎaŒL_‡ÊwΉ§8ÖgS·§í<œb’Àµ¿kÖ¯å,hæ<*a3F#ÖaúVqÕTß½‡32(}$TÀFöNÅ‚î JM¤ú°lA[hAûŽ_Ãûe@Ý2 ¹?ö;Ñ8@ñ°ŸD‹—úJ;íõn³Øû{½W§Åm7 £¯Cy½Æ,ô6ÿ—?ÓÉÿå µòëÝ0ra/þÕ\.Ý0 128¯‚ß0f íßÿfz›%žßËwOî¢osèÄhœ§MVmV%ÔQÀ4vÌ€©=/ ÔR%ÔjIêè¨Åë0ú:tBÕ=MÄî+ GmqL–ˆêèdÅ¡N÷‚µŒêÀEß7Æ|× ¤T u¦@¨%E¨}O`¬„‰Jøn±JT¢|¨ötúåq+#}Ÿ!<êDξB¤:ĽÓ W#{­}â˜âµ^!2ÙS<œ…æ)^!ríNº^ñ¯…t# Š•{/D,С8Q¹÷BÄâ3Š•{/„'Â{Éôu(q¢rʼnn(NTî½±øL‡âDåÞ ¡Æ‰ð^*uZœ¨ñ{ÒtÍׯ?”tDyüü8¢ ‡2.Æ£<½þ¼»þöíJ xªŒ½Çååu¸ãÆ£¼|´ý{óôqï”l\Ë—±Póyõ(ÏÃë¹}ôï? ”|BùÏ÷Oõ;zƒ’~G͵ùÙ|ûC Ó¹Lky{œµÓ¹4·«{’¥iˆRÊÛ ‡~@‰„j÷)ð Ê¢@RD‰Õ FÎë™ôH&gÓ‚\úgÓgRˆùPÛI }àA€èH8ÁiµðˆÑW¢‰Žä`"D´j; g#8­ =µj;‰h%¬ÚN µš ¨¢#aí„V®s‰í"vDG>BR¨NB‡„ôª‡çf 7a"ù }ûBÝý€@G!³ÁSè°§0®Â–ØŽ\ß|…t2 Š[Û2°PeàÔÊÀB• …*§¦aPª œÏÉÀ‚’NvÕ …èËmA.™)Õd2ïvhñí”j6Ùn§TÓÉ¦í ¡±ïß¿=Ÿ, e¾»:‘nÇ]{BC±º«Ýƒ` Å’¾vG€}%@C±È¸m voIw;³Éß>ÞÔP,épï‰3QØ=ð¸ Ðå΀Èþ˜Ž Yâí’¬¹°þ˜ƒ}%:Éš Ùúc6ì!¶#úc:‚dÍ…õÇ·#úcº+ÕæÂúcî±]ÄŠ ‡eà1Eä” ]·XîrDd]î“Dby÷ËÀ]–ˆ`¥C¸OÑ’ª‰ƒ-$ý±ƒ&Oz”‘ _ÐäI98&FÜ1ˆÑW¢™·ƒ^`j°^5Ç”m~ iÓ©Þý`Îëd’€’Á•  ©œÖ Š¥2"³˜™²·ÿ:hDf13%¢[v6SΕòȈÌ``t:•d´™¢Ä1²X`ôX+‡ŒÈãLÓX>@‹ŒÈìÔò_ÑŒÈãTÓèü\dDÇšFÎg¢FTŽsM夹`.96õ¸†IYŒQ% ƒ·“(F¼£>:x;GFýi•o‡dÔ®g@D1Z;âvr FoPŒf§&‚ˆÎÙöi±ޏs6 F³CÚ£&F‰•ÈJtå1ζólyðvòg‹ho'q¶c@ÄÙòg‹4ßCålJó½$?r¶x¦^+Ô@þ©ÔJ­¥³ºSrË7ô˜˜àÕ­­1ú{÷ûƒhÝ·\‹¶S2ÛÑ ÏTôÙCË+?&¶FÜí)å§¾†ˆÆ”òCbkÌg-¯üÐÙ0Nö@Ýʉ­Šå%ûìósbë)d†êý§ @±CŠH*X¸ÇZR<ÝÈÀMÖ6ŒT©€qªCqöá½ä°Ç ÞK›¬à½äº¹4¶|×ßoT¾©¡¿þ~ ¤ò- Úû-Î*ß—s…2x¿´Í§3QßoAª|ã%c1Ë+äRù|^Q‹o'1·Ìò-Ê7m§DT>;@©(X•Ï9f;JßHä9)çdAŒ Á½#‘ç¤8yNŽÛÁ£’ã,®há(±I;Ü=*ÙOãúüéÏçýv^ž}9¡¯JüuªëŸßëîÇñ–ÿ$yX­ùÙ£|{öDåîšþú»ùøÙ¿(SµæçÇ=[zˆ­vïãZ>Þ~üøýzueÚ‘‡wä+$½êèwÔ×O]w½1(cµæãŸO_F”×÷·z¬P>–Ò·}w#PòÃé^ßÇz³ñtŸ¾×~¼ÕJ1­åñ1²–×_íóÙQ9¡Lwô2ÝÒ°–ŸWwûáܽë^™UG”©ºwBùu¿wWf-vºé/Ÿ<ʳßÑX ûóz»þ¾·?Þo__ª»Ì3 ¿ø>KIm3ÑíéýûÙ׿¾NQ«±ö×ÏŸus­™“IÒm5ž|=õÖ3ùv}3H÷ÆÀ˜í-y˜a)ãMy˜—ß¿__®¿¿30Ù¼šÇíl®c¶?›—ÛÇKOÍ\o<ͳ{}_oêëõ}¸©o×o ÌTp<èOÓ…·3tþŸ¾ÿüá~_¯ L9ÓÍãL7õÄ!Fºyþñû—\ÂÌýÿüûïbôÌwéïøÒ~zï¨ÕŒTüe‚yþöºÕ¨ßžîß½¿½1«gÄ~þògz ß<õ¹‰ünO?ÝÓóÀ°ò§Äz˜/ Œ¿¨z†yþ]_oÌ›JÓã›zèf Á‘nšÛówŠÙ¤3ÿ;U»;¯8ŒM'=ÌŸY|¿2œ/©¸ûói8â§ámŽ%ó#Ãyúþþñív½1TœŽTüØý™`êOx„i®o×§·öÚ203#öäça¶5Ò‡ùþñçÇóõ郙8ñ(¡žæ·yWÓ~üñͰ^˜™û ŸWs­×ÕÜ~¾]>10vãèæí:iÏæãþúãúãsÄær€©§V #ÌŸ×æúãQ$L"YÀ ´€Kh7Ð.¡Ü@ ¸ÀVT3 š¯$X–1_Ë1l‚2,Ë“¯åb9WÞN²T¦ò+È ,j0ÔÄfQƒ¡– 6‹ Á°IyèÕ:˜X6a81%jŒ["b3(zÂÊ“'ìœÏë•Dl8ö:èØ@2àØë˜ídÀ±×AÇÞbäHa«P:á¶ ¥. šÂVátÂ*lN'ì ÂV±! eþ@"6çÂ^U,dqÐOZâvr¤ä´Äíäz‘áUB‘6 ‡¨"CƒÊ€b×M¨äTHî8"ëBrÇ^ÕY PÉ©Nrç12"ߎ%3¼äü»ê$wι«P+¨NõÇç´S¨Tû".DÓ ªCW,wjÕ¾ˆKàl@+¨E\Z2E‡A$S”pzXàôp„ÓçGO8=lÄéqÔpœÓ5Ia8µ­Î({Laˆè7x/91а¿}¸NYÇ?u-ÈrcsXûä^Þ ”Sv×x¬J÷Ôÿè>~(fnæØý»6s¼Î;›9÷C ,-!?¯(×zCé_~µ¯Ê4ýêóØôv*¢¼ÎÓ<”¦ÿõò½#Pļïj¦‰y w,L›A4¹cÏib§Šy¨ØSšØc¤‹;–Lóyßw "CÇ”¹>öêVS6æúˆhrÇž]_ÎÍ’€Ü±ØõÑ@Ç”%]~5Ä™ˆŽ©ÔÙì©3×ÙTŽ)»ïÌ%ƒè·c.À1uƒ:›ÝwænØ;öЙKsL+ÖL4Ìí$Гã g:Û¢s¶“Îv*äbn'5 Ô¨-«³9y@GR(£ì@ì ½ F5ÌbU5(¤Dé5dæ³uí1Á13O­:gKpÐ ù”lÌ sHƒ.²h£w i P!§Â ´zË[L'FO¨Ç“\T©ThUm6½hÚì–ÛßÞŸœÜ’?D9MqôÐeP¸R«¢ˆÁâõyP, üõyØ0R9q„ð6 £Ëêd?`€0Ę•¯“}"ZN7Ôé!1{tˆØJ†Ö¢Ui­<‘ýQ+Ѓ Ø €¤ZB®Z*”ú <?Š]© Q–Aêgs²¯ŸÜ·ú÷/e2'»ÿf”‘f§9wîöôçû¯p”¹Æ—Ï Êb”z”ÛíééÖ(Á0åÙœ¬'YzõÍ8Þ=µ_ ”e ú´?rä: Óq úµ»‹„(Ë@åÿ”÷eGÊÏ÷þUÌø Qæ”»îËŠ²œî€òÞ¶¯b–QˆbO(SŽÛ„òá^¿2§;5Âø<§¶Ô|ü|îî?˜d†ùYMóñîîsKóhåÿ>/›òÙÓ{iú§ŸmÿësÀ‰9lê½Þ65༻+sÂÓxå?Ÿ»1ýô«Ï?õYeµ'àö©ÿùqÿxg`rqúre¤ Ýz]áOºA…?M }ÚŽªð§ r¡Ïg¢)üiBºÐ}€ƒ81ÀÑ!sl1t¡;x;&ƒ.toÇd ÀÑ!s,2Çà¸cBIÀR~x‚9#ZU)¿¤rob%2 Lj€b ©²í›\é)Ûi:°¥€¡D2¶Û{ƒ2¶C”4ž°íQ@ÂvˆbâùÚŠš¯¢d±tí%Íß§k×5’£líoÌŽÆôèÿ>O)À/ïõÛ”ß\ûß¿~­ï_¿~%PÆìèÿÆŠƒe‡S"ñ€Ò\ëæÉwæ%PÆäè?SÊÄÞüÐ6wºÿ¬_Ó¬fèÅN;zœÖòþúV×ËŽ®¿ïÝݹ'†ê.'˜Q4Ï0‹{ùÍÀ$L7Ÿïë°¯C0ÍŸ®ë®ÔH0×zTÆF˜º©ï$Œl°¢@ß“#ƒú6ŒTéŒ ÖôXßû9’©­g•(޵5!”ïÇèt-ógÃP‚–mö '´P 8¯ì&Aeä r¡yÔ4Ö[ ²/¹Ð#ɱ”cæáŸpCTŽÕPŽ(¢«¡ PD9VC9 @9ÖÕ –cÌé r¬&äX€"ȱšc ”cWfG‚« 9R ÇjBŽ…0‚« 9Âr¬&äXc¤„•Ê1䨔X¨Ë1䨼•½"É£^¹áH’RUØç*-É#D’<úiÖ³–ä¢Ì^¹Ç%=ÃmIÝ`Ì·#Pf¯\÷¸ ¼¯Ik¾û*_eöÊ=~YÛÛÖK„k0Uß¹þ+¢t’ni¬ ò¹‡.ÏNM#}$A…[k‚| ×é R†Eå} ÷bQµª;Ú0D>mÉe®ÁÌ"§®9¼›ä‚ûT´èjPv¾øõènPvþÔØmGÍ Ñíd¨Äml¡ n'C5n-±žšç&p"Io§€#I@±Aâñ­r§`ÄŽê'2§‚s4†ÿªÙßzâ`+@ö546%u»Å«;àzÂgö8©‰«qÏö¸¸WÒgÔª÷lÙüØ‹úéIÌü QÎ-ﯫà J¶wÀùµü·®¥ÖÒ¿ô¿˜µäbðq@ùóó÷ÇsºSÀï¿0à7êÃ>’Ô4îÚ‰“IB”)à÷_÷i›PÞ_ÜŸƒRÍ(AplCéû?_¯Š=¡,J¤Gùhÿ¼2§;üþ[#us3”æãýÖ6õ+“Ì0ëjêí|»÷÷Áðf`ο퀽rÝv sø]ß—€ß¯'×¾ü Î&ðóW5ü>º÷Ÿ L.ëH­Í€Zëp»¿ C銅ÔÚì¡D‰Ë¨êx$(»¨APC±jƒ:¡†(ÚÔL½ꈒ0;RcJŠÒäé>YÌ£wìr‰Dtvòè=FËê­$%îŸíŒ9#Õì l­›|‹ž!,¾EÏWoÑ· .Ù˱ÇÒ·—·%«áÞø‹×ëMl¢LΙnò[}{ywKG¸¦}ÿÙºrŸ°ÅQ朆åÃýøöÚ(™œ… Êx”&a"Ö”£±C^v]~´¸ÿ‹x€•šƒ4Á©7¤nå Mp^Ø ²¸‡÷rJ<—1àÍDÒOÝ~àn`gÈZÜy¬€ü”á×#:‹˜¨ÓZÜ9e¢âíÀ¹ssÄv àÝÁw~4Qcu‰ ³ÜƒT°0d– Jeb·SíâH«¹Ëö9¬¨Ñ{^/×g,pl qÆâ‡Ög,€/²'b¸°ÏlOqaŸÙžˆâ2}fa·ˆ•œÜ=ÜNŽ4jÆ-Ž¥±lôüŠÃà‡hºz~ÅaðC|,qhmç;8«ZŽPµÊáùUÕj U+@IãJRK(IЉ+l-¡°(™,‘X>T°‡ b(+†ÒBY+†D²¸©Ú€=¤ò4¤ž”Ç€@¼—¾nÔ–0cî¡­µå)cÿhÔº¹³šfÔ–‡Œ})OR·¼JhÔÎ;RÚ’3j¶T¢4•±¥Y(¤©ÌÚ± aÚ@½<³ësÎoÇÂFœÈF/Ѳ%Ï Ð~òX;èF/‰ŒÚ®UZ„~£YP¸VE#ôKášßÐØ£íæn÷_ïŠûqpG ³#ÕR^a,Ýs…îyIÑî¹:øbþ[„÷ݽôí·?ˆÄi¦êçcN:ÐÏíf!qjp, éçö¡Â.H@²ûÌ·ø#D HB±I‡„(b’j@¢ˆ Hn¨Iˆ"6 ¹¡$!J!ÛP=¤7Ô?r|;ˆàPÿHïoƒ‡l¨±á¢.ÅEÙ[b;)вC“p1Úd']ƒ³XƒÃóÙBIƒÃÚBmH0KXhqxD[zjJO4î!±ÀÄ,hp[–˜V‚ˆ¥DÖ L˜±ÈßÕ 3ù»‘0cQ"ÄRÚ(Å2ÂC•ìH*ç‹öð`S赆žŒ DÉíáÁ¦ Œu‚BnsÙ{2„È (äQÄBîr‡(FÊéP vˆ’I%Ø7T‚¢ˆy**Q ©»C%Ø!J)•ƒw¨—ŠQîTÕ¹ÜÛŽgmµÇÍ6M5h«á [9ÜÈØ%…Mµd‰ ÑÚHVÉ]l¤´‘ìÁŽ•†éÜÅ9mjL¢ˆé:Ô˜.D1JËâŽR(l‰;JA‘ñ †JlÔ§tn æÐŽ’’Ù‘úí±–D¨ÊÅk)zQùå© Ž`SãµdÌk„ç’–c â/Ùeà/¶Œ~2lêg˜†(R†©o¥ëÌ!ŠaÚã ÓEÈ0íq†iˆ"d˜ö8Ã4D)”*]2zBc)¦!ŠæáÕõ÷,9yrÎC‡l¬E´±:H/ŠhcÕÈÆ Q¤‘ƒ#Šj…(¹d©5ÈR Q ­+¼#ä'›z˜i6D«ƒdc…(buð ÙX!J&ÕõÖÈ: Qr©Æ¸î‰;"Þ4°±F”'#ôøŽ`s7¤×…(š^§kA#JŽå´®…(b«Sh5†(F›O„ï(C|iªÙ¹ Ç)Vˆ[(gÇ.Bµ2qGY-qG$õÔHS QŒÖÖ¡%³#U6(j½%^KÉЋ¦©fITk>gäàµÌk„çR½#&ñŠ8—YÈû2¢¤Œl„kIq®R‹Ï%at)Íû’%0B7¥W¨>Ì šGûa"kÂ<'ñÓEÖD€"Ö«A|ˆ"Ö«uКP2©Ò¬ƒv@€’KUo´I”Bé×ÛÂ;‚™0=D‘¼»8=D1ZÝ›þŽŒ&©ïÈDeÀ¹'‚C§Kðd«È_¦Nºþ’Á×87'Qõ—ìôϱ–ÚYô5îc-5´²ók<ÅZnPƒÏ¢¯qk¹Ak"‹¾Æ“Ž ^cóU{< D‘´f?J¼Æì³”b í(¡v¤¾€ û½ŽéðZ óTiœì‹tÐ_—ôRâöI€^rÍn\g[ î«vãŠè%gìFȽs¢žªƒÜ;?ÍßuŽY`oèÔÐ[å˜EÔz˜ ­òâà9‘¦+á¡×Ø@¶Pr"¶LöžØî …¬¬O&Ÿv¤¾é"J/gk¢E§ËÄIˆµ”8~ toŸc—A^‡tïEôäß î ˆžüêÞJ&ùà¨{(¹h î hº7xjãoG™Y©ò—pïò—gVx {;œY¢¤J~(ö%%í‘î]ÂìÛIgÐoÚbKxêõ¦ò]µ„Ýø $±Ý[$@ó°Zägã»@SµÑÈÏ^S½AÚµ‡ÈäqhGŒ$šªÅ’dÔT[D/ŒH‹ý˜c‹N•vó‹F»K9âR!Š˜ÿ‡–…(F)«Õi7¿@¾;à@;|wDÁ;ÂzÒšG”„Ù‘ÆwCÕç×’X†^ÐZˆw„h7×´ Å§ i7jA{ ÛAÚÍZ$ÕZ´£4av¤žn~¼éÏ>­^œu}_?Õí½‹¥§ÖAÛÝJŸkϤƾÈîúÔÔѪå=Æì­~œ*Ü_ÞÍÐMúeóÔ´Í {\!†‰ïeêQ;ì¥nð^²ó^ÖAòÃ^nWb/s-U÷ïìrõ(žÇZª§álÚÆ(ô½ô÷ŸÇROû¸©¿—åLQvƒ•p/Ãa×s/V[Çðø®->©Ú"r¨~>Þ“·j$Q©lØMKP{:­äÓÜŒÁ§—¸¥àîéÝ÷$V2ÕY ”ö8ùŽ^'Vâ£3¿¿ùþÎ ÉÄùQžX_^Þ¥ÆbѼ|éßõZO=™]óôq%¶SœœÁ!¹;™\³=™.gl17_ŽŸ¸ X@v˜¼vZÇülî®n0ƹ‹xý¾N˜i4ØH˜È47V0º§Îu÷ÄÈKtî1ЉVWǸ›ºÜM´zïkwÃë(õ½´7â<ªC³‚e~€çÌýßKÀFú¨ß7úPØYv`# ?cue#Ñ•¨ -;°òe㊾‹áÌ‹œÌв#‘ÞŒÆÐ²‰ÉÈZ"‘åUv`# Wì{âv¦ZÃÇW¶óüücÌÿÀ %àŠ·¶Ã •6fªõm{ b¥¡¡#'vÄp´ -±4Ñùó æ)Û±*v¶^!^‡ÀŸ{Š?[•?÷¶$îñ:tþìSMñ:J}/:¶:ö%o?[•?;Š?[–?‡*ñgGñgËñç^åÏVçÏŽâÏ–âÏmÝvÄJ ÖØˆÕù³£ø³eùsO€TZ33ÄŸ­ÎŸ{Š?[–?ÛIgŠý4ÓÉ«›"#n=6˜óäÇÔ¾£é:‡Søâ†!¸Ü4N3¡7 £ñžQ4 #Óס˜¿Æàùòø%H-uNß ëædµfÃX[=n÷2¹6¦{é(ˆQj,­¿Þ˜ó¨Ôu´Ã7Ã*4Vß½Ægº˜áñÓ§ðBfþ<>"Ë“¾õíéÆQ@$•fÕLþlðÕ$FšU3¾Í‚@2øÕ`ZÐ2•ì cÖ@ƒ4´ [Ðx¢Ý! mÃ-èih¶ ;ˆ-è+^G©ïEÑÐ6 Ñ‚¾! mÃ-èiha ªlA7HC @ Ý F}3š†€@ úJ¬[Ðø†e ºAZ‚-hb;•VC­jhˆhAwHC 8¶ ñ´r&XÐÁŸ kAãuˆtCðg,è†àφµ ˆ-hb¥¾?`A×6À‚îþlh ªlAw6¬M«lAw6¬}'V‚-hb%¢ÝüÙÐ4¦5Ù‚nþlÝüÙÐ427g9Z7ý<ÔM%ûc [ôV?ðE±³ù¢ë]{ÈwNÅ‚À F¦¯Cåiɾ0úËR¼¾>›qhŸÎÓvN1}íï=>dA3çQ ë˜1„!«{ «Ðصqª=±÷p*´j-Ú³} ”` Ú-èØÜÀöΨíû3 ï—Y ² U¯Â¡Y`$në›j¯·8LkˆÅ:}c_íõûa Ÿ?‰½Þ«Óâ¶ÅaVƒ¸åõnKcàÕÿåÞÿטlÝ×Wˆ‘ {ñ¯æê´pé†1khÿþ7üÛ,òü:¾·c\ˆQŠá¸1¦ê†Q‰Ñ8Oš¬Ú0¬J¨£àÄ4vÔï©» ÔR%Ô~êF µ$utÔâu}:¡ºY>~ ª&b¿¹›æ¨-ŽÉqB¬ãH¨}ß8ó]¿ÜR%Ôén¡–*¡Îôµ¤µ—ÎÅ!Y"QðEB ¡–ÕžN¿<.“¾Jn‚ð\¨k!DªCܯ¢Ê¼BÙWìk¦_ñ ‘Éžâá,4Oñ ‘kwâg×÷ð, ɇߡ8QùplöqºÕʼnʓâŸéPœ¨Ü{!Ô8Ñbdú:”8Qùp{ŽÝPœ¨Ü{!bñ™ʼnʽBá½Tê:´8QyôBDiL•/„'‡*lj –[¼±·ß¡8QyðBÄ^ƒâDåÁ ¡Æ‰<~;=Ž ™ÊŽoRâ8Žo´ÄÈôuè Ó9€o„ 9@¦r€GŠ7 Ȉó¨Ôu© Ç‘â€Æ pˆÄÜ•à™Îz)@Œ4U­&8@ÆrG<Þ<î…pØÓ5€äº§klÓëž.¡› ôtµx/™¾ÅÙ0OW=]ôti¯7'=]Äy@O±«Ð˜îé h zº4jÏuO—ë ž®‘ÜU«,‘9òt ÐÓå0¡I`h®s€øºo(€¯ûFp€‚õucŒL_‡Î àëîP°¾nŒ}Ýø<°¯¯Ã*49@Aûº B}Ý Á äë¾f‹5(h_7’‹‘*_9¦¿Þ£¯ûËãRr?úU†×?6P]3‰9ùfbªo&2—ø†ö®fçë¼3-¸™½¯[rÏxß.^‡02zr4]ý`iÕC¢÷o!œv+DªxºÝõ]yÿ+„‘L€™™ÕCZ3³Cfæ†!š™ 237 lfbŒL_‡bfn¢™Y#3sÃÍÌ™™63ñyTê:43sð éff@cØÌ¼aÑ̼!€ˆffƒÌÌDT2;df ØÌ$V"š™R2P1véh Ó\FMÉÜ0°™‰×‘éëP”Ì C43¤dnØÌ¼C lfâ½`3¯Ã*4¦+™a3“ÍÌŽà(¡b$÷VÝ©…)™63ñ£‰$T¬±Ý¾ÊL ÚG{ Ì”ª23¯BWf ƒ«†é\ó«søínÙx ÃÓ}yž³)<ÆáTý>~CŒT¬‹@*ö!½€ •e¨l8C¥ƒF_‡Â7 1Cå†2T6 œ¡‚÷"f¨ÜP†Ê†QÊíùAàÃ3T:”¡²aà ¼)ðïæiœ:¡î:^G: ³85ÍÝî‹‘B•32ì¡I\‡¢¹Û}1Ò”¡r(%“ÍÝ‹‘DBeö2Tz9ÒŠ‘Îjê<¯UQSí¾)"£&úдT{(F’ UN-³‡b¤³‚9(—=æ¨çœ¿P±1 G5\*•ì;°‡ª q:G5(•ªÅ„j¸T*f/(•J½ÜsÎ_(µ§»EÕ@BíueÊò!äT*õÑÁœ?†PsóÇjÎæü5ÃèëÐ 5„Ú¡œ?»Ú©9x/8çï1JmN"Ôäü5=ý9›ó‡1B¼:¯;øæ„2È?ÉÉì?thAznr‰±åcb öjº=±£¯D¡÷DÒuÛéºTv™íHÚ®_‰®í ¥<Ð|R‰ý7¾€@…·'èDâÏçd{=)Ûá¤ìrhwÇ F_ Y=/»ÇyÙdÒÌv —-µÁ,dõÜl‡s³ȨES $¶‹œÇ ²³“$Ü'W7(?;Iu% €9Oäh ™œ§ ²´œ§M€b5” Ôø<`( §ò9­Ê:1úJ4†’”¾ˆ ¬¡ L8­Ïiõ͈(k(¨÷W¬3”*~¨ %a5¿¶e@D†‚½>¥PÝ>»}è÷éoÄè+Q?ˆäùññtƒ:®f;Ð÷Ó6Dpþ8ìü @*©üzèþéb“•Ž…*Ý<‰ÈÀB• …*ûy>1…*ç3A2° d “8H!zçZ¥äAJ5MÉoZ|;¥š§´€€ÛÑçTMÛAüþØ`>v;z¦RR•|P ƒH·ã®=¡¡XÝyêA°†bIï©»b£¯h(™<-Áî-é@e¶=¨=±É…:^1ÔP,d÷À‡€@'jK¬D¶Ò;‚d ˆ zH²æÂZé1úJt’5@² ´Ò7l¥ÛÁVúƒ”ÚP*D²R':Jµ¹°Vú ¶‹˜gï° <ýOi¶u‹e`z¹ºu‹e`zɺ7‡eà.î/XéPîÿZº.RHúcMžô(#3t É“r2p u F_‰fò¤1x¨‡†&OÊÉ@§µí @p¸û†AÄxwMžÉÀ™NT:ee`+§ª„Ä&†¼±§:}Ør‹Äš±§zÁAob%F_‰&79šØb’ÝÿVãÞ|wDŒ|cOõ¢,RÛ6û&è$¢¶m¹bzUDâÿK/‹èPYĆ‘*ùUz]ĆaäÚyäq0Ð〻¢ ©¢És=¸3J’ɵÑÈã`XƒR€r¿h[†ð8ô~žã­VzF®i‰•È¥Q}´-ƒ<cÂж éqè•m‰9yþ‹ôuèíDWd2Ô¶ 'ºœÖ‰71úJ4mËÄDס(j[†]N›Ò€`3±ÑÁÜAmË Ñ5Ó à'¤èjq0o}mDWq]g¯®¯öÔϤ؋®OÑæuƒåÔ@ £äó·¾äꪬãœÐJê‘.O{™™ô{P¼ örÒ·w^Þ <Ünœ—7¨o ØyI€}%š¼Èž –`%ë¼$¶ƒ— —7¨o +AZð‚— ±ÉÝôÆÑï:ɲê#Íð 'Èg|H ºæxòé©7ït®¶Ÿò×M æ¸Ï¬—=Ar_½¤;â@?9å,]lîÊܨ©ŸAÀ퀢úq;èñ¤ëõPsLÙ²zwÅ …$ºTŠæÕÏ£5¨-IåD]PŽ€¹2‘YÌLÙÛ4"³˜™ш-;›)çÊgdDf00:‰Ê 2ÚLQâY,0z¬~BFäaZf4 EFäi\¦¢‘§y™±Q¦Èˆ<ÌŒŽ2ÎD¨'fÊIr Tr™íž “ ²£>J@o'5PŒ:x;F},ÇrðvŽŒú1Ò„ÞɨÜ28ÅhíˆÛɽA1šÚÓ :gÛ§=Æ*ºq;9æl@Œf‡´GMŒÛ)¤Bè*„Nò‡›"þ˜ÇøãÎ?æAÀ Ìcü1¢½À<ÆÍáÌOü1Ò9Ùr–?*Íá’üÈãýƒz­€Çßq¥šùSÅ|‹@PÿlðäÇ|Òˆ—ò‚üÔ¨NÑxA~È'¹Ê¡Á“ZÕÅéh9ù!ŸT1xdWy¾Ï'™P¡—¿âTªôÚJ£@d§x0ºZŽ^m©RI";+†âÃ{Éa¿ ¼—6¼À{Éuclz­?½)ISsuýéHIZ@´§Wœ•¤/ç Kðô hÍNg¢>½‚T’ÆKÆ b^,Va ¤$yYÞâÛÉA”êób ¤$MÛiÑ#%Éß «$9ÇlGéá‡| ò5L ˆ$¸ò5'_Ãq;¸‹Orœ‹­#¶£3i‡;ù$ÇÉH‰Ó@‰SB‰Ó@‰SB‰Ó@‰S%Î9¸ä›M‚½d(¸4Šq5®©ÒΗV #÷FFAónØ4 ʘw;¢åÙ»}‚{·h”¤w»WúÅ EœÒæ‘B€Òô0æT¹€(McÎë”V¨ºMOÔüG`œ}7DÍÏi†¢IÏÃŒhIÔmŽS0b9úP·9ŒÁÐt›ž8¹ªê6å©þl×Cݦ<¶Ž•@À퀚Ÿq;”øv0`k~Zb%šnRʘnst €ò¤Û’æÚ0À @eÊí…¬À¢ø– 6‹Jà[‚Ø,*‡†òЧ4.t0+°lH•ƒv£O ›A 'Pó,Ošç9ãÄ+'ˆØ P¤;¨H P¤;f;P¤;¨Ho FîÍ‹¶ ¼G °U(ཀh […Þ5TØ*ðî ÂV±.¥÷j"¶À1È*æ"8è'-q;9RrZâvr=ÊEÄ «“‹à1Rˆ¢\é"´Ðž8“B앜 ÉGÄ +$wƒ¬ÎrçdÝC%§:ÉÇÈx|;–ŒAÊâê$wÎÙP+¨N2çĨTû4cDÓ ªCšq,»jÕ>ÍXàl@+¨iÆZÜX‰ƒlƒôæ )¶´ ëÄ׉#\'¸NzÂub#®“£žäœ®'ÙHàáÔ,¸´ì1ðÑ’ð^rb˜Kûp]£Ý®Q޵K€¿Z9ô €¿Z9œA4þjÏ‘ÃSí”~ö9|ŒÔsþjÉÈ¡ÏÀ¹c¹Œ:`lÌÄß« tÀؘ‰Ñø«=›ø_Î瀿Zlâ7ÐcI߯†07¨›ØS„³J0vß#AÑoÇ\€æu»ï‘ ÜÐëí¡G‚æ€!@Ä쵆¹z,äl@7Y@tÎvÒMN)µÌí$ {­š£eu×3 …2®äD ÒKWMæTI š$8¬ã MgJ Žë ·‡ù ñCèÅ@€z2:`z’ýdÊ;CÛÉ¡C·ÅW|pJtØé°éeÐrJ<é­Uu¥ÅrëP…Ú€bµ5¨BmÃHå>ílFIó×imÀîé1±I§µDÔ…o¨F-1;qè‚AÅÏcÕ Öƒä²÷íLÕ•$Áú gÚR’³év”û4N{¢‹À4NûDi‚œ'ÓvT˜&Èy2Ÿ‰&Ó„tžx×"º¶:¤  &ƒÎoÇdÐyâàí˜ ¸¶:¤  ¢k«C J‚][w R(¡7À †“[$Cb9`Òôä´ˆ´æb'8-Ny€ØIÙ’Ÿ#y8zNÑ€aoûh„–Eèct¬Ž×Ù0gRÛ£½€t¯ m¤{Í+»Aé^S ª¤ *Z‡Ùkˆ¬ í3Qk t9l jó³oÏ€·7…ºô·gÀۛס‰!†-Ð)ÌI3‰)Ž +05pV!t¡¦+lPîvkmp²uwð€a¡¾×½X”¡rµ6 #ºé¡qb’ òÓCëd‘õï&¹à\Ú] Êhðhîe4Låêh;zþé\6ˆn'Ciccp;Ê l‰íOÅ”à¶SÀ>c=¾6 i¤5×c4ßpÆBeŒsF¢Ø ™ =q& ØÊÏ D‰T·øL2¨ª!!œ…p„ ‘“‘ãp¹Ð†¡dÕ#‘“=”(@…jÇAN†*QXR†^qö<=.¿H³“Æ÷Mª'›”¸¾Û9Dl9¢5!NsÔ¹É÷´–£ÎMƒ(G _~Toþ‹¨j@%È¿r*ÒeNü•ó:À^zÓ8¼—“¿òÄ›‰ø+#cdÀn`©PÕ›<–áxòWöˆÎ"úÀAX@õ&§ô¼25b;P¥±z“õXÊ ˆ+y æ¼€¸R¢$½ôx;´ìO+°axZñ€ízÄÓ `²õ„ – ö„ – ö„ ‰)„>¤"ò;‚ÛÉ‘r}HÅ1äsU¢‡SúUD}•èá‡~ñžÌ=¢5Ô¯bÔÆuõµ|ø'M‘aÕ×ò¡‚Éìèù­J.;R_W é‚quÛ€¼ =.o @R¹cÃåÑËo" kãå)Ì8D&Œ6dh‰ü¯c%Vèø_çÂ2t´%¬FÆEyfçòáoÇÂúad\”¨µ×@”’ƒÛ©!?©~bpç‹¢0f@´Õ‰hcA?t,¶¹:¨ŸØì8A Ò>`¿ ÒOìCELmÑ/ÇW|A¼:¦-,ô&$<T<8.g‚´œi¦‡Ê 8– %¶ç@¥m1Z]jX,5Æìü¢Ž ¤…>œ¶š@ä€ T íIjüq¿Ò"Ë«'üäY^Žð“[äD]²½ÀãdÏ$…®¨To J²‡g’&Ð R›Ìå$Ï„Ò!EÔ\?hJVVÅ\?h^‰v(æ¯M}AT±apšã”nâ `)S ·&|ü†,Ru"€ˆÂç†Þ`¢Hd ¢˜hjàÙË­m2mF${`b> •ªóÐ"õ–“˜L>È@& ²Ë> ä(“#D‹T “Àdœn¶+B*Fb´¾IR 5X#cDÉp`³‡G[aC¡‡G =HÅ@ä¨R1< ‹ #‘ã"½%„aŠ2ŸÇ;NpÖ²ƒ(;ZHnÓ¢±Iî†/bpøœJ;•s‚”ÐøA§b†ý&‚3Ü‘®rά‹Gkub1'Þí–×b” ´ÐT=0…¯t–7&ÇXÎPÞÓèÈr,CyOóÜ•;eXŽa½6ƒ´â½Ö£äÈd€Œ?CvÔt?:ãÏ5¯-cGÒÏsš|£:ÑúÖÄ%‘‘QRBµÓ>B¸)÷×ɶÀBW(DCP@üEôXb©Ú±ÐÝ;9ôù€¡'¢+1ÑÆT‰E☾‹QE¡E( ŸcLYb¨$î&3Ž(¨¯;¼– wÀº\ƒ‚t#ŠÁîcb-)ö”‚Çh±]6º$0JAæøˆQ*Ú¦vc©Ý-ëx~}[×áûiü Öa}h9I§c¤qŒž¢õ0½ü¼GÑz¾Ý~ SGÑ鮳ñé½8꽄Å÷2ð´;Æ(õ÷Ò3{©âŽzsy@câ›kï}wÃ4v‰»£ˆ}Iâ/×Q/wIÑó'È,1èý3+Qúpc&²€äÓËûóøïòò¶IÃõ¸º¹ ‡Ê9‰‹ôM›X{Ę¥Ì§ãÕ¤æ×1ȽoœÃ똥̗ǙÒjuW7¼š[Û‹ÔºaÌRæÓã¶Žú}[G{Œ÷8bäFí¢œ#F¡Lèq×——[¤÷£ÜZ ç±’ê@>Œäs/•N«K* câ11Ó!‘Ë£ÚO*U1R¨RuÃH Uù~N{LD4HTå‡1íšj‡Ï£@ª]ƒ×!Šª‰™ £Bêa‡1,R¯7Lc%‹\gËH"=»‰ª$…Z&&ÕIT©ê.¦‘IT©º*’KJbCp€ŠUV;ˆ9€¶™ («Á* ¬v¨€²Ú!euÀÊj‡1JIÑìPQ W9QE*«÷¦±‹’ä 9@…”ÕŽàËRÅ€x3‰UWàüØÉ|y½ÃåBqʪªŒ„m>ÿwTV=ÆÀ }‡…b,ÊêñõWS?ÕýÝ]ˆ‘©òûêýcæ_&—׊ѶÆÕq…Ò6ÊMO1F)ôåö‚•ÕŒSV ¤¬2²²êÕC•P÷=„^&!ö-ºÏ›=ä1ÙC¾ïï®W!ª¾Ÿ‰ÆÊVˆL½_Û !f·Ý¿“!³1¿‘ïc“ ¸‘BP¼=…nä`çÆ¯d´s1F: Ë9Ep³Që±™®â•9÷…xŒNoÕ/eo犷â4òÚÙ¹žî÷ò1pAæ< iü?ÍÁZ–YGùp¨˜ÊãÌÙT^!T§ÎÔLAÉ‘Ò!GJ¹or£:R0†èHé#¥Ü·¸‰9RnÈ‘²aˆŽ”9R6Œ\ÃP)F¡ô—rˆ: àH²iÃÀŽŒ)c‘MGBí±ÇïÐIB#TíPK•P{ìñ;ô‘ˆjÛ„Zª„Úc_yt¤Ä1¡–*¡:ìñ+Ž”3¡Ê$&Ô’$Tâ< ¡¡µÓö}:‚.²Ë½½¯iûÚB*UÛwXÛ/÷öþYÛï±¶_îí}MÛ'Öµ}£PŠßum¿<ØûŸb¡L¨©í{Ú>!ªÏ¦€„jY³ô1D³´!Õ³´#Õ²féb`³cJ %$T ÌÒ† TËš¥x/Ø,ÅgB”m?ì½EÊv•íœiÁ(Ûc³#a$¦A:LE¿¸Ø #†¨Ã4H‡©N/î¤ÃÔH‡©Ž/î¬4H‡©Ž/.Ž¡ê0zqs9M‡©b/n¯ÃÜЋ«è›xÄÀ: Æu˜‰†j_U¨ê0CÔa:$ª}MaL‡ihØ0°s‡X‡Á…Rd©‹† CÔa:L¨iÂê0x/X‡ÁbÌbr¢¼û‘‰ìŸCÆâRþ:­cñåôkþ1<¡~öž¾¾¼½¾¼L®uOÞ)5è!Ò¡Ú]eÙ0žß^&B0îî¥{»»_®í!F*¦ ®åü…NK8´X‹ùpoȇk‘¿p ¨ù -ë/ìå®=ø #nÜrãÚ£¿ð$ù}a§.ùí1+V¼™Ú}VìäÇ=äõÓ½ÜnÃÈsA[]ZÚCV¬|/mÛ@Œ\e w £ˆ ºqJ |/ç_Wב!ÿz‹ï%ƒ÷ÒëÂÁBs²]¥± ù×}y­{ÍEâ̽lÜ£â½t(îaO×££+ظG1Ä{éPÜÃÜÒ±Œg$_’ ÍÈ"I˜¶A&1òŒp5”1bL*‘„ŒßŽ.dávŽz’|6êvJõÝô8^€e6 ¾’|9Ì™H¢‡ 1fØ ˜a’<¤ÀÑ  á†£†xFLjƒ| á§Ó2Ò‘Ô$'Ñù¢RZÂÊÎ^N8 @D>PC>¥ç)¨‹µM’“ê¦F®» ™ˆ¾9èW@¯ @Œ<0(œÔ8q&Påd@>0Õ. >«|`š¥Ž$§ø@+ë­†‰»fÇ1p/Þ‹î›Ý0€s¶mµó(„½¼»µ-8æii ¨R!éÙ¯¦‚¯˜´Yz"ƒ u›Ž¹Ëê6o§ºÍ©Åetp –8–Õm "ÞNu›äàA„hêó‹uÈ,¤¹B )Jã{íé™rZô謹cÑ[sƒÒó44::âHϔբ} ‚6ˆè±Á6NJó}%ùZâv,¼Ä¥SšèÄf‘{réôI‹ùlêO̱×OÄ#ï-¥þÉõ?”É'ÿ©ûò¯÷§¿¾:ÿŠkïOúÕ»÷ÛkG ø 3qƒ—áXFë¯û“?’ŸýÏÖ(Ùˆòùó¿_F*Þ·ïQúÖïèç;’Ï(_¦µ¸·1’5¡Ôß»×úRÌ( Š?ÜzFùyïÞ:ætËét?/§;l¨ž¢O¿~¶÷ÛµfPª#Š×2¡ü¬›æv'PNå/#Ì\þòµ~îoo Õ]&®ÐýûeŽÐM˜1B×4OOÃCb`–Àçç—@ßxKŒç¹fÒÿùw†y¯·Õ¼´ß¿ÿ¼_˜‘~?)ïååe ™¹¼hXIóÔ=»†yc!Ì€â‰æÛó7ÝspêötúþõþGfv!L>­Æt¿½¼ùåÌ xÛ¾ýsÿÕþi)þPL«ÏƯfXËÈfüj¾ÿ®ïõu6# o ›§o¾áÉtáõõ©Îùix–Ô…ODüøi ܽz¦·<…î~÷è‘Øq5 ãjÞ†5þgXÍëÀ¯ H/#Ìçf|Þõ´©öãÖüjž>˜d†y\`üÑÔ3ÌýÇðÿ¿˜‰ ?vŸþÏfbŸÓÙ ·þúÊ<ðÔ63η`Œngâ„û úÎÚbÈ6ó b]w“»( ÊgòƒÙUµaÅ@{é ©|ÀwŸº²álæÑÓD€ˆž¦êÊÛÌ Ô• k3û®Y{šBö¬ŒíίÚvþ)el®cÈgàÛÝY¼´_V/í$>¦š®ïÿ_1ˆ‘fí^§±Îúv b;>såI%WÑ !æ˜ ¥¸ŠnDvF´˜ìm×£3°â&iÂºŠ®DvF@#IJ¤bÅYÐa 3b 8éŒP|ùæàŒ89VÜ•ØË¡ñuTòAi±N«¹VTÞx±p¯å__J˜‡jÂV’JE5Š jÔ(2^£¨!†# -Ò(²cD!Rs?¬êÌØˆBO¬ÃÈ×Á½Xu/Ó¤´îñ¶r¥é†!>Þ|¼Ùq _”ÈÀãÍ}ª´Ç{Ç ’âê›Jƒ«ÉâêÅ5§WùÙåÅ5bPÀ«ÉñÕ`!‘ÓW£˜9¬­Ç·ê|õ4PãÄX'+K÷»(©àñ©,À Áã®Ð d‚/fDÑ}1J.¸b< pÅ(ðÄô sºeÜÓÞèˆ P*ä‡éwÃŒkn˜êFÅ—G?êÛ@ÿ¯~-cÎCÛöEs½öL²wü¾ln˜ºÖÝ0!Ìè±øïËä?yyy­Ýèøh•üZ7ݯ—+Cx“ßíÏ@xþl^Çšƒá!«yºÿ¬þôYæ„'¿Û`^û³}BïÎ{¨Üý¥{» çÜ_žýn«æõesÃÔµî† a ¥…Áft÷þ”ÙÌÞòù2=moù\k°{êú×ç·2³™OSuˆ¯0™ Ó±ŒÚè ”™Ít£cÞ£Œ·zBq­û¡ï¾Bä󂲸Ô=JÿþóããGG ˆé%L/Ùwq‰F¥`zɾ‹š^RC ÑUvƒé%°ä¦ºÆQ°Ê `+,ìIƒLŸávsâéè¦Ï’Êy•ÄJ]®Ε…jËiÆTd)T[Qm©¡Ú ˆjË ª-Ѝ¶Ü Ú ˆjË ª- V[˜µ”Pá`ÖRIÊO •ŸET[j¨¶„TwQôF×7B˜j?Ìž$µ¥&Ô–ª-Wj5Xm¡¶¦¶4ºÚÂJÅðƒ—Šu´zŽ}NÕ^­£Ía;³™©íäk÷ 0«½uô8T]Ä\ ÄÞ:êþ]ZONÌjBÁÌêl(ó£Q6s´Ž763îhf3Ülæ¿O3ƒð’à:å|4íýý£înwætç€îŸÖÜÿ&²ë ƒNv¡u®eŠ Nki¯×®aP¤îã¨àu)Aºð4âO×JÒ¹§´rØ0ŒÒœxˆ‰úç¦xð!"'óTâÍ~KTúúãíF HîJ"™»ÚvO$s—´¶í®CöïAm»D±†žÈæ.ÙXCÛ2 B¸Ð· AáÂ… 'ZÓÃ…e,\x¨üi‰ƒMñ†T’¤lHŠX‰‡õõÔè`3BšÂƒÍ€%ÓAK¦Ä–L-™ò`ÉDÞN ¹t…Š:Æ1”úÓ©h.-[ª Áá¤êÈÓ"S>P8©byšR‰XExÚÑÏïà^Ž~þÇHë0¸ÒÏß:f%âv:ÈIª‡Ä`:œ¤:Ì×ÒÂ5Ñ*»€>`cJÏ<šPÌA1w„b ˜¸Jí•:@Éâê½#ÔûEPÌ¡˜(P1—I.@)•ºTêNV©”*®R·„J Ø¸‘ÐFBHuY 2Ä›!ÞÀl½àöF ¤[7®¹ÉÑŠR?Õ~ºoWÅÌí–6gøÒ Ç·[òQbG LÄûßæ ¿ÖõÚfÞ»{¾5ÊD¼ÿMYê“3|±pû÷—_mÜ®ì ‡¢ÌQ6bîoiQÖ7CË 45ìC´óš+65ð:DS£†¦†Eá÷i4©®/YZ,+ik‰å±e#$³£‚ÿéûéŒTð[¹QH¢u’é!gË Æ6\ÎØ¡Š#õ)'x%¡覆=™Ÿ¢Ý¨´•¤躘ûsiªJˆ"fÓÞP6mˆ"šq7”NëQ,±!õlTälˆK§É‘³E¦×.½a`ƒ£ƒІîà^Žúc¤ÏÜ ©¡·rup¢U²Oƒ¾cT‚4ôEt7HCQŒäôn†¢d’¾Azˆ"ºÎ¤¡‡(Øu~'PJàô¾¾2(•äô¾! =D±’ÿ†4ôÕ]”9Rzxy„1¨?¤/:ÖÂË!JànžÓU&“nê¼wëß)y†ŠWTÐŽ,±!Õဤ¢ô@’Ùƒä_Ð¥GÓ"sËÔ•˜ãlùˆ’Ð@ ˆN„²¨Et"tE(¢¡ƒ,*@dQ v"0(ȉp—YT€":jÈ¢щPCRÝEiX”‡)€®Ý¡ŒºĘ»¡ŒºĘëPF]ˆ"fÔu(£.D3ê:”Q¢b E-G” r]§;zB”sÔr#ck UŒ˜ƒ£'¤cvd]sJ?3S#GÕ˜1gÁx6¡1ãQ.ÄŽty ¤Ê\A¼K‹j> ©ÜŽÄÇR¥4d.ººp(ÝO ÕƒÔ…IFÃëÁÙˆãfŠE3_ÎaQ$Ž;‚Ò9nv²hŽ·Ç9Ì!ŠÀq{œÃ¢·Ç9Ì!J!—³ ºÍÝö8W6QPH¹Ìår] rò‡(‚“¿ÇNþEpò;ìäQ'¿ÃNþEpò;ìäQ´YyÄ¡Le…(bVQ‡²ŠB¹ Û1;B~ÏÆ1;Ê€|®¡|ΣÇÿCùœã̯qGºÈîÓ˜>‡åsŽŸ¹À¥X`ºBG») æ¢k 9äs~ 8_{b‘ªù\€"3;Èç1˜Ù@> ˆÁÌò¹E f6Ï(²T„î¬BÉ–X 7 ;«8gKÝYSc_Õ)ÙñÄäÎ"êÉVå ‘0/z%ñô·XœÞâct•z*%|‹S¸X¿çòüOj 5Ôòø#j5Ôòø#j5Ôòø#j5Ôòü?E{Ó«ÔRâ¸ÎdQ£Ç™Ì!Š”.ë®P*–Ђv8_6DQêÂþ_îæ)‰@g åa RÔnErÑ>ü“&h)P.(¢þß@¹ ˆúåb€"êÿ”‹ЍÿwP.(…H¹ð-Zh£9Â?gÏ€ƒ®'üsö`£ÅSޤ·ØG1¦ëÀF¹Ë>pu뙕¨ñ”ô%%v¤?é%U&÷˜^‚^tQo¡Ö1§- µT{K©À©t虋¢u¬0$ÑBQ¢5H¢…(¢D»¡{6DÊθ#U¢™ csÂÓM°N7晩<*DcâQ!Š<3ñ¨qÝñ¨E´FêžÙQ…zò#5¢bG* QReté%%èEe !J*¾#H»Ô¦Ä(v³“t–¯ ¤Ýì  sT{¸#â¦Ñéf‡›>ÏÉsý¥ihfÂ:Øôç±lí4¯×aŒåd#ÔÇú‡ÛÀîÃÄçä.{éïÑŠ=Æ:k÷ˆ1­c𵝱ÇȽ–qð¾!ø`,¶]1 ¡þ<ŸV¨>Úc”ñ<7ÏÉ¥0*Åë3N !èÃÆ~Ï]nÆí1æ1ŽÍÎέ~ÇpÊp¨uƒ1TZG2Þ †4x|ìûsD{}‡Âàñå<Úk´Zv‘k£ßcsŽX‡4x¼mæyÎm1*¥.{ì{LÜ‹ÕiÚËÒ‚ÿ<4¼AÌ08š="3Ô.¦Ds”CÍaY™±»bd*SMƒ×‘Ç1¦´Y•±çû©+c'δŒ3öùn5ƾaTºppm‡1,}wÅ4vAÒ8yRD$C»Aâ!I‘| È,Ѻ @2$í˜3É¥WÓ bÕ¡b¤â„K‚T$Фb8Àp?^G.at¨H@œi)½ÞŽàÅz•#Vhïx/˜"q"˜T, È,ÑÌyÈ*–0g2;…Êê\…ê'Ò)ÊHvâaƒþ±6¾ÞŒSVU…&Û+«Ç—7¥ìô÷öÚ@ŒL}y×Aöâó˜¹ê—ÇÇ¥¡Üˆ1ºö×AÏÃHYí Œ@Y=Ö$ae5CʪoÊýûwG` e•ÙKØ™i¯$.ÃÐE"Û7Ú<Ï€pëdñýïûlF O£5¼1Ó # öß'%‚Èäî–Ng+D®Þ‰ŸÝ!¤ñôëtåF’„¸’ÑFÅâhÀiü¹“]q°s#óø–™ã iìì\¡_/º•½+^‹sÄ:ä‰ó°ñÉ– È1ÏZ_ì ‘j;Ÿ7ÂHŽ”9Rˆ8R:äHÙ0°#å 1DGÊ 9R6 Ñ‘Ò!Gʆ‘kª#eÃÀŽ”Ä)P6m•’Šê•¬#c,Ž”“…=~åÑ‘r„‹=~åÞ‘¢ªv¨¥N¨c–<"ÔR%Ô{üʇCn{jI*q/¡º+A¨¥J¨{üʽ#E#T†Æ.qmßam¿ŒÙû;mß'éëb¿ÜÛûš¶¯m¦RµýkûåñjSÔöµË­HmŸÀ€Ú>!hû®g8j…iûåÞÞ×´}C"Ô9Ÿªfé TËš¥x¢YÚ„jY³ô 1°YŠ1°YŠ1D³´!Õ"ÑOªeÍR¼©a°ï{Ú"e»ÀÊv öR0ʶ·ænB™˜0åA‹ÖKµKÈ/vñ;Æè›kÛ·Îÿ§ù1RI—j.U_þY—j.UÑ/?ÞÛs!êR5Ò¥ªãË?ëA Ò¥ªãËc¨ºTE¿üx Ê=†¨KÝÐ˯ÐËŸóõ5]ª¢_>³Y—ꈪŽi:']ªF"ªÚ%Uu)Œ!êR QÕa$©¦KÝ!Ö¥0Ö¥0†¨Ku˜PÓ*QÖ¥ð^ä®Ë³'jon¥¦ªå|}N ÑÆü¯7ä=ôŒ9`oÈk‘¯onP§ùú,ëëëå®=úúN’n¬ÆR%Ý÷?Sî¥m;ˆ! Ÿ.Ý[×Ý †QîÝ—€@ŒL>¢K‡ Ý ³ŽB˜YÝ6=~/çWב!ßx‹ï%C¾ñyL´F¼—^g†öV“}ã-!Æ,˜{)ؘE1Ä{éPÌÂ\Ê‘{éPÌÂî]ÊBG$ÈÇ 6fÑAŒBL"Aò%¹ÐŒLÎf @$ 3uÈÑ$L"‰¢‹˜$SÆÌêw€@!#I"܎Ñ>R’ÏF]I©¾›Çú hœN' ‹£}|: ˆïkP¼/Ià¼ðÛ0pÄc1 ò„œNË @D>PC>Dg„Ô$'ÙùíO¢RZ Ï^N @mÓamӃ䤺©‘Zd~Ä!J…ôÍ*œ¢k%É”©½œýðEådV"¶ß_¦ci|LÅY§ci»É)>жÑç`íÕµp/Þ‹îWÝ0€cµm #ؾbó´Š4T ©ôl‰WSqÒS¿|5À@ AÀ¬DÔm:æv,«ÛtD¼ê6ÉÁå¬é6 É”ž(XâXV·!VRHᕺÅ|ÀbÝòËX®ÃH¾šJϔӢGg̓ˆÞš”ž)«E÷­èw@2¥ã=ž)«Es+=6ØÆIi> ¯Ä"ß@KÜŽEÎä´ @”ÛA\:¥ù€N±z7®ÑߪG'sî.pžO-%󀿹ÁÔÈ ZJ²†´bÈÒ<Ñ)'’¡Èó<Q;ŒÛK¯G¦rÆ©Š_猆ÓF»âŠAD»¢†œÑ°Rß:$Sí;Dg¤†Ä­Dè=÷ÇÔVòÏyìîa~ÛÜ’R)ÔpéØðh³¹ªšô ƒÈºZ‹é$MXMúŠA:A<Ú⮚&M¬DÎ;‡ºšºZ=OËÔÈ„ÔÕäR¢ Cா?Þ ˜ÎìpbO5ODn…BÀþõ¥@zvPzfPzvPzf¼ô¬!†}%-’žÙÑWòܦZIë+é #¿;÷bÁ8¼eèn1¯D®]Ù0Äwwƒï.C£ G"ï.C£ ƒwwÇ òw¨¤å@Is„’–ÓJ¡ wFW“ã«Áü=§¯FQŸM„è°(ŠcW¢xÍì’ièƒz´ÅC ¼ôÜ`pj๭!†h—Ü ç¶ZÀ¸@ò˳³x°0'‰Íâ0G#($@ ¸©µ<ö¨gÇM¾î^zw‡™ÞˆW¿—„)Ä^à½(Ono7I}xÁ½¤¬œ¿C x/}12½ï¬~/)+êñ^ m/×øècׯ@–¡Jó\y/©=•ö¿^ †¿—ÑJ0^Þ^Ý<áÞµîi¸_GÑ ‡Ž¯þjŒÁày]æ5ߟۺ̦b¤¯_EŒCoA¡k¬Æ×+– |½˜¯ß F¦wIUè´¢ù‡#ö‚ùº‚a_ïÿ8æLi|ý 10_ï F¦7ÕïŰ|ïÛ Ù]»'ÕV¸"ˆThév×ìIÙˆl±Ø]qŒ²YÑ·»Ú˜ÉV8=½¯”W®ÕîJc£G¦rË=²ŸÔb£§…ÉYëMÞHÉZow‘ê v©%GZN<‹ä²«UÔ‰HáFª7T^Ɇ/E<Žƒ½ñ©mµôبÞ0T><ü—L`I²±Ç”?QÒ ÊÏË/ 2j?ÞKúï7¯ºŒÝÝ”ïMóÔŠËõ[sÅ fjx? ¥y^ÔŸ_÷§Úõ÷û Z Ùòçñß do#È÷ú}ø¿ß$Ÿ±îÓ°ç·WïZ¼z"¹»§_¥ö¯ï?1H1ksÿý»hsD½hsoï/׃”3ÈgòúòæÞêI%ì_^Ú¦þá^ž1HµÈü/s#ðI77¯Ï®ÿùŽA¼¯ôó—©…ßó·×M9½=ÝïOOØ ¶Ë¸ŸÏÿúžä/o/ïîímRÇÚöÏŸû°ž–A™åAO~Ö½¹º®'Eùk}ýýýÞ”’L*ûðÿUö÷··z^ËSw¯׿ß:ÅÌ;ú<¢¼¿Ç22”¦¾ÿù¸¹ë@ɦ{ö=ãç{~Ÿv4ÜóK3üóÄ<å™nÇgèQ†å¬(ƒŠx¿ÿbP J¤±šÝß!Fª÷{ÔØ}±{×ô«Éâ/Az‘o±¨«`÷NvkûÛ Ù]÷iíµ1Û©^îô³n½ct™,0M2@†Sm>C)˜íôJ0Ûƒäx;®GÛÉ ›ÙkœÚJH@öÛm²NÐb")YýFaG«ß\!†¸—ê7û¼oÕ·£|Šõݹ€¤Ð¸w“’FI/[š†h^Ý IY³D9Õ”¦vѰa¤zS5}/¬,SÙ19:B"Þ®*p€’ Z–»B-+@1q5k`«PÍ P2¤fÉJ€’#5KžJÔ¬®&PJ¤f5ÌMWHAzaP,RÖäRݯìèH9ùœi×'öw^œ÷ß?0H@ºSŽ‹[@Ò Í·?Ÿ>ýûè!¼ümŠôO[Ö«Ôb9Âíq&+Ý~Ùèv¶¼FºuuƒA ¨9*‘eùm 1Dͱ†,ßÐ,ß)WS± N1d¥ Å{!•cW¨'¼?J5‘ÐyOƒØ@ –=@=Ù@R(EvŸR™cK©¡ PD1xƒ¼$@Å` Å`€‚Åà•@ÁbY ƒ RBÆÜt…iM `1HQƒ®Wa,²>é‰Wvûe1øßã—Ù¬÷-™|]ûáÞ_02k¯EF˜µ­ïéÞ»ßó'm%3ÀŸ2š?)œòXQvfÚŽPuò( uGè:ù?iÊŽL´9ÏŸ 0ð'AÝieu'ßó'U®Ê¦TŽäª#äjNÊÕÖ)†rBý\ÅQ/>û¹:èç*h† ØÊ‡b=a;ÀÏUrC4ƒC$”òPÙÓø Ñähà3 P°Íq'P°ÑÑ(Øê¸("þV½£‹J.=áå-O#ù÷„›·Ü{4Tú—™\‰è¿'ü¼%IÿñÑHŽÉ°¸’Í­’A“T‡º¶·íàK PDØÁ— `x%P°@l,k½DÅŸQÉJËF¸P1­ŽJËI3u„fZí•U5••–Šx‰P5­ø—è´•ä˜üÁK¬Ø—¨Ôª%V–‰›x†·l21b4ð–í^&ê¤ÖPÝ6P‚Ø“²}– ” –§[Åõt(6$È’Bã”˜XÀ ²¬.§”®¥‰,A¶CAt¢ˆÜ©Ct¢`îtUP*¼!ýlµ6¹ÏVÏÒ ªD3ÞÛvœ®¥Ù=Æ2ãËÂàü¹Ö³¦}Ø\ÔM³Ç˜]¿Û^ê÷m/ýXG¶`|Ù0¦uxŒ«k;¼Ž)W÷ó(“¿n{™ÒÌîÃ2®WˆQèõÍ‚ý²Ç(õ:k £RÚrŒÝú°ZY1¢±ý™Nµ½„´®Ñ)±yÎ,Aëá„‘Ö‡Õh4è9cLú0z/Õ.ìs|/˽èï¥ iL|/=³Ž*Ž1¯¼¹* 1ñ͵ë»b»èµÚúƒ©‚„=¥hœIÑÓežŒAo—YI¦´k   ’õäºq?£ã.ƒdê §±í,|y׉#ž©³ÇÐ¥Ìux57ˆ1s€/Ç×ë ‹§º¿Ç)÷ù¢o>ÎÁ§ic¦ëu8”ŽX2B­Óýi Fºa «Xc'ÏÝp¾˜¼íÄ0jëM«ŽÜã¬5H«hîÑ‹\¬:qóøz¤UGîqÖ¥¤UGîÇPõ±ŠæŽXG©·ÒQ^m…¸ÇÜt^ÓÇ*š{0{‘õ±‰¹ê!M€>V#1·a`}¬†¢>Ö 1·a`} ŸÖÇ0ÖÇ0F©÷R 5M¡"1·a`}Œ ±‹ìÛš†hÒ!AÁhäÁµœ¿ÐiËÃô²˜÷†|¸‡áer«$ʼnk‘¿pžÓ¥ù -ë/ì{âL AÒSÀUIg=®Å{iÛb~ÜCêß‹Qý¸óý uY{ŒL©¬K{èq-ß ³Ž"ÎØÇùOð½dœ]]G†üë-¾— ù×Çš;…Ú}hN˜°§3C{ÍÉþu•N3÷`î¥`ãC¼—Å=ìÁ--öåj™udÊ´3ÈÇ 6î1¤{ÁÂäB32'¤IÂørJýÅ Fï3¦ˆ˜$“‡‹» @ ƒRˆp;G =HI>u%¥únz/ @ŒÞ9My8H¦ ÷S’O§'¶#Æ 3L’8  7 5¼A 9 ò„œNËj @D>PC>D§Ø€ªWä(;£3ùTJKXáÙ÷ ˆ m:¬mzœT7{DÒ7}7,|;9©pº+É”éß½œªœÌJ iöwí0ÈÁ\ÀÚa>S| •õÖ Cš—í®®…{)ð^tß솜³­¬snF°ü$?ÌÓ*ÒP)¤BÒ³%^M…¤'2åÕ{ AOlGÔm:æv,«ÛtD¼ê6ÉÁå,vMÓt›dïs{b‰cY݆XI!…hêó‹uÈ,¤ÁFòÕ4Pz¦œ=:kîDôÖÜ ôL¡½¹kj ’)“ÌôLY-š[‰è±Á6NJó}%ùZâv,r@.žø@lJ0àÒ)ÍtŠÝñ¸¿UpŽ Ó$/ö¬UàìÊÅÀqÅHC2»¾´š¥$kHf×—6ª!õýÍu7¹ aÀÈàL÷pF³ëK«ìE_oF²+:È §!vŃˆvE 9£ÒfW ™<çqFÃjHÜJ Yžñj+#Ô¯óHx¤PÃ¥ãH`À£Í>æªjÒ7 "ëj-¦“4AºäÑfvæa;ô†Ó„Õ¤ 9wêjêjãt{@õ¤®&—#mwõãäñ^ŽÓäc¢²×} Eól; bd7?û×—éÙAé™AéÙAé™ñÒcÑWÒ"é™}%‘˜V¯[Ië+‘kh6 #¿;÷ÆÇ{ ¸îݵrýˆ!¾»|wÙ>Ñ@ 2ðî²Ãø1íÝÝ1ˆ¤¤ùÙàjr ¤9BIËi%Mf"ùAI‹(Ïðjr|5˜¿çôÕ(ês~¸šxt XÅ¡ý…P7F »d,tÒv_ µÕ çv_!©zn1†h—Ü ç¶ZÀ¸@ò˳³Øs£h^-›Å¾ÉPž8ýýöDä¥ï·'"/%ý~^‡,²àû-‘æÛ¡—’Õ|[Ž_ž4߃Ýésü‘ÝYÆìÎC„½%Î$Å$/8IYÛæ†AŒh‹ûœCt&`kdkå­Eˆ­†¬¤B!Kï<´VѬDRà “¢:2ÇHX ¨áË”<›*ÂŽºžƒ{9êz‘‚4¸R×k• ™*¦†,Wø~³s:ï÷8ÚüUûèöZC µIíb€Æ„ŒZô^hŒÂ€í££Aówí£[|¦¸}´Hd¨}ôHrûhó7í£eòàÛG·¶>j=Ó†Ô>ÚüUûhåF@;˜éJÄöÑæoÚG;Y<ýEûhb/°}´r+ Ìr-N#Qº}´H`|ûhQ* öÑÓNÄöÑæ¯ÚGkáÚG,c ÙÔk§A¶vu1`ûhwƒzûè¶—‰¶^e“#ÖÛG‹rå/ÚG÷bŒdö‚ÛGk„浅 µ$ µí j­*Û>Z;Tª}4 Ô’$ÔcÀöÑ¡²í£5B-IB%ö‚ÛGk aÛG»b@m_Û Ù>ZVÅ`ûèÍbhñ^ ¶O`@mŸÀ€í£5BeÛG·øL¡2{Áí£5BeÛGk„jY³ô1Pûh•P-I¨Äy`³c`³cÀöÑ¡²í£[|¦Pƒí£•…°í£1„®lKí£Í_µå-Ñ>ºí§öÑ͈‘¢ÖÏâiЭŸ]ª¢_¾L¥|ëgY—ú‹ÖÏ"b[?kºTE¿|æ^`ëgâLaëgñÕVô˧h ¶~VB·~vÄÀºT 1PëgYDÁÖÏ.u‡X—ÂX—°õ3[?÷‚u)¼ÜúYãìlëg‘P-çë[?›¿jý,ê_´~n1lý,ž©e}}Bëgó7­ŸI[?¯÷Ò¶Ä­ŸIwƒF}¸Rëgów­ŸE¦ [?¯÷¬¶~Öh=ã|ãê:¸ÖÏú½°­ŸE&ô­Ÿµ7—q¾q•NÙÖÏÚ½lÌ¢ õ³³ø‹ÖÏÄ^`ëgb/8f×[?‹¸õó&`Ä`Ò_´~–%Ìß´~n ØúY¼Üúy2b@éoZ?«·S’ÏF] ×úYy7¸õó"hœN'lëgõvJòé0+­Ÿebã[?‹r¶~"~7ˆ[?Ë”–p‚ÓiySÑúYáÑú¹%@`ëgf;˜ Z?+Ú&ný¼©›ý ƒ€ÖÏŠ^ƒ[?o §»bØú¹'@ Êɬ¶~Öˆmý¬í&§ø@+ë­ÑúYÛ Ûú™ÀŽÕVÖ9ÿ¢õ³úô*ÒP)„ký ^MÅIOýý²­ŸUÆX‘³ØúY½Ëê6hý¬é6°õs Û4¶~f@°nC€ÀÖϰ­Ÿ `¹B ÐúY“ž)§E‹­ŸÍ_µ~Öø@ÊjÑBÃeó—­ŸåsMY-š[ lý,?á”æúJ¸ÖÏàvØÖÏ*°­Ÿ™í`· ±ØúYf&ÓúYÞßúY¦XÔúy³”ÚbÀÖÏ2½ò­Ÿµóȸ½È¡gºõ³Æ §!‰­ŸÍ_µ~ÖÞža5$¡á²ùËÖÏÌv°]A¬¶~ÖVB·~VAØÖÏͧ «Iß0hý¬Ó hýhÒW [?ko8MXMšX lý¬­„mý¬-„ÔÕäR¢¿hý¬í…nýÌ€@ͳí0lý¬ŠO¶õ³¼¾õ³|¿/=ñ:`ëg™“ð­ŸåCÍX_‰\ÿò­Ÿµ½°­Ÿµ½pﮕkWþ¢õ³v·tëg¿»;­Ÿå«á[?Ë»Éi%­Å뀭ŸµuЭŸå÷ŸÓW£¨ÏÑúY¦ø¿iý¬£°­Ÿå£å[?Ë'‹Z?ž[¼ØúYÃ`[?Øs{‡°õ³z»lëg„mý,ƒüMëg™Fþ¦õ³ÌÔøÖÏò —¤ìTò·ÿ¢õ³~"lëgm7lëgm%ìûu¶~ÖöB·~f@à –= ÑúY½`¶õ³º¶õ³¶’$em›­ŸÕ3a[?«‰mý,³¾õ³|9ÍJdaÁ·~Öö¶~–µb™€’g÷~ÖöB·~Ö6Cêz­’!ó­Ÿ5¡[?˯¶~TWb%°õ³¼’¿iý¬£°­ŸeJá[?Ë„biª'0`ëgùrøÖÏÚ©V¬¿A ØúYÛ Ýú™ÁbüŠA`ëgÌèÖϸuÌJ`ëgõí±­ŸU¶õ³òW­ŸU¶õ³x²ÑúY¼bØú9 x°õ³†A·~Ö6CJœÖ1 °õ³|¿ÓúY^Êß´~VQØÖÏê†ØÖÏ2Èß´~–÷ó7­Ÿõµ°­Ÿu¶õ³ŽÂ¶~VQØÖÏêá²­ŸÕ•°­Ÿå•üMëg…mý,ïçoZ?ë(lëg…mý¬£°­ŸU¶õ³ ¶~–Aþ¦õ³L,ÓúYGa[?«;b[?ËKù›ÖÏòRþ¦õ³ŽÂ¶~VwĶ~–—ò7­ŸUºõ³¼¡¿iý¬£°­Ÿõ±­ŸU¶õ³òW­Ÿu¶õ³Œò7­ŸÅ+ú«ÖÏ: ÛúYßÛúYFù›ÖÏ*ʾ”QjËÛßâ5Ùøo»‡86ýðׯS^ R½ù«°ƒ˜sœ¾ÄЇþü&$ì 2í,®í-^ƒ‘M=1ó6"õÇÙA¤zÛÖa#5‚0êFú›¶ŠœÚH«Å®tJluêˆUm#‘©sSñ-i|#îç·×—Á]‡×6ÄÀ@Úν¿@Œ¼’¸ÓoÂØgl =F½ÅR#ˆTi©9 ŠwRî^‰Ü Syhåþ•Èo5»ßAäà­ÆCæ;ˆ݈“!v:‘ØMS¿’}ì0Þ=ÝÉ.t(w~T/eÁ€·Èî1ൈvÃ@÷¢®#Qe’Ã2©<8ƒOBÉa¡Tî}Ár£Cý^î^T:M¸{qÄ:à½(¯v§·ˆ½Á½¤ê½ÊÆ0z_?ý^Rò^ˆuÀ{qÄ(T 'µGŸ¥SÂép½¸ŽêØ3I膧ñÂc5ÞýMç…UìÍÅ:·)w[Ño.ÖÚc`^x…˜*ë0€vèÍcÁ^Ø!^xËÊô{1,/ì æ…ø< ¨çK<ÙîÚX¨zþA¤zw0EÏ·»&ÊF4ˆŒÛˆsWèùƒ¥÷€ iØ]ʯb°h« Ùþ³Ø`iáFrÖò’7R²–×A¤zÃ&ÅòÚ§(hoD„H.» 푈ò`ÃHõGÊ+Ù0à¥hë`oE;ýZzloØ"Ï#Ù‡ÔË½Ê ôåÞ!Fªw­Ñ.7á.wགÁ2AQÈnôbtæ±a€ËF™,—[›¹J“]œ¡!k'B>õfà“iñ©–ìóW¤bŸÿbˆ{iàóß§{¨æ‚F!)÷üe»%IIq+äï1DÅáŸLÊ \u,¡jçEn‹÷ÂòvQ JŽé вCKYÍ@Xikˆ!rÕ’ˆ¡ID[GÅò²bÈï¿Å{!ß¿lúËÍ( ÑË>)b82“Û$;„‰§ðÄì@¬²Ä“c$gE!E9Ùœ=©IÛ‚’q'«0Æ‚>Y…3’)T†$ÒlyšjûiU” ¹!ù –䆤6@ HÎ’Šx´Õ1|«¼ŸVEIÈ$¿ÂŠ?§ä,?Ißþ ­ÔJÂÒJ£ T,oº+ %{ËHš°´"õÞXPÂýˆÑé{4"[ÌÿÞû«¿ü·ŒW~¦· ÖžoEâz÷ã1Ò1ª;ìåßoßf„©ìÀ=µž¹õ·NÀ8F†»ÇÇÈðËûÛØŸåêîî¥íîMÛþ|©Ö­}ra#b¤Ì‘ÖQ‡Ï"Uúñ´ƒ„Ñ‚¡`#†Üˆ² £od …êÑNËâX 2n#1)q€HÕØ¡¾ämðFrr#B¤j°MßHH«A¤Uñ¤uE©YÒ6RAÒêÐTôô ‚HÕPŒ¾‘œ }*‡ÄQ(E¸xwr*·»\#aL¹9cdjâÀO¿úî'…aÆY`SÿìoÏ/ÎwrýÞ4OísÿìíLˆ‘ëøüùßý:Üõíý½®Çu4?Ið³ÿ…Ï#Ÿ0þ󌞇Óx×ñóz»6¿ï?¾÷¿Ÿ!F1b|ùâ‹é‰ät^ǯæÏpª­ø^7ŒrZǧÇq/ïžFýh´ãëýzힿ߈áG }~ì>-óÕæ{©¯OÍõéÉ;wİó:¼t}¤«¶2vØiÛ?1ß<Õ˜Æ.€PeZ?”¯m„º ‹ózOûä§Å}k Fª]Ì@ìòËß0À£‹Úÿ+F÷2M¾k¾AŒªpÊ:Røø ·a¤ˆ ‰ªdrA\È«-€  )zvâÍ &öîêëöîjddD>}ñ *}-߈œ{r·®‹Z…'½¼ž8ØQ‰»* Þ “Ó‰x°»%¶’ÒÉ‚é¤Á N:b;˜NL'7 R -rFRªlÍa€@­n§$™´Óè$ƒÛ\:lÚiÛ1ìÑLèØ‹Êw’¢+övºâ”¿b™¤ü÷ÚJr¸tÅéN«Ðߎx;Fâl±uð` ÇÙÆ·sÅ øít H·ƒÖV*=ð­¼ct’G¼T’gÇ]nŒ2’%sË´q­1?yv”"Џ¥–óž}#FßÈì–Q7bÈàUèžxYË¡GE\OÜHF–µ`ݳ£o9ʼº>çŠ tÏŽFZ$­ÚHÅ“V tÏŽv#¸‘Å-£n„½‘¨<È)ÏÎMóÏçgÏŽÌ={#§0œ|cWåâ p®OùƒÚyLm!}­€æ”즮ä~Q®Æ]r;­HìGW=m;†¥4ñ`S~;â«9êsêÁŠgbØÛq­ÈQO  45å•ÊaÍ£o[­y,野V+ Pµ²üâ,ðC¯é{y#·ç®U+ˤq¨V–#2ŒU+G#ÎݪVÖ6’sÑ J6ÄqG¨ZY#ð’#-×J|'Z­$m1Pµ²|ÇjeåRDV+ÇoE|j|µ²|-ÑjeÁ—%Ø©ZY»\„¾Ü;Ä@ÕÊ-y Ld Íeb§«•ՋɨËV+o—[0ÞÎxµò’s¡Ú^!ŸŒl òÕÊê©–ìó¿Éûü¯U+;bš …¤Üó—•—hµ² 7Ü ªVV.7e®r )M¨ÿÎÞlIn\ç}!ï8•¢”R^ö½+¢úƒr fQ.¶%Ù¦ÂO4¦&késog_íÕ$„ ú¥ükeõ.¬n—íTüµrEö¥¯•5­ÚÈ ,‹Tb ×ÊYDþ¼†•9”ã_+«w!忪”sü/¥,D«(÷èkeYE­µxr­µx•ì¤d‘0þZy!‰¢P6c‰­¼ ¤e}¥)«hÆèkeA!‰<­¿O¥¢<’•cN^(þZyÉXVI­—ŸJE¹$KaÁSÅj «DÖ¿á§¡\X^ñ JÁê¦FÉÙ¯,¯•…¯\*(Y3‹²Š‰ÖÝ„ ¿BÍÌënÇ<àKË53sjJp\ÏšHÝM©UE5¾‰Ô»”©ÉÚ].äÔdí»èõ®;M+Ö»4š‚z×}z3AÓ+ªUi ;Í:@ <ÍŸC®wÉS¤÷°Þ¥}—„ü.Q…h¨zרó#Õ» SïZjU"= ZæâÊÐpÓyVï2Çz—ªÇ0FŠjfß%ƒºÓôŠjU¢Ìíë]š.ôëÂb`]ˆ1RT3³ëÂ1®p…ômop¢F-¢ØAàA%‚@5ZåÇ&Ûx±Ê–]Äbô€DÖ‚Ûz—V¬RN‘QJf†¨w­^ÂÈAÍÆA~ƲƒHàcšAÀa-â)võ.­V%²ç®Þ¥II ü("kìê]Z­J£ûY4zä„.Ö» UïZ}\„zl ~Ü ÿqˆu Ì ¤ïµ*™A.´”Ö»¦+Ô» Wïš5ÄHá ž cö€‡¸‡¿„д"0ð žbdð¦éUÝëŸÁSœÁS"ˆD_ Í5ä /Ïà)ÎÎàè"±DqAÎàñò žâì žA€‹DsÍ9ƒÇË3xг3x D·7±V̵+NÏà)!”’*@ øQ¬rzƒð³ˆâJÌà©å\sAÏàñò žâô žbàÛ@ ¨e91ƒ§†P ʃgðÔr®¹ gðÔr®¹ gðxyOqzO 1 JnÄÀ⯜ƒžÁã ÿbèêk’pâ/{gfðÔ;{^Æ gðÔûb@Ý.Û)fO-çš z—gð§gðÔkU1 ‹ÈŸæÄ žb`]æ!’ÿªR0àx–ZÎ5ô žZÎ5ü žZÎ5ô žZÎ5ô žZÎ5ô žZÎ5ü žZÎ5ô žZÎ5ô žZÎ5ô žZÎ5ü žZÎ5ü žZÎ5ô žZÎ5ô žZÎ5ü žZÎ5ü žZÎ5ô žZÎ5ô žZÎ5ü žZÎ5ü žZÎ5ô žZÎ5ô žZÎ5ü žZÎ5ô ž ÷¾Bÿ¬ØûeýHÿl4)÷¾±þYuv>‡šãúV‹“}«âUð܉ å3jîDûV‹“}«"=ñ܉ å3jîDûV‹“}«ÊE2ê"B.1£æN¹oµ8Ù·ªpgÎ]¤Âˆµâæådߪ($Ä܉ å3nîDûV‹³}«"I‰¹AË%fÜ܉ å3rîDûV‹³}«òǽð·P¶ Aè¹b@-Xyˆ>®KÌȹAË%fä܉ ÷­gûV5ª’"£~Ýœ… ôÜ ŒÅ¿„–ü5I8ñ·ò‡91wc`Ç¡†ØsP0è¹b`ßc@Ý.zAÔ܉ å3rîDûV‹³}«2I Í"•ƒE4 zîD€X—yˆä¿ª 8’ h¹ÄŒœ;´\bÆÎZ.1#çN-—˜‘s'‚–KÌȹAË%fì܉ å3rîDÐr‰9w"h¹ÄŒœ;´\bÆÎZ.1cçN-—˜‘s'‚–KÌȹAË%fì܉ å3vîDÐr‰9w"h¹ÄŒœ;´\bÆÎZ.1cçN-—˜‘s'‚–KÌȹAË%fì܉ åc}«b⫉ª•Û°ww#¦ôï…õrî)‡“ã;FBÒ#¢–FŒ.¦' uüÞDºÍ…ÿ¼1}²€×‰YÁ„ý8"£õ †å4‘° Ö+ KX‘&†ý:Q›±€dLÆ·‰¦koÓPÚÿQÉV€‘2yÎueï “a”4I“>)µ§„¾1¦žd/}ʧ‘Or!®ƒ¾ÍAú¤|‡J“½ôiœ&Ò$A×™‚sõ: ÏóQݘƤOŠÕ“VrªXÉæ6¥æ¡äLUT—dg$G°Ÿ%9ËA¢LŸ’í$ôm…å׌’œåÛ¨'a?NÔäd¢äúU$lÂ_'j-2QrŠ41ì׉f>Œ²6~ü×Ç=¾œäúù ­Br½r‚ëgÕH9ÉõÓuâBœ“\§‰W@ ëˆ4IøëD•cNrý°"M ûul\ä1®—=œ˜b*ŸT€qçû£¬PHG; 1î>[$ÄX¡7ŠÅ+””¥K­¡Ö •©›ð7j½†’±Ô•ébØo 4V(åXGåPé>§)ã¼Ë©ÊÅÉ×Q¸P!ª+W()K¯¡6l‘©K»×•v£„ýÒ­ G9é`;Ya®P2VKEèr¡µ”S´Ô…ÖRNÑRZK9EK]h-å-u¡µ”S´Ô…ÖRNÑRZK9EK]-iþˆ‡CËÆ¹¨[GaÃn[j(†©Íëg9xë(TXG9zë(õ¢ñÝÐFBjo9À[¡6KS‹(¼öÖn”°tiIko9È[¡d”X¥ ©ëÛ8¡œ±¥†’±2]‹(Œ(¶qAÉHÍ;KB'BÅ °g‰}£„L-¬’rµ†’‘r³$ 5VÚè°Q‘£D‘#AïFÎbNSWGÉ(”øLœw¿†ŸÆu^áGéÆ˜ä¹r®òk3 Ü·“YÿŸS|ÿþaí´ÒøÙW¥ßz»qŒ¡çñëŸþnóöý£;†ëÇ÷·­{vUãÄÚxÿ~ý;at—§»8kmùì½/!F:Ýåq¹K1Þ¥õUm1F†hꚦMk•¦›æÙFM|—uólì.ŽàtKS™?Jˆ‘!þb\!5#—0Á§FøÔyL›„á ^Ÿyì0{i ”Ìe—dºÎ×å:s.»ªüsY–›¥15ÔwbÌlÖ}Äîéî1Õ×ǧ™Ýû»Ì¢Û´®ªñ9ÌÄ"Q6klãJˆ‘ŽwzÌ==Âs°u1F5žöwéËs§ºJ™t? JÝmÛ{#_dþ.ãB‡Tê‚QÌO “uw™ÏÑ bÜâ<ÖR<–©à±N a ÇZŠÇ2Çú0òXFòØ&ÜŠc‡h_’ýC´/5’ýÛŒ!ÚdÁ€ö%` Ѿx‚Ç `_Áci_|l_Äí‹'x¬öÅæxýþfßb”¶é¾Kxépªb$’VH«;.OëÔµz±çÒ£V÷H«.=hu‡´zAsé¶5)Ž‘)Ët­^@.íâI =Š/ÉOqеǂ!ju‡´Ç‚!ju´Ç‚µ:¾ Öê ĸÆåvò‘ÜnœäXŽÅ`7w úw¹íâŽHV£(ìÆÅVË‹ÝPÜ1ÔttÛÖÔ"ú£‹:*]Üv5µðxÌ#·#=¼‡ˆU…Ï‘Æe¿êçCþHü±–ÛòGŠâÒ Ó#åâÒªÂbœÎÐã ât†W@€âôÛ6"Tãt|—T¬"ýqyØ L¤¨†È DÒ }W× +¨BD3µhbq.§™-œÌY\ÒâlÎ ²‰èB¬@R9“ò9—ËfÒi,¡ãQBgÁHÄzä×KL¡íDôm.;áWùõ©4«¥éW ©ØZƒl^’©FÏb£·‘¬^_×µü š=15½‘ý‹ù5Sùu¬'#~Íüº³¿ˆ; =Dì£Ì žãªŸÃ–-!7…îô Xn ¤Ó*‚G Ò°ÄID=šÜ€ž Mn€&êùË6dUõ|À ©˜i²˜_o ¥á*̯7=—Ð×êNKö6øèÈ{¨Ó’˜ ÞåÝ¡NK8<¸ò }yì—$1~Ý:óØ/I¿9Çåج†l–îšn£%côe2d²z @‘ ˜,K(€,F‘ ‡ÉbÙ.Çõ“n·9µ¨¥`P€cÓ7žªz´r`¼mÒŠº®Pn® ¬èC“ žãK¥H)^·Ï# ¸nÓƒ€ï;¾eRAú!Ä©ô}—'3À)É£¼¶o/@2œG´ëîë@Î÷Úõo„ç‰Ûè<ß©Ÿð|K¤~rÄó¶„<Ÿ#W ÷'*xà \¼Îüàu3ÀPÁv')àŠ¸N<›žéáuR Ä qâ}e N§Ç‚S ·„p Ìò>G®»i„{T0FØÂƒ\.¨rkq¨k=WÈ­»Uu¥F¨è~‚x†Ü~—˜Êó·£¹ˆ¼B|rÃîä“Û—å Š¾})¿z¨¢o›=ÑHòë ¹Ñ½/^ÁƒÈNã\—fN‚µ«…Ÿf¯]#.E;~….TÑ·ƒŠþÉíé’“<ÝX¬¥G¹©‚Ó':€à$̰Hp’K„aw% Ä&¡Ö,<PkÓãBõã$ÝÇÑóaS»Žf…+õʡܟ –M’ß”½‡TéÓÑdY (WHÛV7J nÓžŠÁ!S…Ïò Ÿet/ÐYn€,…€ Ìãž¾Ž#ÑgN¡µ8¤íQr¨¯{‘dG¾ýá[À+Ù‘oÿF"c…ðï+|£ fŒrC"„,j’Cõ„¾PŸº!fúö QKè[57u· ˆ,WB¡ åG²üH"`¹œ“DÀ,ùQÉECHžóí´­¸~BÜÒ8¿@ni1 °fS)_½Ð wL?@”}hhAns'o¡à(ñœy Ú#ž3ŒšCÚ\˜³ = `ÖÚ\ŽÇ߈ºÔ?Ñ€’À!º¤G1úFp–tw#uÀZì, 7`­Ö¬%ÇkÚp´èžä8`MôVBŒzÃxÀZ1®h8Z´499` ŸXÃü¬Å‡´%g¬a&“¬ÕÚ€µ$2`Mަ°ûnÀš:ÍAŒi+!†‘Îá´!mIlÀšÇ œkæ± ã(v 0r.>Øp‚ÆgR'1pø!w)œ~G€dúè:]dŒèŸ:ˆ‘Àz%ÄÐ5€4B/‰¿“G@cø’ãø;u,!þ.9åç1M 8Ÿã†Æj c5@‹™LÒ–Ò«˜“8š»Î&$@2}°`ˆ?(ON'l F†$Ê®Õn8¡6à0໤pH"¾K‡$Öãª?®Ûcä`H¢³ø.…Æîâ°Æ-Æ k$xìAŸ´¨˜ªÝ´FuÒ¢ƒ œøXB 謖b`gÓ;«OÑÄ9š<é1M 8½Ÿã†¦W6óvV ˜_)›ªvV‰“8I“;è¬Ì*;«Ðé¬6b$pg 1 ³ÚxˆU|ì¬bŒ+œqŠ¿KŽæ‚zLÓÎÅ縡٢š(hg\ÙY „(hg•8‰sN ¹ƒÎª'@2}J©“}ï3“N=ÄHàÄÕb4-Uãøô0MW˜¸ŠÏ‘¡‰«ǧœ³j-¾K&•-¾ rV™sÜÔ̪4ùuÇcpô«Â~ùc÷ª@› OaÐôXDª¿.T’wwˆL‚¨µ´ˆ+@+Ó‚@«|’ËEý&«!¶ø±Å©þª°nEUzÝáqîã áÊq?=·¬<‚Hà,]‡ Œ>WI¤œ™¥Û@ 4ÓW%è$RJ¤ìféª3}ñ]28Ó·†8‘‚鑃™¾r"eÁÀ‰|Žœ-Lð؃>XgTz¸p10äXeÔ\eÔgüòC"ErŒï’Á!Ç5Ä€ŒJ|— 9V5'•8Ç [&xìAŸ”¬xûg¦-{ˆ‘À©Ï5Ä0hb³Æì…îí/SŸñ924õ¹ zû¦)ôö+|èíç€Þ>q‰QçÑÑ:£Òã§=ÄHàìb4ÂZcÔKk‚Qo , £ÞذŸ‡¥˜8,ÅçÀa)>Ç:,æqË!çqkÎöõàl #½‚0p¤·t‘íHoe”¶âÇÝ@ 4\öƒŠ½ÔÊ#½¾K Ç‚ã»dp,x 1°„Ï‘ƒ±à²TÐRËœãÇ“<ö ÏWÌË™ùäb$pNz 1 šq®0ûv–‘6'Ÿ#CsÒ›1°„¿ öƒˆý |ìásD²žûíŠV¦¶K'¶‹LvCyºÕÐw|ƒ†¾‹ÉÓ—§³Z5ùÆåé¬V¾¡<Ý}p¼ÓhÊŽb$pø|1 >/vèÝö;áÅïRUø.è»0W8À^áSv€½ömõå«!øø Á×¾KÊ嵫 c ¼6ƒq…ƒôz°ƒôµïrõæ»\Áw ¨ÞpÛ¯VSê bàzƸÂþÒ]Î ô?Ì~ ¿º€8‰A[D³è¯ÙÑÁ\@#À\áj&ìjõë€Ú)®ÓíW ¨û (9b,³¢Ã€\Á’Ùà—Èùƒý’mQ‚ƒ.J¨e zQ‚Fˆå¶-'1hÛ‚¬.œí´ZßÒ ëä V6¨œF¯lƒ$pïCƒA Úûà<g[cèr2 W°.»ÄB=}Aéjqƒ6a¨RSñ€%®ä ×ih4a×i¨_ç|›À|ø:ú6—ý HÅ· û6È.öP®C.öPõÀ G\…õÀm«¤å Š~>±D¶ž \ ½li0ˆAFd=p^ô¯!N‚6È®)©vM‰ú‰o gƒcœée׉úunlÖÆaœ¶!@®paŠH“ S ¤¦(Úd·0E[ºâ †KWŠKW¼-!F·às°¸Eý.ôâY3𽇤li0ˆAÛ_œÇ 8® h‚ã äŠVÈ8„_!£|~…ŒÂkô ÙÀRèÕâ$í¡Ñø$¹°ž4qìI W°ÌF•br™ª]o¨kújfï«É q‚° qÔËl§àk[u1p«Žf>É­:Ê÷¥·ê($I¡õ Ðz¦ë)læ©e r3b=Sœ+©õL#¹a»‚An÷Qï‚åλ ¹s߅ݤ2Ùå䮆r—îF_hk†ÄëÐk†”O“!'mYU„ÏaÀª"EüùUEʧÉbŸFØwä0ˆûŽD’œÚw¤¢ûŽÒÒûŽÊ^&Ê;“Ä0pg’Brg’z—ˆKj˜¹½F´‘°wIûºôÞ% „Þ»$‚œÙ»${ò§ö.)g!÷.)J-ØNaw>‡A»›tŠ»›ù¥w7)<Ÿùm‰ÊKŽäwÙÿ¤P•Ýÿ¤^x¾«%Rƒ¸D*(˜\"¥~_v‰”NXc¯š$ ¸¯9ÑhBo¢Ò4½‰J¡7Q)ª¤@ªdÙf…Ïaà6+ƒÜf¥Þ* ß%×Ã#"¤à7b©—!|= o³÷õ¤µZŠüòkµù-Ýeòn.‡A ÚÍ%­S»¹‚†Bïæªer7—Â(7ìºB®¿í¹^Ú殺 ½ßKá’Ý~/mG˜ƒîSèÁîS/éÕ¢1‡A \4¦]‡\4¦òa-d´½·•©Lo+Ó˜ÝV&žäܶ²  ÐÛÊ$ÊòÛÊäO¼ßV¦m<Ãç0p㙂ÁnË~mÚÚkÿ˜w7ôC“뺎<ÛK§ßÛakZt}Sl:ç"Ñó7m¤Ëi–ê´ÄEÒ©Mj?¢ãŽm°Šî ²eÌñý#ļ•B\9•‹ˆÑýWµ#‰c´ g\.‡Evѽ>kl& È#Û›6Ô#‹YË|ÙýFagKËÐ#W9¬sÿ|ŽBg±–¹Ë-Ža6ÝnäˆÌŽ'ÆW Ù—+¡:„í";ˆ,Ÿ‰Í|ÞAm_KÝ?{t"ÕWœT!’ÀÜAdDGR/ÊÊâ*‰}@"›É¹ËƒAð#!@ ö¬X…3FŠÌJYCŒLYTÇ‚q…¶ Ó4GÆÉãsˆªÃ#±_0nÈÂŒ1«Ž£mñ£²ž‹ÆdäæI«}l\ Õ6®©!†hãÁ¨ظ€l\¶Ý<©Ù¸€ÏQHö)Œj(FmU1GFÛïí¼é1ê³qšZ»ÇÊΊؠ „Ñ×<46x‘ªZ,¾a1·ÿÇÆ•M !Ú¸alŠöE®_¶ûêžb_DZ'°ƒHÔ½M%3ùõËnÞ^ŽFô‹dÄE„ü;ˆDÝ%oòºíG‘†ç7?ê¾ñ)âKäK欜Ŭï 0_Õ|/gÑ‘õª/™ïäLšò®ø’ùNÎâª/™ïälÿEZìÝïºó´O"ê­]sž2j^û&›Þ.5îH‰&…ÒêퟆiÿlõöOslÿTZRª †QÛ.¥vGslÿÔÚ.£yslÿ”Û…ÀÀÄÚ?å>Ãhú˺å†Éªq"ѸCl˜4gº­oìv´%‚л+!ýoÝŽZ‡ ()°Û±Õ»ͱÛQ뺴ø¸Q:@ Ü(]B Ø(í1ÆUí˜Ô¤~×í¨6[ãﺩ‡ÝŽVïv4‘nG­CPcTêô1Ôuiñ9 £j†ìvŒ-ßÜcdÈ´hƨŒ:uLF5$£ßt;êŒj(FmUÁ5h‘ùÜÓ¡X—›š×\&»q6Î*Ö…ìv¬‚Gºß!u;ºÛ±ƒpv;ŠäDÝŽVïv4gºeròÝŽÊE2â"b·£9ÑíheIã»+IàwÝŽZŸ¡èKæ_nTäâK欜Å&Í™nGÙ—ä»-<…Þí¨ù’ùîÑÜe¨|‘]êCê˜T?É®ÛQþ& w±ÝŽÚG¡»•¯Âu;êŸeÓí¨uŠ*4—‡Kí;&EÕ³ïvTl’Æd·£¬Es2–º ßíØ›%㊺ µï’W¡&¾KÂú ø¨ÛQý. ë-”» v;jÖé¢Z§¥ËPäõÃHF©cRÑ…-sñŽIsªÛQÖ…'ºE]Èv;jº°@2·tŠ2-ï˜e®@æ¬Þ1iNu;Ê2»­ÞíhønÇAb Øí(Òu;Z½ÛÑœév”)Êv;*B‹º­ÞíhNt;ªa»•/BUåèvT/Âv;*ÉÙ¨É#Ðí¨DM|·£xØíhõnGsªÛQþ&'ºµ»°_E´t·£òYNt;Šòz¦ÛQ&È…ÿ¸b nGåã²ÝŽŠ„ÝŽVïv4gºõ»°ÝŽêÇe»U¶ÛQãRd*Ñ £»uª²ÝŽÚ] VüÄÝŽšøóÝŽêÇåº5‘I(s+v;š3ÝŽÚÇå»å›ÐŒZa Ðí¨ß…ív”?î™nG™"t·£Æ"†f1<¦»5²òÝŽA V—Õt;êwa»Ua»U¶ÛQ9Óí(›ÝŽ*Ûí¨Þ‡ív”Or¦ÛQ>ʉnGäD·£ Âv;ÊD9Óí(åL·£ŠÂv;ª l·£L•3ÝŽ: Ûí¨¢°ÝŽ2UNt;Ê'9Óí(åL·£ŠÂv;ªb»ESÝŽ*J*¡CÝ­wCDÉX'ÙðÄ-rŽD'Ö"DÎ\¤š!­ŸMèíÛAàI†AàI†A I†±–ÍĶJʧ(È/RAˆDkÜ_¤`»-‚ÀÝ–ð¨ÛÒ)_¤¿¡Û–±î‹"å„ÝZ‘èÂÞqg@F;…ë’’ŒìVmнÚR0.¬ê“¾I¾+}$šöÌ¿$AûF:aÐED)ÉwÙ?¡ýB¿ˆ!/"ògþÅp± Ćť~MJršÅr¦äE”š©™ üúE2VVY« ÈZ±VÁ³–G˜µdˆ °V@_¤ ¿ˆBΌ՞wîüOC6«7ZËÔØ­$Sµ¸‚‘pw±¢%¸<éZ— ˆaO"ÝæBúãý§¥¥!¯ÓŠÞFÂ~‘ÑzÃršHØ„¿Ž(»—„äמ°"M ùu†µ’W^~j’ {#ˆ!áA~6³Ç€;Êb4œÛc qh–—Ÿšì124X;às\áiå»òÛjw1ìs&|ç{ãsà™Ø%ÄÈÐS¤€1®h®¶Ç9œ«éŸ3縡¹Ú=ð+‘¨*KN½Qèqã²%Ö–¨’ⱃHáXmî| <["'ž‰íåW";<»Fx&¶|‘Œ¸ˆðJdgb‹’vb&¶q╈­EŒ;VBà¬d‰ ðLl ðLl‡ ÐLìZäpþ•ˆòEÈW"ê'¯D–oRˆgb{ˆgb;ˆfbkŸ…~%R)ì+‘ÖC h“*Œgb×#E†Mãr&v 0à+í»°¯D´ï’°¾B 1ðLlŒ¿‹¢KÙ™ØÀÀ3±ëľiJ¿QtaAË\+òØ™™Øbà™Øb ™Ø².<ñJD£ûJ¤õëB1ðLìb`]ˆéu!ÆÀ3±%šâ™Ø^~%²ƒÀ3±kgbË)w‘ª ÎÄ.=‚À3±e2ب*gb—ÏÄ–!r6j‚p&¶5˜‰-‚˜‰íåW"{ <»†x&¶rö«ˆöàÄLlñ³œ™‰-bœ™‰íeúãb <»†x&¶‚Á*ÁcÀ™Ø¥‡x&¶öq陨=[¹ )2•-!œ‰]âsà™Ø FÁŠ€p&¶/!ž‰­}\z&¶Èî en…W"{ 8[þ¸'fb+,£Šþñ‰™Ø%>ž‰-~ÜS3±½‚BÏÄ®e–E´ë°3±K1ðLl£`uY 1àLìŸÏÄÖX„ž‰­Ð3±ES3±½‚BÏÄÖ@è™ØÚ}è™ØâINÍÄ.z&¶rf&¶BÏĉrj&v©¡Ð3±5z&¶BÏÄ©rj&¶ŠBÏÄÖPè™Ø¥BÏÄOrj&v©¡Ð3±5z&¶v!z&¶rn&¶†‚fb­­… êµ¶–ÈUup©ƒ ¶`D¨jí$Ä]24tÔãs\á¼Pƒžz¥ï1D'È !t‚˜3 Up #òøx^¨DN.=/TI(s+v‚œœ*ÜóBƒŒÁ2jå œªÝ…ž*žãԼР ÐóB•£°,"†?'æ…Êd=1/T!HÁê²bÀy¡Ú]èy¡‹ÐóB5z^¨rj^hPPèy¡=/T»=/T<É©y¡NA¡ç…Š gæ…j ô¼P‘(§æ…: …žª¡ÐóB5z^¨H•SóBUz^¨†BÏ u =/T<É©y¡NC¡ç…j(ô¼PíBô¼P äܼP ¥cɦùjñ4KzœBø÷Z :oÇ!ˆD;EY•ñ¬U!(aôã¼jãÂQ#ž«IÏŒŒÏdL©‚A›É˜G*‰¦7Ò3#µ‹èsÞZ}¸dz!¨ðg4èLÏŒ”Y<ßóçþ‹`ßÔM† GjÉÔ‹¬dB`Ö’>*=BPf­²–G¬Uð¬U‹äAù‹à‹Ì kÔ´§$ìû‚2†üIn´¶¢¬îGjZ\ÁH¸»T¢%8ŒT"2Øa„ vé6ÒD÷ŸFäÃAåÛˆœz!¨Ñ¤Q@ Ëi"aþ:¢ìFj„ibȯÓÖ) á4#”¯ÓdW€Ñjc˜ïŒ©ü°;†!¬ÂH¡Þ¥@_wT¬ê9 <î2Èc©ûFEþ» ê»Ä}Û;õ]õ]´»°ßE;ù]„Qßù4o%[‚<§{‘ SDn2CÐsº‘ ‹DÌà˜E çt{Ã…œ)yå£Òsº=‚Àñ[ƒ d­R€81§»A˜µ<‚À¬%CÐsº!f­Ah¢%î$ætyN÷#ãLR+Ê*1§;Èsºï é²TÒWaætyN÷bØ“H·aætyN÷B^'–uY@Ø#23§;Èsºóù!;}Qð˜9ÝAžÓߟ),aƒ’‘¶6*}&f®…„–`kÍÑ\+†2Ê#æhk•ÌœrŠ”ÌÌ)´@ -/’±)Æ€ pŠžÂ C)Ò¢ Ý¸¨¸*¡å4[kˆ„Öb(Å/RÐ_D9ûEZ /â4[k[Ûj;1îdèÖŠ‚mm«íĸc$dh_I_ÛÚVÛ‰±€ö$Òm°­mµ y™Ù±­mµ ˆa9M$lÂ_G‹ÃÈÔø¥”ñ]®¢Ïo­NÓë—Ý8„£Ë߯ÓHzÝŽk’ä÷iÝA˜e$Р¥Õþ;D*èŽÞA´ØO©øz˜ÚBbl| qʾæ¿\·>DŽÁq#•ý¹¶Uý¹üËÍj‡‰Qe!ôgZšgÚA\gê‘gº`ˆži@žé‚¡ÎûW=Ó{¦%ÄÈô¥Šgº`€‘ÿúwÉÕïbqÄ<Ó¢kÀwɉ‘ÿè»ääw©ÄÈôµúwÉ©‘ÿŠ¥Í·Þ\ÄÒö#ÿuM˜ï½¹ƒ¥×hš0ßzsòÈÅÒæ[oN³´¦´´Ú·-¨‘ÿúw¹¨&¾Ë x@5ñ]nÔÈý»ÜXŸ{@%ĸŠ^¥í>‰NS}Æë´5@·rë²ö='ªóM½5PÁ•=U\8ì ‘ÒÈŞÎÙ#\8,ºx@ÕÈÍa =2}y¢‘‹-‡É‹É/¾$ ‘’üCÔÈIþ‚(’¿``ì ÖÈø׸ÌMþ-¹ãwÙå´PütC1ôAû.·]Ì ­/Ð"¨3X-§uC1ÃPÿÑõÇm¿dã ?Æâšþ¸íVJ[z |Dª #Ëí°JòGzàµÜNë¤Ì2@”‹)+Ñ“ºm󱛡ÇÄØ =®ÌN;ܶќc{ˆ‘Šõ0¤?.‡­4Ç‚R +}µƒ¦AV P…ˆi‡ˆ@‹ó0=ÈJáDÌ D_¡qÉ ²‰m0H*g0@.ærù’ á§(³`$b~òë%¦Ðö"ú6—F“¶U¨üzáTšÕRì+éÛ`›×ƒdªÑ³Øè­@ô­š–_@³×ÖDö,æW4}x˜1 ø5;ðëÎþV ºë0¨àWýý,7…îŒk@ÜÌÄ#é ˆå‹ˆ¨çC“Ðó¡ÉÙ¢êùË6dUõ|À ©˜á±˜_o á*̯·-¿ä7@–ìmðÑ‘÷P§%1YK¢òkÂÙàÁ•'N"úòØ/Ibüºuæ±_’ ~Ö› šÜXwžI¥¼U@y«aIÊÖµ0_йíù$òz©èÛ—‚Ùê§~œÛfk4’†üzûÂ-‘ƹ.Íœ$a¶ ‚O³×®—¢¿B ªèÛAEÿäötÉIŽî@,ÖÒ£ÜTÁV.êŸ'¹`†E‚“\" »+Y 6é0¸Íà @­MéÔ“tGχMí:šP`¬Ô+{„rC|‚X6I|PöR¥OGeAl0 \!m[Ýd ()¸L{(‡L>˃~–ѽ@g¹²&0;xø>8ŽDŸ9…"Ôâ¶GÉ¡¾îE’ùöo„o¯dG¾ý‰Œ ¿¯ð.˜Y0Ê ‰²¨=HÕúB}>膘êÛ+tF-¡oÕÜÔÝ‚ ²\ A„2”Éò7"‰€årN³äG%I !yÎw{¦£ú qK?aê¹¥Å(ÀšM¥|õB7LÜ1ýQô¡¡¹AμA„R€£ÄsæhxÎ<0j}hsa΂>ô€‚Y|hs9:#êRÿDJo„è’ÅèoDÁYÒÝä)M¡K: â’+Oó•~°@]Ö‘îØDæMÅž9ï Œ>Ö¨ûÆðéTwÞ¿éĸ»GbgvÙ2Tà~ŠBŒ´ƒ¸ê3'š6ÈÉÓè©c7³Fþ¬c˜8F˰FdfMtN”Æ›™5Ç/k™/»ŸY#Ì4RlÆÈUëÜ¿Ÿ£ÐY¬eîr‹cX†Mï<ö 6Ÿ(LJ³¥Óªá+Á§Â<¢DF<ÅFNì ÔÉJu',µC©>©r‘G$;u®Rÿš.Òh¹ƒ¸"e^Êä³}³Ø$²Ù.Ù§Y1 4 b¤`Ì”¬:ŒLYTÇ‚q…¶ Ó#GÆÉãsˆªÃ#±_0nÈ‚Çk£2ê4Ï0ªam\€Qµk€ £`ãÁ¨ظ€l\¶/©Ù¸€ÏQHö)Œj(FmU1[·Taf+éLvãlœf n`eØ4ü"öds¦;uÖÚ#ˆTÕbñÁL;ˆÉÆ=ÅÞ7—M qE¶e¥}‘ë—­wüû"ÒP¥„>Ú©©:<!ùÆãS>ý"qaÒBŸÊoòºYÅ NCj™/öm _2 _2gå,6Ah†2É¢š¹³T_2ßÉ™4ÆHñ%ó/7b’êKæ;9Û‘{÷»6#í“Tb$` “öMf uø(3Fª1R¿ÊŒ¡BŸeƸ i@¤©œKÃö ÈTißöB BRŒR~HˆV‰84K†ô]ÆDà»$¬«PCŒ dR¿KB BÒ¿KÂz %ÄÀîƸªSŒ€uº¨Öiý£é‚–¹ØØž=FF!ɺ°€c¤‡Dª.,ö2'RtaÆHª., Ì£4™Ûu㩺c$`’,sÅ6Œ”G)2WÂHY6ëBŒ!úèùè·/ 룡Ò|ô;„_  þm»1Z¾ˆÌ·/)3õ§i«Ú!—”iØŽþEÈ`£…þ†ƒ ^$Qq‘œš<‚ÐçìhQÓm3Ù7ZA2ryØ-”…„ÀÐähR²`w±8”í0د"å †>ØFû, †QÇÉhþB¿§é†r“ðã^øë!†>MFý¸—ÝÇ=ί‡:°Ã`• FÔ”™£)è³WÐÇ¥§ é}Ƥǡ'€CH‘©l 1ô¹)€ª9ÿ@Ü¥`Å?@ }Þ‰*þw £NA7Ñã…qBˆ*2 en…Ù{ }Ȉúq“ˆÁÝzX·'4£VCî¢ëv‹3•—C¿°4 #t>¿SPnzÂsc¡²ˆ¡Y¤Åú$ •¬±È8ôAeÃÊekˆ¡Ïw)P2Ê¿Ù=1‘&- jÀ ’î{ð¤ñ*³¦²;³™-€@2f.ºaÞô«'É0QˆœÅ>rä» rQ6òúäÌ#i•(ù¾+Qzœ¬%ÇÊq|YŒPræ=/¡^ÀªT)öŸÒûUˆB=>E(9ónT¥J£Jä¥z’Á+òÊ-J•ÈG„R0¯Ñ…ræ’\ ¯L/à ·r¬©BÌ6Lû§ÕÛ? ÓþÙêíŸæØþ)¶]JíŽ&Úþ)¶]FóæØþ)·; ‰µÊ}†Ñô—9t;Ê “ÑM£;ˆDû²bä9ÓíhëAÀnÇhàiønÇJHÿ¾Û±o”–O+nI ìvlõnGsìvÔº.->n”6Jûb\ÕŽIMêwÝŽj³5¦)èvT¤v;Z½ÛÑœëvì_1@¥‚Q «Òñ9 꺴øQµkF•º ͱÛQ옌jHF%h ºuF5£¶ªànºµ>CźÜÔ¼æÒ0©ðdzqV±.d·cÕx¡ûR·£¡»û^Z »Er¢nG«w;š3ÝŽ•óv;*Ɉ‹ˆÝŽæD·£•%ïv¬$ßu;j}†¢/™¹Q “Š/™³ro˜4gºe_’ïv´ðz·£æKn»µ.Cå‹ìRRǤúIvÝŽò7Q¸‹ívÔ> Ýí¨|®ÛQÿ,›nG­ËPT¡¹É™nGù('ºeÝŽ*Ûí(åL·£|”3ÝŽ* Ûí¨‚°ÝŽ2UÎt;ê(l·£ŠÂv;ÊT9Ñí(ŸäL·£|”3ÝŽ* Ûí¨^ˆívANu;ª(¨„u·*ÄòEÙ<¤i ë$ž¸EαƒHà$ÃZ„È™‹ôOó!D¢õ¢ ½};<ÉÐ#<ÉÐ!4É0Ög´ƒ¸ÂVIùùE*‘hMWà‹l·e@¸Ûžu[: OqU{ƒ†˜B„H9a·B$º°WNÑéf^_ü®OÚK2²ÛÕ'bôjKÁ¸°ª¯0ò]Ù@è#Ñ´gþ%¡jeÎÈ¿$AûSˆR’ï²Bû…~C^DäÏü‹á.bˆ ‹Ký š”ä4‹+äLÉ‹(5S/2øõ‹d¬¬6³V)@µ|ÎÔ(ß…}%¢}C„¡ÂëŒ=~΄ϑÂùÞøzФ}ê•à1ôJ$ž*‘Ï Z'ÈÉy¡Aày¡òE2â"b'ȹy¡¢°ž˜*â̼Pƒž !ðk¨Aày¡Aày¡5‚@óB…§ÀóBeròóB1ü&U€x^(ÆÀóBkˆæ…jŸ…Ÿ*ó(?/4@ h“*1ð¼P1RdØ*|h– šHS…S”½3ˆýA £÷¹jãÂQ#ž«IÏŒŒÏdL©‚A›É˜G*‰¦7Ò3#µ‹èsÞZ}¸dz!¨ðg4èLÏŒ”Y<ßóçþ‹`ßÔM† GjÉÔ‹¬dB`Ö’>*=BPf­²–G¬Uð¬U‹äAù‹à‹Ì kÔ´§$ìû‚2†üIn´¶¢¬îGjZ\ÁH¸»T¢%8ŒT"2Øa„ vé6ÒD÷ŸFäÃAåÛˆœz!¨Ñ¤Q@ Ëi"aþ:¢ìFj„ibȯÓÖ) á4#”¯ÓdW€Ñjc˜ïŒ©ü°;†!¬ÂH¡Þ¥@_wT¬ê9 <î2Èc©ûFEþ» ê»Ä}Û;õ]õ]´»°ßE;ù]„QßùýWßrä9Ý;ˆ"r“‚žÓÝ ˆ]$bvÅ, =§Û#ö(äLÉ‹(•žÓíŽßa k•ĉ9Ý ‚À¬åf-‚žÓ !0k•Â@-q'1§;Èsºïg’ZQV‰9ÝAžÓ}ÇHH—¥’¾ 3§;ÈsºÞDº 3§;Èsºò:±¬ËÂ~‘ј9ÝAžÓÏÙé눂ÇÌéòœîüþL¹` Œ´µQé31s-$´[kŽæZ1”Q1G[«dæ”S¤dfN¡Jhy|‘ŒM1SŒðJ‘íÆEÅÍP -§ÙZC$´C)~‘‚þ"Ê)Ø/¢Ð}§ÙZÃØÚVÛ‰qÇ C·V4hk[m'Æ#!CûJú*ØÖ¶ÚNŒİ'‘nƒmm«íÄX@ÈëÈÌŽmm«íÄX@ Ëi"aþ:¢àa[Ûj;1ò{#HÁ6( Ys‰2[´l#Ö\¢8Z¶ &Ê)Ø‹Dž©¹X­æ’Çj.JÁ¤•N±3Qšß¬¹DUjzÆDÉ_¤ ¿ˆ­ü" -2p¥æ’s5«Õ\r®æbµšKÎÕ\¬Vsɹš‹Õj.9Ys±ZÍ%'k.V«¹ädÍÅj5—œ¬¹X­æ’“5«Õ\r²æbµšKNÖ\¬VsÉÉš‹Õj.9Ys±ZÍ%×\´jz $‹‡C5Ýkš=‹Å/r)<H³¯1«é ‚€š]$gA÷7D,;WM÷ÂÀú•D ¢šî5ÍžqÕt¯iöŒ«¦{M³g\5Ýkš=#«é^ÓìYM÷šfÏÈjº×4{FVÓ½¦Ù3²šî5Íž‘Õt¯iöŒ¬¦{M³gd5Ýkš=#«é^Óì™èór6¦ˆ't…ÍÆ±„Ž– "y«œ"c}öAXŒ¯"ãålLÁfc¼œ)ØlŒ—³1›ñr6¦ ³1^ÎÆt6ÆËÙ˜‚ÎÆx9SÐÙ/gc :ãålLAgc¼œ)èlŒ—³1ñr6¦ ³1^ÎÆt6&ÈŽU÷ÍDÇ*zލo&7ä42Ù±*8ÇêÞ€b£¢—q!s«‚s¬z´ÒWaBæ ;VéX­N"݆ ™ƒìX¤cµ|›¨nÍÈ9ÈŽUA:V+N ›ð× ™ƒìX¤cµ"¬S@¶í¸1Õ _º/¼I‡fºùw³,9²@Ö Ë_k"‘~9u‘–€H¤qŸ-r°ly¸ˆ­ÛB¤Òü¿² ”‹d»ñ”ÑöM/p‘‹B$úÖèZ;Eβ–G ‚ðr'…!/bk‘€(Ø)Ù=D¾jå#^Ãý«^XÎ0rž»Z'c¤FåÛZÆ0$FÄÔe˜ù.Òg)XzT>âe±1-jý1vŽ„ª?z91°ƒÀõGëB¤(ÏØ„O èää–€0°„ !Rt L ˜ª ðWÉ/õrHžÝçD­¿ˆRH… (Î|  ©Ä™Bª—1èBª„q¢êJ Äkr"1 ^„®Å:ÚEÈÄ€Ì81àå¨>‹’YCX–/’‘‰´„H ¬dBXT–>ꉢ²C(1 ³¿HA‘¨«“‰kAKÛÒEN”¶5 ¶´­aÐ¥m/cÐ¥mé§JÛ^¡KÛâIN”¶U¶´­‚Ð¥m¯€°¥mù$'JÛ*[Ú–AN”¶UŒ,˜EÝIs¦µ/VíÊNÖÜ<<,mxŠTʔͩ5gœÚªt")_O«]Ò)NT»‚‚ÁV»D Þ©µ5‚H@Á,žh9WíR.Â:µÊE(§V¿]í’/¢;µ‹”TA@ǸÚ%_$#/õH íÔ¶+G!`µKd-Þ©Y‹tj5Ö:Qí’/Â~‘¨Gjh§ö°{7 «]ÒENT»\-c°Õ. ƒ­vå.tµKÂ8Sí ]íANT»D²ž©v© lµ+h×a«]òINT»T¶Ú%ƒœ¨v© ±½§¬Ú­G¤\]$hµ•”©‹´z}&ŽIÎuRïr“.ÓÃË 1=@½K¾ËüêO¹Kk3h“1ÈÌ ,«|¼(«ì»aõl»r êݰÆ9ÍU@ú»aýËŸ%‚/Â÷~‹_„|7¬Ñ¢ iQ5¼Vd•ÏCU!ÈdJÅ óP²Î óP =Nä¡äƒðy(í$|J&ë‰<”B桚ðy(å$|J!óP Ÿ‡ÒA¨>ÐêÐumÎw]Û˜'wªëº:4½˜ÿC×uD©žìºŽ¹a§º®«C¡Ãüº®•‹P]×Õ!fNw]W‡,–9Ýu]2.æt×uuˆìÍé®ëêQ›Ó]×Õ!6§»®«C4lø®k+5+¡ëZ}!½q»Ë|rêQx€)|Ž-Cl$D_tÃSø¢BàçØ"ƒñ4¤…Úu-€'»®«Ú#ô 0àSÀñgžc+ôsl ãÄsl‡ `×uÔ&%çžcË¡Ÿc;»®•‹° *µ|¦ëZ†¹®k+u]›ó]×ÚE2ò"m‰ °¬Bü[ºÈ‰çØAÀ®k‘µø•Z¾ûE¢®Nræ9vÀ°AE¼È™çØ¥ŒA?ÇV0èçØÊ]Ø‘§žck lƒŠ|’3ϱK„~Ž­ÐϱµëÐϱœœyŽ­ÐϱE3ϱ5r XÜÙ^â”S¶O¦Fh¨_½1ù[v¨ß–½²Í°v¨ßÖmØaCýê¶–1È¡~õFuì0ö.sðCýêØï0 ×̵Íûf›Ù,“F9̰Lê>—OÁ609+að L.ÊaæT“kkƒl`rQ3§˜\”ÃÌ©&å0snläN'ÿ‡±‘B$p`£ Álô¶Qa§-BˆLê ;Mþ£kƉ'æŠô<1çPÄ GÂì…Dè¸Ñ†*§ ç¹h§`Ɖ߄ž0vª<z]´ñ€Ê)Èata§¸¡QE›í'~z ŠüEø…q"-èÁ|agL¡ED›ª'žâÌT½RÆ §ê)ìT=ñ»ž˜ª'ÒãÌT=ñ g¦êÉ'93U¯T@è©z;UO¦É™©zâIÎLÕÓ@è©z"È™©zHFö=‡˜Z>·É*êyœœª!ÿC\$=s>êÿp_ƒæBE¾j}ÏAà¦e âÌT=/cÐSõ$ º¿ÃUAà¦åAà©zòEÈþí"tÓr pÓ²| ²iÙWA$HJ0nZ–/B¶Èú¨/ÈõwÍ<9UOb-º¿Cf­MË5‚ÀMËò)Ø/õH¹þŽ 9µç¦ê‰93U¯”1è©z =UÏËtÓ²DSSõ¼B7-‹'93U¯T@è©z=UÏ+ ôT=ñ$g¦êi ôT=äÌT= „œª·O×&ÿ‡©zuÔF›ª§bSõä»ðSõö)ßäÿ0UO¾ ?J¾ ?Uo_0JþSõêÈ9ÎNÕ«#žþÙ©zuÄXªWG¾íÙ©zuÄ9;U/NÓsSõâ4=7U/NÓsSõâ4=7U/NÓsSõœÝåÜT=½ËIÙ~—sSõ\TnÏMÕ‹ß%;©ÇãŒó29U/Æcg§êÅxììT½Øw¡§ê…xÉœ^Ͱ{ž“)„Äîð}úæÿô<Ç!8·L„8ñ¶F¤ç‰·5"Ÿ{±5‚€sË”S°‰åìÜ2ñ›Ð¯ZöYéU‹ú$E>ùbŸ²ž¤hïIÄ/ÂçÄ/ÂÏ-iA?Ù' ¤Ç êKég^r(ôKƒ}É!~×3/9¤sœyÉ!äÔKñ$g^rh ôK „}É!ÓäÌKñ$g^rh ôKäÌK „|ÉQ¶1s/9\TµŸ{É¡b/9ä»ð/9ÊWùyÉ!߅ï¿äØ{¦ÿ——.r޳/9\į<û’ÃEŒÕÙ—.òmϾäpâìKŽ8MϽäˆÓôÜKŽ8MϽäˆÓôÜKŽ8MϽä(mì.ç^r”Ñ»œ”ýèw9÷’£ŒÊí¹—ñ»d'õX#`œÑc^Æ _rÄxììKŽ}Éû.±Hÿëã?þù÷åùåõíýmôË\ùì§Ÿµì'Cãïö÷¶êþ7ÙÉú÷Õç>7CA Þ‡ÿúÏp¢o/o¯Ý‰\w¤òWóì¬÷ϵ÷5d áD=ýîì Ôºç28Gž(€þ>==@oÝÕf ïž;Kž(›€¾þ;•ÎÍ@¶; 4Nãëîöïøåßml N_óû÷Ç·_“WËg6¿.æzïTö«Ÿ½ûýùò›*& ðoèý¥&ùè6~þðuþü‘J7}~ëž?ËÒôÙ:¤#ÙW÷ú¼Ûe´Ç¿_ÿö—ë¥ddÉßîg>×eI~·K2IÉ¿³”ôb2KÉ» {;3"õÑò€ôñ}AúÝ Ü'Ë”—‘½¿†.tïºÐÝõÜÔ#}üx©êÖ±H#wŒ9S|ëúŸß-Kñ뤆t¨Ü üóç6{¨! þøuT'/½Ì ¢òöY¾uZ Ó¾$‘FŸø©ºï‹B÷½ÿËžé6!}„åýí}äñ.ðë‰Ô]o3«KÓ•£Øýûç.v=ÌbçýkûJ"Mú?ã™úNù1Ü®î…î­öeC"MI˜æ`ÒÚ‰NÒÏ·ú'k ÆÀ¿?½ ¡þzÝ·ûö«i¿ÕmK~»$%xÔ*½ÿñ³üm­=Cñ‘ǧ,UgU&¹¬J§SÊï¬Ü%×É>M<ÞÙ'g'ï8ó£¤å.ÉGЇéå.Áýí³²í Ö&ÿ:»aù¸óøÇç·úv}Š"ýùæY]`&ÿúÏÄãîÃö<ðø¯7_¹šäL3ëñ‘Ÿ:.õÓȽA`ogÆÒÄ?fü}»IØòí­%‘¦æ¤¦3õÒb§3uL`û‰”Ngú;JËû˜c¤åí³Ã呲‘Nu™¥e¸Ý 3»?IøA"]E÷²Ã#ÜKóåòýËöóO ýËi´Áƒ;×#½õdú-§ë>k@§ÉŸ÷µao—êHÝ¡ØÛe‹ûüüòö6»Ï¾üÝŃ·Ê"]ŽxO§Ù—È_räÒ—%‰TÈ>}Õ]îÄínÈ©¯<Ë™ª[ß…s†ºï7Ó¼Yþ~£«©…?4s޾æxÁž§æ ö<Õ}¾îÒÜyIAÔ8–©.Ùò§SÙ™ÓÇ8ÑÒ§º˜ánÔ»S50Â[AåzhöË×4Ù å•%}ÁŠó~°§š]Î;ÔäP]LCÆÔ%{’ì v§‚ñç ÊÄÉÞ§ÿ¨àz• d·%^¯ 2VÔ™ ^—{4£3<šÂ^AåKŒ=A­¬í£ú (Èö¬‘|O5ʶ,Ôà| PÛñ^£€}u‘#ööwïxð~G‚‚Úx¢ÿíˆ=JM$ØÎk¤“ø¿õ4Ù¯()ÑÒP —БŠg382G—èý£³Î}¼Ýê³}ÿ]Ú2ÐP· êßÇ;”}†ê³ó­Zö ¦KpÛ‹sÇWƒûÑ‹óïNý=×-+8ée!û¨ël=k­ ’…f—ÖÝõÕ$ÑPdƒG_0Eé @;ÿY,Tº%TÒ_ðºKM¡ÛdqBh•£<Î}Áâ˜\«”cr©DÉ¥ÔMÍ …²¥Y4{ˆÁÑÐ ½ÔEÈèUžËè­ !¥7ú3_03¬<—‰[A¥Bzp„ÂéÁT†²z}ªk,­Wº%­G N–ËÙ¸ª¯:ðJ&+äaÕi¾À«¾ì2{ÍW×”Ú£}†ëåöh“zMôä^ëj–VWƒ²{üÓ8­¦§AWPYœV΃® ®­zÍÀ$BWP9Êò´*â©ÐI‹âTè ê†r¡ô©ò%ñXs‰ÇË:ñ(§ =æ…Ë:ñ¨¥ KɨÉÐ’I†^ÈÄ£g‘„Ä£;‘x¼ˆ‰Ç]ºýv9Ha:Ï~;=ñØœ¸Ý ¤ø<4%µËPSâQÌ€yGsù”xTR|% %$݉Äãe—xÜe ݉láå˜xRÇ´n¹ÂÔ1 •£l!ÏWÌazê¦d k.[xÇ&{*"ñHCi‰ÇšK<^PâÑÓ‰Ç J<Ötâñ‚5x¼è‰Gw"ñxÑîDâñB'é âÄ#{ª)ñ¨$ˆhqžR³ ´¾"4”ÑÓVŽH[]Ö‰G9³Z~òdÏâ0w"vÙ$µÌ*M«eVkú‚̬Òd¿ÅórîD^î²I"ñÈ^H<ÒP8ñÈr;‘xdÅùj¤l¡§³…—]âñ) Ee /›Äc$[XÓÙÂË:ñ¨fVé/ˆ4”˜xôtâñB'éŒÓƒ˜P+í矦æÒ̓š1wÕá,Y°²S/ ñ&Ý>¨ùûô÷žc\9µÓ¢W'éöAœ÷hZhäòŽ¡vnëüëëÇûG <ãtý f sÇ‘clÚ¶äó•tû frc@0ÈM×jzG¯£Q÷Õ:#Ó}µÞáh>}õóýg@œ®Ôă¶žÞ´¥Û5݉ž–õÂ|¢xéöAM4Ì*mf5(ÌJ7jzèç˼¾Ü§E¼†Ð¼ühÚþLÉ>2‘ÆÈ(´ðñJº}PÓG3K`´Ê:–+¸)fj)›¢†ÇhÔй '*Ý<¨éƉ>‹Ë9ˆÜý_’¦<ãcø{W»ƒë3#ý|ö,R±8œ“Ð ¼%¯¤Û5a¾Ýëû÷ûíªðë×çÇûgCêʇ i¼ÝéÏ{IÞnÊ1ÊÞ¦µä·KVý/³%BöÉÀÇPéæAÍÄ™#ÒÄ™ñ@+Ý>¨ £¿,Ž2VîÎ(w=wZÒŒ?Læw﯎æ÷óý£"¥e|PÓG£HßÞkÖH™•;>肉âƒ.`¼Õ”~PÓ²‡jx¤Lv [æqtº­FǼÂÖ?;Ê+ÜT£e·°r=ô +Ip -ﮫчÎòݺñ1-ïcn«ÑO¬â=±m5úàeV¼—¹©FÇÝÌ–yœîªÑq÷°e^$§ûj´äV/m`)DûÃ6ô© ‡ØÒPÐE䡀ؙ,šV׸kgy×nW>ø›–÷7wÕ胛hy7q[>zw–÷î¶Õè£Ëiy—sWV<ÅŠý‚²«8šÂUÜT££¾bEùŠÛj´è,öƒ i£½EÚÖ`w‘–Aä/¶Ž¶6Øaä/x‹ûy–÷ó6Õ舣gyGoSŽxz–÷ô6ÕèˆKly—xSV}=šì&E(5qûß¿#_ÍþPUyÿÙ¾ýyCíAÙ—kt¶æ][ 3WËŸï?khžÉ;ùU{ w,óÈ,5°ñjsßL5_¾½}'O4—Cï4+`3ÐóÈ¿Í.ãlýìü¦¿¿ZãÝçóè:š†¿ãÕzÓàFÅRÚðÙñø÷7òDù4×¾îÄ€Þ¾ÿçÉÏ_h¦úVW€%ï@·%ç>{ªòĶâ¬H†|P¥¤ê—™“HSQèï?w!ù¸sÒÛÇŸ·Š’iªÃß§(ÒŸ5A.HÓò²ðÏÌKnê ëyéõ£ýæH¸€ ´â锩•‰ƒÐìË%Á¥‰@¡ RK %‰d`•ƒE«ž B$±<á¹ÐqAëž g¤\¯+„P±H…Xꨩ tA’K5¯8Ô(§eY)JúT°JA Q¦hX(\§`Y(TмJõÏ¡+¨\*zx.]A‰µ Ï¡+(±Xá¹Èq¥=Åj…çâÙ.WÐ:]«W"]Ai‹@¡+(X±(é fRÝsÕ ê «¬Ùš‚ÐH2Þs1Ú ª€•êK)ì\ÛÖ<9® .°,Cû‰T—ñ\º‚‚A(*„òPzñÂ3~£ÁÅ Ïù†-^4$.^8I,^Úo4ªß8îÎáüF£ú3ã7è7ö…h:ÉÅ ÇúFõïH„ßh¸â…'üFÃ/úT°xèSXq(Y¨ÖAh(\¼`¹J.^Úo4¨xh¿Ñ âE ýF£ûÃR.Òo4ºß8C1~£¡‹4”V¼ðœßhˆâ…çüFÃ/Úháâýqñ‚•A¢xÁê«ÉoŒTí›]ñâ) Ey³F÷$ýFÃúü©ÄâE ýFC/è ââ µ*^ì»|ÉâÅm³ç`_¼vàøºÏð’@É´+^Ì@j8 ³Ô[3_ª9ܶŋýK  ˆ¨‚l:¡ÿ®‹åýj¾ÎÕr@sñâqgeúõX?~~üùôÐ\¼ÿF¾ý $*^XÛp@7áÁÀHl¦x±î„žJû¾7²äpÛ/ž¢HLÉá¶)^tªw!SÿÔm~Ÿ¶ÛФ!Pšii$T¼à‘²éL‘ššûQýüõß/N×/›5šË{²UM­úõß °vw Y™Ìlùñ}aKëz¶$&rOïîúMuÇáDÖï@:µ‡ÉÝP6{š{ѵõ§ýõñíW €6{åC¬€ùã÷Ïλ'4bW®/`zh&öß;oß xÿØ®B•Ð; 64†@Æ!.ß^ßzçd´%m[µßÃ÷ú› ”ùße³èp¦îrå¯ß/ýø†…JT¨ ^o¥z'=ÅÁ·ë 6] ‘vңȷE¤"píùÖ£ˆ´C®"ß{‡vÒÈ÷Å¡‚tMòýÛªC;DàÚ!ò½GqPÝ5בï=Šƒ6©¹vˆœõ(ªªá€nRëéäâ)Š„ý€|çQDZ×zï<ŠH³é/å´GQÑtÂí,’Ô[eKV™¬WSD´IË6Wå›ÕuÒ²ÝUùf5ELŸ ·£ôÉz5EL¡LH„BY¯¦ˆh”–m°Ê7«)b*¥ßBΩ”õjŠ˜N‘²^M¡*•–¥¸¤UFÎd´Êf5EL­LLN¨•ÍjŠˆ^iÙ–¦|»š"¦XF–bËf5…ªY,}*¨Zx(!õa[ÚQ¹\Ô܇esùæ½O$ùaÙäG¾yï@ÓÒ¾Êö½Ï!b[ÚYÙ¾÷9ä?,›ÿÈ·ï}Žy‹–Í[ä›÷>‘TJ˦RòÍ{5Ò²\p‹g.lK{,›÷>‘Ô…mi—eóÞGÍ]ÀÀeóÞ'¶™«¥–Í{5Ÿ &Bx(1­êiÝ’€¼ª§uK«žÖ-‰ª[ÆÛqº%QuËŒÄè–äV=­[\ ´FH@v5ÐZ*aÓ«ì·»IYQOë–D×-3“3º%auKËRJÒ-KQº%¡s¬ô©p’•†ÊÔTMŸAt0룧jlÍi©bçE¢+ÏEWÅΊDWž‹®Š˜´®jNK1h]Õœ–*/žѕ碫âà¢+ÇEWÅÁ:DWŽ‹® ÚªZöLbtUsZªˆz@(¬¥Š½‰®<]Qh]Õœ–*x¨â/ˆ£+JŒ®­[ÌÖ:ÄDó[Š/Û|y$N œ/U|Ù¥ËÑU u‹ÑU u‹ÑUà< bÛ‹‰<盆Ähœæ9¨Ø4$êÑ‹$FWÖ-EWÖ-†Ž®X.—£«@ëCGWô©ptEC‰uæš«3ß¾$ Î\suæ;®3“'ëÌ5Wg¾á:sÉ­êÌ»òpë>ªßŸï¿Òmùï¿Q ÷àk•Ðï@ ÎÜ¢é_w DlH.êW$±³±c@±É¢>Š6nlQÕ½olQŸ‰¸ŠÛ—tPÔ\ÅwP8wP4î  $Ýï¦ctöåá‹Ñ•öˆ„•ö‚µvÅ"¤mA'Æ‚” `¼6 ’ÀÞ-Û Ô!þîëo /HÁ-‹9¼­I$Èâ4’Ø%ä¹.¡ËåËÿ’¶M(ÐX¸O¨¡±p£ƒX·­ GRœJ¸@•àH•páU‚#‘°JhH$Q%8R%\"*a'Èœ/×!gnB‚þÅ‚½¹*HˆâP_6þœæÒH‚Jè»4i•pÉ)•¿k, `ê ¨‹šl{¬«zÅ9· ›#{¨|4Ëë¹êK·¬/½ Ag_4óiþx$Ñáð¤ÃqùR‡Ã‘Ç ;5‰„öLØá`‘p)K^r—] Cš†$zư¸$Lì9ú%‰MƒeÏM$‡ŸKñû¡b)Î*¨–=÷‰„ã}I2ÆlÿÅtâBµñW8jXa%È×G*x…ýsauX›žÙ談þ~$½.žAoÖX(ž^ ѫ%hÓUhåHj °@Z…V ‰„½kG"aïšE’=ŽŠ¥x|<_±/X/HØÇco‡}< yèP/.)åë·-!ÅFUT¶ ¤bO;…±Š½¤±°b÷4Vì5ÄÚ´ëtôz:D¥UkÛÿšÿÜ;>gaícè…¹+¥ !\ Ñcݸ¨Ú®t•ªL¡Ó³Ö9ëˆu%­3"Ö ZgdQWXÐ:#‘í˜^S]ˆQ³­êŠeu™Õ¹²úÆâîÊê› }×X8«SC¬›Õ *.©'™>ïnxc]Ò†ÆÂ.i ±°Kê!Ö¦}SÕ]î’9"Íss{¤tJ§IÓ_ÇÛ½}ÿ(ûDp»ŽLý; )[fVOHvþvãí–Eº.gš¦_gš¦_WÝåXµ”æhíüóDnçX-p)äo׺ç²á)~S)n;Æ$¹ y8P|¸Ý„Tzyfõi²)_÷SÂÇÁ­ß~ñú;Y¦„s[W#£:­òûóå‹d–)á1¤÷—@j§$ß®Òßx¦#ý¢¥%¹ t²åD§ßì™òÒ4M}@æ²Ó/vß! øMøvÓí” ï{3>éñðuÖ¾ãíQûÚ~®7ëLz!ÃÝ$;jßéÓ—¡eÏTÈgj»3µe`9ó&Ÿ©íÏ$Ù{˜#Oßî­ÿvvö0~wšå¹®H:¥©³›/ü”®Æžß½žÒݽžŠµÁéjêùˆ´øÖ¿º×ï´'žNsùÿ‰ÎåwUÃúOé¤Ç§~»÷·y,5Œa?¡UÒ«0d°ß»¿,?¥ù2”Ò™÷ùSÎÔ†ò©;|´Ã#Æûƒ‘çŸoõ{¦Û®Ï¼So=?MHoÝG$y<{P'ò‡²ey<›xüë¿O³'æúŒÁäû~š3³d‘–iÒ™R?6æÌlê\ÿÎãøG9v.T½›É"¥ñiü“‡ñùíƒ>SÆ?!ýùFûãÙU˜Åßs毷§&ý‚,‡ „3sž€JPæz*—pððÃTÂ!¼6%”¡Ì…ÐUÎÔ\ž Ø%Ž™‹šË\넃–Ý!n(—R’@ó®%B~¶1á ~·’È8넃v&ÏÞ΀T‘gYࢳwI¤ÁŠMÂANÌxÇÒé ÓNì·ËAÚÉ•,R?“ãSaÅ&áp “ãXÅ&á %ÕÈ3% £¿]’ÀTIñÄ ´SIjð$§ÂŸ +V %åkU’k<íäøD_±J8Èß®9ÁO8©Æ~»@ò¬´L ‰Ÿ^ƒ’ècéd=Ñçp¢¯X'Ôt/ÉO&…é^)‹ßÎñiÌbpyœI­넃š‚f¹ €)h醒´ì™Ò˜îe}Õ‹’î­©to±J8è‰cöLZ⸦ÇÅ:á ¦ Ù3e(Íê‚9á ¤ Ù3åJ º¦RÐÅ:á ¦ Ù3i‰ãšJ›„ƒ–Ì&Ï”]$Š{6é_¬ Ò­Ÿ2#Q¼f“þÅ&áႚ-D›„C„â5[>(¶ ‡#Ôlù X'ŽåÇ—f¤"^>p|ù`Fºòó$Òõ%ØY­r½è…ˆ"f¤–4H.¸”ªgíÝGÊOÖ‹¾fz!ÂÖë¹^aÁ†½]®".DÌHE¼|àøBÄŒtCE$ÖJåÊ™¸’ÆŒt…-’â¹Pq|qdFŠ#Ž/ŽÌH°8Èo—g°DÆž ù3¡`ÃÊ]^À²{¦,Û±ÙÌP¶s,X¶cÏ”À²‹d`ÙŽÔOE ‹m,p½ÝU)ÛÕTÙnFÊ¥Ûy¶”8#Òí[Þœ‘nÒíj¶(9'Ú`Q’<Ó튒®$ùé–èEIײöîf¤Û9¶ä:#¥Òí[r‘2Xre‘®zɵ¡íÝ-×K® mïn*¹ÒgºI%WÏ–\ï5 ©æêÙšëê"]k¶èz‡J`M™>•EešV)¬*³¥’‡L/¾Ö­N«t=‡"^œ*í矖ÞÒõ V¹ÒõŠ©äÒá,%—² ^›!;J^-= yí ¨F ÑézEŸÐü{O²æ|NFWž¥Ñuš3£å’cmÚÆ‘WËA*º¬È¡\mÃòѨR†û-ó¯¯ýrG{š¸."}„šd¤Ë*UÛ#}_mu§= R²Cš=“|ZV©ÚL-Héiw;˜2Z21Ñ‹î{ƒR! ÒÈà}Œß‹\g;‘ëMyó髟ï?² R.& Jû»Ó'(± 󙞖3õ¯­æ3YšN‡DÃéÐþ@xÑ•SøóØéÛëËé5„æåGÓ¾ÐgšÊÊ"Åë`Yý¨A°¯ÊÀ"•â¡-Y:¥Zèú»Sà,Leå‰â¯/ Å(ÞÖ,Òä>Î¡ë´Æa];þ\·¤´Lee9à ¬òMæÖ‰— xÕÎñA«ñ±½ ]£¡kcV›I‡§§Ý ¹^ÿ×ýe¥Å\&¤Ã ¹éç3kÈM²w“Μ6‡9.¸[Ì<—j·@¥uUøõëóãý7Iq“ s©&¤? ,«Ç§²òÀ™£ë4ræè:õ5«ÇM¾¤gîÞ\HMNØgëY¤)ü$øeÑ™cøÓtÔb%ØÌ¾Ê>:=ŒÏ÷VZÒÙWyŠ"}{¯-y¦tü œ9Åg2ÁÏ‚„bŸ_ôíPèC{™©ù”Ö±ö.…ˆH7xµÀ‡å#!ð±|à“ëåŸ\|¦ ÃòáJ.>«Ód•ëåŸ\|,ølðœçŠW6xã!T_v8„ÊqàÓWI|r=ð©øÀgû€W WªH¤9ðB(û£jÈÛ®´%ËOS?­ÈD•ëOÅ>9øXI|ª—6°HjàS5Ï¡%y<ÉQ¸Â*ß9ð‘C( >UãH:IåŸ\|,øäzàcùÀ'×Ë>¹øX>ðÉÙÀ‡Õ™sàs WF׉Wòmàs ¡z$*„Ê©À§ê¨ÅÞî†BVZîÏã~-&Bå›Àçñ¸`“¡ò]à#†+ô™Œ®´ŽµœëÀgÖY>¬Û=à=lò®ÆUìØ»ì X >½¡Fï;PßÞ±ç´ü£ä€L|!ø ôŽê+w T9‘sÚŽòP¦œ¨RV”†òØýᚤQ[P^ºèù‡'OTÄ÷“Wk´US; ›°žÜ–ÓzòŸ$Od=ùˆôöý¿’$Ò}Ån|…p(«Šä¤yÃîa=ù(%Þ,Iï)ð9n'Ÿä­Fš¤4¾œ|”“×ê›co‡ËLjâ9S>0‹’Y”fQ2%‹rO]"ù‘)Y”{:阌̢T¾n8 +,Ö’WÃåc’Ø,h“'ËÇžË}d(‹2#Á|L†²(=•EÉPe@b²(™˜EÙ!ÁÜG&fQv·ƒù˜l›E‘ËÇå>²Ý´X1³¦ò1Ùn Z¬YS¹l›E‘ Ñáªïœ-{ —KòvJù¸¦rÙ6‹¢–Ù3õÛá,JÆgQX=wÏ¢HEß’U½÷,ŠXˆ¦o³(ô™`…FÂåcR«ÈåcÏeQ2”E™‘`%CY”Iûâ,J†²(ý’*‹’¡,ÊŒ³(ŸE±ì™®JÑ7Y” gQz$"‹’‘Y”ÖU¬ÜÉåcÏå>²Cå)Š„sÙ.‹){.ϲ(rù˜õŸqù˜üvDù˜´RDù©`ÊÇžˆW ¦|쉪ÀåcOÅ+.{*‚*Øò1 „ËÇ$.7.“Ÿ_,6\)Pù8°!TÊÇ | T>làS òq`Õ•B8ð鋾>…øTͧ#Ÿ‚+{®°|ìȪ û£ ä™@àS½XZë^tŠOÁ>mH.PÊÇŽ | º|LJ .7ì™Pù¸a•8Q>&µ8Q>fù —I$¹|ØÀ§@åãÀ>*6ð)Pù8°OÊÇ | º|Ì~;­|ì©À§ ÊÇž | ¶|ÌJ°øLøzà3!1O¡>grOÁ>¬VÁ«éPàÓÝŽ¥Óª|¼UE–ÓCù8D”Óíå]±¶ê"ƒ·?䉌ÔIñÇŸ7òDé´«úÎ@jX_K×åã8Pwµ?uCžHšµ=›*§‡òñb J7åãt]>þ».—wù²ÓL-4—w†ÀºÊýüùùñçµ!r.‡£HßþÔägƒåckÙ3%KÑwÿ0€,ú¦»òñ?Q$¦nŸ¿Ëízl¾]Z’+/ãRöɽüÖ¿Ž²(±¦ýeϺè^wÚ:¨i£]ÿо\ þ«¼µ,T2O$x<´¸ÕóÏòGÉBÍ^Êã㞥lýiígýX¨yºAXš'l:•«CÃBeÓ©ŽŒ>œªþh²_'1ž8ý}L; «Þ~¿t.j”XAå*T¿Ÿ>Õ<Æ?ÒRÒÑêç¯ÿÞà\/–\Í”Øò¯ÿ^B ‘f35ë„ï‹N°®× žD2Pj RÎ M…f½¤WetG"(},R Ùœ¥S†d¯iH$]^Ú†`òœ—*’—¯¥å1ÄÚ¦~üþé<¾ÝF ?NnÆžâ¿>¾}8I“–Êõ XžD2R›"é°æ_ÐïH:¬w ±ß1pýŽw £1mŠw TjS \ãä(S€˜~Ç;ØïH:¬w ±ß‘tXï@b¿càúï@b¿cÍõ;. )ö;Ö\¿ã‚„ûIìw$ÝÌIìw$]ßIìw \¿ã‚$5Owq4©LŒ®L& B™U™´lóôÈ(@œ21ª2iÙ.ì;P¦qÊÄl•É^ Ħt€Ù*“½Vš€­dTeÒ²ÍÓw I™tñ©L P&#£L «LZVH$e2J £L P&“¼ÊÄèʤe›§$!•f[Ú¡ÐSi¶¥]=•fÙTZRi–M¥å •fÙTZRi–M¥å •f[Ú3ÑSi¶¥==•fÙTZRi-›JËQ*­eSi9ŸJkY!Iâ 0ÛÒžIzT&$F™Ð©4ËR\ÌË{Vd /ïY­”¼¼g•IòòžU&ÈË{V™d /ïYe’¼¼g•IòòžU&ÈË{V™d[erȾVd;erÈðV-et^ž=S"eÓ=«L2]™ÌòF(“ŒÎ˳Hb˜Ssʤ€aNÍ)“†9ž s æx.Ì)`˜ã¹0§€aŽçœ†95§ æÔœV*`˜ã¹0§€aŽãœ‡9Ž sŠa‹$†95§L æÔœ2)p˜ã¹0§ÀaN`u@œÀj¥ „9óL à™ @ŒgRÏd>t( à™Ì'‚.N<“‘Ø”È@˜X­”0'pžI±÷LaŽçü‰âà™ÂÏù8ï™´$•ä0'°Ê$CaN`• í™X–NbÇ@à:n_þw¹‚âgà:VPbÇ@Íu ¬ ÄŽÀu ¬ ÄŽšëXA‰ëXAáŽúT¸c€&{!Õùk®ÎÛÕÔ#½5×{pÛÖÔÕŽšDš:þ9Öù«ªýÞéѪ‚„J7Róϱù ‡ ßQ¡µêØÕ[÷QUŽ`õt+5áß(”ûÓ”,T*v2TÓ©è Ê}6Õt* IM‡ÉB!©AÓ}WPÅRïý÷çû'ü‚Ù¶sàoôþ~eI"!©A·}ŸÂê˜Pf+5’:B ê´©h©1[# c¡RÈê4­2(Ëô©P· Ãê†k·aФ&B+JjÒƒÔÄ©I¹~›¶u$’š‡„ºpZMxh 5ëO»í{:5g†J¡[EÓ*CÎ^Ó°P¸G­d¡p“}*Qj×[ÖA%[©‰µÍ0ýn îRcÏdVo]K±úå¡£Ô®«s/#–À5– 7-ÛÀ¼Æ’§ß>ÇDIk,)¶™°`l³ÆÜ´–m‡^cÁè¦å±`xSñ´—:¢GzᨤÇÊõ–è ‡J+(áTž…Bä2¬Õ4 GcȨžÆJ¡0òçÊ06 Ãô¤ÏF £î´µlksetûÓwZ1ög -Y(Éoëô g5.±nºã6bÖl…%åÖú­ž”ÕXaI=iÍVX©$Œž´+,Q€iÍVXØñôˆ?—hi:¬X GZ  [ ÇB é‚–ÍŒ Ä*Ô|AË&ìÖXRš­ò\šm% ™[c¥Bœ? ¦ ÖX² ÇeÚÖX0ÕÖòX0×VyKJ¶ôÂiƒ+׳m̬ `º­¢O…ˆ`ˆŒ ÇP†\¸Š LO¹-Âèh¬2=O¯ #®+J•µtá’C t,ùÒ…Kö1P¤PS“.\c ¡›–²@I4Š [ dÅrᤠ—ð1êó]cáriMc‰õÒštáèÂMPØ%¼ ×ÒPX€†È9rŒ¡ñ¡â(UÓºå(/@9¨›Ö-/@9[8­i,\9åi/*Z€2P; -@[<õ,”yÒ™/ÿK. ò¤Za‰IGZ –Ô¬3aa¦_a¥¢kIZ³–˜Dð¤Zaá$‚§±p?—˜Dp¤2»,\$‰àH dè,tx ÎÂyÒ" çI d¢Y8Qe 0:+…LÏÓ+ƒ‚ÍŸ Z ŠÇ‚ˆÆH.B/N€2Dð-@¬²ô©†áÁÃÔö~ðóû[?/t²ì‡éÏÚ®îdøÝL¶•eÝ¡yG%:P÷ã8 3íZ†öO@õçŸðZ•$P*NÿïêOoÉ«eâÐ~ß~þ)ë"} « Tõ[è_= ”ë‹ >}EҨЯÖ!趬¸OiN4Nin¼#.G¤· ÇRûrYú±ý÷ ͳ³ýJÇrÒe\=©GêlŒ‘ªîr'ngŽHnA:q»T>SëžËÆÓH󿆝÷= åDz'¡êŽÄÒéº M«$7®n°nbét\Z7M¶·I8oY¤B=S÷W™ª»Eºék ¼c¥nšlXqáæ¾%Ï”LÏí¾î÷@ØÐOþö«t,Òj{Ã0}x5Ìë¹î·7ü`‘VÛbHï/EJã·ëß7ö·û ù)Ét¤_4$צÝýëÍi_‹” ï‘j°/c‹TŸÔ-[¤Ûiw;þÛ™I‡¯³ŸŽzÜúçOV«˜I‡§ynÿ÷•E°?ýOÚµxüñï×!ê½”Ñ"üþp?­í§g‘Œ¸ ¤7œïe` “Ê%ª÷ߥmX7™º›¢li]0N¶—6J|úN¿°gÊe¤ªGjXMgäÕŒ¾ßuR~²Ú×LJžæÝÃêŸ~[×<×,Rú  uv³³Ä¤ N/û­)Î.[Slý£byü|«ßHiIo»î«N½ 9þé­ûˆ$ų}_†ÓÒ>[¤Ë"-ƒÇ:IðàûvìÔÐü”Íþø¿O³ïëúgæ“ýÑÐ<žM•êðï¼/c”»q_FÃ#¥ÒF ?n”ø o—I%ü¸Q‚ö³«´Q¢ž÷e<žˆóÕ·º½K×ó!äÕß ¦Óõ|†®éz>„´ú»b òj©²Œ¼6×9(C‹¶KòD`‡¸oد–Ç—û¹e«9IìD>eE‰;ÄݴϓĖwˆ»y)ËÚió·ãút7"²ÜqAFº›Ù!î¸Ð Ý͇ˆìw\hnæCÄ÷Pûa›³,®:R@ªrAÊõ½æ rè¤íÆvìínânl?®ˆsäí¦„ƒ„Ô¯÷#Ï”\ô é räD_[×™)övF\[çÇ-Û5‹”¢]ë4„ânÞ!^·¬»¢MòŽ¥¸°JÏ-;ÄI—Vé¹e‡8‹wˆ’Nòq7¯Ò#Ï$ïwÓ*½š=“¸CÜq¡Á‚$îwó*=öLâq7¯ÒcéVé9íåþIÛ!Þ «ôH Vwˆ7Ã*= îg-ç´JO ~±Ò2­Ò“CÚ}Z¯Ò‹„ý–mòvÓ*½È†t7/ $¹`Z¥÷Û£5- dé”JÒø,Hh‡¸‡Ï™⎈Wrf‡¸#"¨ïwTà“ã⎠|r*𩚒¤ |د–£x¥%iTèT‹*öw q‡8øäh‡8øäh‡8®äh‡8BåzàcùÀ'×Ë>¹øT|à“¯y¹ÃáJ¾©´Šg"B¨œ |Ú’æ§›¸› Wr=ð©ø*ÇO_p8ðÉÙÀDzgÒŸê¥e9óøDÕªy-iT¶;Äc[Ûûí®h“|ÃR>¬9Àwˆ³ßNÞ!N>9Ú!N>9Ú!N>9Ú!N>9Ú!N>9øTì·Óvˆ;*ðɉ⎠|rv‡x å>¬´àÀ‡õÃPàÓ:Ö/Ë>¹øX>ðÉõÀÇòO~Ü!¾Ý¤8¯N}öåV2Þ—žxH\ÉØïã úV€ Q€Æ=äÕÄ•Œã‰Ô­ L÷'W2Þw•@âJÆû®H\É8lQ êz ¸’±œ× ’!Å•Œå¼^€d$4ÜU{¦DZ¤xß0Š›‘–;Þ·ž°·W2Þ·¨5$Ì¢U™Yûù'ÀäGFdQz ˜ŽÉ`Åúç@dQ2˜E`%#³(mS’4ºÂb-y¢Ö¡É°Ýp@bùØsY” eQf$˜EÉP¥G¢²(Ê¢ HL%CY” fQ2”E™o³(Ù6‹"—jC°,ÅåòqMåc²mE-ú²t*ôkød…nÉ¢Äo3;Ù6‹¢–jÉ3Y”h!º¦ò1Ù6‹""áQ¶Ï¢ÈVVèY”¶y.Y=·Í¢ÄJÚ%K§+*i—,pù˜½.³H¸|Lê¹|ì¹,J†²(3Ì¢d(‹2i_œEÉP¥Câ²(Ê¢ÌH0‹’ñYV«åã@dQ2œE鑈,JFfQZW±îœ¹IVÏå²]å1¶ÆÊ3d±,ʶÀê¹*6ð)Pù8°OÊÇ | !ðÙ‰W !ðÙ‰¡ X>v¤C_èÏŒD>î›í ÑcÛ‡º±R­#úÍC]µÍêÊõLL¸RpåcÿÉê&¢|LR—öv¨|Ü°ê —’ pù8°ÏaÑ—E*`!š4,Dù˜<Ó=ð9}®»ÀçPˆlU òq`Ÿ•ø¨|ØÀ§ ËÇì·ÓÊÇž | ¢|ì©À§`ËÇ {»›T l¸RìŸÇ(B›ÀG+i“||ä’6{&#}Œ\àÓ!‘\ ¥û\²|œª ¥g ¢|œª ¥{ Î#Ð÷@o€Œ4n¦&O$,”žO¤îÞe и™ºä€¤Gѱ©òqª.”žˆòqª.”iäºPz$,”Öð ¥IbK ¥g¤oX"Áò±µ ‰$,”ž¤„)ú¦úBéYÞˆBtJ.”nZ)“ÿ–ó.N×Ý8·Èâßr^pâH$0±ûvžD2âªÉybw@H°4¯œv³H`V]ßB"©ý‡4ù—ô‘†à$ö®èd ¦è$ö®è”)@LÑHì#" ÁHì#" ÁHì# \ÑHì#ª¹>¢…!Å>¢šë#ZpQC"%R÷i$#u$‘†`Aûˆ×G´ IM‰¶d•‰Ñ•ÉD(£*“–mJ¼ˆS&FU&-ÛKxÊ N+™­2Ùë€Ø”0[e²×J¡•ŒªLZ¶)ñ$)“~M §L P&#£L «LZIR&£”0ÊÄe2É¡LŒ®LZ¶)qABTÛÒ…¢Ú–vqôÕ²!jBTˆ¨9Q-Yæ Dµl¬›ƒÕ¶´g¢‡¨¶¥==DµlˆšïCÔØ®0&°Ì!ê.ØmÙ`7çCÔ–=“¢Ú–öL@ˆj[Ú3¡CTÛHb¾Ë³: ù.Ïj¥ ä»<«L2ïò¬2É@¾Ë³: ù.Ïj¥ìà™lÓTžÕÙÁ3Ùw‘Z)ù.Ï*“ 仫2”ï ¬ZÊè|{&1ßåYe’¡|—g•IFç»H9‘ÜšS& sjN™0Ìñ\tRÀ0ÇsñRÃÏ…9 s<æû0çÔœ(öaÎ!^ª9­TÀ0ÇsaNÃÇ…9sæ'œ’DÜšS&sjN™8Ìñ\˜Sà0'°Ê$aN`•IœÀy&ÅÞ39s(нg;ãâÀ3™ gRì=“C˜Xe’0'°Ê$aNà<“x&ÃJÆ3)g2#AϤà=“–d€õCÎ}«©²ãCΣ–hÏIJϤúYÍÕÏn»Ý˜‘š^ÍÕônìjLøŽà¶ÛŒYýY΋×àí2°ù³œ÷®±Hèvm[“Hr±bo—‚µŒ÷ÍÚ,ª3¶-‹$Þ.pUÔ)UÔš«¢.H¸ŠêH$#È]å9¹»<@Á¡°à­  ä*ñ ʈ{ß¹Ï×C¡µÕžû~+(øÁ„Ë”øù/»¥Ž‘/èÈ/xa—:ÂVÄ”¤<+Ï)Ï ìMž  ~YAAõ &4¬ d­è ¦`« ©@WPPƒÚ†…2pß;¦ÕNå-ô4–Áš…2pµ7 û™ÕÞ4¶ð% eàêe|*zõ2 …¼g¡ \ Nuf5. …•LÃB¸oŸ*C2XÑ´b¿  ö«KÅ‘ýA¨›Þ—‘òLûº{•w@‰þB¾¤ ˜=]³WK—g"÷¶þÕ&‘Ï’ÊôGÈM+NÝ]Á矢•Ùå`ÆsþP¡ŽxÖXï€nêT†!ÍŽ!%Înk(ÑÇŸœmv²&ˆˆeô½UÇ$PdÍŠOv@W$",±ÑÀøšï^š6@7$kPDÌ(l–EºèÒÖbiÛ&Û婉X“l“íòÔÄ@ÓIŸšÈè’M²ýÏ×ÇœÝ÷÷Ž™ìÔË]½”/þ¹Ò%ûò¿ÛÊzÿéŽô4![kG¤—ÖÊýå{¤ù¡Qôm@ûéŸ,HfA:Ž–ë‘Z)?gòïÈÂ-H«mi‘3uH@~¤ë¾äÒ/ŸÆÝ¹ç7ëKñy—ýã²Ë¾Ï·Î»ìm<¾ `˜ß¦ø®IM0Ø`:m"ÎøX@÷úa¿a:¥¬/ˆn— Ó[S6<[¿ P¦JAÓ›­ßèÞ)yµy§%y¢ º¹ä‰ é­š^öóÈÍ-kÚùiÉ«]Шв¬­ÚÁÆ)Û½ МxRJ.zñ$S^RèÆ³gÒ§c0:€öãK(Ñ'ZÊ„öãk(…î7 ”¡€ !¯†ýx’ØØ' ß4ºGçX™?þþ+àÇOOÅebXeÒ’€•‰e7…Q {&èÇcïûÊùñýxì ^I?Þ²HÐÇ^å•ôãqDp]ûñ’÷ÝÚ{ß×µ/F\~|ô}6áÇ_~|ô}6áÇ_"mXcR÷Þb]gÂé3IZõæRÄ%paï J”’ËWP¢À¢·‚%†äó”(2¤ð­ ®0b¥O% MàÂèTž 6ø‚»ÞEéYìþ€ˆ~ýæÛZÖQjZ6WÔê¢JMË&‹VP‚ÔX6[´‚’¤fxôGJÍE•Ëæ‹VP’ÔŒ§â¤æBJ AAjZ6ù´‚*À«M‚×AÎh~µIÈŸž3jÙœQ¾mRPX½"Xýa#5²òPPjNx ¥ÆÒP)buBjR@BjHÿŒ§šŠ‘šÕC³-o!Œê¡Ù–·Z†ôЀ'›o;_4 ³úsÐ*)ANfôc]"îéµ,RŠ\*,17U`?sªKšÉ©ºD±·+Àû;BZÏxZZ6žñ$’hc<çNZ1ÀÆxÎÉ[A‰6&pò²‚2’6›¯ RÉ\՜쭠2èNÑ´ºJ–¯æ¤o%ÚÏyf+¨<4ûÀ´Ê€gVsRS xf¼á™8žñœ)ˆxÆsF¦ â™Àó'Šgj^7ñŒæÑÌ«²|9HM\-Rs¡¤¦b¤æ<³@K òÌ-5´gH$ƒÚÏ”3™hû™Ð5¦5{™cû™\Û±¡ä€ŒTÛ™–Û–ìÕR°Û¶f2PÛ©Bà€®¨‹IáI³o?S›˜, Tè=Lj‡–9¶Ÿ)-'àD'ZNª@"–“J3R†i9©˜–sªåð$j9©˜NõœÔ” [NúnOòD°Û³,9 ­JMBµœB“-'}·'y5ØrÒ² [N,‹ZN .-'–i91LˉeZN Órb™–s®år“ÞrR1-'æLË ÖzËIÅ´œ¾å¤÷&H Ôrb’FWèM@9ôoH ¤Lª&p@°å*ºåIJH å„P&tëxK27V&–$8R&jˉ9¶œh-Øïb[°ßE´T EÀ[´,¸]Sy;º” ½Ê])W+¹áÛ±%7|;®äÆÜ.=Ü.^Á·cK#øv†äL¥4bŽ¥-•oǦ²ñíVî<‰dPÊÜnŸr…Ÿö)G%y èTÄä.ž·cSCøL4g²H>&’n—Í Zû˜¨&‘ðc¢@"áÇDžD‰X:áÇD%‰„±G‰œ¨éöH|og@;Õ½üçI$ü˜¨&‘ l´…\«5»UóoM"á–]O"á–Ý@"¥°Ñ–¥S›K µ„”˜Çs¶e—½”L§„”üí6ÊžÉÀs2R̓Š/æH 8†¡$ JV ”¢d!K#8†¡,9 +|Ÿ8 >OóP_§‘'ºÁ|:¢Ì¥9’³éç[$NÌ×|¾U’@øùy5œ˜'¿NÌ“@øù tƒéô@2äLñ{ 'æY¤>Ncogàã4öL)|œÆž)ƒdìsiòÃO"¡–¹íudà] ŸÛ(/w …ŸÛ ?·ñ,~nC_?·)Y¨+|#CAÒdÇÏmàéç6žDÂÏmj ?·Áœ@?·©Y¨¾‘ñ,”/w ¬~!ðd¿Â724Ù¡Ô´ô©ðsøéç6%‰„ŸÛÔ$”‚Õ8©Ñ4ÉÙç6ž…ÂÏm …ŸÛÐÄÏmJê ßÈЧBïÊ–†ÂÏmट۔$ôÐlC"øHêF:hXþvÏmä§-ì™ {†Eævx< <Üñ$~nS’H8ÉÞ.‡wXŠãç6Nôs›’DÂñ {&øppæñ¹òr§f¡ø°Å³P¾Ü ,T ¶”,TÑd¿Â724Ù±gF“?·Pôs›’DÂÏmj ?·Á4§ŸÛ8 J ÁêRjN¸RSÑ„RCà…´4üñsú‚ø¹ <ýܦ$‘°gH$[vå3Å[vÅNÛš‚ÏmH{nãA.>Ò²oõ hÙÕûZt…ݨÊaƒ¬ç€ ØÕJÝ`Û'ºßöéH$Ô¤eGζ}ê·;ÓöéH$ÜöÉ"á¶Ox;ºíÓ‘H¸í“EÂmŸðvtÛ§#‘ g*!úÙ¶Ox;ºíÓ‘HXî<‰„Û>õÛp}Áíh×ræ™¶Ox;ºíÓ‘H˜3Ù3 vüñŸ?ž;ûÛÙñÞ™ëþy.»?Ï¥L|6›ß•Réfg~{ ÎEY€>ÿ„×.\à€’èqêî6ÕŸuEžh¼Z÷¿ñj¶_D9žÈ·Pýi©ˆ .ÊÓÓ×~yÏëË{O£A‡7õ³s?þ{-ËÀe“Ó4ûímpšº«ùòwÇ—“âòDc'Äpµo/o¯ö»¾ÿ¯æÙuxàÆNˆ¿O_ÇuœTöáX"ßÇ3©¸a £,÷{f{]‚ºr»gVTR $ÆÀG\Põ³-y·‹ªL~wÊ„‡ R¢®¨ú¶dÏ4)“ÇYôb2«€¦mžk–—.›çR] u¯¬:×?—z±¬À]2 ,Ôf§L$­/g 2é‚:G(”É8ĈP&†R&mYÖT&- $(Ë+£*Ë+£*Ë+C)“Î3!$eRñÊİÊÄzI‰È(³S&qP½ØÀ"¥šZªšçÀJî¼[쟧Áû¶ïý톖ޞ\gvßõowØþýwìÛêQ>¦‘Ï]LçÚ’DšÛ¶þínßÕôŒâÂãŽà¿ÿÞë…=Ò<^à¹tìí¦Éc÷ÈØÓd'ËÛ–Ï?ŠŸ÷;‚¿>ÍU¾ï“Ø 5qW}6Ï,¦–­Ç¯÷>+ë–3¹Æ{iÒ)O3Åwgj¾<èqGp”âo>LñMÂ×§Ç(~~¼”$Ò??…èí~¾û:Hºßˆ Öƒ D÷;@‹¹T F%¤ùñ0½»AšûM^-ƒAÉ~¼çLïnPAÄ÷œéÝ*8úñž3½ÛAªOžHñãkÊôn¶Ê°ÁÜlÕ# ùñ(&ÜlUýxúvØGg¢ýxÇé~¼'´áÇ{J™R™´$PHôã«LXe‚üøÀ*Ú'¯¦øñŽT&¼O^î¢OPaÔ’a”Iç}7+¸)ŠöLÀ¯«wè-])?>„–E‚~<ö¯¤#‚ÍŽ`Áû½÷íH¤Ló™Cï3³HW=¶(}ËÒ)W#‚²‹Ø3­üøã·ãüøM'øß½÷=ž©ìÛ‰´éj<"}üù`Ïd$i©¹¨÷8´ä(. {#CK\NÊKdhÉߣËK ÌahI„;=ù†–D„/p¡ïqGð‘Ó=ûw9pÁodhIô R³a‰~ý^£ßÀE¿‡¡%©©í¥ t…/Ý(‡TÀ‡ŽäW»¡ÇiнKÎ=â£YûŸ¹‘ßm,[©OïÈw1ðù%ùåð#>Ï"áG|,®àéöÌ-9ùˆ=SŸÞ±H7ôÌÍ‘·»?âž¹©Oï’È#>í™y»éŸŒD»û#>ù‰"kSRøD‘EÊàEé Ÿ(²Hø‹TÀ§w,Ò >˜#‘¦G|Ê37VZ¦G|Úƒ9öL‰ò`=QL"ø´§wì™Råéz¢˜œ|ÄÇž ?âc‘rôÌæ‚>$=Œû#> I{æ–ñ) µgnÉñŸúD‘¤SšÀ‡…¬ÿlàs@öv)|ÈÞ.Ó=_õ_B>â«Ñ#¾äÜ#¾’‚}Í%y¢´"z–Fºš'Ot…ïI ¹’$6…äJ ¹ÛG|Zƒ´#.q$Ǽ½LŽø…¾Ü})”øúÒ“ô¾/…’ßq²‚›*9#¾}ħ? õ$Ò¾ e‘r‰q¤µ¥ÓœyÏK]ËêÊô(”Öº 'ՅФøøì;Ió¼t‹$¿-óðyé)…zÙÛe€ šÀÞî º€šâ9|Ìž©€zY¤|dL~;ó€\ÈO†sQ°°˜Ýû$é‘CIøÆ¸ä€ ‹ÂÒ(C'òäÕ®ðÕ3 ” 좘­‹"¾–p5tC¾NK!E}ÑŸk. }¦½éö$½%Åò.ŠÑ]Ë»(FwQ,ï¢ÝE±¼catÅòÎŽá\”6°,.¹(µ‹¢9–¼]rAÖiý¨Ž…þh}‹d4gùs·CcáI¤DcôÆ·ä0|BˆáH¤Tˆôº-RGk°gºÂì:¢SÂf×=”À¤8 dà°òj8»NeèDP?%8»ˆÐu3ZCB¡ëf´†ž]'O„³ë É0'NéºÊyzöL š‰âYq3pºJM"¥ÊT&LÜŽÖµ0Að‚t…#_H% g×=º.H8»ÎÞ ÐuÑ•0tey<ãcØÛÁì:ªE-H0»Îª9%»^S¡ë‚„³ëì™pvEÊáè–â0»N#ÝàèòvDv!ÑÙõÀáì: dà䟒ÂÙu’F:‘'®p ” ì¢ÒEiI LÓ“@DvEÂÙu)“–jÉ $Ïž)…C›<‰”)Hœ‹³ëu,`v=°Ÿ]g)~£¤°‹Âg×ÉÛ%4Jʱg‚Ùõ†EBÙõ¦bmJ sâä·›:Ÿµ1`$gb…þv9ÆÒ f×銑\0w>Ëc›pìrÈ€  <‰„Ç6±HFCrús¸-Rª ¥rús¸-RÇ[•$Ò¥Ò‘ŽC©”é 5 •€ùV¨6rf(`©ÃP*mT •ÁQY4­®p¬ •ù4Ù 8À‹>Õ Nv É>¯ßT†9ë§ñX œ9h,gjð"Â1eü34§ 3j %¤™8Î)‹N<# %ûMèÂÄ3¢¼± ¥p ›#‘28…EºÂ)l˜§.º™XFSÕ,Tº1fM-(yÝ~9˜ a4 •ÁÙp4­®pö •Ã1s4TgÃ9êÇxñ,úçxÑŸPª¥·l-}•Àùw<–Æ• c<í34˜3*¨§/#þ<‰¤æãÌDªš‰–­‚ç‡zº<,БH`È"]Ñx8üíŒ Ú–7ñF-¿íÆÃ©#ëØ3¥pd]I"eS.HW4¬ »Dñžþv ˆâ=ýíÅ{úÛ% Š÷4ÅÅ{š àž9Î=;1Š ùTûQlê¨«š…‚£ØKF±iâh¨ ˆ£/x…S³h¨Κ£¡ 85‹f†[çh}€sÁèO(Eñ«xü¹8Ç2pÊX ±R8fŒWšÎ‡DñËœ?O"%Úœ?Â=+Q¼<1БH©61pô ůf²gº¢qøÛ!÷,Ðß¹g3ñvÏgâ ìžÎÄØ= œ‰/6îÙŸ§¯}ìùýíÃöÜ—~ª¶­ÚgÛ~ Óéôû¿|ùvÒ¿}á§Gún¿E»é[ûí»ü^s4Ÿþü;”µ^ç²Vßœ0ºÖ²®ì™ ˆ‰‘6ßG×JL\±H8ëÊÒé }(Ç\t]}k‰£kÌ9g}GF×ZœnNEׄ­Ê9» Eü&]K‘,Mqh°6GÑõœ;¨X:Éváî¸ÒL~A!qËò¶ –¾ Œ®-}*h°µ¢£kÌUzt]1ѵa¢ëЉ®Í©èš° dtMØÏ„³ MÅž ö4‰@²ù3/ˆa”ÀÚ#‘ ]pìíRXb‘2Xbét…•¡@"å°0äI¤V`à·ƒ=M5ðìöH ¬QÔ$Œ®È9]³H¸FÑHFì™R§; ×(Ø3]ae=ô¢hŠ0wÀ"A/Šæ'"º¦¡ …5U£uÏBá •Â@¾ ®Q@þLØèº$‘XY`Ï„£ëšDÂÑ5{&èEYöLWÉÊ?]7$ô¢,D×b„Æž ö4y–NŒdY¤+Œô<‰”Ãè,HŒ¨àíT£pPîb•s8i:9-Ú~ím/Ó+ëîÇGßQ$‘õØp|Ã%`¹}|zeÈ åö%y5¼j½ä€2¸ºÂeÝ$Pwš{¨€+ÍI ÜMÍÔmÏ,Òîhf‘àv^úvn1$R ·“wAÛyãOm“ÿÃvÞÒq@p;/Ýív^uó,y¢wÊ€ÄÅ;¡’øv^}É+ùÕr¸™Õs@\‚JáÍ¥$ÐåMúf?Ûåw ²H ¦Ï<&Âv^}s){¦nS%å+Èßì¤o(º*“iÙdɸ#’¦ÑôÕúåô‡+É©Ç4X?ÅÓ(m˜ îÛ5‹t…öN¢“øøA´æ,R-gM"a‹ÏDÛ;)ú©$‘ Ôì™R¨Ÿj r¦e‘°V‘ét²¡T¹Ý9­Ò(h•§asCôú>æØû&`_–Ï~;\ßlF|Ï¿ZCiÕøgçú†ÒMBJâ'rü‰òD.p@ ¼ZÃÈS4ZËI ȱÄ^‰Iß3ÿïÓ½gþûü–ª}îró*ö´Ëþõ)üše_陋¶ì$¤¬ž} ‘’8ÒÀ’Rû¼éqÖFz‡Ç©îózßß!ýzqîg og¶o ŽtÞ¸€é”QtjŸ}M":UÏu ‘ ðí.ˆN#?•iû&V秆DÂüT’H˜ŸÃùçÏúÔé†WOaz>µðÝŸåo÷üqšïnÜxº;ßMp§ùnš‰ó÷ß?÷OkËåÓ~ë¨×žÂ›Ÿ}|¼Ûåc<ÿrÏ‘^ oê3ÿúÏt>÷ag^ùõñúÍ6õ9±zé¿>EÏWFßiix£hüóøçÎ-wúuÜb_Ýku /›¾ïßû÷ð¦ïëNã]‘Ú{c˶cV{Ó²Ií9wBím;1¶Z´7§³-O EËPžK‘ýíÏÀe;¸éýãç«”ÍvJ¢”Ý©/›ïàv§#u¼ÙNìu|Õ„S§»“áÜ©O1©=ÅfÔ§8eV{[£QºÅh”çΗ «qRlÍÑlô‚6›³‚6©½Ål¬Ô^Ç-¬Ù0›Ù>ªÙ¨NqßåŠÔ|uî{äºj›úÜ÷( ZæÎ— µìO©å„SËîVËõ8¬–Ý8M-‡j9aÕryNSËá„ZN(µüìÊS|wƒZþÔéµ|êÓjùVËçĩ哂¦ªåpB-'´Z>w>¬–Ï}¬–Ï}A<þ<=çë'EÏçûõæËÿþû Ìƶ§ÃûúôïˆçÊî7àÙê?ûßÇ9¼Q1‡~ðÉÐßÝ_w~AöÞü.ûÏSxóËâè÷ýüñþÛž;_ºá—÷·ïµ|îø¥:‰7O‹ˆòËç·÷ØüP oæ¿_†1ÞïNŠ?þþh>[w /_ø9‚×”ÞžÃ+6ò±§_ÇÚ'ï;êç¿“õx&÷¸^¿”¿_ž?ll,°ÊÏ;ûp‹À}>‡Š ÇÓíMÃгyá.kš‚Ûw9qáufNÓ0ì}3¬aª3&S5LuZÃlgÈ¡:w¾I0+qÙVÈðäù®H#´çΗ#P…SxÒ¨'ñnºBè,p}ŽŸt•Uù椀@ Ã~á ©aX ^( ÃSð²Ñ0ŠÏÁàm;½tŸÈ“}˜ú„†Ùv}é>̹ûB ÓúSxô‰Îï }¢òÔ0'ñ è…Sx؇9ÉÏØ‡9ÇЄCžöaÊSx؇q§ð°CÞ7g}w OöaÜ9 “³>̹ó¥Ðç8‡—AŸ(œÂ»BŸãÜù`”ÄjÔœõaÎû0å9~Æ>̹> ˜°>Ì9<ìÔ§ðÆŒñŸÇ§1Ÿmû®©Ìøã5Ôÿý*os ÏæIìïû F<×þWý÷û^r<_yÇ µµáÞÔ4ÕkÀ¡Í¥µ?¿‘)×áÇSx餡¿þ;kèò£œ4ª/ŸËŸ/á^6âý}œðÞ]¯£Gß™·ðÞ\•^&“~¸¥Œüû9¼ºSxÓr¯¯}õ°±ÆÙ±Uìwûû÷sSžÅ›V?þ¶ õÓíú¼q÷ö\×?Þšsx·C}f ßtßg‡ò0~×~ý;]øû¸‹nÜfö³lžQ}ð8Uþüûï´Í–÷õh,“àpe7¾:wöÊSOÓãT§é•ªsïƒRmšêä §dùÓl–¦†½Yê1;»YŸœ+IÑÿ¯ß>Nj­©–ôøõnG¬[®Üøæ$Îùò§pºòØÝºãÓ4,¦+‡h×À¯—oþä §ŠÒßhE鳟¤|0™JJC£å·pv>>½?÷•“˦æ5xGÓ {勉œgO˜‹·nQo¼èÅ:Ê÷ìñv’lK»ì|kÊÓç3¨†5îI¼;ñйâÎÝ´'òx3Þ'æÌøsÎL*83çÈ“ΙIçmílùÎVºÙÃó眷t=¸IqÞšsx׸óæN;oé*\’7G;oé*\RÁsürΠcÁtëÌD¼AÎL7ÎÌÁ}s§Ý·tëÌìÝ-wÚÝJ·£ùø¤NHã°;í§›×²ËJûoé®õèÏùÀéÊ™Ñþ“4, S}ð÷ýi8]93šS}–†‰àö»Ónºrf$8œñg@£yéî„—>¦0Ž8§^“ Æ'¯|ÕOèHgÌa`rÒcÐÜþpÆíŸoZ`RžLfä†Nç$Å\`ètŽmL¢ž0ðÁÝ h`,vòÊ) ês¢g2:•'¯|…ÑâÉ’Ãàî$`ÃÏsÊÁÀù$ Ó.’'”ŸˆlÂYÇš”Ø‘ ž?o‰ìÃYw:œ^‰ú‡Ÿ£|&†wÂ;‘C±;‡Џòz)B+î©/›MÏjüŽ˜èñû:ž¥âãä\üÞœÃ3r<ë¸x69Äïz<{Ž~Z1"PñgrŒßÕðÓŸÂËaôy¯€¡Ý9¼ÄpT’Dãw%:>wÀ ŠJ° I¢ñ»ˆù³W60Ì9©R朤aƒˆpð }þ“4Ì¡Ïò„ô¨OžðýÕs'ÄňúÜWž‹Š7xò„‰è zÒLHoГÞ`óEïí,žÞ›;…—Bo«<…‹ì^{ƒ{¼ðõm`ÒqàGUùÕ“ÿ÷”ü~ƒ¹ù¢˽¾ÍmYÿøñR?×åÜë!"Œë{ÿ a\ßûÞYŒr°Ï]ðR…êyØ "ŒûÍÇ1,BGä¡zÿ]þnÐ-ÒáÏ¿‚]#|–ŸaLŽ vûI0óV>[•Ï/¿^~¹€Çãk§®ú½=§ØAEÛÆ>×?›ÏÐùF!¿OÂÛûH‡!4o?ü”tæã×?cçÎë¼o¸Ó™?Úîc¶õü PD¸Mßâëü-¾÷G˜(ÙýVþâ¨Áx ÿÌãÃ.ã¥|±dÊ‘+;–z¹rÚ¡1påG¿"±E÷˜¶x«‡­ÒS[cŠêùóOýi1Ç´þ×îs ›<†{Œ_´z~ùÙYÜ—¹O†È×þ _¿Ê²ÈÑ“³_!ÛK§ÿl?D¶,Zž ùš ~ûÈ“±V£xŒÿý~ûö~‘iot¯©ˆ.*v‘ôoþó34cåêñéŸÇé-í‡|˜N:ÚÆµø£NóRú=&Ý)î/6­­­{~/ßžKD‹Ñh?þ Ĥmܬ2«ðë× ‚˜tæøµß3>j¼_ͳ³¾;ˆ}Gäœ ó?£ Ž«Ê{Þ!üó·ïÑ"™v ¯k5oî5Vg£Þ _$S™) ®~ÿ”ÛÙQØ?~¼Tõûñ† ²eÛÍp‘‰µ†‹´ÿýð?<ű}}ia¿»¢uÏÿ5÷_†Èå´C|„~‘!.ë=›Q}¿OaO¯|ý¬Ú«ï!íÝC<ý;A”+[—å¤;ÇDwÏàOwväüÖÅwÜ9¨Ï ^ÄŒC¶Å7Ì"³£úµMýÜ|¾½55ÔZfœB6ŠYñ}l( ¾wvèêNcÖz†ô¬Õé‹——²çl !&Ýù44BZë㮵^ê.ø†vdJQí;Yˆ©“u€øxóUS#a7ó:§YØ¿¯„½-ý³ýƒ$uLCw®Å]åÜ;¦{/íõõ¿ ž¢˜Ü´ÇÇÙM &7­û u§¹MÎããÝÃù¸ë‹_/¿ 9çäòãã(ì³MÄìÃ=ÿq/ÒË’þ˜$Õºò.©½Ä@ˆdr´þù÷îh ®ÚähÙ²f’ÔfIýpã«¥^Rü(m‰d$M—ak½÷v¤MQ?£Œá‹4[O›ú6L›êƒ~—ûïßß;ûÑ"ˆë: ˜—IÏß>ºs ˆÉ²‡YF•3;¾ó÷þCZ+-&ÿâï Ñ««¢Ï¹½¿ ˆ[LR'ˆ_¤ºïïȃX†mMÎ-ïÎÁ‡ûá~Tâ²Lp˜ Æ×l#ÄÛŸ?ECÙ4TâññQ~ÜOñíÍ}–HسiŽDxœ!Ü â盳?ƒg#w>vÒ>å:ƯÚùZ¯Í¯Ð9:PسlK|ëc‰qTcëÛNRëï?ÄžvÞÁŽL Þ…»om÷§óÁ‘÷›Mºsšùñ:‹Y?S£û¾Œ˜eŤ~ÿ.Ar9ªßŸÝ÷}þV~‡õ‹«¦‹¸^sµÏ(:œ¸3ü;}­q8Ho¿}GSÑúqNSšoFÓ~³íÛ/‘\”avÏ䢄.ÚGÜytçÓß ÂŽÂ>@¼unÎ[‹Äì:·7ýsw׆s6íÇOlO MãÆúâc1Ëí«{m¿üD“eÿó8[v7„4£eo;-þñ‚È'ˆî-&ˆNû~";r-Ž)œ•sð\–B Ç|¹¬‡—F0½–0 BrL­¼‹ç„$Ђ`PæÝ„%ÞÑ@ ç§ ˆj Ç}:)X` R¤p¬$¡ ‚–Âik9…³â(˜Âi)q Ç¢{àN…˜ §pZ(])È©…O‘M!Ù<zŠ!†xʹæÙþiq ž–ÌÍm:f‡Éõ/â\ /2î<øþ]bËû)ìçò¿×€ nÚq•“’j+mõ°KªMnÅà+vúRLª­ .»¤ÚäVLrRm‘ ¤Ú'õ©r—T+Ý’T«á)R5©ö^¶ð£&Jªyx‘«æ´¥žæ\AäBšs„ ¾H!|‘BIs® nBš³‡ÐÒœ+Kø€ÒœPñ™‹ðE*¯§9W Js6Â,iΡóaò+ú2»õŠë½‚H—4ç1¦9Gˆ.úîÐ1JsbßdJ0>=Î-£¾ZËm¯~¼"ˆ¥9ÿƒ§("9ÊÎ[¼ç(L‹Ê”6bLáhiN¨/ÆÎ&†¸{I] á½”æ\A$ ÍÙ:Äc GKsBËž¦(Í ý‹4iΪ†W”æ´"×ÓœËÐ!¢@9Jèñ¥7%SZF_d(Í ugvAiNHÎ,AiNÈ™iÎÊAˆTOsVe!2ælK$#™Ä½AÔ’ð+‰;{- ¿‚(P:ËÂàðOgÙÖéé¬Utø ¤|+¯§|W—xÊ·íÌšò]A$ñ”|WFHùŽ’’ò]A¤BÊw€PR¾+ˆLHùöZÊwqR¾ƒ£¤¤|W¹ò!ä”ï ¢R¾„’ò]AÜ„”|W™‡=‘T+‰¤'’j=‘”R‰¤FI$¥l" '’N$¡[\a}‹\OE•J**åz‚l‚ÖOƒÕTT@õ e>J5ó±i–ÒY¥šÎÚ4 «ÉôAÇD’šƒ)̈Arf …ZôMçD’’Â_$‡y9¨i ˜—ƒ‰¤ò’SM$Õz")%IµžHJéD„À‰$Ä(‘T·ð‹‰$Är"©†‰¤%’j˜HJQ"©†‰¤%’j˜HJéD„I&’R:‘„øBJ$9"‘”ê‰$G$’R:‘!„D’#I)H‚§(`:Y7”‹‚’J$’ £INI$¥t" ÑbN$)Y H‹æ¢ƒ‰$x œH‚_'’ 9 )aPÄAªõMº$ Òu/šÎB™IñtVÃh­,é,¤Á§D’–΂ÑL ÓYè‹dLgAˆ+LgAˆ¦³àÁ‰$HN1‘`")Ý&’ŽY ³@é6‘tÌE9˜‹JQ"ÉÃDRŠI5L$¥(‘TÃDRŠI5L$¥(‘ä`")E‰$Ié6‘tÌ9˜J·‰¤c.ÊÁ\TºI$}û¢a¨¤GDé®#)²÷FQÙÓmG’nWB»CºíHCå·¦¬Ð-Ræ¾ NºíHR¢Ü?U«x¨—Ñ9ê4¥›Ž¤)šF)oÁó¡tÛ‘4FC#”ÔkÁë¡tÓ‘4C Z0”n;’´`¨‚Ÿs»†íã½âžƒ¡îUxþ^þx.Ñ=.ª»ÙKY!»ù ¹ê‚ÜÍï­æypC„;î„t‹»Ù´âóŒtÛ‘¤¹›¡…´ÐÝÍþBÕ-TÓ\·Ñ”¾®žs•]hÚ(ϹÒmGÒžŽÓs®ByΕn;’†Àði\sðÝNmµŸ¾úùþ³ãñwê– d­ä^·|\½%¶ü( µné>[éyFºíHb˧¨£ç«1ø”Hz[ÏW.V§rú7áãÃ"ˆ‘;Ãß»—ö±‚èl€A“»ùwïb ïuõŒ n‹‹5ißÅ(.VºëH]¬bt±FÅÅJwI_§ŽíÅÅ 4+Ýu$úb¾ÈÝŒhaºíH:œb²#Z`˜n;’zQÿû8i𑞣ÿð•ŎŘæœùâväׯÏÿÞ_JqLÑ× b$ÅdŠÞß1øø¨,„§ÅÝtã㡲‘ðñãT¿C-†˜‚¡)†X‚!Ûäðì_?¾½"/ ¸›ý»I "ÃîfëTw3#ÝM™énZt ènÊV=#ÝMYygª»i w3SÝMK¸›™ênZÂÝÌTwÓîfƺ›ðsJî¦%ÜÍŒs7[)í²‚€î&ä*ìnB¶îf›ÝM iÜÍVq73ÖÝ„ŠBv7[ÿìtw3Cîf¡»›™înV„»¹Ût ûеfwSöX1p7« ;t7Ûqgr;7–pn²mÝrïÜX¹ɶîæÞ鵄ӛmÜ̓Ók §7Û¸›§×No¶u7÷N¯%œÞlënî^K8½™ænNÀéÍ63 Ë¢j²¸‹Õ.V¶q7§»7yÜ鵄ӛ­ÝÍ£Ók §7[»›§·òÐéÍÖîæ×¯ÿÌ nçG÷®©úºçïç89³ÍȬ^Ö'gv7G„òç{ó=„{ÇÇãt†¹Q¢Gð?ß?j€0±æÓä$½ÿX!üþù;¼x€ ö{ØÆY3³ÍȬécLßsh:é`lýìÞ¾=;t†ëRé òû½ÿ¦÷4½m>?+€0MxïSûÍ€P>[-³íȬŽîv…ðöçÍýþ&wóŸ¯wŽråý[49÷&¦ O3ć[XêÃVïK]v*ó}ô°&ˆ×öü³»)©‰þÅ>‚G ºлl”6|>¿}B(–íFful56ß¼¾ÏŠ»‡xÿ½½Cδóé8³þüù_d™5ô»ßÜ“ó¿ooM əǾˆ›eô£ ñæDè}• AHåÊŽj¹2ÛÌÒ BN‚ȉ‚P#ô„@À!t \*.5A,y=B_Ä‚×#ôA,y=B_Ä‚×#ôGá‚dJ± äõ} BBà‚â*¢ O B%â ¢ äD.刽F­ XS‚¬u“ÒÌ^ÄVÚê–¥Ð)ÖSe© ä V‰R– Jž`aIJT­æ V),K!O2X–‚WX–‚9,KA¾(¤²”×#ôÄM*Ky=B_Y©,åõ}q‘ÊR^ÐW‰T–òz„¾‚0RYÊëú FèPkIºµAÐW0BÇîM.•¥¼¡¯ ©,åõ}!Eè¶Ö#ô•—… B¢)*ˆ‚WÝÍ‚-y€€ Bè¸ ä.•A,èn   »Y€‚P€îf Bº›]‚L)„t7 ¶ ä!.5„[á‚Pɉ Bð£â‚’òK!%þôX ÝÝ €»Y°î&TW²»ÙvR¦»›r7{ÝÝ,tw³j>r7 ÖÝ„_»›PF»)¶»¯ rX–Bb&„t7 T ÐÝ,PA(@w³@¡ÝÍ„t7 T ÐÝ,è‚ÒZrAÈCw³  Bн Bº›*èn¨ ä »Yl Bס¹µ­ #ê_þW+A¤ë‚Ðß}AhD¨ßþøÿ@H–}Qs¶ÙÝÏÞ~ÿ÷!L›oÂãRAø¸#|ü|ý#»8)Wª*„ „*÷\¿¾?×%@¸ cº[ ‚Pz(Íêjþš¨ ” BûžMTZÏMè8j)}¬8ªúãÿÔˆ£Ÿ³œ;»ÏYµ¾5bâÊ¥ü0¸Š3Ä/û§„óRÛ]d€xyÿøå-¼ˆ‰â~‘7û' ®º€–ÍV)‚lÖ§…Ç¿a§¬zÎüùóóåÏwxŠ©eóéヲ´@<»—NF¿!ˆüX–šª|RV)YRJté¶ ôuR™K¶¢ €ùØÌMX©Šï‹ª¨jù1Æõ˪Ô}Ò§ù¹Õ4£¥¯ñ¹êýãû›s©òϽÎhç:£ûQ9±Š0»×Z«Beðë?WÓÒýìÐÅoŸ‚/p˜¦%ÜM×÷{oÐÅûÂ,Õ;ÀUå…~ÀºÓr±y×Zî…¶î{¤Ï¸é¥]€ûsµÁd”6Ø÷ÞýGzѺT¨°é¥è<™+”3†¿–Þ½„tŽìŸ&õ2—¬­mýÑüzÿ²=ì,”êÏJè¹îz)Dn°R?ÇuÛKñ+Û~Ò„ÊÛõcƱÂÇø²Gh«ö[ø&Uþå×?lf£5 Ô@H6tx{_èP¾µß¬X2_ŒŠÐŠm BºW±ã-:µXU®úÏþ÷³EAå•kÑÜaòņ#¼¼þü­$R§UÐ;­:€+è´ z§Õ‚ vZ½ÓjA;­‚Þiµ àN+t ѱz§Õ‚ ¶³½eA»Y‚ÞͲ R·pî„›ÔíœûG=Hí^À»_A\¤~¯ ÷{­ ©ß+èý^+#õ{½ßk‘Â~/HÎLê÷ªõ~¯ÄUê÷ªõ~¯D.õ{½ßk;­ „ØiôN«•¶šS[Ôœšo:­"*³EÍ©ù¦Ó*¢2[Ôœšo:­"*³EÍ©ù¦ÓJU™‚S—o:­"*³EÍ©ù¾Óêü¢À|ßiµW™-jÌwVG•iK¨2s]eŽªÊÌÊ t•™ë*³E-²ù®Óê¨2[Ô"›o;­"*³E-²ù¶ÓJU™<…¤2+UfTfTf®«ÌµÈæûN+EeVœ‚ÊlQsj¾ë´:¦o-Jßæ›nHúÖ¢ôm¾éˆ¤o-Jßæ›nHúÖ¢ôm¾éPÓ·ò-ÊÔÓ·ù®[à/´(_˜ïºéB‹Ò…ù®[à¸T±Å^fqP™ë²m±—YUæþ R™Å6}»O"[”DÎwÝÇ$²EIä|Û-I"[”DηÝjúVV…ž¾mQú6ßu Ó·-Jßæ»ncú¶EéÛ|ß- ¤o+x)}[y=}›ïºb/Uæ T¼¼þ|ˆ¤®ËÛvxħj{¹V|ªÛv¸Òñ'ÅÁ·m³üêÜ\…ø!å:þ:¤~˜Æ½ðCºå‡;½ã¯ê¿føýí dG„yr*⇔ëøSä"=臵Áè¹釔í¿æt€ÖzèmÛã¥v€"±´Ö;@oÛ¯Xh°H?\Ah­w€Þv=^Zhb(æ‡+g/¤¹©—‡Á8:ý*TÍXA$Èr ½°+#NÝÓMç "ü˜þ"š³‚ÈGf„™ÄUðdr*žÌ "\™BveVPOTòGÍuEÑ7=hŠb5…¹®*úShªb!èŠu‹¯ $e1ÐBQ+¨-Ïn!¹—¨a|!vŒ{½cürùò¿h÷zËø ÷Œ×7—Bìwz×ø Bl÷zÛø ÷‹´H@ã¸×Ç„Zñ [73bE°"—Ý£LÍŠ!Z¬ÈeçiF¬ˆVä²s5#VÄ+rÙúš1+‹l͘qÀŠ\(osˆF%ý}Ùì ˆ…£ýY-üXA ¾}œËf[@t‡ÄV)ŠŠ[x‘L‹{ZhaÐ â*ÄÅ]T«Û²Ëvc@$0¾ˆ­ +2̸DVDx4C¨V„{yTIqé X‘J éV‚é_’A+¢?>G†rÀŠh´ÈT+2B³"ŒœêÄÔ‹ö3-µ3\±%ò%ò6í©Ç„I‹&+˜1Q4V¡¦LZ”2YA9“åLVBÒ¤EI“Ìš´œRÚ¤SzЪl<äDˆˆ‡ˆ‡.Û~5 BŒ‡ˆ‡.ÛŽŽX<ä-´!79]v=Z<É)ÆCóŦ«Cë3%õ\…tÖó¾¥|Ú%9Äꇤ ¼¬d÷ IËv;a¤t·^V²‹ÕµÚCƒ $/«§…ª9“m¬«>8àe%ÛX=V~¨—•lcu5÷_Š7üä‹›ýwBLÿ‡ ~‘Èÿ`Ë’ƒÎ:B¿È­4B, N²ÕYï½ú¿˜/ÿ»<èî7z÷¿Æ€YÉç\aÀ4Žä¯­0¤<Ž-Ag…!¹àèýÿfrdzÝG#„Dœѹ߀7P~o„PYƒÊïµâ¡„Ì%>W©8ÓóÅ1¿·,Ù‚Ìï)IQTÔýí÷—o¿ô0¬(e‘¨h›ÇqÀÃ0»W{ZBˆyœ< ³‹Š´ ƒzž_ÞÞ^§A=¾l»¿¶y¶ÿ5aZf:.­|}›Ï0ìo~©ŸC8ŒÚ# »Lÿ<>>õ+@ßíû‡–™vÿõиÿáºE:"ü3"¼¿ {‹K×!8×øçúÒaÜd:®ÞìÉ0Lêm{U>¿üzùÙÚ!öÓ"Ó0o!}›Ò5¶;ÄÛÏ£Ÿöù´ õßÇû*T;!ô«P;)A·(Öm6‡àµ }ÍÛ´²¸oN¶O³î:*6- ~7õOËâd7C4¶éHëÄEÝ ÞÁYxŠdm€Xs€ƒ"Öœ7@÷›ÁˆIˆa3x OQ¨›ÁßËÔÛ¼Öûq~¾0‰ëØ?¿—oÏ]dÜ$m÷}gºÈ¸ú¸|`­~3øk…ä4Iâ›Áˆ~3x YkÚýuÔ7½ÞtvÙ ^9WyxŠTØ ÞÔa'·…™°¼‡øxómƒÉy…FL„¸¨FÌFlåpêÄ£›ÁF1ƒ—SÌ :6b%@ÀF 1ô5 Í•Ì×¼!3èaÄ)¡ ž1ŒX©±ÍôAÕ«@¬=±è7uЭXOŒ~ÝŠõôAÝ­€)¤/â [±ž>¨»i«Å'¨uŸà²2b’gRëžÉeeÄt·žÂ@·‰Y"ºX5t±.[#v$g ]¬ËÚˆÅ.RCÿh†È%rÖÐK›!€‹U·På$ØÅ‚–ð:zHFÌE:…ƒŽÞ ‘ GºÆHŽžƒŽÞ ‘JŽžƒŽÞ ‘!GÏÁS\%G¯†ŽÞ ‘KŽ^ ½¢€î&„¸AwñEú0Y³Ç¨5 U² ›6ÏÎ }¼Íï«”IU†ØlãÀ`Õÿ>õtè 0ø²J|œ·°0ª{ë}`Η V¬óò&®Ü]× 6ì¸.Z»Šüý¾JÅéZû/:{˜v˜8]gߊEÝó˜@S·w€Û¢ò€IåšÊ_ )Ê }ÇËþϼh¢uUxþ^þxöAU“}6²A·0 –ýŽxá’‚€ú³Eg˜tä`;9î%udÓQ£FtX©È‰>îì ©Èa¥!„I7 š†\‚ ‚±XtýØÉg  ;g_‹m4Õ†Òôã&פÈÛh\ѪHx¨#!‚ $-V’›ÁÖG-i±–Ü ¶>j9‹µÜ&?*Z‹í&W%üœ’¦´XSn¢qEUv‚ŽHq1HÓ‰ºr«ê²ЖUGH‹+RUÖ!ˆ<®q-Ö¸—í.Qݵ²ºÛDã­m±Ö>Dã»S¶_—ëšØäÁ"ÛŒÏ:.œ\láÔ@Ø7e﫨–:€°nÊÞ7Q—àúê”÷Ò ‘ç º9eM7.›j€°kÊÞ×P yVMM4ø¨‚4(`d!`Ý´ †l:³MÏ‚[ 3àà!àè¢8¼@b|áuÓ¹ ˆ†×Mç‚ F^7| ‚bxÝø®8 Ç)Å Ãë¦s£Œ/Mg‹¨‰M'¦ 4JH 1ÒðºÝ[Aˆ¡†×Ö Çð8ØH[áhC¼ˆ!¢RU™†6Ž6Ð-p´Î€£ „ FªL¢U¦QUæ€T¦QUæ€T¦¡£ !FªLÃFžG ‚ÀÑú 8Úh -®R¨ Ê4ºÊ €Ê4¬Ê´AÜ`À‚."/%w¾owˆ,kœ!ÐNò Œíj܈+ÉÝ´ªñµÖÄänÚÔèÀ P´!eг/7mL{ב»iMcåuqù@ƒ·öO4¸1t–sT1ö¾?ÎMÅÏñ¯pýò¿Íˆ÷?S¿ýÞý÷?îï•· $k¹ÜÌ¡*TîEL`/FA°î¥¶!6ÐÍ¡kÙ/0xo«÷æñOOó€`;#ûíûsõ!\Õ9mï Ð2ÀrÚ ^b3‹K㑎Žj™.˜ºoY*ßò‚¹¡ã§Zá§Ý40ù[6!ƒü„®êt¶w…™2±ÚM—è'V7H© g¤ò/7‘ zF*ÿr© g¤ò/7‘ zF*gm„µ@´AÏHå_n #ôŒTþå2RAÏHå»çžZ”™Ü=*?2B‹R“û7åNhQn2ÿ²5p`…%'óÍû•ZfhQz2ÿ²2pà†å'óÍû€;´(A™oßÄ}ß1ß>îŠ-úÎc¾{ÛYô ¼Ç|»µ6¶è¸ùvk­æ?¶è 2?èd¾+îE}2ß÷"‹¾ ™ïŠ{‘XÂC~H@0á!?l^G‚¿ææ}p$ñ£6žh‚l, ?$ ¢ðRxÈ °^·»ô1{áu{±?±^·ÅN?Dì…×íEAë+$G ¬¼n/Š}ñÿh/¼n/Š}ñÿh/¼n/ ¤†Õõš~Ø2ˆÙ‹ ë‡Ý$ƒ˜¶º~(¶+Jcçÿ§íOv\×¹°aìVÞ 8Y²Ü 2¨ “ eÀ|e¤rGQ¶lI¶%rña«†­J\9ûm°q >&¹¸ú¦qó‡ÍxB©S^äžìôàæÅ=k›?l÷¬A^4nþ°»gM6bãölÿû·[™šÚ¸½ý ~Ÿö¬à÷9ø~ƒÕçP¹}ý VŸCåö9ô+ø}¶sˆ<>‡ÊísØŽ¦O6ïOÝç Z,¥Ö›{ >uŸ]á‡ö{ö¬à£†¶õý5ؽ¶ŠjØb_z hÓ…sÚÞsÏ ‰ÖŒ]¦_”bß.|Ô`?‡¥gQ.æX7±œJ ÖSXN£l§†å4”ã.—Ó¼Š_ÂNPƒ%¼šƒ%‹t°„Wu(½¿Â¦;°!ñÝa°„My`SÍÊÃ` ¯ö`?‹Ø38ºp«ý ‘÷J+ë6b7“„U8+žÈ%WOdŠÝ|¢¿ÒÚ·Dâ%,ï^Na? «`ûp°Š~+U4ž‡¾øï߯C‡ÝôKøyEå[ÂÏ+°o +¯À^Ñ/aåØÃ+ú%ü¼ÂzñÄ!óö}ÄNí²õÙtk§zÙúŒÁ^kÃ’å "&;xE4]‚ØÏ"™8>Û¾d*UØO"™FØAÉT¿•÷WøW…o‰¥÷J½¿"ñö-á÷]YÅzâðì»o«^QxxE¬Ú º^QxxE<Ù±õQ,Û$:ö<ôxlƒ8ÖÚ·„UÛ,<¼"žlƒ8Î"™8×~ÉTª°f2*°ƒ*¦E<*UL yä®+M<ÚfQz ËÃ+zÚľ%üÚ¦u#›‰cpíûØLêÁ[™ÚFSÛb[ûÂHo_èl>ˆ=+øzðæÞ=x [ Åèoí óܳ‚«}aai_ý¥}anj_ií ÝÍÏ [W³¼| =ØÛb{ûÂè¯í }û°·/Äöö…Ñ_Û¾%\ âlî"½}¡­Aœ­ß^¤·/twwó.±öö˜ó^ª¿Aœ÷R·ÞÖl¾7æïÁë}èö¼]k6﯈¼­Ù|¤åïÁ‹½¿bémÍæ£ {ÞÊÞ-2´/tµ.Àæ³ð5Eî¦hÑ„¦hØÕ-úKS´¦ôlÁQƒ[Øš¢EhŠ–¿} ¸š¢¹8Õ¤¦h.>õ‡¦hžüMÑWzFwï.$-ìzÎH ýdíg[XÈ9w ±¬Pâ1rsÏ ¾¬4û.ÆŽcV~eH/WQðófÛMLå %v/àçÍž¼¼9¯Ü ,=)7¶7™x¹Bá~“‰‡+ ¤Cá^`핞kÜx¥ƒíl¦J‡Ü½€_:Tî¼Ò¡ö,°ô$Øé`㤿wÑÁf" Æ½ÀÚ+Ÿ<×è•vÞ¾˜&Jï ‘·{Wˆ}òÅÎÛ“¤ƒ‹·/&I—|YLË"°ïb9r;³òìT¾›Æ½@d£†Æ­+¬Ç}LÔиu…µÒæÁp—…[WX«]tzjܺÂzÜäÁ©+äžüºBåYÁG·ï"òè [WX½Ž5´>ÍqíÓ[Ÿæ¸öiŽÈ§9®}šcëÓ×Ó5GïoðRƒ÷7øâèö]ÄNjh}šãzìqsPƒý.ãiÔPzWðRC[yVðRƒ÷7x%Eé[Á+)ìôO‹¢ÛÏÁ-)OR¬'K û9FÓ$Eé]!òñyï ±OÖØé)šª7øVðë ¹g_ ݾ‹Ä£7>jH<¼¡pKŠOoà+8$ÅÆ§7ðH¡CRl|z=;$ÅfºÞ y_Õü’{VðEÐí»ðIŠÂ-)6^IQ¸yÃÆ/) 7oبMHíwé]!öÑ“åUmþ )°g¿¤¨=+øâçö]$IѸyÃfÜ<Îêi Ɖ~ ñ?téòCÇüÐ¥ËÿÅ]Î žà‡F.?t<Á\~èØà‡¶{‘ù ¦zKWˆÿâyllYÀçy¬Ütà÷ƒ©Zšõ 6 n%VJ"½×ñÔ(qåYÁ%öý”Ø·‚Ï‚«Zß.|Ö" ê þ(±mÑÔ(qå^ÀK ö»Œ¦F…°gTÈ÷üQ¡Ü³‚Ï‚«oŸ‡[ß.üš»m…xªæŽÝ xs4ó'Å©S5wAGÑÜõœeÎ@î^ÀŸ3P¸ðç xÑ›ÏÕØ~Áfªý”»ðÛO•{ÄÞó üöSã^Ào?yqåÍð,°öæ x¶àÕ›­×89JŒÝ ø£Äæþ%®<+ø£Ä¾ßàûVðë ¹g¿®à;”ض‹ÉQâʽ€?Jl=ÇÉQâʳ‚?Jìû þ(±o/5”g/5”…g”ض‹ÉQâʽ€?Jl½ËÉQbìY!òÆx}¿!öÆ™sÏ ^ÍÑ~—}ÿØNO“£Ä¶]LŽc÷þ(±õ&&G‰±g”Ø÷üQâܳ‚ߎðý¿áû þ(±m…ÉQbì^À%6/ð—(qåYÁ%öý”Ø·‚_RÔžü’Â÷üQbÛ “£Ä•{”Øz—“£Äس‚?Jìû þ(qîYÁ/)|»ðKŠÚ³‚?JlÛÅä(1v/ຼücT(w/à UîüQ!ì^ÀjÜ ø£BžCôf —¶-LŽÉäîü1ó-ü!&ƒÝ øc2¶_09&ƒÝ øc2¶&Çdr÷þ˜ŒíLŽÉäîü1ó-ü!&ƒÝ øc2¶&Çdr÷Œ#‘XóÒË9G9¢ qŸõíÒV§s^ií!#渕ÿ;¬¦¥­eø2ÌûÑÒeòö\æÕ¥˜²Œø5ß_|òSs¡Ë\Þ‡óíYLú51/PþÜí¹°¢µÿ²@9oσ&´Ë,³ÝÑ6½Çn¼3ÎÓìz@?ǃFÆeñkX£þkè"ò×\°É7.³êÍgýlSǦ©×óÏéú3él¸oÏ<Îrš!ù5ÇúÙ^ꦴ õ’ßÂñ§³XæØÜ³GSŸªBm\†Mã£Í”é4¾#:Ó 'góÈ«Cž^ïO]š˜ÉoÔ¢”Jæ3ë$|ºå?Ϻ8ÅmÒÏY:æsTÛcªù=ùétºg·Ë¤+_BÞ3A•~–Bߨ}uz{§BO(›çMZ‡ÓóçN¼S:@¾ÓÓ팮øZNZ'Ñæ=3.OÖ9µ8­®Ùy’¾±‰ B?¤|žýÎç3<ù÷¬{ù.Öaz‚Xg²ž°” ÊÝ:\.óu~Nø6M./…¾Ñìä:x°Îã„Ñuš‰Âõg²Rw_Ùྊ½'ÑOÂù3È!ÖAƒuRœÖÏÓ¤u¤aü%ùWÓÎgià¹àáïj’>–pýùÍåÅéxÉsæO¦z/¥Ã;1â'­Ãõç÷î›ëáˆ0ŽLèá]è8MOøDöÏݯïd¡\ÊwT½Ûóó8i®?¿÷;¾/ÌÕö{ŽäϽºO;ç­"Os®1yú òô‘MZgõ!öõÕí+ãú*ÛWsÎnÏIë,Lîñ{˜{¤qñçxè,s¸GŠÜ鉇.3§—ågÒ¯‰=^–G“OYfé󲔓–IË4•ÏYÓ-#Ü#Íž9$tW9ÓX0>\«"»V“ŽxíóùLÛÔf謡¿F:kè¯ñ:kºe¶>ŸOUO"¿“ *ǽ ÊÉûuW¹++«_'ò9¡ÊiëÄú:"*ÅÖ©ªvÒ1ó™C.oÖ}Úù$ú:ô÷Èur·W¬_ger‹å¸w‹å“ˆy±VÜb±þÄØçë×ÙøÜbÓ×bës‹&³˜Häp‹“xF´ð¹Åð4¾õî,:ÐMº³ŠüE“>øà£ý:qï^ë0±%Öyׯô9i¥Ï-öœv>ÉÐ-ÆØ˜p‹Q6æu‹õë¬|n±jÒ{Öýï9H7Y‰‡?3ò¾òIô öüµã÷Å›ñcvÎ/\Ï|˜´ŽàÏT-ë°÷%Ö¹¸8OÈÂÝGÝGl®eðuNõõ:q_ñB‚|_ü¾ð§ÉÒ8ò¹Å¦Ý{ûÜYÓèP¸Gîµiô'>wÖsÒ{çî—{mš–¯wÖÀL&üÙçÎê×Ù¸Ükìq¯õëlMî,¡î2wÖ4uWºGlîµWþš¶ÎÂçC“ÞÅ2ò¹Å¦½ æqº³Ð4Íyéq¯µÓäw¸Übå$z^®|î¬vÚïY»Ýk-®¦­³ñ¹Å&þž­Ï-6~’ŸèÑ{§EÉ ì1“©f ž²Œ× Äù”eüf`5e—ˆ'˜‰Ï ,&™ÉT3pÒ¯±›Å$30™jN#?¿8éç8Í@<Á LìfàÈ|ËÛi¿'öš““nËdŽÌ7ì1ß»¨˜““ˆp‚8m_.3°™`&“ÍÀi¿ÇoNº÷ fà$:œ`Nba63O5·ˆ§šÉd3pÚ9ÛÍÀb’˜L5ói÷å3q>‰žmf žj&n3O5·ˆ§š‰× ,&™Éd3pÚ:~3pÒ½O0§ý¿8m¿8m—ØL0“If`ã5“©fà4ù>Á œt>ÌÀi¿ÇoN[ÇoN’ÌÀIzÂ3pÚ9ûÍÀi¿ÇoN[ÇoN[ÇoNºw%§Å@Œ~Ÿ§­Ãõ†ê ‡ãépʸþƒhþÒ™˜N·â6isWñʧ­³ÕÖaQ{±Îûú>N[‡„´‰-t8QM-B:ãNñ|w¦™â•Q ½1º»1¢rÐ…^iú:“³ž¶`Ñ_«ç¬•³úç³™JÒÒ&üú/t¢©}Ù5ËOSZŽ~QÇìiåÛ©¥¿M\Häæ}¥Ï­¨ðÔ_´-Ä’lÄBøXÒ…¦þ"Q ðþËU~FY~®îÌÁBœ°‰‡¿¦UñzÞ§nSöþÍ)›¾}–¯ó$œž6 ¬O¯Ó4Îø!~ÑNÑä=*tŸ¸5‘A½ûúoMØì­=Χg{šFÙÂ8ÜS§€Ø3ÄÖÞOìLI,Ä­C~kRkè¶V®y9«EËaõ‘¢6\Î驚Ȯ£¤_ˆ¤(P¥ù8¤õóît×Z‘¬‡¢oíun®§÷Ô[[÷š !lVgÉúLYr™AE9é׬œVPSºsÍ»eÖ#hâ¯Ùxl ‰t³õ™@¾1šèå0]|:ÌbdM©rŠ)µ˜f•iëxM ›_øM –™@Õ¤uœ&PKM iëXL r²é²°™@쥗“M—…Íþž &ÙÂm•“M …Û*'›@ ŲZ.>%h¡˜@VË¥œFÓŠ d0Ê&>VÅ2X.SÑÊg¹L]hí3ʦnÍkM½µ­Ïr™¸µÎR,—r²å²™@£ õ$£l12–K; È`K±_4Á–Zè&ÙrAÓÄÙÐ2[.Somå3Ê& a9,—© m|–ËÔ[ÛúŒ²‰¿H3ƒÃo-¦™@è^M{´š ¤e~h12– š¸µ¥Ï–šz؉Ïr™¨ñ)&Á–šøÖü&‡gÇM ÏQÇN¨œjÅN¨œjÅM rÒ2^ÈóæãI&Pë®;é–ñš@Ó~ךF7^ÈMR‡¸¢7xÒ:‘7šTMZÇš¶Ž? ”OZǪ'­ãM[Ǫ&˜@É„(P5ÁtI&Dª ¦T2! TM1’ Q jŠ ”ü% 4íiLˆM\Èšö8&D&þ"hâ/òG&.´±o ¿¨Q W8i"gôG¦m­3 Á›Âop$jÈNª&eÉ_¢@Ó¸Ú„(Ð4v=! TL[Èšxkþ(ÐÄ­ù£@òG¦ÝÚ„(Ð4%D˜@®àÍ´[&+œ4íÑNˆM;ì Q ‰[óG&.äM¼5È}ØÑÔ(P1e{¨š`uËØ£@Õ¨[Æʧ,ãM:bhÒ2þ(ФeüQ IËø£@žMU“ÖñGð¤uüQ iëø£@õ¤uüQ |Ò:þ(дuìQ <ÍŠœ&Xg‚ 9M ±Î(òEðD(òEðD(ššö4&D¦Ñô„(ÐÄ_äMüEþ(ÐÄ…üQ ‰[óG&.äMÛš0ŒÁ›f’Q¹áØ[›d¹D“£@Ó˜‘+ ÔL2Ê¢ÉQ fÚBþ(ÐÄ[óG&.äM“D¢@oÍš(«ýQ i·6! 4íÑNˆMS‹&D&nÍšxØþ(ÐÄ­ù£@·æ¹omr¨™²Œ= „'™@Þ(ždMŽá)Ëø£@ù”eüQ IËø£@“–ñG&Ñ cc¿D¬²ZMþXËžö™¦Mu(Þæ#ŽÅÿM Z´'j5iÙ)îz¼\ê󫘴N¤®séZ5]˜Ú ¯IëÄê:¨ë£w=6BÍ´uçÙ7Ô$£µ¬GÌ;œ’óÉ‹CþªšëuÒ:‰¾½u¹Îår;NZ‡ñý›Ò2]‡– Šßó.ÛÃ¥¸X:¥ªë¬Å:¢føÂLäX¬S¤ÏtÚ½o„©¹û–¦fNZ˜š)>YL2um¿3}É+Íy…ë­)QšÓèðC±YÏÌDä¶fAéçÞL[hÁÍ=«å·è #»Âø|'ëæ’Cè M!ë5…²À?Ó®lÁÅéûûS[¨ ~Zäù´³æ "¾Ø£§ 1i**ÒG‘Ó+ïñÅ\ÀglŽðEÙª‰[[õ¥ºÊ/º0ùŽ›‰ ­GÝ`2ªßuÝ`êËùõh&ޚ௠ÿEÙW‚¨¦@…ãÔ3⽺¿ aòkƒ¯ÏŸlÚKm"¾ºòóóE¶ɯ?‘-7K[Hö=Ñ¢í/Ÿ·ú5Žºq »a—šó>mEl}µ…ä<…Ž«ñÊzÚ8.=äej«ÕZj aÙz€,t<ÚLim¡¤ŸPfè|úNE=m¡Õ¸Â…MÀÈøÖr”¢¼˜xØku!ú{2¾µüv$$0ñméísAâ|â£$e}ë”M´šæ=‘ɱ †…(AÞÞu>í ˆëÂB­p€TשlD˜@;Ѱý,Œ©Î%SŸêil$ŽG¿HtÇÒID~žxF¢ÈþëËÔÔ§Ép1QŠpˆ«øÊBÔ·sÄø=qk+áÙ™ª®yñ3 ãµ»-Y‘{xöbbwêŸIËx†wy%ÈÂ?¼‹õƒ.ó)Ë,MÀ$‹¥ÀòbÊ2‰¯‘sUOYfåè¼Å'{XÇÂ:¼kÜ︜tÄ_›âû¤_ã7<ÂgHú:x²)µ°˜@š)5mØeJL© š~O1Í´Ñ é÷ÓL»a-Ë´«§­³¶®SL3‡d¨›ˆx²‰8¤C³©‰ÿ²7t[O¶5Gµ@NcsâËˆÌ áÉVë°Èm¶NüEKóBx²ý;ªrÀ·¶r/Ôx-éa-Û®§-´qØäxŠM>ª²ü"<Å&Õ¹lrO3ž´ÌÒ7rÂãiŽ&0,«)ˬ¼ëIG¼¶.SLò{GV“Žxë€áqŸG&Wà þóÈ5¹b䇟tåþÉå´gå`XNºtÿäŠû´óñ0¼O¢ž–àtéÛÖ‰ôЀӅŽ'­¹\èN—~ä ¨®ïzÚ:K»§»=Í‘0»Ð=®ïH 8ýÌÓîkíõO[ÇçA­¬ÔH ¸}ÃÕ4:üðzbëi y³£ðÄ…"¯ß3Ÿ¶PìuéN<#¿uâ£÷;P'nmåõ{NÜš7; OãCþì¨jâ/Úz]qÓrfG5NÇW¤‡Ü®¸i×ßeGÙ½CÍ´…b¯whâ-½®¸‰g”ø\(Å´×oËŽÂ~Ud 8ÝL{ãõ|LüE[¯SgڭɇçcÚ/’ÙQ‡Å´[‹½Æx3qk±×=0qkK¯U?qk‰×ªŸFG<;ÊiúNc#Þì(\»ÑDÓÿà)Ëx³£ð¤eb¯ÍZMYféµ'ýšÄkÞM:â•׺˧,³öe“6µñÚRÅ”e¶bÈÔž¹»œOL‰¡Ý PZ>Èå§²6ùÿÿ­†Ô¶ã…È”L•°¯šGŽ]ªúè+N\ͧøêLÙSÆ¿ªÑ#»–—ƒá+®ø5»½øŠ¨¡™Àªë4-ké¬}ÅkÛ‰L¥_‰ÌŠ·ÉWª¾iz4ýBnX¾¿˜¼" 4ÃŒe¥ÅíM4Ÿ\Š™ÿÃÎs=8†ÜûŠÎûæMzÍn‡ws?_ _‰¤™_^ƒÍTµŒõØ©ÒÇóú"GhúJ˜vœ]œŽþ~Ö)Æi‰‹ËÛô•Ðy9ÖñÌ”y9Ê0}ÜÓc•¾œ­\¥§AÎ#GÕýôÌÉÁ _­Æœˆ%µ> iÚÇ9žL¿PeƒY_6ÕžÛó5—)D£¯6ʾÈñe|ô$!Üìþ|÷Å3¿ø-Ÿ2|aJ Í{z=_ ¾Ô’ÉѯâÑ-ÿ2˜~E©—^3ý*ÇEq¯qnøÊrËe]n9Ý²Ž…-X›Ñ/T÷…-ûÚx~!6þÂMÿ ß¿Ÿ{nŽ0ñ¾ T¦mÛ tÜרŸÿ ïÁArÏ •·û]ö}ñ¯¾äW˜A±¯²¬d-8 _ñ3l~•¯h§ë4+ïª6}µT°xe#ÇzÜN•‚5™l8Òr±ó4JËiÄÎÓ(-§;OYN#vžFi9µó4Pe:Q—#mT†Ó7õ1Ý26ìkÜÃÇDQ•á G-{Œ´QN#ñœF‰Í§á£ l<ØyôšN#vžÅ2†6°ñ4<ês÷»ûbšá‘6 ˆ‘’•䟆ÈiþÕÿëÿε–‘ÎA¾l¸úudãosîlkÛ¶jÓêbù2â_ 3äÈ4.>p’`iq–ª’ö%Ócw_¤:Ò·9˜UZQTË—K9”t/†È²úq1D¶ÈËò~¶|ÉÝJ;©‘Ù½x ´Úªö¥PP÷Rëfšˆ ñ´uÙ^o–/e8†:¦#T¹Ìæ£j©ÿ±íƧ?^_–/·>R6³Ñ)gÓ Ò»œ1ÊD'/”>È6o7©~êŸ:4ׂzÍ퟊ây¦¸ŸNGn“OQ™§‡çቶã]ˆ¨tó+?½ >Íó¬¨Kñƒ?ù¾týSQZ=êÊÛ§Üîùä/æx’/¦Í«ëõÐâ6ÅwÛ§ÜqóÉú)2üSBùïCeût-´ü½IË?=®ee½WNLßÍÿ”ö“‘{EDçI‘d)ú§[m‘V¶cŠ>T#ëH¢®ÛÕwÛ1‰<ãf·3Ù&m[ÖgÛ+çîC‡R­?8^~öƒi&è§M]gE–¢Û§K§©r ¦Šr¯ª‘³_R¶Í,òå‰9‡KUX¾Œt»¹cK9yêøÒX¾Œ9æ÷§øµÜ&`˜ÏÛípiŸWË—ËÞä³·™ÉÏ Ûö™Œ÷™‰aÛ3½êwÃÕ¾sÃwÝÜðl0Çüp«n¶|¹V¼äh˜gÚ<Ðù–[¾tÎR.ŠæúJ-_nÕ/±üµäËGš6í>9û݉ðÙ‘Î¥aÁ”(®ïôBŽÊöéB5°‘¤"b`¿ b_ÿØ>œ¶ù¡ÊÖO¥;JtN4,ž÷ŸcßóUÿT’ì¥u$Ù/±Òo§×%¿Û.•³_‹ÿ¸^ó·•E±ÈÎТ§¾½NuYKW®þéÚ0½¾£Âìzè IõOE¢šÐÍÎR7㞩Ơ›õŸn5E‰=¡(áÇíçaãüÓ±ââ£Á.yz²}ºP_쵸?o—·íS94þ·û”‡\ø§Sy³S$¼ÚT¬r¯öEªv§âVÄjÿéR÷ýå}ŸËµ¹µ¶OEþξ›NÏ-¡Ü=®ùÅFˆÑ€š“À&‘5ïÊzLk! Ô%ÄÂÊõenæ”ó ?gÁ?'|Ëm4ÌË.v»¦s®sæ¾ÍÌ ôC$í~v¨¢g#CÍN”ÇØ>]¨®µ,ã¾oêZ{àâr9Û>¤œ ýy°×Ç £«šx-¢£} MK LÓÊÞ÷[†­Òq©øçsÏqÿ\ö¤î9Û½Š8ˆÕ˜ÿX™©ˆ|ؼ‚o¢-ÙH‚Ç:vX¾LÄ>æù‚eô+/ß§?KË—^åû]Y¾\ûLUbÄŠòmWÛ_¶ûô*ß••>\ÿë.†&ú2?ÒßL¬p2 ?*u~4ˆO¸géàžñ”|Â’T§›’Ãà®s²ØÉÉJ'‹œ¬tp²x˜èàGÈv¶ÔùQ<‘“Ù)áÃÌŽJ;RÆ0ªì¨t°£Xád&&h៱…“)ìáÊvJ'S˜ Q8¬Ç”8rv,ì(s2c⎅ ÆS9™NKk''+œl=‰“™iíäd¥ƒ“­'r2U‰OsjV•åK 'ã9N&N6Ê=²fG™t2%ÿÈ1Uådã)a–‘§FN6 fËÊ2r²Ñ,0·NVX¾ôëdØò¥_'³R‚U'Þ’üùt²Ê“Q…®Q'«,L0QŠr]:™u¯~ÌúƒG¾‘%Jµ­9éÎÈûOý:™öéÚ£“UN–Läd¦ó]{t²ÊÂÉ“Y5+íËx¢u©¿6N†íœ,žÀÉL:YâÕɰ•“ùt2låd> [9ÙdÌvB¯fe»•­W›kl”`Õɰ•yu2leG^¬²òÏé:™u¯~̺×Ä‘õjaG^¬²2Áé:™vLN†­œl3U'+,_Æ®_3'Û +NŒy–çG4Ïòÿü¯ýßÿóÿ×ÿþ?ÿ[ý—üïÿû¿Å‹ÿÊ‹ %?¸¾¥×âçÇþqdÍŽ«ëúVÜRbY?Žé¬ežžö—¾\XTÚ?N<·§§ýãÕ0b|9¡>…±¬ßÊÎùÙþñÚ—ˆ‹ol·ôã’|Œí»S€ÉÇ®{–YÀz¢i›’_Ý^Ë·Z$ïßßâÈx²yNeYgÔ¦çÆñudKü$ØõóZÖÎ_.§5òºÎ<—’a×7(_‹§õkHuÅ„T®W"<í_'ŽDYúõéîúz%²V?yÖê…7:!¿<­Ï5Fèyº;¾­‹÷zÎ+a)—"½Os¡’šH(b,%/Ñ«:¸XÊvœ3žÑ” š”A¾~ÕÇÛéDÌ.;OùPO­§TbEßžÅÅA-‘#éüð §6f†ÿVÿý£ßÿ[ü÷ÏÆûe\¿Òcq¹¸3EZS ™".ê´HSäù^Ƙ=Ý x™cÚºð2ÈGæ^`åãsõݽÀÚÇeßž¼ÌòîYÀË0}t°ø°=Ê4oåµ,Ξ4ÆÉ³Î8ã,O ã4­Ù*z)ó< +ðíB2н‰¾ž)í+á^ÁÇDoïƒg#Ͱo…•‡^r µcǘO;eìÕ”3”¾“tÔï-˜×»W4)î‚(\œs«ÑëÙ\<ç 3WÜ•}šÌ^ÏKåYÁYÕƒÑmÌ`·ÿ-É÷ÑS˜+J>ßí;ë¬Å°~ìeª¯£ýc+CméÇ-ùøjÿØÂLÉš€¼òqâÛËþñÚÉÛ#NgýØÂ@éÏæüïð¶ìež®ãÔôEÆü³ãSa{ê× ³®JxžDal» Ó€ÝìëɃmÑ6Ù/¯[òñH¿W¿^š5]öË »-ë‘‚¯~ذÉ/¯Ó2ÅίW&ÝŠ†ö¯Úf+[@Ø¿ÞØ©åBXÊQÑÙ¶ÿý£ßÿ‹ì:ÛЈMÓ”æ‚9¬eo`-—úTœRtq/àe/·«{/‹¹Ý xÙŒïxYÍѳ€—ÝŒŒ%Ã^–“î¼lÇ·€Îz¤„¥ÏÿùR5.Ã Û ”ye× +Xz·p–®åï9Xt6ΠʆL+,m+PFF^Tí{QRgS5OÎÌYf¬€Vð±$Zgê^ÁÇ–há§{…ç]·Ùi°Ââ㿘,ÕÇ£y©Ô¯#ß{º×ޝcßc¹MÔ¯—.*nU¬~¸¨çúH#}]ýÚwï·ÜõµïÎ#M_ýÚ{ßÏ¡Sòùüýþ_¬È"Çoà Þ{?cÏ Þ»[}†–.,KU.fX!q©BÇ,}ã·gÇòİ‚ndzg/=Œns±øoͨ)šB ÔÅýt|y$º;vzPÊìüóv|½ô¹OFN8õëÄŒÍ|~ì•z[é$ÇŽ¯×6g3•à­*ÁÕ¯76w1•œDäüàÇ×[§#«.jùð8)Ç‹ëó…VK4¢vbÔ¯µO¥×ìáYÁK³Þßà¥ÛKáYÁK»Õg/ýzƒ—†ÇÚa…µÍ÷Géøˆ4¬¯°±yî(-Ÿ^i…+Ï >z~Ü>ŠòÑtvômcá£ÊvdÙ6d%‘ë.š.{ßÍÑñud£ÆVPn_ÇN*h7ˆúõÒåý}8ÙèëÄå·E(½ã»ãë•ïÌ/õÚè÷ÿ–T‚N;÷±=jXÁ{ö÷Ï ÞóÏ Ï KWèòv2½Be…Ä€,U·Œi…•“§Ã|Ä•1‹ˆ%ÓtÖóu䣃9¾Ž=¿\±”¯—Îûo³sQ;¾Nœ:0R­'åk/ÿë?Ê×k—áªònõëËz?Ó ¾8¾Þú¨åyÑ[,\üÉD- °‚—jÊÖ³‚—rRß ^ê9`Ï ^ :ûVðR‘¢‰è+¬]îèTóGVظÜÂOU£5­°urr¤ÊߘI’ ¡Ê5t©VDrqãø:òa+r(ÜsCw1 ÿþãYAô4ìîœy:Øé–“ÕŠ´*ä̈ÿG×ù9b%Nÿïÿëfüÿýïö¿ÿû f&M^X~êç/Q–X§: €7O맸ÎÛ(’@û(Ç=P› š:²–+—Lv¥´¨ÅP7Жæúýœ.´ ½åÓɯk] †'J Z;.ò¦Ã¿¿öˆ…$PåhrKSψ7b#äý“ýÔ#DÞ›a£ÃÓ‘)Ò‘r>Û‚°;„Ó¬Bý˜hãÖŸ#km€ø ®¦ÆW\•Höc FMhÓÕŸƒlºÊ÷T¤¨(P…”ôŒH¾&Jäò5•Ýü¶`$Ù7t·“ω¥7‹çDÛŽBÑÞºGb!®Ež–¸¹¥ Øž6¢}0çEŠgÙpÚ{ ‚º'^¾ôÙ0øÃúž1Å 5õëu©oe tzbœãF„‘ŸORE7ørż¥OÞTí‰G±ùžPuEW $ÑÒOˆÛ®ÍÙeOò¨€dï({,2$Ö#T ŠŠE‚G9Èö$ä ÙÎ(Úãý¿v»_Á#DÇjÊ#žÙíÍ µ§•¹¸¨¹S ¤õ°². Ël./_°d‘q|ŠÜ(+¡€"³Ä•rp¾¡ÅÖ>íUYú€Z Cf×2rj5dÚ¢À3éŽ;«Ôª"1~;UOöw¤² U•lÎŒYé—EÙd¨)€âžð¸XQ¤-n«ª ö$¸¢ëµ H‰DÚ›hœŠv(ŠÚʧQ[![*¡Ö=’A[¹¾òŠ"¤¶²3i+Oò J¨{ÚÚù8‘í|É®¿Ü±©ßžIЧË6UR&QUaPãèøˆItö`Y4¨ÊCŸî8’n6Ó“0Ó4¤XgGÔ= ‘Ž)†B²0 zO-Q æËA iÀ$øLŽÄœ8%èé9˜DY@<Ýq–€™I´‚2 F& GïéÖêžL‚ˆ Ô<Ÿêå~ôc^¤KTX¹tSÌ?5j¡¥ÐqŸè÷l{sÚ>9À'ª! œ¢›1,f;E5$ã¨̹yWTCZö“S nѹ&(¤¤,˜“\ ]‰© …ävŒæóÕe i­9,;-–°#ÚŠÊ7V±A=– zVP§·µšO ‰ðØêå~˜•Ka|VÏS Æ$vaˆÊ’p¾{  §%!ô”6´FœM`Z–YàöÙ ð}ˆ!Sb°•ðZEŒP<Ø®–vg"!õŸ•ؽ‰Dôø-u¨•ª dïñx/Áp-¼|;£?‘Ú¡P/XÌÌÂv€[§G±œ„Ò¥¯˜Mò¹ï\ŠL€H—â_¡v%g™ |Š,Â! ŽMQ7PPÑp⠃ȠêâØ¡ b‡H§öÙˆc¨¥ÍBMì Û#æ%ª#‰ €1 Íw+jH‘C„  Á¨"Åv÷¹(ÈÓ[:=‹!ÏWEJì^Yj÷†ï)åsšÍ)œ"¢a'“Ý ¸'—¸,7ŸcóùóÄXB FŒ¶0KØUòn…ILíR?ýH*’ðî|éÎf\ HÒ»³ß™œÍLú!Iû;4p‡”>›Éáôî¨HÜ»óŪt º`Ô9f󶮊êž„áöµ×´YF·ù>In_ŸF¤ïŽŠÄ ·¯½p„ Œ§é°Ó{䧺CY-_l´¿(Öu_Ô«­Qµè½c’Kˆm@ï˜Ù™læC× bÁe?;.‹ÅèOÊe2ye…ZŒ¹ì—Ë¢¼Íó~>B2Mvκ› qù©HüôŸH|‚ϼ,pÞÜ $Îe÷_šs±Hq•VMÑB!%Iu. ¤¶€Bâ6ïWwOƒ”KÔ;¾©¡îI&îw&—ßñq¾A!mt7&¥éÆ<\($ÑÕXØk̹˜÷{ÊÅ£…z¹"wðKO‡¤¢òA-ì9,HàÓ ñxê_<¦Ø®vO›¨ Þ”tñÌ .æ±PÇPª6¡»ÕèÊÔ „BFý‹Ì•yéŒìšW×¶‡Ð ÖfW&½+bÆãv~pEƒÃPYÑ<«”k/i]À‰DÞkÇ¥T*J¤ª Ü€ÉÞ¸kÇÔ¿t þ1¨ã­Æe u€‘àïo]§%Äþl‹L§¦[ǘx‡ ʠРbIìýùIè"‡ÛÕRêÏ|W´ï0»jñµÌ1Ü]%æÎ¯äiÁA Ì7±+$y`‹Kªc€»n¿á^^,6*Ž ¸µíïÊ`ë@BÅ"瘻D¨ßžëÜoŸ5ù ”H:æw% pu†»+6úùóKÛ *Ëz¨c~#ö8Öc,·I2¾\V¡àœ# iÕÇ'î5 Ö4jOk‡†‚W¨HW_Ò¾úÒ¶/àÖõ°| ýå~XkÅ)ñÑšP0&±°ºZ)?biAPP‘!ω7Ó!¤W富б«g{ƒ_ÇìEöÖîýmHªjZr[-TâÔeÛ01iCÞmbª…`±ALñzç¬Óe1ˆ˜Š bJ uƒˆ©Ø ¦x QT‹³@#„˜Š bê0è ´1È{J´Ž&¸×0!„G¬Š©/­£ Eˆ±ALéuÁ%€˜Š§ˆ)ÚQb¶G^CÚª²ch @ˆ©Ø$¦ ¦€˜Š'‰©j ¦ô‚®@LÅ1…û2µæ‘Ÿ*°»2ˆ©¼‡* a”PP.1Eóæ—>iP+×T%ÒKQ ·[(.ä(Æ”æW$iH‘ÃiæžP‘bW/Ôiéê8ˆÛ–W÷ V²)RÚ–™›¾AÜ“Ú^Îò PX_¢¶—ûÚ±>Æz;¢ ÕMØô-Q›¾}éÃÚ°ˆŠŠi*’P0é4ˆ¦oɤ¦oLJA!-]­ØPˆ:¡"%j-?îÔ êÓoÅ–¨Éš6Áî  ÁWbhúf@hú–Œ›¾±¶âôX4~z¯6î– S , jAOÏ–¿-ˆ/°6| µàüèËÀrn³׆_ÛøQ Ñ-Q仡v–Þ@7§ñPíÝ×ï =ÎD'²»ºíí0Àý¹—ÞÒ¯Óù,mÚ´l<¬›7b“H²c ŸÓB!Élá>{U¨)+0ŠXkᘶïBª¡"×h/ØŒû>XJ¿"¥Ò¼€ã}¼=aIß;½­L®[(äÓ}°§àP§#0NÑ Xí ,‰a:“Ê:ŽˆA… >Ò 6ÖæT”,²<¸»W%ZÖîv†>XtSp»’u¯¦ImXTYƒâÜâ«Ùõº³ìÛØ6([¦AEšJ‹{v Ñ«‡Šm  9Uµ´OÄjÂS”¨çµA¼9UïŠ+/¸*Áîj%½~;“×ïI8.˜ª¹Ö}™ƒ8yÄ`šE´Q[nq¿3‡:•õ î ‹Y#ïï}ßH¬óЖ—C &…e{4sË„¦œ?W‡Z¸ òC»N¡"=å Ÿ•äÌŒ nS묌 D€Èì65W£'Ydp›R£ô·ŸŒc,R:i.Ÿd4J•(¬U!ѽÈ`”R½l'MÅ É=•Ùgõì)‘É(¥¥C{aÀõ r –X_@ÞR"íz$!~Òü€‘Á(5Ä{Ù=…Å{#ƒQ* Õ™IÔ¿As‘Ù(58Ò ‡J¬‰ F©ejh` Od2J‡ÖÇÐ$xÿàìž² ïÎõ|SÎ5P3ƒ·Ki¢¬RÚÔêüdÏîß½©áo•>æ{_"³QjšðJ¡²´‚ƒZöÖÇapWü3r‚pP‰C£ ‹cG&£Th´<ÝŠ3ZžnÕþ4m ¶«µžÙ…»VUˆš™ŒÒ±ò<Ê캥Løn{–ïJj´tW¯ö§#‹èCj´¦~µ%þ£ÀháÔhCÔÌÈd”Ú5Ú2L%3¥_ߌ—35?XzCM€îu@瀋ÿVžÎ¤ù 3éüþ\*Pä¬èÏ¥úL‰®%yßÏj~W™ ú7Ñg¼¤…]’Š™ú+æƒþŠç;R,J­»’{Ù¼wCm@b×i)zmÊþY}A*뵉Êë )15ÌM#ïP÷´²öÐ}WçvdÑ,=YºŽµ³‹_5¤›C¤³ûÝiH[k-ëÜ6¿}…þr1_¡£#Q;L+ãZBéPŽ®]lçl~ý·ff|ìì1Í(!|-çj Ž«kW ¸ŸØ3Âsö)8KG—«¼ èr%q–ö®:˜ßÝHÁôWÌÏ †–£ûéâÉç¾Ëa mQÔgé¦7°sK]¡PˆÃMÁYê£ÎÊùW,pÜ®J.!B²! ?.Ñùü@Á‰=ÑÙÍÑŠñQ©1;“j@E@¾4ljþKÆEÏƒŠ¼|P‘÷“_rœÈMoóå·‚[óG3zëpd‘ý¾¯™Ì5“¨lApÝY*[ê Ì~Vî÷3Ÿ¿)8kOµÕìnÙ ÎÆÚÛže–ÏçoËIüë¥aÝ'ó·2D+]Nåo”_u%4ò7c_é" –ãÄþ&Cøù ”k>Sp"7½Íço Nìꊂº®Žpü­ ¾äƒb»ÙüMÁqñ·ð~Vî÷3¿{’‚³ö”étùálì}ÌË"ÄþIýúó—Íoص6Tc0»ä§¿^÷¸wæ i #œ¥£Ÿ}"Aº=g¢ƒùr[Á‰ýìQßQpbSÙ®Ë/±çš gé¦7°sK\5ZmP3µµÚ…ÙÒÔ3'üz¾xýŸVX>nê‰e§À…tZQp䌪_ãŒ*Ü–suœØšd¡ ä ÎÒ0B»ŸQõÈ  ûqϨÊçÏDSpVöæ¡tÎôü™h ÎÚ<;JúÓlîèqgÓwÍg± ÄijØ-µ˜= ^ÁÙš1³Ù:Aƒ˜ÕwúaíJ':Uíì.Ù*ÐÂ<щßí`€€€"ÃLÐÁ ÎlG±s¢S€ÏWZê“3óÁäÌæµ£Ä<щŞ^-y°PwäjRJ¶Gu®æßmH9¼ ´§(]¹óÜ0´…qí|~Wn'²ö ¹Bðå8„ÛðܧçÍ-mJ £[º•Ÿ´½íÈ1SƒpÓ€Zhe˜(Ÿ&Êß® ÐÚ­eÍŸ  m<Ãе¬hëÖ².ÐŽ¢^ËâïˆkYìhY=ÐBë9ß7·G´¬ˆ§F‘[{G‘Ã-×¹IT Ã,ïN]À!q”õZÇyu,@&ü$AýÃ,ïn˜ åóã\ Žæ'É: ¢ ê à,­þLV 1߬àØ;ÍgmP!¸‚³ê%Ña ž²ºÎ²†ÛϺ/ÀU'xz ¨Up6†¤ô¼OJŸ?;^ÁÙz€fY óN?ìŽà°Ähábq( ò ‰YÞÌRóªú98×®®MP¢öËïçUá~ NH‚¹YöüЂ[[È\!X¶RA×ì¤GAX’ìܲ¼&Z>̹%nÑ0?$­à¬¬}Y¯-œÛZO‰¤ ÔÃ(8×ÀQ¦ÔüŸ­[ÔÍA©ïôÃ5‹:\Ö©5s»¯n—¬í¡7tºþd†²eÅÜ—qWHÁ— »Å7ÜÙ›2daÃU ÄTÀ– ØŽ/ •[SHË0ÍT«“³Ö^ V¥JNÏ‰é ’gçĨ@[sRŒ¬PŸŸ£JVòFÞÑÂS´`ßÅz˳²Pà0uni²ï Ã-‰²ÐÿRÁ‰ìB‚ö ±W—º}g™¶2¤QÁ1xæº<¹6Š/ öi¢aÔ¹QÁ1¼òAC± äÒ`ßYÚC¢´Tí;j<ì:ãAÔ73ãÈ×"ˆeØí—)¬vé ©àxøA‡[ª]jÍ.³°Y† N—7»3æÍίÔVpC÷Ä|Ð=qveŸ‚³ró·ãn©v§µ¡ éí«àˆ÷ái*ðãJ4nœíp4™¦4\Sß釛a‡ÄÕ–ZWZ[(€c'ʰ[¥i>hAÚ" ØZË{ÒB½¡ÅÒ-„Bb6c ûúŠ‚².Æ@+mf”© ‰:óQ‹¤`™ÎĶÓÄÇ_ã¬í¤3&ê¼G›“éÚ·t~p:Q§=2[¨·‹»r®²J7M ³û¾’Ãä²'ѳK˜ss”„¥Ÿ+8k×LÄ6HKÔ)4Ò>ðÍvÙ79‹×Ñõr¤ÆÙßiˆtáDÖ)°WˆwºT† Ê!ï4$ý\ÁYºùíÜ‚“Øù› öŒpVþRZfG@]gíæ;!Yr#û”TJo£”œ­ÉÐM‡£·a˜ËÄàBì 1ÐÂ9=>È7Ь _lJÑ|Ë;þocêha¬€ i¶©à8;Z O‚»2g )ÌÖáœåбRZY¤ÂqÔ vÌW~œÈQY@jûXÔußDÔ9ÎÒMoó-o'ñÌŠ蘰Q+Ø­•p!©ç‰ÀñN¨"&CXe߯R©u´»„ÚO왃P¡¶1TD~š¬v•Øü€ãÄ~0¤ƒù9k ޳"2œâ)ü <·¥›ÞæóQÇåC 7[þ(8Ò…ðk*¨hzÈmþ‹M‘JÚ—§!i# ŽÌôkôB‡¢ÄüMÁ‰ÍzxEdÈ„giëDE›.‡˜Ü NâèДý à¬ì9çäÂígmµAé- ÓOÁÙ¦ôaõ€L?gëž¡zÅ׿~¸’™ ΓéP?¨ ˆ×$)x9NŒƒXÂ8ÓÏÎJSÆJµ!nzgþ,l>úFÏô£Lû ¼<“ÁGt@:·¥›eÏWE6z¦Ÿ¥ˆ=l2úFÏôëšÜðÌ8ºNo!3Ä7¦L?«h˜ï¬Øè™~æṳ̀›Ÿô°1fúõéjÜ‹ÍÏ-dzøÆéçA`g Ö‰—€·1dú)„òÁTšÛµ*a€b·¸›Ÿ®¶1eú9†ßÌnA½1eúé†C?|³Æ0@+·`…£ºµ«9fHëó!ÓOxƒ¬‘¢-ç3cøñWÏAAYd›?„Ãl![øÑä a¨¶ð£!)! ü¸1‡?ºv@NÂæáÇßïfjø‘ú²ƒ)üÈmH¢À¦ÑA¢†-ï´L‹NäÈî šc¬àĦ©êù`ªzSà,Ýü D¡OÔ,2[·Â !² ÎJ͆*XWª2Âìgíæ;óÃ ÎÆnã—Aã4œ­CEŠ5¨ïôÃÍàæT …gŒz€íhYdÝÒ|°žëÿ¶´wÿRqh;Ðäƒ4³G¨H¢rð÷·¯äª)M^|¸DO ¤Øqzy yzKS|ØE£BJDjn3¨OëN/ q i%F¾4Æ‘/Y7ÒÚÔ$´© ¤©¿N>è¯3{h‰Š´µ¶œeæ·ÔÖ_î‡5½#+ƒÒ;t¨…¡-Í`àÂ|ѤCÙ{Qga³t¨Ø•p’M¢C-Ý }¾Í'¡”ž­J¯Á|Øk0BŠÜ,)`–Š»YÒü„] iiê ˜;(BÝSb­÷ã½AÛP–4êÞªtUÍ]UÃYR‡´6ÏQêúi³‰iãæÐT¤­§àü1JÚËýpë-L"áP£ÁæE“ÅCd¼Š™[.‹!^!BJEŠí$ÖNHCZº¥aÐP¼1Râœ(ØÍð#­ÜÀb—Ús0‰€Ó[šiÏFó“4$×` 5»1²†´Ôû¯ô£{®‡ìT]g³£Å…¢½¿G¹Nv”ZUÌO#ס"½ÛK>èö2¿&]‡Š >òA£Ù¡j©¿)U·lxf*«@%Ö‰¼MJ9·ìL‡ZÙÇ2¶A…g:ÔÚš5Æz‹ÌÏÓ¡6®i‰b^ÚºßÕür­j”Nê À 5IŠÜïj~F[Çce@Ä>Ê+U;íåƒN{áÄ©îlÃhÐ2hˆŒµr¿«ùÙ¿:”«•vPojc%v6P:€Øc¥•mXî*ÀôÕ ";cjÛ 1®”a¬ô€1…°ÛÍ‹…I·ø2¹!é:Tdj:‘šN” *6¤0uÎô 9ÂÔRb=`·Éu¨Äü®J.DB“µ²;EƒéPkk¤,l6˜µ±²°¢jkí¹Ä’ÎTNý ¸|0”.‘7Þ`>Ô±"7 ŽKqÖZ_ñüAD:Td}ÅT:BÜ–2fKëÑ'ù· ji6Fºúˆùú™åÒÏ`ž–ê±µ½¬õBƒr'í„Ä@4¨[:Îï&MUÁÅ»GЬ Ð„Ù£p¼W[åôp†Æ¨¥[Ž„Ž “Ýc±¢p ÔÊÍÈb) &Ya¨AEn²€„ò•wÏÃÔR—ƒ`H ±G<:;6FFýLòA?“"o  ¤þ»Ù‰HS Ou e/í]MÁ ”½Ú›5 s]Œ¡œžm ?a µrS`Œ¸hLÆòÊBa.Á1Tdï‘‘…6Nº1FzÂ2‰(† ü1Tâð£<je% J!d‘¨Q£ Ç]Äÿ4¨ÈQè  CÅ®'&ÚmÌÍÆÍHˆŒ³ÒóAVzˆ‘?†² ¦Ý$XëP±ÃuцúéÆPÎ'\ÚWc¨ÄYêhôŒ¡Vn lQ0ú…'‹ùu8:Td¤-J‹š *¶["@d1Mˆ | Ê×§"ÈŸO"Ìè !‹D@™„ˆé®Pƒr ‘2`à%(°Kî ÇO)1¦`<„úøïßBmöõù»cÞï“ð~cVRà×åì'P$v=P–÷@y ÷y×w´x¶hBåF’!‚ݾo¯Öí‰öÌCÚ²P •s¡NG·Ö@Hч(È {b5b‹4›¦ÆW\Jª/ÜHe‹¡ö$†:7ߢLB u¦§W¤tòv…÷|O¾\Ѿܲ,J(¤e??Z–Gg²û/¦Í͈’á¤jÞ¼tðrY ÒJm1ÀK—9•óIÈ@Hkç=¡²B@Ü(âjÄŽèþIÔèP¤göS–%’hÖì÷}×°D˜ÎL£š("þ0Œ3£Ù÷eA/ ÃÆ sƒ±'T]ÑI𡱰ÕbO”½> £ÒâX›ÁMSâ±@:7Š—ýnÎ÷Ô#Èvn4† …$]…hr!ŒÎ–ß™H Ö†áéÁ/ÙIKf„š W0@‘¨jªH:} á©ê Q"ª‚„(M@èVÝQb/D•"›* ;uÚ×$9¹¹¼UZ÷@a{}åèè6æüèèŒèè¶¼[ µ×S1Ó*ãm AP/Q1ˆvddñßT™a|„3Ì•*ï ûõµç;BŒÄŽŠòVà¼9Ån ¦º0@üÁîi+Cú`¥—ˆ>Xj›5E ”H }DöÓµÐJ¨]ûÎ-À¨Ž¹: ||œ_@T'õ»/Å+À‡K D ­³¿0 KLô­¿uk($é%bUÃ?¼1Cª¨—(;V i©ù£ÄžÒ±®*(ŠH„ѹëŒN¦ £“Xs5–ñÿ"æòޤg³äòb®«!E¦)‰¸Ÿ’˜Ï•RlCb|ïo ’ÝHK÷žOOHfot~ÑæéP{Zõm z«wHélOöñÚl¼àü¨ †´é¥ûaà‰à@[êôF]ûÇÚ2¡ˆvB½ÜM‘Bµ7@¨…З÷º¾\>òS]ÁAERaÞË«ÂHk%!Áº#ŠnÔöç®ã}Y?Gô®–:R‰ïª­s8™ FZ§PU1×G¥C­lÈíí/Î=PkÛ»bPkªî}ü¿Lß ÕMH‘} ˜ìÎ:)£ i |9SçHœ©CˆÄÈ |ûnä¸ëF.#ƒð5!…+Ñ$á[2…iÕ#)‰2¬ÇúévzNá‹X…ÒF5­±tëÔ„!5áÂ7R…ï^>qŠ—ˆ‘&|?P²#R…ï×÷^ž“ˆ,xG(0–ˆ‘IøªPTø6³sšt¨Ø<%ƒµ‡=À¥i­K¸DŒLÂWBui‚´¬ŽÖ;áû¹ëXzÖ1%‰iÂwo„ó‘*|¿táKÝôeS×d±˜*|Ûx«†$®¿¦8(ÅÄY„ëH8ë‘êâÔ! B®<_^úµ‰ÖÒ *oÚIÆ\…-æ%RÛPH«>D)Èœy1™„(5¤µ)r(Õ±²I_5Ô=m\I3!ÑP ikÛBXxüô—ûaM‘ƨ zµ°æ}3¨ªªÀøQÔ‡)•¾i3?L©CI>ñ½Óã”ÔÓX—PôÇ…ï P)‡:5!(ìrô : J>Ò¡dBU¯i2—½€BÏ nWkk‘’EÖÌΔ֡„¦¾Û‚•ôüpkVD¥oF½rPÒW„`›¦þ‘]¡¼i("2õGP’[P¨*¯ ÞUi:î{HQ‡Šû8¢Aý ˆ#êPK}rgt+/˜ˆ{(¨Ä U5%Y¬ cBñ`Lh–C)€2Ût±ÄË`W͓胂¡Ø÷÷¾[¦¬P¥Åbyn‡:•õ Œ1ÅÖéš§À€Xôß¿X ½§»B¯²hP_R‘ôí®x"°%)¶zÑ’ž€ŽŠ4ê#%¦Jm‰ ÓºBJ¬óIa*ieÏžnqH𶆴¶'„ŠQ•T¤uê)0È¢"mÍ=õ(•a}‡i]ŽÇžgzO H‘‰ØÒ º¢ŸÞÑ^ù¦"-m º”öB’Y5¤Äž6[¶ {¤Zé/7HU‘ÖÖ$Irz!i~’ež¨xO{5_¿}ºKŽyº áé´qEß[°à Ûìl<0;Ò*/ ¤Óo']q{*Úì]euS!ñ—ûûûÝõÈȤÑQ°±É!1BZJ¤}$’$RY@!usOv}ÃðLÜEš¯œ«H<‘úWÞ“t/Ò{·¢i im§ˆ2{:ÄP±q#ê¦BÚö´' b2é2eae\BíI8ýñuP²ö†B•CA-œ/ªÆu Æ"÷“šßwF‡ŠÝoªÆŠ*äXÌß/=Ýtú0Ü] s¨Y7i5»ÎU‡Z¹¡šù‰!ÔÚjGaÔ0C‡²öæ(1ª)ÔŠvÍ9 –z¸+îôz¸‡nç÷®ÁwúíX1‰õ$ŒéQï_< ;Ë:¨­Ï…iPqïáÖË~ªôÑ °»ZZQ •¥TÒ{¸ƒ»¢X¤je‡j馪ì®Öv»e¹Á-Ø®6öwEÔÚŸª"ÑÖþ®Zò®ª¬„ÚU̹Åû“ûíÏ"Ï*cRøFpùÊ+0e}! ¸nA .2D@ Šâ–ÃíÊÁ-Ê*¥å PÇn¨¦³ âeϘÔhÑ-Žiw€‰1QÑHß0ØŽW}4‚wŠáz BÕ£x´?MYƒàÚ UµØ®6Z4bøÀ· 'íjkiµÃvU…ÄX4+ø£Fp( P¯ö§"Ë…Œ±˜ŠÐJü'¯–‘…,X¯"Bm EËØÕ‰Þ˜¸\š)÷E¢ˆÁÈ"±Û% 0n±\™É‚ÔÚÕXªiç7–ҡ칬%ESã`Ùrÿð ù”5BŠìymFÔŠ"Ëb[ž\ŠiŒ5E „dÍýãH9€i0rà+ÇxH‡îUêô„°ù4¸³¼nO ÒÚ}O-€V sÿ†÷Ô%¾ðør …´ußS à‰”ÄûÞ ƒ‰÷Ow¡‡ù0/ÚâPΡÎO¶]Ñ3™¦Rs¤AY}tWe`Pl µ´7ÈA,FÁÐêC-ì®Vö$¯’<+ÂÿÀvµ¶…÷lW­v÷dAóÉà ¶öŒÆ–*êpP2÷Ï”ÑX6×W“ƒ±À®ÿŠÉ ÃjÄJ0(G¦pK« °wÕu`±@Ñç µ´'%·ä$+€¨K4tš“’ÛìÔTŽ,¸b±§¢‘ u¢ñ‘#"èMy¨Áp- ÈJ(º+UUÜn4' î[‡Óüg¸ÜöNƒ¿çú‚{²‹š*̪ ®Àžp׉EI fˆ )­X””Põ$¯ *6çir(š§ wWKsö©¼«C ¦1ʼnÓ.›Û1…‚Z9rØÂ*Âö6½moPÛžÃfB Èa[ØsØô1Aù^‹©9l´AH/b i ØjÙ§-èž´¶¬oƒ2˾¶a;â Ì²ÅrØJÚélO[sf™@J›¼§È0NJÚBM³SJÜ@H"9¥ùÖ‰l©„Bä¦ð©H<7…OE Ê÷R‘–Úž:ãƒå°ÍÏ‚Q‘÷=¡C!­Ü§WÃíi­5¼ŒÁ¡Å%9ÒFGðˆLMiÛ÷ÜÜó=Ä"P/÷£Ÿ¸#}/Ô‚PEzˡȼolê-”k£AEÖžWôªBÒ4¨Xm»1”QG|¼€ñ‰ÅÒÞ ¢ ³ç5¨D‡å]è­"†NµrÍ>iðëØ4PP2rôþ6FŽa´PP‡ðm!˜Ed¾‡Aœ€ ¾‘Aø ¤ŽÔ1ˆð Âw˜ÊNDøFá+Oõ{¾‘Aøšî)\øFák:½nOk­á–MäZ !|#ƒðY8à{Új ¯EÂ72 ß¾b0Ç @øF“„oÙ†4×Ò 4á;¬‚ˆ‘]øŽŠœä|4Iø¶°P‰î‰Ë;GR |#‡ðzâù©‚zÀ&á›÷P%!Œ jcN¦ž!Ù…,ÎV)Kñ!X-cê!ó5¤¨Ü!å¸G*s(¤Á(e5t^RÖ–îÓ›?KYCJœ§0LYCZ¹Ooþ4e IÊÙwÇû‰<”1(¤2’g<¸ù °=¹*çU–> ^î‡r|r Ÿ y|ÝHåÁH£ÁHeÈó“3•-“ŽA0Ö2D:oRYÕ9iPK7T@“•Ø¡¡‚N­¬¡¸Ÿ¬Þ2¹ìQh ±€‚ZÛ[¡¡² ôÙ/4áKÇ,°Y,G>ý€O ÈžnŸ(»«­ª|¶ Ô²´ ¢‘í…þ|¾ôS2Y©g FìÑÂ>´—{Àx`*²O"& ˜¬CÅööZD' IÒ d†õÎ8M·ÉPÅne˦áø ì®VÎyºåüö:ÔZ0Ù˜ˆºG|ÛÕFŸ`"l‚IS€±[Þ²‰U€ª‹c{„Ò ?¬#:i&ðH¦¼q11&˜:jÞ¸ivf{+ª¼¹@HqŸ%<6 гá™jOË~zæØ,HìôdûyOÂ,`÷DÔÔP!òÆw"“LžÏgÔ« „´vž^Ó‹_SÞ¸‰"ªùyã sÞ¸ížÊª‚:½ÞÙ™ì·ãã|ƒZè¥iÀ. ”4@ÞsóH ŽVnAAÅ–‘´ÜÖ=À¥i(-î,8ÈL”$\Þï ôWúÜÁ¼HáÑ店EPåÂÂ’7ÎG•ºQeÜ‚cí‡À ¶ö¹ìÔXL`0ú°·ÍF¬GYµ°'xÁ‹ZÞ85«˜wéÆÊe×¼º¶e¨¯QË·A¡CIàhi6©5¥j0¨Ä>%”¦Ç»la[â+ÁjÁvµ¶OÃ-ŸyZç-nlÃOc ©2YXòÆ I† ÀVòƹµm$ µ°Ï².ÉU”~,Ly㨀҅)oÜ27»½U Æ/탳Ûã­®J°w%¦xrÕcp×c<M wW+ µë¡2Yúñ$ˆÀ(p0\¯Ç œ Ž1ŵñ8ms(š‘ µ5O0æþ:Á8ƒ‚¶Ð‹÷é`a°]Éöêda¹«óü&ñ”eà¯ôÍ Ñ bÓcÜALOÑ –½PdæI/± .m¸°‡J,sŒ¹Ã,;V)Ø®,ƒŒ…°®Àé¥pnŠ™æ„<À½ƒ1MÄÊʹ•v‹ÿ–èCéÛNÉÏ„Sf@8‘#Š„hÀêЀàˆX¯¤NÍ\â¨-_WœaÍ Q}‡žâyjË€œ‚cÏ>h š»ÑÎu/Ù˜înJ·=…ãä- Nd —X„Ο Nl‰›sœ.æ6kRp¬áå’ü iªà$Öj0LÈ:àý(8+ë$†ƒž Žeb'kq€Põ<Ý+9hÏíÊ8/ÕºUÕ¦es?[[ä•ÑÁ-mJœn\˜wmÛ‚Æ]çZ*Пäݺh|²‚¡„Ed޹ÂÅ–Ø$ªDlò´4E&s,€ŽÍìÅ*¨§dFÙO/íxÚœH»Ûh%uï¾@™ñ;Êš :e0@ÃÑØL®ÊvtT®Òòn¨w4ì'têKçÚöÕÜŠ6ÇÐVš˜ûÞSžK΢‘¨’Up–>ÈŽN¶B¤GÇGŽÂñ®ŸÂu- ¿ºÖfeƒÊê2èCý[ú:›]Ë µ ÄÔ»®YÛåBqø Ö¶ÊËö]À d•aF{£*¯a€˜^B¨›=gº#zG¨&–Æ5*ï@@‰{GíìÁO*ÐJhtÍ ÙG‰¾ Eukg"iAl¯ ˆ%°¼??y]5ǹ«ú‘ׯæ\RD ­rt4ÙÇN¦-9¤€gÇÕÛáÕeUÎmT®!E}©M—ÖÙ‡Ï/Þ@HÂxm:~Ç‹zˆñš¥8 ¨GCâfKCÃL„=ÏÂ^95ZP ÅY´ÓZWÊ]çg?jH‚A|} *Ï0kÛÌÞííX´u…Ä•”]‘Ì•‰ô²¤màW‡8E„DiH[ËéÑ—KN¯¬+  —ñî—퉹!e9Týª ¡Cí)ZJ‘»&¶À{Š"g†%ªnè„k¶ENïIø OEñ†Ú“´bíQ+ Ú#HÃÝS"Ê/]¡,r „Ïsiÿ4o§a¦P(æaª@‘!»#—SfÛ µ— (¶úU©È˜?§-Ïkzž‡sÑ¡lw”X«%éÌXTV®Km°‹]iq3r© qB]ì£7Šö0p±ãk9×å©àÄ}\¡ñç]'œ¢~=Ap–NW~ŠÊë Gh(Íþ»ãs¹87¢´iæÊ7¶!8Ÿ‡¥¢Gf§GD©v_‡ßÇùy=®W:”ö1 ]$ÎOöCÛ» 8B3á­‡Ò­!p®§ëýs?ÒxÄÏèXÞ ˜ ɜگnGlC˜×ôúsÚQ¤ÝàŠ®Yvÿbqq¯=2 ª=ò§Ÿìy= ŸHdÓò¤5„™pà@)B§´‚!nn·¼‰¸c@—3¹¢LTm çÏ1½Â­¸!ûÅÙé‰Å©x¿«â‘ÞYZýÀ­-#ÔeJå†á?µú»ëšÂsúæ½ÂRüxg@G'6î¾¾ó; úp;ÁH"áZmvT„ s™îèØ45¾Òj·¦‚Zôe‰ˆ^‘"OéC "{¶aBqòæ@Yù~´0,HäÎ6{>·Û+´<‡¤fÄháÕ)Î|½QÁ‰M9KÀýÄ}°J*öRÿ!¦d[ÎŽ!)8KŸkË>§à$öÔ™·Á÷©öƒq˜y|?‘j?Œâ¸é Lé Ûƒv<5–á4i“=ÏGa?ì›ï‡3ï껉ÁŸƒàûáWÚ)^°Îqj"P‚#ì‡ýW·ŸÞ~h‹òuE0ûÙ8R¨Ò Î@K©Mì~d—ùZ‚úN?z½GæPå¸ïI3_ïQ½Le¢qÊf¢îXµ§ç †Dè£Ù}}Ë. Ò1G»$<‹bî”oHh »ß¨× ÜæÕh %p nq Ô¾ª †èD3¦Ù™€ÊÇ Ï{¨@«>sOjÛYÆ3j€Ì½x¬Ž°LÄ'Ç=N`&båŽPO޺⦆‘G¬¬›6œ ïèHõG,â í#¾*Tç?0@+qt¿Ýщ;bGw¹<€Ä+éf-4䎸ÒU(=40–t}í™<:ži DzGgEGMÝë'r²Üò±£;r÷Y&w”£cZ70Ä|è@1 ¬Â0;JgøzÓ££ºÉ…—Ý?ˆršÃ½ª`î(aœ|{êÀg?s>gåFΰ:]/?0öQÂ9å|GÄyÝÙЫª |‚Œ3¢ûâ@2[˜UyQ{ª+ Î~¿ʺ;ª TÜ›CtGœ3|  óEYPNÎîñó¾`€8gøúd:Ã]Î܆%,èp¯/ççñcˆ%‚3|ÿv;’Ä@w„Þç;ÕqÎðõÅ©.»‡º’“»_ñ†3¬>Æ@ø’³K¢@i}»ŸZ Ä9Ã'çÞçËéBS§h ìô8R Ïü «Hb–¥úiŠæ $u• ïõ,8ªQúl³öœ=aüu«e¯œ f–  ÃýÞÀèÞ«D¾åTÌYüãv¹‹ó-Oˆa¥q§*ªÏ·×èègØï%PŽp·£òœå/Ý{Å9Þú‡3º \d~¤×Kq,9†áÞ«m¯œÐ!át¢;ªï—4½]b:‚3ìX¶ÓEF®‰„½àâ~<¦˜w´^ô–ìˆò†DvtO[Bu×4…Šzª#wtarßÑåRåãøxÃÅýѱ;"ôÍ•üÛåÞ>ÎùõC ë刜|—šÝ®/˜w´Nz1Arqv¨½üœéhG«1(“ä}ÊÎ5±˜a€Öc $Ò Ùé¹=yò×›ÙMƨ*'?í%=ç5Ðv¼#Âçä;º¼ŠòüjO0aÍPg ïˆyhÄ;:de“ÝP$8Ã'ó×™ŠO —GYá÷õ†î7ãÜD½˜ bvfß»Èîmù‚1–7ñ€Rºh¨™^Ë;zb H¹à Ÿ{©sc™«ÄçìõB@@*gÀHÌ$œáøsÎK ΰY€$ z ,ƒ1[6ÒšØI%Ÿ[å\É¥iuG›Õ bÈ3I íýx*€Žn;ÞQ–aiñå§Óõž=+¦ºýxNèŽG—ÖíéDT …~G½iùJoEsGÛh$a©oKŠòÃý§=çÏF%Þ ÎÐ1AÔ IÞ‡{û:çè¶ÎÐç 2‹//Šã­½A¶k‚1U.É9SM›ûëôÊÖHÞ0˜Ö¨sûˆú‚ŽYŠ‹ ȆÝrÎð¹oðœ0 [–’¿ÃX[ÁvBÉ 3¸rr¿œÓ´::Á¾›NLd½çäP”msÊtú!¥m©¾ÄlBZôn'±§÷{Jo¨=!EC‰lé" /½4‡âuz!(¤x´'Fâ¼w!;=²§çi9Úº\¤c5=M‘ÑL; $á‡”Æ •‚"1üˆÙ÷ó„ÄÄïШ Z8CJÛì|<@iv„C¼YïµošÀuf~v"/š*E¨~yø]|l(M#H—ó­²§ÛmJŒ?Üþ¤@H[gC¹ËO`C¹A’¢¨êe­nXcÎ#Xž/ºŸ^Åè= Ëz’˜(Èž§WyÅ@ c£9Ùj—¼”æD" ÷Äó¿¾YZ-i žòrÛ";>Þ'Tä5çßlO4=Vî©z½—ÇóþÛ“LÍÿ§'2æÙéѹžÝ_^C’aLšOÊRæy¬™Øš·Ç­ºžo`©¸B‹ {•°¨GºeDÕƒ:½ ï,Ǻh™W’çÈÖUÚ^²ëý~…Ú“Ð#vß;›e{"´×¼‰ü ÏhOÑljðrê;–ÝŸ¶<ÁN/Z |Ç4§¹t1¥ò ¾·Uš>€y…/¹¬Ê…uY6tv)ð1ÅPTI=‚#Qñ.‘.ÄdÂu †$ºþ~ò®†,=[Ò^vº†6V ‰L‡ý§ =!6Xp»zâg¶§ÕÀ©B|]zŠhp[^'(ŠX‹ð6å6ª7Þ¢áíŸG…*0* ‘UÎS$èžÚË+ž0PvÁã ‘rÖ>#=žÇ ÈL[Ľw€í™ôíî÷ú|M2EñbFˆeÅ cúzD—ªÜñˆ†Ñ^z` 2Q¤ö¼^›{s *%`ãc„ÿ«ó­œ®§7†BZªQæcë¶x^^A^2¶9°þ´Ô8©ñj ô½x5’Oˆ*,HZŸ‡ŸÛ3ÐË•FŽ˜/™Ÿ^ýs®o`§'y„¹¨ß:Úô\§PHRØËÈYÖy“ïí›PÈHcY~¨¡³ I‹ºn/4êU?´pv•hŽ¥!q[ãwßusÉ:¤§?øø²Ôx¾$Aúê‘äìš-Ù>1P­’H˜üê«€‘ì÷œ]Õõph€¸ÑRäR7Ÿ‰S9RY] ?b¹ê‘xQ8÷ÇÓ¢ðÃácvâF˵Öh÷Ö'Q]@žH§6Q_)…Ô5ÔËÝö‰Û:Rv, t˜Eò¡X5ˆçñ3«¦ÂÔx:½dÏàöÓéTœÀ"á%àyÁç®õ<³ÝŸ÷ê E"sò³áAÕu$Ò›âv.ºŸP‹Hül>%Hs¤²=ß ŠNEîd'ŸÎÔ‘ØYŸ§*Ë[ÈäÉ’O )ƒ²>yöäç{×%Ùãn`僫¼’ƒ<}rG¡˜(êbhïþòx+óòõr·iÏyùIê°éx{¿ó7B ”Ÿ|1ÝÏH$~ݲ#‘„øò‚BR«.rÞô°+Á) øžH¡Ü}î¹?Bú¨?â§ø9>Áô=™Cù%´°“¸'VDY?ó|äÕé%Ýe"å¯OŸ¹QC­Ï"Oï'"ž Dõ¯N¿ð’ŸLRù1Ë . ‘J9,VÈD*%-V¸^s¨=‰\ÊýþWž§=~zíý™ßx„H¦lº<ÔìÒñˆ&-nO ÅD6å{ßåÂç,$Iöô¢¹ð' ”³àé”Í—O¬`AHû5»eDƒÚ“ðG4ß²#g¡cVƒ‘µ÷×û EœGìY´••`$¼9DWA÷WI÷õ€GtÅßèþH/P‘c™RùÉ÷Ôù#¸× ï?7¨{’ÙÖéÒŸ^NièG@{âI• «aá´—Iÿ¡½r[W¨^Âñû«w9*i@-ofÓ^ljŠiè>DþuŠÕ¦˜ÚDêã8ÇÉšb𿢆5ßTpdªOã|Âë+oaö“ô8†ñ„7T•0ûYi}m˜GL©h&ªà¬û©Ýú<ºG~ ˆ™Œpätð}çÏ늒Ëp?rÝÎà»ió–Hô æ~h ¡ŒÚÖªªùÎñx8)ÙÚµ ÝQ Å5NdíÆK.¨ šR9‰í]XQ ¸Ÿ¥ý¡–E8Cèp;ã!tÌ:7Cè*«à¬õn¯]W¨c³aèšO~úêfÊ®¥”ª´9dÇÎÖÜU–ï§hŸ§+ ]ó<,½­¬8¸öô,Ï0@ ‘H´3%[¯-8Oä é“öÊ’IXÜe|ºˆö<" «( 7$º£Ú¤Ü#)Xû/­'o‘bHêÝQ÷_Þ¼ÌJf@Õõö~À‰3ûFö¹ï[åSüšç@òa!ûU~u@}¤"¯Ús@Ž1жâ õyÒ. (½pûJ[˜+¦+0Äw”³èßѽΠyG Mùé'䦴W7ŠÔ‰žglGeû:W0œ!§gž;uŽ^j\=v$Æ1uîD8C§7–yzxu=·îâŸìªÿoláqÅ‘_%»6§­K‰âØÌ=; )rKÑ!ÅýÜ9©œÈ!¹asç4$Ùþóî.ŠÁs/ŒÛÍí ¥!q¾c–8£Ù”•R½¬¹ýš4$ÑqøkØA™I¥—u‘³dhHk÷ؾ6;(WCÚH5¯Íí+KêÇ( ho+^îçN¾Ülðr BPHÍÇt}þt™žÂŸ.Ñõ™‹øÖq„€7µˆú„òñf|>J6P‡â0;. ø]qEïŠH÷WÆû¢ÿþ‡Šð7¥rYòE ýõH‘>-^äÚwELôtn†¦†kãâÙžø›¢ér¨= iØìwÞWà[ZCÝSÒßçHœ÷qŽÀûz¤•Îûä˜kbÉ4iyi€Ö.Þ‡Â%G´\b'ïIZhôž×üZB!m¶ ÆúòŒºÖ ^î‡Îúäxµ²lš2½€A-ì³X Q„³¾T$Xß§IÁ¼p57åá_$TÙnÔµ¸ª^Áă«JiÛ( $ë#x!BJEÒY\+ NoÙ„a§wÉzÁ‘åu™Í ŒhH|*ôîKªç—N=§EŠÞPH¢wý×~×MŠÊ2qzÌU (bí>=tš[À¢!‰2­ß`碃ˆ\ò¨Š2mæ3Õ¶îÓkf{xõ—+Xí¦É]b]çPµq…½dèŠs T¿^ Ø®L¡aß :HCÒ ìÑÂ'ʆö±‡‚’Ã?M²÷týÉJ¨ç»Hå°ºð%¯¬»«U/|‚)IÇeÛV wµ6 _¡Î¾^¸ä íYF7°"º–Å£x´?M;׫Cm ³\:¨*OËâ %}yå7¹¬n> ˈo¦Ï—ÆÒnPP ·¤Gíll!âªCíEHún ‹°F%½Š¹å/jgߔЫ$c©7”+•,wAíi锊„ÎMÑmO(ë÷Ô4M …´r‹²½CÞÚ:)6 ”*ÒÆÍf÷´ïi§{wÈ{:ï-ØËýp³¾²}C‘„͵{Y_že-”Ç¿tUÂ=YŸÁ‹Nݳ^t)rûBJ4Û¢"Åv_Ñ”BüÀ*ÒÒí6@ålcTEJìÓ@¯Š´2Œ`Îe¶Y í%éc˜vh½&T=O÷ (2Gfb#(¯MŠRCLßÍû)Ùaä0⭾ÒäxäŸìŠÈ~æKâ8”$Ü™¡iÝ( A+8J™6g“fRÒ¹”s_¬‚ãÇ]¢€D0GÇÍ"†§Fe›=@pôÜYGLî'GíìI„ Î`ª:.(DÃ"%N¬Ñ‚Ó–¸Ç²³1æ(d,»‚÷ gŒk‹š@G8)Îš× g餷Ó›91Ó[ÀäKGÌ_nv]ÕzλX§uA$P“aœµÀùÞ«uø§ª_ÎÆ•aOEÝ\z‹Í|ÔÀ¯Éû ©±•*FË£ â£ñt>Ú†ð·ØÊGEâ.Ç¡µX'qÍy¦òtîˆZŽø¨øµ‚ãâ£eLÑñ:à; ÎRO–‰Èe¿Vp'½ÁígÕó7ž©™u88ˆ¿)8ëž_ Ñ_•áðkg£Ï=‘óèÜ“=fê½ «½ZŽL“ÑÔSÚ¢QN=}¾Ò¹ùr Nd˜Ö {²Ói Ç 'Ö{úÊñ´§ïüîÁ ÎRo‡ÜáÜ/çgvÙÒÝႺ¦ùçÜž^†V]g¼ÇnN4Q"¹ñ\þ–‰@éz”ŸùËj?9’…#§©g÷Tp¢>Lßñ®’Œ†ésœxècò÷•q( ‹‚³ÔåïnÄíÆô6·^[ÁID(¤¢PÁY ƒnt?²«ÝÏ/@t°îqôŠBÜ›[§àˆXÓu$¾ˆÚ‘¸yä§ Ìý `‡U– œüÕæ08Üݬ+"¬´4H!U„³™÷"S{9——¦}ime*+õYá[ŠÛˆó„=+¸9º”†¶}5·"-ò ˆæC¦pê™B7@¦Ð…ÈûÒ*ÄÑ¥¸ÎŽN7‡»ºÏ@ Å1$p:öSˆ¡Ø †:7Bg…‹¡XCw/Tâî¤PJˆU1´ïêeq_÷.îbƒRÍî0·•‚£‰¡a}i¸xˆ­b¨W{Ê"\ÜÅv1$Rœ˜xÀ¯ãæÜ y\ U,*†bE iv*CAvª ´pÊ»CUŠœò®ù™-£ÅCy׫XT:¤·6ÿ*Ö{_VVFv½Ý¯-1$hoºÿP;Z‰D˽ìñÏSJxÿ¶.ÎaªÂ ›‹]‚§7„ÓÙí}T î—ýýí«´#iwÔ§çh+€>; (f@×|îÈ?U²~ ûˆö¢•]HQHV„ÿöí)sŒ;ª»@²5Šúj i«H¼e9Fx61ĺ þÉm<ÝGŸ¥ó7lp½¹ÝjžÏ{ ‚ãì‚â£Wp–Ã* Õf½Ò69NÒãlÖ¬ÍK˜s[Y³^¨ ÉPp´.8#ÃëulÌýl4_sŸö…÷³T¿i]p˜õÐÀ¼Ó­tuÐ'œ!˜ºà˜‚5¡Uë‚£áÐmðC5uÁѬ‡g©>Ô¡VÎÔ.8=ãY)Á ÁÔÇÀx$†.8»/ž0Îk>¨ÖÃî§AÍõVÀàl†ŒGÕ€CZ¬$zœ^>Éq/¼ÃÊóˆ`½ ÎXƸW€s µ!Y¿ba¥p” œrû¯¯AþƒTTæÍ|½ÔÐ‡í»ˆ®9 ªŠëó´¶ ‘]p¤JÒ&$1uÁ!ÄðÕwïÀYG DÛ¾‰ÙtËg½ðÑŸ4ŸõѤUÙ^çVB,YГ•sÑŽ¹/ô®„ÓÍŠ¨!D‘Z â`Òbk‚=aÞAõY*ÒÒUž"ö4¤ÄÚ.65`ÒÊ**²²I›ìy>!‰Öl»†#û ¶,O‹¡T 6;sÿ~3nq<ã ŸôATô"mX (yŇgò13‡ÓŽ™aR¸D5¹¨ò]¼1Ô‚ïêó[ìŠÐ9ÝÛÕõTœÚ câã3‰]ð)»y œK${g4ÛÏŠlØ’'ÌN/ËØ~¯×ããEb€æxx+jÇ·Ö9”¹#&h ˜¡- žÏÇíµê¹`>.… ^~½«ãñÅå ÍÑDß|0Ñ7=Aq‹x3ÞIÆ|W??Õü*> йÈÞ;>]äŒè°#V½\§M}ÉŠìz³‚·x7ŸŠÞ—ÂuZ7O¢K_PÈçh•“Ce4ušÅ‰ëôçñªŽÅìé–:ãD9ãPlºbR¸¨Þ=Á<…‚Šù®ö{~Wc‚9&»zWʯW(¨¥C´ãw%tN²«6Åuz½ÞÏPïŠÏÒ|7â™}šñ»ªòímW(EšÓìu‰à»¢øl²îÅTî_Iì"Ÿ`–¯+:C=tœæ› ýfªöFu‹š¼ªÛëü>ÝnP¢q)æ`ñ‰['îŠawõL›êù¸âú åÉú໢zà‰îêŒg¿ÜëcZ^o×{Å-èDÍ7sªS¨3mÄÎ4&ÚßûU=o?ÙêéHÍ75†¿)Ô)£e©®šëù~)žEYBAÅ Š;~¨·[ìêŒÛúyn¯?Ç#”"M‡j¾©#š !vÊpém5UŠPýnÏy ¶«„Aí¿rÞžçïKÑžŠ×ñþL¡4&:VóÍšmpÆ$yàO“¶YS\ž”ÕHçj¾©…Jîêt9^¸‹ç‡öݦ—{{F?`ȹ+ø9ˆ&Ü‚ž`]§·ó¹®/5{WÛž,(¹+&ð)Ôñ}.j„PÞhÎ-„"Ͳ_Ù ¦Ä~Æ„J~Z(Éj¡ ãLtW÷C~®Ïg(¸ŠÆH­+y€§óý\ŸN *¶Cµ÷â\?-Ôrt€DÜwx­É? ®· Óß(Y LÕ³œ1¦ã ]~ªôðÊÇÃeÄË5´9 ¹ãá2†—+h/läKb.óþ4É\œ6¸îoŸX_®”¹/@j¨HQßÌw8±DœÈ–dør›}?sƒ¹ Øé!¢˜# uzKÑ1½é;¦ ¾G;¦Wi;»m°Š”˜gn°Ó£cˆ›ðÙÉðåÚNeµ§5ï;ÿ2õf'FM>Z!ÏV¶œÞüÞÒvØôGX„ øË¥]r¨{’¥f¦Ù…ä–@&S$ãJ{ªñ©}àKÔ†4­Ö "u´ÇPpж `„.‡ïF b*9 péíÑ ,I†é»_Bvðf¬>u‚//·kUBA­ôÎFƒ¦ó £=’Qú®m´GIl jãVfÛò0Ÿ[{U™EaýíU¤È­b¢r¶Š©"ÅvVцõ·W‘–nÅ€ûëEaýíU¤•ÛФ=28[ÆceúÙ a.Èàlq8&P{Èb»c¢D¨¹¥ÃÖLΫ»‚öÆÎ–Þ茕A´ ¶…ÚÓÊ>;ÏË=-D˰¡Ñ1žëÑ4bé…!É‘F¿º‚žÓé]óùžŠÛULT¥US ¨=‰‘Fû†%ŒŸ%í¡ºJkj„Ì*#%î=U!#ÆH\“ ÁPÚœŠFóxj‰é„«G^€Ñž¨úþÚK$¦H¤¼z¦' ¤²§Ë™ï åEZ`È=m•=]Î|O rOn£U-ñuFGçê㦔àæ8Íj¨%ŒŽ†F'Ee Ëe 5 ªPÓÖP„ÎkV™ýÃs4˜S–¾)jÇ—m“CA-íö ¢#ÓïJÓ†RŠ6.kÁîJÍ *––À’ý¹Ž †fPP¢ÀX0‹®¶ •¥ôcsÛ•¨0þwE¡äð=þŠÁîJÖ þš†ÎçMJkÞ‚ t?¦Ey ð«H?¦ˆß„+/šó÷{'«Xæ÷Ľ a´PHK·š”¶j’æÇäÞ‰C×-–{âRÚÖ®BZ9O/G9‚BZ»²´¼@!mܧ×Ö8BÚº²CöžÄ”įïw…Pù³x¶PP ·J¹«HÙÕåŒP »Šû8¯ŒTö:U* (ªèÚW[Ô¿€€‡•ôêŸt$Q–Ä}ÎêŸâÇÝrx ×ÉX .„N¦ú1Âh¹{Œg¢9 Ñ+·mÀv%ZiýîŒÉ·´AÔÖ­i’EôaöÅ ñ2$[ƒmçžô^ýËšâvÍ  "·R (BX¡ÔŠ>ШJ{iƒ•ÚÔÒ­Ô^*¸]%½RËßWjÙ»‚PjP+wÈ<ÀŸ¹Í$U?Ù—2G£¿u?™%d*Æ&?OJ«0ÔÒF†:½¥3¼L˜úêô÷ž„BZ¹c¾Ác²?™9UAŒþûÉaXÀ=mí <bôw¤*µÖÐhðèoÕO6ýÝËŽ¦¼âk ¹ã_þ7î«8ÿó—†jHîÌ!ñT¤¸oW']¹t¼„µ«S‘–ªÈsØžÂZð©HIßOì)—™ÔñT¤•‚$ Ì™ã4¬OŽŠÄXßûóóK °¦ïIôZ{55jª¢BÚp$>;‡"±øŠ@*Q{C!mÒ^"åY¿§+¢Á¨—û¡BñZ)õB¯ûo+øù%Ïe]W¼Wñ8µÅìÊ *PŸÝTó®ƒáëõx—ù¥†‚âú—ìŠGÛàL PO_§6;ƒA-û¤]–çÓ†´-QVA=*ÑVð«á]ñ.g^iËÿ,Eõõ‰®PP+wÿ¸ H¶µÙ’èÞuɺFa„ÑViÚTPPw§5È]m…ïTvZ ø®²û­I¬8I$ãZQ9˧›‰E«èŠ€™XdOkC›ìÑT¹|0Uî'¿ä@H‘a®\?ïuùB²ÏlÈÊ ™ ÒÒ®£·AS4¤D^Ö!U¨ªoO(¤•aŽT7é ¨É©Š´î'tÕ$¹¬S™“¦! Sž JÓªR¯‡bö`P IH¨Ý J¡«mËòöH {¨—+&80£WÈ]fÊ3¹[‡¤‰kPÎfúEÀ,@ Õ +_èÖóÁ°åp~Ô!E†1Èýè*~Ô!Å®ÚuÀ:$7? ©]W‘;—`óbáNoåäÓƒ5¤µ“K œ;NQCÚ8:4äeX‡ñt“ñ<&C‡†2¬GEŠô¸h_‹ƒðµ¬k $ÝUßy\hFÍ¿ž@HKó$O™SƒÚì„$üU¿b8kì<ˆ¿>ž%EÕ¯ä€úþ9 8_·T‘DLy/‡Sˆq©y=ŽG(ŠØ8ú[¤(¬¿ÅiX»®öìHiõu@åå~ˆè¿lÀ-Ü}"úßžžå JÎ¥lŒ&<äù WýWï˜4K§9 %†" ‘òÕ{ 8ýq¨¢}žÚ´*PKá˜èps]L¤Ä=Ÿp»Jã†òÀN8kn…FšìP£*ä€ìXü7î{b7„PXo¤1Rìäè¨ æè e¢ŸÑÙ×–aÆH‰Æ“ú -á´U‘!­ÜÚD@œ-–R⌳É$ûmBEŠ´~OŒ"dÑO€ŒW‘b³ /ÊVšC6[¿T‘D‚Ë^‰èuÉü󙬊”ô2^ÆÙp"¤T¤•‚$´ Ñ Ó&T¤µ[›(vT‘6n¹ ˆ4ðK¨3JT5„É6P/WxÎw¿Tï9GU[^o`P 1÷b§Ï(iÃøãG‘[†³¾‘صCZ-z} $7ë †±Aì:„a@Œ(vˆ]ƒ[µµÿ)vÞO RÄT¤ÈÞ’0Э£"Ån·àé-Ýᤥÿ=……T$÷=…„T$M•ÈònOA³n5¤¥;TQ¾ÖRvþì«"­LÃÐóÁ0ôz¾;{cs¿©ÜˆŽCÈŸV‘"GÐ M¡U‘ jlŽû¦EY3{4Šdq¿ÉÖ\A¢æ~ëT>ÊC *ÒÊ4Ó9Ìt»§õè=;™Ë†:×´·ÑZsñÖ>¼5×­¼"¨ÓÛö/W„‡^®ˆ2ë{AE*’ÓùQ¼\5eyOa¡”ˆRÞ“¤r¢G@ž^2àåÒùÑi–¸¬êêôVn^PàK¤d‚ÄËU$K’±È<ÑXT$GÐU¨­«Û iéæåAFõFs~88, E¬Üܨ F2Y5¦>Yá´g²j ´bÕ¨H±›žžÐXº÷¾2êD8RZê^õHÿý[°®H#ñô»cäSׇ6+èÐÙ¦Ía€"7P—@;Š%о"¯IÕõߊ]@K'®K¨;ô`OI”_‘§ôhYU<ÔŽVn ÿiðœH4)údÌWßcY_å¯k]íHö(jeþD¥”@ySmm—ª¼Àòô`E;ÑÞäDT",²çÂÃÑŸ”dÒB¹%6ÆŒ–øW´Äð–d3îšhßzM îšdíÞJŠ!AÞÓÒqO?5óx!%Ã.4<÷6"Û¢Jk¸Ó[éH8둪¼Ú“Œìö½¢Òí‰uäm€6½cª+9ef'+«.žmµ§­¹áê¬ãC$ke脞ž¨Ú Ö̱ij|ÅÕ£4.¤…©l1Ôž"·k¾Ec1ÑY‚ž^‘¢¢h(¤¸ç{òåvõI?uIS@HK'±0 xy”ôÍ2¤Ã#“ =1k–…´¶åàŽ©7º^ŠöÖæ¦lü=±fPÁÕˆÝîWÜï Âîé™ý”4ûi+êª÷û¾®š;´QŸ´§xPÁ-údð\ìÓ£ä{ñÂÖfŽí U×?Uƹ ÏIä{¢ìõIÐ=űÖúƒŠ ,NE% 㥹ç{<–„$:u®•s׺‘´]÷Ì=ñ:{†7ô‰þކFaÉ"ˆpškg¨@‘¨©æJ'(î“éT%‚v0¾¡ hG¦U tƒº#Ë,¡¬Ð^Ó9 Ð`–A2ÑX Ðz8lKLäŠæ2qhcniÍŽµ´:º-ïÔCíõT¹d²›zE½DÅÌÅÿ-¸;êÃ×LýA_gPxŸVNw„.X ¨M‹òV`\Ý  Ø ”7Lj?Øý— *½DôÁR‹©i  %h×eyT´@@²—õ¾s 0ªc®ŽçÐÚÐÍP:oh7ÃK ´ÑâøÂ¬¥c¼¸_h«sïœõáÜû4›©jöc˜Ý=´Ÿé–h{£{ „d2½ˆ ¨²´BІóþdÈó.|EÈ…†'MHEŽ¡+gtò2£„.{xaܦ(‡BâüድÂ`[êTζlü†:½•à­ß{É[1êxkUàñVî%"vãy)ã>6†t¼Õ„U@Ñž`ïoMy ñœ/Ó5¤íp² EâÚG Ñ4Y+ ƒ„O@ž£ˆ'íöWBIõ… =qz„öÝS‹¯eŽÁ"ë8ÂØ\F ŠˆDUïbÃö„$hq™×¸’NÑÒ„ëè=I/Ñ—æ»a‚ðx¼ƒ^W»ëEnô ï imèršÑÄŽ†w9ÅO¨ÓÛèH<ƒz¹ÂKÄ=_ ) ó+Ô{’^"~Oâô{:ƒq#é%âzDïùâHÚJõ75£e]Q8Rú‚ÒÂ:/Käýás7Øž*ê%ÊŽ‚B2´¢Å=Ò±® t#æ%¢Fç®3:™n$ŒNbÎÌÕ#þÅtTuH-lc”z«³ Ñ÷4¤È4ÅKnDöTU@H± )Åef©!-ÝH€§—ô] >):ýjO+è5¡-³ð×¹/WCZÛÝ_mYÄ5¤M/ÝO×ËÛ¼*r¨ÓÛڑʼ­«¢{¹:kq% ÈAmj±Ð4‰N3§t~›í÷СF³[5(:' *¶íŠs¤[ èOÎ<ÐwŠȮࠄ Jí5Õâ(ù©®àp%M޽¤@Œ„¹[vQÏö»éPƒ8¤”SbÜ•S d!f·þ~™<¾ª›P¦©Â÷K›ÝJ ›ŸÙ!EZ«&†t-Š´Å"12_9H„"qñ!æ#ƒð5í)\øF“„oÉZ ¤Õ°ÙÐ(%‡vÁ blONá‹h (¤jZs9ÅbB´ $XNEá+‘dô‰ _0¤¡ðU¡¸FQ€1‰ðï8‡ ßÈ$| P\6Ò„ïç®ãY÷¦ $b¤ ß½ @ÎGªðýúÞK²`‘“Å‹PFv€+;¾¨ÛÕÚ:/ç%fWƒíJß/]øRçyÙÔuÔbªðmó@ñ±Ð„ïŽõ6JŠ:ó ̺8A!Å:Rq%H Îr $r–¯Lc§ mC;G4Ô= b® Õ™"åM …4(5|ã¬ã!J imŠQJ%©lÒWÝ!m\I3!1J ikm±@Þ ð-ê/÷Ú"ÍmÊÁž®¾†¼oU7 Ô‹’ÝÖ¾vZ‚0ô´ž<Ô¡$ŸøÞéÑCêi¬K(ªàÂw>Ï—CꆂJlYNEŠ‚²œt(™PÕëdÌe/ Ð³‚ƒZ[ãz”,²º(ÁÈBhê»!„HÏðíc”¨ôͨ†’¾BUovšªNv…rò„¡“ŒÁ¡$c¢P„1A½«(Ò”ZÜ3öàž÷Kƒþ±Ô¡x²þ'¯ÉTÃ{å%oJ°»JÜP¸jÁô¿•aWÕGb—Ž¡Ö2·½‹ð vÕ< ׃ڨRžÀ¡Ne}ã2˺=wS4qwWTAí*þÐFswfA`@,úï_¬†ÞƉÓ]IYY4(€/©HzŠvWRF‘Ø’ŠÛKÊhÓÉ€ŽŠ´4txÚA:ÎN‰ÓYÚJ•ý#0L¥"9Ò´[’=­!9ò´ E„¨J*ÒÆì;ï)Äw "mÍ=õR”a}‡4n¶;îl#ÒüpâMW‘"7àžÕ]»ØŽö‚Ì7iiK›¥´’̪!%ö´Ù²ÝÓÊšPHö’§!­{$G)Î*ÒÆ¬¢‹÷‰$j,¾~ût3JsbÊÓÆH 6yYOwQ{~³ƒuB’N¿tÅeHì©h³wžÕ!T>BâÆü¯D’®8Š„oEÓCôˆÒÒ¾§2{ãS †”¸‘ÈA¹¿¿ß]Ï”Lšlyµó›³hHk‰´ï‘DŠ)AÂó›¦hH›~O¢L%“ŽL‚ âF#¤m¿§IVÞP¤C½'áô³]!°M §Ÿõ¦p Æ%xWZ#µë¦ìf™`H”(ò•o »¡pS‚íjÙ{MÕÐ<ÂMZým@»jИCÍ7@Ÿ G+÷®ˆ½eoÍQPkjcƒ*‰ÚG¡PL½kÎa°¤Ýwú =ÜC·óû×`ÄÎ~»÷'wú3Ä'u’»ºµu^¾òŠ1E‘}WD©øÉk0n‰Á~g:À'ÁpPKq€œ³“¼H¯é&mÜr¸»Jì»jÉ®hW\(¨Uï > TÊ-Ê*¥ÉâPï*ZÛ¡Ú*Í«ùÁX jãÞUÓÀûÖ꣠¡·,­·ˆ?úpŽ*}4pP‹Ju¦yuL+0 Œ#ÛRÎN°…"‹8î#G‡Á»âd‘j‡;À¥ª%P9à®»ïªe9÷pP«>Á;Åp•¡êQ<ÚŸæo­(Ô«ýiÁˆ}¹SZ‰àÞÕ2²ëUD(°­Áܱ«-½+0Ez¹4S ï‹D)ÌY&²`»¢dÆ-–+3Yð]Q²€ƒZ»K5íüÆR:”=÷º˦ÆÁÄÙrÿð ¡Ä 8tà“çÓàœËòº=…Ó_dÍý“Y†-ùÿºÈ ¬¹)¦ÑĶ ç‘-÷¯KÝàÒ iåÞj (Ú[Ûò9R kŽøÃ6î]@Œî¨lr(*ߺ‘P…+¨—û¡EÄ0¯zc)êäUå`Pz˜²á!¹„L¼×Ó ™ªRs¤AÅöþ8ˆÎ1Ô›Z,m1Ez€e`üm åõ¡jeÏÓdM^ 8b_»¡òŽ,¸ðÝ¿Ùx¾ž>rÚ*ðÑ”‡ jkÏ>m)Õ×-”¤nÀ=U”ä®(”ØyÁpP {¢k›šÉ*™û÷kÈýCÍ>…ƒŠ{‚Á]q}åpPK{òdI„=‘Œ`P‰VR…{ÆD“'áÈbe‹×3¨ãñåÈn© ¸+G¦pI¨¢$‹­Ã Ãj/K(Æ$±¨)¡Â¬ºàª„ÚU׉EI fˆ )­X””PE›PAÅæ”PESBÁÈ"^šSBå]J0Ñ'N¸lnÇ jåÈa «_ØsØô¶½A™e {› ) [naÏaÓå{-¦æ°Ñ~!½ˆ5¤Ä:ãéXVµ°ç°qI•õ­KpPÛžæw Ê,[ü!‡­¤ÞÁö´5g– ¤´©qÀž"Ã8)©' \5ÍìAuQ!‰yRͷ檠H¸À )ÖºüÉ‚yþJ „´tŸ^‰(¤¤Ï·á“žx¾ Ÿô”Ú£"­ÜH™=*ÒZkx5N“‡x_T¤Ž4à!ÎiÛ÷Ü^ Üó=:㢂Bê:icJ@é-ƒZ¸zËåÚhPö–MôªB¤T¬6¨ʨ#>^À(}±´7=(Ãì *q $iðëØ€ÝÕJ½å]”¯"V}vW2rôþ6FŽa´PP‡ðm!˜Ed¾‡A<‡ ¾‘AøJ$ÙÇ ƒßÈ |R÷¨0ˆð Â×tzáÂ72ßa²+£á„¯ )\øFá;ŽG°ÒH*ßèH²µ`‹!Ä|d¾ÂABßÈ$|ûŠÁ (áM¾eÒ\Kƒ²¶lbW |#“ðÕ‹œ „o4Iø¶°»Ò…ïÐ=öÈO­/ uàyç³j„oä¾y¿«’ÜV µ1'Sˆ Ï@¶´0ßÝ^ *Áj™ø¤¬!EýÜá)—‚*dÀ±†»÷4f³†´tî)`–²†4¦¬¦”AÔ5¤•iþ4e IÊÙwÇû‰<,P{Ú(#yƃ›DóƒBrTΫ,}@½Üåøä@#>òøº‘ʃ‘Fƒ‘Êç'g*[&ƒ`¬eˆt~«²*>Ò –n¨€ê- *±7BCZY7PP+»Ë5ˆ†² (¨µ½*Ë@ŸýB¾t ›mtäÓø¤€ìYàö‰r°Ü:¡Êg ¶+–¶AÔ¤½ÐŸÏ—~J&«*mÁ(0ZØGébÚ«CEöùÀ-™Ú«CÅööZD' É:Рd†õÎ8M·É˜°—-›†CE(0 \9çé–ógØëPk9Àd7`"êñlW}‚‰ðþ± &MÆnyÚ±tÞ;@UÇö¥AXGtÕdŠPÅÖ”7.ºÐãAzSGÍ߉l²~Ò$ÍÐ É1¥³½yÞÜ ¤eŸù<6uŠWT­h¡’~ èØÔaHM,ª´¼qËžš"”§ëyãÆ=U * DÞxGå¨bTN4Ͳ£ò­ 5uõr?”‰ªcûíø8ßÀ˜ÄB7àè{’ÜáÒ€AIäÝA17´àhåTlIËmÐ\š†Òâ΂ƒ<ÀD9@bÁåý®@pe›€Ë&Û:ÕMyã#¨ÁH9Õ íÜõý7pgÁ±¾,P¬v±µÏe§Æbúh  ¢{ÛlÄz”U`P {‚Œ±¨æ3³ŠYp]·ž4»æÕµ-C½ejÞ¸ ;PÇyãc‘úY³ž`cQÍ7Î÷¥-ºê1æ¼q+T@•ɘ7¾ãš+’àš/’xšì ó¼qóØâöFõLäí#v\3“»Êdédz¨0‚:@a€G$·Ç[—-ÊöïoS=¾–*RÛ>g¨‡¢ù pPŽ9¿4íPˆÈö¦1É%9¿pW‰}ösù¤ìÊ:ê— ü‚ Êž¼K¡\K=Ô {×0ô jkž`Ìý=t‚q5l¡ïÓÁÂ`»’í#ÔÉÂrW碄ø²}„:ZXúæhP±i¶0î ¦§hPËÞ (Ò夋X—6Ü ØC%–9ÆÜa–«ìW–AÆÂ XW`ŠôR87E„LsBà¦7ÔÆ4«Ìê™ïjñß’}(}ÛM’)NVáDŽ(¢«C ‚cÏ@hyóݹühÉÆZwS­ÖüŽÓæ08‘%Ô\bj~Ö 8±%ÎÌqx¶3]Á±†c˺lB:\*8‰µz ›7€Þœ•µs?ÃAO s³L¸d-ªž§; ½ÉZØ=ïÛÇE_í£ªÚtv·Xgk ¶mEÇsm'õ~ØB¢ŒànéìŒVhaòîV4žWEæÀ!-ð¡šhX8¯Q9WSUxdm×õ³"@T÷a³,‰°+Ûw´ì³à”0JÖViÕ6(qÑîE0@+![›A¥k¼òŠêÖÎ8bö• ³eߟŸ<£™ÜðÈëWs&Šc DÞ[åèhð¤h ©Y²ßÏŽ ÛáÕeUÎõåiHQ_$Ð%¤õŽÿµÅI¤è4¿ãåD½ÏˆzPŽ !q²¡rÂðŽgá]+‡œªhv« Iذ;Ý¥Lo¾+^C âëSPy†YbönoÇ¢­+(¤µ‰R9A*ë H\ˆPÚ®‹Ú ÁÄ㲆¤=­§ wírÚ ©äÐd­pví~s ÈBŽúUBCZ*»ö›ÀÓ‹"gnªnè„kZëÔ&¼'§¢xCíIê“‚"¨>‰E$„áîI*”_ºBYT è<×­ñOóÓ&ù …2 Ã‰ âÒ¹œÙV¨½T0@±Õ#DEFÀä,h)8QÓs"º#VÑMÜŽk½£€ép*ÐÊÕ¦ vÚ)Í9FÎ!N¨rÔšCÑÎAÈj@pb×°¶gg,pÞs£8óÏMÁ‰ítJÀý8ÇéµÁ8‘ÞL8¡ç©ôf¥¸Ÿ¸w‹ÑKÌ™F}O €“8Ószw8YÞã:½Gcà¨5¶Û™œÄ¯k6 8±Áê“9‡ÔêkjÝ-’ØÊºm*b2W0ç–èÅÚgtSpVÖéGd?!Óœµ™_ gtñlç&ÿ)8›aÞÕé$m=æŒnÒŠX`0ûÙÚ}Ä„‚ÑêØ7£×»¬ÂÑã¡o†&,ÂG\ßJ Cq3Ú8©âG 3z·‡y…3úT´@G·4™)3úTä ÐŽÛ k™@ó[Ä.ÿ3æ6q…²)ƒ¸‚i0÷8F[Rpœù½¸»áp Ózœ¥u⽟€nÁ Nb”MCa7TÍg ÆÜ¿zè•p9TU¸Á‰•fœæFé´d]ÇJ+Nƒ–‰–‹Õš"k7vÀý,ít@„C0½)õDFº&tLoJ5ÑŽÑÛ‰àœeø°ÌÓóhêçÜÄižüs8NÙÇ“tŽÙCdwESdk ¤ÈíïIÑ!ŽÃG¦ ÊèT˜ÃGCI¤Ÿ"äÐgÂãó¸MÑñ „Ä)oÇ$£©,PŠÈC: ©H¦ò”\¶´%FÄùE{k·¿¬MçF¨4¤µ¡ˆ2¤ ¢Š´/—rþr³ÁË}4A!u1cFüé²üQþt 3šØ®A-Ü~@À›ƒùô¬Q®oæ Ô¡¸aǦՈ»âðè]]óêHl¼½Þd[å²y8Gê‘"=MCä¢C¤ø„›[”ó7Ô¢\E^hÖNã}EÈô@)é難Ñq$Þ×#­ O°D*›´¼@íiíâ}(\rôH2n¹“÷$ç!Ò{z\ókY!m‡µ*ë j®½ÜõåÒ!]ÖM™^*(¨…=Bˆ"œõ  "Áú>M æõ€«×ü!\“¦suý›ÙUáÁU… Ï#9X_^©*RlOQkCÇŽ‘DÊÆN ‘hÅN/Ëkt** ¤ÄTfjO+=.—m:ˆ(LÑ»BZó ¿_Y“L} ¼D„zQ¦MqBÚX›¿^[fE•P§·u#”3j/W°>æ«ÖånØ(]j1lÿz"(g³ @pbÓˆ Üñëô6·íŸ‚³´M=b84 f?‰#…ä})8+Ûd ºZODokë°#J´¥H‚³1 ê¡ Ô37v¦àlͳ‡Î#'tóN?lSOiº{øCUÓêõ9® '˜ñĆ0npJC8Cˆ ¡؉;…'”!Ć Ì ¥8Á !60­Ùh£ବs:É~ÂBl`zb^8Cˆ ¡›É2œÅØÌ0†Û N½ÀЛL"úêu’›pÒ––™ÎŠu Á4u…i¤óé*8‘µÞŠì´ŸSpœ™Ô!𝂳T»,%jHóM'Q‡¾$jÖæ%̹éÙ…ƒLêpz3eR›,†P:Ð2© Ͳʢ ¦S&µÞg©ÒÁa‡Ó›šIýe¬ §7%“Z©ƒÊuP×¹Q©%3µXjÍ€âvŒeëºdK³S5T¤Í©Áòá­!ÅÖ`«Š ˆ¿ªHKW¨<„¾5¤ÄÔ¦-´i{faHJõЮÙíŒ9Ûá{ÒꇌéÔ <;ÇOEŠÝ>àpŠÕYš”AµJR¢Õ@ô)j9‹SÎÏ»ãn¬C©dn¢Ví$(™pŒ™³sÙ{BÙ¹c¤X3ÁD¤ƒÕ ´EÑ@íIG¿¦8Q›§è!%Ö–‘äôsfÇH+GN+—Ô=­û®B‡AØŸùÒ ª¿#mÌCçí݈æZ!mû¡#òôp.’sNåJÿNОw-Êtv*¡Š9òêÛÀZDËà/WÎèßÀËU3ø-/·¬St¯‡ÔhQHÒ„Š´Rsй¦ÌiïÊæ!­­ýÀh,9üåŽ3øÍã")í…åÕ'¦ ~>°Y•¹8mpœð™X_n߸4Hj¨H‘Öh N$-<¾Üfß'kç™LÖFT”U„´t"µÂR"Ú±~™àˆbÙ„çz&ãôFïÇJÔˆ*m/P§·6'k3Š`â)è]%æVùü®Ø@°\æF(2Z·Ñq)çîС6†IEƒaƒÍnW[s{6~‚½b°»’ÂM}ò†Êª0b×ý˜å%À ¬"Yü˜"~®¼h~Ìßoá ¡¬"®ôÎ)cBZ:‘ ªRè~L‹šÐÙGEZ¹U¿´ Tý4?&÷¸ôóž¸w1ÅmÝ@QÄÆDt¨=mÝ Ù!{OÝ€¤w…Pù³x¶PP ·J¹«HÙÑÉP »Šû8¯ŒTö:U* 0.»t«Á *éÕ?éH¢HÜç  þ)~L‘ÇG?qŒª :™êÇlSâî1"<˜ §»¢zEªiª~LÙ|\Kž¸¥ ª  ¶nM,x# K0Ô‰DƒZ¦çƒiç·k¹•Z@±ÅžaÝ¡JíjéVj/Ü®’^©åïŠ+µì]A(µ¨•;dàÏ\ˆlpÕOö¥‡ÌDÅOf /—ms‡BŠÝáå £46ùÉxúÓXY¢ªsÙäP{JÜH¨ÂÒÊó îE¢øÉ,S´ ú«ŒýdŽ0,àž¶öÑ_%R•Zkh4¸¿Šê'÷WéeGS^ñµ„‚ŠÜïÁ=.XSQ“ }rW6 FCŠô>~¼h÷ñ›_´ö/ùom¨•cæƒrÌŸü’!E†‚ÌAŠ€&’*’½ò&+ƒ*o4¤¥«‚¤(ú“HjŸƒa}>¨£¿§Q§µ’~Ðù$üžF½¬õàž:¤¥£Ú"/ê-E$ö©n¹¤ò2¬ÚbŒé¶hŸÿ2gKCŠÕKy`]Çšó½È>K0ï§÷„ŸÞ„¾;¬^ ¨ÒgŒ»)"@>Œʧ|’Á©ŠP‘"÷=…ïiD–{¢é×סBòð½€&‹‘DŠ{’=ÍÞ“Šä‘¹{Zúï)LæªH‘©9Ô#×óu£—«A+’ *RäÐX‚š;hH±©{@>èzz‘kžnÞ÷ð¿©HN^^œ^¤v³PD@œ7–HɾD*Rä¾§6xO&¾gJà ߓÂ÷ 3bÓºÀi]çh:Ò’þ‹~&ú¿…Þ¶Í0ô–aŒò(êÝ9ìì„;‡õm#;B‰§8â~ì-µÜåØÛ¶•coK  e?÷V±ª„Vν­€€’>IñŒ TàGù€’ c< p:#Þº€ÈõŸì‡\á°0@k‘DóuXlˆŠ=6M¯¸iÑž:6. {U–P@"ÿƒ¿£>Ù‰6g)Rb¡¡HFv9}óK™¼$ÌTr ¤a+Ìã Ñ-¹©©:Ž¡˜P×L`/‘xO-ŽD+¸œ æTñ¶›´¡R uOœ=ðRƒ~JôÕwšàô˜DqÊ®ùý6"µ70$Î vZ×iŽDg”@Hk•׈6~BâIbòôxÅÑ´˜:äoõ9b’"¸OžßC:(YûaÎFãÜ膊ŠÊE8w·û÷ÄÃüìžžÙ±œ î)*Qó©ö¤šJ‰Û¿ô!ñXä‡2ŸÔÐH5uÝE}&8W‰¸’ÇU¢²&r(¶¶ÄKK|ÄG0 ¥­'mnŸN³¹« ”X^lt ØŽV’‹Ûdrއi©†Z  /ÇëoíÚˆ«æßr ÔÜŽ) Ë_Ù‰ñ"ÇU&郥!}”½ë¬nêy@ÍNŒ¥Ñƒýí,O´¤±Î‚—<ç0@‘Ú÷@ÜX¢@5FPl­9…qHÄÞ´[óñt¼Õ·¢|àºy”@w”ôƒOãÞ¨!ÿÅ0@ƒn ˆæebG5·—`€£„9×8PÙ¤¯ºÚ úK ,ï¨.ÿÖWÐ 4q)Ž.눡æ Ѓ•-@÷»þ’z¤GZ€!-¬U¦§¶ ‘HÏ6ã£}Eb[/)Úsó—to7R¬YC™ô·Ž½n¤¥.”„n̄ҟz»‘„ óµ“{ Ò±ýy¶@¬UÚ0ïïý Qî©ÍÉ_¡No­[KyOˆ(^%ÒFˆZÂÆ…¨ÍÈž#¢ö§®Ôž„PßïLHO"ÕK ö*‡»ñ!34¥Rޤ}_-±-€hO¦¤¾¿%íÉê´óq‰0¤HÜÓ^ªD˜u‚ä§—×u‘ͤò‘4—FFÌ^™Ö.¨£¿) ¤H u®jN©Ê« )6j°‘ªÚj®¡!-É*BvÚJMÛ”U’µ r‘ 6µ'©Q›HÀÁ=ÒƒP` „4• ë·ö/În¤¦G ‘ÚÒÖ¡GœúËýªï5“ Ô·9Ô¦D–#o«k‘îêÑ0•>0(¡ñ»Ru‰k{oØ]-¥21ò®.¸cè‰ÓnoçGt¨•ªN`Ü yLäÜ®ÖBŸØ›ô‰SS£Œ,6½Q™”â â?ÖîC¾¦H)Àƒ¨!Iâ—–$Bab^EŠmsv蜪¢†´´NÚ!‚*ÄdÓ\^ÄIºw{#÷ûÓt47ÒZ糓­º¢jOW0ˆX»Çö„´í³!ø{èÙ{ Ɇ H¶tˆ)—<"$BCŠÌå-Œö‚ò!4$™±ïÒ:wAZà+±¦ –}%°!õâ …äN‰È‰æòBZõ]Lˆ€êûD@eÏ·Œ"DRÄ~/rËU8Ví5ÒÆÚ.åÄÆq—5ÒvØW|—¬½/†z¹#7©š­@ûšC]TçTÔKžN¨ 2ڦ̫†~ÇÙì*vièw\fpPKg½-T¢Ý%÷£®ó#j20Ù±P_ÆLt?4`d!*Þ¿E€ÿÒ…ÝO4TH³å¡ „oñkà³Ê¤†~+ê¼¹¾«HõYib¾H‰Ø4E …Ôù¬T1Ϫª, ,‘<î³Ý“¾ûIÌçBJt1/ULÖðãÒ@!­ú~RÌçýžr¢º´@HëáЦc'©˜¿æ-Î6.¤æZ¶`H[³˜§´GÃâ-Ê¡¤ðáÝ#ï–‚…ð¥S E2+Q„¬ûE™T4 ˆö6/ƒ¢¹e ÷ÞYYÆÚu òÎjPKÛ4 ½DcŸW”d?ܬ! %,ìßa_‘Lª®ò¬‚‚&öï§Éé—]›j  „ýÛ…z9YÈ]½«Løn].Š;~<`Ò÷Ãä£à™óê˜b0¨…Ëkzo«+ºBA‰àÞ×÷^÷šÞª¢nÀî*Нiv齦Ç[]—-gífdœª?_ьأDןù±¨:c°]­Ìú3×·A­­ã-Ó_éì|n¾]ÌòíÆãn læ^ftn NdµES/o%FŽÔœeÏ{~C2;¶EíJ©]8KáòÛ “údºoK€æ¦W)8É(¦Ü¡%ÊD[ã×sµ±ø?n°²!YÛIžidz!™ËåV7Ð0ªË³tNeýškI+8[™ ´©\"èrhZ˜ýð8?gpÂ5ÀHò `p*ãD]`˜ÐD®R¤òP¢æPÓ ˆ#{éwß±R>ù˜çG#²¥3P,vÄÌM¾#ÊKÅŽÒ¦â=ÜVÚ±‘Jc5ÊQÿÖqJ)oY¦Ö˜Êc³¶J›²Ê€"CÕê <6/þ0 Å {ªVÿÒÑ Ä4Ô÷gWµzéZoׯ¦.«€¤…6±†hºŽ¦¼˜”5´§Nà ít§;n®ŒðÊHTÙ}}Š~ºf%¬KðíHHmôRÒ|PJú§1(N ­µ¾3C($MA{°†ªË|PuY XÃÂSuy»•@HQOìÍ z`oöv,ʺªbCÕå ²¾r ¤¥µ2ÃiTÔ® ‰!q¢’5•–Qýª‚CZéb©›h…꿵ÅQl–šQiÈ/b]<‚ò‹T ÈPM3(rùSc'PluIfmâ’TLµƒ‚>¸;J<}™âçZ˜ø8˜QP‰b¬'á “pÖãÕ\Æz Ž6Œ÷xÒ)j5ŽÓ“Ѧè/ÍÆ\8KµW¿yÕ÷Oñ(› N2L(bµùÔÁ kó3:õGDÿšý·ÀÉ1îÚ‘´§ì~†¹©íN†¥!ö“=¯èÔÖÎÆåiJÛPO“’tÓì(çázjNDw•ö=»>L}§ý¤fÊ̤Êž‡ç±ý"ì…æÛ&Ÿ†øP#¤ûP ©§¾ ÇåCmqb³‹'†¸œõ GÝä2A3ćªà$öŽ4m]t¤‰\hÔ†àô£‰ÌèÓ˜HvkóùÕ©6 ¤ÓAˆŠŒh¿®BµEýDsužH—@©’ G¤JVWôsÁY¹è:„cGºmªD’©t3Ñ$Óò1[¢F& ÄÆX˺ë^³Âiƒç¦øq¿™’ÉÕì÷†¶·sEkÀ@p¢^ œ<“uz·3*nÌ~â>çDM™@í›>WSTp–V9Gõë 'Q+ô÷CÂ\æVH)8+{®N[â.Â<Ï£ì-ó<ßB!ú‚£Å †•ÂÙ‘ ÁеˆA|íM1ˆ¬9CÑ;"T …Ù6a÷ôÛ¹ngˆ»°~›onœ\úý<ëŸç³D- ÷oÿ~ ë„:ƒ; ôó<Õç; w$ü¾¿%Îe+´çñtKS CÜÌES©Dd7QzX‹þcsz«SÓ6%‚bláëkÏÄÐ1£ö"G÷È«¶¤4×>v´æ;bTGw„.BO ;BU•·§' Іïè“îètDˆ'Ÿå²:äoÈqÛî½]Ð2qGTBÇ8£:ÁÊCÝѺ儼É~dÂkù¼ú®³ˆê6 Ð…ûjO¸ªÓ<«€ÞÑV>&a©àã;₯º¦E stKÁö{¦×Ù#"2–¼£<=\ÛGVÁÈ£åbÔäUK rÛʦžïLjLþàOcwžÿœ‚ ruœö…3¨2‘çÖûOñ£¬çÛýÆ;cîáëØá88 ð~Vvÿ)0ÑÎŽ¬)8k-SÝÈkCÏj¾ßLkÝ@q>¿{œ¬Ç©òg+ê,Mò®At®̹)õg¬T—ŒL›»àY*ÒÊÔû0ô>¼½€ }²Ys´·ñ4!ÉÄÓËÍò¦>µÁ/w1~¹–Ô?ÍØu# :Ü©…eh#Û1R,F¦S*g³e…|ºþ<Ã_®iL墀¢c¤ØÍdy MDãŠN{Û¯gñl’¾/éä¬2YÖ©5ÔO@‰O²sªÇ,óÙB5¤µ©W>èÅUCÝÓÆÍÎËôR!m­Žþk‹‚´Kíå~IåƒFR·Wµp‹Ž6›ž¯CEž>H7tƒ‚ŠÝ²ƒˆŽ3Ô ¶S<*&;Ø£‚Ѹ¸Óá«jg(þ[¼b†1'\ms²0xÅ$b è^1s“ µàt¯˜Ã¯xO‰§ÿù­½!ÔfÉÑikÔðÙ¥^îk ŸÐâØ€ð‰ ÄÙŸ{žÍA6ÄwDå¡(žW´Ê—.ï˜0D U 1Iñ·óÉÔpê=z>št¶±3 fÈcÃ"޼u¦?—ÙüAEŠô‚ß|PðàÿP‘b;á•Aq; iiÜ]Ûª ˆ@iHIŸò΄S_ö›åiq~¢¹-4$¦[¾w´ó «]z¤âYDæ¶%ÒZ ɤwžÌÈz­ÜÊúz»4?@HŽÔe½ãLÞS};Ûö97 KCÚ ^ôÕó¢\$] ‹©œûÞ¾~Yí‰ØŸ¹œIˆ‚Ýcèû÷'ƒbF”0B‰ZT]ktº‚A%¦D×AŽpzzU¢ô‚Èv€ôüX#„Z\Ó¼&'µ É,¿‘V^÷Ó§÷;ÆuJ¶Å Ñ÷ާRRF›‰»ze÷û¥N_g0b'ÜâÍ2˜L<Ÿ1/®_Šöô8ßîϘôý©) õ¸æ/(@ÆÞ¡Z@* ]CŠÜªl›†òŠ…ÚèÅä2h!TŠQ¶£U¥ ²·ÛSâV›Ë´8!­\â#?„‹uZ¤MÉœß'GhèÌšR­•"•L)rY!iNR¬ÔUh/PÉT‘D›½®K u_f¢ÍÞë‘¢+†:½D4ô“ýeú=ц~¯×|uVEâŠógó)öta®>Ì‘ÊWYã ¤µ[ɤòͰ&¾ïþ»6íùè,è‘¶¦¤Û|t[Ì—O‰Éä5µ¤}?ÒÙE5${gêhèn­!ÅÖÒë,¬'‡†´TCœñÐCS<ÊêIʧF—O„ÊC’ªT¤Õ ˆ*ŸPþ.CŒ¶D3yE‚çaI*BD)¸ÒF¯jÉU-UÝR„ÖßfÔ¿Ü2$ð "EvÇoX§# ÉùžBziHK;•- òô•òrv? i妈€,†È@{–D±°š )²SDXÕŽ†»)ðô–nI8¿‘n¤hË;SMH/ )29ˆü£«"Å.Š)ÛЖ½ýtt¨Ù[ŵ|ç@H™ðR‘Vý^Ñ¿åó‰þ…uÿ)ÄûÛZ§ðv@¬¯"ªeY»®?Z²£@@2wf·MÆE¢ëúµ.s ¥¡½;±h$PÞT@@– ¼H¶wÿÛ8zèÚµwGÙ¿™vE¸ý“¼p š°ý Ú»‹¶™ BhãºÓ>ò ÐVmºÄßo›Ý«Ú‘HšôÍ/Iö(Ê~pY6êÛáBZØZ@¶EŠÑ_[@º"[H†ô×&.¤ØÚ´þ„X²j D‹¥ëžjÔVê.$‘Ñìǃ‹‘hk ¨=­ øHí imÎø@²ÿëU!Éš¡_qOçn¾ïÏ3û)‰9uO[m>²<=ÖˆÿT< d퇡å? =É–ÿ?P¢)ZX[þ¾wCE õž"1ñ¦ùÞuõ¬²1qAûPÔs…Ï?û\ Ñ÷Kj*ˆüi€€•’¢Y9SòÄØµ7P;ŠÕÞùx´P hi­Ù§ƒñN§ÙÜUrt£à%PP;’¯k)äó̳¿6Èw­õ¨žµâ¿vüwYj$‘œap;¦0@[>9ów'§™gl Mãl³7Îêf&cX‹šÊ¾ßߎ3ðZÞê©Äó%(’@îòXÕ¸,€€bk9×)Œ3¨@"•®k!{³Q_Ô×Í£º£DíºöÁ¼¤ž5ä¿h5òì²”=Öo…%Úr{ hm¨÷ÌÅŽh½ç«º#™úß5áœA=Ÿw ;ÚªJDg ~tLíz°£ÁŒü’z¤GZ€!Ù] tdb€DÒÄLbÊ…»ëv÷ƒÿÖðÉ…$GïLHOÂYK 6 W~~Î]ÏTSéÕþ”ˆáÉN¼í·Úî¹Ä? ÊVzMs/ÑÛsƒ[¨=­5»l¨;¼@Q„©zšëû¼zúVAíIF~í”Ñ  éØþ<[ {’“ËGÃA»=µ9ù+ÐéE sE¸Ôˆˆ‚\!I±—*oõË_nŽë"›yzÿ"i.Œ˜=Ÿ&62bh;0ò§€BŠRçªæÜH Uy… bsµïEÿài9 Í$a§­°º¾ªBJmy;B& E;¡ „´² ÜaH¬= ÒZy0Ò#nm ¤¦G ‘ÚÒÖ¡GœúËýP Œ{ñNX`Ý‚1‰…Ð$ö&MâÔ`4WêP‘©ÝPÇÎï¸ÍÁ0Òpgò‡â*K+°]™JàP飃J¤'.$BCЇ3DYú@g†¦¾;4BZêmK©\`($wJDNdüiÕ÷†óâEˆyqíãomK\HkÙ ´›´ÇĤ="u „´±v¡:m^´ålCjaH‹Ïø.iRjµ'éSlºFè£l…æú{º‹…5Ó–Î’ 1¥¦Ì«.{§®¾ *vé²w\fpPKgtŸŠÞ *Ñ‚î’ûQ×ù5Ôûåj³Ò¥º£û¡# ѬúûW„Ý/]Ò‰† KGn#~ |V™´o„×6·Àw©>+Mø’\¥U… (¤Ïj¬P0¤¦)P„d‰ä‰îåHRøîw&1|œo)1t'*&ëNvi VæîdRÌÕ¥BZ÷ÝÉDoq&EoñW[‚ÑÞÆ…Ô\Q›CQÄÖ,æEGûº Vf#ËPÑ áK¦Š$dV¢>è”AQ橳U„ÍË hîGYCA ÆÅˆÌ>.†O¡ñkPÚäÛÑÀ íe<æR(J† P+!¦¾÷º×ôV¸iÁˆ}­xM³Kï5=Þj\¶P/XöFò2©(e¸Ê³ JDö~?MþÅìÚ¼P%}eß¿.0*fîŠ]½+°»’±=³ãåŽTdò¼ðz uL1TìòšÞÛꊮPPK©?ïMúóáÈ"ÑõçA~,ªÎê]E+³þÌD#‘ƒJ°»Z«q·aò%˜=Š·®û06Ñr/³¶h1޽l›¦^ÞJ ´Ÿxƒeûaìœî§¸ž«'ñ wJö ëTÌ3Óxö sQÜêâ†çê N×yßãÈ|1ŠSbœXúAöš¤Å-ë2‚³4t¤%ìNâœÒ 'ÅxGú¥ƒëìp¨‚³E­Uœ[ŠpÖvçQÛ†¼SgÓçn‚x,£êTÖ¯¹¹[ ÎVfníÇœgn]ÍÜú õ~èƒPºFß-yHí{vùÄÂ4LÁPª˜µÄfGUžÃE† ÂA©b^ü©w(öTþm.ŽHt®é*/]‡yÚO¦¬ŠiÚ Q®öñÖ+UU" $4…nD_áÍfÛ*Ü}±A‘??”k³tù²¤ù{Ǽ­+  ­®—õý±®Ý´µÖÚe…„ŒµûÑŸ£oqvŒ¾oGb¦W@ÔÐõÿ÷<î*àÊŠ<p·[ „Ĺ稀;Ë.PT£«_5B-Ø=- uiƒ ¸ú~â¬ÂíoªKËpš•2+H+Ç|.rWl75Ò‡ÿÅzÇh-×CôWÈõP"ó$+YpPþ­Í(¶º‡hì÷ ´4O—’ùÑpw”xŠ«®¯h¥·òë«•‹ÅzBÄ0€‹³'¨þ-ÖÓ!´(¼.›¶@iapbÕJ¦1…Xãrø—n’˜´|Çe·€8±½BŸ0ï€ ýÈLo†ž-íP3»ç@d¦·OcÿFè­Á‰õòýûÁiƒçÕ¹u¤ÄNÙ$Y­ïv®hÖ5N4lyÈpòLfÆßΨ¸0û‰û(¤@aoy˜•¬NË6ðÊE 0œD͉Ü-Á¾ÌM©UpVöèXKCŒE ³ŸµµeÕ ¡>ªàH/ÆÞä]Èš3ÔýlUoɰþ,;n ³Ÿ®ôqÐypàf*›z>CˆLho,÷ho³œ‚Ù²uN#UpRyn½`À²F08K5æ;r¾Ž Ž#÷˜÷æ:·•©s,–ˆü'/Bp"½¢ÊÁôèÍ€|nªê‹¡‡ ›ê;óÝÁ‘AuøÃ&ÌbQ08‰uìË#LáQpV¾‘öefÓGÚ·+‡Œ´/¡¼#íÁ,#íËy#íã‘öm„diæ´ÿ>ÒÍiÿ}¤=š7Ò>i‚_î„‘ö퟇}ÇóGÚ•Aÿq¤}øË:Ò>ü=¹GÚ—óFÚÇ!#íÁNÏ2ÒÍiÿ}¤=š7Ò>þûH{4o¤}i9=i¤=š7Ò>þûH{4o¤}0ÒP§çi’eþûørÞø8düìk2 €wNÕ-÷4}ªn‹"÷kúãTÝ8dªnè=©1OíÍOûû\Ø@1žte˜˜YΛ˜Ï™˜ÉS–þ813™˜ðžô‰™Æùˆò+:ž„{„pj|*Ë´ÁaùÒ__Í7À³ QyÈ+żj›öq?CÍâá´-:GbÏäÜIœÛ±9=Žmõ "‡×’ÑŽí4}þxÎ8]‰På§Ó¡mQ}‡b9&_û=ËT=^㤨ÊÓk‹À€"¾£õ\œ.':þŠ=ÕGYV猈‡æ ñq´ß!=:²¡3B5*ªæxËÓ†'ˆaf›õP›õø‚JÜ:0>¿gR]_ȳ˜`µââOÕ’n¤È5ÌQÃÿmo·ä¨î{ _Ï[õÛõL tÒ‡sީ깄t¾“8’˜ê«Û@ÀØHÖzïÙµ«VÙØ’,--±ì@„»ãm+Ñ´ô¿ ýèn¤ÄqW÷‹éÃÙrV–T`çû`í³C¤Ø’ãžÌ=Cºýœ@ÑÀËjï×?7RäI¥BxÜH½×Qs—ôyhîRØy"õ\Óð@„¥mGHÉøåÒ½”¯¯û#Þ½húí’öÞ.Úæ ‘"OŽN\'b›”§FHJ}|c^Ì:Kܤ‰¯2+²ì~ BJg/èm1Bjºw^U¤÷¯‰UØ)mŠae†‹íñx(¨Vý÷E=º5m š˜rÛÄ”T'b­Öô­Ö”žë£wnÖTyñ:ïŠ3Ò§û>fØœÆèæNeŸ‚¢JËÍð¸a÷ia»¹¯¿æe«DöMÙåùªœ.#BZ:œ{õ~vîÛû»Ñ:uFV¤Í,iP6%²Ð-Ç£¤[ z$ž✥D@Ñ上{Y­ˆqA÷9±ÝxçÊ5ã*.E–Ò--s1*‡k€R™MŒ‘Ö@Èäs}8éò¬ZÑŠôéæÊöæb4C¤/·<ƒŒ«p­]@\–LH ÍùÖN½•>Péö4¬ rr¾ª·YšíÝbáB*X cP¸¢)Ýn&¶’Át»ÝHñ”rwƒSîv#-'çŠX£ÎCöt“¶ü~Ÿ¾]Û‡zÚGZ!Bú°Ìé!ÕïN"¤•½ñ\#ÕbkÒÚÝÙ•d§üs4äÛì^3Wä îDHÑË“&WHÅ•kŠÎ^&²¬ BR6âWþ3!Q7AÔŠÔÖ9^ß›îcÔhSÚHEñ’K" ž`« ‰T§B¢Z°•jEñ¤q=tñp@›¢!Ðr(³ÝŸ"Y ÃR­È¡K­”©€>ÆòˆÅã° &N £ÕÚJÈ+¨`#Lœ@R­ˆ › O5€øwóOÏ:>7ã®j5v~És!‘¦!²4rUö·µ Jò¬Û®/,þ±Y¹ ïH=–j ‚3AOªJÂ,CdiäjÒï9Xqͳ;/ä=#úF‰> ÿ6æ0´Ó¨«Ãð# ªoô¡W´iG4Ö[¯HVÿr 3_{c[Ñ£:ßÐúMå Qwi¦k×+*Ô èÓÌdݼMkR@uàp£º°,’½)o‘¶Oìk)²5r½ äkµyM(I„½M€UŸ©CºoR<=¨,CÜùi9–!îœRy”Æo˜¾û«žK'"û°°xt+ÁãkNµ&íÒ¿6ï³mÒ¾üyPYñÅú­§âxh%ŒòjçžeõŠ¡:ZŸõmŽn»{eZý/•¯ýÓõoŒgÝdüGR­)ZØ…©MD¤dº"í¿MHͤò©,Äy"þ‹,Z_¿¿Ú²òNM¨RÏFÛˆR¤‘¾FÏ¥IfRP!ÅvÑÀfM^ËEc³D#¤å0Zá¼óí¼úP%ÕwÒqQ=ˆdE¤d%Õš>Þ&Õ7ž° ŒŠZ25ωV½!HjØRã õ°¥{µ2I„´žš_Ø 5Ï"¤Ï‘wïÇåU!µ³·þZ¡š¾*¨…#’zF¡"ÛÔ“ÖqÜx™’­*Ö~cˇòü¼Í©îÔ¦ÄÙƒÚÞ%”ŽºÙoýhâRÞJFuMˆ4t½æ[8ݱX9³%¾¶5†Zw Ä]orLœâA ÄÿtÏÊÀù6D¤•B È Ž"û´å¦Èæ|‡HñÔ½fTlÀ£c„´f+ûÃoC’ˆ#$W±$]“ytl¾­vâq(¨,3ŸzÏ›ü‚.DŽÖ® ‡ŠU¸>;6„ºO*¦îSâ¿Å4¢EJÍÍ ¡CŒ&f4g/ˆ1BŠßÛ)O§cû´Þ ~©^ˆ)Òr<=¡G½¸sÁ©Ü”ˆ´òñw"¤vR fèÂ~à Øçå Í !­ºa8ª‰A!)á ^Þ³”!­'‡áD™ –a3ó#¤ÏÑ`ö^J±„Ê:oìå°²//ÏTPA-&5Zë±Ü!ÏŽ…1`ÞxvædPΰùÆÏÔÒY݇jÎ8¡’QÑÝX¿:£½gòLe“–¡]ÕÝv’ì°¯ÜjG£;k•¡øêå¬Î&Cq2•×À{rVCç+¶ÕS*Ï3Á‰¢.;öP4HRŠŒ i¢’§rV¤HÆù~oln~?^©Ë$b6C’N’ éÃ>$ɸù*t)‰VݤÆùj—Øt¦ò’•¡¡Kôž³š@Êë‰.9Ò§ÝÍ7­Åõà§à`v0/¾•ú=N˜^s!eIf$ƒŒéùÔeL÷×Bf%Õ—ZD¶)S\‡uÊ”StÃKÔ…øÞ@÷ª6édP£Ùñú}Ý@ÕD“¬ ‚Jú/FcÐ ¥è-g¥“ΪI:k¨¤ójÕ…–!夫Z[uM tæyz&»Âº²÷ÛV`Õ¨WNv…#3~ì¯-¿x¾È'ÙšÚž=ñrã÷ûŽlU‘-ó¢új¨ý–“AÅ®¬é ª9ç„ZšøùÛ?_Ø‘î[%ãø¹Çeù‘ÌGn}ß’1ª{­†5ª>'òÂ34óÉÒKm·µE3]6²µR[Ç»ÔÔËkƉÖ¿Õ+›õ4uåÊM•’oy‘"OC<Ö×ÔSaL±›ŵWŽõ¼ñX_³Áùîp ç©ÆA÷¼Äc}ÍáÀÊÊ ©}+¡ãÓ8fÓæ{”o©q€ŠéÓ8É[åõ-2ªÏÁ]¶‰Çúš]ÙuˆsÝr"œÕtò¨,CîilÓ×ü;¬*þÌ!+žDçú³dêÇ š§sÚ¡Cÿá=5CÝ¿,󆙄vÉF¡Ã÷™î–VÅsY½Ù³<å4@‘¥ƒ°×ª˜ Š(ötÂäP@K§j–4Ó,FóÜU33ÔX5ö5­¸uª¨äD@:R،їæàe’è0hÁÐ/-èQî†.Ÿe5'q_ù‰\Ò­; æ0h æ0\÷Õë//h€>§†q©^;Ð0.÷…ý3Ùkwf,¤d€Œ$ P<™H©Gñ$R†@K ç»×ÅE÷OsL¯Æô1†ÚV9 êK‹Ç„ˆ~—Ÿ;œ ¶´xL‡STÝÒõ8Ű×ëpèe÷Jî“‹B^ã‘Æ¿Æ-t©€(€ãz—„8ñt‡~)³€ýÈ~Þ,ýùN@~d?o­%üZ ‡“àÄãÑÜÝýá[ÉyÐkoP;•ß_mÛ[z6ìî둉« Á‰ ÆÒ0x=æ5=™§WV˜¨Ì[ÊhÖ³œ´µd8Ét}§”µÚsØk<²ü[òxïûÔØ'¬}à¬&Çß> ±£œQ£ßtÞ×UtÅøú¶e1ÎòHuZvofu/Í”Éo"›ú¶¶F”×à¢qû…ÜàÒøVþqë€t}OíÛ=äÀYÙÇkð¹—D8‰M´o¶ óÜ8 êŸT„àD–óf)õŸ·ÈrÞ,8Áû6t@]ãpßÖñ>YPÛßïöáM-ЧwÞ,Ekº}û脟^—E™6óGr‘t/Å£¹NõSKŽóÁUÔ›oËR4)ÇPO c!½)µT»wìí^Ôû0D2å›_ë#¿Ø2l³ÿ)™ µÏ]C¤[YÚë1þs!Yº,zï|ʳ·ö4H¡S÷#¤OÃ?·Üܺ9ùЊ´í)³-{Q!õú£†¥œ,´99iÛ×Põ)?T~©-·eévw¸à›ýGHË¡Ðì™´©¹’ܧ÷GËT"p›…Ÿò>ÑsÂF„6¢Æmû7I‹®?ª<¼$BZ»“Ž„§üÓ-`TõuÞ\S„ýµa¡£"Û‚÷*¬Íé3§#köËZ†½§[§!Åž¶¥h¥ iÙ5ízmKjA^qé£Q%ÖÞLtfG£RìÙÒëða¶\>BZÙë‰M©%H»s„´v7žUQ Ò§§ç6kÃysÿXazD¾[q¤ZÔbáœC ?9†Š:¢˜ŠQL½l^¢~ AEo¦Ïad7\H]¨êeØ…úŽ»ì. <Ñ;eºiä!%RÒµr(Š^ÏW 0}Ñ…òýýmfÿ4æ¼™NQ=ÝÓ®îw¤•­ç!íõ<Tßií6çÙöDµ{Ÿ“¹¶KÉ‚¢ËÑÍýc!ì§=Âþõy¦‚Z¸]G¹å7*¨ÈÃ7‡ æqBÅnßQ¹Ž#ÔÒ9P+ÜwDïtG®ªDS*þ[X²b‘,6‰d-,Y1G‰…<ÆY1;eöÌÊÀ†›Ø2ð|2¯Cøzl$´ É6‹^µS®ß‘–c‚’-Å\ÓyRÌC uòTÿP“k1EÁ:×ò¸Ë-(n€šgo¿ªÑ/ß§]õdûsâTHјГö=Ù‚!R<ý™² JÀI« 7÷v”»_ðÅ[ƒ´°6¿Œrb4˜Rä¾MÀ–.¤Øµ”ßiXóœ:{xzœ¾¸IšˆášÏÞ)²Õ=Ó^ÝS¤èÝKl6ÂFs®)K[väDHÓd¯:Ž h½!Åc–BÚc)ä… \ÓˆðÕË1wß) ‰b‡HÑtF•!Åî5$u"ËîMäÍÃX#¤È}Êñdþi`#6¶ä[%k„ù¦¬v/ÆOYƒI;Åè)kL+>OYc¥ÄLY‹ÁSÖ pÊZ ž²¦ SÖâ€)k ggŒœ²Æ%cRÒ­=ãÜ`â)1vÊZeÁS¢y¦¬e'3 Þ)kŒjM“SÖÊꄃ§¬Å˜)k ”ŇLY+©&¦¬Õö1e-†OY3HÀ)k1|ÊšF‚NY‹C¦¬‘ò‰)kÕš0SÖbø”5ƒœ²‡LY£:åþ)kX眲–qI䲆µäŽ)köágT@Kß87ìiOY£ZÑÄ”5e‡ÀSÖbð”5 mg‹ÁSÖ4tÊZŒš²Vž_8e-˜²†= Ð)k™ òNY£ZÑrzTXy~T‰ (±sËŠ+GŒs‹=SÖìãܪS÷#`ݱgÊÚxœ›^tœ[ ž²ÖÁ§¬Åþ)kƒÙg <û,ž1em0ÏÍ ç¹Åð)kzó SÖbø”5²‡LYÃzÙ‰)kŽé]T—I¿a3µÈ>ì“ã”ÿOŽ‹ýSÖ†“ã´§…NŽ‹½SÖF“ãL”œû§¬ 'Ç)$ð䏨;em4ÏM'è<·>eÍDDÀ)k1nÊZyNpÊZí£ÏôîAGŸÅs¦¬}[¡ Ýâ )kØðö”5mΡSÖbÄ”5mÏ¡SÖbÄ”5œ²#¦¬)(ð”µ1eÍ|+à”µ1eMo`‰¯mMOY›˜}†ÏëMNY›œç–Q!y¦¬¸yÇ”5ûì3´©pLY³ÏsCŸ>ð”52¤‰)kÆN§¬Åð)k 8e-†OY3W8e-™²rö@SÖÐtè”5<bî”5M€NY‹áSÖ4tÊZ Ÿ²¦‘ SÖbÿ”µÉÙg°NšØ?emrž[¢!y¦¬•™(ˆ&¦¬©X|Ýè ¼SÖè &¦¬©@ lÊZŒ˜²f\p>EŒ˜²ÖòÍaSÖbÄ”5ã;€SÖâ )kt=qçªJ4¥:e-@$kæ”5“Ab!Oà”µ€~‘YSÖL^‡ð;%õ Ø”µ3eMµSÖâ€)k÷ 6e ý4œ9eÍ”ïSÖbø”5Cè È€§¬¡?xÊZ¸{󧬕‚)rß&à”µ8dÊZèwòMY3gOƒOY 4Þ)k]ÝSàwoæ”5EYNY‹C¦¬eTH“SÖK8e-†OYSß) ‰bÁSÖlĬ)kfMI𔵀ZÀÌ)kê”ãÉüð)käñ”µ¿_¿ß¦9X7œ–5AFä‡û 4*li^ÒŒ* VžT¯œº¥ ö¤H¯Èh}™™ÝË•Â+LË;G…eõÒh€´yo.Fû®M_kJ¤ȇ³è>t»Åhd9W:²Õ+—hå˜ß%ëù]eN¤ôÄ6¿›Á`#V»ûýúÈ’HOPú•…% $ŽNaOÍ5ª,^FtcMgjþ+©¾Ò˜»ïÖÜ5ÔCc…®ù¹{ Ë@–è«o/žÓsgî,S…O”æt{¦Ò-R¿_ï:êÎ*ó}Hi€´¹ûݼó]5På‘JA¤ÍÝPƒCU©$Z‘6wCY mî }â •ÚX=´ñÝ´vp¨f±Ș»¡ö†2w÷ìç‰.¬®Øý~Y kV¼r¢cg vSÊYI„Ôš»ÍÜUÞâtÞÆ Ì]/Œ¼ŠŸ°Í Œ{7w]t—æüº½ÐÅæ*m¬WéÊ@- åØ8ôØ5ç4@ÚÜ Ó­æÎÅŠ@æÎnlwö‘í²œh5¾²½ +ÛÑÖ­ÝZ“%cD÷ès›°¡zÉVfU¢O]4ÊSO=)Òº—@’àD®3—BUN§qômŽVP8×Ú!?P4VÊiömcÝ·ë–ÓàD®—XZK¾ÐàÄv……Sû‡’giŸme¾ÏOŽé¢±RÎd\’BUÁ¦q>ÆÙŒÎ å‘‚RvKKo}ôæX'³0ºœ(rÊ–°<à ¶W2&®—d`å.¥Zz’ ç3£R‡NOËýiú[ëz³úFû+{áŸä‹1¹ðöï%ÄîD´rJG¥¶jÿ¤îFFôi PÓ^€šæ?XGôŸÅ³N¨Ïíž(²Äi/n„Õ´@±'n„•é@KK8—öÂ9ªÁ9€'c2 ³5ú…Y¼s{é==äyHø³†s_Ö°±Zþù5žµó~:ÛfÀ1Ó8&œ ¨Ôá‹çWæÆSá\ÿû<Ò-6á=À‰Æß§ÎÕ=é48&œÛØÂ¹:»Érœ¥Eð® ·‹W–Ó¬ÇÎeÀAÝÓ8nï¾~ûÖQ¨§ÝC?]{O±ñÜ)²äkÓ^¾–eTH±Ûù .¤¥'íët!%n_$^/A„ôá¤`8£ÒÊò¨ìn´qi9âÛ ³ “¯~XŸ…(²=ûÓÞ³Ÿ!ý‘îúúoä)&öØàBŠæBŠÝkj±Žùh÷¦¢.`o£ )rQxÉ!I€ú£Bl?&›l»Ÿ~Š8eÕjx÷9" Ôt?÷«: ÐCœhE±N¿Z Õr£€8¨ëZ:‹åeYRmy%Õò9?ýìz³¢Ëõv8 “ô^¼Ÿ…ßVœÛÈIp¢ñR.½Á)j©fe¾U7èá¤Ró¬då± Ái(«5·å_r®bý´¹Cö;ÉøHsá$ góÝàŽçTɳܳ,?f…ØîhÎÁÇÈ&¼ƒ}ÎxÎÈöüöMBkœÒðçÂ1çíëÛzÞ@$'Žã¼ÎáçíÝðLdˆó¢Ì ÏbüFz·Ù½{ðâ'§ŠÜ6ôs¹å…k›M´¢¥Å–¦=[Z`ï궢ØB¤™@ª.ñÏœn½sÍ©»\³2+$ PÜ3§ûS9Qæ´`"ÿ©Úœ<ߨàb4x´8,¤âFr|¥ç¥þJò‡Éɺ­™åä<$¾µ™š9 Q«Wl˜ (êÚ=‡!j›%èŠ,Æ:Ãöš­P‚Q+Ü‚hj²)ã¬z'_®?Øod QÇc™Îõ2ÕÙ…9™aEɹpâÑÙnC­ú…|û }Ý¡1§®Ù·c.ip"'?'¾‰w¨5±œ1ôUµ…@ï6¡û@0©'Ðô‰»T/Ö€†@Y€Ý¶…@ïw5íÝU èÒyš ~ÛÄ-;w‰Ûsj ¦W$sìa˜ Æ÷èfìÃÔq8f ¤•-"~#lM¸" ‹¼­8oùá¯aU-žœéý±X†Õÿ"_Õ×{oN@6q™\à R¥€ Jh9|}TYF´uKw3P­ A”teÿzŽ‘)÷ÖsŒÀ}TN ®*ñ ´êÒê¨yIh XÖh=â›{Äj Î'ß­è³+ð½GÝ9“×í!ÍsAta}}TeI…äë£bT\7|mZZâ¹v­ŒÃõ"Ž€Æ‚7${ÕׯTYê½ë€ÄÏ1Íi€œæŽ µÅ Ôë£RWIõQ©«ì£rõú¨4ÊÛfˆ>*'P¯ª]Që£r}tíMskor­:FƒªSÄÔ°åZ;í*¬Ê ôÙÙÕ÷_cîö×Ö®Îé£êYp&_‚ É×G•œ¹‘Zs·±™»§ÈYÒ°êÍܩڄ2w…H9 1w^¹1w f•¨×Ge»³ >*'Ðr|gû@ >*'P¯ÊvgA}TN É>ªæ&Ý«ÇÑŠVS­êÊîn¹ òõQ•ažbÜGeÀýM kÕoßQðÔ¯å‰\gØGåÂéõQ™˜·ëöQ½áL÷QÙ¾¨Ê…¹HÀ>*N¯JáèQ)¢Ê…Óë£ÇtÀ>*NâŠK€}T.œq6£sCé½à't6ÃÖG5™Í•z@¾>ª€7˜­êkÓ®¨¾©¼IÊü˜Ò--6®—d5l9O’R®t}ŒßþêÔ©·¿Ì_‚È×GÚ‚õQ‘}ZÔÞ{¼àé ëˆl}TÓ*„ÈéŠ,qcÚ‹!}TN Ø7Bú¨œ@–>ª´÷Û¥/Aäë£*K" Q8Ç;·죲„?¶>*K8ë£ráX¹Τû¨\8=†·ÉÌôÂX•ÕOï[/Ì‚õ7¹p¢QØØ?°~-N¯jÎû¨\8½>ª6sÖ…Û°>*Ž;œËð¯}kÕ¤wàÇ2T˜è£šLׂ8ñn¤È’¯M{ùZH•)v{"P•iéI;Bú¨ÜH‰ÛU®èE„äë£B;#WÕø;û¨†HS}TÖW?¤Ê ÙžýiïÙϰ·ÉÑGeÛ;P•)òÅQÆÌ‰Ál eƒÄ`6ˆ³Ab8¤¹J`6H gƒ( ($†³A” ÃÙ Ê AÙ 1œ ¢€lÎQ@P6H gƒ(seƒÄp6ˆ¶àP6HÂ)‰lÃD[!($³AŒ¹²Ab0Ę;`~(†³AôU²Ab8DÙ 1œ ¢ï, ƒÙ ú&AÙ 1˜ b®, °A2Iô9ÁÒh¾˜¥ÏQÕ:0ë$³A” ƒÙ ˜ ƒÙ z߀lÌÑ8@6H fƒ48`6H fƒèïdƒÄ`6ˆ>o@6H eƒ˜l ƒÙ &›dƒÄlülÄÄ$@6H gƒè$ ÃÙ &ÉcƒÄp6ˆ~ûÙ q„m— B4ÁiT$³AÚ–ŽŽál7ÂØ 1œ bâF$³AÚp.}  /ÿ,šÇQîʉÁl…eƒÄ`6ˆÂÉB’M³Ø *\€²Aâ9ªº–ïeiÄsTu-á”uƒÙ *£eƒÄ`6ˆú>P6H fƒèó†íÏcƒïdƒÄp6ˆqÀÊ^Œ`ƒ˜|-Œ #Ø ÚÙ 1‚ bÒŽ06H gƒ_dƒÄ!l¬3šÍÑJ $†³A̫ƉálöÙϰ·i.Ä<ÈKôÞÍeƒ˜',Œ #Ø ÚËÙ 1‚ bü_†¾MsÙ Æc ÃïÙl½& $F°Aôš‚|†m÷F3–fÆò 1c™af,¯3–fÆò*hÆ2ÈŒ/Ñl2増³Ø ýQ¬DIv,g±AþoVvÉmV¢´Aà3–KÌŒåbÆr‰™±¼ ›±Ì¨LƒwÆ2ÕŸš±Ì03–WˆË 3cy…˜±Ì03–WˆˬDiƒÀg,³¥ Ÿ±ÌJ”6ÈrÄbî lå,6H˜3+QÚ ðˬDiƒÀg,—˜Ë+ÌŒå3cy6c¹¤ZÓÄŒe†™±¼BÌXf˜Ë+ÄŒe†™±¼BÌXf%J>c™•(møŒeV¢´A–6|Æò 1c¹ÄÌX^ÍXΈŽ÷ÄŒeV¢4;À3–Y‰Ò ÏXf%Jf%J³Ã;cy8Ë™•( ðŒeV¢´AÀ3–fÆò 1c™af,¯‚f,ãß`66Èh"1ÃL$^͘±<æÌJ”6ÈrÄšd€±Aà3–KÌŒåUÐŒe|j 8c™ hbÆ2ÃÌX^!f,3ÌŒåbÆ2+QÚ ðˬDiƒÀg,—˜Ë« Ë,¥š˜±ÌJ”6xÆ2+QÚ àˬDiƒ€g,³¥ ž±ÌJ”fxÆ2+Q$àˬDiƒ€g,³¥ ž±ÌJ”6xÆ2ÃÌX^af,3ÌŒåfÆ2+QÚ ˆˬDiƒ f,³¥ ‚˜±\bf,¯Âf,cÑÜˬDiƒÀg,³¥ Ÿ±ÌJ”6bÆ2+QÚ ˆˬDiƒ f,³¥ ‚˜±ÌJ”6bÆ2+QÚ ˆˬDiƒ f,³¥ ²„³A*+„aƒ$`6ˆ²A0DÙ I¤$Z‘— R}£ 6H½u’FfƒÐ­¦° $³A“6Hfƒ $ aƒdDÉÏ¡:àSlc…€lÌÑ@P6Hfƒ( 0$³AÔU³A0DAÙ ˜ ¢ lÄÏ4´‚’4?dc5àPÚIfƒh ($³A´¹ƒ²A8D#AÙ I„Q¡ 6ˆ¶BP6Hfƒsdƒ$`6ˆ1w@6Hfƒ˜«dƒ$`6ˆ²A0ÄÜY $ÁLŠÁ°A0Ä\Y $ `ƒ0¢M°AÔ7³A(ÄàÙ ” ¢q lÊQ8`6Heƒ˜}²A(ÄàÙ Ém~ù@á€YÉmqLf$P6ˆ9o@6Heƒ˜w ’€Ù m6ÆIØ ø7Ø,6ˆZ˜ ’€Ù &Édƒ$`6H›d€±A0¤}ûÃØ IŸÚ²A¨€&Ø m€ cƒ$`6H ÂØ ˜ ÒÆ06Hfƒ´q#Œ ’€Ù m8cƒ$lŒÓM°A´;‚²A(Dã@Ù ” ¢q lÊÑá” ’@Ù z=P6Heƒ˜ïdƒ$P6ˆÎhAÙ ” ¢¿” ’@Ù æ¼Ù ” b¼ ’ÀÙ Æ=Ù œ ÒækalÎ1žÈIàl6ícƒ$p6ˆñE@6HÂÁ:£¹ló¨²A0¤}õÃØ ˜ Ò=ûÒÍeƒ´ò½w3Ù íÆIàlãelÎiý_†ìæ²AZcƒ$p6ˆY ’ÀÙ fM@6HâeƒL<ÇŽeõb‹>ÆÏ±·4ÚDÁW²êO†3H3š|#à“oÖ¨É7>ùfš|#à“oÖa“or ÿä¢o49ù&‡“NÖ¨É7Ô@““or8»eš|#à“oÖ¨É7>ùf8ù†èÆÎ˜|Ce„&'ßøä›5jò€O¾Y£&ßøä›5jòMg·¬Q“or8»eš|“ÃÙ-ë9“oFir8»e=gòÍÆjÀaì–5jòMg·¬Q“o8|òÍ7ùFÀ'߬'ßP¡ÉÉ7>ùfš|#à“oÖ¨É7>ùfš|“ÃÙ-kÔä›ÎnY£&ßäpvË5ùFÀ'߬Q“o|òÍ:lò ÑaøtEà@ÖÉzÆä›Ñ„΢Yc&ßäpvË3ù&‡³[Ö˜É79œÝ²ÆL¾Éáì–5fòMg·¬1“or8»e™|“ÃÙ-kÌäŸ|³FM¾ðÉ7ë°É7œhrò€O¾Y£&ßäpvË5ù&‡³[Ö¨É7>ùf6ù&§òO¾!šœ|#à“oÖ¨É7>ùfš|“ÃÙ-kÔä›ÎnY£&ßøä›uØäI49ù&‡³[Ö˜É79œÝ²ÆL¾Éáì–5fòMg·¬gL¾ù²†Y0ÖÉzÆä›Ñ„΢Yc&ßäpvË3ù&‡³[Ö˜É79œÝ²ÆL¾ðÉ7kÜäŸ|³ÆM¾Éáì–5nòMg·¬q“or8»e›|#à“oÖ“o$Òää›ÎnY£&ßäpvË5ù&‡³[Ö¸É79œÝ²ÆM¾Éáì–5nòMg·¬q“or8»e›|“ÃÙ-kÜä›ÎnYã&ßäpvË7ùFµNÖ­Ò:Y#´NPëd¤u2ã!Z' \t‚˜|#1$1ù†hròİAÄä×:Y#´N Hëd¦uzZiPðéÉ7®u²Fhh ˜ÖÉ¡u¢€€Z'k„Ö‰ºJ`6H‚˜|#1l1ùFbØ bòÄ4Ä䉡$ˆÉ7ÃI“o\ëdÑ:ÑH0­“u˜Ö ÕŸž|#áZ'k„Ö‰1w ­“5BëĘ;ÖÉ¡ub® ’ &ßH $AL¾‘6H‚aƒÀµNÖ­seAZ'ë ­“ŒèÓƒÙ É6È»TºÄ°Aøä‰aƒ$ðÉ7ÃñkX.`–†_ëä{cŲNÀZ' Ìk˜ïdƒ$ðÉ7ÃIà“o$\ëdÐ:i³$Dëÿ›9ùFµNÖ­“d²AÄä‰aƒ$ˆÉ7®u²Ò:aD@þÉ7D@““o$\ëdÐ:iTˆÖÉ¡uÒÆ06H‚˜|#1l1ùFÀµNÖAZ'Œhë&'ßH $O¾‘6HŸ|#1l>ùFbØ É6ˆ%Ì‚²A’9lË9€²Aøä‰aƒ$ðÉ7ÃIà“o$† ’À'ßH¸ÖÉ£ubÜÝ›`&ßH $ÁL¾‘6H‚™|#1l3ùFÀµNÖaZ'ŒêìMN¾‘6H‚˜|#1l1ùFbØ fòİAÌä‰aƒ$˜É7ÃI0“o$† ’`&ßH $ÁL¾‘6H‚™|#1l¿ÖÉ¥—"xúù¿ÈRˆíçÑdÙ×} Z;gÕjUqEh(ž €²Ôa@±N¿Z õ‘Õa@Kg±¼Ö£4@æ•4lÄV+º\o$Iz/ÞÏÂï?+ÎíGä$8Ñø )ù²§(žÏŒ'¯§)Âêõ¤\ðÇzÛ·}Îhp̾}}[÷ Ä¡qáÄŽ d^”yÀÁ^Œcðw›Ð[Ѓ?9 Pä¶  `ß ;ÓhµMHi€––»šöîj±C~£ÿl*Çe½^3 È½¢‚‹]Ð „tÜ#HšØäsã)±Ï÷yâ67¾‘#”Öo±çþT4@‘ú}wãY&ê€ø±“9ÑŠâA¥—±®Ò»½¦cD+ò¹ñji4@‰ùF›·PKoÝåúså8 «ßȯ¶³pN¹ Á‰œì™‚•eN‚Û÷M¯çp~± }Ý¡Q„ªöÿðœ'rrR–e’ÇçÆ¶Í¿ÙeO•ñáÈr/ýn||â.UT°sP7`·mnüý®¦­M¸þH~ÄM¹ñß6¹Õ¬H'·Ì©ÝO®HæG4vãã{t³?@7žUn²¦d–ŸUÀÝx2ËwËúi¤€v… Z‘ÇoR‚vã@ÛÌpãáÍÖÝÏÇsŽšvã–³uã ÖgeÉIpznܲoP7žÌqãï£Õ¾Ýx‚uãÀ¸1Aºq–ìI7þ®*¯lÐ'h7Žß9 :½d–Ÿ}¤Î\qZ>-¥£¹noNnܶ"`j&Á»q¼ý»ñ,ƒ‡Õ 7¾%Õå广A/½•ß[’êÐ}w’D@>7Ëk­ðn2~Ö ”L¹#ɯñÜ78×ÁSŸ‡LêpáŒ_ãm²»®éä>ÇïÆÕ¾sIƒãsã°d÷ íÆ¶Ý÷mB÷î»ôÈi€|n½sP7`·½n\ÏÕaˆ×ø ïÆÑæt†ï¯ø_¸q´ý'ÕK@@¼øcÕ¬Ÿ3 ¤®ðâG7R4Q†Ï¼ ïFŠ'êð V‡w#-'Šn Vˆw#MȬ@þŽ4³B®@r'ÐT‰\ÁJäN x¢v­Wª]Û€FEòa1^ŠñN ©*¹Þ:P•Ü ä-“X‹KwU•,žÕ§*òÚ:€ž}n¤Øm@%y7ÒT©Ü\ZH©üin­ÜÜZH­Ü¹×*–[‘üÕrsŸ Õr”÷^‚Nâ…^- üBw#M=Ñì‰îFò¾ÑaV"ä‘^R­iâ•^2¥¿#Í{¦k Ø3Ý ä}§3" ©‡º:x°‡º È÷R7[z©;¼Ou˜Ã x«œïyuc u7’÷µŽÞ<ðs=ÀŠÏz¯·—ò^G?ØÑ¶uæ‹Ý¬ ôb·"žìhS4áÙ§fwf ìÀba#FÎÞ #`ÚjÂÓYˆ”…DH“YŽÈB,PYŽÈB,PYŽÈB,PYŽÈB,0YŽÈB,0YŽÈB,0YŽÈB,0YŽÈB,0YŽÈB,‚²xëÍBDH“YŽÈB,PYŽÈB,PYŽÈB,PYŽÈB,PYŽÈB,pYŽÈB,²e²„@-ñž€-æÐöÇi^x€)žh`)¼AÀ´ôuÀ¢s_­ ˜…X ¨ûê3Á8N /w?“4@ñd¢ NÞ·yÙûzë@´?'—¾_yùûÖæÙC,žÍ³[´q ÝH±¯Wý™ærø•uf!A$~´Å›Ëâ×k‚e!a4~´)‚f!ªíó›…È2ØšObjE5]ä×?+bY3ȼJîÁÎø ÜlQbš-ÜHÝ%¦ÛÂäm·€}¦€о®À %¦áâiv (ÃD_øPÉ  x²|–a¢/L (ÃD_ø0(Â×€BÎ÷¬¾‹ÓwáFò6^ 7Üy`Ågµ^”˜Ö‹w$pïÚ¶Îl¾(1ÍV$@÷Ú!Ø Ó·F°;8‚ÝáDšdwp»Ã‰ägwDH~v‡ Bšdw†É«¬áž] Ø. ?»#§šdwp»Ãä÷ìÁîpùÙ’ÈÏîÀŸï™ìŽ`w8‘üìI„ägw¤DH“ìÁ0y•u»£ BŠÜk‚æUÖA쎜 ÊW)áUPŸØ,Dõ'šÉîE^ɧü'Bšª±QŠü¢‘(ލE^Õ§J”$BšToâˆP4O÷Áò™€Yˆ/üÀ@T©hžòàQŠæI? Ú¡5 ¯ýÀ ‰N ¿†Þ:k@o^ HÛ!X¾#òê?8õ¢ "¤I'ލE o¶’GÔ€¢ ˆS„Ðríß !æ$3Œ¿]!Ôœ$¢¾Õ`V"¤¾QíÞ¤ “DÔ"”D†ñìõ…’hRÓIfÏŽQƒÈ0ž= ¾­È/ë„?ß3ud†ñ·!õ…Œ!ù•$Ò¤´“DÔ¢ úÚ¶Îw’ˆúBV_@›"x ¤ºÛ¸¼s{L ì+Ð,vG’ƪ€–è1ØÖ-ñy• ´¢¼ ä6Ř¼J'Ã㼓W©^Nð¼J”W\Û“WQkæUbD^E}&`ô‡äU²‚h’[Ëy•‘WÑ[‹¾â¼J™Òù¹µxëåÖr"¤In-GäUâ ¼J™!MrksD^%Ê« -ÞlnmŽÈ«Äay´)‚çU`û·Fð6E†ñ·koS ò*q»h%Ö!¼Í”i’·)y•ÅîÈ0ž}ÀÛ”4@“¼M‘a<;†Ý‘a<û:€·IäçmâÏ÷LÞ¦È0þvÂÛ̉ü¼MA„4ÉÛˆ¼JÂîÀÛÖÙ¼MÈ«ÄAì¼)³;@­q»2ÐÃ4¯k¦…ÿoñOXí if®d#–AÙ¯"hÞŠ`ÇaЭj¢ZtkÚ–ø›K.ƒnhE‹EÀMâ¡Hs³®ã„d]!Æ!ñf]’ÞMB¾(5ž|%ðÃVšÝËYÍî唠π^N4»~8à+¼‡•ÎVh žÁüù*äÔ•y ÐÜSq«€XVŸ[ác! §¶BŠBÖ4i¶WX‡uÈ]‚lÞ:à.|Å:à.Žø:à..í:ÀÏÂb”5ÞÏë¨R;¡H³_€[ûrò —ö}ò2XtüiËÛÌöKi Ðl¿$ @w tÂ?îŒÓøà—`‘×g€_ÝÚhpò Â4ÛŠ§ ¼Åùô ¤þš6¿¯¿ÿštááÈ8?«ô;cb›ŠtΚâæõßã¢OÔ}ýýÝ4•‹Ãþpbü\=Šm!ø–s>˩ϊ Ðw”rTYAÔ¤Ä7_õÖÕéãéZçuúø^V+Ê N´ÔÔMCç8œŽªŒU…ÅÕJŸ—"#úF‰’ÿZ º¬i€Òy4¢@ H‹6Ö@L«HÕ@‚ß³; ÐÊQ|–Kç=Ëf­›S÷÷·ÉðöÇk sõ©+E¾•Õ ÏHn6ÕñÞ×ùýzA<ÝKYð ¯{”9Ñ…ý£* òß·.=sV_$Uz.…(9Ò¢;àæ+i#ôsþ)²L0*#)s÷õûnîj^ùØÚ !×d >ý`e…äæŸ¶BÊ8(+”UFˆ  mîä¿M ĸ±«YmW‰€´¹ûúÞhs§ ¸2w/È€–ê*©o¤®?›«”n…) Pmî¾6 ж> Ö|#^aTÿÝœ8 ¨ñ±ÿ½»óñ©«oRõ¢XѨ9 ›ßßZ‘9uõŠøUH¶§ZQ¬NÝo{êØY#^o^`½ùhi€¾; åÍk Ž÷æC ¤;ÞÍ7ÒÇ»ùFAÇ{ôÑ|£/ójd¾Qv~ñŸÅ¬˜´ê\Ò®w¼/Bl—Û\æD@ïÛ¼þ*[w<³jAçæ]Ë"-Ÿ)ЧR§®jb; $Ä5eD÷¨ñ}•KªÍ÷®÷‘ê½Ëòm!sItì´ïû«¢ÈŸêQ¡8cù]ÜËŸ<Ë©”q¨ïÒÈÜ ^…(è5ý7ûþ¨øúêìy(UñI᥂I<ù×bðÎi‘ÈÖ¤,Þ·ñJ=‡Î+Ú³\DHKÔ¾”ÎL‡’5RH2N„¤mÞk£¿“^SórVaaãýÒ‡öé-R'¢ºO%'=ÊêU‡B}'¦ãã&zHëÇ’2{ßõîUKjwïžVgAÜ%ÛT»÷©‘*»gêO#å¹ÈÈnîG€ªT†è¿hh$t„¼ë]ÝKâñ y„Ô ‘ RÃüSH!ò)¶Íî#¤^l.Tóª5•œô;%vcÞdˆ² «»˜N©ï¤w¯ùN!)¢R/GÔ"¥æì…äˆFH½$ÑÐÄfAI¢’É}·93‹ þH—*šH‰LšèëŸ-uçóDóæ ¹óDi~ÞÞ‰V£üMû^ÏDH°Uç{£8úíÔ$pêüMI¶&/oš(vÛ3G*¶ I#¨È[6imŽê49бem޶=s¤bËWuäÕšâ.â{7|b[æyŽø†Hml94| RZJ*$óžþgÇ™ÜVsNµ{Æðml†o®¨ë¤ÕØðé6á›)ê:i­ ß«EjÆOÃW? ‰>»È|¸®‚ÒûdÕµ=j,Ÿ¶Gµå»¤ù…e¡¾°ƒZØM_ÓSE|Y&É ¢îÁaR\ÇYº-#¨X½šÛ»ïJ[êðØUf‚êü-–jÓAÍ“ã!r™‘­j`v!RõÉÉÇÃv÷“ÞºøR¤•C‚GçYjœ¡/L›÷F\Ol)÷Mg•Ö;´ê„å·IXò&¡–"?Hœx\B39e&òÊaÈœgÙåöT†€·ù•R²TÊœf=I—ÙûÙýŽ:RaLÖó1O¹,ipšÜÊ÷_Ùäõ‡º$XûŠêHWÿ²‚e·[=ÓY±/­wÉ‚B¯!Psâ*ÛS?n÷»£i—Ê ÑeèV4]Â?—UàŤ$ZZ*ë½~*ò P⩬Ÿ³3 Ї£R³4Ã×lßÔËLÖ®|×+xg»]ZÅ‘9c‚èÔ­ṴÇ —ÚtãŸKC Oõ¾þêÃpæMq¡ùF×½( * qU¦Av¦¡> Ê4”<+oh×úßÈ·Ú_eç2(ã?Ò¦AUÏu ˆ§gµ¢Êå•ßRyç¶µ6 Ê–šµéܸy¥Wg»ZVš†„%ƒìZSþ‡?µ©ÃžºNäç‚Â’HãŒÃ¹÷òf“¥ÃSFÚ0«žNˆÿ>‘ïû´ ¢¬©ûà £ïS§j6¶ð´6 aa£#QÓ%Xxx:HÓTÕž^—ùž“àèðôµéîa"T.(à ptxZ¯gPÀâ•ÅN‹ê ŽOÕ¹†§gY<š}ûÐeç/[j0,¬ÜEçî9ôŒàD£ÊKK«(yØ9ˆÆçÞ9ଥAÕÞ.àþŒ+IoöÀdeêÔmðzFöà×b2BœhDk õ™ Äé}Ÿ¶;¦—¥eú}ö@?#÷S‘-ÓürIk–Z§(Çð_ß½?${Ѣȶ³tKæ E“„¸s`•yˆë××޽êÝU«šÝc»jQ‚j÷–úÑúe‹Ly¹åüF„4MU;V™‡Hж±iÎ^} Z‘¥ÛÝe—Ëgðî ¢¹_Ë)ßÑœˆ·Ä䛨úP7"¤x:_R†Ò â‘fN]SìNycóšÝkhP9Râ|e[n#úe+—âRÖt«œQˆÕøDôh2c'|± ²fÐ:Øœòæ™ÌBèç#$“B“ÖåšâikÄB‹—‘5‰öeM¢ÝS1KóqRâá<¶"¤Ž Ðd·4 Én5¼‚j÷V“l€spI,%ÒÚD~cË;k”r)ThÔ¿OŽ›»ÍOyôvŸì¼¸ ÉÍÞîÓW„m´-WÔz±¼ÒêéL…´tÛÂÝKì,(±² Þ‘>Ü6bædÅ9H+w‰þ!%Òº«›« ¸º¹µ ¹¹Ñ{fZ~ÕÝJOµ|5Šxe]$%;åmjzâ±Qf;|yü¬±Ïlô…åY3ýÈJ~ãDH±¹­œns{a}ÖØÃeQbå oÌ—¶Â8?P—ÞíC • Ø4‰ÖÑ£æ!Šâ޽NqÔÄ—ã”îÀîBRî#¤ÈáEbʇHñôgÊ‚Ò8#¤¥~|nÚï¤;cšÇg*ŸèŽ ´°2C†ß)$U=BŠÜ·©ÜbëÀ#¤x2zcÕŒ–î³ôÔÐHñT¥)-]ÏÞ)Ý\¥³¬BØ€bLµ{ÉØFL°7DVlÙ­ Bš.ÌÕ!l؉HF6¢-•¨ûÄSó¨¢=t à ½ͦv¯L·l—!EŽûTÚˆw¤Ø½&Vîð‰ñîÙK›udrŸ"Ëî9N9žÑÓ!ž²ã9ð”‘"t í^„—N‘ ¾˜(@:Ey¥S¨€–^ÕN”xUgˆ€>¼ª3 ÐÊ¡:“ƒUg"·tÊ”êLV‰ÜÒ)SY½¬:ù¤Sl{—c{¢Ò)£ÍË1’=‘O:Ŷ{9F³Ç…»E{r˜h ié•"ºµ‹Ä­TH*‹·øð*Q­iå•"¢úNkRNµ¦O¯èÑš¢?^Ñ£œÉ'¯kds!ùå•H`y%ìÑÊ+ žùä•R* ¥W™ŠÓ%^e*" ¯2ÐÊ£LÅÑñ^{%°ˆVôé•ÀBº%¨zëÀX² òI`¡_e` ,Iä“ÀB› »–K¦ŒhE+¯ÖÑŠÖ> 4§úô ¯oÝ­ëR^ãDH ¯ôRä“DDŸi{Å׈ìîÔu¨¯‘­)qɯåPù5Ò‡WQŽ iå•”£Ú½µWRŽêæ~ú¨Ì«~Ã8Äë’_&ÈFD^™<ìî!dòr"$¯LÙš¼2yEA„ä–É+€ zQˆL6Ño—ÉsÊRíÞÊ+gHu"Ö^9C*¤O¯œ!Õ}ÒÁ‘KÏ já†Êaô%'TäÓNÌÉ b¯L#Ù.}:’êúêiR¨1™ïøðªO’màÊ+?Ie•š É%?‰NÀå'±D¨ü$>…–ŸLÉ–^ñNN„”xÅ;©>¼âTH+¯x'ÒÚƒDwŸ>½2¡9 $ŠN¼ÁeB%’W&” iéYåDH‰Wd• éÃ+²Z!­"«9Xd5òÈ„N‰¬æ`‘ÕÈ':I‹€Š¬F>™PëöåZ'ÔbjÿrŒH­ÊÍŒ ÝÀØ'S+ȬìÒ«ˆK¶‰O—ÌR,>¼ê»T†v±òÉïÒyĵG~MEDÈïæDH>ù]t¶,¿Ë'BòÊïTH^ù]Aµ{^™dª±òÊ$K"¤µW&™ éÓ+“Lµ{óÝØb¨Nrä•ßJÎÁBÉ‘O~wª 3+%G>ù]ëæ¡éÈ'¿kÝÀ£4yåwm˜c¤¦P^­i²Ã¾rCdMGPk¯¬uAõéƒ"³KÑŸ‚6'ƒZx´Éb ¯XwNu,"¯XwJu…#ŸXwP†ñ*ñJ“‹¯9Ù®¼äË·ƒIç‚'òJç$8±Wê¹°ÔyN‚ã—:ç$8±GÂ$Õ#Ô¹KR=%ÁI<8©¤ù>^éö‚gåÆ)`í¿Ó8k¯D<Íyûtã¤0)zÇ=ýcïóä8-ú(D‹>§rjѧ„+òjÑs" åÔŠ8F]?òhÑ;Õõ% ЇC]?«ëGn-zW!L]?òhÑÛV”cæD^-úÉ®>²©ôÃôÀžá»H ïh"Û  3®ÙTH±o8•½3©‡ñt‚3À…”xç Pˆ»ì ÇÍAˆBæ ä4@s8nB„ƒ@³´ÍApMvT+J¼“$ Їw²CÐ+lþdAƒy'HœØ;AÍɇMÈ NäTA³žØ7©‚§a8ó&Uà_G‘ï¼ 'b$8±g"AY ÀDŒœÇ3ƒÃ&bDî‰ÎÉ’g雼‘§$8‰wÂÍ÷ùðNø Ù·•G$8kï$šõ|ºqrØÄÇ=ýãYÎŽ,‘$8þ‘%œ'öáð”gé`°-Ücך}ûðŽ` :oóG°„}Ÿù#Xˆpbï¨N‚³ôŽz¡ÁI<8çzà€\#eð1³FÊpÜH™(`¤ žé)“s"¤‰‘27R& )ƒï±”q ä¡BZyò²Ý[{òPˆO÷@ž6' ÈCpŸÜšÈ7' È“!yò„Ÿr÷@ŽÈ äŒêD¬¼ãŒ¨NùÚ3ÎHíÞ§wœÕÙ³Mýía¡‚ÜQÐ<£”É9Ï(¥\“ožQ<²b¥µK¹¦Ä;£‰ É5%ÏhŠ|óŒmK°M‘gž‘uM9fî” éÓÓID·&­`àe- ˜²L§¬a=xÊ:æ›9e㦬E!SÖП Šî†@q§¥i±B0-M'Ðrl…za$LIÓ äŽî`:šN ÃAüÖ±QšXhŸ³伜@+·Úä=Ð÷½Œ›ÔšL+‹œHÏŸª'TX„¿yYp4P4VÊ™–ý.Jœ¨Óߤøu‚?Ëñ_(+å4‚éÛíUOö`ü€Å‰ÆJ9u´õe밞Ȣ”ã˜ê‘g48aìzJI)sN‚c†DüµŽSÈË]Aƒã™‘ï°/²(å|éT)<×E²,•°ôÖàŲ°Ô2mÙŒZäCfR  È’dèe3@’N Ø“d€Hb8–Šÿ~]Œê˜“2y=¨™èÃ¥R‘¦x74ZuÒÍ7ÒÒÍ7‚ŠT8ÖNŠ”9ÑÖ}ê +» [Ÿ:}aaà#ú/W€§¸ AÏäÿÆ®uðzíÅ Ú¤(öÄÖ¤héæLæYA´u‰“1ô¨|úèÂ9Ë0èàpna 笳 ùan}btQp"œx4Á¶ ç®"Ë÷<0üyß·‰!¬EõœLIp"÷XÙ ˆ'vŽz ø>3õÛ MY7@”‰g6ö»o¦Ç‡>Ó’ÇÃ-ÍÒ ™7ë(Ôý7í‡@Ü 7R4Í® Ë”Œb·'±0ÝHKw"DÂt#%Nf€‹!é îûÛP0•×SÌêP  :#$GǦÈxVÊÉ"Óe¥5‡½*ÿ³ ñÊïïMÛÉÆ Ã…íªU1,êú°«&÷®ÜJ@¥)rv»ØðRlâ-ËîÕìPïÞÃÅÚ(2‘m% ÐM|8gA šRì\S™É:äC†Ë(‰fÕÖ´°ìž“ z¼Äx6,ÔÑl¬àD@l†cƒÄ`6ñAb0„áØ q}Åx6H)r „ÁØ 1– RŠ2'r³AxV"¢cçfƒÔ¼V!yÙ ¹{`6vó l& — Bµ¢ 6ñAb0„áØ 1˜ ÂplÉÉŸ,ãD‡aí¦°êeKäcƒdTÇÛËaT{çgƒdD›çgƒdAkšÏAGw@6>º›Éa86H fƒ0$³AŽ {Ù “$ X&%ö²A&i'eÁi€$£Áñ²AˆpÜldƒÄh6úÙ eƒd48^6öû@Ø %” ãÙ ŒÇË)‘Þ©ý ãÙ øLÉ\6ñAb8„áØ qí"€lê'§Ú=¤ÖyÊox$ÿª³AJìŠ lZR;±Aâ6Ö†ÃÙ ,x÷f°AjUèĉñl|‚Ä©Åíò:ä³Ù k²±Aêqê×:˜M.šñZ‚äþØNDbmËïÏÿj7 PSzÓ@'Úq™W’qÄ´Çh€ þH·g ØIiÈÒ â9–ŽbyÄ ªñN ]/Øè H­†ÄÚ­»^øñŠ2IïÅÛYØ|™OTm\‡ÃŽñFŽó(p¾çûŒ'6û¶±íۓ瀼“gx‡úûÖЂô¾"å$8Ñ{%¬Þ·æý¯÷M^÷[œxlz8÷‚ŸÐ6a1ŠÁ6ážN È™¬Mø«º°Eà›vEu°ªÍiq}fù‘hë––3×»«üøB®è?KÊqY/ü’ÑEî<}½‡®{tyn‰ü_‹…H|ù%¾ˆ€&%¾œÔéš”øpR§hRBÀIN ¿ÄÑŠü_œÈ+ñE䕸*ˆ€fH| "$ŸÄWʈŽÃ ‰/äš&I“Ê[œ(òj‰ù%¾ˆ€&%¾œÔéš”øpR§hRâKÀIN ¯Ä—4@~‰¯œÈ/ñE4Câ‹è4ÌøJ‰ü_A»‘ø"òK|MJ| 8©Ó 4)ñ%à¤N';ºƒ‘:@~‰/Iä—øâ4@^‰/Itêü_èÔø¢ÁñK|q¿Äò%¾8 Ž_â‹Ç/ñ%Hpü_48~‰/šsà”ø*`¤ÎÁ‹*ñÅi€&%¾œÔéŠ=I©Ó ä—ø4@~‰/" ¯Ä—Ìi€&%¾œkéòK|I §ÄW#uTâ‹ÓMJ| 8©Ó {âÆ¨…H|m_â‹è0ø%¾‚Â,€Ä Ž_â‹Ç/ñþ I“Ò[9 Nä•£ÁñK|¥$8~‰/I‚ã—ø$8~‰¯‡“ø*`¤N7’_â+'BŠÝžDêt#-݉T©Óä—ø¢Ú=¯ÄWAµ{>‰¯â†GJ|  ¿ÄÒ%¾ ©Óä—øJ‰ü_"i¦ÄW uº‘ü_œÉ'ñUìÂ9Dâ‹!ù%¾ HA_D@~‰/" I‰/‰aƒ`$¾$† ‚‘ø’6HÄWAä—ø"Ú:¯Ä—$:u^‰¯”êÂzÙ W‹–øªÜ3¢¯4Câ ¹&¸ÄWNä—ø"òK|MJ|I #ñ%1lŒÄ—İAb4„e9Ññ^{µÄˆ¶Î/ñE4Câ‹è|Ïø¢Z“_â+ "ñEä—ø"𔸒6FâKbØ ‰/‰aƒÄx6H *ýÆx6H ïH| " ¿ÄWJ|Ñàø%¾r¿ÄÒ,€%¾r¿Ä Ž_âK’àø%¾hpü_4çÀ)ñ•BÙ A_9 ФėİA0_à ’ø’4@~‰/" ¯Ä— : «)å-‰aƒÄh6H$h€œ_)” $ñE4)ñ%1lŒÄ—İA‚$¾ˆ¶Î/ñÅi€ü_Aa@â‹Ç/ñÅIpü_áÏ\6Hh¸0“ ‚~ƒ%¾hpü_‚Ç/ñ%Ipü_Èp&ñ•BÙ a_œ)v{" %ñ%1l0‰/ª5y%¾R*$ŸÄWzÃ#%¾$ _â i‡À_)ˆ &ñʼnü_2i¦ÄW bƒ„I|åDH>‰¯t'‚9Dâ+'BRoŠß¡ÄW=P³òN‡û DiXú$¾~ß%¾j tK¹ Ò+êª( Mz/ñ_ñòN ÄW=ä‹(Ñßè»= ºV}£k~—8 «Ä×ï÷׻ܛƹ/ž“à˜£0P Ò8)Pím鑸úý6_ïûv¿Šk‚3ºC½}ë]Ö«øÉ Žeߺ+T}©ëöB‚mBç `.v铸𶠰„Æ/ñU⯪MâKçêñ³êÞªV$ö×òUp ¥åÌußèš¾~+²K|M^V  ÛÒ'ñ5¹¢ê8ü %¾¦ïÑs»'Br»üX‚|чMñí]dÐîóx–g5Z+Nç&×SKåAÖ“ ×SæûjÅy{+©J¸’êʪ~äSR•p%U'Ф|¦„+©:üJªD[çWRÍi€’)…S W8]Ù”&Jª#ÅV Wluá8PIÕ…O)œJ¸Â©g¤¤:Rl•pÅVΤ’ª„+©ºp&•T%\IuemÀö©tJ¸’ªȯ¤šÓM*©J¸’ªhRIU•TW–1¿’ª„+©:"÷Š@Jª6 Jª®¤êFšD/1‚è++mÝíÆKŒ ºhÂv—At'׳”ÈëÆÊëN  Aô#ˆ¾²QÝ‚è%FÝ…ã< `7CÑKŒ ºÇ'ˆ^bÑ]8n¼Ä¢»p&Üx‰D_Y™3nQbÑ@^7Ž¿ª³Üx‰DwM¸ñ#ˆ¾²”ö|n¼Ä¢;"÷Š€n<†»ñ#ˆîFš(z0LÑc…(z0LÑc…(z0LÑcTôï¢G&i€&Š SôXÁ‹ SôXÁ‹ SôXÁ‹ SôXÁ‹ SôXÁ‹ SôXÁ‹ SôX!Š SôX=ðWuVуaŠ+DуaŠ+DуaŠ+DуaŠ+LуaŠ+ÑÃÆ]7ž ¸ ãÆwA`ÜxÂ] Z‘Ÿ»@ô&¹ ãÆ8wA`Üxç.ŒOàÜqã œ» 0n:•G Ô¼)5ÐüÙ/^ •{öËì{äR3 þþj­æã¡Ñ¨kN])òm!©NݧsöKeêf¦ÏüöÒ “ÿÌðκá/ a‚ iáþ’ñ™ŽÂ¤›~¿~ßÍ]£èŸ5‰ÈnÒ3ƒrcã,²êo È­Æ)xF;å8y‘R)eÖ¿ê©«¤u««T‹rRm|ü«tµ«³p`Í7ª…?Óf„”8 È2ŸÇrê¥Ì2dE‘m>ÏæËH™ÖÖά(;¿ø§‚h¬™Ún¿ ÉöT[·tŠ™r¼7,óyê¬U|RÐ}8eSîQdÏÓ¸¤]ïx×Ú—Û\Š”h­…S7F µ:t­@kZ>S* O—Bk.®)ÖODÖù<¿jó½ë]¤zï²Ú›çœè4hß÷WE‘?GÍe¨eêIM?yFeô8²úˆÌh¦wa×ô_d¿XÛ»¯ÎÞ¹žÞUÖ^š!ékuid‡Îi‘ÈÖë!¿Öa9Ë I„´tŽã¨"IF…”LÏ7ª…S™$ûNÚ§w¶Hˆê>•œôDè©d_:ðb:>n¢‡znÈ©ÖzüÇÆ:fD²¤BútIEFvsÿ8ä På?-W?’‘ßX§DÈ#¤È="c ³ ß>BêÉæBq=l­ä¤ß)±ó&C”]ÝÅtŠÈ2@. E4BŠÜäðQåÉ1ó( Jz£Ý,Y¢;þi;BJ:bŸFjN„Fš?­ÎäÎͧÁù‘V£üMû^ÏDH°H\óLÞ'󨞘ã{aY¨/ŒÞ‡|ONò­§|“AE݃ä ¸Ž%²t[<8FP±{j°d)Õí],cƒEÎ32ƒ>0»)«[°¹DË ÷“ÞºøR¤•CÄ~(ÛœMƒ3ô…ióÞ(IØØR#ï›Î*¬'¶ŒÝ|ý~›¤2oò*©œrÉœ'—ÐL–‰œå©LIp–]nOex›_)«+Tȼ ÁIºÌ^CœÕ‘J­ ù|f§T–4û¦ÆƒÖ¥šÙ {=‰×Ã|RV°ì†®CkuìKë]² Ðkéù7õãv¿;6­µ÷+ê¢LJ¸¢é~=ð4g’K ¥¥²Þ+áÏxêJ<•õ¹O½@î§;mwL.KË"ôû ì~Fî¦"Û ÎL«‘(Rtñ7~[¿?${Ѣȶ3gú‘¢IBÜ9°Ê{ƒhî×rÊw4'âí1ù&*·áßéí aÍ—”¡4¨xÔß^×»S®díÔpÝ";í^â|U&"ÜF,œ<Éf÷ò: ͨvo5>½šÌØ ŸV¬´Î6§¼y&³úùɤФ5…F¹¦xÚ±ÐâedM¢}Y“h÷Tð#RâáÌ•Úð#}tl€&»¥ÙMvKqð¨vo5É8—Ä¢Q"­Mä7¶¼³Fi —B…Fýû丹Û,ð”Go÷É΋»ÜÜèí>}ÕA˜”®ˆè*by¥,/ÒÒm#w/±³ TÄÈ‚zGúpÛˆ]zäDH+w‰þ!%Òº«›« ¸º¹µ ¹¹Ñ{fZ~ÕÝõá3-_µªÕWRtË×øæþq?6Êl‡‡?kìÆs }ayÖL?²RÜ8Rlgn+§ÄÜ^XŸ5öpYTXyÂ#-m%„q~ .!¼Û‡@*A°i­£GÍCÈ⎽NqÔÄ—ã”îÀîBRî#¤ÈáEbʇHñôgÊ‚Ò8#¤¥~|nÚï¤;cšÇgõö,×´°2C†ß)$U=BŠÜ·©ÜbëÀ#¤x2zcÕŒ–î³ôÔÐHñT¥)-]ÏÞ)Ý\5š@…°Řj÷’±˜`oˆ¬Ø²Òta®aÃND2²m©DÝ'žš@í¡HïE³©Ý+Ó-Û¥DH‘ã>•6â)v¯‰•;|Òm¼{öÒf…ܧȲ{ŽSŽgôtH±¯ìx<åC¤È©hRpÉæ§eý‹‘jÁbÐcW4áL  ¨‹*-Š&EeöˆV÷º^•RõÂMœ@=Þ•Rã“8\ÑÄ ÔËi =³‚ÃMœ@E“²Ìi€VN¡Y¯Œhíºå,Ë% ~ݪ{ÔåÚ” IZT÷HuQN šð2ËÑGòI§”@2u#¹Ûau퇴°¨e8zTò¬4@‘³íFæ<#r´…2R e× £­ž¨Åá­0N ¤K³uv• X'Œè£Ë²»šv+‚5Â8VÎæ”'cXß·°©eLÉú!SÐ}:{`ŠŒq¢éî¿É¾”ºEÓjYPt7Šß ¬¬?Ø ´[¡^ kyv¹£;X²èÃÝ|ô}ÞkÞe3%£Wwl‚®}ÎnL4@kWr*XY}£OÊC7 Ѹ¬‘œ±èVð²48Q×@;Hñê–ãB4$º×:”WÃÒ:Œ°q~4nW«£­/«€NÀz"K»šC>'ÏhpʵP)SN‚£;1›¥±ÌL^î$ Nâ™Ùa^dkWûþÒ© S/”¥–Þ¼X–ºŸ-›Q7wÉLâ°‹1›qdèe3@Í]N Ø“d€4w9–žæ®ÿª\Œ¨Œ“Í]y­fJôáj™D§nålîJYAµ¢uÔ Ôh™èS_XÙ]XS³ª.,¬!Ÿ[)ÑzÆÊ¬]8wY¾—áÏû¾Mé¥24\xo›€- t^f€;eY¾Ïg©5L¿XjÊ:±T&ªh“à$n­Ô':];ÀùpÓ³BŠM¼eٽꃉC¼{o kÃÈD¶•€†7R4©Øv΂4#¤Ø¹¦2“;tȇ —QM«8„¬iaÙ=IÇ3Ø S´“ŒÈÃÉ ªM°AŽ ƒÙ ljÁl†cƒÄlPô£Ù Ɖñl2Ïi€ÜlR@é¸/¬› ’U†ˆhI~6+ˆ¼lPøÏ`ƒL‘4XJyh'¬4@^6ÕŠ&Ø Ç‰Ál†cƒÄ`6ñAb$D^X–4@kí6@Ù 'ò²AXJ…äeƒ`½ß4d‚¤ø™,l)ÚIFäaƒà£»™l†cƒÄ`6ñAb0„áØ 1ž  ¢ùØ e˜ŸÍ)Kªoôéfid…@›+d’u’ÑàxØ ,Ç$²Ab,¿(„ÑàxØ Lb„í$ Ž— ’Ñœ¤Ls($F³A˜äD@l†cƒÄ`6ñAâ6þU cƒ°œÈÃÁ»! ¤„±Ab0„áØ 1Š R]X($`ƒàŸÉ³Ø ljÁl†cƒÄx6¬fãÙ J $,ÌšË ç³AˆÖãfƒ0 $ƳA2$#Z— ‚ý>6H eƒÄx6£Áñ²AJ¤w€°Aj?dƒÄx6>S2— ÂplÎa86HÀA» ¤úÉ©\lZç)¿á¿„ ‚U‚Ù %vE6H­¾šƒØ qkÃál¼{3Ø µüjbƒÄx6>AbƒÔBpùNòÙl€5ÙØ µ6øF…úµ´b“‹f•ÅãòþØNDbmËïûj4 PSzÓ@'Ér™W’À´Çh€ ùH·g ØIiÈò J:–Žb¹¬iŠ€¦H× 6ºR«!±vë®y¼"LÒ{ñv6_æU×áÈŸ#@Ð…ã< \îù>#Á‰Í¾mlûö¬Kò!8Ã;Ôß·†¤÷­)'Á‰Þ+aõ¾5ï½oòºß’àÄc›ÐáÈ{ÁOh›°Åà›pO 'PäÌ@V7U¶|Ó®¨Vµ9-®Ï,?4@KË™ëÝU~|!WôŸ¥@帬~Éh€"÷Š ž¾‚€ÞCH×=º<·DH‘Wy bQ£R'#òK|MJ| 8©Ó 4)ñ%à¤N'Ф„€“:@~‰/¢­¼Ê[œhíÓ‚È+ñU¹IðÒÂ#&–RÙ†_È5I§мZbD@~‰/" I‰/'u:&%¾œÔéš”øpR§håSÞâ ÐÚ«%–Óù%¾ˆ€fH|†_)’_â+h÷ _D@~‰/" I‰/'u:&%¾œÔérGw0R§èë¼%i€V^-1N䕸’DßèÓ+½…‚‘:K¿Ä'ÁñK|!Í©sZz‹“àD^)1¿Ä— ÁñK|Ñàø%¾hÎSâ«€‘:ë€ûÙ_œhRâKÀIN Ø“d€:@~‰/Aä—ø"òJ|I¢S·šRÞp®¥híÕ“4@N‰¯Fê8"¨Ä§š”øpR§(öÄP $ ‘ø"Ú:¿ÄÑaøðJo…Y K87!%Fƒã—ø¢ÁñK|†?³%¾r¿Ä Ž_â+%ÁñK|I¿Ä— ÁñK|!óf0‰¯Fêt#ù%¾r"¤Øí‰@¤N7ÒÒH‘:ÝH~‰/ªÝóJ|a :`‰¯â†ÿN@‰/Aä—øBÚ!°ÄW uº‘ü_)’_âK„"Í”ø*¤N7’_â‹!ù$¾Š]Ø!‡H|q"$ïÀ7Ðã%Æ|ƒ…úA_D@“_ÃÁH|I #ñ%1l ‰¯‚È+ñÊBI|}#¯ÄWJ´"¯Ä=•Â$¾$’_â ‰—øÊi€ü_D@~‰/" I‰/‰aƒ`$¾$† ‚‘ø’6HŒø–Q­híÓË  ¿ÄÑŠfH|ï_Tkò²AÂæ³ADâ‹(žRÞ’’Æ ‰¯‘–˜ÄÐN0_à ’øÊi€ü_‚È+ñ%ˆ¾‘_â mW_48~‰¯œÇ/ñ…4 `‰¯œÇ/ñEƒã—ø’$8~‰/¿ÄÍ9pJ|¥P6HÄWN4)ñ%1lŒÄ—İA‚$¾$ _â‹È+ñ%ˆN_âKÐMJ|I í+ñ•BÙ A_D@“_ÃÁH|I $Hâ‹hëü_œèÃ+½fÍgƒd48~‰/N‚ã—ø fK|q¿Ä Ž_â‹Ç/ñ%Hpü_’Ç/ñ…tC0‰¯Ê “øâDH±ÛÙ (‰/‰aƒ„I|Q­É+ñ…-è€%¾Ò~M@‰/Iä—øÂîTâ+±AÂ$¾8’_âK†"Í”øJAl0‰¯œÉ'ñ•îDÐ!‡H|åDHêMñ;”øªj–)?ÜO JÃÒ'ñõû.ñU \( [Ê ^ÑPWE Lz/ñ_ñòN ÄWeŒr D£ïö0è~Xõ®ù]‬_¿ß_ïroçZ¼xN‚cŽÂ@5Hᤨö¶ôH|ý~‰¯÷}»_Å5 Áݡ޾õ.ëUüä‚Dzoݪ Ñu{!Á‰Ç6¡Ãás±KŸÄ×´M€%4–x‰¯Um_:ÏP¯ˆŸU÷Vµ"±¿–¯BÐ--g®ûF×ôõƒ\‘]âkò²eØ–>‰¯É‰4ÿ J|MߣçvO„ä:wù±ä_ôaS|{´û<ž¥@ÖŠÓß¹ÉõÔRyõ$ÈõTO1À}µâ¼‹½•T%\IueU?ò)©J¸’ªhR>S•T@~%U¢­ó+©æ4@“Jª®¤º²)Mø”T%\IÕ…ã< @%UΤ’ª„+©ZpüJª®¤ê™TR•p%UΤ’ª„+©®¬ Ø>•N WRuù•Ts I%U WRuM*©J¸’êÊÒ!æWR•p%U'Pä^HIÕ4CIU•TÝH‚è%F}e¥­»Ýx‰DwMØî#ˆîòºq–ÒyÝ8@yÝ ”ØÝk‰*_Ù(‚7>JŒðº ÇyÀn<†ºñ#ˆnÁñ¹ñ#ˆî™pã%FÝ…3áÆKŒ úÊÊœq»ˆ#ˆîòºqüUåÆKŒ ºh—Aô•¥´çsã%FÝ ¹Wtã1Ü—At7ÒDуaŠ+DуaŠ+DуaŠ« ¢Èx‡=2I4Qô`˜¢Ç ^ô`˜¢Ç ^ô`˜¢Ç ^ô`˜¢Ç ^ô`˜¢Ç ^ô`˜¢Ç ^ô`˜¢Ç Qô`˜¢Ç*¨è¿ª³Š SôX!Š SôX!Š SôX!Š SôXaŠ SôXù‹6JÀx×ÄïÆG$ ‰wA`ÜxÂ] Ú:?whë&¹ ãÆ8wA`Üxç.ŒOàÜqã œ» 0n–Ä̤Rª¨DMÍÍåfœ-Pì$ 9rÖ|Éôt:¶ ¶|‰>Üc¹O™å™A@ƒ|É”Þ'ÁÞý7zœ´Ý f»=ì—“(g¥ºgE'QJ" Ø=n¨” 'd/4Þˆ4@‰ÇÁ¸›½àÀo{Ááõ`ÞÈÍ^˜özÙ=p߆whÒ»îÛð Mzײà$8±Û»2˜wñÞ½  w-aÞÕÏ^ë£Ü¸‡½àrãè;uãh» sã,]Ñ|7N‡M =¨¦d–ç#%3”¬øÆçåa8³Ÿ”€áÃ’LH _X’D@±÷í*h€|aIZ}#_XÂxŠ‚…%Õc<'Á‰¼qœØ÷ÏEÎì°$K9 Nä}ôKœØûèGß è£_ÒM†%-$3‡Ù¢-½Ùäg°ßœ]Àž:Dv!'Bм~ˆåÆg$”„eˆVäuãŒhEKOƒƒÜ8>»ÀXŽÜ: Ï'Áñghp¼ÙaÉ.ä$8þìÍz¼Ù‰>ØÐì‚ ŠœÃÇ nÙ—=esk­ñœ¢îôk¨LËœ(òÕZg–@ã9E]×#enÊ>žQu<f—Zã%P×ãa.Á(žQštõ³‰2ñŒÒ¤+¨¯\ö €‚zü‚fõÀ’a<§d舵ñGk—m ±öÜzxZÉ Þ»Ù•¼l®oƒ*yu™(Ùé‹2À= ªä•"§ò¦ " ?ÁHÐy+yïTÉ››ÊŠÃ*y³3Üq`%oîc?¬äÍMÆA•¼šÈÄIp¼)@Iƒã'¡o0(9 §’Š0•<­äÅ¡•<ô§±vN0âA@€`àÞÍç Ï­äÅ¡•¼¹4°8¬’W±&òºq&i€¼•<¨äÁŽž' »HèJ0,ÁWòöÝ89 Nä}ô œØûèGß è£_Ðy*y@7Žç Ï®äÅ•<üg°vž]d÷nv%¯|b le¥¬7/ g^%”-ÁWòêlI†3¯’\OŒ_O&ÃpæUò@çmrÞ2†3¯’\OpqæUò@çmtÞŠ0œy•<Ð÷Y‡|ŸŒ‡áøì[[ÙŸ³ždšO;³ÒÊË@œyë©ÎààÏ[ ZOŒïSóÖÍÉn»ÛGˆ€"oW‡ òJð•>Èip¼Ò9Á™/}0‹êìÇñJôAvA`ï‚ òJ`¼9¡ ò7'ð @sBàÞ¤$dM!Ò³83€ü•I" ØÛ3 h€ü•IIä¯L"´2 :ÞÍ 9Ízü•É õ̯L†}@eRàø›Ð7Z™$òW&‰€bo„¤òW&‘g^™Li€üÍ a+‚T&©üÍ $çA@ú'BòÓ ›‡/ç¦,g6}`þÎ…ÐÒ2 ÙM€¬' ¼–É0œÙôȾœ·L„á̦@Ö“ÜŸ< g6}`þy[·" g6} à|ŸŒ‡á¼g›僚9yu¬½»d*žsº_è_âÓ!\Ï5pM|º»Ý÷óÆ&Ά‹4Ü×?—ž;¸}.Ò‚.6³óÔG;ŽÍêêö(Äþp;pJ¸efš‚«ç„8)f©Ê̆KT¡dû횘¿ ǩʇ†kfÏ5põ‡ãî „$ÝÌU³™ ÚÌãñÔ~»Ãõ(¥ …[k8õô¬áš9˜î!ˆá>õfv/Ýf¼žÞL>sÚôükþG-oóÕ.¯ÁÓËcäxÚ\ê·÷Ù˜ËB²ÇmŸ’âEý©Ú»v,«ÁÛå©[(˲ùmO'kËãÌ*4F»¾eg8µ[h.Ÿv ä—o¡ÇéþÓç¥2eíy©LÙÏÌIÄóñ>Ô~Êßî¶·¦óü#î[Úë·Xi¼îºwž¡ÂÛïo´xkc«¿ßlµÊl]÷O¹§uëŸcc}îðž’¤ç3úÓd¾kÇ…ª„ZÁ‹ç3#Å[èûg±*Žíݿʼ”¤®6Š4^{^ïÎKe^æéÀÌÇÓSÖîÚ0]íçåšÝ~H¥H….›¨îC&FЧìKmaºý<´- ± ²×*Ë÷߀‹ðÕ‚M®Jy÷Æ|>ž÷Çí‘SÂEk­½Ÿ†{Üv¹ „‹Qµ†k¢ê<}žv<¥„[ö'R7¾¡ó}…xf§ŒN»"mʆA|ö:É‚îc™5«Ó‘ÙyŸoIáV#CÝâ÷E.IŠ s¥5ªÎ·wZ¸O ךéw¸ó–ö"˜0÷ëïØ-Tfå öŒôžë0·N‚ÜBmÆò¢$½ ÍuÒaÙðÙPð{v'ŋφ’oæö³ä·aažÐßú ­ýB³Ÿ—ŒÜ/,†ohm©5¹cÐaîï×_c;Y3˜¾±ü'ßó}FŠ·øYmsJ¸qöŠ7¯wE‘R³W}?»ÏvwN ·ûYó„®ýìO‘JJ¸áÕ{÷³äGeœ½jVgü¬éêLöjómu|CAúí,nÝ|»îÂhW§_—ÿ^­3fåP'æÕ… ½æ&{õúguCb_îIñc7”jÂK톨‹Î^ý~ýûnÍtûúªÌthvn„ÛÝžþ~‡ËÏ™v}˱ÛK ›ãQV¶““Úi½úkËî®îeàúÆü„ í×vùê˜,ô2")LÞ…*Þ<JB4¾þŽóœ‡ëù˜ÊsЗ‹lE¶·ì·í%ÌÁF–ƆücE»n9%Z<|šœY·“ûóÏ…IB´¥þnÿ¾-“óñ%Ãòc´ÄõL(ÊÊÿ\Ñ><µŒË3°–¡yNÑÛô÷Í÷{)£™þ. ö¸1A i¸ßV¸×-´’ñgŽ¥2ÍÇ:ÓX'븨x²[8®ÎV"íÅ´ò§8RÂ%¶²IëÈB¼^”pãòvËöÜÝö¯—H)áVo¬úvÝëµxwq?å”pë·Šl ׆МØ^sÒ£ò9Y29WûýLM\ó?ö E14ÏÁAÊOÛ•¿­]is9õEÏÃSî¼ÈSÒ{l¤xúùºiß“ÕM?¼rŸ¥»)žvy_›MkɺÛP›é’ôò™ óëÛŠWÙiF{^¬ü‹öKnËFÚ#`°RÐâ­ßÛÚ¼4Jm^Xh®j„ç£`‡‘ï{-¯aû–WÉ{:§W6ù‘ò‡.²<™{™[y:IJ¸xœŠK;O{¸·‚ni÷Eox–Áåû!\bO7®$Mü÷áI?Þ„!œ¥ä•öJ^ÔGÅVòêî]^2Z8cV~ÛÕ3VQEe%é5ÿc1Ó]ö¡‚ =+јn;A“+îé!Ï Ñ,¹ŽÎYxù"³Eÿ¾6m®Ã4eÔof.Ïa9ÛÈF\îgú;ùH·)%ZäbS•Õ”hñ[(6ÈuÔ};YAˆÖæ:lEß³äÜœš;ב…æjhžì9 Ê´ÿg®Àó¢y ‹Fxž°á”‡çž%nà½^6ÜHñ–îì¥rç¤xI¨è^¹æž7½rʯ÷(Ñx ÏPãó Gx+ o,íñÆö—-)ÞÚ«ŸÏOw°²-‰ñÚ¬Çoû›ª?`p¸2\xêçs(`ì)Îôàx™…=†pÊžý¾þÕp‡ý«¤Ç£ØVÖ³<åòç‡"b‰ß7ÈÈU‹Û§[ºØ/ÔK¾[4CÔhDUµ-¶WЫ›—>ž;yf2%D[v;Y8ƒV]~½‡w› Ð+½y}©Hs8«£\Û€=\meûl­¶’ªDzäúäáþêr‘ҮΘ“A ‹1^EJ»ºØîãjÎOIàã†pË7·ÓTtœW_¢gy<蛂#b<ăö¸i‚Å•Õþ‹š(ö¿arªOûI{ô‘‹ÜŸIñ"w”¾-£ô!^ìIâf¼;¼è}?ßR‹i/µX2R<[º/í¥û²°ÚÝ/v'j ÒÖýœZ_V¾)^ó¬û÷ªÃÌZ¨ Ž´2c%?Þø‘b?ãÿ-ß×”ñ¬ÂÚ:]!–i~¹ìÒK.ŸOR¼hÒXŸ)$#¼Øc­‰î_‹·ô˜k"ûÙâ%¶Ð=í…îç)ÞÇøaÒÃK«eÒîçÊÂ7ïÔÛ,0M5ijPzßÌžµxŸê¾×÷¡¹ïú>Ô÷ä>´ö¥wßëû÷­ïoÏË%#x|ð"OJ ô> ñbOR ¼ŒñŽ·tŸ:ÿð~ß§îCƂӶïxšhøûo³Ûî‡*šhJö¢Î¹?E —~‰­íÚÞ«B¦©¯–À9FGÇ  H¢}1ˆ ¡£ã„‹}Z%I ·tÀqŽ‘FqÂ%6eµ™J%'=*!–ju!'Üj¬ÃÒ’ ϬZ#Ý̵OöeKººÏ¾Ø~×µÃrŽs_ó?ýjlƒ§Uf<ŒÊŒO÷Y©ìmeÆRE˜nÌXmŨñ†ؾÊçU7^ìS™á¤†L'A6¶N$¥¢“’Þ†EâSµyÒ®ÏBÕ·½Qµ)àÕf7ÞÊ¡j#‹¡jãÆ[ûTmXAŠ÷éSµ¡µžF%hJÕ¦¼ýÚ³háÓa‘AæÚ¦ÁÝÓEé1º*ë‚ÑEq¡E¦Î{L†‘Eq¡Å>åÚ–#?Ô÷{Zâ“Ï)(wòÃ'9Aº“+Ÿàé X»ØN2Eð5]h::ú2 ~î=‚öE W° 9Þ@ýÛQcp¡YnwëÉ«Ûcp¡½Ýîæ¾éÛ­âÌ=íNZn·ê®W·Ñ]ïBK1æYµÍ)© 1š“J/SDÊ…¶òõñ?(ÏäÚ×ÅŸSîä§¯í¶ Œ…,ó&àªW$¢Ë× çíòåœ.vÀU«C4;á–ž¦bÎI73qÕ…$=*–ôTÏ z˜p+Û£¼5—˜¾?'ÜÚö&×ö²y“ÓÂ}úz˜ó”ôšÿ±Q&•еjbNIæbáëb>^t£7ÝÅœ“ÞôEìêb>¦ˆ.f7ÞÒ“Âw1»ñWs¶Ï$¸‹Ù÷áëbÎh¿ßÊ×ÅœÑÞ‡µ%°í=[ &±…o>Þûkö^’þ¾®×βë%š™HÏ­ÿ¬ê<“ï-í ·ô5—„¥û†pɸ·¤¾z¦·$4Û7„SóצzNÖp줸ÄÜ•·âÆÃ’í&¼í3X*4͸8Ÿ:=:– Qn‹’MËjmJ(±Bãfi%å® D‹5ÚæŸA;›æì -­Öö"D[j´oƒÆ›K ÐJ™•¥ DKLÒá» *°†ÊU‡GÛsZàòÀ.4#(#»f+D÷xny.)Ñ´Zè·!¤v¯„ôYmçAî9!ÚÚ }[ЪØHÞ·Ofç§Žp~Où––š†·ûÏÎô“TëÛÊ‚§”pÊÍmj‚û0…ù¸Kyyî$%œ2'›_K6˜_ÎsQÂŃ™HïiümÚRÂ-;8K>x{wJƒ²$¨NÚ«6¥2(4Éî®gRÌêZåŒju9/HÊ8EÕ•åv_õEˆÌÛUŽÞ’ ±÷‰¢ñf’Xµ™’_·J¸ØýAäØÂËÿ3Ÿ"Ù7^dI|›òHø¦Æ‹}9$¯ƒÿÃ×ȤHޤ]_âIíÃ9Ën¼.f¯ß’&fo8ç5%ôi¼¨ßL¬£v×qÜ›‰,Iñ"óÞú6/ S¼8ëõIR¼ØþâÒxÁ/®ÞÒqöB@~º0É’ë¨íúV]Œ;Ä«îÞóRŸ—u(ízo/³>ž´÷ïsªw¬Š‰RU½ûþ§À³¤sÛüNûÛ\x—Ðái—ÐÙ øôO ;¢(øs»§ŒíšöIÁÚp9bÄ5[ªnÝO¼¥‰3â•÷4,ÿ>œ ºóª{„£ºK$Õ=ÂQÝ%’ê…PÝ J8'Õ=ÅQÝ£ª;)œ“êžâ¨îžêž2ÒÕù©î¤Gešê.ÐT÷Euhª{§ºóª{„¤ºK$Õ=šAuŸ¤žÓÞ½–ê>M­§=/~ª;í÷óQÝEA»Ÿnª{Ž¢ºGATwRã9ƒêNz^fPÝI¿ß ª{¹PÝ%’ꡨîIu¨îœmšê.ÐT÷(€ê. ÑüTwÊôSÝ)O‰›êÎQT÷Juç!T÷Eu—Hª{„¢ºK$Õ=BPÝšê!¨îMu TwBuTwŽ¢ºGT÷”ÍKu'=“~ª{`, º Õ= ¡º§”pNª»ÀQÝ£ª{Jº™~ª;éê\Tw‰¤ºGª»@SÝ#0Õ‡PÝ£ª;'½æ~ª;-žŸêNzüT÷”Ölº©îEuTw‰¤ºGT÷Au‚¨î)žŸêN{\Tw‰¤ºGª»@SÝ£ª{A 禺sÕ= ¡ºsJ8Õ=0Û§º“<‚æRÝÄ’(€ê. ѼTwù"DsSÝ Õ=‚RÝyÕ=ÂSÝ J4'Õã¨îŽêžâ¨îŽêžâ¨î’êÎqT÷ÈGuw‘ÁIWy™õ”DzOuŸàžSžMuwù)¥¡ºOsÏ%)܇YÏC˜õQÕôdz©î9é½sSÝ%Šê…PÝ)7ÓOu'õ>‘˜†¡ºG8ª»DRÝ#Õ] ©îœêÎC¨îQÕ“âù©î)^âIíc¨îQÕäûͧº%)žŸê^ây©î’v}ª;Šzá©î(j}DuOIñüTwÚó²¶SÏEõ<òSݧ©õ’v}3¨î‚ÐGuÇð²#<Õ]¢¨îQÕöz©î‚zKÝT÷Eu|TwmÖ·{>u xÆ÷™'à—6-–?ïÃì¦Òï%˜OìB‹<Éw^æ„hªTóõWe‹OÇs˾;œ_/–•IöVPÿú§æ†ê±aL?üίü%4k{Ÿ•ôû×¶“•o¸Ò|·÷II¿Öïö,N‚tm:èX“¼yøÜÙMB4uÁ7Ýx¹nLù£I~ÝÛ˜òÇùüÃS°¸³ Móy[DŸ*·çR€‡Ù»Ð|lÞKFð݆ãÉ6¿Ýä¼w2o^rJ¸ÈÁå•—+»ý”p±Ã dH7ãÝâÓÅx7IB´Øg˜iÐÞÝÀ”Ó)ËCNˆæu4ßm® ÝI`7‘¢yÝéNzÝÂvÅX7ÀDQ¢yÝ#øn7À J8(o?œ.ö¼r°Hlt•Ù¯œÍÿH Ñü¯N6û5¢ù_9!šÿ5@¹6ÿk€ò»ù_”;é HB4ÿk@¢ù_ß ò”pþ×€¤„ó½8 „¼8!šÿ5@‰æ  Í~ ¤„hþ×åÚü¯J4ÿk 'Dó¿(׿ B4ÿk@¢ù_ß ò”pþ×€ „‹}óIãPâiö?ï-b“óBãIüh‘§©‰sʵ™×À¿Mk˜;7ðbÕK)ÐÞÝ€ü§Ý@Ø¥gí¶X ôùÑL¯Ýfcûnµ(ÑÌ™”ÖSRûNˆ¦;í~m§äY\§\›ÖjïkOIc*ó"£DÓRB¦õæXG&Z.Š‚r'µ’Ðëo7ž·Z-çŸô‘R®mí›w ¯<‰6tv¨fqžSÂE¾Ä[ÒÕžÞ]„ˆ¼n`ÚéHB´È×¹‹p:¾¤ËÅ¥„hKŸ‹K)¿[âu¨”ßíÃíP9Æ¡zÓk÷¢EN÷ÍQî;ò:T«û8÷íI¯9ƒIˆ–¸‚ <é5ghBy&WÞЄr'×>´”ò”|z!ʵén¢I¸w9àÞÀ‹ÔvEN¸ç9àb_ —“næÒW’•ħ.z!€–ÓqlA ¹âØÇzÓÌ®°9¥„[úÄL·¤ß.ñFé¤ßîÃ¥CVÍŒÒ§ãæ”Í›¬I)×{â¯Ea±%‡Å–ѬØÒíIB´Ø¥„hÞdMJ¹¶Ä4P¢}x8åNz“59åÚÖ^ŸZ„£ÍLÖ¤P¯Íó©.¯Cº:ÕÌýûjŒ×a¨°êÈ£Ø"+O¹üñµ]nþŸˆôïzÍÙ—7zMÈé¹AN'™‡ƒÄvIçºÎw(ÒséÕ«šò®݈béþLϯâšy™3@t¸!ÛÊ×ÛJò+óÆÝ3@téPš&¸c§»°Ï~ø%óºý ¦­Q娷 {y»ló+ÏÎÞ—í µQšœCqõ»Ý Ÿä׺Q^)@´¬¼úò–ý:gû¥^­›×—îï<Ô<]ϲê€ýH ÃP­ƒ"+}ë7_í­oת»Âf¨ªÍAY¾¡Ô×Þt4×מåv!@iîýæKÇÆûé÷]xvc·{F€òѡԽ…¥Vo*éPš›¿ùU=¡ûÃAIDÕZ‚§âõÚ2 J4~º¼ƒÔÒ€ˆt[–á Úëý¾O²P'ìy’Uü¢ñWZ´$• D> ”óŠlrÂ*~i¬‹QÖåv¹IA’hÖP…äd_ÈÁv©Žê߯oP¨õ* à‚eék—¾ÂAV#5 »ÝN„ƒ¬-+é@ÄNìvá Ÿ& °†Fùå²K .ãYÖôp8|yr}‹[Œ(ŠöÆçËdÇŒÏÿkEy”)É×ÿè«ÍPØE–&Z”ï6~á½øå!I¾þÚþ8ªSÅ%þq4Dù´?ô ò¡7 ]õÝß¼þYŸ`3f?ÍAY8z%¿gw”Èþkv ÿ8¢Ä ¥NÊê'Xónit%;ýl³Š"hl´ÄJ;÷¨NÙ_Sy?ïÿÒŽŽŠú DYK¡*QÆN0÷±»]³Ûƒ Dz-òŸu-G!ŠŠÇª@ÉèY²žžåéœãÒ/C”å@MH«f6â>Ûóý’^(Ö’ ¶õ0—F$i{ž3¡pÊPÚJ+#i”9sç ¬rHFìYiæ;¶Ö'ù×È‹¶)‹ê$?®×ãÏ‘åÓœ±o}ÆŠ:cü,ÊãÅ­ü£a~ÿµ0F¹†y>Ï/ ˜ÅxÏŒ$k½g—BRìÙÔs¬ºþûâ!±)ÞŒ®¸¨ÒÜAY•V(ߟù €Yvùý §]Muœâšc³¼#˜D¯æ·]Mãeôjnùù¼§€ùîlÕÏ?"ÛŠŒe~mÚ(û”{F£+˜Ûêì©…9ÿQ êa#M‹“›¶œöæ;žþöŸY^Ó:F2mÇHf·ÅõŒ–i£FKx{}¼ €‰’ŬâPȇx”0ZšN›}}ÐÚYaÛýS°ÅõŒt°i7í܃ùyŠs‘RÀ$oÑy[ºÐ¦3CFç#˜aH«µþ›ªÂ6¿œ Ý‚ØIá³ÞrÁö¯3ɦ­G׳ƒiî ‰¿Qï³×æKmZ;•¤Ú4ñÈ…˜1rVTûgL“h‡ó’ýä'Šk+°1’Žo3Ž_Ås[ÀDŽQÃ?/®W’MӌƎ^ÕµŸžüRþdñs¼túÝg·œÂtƉýõ¬t&Ïg ïØéÊØs0þ{oÕÕ%€AüL]øï´¢lÀAY4C¿áÙëp»ž PtÈ©¾ƒÒ Ò²Ûî~ÉP&ê×ú»„VÉߦ ¾W–MZ£Nžìö÷'ÊÇ[=öxèê±ÕZë±ÿ JËeß (ÊÒíz•i)x@Aö¿am¹’µ×lNrP1ë¿aqÙþz ,Ìý7¨.ÿþþ=žxu’çýé@€¢5¿›Ñ£¦Aùyìï(o匾BE}ÆÂÊÿ½¥­KßíI潓|,ÅwYë“ܬeß®EŸäý…ggìS£|oºûÒ¡”PhøoTc¶G³¹æÿEæ÷4°v—‡K6‚‰ÞX}šs}°¬ÿ"ã–ï¶ì«µe Œþ6ÛTä9LôÆ2š,Ë`c¬™Í%m`ÛœF™³ï¯¯‘cæB²ÓíÁö0‰†ùíEÆjJv¼_Og ˜·ÊéРa+§#˜•½tªa°EÍŒ1i«I»nqõÆÌئõaž[AÓ5{t†-mqÝ]Y5u¤›IŠ9;í.Œ'ßо!`×eÖÿû/µÛ´4é ’&=‚‰º½Þ´v×Dºåø}wÏ £ÈŸ ûÜÁô^:âd:F¯#Î {Ö†0‰Ý*+ÒŽ`>tYðÛZâÌ®þÎ)kóKSêT]Ãm’ß¿Ç=ŠÛ4‚‰tÍæKS4LSLûýYà<ÛÂRå¬7M3èNÝóYº of5uÔaV# š#°Um»Ñ6Ûó^Š‚ä@¯»ê :i̧«¥pv<Ý~(`>‡šuÕAÁÏ·ôFrÒL±óÛ;ÛqõýÌ%ªÌ1ÆÙeÕ4Î5{f9 Näòl[ ãô–B$¶¬:ÆYv•HåÛXÏ…¢+‘cœ¤«ßjœæ¼ilývŒ£Á¿¯–Áaœhm Rd;Èg5Ü—v#A/;ñCó}ô,ÐÁA”¢2r§ ΧÆigŽvÏê çþdw’õDÎ,,Óá$ÁÔ¬ý>LnOgq~’àD]¨?½¾ sòÊôàêDcœxxμ-I–¯ëéIDF¾á×–÷(ÊÊÍàDƒ¼ÇkÓõ»ð†s;ßeQûì”ÆpÓtMr„>OA£g;÷=†œ¶{¾ÎÇ’“À,;˜–eFH§ûëù˜“lZ2Buæ» B8J׿£µj BÏ»§€Yõ'Öj˜´*þ¸ñü‡f=Bû«ùÙÅÑ{¯k³švŠxÚNžr~$¹ž†G­‹B/ižO?7=Oø»]r;çp?4æ&ÞÐ. Ý=y†Fo=¯z=†¦j¸}Îþ¾/IŽAÇSû¶†¡ÈÆ¡1NÒUma(²©gŒóÑ¥tÛð°I±ˆ-Ï·?âù$ÁYu9]îöpNW~=à¬ß$«ÙÖòç†kˆãèöÁ_k5¬<ÿ”É÷i¶&j5xÔþúùD8‹^ú¸ÁQí çQ< š}3|µ¯6|7ah=žÏª:'¶Ì÷îpȼa¬õÂ÷'ãâp¥±oвööá=œýíIì[ôáÊ»Ë2ð×ᬦûú¡Ý‰ÖÃïs6̈g]€?h"Ä–¶6˜ïnž#òºß’¼=ø×´/ÕÉ0Ó$U'Ã$*œx¤€ó†Ò|ƒ‚l’¢D%”´§„Rb}\<ÔÀª”¤=•’ ë±ã‘Îæ¥zÖwmc|=J9Ã7ÆQ’Ê9íP°ñC”~Ž7DYyôC®ìJ€²ÖéˆM[ß34ì3ËY=ûçN€ò9´fg£ërÉ$»ŸÊSFq+ÿXúü{úD,Ã>Bâ±N[«loŒ‘F`å)§€‰º õ®×ŽS¹•çgöĵ㨼Êñ ï»E©«åv@ö½£D*|’_½Nÿ6|:c¿ÌE ’_=šG;$¨[ö(Vaõv„Ô÷3Нn›JºÀ©xÊâ"o7Н¯eC[Òºj+Ô(»¼n_5F1¹Èå‘ßr”õd«Ç™oÏüÂ/ʧ=¿^›²:7€Ì¯nåŸA§Ç‰õ`Äíq=‘\~ÿïe×Sm˜+˜û!»’¬&ò4”`ù÷˜Øž[Wn[Á,-Åi¯±¸@öF `’®Kz×ë,V–¹^ ²wó1Öòí.gÁŠÛ± €Y tûШNÚîZEš$«Yk³Ù5û°žÙÌÑM ˜Ï¡ÜrK(¯`Ľ®žF¥*ÃùÏÀœ{0û;Š“¦jRÓ=ED–S—¤ÞÝ€ba6nà°»Qh8Ò‚©TMÃ’ÉŒf9n0O{ æ"ÍI§¤ 6ÛDgÚ5þ"#˜[ëK"9ñ¢ð7ºïoßô"4FuÒ4ÙSEèû6T,Ìê°Nó¿QÀÕ!ƒ³5C”‘¼HËÀ¬ßNXRñ%¶t•ôú£úe©ò&µøb“7áU‰±’ßnü†c“Æ#çw˜F¿J÷ÛSÀèš’ÊÙgÕô[¦ oý’K\ŽnajÃi`N§ý•féÎ6•[šo“¸ÓMÈÖÿÌÇXR2íI2ídJ²š•M3íÉcÊÌ´ôÓ9$«9„™Ö~:‡¤5G×Ó§þ„{Œq|úOçìL‚3­uáãÄýZ+svÊ.'F‚³´)˦=eÙû'ËäöpN¬Ø’ÐŇ;/¸eG`ôF¦ƒå6'± ÞüZÛbËn§áË(쪽  •ãa»ý}û8RÀDžV– [ÚÁÄ“ýyçö‚!ÌÒÖŸ—öúóBîN“XúeºM ôÔ©VxHµ×ñYIÁÂCÃG&¼Æ8±¥×¬Gó)¿‘à,]q‡ à¤D¶âÇ{S[×¢·—§Í÷æ=µikp‚M[4p;_]-¿óna4¸w˜¨cùš’Q&дEonÇáݲí)§€Q)©ÔaºÖ,õþx•÷ëµ €I:'Ú\ÖV?ÎáN4º¶^ 5 Vðp³ê¼›‚QN´ v¢Ñ°Ø^kê(5"@ÁìŸÕ›Šä¤}zè–hÔàzþÉ4GM=ÑR„cœ…ÛîÒ— Á‰†öæÜu8Ñ:8±‡ÖyynIp–»Ö—§ëb v×Ñ»Ûu™¥½.³ÃçÃí®Ó]ˆU÷iwMêp<)–Ý <%î=#åR¢@¦Š¶ŒÔXôD“"Ñ¢' [Fj:‡Æ#d¤äkóO‰*0m šÉå‘‹¹zëñ{io1ª…V ºtp>©’[ÃWÏ*—½-ÊpeÕª•|7MYçg¦ÏP¤l·ËvE8H¬A¾ÿµ i ²­‚›¹.¥Ùµ] D”b[¼ÂAôŒb‹ÒIz‘üüä{ò1j1ÕÓ•šÓWØÈpU·í6Ín/· ÁJŒÀÅæÛH©4ѳRž8ܶé™`%Ÿ£VÙ3ïZe÷eúCp„uíËÒ)ËÏyzùá9Án¥-6#qÃx+¡Qœ¶ÏcJ€×»o¹íÁ·_ŒÛØ;!âòõÊÊÅZ´r¯%\J/|—Îï‚q¢$£žsïëžžc™Q\I]Tû²d6êµäóœ(+Ç@™ÒÄVâÅÌ4‡”Å5¦ZËü4Nï@š‚ ,}¢êI€’ø4ÕSŠïòá¢?î8ò$ÿ±êÚÕ9(ª;QÖ>AuNñõ?zê²HçÒÜ·òOOQ|~M™ÔS/o9‰qi~È ùa1˜j—äG€ñ¡v*~„1ê Á\?œ(K_ ,ÉŽ%®LÉ1ÌõD¨'Ä «36_ÜÐê”åúwmC=(ªÑ6, «´¡Q‚«¥ %ÅZ\ʆÕ›¯lèDYºÊ@Ç40Xz+Õ»´˜^9ÊG÷ ¯s‹æÞ°këN^±Å|—ÿ†Ó໲Béqxñ …!Jdr#ß:m¡ÖÒdzÔZ ”ØžÑ(ÕZ$ÅZ––‡RÚ{(Å‹%q TOË# ”î-¾ë=-Uøç4ŸwäDY²äÝ$BüCiˆb$¾­¹ëÝ6{q”O÷sl~¡Ù}+ÿt‹±ÔÍëÅP|~’M>”g×Ü0‘£“¯~‘Ș|aåQN6òý¤(‘£/Ï}|N”Ø×Æ÷Ê P–®.¾*XšÝYãDI|M|{Šûðõð N€²r¿a‘׈²vu𱺃â$úøJŠ3¦LÙD-¶Žüv—ƒÿÏÇ M†pXš±ò–8ÆAgºq”ØÅ"Ùeéþ.ókä±ú³˜ ä Kä!ÎÀ9v¼û‚<Ù€sì*ß8Œ¿–8ûÛDøZâüp9 ¨%ÊpØW擯p¥³`Y@ –ÑœZ⨗Ã*p‘³–8U°ä°‚eä¬%ºË|E8ÈÚ[%ùôÖßr‚ËøÇ[±$¸(&à·V,SXÅ2ÂÕsX-1 ©%R|w-1‡$£Z"ÁAöÔAé±WKä°ZbRK¤@‰¼U¾”%vT,9¬b…Ô -‘ ¸k‰y’AµÄTKŒBj‰gÌ]KÌ!µÄ(¨–HrùýµDŠ=sÖ9¬–…Ô -Q ¸j‰)¬–…Ô)vÌ]K sýój‰VKŒj‰² @ñÖ е¸j‰)¬–ak‰y`°4¿–˜ øk‰˜¯®%¢ ðZ¢$@ñÖ еxj‰*_„®%B*–‘¯–èªòQœ±•·bIâ¯%R|w-”ç‚j‰œfáy(2°²–ÈaµÄ(¤–˜ 8k‰TKŒBj‰)Š»–È!µÄ(¤–HñõýµDŠs×%òúÃk‰'Ù_K¤Ø1g-1…Õ£€Z"2V†ÖŠ»–˜#¤–˜Âj‰QP-± €‰<ï¾ O©%’lšú6_Õ 8ÏmªäPY–•s[–¶2/…QüSs¨Næþ7 ?»ñ˜Ë%pDC#Ó»ªŒ Ïž?Œ‡ƒÄ]PÖås]æÓ’ëþ˜s.÷oþš,Y»]?çã6¯é á ‰c%Ï긒`%ž|ß©Ä}“ÿÆÇk"Ý'/{vË —pv^„³­Ö7b.WvŠßm˜ãBf³o}ì»õS¦¥,y8ˆ÷ÖÏ?a1öÖ3À­ñ·žb%ž[Ÿn}Œ¿õóíWŒ¾õå-ç(Î[Ï@·>¸õ%Jäõõ3Q[>Û×§á ~_/ÃAü¾ž`»ü¾ž`%~_Ÿ‡ƒø}½@@}½$@ñûz°aó}½$@ñûúÙÇ8Ä×§á ~_/ÂAü¾>ñûz‚•ø}=Á‡÷ûz‰úzA€â÷õ2`ÃæûzA€¢´oÿÖêIÛÝþp<°¦hÄÓm*RQý%FÇ8~Güb´iý\ø;&4@¹«à€Ôо¾ÃöÀ:®°(¯"—ùxÚ(v¥rL€Å-õ¸ñ†¤vh¤ÏÕ7µàa¾Í¥`D@‰úõ´@L)¥òßM´oêÞ_‡‚åD§ne€6>ÞPeá2¢­Ýß(·ŒjÇ}:¿‘”¥$ju‰ùOË"Ï2^Ù…t?>©LßøGÓ}R®‘î»SAô•ZN±YÓé¨ÖÄ*$8åšâÁšªX§Y“B¢\“2zÄéao,ë£ÈxVÔHukµÎïR#饑Du ‰ ào­¶WŸòãA‘sêSÎË·÷qøŽDZi¤ÍÆŠtÞJ*$e"jþŒFj¢T¢"-ˆ>ÝH/ˆ¾S¤û þjkÄØ©µFU¨]n3ª-œHÙ–I¢›iŠc3/¾ñëj²ÒE¤Û2Ýæõ-&BŠÝHBpªÝ[êXE5PÕ± gm¬’WQ#:{ÍÄ I3ê«“×,J!í¯EžeD÷IMAÜ4ž°ÚOxOËœ‹ÇN–d»·2H›©²{©Þ=ª³§mÄWkTЯnî¥2d»glÄ¿Mk#:$~¡CŠMORµ¦]ïD4§üQ_¨’h÷bm#¾þmÿTݧéQl«»d’nMÆF|ÿ3HÍÍUH™-c7-Mñ½é¼{GÜ«ûKõ’î”k¤s/bÙïodHzü{Ãúi†–5ã/žÏ³üAdËãÕ©™/©‘ªçÑû6^k¤&)Ô {HûzÒ(Ò§FúÞt»×[Ó‘ìD,Õ[£‰Â’ŠÂÒI>ÒB#É-RíÑ ÒöIõô\Fý?-3ƒeÕ{}{Þ9U »4óD¢iƒÔœ=tÞçTþi¹ÔYœM›Åi"KÅ)EÊ‘§Ü4ßH:Ó@Õ_œ(Ò¶è·}Ó4ƒó´-ªV”æ4@±(9ÑÖi;.¿Ç/š²Â9¨€´—¿Ý#­¾Jh{‚è£ó;ik˜íMœ\æÕÒˆ¾Ñj tæP‘­h=òµ}X^EIt¼u˜§œÅèZ’µ­çß–0ïžòœ © ó¾ÍWjDÔWz–y)¨tvüëkœ¯s9•7Dšðÿ"[#ò;’I×H²À¦‹FH:?þkK[ŸÓ¼^ R}uíÕUn0$ÿ:†ZŒ¡ø¹ƒÂ'`ÇPÑ8›¶9ÄŒï·Õ•ZÄÓ)ØRdÁÿJÇF¿–\9+rVHI•Œ¡L²¼†ÊóœìX|tyÄAŽ ÈÒ­ÄçÇP+7>9:†Zk÷¡ÍÒ[βúhy‘‘9ßÏAÒR[uu9cT‡]eÌ7߯¦½µ3*—x—ÙŽÎÑ/4Ô¿M U¯JCUÑlIåAtÎüïoûæP™e-${ät¨­Åï_[âR^ž)™VYsk>±>ìg‰ÎŒ¡ôÍÍÆ’º¬% W¥­…l¯0×®±†ª]#™ŽVc(eTžæTW8꽨†'°rÙË1Ôç0IßÀ * }9Ž u^L 7f³ÏKª Œn¨\fTÇ"Žt®Í+žzPòQY]2¨XC}ý³$eu‰S²×Îr˜—U!§‚:dÅ•ì ljþVMo™NÌÖÃVõ·Ú±œlÕ3¤ cƼ­ ˆI·ÿ ´¸š™¹VµgÔ×* 7BŠÜHøTÜ)våâ²úr"¤å°NÔZõÊW•Ÿº!%c$mÔ$|6n„ô1²é}C%!­º4™) M6BZwÉ+½{MòJíÞ³”èäÕéS§”~»z›@Hù¶vx¤E3Rô-yÕÌÖá3ÓHUøüÊ«#_!En¤CbÞÔÍýýý×úÎæ©]#ÁK*¤¥Aúî £¯F*9’âfüšÝ{K)]…,÷\!éäÕ¯-¥T!å×’ê쭜ߩúoFuöÖîï”f)'BúìRCÿT=q¶•Ë¥B2É«)¨<';|&y%7ß:!¢|¡Jˆ”ü~d«Š†©ƒþ{þõ“ÕA_è$÷÷Æõ¨Œ#³²ªøúú«^SUxYÙ¾sã:®Y‘fO™Su•¼ª ÔË·‚:_AUQfdߪ÷ÝõLúEˆmY3§ñ9áÔÊ U=|%Ôz”ég)öÛœ‘­ê³Kˆ K|¬ÈÏÕ·2tÏ¡réî6°B"„ê=Gw??GÝËSsîâ^þȬ úVQä†ÊËœê[EñèåÛŽò+>«>‚Zv/_µª“¡ŸT«ÊC^¾#¨ö9jc$eü‡ðX|tlµ*X¨U=ËŸ’J¿ ~G üê§®õa“Wjæû@(è GßߟàD“þ·þ 𿜸«œ´yá(|åh€³œ´{õ¾$‚8I‡³Óï(M ©Þ†ù•å,%Áùè±"UÌlŽ6Cà(iÖcÞºßßí¾ÕÂD†{’±Ã™§×ï Ö£YiÍzÒ2„L'+4=^»^Wý}DõÌ­"#ä=Ç½Ë Îw‡£h' 'Kip"÷z8ǾâqóôzŠ¢,hpŒ<©b'ûÈ.wñ Ù·dÜEÆ;œ;X»[[™Ûõ¼÷Ñ­g5î ãÝzÖ£Bµ!eÔv4à 8Àùtãà_µÃ{ú§ãŒš¬ò ;"ƒ°°q$²î» ÛX‡@ºÝ`£›Ÿ‚¯N=Ü« {›D[;Ê-ÃÚì!qÞ«ó¾n%#J: ‹÷¾\vŒæé±(:¼SØÏ,':u«1ƒýÿhmhå­ü±ç{" Ï1S¾¾G†)/Ñ=Šþ˜††®nV#™††:ô-z´ÛQ,÷H·èž§!PÔã¹:ŽGY>åU”•-¢ŠG@ªº©€ªX.£1AštÑÔ6[:]Ú6¦ÕêS mš‚·ŠOÕ³_ŧ[<•iô1zൎ¯¬™`è¼ „ß%6¦q$Ú‘p¢éæì²:oì*ipœ¼À²zyá,§x™Hä5¬Öêû?$ßÕ5&’Û‡(Ñ6a€Ó<$¿þ58õ¶œüù¼ŸÎZá4é¥úrâŠ."Îûûë „$Âùt>Œ³màÃø]Y£ñCÿL/{£Ø®{Ù«§'2‹ŽomÄBÒž ËåúºÓ7ôõ¯WkåOäî¼Òéõïo»u¼·uå븣¹«:@ý’߈·üç'/›<Ñi:…š©³ßO,­­ö^r¾«žÛòHÔ+´´+j·îò8ä;škd$5z‰ŸÎ±nÃz÷â±¢Fej Æéµ1@‚烪J,Ó@¹|Ь(êõìzœ õZI«­Ãæh# 4àZMàT_HàD“Oñê'D]e€Ó Ôzôø«f=, …`€³v®·m%ÕOˆ>ç×!?~µ¦çý~àŒB…£b`þÜ£IŸœ^ιS¤é˜\øœógÝS(åœCÚè8Ÿ#%¤^¨Mq¢Ñ=µá„ÛƒÈwO«Ð'$ÔŽ&Cú¡=( Š{?gÖ…ô÷4ÝÓqHOqOû!}jÿ5!°~}7!ðcÏ/Œæ¬úö ³oõ+{ y:DÖ¾É&h‡Ê[‡z H[D“!½Åî„ô‘5¤ÿ6µÎó®ß0KåãB´èôÿL ¥y¤ÔEiqyÜi€"ý‰¾º˜§õ'â‚ïi>‘iÿSá¢yvq}æBÂÅÈÒ¿¯¨‹â.µy Jº žúFª‚W[…‚ "ùλU¼GWÚ ‚Šä;ëv'¸R8äÜNí[hå3LÜll•Âç¥Ø$8¦")ûº–¼ÅI¥¤ù>œFk’›J!Îj°oïIº}[O¶ÎÖ‰²mž­çs²¸Á‘2§9omEòË*gYÏ: šæØV+ áØÌèv¬º¸)Êmž1NsLÂg ˆ•aÉhÔn å …Ѩ1|cM7—>ß™µ“ Àá©3Éok鳸fœèÔ™Šäfc“Ôz‘ƒ°T$kƒj*’‘J OEòôX‘òiõœ¸S¾S¶›ÝOqÜÑi‰åFÔ´ÒÊÞ ÐãðÌ.D–Á4‚[k¬Ûú„—4§.Z¾=¾uŽûãö JÞÒŒu¡#­Ï·.t”"-ˆ€TÚGÖŠ/ÍÖé@«Ùº#;è´Ïhåâœå4@êAÙLKP‘£zݳüz¿æ—ã•Èz«æïoEŠØïŽì¤LP­]žÎ—ÛíB³uJ6µŽéÌŠÔ©S+ºž)Ñ©Sª©õ}mŽwZ0¹ùªÙL[* ¨´;믯ºëé§ÌŽ{²ÅöoĪ˜N}£=Mü¨$S¿6j>Ë©jR­è|ªÈ[Nt”bjµ¦oõt­çÈ× “Êø-Ë·Û;ÑŠT¢IO:U[w2+:‰ê!^l©V´Rßè÷ï?õX³ u·K(ç§ZÛšÃЈ¯ªH´ùþ«ï‘v±{YÞÓüÁ‚hë–Ê2TÇ[†ó©; ’gùáy 9 Ke¾¿;69­s Tžö÷Çþ,n4@Ê2ȺݬuÓκ×3ÿ¹ç,'² RêÛŠX½ ½¢´ o4QJ­Rý´l¼« EÕ=ÚÝnÅñ²% ‰—Ú2ük¦ïÕ¬«Fä'O…¸4ýå4@eÍ©Ûîᧈ§ÛÇå"oDÉ™•^Q£ë¾¯ÇÙ7¯òzER.‡×HÅ ÕëÿŸ²uÕ9¨ó Õ7b»Ê= ¢Hu©,×JëÃÐ4n^O¥xUŽ(Ÿ‘üÕ÷(Õ@Åϱ¸RË ]yÍ%PrEÕÖíÊí±ÈhN]ò34m¨hwÛ•üXÞˆ€b ô­7•ÝëéV¾ªoöC´uÚ2l”e8V‡›©’ÞõT”§ãó²%JœDÊ-+ õšøýnÉ?çŽe$¶§ì"î4@º×ÿû·2+ª€~Äýr¥2"5U¦¾°†*S>ŠmZi€>;9½èÄRÞ²ŒŠ&Ø0ClÔy¥YÑ©[ãű8ýÐ-F¬Ú®¿ ™ó6ÒÈ×?½¢´“Ý|Šý¥ *J|˜žCÐb*¡Ñ´.Åa¿Ý-1vâíC,çM×. PÒ NšßÐAršHõãC¿aëØ[ÕsÔˆ–æ ›•Ç'QêCSQ›S§J{Šr¦Z·ü@œ|¬Ý@ò!iž-Ÿzë¾ÍÖ)-^µuìvÜ­hõçÝñy›´¯ò㵺¯4‡aµ°iÇ÷S…3Ñv¥,Ãk£UëÓmïuYôE”F[)íÊÁí“ÑFÙþš¥Ù‹hë´òÇ·Ö‚6!q ´¿¾^é+#: ‰N£}«‡X=˜ë‡ØžoOü´'Z‘Š^*R=ìOU¨znÞGÕÃh{æ… úFÊ2lþ~«ÉÕ)šñ³PEª+üÒqÝA£è.ž¢–g¦2y†oã&εúŸÊ3ü<òÇîNc‚ÖÊ2lôc¹ÎgÔoeÞ=òó~Gô´\ë×D-_¿øêüzýX®^|"ÝÞAd‚Öú5ñ­y¼g^Ÿ:•9)žy-_Bc‚Ö±h_m‰ª–k3|ÿš­S‡Am]y{¤ÑaP–a#•õ>(ÞýYߣý¯ñ6ÒÈ¿µ@^“ÝÒUË&»•æ‡Ãè­@EQDßHçä¿æU÷5m¢üêåâ\Þžé‹è)Ë ¿ÿê7ìùÔÚ:¹×ÿ¡qŸt¾®™“rh/l“¯;ç— UÌð¹PÉ[Ý|4V¤¥|Þ÷÷c™ÒïOe^ßêÕ¯£¦ £úFO¹»ß¼ 9ÞŸ:Ù”uªÃP=˜Înå©`·'•?ú\vÇ[¥ÑX›”òvßžD@æ5¡VÔæ‚T’ío?¢S§-÷:u[—ÖßèΩ¶NÕ&^õü?ªCÇ›Swß‹¢ ЉÃZçTU\wlŠ-*®»]Î?Õ‘¸Ý#­‘Òœºž£Òú¨§âk ß_£°f&5Nu¶% NäÆa^³Â¢ßÛß73Ô¨Æá!õëÈÖWòÛöãp=áªî÷¨¢…”'ãôúJ¶õ(-œŽðÖi@Õá}Ó÷#¶×”æ¬:}eÓÓÎbA)“ÈÖWbÕ€J«s/PE¶¾’¿¶þ¢=ߟ¨îéŸe«/Á~O'" ÅX€½›·(ÓgItÑX½cRe'Y>÷4@#ÞÑ[ÏÔuËñìîÈ2¬¦™ß¡$yFI.l+“@tè4#qH¤ŒhE}³pèÌB Ä®„fÁ´ 6ƒ¦ô7ªýƒþFÚ×C uçˆ­Š‚Àá ©þòßhžUìÀ#‹cµ­'Ô±FÇ:˜£Vã;ÖÈâXÇTòpÇYë˜JîX£¡cýn]yGwxÑб¶ Â'ýÂkp‚oj4éXûzá/úŸwfý}‚xäp¬o ¯Ïý‰h1fwkѤæ„:Öh¦c•?%VÛaôæX‡Í‡a„ÞhLõïzµW`׺›r”ŒÚû@·Aµ"Mèm:§Ý;EñlËBÃb’¡„v¨#]KÎ%ý1Ú¶Pa{­IøÑÖé§ñ獵‘»Aµ4gý£ÃoW:L9oÃ^ä4ßH‹ýþþµˆ±T+*Ï PÔ¯õwNOwnÕú£1ÕzëBòјê?¥W‘ñ3Zhñ¿Åÿ–Ñç¾Hr(;SE ¨ciUx³2»~î{"¤ÞÙk™iÇD?{#>û)g%ÒGwÊ5[¤]“ 9å¾>ÿ¥±‰ÀF¼+õMM cùãpû·Þ§‰S^føSMß'ËÙ 9‘í>mš éxzz“!…ø÷¨Cúcæ´÷7ïH V+ ”‹œHVýú6˜¹™ì[äN%Œ²æR[÷«¨ŸÝxªf„ðùu¨,,ÑŠ–hÓé­«€ªÅeDß(qo]*÷D@F¤)iœ;Ùw)˂譺¡ -й•}Ïs^­Ý@R€* OçÖå’ " ](6ÓuÞÇ¢åéþ~|o])~ŒV—Ò4Ò}w*¨ŒP4XS;-¯)ׇ£5kRH”kZŽ$˜ ƒ¤ž Q¥TkJÆHgÞ!å© ZÓ‡}² ׃ˀ²ì.¤•}VŒAÚÞs*¤Þ¸ÉNê—k$žñ"-ˆ>ÝH§2¯fÞòWo`µó¶eM*Js¢¡kÆ“HBpªøA…­€Z1Ù{Zæ\ˆî“™ZU“BûÌõ)¿%Ô]H=Ñq…tfX¬Ý…´6b¢z~¹Þ½æ”?ê b¯¸Œ°ƒæ7²–߸åM-œlM±&¤#–z"ι•àå6£zbÄ 'R¶eT6"ֹʦóTíS)°z÷ꔕ…c7׈ۄǦ‹#:ï~ß ª³O%¨‘öû’™Æþû¯¥Ö±Qum›yŠ‚?¨ÎÞjŒ¤úR-Ž@„´î&Ì¿³oöé…ìæ~í×M·{½5aC\/\CJÝl¤TÑŒ ŽÝp!-ÆÃIU»‡BÚ>s*¤ÈL'ýL'å5;ð¼Ï©|n#7OÊ;¤}‘SŰJ5n£#Ë}/²l²8Ud„÷ Ï­Á{KM‰kʇ@шoú šaót+ŠÝ@t+Z:€d ”%n jëR ^OÁðVV8‡y þ¾ÏË6@Û‹4@ëΫït¦M·Snë‘<)§úFŸc 3ï€r!¨.ìŸQøÐ9uYçK*¤Åd«Dt-éZ:“%¿§`ƒ› É„yº2Ó<Ûçí³¬«&DHKçÑ«S–DGÏ Žœ8{iuöˆn“IYÏ^Ñœ=*¤•ãìÍÙ£BZ; &¹¨þ–¢¦õþ¿nº¹£”ƒIò we&Oå^ÒÅn Ž. –öd<ï’ñœ(±—xW^ ú˜®5åu­‰gD@«éêYÞTÏr¢ã½v~#)KIt>Ýß(—%³2“6•*$We&m*3TH“•™ÔTf¨&+3©©ÌP!-õYo •y°UfÚlj@Tkú°×D[[ ºNý)Í6$^¤Dî¢måT›DWm*ˆ>íÕ&ÑU›ˆND4‘uå]Ö•è;E 'R¶…fu!¹³®’îìE¤;{º¡o2㟦%Õî%$síч#“,›L2ÕšVŽL²l2ÉTHkgý1­=Ò§©z±rU™™®?Vñ+U@¾pWó,#²°±£z+šê-ÙîÅÓ5UQ×T%#:{¦23¬tŠ®ÒItöú•™~¥St•Nªï4Y™á¦2Cuö&+3 )GWfFH“•n*3Tßi²2ÃMe†hMÓ•n*3ToéÉÊ 7•ª5MVf„©ÌP!MVf„©ÌS™ùú§‹êÇ yŸþ‹Lè½4ÓG2ù¢IØ1BÒ £ß^G¯I”ç4/Ä!Åc¤6cT!I޵#$“2úéWqYy &EA„ÔË ¬¤T2ªÝÓI#ùÏ$ ?¦ÎåT«;—T'Bg¤ÎUšÝÓHEyTßi=Ú=£gVïž”’lMŸîQæ’ ©­Ñ´cžÍÕ­ë[! ‰1Ôb ÅÏ>#1†Š&§qsVäÕIÏÉVOän  IvþLò¨Ÿ*HÛôGÆ÷è¤Ä*™fÛ–" `_Œ¡>º~RõåÌŒ¾ÈªkUm Ù±X¡Ô±PPÕ± ÛÀu÷àm{w¯¼c¨Ïa„Þ±+¨€ïØûþ™LYº=t«29¤ÍÆ’›—§LUôÒ&‘6£ÔN½ªÿ¼CÅn(|Î` µÔÌ¿Íø)_¼È¨ûˆá«¿•‚:ÈœÑ}+X|×)`õÄV®Q=±ï2Ûd¸ÒPÿ6-”‰o òý¢Cikñ;°ʲKöÈé6P[‹ß¿¶ÌAu±èîU¬ŠMgîè™RØÈn'Ô ÅÑ´Œ1TdÔ276êGuæ©l`…¨{œ•ÁMÉ –ÃD…²l Yq¥;ÉXœ³¶æ[íÐuÞ1”²Mp6&24Ájñ¿ÿ"ËØŠ”…C¤=Ñ\àÚ åîè‰#¤Ø„ç'Ž–v$Þ"¥TH‰ ÏP!9)ŠY£¬K„´²#‰‰jMëa¬Õ«ð¥”xîàésŒ¤Cõ O‡ßÜ?£P½?ÐÇP=ž¢*€§8†Š:ú ÞÀ†>¨6ðYÊKµCÅn¨¢$;}ª¢åxá*qžÀÏŠC}ØO èN ÙªVö(ºHµväŸóF0_â¡lJÖüsÞäŸ9R4mL›l#O‰âé j…$2¨ «˜ÄT¦»NÖR­)qfïÓB¨NÄÇtµh2¨Õî­ÜHL ª59òÏR^L)JŒë…ªÝÜ?ö¤°è’Â9Ôžê6Px­‚1TdÏÔò6S[TPñ4SMgj©N…É?[SÝ2ô5eÕ•°&ð+¨<ÏɾՇ3%'ñ2c¨• ¯0†ZOçÉx“'“dPŸîDcZdTÖBåŸí)9^OÁ§äVu‰éœfÊÕ63 ~ÿÚd š”YøÛ¼K4’­jé®HÂo•¸kẫU• ”Tæ6rW«Š<ÍÉîÕDµJtÕ*²o5Q­]µŠ,‚žÌ?‹&јãóÏ ›Î„Šç%Õ·jóÏ£¤°0Ia² Œ§RݤºÉ6p2ÿ,Lþ™ê O矅É?“­JçŸU¶qßË66Ĩ* LE4¤`M Uoí”ÉP°6æwf©rŒ¯üP„ZÀhHÁš@ªÎGA„´Ôã‡þmºñC¦QKTÿð2'BJ ÒwoÐïJN…¤)Xf÷ÞˆQW!Ë=§úNš‚õk#{UHùµ¤:{k牨Ç=PˆÏéÝK›Ý#;åê lß¾ ŠnßbáÞ¿êîR>ý])=Ñ+yFõ©ôxt§Ìð°4 }V ÆðMŠ ’nU‰sk›Dv,>ÜX%2¨•Ûþ¥hé¯1ÔºË! Ë—Õ[§–z%[Õ§ªzP­JS°FP¼…";ìš‚5 Um •µ0O`‹d7g²ä÷;ÝÆ¨¢¢ŠÉ4ëõW½àª–5c‚ªÜ5+Òì‰gv ’a¦Ÿ®xý¤EFå¯4«zêlôªNæ]Z­*W™‘}«•NÂll«zTŸ‘Eµëîµ½ë¹Æ‹Û²™ C.™v¾)(Iw,â?£|O?µ´ßæŒ,X_tY¬aã%“ù¹‚¢:Fkqc:dõ±Px®¢N:¨Ø •çŒÊZÄK÷Î ²{'î{•Ÿ•e?<6°ÈÉûÊe˜„¸n ÛZ¤yN÷v[‹TJ2µœ°¢³TÇbé²Ec-ÈVu¹95u\…œjêxù#³‚êX,c7T^ ªc±\Žg©ë>Âf–z7t•ŒÒ€oóá¯Û‚ì[}ti@µ*=«»YÕ³ü)éŽÅʤm­¹ÿ!<ë©cÁÍ $ƒútCåeNu“?S'›Hœ%‹©(Ì ¤r"I4u¹9TÖ"‰§N 0' Ê”îG¥û"SÍ‹h‘ºØ2#¼£ëö ¾f5À‰#žª÷þ½8À‰Çã´S=Ø®ÆÁ98ËIwXï[@ x€“t8zŒÔY 0–ež_ºÏ}€c‡j™L£„Qãä|Ë«Àyâÿ© K_©ðo£·ëiƵ8YJƒ¹×ÃÑɸNì\OQO#ÁYmµo›^Üå. N2V‹ã΋‚æû| Öó®G·žÕX)Žw8tëYøO†UXÛƒ€ÔÛçÓƒÏ&ïé#.åFæìÂršƒmX~²Õê§÷š1Ì4'Áì7f°9ëT$ëé¾[†õ‡@±ˆmÑï—!qB«ºn%#ZQÒY¼Ðå²cDßèÃHÕ|[¥jÎŒêx¯ÆJ5ÿ7@k#T³± Õ<ö|Oô9Ö©©/¬Ñ©‘‚èÂꂆÕ副åIô˜ ô_<ˆÆ>\4 ‰’(rÓßbçÖÕÑ+\È›pAҹⅼ‰  É€!7ÑŠ&#†ÜD D+r… EH rôéÂ×UGöÃ—ËÆ—}¤6jã1:<ɉ&ÂÑ… TH±©Š$ÑpE8P­É9ˆ&r :“¡ƒ0 i2v Gš ¸ ¨&£n¢¢ý1º‡›³†2©Nìp&Bêi†}ëÌ`3ì»æ%‹¢^ÿÕ¡ksP#íËêÕD†íV!åBP…*Q«XúÝu_¥ílF–•‡’¶ »ÊÎõwR-¡DHެªjÉCgUÿ›Vm:òò‚È•W-²rÌÈ•X-B´Ì†@®Ìj¢w3r¥VE“ZÍi€>z ×#;tOyItêL¯ø÷w»uN;¿)C›Ö!Po²¾±¼[Q#·Äi€>G÷¨ ]K™3™ã'®Å£†ôiœ\æ Näjþ,«CVÖyoF·)¨qØ•g9}‡²<¼ òÞˆn7 Õ÷ .ƒ ÚЛ–ã]¯+C%ºªxAàÇ}Ä#õ¡i‘â%Îc‹ölÃou …àÄ“¿"“!ÃÞ8Ëá°€¶¥¾Â ã<À鉨žé¹ é[4‡¾¾lv‡âD£ófà ?×cû6<¥¤8o‘ï¼ñ )ÀŽFVûÖƒ3ëìÅy‹Fçmlß(Î[4(ó~k¡•b¨q$Aùõ½»MeT[ÿJ‚rò{oÛ4Nh™÷½³mr߂˼o}muòq³±•_Ÿ—bK³o&m+ûCÁx‹“Ê‚çc°ž÷ò+ÝzVƒõ4Áx‹C¶žõ¤¢F‡ÔåWšsð9)§Ñàä©$º§¦ßePÇÈ$l¿¬c³Ä£Ls 3ðu£óZ³£©¾Êmž1^ÐÅn V†Õ“‡=lÖjd—y‡lÖ´puê‚˼ïýk =ÐZæ-®':Þ+éöDxêL¦v³±M yÐBC q¢¶*Ò@‘Jš™2¯¡±›†ZÅlªS>}êÆB¬Ý´]¯›VãÈ‚g48ÑÇLi+•¸ËIpb÷¾±‚Óàô$Xw=µ>ýDÙ ‘Òà$cœÞS¨VáJIpzò«Úõ¯¬a(“à¬:GÔ%2S®qÄöšÒœ·õpÌtÿ©ºçûѹþìp,OÕêüá-ÏXvõÝh÷u´ïiõÁh€cÁ”nŠ”¬G©EÝUHVQ}¸‰‹,&n X㛸ákhj=¡¦gøê­ÇÈ Ö8Á¦4²˜¸q´nz"‹‰GÛá¦4²˜8ã] nâ"‹‰3Y¿úiœ`Mš¸·¬E°é‰&M\? nJ£‘‰ë…‹šC×|œPËLœ5–ü¹?­(r$þŠ4DÞd–þ›‘b,Ò™û!RäHþÉ&ùGµ&GZ»,XˆVçÉ•h šÚ9Br¥‹&Õ˜!½Õ=»¨æ*l¯Q 2¤Æà}ýk QrV„8ïï¯Çž_†a¼#­5ÒwƒT·ë5Â{,>ï§KÓc„ôÙs»Ùé­ô|¶EsÇ7÷&•|µqCÊ»AyY**¨…á¯|·¡ƒ)Q×ífâò¸SAEý"µ©†s}ü¥AR© êTÔ¨OŹ;/µðáC'D½#¹ÊðEef„äâÌli|ÇâÝwlŒE×HÍ…:TPdHÚw4í×â¼óR!$Ò§“Dâ;cßÑéƒiµ|+wçý“ jÑ)÷k(nDÚ+¨ür}Ý© L¡±²ûÝñÄrù^r±{òò¹-TPºŒðWo cµ÷Uøäum‘SÙ>3Œåïo Å{Påë¸ãTPZáY~(Þ êWû÷xÜä‰ ª§ðÜBµ«º<ùŽÊ(™a,=Þ[ÇTÝÒ„obx•±ØØBŠGQÅddPŸn(ž¨6°ë×ë‹ N«ÿº|ai³!á›ÇFHÑ47 ê‡!ÅN¤€ö±’‹‡7<„‚ÉÅDÈk&‚”DH“\„Üp¨Ö4ÉFÈ5lM.>B‘o ™S=#¡h d7÷*À;ªÕ¢ºæs ý!T[r5ÁK/ *vC±M¡”‹› B:ÉÆP.vBÒJ6†šä'ÃO ;ì+—(Ó‰ô°Or¸á(AM²¸a)y_w?ÙéÿÖA©¬}s¯»®^ŠÊ®³Ûá)Ž;*(¥jÕLj ´‚Dõ8<³ §rVQüþÕÏÒZ—ÝÔ±ø§¾Uµª“ùV'!R^lé¾Õʾªæ[5«:‘A)kQ9a•C8±´ÁªÌí‰ß²|»½“A)kQ u>uP’gùáy {+k±ùþ«­…öø{YÞÓüÁ‚ì[)}Ý/ù·¡'6Ò’º|=óŸ{Îr2k±Œô ¬}û& lîUµ¤TˆK=·ŒÊ²/Ulñý¥¾;ÖU­*OûôqÈoTÓr9„ª¶g uìÏù *Ñ'°áY5Ž‘) áuw»ÇË–“}«ÆZÈæ°owÍJýÞ>.y+¸ ;+},j…êXT‡½É%ÔÇBÊÃåðº‘Aikñõ¯ÙÀcZö&‘u=•Åϱ¸d'PY‹_U}¨&qQA±]å…Ÿ… Ëdý¬ª>g½*ñª>Ùª’…>ì:¶¨sÞŠW­jWn!#<PÑ[ÓH´k¨ÝmWòcy£zÊ%±†úÖߊžäõt+_Õ†þP@¥¯[‡L ª:êLUœ¯§¢<ŸÕ¦‚JœB[V>TPº½ï»-Æ» ™Øž²‹¸SAé¹@ß¿”YUõ#î—+Ôº›ÂÛxªà‚·µ¤"¤B6‚ÒÚýS÷cêÙÝÔý.Åa¿ÝRö?:I§™ìÜ,K­ŠñâXœ~¨ zÿ¨sU>ŠmZ© t–óõOC¥*!Ý@Šý¥(È60ÉÆt"[±ÍY5äc9x5²o_y£žNÕ-šêÔAè >ô³»~¨jR“eRÏî¬<>é6P“,šo¥JŒªpªJŒ7‰î C­ÝPù,búP3+Ãn¦²œôaߊlÍÒìEµªÕý­¾Í·JÓ:ÀUߊݎ;²U­ï^øÈ«(¦Í[¯‚§TÑí*²@i/üSŸ¿3Ù«q¥¬ÅKg‡ý©Š9ÏM̾å|{æUH¶*=Eìû¯ÚhéúX쯯WúÊÈŽ…Š-^ÝñQ 3Ýú^W„_dævõ¡ßÂ߯žë1¼ê-üóÈ»;Ù*k±ùû­ÒY&ñS§³~ÄÏþAÝ®t–óKÇý­j¨»xŠ*”!;:Ë©TfÇÓ‘i-–ëyÏ·'~ÚS‹µ~‰|kFǙׇ]¥HŠgžçŒ,bZ+k±ÑÏî:CR?ðys,ùy¿#{ ¯#ǪöÕª¶de͵Î[|ëÉñ¬{õé¶¼=R²{µÖy‹ßo¥”Ôíð  cÖ*¶ØHenŠþuÖ÷j_Y²·ðZg9ÿÖ3»›$.kÖIºB懙¹]¯P<­ ÈòëµJ¨j…ÖcçðKù¼ïïÇ2%»ÂÊZÈï¿ú-|>µ6PnÅõÁ¨ >ÿèÔc}w‡ö6©Çs~¹¤d'ðsa¾ÕF§U2A¥Ùþös![•²¿ò_s¯*’6ÏÆ *çòöL_TNäSY‹×·‚ªr ]´‚zÊÝývàd‰ŸÏewØU’޵¹[)o÷íé@u¯>õKä[«êyÀÚ|`µª;ÏȸEÊZ|KUg~ Tu.ØíYÐA­tBUgǦú¢‚³ÛåüS^ÉN ²¯zv•±hZPä}/Š*”¦2·ŸŸÓ¢¢éüøUE6Q~›ŒB…ÄgTH‘{M`œE6Y~›…PýÙTH.цÊÝWo+ªÝsÉ6ˆ¦wšjM.ᆂ…%G¢‘4ÿ”tCÑô5S!¹ÄŠ¦ã˜ É%ß šjAusÿLé*£«@µ˜ÒŠF+‚ ÊL ýgãe'Y>÷TPñ¾¤¾•’½å×-мÊï¦WèÐÑוÎ÷VTfVRA%n¨4§;½ |è.p Å®¤Ø´j4šú[ÕÞC«º ¥‚ZOËnÎ7²9ß¡ðFAá|#›óµ­)ØùF6ç;G)(œods¾c ;ólÎwLË'p¾ÑÈùÚ¤>ÁŠFÎ×&^"Ü|ds¾c-çÙœ¯E !ÜùFVçû.-´ÔÂÅ^oÄE¨öÏã|åO‰îþA½9ß¡šD w8²45ô¹ÃÚÏ«ûëíè|‡M oz}¨Û [•¦)7q‡î•£¸Ã¥äÇ2¥‚Z ?¥¡ q$»ÁÚùZCŠíµn6(È6P?²7½þcn(¥¨›M©¼¯î“üýk骮 ŠÇóBµè—Ñ;_¥e2ÂÊèѸ©¡>ì¿]i6å¼=ì—”S}+ÓÔ0µyAµthù‹ ‰¥Å´Ä’ ) ýx1[b©~i×zþRì˜P ‚$–ÓKã7}ÄÒbZbÉò¦‘XZ¸$–F/Òç>¤Ä"±4)G0[f„´î ‰†ËÔ/²ñé:å?gU¾¥eTxR(;SE}o¸?´Ý„ÍÞeü’T"–¶qPVe´2dë⨑ðí]°wC$׿mYÈæ ‘L#ÿï¿¶‘?åÝØ‚ûë|!BZj¤VÚ«U‚iì®Ø)n#¤äϨšŽÓV]J´ÞÑI ~˜8¬n61ýáw™g·ã‰ê;­ôš¾ÛFjÞ[Óùq’?DHšãúûmÖ”¶¼É»ßå›Þ‘åc·#»¹.#‘7F‚…,MÔç5yc$¨\F¢ÌBŒÄ)ç;Ã2V¥úP‰5³!åAª,C¤h¤^×$7Ë®{"¤xTåh¹2/å™S!-M•£Õ=m×T7­Ïû)qIÚ°z:5C•ë—ã{CÿNÄ`¬\³{š Ñìžž©A°{ÃÁrõÙkii7í"üì FËõé-ÍÙÓk"8{ÃárÖÁ’åà ¯ïf?ÖiÄ RJ„9¿+ñß)²Ÿû„,0í½CŠý÷©²åC$·…%Ù½¾…ÝÔ,BÝ"£˜}<ݦì* ™_ç¿k–õ/ºÙÞÿ-Fc„¦R¹ç4@½Yï¦ PÓ%„<•"#ZQÜIe·@ZÅ«–;Í3AdÄþW#W§+¼–«ÛßÏœÈhýi’ÒÅ«k5 Ð}w*ˆ¾‘þÿê­«…NÍÖÕB§ä&9V. ‚mÐZ黎¸9ÞœµÇ;õðz ÕÓöõmzÚÎ*Óí¯E‘zoÜöO/K¾ïåãS&¶E#ñL´wFåïõÏ é2ƒTÙU:¤žæ¼AjJ…TׂR"¤Ø”BÊvn¤åØYt³vŽ:DGo1=š¢FÚï9£Z“øÛ(ÁyÍ[Ð&o¿?s)ÏT'b5Fâç)OïT'b­‘þn Ò¹·¦‹|–T»÷©‘¾7Ýšz»÷Ê©N„÷Û¨à«Gein°ñ¤n¤…F’}r,o‘öÛ‚jM gFn4 W ­¨5eòñ`ù‘ )ÖHŠ´×éÂŽT'BÕÀ7:%_»'%§Ñx󫨈\“êt¨âÉ?oaÞС9 ~rþþÛt æ5†œ­(6@ß=ª7@©`T[g¾Ñ?Ó­~î<ûùõS¹vA¤ÌøF»Û]K4*®"»óBÞK¢oô¡c•mEêØ±”h¥W¤œíΰaõŠ$»s" õhëqJåù=#: Ÿîeglø0º°z¤•É ¬©‘Š:îO‰ŽÝb1FjÏ]QÏ5TkêM‘QHšÌÙ erû̉Nø¢OÑH¼]SmÅ *¤6ÌÛtߩ۽ûVPÝÚ~˜§‘νïTy[2$æ5Ò¶£0¯Ræ•Ç‚—T§\‡y² ¾N½5qØI7’óFýB 6FÒíku˜§ÿÕ‚Ü®i_þ<°Î’óú„eÞ†yezÌ8Õš45ºa±7„oí›Y’Ïò'£r·*Ìûjž·o3L2ã?’ É„¶$Û9-ê#‚ôç} Ø; £€ q4@Ñhôés©&3) PÜ¥ ­;5PžæÐ(ÌëeŠªUÑÖ%ƒLÑ[ôu 3®F³ÀþZýŵ%§Z\`¨¼’­{͹¨¾šäMNt>Ý@"Ms¢ ûgÄm¡ø¡Y¢Ò¢  õÜ!d‰FH‘v[§~î9‹g)RìF*Ê‚èÒ.–&£²±dTxÍì¦BJÆ•>ÒöžS!é0ïë¯-|¸”·’ʶ¶aÞ?[Ž­¼8•q]¬ß3]³bÊDY4CÖÑH‘…šÜÇ1¹ñ²é¿,8 NÔÙVË­-¯iF³ž^›˜çZRáô²âí÷éö­z§ãÏÜN2¬’tµ‹ §føÓàhy·¯&óÐÈÒ+ü]ÆäN°GŽ·ßo8+m¾ß:›TU³de èÂYëõ4Ú÷§VªÉ¬GJI³oï¶]«¾Ï¶ÞDNô?•býó~O'pŠ"-HpÔ=•¿mJå=›ˆáZE[œ œØà|w8)ïpJž“à,ëI¯‰ƒ.œÄ½žg–Óà|ttu4I¤9e­Ö%IpVo).ÝWÉ[œ:Nà¬ß‚û¡}«55hp>ßbû!ÎöRá˜FïQ0Ò¼ÆYñÌh.ió~KetÏþÓN–4'n\ùgJ÷ÛœÈ$èdçïwëT ‰*…T®½ˆ€–zE›Ö94ÆT¯h›çDÆG§:7ß›–Y>e©Úh3tõwai mFƒ¶@©˪¼K PdÈBß6²Ðå.’(“…xtç_&]XúB¨cÓ)`8ŸÓ'µèMªÞÓQÖ±Ï:ïÓ'£YÉ:~}Û²ŽgyD×ù‡@‘¶¥­Îî‰g ôÔÉÍ óS#\Óݳ,ßwbKÔ›"Wgϧf€MµaLäÕ‹5 NؾõÑÔ@ßP/j 2§¹EJRòÛ lvÖþNÔóP²Ÿb›¾ˆ€ôŒ—)¬W¤é•YyÛë¡ÈˆNÝúm¾Æ¹Îtë%¥Ìؽ¤út康,câEãYõœÉ¯o3ü±™d¤‚¬²¨Þ’Ç ™2©Ó›LGYºrÉJF¤ç@ýU‡¡ZÉœe[uŠsJsê´ˆä÷ßß6œã=” ñ"Š~–ÝôôzÔ WÊYçzÔÊvw)ïgAc½£d°uzÜcåçÕ}=Å Q;Ñ廞Wxbúݳü^EÁ—­ €¢UWø0RjçÔ•‡>ôK‰eÓ!PyH-g„dj,›­ôñ¼Û‚ÉYd¿#›·H©Äž‡’®²{§äátñCneH„”¸XuwÉúâëãòGS}§Õ[E§›±¢êÀ˜ ÉTZ~­•–: DuÊ?G oH×’ ÉRké·\^è¢åÊ[~­Å–kñ#Èì‘»Úr;f3”¶ß:í­Cde'ØíðÇ”V£øÒ4JPA›¤Çá™]8ÕQo‘lE¤mÝI“‘ e*6mošN©©~»£ÜŸJ’(ݬØr¾OŠ•¯¡î—ë…ìªg´lfw:zƒÒyg·]ßC™é©Í+­v¾Š„¢ ç—#šV3ö¾fÖò?¥Ž…‚ºž‚ìXD‹Á`ñ³Dl¦}WM”tPQª™µ¬ZjÔ¬åì¸'\U7WƶáàVPýtçéöy»\o¯=ٱБófóW 6Põ˜Ì“¨»öé tìüOAµ4¨z…Hy‘ÑA}tïZ½þÔŒÅÖ“no,ßnïd¡¦š‡øú§„eNœ1Ó.ty”C­ßFÛ׌ÜfTpuØÓWQ^ÄåN¶ŸzXõ_}¯´Ãj¦çþØ‘}«ØLOý§Æ:™)¦_Ïüçž³Ù½ŠAÀ2”)€ ÐÍ´ZL šzÊr­Þ‘"ϰI†{†ý„xûw¤å¸q¶G€ #º‘ K`8gO!=’›&Àåã@„´ò ú¡ûN­Ú‚ál+YI-‚PÊÇωi,·òNסd÷ëŽêæþѳwŒŠ½) ©Ù;Œ"¨…gΚ„¥'5Œš”¦Fw©—xLXj*ßšìÅÔ)¯©#l˲ôE{wœÌ^<îSúÝl¾G*â¢V«¢t ÑГ¾!úFQ4{·È„Õ†<äØ ‘tYzÓ‡}›¤×wiËÊâH„ôv†F¯¶ãزÚÉ4Äüµ¼D¯…`,¹c„dZb6½‡h[/®Ïòò"BúèùpÊEvȇH«·”ß;µš³×Þ" ´t;wzÁB\ûÉyÊ·Œâ”÷µtë¸üŸ.L6uI]˜év‹­E–CûÚOíÐܧè‚Ѧ[zAÄõx¨â•ÒLjìÑ%v®ÇGvÁjéŽV®û´-)îSô>÷ÄôDô¨fw™_®Ù6#B2$°¯v>Mj¨%w¹-¯é)§º¹¦³õe‘…eëã) öq7`V°‰‰Èèÿ§íÌ–×u¶}C+õ·EËv¾³>«Ò—àx¢)›±(;Tåê Ô`‰ƒa]ÕO‘¦@^䜧? ‰y>ݼ>Ãÿ· ‡o4ë˜/¬F¢×úSåIMëOú؉³""5sO¶Ÿ/VL7Óå:'N³ »âv~“(íÍPÒÞ%(íÍfH{ƒ\X†—öæ’hëÒÞ'íÍÀÒÞ'íÍðÒÞ)¨ÿ™a¥½Ó—D[ç‘öÎoªø@® CI{ç‡[&`ÒÞ,,í=§ÎåN€Å©Ùio (¸Í&H{J9+TDœ…¥½ÇÂè% ,ŒÎæH{çT¿SPÚ›Œ´² nsœà6ƒI{7Æ!"ÎàÒÞ'íÍàÒÞ'íÍàÒÞ'íÍàÒÞ'íÍ&H{·9Np›Möˆˆsœˆ8ÃI{ç—TÜf(iïÔg3¤½±¿TÚ;D ´w±u_&FÅÀÒÞ)NÚ›¤½ÇúÔ)Nq›¤½íâùåñ#.œäöNqÒÞ ,í⤽LÚ»= pÁm“ö.?Ù'"ÎàÒÞ)NÚ›Á¥½Sœ´7› í=ÜNq‚Ûl‚´÷@D<ʼnˆ3˜´wçæ·LÚ»s¾À"â .íÍqÒÞ .íÍqÒÞ .íÍqÒÞ,(ííÜæTkŠì"â'"ÎæH{SÝN>iï¼¼?`ÒÞ %í]‚€ÒÞ -í͵$ZQPÚ›<ÒÞyéYf)ÑÖy¤½ó˱°xóLÞXÚ{ Oâ„°YXÚÛ a³°´·S{^p1–övÊ`SZ7ï¯Õ}€ê¯³ ÒÞŸVT€Á¥½9NÚ›Á¥½9NÚ›Á¥½9NÚ›Á¥½9NÚ›Á¥½9NÚ›Á¥½9NÚ›a¤½Ë/ ,íÍàÒÞ5(íÍðÒÞx§&íMÄqJ{Wû•öfpiöf~io›ttÅJT3¸DuÍJT3¨DuŠ“¨fP‰ê'QÍ Õ)N¢šA%ªSœD5 JT¤£Ës–ŽfA‰ê‘vÍJa3¸Duu®¡Õ .Q]?׌ˆ–¨&ú€ÂÕœÆ"˜¬Gg9ETÀt–Ó„äÐYæ8eÖYæ8e†×Yæø?ˆÎ2ߥ È¡³œât–Bg¹¬ë,³°Î²5„˳°Î²5‚ :3¸Î2Çé,3¸Î2Çé,3¸Î2Çé,³9:Ë9Õšü:Ë9Pg™áu–S“:Ë)(¨³L ê,ãC°I:˧³ÌÀ:˧³ÌÀ:˧³Ìfè,ãÃJ Î2Õapè,§8ýcÕYNqzÎ ¯³>?>¶ÆëhE(UØØÛUžžÓ¿ÜøuÜùÛ¨Z¼5>˜Lf@òëhÏó‚ê|ßßßòWúê:…Ó´ì8&B^ˆVÄÆ Ê@P–‰V´4 í¶]z û9Ĺ^Pl@ŸÛnë:Ðwyp÷‚j7¹.åþêò$a¥Ü^ÐÚ€ô¿T™!Õ¦{A›:¡m¶®Khó„ëÛîp;?‰û •`¸àžñ2ÍGôÁšWÐÊïÛP¾øuºñbè¶z8Jß4 ÇÝžîs“”Å’„cì‚þøg9ÜI²»`¡ǘ…Ö,˜çðúk½©{J³ž¸«êo­Bû ݲ®h8«nèg5˜µØµv0ëér”»œ†³îÏü<Ÿ.'a”–¹TúpKv9ÍïÓw^!7ãΫ1ä×CÎ!€>λù}þ¶ßÏ¥÷ûHuÙÎàwrŠÏ4!á4ßé¯õû»«$6²/œD'ÌÇYv¢ãë»ð|§YOü"ˆ1°÷›¼¥š„³òœëó8×€—³n\Ó­Í5}–ʩ؛n1Jã\Óª¼Ã¸¦™Ä^ CP4öFún¿i¢5G{»µ‚nœ ´{#UÉ€ñFöß ÑÖÅõÒÖQƒîÅ"Ъñ?{V®½UeÂoOÐúµX çȧ.¹?ö)Úœ¾Yü«r8o 2¿Q: ¥h@­ƒeõêaýQ^óÝ” åèÔõíËS\‰¶.î¾£&|¨£*|8&*!Z‘ÿxÿHþ¼Ñ€Ìñ.U¼k£ZK W§N^î—ý釴€ªhßïûåþäZÓ€ÞÇ~}%güúgŽýÞ,B¯ßQ?P)Ó?D häÙ÷Ã-ùÉŸë\†ºEóܩԟušCj°¼ ¥Ï%åÓ„˜z}0Ø Þi÷TP‘ü¿’LòÓˆäû™ÔyþÏ4x0°küó"” ˆÿ‹PÃJh˜€&BÃRIr ({3Áü Ç0‚ ð‚Vné}~Sű%R£À0»ô>?Ü2‚B±(0LÀÖzÁåNUê½ w—H} ŠÔû?Ø?‰9(}‡ ¸F>ðWTkŠ\c ªŸ 6 ÁOb~h@‚Ÿ&À‰Îxx˜É1L VØð“Ãh˜€Ÿä&`H°a~’c˜@³&Ð0ÿ]ë&P“€Ãü$Ç0†t€% #ø0‚&à'9† l˜€Ÿä&À/?¤ñÿB (A ©^PÐøçBÓ€Xhj'y† [÷¥³TÒ€b·ô>¿<ŠÓÀÐÊ®γ›ëŸ{Ak»ü¹ÁäϽ }C‚Îað‚à 6‡ÁÿÁþ±ÏG0$Ø|?iá_h@‚ŸÙǘó[à'1û(††Åà'-íjp@‚ŸÛ$4$Ѐ?É1L ¾ÔÃü$Ç0†&à'9† qhØ0?É1LÀ`Ãüw­c˜@Mð“v‰ó;Á$þý¤($ñŸ}¹Í0÷€2ÒÒ­ñÏ/‰iü[HÞam6¯¦xAa©žg_ÃR"g˜@¹‡:K‰~#Ï0~9jÍ發ñ0¿V7¦Sï­í2õ“©÷‚6ö© 4Á z÷ƒ@ãüìŸÐ|Ne¡ d$Ç0sYÀ$þý$æ'ÆøIŽafë`Ãü$Ç0†&à'9† Ô$à0?É1L ù΂ʸ¶Ã¶ã„®"ò’u˜ÀH¿âÀDñ}œÈ5¡âÀ†#ø8Ì5¡æ€†#ø8ËÐp„”†‡†#qV.1ôjß`bè/Ç0O+&†îãD®¡54ÁÇa~h8‚ã&PÝäÐá>Žc˜@Ë GðqVÞõ$øïÇ:LÀ¹ÐpgãŽPžƒÚ€…† Œ‡#Ô`GM4c˜Ñ&Óœìð0Ž~Šƒ à (²kü7 /ˆÙ§lj´ôjü§;XµU&àœZ+-ÀÃê,‡Ö°FˆaeEp˜€´ñ…Àa^л/‚ð°Žaæ¥6LÀOr hÞdAÃü$‡^óJ&à'‡ p¢“&À¥T¤À0\htŠ8L '‡ P‚Ãð!ˤaM†4LÀ r h@W®ˆ@Y¡6k%Œf àD+ À?ÿZ‡ Åê«{*Vo ”Gâîÿ,Ib¨X½Ù‡l8‚Ãü`ÃœÃæ%2–„‰}8gå®ÈÍ5P ݶ tmç(†îãDö¡æÀ†ø8Ì>„¡á€†0ø8Kûp„:ðGðqà 6ÁÇYÙ‡#l8‚³ö®6ÁÇÙ„†#pšïç=4ˆ&@ à4¿Px˜vEàaèŒÉÔa&“&à'9† 4$Ð0?ié—øÏÑ)Ø0®Rtzfú0*›Óàò“œÃ*LWÌOr 0ù Ø0?É1L !† ¾Ü?v…“Ѐ)üP ûÜ‚š[@ù“'°a”c˜@e' Ã(Ç0 &@‡ ¤T–Â5L ®û Ã 6L € ÈÉ>á÷ì>Ùo&@‡Z„d÷éPQhCJõ]ÕÃ| ÿdÇ¢®ötiáóR ŸÌ)  [Õ*4øµÍ-È©¬…&à‘ݧ;ï¾¹y9·€jÍ0Ïܲߊ$þñù~ç0çØ‚œŠ&@F ˜akíÃ>¬U…0]h?)¶-0$˜.´ŸäÏúÆ øIÁad¿“c˜€iÆ‚ ð“Ãh˜@àËõàâ4#Má&`×øŸ‘{q °O-àš&0ù† Ø%þÑ[ç&`[€Þ;ð02³Kü7s ‰?ii[`H°±~’c˜@ýæÀç\‡ ÒœKÃ>L`$ñoòô0‰?‰…ÆÌ?{þafM°a~RìNúå:—ô›8L "ÍKd‡ ¤T$æÛÊoRU½JÕ«U½Ø U/ÐÁðª^\ª^<×U/Võ2 ¨ªC©zå7U;PÃ!C©zå‡â„©z± ª×Xl+/¶,¶Å‚ª^¶Éí; –c3T½Ò„è4T½ÒTkrªzU»UõbU¯šTõbsT½r*Tõ"#9T½JK„PõbpU¯†TõbpU/C‚ªz1¸ªW³& ªƒ«zÕ$°ªƒ«z5$ ªƒ«z$Œªƒ«zTÕ‹áT½ò˪z1”ªW ªz± ª^.±-¬-rªz9äÃrAò¨z[÷%aý» ¥ê•_Åià heÛJ³›@ˆm±°ª×@>Ì€ òa ¬êUàª^ ¬êe@PU/Wõ2$¨ªƒ«z5kªz1˜ªWï<@µ¶LÕ«]gH@ý0WõªI`U/WõjH@U/Tõòèq*Ò:¤áDFÚØõÃjG¬ÆÂª^CM´†”‘]­›7P*«I`¥2Võ*•T©ŒU½FJe5 ¬TÆ‚ª^#¥2ó;A•ÊLÕ«M²] £Ûb U¯F>¬åÃZÕ‹k©h@AU/Nò¨zåÅ%³”hë<ª^ùå¨%Ÿgˆ‚ª^愪z1°ª—AU½XÕ«U½XÕ«U½ØU/§ÖּˢêåÔ##9T½Œa…jm1¸ªWCꇱ ª^ƒNysBµ¶ØU¯AóCê‡1¸ªWM«z1¸ªWó;U½ØU¯‘ÚVaî$Xm‹U½¶ã|Áª‡1¸ªWŪz1¸ªWͪz1¼ªWžp‚ª^Dœ•Km«Ú7¨Ú ªzýµr êa ®êU¯¨êÅàª^5¨êÅ ª^ÕMWõbPU¯–“cßʦ©zTÕ‹AU½šõU½\Õ+¯gèÛnªªWͪz±ª^œæ „U½8ÑŠ‚ª^)úá¦ê5ãeÛÞ¢:Û2P±-Võȇ5•@ù0TõrŠmqI´¢Ø+Æwh»0QÕ«ÁÀª^ ¡êUV€U½XÕ«y*ªz1°ªWªz1¸ª—y)…ªz1¸ªWó& TõbpU¯æ•¨êÅæ¨zåDG< êU|J‚ŠPõJ…Fg·€ª^)( ‰má# §ª—]>,4 ¥¯:¬êÅÀª^ ¨êÅÀª^mÆ ¦êÅf¨zQýFAU/ªSçPõªîY¸ªƒªzÕ°ªƒªzTÕ‹AU½Ž@°PU¯y‰Œéª^Dœ•»P¶0§PU/Uõª°ªƒªz™sUõbPU¯†TõbPU¯:ð«z1¨ª—á@U½XPÕËΪm± ª×§¥^®Æðª^);U½ˆ8mÂÄ)¶E´q­ª—S>ŒjEAU/,¬ê…ΘLUõ2™ ¨ªƒ«z5$ ªêzq•¢û`ª^;]®ˆäTõª²Ðf8†QõªHÐ?Wõ2ù ¨ªƒ«z5$ ªC¨z™„TÕ‹!T½PÕ‹!T½LòªêŪ^•€«z1„ªW…‚«z±Yª^9Ù t¨zÕu¿`U/†Põ2(¨ª›¥ê•’ýVï!©-Nu4ª^n1²cñ¢êe•Ú¢CE!1:TPÕ‹Ì'3ª^©-:T’Ú¢C­BR[œê¾ªU½\²hi)‹F¶ªOj+-¥¶¨¬…QõòHm‘ýVFÕË£UFö]…T½ðù~¸ªWJE ªzÍø¥€ª^3~(»ª×@kˤ⡲)l‚ª×‡µR*Ãàª^&ëUõbsT½È~'‡ª—iÆ‚ªz1¸ªWCªz1¼ªW*N ÕVõšñíÂT½rI ªzͰ{0U/ôÖU½Ð{Võ"#9T½š‚9 ªƒ«zTÕ‹ÁU½ê7>Ç”OTõ2¤9×SÐpÚÑœˆU¯‘~˜y€ê‡1¸ª—!AU½FÕ«üfÓyI¿‰ª^i^"¨ê5ãrŸˆ¿¿ŸÖA,¢j©Ž7u„XØ¥EX¢W-^‚ì|6“1*Ð-ûu«x@u¾ïïïÇk¯k ºåÇDÈ ˆAÍÖ• ,;&4 ¥m‡è+Ðýœ‚Úó< Ø€j0ôÀ "< ÓÍ=âW‚$´ôÙ2ÍÜC-˜¬åö€6uBûw(ËËâ~¿§_7¢Ãðn@êÔf? ¶gßk^A‡íéõÞÝ~„: MCÓ!µè['Gé›&áÃ0lM¯9IYÜ(I8Æ.ŒÕª+N²»$ ǘ…a[ºùZoêžÒ¬'¶Tõ·ßPa¸¹¢á£0ìœ4©2›ÃÜDNNqÜÎø¼õÏAY™G³žæ¼ýZÏ›Ø]… á,Âfß¾§áÄŽv•Šs¿É[ªI8«ÆõÙÚ\Ÿt@_«‹QšpàúˆTìþZŒ²„Õµºµ^«7’Ôò€ØøZíƒø ´l®Õ­íZ}¤{žÐ€âñµ*:Pº?'D Uãc uÿ+«-~{Ò€ÖæÔm?m§®psôgôf¹¿?µÕ³/ÜF¼{³^àVC'¡ý7Ps¼??ÿÇ æxo·¶Sw{¨» 5Ç[[½Æ›<)EòïÉŸ79ÞWRGyõ©Ó—ãOAu©ÏïÏ?sêjލ@ç ¢ßè}têúþiõ#OÝ›E(`à 6+*Ôgž¢‘çØ; ·ä'h@Þ6)3Òbè5O<°A½½wôi‘ü›'“üð$"Õâ¢Uïéþ«o…’²:ïzP»éÆaUþÃðJê;Þ§Ì>~5FH´œ2cL‰-€\ðº޾®39ý³`e­9·/H+­Ó¬gûiãðëþ\Ï›-/~ ­õ ì.÷l/¨YÑËu$Ú}k€HŽÔmýϺ" Ññ‚ê›üg[•‡R—¼9s¼Ø;¥ŠÛA…YÈ ˆè0¬FVÁ|EÕÖr7oE#³ða5 %šÔ³ Ãà¯ÏÝQ?%ìܸ1ØØ…“º8`çªi6»}û>èyœ…Ón÷9ß_ »ìœÏü ×c·s>ƒªh@QÐü$4 2¨šhëÂvŽhEa;Gô­FV¡µs…U(g¦ÈY ›Yèì\i*P93…dc¶7\8޼Z‘..ðÛUžžÓú?Èþ¦÷±m ~á¢ɯ“Lh@½7½bëÚ7½4E¼éyAl ªýSÄ›žÔ{Ó3 K{Óó‚zozíÖu Ø›žÔ{Ó«A¦2#E¼éyA½7½T•¤ˆ7=/hÓ%_­·âú¶;ÜÎO¢ÃðîJ>j^ì/‹Ü‰>ØÞ›Þø|ßô^Hî7=ô¦çãôÞXÌYèq€oz>NïMo|¸oz>NïM¯æ˜Vçñ¦çãôÞôZ«Ð~CÀ7=§÷¦×˜¹ö¦gáØÞôlЛž3>oýs{Óóqzoz6èMÏÇY¾ÈêÎð­Ílj»·Ãñu|;ôqVë³µ¹>O Ie ,©íMïÅõ©îÚõÉ$ÖðxÞôl×*èMÏ bãkµ½éyAÎ7½ê¶»ˆ¶.v•ÊÔ×êþ;!õ=:ëÓZmØ›ž´~m0í9 Å©Kî}Š6s¶7½×7½jë*ÐY(EŠºÌ½åÔÁžÚ¼ ¯E¥wß™»<Å•hëzÇû5ž¬ÜÓc¢¢ù7ìMÏ 2Ç»œüjÞô.U«vyêäå~ÙŸ~h@›ȼéU ûåþäZÓ€ÞGÇ»ïŸÂÞôÖ–áñ¶7½.(*‚»ñ¦çE#ϱw€oz^åƒí­öÒfßô¬6øzè'ù7ö¦ç'1{¨T–Aä€8d@Ѓç€x‚É1xÈ€€9 ÏÕ hˆÁs@5šbáÐ05SÀ©Î “ML61x(•˜ç€ò2ƒÏ1D¨Ú;pˆs@†Ì1p¨â€s@ œª9Ðç€ê¯šbàPýû@s@ œª9Ðç€ ˜bàP} 9 Î0ĦÔu¯!pn†M©ëŸkp®‰As@Æ#æ€8Ô¸>Àƒç€ÌmÌ1xÈ€€9 ΙۚbàPs­s@ žª­64ÄÀ9 úÔs@ œj@À›T×m9uÐÔ ›T×ý¿9r@æÔAs@ žªÝShˆÁs@õñ†æ€ØôPSn]ž:xj†MÏ™dS‚'›<TßãЃ瀌ƒ Ì1x¨ö 9 6©®Ûæ33lZ]·eï Ù&†Èw ˜bÁШ·Ÿczû׈Þ~Žéí_#zûyŽª‚÷öóUïíç9ªÞÛÏsTÐrR¨ßrÏsTyÎrRèUÕ UpïíÏ1½ýkDoŽéí_czûyŽª÷öóUîíç9ªÜÛÏsT¸·Ÿç¨: po?ÏQu@àÞ~ž£êsÀ½ýÜÛÏsT½¸·Ÿczû׈Þ~Žéí_#zûyŽª‚÷öóU´Ää€à½ýkDoŽéí_#zûyŽª‚÷ösLoÿÑÛÏ1½ýë)½ýŸVgššYNªúß‚–ö–ûÓr¿žÒÛ¿ÝÚŽ7LD`èíç9ªÞÛÏ1½ýkDo?Çôö¯½ýcR3q84n:Ã$›b„¾£Ää€b„¾£Ää€b„¾£Ää€bpÈœ:hj&ç€èAN}GIÍÄ}GI6Å}G‰ÉÅ}G‰ÉÅ}G‰ÉÅáÐHvQbR3q84’”˜dSŒÐw”˜PŒÐw”˜PŒÑw”˜PŒÑw”˜P<¡lÔ¢%á-Z›)½`£¦3 o:Û zÁ<´Aõ‚)xhƒêSðÐÕ ¦à9 Í”^°Q‹–‚ç€6SzÁFMg žÚ zÁ¼lƒê“ð^° ®LÁs@L/˜‚ç€6zÁF=Z ž›ÙLèõœ)x®iƒéSðÐÓ ¦à9  ¦LÁs@L/˜‚ç€6˜^0Ïm0½` žÚ„{ÁÆ=Z žÚ„{ÁÆ=g žÚLèµhIx‹ÖfJ/بéL›Î6¨^0OÍlP½` žlÚ zÁ$¼lƒê“ð^° ªLÁs@T/˜„÷‚mP½`Þ ¶™Ò öiõa©™Í”^0«E¥9{Á$¼lƒêð^° ªLÁs@H/XÛ¢%á-ZH/XÛt&áMgT/˜‚§f6¨^0O6mP½` žÚLéûµ®–™ÙLê³Ú `¶iƒëSðÐfR/بEKÃËs6Sê€FMg^p´AÔ• D(Fô‚iLhBШEKcR3ê€FMg“l‚×Õ p^Ô€€9  u@c^ž³™R4j:“ð‚£ ¦¨Þ;p(†÷‚iL(†÷‚iLn&†÷‚iL®)†÷‚iL(†÷‚iL(†÷‚iLn&†÷‚iL®)†÷‚iL(†÷‚iL\TsÀ9 pPóûs@á: Q‹–†—çl¦ÔšÎ4¼àh3¥h»µ^«ÀPŒèÓ˜PŒÉÁËs6Sê€ÆO+ð‚£ ¢ÈXmh(Fô‚ixÐQÔ€@u@D9uÐÔLŒè£-]-Z^´AÔ5 PÐQdŽ74®·hixyÎfBиéLà Ž6Sê€F½`“н`“н`“н`“™‰1½`“mŠ1½`“Š1s^|Îë»mLAhΫ‚Ïyõqœs^5|Ϋ•šóªás^}çüC¿ú>PŸ6ÿPÃÊzAÎù‡ >~Õ rÎ?Ôð²^sþ¡†Ïyõ‚œó%|Ϋäœóªàs^m ðœWŸóêEÎ‰Ž¹¸¤ÇËhë–Sæ¼×–œ‹øRš„Ó®gØ{(Ò‚s¿œîr'8Ϻä\’“Ö$÷<ë’“Þ÷OäzÏ:Eعx’³›CͳNv.žc父.lçˆÃjä-ôÔÎÅ“ìœå7‚Ú¹âÏusx¯ÏÝQƒ¾£5ÌΙyEœwR he°s…ǽµÆá·ïƒžÇY8ãð>çû ‡¯áþ\N*Çnç|²¦…ãÖ„Œ[5ÑŠÂq+ÑŠÂq+ÑaX¹¢¼Ê*î'¬UpÙ9ÛœÅëó¾?gD È‘ŸK%oñߞϓˆ|žäÌç D>Ï åó"Ÿç…ã@ìŠ&Û<‰ÈçyIQ0âLˆH,¯kªÝ ǶT»Žm©vϙψ|žÎç D>ÏKrÖ+DlM+ÄTP#bÛhJ%žeÚ 8¶¦•â²Á~^4­ÏúyÑÄb¼Aí"¶&Vã ŠG±m4±Ïrð€~^4±oP§‚ˆm£‰y¯• ÛF+ò,'èçEKò,¿ÐÏ‹¦Ôä}XÏØ…c[Ûà„q…Ƕ©@Ķ"¶5Vjóà±mg‰$4½¡,ÅØïc[ îö‡ãéXK‰d—ÈD–¦X÷#éÍÞçô±ý-ç%• ã™Q’ËÏ1K').NE hÛÌŠ Pñ‹q¢•ÓÇßÏjEÇvE2yæRí´æZЀ– hÛŠRšj•Âæùçxn»Ë“” kE2£*LÕW 2úÖ¨ÌW­h]m]*?¤ã¡<ÞåŠY*Ò¬d%D§nSªê²ò7â¥2‡á)DºK5è½}”Ó…ŠãÍÏ^~EW™ìòd§Ê¯–èƒýS}HÕù.@‡æ|ß“\ ùاŽèGZ,Ò¶#¤Ò)ÕšŒ¹ûømÍ]±$c…±Ë„Èp¤Ú¬¾½Xð ýnÿ+té@7©ù dÌÝï¿ÆÜÕ ¦ HMS0ªÌÝö£YQyðÌŠd~ùQG! ¨6wfE•¹»ˆÆÜɼøoNŠÐgj ¸Ì NB*Í]ñUšûSyê*uÞLí„x|ë£Nh@ÆÜ•ŠŸåŠšã]®ˆK½SZ­¨2wÛŸ¿•¾õñtáÅY(ÖôÈv·4Kò'èÝ€*áÜTY!’ò¦9ÑÖÕæîï‡îÖrï®RîrUn&ú¯»NÇF¬9•wyÏ¿Tª¨HÆÜýZÌL eæšþ¼ÈVHÿµ˜»K’¥G*1wÚfîJä…g4 Ö9]¥çЀJÏ!+\;vº† Æ»ûý×€ª­3 Å•&ZQÜùBÆ8T¾Pi {7ÂV‹R®¨qQŠo6K“Æ»(CкöªI‹‡nëj¿á®ù>Kh@ú·mAåÄ3RJ¦DÇûÝ|°¶p¬8 J£íêH.µ< ¿ã‹¢ºd“$!áDæ(|6GA4æ»8 yq¤$á0ã×Yö­Œ+ ·ùµFãÀ¼t‚>'H4æ§p‚%ÄQ“pª}ûÜþèІ|…ÿóLžJç ‡uCÕ¿O* ïdÆy‹Æ:ûærmÎAmMw"­¬©¢Ù·x4¡)CÏžÏô\ì §6qU’aßK2QX.EáÔ ¬AhÏ£þ‡Z¥Mö½´‰eYš¢&öÿ´Åþ×»|Ø8öè.¦µ5N-Gg»¹XË]›á AõÅú±5±ÿ‰w‰ ânà;žIЪç“;Ÿ$/üí[°†›hE&ލ>£‚Óz¨\>Žy¤Õi“߯énnðúx—¿“@ßo– ¯òPyƒPùÁ¢îfÝ÷n¢T„”»âGJh@ÆA­FŠ»¤I} N’ в[QsÊߨ> ór&¯ Øä¢·]´"’&Z™ï”,,ÎÏÀ0”IA:NÏùÙgÁ…]^xŽsŸÅÀùéí[Ïù)=,'úϒ¯Ö3r~n²°§AÂ1ÎO¨ŒQ¨Ÿ½N¯‚†cœŸzߎíy«³%ÅQȰ7Ñ€³:Ám¤=ãÅÉ›³¢¨½ ƒÎj"p}*kdÎÃŒ sD2wTµ¦ú<Ô¥ûõy(þßA‘šìñ¯m÷×è [GŠ,»7HHíhv/zÙ½Ÿ­m÷™ÒG*Òx÷Z÷<­ž•žuÈ}»×ûœæ$F¤p9!äÃBå„nˆhB9¡«n´wQ œÐS·˜p¢…Ê 'úâPdFZkK‰@ë`m©¢m‚%Ÿšô,b%U¡«¸T‹K£@9¡«ºT«K£@9¡uM S0ë#1ך¦bÖGZKf©ÖûI Vâ#­BÕ¹‚Š´ÖSýN›`!0Õï,9VD»Kީ܇(Tr £}¤(XFMda#,£¦Ú½e°Œ¹&{µ*Ž‹ÂeÔÎzm*P¸ŒZÒ€–ÞÂp, eÔ¾a ‘µŒÚS®r"Ð:T®ˆ@›Pax–ЀރíTìŸ`­» "-‚DŸlõ÷v$ýLuÒßÛ’@EZ†Z$ÑoÜ ìS‰f´dD ØÛ“b¢@ûˆ·—ˆhEë`/ÑaØ{‰ˆ@ïÁ^""PSÞái&RD¤…Ÿ„ÏHQ¨oIQ‘X°CŠj÷–¡)‘bT"Sª³· ¶}QíÞ:Ø÷Eun‚_èßi\ïá$Z‘p¢`ƒ™ á°GÐìÛ2ÐÈ&¤$áÄÁ†9š}[æ$ö=ÁÚ0çkÌ“$œÈߘ§ay‘¿aÎÛH³oK{ À5FÞ†9G£¡ ä¬‚†4œu€ƒ¶oÎÆßИÁŠ7Üœ÷`ãdFóþñwN&°ÎIhlÑ$²ßŸÁP«¾ÒQ@ê!¼ È«¯¤A½ ÀP™ é-;)¢ò•¨©;Ìs—"ò‚z•”T)L‰È òŠöd|—&D[ÐìIsM´u¯@Ë^éœôîלQ½#ÿûg$,‘\:a‰T°$Ë4nŸØÃÓp"¯Ca].¿Ãü’ˆ†³ô7õ?5Ö¢Z¦p—œÏF¦ áL/8І³ ôìÓYç`xiÛ¹¾k;jNs}X;vuªˆ8¡q†Šhßš~Ó¿ÖÞL•ï3A t›ª=@€ÃÇñúÊ@ÓÄ—ÖIH‹IM$2DÊ ê ú²8 °/ˆÑ` ^P3\Æ^§;.‰¶.0è‹çx×gaÉÖV¡®°¯¬©°ç2‘D µ·Xˆs@ ŸJi8¡PžN0”Óp–¾ÜLÍͰ`È™kâ4œ•77“s3,˜ræš8 'âm'˜â4œ@ˆïA?Ãç€RšßgHͤÚd;r@®dSJrä€8.ÄÀ9 ŽË1lˆïxB´u¡Ç»>P̱9 ügË¡¿#Whšá¸Ô ç€É&ŽK61dˆ—]7 È?ÉWsX²‰ÍÈ¥D¿ÑÚŸšI3ªÃ° %›¨¾£@(ÍrEàPJòç€R`ˆ¡s@³·J©HÁP®ˆHÆÜmÍm^q^ÙÕÂ(¤â&2ÈÁØö,Ñs¼KŽÉc”¥n¼*[®8O¡vŠ„Sß¿ŸÆ 2 U ¿ˆñŽ7s´rýõü~6ûvîž Î-ûäÎ|³žá¾ÕœÝS«ÃqÞ,‘x  ¤ìÑ 27yïª/Øê$ˆôy¾g4 s´?û?Q"Ð^¢­«rt?UŸ_:ŸÊ;OT žþä\ä\Ó€âTŽØ}ñÂÅå½WÜ~<ÏÒ]ž¤ŠdZ·K—ÁòÝû™ ¡YøÔÖßè~É/( Ö;B@ÑœzGI ×; P¸Þ‘ä¬w”ð\·ä¬w”ð\·¬wTD‡!\ïHt¼7Á2D¢­ æºsª6\ïˆ\¸ÞQ‘p¢`¢&á°`]% g¬C¤ásÝXË Êu—uˆ³ÎÁô\w*H8ázGN¸Þ‘†®w”$œp½#Í9×;¢¯Uh½#ÈYï(á¹n/ÈYï(á¹n/(Xï($ (\ïH ×;ýFázGôg­w$9ë%<í9ë%<©î-ƒeˆ‚‡ +%ÑÖ…ëP¸Þ‘èÔ…ë‰V®wD‚àõŽD p½£¢…ëç­RïHE ×;fD¤p½#Ä ÍªwÔ4 p½£¢…ë‰@ÎzGÉaê5&„­w,ËA®Ãç€`yºYõŽD¿Q¸Þ‘êƒ ×;"—®w$œp½£$á„ëi8ázGN¸ÞQ“pÂõ޳ΠÞQ‘pÂõŽ4œp½# '\ï¨I8ázGšsÌá-),”fD g½£Æä€0õŽ“šSï¨$ (\ïH´uázG¢…ëÑŸ´Þ‘¹Ê5&ÄÀ9 Ì1tÏ+çšhEq°°RÑ€ÂõŽD+ 怨Ž÷&XXI´¢p½#¯w$…ë (\ï8oEzG*R¸Þ1!"±¦>pk©Lî7y€¬i¨w|©ç&¿@fu¨w|©ßì*µnúë$“yœÅ ~óÓV¿yÕ§§&áx«uYˆä¸ê…•Iq¯Ó€"_¢.Ë% ˆy+8“DK"P ÞQç<£…ê! G^ÐÊ|­ƒzGóµïç|ÞŠFfAÛʆ“ãw¢‰@‘«ÞZÃë­×¶ç×A]÷¨~\ÃëÇ}g]·„×u[9¡ºn ¯ëöqœvNë ×]ü°“ðr/Èiç4¼ÜÚ rÚ9 ¯T÷‚œvNÃ뺽 §Sðºn/ÈY×­áuÝkë4†P]·†×u{A;—cúJÖ¶ƒßÎå˜>Çaç8¦ÅÊñÛ9Žé_ñqý+Ó¿²xö;72¨9¦­Ä Šìæ‡ce¼ GÿJŽé_ñ‚–ó“JŒùaA;74¨9¦QÆ ZÙÍOŽi+±Fvnk=uPƒÊBvn·rLܺ†Ç­·®'Ä­ƒx2ÇÄ“ë që >Î1ññ·æ˜¸uˆ[9&n]#âÖ·®q+ÇÄ­ë q«ÓÎAÂÉõ„¸Õeç@ò·rLܺFÄ­·®Ãq«%?'1v.†çç$ÆÎÅP;gâc¨‹¡vÎp v.ÆÅ­`;£ãV ‹ÁþœAÍOŒèGÖƒÃí\NÂì\ ¶sM€ ´s1"?'1v.Fäç$ÆÎň¸UÂãÖ &n•ð¸uƒ‰[5¤=ãÅÉ›³¢¨ E‰ª`܇Ê™ó0#¸‘"s>ÚóP—®ÖçA¨ä‘šìñ¯m÷×ma[RdÙ½ABjG³{ÑËîýlm»÷È}¤"w¯uÏÓêåoÆUÚ½Þç4'A0"Eñ_¾Ž—tH•»æâIE I•OIÇÕeD ç¸:¯òó‚œãê¼ÊÏ Ž«Kˆ@Áqu‚hë‚ãê¢Ã’*9ÑŠÂãê4rI ©r¡œ†W§xFÂ Ž«S4œà¸:)H8±¿¢ë©sNp\˜u&J•kqLi8Áqu ‡ê‘Ñz‚ãê´ á¤Ê“=OH8!©rå€ÇÕiIrŽ«ð—z/È9®NÀk¼ ehŠœ4 84ïžÇÕ)¢…¤Ê5þ3Ž«Ãû ÇÕ ø“äW'à/>^Ð24ENBRåSçCA!©òëžN”*ݸ:¢9¤ÊE7®ŽhEïDq†Ý:—T¹s.ž$ÇÕa-x\ÝÌM–*Ÿý#M—*©&"ÇÕIiƸºÂɧs@ »oθ:W‡ÊaÆÕ¡r@sÆÕI"Pp\ :ÞÁqu Ñaæ€Rª68®N#—Í¥4œà¸:%H8¡qu*§áÇÕIN0Äi8«Pn†Ï:£s,ž áÇÕe '˜â4œà¸:‘p‚9 ”æ÷ æ€R´ÉŽ«ÓD ç¸:T3®•bøׂ‡æâ%ŠW§ˆVÌá?#à¸:MrŽ«Cå€0ãêP9 츺rŠœJh@qh.ž ZQ0”‚9 ªãÈ¥Õa怰[Ì¥™$ÇÕa-x\ÝÌr@))˜Ê‰¹Æ8ÕãMôT™Ø¨šµ€qªeò'ËĆ8Î1NµŽød™X''4Æ©c0Y&6Ä «Ëpø¸:A «#ÇÕ)I «Ó4 ð¸:ErŽqª~£é2±.PxŒS š,…ë!‡!šSï˜Ð€ÂõŽ‚®w$9ë%<×í9ë%<×í­‚ÕD u°:èÔmBœŠhEïÁ N¢M¨wD. \ï¨H8ázGM ×;ÒpÂõŽ4œp½£$á„ëg@½£ á„ëi8ázGN¸ÞQ’pÂõŽ4ç`,CD_«Ž\·³°’ä¬w”ð\·ä¬w”ð\·´ •! ¢­‹ƒ…•’®w$úÖÁ2DôgäÈu; +‰@ÎzG Ïu{AÎzG Ïu{AÁzGI ×; P¸Þ1¡…ë‰N]¸Þ‘hEázG$^ïH ×;*P¸ÞqÞŠ õŽT¤p½cFD ×;BŒÃ¬zGM ×;*P¸Þ‘´t•!jLjfB½ã¨°Rc’MlBÈY´G´¢u° ‘hE›`a%ÑŠÞC¥¢T  õŽÈ½×; N0Êe0t(W4œp½# '\ï¨I8«`â¬s0=Ä '\ïHà ×;ÒpÂõŽš„®w¤9ázG´%…Ö;œõŽ“ÂÔ;jLhV½#ÑŠ‚õŽJÑ€ÂõŽ’®wDFÐzG"³ÞQcr@˜zGÉͪwT4 `½#ÕŠÂõŽD¿Q¸Þ‘èÔ…ë‰Vô,CD‚\9 wa%(\ï(h@ázÇy+‚Ô;R‘ÂõŽ ‰ÙÇE×Eabú¸èš´„Ž‹6œéã¢CǸhSWySÇE;9þqц#&‹q"¢˜:\yÄq‹¶VŠés©ƒ È[†(Xèº Õ;: +ÅôØAÐ2P†˜¤D Ø_X)ržÑ€Vö)Îæk>ÅÙ™m+ÓçRA‘«ÞZÃë­×¶ç×A]÷¨~\ÃëÇ}g]·„×u[9¡ºn ¯ëöqœuÝ^×½¶Q‡ëº%¼®Û rÖukx]·ä¬ë–ðºn/ÈY×­áuÝ^³®[Á뺽 g]·†×u¯­ò硺n ¯ëö‚"»ýÉ1ý+k[ŠÁß¿’cúW|‡ã˜þ+Çoç8¦ÅÇqعÓ¿²xöSìÇô¯xA;—cúW¼ ‡ã˜þ/ÈåÏ¥c~ØŸË12^ÃÎå˜þ(dçrLÿŠÙãVމ[×ð¸•câÖ5m€š…c³ 4 >M¥{¨ü…~>ÿ}” Óñ|:Öe"ÍÏJsž¦šÄìõ‡¢.tÔy:É.¸Aóà™Ç™x·NóÜ Ç­‘ë¿·JAŠ‚Á ÑŠ‚1ÕŠ‚ù9A´¢p~ŽhEáBÍM!´ c5ÍÎMŒ!<¾}235?7qã|î„ÌÏ%D `~N«Y A¡Þߪ˜rò„ט±ö;ï‡"§‡$ÆÍXµ™æ3'ßÌ€;‰™flÄ3]Ç&Ž<—VZ˜OAÏLíIyÑ€w©ÂÖšÇùáø£IyU pXþ~§3çç*'|ÐÇ{²W—ŸLHyU‚±81U t.wžTCnç¯ï¯ÓƒŸI-Ù"®yÛÊw¯ÌfyB+^–ß àÔP/V㯽ó"²ä9­8ÕɳÍÄp~íÙ=9žIqÑ8ê¾¾K&Òû‘g¦|þü3£ÕD5ù®y–H™ìòœ"ðŠ^>º”Q5ã^—箄´Èþlah‰JrJ³¿É44)w‚¶ôïäNJEH«‡ý~|š4¢¤™Ar<•?rÿCHë}àÕ\Aó? Ër»Ÿäî–Pþnk{’½Þɽ~<2Êܼ¯Ó±sUÉŽ*±ØÒÞ_TCY‚*z Z“j>¯öj>ßñ.ÎJœ)qŽçó õ!§üåº×ƒ×UógINù/ØËêNÇ.Wüvt ¸èõí ÷6ÒßL%ÚÍŒÇÉÌÞ%.îé¼øÇ:éõIž>gZžÿ?eéñNÊ3s®~þ5ú’ˆf¦_UçðõEÁ‹þc¯ûÙ³cæ÷«ì‘Öñ"{¦ª±Ò>ï)mÄc/çed9©ÎKË[Žï¼’×ÜysCØ/¶yæsßËôv å­¼¼dOÍ«g\êÊc9v~m5`.ßÉDï§™òýaFH«+ÓîuuÖã%ð<1›¢ke*dÚ!/ >ÚK&®ªp«®õºÂM<„{>Ú0׋·B`Þ|´ás‚èih˜ç-”µéêwÃd¤}´ú™«Ï]þn—s‘ÈÊ:Ëâ+ø!ùÝ^ÒÃ?·ÿZÚE´´"¸#¥Õgòçs[ïd9Ù:©’*¢°Íåâ’!Í Ò.ýèªTÑœÉrm×»|ÊÇ^Ò–ý¼þ¨ mwO®‚7–Ë”a n†ž?ó"ÉŽð*­yzÕ]±]ó»•k£²%/“Ž?¶úŸ©™í,×S(jÚfd'Ë Y;¹ÓJPÒÞûÒûV²¼QŸå#‰g7¼_÷Ÿ¾4í'ŠhëIŠë)ÔVþйó‡îI±—é/·ˆÆ¸&åP,p'dFùÉ-Ú‚m{.Eã-ç’ø _ô Js7¸â`ÞwŠ“þvqwï”ßxY¨^Þ;Å7.¯Ï¤ô…fáìuä??ÿÜ%¹Ô&¥Àe;‘λ ì]&Õ=gVW•W˜Õ%©âWJœ¹z~WOižow}×;%(qËW?ö\º±ÍmpK²C–&”¸xà6_Dç6ߊ82KIWgnŸßÁꪖƒG’N )nýz!œ«;ôíç4ÏÝâ†÷ÁUí‰ÞÎ%éw÷ÞÃÞ·bØÕ°ßݳäJzTšȼaW®ºèƒÇsš8útÞ¢/½o¥±Íú2¡4-/ݰísEqÃî§'­Ùl-m }ú[Òò–}ÑùîŽ5ë»ïÏ-/6Nûïøs¸ì æ.¡=Ÿ«QPÞ¹í×´°f´¶l±~mk΋ùÜŸÅ­NËÛ¼zçÞ~Öl÷œ&~?÷> –Eo?wˆFÿ½þ§ Mšõ%mã›ÞM”ŸÎ3~˶q$J'IÔ¡Ðõ TþýMºŸ‘q\¶[IËÓß)1¯ö\~>þ™à+)(êàKå{.ù–·4ëkÜÎÇÍy)×§Ä–WëÿžYeÏø¹,ë¸T)𲞊çÉE“òV5ï£á•‹kxIš“óÖ¯ÎÒ‹oö8f ³4>ÐËûõ¯÷²OQâ¢AÞëíwÐR“®Ž r:¯—Cy`HqË‘í45c®¬#ÝÌøÕtžz¦³¸Š.§/Ó9®ßw5ˆ“ùñìÛH‘ÁÙ ª5%®‘1øøgKãØ Aô5ߎiõâ, ÷ÞgŽiõâ,÷Þw‡iÁóâVög 1ç(B<Iô3PZg}˜Ñȇ™Èû ä}tBD_êH#Ÿ"Ä3D?EÁg ÷à É)yÍÆ¹fÔŸ¸(ׯ‚3 !m|tÊiqèaFSÒVöG'9çÑ) =yf(OÉ&ôèDº“ï¾w™÷.Mxú´>¡^"ä3P‚{ŠÏ@÷ Ÿ<ï2”_Aó äyu¢4_žf­Îõ äz—‘ˆw™(ü ä|u7Js&%:¹M~jb1ç]&šü ôò.ƒ}uŠÀÏ@bÎ3P4çHRâ6¡<&-îÝó,£‘Ï2QøÈþL’àžI¢ Ï@Žg.=Ójºž¬Ï2ù,…ŸÏ\z®»{JpÏ@QøÈó€®Iy«à³©q™ð D»¾ð3íúÜÏ@ý Mxr¿¢“º-í3ÐøYF¢Ÿe¢ Ï@ãg'‰~vŠÂÏ@–g‰~–‰ÂÏ@Ãg'1çÙ) ?9ŸeÄ…ôûkžœÏNÔ¼µóåB¢_.²ѿ6Ïûêžá~¹ q–<Åí}g ÷ÈùŸ\\ùÈ…ŸÆ¯NýêÍy"ˆÖ!Ï@%.ü DŠcžw|—‰ÂÏ@¶W'|uŠ0Ï@ý ž|]õ»]·ý2ú¿°þâ+¤ÜAHëþHä]ÉÏÏŽ§ó!õÙÛÚõùó¬³C2²4KÇ|ч,ر8WÒˆ”+â©æCVþ•F#Äüì“Jä—{ØËýž€ÂF”äÒQ’ý~OðAštÃÖÖ8|Ì¿Ôõñ5…b¾{›dÅ!ý»KFqÆÌ‡?Ô5kIŽGEð¹,Ö/”~ëó3¹üdÏ'É÷b>}Ý~/Í{cù½Üä=\;…b¾ýê×7ј›¸ß%ÁZLÊ`«µu-â–Ù˜BYʧu-òpßKù5<”v,b^JvVÙ™€²Qª7CùúVßß~ÔÜù’â:~~Åk.ý­•rÓÏœâw1ßþGûí·JÔÅ·Ÿ'_ eóB®¥lRŠß¥¹÷ëÄEK17òåúM±ÖÜû­”GžPüúÌ|û¿ŸV ¿jNA‰ÊgçÃôܱGX‡| Åxû¿¿ÿÚ3fÜ×CöÈ¿R-1¿K+†ÿ"øâ¤äág)”ÚZn¶oY'o¿/w=ä·Ðæ§$ê®R*OégÛ Éï"»%:}žï;f"ñígS„pî¥5Nk86…bRCzÛ$Oêฦ\ùuW)k³cÆë;w^Ÿ|•Ÿ’„‚Ò )|˜‚rèÕÀ\’ÝåqÙß)vìÝ’ÝJzÙ-¡¾(¾Ê?f1úŸu1_{”£<Âôruûž4rºß'µL ”QxUtÒ3ñ(µÐ)0MñÇo‹©â1ƒ9üh}¢À˜¢ÏßæÔa_užBó3 ÆX€Ïö¤Õù}ƒ9Ü9Éo³z üÚ0¦¾4ÖõaÚh©ú:[Lq ò¦°^ùS‡KŸæ¤ÏÕ#au¤Ú}=аŒón0¿-æÒÜoâv¤¸5ÿ˜Ëùï«›i.çËWÎ).´¨ñ>­˜¯oœ×4Â'à£u4k¥¾úz~dŒ“¸ðoä–^Àó!sŠ{ Z¾¤0ËMݦÍLƾ º½^(&QZQf%Jß^_÷¶†rh)ìûvÓI.…¤X SêDVM)]Êò%ÅÔ*îÕ†ffŠém0ˆe”ü©—™)¦·ÁËÝïïßž53%ÒRæ?÷ÛùI@Yʶ3fÍí\R¾®÷eóþŒÌÌðÿm0 nûÑê¶â£Õ÷rÊRIñUþ1G¹ZÌ¡]Œ9ʇ«È)>ËÚ=ÛšÀ¡]MóÅ% &zy(Ä€³Ÿ|Þ^#MeæsÌÛk¤YS-ÅlY©÷L±æ§_" ,}®ÙìœüÛë[œ™6c ¦h)ÇðôÄ)”Uç1U¯çºø®zÅÐüT˜² eݹ†R™2C9?ø€²yÉ1MÙÜãÛb`ʬ”¹Ù¿—ië­æ¿Î÷é‹„³è*NNëל§<ÿp"ß«¦ž‘sr{igpF¢Æá¦µÏ¼ytÈ2¼ÿ4æÄ;h8ͳCÉÁºƒcŽßQÓgt®Æâ©–º5-óT—ÝÎÇû%=Ý’}«[ú£¤¹èFI«ã„QÒÓ8‘‘ýÙŽÈ6ßO9"ût=pNéG膓ÔwiÅ)~žgšÒp–¯ûv®%*N’ŸNéãNbw¢ØþÚÑT‡Ì{SY _Ôû¥.û±x}R¯ƒÁ£jaÝÐAÈÓ‹BÚbÑb°QÈãCffï/¯êåÎÆäôòݧüëtÈIV³Ɉ6òjâyHò$<ßÍ`Âc+)£ÚÆÉ~/ó4ÉæCF¥‚·¥åBÂSø&@jÇ£N©~uíôåÓÝE%ë÷A͇,;È ÎI®ç)®øU¤°”£êÒvéywÎå|Èj¨„øÒ„°ã"ó!ëaÂEt=»<ÿ>üð›a–³ƒÜUžçgMy7?üøñ¡<]×ïýT÷Ùû1þSšÚ²2ôK$¿|ýÈéèrÑ Ðå¬U´¯*6î.—cB@‰B].'M@až.¥].^Êr¨ziÅ\®ÏÓÏI¢,Øt‘Ђ²ßO BqkƒQjuÞ(ldŽ[ÕŒ«w®®’€²=Õ6”ì&Ôý&QßË›U7ãÃ’w,¯–ëeÿ¤ ôƒjé:ÞâÜïøeö]rŸ¥ä+(·[XÌt eÓ¤h¶]Æ©K¡æ»sª (&á¤ÿ6Z¢¢½^vIºKö$_埦§)˜^o§=ÅQnÒM½|p/휦©>“¬&ê.²Nu«V¸,>L¾ÿNHVÓ³ËLùeÞN*¡8Í‹Æëg·«Os?¹•n´¶ÏŸÏFÞ82"ÉÒ|ÿ%v$«YŒ¹2ÏübNZ…‘_D˜:Ñd H_±i×[)Ò§ž$›¶1˜­ÁœDcœ¯7‘ò¯çóî)×)|¦éå:VÏìm1±\ç& (Örf®HY®“e_¹Ná3M/×ñR–ž×:­¯ulð&hñ™>>ë­+"n¶Næ7™$Úf¡1 ØÖœ,ÔÈh°û*á1¥DNjšuŒAè~£ ¤už6þiɉ~£wæ’Ô&9ªÚW‚¤©(>W×è=iÑO§|µ~›!9†Ä¡HÑ`M…·S­‰&H Ê5±ÁšÎ§zM5‰rMu:âo£Ó˜ðR-&Õ%,¡2áñ˜Ôhø—$•H"Ój:Óÿê&ëyìÆ²qÉÕegs}P¤µ!5#¡¤Ý]Q­©6ål4Cªu}k’H3¡©NÄ»Ÿ$²„ÈF´ãóŒ5*%Qkô"ߥd·úÂKJw\r32¯¬¯®úùùR©o^Ë;µ(Õš˜Ÿ$%Ùšj¢º5*m|sk”ÚøR>ö:OˆÎ^Ôøÿ>BðÖ‡(¼/Z%*ÒzL*½°†$ŃêwÚR¥ÚùÕ*Ò!¹’òwCúÜvkêíÞ‰ìD,ëXão­CðÕj^Õ¤³~<¨¼ååÂô¿–Túå i÷TTkŠúÜ_­ð O‹ qw¹§"±~wõWÛÄmH¥þ=щX6é¢m›Å1že•ÅÉËŽÔhF½dXÝ â EÆý¶1Ñ@­l!ˆùAt[gì¸þÇNy± ã‘jEÆŒ·³Ïõ§Ô€vWIZuwàÞ䥪:‹ÊOÎË¥mÝz ºˆTø•D+ÚŒîÚþ ˜ß$665nÞ_+è–“:‹›wOމ"#µnÞgó+ Þ†MÏ⇒T¤:—ü·žÃðš´.¢ÀTgØké-² 0š<|IRh"’ÉëM~¼qüË´u¢Å%§Z“Ik“ò/;nÑ$È“,?Š„ˆd2俽ĵÙ=™ÿÍäQ‘â1©M‘¤bû¨Ö4–šnï ­¹ÊÙÙ[w¹kCâ(H™Öd'bã_גꔿÖdBÁš„OCŒ¿Ü?]VÔÄìæÓ-¯Á9ù×1j1F]D‡Â'`ǨhœMÚb*è ìÅÜÉÞ\¦3œÿ1ÊøF¿–\9ת8Šlã1ªùªJTñYQYŠÅªË#rYšì2|qŒZûQ ánêü^Ôù½ÚXÔù½»N÷š õn¬º¹_’–å–¥T‡½Î˜«ú·mWU¢ÌªŠ/8§:uʼ—¶4¨zUGp2hræÛ˜£ÎÔÖBó‡¢CkQN“§Hõõ™Ð¡–Î|byØ/áoÕë%¥.‹Ee„«êMK¬QÂ\÷%Šg…a¢2·ÑzŒªÍm*Ì-ÙwÕ‹¨†'°¸gd/ǨQê¼;jFúrìA›¼X¥9Ê_¦çD§dÎúÂ*§2·,29¸–lŸ.¾,2ÉŒŸý«Ûæ¹·*ý(L!j9ÌËÖnt:¦Ùìf±ù­*(“˜-»ZÍoµçŠlUõ+[åÆŒë¶f¹1Fô5®dÍgU‡‹Õg5#A6"E~>ç7"1_..­N;i9|'j­zqWå>u5"Åc’1ê Ÿ‘V#›Þ7´3²d#ÒºK“YH3Òd#Ò¦K^™Ý«’Wõî=ó ¼‘ÞMJé·K¡7é—ÂKß 1çì•F"zM^ýþÚRJ·"ø¸åT$“¼úÝZRJ7©óƒ–D$fB‚m“è¹pC*œçŸä˜‘‘–~R±“É|þþÛv#›"ÅÊì¥T¤fäã¿ÏÞ0FÑd’α°/¤µwM…Õ#;{ÿšd.¨Hï]ê`x?!ήpЩv¯I^¹PJ‘-ªI^ÕsË„Èù"Ú„H^ŽhÖT¨ÚLÔ½“ûcáˆ_Ô¥2²·4KÒg&©ú‚ Sý ûç+ÉR²ßjiVU‡£ÅªÎÍÅ[¬JÉ!ʤ¹?·¶U= £ÄªŽî{æï*å.W…Y·NÔÁ¡Ö~Tñ]‘‹Í(!ÒÏRvŠnß»„Èð‰kuÙás/£Û÷O—¥Ø÷ŽE½—âÇ¢CõÂÑý×—‰eMÃ]Þó/5ËOzEE~”¶êxãP¬‹|kÔ¹©Ô¸—É¿‘ïµE¾ý [ÜvÙow‘o½ªÚÿ«WõÌ¿rºc±j"_[ñS*¾O ‰ ~GoYZ½!a“W‹ÿظií…Ó ÈLë÷7I‰œ÷oÁIgÜ¿ë^ŽN#W_rð/Gβ³{{ߘbmýP×»|d$œxÜ %:Î]H¬áfce¡þz^{¡èÖ³wB‰ŽC·žÍèÁµ).(¿ÓQ³I 99ø‰YT†Ì»ø8`â…åÙÓü@md¦Ç…|eÔ•+¢5íŸmß|ÛÄsW*ß¡[f‡ æñ]ªiÎB[P°µ^·æD+Š;å¶»^÷œæ+2ÓYŒ›0.Å."?¢­[+±ÿ7 MSˆ½µb—H‰@ïã:ìò;jê°µ$úŽ¢?#—±5AyYÆ‚dk—äµißÍÑèØ|À‰ÜM˜¹ÌËa‡4o¥Q^Ž;¤áx\ÓTÍw_öí®iñûÌvýúUÝÙ¾÷”PŸdÆÓ\d8ƒ'@ÿ07àDΛµ°ÚsÚ‹œÞy«×c4<ªõð•mÎrØPÕVpë™ÓÌ7àô·Æ—PrÉÑ­|ÎjÔhÞ³;ç 7gþ¹ŽBçM¤zŽÝ‰œömx®sMqÞ¢Ñy«ÏÁ…wöâ¼E£ó6¶oç-…ÞÍ„½‹Iõh‚Ðûõ¡´U[ŽIh‚Ð; Üu­gnè Fî:Ö3;ôŽ†ÊŽÛ­-$~^³&áÄ^'D"ZN¢3Îj°ž×˜n=ëÁz*ÑrÈÖ³qÖ:—~È.ÓŠæ\¿;Ë·+ŽJ4ÍykCï«*ˆ|䉢¹E‹Íy‚¢¦ ¿òÊ›×ë»Þ©” "óƒx®$ h鎈 '{vè*ù­·ÐüÐûõ)´z²±†ÞÙ-¥úÖ¾g¨3áñnBïíÖÖ™\Ž—&ú`Ç¡wÕ­b@åägš™Ð»?e¾ QTáöð ŸÂ²TCVmz Ç´Sæu? §áDþõGNpØh=­ËXuRŠ”†³ìj;÷½zU¢Ìh‘pâ1Çô$W|××€³ê*HÍÑ{äå«1ÍzÖÝ×½Ú%Âpäî–Ðp6Æä~¨z‡3Ñ9è5>[BÕâüå’æ;ý3.fï%tÙL³ Åbt;ôKÙïIq2h@Ñh„mkYLÜ G³äÌ6q‘ÅÄÙÖ3×ÄE7è£-9³M\d1qc/x¾é‰,&nìÕÏ7¥ÑÐĵY?#Û]9róMO44qŸm6Ntã|SYLÜ8;2ßÄEÿµÊßg¶‰‹l&®qÍ»FUµ4×ÄE÷R³ô<œ‰VäM§â’fø²×¥¥¸§_ Ó¥*Pä•ä «@oeÊìeIÖ$c>gÈ>OUJ@ZX~&iþîž>l¤9™…‚Û§Ok2ÿ¾Ú†iô¾ïØ{N!XÓ8‘þi}¸y¿ñ­—–5Yµ°~“Ht{i…¼˜‰n{A‘W¢Zk™˜_¢Z¥’ô2ð§«`ÊsWsö‚âþü’NÌÙ€`bÎ^Ðʯ§›B¾$/híe|Ç©@=ÕãRï r{$…c—{-½ w?ô–çÿ`ÿt"­ ©ò»jÒ#‡´šûI‹Þ;Û¡,W¤‡$$5-±ŸŸvñÏ„gD$ÿœè@˜YÆÛß¡øgñÕ‘é Õ‰ˆÇ¤JüÓʪM"ÒʆâŸ5骟9‘%29âíïPüÓ¬éRiï'Õ‚¦ÛQÅYEú†½øIï†ô"þ)Z¨4Ý×þqÊ`·º’™¦Ú½‘ÊK'NðÃ-Ë âÔ~R-hº5ÑÙát>7ßS)Òtå'ª³W·É¤ú¾-I͉(I\2ªÝs7ß&üò“Ú|—¯S‚µ?ùçÅÍs@]¾^Päoˆ-Âv"óöÃ&’ "PïÚšûvßä yv“é½4®)(ê>¦”é;öº‚VTû*û&#i@:½`¢!híñ;Ö)‚6½Ê½dnÀ ”Eð¼ ÷1¨ý2 žÿƒí•ß×$óHZ‘€²t~R?û`HU~Í@šÔ~RÔ)j´?S·{0•$?‰½¸®%éÒû`"I~’qó~¶6ç+?e2§úâ1©s¾ò“ØK}D2nÞH¶¨" XªÚO2nÞèùª&Á’ï~’qó>¶}¤ŠtÈ¿Tf¼qóFòHõRA´¦ÆÍ³tÿ—·úWiÉ÷“ÎŽü‚ô(Nd`ÛvhW‹­N‰¾§¦ÚÙ7œ’‘ÜÁÅî%H ØBêÖÛô+HØ j²yV)]]„Ò’ÄJº*%õ+7ÌÑú*³2ECPìá3ECЪKªX5 “y®øP·Þ­HˆÎ© Aý§Íñ­ÓÉò‚ÞGŽJ“þò°ÌeÑé^z—Åw–kMDZøI‚'D¶ÁŒ9܎Ʃԗ:¬¿ÅObãŒJŸ´»S}´›7’W¬H×ü;O©H›÷Ï–c˿ςŒ´rê'åâ²,¥úÖN-à‚tÔçT§ü5ìªS.ó 8É`@Š,/ë}N“/9 Ù >N!LRšõ°€!g9|Sè^/Š}{4þtGÙŒfä`û¢PsîiFÄ©¾¡rHz¹žó‰ŸÏ'ݧ\ï%LzÚÇi¦$lû鮿ù4çyªÏ$œYO©FdÖsé­$ã㼿xA]ï[ýûÀä!_8‘MnÄÉÉ ì|œú;Õ¿mò®Î{VÃ-Kn {Þ"›Üˆ‹#oˆEc¹‘ŠóÙqÑržiB³žØÏ¹Ad }œÕK’«“ªÎA®Ž»Œæ¬»‘†ÓÙ\]¯Dûöê íèm'ˆÎÛ«'<äì®§©òsêW?±^d‘ªW÷”Æ÷:'ZQ4º.=S áó‚ÌSÈg{7TΕy )®þC´uK³¢m{9TÆÔ¬¦=ãÅ^ñ¦ÂhståA z‹¦¨Q•âÈ’urG–b!˜Ü‘ÄÆÅB¢Áô޼ ¥_M‡çRЀŒâ·þgét—RÚf—OË“Kž\r©h@ë—·—Kb—¥•¼ /ÿ†•°zAï¾@üVÁêÿ`ÿ4e[[ÀëÑù®/Š×2ó6Q•|ï3"Ûж¼üµvÁ‰\htJð͵ºÛà …ú¬4ˆ­>n}®Î2!«ýõ‚b[•Pû$“Có‚V/%‹ûVx¶4w¢î=/ÔV·»8‚-þ³ÎÕpM5™ÂXXŽœu¨)g9|ÃîÕƒ Ì‰¿”¾&»…¸¦b^ªäµºøã³êÆ>œ Ϥæ¤*M¿ÔÏ•ÿä4çÍ›*Ùåyz¦ù}6ÍÈÙÂ"ûS­‡ž´û§¸~å?{λ)–Þ¶ÅÒízžÅïsÌOšïôùªœfýUî}ýñ}¢hBSqRI^ËuDáߣ“´M1°<-Õ:G‹,!á˜äÏç§¥DìvJÄ-—$6âtávRòÆiöÍ$>?Úº­äÒ3Nìåäò&iömÕY¸±~aá2NsF¡Í$š’sdœÑ;hÿf¶xú8ïîVƒÞegFíýðü(Tñ]4­‹–oR2éã»ø²KB´¢¸Þº2X^gn@÷TÝ çôº“¹¢ËðùYþF‡“¨÷¥ø`“Ýþšß/’hEk¿„!>ÿü¶peº­¢Œ3Rê#RÔÉ Z2Ð0yA?‰uƒ]c¬hI A?i铕㪔h$"Å^;]®ˆÔ>g¡K·˜j÷Ö/‰õNEª&•Ž1©IxÿZóÐeH‘ÞG5ò/¤[NF²¤¼ûýh·£|¡šœ÷¯5ç}˾$ª—ô¶è"ÍHz¿5é†7§ÒÓ«2:ë="EíMFbõtÞ{DjßCá¯:ýhQ€)7ƒôRì0!?iP,Ïf\†¶éZNÉrÉ ¨Ñ\Þ¶ÙU’°~Ù)þÑ€X@|¿uµ*öHÇ)¿ß»!©·yÆ7ª6¯6³6oHb/wîë³àsŽxK¨âtÙ½Ü'ŸóÙIÞÝÛå»÷"0ÿñÙè"Wù¤ñŠËýLµ&ãï5ÝŧÞÂ]«ë-Ý¥D¤ØíåY:Ï7b.¤qiZ:Ïßsžˆ±1šu"ö±Ý¶µ!Ýï¤Ôåš?ŽD¤å° ¥ Ÿ )}ìÄY‘b·$S~“(ÉÄPÚO%(2Å&h?9$™¸$Z ‰L.'Ö~â8í'Ö~â8í'†×~J¢Ãà×~JASؼ §öS.wÜÑÇÚO5ØÑÇÂÚOcE¦’Vdbaí§ñÓOµ¦!)¨ý”ýLaí'2ÒÒ­¿“ß”0ýÐ~rèïä‡[&`ú;l‚öÓ@eŠãT¦Øí§rÇ)g±°öÓPÏŠãô¬XXûi¨gÅqzV, ýd)Tã8=+Ð~²èYqœžƒk?qœöƒk?qœöÃi?å—Ô~b(í§Ô~b3´Ÿ°öªý” "Cû)Åi?1°öSŠÓ~b`í§§ýÄÀÚO)Nû‰µŸRœök?¥8í'6Aûi È”â™Øí§ÊTŠS™b´ŸŠL)N‘‰MÐ~¨L¥8•)Ð~rèï–õKÀšãX@ûÉ¡¿“_…çD‡¼qó†zV§gÅÂÚOC=+ŽÓ³baí§¡žÇéY±°öÓPÏŠãô¬X@ûÉ¢gÅqzV, ýdѳâ8=+Ö~r+2q¢³×h?¹U¦8‘ði?åÅÔ~b(í§Ô~baí'§$'1¿È×’äÐ~JqÚO ¬ý”â´ŸØ í§œhEAí'*ÐÆ.É”â$™XXû鯙bí'‡þN^4Ù<>Ð~rèïä—cqÓλjÇÚOC•)ŽS™baí' ¨œÅÂÚOÃ.ZŽÓ³baí§a-ÇéY±€ö“EÏŠãô¬X@ûÉ¢gÅqzV £ý”—¨öƒk?Õ öÃk?劄Ô~"â8µŸª}ƒj?1¸öSÅj?1¿ö“M[¨â@5Œ\èæ5ŒTÃ(Åi 1¨†QŠÓJbP £§aÄ F)NÈ5ŒFÚBå9k ± †ÑH+©æµ’\è:×P #×0ª¿ŸkFÄ kaãW°†Ïh@QHˆ'E?¼À„xÒ„äâá8!âá8!†âáRЀüB<|‡¶§…xRœCñ”U`!âá8!âá8!âá8!âá8!†â)óNXÏ(Ä“‚Bˆ˜$ÄÃqB< ,ÄÃqB< ,Ä“â„xTˆ'Å ñ0¼ϼxrºgiÈIq9,$Ä3üIq‚?Ì/Ä3–_Iqò+ *¿’âäWT~%Åɯ0¨üJŠ“_aPù•'¿Â ò+)N~…áåWRNP~…ˆã_Iqò+ .¿RÆ­`ù6C~…hãÂò+9ÍÎõãV{·;vEî¾zG?:pÚWÏq}õ ÞWÏq}õlF_=ǦΠ}õÖWÏ0}õUP í³b˜¾úŠícúê?­ñ+´ÛMè«ÿµ°Ð~†è«ç¸¾z†è«ç¸¾z6£¯ÃÂûêS*RêvÇzú¾¾z{?Ùš}õ×WÏà}õ×WÏæôÕϸva}õ¹ E¡vwôŠÀíîè%ÙÛÝGMè)® Á›ÐS\: 6¡[¯ÂÂÆÎ» '¶QW¤y×ûxM…¶m,¯eã8/+ƒnWyzN?±uyïùo5ª¢Uâg$¿N’d <˽ûꊋӴ,38&B^2ƒªƒg@:;&4 ¥m· èÒÝÏ) 'àÅô¹í¶®}'äTWÕ¯¿_]WW ’°×_/hm@åsöWw-5 Ðs¶´©/³uŸÇ®o»ÃíüT4 w6qÁ‹åpý“šˆ½JåŽÎ÷í'Ñ7äÔU-ú–ÁÉê I8Æ0èötŸ{œÂ¶î¤"á» ?þYÎ\’ì. ǘ…Ö,˜QýµÞÔ=$œ¸+h­Bû±Þ²®hÖÓ“J­Ä_‹]kÅ_O—£Üå4œ¥ÔóérFµ†K¥·d—ÓìÛ¦ÓT¯´Û¦z¥Ý~=äH8ïæ÷ùÛ~?—Þï#‹ÏgÖw:¸Á}ËÎø;í?↾ÿÙîï2^¶qvWAÃY¾tœ ¾ÓûMÞæ}§ÃÛ»JåŽÜ„ÂÃRœf=+Ϲ><‹s ÐÃñqÖkºµ¹¦O©v{Ó-F9†kZ¥"kšIEŠÆnOßá7MjŽövkÝ8hÙ¹=/µ7r/þ(P0¬ÒÉ òTJÐøÔõ}àËS\% ¨w꯾þ*¯þ˜¨DЀV£ß¨ï›Þ“ã z³ô œÓªíÛ8§Ï[v­ˆ…çR"ÐÒ­ÈUî¡Îæ}K!8» ¿‹EÍ3yc!¸¿Öû¦fæ­íúlÓgó‚6v ½„OÞ¸„à |>Ê.çÑ£: ­›çÔ$#9„àÌe“g󓘟’œó“–vqó#ÁäÙü¤Ø®Ñ.èŒÊT!¸š‚ó“BpÍï‚ó“œBp\æ(7 M‚«9 !8'(‡ß9˜géh«ö &ÐæãÄ.Á¹ŠœóqœBp&÷™*Ws@Bp>ŽC®ºù m>ór`‚s>ŽC®á€„à|œØÏ Áù8+—@[yrh‰~‚ ÎÕ`…~‚«Î5LÎÇq ÁÕßÏ5#â„…à¨@A!8¬× ‚ãèG?˜Oˆ@!8SP‚ó‚BpMåHÎ ÁåRÒ€üBpér ÁôÙʇz >›´¶+ÎÕ±^-ŒÀBpÍS)HÎ z÷Å*@!8ÿë‚3/¥0!8?É!׼ɂ„àü¤€\ŽöèÀBp9( é³á}a§œ]qŽjEK_}PÎ rÁ5 œä‚«¬T Í¯„„àHpÎÇ ÁÍ‹¿¦ Áq–v¶z߀m>Nlœ3¿LpÎÇqÁLÎê=ú…àHÎÇqÁÕñPÎÇqÁLÎÇqÁLÎlj½˜œ‚›ïO‚#âlÜU¸¹ ´ù8ïvÁ¹úû Îy¿Ó ÑÆ……àˆ¾ °vE`!8tà:UΔ0!8?É!×@Bp~ÒÒ/Ï–£cW˜W):x.WE¯0¥?É)W‘`ê7~’C΄•0!8?É!×òÉ%gâJ˜\å‚kP !¸* ‡aáBp9)(— "RPŽlMK»<[S*’ãò“b»äœ!Áä¸ü¤ ÜŒk&Ç5 ((‡^X½¤‰Bpµ_É眼‰Bp†4çäM‚+}òtÞU8Q®"Í»Þ-k²÷çæEllf¨Fàlf3A_Ã7sIr4ó\c¸Ø€ À Ù,òöjÎÀYºã‚è7Ú¸ûsó›’ÖŸË‚À¶ŽãüpË$¬ã˜Mhµ²æÅi)²p#°‹¬»d-º÷ ÚÜÌÂÀãææ’nnfss¢¯6ÜLFr4—–ÑÌàÀ ØÌàÀ†mfðFàfMÀF`o®IàF`onHÀF`o.H˜F`o6$h#0Ã5ç— lf¨Fàlfý¹¹ Z uçD ¥½?7ÍnÑŸËÀö¶Ùüò(~$¬‡lm¶·6‡áKŠâX xÜql¶ÚqÌÀÀmfàFàlfðFàŠofðFà†lfðFàšnfðFà†lfðF`³{ÐF`o6$h#0ƒ7×—:¸˜Á°˜Ák¸˜Á ÚÌàÀ5 ÜÌ‚Àž¦Yª»)ÜLFböæfsö ÍÍ ×œ_ lf¨FàlfèF`®¥¢9ÈÓœ{(³yßÒ¤FàürÔ’Ï3yãFàA7«¹/f$Š\À>Oäjvö²Î»—ÆÀÎö\*Pëæ}Z/uh5›Ðü×J‚ö…3x#°1¬Ðö\onHÀ–co6—:´˜ÁÒQ™Ú\“ÀÀ ÞÜüNÀF`†i.Ï7¸˜Ák°˜áñN?¬˜ˆ³t5èVûmÐeÁFàQÃqÅ63x#pÅ63x#pÍ63h#puKÀ´Øp À ÚÜpžè'ÍiÀíz`À Þ\žp#0ƒ7×`#0 6Zí´A—ÿZ9Іc6£˜è`‡9ÍI7§è§8X#ðŒòƒIÀ¦ ÚÌÀÀMå°˜á¹$ùù.UD¿‘³¸|¨73p#p¸¸y*63p#p63x#°y)…63x#pó& lfý¹øD½ØÑqœ MŠBý¹x_ØÙlï8Æ“›ØÌÀÀ ØÌÀÀ•‚7è2h#pÃè8Ú÷¤0q 7KÝúÀù©Õkçç™'D h|z Q8?rè5iâ<߉xÎT¤Z‚¢ªÜõCR¦ô¯µ›~VÅß‘ê{@§,öþjηh9‰P4œÈQ¾Å/.£ëíëªæqú¿EP£æÜ¾ e>Îø÷1ë©öíøØßçmaÿ>¬?ÐCgJÓ€z¿ÐðÄéëswÔOÈ/Nܸ¼ÎüB'(¯óqÚ_hký‚n߇lgáü‚úœï/€™óqÆ¿O{âŠß§Ô€Cþ>öWý@݉+  TjÀ yaÞ6Ö´ˆ!*E}^ŽÂ½]åé9´~¸bK8~l››ˆ_¸è@òë$‰@½„c±umþ"My@/ˆAU­SŠÈlzA½„£]z+‚%½ ^±]Q‚%½ ^±™G‚‘pô‚z ÇTZîJ8zA›.2zµ@Ex|Ûng€eð‚Þ]‘‘æÅ¾qý“ú Çñ‡L®mã\Ç G”Øôqz sz`ÂÑÇé%LJ˜pôqz ÇšcjÒRDÂÑÇé%[«Ð~CÀ„£ÓK86f®Ç%-[ÂÑÆ%}œñyëŸXÂÑÇéÅá6(áèã,_¤Zç ˜pôqz ÇñuL8ú8«ÆõÙÚ\Ÿ§T;‰µ¤¶„ã‹ëS‡µë“IEŠÆ·]ÿZå½ Öe6m PfÓ r&«Ûî^üQ4 ØõŽW_«ûo¼GbK8~ ŽõaHî}榶„ãÇk±ZQ:C² ^P/áh9 °< ä5t” ñ©ëûX—§¸JPïÔ½†y•×xLT"h@«±ORIñ¥ˆ<àÚ2â%;gq²`™M/È{ê€i@hœpüµî,µé'Eö9ç#³p0>ˆú õ3x0ÎL0ÎàÁ¸ƒqƇ1r ‚ÆÈ,Œ£þú<¯@à`œÁƒqã Œ§Œ3p0ž—yTx0ÎÁxµwà`œƒqÃã ŒWp0ÎÀÁxÍã Œ×_+4gà`¼þ} Á8ã5$3p0n8À Ÿƒñ_ë9€É,Œƒ~ù¡mœ=Éf߀A2 㣠¿â€ƒ~ ÆG Æ8o|,`0Î&UÿØ®U`ŒÌ&UÿØ@À¨Ÿ…ƒñAŒÜÜvÀ™…ƒñAÔo@ШŸƒñú0€ƒqÆ0gð`¼> ЙÁƒqr#7‡Œ3x0^{Ð`œMªþ±ø>ЙMªþy‰\óŒú<7·0gˆ`Ü€Á8 ã£VŽiÅY#Zq8¦g lÅiV„Æa­8õ@ÔË8¼‡ç¨—qx+ÏQ/ãðVž£^Æá­81ÂÊ MŒÐð‰>Žsb„‚OŒxHùM›¡à#¼ ÷D‚\\Òãå'…üBË)##0JÎE|%š„Ó®Ç2¸ñ’Þ/§»˜Ç Î()9—ä¸\}œÞz“)Ê}+Lö÷qMŒøµþ@Ï}–$4 ÷™qâ€3JDû O\<ÅÆõ¿ 4•9ÂÆÅSNœå$@O\<åÄYN6ôÄÅ“Nœå‚ž¸1GÁ§â¼ÿ·†OÅÑð©8>Žs*Ž‚OűrBSq|*Žã¼ƒ|*Î gòTŸŠã¹ü¸TÂý¸ÅÛÓnÀ‘3 #ç9¬vŽ™ýeù/Ö3üË Š.V½u0ëäræ†^cM‚y~’ËÒ•dPKWÀ¦.Ç ó‚\¶Îp­³ƒÆÎ€@ÆÎ rY»ú7‚Y»WÐTsW“`æÎOrÚ;°w Œ½{·ÀØ;‰°w Œ½“{·˜`ïFVH ¬Ðbнû°þH@˺€Ù»æ[‚G¯ ¾Ö X0á9â׿ÚAÁ{ÀzA®¶Þ:X<ñ šÂ( ð“ÜÞPŠ9wkh›c‚X/ÈÅÑ%ÆÞ­Áa¬ù’ çn csLû šÈæ˜@ÖOŠ\n—D¸]‹ÿ6Ásgëø;’>Ó¿ÿÎ ùwáßù@Î;I ü»ÐdÿN ü;/É¡#îÙhZÒn÷Fܳє¬E_|ÏFÓÒv£&[°½‹¦åíÙÄ=MLÜY~$ ½‹&fî,¿øÜ­áÉbbÎ]øžeqUŽ9á{v”–ˆ =‚ß³fëÀçnHësîÖˆ¸B ìCØ»;P"Ð1K'õ?N•5iEøòQ­èØ[Ñ3—j§”žT 8´l@Ÿ¨ZQÒšk"P]~Û„dÇso¼È.IʆhëL[¢É– vG*ã"кںU~HÇCy¼Ë=²T¤ºd%D Mªr¬åoÄù¹ýžB¤»TÞkÐG©_Po~¾ðs•É./ŽxñÁª&muì С9v÷$WR>öÅñ&:v‹ECÚv¤â@’T:¥Z“1w¿­¹+–T‡D‰]&D†#ÕfõíÅ‚VèwûÏX¡K R7©ù dÌÝï¿Æ®Ö¥ù HÝRMªÍUVè"s'óâÜ労l@Ÿ¨1w2/8 ¨4wÅ鮤ûSyªnLí„||ë£Nh@«ê7úhCù͚à óËOr‚hEÆÜ•¥ìåÖuÇûY¸z§´"Uænûó·jÜ:ž.¼XP±ylwK³$fT wª:BJPe… HÊ[Ɖ~£ÚÜýýÐ=ÃZîÝUÊ]®v‰VšèCZ¼J‚œŽMR*îòž©TQ‘Œ¹ûµ˜;© ×aæšþ¼ô¹|”Åì+T"/<£s§ÿZìê%ÉÒ#ÕŠïî·öPé9—âJ­hÙ¹‘Ä¥tí4Ú‚âÎ2ÆAԿѳTz›á A«ÎE)WÔ¸(Å7›¥É.û(Cкö*-§C÷Õ~Ã]ó}–Ѐ6ôoÛ‚JñRJ¦D§îÝ|°¶p¬8t…Ç‚F½åYø_Õmž$ '2Gá³9 ¢1ßÅQÈ‹£ % ‡¿Î²o…_—nò#ŠÆyñ¥þ'è`<ÕÒ)‘Ïä©Džp"ã1|6ƒhìiá1ÿGMÂaÃÐÄGõïS¾$Í9oѸÔ\®Í9¨Ü®ˆÃx¦µ¢YO›`G ç=Ä!Ú·&nuµŽ)X똴ö¨Ñì\?nµ6©¡ãVx“š¦"EÁÆ;ADbÁÆ;*ÒÒÓx§ÀwQ IÍÕx§ÀwQ Iͺ&…i&ô‘Ö®5)L3¡´ñ7fšì”¿Û©Î^Áºû±ùÇ1jl‘$³GQ¨sëÝ9{$ݘøhÙÑ#éëÆD$ì0¥"-}ŸèðrDŠƒ¦TkZ;Lšäê0µƒ”¤E¡VV4ÈÑÊêišUD¤(Ô4;ŸMmÏ•D¤Èßž‹ã±·çz3"’¿mö(à•gi]ý3P~¶÷~ H›ƒù;%Dƒ× ò+?k^­´ìºˈ¦yªÈsï^ô‚z/TªA°æE/ÈÛç—ñ]šm~i®‰NÝÆß=¦ ý„^л·yl¯tN´"£üìnã9pä’š¢ª…K$9¹t]<©:N ;$I5Å>Ž¿7¤À$4œ¥éøl:ÞupùÌ” áÄþ~ƒg–ÓpšzbÛ9¸k;êYç`x9ë–) §¹ˆ>¬ÕÄ:UDëabbE´ž¦Dõ¯µœSåûLpªjèÙñqüêhÅÒ*Ø·˜Tw"8þZ]ŒBXSÓ`q`5 ^; ¢Áj¼ F1ôŸíY^§;.‰¶. ÞÈóLЀVþ¼'þ0,êû{øüïHåÎ8ÞCPOØÌr`¹H/¨§kÖ¹§¢R‘^ÐÒ›IÓ9 È«jÆO%ÑahDÍþZ“[¢8ÝH¯ñÍ*)íÎme9(êVd©™¿¢aÒÄ]Þ2wIo5¬Š`œCŒÃãÙ^PŠ‘AFˆMÆQ?9[ Œs\0ÎÀÁ8Çã Œ12äuÑ òãYºƒY;†ƹ ƒñ”hëÂÁxŠ\(çÀ`œáƒñ\pBÁxžÐp¼Áx Æ>ç4œPsï‘Ï:£`Üô§À Ÿaƒqé7ñq‚Á8§á‚q¾Ï2N0Oi~Ÿ`0ž¢M6,O3"#ç¸`œƒqŽ ÆY0wÆÈ<4 ØõóOˆ~£U(FÆŸnG0îˆúѧnb0ÎqÁ8ãŒ3d0Î˲–„ä—×õ3t0žf¹uà`<%‚ñÙ+ã)É|I[è•ê=¼šk_0Äí)Ônú'Û2‚ý)Ïeô¿†Ãë©öGdê§^Ïï§¹ÚÙâÅ[8ÁÇ›:Îäôqœf=ç.KWpnÙO¢I8æ÷)?׆#ÚßGÜû4Áq¬c¸ î/¨Ä è,• ^P¸ò Esj1P¸CЀµD g-†„§¼ g-†„§¼ `-†"…k1ˆN]¸ƒè0„k1ˆVÔ¦Ü5È%9Ò?îšE ×bhN¸ƒ†®Å á„k1$ '\‹1ëj1 '\‹Aà ×bÐpµ’„®Å 9áZ …µ¤ÐZ "³CÂÓ?^³CÂÓ?^P°CHP¸ƒ®Å@Ÿnh-ÈY‹!áé/ÈY‹!áé/(X‹!3P¸CЀµH¯^‹A ×bÌAj1¨HáZ ÈŸU‹!h@áZ E ×bœµŒcj14&ÇÖbd°±D1º£*ú :uáZ ¢Ã®Å ZÑ„Z $ \‹¡H8áZ I ×bÐpµ4œp-†&á„k1f@-† á„k1h֮Šá„k14 '\‹Aóû„k1ЖZ‹ArÖbhL0Ž©ÅИ`œaƒq¾ãJÒ€â`ÑÑŠVÁ ôéã)ÈY‹¡1Á8¦Cc‚q†Æ9× (}(P¸¹"x-(\‹1©Å "µµ [KíBr¿Éä€/µ/µ ¢ãÜäè|/µÛ¦ãµ¶äªOO1³pÖ–t57ýu’4œæ÷Ôb˜};ÞÏ9ò÷±×bü¾Öbˆôd ÈYý£áÕ?k[:Tý£áÕ?>޳úG«¬œPõ„Wÿø8Îê ¯þY[Å®BÕ?^ýãEö“cêÀÖ6Gkpâ';ÇÔµù8ŽÇ1õfVŽÿÄqL½™ã8q9¦Þl=¸í¦œ¸Soæ9nU޹U×ð[•cnÕ5üVÍ1·ê~«æ˜[u ¿U9æV]#nU޹U×á[ÕâÇỈ‹á~œÄœ¸îÇỉ‹á~œÆœ¸îÇỈ‹~œÄœ¸ìÇ•ÏÆàÛn3áVÝÞ~{o&ܪ£ÛNÃo»Í„[ut{køí½Áܪ~«nP·ª„ߪÔ­ªá6n·q†³q¸3'fã6pg80·Û8³o0·Aظ²q›+g üµÍŠ”»2o6 g×¼Y†-¸j"ŠS>ñA%Šü5ÙÔZœ Èß7 ÔÔ* h鯉ÐSÓèAPÜÕDŒæZ)@MD´ϵ* ªM¯‰‚Ö#ÑÚF µÁR&:uMÄnjß@ôÞn¦Ý‹úÝk——ƒK¤"Z‘)UpV_è©õïaÒÂ[~!ÕÔW•0ɘ»Ëú¤z6ÔÈ5Õfõíõ=üÓ¼ëîOͬž©o}Ì (ò”u›˜H‚ب¢¤›¤~“š¨¶niÆ•n›±/…;\ƒd~ùIŽ"‘4 Ø_»"ÕÄ‚À hå-^)Ÿ<ˆ@½É¨ÃIÉ\Vcüˆ@S¾²mÊdŠŸ¨-“IògFz÷ÕÉ(y˰nÃèƒýÓMaÝ÷ŽÝUÊ]®v‰V‚èCêOG-n¿Så—¶!wyÏ¿ÚC‘Œ¹ûµ˜»âžØÍ]ÓŸ×jŒmõp82—$KT È[ϤŅkPãÝýZ Whé­4ÊÊj#PÜùBÆ8ˆzëª1ê3|¡!hÕ¹(ƒ¹PYšì2¼‹2­MQÓÖZ<¥ù^6þê©D¦DÇûÝ|°¶p¬¡¶«‘m>Åïø¢¨ÓhBp¢À¨{!i8,8‚é3ØFÝÛG¶ƒFÃGóFÝë©£î£)£î½#ÛiÖ³ Ž8ÏH8qpÂ9;­‚sÇÑ tî8(òÌ´†L鎦ÌwÍ´†L鎦Ì÷Ï´Nh@qpþ³¢­‚S™ÑÖôÍUpæ˜3MŠ‚3Œ‰@,8[X͹ˆ–‹Õ1óWp¢à,^ ÎâiP/«mF.h¦l4e¯w¦¬&á°àLYÎ28ƒ•†G°ÒpVÁÁ¨Ès€ŒJEŠÐÓ›ž"¤yCû¤¢…â±ÿ¬¡}S_£9Cû ï°è¡}ÐwXüоR¿M†up: Ññ Å%D[êM9ÑÖzÓÅä¡}ÑÜ¡}š†êMW<#á…â gé ›x0ŽÚÆç íÓ‚Ú§h@Á`ºCû4È7´Œ#‡öÁƒñ9Bq‚ŠS ((‡¾€Bq2K‰@Q(Dž ãNI:IE íÓSå¢YCûôd¹‡hÎоdº C4gh_2]V"š3´OO—{ˆf íÓÓ墹Cû¦ŠgG³‡öÉ„Lÿ ›¦ ís}|Cû éôÐ>húgæÐ>¢­ íD§n,‘ ½‹>ˆ¶.<´O#I ¡}bòоhêÐ>g„&á°`Í '8´OÒp‚éìš 'Ó‹&ís×|(N¬‘ Y Ö|Ðpµ’„®Å ù}VÁ …µ¤Žô³èƒäÚMÿ ‡öAÓ?3‡öm]phŸ–4 àÐ>>ݰ9š|Cû éôÐ>húgæÐ>"PphŸ4 p-Ò=…×bµó@Z *R¸rîfÕbP¸CрµD ßÐ>x0ŽÚÆgÕb†`-(\‹AtµD+šP‹$k1 '\‹!I8áZ N¸ƒ†®ÅÐ$œ`0ÎgƒéCû„ á„k1h֮Šá„k14 '\‹Aóû„k1ЖZ‹Aò íƒãÈ¡}ð`|V-(X‹¡ (\‹>ÝÐZ "oh<Gíƒã ß> ÀÆüñ†×b -¼ƒÚ7sE€`<¥"y‡ö‰éƒ¢9CûÄôAѼ¡}bê „hÖÐ>1yB4ghŸ˜>!š5´OL„ÍÚªþÁíƒUÿLÚg¦¬Ê™2´Ï:Xe„Ú¬þÁíVÿLÚç¦à­ŠÚ¼UñCûÀ'9´|âÐCû€';´zâCûÀ';´|âðCû@·*~hìVÝ`nU ¿U7˜[UÃoUôÐ>à­ŠÚ¼UñCû€6=´hãf íÙ8üÐ>˜CíÚ8üÐ>  ísfñ|ÒÎ-«X:Uñ¶cÓnUç/”'jgš;§^lâ-äþ„ÄôÃ_¥;"I8awdæz¦º#B‘pB—— ŽüTyŠ=àOUA@x˜OtL٬ˡ0 JÍã,¦šž„„º¸Fr 'Ž E ;ÀSlOìî홫Nú„<œ©±ªDrà—ƒ€fĪJ’p‚—ƒó8“/‡„„¾Ž¾´ …/‡i'nâåà1ÚÉ<ÎT?N+Çžø3Cvöíp¬ã-ù:Þve‘ᔫÿ¡ûëm àÊ2ô—ÉI)ôɸæÃ-ó´‡Ã¾ÉŸ´ûÇóñ½Ÿd &ãXs:¶ ®ÚLƒ»?¾Š·ìV·Ûå¡u­ýåºÿ>fJþvucÑo]˜¼?žÏ§ö¨<2ùLÏyF‰[ÜÇ¿Wýv—þœi»²Éè¯6e×ûj3ËÕ]ïÉSì.—Ã41ÄɸÁÕ«+qÕê î©IWÊdÜ{ýÝ骼·üîÎífo'uÙiÒß®j;*yúŸ•·»Ó.¯™Kÿñ·Y¿ôÌØQNksšÎ‹ ïsÛÙ±žÙTÓÊI§óXßuÇå u¶¿¦äÇe±4È·­®ÚŸêõ]„¾g³,™¥yÌCS)iæ·Óíowî]yÙ#ÙIʵ1Cû°} YaªJšùÝ>Úï¼n#ªiÏ‹¸ä !­YýÏöÕ]ôD©€©´U@öÐU¹œŠcB@z*.Z¢ï‚ÖœÉ_ë)»ë¼«ÜÒlöú¼ÐJ¿¶Úæþ™<\¾®¹$¤µgòÓb™/§Í)×¶ê{|×`ìòã 3í²­ Í„‡ö0ßó¨iqQãñmmß!Ý?$%ŽýÙäÒù³Bf %n9v0së”æW&%.nÌ­ÍÁ$?*«±ƒYÖ5¦–Št3×c‡¯Ä5ß•Óâ6?ûiõ/ÇoRÜûØý*W׸_Ô›Ywíÿ­»ñÆîÞã(󙗭˰ÀYÍÊý0­Po2.}ç‰è¾óCñ2JY±~ y8ÎŒÊm}‡%î×jVг¢I»Æ¬l·¶@’ü¨ŒÍJ¹¸Æ¬e¢I7³1+ŸŸ_ýôyBŠÛøœõ“|ãÆf¥ÚLó™“of•ØŒt–<§Õv9y¶6Rç—Ý“ã™gT~þIQ)ƒÔ’‰”É.Ï)<¿È›É,>„äñÜ%Rì!­É7|trÕ([ÓänÚàð©4fO 7kSINI[ú×VJʬ»µ?>Mµ(iFhƒ§òGîi+{Þ­^Û^?™$¤­»ï»Ry1ßw÷‹Ûý$w·„r'7/QäéØËC²£‹"£× f}J†4¢_SùÊÚÍŒG×ÜK6åy8K‚kîm1¼V­·¸¸O«4žÎ3" å½Z[ÌK"±“4?+ýõEÁ‹þc¯ëë}éf}Õ—Nä¥t¼ÈK66úÂ-½œ—‘ݤ:/-o9¾J^s+ÌujG<£‡òa$Ú ËY&rª·ëçã%ðD Ž$颻ž“ù“£báÁ$mÎȨ×&gä£ ß“Ûì¢È좶<–·IŽŠ†Irøhq? PUlT;YWlˆ‡PYFH«ó´•ü]I»œko½¤¡A¾“?$´—|ÊÏßí¿–V‹àU´Â¥%¥Õöùçs[ÿn¥r\É*«ž‡rqÉf„ê´Qfm¾·rm×»|ÊÇ^Ò–-©ë`΂ó†Vx|Ùþ*ï£5gRwå"ÍNî ÏêL.^ߺ/  D„ùJ‘[JÚºkÁ¬nsw Ü“‚–e”¿Û¦ßúÛÑÊ;õYæùàY)í½ßÆ:¤‰ÂŸ}*ʯûÏx+›0« î„Ì$%nÑOŠ˜v÷äJ¹—‹¨Ã5†Y˜O®8–÷⤫3wÜÖàx÷Š|u¡þ×â’¶€OQ⋸»wÊß®,,ïòN½>“Òšµ™o6Þúâ1¸êÍà’Tñ+%ÎÜ<•xm…»$—Ú^¸l'Òy7Ï›U“÷ówpõ”Žåí®ïz§%nùêÇžK7¶¹{nIvÈRRÜÐm¾ˆÎm¾qO–&”8sûüVWâv$+ón”¸õà²3F¬*hMt™¿$ý6ÝM^­ÎÜäÕê \¢%)Î\@Ûæ2ºÕ´ßݳ™Flô™ÿ]xm‚¶¸ðJ1yEÊk‚¬mduOhB<žÓt"¦óL˜µmRÂF¡Äìg6×JxÍ¡¶†uýM{:M†Êèat„ùýJ~ÚóÉÆ…(C»ÂºÐÚ–ÅÊ ¿ã¯ý²+Ö¸KhyëQè*zëÛ!*¡ý¼Í«tî­¯4/ÏâŽ'彿¶4ß»±žÏÂ'#=/ÑŸWkݬOÔë»ýœ©}‰Œß²ýk‰Ê|Gâ ôwúM»>ã¸l·-¯zr2<•ójÏåçãŸñ:“(êëHå{.ù–·4ëkÜÎÇÍ÷Pî§7Z^•ÿ)<³Êžñó9)ýÎ2e[ ð<¹ÚëhUó>^¹¸†—¤99o=Á^íg¹FŠï}ØeôksÇ,!ÆE¯ÎÒ©ç,Öårú"q–Õ§ýŒmß™(ëqHqÃzœ×»ý ¥”¸xt™šŽê¨”5¤¿Ý*ÔᤠÒ:÷§®è5ÛŽéòâ,éöÞQÁôyqÁþ­cB‰krÿl©òßn|2ûF ÓCâÅ­œýxì¡>:‰9Naµçã…ÎiÌóÄ¥‘O\‘÷ÈõÄ¥‘O\Ñ”g Á£“D?:EÁg ÷ÃŒ¦  ²qîG'JZðHÝi,˜”NiËÐà Í÷6ÌĽ>:É9N‘÷Èùx‘à/"ï37ÿMº“Þg {Š‚Ï@Öw{—‰@Ï@Ý‹Z‚{Q‹BÏ@¾‡WÊ_nÂ3屜ð DùÍ-–Á·WÒß.ü 4k3]Ï@Îwq£ÄEW'‰xuŠ‚Ï@žä¢ Ä-ƒ¯NšÛßeÄœw™(ø ôa{Â>rEÁg á#—˜óÈÍxR’÷|ä¢ýÌÃiZÒåyŸ4ò( ?ÙŸ¹Ü3W~²?Ë$¸g™(ü äz6Ô˜gÃ(ð ä~VÓ¨gµ(ð äzVÓÈgµhÂ3Ðø™K¢Ÿ¹¢ Ï@ãg'‰~vŠf=‘ò¢?Ág.ÒóÙ>Ÿe$úY&šð 4~&‘èg’(ü dyæ’èg®(ü 4|vsž¢ð3óYF\HíKó ä|v¢æ¹Ÿ$ú(?‰9Ï@ÑŒg k=éH#Ÿ"Ü3F>E˜g ‰~Šæ<$ÞÆB•·A‰‹‚%¤«cžG.|äŠüÏ@®G.|äŠ0Ï@ý ž|]Ù»]·ý2ú¿°€Ø+¤üÁ ­ß þþòŸŸOçCê³·µµ•óçYÈ`È3²4KÇuÑO”¨˜‰Ç+i‚·r%:;@Vþ•²„`»êkû[1-ä ¿¯;õ}ýV‚`%ùm!¢NVƒJ¾ Vòî_‰Ð’bÒ/K©o‡z)™¦Ø/“ï7ò'—®‘?Ùï÷’€YäÑR~öÉ…ùE ör¿' ˜ÏÞÖèzÌ¿ÔõšPü.æ»·‰Ò/±»d¿‹ùð-âÏäò“=ŸAÿj eýBîXr<*Š3Ÿ¾n¿—æu³ü^nò¾Sk1ß~õëŠh¿Ê›¸ßƒCo¦Ü‘æÛ×Úºq ÍN¡, åÓºy8;E~ ˆÂQ¢ 0/%;«ìL@YŽ(Õ“¡|}«oŠ_¿¹ó·c¡‡â:¾égNp’£æÒÿk¥< oÀÂDæÛÿh-L+nZX˜<ùJHÖ²y¡ ײ×á÷—)”æÞ¯-ÅÜÈ—ë7ÅZXsïÿµRyBñ»0óíÿ¶ß~“t­½‹GXtv %j(ÖµðkXFt Åxû¿¿ÿÚ3fÜ×CöÈ¿òp °Òª9¿m:)i¸j ¥¶–ÛŸmç[ÖÉÍïË]g$CÝbC óSä7Ê·R*OégÛË4÷~vKtú<ß5ÅDâÛϦæáÜKkœ×°0áŠI ém“<©ƒãšryä{Añë¯ÍޝïÜy}ò!T~JŠß¥QÍ/|˜‚rè•Ü\’ÝåqÙß)ÎØ»%™–ô’iB}Q|•Ìbô?ëb¾öÅbÚöñò—éi‰¦û}2qÒÀ$Ì $–WU Í1R;˜ÓÔþ¶˜*R2˜ÃÖ' Œ©úümŽ@UGà)Ô1?“`ŒølOZß7˜ÃýSØ™6XÚ¾*Հƺþ#L-U_g‹)ôQÞÖ+aêpéóÜ´ã¹zD«Ž€T»¯GüQ`Þ æ·Å\z˜óMÜŽ·æs9ÿ}u3Íå|ùÊ9ŦEðiÅ|}ãü™Æ8­£YëØÕ×ó#{d4˜Æ ø7òÎJ/àù9…錖/)ÌrÓšdl±i3“±o«J÷ÓÌL”¾½¾îm åÐRÙ÷í¦‹(0I((lL©µâjŠ’bÇ–/)¦V!®643SLoƒ'¼ßß¿=;cJ¥¥Ìî·ó“€âHdÕ¿þÌÓÛËt£r-ÛΘ5·s¹–¯ëý@@Ù¼æ#330Ì2Ú~´úy­¼cõ½œæ„Ìo¯#ŒÊ£\-æÐ.ÆåÃÜ™ß^'•˜Ïm÷Åô¾Ë£¤ÁD/%ƒpö“ÏÛk¤é¢Ì|Žy{4kÊ¡¥˜-ÛÇš‚Âü)ÅŽ-}®ÙìœüÛë[œ™Î` ¦h)ǰTïʪs̪WŒsý [½bh~þ~ðeÝùe†"ÚÍO…Y¾P6/™Ì¡)››É|[ L™•27û÷:NÂxecSvÛÍK̽-œ¦¬)¥¼I0A=Ú3&an¯÷PÎg­(–µ˜G̩ںS(¬ ÌlÏX—\R¬eùB=ÉÝR¡ ()ÛZŸäÔkI@Y1›Þ®òóšfkYËúOré•RšçÅ6•ýúXvËQWÌò>~ÄìSò ¥©-Ð[ëbÄ%%Ù²ºÓ¡Lo­ à[¶Ã˜fÎOäš_Ýë±;_ê*(ƒê¹Ò¹´½n·c® àW '€ÍS%€åW¢(ËnÚ-gz×»Œ€Ò“ËÚ÷¦º™”éé‚)”Õ8ÿ[ýöf-2ÓkY[¤ º>·øßÓ ±ýµQÔãç™/}¥¼O2osÌå–3Š3Ö´U5/&Æ1˜Ëîñ#H0Í×ÿÙ`’Þ×ß=’3‰‰ºƒ-+‹4ÿ# {¹—G9f¤aaêÄüoyÐÊB†&‘q•IaÇvßêr9P`Lî§ôƒ³Çeýèß4Îc~³Ìarü4h—iH1®¬þÛlÙ¥÷ˤßûû5% ˜J¹òÛ4”*ùo(?ÇïÛ…€Ò¼ÿn­×ÿýrº ëýÿÙösur$w]ì_¶“ã4‰ÌSùË´˜ôqüV$«i<ýϺi'IƒYvƒÚ͵Ymš¹6ï×ä©)0q×ëcy62Wof5z­rÌ3eÜ$̺Ûgñ›®*Aù#Œqš4ó©—f¾kuûþÙŸ)0ïÃÝó´º~ŸeBòyþ~ŸMÅÉ)¶íûôEÂYt¯Í §õž ÎSžH8‘ï­Aψݾ€Å嘤¹:È›„c¦ñÎÀ˜Óó §I9–¬70æ¬ì”æ-h^žf1ÌÒ÷ŸÏºŸgnrãuz´¹ªÛDm“ÛÂ_Õ# ëüŽAÖ¹Ä`ýŽf9ó¼óJòdƒ 32 ÐF1¬½©“ý^æiB …5ê0òy(—TퟩM@Bu=teí¢’Çõû çC–dàq$ׂóWHüªLTŠ&taZzÞsÈj(ôR ¸ãbêC€²œ—ÎÝTyžŸ5ÁéÚ˜ßdœ*øë÷~jÈyÖ4v+yŠ]žŸ(>Æ?ã¥4,eÈ—H~”.Õh©5Õ Pkʬµ,¯½äîZÓcB@‰Bµ¦'е0O­©Ò€ZS/e9Ô캴=Î×çéç$˜ƒ<}bKAÙï'hgM¡¸µ±Ë‚`S(l”4o ™²›P÷›Dä7kóꇅ’\µ¸su¥ø]bCÙZ¯–ëeÿ¤XKO#·Xá=§ýŽïQfß5{¥£´²1åv ËâL¡lš`iÛÅ~]2#ßSŠk,ÿßFòJô$iÒëí´—_埦½` Ì.ýÙ“|ü‹Qf¦—JÓTŸI0Qg0;í‹Jתü0o'•lëî˦ü2ùþ;¡8͋ƌóLÕ§¹Ÿ\Ð>afÊgå&WG€7Y³ü'Í÷òëgGñÕÔ£R L#6Ûº2æKaêþŒ¿©œbÓ®·R*G=3 ÌÆ`¶sq¾ÞDÊ¿žÌ»çy¶ð™¦?ÏZ=³·ÅÄçÙ›$ XŸg-ñòy6Ë(¾çÙÂgšþ<ë¥øòæZòæl·øLž´yšP‚Yó³$ ø’æÅŽMOš{)áäÅä»9𑼠€“ê6Âu¨£[£] ó0ßO&Ÿ"ŸµžÍ.8ýß§ùN³äÆEFÂ}§/&û–'óöíU@¥à|Z9ùгìKu o†kþÍçÙƒ{ýz1ôìAþ}ΰ7u‚ã;ÍD^ÄÖ$œõðêîÛë«HÑë±÷Ÿ÷ vwDY£KŠÌM×î\5§¹éDÊå ˆ½lÝát4ò —y&ž‡3öÈÐp<…cI"Kù$"Evß4Åù¦,ì›:`=e!ßtä§8'˜ù}S·Íï‚hë–vo;ÅyÛ,ä›zÜzªßhrëAδ¹õ ÛÈÚØWÄqŠôn_Ç*¾ö=RIq‘ ƒF*).Ra¡HeA¤¸‚…"•aD”â""†Tˆ8ÁH{´­‘ÊÈNqž0 {ܯž}ŠóìÞãž÷ûL÷¸‰8A;Õ$œ Ç=Ïî Ãý&€›"4‡”ê€uÖ®æÜäÄÅþð¿U=ïÈQ½åÇ›:~#+g1XÏ80*Ö“ýh€eðqzëï[~ø>Nwêå|Ù¸Îó®AسUDþ­ŠšÕ¡x½¢si‹h@¬¢„ý‰ìu‘kÿ±¸ŒMå‚—R8?{¶­¥‘?ÿê•—…¼•—ù÷·H©VTçèþþZOÝñ~αVÁ6%¼YÃñ;ÉfnÝ(3ì®Ã€|GÑœ: I ×a­ˆ9A œ‚ŽCußþ‚EŠƒ hå¼ ë7’ð\·ôîú$<×íÿ`ÿ8#>Πǯµ` ›ë=a87ìãDÁ*AÂaÁ*ÎÒ™ÌPà·'væ2ø-ÂÇY«1fíÛà&òUcÐp¢`5FBÂaÁj EÂY:sà üFàãÄÎÔ°¿yø8Á\wŽöH`¹n.4 Èýº¢À¹î8T»mÿ„8×Ë·m߄纽 ç‹„纽 wM“纽 u°ØýÙsÝîê]AŠ‚å® ˆëw‰@Îçj Ïu{AÎ÷j Ïu{AÞã Ìu{AáÚZ"P¸¸–èxsÝØ{œë¦¹«8×í…«“Y  ¹î‚¤¹n?É»yÀ\·ŸÄ‚eˆCç€øä±9 ª1g¢@䀨ŒPJ æ€ÒŒ´rVÙ Dˆs@Íaê5&„©wÔ˜ƒç€ª½ƒç€4TsÀ9 †Ïå '˜â4ëY:ëQ"Ä 9 Ãæ€>4ï÷™ž"âs@X³ Íq–Î:QÈ1hÈp 9 9õŽhZï(i@îzGÈ¡ê"„©wÔ˜¦ÞQcr@¨zGÈͪwD_CÐzÇ„®w4 p½cFrÖ;jLSï¨19 T½£@䀨ŒPN´¢`(':ÞïÁ2Däñw¢RÜ%{‘šUï˜ÍM«w”à®ÞQ r@ëÇõàzÇå”zÇq9¸Þq9¥Þq\¿ ®w\N©wjë—Sêíeˆ [b9©ÞÑ^X‰Ý8O½£½ ”ÿYNªw´Vb"G½£» ‘âPa%—4 ^½ãøÔë—“êLJ\ï¸ô×;ZëºvnÐͶÖu#ìÜ: m­ëFØ9+'T×°s>޳®açÖ!™[«AEعuHéÖj~vn»µT„[‡õn-æGÃëº×AÉ[›AUðºîuHõÖZ×°s6P¸®aç¼ —ã ÆÎ1°«8`;Ç vŽcúW¬¿ã˜þÇeçª}Û9¶sÓ¿â¹ì\½"¨c`;Ç1ý+^ÃÎå˜þ/ÈeçR‰±s nçªßlçÜÎÕ ¨c“ìÜØ.€í8nå9ÊŸƒÇ­õÆAíþµˆ½õ]’$’ÔÌù©F¤™Ãpi‹ÇOÙ4Ñ×  ¸> ŸÍa¼“U†›Ì´:ÈÞMb~¢ª@«5¨ú> V5°4>ÕÝ*“\?Ó¯,M~ˆ@˦üù³+®N)Îñva\¢^,éoõÁžÛ‰½©JÓ/õ“J¹'­^nˆÊҵߑiVü²ÖY+úhWTGõŠø^b/q{uã-”¶®úŽŒ­+…ýŽìåÏe?Nkê©6 \k¥‰Haç²y!qB(Q4 Èï¥&0/5 âqz©*¡-ƒî0ÑŠâ ƒO´¢•ßïV0¿;(Nèsð‰¶npð%ÈÁŸ NèŽ$4Ñû'J I¶PÂͰ% âq‡,Š„ÃB¬]p âq„F,4Š‚ƒxÜ!Íï³ †`³8£›ÈÁѰP/ âq†z"!á°`HI³oËPH©i8q0t¥Ù·U0tE[R[èêéŒbdÅ% ˆ…bdüµj ]}Q?(Fý hŠú%ÑŠÖÁ¨ý½YS.Ì (ò§,½'ô¤¨V´ &L4 (&L$ heO˜\Â$š0ˆÇ•0DÇ{L˜(Ð{0a‚< ®Æt'{Y&¾Ì 6¹àjLwgfæÆé.ÚØÙ33îPË…Å —ìsÚk2}þš9ÿä*#á„2@—¹ëYLÓZ¼Ì]Ï˽÷Ùœ¹Æx—b¢àHr=oÖG= ˆË"à2‘D fEõ½whDsÌŠ”DŸ¸7k,nU+’2áD ò&ÿù¬äKv§ã…óòš("¯4ÏÓü¼ã*Õ4 Ø’ižV Ho.Cƒx,¾I3y¢î44 ÎAÌO­i@QÈÎqÈ÷ÊÐv.}¯,hç\ó~.s9‹IuÉeî¾M²shçÖÎå@;ÇfØ9N Ú¹œä¶sÆü€ìÃØ9cPAvŽÍ°s<™šjçò§V4  Ë§[î8 Àá÷ç4 'ìÏÍ\ÏdN“pÂþr=pNÓ€ÂþÑŠÂþÑŠBþ\’Bþ\°sqH€ÃïωY €?—Ñ€Âþä7šãÏINÐÎÍ]Ï4;Wø’„öçëûs’öçˆVöçˆV´ ¸Y ÈüÀý¹ÖqÌR¢­ ûsóVðçP°FkbµL4©FË[Ѥh@á­„Ä‚…FD+Zë4 (VË AÐìY€øgS«K¢)U9ÞªYœéþ‚†,ð× 'Xà¯ÑV௸¢ ü“„,ð—D eð}@þâÆ5 (XàŸI ¾W­(Xà·  5õ½:šôÔï}FFn¸À»uЉ=uÐÿLO|:Œ¦=#û’tÉtÒ¤Ç]G0®rA ¸Žê2—358wßBAr“£SÈõL’›¬£$ùƒäéoѼÇÝé¯+þqöæáwa¯ÈÑÌÇ]1õq7šý¸›iP(¨8ä{‘ L 'hçæ®gj2pîz&Ù¹hçÖÎq Ã$ó“XÈ r"P°ˆdçØŒ"c3ìOf¦'3E Ú¹|ºåžõ¸›hNØŸ›¹žÉþœ&á„ý9$îÏIPÐÎq¢í\N´¢?—ìòqöŠÍ|ÜSw£Ù»YF ûs­›ãÏINØŸ›¹žÉþœ$á„ý9$îÏiPØŸ#ZQØŸ#ZQ°ˆdçføsYJ´¢°?7oE.¡E}UÙ}ýpXØŸã-ù:Þ.§2a;Y&®ûЪ¬51÷­†dM;\¾nÍÅ0ÍØðŸfëÓgÞ„إbGA[8ÖV+û]ïŧõÜõ U¦½¨‹îOÇn'ÉŽn'‡‚Ûî”tkK2IJ[ŽhýTR’î¤éM,_´«SRÞ¿óMŸÄ]éËeÍ¥:øêÅî§™ÇÄ¥ Úž“z/ës²;Ê™çÄ¡ ú;øêüöT»œtu½“RðÚsù,nèÛýy>I€´ê\ÜX­6³1–åff*’·êKxmó-“\’næºÒ@ýü¬»â=7¿Ýã(“,»§¤«ÛÔ¸ ®p°/—dé÷7-îÝnžëÍ$ûF7õ·#;*vúáÅZ|w “ù6Öh¶mæE •“âüy¶K³ÐE¾ý2ú¿°oâñÒT¤ó!ã•$—¿Óï|>¤6Â[›'rÌŸÏ$õ SqÖ¸ÈM‚'nÄh±ØüŽr>‰ }ŸY ý•ìµÊ–L€ÔrÛJ÷ùph!ý}Ý©ïË5¬À;²i‚üv˜xÉh‚ïóq—l×»Yɧu%üªR‚íªÕ¿^jA“6/rÇÇåAAY¼|)­wTüô‡ì1ãKy³ÜÍ«Ý†Ž‚?Åo¡vÌþ¸JA@«Фû]®‡Ëƒb-˱OÞÖÍNóÉm{jgäùw”û€ù)çóñA@aÓ܆Å»?¾q'ÙîoomÁË1/)¨“lw³›«¥Û>“Ëá"¹  ôÌ~i¿ÊÂY*œÁÛW&HvlýBy‰PiI!Ù±Fþñß«…©wì¢2Ê»Iþ¶©ÐêÛ7‰Ã¯Ûñ'§ø*éÿ°^•ÅOóCòó/L¦º:˦>e5æ¡n_${¶'ªË¯¿Ù´óÏ=?P`Œ]þ°ÞÊò~Ã91#̲{FcÔm— Ü˜ÆŒãØbÃÂÎ\‹#U8c„Yõ§~ìËéêÇ©0òKq"Låû7fõÛ”/<õ8è›ÒßZ¤4–f±©1Õj* ¯6­Ææ}h_|¦¹ŽÿÛÂå3õ)sòa-~ëÍðÎgºe?Çë¥8j=3ÞùL·ìz¿=4¥Ñcµú²ùå+E™M[ ~I±þ.ù×7î“qJíY™Ûé‡?O?‹ÎžèÚ ùáñE@YŽ^^ë¹YµÇœikÅ0³çJnöö¹¿–7£²Ään›…5uêÛm[yß®(“‡ƒ Z뛚×Ñ߇Ã!ÿºØ´ìûO¯C~ Nr²> b@ñè±; ·“²«}LÙCçûáÍ&ó‰à4GáoszëqÐØsˆZÿÛv-F-Gì.çň¾Ž•>.W}Èiö­µ¶L•.Û4Ñ9XÙËXÒ¦ÙÌšvšÎ •±¤M÷œµ½Á·ÓsË“y¿Ï¨íðÓÊÉoTœ—€zhá®ù7Ÿw®G¢Öÿlç:ÿ>gXKêµÞÚìÁU¤hŽKDôŸåâJz½ìªÔ¦Z¦8ÔÏÃû Y›²l‹Óf0;À&ÄÓŠ0^³7ƒæ[Þ:,ƒ‘Ëáz`(`çâpáÅp0rÍ)†l\.¹¨M›QÜØ}›:¢6mFqc‚½ÈÑãšrÈ/¡]Óü.$ (èšR­ˆÙAEì À>pMß±xõ5èÕÇS¦ï8Ç<¡½‡"®ˆ>Ø?vǾ: PÇ>ž ó1pìkбƒÓwFWÅ^qpúÎ(ð2XàO˜¾ã TRA *DœUÈážÇé£8"Ž»@¯8¨bëPàÀ+Oßq*yB *\‘p‚q޾„º2ŽÈ˜ Mr„ÆÆ#…ÆqxúÎèS5 Xl‡te,g®¾¿Áqš¾c9tÆQ€EÇqpúŽ/ý‡·>oü_z“ (˜ÄÛ…7X ä¸YëÃLÆ!¥ËÕj@°`±­hãZ‘ƤXxîhE“^`ð`¼: ð`œAƒñšÆ4¯8ð`œAƒqÃãs^ iÖ~5¤YÏ*øÊ6k=£`ÜýÊFÉœÁž@ã Œ4ŸójHà ¿Òp¯ÔhK Æs!i@îwjÆ87 h0΂Áøø,hLŒÌ‚ÁøøpkLÔÏfãxkú,ÆIh@ájA —ãd4 çͪ1Á8ã Æ87>4gà`¼ƒqd…„‡È Œ·µ)ê7¸ö“@S‹±œ&ˆ1¬‘×b,§ÔbŒk>ÀµË)µãÒp-ÆrJ-Æø÷×b,'ÕbŒ‹KÀµËp÷¨*qÖa=k•âd¯ÂzÖêĉ[„õ¬Õ?ˆ·ëY«'n’8³Vÿ NÜ:$qf; <Áœ®7«8à“Í 'ŽcêÍÖ‰3ˉã˜z³u@âÌvâª}Ÿ8?q5zâØ$7þ…À'a9ÅÆ ãVÄɆߪõÆAOüV­¿Tè‰ߪjóQÃÝn_˜æ÷Y}áYœÑMäàh˜ÏeJœ>·HH8,èÛÓìÛ2äÛkNŒ!hömŒ!ЖÔCx@:£E`EqIb¡`­Ú¦ÊûÂ/"P ¿Ð*~¡O÷›5UâÉLЀ¢À<$Xœ¤ú^ã<ª-ƒ‘«¦ÅÁÈUÒ€VÁȹ"—$“„µu®‚Cwˆ,gƇ.úCrtÿ9­Ý3ɧ“–á)® ø'W 'Š_æ®g1­™ñ2w=~KÇ»ðL%Ž3qòo'\jM ž8Ù9†>q¹$œà‰›»ži'.¿Ì]ÏÔÇxâò§V4 °›þ !fG÷lœ&á„mÜÌõL¶qš„¶qÇÛ¸Œ¶q›cã$ 'lãf®g²“$œ°S8ÜÆ%4 `iÄÄôv4éQÅû֑Ѐ‚¥_'£i*¾—"Ð2˜°×4 8˜ÞF‚ ¥ØŸV‘MMGSÒèÞ4í,ÎôÒAà –Fè„„,Ðèƒ +P\Ñ€‚¥IBbÁ”ú'•Fˆ×4 `iD&i@ÁÒ쩃–FHìŠy·ß¨òé†aV6&ÉH8¿Q]æ®gj¤2w=ÓüF15ÍÎÆdšŠT‡ìÜŒH%$œà‰›»ž©‘ÊÜõL=q<ÁqÀ‘J¦h@Á—Oÿ†fecM ۸™ë™lã4 'l㎷q (lã ;7ÇÆINØÆÍ\Ïd'I8a§p¸Kh@/­QݼÚzNýáòuÈÇ8çÔ¤>»iåŹ«i—ÓW’ÙçÕ§f^ý.; ÚÂ"Tò:$ýñÜõ |¦5¿›eî{AKŠØ\ÒØËÚúó†ɎÔîýµ›/Ö¦¤$ÝÉ84ãÚ6I{:Í6R»lA“ú¸=ÕŽ J\4üåZ\ñËíŽræ/g²ý×6þúñ<ÜO3?û´mÓÏ7´'·¬TW¢ÄÅÍÁüì†H׸r33Å…¤Ä­ºï`8ûvžOÐæ9WéÏþ|~þmF Ÿ›£ò8Ê$Ëî€æÈ ¸MûL0®pI–~ÓâÞíæ¹>*d¨ùÜz2ÉŽŠ½}xæNa2­ƒØÆ›yÑ…OŠó_äÙ.ÍB¹o<ð«ËåòÒT¤ó!ã•$—¿Óï|>„õõ!_ïÏcþ|&yð¨O€,_†\!7}ž¸ øeÆõ‹—S@Î'´€ «¤¿’½ÁTÙHÝk³­ZÜGcá¿/WA±]›&Üz m óq—üðïf%ŸÖ•ðk¸ŽzÊÇøgô¦š´ê]—eñò¥ g¨ã¿”7Ë]ПÔޜ⒂?ÅöWè^ ÜÿñW)(ã¾>‘t¿ËõpyPìØrì“·ÝÓ|råÍ>zèùw”û€ù)çóñA@ÙüÎñ>æ÷ÇwŽ:cv»1úý8ð™\q欧PzVè÷ÒÛW&HÖ²~ûíŽ_e¹c¨oßêT7¢ÐÝ·_ïØEÿd$kÙ¼ìXK)v¬plË#Y‹±üÖ;¬àüüúé¯~˜ Sÿ05æ¡n_$[¶¨¿þϦ ±dåÜš"püºr Œ1ËÖëRÞo8ïb„a]¦uŒQ·]‚ò/F˜¥Ù´nÓ [ÖlÚùçž(0•øùøÛĆå]v©¾ÍëM~)®‚±á$̪Æl!h…I¾RE„©|¿âƬŽ@™k¯wí oJî%Í×¹ØÔ˜jÓ* ¯VScT.ˆ0ïÃ;àÅgšëø¿-\>SŸ2×)Ï´Þ ï|¦[ös¼~QPš†ÀÖ3ãÏtË®÷ÛCP^„à‡;–_¾RŽù]lÅ9• ¼•òõóþ]s–@ævúáÏÓÅÒ2'ºB£C~x|P–¡aòã7£j$ùäщ!ÙêF`süŠâ‡¼Ï]ÏbâŒ÷¹ëY8ÄôúëÉßDZdþ4Ž#óÿaUd/Aãzd(êrãËω¥¦bý$çPú½ p eßø:Ÿ.FÀ‘ žî÷ÉÇžkèñóñ¯þXù©yàåe)ê÷·H©V´r‰²7ò±3A£DôÖ6?¡ÔŠœyêÂòü­0ä7bx;²? oçæ®gª›»ž©vtØ ;2¨l’³›c“ìœÝ ‚>V´snóCµ¢8dP±‡Îõ†é4?3ƒ½´ÄfPgnÝH¾ºô濺V…Æþ胞²"á@«ö£åˆžýItv™É|®¯-+æ+JT²8ŽË.XT*ñì$ (2‡»þ…ʯ¨ê03_‘HS¥h@Æ.ôÛ¤z3~”>ÌÛºÑávž¹ rÂ1„ûlkN<Û39‹IßPû†Â1„û’8ð¢V”À¬Â„Âmˆ@ËUŠÍÑo´ò›Ÿf~Â1„ÇÎIPðnͦمhšóØ…™œÉŸ«Àqñ¶Úºjâ­-蟲—XêûUÕQr“ Ç1ï¶âTón±çuŒ»­9å¸["ŽcÚm}Êi·D¿cØ­áˆMÄqÌõ®ÏA9×;—s8¡†ÃIn\hŽcª·1=·<™·o£>þO+'¿Qq3½áù>gX g—uµMa«GzÏû~F²®[›=(Gc×ã’:ügùª!ÎT çle.s]N<Æîœ£åÝã(€¾U®éæRÃ=*4msá‘°pÕ ÃõáwA´¢¥Ýõ©Vw}XÈQðøXT‡aò±@–Žù§x}¬4£mì z<Ø™cÁi¶Á|÷”…¦ŒÝÆêØÁÝFu ê62¨ÛXqàn#ƒº5ì6² Ûètç°'Áá6:ÝS¢õ¬œ}âá62¨Ûh8P·‘áÝÆyû6Ým$âÝÆyö`ºÛHÄ †)økÕ!›åˆSr¼Gb«üã(@”Ím‚FD,XÿgrŠ!˜€åp›û±Ð4O2oµß Ù˜ü&PJ“¤ÿŸ¸7irfÚÿÊwì‰iÏWµUßê6‡ªˆòµ/ÔÂ!Žý€(Q$6’^;ì¨pȇ@"‘2K7„“ßg¾`øcãáÌ0Ù!è»H®pAhªG&0wPZ®s ©Šµ)mqW„”&rÝ<Ÿj"Ý”Æø\þ–v¶­‡š¬Z%¥õô¶õP“U;ƒŽ²m=Ö¤éM¡cj[5y‡3è(ÛÖCM–° ë¶õP“&<‡2¿qÇíæäqÏà¸9CæX˜Ìq;s tœ˜5ƒãvsò¸ui‡6t¬óu‰”s)ó¸uùs)ó¸uùs)ó¸©&{!e7ÑäqÏ!´Ue Ïs;‹ŒRf˜(çvsò¸4GÎMÏãnéL–sÁT9—hà§ÐÑ˹D›Ñ?ƒŽJεë6YÎMÏãN´ïUæRÉ9þESå\0YÎ%Ú÷*s)ä\­}¯2‡JÎxŽœ ¦Ë¹v&˹`ºœã„¦Ê9ÛʇC¹0YÎM¶ ’z–>7Ý‚à 7UÎM· ¸Üž*çÖ6rN.~&ɹµYÎ)¥Â$ñ³6Ë9¥äž»C¶ïUuîÙ¾WyˆWK·1 Ô¹‡U#çÆ\7YÎM·[“z–>·ž,ç¸r?YÎm¦{Jð9·™î)™¥Ïm¦{Jfés›ùvëÜï™l·N¨›ïòðº™ñ.o–>·™ñ.Ì‘s›ïòè9·™,ç„÷gªœÛÌðÏá9rn3Ãn%ÓåÜ~ŽÝJ¦Ë¹ý»•N—sû9v+.çösìV2]üìgÙ­tº@ÝÏx,M?û9ïùÒM¨ûYv+žn·îgÙ­pºÝºŸe·’érn?Ën%ÓåÜ~–ÝJçȹÍt»•ΑsÓõ9¾pSåÜt}ŽËí©rn3Ýn¥säœ>'¨sn²œ›$~6 äÜÜ-²¶[át}n?CŸ{ Ô¹‡ÕÚn¥säÜf†ÝJçȹͬ>±Iz§gm¾HZÿÀªOl—œNòÚ!EŸXAˆ&)Bn)úÄŠ4Ç!„ÝRô‰yŽQ “Ò !MŸØ$Ô’œGȶOl‚CÚô;»Ev}b»„dJs7t4}b›6\žé:¦>±]bíÒu3õ‰íkˤ„Nè(û͉La álƶêûHxE vCh3kqU↢Ol—ãXÂù[dÕ'¶ËÚÄY∢O¬ TãŠ:"¤è+–®(Ër&×Y÷‰mٛњ»GòŒ@í->…¿M¯ëu„qCèÕ4M]SJíÔ‚ÜZ G„6FÈÑÒmõ ™¦ý£9½¦åè‹öM OÒ´€ñÑœF¥£Žì‡Q§›II¦Ó©éÀiº£±Ö‚Fw$Nè&:så‚âÑœBG-§é¨æZ j]ØÍþlºð":£›HA‡Nӹ͵”:7DNèFÝÞͺ­Mº=uCgc´!ܬÛÖdCÐÙ"[fCèŒê†0+$Án&ceþµ:~4§7¿ÚÍ/ä†ÐÖh~Íæî?RW‰Š.¡B@oçÁiv˜ÔàÕÎsõEk£åJÝÚ-Wì†ÐÖh¹Îü"U]%¡¹BUõhNm"ãE„ÆæT”f$é£9´«$M‚””ÖæVšªWÜUBJ'tL¦xºô{VV•û˜%^:¡FÝ•ÚãÚpSìŒðÌï‘w¾“b:fŠ"Žu_Ä%Ý©{Â-<›ãþH" ¡vé0F‰#Bì¾ÿ¶=£Âèœ&IÌÅu]Ôq˜Â¡œ.ê¢%D'xeÖ¦Fx’Û¨+*ƒ«/"4 Êê5¥nå\2å¼³å\=éóåÜÒﱓsuºô{Lr®• ÉDñÌs­T¨' Ô`œK2ʹÚ!µœâ§pDH-ç„@$ç‚r.YFÈVÎÕ%n™õ9{Émj-¦×ç¨:f}ná÷XësÔ `T³f~Ï49×(ŽÔ !³>çè‹Ìúœ£/2ésh‚œ3¶Óéså9gl-¦×ç–}Ñ}®tCȬÏMa†%úvBǬÏ-ük};¡cÖçf~Ït}»!dÖç}‘YŸsôEkƒš…&‰ŸéúÜCq,'‰ŸEúYDh‚>‡Ü2¦¼Z¦-«dm rCȘòj™uì’etŽ­‰Ô ¡1ma&¡©)¯s·hZÊkiæ6éÚðû":ö)¯Ð cÊ+ENèS^élÆžRãµ î"7„Ìájâ†P` …ÎÞ¢I)¯0K¨BÆ”×»!dLyËuSS^ñÜ/RÄóÔÖ ©íâ(*Ð1X+$]ú=¶^™¥ßce#3¿gr” ;"¤·VìÂ`Y”ÍÞÍ æGÙ¦¿Àü(Û´pXeƒ¶Q6°8ÊVR7„L^’L9¯ ¼2:¡c”sK¿ÇÖ+³ô{¬ä\=QÎså\2QÎÍñÊtâ§vD(0 ÔÄ!c6Á$9,È&(}‘QÎ%˾ÈÞ+S7„Œr®¶—Ü‹¢lˆ:¡cÖç~µ>GÐ1ës3éL×ç°BF9—8ú"£œ«}‘Ñû‡Ð1ës ¿ÇZŸÃNè˜õ¹™t¦ësÔ !³>çè‹Ìúœ£/2fL? ô¹r’øY¤Ï‘E„&èsÈ ¡—ZÇGÁ©s†ç씲 lžËhý jIÑãÔÒè^—Ô„ ¿ÿ‹È¹O% º 6¨@ÅW2:?Wò„Bw+¹Rì/qtÉÙA®Â3­&m2S{Ô¢úyîÛ“*ñ„2^fjëµþ·Œ~›xÔ„[.iîß®}dsBÓt 5U¡²ÁãwÊ£…§(WöoÀ'üÄe 'T³  Áƒ;á/<ÒÒeœS½_Vì†Îò*Žð„ªoä6ýÚoí×uâ«ùº² Ò¸$·íWJË¬Ä vÊ*mÏãûï/ß;v‡ÆÝÞÝΕeîvïöœÜ÷ߎS°SA•Åõê–ܧ\`òÅtƙÛî[ºwÎXexóú”ïK)$ËŽ9™VÒª²C­¾Ü…„=ÕS\äeX”¦‹üç¿1ø_fÝD£-,– JŸD’kq­— úÍO_ïÏs]U¨6²º‘®ÃªD%`DâE¯‘M¿iùèK2z2ò™‘íèKúDŽ•z "¼6ÎO[’òtz9Ñë%$×ô]|ɾ3òV£Ñßñ9,|ɧø’_é—$â‚»Dù~®zøErx¾¥7ì€Êêå¤<Ô¶õ§ò¶à¤ü‘܃EççQi¨Ì?*òìž祿ù§ vñ-ã:\=÷årJoÄ•õX'$0Úéä2*r×ÎHóRÉsT€žJŸo¨CN~˜ŒÇòÛu'Ëõí™ñr®*³8Y®fwR¿oIW(=¥ðTcTzbŸ‘yœJ¦½0e0;”ÐhÓÚPÙ½Py±PNECÅÉŠíû]ÈŸßÂW,¥÷Ò •Oá8ü÷p…¶g_8Ùù^»8•BôK¯J¶5w'Û¿žê–—[2œË8™ÉNÖl5vT7§¿[´øž×'d„\þ–ÞÊ8Ïæ)1#2½êˆc2$ Ñ,5fDFT ÿ؆LÎ\˜‰QâDš­¶ý‚äŒLsevdð$ŽÈ´º»1Û½i"<œN4#ôÚ¤[º!³çdÚ¯iÉ$í¢q2¤†ŽÈ|¥ó‹Î´T'ÿ³RéL}*K•òaRôC›Iž:SVÞÏ—v@¥+àõÐÌ’§Î”•—<»¹X±®B¡T—­ÓC1KlÊ’®*Ò}©×yGFYåJbÈdÑ=©¢»*’Wð™@~ªO·ƒ*ゲ¼¥Gã_ÎaI¥&ª'{`~Çô%‰5)&¹¬òÝB]5¨ŸŸGšúã‹J|:AW_ôEÍkw—ÓéTR³Í!´îëO¯}•2]p¡Í(€ød†,"ògz6„ä¦2~˜aä„NÇ _+ô¾žà‰ÎÝ!E™×¿?ÏG%:0Lgo¢Ìë׸sÈé”^è©v³n]™WIãæý×:⃭<…óA‰+©ÛÉžŽ)EÐAY ±:#~{=Y–íÏèýׯ”N¹¢óbP%Ü¥¾&ËÎϨÌë__×׸tDg;:§ÏuƒðR̦£zÁô#<èŽÐëe×¾ì²ej «S³÷snU2ã–õݞ˓ûnOú¢}·'}Ђ¾Û“8nAßíI·™~«Ò9·¤òÜ šP®NïXÞ9p×¹ £È; î: BŠÈ»È™©è€¸ë€,¼ŒŠÈÛÈL*`yäÀaä‡XÕÉ7pÖ¹ È; N; 7/3åg;÷ùÒu3•ƒëÜÚòÈÃÈ­XÑ9p×ùG‘v@Üu@~†¤w»È¼rà®ò£ª´3Vல ¤è€¸ë€,–NÑ9pÙ¹eoEäÀqdq‹Oáïy9!DÜzuMS¦w@~ª ¹!´6*@ŽmŒ £¥Û G„vzBdš¦5½òCÓ“4­é{*ut`?Œ:ÝLJö:pšî8£òCw$Nè&:så‚]äNG-§é¨“; ÷ta7û³5ê‹èØt@nèÐi:÷äÈO"'t£nïfÝÖ&Ýžº¡³1ÚnÖmk´!fKRËÈ!Zº! Æ I°BÉX™[u@î™_ŽmŒærChk4¿fs·Uä!\B7„€¡Ï4;ozä§çê‹ÖFË•º!´1Z®Ø ¡­ÑrùE–Ÿ„æÊ:ëÈ/"dÑYPš}l; wÒNÞ9pÖùAGÚ9pÖùaЧK¿ge÷Ð"]ú=v½Þå½hw½h;Bò^´»^´OŽK¦¬\0›ã¤½hg½hŸ·ô{ì8NÞ‹6˜Û‹VÃq šGg"ÇÉ»‚ödœýšQ¯¸'ã¨:À({ÒYYEAQºtݬeœGgºŒ+Ý2˸);´DÆa'tÌ2ná÷XË8섎YÆ‘yt¦Ë8ä†15ÂÒë<·S^/ÖÜ2¦FXF'çvÊë9ìZöÔ ¡Ñ½=“ÐÔÔˆ¹[4-5¢´u/è”'Ü´‹èاF@7tŒ©9¡cL ³{ZjIˆBÆÔ„Ü Œ.³Ù[4)5f uCȘQb7„Œ©s¹njjžûE¶òú©íÃ"o *Ð1è$]ú=¶Þ˜¥ßc§7B[o Xì)©B&K…$SVn¥‚ :FŽ[ú=¶–ÊÒï±å¸Í£3ÙR)‰BÀ({ìYÛÊ£”¥Ø ³Œ[HÇZÆQ'tÌ2Σ3]Æ•n™eÜ”•["ã°:f·ð{¬evBÇ,ãÈ<:ÓerCÈØQeBé˜åUBRSbçÆ«ª£Jà¦£Š¤ÇÉ„:cöU”=NÜ웪Qư[ŒSjÆŽ*NWrcª«,«Þ,í¨¢nq2áMÝ„Ž*ª®5Æ.ɦ~1µSrkS—e|©ì¨¢jà2áÝ¥}Ge——äŒU§äŒUÜ’3vTqÂ*ÖUÜìü º¬Å‰ ‘ùgü0XÕÀe™³ì¨".rEG•ÀMG•N[wT ÜtTDU×UŒ¬>¡£Š²Ù‰‘ã&tTQ¶m1 \UŒf¤‹Ž*.–KÑQE˜AŠŽ*ëŽ*‰"ªŽ*âSUçUfž”‰Ufr±UG•nóåUGUEG•ÀAG•~—Cy’ÀAG•G8ÝNó_ÐQåIEÖ·%XÖQEÒëd–SuTQö:1ÞûS:ª(»ÃÌ:•úŽ*’^'³N¥¢£Šº×‰*{Sw'+öijuâd÷U”­Nœ°òj¥êÓv°Vô‡ fvTÑ´:qó5©ÕÉ,ýBÑQEÒ¦]4E˜`nGu«“Y:†´£Š¶‰“c³Ú™úøùš½©q‹›¯1vTY¤ÉZwTY¤”:ªˆ8ˆ¢£Jà¨£Š ¢è¨8ï¨2K:Oî¨2‹—-;ªˆÌEG•ÀQGAEÑQ%˜ÓQ¥ñ• RÛºæô$Kå^O¨]3¨möýšz(êp#Z¦ é |?Í™9<éˆæwBe ÖvåW¤Á"å•S>ÈXï[³AÔ `Ü …tVVŒPNcc½o# iŒ`®÷­á8ì†0rœÝ;ŽÓìÐB:vGÙ.°Ý¡¯!žOP¨eÜnÜa{’Œ{ý µŒ›FgËmP³p5"(„óè(¢ßÒjªS„Ø ! 4j¾CI$^]$L•®áÅ8ò>Pðä¹ñÒɯ‡I„ìy®œÂ V׃‚·©:ÀÈÛ é¬¬ÎP9í ¯ÍÂóèL^yn啚ÜMúuÎSþàøÈÃ’œ88CƒT)R0Ól äl[O½ihtDîɽp@ˆŠêqÕôR‚ð„–éÚH¤#BOâåDÖ¢QCDô:hˆˆDH¨ƒ/Ù"ÿD ¯¦ß9Ù¾ì ïÛ‘>;ÍÞ‰÷øGP9=ÄÝ­¼fe<ÆÍ ¿2Z&fWÆío3¨(t±•¶š ’^o׳*½³2¼šÞ0^*Á •Çîw][ ¾@TD_!0TDš{ ÏÄ•MÇ^ÏdÊî›ÛRß²}ö¸ê¨4’²ër‚ÈÑ«í[*_pv‡ÐÅŠíEWßv÷“¶Yû¶ûéíPÓ„T>E‹“ß¿¢)§Â›‚ÔÌC.8¹íÙó”ûm[!÷A¶Tî¿Ä ~•ÓƒŠd!FÈqøÿý“}K}(³1Ò(Á?–¯¬ÌLyCWDPú¼ñR¡ŽóƱ*o8ÎǪ¼qà2ojÔÁ;òÆ]-ÝÆ˜ŒJæ’ÞÑ:28ˇڜW07o\“ŸîˆÎÚ˜ïf6Ƽ~7t¶Æ|{º„ŽM†ˆUC't€!¯_šžææÛ«óú]ÑYß)”NèlŒïÜÐÙ3Ægò"®&‘BÀ˜š¾ŒUà*SÓÁÜÔt/¸£ÔA¨L³Sà©ì{\Òê„:¨ ܦÚc§„L_$ƒÙ©öê/rFhm|<ÝÚãáÈ ¡­XnmŒ¹fÈ !£œ[¸törÎ!£œKìÙÛœ`¤ÓçÜÐ1ës éXësnè˜õ98΄äõ“"0óI‘^qtôEf}ÎÑ­é8ŽmŒ¯±-YŸ[öEô9G„€QÏš²t“õ¹žÞ膎YŸ[HÇZŸsCǬϡyt¦ësŽ™õ9è†YŸsDhm|˜çˆÐƘSëhÌúܲ/š Ï9"ôO ­y`y º!Œa/G„Ó›FËøXÈ›š‹y„Ì#4õñ$BNèã#M7ßiÒ%t¬iÚpÀüP“8`^(¨} Ü>…ÊÇ `öcP]ˆÍ¡Àøêt6kÿ™V¬ 9"d¬ÖæŠP`zÞ gJŸéÏ[—²²AËhXesEÇd­,¦ci­¸¢ôz#² C€…ñw„L~@XLY¹ùñWtŒ·”Ž-Ç9¢cä¸ ªÂϳ;BÀ({ìY{†ç¹'KÝÐ1˸…t¬eœ:f‡æÑ™.ã2Ë88Ð熎YÆ-¤c-ãÜÐ1˸™t¦Ë8G„€þY+”>kKžµêÑB‡Ô€üÅÔ>¢ïzD kìšñ-qI-0>&©­„¡Cjõa¬| Þø@˜º$g~ ]’3<&ÒÂ`ÙaÍbâ¬tIn£_L(} <ŸÜÖøÚ»$·3½¶.ræÞø¸ÛéÞ}w»8ÛNEΫŒ®qå[rìà:ø#k¹£xºN\’3\äò§ë`ñÓõ>‘ÕØ µïãÁ̧ëª÷ñø„–YáÃåD6¦Gø/'²5¾ô'ˉì ðÍ.` "{S9D>5 ,Wû W_´À{­V†ªsOÊÉ] «PúÚDZa2•ÀX8 ²Öëäò `y†>•2¿•¹*@^çjë<€eÆuð9 bªÀ€ÏÄ•±š„‹oÙ+c@TvÆš.¾eoX17ßòiª&A]ì~'úÕ¥1ˆ‹Y­Œu>\ìÌ Kp8!ë‰8!³6-t²7SEì„Ó¶ÆÂ%Ø™±r‰“Eۛȸá´OS”E:ùŸÕ«Î¤.ÃBP¦2,ÐÅ·Æb/Еµ©ØË¬“%çèKÊ`T€©¤ ¡¨ÆÂ5Еµ6µMúN|=©-€>d„5O§Ñ1ÇÚTïÑ×¶%ô'äJž®­z×O]¸q>Á4:¶ 7÷{&/Ü8þ¾™”hÍqhkŽ›ù=Ó9JSÝÝsÜB:Ö7“ÎÄöA%}Íîsú¡4§,Ìé×d»¾z¸ÁûÓÝÐ1tõ&>ƒ÷%Œ—Nè;ÆÀ™Œ09¥öÕ°ÎSj¡"¥,K©UK…ÅtVVRn˜ –¦ ª®˜òAÁü…[JÇvá :Îä…KìwhFï¨H<Ëu‡æÑ™Îqp¡%·Ž5Çͤ3±‹$€åéfŠ.”$€7 `ê”,è0¦›‡Ô}Iìa’p“$¥I#Â.Éc^tI.0f-Q—äŒ]ÊÒ%¹1óÅÅbÚwQÀα‹B'R†©(ÀQ*Ê#KJ²DÀìT}–\N$0f$åDÖÆ,D6Æ˵5æ#Ì#2©‹A˜8 ôw†1|à*†ÿˆ®CItÌáë£ëЕÀ]G¨¬±bT6ÆX± *Æ. Ä•1è邊±‹Æ¨»(@œlH$[wQX$“­»(À93¹‹¨ˆo¡¿¿âªdl&”³[JQZ÷C^=uèIåë=ÿ Kÿ¯änûŸÿ…;8@M¤ä? G¬³ƒ;8ÜÁIèí–ø„#ìú8Dq{ƒ2Æ«Ê*BUMð{áp4¯!ù/Á; œVmprtî»ÄßGm?÷Çê4eì:8ʼnÝÌ>áz8xy3œ@b@÷Y§áäŽuŠúŽ=¢ãcŽzÇ<©èÍç*p²úœ§iâÏëëö†yîÖùJÏEøþÝjÚ†wÂß=¢éŽù÷Cê$=4½T>צ'’¹òÌ׆)i9Îo?W@ y=å}™Ó[›š µG4úªI–d>Й§¹5sžòø\žèåì ÐóÍ»ÏqqßaŸòøB겸x­º£Rû÷C˜x¹žx:=ðþWz?”YVxÅ3~ÐÕ[ŸËáRžó÷rb¿hOm®©C{Å£×Ûk˜©W<|¿¾¿:++yâI%tlGü‘0pZ¿øÈ¿iuK``xò[q=–^ñ<¬Ð‰ÙwÀY‰W<Î =à:óŒg­“?‡¢¬ªÂ+Òùþýû?×'-iÂD"ôŠg+ðtòg€‡F{ÅÓ=îdç=<žN H® Ó[zÌ£ ù=_âhk©ŸŽ§n}N”–0»ÔgTQ¯xÄáö| Ÿëó¼SawÇçGˆüî×ãNín Á@íq«ó º`¿€†wêó„5€.Ï€wêCëx®Ó:r|óËBüN}Ñ:Z½Lʉ­£hÍýý–jæEîÐF¯uä(<¿4^*u¼0¥£¾BŸp€áŽwë6 ä:ë%GTÕ>tV0zøÉoÔãé)‹ãÑKuÊ£ÌëfmÆF³:Ý…q…ôàÎVn‚‰Íòa‚QŽ×Ëñ4Ò^Š[#âÎ^¢¢žvH¯¥O8Ÿ’‹âyså$vêð5‹Á™Cöâè½Gë‘"4pˆÿHÓjÈårD^ñ€ñ=!.öÏ9$~ñtŒ¯ŸÇ~¥Ï³½ ¿ûÕå@þJñ0Û«ö»>CãÝzÏÏV«ñ©>½ù¼ÿ1ê=½ó•dzÅ£u¶P’%¤ôŠGâ{œ „Uxò ŸWò"!ƒxeBšŸ}Âz­¹áÕ'œ@wØ®ó$Œp¸šÚjÍC5•i>管O8çûo§UÄ_ŠØJ¢¦¶9ÆBMm²²=ª©+‰š*à´N1ÇGœàŽAM¥Ä‹šº²TSc{å¾KLìV"²~Réê¥ä&o#©ß¾>ŠDL•ž‘Õ™_@@â3ä€Z3–÷9Î m¿GãѸ…gŸpÚÕ¹ý|?»È©++ZžËÈ© Á'xz4WÅÓÁ’Q}ÂY+¥O ÃôDc§#^Cñë¡ÆIòØ,R’¾Õ>áˆfBö ²ŠKR'~Wg÷LV ™É3!oIÓÀÙ+Ãí ïÀ·d9÷áÉ£jvÐÿIz•eäx¾">ö\—íAÏÂ3%oȺÖÀ $¾ÂÎu¦ŒÈÁ'œõø ‹“ÕlyK¶ªŽ;´{CÔhðNq:ÇWèÎVòˆê‘^â¤~CæµÎN—$_&¾º;ïV~ÀaúNé4Ópõ?Õ~§þ#È/!Ù·ê’]Æ-à€'œ.Šœˆ AyçÈ'œ@Àù÷W 'Žz½-à¬álGðŽ÷ÍÚ8ÿþJá\“x-àlŸn+ŸHòÖÍ’>/æpd¼s~iäþ~8àÉÊÃŒÐfušÒz>áHNV—lÔ¬&ù„Ó¬Ÿ_YæÊ-=Þ¼®Nw²¨4‘æv8B¯¼³%½tß'k7–;ˆë;-߬¼¤Ð nt§oO,à|ŽÒ rç–Óãùv ï…3Îڙ蒬ÂcR½û “vE…FI…n“@-àƒœŒÁAÏ_J{¿Îz,wéi .¡W8ùÉp¹$Ÿp¶£ô¢v³„÷‹Yŧ7Ëq™\~°†a› *ß}°ÆŽÊq¦e—\ä4ÓÒŒF‘f)иM³4£‘ªÞ!ÇÈa4ÔŒÆt¨\CÍh¶âyy^˜À9:FÓ’Ö{ÿ•W¹Ë2f4•½ËlTvÏk#³…ÑÓž¡äˆ<¢Q˜Â"lôSX‡f3–7½ÔÊQ=¢ÙC»-¶òçQ¶öõÞ6c|yë‹zo}‹#ö žúºuÞáÂñ?x%Õ9þÏÇ õ g-‰C<|ÉeÑÒëfmžqˆ¡ÐaFytËï^álÇÏj{Ý5¼:Òáì”j›ÖíŒCâÎ^þü§‹Ò¼çùΧäÍ:ê½Y?Ä^OÖ#7ååÅ1DÏÇ‘WæY­ Q¬·Ô<Ðບç[qÅ¥W<’b€°ǺÕzųÖU,oØ7ž!°–B¯x¶†ô·w¼ÓàÙnön¿šóu:Ç'â\)ücPéD¼¶%O%Bˆú„$¯ŸnJ&ô §+›N%7û%u{YXÀYËý‚â*}‡_P g#ó§Àg¢.½®ÎVŸh•ã¼ö g'ÏNéž=;ÍN±€³÷ÄϯìÞ"·—Žmï‡ó9NC{ÖÔ-É%ñË;â%›:ÍåË ³ð»>ÛQ±ÉËÏñÛíž¹ Ü~Ç^!‚ã×Û€zO%vŸë§‹€‚±Ù׬Pgö9~½hÈð€¯žW¨÷†QRæ9Îá²´•W¢ë€9­ƒ©¤zÈ(] —ÅÖlð€ñ¡ïꉽᙧìˆõ<+NËëÛàYëëálL» ¯«³[:½œºÂäÍpdÓ4)½5ô ˜2zoÈ'œÀ”ÐKˆO8ë~>ïéøÌç…ÐE>ïT8"½ø§Mç=Ÿ“¤\ ÜZÈÄ;œ­)›7÷ ggJæ%^úÞ”:[x…cL-.°W1øaJSõ»[«•)—úÅLI>>ó° ”ÓÁˆO8À”tT–>᦬#äu³Œ‰>‰×ÕÙ˜² |¨<ÔTuÂÆ­ô`¦ÿYŽ–;YÐ+c‰¿ÁŸ•ìpÉHßý2&ÔÄ+cIâw}¶¦äµøÍÇ]Ò—x¼ÖæFˆäµw;V$]‰_$sŠž’9*ιG4©g3}·ãÈzMª{6{ÆF.Ë^!ÚËÖiîDv},I臗WÓ%-/åèûD£?YѵXÖÐz"š@ç°l*þ8ÕO”DÂÐ+ /¯RL¼â å~õ»>kSµŸ{ų‘ûá±$^ìú]ŸíØ1Ç ÙpÇÜÒ’(“ñìúµ‡Z<¢öP‹gqјÉxD-¤Ÿ¶ôPë)lñO¡<ŸcÏe³_çÒû~õû~Ë+Ø8 XBÒ°¡žW˜ªÅ$~Yh˜ êx–‰âaûkŸØëS95Lÿ(íYš~pÀYíŽ( ùûó#»ÂØ~…Ä'œ@Rܽ‡F„ú„³åƒ%µášÀIT½®Î¦ëT5n…Ùô)8£ ô §»Þ~Ú뢃ƒù#öôBS¯›ÕÝîô¯EÈëfí•]š«âRÁÂëf}ÊÚˆpM›‚’”^ÅàGwqɬöä@êKæ—Ëßß»î:mÀŸK|9%G‚½â‚ùþWHÂŽ(ÜÉàœ}_[Z/ÔiéƒÇ¦²ô…iáNwþJ¯ÑKvȰO8ÁØìÃ9 èuuר¤wizá|*[&´ Ôëê®Qz¨³‹W<óFšt‰Ò¿›™Ñ ©ù÷Ÿ¤WPâ6\aY²KÛª®r ”=º]½6´ù'mh“Dz…ž&à±wY´Ïq²0?—¡W8ÄÈA=#‡Ü‘O8kS«ºÚ+œ©UÝÒÃ4p¶¦VcÈëêìLÆüÂy¤^ÊbIyMNŸp>¹Üù~ô©KÓÇÛ_œŸ|¿zƒÏÃLS;9˜ŸoÉå adž•©ïYåƒ{ìûž½! ÁÜ÷쟤 »&N±O8ÁX‰G=%þZ^¡O8ƾg!õ g#ï#ÿì{F¼òÎÖÔÙëêÎNÖÙ«Ë_i:{ù]ý5•~®‰q»˜Ÿ‘¾éÞž]OîXyeU*U zVšr»i|.=¢‘u¶ï­ÍõàPÁXY•J–"î­M9´üVv¥RÇí»rÖžùFV\»‡ÆóNuý·~ÇþÁœ²ûÓ¡ÄÑ T2ûù•qq˜º|dFÓS,FÎÊKš§‘ÿMð\É™ 3—oÌhÖ¯žÓ¸ñ ™1|v™SmF³éËâ'(ÐÜî©ÏµÙö¥GÓÜâÝÚ@Tbh^b³c¾av¹O4ûQó°ghöV‡ª}òͧ\wh#Ô§ôûP¾m®ßâï‘qE¥7UˆËÒëêpq|ÿùË®4N!1Fï^W'p~þvpçŠÁA¡g8kç·ƒL¡€S³Ýª½ÂÙt›õûجçêà:¬¯pøKìv³Vî6«aå¤Àøx¬}^å¼ÑƒóÅË%L±Ró¤ŽJ^OÖ¾‹ÊþŒs­rz‚'úÖÕ‘D!µëglæ5ãæÅ™Ñ€WÕbÚ”ÝHæMðªZ Ѳ¤Ѭå@Åõ™_PUzD£ˆ@tMãF Ìh¶£„wÁÅmÂûâ*Ѭ ùÊè¬ø×€`‡fi‰è‰hÀ(ùþÁÅ$¾×Fœ©ŸýÔ{®®7h<¯ÍZ®v•¡Ö 1£ÙÈUÀÍáXú\›­©uˆÞ‰FzOiºW‡Ø#`ê\M¨G4¬kuó`¬ëZý^¾±»§ž«½òÍÆÔ­ÚëNmGº_ßx<ߨûµùcº¨ø£š±òç6›Ó%ö3ò² ¡O8ãØ"ìÁ¹”Ÿp±Åîvp[´€#¹¬ ‚ .ËÒ'œñmõ’9‡vŒ¦›ø8`%u çgè—mðèÏÖéO¥W<’Ã…ÒçáÂS¯xÖrWi(òÎ?’ÀUïÞº4I^ñôn®QÞÇ¥ Ï´ryUü–&VŸ}z²ùˆ—5ä˜ È“·E½w·ÉÛpyòö£ü}C&†ϸt7ìÝaÍú¯xö"€ÍKj>r1šõI |Änãéf<Ÿòø¾Àã:¾o!?žÉ*Íï¨9ðbü2ÐjõLW€H¬g@`ÔF÷±BopÊk:Ž®” › £kÐèØ-oÆÓ3Â$"Úm<¬ᣇ®Û*&6xÖ¦6ÌnÝc`ô:ÁÂÿ#*¸µîÃã{Åclœû]ifølëÒdƒgmlÕ¶ð|§­ÚðÒVm`V«6uo4¯«;Çy…³6öFÃ>álŒã¼®ÎÖÔ¾ÎÄVmY‰ˆO8ÆVmKSø€ãVm^7Ëܪ ù„cnÕæuu ­ÚèâVmÀq«6ä޹Uñ Çܪ û„£nՆݴj.ZµAg­Ú€ãVm^YÙܪ ú„³7öFó çÓØ9®ô*?Œ­ÑüâY[ÇyÝ.S«6¸¸7pÙª Ñô Çܪú„cnÕæu³ÖÆÞhØ'œ±sœ×ÍÚšZ£ù0Óí[µÑ[I¼â1·jó‹ÇܪÍ/s«6ä¹U›ßõ1·j{³ô™Øª zDŒÍÈÞ¼6Šr£êfm~ñc32»5¡™O4ÀØnËå5jßþKÙŽÌ©¿¸ýW²¸pÚþ+\œŸ\·ÿò»>æö_~×g«l·…Ý´Û³Ú ÛmAgí¶À¬ö_’öhØM{4à¤ýtÖþ 8oÿåW Z´ÿò{Âí¿Ôݶá˜Ûïx…cn¿ãÎÞØïÆïØ÷»Qw˜Ñc÷ê¹ß ñˆÆÜïÆ'ߘûÝøä›­±ÃŒ—µy-u®é¾ƒ<¢Æ3Ô#šÀØ}{D£èwõ»úÝ`gýn€ƒ~7ÐY¿à¶ß ñˆÆÜïÆ's¿èSú™ûÝxÆæ~7^WÇÜïÆ+s¿¯pÖÆ3^álŒíw¼²òÖØ`ƧØyô»Q·ßñ©YXô»yëe>¹ß öˆFÑï:ëwô»ÎúÝ·ýn|¢1÷»)=¢Q÷»ÁnúÝ7ýn°›~7ÀA¿è¬ß pÐï:ëwÜö»AјûÝøDcîwCÞ‰fr¿è±ß ¢јûÝ`hÌýn|ò±ß×2÷»qÏÅ‹úÝŸp=9 ³~7ÀE¿è¬ß pÜï¦ô ÇØï†z…cîwãîîtÓï{Å£?[úÝ'ýn ³~7Àu¿¿ücìwCüâ1÷»q) çö»ÎúÝÇýn°O8Æ~7NúÝøá}¿ì¬ß pÜïú„cìwC¨O8ê~7ØM¿à¤ß tÖï¸îwSzÅcîwƒ½â1÷»ñ²>SúÝ@¿€Ìýn<¯¹ß ö ÈÜïúáië~7Ô+E¿ì¬ß pÝïyÅcîwã—ÌýnˆW<æ~7¥W<æ~7Ø+ž½±¿Œßóþiì¿ãE¿ÏÚÜïÆ3 s¿›7ù©ýnõŠÇÜïyÅcîwãw}Ìýnœº£æö»ÎúÝ×ýnüâ1ö»)©W<¦ž%É2•uÝï¿óaõšäµ±Âk˸,/v"`(ƒz[f€Ù¡õUPVA%ËpÄêüû‘Á©*šø€3,dùï·WùQb¸:F ö‰ OçÎÇÍ#?§êµ™‹`œÁ©Jïù9U}£ëþýÅÑÄQš&¢¥Õ9½ßIí͆£ùûÓ¡IÒ'z/ü¢Ù:*TïE#-öõ-=SID“eå+'¢†’ïÕ{Ï”´>ÑkÅ÷gIó{D ý‘²Ä¥ôû3ýí쎩&cèiu^+¨(+2O«£º«†àR™8Õ—žòÀ©¸TÇ Üj€‰W8F p©~¸Ôk =¢1j€~N•­èçTÙj€^Ñ5@¯hŒà{ÑLÔ‹¥`àT|¨&{DcÔÞTË5Àû„cÔ=­Ž­èiul5Àea¾e£`k òˆÆì¤ïG3ň}Â1û±½²öRhÌ>ÀÒ#³yDcöúDcöúDcö¾Íd ñˆ½nðýhF®ÕIŸhÌ>@—ÒÏø„cöúYk ñ Çì\(sûKhÌ>@ü~4S|€Ô'³úØ+k öˆÆìDј}€¥G4k£× zD³1z$}¢1ûߊf²Ð'³½Í ñˆÆìt)ýø¡O8f ŸÕ±öBŸp:Þùþû¼ÒÇf³™«ˆ¼Äy€êö·¹¬§ é\ÿ’^ç*Âxn9Ži‹óÊ9bq[•RoØ# ®Nަ¹:!JawuÖš{=ÌBˆëáŸl§’Âú­häWçýK†æ\RrCïG3’ÇÒnÍ—C¡K¾±½”Í£‰'8¯§J)ñR8+¢ÇÐ#`ǽ͟ ·ñ èo²øv˜QßUÈ#`¼« G4 ¾ahÖÆ›ÓçNmLhÏÚêïqºøŸQkÈ# ×*àb­bND£ã@h€IÇ¡.O¸µ ¬V¹ˆO8À¨rù³²Ô=m–¥ Œçë\`®¨Ó¹ÈûÑX›ÀdZæ*9º‹zDc4‘ϵ ŒWç[ÑL3!yïNM5©ËCµÜögXÊùgX¬ŠÎrtüÞxÊÛäÉ>Àa±šëa|ªÞˆHÊ‹‰ÞJMy1Ïhy§'øèôt&>ÐŒËIvJZöèhøNýÒï׿˜Wô¡aJ}¢évêç祼+æýÏayCÑ(ú•áG¿²ÐçÚlFµ"šk³[&ý(öˆF*þùù•pß\¼“”îêðûaìV#ÞçþûÃeqœ&^0¦4󉿓£ùúák“ÆI[¡¸Ù)„qˆ%=§Þ)ýD‘£¯¯رñÎj¸:j 9T‡¸¨½Âéı€qô9—G—¾õªR—7’ˆã›¬™ÛÑŒkÞLo’újoDÈ{<áG§ òˆf-øæWÊ7ôv;à÷£‘WñMvÁµO4@Þ? äM ìñE…—'ܺÀoqRô\öõ GÑå ?º<ù]@Ëȧ ¼x…³ñŽèeÔòŽ´üÝ[à¨+?ª—1èXëúcÛzù»ß¯ v«#-Æ÷N8Áˆ•×ceï›ÕÝôu³„¡w­/ÔÝíùǶk÷/•ðƒƒê3A>á¼´í!»±ˆO8cåB´ kOÖ)D©W8cCøÁÊluNYéÐþcß¹›J­½°Äú„³\¡¯b0¤7é;áì„Eó—_MÛÚ®‰ä¥b¨Ž•¯?+[cøKÉ0°T&G¯p:kø·ƒ“vW(ƒSá1ó*wúæp·[O<ÇÒ;!—ÿu‚0zž­,§×4‰Þ{¶è´“nz¡7¯p€~ÂA>ᯂp¸:a¯pÖÆˆÈB̈ˆ cÐY ̈ˆhâ3Ð#š@‰»‰MB³6µ=^ª)OÞk; û…ô:Yl¡Oƒc6‰‘O8kyü :‹_·±½Ò# {bgqO0'¶÷+5±DÓÀŒØž&~ås§6Ƹ§ÏÚÊ£iØY4 ̉í)âžhqÜ̈íiÂW>¹ØÛó*ý>ŒÁ4¯pVÆ8¬W8æØÞ[YÕ‰^jY9ˆ_·±=êM`Œ{ú\El:‹í9±=e;q„<¢1öZ¯}®M`Œ{hÖ¦^Ù—h¦´W>‘O8æH£W8ÜʃÎâ°Àq¤ÑÏê¬T&ù0–æŽ1ÒH¨O8<‹ÅaÁŒH£ÌÆn\Kûã5Ò¨Îp-}ÂrÃ:KœœG‘q eÜNƒcN¹…>álŒ™ãØ'œ­1ÍÕëf),sè,#yœ½Ü†Î2K§Áù”ÃÐYféD1¨H¼ýO-Æ:Çn²¤'âJ•»I®²Â#í°.Ï®¢Ð+ ×Á ³|¦‰x¥†Ý¤{Mij6e4!?Ây`E¥pä{ Všô³Ò+œÀ˜ï…}ÂQ$XAg V`V‚•:ýÌëêlégÐ'œ|u°³ä<0#ÁjÄÊØYê"˜‘`5ʆÃβáÀœ+]² _±¼2e B¿ë”ùyÐM~ÞD<1}Ñïú¬•x ›tʉx6Æ|J¿ë³U&TB7 •ñìŒ •~×g¯ÄÝ$xNÄcN€õº>àØpúÞó59áù„ŒžÐ'œ@†Ξ§öସ§¹¥m)õ£ÆÐÙ‹Ðip€ñI(ô GņÎ^ïNƒ³–tì,³ÜŽþ cg™åÓà(:v–Ê= Ž9AJI¼5•[’XŽÕ‰åàͩܚÄrŸk`½¬1«`Á›`5±6ŸhÌ °Ð#šµ1ÉyD³1†!‰G4[câ4öˆÆf“'À‚w'ÀªÃZÔ#šOcPË'šqì(éŽ9Äæ0ZoedU¬Òx Ñc:.ôˆÆl: hÌ °äýh&$ÀBhÌ °>×&0¾äsÉ7SRN°^áãÃB¯p )§ò‡…à?rŠÕ)§ÀwÊ)Ô¦œ‚ÿ@Ê)V§œ‚ÿ\Ê)…>á(r/°6÷üçr/ÊÒ'`Ì.€>áÆ€5ö gm ç{…£(nƒµñjðöÜ e8ŸpvÆhšW8{cpØ+œOc,ß+œ‡9¬Ž ûÅÃ+Ès¯vSA>aö¹è"™Ò¦L˜ZTTx€±äIµÿïß®©¥8ê-ˆ.Ùá}ÂN·:8T"ŸpÚÎ Œ—Ÿ«ÓõB(+BNçøDÞ ‡£ùÓß,çû¹:ˆwiàœK„¨O8¼‹Æ×ƒ•ã¤ee'B9ÎkŸpÉê<7ë\Fôð^8`t°Ô‹s÷Ú# —:9 Ïo>W`ÌɃsŽzçœ^K¯x€žw¢«ÞY y‡7ðny§YŽwÈíÝ»Æ]–¾hï<öªÉp¿Ý‡hþX66ú¦_/ÃG–ôßêë‘xÅÓÝY?²+&)M W<ÀCÿJñÐȪI—;öjà£RXuŒ0öˆFÈä‡%‘¤0y8Uœ  òˆFœñã$iò¸!ÚFÑËdàŒ¾…M‡Ýß®Ãn³4¢Ã.JPŸ¡G4ކþíРfmàÍ9÷‰fk²@«·¢‘õû ð©"Sè 0yÜ+ô~4:aüêp§Ä# ‹ÕÀKvÈ\J¿?3®ñ>œrÊ8l5d¥.ô³:SXé…#Ð'`ÔÂn5@ìY$ïG3EÄ>á˜5@äc¯l5@‚=¢1k€Ð#£X–Ѭ:—ÏÚõQŸhÌà[ÏÔT BhÌ 4ö $ј5@—hh€Ô'³ègu¬5@êŽ>Y'ž‰gÐ>ñ xH<ƒö‰gÀCâ¶O<ϰ}âð‘x­Ï€‡Ä3lŸx<$žAëÄ3à!ñ Y'ž‰gÐ>ñ øH<Ãö‰gÀCâ´N<ψuâð–x†¼âÑê;È>ñ øHñ xI<Ãö‰gÀGâ´N<¾ψO8!Ò6ñ ¼?ñ Ú'ž÷'žAûÄ3ðþÄ3lŸx|$žaûÄ3à%ñ Z'ž‰gÐ>ñ ¼?ñ Ú'ž÷'žaûÄ3à!ñ Û'ž‰gØ>ñ ¼?ñ Û'ž‰gÈ6ñ xHñ ¼?ñ Ù'ž‰gÈ>ñ xH &×ãVf1­ó'õÁfš¶hòO‹&dpØNAÞÊ#DéA»ß#›i> í>ªù&Ôä^ÖßrH¢ØjÑ…ô»™†£i§¹`'¬a„»3®Ÿ¦-.Lÿý¶ýI˜¤­žË& o§4?Âðv±™f˧ùækÓìSŽ'¼¥u|¼ÇÐê£vÏ%>Ûúómc›[Yd%º…Iy°Ú©ý`È‹m·ÓœNaVw÷¸~š¶xîwûQÇÓ)bkÓ–ÃÏ!!®ÎÅ +öû΃ÚSÅçÉÂúBÕ<‚¹ñ§äxp]²YÏV[λ®|ßÿ~‰óÐ4áóàòp-Ï>ZÍðy~þŠyPÚnæ9Öå%‰Ýw­µÇ<.1–®sñFý[4ç¼Vóèúa9ûŒæ ôGË£Õ¶òµù´¤$aUÝn„,?M\Ðôå5ŸBš„ßmmd7‚9Jš›Œ2…>²›ˆë›÷¿cµõR§:^.¡ÝD;>ÑÏXq½¤lµï±ü´ýó€4|”òæ@-Õ8Ìn•í§}'zÜ®ÍDÌ@µœ ÕΔýö:»…×*T_g¯­¡“¸ïóÓ5»KY-n¡Ÿ±âÇGRÖY×Ú4Qð*’çuG»/ËO[k¯3Ä®3…ŠxpôÕuvD‡ÃÝjýuFËãñ`5á:#R«y ×™ÚÊÌcºÎÎil5é:Kov룽ÎB&¯/vë3ºÎÒv}øuvJê´DVó®³¼Âvëï³ v} Ó¯ed7ÑJs/&ͽx°ÛyÃuv€èp´›HwRv»3f¸Î»M3]gã«ÝDÝuöÛ]g­)ÝŠ!¦¡ûÃÓošhx=M¼Kz:¢{L,{t=|ì*ªô‚,ùhhT¡öãøå‘×Ka¹Øâ:ë_°¨cH†èœ†–ˆF×YŠ’‡™wή§ÙÉüî:û’\gšg·ýÃë,}:vbT”ªKDëç¡Þ‹eQ(;Ù‰°¹.Å^0ªQX“—*õz=î¨Û¿>øuÆ®!vÒ 3ÌK›iÚ…¾µŸuŠÎ­hL›.VUEª¼ m¦ Ó$HôæbÓu¥×èn3ÞË@˜ZVÚL³~«­ÈàŽ<¦ÜéÉOúp!æ…¼ipŽ„tÆ—ìÆ(,l¦ÙuĤÛ)œÝ#Œ0Å6ÓìFªf«rU“Klµ6û±“S>¸ur¢«šÏøü(|…‡+µb¿~¹ÿþòË=Mø^5—{žœ*ˆ®±Õ<«’ùMÚ* l× EW«yFŠxÚÞŽÃ ³Ácd5O Sè»y ¦ XâYæ›Åæ)uážÑ<›‘BßN$ú®«y¶2À«>lŠ)=Zͳ©P­P*,)µâæÕ^fð41„º1xà`«£¾üÌ Œs”Æ]*Ìê(©‹“ÝwÁúˆ»¦]ŸäV–åÑ껄²òÍÏSVb®Ï·jxy½Ý,EX§«üýî\Ò­_ÇŽÊC”e±Ý<)Æ’XÓNSQrabŇÀ`X¢ÓÅÏVÄÄ~; %<‘a¦QˆB«óv¯{fVvxpxÍ"T]¬äØë Ô4ªÑÅn¿>uóTÑYaèŽ.d®}ÿþûiù0iÒxP^oY­O°Òùëó9¥Vßp~þ×™§iÚF¡Z%>9×0µS{‚``æ¶*³0s™S…Äj¿‚µÞ€¯*¹Š:šg£Ÿ'©•ü ¶ó=oÌ÷Òn¿všy.ͼ§ÛcVÊNvgÿwT-am·ý&ëÕÅÁn"“ù“U–ˆ4öª™½¡Ô?†u‘µa ¦Ig ÆìxDYE-?mh¥OK*l²³PbÇÙzèÆ&ºØ]ùzèÝ”6Ðð®þ({ ¯ÅØ‘`¥×ò³ _í&²‰„:Ì&ª+d·Ø#;¨?QzºÞ’«åDë‘A…áð¢Š÷Œ'ÚèB«áí–Z2d°•„D;U?A§”b;1"l¡çö#ø%Yx­¬·¯1ªnQuµDô©K^º\O¡å®­uYPUƒÈ’ÖCΑL¾ýçì–Xnÿz¤`?ÑËɶ#&v‚m -Gö 7vh‘Ý®M"ôX£šmq±H\£CE”îÏzü®A]»–‡Cd5Ï0¼&"Hm\,˳°V%y æÇ×Ú¬_»…ø~·šGØZ_e`ãqÕ&2†Ê&爬æFØ—U*"l’Þîb5Ï–Ïóûøq_A3OLHÁ,>»ýÚÉÔÙ6¹§Qg•>sñ$½ì;ׯ™‚ÕDUãRU$Ý¿Äúœ…¿ «Ò°Î«"«y‚Á<ü€ñyRUB«yºÀê—Xg·>Ævßo”ÅÉî»ûy¤­'¡MhõD¬æÙê÷K¥£‹}ÿóšë¬Þ/iÏéŸ×\çþ~ñ˜߯âVÝàÝjžá~q—Œ˜‡T¼^­æY¿®3j¼â\°Ë™\²±šGì×W·ïIÜúÐÚ€:¤Lk «yÄ9¥Ýy¹zÖžSöauuŠ­æŸS‘ußî;R™TànZöéÌÍ ¶ë1Fò ÷Á,@Æ;ümL“z{ErÌ`–@“@‘äu˜Ë9g0ËZÇYXÕØËF›…‘åP.ݳl%<Œ–ŒT9•'Ì fÑïô½¼Êo¾?|Ý ïï5ÁwyúçhÃnGª—GÃyd¯’ªÛ£yÖ2Í@ðM˜áMqC çÙh5&¸äÑÇÑ<[ÉMÓízEªÛÛͳ“½8ã9ª„Kå ¯æ5 øŸ6v/βê`5Ï8G²½!Ä‹3R"»y™‡û¹ð-'+3þ_çYËÎEëÁkÎ…2K`4ÏèÅÙÃ+}Ks|„ñÑn·š—bEfgj‡ghÁ%ÜwÛZp¸:§YÍ£}qv Ïô ­æùâáç‚ã)Î…-žÕ‡–¡8R½MnŸwµçÊ¡/§ƒÕ<†¾RUþù`ž@ˈJÇíhžµö`ÄøHVótÏ¥_2ÊøÊ:Å×Á«Õ<â½ôï8ÝîvIS¦ñ„7«yF Íš3P˜'±Ûwé‹iqÀ’0Ìn”XÍ3bèÖhxNùÍO—Ç. ^…7•vµý 33ø“ fkW·Š™å5¶wûï^ã¤[ûW0ôù,Ò `c²ßî¸<–ý'êiGCù4q$L%6 ["zdº%±™F‘ _”X’ ¯žfý²6Õ ÄÍ­†”©ÕGmø4üPœã6wòiN7v²îýîžfkÚ©þë `ô¨ç5éX±UG(’oÕhžñ^µY±Wø!±šG·Y£gxšyÄnq™Ñ¬w‹4ëSÝBx¬ÂÐjžÍ`×SîÇjwýÑ#Avx¶ü»h·ÎÜÚb_£ªU5ŽH1ÏøÕþ“{:&dÓäUu§äp?ÚL#vë‡O“2Û¼Uå›ÕIrLJØOƉÁ 9RÆ„òN^öê‘ÎÁDMò{XÛL˜ŽD¿†zšõëÚD“ÑLƒªòT¤²™fpÎyª?ç9;<ÚL³}9WiãGï>Š]Ÿ%-)±™f7˜&áwz; ÂøZ"«Ú¤·(¸´€÷>È¥ÅpšO­° Û¡QåA7Âbœ­™G‘Ý Q´fžWFf_?„ÎùVÁ¸ 3«y†œœð|¢–“ká£`«ažõðDpaÚΓÆwXB(Ÿ§sÂKÏy‚­ Éñ¥Õ<À$/îØjž@džÇÅG»yÖ&‰ÇVóŒîôçYÏýâEaÖÌ3:ì½S £±šg§UœâøxGVóìx0žk|Å%´›çSó]ÇFúXâQåµu”¤›H‘ÔJŽQn¢K÷ŽjáR;VìlJ„Öä’ߥš#ÂÏ㬶qVC8å4¬hn5hBñiç ôJä<=šgø]âYQsV«¶VñiÕ(¹æó”AÕ‰®÷µšèð4õÄ´ëüçÕcýTZš¢ ÒRUg’—an5Xç=ÙÚÉŽ*$!;< í*L70Ítƒ Ó L3Ý ÂtSM7(5ÝÀ4Ó *L70Ítƒ Ó L3Ý ÂtM7¨0ÝÀDÓ *L70ÙtƒRÓ L4Ý ÂtM7¨0ÝÀDÓ +L70ÍtÃ Ó L3Ý ÂtzÓmhsA…Íô¦›œ—Ç ˜fºA…éô¦ÛÐæ‚ › èM·¡ °4Ý„Í6Йnce*l. 3Ý”§|ds+ÓíaB…= &›nPjºÉ¦”šn`¢é¦˜hºA…é&šnPaº‰¦T˜n`¢é¦Кnº“ÇVó¬å&T˜\À`º M¨0M€ÖtSÒ±I &šnPaº‰¦T˜n`¢é&)˜nºA©é¦›nPjº©¦T˜n`ªé†¦˜hºa…é&šnXaº‰¦T˜n`¢é¦˜hºA…é&šnPaº‰¦T˜n@gºÝÿ}5xŽÇèÜéb NаÆYžÜɰaÂËë¿ÌÂùŠv–Œ&/Ö•³ðo¢<ö{<‹;,J\Ü’â|})‰¥œ…Kyúó+fIŽÙâ–ç2:\-fá2ž~ýHf óSTöS¨”³lÄ,, ›¥‹SYZaáÊRçqÆ,aR$ר´ÁÂ¥;ý~ÌÒ¶¾jgI³,#4²™e?œ…ci¾(=E\ZÍò9˜Eœ¦v–<93UånÃuB®ÿýùi’¢4æÉðIY×õ=iÞ­R›iFÜËK.pî­hR©¸÷ϸœò,¡Ë99ÚÍ38ýÊ“"UŸƒÁ<Áh•[½’¯rv&÷YͳÖpÎé’űjÏól4|EY–vó σp>4ߦEq'ý'óšy†'BÌÓ~WUœ‰’ óì5ó¤Er¿÷“Â4ó|jÎVV$4²\çѹ`—LŹ IJ“ÂnV ¹Î9:gSéåz_¹°†ù«ižÆW›i÷C+M9h¸^T‹±P梽ÊØfšµüžiÑð{Æjm6ò‹†_íEÛL³ÊŒçÙÊš»ón·6»Á4½£•ŠSL즞a‘pÉSWÃ-Ñïë áÎ~õõrªæ¿§`¾ÑäÛÍ£ÌÍgl*³`~å@éf…E^"ËyÖrAXpAxc‚ð`5ÏF³ëYq¡ÔÏV.Ûm/Š3Ó“íÖy§™'-*&P±Õ(yìWvÎŽŠõùÓyß_l,Õ}œ°û¸Ôž ŸF «“]ï†ÃõbAȧÉÃ,:š¨¾ª§Ëe1n®þ"ŸÒ ÅòE~xÌ•—MÿÎÛ"¥EÃu¹Ba“,šDaÑZ‹Fvaɬˆ@kÑÈî+™]è-Éu%³‹­E3ä™B¡ÿ–ÍSŒÊl‘ÀÒ¢y u™]h-šÝMf£s-šÚŠyµÜ;¶Dk‹¦qŽ-£`¢E“(,šÀÖ¢éï•Ä l-!‰ …eØZ4¯ðÈ ”“%š`°h¤\(±°‚‰M¢°Œ[‹æõ"YFÁ|‹&±Û°•ÖS5¶h‚iM¢°h‚iM¡°h½E#syÉL‘@oÑÈ|^2S$0X4²‹Fb_–MïlÉL‘@oÑ uÀBaŠz‹†JN–̾ ì-š§`["Á‹¦gQ,£`¢ES(,šÀ`ÑH] Í?0X4ÒM—X"Á¢Q¸ˆF–Q0Ñ¢)–H`kѼpáØ ” %–c0Ñ¢IM0Í¢)M0Í¢)M`iѼh•cK$°µhúp$–Q0Ñ¢IM0Ñ¢) Ì¢ÙŒâúï4‘Y4ÊY”7”X4ÊYÕA$r–µêÚƒ‹F9ËFuëA‰E£œe«²‚‰Ä¢Q΢ŒÑ@‰-¢œe¯ò³C‰-¢œEé&ëJÍuæÕ4ª ”Y"IÀÜæ -#Í<Ê‹J,Í<Ê ‘X"šyÖÎYFšy6ª J4vÍ<[ Ž,Í<; ž‘%¢™g¯RˆÄRÓÌ£;#KMLJæåD*‘Y4ãfŠÑ@™E£žFéñ"‹F=Òå%6„z¥Ï‹H #õ4J§‘Fêi”1(±!ÔÓìT^m"±hÔÓìUN"±¯ÔÓ¨b4Df‰ÈøØ£!2ËH3ÒÕD$fž@åÚ B3ÏZ³é#]3ÏFåJ! K3ÏV³í# K3ÏNƒgdiæÙë¸yhiæQÆh Ä¢Ùô½ìb4DbÑHN…)FC$z Ó*‡lq,àŒ,Í<@³È#‹fÓÏ:³‹Ñ¹E31FåÍÔ ‘Z4†äŠYúìÚ“ÙEúìÖ“ÙESc4PjÑLÑ@©15FC¤vÑÔ ‘ÚEóc4Èf-÷Ž-‘É1"·Œ¦ÇhˆÔ¢ &Z4œoÆ)F£¸€G{`kÑô9P¢±ÛÇhz<(±°¦ÇhˆÔ2š£!RËhzŒ†H-¾%1K†Öú»ÆÍÔ ‘[4“c4PjÑLŽÑ@©)29F¥¦Èä ‘ÚW“c4PjCLŽÑ@©E39FC¤öÕÔ ”["“c4PnMÑ@©EØfõ7K¢ù›b4R—ŒÄ &Z4ÂÕ4² ¬c4/Ü3¶ L1)ûH,5SŒFájYŽÓc4DjÑLŽÑ@©E39F¥M0-ëLlÖÈ &f‰¯YFÓc4DjÑhc4ßß_´¨qÔ]ű`wz]ïþ×ÿûÿåÿgõÿ¬·Án·Ý®ÿëüïÿ³û¿žcx˾øQ¤2)“0º²#^’X9–÷•øúîÑm7cÓ*)á5Š”cyÁý¯û_1VÔíoÆžn§û–jºë]ñ¤·›ÜÈ‘”T9V´Bùûmßßò±Çëñ˜]ªQŽÝéò—Äœî)¾î¥r¬¨Áøû÷·Ë.½öùgC÷t¯’ÛírU ~ù¥¼ƒx‹™ííµ8Ÿ ¬û)Z2~ýåtE)66-ïÅ©.™F¬ä Þðá盃Žz C”§i~Fê ^­ž;|8Gq÷3Iš‹£8‡g|U‚²Xê$…¨ójÆß?-c&q*šœ$e1é™a|KÕƒy ãï¯v0LÛ¨ |½Âë_BõàíËษÆ,(“뵎q|Ö Þ½ÂnÂfµåãñÆ`5ƒ÷ýÁŽ[IÄŽ0>ˇºÁŸ¢ñAËMA~¡ê6ÕWóßÎ'õiäm ž”[k b¶Ú‘V¯6oýÄK¹7”#Ä%1£|,3ˆ³¢ÒPæuò™ÌlÃ–Ãøà,.C”æÕE=˜—Φù7'±xIÙ|ó5.QšÅwõஃÜ4®@\l†” ²`²_›så 5 oÚ2 å8‹òò”©åoßô,š>ÂfpYfUv¹œÔƒwÏŽöíjÇÄf«}ÌÏé©ÊÔƒ÷Ï.Í‚ÁÇy˼¼¡¢®sõ`Îaß|µ{5^–âò~¿Æ¸¾ê{æCô è`'½o¾^N·ì¤ÞgÞ‚éþÍ™$më~žwTÆÎõ` `ÿv°“¦« ŒlXÄ8<«ýƒÑ 0¦Î•GtÏ«û Gê;½m¯ÄƶZ`ÄØS¼9¿\’ ÊÂ{È´Bõ`ÆaLý~7«ÝHOqÛD(¬²£0Dja :Ê>¯¹F~BqÍo·œ1¬zðîÙ]¬©µÝƒÛ»ŠÒð˜0‹£[ímìw›ÏfðjóTdî_mÿ•3“ùm¶Ïìx%á±Ni¨̯úÛiAœ;››ýxInI|TjAÛ5²…ÝüŠ™IrP^a7{ÍÖI/‡‹¶¨˜ßÀ>œ“Vò6÷3;LIMÊúæÊÛ'o³[²!Ùʃ3!á‚ÖêÁÜ^ùåß|d°ë'‰i‰Ó°¢w åýó]<ÇB_eƒË{œ¥¹ßÕƒ¹eòï«£wʦ‡{^\⫆2×hä£Ù¹ /M§ õè^¡‚8ä¹[àI’‹c¬ÍÕý;&GþÕ|ô=®ò¼(ÑŒæô/W˜ò‡ìf+^UMãyÝhn7ÿûù}Ž9‰”I„ðr)KÍèÍ òT´iMÙhf¼ç·ìVšÑ[å誨òsuJu£NûjRSãûÀ¤QÛ„ñ8¬Cˆë$­°fôþ9úxxŽ. l3ZtNk¼(ìˆD0åês]uX„Ýݱ]oöÁ®•fëž@ú÷ûï¹ä)—flÃÎÙùt‹°z0ì¶(ÅԎ¦!r¤¼2y*x¥\ßóóíB¨zðZ=ørϳìk(sFù',㦘êÄBçauÂP=x;œ6² ¶<&ù-¼œŽêÁ ›Ü¿˜ûÛø»b&‘Úâ`ŒÃB| ·s‘k¾¹á’F9ùýaÖöùnOfæ·;Ó0¨Рn]vßm»‘c$N5}¹„çšÉPb¢a’v4¿çùèVɸ\nqÍD…D7zÅi·nïF“Œ£–EÚ1¡'‹^6ðÃÑêÏÍá¶{8ø”i¬©ÖõõZÞ‰r™^‹“2õ‚­D«ú몆¾Öm÷¦šç츨꼂ÝëQï-ŠÃÑ»Š‡Á~vÅ®àb€•+ü9,zÜ·€ÙÁ?PÕ ¯ŒØn†ÖùõÊäšj…[ŸÅý·m­6]ÔÄ=‹úR•—Œ RµL­ÇâÎ,ÿ¯v(o©ÚìkQ£<Í«ÃU¹L­¿‚ ýæTcáOk¨2 ªVª¡kø‹M»>×Í3ĪªOy„ FC7œ*T»–_ Õ<¯²+½*¿u;ܸHÄ·&!|€Jª»áPÎÿí·†!»¯Ê»jè~8¦â[iÞnÅÊ}ýìkãeHž†yÓñHõ­mãæ×¡íDz¡9³ÕO9E*³VÜtXvÓíV Øï= ôu-–†”cQOƒÊ±}kt±Ç®åZ”iyñõZ®öáØ­ünDz»}8V¡wA™Æ6»W+A#Ýt8öS®B™v:⹂ e êhðJ®õA™Ö7 ÔË5RSGƒ¹¦ ešêhðZ®Ô@™R3¼‘«pX¦ÂoåJ”)q£Á;¹ejÜhð^®a™^4ü)Wå L•I¹2‡eÊÜhðJ~wcÙÝ= Œ šIzÙCáÀ2…c4x-Wê L© ÞÈ•,S:Fƒ·rMÊ4ÑÑ`…~eúÙhð^®B™6:ü)×G¡LÝ3rÊ4ÒÑà•\í2µg4È•<,SòFƒ¹šejÞhðZ®èa™¢7¼‘kNX¦9oåÊ–){£Á;¹ „e*Ðhð^®+B™®8ü)Wù Låi#J¥¯ÕT£R¬EÆÏwã¾n³(Zÿ^]㺮‹û±i\-¯?V«í'h=÷µ4ªU„EGð«síM8íÛb[ѹé‹ð%:gYçÜmÀÇ'øØ6ƒ?ÿ¯~wÙ¯®»,ÏÐiÇÖ‡,Ì’\9VÐýíè6EÄ!ïL £ärIÁÞñØ`ÐÕ6å©—-]D£°zîÓhìz„9í0Ó!¦W¨Çr_æý¯ ÛFÆ9]ˆCÚ¤Yž”c·Ïˆ)ËSѺךԗú¢»t˜ÓTtñ…ex@‡ðyIÆîG€E«åf²Su=Wʱ"¨Â»õ¶ßûXçà EyžjxãC€f7+ÜÈž®õ0% 4 ©z¡EFç›Òù°9PÍà²(eT¯ƒ›¬e18†qt‰’G8G2˜óVã”EËö2Ã!ÊhžŸÔ<͵ÆïV4ßÜ,u£¦©u”<’$ƒ7/«Ýòt"83Žª*JnšÕÞ¾Àn>¸=Œ ‹„QZEYvSÞ #.ÚÁç¸bãSõàýè›Û'*í7×I1¹«ü9øfÔÂnurŠn©6øxÝf]ˆÕf¡¨¨5ƒWÃÁi«î²ÁE˜Ð,:#õ7s­ñ»m÷ܶE†í±jÚ"_“0.Òü)ëǃƒ'{6IE7yn@Äz<´¸«¯Ÿ°åVÒ7† £œ„Åùr=‡êSzò‹ noÆ„wsf¢«8]OÉQ=X°®4 Ël0Ûçðz¾Ý5ƒwÏ}n¾¹íÐ^QuLužÐ„¨·F[ñ×6×NùjC^ê";‹S¦Ì3’~y8½QEøhv9Æf4§a©Þ*®5¾Àno Ñ3Q¯vлÛÁ a±Ïˆ¾ÑX-†‚.ÍåïÏãZæý²³‚„ *n‰ZäÝý(Do+|ùà²,QB«R-=ƒ.e·}Ž5ˆç‹IX“Ë톟&ä†é1Û  ÷õ5‘Ÿß_>6‰yºH3“K~½”ʱ sAývn$øtA…gŸÂÑXþÁÿ$¼''tÐŒ] ÷•º¯ÂKÏ4ËÔ?‰ë‹Ñ½œ.½åhìvä¾êÌÖÆ}…ËbåØzlV_iÙsªŒÆŽÜHVÆáùV’<•c?Gþ˜gðÑ%ÇRM·s#ѧÁ›Ÿ]ˆ5s¬^t¤iÌe@ë›ÈI߯jÔÎI?²˜B] ì~RƒŸm|Âú–3³âéØ^¿$S2Ô¼_JÂÔ6J¸.t‡iÓ—õQ{ŠyfI]Þ˰™E3xûº`ýÀOQîe©ÙæÎôô<N3µËòÕƒ÷CÇÆ“r^_a“ªüùTuEº®H8«£æ£Q¡9QBðw$ëOðŽ$I°6c:˱±Ó“Ýcõ`ŽiW»1x!O‰iƒ ³ctW~Q˜i“«[ØøŽ(Íoºo6‹ëÇ©Ú­Ö«í¶•õKqM•cQä"åØÀ(r¡rìÚxM¨éšÅµš®B\C‰¸ÝÉÅ&”ˆÍÑØ½šîPÔÆ~ÊE=”ˆú1o|È%.”HÜñà•\ÖC‰¬r‰‹%w<8Ëz(‘õãÁFq]ªÄj#šP"4ǃ·FY¯Y°Qhj(+Ä5”ˆëñàOù-%·ÌX‚|È%.–HÜñà•\âB‰ÄF‰«^0!®u·ŒZu^‘³'ñ£«wÝOEq|äDï>?ö›@ þ¯ÿû¿þ÷ÿYõòâþýû×%œr'e3½_ò”ìÈ4¤u‹Pbƒâ^ßÎUO-QMhP9ãøGf¸rŠõk–ucƒ7þ6Å=¬Óß©6i௹ªê9D¾k[¿àpH"‘ ž8©Éµ¨Óª4Î!n‚¿vÃÓ£QuöPÜ‹ûé@ÌGm=o­Ÿ¶ºlx;–Ñš×c#<\c‰ŸKÇ1©qHl.®žÿ˸ƒGìRtK˜Ò’œH’£qŽ]ïÑâ9Žy`Á[u)Ëòv¢$4ãØ?_¢„Lz%\n²õ€ax»œ³ã3°£œãóù^ŠÍùëDz9Ò·Œ­ŠQ~}ô_{ÅíÖr›®Ù0¾¿Eäòýþ´šBó¼¤Ýö-ì oUEÆoéÂÇ<ÞÎDGÔå‘ܘzÊâ²4Kð|3|`—Që'g“œhWWŒóôb<·âZ=B(ÆvŸ»íÇÇÇg;‡öùC1~þ  äŠñ#Éà@=xðüA2x-ÁPŒ_0Hoä/Šñ Éà­úAÁßh`›ž?0åZ=xozEPh¶êÓôv¢ÖPÖ=Wƒæ£û—ˆ/…ñh ÀP0ÈFò Åøƒlôº¯\7~oÇjz'IxÌókG{ÿñ±]± †/‹ºz/ƒÙw‡×ÛùxWr]1)ÉPW” ä*^3x âI¯åÊ^Ü â!fÔ|ñ…BÍàU? ß¤¾vÎÎúpÀÔ]ŽÍ—p9FZMiL)ãiÍà@^U WØìvŸÁ bã²Å¸¨Àx,P” äeŠq…ñص¼ @1.0»‘2(Æ… Æc·òRŸ”ÀxìN^¡—@ÝËËã"㱟ʱÃÞøW HÆ$ƒWЉb¬¬@†ø~µY­öŸmöçöC_€ pÉ` ª@†6´dp <°Þ%ƒ×ªdh€KoT%ÈЗ Þ«”êÁæúØ{c ¤üi¬  , p]¢­2À‹‘WV6¨*С.¨*¡.½V°!#É»Ú~|{0¬5$+`CFWÍx0P• !£»fWYeú ž‹ò÷»­³e’„ìWRO“b†Í ±ý-†ð^ë" kà [‘…ÜÕvGšÚ®$?×—¤4aØ=3jÚ¢y­O¶-šÇ>¢.®QQfx©x £–ÿ›dý2¾ßøÀÅ£¼¢j†Ï—b…MáÖoÔåîá‰i¹¹‰£^ÁvNÅežÄ÷žoyz6MñR ’ífÜ~[Ëã1>&8‰`fš¼.âïž`( ã#¾Ü/wÓÁK͆«º §²¼¦ø”]Lg£+»ÛÅ^[¦l½ììÏÏøˆÓ¯¥QãøYcÒ2<žÂÚÄW¯%x›ìøòJ£ðË#Îåh•SpÞd Zû!íS”«:Å=.>š7uÿZE¸ ðBÀl|SLÌ(>û÷ùemnüî·2Œ³"3×Ò¼ìb{Ÿ1¾£2‹ËÚ$lD0ü›ßpq»œÜ™â;-™ihZ ðRDµ‘6±»Œ³îqe¥i-D±^"ê¡`›zg%©MgD”ìÕMaüÍKÛ¤¹ïy-mT–wĸ53É °T£/Óf)PÉ̽Ò8Å΄¢0NÁUÊß¹Õº<[X†I=]ª)Z“•Ý„üf¦rÚ>ŠEèœe•÷´¤•i9ÛG4lНǨUž˜Üãû–ôñjR9Ū)tûÝÞÇçètÊ›£^Ã0:²US€¶Vî#ƒ¦5¯ŠqX„˜f5ÂÆ øÍmxjC„<¤Z–a–Ý£E7㇬ù?bŠöÍã‹fŠ ]O8?T¦)6Â^•ÞÏ<’!JùŸoeªåÅVÖH NÛ™VœT!wà }›¥}qœÞlJÒ†Iµa‘þO4hö³ÑÇ›¯(ЦBXfX?ÅÍáœ<ò&IÓ˜°½€'à "ü‹kXÑCOLê:> ´:1ðcþÕºEš¼nÑ4£©ê{gòûTÔ±aÑl Ó4»Î ÙjRà {aO}5‰ø‘0Æš½ÈNÑýÒ¸0ÍðùÜŠRÁÅQu®3x%‘‰£>^sº¡š`oáíR%„bÓ«—Ô²æÚ·¤lŠœiŠYv=Ó ?E›ÔÛÎQž‡§¼nš¡˜¦úÒšjmsŒn·ð\UiMŒ"^˜ý<┈ç„Å0ªjEÈÄVÝSàŸ.Ô)²ªÛ)nIt§Ç«iŠí`Ф+­Ç¦8g„–ô}å;¡ý¦¸¢ªÎ‹Ts¡o_"Ý__"nšv9vqUi2Mñù,PЬ[Cˆ£( ÔTÄ¡Fi%´÷ÆåÐt™èzÔu‘ÜÑ5‘›Rã¤ë¦iÙó”q«㸸¥aMS´ÜùÛ¸DkL ç©j’]Ó{mš¢×m6< ¿7wïLJè`šbýŒÁ7› ã.ƒ3†u|bËQF¦)zþE†¢½ÐÛ«Õaš^ï÷ßMSˆì‹ žÁ¦8Â:ŒïG†Ã4ÅîÙâ¬]Îg=Å;³o3|Ý™6αz9%q"RBšm ë<¥=¯šrŽžÛ¦Ý”¶*“˜K`U×!ÈÈ]«`¸¤Ýo–4M3—´30›ÊÝ\Ã*oæ èjœ£§Ã··I’<•ÃÛ9ë¥\(çØ>»ð5åorš}©ÃSŸÏÅÔsˆ‡ï¿Å¢¯V»/I~Ž(2ϱÖ¨8ÄkßÇ)+bdœã5éºq`´}Ëxâvš†øˆòëãeMÛìòK¾ó"9R³ \‰&GbMcѧˆñ‚uMŽet4ÎÁSÖ¾Ú§‡ç¤ƒüy;Ûäûýâ÷¶µ4™â&öš§^|Ž,L1¾æQ~7ÏÑÖWúâç¥ñì¶Ž¶¦aoyU@t5î‹°5y¸…GQ€eáô”çÆ³xµ¥û_ö-Í;ª¶Ò GU×aÒá0ãàE—¾ÚË):ó6N|Ž8/^±yo÷ýTÂäŒDí”Ûå‚‹ø^G¡Yq{³Ñfyˆ4‚ÜÁTå„÷æ}Ueünp~ýðpc{3´Þº Œ‹$Áwãš"©²UŸxŒ˜[dÆEáù† Q‚O[ý©í°yõBva"V7DgŽã6'S]˜,ä¦ï)<] …QqBæ9Öâ[š½m‚&âU#®£¨Fat;X|K[¬yvÛÌѪ?Ü›\ßïL¬ëª4ãè¥Í‡Í”¶lÖ4BL»ÎëÒx7ðâ`_wÑ %m“Ø·°õ()ÓC’ì~1ÎÁùô§Û[»JqÁö6¿!3|>knxën…7ËŽE]Üï²õXõm.¢ðˈfmÍ‹vf)Ò îe^ ‹±Sfk„˜2[bõ`–åÏI[Å…î‡&îwÀ‘z0¿—ÿqgg£Ç]s»ò€¢0-.Gõ`.è~þua°6}2m%˜Ô·‚m„z°x£×Ä9ÙjŸSáó8ŸÎEtGWfmkLä{p3¿}*Ú±LŠéùÀŒ:¢¼æ«ÝP¾Þé¡®šãÂì§ ¢EMž/|¹¤—8ŽI¨Ìó=¾þñÐIÔ(ÉmØâ^rtÃYÈ$ˆfôЦb´0B™9~É!ÎoI(ub®z‘†&rô³w×ø—}vu,ïMó_r.´xI¨¶4׊Ùèã½¼Ín˜E‘†×¸:ÇXgÓ6Œ~a‚Ù$·\#VºˆF‰¾—PŠ#—0;Ç:Úë'rF»9a-³1Ú(Fys?êV_Š<úÓ˜\<.ˆò:™mPÜ™†Ï¹ÚöýûÈCk²Áš·AÛ¾‚ޙΤ‘K\aëÑŽùù®NŒÙápªu£÷‚v³æ¼@gÂ%£}ÌâS^5£_òØÚbÒ¼ÀÞåH|DI¥ùî@䱉>jIWXâ’e,˰ËšÑ+ÁçÍ蘗åŠû-¾6a&c5£¹JÖ†üíÆâxì*»ßKr¼RͪqeLD2š2 ÂwR‡³;JB«jF¯_³ÿZ¡˜¶û½Q¨¹¹Ûÿ÷Î;hž'˜È‚ ëšÙÄɥЭÚöIûœã®»ó9=£û!f‚1ÓÑÞqÚ_¢\Bú0Ú4L.ª9¡Ïë‹sÔ9ÉÙh¦-á5 5gŒ+Z÷¿ÿ~»Ú\ž·ÁŠ¨È zÕ|÷š›¬_ünôþYù®ñ7ÇCØèúxËsÆlºïþì¿ÖŒb^üqæÝâ#nu}Ó¬ùæãÕïß–ìãï“`Ø\ ÷»N=:ðDÁ¿ÖQT¤'r$šïÞ€o?OOKÚÑ3h’3¥Íèàe4ïNɇͪ…‡ÃUG»ó(ó5oÓkò°>ŸÏõëVm3%vç» %–Ïì²ÑÛ^5ßFG‰ˆuÔwTêô 5£w5ôÓaâ.C.I®La¨Íõ5þ’®±hb^jŸm» o µ´?Eðñœ‹¦F˜ß!΢Z7zû1¢Í]‚œ6½S¯m¹¾Æ÷»­LÙ&ð´£ë$9¡{¤á–­kü&jóºÆ±×òa]è ‡†øî8Ù÷LËeJîñ|sÝèõ3e§é„Ê_4Zz|`´K•šó½Ýô!m]Lîh¯cÌ8î”УñŠg­‹]¤DÞbF›09§áóíN¬yã¤;ñᄯ9cÖÖK§C¾ݱHœ’fÇ®ìS؆kNèöó©Ý‡M>¦ÈŽnhç§¼.îTsÆvüöÿY$­aÑ&®…76YÞîšïÞ ^kƒͪ‰›¨9%yîL®iÖ|^zîòÞò̓פ!Oø¢ÑSwA?;‹Ýš<ï/mlXÒü–ê4ìÝú5«*j$j›˜_ »DOñAcÍí6Âöoªñ#žâ# Qv&XG[¸ÊÚ{¬yœÜ…Øõ¡ªiÙ¢Ùï· ~š—Ña›:šg]|¼§è|+µ´÷"¹[èi—Îô–’’8 ušÇîóÿgìL–$q0ü*sœcîé<ö½;¢úð xÅD?ý°zI,ÈÜ t¡x=jÊ­§ZÅ\"<Ž$yzn›U¦JZ«…JÊ)›ò¤™ë2£ë>ºÝ ­ñ îÀCÒä1ê÷’ÈÜ ~4™ÐÆp(Ë¡›ˆ›Ë ª>ÔóçÎ±Š±‰W¿[!FB·šèµ·Ssm`›ëQÒZ~¤Ök›‡¥/UîDÕ˜3‘%/4rñ†TLôÆfPíq;à|@«3óqFÏÏû»f•Îÿ×tz¼bÞ‡¡e9[(Ç¾ÖØK¸ R+͆@¡¦o:ž¯.`Ok¬¥?³ ]¤tßÊ™À5^_Ð=­¥Wê±ÎüÛvt¬G}]Ë“`}†ó´>¼\$ĬÊÖ ˜Oq\mèžöµaÖ)­(MîXƒ†!Á”gq~¯€wuÝ/lȰÔrN‘¼Nfp»Ñ®Ïê!×| Jê&IX½&™xÚÏÒGœ÷i.¬œ°žß}ÀvFô+’KmMšañu/&öž¯ÄåÔ]à_|ݶОS‹ñoš‘<áŸ|ݲ ´˜¸ŠR\¢4ݶ¤š_¦ïRü4ö»Mê,›ÓWõ}ÔŒœ’á°øõ]@[eºÖƒ¼cw¤!5,~¯çlœh$„EË%#ú>o:‹#û!«ÑV‘ä6S#å¬ã¼Â鿯֩R.¾m¾Š¢áqEÒžgTôÃ8s ~R,?b¦ì»Àöcëíi›*Ó¤QݲÚ꾯ºfM òÅf…ýè+“õÞÙ M—¥sϳ£h«&³›ˆ7§é@Ó 1xžoõz팘– yÈ¥|ÌÝ~îĤXÅqÛn@K!¤ñËÆ ü,¿¹´›_Wp¦üwðWµ«>`‚´Ý¯ºÍ)뺦*Ú8tÀ”‰3UbÁ›!«¼Ân.´r+6Ýnä*áé˜ÂSe«üüþcóÚí® ¨ëêî¶­>°ˆûW/Oœ0–> [}`mó>i×v1’õnß7Å1U.Ë0¯T·åm¡MÓÕà‹mvàÏÒmâIlj µlßU°Á÷vÓG9Íy5U¼<ï»}ª#’u”ÌóyÈU‚ƒÅï88§&ºFµÜtÍØŒb ˆ£=u˜º`Ùmi‰`Œ:x÷´ÑÖQQ…¥M—KQ.D]ÕOòáÓ]¾®BÙVé”-UÄWãçS¡<©zuOŒõåÓ˜’@Ë›²Sú|6•£TË9¥Ä*ø7?l ¾òfzÓ7‡;ïE×I[}ŠÉ‹«8ÕQ­æÄP!ø˜Ò8tÊ3êĉzU5åjT&U\&"´l£ú7gÚ½h£ªÛ¸«Š¬ªàãFùE•ø·í61Uvt·‹¢°†¬[ô×ü׿ÛÚd:×—‰üè“Üf üâ.?ÙÜÉlž0mZP»1³ÍélV§9Yšejï«[Ñmû.Ž‹MnÀï?Ö©¨/’¥ËU–ƒ‚ÚçWö(Æ.;Bk[Îáv_~îªufêÜU\OÔ¾wÇ£ŠŠpÛfÒ`e+—3¨öç²Úì±+.š2 <¿Ÿƒ|[²ö™•Ó¯Ëê9Öw!f©ÄÃÌGùIå°xW G‰ÍC¿·¼b¡Ui—Ö?ײ=Õ-,®„`uè¶½ÂývV£Eêu9ŽÒð+bXüØUT#þfî¬<Ž1?¾w~Eö/>u—Ö¦mD—“1Ðò˿Ը{‰ºÔ÷’]4¿0k)›H2õ›“ªÂË.Žß}ŒîåS~Ò„Bd LÕX§.ê.ÛS—Ü£˜ËÍž*gfÿ[ŒÝÅ‘†_ÆX³zº}ñuµ&L%“á#[NÔ2Ù~‹o_Ý6Q¦Û,çD@·­´”Î[/r)jåMsxªnSD¯mkŠô]‹Ÿ[k"Û˜"*ù½j!ñ ÂÓS9úø|nÑëíq„ðÔúbIO=^©/¾Zþâ•úâħrÔ?!†=õ£¾ø=ßÀâsè<…Åç¸ù@Ëç ù@Ëÿb>¤¾B`xêGÔ7MÏ=ÒÊS8z ~œbàË€úy ¢§>ˆþH}Šo’€új@ÆS¤`ñÔ‡Åí)—c<;õñìGêë)d>0cg°ÓŽT•jÃÚ<8=õáôGêÄU§îùº¼¢§°¼v8xŸ%O=”/¾A,yê¡ì|ñîö7΃8xêÑè|1ˆƒ§Î¿N‰î%,~ŸbÕX‚èâs| Ûç4:nß{ñÄÁ7î@ âà©G£;P?ÎꉮnßççE‘.Ö¶+ÝãTYb2ýĤbª“§°øvTŒt©¡Zòlµ|ñý¬i? n*õht¯Ëõ!·#ï7Š¿!z¾øL©”óÅ ²•zà@_ü€µÔúâ'|¥ûÏ¿ *õ8x¾ĶRýç‹#ˆ5K=öŸ/Á­Ô#ð,ÜÊ=†ÞD·öÿúvúI/áûuyÞÞæ ûú¤éÁ'í‹O?锿‹Ï?i ‹·~öÔÄhês:aL^zXZ5ËTGÏÇõñÖûÁm›¿´[7™Ñ„S²FˆøâN¹n‹Òøœqß³\tu°ø¾¦]™hAçíVÑ‚8χÕ,òÅ5”xKT‚ •(Ùá~†ÅÏí»™®Âˆm·ç,Ú:[}ξøõ…[JbàafÃ@ºõ Ý¿¿tŒ¡âíæªj,Ž<ö™ó±%ò›NZi_üY“uõÅ<ë’Ô]NqŽm1 yËÉË”PÛÏ]|‹ËäÔ¿[®³³:ô»_›¨DWÞ´ŽdAÔŒlH«Ô&Øýv)‘&(Òôœô%#‚¤uô¥^s9«Z~bò~Z-¶ÄÏM™"æ)§qBm\ÌYºžÕ{Êe àÕáÞ&/Qµ=Ò9gyWfÌ&Øý¶ÉœÆ03¿»â8ŸjsËK°WLÙoÓP•ÿ{à‚¯Ä°õ6Á.³qÕJíªb:Ôç4Ôöci +Tþî¼ì“fB«ïÿ@ýÜg¿;Æ—Jbm§†O V‹I°ûe‚/T‚ 8™êIÞ9úa`¨¨ß+ÀÜêÍÖ4uLÐÍt¤]mÏBÈL&(Ñ©¿±·¸MFPÖPÔ¸X²ʱE?MÓ‰ÀŒ™¸‘Ÿß¿WþÙ[”5-B¬YÑOê«MöZÔæz<%SÖÊë1jÚ9 ¶‘#³#{Ú§ù1ÉäEoD(çŸ ùçÈ úm^u½*‘({1¢¹ |c6vd±¦--w&¹lYÛˆ”e( ~nÃ`¥Wš<–1©ŠnJFѳ€Áa£G|¨Õ¡~ 6头)’”¸7g*w^'3Ê3PGFmJ:©»%—(Í<ðv,Ÿš¥H8šD–ôɆ5v`±¸%“:”iª¶n¾h©Hûd“ôt ¾®ô;«¦¥U'Bs’„Ô·õM©Õ:µ…°Z!DJ7ÕoÔ÷ݘç.Å]rÌ“40æG€û„4÷)0ßç.U »HÙsòº¦IÈV{¼ŽSä¨K‘+Cg¨K°IQqµh5ê¥Z¯4ëYL²mQ}`?· vN]اIÕó„ÕzÂCîÅ/|FMé2]ø,Kx`¥B vtI°ãQ[ìþ¬ v6¹O½bˆºá› J°£.Á®hCm?Ž“é’ÔÈvêóyBÂE¨íSVÈêy¾ÓeÏVi‰=ÍwtœXH—ÄÂ2ô»?AZ ôüuY# õ˜ç–ø-Ǽ-EÂi8]‚MÏSG‘v[Ê…VôŒpµæê›eS-É^¶Rby‹χ6°Î_÷Qª/wD©µ±×td 2ç·É•=§¢Ú„fìõÜ'÷6¸XÓRÚ\š"°;¼^ÖÚs©vg’Ö+ç¦Ëp5 ÁŽ. v¡¯äµ‡oè3P£²m:Ë]½i`?· v L¡¶ßî)å÷2jÚâÊFÄJ£B”{_S©K lBûÚûfÓÔ Iŵ(Ú¶$Ó‡l‡·¥øþÈ17ñ5.t¿f=Â%QHýØ¥%Rƒ"ªçS× ÖöCÈé° 'W‘T®¾ÎvJ̧<4æ¯FØ<ÖÚû½¢yôZse0U!¨z“†z ŽNØb}øÆÞŸ3ªXóèrœXH—ÄÂÐZ³ v¿~’˜ ¥"ÏYÉò,­µèvÆ2kcnìL·´©Øˆ¢àõ”M"tÙ;ÃØÌ´ËZ;ó«¬1B]Èf2 v{ ‘оûyè9¨_lj…]ÕåI^ÖrÑnÑûˆÞ¦~·£·…α(:N l\j ª?kÛö¬­{QUÈc4ç}à$ú\ŽS"GYÒmJäz·ÖtµWlê-®’ª"p–|n!N\Ÿo9qêû®€MáŠÜªTo‘÷Òr!n¾?×Ûíz¹=ÿóß-'¬Ñ°ö­4¯PMJâè¨1c8i@ikzŸ³~E¢6‚·_ꊉJï1›:}SAX‡ |îR« þÎÄÆð9iòªXêº|+_0E®ÜS侕ïc œ¹%¼l«5¦ò[i‰£’=‰qCi[Û :ÐÙ ç3t^ŒFŒY9fsÖA+árŒŽ3Ü9‹.‡~¨-éÇ%Ð*ºÞ΀u°ô~ Ê3ROƒVàu³½ª»Èä±ÂU9¨è›%–Ä“>Ï0wÝI_6Ïýß2LÆ-*[-Êa’ÿbHú>ÆãU>Ï“F{6±¹ÃŠO7ÇœŒçõ³BbÃ1Õwäb*8.Ðj›{»Ãe]VjêòI[Enˆ¨n—GOzõ“ê‰ùnb>Ç I émïxv,>Íló^îäÐoµ„ÝÆZM¬{Àð›úA®Ì•áçI¿ð®R“”tMƒ8Ê´oûoôÙž4 þË7à?O}³óÌ8v^_ÎSžBÒÏþŒsÀ@5<¢mš^,%M¼ãb ¶[Ö '½ƒG4èIíCÄ_}ÁËè’>ZòÐ8Å´ï÷@Ḡ=éã{rL½{39=îåÎIŸ¸`³ƒ zÒ×1Õpô©†žô} %}(¡'VóÞ&KžB%Ò‚å|¨ hƒ¹Žq„S'gŠñ™úè—c¡æ *¡P«ëB±ƒìˆÇíXª ˆ´ÜÒ=éý`-ÄÇãXZùìCOú<Ž>øÐ“¾Î˜‰”¾Q£zô¤z5ÍôG‡U ž ü–·Æ¢™Ç:‘_$ýl^Ï”[ÁYТ–Çèh~^Ž£Ïhô¤×3@c}¯ÚÁû%ÕXe--zL'h3}ÞÀŽ ÓeTƒ§Ú`žïgBK%-˜Y\Îl-Äçó„Yù LOúMƒ¤Ö&i!ïá}ŸbÈäz¾dí$=id9R?›LeÑœ±‘1 .‰ÏþMÒ¦qQ ¬ÄX ÐòYzÕ?—]ºà>Ùj†9£ ´†_× rm›žÔ5±y®¶®¹Ê;NsÈ ·þÛ?þ¸Û\a‹ùayoÍ…\™Ð]ÅÒѼÊì°9éþþü8P¦C’ëÈ=´K¼^g¤J ްÉ,ùùgÑCŽ3 ~k®ü¯¬;í©EؼRë«kŽX?f#tH¾>Û[¯)NK¢JÞ—Ë´ƒ&ç}ù ؤ“¢6™*‚Á¡Ýÿm<?¦î±Åj•«•4­ch[³4æ9ú4OOz?…BÃdܳké?ZX¾®‹d¦ùX2È9ð¶Qm™ª»¶ oRf„öe? "ƒLé·I’·Qƒyîêÿ*zèÈIOÓ2¥ßoS%PýÖLsGõ»h™TY"÷µDšÄà¼FZªm Eówa{y×eHžzyR€N‰iUùc³<5%™´´ïê"Ÿ§¦èrò»²N=éõ“ YkÑí”r ºQîÇˆÓÆGœzÒÇÙókþÖç)Ô•BÒ×ÙÓ)†¾œè}òf»BQ=itÊS;ü9{ó«Ïå„;pè|ý\áwÚ/|¬'½X¡þÜOѯ WîqJn¥ÏSð*Øá×1u•úÔUOúÃb .‰À™m|ά'ýœ¢ZAÞår j…µ×“w`$(¨½"^{P{?ÛRlëkgPÜÖ>OѰpŸ_gïÖç÷1Жú@[_Àpi@ e©”õ]Û—Œ¶k¯§(Zpœ]I“B\“×ûÉûŠßõµcnãp}íóÛW-¨}ÂoA—üÉ÷¾möè[_‚oáv?§àZPëäßÚÆ‡ÞúÚë)òÖÞÎ^ÔA#îj|äAÌ/¸&]d5ŒÊmÀw“[ø=;ë|ß´nr²Ûø]_û>ô‚{‹¨†ñ¼|±ÙÆSû/ðóöÞ»„À¾ýìëk¯¡ð&¬½‚”Á}ò~?ƒã|À8àföµÏ3Œ1ü Ú%žvꈠC›¤+Ù×bêCˆ}m´M}*tX©u$$}R§i:-wÕÛíöy_¯*Rà¾I43ÊXÑ)jœå%EÛvKÞÔø¶¡e*©Ã€5¤%Z Ùt•,¾oíuàVi·,2'#Aåþt ~¬‘ÓJìòI¤8M0êªÍúðÅÏ L$5î~»@ú!ÏJQ‹_ö7›êõÆ1fºÊn]οù½Kš2¯âÔÁ³Ê4[‘ŸÇõy¹_"íÀ[îqÛ‚·ú”áÔÞ¾HÄLaHÄålHľöV±„7 b_ûØ“—©aÕÔ-Nš˜ÅxIköµO¼\Zâ³"/#Ú-äe_»ÅÅ$¦Ü^IÓªÝÔ¾wL]ë!쮤¨åÏÑ&¸Ü´kÒ{5¥#DEVÚÏ&™/Q¾Z“ý!µ-!Mɲ:ƒ×Æe?Ð%5±Âj ¥¥Eb‚,¾~‹©©~&wKy­T ',¾yÃå(ÂIS'[“{Ä›bõqJ Mœ¨”Ï&/çz˜sañc'–+Úp^¤¸lFÞ§yŸÂâMøO¬|¾öÁ;åœlTL,~}OÕo²ò7Ï Ëš:0Ú{Z4uÌqH¨¦EWs‹£­X?yëMwZÚ JsºžÇ¾ø³°ÜìzÀÔC Û¼­áäòµuå6/Jm?C./ÓψLË‚AÌ<7½Ü†FÀSe8DÖ–O4OïUÓòѶŠû@·ïkz†RÚÝKN+6’2°ómiÑ:SÔ>3©LÑVÄ}GVG£/~~‰ÉR hË)Ð ï}·×î“ÜŸNQ‡{hùý…]^QÓ ¯ÍÒ|eˆ£Ý€eŽD§Å˜¡:›ám×Ñ¢—n[®îvÓ Òò œ3—/ȵ|QÛBsK1¼Âî×=äšØ„$%ž“Ž‹JÀ£}ß&Ìë…ÛÚ¦á™â Áb Jt”Eí("zž1 Œañ㋲ø?Æ®c7vÛþÊ6ÐÀƒ+—‡ž¾Óž4¨À(Q‰‰ûõ±$•IªíñYŒ›;¬Åp 0¹–ÄÇÓ`¯ÐâÉ“jæù3šôumUԙѾ¯:÷ee²,̶´pY>Ι«Ê³Eÿq5ïözõ,´@KC+Z¥mŸâ¢Í$„Q›¦í&NÒéÓÓ%yø˜Ž§I4ÇÆ3 ~å6™-éÒý¢Q·~~O£Þâf}soÀ[4}ˆ™—o„G}frLƒw1[sè#O—‹¢‘sÛ4m|Ù‰,íL)É(E!Óàëo:tŸ¶`éÐ!gð-ÍKŽ0/Ç•Ó<¾' Ñ9Wœ³•Ô<Þ“&ë77¯:=` †ózJƒŸ¿‰ÉWVóNÖ Ë´ü¹w‡’KYÊÆígI„PÝ{f,¡ºhÏ }=½çÖªýéié±–è3atà¤ùò=·?s=çºë}toœ>¶œ4?ßÒ×òûÊQÎÆŽ¥J!^7åýü¸<î÷¿þuþë?ÿ}ìÜ3¶’°6|8عv”¶1:(Àa‰ Ï;ŽY›ÌïNoªÀP×-}ñÄÐþý·¹Û6Æž¡¶×7¥¾è» úº«3&ßòÛ‚¦VæznпËBP’=&8Û-ËJÄC[Ÿé=¬Q mÒÇ ZD añâ7¡ñªUêªVõ^[—yíㇾZäUµZµõ€&¨P¿ÆÓ"èÏ5OßFŰ-æ³Aí¹¯DG§:l“Gfï¬ÿ¡5*ضS®ë[¯Â&b놴p<c+7g>”èäj«­ã²6AÓlë²wÑįŸl~·×o¢Ìð'̨çn6Åà¾ÖÆÓãÎPÍý`Î ¡†aÉÁoÛ”S\3÷ú MÓÐ- 1Ûù{PݳÕI@¹ÚÑ8d—»wß¼¢¸š_]@ 4BðÜN==w4J¯RC£„ çzµ:bp·ê¾ä_³ž ÁTýÌtrpOâdß0nâõ@† €‡qÊMÜù´‹ÊXÆ/+•h¢_¢©{5å&.SA~SPƒ_Öej䉷ˆ­§˜n]Ðlç÷U¯‚J=òr1 …bµqcðÛ?NdÇí…~Ìí`86að ë§ç8«±íÈ¢Ò`G!+]¦œ¯Ä°÷’ZÀB9*Ö<‡ßàKL_`˜_W£ X›À|ŽôœUK _õíðFXØ}æÓ$˜ÒW’¾´›ßã`jÀäüX $l·ioG»Ô·)ZÊ¥Ìtû¹úEÜ]ê*-õM 4¸¢rÊ´üÓXfÀîNøG~…UÄ5õ\a°´\¿S2èS†Ð[BšAŸHuÆ‘eЗ8š®è\Û׸ñC½ñ£bÆÏ›°ÀšHjÏ{,tVªÕϬðÓ=ŽÖFŸICmÇ’åfÌ«¦…•F<‚!—ÁÔ ÍÎ÷3ަ]-´3èϸѧêœ4úÞ…b&£A“ô)Ù6øÐç÷]¤Ì.Ñh 3£èüÞÑnƒi0v¹5vEÜØ]Ñ *"¨ˆ”Ù%ç{®í¦nóm?rfº8B?W·Ë^Æô•½ŒûJ–١ίŸ¡`P}ùˆS0ÑÍ¡OGN”gÐçü†õk¹D#ÞAàe}ÉR0 ¸”™ù¾\ãhº¢s¿û¶ròwɨÏE5–ÌœŠ>åË&tÖ¸ùÅf˜ðOôÃ89]l䦄ó®‡ý’YkÎÁÿ-Vt®íÏxÏ›µç™¶‹ÿ÷ƒ’ê%L=(Wô)C=Eù–z*†>gÐŒ·hkÞšt˜oÓslUG­T€2ÜÞ@á!³Ö®×øs”®ÏÑÌ:¿ÞòôOчôо=¤§:ÿˆh¾íg¶çäýéV‹µË¡åä¡~Ì ¥ÏìÐÛGÍWt¦mWê©;þíŠ.­º}Ï”rªÊ†f¬½Û9å? ÁYk¾àóü3mS/pm/taÅœC_œ Îìï[âù.ü󂜭è*?“®‡jèrkÍn=Žè{lHó<¬èg²ç<éxXÑŸqÂ.»ø’óûGÒéÁGÍÓù¥ÉÂø’µû9N÷ÅÝ£ û~9¢ûÊÝ‚÷k’rK8Ê-–9×î·¢2šíù=é«i¼¯&s:¿4YËÍ÷sKæ|Ñ.){YØl{nÔn"±º‰2=÷t~¿ÚækÛ™1œbt_ŽbÍÑ}åÆüqNº˜ î~ÜÅ´¢/ñ¶Wª±Ü[ÐÓù¥½ceîlyÜâ=§¶çÍQÏïIôò?üîGÜ5F­k Ä]c+ú™CÇZn¥:¿A[¯rûûù‘£9Ó†òJsCŸr>=FÛ˜OoEg)Ö(Åù¶/›”|Ãåå_‚zµLhZf>xJ½óÿ}œ®—ËýötþÄË6ï:„ëíˆ[7ò4vjxY‚ ÚÝþÒº,7QÐÑ”Ò ÿ.‰£/ï¢éARň¦Ô¶ Ì }ÊÒ×÷Ú¶G·tu[zv}Û°TXï˜;’Mþ‘qTô6-®2¼n›ž3¾Ž<޶»Äx-L=¸‰œ;¦Rœ/ܰ?t¹ßý܉m2~k¯‘†0ÿþÖèóíózsM—Ít¯Júî³{£Ô1@Òºcið&=Íeã5>M‹6zÚ!ÓòN…ÜQe¸vôcŠÓÁWíGÁ×mÒ'„/ iÖ+¶ÀP( ¾m kK›ÛABÔžÆ ÐMiðFpÈ-Ié(„Ð:Áiðc'½ã ámVÅÒVú.NƒŸ»–_jŸ,¥nº|RIü¹M´¯¬f&qÒ;z‰£ô23Ú>(è£ß•%DÁn‰!íÑŽ9É¡û ýŒrèón…bæŸÝ mÅÊ ú²Ôª`Pû´"8€tUþwû2¿¿½ Žg ´è®UL™•rºm2V«ê¥Ugz ¢ò.Ü8:Ôsüøž;aZßöPávÌõü±SK²ïO?j¬Ó+¥ª—\Ûϵ’Ûæ y]qÓöˆIϹO¶uœ•IM!Aæ =hÏÌ÷y—§Q½ø/MÏǾQ„ žAïÒmkŽ$sªð‘ׂä¯,+Cj´§%³Úâ`\ ,w^RmÂ!.jmgÐ×7Õ#O§àÔ:Ñ÷"3ß>©[Ý¢@ìgø¢)CÕ£ÌJ=ß÷ú=Ø‹&õý„fÕ’ ú±L¹¶_§ZÛUhÁ˜kû—vÓµµÊCL1=á*ƒþܱzþ"‡FÓÐè¥:d® @$úBûÚÐÌ”w C‘Aok Ç‚×BÃM;Äà¢Tæ@¾œßY]hÉp²sÞ7K`ˆ£/»QC–ßÊÍØ°¨^¿f½¦JýVáʼ‘¨ÍS$λÖóÆÑ¿j\qP\¢Ú\K!2«ÅÓ÷m*7]iÑ-Z †cÐLŠ£w¢¾Îéø[Íé¼Ðvô¢qôs—nL%_nfHRÆQ„*•8ús›ÖŽMZ»sV4z‰êÞÏ$s¦î¨üœ[Ì÷\¡¢@¼¡jΠww¨ýáØeÅ·•¶meÅhæl¹ž÷£ÆÜ¨Q3j@ZOqæDöœ~–7ÂTa!'†¬{Žº©CË„r·ÿõúÖsÏ5”õ _íz¹Â\Ïoï¿;<(ÌïMO²èû–¥Ù¼e[Q6ú.q=‚œùØ«ÿ ¯gtl€IWœxf‡:=éu.*î1£<¤ŸQ‹8Úk¹Àµµ¼JPÍÌeÉh¦çNÏE..¸T™XŸ\&ÉÊœípó-OÅE‚©9”@ò’Ó9¸ôâh{‡J¯dÝ+ó ‚RÂÌj¹]vcŽ=e‡µ™/rÉšwÿüùr™’Ø'ªS†mvÔ²`™sz.¾½2Iô4zj\Ënʵ}ߥ`D¼4‰¡&@å’y =î·uÖÔ).-KmhÁ¦zó4x×Ð1ÔFí(s3öù®©âÈX¦Ê ‘D™=vÿØ¡Íl9í 0X’ÇLσžKÁ eø?}%K˜Y©^Ï%´mÖ8ñ!mu5”9ëþ~Ùµ C‘ùÝRèW3b™Q à0j {ǘF1c9åFÍ¿ ~þNzâÓÎÛ -¸U27cwOÏf`ÈN5ŒL)²üãè7nìÙ·¬cŒÍD·µ=» e(&×naîþ˜yÜ?C’£Õ%6Ëѽ ”d'P±¢ŸÏÛåÃJ+ï´g¿\ ±Š‰®”ŽqÆ:RMc»I#2g[_åŠáJÊ犌Lb/ûú?â5äL®=ä’’žMIìuW…Œ\Nˆ«œ°HÝTIìmWÙJlÚ•³« m!‚©Áéß{ßé˜â Yk~oWÎãdºÏm‘z–lx‹8Wªs›Ä>w¯ }‚¿©Æ8„Ãô8îŠãQà„6cÅÄl ½ÒcõJïNp+í(U€wiðiigœá°²Zø°\Òàmr¿=ø_`nþD@‰‚/;õ9b7ÇPóÉLÒà}0ÁkùIѪX²¿ù¶z„ìŽp—¥]!KYXu™nß·uÓÆþw¾J2IôožT—™ªÇΑEœÊud1¦ª¢í‡ôú:½{Á˜í6à²TM g%Òàmp]áðÎÕOk)›©%@¥»}Þªn[°Û޼4`èz•ž*ï—ðoäÚu}q}?pQC24 >o3$ ¹ºA1‘R±öXd¾ËvG2”@ÏÑëÍŒ%u¦ÛÞ 2QmÛmÏTj»ÍœX‘^a¡ÐüÇ.OÛ²_ž¶e(+>ƒ|¡ùŸŸˆb·,éG ÓàÇ»‚ôË#xGkR‹L·Ÿ» ä’tÍÚ6œ4-Oƒ÷dÌúßE3ò‚ Nƒ/FSêˆì ã²ë4M¼/4'«þ3`lâÕÐöé3ìrÞu›z=`®!’† ¡(ø²vÛÞ5ÌqÇÙ»¦ŸG2¶é;=HËÚcÈ㺚‹J6úMÎI?‹Ì€ÝÖ€‘‘²'ž—Ö¸Ä9Pâ*½«.Álwc8÷¬0ç†^ÈÌo©Ü?¯¤fæØ¤÷E3·½JƒŸ»ÏÒ¦Á¨DF[dÀŸ»×¸ig·ê×xÉK¶ŒÝ˜0'*›)PŠ¥Á§í~†¾*ÉH9écH‰2Óòy-CsäÛÔD†ßy\„êHöõ²?)Â~žI9ë–™Óó|}+ÀžÏI?ŽôíÚ`}Ûe~³[a__¶(Çd渷°n·tiÓöL“ýñÙçÐ×Ç›–™nXÏVzc5ÙÚ _oxms‹ª…¤N/’kȪý6Á5mdC7U 'ú_ê3,·H>·ól¥èßUz¾8/D™þÍ^Jöû™gë öš¼%†ÛerÍQð–Ž¥¤ÐZC–E†Lß6p¼©ä-*Ë…sŽ¢ã¤&Ve‰ó;¼ø aÈÇÑ£z`^êfõˆ~>Ÿ—³eÏ:ÿõï¿þóßû6pî½¢ÈÍ41¯±˜“"uðOmïT:CØ“aé¿P}  åÁü¯p^asëù:&¥€¶øÂ|áê)ç­˜Iþs…®Ø«oÅønû>PO%fð`¢ ÃQîC«²*P¡Rw,Š0‹ƒ/¸ÓÙë~¢—6”j¯ªFýŠçš"]ÔúÜn“€)«ë£õð¹eú4g–»›ðD'8i# ähE}ìˆF1õV<¡ÉIŸ\êh(O§ߨ™N_pm# 7±£Oœ·½Df:h”¤-í{ᣰ­×¦Î‹ $:œ-©(Ý5«›3:S·%»ÃOÜÞ¹¸ÓÅÐx¢Á5\º£Oì«rp08ô'æÙÔx”›çmâmQ‘}[˃³¾×?¤©›M´,ñ‰çv,løÅå3!ôî¨HK{ñ¹SüFÐs™²ªÍí5Q'uZù“~ñŸ@žRDBÒ¡EKÑ~Âk:zvçÚÒ8 ‘Jß|X6ö[âç·B Äù#iµITöâ²F…€5]<Ë,­´­áѺxUï¸OP“z솓 0.ùÆøÄíÍŠ¶ê’i””UßÇzq±Ÿ8Ý~]A¥ÏAÂæúÌ1üí”ÍGŸØ^¢––,¼qAa;AGŸ¸¬Ç·µ«É‹Žú¦EGŸØ96 ñÖyß„éÆpî{q[¶šúåÞP•€!Ë5ó‰ûºÀ‹rUmÔ½À“¬‡–NÓÑ'¿‚úÌÓh™ þÐÊŠÌ'žoï÷W^€ê:—p¸.>½˜´uBÖÐߨ&1(mS .‡Këc#;ådw˜#ÇRCÙ }d~ø“Ïþu‚Yù‹}ng¦žr<PÇ`R4™-ó*yº%@SÉÙÆ9™úÆe/z„‘“©™Ë¹îmŸŒÝñx\÷da„½úÁ&€¸~úW‡ßp•ȶ’ʼ‰‚+½Gí\–íÜÂîxLï[Raä4hô¯1!ÎE?ž…‡Ão<¼ÑçenCm’(Aƒ¤¨k8=ŽÚʦJÕ.ûÒ>§åصR–˜ÕR~ãÓÑc};z,‚AVñ®Ã¼Q‡ç×Çú 㥠߀#4zOB4ýá;Ÿü7¾B?œ,Gm‚K}¡áÔÜ7Ξ'Ìîl-i3¦úTéû`™Û¢9üÆeÍÔ7!¦ MgBLb$%]&vøë*RÔ‚^·P)®”yŒ)…}ãüö¨ùö¤9–êެѵ’¢êFÆl¿ç *CL~§õ£iKE¿]'‰ùœÄžß°Ì¹ÿ,¶™´É8Ê$ÖÓ儚’°šM0ZÚZ|Lbç{îg›C<´läIì.U¡¶ÚõÎZ¯ÚEÛ†½€é>ß7'£‘Nñ'ã`8¬$À’1ìi?I®ÓÎeµD±0ªX|Ž 8‹wç(ør$Ä\”iðõMÚšÂFzЦ 3w< ¾ÅuœÅ»Žs|?ÔÞÍüæG\¹ydŽ‚ŸqIfñ.ÉÆE™›wQæø"ùÈiÚv«¦m}JªÿÎ’øRÿ£ÏY)^ø’â£/qéÕæ]z5Ž¾Æ¥qÅ»4n}‹«ãþ?e×±ôºÊe_¥ «Ë¶ä4èÁ?¿_Õ9€$¡d…ºOß$,Ø|]åé2AÀ†Öú|«ãºÑ‡ÂúT&]kZO±3ÓFÜÄfÔw€~†TM`ƒ\_!×jûcfívT%?»ª¤}uKwVßÒnôÍ£ÞI¿Ô;ÝèÈ#àY xºÑ±[¯úVçs£­œ¼ØÏg™…ñ‘”øúÒ™ä €~ê+=a¼&NáR<€“&ïšqжÈUºšâ‡ÛvAÀ’vÀÄÌ ±> íèT“cúσз „Ž‚ŠtÀ¹¶μÊr«(}‡¥Ï6Õ47úRK¡¶ŸA 3àtˆ^AU/¨çƒznrxO Lü[ɾBÚ^}.7úTÊÆGA-%  q5‘x ÃªHÀj1ÝÞ"ÐM¯Ç~…Ôæ@¿!¢ƒ¾‘û‚{ ©ö@§ÃÝœkRW]4Mâ´LÅe±uÎZü:&Ú­qK¦.ŠTùT‹–~pÏ?ØHêÊ~kò¨BéЈË£#Bœ—Ì6Íj¡0=€ÅJÀvˆ@åÈPEìÆ2ô3Šg|·Rh)Žñf³qkaƒ°)’V\£úTÑ9ÏúTAµûT1àgˆ Ï ¾Þ~>º#™|s˲obY'8 òÊ~p⣀n߃¤n¥üð³²Y¼jNð$FÛiÕœàL¥»±É9Áo˜Š®Á× H‹¶S²¹ÑW’-„¾À4€Ž@J¶TÍŽab³T;ÃÄfôf/®aô3H‹Æô+HÇô;H‹´½øÄf=€¾©É€½­ß~ ç3Ôv$N4ýöéÁ ô$øÚ)ºÜèG¢ øÞZ;ÒMMfq]»Ñ/?S6£ß0ÉÖFðå6A˜d+€¾™²uÝ‚äbÀœ¯õ›>†p÷Ê“ !¼JgðãKÀ»dF²(úi „nÛòVr}æ!Öxh–1?ØP±ýÕÂZ”hÁ9%ï\òÍKtû}$DS`j ¸†dš†®(Oeê_Õµ\ÍØJ”!g¬B]Žv‚Ú¬±“‰&“êT:EšWE×´UG}‰J%¿W©óг©Â'í ­|Q™¥µÖެ$ ®á¶c+GcºÊz‘™s^ÖõœèCÈÕÔ7šäJU߈Pñ/Q¥f–kqPË¥ú›¸¦;ój‘Ám9ñŠÃ®œ&œeà¸_G’­œì‚dU3uªóšó÷ž«$ǽŠzËq£¢ÂUÛCgÊå(+K]tu¹èù˜eâ–q`­ϼ®Õs•'UÕ˜hì³@ßöY“aO5f¥‹AêO—-ÙÔ@=?–òçR°T;ˆ:ñŒ?Ÿ†wÈu(ÅöA¼²E™²½¢¨i‚ʌδñƒo¶ê2e”k}z‡±¼ÙûÁ‘u®(7¨>W2&9âËþæ>ƒ× @sÁ3‰ˆLt» hY(¸|TnÌÐíÇ^…&Ããf{©ð8Â$cE•ùÁký›öBJ'¤ñü’±ýdu>``Ì/«*@:œÕÖ”umMëúà^9ƒß6›Š¼œÉ·›#q9[j’ßÙÄŠõO{nË5£ ÌÆ¢JçmÉ{íïÖ|(fÔi™ ÓùÙëŽ蛽BÍæR+£²Æ] |­kt¬y˜Ua±Ù€qÓ,{‰mòT¼ÒÁì¶Mùãþx^^±JV=²bè©4 Â0ˆ…:v^¬Íì×d>%gÎ'œgƒ¿ÝÈÂ~1lŒÙÐî^™6¶6(±ÈF<Ô{ü넽[Œ"tÍÕ‘÷„”'ÝLK?öá窘eqænâ„}z©*R>ñôÈsq„ZÌ÷Õžý}+Ô2Ÿß^VtH®\çµq±k(ŠbÿÀCÃpþÙ_gðÕbðT¢Ð«’¼Ë²—àžÁ·o}rj‚–¶lºmÒgÍc©*¬ ¸T,#z Ûñáf!SÁÌù¥jYÅ]ÖÐòý›FÀ´¬hÄmUÔ~XD±”šA‹nW£4ÐíC¹‹¸Ö5ªåRX©¶øµø†´m¹a‹0Uøý]=Uî‹â Hü'ÈÅ¢P¬ŸÆ67n3ÿ1°2Žþ»Î¶ÉÚ“cžæ>_ò´ú ¾‘L:šý€ò¹ì:f8²IÖz_IÚ N‘¶ð/’•nÔLU„$Ì_­8¾háß&Sqc¹ &B(Y.fŽØßÙ0{üëà](PÓuK7Ý~®7¡ÃM·ÑôÃT¡ú@#p¿äSò‘dœt’؈¥¼?VÅŸÁGfE  uÂ2L•sØ7“¤hhŒ"¸žm*Þ£”LÔxêÅ?ÓüwiÔß™—KߊW<Ÿ÷ÿu<.·‹ű~þüèʂՕ\d¨"I^4ûÚ>ƒÂãÚ²©?=_ðHØÀ‡Ý}ëåù£e¹eËúIª[ÎxÖÝŽõ˜ÿ1-3“a(ǼLâÎwÞÇ3X×U™܈L뤘O‡%OÙäk…G“W™o[R‚«Š1fî?-019ö,¹6Þ÷¬£öLÖ´r¦êüßã ÏuÁ™ü¶ÆL6Ö.Ñ2ꆦ'=ðM‚ÈŸŸyß\‡‚$lÎ&Ä€¦‘ýù÷gÍ`ÒÓÍÊ ³ ¥å°sõ8Ðz‘™ë¶Š:aLjîÆæ øZÚÌþ«“*Ó\%\ëd 1=€?2hɤéBç¢Ê”ë>q_¡=•ȾÛé@…)e%f#Êë¹çМ?Ötƒ?VºÁHÅÝ ÁKÒÀæ2¦öÏ?ºç91!E XŒY‹f¨ç¯#'ŠŠÙ›—YÊZšÉ²i`‘¯ÆÖ”mk Œ˜µf³–#´­µ~ÿè/†uF'ÕéÓçóiIO€Õr»úž8Ô­äÐF íG÷|»¶ónAM= Ìš©Mÿla9³ÇÜtF°ÇV“ûwãÏ¡ÆÇö™Äá€:@=­À¾ÖÞçÕ ¯³³ýa.ûsß‚V€ûÁ‘Û 0—8c·ñâ.ãußÝV€»¬À üp[î²'ðÓm¼¸ËxÀ/·à.+p¿ƒö§ÉÅ}s×A|F_ƒjÛcB˜Ë„œÑ‘Û|q—ù:£Ã&Ø>Â]&䌛6!PÏ=&„»LÈýãÀ÷ö™î2!gôÕm¸ËœÑ· ñƒNC a.rF‡M„›¨çuÜ&ös½<ï¯kt×…äw¯Ÿ;nËŽt¡ƒäq[Í­ dÛÖ¹ ‡à6ŽúnÓÓHg°.+˜íòšì§¹ ýXÉÔtïÊ )Ð3k?u²T#€>èr‚Ãñ3‹õ–§ÓÄ¡¶ƒr ôÅÞ!8xµ\Btšôk€GޱGÎ 2Éh¹Ù®æb‡¿Ñã‚LÚ$½†dëb"ûO–½|óÛ¢Á¶Eð—úšNµ—‘ÔªIŪÇqðƒcÈ–tG[âßCa LØ#µ@ ~Z¤©Šyu¦—ŸÇl+Vº^ãûãùPœÏo:rµFñæ—NJ1Û¨ØÒpÎØ›EíýEGÞ"Úo‰êgltfº^ý¤’éz¹¢Æöxy’ðf‰¼÷Ý?kò “Ÿpñë%ñb{ŸMsÅ’¡çe•óü<ûÿ7folQŠŸ±¯ÃšV¤¸¯í0ôHÌyïo÷mQ·Ó5>¯ò1’¡é(ÖÆÅâ2W逅0á¤ê‹ŸÂ¾Zà‚[ o8§¸Ýž=ðíxö2ì`ìUڥDzÌÉ޾鋙ŠQôŨ”v?8>“—Š7^“wm–ûÁvHL 1³2+Ϋm…÷ðQ~Q̶ªÒÔ¬ËÉ žMsݶ~ðÓÆQ#½!ÁxLrqx~ðë¹ÌTJ€:4³™ÎˆwC=R`ÂÞV·Õy[Âûœ‹C ÝÄ«'È™Ž\«êi:ò>o—ʶÒÑe·µ^&ÒW’²¾®üÝ>Rîiã¼…K„uÍg±C?8:hFJûfˆÙ\I|»Œ‹cè›>ÅDˆ}Ê”TU=¶þErÓéÁªPEæAä†7Ïò¶«jÌ{ÿ¹©+lvÖeB6b]&SÊ Û‡„ÍãÍ5›u9M1êÚv>Õë‹·¥Ð£cî—D\û—óÛ cFý[RW×|1Moc.§óJ¬ðóŸ¿Núâ©®ük;ò$ù0™ä“YI>pdÑÎ[…©MSíÇû½51|Ú0¨,–¤ûtþC?ZEøÔ¥W¦šøʆþƒÄAXõÇžaªõdôÆP7¡j©q3ùwUt ‹Ö¶Jgà©ÄCÑ‘m®øe%nÕý<Ã\ÌÙì7°ÑûK‚G+UÉnWŸ2ûàtòÏv|±d$4q•XhÙL&2´q û!›Ž\'ÆÒ5ûnÁxnÿ˜"Úª CYÐ *G„è–ëG«7uõiŸf’WSæZž·øxmTW!󖥇·l9;¯`|³]±„êÜV^.s›ö³Ø–³Yþ=ÛÇ6ÍËT8‰Ç'?îÁƒœ}Zœp?øþåÇ5 N²ÛŸDÒ ÏÀ„=Éo™z­±:+TÏ~ZžAé•4oàEùâŽßÉ~sµU/¢…L\|©bfûmü?\!_„¹óŠ¿.’5‹ì¯qØ)R1ÝY5!TW°J4[×ß•ß@¾ÆV®Er¤LSR ãÛóWQ(Ž2Ѹh»*&´TUŸè蟔˔sÍy%î%džp[­ËjXrÔ:û$•ý^s kR3΋l!~ðAˆG=ªð&”Êh$EeâGv:¦tej-ÅÚŽÝ8øÁñ·®3Y¹{â<éêjöƒïÖ„a£õ§ÓuÊž’®Z~ìwî/ý 2£ûøÁ¶5S:>Zˆ'C<ÇC]~ðñæ+nûLqÛJð˜!’à¿-yâõ6%3«¦¡ê“9ͬ-Gmâ3¢ –¨ÌQJ вQ˜?}ý”Vj% -ëÄiM `¾Í昵^I¾Ò¤o¨íÓ%ËfÌtd›š2m]…QÕ}°D×PƒJßÓ[K +ë­Õt–Ùõn'JJŸƒÎÚïhžÑ¡wÚK[ŽÚdéç„…{™­.S¤²blôóøþ'òvbÞÒ4åbcy}ï—5n\ÙV½Cxƒ>÷û+ATžâÆ_ÂÅ[¾§Ðþº]¬²@ÅEÊ´Dp[ÎUV£裰˜*®3G’8J NÄzR}È;¡§žuÙ†¶”&¦+Ý”¬Cás?M=°Ru¨a6Ä2™&6Ó2ž¹¸Œ¦ž ô}_-ÆíÍtF™ÇOµL žôA™G¢e¹“.:&óGY5¦`Û¯½€UÒ8ä&MM éôÉÒ†èÂò¶Ø¡©ÎÁTÆŠ~ò¬Å)°R¿é ¶‚eE¥0pZÍÀ‰_¿.y†JAY"iZè|o£õgÖ—Ûâð–+Rdê€ýG_—­’®·ÖÉJšzVKl;)u%òöeª’¦ë ëßÕf2½B¹&(û´â8/‹œî¥Ö.ôã\j]jéóvÄ£Øß p*®‚PŠ©YzÎŒõ—‘¡>Mû¬ë·Õr‹£ËõùPûb}ÁRÉ0âX“"Xåî9ƒí³Áh‰j±<Ïë~Þj—àh¯‡Ñ‘!fâå22”µÕž¨æÇ!á˜ýžx{]Ä(ðãXT¢59Ta V{v`GkzìÅÞ,#VÂb™¦,Ó±è÷ØÎ }Qu)JeZ„–ºnö}yÂÆ_Ê.†n˜Ie—|éÒûÛ½ ËPÓ°–ÉÚ%¯7Ù®3öPTbÊŽV4†Ç¥Äx¿#°O‹ˆTªœ­ç/ßOón9NØ×~›Ö24&÷¦$M9.mGêž÷[!Rn+¶ˆá‘Š;JYúׯå«Ó{à Ë=4©l“ÆÒ•Û_R¯vâ2å~ðíX4ªƒhæÅ– ¸Z›žÇ5Š/×G/iÍ2‘’M \ªër^e/öf9˜Ý k¬'Y·NØÈ–Q×9ÝgÞð…÷¬ê /6þV{-Ötÿ$Y’¥Ø•ÏØû×ëv¦ê5¸®ëÅ}X9D?n%–4D¬Ö£û< é¨}(ÆË8Åk·õ÷µ›™é ¹åë6›{Ò/Cƒñ'÷bßG(Ö,’TGÈŒq7,x“Õu¬£ZXªÝŠú•ÊT”›Z˜|Ô KUÃêUqFfÄíçÚ¶BÒc´º?H3âA|áÁ¶/’ys …“f鋱πý5C¨Ûlgð}m•­ÒÅ@z‚±Òm˜ñíñ¾?u$êjW>z£´ØheŽ@ëc¥½»c¥Ì+=ƒïîp's„;Ïàp ó3\f~p0Ð:-‡­X$w¨”£eYŠt"‡P©} †i!t0ÐÊ3Ù¼ñÔ(2òr™–¾B²=aï·ëíy½)oÒûÀo\͹æ_×…BãB áéîÈ:ƒoøPú!æ,GÏÎÞîënqœR#([®—´aM €µäÇ,j¸ßË.EbKr6ÒŒÏà»Õ2Y ²ÛháL&Ø~ßü²ädíöÄ„½ûàdZ~~±ôÿ_eW²+«nEçùŠ;Œ” (Ógv¤(£{¥÷ô”Q”EÆ4EW€Þ×Ç­ííéÌVŒÛ½Ö^›lfׄ¼ó<%À§Š¤GÕ¯ßöØ@›ñ§YÞNÇ×j xO›ÉÊ'G|çM…0ˢ˜1äè4%S9§G½úq™ÕXÀ&L¾$ÃÀêh‘ª)H ü((ɲtÞ=ÝE耾æÙ`"­¹(zefàx Ð{{—ü"YpŒ·ÍJ¨¯Ÿ!FЬ&„IÝeÝ:Me³¼ó²9$ Zú+ÿyø+WòÉ鈭‡ü¹@ïžkHñÁ"ÌžÄ`iÖç}±è–W%I^žš[¯å²€m‹»%j¼JL†·rt³.˜³d;ÀšâhjhpÍ ó~Å nõ†ým gIþÍ$º ›I×TðÅÒTWàn¤IºŽ¢çc~ú¡ùÜùÈ=§6ýú)c˜÷$g“ŒlbÅ#/J»6½a_™ÁV¥ã:QÁ¾Mo˜Øô†‡°^ ³z±÷äYVn×dº,$É«)ÞÇÍV‹ñ-Òc)xOاà2ù4ï"Þ9¶ˆÛ½ˆ¡n86µ"zLºDÕc&Wä\DÉS1½teÝÚ]&Óc 3û2¾æÉܲLhÝðö]]…–×»í]SͤóÓ F¶2D#1ƒÝ “K.œÍÊ<É^Íû(ƪ{¶Fd0ƒý‹÷œ¨»ÈV IºiZÆxçÀ¦ ¨*3XSaf+€T'ô˜qŠ’©àèÊNbaKê®.Šqz-C¼óµÂ –'+Q+¥®³&-ÞÀ qôMO¼éÚÒô}Ö¶Í´ pÛèVqäŠ~5Ï資k«W5ChÏV°j>ö÷ >Àôx°ðá¹@CüÚ ^è½# ÖVÉkmAèØ"ºX`AÚ$YFáØ}ްd£9ŠÐëÐèZ?0—•*Ûµx¾«z]Û7ðÅk“M€m{6ÉÆzoß&ºH ¶X6±ök(4K6!Ù€z-ÒÈ&Dý@!›XÈ  c‹d#'’, ëã} Pºáû}IzçŠ UægU&͉µˆ¼Ð÷ýèž]Ê™q¦yä>|LóØI3 ´ÙÅŒEK:©À& ›ÎCÓ°û»Å®„#]QˆÚ0tõݲÔtĺ?ë]³i‰ˆšñ|¶u!}7|ÌXÿš}ŒËÍküEæ*2:]ŒØàZyŸßeåõ~Y›®/Ì}Zm ˆ‹œoº,f°ÝÔhÙîiКÁvKƒÊ 68£ 6¡ 6øŸ ¶ÛŸÊîf »™ð­¬^K´ÝÊ`Ð6'ƒâ8ÝÄ®x.ºiUN§w.?æ2¨!aµ)—ÝóUÅ¢{mcÆ`›©ÆY~äÂ)X÷RàQX›‹3ÕçÃ*¦‡H^ÁÞåW{íºiJ¦äU6ÄŒ½Ë¯H%%c]Gß·ÎêcoW°ÁuNå{ؾ ÕÐ¥~1÷³XÀ¾¤M¶©dðHÏFt„ö'šCÁŠIñë4£¶ó']®éT~¾ÍíÆ·g&ÒɆ=sÉìR`l8‡ô"|~%Ã=C—Ð}ÈÍx¯G)À$—9×ìºQ%§í!¿RÁÒ"[²Ù,ò-˜Þ´ïû¹}uí^ùûqà‰@:oè'rKp3Œ¢Çxšòu¯è«ŸB=éKpò˜ƒ§bóaìÆ·|Ia ÈXŠ?§aX†¡ËŽÀ· ö®-—ÒŒ€Nã"ÇlÁÏ öÏÉ6E¾UW§ï<ïd¢Çý-¼…Ç£§ @q5/ þÇiÀÈê£2ìà0Ä©Dôão?îÉ–€›Jeû »§Šõ'ìÎ*‹í'ìþ*Ö§°»¬X»ÓîµBl?!—+‘ÂOWM½„é.Z­U¿ö‰æ'®ÃI˜S‹êb• _sŠ“©ÚóÂ5à{)RÈÐ8Ò„—ÂÉÌ`÷X)ù@ñ7¶l$K­¯d?ÊkÀ§%¼ÛøFXÊn{µ¯¼]Í`±¯|qÃÆ;囜¤LÆ÷@çr÷6ƒƒK>¥¸2rMàšŽíÒ&][™ÁòS !KÙiOÌ*èôå„àS]Tj¿.b!qk ™HKŸ›]“KéSŸC;´+†{Û\„ºŽàÍc LfFOLY|èÇyŒñ.“N-ý\í4õëžà§C£ÃêAäîìS× ‹1¯]Ò–zs"Ü/A›´¯nælú¼ê|ÐB9ðs‘J{\lU¦ÊnÜ¿ 7'Â/Q÷OJYÛE™7ãpH)uè³Ë‹¸Â[9š~LÒ)Ùö:txEoR†~7i•¬Úòff+¥ì¦,¯Žõüžé -Ë@Çg–2cçc)á«ç$ŸÓÏq¶×­)ŽžG'*~FŸ½¾TŸ¨ ¾Œ¬Txk»zŸ¨ ¾ìé|¢2ø°„'* ¯z¨<ºZyôÁ Žôô?Qé Ø@•„× ÇJ£Wú¡§ð‰JáëО¨$¼m á‰JÂëОžŒnU2Z‡öõ>Q)|:°RøÀç~„z Ÿ¨¾Y)|¨íXO£·*®[S=…ߪ¾m á[•„ס­\áió‹P„\~WðÃ{fŒžîžf0ÒƒÉn°kc€ðb{6f¬Ì`_ß29Z&fp`£½* åP&h9Ò¿39ÞÇï4qÞ x쇣G“ 4ýxh¦–¨NÜÒ¥-iH “ídxG“ ½€h÷| §·¦Mp=N+3.»d‹¢‡ƒéŽŒ­KÄ¢ éD=û4CKFÖ•˜Áöõ¥5ƒ½«y0šs>Ñ«õÙ$=Þl|;Ÿ¹‚ 5‰s—J‹UµäÉg¯Ñ bÑÑIwG)ò:?L|Uì©ú©(ÏVnËÚ2Ð ¤:žUìÕ™‹½,ßr,îUºgòªØköq)Êžp,ýÀÍÒu@_Ý}¹pEd’!Iòò“7{ֳР/XÉØž¹I>ô ݯfltIòÂÛÍžeLc…—Ïhî«XJ~ÿ%¿ï^®\õ6£í–*Ý)°0gÝ2!—¥Y÷j+(Dûˆøñæqq§v´…H/gyÏý2½§ñSï)`°¬0óÛŸ›bA,t\±âºO—Ô võÊ_¢*Ï`AÊ_¢*5`»òw1ƒ]«x·5ƒ=«l˜˜Ávå/ðØ^Ûªú[ 8´Ê†wŽô²áV• kÀ±U» ¼óÃfr:ä/mPþ¶ªòW‡6(‰ªü=£})‰ªüÕ€‘^¼KTñ®ìZ%´Ä öôâ]¢Šw5`ß ƒXõ·À;”¿DUþjÀ‘^@KT­[µ»ÀcßîÔå­é³úV‡~~UëÐÈ9nˆ´kUßBïíÙÂzoßA™!´]ù ½whS߶ТÙô³í c sÕ ëÖ«iÙ˜"< ê†UåÊ_ ÏíÊ_¨×¤òÒîB½æ[µ»Ð“Ví.0K„õ=¤Ýݵ::tdÕîBmÇ–Ttü>Ð~È ùð0A|—úh“âñ{1ƒå‘ô§mvZ´åŒ.*Í'O·c?öDü)Ì0 ÇQ!¸: ü!C–¥Íº˜ÁȪWÞfˆû@þ# ù>ð/ò Ña™ÈßäÓÔåà ¸¾çÜÃ`äj›].½>Dn,TYÎ7[Þ†¨ëFŽçÈô=ÿÑ1dïõ§3¼Ë æ¼Ãüóc6¿KÎÌ:š–•¼•Óî¥\õˆêªçz^9‘ÏGXùùÕÏOFVK> e÷,jçf¼{÷¥j³ïq7@¡ãˆ¤õ³•ŒX RAÉ›|ÙÑ%ñyÄjT,R-ZØûn-týžX×vªŽv½Gˆ¨jpºœ‚4Ëb#+SR™Á®•)Àž•ëÀ¾…ê8È 8°ŠþŽž/r&NáÙù§0åÊp¾É1&º··Ïy ·ÛíNí†^èűðÈä³}Í|€þ.”ZlFÓÇ_>˜Íéç2“Òð ʃ¨”Çå"ˆl!*Ù¢[gæ~ÀÑ€] jJ©šâ†þÃ÷D‘yï¡yì«÷ðÕ¹ø ”øÎzød¬#k49À‘ïÄ‘Aæ íô{·EŽëúRÞÚ鉌ÀøÑyïñüà8®È.Š¿¹÷´pB{Q÷ ˜f™Ç ]ˆùž\{;³ÃôH»±6^!±R .ío÷<Ã~ãVnlYÌM:}šº˜ßi±óå:4:g )5†“üÞæç%}öƒ'ÇtöÁ7ý²…:WÝ3Üh6cŒu—µhÀèf¥ÉÛ•fñH·[iú üØ e÷9ªX%~†ò3ô£kãm~û(ô·Èû,øæ/f0âÔ§°²×+—1,FítÍ»m^ô´²ƒ(@t×±…LÖÝ*àÀ²Jœç¥øO“ÎriÅóÂÈœ”Ùëè[><3=†³Îfz{>µù1¼\°Ð¡ì3äK •³\vvµ´U÷~ùüÚEógð)«LWÕ¹Qª:ŸÁ§“4Ücûw¦Kq€± ßlyÔC¨åVÓrD·×‘USô×,¹ë Ž”^R»ªnòg_׸øñÇ¿þøñŸþƒÂþNW_þÿ¿?þý£q….¶„Ó-Šþž˜+lÀ‹àeÖTôÚØ¿ªfzÿ_¿‡Äï}mÏ'Yþ|Ïg‡»Ïhý½ó“ñùp~SúdS–}=½Šoþ’x&®íã¿Tîï8eãW뫲ý’wé-Q#Cdkí½5¯]•õó7 ýåOÓKC&@regina-4.96/engine/data/census/CMakeLists.txt000644 000765 000024 00000001626 12400021264 021022 0ustar00babstaff000000 000000 SET(CENSUSDATADIR ${PKGDATADIR}/data/census) INCLUDE_DIRECTORIES(${ENGINE_INCLUDES}) ADD_EXECUTABLE(mkcensusdb mkcensusdb.cpp ../../utilities/zstream.cpp) TARGET_LINK_LIBRARIES(mkcensusdb ${ZLIB_LIBRARIES} ${TOKYOCABINET_LIBRARIES}) SET(censusdata_DATA closed-hyp-census-full.tdb closed-nor-census-11.tdb closed-or-census-11.tdb cusped-hyp-nor-census-9.tdb cusped-hyp-or-census-9.tdb hyp-knot-link-census.tdb ) FOREACH(db ${censusdata_DATA}) STRING(REGEX REPLACE [.]tdb$ .dat.gz siglist ${db}) ADD_CUSTOM_COMMAND(OUTPUT ${db} DEPENDS mkcensusdb ${siglist} COMMAND mkcensusdb ${PROJECT_SOURCE_DIR}/engine/data/census/${siglist} ${PROJECT_BINARY_DIR}/engine/data/census/${db} ) INSTALL( FILES ${PROJECT_BINARY_DIR}/engine/data/census/${db} DESTINATION ${CENSUSDATADIR} COMPONENT Runtime) ENDFOREACH(db) ADD_CUSTOM_TARGET(censusdata ALL DEPENDS ${censusdata_DATA}) regina-4.96/engine/data/census/cusped-hyp-nor-census-9.dat.gz000644 000765 000024 00002776415 12400005715 023740 0ustar00babstaff000000 000000 ‹$ çScusped-hyp-nor-census-9.dattœK’¤8†÷}Š6› ÏÙõ>Ë,ë∈›Ó\€ !EW׆/õòßÝådå=c]ùïøx<þýßÿ'ø§ø-òõ Ÿê˜z\Êú ¨Õïø€OÍh¼Ëá)±G+ò žÞFËë'>5£q £‘‡=ÚÐõøÔŒ¶Í0_r¬­úùÓçEY–mÛðãAx‚ÿzèº,–Žshœà·gJñf tWeµr†€^@·òAxÃ:."=8SÒ”“œ6=Fz™4ÉßCk9Z(ÀG>ƒx4p×QK—âhúZÄš•<ôÌj3Àn±AWQìYÇŠà6€8òŒ!\Í.e î•]„Ò€UùApiÁ·qT  éÍ8ç m`Œˆ^ÒZäòž³½¾,{Wô2x ëè^ôÒÕ{Ú» o] ê¿‚kWÏÏsB@ hc-‚Ѐ±(ÆAt¼mõà$¹/pzçoäuÁJo^/6 ¸ žuaZ\¯Ê}ðôjeµ‘ÞWÞ4M‹à²òüó|›®®+W&DoWÙPqqÑ<±æÕV! —éæ kPÓ"¯ª\·o]••ú‹àè*ך?ó‚«3äùn’»‚¹Z‡W#æ3d¸ ¢ŽïΦ‘[œ‹j™Á¯Lp æÅ[¬®¡6¯\·Ho-T†kU" ’äÖ¦UùÊwÉ#òx;CpÉWà %€ðÞU^× ù§þù£ö¸¢¬ªJe÷¶› _êŸÿþ°úª‚?ë¬ENöó·`ºWCö32rcBï};£7&Å Y¸³c.]Ϲ@YìÝ7M,>Y¥àK%’´Knl=²tgE¥ÌRñYmÆf}Ù}íºRˆÎÚE_lFlVo“aÔfbÓvÙYhÍ¥Us1í¢}.ð« öˆ v¨(¸j¤ ÛÄ>—àœ‹½Ý.ñèw®!ñèw®!ñèw®!ñ¯ÁŒÝæRë0¦—¹¨†ÐnÝvbê[C­·Ô8õ´k×rAFn6Ûí’D>›íöL"ïxzMcÿ< #ŽFàgiê×H"s×ÛyFüë3ÌoÖ,ñŽ7 dŽ]€¯/é>æŽ ìñe<ŽÌÕAËü:ôÈÜyBŸAèŸç‚ÌöÝœmí ‰6tãv±¹æ—A®R¾Ñ+[äSÊYxÍ/B°7䞃9 äSñ>Íp²8˜ÊYŸß¿ ºb3Ÿó K¦Û•C¹ÊYj­¯b›Ðó¼ú'+ϼ» dÄΟ¯fjYëݬóîÁ¬œ,Þó²Ykíy÷`vNnUu`æiçä‘u–ž6ƒÅSlé3³ì¹ò¹2,x\V¯Ï§00¸íº %äjµI¹2¶"#×ÛöÙÇœ•ÌuÀŠVÓ.¼íªý ŠB1Z®lžUiFÂÈaP¢À9ŽDï=”'qè(/åFusdô®ncÚYž=*,²U’Z¥ƒÅ÷¾*€Eö—¥Ò}†NŸŸiYàÐK­ÝñÌgê›#³«Ócç¤AâøÙP=ìŽsªEm3xâý° <íõè0ÏpÓF‰ëÀ“xÿ.䄌ܫZ­±m >±mO'J|9yžKuˆ§ôáÄÑk™—¸ñ7I¡c…{žà/²i6ЖRG#Y,¬˜Á~UuSjŸ‡*^zÞXûÓ»8¥¡3ÏüØ)uu/ø¬/[(µö€½ÚlxCŸa`Û ÖÀ‡çgæŽ÷· ö&N;U§}¶ ÙM£CÛ0u´§¶aêØ¥ÝæN4¢ÎxB´³¶udªýߣÂnÛêÕF¡;Ϧe:Æ"wß”Åül ]L<þ¹1+·=ÖP.ƒ—ÌÉÃ^ø`’xòIJè<‘>ܘ†<ñFFîùEç‚$só ä‚72«?óRJ|xæyä‚0Æ'¹@® ê2¡JEÍB7'o*'0Þ-V jØÆiƒv+ÏkÆ–¯2re…(F®Ûen;ÁÆöƒÌi·è>Ó«ïj캾ÛVdÄš§|ŠU;ãS1–†‘šŸ?ÿ÷Ö^×5\˵*›oøöªùùÞÓä;]—¢€HVš– ëBÏ?ÿéž¾dQL=RjÑ­’ŸOehxÒªTãÂE[Ë6¤‘KU¦=iìÒׄ4¹Óª“¦.Uùý¤ÙAË}Î/µ ¿¸±ÆðŸ¿l7¥¾T›;b°Ö’¯,j°Ç"YÍ[ƒ‰ƒ97CÔÁýré öߟ_}‰Q×úVhÓS#(ÔŸß|WYß µ†Kä­å§ÈÔ#òÆùÈ õˆ¬E'õˆÜºæœ$Òh·æAÛNªühÚÆ–9æEœÆ¤(²E[RÙ¢‡)é)òÅ*S }.Ï×jwù­qIäó¸ ½K(êy34¼S>3Ž42³ÚÇ]†¹ù”/ùgFz×WœúÆ>}×Sßø›¾©O_C}ú ¤>}¤w}ù©oìÓ—ŸúÆ>}ù©oìêÛ}¯·wb·Fâê;}WßÙ蛸úÎFßÄÕ¼Þqmørÿî“õ–#%÷Ø?£;óÆþ™2olâ°Fðð&øÃÛƒ‡ÏÛåaàáóvyX#xø¼]Ö7khÖsV×c‚À§?gø4â笟Füœn;÷ þ|ͱ+RG#Ueè¶ÔßvžW¤äûëûAèߢ÷ØB·í†y#ðä óFyÆEŸ bϸè“Aì÷ÉcE‰ß'k$~[m­Ö(ýbgíÏAêY¯òçcΙ/ŽÄ9çì[ÁœÉã[ ¤¾9ë¶Á·9 ¤wÄ¡!>Ä¡ùæW-”Qä›_mé]ßõ°ñù•¢»­HøÅVZ}±•VDßbA·¿Å‚ÔãWûоùÕnäÛœµ é·9¯H}þ¬g•}ógŽÔ§Ì™>¾iÔ#õ­WÓàÛz%ÒsïVG,¨Gù²ì»äyiÔ|~þþ…–ªmÙÍ]£÷_zúÕ•>kÞñ)µé\ò¾ï‘†'­Á¯T y/FVÍo„V¢Ç¼îÝ7«¶$½W›ŠÊé]ç'¥Vño‰öc¥ž#…:áªÿ‘š#…žc}¿z)Ô°Ìjî/LωUÉlÃ4ŽŸéQ¨ƒY­Œ%ú¢× 'Íì§lÖµÊa‡s:ãO(ƒhx1Öqà€×ŒÛnèÈ2ånÁÞ‡9¢«)KÝvã²gDzš²Ôm«¥\Y7! oK*›òihd/©PKÚZ¤XØé¶íRÕ,_&–cÍÊe•Ï"MklRÝõrÁ^[®eH®t_‘T™éÃM¬P)KÝó³gÕ )5s†Y©+— ix[ѲŒ7²Vôæ‹\C[+‚×p‡C§·A˜M¬ãú€D3—¶š ¤]VÛJÉ _ žô\Ñ£s»µ­0=‡ÖzÛ™½ŠÊÐÈ¢«,ËòùAjë;Íl+§éY¸ëIU}?¼Ù4!M-:(3Wå)„Êçï_v¤ðªÖŒ ¡r1ô¤ò]ý~Xi^´í·áã–v ü»™ÚvÎ[–ë;ƒðᦸoèë©s“±ñÚô¹wz£Ü©s“Q¼¸þãÖ|CêÌùõ¹´ÅøÖ¶^†©Y^©}pûäKŽ4Âm,=бÙÖ)¦JÝsþþ”ëÛ´=Såî³S7MªnDšºwu‰4³¢LJÅ¿5fß!ñZc™‡)uéhÚÚÖP)§ÉõÖ¿‚9!=¬×K¿E°Dz‹àâŒà~‹`CÞŠ¹GY1Ú7¢fKƒÔ‰àW;UH=üžºÌt‡ô[êFpSO¦kŒà‹ÏVzÅ¡•ßÏ)q|v^W¤ÔõÙÒôšk=È ýú®øˆ4r/“vŸ /ú³cORUÒ2@¯;4Û÷$Ñ CÅßH/úkÏ‚ËÈ)µ.E_µý>«ëm¼ƒ±Å´½ù¬b4¹ô|h$ŒF©«7¥ß4ZÒÛ…0j”~Ñh÷ÉÔ§‘<5J]„Ñ(u5âF£Ô—e•†úJ/´ªŠ#RøøÜ°ddöIû‚S{{ä½ÊÖ0çÈÚ¯®ñ ãFä[ü ¤¾ø5m}ñ+‘ÚñË1~#â‹_~Äodçï‹?ëqé7–H‰{…©ý9¢ßüY÷~ógÔíy÷ç(´övݶ\'¾èVY îõè8õ•Î*Qä9ö­b¶ )unL÷|«¿ñµ¯(¶#ŽP3¡¢Ø—Í Ñï+Šo jZO=_Þ"PQ|UÐøó¬3a”¸þ<öç#R¢ÔÛöôöÌãú˜ ¾?¾ØJk?\[©ã¦Üm?.¶²Ž› RûlÆñ¸{ê͹⇭⇵[á ,±ÁÅj¸'(å˪¯©b«Þ¼ÒÒsÎGÏ"oû±C"…YIU}±¼FÝ®1Öã#¾æbÏÞÓº5ûû¼Øs «²éµ‚ñ=Ê€ªƒk6¤ö™PôÝüM[ûLÈ·±¨ôq#ö¾Ì‘‡çÄÑ· ÕYûr¬<|2޽—î‡×ʼn¿g•€z=–Ÿ=§Þ¬rÎ9ó¶=ÆMö¸xÕ¤¯Ç’àK,èkõ„|Ë+R'oð=âÛaϼ‘7op̉¯r¯ä ¹TÁGçGB=Ö(ø±;'V徯ˆ³…Õ:&W¯;£›IÁy‰ÚþþùÕßí¨½ >ÊÒUbåöóž¢e¬…XHbOÏK!Ší…Ôè«Ï‹ê|”ÞÚæ¢yë¶ö®q¶ý|X…Ôþ†> lY‹”^Î1Uýžû÷6ikÅ̰=åK–¤Ä©‘fnÚ^Ï@õ^Aíú&î¹m˜§¦Ô5a’º;¬¦úT—d•ýkFJ,úºQzË¢Ë6èJ&õÜ4À‡´Ë¸"5Yl%æ‚m‚#µ{¦çà[Ï©¯ç)µòäkûyŸL=µ™ª(òE¿ÌI‰åWû±mdõ¨-™’«F«:‡»nHC«ÞÈ•¸…΢)¹¼"Æõ–Gýœzb°Å{Æ”ú.¿×##¥á-ç€5rÆ7}ZL#o•Û¶å€ÔŽPýiÞÙÓØ:/˜@´O¦‰ç–¢e¼­7¤·[Š‘uûušXq´gQ¦þ̦çк-Pûc›ik[’WLT—YÅvE1ÉQè ì&7¯[§k•ÔŠ£=#å"Xy#ÍìŒTí• {¶Rr›óôþè{—4óí°L>kÓÖ¾áèÙ´VMƒs»ö:¾µ Ó·©uGYím{ø û‰Ô¾ƒæC÷y= M=Y¬‘at[7ÔóVCÛŒ|¡Z…,¸ä̧·g^o?σÙÕÛ±í©QúîÆæeÀÎYü…êØÏ0nÞ®c?KìêËìtš¦ÞNî;]–~Ûé$RêÉ9àÏYæ;żû=çœßÚ§yœb²ÌûÎÌZƒÁãaÍÙD¼p Ìç?Gæ‡HéäG×ÞÁåóŸKe.ŸWzfïj¯å0ŒBkWA:q¨sæ0RûmMþ~~ØÓP¬ t-EûÙé™öžÛ7¯&> Þup×{Ps›«ÛÓû]¼&†Â¬6ø@²@šZ´…/n‹ifÅ~ÞM<5–À*©¼§Ok°­¾±UÂËéÛ[R=0U®4S“nºç8Æ^Ah¥Uˬr½Ùx‚±ƒ/ÉEñ¦a³„€9qbá®kz&͂Ԫ®¿`°Úï¾C«MÓó™3ã%s-¤Z—Œ÷ðÏ~ ¬û׉1eÕ·Á·°)ƦhŒ£û¥o£±™±·rU¶º4=ñù œB¶îÇ©78¶$ɇR<ß°üvª*DøåÀ“‹öìõ¬ž+Rz˜ì(N¥|>åŒÔž5kú©*8ÒËË;…×mhšÝÁ©}¹ó Ç¼×{<¢//$6í߉÷eƲM/¤Ä¾ªd¯¿º Éíe†~©P÷|§±¿ç™ÍHÝYmU‡ÔsDØô¬²/G8^Ìs¥G“·n›zÛJÉ*¤¾‚ \'x¸/Áá÷põKð Ü#þÆåÆ¡< ߥÅÂ>ÝÜ"µ^%å'ü*ùICÏÆ¨)ñ]– aÔ¦•¦õ‡õ-ÒÛñb©ún‘âõî¹)מ½ ¤æRY'>1<ÇÙŒí ?.†Y»Ö°åÔþÊa>ùÎÌh4ŸÇÇ =Çôóøü?_W²íºŠCçõ51î‡o~ïZUŸ€û&q7ç}}!a cÃÉt+¶’P8¾ñ¿2|tß(ÓñÞÐ$ÓùÞÐôßd:Þÿ{¾÷&í*@¹ŠŒi˜C詃2ÉŠœ4¸'Ãg)0Éê8ñ³‹z\Š/¼—½ )+Î'l p˜¡œ=.zÊF~4f×u9z)x•í{¶o°hª>3õ_ØGµò”Pö” ä3s-²|f®E6p~™g‘ œ_æ=y%–j>½a±eþ“WÝ66û!TÿïZÖéSª‡¼»—6t!˜KÀ,|Ƕ¬Õ“}M»›ZxåJh iwZ¥¦É4¼‡5ûÞsB#­øÚlü[69¡±^¸ý¶/¾Š/„3x‡@³àAÀFȱÃé'%ÄŠfZš¥XÚ¡$”=—œj°\A7‰ÃÌYôÃw_Ïhº;£iÇ5t@¼ÏhÚq ï3š>PS4½z¦kMè-/qFÓÜr)YŠñQEùjˆ»éÝ¡¿íšÕ¬‘¦Ð5ªJs˜B×l‚i ]£Š6‡)ÔëŽ\wW+T9­“ŒË¢iy"Â@#:“¡§\å(ïMÊÛ¥Pÿ½ÅDuY N¨§ÅDé´ußï›P_˜úæ Õ+wîÛË s”ê¿‘1½¡uNÎBp\ bÊͲAý÷Ü”áˆ[ÖuP°îdÛX6%¡ÉmÈ8ßrBÙÍmÈ„·³êÞÐ<ã’Ó¡É1ÈšuÔ ¯ù™I}w_;õd½#¤ûu-ZBC­ñª›$§CcOϩߦ ,ß’Ó±eù–ò[Ü”wïeqPÞ½×=ótæ¤aD—Î*=ë YXGךּ,ýÿËž#B –_eÓ`ùU6 Fnx6 FnhÝBš•…ùõS§Xh°ÁzŠDacoVÂx}-Ç“£P–}×wߎÐGîÏ«;Q÷öäyÎü/3=¹í[Øè\jþäwd‡ƒVNÔÕ-t?,¼Þn#,”½u[…²[Sò¾¡z¥[ ‡êG·< äZ8Ÿ9ôV8¾÷äs2ð~BÕˆpÝHøÜ¢µó Ådåk¿¨ÿzÚˆúQŒ¨ õo#*E(ÓŠ]¦"NP»‡EXÒéMhxË ôk…»œ¤Eý¼®yÝëÜ諾ÜpŸ¹áOýËhMèp£"TçÆ°ò¹ëêÝѵOB}-!0¬C’ô ¡Ácöù^¯Ðiì³}ü¼ nœÌ¦mÜ 5^õb¸uÉ7^Z6Aüz>^`‡VJtϧ>k{XGµîÊÂJ¹ÊôµP r-ôoÕ‰Žn09PO[)SñëSõ^_“èœÖQ_óuäj¶&<á|%4T+’\ “²­ 4TØÉÏØª'ÇÚj–,KÏ{õäÓÕ=á>˾4)ž°žÅm–MDߊ»¯Ñý:ô >¨TâIÆ÷DJµ£çeI+©J^• ö5}‹púùªq9ŠÁáݼþJwé€õð`€æèiyÔ'´þË­Ë>Åd½§×5‘™Â–‹7/„úzbM’?Ú õ„ÚS¢Þ{V/ä{+!´yRièè’ß×jáæ+TU/äb îG¯^LÕ 5Oï·“Ãî%‚œCCê »õ:IÔ˜ï¶` ù*/°¯Å6Ã"D=O÷Ç‘Ÿ‡Ón{B™Î±L˜û¥"ÔÕ9vCEÁ±/¡šÊ2,+¡U=ßÄ刣›}ß¶ÿíÑÖk©G‰6øä’P¦YŸ&ÏÅòUúØ,|Ä.Z‡ßÙ½ý9:ƒàeŽ!8tb9Z‡ÕkÏl‹ê´»d[Ö,þR'0íìøìy;;œ[? ýø}ç#œçq ÷,Ï.»@­[N«}â{­µÏPSíS¡†žTŽÜ🖸šaëð½¡ÎI¹òò3.„Þ“åYSW°B\zé.h•ÔЩãzÎKúTBÿ…=ûi õøADÏäbe'¡®ª‹Ãжímµ² ºÚ´'¸*RØ~C¨¯óYÈÍ€/ˆ®½©”öŠWE¢¾J÷¾®É¢þi_Un{U§øUWß"!·¦’q@p÷-Maß^N¨^*áé§,kõd}ChsZ”„úº¥ß/öXhpûª}ÇYê;¼8Ù Dh« ešäˆ8nžQrBçéKé– ˜P½¨8Ní2Þ¿U1¢ÜfÞwسèh§–QI*tŸ9ž|ËÖºenŒgA롺T–ÃÒÕJ¨’J,¤õã°|*B=-r­Ú”¿ß`u"ï)•)矆ï„^³ZÎÛûÔU%:Ô³9›°@«õŠùtšæ-å.гÃ)î éº¶uo|n¹,Ji}‰Ú{Á/ˆ"ã{»ã½‘ñ½ÍñÞè™§Û¦©êZ‘¾ÛèbGÁ&Å/K^íYìX²‡˜—Œ¯^ÒéÁ¡˜X£‰=‹§ƒ9ÜØæË´ ¡4G2O#âÂn@4xæ“¡_zŒýâà ¥uú‘>E¬ÏþW8ª ÇØ?t¯uAH–Ì—ÅÁsO§°IýŠI<#tûÍmR<;ù*œàU}s¤Æ+3Ù»ÂoÖ÷0Jn KV`ôûϼT"‚Æý‘ØV,>oá` õt^}ˆWþ³oM¸õüà•¯yI2_Å0/ßK°ýåÁ«ÛFÌ–µŸáã“Ý›Ôa“ø3ÿz[ë`ö1k9Í#Ê'ñâ/¡ž²f9®Õ›obCà{˜ß vñÅ·º! e¹–ëªPWûæ¡ Ö$b¦¿gpãÙ–à ††|÷§«§ùC¨^‘J;ž&eG¨«E“ã¾ VQãÐòÞ ,Clʳ§éwšSBŸï¶ŽP]ƪÙ7lꊣ[Fü |ßôãè™QSñÍ—ÿ·}êcDÑ3;SÍɶcf9Žt=B#åÂE4~¶2|qOß›Pö@KÌ Åñ3Úè¿û,´…P=•%ÎrBý›”åtJ³K7¬†bïè²[dVå%̺æŒÖö2ì&Êb%ô6¿ËÑBÁ^έ6ùÆ1ùfõH¨§ó9çý¼ì€²§Ï ´lM’•PÏp x–&„ÞwI{ýLë³½ e¦P_­ƒ™ÓæÙ”ªgª²%åEºÞ²GÔÎ^®!&8W:ö²®t ¡¦•®%Ô½[$8л÷…h_ÕŇPvó‚×!?ç@o‰µÈÞmN(ùWèºÏÉ0| ?v þ­ªpx_hhùÖÑ›Ÿ» ;¹½ ž[ -P?ЯŠ¯»c—¦—;º/Óœ•P¦µe^|™&o e·ÿõYö²Ög'B;¨Dô…hd<3'o¤TƦ3sömþ¬„²ÛŒä›o¡®!ž„9†&·†×s3}5×ßÅ7¯öÜ'{…+”w­µòÊçßëYøüí5ðüMæø6s"ô·Ð˜ÇC=º뤂'Ì M;?hD‘-£‡ïMýDí¡ß¦fB°IxF cÎ3n¯ë†çPùcÌÑv1ª÷®À+f8oå}f!™jÔã¶]¢þ½Õ°ÈÓ41èóžÙÀfo·lů2ø×M3l´Ï1škó,öf¦÷šQŒˆ76BŸÙ@a5¬ÏP+J WÈXlÑ2ðe˜û2É$è/pÒefýP®\f’I°0¿®c³ ÕWQ8hºkñ½ÁsoVÑV[Â3BïVúÉQS\ïÉgxrR*T¯%mµ'̾=›ù«9ÛÖ5'TïÔç{ïÞ7|rÛ%ùäÙ5Ì>|óPã}Ó{…ÿ¶îrÚmñ¿±E¡¿‚Q¿Ð- YƒGɼ—Ù³Kü/³ÈZQϵ٫‰ÐÛ ÂëkAÚ½Û>cô8ZÁiè5bžiw;ž£k¬ÖtVN‡Qõ ƒ^p«!'+.½B/|ÖªyqG»T˜T×Ç2¤Å2ÿaù1c[qè¯`¾û´¢#ôÀŒ8ÞØð_Ž›£á¿L«É<2œßyUF]=—„Cذ5ƒÝºz«ˆêôƒü—!âODüœ,„2- )KW ¡º4Àih þ70ÚIáR¤„²;º®¥Yø»1P†°@ÔŽ—Ë¡ì?•°Þx‰#ì`*ñTx¸‚ø‡Ž…¯þüƒ÷B&yYÁ6ã!Ë?t2¼Npþ¡Ãá p®Ã/þþ‹bÂGà¥pªæ/6¸13Õ€'TŸ–Dà ‚?ÿüÓJDà ô{GÁ@B!O‚ì Àß/ß!0J¨˜`6õ¶:1ÞD°¶ŠQ/Å^&ŠÂ1R¬©¢`OŠK?êôxÅõÞIÖØ™¶|l'Eá?(„ÓW_)‚…pGø•"|PÀI‹WŠèN1ŠgìW äé_5+xtøuÚØ eçŠRTßùŒÄó$(‚¯”_fO8ùpÏ$àHp¸g}Â!àž]À«–¾7ûTK÷ì^ÍD`ð YÀ«Ž"£Ttê#c£P\”€kBq¥pŒBq¥`F¡¸R¸F¡¸ \·8ÍŒGƒÿÐEO<ü‡î:xàá?tÝÁsJ«J²Ó5Û¬¦:§Ô=§ôö„Ïkÿ¡“þá é ;EV-DpýHÐt8,~âÊ~pæIòn$Ó@‰À(¹ÇG–aŽxFûýoÜïØQrë Qr‡Ë7D&¸>!~(hG*šU¼#Í*Þ‘Š‡¿¨øDOßHÅÃ_T|#‹Š+‹Š«o°¨xCW6¿PXTüBaQñ …EÅÕP¥Šß´ïBø¡{$¿ÓäLõäÕ@ì¶r€zíß=ŸØºrlË—LÚ³§hÖ—Mÿv¨Lþе ‚–«'Í œAòC—+<õoõø¡ûôWTÊH8Žé#+e$Çô‘•2ŽÝÛÑ ;Žeyñz‰ºnÁd$К:vÿ­¾˜ʃãØD¥F?æ¢#F1ólvÄ(fžÍŽÅ~±¦ÝÓš:ìkÚÅš*‹5Uß`±¦ê ñÃåÚN—ËqÍŠ³.—ãš%j#V{f™ÜˆÕží '«½_dr#ƒ=&™ô~‘ɉ,2©,2©¾Á"“ê ±!t:Ç·_‡#ãø¶àëpdÎK?ŽÌD¦àëX¸_92º!=å!°Ò½É"09Ðç0C› ~3´=áfh&úNhsÁÓ MÃÄQÈõ‰¬ÃºŒL†ô\/b›)>׋Øú„c½ˆíëŸÉãUn'Å-…o`/³[Ún)S‹Úý #²š9ÇvÜÞÕ›L†ô`³šâƒQÌjŠF1ö˪L¦øXX³1 o¾ù¡YôaâÒœ_"xx *vežQ¢ÀE‘ŠÃ<‹3ŽR&™o‘Iñ‰èÃ0ß6YxÎÝÑr÷£¦ÓbÍ5>”—YëCy™Õ¹>”—ý¦¼ŠÀä\ÊËB³êNgEÖ5ë`Td•jéä°Ø8Ý*\c±yº»sºÝ—yº·sºÝ—mÕ;ôÂulëæ¡®c}‚Ô ×ùÅ€ÌD`Z7â:–å`¬– l™qŸò7˜e>×5ÊäØ2é5«RzáÚ4k¥­v½_¦ôÂõÍÓ½Óíúv3('+°ÌiÝÀ8 PÞC`B«vKGË ­œ1|p#£)V6Ê,œ<Ç­6êàdüËl‚Lz/ól6çlz/v)Qžc•(è2ø¡2ŒKH”Ç,‹Ú93[Úîtr<«Ó{(¯çÚç5ËóÌëÅvÎ…g±öÝ)ÕžÅÚo§µ÷|ólnçlzÕÉÙô,2¹^Zùpíƒÿ‹“ƒn³ïXìÃ)Q¾ó‹n‚}ðÍ2Yu§<øÌfåKë»6>TR/|«r̦oõ@ŽeÑ·Êäù V™<¬½o•ÉC|«LòàÛdò”?´êÅñ„Ð&Q‡…ñ#+'QD¶ÅýädlÅÁI›{pŽ"°Ë¤”êàeãÃ1ŠÀ±Î…”‡À±éÅ1›³}Ã!Q³âü×úÉÉÀµV$›ªdÉäƒ`!ø&y×VÑI$ ñô xÂæSÞ‰ |©ÜÞe>¿TÌ_&ÝÂ;$÷¯…Ìíý4CƬû”´ûå#ï¹=yyǨ^ñ`vÙæ“dvø"f?;+0ä %·Šòª;t­CGÉí…SxÛݨž`h¨ÙN::+/ Ó7%ßD°}["ž‰¬¼¤îÑ ¡XNû¸—Éå#e«.!+ö „Ž©lÕ4Ôj:vVÂM:?t3Å-Û‹wÎIV2•g®/‡Ã"dV ™*‘•#ÚˆYX9{1A`$èÕ+=ãÔò·d3²r„3E/wVîc¢?ÁÌJ¸Hé‡.Ì"ž+@«jʲjVŠ•)²RÞIˆ±uèj ~ðZ^K(yí*VŠñx‚¼{PŠŒkaežîù— ¬lŠ}U¡i¶ú|"CCÐw½¾âÎÊ4b[µê Ïb*ôV¯WŠG1úÐ(Øig°«°,åE‹Rp]*¦>ÛVpfBåä¯ÿ; nãÖ)ã„åÒTyÖ {cÆ&ô¬–UŠÀ7 £æ’ª-Ï^¬†¾ÕÊFƒÐ·Ãþÿ|]Ù¤ª²ý¥çÇó~;¢ï'8+”8•…}¾þ0™ BõîèØµ’Ì•©z“ ¹MѳTe‰WI¨$Bšx•Ä¢Ö!¹OqÖ•Èoïüƒo¤¸Š”ÎÏü:߸u¾Œù¤ÙEQ]ô­ˆœúV–à¤Ùåt]ô­Hœ8JGänAjî0€»*K޽œ#,ôÔ2Ù˯eä^d/¿–‘•½üZF.Tör­ƒ:ár²+¸p :Ï·Ȝǻ7o‘»JY¶ì‡e““ý°lj®–íbUÔC"§ÀH«bb§U±‰³ k <»Qµêûªj7C@}bµ7¤[¥!/ËÔàtvŠŠ;\AI×¼.ˆ @¨qK¹&x,€ø]>3^ ’›?ÅýÖaêf3EªI¡ªMç]~ìÕzM!ß¿œ€WÚ]¢Ü‘Y{3‚³ÖI),ú¡@< „À£@(< À£@ qVÎ|E” ‹½6ëzæ-Ž;VÉK³Ä[ó¥5LêÖ04LúCÃPx4Ì †!ðh †1†1†apJ”Ö0Ù ÃàÑ0+<À£a À£a À)Q•&÷×AI5˜¿üø †<¼ùËE0zÃÄòÀ%Õ½abyàgbÒ$埉I5˜~&v€›‰©× \+Ùš”û-ŽªÍýgQ‰ÜLŒÂB…îãOa¡Â”u€‡²Rx(+€‡²b$΂1µÑÊŠ࡬ ®…:÷"þAY1<”• tk©½HÜBË`/’BKàZÐRx„v@â¬(S{‘þ8Ý+<§ÛŒàZ¨s/²çb€ç\0„ß[»ynO¡º]óuX¸œ…§ø®ó`õy±€¬TNð2´Y,µlóέÿº´œ«™)¢G‘5Í*ˆÈÍúûG‘þ²{UÏ 9:¢K·~›gó ©aA"}Uí{ €ÌY8'Œ{p½µd)”øo-)F¼ÏSS{¸/à׋%¶ s>ƒ÷bÉù ±¿`LФà•x ФIû@4)x¥~âÝË×ÌüÄû0 Þ\Ä[°Ž+ 6µpïv€‡xopï‰àz€ƒxŠxk€›x[¯é$Þ[oFÈÕ}TnVî/Z“›e•‹ßšÚ,_¹8=7Ë]Ë­ çä3è’ùÒA+ùeï ‚«Õh-7Ó®‘\.,›õWn·XIkš/À™}`^·N$•Sš«â-9àØŠ®!ˆ N÷g+ÜÕb'àc°ÝªŸcW¯û·ì°™"½:à’X€Ìdþ®f„Ö[ñ|Švë*³*ºg!øíFZ B¥øjFéPw‡A ƒè„#VÎo­í6×G½D¶Q¹kê“ÜÖŽ©ë~d¾Dʶü,w;XˆÄ$áä“®++ÞmS„IÓI«ÀÇ c=•fÛƒÌáGh…é.fV•„Ra‰Ï#Ó 3ðÖ"j…iÿ±½€ƒq/]2}läÇ¢ÿ"ÞV€¹‰,àÌNÒ>F›Ý3CÒÇ׀ؕR4È|dæÔ$¹—’iM’{ë•&A/o%¡Ò$(ð3 á‰ÈgO¦Ÿiôn¦aMáfr%Mîƒipn €;ÓX Ó@ÈÅ4Ã4•Q1 S6¶;ÔC†—,|Óè${CpYÍ@–uk”ù›—–`€}ÔÆ‹¤{/¢IÀ>6Jåâåèö½cˆm%Á_ƒòe¦]ivrYœ^Ò”í6 €ô¦D¸÷Χë2KCÈsÑq'a^äO [,x1S(…ùW–e¨LÿV dé6ƒkùýQ]UÁÏÕ²ðãgH#dY>F]ÔË—ˆ²«B]…Þòe)pñ±Æ¸—fÔ‡xI4âR›!”îñùâ÷nvD(Ì!Õ2Álâ²cÖK(Ìïÿý5©túù´ß}˜ "{¤Ò™N¥(ò˜{JPäN¥3J×O* r§±1bw{@ò,¶YU±M€â¡]ùÉÐ.ºH ‘[ oCäV¢Ä¹Õ€Ø˜5™Üùázf5 }Fò#Éÿt7jÓC†þ¦çZ'/Ì_§’&xê áݺAíE€2¿“9æÀ„…¸F©\¿uû*Á÷[·N)LO¤ŽêrÀTÚ;ÊT6 g}×&Ä>|ýpj„D…Á§†À-rÒg1…ô‘Ûà¹Óg1…ô—Ä<¤Sä”K:/EªO˜ËÍ ‘«nB¸Àª´·…Öð¥Ð×áäKaäâK½áK¡_RB¿ ¢’…~¤h@x½©g¯ƒ¬ÝÂøîÔœÉþ}\ ÀððNК½g¾’Â೜K_ÞB[·7>jòÙ ¾>w@âtÍÔ‰]µxõz¤u “ë[Ø^®]9=ã‚/õ9Pò!SÏÅ“†é”Á€2OŠÀ€Zð@­@ ÃÔ€Z†é…ž±¾÷¼o£d;á5l¢Š.U!nÒݶ{( >íëµ’¹Ç—©ôR››Eªè ´H¾Øî(ð¸lçnFÁ’¿ÀCòÍ’Oà!ù’a7£ÀIò1ìf˜p¢mXéiX#äq—NÃ!·ae§aÐÃjúÀcX §LörŠÐ/“ÒuB¿LZG†ë´Ýæ’ËÓvK©¶.¹\iÒVН›þ "gS8=÷ò²ïù_ÑfIBÇ•øøê¿ Š}SÈﯞ€gá´h@VvݺZ.uúCW3xtµxtµ™Â£«WÄN³¨äÁ訇͚V §Í²á“``M0¬«:—€ = Fìë?vŒøåÈГ`į™ ž€ €' Ã8y”$œqà «ªƒ#ù'Z™Ç¡GÜ'+þu²'ë`°Ô¾ø,uìær –:þÁå<\ŽÀÃå(œ\N掃øê-^¥ZȤ¹ äj T@ø$½§a5×…ž†URµØiÜ•xpvúb¹»Oh_,|#hW+}#hWëZŸv† ö…ì‡Ê3扻µaêJâʰT•yr½«+Óð¢‰õ°©ü·U~v ,6SDŽZ ͵òÔ͵֓kåÞþTç™sN¥Î2Ÿª,äÕ w{RàÕ¢—ûâ%xµèõr ¸ÞèøFPÛ^ÞVJŸ#«hÊÒç=èsôB~=&%dªªzlÙRôº¦SuÙ=&BÅçOÀ5TÛµt<]K¸Ô\Êß»… Êß±SM­8ÔT±-pFœŠVÕDáå`e/îk@ö$çÚ" wWâ,zyܽÓ*¡WìAY%äë/Ka7·u¦°›‰¯ˆNÑôr×cô„6s‹¡ÍÜBKAhsß§Ðæ¾¢u6QðrŸM¬Ï& ^~=)ßÂÓcSêIùAàדò-äדò-‚ëÁŒUKð ¢È.ܺ^h”ŸXü‡¬Â­ÇíR àî,.¢^(pÞû8–MßÃEóÞ'(ºã7 œ™š¾Y‰j_‰‚Ðÿå ÷[Ë«î·XžoÑ’b&fŠç[|õÅN HÚ^‹½]ét×´J`¿¦U“øtõ)0©_Û+ñpNzj˜ wÓzj»ˆè:‚Ö0AæAk_GDvjôrÛ vjôòi9E“ ~èÉ7“¤Ïfø Š<›aà3Iúl†/¿Q“g3ôúêÝ4‰û›W»ðßÅ[ø÷ìÜî0ú±Pox6Klwû7KnwûN÷ùžÂa³·Gaö¨ƒ"î¢ðÖÁÆ6( t‘ã@aêžBh{5Bêžâ«/ù¢0½ŸMhËßS®íetì®>ŽúXf±ÝVö2B×—â‹6'ÝÔ`²rEHÅfEÁ¥€¡‘¬·Ûð<’ZTß¡köÆ«Ånš ¦ƒWÜy56¼ÚÊ`>yõ €¯¦À«­ æ“W›œ¼š-f„;¯¦†WG×rM[šC¾Eä•IyßE¡³Yµ±/è·½2ù#Nxî€ÜR-ê—Tcx¤ÚB÷Ù”òðëlbxΦ„¶k¯kÚ^MqYI«G cdœj€k/‰9—IÊmÖ~P„Fä¤TcŠwþ§@¤ËV‹JŃpI†¹$Îê‚¢R‰É±×sg2yFDÿl ³ú«ËZE_¦¢Ý0f°XÉZÑ}Ù‹yÀrKª¥È-Kó%µµP¢töûÿÿa¯F‡½øSfŽÀÎQÈÝV²~EË#¿®ZêÔ1%ʤÄ/'³î ÜcÑÈÙ‰V 0ƒjš„âk_&}q¼ï›©x‹ž*ÈJ´ZW…ð1ß.BV¢ÕÎÎëHeW% €ëÎú-Vº”kGxjJqÓ•½w ûÊ…ºØÁ%‚ÿ €ð±û¥«;D7UŠ¡ Å—Æ[)´ ÛíünÞM§öœo:=²aœ—® ßØP¼ÛïØ @xY  C±mC½Àjq§ú%4e1~»á­^=~EÍø€È„ZåCÒbØ«hí¦±iu7Óвj©ÜB±ŸÏ´ÎtdHïYM%ÙÕvÇ×N~­40M@·F}d)—a™g„··à*¤zsÙÀó5çú|ÍøöšÒ¼ïݧÜÖÂŒÜßbÝ¿c¡–=úrD¹š¥F®~„ðé6€ðÖ¸Ÿî} Å €z¡H×}Éç€ø8ÇEó‡– y¬ÃÄÎu8óe7‡e©vñ½=·{žÇÑL‘ßVrîÆïQ•o³P/ÇZZkô ÞËï§Ó™ï6svto·½9FÜÊÕŽ\g§g§Rg'rž¾® í^µï;~Ì;™”ÜFׯŠj;Þ#)ß»(µÐ€ø&·;—ÛIËmdoG¡o à¢%Ï ém¿ú‚ó²®j=6—ç†F·\Š| 25ŸÊ¬ƒ²KÄ·½"‚›hÛyÙ÷Ù¼¨uN!*:Œr;²K ©äj—ËÊZyOYÕ’_«¼_¸8öövˆºvÛ÷î(pés)ª¹‡~þtµеå+»Ž­ßãé €äÖ¥r©¦b%¯ŒÍ ÔÿÚC˲è;3Ev;€]ÁÖé½ì¸§¶¾P}cêÜP¸xâBÓOÜŽ 8ac­A8¶cYX!UMâÚŽV|°hÝXÛ¡¬µ j;×é˜Ö½aÛ6๸<·#qo7ñxyÀÚÉÛµ(ǵŸÞÝÊàz˜2Ç~õ}ižÁÞ©Fªa(*b-”ÜŽ?Êï“l¦ê¥Rt'qnfïj~+©I,eusìdU8J^îûgµ¾†LÛà»×µË«]àtf5EàJ¡+§J>e‚¯ÌÔ+ù¦ë›Ê–cèÚ™ØD ëjé+“Õµ'ÿO~U%7ÏÏâØ²yJœžŸø\µ,ðhÆC¾¤" 2µHr BDù+1Ûo”¯ñU76ÕºøR¸N@z3Á¢(cÞ[9Ev­ŸU±„š\…ˆ’m”\JS+]ýúæ®!í 3Bè™i´zÿ‘Û­\CRŒï¦¥ˆïQ™òlŒ®}…'lÅw·í‘ÝWø/x+^r=Ìá³éo¿N} €Ë^H¯­/Ú±þr@z9þ•–Bö÷<·+ìØs«š+¼,º#«Ý®u¡ŸîÓ‡l›™ÂÜ×WW¶ahW&j.Õn÷Œo©‹k\$;3…E€Uü›«¸º‘‘!«Ý®ÔçŠHжø–Lª «Ý.8Ùªß6›73BþT××׿À8Ú|raØ›¿ "p, 9Ià XL:`‘·€…Œ 1Z4„Ò ¡#¢UDÃjÈû X0ÜÔ,¬†¼€…ŒËX y¸,æ¥Øç›)rÃ=uni>_bž€Åbæîªp-ŠUÛŒÔiTJhâŒì–½×Í­ìÑŒÒË ˜•¸ïV¯…ôÃÓèëÓ*€RÀÌ*W¿X?ô=À6Kn—Qîì €È se÷lcÙÜ©ÙWXÅçÊÊ^èÙñÖD Õb¥×6‘ŸÅÒäŒù}ÌVúDš‡ã`\6:3}ùsÓ±ž}YE Ä.6!¯k@ò`㡚ôÆ&”ÐÔlÛë]-Tv ª.+Ã\7+ùѪ•÷zÜÍ÷ûŸœÙq'ò‹`5aÑ€÷4ôÕ sε%_¹7¿J‡>ÍmÇË’(úiÇè¹_ngk„÷À£Û\5®%žZ‡y ˆë°ó#€ÄYn+-yöºÛP• 'g.üÞØ÷R°+¦ÈWúCÁ.Êo­Ì¬Fý´ÂצºvUb?K"ouY}\1•&Òê²jÝ{ìû ÷X ­©KÖ·URNuMæèÒ_ˆ;Á뎗n*æZ¸\êÈ Ÿ¢ŸÒËWˆ·ßhÓ0©´³»#®½ä};Iš²›#~²ªmÁT½¦qÄÿk¢mÒÏȦROYýAëO€{˜ªjî­LV\D{ÑøT“y†übØP“˜×¼–ü E)ÜìQ­,¹¦OþÇו¤M "Ñ+¥‚¦.ûÕGÀyž§¯OߘÁ þ›ªE½2!ˆá½À qñ}¯Ê%™Šž»dŸ.¬Z fÅNÀÚ˜€ßöÅ Í´O ƒ 92¶ï¯»W74|Ò® ôÑ›ëœçrÝè½¹Dv=÷>I T­·àsòo½¬ 0¢Øì¬•Ép¢ßÛ%YÔ[DVÓ+aW}{Öˆm#Éî(6¬¯Á×D—5³Bxvþ'?“åO]ghßN.ä/6']~)y ¦¹ÍuLç)Ý"1ÔªZ.v¶Ú¯z4KîzôÝä!ñQc§=l7(þüÁë_ãš?ùÍ à;KÚP%5;ºšŽ2«˜¸å¡.–µ;ü`¼†\´lócâÊ:H77S?¡ªjPwEqa//O³:'pU?Ö§oF;ÖšÙ®á Æ¹<Ãk[;C¨ÃÆZ“£û:#ñ1Ò嬶íT£ô<ç÷§,~=[øŠQÿ1UçÒl­8µ®°¤œ ‹¢ ¿Fv¦¼ÄDZßsiXs‚ß§7}Õ‘õšFp©âÐô˜nôÙ¶I·ª'üò/i"SŰÎk)šöøªéëïd|`UzÉÊ»júj¾Åº±{¢¾®·hø[ g¥ú[Àþå;cO Ž¿î·hša^Õ4ïUÆVcÁ®u`¿7ú…HÁ"Àm!à\ˆ£WGÒEâÈ”öÈðMôË–R€ZÛXÙ>÷N-ß~ ü§¥ 3€Þ£,üpj³uF€~­ì;½®¡H@óÀ·f.jœ7À.£æ]ž6§Ø›7 |ã‹]Wcð߃6Œ“ÝÆAß¼ƒÐ?6ï‰{ó¸yoÀËæU€Çæm~›÷¼lÞ/›¾fðÇæU{ó6¸yoÀËæUOxÙ¼ ^6¯„κ…\ÕÖUƒzÕAB߬ÁªÑð>«-~Ɯݮ)ÿš<ø ñŒvXâßÁqÛ±Í5€ªØ·¾©*Y"ªê7€<~‚Ïf)×dìþ‰a¶ªA€£kGU%e‚âŪö<·£ô ‰YÈ+ÏdÈÅ]BH"ïÝÍ©$€Øªü{ªùǾ+ÑÔ–‹±ôÚ^8o ®rƒœ7bö×Å qóã¼³¿.rÞšçh2 -…< çh2'çM ò…óv"à…ó¦žàæ¼µ%lÎ[ƒœ7¢õ×upÞÔkxî(}†© ^£ô¹QU°“‹nÞº|NaÙz¡³ªØ_y·€Ïòƒd¿d~jµépÁÖùº¸=Sß Sy^°Jà/ñ@D+ŽÀ Ó3_×µEÕ¢!,í¾®…VŒÍ}B~lj ¡cWÙºÔÕ"àkwÄlε™º‘Õî’ûY6 'b§÷Ê#?¹"¾Æui& Z.ìè0EX!/vçóa ñbW˜Ò`˜r^”v˜Ò`˜rÜaŠà߀—0E½ÅK˜¢/aJ‹€—0eUåS5JÏs'—Å3üu²Áš¨Òj® %ñMq€º×©ßYáéðNâ“·4ÜÝæˆÿW¨´"Àw{bYjÝIŸ^§øî¢ ø~øbÑï¢ 1Û—bQ°ù‰Ù¾T7ù²(H´ö¥O‹~"à¥(Ø à¥(¨žðRlà. ¶ `, þ&ê¥(¨ÞSYtƒ@!_s²Ûïú?ú#ô]àNÌÊŸˆÝ‰Ù>é¦G€ït#À1%—1+7‚|ÞÝ8vÈÇl#MÉ©…Z!ÞK- ØZQ"ZSzÀ}ß2KEj—h LïZ€,,kSmèÀM>2'¢50µŠ{×µUî©(À×UU™gõšÑ£ªR%54ͼ±²¼ZõGÖ(À}ªü Tו%¬>a¦žVHì’5U¾ÖÐêpÀ€hz–5ùx"€Ø„Òm¹êJd¦nµë.3ëû4K(€¼"cfe»BÅœÏäåÏ˴•7àkÊ"Û®úHë‘ÕÞ#[ÎòJÀDßÈ˦R¥”rã¨Ùª&꣑r@"´gQBðK|»,×Öss¦M¶oQAª•[3 [ÿªñÝ}xÕl›K Ô³ÙiÚÅ¡4°i3×ÎÒEÜcM1IŒÚmÅ<"À¾æbÓº>ú DŸ.a‰Ž±ªê%G€Nñc8÷‹¦¯è…Ï\Œ!;³î¨Ú”ìq=úÜpBÌÊ¿^2Ìaª¨ËLˆ¼í”, à;Ë–‚dA´Ö¹²å¡F#C°Dü€ÍÁC¶ÚÖÞtP‘[:¹£€71ÎhòC‹ Ñ; Jb÷çîøç øF;gÇe]“å N†’4ÙFŒÝtPA/*öfC@à&Š“‰~þ¨Ö‹Ÿ F D,ø{³óãE|wE°îêz»ð¬žsM©‰)òûm϶뻾„PÂù©ŠàXB>KÌ6¥fiæROU•ë“­D~Æ%ô)›«~È`×3~×å Æi ¨¦mReëN~j d<¨o]Þ‚=/áèÑ„‚VRu‚¤*Ѻ©Z"Ù.¨nªŽ¬ë‰êdƒ‚¯Bé;|.JlP {V @œdÏA¨“ì æ˜ÒWz†ÝÅtXøÁÅt0H&‚Ÿ´ÌGŸˆËg ]$è&a¬ß4À³\Áwú(Úµº©üüKYŠ€§;t¬WŸ)@`–³c#\cô[‹$ çƒ/ž†¦;$…å¬Y*}ZµÕÛã*§l˜Àç=Û¢ƒ»”ì|FÊZ Â3ÜBñŒi?÷麈ʄãQÙ¡}¢srD|y”¬+M!¨·•£(1³]!‚_Òñ^™ÓÅŽ}ÕËzÈ+2y~ ç5fW©_KuU±t¨ 5ûY®]Q0eÚHãGç‚s/G¨=èz¦šÅ\¯nSúvÎí>=ùlÀŒ¢I52îfÜ•Éȸ3̸£ÉËžéб:Au¤äÓ¾«¸SòB€™ç:[{|ÝJw᱄ô5Û6È}Nßse`JÂà¥ä¶Ü¹2MSõ,¹©'—~´Nà á›~tÛÖ Éã8‚ô™„¡K?:æÉºÖ`RC[°«²ìòä\/†€À’ŽÝØ'í•# tÈ ¥~åh 6qšò³ ê ‘FžÇ¸M:vsÖñ n˜øNÀ¬äAòþ7p' gp' [õî¤!,ûÈ{Oj]2 &fÙϼ‡ª\ä?V5\ÊQÌÇ ¤J/3'ƒ¢ä‹~ܲRˆ‹77B×” ¼9Ij‹ˆ›y'–ØÉˆ¾Òâ$ó.2ò³–|žØì‚BÞ3yË·‰%ÒÕÙØÉ(p¥ôoñu‚ê_·,åtƒÊéÚ$ "’(tk_~âÙ>L½ ö…Dæ}Yš0%aÊ naJ‹[Û–ŸB] ¶:ú¾W.*5†Ð¡A1r¾NÁðÍ"¼6Ðì þÓ‹Ü€ØÍN€1Dî3 Ù QdUÓtZ̃IÕÄÜŒðƒ`MjŠ”öElæ,Í.mb±ïæ´"Ç9&6)ZuË.x‹8p±æÚ<©‡ràëÞ¯ð¤æciÊ9E±í<\ÜL@ÿá×u/ÙÖ]×Y,;7Ѷ‹ÄÔ5ÈYÜwÑ¥ …æUÓÉ=Û©GÀ#ÈßÒaIÁ匩äKÀ9Ï 7µw‚¾føG‚yA€Ü]Ƙ\rñC i‚¥aÉ•(€oŠ^ˆùawÇ_ûH’*Aþ½öÔ”óÆÊ iü5Rq¸¢Ò‹É!64ÀªÒ]ð5ÇAül9§ÿÌ×áB@d±Å×fž¸ZäÄý¡,²³Yš%W¯yßp~{{°µ²f„æ¢?„gÙÚqyøÚ«•!ÙÿT*Ž#ßL{±iTù|MI5),íÿBGZÉ«aÕ°d©6ÒÀf”µÈŽîÖÝPn9:¨Eű³IÚY¬W*#v5IËÎq­t±®Ù™S)W…¥F–€¼cw¸Ô[k¸çíÔŽ >êaÙ”­$Žcý evŸ¿CÃÖn­Kèçq•4ØÛŒ»JÅX#ÀxMñÍs&šæg ª±®<5+]ê Ô"tŸSºey ÀÈGð™èæ¶íÊCýDøâj¥_§Åe`úñ^7[…_JmUŠa%à ä+q"àÅJ x±ê'^¬Ä‚€§•øª]ÜaX‰Ÿ¡òn%– /VB½æ‹•Ð&êÅJ¨G¼Y õ¢oVB{ÆÃJdó•ì•zÕ7+¡>ˆçŽVäH©3ZÞ ¢EýÐ÷hE~2ƒÀî¼N#6à!zú \†hàûK"jÊ€~vfpß.ØLǼËÖbNØ¥ý|Ï®yësvºc¸Ê¦¾ |˜²Vä§|ÅÉÛìí¾œãx" r“¥a†®üV×V|"„OE?nzg<ZøÚ-èÐsrdc3jO N[D 7€º=äÛCîº=ä6ùg/v¶_¹ú‰Èj´X­l®Ú‹! vgTà ÑkOp€éçQÞÄèŠÕô¿®jðL”¯7M™zŸ÷ CïóJXÙaÙ{Þû¾ͨ÷®Æ5½‹n€“òÂ`_xÞ+åeÕÁƒ6äk).¸¡•1ÝÖs=ÊtG€ÝN ;÷iÉõšÑÓI˜š²k»¶Þ¢=A+ÞnÄÄÆ ܈Â{º C¶½BøG"Y5™y"þ õªž­™ä¦nžúbPˆÀªÌ7X™§žÿš]ðç),Vö–×°*¬Þ¶FóÛ¾»ùmŠò oܧ‘ý­·íÁ=7†€À¨ž ĺ¯P— –þì>»Úè±9¾V;¸äbëÖlŠ`‚½m©çìm{wÇUƒ|4 ‘kw ¡N¿6qÅOàjÑTÓŸiÝQªugüîv`õ-ý™Ið[ðBðS€‚Ÿú‰‚߀€‚Ÿ„QƯ,H5 ܳ,¸ À:êEöõò'~ü\ª®rðsO‹ŸÛ ?÷P7Ñ Ék[wvÊeµu—ón]s2Ñ]…úë`‘QWV·c&´aÔÿèX(›f{’ ‘ÌŒ$Öýx3óÒ$§(MÞjåê²m+öì쨦´Rˆ[lý6eB»N–§û$Òä7àkæ9mÛVý„]ÜäÿÌÒ7ßsånǾ߮~.àÂl~nÌ'K;ðÈ|Ïìw.­mÙU¹èþ‡jñDòl=Y{Î,Žp™3KÎ vsú¶®óúÊ÷šH1}÷-Á3Ôõ†¶o Χ¼û–à…k ?þÁµlðµTOpËýå¢w¹?¤ ü?zÈA~ß{hß™‘¨à'b·¶å¸’60ù<Ó³@d®†>–%Ã3xÌBGD‰im 3ûäcœz^¸ïTÓé=¹–â[[²q_¡YNÿ[ˆûò¨‚L4N ¦R‰¿ÃmD¦~*ÆÄ냷 $üðF­åF|ló¦/«?¾ô‡8ðÒľEôG‹öìQAéçm ”ó(ý¸Ÿðk¤AIü6†&×Î5½ ZSj|Z%û×ðÅæ|¨² Ä¢÷.ÝÚï§Sê»ø¿K·÷§ð-*ç™Wu#³KšèNVÄÞí'«“ Ts¿ï¶géÀÏ.ØŒŸi«ò*I{„7±¹êiÍsõ_ 0WÕqÌ•ú‰ÈyEž XQJޮྤwNƒw€üXïÆZ’Pó"/³X/4 T“<‹õ Ü5h0 ô}ÙoÀ]ƒžaï[OZZúh‚UÜ]n7…ºûœÏ¬Ÿq› ÕUZŸóm¹X.X}4°ÌÀɺ6õZ×Á>®"usmuÝ€|\Aesí|¢­‰KM ƒ<‡j¨ pµ»¥$›[­ ß=à=‰4|EíÜÕª·¾•©þ¥Z3Mfþ^M}%%Ô¼:*Iïªe2fãÑÐ2*bkW¾°yÒž>“H™ àûØ&K™ÊoáYÞù=ÕÅ”esŽ€Ø&©õkÛ&¢KÖo¢>nE‰XRÿ‡¢¤AÀ‹¢D=áÿ|]W²¬¸ÜR7 †ÞÃû˜Y‚„Þ»˜Õ?©€’(ÔçÆù» Ȗˬg­½|J‹´òðÆÀÉ`¾‹ÝspèSxæ6 Æ]! Às²Ïáf½³Zîìó®E€ç.Œ€5÷—³¾QØï~µÖúXH¶–­¯l~Á·Y-z¨ce¨g|fD›Rh Bι–h ˜³ÓŸ\YI`Yýu,€”€m €€«JÄ­z6a[úºàM<¦øX y¨Þ(“±l²!Ù{ú äÐc 0ýuÀ±{çD´K·˜—ü’ѺL¸¨­_0‘D"Ð@¼+wL‹¹¦¿nO@ˆžÏRëä´¿Î>‹ãuŸg>„Oë+Än!Ržm꜒½…`Ä´Õþ–z#󱨂®£‘+ùP)ÃÒ B¢Ø#”õ+xbýFä’OZÁ"D¡{ÞQ¿èçõB‚Ïû·é ^ø“«qð®³}YÁ`ú<|hL3Vüø.¡eH3Wš'|œðúBt½ò05€‚Ñ©>Ë^jñ…À¢AX MŸ»´+6øNlóOp¯°<;ñvNK°ê>«H«†´™“[׺*K)t¨>쇪EÀ‡jCÀ‡jB@€•CÇIÒsѯÝ¡@z{Mµ@¤_Eß÷<`êagÄó°éÆeÈþÛ÷xÍöµ@³åòR}äVÛkáíàó# ŠéŸOøGúgD€ç¬ú=öEô«Ü}UG¿|)¬™¡âyðh5{Ù*³P´°Ò0㨠GÑJJ¤8kË-ÙÆÝü#4ˆ¶JÖ¬é |`köDÌÇH"Å¡S)#|j4©, DŠ3RXUU¾Wq…€¯í«Ò*ëµ»¿pRÚ¡I@70IMîç:Dž„E- qþªÒŒ’À¢ÀZé ëÀ¢<…èôÎ ßt¾á¸ž*¾ÕpI‡>o¸A‹‰÷ T.„¤ ýÙuxß³½Ìrø·»šÎT¶ê­Ë1á«”“¡9ÆO³#Œ?ñ"Î6`¡ÊÕ:N]óERÌ÷¿ÿ;¼}ŠíiºïýŠ=ßÿè¦ãÉaç}Ÿ÷]c~áKú"¶|¨›r1/i饻Œ´mRe¥…x“jõš×“Ètià…Ѓ¹é5#ŽÃT¨+g]uYî…ðIL“ó,ëÞD€µG§ <ÖuÓ£u׫¼º †{8^}Ëó¢€â$»Ži ÓIål¤ECÃ?ÍË©æM/ €YˆO-3oZ0»2Ñíu”yì€$‹§kb›ä@e¢ä´ŒW)ŠÊü:$Z'J§ü“"—Ðäý(«= \áêÒIY™‘"\¨T.˺.e" Â#—øf0 6=Fsk—r[¬Ñ|–¬Þa2 ®Lvë)ÌÚЬgIy_nÖo|®~!ÒTÙü6"´”Ö²c‰' ¨¸\ˆÈÖb;êkgƒø¦íÑ^aÔo˜A÷^$s0ŒË:B×Ú ~w­Ícx„x² 2›äÐ!À§žfŠžf¸8>c=žjÊvOºšÚ¹™'è`÷$’hÛ)…¼€Õ=香3¨«ònjõœš9å(’½A€G™MÝÖy—#À'¤GXÐRNðqXt`!Ý °ÞåKNçFÇ.èæ||ÂiœÊ´ÊpAMóä“ètÝ5¹'Ë=n’ºßðq6X¬àhw`lc<…žönÈ¡¦% é@鱞ã^Nذá×åªÎB4š¨á—hµ€…'m’ÍðíLóé&¦{&<üȶ“í’ €Ñš–Xù²ˆð¡tâZ}ÁÍW„dÙ«»²Ë$5áMà}³–««c5/ù¥öDÃy¶«¨— 1Îâý¼(«ö¼( ;ôvQªESóÒBÐæÙê¢é›á~°Cë“A0’FÕƒ‘eÃ`2©õ’â¤Þ«NªOç²Î$rÙº³rËK > éï¤m]¨[5©-pÿœŽ}¾ñ¥µšD`õw²‚æù¤LÀn6ïð!3Ò×OúŽÌ'Dġ߸´Ö\g)NÀ—P‡e±4 oÍ;ܽ«CÎièAVõB\³‘œß±Õ1Ï…6/e0+ÿm©eGiüsf}6ÄÛ¤=«ï—Å•RÝ}•õ?> ŽçóÈÓVj‡Á8o•™I.x¾m %‘IÙ©Ó¢ð)I:¼—%ú~~0¹y+5I:ø~œ$éaàÅ9ÀNr”$ÝŒûqêˆý /9tEZÍ:ø~\Lî6|“#œùá&wÑÖÀBû†.ºy=,c «.°(Îÿ@~tXà öPžLY\'+Œ~,HÉÈ)éã¶>Û[}J_{'mªYì 'a).a+FÛ›ÙºUÙˆ€€äct$j«íù&# C-²LÝòZþ™½ˆnGv>B¨GÌæ+ U-@{"'`ðuÊZ¥‹¨¹ã»¦’Åyâ?¬€CçzX²bèÍP½=—ðU¶™/}ØÀe_Ƶ”“A$Pñ9Õ:GÁÈý¸ï[×õnªž~,›|ì¶n˜`wU?"øù45:[y|·H Lzô‡HI‰Ï-”fø‡PЏ‹yw8 ÿ¥Ð5ìýúCþGŸ¸ï?ÌðoÏÍh¿ Øû¯B? Jønþ¼dð‡V¼$£€ƒQ×åÝ·ü›¹b꧘ӌªÕÔ7Y³Û„€À-(¥çâýq÷X¹J¯ØtžcE½Ã?ja ¾Ô$Vp/¹ã%ÿª‹4ÏÍòÔïð ãØ,Ï ?XžàtìVX´Þ-i ²ÀK“xÑU®ìÞéJÒ'K¬< 8N=ÏÕ:Iy·Tš÷t|¢Q«ü¶Uì5G@@ìÆ˜ó8ÞºôÞQN—X†iDÀ‡°T2^gs?f­luÿÄMS 2ž˜d:ŒÓ%5øÞŠØ´õ›Æ<á`;v‡päš®<Ù-„Ý º,϶)7—(zÁ<ÿÑGŠ ?tæéìs¶¼‡ñYójÔ‰æ¿\)¯ªËyÕµ@=…M6À¬.àP…Ú¦2Un¦þŠ»ÎY|uZ›»%/Wܔᘹ…ø@+¸)!ªgèÏc1!€‘›¯k e&ð4/× Cv„d¨‹"áM¢ÁÙ½”ý’ÊXà9^²Áµô‡×vz ÅÐ@@¬>µleÜYFõ3«¹Ü3ž àCÂÊcë²­Î@Ét]¿dë9†ï~fÕ '6µË u]Ìcnï5Õ!‹õ¹ÔŽg0ê<æ …²¿sð==F§ûro ÙšG0DzïFð¹<ö0 õÑMuº'€æÄ’4žtJñ† žMk3¯øRŸlU>Ù>Ù9P¯‡|‘™Ð æ5ÖGšy3AdxÁcçœîk_ûê. Q=”ÊBHÀcÝëPB…€;{hÒÈ+¦ÜN@ôˆ5¤ÉžóÜèvWmÎú=•«¨•ßJ›®”½¶°½ˆP#ãX¹ž¸žÌs;¯³v^Á^ó"Z3¥{)–)OíQêp^KåZnæu^ëBwýø<ŽMO\¿ŸÇÓ™èhĆ€GbqºBþìÞÛÏBÊ3Ž;Ç)½ÅÓ^ÆÜ<‚‘¼áR/C/kóˆÏ#Žž^¡ìíw,c*n€ÈÍZÔðß°Kü`-€O ݧ*]³ZÀsŸÛAY*À{d6l`L•EVóµ`…Ïþ*|D—! °”˜Ãv—sÌ÷\õŠÃ¸ð¢Ð%rÌèÖÁd)ÀXÆ"°_,óïAÙ{2@Ï…Ï~WD€Ïú}` 8;§lã˜ïFg÷vYW̵]Ša5–‘vYGôêè6WêF,x9ã%z &-AÆJw×­k«¹R†|—»E—,x;_²SoÔyx?}©f€ÿ“k·i®3 šîjŒ׎·¶&¤:]¯É;CŒ”éÀéÏ)Gi¯ª*¤2j`ÍÕãôíµ)å-Mõ’é•ÐJ¬«'H™ÕÙ†èÓ‹„g±ý >)+P›v¹vO­ÝãlE#l:±äB.¹@ÀÇ.˜Ô‘þx“b—`gÚôå;Êz¬wÈ™ÜI]w«Hù,¤4_Aåç®.&©Eë˜ÝHJ×ú§ñáLm{\—umocûNl8—ܼæ-Ó¦§Tý'Ú$6Ì´‚zuóuÈ "pwçÔÇa¹vXÚ'M6!ÂÑvóMðoƒèq‡CgÌíìŒygÛË­Gs÷´¬@3ÝKÑuKyìѯ‹b²¤y¹”Eƒ€“ ?(&%(ŤEŠÉ xè#ÅäPŠI‹“:O}]µÃ(“ôlä&y•-à`’æ h7>M…Ö¤b÷~YWøxn*Qñeö~xàz÷ «–þ0€àQ‡•Um©›ï2övµSW.~w؆¤y¬Ù :•cµNcÞsºe¶-{WBóPƼÇ«?Sy赌|‡r¬àrG@@è]y¶—I›˜_`¶»¤g³ʶײόù®¢œrã¢Ôå,Œ=¬!øå¡·}l~Á'€±“ݰ ¬~YÇ/låÐ6©ùFšV\po0ß.[…xmpU:@ü IüPÍØ=r–eÇK0Ÿ™‘|<#h¢ú}u’k ^Vêò*ÝÐM«°JÁíKF™·{—„gêz¾võ™Êþ5¯aˆƒñÈç†Ë<Ý ‚:òåº+çR÷'»ÌnR¨ãËê߸ԥA|H$®–ÏZH¿œÚý$ãW>jg‘‹î }.½€Ô7MqÁ³¶^Võ(>-º#9d»NÄ›HŠŠ÷KŸ›§x”¸#›%_«ÅŒ©GûŸˆ,mä¬û^]ˆà²"OóJÝêK·d™A0—TÁžÂ{îä0ðaÐÙO¯a›Ÿ}JB0 ešgLÊ×ÝNq]Õ•!À#ü¡¥˜– è#\WGš‹?ÄXôì¡+Õš¸øCŒ‘tô4! pÓƒJ0B*‘Ä MØA2ŸÅo'=ˆ±[‘-Ö¾!;ˆ1Zd{˜²Hb6MøIìÏÿ ö€GH5K¦.°»wb:93-rfN@àbÄȪB#„˜~éÖ^&+>”Ô ™# |Òaªƒs"'×¥4€¯“ê2€]Í»«DªË…xªK‰T— áªK‰T— ỳz°,š2e!àkZ4ågjA½Mùñ -ü‚ÿËU‹Á³7=ÜÙ²ŒàQÒræV"²Ï­…¦ºcŽŽˆãª6—îÅ>̽.Á÷7Ï ¨àÛɤ£RQ“'Àx0ÂHkÏ—.m`¼ŸÃ~+ã.9x?Ÿ{(ù”Lå° ÙÔˆ( %€¯µyànIÆ=—‰5P/7 ÄU¸ÄÏÊ”µ,8Ô)"ZŠ@ºtz’¢ë:Ñk6ô…ÜˆÍ ®®¦ÈO¦jÒƒøDû@\êÅ\»X0íÉÆ¹°Æ#ºTÏ=×3_øb½é÷R›>ýÅD&}ŸäÖÚzÙ^³#š–ݹßW:rkÓ"àÖ].;r‰ãåswÎ/yï”wqVˆš{*´\†ÖOewî7?KPuçñ®iÌ/PóH(ßšƒö>û|áìLÇ€µMùÅ¡k7`ÇÞ¹š">–©*ZPe®æÙŽc>–}‡Ÿäk†X™ý¬ÃÕ´méJÙÊk7›GP·¹òºY´4) oâï´¡¾‚ý¦ ÁŠ ÙoÚ,˜ðó›6dLMô-Ry·Ç‚q– .M¬iÀ)<_˜«¥ëªÔ|KªVT¼¥Ó×pøYÀX-Óeznj#'¹9,|vC1’^ðš8x$y³ÆÄ9 Óò€Òekì¬rr/”ê5SÐJ‡~]»JN ¢áÚ«›¾*ÓÌڃʔˆF‹¬È|fôºÏ…˜›Ê¾30‰ëèõ`%<2«G½¢·‹{˜Œ•žò·î²Ðâ9-ŠZSìÿÏו¥½ªÁ-%QQ÷pÏ"ÀçÙå_º!€Hþ3¼Õg覺*JÞ®Š<]A_4à!ÑÚ0&Î+L¢§†k]/Ö;njZ%#§ÙœÀCP»¤×9k…$ŽÃ_NqÐ>& HÁ]±~lk¶Ïf ^ÄU‰ØÉ4âý #Ÿ£ciFâíÚ&3q6lØ`½WwAœÊÚ`1y°2q¼Ï™æÍ‚©…ÄÖaè]b;e9^â$’-<ÃÑbW.>÷Œ]¡Ÿ›žú¥¬ºM¬Beù„iÏ2û O*}7ÒE~ÁãçUǺ­Ù5ÀÕÔÊϱne”™Î=‚ºþîi%Öl HûÎZ”bfh@ú”[F ÀÒÔ’Äm¨ˆÀrƒ¸kjA+@g`ë âã’à %%wù$pìËÕ²W'È Dè„W%e3«róBÞF]©œtaYÖñKâWþ!AzjÀ R\¢?$H¹¸7Ð| ŸA¬*J¼bK}ô®ûùÂXUk€«÷>/ã8_¼Ð€Ðq€Â¢RÞ,¥#M”Ë:GVDꔪ)ûçšó)Û9Õ4rŸ®Ïå”×®ÆQм ÐËR.Ù–£ õ²@üÁäcz3ÒÄ—…åÕÉ:`S€Øy›×užËÞœ˜l462ÏcÍYRý6¿Ç8üñÊ Ôëa#ÖsÂÕô~©ÎD–!-ñV A9y;` ‡]k͘B̘bıvT¯Õ_˵”3Æp70áP ¹£ÞXÍdÒ§zÿ´W‰#Ïqh@èÜ”K ~dØÍÄ)ŽR¤äÓ S¨ºæüî2åM·t<*—¦¾áýb¡­}Œ…£¢'(äD‰CaS9½FœeN<é'®ª„bâ̺±Û UaRQ:Àã&‘›^ľ^”Üô"~RÌ¿U r‰!>êÍ-¤Ä™tÑ€E )ñésðI¬´²*Ü .ÅÌ.øÙÈ¢>·‚Kæ3 ÚQÕ/JŸÝ„%fžAè ӀЛ¡…úÿ(M~gh‡LÜ -7Ú4¹ç§ÔæÝtoäkãr \àóU§g;h@àf‰/pU—mH}.{åÂKéÓGî–ˆ_ÀXì#-àö‚¼~yW-ìÎ#±,oÆRåºK¦Oç©Q,b ²ÇA’:ò–sÓHâ¶îˆÔ,âUäxû¤y,;òrí5àc™AຉÒÈäålÉ)w0lk¦®ä„#Äð+$÷r;«q„›CòrŠîe7§©îŠv1mˆMU¾4=_ò‹ @îåvL…ýxŠPg4?‘:™¡\t’Vö@™›X%OÓkXàêØåvÿþé|DÎè\²Å´âí*%ç­Šü0ÍxŽÃÏ~ì┚®¾CÛSžÇÊé<­_‰œ$Vžâ…ƒAQfbWÈóÎÞ®C]“Õ´B/µ¨cÍYƬñHݽg¤@ÍÜz›<2õÛ4ckz‹·ÛhðXHi˜\ìÅq™ÞÊÛí§vîˆÏoõéç_àKŸr>%¯àôé©37®ºl§½ÂŸ0gdgÁªÏöÔ·â­êŠu¯äw¹EÌxÂ-¾•µD‹Ü©0M!Ž†Ã®ÿî ŠøVvÜŸ*¾jÀÇY¸½p“WüÇÂÍ5À¿p/ƒ¸ 7× 7yÅŽ«´ŸÊò¾Ïw$w·<ÑÔl«óA.X‰Ï~ŠQ:Õœp ¸5•À¯K|z%Þ8v3õeN¸6Ü%ï'¬Tvžè§KÞ·œÞ×OwÐ~º 8v¹›¶ËU€Ð#T7ÏØÍ÷û—’Ý<Ã.KÞoŸ’ݼ^Õœƒ’y{]:€t8óâó°uAG„^9"(Àçég°H?üYØÈà‰,øøeº`Ú¿Ã?dº¸¸ŸÿÒÌmÁ!ƒDÞÑC¾F’‹@—…|ìë^XaÎBI¬ئ¤’²$NMHY"ïÈU¥•¼”î+ЖW€È‘È:wqF‚ŽKÖâk_Q•=v“£ø¸ª¬Ö€È¹V€"z4æ Ä+9S㜌}ýܲ9ó½¦öû6»®Ü àódGO-O vtžÓRìôT<äçio¸yBäp›sñ‰±U~›NÍŽä6ó½ï¦¥Ê4 vÏòlÙh…b 8[R]QÑÍ­Ñ€Ô%.SÚÓ±™Ì@½ -YFÀ-Ç£- Ââ{HÎ*S ññú2Lø¾RßÅ¢´]Àµôú|¤í‚¼.“„ŽœØÈù\ã%ŽD>“­n‚eêóúQ4?ñª“Èçå-š÷UÔß&Ÿ¿*Ap÷LbrJ°!Ëê „1ÈÇ­Êù² ·f b\òeÅ=ç –NŒKž#œX—+-4 ô‡å@ô$lj(»5òMõ‰äÈi+žã)åcªr,_‡ ¾B HL”Éùª`«×€Ô²cÀù@»î:À[|ˆ›UÅq]¬“Îðñr>y«úóW ¦¦Sbé ÀC ­›\¾,r(Ãù¤Óh=Á”%(A‹ ÌcËJbÏ8l½|Y†’ó¬[À¡öÚ1tEO—¡Æ)—ú[ÑÜ>븮“ÝLoŸÿAŸ^ðòIÊq-)G‚÷tšA~Pz`$ïEš¥Ç>>¹_ÁûÅ¢?ö ®Ç⦶Q„Án<nâÐåðq¨¯]ŒAè24`>Ìs9MóÑi@èøÜÅYlý‰CíI©ŽIƒÈ'L¹gb?i«®hxÕŒt)0@ˆ[}§VJ¯ód«|\UñN„NLvÄ[0+Nï)@èί•¶¨Î 9ŠSÞ·ˆ…4€8ÇÚs)ØYÁ¥ŠÄ®•àyŒC×™6$öÆ ìk¢`x#k°?sÜ’‚Ä?åÚc:-€¾ ü²ϾÚÚ3×ëˆ"ÆTäÉi {6`/Ò?Ú`þ6¬¹üh×€ÐKŸD@øúMŸm¾~Ó'q! _¿é“˜¶ ïâ%_êâ0çê *@dÅŒ@ê"ç¦ Ä sÑÄ~ŠÌêðóÅËüa/FµáûšY«Ÿ«a:Ù××$üÅLj¡4@þÕ~ ÿù´e’rÍ)•Ô¢8µ][hÀÇkܺ†o hÂ*@`3¸àm^Kv!»CÂÅ nkîzaäÔVÉ6”uÎj{Tâ’Xªl̲ÎüDlWFA–#Ÿ2Šun Ø…Q€‹>ß:Ó‹ô¡¸Q´ÞV3P/;^ÉÊ)ÚbäFDžAª®l÷ n¸¾WÆ¡_F×B=ìá’´våE3ƒpÓoy9CŠ_„-ž‡¹Š¦Îkä®¶+²-¯À4拈›†ª§sViî‹HžÜ¤«h[|)O•TÞøVå)ÀÇ©©Ëø¼òžö¸5uó·¦NB·¦Ž~kê z—US§ÄSS×Í‹éEü`7µ¬=Ú]’' jÌR_QÞ>¸ßzy‹òäÔ ïSK56].÷E¸Ü¤M—Ë}3-X[Ã{µž:±# _S™7övÝF:‚MôlÄÙhY‚ÜÃañ£ŽÖÇ2™wbÙʨ´]«ŽíÖ3nŸ«¤K~ÏnÀ o`èšöL>Îhœ£)zLB…ûè–b†­4Œ‚“MÅå;ùMżI˜ü¦ÊO(ùƒ6zj@èOîàÜú+¹ÓjÀäŽüHîÀ#¹3èäN˜Úað—dÕ4â¥x(!ïGt'93"vë ø<{†^0žb•ò¯AWßî«fU^W»‰£¸iƒ¾²S¡ÿÊEö€8P#\n±Cém¨ €×£²b½”+&yýèfK9æÉ˱NÓ€žc¬Nî4bÅ>âLf|f=Ç¡Ú8Þs0Rqr/‹ò•ÓSbObFän„i3 ¾mž (hÃ8lp‡ˆc„©P90 dr–ν=.©ý@{Ix#wÏÝoÙ Îæ¢6€ÃãÙ·yÃóùü˜“³Ø  xò¸ö³D—n²mPSîãëE6d¢vòèåãõÉn·D/_/@Hp:€ÈLîÅ´¦‘0í1‹%nh¥Î õ&GÒ‰r5uð8fL´EáCÖB÷„1ˆ«1 Ÿ°,KQk€{HÛD±ÚÀb¥®bŽÂq0çúJÜq€Zp±bs ¸Û¿M±R¶µDòá>[ežðè¦8ªX®KL¹î?H“19Ôl§§Àp Hœe(õ—å-¦R—X¸˜‡¾¸Hàè8a"Þ1ˆÍ¾|WJËiì5À œ:8ÙE‚V\4±£–q‘]$hâ¢"«Å?Œ‹¬"Aˬ³-³*“©|«HЉjvÕ8E‚™¬{¡[±ÐÓ´!q"–< –¨’{‘à÷»(2GZÓÈ÷ËÉ“‰.¶¥ Gì"Á{8²«p„{ +ThCË®}Û "pêé'6Ö-=¬_ #U†VcÕŽ{k½ÒÈÑe\ûâhÛ7è»f!ãȶíÞðKž˜" ^ŽZ‡+QÏÕežV6ãÚ@ä²L.*¬í5€xIxì$ñ/O߬]pf&¿kÄåQ'ýÍSV øxÉ}xŠˆÿ ÷AU ‰½ä>ðÛ.QŸØ“v*\gºŸV¶2Þß?Rá\‚[ºMÄeërU¼€×ü+¶Ì €øv. q׈‰o÷ì;ÚÏ;ˆ ’»ã"ÍÔ]Z — P]CrÍ/°õ¼ë5@Wf«o'¯óŠu`·A¦ëšȼ»Wñ™^´â¯ì…+ÉÊË¢ “Ø^Í<×.W½Hüçs8Mþ ±|ïì}§Ìê&«ÌO[ð'DäOÄþ³;‘?¨»ð#g³±¡ÇÓuìn¯…Ú¹òűȽüXf¨ñFß-Õ?q~â¦À¾)õÞ6ûŠãyk=¦¬Ÿç>׷¶[¡\¤IüÔ+ÄôЙŸ•œ0ÁÝ©Mò9íËnj+b98[¸¬£ùÁq‹7·uë€We|Z5 rh‡uQŠYhÚÁùøïŸYåh³Qz¦ ±ëÔÖ²j«7ìfêÓ+Þx6ˆQÏ4Àœ"d¼¶ål˜ÆýÔ€ÀbÅÊ W#B_L`Å©«x(Ó¯E±ÒÃüÄÃe†ç”ÉË6ÇÃS×K¯ÅF3ó„øV”ÝœèVu»Ü$Žà¸U–g1Éu2ÕŠ‡–þ£b¿ é¦Ñ+V e¿‹åxÂ{Ëäå3ß»fﱊ—$/wƒGK¾p™N^~W¼V,÷œi€+ CY^8”ÉË”…KÑnª€8Ôým-‹íÊÌlGdžk³UJ@¢½tä"µåÕRäVH@j©UJý¨|9÷º»[½æŽß¿§^^ÇÜ6£Ìh&Á}$­bʳ‰ÉÝ=½Pn=ÓPÕ'7?aÝ©ÂMgT"wÆìbªÓâ—²,;z–m[i)ø‘lÌö†âJz¯×ÌÄ»Àk‡&kêåÂFÞcÂ/`ΛzÆFòñá”ó&^^ž$×»9®« ¤MBG}ºß¶òèçN"]¤(`à&繇Œ#çUŠ(@ìe딳$·—¼ú¹²ÛàTuK3»|soÕhÀçaEÇÄö†Ÿwò„i;Ârßà °UÕm§ç¦qj÷zÕ€è È34c›54ë5€|X" EÛ­X¤@ùø«ºÇqÒR©ÉWO«@Û¿*_šíªzª¶¨:ÈãI'¼érªºi™ËÂðaã4GÊ©ê¾]uSñ'«èfŸ‡„=/ª9AÉ#m$Ï÷P‘*:ËÄÔv&ëZ±Û3 4@þD~òúTcu¿ ÓR¾ÝÁrdG&ñC߸=)ß5ÀvœÅÛ°…Ó#Çk¦$v¼:d½è²çY‡÷*÷BªLEž|\ÆúÂû´ä– J©7gbÌgfIœŠí£êêêBZA»%.×t)·Êê¦Y"J¹ ít¦Óhz‘:Mâ\M™$&'Ä}Y2…Ç*z¬“|žwC9Lëë+dÑJÕóbԀР]›FüL¡«U`üÏè.÷G¹Ñ S6V±˜+¹D'ÓM85L¬Ó9î)”MLj‡­ä¡±!¯ ŇCñ¢Âñ¬ýJ\OÍ|p¬KHRwÊI7ó¯ñ5I½~$ÊÍüЀ»ùj_k\³òZ Ь\B‡w<Ï`Î bŽ =œÆwÚµ½iyŠC+ÛjˆŸ–Ó¹´œVÿP_xÿêrЀW~9 éòóxÍþ!?_œ`$ù}¹ú¦Ÿ' ã>/뾃‚IƒÇ‡ƒæ¾à„wàÚOð©¦ýV à:š@ÒhŸ0ƒG™˜†~Õ€ÈÏ"$ ÿ`‘œðƒE²h€ŸE’*$ ½,®Y$iø›E‚iŽ4üÍ"±6ã9 ËU ¸­rq‹~ÕK[4ßy ú‰ï‚¯tžW®.ý YНBÓ›ôûWŒJaæù8Vɪu×ϯ¬/&Lާwé÷›¯6&JR·Úæû²òþDšjšø7µ… ˱k€ÙšÕíÈ_us¡wËO0>\.zæ„#ñù¢N‰DfÇÁ3ƼUt.;óâðõêõhs¯±•…Ä¡ÊDHY-¦‘É·°IPÈ¿ûc°Oà GI§|Å“RšxÍc:&>=T!‰_/Ÿt|߉3_œÀøî¿ª_Æ31 °«âñÐØæbëž o­%&ËØ2ñëî õ ËlØ'ÐÕïe±T@Š se§ÄNd|ÝQ S7ðe‡|w¡éÍ&½*Áä|Ã[£ï@½\Kíõk©¿Þwú”í&ñ˽ºÂï½¾8¯5àãd®ùµŠ¥n¸òv–%=Dè«T†%ˆþ0,áðð¤Õ€Àñ#´‰¸Þ0õÿ|]iÒ¬ª²ÊB (8‡s"î ^Ø”½~¶¥qG•NÒ/ö¿½‚R„•}æÒÌi~nÔ£.ñ{6Z’*«ù¦÷¢ U5îÔàvÎæV\ "·},;y¬9\eq²±lsp»Aü’ñ{ÌK¡†^|vƒàD8ÏçOľþ‚JçjÉ=*@Š1Ï»¯àGEß´LSË)„ÉŸdâȶExÿDvTi&šIS§¢ÏoÞ «”èÅ÷.ŒS°gûÞxfWß¾w`§ôñ:ížµØêÀö{_D('ý4Bõ¦Aø,S\»qa\@׈^T*FI*¥FÁžÉµb 9=Óþ—þ‰»§¥ZyZçU—,Â:§[,³E3ë¤\sÀfÆ¿ìÐMC¾ `u{’=ø¾¿9éåy°Ûf\³a†/7„ú~T·mFÓÕû¸`o_ÈF~n%{í¶à“h .·:~¡A±úÀ4(‚ã}Õ•ò^´{'ç•Q»¶J—¡¦u*;¦^ä$póÿN’rIÀÍ^ãߢæöê¦Êyöì^]¹êŸ½ƒ|ZÁQÒ)Ýd™0kÎFfí¸%¢†œ"§êàê^·×ã%ÕÐÓ½wºŠ*A ŠÈc™ŸÍWÕ•¸$¸‘Ϻ-Úï¡J¹ìßOQ8)çý›ˆ#‡¨¿©—…¹Bõ;)ë4_æML C|‹e,·QúQ¨=ñ0¹Z‘Žc!³|Àt÷žÍLܼ—l¨ÏÝ{Ê‹B?õDuEÔ-=gi½©îQäÎ ºJzŒR  Ç¬ 1_L’/ÊÀC·Ÿ‡Žù3•S;Íõ$±cÎÍö-[dI/Õ%?W°å2B¦u®‹Uðc`a%܈Üb¤8ðeCÈùS…˜BÍŠ{¢¡ðõ)~¸ÞÚdã @îû¾hJ‘ˆtB§@›ÃÇ?Á²Mª²Zཟ’l,)þøÊíWUêB±=,Ì(u9çëP»pI•ºlûU‡Nñï-+Yößoߊ\ÜA»¢ç˜¹Ø7ºFÔãô?R¦»'êì=Ò|[™_CÒ§ÛÕrüUk)Òª/1é\úŒ«õï/; ÔûpžÉfØÒ²+¯F9+o§‹þîtAzœg#‹YÐ#³m‡¬’ÉìQ³AnÑ*ò6È•ŠfÏ?þ¢W)8«qKQKqè­Æmîj\ŠCo;UK{ˆSK;¨ZÚ ºuÍÍ]×Lu…—3«â*[¦ºÂËšô©Ê–)ŽœŽÿ—ýÿÍû^ZÄë@¬ëNôüÈy¬÷d™J”|ܸ×Ù¢h/EPIˆå’æÊZÞoe~èŸT¦9ùmóßš(@äT™ép^ÜqJÅ_;åž*{Œ3K÷l­;/@¬'·Ÿ1§/g³?iiÛh½Ãw¢+f5gòHÅnchybÄL§zÈÀí®’µY›üÚJÜFk57@š¤Ó?A/ÅÈíÉãôAàØnùzi­g±iGŠ8úÞ¹•Ms$—±F¬Ü›ì²ƒ„;'o&¹ØçæÈö¬¯Ÿx‚ÜÁ—®õã:B§O›´ûuy•(€¡¥dRµÎ’q_gýÄqÞÿÆ­n‡íOB¿î-„ß8œj·tÙ’”D \Jù¡£ž“û©ç¯š+r ÆAŒ„¾Œ»˜fŽGžõéï+y07ÍÉA$ñKbQ_×!®åˆŸÃð×ÌØ({ ›‚8Ö¡Uà ¯Ö*Û•¢Ùv‚  c¤j Û=¿öÔ9Çtúå£þ‰ÐõÞuÉxT"A€†Óéøt ¨)›ô™ -•5á’zæ­ 'e=çc1è°fóÓ–ò*_*!u¶åržnUÊ«g$laÑš¯j¹ÕØ’w{5ˆ†éµ ßO¬"‹‰:óÖt;Ù}>¥Zøè×ó=g…ò“]ÈoÙ£ªtüKxÉÒOá=+ ¼ÀþV®ò[0_!C£Z¹R;y^µ-Ó:Š‘¸þì’8+/Ï}^âEƒñ¢EÜxÑ âE4ÚTMËT‰>‹4 @ŸUUÈŸ@°“SÒ`„·[×)È·p:@Y%Bò¨¯£Q%B4¢¾Ú™F•]·D¨Q%B€x*€vYtBOÐ.+€.@ô|†«4†Fà‰:KchÄ^ÊRWG!°WY Bÿ`‰» ‰Ú¹»wR£ªh;yU!]ìœUHàQeê׌͔T§ÈhQ€È©•hT­µ“{UÇU+Aià­•P¥”ÞZ‰ÔçǺj%.@è¯tØàùwa "¨°¥‘…-Ô."p [Zp [UØB£ÈWØÒ¨ÂêL2^ó,Ç Fª¶¡Orû€JÑMšê,èˇyŽ )Ëo×–_@w â%Pê™kÅœ¤»]T÷ùhsQKEÝÁ3§óŸÿGSŠù¼”2p{êRL¾¤”ù Œ*é¿©\!V8þN3é9‰äVQ²Bzh䬠\\é==S#;§Pw|Žz͆¯0)òì·(åC†Ð[´e.Ô¯hmý"÷}œä×â+Ôü{æ 4Qj3 'ˆ<”âf×¹(‚  ù<«öP0üp˶¤Ê¿Àœî-§U¼Œm_OÒmΈŸÚ¶Ûd””…þÔ}€œ~@¢Ξ‰Ü]ªS½Ì~@Gßó$5R>-Ò‚›«uU'_!ÔŒ &ÓRK²cþÛzp‡ ó¯–›”¼,vç-]nÒ<=£fŒùÎdÊM˜±sð(sïÅéìÝÛœÛI‚@˜k>œòbì¹Ê+#VŒúÎ$ÿ‰c”)Š”ÙéùÝù?]Æ9€˜E1²æe>¦eÓ€Peæ^9/¿d®ef.eÖ "ËÍÚ‰|rêÌqPçá®Ô 1†*5fYã@cì”Ó£ 1¨sb4ªƒÆÖ$ý wµs^Ì:‹æz⫳hT5r^lÑ|ÕYP;çå®’hT•·Áù]1Ë »‚õ{É‹«‚ÆXao®”aCæFRÌÓZ'¶.Ž2aeÂÄÌkÂp ©kDº5Z¤;&L¿Ô<ì¬FÙY:­Æ]!_äíŽQÝͳ‘¯ûhP4oíS¦ÈÛÍSJÞØ;ûªZÚ_UŠ”öùøj^¸ªÒ÷¹h Î>P­ÕXjrZñfYv™hÅËìîãwqÀÞVù.m=æ&Qœgý[W û‚}°? •_)ö!¾¬yq/ú¾¯@û@N–Ó=áÆŸàg¼iÈ{¨½~®ÎôO„^@«2ò‘y¿ég >À&÷€991s²n³ ’²ã º|ƒû<ï•P8Ù'ôhó}¬êA°ßÕ3 @ô82€q·ÁbF†QûS-cRʶ§ìÃ|¦Ü9Rg–éŒõP‡›I&ö²àã“8r«sÑŒÙ9éåíŠdXKá4cŽâŸI´ïòí'·:ÀîXé<œ‡|Í…‡“ØmA+6I6µ"ÜÌ7ò–¼œ*„`½Ä+š ½€F?ƒÎG;5­´ñIQêu¨Q'¶²+²¥.å½°3ùäÉ¿ñË•=ý ñCò–ó$}b÷F}<*HµÉëÇõ¾ÓV|à©atéa0F‹pþ—Ù²*r¿ºnÊø雡O˵€¸€_/Ò{ô ¡3Œê—®+—\½DN´¸Lª¿û{#or`’L…L¼ÌɲæjÔß:ˆTp8ÕÅWܽÈÒªëV@f9‰d±‰s¹àgÔ¼I¥*ÆÜ&Ö§R[Ôb.ÏÒ+€;®;ýÛ~© г ô%I¦ü^%&€>ŽT}ÜG*´Ë¬®ðÃ/©¿R™»±YÿÿÞ¢"?:‘ÀħAÀù5ÛöÛ2‹’ÔȹU-¹YðBRR1TÝËDn†½9Ä{,ù6×µHcÈqXŸŽ˜=Oû%­Ù úAqæ‚4ã$N”’Þ=ª÷~ÛÖqW#O;?³¬—mýÊ}p:kªm/ªEÄLJŹND±CVlðöG]²æuù§È)õœÆ$ 1–鯫V©gr—z2nb¦'äÉÐ5§ ‚¨å>¸WоT×CRGª]s)Û¤ýJ R91·gÿ|Ènª—®.™ñ¹×e¨ùÉTìCÚÈ&G 1_î ·˜—bÏå[Ä>ž\ûVÄ@Þ#'Fê0üñ*RÓ6w¥ˆ™1¦qÍ¢:ë5=R9 ‰a䶸WkÈ·z*sAAFîÀC󳨘§é©8ÝrÔ™ÐY}6LÛÍpnŽ|¡Áã8’#ÕÅ Óg®XYT•¨aÌ 3ÇRÿ­b\9Ãñ#]EzIò¬•ç˜GÛºû\~—LÜnÀ׿•äÆ7ªÚ‘®ÂöÒJÜ- ¾o±åYÿkD#/VÐù ‘¯þªúè3§CÙÕ&_øcøåLÀíP»ªµŒ¼)sòbŸ*ÆwzªQl¿E%þ ü#£×o‘äQ/ßåûK$=œ °òiÜyX\è~2Á…Ø78ì¯ü®¿ZÊ £ Ò£ïO¹0ô}Í‘›‚e.‘«»Kííš:95,¤Ð ¿ã_:ÿJQÎÆBê†Ìeüršì+ ZYèiÛq¼óNt,fa Ï—Ä¡>P4:[„?šÙ¡ ;L[‹ŸpBAW”¥SQX!ÿ<ç¡™O~pÚ‡]!RKæDÔí3#VäŽ<ȲDw«¥Z…¾­Þþ~sÚÈ­¶ƒ(öFÍr£Ü”™Ó¤OTDý1ß«"†EÌŸ#ËU2pK Æd[™Ât ÇdûN¼Ê®,òæý}ó¥›Q|ÄtÅî[·­S'BbŒ~üA÷áoo7¡O:3çokpÞªlž;F½]Òøá]û¼‹F~„HéÿðkÅ ~ÀÝãŒ1o¦ÈÒ×Ü‚8ä[ÄöÀ¢3énئqåy ±ÿ-ÄOœoúž!ãæËrÜÊMÚ“ìóìÊ!:^TI)Ê<ÅþŸØÖõú æˆe'€ú7J¬pnà º{œ1í4·ÜÂïÎdý.ú@¸#±pò{üó/?ÒÎÛ¼Tɾ4£uD‚p«µ¸åk¯G \·Y¸Âõ¹…‹ Ü:Z8ê¹’ ¿•_u%±&óJž°,Mò\¢¶jÒ©éLöÃDù† #~¿‘“ sè¢tÑðßé>RÄÿ 'lžæa¼ªµø3øSÂ4†o«iþ þ”0ÍŸ!ÀŸòú¤3aOþïÅ-×òëê~¾øM×)~• ³8¬¼ô ó’Ÿ#0uÉî»~˜ºd÷˜]?L]²{Ø®‡§IkuÁdDSZ]ðy2bu*XÓž¤ódÂ(këÝ„16W ºdÃdÁÀKæâ Kæâ Kæâ KæâáT7߬ v ­û§8©Òi6a€e#l¿…S¨cbºÊ9éÈÒ+ç¤#ÿI¯œ“Žü'½rN:Uâi2¶r)8'ùOzåœtä?é•sÒ‘ÿ¤WÎIu) Çlm/xÒxÒxÒxÒœüÿü×ÐÖ7ÃPß{¬MÉ'¬òÞ„!v ‰@›’¾½eS€aB<æ:±žÍOˆÇ<¬ƒ óªˆSS$·ýzg¤xasÒX?Êü°%IƒnÂûÙÈ»›p7a>y3Xw:„¤×`Ýéðm5}§CHz ÖA7¡%½ 3WÂô!é5Xw:„¤×`Ýé’^ƒu§ÃwéÕXÛ K/K/K/K/G¼‡nâ÷‡àC'`» óQÿn: ’Ý:tôm5}è($HvëÐQÐ.± …É`: ’Ý:t$»uè($HvëÐÑwAb½é‹ ±q° ±q° ±q° ±qÞCg&ÃæÙÔæë3è`° ¨õ驪3ˆ!çlz8ï!ð^˜öpÞ£à½0íá¼Â?ý »é|AÈù²›Îôœ/»é|AÈù²›Îôc:†=@Sc7/èIÖÝt¾ $YwÓù‚>dÝMç R¦†ý¦‡íÛB{Û·…ÿö¶o þí=lß `—¯2C¨ßZÛø·÷°}[(ðoïaû¶PàßÞÃöm¡@+.¶~0ýóAÐ`úç‚®3×ä Á =5MƆà§=¥ŒÑ”ó« Ã~XQÕŒøas•Ì&ì°8‘zCì‡07„â„?ª] 59aᛩ¼(„·÷èÛ[QF¼½•V”Qš«œÜ²±1a€)/Š@s•Ö[QFÚÏk™•m‡ ê·C*ÛAÔo‡T¶‚¨ß©l;QØ\­Œí¥°¹jØ!ˆ‚×Ù´C¯³i‡ ^gÓAôÕ©n{µCnW5b™7X+†ŒÆÁúXñËjÆÇŠ!£q°>V Û!†ÑˆbØ1?V Š6ëcÅ h³>V Š6ëcÅ/KxHOþ¼|,WÀ‹ êl:Pqð¦J)ªÁ@5"L©5n É;ôŒ ˜‰ø£VÌ03ÓŠF€b&`Z1Æ[ɶ¹äÆïa›Á„ù5UsC,(Í !÷ˆ{wÓUˆ Ľ»é*ÄÜI7,|'‡Á„!`5¥áãèm5e/àRÌSÍÃRóSÍÃôe5­æa ©yƒ©æaØú4Õ< [Ÿ¦š‡A¹0˜jåÂ`ªy” ƒ©æá¹0‰Ë{‘ ÿª³ Cþ0¡qbˆ‹ «Mö r€¬63ȲÚÌ ‡Póì¼òØÒÎK!˜- 3–ðjƆ ŽpØqÄ;Ž@€8ÂaÇHê½ü’*M• Pïå0%>‚³ÝÔ†Ô¼ÝÔ~YMkCjÞnjÃÎ$CÍ#v&šÁàu65‚Áëljƒ×ÙÔˆán~V´]OxÞL;‹¿UÙv!~;«²í,BüvVeÛY„¼Hg­ÕðE:k‰¼ £›ßÈ»0ºùD ÕÆ÷M“}3c59ЗgÓ¼éäZž¨y\ù1Ô<¿)fúžÆþ7=39Ô›† î& †`5iåÕuOÃæcnîÂ*(7c•†"øÖnˆ@R5­Ý¤jZ»!IÕ´vÃÔ§á‹ jHçÃb×2!?–!eBmÈ`J™ÿvu[¯ª:ô•õòÜŸ5ÆÚ`k•jK«¶Õqžþø$-Éþ¾Û9´@f™Ê”šw™Rbà.#S–“[¯—’åäÖ륤ýT{cë!ÞÞÉðañJ’^o`P•U¼20¨ÊŒ*^TeF¯ ªRPZdÎ3dN.HÝeÁ-– \’53&*"$*¢ ”ÂTL/м¹1Áà È› м¹1Áà b:[HìÓ|7B˜ =ËŽ”Ïvm¨èP †¢C ôEŒ ú‚" Æ}A‘c‚¾ Øl×O¯äóÓÂB%¢JqŒËm”JÑ‹×4ãÑZ m»,Y«œ®ü€M\åTP5°d­ ®Ðáý´à‰Ù±XYijÂ#÷¡&‹9ÒèWÓFF&h#1$# †1$# †1$# †1$\ q,:K¸âXt–pLÕU̲”/H#·K~2v¯wÔ=“¤‘Ãí#S¤‘Ãí#Säf]&Ëh \&c~¯ÍËØêŠ£yYή‚[Ó‚]·¦$ÃG'PyÄ•&ܼå3ÒÞ-V³{–<&C ª¹à—[…\pAÕyΑmï2yBYˆö–§$•‚ö–§4ù™Q.iò2£\²¥›^Åf”îiüfäžÆoFîi¬/hðó©4vÞvÃÏ .ôóV0#õXD\:æÜ¹ˆø¼þ°·"æóú‚™8ô…BpŒËùB!x?µCHx?í ,{õ){õ¤/{ I') ö’ORì*(>Ii!,\ѲȸÛy}‘qtÅm”EÎ׸&£÷û´Ù& Ç^ïYqq ”]Ó8b÷»Å»/Ø­-mòÁˆd_*øˆ4@‘CŠ£„HiŒ£„g5ö·¥<« Œ´7o|ÔÍ›äâÛì~›âËM„‘û©{)»/ø!ðUP÷Ûø*¨ûm9½;ÏÀzé(‘â¨`Ó ‹#6­8ö…8ŽX6h )ŽY6hÍ2föà§1›¤¸‘Æì¾`#RÿK¾0Aion¤)kon¤)劉½Å’÷ÓÂèTÑ>Mñ©âa´ŸÚ‘f¼Ÿ£ó»Xÿ’/ Fó^ûÛ ž÷£#ùñ4ñ‘Ü@ɸìÒ‹˜e\ÖDÌÛÛ±XBðöÖBíõÇôŠ„÷úÂèhiGšòÑr‚0š©Úß&y¦ÚA‘ì¼)>"µF¯©…eüšŽ&ž~hXÎÉõtãŠýU4 ;úíoW‰ý•*,8Òšò5÷ót:`1†UlЛv^õ†0á`ÛgôqÅ^¯_®°ý†ýZÒYoØk{c¿ëŽÃî8qÕã·ÂÖ‡mÄlîîs÷BO“¶êYmĬŽ]; ˜²0$5R­ß­€0×õ»Iî/ÕïùÕw#„¦ßËÑK0våØÝ kö—>¾‰Þôöµ6Ãý~oé¾èí½Ë Ʊ¯·ßØ–õd¤×O)õÎÅÿó¶×Ž×òtûŒ„‰l*«Ï<¢§%¦· zlËòù „á~n}ŒáyëÂP;w£ëÖ§½t_Ö¿pæFÝuÛ²¬Ÿÿþ÷Ÿ¦wiÇi('3÷ „åa…(]¹!$¬,•{iÂta”u;Ch89ŒiX°9¹ :q·5¾úRÌyõ0w[ÃÚJ0° ’n"Ñ#„}­!ŒÐAšôÁ B.©mѼÅA¤µ ×¢Ç!w¸èŘ–èz»æ„pã–Ûq· ÍI’Aj7Ù"ü¼ Ò¸âN7„“„”vWW%0ǺáUÉ_s:9çO¿ÌÉõ/ ]yóæÔO]ùþ‚ýšÓÜŸ~Ÿ¦(®ÛÂ2 v¯ Œ’՚ݑ’æ4.ûouCÓQ¸;úq1©ªUöGªjéáBæ4¯fò…K)œÛ«SlN{T?zšgõ±³÷Û ë`·Ûés…0R‚¯E0J4ïÖ^ ÌÝ6\Ó®fþ“ît7¾ LR2w÷„©«;Ÿ—X§½ÕI`NІëzûp*‚å¿°Çã4§Ëy‰-šÞ 9µõ\Ï%ÂÅa+~hþQ7쵟k4ö1ã^ŸŸß—z ³É5/“×_ºë¥½Œ'!N¯lbÅÕ ¯lü+ÒVõjžÎÍ¢O‡6²Ó \LëúÑ’"O¿,jIâõm¶•!Ø·˜Ûûa‚s³5œ$g”¡ªñù9`»/Ã.Vo¾cÌûÖš„%AØtiM a¿.¶öFAózC’O§7„©ðôx;l1#õ Á%Ge+BiÄHeµ."¦1«ÏebÊÉŒœËé aá—Vׯ†Mp¡÷çi½*„˜óÖÒ&Vfá&k%»ƒ°_g5¦|{åÊ8`‰Õe¬¦%c:ÄâT€]ÀÚ…»”>MK=þJ¬ª•û „eØÂ_°Ü'VµÍ¿úáý~>+@bu©7·¿éêô>×#šÞ„›uëk»n^éÂÅ(,í?Ϭ™žàXR°©ß#^¯=l~6ê¿KS6³  3FF <ÙÃ…4ã‚áìæ.ã‚¡ÁO£‚áLQ:…Î4sn¤Þ4ýÚÇ}xó¸Ü\”Ëû¤,ìý®O襡ܶ]%þÌÂ$¥,øksž9 Í:£™‚)J^Ú…Á‚©ƒÅ& Š9L( dÚƒÂ`A1‡ …Á‚g„ÑÌÁhæ€`1o. f7½. fgH. fÏÐÓhæ€`4s@0âË’þEÆ ûh™ æ£e&ˆh©;-3ADË¢e&ˆm_iÍÝ!¥_-3Ž–3¾Ò%ÌH}´ÌF|ÌGË,x‚k/>¹z#h)rÛk*wÇÏ_SÉ$+òlCt¦X˜ Ñ™bFêCt¦yáNWvB2òÞÎCæ§]¬ü·d ÄŠmîœå¬ôñtü¬'ìçõyDÀY棦ëóú<âÔt]^ŸGá¼^ã¼>H#‡y}ýÖ·]•`Ô½}]‘^Ej#Fê‹0 ñ<0RW„É9i)_„É'¤¶…ÐQ‚ÙBè(ÿ‚/tä’ª#¡›]¹¢êHèfh<ÿUúö¦8A`ooŠª#doФ ÈÞUG2ÈB2FúXHÆè  ÉÂAugÑ.¨æ9e!<ÄÉsVoÙY¯Þì,¤`†,¤àkÝÉQqCp'G wþ÷Ýïõ )>p$ïæ t»‡TˆífT$Ì­ ¿)#Eë F!˜'•ŽézVA¥c xVA]Kž'H0 IÅ^ F!)‚a Á(3RO0 ÅèÎy‚Q(F›×ïõ/l÷ú"c^ê÷ú‚p@OQ Âg|ŠZ䜎«÷…‚{šõ‘›ø,DD1 ó"¢˜‘Tu±÷€Q’ª6ö°Ð^?Ø{À$%‚zÄÞ¦Â/u±WD‚u±WDœ.“‹½,¡4fK» ¼bí-E”0/uÑRßÚ^Ò\|QJÅ7â›*!!å#¾‰H2'·.¾  ð[=v¼WD{ïQÎ<Íñ^å¬íd§·ø}©ã–Ž Š8"= °AGœ4¨%f"޹§Yb&bb3Úc¯[¬8¡žf@ q©tÚ"@‹}HÌÓÆ8t¨|\öí¯×£ÃHÄÃG{f¾^¯¶ßöù»Ášú¸sÒÏ¥íŒ>`ÉL0Ó϶W þþ=Ÿ/Õ¸º®kýõÜ&í±úqŸûzÚV„ùûŸ?ËÓêå¿YŸ6\Ë©=v™¶aþþ]a—zƒÝôPUc}!ö÷êþ·Ýâ=Û[¼fYÔψ&¤W½ËÄdª8A—‰ÉTÑ@—‰sVhÔºLL¸ÌF½Ëš˜A—'˜é\FÄÜÓœËA‡ ΛHÈ0çM¤ÌÓü¼ ^”ÒΛT¨™Ð¼)ÒѼ)N$ÐÏ[Æ=ÍÏ[ŽúÓÏöúsš›Ùu³ ø}–¿%ÐÓX¶·£_À¦øm¤—ýRþÚºµÏ„ [pkßVÿŽÏu°ÂtsÀæÏ©=AXJÁ“V¿míÄõÑqÀ”ƒ]*ÛWðè^mÝL–…`Ó,·°³m?énzZ™ÃÂöºÿýƒUªúsÐôFw¶cX÷¸×vµð1ä-›ËÑðv?·U©'®¾¬Ï[pýµ<Ð(Ž~Ì·üºËº`Õd†Jß&´®qê;ZªÚ<»áÑ•æèT±8ß@·ü¾æx¯?æùB8põ1Žjhš^ãñf·>®YÇ«ûRWçîaªë8–ýáü´déÀù@¶7¾Z¢ku¾½dÇ@} Ú÷W Ù[û6=ÂŶ…ãt®›cï[siëá„ÃU—­§©†÷2+ÁcqÉîb®º{ãRß:rt-롇¹©‘ p«wo¸g׿fŒSaÜë—…pS7 GS³Åå·oŠ ®êªêëy»b\…p×îñ0è½I q›Å,¸õþÖ?o_þ¬ó¼s-ëñ95íŒæ9I~pËz´§î—ZÜæ›½tÕÔ-ˆü<Ù×㟿·,[Õ> ·õøóŸ?{?ÒvpfNº»zŒÛÖãφÊóá—íâ”÷zÀá;Ƀ¸÷ûþ¸ \aqË{²wW6ŸîŠÂZyÜúóÖ˜;v÷S[wh¼i qÍÑ k^×¹Aó—nëñçÏ6Þzóàaìïe}ÅãH·õøówïÓÚn¦òVWA¸m=þL_ãíN§~ï¶Óß ·ûù‚»4·î~E8Ä?¸,„{Ì·Ñ|.8½QÕw:ßL‰âsZZ͹·íÅ®[ÞÅWR¾–U?¶“òÿlOklWíûUÝÛ;„í¤üÏNÊNÐöº™O„¥€»×®ŸOϧ0ù[~[ÓÌõû a gõ6„rý®†°,Ø´<”½ž!,ÿ=Ë\~Û¤ÇÒîCÔíóezϺ}÷&‚°úÞŽÂ~;×{ö¾sQŸ([óõÒ~ÓH€O”¡Çõ½opIà„¦mvB>m{A¶µF¥m¶ÑT@}–5m[¢çfHS3è~riÐgùIÛ´OÛ€>K mÝÞ˜piÛ§7F¤m'—¶% Ý%ðçbü¡j´¬égÉ¢Î& Ÿ"ó!ÌÕ›àÓÞ÷ËÍ–óÀ§Ý¼gí«°p¨ªú@˜Ä‹µxàæYK"ÐBrÀMHi]Sc.—²àéc[.Ëa9ôÛ¬+=;#dPG ÑãÚa"è ¥™¦7„%§ h<‰DQ•Ž ´5‹„¹ÍãÛšEà{rÇ&ÐÖ,’Œjkž4 ÕÖlfèõ}YÊ·5‹$£/Kù>‘0‡F¾Ï_€O»…$´F;B bu™¦²jwÊ(|_³>s;AXøBù`î ‚%!Cê×ïõ•ìïµ™^#„…/”_ûòÚB{ç#8¤Ôî¼À@Žé±ßaÔ&ˆá –P ÷¸ï%€ÚBˆàb˜¤øí§ƒ0EÑÛÁ@XF±[`9E2 z©ã¬«œÁÆ 'c®ïyšZ4½Å1mÙª-„8æ×ó„Ç­ÛÑñóªGýFS·çØ7î}ˆÀ™nÞs×áåO1nù_pï÷£0N†qC{ÆãØã0îó®ïÇg3-.³;a¹î˜ÛU¾n6]»Ì3Â…Cú´ó%Ò@«Þ ÛÔ‘î—C”Vxµ_ÜY§e+î´Cû€0AÁ>êÍZÇX|gº=«ÅüΖ`¯~…µ&‘º_cÕýô{œ LaÏoدµßÚ¹ê^c^šÿÀ^!X2›-Ì­™Í£Ohz£ŸØ´ÆÍõßDI··œÊßMÎÂöj° º‡×a‰è¥ih;ïû¡}¢§…»‡«RO/#¢ðåu(¨‰/AHªNzúÂ~)ÚF”Çáa , ¦×S{±VÎH1}|º’¾Ik 8{IsŠÄxöZ½¿H¼g/ Õû‹Äxöâ[½Ã§%èi’<-1¦´{€§%¾ÕûËz‘òŒH ú6 hi¦h3RžiAäoHyF¤a½HyF¤}CP4МýE $¾9;L&£É‚Ñä …0š MŒ&„ÑäÁhr€^J“ƒ¦—&ÂÑäM0CÐÏ ƒ“ä Åä@F9h19AZLdDƒ“é ð87Ø*Péߪ†Tx…á mÆgÑ’(jh|-‰¢†ÆgÑ’(jh| TBñÐ2f  Ї–¦U{|zìU¾éÚqèÍxl^2eª<Ï×ñÑrúó¿ |µîçÇaIp+ìʧ½_à»ÑCÁÄÕe|7z(˜|ÁÂýÝ©»ïFùëÓM¯§AC²kªxCzAmH-„Q†äªcRq†4ÚB•Tœ!¹dI*Æ|=K*T?E$Þx/3zc…É\v…Ð*ýc½Ë.2»¹,hë½=®¶" h’¾éK;Ø@Œ—Þ@ ¡bú’   _ö‹BH!àW@1…0BÀ¯€b 1A ¡è;qB„úem‰d\¾_6”‡<¬õú~ÙPò ‹à‚Â(l]Å'žL€ÖÕ¯“‰žL€ÖÕ¯À5Á“ кúu21Á“ кúu2aàÉ„o]ý>™0ðdB%ÔÉÄO&|ëê÷hà{Rû©±O“t)Ä7¥øÄáatâÐB•8¸ø¦øøf‰œâã[^J$>¾)õ›8ØžP|TÝúŠ*£{A@ññÿ„]É£8ý%@b;ö}&¢ç°±Á`SlCô׋–— TWTTÔáIùrUf’ºƒ3 >&)ë8`ð1Iù[/|Lhl—´¤C̘š„ë¡T·0s àLSƒözèAiÎÏ^= Í ÂõP"€5M &#€}G0cRƒ4£s¸ljÃËÓ £ƒ—Mÿ>´&£s¸lŠOÃŒ\6%šftà²)ÉèÔ4£c/›ÒŒNM3:ö²é¹®2:ö²é!®·¶@´Z& Î4 vÖ4‹¸Ø… .v¦¸EêŠQ˜¢šµ&Ny ï©ZgŠtÂ’s–ŽÚ½ö©ÓîÕö›$ì´{)Œµ{õž¦¡×î ,vä¿'̧?f¢iÄ÷Ňè_Êæ¿;̧lþ{ÀüwÊæ¿'̧Lþ{»äa]Å”u'tSÖUœÐULYWqBW1ýW±Aï*NsYø ºŠ©8i@ÓÍø-e3Öò[Êf¬'ä·”ÍXÈo)›±îßR6cÝ!¿¥lƺC~KÙŒu‡ü–J·aVÓFê¹³žQÊ×ü¢g”:®9BYF­OozRâÖ¶ºì)õ´… tšó÷Œ¯° 9ó§54‡ ÄÄɾÑ.pH0irZCs¸@Lt=p^ &é^ZC“Ì%¶EdÀh„ ħÛ`4rˆWYÈe¬'4³-@£1 ù««`4fáÙhÜ•ø€J<‹üJ¼E¯Ä ŒWâÂx%N`¼oÆë%€Ù¿è…Âx½Ð ŒÓ Æ3Ê„?òCžÆG~„1zÁzFè…cŒ ¢+™äo2At%£]0ŽÔßúyP~æªïQ°eI.œõ=}Ñ6ÅaîN• ÚðŠ9uy&tyàŠùÁåÐå+æ—§C—®˜\ž ]¸b~py:tyàŠùÁå™ÐåÉÎåiÐåÉ’“Ëc¶rÁYÊ·ŽC&OÝz¡¦¹`×…uííB.8ã žh.8KùÎ| ÎRw(¬¦¡0{KÞ Ó†½%ï …Q˜pÈ„µnYÎÕºMX놗év/Ôºe9ß d!87¶A3æÕÜØͼ<àÜØͼ<àÜØ ͼ<àÜØ ͼ<àÜØ ͼ<àÜØ ͼ<8Ë‚¾¤ º>ù»¼ ësÏUiÐõyȈ:Ôõ9F]Ÿ{®Jƒ®ÏA×Ób‡-4H8Ø–z»¶A‚;Ë3 ŒÏòŸåéÆgyÈo‹¹ºO³¼’É*._ 4˜Ç|;@ Áœ-‰!Eá9[Ó! ælIÌ„4˜Ç|·E AGW†J‹3˜îy·óÆ/Mø>Òø¥ gºOhºç gº7hºç gºwhºçɹãW¥ ¯›aÐjZAœ¦ þ w„¹¦õÖE±þƒ0á~éõZè—fž—þ®æ¥™{Êñeû[5Âê×Ŧyîç•‘¬8‹ ð¯„ñÁ+ãƒWä¥|ðªCXÌ (qŽnvALÝ—"6Ðu_ZAœhÐÖ}‰ rïÂLŠÍD Øè1y©`¢+¤ØL@+ˆChb&Ð âTgl‹D{’ݦH@@+ˆc¨ŠÌaü,‡Ü?"HãgYãGÁ"gm•5~L8óYÖ—AÊ_1·¾Œ‚EÎ;иn¾ê;X·Œ+®˜Èºe|þÔÆjÄ¡› –ÚB‹¸:E›^-U[Â+BGŸÁ°V´ÿ%¡Ü!ŒO(˜àâoþm‚‘úE¬¡ä›YZÕ¦`‘fU›‚¹|™ ”¸‚¹|™”¸‚¹{…Z%®`‰ÓÅû¹× â™7)LøWpB& ¹.HVèiB’¦î#Ê5{šyËoTT8ÚT˜ií‚@›Š“8Ûj1‡|kwjyä?äZµEþCNaN¶ìŸu¯Oˆ»›ÅîÛ°‰‚9Ù²/ëç†0÷8!|o èá*`ÐÚÙÑCrÔ «&Ô «&Ô QrªX3·>åÊ ;TâQÆúΨģŒSâ*ñ(ãuò(ç)Úh pff„=_jõ‚ˆ¸Íjf|)W̳< ¥ž˜ªU”BrF‡Š/Cý,8½x“ðèÁéÅß'3Ö-aw›B¤\xsB9ÅIËGçΆ7\t™yš-EÆ{m¸ 9ßñ 2Ÿ¶Lðâ 'D†Þpº>ä2âÈ©ì±ì×y«jO¥G×ÂȘïý'ä0˜“À€¢eÂQt‡[/yâBŠ–‰»ÔvogŽ¥Lù`A2~³pOyªA#æFT»qèj†´W–ŽÕøV¤Gžáäuý}!̽ °õ1{B&\Xz^jÍ•ØÑ$‚ ʯP-ì &´‹¸(ÁW?-õF Ú;Â"×Õª—7óŒÝ›çò‹0÷…j1“)Þ`]g>!÷<Í:„«p×<í~ã›ZÞ$ôþ6½Y8èÆñÛôò&‘ÿ·}æÚÓÂMª^O·¸ayáyš‰# ¨=? –Wz3Z~³%£4Ü´ý™òU°Ä S†D’rR?¡Ô'™§×»•zRqà~|ÜJQ&ž†©ïoo„EÎËÞÓýÏGíiÊu‚\a¿_Q"ŒyÚõ:ë§…ž§5Í­DXäêÒ/|_ªOH#OÃïy¾}æ8Hk[b{,SæXÖ$ *Ráyš=–©ô<ÍKoÿ~˽PWsJ7¿«ê 'Ò„•ÓÅ*¿< „¹ÊMU™§¥ž§µíç‰0÷RÕ–fžÒö§Çä2yš{Ú`[&Os/‡è­‡*‡h„*¿é­ÇVú.~kæ:H Kh¥rîàXf‘çiöXfÂó4{,3á%-Îl9ÄNZœ±ÂAšj²ØKšj\÷ ¿™â1‘%¬"¿e\”ò[–òÁà7¶Á<å·Œ;ä‹ ‡<ó8) 2YÎ ê…<ð4¶z!-CM©<ôôÞ¶˜‡ªù];ýÛ"?q}Æ—rrá%®â‰0¦]½åÞœcò•j¬æœµÂ¬5˜Ç|`žxžf­ÁÜ7Åt…ZÁRÆtßu–ùm™WgiÌ3¯>ÕTƒÝÙ]ú´EXäªi]/_Gj£ëex—W}‚ Bÿò~±[ß*XäÝúâ°ÈYoi·^Ìé‰# áyš9–2ž§™c©`.Ûr‘'Žd9D1Gø°¥ ¸2àfØRri¯½³frÉå³6˜ar¤ž&îFêe1¦ûz54(ƒÜÓ>ÜР rv³À~“aÀnØo2 ^ÙϼLbdßÇK û¹Ÿå>cƶØO€n[i±žÇòû±¯{uOYÚ,ª¦,HÈ¢{:ÏsQ«KåÒ¦Gõ0Õµf^×¹VÃL¤m¥Êž×—î!ú¶˜[M¶AÖÎrºOw7·Õs.ÛaÒª½l¦›çEĆ™¼4>Œ©«n®Û®.j3„SÜt£²~®úê2]–/™Ë5ËßÝaÌë¸m\xn·Ï§û~„SíÝÛêëêæÍ5YpÖ–v—ey·Ÿ×ÝmFXäî<[¶êÊ€„~e‡Yâ÷¶x·æàÅ ›mQ`Â!°E³•Ï a’ƒ–ˆaÎ9…mÂ'ly–ª°R0ÔÂ÷ÛVÀ¶XÓØ¨Ë­ –q°o‰°ü[ˆiß'YÞ€iÜ~õ6$Ü6Œ‹²¶ë›pÛЮÜDaì6¼c·¡/ÆnC_#ŒÝí$ÛžkÎõ¥0v^O„±Û`Irj|×óÏíöú郙:4‰š»±ì˜9˜)±I¯7ýÖ®/𦩄 b÷m÷VÇŸjæqD˜d:–Ù#’ùŽH§í9[Ìâ:"˜p¿è!÷у}ZL8:ð¯óæ½[IÀÍØ`jn–<4«£=xì'@§7Ãi{:½¹ŽÂpOó[Ëeë5‹$àg8`šE’èÐ[[ÁÖãÛ4†E’ˆkTÐâ I„—DÌ'/‰Pû¥ZPáýR-¨‰ð~©ÙzAÚânÕÝÆbuI â¼]7q.ç¹\ƒ¶ƒlÆIžVÕ—¢®,rÎÇß·ú§`ÉÁ-͸¹ŒVÛ7μTUÜ/¦ËuÙ1„ Pã»#º¨ñ÷ëò{Ö“ΉË~é„C’òó#˜9–'2™Ü/2Âx‘!0æ uVdrÏAê¬È䞃ÔY‘É}½=ŒÈ¤_d:„ñ"C`ì—j‘].˜hÐåúR}ÞÒÀwËß~ièUjàƒ„].õAaÂýR{R/÷Ú§y¹÷î›XðRá×Y ÂxE`ÌKay¥_;7ãµ3 ç”"ðhÓ˜2ÒÁUý6‹\Îåuu.„ Œí7ÖÅe|Î&­sY™àtÛwCY" Nïý¾u__ÃT‹Ç5Í3³‹m–ñæF¯}«OK9t&_š¹\Ðïâ‚6ÂrÎÈ—ªÚ?ûÀ}¤m¿,om).Ô£½¶ÈÂTlÞ¯up£þuV˜^9z —i~tÂ"g±é<÷:”iËõœ°©R°Ìw³ËžßÜOÆÓ ÷K­¤fŸŒ§$î¼…€×¸ó|ïÕºe!w#®#_»íboì»»Ùu1ý³C˜ÀÙ¨&î<ÔÓ¥E˜tmM{kiW¹b¶CM~[â Ù.ìÐ’§­Bóûg x\ïjº5lÓ]¯Ëœs±À*Ï"~XåÙùJj½6«1õü(c*“œ1U^cJÝ:“™d®ò®÷`mLÄ–žb"ÄD²³¡gyã'$|¿o\OÛ\°¹²Ì Ó\–óýÔàiyà…é§åžFÞð yä…é;g€UIV.½êè9!,:EN9Íå!Àª"§ œæÇ)F‡È鈰ø9íhä4—ÇŒŽ‰œv9Íí#9-ÿÜÄDNs êÈ9%ŸsÓ‰Àl€õ8m.d-ÁE§@碾¾Íýú‡|¬Íè˜@ç‡:Nº®abF/‰<ä{Í…y|H#ªéÔ ¬þ¶eKžÆ$þúé2!ŒIüÕ&ñ—LJÄߺÀ[âïþn¦¶~!,árpæÐÅîé-*§-ªÜZ-ç \ßOdAr½]ÅM)¤îÑ¿ÿÜ¿ù„í˜èÜÞ°™WËeùÁ…§\Op qÖVJ¹ÏºéÝ„0w“(ä¹”o9…<—±Iä \NZ8^ömØ’Èã{ªÔ]]ikSÏûõµ)Ó™^<î;Å…ÚØ_gÉUzJöýþ¸<Ž á3QóÛôSµ(q¶u_º±_¿æW!̵­s÷¹NÝ„0×¶ÖÝ­iͶFÑWçÖ×Í{Þõ€°Øµû¿¦ÔƒÃ,qìþòÒßtÿ!,uìþܽ»jº"ŒL]7ë;6ꆰœÂöaà ¬}dyƒÓ,«e[›~Ù ²pª¼am/jZV,âð*ôÄ63i_3JpqjûÅ 5Ò*Èè±…å”Ã:Öe_uïaÎáâï¾|5µ‚I>ßP˜|C£ªËë°#»±|Ÿ‹Ïㆰ]¸þR™«IЦ~áö|”dyï2=Z*·‰ÖÙ׌ŽâR@¸[Î×a*>ŸùÙœµ°Ë«Þ¡hŠ[C¿7wâÚïg$8°%ŽzÙNõ8DqpH'k L°µ‹Âä©v±!µ‹ Ÿª Rm¨`¬§3“—²žŽ9È©ÇÓ™uàJÁòS©aCJ õò§RÃŽ”jÜÙÓYSŠÖÓÑ8g"ðj±½+äJÝÏa®ØUõ<±½RtŒ] PϹ»/ßL–qœkíïÊ…‰ÃÀݬU€VÁ˜èæâ\wc£›5±ÑÍ™|Ý\G #ÌÝl¯³jæ¬`ÝÔ/›wÙÏjDE —§N!®µýr‡°ÈiM½1ŠÂs›Í½ }O lß÷_°vÖèæ8~o/„Ñ&c»©ÐtUõ}¿& 4[/ˆë·êì}AÆK7}=°Ø­šúÒl–8α5š©žÞó“ÀRFAè  –¹ø¼þ|tÐ]Ávšþ‹Ðt×ôÅ«¡ËPܾô¯ññ$8wÁÉâ#þôQ’§ReN—y(4†’%%ïuO‘ضQ<ÔKÕÅzÝ»¹#ÌQ¤õ*[ûQ„Ű«7-}[”a‰£¬ª®¦ï¨*j,u”KMP.Ã͹Ó0@[.¥`®[­Ö­{ —FiËÖWØaî—bžg£-ÄÖç–jAʱø-ÆZ_#LX“®¬jå"¬aŸ+yštÅrZˆåØ[}N̰oFØ÷àZõæ2žE.óïAž&NÎÐ6©Û:Cp«8C[§[ë …¹Ûªç†pRîc‘¯‘ûüÄ"Û.ôãµË?Ìi]óÁð×!Ÿ0?Ëû>Ücµ«›ÆØÕa~¨4°ß3fu˜“°ûѪ®ÉKsƨ® Ùäǰ;5ªgò8@rÁÚÉQ¸ˆ1Zë'YáÝÚW[jcU"åwœÊïþ>‰Yê]¾mñmºöKpñɸíÇ`…Kœ80‚.Õ³gŠmrË Ÿ?]û¹Q\Fq›±<»öõ¤¿/×çxÅmýV•?ÍŸFcìhj`«y°ÀîóåI`‡†Š•ë\ª‘ &ÜÅ­½¾°GìM„Åô6µq’‰óëQ©ïªâ³[Uœ¤`ìKUámü®$éQÙnÉtïüVD½%€McÉÈlCü«4œ%·*âV›ÝÉLß?ýè'GûQë‹ Úê¡ïðøtFø‡XŸQn+ùºßÕ»D˜ïꢂʭÏÕBV|™.…9ê~tN PóYöŒ¹`¾8gÏh„ñì…0ž=C`NöŒÜø.Ʋg䀰#{FöŒñì2S–=£z„ñì2Ú {†¬ˆç9Û3‚Õµ%ï­®“‘¿ëZ`µˆ6-¸[‰ûneŸÉ™WYiè'û»eíV?ù¼ÿÌÕñO½ë¡ÑöÞ_Y###Ã?é5 ²¥&Óiƒ4 .§w˺ï<|×!Ì?h†!ÒGïÖ +B¤70ç+ôŽhË`>¼"@ïˆ`ôýógÑ —°Æí™>-±9 (Uo ’èV¦²¯ì…Bw·‡{¯Töì(,°.­iæ½×ý÷öÌlŒ×ÀBC,ÏûiÓB¶äM>9)è:­n£™LaÂ1Óî“6҄У rÏTŽ3Õ}Ea®™J9µä!°`}ErcåËW‘%ùXx¸¼¿m^ì?zœ©L«bœ)ÍÕ~¶GZ Î9aGN$œã9ÂxNA°#§@Nñœ2Ï) S`9FØ‘S §À.ï‘S  §ÀâœI W°§Î}0u0Üì©àºÏ'5Z_¥²jÈM»¹SÇwÇZ@á…7mšÁfvGáe§Ì‘œÂÂ& pÔ8:`sNaE`hË¥yˆ+Ýä=wá…ÍwœfjÍ®Ð;)…±3¥0v¦¦š™±3M Ì9SÕ|¶™½ÇÁ*±=ô)ý`Ç*1ôÄ z¸ˆmzÐvÚº«[ 9z‡U#  Çß—;=?ÖŸ®SzH5™‚àhQ7 h^ÙŽÈdEu0mP"“UæBhÿç 2Ù÷0„öÓ‹ÀÖŽÀ™]Þq¦m®ó–Ld U¥¹õê+­„C·Ov|¦'§¬ Ø…\—@8Ûê`¸,–5p ®™ ¬ÓµQƇd6ã©PC'›×€0m3[y¾ïûÊja¼“ÓwË<É_©ZµÛ0& «UœWê§nª¡°h»2F¥Vjjž§l¼#Œ÷îø|±/»QAìžw‰°BºKNá¨Ý¾åÇæùDa²c9š­†êõ«›W0«ÖT3=xìˆõaKôacÁ•½½I×at•…åq ÚªìÚA>BĉʩÿØ&x£˜¼]…QÌ9÷4:÷ ­Ê¡;8÷v•(j£]ë¹ÚØ#ŒW5Âxµ‘ŒÆ«ä·ñj#ñj£¹Yâr®6vãÕF…0^mÔãÕFãÕF2áÈîë!»/4ÇrŽªx?¥”šuÇô3kjäÔ×ÑÀ)…kñ–¾mSKÏ€2ûõPkSí!‚º.‡UÞ-Ü•Ŭûê{-S„EŽ\þª¼ë•Pu-\¹©vOC¶[#’¼Dxž›J`|nj‹0>7•ŒÆç¦öcsS­ý!B†½Õbnª%®Ø":‹ ­†ÅVèÃu³nV´A¡ÇÍúYñ!ÄÙû–[yº•æp=5«¬1 éQ  +ŒP …ÞA»H“†’xúp–lëæ;H2-&1D#ŒM ‘æ6- 1ä eog«ÑÈÙºú¬#9[WŸU‘Qj]i jÂq×£^koÃ.Ó`2-on;|Þß[‰0aóLïý[6/e3  ’Ê?XHybÌßGk¥GXhó¸ ±¾i»Ž|4rÌòÛÞªUê=ØTt¬¤²qhFX¡ê²úa@A0¯tuëÓûx!r„%GX×Ww©)ìºÕe)—Ò'Ÿn¼WÊ%YÞ]©êiET×Þ˵VR1Ä"ÆI¨òqÑñ|ÆòY}1PIeËk´y—S5.Š Üð#;æKó>GU’C®‘ÃÏb¢ì» Î5©Qÿ½ÆÜèQÿ½Æ§Æ¶õço<œÆ¶µ¢¯§ÎÄÜjPèÃel[ñ{½rïdz4Î`Q4¡Ûs¡ë¬þÉa¾ƒ¸ŽD MèvÄu$ZhB·#®÷@\Xèãˆ0V]—•u…‹‹ëù*ç8ïÐŒ»¥ šåòï´Í.ˆË1 1†”ú¦ïwoöT@Š¿ð:¨á{—ô·E˜ža¶Ú™€2ÿþ1[:ßý´˜d¦FX š~iÊÀëç½Ô†À*  Å¢RW¿œCé÷]Ý*2ÚuS©ŠÖèahË!P†â…XÝ﯎|Õó ᤸ°•¶4Hå%vu#šQ?7&¸„'î¶ZܱȚ15˜ÇšÒc^)rÌsÌGsá>æÉÏ[m†cdsd‰K|æÈºa.ÛR‚H\\ @tÅ™2Ì©j šcN5˜S°œ^sâ¼Ë9§—ÀxN/ñœÞa<§—ŒÆsz Œ0i)<Ý"ŒçiÏÓVãyÚÆó´ L8<#-xF„çóµÍ3"¼#[Þpv4ˆqᎻ°)7Æø}öºÔcU›ªCXÕ“£qTlÙu …6 6™Ç³I.³¡œjú‘ß±Ñv»§çüv ã£íÆGÛÂøh;¶“Ñøh»]qm—ã£íÆGÛ Œ¶m'0á £bzŸ€þ™;:*¦÷ /æè¨->ª^Ì”jk$˜eóv‰*U›´bwË´¥wA«9ÀQ)„ùËR¢¬÷/¬²Þ¿œ9ìÖߊÛóÙê··Í ¶,@W%¼U5sdâÇ :^î4‡·Þ8͡ŭÇô>ª9hÔüÈÍöŸ~~”+%5Âð£‚âÏd:#Œæ:C.›3ÂØ!Œ0šó¹lÎc‹°#1­¹5éÔµÈî)˜PóãPä&ø¢úQÌgìÔžàrng<íé .göGÛg´ô·qöÇj¦—û£µ?ÊaGûãÛŒSx´t¦¼ý¡Èò^0áfqŒLöG÷2Éçdd¨‘!­Xõ4Å–Þç.”)Æ»ì\ƒs€Bï° ž»$Â|ôÄ•¶ÞŸîóÚØöM9ž”)«;¼»oi¨="ؗا0Õ#,ÀúW‹–¤R=e(„…LX´‰q“ÀüV“zYæa‚ƒ½ ,ÞnC± ·T§ª!°ÄÕE/ߺè‰à$¹ú½vÑÁ!µf&§3aL4J¯önpÒ6&‚ø<&Æ~Ô„ÀDœ~´"0>&¶ÆAn–†>¾pÏ÷»X›«+ßq‰”©´k¿ÛŽåmúi“3ÿ1ÞÑÆ²“$í¬=Vmô|È„…4R¶|ôÓ(ý-aXÓ竲ñY*k„ÑV?†—ŸN•»o‹×ë|Ï—'_é/ëmâ¬%+,7RK©ºnÊûú–_·gu~.MðJwUÿøÞYÞ‹»¦ÂZ?]@“ f²Dè¹³S%éˆ+ ÆÙ‰U"Ìç”U+!IÅ¥¬Rgß­:mºCE -‹-Ä)ìn…ÍIß“oùþ*«–C¾È4@žzüW¦vS·|L5 -€0žÍ¯Këg^ÐÑB ã&d]çjÉh\–ض 1«–OÚû KxŸ:¸¹Âë¹›K!Ìw1-Ð=]Î܃ƒÕ ¢ ï,O× ±}5z¨/"ŽÍZ­O½‡ú"bcÈ¡° QÀNaÖC:„ù‹ÒõwGÏM³îšHÔWåJ",ä`¿aG Åøp=ÞÙªFâØá«\J,C–˜ˆ\Yb³8R•l*ùB)Ø\˜Ñ”R²Æe‰©õ„œf‰UÆe‰éuëãC ›2@nVÂܬA~>¯þöEËK[—÷œ—Vj„ùáÌ”~âœpf‚ÆBìj•ÜŒÖ8åÔ~ki¥ðv*×4n¶ ±ù® ñSÆe5ù(“5e³ l%Ò/¾5SBö?­íäl©N’¤ô h^IÈI’$á AK@’ðÂ6 ¯EXÈ&ái„EŽ$< ä$±5¯Ü‘“ZLÂ3°ØÒJ7™%ÎüѲïEú¡ PÚ·/;ÓðX¤ßæp?îÊ´¢bdz°µüešN ˦÷‚;ž…-r>ÕzÜ2™!,<”üo}Z½ŠR",:”ü/ã+ò}gw„‰¬U·Ï÷m-¨ooì1cRþÚæWgE­–̶Q¥õg[êˆÿ]¼Öó±lûgúR*ïÈò^¦9¨gö® Î;à¦I¨gu#Kbʆ¬­ÌÒ¥ã ¢ß v5»ÊQ¿Ôï{Uš:âI¦ÎMæòÝ4í›à ì†1iºÛóö}êgJp„ô2/_Ÿ¶uûzÝÉòañ¥#xùRS§Ï‡œ/ûbÁ)UŒFRžSÖÏÍ~Ôã[`ë~Ûs|A7Û\ *k©.×0‚ÁmŠ÷tµ§ñú>-^]3yø¾³YƒTº'¸À‰{•òCpáÚòݪiã}¬?GAÖÙÔGÑx!ËÇç5CﯮlRÁæS/÷ǯxÐu‰·¸!nßÛ«Ë?/r®–:â‡!m÷{ólꈣ*ûÔ·GŸÒß·Ôßu¶ë¿åkµZÅ^áÌ—'T¶÷êWZ¶¨À>¶;=}ûBœúösõ9idÞ«ŸQœ ½e×ç$íªŸúI„ùÎf8÷¾Xàh†ÓÈû¯\EO|xBKÛ5¥R…á=XdŸ)ô£ŸñVÑÄá5»÷m'«m÷·,|k´Kúž,ï·º SH6˜yBÇ·§{ßÒV!ìŠ0óQÝm=Xìò^¸©Ç§#ÃížÐyÇ%iŠîEq»r†óx÷}P¿ÁÁ:E æ'´þÞLJ¥%¸ððäMtÀQÚöô»š³ÂÓ·ßôÕË/príx·©4Ye/váFõôC”—Žoap_µÛµå Ýùª«ì±9Í9¾nÑ¡F\ý»ËÎs>e÷o§ÉºlOè„›Ÿøñ“uÞtŠŽ·>¡ëþN^ÜJ÷ýàB§JS÷ݪ•%œæÓHT·æ3ÝîǨÑH„®fGò«äúã’£æcÏè0 ‹Žþ¾•㮽+òÛÄA˜F›ôiòÛbîÀk°„9ïe_" %­qôÙû[o’–¹"¸î}ÿìqà2Ê8Ѭ}? º]¾ §Û¡É(.pägßû`™­:s‘ïß=.B_‡ýî¨:6%ʼn£OdœÇSÝ_d3–kk5S/UCY7o‚sw‹úu¶&¸«óš=ëíš%pméõÚ\ÿVi–Àµ]¬¼ÂŠŒoó{Ü{‚ó^•>ÓQ §j¹¶©o2}ÈÇêÌ0¸•)?•+/–^õ}º58¤3;Öã!5ÒE¼+¯eg›÷÷ߣ²åŠEÌxö*Jƒ=·ca 4ØØ#£Aˆ±…¤oûœ'¹GOrœ{’ Ìçìhg¼N‡ý%0ÖŽ6éŸ"Oí膌²I>=Â"G’O‹vtžÙÑk!Þ ½¿wAíüÝ[~1m¡§”Èï×¾±±`Ã÷ÍÐ4ƒBÌû~·Ú"N˜²&'„ëE½hÅ6ˆ\δb[+H@÷hGŒ¦·¡œÄ; åô6”“øl€¯LÂVÑîñÊ`ÚánÝPc‡´C'§G˜ïLUŸyùÌë¾N"æ:7vhýÒ•©î>Œ¢ßê/(x€BØ*ö(H¼gSíyðžýG¢à×.ÈÄêÆÄ’ã b‘%)ˆ%¸DAM b‰óDÁ¡'¿/ˆE~_‹Œvu务Ã9¹rçÎɕˆÅrâúÕÌoÛòØVmv¡yZš$FqÅXê‘Í`ß-m˾–‹4÷&hÛšŒ¸ •tÝ(ðío;„\1r±îé5äRñ°RpdíØ®4£að59É☵c»«È© –æ»ú M¥Vèh+Ãj>äË‚Œ¢CÖö ¹Æg¡êª%0Ÿ)õ ¬yåäÂø¾ÁSs½²)ŒðZÆÐw×éßÐó¹0“ñ½Ä—Ãy³·~¨úµ2U íyíûfaÃGef¦ñ–µ³T%HÀøâ³E- €_‚óüŽa¾[ˆÍ`[¸U¯\œfRA-,bõ7€ñEpJ£ _Ä)™¡²Ï™·æVh·Pu|INƒòëh×sJ­22ò›aBfºüd&ØC:Ãß?àS­ºÑüÈÆQoé Žš UeZ[Æ­ä½éÛç¶ŽFãGór˜¼Ôtþ0ßõÛ¦ëüóü|e`Áy~¾FŸŸß"ŒÏÏ'eÅ®ÉÏ¡­™Kì6ä·±ùùFìÆÐÖÌ™ŸO>Êçç“™^]¬ô¸£¥ÝúðTP®ëI@]Ù)&7´’S4Sç*öh?öùáZ„‘wª3Rc/fû·MÖÉ aÎgüØKØeìÈps]ïê]—կȌnû´5bf‹ÿºº-Ÿ¯²D˜d¸å”êÞ¦}óCiU»8(¦2 RšP…{´°}Ùò|T·?ÁÀ¶Fµ7CBŸŠ0—²®Ñž3õƦŠ«a˜T=µ-©ª×³z¤}oOˆ¿Q‘“g¾ óhϲzJ…°ëÖºÙ´§§Wµú÷%Ë;»X~ÿ7·”¦*ŸYú} ¦G€Åy®X:³Éá%»ÁjåçÛÞ3Apúyù=×2ÿTd…g—׌›Þ‡Ùs÷}|ÛÛ«4ý,.<âj.Z»Ú}§ªªËZ¿Nؼ—i&ÈœeSá ²Ê³Ëkîåf™Ûb”©¿ÛíCpɆ[>[eÚ¼¿–Î÷ ¸jfæeZg*½‘uö/;\UÞUÞŒ+ŠóV\a>üË^YQÜäPÍ.¯w›ÕìÊ¥×­éwãÍûÑÏß-—s0܆ôö«n ÁûñûwÚÜ<±ãL‡~ܽÁE3n<Í‹ ›üYªûÂ6!µ81áæßw_@õ«Ë!kdI.îì38ôÕ¿þ×wåœ?qèß=t…ŒÙÄCÇ44órÒ1 ÌEÝëQóóƒsêžþ®d‹UþR›åÛwŸsû L1€Ïûúf°@‹»ÉªŽYRUa˜Ã–`Pïþ°T`Øõ°¤ÈaÉÀ\h0Ú[‚6»R¾Žoy¹ï槯ˆíCŒV{‚_ñ7¦ñüù/½Ú¡h%œ[õ£ãf‰ÛÈo‡I{v,'äz56ª>ÖNpËÁßgÜrð!Vs‚[>”åàO ÃX>„›N`çÀ4„ƒo`,¿!W»r`rÂÁ‡åµqð›&“„,ÜóZª^Ô2æ{Ú˜1òÕúgSšÝÞÝü†È£8ÄW U“o܆#èÖ DY¢°>n›±ŒÌCUªmÐ9FXDÔàå(K§bV\Çù'Ž0ìE¢Žec¦eÑvù7!ƒ ¬â³>[}‘ŒE–ÅäÖe)™ ëª @(K×’M„¦YM ÊÒQ]&1ß®R¥QJqŽ…ð3÷f À¹—&à†4‹ >Cº‹ç½ý´zWÊh× ×åIžGNV¸Þ}N¶À0{c÷Ñ$'Ü» ¯†Ì¸@¤%’“U$u+\&ëHêV *Ï)u«PêV¸ŸÄ…8 Q *…o¹“óÓ¼GÖ›um6“„{òå}›˜¾kû°Ïª}‹È3]f‡Õ˜K¤·tU35Y4…æ¡Ó2”0çµ3cÎ(°¥†U6ý·WkŸDYRve‚a‚…M&±ñÄ[WYUGZg#†ÆÏ<…LÅPbÄÒéÄ ²àP‘%ÙŽ‡ß¦üfóâýÕlæ-²~¼¦.ÏÆjê Î=p›'«²!ÎÚb ·ß³âÔ·ë}›CÝr4é›fJÊ–à^,Ž,ßVí†#Ñ:îüåϳ¢†ô ¶tú“ën‡KF5§ã,ŽŒ»U»ÿÝŒ½6X•ï÷TÒylÕîɦ¢0Ï"ŠÛŽbËÝ:šæù†M¦öÄ6àÜ ®²â<À™£N–Çóa뛨ÙÌŽOpË:ÏGÀä;xȳ±öù™£N¶Ýàx>¨ìÛ¥' ¢M*)WÍ”e£†äšÁI†…§ö·6•®_`ëv.НjÒ&l0Ìa(làÏ  ÏBaë÷M°vˆÂ¶F; …íSGæ³±©y$±—…Æ=ËφñîùÙpÿ½{~6”ågCëÝó³aݼÇmlšËϦ3åcS2S ?»!ülÀY$Š'5Áö¨Ã{^¢ŽÒpÓ¯‡ï÷d(òBý¦…¹l îƒs_!°k Dшw­¥w'Ì۞˹;iäî$<—swÒÈÝI -«»“Â0Þ݉Àxw§Ã^\Ï}0ÏN•6=÷æp=÷a.ׂþ%Wó¸Žq8ò{Þ‰åHÆáÕå$[¿xC8¢_ÿ[Ô…e?¥T’Bjº±»±£°€kߟ{DB°5×ärÏ'×Þ’¶œ7Ls7$Ö=DBø³]ó~¡~uS‘µ[ƒk†cÍù·ޱÀ0‡Ë¾ì7öu›}ùi s¬Å>tò„]Œ;'Žm±\é3=‡êø™–Ì3ÝTä™–·Ïô¾nòö™¦0ö™Þ¿I’8®rûŒ+ó*Ž? À¨ˆ ùÂåè g1VÈWIȪJ[õ5)FÿqÛWß$ÿÉ Ó/gM3SäQe3}[ ³1ûF$%/|—cö‘Ä›ïr¬C’ô=Žu8"5|á{v§ïù¨9ƒ÷{Šˆº[pOªVa4EðöBD]KË….–ÃÍBD] ›¯–§A½ ,kº0ÓyN®æ üÖ€ÛÌ‘ÄDa¯‹ÐrêEh¹&Sá¯ù©j”““–TI¬~uN$¸4­Îo¸ù+Ñ«D5inÍÃa75Üóÿšß0¤%ëÓ¹Ä^3nÕ"o«øìõÔ­ v~tÒg©»~æ§!ì{‚ó/™þ¥!eúiÚVQÝ÷ Ó« ˆJ˜ð%S n)¿o†„äõ¸§æX™Fä¸$^OÎqiDŽKâõä—*ä¸$^Œë ôsšy9÷ýœ†9©ò®ˆ(j#õÀ×E-¤øraÓ( çGeÉ0šÀ¬\˜ü7ÿÿÆRaFs%'Sqe"W N|”•µðQ*rµçƒ#iÀö}Ѧ¢3_b¿÷Þé|Ié PKÅŽVvÞÄÑêJZˆÌ'á¨!›•y}L·Ôy®*’öiRݵ1J“q n1,àx ™Âz.^¹8 ²¨†Æ¹oD ü‡´Î}æý;€A–Àœ¿KäõM&s®‘Wþ.ÞÍ~*@œ¿­}#1I£"ŸŠ<*2 ó®NkI*•-#8gC¶tþf5†½¾EºµÌï¤l38<`Ο%ÐØ§ oýa·Æ¾¼ò6Рƒ²ÆD®ÆÆù§$̦²t¦l Aal Aa| qº l Açʧq¯FC Ħ:e>ß ÕœoíëDõ›[¶Uä`İ«šu“øÔ%ŒJS!È@Te> (Æ* À‹Ç­ …± (ðQÛIÃ@Âa‹`–‰E Á„-91Š4°«—ÖD¼´á3áP^àp˜Ð C áÚ@±½¨î<°ÃGDˆ³âÕ:Ë* s°óǺAXøÓû —Ôqþø˜wqþèS]ª2¿æ3ΣQg»´¼!çMaâ"Ý”¨L'Å’ÿ&/4Åù¿êÓ Ã&6áJXÞëçA.÷|²~çØÒmËÙfj¨ÊÚ)Ý C ªk‚lW ŸÖh>+§0óMÝÿ~ ã]€*\´ØŒ@‹/B AÎ%ókPs‰ ž‡V†ŸÃàD\=¡Ëò®FFbƒ$5f­mrˆ{B—åZŸÒ}صQlÞæâ¬6iÜÛòoÚTßâa˜sª.÷4œ²90L0ÌŰí-ÝÎ?ß#†y¤¢¸#]êl>­fæãÞɵ×1 óø£§qÀ0T7Ë·ïVWFm—9ùoGcš‚×ÞüŠþf&¡¡ooU]X7ß°! ì}oSœœc ä;†ã,ïãŠ+Âð…ƒ&¸ç7õ•Ò¿ð]œCû —|lª$C:® ý†‹Åz_ǾŠßy¼Ø•6Ü|ÃâMŽÿ;é²þLôzGÿbœnšåÖaøÉ}¢þESôuü- =QœÀ}Žë|‡¡TzÊ!«!våƒS?ä¨ßCªë>$¸àè‡4¦IqW&ŲGÉ>~\ŒÆ”ñ0†û!yjP˜7û;Q²&Kçœñ<"¸’ L&3 ù¸SŠœ œG$O‹Rä ”6¥È6'0[C‘‡*É’y5Æ‚>yOæ´¬té‹ó\T‚ÿö—¢ñE¥ Ãø¢R‹a|Q‰ Ê•4†ñE%r5¾¨D`|Q‰Àø¢ÒH–—/*ÑÛÀ•Èß•è¸lQIÓëyÖ>btÒé«0̱–3R¹@\`¢©­ˆ¦¶À¦¡6MíÃxMíÃxMm…a¼¦¶Æ0^S›ü7^S{İ«¦¶"šÚ&YÞ(ü7T>³9 ÃÕþâ(¬1ŒUn4îð"ø‹U°Â0‡µ#ؓӨpÇtð¼·##0ÞŽ¬Â0ÞŽŒü7ÞŽlÄ0ÞŽŒ\Íf q+ôáBi·#Óf±P¤Ú,ïÃæ}‰ìÈ÷d˘0WÇ^Ƭh±¨Ïö‘›¢îÓwiÚ´=ú?û$– CW„Mý†02pÏ¢³¬ÐýðKCøtîé›d¼¿—¬òôž‘vœF¸Z‘Œ‰ŠÆÃŽ”|bb\Õé°ÈRài.m¬>Á€¸§.Ìõ¥Y8“˜³¸žmU²´Ö—Öhvj n¾Ð¸'Ñò%s¿àjõ.ЬŒS‚{G­wá}eQ4ÄdØí›´œ5¢Ø\//›w¦£’ܯí›d]ùºë~]ØWRôö£³Ëß.wìÓöß:Îéÿówœ9We]¥‡& g7à^G—c²½LúOß&iÓ’{¶ua^q¿¦%7ÍtamnYèþµ}“ÿèÿ èáj©¤„ówXU=ÝÇÚ ¹Z@é ¬ MC|¨“á“dÜ£ sï†ìÂaI‚Å‚s[º+ÝŒŸÏO‘ýbº0ÿ·Õͱ® ßmò)B:wM®ó­æmÐ6h1¸—•¿ª‡òjXþà”~Ã4×À·ð ¿"ƒ×À‹mü M`Ž1}s9FD_a˜Ç1"(ÌçôÅr×*õ¼nÕ.%Ê]ÚQp¼WpÐæ°þ‹»¦ ̦DP!9!‰¬Ôe€=Yú¹šc×ÑXXÄGu_ÞYo.3UvËÔhLT*±§&‰®mM>˜¦®œÐÖ ìÚÔ•J|0M]9¡ÔÉÇE dow@Â"ò!ìÂ"9‘'OM䌅E Ìe{˜`y¥]‚ßäq÷[Ø%øM÷]a˜Ãåqóîü1/4°«EÌ Ìg¸ mY>7»wWåH6Âj]`þ²´ukvù¼ïÖ2M„òyß­5ì¾[+«0ŒKõh“ê‘OŸk"Q9Kž P¡BM„òùâšj"”Ï×}!ñM„Æ7’)Xéyi×=O>Å¥wâø|` Ÿ‚Ò èçò÷’³Bœï)Y^Éù%hT-40›_‚BÕBãýF ãýŒ÷KPöâ°ö îÛ¹ Ìaì*üœ:Ô“`Q—X5¦!l†a>’˜s†¥«†¡¡°SÑ` 凰Kë¶n1̽Àú¡Ï/0x›Sa=Ì炤,~æÓ8y4íêRk {]`ó Õ 3ê`&.Qr~¢©²7†I¢ò°n6L5…{R~•´XÔðÓôSõiy\׃jǸ&¸'é"ÛöH;}+µßÕ‹”MfZ׺¨NbC —÷¾Ì5þ>;WÜ­PqW:Lì°ÀŽÂ³t|®ð¬qìàÐîÖSOO‘Ã6Ýõôtû‚¼¨šâò \ŽIó—y\% sYwHó@<{{:Haï©1Œw‡$WãÝ!ÉãÝ!ÉÕxwÈ ÃØtPÖbïIfʧƒ ²¼wHÙG€{ZTßôrf˜`®·¥¼¨0ŒˆF¯ï¸vø SW¤0×€òìç“ÛVw*—9$ûV ÈÕX7}¦Ï v|i@kþ¸Åj>åWæ¡FN3Ó&ÌŠù8 0Ìß;"’86$pÔ:… É"Øvµ¥&>?\ca =v*æL®&5:ƒÖµß/s2Ó›Gd¦Šý˦º§ËK<춺ͣ,ìnIJG,½êñte¦òš¬Ü¹yšæªáv?5íoˆàH‘ÒHV‡Q±ómç±¼fXŽÁÖÈ[aßÈ«1ŒoäUÆ7ò’ÿÆ5òV=”oä%SàyÉÕøFÞÃØF^M½iä…yÞ7òßÈ[aßÈÛbßÈKey5”oä%0¾‘·À0¾‘wÄ0¾‘—.ïƒëÛïªsÛ¶¯¯Ã…Ø–Kºîmïݫͷñ|Uˆ¦$]Ï^«_=jõòd©{ñ¡†…{ÝûPWÆ[†ÁúŠ;Ë0ð“XOâj¦(Œ· ÓÆ[†Æ[†Ø b*²†‹k|º\Ú‹¼·,/Æ"ã¼Æ#†9 l Ws9ß`«ºÈ×Ã××½Jáþ6Ô{Üö·ÁÕ)ÝÖßfªÒ‘Òmým9¹šÇU¦b.±—«¥7òÛ& :Â]ðVtyš)Ì&‚Uál¢çrÑ Ÿ<—£ˆVø´âyE´ÂÙDϳSŠ–—Ãx°n>)^ŸS˜ð~óîS˜†—*1/Õ’^…XóR-éUx¿y‚™ÂíÅòD_EíÅj/–'ú*ªoŒ¨½XôÕsþoÄÙk/à{Û›Ü<2þ_ 5†ñæ{Þ›?* ³ò¿P%Gú—éqÅw9½ë§¥}Ó»®pZÚ÷8½ë§¥}藍K¢ŸdÿoþÙTÅÓ'±åë5‚ûAä_¸p÷Ë l¿mCËÓý¿!¾áÏMm*¤0‡5ðħ¶²ÌTÞ—ÝŒ/»UƗ݆ñe7ãËndP¾ì6b˜ †÷æ(X5:ía¿¶³q¾ÕÓæÇ9Ç0⨻^n±ÁRÃÇØLÈ×Iƒ.yo½¥Q£Ç¥:—c¹š9 FaÒ&QaûòFkCþŒ{WÍ{ÞVUƒadÞÊýÓ”V:þ™z°íþîѪ󺴴UŸ| H¾6¦üzü\ħ[2AUc*ŽN~c–ÁWæuzÆu  fÚ„IÙT¿†X»u]·:ÌU7¿{ ìyÕFÍÞsÄÕ4IMpvmÔ8I>dI6­Z‹æiaZÚ·õÿAéÉÏû“õq9Ñq½£w×d ꪫÃñ oÖ×ãêªvl§î½o§çÝvjtƒa'¹þí–…Ÿ4î CÛ)ÛÄŠ³¦Ñóý0îšæîmô& ßíHÈ0×¶2r5ëv ×_ —Þ–ß»,ÓtÐdA$nEYGÍŠ°­‹Ï§Ç°õð6þ¡»î7Uš’åʼnÙvY1¿Ó+r9´ð¶«çmGغÂe; Á¹–m2FѼMj‚;¶ÓºÄ30Júw~Š7Áùœ Ë_üuñILÁ¶éž¯{Úb¯{:b¯{JåuO+ ãuO5†Ù´¥jö“ˆ‚mÕ=UfÑ–Ò¸ÙO" ö¹ÙëžîÉÅûû’ÜÇûz¿¼Û³„/ÿö,¡7ö,¥F«’¯ÇaT¸*yx–ž9ŒW%_¯{#”ç0Ïa,0ìÅhÊí™ç—8KUnjûù¤ºm!¥øº”D¶t\õÍUœ(H²"nµEzˆ³q«-ÒsñDõ©ôÜ’ÿ_¥çú˜ Ê{›Ã òÞÛœÀÖO©À0—õSÒÆz›Cb ‘¦­Þæä¿ñÞæ Ã笲߅€ÄÔ{‚§¢5Idîg­Iv¥ˆ.¶K…þ~Í7_lǰË{äÅóib$ëÅóÒŒ2^IA®æq0X^ñ´›u¨MŸn"W{á™æ¦z5µS µaáœhñ–à©Ê~ê>Æ0äÿå•…í’E¦ ÔÀ\I8'X¡WŪaL £"°¦B¤ç}1ìeƒµª=Ázd¶,æ û-Ia´ý8Ù®V¨"Ò ;2ØË¹q-ù&c¤÷öDXÞµ0®ÁÃRñO7žp,N¸'ô¬K² ÞNÝ÷6d†¤opæ¶N]†}Cp®%4âä˜p¹\Ј“cÂåZíFœ—§qrLx·ûöo «/üÛÆ€}ϽnàÓ+^÷vp¿Ä­4u¡1̱$ÿ+œüÔ’ïâ× ÿ-¸÷ë$0öÛði1Œý6ì3 ný:¡¿O÷~Æûuj Önè£iZÊ×4=âT›|ÞGæf¦%Ñ®úZa¯úJ®Æ«¾j ãU_É ¼êka¼êëˆald}Ò¹W}%3å#sòßlª¯Šô]H‡21Îæ™ †uoÍ3¡p‰¨¡VóÌÃ\Nx r™ˆAºËòlßš9ø­c3#¥úªfFõõ[–¥RšD Âý6*ç¿"lŒ’³¹¨Ç¼ûÒ¢îpd`%˯úÛuÓ%II`;‘Ä8Œ­]´ßáƒa/” H·MÒm6 ùobû¾ý1ß·í¼5ß=b˜EË»]5ºé‚)eõ߸(ÛŒ,ïƒRÌåÒFýÚÁ=a£¯wuÓ]h†b™à }Dibº=Òù­4?8äï™Laß÷ñ[ÿæó*Áy”ݾ¬Ý˜¨4Ìëžà|Änß^LJ«²(ë¸!8‚_Ãaæ·SÖ›AYðëöì¾­ªÞ]C¯'‘ÛϦ„¶UÜ´YU\`3j@D‰(®V¢CaŽ­ÙÉrÉ–6Oß•·À±Àá—çdû‘I‹æïM S8µØÏÛ$Y»‘æÄšÂÅ0‡õs0ƒ"wW«ŸÃˆaVI#¼nÁóìø¶=±«Á¯11=s\šjgûj}Ü{.íW³5K˜¦øÃY[ AßÖáôø·…õýjþ½ ª¹§Áë^Uc/ˆZa/ˆJåQG ãQ ŒDUÆ ¢’™ò‚¨Æ ¢Ø *½ ¼ *™ë *×"ˆª±Nà,:e ¢ο˜BNÄRœ)dS!SHp¦yL! ÌåN^ûâÉÛ“¤)qÍv*„w&ñ¾ž á}eªBµéàñà(S#ªMG™ªPmÚÀ\NÓÕHV'çà9¢›`uðÔèf˜ÍÁS¡›e`®Mñ½¨ƒÇµ¦Ÿ’Óÿ ;³¤ U] Oé·ýôr`Uí=ìEŶÎè ÑDÁuÿŠ ¼Ae Â?×PÖ`›HwYƒ'Õ‘²½@e æEá»}«CSÌ,Ú¸`Ì,ÚHZ3‹6 Œ™E fm”3‹6’w3‹6Ì,ÚH?¯Y´‘rfÑFÒ×ÑFÚžF´±Â‹!pºÅ‹6ç™BDz˜þgˆH/0f ) ¿Ï‘•`¶©PMD@ßíQæz·ÇòQæzèu€¤hzRFa®1•sPØ¿¤rJŒ™S9Œ™S9 fLåæéj•àUÎú3ÅF]2‚Èqh=+…ÞÑÌ‘ìJ•—Z8„šÄFS2ÁEghYÝA}·½µš'JºGa®.L¹/‡FÝ®*ÌÃxä·‘/{òP_³/Ƭ€Ù¤0Rò8{piƒFwhÙ˜ý+_ U’¨uhÙïRË*ÊžµK•Œ¹º({)¯ú ó0ßMN¿æk ò¼sYŽ© Ä;—å˜ òH¼sY´LÍóŽ–BËÕ™?§•³AN³uÕÛÆž‹)ǘñŽðš½îç!,¿–«¿#ÜŽèŽPa>ÙàΡïªnâWO½/]7ˆmS˜mÐuëa´wé­ë–ÑÖ®°íþ…qhš´ç9iÍÓïÀQñ¡åS™r£m›ø6‘”€=\i–¨ š®ézÙ3ŒÝ‹Ãî\:'RÆ2V¨Šr¡E£øÐÛ°²ü^‘‚×åßñv\N_dRa̾]™:ˆ¶[‡âúë’Ê@‰­âk™TÙ"1†ýÀçúv8x§%!˜w9ªöÆÒ£æ\‘í®VÒ_WÑ`XÍ  oÁJ<ÜVyhÜìû‚{ãCÛ(cu*O¨‡âd_M8 Lrû½†œ©àx"¡*ÍšÛPðÛ†¶÷¬Ö+ùYó0C1 %Mÿ‚íëk> Uó™`&SeSåUWù¡o $øÖ·•3ëÛV3ëÛÌÕE¢à½ÞÖM¤cŠ¿Þ1X‚Ç|»§¥c=ÿú3âŽo£°öóØ)ìšH—Në©‘Ï׹ȗ(˜}G+JJ?[«æÜ…Ü•K¹îDRËBI*ÌÕ`í†ónL—ÖÛ‰¦^%+1æë0Q²d;²ÆÿùÒBZ“ˆ5ó¢² h°áÀÈw ï8ºó¦9_Ö s§j«ÂçýÓrË\tá,ßTY¡y!—´Š¹TÞàl 7fó,—˜pwü^ —Ë~åÓCñ{9\­Ù~-z½ ÙD"(Ô%†åkíá7t\ó#Z Q>—®ÖœóÿËg öþ}ë|lˆµ´Åœá¡Áw-xhh”Áÿ¾ûg–ÃK»Ì(×ú\åàË*겜*Œ™³œ$ÆÌYNsM!5pο3‰ž™kgÉG‚½K> UòQ`Ì1Á†ž~Á†B|ë÷ÙõnÞG²zßÖäz¦ÜF\‚-DyIšÊÛº¿O=U˜½Ú„£Ã¿*°Ë'Qÿj…]vn`ò¯Jì²»Žþù¿Ã#š€”ò~¾Y•–zè†&—Ý‚ ïÏ䲫°áƒŽ¨Ë®Â†÷L˦æS³×³>͘HžõiPÌh€iìYŸæ€$ïæ™ª©WðPû³šúõyíïjêcŽæè(ñìõœWd¡úOå:EÕõAÜos@`ÌlÖÌæiímTÔðÜos€<Ô×>gOá»y_=`ø |.]OU!–U$=ÔðA•µ†y7cO+‚ù¼¤ò’ÀÝáQMfœ¾´õÒ—B”köJ_bWÙ…9wDÅ¡Às¨úlì*Œ¹&9v°¼ß§;œ™kO9vÚš1®åšäÁÇ{¿µ§°ð[|‹`fñ­ cÎKú–gXú6ÄUü^Ò·ŒCì™öE4m˨1vçé€+&ª—¶¬… ¥i_gÁ†-“%ŸZòPO§[06+e¥¥}]â­;Çy=-u›IŒýv†yT¢ê¼˜H°:ÔyÎßþЈ-¥*9â´¯ÿüï j96£¬jYÝäù¼8íKÕçéZåuŸκ¥Ò5¶¬ÛfHRÎF/ÎËÃii£µd5é, ¦ kÙæÛqìœöõ¢À5&óÂ’Œ Å]R"eÙ.Nç¸I Úžÿâ¦xŠd“0ú~?Äs|—¡dÕRõ’¶¼¸½ÌÊÒö9åÂW^R=o‡ˆtÛ©É<þ{ñ$B.Œ×9^ÛzqY“o\•“ÙbÛ(Ïé£~ù’ç%á´%ÊYQÚœFö”Cß$0º luùŽ1”cÏŸœï~š,°¢øÞ·çºàbk1ûå`H¨ƒáNœ¹±ýÃÕñ†eìwâ xÎJ&u'ºT*¥/¼gžX»a#Űç È•ç ã«d c?-&G©4·\X¦20뺩ꡙJŒ…:LÔèœÁçý»¹L9Iê<©‡Iå¥gi8¾qýƒ;âŸÿ*9¼S5/kŠxËKE|œ‹Sâ9/XÕõ’’qU+ŠÎcAFL­(:EF8ßైèDAáy·Ç"Æ Å¿¬À~Yß(jŒÊBÿ_Ê$Æl£‹Z ¿]¤coiE]¤>([¶Cbªª§‰†¥Y9H5£PvÔb;°ºbà †bÆØ[$”SYîi³s®äÚmÎ iÙÉØÊ cî- ”@x‹äE•Í{ê²,ç]°cþk7NÖ©aqŸûQ©Æ}i¼&®0Йy¸I†d.·‡c,¼±Ã£•M¹mNÛvLº`‘-çÜÚëaXw18ÂYh¢gªhbŸe¬OÉ8X¶6i€—ÅÒ¬4sIÀµÿ^œî'…c¼öìÅí¹-ôÂy& ž·@ÕÜîÙŸJþ8ü=*) 9ÇâŸ,JîuâTÕW&Êrm`ô=j¾@¸]Þ©Lz8âRwvü5Ûz¸öœˆQ©;¥%xÎ̺猕åDêRìPÄÛÎCÑIŒywV}rzqĸµÖ ðmü¨¡v`‡l¿Øo’;&0öÓ]­ÇYÛÀ¾ÿ»ƒt@xC]­ÇÃ3¥þ§°P£š7k“PL©¿.i²%¦_ÄÒè}ŒÉôæÞWú锬ý˜w¤³§Hà¾Ì1¨%¹Õ5åÜk9„ÝÆ¿(Ú¢¥Ïõ0w Ù^(°JxÔ~Þ]3âLWP1üÉ’ˆ¤h’”p?×%ÛÌ£\ ã椘m¼c?ö%`%sEYû‡ æ|âÎÒqK¦Î~K¦¤õÈó;¨1(,Ц³¯ ¨1(,Ô¦«Þ%ÒÂ@sµJ]ñCÌlà}5 ×ö³)ŸBM`é²fØ`,@—+§9\mÃ!òè‹xV¯*vƒd‘ˆ¸$=Åw5¹òÑoH—ÏJì1¼KY^w0§±^÷,ÉÙqE¡õ(ÿ ͼd|;:¬ÎëΤŽY$‡¶üÐÒUØEÿ4´gëÝùm¯çòÏDØóQÖ¨.‘ãjÍýLä¸ÞÍÕ'rœ±ÚW"Gè’ÈH†î7Bï+>u¾ºà‡ìZTÑТÐÿŒ˜¿zú/ªZcfU-‰1³ªV…1³ªy¨FU«"óá}„“8â ×õÓĨ]3$4Å3-÷ÁÖúûûûÎyÓiÂÕî…Y&M¸ê®% ˜NŸººëo˜mÒ«;«Ý ³!Кó"0fŽ!­™#BHkæØŽ1sDy¨oÐVÀ\£æø<§s/0¦S0ßAc|aÞ—‚¹¼ê=Ó·HðúÕšÿ>ŒœÆÊö×Ì%ŸöTó¿{"bJÂ0[‡ÍQñÀœ·ÒA´Ù[¹R:ÌÕȳ‰í¸ÇÏÓÙ†ÏÌ=ª = ¿5 ŒÙF}jÕ”¦Õ§–3]V\ –e}–}.ÔŸ…³¼þùï훯›5Ý[ 5G¯`®‡« îçâ°HŒ‡0ïsqh9ÆlSᣫ§þW,i!Æl]ú÷m lØO¿öîN…+–tÂïJ Æ®Âb•íܱ¨›Ûµ€ž†úú^sÔuËà?µBêÚIcø§mG-{Òš£ùOk^O#›1æÞFù4lg$¾Ìl•#Æ<ªhxF¥¦+“Q‡1ß(£¨º`ÿ}^µAOmë—Aí¦U2zûå>9²ºψHÁ0†—š j7åI5ÔÆZRy«%mØs3RwžÕZ.Õš5ÆÞÎýË÷Þb ¹9“³îö!|]K´í =¢½Ä¦vy£TmmC5ô}’çc¾I¢‰¶fU Æ“jÑBZ ߊ¸¢`q¼ö1ù¼Æ”n{÷;¥»Â˜9¥úà}§t ŒÙ™J~ÊTnØ;­èOf³õŠ‘ , ˜£SŒŒ/ÅHÀ\½b¤TŠ‘€y›"Ì7FVE…±ŸÉ£{Âgâˆ*N˜mÕ€ÁzêæðAª.[xÑ(ŒêÆçÉl¿wN’Z¨;qÀlí˜o Ä˜£ûX±¬pλkØ]êrÙšÀúHªâ€yš™ê6¬?T_Mù1Ή”4³È‡9V=E™jä¢i˜KV'ÙÄ1†–¤L9vâ4šÆvTK¹c?p «¾aL¨ýÃq â¶NÔm`ö« ‘¤]¸çKçí<ª¦KÎR8ƒ:šü,.¥FÁñ>Å¥‚]æÇîÑ=ëS-ëš—u :ø.(ìg¯r7$ÉÚ`ÌÖ`ËÐŽcŸ`ÌA]H ó[T|ÊÈCî÷Se“WBvƈû=S 7ËÌe\bÌ'^úÝó»cÕ®ª‚±ŸãÁ‚{LU@Ú¶>·£,΀9ÀBŒPo®mx:Ï‹Š!&g¼ñq¯Þl?á,ÌÍÆ £(mÏ6‰âÂbîÜqz‡#™ñFç½ðfá%MG8s…ºÇ[׎5d`Ï8Èîã¹¾1!¸u;=ÊTÁÂä_&ãeú8Á—É(.,ü,zu=44ɲ-ø˜ìþ}§\ Œ™•RÔCQîžV)¥Â˜Y)E`L£”R!`ºÒcb¯¦°ªÝ5Ø[ãÐkqÙ©®ó‰õðÝÜÇ]ïCzú/ cf‰1³iͬÀ@ÞÍ39<ààåúŸëÝüO‡Ç…ý>×CYŠk†”û±Úâé/OÆy6lód¨ÁQä†cåX2ž%Õª†Þû{ûºN¿H¢¹›Æû{o:{:ï‡é¢Æ˜ƒ/üTÙ„5obŒéÊÁVK]aÌ#×*Ç…ŸœÒuØÌŒ=ÊÁº£ÅfàÏÉ‚±‘Ë8sÛ¢í‹,ÃXp««|…œ·KÃו`!º9µD£~;ÈmsŽ`¸¹ºBHª%Êòi g·uõ¼íÝF ÙIC8Û”a «Íwvä 3Ó³?³®®ÖìϬ+ÚšcX»$¬]žó-^¡~®GâqEwÊ鈶-êT _é{ù¡ß´‹ŽÛ*·D³‘þoqÞ5£¿ö#Æ4òÅrÔ[‡w3ɪ÷Ä{íù¦{Ä{íýL%ö–£¼Ä˜m*ú «´÷]ô¶Tï»è'mí}|Ü̼ ½Çjsˆhž¬ I˜M¼;jL×JònFÎú^øi‚®¤µŸ.ûoÐþã*ÖmÛâÍTÀ„ÿ,¹‘ò {åµÈâ cÈtWKœà O»*m0æh,Õ¢kÞµCßíª¦P,Ë|ÝHÜÕ¸^¶%Kã½õ—1žed>Y?ÿp¬%¬­‹…·dl­mè*ЯÅXvIF8” ¦Bx™ä|ÈÒ3ŸñŽE8B÷hõJ¶„³^\UÇUÁžœýæ:V¿9çÍ,Ù¸ž¾ŸkâíÝù¥° ÷¢¯e\—äO³}Ì‹ÊfKÔmY¶äǵïTÈj‚ S<åd¹8£·_%"®`ºsLU.üÖ†¹&™A0Ï(íO0¾¯¯ÎTÑë?”©F"m÷[Â.’pÐñ Êk‹œŠ¤³u÷È}º¤ÐZø•P[ÅZ÷2^ŒÙš.¦  (M{W«¾Û¿¥4AköÇ`ØÐ†]cªS'鹚"(mˆ¿Úæ\Ñ$ ¸Ó~Þ3DNÝe¬É²—b(mH+è­ù uádrån×SE ]ž¥èse}-"Ù&È€1ûNÝS¦Ë8LSžOS†1Gg±mû'Œ¹×9œè§HL¼ÛšcžÆ^*ë²,òPr¹staû—Ó±å튱ŸF-b;çô—?ûļK(ã6m×<áÄBRXãx·x¿‚yA>ïß#Zb› ,I‹®ŸIW-ͽôYYŽý¿ÐTM‰ãc?ŠTzâøØëøü÷ñPtì 5Ê$û®Àú4I`y¬O“¬ƒÀþ4IÀëØ_?M>œW@yåùÈå •u€£Ïsééø|âc×,)ÆÞÛ4Ú-¾« o-ÓSû9^Òäs±upb’OÃÁÝoà’ú1g¥²cYåéв‚´ækÊÌ´²Ìç±ÄØÏx/­¦9?€“3æðËñŒÃ»=3aòól,Íž8= ŒÙ§ÃÀ¿tXñY+*Œ9€]n¨Ã'ÀþŸ°kË–UE¶]Z¦fªŸÕ€3FUð…‚oT·õ•0#Tòì¯ý1&ˆ¯9cÂgØÀ„İ·S¡ þTèöاì[ ò-)~&ËUç»Hp%ý}°PœZɯ+º*‡Ìããa÷püú„•?ª0i s«0‘Ѩ“~­3«ÊòÄqà A,«fU`ØëÁ—/X_ *Å0ÿÁ—׌ÃPa‰ ÔtµÅ*óbÁ0Â]=Ôkä\¯rÉh#èpn 1dÙˆa¨Á½õ¹ÎÆe)ÇðdkÇ3ÖRUŠ @ÇïfÛÄM£ÈòþÝ<åèÞȾŸÎ#µý{"žÕ²*dNÞƒm¶]Ó0YÁ!dÏÈ‹8tIþ±!òã…±)Í„\ès±'z„ÒÍm35ã”ÑñÞ7…¥ 7 =Ñíô!8ëaNõØÑUö°'j¹ -›«B'ô¹Ñ­§¬À=e î}eÍYV nï °{ŽÀí]æ?Á¾í]ÜŠunï °÷­XGàö®û8Û»j Ý] ,º5w¸¹+Àâ[oW{»žËûçªÏ<ÏOÝ—‘ÀNþ%ƒ’?s^«zéjØLÞ*1€)ÈOJ 5ù.% î—z©bHéo{;îþj!°Ï¶ßýÍH`áï;»d×Nc9ظ8»­)û :œ,Æ¿­uàë¬Ùå=5X=‘Û•W²× Áy.Í(o´8\yl’­TdꡯÕwi+\Æ \Ú Ü›è¦ä‡n ëÆ>[ îóÔ‡¡_e¯è|¿•1‡5±‰«¨ÌýDÞ†¡¢3^nñHóÜ"—±'¸øÁÈ’KÏGúÚ^Nƒ”Ì÷å¹4 jÒâ^.m€’~?OfQ™ðù{ò„_͉]'ËõÓãX®ãÚÂ<"GùáσÏÿöçÁgŽûóÖóþ~ûóÖgöþþ®•º9Ä|¦Nwµ²0﹜p"å„ÞŸG¢‚6Á|ˆu¦ËzˆkÌYN¨†Qµ›]þ‡IÖZ…P»He¶£Xg6tÊîNïïÚ>R"Ckó±.Ý!h/e6šÃxÂ°à –ß`˜'Z4ëT-ìƒùЇlÒ(Ï2]cXè„õ¡PdaùµÆIèÓ\`XLÓŸ'YˆeÑY•‘åEjü¨:{Ý4¢¶Ó&+« F»2õ­ø“ÙrmÒ€eâýÝ,¿óN–)±¥©ÞßÍòã`ÒéSV`w½Û´»ë%ìÝÓÇ Ì©—0h sê%¬d4§^ 0,~PòCúöù­Ï1bØc JÌ{áï0Óèwè `ñïÐÛˆaîÐÍz£0gèMK {?´½ÄLLÏûsµ½Äµ,ž÷÷L¶* Óóµ–ðg³”™ÿT`ß`RÛî[Z9I˜9`ÕùTj-0Î`þ—Ig÷qÇÛ®ks!1ìŒßÿ¾Y&kÞ0 û~ø")ФäöqÀx™` ¤î$J©Jõ„aIÉòÖ«<íxañÉòËíhù¢5kÓ1'ËûþJšÃË’–É>'?Îópüöh‹0Ó”å-}]ˆzÌóËœb}¦YFÇóIŒçx¯¥ù@Úó$F¤6‚Û\ª;îï Ðé`æcô¹ŸgŒ¼3ïÀÊic”æÜx¢d x‘·‚hq1VQ·"Ä ã*ed¼×Ÿ g“F€Ã”ۃͣ‡TgM^Óï›Ã‡¡¤EÒæËšª+ކsse¢JApÁ­ãg|ÙBƒô¹¶x~DImx¦™XgEößëC4šö¤[²rVÑ\HqûÍq9TG'ÉÓîŸnÆÉ-Ñpñ·9–m°ÇÍñÃÓe%'ÿG€]>eç-Èœw+6'Ìf¬æ÷¢ziÛ~au› l¢ÏÝ“ ÿ۵̖͡ }±õé%¸ÀÕ <ŸªÝؼ€nXùÈ“‘aa¶[º–.Ç.ƒp¯þnáD`šëQÏy&Š´ë1ìí,P…‹/rÚn¨@ÕÃRjmáâYÏÙ• Õäù±K•ªÅ±àÏ%<Ób :øs Ï´Ø‚<—ðL‹c!ˆ@z¤"­‰×÷ºZu%a4tg Θ›¹»1ìݹ-ˆ­ëê!—†ÔGl]Ö’Ìóh\òÐàfâ%s¯{‘1çöa~¶]Qñ>…·Р;Ë­xß›_™µ-Ä"¤û7“Ìë:gÙ¼`X„‰‡ÍŒÐç¬Á°ø‰%Ô‹¡‚œFp ºoÛr?‰³í¸ëkúPE·‚¶ªì:ó Ö÷mÖ –{ß°d6~ìHpþ×nÜÊ–¹[úÜ€0ØŽè|[¶¼I*‚{»ú£@0 QƒuŒF {9Ï%x³Áó¹ÔÒs)~ŸKÜçÒùEÏçR6˜™&maO%RGÅÇîÝT'¹‚õý<ÀJ€Mj°ïº}ý¶I¥ªék ó)¬XÚ`˜F7*ÔJ~Ûû+fK¤,ìΑ¾Û`sj¶ÜN>´ Å~àìç[’µ5†](R˜iÁêb:Â,,>¯ÓõÌY7Ë|!£AŠ‹•-Dš2‚ûöÎ 8çfÞ4:ÁÅE†"c“ÙUt<ÿ×ÅXoy?uŠÎêtŸ‚Ï¥" ³)Aã~6ÒÜœàH•äþÎ nØä¹ésÃïñ”Ù>oÝØ7MÅÉ2“Š€ã«*óð¦«è:£Š€ï‹>3¦ûø+m]’1®Áɰ!‹q¼ã¸óØï€=c2nèÈV~ùßxœýΖªYÆR0ߊ¥äVŨ’™jÂ°× ¦D)Y-!®„ôVÌ­Òˆe·q€ »j™myÜÂØ ¼]1ìý@‘æ©å²`Øç¦Ê.ĦÊ>v †…8Çl*’Wm…aÑC™dÇT¹ä·ÅÌÞÎuYÓåýÃ|«Yœu\­KJpiò±×y¯«P…ä±Þ mOÛë§LÛuYèÒy>î/eeÏòL­ÆG&8t+ÚNBÌçªe‡h…V4¡TI7gµ%¸Kêí÷ÿ—U™ee.Ä ÇG¯h㦬Õ4‘—fÛ$â¢E­ŒmÚ&òÂo›DÐ ØõÙgÝ'ÓÙy¸M¢åH”M™·Â¶§?qi»¸k+NÞÛëuKÚŒ¢/¤^xntOÚìòÐbg=­ †½è‡±¿ ³å³¾›1 +ƒ›JË$i¥T=†wñ¡›Á ˆìMð·ôûЖ‹ÖU‡a˜½keuÖlHV é÷ ¢ì]Ë1¿­TªWÝ„a¤ðê–e£úr!3o]<§¡iÓ‰÷ YÞ?—G9  þéQ@(øíí€SüþííÀ¡ˆ´?žt ý‡$'žt ŠŽr?éÐÑ|š/!ÿÞØB XØžGÁ’¨óí_£1ìš/!ÿ‰Î¯€N¬—·2C<ÃFaï›fJ›¶ðNß”µGŠƒ§áÙüD {ÑÕP*¸X­|‰…¡F¿üh¶h`:é³^cêóp”I•ÉTN»ÀÞ7¡–:Ooo1ìs»Lú†7¼P#™BøTüÈ»L2…ˆæj7÷³d‹r ‹ñÉu®[9Iˆx¾ƒ+÷ì|¨q*dÖ`˜sy…À0º¼–·Ëú Ãðò—Í2tôšß€aX›ßò:YöÌvîÑæ/lLªO‹ òÈïà«ÍW× KXÂÖµ$S8‰î,³íGu3׋Ô†ÅN¯ v×}H&ž›üó3™%"˜rOtBÜŠ¦ÜçÁþVô…)D?=aÑbõ„õu“ ¼Óø¦%[Z‹.é/°{ú¯ÕL© ˆ[Þ;¾·§”3YÌE3bX€;öXÒwR%cZf†>gËNœ‡d`÷RB9¿S+¿Ò¯\RXø¥DÏB&rÈ3ÖcX„aV”$)«\RX|3ä¶…3Òåý#ÊùAµ1ûm©Z‚ó°zÉ>ÞвDW ÷rÑöÀŸÃz.|+2å}¼_ì>—àÇEÛ;*üg…a¾«Â_XàªðOìíªð/Èoû`­KÖ5¦ãÌ—ÃÂ{Åû Y×BÅ»…EŽBv–“‡Æ÷:öAy uì°¼®:ö¾†3HÇ AB+'&EÊ3‚{¹è}Þú¸i{{}úJ¦á¸ùè¾ë–~™ÛQ ›.Ab8gØçh£Áä°ÈeÅ0D:2f5«ôRX¦•‡ÄpÈÉd.àeM ™ 1œ£šÕ–4ŠU1³Î÷ÿ"Jz ÄÁÌa¸jœKü"A¤s7Õõ81}Ær‘ηÏÙöM§ÙÌŠÒª»zX ç?À)Û>/µòE5YÁlE¹ZͱÉ:òP»MNáäí¢ÖcÂ×d%+ây·æYC>°ªhdEp¸{na{e,køÔœkŸÅÇ­3–¹7 —õ±]Õ4Je#Ý&ï[;Þ©¬æ ”Ÿc1œýóIìs§¬«yÛöo¾ÜÃá]Çù’)‚‹p¶ÑÒ¶1ß/&öß×HUóUedm°H†>ªl!{êåa£ýO«®j[ò>^HœÈ63ëdÛU2YÈûxù¤žÏÎC6ý0Ñç ú‡n®Z&pÀ?ÁE)Œ–(QXäªP¢°ØU T’qÝ¡ãç=(S{(}ÇZŒsɧÒ Ÿàšè"Jì .p( -Á½]*ç²¼ª®òCþÖ.ü-,1ÌYC~ÂþEšYaØS…°Æ¹ðOìªÖ8þ‰]¼sá៫zYã\xø÷“.Ò›"ebæ}(6Ÿebáë"ÂH*¶ UbØëV›”¦m–UgmRxI™lYd–MXð\™” °ÆÂ[ÊÁ±Øç¹.©Eaás¹‘™H†aÑ-Y³vÈ«¹·éà²Áã½&i3ÚµÔLs¸–BÿY«q×w(F0²Ã}‡=¢j`cº–%†½¨ €¥íW£* ókß&r&†^@â"¼ë;€ Dþ•ðÂ÷U€ É@Ì á!q0¢Õh¦0¦éhÅò,Ìǰ#´2fbh†qÀ°À©ï 1 +!æ¶=b¬eaU¿,씲®ÿÆ>›²iXy‚aáWר.ÈFwëeFg=Š6”§hƒ…ÅOš óW³–÷ϩŠλQ%¦¡msÕAõ}øFq_g›”¶X8Áù·tŠXRŽb¦ã7 A4 ÷Fi—#}4÷J¨IäÍÚg6ŠÈo¸ð‹³Òu­4–s5Õ9ÁE®ÓÂkáççé yðóóä‡{$ žü^CMÎ;ˆÁ6ŽžÅ[Z„ºp“¦Ó7ö<Ü^ûÂŽì;µ×¾²#¿Ý¤æ?³#‹“ýż[7i{;»I û8»I“чf…é:×\¬Ñ¿EI s E˜[(Jc˜[(Šü6·P¹…¢Ì-E¦àŠj1Ì-EFû!E†s Eµ Ï-E_«[(м‰BQô¹oüïõ“~®Þ¥Ê0Ýýþ­ˆÓØÀe"9†ù÷VhyÉD{rÀ£×-Ó Ñžðèõ“N§ð!AÃéÆÀ²ºˆž²SR-L²Ó8Œü›ìÔP‰m„²°{—ûS{3™×úœ©ã!‚ ².^·ö~Ádc±–VŒØC]îÁB°E EÛ,UAFC—MyÌa™Nû0`Xtëþ½'L´>—7¸õå´ÝÆ:Ýu*.Jã¥Ãv;è©m$†ÎE£•ýZÈœÌè7ËîÁèýL±,p£7é|e™PXàb™(òÛÞRŸèMË|.Ì‹…L!t* S½©Ï…OAañ#½`nòšÌ—ùPÚ@K~œç¹htåì)wy­[_§z!8ÿF/ºÓ ¢7Š <”ù—dº¶'ÒÑ;É~­2¬WMOpZ–¿7(V–˜íBpÛÛÐÿ`ºB«ãÉIY\ä¬V‡uùü®VæfAÂháÏJz¥1ìÞr㢠qRV£«1…e5Š.}±)eÒQDRW7}i˜i|޾øû†E3iƒÎ,Yû¢´Sˆ)%|ù לÂPÍ“µ7F^- '…D3Ïùm3í%òÆm•QÛ¨dëS7FBù Ôζ¯ Cj]Öê3ÎèÚˆ•ñË#­Ìù•fK‹QéÿŽtÔ¾}'sýns‡a¤ßÆá-›(WgŠ6~É‘³±A/“žËa®1Œh&î¾aÝÈZ5 P¸â×¥mÔ³«bⳄòýøEÚöì©íÝSZW¾Š¢'°èÖpšY' hha1®‘86R³¦‹¨g³ÂÑ›UU@>ªýÂÎ+ V\Ã[ê6tàq0Ug–`269×Yý%Hn 0÷­¾‚&ÙŠ¿ÊP/·„Ý‘'ÓùÞ6àVépÙ]X缋‰âÛ—:¯«a‰&‰w ¨À ‡¹î£iÌŠ1‰K¨µLe<iL1÷”ìY°&Ik´H=‡?.tµÝ–Ý@±7U›ÜjÔ\ªnnªŽb¤.Nº˜-ábf=ÅÌzéc]é>E›oË=|а˕zXŒþ‹Š©4è¶&ÁÖÚ7EÓ% †*=jk\ ÐÁ£½îèhŠÙè°£9–A0s‡ÿí}3fÆA0Oï8Ã5š =ô}†Ñ/ï4Ã>Ýê´heE1—ŠZoiªR7Їd¦ØyLÊÁöfß.‚¥fÕè1»Ôs*›¹Ä+åcŒÌ\Þ¸U±lSs{½k¬Š†JFî3žÇ3é4œfEØPÌ¡X²/]s¤k)§˜KŸöÞݼɋ±lv´×6„'ìýkÝ»{?Zš§û\`ëÑد‘5„í(ªKNå%»!Þëó3¶†ÿÒf=\5N(päyÄ0d\ægN\¸µá¼Ø|èdgùl ¾)óg³bÛgÓ¥ç?ͽÓ0èÅ\ÆÈ `–äN“–ˆ*]¹+­Á[WºKI<B7›al…4Ó:8MṞRµoßiÖÊÃh'‘L ð)|L.«›õý «(æ\È[eDY^ ·+y+¥(öbX ùßqMSìm gWú± г“~¯Šu‹ÐÔôæ]c¦¦oïÃ*-guï¥å;ŠÙ¥åÙÑlÒò˜&—}Ì‚2cÑSû=·U•„S08XüôÔΣ 3Ê0b%ƒŸô¹šüDÄãsúP·7®)T×Ôu–SŒÎŒÆ‚©­ÂÒ|Z'ž£-mQ6Ã\Úª¹×±,XœeIF±—Y»LÅSÑÆí²[†{[þña}ùgÉZUÈPEÝŒ˜w˜¹íÙðåÕMt‡cÄÃ;tLBfDÍ}‘t34 ª·-I0«vÌd_)ôUQŽÛ, (ÜÿÛbš-«~nªx>Ø'1>¶kö «ìÄóÐpÀ (ØO¬·h¬åPEàãF¥]˜#ç—S€ÍØë„5WÓ÷Ü|X½íPû\`«°`X2Œlª{À>ýfÔ¦Ø ùE[‚dÈ%UšyXñÛû¸âš3÷«ÀðãÝ'OÂÅÿLBþžÂÆññ4oÉfo6U-[_¦üI<]7sÎ$<ŒA]Ëz‹Ϲ·;ï7eýrö*œ¤ô×»')×m)†:¬ ïår@|ÛÛ¼½ÿþÙÆÞC[^¦Í*“ÏÞ㇭ezÆçñ¼—o)v¥Ñ·M3OC0éÈ“ú%bνT)Ãì€x‹]Ö.¹•1§ûâÅY}Úây<õ©½’]Wv00æ¯î›f;dÙ$! ˜C‹öˆQÛta_¶1ÅÜŸ ÿmN§EÅ#;Ú‹vnÙó>˲q-›¡Ø¡‘o+±Îz×0" °V™„r8‡u¯C˜X Ø÷W0·9gIZd}&§Êg—àÑ´îv´>ïº~]àÙí} ª75q,›ˆÝßç“sûÔ¡…K {9:tÛÓ×-½ {íÀ½¯5¥ó†jJ "YÉ ÉÊÅ3Oüßòÿ¾Ó”NÑN{'óä=6«ŽGJ±óï´ñ¶TL5  XRL\m×-Dìk=Ú¦[¨(&.[ÊÞOñ¾µH áKEE¥êÜÜ7Ï:¢“ROŜ˾0¿×CJ1×Ö¸†{Ù°<§Øû²},ôK( ìsÙePì{ÕUõsJŠy§.3-›ÍbU³B•ß ÍL­mfy×ðÇð¼ê3ë_Á YäĹѬßÍøy¦ mZ˺9kvïžîUŸVÄaÎîÊóunÔŠdøkÔBîÍ:µ¶°¬l†$ë'ö>=?§tÖ²!ê 1^„xܦ•Áž†éúõo†i :`¢Cì0çÚ~U)Ú¯âD¿°_QX0b©Cø6©¥¯Ç¸f—ð>9èŽÆ8ÇfoA”h!‚{f,ß!öD‰öŸI Oeq.Ç  ¢D yÑý­k'9mýUÛKÍÿ#cétã‡Yãó£Ù–à áÜ-` Ç„íÑ£Á$ÜÛGoþ›{\w3Í/;Y.,)f{ôMÍ0ë£ÇUS¸·>c—ð¾.is(nâ0”‰èÒœôu=jp/ÂHÍbÉ'ÃhžÂ©(x¿„<*d[â´OÁk ÖGÙû_´½çe’é³úâ Xëãö».Õzè E1—ŒM!ÞÖ5Iå1Å^¿¸,­á”…ýÚ„N±÷VlXB1ÒŽn»HRë6Ì›¡™)ö½ÆúžcÞuj1[[v{×£e©áÜÓÆµšq₆ed•Ó‰T„‚Ç69åtÆÂ,q_þ©â+·,IAèç9_¶ÚHSLÉ*ˆkþ—9Õ5rq€½,X"н¯5rü˜ís%1?Ú÷¤¤ãW~*;ãÙˆ/ëù2XR%gìçT¯a­í^GëL­ÎgÆ=Ù0ÝhsF‡!©Ç˜Oœmâjq7{´AÎ9qUU…Uvä\LÈÄÅö ›®Sã^(¾¯uáux‡t=$±ÕœM‰i ³Ûò­ßšõð?‚vk9`°ýþþqMF§kš0iÙI_L”=Ù”u“EÑÌNú¾r f9Íæƒõ~}í+Ã/NpWMì¿}/bür›¸PŒ¼NèÏcQC ®×•^õžÈ²Òb鸃Y(Y”fù ƒx{'ÍR¶}ÑMsuÇÂp(ÔÉ—Û»øgèd:$†²lûîg™Ç1ØèD8Ü` b2–1Å„M! psl i¾¢˜kSH“-Å^6…4ÍŽö¶ Ÿ•ìh‹NY“²K¸– ›‹*c'õl*`è8ÇjÙƒ Ø{^©€µq¬A 9Ûä"{«sŸj3ï°-Õ–N‹EmRmޏ™½hF4 ¢œ½üf/&®g/¶8{0ÇR,†Ÿ¸ ѯuAŸ?9,&Љ‹R©KòJ…#;aŒé–®J+m,ˆVýiÙŸ'“ù Zõ¹V¤\MfóLOâ({•Ö6â½/kv´nºå»—¯+©*ó°ˆ8Êq¯‘]\²KðN}»*JÆQ Ðæ/¨VýňŠ9ÅîeQ±PYM1aÃúˆbW#*æuöDR̵aCN±óˆŠKš°3W·2o$ †±÷Q콑å§*¡šK8ï£ÄQW™¨Ì2ŠÑÀ² C•AÕ5ÅÜ o¤ ÷¡ê(F|x{Ã)§¡@ˆÈÀƒ7²mH«7Ò6eQ("tZú¼Jv¥_úÍì k‘7©‘MDº ø’¦,µÙBˆzæ_ìÙÝBq2VÒO&Æ=OòÕQXUmnƒdhiºÛÎyôÜç]§G«+îæ‰(óßÄÝ<‘æXÚjŽãk¿»ë㊃dj' ÔÐã+DûQ)=Äx¥'ûÒ«aXŽ o)Ü“ý¸ë—oó Sݲ£YídžaVûß$—Û<‰ˆÃ7íº÷Òi-Å—ã‰!¡8«>¢À7$ÚÖDw•±”ÝŸt¼™N­yߨRƒuÄ  zÞý Êísݨ X£‚pï«V v_µjNÊ3…‡ZÎ]=÷)䵜̵•r¢‰æz<Ð~¨ääØÛVÈ9³+ýXGÏ•¾÷£g'ŠGÏ*6z°ëѳ“= ØõèÙÉŒžÌ>z–]ÂÛªnƒ—ð¼W·a˜]݆avu›’bguÅÔm³«Û°£ÙÕmZŠÙÕmfW·a˜]݆ß^»º ç,ê6 Õm³©Û”>û{7ê6ŠqvuνNRg¥?çEš£Óò:NÓŒ¡v1ãLÎX“ô:Hœ¬AïxÇd6F¸}‰£0óî•y_ÅÑ€ÞÈëbw rhUD줤æ Þ£ þ4ÉyJvÒ7Öýìml{é’T“ÊzŠí–ò.¿‡=ç¢ít0ò“2yÓ}óš@ÍõÈ.Á;a‹Íž°=Nùçmjæ¹È#çGn}ÿþ¥rõ«C=73tZ‰×©<z£šJõR%`ݾÜëëSÒ¦2)͒㪸Ác-û6Jê¼l(æðÐíj÷2Õ‹¹QÌ%e К¼0iÏÅ^'–¾‘‹MÕc„׈Öþȱe*3‰õ?ÑÚK ´n^/[`ëÏ­Dÿ÷õæ*8N£l“dnLéøë}êˆÄ…?)óÎìo¾¯þôûCUÖ‹© ØçØ8 ­ßQZûEÑlúðþ†4i£Ó±¡˜s݆Yb·¦xÝuk–Ø­)^ÿ§[SQìÜ…­X¶ Ú¶W]Øšbö.lE1{6Ãì]ØÅ,]Ø »°Õ¶½êÂf—`ïÂf˜½ ›aö.lv¥7]Øìp7]Øüxç.lź°‘»êÂV¤ 9{6{]ØŠua#wÑ…6³¿ªV3îÜ…­X6r_[&ý³÷ã6–Úûq›‰GÃäý¸ËÄÏ Ã\K¶»éØ{Y²ÝŒH4‡ ôתZöÍ‚b[®›íkKu§ì†x¶L7ǰgìéN»TU‘³õQæ?ï|ƒ ‹—ˆ¦òÙL÷~4ÇòŽÌwïHhN*îÞ¶%ÞââÔ^·(ôB¿ yGÔܱÿö:aÛ;rÄÞaç_ÁUè=»¬Ò|4ÎËjÚZˆÆç…[hª¹ÞŽM€ÕȤ@¥ô¸Ð‰G“¬ß÷óI¶ºÆ0Äû}R|æ¢\U^DÒq¥¬‹A£bo»†jßÝæJÉ” Ýþ[®+Yi)ÙI_$?µŸs9Ô™Ê01ý6ÉH<¡îNÖ÷y¯Û’bLWvË>¨,Ñ}” Uõ6ɇÃú+åâìyB1Ï`Pýžª<Ÿt¿¬$ìö>ˆú,¨ÐK=~茻ÇlIq¶]³¥ÅÙ7â˜-)·‹c¶´püý½¶]@YÒ`¼Ôû(™(Š ›d$Ç"䱿Kk¨ªn'\¦?Í®»wOã Ñ;#â˜ûÞ`zÄSÈ÷&hÀp/D•}UYÃŽæX0ÓÅúyªüQH±lS¨ïkн(¶½JÍbËMuÛw{“ž{Ú(ËŠbŸ‹´ÎQµf·¾×7¥×Æ :¨­š.„y¦d¡zŠ9Ô€ÄÖØz+¬qù8‡‰!Ð[°œtгÆôÇá’†ggËF"[ÓÒòùµlo^|¸K­ßu5USPìƒé)Èv¯›a&³P5ì¤ßŸTi"iM95¾õ¾Ó²ýg“© ±È¥®Óº*øÑ „³?þÖ¥&?2kŽs11Ä<Ö¾èÆÑA0{j?]ÝøÆ× ²·²  œ@†SŠózÅÇ=Å"Ö/6iæFN³ÂXć¶€ÿex³]t8õA$)æZþÛ„)ÛÏëö¿µ #ý} <Önyëâyj)æP$x3Ë9mZlgýœ Nö+ –+ ~Wú:ˆFò‚å+Dö+"PåOOu°“~®îÛªkîÛ‹ä×OF„i·øé¬^Ú|o›I²8¦»àskàåë~5õP÷Ëw#ª³ÊÊlŠ? ˜°•/”%Åkù‚¦˜k-_˜(f+"2I¶Ïm|©FSîû¸Íýâíý>ns¿³æ~9fÍý¢CH4`q¹y-¥Ç·—¨¶^a¸~Ÿ×á;(¾2ÿíy(¼ã9L\ ÚžetV‰0æ…2ÁŒÞÆ<+4XxG„1¯” ÌûíGÿìùUð·¥_UŠßŸ¤±€Ñ_ögù»R÷úÑï 9©¹ÒóÈgHÔ³¢áïûºhXñ¢áïû¾hXQÌ^4¬)f/.)f/f˜½h˜aö¢av ö¢av4{Ñ0;ÚMÑ0çlEÃ- ÉÈç+…)T†ù~Ž3M1™\º¬aäªø^Œ>ÝŸ~Û3N!Tñ4^´Àñ¢‚è"²ñ¢šÌ=ØxQÀ^çñ¢!/ ØÛª²ˆŸê±,ˆ¤X§°ÅË{ت‡ôXOLð„è>Œ|qmLÍ{pÿ’çCM<Î{0å’c¬WBï>VhþÛ}¬BwÇ «,E3áñi^«-‡ Î%Åhv_mún,º®ëŠ9Ûsõ}—µ±ZÌ=й¬'úútÛ5Ã~ñdP¯^Þ·Rf³FßÇ;Ž™ˆñh£Jª(g؇b{ÁeWeÑœ£ãHÄM»ËÞ›TÉåsÀd¨'Î}ß›aùrÊŠˆßÞ_ß7ÆŸjÝ–U¡1óËÄÿÅék‡èb‡ô‹•É9A¹}:“n“ š£†q¤¼8ÂòâªõÓ²dWûtiE0´%IU…0¹- ÞW~ÙÃân Œ{ŸÇHÌñbµ43ÿ:¥ ns—,N×#ý“É^AVÊÅ‘¯ë9fœÇúŠöAäQ\Í fîâ{üÀp•Aœ~y‹³6óGÆ=ÙÌím2…Œ–+5{¾tšWº§Ç³ÍÚ©âœÃb¤Ûç(Õ˜å–Ôzfš×iXàâXcÍ#Ó¼®Ö;´J©xçÅzÇ1ëz×0̺ޙ¥Ç9|Þ¨9ÐMÙTD¸ý2}ñ¯¥íõÎØ‘鹇^aÈÙ祌ÆlèbŠ‘^á(õ‡Nj_K†ɉ‹ø§,QúTž{,ÿØýée!ÓìÒœbtéI`YLd­Zl¢ò\^OÀLš¼s¿ì±ùÁ#³²è„¶ÅEîò´ë'Šy´Cq[*†bÐEåcƒG8þ⮾Uñ7ËÊ^™B^Ï=ÕÓï _6ÙÚΦ'N\/s¨2kçÚUV)‰DæI›±'’ÿî5Û5W³¬ªŽ?Xœø³Eú¡ˆT6Šþd÷ù%ÿÐ%¹NŠ¡ï†)`ܹߔÁ÷ËR ¿ßË–•¹I1,ìÝ4ÀÌ«ãO1Ò‡´¼Å[@¢K›egĶ*¹zqÒìDï}{R”#¤’«'Í"ŠÑéPû[» ŠÁ/ð¿]ªŸnUBr ™4£Q!Xú4ž»5 ï{§¥š¢¥ëy÷Õ3ûbâ<×Õ3ŠUÏ8‡½z¦5Õ3΃˾$~[°ÿþÇ×™,KŽê`ø•NšœËÞß~<ÁóýôÌ’mQU‹/ìd0!ý"{‰_±³Äo…$~-FÀ,µ«±ËΆÂ ͉ !k™Á)ݲbÑIðZcY2®Äœ!fèS=¬‹@/}ž°>Ws²[zÚ+B¼ZŒÜ‡ ‡Kˆ…Cˆ! ‡#,BÜ@ìºàóò¼½àóò¼óÍ¥{Ý^>ú—¾ŽEÁ¿u|pþV$7÷x>§ ÃZÙªá÷_Ö;ô´^=-³ÊœäïsüœáKš-ÍÃK›–O|u-·Š?'¯î7ŒŸ¦‰ZHl\ùû†~[­›`ËÈã/„é–νýàoÓ£`oTÜ»’·±MxD÷ò6 ÄÂò6bay„…åm–·AMx£¼^[š}“CÇz‹ÂLù †‹UU2Tƒ+¹©’¥º·UŽ½Ø·AîM® ×ñÒ¹€Øów¨¶ºBÌ›êjcl±W(“ÂÂAúÝ—zFñÏäñº– Ç? Ç? ˆ…ãŸÑKÃñÏèiçøgâŸÉãuÿŒ^zÿŒ›‰W*<Æ?£0iòS*<Ç?çuªŽ®ˆ Fêlî×½O–È>•%Òôغ.ù ™Ê}ss%œ¸öáA Œª«SÇå¼ñ¢Y!Fàm¯å ­&ˆ½Ì„0tl¤¬E±J:¶¹É´¢!ö†—çÆÒŸË²êŽžö+j¶'Zí—Ä<íõ Äb”…`3ðùÐf¾  Æ]® B¡ð¢E¿íñ÷ÓvVÓloÊ í][Ç=®dÅ/R‡„eˆÔ!8$ʘˆ_¤y|ƒO‘:äñ½Ô±O‹þî#u$Ä‘:»–¥¯êÞÍ8 ¡gO¡@–^lé±Þ8ûRËÒ«³Y±`°œoit/Kï0r/K°€,½pZ#—jE£W+"ÑóèD·îÊ^_ê2·þFϳ4¦-oÁÅʬ˜%Êr'µ¢Î«¨,g®:sÕ«îØzôÛ‚jEõ± ZnÂ%[XÙ ÉÑÓ⨑@Mø^¢jé[úº=Dõ+Ä¢P¨§õd¨Swêé_ú¾ õ܈‘ÀÍÞæŒ³ƒêÝáfÏgÑEÊ¿qÉëm!·‚݉­5¦sº¶>-‰âó²›ÈÛ¦s­ä0bkÎzØ×Õ¡]“fm­c”±µÿùb·ZûHmä³ZIˆ½°—M—ŸjYR´y:B I±Z¿X­Žg½-›L¢C"¼sx‰M™ƒÝX¢ß£HpãìØ«ØšA$‰ð‰zæÃT t`݆º÷p¶ S%9u¥ñÈQlM{íL­"m¦Í©³$¶æNÚj^ò)O*¶.YŽ8rà8³Ü†:ÅŠ­9#swƦ Ÿç©Áï…f·1ªXE‡y8n¬´Èövtý¬ŒîNdˆû³ÊahoÌ\24@OÚÚë07};--â¾-sõߨí–)ý÷ÿ nÀ Ž<ÚgÛ¹‹K!äï¼C˜[àLÙh©•Ž"ä¸Â;eá¿(¹u.øâÊÝ|émØù)=Åà´ìNž#Ø1Æm]¹¶Íí0¥'[ÈÇ)ƒðN­ŠÎÁCÈI×òõ”¶x.!‡½Üm…šHëf³^!ç æÌF|i'p±C]9£iEeÓLbHuoªZ ÓRvξ!U[3f98ª§Ò1X|‰IJô´oPÕaÏëv5ô}?ºlGB^±*+ N6É8äu±mç{%­tÎÓvÉ8ÄÞ­}:³¦Cáûû`u¬NÓŠÖÄŒJ_õC¿X$ÄÞÁÚW®¥ïë'¾â eò9Ô{ñYÝ¢+t¤€Åâ€ê;ϲjpªï„Ä·ªï~°â;Õ÷M4;«¾÷ª¾( ³Ç—¦¶¥ëÖ¯:ÜÏbG½œ´ãÖ·çmb—»‚#ÏÛĮڽôùw›´ƒ±PÒN?¢ßJÚ9`×I;Ü'íXì¬Tåžö¸žHæŒääOÈ3ºë^—“Nžä>on„X8oNB,œ7‡°pÞúmá¼9„óæÊ›³X8o=-œ7‡°pÞîÞ`ÞÜP"\ú2c̉ª¬kѸë Îr¥ëœYÏç­B솞TˆÅXP!–¡—^Ÿ¹¦<÷säöÌÕ7èi!…ØbE¿íB!vPæŠZERˆ}C±À~šßÞ0Œ]ùô•¥,.#óÔVOä³,yÓ•n æ6Þo,±×‡äyÜ~É'º’JVC,º*ÖŠl˜*aÉýÒß”°äEŠ0X«$·U‹3™w"¯!F.67Þµ£ìZˆ=A²“ 5’|]—ßÐÇ×%,ÕvJXZìý‹‹Ï]læZnk¹¸ùö=·™Õ3’ÝÌ Ùn‹`ÐåÞÒ®ã,áYÅ!ös¡äÌÅf®m[õS±'*G¬›jÊ÷ý¶œ!¶<{§,¸$¯ ¥¼¾LÓ%ëÒYBìs5‘2Qr¿^âB(‹ITì{:1¬™ž¿]…»÷ÏÞüýaWÓd^–rEÜãrã¸.³2õFÄEÐ=bã|e*›%µñ:¸ ëj ×Õ×ßQ+wº]­¤ýA,è¤ÚÐÓž¡•°–{¨½ùåÈŠeC/ .˜6ñÓbA'Õ†^êqhê¼(Úæk'ZìZ~jé¥j?ªåË­J¯ƒÜÁa䬸Wtë0rßT¾¹Š¤°séEn%ñÜ}/f¹¬1B,\7B@Œ\n½k2ø–þvš‹­wÅXti™ÓÕ•Lµ¹p:÷<áNÚbð6ϾtËÖ­ð¦ãë}È­%^¡ßƒQ0·ó®šTRÿe}`ÈI/†WuïßI/¦Gz1Ž{œôbz¤ã¸è$,Ò#½Ç‘“^ Gz1Ș؋ÜE7“²•.v:>Èò¤[Ü,‰²üNº¥GÒ-È\I·¸©c7ð(S)ÔdZ ö>)¼ôHáÅbŸÂ‹Ûbï¦Â/ ¼Xì{= ^ßÅuïß©ª¹æ¥-:«äLâǩڳ¹®‹mKGgƸN®Y õz3 T²Âù(¡„ÃV£—>¯¢}ZÖå%…Ø —Ð[M®S¾ä²@ì»uNhš†UÙ±ÀÌhÍb•RÔî¦.~ ¯PÛùûçÕ*;˜„‹‘‰ ˆ›ÓVW]E'·BÄ£êÖiV5ÃÒ3ê¼ç1òþïgÂëUdó¢Q—Æ™ký a „¼qÊ_¹ s_µø÷=q ]±ñA4sޏŠ´ÞÇ‚¥ê@²o¹÷)å¯R΢Œ¯q°’•œ­è¢£³q1JùÛ÷ê¡_˲hpÞ{K3ŸU›Žy))jGdVÅv×´WÙAlìK3l9$Æh8 ZmuÓ :i6zlÙg4ÅÑA‚Èc ù‚1r‰u9Å/Åzš*ÔºÓÐrM ö‚uËwlIXÍ6šJˆýtð]ø9k‡¥ÞŠ–CìyöUä e”'9ÄâÆ4Æ’¤„ØéLhjeùT§¬îQ÷þ]ÔlËǪb EÜã‚GVñu ÒÁ7f‚ZSZný¼Á™µÚœ¨éÈšEÔˆ;Þ{pÞÖmSóE0ÄnŠw“sÛæ„Òqo˜ln쓺N˜àtBÜçĵõØ–eyhG|¸pÑgþl,Y-ÐÄ{|Ñ2eÜé\”…ßfAÒ¼åÌ"ª8ºäÂE“Ä iþp5SÓ”7)ú}&iþÀ´®”Iƒ8¼œíÁ¼U›«¾,ç—3š[G¦ÚÑ]ž"îuâ:¹(nH0÷>sËRµm‚g}ôªófYY²¥© ž,ˆûåµøß§ž—'þèa¹ï‰ë–TqË€8ò3§M¨9c«¬Çõ yøe´0÷¤<ÓbN:,qщëÚ¢QVp‹æ=!ˆÛ3öõó9¢ùBž?mVûû2š$³ŽaF”ã7íUûçtœPÿ‘7àÌöÒM´“Œ6è;'(ïoÌšYí/mÛ¡EÄŽ³ÖŒ×}Ö2šùmÒp_ÇåÎu–tËéJÑ:ôüó¢ ¹M«¡£LËI°qWEÔaut“PõúŒ]Q— ˆ:‰I°ˆºZr³º€X°ˆ:EX¸ˆ:ƒX¸ˆ:jB¨ˆúämirWD}ÆX¸ˆzƒº7\D]".\D}@\àsÏ{Þ ð ð9ì>„Ç¿ôÊ9iÙÈÎmïS«Ém™­‹É‹µ-­=ÈÕÇÐtÜÛ[ïã”ËM„½li%¹7ßÞ§(as HU¿ÕåZCì… }T­5®Ìeó@™0'VíÊY31pôÒJÓ{žúmCWl9Âà”3/]Ë©ãjoL öE5õ…©£ è{Ô½PpÛºNu0þâÏï“Eců·T.ý’lˆ‹N–Ê\Íë–,/hÑØlei:gi:!îy8°èž­UÙMxš¼%`,FÓVLâ¼Ö·—×R ]\\å> D¶™Pk–dƒÞ~{ÍŽÜíxjŦUÑà~þ:NGyî–YÞ¯¬é ¿#¿EevÌÓ±e%Þè+Áì3¹Øô´ÚòqâlMžtnkG~œu·.õ°ÑA°q@ˆû¼WTSõ5ú4¢×Eá®b£[éÜñç¬E¿ßÊt£Kï¿Û˜}MqB «`½ŽÁ!fn<þ5¨VE:M©ô8ñ/„á?ï‹Ð¡£}K õ°b/gäÑÌVÛÑuoXxÚÄóæÂNnêÑ{ôƒj%S³ñ0Þ,}%ŠÆeÇ &é?Ö/«Çak‡mGB㚤 ~‹ZÉfáÂPc¬/°W8Ý¿¤y%XQAŒÀ*¢æ”<ÐQT-+ ö„jöh¦^šo=‡ˆ¶Nͪ”jW§þ°‚å¬BsÂÚ3Z¤C¡&ß{îk>el†X|Z‹YZSVª¿ ö…ËØ>ÍÕ†‘¨“ïÔ£îýCWl{rQ´… ê_¨žh÷:1mlJ7ºj’R'd£¹2]6Ì‘ Þ®,§2E}çB?¬×ÕN“¹Yºÿ¾—æóé«í.õ<åˆ{ƒK}³<5’2I¥Ä¿ïUÊönÞ†.—e“µˆ‹OÛ€Ž…SgÌ Çã(¥o<éÈ JÑ̳êh¶HÎÞÞ.¥U·e)zž9èýŠépý]´jõì9ߟ:Zb=åÚEKS6Ϩ½Jh13&\=±E³/zžJ?gê;×öþ}Ðoe¶Ñ†*KvI– qØoeÎUÙ˹Æýò9Ý¡OeøËüEªÉµT¬ª¢¬˜: î{Áµ;7¡ÃW¥HÜvË)OÔ¿ Z ÈãwPqþ¦5Ò²D\·•½ÁåB35_ê?â·)µPBÍØÒ•I’ Ηv¹€|êçlÉ|¦Lü=fñØó%¯×…UÞoá/}N½—WLøÀ_ú\tJ?¸+ŽØ]úüeû\)uTÆÂ}[Aí­í¿w^›µÅêÄ{É÷T¿Â}Aê¿ÉÌ)Ä",'n"·¬Îš bgÕqUsÝ5ÃE>÷–¦\‹sNèigÕqejðsˆ½D¢VIÖ~U&<Ä|Ý>XûÚÍ×aÕ…í Ã+3éÚvS'Sl1³ò¬6кzÖr™ðo³ñµW•|ìJ 5R¯*ù4 WòAO#°TûÞ% £œeÝhçåA#5qg¨MgzéŽX„0=E’yH²ª¨*ˆAaÖl7y3*r6çnC©È ÐJÞÒ…µè·½NÂÍj^R92·£Ô¦šš³&‡Ø/!³5س™vM[9µ ‘ê2ûw,éڤ튵ô‹²¤ ãŽé::,¸{ÿ¼ú»±Ú÷ܬl-d‰zäáUâ‹¶«ŽÊnèµ dÞ‰¼esƪÑKŸ!T›¼°ÏôlȘ¢í÷Dg–kÛs°­)ãÇê1cɰRÄ‚(æÆWM”iš’’¢Áx€B~ö°P·u]¹ËL@©ÿ_~n}ùTÖtFsÀj¤z%Í]«šN¼Yƒæñ.I¥¿EFéÊfw!5R÷u'±wYÓlš×qH^ÚZ)¬aê08"Ž`N@¹Þe³ õKt¾HÌÔB¡¶¶ îuâJ:¦ÃVäø»}£x SˆMêµ Y}²8jbUU-3ÇýâSë¼Ö·šÏ¬ëJùý¹{œ²£Ú|YÑ‚­dãÚ¨f!*ÖP4¾äqÚÉhC)Ë$z/‰`Ø«9SN+e2à…Šq'c-è³l‘%þ}ÏŸrM1O™:,Óaá{ùü:—’Á¸úÉ<£y@Þ§,èvkº,¸ÿÈZ¡æF¬V¦´2VÑwIÐå®Y® š°”gh¾/º6Ñï-Z*Yï%_ïîý]KØØ|ª,©qcˆ{àë cu³Q_Œ!.ºâx½Œ3æðus!„Ô˳Xîù‹P°ÈŠ“]Â2ô=_˜3ß[’&‹K¿·ÜqzÝ(zJ[.úqâhIÔ)^5š/Ï^›ìÍU3ŒŠ$ÉÑx<¿ð¶xçÔ Èi5'软¿“fr«æ²š. ·×ãÂY‚¼ _rí,q>±è§‚\/P3ùʧ‚°çkëåûs¿#׋À®—ïÏý~é¡ ö xhĈ°8èÈi ö=9rvä| Ö%>9|Ð[mpÄ•Çõœ Ž€\ƒ=C–#'×À®!Ë=C.¤s/˜å¹ûü„dC6ÉÄmÏÏ€„AŸe•ðßç­„sû™ë ƒÿóue˲ªJð—VwÓÓã}¿'âüŠ(¨÷ë/*…U½#VÄ~Ȱeª +3—ÃØiK ™ë3Óà|‰ã£iMÙçOÓ »4­¡°KÓšð>ivæ+á3|ý4_:L>]"àG/ÏSéqužªé·qž*w_ëÏóT>ËóT¹û¼.ÎSõîëº8O•»a;O=±BŸ@ãïû9—­–š'²­;Øé¾bÎ]>ÍÂp<÷E’@`›½ì#:V\+¨@ú"¯n [ŽÝÆ j^¿ßXC F¬£Û®Ýçƒaσ¬«æ±) 6‘]2èié<î —]ÆöF¾<5cÝw‚¼ÛçLOÇ}Zpå¿{¯îy“^ng’œ+—[îý»¨„ÂGöGÍRöÖLvû!ä ÙÒ­þ-§pˈk´ò°Ço£'xûmô¤0ìÚèIbصѱƒ` TQ¤‚` û{þ¯˜: »¯-}þ¯ °KñŠŽüè¥`àDžv)¨†]‰WÔ–<íL¼Â-43eþW«~c¯s}¼Y½mA”aAê×µf5/®y-ë­ ;í{¢Ã:¤¡ ¯ÝêNÐmѹ©i0ìyPN-›yÃåT{])§¶äGßWR§²Ã°)-ZWÞæJš þ‡´¾í^äM“ü}pš^ZZÎ\¾6×Ãî‡äz(UäþÆÓÃg¹MÚJ¥# Û1¸V¹Ë¡UQaØ aHºþà]/0ì…oWÖâ4(k†.ư7Ù…ŠÂÆrÙ–m1`Øç^Œã˜Séþø xåÙTÆ%5P Ý‹ÈBÞ÷*5Rdmf‚Û®ž¥œ- ¥²ŠàîôÓ[A´RZøÝ=ÄŒý.8 ̶}Ãîôtr¾éPn‡³Òvöÿžæ`nÅ·)†±íÁ3>¥âª³ÆËžyØ`P¬43™2a†ð ¢“]d^K?JeÜÍÔ=mÊÇTFZšà†!2¶YA„#Q»ÔB‡wÛ¢èÐoSTÛ ÃÂEa '§îÝ¢ÒTyÚk³Íô7ÅsŠ”Æ 6Á°=VyœÖ•? ÷°ûÖÌ-llL̽L‡‡=0Ì·t4S%(Œm^~¾Íï&ãÒ“Z= ¾ùwkT'•‚}{öÊÙÏJ ŠÂÞg0[& …}°ÌÞrÀ©Tä"éÄÓ5<ìKÊ–Ô¢¹vù¥%Ýû‡¦ïZeéú·˜ôHÿz¢Øª¶2¸{ÓTÆ‚š,àî Ø¹>o‰xSCZq ¦èyEUO§Ïcå¾¼‹¢¹5ð¼ÛokRhÆý·5©Ä°kkR»¶&%°kkÒÞÃKL¹q“ÂÓD{=$º]©J$CÞ;˜uA X3°ÛcWô˜‰I)—mÃöñ\Ǽîo‘Øm¯ò–@~ay74Zʵ~_,Í #µ~ÏwOSP'ìaÓÄaâô0ª×¹žÐ7¼©†|İ'f±-ÙŠm3Ó·£÷øð0Bg_^nöN›e¡8†½O.ý¹l3h ûœÁL£ÔPaØ‹]zÎù¬@º÷±­D=…ô‡Š€»m—ÑžB jáŒÌ‚»Ód^ŠçzýŽŒ×íqÄõ\hÒû€c((ñUýšGªP»v…UE\cØ÷ ÓÐꩳ<ö нçƒZ8|üíö™0Œõóq;†iª´š&kì~rÑ‹” ÷R.ö¸´Ä‚§Ý[bi »¶ÄØã·%–İû:¹å¨×“‚&ìd€*fvªvª‡ÝìÔ¢àrc§z؃jy¬á”-Íh c¥ÿ¢¨ÜAua“ÚÕgb*' Ûè>K÷i>‚íC&¶81’ÂÙg-h››0¥ãdk {ž¶4MÆŠÀ^ç°aì ì}ÖÒ¬—S˜oÛþ|ÉC¿½~ –³{lTâ8ØwšÜº.0 wÈú-8˜0³Ë;†wwCÏ1ì¼CÜÆk {XäE!xÛ½€a× JÁl(Øvö-D½Fé}={ÝLÊk c'„î¡ûí“ÙBŒåh:˜@‹Èmp®®Õå}/\+¾¬Ï¹4Ï2X<â1†1óš¤Fw£B`¬|ù\Kãi„tññ9 ÖkãØ/ƒ¡¥ì^Íô”nZÖÛ´D6 ë|óŠ}RFn…ùÆnâŽçÐðn,Af–a·z’š)Žƒag7&µ‹òw°ÇÙ­Dªxy;ƒ¥r C'SéÊãN+eú®ôÆ‹ö:\^¸T€»Å×’§½WH’^!±Çï+¤î¯ìú ‰ÀŽWH’^!±Çï+$‹a×WHv}…D`×WHv}…$I÷^_!QÜõ’&¸ë+$Ep×WHôy Õ,$þö¸ÊMgðRÞEDÂÃ\ $ ‚gl§°iM´ÅÐÃ6ˆüXöZ}VU^£—!?–ˆD.úf2äÝÎ$)\†TÖ "?–æ[ê>}ÑÙpXÀØ™$ŬÓ%eoáÔtóc •«kFnÒVg–Ø÷k+5ŸƒSÒmK|Z¦”°*+zè¸ç9#Ë+*ÃAÛÅ]Tå4 kæû',¬çïDhP9s› ea¬=ƒafêªç:û¤Z—½ ö¼4„ùü¶û#°ûÉ=›Nƒ?¼FÞ(T¶ܸµZ_PÀ7ÊRëÒ|Mòš"çîÃNC —øˆ„cŽWóõ¼Îm¾ÍØøê Æ¾×ñjÒp †¼Qv-µËR{?ËŸW©ÊˆNÝÑHçEÌá{~þ]¶Ô÷ Ù…@|]‚‹¥“Ðd‚¢‘t‰F 1ÃNZÊ;-µBËóvÈA”dßÂW â&p= m;Ôö8“’Ìg)I‰a»d¹Ò-×£Î1ìy¦ÉgHònè ÈË`¹p´‘ë8 {ŸøFæmßÈaŸ Ö­ ÷_B­ ùÅv%ket:߂䔩0l‹”fj4k¦j cgš©ù¬™J~ôy&†Êg1Tƒa¡ßxâ5 „Tnµ„Ba{Øò,m8ÏÚfŒ×¼Òu¯ë1bØ-«OPÑGy¥Bž-ë½P4H‘•aí}>®²†ùT$‡4êùØ¢áG­ÛjJh-EàbÕ†uA¹˜µPóÃîçï&Âur€Y#L°¨n†¦Ÿ:/òÀÌìùê°fÓ,Š1ì~.Þ”/kÍžˆ {Ôdâp*‚`N` ÊîaOt/»Æ+][÷Õ¾b“=_¿-a°Þ¿- ìÚÂQcص…#][8 »¶p$°K G[`ØûÊk,t/•µÞ»ƒ%Ãîçî`9Øp°EH°¸ŠÜؤ em/\¦ztv‡Lúuôb¦j.ñr »+MÕ&83@îJg.ྙ½w ÀÝ`AÞ·ŸƒEa—ƒEaÇšiH¦J¦£oÂûê2aŽ«b·ïãeÂê W “Zù%²&úÏªŽ±®q¥‹ÏeÂeaìH¹pñUb”aïûžª½®pŠšLµE‰a/|Ú½jÏIc`dMD`½ƒ™=ìs¢Çž–Ù ¼`‡}Ï`½ÜàLõßuú®Aß”M2m(î¶±w¼^H9ðZ¦QJ‡ë~ÄMu,ÓtLîB×õØkª¦x”åÐÜ&d¸Ýž®ÜX¡¸=/}ð`Ö=v¼Þ”£‹§¤³ ’ƒ÷ÞÝW§q¢s[å=†í¼cç:94µ†Àä½+HD¥¢°c&R c'}‘P:Ö¼ …7>(^(…aÛQ|²*­äRj™P¯õ°÷ ÌÊ,™xa"6¹°öìhMYz»<á°7Oš„ìS™’Å¡°®ä”J3?àÍYÐÖ²­\JJpwª>ã-»¾ ³m767ô|’}O Iõ‚„¬K…Ь…o¶“êÝpSí²’‰¶÷uê]Õ}_Üû`^Ø——6ïH7ßNm ]¬šÞ€;ñ%ÔÜ4M—“þó±!¶e-ÏìÄ6d=¶—€¢«t!ÓXñ1ðû‘ÿ–ˆJð‰“§=޳ºNL>Çìý$ç•Ø3±t“¶‰´mÜ-Šý•x—•ÎZ` ~öÞòÞlr9Ÿ›ZàË|vœÑyäçÃÛZ^覌0 qF}ºV.ÐQE>`;'HV¹W¤gŸ‚d°949&6'«½ ×DH °“•×åôa¤Èg«èDü/ò–wÉ…¤p»‘±ðõó j©‘Ù• ¤v~ÏžÆ0 ÏßžÆÃî‡%iæòTQ Aég§µ0kO`Í:ñFÒŽe)+8•Ǿޓr©:çªÅhØìƒÙ=,ò• 9B5%E5ùÏùó¦wæèÝæH¨7AÚçÿûÇO˵äÀ›cí½k؇ê ¦í” ™µ-†±s˜‰½£ Û´ÏÁ—*,e9¦ÞèˆmÚçÁ¾j „g‘çYÃÞÇm&Ky܇m†ˆš£mfî·ÑpÐZ؉š‡§Ŭ5—ìsX¸Ö U$±I£ŽK c„V³lZµIS=Á5ßï»jP¡†‰š6-´=#Qó|*³¾È £D¿Ì“7+a Þÿ|÷ÒQŒi¢;Øw?”€ß-µCØw?_ÊfEµ.àÓZbØÅDÒrŒMÅø°Ë$I”FÃ^‡]F&U-›ëû·ßeï£ìöÙÂ.ó¥ >›ºIÖ°Q"±cºõëfTa;î§ h?ÝÄŽiKݷЭ€oá{Q$0—jT[©Ò&£àæ›æ2ŒÒÞB?ô(… =á}¼‚ ?¾·³‹W¤‹W ¢ã{Û·ÔT»1çöº(üññ÷þ«ð#¾HÄø¤¸Â„~»_ÇÇ(jD"Ƈ÷¡‰ïj0¦BÚPƒDŒá`_†Q¸ŸÌd¾ßÜ\âö¹RŠ¡C¨¤@¸yÊM7«nBÐø¥fL{!W¾Ýjé•i†l©W5†±ƒŒPOe„䩌İ×A67.m«E¬ éG–3ž,oe=IY“&|.E‰H¿}Q‹k”{9ØÄ¿ìÀ?%¼]€=óv ìš·K`×¼Ýîy»vÍÛÕvÍÛ•†êßÂR£¢l¨B‡¼ö’`V«j):àR!=Cl{:·›ö*¯ ;žœ»ñ4¦5ôGÙFô7qmlcLè”+b^aÛ©Á˜ÀÿîD°h-h0vZ‹ûÃXˆð¿ŸŸ‡±ÿ'ìJ–$T•è/u XUË·qÅ TŒûõ„ÔLµúEô¢'´„$És¤m>oÒ!$á©Ä–Éü úÂ&-¼:ì™4)g¨ø-´ƒ}‘LãÔYwƾ%áö³E5Á^|¥ç@LžöB·Hþ¶{>0x~ÎáJ ž'M>•ºÆ°;á©zV ]ÈßLšvi¨ÖgX2ðåâ ;‹ònDÊÛ§eì—丸³pe` Àc7šP‹Ó-K«Ë´ zs Éeõº¾±OêÚ ÔÈnGÅ.`—è¡Òí<—’Ëœ7_X/Cm#Þ3$—y†Ù_G`‘À]÷A½´u:À×…U5ÿÅŽe¦Ò`JÌn³ÈÔel’¥˜'CA¬°¥–¸¦°'Np„ËÚ|^ÌêÇÙr„c!‚¡n<Ô}ÅÍ9Àð¡Î§\ÝK硇ˆé†R`¿aßZ×8Éï§£ °÷A®!EÝÚO†À>HPª’G íª“îý!•~‘³³"tnX®-¤"»\N#']²¢l…ž‹ZËY܃â@-ª;ÒŒvÝôy çºW‰JŽawÎV‰\ŸpJ‡xgFWU‹¶J îE%àÜàý/ÅBÛñÞ4Á|9ËxWw]ȧîƒOLåŽqߨó”Z+‚X›µi3auV_ƒM;í¦e¼M†87ØZÌ;ñVçÓ„a4ì™Ó1ŸM‘TöÀ';/ŧx¢TÇâÍ\®Žl}Z;h \µcæïØ»¶¬EßcX„íÜ7ŽøR‹¹Ã°¡z¶RÓÔnÝˈ—¦k'¦ÁÛ6À>Øž–Ucb8éÞŸbt1ZªjÒÔÝYÝ.>å$Ì4Îó(Hßö,IýG[»ÚúE׆àöxo­âYóq ï}ÒàÕ•®×µjùTk‚£KöêÇRösÞ鎶7"„÷â´¥‡å3:L»`&]š`™ F¬»ÓJ¾uÜ(a0lwJ„:}¥—|ÖMÛaÛpÝÅ|TºÌ0Œa˜/tL{>˜¢‘†l·âð¶3IQ–ö"´PÁ˜Š&†! •P{ß–ec´R Ûtb¨›]_š·œ< ë:…(‰‹Ìˆ¦ 8\›ê8ö?×Ù2©ù÷Ç4W­ƒ àÎ) ¢(‹²îk‰“‰XÅÉJ¨>Óv'Q¸[œú~æ¹€àïö:ÞàBpÂy•Œc…a$8ñE“©f.Sò4vac×—b1C‚aᮬâŽq/SQÁ1ø†L0­ÊY 4‹ {oŒ”$óUÚîu©™²Ã>±1žYÅ3£„ßö¾6(ZuÆÍéÚÛûâëñaË×ÝÞ$·¾Eê²ÊÇjÐÄ ÔE™ \º»œ®1)†Ý¿ÝåÀQ©_Ýå@þ©_ÝåÀiùv†Õ¯ÔU¡Câµ±‘2,UZ”Ú¨[>èPÁV«O†‡&tO†"Q†Ý÷\x€ÅS×å0i C$ßô vGªun­ Q3×5$³O›-4ÜIÜi€“ø‰äXÏoº©–†X!]e&òË:%OC,>fYǹ*8y‘†ñNæ<îã\äv–†q°,‘tèÞŸÎ<+¸}§¡Aw]3wƒ ŒXh f{¨žèóv%20¯‹•écwWDpOHá"ËŠŒØá+U_ßùs´^H·øçpÊIª¦êƒk*Û´%¨åPÕ±,‚P»Ó ð=ƒPûUo¤Ö{‘AØÒQH­w¯‰[i•ä\/°F¼¯é¯riÓtRÁ°û)–•©–ŒIu†Ôz/´Òã~Ûç/­t¨ÒeH÷B+½„$RĽÐJ·µõóU YŤ•R%܆Bg&×Mÿ`Hu–:)øÈ%=påŽ Š´µßNÂL¤º¦f!¶µ1PZöc(ÎgH;Õs7C>b¥Ž +õãvrÒðªºRWÁ49À0=kó4è–¤êf cû J4´sd¼,Bµ6AM¶XKè’Ã^_ùa{xÜ¿~b~{ÜÿàHàØw~yéw~°3¿@~A€ùŠð ìÌ/P„_`g~"ü‚;ó $á@÷žù’ð ØƒJî-ÐqÏZØãù7¡EbØwB‹Â°çå0ì„–c'‚$ ¶ â^S$ »_ì!Š{°¿)ÐÒèš"! E‚!ÑÙEÂl †Dg/h‹‚~{ýECßX¶ »i}¿i:`Ø…²ÎÄ»qÑ5Ìò³¥›gŒ¶¼c; v?e œ_¢í=ScØñ¬ä}ßåÞg9ûÛ²LÆÃØ799`XôUÎGbØë«œÆ°÷7„ÉgÅV馤Рzþ¯D³õ°b‡¾4Ÿ†Ý‰,Má âd⢠{œ a»jîãV„ÊÏ{^žå~Dª¨›,Íz;Yå½d/0l«BŒ2®ÔÃr§¤ÞÀ†S š4dPŽò¤ë¨®qÒ8ÚÙè1ìŽê»<ße;{M0åØa1ÏýF3öYZ÷\ý?ÙI/ÉbucU >Ïc±ñvÚ¼Ka%|2*vºIµhÛÖ±ƒ—'»æõi\çbÖ)†Eæ “VØ8›ÃÛzˆ¶3³Ÿºº—R`Ø›˜€{Ï´ÞYÜåä¥HúìÎÓ8YÆDÀ\ŠH¢…ƒ·„Ðy)ê¤gD˜[†U’Ã"¦xÍ—„dÇž¯Ã|¸',ŠI©n€€ûù>\êÂá³è‹Þ˜¢À°ûE¶ÁYØçût©LƒûQÏA4Àž_¢ÃØ™‰`&{~ÛÖÎDà;=iMšY%uF>MÙ’§] ",0$b ³×§»ô4¥y ™$b츃²«"–Å,1ŒØŸ]3{¢4K¦%1i?--l¨âVcØ7eÁ,A3$bzŽ18§°/Ê‚}ÕHÄt ²|-Iì Ùv;’:‹,èÆ-öÛª »ÓÏÙvo•Æ*¯¤ [ÒìD‹C^ôMbŠqNá¥cÕŠË]ðP-iP`ìy˜H” é|ö<«÷íìàªÚØQhØÁ…áåìàCë ª`OU[T!D%¡¥~Ñ&¶Ë\!!QɃ҈ÑyÀú†D%ÿK­éu[´Kk0ìyY`¶Øsy)#vÜ¡ÀÌV‹·ê¹»-·C  T†1Rx³Áœ€°=¼M îËÕ¸Î}Nk¯Jóy–“LI÷þ|xœáqÑa&å>Ÿ/«nʳ v¨A<è@BY;X±Èg`_agxÜ•Ùr!Ë._XD.·] —縀»>À®û¡’ßöUàRë,úSà®]Ytx [ƒ0´Ñ#”û°×AF+÷§ aJmàiÀ°o áVÒˆ„G/Â^i û¶r¨•a!ï#¹:îý¹V¹–!©ÐKrí€aßɵ†Éµ’kÙ.z&îäZ†¤B/é×ðÛ>ßT>0ýš!5ÎKúµÄ°ïôk…a_è×è× ©q^Ò¯I¾Ó¯ÉKÏôkIè×ö>ñø%áñ3,zÅã¯0ìÌã—„ÇÏèyè7?C gØÆãgÑÏ5_?Û%@)_?C —Ú aè£ÛßÚ ö]›À¾k3Øwmc_IÉa"Eÿ‡”,1ì;)YaØwR2=/§åNJ°3)YRr€E×9ä”`¯K‚þNJ°÷W‚>4áqMЗ„ Ï¢Ç5A_‚>CšŽ'‚¾Ùúl×t¼&èv¹ZŠÒm¼ö -}þMЯ0ì~õ"‚>‹ž×}EúlWˆ<%üA?ÀÎ}Eúæ=]qì c  ìš ­ªd1õù°(:X€ìlãlTàÄ¢ˆº+!¶q‘ƒ©0ìSÈ!ëÀõ( \0E¯S¦9ÀzYšÊá‘$©'«BÕY¬èuÌ4ûs›ƒMÃv ‹^¨6â7\TûÄjV$[­s„Œ/Ù¼uÈÎÙ‹˜ÃK«* {aEÒ4(’v¯8yÚÙúlnØU—PôíåDñËe}m¿5bÔ•$Ýûse¯SN“i`7¢ œ1T×[˜JRÕØg¼7M5y½½u ’àâg¹«ÖM©¤h ’‚ÖpáW‘º‰õ˜—šc»–$À#‘uÐß`œœ­ÎÔ½Î{ÈuDŸƒ¡eî¯]Te#Õi_k>D¨“|3S=B:{ýÊgv³¦Bå[ýÚCgîÁa©!_Êy+ÜxB‡õ˜ÛE¤³? 8ί:}q‡Ô‚òuûS£ukÂÙß ¦C¼T°S^H’†šÉLOóPØýÖjq„Ò÷ s: rÜŠ!_g3€i™`ë ñ¤‘ƒÔC–U|k)ÎäŸË ŸðzüYîññëñg¹p>^?Ë(ì‰Ë*}i]'…YÒ°ž$:CBÏÁŒYšè`ÚZ\M\ CðÞbH¢s+ÒôŸ#8d#‰Î­nfMNôr¶óRæÆHÑÿú´Þ©w,Pó½It”ÃûxhÒb«Ø$:0{HYÞ“&¼w}ñ@ ër>‹ABVg“èYîP{=ÖSÒËøÈ¯³[¨‘N¼Ô|¿ØyÜ8¬ÃP/qŠa÷³P‚ý”ó~« ±sË/I#·¡d‘$äa´l!¸\0ŒÑÊ[%Uy[–â3léío3&Á°Î ýö‰÷Y)IKßgbˆ{GõİÏßC§öx_V¡Ãô*“I>÷ ÁÝ6tIÏ—ÂNNp÷®/æ±: _ ©ÐæfíæfIpÏ“ª½é{‘ ìƒ/FUèéìÌ¥"|£æ«ÂAaW1T÷ú65í—7½¿_;ÆÆŽî”p´”?†È¥®‡q³mщÎÁ—ƒe‰LGôëhÄ·z»›¡Ø._jʦÞX¦! ‡v™²¡Ç0F¸rk¤!‡¥Û‰cئQeabýÆ´,çÔ”]‰a/\l±~‰ij£éÍÕ”!YÐMVa½Ý2 Å3 ûìŸæ n«2&ý†‚/¸ Ó]ÛÄ£=²Qðd=òÑNUòÚAâé ®Àrž¦<+ùHprgâFlîâÖ†.P pO¢ÐâËÚ…‹y¦ÏÃWƒ/µëœà"RƺÞåöY=ö`8lò’â²µon[2¶AÍÁ+Nú;ɪTvÕk ƒp$^ûÏå>:wÆ"óøggÖ„CZœñLÄ1¨MÜm/Ž ¸4±gÓ8MèóÖ¢›ß_t§óF …6¤ÿî´üxœ] xßïËTj»ÅúÞ©ãÆ˜¶¤8†M&Öñà2±»Žé{Ýxüþû»•ùKG»!g°Lmg°KضJ½ÿ¼…"ÃâKÀ@Ò¯6õ³öý—M}6õì};ªQeA±Ó‰ugPsõ¾diCáÝ€l˜h€¼ò¾ŸÊ؃±†Ê”v' ~/• ©³¾Æ°¾QZ[jš%í:+1ìIê‰Wÿ?©TkÈi¾òûpSd Óš‘ÃÍï›–3n5Ѫ糪ÔB^Š®ésH‰9ç:øåØû@![«lc;= ûÞå÷! (<Ì‘ïåŒ'7"î–àPr LÌ!íóxÖŒêã"‡à–'1ÙÜlãð8Ô3†ø)¯SnÆ‚¶÷Ññ.ÔAÄ™FK õûñ‡n} ºõöM·žW†të]r#ó¬›J Ãn ¾ÞG™Vµ\Âý~%À7*“±ÛT0ìCtæ×<äÔÈ]ïº÷ç¬Goré,œÁ]éÖg²Ì¸/ºõtë÷ EÛîÙÜx%3ý}ÏKy@Í=Á±K\•ñm²?OëÑ×Dp86!ôÄíVO‡uë®æ“]ëjŠûœq×&¯f‚»ÿ\êà›>àngüÿvmɲªJpJ½|Ðíî8SÀ· (¾‡P)»J´ÏþÛöBŠª¬ÌM¢M’Žà¼Ç\|¶Áï\‡À07×!h®ãüÎuô|Ã@›ƒSm«ãn¶Oxñ×µ’›}§U*5_0Ì•L(‡2Žy“§‘ Yqìÿc+—ô|!È 7ëc\·Ë ÙÆO踸íÜÙ,×Fà bSþ•nêB¯À ü\ÙÅGä™U³Êä 6éu™Š±O²¦Q|³'?Á¼-tǰÑ´ ë¦ ¥Ä0†Õ”J Œ™hÉHß¶7§MViO†ðAVd  ÕÆª¨ÇÃ"!쫷Ηy:óWX¬ûÔ«ÜsDå¦V íH¬ûƹì~B$Ö}),ÀÎÕM«ïË4ÇÃB×àZ´íÒõ ƒÅº­Áun;‰ú¬ª@>‹u[> ™ø¥Y 8?W6×Aÿ7ºêÀ¡»ùó¹ä0,WçgÌ!·öù\Œ×mŒkžÖÄñ €‹Xw|=M Y››–R2ưhi'‰ýrÊ3"±îSwqÿ7ÝÅL)ò·½/òŒe±Ãê8&#ýà~ú£±}åºN³• !"m÷Ûºœ’)Kj°á…×ûrZM…,äО­¦HûÛi5-O£²iïúŒCz—RZ̳H·Ñë^6h£¦Œr†ÙŠ^×Èõ ÕØ$W |¤¯}ãp]Ã*ÿêk_LºuŸeº…lÍW_Ûq¸æÕiV"}í¯ù®Ö/:Žát‹ÎR¶ãp]šë5}ÚÇ‘oÒBˆ%ÎàÓŠ^ßFPÚwßmÆTž"äfyã]Ÿ¿ú÷Ë⺥0Óål½¸ÈyÊhEôÖrðX*«¾†èïJpûÒ’d•@~0¢.•„–$ë ŒåÃí£™ãµ+baUo-ìõ¤Á~»XOûm ûÜÙoóNèš¼èÎ~»ÌÚ Œˆr¤“²ó’f@•ŒþnD¹2è½ìº®!8ï~ú³ô‚ó—áïó~6.÷†=7./öظ ]6‘÷³qYMöܸ,1ì¡qy9—#ïwã2Âsã2=7.Ó×ûܸLqÏËäg4.wÓ¸,Hãrä=4. Ú¸yÿѸLæâÝH™“~äÿ.à+ {.à“§ù }tæÂ‹:jUAtÏyœº99}Qx¯3°·±‰Tˆ"Ô°g?Ä£b²¹é”¤åÌ:iioø·=&ºHÕ@;¯YëmQ­•Ä0ï–›ÖÈRQXÊ|¡Ü4ÜÑü6jÝIx•$p±‰Þ×Üûw¨—)¢–§ nh »§%êu–äGƒ›ª¤É‡šÑ£Ï=ÿkãX%ùÙ@å(ž»YN}‹aþ]GNWÖtä Ås"ß¼ÿhæõa]®I¸åiˆ¡å)zðJ1/$k²ïœF›RµlȺ›”*NEQ0†4Ê lj^¯0Ì›;.]b™‡ºi쥋½^Î"ߟ֫¼iÑÓþœ…tÜUìÂnÔDr™F·0úeí_½2·>ixšw¿z ™ðrœ&‰aîêm‹®Mê)0 Ó³›Íæék¶:[¯°°oãÑ‹µ«ÓÆ=‘†…d…lkĬJ®••³0†öøÆ¼¸Í%ZØ8“½üK©·°ä°ù—¶;Ÿ½7e¼Ç¶fi1¤ðÞŸ*ö‰Ä0ïIž¾©1ìB¯Û¾…‚OýÒX…} š˜îõÖÞSöºE×Jš€]Z c_Ayën´–BóÈzÒÞ4—¼[–Yåöyàdô¾ö‹“±ÚŸ½Ø/NFVJ {âd¥Â07 ÞZeÒ °B.Çж®éÖ69˜çˆá–ZÅ+Él†ŽaãÊìa së1,pï5f§YRns…ìuÍ,€Ì暪F cÎ}p“ĬJi Jìõ¹4CÚœ÷ºÊ±š¹Íd±—ÃCj³E¶öæ?ümÙÜ`X€~Ôö°m%Uw°È/ÍiTj=ä< ØßO( ëíïuÕ×:¯\¥Èg[aH÷õÚz,U,ì+ê…¸ƒÖ¥Í1${«ì, mÕµ.ßÒ¤¼QëÊ­j Cš”7j]àãbaOòÜ |YHºÒÅÙµ†yD7qÎûMt“æ=Ø2 8ŒþÞnšyüO£¡æßxñ%†¹®öûê{ Oû~€ÎëåÓBaÞÃë‡Köç~€6ØÖe¼%1,pò‰‚äÙ_ô;Ÿ(0ì9Ÿ(1ì9Ÿ8`Øc>QÄvŸOTg>‘!¹Û|"ùÛžó‰d¤ÏùD2„ç|¢"¯÷õ´DàG wwK„ž–¨0¤pG–ˆd‰x¯K㜭«LcÏÍMŽîƒ1ðÄZVq'¬óþ®´¹Ýħ”I'b‚•äý9uõ=€[²Øl‚óLž¸š:…žt†a˜6g÷h³5z¶\= ô¹òèÖÓýX½iöÆQ£uÓѼŠû´°0ïª^uzófE·=†=íƒPÌgH}ï†ÚÌ5y7v([1/øuc×°]zÁýÝœ0èÆnaþ}×òºœC»–õÖµ¼`Ø7s2³•Dz«˜Sö“Šr¾7‘ 8xè vSÌ%<͉~ 5_™aè^Hät[`>µ½Ç2ÿõ“OÝH {äSSØ#ŸFê¿~ò©)ì‘OÍÉhƒÒN3½Œ9§#}£ãÙÚÅË‘o¶x6>ö¯A’Ùá™R7²Í: {,ÐÁþ†DÕî tpÌø÷:-pŽù÷: ûŠªÑ¸@ǰ¨š¥]ŠÜšOf¯l´í_îØ ,¿¹ð>·2 ‰ª*s6Ì’tâeki— ‰ªí’™î —y& ˆxÃ~UiÛž ‰ª‘ënW,f»Ì­ó½K!=J¸‰–³¹íž“åÑÝrÛX»¾áieªU#°®è«2›à&à£,ò? x¾ý¨”E%[Û‘Ê|’EþǨ»*Žyâ4çÁ!¡epmÊX—z¢Óå¿‹}5é&+´„½Ëÿf‘Ϻö¡eÝ.í¸Tƒ$¸Û.%Å—®€Õw\ Lb˜wæ®a[ª•ŒU5Æäiþ#LaXp׊×ï} »5va ÞpzæG •}Gú=‘na ȼ ôéÊ¢˜ò4ß©;ØýH·Œǰû‘:0æÊ´©¯`ÛݘþªæçwÃ~–ÏMŽŠ$$±-—ÄÝor×Ã|‡HÛxá:ÓÁ¤ˆå&hÛËÛú¡Þ뇆±Ûúa9UçGÈìâ¥~XÖä…|XtaÅË2)*IŸý*3^žvSfÔ—ç–;ʌ€sËŒ;î,3ÎwŠý¥ ß¿Å~æSJË‘ÛÖÒ˜e}/õ„aÞSÿ\%(ñ„«øZ TÅ·°à©Š.Í÷½GÐÖÆ¸ù—ÎæûÍ¢b¿…=ûéºÅþ²ÇÅ~ ‹î§á,öÃë}9ƯjáÃP%5¼¸Ï…{ôÓ‚Ë|ÊCœ {, ›AR¦æ;2¯b“y-@æ•ù®?¬¥3ÅRg)„ÝH,‘ÚÈÊíŽ$)Œ¹æJÂÕ  ûvQ¤‰%‹©®ªê1…uIu(@ü+»%]ÚæÅ»*±)¶Xg\§­\0ÌÇVG¶’ÜU¢Ç°À¡íæYÜËÚtâ¼ÂAÙ¯—º¨eœcà ƒ#D[ºº«8”|¤Cñ?ÄØœ–i5Q÷Ê1ìã¶=¥}Æ—d™0ÌíŽR}?r^AfÝhwÔÁdÛ®ƒ=o릨Á}uçsQ›‡õuÕ(:]ž‹+¸¨ãq¢Ïó n[&uÍ^T-Ågì®KŸH^‰N\xƒË7\_£¸ý–<\&èóÞßö Ì/½ì’BŸßkDMB±TûU‚bÁëY *)|×ÁËí‰FO¹Â0ÿIâɲgR鼓x‚„Kð¢¾ÏTâiîÈ߯$žKl°°÷“ÄSO†p2yn½„EZKÙ²À°ÓŸý뫳†÷ª\`Ôæø„Yå¼{åÕô!-Ì'· ½¥@Ôc2ÏÝ6ïF€qVPÃJËaw5ÊÌÀã¤Ê«ª'OCĬn¶æ$§æÔÿIñÓæÑ;ÕÎ:Æ¡1‡¦…×É!¾¨²\ó&†¬8‹˜Ö-d#Oóà…\…+í²ÔýÄ«²›`²˜ ;üÁrž6Óc˜‡Ï­λ ¸ßF„Ñ­ÛØÂ‹\C|0Gè NËÉ7=”tvIðYØÔ¨I,ëº`ýdöŸ×fîeF†ð> aa¯Q<Bv<Á°ÏÅïwçà÷&ÊC?¸©9/dá}Zž_ýÛQ–έ[ŽîºqFºX÷ÚÄÖÌoî#V‹ÄÂÇßF)>Ê\B ?x_èëxRKÂç×bëmȾåurB‡aþLm° Âû‘æ«¥³SßòÖsÇÂP®Í/¤S5·EÕØû),<7ÕègX8-†ÃBh"¹h(Ñ¥Òh£G%ó¡ ˆÎ/j™¨[•ÙpÆ{‚¬1÷ Maì®B‹Ã ¢/„¤§kµÁðå”él9}Zd×'+†y¤òsخ͢ÓD7áEõ­·²/+ë~É¿'ÃŒ¹;m{œXètü 1Î\êjÑ¡wÝ¢¿M_ÊÕˆaþ lºY+s;þ”hÖ±g ùU•:®fë/faŒD…ûéæb-†¡ —”Oªª¬V‘÷æ&Åþ¸D–E¶ž‹<¤–|6|+ו¯ãÜCM5¼8Anõ‹Ý‰=VkÀ à  nR¼1zæ ÂðZW;fAçš7r–†}°uã[ÆÝhîÐyƒa…•«5ùÛY0°¶Úb¨«iœ3‚ûC“oÛËŽÉçôyÞ¥´fÞISϲÐV-p¾ãåb¾Œu1W3ApßȤ8âw=ss>϶up¡ÓxOm\ÌË, Ž9ñĕԠ½¸÷·ÁО]Å2E’¦ Á}€2vš<¦¼ÏÌ‘9Ñ÷=QV€|ˆ´aï(+PKDÚ°w” !!mØ;ÊÊù£ï_”•²0챸 ô­ðóËvMŸßÿçš"±Áè°TKZž›utã'q¨wUI½&-†!Yù´À–ß—¥æSVû´Aôü\uÑõô:±h·tËpž^‘SWß“c6ÖMV— †1Òa^zñæ¦jþaoRcÙ™úæï/r‹c_áOËQÜ9ãqÓ,‹”!ëFk=ιšµœòz_TLr5ÖVðÁÊ©0öºûARß~Õ5 †yDMã`”¦M3L©B:¢¤û¹|’Õ é‡¯Ž(˜ A«ùël©­³C:¢ð µ3.ESŒùQFvëãj––MÚä0„?ç0,u–Rk ìœS„ó"“3¦JeC Ù]æ]Ï%"ÞÁú†‘×ÀÃÒ”D\/[òÉÊ3$M жÆ]š§*' “ðzƒßÉ óî%4¾É \ƒ}М”q15P³ð‰V(1­…Wm Hþ½Ïâ~#ëK >¾ÛÑ–[ýnÎa³ù÷/¤ª¸‡æ‹Oø Vž„dköîÎ4±¼ÂA­kžÃÅ ÉÖX2ÅñÝXjB³¡Â°€r.ާ-|˜­ì2C²5l4° ÃØýÐÔ÷rçiµyZ‡aîëÝ<=ôxf˜‹ó´¼œËÃ<¦vEÊãiùózèFAJ(û^~ØDl[\•ëyí Ìs`zS…áY8‚‚m²òùl£CJ(î²¹!°ûYȧy$0wŠ‚Ï3—ç,|7.ÊñÙ’Ùõ óÌÆøƒêç4MS Ã#Ýù÷E™¨%YAlĶ Ám#ýÿ~>Çö'¾¤qyN=rð";R‘s3Ø‘Šuâ´z)C¦šiÊB¹ŽTˆS”!!”ï¶y¨ÔR¥MJžv?ÒUÌVZƒa!”}²ìÝHˆíä='+úsù¿¸_ FêýîWöܯ¤0ì±_©'°S1ÇÜMûp˜ÎõÉHpECÑŸ?ê_HîöØÝ(¬¢ùñ?-¯~4®‡&&0ï©¥n¨Qø³¥Îú(üÙR ÷6¤Hp×RJaOÒíâœzö»“Ca˜÷äJ Y,5€·Á­}ráýù´Ï½+m/Ûª_N’]=À6óZóAÇFKe»  ŒÍO#†a©µc·ÜøyÑY©Mæ4à'‡2ªPYj¾­úø²Þ¯×•iÛùûI˜9°æ ï×¥Ä0ÕOC1Š„ÀpúX½[ÆW&£59±0R„ÞOçÕ\ê³TZµ rûƈlV5{*¦ÚÝòýú{,¦¶ßbêûõ÷\LmÎbêwýSGps.(^5æ‘ããb¥^Å5†yvZ©gS‰a¾cƒ³m¥ƒØ7êú¿3~UÃBǧesË™ÌfÞb{òžá…øOéjK°Ò²0ïö…”cUÖæ?ê·À‚ß…aÏa>¡Wîí#C5Tº”ð´ ³´“k•ˆdlÆé§íð«Ui潟 ó‰síñ£½4_a™`X€wZjº,ÝÚ –äú~…W²faËÝ j•NÆž\IæÈ%í‘£­¸ù®xF~ôC²5{?f5mïÍ-,"εû áºsa¹°ðz]­¢¸©uY,ö¢õ~9Ξâ…VÛa8Ÿ`¥:óbny|Î=£×6PÄ­•È‘*øÑ 2Ãe¼–EÌnaWs`¬Éj¾˜„˜GYÿ%ìܲ]‘0<¥˜¨y융N¼ à]Q×}ƒPZ¥f÷Kž¾¥¨Û_ FÑ÷jÊ0\0-twÁ^àÕ¬«™Ù*Œ]}+˜ìûuÄJŽðªç]UÕu±è‚MwØæëøƒuÍ?cb6_Æ>8üQ¸dŠI©è#œ}Ö_£k9õBw„£:Ç[Õ‚J¥fr€‘û\ä…ëömì…I²c(*²¬g¢œR†±é…ùNÃ%kÊ©ÎÆ^‘Ó-ýšõбkúµPý,ÔÈsŒ…´ë„#¥îDˤÄXD²`·Iû’å]¦0“öb…«æ¬âbÀØçš#Xצ£ï|Ëӯ‹m‡Î;Ö¥Œ»¦_W—“žZÊ=ïÒªËI´eO¸ksвR™â5k w—~iû)‡$^šzª2•¨‘ ËÑœ"ßÙX39ñeHwmNÁ*0)ÆŠpñ^°÷`^ÞÏcî§ Rê¸dÍ® (ÃDH[ãl°¬Ö`ñsàqMðòÇÑ”µÉêƒ9ÑãâчV³“È©N1ö¼`íš°rÍd‚±€–Î6þ­’|Í1†û`¹ËÉŒeË m8<¶g1¦°Lè¾mU.|ã ¡×å³u·¶“ío†±S²¼=ÛæL×SÙ“‰/- ÆÒ&)Ÿ\ë±Ï.ͼ+©–¨žŒZêR_-ž6ý"²JhÂ=.\^‹%ïÁzîypEæ¢ÈŽsÑrÂÝ&X£Øñ"öª;ñoí,ø\÷{Òмõ´²/ëÚÉÑ!†‚³ïífÖrµ×¥IL*–s¤ÀØûKEs‰ÇÉ¥xÂÖcÏ›Šæ¹X„®JŒ7ÊÄ7Ø >»× ”Ùu±÷Å)S°aM*á¿…¯(*X«÷' © ÒEbƒ6Ýb,¸+X³:_ôj/ê<Ý–‘¡gÙÔ1ö¾«Dc¶\ eÎú­ß ï¼ðlÖ‹®å CÑO“Ö3Æâ/užÇ#D¿•ƒÊýÕGtãßö3p3/º…¾‰P„”kœe~Tfr[™9`ìuW™iõÑ*òßÞw%—Ì–\l7æ¢Hæ(d;È›ÍuÄX´cÛµ¬Äc¢ï´&XŒ‡×ðEo'1vôÌ>¼†iÎk°¥§:?»È¹ÔN¥Õ å–ÒÁ¹\-ÉA,zœü#p’/Fó?mßo‡=Î+Îî곞õUïÖ’sÔ#ÖÎ 6–eÙa,¸ì["QLt‰ì1ö"~—[ )}4½Icþ–c?ÎÞä1\KçßÂ8¶cq¢KrbŸ°Ùìƒ]ƒ±‚Ü¢Zl1‡ _µà±ýìÔK—¤¬EE‡÷çfËðþæ¹Þh¶¡+g³>Ì«&ÿîñ¼ñ;óFL«¯}ŒÎÙ?϶: cOìPÞ:ãZ‡r7wûS<.îé=HM³OŠÎé¿%MbN¤~f>Ÿ_ÿÛ0d ,[$J79ć²ã¦Ï» A¾ùÄËtöíè<†•IœOn)§e­¬6ÏàÔ>s9×256w¡0ö¼»·WóöÃóõËժ̇ߢçë¾Cf£Ìn-sø‘¨VM1˜±ø@Ù*:´kÎÇ}^V¢ÝgÒ¾ 2‹Û†ÄФ¨Û@)4Ž)E]u%çcÁ¥kv+TË´dðß"êö‚¦k²dY%E^aì‰K[¶opØ(«Ö÷+ó>t¹ÃYUª:­ÙRcìE²«·:à$ç2›§cï‹—gëè-YÞ`,Ü;S{\ÑL«˜’\ÀOÜ×a°2™W‚ÅÈÞ{í3fÎ"ÐÖÙc,ä¼™*Vë[Ó„‘áýA«óÉmãœçŒrì\rînÖglæ°‡xîyW¬VöJ×äE ɨ µýå„9ŠRîu77Íá\JòþïNlœ&\x?‰—a¡\æC •W‹.‹¾/'úÿâËl·íǺé˜íÑ‘H~ó}Áèÿó7+Æž_2ü°ŸŸßŸ?§øIéÕ¥«oDð8cnG7˜*ûŠì[J¨ÂEÁÿI©{~ë¡ìS*¢àÚÑ̺z¬5Õ5û†°R¦AmÌîU'K1© nz2ºNòÛ<Âû¾_»—߆8@ðþU0[ÃÕÂû«yÁìýj!‘ä<+aC¸  Ù`4ø0•U‡±¯¢Ôû“Æ_¯ÖØP†ÆØWi˜äÁ©/öIø$¯“v5?˵Ó\Œ¾ßnôz\$®}i›’Lç^!BUÛG“ÏÍÝb°!Ï*Œ¤öjËB’3›GÐñØ!J•e JÅǺÊcXøÙ9ù*V­LN-¹)ÑvpÍOV³Ç¥z–‹HFéÖ¶I&Ë,9ÅâK/Ka69U³N`ìC\›vµÖï8œ½^¤9âÎhY¯!)Öžáù¥Ûä“¢ñòÑ+¸¨Ýú ñ^ËnëáE;0î4*M[9æ)Æö¶î üæj]/GX¹^õÜÛMnKäXt[ØTrŒ½Qš—iêW®¬"Þ¨Ý2«vÛÃÀ½¾‰âZ¬‡¨®ŠÇk´UΕ£ÿªŠ¿»)ƒáýëM»c_oêû¿yìV!‚­Ëª`Â…´Ôऩ®à-D´8€Š¥C2X„JÊ÷ÂWןP±•5æÛ)E *9ŒÁ-CÇóW|ÉtvXµaŒ`ž!ξd*ÓÃ,VŒ½n°vÃjŒuË ±–Œw6ä±ðËšbcÂ\éPV²|V“"7ï°Š)]µ»ÆzQ°ašò‘ ïÏIT]+gÅ0›p‹¯pîXÝv…h÷¼r+«› `¿ívðJ&²…sò>¦@¸>¯òò̽‰´ŠW/ZÕÐ ï`x}¾kXy-ûªa;ª¿Õ÷ª?¿Õ_0ö]C~ÀØw y‚½NI\E‘¬C’ 9˜¿ïÛ\/û¾†ù‚Q kW˜i^ÏÁjy?ˆµÇwƒuéeQrßèÒc/ªP°o[!+ÉûØVÿ³8cÚ “‚-¥öÝ=¢ÞÙèjé ‡é7¿ü‡Ä/‰Y¨b‹‘šôÞ}FêŠ ä¦Ÿ‹\%7ß¾,Spß¼ç >Ÿh¦š‰|šÉ]NÜ®s¶õR«‹›=Jî‰nž¯ SùœÓû¢jtjiyßCÌÎs/Z¾I0M“x*=÷¦u¶®®»$kׄp´œr{‘ aÎBð2ž4ܵÕÊm}즚f‚/'¸ôNôÉF“’}Õ*Œ=‘;Å4Ç4IJÕ  ¾d­ ˜ò~LïGmÔˆÄu¢÷û7q¨s‰píû]N¿å¼Ã“ ó©ú£ÀØóRýщ:±Ý5GŒ_«?öºt×”¤»¦ÇÞ·E"Õ^$â±ð¦H$CE"‹¾‰ä‹¿¦¯À[ˆ~O_!Ø÷ô…±àkv)¼Óø>»T’ìÒèÿž] 7ýüž]Ú` «ú5Lja‹ÑÑ—Z`ÿ¤J-s«8¤&œj] q×x#“}íKD"T ìÒÑ|J‡mé™4½ï‚…‹º•óý8òV¯ðqù¼8¹ÍbìÅÉ=ïÔ'¡ö‰¹Z66äj/øQkýr<³ñw˜!{-ð9"Ö ëÂr/ºµÀ("foÚ˜ãò¸GÄB临Y2ŸÙ%ùÕ>Ë@n5 ƒk,Æ]«9 ¯^´# _ßr8Ëk黤D¨È—TʵƒÜ£œ§"ß½*P®\͵l4Æ^¸ZÜ MÉRdóZ`ì}Ñ’QÆ„SY3sŒ…7X¿ZQfò߈í[¸NÙöô=3‚Å4qÁî‚Åj¾®¬)‡}.‰+ÓÚÔMÂK‚±˜ÝzÐ}ÏÇríÉøâXŒŸJf ËYtdHpr€×Idužˆ®ƒô Ï×àÙT°L¯%¼‰›ÞM®jq¨…}9bž­½=*Ö4í8·9ÆœF½ÝtX“ªXÌßóXx­¹Ý^X’qwÁöö°ûÙ6éubÎÓ7ãBÚtŽÁÚqÖ¶ŒÁq$ŒÈ1Óv6„7/ùÔ$;õ ^v¦ËG±×¥¥׳ÖÝ Éžááßw(к1¶MÛµš`GÅøößl¶ÄÄl¾*¤è…Ñ¤Ú òù’˜¢Û¿Õÿ¿-¬ûÞÀYÏ—eM1ö9tx|>eוEÉ’¥#ÃûC9›Þ2,Ö¾¡ãûØ„rðòÌœ™ýšCÄ9ŒP4щ¶Ã}ŸùÌ#$üÏ“yÕ [úª“„;:ZÙes{ÜZ L½ÞaÆmñ|Ë$(]ß(<üûža—!ÉZæd<"¬<´ÑY³ª‚ªOàbìwf›s¾²‚¼ÜÇW}º–¨ËT*¯Ètþ óÀ'ó¶¬ld"?‘³$‡çÈ'ó¼¿'Ê™[¢K‘ê„uIÕÐï'@â×v!ËÍûŠ43"á^´Žý4òŒåÜle„{c½ÍáÞÚJ¶º¥“þ… ©k93óYÔ\·dÖ?£gçŸk¡%—ø8øÜ™ªš˜˜ÎãüAÅEé6ÎsÉÊzš½,?{ kê‹SS>¥9oSò¹î,öçïaÀšc³àM‘“yÕ~`p\¸«D:Ìæ©h¡Y¥Éû "ìàvFñ2«néÁéÆ'sÍ+Ǭè̾b ) øIo½¨— cX¥ÎÙõJum·Ô®ö9ï@Îëꜭu Yláç,»ÿ®URîŸø¥ÞaJ­Æ^X™Ë¥Œ$zœ’¥á9xÇÖQŸ±ðZï“ñQ˜ó=y„=&œ€+ßü7Ý™rµCo7þtž7u!È#|Pƈk<4kVdxQJdáRž gOÑ6 ?§S¸ù¯Å8Š”pöÔ3ÿ5œs`–ÙÐ!÷ºÀ!‘ùÄ¥3É~XT¡Fÿÿ¢kOSçˆ3§A8¦F?ç9—ûÉ”±$áˉpGy(Ï3§Ú8°JÑ<†:ÊÛð¸;j%lØÐÑ‘€ô6f§ÍÊuègŒ…Ìy²²*‚Ù×ÿg¶³„âØ2i=¿d@bŒm®PƒÙ Eð6F?Gÿø„·Í8 ¬ö­6::Êÿµ—cpW³Å÷Õš'”{ÜqC¾TeN¸=½„çàçnt“2Ö0ÂÙ7±l[”ÍVétÐÈ ¸×‘Hå[¸°V·]§g2xÎ3妧ï~ÂÆ:©ÆVpÂ…HkG°½_…*I âÑ›6Ó¸´EóÛÒü¹m‹F°ïmÑö½-Ú‚±ïmÑö½-šÄØ÷¶h‹nZW¦ÙØ V‘³¼ØÑº’­+#$4tíIiÞ¾ÄX@²<¼oŠõªÙ!>«'YóºV5ÆžÄ\Û\ºú±ƒR_*Q]Åøvjæ c/{Ù¾T]0= ¾ß™ÇÞ—6|£,ªdb´ŧÕ×3kfb¨ëcѩɃ}R™5£^ ëç{¹DºÔé¬jޱØ|FÜDõ²_¼. ïÏ7YHE:Cw²:û ÷9­I>Sß¾­¢¬RÿRã’8ÀÁ%RWÆ® ylÿäνôÙÌò´JÁ0à¡«2LÇ%eUޱ×%U4]º1©ß2ÚcoÒ¾Á^ÍìX kFЇð¯LyÒ05g Æ"²^º}Ƙ|aäIcR!½ÅfÙœ§,ñÊ@CÎá0³$ iÉ8ùo(Ƙ8ŸDQ5SÉÌ$%÷@Π¶©§É´—…Æ(•ФýóN $¼Æ?È}ù×N¡¿%3¸~ãäüùïRµ9óÌ4Á àÞ8çÕ÷OKEÕ›k.¼Ôï[nÉdeyÎ5Éùç®—{Uoa6Mß” ¸¸œ¶™N·èŠŽó‘JµÕ~øXi%&AfžsþØoÖ†¸¶ç0ïÖØé 'ãòDŽß„í¤ê–jNâMö¡ŸÏeµDãê”B=¥,Ÿ0VJîå6«\'¯wí±×m¦µ9oîßŃj˜'>Údf½àæ4§0~›ð’`ÑýDnÍÓb,FQ¯-±t]eì„c:Ý…Ë´N¦ºLÈðþÜLw3‘Ù1ÝqˆOwÞq2ÝXdÛùšÜÁ.#‡\¤…è·#®”mk3ÖÕ‹–„{éÊ G€Tèúd>âú|þþ=¦{ÃW3ÝWߺ¸ð.gœwC’‘QvŸßz@¥NãÇñùl>©½¥±H_ÇãC zÛÉŒÕ?î»Åól€yu«{sê€DÄøÜÁÛýRÚtvÆJŒL©‚%æ°«1†n扶ïó6¯[Œ½i0ß.xÙÜ™e´I1’Î%[aÁ° B P0?O˜{"嫼…¸züÆ,OƘ\ÏÜa[ãŽr} ñXϽ/ÜPð‚÷'¯Ì‰+ÜLc.ºh„p]÷½‚Þ[í.æm‹PæyÝ—‹×©E£O(©šÁ ̆J|×öË?2n,† ã÷EJÄɦŒy'Õ rHŸò›q˜M³€Èxü&gòß”w;…FÆw“Ì\­”ÍqÓðª€åoZ´è¦»§€ÊèOóØW¥êÈÕPÓ“ÿv^ËÒâJ~¥Úå—s?'¢ç„pqž~dŠLLuÿ}¹¢Øù\ßrðS:åY‡_»w‘º‘úl…w]”–š¦VÀ•òÂ;…a­Ï·íä(»±Â;q¶P§^öE`?*#_&œu¶¹œL9¸y‘ç0HóØ|4v° ÊAÅTæ]”Æ} n˜à!Ø–¶O­š¦¸¨“–ÊvÌ´³fäªÖ2Îc*ÛH¸©’öÿ Ã…8 œ#,Ä©”m VØ›Xf¾mÄTvúWe .vÄæV¥‡'W•iã^&n¹³o(\‘_Ý×ëÿ$¿ºÅ˜M~MMGȯޙę€Åº#äWï‚ĹÍMGȯÞNâ<Ëvò«GIœtU¼SBâ<ÑU—úæŽÊ®éªé¨¹ìLW]ÈNWõ.HœîvºªGHœg™£«‚ì–q‹û0Øyúµq ²[Æ-VŽ®çùosŒ[p=¯È¯îo{]›º×É‘_=ÿuÍCµ2B~ÙùÕté ² j¨Ï²[òkÊd·äWÜ4óß×ä×ÔÄÝN~õ%ôx§„ü ²3ùµÍ4!¿‚ì}ù@vò+È>wôhlõþ ͱî~q='÷kÞEŽí‹;tڌȃòÛygVGU 8c9à?]Mójös9MeÏS íÉóØÄ8_¡øÏÈÂT•}À û5·ö^­­Æ[uÒ¾x<«ö÷Ž‹;IÕR`:"—Çß;.FmÔy´§qÍê“pçÃþVfÇú°¦²sèx«gÛ«†¸pðýsèx‚Á¥lr|¼ê‚®Ml8AI§§Ø1?‚N·ÂœÕ‡i§ÝEŽC Œ/AH§Gcj>|pâÁ{ÕݘÌFVè†=kè|«‘i •m¬—˜0š†pȼ @7í>A€¨'€œº™Éž·ÆI”=¯“3NŠÇóÚ8©™qRì¤Snœ¬˜qRì¤Ókã$»èÙ8Y1ã¤8’N÷~Ðt&k*¼(!þ—U¦Q°RÛ^5ìvvˆ 4Ñã0CØ!‚ÐD;da8vˆx|®Ù!‹lg‡ˆÇçšk’š Û™+‚ 6a®ŠØ¤Ì•å¢;sEÄæixÞ™+ »æš´e^`[ð~rMZMe×\“Ôþ~!â'×ÄuâGV]™âq>Ãçk§‚v%ÓMeÏ+ÙdešÉ^·^ø, ýïp E¼ {^tåÀ ²×å¯í|cñ÷wÍ7ÖŒo ²3ßX3¾1È^ãåƒìžo¬©ìÌ7ÖŒo 2†^[ÖRxÛ Ã«'8Dw®@áAk’²£²'G5.ƒ}¨ãº ök/žª¾üZ›ÄE›ãòwÜÝUÛêyžÃ¢´ c&#áÄjóÄh»ðÔ=1 û’ã,Ü ªãÀ6ûœÊ¼ýÐò¼µËl@¤€LÕtÑSÛ¦Z‚k d>‘Aè¡i¥]Ýñ;Ý·±$ø4•VqGyÅ~nÛÆ:šà³2—éÀtOê«…oIµMžÇøL^7~¾t’y‡~>ñ÷Û¨§˜ìÅJbÖm?’©KÜ'÷þQ9cÚLe•3S/Ëyèr*{‘ÒøÍº\tá4gTö¾,‰éMVk*ûpöòe6ÁØWi–PÙ~0ÁK4ÕͤdÊ.zW9N=•‰S:âR­OUS™Ïœ=›(êU9ºoä½Ïÿ³Õmç¢AÉ\ÏõÄt×Лaž°±~ÎЛµ&yÞÌ“a2’øåú»zK¤š©ìƈ¥bœ³ü Ü|*Íu˜ÉŠÊž§™c[Ù™c%•½øÉãZ ¨L_¾ÇóÃpÕжvÂ*+Øtg*K ü™@3Îõv"Ÿç§•ÕDr¨ì}s =—}îÖn)ÞÂ!“aí¥“e۷ɫſíä§O×þkŠÒ¹M›"§²çÉð½´­rl%<3sÐE]wI™Á‰­80ƒ0ÆÔÙ1 ç ›àódd×wiÙßây4%Bðh¶2k»¨¥²ƒ n3Ç13M Ç>‚¢îNX¤Ò­êî"g£Å¯÷ùdÕfÇ¥ñ„¿öú¹4†íAátk^8áä³9K£íô¬©ìMdPgœ7Y3—sLeŸs[Pš¬ Aö½[AO†Ê<Öœ·!:ÈuˆÊÎKã´£Kc—Æ­¦Kc|¼2â„Jj)ëÝûçÒ8¨ìy·æu·Ê“Ú BÇÞjJvÑ7'¶-¯Á.ð¸ïG*û\ßê¾4~ºñhÚ'-KçkÚj’¸×@æÝ’³ W}þ 9KSÙ=9 í_ÈYšÊîYWøk7ä,ÍXW‚¯8\Ø´Äí¯—xþ 9 [࿳àN_ß@¸Ó×ßO œ€ŠŸ@·ôâõ/=“Ýâáœìu Ü78uÙ9TC hGeÜÙ¼—“4È*à™ Â}ƒ~p;sÕ혪v*{^$0oÑÊxÑÏ]sy–ÝD&)…«Ô×ÁËÆÝ·V¡ÈÇÝvw5•=YpÃZ8–:íuޝž»s÷è‘:£1Èk*{ž2Ƽ*Tn{9*ÛGJç¤ïe›˜*c²7gÔcÕ]=÷ d >±ÅqŒ£Ç(d·p„,Ù‰ôY¡ vQï"AfÒE#€L\%#ØÖPº2ÿ"ð Ée–ºvJ2EºÚêæƒŽÎXÄ>ƒ¶b˜˜¿Ä±£«Œ ê¸Sâ%Ž{64>g“íIp²J0}ŽR± 4må- ÄûqF±lËÙ>×IŠÛûq$'m­Á袱ÿa÷~pP®ï— H“…´{ ýû‡Ø´’y2$P"'Þ| G G{©ë;B ýûË#OLa{›’ÊÞ'Y›ÞôÈÊ<¶«r&û^íISf*Ce,mK^WºI°m½Ÿ‡®+‚2“©ZF/úbT” bÀ<ǺžìáÞÇb¡(©¦ÍíâÒ½únŽfio‚’ðN]~¹âý¹O¶v„ïïµ}B(ó~û„˜ìy³DÅømñ?–¨éd˜ŒÛ#œ×þÒ˜LŠÊ^”8µŽFqÕI˜uøê[™lÚ¢ŒM>LÁ˜dh‰^WíÙ”ëtœ¨ìåœÄÍj;=dC„ÝêÛç›ȇ*ª0ËR tC}ö‹.5ªëâ(ŽìŒ0†Wÿ¹ ½´ø¾å„áp(™ª(…jAàP`+ˆ6€Ô±â ¤²Ží ÍÐ$5‰€ìu"-ØéO#eX³‹¾ñ`³9ÆÑ”ä»èǽÓxc˦ªh¤]¨dÄ¥ Êº±Í˜i¦²ýˆi㮲.ʵÖuKe‚É€v뺞˜Œù¶ŠÃ¡(ú ’1{¼½–2NÊÅaebY2MhÛ>LUw2/ˆ‡BÝ“±Ð–÷e{¤>-§¨bº}zþ'Òm§úÈQwˆtZJÎâ-g~Ÿ%’ŒÆêñQ÷=éì*$ìæ$æ×õhýœêg9ìƒúûä+Þæ™½*ŠbÒˆé|WCpÓHÕ4°Ïñ;~\è욥ŽøŠ:¶¾ÜêÞûÝ©J²÷ñ|ž‚Y#YI©¢œ_×Ñ®$ÖF±UyƯKÊ™ r7©e®Ú:dÏåÉÊ@×о· F(E«]ÛwÒJY§yËÞÀ"w kÞæ6‚®Œ@âËÇBÊ&­ñvßw2Û t=®H>o¶¹´¸¢õsšUÓÏ}@e/¶q»ysò±éÜyã‡ïÑv°º¸-“Ìí¯-cEDÝÐÄÒµ ¾[¼®–¶La˜•yÔ϶~ǽ1FéDfT&h­à:3©íkÚ awê³Ö¸Alk£¬c÷ÁŠÞ×V;޵j‡ëö‰d o¿i¦åpäù¼I¯ò©QìÛ¼PåX*¦{ŽcìÝÎFI~·èBú‡¶²Xõví×0Ýç è¯f5gý̾“¿/¡”m³ú`ld§”äŸçbY¢?RõyÑóûn£ ·ÝŠÊŽC•°—»õ*°Õ°µ ;æÚRÆìµm½ ÔL`ë“zž;öé=ÿˆ…ÃwZFìºÏ'Õáu—3ì(aºoÝËg5Ör¨¬#Ýû*’À¾B†LG€ÛrÒêLɉ_÷K|[YU¿x¤Œ‘ü÷¼k(²íH±­}®¡ú +±“ÿþ˜ô–X1%(¦ðƒß2ÙóDc…äíÛà8ykµ‘mÛÎ)•ízˆ§MÛÙ˜ëýÄçPŠ@Ù6œbcw >ÿ5Ì÷j»|0Ž® 2Ø=2Îzœ&y3LxÑïã~ 'ŒûßDZjf›‚äݰ|N¸þåY|°°[VÄÅ0v²MeOjàÛö`”iú¾š‘Øùƒ{ºãjôŠt § ”?xHwL´ø”à.Ùç¼3‘dzV¾úïß!(Ö‰}-›"6QCeÞ‰¯Ü„Ñ–QÊîT 6Ù•Þɾnê2˜Øú¸.'£1É&mëû<,'c8ÖFÛ^Ïcw„"²d·âšy®¥ýñ=%½¯ËN+›ó\bâ,ÈÞ§ìv–mh(¢Ùçô@ÒjŽìÌÐ ûîs X8ÏsµT(D|1ŒP°É0M™ìyb#¶agÊtÔ9•½Èsƒ*-½¶i÷Ü^§;Ý ãím;*»»Óm¿/ΩÛy44H¦ä)@CƒaJ^f uTƃ¦W @^Ù)S„½%!df–]\ÄTF‹¶1$ ìw$xªx º äIui×ÀCÉ|†õN0ĉ]@a©Ã÷s„«lï>BÙ QÎd_K«À/ÇÒN‡Ùßæí³’U‘ªYº¶°³.öR­ðgˆ2¬ò™QFÔÍEP¹>ä{ÜIØÎ©òPÙ—–¶­m!©ZŽaR™óÍ8nu¡Û¨(†š=A¢ ¶ùÊÜßÔàãå›6ëš|­ál‡hŒÒ.¥²'ÙØ´œF5•½N²Áv"£.`ßÉß½Ô‡ÒøÞÐj‚|A÷Rï¹Âk³—iÐØ9×De_š-²dqžGc Ìgÿï´àÚ¶õšÄTª²d¯cˆf‚­¾S1zÐý¿cÙs ƒ–‘¹²«&{‘&á-yTCWNTö&Q;0î&ml’Ìa ûìMfëi”žU EQÙ÷T¥¶´…xN2|¼ïã«ßzòZåu«jÈôÿÞ·M&Ùkþß¡˜mo Ë3žC*{ÓÊ­­~>œ« ’í@eþx×aFJ`Vö‰õ™ËŒ•îqêK¬Ï u¹r9s-딢^¬âS}b.ÞÆ8€Ös>uiTöb1iô° LÔ -•±ša)iºÒqØP5Ûö(t©–|*ûÒ¬²­öÐv¾‹4ÛÈÐȱv§,Çx½è‚—[2yF*ó")ðžãNÎE43©F7â¸$øÍÕÀn•ZX ÷mWÞMyËþº?ŽÃI·ªB)“D&LGT¶:Ë:èÂ"«][ýðšaç·_–ã…´³V¦#ý9–÷ÅÁ¨ìb›}_n´X7=bÕfÃÿveK–ªXô—2ϨýÞÑý ˆ‚óÆýúFaëÞz2»**¢Vàö¸–ÓøÇÛÆûGÂf“#¸û\A1¨dYÖªŒþ¾Ê÷w××ïãJ®žÙÇ_»Gq}1ðÚû,#¸ÃTëk¬šiî:ºn7ÌÞ7ïë§iàwÇ’Á‘êU2^9ÙË·­Ú[ß—ù¯[1EÖ—T÷…Mo™l˜?d)n4Ëàì1¼a|ÖšÌßí°LD›?- ËȺmsö¿k÷²ÌÅv2v³lÍÊoMpé¯ X¯?=ð•¿_gÁ„˜U0E35c$—I¿ß—ˆ[Ñ8•aMÁhe3äÃî`« ªÙ—öM/vYÀ’¹¢7‡±vôãýül®FŒòúM7L]×bØ ÝQ5È{ÓÆ1’\DFV{bQDF"ì,2¢Š(2â4†ýÖ¨4ì÷ÿßo1n”žØÀŒê‘™À°_;ÞíàÝG¥Ü´­‚ѾÏKŠÀ3kKSéíL’‹g×NÁÆA©]Šø?îÀÔœ«NÛí¤¹Ó4­žb¨5¦bÞ©Y²f‰!ù{"ÇøP7˜¢–#ùm¯ÏòHnˆ=–)â6¸êÞXǰÛoºG1?œ"nƒOºGµÆ°Ç§R”zÚuRÄm@ttÐ=böÂ^ævÇ®í6Zƒ QЏ A£­³Ú”þÄKçà6ˆJv›Ø8v&¶s§·å A!ê+,Dÿó“źb-©(\¦ ‡a÷MTnûd²[êzÏ£°pºa —vX8X:ˆ Šƒ„‹ÛÒF ø”ð˜Ó9v'¤B›0¯ãb/ë8¢O|l®ënBDðµÕA}Õ<Ÿà¼½Hoß&¸îßY×97ÑnB,WX›SÖv—[æ·jç~bsÓaØÂ €ñ¦Å0Tð•óÖ $«¦Øa8'ƒF9_ŒFù£b!\1ºrÁŸ¾½¯bÛ—eºI™.¯1,¡°`UŸcØAQ9ØÞÚÁ;it´h–B¯ù–a±¬7Þd#‡´;öžôW•Š<6Šâ(¹Ã˜iøž÷íÐ=FŒ‰«uÍf!3^•ø~\pvÃ1NqOÀ‹1co+ùs¤&“Ä vܶŸŠF²ÌÄRaÀ!3(’hw¥õ†îÐÓyA$úÁýV\s]ˆe‘—âŒÐ¹YY£[îÈ{ÜP§{ü}v©,ËJéîûÂR?1¦XUÇ–AÀÝ0x¨R´·¬JEöÁíjãx;×ûLÁ–OΚ¢[į(Kîêú8¡ƒ[b­Èg^aØÄ_Š­HËÆöPÈ-9õ€ÅÚ˧l’6–¹DØw[† O˘äB“ßöÂ-Ê[¯˜0þž6‚ #ŒaÛ›®ºl2! JŸ‡°ï_ -Ű(S]eÍX“éER:Q Îr9©¬mÉÄJT¼>óZÍBdG‹¶µÏåb÷mœ^¢Ýã‘[o—â¼`-Å=Hj|cï2|mŽØ äô9±XUdÙÂòAvô}_$î¾m”UW¤RоïûÒ*¢261Sd§„Ï‘¶”¬ãÕJ‘=p|Ž,¨š«BԪʀ×÷ñ‘;ʣħ˜•°¢’E€û>´[c oxæ·Œ&ówC¯¡²yÅÉÊ?ž¼ïí~if–UBMŠlùà%þàN›ŽµšÍBº÷„ceM*ëæJ‚{በ¸ë:ïžæ3ÙÎ7RW´E3ò¡t,ûu€—xdÂsóŽqæG&¸ôÒJþúàxlÕY.µÎ£ iŠy}09†(½U™‰Hîa$7¬ÚTƒŸiŽaw,÷˜Êɬ´‚<ôqaÖj$—ZëE„á‹*ÚÙõ’Y]APô~P,ÿ+P,CeS?í|J­ŽÇÌšADª±ôÄ`‰è¢—~{º¥&0¢jê~ëÚÏÉ…²"ìÊ´Žæüh †=¥e :ÊYãí7òÐ'Ž9‡’¡~*±y÷#Að}h×9Éc=a„½q1^xSU-†%WXÁ̲0HäÝ©&ï.¸Ó÷}&ýÑ­Éô~]›Ê³¢Ð“!¸o¢ñ»EOgV-ãÆwºµ×s5g½VàŒÝ¿O„0Åk]rÓè)~®ˆrê›Y?ÔPa€(§þÁoÛõlîóBWF»û¶zG¡XÑúÉÁ°ÇÅÒZÚ…-Uëc"ìy] ÖþdŠ4Ëöú´®íº®öþ´®Ùº®ä¡ÉçõZtI&$½ÀlÉd16¶#ÓûuQÚ®kÛñÙöd8$ÆØT¹¶)AÑ p¿.ïîþ©b·_+v÷Iùjµ§Í¨àç=þ† F8o¶Hqëý¬Rk-0ì~ÚLª˜½Ë³¦$ÉC¿ÂÈCŸûq¸÷ÓØÞ²¶²öºÀšO°7t:ï4ÆÛºZˆ}k>Ž:”O0òÛRÐc_kdBéV­•)Ø@`Q:v˰Ĉ3Ÿ+ïî:ÈÒb:´‘ Ÿé~†ìý¬Ü¤bDOMn®,8Ÿ˜íØl¶¬ÙT/Òî·Ò“d¦bðg UVI+K {¢žîèM,"SËl†½Õ”G.15u.—ä¡ï„|¹¨QµmQ P˜-ŠÌdý¸OÈë,ß™…š·an€’ÝC©:¿Ö;ÝÄ1ŒÈEÉXÑT8Å!®zô U®_[l»Ýν¿P}Ô™:!oÀ<¼#aéÿ†gÒˆÂ-9«& K>”—jd¼ƒÑÞ'Zp%yÝûU­†ÝˆÛ´m‘õœž T[aRºTd«åتÂJa\Ù»m˲êGflÙ`Ø\2Ú-yn¤Ýßô}·øË”tÜ7}c¯dÝoJäZLÙî ¤t;±”ó~-6Á°””áßelt/ŠœLï¡ *öíÒr:òª‡à],Ý*Ô¢VKÙ‚-SÁ;.cå¿TÞ2þ(!¸;© Ø¢SŒñÅvÖÜã¢Öz7m™²ª"¸ç¥7¶!½±é…4÷ÆÐ›"Ò<Ò«Iol„]{c5é°Ç¥ßY“¶èôDÁ‡`¸-:Â~o‹0ì—¶èÚ¢#ì·¶èêïéŸmÑýÞM~ÛïmÑîmÑ i‹Ž°ôcpUïQéÇןä`Ž>h]Öæ.öNw¶ìÑã\=/8ÿÙL¥™À'Dœ„k"—G‡6¬®ò*Ð'áåaó£°ÇgXßSØ“¬Êk6ö™²ÇíÊÃ`ý8âÈÛ5[¹ÁÌÒT­sv¿xµÂé\w=\pJ°XÝV«pMiÈá=ŽìQ ¥ucfp¥-0ìE©äB–.œ‹<“éã~yÓðPÿ¦¥æà!"ăq.þ¶™ç‘c&EDˆ{\&d”Î>Pöhk‹×ƒpfžKÇÈo{BR“¼©R¥Y0ìuáÉ)ü]•b‰þÊξˆ}=›ÕÄùè·'†Ý®$ÞÌñÆol¦‹°û'—`ÈfÛfv=£W mˆ€>NôVÍ3ÙpÙÅzþ1CîÑÃмé­!ÊÃNnþÆv.[½Ìù€aˆ°]† 4žçùz©J {\zyüoãk…uaäÆßö[Î¥?N¦šü6D •dzwÌÙJÔvÜøYlnR­]ê±o†%TsµYsf+?5 ÃF(™…„Äš?°#™Þ¯‹ƒÌ ã¦4y<‘ò3®ÉàÞmä9·üñDÉ’X Šº•êr¶[çYù9ߣŸu•%Åí [Æej±dò¾÷Ú½E0ÿ ±ÓÊ~¿.{eLçã* ªrœë©›–ý{}øÂVX¶ZÞÊ¢Èÿ$°—Òû3eQïÔìªJwFÒÓ;xOÚûbÿ¬“SS]4Hs¶ªfg9¼ê' =ô!Öv#9†Ì×Ή(èš>ΆFÌ ¹ê êþHO}K±¬ÍÊŒ)E¯˜jôÓ‡8cX gp(´éÆQÖ†_X0ã•âÞ·áÊÕ†% šÎx8÷×ÒúB¹e?\SÒ«±ÇŒ Öêjž òÐhSÿ qoÔ÷s—Ü7ªfŠã-ƒ?‰'A—ëöé‹ñ‘¶ÇÇÃf'–Û5Ap‡R/¼‡­ü¢*Kf‰H‹<ðøFó¦æt¼×§²§em±ˆ×+¢‡Î~`ÝÝ踃VÙôyó‚âÁÚä4Uà>¿ ‡ ߓۮuª‰DFôæ·I©ZÑNJOöø¥fCâyû«¦‡¢–'-¸É ÔÓ¬YRÝDªÌQVnõL/X;ßýÿàš@”•¨ÚÆ÷˜À‰²r«}Ý>W¹r:L˜Ñ³x­ûŠçvƒx‡¯ãªÉÇöðs¿^¼QÛ*ç–R¶öøðÐÁŸ…ÀŽŸ"½ŸÐ¯•Ûrà¢É ûM£`€³õÿ±íi »á¬fÈRùEg)–\Ì’m¿Y®êi‘E†a7¥–¡=(csÑ@þö™œ%£—aìÌò®3vbGÜê'ÛÖ´¼(0ìyé¹µläEÝñÃ^¸js{ÓŽe}ërN^á}dmbi±hu-*Ù– ìc¤#6þT23”==÷¤1T¼ó¥Ë[:7çdz¿.¾ðVbÿ´’q(æZÐ9p-¤ˆÎð“ç¾GÒ³î_7ÌÍ< ¸¼^_ŸÏ¤v-2%$‹^_Ÿ™ŠQy{ÓB¼íõuT‘ñ|™*›Ha(M{rã/L ;˜ac.ÂZo.Cêõu–FVäbY·-$½__$÷Ÿa{Ö5l‰âa–\®¦bM9–u†aé•.¢, ¡Aê¦÷ëÂáOÞ9Î÷}a‚èÄØ6®‡Ã+ân¿…"ÝBz"Œ<5û‚XzúºpMò-^5½7¬¡JøàGü|Õ0 »]O{¢xš"ÂO<ú®@~@UzײµJjÿ×óÄÊ Ù‹XUü:+Äص.‚;l?YþùùÏqqm´}†ÁAÏö§þ™) ˆ ä2Ü ÷×¶E©ëÌ“…<âÛª !¸”ƒl$¢ò ñøó×e˼ßj0ì†"èÌvÊ© ÖôMKgy¨‰ ãÅ6ËûDSÕqÍZK¼È`Tg[,˜¸u`Ãe½áœÆ¼lÝ¢ãôüa± #^Ñ“EÕjưÛU»Ñ»+Fƒvcú~^@BÈs2º¯öy{þ)ñé¤÷Iç&‹­êZû¯aYd<»Þ¯«ÔI`®rηÿ¶×I$º?~z ]ÛfÆ0Fœ«>M†ŽöÀ›cÓôl öª¦·7•e«u”ň°7ꕱ[©Y7Ö†%W^IÑ/k¤‚aØ–’ŽÂa±ü‡ 3¶ª’¯# õcß-¡üE—U“鬪«èä'·³—šÇXñJGfÁÎO®e&[È`MùÏ}Ì *3‰º|á¸d½LEŠ˜q QYøaf¥÷.ãÝ–œy‰ãŒLÒûn½Ÿ »]”.úaMY@ãPrÿàƒlþQ?÷†CRr?(¿ö¨BУ*z6@0¡¼Ä[ÞzKÖÌLv«þ†½NŽvèÐXúÝ™ÅÄkX*´"R¡vå‰]éDÌ´Û+ÉãL'‚EËrß¾”ZgϪ/K3-õ ®Eò¸†¨6/I;AïSò<µ!G^%½Œ½Ê­vÃ!*øÙÄbü¬ £>Ãö×{²Ê6ûh/J¡ ŒjùPËlØ«й=BjXÓåYí4Éë<‰!@Í Ur2ê‹K_µe[I¶o¤×©RȜՋå5íuø"lòaÊ«i -$9Ê b& *ô†‰ÌÙè’%ïk‹tè[ðΛ?‚G #loÐ'›{ûÂɹõ"òÄÖ2鬕ö¸5—¥cδ=±·yGÝlÛ™q¨ÌJhëß*Bü¿nvlï1ìR´áË›.뜃F5Ä’wœ!ë‰_2Vzã,ðuhŸ§cóìß·´dz¿ˆ1:_Õ¤Fµ(‚û¾° éÅi+¥¥ãÝp¤(dÞõ,ýþ…Îá䍨9¶¹«ËÚ_½ª¤Ï=Yq[ו÷ÉÊÎYùÆœ!Ÿhk;G™ôĨÈc½‡?r”©6Å IÏ…¯ÀÐ Zæ$àÓS—gK FÆ¿.<ôÌŽ{xŠq™šÚí"Ôû~0POƒ(ð p‹Ÿñ¹/WbäxÒ¥'¯1òUb`yÍY¯0Œ*nŽôX0¡µ\0ìŽaÛÚ÷5³¢íq¹½øœÍL Ç0l¯Ý`ß,nU‰f  ×î†i«8›T3AUfú$Ê2‹_–¿ät9”=ǰäÂ|Z²¬h5‡æ¼ô¹ÇÏþkªt§[ÿ‡LïׇehJ=ËðúmúF®YI »¡pr0p²Ì¬µÊ½À°;…­7º’Íþ ưOËÀ浉<ôy©\h´h´¿Ñ[ {aضËWd¥í ¦”¾è2läUÛ¢z3Ó¿©Â°„f¸Ö¸£cïGš’ÕÚîs–5mí/w2½_˜Ì$ÌÜÈ”öºAÌø<ÂŽˆ±ðCsoÊMÓ¿ëš †ÝhÓÓ’á«LÕ´ý¶Û¢"¼H=zë\ìûŒÛVkêëÊ[û3°Ûé°M“Œõ²k²Ãn—O°X?Á~NÀî—,¸î{g&²¹{\Õä¬õL€aŽâhP÷n©Lt¶—1ðDšºªf·t"Âî´àY„à¼35bØís´(Ï…#Àî¿D‹…=~‰õš<ô‰Xqbû±˜œòÐÇîa«àæfóÉ•b‡‡ =Àn¤{2èÏn„*)€Ý¯ìU~4){í0ìqM½iúfj' {b›Xè5²œ±‘¼Â‹jPnâoç¡—=†i¼ÐG¶)Ååÿ#ìÜ’eåq,<¥I’—ÇÀ‰¨‚ÁØ`ƒ¹c¢Fß[ A’]ÿ©·/`'#ÉKK*ÃØ›ÞrÁÜIçY0Œ}NÖÝPvMeZC./n‹eaš–S1“ѶHŸëqkŒm:I~j‹„š—}߬¡Üy·ÂÅÀ²!÷õ†j_ú0“žBÑ‹‰ë„¿u¢—.>ªLü=23–µj-Æî‡1…ËѺFªl{Ôi ºv’*ß. ÝhöíK˜ÅîØãéî9Yt!ð^?­U¶5óuм֕¤‘.è¶•OóŸüPU þä-[6’ÈIØ¡ ¼­UÞ7i G{ŸJm~gÂ] p-0†Æ „¨Ð½†¥¬*Á1¶Y«¬™¾]h岆Žöù¢]ªYý¤t_ùâþ‡]Úé«.„àóXŒ»ŸZXÅTiK…1ä$U¯¡›e´ €íNb|÷ONURäoCBÊàF´6ˆ°0p0\7ð›+]—͘——ö: úv6åÔtc{ݬ—̨†ÉösбÏÉ1«)fÉš9£—÷sëû¼lÍ­hÉçC‹­(Ý%Q¬+º‰pø«ä/ݲ‡ÁÛV„'óv;:æ¬ÑËÜg…åy†±;Ƽ=Ø‚¹@(ÇXtzΧʼncf»€¡ê®Ÿ2’7iɦ©nÆâÓJ(ëª’î¿ cOªØ_]éôâø¨ÉI_‡A¬k§‘:MŒ½ñ”`/UÍ’ÎÚÒrŒ}pîîǺêΦ]§Èuó·Õ®ï*‚»¦®›1ñNwÛ\ç¡ÔZËÚ]Ö‘¿¹ÓgÁQ3i»4éæn&Ür'þ- ¾eâK&¾4É4ø$nãÜ|àbP&i(Bò®ëØþRUçÊI6ˆA ½pkýš ÍËŠY1Ê­[#ÿü¼Ž"-o›&%Êís’gMµœm"­%Ïñß^¼×Ù­uÍ,”ÅÛ¦ÛÛmê!«gN΋8Bq†Éi’RNá¢ÝÑ3p.Òqdá–XÝ]æÿ {î_]VO“ ×åŸÔ~ùØ…{ÅÃçÿv”`±ÑòaOå¼­*´¥a‹ééo1½¢1ýíÿ‰é5Æ.cz£0vÓ[rÒ˜tù}xYé´‚€øvðÊR¿qç¾ØÉÌŒh1¶ —²Ð« kÒMa+`Ñ®­c,gÓˆ±ÇŽ…ïúªW4Åb´]úȵœŠ\'!ô¿Åã~l¥½ø¹bì~qÒlª0†—l‚ת®K>ÁÂC+%(æ¨Ìtž`ì~r½‚ë=<æ¯C(ìì‡`g¯0v?y·«Å»]Tù€±è«Vµ*çíAzŸ4kkGa[éÉ6‚…ÈïvTßx#™ÜEL.…PªÅšê ™$͘ Æ"Œ­/à‚•<›gŒ=ð6Õºl¶%3MW±~m®™ê›< wáþwÒìÅM½ Iói1v! +ƒÁ´Ãn§zJx³F«›Âôûí•aÂàâȦm …±èªˆ3‡7ë~ÿ­D#Øw×þªÊ¡PrNÿ]¦Üå}‡±} \ 6xFeVñ °ÇY¿à§læš•mX|T¢ùpS3“Y]BÄ|ãÃFšêBÈÝ5Þ0XÍsÝÏ-ë1ö8•‹´¨{Þöᕹ?¿—÷]Äßmå}‡½~èj v¿ nKø¥ï_³Ãm¾2÷ÏÁ ²G‘šÆ]¸¼Ñß1É ZžÒ%¬e[ôwX‘û¼š6aŒ¯|²ïþçÂf1¶©HèxÊdÒ'°öFXEòÏ—]Ö¥«ÎXSYN°'È»ÌÊ2š»oj¥KŒ½¾yÙÏŸ!$ö„Ä‚•XÛÑYŸ¦eKNú¡^ö¾0§l1rÒPB§bžf–cÍèì̹–IÔÜŒmQn?õF(éݲ9Á¢“4(«¹Ím_e£F”nC¦©£&¡­všØÈf¨¸ ¸[¾"Ts–UIÙcì…4?ÛQ£R]‰1|@ĬÖyANúù" âŠ%YÕËûGÄkiܺ$³,·ç÷TXÆò=×M2Žchô,£m9/êcÑYmY2'EÇ0öøªæEp-,Þ_Áž{cÙbß(:ùÙH/jjí¢)ƒ1]b¨~HÊÚ7{À¢+S) ·áñÓTªÒ»“Ðl¹ †I­*6´‹È¦~¼§JÔ&€=®Ü¢¸ÂX¼Â ¹™‘’×½„jÛn²9•ø°±R2«L1cìõ¥_#­³9KàAŠO’ª5v°iÅê´,Œj­ë;Óˆd…ÀXDµ,imkÚBÔc±ÝekgÅ’]fM£ú,ÁØ®I³ÝIó©wou‹±çöje¡þìrÕ:ËUÒaìõ¥—¤çY¥òcï/½$.Hy’aìó¥—dÒzl·e5¦½p›”²QYÓ÷­ä„C“«CÀÍu=ðv‚’aS ´âÒ?©8¯$á"êQ·ø_ô¬gŠäÚa‰Ü/_îצiÓ@ÀÅÔ_âymRôüyµéGÏŸ»ë3ܲ×Éb}q”³˜ oÄhø‰TÞaÁ„ph‡±;š€6QzÕ%|6ðîû‚É@ÞÎK8=‡+‡ì(ÆÂ¿€Ý~lb– "ˆÇý2è®QÐý¸_ÝÕtc/Ø÷%2S(ã¾…£+0Þ—™mûcwlõ°mÒÆXSÀKýˆˆÔsÓÔ¥©n¬ ¾X€í»,à‰ç¾3É\1X¾uƒ‚[7ÉÒ õìyÂÆÆ¤¬CN‡a%a­Ö&—c†±]•°nÕ/k)ÚV Í1ö¹~ž·Çã¸õt’ãl³I¨°à<Ž:ÉÐ?¬:©¤˜Jƒ±û›—å?È)‹¾É)S2¨´ïýþÓÿà ÕÔ}&5”(Žýþ^<(BkÊdÃjóxþjMѰiþxýhé©4ä‚÷¯\°…HÿÐìršÎ¢œæñ»n;é¡Ù{éÐôÖ"I_Um©øïèŸC°±ÆØý¤Eä¶ì–Ô`ÆXtšk悽trK‡± 3Öë6‹RñqRÃæ ð©I­ 2)†º•ƒ …Û‰IÞtÆ^_LÌ‘¸ßa·â~Äý€]‹û Æ®Åýc×â~‹±kq?9ÚYܯ°¸°³¸_aq?`_ÄýÙ2(–% cgq¿Ââþíòþ]¶°À#rÿÝÂb1vÝ¢1vÝ¢0vÝÂBŽvÝÂBþ¶s ‹Á-,€[X naìÜ¢p `d$ç6»È¼; /ýR&àT°`E¹}âcãA¨%¶¬m¡`Å£³U¿ŸîYóAV¦ÃØ^ ça®©²®™6L¼Ô ¿4LÐlk™™DgCVAܧ‚ëhˆyì{œ¶‡ýFc¹â¹0v?aëØŠÞÈcÞEÎaЄí¶O`ŒD0€-\æò2œ rÒ tÖ'dévPªIöDc«|½nnáB®c/:ëQ¼@gn“ΆQ?€Gýä2ŒúÙ¾—/R¸a°.¹¼bèÙÐÃOx“mAæÃ ·fr­Ò®5Æî[ž&Ã¥[Z‡‘-:áæyn ÷AÇØcòð$©QŒÃPócñ¥ÆŽöù­12;kŒ ÕÅŸ#³iŒâä²Ú«-×mRS?÷¢Ÿ|䎰b¾—zùˆ¸Ï½›c÷CV¶u’ë¶i;®e^$£vév“ì¾hW÷u^ˆÆb,Þ>š÷Sãž9`ìIÉüDÀ™õuY“Ÿð¶¶"Œú›µM¹ oÒ5¾jÚ¤`By‹±iðo–4l |öü; ½Nªtt© ònçöÀ%Þs‘A­ GúC €œÜɽ‘0h ÏŲ19qF~Æí,ºË¹Ô§sú;¶Vé%{ç+Çm^XÏpàžd€§ŸB—ºèÖ úؽNSÙ:ÛÚ¤IX«‘ËÃBÂK¯Tɱ=ƒÎmU¡ÂŒ<À"2;r-‹§9Ë[%ˆ'2›fI]¬Sr´ø„¹eºe,k Æö¡!luG[¬ôàOÀ^ØcË—”—þÐaÊÈ/}ÓÞ®% ®Ý_'x'0ö9|”–w‚©<'rRÒæ*·¤§ç“$^úÁw¹O嘸³ƒ{Ý.J®© #ºŒO=3P}ÞOJ¾u¡(³e&XÒlËñ_4JÑ(Ö·ª‡ Ç'Lϲ-oYÆ¡Ê`ìA%zk(·Maj‹1Ò$zJp–îúó~©ä«Z[Í{b¡EÉ7ñ.í0öÆ6ÙÞ^^Öu—M2DtÏèzX{ ÃÚ»o°ê: '} |Ð`••ïûE<åø$”q_cSW#ƶb×ÕU…ªÚ²ÃØ^ •”2B #&†1d´C¦e;M ~}ÆÄe‰AeÜȶÔ¶¯óŒN>2¬©L!!yîæ§ºÌl5lÖ!G–m[×¥'‰˜ay}ï—6˾Ž;©À2·Å˜{S Æ"‚­×­`¥‹×Ëc¢¶_"[–¨‚wƈ®q½YniHO„ÆØ“ –÷Tƒ–Ÿ0ö:õ MUÕ¤ÕÅîçÞæJ¼\×f†)ÉCÆú|Óö`ø¥k—B™§ cÈ^’ £ ݵm‹±è‹w@%X!9™ è§˜¼0­Æâ“Ű‹lå\t&ÇØóRƒ—÷ó[ƒd0vÖ ªAz~®e-UµU‘gÏ×R¦ÅØýàp'ûë°ö¾nßíêªbEÞ›ðy] á^è*P/Út´íæ²^tuUL5Æ¢ÓС¼tŸˆ‰ Æ6! _C›eÁ_„ñä¤16z€vižé6}‘Зšƒðëñs„)â¿yöøÊÝ •Èkޱ˦9Ztåö¨Ãó†<{ˆÑÃú„Œ9Ôv_¯/dk,j»¢(`+tóÅñÍZ›ë}«d^uÅvyCn!™r·%S/Ú%³$9ô›1v'ó$¼‰¶š@ˆòÚßú~訯S¹Åi5ÃúözÓdjÏ’8Î’^G9ÐfXÐ×ý, r@f˜úRqnœeeÁ1}I:œþ 3šþ s1¥eJþ¶U ýçcže1 Ù%2ã!éOIÓdÆsJ†=ýÙÍxhöSÒì™ñl3BüÍš*¥'$D«`q²•¼®EoÃfð¾nr…©DníÒ í|íæ¬ß’š©¥\Dš¼Ùo" —ˆ„7™ÁnÛ*,Ø}ÿýì‚Jx7 ¢‚ݼ#‚ÝÝ,ˆjg[E»ïƒÌë Äåû誮:×*-¶_zû.Øõ'Ý»ïÛá'€®×$ã°L#Ûž£«žBUªwô%œòCQm• øô¾gíìò05í’ö¶¬Æî© ß-÷…–*ôûÑ^"¹Ô(+1 ¶’a ÂrÀú c¨Œ¦&c$“U:2Œ9¬¿bV*…N‚wL[Ž‚ÝÊRÑhFÕ×ä¤ñ'ùäœwŠ©6ƒ*ðÕ 7l•¢,X=ìµ'QÒ74•]2Á¦Ù;¦c)Á»à¥— Òžw|è¿„-¢¥/¸.ìH.ïårà8·„C7?lt5SÇ– rån¸/͇q k˜ÔRt„CU[¦É‰åSUhÂ=ömD™ 5켑ÅÇ…áw¸7mvE¦„{¢•ÉßÚ´H‹<µÖî…÷Â}w»RmªkØ Ü›|rüå2ä6çpÝ›Vaì,¢Í¤z Å¥÷“Žê>œú±ÍÏ—“Ž»<éö|¾æcðjñÒM€÷û¼W´Í.W[SÔûó{v¹ÅØõìrƒ±ëÙå{\‚¡çûýù>»ÜàÙå€]Ì.ßëÅïÏ÷Ùå Ï.ì}ÕÀ{Ÿ¿CNKt”-dSŸÛOåL°K¥!Xt2)û©Rè_üܯ\TÄTéÚ ž,AG¹nÿԢΠœ:ìñ³­nØXu5ÆvƒY°6UyëŽVCÒõyÐiYù½ÓR20‘À2÷y|û}ÿ2{ͤs‘“¿-Ƶ'+g‰“ä9Ÿ™Œ‘@¿loŠT†Ÿ™!¶ÉL´Îl¦‹”œtä›}…²ª "ÄϾ7é1—·6¬CŸ¶Ëë›q³œYfŸ¦%t}~ö½É“7zS¶aÃÆæÉ¬ƒbr“O¢‡ûŸkëÚå0æ(1:‡°Y¨<"—}ÀN8iëb"…±;•Ç®û¦¬Õ­íÛçuèƒ Øà^›ª¨&±;‹²¾ƒ}×U)”Q>‡Žˆ#f1vÇû—ëS²ŒH+ËÈÑ¢KŒíGE¬ËˆiYj´†¨õ³W[¾Õ ÀKãó9äÒÈ~\ƒýøýö÷Û(*h>¶½ªk#âº1Yõ%Sªv»R·èšÐ¹°;–ye±µP¬V‹pî CîÀK>…¸ `Œù^^ÉD3šPØ Xüµ[Ã%6¶ÀØ«‡¼¸[ÏŠé™mEþó(?yçÕl¹Ø cï¯»ÈÆ‚«Áíl?³»Ø\ n›ýÌ6p3_« îh³ûøÞþŽªR?­Å-ù¥bp¢³%–o1–‰ûøJ±ýuA†» ‚åîæ·‹èŽ£Ï«vpÿ0¶Û¨¤a÷b9ZÍ“‹éâ°nsª¬Oʰó04]>lüÉ2›í\kœ€½ÈØx?ä3/µ*%9)²QY›5rÙEg S£}vsª0‡¡i:£ëV“ëæWé>Ôó/ƒK•K6%~žÏÆÝön£ÀñD¸œK á¶Õfçæf®XuàÐtyé[Nš¦ìe¯Ê’p¬ÚÁ˜²kídÀáí„pÞEÀ§²"Ü>µܸnÓöæDÇsÿØÉ¦ëZ!­,÷&Üò_5(Ñ$IInÇí%7»„é²Gì2Mr︥dýÁYÉ{aù¯Åƒ|—¶leî:΂ê†Ü…”6ÏG]J·ÛÃrî<ñ}÷•.m'7ä.D¶Ý;[ªQ³ c8£òS ÊÑ-š"cÏÓj­«uü{µ¶»^­ v½Z+Œ]¯ÖcçÕZVëøûj­«uü}µV‡Õ:&rˆ£Ð G{žæ' ÿãëJ“fU•à–Ú¶{7â¾%€Î3hÜÕ?B«´ûûÎù™¡ 2EVf#]UbØý"JY»Kî¥T-†]µ+7­äö#¶T^0 ™VûéÇ ÃõBÈZš:„RÛÙUH¶Ï`£}™æûœ~ÓÂÛc„Ô3à…`ñÖõŒõ'Øãb}*2–².í†=‘µ°‡¹zI;Þj‰a¯Ó©Ëm_9Ÿ‡"­0ìýEWWvÆNaÈåW (±ýÔ—ŠôÛÁt©ÅÍÄBÕe1÷ÚÞ½·ƒeèu4ì³ö ÔRÖ ©íê[µkÜqǽ9!†”³jÉ.ÆöÂÙ¶‡u +šBÑ÷>ˆ ±ÿþ†™ÆÌŠàždƒÝÊ–‹Lµî‘÷:ᜰVeÊÊ;î”Jwä5ÆÆ*F¾Ftˆøðà™'L¯²fY%Óa9±[ºÖKAúå~£³ÇQº26Û…‡‘~¾GEò‚Mi¶JžÜý$ZãRj¶­ÌhúÞùÕv§\Še,çLÐyv¬ÿh„vPÛË9}Þ¥Þà Ç+nºžà^xÍö$AƇYµŒâÞNA¦ÜØÝXeù÷ä°††,‚K„¦Å¼PÜg?‡˜Â«ª 4Ò°`ÜÆ¿òÁ‚ãÝÛxŒQ\(ÿ<ø«œµœïúŽ»S^wJÌRÕtŠŽÓÅä6`rç&ÈK‘’%(Æ…^?[Œ6¢HÓœÜs—ý g6Þ1ׇ&¸Qá—ÛòÒ7áím/LºIB^š "¿ çzà]+GaŸc—þ&TŒöc¤mC»o>B2Üþõ½a‘ Øíµï¹èWÒÖè~¡6]§º9Ké{cÌZØŽÛÒI«tèî9&™ß®RÅÐv• íÏ_쀤m·£SÜ‹\yá´Å¹hÚŽ7VÌôÓV󼡂)àbOî9Ã#kÜÉ–à>— Ð)áD®4Ç7¼­yõ»­-«,r‚ÃÛŸwpäM]«~îZ‚£¾‘n[ãÂØÅV‹žàb|ó´õ³éy§×^’qp\œµdWIÕô '8\9'|ŠŒ¯…šMNúåþÂÛ$#Z•/º§íx_¶!ûeY=‡¼lÀ%GåY毞즑÷K_Yä·¿À„òdZÊ‹‚¥ç·?˜²›•]Ï”"ã/ŽÏm¸íûΆ®³ í‰*æ¶f¸-CÙÝÊ«Éýw““jnú†àxò4^» F/ä»ÁöØ.n}týÇŒ]±îEpîà*5c‹>Óø%õa~Øvº¢ý—\ì>ͪÊîs bpíª`ÂRz’ÐôN› L9À•|„%4CNÊÓ‡kÙÊ>'O‹ÑÃçÜÓK¡ (Bš~‰v‡ábZFUÑYBó¨l¸œ·‚ü¶±@vK=¤|ØsM' ÍmýöÖÛSÖõDž–gs÷Nãzwí{ÒtŸ Áײµ€[´(:•šŒ™Û½UXE£kY†lÎÜNOpwœ€ó‰¦q€ñp1){ÜfEf´Z5ÐóŽ$Þ3|çÖt-é¼ÃzcK¬©MÈǘ¼irú¼ Ãï4]Cþ5º¼á>ÛF ³ì{¨ ¸ä‹Ì=sácF>Gô¹àl(o%ywìm«£éKÓ¯ÀŽ ¸ˆqnÁ0¥i•ð9ÁݯÆKyc´²&Cù_q³ nµ!ãàþ¸0mg —P ¸çE´=Ÿ¶b‰Qt•àñÆ®LíÚ ;<ƒÙx¥ŒœÚ5„އ”ª!¶êùÈÚ¾,öAѪŸÀ×ͧZÖL£û·K0µÁt«CÚ!ºŸ«²Ál|Ô³ª{ XŒ'äýÚð¢±kEžbØãrÎÑN©™¼ôyÙ”‡.TÚ§=†½Hm¼ûmõ¸Ôv6 ÃÞ— §³…W]>j KèŽ ;}®JÅXQC:$ºžkV¶²…ó‘ÜÕ·Þ,¬—vƒ'¯°Þ.аS€¬åžwö?ƒ:>;2{V¨ð+8.>ea#mÌ/¾q!e= é`-›]Xì%\#ø ´­Ö¾Éæ,|Ö÷·-˜ Ûu!q%'båo¶ç©a6¸ m”œtŠ ¬** ‹©²ðv‹;0ÛÞ²Á°ÇwØZ–Þ§$ÌE±Jµ6áp%”3'$»>Œ¬VÕ2bØ{’xè~h ž$†j–à¤ZªF©ª+%†¶UÁp8•Y1²jÿ ÉE~¦Îjµ˜p²ˆÐIЍÚõk^&\HD“Ø®åSg{…€‰hþw";÷¥}Z†añá!m•ÏS&÷ˆèóÝçb*²r*‡1Űç/.9TG‡ˆ¦ùïÁ%À»§ÓÔ‡X«câÚ}±T½fÕþ´c7*a(5E=.MDô,ÿ]ôíi¥t~.oAz–ûýŒ„§‰ùxZ|¾QAüÔ%ªJtèYžZ:æC–-‹Á°{è·íl²ÝÏØ°xXÇp…È^?˜éù8® “PÕ²—è¥N"¦tU­ †í¤–î ðöiS]Â@:ô,A- ¶šÖ.4µ¬Z懞e°h÷·mf7߬T†4µ‚AÄ*òÉ®—†]ëžÛu]«VÊÃHݳ¿é×RWý4) û5,ƒV„D4ÿÃŽö‡qfŸ`Ÿ“•– ²—mk§*èpGñí\^æKU[¡ %µ`Ø=\óà„"–E¹ éþødÅzÐÝÔ0)ÔEñ¹lV‡r-–r1PÌ!IÃoNea;²Ԁ9› ¡Ã7>‰/qH‰Ø7.YÝ<ЧB:¨Íj+Õ•, 'C$ôç é a³”liÙê Ñ!ôw*¤[GTHa¡¿/r þBèâÛ=m²™É¢Ã°7½°Ú‹`Ö[ÇÙÌyÎ0,ÆÞ¶F¯b\kW¾€a"…°ÍúŒ¹æ¤ö¼8~»û`Îzp*ŠžÔQœ Tι±^u…aï‹a”ãI Árò´ñ¼›}’m›g ÃfÏ>­cÇ€» ´•‹˜Z 9åSe ßï“.bjÜ8Wjé*EÛGï·¬HžõJ×}oŒÍ» ªX»ôÃDšqT´mÍuDÛ\ÆU(͉ˆ˜pï·áääË5o±€{aœ ¸i-N¸7Ù¶,ýcö?í—ä(¶…÷vªÓLó>'¸©4بsšu½±ÿÉ8¾…–#ºìWÍêV7w¤Î3å‹ejiXÍ £Ï»‡8ÍÇ_›scZ¨²)Éwó÷Á®va;úSçš)}ᄂ°pJnÙ`]ÓïáÝ–þ…ƒ­/±˜g,å÷º(©:[êÙ¤¡ÿž¿²ciÕC`ÅDðx ‰‰E {PŸÂè;‹í‚ÅX_uÅåóu¡×n}ÒI.‡ba-†ÅT;㺡­Øˆaè&Rrö¥¹óL+ÙûòÛ¶§Y˜á¹2vGñ÷njWMYnbu»ƒšªŠÙk;؃¬‹[U¾»&¯–ðõ’_Hƒ­¨]eÝÖîkN"x»]³]x«ÆEcXüõ¥jªÂ½’­;ÕÉñ®¨*ˆÙºëKÓqÜ›ð9ëæÛÙkióuM‹ñëv:ß*`˜¿¢ËoóÉ͹‡‚ªéG})  Ñ‹n‰9¼ äð×ã/rxýØýb¦c…žKÀ/Jƒß-´l¤¦³) |Ä×ã¢|PÍÕN5[â…C®Y*W^Ç–HAá¿4±´ìok²©ÞÛ“KÌoŸ~ûë‡m+œ•Ã)>Qâ:'ÄõCñéD\ׄ¸þzžÊv­]½–Åh~¯×wç£|ʹ6œCözŸr” ¼Bëaƨö:]ý¸ÚG·¦®kWvãÐ.v¿P8×\VLg:ǰøR"9g¬ÕÝNÅA’D›ocx©äKW…š°C’ÈüÏòø˜—̶²n§öÌÝÿÜ‘ž?l#åª:*†½Q%x…êe4YfŒKˆàÁ–—©ÄZõAà(z}Îò àÙé`µì~r/¶{/ïÙ\±¾Ç°øbr °pòú\®Ì¶XÞX˜êÕÈ1ì{¥RƤ« ¿íEÊÊ›ú±±É {ß4í…Ù˜y_ä!•ùŽ®0/V™‰Þö Ý/BšE1©Ê엪1¹ØpOËÑ·u:bc¾ë™å¢T·7Ò=üeŠ¢TÌþ/0ìu¡YÚXY²L† ³wtecævð ßÑ©ò¾ï\œú®CšØÀ¿éu“N••tïí¢_#R>³t¦oЩ[x2î"Æf‘)ˆÕÜU4Ÿë^M¢ ß+"ì¿mú1g:úÞbÃG¨cÍôËrz£NEMp¯o»ïàv_X©ß÷/r[aµäÎÜ`1ÎáŽ;É1PäßñY–Ñ'Úó¸-³!Ű1Y=±¼,;»óÏášèŸda))W5Ïuïø¬Ò¥B=þÌÖãËÆ''^X÷§¼cµÝ§9†!v*(ØØS°ýiB‘&$?Ë)ôÛû¤ÿ¾uÕ©aGï÷¹4Ëgí&±¨B¶ÃbÛÒvMZìz]b؃ø‡xž™ÝaY' ìêA=‰ÔÇlŠU`Ø ÁüFè’Z¢ì yÚû*¬¤˜hµI‡$±˦f¡1€}H Þ'Õ,P‰ôȈâ©=„6ËØ†Ò¬÷ç¬Þ`ŒÀîÄÍ̵@èLµ†ÓÅ! vÕLÍ!)ð>k@C´7U™‘u_ÃtNNÐ!#ÔÎt¥š8†Ý‰z‰¥=ø*°%ˆ’ÛŽM–‘·¶Å d%·ï§²vnêy6ù–ÜÎŒ+àŽ¬ƒY…†½ˆŽ­×iai“)ÄÒ¦†i)J¦– ³»ÿX‹ÈX±¬à°Ï¥âDŒÙ°ŒC÷bê¿ßÚ™WYÖƒV”\$à ,+œeƒa¸ÊÖ^Û#Êõǰ˜j¥¹Úòг¦1챇¢ Û¹-«LÌä¥ÏËéš2§qø‘ItXý‹šÐ ƒn¤ÛQˆo *W{zkÌÞ!÷ëçÆe—é¬ .¾^­n³¾“éM Ü$1•Wwû–[ÅÒØÃJƒa1†“Ö¶˜¯à0¬Ÿ aÇÒ®IA:¹îF[ñáæ3 FžF¹Ê›jv¦›¶*Ü{‹ÿÛ”*j¡Hí­ òÅ}¿4F6´ ߸Ê|´A˺î½ ¥7^éŒ=!òã VÚ* Wä p2)ÀŽ/àî{æN@ašS76ÊÐ_qšÃP×3Á=°¿ý–‚îX§ãž¾qc¼É‹‚«¹™i;^·qŸÓ®‹ ýòÆþöžøhÜ¥´‘Á%té®·K 3‚»8ÏsÑz_NPÑþÿîGýmÿ*¹È[Epî{üc\¬ÉáM&GÈÄ!…Ò}n¸·Í¹‰'¤PŠîLݧåvú¿R(=F¼y/UÛ ò´7Š|¡Cœ‘§4†%?ŽÏå¶ù³+¬WþÝ|Ñ ×zİïÇ籕ưïÇguŸ“ןÇçŽÀžD&ÉŸ‹§lV&¤ÿ< ¤ ²06—lŸÙ¯?Ï éŸÇç…tÈçbïÔ{§(y·w*‰½S”¼¿Û;•ÄÞ)Jþ 9öNûbïdgjÛê’cØó;5\¹&ÉŸäßÀJ.â:<ŸÛÙu n*'VdBæsûËu¬š[ ‹Ù‰"üçFRáè²$çå¤Xƒ?Ñ÷rš’–Ó MRNSÒr¬œù%iÊ>gW?ˆ‹ç)ïJ»Øó7l²°Ãî_`ö¥2å-†Å—MX7ö»÷:ÕöÀ9¢­Cæyù?_W’,)®¯ôR9/ÿ¾Ë¬® !ˆyV§ÿB™¯{ÑoƒRŠÁÃ=1kÝôv§¢“þ¨1s±ˆu°LJžÊ0Ì™Œ=•÷ýÔzñ?™¥UfÖ¼'0¼¿…”½,g3Š,øåƒædPnš‡f²m…<ŽÓJ›%@’I>®¶Ÿ ~YÃT i—m÷ö8´^@jÇ_m]3‰a»ûˆ¯bw5YÌàŒ°ÇËè¾Ð}𴤇éb9ÁþDyYFmóË›B‘³4·geµÓÞg ¶ß+³uæý*[Û,£ý!îÞo™TI)ë5Űí°ßæ;§É†ÕŠ—ÃÔŠÖí„IÑù‡ý±VçŸ(Ç祼m,—¶‘»…´:ÿû|ûvæ]ÚGEÁ÷ëpfå¿H'1'u¤Ÿ!­N¿#%Ïí®¦t«u‚aw¬»î“W{þñT¤1 ïmH˜k W“}Ûõ2å«÷Ö†\þüAŽ÷Š÷F%-ˆ½ìuz½N]Q‰œ“÷öþVxÑ Ò=Áªªûù9ÌBä8K¢û\[Ò=ÂŒ…iƒaD^…qA¯ŒÑ“ƒ!¹Ñ(÷¡‚1ƒ)†aÕ †±Ãt‘Ýð UNi gû¡Ãm°jtj´l"ìè¿ÙY7ÈΚý\V] ÃBß Ö·}o¸ªÀŽå*Œ2zؤ:cÈá‚Fn¿»œZƒa›ˆ/„úëɰ"”@R(Ü4~ßs s‹üÏ¿?HÀßyAôk^Æ'=9Œ‰¼TËjÖ4>"9ûG6©Ò\ò~6%†U²ÓIVíd»bý#¿ zQ­L· †Ý,Ü›“°û¡Øc·¥ÒJ¶ £° ÌÜ“ò~k¾Žö$[´ßCÜ@÷P€Áûy=` Ç—®ªc`ÆTßæq”ßú)¯íòÅ0DÄQŸÒ”œÛ7 Ä/†¤úüÐB SÝëÜvEn0ìþÖª¶M›Ãˆ»#¼±É˜LÈÕ66d8õ"^´$¹÷_K¤\$¢œÈ !Fÿ“q ‹6ç0ˆË°Tß'YÐ*®¤×Ù6 y62²ù’ŒÚ¹ZvÏo²Å(Ã!qg»2 ͳSiúJÙ ÃØYáÀî!JÉ>ê.`Yiðâ U4j…Ù¶ ˜lº IKÚd<´Ù&`³`‘¹ ë`s϶Å0ì21§’k 9Cê AðXΕ]qý»w ©/ì0??0TUÙTv=Ñ—^fb­@O™!õ…ÿ ZퟴʖqjðºØ yU6g÷–Fey€=Nz ]ºtªÏúÞdÜÜ×b*›©*.¤ËÑÔÄUÒ$óuÃvSËDÅßs¶Ôy“gäõîâ)øYÛG]ªqIG‚»à~ŠÊy"ÜÜÁ…ÑoP´‡qš6K¯ˆÛ ä†4!À´GCUM ƒqÛֺݟÿ»«GºˆÛöÖ$–Uá*@uK¾¨ ‡‚GèjÚ½ÄþxÆ…¬0 ÁÏ!fž Bt†àˆ”/ôW|´ÿò‘¾¿7©<…$Ò‘ƒd;z XÞöe,²£ G|вLíoÇbF£QKR1ë´&°ÛAèÀ.PnW_ËÃîÔ!AØÊMC`ÄÕ¼àg#·ý*ö Œ,í8Þ.ÅT‰Ã^®XœOî {˜ï·Ø«MU/òzNÊU5h9 Le» ê/ùþçóN¡bHÐãøù3n“³íó³m¹‡Ô&saUR'ë¢ÁÝöÍÂskŸ¤‹ üˆ»S^åU¢Ô2Žb—+•ÛúmU´]Ùm¿ Úîݺ›‹(ŠbѼÆ0”°ùÈæŽ}í4Þ0ì†y@>ä°K®­–ÄÌvÿk—©'°ÇgØr€=‰Rªo{HûêTQ* {}€™¡S%(Ùìûþ;hQ»n[A^‘×qV¹ô}) óåÁéÙ^Z¸ÓŠàðHsH¨Me7±©jéõ®g\o—¦:âˆ4U°ž«ù\Míö“Eí^ÄI@rj¨”š2]ܵIC[ÓõÊRÌ#Á=ñ®~fv p¦ dÝí»g(ÛgÞóÎyVsŠóÒ?Q€mÓ&OۆܟïgPÇ1Ûÿˆ˜jwÙçÕÇEjW˜H(ŽææÜœ¦îú%þÝ=½rÙÄÆn±AJ»ŽkÌé.72°.¢P˜4å<&FÅ—û©Fª‚@ÉZ¶K9j Û› Trœ„Ƹ6Àd—Ç‘.œ¦LÂ»É NìybûÍ݆YK¡Ç¢Á0†xÀíÞÌe݃©0ìJ„ };½›‹Æþ ÉÕÂòü‹Rsî6‹Ni ÛÍ›Âõ©ŸhD¹Å¯ÃÈd4Ú#zìò?í÷â2qÌ, ;Ï܇®l™·K½eÖìçøM£¹#ÏÕÆ‚í‰8¸s°y©ëÃn(z ï#ϸS%ãvGAL¨oؘ¨ñÿÁ°½–‚›onr>˜8‘ÊØ‘K¯6މ^ÇZc­¢‡!<1Õ6pZ1ìJ8¥ÁùÕ†×åXÆ{c|¯ÕRÌUâ Œ±Ï"øm•óQê!Ç0¬“â!#$7²hÈÕn˜­âù\Œö^×Ãî44ñ xí†êè½=öÍ+…>Kº,ZuÉ„aØÈ9ìý³âK“dmŠa/Òòð<ºÜØ@¢«âz»ž4)CËc]y›ˆm!Ý3±¶l†Á¬ Ì90v¿É,®EÕ×vEåJàòµošª"W»!À4•e“4ëFE£.~ãâ«]ít öø&[Ënìþ›{Ú TgÆ¿º§ñþº§•vÝ›;ÁÚÚÀ•IÓÇ-š=O^ÔþjýУ² cg/¶ae–Çê{Fø€Ó'öjéØ?zÂþÞì­i›m{–±×/* }/ã6øþu* †ÇØõX¿qKpÙà»^Nƒù!!±±hÇK‘û›;‘Ñ`×oµeà~³+ûµ¶‹ÆWökm9– ¯Gw¤MºAÍù´Uh°|ÑÿÀ¦×¥´CULõT`:O¡?eÓB»ã7ºÆ°+íeþIg]Œ ‹°ÛgX7äj;{%Q±<^Wj”@þØã ¬NÈÕv‚jõžªá¼m¢v>À^'ÇiÖ•I/Øû¤é$‹ žÕ9¾ÞŸÍµ'Ê•)xos ‚»Påw—PuŸpg×9•UY—&~¯Ûçí×Áì0Ø7òØ ÂIGņä¦vG<®VekJ`·“ʧƒ©6› l“vÕê^5rî$†=ðÑ:òc¥¤(& {ž,HêÎþ ‹ Èk{áöYGU¥Š¾7‰1¼÷jb·®aÀ)¾ÞŠsU‹ë¦e¢ŸárÒðu&Z»†oÄ1R- lªày ã“þÇN •Žw•0¡×»~Ä)3p7ÌOõuÁkYpQÐßã=Ö®Ó8q8*¯; ı—KÒë*îs·ÃHbè‚Øä`xÅMN®öÂ:/þ3ˆ>Uý¬Áö`o26áÖLI>òz7çFϾõUÁyàe[Vô3|à~Í«jæIÔ‡›‚à‡SçË84¦#8¤Ó©ÀT´ÌûÂ.úˆ;“Äüž¹ƒ]K!Ñíþy¢Hw9ŸÚ”»Øí~«ü@û]ײáÈMÈ”yË»<Á°R¾rJ^Úß6K »ŸÆ¿lžÖÕ½ìa;¿=N®¾þÞÖ¤Zí:1=†¡ ìaÖD­Kšôv%DÓðGç¶*Š•ÀnôÞ‚c'mâ×ÜóTuÉC6ׯéwaÈÈ‚Šú`3¹!Á%€]‘lDØ ÖuàÃÒå†Ýèô¢O^§´m¬¯Ï%2×›U»üH´m?i,Î'IºÉy²Ûëìäþè8ñ9íɽáÞ¬¿\Å—ÌåUvÇJþܪ:{Žë±$°ÇaÈÜ=B’(¹VäžXn;l¬ö]HebÆt£ªÜáN‘™s›Æ~ûíuhºLµ|©Ç¦'0ˆrƒ`_·µ§‡º´J nRPZ“ƒÔÊôf$8÷!ŒÁ”TÙ¬õÀgAqד°ªëíªìöþ¬¿ZRɱQ)†! N{wµ(y;cØ•Œç{ó¥%ã¦Ì¶—²G`mßbØýÀ¨¶ B¡ÒY)Máqš_“­ýëbƒ4Àž'ÑWYdZ5µJ0lTH¶S:­&9Æ$ç~R]QkÍ3Õ´ Ï`Ð"ŽuC]躀!-bèQhé¬ÉÀ `´ˆ¹FZÄÃ.¼!K· nÒ+'ôñM²8R”î?hzèDGŽ^ãì~ôóÛ—_ÍT5ŸaÙÁ ‘æ™fG3ÄÉ`flÓ¯¶§rqxC!§<ãñÞNZëÑ…•ÛikÆvRû¤­Ia_µ5#)„#±¦<Û`Ï_Û'ñl@*\îcQ}”5ÁvýÞ>ávÅ%cÿt*w6Ø/ Û÷ ¶´k6¬‹Yc(zßÿB,¤\òâto=-‹j+®ˆ3Mä´Húk }4íÚ(f)R ÛuÚâÄHY*.µˆ³ûy· ì©¶×Ö45†Ý6åöÝZ°N’v õîHço”£õtN-fÌV {|hÿšEs1 {n‰T\ãΡ»Ï–lưíÜ¡kDÒÄŽc€½wž1´(±,é¸proˆ`wØk`ô!1´?x´k-‡|Ȫ¸|‘ú¡z¶)Ïû-†P>%W6¹òÁ>“+J®|°ßÈ•e$W>Øgr¥¦äÊû\9bØwr%ù£ßÉ•äjßÉ•äjßÉ•ö•\i2òz~øöuO†ÇõðÜBî~-ŠìGÆÎ2ßR4í¼eøª½Í Û0/]ln¹`Ø'™ïa•zá†]ñˆD8ƧµN¦:–Ç‘tÝ¿¿dªˆÎүð;¢ú+øà¼Ï"‡Ÿ=ð0Rßs¢Ö<Õ1){8Õ)DIöÞd2ÉíÞ¨`%ý)›áwöo ƒaHµ0 ¤©ªµ\ °Õa»&2/tz,ýœ/e.J »÷5_ÉÌlÚä‘€‡4éþýA;\SöMeÿÃòX€ ;Ó÷"ûðŸlàßêUuuQ6Ãn'iq÷zÓ5J‹3$„C '2èç2™M#†±Ûj„6™°‹7Å°ë© ×¼‡ÅLF¬n=jp¼Ô5×5¶©ïE¢ä¼S5Ž}Złݦ¾w Êh£³líä€a×݉*Ú¹¬¥É\ó`ïÓÇ‚E¾ÚU0WËîÛ¿¿ä›ZX!b1þùó«òi¤Ó<±“ÏYù4žHΟ¨þ`ðtÙ”M.žÝKò(K¤úµ,¿#ñÒ &`ž‡6½çB¿ÊÞXfHäŠ~ú‘/f˜b7ÿùÉ{ÇÇ ØÚˆ=2ŽqÚ4±HRâ={>?¨=úi¬Å•taÂŽa-¬¿È…0«F»'™nÄ0R<ñß´LœNò²ZXfæÕÌ™1ägÿv“ÄTÎÁZc؃”¹˜+³_UΑǽia!Ã@Ÿ L¼éË>ž ›þeÿM$-}„÷ýü(-Ξ¯ßõÍ"ì}#¦AS:VÅÆ4xýüÊ4ˆÍëe+([bd©H™HÌž’­Lôº|+&Õër*…öeõv=®f W¯Ëµ Ua÷½g ëR×éÄ«æßÙëBêÈ<²Kå,U×àɰ4CÁß:Mu!A6`/¤Îç)A¹°1W7ϽéÈ¡Ìô`Æ4ÒÞ^—“˜PhÁÚßßÒˆa&Ï@ŒO³à—³TΗWÒÏŰcÌŽÏœÞÞÎ. 8Ù ‡á€»’7o¶¸sß^Hxñ¯Aµ_'+¾´ àò8‘äÜõf› ‚{ž8áž…Ê‹’|4Âl:Ѷ¹º¥ÏñÆtº ™Ìš'+LÿÆuüƒ9D¾p^–9Ï79s†¤¸ˆahVç6ÓÓé€aÄtÙ×lû/²–]…aH¾Ne0°;έ’M‹a7Ôà ÏZå|RÝT‘{Ûfgí—Z©kÃ;Ñ­†\íô4À÷2åºèŠ^`Øs"@õ§)3»m$—£*{á\ëÖYiìº5QŸÚYç½è%†1 sIþ8+>oõ®Mv|oõÜ)ù ›6ÙÆÎ Ù{ÖÉbà²]0lo‘§³Öy¢»v0ìqš}*x¢íš‹9צM†`ž ÁÙÖ}l8 m²OE¥H\z†;Ó8s·tÝ~à¼èIâG˜½½0\س³&¸Ë·“)öç_¯£„/:™t2½hG’œL :™^”Vs8™ŽÏqÿr2•ÜãëÉÄ îù¥®Ø‚ýlĽ¾àÆ”âÞ‡¤Süª–u^Rr »ô”²Ýûs3|<)b¡p—=5 ñ°›´æ2uFpìsEó¸Fƒ9‰çy^ðIüÚh5gÙ—¸½Ïî¡ð¢s¶±¦‰eZ|¢ªB¹)lê²Ô æÆLË®ôî9$cÃç´ž0ìJ$܃s¡â¢21GßeZ6oГ¢W9†íJï)ÌÈÏ4§ïŸiœjtÙ÷Yj Øcß—ÏšöN+yìZ°ÃB¢iд7uV‹ØÚy_ÎOò æ"¦}ïˮг=‚Kf=—E÷±÷å ¬ùœ=å2 ë„aB\ üý¥î²9ö¥ßì”DæAD¶lV»5†1¬/Òàº,²B×îxàÖ¯óªc]ð8¨ü¦¾Ø›r¸4u¢ºrê1ŒÑм»Z?«¾,¢ðÀûJ¬Ø(dåR;ª Sö¾®lKVÊþR†CDÆc½w­Õý ˆ‚8áúù xŽ˜uó>îe(ã÷†Ê'7ÌÚÍ«^Yå,„õ `56ŽbóaWG‘¿t*ô.ma1ƒEiõ6¨çqt°,‚UUI •¼ß ]agå˜SJÆF/~Û3t…e¾Pb¼M‘ÿfˆx€zÚ³Fmdk…¯Cÿfwú³”n[.XÇЗ~‘jìÙ‘¹’Õé£á…•¡gÖtÛ´ÞçÊ'~¿Ù½ÕÎ1b¬ëÖiž9¡ Ÿa…e¥¤h„_ÐŽ<å=¨ñ]v¡|hë›]›'믋ª¨±é&üUò•¡G¨Ì;ô¶¡ÝV¹x\~ëá>=9²¶Ùƒ0p»Øa¹¢u'!,ÚhÖÊœ„[ÃËß­méÈ÷}{7g¨¯‹`x·[Y x·u˜Û~°4¢|U\IˆÞ@ƒôØŠçWÝç¿[ñ6û»Ï¿Ûïs+^ƒ[ñîä@7åcâ?á{·™ƒìŸÓÖ5÷¦€ çèA&R3Wr™þD¬f.ÕU;/´«ãNÉ ²À©¢µ¹VÝu™þ$·T˜ì4ÿ„a ü´Kµ1Ó˜cmp°4Ò(9ØEiª!,‹`º%›˜s3,¿‘©óã&ºwV¤ƒ…¤ +¤ S±Í»€°P»@½Š+Û Bvéšì 2¸jzbu°$úRÀ|Zž–¦æ]Ýñ±D_ yÍËsÁÙ†¬nÜô /v5†æX*ØH1.‰Ø­±ðµ©ÑǾRLÉÏcs«|¡¤Çeð q]æƒË‘¡Ï}å7&U{á«IRáç¡¶mëU›©ëb¯Kü~W…æÁ g—§1J±:‰^»·©%U?²FÄìYæJ4=î ˜YÏ=fƹë¦qÆëøâŽÃ©Ÿ*1I¡$½™ºFiÆáœë±ãRÑNSO\íqiT¢Pk³äÆP@¸ z.;nnÅU÷hü’ü*p«¹(ˆUd1îýG%@Å(Â}¢ÜK¹›±3fÖ€p¿°À]Ÿj•Óø;¾—µB°©œôÄ3&* ^“ºœëA,¢Uç\s*jN:aW:ʳhpɈ­eY!,C,÷§7inDU³Â`IòùnE¹—\‹àfLγ–œ@Øq-¬XJÙå¤ ûÎß\ÛöED ßœXIC•óKüðþ@eÌ“Î¤Ü >¬e‰p/Ôzø}kN3Ý£!¡dŸ>,Í””%%èõ®¾RyÜl<Ó–Þ¦?{.¢YuS!Ì ŸÄ¼£^$×µ®Î  ³ËÛBqÈ k¶Åjõt0î78Ε;mÙ!áeÖçÕWƒûÌF[Ñ"8Ÿ‡í¸2p¯§Êœ®!…#Þõ¸ä±4‡™ÝˆŸ—>Ôæ¶6§Dë%ɇ¬  –FAr´N^úÿA„ÏæÖ-J¼N^ú-üîy­érº-çäÅYÍÕ\V¤"á /ýyŒVå²µ›§cLnùÕ³þМÊBÔbo˜?Íò[¸»t»b\¹•^ƒ°Ãjë&aid¿Y©­éŠ ÂâD}wˆîúD}í¢D}½È¨O¡Ý 3×Å9À‚÷]!”R2{N«žæ}EíÍ‹Ï_’j抯Z—8Mi\àð:†¹˜«mS†â±§ž•6'°8³gÚ³„WË#¶²'ã0êÁÞÊkó¡¼ÖCØù¼µû„qÞÙ^ Hã°VÚ(¨ ? ¶9žFã°IaC{ ïÏqÉø<ºÐ1Ð7¸ðÀEfÛª¸Ø„p $X=Ûþ´VD“`Í|îÖ ‹cnÆZºømý{ËðóVŒÇ° ëŠ`IÔÑÎ…¬7=4vKýÞÑÒ6µï#r° g‰˜,䮇 Âr çtþèQ hn ôno( qæ÷Ðrjjûj‘“Òhh¹.mv»:­‘o›—ô®öq-fKžŸ&©#þM_?ñÓŽh25O•Úëç~™ŸÅojÞ™~úz=HÏ!ÇJÊ–9§= y¬îT8QÝ'vŸ²kNˆ’Z²Á(”væÃöaÅìRzé+¥g]½sɹreÑé ›ua¯r9H>L® 74;®§Îŧd+§aqŒ)¤Ùq|ÔG<ôP%‹#Qq°ô 7»„Í.çFî»(!,0«•³²%­èGq_Â)Ic®sUàOx#5æ*תrŠâéëv!Yçľ[5ˆºªÄ(!,AB¶^S¶.õÆ 4¹KßÖ¼.­„e—º¤;¦—fÞeå‰JÒ×5µ†xM …žjØgwo]¤=Ï5ì3„ý]ÃŽžvN¶'R«¦i.{»©5ûÜpÛRÙõ“¼nô™6Ô[ÙÏ›¨ F­ÀÞ÷å>‹Â2@w>nf[ôÂËqBÚîÓ½VÆgZ7{£“üì§ÛêY‰ÑýhòóÐgùu»#ÑÛIÅæ5ˆÓ>MbÕ5·zùÐ.uç4"ÜpÎÆh\œ‚øÕ›¤1gÈ‘¡Íû—»š! \çý±ŽlTMëúéìšúÂIÐŒÆ"äeçØx,ü˜ÜñbV]5AX~S®¯ùj•ëéî óì±bÖŒðe\]…‰ƒ}@cŽ+•àåäz†Óä?%/yã$R/¾•²2>°kÏJ“Hò²t‹|Që\ydsÔ8*Éi blˬª~ˆ#ˆ¢ë–Ñ/¤_LLëUëaY뺯 a€6ñ,Œ­1.Œ+Wêá`é# ¶Ùó“·ï:¬^(_Ž—z9Ó;››f•Ûõ7ŽšÂÛHúи&N’<½sÔ¸x^Ý©fï¬f/„¥QʪîtÏ™$ Â2;êrdAv=êÂr\ºy¬/”öSaïhŸr¶L´l½?“FŒ³çVØÔ>ïƒré[ûô"­6‘Uecö`õbå" G0È8ë%gŽÈßàä=•Qk‰3¢yw^©…ÚR÷VðÉ åŽŠ)$•A;Éã.6?ÿ¼5Ñ2<±Žq.usð œxJOai/¡ÕÆ3ƒ_vÉ­W—ìO„%ˆ ïLDsݳÎuœ¤ir_vvØÂÑ×k9+»z• w~±f"TSW×à`ù_þÊOÓWèˆX¦«#"œGVªx鱦ïfNÅF! JÜŸ‹ØØ’»“ìMçѰ ý}Wn‚¬èGãÆ‰a'Ì6NL¢\²·3f~³÷­Zv¯W:i€ª±ìµè}¸*Å:q¡¤µ!‚4ÝÖ5–B©Ókl mŠn!,ƒ™ùc¶¶¹ž7â[—RHô¯çÞ´_:òU„BØ;Џ)Q6dÜ{a;’LæG·µdÞ24@œó 1&†°oT±ï²‘³gìJ½ÊU rÔG°vT•ª!,,$êË(ºŠ JrÖAX\Fao‘M¶Û aWEyÆRÍd…Ú0YùU0bW/+Oiº¡ivµµ›€°7pœSÖ¬+×c8åîµøü¬žoÉ`û¯Za±Ž­±¥Ç¡Ò­€0Èp.ró£æhí¼Q˜¾ï4ˆ.J9kNfâ=íô}ëÀq)èvä¾è0§Ô_QT•ëmšÉü5Â’èiõ\“:ð¤éoT¥~t©‰Ïߤ¿ÏO›f«qƒ¥Ñ»™·³ïæ ±Nœ‡ªy{ó>» px»Ž³q‚°øÝÚnè÷U»RÜ’ÜÜÆMZ a Ná)ØÝÚV„Ͱ’tXo¶‹¡h‹Â­·ìõ¼Þló1†›:NQÊ©ÒóaéE/ìõ·HÏv&ü^È^h½…q3ïÆX¡\ušƒåã¶ ´s à¹Ï©7×{žfI³„Ʀѭl û@ý`ÇãF¨ùOFû§^paæ~ ì Uwb=Z“®¤Ô›´Y†I}G¶5ߌ¤Š.ì¤F+¶@z»ètŒÌ²˜6¢µÏÂe7yÖ Òlkg&^íþð f׌8߯73Ñõ•tJ¼6¼åá0§y aé#ÌX-MaWƒ„»`@°üâ£tg\Õ³øúrƒ°w›'ÒUT6„ÙÝe>ôÿ¨ÓAãLµŠ(\® ÈÖÝO¥¢iKç‚dwî[65Ã;7\ò ù¼«‡,‰U«äih=……™4sƒ`äpÉ¡¢Ý2~ÙûÎw1¶ž®´.!ì ¯Ó°ê^oÔÉWùH€Íâ%ÚG:³7êä+C§ ³‡eèݾHdᤡ5'¡ qÓìA¹Vˆ1ኵ( ,‰/»Èg¾¯ „¥ÏWH;8éË4»5J"˜”µ„°<¾Bª•À+7J^°z#Øçá4·¼ØÔÛ—ÙçïeYîmç3Sßgo‡W ê²Lý/(`›K³ÞJßf7å=°ÈÇÆ\q;„eO«w$ÍØ ÍãCŸKs¶z£ôb™Â‹œ ¬êÖU£§}¹Y»ÃàãôPÞûÌ©å±zÑ~£ENŽEN²ü½NóÛéËVsú#4}ÄË\Jíöûç)24|ü½Ÿ"a€Ín|²°BŰfhìqº¤Yç–Gó0 ÓÜmþ„w ;ÕÒxé]Ÿ"ì`ø{ÓÖÈÌgÇ£—æ?ÿaŠÞÇòŸ»M`Ó´Lö`¶«;õb…ºÁ–UG°üaC Aˆw{?nèaÞFwúBº§û†í a|©¹‚°ôÉHåaYH‘W^*¾±‚Þ«:å¯?6´1âÄeÅå¯?BsŽÃq{Ý6t0¹)}Ù]ùë/ë—;u„°ïÓF݈RzÚ±¡O« >¹¹1¸T¡F‰÷zÜ©}Ã'¿SsìHÁ½Õ“¦÷{+OþÜГY™–Æ{Ë@`oåÉe Øbî;,¶`w ]ç·`žà@·W3žñÞªI¹;p}¡O°5í–£r€°ä¶¬¢Éai$n3´dëuÑ£Í0ìØ‚„ó>£…_êšUÌìú±«!ì•J[ÉœsÊ?-»wož1}!&2©±® ,‰ n{t{p^ xH,xHÒzHöà€ŠM4Ïþr@¥Ù5ÜÛpyvw@/ƒÛ˜Í aÁ ³0Z¾nY Â~#ƒ»o ¯´yCûBwö4ßKÛÜÙ<»mÁ`˜Æ0׿VE¸øNU ™Ž€è ™Ž]gN.ûžMÇʘŽ#„Ŧ£ÕJ3Ë©F°Øt\×CzÏGÌó‹€Ç—8U ï€ÝÜ„åÏw8Ü?8û‡îpU\Õ±áp?#©æ+Û¡ž ì÷¯«ÂÑ 9ØVËœ¬Ýµ9SÔzÞŸç»ÂþG¸‡x Ùfœ„æ‚üªŽ/EGŽq±oµòUÃ[åsiÒâ[e!3¼U>~{G·ÊÖh.^ïç9Û÷Þß>¿ÏŽä1gwXœ\0g­ìÄîËÑ¥j鸡hS­]A[õK®9[о7n@رß{m‚[éÝq&úÒŸ‹·zw¶Õ›p×ê^|´GéÚ¥@v½—sWAØ°í¸º¤Cy÷2Œ¾ I6ÛSB{*$Å߀\€sH„(&ÝMNÜ)¼µAÜé¤NìØÀ„÷(Þ?·Š9Bäkâäï[xè4 ¬XYËÂé´öKýýs÷Ø ©K™w›¨U<°w¤V;|ìêkDÞ!ج+g5mÛ¢D%!ìqãÂã¥ïäÙ7á|"S=…wKð¸eï6¤º7Í4ùM(‹Ñ€´V"Dnax¯ôùY©ÃmfG™åã!,D2@ØmÜlŠZMÓ Gßd(‹o-Í‚òmrÊÑ)$öœìvGObž‹¶sz …Fj;nSçãŒïH7R7”aÜRÜìâ½fsâ/ Ù}ÿÄû*C>Æ õÿlÊG/ÞWpBñƒ`ϲ@ w»Ô¨ÓƒåRÍ}5Sô´ ¹NN²C×ô½ôu²ïK©Ïìpw5{¹kŸ£|_­§wÜØ•]«8½“À-o}°3ßLRãÓ íˆ`Éc®˜ÛƒÂÒè0Æp)‰pzài`gö|xVÙk×VtBØCx"¬ÒwWvfÇ5G&¡TëP aà¸Ú°v1o¶ÔþGó¿B~-™ÛÙ‡üÞùsÈϯäsÞ<6 ÃðRêCM€Ä™…V Ùï ÂòÇY`= ³ã¨;suD}ÕV«ìrÕVCî#³ØqÂØq"\Gù=vMýn ˆ»ïïsßÛFV„ EÔ–ÛbÓdܸ)œ#96 ƒd—Ö|DCwš…8r9^íÒ·v;\†pvbËÿçëJ“Å™í–ll#ØÃ«ˆzKƒ06˜Á Ž^ý§Ô˜‰DÕ½UÝ?N`#)•óÉ… ¹ÎÎxxo$q¾_Î5¸…8•3/T ~ ŽŠDÚ7ØYN|‚ø—Ïâ…aIü¯Ó·À°[Ô î¥üð{pØ•´B ÃñØ%çk‡aià·Êƒ2ñq±šÆCœ*•6M6)”¦”"ŸÀÖñIÖ-IXѶÃF——†8u€ûý~õ½5¦>F¥Þ„B). qƹ¥¸ˆ¥ù^ÞØÒL©³ŒŒÃFî¿—Æ”Ïʸ£ª&ãýr5©‹…Ž;„|¤QP‹„j{¹ÒÞŒdAI™»Û¦s×" jcLjSžâþUv£G/y}_ßrư;†©Rc “§½¶é—”ÍH~{vm+5ì<- `Óó·—¯íE`° TP²0¶D±Î߯ô­z Ëlÿ 39Ë…‘SË¡ul ¶ú[ÂÇrîiZÄŸ…/uL},‡â ߇JÏRË pÅX®‚~î-ŽÖâî1\ Ÿ[ÜáLAÜ”$¸4ªñxÏÆcîxZœÙ[©¦~²±—ÑЪZ¿fÞÚº ÏË#¡Õ˜EV‚K.Q­WJ­×Ü5ªõ 6ž¬_’ĵž˜&ú¹¡6+%¬Þ‡r"¸P›•@h|÷ˆ…t!g>u—"œþ~°iR×Ò}KXh“Adzã|#¸,ÔU¦ ³³ókeo„»V|¬î €TàÔ9c.Vª­/Ü¡r±ºCtM¤Q6Ø#zä-M3’‡u0ù4®t†±èA‘6t=bX?'ÜRX“ßÄ·º~†Ç[£§âæçÖw ·u€aØŽFÃÿŒJ&ÎAÍ϶uQÛºaXBèb©„¼QÆ¡¶5û)šõôŸYô´Cœ© 1ìN³Ð¨Ât?w5æñm•:Vn«÷xrRêòæ¯q–œK™“ô:Þˆr\żBÛˆIº}Èéu]X\–j»œ¯˜Ⱥ°øýâÿ~îŠÓðz[åNÁ¶ÒíBÜBÏkx¿ù³äÜ-ÞÜÀD¡æ¿–Iª¹»NI¡âîü ϯØÃðU§_B^:ºÃîÁšH{|§ÝÞ$ìX¢eIñåUÁ«Ò6O°ËyÜÌ •¢ZÂæ“W`¨ÔÈh÷_ÿÛZãfZ¸¤mÊæ¹÷í47³m5Ó°ÛöÖFåCÛ—vA®AâÂÜ™¢ï%÷BX\VWµVâSˆv=ÌÁ1¼ùÐŒZUîÈ1Útbƒ¾ÜzidÉ¿öˆó~¬¿Ë®aݶîaá¼€¢a Äøúd6Óþkš_S`˜_^h΄®…Ò6åžÓǔߌ÷ï¿ßêI–÷âÖ¯„q׸Iì#„,ùGõ‚wìXr^”RJWlð[Ür.ŸÖrfI`ÛTýø;Âb¾õ`97Òr.­åÌ’¸Çl|[6òÝXÜÀö–3; 5#¶·ÃY÷ØT²¯(lV%'éM…ÂòÉ1Oy4ع|á¯!mµ¸$ÞRRýÜ[Ì 3‰ççèMv–&±0Œ2R$ÇdÇ<¤­†Ð[ †÷Õ,¡&1wŸ;‚‰=Z=Ç<dÐ(NN”2‰œ4í+ŠSÕ ¡).¿ž5Å™§‚Éûq²×ÏÍ+Y<¡Dª±}+VX`7¯d5–j°åÕs)lè†Ý¼’ aÍ“À|åGej—®YWñ±„0ìH÷ᕱî'vÐrsÿÝîÔN@ÊBÝA †Ý¢À<­5yÚ=0ðëÕò¸bµ`A@ÿs©ŽÉ+¤¡°õÛÖ¸p »SEæ yëaà~°Ì`²½ùí;ßmồFn à€™w—*Êj”G%–.+šZúF/KÚË(ç);ey4ŶUMm)ëѼKM¼&ô1.*éòV}MÖ ñ>UÆÛÅ(õOkâ<%õÒA•w»wç©éò7õZÃq]·ýŒN3T™EÍ€/¸Øº†¼Æ5$z„: 0Ÿ[‚s–\{•n«‹–¿Z²ÈºªÓ»ªÚÍ›æ©Û+‚cg&ƒÜ3†(¨ñu+Šºa'GQP#ÛBÿ!çø7.äÉ)ÐÔÿƒ<[Ù¬d?’ðú–îà>·KKö#¹\·¢ ë—¸"znF ¨1çMíj†óÔúºpoT¾Ì¸’s•¤a±x©.§™¢ >XIp t]|è³4÷Yßµ¢äs×\~f%­ä=n—¨•™7rn×ÐJÚJ"wÁ-½WNe/zGeÅèè=j›Ï?›èaYP.êms¸—1ì8ø£Ñƒ?†ÁÅŽ²c¹(2á«ÂÙ¿Ùqð‡y…WÙ·bq¢–…TÏÚùCç*7YF¨žõDÆLô¿#†eÞÒ·u 0Qa•ö†ù1¿uU› A±üxQÓ彜‰·åÀ`¨ û¯b¢ºè ¾;1˶¶¦ß:wî`ôªföÇ¢¢Ÿ{q‚W*úMp3ñ±Ìì,;äç­X¼»ZÞ·ïâXT|6)>;Á…\ 0PîÙH¶ãšGqëꪲY†¬$l­´Ç~!¸kˆ[ Ó§èÉþ&áWÑëp´Uy0Vþöð$ŽÞùòµóXîB¤düóV%ãËÃî±ù¬c7 –Ì™å‡Ð-]%aãgŰ4€íóGÂf;ê†ùªlW÷ܘºçg/,¹nv9’9W†í]¬ï¯Ïwë͂T–”¤jk ¡‰Õÿ‡Y‹6½{Ëš‘]¨wVš~áVMnà Ã0ͦ"ë}Ýóû]«™|·uøê•R³ÝûI¾ ú…Ab·ýõ#0ß”e—·úvCU ›ÑÎ.qg²¨ü#>YÞKØUPÎÒq˜­Z4¸k|‡Þ-ð5(ãò°É%g²˸š.Ð(òÔµh7ÊŽ¬¨¶îãÜbØa»”=+·kš,ƒEv`E-Mw¡‚ a¯ØìÈŠjf› Í÷ÙV?Û·XQ!%/Tzü½¾†O»bXMßW;Q˜³Æ¸QÍÒ|j~6)€f}oDðå!@ZE·áÃuůÚ).¡ƒ>à4•[ §©&¸[ˆ«W8²v×{ЦÚÙæ¾Ç#&ý»”~K ‡fd¥ÿ½"éOþ!ýûâN]r.ýmÓ÷v"ýûoß1,”þF ͲU–ŽÓÍÈ¥¿)^­åEp3²#Ò¿øT~FöAúû÷ûðÆ°¨ô ¾LKA–s¿è ãG:ÃÐÚr‹ì8n „B5 ¿Æ®Y·ÆhÃì@Õíg­k£«0ìd»ÞOÛÝhd–ˆõçó!Os‘Y3,¬~léNæc÷Ôg#bC¬™¯‘?b”ïØm†aªzˆC¯b©0̧™°üÃßã»Ç°<&­L‘# ‚¤ß@ƒ+Í÷ÏH¾œ‘~=NU7îþø¯T¿—„§é7s8M3Á…åï ÕÒ ôsï‘D?çŸ}´#mÐ$òÍ0<(›¸mûFZì¶æ2óìÄ£”W…´Õ\BæÙ'þ;ÔÈkJžU s<…0¾ÄSõŠ:JËìN)‚lJäP®IE¾[…ÉÍ(ŒÅäpç}Ý–¾d¿mà7QXän–r|q>îty/Ñz‹~J{¹>þQoÑö;Eë-úBxÍÿ t'…#K+¡Ê£±ñ˜ŒŽ3"|ïNØn›Œòä•nŽTqÛú–†I¯R%½ì¼²ì«·hžË,æ¶›m3Hö8ððØ²Œyšå?¶,#{ÐmpÙ,¾ãlVöH@tèÜô¦xrò8dZ¹”A#kŸ2ÈÒƒÔø€M%=+wÎSÚ(ì>¼ùûóû}6 »EaK]Û™šYJ‹Êü¸ZyAÄÃâÛÕun f–ÆËc Æñn^6”¥GÒP. ZLÞ4 «Åt@YT–qâúÅŸò[NÖ,=/*+†b³ža–Ee®ñ¡‘¶ZC·+‰„4ù‘@0? ÂÖWKè¼å÷—ŸŽ—Õ€a·&ÆjéxegfŒ4*9/øù™j¾Öâ‰a¨°¶¢¶ôð£J–íf—Ú°òl7'{#¢ÒF„µ!³s#bWg gÿ0"¤m8`Ø-nô/Û²`Ø=6ÐðÝT[¿aØãÄÖ(Ü9÷‘¦ÀÖ¿6ƒšeÿ0"ºâ[a؉Quay0@¨ÊYnëI²,æBhÕ5ï#Å]cƆ´–ìCÌ…˜‹ Œˆ‰àâF„47kú¼{@wÓW¼‡™ŒÖÁÍãi[è+B5YïgSÇ~1ì%5¥( ìŽM=DB'©]mj4óýë~Þ‹îê¹üÛcXƒ \ªÍÃN† #òëLÉ›²!¯0øn¥´½²¼—À¶žù·:‘ÇÄŽ”¬ Dàšåg C†…¼ìõ m).¼‘àî!‡«J^lœ¼®or$Jzà‡àÒ(Ù«<‚¾‹ájЇà²h’bZ"¸üPܨϕ?¥ çø‹©rÖùåL,*>-®C=¿œ‰…´&„;ïùåJ¥kTÊ/çJµoTÊ/Çò)“Ve*ÂÖOç—£XÎ;'¯ÀâÒÓ–VÈòËi] ­†…bÑH{¹lÜØ—ürÒ¨¤†šÕÚˆùå¼Q©‚†¡Šà’БPb¶Oôy¡½âó)ˉ¼Æ5ì€Þ¾9±0¸¸jF‘•àÒ ßNùC›‹—‹õåÕI¢Ç3*ꇾoV tRU4;§ËœãKT|ä*Yñ1¸k¬ŠNQ‘ýH’ÐZ¬Ô÷;ànÑöWõ‡àîn°µŸX½¾>ýÒ[Ѹ&©š:€q|¿>ïz­0ŒNRµ5ð"5†ùª‚ºÔsÕ‹×\OÀ|Šaž ÎV4u‹²5ö`p ¯NÓæWZUà #ê´»Íüä>n Q¼6íG`+ª¶[ ËV5Ö©lçÃÐ$UcS‚  jò¦xšT]©ÃgÛ×ÜÙlCŽ9Q္oJ ±ÅOÊÑ4)UüTëÎÏ×4ö/(&8Ý»ƒomù<ŸýÜ»›ÏîR˜Á«GVåZÒ€³~$¸ÔO±2µã aò‘6kop¸´ÝŒX[ëj®È2_£Æ/¤×CŸ—Gq›Ämä_èäBž)Š»ÚLu1:´™’÷M<ƒ{Zú²Ó{'ï‘܈Q«ˆ„€ëq!g9¡´ôÆø•÷íg¤8.ú«jkYAmVÅ9ôz°µÂ £HG`xª¸Äú8Ç÷h‡¹\ ,)ã‚~¿§OUZyÝŠ²äë^—hÿ#$ ÉþÞ®þ:«JÍ÷8ÏÕ¾·N7'¤HÊgéè÷ÍäŠ ò$N.µé^JÛM™'gÕеêšjó$¨Є$«|S¹!%†=È­§¦¬Öy³~Hî{CŽeÀße}¸<9­€1€e~~t©‘C¾KZ+ùг“oëô™Ï?êŒ^Ýh)/ÕfÜäsŸµ™¼Z:ò©úØÚ¬!¸ä ÍàE¤ôûŒl~CE*§<¸ÑÍëÈQþ!ÄM.ap¨Öƒ~.²F‹œþ’.ÿ“àX\KywƒËS Keþ]gÌš ¿ž"@åÎg5çøÃÕ¯¸kT;ƒ×Ž7ß’t ½Šåków‹&+‡q(NiÑ?&ej%¥úƒKàB-:áL}8ô-ª:êÂÑ¢£Ö¢#9WF‹þ9d«›Æ…r î Eá¸lůæåJÞãv ý–ÿB@ :É7‚‹µÀÐá ï;å®s•ó xrnfA~?ÌŸ6nµ²?¸·-îhJ®zZm*½ji_VÎÄôs¬¬’0~„=BäKïOÝÏ}yð«Éwcñ^GøÅ°,ÖêÖ ù殈ÂTéè8®¦}yŠ[•Ønw JVÕd„ÞQg‹Ó>¿JE¯‡K[k­¦Öo÷þ®v­ÁÝ㘅ã°1¸G¼ƒAZp—ž”Ôº’EƒcøšÒf™ÔÒùèñÄ×™‰ç¬¼*žnþ¦Áå\â|‡%îÄ”wcÁÉ÷‹uXB‡…ïœ4¸$Rë7@-çFŸw‹Å8ÔÓçÝ£¸¢8âaìBpùe “¸ÓK‚«¡¬†à¢ù0\ªmpY¬cwD\éˆ'kÝè:ßÂc#¯•A8’ÂüABŽ&•.…%‘ò[©¨vmx!GebB»Ž%>Ž}ûúLÉ‹¥NÆÃÁý¼-‰Iþˆ_S Ö––¡ ÄCŽÊû.}Èñqrl!äÈ1,FÝŇv»^¢>5ØñäË‘š/_“€C‰0ïB‰(Ÿ?Â£ŽØK1Ã!ÇÇIÈ‘ëãFßã´¨ö1W¨p÷PþJƒ5OÄI;Î1ßå ä¨C‡»Áe1 Õ=hÈ‘„%Ô©´ 9⡚z@qר5P [±\\0Äî­”ŒÍv];:²_ÛÂÏ<¥Œ¬¨Ýî‡Cö¾O‘´‰@È~.]W^žÆÅL•‘ËQbØ#®æÛ~h1, Õü0”MëZÏòô@àˆKäÁ#°,¸ŽÁC—)ÊÓ+ÈVr›­äÎÓó©–Š¯Ÿ|ê5I†[ÛmðzûH2”QÜ-zk£ºƒÜõ):Ž"qV*ÊkŸ•VEòD¹ë˜'Іep‰"v6íQ¨Ä¨À°[xN ‹ v-e9;æOÝÚóÒ%FsÄhwLeMén</ªԅçR”9£#€\+¿Ðm,£ÔS8#²¢(;'Ÿÿƒõ Ë{‰žNDÿž3zœHÁÚT¶ w}l±Û„oy‹k<1¡ ÁÅÓì¢6ÍžŸ0”©D!ç¶?$Ï‚[Çf¥ àZ‹s_äÏ¡=¾Ä°“4{é3€Y,ÍþlTvÃÒ¸stìÆâ‰B龑Í¢‰Bù.D—ʼn•íþlKî«1›·¥> îÍc?}^D¹”vv¢ÜKcp‚»ÇÒñ¶¡³ ÍnÈ×Ä"—Fó„EáÅ' ”»Ïb¥(w%Ž•¿Ÿ²åÎíõNÎñ%vCÔw%ÔbÛ¨†Œd“$l¢êï÷ÛÙ²ã1é`Vœýùcz¤˜ƒ7p¹3^Œ%†}I_JFV³âìÖ #÷ 2âŸ(ì‘÷Rôc¹ƒEá8ÞÕv°»G®ŒÞ:»Ââ`¨*M¡3³ƒ…_º:Yí6ÈSpÜ,ŸïµÝcØ'ìß÷Ð\ÌÁ¾!X©Ãd5ʵZèø· ¸G8n,¹.PálcòNáÚˆÓ6\ŒCß× vÜ3acŠ{# <çÝï=¬db¯ËÅè~?Aܺ ܽB‚ÚÆpŽB¸û>×î i©AöàÚi[»6úû×ÎÙÚ:ȳÂÀ{ÀÅÄö±yýLwèõZþd 쉿0-š}ZÿóN–€³¬ ¢®âªÌHV{ÞL†>Wú.˦ ÃⰦݩ°$¤@W=b”aXXß5œ¯%†½ƒjÌî1ìÔNfІ} mLK¡£ó_ë7,Õeãu_¯l™0 ×oH½Ö †©œ›£Á0T®·`-ÁU¦eC`~X±RN®I&×íXÖ¾Ç0_¿qòk²L9Ò<'[xx9ÛÓ½ö$Ηl °‚A`©îãè¯ͦ¤ÜT™€¤É, ݲAß2²Ú3tˆr=oYBÊŸð-ÛÕ-Û,¹ß2SÕ´zy’WMyÌL},ùmïà-[ÓÕß²äz} eÄušcØ÷rËL$€±î¼Œ8›†±>îÊ@Á=¹>!ºŽà¢0î8æ‰à‚C¡Ù LÏàâçЊ‚\d¨–m;‘oÛúWWFim–Òõ‚ÌÓÁŒÊ ¸Ëõ±Y~ÂÔ×á€>ôÎëÖOש óºÕ!…üø ·.¸ØT£}Õ)ú}ä®.Ôay†aß°Nño­ô)n–e£Ï½·.¸h‹ÇÏ0iq«é é÷ i Ä•Ü;Ä7Ö6TJ¾Æãìèm:‰èI-ÓÊÊbùñ k|«´®«±šÝ‹`°·'n‚ÅÄ‹½•ˆv£ÒXL?Ÿ;Ù®5gü¸oSë¯ê‘wëÔî¤`™†Såc6çÙ1`ØÙÖ0³ƒZdw¨C°6µÀ0Ç•úãF]EV÷Ù‘—ÎÇÐÈ'K]KU«×—Uþ¡(òé]TÝ<=:.˜kå`h€YáŽSËÙmû‚ahpna/ÏØVûR”-l!!cuRøXcÑ ó0L†¡ZûvõÅ^y;@òñ:Wsym£=ÙØ}+ö ÃìWøc{Ù¡bÞë}ìàÀNåþß?:-çbÅÄŽ½>àӟƳ©*Ël£¬â8¦%ÏÛÙ9¼Ó81J6u@Wë0ÉÚí4ú¹ö]²ºDÉlÎòªw[ˆ¿Ájyƒ™î:Êb߇ý{‰å¥ZñA*ËFÙÄEî®L„‹606-Ea>ÈlÐ.WÆÉ>©wa‡èÒöR[F+1¾§i ©‡èÒöR'2L &c‹ÜÄ@šàÓk2²ê¡iÉ™›1à`~$ "˜dzã€açH!]!ë6°Ir¶cؾ©c!¦ß³:#[ð‰E‚P†VÏŽ.#¯÷oÕ®×dëfn w=é·7-M"Ké®Q%†¾}V°¡œv{ÞzÕ±&]XÎ%y¨/'M¡<¹XVŒ#Ø`QL:£ššhóQ%FuW ‹n°b×°œÂžVÀj[ïš9X|ƒ™Õ¶œÂ’“)gÆ{ü\i Ã^æ*Í‘êX<†½Q{<§ÕµP¾ÚB¶ðñ±i(ot}í²ùד1ZÊXs¹RWý¸‹a«[SÞ?ÃÙ0B8AÏç‘Õ±ÁÉLBBI«-”&˜åøs˜¦²ÌmÝ6£S`êB­¦¬ ÇÅÑ)0Ýu°v‹i¦†Eç$ Ç=ìsžå^ÀÓç† ™£¤”\?*áJ`.`60ýBª}Ý~þ\Ô½ëVÖOë^Ÿ«U`k9.k3JÇt0¯¶L½§†ÍÏu–f #3AÝj•žö$' ‹ñ 1¢˜ëMɈ`ÑEÝ»i]]Œe]€oø|’^n(‹ú ºÜ¯ªJغБÌïeݳµ>& ‹n¿M3¬rÉf{”? F=ô˜šªÙ0,¾ÉUhZYífG:˜oܤ Û®«•ÇŸIÙÁ^x5阌b›„¯F–:®iN¯Z­­2œÍgBŒ=°ÃHÕn+Ým‚c˜øç?ø.tG5é>zû›%ôñUÀi;QËlØñ :ûv”Ré$§ÝžçÔÒÃuV?¦­- C|ׇN®™„âóCn½îFd»0OR*;ú`»† †=i« Ó4}:Ž‘¹‘Bæé\ž2U¥‡ä« MB°]Á!Y­Pתg݈a¾i:7¡u|'uá•4‘-|P¨GéÀÇL²µ¢[øB‘{)¦~_Ò„êóCÛè‰Ìöç­Óœ„Šà7‹[¶Å&«nÎ6›ùc':¾ÑØ iZíç[,îѳc3áø'Î2ŸUe[Ëyǰ7°^Þz=›Ža„0QØñhe§^âHVÃMÎío“ý4ˆms3 Y{¸ Swô£qà`/,ÍÍAß•?Ê TùóKæ2Óbb,«¡(ÂÁ>æºl.ëR­9†„ P!Ê`-xå sÏï•0á¶šº[A“‘§b„‹åEÅ*V0òØ3(ÌÀݹ2Ñ4+•àžÞ…6°y©û¼Ÿ Î{pÌN UÛ]¤&°A´êyFÓ¨cãl`ŧcCüí±"þvL'5h.¤µG‹ªX„2ÒŒºåJÉÙ—ÜÕŒUi,’øTrš€Éá*ÊJ›Ê+ˆþøäTiÚ¹žŠf`Ù"š~ÙÓ ÃžÈð6Ì:eŽÊ¬½ëüî`æÅý÷?VCXÑŸŽÛR`9ÇO2M]«Í‹yæjœá¡ñ•TkEÿRÝOÔŽ:’À v“¶ô9äçãÛôÑ–Íùîî~üº­æZ*TŽaÑY¿ ¬"”—”÷)¨Ìø}q ¬c£ï>/Ëdzü¾ú™kâ$¶b[çÞg”_·¢ÑJniª’/éŠaqPÊÉ&)¿¯ýo\*e•Лâ7í“:ZƒR"{ÛM—ßtú†8Li–ƒ}¿/Ó7œ¤æJFôCù ø2›.õ„Ôµî–Áõe×{v‘Ksh§”7º(¥%¸Ç9#úßpucöl’egMvp"åEš/#ù^®‹œÇ™WÜïÓº4t½8(_•Åò5F³é,IBäNãlzXÒF÷û IX®ŽCJqï„]•„ès?”+©=Rç}¦'ÆÙÙ›ä,sˆ,ÆoTæ`ã÷®}”Éô=ù}¶ÌᯱÔ]>EÝm­ ×'ò¡JoÑ+û£MÖ¤÷ôíÍ>¡ë­ŽÊy½?¨©ãåz‹^s]É9þ¹P¦•gä½D •ûYw€‹nf—\ÉGÖv‡Í[AÇ¥”\fôžÅ$mpJpýo—„ÅÏÓÓ᪛ M­šqiñ¡í¾¥M¨é˜1uÛHΈÈ_H… Õ)k6]„töGBk8Ä ¦r¬«e+0‰hŽ`K•uì8W‹H|ÐX2ÓÏçµÉ›”¬vz2ÂÑeªéhÛ±­f ;ç¿ù©ƒk2ܪ]:/0y‡‡%­cã Ë¥ª0,£³ìˆÀºÕÏg1Ac‚ )Õe,–y]‡=ƒ¬`ò¼ÐÜЙ=ãKÙ‹¾À°äVa[×|Ûê"#}ýN8à›¢ŒP(’°ä·x¿M 8Û(yý;-0aدi75ÍÁ~O tö{Z Â°_ÓÝa¿¥&aÉëßiÃ~O -üš¨2òz¨k \ôøç*q“7 „:£­ÐSºR¾ºñv’¸„ì»´îwÚ$yßZ"Ø„[ÏÄÑuÙŠa1bý»ï8ê‘'@I¼•M[)½9¶÷9oeCÅxج<*Q †(õNð§ÊKèJ™Ä[ÙÞl2!%Kæqäþ\"+;”V†¯õ §•+šVN®ó?r+.ëzßúš/p.¿ÿÕQKªZU±Î=†E8ðnîé2+߿ʯøú¡’KKKÓ€pŸ‡³“ƒù -‡ø•†5½t==ì駉W;¤4ïÀж˜1 —5YWRìËÌÛÙrt04vz¬ƒ¬ÛÚÝÀ×5¢®?–IÇXUûáäà+ú'Œ9QþzÞ*QíÇ:†•—²ƒÕâ;ÌäpÆz]3¶3 CCR ›®™’ZÓ^“Õž·qYS¹ÏËžÎL¡”÷æôût( ±Ï!íy½è§ÏŸ]Éú#[jpÁ_´­OÁ¡ŸÇyTß >ýçŸ0È˽¾ÿÌUîʼüNmjÑÅüÄ\® “Pšó~„aÕ\í;“Ç‚aNTï°gÊJ/š•Àžˆ¸oaùª¬ÂuÍk ‹iyŒž‚u[š2×ãÙÁ’›6ÒÙ%ž­bxG´Mš¹šAõÄb†¾ÜyÅ\Ÿ÷<¯77wÏÁž¤mõ«eÝ×” ½£“ÞïhbÒ|ßØÆŽ Ã4{ÉUF <Õ”×Ã^!UÙð¢aXGoÔXúþé ˆ—¼©-•úØ1wr¨sØiL¯3„{•-x´ÝÚ,¹¦Û¬©ºïÛ^/ ¨¶÷…%âü•¢NÙXtYZ`J·™IÆZ8l¥ä3$÷ß Ìç2 E&öé9 –œD—Ì&ïêù±ø»6$t{2½cÊy 0ÿzTÚWµ2/S|Ó|1ñ¥ÑY£òà…EÈ^±kT+ÍYÃ72¹Œ^È ®hÆ^,²õ÷”f—|¾bh³iØ”ëˆa8AfåV·]%òvð'®´!|Ù¦éÂZømŸËN3XÌ{9MG0/‘Ü´'WNT•²^²È$ï/åh¿ÂhJ®}3Ãoûü\…ª=IsÅ»†ùjeBiy¨ƒâ„>üÇ´°W'ÖRŠqwé$¹^NûZÌWÄ|®7 ¼»L·àYa(õœÃj]·Ìb^1ìLË@èp™å0T>ºìGcž2Äv “íºtëžbXôÇ îžðøh,ߢl±å¾Âëî¥ÃL½çñhÁÄÿ¼.™ýܽ&ÞòÑËÏ›ÈóÀº±­eZö5†Eسٌƒ‰”—nÀKü¹¡í€j%{˲(‹m†r µe`˜±aôó)b44îÏ.y[eùödµ'JïZòGZ¦e‘§ {ñÐ8 'èoßÕ{'÷Xúç¤2;Xq”‰yÈóÜMEÏÉMѧK_öMÆ\×ÝMn éH>~é]ðiñ®^X•27Ç6FƒLBçmú-‡nß(|Þ*wÞœp@ý÷ÿš×kE7T­ÊÚÝÔ×úø¼3ç¬<4¹ÛÎ\)Ž^{–‹G}1½|3÷oNë¶ô: õÅ„Vg/ôA¯—vª´–#…Ý£«m?‘*ÚdäÒ¿+;:5£iç®QŒÂ’ËFò¬rV¹ °ç‰I3µØ²XJ°Nÿâû”aôØ} #Ü2)-¹ %4Õ~Öt*ïË­1%…}b”F”ÓZomÏ–~êÅ Ÿ¿”¹VcpéO'¬d‘ ¯6ÙñÂ>W›g.…K\ÙRnÇOÿ®Ç`øœÛKLÈ+:‘I’iŸ¬),ý”„J«ZYÆ&¯ZFaÙ¯€÷ÛçìEc2—Ó0ª’/†Â;ÄŸøAI^ž·hx¤—³Õâžëû¸µ³1£¢°„œo¡=•œ &5úÎéí]ÁØ•{)E×1 K®_½fÛl4~ngiBÛæå¨ŒÂ¥Ï®.v¸êͬÆQá„v(Ó¬Të6G/}R—¬Òýáu¹½Ý[è*¦¤v)¶ÉÛIº—ö†Â’¨øÃÔ¶2–3+%%8!ÜTÅWwCY´ ±˜&qG·ÓšJÜ!¤h沦sÃ畾¯©»åZEa?×t0ö8‘·übéjZѤh`á6r0¶H, N“Ç¿®©‰FúsMñD"E3ßüúc¤é¹°1ò¼/3Usc–}':Ȉè’ꕯDÜH¯kd;¤–ô ê­ÂMþ>è^aQh%§¥æöÑ~ij·l+΄R…'("n¤Sk+hPÞÏy@°ìh”Üx 'ùýö%íååö´‡dPJ I¢ìØžDÓÀK(m"ÄC˜b¬fÀÅNïgvdÝÎì!@°„R#]Q±Z+è³0Ê®kº8ÚÝâÇ„ÜOéi`w®ÓºNœCÉÀÒKÆËU´ÜV–²KBUëb«ª@Øã„ !k)ó©Õy7Q úÝ›éü"´îñç|0eÄtNIõÊW¦³¡°ßLçö“é<ö…éì Pn4¶XJ Ϋ­©Ä&q‡d—²¯BÕ¯mËëN¤£ÈåPjç»M°ÍS½^j K"Awÿ=;¯U‡Vô=6 Š5&›ÛuÍÒûëçî­F9£I@ja $D­ªæ ‹vo`a»ÝÛët«Óûë¤ ¡þÅ™ŒÝ–ÆI4Ÿ¾Q[«Ø¤…e„%\¬Ý.°gTŒæqCÁ<¥^ú¢Äà*𢩗å8j^±¦îñº/Ë÷£éý#ö1jê ëŽ$àC¤ŸZ˜Ô)‘£åîfæþƯ½%q’Ýãf¯ nd4Ši¦Zœ'š©žcÔŒÖÂ|ÉáÜ}j¾fÈdKaÉÁû… ÚÙåƒ+ƒT+Àî?íKøV/£¶%Fí©bâlÔ*AaÄ‚”a>®ÍX²Gz?¤‚Æ¢·br^Ü‚Ç9ÓChkªYz K¢¼O¯²Ö.«(Œ‰xhú2­¯­¢°#`º§"vÎmc‘æžÒЉ¶Ó´6wº‰`G8l§¹ø=ÜuóÒoØ«`÷OAšC-›R¬Å ¥w{Duª/ëÞbëV€¥×µ|ÏŸŠÂN´µ=òÞ‹iF9À(m-Ä꺉wÝÒ6 …½Žz4äçNåʦ²Í£—͈|Ò¶ô ¾qzú&ª-·è†qá¾ØÒ¾éOÕÉhJn$È)7ßô¹AáBd—„ñnNL‘Gœ5ôÙˆ}Yí¶[Që•Åñlëþ1y«ñÊdQOèªu·tE5ZŒˆ=²¨`5òÛõ|øíç¯/ZHÛV¯ÇëKr=9áñGÕžzí4ô?Õ“›šC/’\™jªP”` )¼ ¤f•ۮ찖`÷æ#b¹]Ëuê"Ø#®Ït¿.ÔgÎv¢0Z¹/öÏÆV33ÝŒq¢Ç;ªö<Ž›©t‡RûÙ™ï/Õžª=u=í{µç´š¹¢°ŸÕžs<½?«=;án˜éc8µZ¡Ö%ï#Ü5ã«BÍŒU¡ˆ»_’í]”lO Íûk²]QØR*ŸÒ)Y5U=Ã(Îlpô0 YôsÇK¸ÓäÌß"ÝÖ•u.(,¹p@L•7j†JùÛ#]Âeã…=P|2M¿Ô…¸ZÙÜo1¥äç£RΛr{¥Üf6 K¾<ͪQ ý¦Ù¯§ÕÊ­—1–|•mhÙ†ôLõ=«;àô¾N/ ©êÚ—=TºB”pQƒîR÷W®˜QEGa - Aÿ¥óâ„ Û°;i´±[û¾ÑFgJç®RØ#:¦÷J¹1Ó”ÓMß§z p}nyhtX‡¥÷ ÃN‰R£[“Ù¼ÝI‚®ï&66[ôõa…)wwïZm[{_Ä3J;ÚAJ øÛßf„x¿Ò`í?DÙÿüóò͸OÕý©%ØJ„(ع@âÝònãvƒ*É”e#˜å³Í7 ô€·‹÷÷ŸÖj5Fmv'L¼m°3+¬eö¸Ú§yÕc]VpêgGÒœßTHQXr²P‘Eš¥ÿ.dÑRØo!‹v²P‘À~ YH » YÈHÈ`¿…,`—Jp$d!#! €]…,d$d°«…Š„,ö ŽT‚Y a: |¦ÙÅ´a˜ñ¥'–D™²ÀÂZzÑOKCawº{ÝÑmÎÅ?6ù3n(WB3>·L”G|5{Æ~ôi[b܆p¤¿nKIaä~‹ ÆFë~è{œÞ˜¸ÖÊ=Nº;FŠøfKb¯÷£Å²©‚ƒ08Àî”4d8éž8hX¬'ñSi!pÍ´ÛÀôžØGŸæìP–wf.)lýïÿ‚²ÿ:¹òµ+Là>ÿb[Ï?­ôŽZC®öóÿ¶’¶6 ïs(NŸ·ëoóOó 絑ô`ƒÓßæ§c•kÛ8_Â>2,¶Kq&a» GšD÷.©ˆl·=ò1Í–:Ã處łáÄÍ;&à¹Ã²l»êÍÒƒæ}´º•ÏÕ¬ƒÄÝ{¢y—†í{)òuÑÓ²¯ÅZù¬ñz~Þ¯#…‚(±pyŒô…¯Y8·ÜáP YÌýŠO{œ$òª©·¶U­RH)ùм!H µlFÍÅ:á¶<ÛRE4¡ÙË}•¸¦Ï“#~ª´ºm',_MOãj°k)ÝO+s 7àó} û×A?ª¨êuÅ@=!c.u?lZÿJ}$pŸ'#)’¹é]¤×ñÂMþúûB:ÚÓš¹r` %|Ú­”ì ž½âþ» Š‚åbr8ß(]ùdFKbFºòÙûzÞ8É_ç@‘@žÅʱó:ŠæK4íj¦‰ÂˆØŒà¡ÃœÙ¦ÎúšÂH|tô­Tű¯"À?é£8„ôw}£ûdÑ•Ï5„¼ÅO†Ð•#i ÑúMbzéóœ”íZ/|sFãHa_EþòqšÑ¯ te°-±*‰¥]@à$}½¾³seÄÎM_ïgçΖФU 0µ¢o4 é¥ï¿ïL·G–<ÏñÎ"cxZ`P¸§­M¥>ív¥¶†Ç¹yËW b½oQò…p*_ÇçŽè÷¿“g¸¤°$® •A/Ø|9}_¾î¿TOFå«.ÑeŸÙ‘ÖùOcÓö•©^EƒŒÄ]ù Ç·E•¯®a¿½³K{,P{Èõ8-#¬éûyÊ0‚F‹³S5Väÿ¼Ï,z°-k½Žn°K# AÊÅH¹våÁÿ!íÙ‘ü Ó»­¢¡ytú>I¹`þ(Ï7wi( Hß?*Jx§Ycj¼Œ®­)E!å}Ö„Fäfv>Å‘>JèÊßÊã!?žýýýky<|ÎÙ©!ð¹<¢ïi åñ(’ä ¸j {|‘ƒ›‰\Œ‰Î›Œäà2ÚÝ3†Q9¸ìÔÝ“ÈÁ)"—º{:o*’ƒËNÝ=)ŒÈÁe”`üENNöS®†ðK®‡ð[®¦÷·œŠp?äàþ÷[NF8RyèEç¹,Û¹Ü)ôɸ«nYJPÛÈ>]E?ÂÄ{ñ°8uɲëÜ ¡/Ëæ¾|ÓWö¸ÆDfZ’‘rvDtSÑ-û{|'ºù;u•]7RØw¢›:ˆnÙ©àq@¸§©Ub úì/ýÍÕSW/£ÓPŸ´† ‘<,Âì/ûnN½vw4–e'röQ\çÏßÉ}ø#…%—RdÝTÒÈi.öúnÅjÄtQ¸æÀ³™œc>Cvj¿Aö[ed©ð¥·¿‹ÇîZ8X.×,‰d6B›æÌJÎ),²Á åÚ²ìA‘,Wƒó½4¥‚[`­òeE »êTñboÁT1 {’o!ôkußB׉øåéF€a0§d¡ƒ0bv»¢? z Ú¦PÝ öieŽm}½¸¹™h{d„²Áœ›Ï6QØGݩٷôõÔ¸·ÃÒߒ˶ÄbÎY°eBØý,龘Z»÷/M1ìR¯µ|õ·8Ô ,Î8“9Û7»e¿aÚÁ4…%_`}Ûó"Ÿ)ŒªbdìyoÇU3 {Dùñ=â©8¶W…¥ô¥°{û–ùbö¼ ø"V¬`ue·XþÕÏ@Ñžª —ž|õ&À`“ëf®uo),ùòÒnãª,ÁÈ8±`sŒ‡-º,äb;Ca í48@ÞŽ(K¨@Øý*afü =£‘q‹+öè¶©ƒubfFai¬dá¹z¦˜GV4œÂ²O‚DùÚŽ³Íëè·=IÕÇ #ô-Ø+ViÚiþ^¥iÃÅJþ.‚;¬Õ kÿ‘UÈ}ž¡š:Kn—ÊÛðr7q6Ÿ: K.jCygÝœVSXÜâŇiK1±ÒXp¢2Â"€@"€9A0û°‡?á°]Õ¥húa·•ìÃޢƌM#D_0h žìaãÀ€©'æ¯Øè+;ØÃ'–˜˜§YH „-€½O0÷ÕÏ|ndzß8½‘TÏÞ/¦©rë¼…?.‰Jo?òµ«¹j” °$ÖÌÛ-¸Zhi9NÜý‹‡ç×TK¾Uc),!*Œ5ñ‰|È«¡)ŒV„£×pw&%<#œå³ÒsHÅ:¬³‚ÄQF…þƒBh ’ެ^›ºÀ}ŸÑ iXãX•kÕNì̧ök¯…Þ8p–v´³È½ Ò™œçÖ™%‚=>-m1“æ[”ݬ(,ú…—º;K ÖPX†ÇeŽ5gÞe/K {F°a9/s {‘< {ŧXG{“`’‘·MÎc°ìB”æ!¿$¶Ü}ÏÀNÉ™ Œ!BQ»åh$¯ïá_­nd‰Ê,9)!¡MЩ¥a¹`8Ò÷™³ ´ÃGgpûíX uG5y×m‹žv'Dh êÅaYÂ!J#ù=´©p>Ù°¶]‹¤ÞBÌ©.rµªæí̧®‚ˆ›;kòu;¨fg>u€ù¾ò; $§冡šÌMHU2ƒлÿ€m[{ènç•íD‹Ô=‰+&÷{×Gô¸®›¼ÂYv?é*UêcÃ[ÕaG´ì~¿ä¾B…©›šI®…Qòe‚ŸaÅ6ÙýL"„H·°…ù¿F ÒwÒlÌ ‹fôýì¶}`îgZtîqçö£§›{)ëœÃ=-ý×:zZ\æ-_xQl……òsÀ„oŸ*u=É–Â^Ÿ<‰܉®Xòeã|£°÷&–í#—V4kÑлŸËÄ‚û!–iºÆBÔ7# óh¨ƒE†ú9£¯Ce(&“‘þØ"°XÞ5}ÕRXzªsÛèPÉM[×kî/ÁcÃÚ”¨ìkVa,Àè† 9C7!['z1S r7ÅMïÆº #"÷ìB¨ Õí¢Ú–4’±ÃÝþ4^TΪQÑK³kÏ7g”»Ý+¢—>Iµ¬ØÓ¨rª6-(3ì…Y¶÷¸tP/B§ê*+ö¾Lˆû´T.fé"TôgÉË•d–\&dÿfÈ„<£,êq:Hßo°CNaËY#çÚO”e„ç׃3ô*>RX‚UŸ9¶ÀÛC„е3…Ý?ØRMÍ‹ôî¯/mî½!b‡Z´å†ÇåûʹæÀ¹^Gµ!¡‡{–¾S|¶}ÊÇß5•¶or34ÞÂŒ`´T¡Þ äE›aZWôŸ$5jÌPäÜ€¦0ÀÒŸy(X…Çí§ØB9õ3"²Ç5œ9ÙuÔC7åq¿6ëÙƒÃUBi`°dûYGŸffw"mø´Ç¯§íUíŽÏoz8¨ÜxÜâô"‹³ea ð²GzÖⶇZX>F0R L3/-¸ dÏ( ý¿D={o6UŒmK¿³ô•hæaÙ)0|T©ô÷ÞJ K¢v;/Ûä™FP9ÎqÞ“af¼¬Ë¢0i˜=Î ¦2|YÎÉÕ²INawŒ©çHÓ²Î8æãºE/ˆù—ö«&e ï™]„ÓAêÜšÖ9G‹]),9µ¨©íü¼¶-: £R!«eEgM­¡³Rö875æØ `o4ÝŽ–Ľãö*c·¦B õCyÙazCý›ÞÙMoYQØãô´Ÿ†æ`›ÑV”-ÊÁl–Â(s4œo•Û–­h Bz1£ƒå³ZãÀ-Î(iø¸Ýè]ýÿ„]ײ쪒ü¥ÕN¨ç}NÄO÷.î׈*uÔ}ö5O­%”ÉÊì!çy=®ûžS].¼æ@YŒ¨šóÈ8§•M ‡°ç¹1gïaØúM‰Žã-¼NöaNumÌ–ÙRŽ(ì(¾’Ç+¸ÙC` `óE×Þ|“3hYD¯è‹Ìæ@e6£×Y ÐeP¶¦Cœp‹q»î*5`“ä## SÀ9éÌù'Lœ×Sá_¥®$ÒieY—`2ÂWⓊOF/öËÁoš‡nYžƒæÿ¡T/:øuI%—¥í9…=|[Û5âÝ\” ö<i‰tÅ0ѵ­‰/Áß`/ß¡x/Ô ©¶a£°èÐrͧt€±¯Ê†÷¥rãJagåÆÂSnŒ†÷iD .Qáø É2¸hô/ÂñDÿ"ïÁ¾ Ç{°³p|ã ÇÌ댻‰û¹ÙÒBâ†=Â|Á}Jʺk§ O@B¢öâ·…[ŸãN,ö¾^›±/æ§·y °Oë@¤.t7³ÁeD…ãÿq0û)Zí`Ñ¡ ®€ba²ó‹.£0æ½S ›gs–.mçÝBŒr×sÓm3¯š¹¦°Ï$™‡©)5‰‘I޼_ßùÿ œ“ý¹4ÉuQƒ¡,ânXy·~*Úi› 1‹<ñ.Kœ²$t] Þ›Ÿ®0Üã²í"Ë&P‘öÚ.2iÇ…Âî'¡±Â‹OGÉ\]g6“Ia´E§b UV¦£Ä¯„]›AždÅá¹AFšæÝ´ày…$Hœææ¥MùwÊδÅýo3°¤U†ìïL_´¯v›×š'Õ:eb£°Ï¹BéêµàëÚÄ|Ä.H{K¨›×Nðj",$~i(MmvXW3…Qª€+7®ªÐý¸€"ÂÄÀÒ“ûE›²è¦bÊ)‹B§Ûn ³Ý¬•I)ŒÕ¥®ŒÑ”«9têÝBDeA5i³H¬Ð³ÈÂÆ^„=¦µÕøxï3°sº¨CŠõWÆ|aâO[Y EYù°Ç%¬ aÏË‹VÅç¢ñéo;~m4¿6RØý+l¥°Çå©Èyÿx åço{ÿ~ …} …=¿¥ÈÁ¢|k_>uÈVŽÎQÀ&0‘iŽc‹aHÿsÚpwºöe×Íõ$~œÊaPç2R›c‹Œ:;4WR¼n;Vöð…l¨'lø.A-`Oo*t/9s×ê‹D!-Û&Ÿö³±¯¹\Y'Agì>gª›º [=ñ+Ü¢¡û,æ.Õª©(ìqî>Ï&‡2Жžâqæ‰è É£{y‘rõhÅË#i?¥a¨«º(*ë‡rônʽe@ª3{%ÇI-€ÅG/d&ç\Û¶Wèÿû`çŒÝ”ÉóO¼ÇKÕ1€M2ë!_:ä1ÄŸQzÀÁuÍ›íÂý'ê»= DíÍqóÏ­ž7¼k}¦É²-;Ë€{úpö%)ê¨*ÄÑùkÚ‹6õÜUŸ„+ŽBöû5ó*Ì:6à˜H"/v¯èš;(ܽâãpðuüÄyrµ6±¬Û–z0æËýÁ 3‹ð`D" ¥5«É[ {{¯aX2çGØFAõE/ú‰Ï3<ÜÍ÷¾0ÿßµ‹É{Í—âáî§å3±µ£éøí³°·•çï7œ›‹Þ!·Î6y˜…“'šÂî§C)7ˆ$„}dÉ‘˜ç¼´êØó¤~)Ìr¨r!Z {¾sëð"ø2/]|æ|5ß’˜ÞH«„wêx=ær›Z«æý¡Uºº4Ùö!yKD˜Ï~O°—ç’ç“:.z Ƈ•«,XvRÒ¢Z ÀÈà*xÿÚyjûߑž߆¸±„ò¾}ᯥ‰2‡våß·€¿æ q÷`_ 0v:0Í;M‡´Z½™õ>oÂ~¿¸°è ÍùoÛ`Ú""ƒ6=HoÊøûN…yû©Lñ×.Ç&˜2ÿ9êï n³ºÑnK¿‚ˆÐØyÚ/Df²VßaäüƒT”æCËùöë6»”ß.?+Fη¼¨)ìÊ{s°þÅÈfx?| êÉk1ðÜ<äŠÂbïäµ°<¼”¨-ìM)íθ.Ù£‡ã{#u¯™jC³MÅ4z8OÚMHl]Û®¨`…¸;õ}smšiZ»ºÞ¼'|{œâuÇG>Õ”ÞÄÔ„úuÕzUÓ„~]Ñ1gõÙ•öq¬Ió‚ç ØìqÒ×J’"›sÞ¯ëJKß›(¾ÜJ\ÒQP€s«¯›m˜Ò¬¤°û¥²žÔCˆ‹EGóÛdxQ?Üéuðü{Ý– …݉Ry{Ù÷20ÉÕNÝ@ÅÕª)‡$[°6ú=Œ-Sa¿[³óùÃhÉ#‹jqì/(:#Íx‡é*{ìïc9†ŠùàY¿wWd °ûÙ_dÿµÖ|KE ­tF§T®”j€=¯•j O©–‘)•Kö{°×)q)AÏ÷½ `ÑÉ@9O“M r¨ »Kæ|hMô2·•¦°ÑYAG[‘q9Ý##S*`ì`©¼€Ý©·“£•ŒZ×U çû‹³ñ×Þ¿Ù‹%…ÝOjÛÖ¦íÐCq’‘)O†Àv×¶q-FÄëÿï?® b»}9V3Œÿ1"^ïÁš+Øó4u_xS÷ŒL‚\½…¾·@ >| >ìNû4Ž\¥ÓÂS¬e·Ç©óõ©È)ìÊØ2ÝŠ"…#„åwÇ–Å®ù5ž `¿3¢üîr7…¹Çpå6©•Â^β κZ•#…EžâßÞΩ䘮²Âwz"‚¸°`ªËj =Øíy²§BŠn_”¨Æn¯kü2–ÿÞk »Ÿ4#2>ªRJ0hdvÉ4þ’!3/Wº þmìZ:޶ÿ¶p°v¤I5sÕ¢R-»„¢­|½÷/+kÛÖÍ |FV°(ŠªEµ@8°Ka^¨(/ŒÌG„Š'›¨ÖBRXxQm/ºõR„ŒÌG\ Àgy¿ÿ`nŽÝO­M<›Ö,ýÿ¶G8=Ž„aHÍ1³Rغ d.1i{£ PÏÈ4ÀqQÇJ,-3Øuì¤`Žnsã:,*ÌÝÃÉÊÃÌoY… æŒ(˜ºenÉ”kVo0tÆèЀGéË~¨F<>îA(µ/Sk-S‰|2™;^”…—အ܆¤Lÿ‚•%~½ïSóÅ}!ÛR+‡¬’Q:ò©õ®v-ê*-q-<ô€áa-ÓÉÈìq;üì°eK/ 6Õ‡?}EB»‡dÍdS3€ù÷{©kß’R’ ž€FCͱít•AÓŠ}HÜŽ¦‰ùLf "éðh£$î«=Vý#ô`su8“Í˨ð‚eP’C¹•UX_–\âaôˆ‚³>uaÙ”é$Á;=iW9˜Õ¤°³ Œ³L¶iËL²Í©@ bY ¬›ö í÷ äÔª¤ª· —ó‡1Iý/MŒ¤ô’ª0Ù3AÀÑ¿‚…µø…·ð|ÞN8ŸÔeUYT ÝÊu߃’‰LêŠÃÔ=ûpÃêu5ÌC™'´KXr•|UH±bÏP¨â3ú7Tf¨(Ìãœ!,10åÁžb>íêQýLaO¢ÇëÆOÒIôM^N’Â^*$dã¯u5¡S;À"ZýÑNOÛZ¥Æv0³,›VVMÝPX|ú,“Ä|–9ÇÏò$* Ÿ¥æ{ÓâøÞB¡síxù•åKåˆÏÍ÷/O„ëßf³LÒB®*£0"ì¬Q+8]jU¤#¬Ä«1°^`„n£Í¨g1‹Bå Ã^áôÑ⯅I)+„Ý}ª·„ riVÌØl÷žx„ê`šŽí67'û?žô{c@L¢ ³×3œ¸‡šÃÆ‹6ÇÂ_üËŒù3B7ÜKuÒéôg}ÙŽIßãæðŠB X§£(d:¨†Âî§4¶òÓØWpPbÁt3©¸†+¯Àc¤]²­é·e1ÿ°÷õŽde‹mž`-2Y0Œ\¨µ²œÂîŒÊê‚ 9g‰Dý};Œ¬0Šn×n“V(“ú&)…=<É!w æC™­0ÚÌ.¬ëIÞm\ZüµGhâ$áfáàlÁ¢gè‚àW§!­t‡®, íJXûy:vI)d‰=lƒŠÂ°Vš÷˜}DÑ™û¾”èt›-9…Ý/Œê`|¸Iׯ@açcž—¹¨r 0>¦ëc¥°ûÉ>¹äZ³+½¯éUy.ìörHŒý©_.UCÞpPœfìöó™Ð=­<ت&ï5‡‘äEÚÀ²€ÀAY5%çÍCÆŒùB¾¡U3T²h*öð·è¶è¬èS {^ ?«…Ÿ{|Wt–U†ÇŒ=ÏúÐŽÐ ÑñÞ{…ö{ÒEåÌ>ìN™ôî¬Ïó¡R¼®(ÌólÞ³âÚ¼ÔÜ,AAaD“<•`n¸˜—ßÎ…½h¹?uµòÊÄ–"Ï)ŒxÆàÀ}›¦×µ¦0v‚µæ_ÂbfŒö_›tçÁÞ'Øþk! ˆ•@dÙÏ;³Êyšú¯D—°  ­¦I– ÚÊXt„6~ÊØ¹øºo«®á¦ðªqøHÇ'ª†iÕ”P]Ððäò¼Î5e2®X 2W¹)RRØóô¦Þ¬R®Ma/ªñà(*o-ßÛ»…èzî:M 8ÙûÇxv›`P@ØI—NŽpjvÒ¥“cAaÇöÀ1{n¬NW7Á” £®ô‡g¥í fÍó Ë¥ñÝ/'hy¯…®¶Iò{œ»2. ­è{²øñ][rXQ[’Åÿ"+ ›tü:é!ƒÁ(Îaqt-œSxÂ9Œ°SÎÂ9% ç0ÂN9 ç”(œÃâ@xiæNóÖœL ^Íb&=tbªDóNàEOÞdæJÚ:µ§ …‘L ê+C×7²Ì1±ˆ/$OwÚõœ#ŸåHawÏ•ÅÕ0Ô²˜Õ:QX@¼Ýÿ6-4O°|õþû)ꃑ/iÇcä»?Þ~hg¡ÇKÚÊÿõëRBŒ)ê`±O[ÙÏP—Öž¾rj)Œ&‹N«Ù,R>å+¾…w0ohÍùv~U›uVÉžÂî(tœà”q? ó˜ç@Ge¤­ì‰¬ˆ´‘öi+/ÿq L)PÉ4—³5…y"+{ádë¦jçdïçïQ,xõ§f¦‹AM𢬩;´ãÙû_¸êð½Ñ.åEÝ‹aïø«Úç»×ݫ樻¿ãs%iwâ¼_‘â÷ö¾Pı 0-—UwmGažÁèþ²f=§ãˆŠÙìíÓQMµð6Õøïï÷¦ZPØÅ¦ÚÐM5&2‡Á¨S˜3)T9A5:þ †jØ{ž4&Ý…4%þ ‡jvÑÚó2˜è´[£]j Îø/( »J’YT«² ØMQØ™6ÓäU]› ©¦0ê> Â`J,»<À‚ê ¥ÈÖT£iOü&-\€á™öÄÑÉ?˜ï#a¾Çì7ó½ °ïÌ÷•ÂÎÌ÷Âc¾ÇÄÝc¾7ó=&~èó½ð˜ï»d¾[å¡(Œ]ª 1éÇz»…'±Ó~ì•ÄîJag¥ñ¢Ñ"W˜QÆjàѱ×\·Ÿar<¾…æ©Ë?,]U«/úÉÃMúŠR7²6y-…}UWnF€Ýσ,{Á©lÆ$ŸðëýtPá¢Pñ•ru7C ¾=‚)có[ JàC%ðøö¼.wÙR‡?¤Û¹îýŠ¡M;ìWħ.%°¤‹M—¼l@+4&]J(†¹|¡«9—ÓŠ+ëÈÙ’ä®æ=È\ë|„­æÆNc×ÚÕh[)sÉ; £lUpÇÐs.’Šã-œœÝgia:)@#¾Å×=¬ªÂr&ÍÌ£öã`S=åªñýïªÔa6‡^ ›a·ïqosĽñÑ0<ÚAî\èÛÞ\RÃÌr|t¡ÖˆD’¾5Ÿe/¼èó7M/úúMð`w'‰T£µìÁO3¾¢G"0ÌÛþ®a ¿€Ý/‚¬ÔÛ†g‘š: -K¯þ¸ÿ$ÈÕVD!) !rN@Ñ^®ù“iªjLZ|g%–e%–øñüÍ2ƒ/„ôî<^˜‰~/,&½»³¹(»~ yî?7vVhw ‘jMæœbÒ»;‹‘ÇÆ–(ÿb³¶6x Á¨“Κ*åfUxá-Á––!¬hq·|þ¶è=tϹLò¤‚T1ì@?0=·u›áò¼]Ì☵v§‘…=|ºân&ÎÓ½DDaQùhÅ sÞ˜}ÊçÍ÷YF5'ݶÅÒg A°è4?j.jç4^ôK[g¼Iù’ev?ÕšÒÄå(àՇަ˜bO^Š?Ÿ?Rl¥ ûˆŸçÍ£ÿ?ÇyJä_.úÿI½RØì!™rb:¯s¬¿ÅÏèg j5ñ“¨ì'Êm-ðN:ù ¬´U/ÍáFa䳄ÙÖb“]%;ŽÛ;ÔÞ†º{©Š-­&Ea÷kØ(¬Ò \QYyOîòYòÃÄ}üú»EÉv‘жMÍÿv»žW6°¤U5Zö1S2ÒN–s ªÏñëËØŸ´¢|2/g »û ”í .Ý̜׭9`ð³&Û*'ïמ¾åíØ/Ël–Ìq§÷ëh޶-QU1QXtûëìxÕÕØ#| àº×ζŠ’ð1‘Xù/Õï³çé–r[˜½Óþ×? H+–Vm}]W’ž”ä„GÍs³óF°E¿.Öénð±¶yÊ‘`¿ˆ »‰jã)&™Š×)éÇ^¹cÁ0&ýØK¹z_QàsäÞ•Ùàìé°âscßa¶ªUwد8Ö㔩^g¹Y‰8ò{ì‰Ú“ {4ȱSîäa£•þšR3”tâ(hâÕd^=Œ)…yÒûgY¬K6ë«QPšP`©f`c¯ëÎúèqaü´ŸÎëPØn€=OL|09.PÞŒ£çor¼Óèõ›„°è:_Âä :Á|!b×0­}Xü£ý8`û1ŽÞ?Ú ¶ãè}R×õzžðNÞgÐ¥´8èyú]Ê»”1»ýèR®Ø¥ŒÙíW—²„.eL|Ü<}’ÕìÖ«L µu‡ƒí¾¿|Á›ÊþæÏ?:ÊÌ"Å!Û“žçÕ¸Ÿª)욬"pÌÎ#×ο:idŸ§0m­Q’em™I ?ÆÌ (›`šòy†ýíhÉ!-Eº[˜»åÿ »–¥gu$¹Ÿ§ Ý–½ŸŽè~‚ ß>clË_ ÎÓ` UÉTù?g™¡Ï€TY•Y’»Ý»»@ØÊuoX„1vý·Íª×]a.ß6ö‘4íþryEÚ]l¯åŒ`<'ïàq³×~m>¿·1âw»c¥W+rÑr$à@­ÜC˜ÈäÍ)]in§þ > ŒªUe;Ä^«e»‰Ê¶µ*Kh§¯ð7äµiÛ:ôéX«¿VªÃéaÛÖ‚5|¿pXõ–ü¦gpDžÍ<#àµÁ;¿lvç×r™Wƒ.ó²pÓå|×-ØÍ3>é&¼^'¨+/Λ)Ú„oêäWûX¸Aì|ž &Öœ”ÇÞc¦ê*v"5a†‹duß’‡0|¹òœ8ŒEñá臰 “Û ¦þÍîþðñ…˜•SLçŒëØîýαήl2›~Ûß|BØáa`ÓOܲöºï»~Õc—;E»wO×ÝívÝìNV}]4öÞNç¤mÂ)XöË— 7Àn›ñwâ•ï6Û=6—±SÄoö}7F·îar­ðÜÛík aUz„pKÌXèîSÉ aê»ðÜnîÇ1wÿŒæŠ‚½(6œ&⊒¾xä¶ý›®<¬ƒ°õûIÆŠ2ÜNë ±Þ×>×çió`€ÉïÀ5_Ótéž×wÜÎì ÌYó¡óDºî¯Ý+\-àŠü„î°d¶÷Ãmsß„S¦tyÒA…sÆåy>=!¬Z»ymœâû[ü£*K?—±6]S¿ßÇ!ަ)ñê|;Üþñ›šõ“iç³GúKð>ÆuïÝûù~ƯྚNg¸Ç"ÅåW!Å3ÜÇ_9\Nu¨ë]Y¬ ·îµ;õïгæ ÷±RËœ"LP\Ó­m #WJv Wºr•(çÜòymŽÁýw`¿×j#pümÕúW¸ýoÓ“¶¶öég7¶™Û)ãoÓ+½ŸÃNýnw ›£°!ÒŽ™¬~´·Ð¥ãàí:°üŸö¸LÕç+À,Õ™0޶¹)Ìe·ë,ÀcŽw{ß6·0ß²=U)i¼Þ_íý$' j›Î˜èým‚qàDÞ\[\°¹Â‰ò;=ž—ÌÆÿÕ»x<ˆ"¿2òS¾·ï×ηáôWo1™>ý!\¼^ÿ½îÇ6”ÿN]cºòwœBÛy×D¸|¢Þûëµ}Ü<„UøZí©é¾Ým¯›ú`Õú «ãDêûÍC„b~è‘tÐûøÒÏQtÀÔXÕ–Ÿ uœd<<f¯°ôŽ™~Ù1ãà¾%hz´cƉìè’tQ,l±w’hØoPþ¦jCüœê3U—LÿóojÆÜC¶§;)¿Õ¼yÕ~ü“ý%ĹvŽ÷Ô¬ø:IÞ+\ùí$±úÕ¾|Ú?í$%éLMÏÇKH0œ4ëJãXȨ̀€”– ч@Ò}+´s}zØ<gŒ½U±Ö~óÑ{‡¿G¡*)'eL.7þØB„í›vhw÷#‡J®Û7cÆå÷çwü¦™œŽ]l¿LËJq.v\l¶­:waÉ€-Dk>`h 2ø\ÅÙ…]ßvá°2š„°YGÛž^—°ŸÕ%|Õkœ*é‰t8,I 6þ[`’Ù âcˆSüŽÀàÆ:¥ò÷öñ><ò>œÒ|VŸ”8 c*c/Û~a–RWü­>O_.ö¾ñwóM}„ñIA/czq~½‚¡ìTv÷ê«i–÷¦ ê·M•ø#(N—ëû¾{õÌ)œç´ ²šÝùíï1«Ñ’ÊÎï÷æÎÕpPS]+yÂëbé?éHíIBÜlÿ^ñ|—Ÿq»$?Óiv)ùÑßß4H—o˜€Ûéæ$i»Ÿ¨dsØC˜üÊÇß6¦K6¨íú{›áÕŽÄaßÙàÞÞÛý’ æënŸ^w¿®÷…4vÇ6g÷x¼ßo÷I¼A˜üÊ-çß¶¹E2Òàÿµt%L$S|oëÿè–Ï©¿…Дß)èÇì»ûads滬?L÷b,eÅÊ>[Ê #×›<Ÿ¯f¸laƒ39Ë„>‡i3h¿;ÇTÊ(¤‚.­Ïþöyæ>VvÆm¶ÃÎæ_H~UzÐT»±x ©”±ë·ºL&öqLDC ÅÒ52 ö¬R[X€¶d8«YXÆ ¢ws–ý:$ì‰o§=ña“™³’Ø:?ÃÆè`ÕÚ#ÔñB‰³_m$Ÿ;‰ÚæÑï†w¸>ÃY½>‘¦=|ûÝ>8ÅΚ¯'ùÔc>µü&³cX2ßóŸÎÒûåuÃ~ÍÔŽ¨[:W®ë– Ò-£.í|ÂK;ëGºÞ7¯ûý·Y;—ŸJG»¿§Û²â:…g£eguîÓYÎe»cÓuðtMçª¬Ú £_¯Íøßø LåõB< vüqËîçð-_'IF.Ç6sÃ|Û×~³9,åÐTWŠ”¸W*ÀÄÿ4S‘òÏC‘2Ö¥uø7‰aîÿŠ"ªƒÍkÆrfói¨›ÎéîÃü¯ À·ËÛ×å3¤‡ÀéOÿëã6†ãi¶mã7¾õÛ8¢XF\žwéÏÓ¦˜”ôŸžŽÏHÀŠN®vªù©Ç©µï¶˜Þã0øahþ6Sf’€šv›æ†N—ÎA ý¼ðüû|Â~’Ho·'ºð?ÿ À:¯ç úÓe1!Óý ¦õèÑd%|£Ù.¦o4ÉUÿÝÍÂøü5õ¦4õzóBÒÈš¢¢z‡§¢‘xLM#=~K†FÞðYÙzü–Ü9ÆÖÙv™^è„l.ûG—,äõ•#Kˆ<þEäéqÈ‘byy|)ב×Ç×ï¬Ö‘÷Ç3Gª,ØÌ1¤™‚Í~ؤ4€£Ò Üþ (Öâ\3þßîîñ UiÄ5à_€ôˆ%rV àß89«…òÈ9=LwZ"g•h gIL~ŠfIL§Šâ´1µD,©)–üKj~ÄÄ’šbÉð§–ÔKàÂ’š`Ézþ2€%5Á’ `IM°äXR,9|æcúÖšbÉyR€o­I–l=fIM²ä™XR“,9#Kj’%g$`IX2F¶1 ‘­i@T׉%ב7ô6KM!AT׉%בxLK#—¨®K®#oè‰DA"ST׉%×£z‹× £z†”tTÏÕ3¤¢£z†ÔtTÏæ;ª‡@˜¢º!¢z¦¨nVbð)FÌ~s>ÅÜÈ®DuÜv-Ò#v5QÌÓúãëTToO~º])Õg©…KB‘t®›¶i®¨iàó†>öhDK§ËÉЭÅàó„#y¢Ã<áHžè0O8’':ÌŽä‰ó„#y¢Ç<áHžè1O8’'zÌŽä y‘<Ñcžp4O4˜'Í æ GóDƒyÂÑ<Ñ`žp,OxÀŽå x±<áO8–'<à Çò„<áXžð€'Ëð„ûÉxLŽ'0’ã Œäx#9žÀHŽ'0ÒļÝÅ<.!dÊ™/àdb ŒA&ž5MþédâiÓ$0™²X 2PÚ0OY¬\¸¬,V‚ .U¤d3E}€«’ÍL^ø'Èôóc‡Ð1U<ãŸ>ÜÑßAf ùĂ̂ ¯rDîû+FJ ù쳿&ð> m?‹bhî'<…‰|0RSÈÇ!ÓÈË #-‰¼î1Ò‘Èç!ç ó¯IÌÞ~NÈø|öGûx´Çø–J°|¾€Ícˆ±°„ê0¸¸çŸüÓÝ+8Lw•'àGÙä貤8z&Ž.KŠ£g`â貤8zÌB!G—%½|jÈÑá…‡åó°(&d7.Ÿg‡%‰<=ñG$ò~ÀHI#Oø¯WT¼“€l^=¾.$óê®ÞtH©%íc·»@ ™W7× ªïP]çt" :©s:‘Ô9H‚NêœN$A'uN'’ “!§IÐÉÓ‰$èdÈéDÒÚ¦Ik#°?lNè…¯ÐIÓ‰¤è¤ÎéDRtRçt"):©s:‘,´#`¤"‘ÏFRtÒŽt‚‘†D^^iIäu‘ŽD>ñ³è$›S„©"bA¦©Y± ÓŒã”SXc—œr:À—”Óå“/a¨«»î€€š^÷hH`¸C ¥Oô§ãÆè¢~y ~âÕ?m§duð¾^Pw¿g_/ñJs#ŽÀX•@Ý]ýÓ Ñuw‹½RÓA;tÛM?@ ¦€Í¦»@ ¡€ýfÓCàzFÐNÍa;4"‘PàÄMšÉÚfÓìc-^j&#˜—=zADF0#¯xLI"Çê!«õIÙNÿâ;2̤œꉀ–11П¶d•ç1Ñ;²nô˜è?b"zGÖ½#ëF‰Þ‘uc‰Þ‘uc‰Þ‘uc‰ÞÑV?&zG[ý¸nttÝè1Ñ;ºnô˜è]7zLôŽ®=&z÷³nDœ­1’«1’«1’«1’«2Ö8íÑò™'÷hùˆ‚Ì“{´|DAæÉ=Z>¢ óä-Qy²GËGdžìÑò™'{´|DAk»hùˆ‚ÖvQž, :OîÑò'÷hùˆ‚Γ{´|DAçÉ=Z>¢ø™'?’Ë“1’Ë“1’Ë“1’Ë“1’Ë“2Ï“S'Uê0%ÙaàQ‡(É: DIæÉuˆ’Ì“{Ôa €ì’5`ô¨C²£G ß-­?Lç™Ì@¶¥£õÃa'ŽŸ»¿±âìÄö±}·¸*RôÈNŠ”=zd' Ř‚†"íÄÙ‰BqŸp®P¤Ø!;Q(ÒNì(i'vÈNŠ´;d' ìD,öHªš”*{$U MJ•=’*…&¥ÊI•B“Re¤JA&=’*]˜ôHªtaÒ#©RÐ…‰GR¥ÐLs&”*S˜ôHªLaÒ#©R0…I¤JÁ&=’*…^“*“œ ®!Ân¦°kˆ°€)즅]ÃÉCj‰†nìš+ÿXêû£ôÅ“°Äz23@8b… ™ 7"\aŽXaCfG¬°!3eØ™ (Ã~ÈÌAöCf²&ÊÌá˜Æ.Øþ,µÂ†Ì ŽZaCfG­°!3„£VØ™ÂQfÀG®Kf€,X0™²`ÀdÈ‚[aÀ +î1•–ůÖÉø§Ë_­“gÄšFŒ@Á­YÐŒ)™ØxÔ'%%™ØxÔ'%™î×¶ëA2ݯ#0­0Y±#¦…#+ú¶-X8’ÑpG`Z8k¸Ÿìâ“S‡)_‰®Äî70j¸k¸_À%±‘XÃýÆÄFþÒpÛøz~i¸±+BRni¸’ÒpëLÕšh¸’ÒpëLÕ”†[g®Ôt G®Ôt G®Ôt G®Ôt G®d:tG )š äHÕš äHÕš äHÕš äHÕdª4Ë×ðe& Ôðó& Ôð­3©R;À·Î¤J#¼uC;9-ІvrZ íä´( ÚÉiQ0©¼É< ׬%}׬%}׬%}׬%}׬¥Ë¼f-]Þà5kéò¯YK—7xÍZF†¾Kxáëå ^³–)oðšµLyƒ×¬eʼf-݉ѣN éXI$_Ž•$@òå8U &_Ž•$À[wLyÓÎg)}€UÁ™H6(Hž]’¯êÇ~Ñ%ùªJ*7ÍZÊ+ªõeÈZÊ+Á¸h@Ùú’µ”WdëË,h%Ḕ4íÞP%( (ŸhDC— Y J À$+°_teoM*à+IðÙάŠÊvëlgV%)VÊvfU’{á €¯$[À'¯²ªØù˜ÜÏŠn–ð¨ý¢RdõåQûE¥øÓ|TL@ó‘Ó$Ñ|T$i÷¨ý¢R$i÷¨ý¢R$i÷¨ý¢R$i÷¨ý¢R+ó1µ×¦ˆ[iº÷m¦ˆ[iº÷m¦ˆ[iºßeœ)âVš«•@Ä­4è}ÃÒŠGòOeHùÇ#ù§2¤üã‘üSRþñHþ© )ÿx$ÿT†¬<’*CV É?•!«äŸÊUCäŸÊ0û5 ü^øjÕà‘ü%‰\䟀$r‘RÒÈþëÕŠ‘íÅ­,¥Fd{q+Ë7hDÇ7hDÇô’@iEœªÄUÒ#VR%ÉJ=b%Uò#.¬¤J’•zÄJŠtóf`škªäeåE-VâG–éK R;èQe£$©Fô¨²Q’T6J’jD*%I5¢G•’t\A•’t\A•’t\A•’t\A•’L¯T#”dâ ªl”dâ ªl”dâ ªl”dâ ªl”$eåi HlÙWú.‰"S¥pIlÙW:Ab£*n…ÄFUd¢Ý D[Ud¢Ý D[Ud¢Ý D[Ud¢Ý D[UTb“5ò*ÒÝÎyéng¼J1‰6záŠI´¡»­¨LrÈy•IY#¯¢2É!käUT&9d¼Jq"0Èñ•fT5(ÍõL‚ºX®gTÚÊ0mÐkP–iË€^ƒ²´}:ƾzÛF.v´!;w¤Gì—hê8•qÓÌq*ã¦é8Î6GJtÁ') Ðkœ¤4@\1Ò]°ÆIòôuAŸ‹\ Mç4ØÒtNƒ] ]ÒÒr4ÓLO ¦¤\ Ö#H—” €1è’r>À%âê’r0F\ 7†áÔÙ£ÔY 2uö(uÖLÕO–.*ÍtQMÀ¥‹Js]T°/Ks]T°/KWÔoÌŽyЊúÙ1Z±*_»D3­yUe‰Z³š\*òµaU¾TäkÃŽ˜Š|m8Ñ ùÚ°*_Jù´ùáiGžÑö‡§yF[úa¢ýz¢;"x=Ž~=HÑŽ‹ðõ8²—qn"XúMÁQè4k{%Š3%k¤%Š3%?âBq¦dX¡gJÖHK©«¡Z=ƒè”^ ÀL¯G0¬}FÃ(ºÈg4’1ÕSF2<}FÃ(ºã{L š‘t¢‰|F#éDùŒFÒ‰&ò¤Mä3IðLP –ˆk*2âö(⚊T@[‚ùuÂXlt0t­Ð£êòê¸TFó#.Շь «£™rVF““£êÃhrRxT}MN ª£ÉIáQõa4]} ‡Áö¦êÃ0;¶>±â·¶¿ö€5HVì‰gŒc5€Ä3Ʊ#&ž1ŽSÙÏÇj‰g ]+x”^[ºVð(½¶4Ïx”^[ºO®Géµ¥k…5YÙ‚l²êPzm ²ÉªCéµ-È&«¥×¶ ›¬:”^Û‚áÉÓµ?zùÕ×–T2œ¥×–NØqzmé^¾¹ÝhaW+v »ZùkßdX\¶úµoòœ‰ߣúe¢Ÿ!˜¸0°šY 0°š1eV3KfV3KvYM›–(°š6-Q`5mZ¢ ÀjÚ´D€Õ”‰>ïH:…¥»à{Ôoé.øuÁ[Ãì\v…5œK ì kX<Œeu ð0–Õ)ÀÃX®ú€cY<Œýå½Äßè~y/$Í®Ä׎7»Rà³ 1—cÌ.Ä\®dGLÌåhaÈ#ærŒÙ…„!G C b.G C b.G C b.G C b.G CA¨\xÆ FÆ Ï8ú|UìNÒ}b¨bw’1eRNÒm"¨bw’K>@ׂ#¹™;TÀÃTlÏ x¾‹ãñ°'‹Í,@ ìéb3K4»ö ØL˜”¶Ò,;¤´•™ˆDºŒž8O³"F‘xâ<ÍŠ¨höw&^\èYI»  !žfU,4^®Š>f,HYB3H¤,ÎíùcÆâÜž?f,ÎíùcÆÒ˜Ž‹s{ŽL5@ 2÷šíI {¯ÉZ ‘JÉZ ‘J‹y|<·—²<æññÜ^Êò=½Ç\®h1åöHºÎ½áÃâÎxoø°¸3Þ>LÄd0|XÜï XLàg ¡hfEd ¡hfE„`ñ)+#ˆ§HYwÚ9Ùê¸|t²‡U;eG,1Í¥•>è+Í“¨‹ÍkRyuÚyM*Oã#:M*YP“ÊÓ¨ÓΛ{yºC°Ù;“g{¾áƒ’B#ќӒB#Ñœ³øƒä ñx²(0íó|/ÊΚïåAõñ6;àîÃÞB`XâBxšG®+ôˆ§y<.Å›Ry<.Ågy¹gÚ«=»°‡@JªObú#P`†Úò…ÌP ±×NH‘jkÖ’<£5Rdò,>¢<‹q¤@ðá ùžQakŽ_p‹½† Îâ1qÖA›ò|³o 0#âö€Há<·D ç{ "æUàb/ADC ¡‘ÂëÊ‹ˆF ¯+¾®pÖÑ×κŒ+H΀ä{f³}]y7 ­=;•*¬=‘ë ]¾©ˆ\WèòME4X è="¬ô‘íéfÛÓ)Ì"AˆvÄ|/q€ÀY`œï‘éGÓ=±ìÄí g†=°ˆ3ÃþÓEÔÙäE³(£î+/šEщfQF¬8¨›‰2ê¾ò,—(cqðr‰*æ/—ع®N{…e¬(’ÝÌîL‘îèfv¯‹4"ì¡™BÆÙ ›u±s]f_ì\Wg+,b ÃG3HŽ’Òh 9”¸Ñ@r(ËHô¤E$ú ÒBì)·×{‘Òn¯‹xˆ–³âŠ2¢å좌»÷Ý;STq÷¾{¹Š*¦?‚g¸Lbú#x†ËdÇú°ŸŽÇãÛ5«Ž[Æè Ž[f;Nd»3%Ûq"Û‰Çã  tŠ2¢"•«Œ¨…Hå*ùž|´¿QìÉG 2Õ­c±C¦ºu,b œuSà¬Ëˆ¤€ Ruù‰½´b<ô•U²yedO•îE^õ 5;Se{á¡ ÆÞBûi¶÷¶QØÝòä{~.ÃǞNJï>öfUÌ”‚ze'7\3e'7\sUÆ´ TULK@UÅý…VìeÑP7ðÄeIñi KÒˆOhY’î˜{æaÏ’lÇÜ3ªB–d{oá`€lï-l 0àg—'ß ðÓÓ{ì¬ùžÞÓB`Dš¹½;ÒÌíµˆi^KÉ’"¦x-%KvÝ€öÓ»n@ ”F*ÁoŒ½3àåÊvB‹üoÜ -ò¿1Mö(;bºG‘h¤" ü뚥Y,²À¿®YºsgÜ¡HwîŒ;f)Û Ñ2'<Í÷B´Z¤¼#˜uL72¸-’n×óçøÀ’>‡#šLø¢Ó¥xŸÑ‚/Úe¼Œß#B¦Äå}Êç}|½h¡k~øëŒ‡·BÈ<ˆ|g¸h—á2_/Rú¢gäñˆ¿^P—÷f#Ü,²¤/©$BV¤@¸\jtÖûžΧyÓ§Ù»s{yNú :ìËE[®äŒ¼,Ë4#oçæÜ¡#—e¿—w^¥÷pö—wE²Ð5ÿÖ÷áºE†;3ÎÙ@ýɾ,]PviKr±› LŠÍ¥l§K©¤õSˆHkØ¥Icü>BssŽ&±ñ»±{ÙOs *ÿÌÀyÀµ™áØ>ƶvz‰ËW\€ÇÓ´Ùæ}ë~ãëÂáY›•®±ƒÀõ ÿï¿éÓæ•˜~c÷Ñ9¶Kœ`v6ZϯûI# 8æç‹Yž¡è¡;=Ђ'igóZÞ½o‹)¼:ÒMç8¨o‹ÇÌ *j„õEªþñx6_„d Ʀ?‰ëöüYrQwû¬ÈºC'cEÓé÷çj*i õk¸ —þ"Ø\ki#ò²Ú h¾kg’ó¼;ëAWVÌ6¯Ïuiò;½úe-4áSÙ@¥OÌ-:f`×<Ž7ä$ðs9!Ñ2OsÊqmÅ 1~J¶îü#TÍÃÔÍìF¯Ý#VÒÔM7iÝ/·7%MÝLÀæÑŽ(ˆßxŸ´i;bõý"k¤g}<" 9ë¦>| 0Be+Ûá aÏK‡LÆŠö¼tÈd¬hÏ˼Ž/õ€À’¾šLE,O«äÕ¼  àHØ ^ðÉ?Öúä1›J¤™KÚª‚!”†°J ®CnÂ*%¸¹a«”z 7 !èG‡) ¹a7ýè<…!7 a•FÂÎ1„U£¡:y=£)†°¤Ân8Üñ‚'ÔBz°Êb[ À*‹o3«,¾5îÉ®²èÖx†°ÊJnÂ*‹1„ÓÙíÜšFâ)†°6ÀŠvx2ôÖxs©bñ­qæRÅâ[ãÌ¥ŠÅ·Æé° Ö!7 aÅ¢[㊠¡Ü0„£ÂN!†°bC8¸¯Xœ!ìÎè7’ a7œîI1„ÝípÂHŠ!ì†÷#©°©cíbAµ¥@ Ö{úw„@¹Y»Œ,5éIk‰[ „)+Ud';k'úvŠ› ÑópÒs,¨“.^blî§%ºÔ†¡V¹ÏÖØžÚúÜÊn„À" z©Ã´ëhÖ%ˆ=_Và]žŸ£<Ý!°rÀóª/­ç›mÆÿ&…ó(P·¢u Ô­è@ÝêVt nu+:P·Gº¨Û£@ÝŠÔÕ(P·¢u{¨[Ѻ= Ô­¼‹?trªVÆîTÕÊø]ðªZ¿ ^U+£w¨j%é1TXU+÷œ¹-Æœ¹sæ"`Ì™‹€ag®ÂªZ߯ªUñ­ñªZß i;ZaU­Šn PÕ*Ò™«°ªV‘ÎÜ«jéÌí±ªVí9s[´à1g.FÆœ¹sæb$#Å…½8 K J\Ï@±Ä0Ð× ™ïçrXiÿs,–H t9H,Éè>10‰ÑÍy׎Íþ7æq ÿ!RÛÇéNÚfäˆþ7 ÒºÒPaIz„%i†i¨‚ £ú+»Çƃ²†*ˆÉ UŒ‘ ÆÈ‹cäÆÈ  © £iã{°›]Æ]6„Úú]þKªè©p1K“(Ð=Æ,Mâ§Â>ÆHŸ 'SÒ$z*Ücl€œÚÇØc¼É1Þc¼ Æx ó&>Æ,Mã[svÓNã[cc–¦ñ­±1ƒ]w7¼‰†1KÓèÖ¸ÇØy³ícl€AÞ¤±–Ð?ÆãM´à1Þ#c¼ FÆxŒ$=£.ç‹¥ž«aKY èÓpXJ§áh˜†c€A–^Ã4 ²ô¦á §€. Çñ}Kóج}Kóø¬mŽ’³váLÃQ0 ǃΠÓp P@Ÿ†c€¹Ž6 ÇKhÓp °"–LJ‹³”Ç܇‹³”Ç܆‹ ¹à.øÊÉcæÂÅ >f6\ÜE0A½ëà^ B•[ÂTá^<õ °•ªá~ÑÈàk8Ÿ0Ç¢ïfƒJ'uêp‚@N›óýFrÖà^(>a;¢l®/ÌÈOËÏõi°×eôÓÞÅ~Ã@kƒ€ŽÚø<Ž8Ÿ‘¥qÂGœÏÈÒŠ8á#Îg4ÀЬq>£Nøˆó S@ H+BŽ8Ÿ‘eIlÖ@fI|ÖNfItÖþre !H%Îg4À€ q>£ i–‚tÄùŒX’@'H³„¤#λaY[p H³4¾àNfitÁýåÊÒè1ó‚4KãÇÌ Ò,ˆé#(,>½µ~ºÑGP0P|ú'䩃b/Ëè@¯н,£½&Ø[5èÓœöeÊS 9k-Ã@ìÐoô‚ÈNÆ ÒŒE©ô,Ë£Ÿö‚4ËãŸv‚4Ëi–VJ`“íÎÒÍÈ–ÑˈÞÒÍÈ–Ñ ÐkͰ’öÖi ,#­q\¹ƒe%åXRCÀô 9f w 'Ö!`€‚œµãh@ïЈÎ!À@ïà§­CÀùiG°$úiYÿ´;Ì¿38êHâp9Ê‚€>\޲à!  —c,"qa¸c‰ Ãå‹H\.g€‚ø>\ŽÒå¡É¸p9J—gmÃå œµö,‹Dd€p9 ?ì0\Î<Ë臆Ë`Im¸œVÄòøp9*»‡& ŽÊîÁ1\p/ì‹3ω1?f6\΃±Ì 3F¿33F¿3 #?íd8£ƒÇ5 gŒG?í‚Ç ‘¿Ñ`P§Ð0xÜ9ôÁãH/¸¤"ºà.xœ1_p®ŠçtýéyD§sqNë\È#Æå–Z&ã‰\.(·Ô:kGärA±©8Ešñ‚R¥pŠ´ì½§H £€ÞÊåaåŽ8EÚ9V./¨Ðeœ“ÎxIX¹#ÎI7@rÖžVàeôryù·Ðßë*¾×þ^WQï§WÄYg3К!8kG€Ö a %D¼îŽ¿3d¹xtו.¿”±ðv Y.ÞŒè—'²ûÞü<Îî;óCPˆ×jfBD?ííQÐQ¢“©)+HA)ë ðhi¬ðôLÜÇ7f䈇ެc‘L¥F„O‘Æ€€ð)hæ\#§ ™s…Ÿ‚fÎ"| š9Wˆð)hæ\#§Ȣ³ö„O‘ÅgíŸ"‹ÎÚ>E‰Éƒ„OA3ç >Íœ+Dø4s®áSÐ̹B„OA3ç>‹-8 | _ðÉ÷„OÁ¢ÇÌ>‹3Gø,êö÷ºÈã.qw¯‹˜:#H)8ÝÉcz "ztÛå¹í‹ˆòÜöEDù@nû"¢| ·}Q>Û¾(h*¹í‹ˆòÜöEµ×öŠ˜òÝöEý´W>Š*þi§|U4Ú?qeB?qˆÜ+SúuEä^™Ò¯+"÷ÊŒü´B{ÉâF®ÿ4#?­ÐÃ^æÑOƒßH_.…Œ³’ŽÔÈ8+é˜A…Œ³’ŽTÈ8+é˜Ág%3Ø#㬤c²J:f°GRIÇ öÈB*é˜A…ö²Œ~Úß™²ŒÚÝ™’Ì5œy3`œ•¤n6CÀ8+éëªqjÒ„€Þ8++R>*dœ•)2ÎÊŠ4Î42Î@a˜ÐoôÆ( œŒ3Ϊ$¾àÎð©Òè§½áS¥ñO;çŠô¤CoaE‡°iôVt›FoaE‡°iôVt›FoaE‡°iôVYä^÷°¢CØ4z +µ¿×‹.¸ «<úi¯«<þiw¯«<ÊxÛµâQ‚ÍSM§}lˆjªD”jòFnEå#Veè'S‘ùˆ å#V´©a>bžÐ¾J ßÂ]Æ9)ÿé2¢›I8ë*þi÷YB«\hYºÉ°,òÎÀud­›¡ud,ª›ùóÈò¨næÏ#Ëiÿ :ŒÇ?íÎ#ä1Sè-dEè'S’o¡Fo!+Éó¨Ð[È*RHi$ó$Î8‘’'¤|ÔH>æiôÓ^öäYDÀ;“³¸íêŽYÎ"²Þ™<ÚÇœ) Ý™\Ä~2ED†Ã;ÂÈ‚#úßXFõðé*®÷øOW‘;ב'ñO»ß"]þ÷ýoñ}ÜlÅàAíw0;ˆKq@é€÷ÓW ˜a q@ úxÿžá“k;ÉÜ÷ûý‚ÀU7[G<ÉåG.!•õh{ ßo8 ¸u_Ùâës—…®þÎõÏkÝÁ¶m)i€e¨Ÿ·|>Ænx| °²‘’G)ùÒãu.H©ZÄÖKqÄn.iúnÌw€GÄ=%–ÐÔxìßõìš×å&DëËuµ%›êáfbX p­…¹ÄÄÍ•4æ9·d?Ü›{ßB pÀÓù$—ç–ì]/,ð|2#N+ø¼/íCC`ö`ÒÖœmÇG‡< "u™ZäÑM§½OæëgB^2sÈóñt].â]}¹<ÐR®µ01òF®¥J—ê.˪ÏQ¹CÝÔ³#9DÊ«EŽß¦>£eO…ì·È!×­¦»óhê[f‹þ¬¿s–˘Ý0º!+ˆ\ÛÌçh:˜õýˆÎz‚‘sÐù¨MÀ¶E¦y›¿¿üÎSszà13‡œvs]ùùp~.ª}à1D®__Žñåü²¢ß s‹<:ärB&äã‰fþûsœ£¶—Ék¥šQ)U£õÌ„C®•gåzêfFé‚n[f¼ÿgâ¶ç›>¯¼¥¼à­{´ÈÖù,9äñõù ³”U)ݘù¹)„d B.+?#Ý™’H½A®{4‹öóÙ½*ª­Ç÷뉮;[÷h¶ä—²»ë#0!ë÷E£=bëý]÷èêÖóyéä€V‰­{ô÷¿?·òó¾Ÿ.ßã­<îÁ8^/gs7Ý­{¾k$C˜«ú{8Yäð¾·C§ÞÖö6H_ö×yWÏ›’ŸãÏÈ×ý]kôʵ’p.ønæka£æri'S£÷Õö϶VçšQžzäùr½¬µo_õw¸œßhFyæ‘K¯¦ù¨¿êR·h7óµîï?–¯¯’aúz3vãIÝ2÷È‹ëò­ûók¸âq¼^Lç¶AÖoÕ¿ßè„äfæ{t¹œÍïüÖ·ÓëyBûž¶:ò¼›ë-žvSw÷öˆo\^äuýú{nƒÙ¼Þd·ËRŸxBÎ}˜nÉ}mæÓÉ4"™V©}>Õ{@2„§¹þÎ ùÛ¦y2CÈå,Íc¾ßã°A2€œ·èºŒÙw׿ò2÷ÈiF—u=å ÕqeÉ] éãyío²œdùå½›t<;™“¬ûi7›ã¤± dá ÿÙ¹ÏÈûdvHýá¥Gž];›vRj†ÇˆN¯<òâ:»|ëãеS¸a‡u‹&èIwo=) o4¦MϦ1×32Ý©>Ë:‘ùdšÓÚ`o^ùS{:5=ZOÁlO›I.W©xÒíilëæ‹VIä9ùEÚLÆ{ÛõçÏ!¹­´ÎÒñùêç!@^—Š‹3ò5 åëFû+R®•¶'äm’6—:Qnë×§]º7 þºI9Zd²\ßÍSÿ‘×·+ŸkUÊäyV7Ù~~ëý÷ïŸE*.WnZNÝÎu.ÑÊëý÷"g·{óºvèvÌW?©8ŸÏ棺=÷ÈùÈ»n]—®{!YW¬{ô׌iåçó$ßú‰Ç9¸ÞâW'»ß÷¢È(çS7NFëI›bÙ£§£<ß_eH3mew퟽Eµ"§•?Ú[,?m}ý¶·/Öæ<›FÓ®?Í¥Å+_¦y\‹±¯úÒí3ê«D«T.{ôïŸ?ó×Ï+²ïõ´ž§+Þ÷’yäùrv_?=/Ý£rÙ£'ežûu9óóÜÕãñjñ˜"W«uA^¿°¥ ‘· ²#?êñü¢•/Kˆ\6sAjU³BÈE±›‘‡Ã$²JÂÈã/2 #?Ýã9¢ßYe¹>†3ò<^ïÉÏŠYä¼G+rÒc{9Ñù¬r Ùo‘œ@Ž—»Dq%6ÈUS}Œ“^äFa¨ ¡—-tÙ+ý¿åôMëoN_óhnà ,›¥§‡©>.Ýz¤ÇÏå¡nw ]vKÿ]F½º[zúŒ‡‡ë3"žÎìÒôŸòy>£1O·6¯›yºvÖ\ Pl½µ¬áX˺uâƒ0ó¶Ýû¾y °$–çÖÕ7ûi*á{ùRé÷›„o7b3 u ›„oÇwjÝÔèÓ9±àÝßÀ‹~8ËÐÇ[†XÞƒgy‹–÷:@ Åòö€å-öXÞc,¯‚@šåm%1Âò:N¶À,勞,¯¾ö²Ó€å-",¯„,¯«ô½¹®ó¡@×µŒ•‡×V ûg›Üß4í¹@ö{¯×Jà^—Äu#º®%q]I¯kI\×ùÓèºÒe@¦y´“ %q ë¦ï­ì©~ÓÂÜ1›}8ΫÐu]óÇì‘ÍSº²"›Ÿ*Øü4§Óëæ2r¾†D.R²†„‚5$r^·­!¡a ‰¤×mkHô°†„Ríb| ¤ÚÅø(èÞ°½)"‹-ï镃̾À§}O¯föýîµ–£{"Ô% ÊkÇ N¹Pd‹|-BìòµÌ@àk‚òµÌ@àk‚òµÌ쀯Eˆ_ËíB9!`A»P0°¤Ÿ+Ú‡iBsîøÛÖ×âÇ­gÍ[ÆÊ Íü6øë9Íü~ð˜œæ^ ïX'UYÐL¥iÛg‘%Í— øwV4õEë™%4ÃÒ¡¯¯¾–0òAf4Ã2¢•_}-a†eDg)Ëi†Ï=ã4ÃrC+¿úZÂÌE‹gA3›•4sÑá¯;ÞÄŸä9îã~=\𘫯%Ìqà•_}-aŽC¢UZ}-ÿþý³Ø…×UŸæ>=ö7Çt¶^=ó¹‹Î¦Úñó©õðÁâ0ÿ5 »A!Ò ù¯ý8#¡ýhâ×|œ‘Ð|4Èâ×$œ‘Ðz4È’D^6Èeþ.¶ãÙ°ŸÓÜÛv¼8]ÐHø"o˧{_×/´›«¯Å OºŒùx¼z´J«¯Å oë2Í+ßÎ.6´›«¯%„lŽ™Èî~:á19B.ÌÅ‚¼«ûæë‚@*}½¢3¿úZ$³„È«C~¦•Ú|½"h@®ˆ˜…H‡+"uÀæ}¯0\qZö‡qt @ ’6ýÝZ)"Ø É˜×ýs’Š„1|õƨ*04ßú||@`6>rì;{+ª¨jv{¹+ SÜþù1âÔÐ!+R ¦VWsy Ü·èØ"ত‘SHëóx@ Èp×Ó#/ÍÅjEâ{Ç"àç2¿@Ž£\”EßÈú´ €ß pãé—7ëéÿ<ôK«tLx=/©0'}f ²ƒÀ*|w°Á@ÛgíÞzvÝ[çöç;B¦$3óÚÉüè¯/´®Oò3Xvß YùúEnÞžõë3yy=1’f; ‘Š4R7ÒHEJÐHk×6O#ÁT%+Ú~¬Ï˜Fö¡oß=rx¼· EÈúé‘™Td¤™Ô#3©ÈH3©Gf¨u3 ԺؚI 2“|­ ÊLÒ3“ZŒ™I3“ÆÌ$ŒšIh6Q3 -PÔLÂcÆÌ$ŒŒ™I3“ðI=BÆÌ$ Å'ç…JxýÝVüœW™Pœ×{â9¯2¡ü–³/ ø-Ë$ÖÕ ø-Ë$ÖÕ ø-KÐÌï÷ º¦31òe){וÛP‚]Lü2£#Eº˜ø%UÁgyŽïÑ>eëæyÇÇ©nžÓ^EŠø'l2ãÔÁ\P3 HŠ5(@]›Ï] 0 )f jôù†€lf`*vcÝYôd¿’Âwwë¡!•‹i£ù€@±i}³m?Û‹ ×»ÓÓëõàÂêŠÒÕHæ0,ï/Cz܈Ÿãíò@ªú,±ˆ5O÷²)'Í&yv³'< °CÀ SNŽÄªow AŸÕÀy¼øóXEΣjηáäy¼øóXíÇéó¨Üy¬vΣ;fÕÎyt·"_.^®*!”]¹ÑŠ«txDÀ€V,7Z1(…­¸J ­Xn´â*ÝÑŠ­ÎW¥;Z1F´b«|TéŽVl…T•îhÅxĘVlõ½*ÝÓŠñtbZ±ÄÈ€VÜm´bƒ hÅÝF+6HN Õ2 w­Ø Zq·ÑŠ ²$jo½¦"î¹ì'ÐkªŒÔk4Òk`é½^Ó ½–ÞûmÞôXzïôš*Ú=ö!ë‡=o,¢®LODoƒó+QWfMÒÉë™ ´ŠÑÌj!£=˜]sþ‡€"­QXt),¢aÕ¿ s¡PX4¨ú·õ‰ö(,ºÊɰh¢«œ ‹Ö(,ºÊɰh…¢«œ ‹Ö(,ºÊé°è®žàŠ*Á¹—é}|¸y”عÝlŽ|EÙ¦ã¦EEÙ¦ã¦EEÙ¦ã¦EEÚ¦KSXo›V¤m:+i 6¹"mÓèb“+Ê67(*`›n™´îõ>Ý ,c]Ô¯öU8’¥tc÷”—‘tµJZw½v§Ó· ÐŒ›€u=vÝî:¥ÎçE0ž¿kš¦ÿ\ °øõ†. ùi_ˀ׉ÜôáUE…`‹€¡ð€% Ó‡TÕNx€D#FÂ0C7ùålÝäMãêUå 0°ƒÀ‚v§;Õ¢ò PЛŽÕ¯3} äòÎt³à ñ`{ƒ…'I¬7’7X ÐTô‡ôˬã§ãí9 lEaÖ¼Óéí!(݈ê}¯ÈHà Ã<Í\yïdŠsPI4ðty"‚'4¡aÊ Oh"BÁ”žddÊJSV 0'CŸ²b€œú”TÜÖÊî ‹ePø§‹'°ÎâO˜ÃíÒ¾Oˆ¤{ ~< Çš­(Yw#¢]XÔ⣕_ÜŠ\£ø\¯ãåó‚Àü8ÿÆA/£»àV©Xs2&ÙÜ)·àœXpCm´&„ØÃÉ]sSêóÀ’b]ÖOÄë| b}Ö‘ÆXçc¬³‚@šun%1Â:?>X »øŸÜ‹Ä“â‡UÁÀ7åŽÝÖ÷Óø‚@FJûfì!0'¥ý¸z™§?Ç£µ‹_úªúÇCu E›^öa’|XÆJ[C±WQ!V˜5ÀPˆæ_ 0dÐ`þÕ©¶uÞò1@ªm·| P]`ä)| q†™‚f‡éáD@N/íA@2Å4Å9¨½5Å4Å9¨½5Å4ÅyÊIS¼¦¸Mq Mq šâšâ4Å4Å °ˆ\œƒÏSkºE® Âåq¾†È¦ÙÖôd“†D.ÎÁ7ÀÈÅ9ø¹8ßdÓˆsð °¤¯¦{ŒÕ Ó(ãôÂt—ñ!0ÆøôH3>Z¢#ŒÕ SÏø˜Ü§·*Ò’öv€‹3ÀŒ0 }5Oé,êfQ`0‹º‡YÔHõFÖY–PÄâ¬!É€êØ#(±‡šg)á”ØCm€!«{¨ 0ేÚÁ{¨ ôP  –Ç» °Eµ)èèãYF†¿)èèãYF†¿)èè3@F½£Ïƒáo :ú 0þÖC`,ü cáo ÆÂß4ÆÂßЈÑð·!cáoh:Ñð7üõ`ø[} ë¡£Ï"9T?È`ø[} ë¡£Ï"K‚~ñ./ž±ˆ’&½ËËÃI8“é\^NÂé5=Œ'Ì ²äørVCÆè$œ®¹4ꃀŒ†ùQ£:ݬÚ3#†ƒ1º¦¾}ä¡×“5|ؘ䈉Ì8m’#&2ã9?Ü€‰Ì8ÅDÎ@ÀDfœb"—Ð2ÏDfœh`·§ÀÈD„þdž‰H}àO6Àp+7˜j€9ô¹¡ô¬j˜j€!Ï*®`ó"ÖX(»YAñ ó‚~!+~aÄl 0äYÅl 0äYÅl 0äYÅl 0Ø×U°1À2O£ñ{\’7¿Ç%x£ñ{\’7¿Ç%x£ñ{\îÞ4 ¼AÀXàM ±À±À4b4ðf@ÈXà šN4ð¦GÈ`àMƒßã’¼ið{\Ò7 ~K:ð¦ÁïqIÞ4ø=.ý{Œyj¹!´³Š ´å†ÐÎ*‚ЖB;«vm÷#«B#„¶T(è:Q–±%Ûü,}•ÀëÉRúA„6Ki?"´YJrJ Ú,µú„6Kc­~¡ÍR" XâNβˆ¹89Ë¢æš à4À˜¹ÖB m®ÙNŒ˜kÖ cÙŽ¹fí:–N)ä¨2%ª8cß/"ŸXN·~AäËIòI#ò‰‘‘N37È'–“ä“BäËIòI!ò‰å$ù¤ùÄr’|Rˆ|b>Òéçº" ã±vr@íc"¢ìBµ‰Hz(ëf€ánöHíc”Ú7â’ PûF\ÄE‘„áFœ±¾î>Üȳ k à 0n4âp# „8ÜÈÜ܈à P©Knd€p#‰Ã °$˜4_£Žƒc!ÎÝ“¡¬ÚáÜ-ʪçÈPVíqî#Æ8÷iÎÝ‘¡¬ÚáÜ-Ê*‚ ]<šy)®MΫ’G©²U kÔgU’©² QŸUI¦Ê*D}V%UFv~>£YUă$q%t^U„Â>âJ輪¨ôûé^æC$ ¢¥ ó!’„ ÑRù0À`ˆ–‚̇C´d> 0¢¥ óa€Á-™ †hiÈ|`Id³xÓ^$)åÉ]ê¤:O®HRºWU7u_í¬³…ì£Ã(n®ïÙ[`ó»ú×U$œ~`Ò¨Hø¯F ê‰ÉNÚÓ#bn@Ï?ФˆÔ[ü£H Râ*È?Ф %®‚ü£H Râ*È?Ф %®‚ü£HöŠ‹?ìò”$g¯ g/’Š ÑÐ$iB/84I 0¢ Ij€Áà -M ‡(h»`08DA“ÔƒÁ!š¤ö»B“ÔË0eM‘¦‘è0ÀhŠ4D‡FS¤)Mh@FS¤)Mh@FS¤)Mh@FS¤)‚0G}ØÔ1Ù½ÇG¤éñQÐã#ÒŒôø(èñiFl z|Dªz #SÅ.Rs§z@¤¤!>}‰‘æT‰ìòiˆV4U0S¤œÈÔ8S¤œV¹`¦Å2A±àåJiJiXòLÀB˜8WmM€’ áúDî*”;®Jûr¥U$-¾\› ¼\Y Se@iÈM‘ÑÍù44DF7çÓÐÝœOC@dts> M+üÄÎESdÉ|4ù ñ?p]=ó!@â@Ñô&€Èè몡 ‚‰ØV‰Ñ"c±x\oˆŒ‘Ñš"cdôƒ†&€È~kûÐK„(²œBq¢@‰Ø¿YC.Od0#çÇúðD¥Èx¬ª†÷ˆLláÌ*¶P€tß­FC¶P€tß­ÛEC¶P€tß ð†áç²…¤ûn3ßÍ0ç610LJ#Ñ rnTÐ쳊ÌçBÁœ‚%D0§ÄÁœ˜QÉiþô°\ןn–“Ña&µÑj)9@AÊE但 RNs¤ )H9Í‘*¤ å4Gª‚”Ó©B R.@þÌOø“yAÛ £ôá¡"/¨ðP\NPÀä‹ `•a˜¯ðãD†:Ì.øõœ"¯ÈĆéyE¿ 0zV€4„ŸWFÏ`0zV!SŠ'TvÁlsù8RÁÓ˜Ò^HqÒ“;¿ @Aâ,ß­‘áÈúày$Œ >윓Y =ìœn¥ ÑÃÃçÃééæ˜qÓ)¼ÛEÄc¯áˆ%iäj¤rè pÄÀð«€T.^ÅT.ð*À(ä ÉJ\‘Æ|HàPˆˆ°‡®JÌ"ù®öÓ1BCúÈ!b„†ô‘Š,˜>²À‡de¸à1+è ¸xû5"]„ I$…€Ïǯ)åvQÄ¢> J2 J! ÅþÒÜ@y(Ò`ÀiÀ¾ö{‘¯Â|à«P¤¤ª Ð«P¤¤¥Ù W¡H ‘âò>ÌåŠÇ?B`¤’EN )äc‘Ó— ÉÇ"½3>‹Mà-Ìòˆ …’"ãѽ¤ÈÈô¢Í—‰X4ÜBlala±s¯­ Ïʽ{­ 0v¯ÍUȪ{mß™¬¢/W×½f‘«0ý^³$:¢ßëHQÐè÷š¥äåÒèåbùr)ôr1òUب ŒQBjIx÷BбXºü9ýºNÖø9y5:áŒÇš>ƒÎxtD™ˆŽèO8;bÏžpVì‰=1Ñlw¦ÜÍö„³øóáÅ«¢bÏ« ‘Â|«²W!O¢bÏ« yº#HíUÈÓÈ1ûËåeEžÅò¹úïѤ yQ)ÿXäÑ ±þùt#²èËåU…áÝkQEßBGîEÙk 4€"5@±]' ×RŠ,:¢×RŠ,¬Í‚Åúô€w¦`Ñý[XäÑý[XÄ„=TgB¾8éŠm€—«à‘°oø^"Ö_þF¬c¬c±£?Öv2åžþØB`LǵŸ®vtÜö„¤€†O™ÄúiV&ѽ4+Óèˆ^š•iô‰óÒ¬ÌvD³•f%ÛÍ c¢ÙÜ2ßÍVš•9­‘"%®$¯ÂF‰+cŒ&”%©÷,îT/KÚvÕH§9}O8bAÇS ËU–±"Þàr•etD/Ê*:¢eµ#öìo¬’±gc•ìˆfû«tG4ÛßXE®º®UëS®k•EGô×µbÑýu­bÏöUN™)RºÊ£¦Ø¾cœ¹á;ƙ۱cœ¹ >ÃUë]NxUDGô'<–k˜áªŒ^Ç­ªH–/˜L™$±êó~2e’DªÀdÊ$Žè&S&qMʽ®e’íéf-Æt3ûi¶£›™×Õ3"ŠÄ Ò2ÉiÕ Ò2É#o!`¹Ê$vËU&<:¢ÓqËDDGt:n™ÄÌf gM>Ø?S&EäºòªLʈ‘ È«’t"KlÅ•I´†¯¤%íDÆV\™&Ñ -Ó$Jh8½§LSšžÎ£³gÊ4Û¹×ö¦lç^Û[˜²{m%EšïÜk+)H—ïš~éÏcÊc5*ÁyLytDgRÑß™4"ì¡W¦ÉÄi¨Ä•i!*¡ÄM£u]ÄMËèˆ^â¦UtD/qÓ=[Á¨×e¶k+(ŒÙ f³=[Á¨×e–FUWg²,­DJÆ":.)‹¹îu-³hùøiNËGH^•…+ƒó˜ RåÒPå*I—ï:¢—f¤ËwziF»| —¸Y´ô$¸Y¹'qí¬«‰ëNOµó*ØÎ’½WAA`„§°÷:ÞÈG–îðö^³l‡§°÷še;ЦûlGÑt¿‘í(Ãî7æ;ʰûy”ô÷šìä·ª\(b­ŒÁueE¬*0¸\¬$-v…„=+#)TXE …$VíYqæ7æÉŽg¯BžìXšö*ä鞥© ä)üÎäÝŒ²®eÍŸéw•˜u-ó<:¢×òH`Òs+„¤YΣ#z‰›‹èˆ^âæ1-¾3yACèÉ÷h{¯ó=ÇÞë|Ʊ²'ߣq¬ìÉ«(Áæï5ULƒj!–‡‚§sª®<‹Žè.Ï¢†×ìc©H¤´ Ðë´ƒvzý‘óèˆ^ä|GÇu#Š×(vt\7ëbGÇu³Žp¨ò2b±Cµ0ê ^€’W{öu 1ÀüF‘ìp–§IDö@‰+¢EtÀÁitD¹DÑ_.‘Ñ&’¸"ZwH\Á¢#z‰+òèˆ^âŠ<Ê|ø'NZŠöæ½{ÂÞ¾×BìlçבÃÖ!0rØ4ú‘ÆGŒ6w4ÒÆ?9lC‘ÃöE¿1vØð±Ã†çM¶ÓÇŒ4zØ^ç-’8lçá¶EnŠ›nrNÐ?= 2Thß/„-=þ15‘Lcï¡[þ`¾t²2'ëU.ÝôIC £GíÄ ~ú¦ÏQ¿œÛÒM`q¸ÝÔy4@ªçÙ<â³½Ç fÛ-[üæ”0@·Ž%æB«ðÍ)@•õð^ÎöB4 Ó衺utEL€ÓÑm€”v•èÃ@/¤]£PBFwXÒ"+ZBcà"ˆwºÜÙ'¡ËøÖx ]îl“@åÎÖ¸ãSîl 1²5-± %Z‡f]Ò +Zžaàº5v!¯NLÝ^¯ûÑŠ)Pá·H›±–Rm²òq/“¨˜¦}¶’¼Sݲï®[ó¿ÿ–õ¹]–WÃt·ÇA÷ æ¸é‘‰ÃBÇ'MÝ‘ П4!›f6s™Ó½‡@s|þ¬{8³SëŠÍù…€9 |àù/pÞšiÖ§ z2ö@¦éά­|gkðˆ‘­iш±w{0ö.  ÑÜÿ›K MÀ‹ë 1É{CU>Fn1/êÓù¸ê¹§q÷Öx §=¢»°ÕΧ݅­¢Ÿ¾ çÙog–Y!~«o}4ŸÎà#·ŒxñR|<< ™Nwá²öëêºy"Ýéð†@¨‹_–ö±ë»04Z¢—‡øû¿¸êÓo<Ÿªýž!o€KiýIYhÛv!p÷ß?ˬ¯i>]w]7JE°»–TÓÙ±Â9”É?Öc¶öÛéïð|Ý °‚ê‡q= òv¹ž†Ë€Y±ÒÚ»êpëšç!Íÿw鑸ögT¦n›QI<æ¢%ý]¾~¼š~Oƒ^ßö|@+´X±ß?¦m<ÎÂb^ËNºÓszC:„œ·çû÷ßÿf¤\6ò6-žî—Ö!ù¯Ê 7UFér£Qe)ÙokTYT·è&JC`Nw¤t‹nÒ¨PГ±ò"Ëvfí[ŸµÓ¨|“”ðdno ô¬?'¤gý¹#`PTxÖŒÔ#žu¼å<˜5ÛÓ#[Œé‘Ó#02kwÂóY»žÇgíOx¾g3´³0f3  ñ4qIMèhÄ%e<ÞÛqI'¹$¸$Øl&´Og&¢Ÿö\RêBo¨¶qrYArr=âä²’ŸžjèNOíÇ NOµ'ŒÉGŒÉGôd¬¤`ÉάíéaI|ÖNR°dO>““¸3ã†e)qpÇ ÿÊÒx÷\wg@CœðˆöΰlçÓöÎÀ†8Oû;òß~å³Þµ¨›¯Çá{7ºÂ¦sh6óØ~Ë;úâ£.˜ç=w©RZÏÁm¸ÞëYØŸÏ'#ìeßž¾R½Þ¸:CçYŸG£Öm¯O æ–!®ܼŽóÃzOßýFn“ˆò âU3vƒ;=ÂS*ÿü»z3R—HBG%¯ÀÂZ‡õùºG9}z¼ÊÉDÔhÄÒ[‡ç«ñútUjÀËÌÈå› íᨇÛAê3ZpdF^×õ減ëdå#¤q†šé\-çÔëáeMSƒÌ rzæ–Ÿ)ë× {›` "¯÷õaz5B‚'ö¼ óŒt=õˆ‘ÒIòr5cÖsLF®ôw>mÓþ,‡èܟϽ:ç+B¹.ü"¬æÙ|ÇWÿBÈe‹þýߟå­ÝÃÕXO–¶jÞè`¦•E®OÓZ¯mí]ãs”-{ôg~í–7l]ùúÖ\‡c‹ÆÌ–=ú.Æöuºgó×ï“^ӜΧö„™CžfEd%ê×c”—í{¶˜úÓ+ÿßqùöl¿>j¼öJŸž™‡…4‡¼ 5…4ÊêÃæ5ÐÎ*<¢Õ—òrçÓV_ÊËx 8§/å%Ùa;Pƒ¬Ðn8ÈùØ>É~žîí:ò4Þ¹ÈÉ~ž’Ï·F/Ïv>m_<žE?í_<ž‘ÏNƒ^ÎÈg§Aï'5°¥Õ¨×—8ßZ Œ z ‘ª¶éRõ tŸ.I Â‡¢ÚÚc&RïìѬEº´“´WK£Y ¶tŸ¦w¦Á¿‘ïݧéQø7;@÷éò÷˜-ôjcœosÂ}ÂÀq:Î6†%ÉAE·ÿ­-à.ÖÆh•ïÊ:&AfÁÿþü… ÑgݸzuƒÀ,°¢AÀJ‘FVz°Rà(3ìÁÔÏþm¢¤«"#š&ÍÀ»<÷7ÃÃîJ}ݘÁYÛåi†¶ÓÊ´ñ¬@fÁ÷ß•Ÿ¿š×«Ñ²Ó“L@}³<œKlÝYžž_ êŸÿ¡Oë¡n>‡VC Ñ;ÿYâÖ¤‹„õA¾GdNA]€3í½ïŸÃ s œYÇw;]ìÉ”5Qû¸á-ú‚ÿô¤Ó4×úþ‚@ë§gࣾž!°°ÀùÓ+ß?úÜêöÖB` ö7ŽÓyÔòSC`…€7;¢<éIA žlóœ‡ühiݹ^¯ÿý÷g \å4Ç·ùžÐ¯L³0ò£[§ë$³Èùë9}ý}Ôê‘ëöüùóçp:Wçä4™os:]GüõuþþósZͯþâÕ\õÎþþ‹Ö}T/¥–M3ÈbÕ§ß9©ië×ïªdUÝØ@ƒ\õÎ?ÿÎȳCöáqØüÎjÕ&ç•?.ªß¬I÷õ õsÀg{—m_®Ï»; Fyÿ6ÀSwþ^!]Ÿ«ß¡¶i-¹\³-pÏzù–˜[à2oiæ=¾u£ohDî€h{^G}|#  o®éém€¼¹~oßéú XW|˜®ø+êŠêû -xBßqëF-¼>?w÷0ÝÝ!3òò'üuF_ÞëˆáëÓ4·îÛ¡5²×g+Œ¦K¡ðþØë³½¼“Øúž„\Ͷÿæ¯[Ïç4™Ïç¡kÓÙÓ"Íõùƒ¯ÏEãÅ]4¸>k{­ùúG…fd®Ïæ=›•C¯.V`ƒT»™Ò¸F÷Ï3\x”Ø?€&üß?‡ó¬’ÌÓéç>…·Î˱k†5êߣ~^nÈÐXÀ°ï<á]Ýgs!û¾–ýY¯èÓ†õ˜¤õyYñë<ç~XIýïõqÉú›FlÚZuÏæþøB ³¨à"Ù`si?'´à ÐÄŒI= ¬á~P­}t±¹¸Æø\}tþ§½A`¶Îñøè_Ȉxÿ×óÑŒ˜C  š€Wõ}%®~ó?ÚLÆþƶ®ßÖè/JïTøöµº?^X„ø:=¼Æï8tX¦ÆWË®ÉgSî¬Vàtgר«M^èÏ6H£@±Ÿ¿Èï©G³±’íä#× ŸCóxô !3ˆ”.¨k^§úˆîÝ©Ï'‡ìN“ð¯?-Bæè…’³\îâ÷(ñÔd›Ïïòõ›t_ÙàƒtOÏüõ«™QwÒº®û! ôH]œ$øèC÷AÈ —y=äAÛVöYbh8\/5:ë !‡®—ထNy›gdö¨O×~hVBʵ m'ÕLÔžjô;3B>gäùŒ‘¹U´æ•¿‚r¿ã’añvµ¤áû~:7èjd‚˜õu8_² DæA^ÞYQx^_´É°9nêfI)ƒ¬Ò(„RMRa”è,±M–‹‘Þï#:!l“å²Ð ²îhîl%vÿÌQÔ—ójPÉéóõ§yõèw2ãNûŸ '¼™1߯ëáÕ dN ?í÷ƒÎ<ãö5Ÿæ¾tÏc=’ÍÜ…uæmvóv~xFëé…Ø]㲤œÎðá>ÔWè‚{4È‚žµöLv\^ºçÉ̆ÁmªVϧ±ªEå£qgenº\†ÑèûiÊí]èÓ"@}ÈQ§¨5íÕQ HȆúX€žú¨8E}Ì@@}Tœ¢>& ¤>*NQR§¨ ©ŠÔÇ|( õQqŠúè¢>*NQKV°§>*NR ÒSߣ> Bf4¥`ŸØjãù5Õ­)TAŸÈ¯©®ZgªWÐ'òkª«Ö™êÕÆ'òkª„,hcùÐ"dIË#^¥ g¿Y-¨i¼±\yŸDµn²2œ±l)m,_Bf´a‹çJ}„ÌÕ¦¾bdN˜«Ýd®â¯sÂ\í&s#m®Žè,­ÔGÐ\?øw–¿Fh7(d®dE ¹jÄLvŸ_ê¦WvLì~Bö_yÝ)SV‰ß8¤eÓçO#éúµJW“í¥kñ£7­ÒuéZüäêŒk(] BošHº?zÓÅýF$]‹½É‘t-~¥«íð®¦÷\Ðo\¥ë¿¨CKößñøy¡« ðfÒ›æþz O^0óµkÛFUŸÞxkRRnÔn· h=ýÙܲfô¤A²ò;!=)d9) ÆÍ×9y/²AHAÝGÕ}ð˜ËÍýûŸžo™Õ•5£¯×·Uºä" gäc»òÕ¯y2kdÐ<=‚ð®/ªíW~¬7 ô»¾Ùºo—¿îÀMoEoýÈUEÈt׿þ˜…˜+ rÒTÛ2W=ÈQ°@4¢t÷q¾|¦TèÒ|Öõð¸! Yžÿmìê¾oooûé쇆[Íå¼™€ŒXž¼±ÀŒXðÆ.øÌ# Þ¸·À ¦»AÆðäÛ(“ƒ<ËgŸƒlJ-¶ àØOú D@ iÓŸíd^}}¸"à†Ø“«z<íw}H,Ð{óo4y³9ȉ=¹²†MèVÀÃ9È]ÛՆسÀ’Ln;4™å¡ý»y³ lõ[(=n­BÀE¤º,àU¨têÓÝ.·ú9 d ³€¯«æ¢äwÒª»/šwš!1}5v^7ëë7»”¾åjÌÿn¬ÇnÍÒ¶À §€7‹=;¯À˜‡€1;OA mçéf€À˜×C`ÐÎë&2I÷ZÆÂh"´óz ‰X # c8Măv^4 Úy=ÐD,P„^±À §€gA;¯vží¼ØynÁ ií<‡ŒÙy!cv^‹1;o@HÒÎkŒç¤×;Ï!cvžQÌÎk2fç)„¤ìÈ–AÚÜ áü¹A`t§Í½Üs ÃY }]+Íȱ~¿ÐЧ‘ü« ¦?>û‚u ½` é'Q¢Œ DçLJotúór/XA¦¼Ì®àãíõÀ Án2ŸÛCõHXËã§ž¶WkùßLþŽù´–“(?H\­å?ÿ8³ÚTû~޲…@®S6©6·¯=¿5Tð}sjrZn_YŸ«uã³³¬ÎfÖ,Ïð|t/\oÍ_¸3ë¡xKk¥åvÖÒ-O/»óÁ=uÐØÙ:0}ÂÔ¬ˆ„©%LY`€ÜQŽ4ÉHrkvUr+£3Ô4ÈP›€i$ £ (êµå¬⬲Œä¬â¬@Á¬ßËåýíø ¬À÷ŨÝB_Œjã/È_0sÂ_ ‘¿Àþ‰üȈzbÀJÏr*Îù ,0à/È_`" „Vz–þ‰üðHä/°À€¿@"[ð€¿`Dþ‡Œø ÜnçQÁl­i„¤ü³µ†‘Áæëå ’öŒM©!Ãûb @–ÆÔû§ŒÅͲ€r³ZÚýq†Õµ¨!¸QCܬûúyCàV qÊû¹?VC¦å¹?­´`¸–#äzDH0F="$`Õ®0!¡!0FH `Œ 0FH(Œ-Ɖc„útŒ@³ŽèÛaB¢A„c4!Ñ#B@Û ¾m6EH4#$Ј1B¢‡À!¡ 0FH #$0FH OÇ ´dVT­#JìûNY¥ŽñX^E{»#nò*äÕäUœÚñØ@ å~­eçnwÀýjÃR»fzd{ e(WƒÂPD|òÐbbEÄ'-&V GÄò5&2ÞØòçÆz[¶­ÏýÐC`FÞíž%ßé$xv‡˜“G·Ç#è|µOÆ=ð†Vµ²6+ ‡º:mèYª¶µË!>K=ëYäeŒÐÒRˆ¬³Èç§[_.õÏüi·ŽÓ¬‡3þ´ø ånõ8ÿ‘FçËqÌ÷ád;p†ú;MÝ™²@3ëhG›~<ô6§ËÓj²Žçû]Lýé_{´ò>÷Û±‹_n\üyJ¸øÇ‹?O‰àðùÓ>8|ÆÃÍmp¸™…˜œ,E:;s’3·$7a>yNUQÚ„ùä9UO¨k{ë/nØÃœLÈt†iÁýéñBêG>NBoíK 5NGz†û¶Û»ÛBB%æçІ±¨I4^çŽ =¢ä/£–r’'ÃæÓÜšå8ö0Ü»}Z€¢û+#0ŸÃ³{Zýj4ÀµBƼ6קɳ@еîr‘&§ëRË¡vÑ;°Pã¿sɂ˒ç'oª½ö§ös±L*Ô¸˜ù–d˜Sºúá¤ñlRßÓb’)+kÒÜÏ÷󵓖ãD…µ™¸©e!ï×ëý8 ‰¯tÄ$,Vùs]C¦]ìÚvóõÜik畬9¿`Ém Âzn6pY³NúñÝÖ‡þËé¿3òlÕžÛÓó)¿o„,‚)/Ýpm>µ¡ò` ÂPßàîw ãûÂû]‚î`tžå‹`ÀŸßØ‚ßÈ’¬Ö ûÆLÉî8ò§d÷ Kënºo(Ð}ÃÝ74è¾aÁî8ò§dJ«Ý7,0ù¦A÷ ,# 0ÐdªPÿ‹ô¿p žú_4°ÿ…C¦þ=ìá”릹½áL`íÅÎd:kÓà˜|Äø¾Íýæ,ÆGŒ‡Uü8‹ÄÒA~Œç¤ËA!~Œç¡ÜE£@ÞÝ8ØÉðH¼_ ”N?b Ñù|7ü¿…ÀXøÁð…è|N‡ÿ+Dçs:ü_!:ŸÓáÿ ÑùœÿWˆÎçtø¿Bt>§Ãÿ¢ó9þ¯Ïéð…è|N‡ÿ+DçóHø¿Ft>ßÿo2þß"d,ü#cáÿøë±ð±ð„ÿ÷ˆÎç ü?À.ƒðP-T_é°Ë¼$+EjÆ<+2Yƒ4æ4 ™Æ¬A³Ó˜5Hc¶À`³iÌLcÖ Ùƒi̤1[`0Yƒ4f ¦1kÆlÁ4æ¤1[`0Yƒ4f·àÁ4f Ò˜2Tˆuñ5{ç (hô^;´ýñ^CNddò’ÿ' t¬%tµ:?B!W‹ ó#4rµˆü×öµ6[÷þHý0BUD½eµ÷– N§L÷P=lhˆ ©*…¨*QD\ñªY~Vƒ”õ XRJôœÕÏo”î]„fwA‡t*dvIÌ£2.Š@oãÜ×H(2Ò¹¯‘6Pd¤s_#m ÈHç¾FÚ@‘‘Î}´"#ûiEF:÷5ÒŠŒtîk¤ éÜ×H(2Ò¹¯‘6Pd´s_!m Èvû-BÆœûBÆœûsîã¯Çœû !cÎ}ÄÌ@Óð!¶ Ì@Óð!¶È =¦!=–&ì‡G³/¶µy&`N¾ØÔæ±Àà‹­Am d¿s‰æiÂi®¯kŽú^Ûßdņ¸Ô°îM𑆤Ê5$€e¼!i³9¶ÀH‘ãµ] ²ß>£ ê3jy°rïûŒZ ôEŸ¿}FÔgÔ ªÏèuÀ³.ƒ}F¿¾Ï¨V‘6£=Zð$\`Y¹6£™FÚŒ¶™EÚŒ6É"mF12´Å¿“ÿ¶==ϧ§:'Œ¿ÍCÔ<Ô!‹ßFŸoÔèÓ!KºÑçÚÁ!«ßFŸŸ—:7s£Ï/:ëIˆPH“xŠ3SPxaCÖÌ>OÖ¤°ð&kf 'kÒMá ØPMd dØATXvÆÙ?™M…Lö¸tS¡ÁÇíÌ‚ Äí¤iFÅíÈÆí¤iFÄí,2ÕÇí¤iFÄíL¿Æí¤iFÄí,„’ÛISªý„q;išq;ó:‚¸ThÇíØË*4à¸nP0n'6q;R¡¸ThØÄíLç Æí¤¨BÃo‚´|=áQÍžðˆfˆOxT3„'h†?•8?×Ïq0 ŽR·ý«ûqìúf¿Æ|¦§©5 Sÿn«º3?€Ùf2¦ÚÈ\ÜsÔ¸6§ÿ³Œ8׊G3°3íä,0·¡/æ|ÏÞ©é-œyû„@î"_¦s»>‡Rê3ª“U}ŠÔÇMŸž‹Û¬G\µº}©0D.ŽÝˆ9A.N0‡"ÇÇz¹8W$pÔ,~ÝÐMÀ¡ëш% ¼³ýºiÚã`õ{ŸTøçõÙÓ„Þ·âbgk,ï[ˆ­±t®O$¶#[ƒ‘­9ôÙš+F¶Æí¡ˆmMWû±­·@¿5Ò ò"¢c#A^D¢ó /cú+äeDC:¦RþST¤FÜ :§¨H:G#:§¨H:G#:§¨HX!:§¨H:G!:ä…þÖ†tÈ ÝÒ9Ñ9eBZ?Ñ9eBZ? Ñ9eBZ?Ñ9e‚Ú*â’Zê1ÝD¤VŠ?ØœËa»Á@œ ã€Ý0—]„À ÿuzä”ê5æ6¤ly9mTàljV#.=u§µJ«¿>êGë<ý󋏸’.M#¥}»J_“Í÷ˆ\{°¢jÁ)HÄýþóõ`Uݱ™t¹3¼:M®ô{ïÈ,púôuM™™ýñݧùXYfdµ`=Ëpu³å5ÿÆNOh8!Plúí,¹é·ƒ>]]tzüé2ØDçs¾v£F³®¨Î8Ǹ Óù3K±TD=™ý ¯xš†Ìç=ˆ)m>kh>g)m>+h>`Ð|î¡ùl€A-IAóك泆泑À|6À ùÜ@óÙK\ê .—{æë(Fç:WI™Ù—Ùq9NUY8;.›ýéÁ ÿtíäZb »¨º9éÁ `óýÅÝJ™ë‹Peï¢j?bqzÍ@kÀ2¿‘S@§Ùÿ¿53îÏóÁ®c‰Åê®à-Î’_njáùgÿãüyšOg ÓjEW®­ôÔ¤á[m3KQ»Ú(}Ͻ¦;™2èÚÕ.1Ì«&×ôcÿUß@`îg“Û:7çÛ¾6YÙèÚÕšN¹&Î`’ïwoÒ†ÀåR¢`ŽÓ>[,p™Ì’9¾LæÓ\XyàÙÚ¥—Iëš»?=Ђ'iRÿ&äãr?h!ÓÔ¶Œ]Æ”nÌiÔaDÈ "Wîy^ÊSßèíbÊ ÒÔiš½?_îh-Sß^v.¹¦ŽLS¿>ÇÚǵöÓÜ ÖtY4cvýp5k)|ŽÒÉÕ¯Kû¸NZôϽØvÊ“+òÑ5Æço‘¥‘O†w_sÞ%þB.–Õ‚œŒÄýÎ,ñOí|)òà¨ëSÓœ¯™ƒ–§Fm‘H´]m~V=‰¡¾!$ 9»Ë¶ÈÜ[Ÿ'yY´ÞWÛŸZ9Û Br0p]æ©å«®G|Ï…×lÆÀ´Jíõv²Y8:ýú¼GÓ×µÛ'þziõ‡Ú¥TL£k†Áö°ÈjM¾øgíÙk¼(}=ÔC#’-{¤ÿÌ]OF㟋”¾íC¡Ubi òI¶è™ò…K~žéõi\T‘f$p¼" û._㢊 0§£Š¬Þ”eX?ÿ‰*Â@AÏÚê¾ 1kæ–elgÖn2lgÖ=1§ÃÜÜdXlÖ²Ûņâ5ÖÝ´Ccgÿ<|Ò”†ï:©ÏµÃùOŸö¥ßëúV|Ý¡…@fû<â*ˆæÕd¦ш9²!œ§ð}šúœhDc‹ý»ÞÄå7.rà4ž=$ðêôoºJ–ë*ý'à«}O…€ ü¢O›ÆÝvÅ¥½°e‹r}øÂH…‘™Moª]ÖÒ´æ¯Ë¤¿Hô3ׇïÏRXøè|¤}}ôá†Ör}øôŸeÍÍ_ÿÜ÷;>BœD~6È %¬‘±“‘ Æg"°Ù`|Bö/#ŒÏ†`ÿ23vû—q’ÖˆýËxŒcì_ÆIJX#ö/ã?ìŸm®×¨æyW«¾ˆH¨n.˜ýrÇs$äŽaÅŸŸŠ~;ÎÝ Mî]zÁz“¥j%# <Él ‘ïlç^O_wõÏrÃïþ¯]?jüiæj¤ûvþ–/²ù$ZN²ïqÑ$Âo’±€±ãšfÁ¡` ÙùAÃÎû-nyµ1ƒÝãðø6FI‡U‰~>­'+ݾt,#OB§ú ô‡§Úúÿæ ̉ÉÌÀ÷û©öÓÀŒ2) ™Q&È.b=ì"–Ò@¿ñxÐf%} ‘ÌÊÈ:¶p+ªÙÊ$Œ­¹ ybnŽIè,YŸ'T`H‡Oxž’U=Œ¨ÊòtÇ{üµŸÎ(ïñ> ®* ´Î€÷:Ï©{=òÄ2بý/¤EÖ2­_þ»Žhʲ|‡ºy˜Hò ò îY4,» ܳêB^JõÂxÊj°<´}ÇÚY<'C«õdÃzó¨óºî­ŠÉÿ*ÏPcà¸Ä5w…Z /"ªÔjøoëo2@Õ‚—‘°‚žÁBT¡àv°ëXEƒCÀòÄRù¡b*h׌FŠ), ôk[K@Kñ¯Îë¹±“´NWA+})}°úίÓìüv..X°Æ—Áµš×ЫSYPßìæc«< èþkcâàé‚0½äÆêƒeDóQnœ¾DGÈùØ5N<‹"æ|œ§ƒ€Œþ´¹¢ŒÚ0ÈDÿtŒvì öôT@Ú\\uq‰ «à·{6È‚¯q"¾XÅïk<Û ]"t‰øb¿‘ Øn€‹´ÿW#…jî\ö¼¬>X)èg8vhÖ‡D‡FL“°íiˆ"!dƒl¯"%m/l¯"ä”A)Ud4 ¤T‘Q–ûlB £hˆ §Rä‘‹ 9Pà!ÀW€÷£àÓRN…ˆPwðý(‚1«Ü»ªëÃéãEñûšú­­¾<>úÒC älðÊœNEg•…¢øi±*Mìe3ÜOWeƒ¯‹Õp_"üLJY«uUrDüš[}WJÕ°¬…c俍½£ •.|¦cˆmœÂq²²»+Zž2H:ïÓé‰cÝ.¦ ½œÞá±s1)fÁ“ðk¸Ô‚ÁÈ4i Ÿš¢$Y>…ž”û¾ UB#V‘› UŸ¢Š¼›=x7Ë„LЈ„©ØòN!ò®Ì"•Â!yWf‘òs´=%‹TëíÆ-0#Ë;Hk!–¿DXŒ¡qëX²ÍSãky‡/ú4÷ޝ9N{ñ«,…‚ÇÓ£…@AÏúkw&ß™µ *óY[B§Ìwfmýée¾3kë+óø¬?wa¾]æÉþ¢ 3õgqÊ9q`f?>Ÿæ­ó pBà©G@þëpŸ¹.èp¯œú1íà,ÍäyíÔÛéHt_+Í*§~ü»_`I¨šÀÄô´õ 6Ô «*⾃dUQ—3áí©_–${Ô/ƨ_1ê£~ш1ê·ÀõÛB`ŒúEŸŽQ¿èÓ1ê£Ô/Þšõ‹¦¥~„ R¿ ¤~-2@ý6˜úµHN0DÒ1D,Ii†ª› µ;†± Ç.°„íÄ.¸é°Ø÷ÙNìB§ 0»€?ÍCr =ä,É#ÜÐlû»Ñ,4|Y(ÑÐ-8xY cwÄ1â ´ýuöáÅF¾\§0°¤ˆE¾ÔNa`É^œŠ¡’˜Ï¤›tšY‹<žme‹¹nÃmhÌ(àœÞ 7ôv)ÿÍýk±J¹ÃºŠ†5EYš©U Öe Yk›Z¥`MQZ¦nS«¬)j€y¤Thô$}ío;OR€‘'©ë!0ò$H?I{¹2’nV±ðM|‰'éF,B•‚Ëv ªc•‚ÀAÕ`‚ÊUƒ * T $¨ 0FP¡YÇ*ÜälÛø t]Ë­ ÅwÆÅYù+Héõ†aë­"«ˆ‡Ø1ZómV·q&øŽ±mÀê6.é09ëœ7ÀœŽ§ëЈܞðéPõcZGÕöúbe8K€#d[ˆªiêÚªí,ýe¨¥+§>)ئàcÙ6£ÇäC/ÀIëˆ#„m1º x>œ;dávõåp=÷è3¬°Ÿ;E׺ïeFü­{}mêÏÐMïk Âý{ÝÔMý ,Ù4‡7Z#“am‘·«Il¯“T#¤#gùÜܲ€Èu•æ=—Í©¾_²üEN×a˜ÔÎúŽW©úE~›ïð;f–`ä¬J®c>jËͤ˂?žì˜ËIºlÑ>‹Ì0òfÏÜå}•o„d¹ìû¼›òuxt„Ì‘ónÊ—ÔGŒäy³'D~ï]¶LlÓ]ÆüH}Áȳ1F¹º}ûîû8\öu4Èò—·i“Ìzÿ ×=úóïŸÅM°¼½¾×϶=ãß¹fXÏô¿¿ÃóŒÚûá¡02…È«»íõå2Œè$³uþκsž{{—ÇúÌ—ò] ïÎ+?4÷Ï Õûˆ‘9(úkJ†ãýø¹«÷{?ÅÙsÕ—éÊ}.7$9™Ø —ˆ³¶~ׯöƒ+¶Ö*½oõº^ÑÝd¥'¸,íëþÑ?Ÿ'¼G¬²¥´¦=:Û=šnÆ¥u® #áKHÍþU‰iÛ˵më{‹ß‚ ¯«fôl•Ò¿H ú_—*Á+²}¿Œô}rúút’·#s›Òköý6§ Ëþt}¿èç<Œüè§þ¢õÌÅŠüצ ßLšðõñ½!i“¶Iäav\¤}|ÆK»YÏ"ו?~ŽÏ·~o‘•í'y˜UŠõn6ßÓí;Ý„ä @šÂhó˜ÃùýÄ7ާŽà›õs–úzPýûÞÌÓ°ž(cÀQãëWÏäâ±›™_õµål+mcÇÉÛpúvwÁÚˆãÂ7uFÁfü'ŠØ•éf÷ÔÝ>íÞ˜ò¤†‰šx<­êjÌhw€5ÏP>aÈÐ#`Ä`Í3Vì¸FŒ˜gNÕ,vÌ3w,Šw€5ÏX)Õu{E¹M£V0ú„±Št&i}b€ÙofÝRëÈ—Ägy0«×•²!–,OЈ8O?/7ë…Y”z›«§}í|–ªÑºö佚`1–ªÑ:÷Ô½k¸jâ'wÂçÚš¶ «2:•ñ`.ÈË §ŒX¦"¥ŒÔ>e„Á¼Ì›O!—nÎ÷ÒÑŒ¥££céè=ÆÒÑѧy(ò^#v/{‘÷Æ"ïÑŸ¶ì^¾›o0@`,ßY(­EÚ§,§kž*Xó”å ßÀ û‹ ¨o|±3æó[  ‰rdªnæš‹îó*ð”È·q%lÆa¬ú¶Ôsm©gÆY$ôz+BiV ôÕ{+xHÖ•6Šð3œïÑ©FèT«}q¾C§Z‚–ó=:ƒtjƒèTâÔ‚2Ü(vd¸•¸\ìÈpK"óbG†ÛWƒ;ó }u)#3x4/ÿ­£î:NM/½6†LûŸ9f®êINVfjÈüÆÙ¸® Ö&Ô°6! ™à®`mB&²6¡†%™ riXÄ¡öóq êFܽ x“ɦ 0uÔoöàÊïWuOKï FH³Wpf‚º®Wpf"ß º³T¥à{Te1ªé°.GU NR• ¢*}Kò UÙl¨JÐ’«×#®‚Ë@J]¨ îteZŒTÁµ¤ï̪‚+ŸÝˆFŒTÁu‡BUp¥Öck«à2!âUp·Rˆ*¸–ü"^·ÓhÖ‘*¸x2±*¸ýÈ4’9â:¦ 6G²Bâ:¦ 6GNZ¹qÒŠrÇIk-QNÚn㤿žvÔ®‘Y!*2¨]!³uÒTÌv³.Bð¸z++Ò ¥°irhÁmõVüªÆc0˳ûýû1G¶8¶@ëhôY~oÌPØ€ëmؼÞ6¼›0ŒwûnŽcýøvWôÙñbÉ´Ûµ›ž.›Õ \rnž³K0—3q`Zý²”œûgÞ™YµŸ…Àp»]úaxthÄj&Zbn›q8¨#š5¬oìu—Íéìƒ@‹cÓUíê̳ºUòhZ›1Ðâ8”Çܶª¶?’öû*ŠTÐ~_B‘ Úï«Q(RAû}5 E*Ä^(út, ôû6(©~_|*7Á§EËVÁ§|ºXSÀ*-öФY²Ø+’f†b¯Hš[ǽ"iøÓ|cûØjAýé YTqÛÇÅa—T‘ĵ¦X™„ò_Ì΀¬L ¾`Ä%&lÕŠÊ3I\ž‰•QÇIâ‚O¬d$2=—¤Ç`WÎ`ô¹Õã|Ú&иÛD$ûf›A H†Í6‘G^n<ò>¯ðÈÛ§Ýw¼Üxä»Gv¼tždç÷½'SÄ—•T÷çÅï{ø4Ö4m'­;w=fïé…ƒ~_ßvÕ65žRÝH&ZO²Î=àiãÓÊy’Î ¾Oͽ6wôiWûëÕÇâÇ“¼r﹬ö÷2>X¢êßfÖuóÖêøj!° » xToÄžäõ@.C}ÃÈ”ð9Ïnì;Bf!äô‡·A2Œ¼ÙÊ úþy¾2!çí¹./„ä¿Ú%kµiê{â×C»"“ŋůï:#纜_Gñ˜lSNxõ¶“3Ö™‘ª{NÿAûΜ—rñZaóèäÜ%! /å8±È£3'Üž‡Û×j;‰ G£@M—­ûÞN¤I[×ój÷¨=´·îŽN]RÊÚI$M–шö=Ïqj°{._õ©±«T"´\àU÷>]ÄÏ¥“òçkӿЈè¹ôǨþj”?Ï¥{7†iÄë¹…@N=Àà]-Ñs¹}€ÁK]âçÒ-ù}2þå¥qôQY‚çòç]m§wõõ´]Nõ-xB=mÙÒO›{°ÊÐs Ÿ6÷–›À+¤Q|úáò2§Ág}’ÓàS"$ êñÖ¼î5>–‘çRuYÚPÚ:æKqy·u?â1A='ÝÓáxâ“i¯æ@z'ŠOº¹žŽK‡VÉ^-H?¦ž¢Ý^ýÝj^gýmoèÌ™À«¿[ » O|:³œ~Öïè,e<ô¬?ë÷dIžñÜý¬whß3Ð~ä|Y[DéþS?u÷éñ˜åF7«|¿xFÕF°Õü[‰ÐŠ™ä7Phz.Û¾®5^y3•=òØ×²Çû¾y.Ýãòº]ÏOô;ñsé…¶þÞêþ9ñ°ó’k3·ÕDH~Xë<¬%|.ÖfzX‘³Ïå¿ànÎ!ERÃY!¤éf0¯åózÃ> >Öj˜Ö?æ¹´µkT2žŸáŒ|¬×|Åù±>wà±.ás¹U~Îí¤œã¯ç4³eCfÊj‡Ùê0ÂlÙ™²Úa¶FŒe44Ëh@#F˜-w†}wË  α¼UB– ׈ºAéÿÙ6šÔM•’³âOªŒ,˜­#S1Âç¹ðÆÀç ¶ Ÿç „>OP°Eÿû?àƒŸµª[+‰ªü‡ú·q+ ñP'ãV4â¡*N–àî—¢Þ6[TMÙõV# =ªDlD(ºzo‹z«¥¨·­YPD1êµÑ«ØÄª’(oÝ™Ö96¦‚¿›ºÕ˜«2ÚcÇ•ÈbUµói˾ùÒ%áOŸì©‚þm/RlGžÀX/S!Gºð¨CßM'‡ Å"»Ú¹2ó@} öh áç ]êTÃR§yB—:U°Ôižä?õF}éÝöøÔä„g ¨Ãù¨!0#ø¼öõìNÈ~ÓæFØã»©ah€y8>@¬×º4ñÜ|à$–OŸšÓû^«uZÃ[ª¯üªo×C ã€¼µ5ØÌÎ(´<ö|? µ>YúÝ.x@~NC§‡ 2 i•§I«¼]44£¯fƒ„Ðùl‰Ë÷t»\ÑZ¦yHWœû9½Î!PjÞêuŸö¬Ûëõ$Ñ"™–zäû@úR×?ÞµDH§/-zˆ4›þh.—GÛ"dõ«Y}Zyž¤ùe@.K‚Èw]×Í™†âCŒÉAƇh’ÃÞë›`Ëdä vJ¨LÆhûçI±S&ø"V&cì^ç©2ã°ùt¤LF×@  «_ŒhÄÂÆ!ÎZÕZª¢i¯ý©ý\/Œ”ÉÀŸ¦ËdØ|[»à ]ü™¦¿Å/&}¿°Èes¾ÿ.¥7ä*W›¶'³ùð@kŽËd¬Žö¦=·§çS~ß™qð=)‰÷DâÒÙyB×*×°VyžTÑ Nµ˜'›JÎçùŠÝÌ¡< R½ÌlÒ$”0óãÜú}ÚH¿±Y¥òÔ×á€,´< †±äiJFUhБ§)ò¶Œèã4ò4#:ŒüÈA]\B`ÄEsTnäÇùê‹8æéo5~[“IA·xžòX½w‹ç¾ÿ1¬±o:Ÿªùž ð'¦Ëô‘çò³ÂÔ@`$üÛøTs_Êã§xS}ª¹/å:Ÿª²P¹#‘òt/É ´$ËEô0)OKREE “rØzySWB£C‘%1³ Øz9t­E™g¿{Q¤Yƒô ˈ6QæZ5ÏyÂ5´QóŒ‘ 7¦DLN&ܘ= ƒ 7¦DOÁ„S¢As‘‹ë2LVo-M!˜¶ÓÄ4Cc u¡Éˆ_𡱅ºÐ§]s‘ä˜-åsìžO“<ƒvšÛSô-O ªÐÈ3NF_hH ä™ ÛHhØF" ·¡$šðyV’¡$ šðyVZ4XÛ UäYµWæƒezTa€NïšÉXù¨&O*˜ŸÃ.ƒ~2«Ê7‰Ñ±3$UÎȼ…¹‚Ñ­y¢7ß$ü‰kB«—8ñ;{‹4×eÞ äì-ÿj^Ÿ¶¶Â$üÿ»H3+HßÃãqîÚy00úøµ©-0XÌË\WÝ4Öۖþ…ÛFh¾Ônz»ŽFkΩXä¥Í\óË\…h·Æ£Rò+!èÿØ«‡¬Yê9¥L÷—§é¦ûÕÊ/—§énõt½¡(?¤|7ʯ‡À`”_ƒ$”>¨,å¤Y^ÄÞk_Ô7Ïˈê J¢åyEp¡‹ZlW÷µ]5²]9¥ãZ¯‰)<¥:sÎmd<‰ŸÃd?œ{f:s?çEâÏ#z?YøA’¦3§]GΈZ뺰²'Ò¥M#ÙÃa›ŸÌÅæð1nœs2X!3fÜá{=ÏÚ‡Ðæ¼ ÊÍU›|Y¢œ—TY¢èË弤Ê-@W–Èe‰–êõ¾,‘FÊÕ)KdŸa^î”%ÂÀHY¢KºÞO‹~cE—ûÁÀ4¡ËýÜзӔ.û"„Ìè²/$£Ë¾Xã‡Ãè˜`Ù—/ž§Ë¾H<#A—}yk„,è-/…‘r*›¹GÊ©Œèwf‘r* ­R)§²AFÊ©h4£,RN劑9]Ðd3#N4Ù ]Ðdƒ,è‚&ø,­Ñ1ÿ¢xŸ¹í§>¾_›U¿¥O–Rn¾ô‰3I˜Çƒï¯HÂO!nG$1:p;07Tõѱ—<Ü«MÌš´¦¦6!Ñ9Ìõ ä}KÆz°QÖˆ;ÍÛ7eNY©­äÙ6àb½Šm3»0L2Šæ‡æšø£O£³®&Þm<ªú9B Øb–:Ö_¥!pSGÒNæÐÕ ò1ÀÒ—ÇÇÛiÑ {4À –äu)8ͬN?ñ‚'¶-Ú:mÜN?rÚ4›4ý­µ;?ãÓŠ7›1)Rëý¸še 3ö,$›Ã\Q¡~!dŽ‘ædœdwüŽ_„ µ˜ùA 1 F)YsEi`õ‹œNðïšI`ÛG öÿÄJÖ ü–=°!Â6#÷Céýs¬¨ˆ{ÿ<+*öÂ>”ýô^؇}PD±šb¥š(wBS¬sV”!¥t¹T6Q1ÕO™«3ðfÕÉx¨É$.dÙËÉZmºƒÊêd[ʇ-³a€Œæ‚­² Slƒ\p€.Ø*ÔEºÃ[â¦Hi.¸ž¹àþ 4ü°·Hã\ð ÿFš ¶á²á‚­ð+RÀŠX¹×¦È(“q€â…©ÊæqõÈaÿ­¦*ÿAÿ­¼øu]4Pªî Á3×d²ëû^Zݧ*ÿ¶Õêº^Ë+‘£ƒkŠX5Ý©ts‚@A„ø€ËUðßYÛ‘ñ³€·/2žŠ@“b§@ã dû§Ó) õyÒ˜ 0'mƒ;> 8hl€‚´ œÞW€Š !…ûŽG,I}Û¦4`Eª± Ó„Tc·È”Tc_dFª±ž¸oÞd²h¦“1™ªßç«“ #sª^’v\KQD +içßF]J7dB)梊ç°;†©Lâ>xÇÞ” DþoD`#?w ÌâÀÓÃY ¨ô§^ŒR”Ó‹¾ fá‹3>›§µËœ¬šÜ ÏîR[¦Îw× êœµÆ@n×ÑOföÏú*!P=j¬keÐ ° €c[×èÓ%¡Ä¶B„®m þYÔ€5a^ð~2^ð„ÐviÚ[äªÿ»>Ûn%•œÞï!7üÕ>ð“Mkr]-’ªÀ}ú!w„̃5/fäAâßÉi‡¦%öJqhBb¯ä?ý¿ìC«‘¦]â˜ä_ÿš‰äÏCÝO‘íÙB`Ä¿æNe¹ã_sG£üÌr6ÆçµIý³©ÕU{2æ1Š‘ÿ1fúö2£JcÀO}¹!`0èv7»…U¹Ý—îu3)H˜K6vítǬšV…½¶ýwýf@Ù¨™p¬Ñˆ°uèUZåôÖwÖ¾² ž„£ZÇ®¶1ú™þv\r]ç#«AÇ»l¥Ó]dú²>ן³mESBæ{è ²ß^„éEøE#âôÌ«+Ðqêzü9 ´ï}VçÑ’ý'פµWÛŸÚÓxx*,Hàõ‰~cé+~ £6_í{|*4ëŠ~ѧ-µîjsØbRj”-2Mi¤µ6²Rë0Òº1m%Z!C­£.ŒsË›¥ #F.Û£ÿ,ûhÖhþúçþ¸ß1’“HË[[¤øm°D _]ëžQIxKTf=w ÛÊÈ’` %Qg °$XBX;#n­ÂYJHý·V1@ŠU;úi,‰`ïBK×_šéÎu˜…é·C÷¼µ²P¦¿†EË9H<-wé?Ü'EËoØ©¢åݳш‘¢åVaŒ,ZÞi=½¦h¹ÒEË7ŸŽ-ÇŸ¦‹–Í:R´+ZŽWÜ8¶îøEê[ ö”ZóGϦ õ ‡¹ðôAA O4ôÉÕplÛOýêû®G@fýö‡µ.ÿ²ÛÓƒ<½=øÓ9ðÛ»îéí¼[ã€ý6n_Æl›ÓãìöÆg…ýù3F<µ;ªáqtîB\6ñï8¨%NzÞÄùýsœ>½*²“,ljéÌj²ÂÐ…&P{‚3²öĬëkO`FëúÚÈèºRA`N×uhät]‡(è²XÐÕFôé’.–€YáÓ¢uL“r|†)]+¡2£k%lTå Ðp&bU`”+@ÃAêQ€¦Àȧ ,v>m¹^Vì A#²@Ôütú (ÎJ*j‚ ( øpÕA û-%!G KIpž*%!G'¨ªRNìV±R]÷:H•’˜ä$þt¤”„5¤™'¸æ‡®>^×wnR¨.MÛJý@À‚®9!ѧ#¥$ð§éRF˳ÞÄ™è˜~äÅ–±¸¼ô´”´>æ&‹Nà¯7˜#nAÑ ‹D¥$LCÛöÖ6ýØ¿O™«/ts_Ó4“ÓùxÖðµÀtÏðUH¾gø‚|¼Ãw²fë©ÈSdøÎñë ›ã Þ]s> 0bøšT@Èžµ4÷·kÇ£B“q†ïò»–&êæç³y6¦vªÒ†ï¥FŸŽ¾-Zð˜á‹‘ÁH€ùÎ`fãÆo¯ï 6܆©"ÿ^Îb#ÿ^¾çF¶†C¾çF¶>Ÿ<|> ½0ì궦ⲿ³fãËþò\Peg /ûËAê^¸š¯Õ¾|êQÍ÷…FÌéÚ»9]ªö>©*Û¡ ºT,þtIWеÊi.@ù­P¡X¼Îvhi« r¶CK[Íç;´´%º9©4Îm´æøHû9™VeŠ(¤Fœ9vû™úeŠ(¤:ÁÆ‹@Q ìësk 6œ‘a¤û .2º¡¢†¦·«ý4Ý©zéíêü) ü@¨"^Û~íòTÑŠxs,7n, cÓÃ$(.’_KÂAÁ&l¦2Œ&kp€ÀP Ô®À<ÔM»—÷Ik±,Ü ä¡l)-a¤à á4?ÐM›‹” ]Ÿ¬"(ÍDF R V‘‘¢Y#ƒU°ØˆÀ`,˜$j;i¾¾g»Ž¡27ÒOßÓqËM›ú56Ïäãà&QÁ†…ÏšˆU'Enáßÿ&ÝÏ(¨“œoºK×¹ä±ù'shƒfAh™kâúׇ2^7{œ•¢$_…9+EI¾ 9+EE¾ 9+EE†\kôÂŒ×MȵFoa‘Ðá£è½.R:Œ½×E€W³ ˜°š/b=A5%$º0‚jJ¨¦$q5% ÇÃjJŽ)†Õ” P©WÓÅø˜ÓÓNÿþ»ž&ò ‘ÿô¸5gdáGs<Þ'$æÁ>çjzºÏݽ¤ðü¤é>?ÛÚ-ON›ãLaüxÁ#…iaüxÁÉøq…âÇ NÆk?^pr¯5Š/8¹× žrVX#µH k¤6ñ¤Æ†µfûhÅŽÖlU.ÔS¦ïJœ¾Ë‹’Hß•8}—%¡íIœ¾Ë‹’Hß•8}—ƒž²áô]«¥åNú.FÒw-óW”;é»Ö~/Êô]'qËô] Œ¥ïn‘ôÝ 2’¾‹'IßFzWsÑ}c/NE׊@æf™ìðö†• ЉLâ2ÝqX“tòÝ ö(RµÌˆãÅBºaÉvôkE–ù޾`W¼ÌwôkE–|G_°ÌÑü)  ƒ6õ]x¹—ZdãË"PÀÙ|€“„Äg}úºC{UH7硃œÛÕ²s ã`r³)¬t 2n D¸ÖKc(/©Ð§iÆËqc ã`ðz``E2N¶P3A ·5À+»[¹=t€W¨îø#ÅE§øîVaGŠ Ý­‚Ž'§@w« å‰?-‚.ùÔ£íNÇËŠùÆãÑãKÒá¡ñd*x*ÖH6ã›ð§¢‚[ÒKœ¹Ã»Aú¬añ»ÞCu¨'Éüzf¿¡Á3p­ùÞaçxȳ>}_ýÕ½6U‚S\Ì8 ¾jä›FЦæ£iÞÖ»_%€É·À›´À÷á~‡Àb۪DŽ/7|¢ßXº¼µ]¤™ŒìÏ×û ]Ëäƒctg`Ý÷í­£aò}$ÉLç\úGóèîÇB¦>fòd@,ȳ¾÷x3„\*,Èf¸¿Ð|¬Ãn=”kœá‚”ý½ÁÈÜG“¬Ñ~s; =]m}¾b$ -OM¿E [!hii!—ºGYwj´œi@rzÆú-²Â׈óssíÏ­k„l‘”¾ëŸæÞ6·îÛ¡#œ%¿2p:ì]3 µE0ÈÔj7Kꊭ‰^õ$‹Ðܳ,\'·¹4Ê´7æUJ'š ݼÊv,d«›WÙŽo_<˜û´â­ýsßópmRå'[Ä÷U<„|_Å ¾oö=B¾¯¢ ¶Y±‚[Å)¾oú*äû*Nð}óˆÐ²« Á¶Q¬ÉÛçm+DrÀöyP!"%òcP!"¦*H§DƒTުܡ­Ê[•;T£ÕÀªj‡j´jyØâuÏ6<¯×÷Áx(E‹'ÿûgÍÏ_ß;¥‡·=áÂ×ø÷ïòOFK<ÈåÏÁ\\Ê×Mñ4âõ:©-vÄô§Ð¥ÿ}îÝoLA„å?ky´«)a\Ï­ܧS2²–T%ØFX60ÂÒƒ– FX þ´!b¦y óI3@FÑ¡3GÞ5w ÌBÖz‚öÒHd¡0kìE’“aÖ=ô‰$'ì ³6ÀX˜u±0ëcaÖhÄX˜5ÆÂ¬ÆÂ¬0f> ³ÆÈX˜5Ú›h˜5F²x¶úcjª Øûñ'Ÿh8¸|"A÷®[ò‰êÖø¿D"èÈdXþKÀ蔸°HJ¢°Ä…mD І…m …Û€>Ÿ¶2Û¼Ù d$ìP((ÖÙ .‘ÆK”u¶ò˜ ‹KØ÷м5‚¬aßC{·S¶óZñŒjF„ÞÃ~€À-u±²ÚÓë54ç«r¢ï¬LVXó²ë(~€ÎìíÚo÷5AúÖŒpÁV5¬ÛZ©YXS ™H‹8½2Ú›Òî4:á°fDȹÜÚÉdIÔ¹ì/èÕµíÔÑt“ÌÕ½yæ`Šö¶arwŸæÝ!0Ü0¹[«A@ û­°)q)N‘eD)N‰Kq Øý •┸§JqJ\ŠÓó ² Kq` §Ä¥8 P„ÚŽ(è(¡e®ç5p” Ø¡ìel;¢ £ÌÃ]Y £ÌÃ]Y £Ìq–©«+ªŸ®§Èr²Oà´à]­Ý^ç¿×ö¢‘ Ó·ÈhI1ƾӷfEÎ8ÇÈXÄ9FÆ"Î12qŽç‹8Gg#qŽG4â#cç8G¿3qŽ‘±ˆstŠ£çxÌ<”?ÖCO¡`œÌë¡§Pøz* ËÓËCÀXþX ±ü14b, cùc=ÆòÇÐoŒæ¡oGóÇ02–?†~f4 #cùcøë±ü1e7@y‚0C‘—‘F\MS×;ºÍ‚†mOÈæL -8O#@¸à<%»8)Dó”ìâ¤uÌS²‹“FÔ1OÉ.N QÇÜ×ùñâ"ÿ§7(äßâtãü[< ø…mºQ×7õýa€,@ؾ†m÷°Ýýg±nŽç‡ü…çNø~tO aÿ:ò¢ÀäÉ_x‡aNä–¨ëÖ¿X…ÉG\˜\€TÇß´àZpc¬ÙwxîÓm÷W Ý>¯}mßa¨ ò‰Fd–oÜX·ýý~D@ÐjîäZÍÍÕ…[eÚ- ÐÅø(gà€€ÂWj^ &¹0Âò3ô 8™MXþ¶1oÖ6æãˆ&cÞáùUؼúF#š°Näá^Ú'øŠ™‚S3—H%Ÿá)@>fÀà $ÌÇÜdYiä<‚ÝW7ÉS9DJfYiä<)™e¥‘óH¤tæ r‰”μAÎ#äÞO:Ú(s›Ë5qÒ¬×SëÛñcùO³I«s5Hçtã<3o„ ç)˜y#g­`æç)˜yc€±Æy Æç!`¬qž‚ÀXã<4b¬qÆç!`´qFÆçad¬qšx´qÚŸªhóQ;võœ¼ýµ_4Î3ÂOÞ†ÓWÚÐM—V`GNÚ‘0¹Û‘ Ú‘0¹ûH'U úHEÄu…EZèyt[-ñ’[ÿl~#TAÎêÖ™ªgéŽPzö… ëIû,ùTÔ9¸pñ™ÀÆ£ôÍå/ˆ‚¶¼²¼Š<4k›Átç‚ÿv»5ÞÇyaÖáOj4ô>¬ÃR£‘÷±t^-b!`zâÿ6[ˆXˆ¢ ê‰ÌYÙ€…( :œ I|ØòG%­cDQ‘­c4ÒЊ*’25´´2ÚD›)¤— m¦‘6^&~ºôa±¶@àJWLÏ×륚›Å)ÓHEˆzŽ? 0 v›~ãëe Ó’l´;ë4sç1 dDEÆ¥Œ !}¢‘ü¢0£sZjŒNy¡s:·Ãåe¾)ºMذ–ïsIäkôè7tºF2+ÜB§b(±bD“I#‰–R}.7äT7(˜X!`ŸËéŒâ0‹…Ù­ª×´–µ 2êK#?”œè€ÐÆ/ 2ìƒ 3Ú6 í'àЫ“ý•œ´²|ØOÈRÝ<ô0X§­Ïíò@ËÐ5Ÿ¶9~£#êæ®§£FdÛ>>+p’òÝA`Nµ|Kä(¬Ê„Q¨ñýTÃ}Z„¢¥êæ¤}üUUü$ë^ݬOßFa`‰Ü}à7Oõ+ ø=YŸ[UÀ¾}y3Ìe§ïŸë !SÙß2Cñ#n…nºÜðv3Ø5ÐýιáF}?#dN!u}Ç3âi~ç„|ÔŒ4²Ç_ǯ¨÷åñѹLKmbãRÔð:ÖýY…âRÔМN×íúñÏßíaÿL×çƒÖÓôíûgVã/3}q›Ç¼½Nc[ŸÑܳŒF¾ÐQ2}ûpÏÂáZ¿»ÏÁºË*_vs!Y ɲŽùøœ¤vŽ ƒä›j¹6mxß^Mƒç.¶±ÖÒ"‡# „\é“ùø|¿!AoE?£Cý?¼Gkß>‹\›Ñ¯Ñ;ÍG¢1Y ;^§w[oi0ìðпn¶è¶Ef¡°Ãású¸Äo‹d¿öÉ<æ½==ñ±<;Ô÷ç÷sóueäÆì?ícû;…ï飡¦r~]ÏøwÁx$%o—O‹v“•ébrÆIW?â1«`ä’ú·GV>ß¶"»­È±þƒ$XžÈïôt’ó V¬pwóqú í­|ÎÂÈûã™ÃÐPã$û‡ºÚ"¿ÉmŽ!úí¨½z!¤ ß ‰$C^üæ-Î_?MȈg LUê6œ6¿³‚HÛ¾bZÏÛû{F¿“£€O¿ïR?Î-“§ÁÐPÕ>o›»ÉßÝmxÔXÒrde=ZuwýÜF|ãxþ[FâÒ0¢*‰Ò0—†U¹SÆxUåNi‰FŒ”†0RF¢É¥a¤- c€‘Ò0x2‘Ò0x2ti[eË.xò[PIâ‚JdéÿFÞ€‚JÂg镬uZU;•Ülª‚J}:RPÉmM/¨ä×§Ú)¨dªªÚ)¨„‘‚JúÆÌÿqKî¹HBÍiœßM5õ±6À4Á`‹ãvõ¬šB`0&bvMm¼+E‚S'bÅÐÞ}3{8Œ[ÒóM>ÿÊnÌ}ë3ú4‡ñ.Fç6Uý!pSòÒ::Çcý5þ,,B‘ z8tugÞ,-p-aX¢é˜;SYÈ+È;¹ôffŠžxÁ†f£yÆã´9h6iúK(ͤÎÜáh3f†ËÞÚ¤Èñý¸šPT‹„r¥Ék““1×56Æ"sŒ4'ã$»ãwü"$G‡Íå¯ó×ÄeIöë¼,¡ŒgÙ6M#-fÐÚ9œÐ‡Ö #ÎùZ±œóœ8çs`:ç9qÎ <ç9uÎ;…ÏyNœóqíçéÏyNóNásžç\.õUÁ9ωs>.?Á9Ï©s>}óœ:çÓ¬Ñ9Ï©s¾þHpÎsêœÏÞStÎsêœÏYtÎsêœOcâsžSç|BâsžCËx®ÏrráýùøúHS«ðu&VSÿl c)Oíáñ±û˜9Åáh­ÝÅ2}46AÑiÕºYh_c{FŸŽz«ÕÍÀÓ¼  ‰{2ªˆés6{ƒdwV(ÀÅ4,BáL“:[?ìÃh€%­~n€ëÃ8¶£õÍüü­~\´<)T{lò¡Î‡î€¾úˆå±µc^o[§ß"aÄåºT4XÆ<<ºÍ×郿t™cψm ƒäÕo(}:ÌÂJØølž/,Ü’çÙ]ê¡…Àœ’µÆ@nQ?™Ø?ë«„@ñ[8zùõdnŒXÀ±­kôé’.‡ÃCõXÁx‹Â=/ø¤þ5“D žRèpÆ!d‘«¼úw•Bn%•ìäø½ äF^]­¼º´m}BHFH¶ûôCî™o7‡ª·7¢ }zíþ×c-»³`,ªR¤ QTEâ¢*(ª2â¢*ªM! U*R2åe‚` †*50TÉY0HbÚ™9ªÒ£ñB½´ñB˜…bš4ôwi(Hbí.ŽU«4'DÕ¢ÇQ•愨Z4_ ªÒœUóˆPT¥9%ªõÜ‹ª4§DÕ ¢*Í QµüF ªÒœU ˆª4'DÕ¢*Í)QÕ5HT¥9%ªȪ4§DÕ„D¢*Í)Qµ˜@T¥9%ª$UiN‰*ƒt¢*Í&J ´&„¯­4í㬭­1¨nènƒ© f€œÆÁ²ý¨ÊP¨Öä£A•¡"X­É&Ÿ€*C¬Ö´íaµD_½ìŽÇÚý÷QÛO¹ûÕț͹þ> 0#š>¼ÆÇÑþÆ*ÖâÝ=G ÇîÁ„„"PÿÉ&$(îVd ™ÐÀp7 ÇÃhÀ‚,5¡€& EÍ@ X€BQ˜39JS† @…¢þûCÜ*2éŠ 2’Š,XñÂwó#bœ@E†ÍÈ3wÒ'|•!ÇXYż{]Tód¶ñòÒNyîî{›ÄãçÓ¼‡‡„À|œxj¯*ôß%škÌÍuôá¦!P¬ÅqfKHžÏKªÈ\Ag“_…f]sðåXÝðH©É™Ç«`Jb‘Ñ×UÁ”Ä"£»‹)˜’Xd»ÝÅZŒuCÀXw±cÝŰ ¨Ä‡¾½ìå*cœã§¾Ü0û­øi4‹›î!P.Ýëvk!0çÇ€ EÏqEê 0‹Å™CÁ’½ 8"–¬®ÒÌõ±š'F‚⮢ ¸«í›Ñœ§[;¢9=‡GÜÅٜ탾vW4ëbÓ Îdƒ6à…/oDDÏYùÊAq-ZðXPZñ4ýÝÄéņ‘#{¹O‚D6`(²q‚ÈF lâ|"Ad£†"§Ad£†"' ˆl4À@dãò" 0Ù8ad£"—[ã# 0°‰F6Úmâô#Ñ&¦p(^ Xã‚üa! ãäË"Ü ”? ÔlÜIJkÙ÷÷»› £+"s—åd Q…Ì]–“5D52wYþs"}eCX€Z<[©`aÁ8YÈS!› ºfR±™ kF ›AÖk-¾mjéÍÅ·;5XmŠ¿Ùt¾}p9E:$î«V0Js–¸¯šfëåûª W0}Õ 0'¢X¦’'äd4ÒTò„,ž ‘¦’'{ÅŒO@ÀXñ„cŰ·«Çq’?˜î$ŠX³T ×é0£ëƒ` #Ól‘ŽT çA¸uôñÅÿ,…mÌ#7éâªtÅoªÄ¨EÎBÌÕÏŽƒ~K.'+²w¨ŽfaEîÐ=oíì·|ét¯ |i‘ãç§*éklmE"–Xµ5€Ý+jüÒX@ÀŠÓY!+jürI@€Š¿ö›ŠئÏG^’l©FÏêàÙR…ž„×üû÷¿úd(¨9®îLvæ¯j¾Íµòë9t4¹gEš>aࣾÍ&62×Ôu cŸÍx«guÁä`nëÅ.5uVÝ ›û©ZôAçš¹­\‹ï\‡Ï ÕEˆÊѰyÁõ“\þ| y„«@o!pè-ä02RãJAœLô`ÁaTÄU¬¡î7S±5:^‹Y9k ý]ÝØ!`îdø¬’®D£ÔgT6ÆQ%ÖÕÿÞ´º}[âïtp4žàI>êA~DZø­-qè6aGî’×.P‘ Ya$ª#4+†lÃN!Ûç;f…µäxNÙ†ÓˆÐ6ä9eû° gÚ†<'lÃEµ¶!Ï ÛÐÚÖ6äùžYÑ¢™=B¦¿*û’Û TvÎI†Oãë%ˆëµHqx½q½þ^/A\¯®—ع^²‡ÀÈõÑo \/9ôøzßî&TG#/HóL¡P^¡: …ê ‚58T§A¡:¼ Cu ÕáªÓ P^¡:…êð‚ ÕQ(T‡d¨NƒBuxA†ê4(T‡t¨ŽF¡:¼ Cu Õ᪣Q¨/èP…BuxA‡ê(ªÃ ìOúM^´< / Ög9–WdS¡©° `Î/UX­¹PB™iÄU€Ê:˧%‚ª.1Î¥ú}u‰BÄ«KŒ“j YÈêa¦|á«ÖP™òc™òhÄX¦<1–)¯ 0–)>Ë”GÀX¦<Æ2åÑdb™ò-ZðX¦ü€ÁLùfÊ[dFkˆ_û3ó ±GÀˆ†hõ9‘ïhˆnâyü ³aÕH?a7‰FŒhˆVôŠ=a¸=|ÂPÅ¥Ÿw„DNFoi!8É0*!8½Õ ÁÉè­…DNFoi!8½¥QH„àdô–F!‚“Ñ[= ‰œŽÞR($Bp:zK¡Áéè-B"§£·4 ‰œŽÞÒ($Bpð„yÍÁÔøËð[¦ÈWí {moîBñÏ!¯.$â|tG#*htèYÅžgcžeÏr³ñ,‹‚ð,7ϲ(HÏrƒ<Ë¢Øó,7ó,#`IGÁi»ŸÞú N@-ô+¿ÍW–qi#wÑÚd¨ຎÿüë¨å„Ó¿I¦@`nߨeÁ­Ô½@ÿ®¿Ñ0s²Q–ªF#BhÒÇÍ‚OæOç“‚ «±•º¥/F¦aâô3÷q°Ó\msÀů-y•Ö­ä è, *wÛj̨š³Mo_ì³óA ¶a‘…O~ §•È‹Óÿ“-Nk€‚àu€¾¨bðÏéŸWÈ?êáýjÏÐ?_Ç鯭4I€é¸ÝÊ çy}ÓøvC«¬f*œç ÄúêuE™þF—9: _æ.¼3î)³_}„À~ëÛ)³@½%럇?X8ï'4†O•y44À‡O•y¤’,ÔJóº ä‘˜:¨”ü§Ç§”W—¶øþÚ`•RlÓ]Öê§Ý£;4ͳÓW îµBT1, çØyÓøU=š÷ݺÊß<Š›Ó _Íùü8@`†E©™ŒîÎï{û…@Jëlêg÷¸È#º~:‡ùZ/Èáv»ôÃð±¢´´—¤m«"©»lNçæe%¨¤0vã´¤#'4rœ–tä„FŽÓ’ŽœÐÈqZÂȉà‹mDJ•ì½Ø Éûâ^lPõìçÅžžáÃÁ´K0ÀZÅëd朦ÿvmKªLô•"¹üï÷Tíy#‰šDk?ýJc·Ö75W«0"‡>­ÕŸN­Š+znl(–ç‡r¾ÚTDýºfºIò2æÆ^’@KÊfVÏÆ)~ñߨ÷œ<Úwc7dÂ}76EZu% ˜"ý¸ÃM ð9s5²^˜Ë54²N7•°—¤ÎÜEŽv ª¦#¹xäÐ_;èpæ±3”-I(›'ÎPvOÎ\ž8CÙ’„²9 üQGÀ"¸v摲ª¤18®ŒþWû pæö} ­URŽr;öÀkõ —c­Ön©zôõúÍ£³C¶Uoo²©SÖb"Y‹ôTÖLÈSY ¸Ne-èˆY tËZ€Äwz*k1‘·öÈZP GÖ¼M,kAÅ`–O³‰Ád—‹C fnb0èƒéÐ#3‘G{Ä`t_=b0ôÑN1˜éÛ“G{Ä`èˆ1ú2n1X0áwh€!ƒ³ 8¾ 8 i ¨€Ë.³Nà ¸lÙUÀ Z—!‘ÿv9<ädæpÔÝ€ìÂ¥ ;Œ^C¯FÆh+]ŒMãmf—->S”òz’S§ñÑ*½›^ö_8CätKÌÆÎ.‰«æx¹»ÌEœaò¾| _ÄÙ%ó¿Œ0/ÃrKdª†e\\Wû°”­þ2Aà~ŸdÎÖe#¾_³ ôTß"ŸFշȧÑ@×$»RˆÇÈ”I>Wò!Z Ó[ºÉ¡ÍNÉ‚Äëª)…3ÛÈŒ;ffG)œÈ\@CáÔÀí¿Á‘;Ëh”寮áePÿH@¤5ÜÝãÈfÆÂ³p÷€žp·.µÔ@O¸›Žè wh w îÖÀäXNKÏ@{ ô €Žè%¿Ñ'Jí%ö €’} dDŸ(p«èˆ#%Ë<ö+Š”d,;%@Ÿèˆ>Ð} è•è0Ð'*0Ð'J€úÐÝ;}ÄObÜ™˜×7¬þ‘áåì†Õóã¦>à +1ÐyÚ€w†¨Ï‡¼3D}Þ¼;ÞYœÜ°àZ©Ïµ!Ãâ€w¶£>£€wG8 ¦>ÛnXxgGêóþ†mÈ„ûnXŠ´ÕÌq±­œ% ÙI9KG€žr؈õÙQÎû+d'å,ôѱÅ5¥J)Y:KÀ{#\d¡»ZuÄ„‹,tW«Ž˜p‘…îjÕ.4ÐÇg"@ŸiÄ@kµªÀ„ $|¦•]3ÇÆé)ÍÎvò¸'eáo<î ñ¸­_ÆDÂäÐeK£w¹)ÉÂÔ×+¥i <#¬ëÿv%`jÓtß§ò}DînúJ–å«Éu‹× ³®­«G×8e˜#m]==zVÄ¢ËÉê#q¤µÎ}µÎ=zV®qÊ0GÚîgÃ[g~¶Ä@+wM`îšzüìjÀ@+wM`îšÆn‡œŽh官»¦VîÚHî…(pr×FÌ]Ó@ŸŸÝ ÷ùÙ=A:C–]ÑÂÙ7¶©vÃcmN ÏëçM :—ë-àçТ$‹”FíÌ ¼îÛ ß µZÚ’,Œ‚VÝ¿^} ‡,ÿ§C–¥|Kd0¢Ö|XYBõøº?î°,2âx»½ÁspÆ”* Èjʧ ‚Qê§¥?͆Mg®ŽèšÛ1¹-­eç+ Þš»É?ß²ê&¸ïú¿¿k.¢¥r>íA§7‹-­¿×½ ¾5¾i0§™Fï'Anš8ð¿uùÓ_Q•í‹¢¥˜´k]ð ãðdQ€cG'‹B ;VvÕ´²+Û¤ŽÊ®š-•]­ìÒÀÐÆiI"v§t$ B Nª5tmв8%±öƒ¶uï‚wT¢î 1ue̪D­€]W’C§µ ¡Çî"ÇE‰Z‚½£"ǵ¬ã[¡Ïß峟ÈoLlî”:ö”;u‡mEŽpæuoü.Ì'üwMœÏÇI9Äå„­Ø<ŸÌµ\|@_› ¹“–`·"9­’ï1ÐW%/1ÐW%Oí«’'Žq’¯Ç>‡Ó “#M{«õ[ù§þö°(F’DàHG qJ/³²1_†’D¬ Ôëñ=š‡ö¶$lp"ÛëZ‚•›„þÆíXIxtï±[ÑÀÙ“D^·ÂÔ€fÉ!®Y­nû4'ÑÛ8Y;¯¸9ù[wӈ̦|-I&;I|±W”ÉN’c^à1bAë,ITž‰ Zgˆµt{+ ³]ål)H¸Ø“£\â®NÞšûêT¥©SÍîØ×.€¬ÊF¼9ˆèö$U»o¬À-Uk!ÞP.ö4°T¾šeö|þ¾:ØH-*ÃXÖ¿G‹$|^im\uο?À:ÔÀÐ*[|›òö×Uè.‘5îYÊü%² Llå§’ä»ÒÐíu‘|W:ËOG’ïÂÄ›]ùéHò]ñæ@‘$ßµoå§’ä»6âÍ1Iò]ˆx³'ŒH’ïJCgù©$ù®4t–ŸJ’ïJCwù©$ù®4te7ué‰1‘ÒÈ&Y›ÒlaLÚ]#É—¦¶¶Ú º^@ É,M-âÁ Út-ˆ.h «ïSÙÖ?íc§™Ó QÀOÛ½F ´ûH$”“ºB9jDÊI‘@Ô¡Sìg”·~ôÆÚ8tŠUÀ«?2[‹K‘Þß»&Œhàš°øw˜OÜùþèÔ,ÎÍRÁÞ˶Pαuãçq}ÜÉoŒ­åçÖÖtÄÄÞ±S†À·ÇÀ÷C¼›Ž„¥l€â©êx‚ÞÕoüGs4¿ñ®~ãnÂ/¸6O“§”á¬\Ÿ×‡L$¨¬DTmÈ5Óôø]¡ó+ ™­Ëq.ÊJô%¼O€\œ”M?½eò \Güo¿€Êñ×À”¨Üg—¿Ë_Ê ‘dÄÈþqò }œ}î}»HeáoL°†*žN¼ªwƒ©½­äð¨Ê’üFÚÒ|Å¡isúÖœ4•4#*ë¯0°·Ÿ”¥r ÏF}xÈ¢T®óÐÑÈœÑcpfÌ]Ø NDŒ‚20(Òäøø`g!±¨fm¥[OSQ}Ãt'@{yçm.ïO)‹œÚ×âÖM¿æ6` £EúÚí«–!O q’rÏoñþ6øÙYDœÝ«É[~†¶-»¦¢ÀØF[—ÄÖÍb'm}$¶îÆÉÂ^Èââ/vûuªØ‘uÑMÕP «Mº–²Ôq--@t-e©…L¨é%äêÌ2ÇÕ9ñÕ™¡x……4Òi$Ëø iê3îLÀH’€á'ñX’¬.ÎìH‰N;rËêòÀmG’¬.wfuëžduypbG‚Â'I’¬.wfuëžDïyà·#MV—gvdC&ÜgGR¤ÃÆ…Ûœ9 ·GâîòÐåCî.b'íórÊ„zYÀ{GNË”ˆXe˜´Oà‘ÈøÆNrDÆ!ªÂ½Ï¶¦(&‘¦(5mŠ’ñÔÑ¥¦MQ2L::·¦(&íD\$)°ÚHG.V—žXq~PÈE_fû„“jv^ˆÄdŽzÅîÉ#&;ðKà?¦ gÁ/ÌY3>â@G¬ˆ})¸À¾±"¬@ˆÐÀÐÐÑÚ,üy:H›…ãΡD'`¢Rãüâ¥2o —ã&€»n>/\Ž›•†·…Ë/^IâmárÔémotIœÒánBÆ4┎2§~ 0#9fnìôF2ÁÅɘ—8¯ÂsÃÁ˜heÌ÷8¯Âq_6\Y|ÓEr¥˜¯ d¾¥Z<ÚÔä¸/›í°b B¿Ì¨Ù\AdYfZ@Ÿ=<ˆÏŠ; ´w |öpÔS‹¦"jÚ¶Ž‰·mÚ9 2[-”QݰfÄ”j±híʵã0|a³#P{‘ø6âö0ÐDnÆMzÎÑ!ïïC›»©6áÕ¸›qAþ÷ßÿvîæWýÆ–üƇ!ÖãZ.ªþ10±Xï⣾6ytj-°¼öïǽ&/“Ù ,‡oñóšLE±pñÙ¯‰Nø>öTé†*ÿ”ïêM†ÔÎá>ÒLÉ #7ö7˜K@†vüÙÍnaD8^²¹ä­¬~™õÀá¼²’3±;åò19ý©ÝÙÎgf}zfw¡;9Ëq¤=^ÓÈkû¡oݪ$rà;5Ÿ?òF,°­ª ¹Í;:&ÃH“Õêªï|?¤ÉúÑ7šÔÌ·áÝ»m¡çøzð;9Ùæ7óBóîý¼äP6è"ãKŠ¡-ˆØ‰â'¤¹Ÿ8épA™\Ÿ{û3ïÍåãPg.‡÷-ïk2bb«3—ƒ(Šª#¿1ÝúEoñKµÕºïu"Ó“Ù×ü3}¯tDn=Šò×(¾yØæ»Šô¾/?¯Zd€‘æèè¿‘”$³GOëÇý{#?ӵ͋/Úæü¸Í·ÅVËq»8ÞæûíóëÛGMŸž@m8Ý>ÓëñmèÓ·*ròô\ö·/Ï º`Ïoô˜ë½Ö8ï ¥¤OçÖè[Smù#c2§ÛŽÍFýNú5a›ï®Ûãõ¤‹˜±# {õ~ò/dâbÍ®Ku¹7b‘;•¢ÝKni*¹õúª•w 6 læ¼1$Ô?‘9[Kâ °ÐÃf-ýYãAº q¨¯ßj¨óFÄ*š årÍÚßë\¹dõµÂ@{\­[âjz"Yì¢ûêÀ‘N»rF+w±´]?"i;n£å€ŽÐpûþ$XE–nµöï_>VˆCzw¨Ò×J¹EºÅßuû[„Íu µǺ}¼’Kb¦Ÿ>Ãïñ›>M]<106À²0 ªúrêGu®c`bnµkg{^À­2Aë:ŒpDÙ?ÓczìÙ–C®îëÛ\å îûâg?"‰Ì=K®+=eqšé]Ö°5¶³Öî&õ}]Cý˜Þßáñ&È­è£4+rvSòßp'S¾Àÿü·Ž DººÝTP¤)v¹Î" Ëñ_½ókó»¿áFa›eÏjBž”Û›1ÂæÞš¬rDfÙ  K,€ÎÃàD]Sø±ß&$ßÌBòF¤MåV Єœ«9䯾öñÈ^ýµÚKÞQ—*¢,Å|Ù—÷båNWÝ»}w}wi :WæÌ½z5;˺ÝÕ:¿} dfzÔƒïzÏÞó»šIÝy—ã^q6Áp㌆±ã4¿5Ê)ð0q†[$Î)ð0qVUŽÄûß8®ªÊ­U•‚xÿaêÔ(K×,³Œ¦3Ôž-—]Ó4ßüÝÏù= d¨~ßüƪMý·,D9]è¿~lDÑ–ytt¬›Ã-íÍÛhà*Šò—Õ[Ï4úèùì›#ÜÿÞÔ£W°›#ÜSÝM˜Kw–„ÝVºÃCî(ÝY€[é¹£tgŽ‹ ÒrGéÎÜ)•îðŸ”ò“Ò‰<:qFÌ MÉ£‹7bfÒ”ñIŽªÐó2ƒ«a£`ìT¡U…æ¨ÌŸªB ª ÍQ›:ª -¨*4ÇmêìªÐdD‹*´ ªÐÖ yDµÍ{“±,[)´Î Gõ³{Æ‹\n®¯qSRKœDßHbPFr@40¡Ù£ù4[n-çF7µyë…hf`eÚÕK)‹v2oÒÂ|q>ª¥oªZuS×äÑѱ̿.ë\ˆz’j`lõ]ˆ¡“+Mv“«;ì™úún?}™Ô¹(z³(RÇ]¸¤f‘ïšfþõhÒž)"7‰,sþÙÅOd©µLÇÊìVûQ Ëð,8±Á΂ûÜ=\©hµá°Ï˜«’b’‹LßOŸYhÑÔʨ¸\ãJÅ}¯ájñ‡%ºë sóC]aO±]Àçpq‘$r¥€ÒñþiÊÏb‹Y`ñ+¾HHcšDûmaÏd±S‡NÎ:t2ï10²“°±Y˜%Ž€ó´ 8“JÅ}?@$ÉÈIâÞ@Âæu挛ͿÝ3Üe ÕÐÐ#ò½ÊkUêÓl¨eùÔZIƒóÊë>ò9G’:{®«ì²g†I¨‰Sa+Ü™\R‡H:òèøhrI"íº• îIt"˜ÚB$r1¹è£³£ÉUCˆ„¼ ·¢ï¯ïÍŽ´å øû?´Ó–Õö艰¯5ö Èœ™»] zÝöèc1~¥ïBÑæm§Ëa0>÷ëµ”Jm®ALÍôÀ@†š*âÔÔì”Ö¨½WÛl½¹f#n*Ÿß# p6â¦úS`ìÕ›(KW›kÞ Õü 'q+jaæ1>Z{`‡×dQ$Ä@:ž=,ŠôäìyõÈÜçãÀìä|\;mŠ5Ö 6…r‡M±Á¦ Å¦X‚ÒÆ¦ Å¦¨Wm[mS0r_ÓbÍjz wõ­ú5ÝUb óë±Á@û5œ/×°À@÷5ü…o\ü×°n¿ @Ï5\“G§¶È¾†蹆éoäöÚÞ-®€ÿ|°æV¾Bá0 OÂaSƒÌ¹ ·GG¶Ĥ†)¯€¤€ñΕ[ÓÕ15i €l«C€Õ#^÷|ên$#®Y€?–tAYAËÇâ;ÑD¹ðÝæ}i>¡9Í~ÿ›Ë粤åÌ•y}S_P˜­£’(üÖ3Çï{Û·N²ëíº¾u_˜ªQ±¾õÜ‚t}ki~c‚hÆ¢®ïš…¸æ­7‹wÓˆ«l×ÑòÖ"¯ïê­ú2‰Uö¦Û¬=Lݲ7j»6φ-'îüÝ®f=â÷ï¿»¯×ç•mÞ°ºX·üŒr—†ZÜ[~€®M~†]p5}™yD“Ÿ “˜VðYpBLûà\]ê–Ïv*g·ðSj sú…’˜3DÙÊnÖ‡*r°›G ô±›{ ô±›Éˆ>v³À@»™Œèc7K ô±›Éˆ>v3úØÍäe¼ìf2‘6v³ ìfƒô±›ágÆv³ ìfúØÍzØÍ‚Œèc7K ô±› ô±›{ ô±›ÉôøØÍäe|ìfô²›é§ñ±›)’¹ŽÍYÙ*óþü·,…)0šk º©Ô>ó)ÐlIU<놣ͤqe§¬Ÿ¢ï†™õzÿʾok Iõ2ðÖáÅ“TÝÉ h!²‚2.n¤~™9² ‹@¨É.(`èÈ.Ô‹Š:dÈlõ.Õ»(`ä¬w‘¨Þ€Öz—Õ»ÐZï2¢zúê]Ȉ¾z—=&,ñ0>1AnzL€É‰ Òh#U‘ÖG ˜în¡ÝC mÌÎZh7ÈÜ 1 «‡{b±°`í¾4źØe+0:ÜJ²»MM÷Ó¿‘Ô ­—ØÎÓôi®Æ€Ý¤[rc51tN¸qV"ä'ýùƒúûÍÁ9¬,8j‚ÝÈMÐÒ1pÞ_×Î#Ò1Žx½~®æÑ‘ÿ­3=±«I[º“KÎGTåc·t%¼LzbéÂaïÖÕ ŸÌ¢È™¤¸e’hm¾*P& €žL’™Çì$“D±-ì+F²ø¾4ö¾øS¦QU6WŒ"*sÍô’QYj3(ñ[c £ÀÙ&VÀ»rÛ«÷C+PX¾ÞdÄÈ ìPÀõãˆÊ\¾»d@ÕA!”©<¾GwÅÀÄ ì»êÎPÿÌ¡@-ws&A†6¤h«ï0¾é˜A.EÓ òúßtÌØ†” ÙO:æò~þþ]Wïü‰„˜êâY|¿d­4¡ 9߃BÞ~e VŸFfÖÜMM{S;,K]¯·rj†Ç{À@ûRNÍõù½b }©«Gjc`´-ÌBë· b˜ºAÍèÝK½êJ t/õ7æqà\êBÙœC ÞR¸—úC­àæG€ö¥>)  @ûR/æÜ÷?‚´.õzFþ î¥^·ÕowcZ—ú»­ÆaüÑ1­K½P ø®^‰ ­K]=ýÚ˜¸‰F:–úµº^¯ä¹–úã}kº€-}êjÒ§N!™£O]MúÔÐÒ§n"}êèŽåë>uŒì¬0ZŽCO3Í­ÐJ#§•!Hô+Ž6ÁH¢_¨¾Ô2"ŠÐÅn»e$º8q–¬Ä÷Œ]ùع@hËÇ* +;·|,-ùXõh” %; ¥oùXzò±fÏò±æ­·|¬õ[÷æ[;C¢õXã G¥­{çjDZ÷´ÖôHë^§¬y´îhu®$q®pÙ¨Uù¦Ç[ä‰÷L¹Žœpø;‰éÁš;YíhT¡€‰oDS@ka´$™ $=+Œ0Ð=áÆ¹J2ª1>R~&–¡ç1½œ‰eŒèËè10´E/±X}bbò[“ßèË #úÄ2ÈËøÄ2È£}btÂ}bdH¯XEúÄ2èÓ}bdмbä;zÅ2èÓ}bô|bôé>± :¦O,ƒŒéË ³äËÒ'–AwšO,ƒÌ§W,~gp&–Ñc O,cÀ@ŸXƈ>± ô‰e O,ƒüFŸXFƒ>± >± :á>± 2ã^± ò+½bägzÅ2èïô‰eY÷ŠeЧûÄ2èÓ}bôÝÝb½¤¿Ó'–A^± òt¯XÓ'–AÇô‰ee¼ŠeØF0ŸRvb4‚‰—²£QÀ OŒFI€Ì¦­¯ü§üuƒ(-áv€•¾Êˆ™íSCŒãv,Ç­¼A_qšªÇS˜õ†’Ù3£˜‹Jçeûmú©ïú+F˜&_ˆº:^ò×½ÆÀØ %&P 5‹<¬µPCÿ~õGз6÷Ù*ž°6»7ß{¯…Þ˜m±i°8Ä”w×gÙwdz¸ øîšrÔÉì5Èr¾I‹ÝD®GÑKWå”C²Ëß<$#È•=—l½Ÿê0&Èо7ALѱ…ïG³ÊQ-¦-Å0`âO1¼Ì£“·Œ$L(!JS¿nü¼4;óxàël–:íÅÕ‘^\ì’]N¢° «Å%€G»Y-:JÙŒD `«å(¸u*RÀÐÛ©H}ôðdàØÏΊäÌ£ýErµñ³“"¹i$#zŠäÌôœÉÕ=Er°·³³"9óÖgErfij"9óÏŠäàTÉ\ErÝ®H.;+’£/“XéH…RS¯ emªd³ÔÙÇzñM‰e†„?lž£€#k„Û<ÇÚìkÜÛâ9šÓ9CI4›«Ñe‘mQ+«§ÑÑG'NÓÜD"s«i>R sšæcM€¡ÓÞÖ#'ýÀv´ÉÕf|ßœšÑ¦Ú8;êy˜îÔ$ÈÌ/Ž óÊÜ‚Ìüâ2/Jdæ? Í™ùŒôŽŒ,‚'²MÌYƒ w“ê])?!&Ù"kPÊï$&Õ»R~:®¹cn” )'_oÃÆcßçšÍ«€±¥YéÊï˜Û MM÷Æ@ª¡¿Œh§vÃa`h<ér6Û—^\jm+Ûu¯YùÁÍÂî1ÐÎ見nx~G ´æL¤Oª&7`"}Rh_$vÌS—0Q옧^á:ug·Î<Šõ8”ɹC›@\.à&b@«ˆ@" ­Õ¸0'° ¨¯ßš4ºS@æ–;AîÈœÓÓ›G‡.3铪€ÑÉ¢¸èYÚ7 .ñÉ¢h¥èHLÑ °.úŽ¢#1E'@ºè{ŠÎˆ):hM똢£‘K› itõ`€¨N6m‚ÙÀÇÀ]¡Ø}=ìßo) ô,¸dž-ˆí^;ÎŽˆê´'OIœ ÕéÀWÇÙ‘ ¸øFܲ#Apq²þúqÓÕSÀÀ©«§NQ£«@«®^?nºz ZéÕ£€ÌÑ«g"½zhëÕS7¸dJ=½zàH ØI¯ ¤Ê•ÚJQîÑ·èÛ·†».»H|T^s ]¥ôw­÷ÀТRzUgT*¥Œ,«‡RK‚ rÔuN”Z¢ÌzšaúKÄîÓ Ó_‚ v:š|¯½ q‰Gœ¸‚ÔI$qâ:R'‘XâĵZ‰Ä'®5ÐG$1ÐG$–˜¸ZÕE ë1;iedFÌHØîØ› ÎÇ€;ñÕ¨ I€ «à­ûz)à»ß!Õ ïÿùry(n7ñé1puÄG¬Y7?_Ù™Cjs*¨¸Ý l¿CÙ7˜•úfà|âÂ2c®ÞYAië›@†_f{ë{Ó²ÑÀÐÝ_®vñ¼u¡ž¦èác 2¢%Ô$(S-¡&Aù˜è55æË0’u³JàÑá©dÄ@fý˜T¢¡ûV0Ü p±³Èe÷PFBÀâ“›«1Ðc›™ß˜œØf¯=¶ÙÀôÄ6“ ú:SâȜe8û…ãN@`¿0`Üy±Kì»áÅù %ö]5ÐÖÃ~îžm:*+`à~b5‡îÈÇH¬æÐù‰Õ†¾‘ÕŒ˜F‡ ±{ÂÈá#vO997#±ÍÂØÉ¹‰mƦž‰/ÈŸA,ž#¿ û3ar²( 0=Y°ÌÂÔé» â»†ÙÉ•Èl¬2‰YeÁ‘îcÞzĬ² äIGfÞäózoôˆÑå(N²Ø3°’ê–b ;ú uýljùûä? ÔÁ«9¯y3ÀoSÿäCWêh Ê”Þç€æªI?þ¦þó»a ‘¢«—l®zãÏx/º×O—0=áQàPË> XRs;IÚúhS»¯8˜žørrÅñ_N®80>âàäŠãc#ÏGœ´ |JÏKë83";kë7Wžµá1Й€˜ÌG¶®#o 9¤ ŽD…ç‚8v$Î!i ;¢ 9$ Œl»P,»Î,2½Û…rÙ…à`‘éÝ.”Ë.4ÀÔ¹ Ų Í£QˆdG—HŸP3¿>awèÖ'ìzôèvèÑ'„£³¬ú„f…ga¤î&0ÿT=ú„ôÑa$µÿ‘>!mú„µ$f!&*ìIÌÂØcÙÓ5ñXöÄtM.%üèâÃçB«Ip8šAéYÈF¼åSOxœII.Í$<ùpi&¡Ó”äÒL¢“y„K3‰œ†¦ D}°Él ˆäp¤I?I²RIâdª$+•$î{Mº£*`êËsåÛzLÒ³òz+$ÙYyÜuf€6÷×o¬ô‰›Ð‹}µöV;\È\|å má yEC~¿>Ê/†¨7p$º&ϱ10‚âé¼€ÂSÙärîþu‚ê*ëµÕ\Ž=UÞJ Lp¹ž³tôGäL-À6L`vªG+ÛuÚ=šfHQjóZL\üú¢˜È„_ŽÈy~äw~䵃#ueî<æõÚwäáÁÆK) }|¤úˆy.!Æ– ‚³ó3Oz­u¸sÙMíïNFD5˜«ßöw«26ÕR?o±ùûäC®; d‚‘æKÎ[6ÿ´™ät‚¦Y·†þÎl‡TO_>z!ŠÏ ¹9õ’]¹Í§ü4óljEuƒÔßh>Ù0ÇèQ4 }wÆrݳ$¦º¼²/XhAªß)ŽÈ#×£h~z7tb÷ôØ®-óé÷œ€ìHØÝª—ÊwÑÞÇÛw‡L-ÈOñµ ³cETù-¦îS½Í!¼"9ð¡æ™_®ðeæ»—ü¼srÌ\rÝšjÍ×Í»/)2 Që|N¯I¼¦œ>=ÔZRÿbä<óób&3†GäòÝù0䲋ÍÉ0Ý>Ÿ× c‚\O¥n.n{^d͇ë7š‹ÛŠÂä&r)ÞíõCgº•…ëÀ¶r³ YÔm15fVä[m”bx$·"EýÝ]pì_7éšü“ß¿ ¹4"Ó¼m©ÿYkÚ:>^ãH¾QÄ,È9y[Ȳ gHÚB!ßeñ ÈèH}Ó+o 2Þš @%Þ·|~šª*jz»%䣰!S ²+¿]õØ#5ïíÎóYŒÍ»˜r9ÔÉ7ä}õæÄw¡Î°š^®@nù™kÿËeÕýèYoeŸ%äSß²’C[ïΘaäâ€<仯ǽ£cî ?WîK/¦FÊýÑÖ£ñ®% šæÚ4eÙôôéX…ï^Cég9Ní­!k)&2|ë9ÿüæ/qÿ¼úôè}”%#e¬ogv䫪>;$$zz·¢»·ôw& ²Íq/ú’àˆœBSþl¿d–† ‹«½«ì©ß²~þ~y1Pû+² uaA•¶CÊÙ¹uorÖ%„.¹Z ò{{¼‰’¤;ä|k+§÷h±$ë7Z|xèâ)”óðnïoºãn„5–ôpÈ®Ïö>‘™O/ÀÍZ+“5;êѵŸµÖÒàÈÍšßH¼oß‘"5]Ö0®úáÑ>ÈïLC;YóñnóYÉéšýý]3“ºjŸß¿º&ß=­±åÇ–Ó‹;¶ÜàØrzqÇ–[N/Ž*¦YhW1¥£Šiâ*¦4pU1uDø)ÀœNkSGFôT1uä7Æî¦M`¤Ìß´iº ³úªù¢—½`»6d •ni#Ô.k†¯ö_Òèn0¥D3%[×Z¸+éÚ¦G51@Ì5(Y%¥PWlܨcµCWþ¶:9RðÖÆ{†‚ Öš½ÜÉLOtRîñÆ,:)w2«':)w2±­ÐSîD_ÆSîd€gÌ:8RN™u‚Œè)wSÞɬ”Yœ1ëóeb¹Ó`€‰SŸv-x¾ÃˤUÞ]Cx™ì¬!ZûUjż5w¬Çõ°ï¿fsYJ-MåŸ2zDN€!©w4Õ‰¿û};P©%©›ë>|ñ‘?:üˆ )c4®_ŸòG’2ḞÏG¸r®ÿ[7W o=ÉïÕ”d[¨ó¿þ.­üV§~&p·îH€K¨Óž|aÓ`’™-ùfnvD2³&ß& üÉ7SbŽ(a;f¶NÂîâÌõ놤é%l÷§éyèø“NšGÛd*#+0€(HÀ­-#çÌĬM"cü•Û×Üþé7Õù½­1Ðtx]OÜ5jY…2°áZàHV€[7ÏöÙV÷v"ŽQ„¦iЦ&Ê‘¬ÀøW‡o–·¹Õ]û{(C×á¢ã«WÛUgãð«ª×3 \BrìÓ+nd,ÜZDáp+/ …ÛУ;“%Iqo %xr,ýiXš¢Âˆ©³…©Ä}wžùûîÔWt÷ÝéFž¾;fឤ—A„$à'éåGGíI/×èé»S“·ö¤—;ò2ÜMÁ²‘#«o_/¿þFvq×Ë \/Ï.§õòè«—1ÐW/ßc ¯^žŒ˜x¸0bpÆ @7B` Ñ` 1b A~c²1aç<ÑêðÉ׫~ yÓ@FEg†Òrˆw·nPæQ÷.1pÕHý»”'ÎäÈ…¬÷RÝöeªçNþ]=‘g—ÐËÁ›&óeB/ÁÕ$¬Ù%rÛ…8„Ä,=è ‡Ø%váp‰¡t»ZKàêÀ£“£:¾.éqI/s’çâVTÒË6ÒãêåÞÀ^DýZQ›Gg»o Q;µ šYñ1b šp*ÏÀB†¿mUØ™¿Ì˜¢ëJ‰‘8ÌòSW’ßC˜ û{¹”y Ü L\ÀéW“G§)½­’F«›|äm%È£3(ÕÇž±•嵫ȣÚÕÍÄ^ç«G[udz ÉÉ¿ë‹tÍ2äµí賃ÀN¹wA2ñyÄ%&ìÂ!—˜° wñGuU¯v§Ø±Un‚-ëZá³ °µþ`Õ¾µýÁ,´Phµ,äTÕ£¦)3L =Ä÷ruTiÇ‚m´ÐÃË\¢Ìw‰²À%Ê,p—( \¢Ì6§’ý³Ä™¤N>s3lc¤ºøÌ úøÌ[-Cl³³ s{ù² aDî•>é V„!þè>¾·Jlé@ cG³˜¥¼ Y ,ð2\6kþºuso2æ¯[7Ç8cþÚúÑCmýhžTÂK1¢^ê½¥}Íó«2'õv=m`×!KNÌ\A€3WP °ZÌ\A)Àh1s¥k ÅÌ”¬ ° `¶ñõ\à-. ` ÝMèÌ·N=o(ÀèxkDÖÀÄSƒ ó˜9…î޲3Ä)´×­ƒž„Î@µ•…'¡³ÜOBgÆ5 y]j î¦—Ÿ:QàÒÜ8…»0r§Y³pR„Œ´nœO³»>qÅ{øV7ø„!#é¡°Ó,ÄRûV9LÆz Q¢Ä”ôeÞL®ki~×U%œ=+0ußð­W ®Žûo­ûZŽ”±ïëYèbmE¯€îžm#K±0:Q”ÈÜ)~04AÒÆ4…ÙÌÃ{qa6 ‡€eM{d±0uXÖ´G S×­@{d±0sˆlÖ´G 3¿#×™ ç;ýävu‹Û5b ³º]Ýâv‘C§Ûµ­GÊ:¸]Òì”[ ŠOsáǬøÔ‘ß˜Ø ÜG«dˆ›iñg¶X%‹.îX%Žˆ1 ï€:tfîNuj+¨u¦_&ò‹lÖÆ@ŠŽ5û”möùi‹œ1N˜F»ýÓˆb·?Cbmaª,{Ðqi‡fú]ø¤QBª æ0éZÿ/šJßû4>1aàL[yþ»·àÚhöWÛb`D3rß[=`¼Ö+0o^·& º’Æ/¦œ]ÙôË«gW~äâÒÓi‰Úýd^=>…h0oÀyÇ,®T#ò÷³y‚m¦'ü²!+­§|õ3Ë\^ Òœk¬[Où[LyÛMÉLû§¹¼¸Y>_÷3ÜŠ8ïºÿÓûQ ïjúA®]þ.6ï›ßßO9Ч¯Yâÿý]³ÄkTµmïyùøÁ ‘É‚œ?n>¥>2*Ú¾éé—\ÊúäÙŸüù›cí÷Š 3+rlËæÿ„]GìªÝR·qhÿü¾ªû–€sŽíPoõ›`É x~ ›$„Î)7Œ ’s¢-›}ÿö¸Í3­_!Ës³6™»»îy†ïùÏ_Þ£3u˜õèpàëõèLëÿEŽìR×Wh<Ï´þõ¥T<š°öÆ¥êûø;"¤{"ÿ;ÿ3-y'ûÏjØ/#¤§ENÕº49š÷3­eFëßãñ‚/ùº=4 –ä‹–ü™Ö¿þýëûM®:ÆŽ»|8¤4Ъs>y¦:•C¶S^FB†fÃ%oÈn`1\û¼mm7Ãuì7n¸ÊV®à×p) 7µÍP‹®ÞÂMÍ8a §·pÌ¥úF ·®-à´ö~°…;’Y™¼bnÉ 04[8uìwÃu7q2„(olâ eâZ¡~ ù¶¿ÿþ«|é²Ëq–:ÃÓÍåÛþ=«ÅÄÓvGõ2f5MÒ•ÏqRäÜlå2äÅÒ*Ã@Ãu>Œägòy™&i·eFg„ôÍ&N^L20™¸uêÐ !ÃÅŸFÊ)›š°KcŽ¡Á.«T‹—ký…MܱÏ;6Cû>q›Âpýš8öõ -d¸R®Â|¤@Ws?Uh<…áú5†ë´æ¨ïÂpýš¸†™8¼{†«]”á n†ëðnÏeW7´oËü2\ÍpôPãCÈÉÄ­ÝŒ‘ª®/:^Î}4wCÙÄݬA(7þçò¬˜X6M¡6¼SüÇUhÎiÏû:’%Ù¨'•Ò}£:'t¥q¥Gƒç‘Þµ{>—C²¨N`É—;®ñ°QôõVx;¬0&÷‘Re…?ÈpÝÜǦ¤Ê}¼žr´ÆuÆÿ( —κ²#äÛ€lèåi~€Ç¥A®4ÃHb2Ù´¿}Ý5Øì."4FoOã¿.ýQEBú¿HÞæro3ÐtÄ®îH¬âƒ )hÔ4SÖÛ;45M"´Ö_×ûÔ‘ht@³4jón2ôuGïW§WŒ¾î8ÿy£í´#$Q¤Òq&Ù±JÚ•ß4ïÐæuÜ«ë¸Òåò?˹Í0ÒÓøä%óÉsà“®BÊ»O^îìÄbwJ„ 4ÈíôÞ™uBH%ßÇ§ÍæÙwE»²ßî2ü=‚—±ÇGðç*¤”G0÷¤ê}©ëÁŸ«òvoǵiŒŽþ^ØÜÏI4Gð4}ÙL±%®Bf2-“ýED÷(Çë“xºÃº¯ò¦ÉÛ! 7—¼nêÒàäÌMŠ1òcrš ›:br6æ âj€Š9Ëå|T!%pŽCøKëfÛæá†t ®Â¶î-²6.¹#6›fKÖ9CÖÆu È…!Qß]Ï€ÜÖå‹ÿSÍ›÷Lh¤Æû/Ñ~ëQ ui*æÒŒ² îÇàÒ4S“ãÿ .MÆ\ty/“K3¯9šÍ³R¹4ܨs:$ó÷ri>ªRëÒ|£Y›³Rƒ¬h>DéšÝzkÓ3!×î†ôMÕw˜120ÜæÏaäÇìz©ýj]¯ãe“»^òqÊ \/e=Ã׫¨ н8 £1¥cR÷ ú´ÎõZö#¤oº‚ÏË‚fÒæz©+Aøäzh½Ý]¯+Ì8Ó!Bk]Ï€ä€ú{ýxÞë1Ò1»s=êÑåzñ<Ý‚/º¬j·mÇH×줭hS:@#$åïäeŸFI™´{„ÛT²ìçöåQ…:¯¿ßö»ïÀp(Ñ3¯‡n;‡‹Ëù9gü¡Ê£yEÈPëü k´}÷ ™™—ÙùÁ&޼ÍÎ^!Ä1¹Ë” 5Oˆ&RÑLÝ7i*u°†Àõº;*K-åÙâÉZe%BúäÂ_„4#æ&á6Aã¦JðjƒÆý4nqß]SÐ8Z÷ͦû6DTÚ… +B:÷c™–Í‘KLáåv¹µéj‘[U·õ é Y‡ÀõúE®ízk30¸I s“ÐÞ®—&¸Ý9²´Âõº#Ç3F„׋!‡:G§ w½tÈ¥¹µé˜Ü¹¾ÎÑú䮎P5íÙí±ë°àþᛜVÑw¹#=ˆTìšÛ[Œ4º^ÃwF'‚Éõš¦|‹Ðlž®—¾„Iely/{ “ÊØò^ö2+•±å½íeV*cË{3¶„¦…°ˆž£Éï†|m H¬|mã(“!CæSN¤•Ê]cŸH+í ÐÌR§U=ÏÊRw%ªB*MTõsˆRIÇóí¤’²êÇñ|;©d1! …TR>öxþ©¤<Ô<ÿT²@ÑTýñI%ÐB*‰?­©ú)&D*)€¡™Æ@¦$yÁ¼\xÁ~¬4ªæØñ~ke±>¨êuø Ú ß½½ðA´a›!Тº£-ú ø-ú j™…ú ²Eÿõ *[¼È9 ú ¸E‹>¨ìµÿ2 tLPT-ú øÓ>ÎTÏT¦ú4ÎøÖdª*SÈ3^™êç ?KŠ:á% HŒ è’4G]Yâyyó»TQ°3†înÑ”©Î†H¦•úo{¦zŽ;þ q™`f‡k2ËO_É‹ÿ9ƒœÊŠHûAiϼ0ä›ký—Ð ™Å±®³R9…€Aádk<ïå4˜öbšõè€R°,•bU4Yû^Pà•Ä€ÎêŽlÎè¸,è^”h‡Ws¦8Mìš7®ÉÒ@àõq†Øù•8«Òt¦ò •‘v’Ô¢ÌàG9…À@Γ\Ü´rv°æ4·?WÝo*ë~çˆÎó- †*~úÛ<¡–ÅwIŒü¥é!.yÞŠ º&EZI)ïëæ˜•üþ´Ílc7ñ&+²ÒAH®ly ×y¬ñtˆ,xLö@Ny>fé^ÈâØ±‡è@MÒúb@cÄãYrÃÂs]²+éˆ>DžåmGVÔ·išù‹ÿ3Oùd>r‡ïšçšs¯ÈS—±(Ç}ì³5‹ Ü£Pú±QZ¤\C!g&nLÒ¤F˃¿qoÿû÷Œñ˜Ò@ëŠVÒ Ù<âëŸÓ7æÓ¨VÕòÍ£*GHÖ³ñ+3}÷aK*c‰ çï¨kÔrQÚ Ú@ìòÎ6Ç .ˆ©ð+õ„¦UÝ—¨E¤2qí´njg™.à»æ-É<Ø’®uK6ã¶B qKfîu¢D‰ufíç"AŸ!DYÝŸKǹH»=FHÓ–ÌʱoÉœ'×2d=nmÉœ< YMÛ6öéj7Zul´ÝÓn´ìØh^l¾v£UÙgò¾%ùF›«µR ñ ÃSivnIöŸKÍ<¢­Ë–lc4GxKò3òØ’ì¼L’!á–ÄýlKfmE2ª/Ú‹`ù6Àð}¿N(I0|ß/«J$÷}ãeµƒ|Žï?©*Éù±0|C6wkxØöqê Ð1LË„|phɤgü*£²I¹å\Tz¿¾*¤Ws‚·á^Raz5'pèÕ*Ôöºæ½–ÿh"Ÿ’®¼ôÐ÷Á•—™ÒÁùT'C°ûàÊË;h`&Ÿª+OI =Ô«I.KU5²ú°øÍkqóÞëNUA?1…pa–J-\ßN¥—íèÓ®–þaIýÔ¢g‘sãhakµmÕPÄ¢«ŸQ1º ´×Ïôª×¡½~F’+9Ÿ—½~FÅè>/cªB¹þÉþqŒ"‚õFÌ̇˜«4P ýÇ5„%3¼|¬¡7ü˜¹~DÀQÌõÇ·…+´óäzôjZ ©#€f ŸbC-Z(|T¯ƒ Ÿ}ÚBáS O[‚yjÑBáƒ?m æIWá X Ä µ¯b Ïǰ]Ï~¨%ÉO› :Ù2CÅi¡is@è÷ܸÐp‹ÐïÑp¡]-ºPRç‘ ¹k²}žavuÃ8ë•–qLã}‹:ttÅä*&‰•[å*&‰QʺCaÿÐ5X I -EèÙjí‹]©Ð·“éªEÈ‹eþ*ÈÄê„VcVOhž–d6ªE¥T…)¥È3¥Ô¶úëmõ×Úê¯Ñ§mõרEßRk/[|¢”ªÐVk_A ­Ö¾†@[­ý¶Z{ô¾…”X¶ë¯ÿãR¼æ‹MߘeãH >¢#…“ï²Å4e ªPûø°$ñK¶:/¿û ’É ;aöqÖ¯4.¶y°sÛßITG  ÷+mt˜f mD^®IÚ¨¨¡´‘j¤Ž´‘Z¤Ö -ÒFj™¹HÚèWâgß Ð7*üÔBªU£t ­kü˜õh*Ô™Ð,GƒBÚH+23¢Ÿ|¿Í"37¤c™¹!‰YdfDc)¤´‚0•HÏ,së»E’¥ÄÈÀ,6Òàÿü˜ÅFvÜfhÁH™¦¹!ß&ab­ÑÈ;ŽYÏ‘H Ó ƒhu:¹·éE<æm6Çÿ•æ8„ò2Nð¶t4r‡”Äïv>F¥F³é„Fÿ'y™7*´>ÉÛ,¸qC:fÉ <å)rŒtE'ŽQú]ó\Úèï?þ¥JFãxóØÕ @³É¥Žç6ÄWü¥ìÚŸáQ ~…, d!‘\dÈ×R^×ßoad)M áƒ"í!/ï'¾$ÏÞ~‹eR&ÄÃ'帩¿ôáÃ??<i­Ì—÷Ci‚€ëˆþÑÓP  9层@«û**7xRÂêŸç[Lç²)!P0¨CZâÄkUE3ã‘Ñ+G⊴hOŒ=ãqúÆó"Us htfxQ3i4Vø Fø|ëÕ™Š.ߥ:“DšÕ™n#ù6«3U;n“FyûÏsz¶Îã/“·Jó¦Üomj9Ð:ÈF^@K»Ë}žˆÝ;Ô»W˜ØM±û6b÷mÄî3ÚˆÝѧ5Äî&v'€E»W˜ØM=±ûŒ€ØÑ“÷-ĹO^vÎýnQËâ‘sƒ@ÍÔT˜s_µSSAÎ}ÔNM9÷P35æÜ@ç>jÑÆ¹?C fj*̹/üe$#•™„äm%ï¹2 бˆ@ˆŸ|¿m¯ai!y;VÒÂ}œ6t,|‰b!u¨.º¦Ì úÔF×d蚢OmtmW@Ï]ëÕ§½‚!!GXlsÑÄÕ  ÿÃdY\1nÊî5:`ˆ×xì†@´I‰™XÚ³wð@H,ƒ=ïàX¼Ø‘w`%$.$á$š:BâBRh‘‹DÓ@H¬Öcð@H,ýŸwð@H<£O[‰#Ô¢…xGãøKH\”’xC½Ñ‹¨b†ûývnbÜï\RZ†¼?º—3dvW¦Õ  óËv_€;L‰‰¶uÄF\zÀ3^œ€g§ùn(Ûv£E¬4çuWÔâ)GFÉm*£O}Fß‘ÒWìH.†õ#Ÿ#;å4vzlï}Ú5Ë’Èýå<É’È9tÞF†S‘//΃tŠú´cO“PÍ!ö4 ™ÓO gª.•cS@מʡŒ®c¦#¬`öq¼ßàþEÖ¶,“¨×'ޝa–F—y2•ƒ8[*õ!ï5¹ÈUMýy¨GOƪfY']! c®™Ç°ÿz¨™Ÿö_Ý(.2wTãÖ²—«qÏ ú˜Ëj\âã*Œãþ,bº»Æ–zï³Wã߬@ŸvE¶û„Z/&yîày>¢l—±@yùÒ,‡bL!¿˜ü•ù¥Ø®ÇÕ}\ ð£9ænB`¨+¦ctÔÜàéK†ëô "° ™Ræ?&·!ç×bõ^SˆßlêuhäC¹@„,e¶î6¬édÁ+¼Î6û´LÐ`òk±@–WUB½¶Í8"¤¯)t8˜V/‘Dâ;?Zœ¢òÑ5Ž÷U J`@ù.Š)IŠ¢‘mPÜü¿?e0K¼IDÕw‹K$7`©€3!Ð…@Îgt÷øû…m7k€ë÷»" ?Àþ9'\X–d‰éº(Š›O”&Rëe k´+îTŠ›y‚‰´U1¥q¼õ’ò‚€âfžÆ ýöhY¢eœ)nñzŒ½tf2Údßa*p“oåRQå\$)í—:]om:8CNŽP§KÙ $¹eȉٙҊy`éÂðœÈ.Ÿ úͳo†F]±iýWLXÜ|Fò’Ã-N/(c¶-k‰Å͇óGOC3´ämÛ¯·QúÈ” š&â”H¦ƒ¨qìË!C•œ‘f w òqh‡l¢­õ×åÖåâëQ%4ߨ<Ë®âæ;2ïs…Þxõ{1Sšuÿhq:Dì³¹¿!UÖÏôdÅbã™'ENi> ¤§òóŽiçthý4´ìo+üŸ>ÈÏVDé°VU5â¯0“Û­u]iI·‰¢‘—Yw™K›Ð®q¹·h%ˬ»ãIA~=Kt_¿²î®¤Ý$¦=ò)P`Ö], Ðsš÷ÉPd‚ V"yÖÝŸ¿"P<v˶ϲ†"ëN"K…ÌrGH~Lo"?/çÔzô84"!ä5CŒ<ÙE÷ÏÑÿˆœ?Nx”–GÝ€v1Ϻ;Þ+OksæªVk˺vù`d©[2`o«¶‘ÿéÞ#ÅiÒa/Ê3ršlØ‹ò€õ‡›¯L.í²®‚uR‰ÙÝѧ]õ\qîŒR˜ÎµeÇ/zxžüpžFš£ôÍœ2 Pûs[´Û÷ï ,Åb×4- %Ÿ-¥Ð0“<K4à/=ro+æL!ä[¾¶‹•Î_¼»¤œ¾ê?…$²Y/´[“aÜ0’ ¤|EïÖ¶ç!]ˆ,sµÏöIJ©K¤'‘‡)¥ƒÒîìØèÐhòSèÌHÎ)+mñ(ÁË2@H^QÏyÓ Í9?…$’ýT›ã¶Âm†fnœ ¯õÿveY¬¢@tK‰âôÙ èsÞ[‚³ÁhBLÔÓ«oT «ðÿ… ÔpëÖíl·/ÀˆÝì·5ÜW$6܃ý2ÛÙÚD ö[ÈlgÌng :£ÀÔx±'9Ö½öß¾¯3Œ.J¨!^„ïfNFt„ï2¢#|§Í³«ð>‹"ká8)—÷Ãø"T«W<¾ÕêwŒ/BµzÖñU¹<Ç@G¨–N&´5Ï:Ø^4Ï!~^5Ï…£›SB×úÑÝ-bz~tÕdÖ1òì%ÔÔdÓ®šlÂu]5ÙÔ³¾j²IŽ&›t2Ž&›ð_GWM6é¬c‡<¯"‡úý+y>²+y>ôìQb=ëà"J¬\D‰õ¬ƒ‹(±ÞÁE”Xÿ×ÁE”˜>:´g40¼ÈP ## ß1¼Èè/2zÁËŒ€^ÇÔ\*mÓ«%Ь¤ùM/)Ø=;pÌ1Ð7‡ynæž™8’Gi*U./×ià3¯00´‡Fg „r}0Õ\Ôš™(R^<½)¢CÍþºp£Pƒ;²9— °Xš¸Ð¦K¥0꟨°~qR*ªYk%N•ÂB&§GoaÃ……Öæc: 4·®¸~àÙE )n]ƒbzû̾)k d¨#>óX€.—- UœöÏnì…È?š€¿â ŒP¬zÇeDÑÿ D *n¥À_q&øh`Äçï°à7rò„¼ãð"Î%öÏ™ÎÄ@7g]Ê¢èô'‹z]ÑõÉ \wï]ñ-žÒµã%8ýQ‚‹[·e¯ÐÿÓ4tÙ¡¸•"—?è„ÔµRY±ž¼õZ¦Up9y}ô&´¸!¿O2;~?÷—1_ãôkÈŒ¼›)'o@Þ­âB9Æ· q!86âÛ…¸<;¾YÄ…€Ç=“âB)1 wÉ£†»$ë{ÕËÇ2;°‹½‹Êj( ôlÀ§@¹Ü4a×P­#u[à¼(j¬}x;֯ד }rªÈ­~oMÁŒ¤6ú%/>¯UŸFÎyš³“ÉÑ‹¯Á{v]'ï¸nô?Î hÕ´¨öï©ÿ’G¨Ð¦ùÒæ5ôâÕ>004¥Õ-~@#O<$DûïÖ}IUžÖíØ}߯ã½Vs™ó²Í–âWn4:Ôþ°©¶'7ûæöÑ“åQÚзn=[è¸iħmÆâ1¤â®*oQ%Ë—]–Îôá*ý¿ž»y ö~¨Ç´i ‚ÜÒÿk}w^j¤\Ì&A2þZ:­¸´,D3TüðtRa­8¶ ŸºîÞàZ&þ‰Ò´ån f*aÑ­“ÿ’.ÇЀ¾IÐjüƒÂà„™üõucŸ$°ªø|ˆ6AXU|z¢â“W*>-ºT|z t©ø èRñù` KŇ]*>d2.tªøp‚t©øP¤KŇ"]*>d-*>AºT|ÈéTñ¡«äRñ¡3r©øÐ§»T|Ò©âC‘.²“œ*>dFN:¦KŇŽéRñ¡3r©øP¤KŇ"]*>ô=]*>d‡8U|ÈþtªøP¤KŇÌÈ©âCÇt©øÐT|øAÅG! *>ü â£FNT|Ò¥âCþ£O°ÓM¶|åÚ6 4J“-yBIè&[jÉ”$t“-¹žNè"[VŸùCF ¬ Ö¾÷CGëù­€‘5½z˜Ìºâÿ­¼¡\åß—&Iò JÓ7&¸õƒXòcïçãQ¿9ŠbáÙ‘7>—Të~AÖ¥öI|QR­ÉEIµ~4Š­&3áì3»Ý쪜XÊšÝî–h§RÖŒèSâh§RÖ ëSš¥¬[ dFÙI,eÍv}J“·” Ð;ÙxP¹? ó<ŒE¡€þøÐÀ\9z–@WÕ÷3úàK Ü*÷ÿL«ßZo̓›é%-¨ßPb`€£ÞU Qï¶á'“ m¡³ Âã Ù€uSfï‡$È^uÿzõ%×!âŒN‹+S[«ìrœ¦tÎ?eOüF,"=›¼á\5äù:æòç|‹L:Ãï2#+y÷,>ù _‚´ k‰$‹~ß+µå[nÍ ‹)—Çi‘ ²˜ÀÝLëmFï×§óª¨èÓCÔÂE5—>ùï7§UNW)" ðµùû|¿EÙ ²Ý”G‚–y>Îã´drFŽc.ÿ¡#RÙx$l™eMQÔ:l Èû)w‰ I›,C[^i‘u}—$i²üPLÝæmWì€\·:›Ûº#A©š,K$¯ÈÐ`­¦T5ddAr‰¤sß›,…²Üƾ³_›¾)2Pl¶ÔÞ¯‡B1½Š¡Þª¤ŽSx7K›zÚÒÞ­Ó&;#­áÝJ¼Èž÷­áÝAйûZœ}/X¯IäSѕφ¬§ìÈűX=‹gQðG>Ò=ïk^ïr2(f­ü€§AšoäXò©^׊—(÷\Ã)2&V«Ffrw΂L°³½g§e-¿:z(® |M¡í¹KÛ™ ïV¤h‚ô,Að´«Ó” };²¡cnD¨¿“ m§â§h†qüV`sKóøŠ‘7oÕâ!An89cª›¿R7‡Íózí-oLž–"ïDEö<‹Ïá¥Y…—zØ!Îî§Bw-`7·{3 Ø ìÀÿe·ÐPnUk¢pÿÑû=²Æ[`3}Z ôPŽzý|—Zoiv]Ö“} Úœii‘*= Ôå*kÔh½ `ñx|Æ÷<íT#Îâ'OO ÷»ºPñ¼å›a®Ä#ý‘—ð‘?å}Q£PÀx'AL }vÏ®®~ú4@ì Ó0öõëGwŠÜb£ŸI~áÃP¤g2r?XŸ!©H³¾«žOr¡ïªW(¹Ðw¥#:ô]õ•\è»ê¥L,ú®KñÒweH¸Ò…¢/*§”ÝonÉM¨¤d÷û…è|Ú÷»½`w†Ð¶ C* ÁîžEŽPlr„Ž´»êp µ9›'ÿU»®€ž±uѯÿ|:ð*îþQÜŒhB(mEv?× ×J'·Ç "v, ¢•¿¼3ˆ$x5"0ˆÐ7é¸ôXÇ…YU×üÚ®ãÂì*ƒÍ‡N&<“— ôoB]¼Ø=²§ÓyÉÂdb«X‘€e÷KÑ]°ºtF Ð¥3Úb KgtÀ@—Î(y´K–]°äÑÑŒH9ÕZ‰Jžºê¯ñn¶Žèûœge&0ÐÈTãC%Þm;` oNø¦K*N½¤wwf¯gh¹ÁÚmS³ö€úè65ÌóÊ9k›šm)ä] •yþ…j;a Á¤Ù‚š»Iã1‹I³w“fWÛ3›40ä:Ô÷)С¾¯?ìøB}_/d|¡¾Oõ} ´«ï7£>øâ+õ}:o—ú~CÇt¨ïÞÓ¡¾ß?ü ¾¿ :ír7ÌK¬r7=–»Q@£ÜÍ“HÐwhI©%òoNóp Cê¥jD}¨ÉÛ³Ÿ/5ÿ”‰¨”Q¼\‰ÙsÊž¨µåôS‰,Ñ‹´¥¹„¾©y¡±M:áï¬*}ݨXwŸI+©Í÷‰÷ už£¾Ì¿ AßùìBÌ[ 0Ÿ]ˆys´Šyk¶¤ZżgQ’wtˆyƒWì³ 1op|v!æÍɈ1ïšbÞ‚Ìú,æýh@̛ӿænX€˜7 =S£¾^äs+FxÍàT¸‡À<[­EÄvMPK_˜†Œè›"}=&’1ƒxh á6rø¡ÃED2´êˆ d~äÖß?Äè‰hTš‚ˆ¢3ß&ŠÎ©(ºEÑ9EW@ÿLà]J3‘x2ó ZKTªÙIàYwyà[—5kæèɰuyè1ÐsTRÈžµ±nO¼|æ'Sé8ñ8÷ÕP«C—±ãˆ (]˃Wª»mÓÊ_ˆtè0Ð7y³tê$#²C Fy±c1MJjXƒƒé®lüz® %ð¬€áÁt_mÖÌÒV-00¢ þP-’^| òŽ1¾¼hºTåßwVY'ÈÓ^.¯ÍkÈÆO)^Yperþýƒ ÷¼Ï¾œÓõ¹+Æô—&ÒçâMdÒkb[ó_3wÃŽé#¤ Ö,ãKB+:&; Õÿ(/ºêIÇ ÌH9æð¤cnÕáÿlÛrÛrî“xq¡tǹééþó/EÖ™–t̘|Ž5øBBš¶JP 5éßí\[¶ÇB”ŽA^•‚ìõ5n6›EèòÙ\ÑX`5n–“Ÿ¿Á¸ag†¬>|»9ÍpJ3tîºwI`ÆÛ,Ç@F+Ý@Â$]dL8„}ªÅ¾EÛr 1pS®_€bœ#æJ5)BÇÃs|=õÁöÄÑÇ@oPƒëò,†JäO ܲG'ç1&†ìêåtŸÒ;7åkοùö ŒŠ[°–ãc¤K´+nau¬þ½¨í·ôé.QW,˜¡M¿iõë(RgæÓÕ­]6‘¼èmÚ@T@F¹éÕ-Èò9N©3óiY*g1í{|Pd¢õ‘7¨^‘ü!ÍJºJžvÝ6»`™Q1µïbN÷òÀ]W©Ö«”žžK+òž"åô›zˇK¢? dÑ“±»¶œæ.ïÉ>†,f³.0ouOJ@†fä«®¿d„Ù¬5”•vßǧk+‚40dW5œôùûM™`%«J+ìtÝÔѧCöÒÍñ†´óšÌ²GäÌ_ÅéQ¦9ªË{fÏ®W˜a†ì¦Té÷|ˆî›7tLÍÕÜD&@‹ç+òa¤3 Î\Úeî÷B7'ÈÐŒ|^åaäv$®œˆ÷Ð1(ÍìÄÎ_ûûL¯×WP¤AóÛ¥í3Kzz²›]!¼ šØ~ÐÅùYäh"9Ëá§-M$çœKS}òhuU-ÆÌÍÒdz!ž­Ô¯U`æå÷ƒžøx oÒÅì»´}wjrJƒlUóÒ@‘FŸ>z`uH ²%äˆmÛŠ™ŽècAõÏtMúq,AÎ8¼'³†Í{Z û7`æy1èà&Kv…’/‘îÉ—7GµΗ·“û±[¤MÝ7¥¢.÷sáÞ=Xw08;4t݈+º d›€ˆ+º dk®èFÐYV§mÒþ[```%lê dŸ›ÒÔ„Í—09‹Ø9‹*a6QG:ëÄÊ.¬á¿p ³‰]xDÞÍ,³_Wêào@J˜ ,³ÃŸs÷­<¯¦!3¿+ù¬ÿT DEÚŠ©þNÀŸ P óŸÿ¨º™D¦Ý§L rmŠðÏδZYQ½R­7HÊŸÚò¡½ôŒóyšè˜1ö÷ög©‘“¾B)òqz¼1Ó¢•°Žˆ<€ÀCé¢CеLÅû% dV뺀è|à‘­~²®EC€¡ÕºÖ¿À#Rº'㺥ÀØj[g˜XMëJo`WëŸÍË´< ïÖ¾¼Ú P-¨ñR†Î1€ô­—òƒ.ºò‹´‘MxŒÆÀ·(ˆ? Ø…?'@‡4ºþ"‚ itýèÀ*ßN:½° t“< }¼„öwÄÝhØ.ZoëFÃ1гµ6Õ’r,ˆÝéü’ï»h½Q¤®™\ˆÔégp%R¾­§$Ç2 iÑ»ªòµ|a¡gíªÊ7ñÿ»ªòMü€¾µ«*_[féGû–°®’]à ïÚ±æ^—sßb £×åL€F±¦¾¯z^ 8 ¬bM|Wc:´x À< DId‚-³&,­ÁÂÐξéR.Ý#e•‡g«œ^ À¾ ѧ°ÅÏj ä\üƺÂÀ-„ÿÏŸ ³æ|úP‚t/OpyõÛï0:%—A.†t¿Cº—XnæáŒö«A+¢OÍkÈ£Þˆ»ž›ìe󨤋üÏv"Ë“ ]†j3À¾C—É §¥#"»J›åÅÄyÏÅaÚê²! ky‚׿¶ÕéÝaOÈéyFú¤.íÉÎW]%Ýú;gNõëžõÁ»¿î—~¸­fO@û[&îhÒN¬B%=*a‘Ýu™°P‰zçjÓB®«MYt·T›n¢ÔºÚ”E­=4÷0ºhí¡kö¢»»ÚôðhGµ)ÑQmJŽjS:CµéÒ³ U›* ¡Útmi¶W›Â‚ßlœ¹Asæ"ïŠ3Ç1г2ÜFøh±xª‰áÖ5dDfe¸iŽO51ÜjÍpCâ©g†Û1ÜvñÔ“ÐáD˜½‘o:œM9² …L„¦ù§”(aqë”hĬa%zE5¬´e7 ¬ÑKSá>Òëî^¿7ú&*œ~úN/8Nƒ`mUy³ÒÚ i¢o:‹8h¢žnº'F֛7]«3”9¥š”CcXð›ñN¾Í~'F( b¼Gúð»g½+d¼À¶K1ôéÌz)‘õR<"C㥘Ö_¡/ÅK¾Ÿ‚ñõ£+뛑Ò.ÿ ÛCû]–í@žîÝa{…||¿ý‹"-!ö÷û•×陑ß÷«? }s»àZZÌŒ|¾NÈÀ®§wHèÔ€ÛÉJH.ؤ§Åâ’ 6kÀK‹ä‚ÍpúÞ /4àyÇÐȺh1ë"ŠœÒnÒn-»¥Ý´_Å äzÖ‰E\žé)³(¹P ×Ë“\(Ó äzS$ ät2rýÏ$ ä;šÊ©ÉÄ—Må& t5¾àýªñzºF:¯—îr‰Ž©ÇúS°Ø;dRÖ¯ÒnÓ§iå¢1îØø>®¥FyL¿Õ"G€>ê»]Q2}¿¿¿öc¬ ¦ñŸ¥GÑZ˲:Ééc®Çú7¸6 GŸ6åcí¡ñíòïô0=bm0I—@.OU)Ëóùl¾ËÑ͸yÿýó5ŽoR!_6k•ƘÊÿz”7ã¿˵&hyÇ×+ýŠ®mÞ&+Pº#KÌfë`> ]>d¿.¥ ~[r÷ü]î†Çš§Æbx©´òN²3k®iÍÎí ,²]NÓD“N8M±oé-m+Üx›ÝMCãmÑ £ñ¶þØEãmø`‘îæÕ˜sÜx›!ÝMsãmúhCGdÁIãmŒL5¥» Nü> ›M„ã‡g"`ý91ó2ެ~a^Æ‘Ã2ÇÌËøœL=ˆÚÀ_ŸCK››Ñ´$뺱/ÉÔDß9×êð èÙú¬À©O \Ó³\«Ã+ ³«Ã òŽ]ž¢¶ªJM.c®š ²äfârîÀq$@Ïà…Iàœ Ù›c µÙ.%ÞØð¾y~1ðD›ÛrÍm3WiÁ™FºøL˜FšÜíú„FŠ„NÍ'|3‰çî®ÍÄ»èNGtôNdDÇI×&:5÷N‡“b:µœôÑ-¿€ì5Ò÷g‰oðfÒðI³rÍDšbËÊÞë?™sÆ@ߦÌ^ìÿµO¾™£0ûXuÙu>&ñ‰-õ?ag¶ì*«EáWJTŒ¹üàTíýöØcoí§? €s*µn¿Â&Š0›1n²ìðåèíV‡~õv¯ôŒžJ¨·û ¾3`‰ÄG亪è³I.Þĸ–:ìs,éÑç8óuaþ¡øèìñ˜Du¡©ŒOœ¶ùÒ]Æ íäeÌ—Ú5ÄÒ‰S<t¡MÜ¥èá8¢+B:NËcEN™¨>®ã„͈|tžÓ]ç™âó<¢+fŸ§÷4*B¯ÛÒ,e‰Hƒvto&ý}#$6ky‘_ï,fÝ:~t{»$+©{_$¹ï™þ‰™#Õ›+Æ/fáÿ="C»Ø¼þоléæ§›ß‘Ó<í”z¿È®«àhDZ±D=?·äñ°dh…)°Ó‘ Qeº†v:ôíæ7²mK‚ÝüƒÄn+#à í0²D[‚/»Ì‚FŒìþ/|Ûí_(Ïéínÿr!Ÿvû— ]Žô 5Ú¿\HGG–|ÔÈãiqœå»!è8KžÅqv|8g%hOîu[A{rOÊH0°€ªš ’»ÿ§hXþŸ ïöŸ;xÚJPî|•"p%CUléº~†`dEƒY³¡C¿í~¢C7üa÷½O»Ÿ(¾åR¸_éŸPyšm³|[Ùb¯H‘•êlº–ßVD€¤…ô¦åcvy•¡›y| %Y¬Íòiû‘¡Íó‚Ï•ƒ$}·ç­ˆv¡´Píhu×Õ&Á›¶QAUýG!DåÖ‚—’^©ûÀJšTÒX‚¾µ¢dî (tÔ¬2>÷Šä‚çÎ$Uóå7Nš…ÿP#ÃKœEmÒëšJY ò -[1ï-[ò-Z¶;xjÙ’GhÓ²ߦ³>Y‚¾<ë“%hÒ²ÝD \¼è‡"t×'Ÿ÷1tÔ'Ç4rtŽ–ú䙯EŠ@{}2£ ßvEÕ #ªO¾(ª^ȧ]Qµgˆô슪ÒÇŠªÕÞuÝÔI3ŽŸ‘Utû¢K’sA_Èî¡$-–/ÙŠî¦LCõG)>Ï—]ôBFÐŒEí ù%+sD¾•þèAî½`ÍØÔÿ8¦èYØõGñÃî=íú£øt`W4¢Ý¶OÚm`{½Ÿˆ¬6°Ûn«ŸŠÈj»Åu^)wW ¾-àwº€ªIþ"gSîäñ¾Š1ÐBUí®”MªíŽ<wP¨êŽïóëd€ –¡9ŒzÇSUJ êU¨X¨«š9VòŽ̈́24¥ÔÙ–¤Ù(»ó$x¬AÿýU{„¬s>UËúH †ö¤—Úž<í z¢ jöDozF>èøFžþqÞ=eº ž)Sò \‰3e*Á«VÅ 2ʆlP÷‘ÜÔ/¤ü—»¡HGz¦VC>U,|‰µAз]:"0€ -•KBµ´µlº“ Áàñ< pYjt1!®­;ÂÄC–Ñ"ý2bóƒJ lÉ4Å # Xr°„à™ H]áÝT`*ð ØÈr*ÐeŸ m‰è(Û?ußxžËàOrQõÑŒ}][tÂz`7táOÿNv]—uÕ<]øä³3Ÿ¶®Ð ÜßÚ¤K2þÒÄÝH ¨É²+M¤g~‹¢.bLúf²+êîBÀFMÖ&qü]Dž“ÈpíX¢òé<®âu øÚO£‡DYdÆ1ÏZW-$—¥ñ7Õ¦+"£KÌRžg<ò³Àc¾Õ–,Ñšjeü C?æ±Éüóï°'ã“PÇ&6D>ÏŒkA$n×d]Ó¶]…Ç<Œ„^¨Î—nÔ±ÐÈ®ã‘ÚÔæè?3ÑX3ÆÚò£çàè&ËwÔ{´ùÖ–[¬L¸%èæ7â—>ôÝ4¬q#]D%¨s׉’O©èÔÐfYt áÚ%#À¢¡"š½ô$0Ý»‡žùŬ‹PñLFžf:ûÖà°àË!þ µèbÎTªöiÉÖ„ñ§ƒŒNp¯ˆÛs ]Yç˶¡sÕŠ~vùòî…¢y¥D}cÑq¥ã>’ôNàãGkÇò;/sßã£ïÑQ0‘ìU¯âèm7ñ§®\¤ïŒ"M…Œïfk¾.i1æ-"‰&Ëý'W4æ|—Y >zxT‹þù›åjÌm‡us"_ª\Tä åÎ:Œ#ÿ¼ )¾KÑI2¼Ÿ†ïH?|EoH…¥ë0ä´öhš9KP÷W}?ÏeãOY®è΋Ñ"2÷—}ßxÑNt(”k†Þ#ß³;ë_ó.H«²ë˜Î SáS$8¯2 ¾K¬ÂÞ­ð®Ó&]“rX>IAßÚ1TÉ = ÚÚ/xw‚BK0t¨ʯ´÷´¨ÖXý“xÏ_êŸhD“C_C¡GâÅßíäãùnĬTçü°AÔçü°AÔ7<°Dîd‚²A$@ÂÞlƒ£‰©Ý~€¦*ÈÃ_ÅrV(–C¼ÐÑq ÄrˆÞ:2°‹¾=¯.6úö¼~¸Øà.6úÁ}ýp±Á 1=5t±!§˜ûE‘n5ÔM!^dDÜÁS…@ô« :D$^dDÜÁS‘@t£*¡~"·nŠêú$H'ݤJˆA»nÊ‚A»nÊ€A»nŠªÂ"Þe¥¤þ*ª¤þT•ÒI7Jýå"=»Ôßåè¾ÕâZI訓¾§wN[uq¢ó\2|žO,ÇﳕKó{L†²áC6ßéB¾îöÉLÚ'÷ "Bn¾Kï»Ñ2“FË5ú1½‡]ò¢ó<XÖ¿ÇC|$/Ä4ñÕ3:OÏà bÝÄïÒÒäùX£ÇÝó ¤(mhšYE½se´nÏ9ëý˺­† £g»G £g[…æ¼÷žmý5y[z¶³3ݳ-ÁÐìuz¶%xéÙÖZw FUô•zm!5‚¦~êõgǸcD«šü‡;F¤T^$he*êä?Ü1¢hÅxD{Œ¨Á#ÚcD hŽ üÃÒI}uÃí1"U ªH{ŒèJz&W;†Èé…`QQR¯·ïýPQÒwÈû¡¢¤–#ÀÀbÝVCÐ’·ÆM:{SWz&ô6°ŸØ“P°…œâøwk Úõ.´m!¾]ï’AÛâÛõ.´m‘ Ã¶EM?þë‡m ¶-tض¨…¢ÿúaÛÒ£‹qض`ÐaÛ‚A»m ÿ41D:l[ðu»l[6<¦Ã¶E}nü×/ۖ˘ĶÅÚ6ývG¦ÆÁ³ ­WÙÿ®G ªÊƹö=­.åUIÂ÷b ¼*xà®n]3•¦,˪³f*xà®n .K“eÓ 5KE@ž„‘Ë÷¨ã›ª‚IŸ-‰™êÙ £ûO¨úI»z)ƒENuìK­B/­Ôšˆ^›ÿ5øü¡øA‡â¿½Šÿôæ ïµé-TÂĤ1|:Xè‹\c¡8Ä©¬pÈ©1lq^@ÿ~ÃÅc–”gö+D7\ÚkÊ^ `±@^!ºáGœQÀb¼^·~zø«PCÐ37›ÇñFպ⇤è¦7s¯èÚÊ¢{È›¢Þæx•)‘×Û0í©'¼®?µªÇ|½ öµß4p­‡¡Bàñùß¾öÑÍæMÝmŸY-`OIQ£¬û9›E§¬û9›¹Nól¦žðèážÍ(C#:f3<"1ÉXˆ©yÐ2ÑÓ*c!¦æEËX@¥PÓÅèÛÕ)ØAûÅ”‘˜f³U^EžEDMÄæù_Aå· aªƒ|ÌÊ2ÎV5‘F÷ æñà ÛwÆò5a<4½þÔTæòºo³e]“C0€|G|ˆŽ¬âkö¶Ø HP«ŸîàšOÝ´ M5llùÒ9!ø²mLϤPõ4o,Tæ-²G©W”ìQêåD£Ð’ÝAÂ9Qý*„?r¢täD1èȉbБUiþȉbБÅ ='J•_‰Â_9Q|9®œ(Åc:r¢—ótäD/cK_ééÉD¢×O¦¦ w¶p¨®‡ºnê¦ÞŒp ‡ì!¨[8Ò½{¤ÚkÿÛOû]?ß‚¾ œ>Ó—oœ ¥ü"Š×µï’ ‚ÄNü¬ aÃűE éV~¿èb^wp2‚”Í“›Èºù6UýÑË¥…#+ó£×£)ùdº üF7üa$ùDíGÔ›²±œ–¤Ç?¢g ¿FµpTûæôÛ cFZa2¸“sÃYm˜$€¬ö÷‘ïbùžªZªâƒÈÐ@~äë”ÙŸKñò MSfÕÚ Z.H†È÷)ÔZªäe +g¾ DÏúÃ@~äÙµ‹Ê=+¼­K›ö´Cä)¢¹k'Éüq=´B|‘¾…Ündp%+º“)¥E$±’Ÿ ‚¦”¢R‹—$K¦írE²²`ñT¹¨6M?S\ÄèMßE>þì!‘,=æ·*û~§>ëûn@äûlJ9’Q¢¹jXG¾<ѯ¹‹|\ȼšµÈ’ ù<óQ™\FLÓœtc ºŸ¾§R‚”B§S_Žs3¨bIú*Ñ$W‚{t+i›¡¤ÒxS‘ƒD³—OÌÁpXT½Ý»“ž!л§…„L+¾ì–uýÎûÇnY)ú“÷ݲþú½ì–;}hïÞä¢:©§<_ZiBÞ¾EéN,mùÞQoNÅa©õT–R©e¤ý´Æ­ÚjÅá½sS¨NÊ50囎¾W*@qçöjìáGÞ6¿{ø‘·Ýï†~äÜŵdËõEÌ ”ý½k“3-bN€ì¯”"æÈþDÌ™1'@ö×"b^CÐ%bŽÀü„ªCb¤ß•/´VùE²¿ÇgWD¢Ä«8Ò,o‹|j!®ºP«4Oæ©Ó1Ô÷ £C'SÞ‡Ž.7\Ø~>bÜ«tϬ±ô9–»} eùÐôúo:ô*º=Ò•÷ª¡‚ ¡”Ï%Ðî |<ÜvTîmÃÇã‡ÝÑaw '€ðñ°ˆ˜ )"`wÙP³Ý>´AÄœÈî  Q1¼+)ÊFE‚FÅ))ÂFEÂFÅ()kºT£bøKI±ÛèhTÔ7()ÞbÑé^d-AX‰mz¹ôcºè8@Ðá Ÿðð‡CE#:^.ý†?ð¡/ ;„—-¸…ÂÇË’N Ø! êff‡û º™Ù!ƒ‡ýô¼~8`ðeZ¥0È ‘%yDeu 3ziæ@¦žH#w ³ghDG S?=‘Å)çkuè·³gcÈú‚†ž ¦œ¯åí9¥ÈnÎ×ÃѳÁ hR ¤³ß(|>­š45Ô¤‘ K“†AÐ¥ISCÐ¥I3@Ð¥IƒFtiÒ ]š4hD—& Ñ¥IÓ îÒ¤YéÒ¤Á¤K“Ý¥IƒI—& &]š4˜tiÒ`Ò¥I3"Ò¥IƒL§& úÕMš45Ö¤Q¤K“éÒ¤A¿¦ç[«ÞT+A¤÷DµM²—éÛÉUC2Äêàþ%ºÇÌöŸýóùl}2«rõ£ãš% û ‚þEôäØоã;—‚Á™RB»Å^­µÅ{îšÜ×~û'ôÜÓ…ÏÀºöë…×L>­ô¬`õEàÿ ;·­GYf ßRâ’Ã>_=F—à."&ÆM¢Žÿê*…Upô{8[# PõÌÐá¨ÖÍiðøû•€‰FéìÊœà郧f‚ý€§ žfWîO÷<ꨆ žî1xšíL°xzÂàiöó€§É­}àé }ài"ô§Éoô§ÉS{ÁÓTéO“çö‚§©Òž–<Í0Ìž¦×ô§¢ô§é5}àiª´€§%O3Ì£àiIÁÓ 3ÁàiòD^ð4ù@¼àiòÍÙÀÓ’‚§AiOK ž¥%îǃ+yi[{TS™ŒŸ^bán–••šÐ¤ŽâÙ½§G… ^‹%ì¶‹«„C7ªŽ9b!ßÍ¥ ê¹<õX©Y7ÃÂøGoáúº7#úZ<^Îámc‚©Ÿ¸|eBE„c£Qp Þ¶ãØÙáûZÌÛ Q^w¯WhÉ®J^PƒÌ—(ƒŸZ ¥)§D~¾ßA»¥°ðfL\ËmršW•|“d ÊhgmÚ@¶ï›g1ɬ#_Æu·p[F÷í0-c®báŠ~l{™O¹'je¡fÉáU–š¬Çv›>Tyè”êjÎç1y”ú]^o»RG˜KÖyU«5÷D¾Ž­ËV2jpìz?+•XèÁu˜ø ×AoíÁutäÖ±«ÀÓà:´Ù <®C 95A:e#à[,©öP·¹Ë¡ÀÂà˜¬¸F·(| .‡Üb$Dá[p9„oúÀ~–Y-’v’‚‹?|“T†¨eÇðM,á:·×¾¡;|y˜»3Ô*ar.‡ð†Z¿Ê«=ˆø.ADO”3ˆhèϼ†Îi\жÔТÿÓééàË0•Ÿ ¦G­Œa±‰m›”2yõúx”ëväŸ}"]¾ Ùt .º#ѾíÓã:ºtM%ºlVá8QÞ,§¡jIƒRYYà<5NeeóX@ Q*+ \ÇëNúžÊª…6*{×`*; B•}îTv- \ÌfS9¥…¡Kh*§´ÐFeWBT9¥…6*û*4•SZh£²¯¸hCe×BwÓôcè¯sȱºëœ~„ž:§ÖtÇuG í\&)½fà¢Ë¤¤Ê𸧒eY’íœ_PFGå²G5•±bn¶òz´‘Ä·M•…$^ 3öG'hÓFñÁ®u‹ „èÔ¿,KAx8àÕãÀr˜_öc?|±Ðð¦KŽ£ÞÐiÄ÷U'°Ÿ°Ã~ŽÐ&µ¢Êd¨r,Œ¨m)`øU³u‡…1¬ Ómü[KñÕWY&mÒ¥…Ìdx@yÎòä‹!Ûk&WÜJVÇí»Ø2•¾Ù·x×ï¾$¿q3 ýoƒ:_H5äôyÏRbá ÅC‡7"y}?Iþ! ~±nc‰ej®É%¯W×fR×ÍðF7t×"¦Œx 5I²ëÜHòñdB«àìdNó‚ûáûNJ!^ù0·ú7†'˜¦ÇÅ ¯`š }`‰…>0 úÀ4DèÓ!sí0rÇ|ÓháÍ–ÙR“ð0ðe¶HãÚÃÌ.„ýñ0pf¶,BãÚ£…‘Ûµ§#WŒÝ®=TÈcî0@U C˘»|µófÕÂèð=ÂPZWsÖôU……¨bŵêÝí[§“já Œ›»Ï¼´å<7}ûÅB ¬k«ÅH½C9ÀS£Ýäÿáw½ÞzPÁŒ…T¦SN”W8vÒK›í³xWi_µô%f1›C¶G>–ɳü´ôÁuel·s2~ßãëG‰Î¿·!Z¬+°F=Q•eìr‡î„/â>Œ$ÂÀ/T³Ø3}èrF†ñs(dÙœâÊF:O,ôø>Àš%âG⌀"ÎþÙŒp†Ý,Gê Ì„!“3ºý€CÉ¥ê‹âUÉ I:¥îbjL“bPãšž“¾~ÕOɤÂ*s†!4Å¹Ðøv³èîw.þpõS ‘çæ80¾x\*“Á¸T²ørðBÜ®¸PqúìÑiÎ>‹/Ä ÓB¦á! „Å×3øÜ:8ƒ/MXh/I _bqàLÈXÌ'Øô²8ô›Ov°,Cg5ü„qN “¤hd1ô˜Æ~¸O:¤T’LF¸"î\ÚH®Ô¤Eø„Á˜‘ñ51Žf3dí¡…vøRÓUòû®°Ð_zȉñîŠ7þý«]ß·é]æ¢Ë³g‡…ØOû>¨èû>°˜ÛhE[¤Tèö}x˜>ƒ3`, Iñ£¼:Ë3ˆÇc”cõ>(fª Žd Æ{ÌÁµi25òBÌßÉé@ÿ6ãÊÝoe&ÔŒ]N¬l`ìc—+›™\ÑgB]c¡Çʦ#WŒ!¹ ž aŸ¨§€ žŒäøš¥ ;ÉñMá b'9¾&Bd'9¾½¢ÇS€^Ñã)@¯èñ Wtz Ì&×“åø XØYŽï¯ÒÐÐeàè!Ó|’¡Ï¥=²è µÂøÄÎÊÜ:>Cm‘+†6û ‰L#Œ9íƒ&2;0æ´š°}cÌi4aû †èTû  }öA }öADè³"BŸ}ú새ÐkÔ¥Ï>¨&JŸ}½»Ï>¨'JŸ}ýû IM@Ɉ*-öA’ÚÁ·î³¢JŸ}yv›}Ð’_E!_DZ•Ø>”‘u.#ÛKŒ»¶—º†l/1îÚ^ZŠêÐöã¾í¥®x~',tm/uCÙ¡s{©“fܽÑl‹ƒòaìæ©÷3EvwÔ¶ M‚ƒà #ãHm»˜ ˜L -µíb&`2FØrÿ~®¸àÌ­¯ÇLvÍ1­1Ÿñ#ŠÆñ°/Êñvç½(ÑB/}Çò…!ì‹®BMF]:Íw>Xè†â›€Ÿ~(þ— ÝPü¡ŠŽpZh‡â?(~OšÇ ůé=PüŸÇö@ñ;ºVº¡ø¿J7ÿWi‡â‹ŠO•±s© ÞõŒ£`èﶆ€lŽeaÛvÚ¶Y ÷ ©>¡YØÝCi¡çÄdzsèM&Ó"í°ÐÊë•*,hkÓ!â# ´ &¹5sݺ“ôÖÌqëu×ßEM¶ñb‰Ü?^˜RO2´Žifë†ßücš9pá77cV"¬8ãwÇÎV7HŒgü~‚ŸÉC7ÓßÛÅmBÞÌíê¶ifõqBõÇíꄲ-BY5, mµÞz“®8Žëë+|\w -´ÕRW9!6 »EN,kCê¨1³ŽÔQ/B\G}‹XÖ†ÔQßâ“:jx…·ø¤Žš =uÔNÞâ“:j*äŽ7³lt€ýT.þÐÛ°Ùj“1¦¬ýÙR¥J*¥^aþpØL(kK™ ÎÔõšz A’4’b)T<5 …hF,Œ,BO Ãðsk’F#®HÛ×YÜp/+"ôxYâ~êeE®èõ²"—ôzYÕDéó²¢JŸ—Uú¼¬z¢´xYIêeJŸ—ÕD”/+Úð>/«åÝ ‡ÅÀŸ€ÀÍËä' p#¼€ÀÍ­o¾Ñ ÷»¨.(P_.'@uÝæür9ªS¡%,Þˆ<ÈÁ/?F}z]Wóû;k84ÇÌ)4®iæóž…É1sJoá¨÷Ï]‡Ò»q#¿œ7Ö ñ™½Îf]έäTv”#æÛN’|ªrž±Ð\Q=Œx@îé;Ï„L{, ÀzËfšoñz™a!&]ïyC;§ÒrÄœÒÅu;éZõìÇ(K,dÇÓ„%wðK|bÜ!&, l'whaèNDœá£`¬âI`G<§_òzƒEüÂÏÈëúÈë5úÈë ÆÎædI~±ØD? Ä@ã—»“Ö`¿Ü ´3д0tÆÀ@ÓB­ÁB< ó8Êé7s½8íÍÛ8*ðëÕo„=OD8š`½À¯¡ >zZèAhvDÚP& F™ðkèµ-3ÉOüùÓҫȯ‘/Ï¥Q1g¢…ñ‰¯‰€+²_óf؉¯‰ò_skî(îZ²¤}¿Þlµ‰åFÚBEŒüzw1J\Äȯw/äË1òëÝYÄØã"F¾—\Š{\ÄÈ÷’ëCc‹ù^r}(b”¸ˆ‘ï%×®"F"ô1NXè+b$Bo£$J_cM”¾"Fªô1Òßé+b¤ÊØæ¶ÓàdN ØÿаZYõ dr\þK ÿ”°“ ½¥ÅÂÀ¶'мæ—AJjaèñÕ] × ÿäð÷øŠãòߟþs\þû÷WˆŠž9®ñüÉáïñ1¢ã¡"›º-œ‰¡nK ÝDb¨ÛÒBWÝVcê¶´ÐW·%±ÐW·E„ÌcÖ¦‡ª€‘Wx$dCïNÆÝ7tÚÀu*o#¼P¼Í­o‡léý,Y‚ñàîðW\OW²)j,ü94©`uØ¥†nÏ+½Dãáű?®­Z`œ‡W'gtÂûã<¼:9£Þç¸ÌÒΰÐÇ%Bg´ÆBg”¹Çþ níµ#ÜSŸ8)8¤DâSéxè¥ÒÍj欱0p «–C[ŸiȰ‡ëúLƒOÞ9ª#üí3 Îà¡;žjȰ2§~ë\õœÌíó«…ü÷ Q{5-Þa¢K‡V`á¾eÁnR_>ÕhßæÖü§àjôºg׊±z=‰0BõT´-03‘–9ê¬^˜jºj³@“„Þ×ÕBæ4¶FèòÝÔ —‡w¯pÐȈWPƒ^-´ô jЫ…–qA zµÐ’#.¨A¯Z z5èÕBA¯y×'1dIj¡Ç — }½UºÃ8ÑæžÂ—rO aƒK¹§„°Ç'Ú<ºž¬B`"ްH÷lD6âQè i!8®ãû±al0ÙˆG¡ƒl´ w²BÙH 1Ùˆ£:>;Ùi{ŸlÔe}A~£‹lÔ%ªÇb¡‡lQEž`îŠÂ3²ÑÒC6êHKúÈFôgúÈF´-md£¥ê‘@i!­ÊlJ Ù¨[|‰w²(-d#Ѳ(oÎÙòFxùg»½—EÎ݃†Ž'3²ÙDz¶8Ä$öqR¡GVUKêÏ^µÅ#ît ¯IK ï¨K¸$Q,.¼#QìZðŒ¢Ø½ðΞVc†óèî±£G…<¾8¢/Aý 8ªU³ØçB{vµúK4ɉ£•õ7úø©R³B>-”¦ ƒý°¼,pëy~Ì‚^‘l‚ˆmØËºdÊäþƒCÖ‘ÎJ8Kû/, YÜë­Kðú4U“Û3{Aó¡È»²Í©Ã–àSª´m¼š:úÅœ oîvpÅð¤©0p?µi[8>uÝîOyw¿Ž'xža‘/?q7P×B‡ã 2P×BFø‹ÊÔžÅ+éaÎ8P9~ŠÊ"Ô½pùKŸYný.5@×X¸Ýzå<,¹ýKŸY„2MÁB@ #‡°IK*Œw Ñ‡Æ =…ê¹U_÷²£ð#òä(Ä1ìCów‡)ù|Ë’>ÌÍ-¬Éo¼ï ‡.ÂZãÜôs ~9*×yT^ÉøQ­SÒgx•EQ½T eµ,+eÖuõ(ˆm äú˜¼­ûº«Ä”‘'G†ŸX9}ò¤SeŒ”KŒ¤~¨R~;ÕÆ7Q+c§ZGè¼³êý©ˆr7üÌ€C¤ž(+»<£ ?±rZ”%UÞ±q{C¢þöñô·~±)¿I™Ìé‡<»†«o&¿ÖÔm]Öõ·ø¥ «4nZè'š_uIZ)0å6«íÈæ“ì¦vxËœ(#¤,·w”Os;õå,¨2&Ê„®®ÙN,JªÄ¨¨r£q¬O$žu*ˆrà›gC«‚›q|Qåm2óm1¶|Kߺš›eî»ò;(çPלµ]0 3سJ7¤ÕöDC®úú0åÕ®‹’Ü= ²4ʪy•©.~ehvÌ2 ^®žMU½¦æ+èÝ#¤Ür”ò]”é§éèÅû.Ü6¥­=.ªµÎ›þNFÖ¬ºÚô³ º?ï†(ùžO Q¥Ô$<÷tØÞàåÿ–*¼ õ±œŸ'Kb9¸€òîVÒkFë;ú;þ·*· šE9-oöI”W—r¬~”Vj¸B½ìîgmG•¡]™)eA•¤ÑdÙZ€X.ïH¾‹J­·èœ[•ýª¤ÏÎðʦŽ>iŸ}O瘈ï<1°žú$볬ý~mÔ΋²*!fÊçôzUdœîT¹V‰ª¸¾žÔOƺø ª•4ñ[µRÙÊ÷+#­“ì_H“ßü3&fî8”̆¢kº9}Né Iv×6*-Ù]I=Ö´… i6úƒIDÔŽ ÷\¬-8k†v¬‹”\1¶qÔ&\˜Á™¾ÑàB!ÎnÎ¥'pk¡µF©Á…BZh'+ã’OÎî‡[ë§V)äÔ?°`wäH]w3½bh)(x‰d)(€½_v?œ˜šÊƒ÷sNbèVò¹½ë¥äs0û8ì~ÈËþq)Ö ÎÝõ?ipî®ÿ™pÆ<çîúŸ gÌk¡µFI’dL“×7ªyo€M~ärk‚­¨-Â_Ò÷VÞ«þG—hã-- ­B©„b Wü©,†*¼1Ÿ&H»áá§¡Û[ Ëù‘?,d? ÒuqÖ¤bNsˆ6xxpØÖË‚æ-Ç1'¿ñ†Ù–HìÓ¦9yê;{tŽ¥ºõØÝûAü‚¡C»ƒAú‘’¶oLÿ‘òºdh’Wú!ÊöåõÆËÿvfK°ª:~¥v¦/÷ý^Uû<‚3έ¶C­§?€€‰‚]Õ—_a‹L ÉŸ£Ïºws…Ûô)ü3 ->ˆô/¤üŽ5Ý‹·˜IÖæÜâ6ÃëE•è÷3FY…\‘º©RdÉÈ8Çm$Ø%«ŸÔtdVÐ#ò}WHâi$td{êˆÆúË”Õ-ËŽÉ-d’šŠ¥Ÿ‡Qðœá£cG#³Á[Iƒ7Ö~•(Äùa<Èô¯oó>¿³rdE!òÔˆG‹UZDÿÅtÒËŠýç+ªÀïV£aQÂÀ­¹f›OÁàjÇVÒŽ6åMŠÂKm n~ëHgðsÇúìïÖ›:.FP(öÕ…ƒyÞmë ÁÛ±²’ÇÊf¥è?&´‰\› y ½hß!OùâaÏ#êIV,’{DY°=g“Nµ‰ë|'J „ýª8nºTEÍGÒæ)'¹4&Š&û~÷ Þé·Te~ÙøYÚ¡Ö^ï(BºÀqZPõÞåF›~ïr‚HJ²YºåøÉw>×ôÊÅ =&sWÒ:]Š‚ÅËð[,z4Ñ @É´”i¦#z™7+a½rpªçƒ§ŠJ’±¿xäRôUß'M9¢Ž“¬”yl¬Ëó•kôÞŽ ½Gp?Ÿ9t‰ãá‹Hà6Ír10ʽ2L¿)Å]}WvŒnâ ‘°±å]žh³Ï•d´"¡5ÎOv’Üû¯ŽRŒ@9:®NÂGÑq*‹t^úTûü#PŽŽëm¦Â±ÃѤŒ“rß¶}ôÃc"m)(É&m÷ަ)ë/pîyaí$ã:Vk‰HN´£?‡iÉ·¹êdÙ­("׉&E*ÙgG8Ñàæ-Š)Z̪]V”’ ¬,X•R‰¬ä“ž?M´$="rùhŸËá“ñ ÁÀ2æüœä>ÑÎùÓçD#x¢‰ùÃßú˜?}¯§¹M4*jµr0©ëƒ`¢±‹)Éú1M“f‹Q?ží:)h<|é ç •fçd©é™\WùÇ™çvLPW:ê¥úŒñÊVCÔEŽºiT%6ÍiÞ,ß“ºO€µ$ËanúDO^’äÐô¦jÉ?U£nf#rN4ó¤èq0)*½;O{¹–}µ#ò-.÷y`øZÄI¼ïtDý)&ÚúŸt<‰¼»j¬ãq¶,Ťc;;£ &‰Þ–ç[Ž À .À€)¢gò²8s­"àL^†gB¯H¬"—\‘çAÌ^‘ÇšÝQ£@Hb3áX‹È2#Vn¬  É„£2áˆÕ„£2áˆÍ„ã÷áЄ#6ŽƒÐ„#VŽNÈ„#6Žw84áˆÍ„c 2áˆÕ„c†&±šp",˜pÄnÂÑ-žêºÊ>ˆ4™ptB&±›pì3BŽØM8ö¡ Gì&#¡ G¬&{wd« ÇHd« ÇE´  G¬&#‘ G ‡96¨”ßRì§ÆÅ~¢SØÄV짆àCä€:X“ðG䀲Iˆd´ÿ™¬бv«Z Môˆd´Øâ»ï[ù)¿4Ë\3—°Rz÷2“û^ó em=BÑ”ê^·U×ÕýHܳÒEIUf?ª¬S4äß?‚D8×ó8få„ÁH{ÇÅ™„kžoYåù®¢§‰¶VöýNìÜþ§ó°áÿø6…7m(¸œ_%Ïg>•ÖÂÅäS-Ü‘OµpÑß|¬…‹Ÿn¬…[ÈqEkáÖ0b\‘ÆZ¸ŒW¤©n"ÆI ò3’‡ qvJ¯“—g‘^g ”^'§ˆEz}œ!ø ½®¿¤÷Cz]¿Œ÷Cz·ø ½Ž[|^Ç->H¯ã­Òët¨6ÔáÒëz\x¿¤×/¤=x×sÂÿQDLEÿG1 ?ŠˆéGVÞ f ’WhÕÝÜ`¶ º›Ì$¯Èª»¹ÁlAòŠl¶t‚ò²ç&ô07A‚ÆÜ„æ&HÐ3”#k¨#O^oKD;§Ár$I›à8 Γ‹´ ’N…åH61—#Ñòý£ øPŽƒåH0øPŽƒåHôðþUŽäBZË‘ìiß#ò¡‰ž6ï_åHp§~S(]Ÿ‹8¯ç*Pã†@û S6*qœç¶éG;Ï«À®A÷yô£Ý[©áú^ ­JÐ7)I°S~¯…V%ø ´Š_&´ËÌk0ü!3Á™y þž1襭¡^%Â<Æõ¹™!èZÝ Jf^‚žÉ?¶A™y >ÈÌëaF~ÈÌcðAfƒ2ójÕuÈ“ÌüØ63êž™yÜâ“Ì<þ“O2ózÂ’_2óòAfþBZeæ÷dê<®Um¾/ÂÌ™Ìßß÷©¯¦d’·{Ľj,ŠõB,,]×íc²ôt/…—Å=Ü–%k9Ëè zçee©ãª)î „ o¬u ¡ ‚MÁ™j‚ëX”%…½t*K×ý¡,©ÆëþP–Ä g*-¾ñÒâªqïå\W^vDîÉœ|jz¨¹ø„<ᓲ_û…àíEx Ø‚¿²žŸ»ª†®ë?èÄÀ“¶ÑZóB‚Í Í 4/Pk^HÐX±‡š4ÖEì¡æ… š‡¡¯5/$ø y¡,?7ü¡y¡6:7ü¡yÁ'Í µîº!¸Q¼dO0³˜¸‘5³x‚™ÅÄ®ÎõG±UÙ“ÓÄV—bW-ž®Nª+×iþq¢×3‚"¹"ýqß7]šl—Å-%è )›ÖLË:K]ôÔ‡1ÏÙAã§aVçŠZ Là>7÷šêˆC~¹t„Sìû6&ô[$#ÏRÊy¡å_¶%ðÉè?+ØÏÈ…Eù£Söä å'¯jôpYšþGÂ3²ŽïÜLq:cÒSä°Å÷Îá/9­ë¬A¤.MÏã]ª£ŒX“µ´‰U„“"ƒ“,e¦mߤYÇ+ƒ Èð$©È.äïÞóÒÍ“‘J:ámR™ —dE¯-~ú#z)—wkKµÌy1Îø[!hrgü1eÚ¡®+YÆ¼ßæ5Þ‡‘Žº}mŠ¹Û´E\gÙe$‰¤=3yJ"iY¾„ õˆ4û¸a»ã·YÉ¿Ñú—M1–Äüíi± ß•ˆ ì’Ïz1z[6f!Tvpƒ8õî½,;8áî½l;8mÐî½l;øØ£܃E;UÕ£«"Ô†\ÌPÊìRÝsC.fÏýUݳàSuÏ‚OÕ=7>U÷D->U÷D->U÷œ!øTݵøTݳGþTÝsBäSuOL"§ˆ¼û¢Þ—x“[ANGŸõuÝÕ)… { ]*¸ÕlÓEàa­þ9Â>JõèzØ»Eü{ÊÿY9|¬k*o+ ÔÂS»W]´K·¶Ü?Ê!|*×IK£Ð{ÔÐ5{6ì]¼ü–F¿µk?¦ =›F³.†B¼ðY£Y;é¼ðQ VµbÈ)qgÈ©SAÄÝ%§¢Ëãr/kzÆœŠ%çnë!ès*ø](j1À9TçT MZ /àËÎMí$“/$xQ8¾ÌKAby°ß6Y‚iÛ&Ôá/¹M—Ob 2™ÙÊß;û,{Þ Ò½¤~ã"/Sv,AïãxæÜ$™‡eF¤ø<D^-?㈈¾ï¿UÜíøé-û¸YkÜfh#צFŸü8¸ÜJ>ƒN=Q$±‘:õD‘G:Ëß?G˜°öad×çó¶uh¬¿™ðz(Ä]Ý$}Œ¾æ;ϱD›â‰6—µ[ѹ.L|Q—b<ü¬<·“èT0å)'%!®oØB‹±Ä9ñÄ9‘»¦£®'ÔÃ8'â½­õ„6çD€¦ãµžP㜈÷þUO¨àS=¡‚†zB×"þËROˆâzBÄý(ë§í;?Êú©Üwž}ÈÚ±ç»?JêG»÷/CÕi žÿLj‰Z ‡e;CÐ5K6|ûb„ wɧ‡H~'ô­`©Žž¾w;zB)[-¦F|ÿILm¯;e‘ùþ“˜Ú^/-Ñ]mC^dW‚P±‡í¡¹È?žó¥©èÒª+?°•. m˜„ó ¨?¼µHõé¦[‹"^!è„üé”Ñ~ɪ‚¾AÈŸƒÉ^¤c8zÆŒ‡tþ@0„!áôˆÚ<þcÖ¢GGvAi=Â#K7zTp¹Hù8aIøz¥v ËqM¤Ž9Åý”SXM…™&ËÞÊööß`ôþh¹²nf|!è™À:Žç¹KRú&pŽé<Ä2€Y‚0EMÞ,6Ì”nŠ™– Ã;ØÏI\Nsž”ŒÐT êeØÉoØc¤F¬ÀzX§µ[ ø~iIi3îqÚ«ûT\ +òH)ØÆ„ui­|>¸@äñð¡¬x5DÊ8Âÿ ‹íäsÿ©ÚtV¢!ä”h`šª“U94i6$”a–àÑâÆ³©œˆ¼EšÌrƒ §Àô´>"<Ó±IZ5Ò‚óžâî’>Z¤G‹U¿©Üd  <e…1ÄZü4I:¢ÿ¨5¶â,—" }7•súÉ–‚‘ Ü˹úd_êSoœ) Óõ#%;$øé{GGUçe7³¨Q‡¿ dÃÈ–ÙÞ%"˜é'vöêK¾w"]¤Æ%ÐïÜUuß,Ë‘ž‰œX› k‘>HÍ“±ÿÙ–—#[ —‘ç=RZÈÚËlzïeûéz<ØB˜…*—«¹ä‰W›T½Qd¤×¡es$üÅ}õÍKYÃM‘iB‰ÑQäIWÎÝ®¬,I¾Oµ#ÕæøÇb® <)¤ÆÖ¡LT{íg+çO¹ç*ŠH’މ¬ÒOÙç]†H÷Œr8.bÅ»'-]süî®v©Æ™J ìÙûìéZmhÐ[bAHÅ#vÜžv+;!Œˆ N²Ì’¿;#«“á™È/Šx³Kµ”l ®kÔónHMÍÈq)†Bç*òH©ÑJ9ë³v-šo®L6d‹B¡¬2¶O²3S9%ZfD²á?ÿ½tÜÒ×ñP—íÚö¨?=ÇDŽŒ,ÛÍϵ‘mÙá6=9‰§wh -A÷nÜOò›vËè§Àd€I޲^j·mÝ;47½ðJò6KNv—6#ÉÛüÌZ=b#¿³ÌËWäñø…ƒØÚ„„õR-2ƒÐ |£¿l„ˆ=PDg1ó±(úò› R|£ù˜?\%âj¢¬—1ñÒ-4¶YȧïeW´ã˜¢‘,4¶²`c^8¨ú¹lúŠÅhß[ë¿üA«\1²kã&ŽÑ» -ÂUÿûÀþhüe+("C9r²ü,hÃô#¹}´Ú­+¹‰§ü?ßFÿ3”g"s¿Tžö™Yš{ATh”xÛØ!‰Bл›"°‰ 3}țƹü Pk¹òLüSòLìÖ - P!ø¨ ·‚_ ôÌ'ñ”ê´bå¡B•qø?*„*# °E#«*¦ ~T1Õ~XR¦xþ(°¤»'´Š9O(@,ˆ~ÒÆÍû>‡<™çy:õ­¡éEÊ6gìª,VºwQ‡r†¡)ãfƒ w—Ya`QÜ@ß$³’VÙ<“‚Á]&BüǬªÓ‚á]¥Î»¡þ´:ö*ÀZ He¡M_«ÛÖk5 á‰-ßfá‰êúÿ‹:üe–xÙ>ùšˆt,4UŠt-䞟‡ r?âB9‹øÚ¦oޝm6å‹®kFD†6™,»‘Y$#¯¹õŽHr™)Çjòæ; îô4YySˆt_&9š4ÿðûô\Ǧ¼‘ÄÄ®U¸¦Œ<Ó<›FG§£ïed¡Ä Ÿæ³Î 4×Üà.qSs‰›vÎKüî!Öý¨äl›÷¢ÍDFw1ñtšïUŠHrWám¦ËÐ6h,IY$›ÃÛ\éöù¢þ„2²§–?¿¯—ñé9-áÐ/ã¹é·¥D¤kâiÓ<©+ªÜô’ô ª#y•Ì4Í/Ë¡oíù¢=þŸ]Ÿ$ËÚÉ®Cdd”÷¡Ûº¥Úá@NÙ›æÉ¯ñ÷òF&Í“<΀æ‰Zá-š'ßñ›¥hò{‘žž J’à}=’é ë ]&‡/Ëe²ÈÙ—ÉáËr™ÌAx™¾l—É\â\&‡ b¹ÖE}!àZ‹k]‚Úµ:6×:k=t,®u¡¢\ë¡cq­KP»ÖCÇ—©2¬Õ*„uçpÚ}-ô"Ô°= (жCзäl«ZdjP„ÅÓ+^xzÃðé?˜ £§xàƒÉ3¨}ð!±øà9}ðH<Óí‘>$6<>$6<>$¼üÚTŒ¤œÑ ¥œ…o»/J9 ­)g¼ErÚRÎx‹0å,ü•r¦Nƒá¯”3=¥œað!å ƒ)g|H9S1AáÏ”³ iM9£©Š¦œéió3å wºãÛ+·«¸ŽèõX¤ûÌM‹œç"ݪ8jÁ×ûpÖ=‹ÒÍ"`5Öj^¼ëâ=Dsbëû§9=kœÑ8Ée7ò QîÊÔbÊ$òƒéΘô(xϘô(°ÖaÜPLzXë0n(&= ¬u7“Ö:ŒŠIkÆ Å¤GÁ¯:Œ Ÿê0N|ªÃˆÀÇ:Œ5"{Ž ßÀ`ŽMZe©7(UF¢È*K=@£,u 5ÍÈ©vz¡¦9ÕNo²Ô=Ô4#§ÚéM–º‡šfäT;½m`5Ô4#§ÚéM–zƒšfäT;½ÉRoPÓŒD‘U–º†šf¨Þd©7¨iF€ÚéM–zƒ²Ô¨Þd©k¨iF€ÚéM–º†šf¨ÞĦk¨iF€Ú©šf¨Þd©7¨iF€ÚéM–zƒšf¨Þd©{¨iF€ÚéM–º‡šfªâb5. F †©±€˜Ö€¦·bÓY@ŒDÄRtO(Ö‹ÁûGb ÚK6j·!yý(¢ŒÁÛõ¨þ]îi:ËyUq͈jér/ÞŠë&ª8|â>àdN<,i$nïËJÝÞ÷ª¾²tÿü{ÜŒ—ú®=KšQæè ™âÔ‚N|t{»æ×·è[¯ù—/ú¾æ¯ô5?¿†ök~uZ:Àƒ•Ç4!¨oïEY#qàÞ¶²¬ËÚS‚˜ÕBFêŽû4E¾N1êð—åžaß0E$¼½—âyû”'+튷‰\›Gê};,e;ìýŽIà6+dý#:e6MtG_è=ßîäôÁÀz'?©õW’!¬<%ŠSÎ6Šo©D$yÞÞ«ÉX}jöJé—¸Mb¿ç_{D¾O§ÜOª¶kö2ïcu’c]'DI,ºÍ=/Ô¦ëØc&4ä\+wœ°DÏoÿ'ìL“Åu0¼¥Á{èSÕw fÆ‚™«W –”`Rõ žÂO²%½*ú*[ɘóû+/L•¨Í¥Õ[O;Á)©žÙ‹þÎÇ)¹}V™ u CÙUÙ›‡H~b.ª‹ZÎêonÌ £o²œe^Ô<S’¤ÉéÛFrñn9èj31qTãk ¹äó¨BÖQ›lMÆJÔyMÞUÈú ›¼¦ÏôI$He#AÖJí¨„DÕçÍ÷T£®)–¹‘”|œ“Ó49ýºþÛ/¿÷úm,5Åk~51Y¡BÖ9näœQ2:!Ç×N¦tgÎ8”ŠÎ÷à†ãPôµS‘÷ë+éÉÜq ¨#ª~𛬠#9ðÎÉe#É÷ |±¢É­ù1‚à¨QejÒÕu¡^ÕÔ‘¯<R-5{¬vSñbFÞ’y\DÁäôt„ÅfígH}ymU¦%%#wlK_ò3 ¦úŽ‚Íõ†¢6²ÝÔ¬ÔysTÙÓQ÷¸c²Ò©5óœ¨?%]Á" ­ÓOE:7&î HŸ’{뼞ŠxíŒKHSî1}Ó}­Ì.òåGL¾£Û¾™¬s2UêÌDÈ‘æwöï¹R{ìÇï|¢ˆ Ï1ÅECÆü#¢ä‡ÂûEÔ‰‡’™Øý=÷ ˜¼b~7Ù ÃÛ9odÍ)yÇ+6e’UÍéjÚ(˜XßkmW`娦~\OÔª²Q0ñnrn¤ïU!Æq,RmïpBošXL£-pkÈ&K]¤áÊ «äd™›ð’!/ÖÎ&ýù$18û&£Þ] ’šÏ䡑!“̬óË‹/Ó(kj̆̒yssl²a‘ÅÀ‰ø¼dQf{híòæÉ [Iûý©ûh«^—YK (ã²R§bs?÷>Zöõ”Wª–OýZ'6éHÕGófžï‘t:n>%éfŒÄ” 0©×ù<ïšnYZ9òaÈݘ֖|Êe&“j £î2SËb¾ï†uߥÕÒÇœ¶þÜȽ7ÕÏÔdW¨ÖË8è÷Œ,™›Æî=MíÂË…Ìâ'û&§yšÒ”‹…¬uÑíœ\6’Ì÷èŽIj¾µþ^ÆÖ#‘¥V³ŠßÓ›§2¥oùY@@E܉Z­éJŸrŸq‹šÁ\týDçã K°¨Õ|ëx: IìÏ(Š™|™Å\*»ÆnÙ’ˆµŸ µÛ¤ßy6q{´Çe µ¬ƒ>ñÔuÊßE’Ñß †xwÔo‡¸xYøº”}¢NûÛïRÌo\_ñP·uEŸ¨cÿþEÉýe+KµÆ¥Fþ!²—º lÛ Ì)¸r½Äµ¥,ÕÂl²G#|©û÷Ÿ¹æÓµ/‡a¨:b‰UìõeÌÈrP;A¼-ÆD1$ŠÛc 8&«d‚Aÿ°x÷ˆæÝi«þ›E¿¦ƒoP­‚å:‹u‰1ø8«ºÑâªQôürÚRO¾ñ?Ee7‰ˆ–i?õø³ˆ9DÌ ‡ÐŠ˜EÌ!b¶ƒHÄ,b?DÌìŒe?DÌ(x!bFÁ 3IÞÚ%b¶65ý<"fô‰W"fôG^‰˜Ùk;öKÄ샼1û "felR`|œTdÝóPÈ/»¹*²–=®È àYEV)pEV/*²‹ŒÝ~Td¥ »"ëj|Zìöò[Ú2+X‘ƒˆ˜¡j Gþ$ó®ò'Õ·L zNpjèŸ9cÛ!/+»1k›ü¿ÂlÉѶšŸMÓØ# ẻãèdï²HGê<Û¨ö¸ÊlgUÃÜQÑÊJLFà‰¹=¢b”¹°w€ yD?ks¦¥L“Fbð錈¶Z),¼Žˆ^Ì>!YeKY+ †îˆ>;̢˲ÀVë†ÝØuY`ôȦ9ömêØÖ·Éî7—os“¥?|›ì~»ÎÓÏ9ôÌý+ÈÈXí9ðêå3 zÎŒõU˜'z®<­ÚoòdØÝ¿Ví7y2 +WŸ©öÇ ®UûcÛtàø<ûBzÈj°ûÃ!«±/͇¬» #ØBtxcgXš™lìšaiæï(ØccÐw‚fcð\~oìºä7Àð´bÞØ|:CQñøtÇ=ÇçÕ†ãóD_ ©Ñ‚ë– 6ÂÚsh )DênR8cõê0ˆWÜÒT´q\¯eÆ ¨b™°¤BWv[š%Íê‚È¡ç9MŠ.Áà_läp±‘/óT›‹ ‘$)ŒÞA;LkœÛ©Àœ=Ób™?æ¹eþZ,óÇ<·Ì_‹eþ˜ç–ùëq,:óÜ2Ëü1Ëüí“+«YõL]¿Õ àÌÂ=t À:®ç. ¨_fÆÛðöÄbÌfPÐ'ûua†ošÜܬ,85m…ÁaºªcîÔLô‰á)¸ò/ðI.üÆ!nøGÓ:¾é¶°€U^™(0Ùa*l÷ÛŸ•™0®•5O°z¢Ú¶ÇÄ,žw6€+ÀéëÕŽ OÁ•¿Òðynóô•¶ÑÅÓ–u¡oÝ2¿û…¼5;”‚s¨|µ®ÓR¬ý:’—¹£¤.Sq¬Õ`’µœBÞñÚ[ÕÄAÎ/1†tÞÅå¥üé4(hµŸ ;Y§ôÎÒMDÛÏ“Igf'RåDµÕîŸXªüë)´±aq¬¥)pú#âÕTKsÁéOÌ{:µ4œþà©–¦ÀéOÎlkÅz.#_|U6¾9b™Ü3ëËv!’É¥]¨m¥£ ýÛ"Ufëöï?ŠT»Ø¿;Ú5¾a¾÷£–mÚ»ºuj•alÞÚy3¶’hLæŸÞŒæÛ»)„žx*·«Á8ÅáœÁÆü‡SNà 6滯МÁ`à­Iî?ÁBˤ·¸L:óCg™ô—Ig~è<§-¸L:€‡8œÖæÜ/Ò;!ßbàfPœ ¬J¬µÀ çR9]jHbfD`õLjt Mn¥QÚôÃ%4Ê׌4mÓ¼9è¨U\®}ÁE/F ¢0;--²ç˜‹LfjTb0:Wm6•QÒ4s‹ŒB"ëç"£KMÈ»Kt^ C‚aÕSAPñÑݾC´{¿Þôwn™OÚ=àãø•8 ’ù×ëîj*{3Ÿ]GŽ,HÜ®A{n nÎ,ÈgAxš)p$€§YgAxš)p$€§Y-΂ðé®Kn2Fd>ÏêRð¢.¡½u )hMSÈ«ÜMSu¨S“Ô¥–ùüÏ^ ìß§ž^[ñŒAïÜ>”|!™Ÿ!™ÏíÀ½„6'ÐnÖœ¦°/ NÅ·áePö ‚+;íˆXksYšÀÞ°¨sƒ2LÁ­Í‚Ð]º¬nÓ—ä ½S=ž"]‡fê1èŸZŽÂA,x:wí…Ü‘Svv!÷cAôÕ3P1r\íÅDá°àûÆÖ®ßªLgf%è-Œ¥)ÙŽ}’KcÐ?QÆÌÊ.~½æl>¤©¸}ÇíM ÊTÙqôìÅ®)g·Í×­‚t éìqûª¤üQÅ>8Rs2ÛÂ\McºI£ˆËü«A(¯Ö®R-D‡Aüy`*ì š H ¦‚V«Ø{†ËV¤i=þHÍ¢=fD àUfߙɾà$zöp)ÞîBRk9fæ7"Sî´b£1`áŠÆl„?*6Zðù£b£mÚíl±_=œiù› ‰Lâs˜ÄˆMâš ßüHPb!R ÝÃ~Œ¼ü\½æ^-@ƒÈõN´×WÔnª·²Ajaœ!‡úƒ‰ð0KóPðx([Nbáˆê“µ‡ ¾¶Å„ÁÀ‚Y y-µL«—\*È;bHýá8ºoo3ˆ¼mKÕ…ƒ¨Ð1¯·ÂŽó j²Ê>›Õ•C±$e‰Ç”;0Bn*s2”=oæf /cu}öª=*º-“ujæ‚·Í¿¤¹±¨eû§9“¶ïHé÷Pô«kÐmHïCYR„¦¾¬A.ÞŸEê w^Ãj÷ìßY±_M ž CÚ÷„DÉ/TÞ‰¹(AƒÇáÇ:`T|Åð†ÀKC>í%L–BÀ­Z~V5à ¾%VlƒCË ®BýÖµI ©+fPüÕ½9›°OYÒ³‰Ûø0©Œ‡W–A`°!ï(µ¡‚à¬5Wr*$ù:Aɦ6T»st˜E–ð’„ôb6c˜ÞÝœ¯+™ž6¶iq{ÀíÒÅ}—ät{Cf6b°îŠzÊÓl Ó× Q3„÷×R.¼—®%$ dÍ 4·›ú‰/³)ú`È#uÛÊòí–<᯽áv!}FμjPÈ&Ñeö<› Ú¨ìI_G7W_—=ék,™@{F¸¯£›«¯UÓ¸¯#$ýOî.äR |wݯï.V^cÐuw!#:  {C²÷}X­áÃUÖ?Kä!Ú8ËíMö¤õ…ýàþG ŽÌ¼Ì°ð¾Sf%=Z¬c_š ÉûúÕuô?@0xyV-}‚Áà¼Êt=çCùÂàIcј!ç\™ÇÐ`ˆíwszP»B#HYðIjp€Q®Œ£n¨òD¬ i›^¶Àý·Ù 5ȨîÐñ´šn%üöqt€¬ùjÔ7'$]îÁx/¹º.'_C °¬˜ójò„>U¯:ÞœçjU©AMÞ8ƒdü7Í€w’TÆ(e0›ª Ꙭ²¢§dˆIuZæ›»e˜Íe'ODê÷Ù~§TÏfÒCú0di:¯CµJ»døÇaÈ’æwŽCU ùpú3duL'_×¢ZÒíø0dChKõXúL|*uú¶¬ù«î:é¤ÈªÜ­ÄrX³iCFÉÀ…$ÉýØTöMœÇiNHÝGÿûÛbznjÞ¬5›0 u@hZhÙVõ;yYsY“>òp3”~i4-¼©hëÊ:…R³-¯ÕŸš·œGV_Z‚ŽÊÒó¥ìÕ?„ôoç¤,ÔzMfœwKÞÙ/Œ§ïMÅl÷‘s»ß@´ÝGÎí^ ²ÝGk‘S»ÝGïK{Û€Ò1X:.íÁOk/í£« q|¬Œ"§{!wvQä¼³Ó’¤æ´ˆRÌÎuAUÉnIR£gdŽ•(£ÆÞÅ›žì=6Ó]ȼïˆHZ¾n¡å-—Í8XáËæ3}UóÖÌ©¶ºóöe‚ºófà²à‡6¾?´ñmÓGÞê¦È±©xê‘Û6i%¸SÓ3‡'GM™y’×®­WµV‰¾0虫(¾å£êÕ¢^•™ªßƒ>7Rƒm ž¸h¥Úű‹–…Ÿ‘FºBÍ™9M9”eaì[½Ï€õRÆ+‡2R¸Sëò¾Mçz6i UM3á9°(¡âò8Œ…芢Ç`hä,ÔŒÉöÊLU£öàå--Vh@­º±Ù*w»)d”c£¬…iz7+þ´€‹I½á£ZÇ‹9Ë0xXE {º´C¢v8N@mSIüPÐñ¹¼PX/d‹Á ; ƒ ô7^(Ð'^(Ð'ž*àÄ~ž*`©ûÁ Ù*ª®"ä…Á§×REº|¯&óÏ.?jÊÀ­–/2ÿ,ø£¦La›~^ËMOŒ~dPÚ·Ž~dPZð‡$æñÖ_7˜¥vC®[ȉ2~ÌËÜ¿D¥ (á–UwRRæAH—¨R ž{zß .ç¥`›µIAÏ¡)ð~ɲŠ¢K^¿×©.sû2Q)øHøTðáx¥ ÈMþíÌ=Þ®äeR&’€O nöð>¤¬ÛD­hÚ!oÀÈ*]n.góyDÅ+N?à Ÿ‘UO\—¦ÉÈ¿™û/ž°˜¶›÷|­Û•’÷Ã/njìm5QǶ›%ùäw{»´?s¿¬ÚŸÙnYx„ô QŠlêqhDOÈWDÊö;™t©»t-×z äãÐ]È!ŒFm]ªNbm=D ™USjgZKúÌ'& C¾Õy·• !£s-‡zª?ŸÉZYöA‚Üä¿¶–Í^õ¦Ìæ¦ÓYq·ºõIWŠ[ ÈšøEIÏúb`ïÍ:Vl–}´îŸ*Üó±SMŸy¦$ñšvRr“„T²9Ö´¥¤.cÿÏŸŽ0-a¢«_SN¾¼–›ü"[QõË“ïªø$™!·²4îÕå£ÈøÔr“ˆÜ£py¿rõ(©#aÿùwo]Ÿ6ÔŠ4Êõ5ç1!=BÂ!+ïäôš².h¹ÉOR=ó› L0·— êÝeÚ½¦‚ô»–›j (²Je.Ó%64Eâ5™ëgfÉ´V+!Zn"vÖ۪⑶“]÷þ$Ù¹Ëäp®*Òÿqí Í#kð¿}t&™‰n¥š!moÞç"ã¹k:k ´È]kÀÓ r×Pïk[T–‚Hûš÷¢ËE¥3Úø®mIR‰þRW•—ªÇ}߉˜ýTÅ¢bÌ×/ÈÅL[»§c:æá ¤@&™ç€¤ø^ŠÊa—="TÝÜWM½fBÄ>ŒRg5õÌ;"Ÿ™¯ÁäS6›š*Q°­¤ç)ê©ÔÎÌîd™À» ëíUÙñŠÔh&Ý–ªö„3ËÂ¥c!läŠì'HÙ§·KÓ.à<ò¡p! ÌôÛLÛuÞ¶Z"[·Ëõº|áœvT›*Ôw»¥z¤½å0È|k›=ë/ï1Ÿz¦"«Õ:zÿÞ!_ÈÁß#í26„1Np›‘È9^ª==‹±aX‹¼ÝRÿþƒbj}ËX±ö…D#o·ÔÕ1{Ú;«¢S•³šà6ÓÀkWýwÉô¡GŠf©ÜÛø”¯Vo(sW:þÓ€üà» Ól©¿IÃÖ‹Ÿþú‚w,6@Õ.„Ȳã ú:ì–jnNô±ÇºÕãPÐ^·(‘ÍÛ-Õݱ˜óæÎwÌ+K"ˆ6<ö¿}9tlŒ³ «>¦Ðn{©)EÖ,«…VœN¹ôÁ}Þ5RoÓËÚ£5Ä‹ÓíjÚ®âJB™ö4¨@+˜Ó_6²€¥_ŠL0R®‹B–lõ— Ò*5ï³¹ÖoŠµè‹ƒúË>üUˆr)[^)´vúËYÐtÎô™£ØÖ†£5$ŠrŸ£¼U-Y•lÑlF1DÚÕ{ž†©Y–M„LÒÉ•6˺TU17!Ó#ª¶ß­™mËË[EôEoÈQkï~Ç®*ÉÂëÍfô9F±Ó<}ìUKËê{ü‘–bܺºSC5¡y· Î.¨WÙ›Ò™gMÕ݆¾Ëàl¢z¦Gvýœt¦’59zOËà¬0Ó#Çî{dJ ôé !÷9Ò ­ž÷=þg¾Žri‡r+Õ„q@ê)²¡Ô±Rú̧Þ´-ƒ³rkå¤ÎM=§Žm9 ÷9Rì­¦Óò&õ˜qÆ'Ü#{ÿ©ûNö’íÝæÉ4éÕ³éñÓ?>iµÈý(™êæ–Œeæ=ùBÈÚ^BêͰËÊí°ÉãHoõQҬɋ¾éºgòH+ ¯“¹É¶mÆÈƒØpl\Hcx s4ïI`vY5©=¼¡0ÇDüžñÁùk·8V+ªmž“a@V—ìÀa£‚ˆ\èÿ‰Ž²IŠûêݤšTSpôÅ%oˆ´IÀíF*û9GkròÁÈý4;–•ÞGŠF)ýHÓ¢þäË‚ÌD¶EŸˆ´y´×k§5AV—ìÀA~n·œç•ã¤ÈdF¶g†z’EGx¹ •6¾#EQšÜ°¹B§ 4H—ÈULjH¥A™`ä~;×”K“ç]ƒöwÄàìØÀ ®X®§ ¯6Á9˜]ÉJ²9u„ê®XˆjsmË]Þ08ïѬý3ÚOlÕ:£“ÀÁàlKG÷j¢u‘ö0É€vŽþ¤^imiļȜäöNÞ¯pþÜCˆ;·{Ó˜ð%~Ž0Õeu±¿^wÈ 8àø¬0*Ù+"¥Þ½|,ÿ ú9i6•±²ÛP‹ÇuÕ^˜`KG¶œ”‹Z7Œ¡®çLk³líÊãï@1‹¢èÖŽ"`‚’¥¼T¶d åS/÷k7lºËZÛ>Bà_Ò9ò mÉó:GÃó¾>ûªrÕûB‹üë(^ÈÝùT#YQä²ùHVyä, mù¼û“Âóë—ø7þÿ ^Ä¿5pZ[.oŸ_¿Ä¿q‹—,½¥Ürm’¨Åä 8Hö ˜ÞGÔñ£ß÷uolŸïu&ø#ênÀ¿îCê>féï1õ½MSwÈç}¤¿æ#„RÈ!¢Ä«ÓÊ%Cdˆ¥6aëÞ6áb\¦ ¿g|ÄÔ©˜àlãÙ0ô!“»˜ú¶qÜfzS/ð{¾ïcênósSÇæáå–N‘ò’s}J@=z>î£ïøéÏk&eÉ9;·ùºÓŸÚŒ|ÕF2ûõî´d\*dÇ.þ}}?µ™ÜFß‹ ·™ÞEßÙÒ 9rrKWÑ÷Ûüÿþ}ÇÈ#þý=ú~B>î£ï'äó>ú>àEîu}_ŒŒ|¤r6‘q,ðùø÷¹õ™ÜÇÔ²dÿ¾Œ©ã•ÁÅ¿/cêþZ×!íýÛW›Â“™°i´[ñ ÿu}¯1òq}?!Ÿ ôx=Š­ÖK˜B£´;ëþ¡’^½©3½ØlÔ?Ê» O €Ôbg>ò>ï½¥¼ø}™uÉz™eœwuøÜ"”eEÌ®áøL´gÉ{Zuâ±{Ñæ^ÞY/ÅÌûð±E§ãÖȂڦ½ÖøŠ4«h7weñ=P¢G°ýë1É|ÕZH¾r‚ZL ã®äb¬r[„Øèa•‡Üá5P ?G0’º5“u$oé:àíþ{ÄM>Br¶™›Ã¤÷µ•i‡2Gsó€6ér˜ô¤OâÚ¯XÒVªº,Wß”z\ÂNïÝ#OïÃc¡?jj¯jåkU!dò)ds…tÉÙ6 WîNj¡—L%õ¸ã§¿o‘[8Ar‡!Ç]5MLô«þÈÖ¿àwfƒg‚™doîd5fRÿä^8%µG°Aà³HØÒ@>‰LdƒÀ˪DŽ?ñoœnþEƒß1½{G“í ß1½{G“í ßñ›¦³¿€4%mò1?×${‚4~Ç7*~42{¹ØpjñuGûíK±4ðs[v×€R,¼,»k@)–^–Ý5 ËC)ä•°2nó‚¼sÿùãsÉå¹#ñ—ÞÑ“ö€¥uD²~Î;± í¾©;C¨ÔŽ£ª7U¯~ƒ>ˆåÔÌ‹¹þ2>“}.Lô91^U^FÞi‹€‰,38»UèGC+f¿yEÐÕÔ²eTcS„„ï*¹ÙíÐ%|e]ùâÏPrûcøÓmU2Ó¦SY°¢‘hÀ¿ÀÚì^R/·¤­æ°6G|L:BÞãFÖeX‹ò&4o@ëo'®7t¨{(¦¥=%³¤®É0˜­ðâϨÿtÊǒ㪴ǫf°‰|ãbE-¾BåE¸d0Ê1]>‡“{|œ§Ž"?ªu£=BUŒ¤ýÒ†ñÊŸ¸.ÎÖÀ›–i©&)¥ŸÅJ¤ÙX» ¦©z}Dë!ðu¢3SÓU]UJ¾!`’ݨ:jвõó–£w´W f\Ue.—>¥dñQ`®³\º‰áV$«„RêL o©j_™‰UÔkoŸôcÜ7´9—?¨3û;ÓBÉZ·µôëÛ€[53à™lŽÅi¨×ÃT/t¬9áøñ'¦ÛsÖ´¼º£h”;m¹€j^Ðc0<öNŸéáÙ*}ô©7LNó?zžÒghÄGqÚ̪²Ë ïs‘Œè#R˜Â£8íïß¿V+ÞÞHöD¨AÁ(uP1°+_#U»­›;½Æ`ßô@‹3@íÆú].ŽN^9Í–3¢‡@ä="jB6ãÔäYê@VëÃ+¯4à_ž×ËòQ9FR“õZ7.Ï$ޝ܀z¯&7+óä‘â³påRÿ˜DmU¨Œ±ð±{5m×uMv¯øÐ¶™¡y` éÙ`8EÆ0Ë*Š5,´ kó¡| \JâDÀô*nÙ«MÑÈøÐÖ ÚfïuS2ÁäÐàÎ|ÀA® ÊGzOZ[ÉPmֻ˨ÚË¥³Ve-žË÷÷¼‰F¾r_Ç'·\±úƒ*’ÅGÙy¸ÄwÌ“S&UÍ{1¤vö™ÚyîÛÆÛÙ·£çˆd“k¿Ö >¯„µ’ç›È!ðue½>æj{l 0º2³Ú˜Yð»âôäxÿ¾ÙjUqn?ã#áÞ\içÇÍŽ ŠªèÑéµ=Îæ–=úÖzJ…Ö³±[ÏûÆzvÞ h=ï;ëa[ÏûÆzL YÏûÆz̆¬ç}g=¢ÇÖó¹³ÑcëùÜXÏ^| ­çsc=̬fÐz>¿XO8|~±ž°k~~± üÁz𣰠ü„ á‘­!e_í Ü"™†O^’’ÒOaòõÍb¡E9ŠŒ _G vOï‘D*JßëDw·ÔŸ¯7 S*µ6dêëh^,D÷|i!0ñUA¶àÝwfœä4#`ŠHŽm­¤XGž£w|£ +CÁ«NïÖM- ðs$¨Ží±R“>䊌ŽhÀ¿rÿhvä¶‘+â3ý=¶õâ—€¥ÜüqúÝ;ëEÇeËJ² þ<^°’¦vdåÖåd#BBJ3f O˜lÆq-¤¿áH`ÊÍ´¥^5TÍRKÁ2È /ª‡Ã7d û`²PM΢ðU L¹9k–vRÔsÇó3õ쪠‚Žú]dë_@S÷Ý•«‰«ª+¦§/9 I}ö0ÙwuYŒB>C5  /®ù¶~Eïé8³þîùȦãúñœ3C…s4ï€3kçú5gYƒl«J2ŒŒ±žmmUÃíeô>E$y\¨+ÖV¤N’qÎû1çˆwÖ4¢ëÆu…@¸¡ ®èÜw<­wÔ=ð^]1ÔFq·A•~Aè™ÜfZx¡ç¶¨p*™s™¬çæ"_NíÐsó@¤çæËŒŸ_–>Ê™\é¹9—‰*Ù¬ zttÚòl‹R¶E¿6£Þk=7L.@ÏÍÓkÞ¨CÏÍß×âk“>g,?8{Ô²½õJ–)74à_H®Ì ãqµft¡Þ _ßBA²T¶ÊŸP}ÒÆB̼¨iç_HpÊ~6úÑm›µCNhf~|‚¨¤ƧÌçô¢’xžšÊÍaЊôÀôD%=ðt8ü;QIüÜê:†ƒPé¯tÏÈǵ®cK§mnÒ^ðìÕþ9sLÃÆ0èRôš&=rG@Åúyö‡sÀã€þ†gÐí7ÙÏ‹¼tÆ ™ëÀ”±Ÿx퀲¯J¾4¾R(‰Î'd—Nmb6úÄ#31¸×r+•6´èèJ!0© ®¼A@žZ Œ© JPO˜£xUÏÞÓH —îIcǤ1_ú“¤g½qçôÝÂ+ímL>}N^–SW±°1=8úŸ>_'I‘ØŠîv”T[˜™÷ÑÝ,“C‡€\oÍ\˜â½ÙWÖíoa`’KÂÀ€uû’nQ‹1Œ{^mSÚWd¨ÅäŽ=NåSée`Yñö,[àû–fnÊÑ;~îiæ&tÉײs~Ä?¿ÉÎ)üIv®‡Àdçþ ;糃“Ïo²s/dç$;ç?ÉΡáùIv=ú'Ù9‰ü'Ù9ÔíŸdçT‡?ÉÎáéþIv?ýÙ9<=88—†¯ÚR¾jCçæÎ)tWÿž‰­Y»Èï+DˆßR\!ò­ð£ÅÀè¶LãŒÕóAB`DgØÎT+¦¨¡‚ `bàÆÌwUÉ0ÛÐCà;\ê~6—¸\m‹äßSà®^U„ë º«W5!¨–BwõªRàŒ¼fßé÷üŒ|]fõ³=«uȹ«ÿl'ÝEWô•S3m÷(> ˜†ìîŒñre+šHë®î›‰x‡Ì+1 ]‘)D2Wg´V ŸN3ôxÃê{û0– É·,TI¤sÖ¶£»Š­eÓû,ÅÔì{ºÛ%Š¢YšÞ³Î¥@Úé¦ÙshYMÔÆ&ôèèpjýn«ß1¯6#1¾ä²ôYc3q2HôŽ "Hpµo²Z&íýVˆ¸²½?-´ ³ž"àÛß]™œv›y±ÔË”ó›DÄ´Ûý0 ²IYVmxÀ¿ŽÊûÊݺ6[5Úñ.Ñ@B2°ÒöG›%/gÑr!MŸhŽ9¨¹m=Oú5¶eÕLЫz&íyAÀ÷ På’Aàç (ÉÌK¹ähÀ¿îUàͧÝùÙ~½º@ª#ŸWÌù+ɹ 4”¼[tɺÍi§•!$º…tµ›T#Wýù`d|ðŸysε[¢·³°M@F7§Ûð3DP¥ý㨸ÒôÓ0%hv„´aP®p\•š„d¨—Âðd:rIwF§,áïYo€$ªç›¤îÚXC+›aJ2j1”LÌ´³†§$ÃaØ ¿Ñ:®%›xšVù…6 •–£qÎ. ÜöøÙcµè(5,ÐBJGwõÁG÷rÛù>fÎ(Ƈ˜ì¥X¾0p×mAÀð1º+™×•¹PF· ¤:Kà–Õ… G⹜„q§Yª\¦?!02´xÕ=úãÌû^–…JFw^;0ŸÅ¿Q÷}¢UE3l÷‹Ö¥{©å¡¸à oPêc©J Ÿd ‡ÀçózÀÈõ Å¢a>áûÎ’t*ºÑý'ªÒÊK@UŠçòÓ¥‡Ÿðý«{ZÑ=æÕŸ_L®ŒØrÿèãø»¸-ýÞrOôA¿ñ¤Så’N5Ÿtªè,͸®¾PUo}OHR™Cèöçïÿ²øÓ–[íš(zf:%†™X‚S \ü5Ñ=;â~Tµ¼G÷ì–]EÃLå0cVd7Šœl³uÜÐ=')EƉŽ(¬š…yJÄ )ÅÀï—J‹n ck3ñÑ÷M²˜÷¹aøÀK¥R2±k»”Bà/•J^j;zux§rVm‘fëКgÌu(¤K,kôêϵ͊”Ö$C¯Ž8ŸEÎ$+6ôÄï3ç“6ÙÚuÃÝRKD7tŸ¶ÁE@öBž]y¶CÍÖz,Wö,áÏ‚þ#‘tJ6qŸÂÏ œLÒÅns_P üDÉí Œ|?N‹$‡¤Sü<³N¶äÙŽ:}ûdeÕv¼nöš£ô-´+FÓl‹!‰FñÃvlWÞRLÛƒëü®$[R¦'Ú:‡@×B°‹µ|‡ÀgÚ©X¢ÅWM!ðó0¿Åª•uâð‚€‘«1ífH¢_À¶¿¼Znðç«¡eá}ù+Äò§?74D‹‹Õ«¯ç”ÝïQuô |ž•K_hMtiµì¦Ye]·‘4]Ú%@ÜêãLu´zÜFS'ûýy)–Í”¿~CTþkó¢uݵIÇVÆÊ߆›™rÔ–%%µü³ýòƒÿÙ®SÉ’|ßöij{¦©°*‚À÷ë$(Tö Tœy;¦Â¬óÍL…Ó÷ëv§•½Zj|?ŒðR¬ni*Ô˜‹‘­ù-r#«ú}8­‹ŠjŒø>ž¨äi…döÕŸ{~©óê=/òÆX@o20zj;zl?FÈÃ(ɥŋÜes’“V|mûê›!“ɓ傡ÛÙÍÖ8B3”S'„£œzüräÔÅQN=~¹rꌢœzüräÔÉ<¡œzüräÔåÔã—#§.€(§¿À蹘?£’»'G¶Òpm)¯ê]³»#›iÌ~iõÍ‘M÷£ø„¸ý[÷¨x¡Ø´×¢-Ê 0@Màb’§¹§}ZC Tê(-7¤S¹Ñ ?÷ìCfçâÀ‘SÀ3;ÿÈΙ3@8ýK²}m+ô¿õÛZüD·Éøq¥ñÄ~Ä!0:Us³ƒ PÐdÊš ýÆïC¾ñ¢ù¾°>åûÊuøëɲ?3ƒq€£Ý÷Ô`‚~¥ç»sƒ¿=pçê"/tç/È·;7xA~œ¹Á¼ÇÈÈ…ÜWŠÛþ½f”ì‘E¼ ã‡|#ãeò10`•l˜SMJºSPé9~§[WH­œ×7£ÏF4@|ßÃÌðÛwf%êX—ºæË–˜x^|31ײVÄá•"j¨¹;®W‰Ã+ETS6¿X;LÉQ>,nºâ`·¦HÑßÖ â×PŠ MÇ´ÍOš”ÖFœ²ª'nJ‹äit§Ä0æjØ“©COŽx&³³Ì]5 ³=þFº43 £˜®s:$%‚u®¯a’¾Âx_ònüÆŒTV9M_Ÿ0ñ­YYnt”pY¸X;kV®NKÒx±ÞÅ­²F@›¡“­6Â']V­=3!?Ýág†îÐ[VŒ˜IŠƒÆ$A#½3³]š¸qS­ãÜR“­ÐH"ÕÍ[ kÖPR<"‡©ccDHqH EíU£ØR8Ç¿„”ê”, %oÛ}¬ò¼Œt^ô{ÚÔ]Oñ3#õÓíšæ¢j·Ý¡5ò{fýí•êø–I[&ó€F‡^³þû³¢tÕ#™ÆqÙ.#Óà’Mc¶í[Þ~z.¿óhüñ;Åç·;ÐdèŽU¸T·,"+šÅ¶¾OhpÏ%•²× Ô®e¤âÉŽŸžµéRaD+y£Ož½ïÓ~²Ô4ëœ9÷¬M6ÿs"«B%”ÄQ"'âôs`ºå}΋·˜xÈi$'œüîe]+šFZsò òå…²º—ä..¶Õ=3x]‘Rç-é™X] AH"u0^F¯“t4Úƒé#¤ŠÆKd–mFþ_#ƒÓÌ!×YœÛ:ÍüÌ#ÕŒKª¡Þ»Í8•¡û«¾»9í•Õ6$iEðûqëúÚSÂ)Hß–,}Ÿu}ñ·®/†nu[“™<-}¯öHúAÖ–wÕV Œ\²©$7QUü:USó=1v‰¦’óõ’†èÀÑ7{·2p$ý`™%x4™ª­güm<ÿ )+înHuÜáÇÛµ xû’d#12¼JwÊ飤;gŒTÃR[C©ý·—W¹]|LÔIžõ-‘'Jº[´HNŠÙˆjhdô„ÜVqŒ¹"¿OHÞ<<3¾Hõ(žCªÇñ#·TÏvHõôè;õr{ˆnA£‘8!œøëÔH¤H0þ:5'¤?À?QerÃ9É»MÇ1ªò´¯®Z2µ&W=¤5s^M³¦™%½w±­Ž/\¬JjãË ¨hHAVq–ÀÐlhR_e–)]÷¼(&»fÄÀÝkuq‰ð€Ùô¥šŸ4¨æ÷€‡ôv˜‹¥ºèM­% m¬|®¨·]±²e誨•ú=º+jMZIݵFEݵFN}€¿Ú]ÍÏ10¶|ø"× BNº¦ï ôQEí Ü÷‰ï¬é ú@¹XŸðÄ¥¬ŸwÚi#9ïå;6)£ò^Sa“ÃYè½§Â&…bTÞ+@F•Ÿ¯´vˆ0z¯ðbЮY#bu¥d/”æÕç}KKi‹ º¯ªN+´j ¨ÊJ›&|ÞKùÒÀ“‡R˜[‚tמ*¶qá饋¤=èT,[Ó¨RTJµXÛÑLóTó¢èË?¨½ÙDg¯é²r@¥´òWUlsÛ’©%kA ðk€Æ‹Fì5¯ò¬Y÷ãÓ~é°x‘ÊÊS’¶2þТ£¦ãì)‘ýÖÒ|¢¨Ùžw5õк›±*Úù‚æ:E­Ç¯j¾±m­2@È#’ׄ/yž¯B†À°G›µY2Í%ÉWÔtï MkY¶cIÕˆ‡kË ƒüÜMkf–¬ÍZƒ„æ:D¥¶³:™ÇqkSÜŸÊ\GßöTÜ”. ­–k BƒŒÈŽ£!ìŸÆ-êH)ãxSߤcÂ6ôvßC3*¡ÖC"þ³c¤5×)ô#Å7*Çjîç9C½ä+sÿŒ©’D¶Cß±]Üv„ LqÔ]Ú´ vÎÐ\óßϾ¤ åà;rP™¬˜=»¸šd}§Ñ½2¹Öe›Ó”®M?B ®L6ì£KQ´x©LÖ,.±jÕ†3ªÏ•ÉÙ’e¼È ð ²o¶Ž¸áI3ZÔCçgß’uel ðZG¬“°Dœ×ˆ?¢ëˆ›zʾ¬!×ÛW'‹LcBàûHD?^€Ÿ')\–uÝ 0‚_F-0¢Ó4m7û -“âtŒÕ'T±AekZ™WÇ×-ÏVSžUÃ:  ƒ–¦:¸)Ë)í†ðeJ›JäëZ™¢_ ÑÀ5I^:%E¾ÕxëG¢:¼¨M^T?@ÂnÀ‰épqîßð‹€†_wó AAPU¨È””Ð{‰‘îó€ë=>ÈT"<xÞí0RjKÚÏmR zõn>–ðÚ”TæËv¼º«ø¾bMKÐpæ-míýÌÚ±Õ5Äž¥qÿEvvÚìIÍuÍón™-}.§ë!é8éÜ­ú׫•båvyGµ†O@Ö°¼wK6ÂÚ{¦f½¸Ìò”Î;B#ªR[&©N›ýiàsG>VmUåÙk‹Lý3çYV‹#¾¶hà†áîå˜çö~£±•rÉŒ”Ë¡z͈©ºõ€ õp7¤r ôO×9pKÕFç†è¸žîW÷æ[¿ÿñê ¼Ú—¼7xµŒk:ÝÙ]2õd²“ D«p‘¦y7 º’y9¢®3‡Ààt•'Ïåºr ]EÉ´iЫß. „BàÇUkÓ«ªZ.ÈèÑʪ“R*+~û× •ðÿ!`ÜIli›‰hdì0½êÅ&:£±þr˜^Ñ!¿ =ëu™™2^ù;Ó¶+ÔŸ>L©èLž4½bÝ’%èwúËÊ*›3ÔK*í¥ëúµ8ƒìÏi®»#ß.Ó«.Ññ?Ó«i(.H\;W£)a}Q6¸EV—âØéU ×q3iƒŒOŽufEY§¤L«‚¡·/§®ImÖBÿu5°Ë®ëê&ßõÉÀ÷ð¨Ö%d|"Ó˜”}äÒ1fÎò‚B t†£ö¶Ú M)ž9æ¬ÒÂbþLâB´˜û¢ï]Xí•Ýð 4ö'ø1‡¥X§6ÓJlÍ=+Pc"$*.€œqzé!TžÁ«yÞ š˜¨ï!V»”ª{H•Š‹¼¹løÀŠƒäJùµHèžp¶sÔ’úŸD–¦ÎK+^~¥ç;dk2q3.|ô¹;4M¾çk3.¦ÆLO}ÛÂį÷½îº–¥=18‚*°({(†yec!LlëΜç û@PgBÿ`ÙZBZ«©˦WqÉ•ÞK?2ôDí¡â*“Tðî¨ÕŽˆx2—½N2jàü#¹8¶©ë;N;΋uøëN›”·€6éùƒ6)ukmRŸh“ I:i`ðd‘;AÚ¤>Ð&Ò&5ð6)€6©TÚbÄÄ\L™6cö ížZ UºÌhr¾¥;úpœé¤Ï´Öu¹õ¬†@7m2±ßðíLûÚÒŽ³7Ò'8û&i›en' ÌÍD²!ÕB%€ -Ú´m 0tæ¨×¦‡À·+GÍò?ÎuÞSŒîÇ‘¾)Ǻ£uÏ÷ 8,w`|ß<å騥5zµ÷zBlÀ+Òs'ÒË!}gÒ{ñçV¬ÿpƒ6’×SdÿnIo±åpŒ|£eRk•‹ergéjú96d±ß”Ç ½'2†c¿øçÀµ÷"2÷"$²õ´Ð¡Œ–ul®XjÇù™È~¾@™Ct³»ê\/@©Øó¿N•t­JÍ!Щ’žNvçþþVI7ä= m}@Vj1*–•­[Æ@àÛ©+Üá'ºUÒw |TIŸæjKH“C ºªs1³º¨“TrOv±SÒ˜âWë ÔÁˆ«´É¬“)¶§føÄO–E'b7§Îàõ›Á4–{Ï<ˆ=1¸sh áCëž‹CËj·x­Ü;‡Ö <‡öÐS?9´°ÃÚc§;9´°ƒßðà0qÞî'Ójß>ì€@Àãt»¨óõm^S©Îgž Ý£JtogôïÑ(zD£Ä•©‡Àà.‘§€bcD¯ŸÂVôP-kðýTÄPŠ)S[zCpßdPîÆÉÆ2³Éo ^¨åjõu©/ç¤4d5 T‘qÂÔÄ 9­˜S “jš¾ïE*2øsÆ„69hŒÇv¼±–Št‹ßGhyD”*‚GùéKÂû´JZ„|Ã$‰Uo Ú>¶«F~®|ŸÒ؇‰±Q’©`ö%Cº™ªvê+6Ú1t†OEÖÊ(²îÉ¢%50tOÛCÑ?&„Ù¶ƒÈ1!ØuBDÿ˜ ½úaB너þ1!l÷Dÿ˜;ú® AzC#Ô@ç„ ç„ˆ‚\'Dô¯ AÐ|šä:!¢MÜç?&iñÛ&»NˆJFê(² å’’“ ï´m|¸ ñvémƒ@ìü& ðƒ«ú›¼4óBÚŒ£'>\qÊiMª…ñ=ÑI­ê.7¨à<¨Ý¼îV „W[¹¿±¢e© ,_tÅ‘ÌÊ2Ç¢hÔ˜ø™ÕÀZgôQÔq2;~¿PŸôsÌi—.èWzþ3²nÈà‡cœùñ¿ãü凞øË1ã(vŒÓÀ÷3=‚Â×o3ã âV¢.3ôÄ3Š Ì4ðÁÀŒb3 |40£ÐÀL Ì(60ÓÀ_f >˜MÈÀLã}¦1Þo‹¾³Ã½YôQüeч€¿,úЫYô¡Æü²è›!ðÑ¢B‹> |°è£Ø¢O‘Ï‘aP±ŠÓÁvÏý’aíú”–{B ¦‰¿‰~ d0¨ð&bžÈÝö¢†ÀðÉ:"²u8ÈÖâ†ÈÖaà6¿BdëÓ÷)ÌÈÖÐ÷‘lmÖž›î•lM8þ [cà²5~õ²5ÆÏÞ`$Ïwsî ÃzÉlõ ¼0¼‡”ŒÇÚ2e%£)Ž(ƒ81˜ÈrøFQTì.5ówC ?î(CsDfôaŽG™gÈüI¾ÏíÚ@``N*ÊçHÝ೉s±ë U!€TvµÅR»•u²Ovˆ.—ãä €I½ç·ŽPJÉ[œ<òuÙd?!6c;S}» e±5 |ƒ|ž¸M“'C•ø7Úê§ôØä0KŧÞ9©ì·ºW‡;±ù{—Îâ¦_ã'ª]á¿?ê´©FÏÄgUÞ¥ߌöXb "[ÿ•ɲ#yä&1ÄÅËÿ'ìL–å•(üJ…m0^þûÀ(!@ 0Ãã_ d¢¢¶_1ÈBC*óDÞø3¸ $FǨ[È’~ Û’'ñà‰¿šðÇóÕ¬[ÞÉþÕ„?ž¯†® }5á9îåá¡[]^·ºŽÂÀëV7 ¸WxÝêèV›Þ£[ƒnuÁnÓ{r«cЭ.^·:Ýê‚ðá­­áЭ.ÞÚšºÕЦ÷Ú­n„à[] Á;·:Þ¹Õ¡g¼s«CÏøñ«|ØÀÁÁ¦÷,µaw^À¦÷ZÞ›ÞKiwflzÊFï!0ôË=,êò;ÈD ÖÙ6Ømzÿ,ÿap¦¬z»é A浊ý _¿Ù© ðÎN…AðÎNe€àËÙµv*pßõØ© +F¾°³S €ûîi×íTà¾{+¶v*pß½Ž4v*‡Øy…þ`1¢…áo±1^ÅÆ8Ž…áo±1ôŒ±1~ˆ…¾`1;ÄÆÂð·ØzÆ›ØGà]l =£?6Æ\l, ák^ÄÆø!6zƒÅì ÃÛØÛcc! íVÑ!fy19êÁ›CL÷æÑ/‡˜]ñå?›Ä Çcb®ó¼E·¾9ÄÄW¼8ÄT"2ð3Œ<‡˜BÛQ»CÌ0úåßúnpäû—qÀõ ÷o‡F¼ÜoøþíÐh€àÍ8€o}3ØC£ðýÛ¡ºâÍ¡ïÐ[ßn°zÿzh„¯y3Pô˜7ã€;4 ß·‡FpxãC£í\Ön£Ç¡á³°Ë÷ø\8L,˜Q6çQ•­FÚEò…àÓ*€o Í£`ŒŽ¬[!øò¹>ôÁ~vg‘bÓ@ÑϽHñbDŠƒèç7‘bÁ;‘btë;‘bÞ‰/¼) x'R\C0¾Žë‘âXc‘b†EŠhiì)y)RÌ Hq-OÁb(R@KãËh±) ¥ñePÒŠÀÒØ'RŒZóR¤x@"ÅAtôˆÚ×Ò6ùÁ¾QàI~à6ù_)ÎèV¾»ïµ?`¡+¾nüÃs¡ ;šDO¡ ;šì†¹‡Bv(4Ù s}…&ï MxWh‚À‹Bv(4Ù s}…&èŠ7…&cÁ›B“!A ~Wh‚î}WhÂÐëÜšàkú M–“w…& "ï MðsÞš`ò®Ðwà»B|Í»BôF·…&˜¼+4AÏy[h2"ò®Ð“w…&˜¼+4A¿ûm¡ &ï MðÝšàö¼+4ÁÃÌ41±YëŒs>s»úÆÓ'1ûz!ø€)z{å}–MµÝ—E§¬u—fÉ[–Í” [¿Á¹q*âýØ6SN µ\›JâÉGÂíiÅn<}8[²WÀ³…èõËÙ‚=2ˆ^¿œ-ذ pU¾>[p?Íë—³7;¿~9[ÀÏxs¶€¯xs¶€¯xy¶€ ¢—÷lBD¯»³…beU_!2ÀËt#vÒ¡H{Ûvøy{ïÔdëËÉåÖõ;U|\%¶²>ó>óݸIÓD>© ÑFWIÞ&&¥Æƒèíµï^P­GôöÚw¨zØNí»”7à¥}7ƒRã¼´ïfPjÜ€N¡ÕÉÔËAEÐ9+;«¼¯ÿÚ:®rÛ9’VÌrd»bt¤ä¦°OE›–5ò©­áõ·mHÞ}'¾€Dª±Á’·¦L‚+zÆðœˆ.—õÜ’¥C 3&Ü®hj§ ézQÚ’zàx­jÍ4hÒ–ˆ\ Vr$:Z­è ‡ºu;´r«Z~€¦¤+¹Jå.¸".àxmu’Ìl“§]JšoÙbr×I*¨YÉ7õXNÆ“KÁø„ñ½ò)º9»b¥…ÍZÚ]´Aå“_FGrÀEû(: µì÷=•¢íøð9}Ë 8Ÿ×âË,M GàËò´Æ`¸‹`”¥NþhhžäÕPÛ@;ôTFà—ÊUÎ |û¼ÃårÝ:öƒ¶Æz*+PÝz›´·g\ùÐ¥¨ÁÎäög2€ZÒ•Y¥¶¤(ªvÀäãZúYÈi©C<¯Éož XÈÕZ¹ëÜ!2´ƒQ®Œú³ã&îlÑ%¹(²Æä—ÅíŠÒmDÆ»R³^Ë«u?v,GäçRYyYó÷õŸ³þ2WAfõ—-ØÁ-Õ~¢ÛÎŒ¹ìq#¾æãš¤ŠœùDšÎNY8¡‰èð5_WJ ò9§¿lÉð¬¿,ÉQÅê/[2òÌﲆ|ûI»Û3d|­V¼¨îß òã#gŠI¬€¼«§eÖ˜ ®ÉL’“NjV/²Tgj8ëŠ*ã½ûóyI‰‡Ã‹¨ŠÚslJ(˜ ¯µ’Öµ~ÎÈ` µ6Ñ2ÄIN¿}gWEÀG|«†Ò1IyÍŒ'YÕ¶©M{>â›pe^¡!"uÚº`Ð`Ô­uìg»u/›¼|Äÿû»˜ ÃFAÎ*÷]‚hÒ?jÉöý*7F×àÔ3ßÔ½]E1ÀëÿÛgd¥ücüØØ937ͳʲ¡¨ÁÀ1<Ù‚:ê3ïljTÆ688ûˆo9Û #ç:å=¾&”0ÖJʇder#…I—À¦Xýæ­’×,Üg€á] [ê·">V ):»ø7¤ñaZþg£´Ø7/Ƶ°% †Œ ©Û]‘å7+2L¾¯IžÇkÆ–Ôá =hÓ¡Dnäy:ˆŽXÙæ z÷‡:Ô>®ra•µë²²CdÏרuJæn\m€×„°fÕC²öcf éTªu”ੈcÒ|ù²Glzè°!jÈ›¡Gdx Í5ûµi üœ$ÍL ÉQNmÈ7;ô £ÆŽožs¦zDo·5¤;Ö!Mg>|c‡ÊáàÓÆd“ÍtÈŽo¤ïÇÝÚ 2ÿþ)i6ÝB„(ÛqšÙ,#às5õUŸC0ò`4‚QÞÓ {‘ÇÄ0"к©zëïCŸˆò^}­œ*x:[G›³ }î/:Ûš7kÈ;E3ÛDÏßÍx§hÆ x£hf¥Ïvÿã˼ ]Ñl÷?¾wE3à|•î³+šíþÇE3vP4{?=Šfì hö~zÍØAÑìýô)š±ƒ¢ÙûéS4cE³7°„º,lqGãïÊZÀ£\b¦6—fw6v»ªbKjeCJgš¤çX_Yämž¬.¡8oË1—¿Hº®éä´Áß@ZYRæ6¢Nïû~Ö/Ë‘¥Ë;¹2›ÝËDÞ—QTâtÞÇ ï’h1䲚òB¬½çȇ—!ò…SùÙ +¾Î`U%uKçý­#P̽˜\ãœ$š|Y¬¶è¤Ñ˜æÙÁJŽkÁ·¯³)ûBÐuò-]ÂÍɹn#…à8µb1§"MrùŸ¨Á`8»tálÊå`n}<¼®xoãØ'ï]tC5V|z+„ö¹Gð´n,ªè²‚œd_†Ô}Vg|zS"]:Ýns{¨Ü§¦rß–¶½ºêâu&mZN6û"†A".Ëøp’… ³enÖ:)Ð$UlGŠê˜r»µœ’ên¤øŠ¯3¸Hp9á>ødÖ™ENŽùÚå¶y)íᓆƒMpÚMi÷žkÏaÄœÅ`1÷‚òšI¢â‘‚ó¸—ËAü»îƒxü8~3fÏ‹l,ÓÁéÅ ­ý »±,ÅÊlªsüÀÒ&p´¯§ºðËD×$œâÎ0œÑm8sÖÐô»¥ï/óô _=Ø€rü¼Z:d4ƒàózØ“ý§·uz±[û\篸a/~žºöªX!ÿøéiÇŽtu;îM ¤;ÔrSÛ†I‚E²Ê¥=×ÔË]rÁ§oþ„]$ínʇùc{™¤#>Ã뉦HJ7ÑìnÊÇõLÇ;Â÷õL³Óì2¥,»,Sb˜¶}˜ÙËï4îíx·ž3{ ×3pfWí8ðï—” }=<ùÚä½ÝMù¢Á'9aO‚ïëvÌeO+Æn†”×sÚM¨MÒ= ·.{9ÓØÔáÏ.èCk©¶ž{ñÙBq8ˆ,©²l°Ýçs>sРz7ü\œ9˜Z¦”ŸœUË'@í¸ƒÛ/Œxæ€g!ï=¶îeÔŽ{ƒg† ‚ùóqGU²²g|yš§S§q =1wÑæ3#OȽm«½ÌÛGo‹v‚` JðÝÇ%ß~×OÔŽðs­»†5u³Bðá9 ’¤i 1½ý ·ùU]QÖO‚¯ëæiʶ´GÀ˜þ¢y’¤¯WâE[€ÏõyÓŽLGôŒñÇ¥šgàeËáhöB6(©.[¤;Bz[u³;À‘§àóÜÍÔÑWøòôGuÅ3‚ͽõ"Yæ¡ògZ ;…œ?Ò¾ux2Ñ/£À¾LˆÞzÆçõ>Ïc¸º"e£\dCðuÕ)DÒCðú­ÇF~ 6Î,Â=ºY¶y|ι젛s¯u³Ðït³8ot³ÜWý¦›5BðN7 ºYì ›œs=ºY5ït³x«›…ZüV7 ÿˆwºY˜„†D.tI’–ÖŸ¹ÇªÑ"7+4ÞNõ ר¶&üsܬèJ£mÙÎx=Mºâóª–Z–Ö‹ÓŒþ¼QxhKŠÜN›¸=Möý웕Kyº gŒ¼úòŠW}Üfå»RŽ”]¡Ã-Vv¥R¸€·HÙUIa@… àp‹Sj7õ ìú‰=Ê®r7ƒ”]?1ªÞÙ YŸµsßïëÜg¢@‘/]ÖA-äôç@x–äBð™Aðy^ŸuDöðfÊQn >¤VÃJ¯$Ÿ^,äH-I•\À¦Ä ¹­yÔ3*wùïý¸vP¢úËÔç”MnÔ{•¿[N©‡‹¾ŸHS³µª!øq)µ…5xT`Â&ÆÐMòˆ!µL‰" ›ê“zøûG#™J†¼-ru¬b˘?êõ÷??ý}¥¥2¨ x¥¿O˜“mÀ ý}Ù%¡þ¾/ô÷·¾»ëïðB_•ý}FWÉTízÜX$s¨Úõ¸±HæPµëqc‘¼@Õ®ÇïÉ ‚wÉèŠwɼ³HF·¾³HFàç\n¼Ê% (7~ü<<åÆ åÆŸ‡¯ÜXpXnü€ɸÜXpXnlÀ‹í!éš.d-[†EWk–æ‹M²f´g4Ëõššõ*𴩆É$˜?~Žyn’Û‡o34cA¾\Šì¶VQí“Nó0æã: Ü;E¶Uúõ2µ\„LÍŠÀÄÅÌæb™¦…Ѧ˜8ß{†:5P ^ •¶­fÆÐÉd›a«2IEJäÂj –d±§w¶ÁÎd—LIYH=ò©5¬ d}/§¯!ÇMn–??Μ7|:\ó¹ËöX-ƒ>Ié’NÉášúÈýŸñfÑ](Ih—Ì+nu6§=2µ¨2‡}r½;V "#_©ª°«òÇÜ–ï+ë|\ MÈeS×Zù>¯ÖùÚd­!èäÓÜæOåK6ŽY2á+†ÔWÌå^dmóh&ä¿ÿËܪ¼Q=-£™Y^ Ñj+ÁÌtV¿5Ë2FÁØSw›T nž,s³’ŽòŠrÓ¨Á]6g’Uˆm]¯5_1yÈæT?b=ÎÉ—÷3~º© ¢íšœqÜævU}W˜ñ]a¨-M6çÿtð¶,×Ât­qÚ ;¶³*W ,'¿ ?gfÓ‰TÙ¯Ò£øšoHKv OøáÝãóL&IROõñšŸKri”®$îë Y?7ż’¤ÅÜ &ƒ³= 3ö4-zÎLHSõW:5B²Eq¸ûÓçd#&†¯ùòZÙÉÐçe³æGäõÖVE\íÖÖ’oOu5,2ö”QWäHzv·}ù#êÉ&YÿXp-÷d²0Ø}ð23‡\ÝW¬í\¦ˆ| Ò×Ê^L휡qA'ëIyÍ3ù²SÚ1‹¼o'‚~÷gHc©¥ ®3eAƒ~ͧɊþkÈÒ”ºgÓZ­è×|¾}eԣݯ[2ö”Q÷Ý‘ü€í5Õ“|$“Üö-5dx׃`£À‚pgov®¬¿éÚu‚ÏKp”àÀ;‚R#=Ȫ“»œÈ_§®†4cíI9‹v©!Á¯’™³lEàûœ$Ø#0† ÎÝQ kY[¡gü Pwu öòŠ]ÑL.Ëÿ´NáöÚKM“¾hjÊýÁROuMiß4C‚šÜL.†Ô+µËÊä÷³"òéT6RqÉB瞺ɸARg²(-˜¾/Õæˆ w’PýîõòMꔤÓ‘‘-áÌì[þ’Å2µmÝŽˆ|ïä¶3”ã!—ÓP;åÇdŒ,uü~ d˜‹¦©ùñ‘Õ4¨¯ou¡ÿéßÈ”]óaæò;Mø«Àu¡æÐ½®I*xî¾M.©Ö¯º+±<éÒvÊܺÉåLŽiÛÉ—#ËÂûÈVʉ(­€Š%·†?7RÎ@Z7Fn©„(hHùÉKjkL« UÉ­@¶–_ÔëÔäbÈMsû8DÂÇš“?glÉ"³äZ$D‘“ŸÔß‘âäˆoK¾i:V¨'«Éź+©Z,‘L5£"GŸ¦š\æ?LOÖ›}>-¼’P¡VR“‹%usÒªYk¹–$Íš!òéHb-ÚåÚp”r*`Õ䲓FÌN’KJ£MeÉÖÀaȆA=(~Îh'©™ÚD^¶3A½îù¶äîsºÎr+ÂÉTâ7ŠIKí†Èù7íšiBßûsûT_R… ºƒß”+==о£ÒÓ0¢r×?ŽåHí»GzFÀ‘Û"ËOÝš*‰ƒóbIh”Þ7ADcÅ(ïEÎúÎ6æûxë=-$I„K 1 ŽLÌÿ³QÞMú—Ó•ó&› ÂÁF‹ÑÄ‚ŸÚB®ŒgÃÁºT|É:×5/ÃÁŒ&ÉhÃÁ|]¼5­§oÎ÷ÖÛ@jÀU´¬d=¢ÌÔ€ð?^QfÕŽ|oG‘òߦúTšOg\É4¦Uinü S‡-×TÏ”]’,ÕÄíäü <œlë‘DŸ­yÚ.= žý¶óúº.ò6M¿ÝN~T¿µ7ßî/C7þ«°6ɤu#G–ÂFƒ=4iÃUÿ'ìJ’dG•à•Jsæ²÷¿Í^hÄÞé?ˆA™’ª¬–n(™ðp7š Jr“vÄF;ËÞþCnN}I6,OBŠ’m1ÌÐlš«¬3'X¦)ì)~÷Zìuc羚$©¨ÔÀah¹Ê1Àèû3]Ç}”Û” ´<Ñá2w/ÐrOå¶Ž~£9Lþ«o˵âÒ(E.'ì /@ 7¿1ß*ÒVˈ?mòªþ€»‹Qm¶½ŸYv[mÿë®Ü¬RJ#cG{Õà]˜Úº‰-ˆXæÑõ²fØQeÝ%ÃA;i¼Óâcñ¡Z|¼ðnñ¡Z|¼ðfñ9l&ÀÄöÂ'—A°øxá¹ø|zþBå ß‹n”/d‰Pù¯”/8£7ÀÀŸTëÃ#¨ ]N™±cö½s£ù˜†¼ÇÓ0¹™†²gð4Ln¦!Ÿ³MÃä—ih/&½ä—iho½ä—iÈѧ¦¡`x; EÎЧ¦!þôÃ4Ä@ÍÏ´~wö5Z†sBEm×¼¾ýîl° ‡D+w ô¿ç«gx¾¾o櫚 h¾¾oæ«âùú¾ ?ÚˆýŸ»˜3´û?w1ÇÁ‚ÿs³ŽÚ`#önç+ãŒóÕ÷Pó@ëíþxú3¾Žè_e÷ÇC½´õ1·ï”ˆìD¤yƒ÷s;–_ìüb‰€þ°!mv¼W+œ+„²õ§s­\ãí4ô?SœfRÐ<4ëvÔ4.õ|ë„ýd‰|\9# õCÝ¿õË„.delFÀ <õéC/4ððÐÀkPƒÿèŒW]íÂêwý^ *Ò3æÎÖ/Z·d•5Ë2§¸L&Çê!Ëš¹hÆ!ƒKäªsM¢ºE^›‰Ó^Àvû;­º‰s7Úr‰z;ß­N‡ù/À¾ä£’gƒÀàZh¾«Çñ ³¯žÅ°´ën¢ÿËÔÄB­+=Þ„ãp¥zôƒßÛ%s£7B^Eˆ¢U.ÜYúÐþ“¢E«EXkCúÁ_ÅSµÝè€;øÁIO7|¦³Ë>0ý>öXðjÔº5›½p3Öy+khÏ«=uµNPó¤¹mž|g=ëòÝýÆÐñþ -U¢H÷Š£#»Ñ™šò7¦íÜM¸ÄÖÚ>ü)áÙù\^ØnÊ]÷ªZ‹¾iìýð7!ødßmƽüÆÕÃ5nu!ènĵ·‡ùt•ÏëÙ<Øoü´”]f¹ã$Peâ««€}Vwö*Àß^ôUEäÊ ðò*@ÉÖÜ1!Å’bëzÛR@`ˆDÍö5‰©é˜ ý÷'!ÅIkNs»õÜFãþõõ±öèû•È DróƒÔ×$·¬O{‘§ž¬+£È&| Ã@÷ÅPXý§!€É%K:.†¨d€!=…­LG¯*“Åb€š[ó†’M~ÚŽžàÔú®Œ¾æU•EKѧÇžuIªDÚîm†€/4](£º¦!ð Ô$Ûv„3LEÛà?YÛooùNsômÏ»Á#;.óä’çyaÕ¾FÖ÷lŸqwvYÑÃ6+énÄ -2´ÏÖzû²#ƒ5{a4-2‚H“$‘%K÷=FoæZ‘MŽ ¦TýR„¼ÕÌ›ªõ¹w+š·W&kÊ"ß6·+³?S"Û¥¢Ûšåh¬ÿ@a#MN[掼³†{ Ù¬¤j¾wó¸ö»}/>ÙdheîöÛU.ou1uèwúg¤èD1[¹¾0¡Þí2¼ÓDkz†‘ÑrëjO?¾W%£™Ü«’\£×*Y:á>Ò¼æ¥Æpó¨\×÷–æ6’€"Ûöß¿Æ{AËûÌó*ÃßõfàYÏ«…WS…”ëëУyøßÞrr³X€·œx·—·Ê‹ä¼¼ ïƒØÔøOþ8ŠÇ7Aà­?N5Ñïýqln½†0™yÏpN!0ºåñu¸Ä{Š×þ8»˜›­ª ðžÈp‰ï‡DXÛ3Áo‰° Þ$‚üV¼I„%_À§DØ Ÿaw|J„!ð)5ÏS",jž§DXÜà?÷öè®Ãû£Á¼ˆ6s‹Ux4 ÕB÷•|³Lä§ËdÁ%†ßTdcU –zà”ÞªäË[ B`H„?½)*L?íîÀTz˜)M+Òk>F…ÙÇ‹¹‹Ñ Æ”z—Ò#²Iˆie51Àä¸M‚|}hˆ¡*‹.¯;Q “n€Èʲ‡ NV¾Îîn;çœ?1I-ÃøRŒh¨~å§m<²Èh–²’%Æ7Àyø:çŒÃ%E;ì$•«ÏêväSýrû¶ !íΊ-…À÷™¯¢ˆq‡Ì!ØB*ÒU¨Á€xpe|ª}bU?Xšl€Ì[-Ùî8©2»ªË:„)enê¡«Šqk12@H}«¯s;ü;C^éù0VÓÔÔ9éñïŒN¤º¿Ñ‰fÙç¥ï0Ü Û@¬-D;ˆ¹šðïLν½¸:Êæ%ÍòLå6[­ÓrªÊ>%åŠo s\kY%²*Ãì&n¢Àÿq˜a”»RáåNÒ’™æ¥_.XrWÙ(ÇÈS\³Èk½¬Êö¤ÅƬâ¬EžÚÉ…åCð2çÙ–rû`!ðŒ2³w)RQíó^.KLnî÷TËS1úÈÏÜÂЩX&ªV®Ô=š–~•Ùux•Ëæ\iÁrŒ|)UÚäB%ðïáS—¢ÅÃw{JªM„¨JÈɲQ %žÁÐ96'9;–u(†äÀ:ÇFA^Ö]îÌlïÑ üÓÕ&7sSÎÆj-G¼..ROz‹j¥‚lE“ j9@éhÌ¢tÜWДS¾ì¸F‘EfEfN»%Ÿ¦±wcÈa‘†ê§:½é«2ßšÿÎÄ&üª25S*¥m¹­£hIÔT?-$D+­ðRqJùºÎ5êMMõ3OÕ¹ŸÃBäfÞŠµgøyZº•Ö”²ç×(ô`ô_•WÑÿT¶%Aó(ô¿9Ue'íèpˇ='dªÛÈ:mÊ´jH“¡…¡óÓ‹·ZÕÛÈR5x„„Ú³ë˜ζ`æÅ²ìV/Ü"c„ÖÅÄ\[ÕŒ£»4¡„9\ØjS2Î2øA iâM‹4ÚTéR:OèWz>ý¾WÊvûN)›c¥lô¿ÃèÃ#Xþõf˜Ea4β:î"8ú¹/QmP‰¼Z.4}pædŸeß Þ¹­LôƒŒû´éº~ú£œÍb\0¾¯õfÞ/µN+|¨µ¥$GÞ/µ¶t‘÷K­· ïk]¨2†ž².¤ñi­]r#ÿN/…2&ȼúß@!7éòÞ¾ðD>Šb?‡W+8l€áàðê&Wäƒ(ö_p9ü!¿@`Œ8ŽO¯¥b+Ô£} Šü;½ÈCÂØ)à iºXEÝbÚrÙ7ø¾Ü^ófvƶÁ.5ŒóuuƉ=P ]¼ßä±;OÍ¡%ºäçÛ¾YÛ³o‚O§M“«"ÇOŸ®åÙ’xØ:xPæ #oex¶Jø ᵨ¶˜AKû^×’Fø{ž¶µÌ9^I7gH+Û/¥›;(m€¯{j¥kžð†ZÉ>¨•Qøµr‡À'j%*1¼——v³&z’—“ !£èyiJ¼——¦=^ÈKs,/m€Ñ¨¶“—6Àø^ÐßýÆøA×3ñ“ ÿéÊb€‚þ® ã'AÅÑŸ ðAÐWæAП"à… ?Ç‚þøº—¶w%&ÏÒög_'7ÒöKÛ`p܃éšX¸¾ö¬?Ö¼–êŸáðùnb¼ßw²·97Qn|Þ_b¦Áåñ°–¥ûŸnò–ÿ-X?·¤̃Q ¥¸ã„­• y_2•K, Ð)ÅI¹C¹õoZŠJ P¾˜îkÁfÞÊ>¬!0¼4²'rzQ{åcb”ÖC=ÎÃݪ¼9¹ñh6@ÿÆJ Ü©¤â]È@³Ö/;2rÌEµÍ¹ ]ã3œQ©A™ÑgPÍ#ˆ„Ÿ¿1ú¢ÇëGr¹ÄÙOÇ<ËO¢îº–»E*¡Âq˜Ò4Su˜J§anňJ  ¬›5`Ÿ:ˆ—h€?˜ŸHi[ŠJŒÜ×+Š’ç$yA—mhÞy!P®¤f§þ»Pá‚ÈHæò£ÖÇ+ï_õ¢.}5£¼¯÷m›[û*ǧ¢Éppét½üÛ„ Øãä"ÃÁL.yN›A Ç£9#QF³líÙÁ_Vç/6r[s++ÕÚŒÈIÖ;G €Ýjß7¦ªäì*ìûF 6ö?ÿ `êf¾QË‹_¿È0º?Ë0žÃìý‹ £ëë÷³ #oð^†‘¯;>È0r¼“aä§ cüþE†WæA†d)>É0~ dñÇŸdmˆA>È0~”ù È[ýJ†‘È0d|«yîòä’Ÿßòäz|È“³k~òs“Ë>’`¡Ÿ7J‚eI°ÀÏû: —xŸë®ÚŸ÷M,>%ÁÎø”»CàS,úôS,*ñ) –¡J‚EE>$Á:Aèç}™;Ù$Xèç}™;Ù$Xàçý¥öÐŒèWãií'þçžs†6”ÈÐÆ^QC·æ«ç|wqm~¯^éÝ6¿—¯ôÀàöñ]Ø;´ªå^<¾£ë‹¬EI*2Œ/ßÔeõùÊP­&ü?z“·™)ó–ç¤7 Kt8þ÷”'–‘M±¤Õ$ü Œ©)˜+!*ËÛLB°É#ed:1ylVf-9u8œt….Q¹ÆÓ2ãt8þq÷:&Ÿù<’¦ƒ@¤qaÓCÒ~É:¾¢ï5.6»BGÞK‹ÅtÀ‘÷RãÂeÏ$ѳÆÅêòè^ãb:4.Чï5. üé{‹mÒáa@bTm©<\P:4íìøÓ€ÄˆÕj`»ÎÞ‹þ:" ð¾¤ß8Ýqà/|)úÛâïE?€1¦ã;ZÂ…ÛbÄÌ"‡š–×,˜2ŠŸÐo|R6=ätëï) EŸ>™Yê Ø¥®Ì”6åF³ !ƒ+:ÕV©Føëá•ðŒвš@É=ïÀè?! %´ß#¡ýäu+´ß#¡ýÓ‚úKhŸ!¡ýÓ‚úKhŸ!¡ýä…Žo‚Ÿ[ß7LÀÞ軉íO)ìÞHa[e•œðÆso4ž[ôéð–Ž·6Ýê6;5æä}:¨nÏ{ô“«Ü·r¬ëng¨Ä×pX¾ï«$¹r”Ó!µ)þ 8á}"‰ó‰ôî9ƒ6-''¼K~Ÿqw—©w4W©w¨Bzq»à÷ñJì!Û6ªSà kú±¶Ähc€ÚT¦JS@à™”çæÁ^.¬ º” \§ZF:)†XòuÉËɦ1s¬\‰åHÓ~¨!(çZó”ªójí7ô n®ŽPé_[Öý Üoët#­6ž:_ÒUæ€Ô”Hå¶£ßèýœö¹¾É¨Çrë- ýHÏû¾xP6L}µ»<¨ä8#$ï¡öòä™ ”—‡„¬ 6hNÅ<Û›à8;¤~úÜyN·¡›9BF'ÒÈ×RyÖÉ)ŽËÿÊ §÷ŸB®c©›!ˆÔe*äÆ ¥!_©Ù’™5o6„| Õ®#‘éDƦ@cýç< ÛîØ‘²ë6g2ðÊ û“åúJL}½šÄЕ¨Fz'uÈÚ„¢sËÈ<ã™d­Ÿˆ%2oö¡Ëp™!"õ Ú4ã*(Ë`ŽQ/SJ1p ›,öòÐ4?Dé9mw!gPj3_šæ©]´jvp‚Ûvë 0„@CQ+Ò¢.V¹jB`Ó©N¯S5Ž<µ|€—÷1Í53N·JÈEÖB 2/U’‘K ú¯“Tš† ÙŒ²! jÇ7ÈF¡&‹BÖºZ ÔàNÈ\qýŽßXË£h±s9”2„ô€äyeeWÇ5mšÚ­¬àŽD#­£rÓôÃØÈÅ5¥2×)jv°‰™y–ëPÍ=˜ªd(›-Ÿçi'U…:ÜÓ©J»Bææ¡¨)sÕ—Kƒ'`Ö‰|1Ž£.vÀ{%¨E-ãZ.o• âM~1úE jKÝEÁ9*mO£xâøô» k£kÊ:>kó— ï• VÜ⥔ð™2g1'vXFaM9[ɨ§;DÓûR2JûO£ÿ¹Ø00Žd¿"r#û¥ Pö ˜»{ºœ;4ÉRë&S lÎOS|AS<¼uàHˆ}·?¹@p$Ä=o] $ì¼[ˆ_™!ö;+™4º5z»aÁ3à}}#x¶@à…à?žíÞ×ö³ç4Ï#À+úÀëd‘ŸŸ_ØcnÙ%Ð+±ÇÔ² ÙcxE_/äìÎÎgi^¸“Ÿ61^ÚÖm‰Ñœ×ÉÜ;`€N§qâ=”d­ö ¢ïF™¥mÙ›8.e–WÈšân‰”|êæµw™s¬‹­EböZ3§^ڲ†ÀçVäbè̆žÓ¡,ZÎÐ;î|´Ä™’—UZUe§Æ•Cà{ËÄøŸŒÖçK#éˆ:³ßó¥©_MeQ¤sêë€p*ÒXî¼ËÍÆzX&4à?@üÈ™ªõÍÐwY×9mBE¬ðõYyÑ4µìK„ ²Ì¤Q>)d:áÏM°¤‘EŠb™³ÔÉÓzd¸Kðø÷älE\Í1~ºµ ÒâG¹ÑÔó|¤UÏ“®F£i3KÎÍ(t°²Û¶i—ÖÑÈ=rË,™š\f'Ç$ä*iMò²@.”4jƒÈ¦"§BF_´ÉýÓÉoÚä¿i“£¿i“#à7mrôèoÚä¨Å×z¿\…¿éÐøM‡^@à7zßtèQ‹ßtèQ‹¯s´Z)MôàÏ£*¥»jÓ„ÖT¢ñíu ŸNv‘¯}«¾a=Wl\`ÍŠ-¬$@CÁ–Õ?äŸpÌÊ `pÕ]Ô=Ïr@g{´š=jR[hÚk ®ëȉ ÈFúN¬j]ÛJÄÈîâv \1ð¦òKWWá€7•_gà N3ŸÇSÇÎô::$üŽÀ­× â¦Ù6<±(Ç·Hî¸ÅÛ^³u]!ð¶×Gà e”œû!_ÕáxtÒéäñs¦aø$LE›±t´,òø9Ë„ù´NWcãƒÝ›ðì[¥žUK½¤™£Ö‘ÇÊQém1óŽ}óœ&þ~€<~άzvßWçËŽB·ÎÂ’iæ«  °¤3 ßYîÔµn÷¦L̈rT®vG§žæ¤dÚlYÃu½¹êP^UmVd/ÔðĨ¦„ŠÄê´„€dG:¯'Õb1fó’@ Áü~öк®E á¡ÒNµ(!ð‰€v²ò¾ŸTØF-¾.º>ý|ãùèœqMþàÿ·ÇwŽt²ÌË&!pÓí¶IXs€ïæXíW¿â>‚ƒmÞ6!ÕÁnfÙ ùeN %®8O³ù½äã`dΞ¡³,û!m¾ï¯íPV¸Ÿ,H|ÏA=Ù‹þù"CV­ã¸&kpb¸ÊS51ú¥cwÉO^|È\=YÓðª1^L Õâ0dc²­äjb”nb¤M#F|]µ¨Äø¾v ¤i“Š?õA}y=ª¯´Vý4@`tÖ#ÐËJ?«|üÞOqÿq‡·~Šú³‘³a H‘ÕòxÞú).П솇rDµy…åˆârD6ÀrD¼(GÔ-‚rD¼(GT@XŽè€á9|iW:¾Þ7áKïÄQøzß„/µ>ãðõ¾ _=Çáë}¾zŽÃ×û—ðå²Àxâð¥½uPøzƒ´ º3(4|îBphøÜ„Ý" Ÿ›Ð ¿ Ÿ»ÀAhøÜ„Ä¡ásL‹'àEhÐÓ …†ÏMhÐ@>¿„¶ ÿÈûÐÐ!/Bƒš84|îBƒê Ñ]hè9 ÑMhІ¥(4D7¡A=‡†ènÏÀ¢›Ð`& ÑMh0††è&4 Ñ·ÐЫР!0º’ªphˆÀ ŸÂ½$gÌ É`‹éŒùbZ{C`pÝ⬩¿î7 L,1mEÇ2Žk7>Apzt±=zæi·µ\$x]Ô’’@ ¹¦>áÖë÷U¯ Óër)Õ 9Aàóz5ŽoñT”á6‘ê óž·>[ Ìý&Òm~ô·æùZƈw›>c!ZÎZŸP¢ónÓ·¸¨=Úš•.=ñˆg§Õ<»Z ¬ eV8Yó¾ã*ú 5°*¼:…z¬ !œÖX²YgÍ*êÁq °*ô6Îè¤3§íè ÉÁj‡ S@Ôâ è\;”x¤rX–¦D½~ïÅeá‚a5ò² Ò‘Å °*ôÀÒìÐô}5©˜´¼M:Êrg(3Ò‚ \dNð™«Âùó©²{…‘³îSŽ‘€4ËY¡zí™K±"d°!s{½ÌʬZ²yÎd¾¢ÙNÍô=bj÷]Lõf(¹:Võè3Úûc²æ™S—¡sW·5›p››qƒÏQ³²ªsšª] þ>†P¯ÎþGó¬°?2Þ®EÇ(—ùÞª }“jÆjL«¶lòqP\Í·My¶ö}2H  "$³4[µ’.E^õ}) ^è9ß&ó®äRŠÆíÍò˜9sÊmKEG ÇMzžÑf®Ë=8Ží- J')ðB/gÎBs¡¼“= ðeác)ûa‚@àè.¢5§hR0>£G» =´_FÒ\ª=g†zãËéÿš =«P_«ƒ¬&qøCTq­ «¹ö¦WkǬkYRÜ&ñS:.ƒ¦]Õ|œÖÉQN=2<{¨¡cË1AÈçvõglŽL‚n¢kSµÛ- Ù…Èçåzº‘4õTòIKû­ù¾gåú„ ~aåbàV.^°rfåàQˆY¹ ³r ð(¼`åö+—ÂkVn€_X¹¬‚À/¬\ÜâV.~cå·¬\5Ù„üÂÊ]1ò +×ï®2E¿ Iìï¹ßßzm±ï–Î…pΪ„t“yô;‘r{˃Y`bʧ m'“}ÓÌEÁnÆYž„ UR‰•­ ”¦ôÒBK9ÐÔ;``hÊœŽµæäi)Àu]Ð;>=±À”‰:N•ŒeC¥³¤#À,ÐrrWµÁØD ëýΘº•mó²í‹Yç¼€ÀÏÎ*`šfXZõ)_%zttåò¢ ;×÷ÚNÊÅp´¼’ c]Ú¶e!»ªj–;ÍbÍþär_YBeù²¼e×ÊE èã<ÈF?H3ŸKÔN¥Å2-B†÷’"Û¤|þ")‚_$E0ð‹¤ÈÖñç/’"x+)¼¤ˆÞJŠ0_)ï€ï«áqÕÐþƒ¿n˦]}ueÓÜ•M¨Å‹²iî˦Q‹_ʦ·Î¼~)›öwÜäõKÙô€€ï++› ðsteÓ]Qí\Ù4zôUÙ4÷eÓù¸dåÙ²iü/ʦ…/›Fc~U6Í}Ù4êз²i‰‘ϳ#ÂÊtD äN™@ߤGBÞ_èšðnY‘B¹+áå®üK~n䮄—»BÀ/rW ÞË]É‚C`xånãä®P‹—rWÜÊ]-x!wŽÜzô…Ü÷rWx)wÅ­Ü^Ê]q+wU¡¿»â^î 5ùEîJÆy!wÅ­ÜUåä®<’\"µÜUÕdyÐÕpÉŒ¶­R±e¢‹±Ò^ KÚ‰+D!»ùÚžHµJðŒsµkéæÉeº#ѱèh¯ÓA7b$ú~#¶‡œÈë(­^Ö^ &×1ËS|û-M<ÑWESO}Û¹\OxÔ²ó“²Ë9MÖxrt~þ)­¶N»e“ò.×A±táNx*"¯,Q'k »&Bâ #kÑk’ €PÁ ¸VYhéH‡_H<Á<Úˆ'ˆŽSÅÒ©£Ý*`:“tk}ß6~®n±Õz¨ó² 9F üÚ©ã:KSZ·K…üj¹úkõiD“ gµB޾oqâÄ…ÌÓ†2†Þú¾Y²:+Ûš•tÙ¤` ö}ûãD˜×nÈé¯  ï›OœmïYɦXZŠO¨lYø9”¨ˆã½å=òIº¥a'çšÁܶɄ†óaEYÿþ#ÔªSÇR¦CZgùñ‚°‰M )èTNCÒ̯Cᮉ°¥ÄŒ×_9ÒºÎøÜ”hä›fòµCk;†àÒY–æ+‰Uu¬¯˜@ßÝK(Âu9Ôrd#¡êñ´~žêh;¦©ð1 úèée4Äìæ—¦E§39\™ô4ÌK[à£÷ŸŠ6F¹²I Y²ýxäbéú™즼et. ІÇèüϰ\ÓÚóúžîµîL±u†Ýþ áØ ›Ï¨‡§lšÁo,ÃÑ1©µô¶YÇ*.=[5 Ó.«Ì/«tnÕc…Àðnx†dø„‘y«¼¤k'“d†À×Í8ö’ú»Èø®œÇQý†? k±[ë&C‰ ÐJu ôÁ6„¾+[X.J§Bë&BÚãåßÃws•Ò¶@È\̓럢Ü߇äKÕ°”ã>BäêÒ«°À’×j)†ÀÃÕ|±Ý2Ž©'ëïvwWTyïïž®¨öwŒãQÈ ½ã&Å-2žMqäúòpÔñ¶„Àð’ýV­Kê;Iø¼ºFs„1HqŸçk4/’®=;ò•Aàaõ,W;¦l‘|æ†Ù'».ëTøôpøD—Ùæá*Ã*DqŸˆâ€€ˆâ>ÅžI*DqŸ_(ƒf¿¡wŒPY‘Iøê|™Ìš¯hÀaÌrEz±Ìq6e~B¾Žw};5o—x– èäò`ê»,ÃØ#ÀgñE¾êѵ:Í·)†h|ìÉ@à/…¯ó§±E¾¸ó—Â×Õ§)Ü7´¤ðuþ4ˆøKák§%y1 ÿŽˆ¿¾¾Ó’6btøú…–tDÞÐ’jÍX•éfíÄÈÝš¿Èl*)zÍ¢Z¤þq/YZ­þ‡ó>QòmPËž ¼/Ö>¿¤•zIóS Ü?ÿûs¸Lo«Q&·eŸ}ç·@Ñw3_/hA 7ÞUÒª÷ÛÙ'>jœµ?$g ð@ôèð^ÑÓIÙèwŠ=y¼ñ.Õ/S}/“¹e·ž?¸znWÉtÚ—£k Øå4ý€É< g¤ðHüÁ¦jo“÷U2ô FÚ¤ÕŒœo‡å#¼§ û}ìóqÞ`lAì‰gpÞÐ\Èžx7ì „ì‰gpÞP@ÄžÞ|x{ÚÚÀíé“à²,uÀ¢­Z3Û ®·§Ý$‡¯ívª¦š/¬çð £èZ&ÉPûw O{m ÔG`ëv4aëR6ۣï{íU6·w„Ã#ÚŽ#ðA9:xeMz lÝN›r®7å’›ýî´LÝÇoíÆqbhü;¾n|¢LgòýLØ®MÖLx|G›fV{ò¾ë: ~tfrMAM‹"ÛÆñ}švÀ…‹y=¡—•û¹òe–uÓÄþ¼ÿ„y^»§²-"oZØâ=zJ_¯=Ô}V¬HÎ_&é’fîº%ñÀ—4nÉ‹B$TkŠoëYt3ÃÛ¢k“zÚ.¡ƒ×_su¬’®›ŠZ­’žH¼4IÆ]]Y å)÷{Óg„jº©-!-J,ä$;|]ÚrTÈùú¹©¦ôe—þÂðõø¥ìƒ;/ݽìxY·F‚Á·ü"Á ü"ÁP! ¹’Óu Ã+‘\'Á€€ÏK\+Á !ðu)|k%P‹wIï@¬^¥ë¸E®”Êó@+s©éZ·=Lçe€óXÆ3 4Š˜Ö3jq—¹LrK+G9ÑIÒÜé(:àÍÉÆ‹_0»lµCTäXJ¹,r…À7Z±ß¦d<ã?(_m¶:y:É´q0]›Fýçè iUe4rRsmÊ0ò‘öР±îNŽºóÒ·ÉzÆú·I ’¹AO§ENS^"dxDš6ã©‹·¹¯JÌҥ얦ž„æ/¬wT°Z¬ISФFãþxô~é*ã×¢iKq@~²ô5ô+U¿GA1rÏ®'ùvU æPž ŽÆ3ø9 MeµAV-F> Òf/rPÑBH4žA€¦óºM9¨Ÿ0zÏ€¤“"UÈV(dŒ‘áißsê=üžOŒtr)~ÏDnï™Nå*Ò!Á7ÊݬSÈlž&‘q„ü\!™‚Q1áU&BHÿôXõHàøŒæ¯yº>‰ _çxýb.ïØ˜ÅÅ2WÜ9{zäþ²´´;ˆnÒeîÓt@H‚‘úñIÇõˆìš+><—©úiŒ‹H:4žä Éœ¶cj$ù¼%¹ò…‘ºM‹ì OyrÈ7p+Î<²ú?aW²ô*«E_)‰$~žù=Uç{DE»úžþ‚4îmÔL2ZŠv»V6OuÑáUúñ ߉MÙê•g1çÍÀò tû,eÙP·­²æåŒäÂa¶-[Ÿ Me®#Ü"ï¹îdµJê•©Äcâ•Âþ7Çf©jåÅ4!G’¢]-“¥Êh5õsÑâLÈF’âúúc±T”ö…£»±È' ÿµGíÜ÷-m»B¢=O^I×UÈyâÓœ&ø9Wâ]¼l‰ƒô9GýÔ%ÉŒ.kò³CêÛÚ eNZò†d.ëÑ  ©<’49Zùç ’ÿšò¹^·o©\Ð*=!¥¯e§œO<[:: ä㔅ij>áËCr‘§$-ÛˆØû iñÌPÏòé4µj¨‚éZÞÒ_í¯ÞFÝß&Ú»@Ô³<àm,×Füïß/Hö)`ZŠÔw¸¾I°CšÌ“FxŽ˜Í "ÏK$C“ßaL,÷¹§IiìN ô¹mrÅ}ű޾âÐç4±S«¿"íyáÒ^@Cô¦&OmgVAç…ÖÞÿA¾3ú8S·‰%˵À§WŸ4Zµú@«cšŒTú ʳö'#™%Ãã…”i2¦hDóÿræ†^ÊÈ Zžµ0áßJÅVd¹¥±ÉDški{´à7ïošìõüIK±!uC¾Ñajùרâ2ŽŒõ.|¤Sÿ­BjÉ×o¨€KUɤç` F òŒÑˆæèûÝŽ¾5uu\ô蟟}fêb`¢š*—rƒ‚›h4‘5°­ÆÚ­O¸+RÊ }¡ÒÒxJÊÖ…œà¦kª±zwR-S]Æ® .Ä}f« ©)h–‰^¸ÜSûÌþ™>3ÛâVTŒV‰¥f·@ øïw­Õ^5Ðt­ö²Ì—¨‡7 KüûŸ=žõ—1ºÄN1Ú°D·‰Š³™öÃà"*›z(èvç¸ÚÆÌET€zè)nwrÆAxÿP„²¬3‚Í3m"K„­Ô®sm™óh`í°@ tí “EÒL3ž Vþ­×ƒNÀØÏ=1Eø¸L¹>΋U`M}.0Øá—9lð3:Á5šºzš^ý«é$ì…û¿ÑrÀÚµ¬AùÎÿý±ÚæŠU^pW·s[}¯>`U”kZ aªIš£œ£Ÿ>6úèyˆšLÔm/_e¦¦nê¬æè­Ã—Ï*<—lœ£fûøãèöÌŠÓuyfYŽuíú½Ã-dD¨]±²¦µs™BD‹³õ¤šÀ*X9 ¤òÅ&é#èí÷³%zÊûcSV\·ä:;í¦’±ìú2æ™,ê>ve á.´Vh®Ÿ§æ¼—–ó !Ÿ(èS˜ /ŠEjøÝ_>ÃjˆL͘å˜-£ÀÏ HÉœp_WõIÕLM‚Ç’6iî‹2ê]x(„¤Õl°^àZJ:DiT w·¤ i¥½r¨ „¼£¾ËÕò¬ú1*Ù°ô!d–›0çŠØÐ—éÛ1ô*¹ÐïÕÒs†¶± $™RÅÜ0íÏó4ÍÊuF|IöŒ1VØ<ª{'‹:w/‡0¤õ|ÒÔ† ’¡fq2'­§ $ýýýk[ÖIßÎ=Ä’ äÏÖ¤YX‚z¶,mgS„ŸÓ”iþ®—xf‚}ÊØ©ú²iK´çƒ@Z¶‘!ª§ˆN¾·;ÜI“v••[bË©’,z–±N"äãS2WùŒP27²¾X2w%oÚ$sƒœHæR÷@27ÉÉ\$‘/’¹®<5$_$sýæ _$sýýC.%siÊÐÔ’¹xê É\ ´ÆïßÔJ*«„ &¥Ëƒ‡ ’ ‹*3ŽS»¨PWÏ´xN füûßl“VvD¡¾dæj‚ñ'PyŒ¾V¨; óÒ¹èºdp¤Ó@Íø×:–öGåRv’Bàë´vwr8 |´<Ëâ—çõñÖð—a!0€]ÆãÕÅCíÔÚ¸‰â”ºÌÕ–Uâ˜4j.ËBfÞƒâ¡õ'\CæeX±äƒó  xèßÿ¬@†‘Yëۢ˘cÁâ¡L[Éz+k©¦bvŒîH<!yOóebíùðÉŠ$+Üc¶¢X*Z 5w2ÿ°´k“•ÑäÚ_xèÙ‰&J[‰ÏªYö¡ÊŠ!ÁÈ—;¬ÖÝf=¨¢Å:‚â¡ÒˆrjäT;¦B(º‰rZ–¶VBо¥±’çuÌÔ¦[rîç¢IZ´×W ìŸÝ¶²»h™æK|ñÐA(¡‚ŸsA(¡‚ŸsA(¡‚ŸsA(¡(ßùÑѽv‘ºUßJSþéÏT¡Œó¥œROÁþZPv—<ÝVÙø³E3L_¾ö‹,P4e—c 9­ñë]°H)b#¨,•_ÝmFR<,Ýýˆä̬RSS6m#P°xP‘·=ãf¨ALAø8­ŸóFЦx0â¨Ìª‘Bày%YïâÂ@øð°Ú­wù«MÞÎÅ® › ­ŠžNnS¼wÖ’‰¸jcé9 gú9“ªvi;e‰ijš1ƒ@Ó^Oµ5E%£S/Ras/—· êþŒ}ÁâÏ\ÖòoË©£É>Ê>öËó¾áÒ½5´oêb5+È0º‚œMµNÝŸ¿ÿ™ÿÌz¤ucÇ"Ýê—é61îÒLÍ[] æî^{§¼¾¦Ô¢~‘SÁ Þ0}µ¿¬}1$YY³2rɸ7¸?¢•¾–ý½ÕÎ<ÏåÜKʆ9‚ÀŸ>ÄUK‰>ñ>Ëû¶'ûÈ »•:Ä<´”I´à·Z]ßòùšÕ\"m¬UhÈûý´d±rÿÃ7¦uß—,Jê\n(‡(é*á8qF’y®IÚéÿE²«& (efs‹”EI2VV„/’y6&íåèxÃ’‰hj‚š¤M6EòN6õ˜øµ»TL£»’ ŠÙNƒ©³§ßNP³ì=ÔÕž…Ȧev Êï÷ ºm1€œäv;á4С'Ài@n·NJgÈi@n·NÝÝ8 ÈívÂi Ãc€ÓÀ/8 ¬§oœºRpX`«lª›2¡ìBn½r»rÄ[Fe¶Lùîõ ïÅ=·¤ú+I‡ð¨a‡•ï†i°|H6À¦6mRª\+ pylx¬(â¢dµ»i,ðU&-Ñ­rõ?äûÖ#f|ð2u  á‘{±N«!¶õ!äöqâúKŽËejk& à¤ÕŸ«Õ߯טcî¶Á®uåÁ!ðqÐÕJç™V™´Ár#']­ºÄtµ’9éjÕ@ÐÕJn䤫UM »ZɦôëjÕÿBÐÕJ6¦}³ª@šdÓaú®V <êjHÓÁϺZi%ƺZõÑ ºZÝ‚uµÒvµ’Ûó¤«U7k®V <èjU »Z-ð¨«UM ºZ-ð¨«U Á <êjH°ÅºZl±Àð»Z-ð¨«U Á ¼èj-øEWëyÞÕº !ºZ×±uµ:ä¡”|¾DKé’ äöÉ^f½gu»G“Hlžƒq0W’S8~£\Fy$šÚmèÆ®Kef…è—hÆ@‚üq{õ±ˆD³pô´–›Ë4v¨«&Ú½ŒmìXí®Â›*ITE 1Ü‚À™¥UƒEåKFÑbex2ѪwVOŠ€ïϘ–m‹"¶_ð¨,Öïm‡œ¥¿Œ¡Öì_3&u $’(Ûi7†%ÈrLQY‰¯¹£ þcÈ€ï$j–sZãÙ‰ 'ýYÃItí~,§3‹¨FÈçùfó³‡_6l6õæx³…_6›_¢ðd³©í‹7[øe³á©/6›ÿŽáÕf|aèO7›=šú} bx³…ß6~í£Í¦ÇD›-ü¶ÙvÈóͶÔxöƒÍFûÝf AÜvµê9¢ºÉ¢¾ðB4äöƒz²ÖÒŠÕvàn££7ÿ~v-îyašytE¯Ò±ç쀥)}£ÕìxÉ Dúú3ÃJ^Tl‰û’Aàó¸þ,šÕJ"àë¸þŒÊV0ôŒá'Ãt~J ":?†éüÈíý…ÎxNç7 ¯èü8^ÑùI¼¢ó›!ðŠÎM}Eç‡F¼¢óCo}I燆¼ ós^ªCžÓùõ]ƒçt~}“!$A>IfB1"bŒ¹à ¹ßö„(¦‘×mþak¦YŠ2›!08ŸZ¶xÿ2µ¥ú"@ûðpêÎ-:Ð>ü³ò ¹Ò²UcWP1¹åÕ!Ð6)“{€Á joÄhÙ¤¶f”ÜÉɵ¨™xc›DÀCâð\Ž:TŽ€Á°•éЇ¯»Û3*/?ã2ñš5ZÇrk¯C dÙˆd]u /Ú´uçÊ|2Èzàœï¦zeµÜËtí»eŒ\dàªW>‘ƒø@z2ŽÄ“Ygµ˜Ðä–8üÙtÈu4ûJ‹‘•xccd Ÿ‡S$ãÈñ8äÝ¢«2s`·Xdxº/êfÿdˆFû²±mäþ<ÝÀë¾ÜƒÓíæC2÷O†h´ÝvÀÃâ±Z Èè÷­ÆgouseÉ Ããƒ`¡ Ý]œX¹s2;‰è3|\л:àý½kô® Ó» É´§œbÞ•M&LïÊ0½+šL{–&é] ÐdÚÓ»2HïJ€&ÓžÞ•AzW4™öô® Ò» É´§weÞ•@M&LwÅ0½+šL˜Þ•azW5™N8ŒÝW||ã0FÀ+c ξ¢ç0&@ÁèàãlÆ(|œÃ˜Ÿjí6y¼({†5¼t ˜cJ#kÑYˆžVÃïNz^ò®‰kÇ­m»NGZÅÞˆävVMAY4ŽBX¶'BnGÕæeÔNW¾…ÀÉ›j Á˾͹e-#äöYMá§Ž†nêj|©ZÇðõé]¬Àa]Ц⿌“pdq+?­ƒÀPÃîè(cm2Æ…›ú€§¶°À9)Ú±EÀ,M·»Gð<ï㦠0ØQ°˜—™Ç±ð¥›0u²_†õʼšJüXGj<+§ø:Rñ 1ºWvÆ„€?;š?b–¦¾w.§ér‚D„`¾_S%ev¸¾ÁbÙQ<ï Ê\‰Є0òw ÔH1QgóMˆãÑ‘$ør#bàU&šCàÅèî¯MÈà,€7"~Æ‹Ñ]6$ø–‰F/s‘‰æhê«Lt…üâF\ÐÜ—™h<æÅˆ×üâFô™h\f¢ÁH\öðIÏå,hòž /è¹<ð=—ßCOäé—Ƚ÷ë:x(\ü—¼¾4bpÌöÿœð2˜M}0›„—ÁlêƒÙ$D¹\Ǩ‚QÇ”ÿåâ€ÿÏ?Â7>KÝF-ku‹)ž4Lôºa"ÀÐP}X/ˆ/‹Ρg|â>«è™Š"Y ¯Ãö†FôrNÐË„§í ‘ £‘MÓñŠCàû‚gÝMýþƳÎ!ðq'<ëxųހW<ëö¡6Â1Ï:^ñ¬÷xôò<ëh#œp˜»©ïß8ÌðqóæxÀaÎ0‡¹^qÁ»©߸à{wt©khí™úcËDÚ°äÔŸÿ b9DmË–7j£Ž¬€’åKÞ¥ƒ+;z¾öÚ¼þg™G<^d@ ¡±Â0esåèÎ<štd[¥)ªFTæG+¢_‡@©€ìÜ:¦ƒì‹Rм‹!p#Àö=ÞéœiQ@é2éÏ&ÀÎVq]¥Ã´µôa§ç `Cèx§|DÈ;â²dÀ9O—”'è)ï\9÷„ÍbŽÒ8î2€êŽ& ÜÕ='5B,œhÖ¨™âQÝ#è;ºŽì•D=s$êºÃr™\¶E¾¶Júµw{¥¹UÖa.„DÈvd›šû‚Z>-©®Ye…àwÿãæ[ª7jé•?çÿ »²mYUúK«Tª¬Çý~Ïû|¶Ø÷Ê8_Ai×zžK ”’™™¯EêæâK>åe"~fƒ¾õ£ÝkÑbñ}Pát }šGëBÕñ8‘‹zšæYvoÌÒÓê9G%ØN3)…=¤ oñ3}ƒÌtóϺ¦ë¼°%m2Ðíã=õ¿—ŽÛÏ⇢m¾ëíbÀ»Ö¡ ¿Ñ¶^›¯¼w÷þ‘"»©ZÏ1Ëzã}KÞÇʧª0ª[¾Me¬JÂ52´bÀ‰R{ÜÆzZê(JðŒ¾P`Xi%$´/â¨Ô´/efŒpoœëß¹n§iÞThtß÷JA‡]ï¾h§>ߊœG!]f³š¼†m>®fsOÏB gÝsy{:Ìæ Û?¥úÞÚ|œ¬aÚVó¬áç$dq²†œeHœÖs„}ŒÅnê~J;††þ@kxœ÷ÒŽ´·ÖðƒÍ&°†“8Ѳ†1ü"õ„Ýp-ƒ5\Ÿ³ÙÜ-\¾#c¶,}Œ~$0›I¢L‡4q‰ð^芠4|ŸÎN׬ª’­kæóò‘1ÌŒ1LÄ5"FÈÀjxÀã¯O9S=W5òÖlV²³!ß©‚™•”Š×~©˜MmÞÅšös1›JŸ[¬R/Ìæ4à³™}S ñ&ç¼æ[Œž‰ÍffÌfßÒHJîmWH•$¾Ó)yK{´-<àcfJ‹@ KaeÇŠ"äÑ*ë¯êß[ìšôC%\ªšh•€ÙÜÅÖw‰—µ¬–Všz¢˜8u°öb_Œ[÷fó0q*„½KÓ-Q£·©Ì¦x›¦M1Y%®H….*dhL\ªÕÖçm.».ŸRŒ´zçrö¥O¶­oYžhå­ÙÜõìqÚtfu%L΂ÖšMEœfsŽÆ"¢!½‡>AzåÃßúøÔ'Ÿú•øÐ'HsHøÜ'hëðí¦ k ù>Ä,3.¾dôܤޮ‚@E“9ºÂ1¥)–¥åºg_º#]q7©Oæí&õb ¢ ¦ýøK©C‘ä{¡ k ügà×M¿íÑòèž}wôÛòå¦ßR4¸ŠYú†ì”M”5^JÅØG]œA¼ªÕ†èýóL´Òúh å¨Ðo!ð¡B_Sà@©[¹­•€RöÝÙwoÐðÄ9”ª7q±·U1ÖœC(¼]â»Fš‡ Þ.qÈa£‡TÀqHí¶½‡Ô[öý›8¤YÇßÄ!uàçý,É“ ý ‰‡~‡ÄÀ£,Ùæ½—0íæzYõú›„­<ÅËιðs¦o5‡’.NتSï7’†“_nº—^•£DÑ$E@ªï°ýVœK’¼×Ì$Ðfâ`Ì…o±}£Uâcëh^¶ D`K™à¨ÅQ«yØfâßÿN@±#^@àµÄ^)•.—x†ÀI2i¶ì0Q®åŽÛfbýïÏî'«ý¡dCDñŸhÁ4 66Ç’ðk¦&žMbçY(˜4–o<2 :ßa$ßa”" wÓ>"Mš„rSc Z\‚Ä¡]ì« dèu!ùÂg„š:§“¶KÝ•vh{j˨|œm¨Xå4ßΖèa~dÉ«^wQ€ø¿Vn±@Ö¶}¡†¶Rý’u‰ŽYËIfA6ôàËV©ƒ‘ i7ªýVðùAU@Er(QªÛ#IÎ[¨"uû{Ií¡}^ɽöݪH*`¿Gõ …UÙòÜðƒ>àH:¯ã~¾ê@öÇ»H“è-âŸ||ÿDÿäã;ø'ŒmˆbÕÛOüDü«Þ~Õ‚Aü¨Þ~¢nf4ž­%ýÀª´¿(»Á(e¥9’>gn¢Þ®‰Ø®3Ûµ…@ÿº]ÅA;eÑhJà¦ò_d›»)ËqóŸ Ü'–ªñdÞ÷¶ ©|Öã…Xçu†Àð.ù“Ð&™óD‚øòv2I± v4 @¾üÆl[ìA¯ÚTlÄ Ü ðôJ¿ÉÕÚKPqƒˆ!ðmmx¬|€Dx ï3ë÷Y©O©f–Â9«ót4ï _~ã*~cA Ü°B@4kÕ'O‡µë <ÏzOõK]ãˆiFæÇœÃ7ÀžF‹&eÞ $ ŠhÛˆ4cà¶Ý½Ûu¬ë²1yâ°ê­$µƒ+pÀí¼9âÊ´éʾ¶Û5tqóqÄ5#:ޏFJSÇè8âÚaèó ƒ›#.¥ :âÂË»Gœ8m–ß®&WÖKùåÈ›ÞUÖùø|ûZ8Ù¼LÖö<¤²Sè@¡ä³ú8Œí<ç—5£3!ð}ï.Â/TR ø¹÷ ±æ…Àð6û[5“ sÆÖL¦‰Å7f¬s¾€¥/QbÎwN®0}è‰Á½ÙKiJ5«ÞŠ9ßÌ:¥™ñ†˜óŸ½b.U±mzYjÂ×ÉÇÕ¡©ú,k÷u4|]NWí¥lt^„¾ ¸ÕýpuRLô OÑ ¤#™ö í\PÃT meÍ?ÿwsvUEÛ–Vk‰†þ¸€k¥zð(`h{YÈÀÂÑ•…6m:mšm¾@0G^î÷ÌÙëjÊ*j5Á)|]‚9Ù1íý‘˪å³5òumš%ƒ9²i^É—wCæe#"󆞃Ì+UK ™7ôd^ „dÞÐs‘yوȼ¡ç óÊ'B2oè9ȼˆÈ¼¡ç óî@@æ =™W8¥ˆÌz2¯ÔF„dÞÐwy¥$󆾋ÌËFDæ }™W>’yCßAæ•¿’yCßAæÝptCßAæÝ×ñ¼!ó@Kæ }™W5™7ôOÊïç¢í„ÁU³PÁ3^%‰xÛ xÊÑá8±Áæ¢é!ð–{/>Šjnt¡iHÐÝÇòˆ©0t0C‚î>²ðè¸û ÒÁ ɳ¦ñhB  Ôü—¬^¸ (âDÚˆ|+‡1Ö®ÕÂÖry:”ÃF¤hµ°­ä¡¢«·Ã&¼aÕïGOÚˆªõC#L_ÕF\%8ÅÇ1c³àïó‡«$Å‘6bø¾”Ö ÒF ßçWïB ÚˆáûA1çÕ S“!ÐYC:˜òÍ kSjáÑð µ%Ã##¿³ªêÒ\eP­¨øT…{•YUkŸÎˆÚ©ë½xb>§ëC W\o(y~¯æZÉÃðs÷jrõj€’aø¹{5¹zâøÁÛPGÅ¡äaø±6å_d °ÈŠ&š!Эh/áçmÄ3Ò¡˜¤#›G„Dms­Ã”Îë¤Û´j$ñÊ•‘,«¦LGáBè÷ +™”.ìž8ÈÇIr¨f];žëÒJ\&) ê>h¦—¨©–oFF" O—´4׎{>´­°T-ÝÇ[N¦PUQÎô•*ìàP±íuufZª*ñ ¦ZSH‚^’¶CÈÆ<ˆ!˜wt›ð¬={ÌZ3Á³|íh”hU‘À¦…;T¹ðZÅ1_Ñ´_F¾ZG1þà%»!=ˆdú™m6uEU!¤¬â¡„ °‘Vº´ÓVóU¤„ßs’*=´Šw g«.ò‡í4|7.Œ¥¬Çq¯fþýAU¶ˆä9 ÓZéX-Ô‘ÿ³Wç:1ÉF0©Î ~_(Ä u’Uˆ¡\øN~ž п†¼ò®îè8™ˆà×C´&š&ŠT%®œñÈbÖoèA1÷㌖:ª‹qÑÑ_ 8¿óŸ-½>ÎõXO)«0cW‡cYÇ)™¸>H€àüîÅ2 "‡×SÚôKÍð x+Ši)¼Ã­duº ¡Aëi‰ßd&Ní¼•:äB+°Ëþ†(o¿Ws!Y¾±Ó‚ÿ\‘]hV\/ÓƒÙ„¦¾oÖ~Lðà/Ï"ÁËY“º]NÏôµô•­TêiĶh9Íü¥‚ójé㢔utåxÕZÓ{®:–‘Åcu<5B¾ï[îÒÍ´Ü ¾þMË]•ZžÇ8´Ç:\¥#sΗDÏ'@'ÝyÔÙÑ5™gUµiÁ¦¯‘_„©l¦]"àäŽ4œg™®öø’‹eɵ«/¾s)!È¡d:{‘çå`‚À_ru(õ-cÚè´j²÷×úÛ7ÀY$莪¬ß¸âʯyæ_«è|ÕBIyÔ+àû2kƓ˓­|ë ÐsüÆ,]tÍ:[Öƒ[ApÊÅéÝNH˜´®q‘ïøûFrò§¡k±Žêù~žN‘Xœ"#:g-€z2áõ‰à+ײ‡@ï^¦*m–uÓïú{wÁ9RƒmUÙÄÉ÷{óÍЙ8;;Äof§ŠW*;Ôúzüý^¿Ç{s²b2 üJ†EüFÆhF 0ùµ×ÿ©Ö**(0k"þ ð´¹TÚMl.ÆÔæ"??7“±Ž€x×]“ º‘ŸŸ›Íuåæ´€±Mn¼^‹N_OŸY*~cª€žCÀCJ«È˜û¨‡öO„#­ËÚg%y´(Eò ±^zœÆØälÍÊV‰õ’ŸÑ6¨l‚§œ÷$)—²m"ôA'àêÄŠ®–œ)öù9'5™PüÆ8ç“.†!¶u€ò UÓ\1t_ kÖMøÖI ,>É¥XƸËu7b[¬Ô©}Ø=6 £Á"]TDlë€Ê/yDÅ~·<{V± Íú ôJúN~á[šT\¿ÂëñQdÆRôk¯šDØàbÄ­W7l#?ׇÝ\Q4×3…@ï<43C×5ºL³¸Ô™ßhM³ ÃêàŠ:ÏÛ²ÕËó¹ìk;™qLi’B þ,7G\j‡þ8ŒÔ,Ã#V€ÜôÜ3qÆ)/Ó„jàiÞ/`ÇÐ≠Zrk¢+Îë´ cË´nRÏ8§Í л^xÙćœŠ ïþõÂ+€Óo|CÀ@Ó®e…öQÛ!kØ«ªÔ¥žo€òß×àü0µ´¯ÇQQ z†×Óý‰K';rO^/XW±¸Çæø½Î;°E þs½I d+LÀ¢n’J=ß §n)0Òчi©g®ˆ(ˌɛÍ2ÌRósƒ@OgÞÀÀLã>ÅOô­/žª"®–s1äºæHƒk&áŠSF'¦†f¢ö^K#k4£ïizz»Íè[škÑÐ74½¯bizÄ{¢¡šž¾Ý$Oó_¿<1¸éŽfs‘_èŽæ7’_èŽæë!¿Ð10¸¯—tG$®}mèŽ ø¾ß\€î¨€1ÚÐ0t“eÙ{?‘e…ËÕ”èp¹YVý{Geð,kÞõû,»$™pr!ð}mÐ+<Ø —X-øËÅpƒ zÐ;•P¡ÅœRáÃéÏ 'ç£Xg’æi-ñ¶Y Þ=°z-¾O¼ð¹–15Öìëh,´NV@ÛÝu÷õöåÙ¤‹Ô˜Yû?¿tÒA_(È~ÛÝVN@w§ª—²ß7öÁ@r'"ÜÂV4ÄÇçõ¡`~”׎y$üGŽ€Ÿ; p…/ÀÐÝÛFG4€ » í: ¹:S3^ó »Anù òåNk éÿ’ç} éqýEú¿¤Ç‡Ýéña™ ð!=އv¥Ç‡:]ð!=ŽŸøÇÀ‡ô¸>äü_Óã'äCzþ”?=ó!=~zæCzü„¼IË£¤Ç5òíŽjC‰tð¯qCžè(ÐÁ¿â'ºâ†,çzb`¯îZÞ~˜:&}l€êìKÑÄ£‰úĺE¼¥®‡@À§ÉLCè®äMœu+úHø2;”uæeæÉ¸©”€Oι,ÕT¨älÊË6a-z¨Êþ°V¡¡÷]«¤®v!q)ÿÃÚ)ªãRg½|ÐBùï?êÑ–C9M±^É·ãž&CµíÊy[B wçsJñž*¾.­®@ñeèÖ´8;§­ŒÀÎJ€Öç;P;L¼èu´¸í±šÓÎÆÚî–‡s³<ŸË¬áoä3_ зz¨ú›§¦jÆ&ý¶CtmØs&Êú,[Ú3ë5`7m×òUê&lÛÖlÓ!]? ŽçA«¯Á²Ì²¹„`r€EnõŽsµ~,—±ëf𥽇!KÛ‚/š‡qÑ×E{òÖK Á·æP#mça6/{IktëŠ9Û¤$YÑŒU£\QƒšáêÖö{]äÔîû4íè’@3Üv\u{!&¡Ó¢Ç‘Ç6Àî7ksÍY­ú=ø#2¤~‚­÷¾’ëX>„¼Ošá¹?¬Þ{µ‘˺Ìï¨ĉ͢Æì½ä™Ìö¦Eoh†»R8Õ-ëí”9¾û (»Ê|MÓ¸¬è yÍps’ÈJgy©Vï4ŸØˆHûŽþ: v§›½³Q]ŠúúÏAê—d5[XZj Ý òI=T¤,Û­@¿Ój†{Ò(rHóM¢OÒj†²pì•z›“ÔF˜|BÒ^S“s:pŽúRdÕwtF¼ù*ÝYæ¾,¢SÞÛk†¤+ÔuâÕ*Eä+$8ÅòºÒ Ÿ ŠZ>rÖOú½WVR_2]?,cÊiãùÿÓoÓÌ’|¨&|Íø'(«»q½ª¹T¿³,¼Å'ƒF¦Æ|—ݳ©Ål‹}›F3|ý³ù3ÓCÝ0v &ã Á^”îld-hSo,_ñÝCÒÂ*ÿûZìièýÀ jÞp݉ZlÀº“×ÏM݉Y‹º“×ÏM݉WŽº“×Ï]qœAÝÉ Ô“}­œ`ýìü^XÂú×ã¦~ÇÜÔ_ͦ ~çì^à,Ó€eÈWîxÛî'ðñãGŸ_®§Š—åPrgeâÉ:v'×[³±†Q·†€›ÁÍÓˆŒÖrs Áè°Q)½Ð>íðEÁ |.+×.‚e®øDÇÇn ª†]:•>äE¾Ì ËÐ-ú–å}Arʬ/R¾NñS×u{Õ<,‡à€†ßØSºL½¯zÏ-³Äñƒ©~šœ Ôà?W]r£b†qAäãšœzE¢r ÁÍ[ƒx²Wd>"2>™8Rf_w^vt-â2=™\’“Çwª]ž$§¼EKTö¥D}Ã.ÝGÁJ÷DtžhÞg"ß'Ò^³žt%V‰Hø¡APõ}µ¢~d‚´«!uAõŸèÙíBÐ&"T®¨v£t¬:Ù5¨åíBÐ-†lÚ‰ê!Tì¦-ê!QÚ›$‘Ú¦K0SÚà»?Y9’t£ÚÊ!2 ¦,þ¢^ú¼”ã–ç-" r^öÖi5iïÇŽù¯9adÌÏ£²ªÙ呂ü¬³dÉÍÚ®ÎÕÜúrJýßg#żtÁ!*É×¶…` Rs;ÂL¼Û%Ò”C0AMm…cº» –‹~ƒà3ìø|VͧuSÑŠ‚ Ì*Õ–î¡ÒhÀš„€¢,ìâWÚÄqX'+Õ:n•\-¬öY æNVfô·Jˆ{ß7ÙR@ðwv¬¢¬Ü‹¡ÿ9v¥“XW¤Ý}ê îJÍn¯,<™ª]ñåI:aWý¼›Ô~֌ҭ]ÙÈ}ZeèèpWj‡×Âì™l§&c "Ã`”fÌÔ¨ ¡^t/>¨ò»R7A»…ß§n/»ÊŸô½ÞçÁ¨pÉ ŠdÝÞÈ u8饥­ášÊºË?ûšõÙÝɸŒÙ¨}¢Ñ5£ŸÃ÷É;ƒ55í§)•;zöè&Ô7M|ò±þ×çÆìE:³¦ tu/Ì^†&s± ÐÕ½2{Ù7ÂCõ4¼T#^Þ›áE}hhx9‰Û:—3“F4ëywaî‹|ã¢]Ý5‚·Ü\©ýz½#¼Öщý&ª®Ø¶íªþ‚ñ-8ÎFyÆõÏܺi;µToÑ­QsºÚ XÍPƒ?×yGg£¼š°S`†À4«³‘ÐFÒ¼\šÿ5L ^ “ü“Ÿÿ&Þ ³öÏF´…¥êãN!ˆ¶ëöD¢é<®‹hRü­òÓý‘MkÓøˆÜ太 ¹,'òaK»ÌNÔ‡,GZ©/f¨É]†¦SþòZÌÕ®®ŽÈ‘>þP¨­Ù™|~ÏÍy*ùÃä æ’O&OS„‡(Ä5ˆ¯xSÖ/©Î…àMYÿ7H G¸5“…zjÿŒÉk0üÆÈêÔÉ_EiS°©†óùP=ÊÁ— ÷xqàíS»~¿>õ$·®¹¥Ï;¢Åg W™N) Uz@´™ª+–¥ºªÏ«€¢ÅÿZ±—ÒŸ²dtÞöÁÍŸø|SøAUl”É­„ T\q²Y:7nÄà³c?¶ ^%zçc+kß< ðe5Ë/U¯æ¼6m*Ê!ÁLh;ÙÚ—©ðI"‚…}l ‘‰-Še¯ÊÍé%'‚=í3æbH’‹‘s:ûåçkycµsÍ$¡vU:A0ìiVº§Vý¶ãbÉwlòËiê¡Ì$1T™VØ©ÐÃg„ôù¶ã¶f;õù¶°¼ùŸxMÙ™D5´ |Å7’WwVÊ:±»r‡à'¬1ôé”.Y¶Î]>xðõ%†eWÑ›ZÔKWøêÀÏë1«r#dß2¹¨mõÁøÙtްúÖ›jdž|ú( MT`ÊQõ3ºú|<ƒnçm&›qêݺ ‚0ÝÄ…‡Á×+ÜÕ+äjG»jÙL®¯7iç‚.KÙ¶¾”ïsøœD—Ô~‰.A^,º´«G¢K@‹.)‰.}Þ7¢Kj@¢KŸ÷è’‘èÒç}#ºdt€èÒçä°ÌZß,÷½˜ö= ¢"Ÿ/%÷¶õèC×&„O h0šPO …&PîÅB{%¡ÐʽgSµ'ñR…ä̆ „ÌÔ9ðRÓÈlnî©ÉOt«ÇY_€ÑCéºNc¯Œ‘'Šl½ã@Xüã@rÝà­z3­oðçWѼMW6cÀQGÉUîµ»b:5KW&ä¾N‚:8òø®®‡Ã”¯+Â2PçÀë:8êàxQg;…ÎÞr ¹Òp¿ÔÁ‘ù¥ã®zÐÍ _7O¥zxxjrõÔÌÊðÔªyŽ+F¿Ñߺַö¿ì>þþ9-4;17¿ÐùˆA|W@Çq‰ÿ³€nƒàotèÖÏ«€»Õ…ò‘6 z…í{xL~ËÂÞ¯lJ€àäUvµùsü’CÚÜÇî€êcˆ9ÙóUQÍ»ÐàGHî võ7£S¸"§Ïràó ìêoð­hŠÆ*ûüùµc9ѽðo|!M¤\Ýñ!yþÜò©ÒLJ‚—LJjWŸ-Ò:Ð=L831»Ãw¹”|Üž¸ñŠÒ-œ¸­K“A` zLlˆNç“ßø<#,º†À™oéŒ@tEæ@µýز¬çŒ!hř̭…Úª4|z0Ë(*µ /÷¶†`âå:Ì­]¿Z[ë‡$´çýêÖ|ØXîUÈ!8ù¼ÒàÁwP Ña6QZ :ŒbÙÑÃ|BM¼µºfF]Ö¬oðLÚ: M¶T`ªxR7PYô¬E$”ñoQ‘M™­9j¡G|™eUVY-ü€ÿÉþþÚ»³pͶÒIz2A>Tîó]øÄ O’#}ÂWžÓ@çºOSü;]´ÿŠySQ¦uûåãíI{¾âzp;÷“t5#žüÀ±×{ÎS£ëÊ*}_·ñþþÏ’ÌœÕþ«“Uóä‘>=ATy[LèEP•-m\Nõ¹6Ÿ'1 ß óã´Švj›µ|ô¼úzÕº|[WþöŒ¿?óð U÷yüŒn¾^©  Ÿy&²Fʽ§©EW¼ûÌGõ™÷Lî¾Þ1§‚äîëÝNà ~½>æ.÷a•Y…šçî3gê3GO}û™¯´iQƒÿò™KLþ?a×¶,)Ë,_©—Ýíárßÿ+b¾GðŒ ¨à˜§ß  U¶öL¬‹¹È@Š¢2Móc¢Íg¸'ý4¿Z2ôš?;¡/Eµä-CÈ×ýäU¨3ý4ß'ï–²Ù&¯¸ÍðЂ-=…@ÊTŸØúI $¨,ªJ{Ýj¤e7‹ÿö£´¨ðBÆHnNõ"³"d—Žcú´´›Wü­?®—ަKÇNó¥#ÓK‡BH4Ímük¦yÓ‚iþüœæÇ׋¦Ð/ v?[GÉØ2œ)Cv)™×ë¤9è;I¹^ÛA$B-l/«©ªa“4¤¸Oóí€`_rN‡IIRy ˆÒñ&ݧý” “¯.xÁâF§©eŒ˜êòýÚêÖÝNìYvé8ÔU! pß©Ì;ºúýŽÍÖ ½ã­ñíšS!Újä‚!`tç› Š~L|}¹¨¤á+ü•”Cà*)E@·åÿÏŽŒc¦z6¤dl£“%¨÷"Ó«ª*ò#'û:ÛD–®Ø–2Ʀt¥+ƒÀçqƒ[º{µ 8­YÍ!ðn5Pyõ™è¨+pâÑ~r3V Õe¨Å©Lï.K±ìÛ(nüu¶ì1óDSŒ}}jêù7f¾òqY˜S„vÀm‹)OùˆBþðÈ|W2t6Ã4bäÏ5Ro¡Ói?Üv·sÌ(VJÇtz|ªe­6µ³•N\a[Œ¬• T Wz>”M Ï;’Æ×V;à^Fbש­+Ûr.kÝ&‡À÷µ¶Ç<ȱ. pçF™Qtµ@­>K6õ Fh-1 PТ 0Þ˹·85u¬¦ gd˜\êzè­QŸ–ðç´nm­›é(J^"äÏ^PjÉ:›’»ÊÙÌÅŒÆÆ ·eb”…»Yåó:Óýgcë«_/Ï©*•Êö>9 qööQ©A¨¹…kHÿþùk]`·a¬®­ôï ÚwýþùVÐ>Wk·B` 4jOš£9+Z?sÞ?˜{¾+Ó(5NKNT_Aàëp±)\íƒùÊ묢µx_Ð>ú ×û C\Ö©S§ì€6Nýûëd&·cÔqM.{_Õ°m¿#¤ £¿¶v©S´s@PáX9I9£2½ªLÿAà+3ÚRHž–#Ñ;"_›õÐ@Núi­$¾A=bekéM‹ )…BïÞ¥®A§›=¢ª¨;ª¦ŽB`| l4pÁÀ=£Qªÿïð°ª-í*@õ÷£ÿ§œÖŠGþS·^0f¼@Ò<2HGš3H¶¤yÊò æÛ˜ÁÖvf£“Ï÷¼?¨ù~пHc=,hx 5ߥÍ/RSYòaFHÈ7ueÿºMNSû§u«´xÔlEÇê©ÆO½~bæ ¼JuÀ?Ls‡?õê'Öîó0JQcNô­?®£Fòå„üñ pVºØª‘”PªßÏŸª561®Ò^±Eô)9"ë±T[YUã•‹F !_WH5mÈ!ßÈ·i‹?ÿÕvÚDÓ7îšû¸³E0ÞÊ#£ËKêqLKj ¤Q„/kåk<ßODIKË=—=*ÓkQá'0¸e°ž‚æôTo<œy¦t$÷º/ä{ y ›B> ç_·zÍÐ;¾!Ïù¸ë¥³'â…@íÿÏÿ ›}’Rû0€©6o I9튣Ål£€ÿ¸á)¶²Ë0ðÖVüHQ¿£/¶â0EýŽîmÅQŠúÝ¥¨‰@)êwüÍ}¤¨ì=6CȺV/X+Ù·QxjϪ޷©¹põôW¡¶EQTÕKŸêMO@ º…uÞŠ² ÷4“ðñaêîÖTÊ&Ÿý-l=„Ö)«æÊ[·9 d Õ^ä‘Ѳ!ðu ”BO0 |cïZ\ç´–ÎeÉCHòj<›ÅJœºF7yÅ|!üùnqÐyâÊ¡¸å\ ƒ!†Z¼³8ÐÎJ!ðÖâ@w&¾ïBÏjþÑGluŽÖ63/±a€™Ó¹j¬[.Sâ6Ð$]·éꌰӓC`ph!uxµîI×ð‰ù(ûyºÔKøÐ¾0°ÙFFÛtÙ¿ž'â£Gù”³éÃs(Â'â£X mÑGY4båü%Ín<ªiéщ1°qÛö¨²¥E-&ŸY„íÑyߦ¸Ã¹¿džÖÎåÄ#€Ò” XÈ$‡ldY¦*„ .‘åÊôoÃH sUï2NÞ8³lZòu\¥n³EÈ£¾¼(\qP±2ƒ¤Ô©ä{$(0÷ñgËSÁuÐà§C©«Úz=~ÑrŸ_#¥¹cÀm&ûÑ?wÕí9d¼s4êÁãÈ·µ­F7‰\گ劆ݩ‡ofTþ®‘úð4êÃ5BHÝÊMÕb,—”úÄ^’®'aªZ J#ñT €xná4f42m8+Üæ{O)ä^dF!l©×¨óÈ#¢ö%º— 1+žŸžnï¿þþڵéµeDf²^%BÆ»¤ˆËÚo~ä+?!“Ý®pKåÖn©ŽyY¿ÌìZzå–~Ø{æ2Ý’b+Bþés¼¶„h~²¹vR!x©­]0_¯9K§qXðÓŸé‚tÝh©Ä#­ë }uOtf'ÄõpB=W,üð²õA‰$µ"4óÁoˆÕš eÊj…rÖe]ÖT3H„Ù{‹ºÉ,•øÄ¼mk¨T3ʸ*¾o{[¸a‚6îñ‘Æ^ÿûkÏP¥íJ¡ôé^ ôŽVõÄ+¯„L+2ÙŸ"¸³K ‡6Iá…ù‰¯¼æÐ&)„æ''E5Ch,‚\¶¶² ýMŽþõæ'­"miB¨²¥¨?Lnmi8´¥qÀK[šÚÒ8à% C[|_wp› £Ç­Û ‡n3ato“Ä¡ÛLx¥f€»ÛLÔì?Üá$zܺÍD8‰„ðèÃ*Œ~¾}f ÀÿJü˜Ý*¼R³_ønB5ûS½9‡Ž8á…š½wÄáÐ'Œž·Ž8+tÄqÀ»‘9qðu<qð’ÿ@¡#ކ7~Xb…ÑëÖ¹@ *Pô¾µÄâÐ+Œî©@+´Ä £÷­%‡–Xaôþ6 (º§Qh‰Fï‹÷X)v©0 ¿,R@P-ŒîK´ ­a`> Šâ/•®œ—1·À·¨Oòí^P}Ô ×GYÚHÆÅçw€Øó%!yÜgaòaÁ\9]‚’¦"÷~ ¸ß$m9Òíp°ŽkÚÓƒ-·3}˜Lµ*jx¼53u‹¥b?0F‡–Û¹¨f£ðÎøÃÁ{éÈr1æèWo!Úú¸Ú‹ÁgÄ£T—¸Rí'Õ+¥OòNþ6D2¿ÿùcΪíÚε×ô ãáu/Å I§²OלOå [:&»%å>-é_ a}Xô;æ´ªöÚÙøH7ØÔ¤–ØNÔr"²&­_ìãÏÅÞ•I*ŽÆñïÓ!Ã8‹ýÉF êð8¸µ€áÐ&Œƒ[ -`ÂCÁøÃ†C ˜0n-`8´€ ãç—…VÙÇÏ[ -`ÂøëöqXÀ„ñóÖF  v z¶€áÐ&D𡨆C ˜h†ž-`8´€ ã72Tû´÷ù¨ðùûÇì6j›+¡>/íß}~(|^Û¿+ôè{ûwB%¾¯ó¶SG7œJ„œÊ8ºáT äTÆÑ §rKNeÝp* Y§2¾uÙ#q*ãp*QŒ« IÕqüåWCRuùÕTÇ7¤ê HÕq|Cª6TIãÆñ ©ZQŒÇËžGHw“/Ë ãä†5l[<èîÉãk?t÷äq‘ $~'?-úGCÖpÜp†ì~„…Éó†!n€!žÜ9¥Úî9ÂÂäy÷ÛÇÁOîœRí~„…É­Sêö…aar딺}áCCàûӈܥjI 0¼°6¯Ç4çzÙó?æØg®ºG©½{Â_ ßQ韗7eH ˆ^ª¢Š€ôã,]…Zݵóà…Ã$>Õ‘Ø0œ4¢_3¾ö©4“ø¤ ä³vºEÂ2^øš7 €wÔã¸GÓ®£ÝPCà #6ÎAGú5f„.ñn€t§½ã‘ø¶‰Z«NÈRZšA TVqÞŒ´^²t@Ê*fgßÒŸ}U}) zt‚Î3®zF¦¤Ë;Ÿ,HÎ2¹¯äh¹Ô/[ñ=û4•sþÐ=YÐeìfÔ“'‹‡Æ–w´^§Iááv…yÿ¹›Q[y †zMÅòu© Ù•Mšö¨3‘ÅÃÆ.¥ž¬ _S'i…ð˜˜X)§#£C‡ªrþKFº²,»ÕS‚èkºÉBzŸlçqa*GH[ùû»8Æ‹žpóï·³=úœ(Ü¢ª†P½Õ3BËŠj¯¾-h‘u#zÇð~ã¡èÑÑ¡QVº]³¹¤Œä¹‚ÀøÜÎû°šsü²î»ó¾ïð/ë>aùsè£Õv£^ÐNG„  ô´Ís¦¨LEêr~ùDH§Œ©„`9q5 ùú\£ôÅÌ‚ReÑã}#ö`€@ì!z¼oÄ ˆ=DðFìÁØCô€W­çS(öˆÑ—C:H9FèFØÃý/ì=¢aí|{DèFØc;Í©ÛèY¡°Gôˆo„=l?îÂx!ìaSeÓñŽÇÉÄl7Û¹Ö.}Ï:¶å§Brsnš´âÃ~vÀC¥z?\6͘v“œ}‹@éòt¤Ö&tÙ[J—øûº/»òxÇCLñêLõ˜B`pqî¹Þmöptˆ)^´8ë#õL ð(ì,wnẈv,…~žXãeÛuÂïï‡þà©ûzèóvfû¯†Õ²³_†¹n™$N¯9úƒæczCG?á×bèuô«ÙOø-µýCreïžè_Zj¨ÅoZj‘ª)ÙUMG¶°Ö?:>]èùS«“ZÓžÍ3C@dwí4ÀÉ–¼‘•€ÀçÉJÚ–ËZÏVÂ!úJ¸pj+—!,oV¼©‚Që8®xS“ÊÊ‹Ê;`äÙ[øã,-è²²VRþü€ûÎ è¸(3º¶²É 08€žÇ™àK:¥‚@àó¸œØÊ‡7ëÔf­iº Ž9÷×ÖÚšûnfu¦÷aïãÃßN*"ô’R-jq÷wM÷š4P ûÌN°Ý£ý€Zzw ³aæ]Ï«¢Zc$}”»×<ŠÅðCsÜ|‘þüÏ…)6»¤ÔHÖRJÔ¢µøsHW<Æõ/^Š¥p2»ùs },iEÒÅ\; $ÒÜå«Ô˜áX¬QðÀù&Åew¦ëÚÑkÝFÁãDJ+wùܶbd-:ÀÑך¤™ƒl&z9“µø‚Eò®7¥ìI¯züh›ð<Ýn¥„´¥RèÑv6l?¦r_Z‘%™ø@Ð¯Ž€½•êÕ7ÕûÒì?Éàq ·~´›_æÛµó˧Ëpî\m)6áÝJ»uu~±¾ÃÀÍÇÖoRúØI¤‹_ƒ´àGÎ ðà\µó7åzTŽÃD!ðyÿhê_2øÇ£—ïÝ”¯<G =#(uy²çÐó7R—Ÿšoz±¢Î«6 ^gW¤ÊQ|õò,Ûfhü£ßhésöI–â;ñ”BA`ph@ìÕjé†n©ÿÕ!š]ÀÑì"ލ­hªOÚÎí- •oâNiW@`Ѹ èG§]•èß_€ CPÃéîo(:šòÔ± ¢Còä—ÀxOŽ•ÞZ±ª2#ècŸxY ³`LJÖ•å„;üñ‰zÜå¢MPSz©výðAÇ?5Åm_¨‡~ _ŽØcUtŒò©DÈ×’‘oÏݰû±í$*5Pø=- æ×Ê+X¹DÖèÉÛª¹ÍEß ñ/‚–¶[R7býZ–’â÷Lî‘+BpÃó|öQuiK¹ó2ñÈŸ{e‰ý·Gÿ’ÇãøEχ²‡*¨~ôßàBÁE¯þÑ1šãÛÆè$üæµȸoc1R–0ÀÚE¨óʆ\ ~Z$(ar!¥S쩦T=”o°¢øÊºLqÔ"òõ±1Æl„Pø‚’ÿ;y–|ÍQ3|»¼>2À‰Â¬Ö{‡CûÐßÿœ´Z½9 :Žíö%09qm‡cÝ?s'g^ëÈJ@`|“2‘’ É]&D1…€.Kv…ôÚ2ù󩚨.2ݤoóùI¯ó¹åJ΋è00¸ö²ø‚‹.Ÿ[Ö]^Ñ©ß?´'¬Î@=_ÏÀkÕÄͪÐÍÐë~í)Ì&v4pÌSÉ00º0زՒº;Õè‰Å,AªÞnYÊò…ûóñ38½mƒ^ú–¬/ô ƒ“y±ñëéø<·íšÍø¼4ö©”šk‰€/´ÙK d=+û=ú€[yšr%ô!’Úû^"`ô©gA ™›Ð±BÀÚ!Û\¬q•n»T5%&h‡ 0K•lQ‡?€¯ó—´¦mÓwÓâ‘?IìÃ5rá%ÁÈàs¸É¸¤Šëó¹ÿ=ÏûáVEG© žÏûá^W=Ü…„ÀÓp[þ>•ê2É ðz¸ËžÉfE-^÷ÈU×ᯇ[›¡FÀËá¦F<™T¨{®‡›èá–ûp?èá–ûp?¿ ·ÒÃM÷á~~ne†›bäÿÙHŸñƒÿ=_')h;¦VrW‘@*–Vúzí褨{°•ͺ«ò|ÆÀà ¨§á­»hÖ]ÆF峈Ï÷Ǻ»u¤FNÀ÷u> T€;ൔþùãìcÔçûΙn¤Ð™.:t„OÎtD­Ð™.:Â×ÅCûDŒnЇFIañPäqñÐÿv˲âJý¥S¾yŸˆîONX°ŠûõOžLJԚÔΕ*”ÌCÀ‡®èÝZÑÞ »µ\9àè_¸µ ÃÜ»µ¢G|áÖRBàÖ²ÂçUc¼[Ë n-%n-+|C…zëHäĔڸÀ#Á4:}¬eJG šÙ/”Ì­¯hh(ꊢXx …gH <)\Ä´¸ÀÛ#YÿX&§ê ·¶öœÌèÖ&3}Ó©½&|©ÿ#cé>3(4­Þÿ3;dyoH5É»—Pè9BÄ ÕlÊ<[z(Œñ©_mÏØ¬;¡0h=‹2SWlºlYÑÿ @ø¤r§iV£ÖÜP ]þÞɲÊå3VÞ¯”»ß~> ÊÑ®2·i ^“ò08îhtYåR¶.&wÿH€ÁÉ&›ƒ£‘ΤßÒbåßl„¹%Œ‘–1Ô‰nÑ•rc;êE”óGSìw+[Ô×mJ)nQâÏ„L(A/Ì›¡¨å8„în NÊI)ÉŒ”·O»K5O†kˆ¿[öí×&»äü•3bó¼œòá Äù^¬Ó§vbøšOÈl¨ìÑçÄê)œ½à 6*³¦p_¯ÉèV[û2z ÄÛu¸Eõc"|Tï@q›²p#Œº"†ÖÖD¶Bów²«xù„T€{“Ïä•À'|8fåç±0K›é)§¦¶çS¶Û6V¼ƒÒXITâÚ¾ ¤AÂ8X’èâTèÖÉÒBîr*÷o'À‰Á– ï—p‡A áãÙÀÜPô¼Œ£¥õvSѬS¿m¾ÂÂ}Z:›ma…ïO²C×"²ƒF'´‚ükI¦ræ9¾5ä%˜dôZ®àåYë"F˜| VªÒŽäî®EüçX •£Rv9RÞ>RIT\±Å×¼ dÃ!°À)Ÿ‚®E§|†1}»7'åëCÀYo1NùvpG`TA0ÒÖdÍ-Ñ)#§Ô' ºíòÞY¹W=Áw\@¯4tãS¹\TT*!2ñJý/ÕW1ÊGDª’.êë?Ú@*©ÂîŽK;·4Ïòv6ëú + .á_©¤¦=R?WcUk«|\» Ü’°þƒ.¿¬ÿ°Â_ññÝ q\ññ—[)‚ñçRº Á8ì„ðÿñõåŠÐ ÀÄa;‚ ¤BDoÐààâ2¨ô-øÿ÷-ðºÂûehø['ßCk^‡ÖNÂëÐñ“rò=´vCk.Hâ6¶O˜’«ÃÇ¥+O<É•åê}]Ïc|î”~cSRW㣨ß*—¥|ŒÝ:î<ä êÖr4ÌYƒøOH¹Ó€òvM>s^ÀW “Ï\s_5L>sG°¯ŸËÓºtôào Ñ^í·ßU¿®jÚí·ß§«YÔ9̽rQ—¥Û±È)v‹UîA›rHŠNÔD.r]‹äTóU=i}íT%ùk¡ð Ò¥­»¢šKº¶¤÷­¾ŸBû.7¶éH[ÞmèŠoT{×Vç¡£hÇmDW<šz®S²ëÛ®¯6’¢+Æ@X•‹^.ò?’µ:9¥t+û´Ié.FtEÚ7ìv—ü½’A*W·ÓÓS!ì‚°fÌÒ5Ç–·þ÷_[@wIºY½­+0dæ<–Û¾ÑQÞ)L<^h¦Da©f€œ—CéÌ¿¢ÙÖt«;¬Óí_µ¾òö—ŠMS>È#þŸ²˜nÓÉ%cêO´@Û@šv“³,-‡Â“ƒÛ°yˆÆÅ^ÐÁí+8«F-š¢º Ÿ×!@7‡$g8ˆ…_B€Xø%è†T€ä ‡±ð2èKÃ[áeÐW¥·Âè2æêŠHDòŒ¹ž„À¤WècbÙ˜ž”}¿uC…Ðæ]›ÎÛÈ ’t¶¤Œ>±P/z[±¦e99?ø ä8ž3MæaßçtÂw0¤’; nÓT­0 E+†maPÃôgsŒ‹Œ¸x¸&á<“Y cÝ¢þsl§ÖÑo\>£fm¬öªõªJ*(¼‡è”µ¢SzÓëý :)w«ó…Ï !'ާe…¯+:åÐTHøÓ†@uÛ(Ht¥Ž’sT·ÑW·ÝauÛ]ÏÕm'XÝ6ú$ºzpð«ÛF¯ø’ùÕ ƒMHt5Nw°IK2‹U¸WøþÁïº(}Ý8.•?f{c ŠêH¯6ôÓ¸A!ÀÁç&ËM…D6UY7B!H„¤>èZ©‚žÙ’B¡!üšnëÆ©üo>…}×–zš?–j™Sot$Ò³ÐÌ=‡BT˜ÁÌÆY/ˆëáïûÅüÁÜü„ÏOO¤òE Qí“ýÞ°ÚrÐ<鮸ünžœÜÒôý<Ùä°'²«FtÅÇ¥'²ÄW|^z"‰@W|]y"·Ñ­ÞÏÃ<ðDÎŽl…Ñ¥'òÔjíúók<‘f5Ç™ªß5wî Ò“P÷ât¢÷ë‚+¡„§½_—uÙwHªˆп㊀T½ßפ3È•ˆÞÑe‰Ùâ"¢w|‹PB€‹°Â0E â"¬ðqõx<. Ã1ˆ‹°Â0E â"¬ðrcս¯Ð JpQ€`x<€‹ˆÂCª[ q$níÑ $b»‹nµÇÀDÑí_b®è10Qú…c… Œ+ ``Ô00VÀÀH!ÄÀXáûêsõЖ(&„ñЖ(&tõIwŠB`BEŠ`ÂC BQLhS¤@„¢˜Ð!ú D(ú&„¡€ ]~­)''$ÊI¾ºÌ¨;˜Ï(XÞ¸é#út0;vSn‘½¿ k7±#–ßùÍ,Å—•cÄòGåwªË –?ŠâËʱ ÄòGQrY9–A,%EœF<Ö(þAtóÌÔfRÞ¡ÍÆ|än1|ðÝŒKTû´y†uÝ-ÅÐB!²j¦|‹\îË0Xþ¥>@å*{H§¬Ý8Yœ¼>\jµTPWLyAx>´+ºõ eF™“†–Öd•KtÅwP8já…:…ÒÓÂ2ï´#¢(k(ŒÅŠì)í²®Ü 09‘SŒp¡ãR`¡=3úTnKvRÞ°R}5úæ"OÊ{PYÓíCy,±sC1V¾–—Y¾­;R>ÄôÒ¹}ë–ÈÁGÜcpfd”®ð‘¼;§õLÆ)߇U߯Ûê¡HóZ¬+ÅwüÁ¬K ¯Ç†¯” ¤›2öËçÜÄÇäÿ\w±ºù8¾A ºUš4v¥ì–rêQ_ô’: I6,Îßý÷_Û"êZ´v]C‘òŽ¢’ºíé´1:o+Ë‘òñ©¤ÓºtRÙcå8+ì“ï†u¡CNv”/¬¬¼R¥_#å»5l—yK…Ë$³JoxN­áP)™ìŸEQ¢Ïí_)§¢DƒÇ=9”›ã>¸ì¬|ü„•ÝÇ5Uo°áúmöà ÖõºÇZ¸m9Ü"íº,¸E „ùŸÙÓj¥ÜlduÉú §ËÌ;²0Ù4-¤&ûŒï0ö½/¤hz¤ÆXå;¨ÜiÑ5%êŸ( ºµ_å5Ñ×ñ€‰†#[´ñ-]ð˜ø€‰µi‘¼{«þgW¢þÇlÉ 6‡:lÎ^Ëûw¨/=oae7K%úÞŸw¨4ë¥ò¥yGLB‡…T‘Ž×ÛÐÒ)Ÿa娔è)=_a¥ØäÇT!¥~Gæ„Z­P4I¥#­ï;²Ê(¨lè°ž•1P–•Æd)©\—¨>õ;úG%ŽªÎ .­Hªê“¡Éõç“¢ H¢ß/( J) ÜŠxz»xñ㟼#ž@ü¸à (!ä „0«õ«æƒ'1«Û=ÈeˆŸ_vÃË?/¸ öñx.Cü¼à2è=à2ÄŸtÀÊ7Ò( ¸Ñ(”Ò(pëïŸß? èÚ«´ÞÂÝú}nué¨ÈqÌ ¨±cažM•¦„-#Þ°^/{8g‚¤ˑЛ¼25žšÝÇLÙ8ÁÏ?Z?‘^÷ДÊNAð|9˰ ¦ÚÚØœÑªÉSÇâ¬ÓðìðË:ÙdЙís#?£ÄGºÞ•CïÕqryä“)§U…AKÀ6‹>? í¹ª^EdfeÂÉÔ±ÊýÊ$AšµP¯ìµp)äh…/àÓ[S&—È9Öâär­ÛIwÕÅ eÊ ©rŸéÓãâ@ÿNÇRTnNWL‚½+Š“$Z掷 ·ÿi‹â¤¼yç|&öxbÿ1G Ô-ÔYG䪗EÉ1lRbm¯(ÖÝ¥¨àØ‹2g úïë2gþƒ¤—P™³¦B¦ìܰïërn·gÉ9›Ä·ËÎeסÜŒ­;l·9µÕ<ɦÂw' D¼î®4µ2¼s.*ççàØá,uU†„÷+!¯v …(Yß̈|rÕÛTîT,y2½OÂヴôáêì|ÝŠ®ø¾nuêþãû/­vV‘äý—V;7@òþK«7…_Zmk[áu«ûýÇw¨˜Ñ®ŠqÌÚ: ©vá£C€Yž¾œ0kÃÓ~™¾°00}Udšàô˜µxúÒB0}Afíçô%{…ãæ@fmpúâHøeúrSbÖ†¦/|Å/Ó~›¾NÊËéKn[¤ü2} ¬ü2}îþ¼*!E„;DO’óJÒFKÕ<×4=«M„",Ë?ú{е¸ÌâkìÓÎã@RWÐÓ´tâ$ÇݬÝ;+ć¿Ú˜H ¡`V9*‹]SÅ?7ìZ(\p³iV‘žže…P¡—ñ%ôÒ„§=ô2¾„^ªè=€^Æ—ÐKLÐË@/ÃvCëЋ!ô2dõqëŸB/CVg7ŒÀ6탊Ð'ñÏ3pÚn°"[³ñqï]§x*MÄõдkG8Þñ YaÛT3·Á5+| Šo¥ò¦l«qÂçeÉyâ;Å1}}”œºä| …ïO>¥¢Ïv„L3ºutYÈ%óÇ?ï‹Wh—°Î­¼Bm×`NS» ÉÆ_ÑrÍþgk[kÔ'áKÍ©s—[¡Ï2sˆYòíb໼ƒCö?fÄ7Ÿ+ŸgVݰ—PxwùƒFhLãJHJ†„Ÿ?˜¹¬&}ëeã…O'ÌrçAmö…ôïæ _.Ñ0ó ]•–׋ÕY¬ð¨Èjª.i¢ìšNûÜÍ F €lá>í´Jõ",…Ì Á¢ÖâJ©…Ë´L5&>|\¨¤5ŠÓ¦m¨Øò†¡þÌv8S$ä}-ÇJ`v.-g_…Ø 2R¬¼{Ú‹žÞKSG} i±ùNsH¨øï\0÷ˆÎ@|kÅ”#Z»ŠµÜ× aJ½¥t«B’ŒU:C!¤›–nÓ@39Z伂Âëo›W _ >w'sÛ2¹½àPøD ju˜ÄþT¥¦T´¼vƒ@r®` [RØÖ¼k…A®"ƒEæc@¼ ™çv«⥅ÜÛd%¦øi·Xor ˆ—xiÚ˜:›¼@ÂûgÍÆÔÙt.>+|\ÕÙäbGÂçUͲróáí/Ũ‹É=žû¹^© àÍraº€m†«V»Þsp±ß@Á9·#!•óW§g9÷ò´64—Ò5Lœæ$Ãî†nÃd‹ÙZáÝ…”m,RöŸ®«âiŸl9.+|xa©C^j?R¹è›n…Âç¤.lE¥ëǹ¡¼gPø: U,Ý× u(]>ÇÿÒÊ éh­2%ۭ˲ u$}·ÐS¾Xä¤W”È5&¾®nÙusÎ.Ÿ‘Vj˜\û¬B®ø’¡þsÊ]£Z)ÿî´ä3Rú<3=ë˜é^¯]N¨v­–å5G2•ØØ$· O‘Ò—åÍ©M¨÷a혺(¾æÓg¹é}¬’N|å$ÖÙ*_Nù‚JsÖ¡”•JôÆM. UVæš½J$llG¤Œ¼²tˆ:ÅÓ¥°›Y§ŒÒ8­ë¹Yó*«è‘Ҽ£_•gØêNŽ5äŽúúÏÛ+ŠÊ,¬d?Ÿ¦LY)o@©›®•êò¬/öBìØ ¦îÅ^h‚Âû l•ãŒ{îïï40USWå–«t.“ÎZž5%n±ë5o²-RF[Á¨»b„& wî]Õ\ »v«Ü"ãŸL+>ÓMK¿qniã®}™Ú•g¥‘`\”´í ðÀû˜ºê^.·ýf£ˆñ›žm@ĪëåÍg·>áF¥ÐÔû«ÚR4|[Ï&¾T´'(àt«‹uM¡å?ÙÑ`^h'‡¶©€ÂZ<àr!{r … 8OY›©Q^q^Ø6Û’¿ñµiò…Cø•‚ÔóØqÔêÚ!Ì›‘ªÂ"&PhßÌÜõ[Nö =èøŸy>&KA¶¦Í™ÀOüvCˆ` ô•{@EAÃJPÔ¤°5Q;Þwc+Ö+G¤;ó¬f²Ly¹R”σÊàfÜjž–yX‡+_mT•æEV+¡éÌGÜÙÞPiê)4ÍJætÎÔ7Œ_F‚MäFÇ:2Ù‹6ùÊ)RÆÜhs‘RƒLBÊäPºM-§çª3êGÆ/c뎺³¢£ó&7ÌèšÆ/óÇ}?æƒÌ—‹¿cµJ{Æß{5×Õ0ïl"Héç>yM»à¨¦Šsº¯;êÆwÌØÖÞª‡%ç©aNèZͳ²ÜD+çÞ"_ 8FJë¾”½“Õ“ÿw(|€Ì@kmæYÁ«mnK$ô¹újuY›¥²h[Þ²ª¡ðu«Ònƒ9™å¹uÿý†Øê=Z—'— ú]1:^£O1’ƒôÖN}O 0F=ÃÔ\ŸÖ7&ÇnÐR¹|ÝÅÈ2ŽZm3týë6ÈŽ^dSæèwNy;_™¨š¹œïh3LHyPlk1f%—Cõ2ôoÆ*ò/´Ÿ0Âù _º›Qî‡-N/Z‰>ñ1D\ÊšJ,û†”¦Î‡º{YXÇ$ã„r9̵¸Eïϼm›:­˜Ýæ~Øâ>¢©;4€Æ€*Ñ:gn¿Ÿxu`æ+f^ƒ™ïvf© œUµÎö!Âo¸î.ýTËur;Üû”5Ö™­⪶™ý4•ýÇ×UÑ×f¨Ðô=]ÕºvàÞ¹{2%F¡ê°zÎÙ…1¯,{YnáXE¸€ÂÄUÙfߪ•Ý¢h7;?QÄD¥åMaTÒœƒQi?T¾þ•öïúuBÂêœ${,Ö¯ûÞ¹ïû}ªu­ujõÛ”îU»ìPˆK èÆL½*!VÌÖ›Ÿ°ÏÆ£FÊ©/*²‹©] ðy, Lj—þ u^Ðö¾ °2¡8Q¤b/¶´Â÷eM´Ý?Çè{M´“Ðfôÿc!kÆ|θújç Ÿ5š‚6¤Ý¶Ì}3Ÿ5L_ÓRBH»÷;ÞÃB®„-Â[W¦‘ ¤zà´‡Â'º²~3áuÓ5Pøºú7ŸmØuek¯Ó’(Ó!ºut®"YWºŠd%òµ:FK_³Ãë[*ä¸Ê&>ÑÀØ\c¡¤Mוèñ€e¥‚£è±bic´›6Ô·¬„Dn¹BÞ:ZN-z@`Yù¡døšÿ'ìÊ–dU•è/u× öã~¿'bŸO@œqŠóõ„ÔL˪îˆ~[J1ä¸Ö™ká^lGÖŒJqAæÙwrWvÅÈ›¾#ŸþýÄ—²'ûjªªÐºb#™v³]x>mmÚ’•uA¿(~è%¸ Ö÷Z¬ƒjòŤ/u4Ònew¥t­½Göd–nßP’êÞª´HÖÎé\Ñ1o¹ñöÈ­|´¨Òª Èû5rqH²–¨æ£7+í­Û´]¥v“íBó‘ A‘´Äw»èG6Xs~Ö‚üF·˜îº÷t師œÙé‹’7ÈÕ"é|%¾0^–¹¶'뜋Šüî÷¯w-){~7¹Ñ05ÛkÕ­''Í×6ø÷/ÊîòôžÛ}˜æVL*ÈÖ$÷¯ ý[Ÿ&³.ÔÂÌLF¼_W£ÛÑÚéø@W.ܤãÀìáÅ!•‡ˆ§/5F§æÞðŽÕºÐu™Ü¿NµHŒ¯-º¼TdÄÙ8² IúÑèe«ºÝl“€u¿¶=c¦\ÚC†Ìc`Ðý…|ÒWR³!†òû@nYDŸpäuÊSäí@•—ÒMéîñŽ"ï‡nßîê” ÍæŠ>Ý÷ ÿn»»ò§r2¹è u^ ÛdDJ9m‰ZÌÌÖ¶%Ƚmxs³Üt%˜âü´8¾“·ÈÓêðg!R tOw –¦õLÖúvþ÷gc¯ËC™Ë ÅÒŽ3uîÈÅJÊÒ;3Z§C³Î%do0…9°;YˆÆX ˜9Þ(±t Åb]„â§<´¼oôàî€Ó0¯…E«XKˆ=Ýùlo†±À•5ÃðçLè¿Ó)±.£ dÄÉÁ'}6†3ZÙ«Öp>cà®8¾…â áCq.BÍæ°gÂd<¢÷݈Ó4c .¾”@<­ŒõÈ8”*!Âd°¤eÐ)âª×¬ -Æ ¢{õ—âNl§­Ò²y®0ð>ðá‰I¡ZV-¤ª»]srM6X ÍZ7¢6$AÔªºÚh“‘G?Q¨[”!«SÌM©ó¬ÇÀ5â\ ÌúF—¡µ9c¬ œÁk>ãÈÈÇ$¤kóèû^el\ð†É--‘‹±'nÉyfxÑU[Ù0ž­¾´ðuç®°±Õ­ì9,³Ç©Ti3©œËf>È!ƒ‹îñx)óqEǧ!”0’ïoÓ Îæ2Wv1Â"P«·†—pœ=Ä>´×¶ kÓ®oxC]í]ýlnÈã0W‚ 9l¶–WŸ5˜ì› ¤b¥;Ií!®Züyë¯È@ BãkEªý«ë•’ÜÚ…°£®xŠ!R emíi€GGïcÈöìYÒŠoTÅWÊPŒ'Ó ÉGô¹ÆN. ¾¯±ë÷íú®—ÅÓ¶ô@Û’<âü.=Á$ä|†‡Þ*kñàÞª‘._÷VA*‘.ÓÞ*ûâÞªäA;,C×[ ¬ˆŽìÄ1U0!tp´ÖVÀÀۑ㺌꺟u?ˆ*Øõ¨mšÛ;šnYM¾ø˜ç×asýïOhäõ7—K–K¬RÂ)¼¤Áž±çNVꔯÂ)ìƒ`{ÐHNá ïÞ.(7EœÂ×妰¯1§°Ï†´¼Ë_ɲæù}Ò[÷-ùðöˆäõÏ&ä¼ÇÛˆ5¯éˆwàëe››æƒT"ïÙª2âã Ø–¯ÀçkÀ©-o[…Ñ5pg`ŒþÒôï8©†“+ {Ç3ðç5âÍ‹Iut¿®‘Uú‚¼8!6Ç-Yòö&\"k³Ð1½íCñ!M¥=Ñö퀘uwm"Èút™fà« ŽÙ­žÛ×#…—¼Ö}ŠŽsüBÌQ˜=“Œ8f¯$™î ðñØ=yÇ'‰¶ù’‰EÊ…•rŸŸèµ¯Ý[SRkêÿbMíïÿbMIƒÖ”=L‰5õŒßXSN¡[SÏø5eÄšzÆo¬) $ÖÔóhÁ'aƒuÖbŸ²Ží¿uB„« ²ž{[6vIb R ,îº3\ï™ägBɲrWZsÖ62oü™œ‹ÿ¶"h—7½lûÝ‹|&§â¿Â1”¸è¯ýŒ¦+¦¦ÃÀè(q*Â5§”š‡ZÉŒŒŸ¢D[„ÜîÕ:¹ÒLÎá$÷Ž-³/hZü!4;¾¿i®=÷ô1¸ËHT­ga=]¾NŽ•?P¨á–nÅŒR¬Ù|”¥ý;~ä`<;"eÝÏyÇÈ@e‘mSUE„Ð×¾ösÁ—šüŽ>3H&²ÈEÌs®èE{µ€#umR¶ {X$*þ“e¾-uÍìa±ÈrÏä\üw YÓÌŽà› ލÎñt»-ªIOt­cmÚ¼v>˲ ,.€üÆ* Eâ¶li«|%O¿íÙµ›ÏµÏz°êž§,­3áË-j¬˜*ùÔ:Ÿ>Kûï¦&ÕôÊ)š¦£{Í“eýÙº7átsV¯fÐÆK^¸’¡þEÚ‹lÌ+M™ÏŸ“{%¶r`gΚ£ÀÐXûß¿„#ÞÍ'g'`+ˬéBG|#ÛãOëò‰CÿÝ)Ù…¯ö­¨^oγàTF¯5о‘Zöìùn>Dgs6=«vÄzªÕúõDüü‹ØøëÄ9hëiÔůH¾ÚÝW³¦æx%9ˆŸ/€ý¼¦,÷c0ôƒz ˆºŸóÜ«ˆ–„nþ¬mç²Kû:…`yôMš¢+ÚǺ*xd"?S±Ê{ | ¬k ýõPkVÖ5>q¹†«OÂS. S.úF±F¬Î·{§±j/ÚŒ°è›Ä½fËÖ¾®Y9²±&#&¨(\'yÖfZNiMæñçÊp‰VNŒ©iLE'üëЉtÁ÷í-ÛU´«.xÈG·ó6Ü:²ìÃT–‹âY‡7TZà#PŽ?‹ña‘ÁœÜžÇÞ‹Áom®&t,0ðqì…Plo•r)Ø<3"á³"äÃ$§µ«¨LŠ(ɦÿ¼vhz¡• #"Q’<”»¯žK5sÿoèýð<öƒ–¢.ò÷¤Lj½Oß8°šjƒu¨s2á¨à[BÁÍœ×vªF°££C”dvM/îðñ3Ù3V÷rlЉ ·Fš?ž8F3f=ˆÉôAÞ™ï…þÃÀ†ŽåÓ¾¹o´Ù)8c[Á·½šŠy™é{îÍN®_ׇ¡»ÁºÓ¬(f²†P³“¿À XÑYפ’†¾'ivò~ɹS‰KK ´0e^ÃØ Ÿ™Œu¬óJ?‡Å)¡¾és^¯*Ó£;=¥ó­{Ýц4Ö mV£Þp½À¦jQŽ’›f*ð£!êb±Tc–é =ÿ`Zû´èóª±"äÿ·É‰2£Œ«bß»=£;bç^^Žlb´cËÃ6{þfË/øÉ–'#~²å ð“-O€oly…lùèù›-ß`à'[ž|õ'[ž?ÙòtÂ?Ùòdȶü@¶¼:ÙòyaË«“-¶¼:ÙòyaË«“-ŸlyŠ|cË+dËä[^![> ?Ùòt­_ØòêdËä…-¯N¶|@^ØòêdËä'[ž¾ç•-o—\Ûf#µù|Žøp½‰W§øð!¤ð.>L€¨²cÓTÜ"].YÒKö]LèѳPì³»Yïþ%Þð®,ö: nÇ: ¼£âøPøâFì¬Y½øÀE‚IJOîí9,0ð‰ÌBšÖ°Á0n ý;‚° \¹Ò¯ÊrØ¢;3ä5ưËY¾Wl|M™9ì ¤’î…¡ÒßuêÙ®3ˆO!ÊV¯^2¨¯:t&Ð!=°2òèǫԲ+íêªt¯|‹0¹ÔŸc8JËÙÂ'¦ ìýœûm‚Ô×óÀñ D­ç´ëj²‹‚öÂe;³õ~*¦ô­ùî8šEWäkZaàíˆyA±.“i»'­b0¸l§ª™øþ¹ï¦^Ɉ¤Ñë®L­«¶&ƒ{7Z÷1e®´Z ý$¾“Dwû,j£G1×k¦0yß #È;þUá0åØ[Ûšã;öˆñkŸ­S“gCFßGÓoR),²ÑÌ´þ1JšÒŸšv†´êçbcñJûžúƒì%ÉéÂøÐwCÇO}7ô‡¼ê»‘yCúnòCߤïù¡ïæôô‹¾Ùо›°Ö/únú†öÝä.açé‡RúBƒNü -÷¾JøB~ Ò=„uâWÕE"+÷)úE:÷Ü£^i¾Å·‚éÖ”y­°-ŽNÝzþ0°Rݳ¾KsUaà{߈ô¶Ëªšó¾o ¤FŒ7¦µ˜º¥™{ |àðX8ÿMjýÌ~’ŸWÀb2ŒˆšOprgc¯K3#Ršx—mÚ™ 'wó²FÕ‹}QDÇ©±üëû‘·GWªiëzª¡Å9Lø×±oó¶/)ÇÙpú5G·”"m}êyn/ò ÷ÈÛÉ0òo9”µÉ¡n9 ý©ñï_¸tÏÌZÛ5ÄËŒ.ŒÇ+rÈ™"ŸG;† 6”4‹ØZš £7H»0%™÷oÜ륚íEžñÖ‘Ðu™äfÆä:·þG+r²Þ¨ºwçÜÅÜñXë_ÔàpÏ·?Ž^–q†hI@~ïÍ ÁܱOŸEÚ÷äéÞˆd iغ´ÅxBžó#šÙ?i-bè= Èä¸E—ž5©­‡–äóŠ¢°!…qü‘;bÕ#<U}ø’é¬xß0Ñ5ˆ¶+œh]V EÉë–a R‡ Ïd_¬2…ÔVú¹ …5l_f1*/ÇÀÆw®×$&R A¤2Ðvi¾s;$ˆžÙ{âÒÏêG™¦ý8`‚‰À¼Õ/MÍ‹LràÒKâS MOWôºçdD”0ÛéD&µ,“jÊš| $ÌþAÜs]Æ*ÞjžÓ1o˜Ï.¨î6V\dŠü8‡{ףõæˆZ—š"Q0©ØùìVVØѧcʲ܇b­gúªž úEa󜢎{nÉõhò -óD*ÞT«Vlf Y!aöïßí顨LÌKg'j"?Ñ7¢-ƒÞ•%—ËÜåý¢0 Š–~ŸöàmdÖhº+¾Qü%4V¬ÊWÕ›œ$ŽV”ž¦ƒ33 f™€ß< /±fËØT3Ab…»Ð[]±Ê><ËÆ” ŸGdA„ba!XÍG»-é·G;³;‡þa5±n\„HMBëf·Ê2Ï Ó²vL»q$ÀÛÁÞZœQK&«¥‚4ÖÕ @Ÿž¶»Íz…Ø7Ua|/ž·ï(TºÐG?ßçŽ1:çŽØ šã·¹£A‘G£ÍÖeãÁw»\v"t$æÓü;É£Ô²»ä0ðöývLß8úýóõ.úÝ+ýþùzýv=l8úýóõ^ñl°g(ž%?ß/µæ #Ì45^JÆ´†¿ïX<Å;=5¶ ý€K Qùø¼ìUغ¹ytt„v3`¨³îeÆŒ¦Àø•À[“,¾s í­ÉŠk‚Š©H1ðv ¬–ÙÎ&ÞIH;jò¼±^^Ÿaàãˆh h‹uÀœÕeÿ'ìÊvåÆuà/Óëñã¼ß™O-[ò¾ÛB¾þj!e²Û¨ØmY–HªXuÿD»0àãpʆúÉÑ Šjä¡ðmÓ«A6Ë¢ÙÃêÐ £›yšætÕƒ¢ÀäL°·r <N^¥4°@>N«(õ°Æ[¿Ji‘Ŭl&4Å%?¹¾hÞÉpÀã­ Õ°H<à¦fPÌ-B›¦k’È‹mf@VÈð—óÊócY•CJœÕ R¸{m²º-(ðõØ/Ð_U¯©(È¡5nW×u/Úygɕɥ9é´ÞÖ9¦ø®òçöÛ}4(†9uŽlŸÄ„*¢ )"ˆ6½(ªa/q?N(ý ¨Ž` œO¥f))0î4¡Å?w/á2Eµj ¶ÿòÖ 0uí&«™m§@âC…Ý€ÝT Ù-¶*$7FÈÐâ©\Ê&kÌÞ š‘°ú#…Ø6˜yް°+Öƒi)ð‡±UGeBÍÃ4³q$_MY¿by4"&DžYo+P×¹¨½ KBä9¤×÷ÈriÙQ;óZ|–yÑ:ÝR±2ä• ¡Çg™ûÍ&iÇç CAFÛk®ëº­ÌoÂÔ…øG»k®f]G>Ù„Ó §6O¶sÝ"S†<”¥„j÷¼Oº $7bgî‘£Û—.š²©×šMÌïä 9eåXO5›G—/ÂV§_ºél¦™Ú”L1$a@ äÓÙÏ"/¥bOt! úyQáNlE®y=ÌÔ¡ÅÒþN»ªŠ®éøÝ‰ö'Tê,O×ÁþN~Í;íB÷ÇÈþ½ÛDxBÎ* Ry†“C¦6ÏÓ±YÏh|.%¨áØß©†RK<ÈäagîËf~EpÈ^O3›óÄÎ\×u‡Ý8:ѶÌ|½"ím=²ª^‡µGlh)TwQÄDœZ"óNÙ-wFÉFéz¥Èp÷a™Ô² k!òÆ~÷óÈamPw,}¿¬Jªw6?¯C5ΑÝ5EO¢ìòIÈñ yíÞf£EÁßæõ‡°ãa¿r’äÅ–W‚ͺkhrõõ³êg¾—ºÑóÀÖogNÄà½ÒÍ.úyÙ›’­ ·oÆdô#:Ù}­3[ƒ²ÛagŽ#À¸lö¹­öñåš±ª+s<‰²3d’Ò32d¬ê:âaÐiT3/…²91CÞO)ŠÝèf(Fp÷¿RS—º;·‚ò¯[è¥nçbÅcfúÆeLçq(ðö¨æÑ0àýé±j©(ðqJz¬çqô˜té7`g%þœ²#›ÙÆ™XïOW°ujVHüd^x”¹AerÐ¥Ií9ôw8Šë²`á2y¼k%hÐäáÙÞ;Å†çΉ—mØ™t¸¾È Ø+2yb9z./€G³Ärô\^€gÛíŽír¥¦é0I~^ —ÊKï—ᄲR¤f&oöaþtÒלF×R“ ¼²9¤¨][WT x;jðNeŒn‡ éöěԧ׹„Ð^N«ÌQán Å²f E+îIÂÙy8)Óå®&=ÙÅõŸ“„±9 ]Íñ(SûŠÒ¢‰ RœmSP6ÑeºfÂÞ]¯ xg©k8†±IÏ$õ ðpdÍr¨z±µµù­Ÿ‡_›„Ó•M5Z½A“ƒgúçß éÀæó¥mPA'Ix$œÇfÇ:Ó™^6ž„Ø’þþå¯èÆÇÛvõ¸g¼™ä‹”Rü¾˜¡2–½u#¥™7 ¼žÎwÀÔ.(TUµ1•}h¹Âw£Ós)tsù)tüx ¥Ð“Ö44æ`£Hi«°‰fVâo¼¾vðÈPR•¢ÊÕšgqÀ©vÇ/ðkóEâfõ0VMGWfpdo7EVö;ÞŽÌLA-EËR¬™– ï˜p…O²æ¼®Æ’¿ãùC‚zZ²ªî;A¤ò[·Úìp“X+àIžîÖ ªnÕ¨ÒšPÛñÇNI9¹—ì7&\×"l¶Ý4‰´ 9iN L#LêRgs•¢,1"¿?Û“ãã÷ö7{òŽØ“'ĽýÔž¼Æ¨é›úçø(½]»Ú z\Á§+a6ï¾D¤£˜’)êzÇUšØ¼¿)Ë ×†03à?[?[™¥z]ô1L¾)gÕßߨFL«™b¨z˜² ax:=Úev ¼¾KÐŽŽ ZéfÅßxý U ÀV"Xÿ¹MÌ “‡/VÛÈSw2…Ïë°uŽüpÐ`Ã?#Öbëœc°Ö¤z[õlðŠ=ônÃ8Úè¼6󆦌¼½¯TãÜÍÓ¶ š@Òy˜¡9yÖ³˜Æø cµvÐx±©vÌEaÿ%>Q·=½PžÎô&64K¾ïÃŽhÝðØáŽÃóxãAÁެ+‹œ×|£ÀÈZÊrŒCTßõª[SîxtªÅægûåô…XEœTéØA£{-º®ÚËXü>"Oþf”Ų’7ó`®'˜fø7“O›œ«‘_k›áJ›,ª À„òbë*±°ÿú´øÌC…͓ɤ¸±Û¯W£‹½­(ðh0ÊPVÇ)lU•Xꉙþu8dwŠ{-pà =™êPOª6…â¿ñ~‰ ¬x:‹»£ÀÇq†(± ·žúI÷U¯(ðy¶’z;Ñš_Ñ¿šÝ§ÞR¡ 0¦-n^ßKøœ«¿ãþ‹«Ï€áêc ÿýów®~7²+~æêï#»âý¼>=ºú4NŠä…ŒŽ´%»Š.:º‡ yùz±áq¥@Ï«Z!徃ômBmØÿüû"E5y‹µ_bÃÏvÃ÷š­y¶I½°+Þ"î]-ûLÌmbÃèÆØ_9(±*ÓVš]ññ.¨0N£ÝˆÅhðy4åÁá†}êfmŒœAŸ-¡öÕÑ’%x|ëYU: ¼.RljÍó|Íw,/Qûj¨O‡Ó¶¹Ê”X¾'öÕÐæ¡“˪¦&ƒž‡„ØW#é 'ŒëÌ꺡Àó=‚XS ›ÏÅ‘ØW£¥§¥®u­§n…sЄØWû ;G÷ͺGû!Žš= QP:dA•©f3Ú4‘Ý:pÙÂ1¾ç9V°îæ´Éê"eÈïó`j7zÅhX8¿S½ ¦â´¸ü%˜»Ûë(5\À¾9Ûˆk.f8íOˆ)4œ{ıò¦Ôè8@Ç 9 W›íw-†³¬?ÿ2Ón3ºÆdYSàí¼‘J̱‘*9|”?ôGéš/G f”r°p‘Úÿ㫹Ÿt®A•Áp@Rùúå»Â2¤Ø iîZ ™ìá(LxØPƳ‘aÛ.¡þ¿g]aSœã?„‡ý Næuز‡6m4rúõ*%—aØð;LÞLp€âç!Ÿ0Øê¸&“h\=ŽN¿×Tx¤så-ni ¦ì25Øÿ&,ÁOÔyÓ¡öd²Ö Êÿ%WN*Ï¢ ¯„íWn3˜áÔÒðïÖH˼6*]pK¢–†@‡Â“Óí<ì7jiè²HÏI üœÚ J†|2'[dô¦v˜JäÇ\rÄñÚÇTLu_ÌüÙ“w¡C‹t›CÛ²‘ÎMø £ìž.³¦˜ {¢ ás¸¼ÓD9¤ë²eOt¹pÉ'àEÕ6«Ks69/|YõkºZ*›ùòoò†Û8µË溞Mä}DÞ™ì¤B›Øíº±óßùø´ÆØ¨H0ä“Ö±£¼›¨fÁFþòCwæ Ÿb÷ïQÙ¿eìS?87þ½ç¡mDUU.“Û׫)Üšo_/»«ÑÏcƒ_Ñí‹[˜¿Ý¥“Û÷Üd¾’Û÷ßoÝbˆCÌCy?uýÔxFÌC68tF¦=^hãuHT›^ô½ÞhÚKnNúˆÚ th—5Þ^dÓý*\ÚHH©ÕPàÃñzSk±Ù[ƒÕBr˜‡;Db=Í=ŒÉÍný|oo 9ò—´SO£;¼ÜgYï6âeÈ$ò pzj‡\¦©ïØ(Šä+]¼b9ñõ=ÌL}a:W•¨· ¹”ÔáöP8všñõ8TcšbüHnO+»â•–‘C‰m±_e§O^n±É:¨ˆWvÝÄL“8ÜžµÖHDtQ–&]üöÜ–;>ûèÒSÜZªR‰XÉ=n#Ðá”–•HE·f˜PyØÐí8êSÕåÇïV»¤oÎÀº`OóýÍÅTݺ¹ˆÍ.[‰!áíèø È(9›Û5kÛò¹á¯;Hž¸ÎvY³SYíjÙ}É“_Á#@ÇÑ64}£×‰!ïˆDÙ0íu#¥lÛŠ?Q(.¸´Æ^2°sªÞ¨A‹jæ¿3š RCÌÝôãžCAr»¿ö;dPV窴?t/(ðBvÔ ÐFã ÅQD†ß£¿õÞeØp»“Íü7eñØí¹ÍÇ&>Ílæ@uC›ç¶fF<ú²À¤ÑåÔ¯é´Ûôy§@nDâãàzZm(¾˜IS ‘]Í¡“Àm67•˜Ÿ­Ëǽ2CUWÊl2.ÀÔˆ$DÖ°ªï6Ãß×¢ãO¹—¯XpH½¯Æì¹¿æ…(A`_Ó«4ß ¿æ•vx‹Ò–4²]vÜ¢¯<ø—ÑNÊ­Evõs&½™žßÙxP¨†¯„#C8pýV ñÛyð“]¿=‡ªÒÕhÿ»âH¡¡²¦M 5PàãÌ,ì=G |¾k¦9er-vÔLKˆCô™fÚ®+¼|V¤ÁjÒíç?i8ð/Š4øEš8Ó~þC‘†ïgþâU¤à‰"Ûi‰" Ÿg¢‰™Y›åžO¢‰E»ŽËÿ »²eYU$úK»Ëò±ßûFœû 8â„F}ƒ˜i•û¼ì§X‘!YÃὟ í?:œG]Äå̲¡ ->Ž\šÂ“LÍyp®ßÂ'› Ê!-1¦)³gX¿ÒIÛg†•¢%ïèvÁ°²õR\òFq×ßVP´<â®/Vð_G· †•Ù†Ut»`X©¬& «èvÁ°R5eXE·+†•М‰MN~ÖîW +¡ q*º_1¬l?¢Ëšè/—5ièÇ¿\Ö05aà/ +Eý Ã*¼™ûÃʼ°Šî +$ «è~Á°²@̰Šð óëgúçñëg¸åP‚EÙæß?CÚâÕg(ø—YÑ·»y§ÙÒXhžDÏ ¡¹Xhî_„æ6Ù Í=ðñé›UKÍsÉ.†‚»½a£ôÍMßóµUŽwl5µÛìUs!‡|Ô#¨ßŽànôq¼*6¾pe†È‚σRzåÆ&.£‚£ÈÜûùs.‚C€e0ûúMÓšÍY§f‰ñ h[tÀJà^ƒ3û”Ó=yÎþ;ÅÆ„\›,k0p?èÝm8¤o°ATº”CI:ü0*°¢—]8.™4“³š òȼ€¸Y-MÎx`–EÑ‘¹#!ÞKl«åÈko7ÈÇt5Zk_¬‡Ü, 5m3dAîz¿½3eoæ{ûxŠ YN.l¡£Z³ám€¶E§,Èür,Rpƒ#¤w6kÇiS¬ä@‡µY™{dSòM‰®d`ÚÚÈ‘/é6ú²¬åÀ ð±þƒîÐTézÉEaÍ£ ò¡CŽæGËš|h÷; =ÑÓNó>+3©gš Ý;úc3 áÌ'ÍWf/)”ñ£ùQ;¤Ä1HÎ?‘Q@ÚOh#Y7Ï‹ùÔdEîýûÏ¿ûä¶5F½ÔC.#yG÷˜\Ëú T³››e…¥çõ gf³×²#Þ¸]d´ß¶êEñ’m.Š©qY¾‰I%×À̈âã2WÃÏf>K–Á6ÂþÿÝ홸æÑLñp‹bb\–ƒäyf¬Ñ«X3 ª÷ÌòLœaw­Êš™)~ÂÀ×Á,=Å&ašN—“Å‚y3ܪéÚŠfÉ"¿1(XXÉ\õ´ñujû”,u»?Uö[ÇÇ–tøª0ÞÈg¶¥[[$®EùB˜U$oéK¼¤Kz‘|aKZÚ$!QÂçS›Q±é©Md\¶S]ɯÛe+Hgbã2ë"X²ÉÏÈ5tÙ59oÍG¡É º!X!Üžˆi]¬EUÓßùF®…#s™óXY+³u£m·;)¬åÆx«»L±þƒO¶b¯ÚYëÝåýL¿Š*%X±uæ}Šq!HtS@Y̺6­2Í2˜b±"„Ðg›”L ±d žûÌf;Ž—ÞlɆAÐÿ("öYþéŠw[¦UOÁ‹íÛ¾!Ì6Îf5´ÍøÈ:‡¸T3–†ÚLH=éyWÒµðÔÝ0Ù}™ëtkJõydpqô¾zÖí`hªr(ÙHzÉ•t÷pòv=yË3fN*!Nõ¾þû°¥²*mÙõ•L»‚"ïÄ/ÔÅ™l‡b›ùYUäî …rÌ$yG'ŽyðqÙŒÏy·-%™B¾ø¸Ÿvm޲Ú2¸OõÈ× YíÈ^VkžRdŒ‹‘Nx9°¹+G³`WùFÈÝ Ø8UÑÔ,›(2JËÞe[[Ö¥&óñó' ‹ÝyÑ~ï© ë*MÆ’3.ƒ`UO×¼f¥&Oú"ÈT™›qVS¹À•Cô>«r²™UY4JÖáÔð>«òA¨êY®ß0ðø0³l,åRÔJ”:ÃÀ'z¹…"ËÈ£££L^„ØIUË~ÂÉïMêXèºäV›39ø÷z`L€ÂÛDc‘ PEA?¢ˆÇA™%µÊËv00¡Rÿ}’¹Îù”ƒÆ7¢*N»xŒ9'åkÃ2!nïmªÝúIl=ß–j„¢\”œ"y î€M‘ò*ß2™c ޶¶õqç«Ï»¢mÂî„Z?ùˆg{±V¤Œë®©K ·L{62C\3ÒbŒ¹ ž¹eF8šØ/Qròjá »uÛN#Ç@Äþ÷nÄæ7v¼ò.¬)É9W{öÿÒ.¢]Ö$âQ‚sS…\©ê~Úȯ¼®˜" µ©ie H?úc_Rj¶)%m|” +‹,|9{OÒ5O¯r22ü•ˆ¾æâˆ6Q\Nõ”eydÖå~TîL/ÕMdÈÑÁæYí–[ÂNN©Ò2et¿²`\¹-‹æ“>!“c¾‚U²fiÚ¥ ÏV2Ö²Ì oÞh¶¯²˜¨’GˆÍóÕ” ¶ùë`ŸüóßÜM®¿ã)‹‚å=œ=_?¨ˆH}õ |“ß•EÍšÉ9xàó°¯>_ Æ›R–BøõsÌlÎDØ+ÎʶœØÖ^ñëC…äåÒ¶B?ò´fÇëFõDé2n[Pº¼ngGm.Jà×Y¡øXcàã´Ò]TR§ b‹/û²4«Z¤#\¤¾Žë‡vfcZíÌë†DZÿû×3HíâT µÇ¬‘&¾Ð|èCóñº_h>æ“æãuÿ›æ£ÆÀ–Ï÷¦ù«Ù¼†×ãKè‹·T%°»^sò¬ØK_»lgšt'H‹8L‚H'Ƨi`@¾x=ÎãPÌ­Ù`Dâ jЌƵ5ƒœñ¥y%|¨+[ÍP+×c4Ÿ‡ Ñk/`gõzœ“g÷ýé¢ië'½¶Þ˜Ü H¸8ïÊdfÎí+éð"„ÿÆÌçm …Žzô)%€Ìl-¶g‚Dã¢t76c³uKéëöÖ±ÿ8ÏG 2s€4{EþsW$û@ÎM])% 2 v´Þ_®ª¦‰ ã|¬_£H{IÉ +mÜG‚gñ{Þ•ÅÒ“îÙ'A½/ʹ€C–™2š²ôÔÐá?_Õïéœ-£ÈÛµÍmXÿfs+ðÊæV›[üÅæv#Àk›Ûm!ÀK›ÛMPà/6·ôÑ¿ØÜÒîùbs+¨Í­^ÙÜn‡Ím|es+N6·ñ•Í­:ÙÜÆW6·êds6·öÕ ªØl:‰o¿›MÐñíw³iNoI~5a¥Ä÷ßY)LSñpH>%­áÑ¿HZA€c¹¿JZ¡¿„1þ>o§¼PÕÍ^jM¿OÅD¸8ÎõÜæY»€¦5Æ»¤ÓvJ15›³>évÊÐÛ¡Ìì&FߘÿÍ4,zZ9¾p|ˆ'‡Lm­ æÙñûã¦26ë@kŠ“Π›Ð:óqMU¶ÀJcåä¬9“åRÎGŒHqg›'$<=,N¾ðÈ#>öΤNU˜.£>‡Åã‹`úº ]ÁiÇ_µoegWE\:ó)¬)ÐvP6±ºú»0ÀnÚÖªl1ð°(,|ܼmQvÓÐù°Äe»«.î7ºfS¡×&+DO§^Á»T}jN¼èµ5fñ téݼi-%,5ïÇi£Â}ÜŒðiZÌrÄÀ`Þ”…¹Ây21%I‹  R |£Žlâ}ª`aªpvPeG£ þ¶’ß°ë2/Pk‘Ií¿Â÷ów+âhvïçïVÄAŒý~¢]µ‹M;Q;£ßEí)TÈÞÑ©Òhd²)¥Ð9\»¿#*9©ß1àóRýÞÓGG—ê÷m#ÿÌëJýÞ ‚<:¾R¿÷ T`Þéë«ú½ƒ3ßû }ýñAaÜ«ß[]·Z%éðŸÏyƽðo¿.{]„&~1îíÀ¸Wcà4è©§øí“¸lÛÃîèM­ö—í[\t1Sîsjlé%ÙË`ö×sgˆ!NÓd Pó4›k ¼¦ÉBé¥&-þRz‘x]zkòèè›e„Yj,7 ZL>>ãcZ³Z ÁÌãÎ' 6ÀpÆ~'gKe¯'”dË66@M=bg©·ôZ˜ùºB¡ÅÎz O»Ð*ëuQ犸ð÷!¨UÁç~ÂÀ'õÚEæ´n&E€9/8gÖ¦éz¶40%Çʼnùþ8B‰»óìR–Ëî<“ãâÄ¿ëàgØUV5 ¾1Ð/]X×jÍ Lðè -Žº_Íè$þƒ‘" ÈÕœ8uN7t=Ê]=½«†i`äßñõç}7—æ¦Í©¨·|ù@—áÇïl²¦YÁuÚ#ŸY¹‘aö˜TÁ­§GF ppOwÛÖlfŽ[ ’d|xS/Ñ•K3„ÅGeë 0~ïaë…>ºÿ…­4Îû­W“¿Œ´ð7ìÚ:.2 AZ çýNÂklÎû[7’GÇxñ“ñ­Ö9cíŒoB䨓Evé¦`@vÁἈ‡V à¡MäÑØ/ãÄCjúj‚.Ÿå0.,Á©J›1_ò~ÉX«éÊ:²©¼“3«uš¶A>1cÍy-cmJÆZ‚Ø®ÌC›ŒÕlšé¿½ÎŒ5«ïrŒ5E‘øì Y%“¥LÁ·/Aì=ô°êHÁ:žÊMÒþt§Ospñ)û[ŸŠ™}A÷Ÿk~ýßÝ »¶ú35Ùéz-W‚ü… Ö‘Q|œVö€îVãDÝý†eîù1v1ëšrrgAüó\¨Ú²š÷3.›h'‚|A–1+!ã¢SÛ°°‘¯ôéñ‰aµ'«­gVÕHozKëRÜ[›¸o¾Þ™¹hfµ*)éï|’RGÕ`“è‹y,7‚ŒNZmӬȋîÖ ÔÅɃ~Ò‚)ç~™y–™ƒ ƒ*%Ýw¬ûz*Ù–®©O¥XS‚ š7:l/¥Ö]#ŸRN÷ó:ƒ%užTmͼ€nJBÃ}4#ÖuÝÖŽæ ®1ðŽ\@|”ñ,E·”¿þ¿}ï6À¼\³eÂÀ'/=µcbó¼“ë“zV‡›Š\K3¿È`oBÃ]hR8ËH¥[=ù¯ãCØvÓ=mÕLr#À÷a/Tâ¦ÅÞ´XG'P³?þëÁ´5tÙÄðöõÕØ…O§ ©8Þ{øw8è,Wæ$"G8ÚãM™­a¦Žˆq§@»™6§á¬’P°C±³.Ͽ추]C~c©´Ê´è?óÂ=î<-l›Q~ôxD^ íH3ö‚´^Íñ-P МPìl ‹…ßX™ßX’G3ܶŽ(hOa²È4RÑŒ&ûÝ4RàÓH+–Ħ‘ÉëÂ4Ò‰idòº0Tæ…M#“×…i¤ª©idòúPкËJ«lÄv§I|awj=ò°Ýéx{¶;U4ÌÞ~µ; '×ø/v§‚üÆ_ìNÃ7¾°;µ^ËØî4‰/ìNí+Äv§I|awjØî4‰/ìNí»Æv§ILKRiPÐnŒ™íìaœ`?f®7޹ÞnjöY¨Ù—Y]ôMÚП÷ÆQÜC)%¡:ÿý¢t÷RYÓ®ŒS Ê(ÕB³l§|ÞÂ8;®4ìÁ~‰{AI7iÑjÁÀ˜tä¾¹±·MÅ2ÐT$!ý¿vÏ98hVd‹™¬0=o–y=g¥ºQh=/‚ä ~`äîÅb³dÍê•äí"¥àæ´N÷ψ<󑈼$ùKD^˜’¿Dä…ï&!²§p†L2ç•óüA™À_öŽ/Ã&åø¼ gØÌ”F€Wá ›òë£o§ŒÊ2J¼}ø‘”µevúuêDc<"àÝ ß™ÖrLÓf®' ||9È^AxóçÀ©ÓOœ:v2|_':âOGäÒcä퀴<=æá䀌.eFƗȪÆÈû²ÕȆ Œ|œ!GœÈdG–®ñ ®W7‘Ï3¤è§åùÚ×›ÓÒÓëm¡Ë¬mÎ{Ÿ'Î[9©bÔF)'úrGS®["`|èqÀ¥¥k‰h9¬»¤rh¥aÓéœm¬Ìi£HS"`+-mx¥éØ,Œ!à—dº›¡oŠ÷yÌmÔmâÔª²¾z|Ÿ5®4ýœM™ªÑ„NüÒqÍ/(亪#oŸ”†¦ËÕiJÜn?‡>È’Z9Æ´©F%óî9T—uÕú¾‚Šm+F€.Ðs©•tíH*•€Àø¼8zà{Ìv‹~)ŽöÑôíƒ/ŒØJÖ‚ãïÝŸix™øƒ"Í?šo&øE*×§vÚ ©\Æ!ðB*w6"B+ÆYéš4ðñ½à± óøøVð¨ˆhÄ«‚G509AàeÁãÔâßøød¹Û*æ¥g¹ÓÀä„åÎé+ÍcVm *O´B|ÖF›Žá>¬×{yâÊWE‹f€ÀS2k:ò‚w51>íFV\ønd ܽ†ó&c"!0úä+fÓ4n|Åþ¾E^»JÞ¸ñKDÄÆ,Œ8õCJЈñ ±šQ^iÈíÝÍ_› ¶¦`RÁR¦Cø„ûæügËžYè#ûq瓽é!(“ ÚˆÌTÌCàso®15%›qBÒ&Wô2{“ñPÚVƘ0…µø†@¶-¬)u ¤aÂðǶ RïfœVÊ9¼»|ª¿spüŒ?£F iìZ¦õæÃÒ±\G ñ™FHÐÈÒÀÛW,©|†n—&ýxNÐËD'/ãTµ‘F/Â…£u£· ÿãï…£J!`ôi]¦~×wÔÀû/úŽ>³Ä*±2½w}GDŠ6RÓ§5Ÿ&N|=ŽfèÚ…iÁ‹yey5Aà^«f´¶SO¦–§¤¦Ãkpûh3"O™Ì¼#`e‹¶4parPÍ0·ýQó Úº4Î&>ì´er[Ó9g‚,sW-hYå? dV¯V×2ëV|Ák^Ç~§=èÿÓ éy£;ý0EÍ2ïºGCÿî{‡tîrï ½¥ µh&oÑŽôº+\‘’ו(ÑûÜb€´„B†ÛMuqµjy™pëºFÈò ·:’Íy/‡ºD«ãöHVjdQÖ -Ñ|F?€úÈ#¹ä:ônò [Å +Û¼§ãó‚l˜f„Œ>›Î8/ÚÌ4á1cÔz¾Í’i=¯õZb=BîMƙϚ0ƒª¼èk:f9´åCS“ÑLe#wAåÌßøÔm§}˜KüF@«(¬¹™2Õi“ã1_{\»D³_¯.Ë!ß 7ëDw̘¥ ´Bâ˜ÅuIv¥”uÚ!wÒß̳kÔ-kµ‹Yh[ˆ£=Ù_;땬:*ÕˆŸïÒ/^±ØT÷cKj‚w_²‘<»ðºÌòfõ—wùð<@žÄÀ"uD¶ dq±«ù·U6ÈÓAh!ËyfÈ:âçŽô)þy"k5òlD3Û{­ 0½= 0½á†ÕÔ.";‘ŒµE]û?’v®ÌAÛVïœþ-:¶Yút|®]§|iØpÒ.3äñ–³­mÚVfK=B`hkÓÁ¿»Æ×#Ò.'û—yíÕ4n³9öy¨«Yèó=儜9ÖÕÚôõ˜¶h«½|ø\³zÓÔÖèjþn•„N‹h(ªžæ½«£=iç³ñÖ“`df2_1  ÿÙYiü[ŒØÍÜuB¶—ÜÞü轲NEÈèš+8Žï¯ÔXÌU0yà%5V¾„óþBÅ 5^Qc©t¬Z¼¤ÆRL —¹¤Æê‰F|ÂjGk6C&HÆÚÖg(bH2aí«ðuì|\²… ŒÎ‹ZŠœ0QA` šê¨1•K§ƒ½x?+jÑVS1ÙCàãStaKŽ õ±züƒú+²²Žo‡èß1ëý¹àdT¢k pomÝu{ôˆ„’¼C­Kçá‰eábêšA«µ+hÖÚ$TÑ•Ý{â¾°ç§ FÇ9㢠†2îtãm´b†B[k^¶è7>ý‰œæN ¤¢¡MÑ£_û1ëç±¥yÞ«\ú+' ^¾…˜E᛹ŽkGíãG{V.Ôãejùv•ѳ½§þgûÚ…«& ÕÁÖâÇŒ0µZ¨iÉ¥‰oI3IÜ[ÛLu‡±X½í£¤¥w ï¥Èšïp ¨<0¯^4àhpÛiÝ®i;ÏEË!0‡6µÏ.û´¥ãØsôŸ»óY:’us“‘©hÄØ} ê|:ð¹®9úï½Â‚†T˜àyGÊ¢GnÉmqŒ¥!“ï­A'ú0³wDß3{:®G)…]}£¤±å 6½&%Þ¿SÒPïZÄ÷ï”4#ž%ÃŒx[ư£À6½æ)Ñõ&ÙO”-€UJ ßúõKß±¿²Û{Ѻ °¼Ï¹ÂħíEeÛ.ÉU¿hÿ+‰Ï¿Û¢p/ÓÔ´#µ00FÙŒíÌ.º\¥ƒ[ôè;Öêô¿1ã5¯W òŸÙ6âvÅVf-a}‘͘ "´mõdd-s’MaÂááþ×)~»Ý§”bI»_»ïCÁµÞ!Çœ¥…w§ š¶¥×)ìËôtÌ{^¶>šGjÚ–ÆQº›ok…%wCw2$¤U·U1û y¤)LZGa⣨ûéë“OhÄÇ•Š.EÌIž#d|)b>¶Ø& Óãþ[ÕP8OAÕÐ9Ñ•Ÿø;ÑÕ8 `*È_U³^B`|É_UúÄó=¬'üU$ìYñž&>á¯Ò® ztrÅ_5-azbЃsÂ_5â߸¥‰ÿûkù«¬¿a¾§zª!ð}ÅK'/Þ¿ØIvÁÇ%?õ¸)Ûûœ ”uþHýê¯íT4ÜFüÛˆˆ™½ZiUЇ®„Àè4QKˆdÌ×^Üq‰µ½"Ü^&7äR»1øúl™+mËœö•…¬‚%¾NÒÓNüƒ b” ƒÀç¦\{XŲPÌVL’m¶@_‚‰zu\> “ޏ»CÇÞÙ¢[ÕB'•Aà´(¹h‚«¢ÍÇ%dï€Û’MQëÎËF¥ó¼Î¬…@»÷ýs6c³ƒÞL…aäDþs&{Í1$º o6zO”8):O¢)Ïöøù$±]ÕÔ¢‘#‡@Xî|Ðy’”Ï©~#Œ¯€E±®›Âhh Ó_§j*4âcçãÜ8¹7!ÔtnÙZ­B‡ ì¨({ås Ý™·]³¥X—¶ã4]¨ß|»3oÌyýR¹,u3 éyïq–?ô™Ø5LäÅ€&üg§ÏtNa ›ä*ó´FÈ›×áI ÏlÊ[Þ/m‘Î)BFÀÃîã\òFÑ”û:…Ç&1 jÛH°Hã|6¢D“îHAä†tò¦Ë¸de—Í%šLëcØ–óÌ5@ë©ò¬/ýBÜYï"Ü1êŸà›Âøêb 1t4thÉ6W¤paŒ©óm×AùÚ! §ý4íƒ ðñ)5Ð"© Œ.)“[i(Xýùþˆ¿Wu…Ìóã×^ 'etj+£kCÝãþ½Œn£ó¶TXâ „“ÏÛR}åÙãqÐ4uÉZýÇv§Â;³mUi uUL,úwÊ¥…ÀžKv«2 ܓٟä üV–!Öé/÷ÍD|å¿ÅÀ¶h`ÙÀ” Û@²«Ìüos¨ôôØnC£¯"á7/ª”"…ð:]…ØJQwl7ÃZô©p¾ÿu£6-£gpéV" ¸î£nÏgëÓ¡I}È$_ÃåŠ3==Øg+B&[×ðÄôÏô[ i+h2—ˆSQêßxýx¢+ÿÔ]{Óª`¤U¥L›œ@fõ,†¨}ñà·Påö6Ëì|Yèœ =ñ¸š·íLÛŒÊÒ±-œ/· ¼lS­i*Å}Äô,Gdæï© ×f±èMËØÛÝÁÆèB·½‡™ÆÌÝ=õ'Ñéh 9ŬŒaLétÆ…t,ç> âZÿþI·íѰ?®YÕ@`ä™6Pï|öŽP\ëÏŸãElK2o…P¸ÊU-Ú´×ÖªX׬A€œ;V ì´¹®%Æ;wáôSs)r%‡Éï ¸âüÏV¿8ÑÞÌÔÜOé„ý@—Å6b.‹IÏ}; Wœ‡2c=9¨Ì8‰¯ÊŒ\í4³¶@Òl)U¹-3ÅôÇn}p …|ð Þ"Ñ ÉqyYw ©M"Ûà˜&g7xU¸êë(« ðìO‡Ir)3<âN7iX$mû¦Žr:IQ%ÉA ú´cÍHAUÕV¾ ·(8×g5¡ƒ¯yM’ƒèdéü)“c¡ê|‚@$:éœC5ÐQo, ÑÉÜ¥£­B†Z|É}’ žø­wÉXT]Z莀Ï)¼ÄÒ&S1‰®øÚÕ)af*ÛÕW% j Oý¹n€Lp™‰M8"Ñb®4”ðA¶lvdòüä7s×ýBÕ‚ _„–Bt°$ð4ýË‘cº ¹âØdI4ðñ]–¤ðZ–¤ñ‹üù8Ê’¸ê_ý­Õ’eU6B ”% j#|˜Ö´(k„²$tï-ËóÌ x`òI§:nÏ>¿Pßû·N¾SßsŸ×x&ß©ï÷õ˜\ôYj7õYQ¤ó/Ÿ xâÏMÝÓ²Wè=P6tÌ݆¶+ôeÑŽjОï_dÑ·~ÿ"‹†ñUÖ² YË×Ç–â¸mõÞCó¹ï½CµëÀ>¡Éþæ"`‰]'“CªH(z}ds¼Ž6“j-g²¬Å‘­":ŽÌ{ŒaÓ¨ãì˜Ö±Ÿ×ÙWµ½¢#£«÷1u¯Á± Æü1ió ]-ËaèÚÆÙÌ+þ|ôë #,dkùÆI­]í ª€`ÌÿíÌ»Vá—lmý 3”w±ôo•%f“†êÍÔç“¡¼ Ò©Ÿ‘N½>¾ëÔWžÎé Úò©Sï‹ú¡j Ò©Ÿ‘N½^èÔó SïW:õ­×©÷Ào:õ-~Ó©Ÿ ð\§¾Ýuê=ð„¶zF:õaÂOtêû¦gM¿Ò¢BÈo:õh‚®tê³ S':õ­1¼â×ãJ§¾E:õy¢Sß"ú€<Ñ©çH§> Otê9Ò©ÈúéÔä‰N}‹têÃZ?Ñ©çH§> aÏóX-©YIž«ä•œÚvù¶ZVù4Ðà †fo¡ÕU -9(݆æÕ1ª]Ùq…À;ä ±"+Ò©í²Ê¼Cg€s¥£ çvkx™IW°uõiW‚ O?¦^;;ÖvÇRî&Q %ætmÊ#PjíÌùT¯CÓ #šðŸiŽîÍ|:–Ñfh‰€È.Jj;†´/ë Ž2‚œRöékMøDæÊ—Èý?aW¶,©ªDi[“åãy¿qÎ'àˆ8‹ŠÑ_AHÌ´´vDï~Z%"世CÞ’[º/‘2#Ê›&dÑÜ÷dݪñÍÂÏm§¶“‰ ŸžwÝ2™nÌšyÞNËâ?Þ×.÷½!·„ùÆš»­`³ö• 2ÄHû;ÓY +š4!È7BºŒb?MFô$…&\‡Üùá‹Ì}¼F¢‘e³jÈ*9¹o½‘R›3Íéù¨WIx"C‡< ;ûá§™³³mŒ»øþ•mC`àUú¹/HÍé"}#0ðvú™h÷߈DšÎ#X/»HÓÑzZb½DÁ…õb–[/Qpa½iCl½D»ww°M¾l]bæÞvtejË…XÑ•¿¬ÀèÊ ÔNN‹­Àè7+p Àç§ü¯–ª×Ö´ua½>²—I—±6³ bÑPtbÕÃÍç-YQ K ,Dïã˃™Ù_õ¦XKVÂ)pír DH¦pÆ.öK á½ÀÀ/S'ðÔÏ_¦ïiœN]ÏxÿT©ç›¿˜ÎÐ(½H)ŽÕ`vn h†¾kqÝû¡/Á_Œ^+s¢½Ô2mw9E!e¶üX$A„üÅ3O}…DÚðC`… …¨{'÷}íC[ÄY]‘J}æLZ1L¦ÿjò TêÑSÏÚºJò0'Ú.³Pjm ÅÛ˜Gþ¶‹QuN»*ÍȈÈH¶=¨ä…Œ³ xx1üAÛ¥^+Á@ÛÅ#ƒ]ðî.^ˆI&äW·½Ú¤pé(•qµôYÏè˜6ÎYaëpTÚ>æ‰9äãS/¦vz1@oéDÛ…oÇ@Êd?ŽjnÉ·Fò?­²Œ5³4«óen¡È!C„´‹d\ÛÞMJ‘žp1ÎÁL§¬*æ|b ‡Œ€Ò]_$ª–­LVpö¢ú´?n{¸ú´©«Tễÿ“S\w 4èë§]QÃFÌoŠDâ?³èÈàË •!O* *±É;µG£Ïµ£ ÆÎ{s—ÙE®ÁJq™ÞJ |\ÐÎWÚ±[#øÁª»¶íô×T%{Õu^ÒÎw@Æ|§7õi^ÑÎL¬dÄ'%ý²í+úŽï—Å þj`p•%5¤_|ÍýÔí¦;’~kS€hçi:µ¦éÔÑÎ{v0'{aL ª±j|^ç]a ÚùOÒ¯–뻎üÆðœô«hšŒàûS¯ É hà턵ÂÀ/2k‹÷ë‡u¼ÿ’¢ ÀÛ‰ª}‰Uí5ÂuR-¦ vªé‹:)ÇOü< K ªo$XȺë9Õ4¹S¨¬*¥—±“hGTÿÙmÆmþHÉΤ[Uû Èü’%©;FF|ì=®Ülk#ˆãªKȈÏSz@¹ÑVøº2bFcèm*Û2¾eöÚLÛ±I«0ð½_ñ[ò±Øj>äÄY+G Œö"ÚMã¨ØªH´·Ï!Ÿ þƒ‘–J@#Û®©²28•„»$œGÞP†ßÊœn|E†Âº cÞ/¤Þ¸7¹½µ-fêbfú4]מ¥ ÝRklÚiáå˜ætnú…Žù:‘K°|œG†{õ©“‹)ç¡Qµ¾urºß§Bsé.4ç‘щÐ\Š…æü^ÿ9šK±ÐœG'BsšóÈÛ‰(\‹Eá<ò~Áç¼Oü„ßYWG…¿ñð ¼Ö‚YG8-߇ºÿÂõ*¥ª”Ú1‰³oˆAÂ.‘RŽ‹ ïg×|¡¯y±_óot)Ÿ¨Ë¬ãˆÏku™•_×ê2þR~ï)¹ÏÔæÊ•Ÿ:ú•ð…o¼[SŸ¢ F²Û›i‡)+{Ã]0Í߯s¶6"OÀ@ä¾4Yš–LÊ$­Ièfü»çJxY7UÍSCÍw\÷ïÒ¯…Ê’rIaƒÛ…’ÙµFÉ,s©MÜ›jrhÍ]›5YDÝÀ‚·]Élã¯a‡¡BS*ɈáYèD%úX[“sÜÏB'[DD!2Þ>Ú„ÚzŸ³¯•Ìb°0‚ûw%36Kpÿ®dÖÃwÜ‘’™¹!àÍ˧y¨†4åÒØÙ¸¤R øþìØÖÀT›V“ õ:`„PU*Òyf›È‚{ >PÛMG¤Á§‘Ë€šB|¼Ðà[f.ýŠ?^Ÿ®è´ƒÖçqLóûЇԜû»k±@Ÿº [ódÔWþ#S¿N•ÆfÈXž¸h°†W<®+᩟¿ð¸r‰·+ï/—`mï”ÏŸ¾7¾š’xûl3U¨,8P>Çð,åÚ–ób°<ïO ½ǹd3ÂI|0ĹT“2™€÷s`)‡ðAÒª¶ eì‹uD-1ð¹§=àaø,gm% '7ä€/”Iq4û|žçba…è10¼f…`ø¾–@Ûà€Ñp™‹UÿHòCœµ?Jk¡–ª/Û¦çŠ ƒ]”6wls’ʾ2'>ÈBÚd{ÙvªkÊQoa‚¼ï‰ ÅÔ“§™sJòä6‰³ñÓ¥¹Äð±§®.Ç™Žù¼”w©K8‚¢ yAå]ÌÝMä]&*ï în*ïRSy— ˆ~“w™1ð‹¼ ˜±;w÷AÞ¥¦ò.çîö/Ü}bÕR ïx"O}.ïR#y—ÀswŸÉ»Lj-\ì+8áî>Æ¢ÝÜ·Ÿï±h1ˆ»û4 Aëàöó5ö¥SwæßÒГ$P51ðLM³8òÔà–í ç*޵¹™­ïTLÌEÓÊ‘¥RøØŸsW«º)Ã!øœ>ï\a=Z“Jål…Æ(|!£8s¹ûjX*s”“©Ã³3kòÖóm§-ø c‹x$¸ÜU8`ôY6¥ %Æ™â#üÆÛ·èE®VÇE jóÿüõ*[®ÛÜLûˆwĬH€l»Â¸ã|nT›AdÝø yÝgqꎊÛA¢Ù¿nö£L®E < x=€zp«áÿó1uÅT‹{uyºU:»²R5ŠîwÌ/~&E0¤9¾<ú&¨l4ý0<^r…!–0õ2‹dN1•{®FÓä‘ uWa`tÁç¶Î@ü`~qS‡¾Ÿ¹&°TÎ)°^˜_Ü:§)꘸½hýÆê«kQ%CE´ÈôÌ„4•[>†Šh‘Ïù]ýÕôþ…ßuh1ð„ß•S~×`g;¾àw¥#žð»rÊï ¶cêŽ ”ß5¸!~Ït³š¦Ž$‡`íúaDëÞLf Võ›iÚEûn“߃ϚÌmKhàÄ4’o¨èÐZ½e’4ÍÌbåzMÄë/;îªÊõ5Å0ðñi¯ G”;0!êiî œ²æx»"Y)1ðþI‘),E¦ð ¾R;Ó=Íô÷ÈÒ²÷ŠP`W~mšðïnjQ°ZfgÀ®ü>Oi<™ŒYÌÈÃØ@ùvÙä.›7¹dk#[òÃOFmŒÚ°àáÇnÉR0jWxûdÔÀ¨-0ð~ͨ VÚ=ür†FmAF|^¾kŸýB‡ÚZ:ÔOèPС ¼ïVHšÝg²ÑùTÃW‘m¶QE„E3Ì-K ðæ©É¶¾i¶´½þpV^¸åÁ<…˜x±èª¤O×Rp„§ð%/ÝNŠxÈ´ÑW­®2-xüxú çï®ÝÌ×vn]9N€y ÿ8÷Âޔˌ'´b 2iÈ¥¾\›q¨ÉüZºË pÁ½ãØØc`H€ÜçqóBm÷S×uéKÌSø lšÈþaä˜)ÇlžÂ-àïôp˸Vu¡|×^žBÓôm/X¾-e›U.b‚ÜÛÃhn§ÆÐP'9E>PZÏih·²(š¥Y2²˜Öäüwq´.Ûïì+»µå Ù®&ÆÉØg—É8—ùRç%A† ª¼¥Ë¬E¥ýÎŽó| ëùñ,qA©2VÍeÂGŠŒÈí¡´I•Å9ËÈ^ÿAµ¼¥M*ò²›V סì<…‹‘2ú/óeXE=5¡z¤H®²ÎtwóÜjûK¥yÇ-W¡ÛÍSC*9A>0rcéÚ¹êŽÈ½æ8‡Bü¸×®`: G‹ÈAn10¥×>ïÛQ‘ýyÛkŽòR9›V¤ã˜ïSdÏÒ\ž=ºBN¢$‡Âý[yƒmÁª»6Kô§DƼ»®®?ˆY\ÛW†3B4°çÚÕå“)Ò„¢ú¾?qIþû?Gvo—5iÖ¾—à`>>‚2Ef‹Õ†¤SÅ\zàí`~ZÏK¢¯ëÃÀº¥6mÚÇy‡wDurC¢†jæy‹Ý–N]”ÐL]5u©8>žkI6#¦Ý¬’_'µ'M_j­&˜ú~¬Ètêò†&L¿›ªxÃ@î*—²xUÙR½Åû®`S¹TéáÎElt´¶v}´ðx¯ó1³ÎÈ¥J ¼‘/ÖF0Ì›‰t #Þs³»·ï++&Þ<öК¥Àqmje[k³[Ôû¾x"HhÔF(k®ýëÞCkz%7ŸdPÚ˜¥ÕÒT¾`VÐj³@×i)“²®1ðž’iÒþô’d! g¡^õͰho†,øFºæ«j]‘åþÌG¡5×·ÕÚz }˜öŒ<ŽkûÇUëÃìÚÏYÓ™äqLí¿³Nêz)K‚| dévFµÎù’–ÞÒ@¡µ¿Ð+À Ç[U¯Ú³XÒÆ>ÿüuÌÀŽ7BÃF –gÀÇ oŸä™¶¿ñ~=5Äâ'æùÔc_¦¦Àûg7K»ùĉyÖÍ_AavðxM&ËÄ:Ñ·tJ¹§SÑ—tJ…Ò)ˆ\Ÿ'ÉË*æq%Àçî¼e®­Õd šqÌ9y˜×U¹³èÀÁ|D¿¤SÀQDŸéçA±Wœ +Fg]芙²Zp«%æY:¥àÞ°[ Np·Îï œónA™Ìúþe<.|*Ö4˜÷‹aÖC)ĘŸÁEKýÊ}˜ï¹¡²ðvn،ư‡¹#"]“¾“&e'Ï [cdâ¨ìäù­ì$1e'ÞqxÂ’›Ú˜˜É,‘ø8å‚0S œæ€OOriÜ!ÛÊ*Æ¡eãßh ¦¶6Qp.ù˜ i^²ŠLM ¦\°~Uþº@½,Ø™}ÐC®ªâiÁÚo§t¤²êùü^0¥ü:>¿L †^LMœ<ÌëôÍ”ú6nÀW|¢k[¤–“Ê›ÊAÿ#OýÆ@[xf€SÑNPúܯíÏw‰D 2õN…µk’R¶H“ûÝ~5Úyê§ÆM ÿýû+ÉåÂ*L½\…sjRÕH9ϳ3oÒ™™ø– ×péË=7ã p`¼"SûÎLæ[6\¯gKã󚬂Œ˜yð”¬ÏŸÑ²>ƒrÉWtÑï‹ Ü+ +‚„Zð·"HXðð“xÙænÔ8³Q;-Pˆƒ( í²e…7gÜt ¶Êi¸!ª¹°dK›mÆõˆc<ÆÚ»O0ð) °×'EƗ届޿ż ,TÏÓT`àó3y ¯’<@¤‡çɸéáyòÞux» å rÐë•&ˆñ(]N ÄAo „®G&šÙP{:à“vX‘îÑBqß=øÄ ÇAù¨Ý>ÙJ D–OnIÍùhxÍÕ:V>ÎriÛV¬èG |žåÒxUé-D;éánØo†‹JÛ¥ — .Cóf¬äYa9Èç~TÞ?êœ{oˆé;‘•·YîMÍl]ZmËfx#ähÎŒC‘ M9`à]qÈâDÕ=ß'|Ö1s‘®"—lì笟0ð‰˜MÜ‰Ûæ‹*X=ùwýþÔ/µ…²c¢ei#Fµc»2…®k¼=b½”Òê L2‰eÌ›<Ã@¬—RÚ’=µàbÐFTó&É¿q{ñ‰€ŽÃBãv5scà‹0~ÙÆMÙ,MÏk‡!:¹IfY¿f,o0ðšEÉ\ªÆ¸”r…¬mñÃ8ͽâV*Ë:Ž¡n.Œâ‡[hz«Ëo“v-ÛXÇöD£+Å1—ëRnZ<ò†æG2“]=eäÁƒûÉ ²ÖîJÙ6äíØ­)í·XeíÔUË,ézâm»ÏMgR–˜j2‚DU0Ûr‰×µH2ô¾R’ûUbI#[1Œ¹·^'ö m¦€©llZºò­ÅIîgWlXF§SmÝz\c‹ÙqJ»‰%Ýq–nùç?¸@7rõ.7wþ‹Dª­Åyjƒ;vž×sÓ­ä4ÙöŽ ÈÓõE“tk™Ðb‹  «Çéå®"‘rJkú;÷¢‚ˆeû£k9wÍBá^éì8Nʪș™Þ7uΉüù¬­_±þþ94ç^$Yõi:ÖˆzE™ Ww¡·œ”,®UŽh;6“1/û!eV{ÿê‚AXДX«1+¥Ž¾púß~A8jhçCšþ7P“þoÒ¸¹ðý©"œv tå¿qå’MØâ¼ºý?aW¶$-ÊD_©ËÚ/çþÿ"fEQ7Œyú„ÄL«ìéèËP²&¹œ#íÍcm»’ øÊà ûgÖÖ\Ò‹›éuTXu—'•±“Ø—MÉé$&_·¹íp!?ó‚iž‚U¹õÞäKÕ$&J ‹më½™GE¿è¾‡¶òÀdGÓ(‘™”þÎуÕ6iS¬&Èçža,yûEýXö•Eæü‚ù‚íd{¶ ²ä!½;ÏÿÎŒÙ7Yë?„3òHĪû¹"¿3¹ )¨Ò«.•Kò;ôvOË6ž³–E^?‘nŽæ:ÍÈÑJ „'N˾Y4YKÉ•€d^3]N+=’¯ú#õêä”!Áà…ÊÙ?ߘK!ÁT%¿¿1s0ÕwÂã¯oL¶JÒâéS p¯#ÂãooÌBÑßxÿÂYí wÎêËëúœÕÐ@„Çß9«)H1šr©º2‡ÿ <Ž@Ñ2]•„öò:£ºó‘¢‚§#&<þì!÷:ˆ©Ä|9ÌKWÌ5”f¼ž‡ûìåZ.E_ò5m0:{·EžN5iÇã"Ò„ .îz˜Ý;9¸ ^Oê'<Û•´xGïj€+ØîZ… ¬BfvÅkY›¾Å@œÂmVŸ=>K»f5¾¢c01ëuèÊÞî¤ë÷·“²šô”­! ø!Ý(|ùÓ$Ó‘gCFÑ b™Ø‚ ¥EÚáØ ØûÂìpY…mÓH{GUPtñBìpÞÈ*mM7±™Û5”Ó…qÃÎþY8WóÈ =Òy„ ‘d§G:‘JÄï­Anß™ [ƒˆ £bëÖ¦¿K›‚Õy~XEŒæò°Œ.!iËÕû­+œˆý¨' £ kýçPºãe ÓM‹ ³™\~‘Û‚ßù:‘Ûª©ÜÖe'l=ÈmÕTn+¯ßDÆj,2vÁÌ®Dd¬¦"c—Ùõ 2VS‘±t]ÿù÷ÏN °ùˆuÕkÐí¸ì°'@æ'³+Òa&j‹\Þ_´!Ç«h]ÞÉ ç»}$”™¬zà1Ád¨›ìv{»l­šrž‹@†zy_2z@a¥&Gå>D× !CõœÕÂSQkµÚ%Ì®¸'¡FÛÛ=¸Ê™ò\îñ®èQ±¿Q5¼fUƒ¸¿¹/å•™$[{ÓjÒ5Ò9iwz•µ}ÌdøWàÆ%œŠµC(ñ/ﳂ_%5 ‡lº7-øÝëxC°=Öñ¾)¥Úgy.Ô”¾iÁïGT>–ç¾qÁïß¡fÛ»°ìo4*: ¼ŸW݉|œWÝj|~-Qµó8ÄÕ÷ á`{WóºZ†È{Ooø^  ¡ß÷ÊI}¨–¤ÉË<ø5γ|®ìq /“7M„Ø’Ô¼dÑÒ—lX5_Àcßv¥h”(r‚|!§Bä;?3¹y'È7¹!¼>†»!Š´o2Ðwº°Ûž ogÈ&§£” xCÎãs=ííÌՀܳ‰‚7v[ue%mÿdÿ&ÏÏ" »æE»uC‘/T¥EAr˜r“N #È7V-ƒè˜Ï“}a’Uwýßå&´šK1/õ ÞØ€¼ d /µ²uì 2‰þШ÷èöæ‰a {ózÅ2/¸T¹Œ²"ãy½i‹fóœ•Ù®®È;*¯ªÆL«YƬ݀|ìG§KÅq{8ï:#tZC©ùûyÌ{à˜JkàjVdˆKöƒKÃ>È ¯r¸º`Öpg…ò<°Fö}UYßPàí“ìµ(æN;VXÒõ¿Ø½¹ÚÒÚÍJ[||& ŠQq—¿6øÄ™R­i–¶;kxL )vƒÒ#KM4WŸ{¡È_›K}{X Ú\9¹!-†Ä?›£"DRÛ¹ìxoG.ÔISØs9»Ruí>^û/ª=S)Ò¹ž¦œ/£ý~}uˆÍ6Ufæ–GþÂ7Š®‘¤O;{ötmñŽù =°ÌØ\fË>‡{t-’»ËMi—ÈÔJï]žñ_’Žë€E“5¾¹›¢]àœåYŠïý62è_0c÷wýcÐWøƒ~·¯|´fã£5x§4ö!×½¨uSC"Îû}T¿Á4ö2ÒØàó„¶¶_˜"]¿NI쇌|õ›RÑnO·Š¶ù¾hê;3=0s½÷ÀÞ`¶á”`ö½ö޳ÌÌÊ• ¯G¶ûÊ ÏÃhO‹† oŸÌô\°N®)0ÓòU˹à>3­éæ©Ì²±í2ýñmúàùÌJký·YK˜m, ‹¢oú1—+ý¯O±}4cêäççL£Z øuìÄï-|RUð:ÛE.ôÀC¬#!ìëðØóÉÚ‹bÒ´!·1Aôâ!Ùο¦ìX3Á@ò“kò½Š‡˜Æ²êWV…ÄüÓ‹Cñþ¶)2¶NȨ"-îÜ`îÈ(<§§ËY´7Έwlzc}Òy£–t2 ÷È–÷I¹;l*Z5/sHü Àç°Úî°íÑì®ï¬ cÆÈÖvlØÉEÞçMïÝåá´R²­©l¹dÀö(0yY£ÚŽy–… 4@"½˜"¶)ëZª6¥m&ûU†+íÓŠ•ËÂɇ_b*4‹DyÆJÇ(±’i¼ì›Gî‹8ë[ûÚ¥mÞ!Ü»yL ÿ¼ÏêR¶mKæÇ?(Ì_ž¦ÔQ‘rÝ—uÍhïÏÈgá½¶Tì¾gc–5âð;C½Ñ_Þ( *¯–„׉¨º\QT±%ñô³}ªäñ‹®$ó¸)Œ¦ÀäÓ°ã]n˜[^cà•¤³ M‘ZbàíÓ´ÛmžKi‹÷H’ïúm"SÛ»ÂÀÇa÷ˆ¸{VÓbàós÷tSתfÉòÕqS8³[lWJÚÊu±'pO>æ}¶Ô—…àNTá—z—úئŒ /ŸK½ìKºÔ¯TŠÙGÝZlÇ3[WA†Òo gógÎYR†eiì°çÒ××þë}µG5Å”ä.r–m³ãó ë’MSÈÕ¤· þq®>$‹œÛ'‡zúE~Sl3´ H¹/2iVkUSä mŸhö3#%«ßþþƃ¬rÉ—¥œÈZÿÁ¶ H «|é…ÊÉBJ¾PO¯«ÂzÇÉÏíw½ãY x®wv&ÿ êðÆ!#‚Ð_>‰$¼w°Žº®Œ]°-.Ûøm”ZÛaç,Žî“j.”Ì ÆŒgO0À¼X²™o˜.z‹íâ;Nº¾Fzs#û™IP ÀXiˆ;½x‚äƒ=2 ð‰JR &´ÃÓVÍ(W2EZõ•Ä@\²„݈çñ™:ödëÆ©Ù£ åØÂ0ðMÅâo¬ìo,è€ÿœ¨9º‚@>iFè¶r·l¤z”c^ƒPZòó:† ÂU"eÚªu©c‹4aÖ›‹¡ÀßÔlCJLòCf·xtéFÔ­js¼¥è~‚ñyÿš{ +؇»¾ÂV£´ŒJ_M=tZŒyÎñËå¬ÌU¡§ÉßH KOÎcOq!óêaЫ9þxïC‹Cª­‚$ArI>»ÉѶkÎ÷®iq'ìT@ئðr=!ìT@ØI€4w|s“Ú•“.YÕ#¢œçèv­‘ÓT)lÃË!ŠÈ#¯W#8wŸ]aàý“+TW¨ÄÀÇ9Wh(œMv‘ƒ®PE~ãëó½hœ¼‘"$ö„Ý¥U-V.CNor¹ŸJ¥,Ù’ Êýï’-qÿUQD€ß–™}“eö e}Rª‘¼B$Ž’ÛIt2ˆä@R:y[ª&­H×»¼B9lÔ¬Ê435ù˜]#ÛÅ.=ZÝ«1­kb¬€¼@T¾óâ¬CÑ/1; ¦œæ%Ô4×Y=WáøI’C†6y•†²$¡î* ìy.sÒâõ;p)ŒhH‹;-6ßê®Ý9Uj)JC -ïñ ï+¹Ý{N+£´I» xIú Ä>·+'&VŽøÄÀ*ÜIcé´Ó—_àö1¼²Ày&À7ng@ÚŽe—ÇÌwðœN飰škÖ3-ÁU–$‡jÇj¼ýJ‹4E¾Tf&È=¼@ö'¤KÏùϾ»«¶Û"»B/ù¢Ù$K‚Üc«¼ˆ¶E±4²è‚â ï´Xi#Ûà)+…}~§ùøD–Y1AOŒô.‘ ½°+žŽÒ b–`ïnÅWL­#ës‚|Gö¹ôd­ÿ|C.¬å#ë(òòÙYäLzO’ Þ ¿ÓúN âß-&– Ñ2òí>þjóË \3Öe¿ðîðEw/)|Ü©k;{™õ¬j òqDVÂÂD»Ø¯£'ʽr™@tdYg’¶ùúЬæ1_R²’}üûÙöcŸ–ä‹|üûÙ-£b)ù× Fú¸ û|ä}Mæèš|EÚ‡r»Ðñ¼^¿"íáiM‘·¯ÈζÉÚû}÷ ð*«õšj¦{NvÜ5R±²HÚšCÎÇJ®+A>#²È·i·×y]ËAæã ò¤­ÌÙ—Û)ÛƒµwÖž‘3äúŽÈ"'ƒmÓ•äÈžÌûíçÙ[dªÞ““ûv+q(Êì;—KßdÍ߈Y3Á*‹ltÚkM¾èv…ÛŸùJærk³³K$åy‹Á*P_©Ò:5fÃHN°Ûá,žŠyš–c5ð‚ÞnOdïYDnsôÏÿþö³é뫘5 û^†tb@nsôϲ}QPÛÈe&ÕÐŒmó}@:3nY²eh„"'íýç›2¡}!ia0s¯¿^È"úSdÊ÷â~ð`%·ß‹ûµ1ð¼¸_KÒõ/Åýô7ÞÏ,ÞW°˜%þ¢`Q ­Jõß' w]Å0’ÿ9E®’|7 ¿¬ñ1f¯%GÚ9»cuW†A:$ù(¤Ëªªiª5kÀi˜¼ˆ_Ü7Ù¶ 8Íy‘ŒEǦÎfíËo§6l$¿ñ<ûá7†™Ž >€ÅÊw]`­Ø8Oø¿ïŒSw«½Æ1ðuFŠ3 ž÷ÐC¾Êg`•íÆš[¿¦Ss9ãÏ‘RÑ6“3ä²Äãô…âsN­n«² ½·•LMI{¿‘ò¤éá‹N!v È÷—‰È f"'X‚ä_N8Á üJS™­s3Û_r=£©,ÚYO;ûd‚tbþÞDÑ\j§Ü»Ì^Þ´Åë,÷´²v 1=Ù—l<£?ubÐWë}uò_ $»NÌÑÅ(âb¼^|@ :Šru §þ]ÜÄãUƒÇ«ÆÀäK*ÙèSÉot^?]c \cog©d”>ð~î“ø8wòÕϯÌ|¬V»IÔ|gæ‹ëñþëÎÝëã×õ¸BÉm‚”g¾¯GÚâÙz´Ó GÕ®O(Ø\ÔQ°%»üË‘ÞLט‚-Aò/”‚MŒå€(Ø’ëó?(Ø Œ¶Ë¿)Øt)Ø’ë댂-üƆ¿P°¹ 5¢`K®Hp j¡}¶í¦B¤CüïGÿ¶Ìvê°©ºœ,3‰_•¨Ù‡¥€ÓÉÛ¦öZ*­ åCÈÀy"·*²±m¦ylÀ‰Ž… þ„hv`T¬oçº!-"mvxÛ()Œ™TH¿"dêIý­íí 5¬¢ä¨MìÝI›Èye¯Jò; ¾(½E¥ó2×U¯Ø[²;‡N±å#Xè\®ö0+LFZ|íYСê½jž­•6‡R‹ü’.-c,Ëf:´3¼AV[¿×6Õ­ ']£êPªŒ–ýZ”M˜NaüžèY°-*ðaÞ1]Ï_ÿÄÊkgþ[óµm ¢¤æ’ûÈÐŽr0- ˆˆò7íVسz]Új`|!@%òÜC®kÕMË„(JtÑõjñ¬˜Û Ÿ8ÑӿѤLeY,<øà }‰¶2/u¶ÄÀÂý@×åÃêÕ ¥VRvdÀi"FJ£æ^äåi,²ÏŒý'ÈÀBÿ÷æðß3XsÁÌU èièÝ­|Áö¨ÔU=5dÐýûpÔ 2´¢Zøÿ »’%hQ&øJ½/ǹÿ1ó¸¢(*BÌÓÿl…ToߥOÚ"BQU™)Ä8ÔQw=à¦æÒSà¼3©dTJmf‚™Ø±#I:¨E*9NË0#ä=gI榩QÛ\â ¼+zWmàSÚiDé´aÌÆˆ[¿fr=€ {·C.¤œWô?OÇ ¢*Õwš´å òÅ`RQúÄé$•GÈsBút½'1ÍԬ¤ îºËõdSdžËJ¨Áž*4=O×½º ôÊ7G~4Í¥Ó-A\äàß|©ªŽŒU\ƒk2d”Ûb›&î|<­ès;=rd¨«çBäzqåÈ:²í÷eúñ›¡Ã0ð CÇÆÔt@æoÄ›A’/_‰7‰™t}¼:êaþ x›Gà-gZ5‘iU‘ÚMxŒ^-ÿ ¹Öø¹ {®u%÷øøH½®4Z¬9ð‰¨×ѨÁËzÑ€Ò«©“+GSŠI·szìçoFa"O!kŒWF¡]Ú >ÑÉö(˜8Š×'â°¿‘ÛŒDW¼~å¶íóì™qØu¦öäÇÇôý¢r`\¥8ì]‘¦’ö ÿøøJl“ø?¦¶…²)c`ÇVÁì äée¿òeÌ9YX»¦µ+ôˆç#A½6vЮKQ¬f]u÷æOûv&.‰ ˆ÷Ÿr‘ÿb4:ê¢×Û\‘>^É)…kMzZ›ÙL9ðº³hê­(éü’LרxË‚•6| r‘™,XæÀDØõèaKª–±éÅ6 §~¤ Æµ¾„öËYo„«B”9p7Ž­½žug%tISÂüÕc¤®Áàv¦ËÜ ´%è±Öq—o5’§uüvDô_£ˆö‰Zó‘IHÜ^³£>ŠwkÚb—\6—À»½Ú¼FQV8Í‚ß}êÈ‚€ˆÞùVÆÆ¥j!ÙrËz%ÿ‹ ?#{VUtÙ8©ßN¯zzñØ2Zm)ãq;}÷©3Nn´CÀGæ<6~寥t¿90|ˆ~?Qþºª [L7" 2MÊø ¢oR›øíŒÙCÁkÐ)¼×à$`|./êæÀ 4Œ+£=t91&€¢B»’W}tÝ;Ý.È É/¦!Ë$Y)™Ý•ÐS#XH?¼á_5ÅÛ›Ù¿å<Óÿ”ó„ìßígΓõ2½·?å<ÓüCÎÓ(üšó4 ä<ñ­ä<ñð|Èyº$sžó¼]qÙ'ÂͺAJ8³VÁ‰p{E”¿Ý¾$Â]º5O„ßn_á˜'Âo·7þ`”It ±lÒ­ïoÕÞNTv|Fmîê‚DAí÷²p»¨BÔž¹ºæmÍbww=‰ƒICª×AJ"n ¡ËÀ5ÇÀgøç_èó@»#¹XýÇôË´Á2±°v²+.Þ¿t±íî8§ÛãG÷{þö'G²4Ížèpè 3Q ”M\¶] ¨™YË:»§YìNCŒhá››µ¸H%}¸ùØ-W¤ î/ÑôÎ8à`–b€^Èû-h/»Or(Ó¬"š;Fà5sˆ \Ó’ÙlÌL1[s?bÓ›bH{&ÝF^Ôñeö/Áy¦‰ñ™©g5Í8¦œîY+ÅK‰BȵvYµ<½•3“X)ób¥ñÍÜÏØXÖIó²ð¹ ¶>/¯ƒ+åîï»Bœ¸íêÉLÀ<¹_º2ö8äÀ ê/ôñ™ŠÉèiÊ×ÏÀe2 Þv]3n]Ñ.}AVƒ€÷O@€èa{É5ø|¸[Wr°q CÀgV›´ {kY¿CˆÖ”¼tã³p{ïø÷K&üŠtÿr†Õ}÷}´uS…pSØ­ØÎ¤±G¤qÞ‘ãÂFØÜ#ò’÷ÑÆúµEv.˜Ãw¿~FβxEº¤Ã›´£ä?[±týÒà Èûä:€½5 É"’/mI%¾ûó#²_¸½æ†æúá³ •t.Tðå^U6Ô )pïÌV¸ùí­"d9íâk¶f%P»ß^ëq 9n4ê%¹ßÞzIB¾\:_«uK™Ëûíw/I Óî·]’} -"QxKv”£â ì~ô¡—ä¾o´»2BðPí³}'s`à0þýWd—†]Ì©±eƒ+¾×5Ûa¦ÃoæùµßE˜ÒþǨÌ{B†¾2•ÂëºVuÚ?GLs¢&q©¤›ûÚª¯üÀÂÅÏç}ÌM‘ëqŒ4†5 Ýú²+Êîôr¥ø,‚GÜØ|(¥[ÐAçq|9Q&dg웑#YЭï{ Å·ÿ¸ª;MøºåÀÇ{±ÛžXP±ûñ“º»§oÅn¹çÅîÝ"à¥Ø¯˜ŠÝ»EÀK±Û~רؽ[|òd˜w½­GÆvvy4ocfÖšõ¤ŒŸk®üÿw‚‹QÃ:r]™èW±—52YÖ¢µIüL€ão{뺬 âl—2¡4 g^~¥ð%?E]i3¥ôÆ#˜ …(xδ:ƒOJÛͪ³›7véã†z›v ˜ÕbO“ tj>nˆÙ€þÐ鯨¦‘åÀ[–ý?¢™îÔ:·xßýÁüÇØGöì>5FSÇ›øÜI¨`À»,k3¬mÝ ÿr5¯H³ Ű6!éƒÍa6/ÈÓŽêï²i^×"­SIé7CÆk’V+Õuøš©ö–ÉÌ,duÓ è…¯Ÿ‘zîºA!dª½@¿²ð©›z©Ëõ¸íòw±ö'Ç¢ëu$}Ÿ>‰¤ôk‘ÿþõo’“j‡Á¬C%k]"ä3;[žûžrߌO¾‡) ùf•~¯hâWJï{(¡Ïùqÿîšû\Ÿ2'/ýC]<}Úìt0Äùüm†9Aáñüm†ÙtÅäM=CñÍy 2¸õó€eR†¡#/«‚VzQ©¬¨Ê˜È[ÄÔ¶Z, ð<¢” Ó7䟻,°¿»¥‰¦"0à‡=GOƒ¦Cjjúº.ò˜é9Ç”z3+j§†š+„<½#©T U«ŠV.€<ïÖŠÈ•Èfiƒ‘û&‘ÿOJÍP¯èÑÃIÄBƒ²§qܾ­LßbDÞ2$ H?Òbk×!ï;û3‰4©[µ¨Î ä#15«d¾j‘•"#P€"ò üËð?ýô ½d6î:~œë‡ÏH!«ä1CîO´PGvGssï¤ñéÄP³ïI«V{ÀäyÞ•ˆ£D…³I1U9¥ô‰^œ;Ä9ç3S¹i‡ÏŽÖI„‰s:›8•Ͻð§ìD+Ûh§bwh“/F‹“9ðúùh`Üj sþt Ǥ)÷ü“¦œDÀšri¿iÊÙ¥iÊ=¿iʹ“S®)÷ü¦)gHSîùMSΑ¦Üó‚,vç1ÛSIÇícGàõ—GÑàQuz¾$áKP]•+'²\yZú¯¯+:Ø:)ÚôöN§Ì, ‚:Å:,EW¬ °k2ÿ³ÜçŽd]h¾©ò2™ HÚÇTï̳u£@sÿ`ÿ¤(/X öO'dòOt(ôÊÆïéTV]1WgH}°Û¢‡,èaއ½FZÑØ(¶¬®rµAU(·Ù¢´Jt‡árWÞ­øš§T媢çaËYÒ¹(9¡(«ì×{ÈM7’¡a#z»¬rèåsw ûv´FȬïÎ ’/ä,µ¦ÃÜ@}&"Sß©|†Í“?©0SÏ|÷Ôwçûý³‹™.¤äí†þø@¢ÎA¦šm‚’^-B¦:mtàÜÈ ±N›*ú ÍõÃwZLzí¯oMëlÆF[ªÔ@ZDRþ)ñÐBâan‡)b_âHnl:9Ú÷4æÀÜù6ö0ö‚“2Sn½[†ÖηӽôIÌRnºNËÐýMX™ÆÃ¨æ“Þ¦´ßæ”dߊIU•®fÃé4Ùïè;+#9ÅÿG.ÕÐKôÔäé‡gêç‰mº©…'¶x+“Ô‘ÝšŒ=7šø¹5ÁÓh®7=0„<¾øèú!ŸÉ$ˆý†23ƒQ¯“Ú”„ÌÕ3·xK¹™?²Ûò¨Ö ä._î£Ð¨É´ð©šÈ†Ùù-c-SbœªB üDYïdtjE¹ -ëUKòž}Q¶N3®Æû# ICàäúj™™×±êÑÄ̾³ÀásàÍßDOáõÜ-Þb^’{œÔ´Ú«?7·[@ ‡¨iQ®:žÞ¡GÎÍ™ÝÂç=Ž€ß{ôæýÇ+?­9éKB(ðÃ;RÔ´#|$¤DÈÌ&«ñUe·ø Zˆ¢hZ„<}Fv™a!dî¦2Îvá]fÓ^!/¦tÓ­Ac„l²"Òp-Ò~+BÞ>!g{weÿ(BÞ‘Z¡OÈUºZdYhwÈÇ'dMeY’ #±§v(…bh? Í£Sæ©]ƒVÉB#L×!w›¬”`-íZS¡2kíõâûALm Ë`4þÒÎYh§DÛHôa€_srvvÔmJÕ 9TyÍCë`;æBë~ë·R A#ì³6pd ½ÍÓ^fN’s}Sn­FG” û+ŠÉ°p(lØFû¢ò¹#}rŒ†g·Èüù‰j¹MÊqa[EGÒuùsÖðá›gíØ+©š±ÕÌò„}]b‚³B¨ÍùóËaÁo䔤 àµ ÈË.é6>‘œö´Ðxž¯ß=J@ÞÞ‘‚Œ{#Gh]Š2aÑU&Ôã{Â{]±©ÁÈ'F:¨%'ðjôG™° é®I{‹ð5/ÇOÈÍ!ÕJòôŽ wŸ–†!ä9K}EÒ“KhšÈ Íù r¢¡/¸_Ò4‚®B^³N¨XŸ†vJ‰·˜ 4®:4½”%šÉ—¼YºY·P.ZNZ.ì‹„‚G)ÕISÇœD'+ªI)ºûõð ¹I…Æóz|GŠÑ>·3⃼FØM™€—Ù3𠻆s¦‡9ž¾†âš!àù[(ÞŒ)(Íûd_BqæBñýÇë^¨­ ­ØÄ_Ò­¯/}`°OkGô2vcá90§/ǯèû½I­hÜEn3²±gC³Æ‚÷ù€StžÝkcG~Úà{>¼¦è ´Ø™Á.êÛœžúúb?SÇ-zÕ£]¥Yu¼¿µ,¦vk¡güœÙ>@Ö"öXvú®Û¶®90§/Çá)ìªB»F ‚<+º@‘`.MÍå8Î5B3 ÏØ´TåH§‰Ät ³®HPß}aT=! !SÑ%0fü!¤*[> ”¢'?f}õuÔÅÖ²Ô’7ÓØ"ä5G»M‡¬F]’ !o…#®ÓÉ7Yð!ƒ`Œõ@…Ìu=qŽŸý±[ÅÀ5»šŒ£¨U×!ä3CÂ5²Í•h8zv½þ–!H£vöÖ´Øä„æp,ºÄþèð6'N¸RY ä ùØùé>/s«Ër(ѳŸrw:°¨Ü6m×"Õàk¦ÈÈÞ½n!ÅAM;0Æòš!Ã!Õõ08–{„@_þëïDAp£DT§›¾ÙÐ{ôeo‘ ÌO·¡tzÕ3ÇÈLèàsIK'èDÐ;:eÚàÃBíül‹Šûå`™ñ»®]áþ-⻤L±Ò¹"øî9}¹ŠÄ¡b(𩍠ùwú²ûäIÕmC×㻟ßùìAÕ°žUz¢¾ì—¾ªìašŒ}IÑ÷þ‰¾Üwd˜´jz´Îeôå–N±5ë6Ù­-K;}ÙeCßé6·†ÍSh]:?v$‹â¢Pke± šKç<Õíu†Ü-”•M%ÐVpÙ)IMì+b¦1´%%Ñÿ¼dMvOàuÑŠy03\ó-)N“OÚMNJ]§ãâýÕ¢†Ý·›íK V¯üÎhËjàU>ÿ`Ëš²(Ï?ز¦[?ÿ`ËjæøÃ–_ñ‡-+þlY¶eÀ¶¬ Û²Fà[Ö¾3M¹æÀç‹b–,ŠÏÇÃ/‹b–,Š#ð‡EqÌeFà‹b üaQ,Ñ­Xã+~°(–Ø¢8?XKlQ,ж(ŽÀš[È¢üð‘á3ÏGÜëê«4¡UzPœ£¢ÇùxBzT/ ö:ƆË)Î|xÞÔ Ó†Anéxzµ3a Ú¨‰³zaÄÏ¿XèfOˆãªóëL8mzøºŽÈKÅqýSˠߙǕ¨Vv]¥s`¨÷µ8Ûi¡ZµÔ\ð­/ßøÖa§2t¸ñ¾!]Uõ oßøŠ÷t¶w‚a©è…ÞþOØu-IÎ2ËWšiµ½üïÏDì÷ÈyKìÓ\¡ª6³kî2P aÊfÎÌ€?ø}>Hà|(/,wp¹’ÕdÄÇ+p| Œ­àv×ä!rJt»ÚOϾOà x›N¯{e‡g < ÒYÕ¡Åq‰Øó¢ÃÀ÷åz˜ü2ûþÝWZâ×òËX¢¹½°ä¡*äI†B«|h§œp*K§Ï‘ÐõÞEl6t#r{Awp~öngðnù¡.æN€¿èf5ðe¿ëf­š?ëfͼÃÀ_t³Ò„?^˜©V=càå3ñ8„B¿¿P§:âqP|צ/¾öªÈ¡fcîæyÈe 0ž¾>4,¸VT•”˜Ú“ s‡¶2$\6@8¥ì=S-mbEÈm} þà@›&÷E˵ê6 <½*ÃY›Çf²YaÄó ¹lK^ž[1k2.³Üì¶©ájǼì‰Ú-G']eÏ#ðôa»$¢"pÿ°]5žPš’C!åVÖ€Œ%Í⊻¾æ<" r0õ€„8øÔc1²z*yÏ00£óÜ5YÏòwÏXÉ1f­L«øæÇéñ¡T­t¤{E¹¦·F=›Ž]"Õë®öæ…,FÌŽ2Üà/¸èßÂtÑ˴̯žÈÚÊŪY›>!¢Êø} Ñu–/äe®¤È”ÉÇ|zl òo˜jIú{¸iuÓŽË; ¼ƒ~¥—¥ ¼¦/”ýž51ÐÖb¤¨¾³¬¬·ÀV“·Ž´õA24æB:½J”Edc$Ù°±ŒPìUQo«$ô}z£$[uó´•PnȘ^±>¯Æ´¦ØT³útDøã“eärä·e¯ö‰"/¯¶œ[.Î&¢'oËEíµ,C"óo˜(¦doôä/¢ 3zgGøy³+²GäÍY–} o¶@LÞïÈ›­öÑpoÈ›ÇY(DÞ¿7ƒ­’eŸÈ›å„É›³ƒžüÃolð y³«EäÍ¢'¯R)?Dýý^|`Uø†á Ò ÅŽ¿¤¦?§€?¦/ í$z!fxôõÉVJK¥W5ð=‡°#bG•ˆm9.K5(NÚÁ:î„ì édã8öÜŒžaÃ>ããn‘µ]§¢@ÊÁÀÿ!@³Nƒ=’üY(þRFLƒÔ²È10‰D;»TÆ“j7j\¡fÏr·"ž»ÎõšDžÂÙF@ž=¤g²ÛSAo·µ=$ÕföjÛ1¶hðŠÍ{Þ mÑðÓãíR5M+bI¼ÀÂçhøØVU&Š FàíØìSöØKŽ ýõ^rÈhÔ.}µ€™”¡Bà ‘’ëÖ. ÆÈ<b¾*ÏOÐÒUfP›†Xpv{«‡ÐAj]]“‡£BÃp¿Û)ꣅìR¶4C…†‚}ÜÛÚ,MÚ™ÌeÈüýó„la5ýŽßDn3ä^Ê=vÏs4m²Éä¨j¿ [㪽لh/¦í4ëY»rÈ~dw"·%“ƒ’BËÚ«Ï&Ê«8Ü岌y^¦ q”åEþD¶²¥Ù8^‘P´H†¬ìÖ\‚Å’!oÉ'’à¨òTÆë$<½i,;ÜXš¿þÑX 7""ÍßXJïeš˜½f“·tþþ…¶‘eçÓ¿º¶ã„c÷·YZpxÏgÂ?ÆRˆÁÚ*S©WÞøK–œòó¿²´àBŸÿ‘¥•ŠüÆ æQ‰}&ód&ëñ‚{¾üâ#’é¹~Ræ¶¿© gçÛG•á« gçÛG•á« Gà[Éd…%“³÷ÌãðèC29ÃÌã$ÐggúÎß}ì€óãE˜ï+Ѭ<ïâv½|¹,Ì»"gõ,1ðD²¹þ­çÂTËb7ÙŒª¯b¸î£ugG ªáOº¹˜Œ6r#È;²gê`ÐpÞó¶Ü{FN†Œ¨SŠÐþQ嬱v;±.T0ÐwPúÛÊuPj£ä¨/þÿ![Ê+ª[W®Ò ñâCr¸+-ÐtÅ4G?Ÿ^ÞQ)Z±ÎÍF€Xt>öǸvá…ób0ðàuY† Qbmkkš­àk"^|wÈ9ÇY‚ãl·úT9âʼnË*¶S8=ñbÐÃN¦'u)x)Ò"ÉB¬ƒÚ2á_G£²7 ýâ««Ò© ‚ü¦H_Ü!ùº”:UØE$jµ_|©Qå[éð™jñ“xmì Îcz‚u•\»øo2~ü€3³.ælž&ü+E±SÞ½ãB·KAˆKþÇŸ¤©)I”åÀUwxÂ^}¸&iö}ç¦GÅ•žöö4‹@­×½È-pÁÀ>÷âˆó¦öU±Zb`$ò@¿<°T%˜rˆÐâÁúñ¿‘WC$ýÊ¡»?I=ÝudáÜg^Yz†ÝFô/cGœV ¼¡”rìüeº‰ÛC—aà5üÄ—½éì-ßäø€…/¾õMÑš™¥t¿H™®_‘Yñ½!Èx ¹ CYòôÞ+7 úÀ®¸QÅoY+eš®¯7½mO*0<}ÓÒLÛ˜/`Ó\q£ÊÿbÐ%¶`L½fÖ#Ÿ'zõÿƒID*Gr+nTñtVe¬DqO¯öQ+ò%¿)[˜ø¹c³œ>ýŽuí7…ErÓ·5§O.Am¥Á þ.ŒKºÖ¿2ºÿîš¾6=™Ïʦs׬QlÃ4Oùî§’%ˆõÇÖ¸1öÕà\/¨Íú'ÎRúFR­=”y\/¨ÍÚ#“2ÛÞ ¬˜zEÖRl³v©·ªfܘe½êšÌü •¡vÞÍR£Ë’ ²BN7ÊŠ$ÂwìqÝ÷t>ƒÿLœxfºe¼‹zéÉJmÖ»y•2„Ñ”f¢Ù6Yä˜ùúD‹¡ªtñ]Ÿkâ ž{v² ½Ìg <½5IÜ %1ƒ³ÐS@‹PJ>wó°m#,¹Û'ÛÅÌvHÓ킌ů0eEŒÙÃ07éÑÈXüÁŒgM3-lïZ0›e„T5Bmî7Öº ¼Pk¨NfS/ ÆåPFˆùmît•¦³þ¥&¿ñ†Ò¯Km[Ñ—¹¿ÍDI6* ÌW”³þsb>x²FSg yƒ$^S¨l7Fàé—òÐøe°„ÂÛe†–'x^f;^fHžàí2›$1{¶Îâpž*x´HžÀ“ò¯[í6Ž^»¡Ð¼o–ˆ:5/T¥û5s ÌPÍp0q|>j4<9ª·#4üÏðÝôp{LyäÙŒÀË»oÝ1)»”u¼ýÞ^ Œî0»•Ñá· WÕƒu,x&.[ÆnŒCoÓíLlœ°¯aÄysFFÌ>ìkûêÜFZ o÷u"й=u»](á7º{di0ðzÈa‚–°˜ô.ÚrêÈ£ow¹£çò:jr}1¥"¾¿ß×®œI“·~¼ß׳¤ŽåÌ"©ü2¯¢a&ÄÜ.Oq?|Í/MÍ!±~»éWzØbÈ9#ÈÓÁ-F5mæÁÚèýÜI>&êQ~L5j–â¼7d~¾oêH;çú¡©Ãñk⦎CááCS‡!À ¸¬C­k,yÇ\ÖÙí\Ö<¼æ²RJ2jx.ë*So·7êG¡ÿØBLívÿµ#ÀZÈD¢Bž‰ê]Ÿ¡u%¶Èû—ÝQÃѰ4ÖÈîß¿š:Ù¡ÇðZ5ƒu²÷ÊþÈï°Ž@†” ¨Ž€ý2XG ³·ÐXR5»g¿KªŽPhrG· NY9*+ú¢±4í!ˆéï†rÔPLÚàé8.Dœì4Ó›®gè￟ ë? Ñ*—AÒ…ž‡¢ˆR ˜º+s_äÆý>¬Ý,¶°îÇmó¨ÐbíJÓÙ?n‰“ßxý%ôÜÛæg÷›+²3Y»½mø¬è[ß?†à<»ÿ«óÌàé56©bl‚oX¸aû/†0Âáì»°T¼ n!ŒP×ÌÔ¼,‹§ƒ¯² fi=äÓЬùön }¯=ÏùX;-. <¿ö½r^õ£]] =»X,|*wa=6&ç Ã'ô!Ç20ÞHûe:k›¶yô ƒÅ瀳‘EÑbàOHÓ#íô@" qý§yiÂ¥p<áGG‚)ûèÎ=zÄÀŒ¼ ¸‡=,ŠŽÏ Ñwÿe´œV)‡Ebà‡‚²Õ¾^é=ò„›T³ïxƒo4°œ&†÷T„N oØ“b³§|™ã°ÿ±÷GˆçÇ=ÓVã$»O°]YÚ®aòQ÷#úî¶k‘¶«ß׌u#ž?ÇqÉo¼~’zå–}gÞ¸?^ꈢsa˜õf Ç~¼Ô…}]6¬Þ9+VI%ÄÞd|4E£ðœÂdy#Û»²wÛÄ3/ˆl'*Äk]²²]º†¼Ì•(I¦Ùˆmnû‰<ú† òc-½ö’1ˆ³Þ„'öÜÂJ±¦b`mÞ„ØÑg¶<Ïœ2¥hÕ æŽL8Šf…t´µŸ«\U[5(úiRKô‚]nš:o& &»?p‘W㬂:‡½7ç±bôéÙqÍAÜK¹î³=Ï[CgÜ¢˜ck?O^ö ór$ÎE“1ÅæåépQÍùèÚ¼Nyð{áòHlÑÏfNý‹šÚþüùà ¨¶Rz®6%r§ˆ|@RÁñÝ„ íu××:ïò;CÄqw±´ÄN“w»ý§©eDƒ.Ö+@%{¡[×ÃHÇøI"¦”Bœ¶÷²wŸ(ÅùXš(€¬FÖ“*%¾vØ=ô¤n@²âM Ò¯¶ìúTP7â]ذpZT@7âM4Ь¹o¹ºo€3)u…Ðx6[üï°44ó¬ì­P´)üÐ8Gr¬dîÙâe ×ó«y6¿Ù®ýA© Ã\žË‹ºÏÜ7xâËma•xÇÚ¡|Ì Ää¡î|¨GºóàDþþþΞfü´ö„?„tÞA„è;Ò1§JEÙyÿÉol7@àõ…M0ºjV«Ü¦o°|5ËH­´šTŸ[K*È™(z³¬F×ëÍ[¬óÚAàõl6Ÿ¿°E ˜-"ß°E´˜-"ÿÅ¡!ð_lÿÅ€oØ"Ì‘ÏcõD;=f€ý†a½³™|´ú€©Ÿ¿/¾­ôwm·Cฬò ÓУ"“x{‰uµ¸¬n÷.k Õ TB&&:ËíÖ¶$«eàš€¥ÛÊÕ;|üê+‡^ý|“r_÷X¬ÊÁ±‡*d–\!s왯7eÀY[ׄÂÕ@à»2à}ÛöUPüÄ ðxˆtÖµ[ôÿ$3±B œ¡¤pPªÕÂdZAÎïRø’iûyãSçGb~®¦zîë\9›Pû'·¡µZúãÖ0ºAà Ær®Í¿užn%V'PæÐæÔ{g¾]x.ËÀûyiÆk=Œ¹eÜ4¦Éx¨HøŸ˜3³S~¿Ò!·ãfàêp¥ÌWdpb¨3A~þ$—÷®;h%uÇë ½­È”§ÊêMÉN—{ðj†¯OLÆÙ ½I1Ó<¤'É¡6h'&Â&€6²Hÿ†ž.«%ÞA¤òÈD Ô;4o/'Å©ÓÚyscîU¨ SgªÂ-ŒÜ”‘Á¢(MbÊÛ³Ë!Å ¬×ø9owï¹O´Ã½ð@ºñ®›ðñ[±ØpÍM‹µzÅbó±Ìîÿ¦Óšs¹º`’þøÄ¼göÑŸ¤3ë3ðµÔ§òVo ïÌŸP”hml2Óîú=Ñ «ðökE|ѨÌÀ d‡Ò*5ZÖKêòxÙ…JeÙŽÞçØ€žøx[:4fÝB`¢2>¸££ßG7÷+¦æÎ?z8Q'*xˆ¿ ®kn`ñgølE_Ì™Ë3dž¢»œïf]šª“ÑóÝÃe—Ř*Èè¹~þèBûï%ýÎMY¯ì„%Rçzëwö`Ư¸ 2^¼&£2}Ã!—.¥í:)9YÕgéR OÆ„—wQT_·+Þ_»%C|…MtîçÞA ’xH¿Qk«½AÇ'ôŸ¸ƒ;·r¹k+zü„é”,åèí<öŽ@ P‡ä‡:¤ÿËZ‚9ö—cj9b¢-Î-nBÈ3üŸNŸ„lc cydžëƒ¥Ïõ¡dfšEÈe‘hATã67\NN duÆX.Aó6;“z®ñºãÆD^½µDï½)óóè)dêIgÉÜBàÑ““83ÃZ¬l&G hÉ^0‹S² FZÝ '¬z‘Š%Ž»?e-w¥vDR¤©Ò`ñ£š:wX3Ÿl±ˆ~X·Õ ßø<­ŸX ÏÝð—öc‡ˆ{Œ¡òØ?3Òµœw¿P22§a[Ûê¹´*”ÿ8’.9ß2Œ9¥ÅÀ¿|a=‘¬¦˜Ú Zßô5~æõ䓹^¿žê†ÈmãèÃ/‡ÉIö$F‰ Um#OFõ0ñ—Ê‘“©ß×ãIÓd±¨£Ž‘¶R÷}æ'š÷ÈÇ]FIÔ|ž¤·óñ3ŸGM] Ñˆ§à4Ki§^~gÒ‰J”§Kt¶-k6ÖÉ!¿NK?$bE ñO«j:V¾èúñ›Â@ÜûŒ×ŸÌø|d¡k²Ï) Ù¼)¨-Ûì xì…¾ßnëªHŸxGò˜ÈÚ¿Ý@àãe÷¨c÷x7 Ÿ?wϸŒýÐm¬ìžëÚunwQMÝk·ÚMèc¾~[êÛFÐoq¨,üÃL¿µ-žO àØä^ÔyfΪBb™_˜2¸YB4Ž—ƒ¨…™¦¡›ÅÐ뾦y)$ÙwË–Ìto‰„}«¥‰ÆšÝ4µt¹(¿º>^ºDhNBÏ{Ý ‹޵ åþˆ“”ºß¬ÎPº…!ðvÖ÷•žÐv&Ö;„½±‡KÿÎà-P±±íxî²b+3oõ~ÓÊ çý”»Ç›XçàêžC ³eYVÎífë¹]4<ˆ„5«Fš…HçZô k&)‹¯žSRLeÀ? 2FôBÁY½ñ ò‚‘M~&g~iH„­%µÈ‚/%tÇÈ@ª”4ó_.7CbyˆÙ¦LA¼M:¾ré°FÈTLZJ“wDCm#é2­IA> 2W“¦ÕFúFŠMÐå(Ë­Uf‰¡Û2ŽxB¾á²¼¦ NË3Ÿ¸é;uN Q~³Mxn–šˆ’¾›v$Þ~m±š™€À£é›¤"•£7¿ÍgÓ÷A¼ã½|îl _ø!Üjf|’4¿ˆBÐ%¤gšÅ/"4<Ÿ?;§Æ–·ÞÝ+ôøõ+?„R˜—z<ÐEi€ !dNýÖEÈËïé%2ÔÞ‹«¯¿èz¯³s_âaG,ã*»Ñ Å¿~b¾›zÕ½úhÊ6Sè%ü#ýåXŒþë'*qû©V½|¾0ˆ'Óµ’¤8p×Ï—óêUÕÚìø/å̡梂‡¶NÉ|Ct½]ä¼ ŽÆçGëT8~]B¿‘òú²?ó†Ò>I:0âí[7ÏY½G®ë¶üö;ÊÎ4«7q\OKü!#¸b0EiBÅ`C¦ !Ÿ°d0ilx\ìBŸ¿ e 4é—¯ßE­M‹Ö:v.bĬ’mhò‚‘‘“ŽèUÖn B"açÄ9f:ÿGSjÑÚ£ƒm­3ãÖÔ›zy{js3r bo׺Ðnä#“p¤Ù½ë^˜û òQ¥ê˜~Ž5gDÎí6v%ŠŸ‘ÏwÈ- 5ÁÈO(};¯s£ ^u@b2Yô!Ñ©&›Z´BRíÑÁˆ‘]Ù.Ë"òàã îx²1»®n×e4ï'_ä¬IDOñ'b3¿ oHª:U’Y¦“à£æä㣢Ä»ŽÛ}–¶Äc3ò~"e.ûÚGoqÌÃŒç(ññíqÇå–t®ÆiZ˜% òù¾¦U@‚&4Æ"tj·Nf·Å-¾} Î‹tSƹìùÒ;•u|»` V¨*•…·å ÏÐ6/F¡ÖÊ_ê0…oÌÆÇ õ¦ŽûÖ+Šž-ŽZg7*é¼ÕBàÛ:bªû™Œ™‘*續鎕•šÊ¦ƒÀçÉ™“û$ÇŒ³fåY ¥º]‘§˜æ’ÀLÏö ÷® ö“b˜Ôß.5žœ9Œ&Rºf«ÝO}›[*3qæ¤ Á8!¼æc lß®È|J”hϤ§M'‹Ûs»"ΜLWjO4㺛ÑŸ8,'ieÙß·+n‹˜ak¿ÂÛÑQŠ^ +KzÂ9V“}i&<à‡J(îK~¡¤®É‘X¿]!gΤq¯È“3‡‰òávì%ç‹èò•“ÒîáŸÉ:ºwmf/)ÈêD†AØ7ÞÁ–¬iÙŽß~?Ãï…‡góÛQ6N—³ú™p23,l²SÞù0™ö¾ Ÿ0¤/bâœZk·®)j5ù‰d&#ùêÿ— » œ9sþDÃ,µæù3•ìÞº^2gnYëPA6ï\«·­&D¬yjÍúÃ%ùS*´ór[+´-®g¬&†—#gŽé‚аh”®·³¸Hð¨{Ö8²Y¨º\w[â J6«íˆ·&2{iAo[$}e¿+tßjüE§»] –¤uØä˜GÞ.ùÈažý’ŸÃj´‹®€P:zq<åP7ÞêA³y,«±{'&“ýJ&¼kÑï¼}œÈ4òÞë UF=ß:´>o§F,ÔPß$Œ1ëÖµyhÒ¤Ý$Ã$uMQ“-ÈÛ™I’,é´©à%÷Ji´–nŒJ¤³ÝÏQm×IŽh>`LŠ]ùÇnm:È9ž:[œqõ¶ùc #ëwɰ¥éÙ,¼êõ›g«³õö§·:'4›ê7ÉçyeåÛoÿ!ù\]§²ÞÛº&U$Ï*¨¬÷¿ïLþXøCÃÊP®ÂêÅs(Ì ÒÅmmwÎ!8![©&1´C)/¾aneJK-Ð>l af—3V˜(«Æaôs)t# ð‚R¼‰nÈ+ðñ¸ÄOõë«·rj‘i[ÆÈLؼBàg!ŒIšQ‘7jn!aLDýÞƘ’~E éá&˜¢ôXQ¿w™"µ•( àûN´œÙ‘D'½¦ó±0[óÏd_ œÕº·É¾#ðz¯QÞ[%/Ñ‚óÖÑüü©Ëq°ýiªt£´µ\yí¦^Aàí=° À¡žÊÛµ–z©½9@àý-Ðz F<»š¹È¹€AÍ‘6K:|¾ŽVM%Hz;BšÛÿųOdfÕlç¶6¿ÞÍ\¿£cµ—ÔeŒÀyc£ÕKçWð„—_KXëyEHU¶éLòö¹ìþ™!Ãôì™ï7›Oí04¶ŸÝ² äý-²Hü;™*x‘ß>hÛÓÑ¡™ŒŽÕOdgMß» !?#2–ˆ¬MÔ›—ƒ²¯ ¿NdPjNHîæé« ϻߺpU·_™²s‰|ÙÕÇ”Èg:ªªúø¥D>¤u`‰|õñ%òøÕdp)yªZ-˼à+‡³Ì>&%#ƒê#¼јdã$å¿Ø9”1™d&sÞöB³« Ò@àíg³¶”ÚŸltÓè‰Æß8†;Ç[¶ƒ„À;ˆ5äá ”0¢§¬Gó82i)†*^"™:@ Jf•þ¼–Ì6Ô4Aà'hÏÉÅ ÊRB½Ù2 W!`.7ÞÀí{ƒü÷äÉ÷u•݆€¥,–E¤èM,‚BÈk)d€#äÍù%è@#d’±ýŽ–‡Ø‚ñ_diÓ#dªÚÿ äXÇiIJVW\D¨¬ÍÝÌûŒ‡ýò8=ÄñídèCôMùåù9Úѽ"Ï<ç9»-¥ŸJÇêZ#ä@f¿CŽ£Ü7Òeöæ²ÖÃ}Ç}V³\ù»dïdÛfÑŽ‚ sô7Üã¤.”J¡„o§»™,B^!2«ãxäLC” !Ãý o'u ÷zdç”w¸Ñx‚ìCóf3ÌtdôgBºo´ø›Ö¶Ütrð>ü^=^¬¬êöÕãÇ9xûGõxçÚ®Þ ð=ÿh•ÊY t4ßñÎí®t3TÕÏìm.e3-iM]—å~ÿ©ë¢7æum´)¥˜.W¢¥ÝgŠJ3\…;vC®"ELZëkYsœ1wÔ É"pÐMKÄÒ—Ú«êŽ{R€=RMæaÖèÕ³¥€çϺtFì}Ìó¬vãYËû×c¿iµZü)¯L¢×îìÀy‹Æñ ær¢’nÈui&¡ ð_ø»¨.’*Uõ@}8ÿOØ•-¹®"Á_êöîÇû>7¢ç@ ´¡ â|ý°•Te»Ïø9C–‚¢*+3Uà“¦“Ðó؃Pvþªß5;`š\nÓïrL;üM¿Ë™½mîrûEŸ×±óå°8ݭγ¯ÁÜÛÆ´Ã ƒ I£Ú[8ã–¡s«çßt°ÝÏèG']Mç÷[ÿý‘[lHúÞ²+K•ç/È&ñs'.Ä-È&ñs'.,>‡Mâ‡5eqjË~[d“˜ì¤ÀÍ%ñ”Ý ñ°‰Vn!ß[€X0Dê²JÊöÕnÑm§ªk;x˜+‘QJUÉÁ\U[ L˜ë•´šòp\Í2 +c».‰ P&Ï~W꺎&×cMùŸºÊN›~û¬ö©ëõèÄ%½½¡!=š†{¼Ñ–ÝpÅѰbl6¾Z ¼co·äoŽx>@ײ DÅq™3Šó¾ÝX‚+ZSbuêíãºTK)8_®ˆy臄KV]QYõæ³V?;Y2J8ç[ê7yz?`ª 18•¸×Cž##7ÖèbœÛ}ªò¼¹Ž½3G˜ßŽ+>CŒ|=Ü!ÞͪýÙeaï¼¾éô7é‘LgìÒm ºw¹âÄÃOjLkê¨ÝîüûžzXw‘kÑçÿ}j<ÿÞâï€=pE=Ãe@4™}”!دḦÞåbk ë²zUi袸+¬äÈ:裸«ÔäŠç_Å]ä oßUi˜{zGUs7ÒuNp¿ò™€'­åîìó¸HV­Í©öÛéµQr?¾Èa®6ÅÀó箺F`ÀÏï‘øK׈ '¬ÏŸ›AºÐ B€—_›A$´}#{£=û’ì û§ÎÝ?%«:ÞL¹øŸÿ$¾©Hv½±3PkGöF?Ñ" ÈK,-ë-0«‘½8TÁD09±½Q|5Õžn¨‹~´ÍÞ·ì>v¹™ýëºü¥Ë­ ]nžm^«¯ ¼üÚpµ/· y5oýVÇ<;ÒÌ??Rætm;¯˜^MJ²d‘WÊro¾]óÔ‡f+Cïñ ”±¢.òÒ,þS òRð¯ß%hA¨åvý´ÿ"A«ðw Zeðw Ú]#æð‰ú”[êÜr„ù'=L&JG êŽðîû·Dbþ^— ÃSÛÑ,xLÈÜÆžˆùc;µuDþ-0Ö#m%^0[ûøsö4QÓù·€VmZJýqÎO e* ¼áæ|áŠÅ`ØŠÈ{ 6>r£9‡N×Û¨*ÄÒU²P˜'eT£²ETZµ´k´œ >+h¥¹Ý_ôýržýE7‚ÄÕשׂ -[¹mWàÚdä Wªc•"ܦSƒ­öÍæþÖM¹³Ñkî¢`^FhÏÈ3ÙTã0YS V¬ öȶ.›Vå|¥Z£W¹p§—2t™s†~ÿcÒÌ{w?“´ÂáÂ:«¾õ§¤ ºîçMž|ܺaäD®x&ö`íüˆÏ ”Oïèl)–É)2ŸLíÔZq <Øyt‚†ýbµÙªmÁÀÛÑÁ–¸¡XÒ =êª#÷xhòT¢”@ºjMɪÙaàN… Ób“8<ƒ¡V |â ¦ÚÅÅý™j̪»—ûåMð*ú”ÛÈq_î——6Eüë6u\­×Nkd7ùM¬ Ò* û^I‚[‚qj>+LHÿAr½ñŠÌu’ÄÏ­p~5CÍ[2?Nßdï‰ãé?ÍN¨ÆBÃ`FžÉì°¼ÄhtT7Ø¡%Óý„ĵ«,Ÿ¼,JôM5—ä‰N$õµ—…‰bnCf]Þ#ýŒÏUÖÄõSrR‹#ïètˆkïuÍØÝÖÒkÞî:ï=ËÒ«V‰º ãù ‚݉¾î¦šù°§¤Ïþ}¼‰Cgå­‡%È…öˆUydZ4z-ëŸ& DGHåÅ]ÍGÕË:· zGa qˆ4Ë'­ëž +î–Yb(õªÇÚŸf1ð†Ò>eü·mšÂ)r©$v¾HcK°Ÿd¹ÚäãvöÆq?̘~]û¾_ÇÀçuÊhIpgE¡f:à_Ph."óW¦ {UÈ¢›*‚üÆúÇ™ñäBw -ŒLIc&¯ØCe9›®Û&¸Ð“•W—yeþÙ÷ãû“ÌžÒ—A»be¦)ðB'Zj«³_úæ}z¾½s‚̯i*¸“ o8bͦ³Æ/mP¹S9Ãônb›€g>MzWîXÎØO‘S;ÖÌcëÈ=>‘™¯L]&Nê‘©z³díŠC„Ôßä,ô2@9áþ|QnKmH""ÛQ»µ#þ}B G™Ulg#…?AB?ùÉæ•2=’ Q– #sGr†v±Ô˜/˜‘j–n&ÈÜþƒ\fÖº-å´Õ ¬~Gr†R\ŸÇÝಘ •‚;’3Œ‰ˆaF¾³tœO o‚ÌR¶ÿDöEvÊkMã×þ¡¦#È_¥ |Ø%ÚV-Õ¨623°‘•ñac#S«{‚ü~—WYô0_d¡>¤ôýÆØµ~­ö²¢?ÿÂÚËv“Þ:aƒg¢žòÆ~/FSg£“ ¼¼¦Å{Œ†iÓØb Ò¥LÌð×ÝÔiÖ¡÷qH$þ!Zñræ>XŽ/* :sùÀE»ÔžaŸ¦¤›žµèÅÜ’+>ÿ"Æ'ðãU:Ú•tÅY¯™ƒàáqúåä,çÞÍ[µA¤ú8‘-”WPd“’K³­u3càùè gö”Ñ6Á· ’y3ü(QøhÞ™ðÃÀ믭@,ÓÈEùs+ÐþfÎdšù‚2 O/´é!{\^sCYÄÛx`«7Ããú"ØíˆrV/†3ÌaêûÁ¶ºok jcûËæýþmßMS§VhB}<^YÔÉ›¡ Å= Ä¡ˆH‘^—ÊmÛRcÈ–5 Þf¥^oµ b"#î]qnÔ¶je.![Ö¨^°´~R´>R›10Ñl²(O³v«îjæ@äàq×@ø>-н^”5¬Íã(®ýÙ#µ¡j(Ó5,|£¸–Ù+"4Ï Ê Íý@ŵ?i9Ëë³9YÛ¸”cÿ󓤯“õ0ký—ÍýúG'Ôý·Ñlý6•å6ïóâ(®¥äsQËbÛj©l]Ò‰±«û„kf3ÜÁ?Ñ<׌̌ï+$*XÐhMäNfLmXí(ò¶óýB—j"Vøð† Ý }ö£¸HHÒW4N9Väã]*¿ORù˜KÈ´÷cK©™ ä2ƪZf'È!‡ÎÀ“- ¶½Üìj 8!‡ÎÐáÈK Ô–V¯kãÿ€ÇÒûhÿðd—Ù/©½Ó@3:Ü/?6TM;Iÿy¢ïYC%.”²”L÷ù@¦£¨A%Ø éêBUCË[zÅó{cKûb‹ðD,££$GŽc+Únc‚1#¥r¨¸XÜþÔÈ&=¹ŸÃj>O³•þå¬xÇ})¦òŸŸmVlä©‘ýaÌ!„ ÜúóçºÌô¯Ÿà8öãi5Ik'Æè€½ ÃMN½_Í|˜Vä÷_|# Až5»tçWŸi+ˆž]á ÔõjõX8Ø’ŸO’~;²j~¥°ºã®'Àf,l¦Éàùˆª¢G{Hé© 3NÏ'uIJÛ"VÍGcmÇðJ,fâò³vóÚ fA¥ìyœ’?|ˆó,¡­üyœ’?}_Nï_ÃqJþÜ›éŸÏBl› aìÒÛd\ÎÓ]±^ÜàAsÔ¹vÚ& 2î^‹Í/§¢œ00­*‰ÝÏž|UN•ýZ“+^ˆ˜TN0­Û\ͺ"#¼Ÿ(ä\ga/5ÊnÔÌ6ä¯oÄË0¦;Ûj?:ci1ðþÉP| ¡¤È_?Ž]®Ð_²ÉvV 4—O „ÞBÎå+0+>ƒV¢ÑùHˆë¢7ùù.=RÌïÈ$ÒºÑ*ÈwöS¥ ­ÊÌsdnw|lPí™™¸“.3oy¡9ž¸òN«šýE»"#©ÿõ¯Røðx6xz1õŽKP¬%ÀóG}ÒÅ¿›bsˆ€@Ù°ö ô0P@ÏÀ+¡~%oäÙ 5±.Ól2ðölvà0) ¼£œQÎï˜i5ÓÖ”¹Ü–lø+ó821mZg>b>ßÂ1-ZIü ’z‹ôï}Þ¶­™‚Øônòé*İ“µœQä郊hÑ®¢jUÖ†ä¥r¹zª×±-éĸ…Æl;Û,m78%ôÜäu÷æ ´³¤Gã˜j·­ÈiT@îj’|/²:κͶ›¥ÿ~G¥¾¬5u=©:­'‚|¼ Ã>V­“¢ª(ò‰ËrM|$nV;pÞ×äßO_ØG7mP®Z·ž‰q 3îtÛâ 7:šu3_ 5AžpY.g?Dºa›!£tÚ{ªœÔ ªgkJ}ù0N—wäT®ÓZ‹6;WrïF®ê,¤ÖèvÕ¡b?WyCÈ|fõòl-“äʇéßEú÷m] QÐñ||@Vë¢=²¤ÿþܡٰ\ÆïHô˪W²Ì|–™0†Y8]±ê‡Öe2j ¤aI-ò]ªfŸñç÷@GîÀn,Ïì–‡aàõóòÐå “‘xÛÙÏʪHTˆn'öFÀ «"ǯ0E£}ûa»Í=˜X9©äÄrŸ¼ï˜àÛ" Dõ$Q^Ð?Ñ=±v?ö`}(Óð·a<Ä{Õð‘¾:Ã<Îs=;TIžxáãT/¬fQ®99Þç°œ/vl©Q2;=å›CÚg™jÖŒƒ¬1“«&jCŸ·×c¥ôŒ(Ì[í¤ eßK=4EÚ%¨ë‰¥è Ö‹ÔÝ€G%@±o ·×¥öMñM¥¥vU¢Î¶½TºTxFTû6³ªóõÌ ^>f Kž¸Ûöø+tO”FvdŒÙÇÔã0à O&ùn2Îùh7¸><¿<^[vœ1œfÇ·ÚÔ›ÄÀ èÐåÙ³l ^?¦Go(Cò¼oÓ£»ð$Ï{0Ž)Ê8–!ýÕŒcb›1ð 㘢ŒcÒ_¥Œc’2ŽeHõãyõOŒcøã˜ÁÀÇZ²Ž?0ŽIòêÓ×k‰·¯aA$]Ù™²g²½ï[ö]ר¢«ÓGs>¿†º¯\·Ä‘˜±–Ià.)SOµnÆŽ\bàå W¨’ߺ0¹õŒ¼îRû·àŸ8·ùÒ Üïavè(: TlÙV ¼Þ}UÖûdä`+ÊÏO âU î«aë6Ïû®8?7ˆ 1 ãÒ¬á·+”bÎ!nÉ‚}Bj-É#S‰xFÎÑy ôåXË$•OûàÔÐ6 kRäð|yªè²h(m¹L„8_žË âè[Î{)ʾ›1ð‚¤ù´ue˜š{…×Ãç;-ÚÒÎLóÓñlB¦0¨øj¦eªŠo,¢½Ð„àÀ7^Blá|!Ò5©Ž-d¹}›óç`ŒHD6–þû:¶PðÁ˜˜Ž°‘ý“ˆŽb3ÁäpDë³'ÙƒIˆÞä3ß÷ÅKŒ¦Nm;Ίbr ¼à°¡HÕ¬zžmÁ @"²±.Y³A`àí@€\Š) OT¯‘ô‘Ç&ñwl‚[^†%=ÿBµm8÷*g8kw‰”˜~ ÚÉã97D›²! þuœÎU¤â¬*´óÑ Až+»Lªr’\·ZŽôG<¹ÌÔåÑtSÇËr(s2ŸXQÿšüâ-;1UåzJjK€¼î‰ór³ŠóŠ5eNÇSv5ïm L±Í+,yÛ‘5Ô$«AKá¼F6QjÄ4©K7Jo¨²ºžXiP¤ŠzÅÇjôõމ”A“pa‚9ø˜äka¯=ÕwGé\!Þ“•?Ÿ¨J\µÏy®tœç3ÎãÆüè¸åùæ­È*E²‚þçÉ `î]ÉŒá…éé7ÙÿlŠ1ï茛ª1¥ÙÈÜ òN€ :ѵe¡lA7„„N ÞÙÇÃ,f²C޼c’LvÓ¯”³:®FòkMªWûÓ­ý^Ä“!qÚ79ÂÚµ`†ÄißÉíwÏã—"¹ý¸~üR$GŸøC‘Ü~ ?~)’ñüø¥Hn¿)Šä&w§ "¹|S$çL@\$—€?ÉíwÏãC‘œ˜I‘,ø›"¹I’"9@ž>ÓcKMç7J)bÆJ)Òª|¯”¿âåëg¥” 2Q—/Bùj&*À ©_¾5EâlÉúå»aÛÎ0ÆÃÉÂÀPàn½ktM2$ù.G8çpÝ#ÁÈ÷]©l<âA¡{¤N]RBTnÊî€É\ß'r-&„Öí„çOż¶]a³-±×coáÈ.˜7…Ä^½)$CŠ3ÏYG³Žðêï׎¸ég·ÏÇ–çñŒ~²–s“‹Á_„šCÅX®ôð‚ñ&ñ@]–rn1ðz(+VÕž#t¯ÞÜ5ŽúÒû«ïë¡ïScà å&¢ùélä¶Tªë2ë;ún ÛÁeYîfÓåñÄñýpÎ]lY'xÇ0ðô]“:̸Ϊo{%6²à_™’î›fó6ŽŠ,äéDz\Ò(Mí)÷ýó üh¸yc±ê| ÈËA%`>ÏU’cä•xF†QŸ=ö”®•%;㔡Z“TX¿.C»®J † ohqøfœ©œ$”k]P#bª¼KFµwèYÇš¡$Ƚ8¤Øë"åÀíÓUzP2ïÐ)Ðò®ltkÈ3ÇÓŸXR+Æiµ)#{86"š+L±ž(o·Y¦ÈÊ'í?Ð<ã·’;‡§º^ФwÈ •Ûö“÷­;óªËÔäÈÔfƒ½p´|T ÙÇDD;å %óáîP'».Šh‡&LX ¿’²\ûò3º“ÏwÜ?·b-¥íëfKãÄr;„±HaäEMW( ö‘ÛIÁs¹eÛbÔmqR,·C´év?åP(_ŸWËMÔßœ3g@¤f­¤ÝÎMÚÈŠ‚oŸ€šÕH™0ÈpÈ8j(¯_”E4}©Øg‹µÎFÀÀÇ+0>q{zâ¡Pˆä °—q·=ࢸ~=2píy~A®ZV扙ÄÜê{nÅúÙä+ ¬X4L5}Åù½O×#NL’X²Ûs¶ô5E¢°F™hÄÚóNwº,r¯û5r1Ô(Ñk[Á±™H¡¦J|GÜzmjµÑíÝÎàCÆh6ÏY—sA‘G·s¹·"°‰÷s7Ó }³ô™W"S5¹» òôZëUF£ÄùòLŽŽàçLvÖnkM>IzÈ4Á`vÏV£Ý÷K×§þ@ï¡V›¶OÏć °=±©áÝÜq:÷xÅ,Ò… kÚT=Lœ|¿çûk9çlôR?!"£Èés¢œå2•+ÙóçúÕ`PH7ÌŠu{n)3_ï‘=ëú…"O™JÌËû®áô;ºÄÊX·µíá+>ÑT"jì1ðŒ³o{V] S—Œ/Ÿ€CÉÈ«I²!ìv==ˬ§<‹Úº–p÷^Rú=ݹÝ*ãƒ$ôw s“±ä‰§7%ÀÖ*¬^”].6“Y0ð|4 C`C¶¥œZ6ÌðÓ ò(œígnU’ Lë;¢†fQKgñaß¼{bâ85¢¤W1kÞª¶n1p/Ìg;‘œ²rì—v)È«~Ç BôÞ4Pέ)& Ä6„Hü_–“jUb éÔ—©šl5óugüº×Õ<5¯ a°ˆF†t¥Þðån{£n†å¢þ‹ GÑjU­0F×f%À3ÔZ°Xå'Óö]½Ù L§köd”@ë‹j;éª ·„å’Ò\Dn“ó&m¶ÏD’.Žðš¼ƒæõ É!±û T;Ò°"Ë×Û…O¯V­3¿«yܯæÛS ï“M§Ê‚LæìȃqŒÛÔ¼¿ý¬7™—ø«ÛÒaº´Ú¹\Zåy r™ä͸1_mNücÞx§Ëq'ØgIÞÔ¶ÈgUÁ¥|xØÿânG±Ì#Óݸ¿B ‘LZ_R<ÙVzuÞô")¦×sk,p!eHŠé%´›Rú ³ó/”Ð`µdç9Y6­XÛA&Ö­,»<‘OÕÍîBq¶µìŠìHŸÆžº*y&[³-›ó̪/¨@)71»«ËpòÄëÇsoÙ¢(>ôÚ8+¤ìç|îÈ«oŸH½fÇ)À2tc\ÇΓƒb -R¤3VºiÒ,‘È'àƒÚi~:Þ¶±£ÀÓ:s«D÷åü»¼5+Ø?ÙѨÈDèçÆ¶îÐ%óN ‚ÿ¦g†_Ñ!K³´c"¤äå½6·±bƒ>O¬¨õ¢Í=´ÛbàmnfÐæ½J‚T=MÌX=-Ã]oÕÓ 0Ž4ºÞ«§Qà•3F‰FZwXØE2øuŽF”âLf¯¹SØe‚Û=CšÒúÐXë=yfƒUMRuHÀ FÇÖ«m'Ü£g¬‚2¼rf\Øn]G <¢ge•LíµÊmgyÐìFH çm¤‰m3΂…ÆÚìöìØî,å}YNBHòêoJ,çwÙ¬µl[¥ÀÀn»ˆ¤ëžÀ·îô4’WãèYô0¸CjÁ ]Š O¤±©Ž¤}aG;ÈŠ N(øvÏ,Xá,/A†™>‡˜ÌKÊ ^j$lMïäØþÅìFnÕ;£+ÁÈïxÊKm¸Hëö¤Ö=D¥òFXjÃì=CÖzh‚DÂíÍ[ÆÚ±m“ô I?jœ»´9gÅÖ$Že@>VŒÝ u¯ljÚë_R¤¶}=ã/uKè­’u¼M›û¨É8“c›âWÉaô¬hB ™ûùBRžaåó–·|Eâ5ä¸g‹H,R7¥r=ŽdŸ3Ì{âQSÏFgâLyC¼çÉ–‚ îªh8}æýà(‡bæQ³qUP›Cº§È 6É6ÍÚ-WtF‘!Ý­RÈÅõ§bVBÍäë8Ø_‹¹óãÌÿmjnYùƒýÕS4Æ&×’6”Cž“q^ö†Ôj·úg¾Luß4ŒÌ=±¿þ8]S¸b¹ó³ôVÒ·_¯ü"gdzYvª¶‘&^Ê(s]–îøÄÀ3feJŽzk=}5ä‰ÌÊ[Þ# FžxýØÁ ÆšÈñ½éÆÏÜ;Fâ#õ¢åîÕøOÙQü7„´« 8­rû©ß·ê#ú“‚áóõD‰Îi5PÑ„?6# –’íœK¶Be`ö `þ,LRÂ{â‹Y: ¼¼Û\fwpCöxâôò”Ä¡@¶E5Tl%¯ÎzÈàœ„”§¯®²$(³Çƒ|œŠð<’Z欢:š=¨k9æl·­ÄÀo”—H›blgî..Éd¡ùA°ß y•÷šŒšGј”ê˜Å 9'Èu‚|) ±–yÈÅ+Í7¯ÜÃÞÌZ÷§A^(9|ôcD¾åH dHÐñÕëèú£4ðv"ϳ¿Ì@Ä.»HEm±+?J³²^l@š—!±ÄÔ‡Reé2›qá’¸=ë$`³Aí.»=§AmÝ[&f«d×o¸F÷:å¼ü¢N 9¤ªøVr/_DªŠoÕ)øËHUñ½:%cö±¯¿ûµø†ØORb¿ ëb?I‰ý2¬CøžØObàOÄ~"ö#O|Cì')±_†t)±Ÿ¢Ä~Ù¡CøDì§(±_†u)±Ÿ¤Ä~€üØO®ù±T¥Ü®¿û‘µü‘ØìŒ‰ý(ò ±Ÿ¢Ä~€|Cì§(± ¿_ã8¡pç–‘I±ë^NEË ¡A!ÍÄÿþ GFU%Š;)ç­ØöÓêðõ^y½*玶 ^0£O|bn¶ÁX}âõ¯×"Lß3b`Fê"±©—ÔžzÞOxCDÕ»smØÌÀ;­xŽ@± øÌ·ûsÉ_ò<²EOÒ™j-^Þu×àVöø¦ÅÞk˜ãûÛ÷sNÔŒnÖ©\ÔöÀfu×±ÄÀûs«G³7…,øý ¨5Æ6oæ'Q­ÈyÖ°¾®Éò¤6ß4Sì,îVTÕhÀ¤»£ø©.>Ô}^K_¬{;ܧÀIîßïÝ|›f¨‰AÒy‰{,Åâ|VŸç=çIç…Öƒ½ÌoàíÀ6wVÂs~æUN]3]ÓöeÏ&h3¹Ÿ_?ÄcŒcнv?¿~ˆ;; 'À+ù¾¢ØðTr¥ÝiEƘ!`²¥8xàJ€·Ã•§á (zgìÃÀƒ1ÞoÝ*¤@§’Õj®’a~#rÏ”|qD.+½.äÕ×ä‚3†Z²úiÁ¿>ý†î³Y òtÀÄ®ÚJ¶}¯€íŽú”ÀÄI'¤‘…ƒ>!/G> Ò,ܹ•~ó'¨KÅ^]™a~]±ši&Fç¯äÈß↊MÜý¯ »-)±>¹“sœX’™Ë4Y8*c6Ô~¹½Ø: ÄàU‘º/ÛvEžK-0ð|¡GŽ>b#gQ`àå8‘Ïõ¤…ÆÀë¿€‹Y6X=€sÏH=VHù'Î…®fS°9ÇÀiu‹iYou»5@}÷èÓ~ mþ½y‡¤û2yV²²ØØÒc ‘çM§…›°]YeÉ«±ÁlsÇ0š¯?6vA»{'R¤<¬@cL¹®k¹@ÂÀ!‘g'´ùí5i»c<7"‘„²ˆÕNwÉÛÕyf„Ê#A:óe[œc°äóDŠ((åwˆië‘‘÷~ÿÂîARʽ#]çËJŸýPæ‡ ì”o.]–‰|¿¡ýtG¡ÙͳæƒÕ9[É;º§§,³ˆñ“v^ú~f‚ÌPGF3×Q6*ˆ=z ÖÍØ螨•Û"¶‘¤Û‰”±5Üàe,á€DDAý‹­‡¾\ â‰Èlj‡ ¶½ÆŽ|{ýO„¡ÈÑ—å(¸<Šùö\À‹îuÏìZåd×=HAÍOÕÒ, sï²%ññ"=Ž!‡Î\d¦×j ¿ó(ç@ÔèŽgæUgéÊgçD]yLÔ±ºžíñu´ðxúmç “•WÎsbmž·³ÍÙEÁx±4EOƒç%¥ÕÌùh¸êgŠD2„0Ë8ÏŒ+ÓIC¬üó”!<„ÝÝW¶–—oóùuŠå¢»ËÚ¬—Uz¢é7w“mn&èy¾ãhÔŸœ¤pç–; Éþ|¦WvP¸ª®`ržÉyfo)¾DñýuQØ#ߢøþ {WŠïQ|½’(¾Ç“âûë•|¢øn Å÷×+ù@ñ=vrìCÓOøÅwo1ðŠoE€?P|Cj)ìÅöÊ<ð(ã;óìÌH¹nO‘©[ÅAOF3ÄÊcqd6U^i–w˜kï>Û+uo\ĉ´–öéu.Ù™¯sNúOH㋜ÿÆ5¬ÇÀ²‘¹Èa–oîUÑûÞ Üíп£ž|h:ñí_lZ``ú=÷ËÃÊZCá•^¤1„(‚c¿ c·z…¾,÷;{žÆ¨uu>;TØ_Tû†ûíØ„gþæBAc'‘áÛ݃šºMÁ»n­6hÊÁ2|×7#÷7#10&tþ C¨{R®Ð‹ÊÅ øäÜS%ûêì¥N9˜AZ}Á§ _ô\eº¬ÙûãiÆåø§JËÓÒ׬ÂÀC9$˜èÐæÃçi @õõúVo_ê~ïÈyü U¨·r[fÍyNÜp“ý%“µ ³æ+á¤oßñË9V‹å}"$ ¼7L¹Ë¶•U•;Ã$Yö8ªªÁ)çQ­‹îA¾°'éâYYS4€ý»H.[—µÚ†Õ(zMÔBò£nz©Ue6²×5éï«*7÷±G[€ôíö‰)dÎûAMRòïïì•t›IµB`àû‚ðÊù×9>O£á9‡÷Ò¨F÷^Aù ëÛíªÕ Ý©:æ|e÷U`rxµe}ÅÝfÏ' Êé¯Klê4•l‚þ¬Fw}˜žss ̦ˆQ3ä#óÞ(L/{5CkFzŽP}&¡Qß3AWù±nz;»êÿýçpS¯$'¿<[M®øuæÚvyW,Z¹ÿ]rémüV ©µ1Û¦ _5¥}¿{\;"jìùfîšKÝgÛÓRÀi‡¤õMÌÝ±ÝÆç¹¹\ñ $ká€Ø?ÍÖ¾é ei½ïÓè€ D¤õ.Óè^Zï(ƒci½½0 œÃîítg p§ÏoMÌQε‘¢8Þ̵ºë§;pMMDA7ôÊ+ÓpSæ#gxV·÷Ùñ °Ò{ÂEÑôIY|Ê8ËäcËÔ¯38Ðéó¢r&JuÝÈÇÎRTÝ>ÒÙáÖîÎîÆŒÜ:ÅÙìpäxú;ÅÜq ÌðlKÐõҤÀS¢Âwþ»¾Qk«˜bÿô‰Žœ`+âïÝa7²eâ3AÆ—Ý‘=VÈ7?±ú(Ò'¢Š¹÷©ùÕÀ“cvÒï{ÒäÇÛI>Ê÷–FWÝ \p)ŠZâhtpÕßuM‹ïéëBS@(á;¶À8gšþÄ¿°–?QÂ+Íê Iæ>ßsÇl>(›RcP`ÅçÓF¦„kùJ2Ÿ‹qÀÀ×'à**Lß°Ñ/›-W¿Ë10;Ùèa.µíÝ¿=Ö×¼òÖ»ã;òö–WS±õ$®ÿ¦¯‰™ëóQ¹8dØ“~-_.Fæ‰ ŸHîÛ.’·«¾æ¹8$½{Bé:w¤¢ä“hhò…æ#r˜}2“×UÇ"͈AE~› >Õ&„8‹~¤àïúCÑZ~秨áâ÷4ÃáY˜í»ÃbœÁ3ÇßýƱk:=bàí¬ŽæÂA%uzwáC²ïvŽMã}ivÑ4ðÞ€7©(»®Tx4)y2 èù©†4)e¿®†@³ |6ˆI€FÐî…‹­­•@|œÝ( ^ i=•@ã~è0 |¼·AÚx~K <ÙÙ‹XÙV…ít‘ëb²í?{ú‚ÕýÖ/Œ<ÌѽËκÂn£]ìcJÙvï–P;牕ƒm¡ »‹b7ûÃÔîJ¹ÏnÈbœŒ<{Ÿ2j™jrÅÓbð²§…­Ì¸XۓǾÝm)ÃAÒöU%,ëa0!»¡zÚ^)›‘¹ÇÐ5¿|Áû™ÛaXÏ=¥qOOL Ç7ò²åÅÚÀèwvCÑô¿»0ÛAÒ⢠mÊ‚n¶ä(QJyä<ÕCOïþB³ù±†:¶¬¶âÝD)̦íY°è+r´v”tå³#Àq®Ò™å¾á¦iÈÊõ-Ÿ³/r¨OÚܸÒÅOyCãÑþ[ËÔººøn!Èû™‰Ü½U·õîæS ƒ ©o…ñ"þN;­lq‘P~eõ­0pZZ­]œ_;WùªVÅQžìÔäÎÆH²ž‘/ ã³OKúYF¼?at%¸óM#įܱO>·XOƒI±"çõWUÞù_Øv¨KíûÀûuÀÀ;Íî[Iº(¯lç\a . W2¶×å¸l:ú³KÓZ>ò×fYHþd—¦¥"æy”Úo@wÜœANÙìAÕb#Pð¿…¬ÛVå³/tç…X´­û¾—^2– oˆ¤+?s¿®­SCèvÿŒìéëÆ™äXf6¹¸£ùDÚs½žµÕ#È/Ü3kËm[7MëÂ3‚ ¹ÊÐÍ!CðѰyªXÕIz÷×gäDŸ=ųð¡ÄÑ2©Ü‰RZò.#ËÐ?{¤ži§ðc$t¯ÿúŒÔämž,CÇÜGÁW¾BL‘wÞ#íwä“v Äè£ƶ¡âˆüúˆìE¾ðoÙ´VêðH:á_E6¤fS+“t=ÓÈÍ!é534~ ;¸‰–|¡—„Šô±‚ìùA¬ ¿ˆdÏbýE¬ {þM¬Àbూþ"V=?ˆô±‚ìùA¬ ¿ˆdÏ¿ˆ™eöü‹X}˜ŸÄ Èòü(V`ò±zsÚ ­½ºÖ,Ÿ¡5#ûº¸O@ôlu>X¹TÇ·›\™F£Ïî€V7ËÁÀ˜%„,–^ÐÀغŒ“U‡×ú¢´ýâ½pëô/Äš??œm½YJxj‘Œæ¸Œó6Íe¨–¥ZÉsh½CòðïxjÍ¡e‰äáßjYå"$ÿAË’üƯ@<óx‹¼w¹ÕÚÏðÅ©Éä”^¿=õÞ>ÅVÙÍýÀûúÙÀ*»ª#$H}ömÚx “_ÏŸÒÞ]·N¢f@ëבs³Må¦0ðA\cÚ»šXa"Mv‚tKÃPýl›n´ÎsUcà×ÇŒ»Ž‘ Ò-Í:PMkôÚøºy˜Ïiïmj0¦½Ã jN8`‹sKä¡~4Atq‘6b¿æh¤ØÔÐä&FcÉîý¨M3ç¬ä7Â8÷&Ý’öôöDuo¢Ë"Ò+£ HJ}îô/Òà òe䬶jé0uÁ@üR£yÕÇn³ÉJF‹qœ7S»)±•äÖÏÝòáŠy8’#Ù{ìb EîÑ[-Àü!YɨjûŹ;ß¹é'K€xH¡ íZè®Y›e˜bùë¹ÖÇ-MS­\2 ̆¬½³Ûƒs–o¶n¹êÉ‚ÿBŽ$¨Å5nÿjÔy» «ÙNô%Þσ6fvyGåì&#Ïs{å¢~g·È¡Ýá Ÿ."躌WöÃÐkP…H°ò¦;{ƒ‹‘|©ç¹(×­Ç@Ü ã¹•|'L•Û¥+Aº(¹QÁ&ÔQÔºW¬ É©¼yi™‘9[d¾*ú¢#ÆÀݹèÝBbà‹èïH­‹' 0½èVÄyq^²"ç<»ˆç¡ë u{òuõX"[0oDYi&r¼£ÒœÃäBز*ÌÖ`à  3"|7ãXI‘-¾¡áb´´ç:"&BÃ3ˆFè¾ÝèƒÇòç¿Ðë\ÌTZ9ÛY` ‘¶ëh¦Î¶ëÔ­˜³ ;z¨+ÕÚ0ÑRÅþ( 9W]ïì–…%W„®à£i¸lzçtÂ;¼hBìR°¡+¬×}Ÿo}gÇò!ÙÖ«¼÷¼G"ï=œ#¾9Õ .‚×ÇÓ¤´6¸×NýwÝ;_·šëZ+~a‡©9ÃÌy5÷ô7âQ.¤BFOvm;rëù‚)È~¬‹XYˆ@œ,[îŠc7êRw˜‘f¯(¸bTgÖy&@8å£N[•×zõbÈÓÜŽX-"„hi\ôÐç– ïPÛ ª:gÎB[ [䕢Ǥr­¼Ü)£wG¶MŸ;ÒjP¬&‹‰;m°°;C±¦êAc*}"Lv²™5‹8lê&xØã`<ówÀ©ðþ‹Ä¨®® ùG‚TB)‰«óâ1‰kr¿ÿÐ¥.汌©É!ò“}+eÍÙGd“oú’¡3µR.¼*­³ÐeçxÅÑS®áhÿm`à“v©‡ ¬j[ÖbH_2Ã\T5º,‹zÈÃ$ïºÔ¨GSy Ò— M±{ÕÉŸu»äVt#¦¤O\ŠzSñICß{fh£Å¯Q”¬Ûº¼¤W¼¡A¼*´[TÎ\Ô…Ðfk ò††æb \OBLS[prsÚ²«‘å`Y9 ‚Þ± ÂX7ÒÊ©a9½û#CÚzíʺ욮2ùuʦ)ÉB»Ôœ[EöPhٱᚡ©’¥vûR”A¾Ž±µã IÉ&Ñnù8dzŽ­ÁäÿšwÛTwõ¸d†{{¬OpOÕj­í²×¡Q¸Hì0¶[8 ”Ëj õqJ›^”œÿ‰•’Ÿ…=O)ÄùV묇+^&È Å¾¡“å:Vñ”B’z¿½žF™Çf)®Z"˜96b&HR/h‹žnA½Mk^A$ñ@É=ÊQ­kÌQ ¼÷ÕàR#¼÷ÕøÀ¹Ï}èÉç%cc›Ú,€5‹ETçZ:š8Û÷·@ë€5|×!õ=Ö"Æ¡½Ýr«bƒnòx~jÿŒ<¾>ÎD®{ÿgfÖÔ "·GB¦F0p @‰xàÓ·íß̦kó“ÏO]ÃüþòÔ¢ÆÀžZ+þðÔP–z¼þòÔœ??µ‹110ùPcC¹x$Ÿšp¾úåé_FŠÀì’_Ê£(«®á›ÛáØáˆQ.–S"S¼ó÷õêìø† §óõ™ ð(ÐäŸÒبIó¨ ðë=pëæ‘>LòžÌ®h½øg>½-K…·Ù«a1 ¼¿J6’Ó+>Þó¿¹ómÕ䊗²,O®š5&HÏ †ÍAü}bsç\?rë‡Þ¡LêŽô¦nzUFOÉ1½-`oð]#9¦w'×Y:U„1X8>z·ÜQݸç3p›/AB€ŽÔo(E¼n¹5ëtÙ R¿9ºÿb°È6¸'×xóÕDcB¬p§ìz:µ°#lÜçë”ñSè›bhË©é‰R„oµj"u´ü,‰W,–ÑöqR8Ÿç¨DAþÖ¹(¦mù?aW’$9ˆ¿T¹(Syœ{·YÏ@B }ؼ~@(B•YU}è‹›DBDàᎠB—r»ižJ ôeˆÍBß·³[rØ4ï‡Aðì™MÎ{.›¥ÁLO–Ý.¼®m´Õɹ%À×ç"8„ ÷ô—"8,R÷ô—"8lš÷ô—"8D¤÷ô—"8½âEpúŒoŠàî„Áïé‡"¸â"ø=ý¡ÞT¦È üTW¼Êa>¾~*‚»vGü¡‡ ÷×/Eð8<¯_ŠàøCœßÁm0LŠà÷ׇ"¸’"øýõ¡®¦‰Áï¯Ep5Ñ"øiÐ~yÇdƒ‹·2Y:›/±d +Ò:ìÞbWƒ¾­gŽ7†ˆ}o—Èæ9³yûŒw ôi_c6m~F™n'³ç‹ˆÃ íJ0%>¨bà'»Ì¢Ÿoc=ö] Îa¤n„8#ùDGºÞfùëȹ¡¿,8¬]ù¶õr['¨['_TpŽh@Õe­ZF~jWìIK&RˆzèxIÉ &2¯4ÝòA,h÷7â‚-rËãYrò…ç¼²TØÂÅÁ€ýBïžb *¿Ê¸YW³j]È7ºÆF3&€ÍgënƆÌùÛ%m„Ž€Á,£ R¸€¼àƒ6V´«}£jZÉ7º]ŠÁDPĶwrQã8•æ†úÓe¢âÛÀ&)c# cƒ:ó[_8ˬiOséæ“¿ÚIÓízî;¹¤µ‘½»çêùÅØ¯Kîš"[,6‚|«_³l{{É‚|Í]pœ»%XÙ±ºV¦¥¿£]pîÞ)®®µ1˜iX`wBÞ½Šÿ¿@¯ÝWî\Ø=Ãf˜‚Üý~ù^ɬAH0ØìT2«À»Žóò¡’ÙíJ»€à›J¦vÐa€o+™Ý^É*e‚L`¿[ƒ4£*%6$ü÷×·@î aÓI»rÞàõ=Ð,ö;j ü© oýK,V·’_Ê`±^–Pùá=ô÷É›³Õ5Z@2¹ûó£]Ú­P»ô#I~i—ŽÁIòK»t\³’_Ú¥!ÀL’íÒîQ»t¾i—ö¸Ø.€ïÛ¥ÍÞ.Ýaàûvi³·K`Š‹- Ó®Lž œÿb[¾?»‚tæåû«Œ ‹ªÌÓìI™Ï9hdt5ÛÊj.ã·~¾©;úd¢î4oj¨1#Ó(PRóϸ kÙ­ý@¯xÿ.:ï¨Nk5HCž1:,ïžÍþLÊØ%79ÄßÉ™äDJcݬ]LÊïÀ@ͯ2Ro’3¿#RR[ÅуK˜»š¤'g›¶ÖíÆºmÆÀÇwàb#ïïÀ'õÝÏÕ‡‚vx²ª(2($¿ƒ’·~}?PVs£f©šn!þu$[†r®&ž›.C/BÅç;ewŸM.œ*PM‘ÉticävI1M…âøð»C…;'ðq•z| ä_0ãë7FUrwá÷ú nãl§xÉNmªqY Æ„ܘþ 5wd¶U›SÞÐø¾Ï²b³ýÙàí»wHå-A¦•qŒ^F+1¶ Ñ£óL¾=0O÷À}y ¦^Òn8T™ýv6üÇ@´Jy5/YvƒÍu”+Íb` í~žï裳4 kfò2/,ÀÖVÒq Ùíwª­¨a_øÍ„*‡_öÏ&TŒÀîÿÙ„jGMnýÑ„ªèè3&‡@Ú$æn°ßÇu, uòö+¤òxÙKF€q=cQn¨+œË!ß Œë‹-î;pˆà©ðxÜÏý¼GžQ3û×6˜œ<4öSaÉÙ<¦÷™PQ³ýŠv>Æ™{'|µpb=¦¤ñwWËstoÞ ÎÉ3¾(Е£“•U'Ö`²ùÀ&T9¯}ÙŒ5ú3a¥Ç.·üØä›7MäÕ>0+=˜úù´Úņ69'Ht0šÁ®P mH\Ôy‡ÔrO…àóh›¶µ#½{rð×£/zYwBfÅFïþ@.|ÙÖÍR6[³ :JσW§€¯YcXŸ™ S¢6éO^F—.EAŸó…Ô¨Â2ÔM6Nc%‹¿ž;êç ]ºÑÝÚΦn%A^> ›ºÉ(òúÙ±¾’M#O×¼aßj¯äذºÑz мS¤Ûo¶Yä2ŸÉd!-r;#ß‘ k½Z$ùm„~^°‹-C׳漃©. S¨1:K1áÕ;Ç\jVô+™u××'d_P䞪¿En#§H"-B+¨ì³¹4qNÞhÊ\ú­˜K ¼"ë_uPîjŠmm#5ð@gsŠi£é É€w óÝg™™““àÎÏÌ+)í{·ø F{¨w`M€ÏC70ºÐÔ™ë¾=†üH ‚… 0mý[OŒ¼õë}ªÚ¶ÇI²{{çbiw¾¯ïœæ4!›"+µw·>ΑŸÙû[CBôHê?þÀ6x%²yÌê-®Â/š¹"ÎÕ¨;ì,ÈøìpS‹ÀÀ͹±©ÓXE+¡¼c`ˆøß-¯†‘Ü:ùœ,pÀÀ¤Ó<·Ã3rƒœã@€ öä€Íš˜~Ö_1“ÆgR˜$73ð¯£Ã6³a˜f¢$HÚ÷Ž [ÚµªÈH^ðiQçŒ-ë+é$²ü7Äò¡ºdc¦¬ 'Ct¹c¤ ]°¬6“ýŒú%ù€Ôö?úFÑŽÅQrÈ©ÜTÞä#jSŠ%.ÓHdùûìI5Äho'‰‡C„Î(É=°ÑÞŸpT z‡ÒlYäbÏˉÒ}¸Ûä²Ýô¬ºçå|E F46߯¡!W¼áO¢¯kÕK®X£ŸHS-ÖÐý­—Nš®…áy!]Ï»Kà§ç¹i²¶'Ïø ˆÁˆ¥­ÊÁ”Àbz"M5ú^F;ÞÒ^31›«€3“1ã¬rÖà £ûÎÒ™¢ma÷~^NŽÈHüV©ÁP¡|^psH@úÉK5´Póx"Mµ “«BÚQ­Ìf[34¬=/´o‚{«—ÉT “ýl½æuXÄ1’ Wküoù™uö²’µ–£Zz÷&f€#–ÿ«zQäK^ž)Ë ¹Þ9Iª"èÉ2Åýþ9낵¥ÝO¶ íS:goͪµ Søú…]m 7 j¦¥0J$ö¿/j‹T¢ßŒ!È+QRߣõf´ÓM‘“ñôGFޤ?÷»³E—Ql÷ë±ø¤§¶]$#žÄ¡þÐÞÆŒÕ$õ<IueüÝYµÔùÐBFõ¼¼Ó•ñU>.§)W@¦È‚~){Úç€|¡F‚о1ÛÜp±¿õ|Í[нÃ\yÎä(Ú*ˆlòÿÍÒ°N·b€Æî€¼"Ò˜uE1ˆžó1#ot»Å]U€EÒ² ’M&RÏ‘µåô^Ë g!"ËW¦ú?lmé=0ƒ3`/x®*^·x;ˆ,y`ec½éNkˆN°µå_ß\£„÷MËX×¥î1ÉJx{IUfµ;kït°akK"ÅbŸQµ[I"ØÚÒó¥Bݨêª^%„ÕØÚr÷¹‚cG÷2S¦&M^æuT8aßuŸ;«º š4±µ¥+Öðhn‡~û>â— JvÃÚ!ÇVŒuÃ4yïËòù®jÓ2·É+îÓð€œ™léĸÖ~ŠüóFtþCG»k0¬ÝÑçñ’´íê;p%W¼}Ö6Ëj ÄJÉÁr~7gýBŸ1ùTHžñA„Íö[óÅ•”tìBæ’>=*ƒûzW7UY°y00ÅÀr¯°ÚŒ¢bœuk†¯Ï dyÆË×'m­®.(òrÊÚ;ÛªqÜÊÎäõ£bÖÜt ËYI›ÌƬvG…zÉóF ËÙѣʶ¡éµÒk&ÑL(º)XžÛP‚^Ó»£:‚Ξßïwï«f27Á£‘L©ypt« ûO0;±C´ë–•bã „ldÿy÷Ï9g¹Ý)DŒo‘ýç_\¦êŠMÎ<ú¯?°ý'ìù~G™ #Æ®´ñ‹¶Ü“­åT† àpõô®B9n«è´Ü†ôµÒ¯ÐéæLÊ„7»žÆBv¬†.ªèê‰ÔV÷˜l™y›q9,ïЗ•›ãÔ[+Hå«§ã«ïëtˆ_†5Sf”pÅÇ;YI_­:çÆÓâùY²kÍD¼ÖhCnC#kÉÏ'×îáO®½õ yƒÀ÷Êz \k àÿöÓº¥V‚uÕñ’~š &fûoÓI-²r[ã~ƒÊS¡k.Ø©¢š§Í~Ô‘ ï˜ë¦5ÙV5+ÐWXðFŠ¢ÔÓ4å}Uñ°˜+±Ìk|í~éuÖ#HÎ¥çæÈÙc6ÎöOCm,=7¯ì@Çï™,ÐŽfN€7¬ ˆÏÓ˜s¥rè*8³NgñJirm«<_<¾ídE#a(‰ÓS røvicÓ[›é+½ží3ƒ÷~Å®™3†7ê¢ä¯hãÞeªáÐ>½ž4=ö|hß’7±ôBPà¡é±7øE¨2[kCïDCï–qn ãŸ'] ©ÍÛh¿ucÈÓâücëDÈ%cà §‡þƘ©f¦•»¸ÈCsþ¾¤NªËV‚¼ í¬P“[æ~â]ǃz4 ¯Ä ôeåY¯*ëÚ‚ £ÞpGÞË ›Ý%¯9AÞñÙcðR›»v.…†ŠSж÷%Ð펅oÈ«JSˆÿ×{ ô+bƒ-7‡2ÿóaï\v+pÓïú†á—ÓNŒ÷e+G ¼b]˜`reСbLx£šwû~«§R6¥ÙðNκýêkƒ«~ÊsH²Òä$I㋺²4¬ª[§4=` ±õÙ•-ÔT÷†sÙu9IAlÒšûóÛDÀ0ENʳñ»’µv‚VÀµK““$ ”¨í8:EÉ ð¯ïféÙlÒÄuÛ¿‡_c,—êaªkASúÍþfšMIT^o±ó+=Û¿  ‰iîÏÕ¶åôš÷C„öƒ³fšÅJ‘ 2!/üa«Všé!¯ Ècg5œ²ÔU;Tm^¦[Šíßÿ‡kÚöº|[FCß(Å wÐ|®§f³‰ùè¡´J”ùÇ–Cß4F’¹~høï:.r//,«äéÝQiUìon¡ÕXõùÆl¨N~sŽ^§¡2Ę̈MO·h«á¸Îû&¥‹eº®9ùñjÞ4Ö­×Ú”L²¬éA&¤h¸×Aµ«:¡úF¬>âí´;_«šv£Èç¡ÿ‘{.@ifÑ:¹º‰|#¤–Q€)Žî;6õzVvš µŒ)ƒ£‰–Õ"§Òdd=ò¥ÕÝ4[ÀOsî• ËV±’‘÷¥U”¾sÓ>'Ÿ{&3:C|iu×ê°›¬Ïr‚,I·(‘œ ˜—"ë]‚-ô#ÅMëÿp`#{fw5Á±QÝÉíÙÔÈÊlÆÀ£´ºsovÒ“ýãθÂÀ؉Ƣ·[ž1Égn(0‰,J7êÞ`·lhuÑ 2ªû÷OC'šoý˵išyÅÀçÿh6š|´@ní{|[Ü™«N`rβf¤Ïø:Mïʧ“Ý–zdÀ¿·Øù¾®0–Íñ6OÒ‰vþ4N¯ßÛEŸke#PŠJŸg1åÙÚo¹Ú€‡S`Sf±Ùrÿ4\«8}žäÓøäÞ϶mle‡À¶´ ß°ß0g¢å $f)RÊÛ›ÑÁ‹ÍÅx:³+¡ÀÀô­ö^®Y§…›m°±í08ž8`&¦ž ødF¹—‡j¨kµlì» 4N6ÇÕUu=Uß/xý`ø^ô±ñùî½ñqgc Èwï Э†\1ù.†VÔ”Ó×Ù¨<Òw\IUˆˆ^41âñ´H©Ö®Ôl †ïx%Ž9{d«f—ƒgÙ´`àQC§tjns=oŽ÷_Gkd‹ ™æÍprëäs ¼õëòs ÀühdQô¾YÑ€ñÔ€,ŠÞ·Ð+þÐ@Ÿ1!'iû'ܲa³ËJêØgÿ„®+ìeëÂf˜‘ß’ï÷s!FÎú¬ª¼aΉÿ†£àllmˆ^b ¥*bÁÒɵßâË c¿XŽƒ·Vnól]l~…áô’É\W6±n0ðÔ󵧬í4×6²éÉ3¦^Æ´|®¥M™É­_ä~êꌯRæ _·³³-ürfÎl0@œŠÆXŽÊ&yCAè\fJÁlØ?—‘æˆ-p4‘gDÑFg@„}ácâ)J¿7 ö‘—®‹LºVŸsÒ{ÉÙë•Iez-úœ(ó3ß =r…6ä“û·¿þš~¶ÈÑ&pâ™~ôê†Çëþ£¤»©!=A&ïÕ8 •ìEM}md㋺¥ÌL)]­"„t¯ç‰$K¯Åa׿EöÎ^?û C÷Õ+ýÅOŽÝ^éÆ 52Vx¥dé}cƒPaàý³ñ0įù ¿3VäeŸ‡GrëŒàDà•~ö¶{XôÀ×÷n@{-"Šõzý"ŠeðQ,luÈvçjç†>¿>Ô*OPca¡ ÀëᬲoðÊ ªè­Ð!œ ÀÛ'nœQ5/¿pã”ÆÀë‡H)«Ù/sEZ€þë•û­[1N&(*àÇHiƒøA~Š” Ͱü)9WL¾Kbô/FØÄ·ÆÝ3XÃÆÏýèX¨^AZÄw@y*¤‘µbY¨ô`TJcþ§àýñ´A>ïX­HhŦªÝžç×Yà' 'ʘOÃÀ+>¦ñ•0{kG£cŠ\k†ŒÛ™bäŠ÷wBIÚ %q>&?%)›ÈwF2÷?þ\nâ¼Y*ø2Ôßè¸õ~bên=cà•_öþOص-9®êÐ_šØI'yÜïgªf66_Á¨ýõ ²¥tÒSÝ«°M@HHZ+t†(ÙJe0ðsjÕ©?§Vå@F¼}hÒjM+xÿؤՄ&­õX÷›´´KÖ,?6i±ó«ï?6iоãí;MÊ(ÚÀ-4FêA›´‰1¶£[Ð& ª¿Éýñçœ2ÖXn00Ǽ=Ï r›§©&@\xsp†©Í¶ÝœÈZ￞¤ëœ•©¶.ÜÊvsS``vãe@X=fØØÂŒÄ@ĆÉ-š˜'Vl;~BLÇó_”ÑJ:lk+ ­‹o$hØM'¯u 7£ ˆz' #æc¤\SkZÞ¡ð‘R¶¡ý¹ìÇ!ñE$àAÇê£ãlÕf[˜U%Ƙ`)ÂVˆmB.TUóLFŒÅA ™~Bwßø<ä^*òǦ1ã[joѶºØ™½Ë6¸Ï⎤yÞ†ù NâSšçýáuœr—ËÏa¾N„n ø9ÌWp&].?‡ù/À£+"\þˆ¤C¢º² mË ˜}Ë¡Çëêø\[¾¦~•|“CŸMÈ¡“ßçÐÕžCWø&‡¾¶ãªZ]mdÄ79ôrèßäÐÈ¡“ßçл=‡N¾úM½ƒ:ñM½ƒ:yÇw9ôrèd~Î"ʘ?âf71Õ«!HœçJþ=÷‘/KÝU IyæÃÑT‰Æ‡ÛªÙR®ôþ"U‡GSh¦›¥íabædΣ<ùªºuôAÂW’òØ?Cjêd›j_ð†JîS'ÚˆÒÇž¿pm~”Èöã ¯¹ÅÀ;.£çT°zµXɈ˜j¥^µoS Ä‘~ÊaøÕ#ú¾ù˜éÿ†5¹{‡‚‰Kêȳ±²²Lím~‚„™úv%Ç‘>(ÜwÕ *ãjK><ÕÌÆ; òLÆØ•ñi"ÈëYîŸwIx¿…^«TW ÈCè=ÊOï¬Oz]uχüâ ô¾#åÞ=C¥=Ðo¿Çuо¯©ÜÚòº¯E>Îr‘ú5…-{Û1Ý1‚|ž¹+à„׫e¶ðûŒÌRÌœýŲSœ•bœœ"/]ì ¿ÑÆäà”ìAfÇ}ÈÞ«­ÄjÅÂ6òkÆÌ™ý½ß±ÈDÉîÈÖЧïN¥ý7”¯_g¦åMèÊ&ÈáÃß«,LHÎKx€üB%’I À²jnüá<Ó÷¼cFúˆd’w¬0 ȤȦ9kÚz•ù<¼ßÃîáo9–+|;êêÿî&—ÞÙ!@tÕQAËLÛ–{y<ÇÀü£?݃S‹µæþý/Ž˜F?¢ó?f‹·þ´cR‘wüúôú€÷OŽw pÆÀØçö{'ë-[{ü/›¼½ $Í>9»½¦éA±Óo,ÄRï§l˜f ̈¾ýîµuëwe­T‹HXFV±V0THÎR×-^‘¹®§¬Y£{; ¼‘Œ÷¾ÌµvÌùÔ9 üBSî þÑëÒT®ok ¼CCp´m»Íh{ÝJ·Ìä«OºUÐõGÅ\‹vj4™Ç£íæÌ"×>Dig=øLnÿ‹„F"f|E9õóO‹_‚Ìn±pˆvYÄÓ»ʾôîÕ` ðl¿ uûÕˆqK§ŒµG õ@v`GJÐ꼫È®)òrÚ–8?¢ îùºµQd†«sb®«­ºekz‚Ì¡x‡äC¨‚ðq='“ž”‰‚­ô§|µÛóÑÙ:Ã'ÈÛi¯ °ŸXÓy{5M5Abe¢ä©¬è¬2Ãácœò_»×T€"g#¼«¥õ €|¼Ó02ËÖ´kE¿)×4y“åXÓoЬu¬Læ(D«çRôyÏS™hçØOæz­WVÎÊ2‚Ì°Š½¡²[]’ùLÊD¿÷/â²÷gYÙ/Êp_‹8* ËΈÕß=zŒÉgû©ëWÝ:o£GLñxU&’)ë oŽ•äj=Æß±…76q1­C®†ij;PÃ}Ëøt[ù0_AÆZ+¿>«b4' Ù:fþ‹ÔKÆ~³ Þ¶Ë §$ºè³{fçÈôs«ô¬fÌp+:´[3 ±± óó^J²†ŽYÞ¬Ÿ0ðJ#¹=Ž4R˜J±Ã8/úÞ'%ÝŠ_§±¡rUU”åÈÆ‹¾ÿR[V ;ZÛLeQ: ÄÌò)_;¬~ï4¢¨›¸ä·ñ­Ø\7´¶'ŽL\HÖM š¥^:‚¼ d²ØÙpÃV-›¸x·ÑX5«~­*FŸ~š¸:%Ș½™›¹hòJ Â^NÚ9äe¶"o/¦#.öNuν,6´}DZêª1uÁ„†+ÛËó_‹æ½íIúÀp© úEGÀU%É“p¦VÍ(+=oùüÌ —2˜÷ì×_8áàª1ûõ3'œkɈŸ9á€b(à„£ïˆµe¬[Y$Ÿ1Ý#^HeVÉÖ9§ ¡+—(60;d¦"?"ô3±ùH‰d——‘2{—GÁ!­}ljž,±¯˜u•p›¡V‹0áÈž…Âr;ê9Ñ÷$ æTNC±a•˜l–qàfýKdN£Èàkè¢ö&階yÅ’ñÖ€.øÚ+cÞi¥O&+܆²¥íª™c âê¨SÍNÑwLöÅ V ÌO È|)W°©ê^€×³â Y•*Ö¢œå U-¿½¯Þª‚¿ªoº­n}Ô¼m>Œ•x'ò¿±Où}Îd™t‚ð$åä±®ÚûCµµÞ«áJ=»SRN9òý€“.!ï™Ý_H9«}µ5;ÓïT±ÉõäÙ”ªâ¢V Ö/²$Ès›W`ßÚ¶iý„³© H´ÍE \˜¢Úÿ­ ArmÞ¸Æzäf+·9ñº„nHØ-Ý͵åP¬Ã°ZEGãv¤)IïY·Ã:½ÌÒwú¥öÏÒÿB•l{úE"¼¼G ûÓÙZd½]ž™˜Ù<’Iµ‚^$¬õ_§[«SD@ 9lÃÈòµw;vy‹¥Úú,,ûNH[UoIN9γ¥h&Pà‹¾ÔäwÏð…lb#jÛŽW¬Y²à³ÑKïi¸ÖÔýòëÙÈ‘®Ï V5uê×/cª?LÜýÔÏS¡Ê­ý¥³ôwþƒR$—½”Xb ánYŽg' ¯€Ï¬*ÖlwsT ¥ jj=?‘ZuÛ´EíxIWÜ‘. UÅÆi¬¥çË6‡–¿”úqrPœ€Ù'Ãa—¹ÂÀü“á˜È}gÏ×m~Úëí9ìÁóÅ?Áö ôö`j0ðÍ6f]טÅ`àË6»×úm®'ïø²Í£=°A¶ç=¾ßæuïŸ uÙóó6·&lóv$È÷ÛܽaÕDï¶ù8÷eï£Ä• ßns«šB×¼ ÈÛ<\õôé¶¹1ƒ“Œ é69jÇ,Ô7jÙóÝ6ßý“±×r•®'Ëíó6·v&¿å‡mng6Ûüùq›÷ÞiÇÛüùm›§0ÄoóÞúß‹®v¼ÍC°{R¢˜˜(ú‰>=‡Ûãs›ËÚrgD³õ~†!!A_¥Ý;XíêuKçZþBâ€à–Z=/ªØ0Ÿæ)9Çí:q¦ç5ýBù…¤ÉS·Q¬®·ias(M¯Skx[³f™00Ç@@6ŽO­Ž ø¶UBÖüò¢ÙˆËN[Tvš#–×oe§ •æ—Wõ”Dó´Ìlm‹zdÄéþHõ©µ÷­[“ïðù©Õ…¬ù“&É»ýÙÚ¨µá+´2ÞV¡ ÇpyR†ªiÈ[^²C,çÕZ4[ýqº@r ²ÿó_¨ŽåÀe™?œçòé9.—„Ó†`UUR¸ç•ƒª \ÒÏ¡Qb¡È/ϨXN!À$ŒiμW“ÛtåºÑ r>yöy"zë•¢tã\[ $çD´«uï—Z½Iȹä='*ÞÄãÞ¿£¬6 ½w ˆ4«´È»ªpÂÎ6œÂ„ÿBÜZÀî¿Fº‘92㗓̱mâ¡t¢ô0L™aŠ•x¯¾Ìe9¹±¦s~ž{›çþå—u¬ÆÔ¯Èëy¢ðXŠÞShWZˆsLœòïÿÐ.ã>‚k=%i@~aÚ–ÔSÇ7.˜[::æsx¦<ËBK½X:KqG¦®ŸXTJomE‘OõÁy¶0Õ-kÈÓ)óD|Ï©ëjÝVy9hᎻQ³®–ŶI\Î:íÎIÓ5\ ÅÍÄ2ÇYðý˜jVJ©*¤5òú±?ÉøöüC'whAÜ ø¹?ÉÁ{žÿ¥?ÉàýIP––Ÿe²‡¢ñ~–…–ÇN•ªƒ©é®ð ÝUtW0á¿¡Í2Þ\„B¦Ö>¨t%äõ '0¤X¶¬Â@á×íúˆû´31‡ÎZvØ{M A*•ŽxýÜàfçv¶äP-òÀG>u¦ þ:Y3v€ÈÓìFox!¤¹ýÄRÀ¬;š|°Øö;us µ·¯ŸÕÍA´<?«›ƒ zæ”­s¯¾bÍ4x='HÈ:ê ç³”¬êº‘s'*ñÇ·ŠhUùmy]$d}ÈÄÙ VcV¨¾BBÖÀV”í½nd WEHÈú¿T@ V?^3W­m1ð ÷û¥›´Z-“+M¡0ð~t®sÈg¬Ô[c†žŒø@‚"Uñ¦œÄЋzÆÀU•¦=VÏãgþ®lIrUþRw×âò㼟‰˜û ØÆØ€Œ·˜¯¿`–ªª{º_3ðFR™°µßÿ`UJ2â¬Jè%»=~fUJz·ï$iöļåÿ¤Ù ð Â,IcJY‹}"ÀË;A£Êš®[Eü„÷WàØd¾uÓÜÙ‰±¹Z™Uõ.ÍZ ã‚L"‹œ‘ÚíëvÔÜ?bÙé÷qWÁ¦¾Õx#ùy( ²÷RÛxšIW r¡M§Gµƒîqf¸!& ã•FÔkÛDËÓ¤ÊG¡Ë¯ôÊG6E˜sŽÛ›K!›ï—ÓÂ~œâ'¼‘óG §ÒÖü˜P‹já©/蕎×ùXx™žúBU…ŽÍÁÔ#Sc#!ï‚L§£Ô^da\×e;ZaàqÇâö!Ì<׋ڣ [†L§œF ÎQb˜˜û-Œ–\ú~ë¨Åí‚”¹éLÕ`ö¤Äu ¹Cœ^+î’ªðÔº@É­¦JñjŸfò09!z¿ë¢*øÞì#ü¸îšJg¡‹íø¶_ ðw¿<•\ƒ™ïþçÌ«Bó•|(¹©…˜N®ØÄ|–º"· >ÍÙº rÚk>‘Wôy=Å""‹uœ·šÑ«ceˆôDZHUÊr!H¬ šØj^¥"+ 2K9IBíŠql0»ï¨ý9ˆaàkCŸ(UK«˜[ËÝ;¢c†Tº/˜±´øVœ Õ´òŽþ*>¡bÆ"Ë­õHQ­ª¥Wÿú‚]>Ùê¼C7lùîö7È6аG ÃÀo´¡c^Á…þÌpˆŽ‰A­†Qäíé„Gmu€ ø‘^)c>Ë'lÌÊÆü,¿2t”Žßy,š¹ßc^¿'µ²µí8 e1špq¢Üg1¹µ°$@Ò8ÙŠÜu»ò¶k‰HÞ$hJ–™U«Ç.­˜W²Odð°Z›CrAÚ›ÁÿÁZ™Ú,Z˜©*fgÝHð ˜Ä÷’+É×zÅÀÇI iNÿ0EÕM¥H‹Ìõéø©,äêèÉ ÿ 6çGËŒaÚ”j`5A~Ò6oÿäJ±ª }¡2l€MLKîvuÑù°’Wù‰ÃÏ6äŒa›±c‘¦åõÙè@ÄR»“e×-ж±Ò:„îÑX†>uŽgB¢NcaTQÐ÷ˆÞÑ£©i¹ïEœÚ (Á÷ÛKG¤Ï‹.M_ï‘ÖÙ®y†Ë%²Æ-Ŧ—¨Ñ È+ò¡ŒÝëî>w±)¦È£ÇÝL¯€áÀºM>O¶³0^)°só²¬ä½Ÿn·…7™8¾%—›ûaŒnŸ&ÈR HhŸh6’UdÅÂøÿboHÍrŸìÙÔû¨Nq•iáLUÓiéûí$PEö#ôéöî¹{%sóë­{»‘Í SçÙW°b×á:¾ö¥QH:÷þã-àd·L)Ú»#‰êèØÝ¾mÓ!^±lx­³®å¶‚Åý¬©zÿ0–îÑ(܈Àš¾ß‘{{|jÑzãxHÝ3òÔ‡Í{z=Ðbà×û{œGtH&ñ¿ç{œl§¡œ{G2‰¾Tš ºýˆÆŠ¾'—¾A—!}q"“ž:‡øvsÇ×ym•ûãI­]D-µ¦ÙØ$Šr•÷­ž=¨úÜ$Î!PoѹÊuß8t¸ß¤îô/ômÛÌn…&À»Ž9M ¹ôýÉ&H²•ûN| Ì^ó62©Ô–v{ê»ç× Ð=í× ©b"-¿bètô‹ÕROd¦_òÂ?R0Æ¡qQ÷|åªê‚ ?Óñ>Ô+½ÎÜä"ûVÓxêz…yæýVõ®S¬'o(,¿>)Æ)¶Wû¬5Ó–"S N¾'¢¥ßñó†¨"7Œû ÷Å!½x"KWPéolÃ4—utÕ̲W`PÓáæ`C-2£tËp’:‚‚ÉM»ÉpІË>([î1Ä¡ µª›¯$ð êàþÇjºÙÇ3!žJ÷½fµ™ [` b#TÁÏÓgåÔ«10Ã$ƒÐ/ï.­]츪 «ZÄ.ø†53[]Ø``Ž»©Úƒ¨g6#æb=¹ôyÄ?Ï;û>ð½š4²#ò’¥T5f]ëš$Þâù¤0¬ê­êûŽ /ç6ÆCƒÕÍ]Ë £("¯T€1Žé<°J"ò†¹Ò!Y[˜ŠoÆä‰÷noÓÔ›ºn鳓<°;ØnÍÚ úD˜U M–éFú„"2ÿ®5z»º,û¤ωü]m‹p~„Žäoþ 4ÅØ÷ø…áy .ª'àå=p/ÌðúJ<Ôƒ˜Ý{•ÀÀÛ;  @2bRà*J;ô0»ßãÜÃIù›¿;‡Ë“ ù›ƒ5U˜À‹·qgͺÂÀü P{ {ž²eÝðØD­wa++áT†üÍ_‘“ì^_o‘.®|A^Þ"7ùzõ+F†V‡ä.N9EÞ¾Eî;EÞß"ëÖ¾\={‹œô+ò‘b±ªŒÆÜ¶K­æHÎÿ‰¡ê‘Mx7ë~>ìöa÷ Çg±Ý»Ù{ˆ6 ˆî„æl› IcìÃ~F%‹Þ7DøPoï€.2¼ òaO~”>Iäû¥^j <äÛe¢6§R…*¸â–Üã¡ÿ²W ÕE3” þKø[vŸm½ˆŽ± ­?½l1ÙÅÕZz¤ªÜ6ä.qøúÆ=’5lU«¡ÈË[¤bu_ÓYÒ@] û³\:)|­N¡Û‰lâÜØ÷Áלd2äÃþß_˜!lÔ“[5Õô>³“:ât¯qͺN/ÍB¯Ô°ÿüW€T÷Bû”2È.(MCÇÔnáZôÓ˜!MuDð铬t?\Î%™q_É9\E«£*s°3” ~_©LoéúJ%¤/‘³üÛJ¥‘dÄï+•&M÷ë?*•ô‘-9ԹĠʱ ¨5f7"7_T@ÿÅm?ºˆ}ævÃÀ3M–!²s? ¿j­ˆ >±½0œ™jPš\š®/‘­ä¾ãT2&0ðöèÖí€"[røIô­b¼m§ôƒDÙ©¸ñÅÌ;/:±ï]Š4n$ ÌWÚ=µm¹XG9R‘Ö^I¹‰mëyá #_ðÐ5çžfšfÖ2aɵÃV,†@ö¬_B hÚÎÎìÔ‰ í}µCj‡$¯òÜJ™^¹ïºUb_é˜×ÄxMym‡d}©Ê¼Ì°•þñ•»ZÂz³»/9 'Èû[¤vÈb)2{‹t}žžT‰³ûÕl­ÑÃOt­xÄ’®;øÌ›Záà“}ÜwQ0nº°f¯Ê;ûa»ràÍh& ¼àJ$8 ­[„VP-É2ª¼“€îÒåÎk­ x@ƒ ]¹nKUÓ{¼¿ݹg׺6˜a‰žØ¦ÓwÂ…Žf —~`MHx®¯]ÝJ4cà™2(!oèFtï¨+!k™!IŽ·Þ{ä^²Ç34¶ÉÈybJÔ²9Yþ`š½˜ñ'£Ž¨z˜ÙÒéÂK ¼œRØGaÂ7Ó´‹åÒXzéë÷@zé[pB Í"áÛ(]3YUOsÿHGLÊuþ·'=m«=DzS¹îÏ‘¤ v<ÕÍ66 ¤ö3dQA€F¾Ý?naµ²»˜í4C„õâ_Gê€q›ŽQÝRCØ/>v†ÖY©„‘†wÐÖý⣻p8]ojÛÖf\¡Çëô‹O–q!Hv@UwfšÈãÌ}¤à*’Þ) w&$sDZU¨_oŠmË¢»€ÊRÇeßi½lûSÈÓþ×ß#âù\œTa!køø$µ@ GÒÓ‚·²Ü0ðòĉ?F´£;V.KúÙ$Õ¸ ëÓ÷màûw›…,A^O?è"¨6·”—íš–´ u:Dg—èâcºj¶Mš½Õeôœ˜ÀÝÙÔ¸0†Ô²ÿ…ƒv¤±ÕhDÔ{—Ò"-¤E=GKØ yð¦´H›Ò"K3vÏn>ßâyDú~DÞ¬-œtó•Ç?Ä܈£;*‘òqnï¡LS7¢Þ81=rä_öœºÙÚ:9¢=* IÝ„³­¡=ûTI°IÀe¨ ðAY@‡ ÊX¬sß0È=* ¨Ï˜#´JNž¶÷¸^÷+Ѧ» *süI5­ŒÍ îk{×wÆ,yåØœ‡"­§¼V%9NvÀ qȪéÕ¯XU4Êä¹u\ìÚ­—y#Èã($jkD3W–|¤š–ƒjúv\ú’>Q†ìòbó¨ YüQh¨É¼Œ9Â^Ù–}[j94tÌg’C¦Ý}Lÿ-7F&Ü×ÍÞ‹ÿâÕZ&M”G~²W@49·e[T¹IQä×Ù •lˆ4“V‚¼ù¨švDÒMìâ:ÒL¥¨fú›¼¾‰®ü˜…M’y£á¤®[®†^ýNRá¸êRÅRqzõ <$Kªh]Ô$·u«¦… ÃntãŽææÛV¸]E™£C=l»£tóƒ/sA–™×8POÚn “ô×qùDÈhêà®îµ‚&߈üBâý!0Û‘-æ’ ïÉ'Á½¥m*ºÉV“íXAÙ+SB‰žÙMV u•=kb·œC·aZz yçü‹P‡‚aMhK.æiKZ ^ ƒ% Ü'ïs¾§oþE¬‚ç\8Vè½T ox¦J…ÊA¨y —N4ÿ¤ à[§Ýߺ«7G’Fh9÷÷س7l4ø†Ðs&¥š¸)00'&4‡ÃËÒ2‡n{Cž[uI7êÜn÷ä&??I&'tªñylÖÅÀ‘"ÿz¶ ¡†—uGìa³pÐÍ‘¤˜ò…Pg1bsÇû¤Úr$iDÝ|ÝzÀØØ °9æ´IGƦÙ@­(G­<¶Ø·yœT¹»ƒ²M~!`G÷ËñÖÇqÞk¹%#^O±+ŸA÷ãk…ª„ÌùåI ²‹+¶²l H½ä´|ëu:ÂY³W\–.ìâòmr›ÙÚ~GPOÌQù6ÖqS c‹) C&Çžk±íf]±.§/üãܾ¡vÜ«™I·G A~¢>¦{Õ*dtœ¼rÜʪ>GÓÏZµ;y• Šõû(¯„Â’û:þMš¼ËO²E…0´î7¦œ*ŠLªX@ócr17»ÉKŠç”àÅ:²IˆTÎQù6êëD·gɱrl¡`”_(Ïçg‰$F%µê;ú-?ówH#’ôÖæzNñÈ&¾y% %DG&ÒyN¡WwÛYÃÉÕáœ̓^µbªzAǼ ]2v¯÷lnEoÅÓoòŠÜÛѤ÷NîlXG:æ rþ¸s÷®ºÖyG¬ÃÔÆTÖþïœÌ¥¯ìQosÿÓúšùõ)Ð:Ò !@0v^+(aä×WCÂc1*¦•‰RV’@+êZÛ‚U#ßA+¿Òœ_•Ê“ñ\á!m×'#2°…j,›Çm™û±!!ÄÖv«J§…ýšÔE~ýÂ.qÛ\U›^58ÐäWäP"ÐGBÝ}p÷“K/ùõÌùE`8Czàä~ ž‹ ¼²{Õi˜BgÞöo,È@7m{é6µx‚ÌïÏ2»±L§Ÿ×·›… ”='xy¢oß5Xû橞xÂn˜h‡¥ºÚ—‰Qõì`p(ø»rÄâþû'XÀ„ºŸ·€±jS™™Ý¿g7Á¥ÿb7õøõ6EFØMùã_ì¦ ß°›ú'vSþø†ÝÔ?±›òÇ?ØM}?±›$þÄn"ó†ÝÔ?±›òÇwì&ùÄnÊÿd7‘»ü‘ÝD‘?±›ÈýÈn¢Sè'v½úOì&zõŸØMôêoØMò‰Ý”?þÉn"cþÄnRdÆýÄn’œ Sf=¢Á™CÉÚ”º…ïžÓÞ:Gè¶²3ÖÉI®¾äPÆ9€×)ØÈ©D‡N9X;uäÒW(h–Iyï.¦,k ¼¥vö$ €Ë0lx?›?BɻŬlµÃšÖ—œ´«ùvé@Ü—JŒ†ëÿvn˲ª<¾¥Ñ­öæpž«jþ—€@TÜ#µ®þ!šôf¬ª>| D$yÓå „R(XÖ…• “÷Ä7ëÿ5”XCbZóQš©&þƒbØc9X÷•×2Õqèy¾Y¬•„Ûår,¤B5O|³þw¯óOqMÓmî4qÔº{>_,Ö}AÏ‹º—SIÈ­¼ýÖÖV­*WS’®ƒÅúï^ %˜—îéõÖrMçÐ冷=897ÌŽ??ïñÔ¼âå:÷|.M5ØaL>ƒ­; ’"z}ý‘g°`×F0û ΃å<âñýÍa8b»½gns¶XÞ?kIg§T'8 ¥ ‘;sHað‰ÀXÌRJÕ‰¼Ýb@ 82Ò£oÆë1Œ×¶ Ͼ\9_óHÖcõN^ÏÝ'x_ý˜ÏëO¯É[ìw­`fUÜœ"xýŽVYÒ"àµÕÝ4MrÐk¢æß¨;&Ë­ÜYLi^±£Þm1÷q»£ØV‘ó“sÈðÜja·òžVØ£D¢hß,îøÄ ˜×EˆmŠB cTŽÁÊЋÊQª›íf#6 Þ±] Vò¨[Ú–<úHNaÅ¡EîOʬ|ÀàóŒT¼ŽÚüÂvÂ͵• øn/ýõÉw¡bn­O6[È ÄVE PQƒh!aŽ?_uœ9ܤû“w)ŽEå‰rewÍÕ(ã/GÕ[5÷ÇZ…&÷‚W,¡nåål«uú˜\Á„èbìåQ°‰—4#ˆ¥ÞêàÞ–³Ô¹äÖp fÈ_ÃËåÌx×mS,3ÁvDçFËÚ©Ù#Ê"HC¦‚‚×bOÔ|`—q´“Ø8NºæƒO8Œ0¿ðXÉÐí v‹‰aÀqðX‘…s·»Ös=Ö„¼` YpoØÙ}Ø}Ô*òŠVªh4Í.TÓxOƒ'Æçv`fà ÑFQüØd«ûEa0!`¸s딞ÖbÐL0„ŸîªÓ\Œ²]J fùˆmžÖ©j Þ°îY‰á…ª”@Ý7‚w8z¾OÃ6ŽÁ3Í®¥¯H4Ú™WdŸ/Úu|f“íðJ÷·'k91Bžz GwÚvZ¶éˆðòÏP>y?ÖÉíÝdÿu¬#2ÍZV¶$oózÄPÇò6qnÖkYX2žW¤ÎCIÕdÎ]BB|ÑÒ mÍ&B¦G„àÑ#ÿÞ±˜…þÏ _;Љ]Ó¯º'sézÃÞíàÕjGž·£àùУœo~;«›ÉÙa‹ªcj|•¾Ž¡™šE”KTÍ’¨DÄ`OòšqA–¤ëãʦ٣®EG>öä‚ÅoÂütm\XOÞ{BäÜ`”z±“;Š2Ád˜Éžtc$JJ¦ÔqÁ÷t-Ö”LÉšÌùäøŽØqÅ6 ,ï×¾9Öâû‡[oHÎ+sé¬ ^±´ˆ:¦ºifL¸ï«pSSó…‚éùe”1S"_‡Ü®fÁì( Þ@Þ*Îvß‚5VK[að2ÔûðD×(ËÍØh£1øÀp8søG3…ÖM¬-ûÒÁòà+78”_5§‚-X6LôªSª$äå=º©(º®+ç­(yÅÅ:iŒ#[¾CÈ„†ÎîŸy×ð¥eF7„DWM«›<¯XYv#!3BʃtCÑM„¤n‰½Œp¾.ݺ™v$ã~!¢1r¿OVvsG¸’•5!ŸÉÖ“täŸï…‘ÛA¶³™ì±eà’¿„\Vw¬x'//¤Ï m¶3ùŸ×ë;Û|%Jz{x[]˜bÚÈ ¹¢êëæäÈb'WBf85-ûz~ªÉ2C®·¯¤È;ºe™½€a Û~uG]¼<ýkíDŠÝÌT®]Af^´¡ô”û¾äØp,›w´hÇÎQ´ØeÐr8Gòr^E ÿ¹ˆ¾–=™!É•’ò${IÉãª:\·í_\£[11n!QøTÏ,¼ÊÝqn\fò%ÙKq2/kT(Õͬ1ôé7BîNñAÌ‚¦ JÞQhG¼ Ù¥xêièÉ\JïI8ùÚi±JÐ7ÇgÆ‹˜¼kM#ÆQE1ýÁáâÁkèæÒÒ°ÇRä@^(¹__îäj8Ý5®´Èvb‰„6UÁÈw”&¤Èö1žýÜ¿Œgš¾—ãöãÙ›^´Í —c¹aýØÞº }¿}%ëªHžåCȼ°ÖØŠ½ŒÒã$clŸ{G}ïþçjÉבâ²pÑ‘3VšE†Œgvƹ¢ᤣa[S™•ö(×u(YË 6sY,äé¾a kù ÅœÏ9Ùˆ³ÿ‡Cu¾æ"_K½‘•6Ã^Ø(Zïúž ³Kæg¶¿£me>t¦Õý¬5Ù7³[¨™áÌμ°«^™vvš$ï=»òDŠ9‹W/±d.¡Ç_LJíNé½z%ŸïžÝÜ=|t/“‘Ý~PàkÌ몺Yhe NÖäÛåðìiÜíð|ÛxÎ y}÷ìVåì,QtÔªJ0¹‹f×9+œ‰¼2EöŽ[zäüV КÕujî 2çoÙY8PÄÊ=U'Á2@ê·ÏäÊ«WIÞT±À!WÖŠ©ì6J>Îë!_Ý6ÄÌä9[Ý(‘ëö<‹ @DÍZQ¨|?Ѥü9üß±¬’¯^ÎzS‹™Z,÷ý¹™ìÞ&¨Uná®Ù*G2?ïWL†Û)ÃŒhm5JJžÏ»î™¡ÌíE2_Õ" y<—P²:g°,C[¹tÏ0YÇ E·Êò^–”¼¡ êøÅ‰‚cÝ•œX•÷£SùÖµVTî-Mdß¼£¼±*î2V6Ì®|ëàëxÐËÕâˆx^غԽÕ±DBêÅ-sWëÜýf "ÙTDÂv±€*ï¸fL‘¼ä1?Cèi©­–Ä[{lÑuß°¹!A±ýð8k«ç¦Ç`Xö÷R{R5¬]ÑÝ |¼f\C"µj&x‹§ŸáSjvÓïégø”q=å[ƒÁäÔØâõç¿DP' þ&‚JZüM•€¿‰ j þ&‚ª0ø›*´xù/Ô ƒ¿‰ ’AUü.‚:E%Žþ&‚Jþ#ÊK±êÖ8n;Q2–l{\¯/YR'h(0xÅ‚·XÎÖ—%³Ç칟äû£Ìžä?ðû£ÙñfÎøS µ´f50Ó+tÅÅ~t>-f/Õ T™e.åšÃMØ]·ÇXƒÐ¢]+Û)ÞÓìþBµ²fó\”Üa\ï¯×®k*ëv/…dX¾a8B‹ZlUQ›|×ûéL÷úKê‚ÙÎFµ OÁìÈDb!z2sêà ª=AÇEÄzºÚ˜­ª àýk)F}ÌžÇïãXÃóü}Û£3¨àß¿1EÂ8ÚÒ£Âà÷q,Id\¢®PŒ¾¬ôæ ï |0W$ãòiÀ»cR<_Æ\nR{¨¥œI‹÷Oõ9VÍx$8û1|3áìì'îjrɢݛ\¨Ì­\ÔZ"{à2îÿÛKÊ_ï!wg8]CpGòê^íÞa´å0;sþcú*]¯o}’wmôÓIúb*€:Ó2÷¢¶Ë¥+"˜`0ìGË< ï)â¤ÅSM N­²ÜœR´¦%-fç}VÒP¼0–cÇbrTÑeZ¹KÔÒm·v%«0x\®³CÞY)L8ÉG?Hº©ˆa7î¹îÔª0øDUbb®ŒpáöŠøÏé"/c]0ß›n©;A…&b9Œ¤è¬V+rp}'ؽm¤ ÁéÚ\F9Öà(Ip¡‰?´¼7ïÝw[ÃÍq‚ M ³˜? ®kÙ³^¯´GÙ‹³ÚkÕ—•3¶!oä„Ê2°¶³›Yº’÷¯:GœªéýQÇáüv²ïœ»ŽÜ÷% R?¥’8n}…Áô»èÂ6að-ƒžüÇ_¤ Òâ%” ò‘´ø‹#->?¨4­¾:Œ2´3g:’iZ·ŠTi¥î•dB…XËu‘Œ×/dÛ¾’(R‡K(Eµ±Mغ&=‡ õ?AÏ:®YrÛÅ&ZBfß,l·ïŠ–ŽÒÕ?£¹Ý\|’½UJ!¤) 2#ÉP:Q“§_?è´^Ç@šr!£t½¾«h¯N°i&È(]“Áô[ºÆ€T(éAR†œƒ½i³KÌiBfßIðYGòöe7í$HÀ<’ÛïuG0 ’Ûáÿl/ÃÙZÁÅzr[Œ‚“qöl¶"·¼R•5nE%·ŠulÃ`òYZJ-ïÓÏÒRÎÔSà I6aðQ¡¬Z»ƒ¯XÑ#o§@ \UËšéZU¢Õ¼“›ÿÐëf4¢ixÞbð¸Pß ÁذÅR+ÃWÒ™çGù+¯6_Íœ ø¶Ðn;òµÛ—ËGRŠüÐÞòú¢ß°gÔ“rh›XÚ.¶éíÚ<7Ûh™ûîqÇä>™›©d0ãnJeµ„ÈY.FAæPÜMßtµSƒ®÷ÂZ…5źYN¦[Ș 7†JÅLŽr©Ë™ÏóvOFá›ÍÍàbâmU¹þóI­kØÕºè(]/ÔºÊ]­kƒXõäð¾«u »Z#}¿&ïj]¨uÑ6Ïň÷6ôëª7×{òŽÐbt«Y×­dª„¼!‰„蟨øÊ· Y:Já0ú‚¹gŒòOË+B>1oiƧ³ž•f,è*óü$ð§÷£ ÜK%/7†G6kë¬ñR–Lƒaö${ù…Q+µ³Hí2š<_]*¨tê¬áaj:¾*ºì•%ÅäÎ ýºa0=“#Àcmç,½¡³Ò-¤ûjäƒ7¬ Á¡`ý¶5[ @úórWÁc¥le+]NkæVúC®IÎH Ÿ“¬d¿D•&$L?‚c£Ì\Ã-Å:61ÿ?$Ðu6_³Ðÿ˜á£sLœ} ƒ¶ô?Þp<[L¬TµT} ²é…FÂTe 9dë6óƒÿ3½ Úh €il±ªÆm™1˜ ²’-®‹ãˆMkˆl·Öö³bÌp®oî´Œû3ØHþã+¿[Ì{t'çý"ÄÐðéQ{®ýØ>-íTº „>¥§DL,W+vzÔù§i]»þ³¯Ð50ð˜¤H"æŸ=Ʋ8ó|%Øç !C Ŭ ÊàžÌ+µ¤;¢/¥·ÜRé£b­Q šP.Ð-˹– }úYÈ!Nþ=æ"/Ûq”D¦õn úb‰£û œÕõ)­¿ƒÿÃÕ†'^ANš|¯è+¥kÂàÓä%Ÿþ°ÿ 9+[°6Ò×b›­#å²V9«u´_Ò·l ­º‚­9ÍèeÉu%vYg©Šœ–¢³&hW„Òq•il7và&J³—ªœ"Þ:û¨·®AåÐf(1LBòˆ4¾ê%B¤Iåßeê6+¥X®W ãa_òyò¨ªrv‹äxœ°Óã¬ùÇì¶j÷%kµõ{6n")¾¨ý¤|9÷ÿÒ¿Wü ¯©þ}Ó¿ß0øAÿ^QýûfŸ@¢Áßôï' þ¦ß`ðƒþ½¦ú÷ü ¯¨þ= øoú÷šôïÕ¿òƒþ½¢ú÷@~п×TÿÈú÷šêßùAÿ^Qý{ oI¬äý#‰õï|œ•6!ÒÊ 6çSϼËW L)àzÑ¢— ƒtmÙ?žY™Ê Öæƒ ®”,y¥ò¹3¥)[ ¦/Æ_0ƒÌ¦‹eðIÕ-¢µÏ…n&µ5d°¥Oâ7ÙkŽ…¹¡¼xåt乤ObíËZPÿ¨ô2ŒÅŒ•>¿þGgsk¶À5Eöóõ?ŽmÛ³šðã\”˜‡q-0øé?r½ #S+Ç`úñ]o¥ûÆŠx²Î.ïïºfä\ë¨vAò®CÄé¬Öf|n*ñ»Žž¥V;MÛ‘†ÕË-}2%Z£³+ñíœÚX½hz¶ª#&K^ŠåAz¨û`»®cP)‚×wµC·}÷\±2v²Ó…èë ì<û£Eß—méNÕS †ô>!÷·¥po—"Zy,{Å¢bäÑ7ìȇzÑzܼÙ9`p_þÝÏóGáS-Ç2ç,–¡‹àã”Éß5xÂöwyÍáx“¥$u.œB h”³ßÁƒ!OLe8}:pS²!Í6KÏð=²ò³ô÷ _ w¿Jt#‚9㬰`Î#£…kv ªœ dòÈn$•3?²³Ê­Y×z“`¿g§)à7yîbwfÐξhÀ{™¡°|â½ôçjŒó é^û^Øê¦·³å°g¢RíóÃcx›t/§ÎÛÙ[^jl±)º¼Y§ö˜¸h} ñ¢q†ç]ˤX9‘V”s-º+ŽþD~el¤i6tºcEZÄÎoãË”lá-ܸf¯þÐXÐÍp#·u¬áÖ&;ý¡a¥Øý¤PÒnKÛÃøí\šÿ†Ì œi>Á¶°FBîõíåöýo?²TQXÁ™’z´±²|Òb GB˳Š}ô âÜÞÑm“¼†TÎ?(îÆµÈ$w„Â`‚+·Ôû·0«Ž•å¶)è5Šî€;ÂoÇ|«\ˆ·3ºã¨¹¿ëµX«Â”ÇõÓíŒîº‡ªMSö›'Ûa0}¯ž2öÿ„]Û’£:Ï}¥î$„˹߻êûÁœl0˜3¸öÓÿ>HFJwz¦æfªÖ@0Æ–¥¥µ6é"\ÃïâuKs|…óäFRL–ïï[´ñãº_ÿÒ¢®xýK‹6øð}‹v’s¸_Yëãwóa<4Üo1¶ ø‹ù0n÷ÛoæÃÓQí3¾1VË)çp¿ýÅ|¸gÀû{gÝïu >1cûL4x±µ‹ 1ót?ûoûŒP‡RXlº}SÁ£’lëÎí™8qï¿)Ëx°W(Âq4wŠÝæpi¾?Xõ—G)e/TGz@Ätd<*ÉJ¯fMÛçýýÑ=Ì6Ù¶§À¯Ÿƒ. x'¡«ŠÆ$«*å¼ç† ÷ÇO ž>]¡ÊÁW<<ýi.dWPÔó\ÕfTmS¡™O=ëu„qÀ?^1úh„^ú>gH®€€ÚEÚ:¯ØH~¾ ë—×}=Éw¨ŒÙêMëÅvà‰ŠHB_(0@[fß²þDñ€ø¿à0tê©“tÿBúïý¥Y+¸uç²[!µ­ÜEž,K&È]JÕÖ»Ò¾˜(phË­Íì'±5ÿq“mÓ¾D8«,ªqÛW^¬%êg>\³éÛ¢v 3àÅø÷ÛÔ‚LÙˤk!ªÎ“s>q†fˆVad®¬Â÷M‚‘µ:íæPi È)>‰C0Tð!»«–IHY–8<Ä!ø?ÔJŽZh]n¹^(ð+U»kìV5ãØ–ûZÆ*œÿ Ò[á¾Ën×SOD±ŸCX«6)d?Ôå@O¦¥“Z”Û‚.£ÏÇ•Ën¥Mvò=ÂjÜp£ö³q_‚Ú’ ã8¢©×“ÚÏ&Ù­8]ÜîŽ ¸½ØÏFÉ‹(jìVÕ{Ënýōɿm¿jì&ö³ILm9¸_Áný8SlùQF.’›Qu‚ÚÏFEA ÖëyÛq$&õ …æ1Ðr]:ió~Îs ¼«nÌfëiVÝ"ù„x†¢Tlm«¦ísa–‚o, ÉÊ-Zì{E/eá&*½¢wqéB¤;Ř˥:d?×ÈÛzÜø|¬‚™¡÷+ä:vºI¯ðÔ ¹¶$ßêN/]µbâƒhŒüfx4F2cSÍÞw øÇûÂ$ÆhÔõçb¾ÃûߊUþV¬bÀߊU ø[±Š+V1àoÅ*C¿« ü­XÅnýK±Ê lÀ+Vµ ù[±J3äÅ*óR¬zÜß«ÌK±êqÿk±ŠÿÎ/Ö^—ò¶S_'!ûÃ…A¤.‘UtÏÅ&[{Tš?QFŒ£`<§I ëadC=ˆFÀÿ€8x˜™Û´Mu½Vi¿%§Ç`pÈé¶¹©ÄZ³ I‡i7 Ï^.Ç!‹m­ù—v¥]‘‘e´tc×å£ùÝo„½yëÚs˾µËA6±ÿ|]•\Y-l~FžW&Ì%}TíѶØð <ŸØ“‰ «IM¦Zæ–?Ñó”×R !W6G3 enÙœ¿d©‡0~ênD‹µZ=Ë (q™9}`Á®ÀË ø“žþÎç·Zw$õïÂN3Ö‘ßêQ*6 ¸÷>ŒÃ°W#^Ù:ŽC•»8¹«°çñ|õªcô4ÌÛѨyÆ.àÇKa*¸¸jYö®XØïéû-PCA¹‹ö|ë;>pÿ95ø•çÔíÛ‚L–Ç“Iº  +W9Ë}Zy0 ‘tEÅ¥–!wGÉÆxÕ‘š (µXÜþ3¦ãÓó;¯:Õr’Òw&l`|ñïÿb¦ ]¼è‚K¥Í` ÌYÈy®wˆR ™öÓï„øK\¯EßúF¢œ!ˆôª±«ÝŠ~°|à?Ÿ/Ä?߉æþÓ(rQ® ™Q£&<ü¸Î³‹ ǹfsýƒhBT¬Z cUÑ-ø;y©ÔäÐØÛZ!ŒAe€GöFζs_ø*û”„$׉þÓÚ½vÖ)Ô{åÉ)Y £è¬;Ú#}€8\§D[*_K½ceü‘½j烎]×kSî€Á“˜G'ßà®v(ÚºÞ±©—˜G¿öPùøßá`åŸ x9µyca3ÔRˆ±Â®¬'?4çÉki]Ü–? &œŸWžõ¥ÀÃëûy}YØH+³^K±4@=_­@JØö°UÞ¢VÖóöâ¹V‚eˆn•Ü$ú?IÂ9J©¨XSñ@=¬S^P YSKH>8 r]¬E_ÔoBa+‘™\$1 Œ¥Ò#&â9|ë7Ý÷{‡ç™pâ!‚=@Ùµî:(ðI€aJ¨•ÖC_( ÌhŽ+¾™©]–¾Xüfˆ13&Ñ)ežº¶h;XR‰13¡Ä瀭ß"¥*c84Ôy=‘z%ñé…¸Õu5L&Ùï>‰OïGaÄ7âÓ˵U£ë©­Jìw¹Zka=ÕZ‰=ãž©Tš}þÞè¹a©4£LPÚ¶¾uªU…*øIš=2Àü»^….eÙY_CÉ0¹¹Ý×Ùç÷DS¨ú+¶….W¼³q¬£b]>J=u»õƒÆòg÷o?]«Ä,,{¡¯!,{Uî˜Eà¿t}ÜÄà€=fö¨Y t™Ã¡µõ†²,$5Ÿo[fÓvLÌ!>/ÀßNUó2ïeê™=Íß4ÍnÈ®Ê4&Ïaò6¾6Uí1óßùEŽÂM¤ð¬Ë&¶EÔ;ÄüÔØŽÂq7^^î{<Qc?8 KŒï‹ÆjKW ·º¨[Mx §Æ~¡%Ö>Uýèþl\¢Æ~ÿÄ,I$ætÆ}cŽŽ=ÌÔq°ÂÌ xÖtB\:¶Œpûwy ìaž NXÌÞ|€3T XN5à ö¤Æ~€l$" S—æ`÷>Ý£=2ÆúÙ5^Ý£bHfµgº*—‡Û·¥dH"îV6ñ£»¹<ö©,g†¼qd¥Z=RÌ òlrJ‡ëòpàÃ#öû™‚ˆÔ wÍ^ ã–ôadÈbÏݾ®ŽÝlö³é²À¦7JmnLªä25:å%ê­» çFI Ë5Îub¾(a~Œ}ß6îû­V†Œ¶3¾Pî³°Q uÕ{»´|»ya±t¨å¹#Öæ^åaÙ]®DÎ&òšæ˜Ý“ïu‰ê®€¼½Šh•E–1_ü˜t™‰ZJG–—OïªÄpF[CD ÛÙíT‘v€¯W§µ ú}¶9ꞯ¤LF¢rÈìÊà xc¹Ð”á,Ê~O[ÅQThJšæù6a*4ûús''1÷²OáêMö_dƒ ÝANm}˜ÍÈî¬x‘ƒ›c8¨ 9vÛÊ®x¥å¹ 94}¿Ì’oè«6{ yˆzr§jÅ®˜Šž\…³¥W)Ÿ”°ü7B1Í]1kc½÷=Üó´ßÏâÅŸXjˆ›„Éå2¯BlìÖϨ ¶cr í¢Ga«ìÎ ¼ÇP´¶ÛƵZ'™—Š øÇ©€å;ßüÌ-UQ.½¬uΟÉû ÂÒ¿»y¾ë²C†<×ÿyÚºÄt‹Ðf.sÔHËÎÄ7E†ü¤‹qéÒFßÇdh‡œ©XÜ‘/˜ãËÎÄ7žÝÁ`j×5…m¿°BÓGûü:¥OìùV(¿â/¬Ð1>ÿ Eùâ÷+Tr³‰wg…N/¬ÐÓ;î…:½°B‰w¬iI^‰¾ÛŠ«95ü¢"íu!cS¬ÒSÃ/_9Iö\­û}µòúIx¥ÀºxàÔuM †²5bÔ_+a»rq¯ˆ¿˜ wtns@#ÍÆwnÏK¼ÞžËØ–=̃pð£õÀ±˜-û©Tî… ÁhØXiµmEÙ™‰ Rß^ÔÌM¡ÍÈüƒÙú¬Ö‹ñK~új²—`(ðõÂ㸭FæKŸ+jøuDýEPv?ÓdJì0b†_ »ÏÀÝ´I]4ߟ\¡3!­>¦bdÈ/Ž ç‡\­65h¥AaŶ”;„`b“ \Át[{Ñ•ºŸýÈ'CÆl»CV‹-þDEÆQòÈùÍÈçú’3ò`¤î[ŠÍyêkä{•)\°²JN bñuúæ·mœg {YöñÉjžãm./¬‚àíÅVûe3ÒÐâ™}Pâ'’š@n¥Ä+^ßS›-^ñújóÔRàå=ýZáÃÜþB¿¶†/o æÔ`ýd}|·¤¶:wfÔú $Lb$tèã¨öq-þìtiÜJ$ôL×_r…xÅÇï¹ÂvbÀ÷¹BL*f§QÕO=rtx(…,vt€—„=ÑàÃd x¶9zî®{Ä-ÙGƸfy*«ySÍ1k\+3b]ôZ (+3‹¾ÓxyfXöIyÚt†ÇëP3^ñómÄ› `À‰ÑÐwΩïmh &•~‘èmßuÛaGpXˈ#‘§{ˆtÌðÀYç˦)ðò]² ªGQ´xåÀ`€f6†o?ÉG¶bìòr\Lf-^óú¸nu–z+¼âuÓÆ3S\ãÛJnUÑ1àiœÝáTÝBSÛµ˜|3€6ão]y¶Çpt3ÞÎÈOÂ<“ÓºÖ[aA†3#®I €ð~`Ú¶£ iqS"5UŽz€Äš}ÞXØ *XT9—º*ż²á9Æ`ˆV#Ò¼Ë ’”†B©ØË6—ye•¡‚•1פH#-A$^ËÒ³°»’!¯?"Gw ½~ˆ¼‘|ÐÃòJ¬RØJó)DÜÁP¢Þ=¶(÷Rnl41‡B‘X\¬æþÅŸýÁz—$pÊˮՅmòIØÃ 6îðD«Ù4‚Š;AÄ’v=ä86Âò¹þñrp§ˆ ó݈ü¡}¡t;‰¥~¹fê_ÇxO¶¨n×ÍË5c…5²5eŒ™†a¢Rbã Îö,Ó/{!½+Á‘_§vTjž„”jÍw"˜Rú¾Â1íbØx^ÒWæž*Ö/n­6ãŽûÄ׫v Äkó\uBmõÌ€–V ßQ¾™mj¥ ä•´p¶Í§jr.æ‚ogù]B#Z9Wƒp‘()ðÔ)cû×HßËU{+ $¡/{yO$éÎo °ôø ‰8 vÚYNe¥{|Ò`:²!k_¢ï«zh(0£¼™ zpëQ9cDùùE2áD2ÌnþŠjó… dÌ<€?£'žùy”Õ±Y±Y†<6A¡&ŒÉÖkaøë¾íí8ƒšÜ…1ÇQH¥ ’ddŠÚ ·WÂGäwÛ‘ ˜UæzHÕmÏyJœ)€Ã,+¾4™Ä³ãÚŠ®Æ~üŒx©ñ¾Œà1߉o„¤_ŘÍÛCôiž~'ä}ãÃL«˜ê¥A~gF¼Ôx?¾ñýø‡”à$“^j/­ó&´Îïé(ðIµ bfÞî{áþΖ OöÒºí8Ýø¬Ç˜³ÿøÞän q>çÈÏ36(!_ØÚJôòø+/Y!öjŽÎ¸a¬´r=‡¤Ìæ{®](ӹ݂‰{&¹Zw–uߎìÖ7¦t«§…ªô5>^Hº›pÝÕ± <õÑ*Y*ìØoŽZŒÊPàã´û–ÐHåûÂGµãJ§áH^‚¹qﵟ¦¹§À,±y«` š×fll#,ð³Ç èfÍ*µÐÕîŽF€|¾Š 1li1}¿Ú…IÕ­Œ½ªõaƱ¦À+Yõë˜&Ýs-÷²ïkK¤¬#»ÒÌj;–­¡ÀTÕ‰®dÐ7_µªÈ·’É«Á5ÍÔCnj¡ö0R*¯e´U¶ù6õbžG <_M­?.nhF¥òi¢ÀìôCKòz½›âÊléLô|ÇŸ°ð‘Cö&5aâééÀÔIWd'ÛâB¯†é¬ÿI¨&SÛe}šŒè¬G§À$Fç¯XÈB6x¥ÀxÅM«m¯çæ2¢³ž€ ”>E½ä2¢³~º¦Åâ‚»µ*dßQà¡oÖßZÔsÀàqö,àB/xœÙ ж|ž{ ƒÇYݪž³Ô~XIp´qA¿‹g«>oÙ€œ+_ ÑîÇN÷Ë'õ8ûÓµµG^^ ¸ÍÓúˆ¼’3L_7è}cQ²ú¼üPþD¶åxD~qdC oHbzˆißøD.øåÓòA—}˜n¥VÎF® ™¿¹?ðDw„¨+ávJ†Ì¸vƒ#_¢l®œqUÒ¶Õ˜7{Ã&û…©fƒë¥nó4XI9 É©OŒÖs4Cž±oŽ×¬Ë¯ycEøX¨s!å‘Ë’}kÒà#PPÊÝŸUðk2q"~éî=ÎF©rÃÄã ߦ”ÆÈbÐÛˆHbLCK¹¸Ÿ‡JóñLí§~O‰ò%…¯ÆÅR°YGŒ)£zvx¢].e[càÈצ.wÙ\WR+½Höm^/Ì;,äiÂ5kwQ6—Àã,¤Kkø:ö|=V;ËÞ&xœAÆ?VeÛÕʵiz09EäCFu$<ܾÁŸ(±˜ÃÎB?J[1Ï ¥“¹”ã;rsI´­hG¾l?OÛ‹4Ds‘«µ_UϾ¸èq†ÈÈ¢ñHå]Ù(E³„ ‹M@ª¾Ï8D~b^0/°cTJa*Q-`ºÈóÐX¥7°?تx»¾ ›„DhDÞ0?—Pjìb’~QÃàÛÖ ¼Ò,"¼™Vî\ÚOø/¤cß‚féÍû\mþ?aײ%«ªl©òÙÜý»ÆØçPEŒóõ„Ј̬uU­94}AX/ss?ºô,ºqû>ñ|b•ÙôMéR»°÷˜ ¯Q_fA¾6ÎÍs…¾ó‘¥|yÍ<Û[ç#Kù´ Tž_ÞÇÊ)zÕqƒ’-rnùî¦5ž‰etâdÇþi½0¥00)3„,e³&‘©±Õ›°œ±Úbà nf6fÈfÚ–)ëð†ÌNr0-a!½Í“Ž/ä³òϺÅm¹Å#J>‡\oβtˆE@r#¡¯U¡;¦Ç•®G9*»h ¼à ‡ôµšTe+¦0ðŠ×EŠh§¶hd?CŽ˜…,7E °½,jÉ`Å¿œ宸…U@* ÀVÄ5½ÀÀÇ/«©5,iÈwèëÚ|ð <ÿ¶[ êËAeø¶3±ËÀëok_¯èo$ÃõU^©Âwm9èl½°7ðx³ W%ÖÚŒ¦˜sMJI"¿‘Þ¶èå‚—Ï®µÑkìZמÌõïJIv5xþîaÑv¶ÎÄÓ²¿ùêaá½Â@œˆæÝÝ–·S?îŸì8Ï)¸éf]0Ë1ƒ\1¾l Qc‡ÛÙ¼ ø¾5\îo]m:"º&¹ªuõB`àíw+³ý}|¼O…ab£Ù‰/$€ÿÍRkèÕ_þî ¢…ñ„tx5d–´T¶ÔÆúy¶¬ÎuR¬Bw÷}ûR­˜ÃîP•«Ðƒ€ÌvD™ãÌm‡Oà&®±eUõ4˾WÙÙü…Uè·~èVf—‰FÅàíûîÃ1Í•Z=2ÐP/n¸ÙáVfuî×õü¬³ß¢Ö«j¹WÄôˆ›ÒNÿæëêúø¨5b‰¯ÈFNIM¹”mÏV ¼b«”D_¡* æ½xûô0GtÑÃÖžë™ìîïÚSäˆGazÏbÃú(d!KSaàö¥ñëh:ÕÌ8ƒ¯ÃH`Û¸ä6ØOcÝOZ ™ ª›5k§ÅDn$h-l ¹û2«UÍÊì)ÃõüÍ¡¬N?Sv‘Myø_§ / M 3ä¥Ý}Ýn&Ô‚ÂÖàýÀøB‘7p f%¸VäÌçnxCÞ" ç¶6mSÛ^Ñ)n‚Úk¹qˆà‰{sMš#ãÜÍ£[gú,¡VyX¢é#«ff<£Ë›Iµ—²û~‘±¾„gâQ–z+¥(ôÐW–a 1j¶¨Êi5´º-²ýH^©¤É6D&F[]ÛVx£s\[ǶŸ}Û¶$G¼Óñ£xÖ–ùvp==õƒxm!ï0÷R…(ÐNøÄÀÜ'ÀY˪'@Tx„hÏrã°á‘þóR‹7$‰/²8L¸åN16h‚<ÆI0©S†°¯alyAÎIIú²)]·„-ÜgÁ @b—”<¿ Žù~1†¼X€$k mÚ²ƒ Û·$È;R&¨ó}/Ø,ÝdóÜ ˜ó ÎÅZÈUûŠÓ+B$"xjÓ8ˆž“Ò#Rl>³q˜çztù] ÙJ¾+U»ö‚<#êz–zÿc5NÞ•¥#/ñùLõrSÙ3,G|Ö#E^>‘eÙêF,Š~çë§y½ýÒ-K ͲŒ¼¸\Zd’çÚ [UùÊ$•ýJl†ºâ²™A»‡)¼€A˜¦jgOï2ƒ àyé5ð‰{‚<Ì Ò÷çÃzžhg,A^’Ô?û×±Q“÷,\¹¢Ë ÛF¥ŠÂ†Åù±fäŠ.g,Ó’­“ØÀ_ÝòBÕ#¶ßÙ2í´ïJrç/I$&Üy±ïͨCÈ#;G¹›AmÊ­f'ú¡s=›mAw°xâ[×~#åŒ+«ä*í€|ü>fD ì]òuÌ:×#£ £ðѵ¿®·_Fá#¿°ÉÉ¿[u/ó–TË…3£/àÔ÷äF‚r½ ß®x†á¸5jØßßçï>5Q¯Äé_ÈÐá+9Ô\^××û dÞXæð}+Ó›Ü~>‡†ÒþœçuÆ@44$rã³êCò |;ì°q!Þð¥å⻬´óÂé#;ÔSÅ:ÕÕK6ÝÌÀ£5)6Õ±pÝm¡Úº(dÊÊ@Ô™‘ÙÏVöQŸÀ6UÈÐ |R`½ç¾&ÀבAÓihC`2Ò™\ D2˜Ù‡o ËíGá!Pà+Õ,u×}ðöƒÙ¿2e í{!Ä +PO‘—£¸˜‡âÓ‰uÖKä!%”J½ÑCÙ{r3O·7d:¦©?y?¢˜*åí /¼’E/€Ý™‘GR#àw©ëY[ò^ìßL}›¶b!'ntC¯ý…›·ihª–F.¬È?ÿL ""EžŽF+ŒñÅ·})Ê¥!Úùh×À§Û´CÍÜØ9CyÁ­Îî§çå8Í A^éhÕFµ}¸ú©êÉ3JÑÁ¶çç(7D1Þ·Ò®}ƒä}Y­`~±¬•QŒ™^QRW]ÓÈjêTñÚHÎJ‚äè ,vX¶³r4…3ëH>£$âhÍî$³ËTšH¸y™ù!ÈD—(¬’÷-yC¶öþ²þIÌÈÔÖâlôƒ“Îr‚<ï‡Z­J±ôJy²Ò\.Hp-[EVÆòe^$]j.×/Èp^_x9R$Š ]Z;YÖ­Ô†¬!—Ã*2sÖBTL ›¤®È3º<~ïó®v;ý½Ï;küKŸ·qø{Ÿwß'£™ï}^ëÏÀÛ/v½³?ŽˆT£ÿ“ûé=2Ú–ª’^àvÞ­÷—KÆ][…#z¼Ðsšë Û¾3] _/š ú#«&g ›90­‰Ëw ‚ûxû4ÜL/å¦JºL-œúþ ¸IFBjø_cà™ oµ6Ìõ¾\[ ¼`’“Ô†5.,…ß4ž“LB!;å¹VˆörP® G,äVÚ‘½ÌAh<õTèv.0ð)¡‰š€¶0ŸÏÀ'NMÉTkÍê%þaà릞Q–¦[ °uoH×&ÒŒNÊ!Pºž OX˜3e»Ê³>¼¸¾¦H$d.ë< æ“6iÍ ò‚ PYÛÚÁúbä1ææ̧Õ¬gm}dó}†<+½°uL|o«€x7ÏU ‚·™!OßñÜX4ãºvxEÖ9L—gÖŒÜîqÑã3Üžã`¤á¥k& ¼ÏÖh<;Gkv׿5Òjo<…oX­vÛòó6ƒ”ÆùVH |aîYú熇'®¨ÎÝ>\©ó(á†å8ä²O§·yï|Ìq›¥ È£‚‚§ôpÂõ8c|%è1/™žNDN_Wr/Ó+™ZŒs±«N„0K‹=Q@jµ€L"–âÁG~{|‹š-Ίßx¯&ðÚdb@%º{}T*³¤Ã7좗û=`ƒÔ‹¨º}Eþ/­8ùëiÅ8 ü›VŒÂÀ¿hÅ@çã°júM+Fcàß´bÈ©ïTki›HõrÓ)òÅÜßÌñx Fb9É·,¼E­Ç@|Õ¹€jǹ\}œœÃÀ fîdÛ͆qhãÜ1S‚7V-x;\$ª›Þ SX³iÞ¿•š?€¨( ¢UÅĸë¢.2¢šd“-Ìld¡¤,& |¥ÚÿŸÜ$ÞW¥z¥›Ê òÓ¬D®¿{îÖð–·~%Ƚ$™Ó½øŽŽ·C¹O ߟæÌûÖ­qp_˜… MäNÇ êt$Ðϲ'H,’žµ°µèÃÃVÞPä Ë©gÞÉÀ\dtänžî²Î––ófx8LýTh„ §_nÂéýL%ÉƬ4 %éIN½šåÈ òu ëÌO·S9Ùnñ ¹"êOŸ‡ Û&ÜÍyuäó9“’dRÒPÉB[’+JÒZÉÍ%†Ù /š=D¿‰á[‹º®W¬½ó:<Ìþü÷Ï(oîh‰æ¡•s8Ž}Úðeä™t} ½[z,¯ïNYMöŠYG»Ÿúöi*³:mÀèq 0ð=ÔçŽ/¦¦ïw:2& é݆³ëlÔðûýmd Lãu¢×Ð㻿ǿ@ëØ€s¿@óŽ}6!!zê²'G¼_h)sW×µ~ßFï4þmœ´Û‡.¹™[Wc ŠEú‰õÚöëRôô²ïw¼0£}ˆ‰¼„iµûý­Ó%S2žz•–îw¼@•&µž‹®[¦¢#?òtú¬ç$d»rŠ<£þU^^ÚÎMrYûi!ÈÃmu¿éáÊͺ8 LƒûýMg›Ûtôu¥»B'ßQø˜íë¨J4.ÃÀû¾Tî®c­Ñ]ç*ð{}ë/:Ð,k]U&Ÿ”HTË*>œ®+˜þãç}–ºi¶þI!,ÂÒ 5àÇÏ;{ JÙÁäúV O~#]ÊÖ_µ«% 9 ¼=wÂ,ð'°nÛ¡eäÔ_|ì§²íCJ¶Ë,=~ˆeo™=ÐC|UqØ›K¸êe@€…X¡§ö åµè^’ÙeMafæċӛ״ÈJ!û7–1¿ ¼¢öy®xÃvHÛûØLÊô]7wÆc U©óþጭqt>¨ÊæßXgù•}ÄÏQ3r1Ï_€áNÖä7¾ˆ Æ–Û„¥@Œzè ü@¢*‡tFÒ`Éôj*a ò5´­#wJ­fª òüÆ/’ñìB/Ëì õ@¢*IL¶Ê…O> ¦Ê®²ôìûä|dë'ßÌq°f­f£à9Þßk[y:c aá\…c Žù²Â‡–áÕ`ÅÀ Ä)“Y¡¡Y›JLP©{ÜßMqs—“—rqWŒ¡Çý˜úguSCS…¯8·”i/ºJ#Ê¢×3t‚±^¦È¥Wmi­¶ã2ú Ÿ‡i8h†öEÏ ÕÎ匤e+2zñnh‡‰±uO6Ȭµ²¥æ„ÕƒRUZù¾˜d]Igª3”ª½tv¶¦ ÈïÎØ1,®5D@TÎpë%%z½Æ€j‚ø›?%A¯Ì|V^ äÏUx»G‘OÕùbšôÛ/Ø¥ ©÷†¨f A_Mx¨În>ŽÉƒ/n Ñ.,”¨‚ À4¤Š©\IJ”xÆÀ*E [×¥[1ðPIØÄt{†~WÝRä°sj·¶ª˜{Å´]Èo¼}ú È(«Ðç‚â$ /WÑXÙ$•vÂoœu´£3øÄ3)uƒ¶…cv' |4®>7FNúVÂdõãE»2½‘¢P²µíHnä‰Ð®2q°³î˜A¢°a#¤-yÁZ ÄÖÇë̓o¯tÔÕÄ<¯×}™~SÆ-vEtWή¢ûAÞ¾!ý†¤O<“\þ»ë8D³ÔB™"$LŒ"ßÚ, éÙŸGÞ»[{¥ÚªªŽ _Ø×/m<­ne?+¡ÈÏ6©„]%Ë:å[ν÷Ðyz eÜ5ei«YäÆé‘¼›gä²[9„D>¬– è#dä嫙ਘPŽ+·’+:(°l7Á +«»ÔäiX&€NmÚ€£/AÞwBJJ²buv6³Õ’W>‘\u%;cH# ç§Eba`FlLne@ÇáùóÆÈ±‹pE¬Ô®q´çûpN•cX«•î(ðBIì©¿!ÚV.ØgÏŸw‹œx1)þ…CM92ÈI©¯ûa®æŸ?Ô/ƒOM¼jã›8"‹œ”†nsíÎ-ËÂÈŸÈíR€§uˆr”5 ¿õü¡›.ÝÇìËZI€yÓMžßuzÙrçò#¸U‰ÂQÅ‘C¦¡0ý<‘Ñú}²>œ:¤Ì=×°Ÿ>Ïß¼Ó} ŽÞ+\Oj_´1RòU›AÍËþþžßØÎ›I˦knÔ°H^`à«þ¦cÒa2Õ®™Š<ð¾{ŠtÈúéÙ`Î]Å0ðò;°·x…°v+(ü?aW–,9ª,·tr<™Ÿoev{ HB @hëÕ?ƒ"r¨¶2«/?(A(bpO!Eîü›sçÅÜê30¦Ð<0T ¼·-YÞPäü‘cf/ò{!M3ô!Dáý¬)'6^ä÷0P`œøébÐC.•GôèëGàì&§Wü^oLòÛþïd%½—÷OÀ! ðÉAÆ@*¯zæ`‡F||Šž­séNò{ùÍÄ&µ ?ݨf]W´à?ƒÇI—P˜‚§/YPШûÀ…s¤Î©b!Õ8v ÏÅÛûK;×É t;S;*o;ÅQÈH†#Yð¸#±E”,˜÷dÀ/ݲ,$ ¼}N°ªH“'àý[ -w˜ -J;{ÒÅfúM´<À,Ú%g^ëÆÍ\ÍhÄ'FW 7ï h@ Éu¶\(ݽ÷lj„<#‘Å’ AtÈÝÍ™tåq“ãIŽžˆIŒ.«:?¿K[1õS—ë¦ ð ›ä ¼–ë·Üþôø}ÑÖ,”SDtŒ:^¶$ ¹9Âa¹ rk–FC (mÉ‘‡¥&t1#¡#ÞßK—Ú0Nh= G£Ò–Ô:¤W–¹Î”uß7~Ø$õªýic뺭!ÆÍË„áL5Ë6·ZðÐÅ–¨ÃïÊØÐ2„<Þ´‹S™…™'Ž–ü„ä¾c4LR‹‘ÏZ"$–ûŽcšÙˆ¾7Yqáñû¢WÜæJñÅz¿iègŽ‘·—r™ðñl­d´¦ z‘°´…¥<ͤ¼mŸ¼[‡Þd*mù“ºíb0®nm³´zÃsdÚê“SWSÚ£wóÄ ö}¿f9Ë”\ú(¢PJB¦Ä“ ‹µ¬sPìñ{”¶Yò0#ÿ'CSmTÚ’dÉ»½Æcb–±¦s3ZÏó'³Bœ¬…^úâ˃^©Âý’(„n]aty<^‚Þ¥HJ¶d¢Ë²åŸ/æ R-­XoVº¥°‚^w¼8WÏ÷J·ÄbÉÎÉ”+ Ï©Ýü½ôúf2'Ðã ÌÁÿ¥GGùòy®ë­n6¼CUò˜_¨ÞÄÔ*üý t›X65 ùþ- µD(Ÿ€À'&1ß³YŠvþZ` ²éøñ° Ò±Éß¿Bž^jâö*^V‘qxÉ9Hÿ¬ãâÿf EÈ•nn[$3Îj<&®tëâé½âèˆÇ¼Ð<ñ×·“%L¸!ï‡ä"Ï XÍÖ8·¶ ­{2¨*ׯÏè€|Å;*ݬ?¯ìB_òy´Ôf—hYš¾ò§U‹væùçRkü[‘§ŒlJ TÇ _ûjkÑz"’u‰äLþÚ6÷|éV„„"’ɸËÁ[˜oYšo÷ÆþŽ:]S=“G‰¥6Ý&ëæÍ‹Œð–à1ï‡ÙÚ:vš`¥D?Î þ»Ä¼?¥ÿ¡¥aHS­Ö¯J#äãK]Hf"òùówš¯ÂÏ#:ô‘?ÅeŽÏçéE`>wsÞZ*&•—ÊéÚ–Ú=ÊGV«Üî9÷J»|g2Y–²œ}^^.®{º#¸·ÖŸ“›Îª˜O Ü™ÍË£%«gE!ðP¡i²qDT’䨸ÜYæJ{DЦÚÜ+û¼!"*RúÌm”Τg@â3ðKÕ…_*1V Ù˃Ÿï@M,‚ÔV{[æ‰évÍ‚ÌO¨Ü™‰õÐ1ÑJo7 ðŒ™ÔyR‰¥ã@2ÇËóŽÊGª:—%ûGÏZ÷”®xÀÜ 9OzÆ6§ŸPÒàè¸Û ðN=šø”jØ´ÎÕ¿(e´G¹Ý«ÉO:W…»¸ìÕ°ºäX±ôö4Y¬6ñ@ˆ9^@_QKpkª&©]>ŸÐËÒDQî¨nÛ\D,£¤Bâ~“?¾kG;W£ßx/^[!)ð›’ν±xÖÑÛg]Ó<ëa#F/¹CˆXf`žõ°YÚI(byDºx‰t©˜Øºýüü¼&z1p‘ˆÄRRÑWÅÜ4q¼|ªì!ðŠZN÷c)‡É¥(RÞ>çɵX"]G|f¨ºYUdqøû ¸F šÌã¸n$íÝè>$Íð î%Ñeð@ï ¼O%mBC5KÿìñåÕœ>"ï4fDÈó¥_ï/ø4*4ñšÀ9Î|Œµ{¹[–vƇì/¤ÐB´øé·ÏH£«WdxA6к讉Y¨YõÆ¿ó÷ rñH„ä )ç®f?ýù©féÇÜÐ^ÿ:±…N{Ó<œÈ6î‘§¿61ëü2Ϩ"¶ýË­7û÷:Cà«aãhÉ2Å„Zbæ8õ¨4ÜÊ{…cRb'JR¼}µ€#G“y5lá  [â!ÉÀßW{µWu»R¾Ü30lÿf  ›i¶iœ6|~Wit7xù{KW€×OTè1úK´4¶çx~m‘ß{7ô&ו!àåkML‰2ðú­&f[ðo¼}­‰qxÄû;¼ž €÷Àâï÷ÐÐqyt½ÔóÔ¦y¼`¼†ÆãÊsÂÙÚ@à9‹@ÕE©ŠcÓÈiž^`¾®òÁïHÃkш»ú÷ÏÎöVFä FL+Þ@9{rÁ4ofÝ÷›É#þâÕ:-£÷Q×ÉO(ñ‹f æÅLáÛ›¥ŸíX,És3AkF°EžÇÉ(Ý[íïê‘Ú/o0š2—­#Ý<)‡}G÷nÊ—þBÝn-šõ/¨QMÁdÿè™Éel8>Þn•î=úyø¼4É ðšøÃaæ±W±,øOé Øµ5vg?ä-ô²6ùG¾6bä~šPHÚvm²•z¾j &±¨½°j§Ïï@J6Ù’ZSù,†å;ÖûK¼èsåTR°¡êˆîA ñy¬âd–U¨u\yYñq/¤Ý;¨¨®:»MÅî'ÖIÿÙ4"ÈÍ冎ÚH?/Ò@ ¨YÌ…§kEïtŠØp_Óìé¾%Púõ-‹1«‚5‹<‘¦-ÞÖÏm/×!ÏÇMŒ¦›Ø¢éÆôºZ‹—Læº6"YӪɪ@È+¢ÿÛÅÖ’•öVÄHTAÞ#gŠVþDDG5Þl÷’*ÄvM¥9±ÛjѺ'–O;Scoõ²>8Ëþœˆ©‹Ðf¶¦öÌ‚,dy¤aé:?õ¬"«ì´J1|#a…ªd%X?õnEÈÓQRZÇz&*¹Ø—1Ï€¶§‹©²‰ [Kð'«¹lNÆìž•ÿD¶MR© B^4M}å‚tS%¹4øéû;²Ä¥a4d0~‹ ?ý~ôÚf?™3²ˆ*\Ëò·Äë6) XJ¤ÞÅA;9Äë@2ªp™VÔdØj´“ÏÏH”‡¥FÜå#ÃÓשe†ÕE¿ór¤Xb›ñ^ÁíÏ3"ÍŠvÝå é½7Òzc’ò‚’1ûeOƸ ´?Ê¢Èþ´îܶÎ=™F2"ä-Ç?›]^*LÞ,uP§IbÂyÿ\îMÚfÌ{éôóÁ¼—rï*—{gàùÍ;‘/ÈjGá¢`µç©XíÓÏ‹ðcΉXZ7m\(<ªãvFˆXÄ­©ðŽe>÷Ï@Ú®÷§š…À_|ì5C¦]Ã9°MÍ{ê@§ÞÈɦïk4™Wó΋yW«@  AƒqÉ·aôY=Í|CÈÓ{ølÑ“7ÚM1Ú'ÀH‡ùUƒ)n{;eS|Œt@>dÕlE¸]Ô˘W>‹½ÃèàÉñºÁþ½hÞÍfÛOí òv¢5 ³f¼CÈ_h´ã2jT íÓÎΙéÀæ^Q5L!ŸïF[t•ò‡ ^Ð*%óþÏŸ˜6ŠöÀß] %sƒ~g4ïÑhïÕ{g°òF»²øC‹æ=í0õ .^û•÷ëÄ„¼¦˜Ç^ZoŠã]bŠO? SLñnävS¬u6ŧŽ üª™d4ŠŽvD;þ0艹%0<)b˜Y–qDÈ_h`SÓ|G˜ñÎм§cÈ›bnøaŠO?À¼Û@޶1dVćV>šw`´ÃF›Î+B‚ zaŒåõJx5i<æ SÁZ7–Lþ¦öÒaÞ›’‚ä¡õ‘~E{)™÷?Ù2ìõ!+ÎØ’½üÓÏ«yç], ðwULgz„¼¿w·%áQƒZ§—ÚQYñ×Z€g¬³Ò´I»eê[bñAd»pù\½»),·xþ"ŽÊ˜Ð„ž² …~´ÖN<©'Üü—èãv`3*êm€@@šÇ’JjAÍ$ ^Ž&‡|ãõÀfìàz<0êÒà]·ÉþÞ — ’âòx tí4›cè  §3c®¼=`•F“–0]P›j¬˜ZZ…&ü\ž*¹U àØÜ£ŸEé•îJ"±ª×Îm½•³ê†ûÕŠJO®þ~<Ïx×ÎTóhe¨ÕK¬&ãˆØtØ ¯P̓%,·šº^óµèÈ'Õª.Ö7àXó¹G¾¿ ‰ˆ¤’£h@Ð ‰ˆ¤8R[ü($"vz+!ð’/úI\"&ÌÜ(¥-ŸÂï_dhˆåIx,¿åe7™¤Ì<ðñòÍ„=¶{ÒÈy2ã¸@à×¼l›(g2ðk^–‡€_ó²Zp ©ƒû@ÞÊféÆsÐè-ÿAjtظÎvK÷o]g™0-fZ™74bê~û~c2>8÷õ2r¼âM£‘aS ¶ìžç_X3Uïx¾qÿ£òÀåõùLfoŽN¹Qÿhɘkú@<‡ ”˜ô“JË|QUNUxy( ð ”­ö[Y¨nuDû¹4âí8d ñ~(æe§’¯Üh¿s ðüBÔÆ›k¢4’U©Ê<Ï+‰¦No»U©{ ÐZŸF @Ú˜!'XÎç·”ZtÐÉDßSÂCà kBÆïZV“Q6xG„ûçV»Ú¯èÑ¿ %<Bùì½noôÀÇK Gy‰aPl®;ôŸGu„ºŽ¹elZ–Þ`²Ÿ»v´=Bž | {KY™Ám]v^tOQËÅìlk ÷fðØr1´ÌnLΔrÎÑå*×A¶xýÆß&6¼~çç;É€Àóפ Ñù7Þ^E°’”÷Ìœ?:—g}ÿØÊõœ iõ÷¶Pñú ´µv1ø*Þb}£h°!7ÕF é墯œ   ±{»”'hÇk·ñA@`´>;ý-õÿιW§!ð‚Fìòz×þ²\F|âG71æ°K(¥·&Gkhæ¿{æ"³kø oE›¤ó[C¦GÕ’,rKúj Äe¦d¬zSµæÉ\0£Æh”p’P-H^ÇË qc)F‘R/r¤2ïžË q#ÍÔáÞ;sÒ,&¿k(q™z3/ŒêåV‘œ~¿à„~èż!•ÖJÃAÀß$=Wþ4\„|`â™ð@"õ@²q—ÿþù Yn"í8ôõ†üçȹµ)$Ü@Ç¡-äQÎZ—bÅ 5ËÆV……"R¸î+4ÁØ8Ñ !/™z?=Òv|ÛF¼1®¹P“fBÜn™Öaé+oàòv„IóïôHBVåß'BÞ¿ vô9è d3K³fTõbdõWs‘sˇl¦ÇÁkˆ¿ê’ ˆ¡ðr0Ne.áÇ ôÔs~åç—úÇ&åfáÂenrÏ+…ÐòZ! è·eiDÙ}¥TœÎÀ+JŽ L:0Ñl exCtש3m¨XH.[¼¿7;ÐŒÍ6¬þ‚`&KjgfzÙv ¼³FªÓþUú'xÓ.NGjS~[àYÇ/⋃˜¿ˆË9ˆÿæ ü›ƒˆý7xûäÚÿÃÀ{T W ¬ÇËeMˆZ“íä§Š–¼4Ò­ª²x>*7ŽªØ‘Œ,G@àåÛQTŽUnׯ€Û1‘(Ôýl;3ªzÀΈZ*ÖOU<]®BÜû¬G’þs¾}]®/:…YHÚ‡þ øÜ6o’µ¤Ê%i—ë Ëö´Æ;’ͺ¢ÿɴއ¤F5‘u\üýT!ä !÷!w$ŸæœÏOH@Ôž ÚN;×NËD+„¬+-OU{| ëkNòz:™GŸÏ¤ZýlBÈÛ‹ôG¨ßЭ¹[ô~Rˆ;öù5YL7¢!U#ò÷½¡K5¾µíËC§0Ñy†ÈNMÔ`çT{^ÏHæ‘ÝZ¼×JC}“½ÿ;Wa›CÜ Ñ ßg+¢(šÑ¹t…ì5¯±ŠÌ±ÅRÑNè::bjcOC´D¹ŠlZOâ¦Åy™ŒëÍÖÔ轟o°®`/bóOOšBLè‘·7Ù«C{ÊpŠ<Ã*€èM¯õJë­á“€À ¦Þ×-$ôIA  Nƒç2 çò ·¯ç²ÖèÑE«¾ª³œ'ëfjçb/ï/W;c›ÿ.´ÒÝ6nm—#,3.¼±j»–®²ÊBà9_ ö ÔþÝJ]/Z™½i á4î¶®éÈì Gb‰ÏÀ3¢§Ù—Çû©J¹TkQq`–ÖÝÖ·åq¨Þã6Ô»ÞÕ›PM½]Ç‚ïËSÇ0¢_žÁl3U‹†À(âý'^¥Tʰ…¢à! r RÙ,d3hž³µ@¹øèÆKa„EÓa ¸Xî&=8¿”OvIq7/_Uª]®§ÊÅŸ®DçSâú÷ö—,ã0õö7&/8’öÀ"Ø>ôJ­ÖM¹Š Hª­xR¤ÐÈjÎî Tý¸µuÜIUÌc%˜gr0Hª~ŠðV•E#Þ¾“yàõ?È<²Ãt½¾“yìÛÌCZ™ÏÐëõ?È<zô_ÈÞËxvú]Ñ™Î/äg"˜-„‘¨MXááÊfyC4u,ü”žÅF‘¿©uu ïïSQî µšùzd&yXe¦0H÷F”±IÔa 2Í÷qç{š½Yeß; ¼ž¤…ùnÔ´ó:èAb•@––”éì´1¨úuÅÀ{î†Í¡Ö„6ÁRÓø8¢1 àí“Úwã¨0ðynéz˦¹“¶o1ð…©’F1ÓYɎýÆIvumÈ£¿QÅZ•¨?ú¶pºœ¤¢HT±iæpËŠÕsÎÈL~_®ˆ}âÒT«ZxjvÊÈ£¤a§oÝÎ5Û +‡d8«Œ¦dÔ¦7n0–¹CÛ,f¥Ò¾†ÏsùÏħ÷êErtD®Ä0¢È#^ÿcDáŽùýŠ"áŸH:áð½ßNŒý1Aº'3¸ö¬aÎïç€ÃΡ²³•liJˆeÞï§dF¬*ˆì¤ÁNS–ŒˆeuÛ˜õpÂu½NPš¿Óšºœí @6Øe†²÷û™)˜§â]!Ó‹©u„â †1Ãaá«I¯ y™'Ñ"!sÍ&Þ†‡÷øÂì­ÐeÖ÷x,÷ûš×tFK¸úò»ÿ¨©k“alElòzîòûäòÇC­ë…­WE¤}8ù6Æ“vXÈÏL5u“ÂŒ-›†.\=‚ oÈån:Vù68ŠkM©¦îB 6¹°Ì[EçƒÐ0Æ´5ªÂO™K¦‰ËßôÓ4yK/äò¡ iÍ*ýoìòG¯2¸üë¬T ±i­¡†Xi(²ïJ5¯d>Šƒ:Óoš™…¼œ¶¢8¨ N퇩Upû¤ÐjqÈ:~VŒ¼ÃÀשù054ʰ/'ŽïÏÀÉ'à¾y¡O¢FÁOž»6w)"YÇOȹÍ]ŠHÖñ@¢.Å¡4%A^?#gÆlrû<ºXC´Õ­ N5äïGï÷Od¿#éïÜ;4>Öøt­l_ž|ÉØ¡ùÙÙ©ïýJ{‡&îc '»m½™·|,A¾dâ ÈÚ›ñŒLš'–ÐdYúî;¨-C’–7@Lp#—K¤åQYïç…ñ±«f…H–èp…ÝßÛæ…t´|ýû'¶SÞkŒrsè!i‰¨ØöíÃŒ1‚O~ãÑ“F#Kh)k[[9Ö˜L£(W +Çv-ú _Çq)ê¤ûæÃ×ó ÙŸCÒ2µ¢ì$Z{ˆbÖÁ ·’<:²}mU£;µoܪ3J/Åê ò;oò,y¬}QÔNNkI¼yy"6ªtÐ AÆ»oW„äe°ÔÍvhJøŒÈÇõe¹x“q¹®“‡Ïø&À,Ü+€µå0ȼ%Þ¤ž'*„ìiÓº`¹<þ~j8Ë¢CÁ5 ×YW¨‘] ”ö£š„[+G ¼#QàäRÓ°­_¨(Æ.êŠÅ“ D´8ÉJ7±I |en­:&,Û¶(¤¯W_Á½D>éel¬Þ.ã Ò±vgLñ5;)@&µ<ú䈂Ÿ<5Ü ë·¢k/$^4‡Eñú.ð÷Gç€óãuÊ”@!ÈVÀ0—Õ4#"-Ëþv#2£T@wx⨈—1¯ÂæÖPRüüúQƒ’]–7ן?ÿìéÜH­(YÅÌâ<&µGœS­çªf§)µi—Y­`jÌj$„qa¿Ø¥ÝDùUÑVœ×]5ÈóÂ~˜Qb/ eC†€8Âó‹Š¥ÆTé.C:páÊŽ”ç÷™4š°Bti› ^ˆôBU&ÞHëZ…y™±,¹&\4%U”%|ëNOmø²*1ðN*®ÓêñeÏ‚È0ðè‰AÿËj=Ø¡¡/óÄ¢³±ÔiDYB8Ëðm…I%DÛky/d+Ñ^à[c¸Kðë8ñ¨æƒšç°Â‡Ñ±Öê´¯‘ÌÜŸ?Çò‚}õìåÝTC‘–™ËjM¬0RJÜHÂ-CËÂñXKW\ÛÞzkRÚM´bi{QWŠô°àZäGL­ª›Úmµ¶¢ÒxÅdÝÑ‹ c‰U‰ª/àÚÞR7ãÌ×;)>$¸ ‰`ÎU¡‡ecHOÀÇ™ %fb¶m9ÏÌ…çãNù‡YT]ðæÜ<`à•„z·LÛ,Ââm€IÅðdîý´š­lb«ÃÀ;&€IM Z°……Ë0ð˜‹±ËØ„…£Å˜ßú¸>àÑɃ¶ZÁ 3ü™¯H{“ ÃÍŧ±¬¬‘dÄÈf³ væØ`pMM/KHgTÿ¦L+Yxدû`t©æ¬ Äyþt‹¸%¸Ikðx5éîX¬µ÷*1ÁVÍ  ùu?ŠÔ²‚Úåj• ñN=ªhþ86…3r=¯s±ßV ýŸ¾›Ûÿƒ56bÐ´ÉÆ ûEvHº´S†`ë,šµŽ”e°Ýç1V&5ŸÏ—xGg+pÚ¹ÅZ5jàD;46"yZ/Vµ†¨2m™kÏÆFdæ†z'Oƒ$ÒØÈäi1»6-‹Öz‘¾‰©Ó…c¬,(Åÿì¶.p£¸.EÙO5ARŸÝâÜyxãûäI"åŒ!Ò=M=^~Ñ…“ËùzýaÑùÃ>„¾Xá«r”à‘#:ÿ=ò´UMÅðBÉÆYHÅ ˆh{³”¶r}‘zØÚJÛÂÑ‹ˆ¶wä‘1vKZ5¹¢S.yý°æâo\Ç¥ÕË0Òo?›|·³b‘#÷ä7æÂ·´tcüEÙ~œáfÂß $+ˆ¹?*ˆßß'›!’~Äz_áz 'äûû°>Õû ¼}±Ð{å…·5gÅûÔev¶ ±l†’Š÷å$ÝP's¥Ã+•JCWõû܇ƒ’@vª·f2 ¼aEì7]xtYëk&Fä{ÐS°ëñ¨`Y DO ¹€CQ½&Fºw±Œeªp:ûuÀÀTÙ5Ð`bÙi ~#‚èøRÞ{æ3åÓc'ró ÞsµÕ€5)–„ Ý÷"„~V¬E1”§Á„îg . « xñ}ûá@ÇcÜÍa«®U¦õA<íY6b¤ë`jÛµâÙG<íÅ^¡ äé•*Wn»qGdéL´¹èzÞ@1"K·\ŒXD" 7Y[U¹&ñME·mXGžkÅ˵ìCF¼¡˜\Íhe- V!déý_"`HQ>)Š|ƒü KzT“ƒ#±çdéЀ½e€æI #¾00–² zUSà­\h Pþnà 0®3·¿M•[ ȬRämâU“ÂÄ)Kµôã yÉ7CyèΫ²*ÔO´'©Æ.*hî±z ËMÛ¼·Ÿ\‘X©ì©®a¬ÇÀ®H°Ðºày ŽÕÆ~(ËWìûI ˜s“”™™il›Íü7•sÂV~ÐqÞ |"­- jLp—ÖNwø¢šå»4ɺ–á/'ÞObY°N]iÂñÈf7d¿NÈ]9ÌorAcA‘ß¿Å`\ŽÁ‚ø”ÝÙ_Ü.åèÑ@õ4&ˆÿ{×L¬cèyàv°Þ8 `‚x°,"[ïì[ß•žuxE%Ì©ŠÎû©˜´SGGñûB‹ä3ûi:C¥é‡ïXGƒaQMÌäÑ–ÑVÙ«Ä&]‰©› ð™ÙUê-fº»+~ë¡ uÄG¿œ§z;щM¬§–äeÞD„6–‚Ùzl}M&ü r!Eôü¢* Úq¤óƒÉxZj¦1¦[ëLkõÆZÎbF-Ö„H¿„U {cöOã°¥×Ú¦¬è7"²ÿØûSz~ÿwïO—ó¼ü“€ÞQ­,µi&àï½?U2çð†Ù™#‡©ƒ»]mÜâxÿµI¨O ˆzšÔ'¾E8Ÿ+KF|þÊ+c¼õ多½?rk¹¯dka¯?"ûah ð‚ƒî±8l º·ËªZ‰×œŒ\Ó{ªÜnêÆMxCòŠ)Õ9ÛÞÎÆ N}œ»dOÃVuÙàã7¶1¦>ccN`¾f‹ª\[Í^ëÔz˜€oè—+3ÏÑÎJä3?Lø×¯H¯è§ù¦#–™Žvî$kµ§È˧r™”¡ƒsû‘úo’ ³¦T«!ï?Žrž¾¢‘ÆIÀ˜YJNbüÜ£òÓ¢›©¶x:&–›‘÷v™v½ÄÀHðôo®cHÀ>'òèHð]ºô·G×áÑË„ìÈæ»à%†=fóaAÎ2ÿÆðm¼™xa& ¼àÔrÑØ’ÍË¢:2⦇¾L×*Ïæ·¦óØiéf‹wð0è<ò0"}ôãwg;/Ÿç;Û&OÏë8Ûùˆ|ýâl«$r¶ð?œm:â8Ûô7Þ?%«eØ «’0§C «Ç{Ù•mÓ¤ÂáoÌeûOr ö0ü¾qMå2ßß_gjÂôÒjÓ¯{Ø3ˆËvî½Dµº•M"—ûF\¶ÂöÒ1™¿ô‹êûµÒô BÆìMÆÀ°¦¶,RÃ{^0¯]´“¶>ÊB…=3bàa>×P9¦å0.,8"0=”˜#s5ãÀ<Ûªï1©ZÕI»ÔßUs8M ^iâ~Œ×+'yCG¼‘´íîÆÎ½âýÄ+M€w¬åÈ“ÃËõ"˜J¹D¨²Xêb©W¥C>óâÐrÔ k‹~u•ÇÀ£-!6ëí2ޝj•#™Ç÷ÑleKMÇ«j¨ òUMòÊ#=kg˜®‹Õ4 A~c $¾æ¼fmU¬ô#^O´É4ÛHA|ÕX‚¼¢êÕÄn ‡U 5ÔŒ|ÆïNX¥n¸Q8oË1ŠÕf䫲§ðŠæc=ߤ&Èlj26˜Èªïy¯\¦òx!‡0v]φ>=WÏîµÅ{‡Ý2Ã~ ˜ ù>|S¸¨+üºÒõt­c!VpSƒ]ÞºÊ-ä> ±c¿SÕ :æ(_«dʶm­-k;îF2ó±-á¯= ý«`Tv#S›@3|÷+íNýk8˜Yô¦Ò/“a»¹½‹ÀŽŒãFæ„×OÀC É›D¢ÙPU…Çx°ªÉˆw¸#Ì–I­l-[:bä>—2öÒ0 ŒÕ¾3äežÑ‚?hQDðàDpæ5¾"ðOîÓ³ÑñnDSdÄ7ñ ¢Ódµ«Xµ'þõkC%n|ßNX• Ô­ª×I¬؉ß'S­®©˜•µ]yáØ„Ù™Þ}¦˜‰ßI³D¹ ¼b`<ÜªŽµ.¸ñªÇÀ47udÃß®½b‡wÚa¼§ƒ¤6~g1ð|ädY9øp(4ŒŸˆÈ‘×191rÖ‚Íä­_ˆv1Êø´+œ6“‹:µ|Sm—½NÁ2ïõCC&ü Ó7Å ¦Ñ¦+EUU#AŠ˜±hgsrü ¸jYíò‚h×Ò…¢”7‚1QÒÏ}Å‘ž{fæ²;ÍWôì‰Ïû¯Ô`ØÏ>¸ z§ŠÌ¿Ì[ «D‰0¹²W¥–Éç›l˜?€qT({V m0$ŽƒÏGµ•Éj/C’Þ0ºRàfe1bàãànýÈ,•ŽÛƒ ©|E ¾°zÍ ìk»l xûó×åYXÇ0ðö}yÞ¿,Oë—§ÁÀÇ÷åI#è ø<ÄÿÉòì£0ðõEñi¶KâŠd·ìKש ]§ìv£À2 …øck¹l§­5x£ÃGh¸›˜Æ±ÂÀ;îcEr× ì`·iY ||èc…^7ŒM‡OÚÇ +îܬæÚV|ÄÀ×—†WmUG€ù׆W© ’ôþÝðªÏ†W†$½?õ±zèce·ßÔý-÷1­ßT 2ûÐòb¤åÈ# c I–S#–©Ð%ù™Ùý['«ƒN ‰gTrxªÛ:ø¡Â·ö†çž€:‘&€¤ñ—# =;R¸¨’²àÜ,fÔy¤2ìH4w]/;×Àµß/šô{â±/ü°4Uß63"î€Y!Û t“Æg³mÖ$Ǫ¨ˆÓ.ƒ)¹ÂÀÇé¤.Ó”‹ ëß:rÄç ÿ•Žñu“ÓÝ(~å‰@úEI…ù„ÇÁ× ¤>"ôÛnÏ¿ñè0ÜÎŒùÓòYLFJêuìܱàùß(«ú ¬f·÷U‰,tÜý½ñ‘¹+; ~¿R)ÿTð>F¥³ßšâEê2N­î2RyN•™Ô„m‹ž·Û ºŠÙõVw öyß1)¶…ïçCèÈX›t£ð-ã``êFŒôˆO.‰½1×þÎÔÆ*rD¬«˜ŠÄ“že¹réÿ=Có¡ÿì £8(]¡ äH‰zï÷v!{ÂhÚ⸘ÛoªJÊÚ´b¶ë!ܾ(QŸC€¸Ôø¸$c"$cJ±mª’äzvQ¢ÆYÛ,Š__ Þ’]”¨ùá| ÙÄD³2ˆæ5L4‚ì¤^•Õ³0ðç‘:4‡¦›¾‚™ê )Q£2vÜÎg½5ÙoB®&µnb›W‚< Þ¸wévbjä0n Hš0ÆD¬òÉP¿Íýâ·ÕÔ¨mÞYõ3Š&H¨õÛå˜$aŒ¬,Ú}ã°ödÝI˜=!aÙ¸.œ ßqjJûßýþ¿œšð/NMPß»ßÿ—S~pjRÔ©);•½/NMŠ:5eHÙûh+%y<#*Ó.%¼<¿XÉáS.JL¦³­ì~ÓÑ·£™ª©Ýê Í‰”½OuöH‡_D3¬ºø8mreÒ3’ ÷aHÞ>•A÷r!F`áf¿(°ª+¸…>¿i¶­°xÞƒػ°¢XFŸƒµxGRFǹá:¨1`à)S¾Çt{¬°‹`œC-÷þ"2 ¼Œy¡m•0•´x´çö‰ÅȤ޴æ¥)t9*¤Î \üÁ}&ßk DÊ)B&û.'ìÖõÝJ€¸:¼k» çN³ÂÂC‘_g$@ÙÑù˜J:ÙOxûêbS©‰L[ŒÑü[¸Î“™ÇÀÇg\l>/À½²¥—a5‘2]ÓÔqÇŽ;k/gÇÖשj_Ìæës ™cûç(ß\úïñ裑ž"ß_ä ÔÄŽ›þsqÞ¼„³HÔ›Ž¾†º'%ðç3¤Õ}ŽŒÍë¹â#Cã@6R™`dÓmÝÚBÄòȈî0KéƒlÆÑú]CŽø@¼¬8#²·x[¶>1°NÝgn‹¢áôbP€,¢BÚ>±Y´Bi†ùeP5ìB“m”DzÄÀ7‘ÙO=ø÷q›8ŸÈoüÁÂ1ìåÆ ÂlsEüÏsCYµ+SRö\dF£óDv÷™¢ì+²äá1 ä[…)ÀòhH² ºäþî„•œýÔqÔ§î7L5'i@>¡%È’8I8f%V馑,RjHîI¨H,InF6û  ê„ 9;ìmÓÈÍÕzAo<| ïa¤¶óÙ2½—gC#'5µÊŽ#yÖÿ|èmo…èɃtËÈ@ïqöV.²"g¿"³˜æË<´Õ‚eà2¥êš­Ð‹ wóö@ñô¾‹Ý¤§eƒ_U‚|‚2Þé ç‘lkYWwùÂE¢p„m«*êÁ9ìdþÍNÕ_ oµSõ;ˆÂÀ¿Ø©.xÿ]pVÔb {`¿#l“¼çY&Á—Œ¨ò‡J˜ht:è¢ÊQÀ©ŸTÆawö w<èf˜²TšQIaïˉИÛT9Ø*Çg'‘qÂÀ¶p¶´ˆ®-âM\—¡]W- óx’ }w?Nƒ7Eá£tºÇ“Ê8D^Ox,a]ï“-r1¨1—æþšðî0¶v¾A]7 ÇgóAÙˆ?Ô)&ê ׋V$Ë3Xð?ȪJãÄ>†ðqĹkÓ'`N„åÙIƒ,ŽÌ?:™ù¿béM³Œ¨¬OâD-ToB YLj²âYv±õ‰©)ÆylzÏçŽL¼£­ƒÆèÙï'²NHÐnbÝ`M@@Îfh7zö'QíŽ"lU™LµùÂ,‚øTj6Úy,çiþ«aâ3 >|CEWé4ÿÚ7À]Ò½1¶,ç:ù]òç$ÒîAS(:/µn›·äÚ“7s÷{ä/­nƒ%}+2TÕ”QpKU~Óu=­yƒ,j7ZÙ÷~Þp%´m'Nw ÜÂoÜü‹BÏZI5 ™<4ÿ…°¢s[·CÓu‚ #ˆcVÇÁYé¿)Sÿy„8‡oCÊ5‹ŠYÎÊ.y—òƒ„?{gÄ´Ò{t{;³½Vb\ Wš Š ùCª*û›Ù®ó,fg ¹GwT,©“ñYÛ0[ÖÝ6‘§îž!d*mô Öu,“# os⦯Y¡3ÓMî~’SÉ«áb+”j…î ò‘‘ŽÉÇmÔ%ë$=ûó0˜2N3vËh±,äí¸¿°B*¨H[§¦u…röójþ-CMJë·D*xöØ?A È”&àn±ô¤[£ÌdÁ —^Ðô»æ†g0ðyQ ÑrR~[Ѓï] ¸µO{ºŽuæ(J?½s¬ÑäÔoR÷Ž=51Ͳ.*àG ·Œ˜ï‰* ¢,R)ÃM¿aàíÐ×Ýõöxñ;1ÓêDÈ-ã£X{<¾4¤ÞKTû‚Oa@ÓÙê¸Ìÿü÷ÿÅjEx&£pœ›fxÅieT“ëˆU¦f¼ÁÀf×É)rZœ°h·Oda]=nµ˜L@>ó_â71Ñó§ý¶¾þ» ä^ôÅàó±Ò‘#¾À-Æ©d’¢sLY ¼TÒëÄ÷ Ì8-0ð Ä™n¹saô {µéù¾Œœ¦À$®ãº,›ÀÀ²ƒœ_–ÕVÿï¿ñˆ©ÑêØÕª3ø8jë¤t¤ƒ²Ã¤xE~ã• JºÙnËÀ üäËéU0ðSK@ÜKÚç>á°3—Ö‘«~ÿÅy®ú ÿ‰JÜéãÇCkL<¤ÄæH‹cŽtŸ8eÔ¯2¤Äý89°‘Ì÷gEXÈ©_ÙÕö¨­õ±?Ø H“z´Ý+á wÕìsê|e3¬IýÁ³ÞMP @Âᕆ«S¡já~ð¬×ɳÞàO5‚uK¥í ˜H>QO+9ƒ1ŽŸ$#æ\±2Sˆ$5]„‡yülïÜ,c ¾q R½p1&O‰t/c‚>¿z(I˜L@꿟<”¤ƒ­ùõü蓸î™ãμ¾”ntªñ@éæõúZºÑ±tÓbào{‰6Ò ŸüÎÞ™W~Q£® ð\ìì¿Äj1ûHƒJ³0kÓ.ˆ›s)žªå¶U•«ŽwæÚRÁÐë¥Y”H¢;þWÒyÜ/FÛ&Œƒ¬ ÿ,×Ò€…ÿf |P`ؤêŠ/Ât”‡_ï‹þiâ€Vûðõ¾Ú)ãRñFÝ`þ诺 @C~ãûpŽÂÃÆÍ°aয8“’3è¥¿ÞØÀ<ê7‚ÝÛ¨3Û@~d†|í϶»DTm€SøBn|ÿšB&m±™ª®3ô˜xN2²Î›R©ÒïKKî÷9'É@ ¹)é¸%@¢âum)•ÒÐVøÀµP~½md·ï‰q0!(Þ*¶d~"*$ŸÆŠ1zÌ÷d›t•~>š:å3ÁªGXPGlÕä£ÿ"` qßëçXSàk¿¹`ëü.`í¿PøAÀ:„#ëÌOzæñ†«~P¦1CÚ/úÞ{\ÓÄÞœ¬œJ`~ç>X¾í§VÓVÈ~cþç×vù^RÛy,kÐÉò?WV‘4ñµñ׬,9"h•»òW8uÙ¶£„í*ÿsåÔѿήʿ¸%³äªsü†Ãˆ/e·²‚\õûØÍãÅ«­Ôh¹IO øƒÝæàˆ>éÝ žÜ¾aÁÿdbê°¹3µ1%AfØN€9œ*·rƒowþí©õ´_$ÞÌ’Þœ´güë?髳»D2ÿ ÍEù@D7̓ü²n]GVý¤šMð`ºÖU¦« ‚|¡ym°ïM_9a*zÌs¶Z$Y‚Æ•~Ÿ+»jùÆMð:Ñf„nŠ¥[èzþPdíÊŒ¥ G,3ù[ä_ÈÈðÁ+ƒô´ÈÝ<-ßöm›LÅÆa©Æ\Ñ ùYFEEõƒ4{>FÏŽ4ÎËôNêÞ§ªþ•„fž‘ÁÂK¤ÚûÝ %H‡ý“[ö4Iü ¦µó;9b"8ïêÝ|²…h:§T7»ÛA±köW²3ŒýÕô˜´¥«ní<¯Óo'é«Ló[ay¸›Jèn#Õôø–—‰à·jؤÃÀ¨Œ’¡cpçäÜJŸxC|ŽTÓÿ #¡¼³ÿÆT‹O¼ ð ¼½9Åù}¢*uHðäOšüò:í£j„.|žL®ú}|uÈçi0õ$Øž¾:É(ÜÂÅpŸÎ`ûçtzƒuÄÊyáß!¥ä>Jm" Ätä€ýå0åây~mE`¥`PÔÊ/|³Pr݃;¡§Å8-TÞrT–ˆ¶ ¢‘è!Ÿ‹‰¢ÁÀ×K5Iäóœ´"vP<¢h|¢Ñ*MNý>jÂËUï¦C9ûoÞF®úç[µá09€ÿó¥ŠÀìQEÈsú`%ôLu¿¸¥a+”:ò·"þ‰Ì´=/ºïÍš‚Þî;Úùa—f“ªëi€@9Ï?|#bÕÈùhš·‡Ô@އúRS8hR×ZW—³¿¾UËy9!ß´¥Š`nq¢=Š`Hÿ1ÐýéUhÁ¬Rž%TumTÑh]­m²TÌþýÇç׻ߛ<–×§ÍÉcã}a±k¡=4Ý ÛÔilE5ôê(Ôå4ÝùU¨Û 0’ŸéΧBdÐÈÏß4taOTs'œˆ ;—¿/Úò垇Ná/E¬ãÒä9lUÀ¨¶n·¡ * ùÏ¥Ò»3¹vé51ú¼¾€)d%@ɱ€+&FVI㸊üÏ©`Ó´mzN_y$ôÆdâVoþQ7=H¼¯†âÉ0KîÀ͈¦ÄÀ;âA¦'m“S£Å€Ta=fYþeo’ËK>/À]œIµ¸JløÂÏ®SÁ°³Ù$ œ½³ë—;m-¸YqtNß×48‡0d“S¯j $èøeò@7®‚†Â›v y?Ša¹§bÔ ùÏo÷zvÀG&úü×P©ëϯ÷ý¯¡;&šß´¨÷+šáƒŒ…üA$1"†i躲„u|þš ˆ¥‘º "Rºƒêßûb¿½kT„cóÖ0ÕÏÇU?¯:WM4ówÒ D@ïçUçJÆQBÞ¹¦YÌôG,äŸ8ˆ»eu£}¤”‘ǽ~?Ã8µwÛÅ™©˜:DÂש"ÜèΕ‹‘¬ÔøŽ÷:ew{ÜWÏÌön[r1?x.21oüeÍÒ®äÔ¸åH»·T· xïïçµ~S'˾¶c½u'éM<•Ó+¿ÚV+i¤Y%AÞ12f9k©;K4Ý'÷ýïôo¶Gþ?a׶ܸªD)–Ä~Üïgªf’@t] ö×´ÔíØ3Éë*°¡¾®Åè쟔&;®¦3¬1ÒzOŸÕlƒøwcJÛxæKŠüÆå©'Âõnubœ"ï'²Î£:£{cÈ1ºSÊ?#S`7þN¡Z»eís@~e(v&·TŽ5v!oñõ,­çðA•®¹Zr/]ï'n†zq\TïèÊ?PCþì‰!–Š’Ùoga?‡x¥«M4 ô¿gäÉ×äÂè€ ®ÙÈGÞ÷[ñÔ,°÷ä¸mÂ’Y‚¼Ìrû‹½„bUbôRF¦²Œÿù÷H‹´l¦ŽÇðAþˆ‚HTæµÖ3¿Þ¿˜<ÀZчZ€u¿?3é@Ž«ËI` ¢¤ÌajY»®¯«~ ¼žQ HcD“Gƒ´é0ð†ZÙD*[©Ý2Oá>¶dÄOÔtˆ÷ÁÏ]'¨»½ß ymîjO´ ±«³ÒLùaòÄ®öó°=þBízã!{‹ÄU^eFÙÑÈÄU¹Sè*0Ê,=ØFHáä(—ÏÅ´'|ÎHáä?"\"çpãÛž鑼¢ ±©Çõ©d39í{,}9‚âŸÇ³´Ó.}µ éqéÂçgÀ@ä¹6™7Ri.õ‰ÅØãY66É&Å©“lD¾·?ˆinÿQ?5¿V=‰Šô·?‹ÄÛŸD޼pyê"GF‘£ |/r¤žü…ÈQ@b‘#@^ÞÖèå?H丠8âñõ˜¨À¥£ÀâÝÔ:¦þ"~g‚Rû‰»-øœ°@Ç}v°†¥o“îë­ö^¹øãû'qc*æ7±Fuyí `ˆÜД(UøÒ;?¯@ãô¸?„@~X«ša¬5žbˤ>bC„në£Výñ#èÉÑhõ•«ü8 ò‘R·éì†%Wƒ”~!`íæ¾“~d |РK¹çàw๪¦0õJ€Ïàºo›»œšULtyŽsddI22²´]»B ñ]~í¡dø‘Ë,K#ÍR’õÉlîùÖÍq©Ìv·<îÏ>J-Ó¬™”¯‡vby…Ô$ ÕvhÌÄÕª¶™ oO íqL-Ãÿ¤›ìžý”æÈÀά1áè iûñNrÐá ꘀä’æ8(srf?Ö¤¬úœ‘4Çà:±µ‚° ’æÈüÙ2·ÓKYå0ALìñƒ9‹g:g£×‘¯K΂TFl§üm]i6cà¯íxïƒ539f e;ðvz¯jnZŽ:u›Ï™gýØëIa`:>îWfÖMÉí!Ê1 9œ’7\‹ ¯R³`žf™µ D¢hüXpÍæ–;G¦>U4*],V×ÉáØÃâ)O¿››ûÔ[qí7‰Gž>æ`Ò2+?ÚIõªÃÀøóåñ‰Àe’Ê‘‡ÉÁî¬Ö’è‘îøÒ‡­y%µx»¢Ì>fí&5mr}’Æ8l¯½Ð5Ä͓Nj7u—BøÌP™×wu—lðx{WwiœÔˆk¾³î ÑOá {øCutI%à:ÍŠ ,U%3ݦU’Í:Ç™ $ß‘€—PºV> )ðvvõAE°Š·N2QUøùF%œq ËóE ]Ÿ€ÆËc ¿Hýê³`аžŒˆ#¯¹©d`jRÖ×<’y¤ŸªÎ˜`k›‘h8‹ðÏ0ðñ8†Ä®/øL%cÓµÌ,A^°¢~‰, Ö+uò´YÜJº`A¥¼\Ÿ»™±#Û\ˆ ȱײƒÅôà=´Dòˆ¦*.Û­çàÛŒ4þùõÅÃm–Š L —h7´ž×NtšŽxªæE~à½\Æ{¯:0øõJ¿ˆ%ý"ü>y&X‰î‹×ÝÆ|‡§˜q•ÚÖš×Þ.䩈 ·Iaº².ƒï§co4Ô±÷ÕŠTxÙöq#s¶ä£ãSä\bžodo0;Óq*™eõV75ÝîëOd°’+ëd)yÃL` Yn“møÜ1:û'-sKOÔ5‘z§Z ò !ɲ)Ý[[ä÷[…)&éì÷·S›¤Oôx«1¥é˜Åúœ El¬íÆ{M—wrTº¥³ÅY' Éü(‡8ö£Ⱦ×wÊUÔlyû)]•©6Ã(òó§vU¹2FPä¯jä‘©5›FòZfv¦ŸÌGgAWñ¤IuV/ë¨.#^¾~e@Ë;f1° ÜçI¤2XÛ</æ£$\šFì¦AÔÚ“©ogŸ4ÚjÝ»n9´É ¬¾Cz¾”çª#Ó"~Aòî˜ä§î¦e˜*E~ã÷ äYJ(LݺN Lcàý‰4lJuªê¥XK DÂHlS¾W*ÜÁà™õ“ãfÏþ#ìMöï÷N“mËøqV<ìµÀ@Ta˜KkÂW|wë¢ C‘«…–Y÷fî…%À%ÃI¥ˆS›'舟8딥1æ>xÌô¿(0åˆ"p1ÇûýMhüÊ 5Ãç~rlÖ';ë‘„µ¾®ÉÔ Lõ€hZ_B|©ÅÔ>)Ü]×z'{‚¼à$Z*‘š:[»ÍLtòKA‘qЄd¬ òzh•Éçenbý@¯é˜¨Èç&²Ú5óRºq¦È³¡´ÊäÕáÙÃUå‡#Ú…ÔbàçŠÄ°áMkgË‚ü†”v) Œ­^ÆM5ªáŒ ïˆ6‡§¸ÚÂkË«¥#ÈÇÉ!ÂsŒF/ܳ¡Y+2{ÖKÜÙ9 36z\EÝj0ÔQô!º*"ÕÈL0n«¾ÅÀ£Ó#w,îJv¬ ¯„…œÀåŽì¬Ð]kïÍ8ºEcàí0ÈpåÈÖÉaàça•"K ‰AJ6úó›{z}€ù©+§Æèe&_J%uy!…ì/÷+íIÓ"Â{Îg:{ªéMâÕ"õ÷,áÆÚ•Y¬Îú¦i÷ ¬XSùàa7yAšÙÆ”ó¶5|Å@î{ä~ÿF¼5áwò®®A)Wl=Af”I¾¨ÙX‚$v–@; ÙO†¼¾`gýzsá?‰‰ç¿L~ŸZ9‚sèx¤í€¼¨v‡p2;%f¬gäã§–^Íj¾ioòDWJżP^ÏÜmnñäí¸f*沌AŒÂ(f´’ë°PdÈ<{¾Qu_+Fîë7F¦&šˆìÖÈ}þC B‘°zTÒ²›×FfÎ’€¬*VÑ=º}à  Ï`ÍXE%vx‹?2ùåÀðÁs‹ÅS‚o5ÔªiØfz ¼b›€njD™@° ƒ‡8 l«ÆÀÏwœ.Ò@,¦ø ,1˜ÓE:· ·à8]àÆÎ^TuYçrßoQ\þÌ~- î†UÆ^±_KH ñh©µ•ÒÊ–¯o¹ª´&R{IÙ<ÁAC*c;ù /2163OGüzIÃÅLä7~¿ca.n¼@*c;)ÇÎÁœ–'< לNýxÃ̼áäar8í7DslÍé|É Ê=ÒÏúï¿9ç]=Ö f™]1ðúÄ ·&qCLÇñ9"OÅ&XdF [,~Ö«®qïüÆÛ_ºÆ ÒݱÊÄ—úrã ÀÏ7¼Æ¹”VZØì¿¨]Ènß¡:^Ãû_èŸ ïZÜò©f ë­ž¥Õ½)O5àbçg»73¯Á/uXàîy„—uµ2÷ÅãG[t*•(·±qR†Â@â½&×0ü:Óh¦ÄŒŸOÀX »—dÄ/Z\™ÔI÷?ÇÈÃ|?ã«ÿ‚9oÞ10±þ{Îz;;¡1ðA€{?L¶m_-šüFä½}oÁLnXpŸsk /„[dÿxMÓ65¾ª»Š Dc”eÖ¶U½qägâv­&u¾µË¢Y]š`]ä 5"AJ‘­Öó J«2òólÖß5_"¿ˆY ‡0tF~9~((©…›ª,9Dˆ:C€B/™Ð‚ žŽyGH ¹˜™¨¶v“%A>Fу„ÎÇ2>Ù’žõ“Q”·ÉX-ÝÔÖÞÙŽìQq!š‰Â§b®ªW•ÄY d.è ÈÊÖý"È )®ˆ¥ê—d¸¾úp)Œ™Zr9MŠ=M5ÛV?™~ ȃýól´[wÍzrâ Ì?ÊD÷³¯û̬Y ¡¼×½°EH(õÒófõnÇ*Ÿ$$÷RQ¯ƒ–Œ{¥¨'(ð½¢^žS2+êíµ»¢°§dRÔ‹ËI$Ø":øðœ’q‡¢^Š˜a“n5­Ù0ðûU’ŸÍ&|ô ËŒýú¨ÇH€f%—Ia–FÍÚäÞ§ÉŒ½žÚðö—©áÕÁZ_/§>~ã$?Ob=Äzùö¿þXÜëë'­XàÍQ°ÚÉpm´e¾Ú°Ö×ÿré]zuã\9ð¬?W`­/0SiCô{ÓÏŸià÷Žð5‰Ÿ”oÈ{È]~ƒ–[xž#ÉŽ´¾@Ü"W‚i­”bjX1ð yŒùà/Ôig¼²ø õ@ d‹bO‘_WÃ$¼…O,ù5dUÇW^†e0° ­BûˆÆ®Qk¬6_乬Í8*¨#ÄÊ\û{´\}ð”7pý‘2W4ÿXj¸Ø¹EbÝŸ1¦¾?µ3%=©p÷TfžÅìJÅ0òsÙ¸Öb7#'ËÂS³VN=؉X1ˆdg¾Q5Gøªz„A¯œu2ñx=}éý=عŸÖi Ê­x;(è8 œ‘¾a¹y$÷Ûì·û7É~f{{ŽÕ›RÕøõžz·¿5ÉzÃâÚÀ›ê)bEæpÔ§Ý.Ïr¾™P8˜V[·Z9‰Ûå™Q ßï¯k5,üø¨déWª§€“¾¬kÝÕdÄSšC3\œº¥Ÿ ðó,å@#Vm°D…À²ð²kê™ò¿ 0õdôÕÞDÑ%¬“t#rq ·ÅÀFom±÷<Åß»Íms†—­#Oƒ / 9¸#]¯yÔ­ÍÉ”¸0ëÈ¥àHÞˆˆ@êVOuµ9uªR5y ,"°KDA_O°@¢²¦¥c~‚4Ê)t8¹†MRœ"¿žâ”mb¶[y=åîšë$¥|04š„1ÇaÒ2ËÀ·'«Ki¨…u£tRtA> ªwÆÀ3rŠ´¦Žœõ"šÓ¤¼šÿKf(¤EÎW 3{w”UÜŠŸ>c“Ú•QÊo‚¯¸º|G?ÛX*†7Z • xÄ ºxò0ð“†ì¿1’†,ëÒ5ø…ÒtÉÏ’Si³Ù~qxèðV;µfʨ1ÛuÖ­dyîHÕ#÷>u‘RøJ„o•ÛC‰{kØÈ†Þr7Ò?,¼Î´•Ì8¿f™t@^Îk’ aoXXò’N~AvT§¸jV“Û€f˜î6C§¥ ëÏFçíH¯Í!S#˜nÔ ý&7,ç~"£/بpëð]!È/Ü+%Ym> é³“®ª´ðav½MŠ ŠL±°pËœ³¯ÕÊçjY2 3 ”Û_É”¡œþOص-IÊ2ÁWšés_îý¿û=ž@PQ!öé »{6b"æ&ƒö€@UeeÒž—ÓºF›1˜ë_G¤ÿõ¾IrdH÷üù»!ã;rêzլΧwR(.f”\VÙ°ÑmÜñ½}Ž˜¹ "/‡V¿å{™j:s“yÍ+Ãþ×›¶¢z§1GÞ°¼JÈå ò„h±ä#CÛŠÆ>gÈ–- B]^घ¥ì²Ywzî1,z_®[6ë—«IŒJ¦zb ³÷~½"·î¨¬ë/-­©·ðr>fÖfmÚîåU?ëюЇ|9j0°óÀ3‡šš¹­I{ÑùÅ¡fêÑ69ðû )asÑê® ³Í€÷wÀ%³›A¼9°Ìæ¢R½—€Ë€Ø¿³m"°Uõ ðû õ5¶,¶}já~{fùå|PýÄH•Ó4dÈÓAÃG©A#‘ùw'É]cÛX7u­@#OoÔ9äPUóbìô2¿2/-}_”F5å;¨¤îtBþá¹÷»ÖÕTóßÂódÑëLÔ„¨UÌ#^Ðÿ°ê;î¿è—¥ÆÀ3ZLcÝMZc„i!wý!Cæ‹6À–Õ´ô90YE_ƒ@”œ 3ÄׯÌÕà«n£>O^vòVAð'ÖÞó¼ÎùO_³¡Ð¯È*…´9ð†ãç0Åg=¸õE5QŠút}‘eÛ÷å?å6duáOG³ËôÀ+3ÑÖ ñÌÑì2Ö6©à¥hGýôž§"£Ñ„€X ›]n¢4R‹;) ]zÍÖOG³Ë XÍn©*–v`@!¹bUö?Ñt1ˆŒ˜y`K-W C†ãRxJñR’(÷Ù¥ ̵è€WX²¬­FïNÁb¤s=êSè ЬoT;ƒ°ÍõúZeÚ*8³;†t–¹ëŒÀÛ1ÑÙ61Ù¸ý„s(^oY2aôԜˆ†¶xþÈ˙Ӌ¼ÿÌËi Ž=£Ó#‹çÖê±5PÂîñð<­9w÷n-ƒÔ)vÿ3Û§ðÀ}Ó®M‚ØýÏľ­ªTÄ­°CC0ð’«UlÓ£'w_±Lo·e]h÷ŒJm0ðvx×A|gÔÃØJX¨ŸÇ»Žk›{y\kt×9 Ó_cà±øk&÷ <¿½ÆÆ_cc0ð‚ö±к'CÆ—ÂbàuÒШâ[…pO:®Ï¼é²Ž÷« a“]u\Vo_Ë3ÐQuQ𱍡fŽŒ“xtT2_‹öd<ö<1°sÀiehÝöãvôÚ€MÝÖµ5˜gË] ªuEDv·ü¿C¨’d#"AfÆBÁÁ(w@ìY9e¥[`Ž+NÕZ•Ñ‹)Ÿ(»k枎¨úµ²ŸûXXùê(ʶ¨…4î¬ Âùóp!ücÊ1„TP›½íöE!ÌHBlšÌ–¸™2äy—9EåÍMh·FWt@^°…OÌ ”ÆP;0•½ðï+–Þ¨U-µª©˜íË!C†¬U´YŠÕnHEùä[²/Zýªö_’÷gVie5mG™!Ø<¦,³´`±»}#PÐïõæ*´®z…§@[‹uÂ@Ô«àbÂ.Í¢‰…“ØígT£¡á9b&9³Ð–/˜Ûä=ö¯<­ìåT@WÝí’Ëì”oG<¿¾1¦3o)½PºQºq“BvZcàVàÿý;d]ƒ++(›æq©°Ûi¯q–z€ÿízÔD×X¹(ʳÈèúÝé#žßßøæ®5þ®[ùo×wmKÉÖ¥ÒByÍÖè7Ƽý˸ƒcàéSïo2î8ÝnžlX<£¢ä‹EOÈ·£žsÓ‚O‹¬ùX-ËŠ§L?w{ÕB¥ªëy™0»ÛA #—“KòŸ¾àBô ál¡b®ÊQa#äç¶ÕÌ1Qs:oØÑ>zJulXÜ. ©“ÛÞ`škR%F[ ‰Ë‹ CE;«¸è—¥àît „d4)ë*j¸Õd ±4"1×Xüh—„Wc© D¢‚U¢Ù,Ãb¼ö¢úv áèÁ¬1Õ·ÁEˆÚêJƒQú †ê4õXJ¬­1ðñX½Ÿ{ÕLMÝ!©V¬k™=ð¯Üƒtcº7íe¬‹¹ûÈÖu5~Å2•%›A††ª`ÏÜÖµ^ÖJWòü iŽÈdì´—$'ÌÎý8¶òú9½EÞ>÷·@ëöüG „Ȳóm‹m3àý-жr{þ£¿–Ûóçþe³?ö·X5f×øC dêoÏô·ä7ó¹¿%soˆXÿÖ\®…ä² BÉ\ÎH£![†íB·2 -~nú®¤^оŠáÈýûhzÛnuç&/$êîGŠåüÁÚ¶+›$áî9EmÿƘ^嬂†ÅûQU „Ms;hxÅæ/±@QÕMd¨2à ÌÛMȬѤÔlU@×¾E-ÚF&kKFHKú™¿dHJδSMö‘Y°ÔyY®3c&ZšÀÿæûÆåßêã½"«X$™³ßþÞkšIA×L+é‡y…sß=QÔÀÜ2é%»pm*«”ýjš¥'bnÓ°ŽÖ“S>æ[ú¥jO¯ÖzœâÜ-ƒsdL5x˜¾£Õ` <áR§û©¤>×}§i;.ÔS—Æm@Kú ï˜ûþgkO­C‰‹¥š!‰¥Ü÷ýw,>´ïr™É í÷S¶Ë‡¬çÖAV¥`K’Ù¸Ÿv9ý È¢J'´ Rj¹ï4­¤í¾El›¶»tGY¸k,dû ´ÝÛ¨íNm¡¢ȃ#/CåMW÷óQŽ£ æŸÞþŽ«q„>¥ûùÕPo{7>%Ü·ó4Y ¼"ñŒÄãcÏyv37¬²5ŒÐîwY©0Ëq´!‡à€.òdj1ðCÀ/„­ á«løÄºªP>²Öíóœî¨â›tå£RJYŽf˜iöÛñ8`pCçžVîãÍÇ<íRÈM\¢Ý&ÏÇŽ€ 1•jËùù£•¤£ Üä#óŸ kª(‹RÎåÌÚ yý †ìh@ß?‰!sá_ObÈ÷ŸÅ ŒÚûÏbÈ~¦càG1dbl6¢¿™ßïÌíí!)«ƒ,ïî]ûiÈœõM‡ªz2Cž«ÜŽ\Æjܶ å\Ñtè ïuL®·Š3k控oñy©.c-W»c9ml"d#·ÃÍî5F$^ñ¬îMÛ€çé‘ïñ¤‚ ¶Ô–κm€ò‚Ü·P1íȨÌPcàeOXƒÀº_½a”_™¯æÎܦV”ÍÕ]ãí8øüÁ¸H‘xGM51·Ⱥ=NU¯i|£Åx¢‹G_ÏF|bc»°TyàZð>…ÇWNü(Óƒ4‹·{2kC3$’¬H{âÒsZhbó—xB‚ú‘íŽifÑeÚ»™%ø–} ß—§X›’O52ä啌ÝM6Ìÿò1¯>@SÌl­@ç-Á£Ín2›¹‘„æOéž9\†…`tÛ§XÙ’½¡oÜz¹XnÛéFÙíÉéhqYAÞ³2µ * Ïãxøô†¦[4ßM¬Z]­˜õGZû鵨ìý:Éâ2)ѤOK?ðb,G ¼~6~†Y\æÆÏJKlü¸Ù#Û]Üo¨ç¿1òÂL]!Á÷D7c; (*/Ì2©JxÝwnHqk]k]d·ˆ ß xKS÷IÀ™©…Ö5ØG¤ Š7ƨ xÚÍDÂIÖ'<BÇ®½ÐÇKÁ.¤xÝ4ëÌÔ÷Ša=Ëñ7f9’LÛÞ‡$=ôØ{ÜŽáR^üÎf×xKŸkSmçµ®5k ¼§8¨©cwT¤Ûµ€8葲APLJ7mègÔnÓžgMx¤,G\êx~—b–JͳŸÂÿÛ PÕQ¤_ŠN ¹«ÍßA%çÏv` eEn‹¢6|‚„Þc—Xÿ[·U¥Ë{%JãSÂòüÑe,…NO¼W—=ع±'ÞÿÀê.Ľn¡˜ !ä‰Ec_‹žÔä¦O¡"òÄ{×DJҡቶ¹(EÖHÙ/‚JÁ®ýÜs,^ Ì/¦!YeY#úBL$ûé+ˆž°½;à$˜{â ¦ñDô*Ð!£!jQ…—®‚#4òí‹Y´ùFJ–‰õjÏ´:îÆW“¯T’äôò<½˜Y|àî¸Â œGàù¥VÇ¢vÒì€U‘ñ‚W F¬Wž’ÖÏ=’ÞŽˆIG}:˜0²JpI‹ÀË»SÒ ©X9p>žçŒ^µŸÞ¹¶½ÏEÜ”°[a‚Dœ¶Dk¢aãÄn…‘5¤A¦ÒÖ“a5È·Bü}Ûc-¡»Æ6¶ dpÛO㨺èxz^޶ÔL— !k‘„äž—C• ”xwfA¶h ¼ôzJ|­ç%39ØÖñØ‚lZw¤©mv3H@u;n-ÈD“rå@¥Cn… k‰)ÒÏ3·©lÈžM‹b˜ÅÜe÷ã‘ã¶âsÃÏæyÁU¼;pÛpín=¿ó˜ØÐºËíÚÒÙ}89òúiª©=üzèÞùÙÛ-­ÕM„›jjò; [Éß(½qÊÜbëÚ z^%‘ÒF[1(Q)w X2äó³©;ÄWÈýñ­¥ì Y äþ˜z¶A”’‘Á™åyÏÔ<7?®í3Ón¡rQ[„ç#7¬H’BTm/M[P Çùxþúo¼ŠÉ¯ó濲¼ÅaÄóG–7ËG¼|HÐé†Åw}F>{ït,ÏÈgï]‚ΛøY[â÷sfŸ·]cöšEàõ8›‘x ᘊÀݦ1 ]ºÑdÛe?½ÊÞ]¤ì¬ D™ø€ÂBvî:ÒélD\{ܽµ.ØÎOôÙ{£ GÕïðrà‘øSZôs,\,TÄŽÚó׫ÊDVVh:É.r_›ÿ˜ÿXƒŽt^´ÀÀŒ™UXp(ŒlaD”¶ý{±-ænxúì¹~úñs4 Ò¼8d³(RC mæ&ÒœÏ_/ºuÁֆ͚Ž|*xÜaÏ»3Òv”$žlîš*¢çº…Ïðë‘üŽéïÍTq2S[¸ÓMHÎjca&¿¬ròÞ ELŸ‘…ÒîÀµÉ'7V¯»×Y(3%Ôë©¢Eãõá1ð²§-’fŠ»mXWNx…ôwn)ªž¨f¤ÑˆHª‰4)W¢¼ü¨À@¤GRÅŽ¹…n÷>ö^ÅþÙ X•"v†ž±…kÅø´¥Ò®}4Ö:c %H-‡†¡Zï.8Æ…3¶PBeBºYˆ‹†n¿ÈSö÷zb9÷ü}´"õN¶ÁÓµsovQ"ëü}°"­@ …‰’n™ Ž4Ç£“t‡Þ’%}Îß¹i±)lk…hº¹4Í¢1ð†Ûb·ƒ&îßÚ’ïYŸPÌáÖu‰{} 61j­c!!ŸS!Ì«b¼÷2áæMW>1Ó•Ìóœ!¿±­tl_--#Ì-[Ù#ß}°Š-gë‘kQ¸SiÏÈÿ »’-iQ&úJUiNµì}çüý¨ˆ‚Nxúé0³²wµ¸…)jã½üqƒÖF4ók1¬þHÌÓ…!¯ Ý_Kêýü¢èö/‚°büñß·7ð‘­k-—¬\—–!£¤ä†Ìv™Ú¾Ri¹¦|— µ´%«€£0·ëØkžò]z²Tðö(õxæ Dî óbKWmÜvUyYtyÎÞõ/¬ÃmiÑ퇮³\]dh§‰Ö_Œ"6¯¼!Êò0*†…‰Ž-wR7¦^óE¤-2O-®Ø*'³jÉ­¦À+íÞèׇç£arK·É»Àšƒ?»} Z7|EÂÔW`;Ç µSS>²ûøS7+£¦ƒƒ?Ñö³äÊÆÎ7`Q"P¥H—œ|ßÞäX"[ÖæW隉ö"¶"•®ƒËÇ-ÿýe®¤jDzZæ®$¡J1þÀüllm7ÞP™`+r;—Qµ\Uº¨W|¼tAÅ4Y(ÆÔcjÑ¥#šð«0ÕöÞ«ªö’GÃÀ–q©3)¾éh ‘ºšGÐL¾Ÿ|9æ¶îÁÔäM˜|¢@RœÝÔl6`cò¢¯v3Dq» ¼µ°cÐw(ðÁhc3dé­Ÿ@òäû¬8‰7£­ñ¸ Á¶ç‡y@:Dx÷TÌyÇ6ü‹¤±ób…î2+ C’„£:r½úÐÜ™VJ†¼P*Ù­¢d|D>N}Ç‘ Ir@µE í=’F7 C^ ¡GÙüè4­šüøHËfL‡HW5sº æäÐ|ˆÝgy#v•”y£ò»m’CóRl‚->vé…“naÈ'Eƹ ÿÓtõv°fÈ74sïÝOm׉!ÒY‰§¥­ÄR³ ÚäÐ|8F8`ŠÌ{NÙ~`¯ÎJY[‘N!#32drË‚¸UÕ·å ”?¡3†¼Hì’ šÞ×,û„ÒÙ8¸||°ôá„¶û*/wDJä±-E½¦Íäx×|Ø‘Û.©jh}è-{;— ùÜ‘ »¬ëÿ´E^óßùs ºTPœZç,«FezvïI¤Rùç¯pu¨V4½ÙèTvÿòI(‰ÞæÖ0È$Êï{_ðE&¬þï»ið<»p×í¬ˆoR[–™*SÉN.—×ÓGÁ\´¶³õAdb²€DA Ö¶Y¡Ñ=!üo)ÏWà¬H.ɯS$0‚Àë›´øiÜ„­øiÜ„­øiÜd¤ÀOã&šïF‹ð7Þþk´¨¥ÀO£ElÅO£ElÅO£EŽ?xÿ­|?˜ãýÔgœ7bÞF4KuÈ„æoâ'9×f«§É¦iÞµø[çÀ0 èˆfýwI8ÿøÃßG™ƒç¤j¥(ö´¡Çþ%ÝûHè±I·h ¼|H ኗÿJ i ¤Éuè/]×5>¾„br’œ›h Ãe¦K£ ¼½4¿5§³„BvB©§IÜQ [IreµäØrG¡1±ÄÔ¡žŽ†”v²ˆÙ ÒCB¥£¾ª}Õ©2AˆÏ6Ž/œc;geÙ§Å\i“C;¢ˆ’­•ÿ¥]¡DÇ/}}{¤]³hf“ÛAO TÎEí#žL¢Ã–4L)œ nå°ä †Cø —Ž©pÕuù”/¿BBÍ}lÖZ§}|×SàåDý±¥ÿÆÉ­µ^*½lŸ[n'ÿçý7Þ’Â_ÿÄ´(56O Q°oÌ>Fƒ`öŒ[Ðì%´ÑÌÞà…3;pj]†Ça”Þ@ž\¯ gÞ‰)·ú&¼‰’Û†K[.#Ê—% o¢ $‹±h6YQ[3UO I˜íšõ­ZÌЀ¨^’Щw਎![&¬ìÛ }ŠäÔD#ñÉèÂNÍ8uëD±‰æÿÃVÈÈ`k;oWŠŽGo }ƒ0Të]Ÿ íäh¢ÙÓ±^g…²cÝ@á€?”äæU“e>ƒ¡Ø„pTƒ¶3°0赟ý+¼hØÇë÷ù†úy¦U[¢«@¨§÷iÅ8¸²­Ø§0žêi>Ö8ûç×I7‰‘¯G–œ…08’êiÆÒý¶bîdî(ðN#ZP÷Z½ýòªc7ó ­ÿÀØg–ÔŸ…8“êiìÕŠD>üJWÌËRêéHÍ&eÔ¡ygì-ÞõåœBPÑ–ªk}ìí(ðò:ÍÔÂù0@؞ʗ·Çá&e´²%„¬ø_`aˆ1Hà°K-G¶"›u…ĉ¥Íke3 ¼3¸Í>Ö®žš¾)¶"™‚‰½¬þíºN¥i:­ø<…ÇÛÁ>d©µ•T¸÷“¥‘„7hëX5ø÷,7|ÿX$»rE%dÛ=0û%YñNb ¤u鼩×>ìgÈË.K"±Ñx.Û´+òóÕ“×ᬢÏýYÏ4»Ÿï„¨úÀÜY+ í-zÎWL°ärdd0cg  ‡Dä‘âˆeßð„õNàÕáW¿Óê=ø¹µ³.߯~e§SÐZ)¡ªê«ºÕè`\¯¼ü€±+Ç;¦í0,_¯Ì×.K ŠLK­û ɃÄj ¸bºˆÞMC¹0àî¥ûŠu=LnØçGxÇÓIdØî¼Ýµër ùàãTUÝÞ_ÿ ¥ìGv3O,ÈÅ.ˆHèVWÍ‹]WBkS½EÌàš O2yï±4µ5#•0_£K]­K»²ÿþ>MÅmwe¹ö•jØ}S†"ÿMƒÕ¥É½ ª&†Œ9“ rƒPdŸéÅÕ y¥HH {dÚi{ú7Ì ‹h¬# Åj‚¾þNÒf@€¡$É4^hT°TоR¬õ_o§ÞqYa¯˜–½Hz¼ôk¥£‚RÖ¿”^8}T,ê† gÑL·3“åØg;Yvéë»Èeh§µîæŽoG!'´.Å^1¿‰jpú#'’ŽM 'öŽûˆ{iVL4\§YB¢U¯>"0KÖ°“£ÇiKÎÅ*€lûqIG ¼âäT|¶Œ½•*ÍJÍ.}È»Èîܦe^/ÞXMxßKÙÛ F]OÞ6:.Ï×L#ÔgÚÜ¿: ®ç.>4üZ§Zg@I€ ÝÇX'C?ø¢›Ýž…¬ÆB+ô‰Å $áA}CÈ28‹ŸÂíë3+vC&·o>챺5ÂjÿîâŠ>ìuÛ®vP©5x¡šBqE;fbšgS3`‚4€b¿´6ÂÔ•Y¡e€±Š¥¦!Ý×›uðgˆ¡ Æ"ö¿Ñ@«}EåW¬ðNOƒVXfP›)¹qþ¤4Ûs—£ÕÖ¥ ýÛáVýùûü綤£À½xÏãP-eÀû]óíiœÏýeÒÔû÷sèÚ™­Ùô–¯yCF›@¢&¥æŒ=÷ËοÍ寫ÓZ#pæ ò±·EŒrãŽˤ{,SòÉr8±K´ùèÆ‰¿ó—bŒ‰Ï­F*¬ÑåÜN ™|ÉFø“¨Õ”e­âé Ó½÷9¹´þ1 ¶KÉ‹½í§-Uî݇tâÈ„ÄË9›!×tÌ3ö.%×Cn0 4oÔaºžs *ˆ¼ÅQÓlÙꃨղg´éÚìHðj=2ËDÖ²7$êÚ¸íŽJèÇÕ"8—C¯V†|¾ž:œÍqÜ¿7ÌqLÛI`ö“€­ = Lg»Îa~ÿb„áÄÀk0ðŽ 7 Ò©Li¯¬ {x{5ð-ø¬ @¢Ó‹=(ÞÈ4­µž)ðAäÈ !¬OGïN§ùØQà“r–¨ŸØ›ð üy5Å-šâ–mø×«)÷¦8l@I™b½™âa7Å„hõdŠ5šböp¾tý÷iÌ4¨­JD$„hõd´§Íhw»Ñ>ˆVA®M¼*3¡²UÛV1äýÕlj4›üw>Þ›M!Ênäûù¤È}è™X@þ¼7°bìJ¾óñÈ@䱿$S ÈïWSÜ¢)fÏèry5Å-˜b DdÂLñnâ³Ú–ÝÑåújŠe>J·8·3äíÕk4Åy5Å5˜bÃ-Âã½).æ:_ù.=‰).Á¥)Um|X<±7$1 WQ×­Ò[퉭 4ÅQS0˜â¼9L1 ¿Iæ_FW!/µß§\ŽìêñÈàF»E£Íî=¯F[E¡ùï¼R£ G°7Úµ©R·2äm¢%ÈgUÆt]—·¶Ç/î4n±5 DÒ¨RL²æ†yäs ¥ í»+I(ƒ¹&CYú %oô¢(ðú:RO}×+LF܉¬FÔd¶öÖ¨Þú-_àL½ŸÄ87w7¶Œ‡*\WjA—Ã}G[<5c5ígç6‹ÄƒÊ?E×¥k¶âõ]$ÛÆô>î„ëíf¸?kiÄ:nƧ}åÚÊ{ï¿™ÄáK’–.Ïf}ùó!UÏÍÌׇ¬G~¿¦êÛSª—×üP{Ê2y=LóÜ{àYгäkJ%iÊ;FJWz¿ø‰1˜ªÔ ë½Q)ØŠÉëüí4ëzîl)& ¼ÒùÛ˜qšf•Ö¥™k dLRу‘Œÿ¹}NwJ“»˲y•ùH$šÁäBŸŠb¬šÙŠOz<ÃTiÝú(·°x÷¸œ˜Ý$4íN³Q÷Ckv3ÍüAõ ÝÎB }cf¶$‰f¶5·´ºl•ÖÂ9†¼cY¾ úêf‘ƒ:"©þ ¤Wk+eçù´&mŒŠÍ³Õ4Vë7–!oYÆäGºÆÖVU  ìàƒ.q#ô2Ë™_ýq ½€Ø­dzÆÕÂJÁσɴØðZû“ÜMarØxcr#ì¼?ÚU—5CF‹Ópd¬jvj {FÑÀºH=ZBÎMT½ñGÖÀî(X÷ÏŸ­ÆX 5¹· )û€.{§-4…øË“ÈÔX¯8ÛȃAz{™¶ÈXȱ’ã8ò«ï¶›Õ†åT‹ÔÔŠ}Ç01¼ò[ 9Z±µ2äƒ÷»†wiëw-š 9¨ªv§ÆêTèN]‹C*¢*ñ× 1¸z˜s©Á¼Q•8º{¢–ß$×v˜Ö!ªÿ'ìÚv\W•í/u'qâ<®÷=¥¹>0|_°ö×0Sîô>RKý2„ E1ªjÔ?È¡÷ªÑ7c˜À;V9Çç4±4¢ž#àÑÏ$ùÑ>xTxLZ(EW‰ÔZ+œ?þѻπÚK` Zk~¡´aÎà;swŽe›øäÌÁFÁ„] ›@Zø—\9²ÏSv•8ÊùRsZ¥UZNºÈSDãàÈÕÂ6‹É™[¹ÑK Öü£p¨ÒÌ3_ ÙȾç#$mÙÐz/X†Á­÷ÃçØ¥Gºý“ÿ…Vlîê?ϬÏÇ#‡ç(9 ˆð3¿[µ’ Ìü£*"#g+W²r€<ë—iª[rO7ëæ¥TòU £3é­ØœQž²>;_¥ïîsqe/•…³ä¿ÑŸ/‡qô~ÚiE¢—|¶`ÕUþýÙþs c‘“Cît^S®„<úèl¾nRòãŠæ©Ðf¾ÊYþμ^‡á”P®àÓï y¶mÂVØnó ‘P¨l[— –¡ªÊ›u¨Ei˜¢ý¾fõ,BzñŽ•ÂHM¨.È+ßÁ“Ø¢àîÂÜîÛÊÀw¯êTËw[ÿž•Ò—¡zçðEÔWâm§š&ÙLà=ŸÀé bÊSÃ÷fÛ—ùýÉÜårêÐÞóyÊ ‘ì0kwðžÏûyOaÂmtÃíË YÝ—óX¬×KÖE- oô7ÄÃU´ieœi¢pÌg‰ n¼GîÃ" 8 Ÿ¯ æšFuËBvÜ3T^‡öVqw4M;tM¿æ»c@¾‹FÕm(Üåî–ÀçIa°7_þÙà]$q¿†. £1دï:4!a1À~¾nŸ­•e%ªˆ,Kãúlöž,ˆQN®×£hEnZέYL+QOÁZz­·I²´„ôÓÜNDƒáõ,žx¨óU-Ak;øî¯ Dåf¾É»c„‡¾çtÈú¬ ±òH¬ßزQpv¼ÞðÌ2rʵ¿½þº\ <’ö­»À) ¾fý ‘~æ‘ r»cû¨¾•È6ö—5À,Õ÷Õ,ÖÍì<`mêG‰ ªGzÉ=h?ëóòxtH9*ü¬²Ø*:1€­]/Æ™€§Ÿrw©pH$Žð5oßGÙ$wZ.#]–eÈÛi`SxÓXbAÁr/äî²¶ÿ°šÝylsªõ‰È4›ÁÄyÞ‰ª‰dõÓlFÞ‰Îð=ŸgÿØôÛ•û5ÎÄ¥Fª ù:Ó$“LÒ8 $$åÙ$T?ªî *kV ñxJ•Фs͹³2Bh±—À{ ×ûðh,2ŸT]¤J9†æ1S g¢Û'rLÈ;Ý>‘cÓ8™ø*ɱÀAø‡aßóíáLtKäXúG·œ|—äXÈ9x'ßgþ¹,ž¹,³øi¾K.+´BñcöŸñ»3Ñ- V?N;ºÍ¦òûLb%‰ËÚѦ:ç£dŸ¼*ªh _änë“òCY}à²ÜM¬oùŠàÓŸË:¼¸ƒËÚDæ²*ÈPùvgA[wí:)œÏú3ëelî'‘ïKÈç8ù·wReO¦º0T€Sžëòû‰¢©Ø°myṳ̂)æ°à=o÷KÄ)1i¬=™´ª`¨b àÅq·ÓºÆ™î aß„ã9$íšmÊÑê`¨.ì“mŒƒ%{}bçf‰Üzº ëߘ4®Wøô÷…I ó¹÷š±TuÍÌ×oœ“ ˜¥û÷oœÛ á&¾ßÊÔÎâîh7Öð "ï87Ä‹d–åˆÈGQO«`{9ÈÞÍØG¡*87o9Íêé5‚rþ¹ù«=°!¡úóŸ ¿w¤Ì×é2fý‘³|[ çó$ æÎm“„€ýªé ÷PîS6Ó ¿?pnî$h;gÀ|>n?972ZwÃòv ïŸ97„,]áIôøÌ¹m[s98Õ…sóá¹ an˜À× •wâèvú5o'w©ÌüãB¨Ç,1B5Î20€¬aŠÓamèÆ)ê§õãý“ñµ^ô 6VÈÁPý`ü0k·^Žáï³=Õ1ŸÇ…„óÍùS|£êvAzo-Ô·œ€_³ºn0ð¦q»ÓHàU‘·‰El¶ ¬Ï ²ˆá¶nd<•ÑòqÌù>½˦•ÌVçXˆ•a8ŸulCw\G)”]™È÷G¾qõ|c ÖÒóëD²˜ÉÃÖ z:CÒUf¨R~NS#çMê\c‘· Æ\'Ù‚÷|ÞrÙ±ßÝoGvp-°’†ê¯çEÑÉ‹NÈ7Øí“6KDVŸ8ÌQQâ=D1ò\B¾±:ªO|£Aþö:7^έx›f:Ô #|ú;ó,^3RÙÁŸáõ•;ÆdÉ­V5ÀýþúþÀLrî¬2¥øE¯[‘ó š•í42¸ß_™ED,U9ÇŠÛÉ|ÍW.ÏÅ ) xY޽7ûùª>2“ßµ]Áš}dçn_–¶ÞÚëõ+R6À_zÕŸøFÙ Yà©ýzŸHžÞ8'Tj°ßë¯Ô²e¬iº^5³‚3_Ìdèâ¨Áž™äÀ³ªoÅ…4"­Oö’ó‚À  K©žõR-«0TñÚY/:ÿód¨(mblE;6\5£Èg!ÆÍ{ÝIë•4Mcž!?Ÿ…Ýõ€gêiÃhjlè‘ÕçŠFàÏÊ‘ è3ô;£Hêqóz]»s;;òé^žZ¯×¥k_Äu@ÄvÁxôã””HùuR®«4Ã*d ¬ ‰®È0K©µD{–~•#ádQhïæ]b?&§á…Õ±ÍÅ0cEÆ—ÀºhUF³6´1=!©*íU0|æ$¼³€ªÉ^Hw-BpÄûï@8â£ôÏBwÜAûâ{©áˆÕgi¥ôžä^oØÆ›ðH|¨hÙñ€·ÏÀ}ñ²¯%ð»s»ÛwçÞ¤[jXŸ¹çGžpö…wì©6Yºþ*šñýhïǘîæxÿ­½J#ðñ[{?}^užÎ+¥¾÷ºíÿ“Ú¡éÒóuV)^\™âG¾Õ gÖ•¬©/T]dŠÿý[ˆ¤zo¸×ã¸ÆxC]tþ÷oȾ; î÷ÅNxNTv}v> Kÿhº --F‰eªsåg ¢XP ©ßÈÌzFÑÖ[¬J`pñ6²zvœ$rêÌá?ŽÿcȾ¨ÎXÛÉFàë'pŽ@ €…ìjpÖy;öH/›é6|ÿZÜ¿¿Êö%©õÂ*ÔèÌxß©Ï <ºwÁÝsGè–”—ë[¡„éYï£úðhÔ3ˆÝy#"ÙÒúÌ¡ŒHë•-U‹Íž*,êBv5åç¶îí´Ò¶p̪ n'ÃÄ{.‹íù9öDRÑë â> ²†8‡Èd CAÇ¥WÛ´J¥RÅúv2ÔɤnP+ºmk½ ƒùH:]9ï®O¿}ŸMIhÌMtßuÆ´Fä-µ‰5ƒ=.v±·Ë¾{A5G^?b<ëf6™ºxÔWmþ´„î? —c%‘m¢!ëûè(&C?eè&VÆzê¦hê RŸ¹‰I5#ª0¤ì&I tÔgn"Zâ\–Àâ®Í£fòàÎc²¬"å Õ97ñHI9³ÇU†¡–ËmH‰uÎM¼‡œÀ„†#U u k.Û1qpu!c ‘ƒ’¹gÔº”±ý÷O”±õé×ûäMÇ¢ˆ¼ÿŠ\R×§ú^„—¼Y÷­â¶Ð@òZÎé v>+æàÝ”² ´sv ™çÅÀ1ë¦Éí6w3%sgÁ2:ÃKQשٸͳ†cÂðR¬äZ‘Q#F$ /ñÐßlÚnÈéìõ½Ø¼Bñ\”ÜQ!çuP0Ÿ·R$ UV¾"žNêãGÍ`ˆÖ<µ 7†àí'Б’!:R¼(sh‘n‡=‘ëǵ ~šbd§MtªV¥cÃL¢vnšu/ÏR:ð‰ÎÕÁ“[ì©§Gý(zQ„ G,¼¢·v›² >cÃwd¹, ëè4O„—À÷Ïh3ežÄ'üëgåÄŠÑ€Œ)Ü\_ûÒ7"Jø.ã"„{ºXòö32½h¼qw¿¶pÌ{I?yÖÑ]Ž,Z›Þ†2êÑÿù7»¶‰½)ì.cšÌÆËVȘѦ'Õd›YĆaú‹šÐ0í–ÈšºìK Ÿhì`¿+lµa©¾¤.bÃgMÂQ3úš„³?s}ö¥?=¸ci*3šnÝæ¶©EõB¦6Ž›B#± Ë fþö …î¤Ä7“™Á|†êO £ÚøHàs96«…[2”‡ÙÜ÷ýØ“„-“¤rë=”‡]k'zçןµõã,»Fйåz]Ćÿ9ó㉖³€|†‹E ÆRwÝÓ¨ïÁ¾Õ—Ä#ÿ5Ý@øS¾"òý¹³Ž¢a#03_Û±Þ,d¢à=ïßââfÖ=’¤_ó~»øf~–ä.’ífþ^´«KÄöjˆƒ²Ùß{¤°Í©ÐšT¸Ýáþ£Q‚r¯r8ÖF™³¸OÏÉÞ0€|Bó~ÐŽ‡yGçZª>˜wÿžÁ¼cÅðöÌ;k)Þ?”»õfpNi—r(?S$ùs@lç9PêßÓÛý oCêÃ\—}¼’Õ>¸,g¼Õž¶øú™ÑM,ÏÆ•‡µ\‹6ÎnâÓnVEêOYÊe5²z×]ŠãÖET>óûÇbó÷Ve[ÊÏüSš8³m^(H]ÊÏxF˜¥˜Aƒµ@v™­ÈKêÏÁ®l>õÇ'®$¼÷G sN”*a;]¢óÊÐsŒ°´ ˜¤ßRVº )í©.äg ÙìZ¬ø°)PWE›áIB†’Ã_ôNÞ&:¾QÞS`É/ïÌ{0Å´ !ʉ gŠí·Ïí»0Å"ð§˜`w¬[.ᘋӄ¶0°,N ö0]‡µ6Ø §ÉL¾‚ˆ~ïÁ|Þ*€<™Uõ£¶»Õ`æ½ÉÞ»THs½,-˜Ï¼7I¤žµîÌý2AdiÞEê1Êf3¦¸*Ì»-ovAbC3šÁ˜÷¯EtÁh÷)ƒ¿®.æ%O{%EØhªòVdaÆÔεiRI™(uu1ï<ÕH7†B–,7UWóÎSup°žÏ »¸4ï¢ ’û¶šÞ˜6Å ê3*Ÿ«©Ãš„ÄË-¯¥Ä°çkSqw°®혩¦'hÓMÞFFÓȤV_ û¿¾±6}™ÛÎóºæ6Øõ 0š$3š‘¨Ü;0âý Ö"É!Ô/Àh¢ÌhFŽ´ƒïXýþcò;ÖÿÏÉ#ÖÿûÇœôlý¿ŒžÁ£ÿÇïiîÿB z}ËRcý†²x·Ø{¢¨¢hj“Z}ý¢C8ËÕúydØRB}QwÉᮡ“îw¦c(²Š*ìï]‰Ù 9)Í""ÿ(æSl#>ó•!÷HÒb×î5?ë¤7  ýè=GÊV· fƒúX]£Ì“[“ˆ m |§ ÇA‡ðè897³©±Ùû ¨ÕŸmé¾fZRã†÷èîå ‚ ÖÎn¤]ÁˆYå åÞaÚÍ ˆ±¨é¾ì¤ìöuß{Q«Oªs‡èÜ'âïýõAºïˆsy ™‡¤øþ*O¥ÆŸìݳK`ý p6»Kàûd±ký¬ÂJÍi+¼KµÞØ=D Å=·û”bï¯Òw*Õ.c„Ú—z¾Sä ÊZ“î:ŒZ ?÷ý$Gíea<~An¨ÓyÊ”e9õT3o‡"t_loÁï°¬Wd)Ý—$õÞÍœ©6ø]¨õ†¶<"ÚèyÆÍœd±ßßÐPÒ½¸SDw©±Ï»ýüû7ŽèÍš&nDʆÔ?ôýý?1 <ë÷U>ãè­ê¾å¾·{£•”mÞwÐõ‘ÔÆ­7éîù$űÞ+ˆ 9sÙ«6å`½0x¤6ª =Y»ž’Ô?ô]PZÿ^‹s½£e,ŠHBxß7™Š‡ß'¥•óÙbÍ“h·q.ÏR¹/¸AÎÙÊÆt'|åG›ÚÃXy#ÄñÿveÉ‘³ÌvK®ÁU®Ç^€#¾ €$hB(zõ—!‘2«Ý}+üx,‚œÈ<Ƀñ]dÖ_¨Z“âØÕ“ñ¾H®PŽKn|RLrGf >m|iÕÆµî)„ËN.ŸôLf7ÓÕ-¯ûû¹-MÝ&Vï&lŒÂ^úBå¹–®=LýT©~Ýfúž¸îM5©,£áLpìJKŸÈCPù™•\vµú}¤£?pX'»•tJ»e-¶ïëŽâÑ¿ Û1×¹ŠVÈQ4ô›C<: ëbd´ËĺMJÓÑÑq¸$)¨Vù¹ž™Ws ;¾î49úí©¬(œ³&ˆ±),J¯·DþÜš&²véJÎýÊlÙHÂIÁŽDþib<æ¨êŒ×ƒ#§'¦HMzâ¼ê‚øz Œÿ”}v&Ù2ÝÏ ›0ð~ò=”²nûkÈxÐ10[WÞ1…Òâ;:k§1ð¯üóŽOdZŠLæy(û£•¨mßW‹¿þì9ê\v/ ÝøBÜcnzÓ¬s…éüãT¹uáë6œ×¬ªŽýû@œ©d˜]O?â•ÜÞ©œ)ãY·÷¥%È3°_ÖIu‹›÷R Èû22þ¯jðNž|pÈøÛ ËƒŽOL†—È"]EÊ[ä“§A6‘ws„»!HÔa²hçèÝË !-E¾0«d6m79hæ˜ñ=Ùë$ç!³Wlý 7u4äåÔ¥Ejò¾sFZ+éù9.NS6yÒaî«aS3q‚¼QdòOrs 9AWÔ¤¦ä{Ån4ž|÷+ižkóF;º¦ /Mßóä­JL‰oãž¹íd‡\Ÿ¨ï3´’H.w;Yùœñï£âE¯mzcÃ(WEßóUºžH¥™F½n3è¢É!niÃk22ú킨k“©%Û 0”1ódB”Ä/ëã2 ;çló ߘw¢RƒÜì;9²îô!_Ï7"t0ÊZvœ`b/´ˆ¯'q@ØqïU‰ ¦¹båà…²Ý’§Rp•³¬3­+MZ_(Ûí×7¢VW Ûט8ØcàI*S—–Î-kœ”d2„ý p|Ô"Aûd›põ_%ïJsìÊvóP:™ Lµ¬Œo ;¬Ž“'ù;—}y¢ò†ÙÆûRºðB<Éß¹œ H÷àšq%±$d~ýÆ¥d&8¹ªiÅ‹x’‘ó6FD¶Mw”*½Nžd‚l¤¡ïy/Mó1Rúâi›­?4ê5âŒáQ’]¬Ö¿`G›ƒ×ó°©Ìàh‘(‚fëä2›† Ÿ"]PmÕŸÈ|xÃzéSÅâ콚*ºÕ_ÉSe±F,Aa)²×? RԥƲᵕƒá¥öŒÌÏä˜÷U¯== ØŸ[/Gòë­”ºÎ·hAp;Z¶>âëÝ­É©PáÃWÃÒs¾×xêß³„VaÕí6 ¼!ªüB»j¤ÖõÚs‹¨æ:‡Á+­RÎL+~ž»¥MšÖlÐá£Nd2íêy݆®ëº_KŠ× ݫǨWâŠOQ¯Ä¿@“’ûÇYhbÚ¾J¦¢:5¼üÀqÿl‘F.,2êk ¼ýè1SmaûºôR³½ª üD”QÑ¥J 'ûFê®[Èd(íÉup.(ÒÙ‘w|þHÞñ §+eÝÌW&ïûš¼#qæ²r4aϯ«÷dèËÇ?dì³G6K¤å*t¶Õ<4288s?#ÉW„ ôdPéxka5[­è{ÞÿD?#? 1k*Ö ÞÀë§@£äãïHO‘O„LN§Š=ÔÌô³¤sÿú’ÎýEHa’zŽœ‰[W+Cf”eà¹Ñæï×çFËc‘®ÿÎ.IÔ¼‘ÛÚäZèÝrië¾+Cß/w*ÈIj¦2£bÓÜ`àÕÌ%:ÞÆ±m÷½>¶Ñ‘pßÉ`Î7»v¶A²1µàý(ß>BEëb~¼,9nšúÐ~’„y–ÃËYhì1Þ–uüw̓R~ÆÀëOC³8´Òeyž}Ç „BV5§ÉúN†SœŠ^Œ:&sZP.rhEY3÷íÞZ @|ò_öÇ›œ5Ùs³Í½òˆÂ‚Q^åüíŽ)¹-xCí!%ˆð@ÆÌ±ŽÇýÉq9žeêÀ¦~håDŸˆw´™bÒD&çõŒR²#JV@«æYU+gÀ£Àƒò ]¤¡;ívìKÂüýãEû0ו€ðª&à¬:psxv†ª2qYLÁÃ2ŠÑr ¼¡ò{¡2I޶CÝØ.(˜wx솞™1£gœ²%…aÀÀÏÓ‡9”ùE‚óÒí•ÆÀ³¬¨ ªgïzV¹Ý*òÄ'i~¹‰Ú=Fœ:åð"¸àÙžµ•vïšuÆ@tAPEc)Z³áϵGd·,x¶ÏS“ãÎâÜ2™0ô<‹QßQ¿-ÑŒ…å)ðþ÷åQiy üay:]ayv³b ]h=×·Þ,+o1,OVskf5÷MCžøÃò¨¼<ûè0ðÇå‰-Æþ8…wÊÌ'“$Ÿ›­³\¯Ðôâ~ù|«Ø®¡Ò¯8ëëQUÑ=”íÀ÷AîƒÓÇ·¦ È¢CGZ¡Mõd+ ¼ãÉäå C÷½|å0ðH@>¦d(弮 |·ö¢°RðµA-•κD܃¥K›æÁߟ–R¹À/Tû¹µžÕM¿& žUƒM©>õ¢Y1»š mäÿ‚àGLð—^¬G î‚îo³× Á ŒÑÙ œøü˜{xÄÜía÷>ÉO@hœ¥˜[mÝ÷x#uüpºVymå„è&\ˆH]ÉT7®³ÂÀ³F¨èÂøDgÔàÃÀ桹7±öhÃ@”DžŸ'SÓ76¸Á’¡¿ùhLjŒg†MÌ,x&‘GÕd˜¶2|bj% þjoÀôŒ ɇ-ÈR‚¼œ¶t1|²‘ƹC1<©9›ŽCþ8Ó~–¶"ÈBÂèÓÂöÖÕŒ‘¯s𳩠cúŽÖ[ËÙ6Š|ow—ª¸ä(ê– ˆÎf´r¾iËÛÎ(G›}¶k²ŠßúÍ„ÞEáœqŒÒÖ7gs;s+ø¸càÛÜú-Ư¹ ú„·ÃeͱR˜}Ø%–o9dèˆB2M~P ³®õXâ×—3F@¯ Ô2Û´A\?ÞN#$ý“·^ûn¬ ý~Eßüw¹gL·œƒ^›n­z <è7X]Èô¦©–Ã6UÅf¸¾5®E=ôRÓ(ú^`àÝ3æ*ˆ ”±ÊÆ?VC#ÍȰ$¸¯lÑž× Í_Ì ÈãžœüÊ…ªz2kÄ÷$FZF¦Íg?­ Ý_’Ð(ÞLŠÛˆhÕ·ãVÍv­V²à'Û¯!GV².Ø+dÚÄöWµ¥-ôÜÃØýy½¼ågäþ†Ñ·X2·C‡ä‚Ä…—±€5‚ŒõÁû‡šŠ‚|ËÏ€5ªwË|Qùù'²ãº‹ •‹Ú¹^Þó3dæ hƒ'¤¯-ìΉšCˬ#2È«ýùuæƒF³%Î~sSð`:£é{žlU¹F«Ä°†×lËÃ…ÎOêâLûV3´TEVézAÈRm»NV›Éw¿¢þâ¥l%æU:nŠØ¸^P~Æ`‰å /W&/Ôy'FI&܋Ȏ1G6<02ɯà³ýRUëZK6Õ† ó7úßï<#è 0†­¸"ëy}žþF]ç¼²¶3ËÀ|Ëé3¿~B.Á~ Hr‚¯ÐA1I|7¾ûÎÜÔ¨º)bæã¼`.,Ó6›Å/:¿äåŒ'9\ùJvÁUTt¡dO™0Gùº[­Õqu}»2y–ü·ûõFÝêø–9:n¼÷Ư%–}E ©Ð_+‡Sô^Õ|ÔTðz2<¦]œw¾®fµ ¶oÂÌ èjÜxyí¢yq:Øôs‰"]?I2_ÎÑ‹OœÕî«­Ý€ €×3˜PR¼©üÔ%À¦ÉDZœXE†FÉîEr †íaêàˆ˜lJé¡eÁµ½¶' |œ\Mq.ùËìfënÉÐÏrt¹!Œ«q”Í63 <îYY »]Ö4 ¾l)ƒ‰ž¿)dxeÁ?0ÝPTYæÃ[ו ÿ¿é­ûxßhàèÙ9œÅ 9Êøõ¼|ÊA”B‰¦jÖï»ÅÀiã–Ô»\zã Þ K «KÀpØw³³í掩òÌœ ¡—pÀ…Òø8ó½o ôøàЯëR&ó|K¨Á†ÐÆig}]‚Q×ç{ŠÀ™K ÕâyG€$¼¥€OQj«ç¹'À{¹+?Û{qí:ÖøY8 0¬6k| 飲¡v¤ð>8ìåx}½‹)ÚÞrëU¥ ;Öm _ƒÜàiªþ¼!gE÷.Œ f]¡Ò­˜Š€'åUÿp å'£4yâ­´²9I»UИ*ü_‰FßÔuJVE ­kÄš·òeÞ¹«¦2&n†å=7*ö¢£ÓäDŒÙȪrAn`àíOàmß7xÿ±-|%]¯ÇÀÏZν£C?pu´\׳軠lZ DTáh0ëÅm²^ÉÐ_(¯®.À!ø#­ßÈÐgjw©^ŽëØÈ°èpÿ74$§mÕȶµ|š¯÷Ä](Õ¬™ kP1¨Æàõ¬é”™{¼uAìõšõM…7ÜœØxõ¸ë…uK‡÷º¸©‹»Rä?ÉíQæH˜·&㔤µÛõ¼«ÄÒ)̸0Îx‰Üܾhå`2 ã&@Ç ³Ž¿00«®aÃÈ“H<ïœÊÈ»~ŒÅsš,ÏY9Ȫ£ƒ¼O3¬Ô¼ä1Èç6ÝA'#Rùì ò¤9ä);2 ^Ol÷M7‘5¿Üp!Ün˶kU- AÞß²§dDºM‹àUÓ÷<8ÜY]®†ª¹•» ïIX²ø 3cmùPÿ^OÌ«–ïâè²ë¶rÈ/ŒLÄÂjõ6ñÁnô=¯ŽU%ZW~pš3º×?Pgz¸)š ]ÖMMdk^ÏÔ±ZB1ÎÐl•Û„ÉwÏž7¤"Ã*uBˆe›¶†>óö'rä!©¿NÏ;‘‚D^Æ&Ÿµm¶­Óä»_QE 9jqJÖÝ2ÕI’($¬<ÛtðæK QeDÝNç‚x3Œ"¡2â»ì´çÙd‡k'‚ÌÉÕ¿£=[©œÊªÓlA¾&TFdÖï×\˜ªW½ìd•nï•|²Ÿè9Jžwé\¨²ûÂ7Æ{ÓÝK7‚LÇ8!;ß“8= B–ÁæVBŸ‘!@~þY)¤7“Û¸q:£G¡œb…·ÕR±NsŨ0~’úßÜ`‰Ù^ïRB›Ÿ‚~pï>WÈh¿ÐDÌ¿ÿÄí.âvߪCz‡4,2›J•­dª$ïèvHúh ôXcXËFWôº}0ÚÎl®í®W²J7ܱõó,rÕÆXG£ ;’ôÖhwÒÿf"È_Œö¶VJлÊÖ¶p3³¬½µ 6J&fæ ™w¬£Pç|É5ïßÕ”áEÑ5í,ò†i‚ü°‚¨ŠÎþ“½®È{¿ßÛó!¬ÜPjEïˆôïèÏÏOè»ö_‡`ªºi²“ÃÁz.ñÜ)vú½‡ƒõýp±»ãì<2DGF×wmÞlt=ŸŸKI—×)22Û Ó«±éÖ}…~‘䋦À}O‹g¶“ê¢s®xƒÞ VAG~9-²E;)9»vO çmóÀ~’|¡vî?j&t8ª™uÕqÈ5ÓX–Àq6Ikqór,0ð âþÖ€[Ïm­g Ì.@¯\c];N=žmrö-™¬ÆúpC_Ôàj'ˆïÅ'&êØòÓ:"Áb®¡Î“`¾—Ø;á’¦ÍÉúàz©ó:<¨ZÔP ¥È]ê¥~ÍRƒŽ; I½4¦ÕW¶µ6‚ìZ‚LÒç<²[xM‘¨DÙ3ƒM­×¡s”|Q» ÿä‹BåVqF1zÍ£^Z`ÞÇv]˜ÔGÖ*ùºÔKÓŽG²e“óÜ ‚|ᎰPs™eɤ¬tNÞÔK)dyEžú‡ããïÎ:Õq‚¼¤8ÒþòD·;é¤ }³UÎê†5 Ùt±^úÈ\"²çlÜ› Ó³Zzfâ5 V¶ôîŠl ËJQ‹zoÞM uHý7Ü”dÆzé~›³\;k ûËz¾N$¼ÍY²Î~ê}MQÁîrî+òDw4+¯YG‚@ÞŽúó¡S埈¯f&Ïì6Ðù‹;yâºdsˆÔÑ\sBíµ¢™žôؘ• SÚ|å3µ\,릔&oó~ôçeæíÿ\ìʲ¨ 2ÃHÙàf¾å‘¥‰È'EòxÍaârM¤Ž&BÌîÆ+×> ÿu CO•3#sÎyî4 ‰aqHÝ”3—Böä+NnïHÞÚƒæy*oyŽqO}¬ä¸¬vßÑÿ™\‘îÛœ¸\g3‘·™¤éã;Miì5rr»sàø¿v¼'69(ØTÒ¡›–u¥±Þ18üù¤Ž_`)^ø¶¦&{)y½#W¶°m+/Èô Mg@š»1ÞuªÉ;JO^}IžçvÏk½“UJoˆ¬ ñ(Xß: ²“Ó;æ küá‘Û?º¬‹Î”ˆLÞ‘|a˼×'Büc¢ HéâáÂ:“d'§àY-jž»n©ªÆÇôÙ£ª€ÂÃÌïæ3Ÿ‘ˆÇFî¶il:«u¦Hþ‘ ©Ðeßwyï/¢啺¶3c¿Âÿ¤“ã¤Çp˜ ð†yè!`Ïï+9—xÿ Pc`òNX¯PV+tÖ&ßf{ø€GkùÐÌÛŒwà2OLZ $@B~׋*·Ñor |"™ªf÷½­šzÔþvCתîCE€Ñ;Ѿkµcme÷;ù“ÑÛ°P¥Eš½×Gª-Áíoô|Í’uûÈ” H,ÇÏÔ6¨n©™ 2!H~ Ûzd™búøŸC·¯ƒô"ê›*°$[¤ËMMíᘣö·pdøÑ&WÜïk¼È.ú~¤õÈnÙ.Èd*Î,ÜÔ´L†ìõcrܱèÅ=ܶm¡¬á‚õ¼Q¦‹’Ç@Ð3ý³¾ùÐF ë/p$ƒu½”ÞqûNäüœt™ 1î ûyÙpãtR,–КœÅi*:¦ª­š{£¡”œ$ôaŠ(toªB=¡«"ùÄ—î uÍÐÉÑÆ QM²]Bµ³ìZfjw,dàqÍ\tôä;̲%)¥Ü)c}¤QÖVÖ²+VXžÇå?r4ëèåycª#A²z.s ²ór8f'ï|ŽÐµš­7 f’ÑÛqm@Ùn VÍ3ÐÍE !‚M9¦žÍÜÝ`àƒ0Ɔns ç®\4^Dð<…Ð8 ý°ñ~ÄÀç;'2›=p辀莅ʯ'(°ŸÂÊMÿ1#Œx,ª¾àÖÛ@Qb`H lŽ˜Ø³!y¿q2¦,÷–O"X?ÎáVQ¶¼XíÆ€š$#\.gû¸#+Áíã Vô ojh#ª\Ca1É.Ygø¸¬gf!”!ÿñä ñ³ižV±ÜÜÅ0àƒ·ljèÛ R[ ª´‡!6ÎnçZöÎß Àp’lþiʘ§”-Û­Ñ/[ò4á$Ù¼|64€:éÛréÇ–¬d”¶Gœž¥¥í! •-y^Æü`§9áÙºÕ:ÊoD YŠIg#´3Bšï¿vÛˆÌÏYßø—0\“çLð Zú>aµWÍÎÚÕo^¼ oí=Ñš£™ô'Xú}}˜äÈðŽ[­c †5¼â=Œ²¦È T<–#ìú©uTÈŠÀsœÆOÛðÞLMcz |œÔ¥Ñ {Ñ÷í^¾N¿É(:®¸à“¾øÚ¤cS\×iY0qþª°Þq¿5ÙÓà ÂÃË^œµfÚëf"Oóý}RÇW±ä·7Õ¸|6dÉ¿o¿ŒIL¥Ž,kIzaÓÅÓ†£é‡ôF_7@½ëìàxÿlûí ˜\Ü ƒ ­ÐxŽúV0 ]N‚[k% §“ÞÓû©©_“§ÎNæà«uäNËbÄÀ'%òõí}k£ÐUCcAz;MÕ?ÿ‰}6È£ÝYð¯w¤ HvA~ÿÖ§/FÈÒ¤7ôº=‹£¨ð¢‡EecàÊ$á…¶WqV¹.yòX £=õãd#UMéï=õ™Lo¨@E¢ z˜[ûæº ‚̈˜TÈßj4jµ4t•ž¸DÞeçŠYëRó™ q`é&Z»ÕôØð>òû/­‰vƒ°|2GÕ8Enâù.=[l5͵p’¥g£þ{Åüà!á’•L/Îï5;þü VsÙ óVPàQo+Ê"Êrh£¶šM šFSäOºÎ‡ bîÖœóª+‡Š)éáOzšð¢àuì€SƒÐBÝ¥iz¥ˆ‰áª=… 1Â:>ÞœãØBc¬¡îëFÔÒê€ýO¬C{uO7 GÒKãÅçm‹%º`éó ŒþÐúF˜´>LoŸ¬íÀ¯} ˜ìç?X4csD·ïwЬòŽ[£ -@ï‹@…ßm<çM@`ô8c²?aÆ' ÃZ»:Êeù)eZ‹T@‹=ùŽÐÉBg«Ï'èeìd+KrëŒÐiùw=³n›0¹õ6/;tèÕ¦•´QYO®ø:öëè~Yñq:8N4—™W<&gÕеˤFèLÜèpcå|q¡í¹7CïÞãvñj_ÌsûÑÚ Ý[o(ïtªˆÜé8ÉžIŽç q˘NÊÚ0k†Ïø5W³jÛpXÍ&çq[í:b`zNA‚Ö¸D&kêUcàÙi¯Â­™Q6²n00#LP²Ü aoßBvôq?ç*@±×±èFc·B.óq?úãÎ{nôdÁ¿pI68£ëq¯ö šsw|Bü ¯É“QÖSdÉã q–§\«æº¨¹g z_wtBDd ™´È©™˜…dBò(Á%0\-ŽÚ¶yBˆT‹üО´Ž›xõ#¹©–@s±+¾¶«„ŒÝã†fɰ˜›ÚªnèëžÜ:9úðÂçàÜ0l0æµxb¬†[«a“¹u¨ÅŽCÊòàiQF3ÉxÃf ̪‹àñaJÇqkW Ÿ„þ.ð3Ha­E k>=›èSV1IJª.Ûú4» îKr €Ï¿3$ç’gHæÓ†÷÷9Zå£_ÞB„þx8ê'`ÔoÚ ÄÊ®léüÐ+eµî9¤®³/:êç®èMнâhýS-ÈI7ôƒØ¯Kçm[ôˆG&ã(½Ü÷Jæ¬Êï' €;BZEÕvZˆ|„7“}]'œc¯£°1¿&ï0ûþeY…yä º²ááÍ« ƒäâéQïªà•g8ô󓉠YVŠí%?®x'r™ö +y$0KWwÅN®H‰e·ý¬U·IzÅäWptÇgÉß €Ù[ ²ô2X…æf/‹e›äÔ“Ùã2{îªÀôZ®|ÖEÅ0ðöéÖ6^rEC÷ƒJ¹Œ~—'äÚŒàÎP-ŽÈe:r<¹3 ƒ?YöF·–DZöõ:<x×ÕsµVÌn¶ “w =?ÚÊuM`úÎyçc¦aæÐ†™]¦^c? [‹Ž¸S²ËÔkÍcºc…›Û« ðù^òÍ»ñ|†<õëBŽ8'ë* Qx   ¯0ªØªrƒ¾Š,»p.a9çÓh¦ª½<Ú§2T‹£òŸy× kgä@VèûþŽäRÖk³åÐaŸ\dgÝ7tÃ+Ù—ýÜMA)’@Žô½bú4óF^ä7Köö´TÌJ‡ì CS”]Ï(üçbëB7,BïþdU@?õ¶[S4κ,»$¸}(²“ˆÎÆVp|fÏ_Þl‘B²ËüT â)]ÓÚ˜…í‡ÙGù*(Dz—×çõ%èÃ.ø ¡<4”]¹n@Y“½4bŠPGâ¬û™) L?²"ì…³-㿘gÁ1¦mÒ.ûˆÞ•ü÷?þ뉃§öÄÑe^3(Dfg¾êc¡@ƒí}~ý^(às­BÁóa è‚íݦ…lœ§~çŽÖ6B]0ðA´ä|êVu]ÉGfò3Bò?ºïFûa”á™Òx;˜)ŸÿoÚ]·¢†'â1:Ràa›¯_ç†<Ì7S‹ ™K³˜¹ÉÕ²ä7"i‡æsÖ‹´û‡¬$èÅÄI1@ª‰-ó@ï~G¸1¨Û7Ö¯ëV´Œ “_5ž‚Å'"ÿ Õ«èwîLJ“‘ÜNäƒöžìj¦bVkÄ:ä??¨…²eÙU« DÝŽpŠØ+ª¢P‚1 ¼£aKè0m·jØ s¤Cîóåþ»q†¥mÅÖ÷…‚B¤Cù€ÇtbŒór9vï©£áˆéÙÁߤÝ´ãvHÊ<Ÿ'wÐ)Ž6tà‚ñ½]0ðù+Ý’ÒäŠwÌ·{1õ¹”±'|"ÚÝ#¡XT`Éíg³—q~7ÅÚ\ÿø4ZlöëôPήIaà-(øÌSŲ@ló:ƾúis}Žâ‚§_÷¿Çº7ø—8€^ñ/q@4R)Òæúˆ ‹„& ü¸ƒÅø!Ð’ÄøüôLœo&!¯ð\aÚUðNíL¯"Îáìõ^—eõ?¾nIRUëö•ª2Ó¬®Ë}¿;bíG@ETˆõôS'V÷9Q·#,EæÏ˜cŠcóQ®ž„:F’‹îv | ÝÕÂ(¡eÓÜ’¢i]€O¶‰8&û¾£à76\É›5©ølënªuü¼ºÕç`žÛ¤ÛB—ê× ¾&‰–°õËH˜+Y@¶4©š4Êòë¦RM¹¬÷)¹È3g1ÎÝÜܲB@ä«òeÏô"OÜÜP$Òš¯Ÿî¹àψÜVÙ“ ø¸"¾Ô€„XFNür®Ñ×Í‘"ÑÕ‹DÚÖÇÇ({ Ĥ>–Si[œšC;a`ƒu° ÷>lbîõPߨø&p6s*9U÷øUQHÊÉÖ*ÓÊ€Ø2s„Š6qvŠÏ¨ú1ßÈ©HöÅÐ;Òª©ºGLù…‘ƒ­Nê)?;•®ÍºÓ‘–-¶B>.åy%ì~ëêxýߟ˜n‘ûƒa_ö69tò…%U‡S­¦µ/ŽÉ 2þËxÐáé½v=é{±`àÙ ì"r©®x:>e>²¬¾ÐhÄiĸÌ&W lÎîI¦-&fû²K¶ó ©ìŽIæ# i7Ê:‘¶/^ƒöÇg¿ 2XºÝ—ç×%V¼é _7j1ðûä¥e(-•¶U¨¹^ðk€œQcûž÷në+d¥Ô\蚆l&¦Ü~÷wˆ Z©Â“Ö·mH°Òæ­`zî¢ï0ƒS7FŽ=‘[çŽù”g¡ó]˜ÝPýk¤/ßçï_º"§Rs®0‘Ó`¦RÑ xˆq¬ÅÀ/T\)¶à«ëº%þë­ºÇ_'»?ièž/,‰öT÷ø}æ_}ûJf.AňiÇjÁ?.…óþdÒòÖp³¶ÕMÖöá@â­0;ÈD7Øž0ß}‘jf‹ ½—ú‡^B<ЊŠß}³P±‰ÝUÈוà@Ž*‚ôÜ …Þ|~TGIê¶••ÏÙ5ð2]Ó`#Ãÿ”9¥œeHf$­0øü«|8L>5ÈÈðOòáÄ–,£AF†à@ŸY@©†Àg^GI.Å&Ö÷*F.]·aàß{ÇÆ•†Õþè®+*àÿÃ]×Z |þ…9}eBÍÍ‹¬Í9A¾GÖ«$÷Y€˜€ô‘ã·Ê´f%“ÁÀ¦æW2Ýl]&i1ð‰4 ¡ µ‚H7¬ú×/$š^ú,Bš9þg§²ïòþµù[R.&¥4×`û®?)¡÷îñ ÌO³×Ò´ÒŽ{i¹'øÀ_Ó PÞn á|Ö7#«–q¡ML„83ldUäo2]ÊxñiÕ½ÅÀs+äÅ´ lw1†x3Ñä¡g“X´¨€ |UŽuÌ̹Äî,ÌßÕÀL®\vje|ß `ù¬;½Õk&‚™‚Þ1É…ñöñRLnÙ†`à5¦}~)”&º òzÖ·YS$@âw¾cÕѬi I?&æ7Š÷–aà)ÂÙžSÒ銫´7xUÿ:ˆvÐþª€Gb~­…¸üÆtÞ k„ÆãhXðº¦üÓX( |üÝXh«€OÌ só„Ï£YÜXÏ=^ÀXè°© ˆøÒ])Íqg¹q;-=–›ý1=†=ƒ=þP> ¼T.›Ççÿ§|eäi”ž5.šN ,ØêŠÏ눃½pýmr„óõñ¸…ph@KU!… &f°LG1‘Þã;1 ¼ô$oŽ"e±è¡¢P¾°<þP€“W«œ•ÄÀ¦fë§%ú¤1Œ—Ì9ƒ—þõª—®¨áàפ…®s˜ªA×˃2ÎsF‰nâÃÖbà÷µ]a.I„Ièqnëå)zÛÇÜ5x0ÆteUm pʦAN,˜“ ¸ðSã"ÈæcxèT+G |Þ€GwðÚsÅŸµÁÊ‘åoʃê lj`¾bîj¬€çðIÛ E¹-nÂøUKzÁˆI!Gx7m«X»[Û{ üu³#ÍyÍ$ÙLvŠß5p<;Q{µàUù9; IkX<Kó¸ 5dÃl!ú]ñ yå’…±3Þ`µ±b£ùé¤VU§>:£©œ€JÐ`?ß ^z|Ÿ»¸µ³ 6UŸ£ IüCÒsé{ |ÔZB‰Ý*—FØ‹Yxs¹ßœŠ‹¥å§‚ëVe;Ž/phÓc.ùÏ|LòÕb`ƒdwJÉÄm’ÇÄf\$ž¤•”Sñ£38:Åïø4,øUÓ¯YÝ0uƒY– xI*PAi5Ù6TW-Ï7)òUšÉ7ŽmµàÈŽ¹üïÑîñ&g[ÿï«dÒÓ"9Êø!mݺù¨Ì4Ïd2Ó$ÓB¡äóB‚¿¢âƒc„µ¾OdÝcoW¯nÿ›A—WÃŒñÅ“ƒt]…|ŸÕAÊÇüºm›µ4¶Kõ}~¡†'ySë»v*E­ÇF3ÇœOZ6ëv0Ñ Z_‚¥¸q¹Þ6×/x1D; UzÝÒé¢8Ô<Þ•0r”Èò„¶å›—s”ÿ_P!/Õ§•+ÃÏÝøFÑi:ä-‹\^ ³”g/9ÿüdפ¸öø€i–öœfq‹N }n2ùÓØ:GЫu¶…82Ëùï9 v˜ 9Ÿøsb_0ðqI¦ g@7ÛÄ£€–Õãûæ¾A?ÂdÓ±±^Æü¯¼½È~'Ýã1\‘ÙL““Þ8á*`Å&`E;ÉÛ…Åï¹ÁÀ'®(/Åj9³T"‘Z€¯¿Á¡”öü@l‚Р\ Dh›ü=bóú\2õ&7:&b,žóí)aKE'ø:¯¯y€áPjÈL<Ù™qñ¿Oï–*'“NL¥ev¼r®Ïa~üïJ¨p4Ÿ—{ûPÞñel[OB!Ýó£®ïÝ–\¨ZøŸ¶-Ó¨€< ªäOLõ§‰«0Â}~Ö¶#”>y³ét•°ÝR¶ß…w’ñÔC1P>?«æqÖ¿ÊZVºyïÛꊯ‹=ÂËMÆíë e‘ÝÒ€ñ.CuÅ÷-¿9øäfžèBm°/Óïbê“ÅLLÍÞ-× ;³ã>&v)ÚN òeÊóPC‘tHW\bæ«+"É&VÔx娭µbtðcž·Ôª29Þ‰0øøÀUÀÀG<^´ècz¾` ÊêŽséðyçT-†÷_° É¿ó~..–Ø u;–UÑLܰ^ ý¥çó&ÙTâ.§ÀÕ>Nkõ¯¿ }„¼GDUïß+è­#ï¨Ómä(¯“ŒùûN ò|ýO¸xÌê€Wµæÿ¿j|1È…­ÛùdšW<ÙäÜz=Â+ìßûÇvU³Ä@Äõ eÁcâ ¶iš\ñë~f—FÔêâ&ìÕV1{„—¦‘›Hïâ¡­1ðùGàbÜBj`UŸç0wâj`óG RŽO57YÊ¿÷’ļnY6 Dþ¼`=ØûøX„ž&Ž¿*=™€t*Ä‹NÕò|ã<(ï¥ £Tz§°ÓOd˜¤ßªÿõ¦³”ͤ!³´F>nÚÐ9j%=äžODe?æƒ{ð¹ì½Úש‘—~$ÕãeµDzf¾B6AÍö¹B¾kd–šL×ì,*ä× ™> Ùk1××ÄÓ êönÚŒƒêàó«öçÍÞ¯9”żò®\ÈBÜI"#ñœÎ×»â!YvpŽ×$l21Z«—ÞñÅÊ]ʸòJ/óX!ñp-^Oª‡b¥È+ì=TåöŽvu(òêuw «ô,ÆAÃì ßר,T­cß*rÑ òÒ2î`:rul[·m[AþúKiM•žÊ´,£ èIDZí‡óÿ¾Ñ^A–ÉØ˜>ÄÙ%žä¡–‚µ¡æUWí±ò#\WÓ¶ýl1ðq+p—ù6¯»PÄCš×ó.Ë;dŠˆ”ÒŠ­Û:‰WG!.à¨,ÒÉ …Bÿ\J¥I€O¯‹é–Ù`à Ë‘€>­0BNtª®xy¯uå·ð)öÛ"t(¹Æ«ÍÎAj )çNöò¡W=š}px³g“ìeˆ³#>«fFfûº¸³gÒ¾.gç›T =¤[Ø\¯WÅÖj³§ô!Ò5·l]‘ø¾ RÅ'™N~¿øõ³þŸÜ1qý«©sàGÜ{­ÛYÀ¼eƒ%M :¿á!Xow6C#KšvHžÿM.£mè& Ä^–EN¡÷Æ:w ISpžÌÚz!ˆ°O …çõ®åN#¥ý4‡Vêßu³7‹ÍÆóÃ): ÄT…¢õ#EM}àE§y]m¦?M{Ï××M´7“óyÒ!Šs²Á:Þz=suuC h…,žëô†s¨@)²­ƒÜ1ð‰‡ÿ2_iY†míljvˆj0µºRÅh»Ïâ¼~¡ŠùÐg|)¸´°<ߨ|Ékõ`N¾>ª×Œç×,Æå¼íÇò«±¼&L¿ä‹£ï¯ÍÇ]×iJ‚¬÷ §Pl¯ \–‚J’àAk`R4·rÚ%®4¸xÌ8g0°ÁÊØ`ömHƒo(U5.@aÒZÇ}ï4ÅÀ/¬±1–ÃggZÙ üU•ÆœÄscö–¶Õ¯þÆÙþP:…aÕ“„¡XðJ5³tf„7¹u~©ŸPF“ø=+ Y€,r¼™ß˜ 1»5ûd)"-Ms/œ€È¸Ûí4Ä€nœ0°zJ ~·š*>Ãg‹¤þçdØõ¯}b1CVªÏ…úX܉ž¨ê_#¿VˆL=±“Ûn1øþiì*¼b‚x…[$’š»Š%NICî.ž†¼d5—Hê9$S4Ø·‰­Ëâëuü¾$·ŽfFúD*"b2Oé^-øÒƒ,9Æï¹ d8 ’Šÿ÷7vÉó~ ¿UKþù¨´\‡c×nîŠ@ƒ¶ùDL©ÒéæÅ<ÊéÕV!_™÷ŽX„†4X!ÔR(J2=SÚ2Z!ß'ùþPÏÝܘ±ÅP ‚Øæ.ÁžK`#ÁÍb oÞÜÄ\Û<£˜¸ÄÈÄx†¯yóS¶(çÔ1WmÛqÕ0qsÍÃãµtÆÆÅ„X‹¹–}[H²8-†š ß8æx.ùäv¾VÀ/¤d ¥cÉœ#FwÕ¯În‡ÿfòE&¶‹Žx¡¼tuœsWê >s"ªÂ/E7­œNl 1àÕ¥­Ù<ðùsµL’IÓ]Ž@/hž·â˜ËL©Òr·ô«æ&딌²qÑñO’óÑÔ¬ªî´’„z©$ª] ÿåw– áüëóúäçï~ òM̤Vzd`I¨õ3yRŸ ñx¾¹M5“ÕžßÉCNJÙÒÅp#À‘2…Û íQ<¤\z†ùú1ïjš¹;y–ÈÜ€¯¿ ¹sÀrÁŽbTnMIß+ÙÓC Ôpˆ¹J[Íݺ–d‰‡™MÛhƒOü¬iÙ¯†i:]ûõë§5I^LJx­Ä€ Ô"rà—ë̈Á{RÝãÙA“Ý“6¬©îñëOìÀh=÷Й@0ðLÿ’#ú:¾{ébœœ¨1ôYlÀMlI¿=­üã/†s i~ó#0.z%KT1lX=šòkâ£é㣬 Íþ†ÏÔÑ•1bÚçµ… š½E~Þ²X)1/A?ʤ¹:´âóV¼ŒËD  úZñ_usí´Û bšvåÔd1‹m±B¶Cü<ëUW,͵þ.gñ6=IB? iͯ» H:Åœ“¸-ô@Çb«0E]âïãï¡ï€ÄVËÍÁ´‰÷n¯ï{²=²2•Eöª¶í0ðU«Ïe£‘u¡ûfô€ ŽŒ2½¯R$¶Z² ^`&ß ÝñêŠ_øÜ<ža æva4À‡Idþ7k~Òâ#älää—?Y>‰ýÍ6ïŠmAƒ%2÷b™~¼>..$íæª+¾Î“˜‚ÅVš H±€m°Df b!ÚõITÊå¿?o:ö° y ¤VÊZàAc‰Ì¼»Ê;—¬ŸXð&3^}|iîç•bà ËŠçu\…ž™ÙÍÖa ’q(˜ÑMÎùÅEt¹A™ðІ9€V·Õ9Év³:[ÙI.L1È.‰ÌÛ‚Çï“1Ã&à G™ÿÕß!WúF½ˆI¯ëJöjÁ?Àê¨=ei’Œd‡þúûé=ÿ.&0¹šÞM-KݺjŠÞsê°Ç}˜Ÿ£§Ýê}\Ήe‡¬GƈI¥ÀöÇRžK»nb›SÐÄÅRž¿s9;7šâåì¶u”B°”ç]F>2òåÛ÷¾Ç|eŒ(•æâé¼/™ÈûÞÎUhî’§§P¸¸¤Ðâv5’óm·x©\ <««\óÀ€M†gsp޹‡mœ&ë0°ù9*œ,×I¢|Àò45!9•kŽ··—ã´›ÅÀ&©æÙ6¥Û©ßGÓk |‚mÛÁ\Ro6¾KÞÂñþ¾xï‡&Îq‹Ã1΃Mæ9wØœŠøkßêyó¾ÈÞ5ï[1—啱[éÎ}s£I³"«é•ÞZ“«ï÷Ã;$Žóá½Ý·JÛA |]2)]q1N“x¸Ç †G½ößßg“2éÍkNf2†`àû”a¬ôç}Ïu¼ÂÍl¿Ø•ÚJòØÈà€G‹ }à§™æ ‡GxEIðcr9;U€[±,0èt‰&fWÁÒ]@f—®;[bàñ†ÿ“¥î)ȊȘ‚ˆ(Hï+Jª5šÒ‹Kð@M©+æ×ì ²ôšÍ‹îR(À®ÙŒ‰(kb\ñ„]É’ä¶ü¥®½ê8wOÄó'¢DФö1_ÿ¸Aª«Çaû–Vµ(.˜È$À h—å. ¯\9UmÅK ¼þØÅ 27,ìø1O‚—yœ>z…\n“U; P¹|œ¿'¦‰Å?U}­·©0ðŒõ^€ÄÏ”sõ>{çã­£´+ôŠ´}ïtÙ4œcàõPlUYWÌþŒso>ÎÇÄïèpžƒô"ù2t–ëãLÔ>ÙN¢õ/¬[=š†aàãgƒ%¸?x\~2œ°Š ­ `©cÆP™ÌZVé° cºÿÏA÷™aݺ²)1éHÉìT¿´-ËUì_æJS´]2šWÆHÑŒjÆÀO†>t«žÖÑzb%{Ñ@Øõ8nvþ÷ç2äöOTbmm–ìÉÀ'b5fbªà“þ@Ôä­_èˆËUí&)ÇÖŸìdÀ¿±Ø*ߊf³¢.‚óöÖ›½ý~9(#È :ƒ!ÉÚ賑nÜÀQĆÎIâfÂHYUo~zb•ÃT¤粓72N/LZLs©ÅúhÎv’Ìõ¯©ò¯ÍdYmІÌóA„Œu´(²vb]Ú¡žòHG¿(gß;mÞù‘Žiö:ÊGo˜aÝd–·ë˜&¦üQSŸç®ï­õk /¸&ª`Êø€ŠsˆD2°„¼e°ƒ}Ä]/ˆHúUÖ¼šJ¿«ŠjnÄ㤟¨ÂO[m ‚ JÒŠñ‹7 븜ªŠ¼ þÞ¹Ò¨T7wvÚ¾¥=+ß-½+»¹MBðýs‡ó.½¶íV?Šó&[‚ÄÊ\ Ô¨åÊšMÀ½ìã¨. [—O~Ób›…| KÇþNj«©‹Jl~ã(šýšðq¯¯äâEèã^Éʯ{Fçyë¥,Ê–<ñ†ý’û`è­ÅÜUx?vAà²qÉ™P-+F |ìæ["]¬Ézå®rJ²l=žO\HOôQ÷w½àk÷=ÜûŸ­£áx‹ûûU Ї—añ‡í\B¡êqÇú|¿U½]ç*?3‚<ïÔ• %¤_­.¡ æqÇMéYã:ž=+ë:ús(Ò?îèªILËGa­S]ä!6/@‘Ñg-eð¦íé»Çø;ÙXº²‚¨2#³cJhÆÝ»ŸÙ`4«ÀU©:î'ªÌUª{1¸^Ï`¤H" ’þPÿ½ËƧ´ÐŽ›çúAÆ5éß½Ôå¢ù;Ï»úCT—J¾LÓ:ÖfsŒÒã/©N=øTgÂÀó!œ‚eT ÉFà!¡äo‚L+ø^ý?„’×hæ]PžG%Ú¹·äoüê„ áR ï?f« p{CJ¸²ÕY(ÈúÏ¿d«ÍZ;a0ð‡lµ0ÁYÎVÞ~̲f`s µÞä>½«M£Òu1Ž=¢: Ͳ*§ÉI–•në] Êÿ{4öú{–UC½)á~ϲüOÏ@b{~P„,KQ<ŸË˜[†·æ£¬Šq¨ÈO_ÿBàé¿ÈàÿF‡'žÿ‹ ®1ðL|ÛA¹ =™6Rëý˜Ì÷û8‰IöTØ“y=L«ß: <Ú ÐPõ œ1ÈŸï,-™Šþpjš¦e DOª_Äœ˜­¶Ó³ÀñÃ’¹/­êJû„¬sJ‘ŸÞ¯™Y”OLê{ÝÄ8ãpvcÉÜ”* ¸úèoX ðŽ)èÖc·°¡Z%>P·{ O• ä²ný‰ƒOØRØþ ÛÂ?Ì0p@¸!Éܬ‹‘~ð[éFükDxìû®‚£KÏÜVÙž ä‰(í§¸ª_¤Ï¾•Ö6’ÌÝù©‰Ü/]/ »jògžv·ï(^C‡Z:SØb"È+îËÈlèðLësƒ• o¤ƒ#%úÂö=o£¿~&’åOP™[]»Žœuù@‚”Y®OWRÔó¢z:Ÿ,uµød#´›äëpAÍ [Å´ô \žç¹þõ9g¤&_ó¼ÓÏÂlO\º]ÿ¯ÕäkžÏ?FåRŠSûÐÚ=“QJ<ôí÷oøFqÒ±^3@õy=Qf˜EÄe²™n—ÎØ…' ™lž Š·iªœry†¹MùÚ¶imÐçYWg²”vðVÉ6¨Õ ‚¼"dXÍÙ¨¦ñ‰A¦sø>*_¿—Á„£%ƒtºÞ ƒøÛF§åãófX-~7&³ˆZWgÎ`]Ýt3pžGf+˜ieit·•ÍbÈÈçÌðÞ¸Ú¶>1mÏó‰hæGdˆÝGÛ³Š¼ÑùL¶MÈÞÙ:ë~%sî|!žñöÈUøžY‚¼î¬€ ï·«=Mô×oŸ·Ím-wQ ŒLÙû¿[vÙˆ }Y¿ÜjMfÝ™Å/×o†åæCèž¾ÑN`a±M%nq“, [ ‘dä +x¤\ié}p¸(Û‘M!C¿c§JKÂ~œX[¨¡6 ÝNt+† ¶óá]qéú¾ûÀ˜92JéJ[qhÛˆ+ŽÙÆ^od”.?vOm H‹ÈØàS¿Á8î;ìó#}o÷oÝ/ºž¯o&t*^Ki3š©÷.d¬ÜÿÉ¿Õíaìëïþ­ÚàÏþ­z?€^Ä=ë±EkB×ÌSSÂ-Éë‹$LGC¾²ibS½bàÕ`²fÜX¸Òw Í<È4€´¦ÑL—-ô–¼¾¾ 솼Añ¤±ï›=Æ3ð†/°S ÆnÚÒìÇÅë‹òrÙ¤‚!óÈþ½¾(]\ÀEà¶­Ûdí®·ú:ºvæ`ÖùØjÖÍ¥#/ƒy¹ tíØÄŠuƒjÄë‹zzÙ¯¬+lü4—ó0Gæ“*œ¨ÌN1†ñn6³%ï}B °¯k'ô\;‚¼`dªkWùÍZúæ'$ƒ=Ú­µœ}°C‘·OH×ÉIº·_O'ÕÞ!É¢vdzcE>P®aþÉ´öhå§ZWÛ…'#ŸÇÞ–²JŸÎvƒÃ<è… _?îÃãIí,¢À¯ÊBE£u ÄÒ׬ö’²Ú_aµKÌj½³ÚC“ëõ‚—}ï,¢Õ#âø¨ UÓo>û¥ø×¬ö’²Ú_?²ÚKÊj‰¶pö|NüåÍ'C[E€¨§Zæ¸(\>pã”ì0ðõ‘'Ï1Oþu~Ó. ñ’¼öét¬q‘#f?@­_C-”x3QÁ!Ik™«¥]]vä…è%5 3N>ÊÜ&úÌ+)Œ¦x4<Óÿ¹P/ÏHäX\eÿAœjY¹Ñ$m~ŠûAËæÚǃNq‚|üì-ÔMdaòÙ[‚7daòÑ[bÈ/ßÉÁÝj ò÷°¯ßT_¡c° ‹w«Ɉ\÷Ÿ|è-;¯ë{Ÿd¾û[zg%q%îVXõµîçb*öE†X É\&‹¢ôMåã»zé5*A eVÂ9šƒ¶×í£ÎÍŠ£Ô¥ÖPdÀ6+{[sjÇucÕÿ*Pf͘´£'͘I ÒëF”S:“fŸÏÈbÛ÷ £@™]°ªTŒ^–Et¬kòÓ÷]Y0v5æV×6ÙÃ:²‚ ûc¥ã±×Á'La`šfÿÄ6ÒLüuª2MU pm·û±ì e2}k;7«Ý® ðL:GRª©d³¬-(L½ÞÌs¡¥.Š~e¢ÀÀ3æ¶§¶æaþTn ª¼žßúŸw’¥¦BAÆñz¢K¦ß‘Ú‘õ,Vðº÷¸åùÖÿœïj'Ù&V¦$yâîîÅq‚ulmæÙ/ |KþøÓáÖJÕ›i8>߀¡#­ ÷oEŸí¼2ð…Ôð²y®ZÚ®Ãl£×“öI–"S0ê±jtÑ[H‚DRT*«WÓ ŠYº’ü8–¢R2\¯Í &nÉûVEtwK;JŠ… ¯ß‘ÂmŸ7ì¿‘TŒ_µ~†¶dî?JYì¹² ŠÝB€Åp3±ÅŸÐsÊ6î__ô’4jÀÇö£itáv&®ï_TßœÐ.Åg)›ìþsÇ6A¿’SbfÇ'úGÎ+^ ¾N\¦‘¬*|"μ̭=ƒ©ƒ¡³?0ðØOý‚Hÿ9™âu©J |à¦å$(QmõÔúü®àøÄ”µT¢éfÿY #oýz㶅˵Î庚’üpõ^1‘Ãbe×W€D¡‘5æE©zÎM™­2‰îr³ŒnÝKŸlHSÓsBÊ^"úf)˜ÔkûöëWÌáV™2W9¾rVyÛ·ßdµ´™i­é }fºúðA¸ÙLï.•lÓ:k¶ò™ºgº¡ì—ª(³) Ÿc¯Ì»u½1›ÊŒ=@¾²ŠJ•µ`êºlM¦OÁ\ÿ­üé⥗l‘Ckrã= OÊ#GezŠD6yÛòSiè×µ$Óý|ÁÝÆ©TàÇÓ§2ºÉ–|€¼îWÊE܆CoåʆR²%£t¾n@ %¥G­X#Ö·7ºï”§ýŒ¬6Y³^°Š>óAõ ã7’m×.vka¥c‰™ðÙ…ÈS~·Sei+ ÜMô¢ëxÀAÛ7༭0ˬz`S-[îÍÀ+l„±>Îb¹ðž)a+‰‰AÿçRÁ/£šb#ÞQI#Ÿ}q#ä|2䉲µª}#ì,›K |”\p†ñÏžx9èš_8*IåjŽËv-r—> ø×÷}«š«¸o Až¾#}¼Y‘!ϛ̿[zŸ8…ãûôMgÉŸyº »Ð¬àb=¯Ý XGW¼$ÝKÊ^ð‚ëv#ÈÛw¤Ï†¯ý_C‘÷K’û%éÐâ=ÑûÕ÷ÅëŠ|¾/^¿(üâýâÝ ÝdŽeîdz_6ÓdfÆMf‹A=om¾Èž ¼\ÈŒKTÒ_>v;ùróG9~¶Óõƒ™\²e¬Û¤šÕ¬ ò‚ÃA ²uÜç…=,óó Ä®x¸ç}'[ <ÿlGä4^>Ú…Ùíˆ2ðúÝe¨5ƒÒªnòÕPÞ>º ©eÁe(ïG-ñŽB1ÇhUXcV |üX“¾û›‘`R€Ke ÆÖ‘W €×k±jÆ ‡˜¶RPÊqä¬ O¼¼)gÔY릒3gx%écÜ.çiX”Ö}¥0ð†“šKdÔµ}Þw$ÇnZ—…Ù|NÚb ’h‡·¶í(„kÛž<ñ‰->RÐKÍŠ~ÜÇ+"™ìžÃWݘQÚy43ð¯)“Èuh6Qä‰0°Ó!ߘ•ýyþ€l+l·¥#È7½›°j;ÿuê¾lÆ• ¯D¾+I:±vlÖÅ™‘ oÄ9n.Ú¹Ú§3Eßäý{{Â<ð|ª=Ñiyl‚lÖä¸IQûì¹&È'¢Ÿg*ŽvŒ÷¢gRä ·§´Ø?“rFòÕ’IzføF]Éêrëͺä‰ô g_HmGS¸‘|Íóù@Fj‘h7võ¸õ½åy9z3ª|1—ÌÚÒ§5äÝ!ÒJÂ.1­©å ¥بÉÈŸo„â‘]h‡ØâÈ(e’ H'%#ÐaãÃ81ý#ã­³z¥{ÇóˆóT6‚XúÐÓÈXMfr¼Ý‹âR±w&çn=X›+R¨X#a=)Œ×NŒ]3›¾7xÆÀ\gð@k•ÛÓ7Cù”"ÆÇ¢Ü2IÁ1ð(¹•%(í*®¦»šü7œ*¥HMjš{5” Þq}¼i—F ½>PÑ®…¦E+=Œ¼õ;eÈq…V^9òÓ/´Ð@`š&Ó—®-È€£E’àAï¾ cAžˆ•ÌZY²é‹¢%?ž6®ÃÎ>!9¯¸¬tI—7íØF¯¬ÄÄî_o|úÝA-«nšrßÛïDŽ€ç3:ð´þ¿upx9Ôgvv‰žL(8–°·?¨BRNÖa¡‡Ï½q§EC¨Æ¸ýÐEÎÂE¶ 0ÍÞÕV¡¦íw€Iö£Éíé÷Óq> ¡4BmH$‰rÁmšm½­|™Óé[Ã{VŸ™æQŒÛ2ŽxFWà ›4Í3ÌeÑ”;²·{­œ¢h¥Ìü‡;²·ûå#Т„R_"ü»ÁÀßHP–jÕ‰X°éµbYFÿŽíí@º-ד†ÉÉIÎ ù ÃI¿ø§pài ¼ŽW2[2c¯—q. ¼aS‰´ŸµÆ'•׺;²·û_xëLºW¹…À1³aàãCdHätXÿ|Êëõbá‰Wr+Ëv©˜8Žó4-Ï߇‡ó·áÁPÒ«t?éŸh+Í„20ÓR’Äd¦À9éÁ.“#xä†äêL`ÝûÙ8u¬ÆÀ;à<ŒÚŸ]¹™'¨ÁXä·üß6†Ot»/c’+mP½ÏÀÛ›Šr•…‡ç²]l·wªÜ±M`J ò¦m‹Þ-[k4âp!œ½MmË4÷o6"½è7pÅ:¼aeò. šž7~0x0ìâŸ>wšÖÜÛœdí.͆õš»¦m10Qäb¶Èš2¡Ùȧ&ëo}'æµpMægšíC¯íÿ »¶IqeûKUy¯Çý>#õùƒÁ°Á€±µ¿þì #2³zÏŒZi5`§/q] žHûœêÚN ·HyѼaÁ¼tö”j²-àžL÷qTÒi <¦}846’W_žÝû@Ǔůé¯Ð$SÚE¶&™&ÁÖZÑ'–Z\i’3ÆÃ0°tìõ‘ æŽËK‡…cl Hà Ô$Š<=†¥³4ZFžøƒI"ò¾N¿LàÉt ™ð/Â_X´ã¬³Ê{pذ `aÓE΢KKsÃ@Âê Zé—é†X5øÌ®Ô¢DfV×óØÙc=¨z,úÆj­¬Z†€WL _Zê0 VUÇoø ê±…Äg+9ðÖVéG\É«ïÏÂl f×q¬ÕÚùZ`à…gÄ6¡YÌ :7,£ˆ’ÐÛ6 î¬,rÓ7$£ø®‡$ƒt°»No…i¢)BÅC¥ïáÑ[|?Îà‘Þ">Îvµ†ý8³x~ ¶å'Ô[}²ìGA€H=HfmÇuÏ×ÉàIVçž¶½Di ¬«Á5>}¿ë4¥ü§gj´!öEs솤ÿü¡¥=©R³¦ïVz?nHê1wèA§yï™nú ÂÀ36 Ki0³"ÙQâÌHê±xïðjÆ$Ÿ’ÕÞc`5ȵì ҧ穹éŠÉ I=fÕCÝ»ÕËë©"À;%°#«YíV5YC€'À5®N»Õ9×í„K”þ=(“;n:?¦ëB&HÀñ…˸vŒok½ÃÀ.n/µ3kÓÙg …K´FfÆ$W³–s+,y"¢Ó…Ö{4F(»Lpî!Gà­.ÍPfC×=Þ^®Óëûàz°²”-߀ãS )[Ã:ý%ß1òçÙ ²[n‹e®s N×SÀñ¨ÌyØ­ytqàˆù–£*9»ÕÐè8{‚Ä~®ÊÄébˆ±]M_yy§æ*V×b£™˜1ð„bƒÅZØ•†’›k4jõgí:Ï’R¯/Ïf.¸¨]XõV ¼âeQèX#›‡Ö óŒ(’3ä"½z4z¬FÓcà’#çQ§¿âz^ÀéòÚÚ¯²\§Ž:4‚ãCþ#`,lÞuºi@Å&ü õÔ–^%­›µëþtygQÎ1'ï~=‰ìJ¦çÇCsÞcÛ’j‰¼^È„‘3k_êi~l³çdØßßO$¸a.Æœn(Ìù~gž‡ s~>fN—_áA^9Fã™ÍïÛÇAì};Þ¼@*Öð ñæ½þ¾ymÚ¼ºƒª¦ÓmÞ áØ°^²ªF²Ö¿è–ÜËh÷-™{O˜ï¨äg>#¯º–l´¿m^Mf ’Ô˜ß+ýš,Ùò•„µ„œå”…â¥óéfÅÀCÿºGŸÜj |pSžFÛÍPCÖ÷ü ?àzq•ëÅ™ºÒ”çb×αÞò¸ô ÏïÀ>ý8"zyL%¥¦l›%öíèÌ8M35å¿vÚÇŠ½h¼ª‹¬kæ>˜d‡dÉÇ}‘×Ì­¦Ž Ì‹ÉÐn»rŽžˆ`Šª»‘³­"mÂÀŸß€}ç ðIM¹ŸÎ¹¥õ‹ªUºŽ òûrk­ oÈÓ;é™R#«¦:SoH zk#È¢í3DZK5´&œoëfŸ[à%¾!-èOÝìQK<ýÖÍ5˜ H :«ç5¼pSƒ_Ó@¾é¾nfôžUÍG ¼½û@[¬a˜yÍ ðþÐÔ†¨Ø\䊻4j£\=Ù00§ÛÓ¨Mòµ_€¨?¦.Íéñbà¶‚èò½ H“ôG¤<ø²Tç V¨#Mt¹½i½¨ý«<ïýÚÌJä…Vªmïç*Æf6ò½Øé2qÚ6› “³u†>ó†‰2Uušw¯ÇYB=ÝE/ž Ô{ khFQëj ò¸#vê¥}šÒ|-uús¡oÿAì<—clå“!-¤Bký¸$¶~û¶h'·ã"êv$ßyúFäGP@…Ö 3ž|çéô R1ÿ‚>él…I07‚Í‚$žá¸TZ%/ШfZ ÌÞ?H¿¡w~·PMxýz¥¡2¹~ëw¾.t·ë×KÌü8ø¨¹5nÑÐl¡­¼0,W!jK‘¢3¸ïŸ|¬ôƒûEäeK”§—\VÒ¨x¸¢ÖoJÊØ;æ­gÛë×[W&—Åybzòiö)òA׳®·OÐq=NÔ+nýþSÜê,_áƒmÆy,°Ö¿Žèñ!˜â£1Æê”®¨õf2Sicfž@i,,®hãGÕÈ~a…nø†ÅµÿûBY6Ú°Z¸E‘¸6(à–øñ\ùªâé"Ã@\L¥DÑ€KËÃsÏ |†Âh'Æ-9ÈûÕ§¸öšü’ÿ«Š{¹¥ù&㇠ï/¬Û«¹î¥äÈ«.I¾¾©b/«¨^Ô ÷ÚÇ¿ñƒ[Xg‰H» Äd¬×6®±W=ž‰lΘÖÚ‰ÚÍjÂÀ£©>JñÜYXgÕ ¼âî\ð•¾Ñ UœŽås¢ŠDÔƒ«ƒk]¨YoX ú¿¥ƒ2ÛKŒíÞ–¨‰—h樢˜ÖIMä‰?/%@ÛµX»Nv³f–Lø*F)Ñ(¾Ni~–VÓŸæ› ¥ìžIßÔ¡3´o^1oÖ§‚Êž…é=ÀçAV6§åù- €€=2×ó[!yþ¹·Br™œjÈÆ!…é7`Ø€^ѵSBÞÌQ·õ×»>KâJ}øÑ]ÀdY×x‡~…ªD)·(ë5]Ul¤Y @q¹]¬0ð„XQJò·ë¬áÁhÁšÕ¯ÀäÔªÛëåíúÎa‘®ÓM¬T§^)¹@æ"´É}˜Uðx{o·.zq‡—Žä²?±ñ „×™â£K©u7vJW¼1,ES¥k±6,ëÔx‡'œ#Éþªm­Ó™å¸XŠzw›Àq±Ó&_¦‚%¯¾ü<,‡;2þ>Èé‰Üë ÕAþ/gY‡ {¨&RÂ茫\\àé·6©Á½}ýµ Áq0/°úîÇ6ˆ!õÝÏm’¼ú/mô‰iC OüK‚#ƒù½ Áµøk‚bÁüІàfMÚnÈœüU‹sYgXKøOf¦„.–ÐÍf\†bEcmÙ§„žmv•ˆé; <á+DíßF#ƒ9¢õ7¤HÂonrLn©Wđޒ%Õqí×ueà¶¼ŠÐ¦\2’‚­S ±‚idHÖ÷‹SÕd0ðürˆgE¡YŒ¦¯îv&ÞqÊÝýt¯gÈ«¯È+†¾®V³Öu_(î s•”ÃG·L¦„º ÅGù[Ór%¯&6q¶_+ÝTkòP¡[ûv¦V@#Û’(Ðm\Ç~ª™ð/lDæÓgpCp¡WEC ߸$?ß ƒ´·c¿’á”"Ûâ]婼ײ6:} ’ÖéåMº\»už—‰ i¼½óÓ4(úLR§—ØižT2Û¥'ÈrJE_h“A^w}Ûä)oÚº5ÆnÔcPE%ÔSŒÉÑŽ^¯ÁÃV?ËèÕÊ}MF”Ý–ðÿîª/Ùái‹ñ̆lRd[XúšiÆåâÉØs^áäƒúÌÎÔs×™Hß~~*ïñRr–í¶_‰ s²ö¿Ù+È­ S?˜…õ‚®ãÓµD!AÛ‰­ $V°‡.ovbOØ­¼¸©§iÁÀg®&‚­cšXcív¡‚z‡ìûV¬!Ó ôO±égvª´D!fcá½Ñªû-=ž—fŒ[%Š7JaàíYU"ŽžŸN·’µš|ãe[ŠE:ÛÉ>¸ª¤-óØèΰ£°ìvy‰žÃÏcºM\p^}}µ˜J³Z22Lë8ïðôBßç1ùÌA. bS”ôÄ6ý_ç* ¼ÐW—¾ÞO|ª9¬sM!\òêÂ*ÃÌ0Ñø äõF0ZƒXÄ é\ïew‡Ÿ.ÖÉtG $IÃÜ|/Y:ƒä4ÑR¥þ˜4ìÝŒ¿' Ûùÿ=iXCVìvÿ”4ÜVONº†<ñ%i¸m›”liûc=Þß’†%T7¥ÙöN¹ïˆÔ©R§ “YnŽóçñfê\¶Ý°v¼ ¤s}¨›å¼ó¦næë#»ˆt®?Syƒ‰ŠT©ÿóïV7u„og6»ôXðH•ú”ñ¼¿ˆ}p[áÑé´láïˆÙîã«×â("ëϯîð/¯n DÕÖåtVÒ/Ìn¤ÑðÄ3)˜Ø_ûù«„d\UxzÊ8¯ˆª­y)yÞ^ÍM²‘ ¼ ÚƒsÏx/zh º?M°¼ ãa²'›Åô‡²ùûÓÛbúÕˆÉ4l¶J |á³göÓŒç4$ç¬MÿÐ*qG”O`zdŠ¡ÁÀ`;ÝáÞP72iT-j2êgÇ1;¡Æ‘ÏÖl%ÃþÆ4c¥äÏmÇ¡V†þˆ¨¶)‡îŽlPùì¡© Ö[òôKr{4ËÞ‘ ¶_ÚM [K>ñº ü¸Cîg9þçÐyÚB,cXªzä†ü>ß7DÐûräZù©šÂ¼÷3ÊWfd{ …®ÚQR$N)«ìEŒÞ :ŒÃ¨ò‡ ÷ÃܨaL£Z€I÷~FùÊŠœÜ•)´›IOæó„rÊP©'k¬Z(o½Ÿ‘4tÎ>g* „ôv°*j²æNg”}V*Wö&‡ÕX1Cæî~~RY•èh–dÝ=Ò„y†èè›`¹TºO^QÏ‚¼aª5¹©_GÑ®}§é3ï£Âv徚WLV½¤gÇ÷0åEÏk»¤—-±ÿÏו-Yª*Ñ_ª=ªçýtDßO'$úë/S*¹«ë¼UE¬À b’ä°VBV8¯«„8™‰Ùf4÷GžIžÝ¾ӱ݌èm>220¬^6iüqŠw¨…ó¥YÑÃbnspI4G{þqu~3( óOß;65h•9ù.¯½i‡~UÄ]&𘯿!×µ÷Hôm>NÝAzf­±ÄhQd–§$W * W„šxGYè½?J þ íá+nëÚ=ôcVQÞó_oCRfY¸×N§tØÂgºƒ"5Òë}é×cíz4£çírwN èƒÉa63òþqöx•¨OT€ä{îãïìúýນÁÕ*žŸR XÕÍ6|}0l‹$.êŬÛîe“/æÓ1h f”J¢íï⣯0ôÇåÉ×Oóù ½P|‘œòµåMŠ$ïâƒåäÁë(ê®Q2æ|(ÉËëˆáZ®9°8CNQ²%HBRß ­¡Ì·Èú P9`û XdC§h§ê&£‰¦¤/rqÑ ñËR §Nr[r\ñ«Áñ®0¦vCJ®ù†‘w\ðÛr[i½Bɤ¥[Æ-‘ñ5 !Ÿ'2lµÐ`Ñ)£DSµ?aÌÈqíÇ´ãìü#„|çÒC2QHKÜæ¨2Ë+±T6íViÆ­…—"ýå>ž4÷°ò¶³VŒ¯üˆ‹â•ÿ/qÑU!äíGyÏ.ºE&.ú'вø¼D¬^vVøXfŽ‘Ÿµï(þÏŸµïfü;_?ª]|ÌýýrÙÅÇÜ‹Ÿå=<£2—÷Œ;Dùµ¼ë’¸è¯ôÅ"%s»Dr„Lâ¢ßuê¸áx•@\ôoŠvÍ(ªºùv¡qϹåŒ÷§N ²9{?Û±íq^ rqÑÿýRœPûá<Å~qQ@¾~ЩkÚ³º¾ÈÄEÿ.JðÜ‹Ÿuê<÷2Æè’g<[¥é÷}qêêReIÇ ÝåE­;0moT¹Tó:]›ÃÎ­Ý [¸rô<ÖZE•»¯ -äöŠ÷gé:‹Û£ï—¶·Ë}dÅ—Š1†7³—•ä 9ð” ¥'õ|c§EÖmÝ79ð}:RŒ'fEwMUÖLݹ>Wåèï?)mµEwÒ*.0«Wåèï?á$H#6ħfÒØ˜ÃýaÖ’5Û¨74™œ›3¹šMgWi…°PñR¼?nb‘É×5¸3ˆð¹ò§â#éÛËNjµY÷6Þ³ŠèÎ9qoGŠiF#>þ2ïÙ3 VQ †í¼×rÓãè(Q Kˆ"&âìežµ;Ó›xϘ®Ÿ»YX âªI<ލÃ΢Ͻmæ=úÒ á‰I¹u&Ý—ÒuçMñ[÷eÌ÷´fT×´_çˆ2CñG*}(¹¬°mê„RÙ¶]ÆÕÇ‹ÉyMÌËø=pȨÞx8+°äÀ×Y“˜Bå΢»»ôªÅ ¢'åfÝå^ª-PTv“UÝL!VU~e Zo{C€gs@.YµüBšôHÝQN+ñ£ŸW¨Nñ´i§z¢’ð†ë&}{Dؾd¨H<¾å 1‡@G ,ܾÖÀÂZb]‡ ¨µû½ý^Cj¤¼¡ +ÍôC^uµèÖ…åÀWlp¡‹°+Ðp—7ŒR9¤Ñîv²÷ÀÛ\Þ²8ŒÂÍ𨠩½·‘OêÉ0™xÕu³&Š×;Zž Õÿ‡Í´ÏÚ’=IÇ‚]6E&Fªõ¤e»‚ëPæº1É|Á‰z:´’W(T"…ŸÙrJÛµe-eâÐNê~i×.-©•ò†ã@¾¶ŸÇªyyLÙ6èÏ/3],d¨²RaÐjfq ¨Â·uXäªÍŽÞduÇ„$Ä`dùwä°j õ¥åí#Ëj}‚í âÁk´×¿>¡?Ÿ8›±Ï=FÞ2¤Øû!vŒÌ,P` AÃlº"d^êÍRñ1¹ë”:6´ò÷¼Ö;1­Õãz´d4½Í{~‚ à& jžWÑ Uº¿ÑYŸ¾ wŸm÷±mò$ž¡5p€wlÜåf Ê%äű°GùÁÜä~'‘dswÑà1s¡·6±çº{Ê´¸_‹~gŒ…˜ gÉÖY»ÐÞBÀ;ºÿ§Xóq@¨¼ò'9Pt‹êÙw+ˆg–OÄ7S&ñÖ×4àÏòŸòõ1b#SFy¥’J­N{œqã_½¡¶×ôÚ}ÆF|XGoÐÛmÚÒ­a@ŠTf¤ê‘ú,Éú¹›©”³i¡Ù©¼<ú¿e½ ýÑ™è5äVb’!¤LȪWØl¸a–FB±`³—~ÔcÇà›¨>¤‚qÌ­XçžÔPÔS~T™1=(wÑuWÈšÐÝP~o¬ˆ+×l­V3ñyò-¸À°áNæ¬ÌF|]iL%nmD?eõ!üä ýìåÐHBà±)+,üä}åàKÔ뱚¡Uú%ßkC Àýé>亂€Uv˜³ð%úà~7Ú}SB4-ñÕ°ehÔ ø$ä-§ú‰ÍPwêÖ«úŠ„¼ H©Hé>¦-ó…x ¸’Ùå‘§2r-úeÙÙÔ¡E¿ÏäŒÿ°…ÉÚ¶ˆæò• Åmº¯t%ZNøéY¢ˆ5±õÅ!g¯äŠÇÌTiXÄ‘“š$™Ä,òj~U!à.3òà¿JÈ*C¦bNêœu9z{öú©H¡Š¡íÔHU+V¼ãî¡dˆûÅH&1£Ø`ÝOÈKøõŠÀ,bSCÓÕhs^BXÏp³0´ãq[Íýž Þ ÈŒ2¶29ìh=ï—þR,ûs#ãàvI&µSú!qÇÅ„-B‘û!íZ­$­í0²„ĉb—Áþ;¸Íô1f•#“èU8%-ØÌ|A ¤¦À_29?ÛýºFßQtbbƒ'ZdôY®HÈÈ\ð'4¤ÜmT{œñÞ„Œ&û—6‡^Ò𳉅ªm„|ÿ.‰ôöa= #R,K¯œ©÷Ôç5Ó°Ÿª[ ùÎ8ÒXŠÍöV΂@ƒh•ÝQÿ„r“dµÿL§ß'uÇâz™†ú?>ý˜S1¤†1†*$–/»84œô s–‹­ÿy°y¢ê233ªä\.¶þON'L…=Žõ I„õý!¶žìØ#¹u[G¡‰ëClË·w\ëfÏyouJF; G³C$>[O]ËÑÀ j•“eZó˜Én±Ä(©g­{ÍAH%[7ÐG‘Î 9‡y›Ð‚gæ úá|®Mîõ>^jjE|KcV­º¿ú®Xröå6 é’üõOUøXQÖ ­›u…òÊ /SvVÂ[Ÿ¹í ¼øLù|dþópU ®¶QÁ‰W%;rà#—·Žî{¾õ&ÉO Œ}›íÙ2A[ZUà½rSnL7ZS«K;$,OªvðÝfÇA&E€-¶*2ÚylB¸ÀS›+Ò׈~c™)åœíÝ%›q$V¹vȯؽ’ìŠâF9KСÿºèîN:ßžô¦ž$p'äíl=àÀÛ­¤3SÏCÈ{†L…íÙJiA '!GÜYüÏÉp´r‡âÛ„Œ…úÎHóÐDÊŠô>P©OŠà„|ýл·, TÂT%&éå 2ºÍì,àÅæ[U?d5ûÞ÷_©a˜sà=&a\µë}O&§* œRÕáѾŠùPRlU…ëKO*ˆ”#9]± ³ùr´¿~2ío•‡ BUB*E]Ç–(T8l.Ïá[tÀfÜè©ÅVåa¸eŸÀýPpƒ«*ä³ù²‘6‘¯É}œ?&“±ùÖ2í_ïÌCπΣª>|6ß7;”vï~„+TUaf‚ëgÃÔfœ4F^åÿüìWt:Þk‚3,¦SG7T6€Ø%ÌÝ]¶çdaäûÊb1Sr‹žÕ1wkŠf__Ÿé.Ö4)ìu{¯RïJÞáCÏ,ÖÚÑq¢ê CÌ“íÉP÷ý²¶l£I!Ÿ˜¬ªò­IñÿÌdêêr¦m:j_ŠŸß§—žŽç2mcm–Ù&¦­"o@Auk‡Å,²5xÏjÃÒ½Èí6çËs™înE&ÞŽ €*>ã…Ù3±$ŠB÷ÎvLíâȹ JÀŽ[éÅÎ:ôè÷w  zô©ÿLk‘âŒÎŒÚ×U¢Y—WgL¢zÖáÜO,‘‰·go!¦¬e·9¡ß?ÆÏê$Ó k·6øÕÜr$Ä©×˾!ïß+‰˜óL¨;ófŒ| d ÅrJE7ÍhB·g†„]Âäú}ÌB˜Îgý6æûªúZžná]ÝwŒìYà Tw³PÛX‚Ÿ^~o€˜×yîº:%Š/L0QŸdƒGsÛ r…ýö@.z”ô_x”\­„wùü.ŠóÝ5Gš‹Å×뇣æb6"N$däð}CFg„­NÀ÷‡.$tXº¯lÛ7µ•¯P ”Y·jVγ!s`Æ¡,’¡TË.¬³)‹Ÿ€ÏìÆšJ¢ß7¬åš3ÊõP¼ì³'¬nïúïûd=P¨Z5èÑ.rž/=Ií°£KhO@€¡ÇBÐo¬.AÓD7ê=·ŠižJœaÁ¿²Î&ÿé¥;š6ÝÃ2©@[÷£ÈWÖˆÕ)óºÎÚÎÓhWØåGê†×I(y¥j£dšëxÿhNscÎdQ¶Y€ªÈDiC$.•‡†vþim£Ð£Ÿ‘ñ#ÆêP?"i–öÐ9ðuU9°Ô*o‡‘03CÅt‘‰Ò¦–4ε’Ú"¥…DKìug9†Ù xyL¡ÏÚé{s3ˆMåÀêbTóUmá7ú2ùV;,x ÿú¨bc:¶º9,šM¢0E‰:96FZuh<¦9¿Í/gÒ(4h=º®¡Ø¬Œ(]ðè>Rq¨^€ñ«>„1Xú&ÎÁè·1ÞqÐ7äøIçÜPN§6>°‚F¼êÔĺ/wb9ð‰š¿bvK7}B•ȯ+ÈÒEÇ™uˆzSG|ãeHn¹Éð^êÔÉ–€ˆç’“÷œqRâ!s`yÖòœ=]”Q‹zL‚- XAO9K_´&¡óŒ¯hÁ¿Îî/åj~6DM^ÈÛÅàÂÀ³òÈ™‹±òt(S†Ãϧ'ªö¥ÅcžŸ-=‘to¨ô¤`!ŸW&„qÃÓÅ4è=FW:}á°H|5™ë-ûí}%]¯6µUêÏ[ƒ×e'¤ÆŒ¦w…v)1²ÄåI±èHʺeTã¹W(Ô±&â¶ñíõ,K*E/Y˜Tœé·ïH­Ézª…÷ÏÖ·³q¯õŠöÜ=K ð$ÅN9ÙÜÕ‹Ô!óÒG "ž[gYß6hîW·|•Œ5:­X„mgƒ‘oÔxN 7#E|‹ÏŽY;0[ºJ¦…Ñh/ÝËÓ Iõ2¤›= «œÇ:1+Q%-Qï¥ÇjhkcñD¶y0ÛˆÌÇÆð‡{i¹'³FHÄdë5Z²:»iCïè¨ £Þyëvjݘq¼%=ÑnQßBÒš– õ|älHvr=qaVéñÎò¾‘I6äû­D‘W;ݵžî‹&6OÈ€=Ê™#z’¤íÆYÙGu!!Då÷¼û nƒ" µÓù„CˆÍÉIuÎÁm÷!oÍ|mÜóîÔS©( ï7øyð}¾–OJ#äåžÔ¼r2λÝv‹Á瓤Û!rܧíäç•ê©A^“kß ‚€|ç œø;µ9&wld½ŸEÖ;” GØÒHÞ»óŸ˜% S²2ÔM:Q¢ÅO?S=W¥®NVªWôŽ^_'{ÂYêJFyË)¨ÏÙxâóyGÈæDB[ôŽ^H¨©M5Û¦©4£×3cIL~¶³D6ùuÝjÐN‰Q˜l—^ï«Ç)(ź™uÜšÑà§g÷à§÷yk'Áfô½¿Ê‘‹Às?ËÓ·V©vî›)šÑûëoHá<›¹5ÈÖ½oY‰c²É¾…röeAsß/$˜è]Ïb­BïýýÈ‘Ñ2kj+¾!ûù~^—&húpsŸÚA˜íù÷ !ö‡™´f§ YÅ÷ê'bkfè •#!R~xïâB&ÃäæO<õ$ÈÖ½O1-rIdy%ïz›V¼žñý‰Õ_±¥Â¯çn ¥èÛ,¾¾+¬ºŸÙ»ÔÑ!o¹A_ ¶|ÅxCt<žÑ×¥-s0MD¦ªA뾋IâÈšO/gÇù ›ÞXi"Q¦¿{ÞŠ§ÜïõÀƒÁçíö¦ ÊyJÑT«Õllßߎ8?ɽœÚ9“%e`…²BŽÚ˜Ê0kí×¹Ö¥QZ| _†ÎN¾Þ.K÷|!70ÏeØ÷íÜÀ£æ­Be¾M—‹ßb‹s$ïÉ¡§ |â'¡ã]:2>ó}ó¦¾ F´Lïºvr´kNÉÀ¯R“)½ô„mn†ef=Bªã<ã{ðsœ‰¬ßyc)ËrG#kÂe™‰.2°úa±™N‹‰Dãòs ÃÁê{Ô5^š^ÀŽÛµ45N*˲½ßô]ÆÑ^H¦·ÌŽÛEWò7ꥉÜú˜ûa)/L°vhgö›Ý4—Ì×¥zÎr–EX½,” šð2ð”¶E×ò°Æäøóóö–¸Ñ&û1|_pëXÓ- «ï@Jvʼn˜r.UÖH…á˜È¦'¦×žŽ¨Å;ªº;žãg½áDíÀ£¿ÝùæµÇWjšÞíó>—ÀÏ+Ø„•2’L·S Ìõ‹©Å¼Ï†ðkízÍu4X€ÚŒ2GTo­Dƒ)³£NDŒÖN«¡oZÌÁ=?J`C‹[7ºE5yC‹$Q·KçòŠ?wDbgYJöaEÈÊ”›dß\Cã̶!ïçõpÄB°éD„öº$B*n\µ¸Bk'V±êÕâYz^[=Þ7R5’/óbñ,¥¢Þ?‡©!RœQ“Q %Ô‚gé¬|H(Lj<“tÓ{«Ñ^ÿ(Hò2 Üh;®×7h– ÑÝC­ðX¤ÅÁ.iG4¢Kt·=Ú:åƒÉÎï²¾äÂà:iä ‰îëòȈÁšhЦ3&ÎdË[ß1„,yü)ÏbS{£ÆQ50öÇ;»g&è‹äǶG˜Ü˜4™ñý~£Þ΃¶¦Ö%"¢fÙ²Ÿ7Ï‘ù]qA;Ž˜FÓx*?¦o«±šÕL¼r%ð³È’Êâµ7ƒ ~ûü5Ld„vª÷Ÿ·+rpµ˜‹>öŬîlñ‰¦çà"J©nb$]ß±®úÖi Æ*͇ÖÃ’˜v·+rð7kvA¬QJ2ù3Öx{]Â}Ic%‡ ¥çv¶› ´ž:‡´aJ-ÜÖ…¾+s)ºæ¿1ç¢Ð±¥Î»mG-?¸‹]Ç©t°¥gµ kKàó÷\E—ã×/¹ŠÆê2W1¯g ,²|“X™…èFUšž.…jR¼Ä6z[èš™Ò3ðä¬9+Gh9Ýê-5ÖjºxÜ_ÿœ®FªUš^ö%ðñè;ÜéYÎ’­ü´EÞ.Ää²€Ûä¶¡Vïúá±XEE×WA«ºr6•[w z£ÙôØûx©‰Ö¾ ¶Ï°òþœç›ü!KÙ³™‘•] <½‚8Ðc'øw{Ï| ¬AÀ·k&x ›gÙ‰”ªÞ/ õ¡k6.½%ðqIƒ »Íº5¬Ók_?¯jdx ¶ví´nÞ–À'óc­µn÷ _x¸,“A-¾Š*õ,ަÑd^ˆg%ð«,=IœïÎnÄph_ï þ<ÐÒÈÁ¨n6¨É[é¤ÇIÑ &ƒ ÞåêºÍÏÁ¶=öúã[ŠTN»@?ê2VêÄb“uBÂ`”ß×Õ•À“Åèèú¸uc‹D©%«edà•%ë.Œz˜9¢Á¼Š’Ül¼¬DÃÉÑ`¾Àx¹’”â7ÊaP™2&ü‘8$ëÅÑ 1e½c@–>huÛðàBQ§EtÔÀ¤wqm;³.ÆVé Rh“7\‰ð1yÇu ‡¢¶¶UÁéÂÈ+í>Öÿäʬ4ƒ1#ZŸœ"u„½ÀÎ mŠàRtF>K=·dE=796K‡ÇþB¡Þd±vNκý I§²öD=@ ±Â.h{¤)—جs( ¶5ÿ¿ÆÒÄ…¼½ëFôé;ÍhÜ:* Ù¾u…UÀ¿IÄ—P.iVýLoRmwñSK`õ¸F ~Ö¿ ºy¼CÔäbÑÑÊ‹•¬-ZÔýÔÃ^@¨±þÔÃb)ÅËGZu±oZ`c<ÐÛiAÆ$JlÙ!VT_¾Ñ?ñý‘A1ˆ`r"k°Ý\ ¬ –¡áhÛeçJ+x«ˆ2¥8§ò›EɨÉóøù/ÒðÄy¨iÌÀêªuhÅùÔä6K|fUyÖÏ7u‚.[qÂ7ç¤Ô¯7µ+ˆ +¦©Q<øÖ¯wå7–cEVŒS0 BVýÔbÖ1!W>\-L5sJQ¡¬uéçý«ÒŸœ¶*j¼ ËÖ"`ÁæÏsrDä£Þ ™³;/aë³Å`)³˜›5k2IçM­¸TböX DÒðÀ €³Óš”ÀÏ_€K;ϨÅóÑ%í–j”\)õhÔ/Ä–”‹V5PyF´ïèÑ…´¹%²MnÃFVø¯ïøÑ%Xfd°j‰€öý?ºZ= ýÖfñ/X6¯„îxãÉ€æüVô™É‘ç8ô¾kÜæýR”¤Ù#Õ*ü:áL…Ð齸œÜÒQ•™³•Ø„0*‹²¨Ud êÑñ|¼vÛ ŸÐ(éÜÊXjsæ W\ò¾þÖPë߀ƒïýöm[¦G—l[gT_?û¾5 æóZÇÓ)Tñ®óžøü8@Ôõ éB¥¾…x³´£-_H*ù[¢@Ó"àÅ;ú§ùøHÒú!o¿"ðï7ìÂ…:¹*Xo$jM#d]Ü$)êE¤ºn#ïÈˤí2QHß¹…8µÎ z¯p}ÒY(Þõj7ñžK`Iõ’³a¥:÷ÛZë"ûüjqz·ƒ÷x¯7XºIÚ0k¤/›ôWV5Ü>xlëS~K7ª}îÝ8¢ŸWö5ù‹^-Á}êQKfÊ\™¯'5.ÝÄ&[¿J`ZïtÝÀ ã^ᬌ6g›ÅGâU­ÝÞ04ã·[Yšò:×¶Ü·ë€:/ÍîHž‡a"…7Ð{…ÍnÒÁcöl{;Ø…:4—oò㹎]U§8d®Ü«w³»£)K;®ÏÈv™ ÷‚˜žÒ“¾“´ûn sñ^³¤7HW“šØÌ¸Å³T0QÐL#‘ÝÌÏ,Ã{õ&?ÞňxQéIó]2W6ìõ‹´‚‰Äã>dÛÄlqïÉìþûhW‹C¤}#Zëe²Ê«öS“‘nï´FÕYûÙ2`½Š´nj{¿ŸÊ„ tqºuÛÚYŠíãê Þ¶),g~ ‹)ÂEIòó»ôq 0K¹;p›ïõ/ÒÇ©¾ºqàiÞ¿I€Š>Gêµut^ë"D€•æs&%ð-kÕ´Ì}ã£ØÄ²Ó–Å §[Ôâgy`¦ú•;à ٢÷ûëbŠ(W€b2 ‘e Ú¦ÖW\\ûàXϦ(”ŸßïE_ ôªó†Mô4WïE¤#W•'(ZœGÂD üÄÀ#g1v=›±S%¡$Ëi`d”£ØåP_ET#ÓÖk5·“@ßøuI´³L×5^òf¢u B"Ša‡¾W¾…/Õy+xoiÊ:Ÿ4åÀŠ©•‡wˆ߶^õ!‹wŠŽ§cp`{Ïw²Bã~;0»Ä)~ iDRŒ|œ/ÝIvÙD%ð“q„,•^2ѽTf–Žè V²ÈØIy!¹¤~6¾ãf­ ê‚Âê ©øȪTäÎómׄe\€„âQ)Ĺwîäý;2jN¸Í-™öŸŠºá2ÉÜF“Qø)ÌΛ(»¼"dN1ŽU½L±ÚnçˆtG—D4ë8ñ^k‰¾ñë'?Í¢ÆßbЄ\Ú}<‹!É6t«È.Ñh.¯þ€‘­ç‘‚ƒãE¼jpžÃ¬NΛwl˜ÑœFj¡µ§'L†w¤µw< mÛ¾Évhð¬_^ý¥ô×-=÷ªÀÊÈÏ2i)ÔŒQ2†CâYúQíNðÎÊËÈ«RéÐî·ÔÖÒmn´Ùð,!6é´Fzß½Þe“Ê`¯ü®‹!挼ý®‹ÇÐØ«ê|)ˆ¤§ù¿ Jëa"hªúÊØ¢(JwÁéj!Ÿ‘%Ád>ݶlr d@cO ýYi<ó¡Í=´©þÎÏïú}:é÷Ù­{âø®ÊGWiáÕ?#_?«òÑø4'òë­=5‚*3yìå98Påä­OϦèJÑÊSìÕïú}xÏ×u©ß—­V.È ÃÍ‚†¤vÄ¢ ðhÆ` s‰gäãgU>C”h>ë3G†0¨IÔQ­ Ö#ú;ê3GæHîOd>ñË™ œÔîNd24=ï¬U^£ƒoà­=ƒßÀZ{mKÚèàÈ•©ÞåHo¸ S†f)KÃþý]mj2Óä(¬Ñ ‡âÞ_ä‘?^(Ø|D¯/IûÁɶ |ýx!®Ô#0“ïgÙ‡n.÷Ëu†¸kz)ˆq¨ÅÇJ`I9•ª§PÂÿ(8–²µ—Â×᜷p n¬žZÀ^cC‹k#j(uJBp²}ÈßЕYpº~%güÏÏúù~]È®ÍÈ&Ô5ÅeûzsjØõ¨ÉRvé})ZÁ[¿Í²*câ9™2Ìdë¬B^ik ÄrƒSn6î%„¼È>U75ñtôÔS„ü!&)ø+ݤñˆ>—(]мߞ?‘¾›¯ëjûYÌTà­þU"¯6WZ°¯ëjûû÷¿ykм57ygäyl†#®Ë…úMú·ß¬ËÃPê`‘J¢)Z#x°>üÉìÃGZCÙÚ¢±Wÿ#ìʶdU•í/UfV©ùxÞÏcíO¤±CÆùú B(aUíû>‡ "1çüüQ‘o›7ŒÄNJ*RØk£øNȂŹhŸÜšÌ}ë7u‹þ¶däú£A*Aß=¹Kq}ª­¤}ÓQ‰W™w¶h‹˜ö‹6T.BF#×´+(cÉfíE*ÕµµåL«FÕ4È'±•£ÿ(nm?X©’¦[ÑxÆ­ 5úQrc«œC3$nm?[©Îh~Æ­í"zÅå}­Ñò^]R:!P mLÉÆD§fכ˕û³‡U;öÂÌCo…iÐâ#³Pôq©ÖĵŸ¿g¿pï90çÕQ”OY3MœL:>Ä8DÚb/¶Ön€W<¾¹“Ç™)&C‰9 @ð:]*‘>ìh7ŠYÐ?‘ûQ”ªX&`šù‚žñòSâ<ý’þã?»ž€À_<2™¿è(Žg4Ùø6ÏýË‹&ÄÓÆ{\qÕ”L9°B*Æqò±\?¬í„žñ“zb•Íå¤|'Ѐ_ G‡RlìSZMjÀã%€£¬~qÇ›ì*FüŸÙÞ+¢´”²?t³:©ŠòÌà2Z§®¹^í>ù½ù##¯‚á‡LhÓö#”›ŠÌp1¤¸ ‹â=ÑDV³yv)!T<ïÒé?šÿ„Ý©ÉÏ0ôõ™¸‚nñ¼§®\ønøÐC¦£Èúú’‹¹:3p­ØwX2ŠWÖ¸–ÎüÇÉ&¨ìÏþÇÀ,À!]ÛWž›Ja.^wpHZ•ÀÆú³ïÎaj|Þ¬ßÂi6f\ÕRkè*Îr\jU^„â„èIH(ùŸˆ8›tNB±\$õ§s5äÀŒ8ËAè¾Ye=dêràŃa@៩1œˆN“Å'âÁƱgna[#­µèÖe< îÊ;©Çq‚lLñyò` ¥;ˆÍn:¶P<;¤9ð#©`»ßnˆC·~|äÈØ%(wþÈÑé!™fú©_*¥-~ïHà:è" JH¢×3üšÕ!äEí¨AOOwûÇ#OjGД‹LvY&¾È%™‰ò V/'àph&|ž!­R”¸bxjô³RŒî mÊÛ&r0zÂncÖen˜€TtQ"õøCô÷{_Ѩœú†æÀO$Ôv@Ã_AAĨ(¿ý´ÉŸþ˜£ê°@þ¡ñ‹3²û!°P»/Î|ðþ_ F½,&ù\B —©À‹•RP«ÙFÎW·I8•7¶àÉ5–ðÁ¹c4à¿~îyF÷¾Ø‚Gp„í"'¾-òüÜ%ÖŸ«Š¼Tz‚>¸·TÇÖt‘Ú¾íÔɬ1Ÿ¿DÛB¸®Ë¯ß¢m¢~þmÏ;Š~¡Húg”~IUºuF‘ ¡EtÓU¼óGËs`•›EÅqìæNÍÛFä·‡n&͵Ä/Š)~V€žXù¼uù ]þzÖš²ã%nn GïRãàÅæðs“ÂhªZgÇvt”'Ê»I!(îø¹Ó5KÛZtůÜ*="5ñás³ès…²³_×Îfßz`8•X<8"áefÚΛ1"VYV2Rlý»H»ú¥7fŒØè»«ü[“ÝÍ£² øÙÚu,T‰¾ãªAîÀï-_Hq'õ|eÜM.DtP +_7VN’úñÀAiš!¾¢HáŸCH'ñµŒ?†(I! W¾P˜íï¢ÞHå²H‡€V¥ªôÒY•KÛ#àåìÉy2]jªW½¶ •U~Þ˜N `~5mö Ÿ— ІÍ*¾2QÿÔ—³XÖ±uèWž?sõÿè¨â„Yu*Å”Ÿ7?càNFëqkÌü¤à0Žv¾Ë«x-Ò­ë}ž¶Ú‡j.VWÖä°>9š*l£&[ôÖï,½ÂH˜Vw ¨ÆD ?‘Ê©;òZ,Î× 7Wn¸#Ÿ9#"扒a5f`ùʉ>ä‘Îæ@¡¢Ì{ ~̘b ¡uFùõ¢AÈLÒP4Qj®Þ­ò»§³è‹çÆÍ'¹ÏÍYf.¤qÇQ5»Þô0-YeȘRk¦Ö,õ6õбP~bãæ°ÍK˜í‘æ©Ñ\ÿ¸ZLá³û©ÉÂKø¯xü„ƒwòy|£üàâŠ^ÓaØ:ÍÐÅ2nB&R‰Gö«t¦ñ‘ëÞÁî"ñk)o|Üm!7[^ºl)þ„6îm”šêŽ.øš GY™Ä #‹åi“Hͱµw_·y±Ýóó /2!TgàpJë šõå×­‡²>¤‘6m6ך³S8ãÅl]7‘hß,3z"’#WVêpleèŠ_p̨µ«T~ Vçõõ]ü1™šJ*¥uP5(¿‰(*³…Ôù(Þ‘Õ—«\Þ!e3íüÄ-¨ÿ”_wñÇ£I0 O+ý†;¯¶üºë@\H3¸”_Ø´„rH19g‰ÛGÙ„ò+ rþü/ú3ÄÍÙM+S~ˇߧ¸‡Ó"VýÖL\î@*) ¬õÉë¤Û¶­\ý%º²À2¬”DBƒë6ùР͟W·O=2½¨l‡4 ÊÅ´aËDž¶­k¢è ÒUe]ýØQ ºÿ½æfØàø]–÷³ŠY+¿ê;`Ì–å]XÄ"¢n_ÍLÐ_ùji<õÞtMÐ×ràg–‘޽]þÖëêgç,Úøu¥·xJ·:%ºÁ0AÐ3Æ¢$tNÅ)Ɉ¨²ÌìÓþ“uë®lå·¾«ê_®-Åòýÿ4\+|žÀò­zpÖÚšÙ4«‡Â+ºPBº®ƒ¤^õqÿ2<æ<ÍFúmV `öe¯ä f+¸!¬ã—­>n²ÀBEÇo¿DÚ˜Õ"àW¦f+9³„ECC}³ÂÔZ \är–ù[éZ÷õ¶Ÿ–[UN­M|ŠÔŠ:©Z5 àULáà®0 CzÙ<޹3x¤VûrB¬¥„¢‡|äviFú§d½H‚‘-곅ݦqÂ¾× #_מ\§†”VRv£è…W?|•uü7_ú•ÉÕõø¾rqp(ä½üþœÅ£q!xäæÖÛ5K$o´I>L_³‚NЍAS=®[‰ã=šF÷¯ÈiEÈç©ì‘a§•U‚¸“òñ›ï«¼þŸÇ¿Š­«¤ªL©qÿORjŒ;žÕÖ¶gV±zÝ"$ÈN†Š­-”}ª¬·ÖŸµ(5I¥ÌèÏx-—ªL_úŸ¿éŠáÿ9Š]\èóe>‘/ZpŒJNÕÍÚÍ~[nÒQ}á–ÙR¤s „ ÝØ1>O5­‰®6,OSšêëE:õ^qÙú«†j`õ…­•Ï>Ùóubk®êŠnÓ&‘xLÝ\Q9 pË«2%ÛÌÒ ~#±ãèeJa$wn?¤ÝÖ±!V?—ìsàûlÜ89‰’“šÌRíèeR_zl×M­=-1> g泺¢›Ø‘<{dh²zÚPª2ohˆÄ®Öɱ›ý|“y³nÀ8ÌÞµTÅíl,†7;@\WXoè4¦õÇQ©ý·óU ½¡Ã/9Yiþ€ë,YTEÆã‹Æ´1ofÛZÖ\7ÐeX/Ÿ¨…šÖ¿L«A³*pÿÐÚˆ MT¸IQ¨UEFXø{lP2©ÙÕ-Zí*¢dOjªáÔ.Í"æ5¾3á4އkð¦eÆ’=1Ϭ;ß÷mk,ÎUÅMGóœBË@zªºZ ª"ë#û)ȘÔûÅoþܯ™´›Ü(í¾r‘?èêÐTÃ&ÿ[ äWîã“!­TZ04H"“nŽQÒÌ‹êÐ$z”2µLîÁrÙ{†>åãrÍ;,ÙŽ'í!ýº€æy…ƒß¸bE³R¿b5kOðò>Õ'5u’:=‚.|UÞõð Xd½5è„Íu[ mÕü^"9Ðl‰ÚGo]åïi¶1ÒëÝžöžUy­(=òMàÿȺƒÏ5p^Û½Þë!c;^¤w%Êsè~i5é9zÇ3ôŽGíä²óV@£Y•³þ õCü²3¥#ƒ¬ju׊DÀ}Ü0ð™“`㯀Ý&DZϯ߀»ÀÀL7nÝ'.3ÔgqÕ‰RãzªÍy ìÙ ¡)ººziS141ЖyÒÛ´ïÐ__efœÛ‘“‚d©ú½…ÌêÜ©ÞèÖN à+ÆüMrÚràçetY§ÂèFÔ^C£z£ö-vÊAOë¸m–/õ ìªrk“ß’ÉbtŸËÌÄè6Úmš³Ë¢zß”ëXälzŒëng|ƒÔeH9­ÊøOÃzôŒÉ¥uƒêF =Ùà¦i…|a• _þI=x©ÏÂ_“˜ZË!Ÿß5D;Iì蘃>ðê}_ùAÝe RÔKÛ<1>±˜æqÿYÉ™ú ßý+÷ïH*•3™)5D¢AŠTµ\«+ô±Zæ&+Ôª÷mågÀ í±Ó$ïoTÝ샛Ã>8°ùFФg‡ë#žæ)Ãæ@Ú­¦‡Øåýq ¼CŽú8…=QrøÊ'2Æüó$„Aà}®ž‘8”šLƒn¤ãèŠy£ïA~;€3YDJXïóp½ýýó©qwšÛMíëì£ôX"wËcÉpnqΈè]ï»^$…èw—zÞëÚæ@$=›Ð•U“óë¤"9ð•´b.5¨™ÅùɶåÀO$?~°ÂCž‚Ðu‡F‹÷½¾{ÙÙŒ_Rõ‚®˜ÕwÍÖ£ŸQv«]VФ?&VÞ•ÕÓ´l¬AÀê:ßñÔ–:›Õ°¦švßÏ»ø@ê/™µŒÚäÀçÕQ¿M”;{E íý¼šðþDú(ðá—ÝtÆ*tÅÏÌ©>í#Ú)5A4;ÓìïþOL>Æ&ÎÖúå…©sR<³}äS2–Ûï2ugP•⯭ å zöþ¼µÌ[÷Q¼¶*}|~÷¨V–Hœ¯M|å‚ÑvÅŸS-iýÑ^Ž¿çš¶+¦·õ´°®}Ãñ”gÓ ñ{^;1ÝÔø‚|C4ÜŽD±^êMÂzö¾X‘ÉÌ@ÌÖê}©ÙZÏ9ðyz æÊè`ÑÂÎo]\’ðË1v¸úeOó™“ŽBZø°þÞ}EHØàaâbž,KB)þ[7þSDuüEÆP->"!Ä(üŽƒ¯ˆ†'N )‰XI'!Õñ¾"ã¿QÐ5¶]«U¬5sŒC¶÷}EÆ0ŽòG^³áÇ2kfÌ3AQ^Ü¢™ï,Û‹lWÂO&%Îÿ œ1ËI]{¿Q£;I›ÂáUk‚^ƒ€¯lIIùc¸ïŒ5æÜg21Œè?+Á³#¨×Ó¹öd‘Rh_à`SïoÍJ¾b‘ù¿ŠäÈ8ñð*󄞱̒P©…‰n1’|ëêû·nÿ6¼ãøÖoà‘³¼Rk£_ô€½õÎ"¥}WHú4ÕÇ­Ù‰ ¨!©±™ý1,%\«Ç/@ç$s>8íð‰õ¾ŽnžnßÇ}Û“–Tõñ¼yñÔ¯«ù2ñmׯ|"½óxTZåÆÝ*‘Ϥ =£>íÏÆf’´~õñºÕ*!äl‰m›™õ›ÎX$úxç§ØÚ¸žï9'mâ‘wwaçI,?¿[Ïkï~ìÅÂràW.«#òžûÉÈÛ!u×&`‘¥ý’øR±²²³ÉeîÍs1þe¶}“Cʨ%`•µP¦ÍÐŒ³ß_}dŠžñwׯ—ª%ƒš,AWL2…î1òi7¶¢Ö¤Èǵ  ž ;ŽÒ+m$ÉÇ3×µ‹¿¬[¶™Y%»‡êã‰ñГê\o6#›Ÿ™L’•¹ùA—ç$ÿ¼ÅgGG_ÔZ$-³}Š0ö1þï?H7blÚ±·¦Í±j÷¿þ-'¨=´®­õ:"`c©q`;oäü Ú1M0ò•!Ósz¤´ß‘Ÿ?²Ù u§ð ¿¾Sµà[ÆQäÙ–EÎ߬í¿fWÃ5qÇ9U  gf£9ðÔ¦g”®#¥›U—Ïr‰š{‡1™ÖvÜz¼Ô5Žã\(Ô¦6Ýl™ràו¦a·3MãC?5›³BŽ '¿;4všg²çÀ2o¯»%“ì¤0=ãÕóC(Ꟁïöòî_Gt‚@ˆy(úëŸF¨ÂCGŸE/20IT©²2¥€@(ÏŽ$$«$l3þì߉Òüv5‘!ˆàãØ`ûÜÏ!Ïb=yÛïÓ¢¿¼‡‘½•´›%B^‘8Œ»æ`.)ÌjÁ/1ÁÁ´“òsG;«„Lcû)"ûÑÑjBÑ`ª‘ÙŽtŸ3î}è ”·=z¨÷ÿùë®é˜ì5u;Š_ó[£L‡Ðdõ†Ÿý­44©àRí_]пo›Â³»ûÔV¾±%x䟟gæÍõËgÁüŽ|½ ¹H/ä"kôŽ<§ñ/­·Û‘ÉËÆ}3:ú÷?¨äøšÙgí‚ßçíƒäK§øéÙï“â§gÿù,ä2aä ¹„Rõ}/šÏ:ß¿ïJ5,vJa¾?DDǵ¸Í\>¨°•áQ Ò4ou4ºOß¿ï¯öZ£6ÏTK2  Ä÷ï{d¤æ:]µUÝpÒ#d½øÈÞz$m/Wݰí°¾ÿz€ICzG^šæ½8 ÁÏþóY= ÄÏî=›ÿü竞KFò\’Z)Œ|‚f˜Ø_W´žjRÅgbc^ßÒíJðDΩ—“ÃP6tRU=ï'Éó¾ 0l†èO4IP5fX¯ÂüVl›™ OÂö·‹b):³Hé÷Wç¾¼ÎÍgRI>A`µø”*wEAÆe-I »ªE¬CÍGzµ0Y_‰ÆñyKÊU!Z:Ë·8àˆôL61˜0©èûrDH·(L"ù'÷ Ý® ÑëÚ¬EƒÉaæí,Àì‘Yòmšª_3È<²¶KKbk´x„ÌdÐÞ(É…ž¶M£÷xõ™ç§¨‰¶Ì78ó!ï'¯0sMƒœ·šÐI!äF:{Ì4cS=žÀÐÓ,™¤j‡¶ÚSxài=¸|>9ŒjÍ‚¬Ñ[O.éeyf1t¬ïUƒ&ÒadîOûüKûvlDÞûái¶ËJU¤m×|èD ZG¤o|ýåÝ»ŠÉe¥ëÚo½£ÃÈÜ«òÙËò¦oç]Æ3ù俣ôZy× ²É Œ;—ª…äB ÜÅI™g&§k¸¹bL(¯doàrTjS¶æUÑQ†ïÅõz:õçÔ“w¬ñh”Àý8Ä•0Bò7Š‚š]3¼žkrjGd1 ²tLÛ÷*!09ø×#_&øåèì‹•¨y2›³‰fãéGÿÿsÕ2¿û4®‹Ânù˜|j‚)ð ‰õ·‘ÌóFÛ U€¤Ýû´œ$)Z‘ZZâj™/«µdäjâ¡W0!Åywo¯ªvS0@ ÀƒâLcXn0D#¡è§ g%tcH͈*šr^!ð‰ùù®0Ð0Å„ ök4఼†ƶ©œu‡Wl+ê¼[uÞ#d²õ|qÔ]“N|-·`q‘é1)ýù]å½+¤^ãV’ æ ñü)mZŽË²zzú¼GY¯Ò\Ž­5&§¦´V[Þ îžð 8Êij; ΞÿAÎZ/MC¢qpÞÀÂ9€­5ƒëÐO¿ÙÒ,+ĤüUŒ§O9Ú}µ‡æ®Üª9ê½`²‡ÏÎ4Ó>ÌVn붬}LC’JCœXEèˆ5á©¢ûè#Á]  Ê¼´ƒÜª2)=l¯I¼uåd1H~°çjsiÒnÑ m±AàªvEºja¢è uíú|…³¼æË”£Ÿ>$^Š(Ñ,êquÎÜûZˆÛ#ýiY¥ÙÍû í²r$hU)Ñ)gt]‘”‡-ߦ9±2ôø„Ý*ÞgÌì’tmA'4à—7Hî$Pr#òŠþ%ÚkÖÍT`dòÉRéÁþ.£Å¦&D.&hayx‚Ù1ò¥QÁ °1BÞ2Ä’R0½ÕͶ`äýp‹Êú²°bOæð(ýÄuçðé°ÖdÒ¤5i%B>Žœ"ìü²c´Ûj$ÉKÅ(:Ĉ¹fj®„‚@hê‚9))JÅT )× fôóJšî' P3ŠBrîŠkÝuŠ·y£!ðöªkfœ“uFÀû®¸ç‰­‰ÞÖv…€@(ñîq4áRÃÇaE»Ä_ŠŸ’†wªDÀ]¼Ê¤ ¾ÛµšçizQjF~ù/­°š]jV}?Î=Bº£ßfóÝ öU[´K«J¦V„L^«ëÝ©ºžAà·êº„ÀÕõz¯®'ÏU×7üV]Ÿ!ð[uÝã·ê:~«®£{üZ]¯ò[u#¿U×1ò[u Ñ×ê:žBïªëWדç?«ëx”¾U×ÑÀÇÍkÙûðÊ,5Q¯|‰¼†æN¿CDâRû‡€IlÉ538´äÒi 5—ep± ÀÝKÐ÷dxI]ɪEŒ…@`¾j“,—ùBŠFå¼k"ò›LJ$–.o§ï0PÊJ:)1M=Qèa€— ÷ƒåš«Ù|™Ûà}€ô:@XŠ|,T~ú‰ü\¼ìSÙ÷bÈ'^¡¿ >u¯5º®½ÐjÑ!±ö›‹í“á ± ù8êÙ4"Ødr e_÷^ }Жȧ‹ÕvïÆ=½ï.m¤QŠÌ’éHY.¼AÈìa`QÍWÈÃÙî‘^¿;Û5~v¶Û+xéõ³Ezg»-:Û Ïm¶éµ’$Û$—8+Abòû ä\ë¡À£5Ëf¬¥ÏXÍ3ÓIвvÔ±2©í¤›n§¾¥ ¼ò^Ú.]Ìþ'ø—wúâFÒì8mé&i‚\Äü€‡Ï 8?ýôz™" ”Ûz>Þémmž/ƒ"ø<¤xè 3+]×ìKìd/WÐ]…VrPL4âaïwv¯Ñ‚½mÖ1Ý"d‚¡¿Ù —!dŠL(v’¢i(CDÐ< ƒIƆ鿞+h˜‰Z§RÛ£ ©[†wÐZ|iÕBÔÚKIBú¼c*r®l•š§’K: äÑl êükœóVOÉÊz+’éáFl~|ûè,ßZ22P>Ä"Mz¸Ñ'5y!Çj5ùc‡×ƒÍLC‡„#»…q¡"õ›Ù±Pž"uX‘>ñ°2gynK˜žãÜYåÖul¡¥‚À· m² íx“)îôQ›[hõ&ÖV6è§_ZéŠ Š€?ñÀ0, áEץ˴@àd®Â_Ñ<̤ÔÒèažpùxÚ›Ô½Ìêè§Cu,§’¤Íòš#¯§©î…:{“™5²BÈäÃT7ÛeQ dú:Õ{3ÕM ,ip­þs¶T›Yg}Û´y{¿(Ø8—xدw°(ü§´”‰ñrEÆ!=•áÏß–¸EÑp")Ý;òñº((k¶J›Ø Í`ÏÂrç¥.sß É:9Ô<•¤ÙI$*Xç”e³ 1è†+LΟÒ03•I!"ióP’4ÀÙ|J¥†À JË8;ôÂä àë©EΕwžI<ºKo/j¸^Qt™'슢˜ ‹áp¨[I§B¡+¦ÐbØWB¼Åð,ÌÞ)Šj-E±EâJz”ÿÆ<Ü!•R´'}×Îݹ OÛ_ó®ks›!ÍL嘆;7I®ç%äjeoD 2ÒðWM)™æ÷z%å*ÑO¥IH—X¸Lï§ä‘S^:5e×p¾ówœ—ž¢`æßQvL`PBÀëu­óRLy;u‹úm¾2ÞîÉëy£Ç”×È—uWÆÁô8ÜLHâÖó¾G![©·B*ÍÖÖ›z©ë"È[>²Ë™(PyMˆ¦ëç\­ë<Ìj¦‚À>Ìqf¢mqWɲïO½F>–§>¿“¦o]ñ£ „Ùâ ¿ßuèkU¢R²ãLŇ¹Ÿ†‡®%Ï[+éIºî „mÑ×v»$SpxÂOÂ$Ó¬fñ©‡ˆðíW&¶Èû1ž¸dX{ÎÙ*{ï’h¹­½ x?±ExîßX‰ü9˜³‘Ídºmù²ôÓW ï€O°? _#ËU#Ú¦Vñ`$»c{n/£êæY>ØöWO±3¥¾Aö9FB†](Á7½…ìrÕ#$,­b¹5m¹àh,¯°¶Fózzµj §ŒRk ßÂ]0½˜ÁÖy‡gÞ€mf®2Óh[òûxÃNLv@#é+Qê^Úw¯¨0ÉrevT^Ñõy úÚ›ù*Ú<´ÐdE33¹`dµ#9‰’ˆRÍfïê2ïh©Épz›I‚‘ní:dÓqŒL!!ÇoYœå&emX¯ïú}ÐD ´á­"óÜt "ÃQ1/´nt±p4JÉ4®„Ï ]yW­h.%‡;K0¸Õ¸’­^Ö6¶$P.çUÌár5ѵ¨Ñ I aGå=ï réFÎ޶™ î¸'b6|(Åœç'äõÙâ!@®ºÎ$¯-Es>MÀ‰‹ý_y'ÄZ—è‰RЧÆ÷ìžôª¯J†‘дƒù¢8kË¶ä¹ Nzy{-íŇ=wÎ\JlóvkÕ.U^"ätôûR¯õ\M´]ð}>ö¦;¹=1—¢ã³Äãù„e~Ï.ÝV˜D~ h¯Ë.{?t›˜Û쇤ê«Íù ¶{øÚg%6-˜Ó„fˆ·ç~ß<Åo ÈáÜYltk*çr¢j*c"•=¾ðFóiŽÖ8 Ðj_9™\ËÈÖÏžçhYÄŬ"5αQàv9UÂbëA>­D # n)˜Ä>Ó kå$Qr“wKn þÇ«žíXÎd¶*]‘C}ñ·×ÞâÞvÀ¤ƒšW„Äð†€þünî:eÒ£¨tr;Ê®Þ[‰…îçš0²õý¼•ðçµ’^ºe ±qôv”]wyùâödÌ+OJnÄrÒ2nRLÍ´RȵèŠG—XÁcO•Éo{iR„Èɼ]NÖ{VÓûÕw„-3%±èvÁÖ{î äcÌš´&´&¿îÊ´úå(Û“(uƒï38#þú1{Òª+)%·#ëùõû×oO[µ@¶Ð¦_¶“hÌíÔ›‚Ëì´q2‘Ø#v»†öðÃv¬º˜Ðú=6´bztÛ‹©ëoäj7ʾ4I!qëíz>*hÛX4}Î nÉIÏ»‰Ú¹Æ3‘^äUÜ΂>QKc,FóŸ­Ø_ΣìýÍK=uG 0{Ó¸Ýuk´vð)I•‹¡äH—v)ÊÝãýhvc¥Ï®õ*‡a¦CäQß’`å7?fEÛˆ¾3<< ,°›kîñùÚ=7SÚªÜDS ðËg¤òŠê³.WzÌ˵QÙæ†² _i.‚PÓhÒ žsˆŒ¯Æi$eI¢¼U¦¯\Tyâ¢Þ²\Tyâ¢Þ²qQgüÆEEWüÆE­!ðßpQ»õ–ý‹‹Šîñu‚À7\ÔîÄE½eŸ¸¨Ý‰‹zË>qQ剋zË>qQ剋zË>qQ剋zË>qQ剋zË>qQ»õ–ý“‹Ú!ä.êÿ »Ž-YqeûKUiÈdØóÛkþ2 œð«¿þÉ…ˆ «úÑì ” »÷Ä:å×ùFüž±ßYÍî7Újh{>/G¥ &µ/äVÅxöøøú~¢^ÚR²¾€øÙó̪EÕSõ¼Õ¬­¡·Ã)üã­õ;j&ŒÏDîJ—ì.=7T“ Ÿ½ÄÒmW²òØ›¶ìy†!þüûOd¥so9˜a­‘#1ˆcyz-pöz=6«ê `/yžaˆ`É—1jhæF™yãcy¢:÷ÿŠ4ýnRÛ§{2êÞTèûA lM—Ø›ô!•…ˆ¡ÑÛÓo8 D’ž¨Jø,±ëb-ù:Ú¬dÄ©u 4½=¤'Ѧµû& ?¬„š†/EÃæ‚“‰ˆGsÛ·SðẸŠҥî­ÿ˜y)ô iÌç›ÊX…øðÕ½*„( û‚24‹+{Ç—‡6=ùÐêzذ¬GÄ,Ä+³ÿùƒ[4øbm›j(éxû™‰„/ÍœÖ.╹òýˆü…³„Û+*ÙjˆWç˜ ÿ@f`Öù/ ôpÇqØ[yíÉÚø~ýÈ~Æ7}MßóM˜HB±€êYS[‡üD±tèƒ_¤ÔLõdÌÛ/œ%†iuPä7"ÒÁâ£j¸n*ˆI>O^™d×ÔŸÈ;b"¬š\ërÉZº]8Kœ™l‘ÎÛjº{Ÿ?2¿C£F¶ï-û™‰¤´gùÛ‹È´†XZ§ÅÒ¶3ÄTžùÕRŽœ¶ÖslæÒ£%¢$XÊ¢îè¦Éé©XMLMûÎ’]›ÿf)ì]õè†O,^j%ŒÚFI©ægN-e.¢¨ÊXoË*÷¶#ïøúÁöÞ«¾[ª™wøÆRÖ!Ý:Êma\ŠŒxZÊ„»&—\Â&u~±”}c¢¿ÌŸ­/µ7Š ¿1#E(Z7;E-Ûèžcb¤ðœ¨«Y™™Y 'ω¶ÿ ïé=\¾.ko·$'ÈǯÔDÙ×u ûÁG)ª¾Ÿ¸„2œX $ÁÆ[;½Ú…QCß_ö)>íÝ7GÓ]×Û¬"‹y¢j$ï:Ë¿py@OÝ8{ ëp•zÀÀç§ôØrï:Þ“ÉpŒ/˜>ø`?(²GàëWM)—Jv»šxl=±_=»5.Bv#ÔÍâS@%÷ßħæÞ8!$£„¢µ4f¥ ¿žÝ¯Ü»1šÕh¬iU4ÙýºŠºŽˆ^hc v>»zé+ÕÃ*oïìñ q_$ówö¼hÅKè8ÔÕÐò©Jó˜]‰–´2 ŸFèmÍ2bú:`°¥-°ǽ‡Báì´ÿõ?!ޝ¢¬ª•‹nÇÀÒ|‘AQº·Þª=ÖŽ´z²“[éïЙ='žÃ–•Œ˜}Š:ór(µZS¿j–’VQçÖ‹:÷sG€ï_™d e¯ѳ`¿GûÙûÿ+Øï1ð¿ ö ðׂý&ìgïkµ ­5Íí¿ƒð;Ëiož«éRAKк+Óôœb(j={jí¥)Ùq°ì¼)/ú(ÌVXK5ýÖˆp˹þ¢9ˆ¥QU¿Œ-yG¿(þý;ˆ2zyÓ(fØ ŒÀÀì“6ÞùŒ7€×9{ '\&BÞ±îÔRà¼PùÏ_Q1HDq¬n« ͯ/äzŸ-f„+³*» S™Àë ÿùów0ºýá3Èa䞈^˜óà¤è1й—½Z`=¾Î{&Hæ– Œ`]1kvNL{¥{ÆÚhþc¢©‘ÓèÌŒ†Œˆxú} Îú c¯Lwö ÷…\'œ¢îˆ×y؇éq6§[•Ü£—ôËÜ~SPèX+]AÁŒ÷Tzê(+ÃõQ4R”“;&ÒЂWà=¨Þ‰b1XH¢>ÕÑú€“þhx3@gû)QçÑ)>8º”ó(èM>åß-Ðn…Pnëúä!æØK·3$ÌáȆªr:[ï$vŒÉ®6Ý ¨Ì=åßÓžU¥š©x$ÿP—qôØçôÕXˆÑ{‹©Üâ'`jë¤ÀªÙHt!%ãÀ1ý <'Ü¢‚Ñe*Y™ºLÀ©ì½Ë„Ïf‡»ðT >'ÜÏ£iì„/ËPøã„c–ºI¿Ìë:áñ”²‡”^SCÑÿ©S)’‡K³m »o¬ã ‹âÿI°§Ù$ؤO°i ¼ÝãC,1¦#ìMCUHÓ7•PVXö‡ÚZhé|_Å @kÊzÑŽPEQª¼ùø˜ÃÖ[¿ èœ{_ÚPd,§\æ®§!µY •Ó(ýçDçBÿލÏJñ³SrŸFY¯Óz`àµTÆJq;¢RKQ)òè¢2‰Ž~±Z³¦Uø ïÛ¥RR=Õ>ÔÕ<ÏÇÀŒt.ÄkxöRP1ó¾]ÚŒAÌÜN`ªÝZo ¬}PßM³S“ sU8H-pY—eƒV³÷í“H)(Y$WÚ yö7ê]N™ ›‘Y„"oTÂYúÆ»*Wmý¹‘*4H8Ù¹”ª” õÈÇUçÞkØ™áºC$î½t×OköëZ—­&kè;CUò1YY,¼çz)zŠ|‘ú£Xc7lÖÛ— E"ih8 ÜR¯Á´ôÛs„ 1‡êuJ²ŽngTb¬ö}F²êb¼èT‘*‡|¬ÙÀé˜oä›GÖ"w&X«@dÝòÓ^ãÑévÈÑ4š@ã1óE,» 8áÞs5 ŠT#2ì%ô•*‡ÜeyLtÌ®?ªe$εÓ’ìŽû=e³Ù¬½ ú¢+º–î§ž8vÇqZ—mÛ:²BB Î_ybLÐ3ÓÒì™ùPƒr™‘ É¢MÇ5$m#òužÆ‘ìÖzOK_³Ýð݉ S¦Ò­ÛJ÷º¢7uÒ½d[l&˜Ý” 4ø¼ï CPê´U6帑Ï“†*Q÷h{(íÚxÒ§†‡FKÕˆMégySÅVFïÀ‡¦Z´´¥íêäA–ðý~^ˆ]Ènhx î*T¹ëPÍoxQîí Po$¨ …(2ðZŠm—¬]2âµ°Åç‰Uõ2‰)F ߟ.ul8sáuÎk.0ð†%ˆc@ú0ÃÌÛϪ,xÇcf¦Rvž¬Âч±¿Ì±×ÚTz##¾€.×,ú†ƒÚž+crNVÖÙ8òWà ‹Å*KUôúï` ¾ßÿáÍÊzó;žñªÐájoTÕNk±/ÞS”ÎÞ-²À¢&Ñ |œ­€^ñÞ›ŒÛØ”Š?O=Ø‹7o=68ožaàïÞ<—éÁþàÍsëÏø‹7_m®Óñæ7ë̓ïô`ôæy"ÖƒýÉ›9´7Rü„y õSvUÑŒ# ŸŠŸÁ¹¼xó³iȈěáDmL×”ÐS~*~þìÍŸïøýÞ|o½yðÇìf¨iÁÞü¤¶Ô[’£â©=­GwyïE/ މöÄÚÅ ½îz,4âD;CxÙ}öÚÍk/Ü,$iùC UÊso—Ó €C9|ô!à,ñgþø¡—èìÓ)+hÊTxïÔ´ßäŸ]5aÖÝ£¹Ø%ägsúƒœÃÇðÚ˜òiéþäÑ/JÅTÔߤ) ääsŠJÀZ8[ŸLøÜ!®Ì3xc¼­f±WÉJÊŸ4•6ÄX«]•ª4xª•<®ôzaÚºÄÇ„w| @!µhV§Ú3cà©ËT¹›RW`NåO‚èr}·½V{–ó’¼c† _ÿb—xg6VôøBt`‘‹¬=†²±ÆCMF|Ó"'ÏZ½:Ž-ÑiòÕ9’Ý »·™FV%T3çH,vÑ{æ çUбb‚¥Ý¹Ì)p«]€7b*°¥èìówè%Ï©];{#PèM@ìéÐR \äÀçÙJ¥]Ε—MÁ€%G”žqTÆÓOŒ¢Ö©ªÉ;¾0ßz4µÜwë^H8T^ífšO®:¥3H \WÒÀbºÅ¨65³* ‘nh¢Œ- ªÑ³õ€ìêY1ðqaÂ÷®¤gÂ?¯Î×µA1ÒŸO,[¨rBʶ>×ë™zý‚4Ce缇¢ <°Û¿ý LýKöƒáÓ¸MÞ?kä\Eø°Ù[~ÂüSî8Æ<§}eb†(Gžh‰‡F޾í›b2 ï˜c‰×Ðx ´ÃÍl‡;T¤³ŒÀäPÞ7 u`Jk¥S`àýxLëC«X{Þqê›ªí§˜(Ì¿®E "Ö·&yu–r¢.‹f2æPÓ ð޾:îë;eÐW£ä‘Ï<$iÒyý9FàŠÆ:}éx’N£ár=f ¼¡%V[`3ª)Š…äX¯Ö·±RóqÂÀ ƒ»gWûj ¤ äãr¤V¨€~»í™³úrÆÀìgàbÍ= |‘æ -Öª­¶Ä…r¤V{6Ö†6jGÀÒ¨Žó3fákì±Vê‰Î#tõš®À:¾ÌŒÍ³½6ÉK~S霰vtŽ}IF&èäž ±¤(‰#d×­ó~²ñUQ©‘”zP‚|ÐÉ=ãG¿ÎåÒ®¥=€ZúE—huxOÞÊÏ÷Ì.1hßÝi‘Û±^Æ|a‘ŸôE›äÝ(è˜o ã‹\¸I¯ìà—1ó_‘ãJ×ú’ïQ¾ Õ!Ù±qvAžrIŠ[™i·vƒ‰ÉÀéïúŸOÝ%>~{í;Þ0Y‡–7¶ôìˆ~9Òßý7Jˆ†¶Vû̲èäÔ <ÃT¡åÜEMÔÁ¶úPŠ<5_…Ö_»Úya=_u~vv%«EäévŠRIÞNÂ(ÊkôʦE‰Àûo¥_ÍçH³õ“ØÀúÇ §ê›è]©;˜I;òý)€Ùý›FÌI˧Èõ Hkç{—U¬Ê‘€î{! QŽˆ½ ŽmV3‡]KHâ0¡Ó~µ½žË6RVGàãT xøüØŠcŠœ ˜äEJÎc,­Ù—¶m¤„³òû‹êÝpÎC‘¨.Û¤–ßè·Œã3ÜÆc颲~ZòêÞZ`cWËHÓþ…:O#rö©E[’ù}ÒÄZÖ@Œ1Ù±H*DRÄÝ5(w ¼‘™Œ¤I\û¹X6 ¼“ìcä=ì4kŽÀÇïýÈiý܈ëðIC±ù7ÍìvTÇNQðk?>Ú*c$oçÃX¾ÂÀ&}ˆtö¬GÓǤMÞIP2œ>Ój}!kà |üPéëôOìØŽODs³öÑí¾Õ #ï˜}–¥=ΆJÏäѯÏn~57Öü]¡2QLH—yèôÔ±%ÚïHµìï=Äxh/Ԭܘ+\ÄÀÏ©¶ï»êxÿhØi½ÁÄJèµ°FÇÀTå<‚˜ß_UÑ©aTpú`ê—þ òÀv‡Sü;#š< ò’uåX™€ªÅLôj.šUûȲµdÅÐ (éˆÀˆ «ŠŠ‰²}]a aÆ ~­°‡î "0KÄúA¤ÀYœ•ÌÚŒ¬ÅÀbàÞß8²YôªS ¥uæG¬uÌ«"¿ÛV4\nN– ¿q«N¸ñê’Û‰oíJ§ñǢƑ ¥R#Ù’±ìÄ#…öd]ÛVpU‘t{ d,sáÖÞ-ݽOЬr}Ï #AÀ~¸fNÇ<Û”xÐóÏÃWE‘˜ç3^ã¸7å̶>•o¥& a·aÁ!.ó¨_þ—Ø|YTá¤7¬/JæóNXÞê–¶®Ñ&;²Ûï7\@âL5›;¶U§c¦D2ógWÐìœåÚ–Ýq÷³`72÷»&$§˜wÝ›÷'*‹ªBU7¬U= ³"³tÏ> 'í¹4KQ'Ã-Ce'g‹»;¶íR’¢Ó;}úû©Ü2fv1ÓþtˆÑ”¯Îê½îä„ÿ:¥d¡–ÅÍRËíº'O|_:ìݘ’IÙ5’¾çãF‘éÛ«¢AÞ17fˆòöüä[ËuGg\Ì›Zž’ª²6æRY— O¾MßÖöfÉd9´Q·˜p3VUÚ3Y0ÖKO¯OjN‹d²k‹\27EzÎ#Gkd~¹Å—=Y5¢)ÉåúEˆ»¼ñèN°U°bÔù‘šÈî{½º¬,Až$϶b=ÙGO´\÷EµEA€3híí Å zÇÏL8±;ª Î ¹Yƒ…ì£'*±ƒr¸€dåL¿(•ر ïàj¦¶wô ‚Îç×ôD…E6·Ý6ª‘>ýTÄáÐùíÎäÁ®¹™¬ùì !CÚÆiðY—CMžž}Ÿ–6ì#÷kŠ/t–²EÖµŠÈmYÈI›Ý12¾¦ýÝ7땲’³ÔyÎ ‘igi©ªm4¹a³³õ<܆ž®w¯Ö•5Ù›Yè=ÿ_(ÂŒdÒö…Ù<—ÔÈ^ âåþ=ëRª±,ÈÌgïKAŒë┓KYHb3d)ò->&Ùb—ªX¨IùEmsÿ+)Ö³¾Ýù¢×IRþaW¶$+ŽC©*wû}:âö'Øà0;Ç|ýxH™U=÷íFœ‚4¶eÉ’ÎÎ^5°¶ôTKûÄ„ú©0%›z]U£è3¯¤M>ÚÚÁ²Ú.—AÞ0n¢¨üf6ÜL$ꦌÞtxýP3ï ÔÛF„ÌuÜ)ìhû‘|Ïçó@F¿;:aµ­íjìJßþ:‘*“–ù°¨–¢²ŽœÚÏ(§Xb|g±2“qonÿëë YÒûAį{}Ÿ4V:Ÿ†ÞÚpåÇ´˜ãu!Ȩóæ½J©VÛOü~a&T.ºÇMmŠë‘œ\/Ì/œe¬Ã¼·Lø¥MwŠŒGBDÚ²"sôB-¯PJ= ëPû ψµyÅ9ÚA88^ ù·»}Y:úöCâÜoE•2a™–Œ1ºæ_˜›+§žC-Ù¬’Äg(¾HáM*ºþ´ù@~#d.~Ùèî“ÄÚ— ÖÅ€ôë$éî(RåVÈ>%Ê#›%w¬¤q\q;õ·B/Dx¬ÄÛub¦§¡áÁ%ÒR \×÷œ5Í69*5¾l“ƒ é÷‹³ ò‰¸òõ¢7ýªô s„.U÷¤6‘øÛÝ:WÝ8³Ú``Öôú“€úÊn‘#ÒJD%³5»°Úö-’rƒT8ÆWîÛÞ?!³ó | ¼ÜŒà½E(Ó0G%Hh§K¥IJ{¤‘¶Ý1(¢§VgDÔŠ÷íN€ªHÏå£d›Ùû¶!¿1_XR¤fƒšÛv£ÈïÛºÏg¢zxHæóu½oÜ´dr²ÊTëì‘¢iW‚ÄÜ©¶NëeS²²¦ì ò~ÖŽ 'ŸÍaß~çãw®ŸãÖòõ¸~ôŒ¸žTwÚÊÛ캛+ ¼¾ëhfƒ·÷Û¶P6ëÿ1ç ÁŒÔ†*óE_ÈG€×Õ´¬3‹ìybúQ1Ê{±‹µ[€ë¬@*æW^fe°mËÊmÏ£¾|\ê‚’o³›k!%‹4µKݸuçO ÑØÒb ae€:†p‰Ç€J¦@šÚ@Á¼ŒZ‡kç~ÁÀ;ñÀÒ«ÚzCCóøîðø<—ÿCwH?ÐNKƒé3ð_èaá^.¿Ðê™Ðfà™…IÒW1ÎU)åž%X‹7Qëò`ß[Gk”4ë1)ãà9kÙÀ:«mx¥:¹·c•Y £@¢Ö©4*5 aóî˜ÄÀûqÜ”¥ž|ö²?n¨‘Vu¼Ô=ôÓ}à·,˜uÇÀËOÀ}ö$$3ðǪ̂*¸ÁØõ¸¹]Ž·CÓ$ÉqÆìª˜«z« ¸å‚5‹RûYì«]LA{7fæ#±›¯´àÖ»¢™1ð‚€ÙmX&·|œÛ ¯g²Fdí`­Ã=­7?ÞPknšgšj+ ÃÀ;fƒ¿éÀ§·ŽxJ¿ŠØ`šÄœ¬È¨Ê“\ñJÜ/£¾;¦ðN¥_Eú…Z²Þo5ê÷3á?P+K‰¹ ®¢ü“{SmÀVn̙ÕÏÈo")M€©ºU BTA^ Ëg1d‡YTb€â±Œ¼bvî”î3Ì®L6CEßž%þ“éã'ììLÈjäHÿ8u;¨Ev£èÛ¿«·—°Çï-P +ݪMp7B’õòü  À/¤:31v´ª]¹†¯?œûÏÛšXÈeÙè­^œ‚­óz·~‰OI·-oí¤êÜ‘^\Šº¶C‡gþH%¤!áýâU.`ʱÜmÐŒeœ)5Èçm«1ðl4r_©Ïûê–Òa Î}•él@[ñª™0ðFj`Ǹí$x Hî6æ9“veÔ`bñ[‘&%Dã`ʃÑhö1ִ涘ÉÝ3Û]„¼:¾pÝFæ”óŸ{°mSçõˆ”\ÿìÕLRlkÇ­<¤äJŸØÀ³eAº«ô‰=<±ÅÀ_çºYÀÀ“y Aˆ¸œÝâ¾`àû\'®€ygë¸VHç:*•à8”ƒ™0ð÷¹]ð L¢¹Žj™q®³«@“x cSU(îepÝ‚&ÿÄÁ¤Kè8×seÇa´øú™Ö7Xf·£õÕ]s æöh})'†Be…Ê‹7úù^+ÆØª~ø¸ÕcÅ6O||Rš%u&ÁU»wÀQ\\ŸÀ:3YÕlMŸYEŠëë£(*Ý4„¢¨Å Ô œâL‰ VÈ\]¶ÚÚxÿpn &¶ð?ÿ#ñ¬®–5ó²5”o¡%óa-{ì$åÞ~ýîN¹'`ìÐY/"s¼åPfuÈ=åÎÏäc‡ãP²Q•¼É­ÿÅ!÷¿Qç~þ~™cbêo_äTÕ/!ÞŽ±ÅÔ4Í9;¢âôpÏNß 3ñàNŽeó;°’”ß(5+u¾o‚ðeîþ.ˆðÑ_P…Û;o˜K•¥kŠmŠ~E:½»É‚ÌK_Q¡L—–38Ð3ûxqû¡ýI¦T6·Ëº±¡ÅÀ퓊ѳ÷å63î%ù¨D”ùò¼cc9L¢#À ÈÍ|ÆBÁ÷ ·?ýŠÒ¹ÒL¯Ê(2˜×™°¶_ǻ٠ên¨ýɆäpU¥]8ެâí4Á=Ä ·?E5MqTµÌÜI·,ä‘ßß§q®rÛéfÇɳêç†êk¡\% ÉFxgÍB•ç Õ׿\~çÞî+'#ÿ¾áy<³ §ßè,ˆ˜)¸™+ÕLb®7‚| â…ÕR‹®©%§ËòyFUN6U·)f™\ òu"U.\]»…¯ŒïÜdÊGóuc|{Uöô™g鄟ô*µçöûPûs¬Ýf‚D²sÀ•¢¶ˆV­–>󂹨Ï÷~D“ìòŠÎ9D®æ® MÑt6/· ºJÕ,9×Õ˜Iy¦|“¯ ÂȸÜ&FŸy¤|Ï·£6­‘#ëó‚D!1η]WLJˆ^2òurÄÿJ“6S‘Ý‘K'þŽçcî+»¥¬Y3 äíWeåHÙ#ÇšuõBvÇõûÔ@p8»aVCÝòš /ØI­­ìšÊ]¯¦c èQWœMœu’™yÃiºÃ{{ÍÊ‘XØT:™Ëã{ŽÃ6¬|Ø)òAq}ÚÁ#K âr€|bæý”–¯fHîïè÷|‘$Lšwk7µN\зZaI"5¤VæqÛ`῞f ‰ÇÀÒï'¡êÉ~¿iÔKf*¶oðfIhpcòXŸ¡Nß‚Œèv=éïóX@ÞÎ\öš JýT†6’·ðÎXa2ï±tbú°,ßø±÷®š¶¡Zˆe¸=°@J £lÝâî¨tÎÈ'rQ2ý‚”Av©biopºkOeÜZÖ+)²8‘:?³¢õ~ÃdÈ~¿dÀÁ侀g¿ ]™®'véŽyú³2ïd¦qö~…ä¡ü¸©›öQÚj”x¡Y˜x¼N‹štÕB!ñíñFL+s‰Ø^ŠÞuz×¢‚àÇ „)Æ3^ ™t*<{Î۾ᢠC §ÕÔí>TÁÀûɼšS£‰YÖûa¶Ï Ïÿþ9û©BO‹íxjžâ~é>ÔíëÊŸ-Úôco1ð…˜W“ÔX톾gVO‡%~œZ)ócÓ²O™ìR’þõ–Å‹ mÌL¦ß•&Èo@†˜T$ÞiÍ&ï')Æ òôÅ_0kÅwC¾P戆šTBm¶rVM3¯yC =†*þ¹.¤KÔÞ‚¼Ÿ‡%Œã¤ÊjY“‚Èm徦TÓúšÄrzßžoý—^·ÆìB7pÞÐSŽžc³R¼ªuKç$yâí§ükØ6Õ‡!z’0û86>€#6ëÔ¸Ò2éÈ×ßžDz…ÅÐ+_€lf`Õ¸`à‘/gñ Oä¬tÝBF]€¥>5FžÕ¬”#ýà_‰U>qUå9NnãlK‚üþ©Ø¾RäåÈWpý¢Û’1³­Çt¿ÞéòÕjÓªª©ÙÆžÚ”ñ¶6Z«VšµÜûmÁÀ+&gKÁi<5"P«y{šÌâ–µŒ H <[ØNíž*Òe"¯~ `.¦õÀ¾ûþ@·¦—vU60Faàë`ž>XIúÒù`ÉŸ‹Cj¡ŠšNÁbLnïgWqòÄL ’œèwëÐums¸˜§ÈELT1)r ±™\(,ÆD.¢6Œ¨dæèÑëªù¢ Ø+ÔSþŸ §<¼ŸWkÌ6a êϼ¥á‰>¢â"óZHúž˜»}ý…í \¢Ý¿>Ž»ÔZ©ƒg³ìp‰”Т,€±! fò§(ø¶÷÷ðS†£ï‡eŒ¯¿µ¥9;H·ìç¶4X@wÌу¹¹GÏÜ­åýú;}ÚÚÌs ‰ûí5Aå6-ôè‘v ¤•qЖ×ÞÁ˜Ž¦‹e¡LU+ã—­w–M‡tf@øU¹ÖJ8™î "¹ÿH‰ÝØÎ±a ê‘‚QíÚ×íXgΨ+ ý% Ò¥EçÏYÿ¿<ñq²}ƒ%÷¯ÞæÍþ‚Ï“|Zä­0”C¸ è 4ï~'u#Qa1Þ¢Ko!;ÂÕäó¸#©Ùíë4ºÑ¯ òy¾‘–©ÈÉ.\Yq MßX5=åÓ†¶×-WýbòrJÚçÃÓÿÌ…Íu¹@eÍýþ©_“ÕƒÍÜ ¢Z‹á~æ¾ÀµEbfúÁ[—ähEç*\Ó{'~“ô™T •͹Ykl½€_—‘OŒL)Ù²/½SWó·g¾Žh§‚ß9²5ÔT‹™Ìå÷ÁÌ”}éxÚ¶ÛVÍJÊóZÿ"ýü© Ý0ïò‹²Sù}P€¥Ù ì6㦹jh¸ÍÈ âT)Þ°ÕÀvçøH¾çå:ã9­ïŸÛ8§æeªÉƸÜ+s$·5Æ›%˸Wy I‘mzµÛ¡²›ƒÃ,#HÇ5½›—^ë®n)òùyq<»[Ì:—äË_ΨLH/[Ùi?ñ5AžQY´ÕárT–S*îà¶5›™/lê:å2¬qÌVp9z¼9«_™·Â|à5x/÷·ÈX\/æ0¶þ»ŽxEìã%P{”ý¢Êi„á ?ùŸ?R{S¼À]÷›êr÷ç»G*•Ûy«Wë0 /Ê›†T"ÃfŽõÚÂŒïIá: µŠõ5›œÁÀËo@39W ŒrXNÐÿ~§)Šwà|ômßOzÁT•”sZo²áƒpù~J$``˜îÍz Ÿ'PåËç‚èÖÖAΡtSL€£ß?bÅÀUB(øó«ÙÒWŸiU=ÛŽŒæû †aɾDºw¼ú1ŸÎXµç¯Ä4‘ËÒÇ͇%ãÔ0܆þ™4säomèU¼îJü shgrÞO²`í¤o ²h\Þ“S>#÷yÓÛÚhúz|Q‰Ë2QI†2…¶Ñ¥i3¹i>Ó4Ùw¸ÕGZEÐ1š|;Õê¶5ºƒ~¤ÚC³B}Î ¹ß(ì2_w;¯~qä#iì‚~âÁܾ°–.ÒØÄÈCÏ~n6)Ÿ ¤±ƒZKÃoônË´° VäãJj†˜8äÍz§Ü¦YfKÌ@BA–dsÉ&CWý…úc‚¼¤jM“‰3ð ‰R‡®ÌÁ®5>®v ¾P/IÎ×éÅ2n&`?ËÀ<±0êtáÑôÖ±²] Çý@„8É˼ÂkW·Ã8—F‚üA‚`Pí F9‚ýAjEÀZšÕ–F[ÿj Ry ÔÞOO¬yºÓþ‹õfê^/%t©>îÿ®Æ¡<ññ¯jÓŒ8§þчGÇ»vݲèiqêý$Ñö!ÀÔ8¦†¨qÇ/…ÝÞP¬£±ÇyˆDˆrSŠ„Zä²òKMfêIh5NÒ'Éx¨­ª€µçñz׺Ê>sDe«Iü’çË¢8[%ðo µ¢£N3ñ‰ÛFAÚ‘D‹ÌŒµÕVoºÂÀ“fJ›ý3í?¹s䉓kEf'Ñœ«óqNÖÊÀ'¢5áw©ó± d¯·cª¼#iÖºU‡?õ7ÿúû?Gb8ÉR3sâHz)&=c;,c•eÏì$ÊQ³ºÌ+¼d6´éõ×Hz)v‹ç½å]S?Î}ØF€7ÌM„ýèæ~qͱ¹mq"”ŽìÏñÕ²bfmk |œ´˜U¦ËéÛenü–:ŽGñÎkfªUM8ì:†g±da¼’ áUqà£ÒÞ ¤Kè~uo%ýN[ÍÕ$€ ~°Y%Û=áƒ/¤ˆµÖL5 txäí»`»)‚í†~Ñ×Ï‚í»˜ö….¶ûÏ2ìbŸŽJæ‚||Wº¦È'„ÆY*ÚIËhiüV']˜%䜑¥>ÁÃuÇLCƳ„œ³bAiоæÒO ØY òB¤Ý³ˆ,o˜ÝºÉ’o¿^q7vöËÒòÖ2 µ*ÈOD/W›ûnïÖ•,ãëígiwgÃÈ(]É@´VQ}°ê[]I²â¯‡,.k€)ÁxÙ8Ù±‰"G;Ä”š—íÞ‹þ¸Ð>‚:ûçï¬!ÒªSÌÔŠµz's” êޤݻ"íîÉ}~ü,í^±ŠÍ‰ZÊdÍG¸a0l°;n4ž[9ˆè”b£WÇò¼wªŽÞrj™rffÌõ3†>P#¨§›ÜÔ.œ„‹\È«Ï0mŠå<æ¸2Í*`€zPö^Æ#KäR]Æ} w©$À;rÆ[‘ʶv”aÍwäÕ'{oºúRßö¸ˆ®g¨AzPö^–Sj=¼U3 ¾á³÷#8Gøj zn%G°ò¢ÍšŠLEÈi÷NôÈË)ÆRC&$üÊQÆI‰žd&raZY÷V’Ÿy9Ún³õ”« [éuÝ›Ž oG¯Fé§Mc4ô}0%$A~‘®Ž”›ê~š*ÃýöûAÜÂ98IÖzc—êØ>¨ºØ¦z?8Šûº®×}Ú;GÏïÈ­ }ûAà½Y–p£éGFFþúqæ3 ÓGÏ=Š_²žŒgv§\:´SH)Œul3 V ÈëÏWcj† ?¾2Ø:¾ïÉ8Glêúã%æ_í¬ >¼XÉl¦ÃðD¦Õ”}'Vúö;)iSEºFÕ]/;:Jr$h¼ä>îtÍ_Ïéy IÅú`4dc^q‰Já˜GÜÐùpè ä˜ùøù"{d"È ¾J%–”¬•ºâÀÇY] :ÞDÇûY] È­xe ¼› Õÿ8«‹Odéþ‘|]5gd޲ày¤1ïÁŽ\f²æ³à÷‹€ !F²ê€˜íôh'6†yæÚL_$ÕC$¢F$õBúÃT"jäüºx9Nýá_$¢ gæq'7ðĨ~%WÍßýxïÍl²%§µ­4ôJ€WÔp^*{Mð&ÃÆ¬… Ǥ8;T•L?oÝVÏ#ÇÀYm&Η{»éÅvø…¦»ðµà¶èv‘ÓþýŸ”/õÔÝìw¦sœF”ŽÂã˜ÓQ‹?ŽìçïS˜U¾`f^ÿOå«ÃÀë/¯>U¾ ð_ôBÀ@ÉT/$2% ½ü­xi‘ºhš¼žoI¸ÊßbndÖ£C K—´°J‹ÑΰÉ<}Xú8ßgM1Wµ¨ë7¨ÝGÒDZԼ‚PZ뽚ë}l!Û{JçÚy¾ãë·Èµc4+*_¯Súø­BÏ̳3ŽUP¡wJÓÃQ7v2ä7‹µM+·óËÂx=-øÑÆ)¬ üúöŠ&I8SxÍ0ðþSÔË-ý"úÅbàQ²½³§ ³ 'm¡¥âùIRYÝ#Ý »~­™óøúžŠÜ«Ë²hˆÄ>ß„ÚJol÷”LÈp‹ :5—Ÿ–Å—Åfè3¯èøY–:2ÎTÒ³cÇB>"s ZüžyžÅÌF¸g‘dj–6ËT$a„†ŠÕz\ K¦þu'¦ÆYœ×àaÖ/F:pÆ/¡)I¦ºÒ;•0n[™o­Ï3¥Љùbè'ôäuUaàª×/A¢No£ªk ¼ŸÅR9¶«Ú5&Â{çtx’_$yž#,‡e]éðô°°z Þd]ÑðÔ®“›ÁmE²®ÿ“‰s°ÄȰe–ºƒBP,늆'zZŽéÎk(æ}>Þ†'KTÆVܰZ±CSÝóñ><¥–l]_{c&òêǑߒ ‹”[‚ä½…­ýD é¿R_q“³"n^˜œÅXü$pŠ4PBD^?T¹dZ¥™§xƒ¯ÂŒ“X­Ó _—&¸x+2d¯×Êšsñcæ¡vj‹ö1ÞŽ¤´QD¦õEwbÒÀ¼ø:3™ *"pÄ%;/TåRó.¬j&˵'¯~VÜv½²upáPë1ðI;=J_‡Áœá:|A¦ƒv4µjVÂ骷ERüUÙ•¾Yc3ZŽPóú8[WrïS9ÏZå·‘ „üÊSy2‹*¥d·‰…ooÈP^Ž>r‚¬Ò9òA¥u%Ø‘)žSì®s±`§Kˆˆa””×22Ó·%Èøº¼õøÃÁ’M;à•;¥åæGémÛÙÏëò­¤*7û% n' ¼‚,oÖT²ãK ½“¯Ë[ÁsSøÓ»¨Ì0èC ãu2im9 ëG<@æø Ü\ɱÒÃ>Û¹­ù'gn*ޱž¡SÃd%…2ð…8!K‹šýõùÌôXèvº`NuU; Oï}RQy»™”—v®(òè“Ê/Ï´@¬kY³rò=¨O*:ji,§msÌI§6‚D\LÀºœŽ¡Ù(Ƚ®ß—PvZb²,Øúâš“V–ÔcÕt}´„0ðóPh‰}Â9.³Dzäj†î§Rvû¯K¢ÑM"L0^Ï¡÷¿pV›¥ùVÁ¦ªgÇ¢¼"26—es2QÍš9±ïŽsãÏ?…"7Õ_)¡«¡nê ŸôLm3µÕrÇÀÒY–…”q®ø\õKÑ&‡ÿÀ‡j^B² ‹å=dÊ òrš60‰•¨Ã° /Ï1;@æX0ÿ˜[×.å‚ü$êK¹LLù(Kêf2ù¼Š ˜¥yJõV1á W_x"Ƭ¨ª¾&Ã~yfÆyoæz” Š 2ß(aKò#y3ìl•;|»‚üýJyæq§ð£f~hë­–ãLPe­àº)Ð⺷¶‚ ×w"¼lFÑHç,‡Lš.úÑ…ùUë-f¦ö?1Åeb®lyØbûjò<,4:¸¡”÷sœï•ÂÀ/T‚_N·u¯÷~´x–Hhº ék0?—^r}yHh:K‡}Ûv”ÓVÓð!4 m¥GïA+¬™¢óˆçu/AÛÒUbëß/Û k ¾MÐ=³;Tn¿n¿NÍš¦æ05n¿OÍXÏhjn¿LMÕWtjn¿Lé;N¦æFd«Â·EB—N-µôï?Ïá2² ‚'§Ôóûš:ÌaðKj |Ÿš$·Ü#§mÆ™š%L%À îb€Â˜pã¸Æ÷–Å×[A/öbç['µ = I='æƒ&]22…†3m];ˆM"©çï o༃'Þÿµámž!ޤŒ‰\%çce"_¡­êTÿ=zaòÔxkÙÒnÔ:ê¿Å"à@éì¦ÔÔIÐ9Ôá<…®ªŽ «ß» ËCýšV@s¯ÙšÆMʇúïÑÝR€ÁçÞuåM¾ÀÅzWZ(#%Ðp¾§ÅY¢´|ª–Mb­*àLy=ˆÅŸRD)ë¥;Û›uÕë{=È:ã • ºnµJéÍ’9-þR´«ÉÌZïÕÔídÄO‹?#SÒxìÌO e{=¨ÅŸ‹Æ3ßc7ÙK+ ò0ÂŽ*TUÏͨl$6%HbñçXô›òÚ™92˜—¯“À D䛑/Áðí%òO"ě閰q;^1uf±¦•U¶1Ü2 D-Ž\AsØ;¶µŒ¼úFÓoÜÝî'?w턨FŠÌÅÎ‚Ž…«ä0…žoîeïdàÄ2fïöp!càƒÐ>`Ø5®{|BR¶=sd=,²‡ô¢Šæ ‚‡…¦ôn·½`i0{Ó-âí+FgÂÀ+Î'ä²q­bV÷zÇÀOB ™œ1£j³ôÖäPoT»$.óðêÕ¯Få €g€ò ŽÖ ×í³¿@¬J_¬ÙðDÎÊ}1ðñ&£Ù‹¦pÇ«LGÀ“ŠBå:²ð+»¦ ÇÚ’kØHüùÂǽÎbaœ5ä«ÏÝͳd¼êúÑ„‹NJ:5—ߘ»…˜áå—gî^rUó}óçï¿OéŒ5uvfƒ'^ß aÈ»N¹xVi^€Ÿo5ýRäH÷‹çû4­^‰Ð}ººÃúY;Õ8Þ`à'¦)ÍQŒp'oug¹G€X9Êš˜ªö0¬¬ÈÛÛu\ @#0þî/¢ÒYdb¨SÜšÁ`àçoíù•Ú& ¼ýÜu/Ž®{‚z,+ï%zâIá¼Gñ¼R¶\Ö²E‚Ô9K« óƒY‡›¤aÀÀ9ss{”šÔœô–aà×O‡sÛ ‹"K€+«z| µ²”ì•Q­lð²ß;‹OTÖÒÀ€'µ™t_cà ß ºžVn;&8ðŸn»VVtŒŒÏY‘Ïñ&' ÖIòÍJ³äõ ïu—“–LÔ~ ‰Q.Žg6ߟy{C–gäû3O¶m.ä±4êÍGõá‚|Ï>¤&ðÈ1¬Î18-ÇÀ+:/šÌ“ê½kí»¬d@€KÑ-ŽŽz‘ãqòÞ¿àÊü´ÕhëÝø…YôA¾µ­¥š‰¼úŽ€€l“r³–oÀöÖ•ÂÀçÑñé<@;‘«žû¬MÀJ"Ã~XÛ°†\·àå!!†»¶²AÎ,È ‘ªÊe€<˜œñÚ$f‘Jzéíf o"~V<¥›6½|䆵2˜@;AÞ4k!ÐT£î‡Q«Š~ÑÏæRL}ž­ýyÇ}¾¥9M)VIYh>ä[VåD_7ÙôrÕôíÏ}¶%úlŒçã_}66ûìñÆÉÅË‘^ ^àç»s§Úâܽb ^êã ÷ÝÄW ßý|g"+ÓjUÆÓ`8^êÝ«:Sóµ6øIï§<äã>io+ ¼ý^Xq¬Ë·ž³Ä꬀ÕYÕýZžˆd»£šr’hÏé×y䛌7˜²¯ÿ$m.PàQ‹Š¹E»7ø«“ì½'^þ“¿Yð¨"¨F7y"±àÛd9åö¡±ËÄ0ðd…9¬ÄdãºoÆaà×Ù¼ ôÏ{»¯c_ÏBaàTA§oxÓï}#lƒ£ø£`C·ÏzÒ•_4>!MËG¾c³–°rW |Ψå Ö*G^}–°lÝäÊ7»iÝO\P’}rèë`Gwy={zŽ|“žºuãÈY»õQ%^dµžs å¡W“²lBZ'Åv, Ã˜-üUÉl‰;pïFí77ä‡e~ žç©•p–"9îŸH}líû›4IáskW3µªÓëâA€õ!v"G]Ϻšæ /mÉW®2ø©Ê¶=~ž¾"/Zµjíå`·¾š0ðöp fË`<¹âGkèÛyõ÷úç:rµ:¶LÑ“/Àç[ ¶(~óÂtÌô×#âó¾-Æßê›}7cc0ð“t.¤Ýù¢Ý¤À¯;™ÎD`ÙˆmlNº ¿€¨‡¤—aÍ‹¦uÃÀ;Þ yùD&„jñn–ˆè¬›B¯ëÂÎöá4eðê· G’nJвûª‰Õ]xŬ2м•:Ѹ(ãˆ5žþ.}œ™· ö³­5“^¿³WEÎýJ‡Ÿ:` °(Ø4µ{×­H­÷ôwÁºVíó¸`àæÛ,g©ØYeÔ¶’WßafJ»}\fl®‚}Öõ->ÐÉŠ…ahLðŽ™ÃÀ' Ü–D˜zèt[tÒøB³DìfiÕF>U7tË`Epiù‘|Ï›/·u7|(7ç›þÖÐ7Ú.ˆ–…Ä`NUÕª×ri_¯´½·¼½øHó¤zQNH¬õþD[Uc½j üº9Àó¸wÿý'—M6Ù@[˜w~6嬸~'‡ËþÒ¸ì-³ƒÓ°t¿I1´9sä®áÖ[ˆ \ïßx޲’¤k*¯¬2jÇÀOJ×ò¸}ìô±Ó 1ð†K}ò²¿ÑyßuûŠ_„¡-“]jÓ-F ›ÇÀûYûжá’\/'HöLe¦¦•z™1ðL·Jв6õ:´Lº–Œã[Þ(‡Žª6Á°iÉ€Z <5ÿE»tQãΔ¦!ÈËY =Fï^¯ÃºÁN|Pᤕ«iÇn\f¡Áëû}›rŠjƒ–íÚC(æJïøkÚB¯ u¿UKë1°4þáWÇéÆX*_™»ä¯¬œí³ª5Ü àQ]Qu÷_E¼<—5V×k¿»„+"­Ÿ…Ù}ØØPÁW?ßµúJÙ­®›ªê?ö!M#ÔG EjÁíJÓUfŸ‰e¥k0‡ÃÚ…pÑõI¹šp{Ã$ÂÍÝa ’–K%<‘IÞ·bÇÀ;–êʛ۪ƒ5ÒƒÃÀ‰ïm gx½ÖŒ|̳8Hx"ã,¬³‘d9/Jf‹[j®½¹|`dFä¤MS/yÁ2è%¯ïÆiÛ¶#BwÅ$¨ )E u:#L³VùyTwÖJH_îƒÑä KgwÀ9ëxÏü"}b9/ìl»õý½K[÷d_i¶.[GŒ÷íÆ\%=Až½UÜÙ÷ªîºx®ï$ý;ŸÙdäÂuÃYMßý…h”*›?Å_Ó"жîüAjÆ¥“¼B­]å8ùF§(hÒ=ι0îÄæêm^Aá°â?^ÅÛcµõµ&È3fMÇô>ElÚ%u5“w¿^Ñ9]T#â×´ýÚ9úFWr¢ @ªÑ~ ‘¶Z]j»rå}¯Hœ|Í+9Óóá²1¿x?³þ硞õ—vùš¾šçÙŽd.]_oÈ]6VÏAméßùƒ2•žlO·/‚,Ïì¥2¦¶ä×oÄÓ"oÝ£ŒšÝ0¯y»|f WiXʽGðÏay’ÅØÒœßã½8ë˜]ª*Zy;‘ª†¶kÅÇN{»£¾„rºí#´&óó†Û²ŠÆù)âóGGéyj2ÂüŒç¯f)YG·×Ù†Rg•èv]­Òéõéxž%£*“À“ÓµQñ®Ûõd§½ã’‘ÅU+£Ç0-eRÓhU ¡Ù@‘È µ;¢Éø6É—w¿#ƒÖ’¬I{HÜ”§®#ï~¿‘†ö¢aÀ6[ ­£¿~;¢ŠÃéžMñÃÏôоFô ѹ5žI_± ŸàÎk¨›«Àf^Å€…¾ÑëÌã•ׯ×iXÜ”+2Cî?‡…¨Ê­²nk?©lÉ=¾°rQSêl¬Ó YïO£„ôÖÙe È“×ÉU¡ä¬µOÝn$£ô¸R)ïÂ7oÜúª¯ÉêxÜ02³wÒûª{CÞ!iT´À‘+ç´q3ùîS1dï³ËrÖJ·ZªŠ¬÷Çó“³)eü¿X_Œyä3T‡ ‰1žÕãhTyæõƒßTœƒšÅÛøîÒz ÄÉ Ò(ÐÄ{Sg]? DýJàþÜœ„UØP¶”]ó¨O*µTm3D@ÈP„ë k|a,¹@‰âúÞ¯TjM³$ö©ía—C†²pOéËmQ“Žû&ÇÀNO¶P·M2~qøƒSѹ>1,¬m6k!¹}ýzçÿ'E­ÝeÔ°`ÖÕÁÆuýz§KÀ 8¸ –JyI¾ ¦Kì7àôL7µ«˜gcÓ%ön“4èl^íjýõÕxß™KÞûIÔÇâzö+›!Y:°¦aœ÷­ ŸÕ=ïã®­ŒôŽ|ÔÞ‡3¤Ë²²8Jz%È\žØá¸Ö›°ÍÚ¬3LLjÐùáï<)¢tf8¤YE|—™O¤EPlOõ ³òk[ <%­…*j!Mw×xn6ðÄòÝ“EõŒ36ú¾ï<ñN€ûEeë¿“»tªi‹Š,® Ø3®wTŽÿÏï“û–~šõMQcà d‹+û®·É !@:üz§Z;»’E7“Ó 4šë‡;xѳMÀ!{ÇN@S®¼‡‚uI< -òDœŽ*§DŒñUÕu Ê…×Ç»­lAZIõ©K¿Á@Ò”—·?îãõ·7+1ð<¥Ô]‡¥©¶Ÿ˜7•íhfáÖ8Ž _¸¿uŽ¢áøÖ7Óú¬9²¿L:› ^\T²:¤{Œ¬Yæ*×7ÍþÌL~KÔ/†“÷>…ƒ’n{ÞøS4º6Û4냦£ª#_(uæ……¼Ð7).žHæØ¸Ôy?¤«Hó†uó¬òq*³¡LDš¡ºòùÏ*Ä <ˆë{º9Ýv‚iÕ¬MË<¯”¿]UéÑlÑíÄÎÍŸ¦­v+ÚBo0ÛÈ5‡RÒ¥­þäVð|Šöñ›7½tP’»¢´ÕŸT‡`v½ƒ«4ve>4ًͨªæ±^Þ4ÙërQiÖŽ)1W@0½þ¼3ËJäM߬bY0iAƒ^P¯’-…wǧAi«ýže1½ Z¹A{2¬xŪ9,›MÙK.0?2kS4u»Ä;ð5nojõÒ$™ºÚOH9Ôi†ç°Ü˜øðní}Ã`IÑì^]6å—n€ªÜí“CÛ õV«NýB€÷#’{÷öÃ!FAÜl:döw”1”ËÈ"V6‚<ñIÍD³ò™ãtì-…躸‘…&ôøOÊ„ÒÇ·~¢M D®š=7£ÅQJ_â´Û‹Šðd5¬ýØŽ@)C€§í’Y3"E ºf}ÛK ÄLˆ¬šÕê­Ò›óZ“'Þ¨f®:˜uû®®1ð¬B Hpãæ9^¿%ÃÀ³÷Iì&ï»LH×ÖñFÀ: ĶKEhVë6N[ ¡|£~§SHœÞW¶¸ðÙæˆ'Å+%·ãľý¼bA1ΘžÅVo ÑRPÞºuГ1²dóËl[UUn* ¼áö£<à©ý(4J€§žô'Þm’ñ²Ã@<àçûÁð%7ô`S^†ó¸Ç‘¼5ðK5)©Åzß©ì†|®ö·0@ãã]‰X 7ìsµ#³vkBNuüÙºä÷?‘®¡ÈËI@ƒ×]üŒ÷~ È#ï¸s¹Çxt*ÄËU[ä !˹Åmɻۑ~dÊ&õ*/jF‘Ó„uS˜¦Ê›Ö‘áü~žd]øF¼åM¯†JPäë4Í=:›fרPàÊ.ªß‘¥O}η©ËÐb f ”î«P ÌlÚò-OÕC<«tðrÖɪ@€—O£Á8‹¶0úi[1ð êP<•±óº•]רºq¸¸¾óø*YcKÒg~« ÃÀ;Îjíä²V¹.kuôÜ¿ o —¥ßµaRŵ€Ï³¹.½Ð³(VÙjÃÀj[Îtùv«ëÙ±ZiòÓoK¨º°·­WaŠ6¡û÷o«”2½Oâ$ª® A½ ûPeQǽÎ&äGûA¡Þv 5<òúÑF‘Ϧiá}¼ ÔkÉÛ`›Ù¿µQxè0oR\\”Í9†¯½eÌH<î\ÿMŽ,+sŒ5sGþF8ºStïÑÜÉâ3ƒQäµs—ÉNÁ?2&½Š¡¤î-DKoJ3Ú]S!fñu§×µ¬¯Ç…(3pú±Ž×c¨->>îïE»*† Ö¾j{ ¼â¦Ê¼‘OíÐæu­0ð†ŠM¦;.zck5%ÈÇ»% ´áè¸Vù\/ÃÀÇv •§y¼m/]7 ╤9?€•Ôx Ù¡Òï"1Š]d;cà…ïå‰ÁÆ·ö‹aä‰7âKŸõ)ç­“mX¶€wMî<‹¤dÇQ.ø÷ä<”¥Þ„ީŋ(OŸÅóRU1(é§©…¿ñöÎÏM&Églûaä.²`„¥|7N¢ìÛÖ¶ŒxÜP;Êÿe­óJŽ£fêòÄ#>d¹Œ»7Lst |1ð””®÷kþnK¢FÉL¿àãìz’°«lëÂ犵ŸÿÌ}WP-{Ðã0‹0ä¬E<‰kàã_Æ“U?Åo¸,#^à&`9²—~}íê ¯¤E2ç²únª¹dpKÇI /ƒxã¿ÿ›²^û(æU6HÈ¡2TE"l—æŽ7àEa Æ_8Û·ñ;·ÊÀN,äöæÕ¨[f¥—Òà ÞžXûƒ ‡,äR´ÀÇÝý‰RZN€·wÝ&k 3(ðŽúóè´jigñ^³bà3­€G`Ãß¹ƒ© œºÚƶLNÓ40 |å/ÅLuu¹®¼ë0ðm{{ý?m{ƒÐ‚u«%þuîMi‹×[çºa–p“|¾µñª”Såoì»Ñïâù!XÚæ^¢¡õ¶­)ð‚Iðù«CÜÈ­é¡üõ¤Q?´ v`g ôÄ?Ï;Ú?¢vøˆ—·{d1_h‚R\A”„¼¿þÚz´õe¯x~œ mYÙ]Üü,$|›;ÉgÅ–=ÿSyîô8‡/XT5Ÿ]S5° z+û‰´K0Ä;ßÖ+l¾çýMlv€fQÌÕ#‡$Ìóþ&'q0‹*Ï=Ežø@b1%>‹ÀD&ØX…ODï)YS±†ój´¾0k'ïgÊnJ삈Œ#Ú|0È­Ú¶¦é€Þó¼¿åVÓ`ú¹]äìóNÕÐc+2e¨ÑV¼SRäÑa@¶³ï;ëW9çý”ûOÎh—lI ‰Wé»y&CtŠqži÷¾kÛtsëò,ú ÈêôŽV­é»?d†ûyPqš¿!Ïæ°}ÜÓCG;éøT·Räë_vl…à9ì4>yÄ Ôž:ÈùÿþJצçI×7`ü3 q—›$ÕŸ@W¹?4Q ¬gÁ~ ?}Ç-§ ä$—ãä¯ç™õÿ±;4±rçýäð õàÝÏ*'¡ÙY\ äo|¡x®H"Pó…n0ð‡w h6)nâ7TdÀ¿ˆoÄž{²É7€oÄÄŠ†%Z²ñ\d*µ*äåÜD&ÍÜH…ýçIù€&z‘ƒh½Õ5¯*Îf‚¼A¹ŒiÉ3Yû8‰AÞ©ë‰ÌÉí…õ³1#A>p¿mÿ¤Œ—sÿòù/犩XÚFä“älÞ}&˜1çóÃùQ”žÅvƒj¡ûéù¤Î{kåž”0 C×Oùù¤²PßniX;tèR§ÌQ;Ê?í*áz)j(Â?QÇýï)2›#l–+>@hNücþ/ûLäeƒÔÕÍñ²/ÂÙÜ· ®X| ‹³p®!ó£]#ãúŽË[ÿ¢ÈÝ=ÞÉt{  Ãõ|¢\}A¶;µj²<®p?àù¤ÄI–iÇjßùÐÇyá òz~ÕБ?öÔNCœÃyCÈ&[}Æ£4îÖ4t ÝÑvPZ\¼ÅÛÁ“æêÙÁ OË\™T£&È'Ef>ФSO•¢¿þBB¡ç6^îÌ`f21¿#­“Ò;ÙɆv•%sý/î"6¹‹,q‚ü e*NùµQÕqm$ND˜däð‡¨A$& 4½¥"EY¯/fecP™³VÝäÅñüë­¤ À£nDï–j„N¡×÷ÿò6šÕ)8äôWà6—mã€y©Ûj-FÖéuû@›€^00—+ÐŒLv#^ÿ´=›a¿n䲜»÷Ýß&ëÝúÈêc7—tc­ÀViLAuÿ1‹ÌdR;Ã:àø¼îD1›bìQ‰‹ÛL“Ÿ¾!OÛBÁŠßzÜÌèáÆúºÓ¼Q®¸¤æÎØ®ñŒ“¿‹h6e€iãßÈ:òÓOÄå-z'£ŽÇÚH€¯S+,÷}ÄEãØÎàO¦èþÎ̦â)Ëz=V¼%Ãsö`îà¹oä~í›ó|¼9³+ @9®½y^c©d<çjs¨ô¾þJ½ÝïxAé•1 ˆ½þB½EÀeaïŸîu<>go-bêm›ïÕÈkî8>±àIfÖËJôM× ‚¼Ì ϳ|#[M¼…Z«ê0'P–{èÐÇp`Zè€#þ¿ÈåµÔbÒUè6‚ü>0 ñÍ ¿A^È5¦ }«Vkýõë)MÚ}ñ×õª}k‚¼IJhãÝŸÉIÊ×cûŒqš§ºg£#²ÿëŽ}8í¬Sƒùìò ™ÏSmJ3=ºEŒ“'È‘ÄÚ~í¦!-ÈŸ³à-Ц¤ nd¢³’|õb`vdÉ*¸ÙUvØÖ7ä÷9A”ÈŸS2]Сa3äÄ´÷x×`ðÖY50Û0¸Û¿^o+2GM[1Ïâx¬HVÃ*†u*ŽÌ'^0ßÙ[=ns¿l¾«0ðdþ‚RIÜ,—Y¯î¨:¿ë&8HE®ýĬÑíÜb &–‚¼ ‰Q‹iÛãÐ¡Ú )žËÁoÖFNp^oÚ uvËü¾®dÉuT‰þRɲ«ÊË·ïÑý H$4ýõQÊt¹:n-îâÄäpN¬Ÿf:´õ• ÏÛìM‚¯ÄÛ x%Ǿ³0oLAÕK)KýFÜ ÁeØfª\vˆI„p쀷Ÿ¢qm¶¾÷ç šÊœ Tãâ¤ÏÞF#¯rã_eŽq˜å°5¸÷é;¢™Á²¨÷à–ùØtyï|Cn†l4¥¼€ n)¸^4û×éaäE¸dšÈ0~œ!¿ŠÑ5-‡µÜá™þ¶)ìÉÞóýšY}pm©!»åo¿ízfê}?_7Ú=Äõ¨ÅûËî‘çîééľ}m¾ë–µž›â‰øÍÊ6“ç6;×ú³úž ¡q÷V~ß ¨,Ó55övq’ûŸ`›eÊ…$áÚkÜuõñóÙêû‡–ˆnDÈê×9"oÈ‶dÓ¼lIÈâpmIùfKB‡—-ÙLB‚- Yþ¾ê¿rg3¼e„ŸgD=îÈ$-ÝYc†ÉàÞÏ÷0‰Ki–ÚÅ‘£)}ßO,-7Zwn4¿eu…ÀÃ#*>Ç^ÓÝu‚ %‡7[Ò‘n0Y]‰é¥V#dFpÒÎ%ááE¿îtoîj½—îí!ð?t_¬ÏW™Ò#CJÏîš’4«";;õëìÜïþaV–~hV{0úlé‚ß©n¯2>,ê DjèÙ¹v×û˜*89Þ&nXB²d|N¦àäÔ62³ÙâïÐcš€ÖYëˆs%Ëþ’ñ9)õJ×½=ö~P‹È™üÏ“%›•þ>Ù ð맘Ùz¨Usm 2±²ÿŒ,RÉ•ÛÈøDͨSt§çl;Ø0Ž#šðì‘‹eñëáÏm+q›g „ÔŠ”ÜóK«&%Øœ‚ fDè±e#~_¤™%ÙL†ˆ"­* èùnsÌu‘Fð^7HQÈKÝú fÁ&‰ã¿a×Î Ò¨C–‰çó š'ŠB‘ÙŒn¼µ¸3 Ÿ|‹ÒÿÈeu¶/ªwƒ)|‹kß&]¢¼½ç[ÜEsdÁ˜ èé`¾Eç2o]á[¬.=4˜@£¨Ý«}E->  =Ið” …õ®¼!*¨+óèÊü¯ ®Ìw™87'«¥j±î¸ÛYíç‘Ê© æU·³Í@+£uË Þ.2ƒL*ãçq%£¤cXƒZ1è…\6:*Öês05.>¹te:9Ï}O²XCõqѾaÙoçœdÓ¸™×³‚º2˜*ˆ¤M°ƒÖ(S†oqRvã\Bà“þir±ñˆ;N¸å •‡Û[ü„•¯)g/Ãév€À¯“Pý$2ƒÝz5+šžï·óâôD” ü$ìÍ.~ѳ£]6¼aÂ…p ôãé°þùeâ„+Ï üœÇÄ -î4·€‚¬ËâÓîè'&ür‹/Eö,r&´V—¤Í»yÔ~\7™†J–‘Ñ\—Q_w,í, A;d$lizù™²Mw¡\ÿ¢–‹DÀ2…䤢Alí*˜+ÇÞצòªö7— ®/—fÔ3²áÕ&¶\È ì1eJ¯ ¨gÄ×/11šQÎäšðï©*‘xºü'´Ž oí¼ýŒ)ƒ™!°Æ¿1=«È.ìzœ¿ñ%%ÿELŠÄÜó~<¿Ìkè®,Š~`½ eÛy™QŒ›Jφ~àý6’=×.V@#úÛ’³'Û~$ë>òk`n&I鼋Á e_W@^=úÔÊaŸÏp™Sl« Þ ³°öùú0o¿­;Êꩪ’ôøDŒëQ «4ËŒpUuû¯ ‰8;”Q×ÿ}sÙœ~SQŒ·7—±xUòÂì= -áåÒ oëÙõë­Ðf[Jn„¦M&’ªª;Ê$'Ua¨Bèùª ÷ŸÀèUú|œ‡=/4þT6Á¹6¡Á|¾öˆóâ9Fâ#ç\¯’Bà7оæßÈû@âšs­2ðyyÛ,‘Îÿˆím™žÇ+Ùs¾âü‚Xºe'ý·+½¿ÍƇÿ2ûn++ÖÈøÈ\›‹X¦æ ï014%PysfÝÖµ±Aˆ¯°_°cX$%[ ðXÆ6•q‚“…hô!»N~¸OÃ<ûÇf›”» ðûòÔ³üžñÀQ­ã¨|Bf€Tèç±³Ýbñ7âKD÷Ìäl6¿>)Ô®UõõbBƒÏÿlgJmx{œ…8Z¥V¬1°Ë¬K}·ïŬ¨¾^ÖE{µ`{Hž…ÀZ@ÑR œBÞœ™³š_5Crfqº’<õû4ø…虲¿¸÷?x]ßSµ®NAàSõûÁý-ÂÛÑ„ î×x×°£’jAM‚ŒêȤ¼Àì˜ØDÙ$Ñ”W··HÇ©›ðϬêwÈ9´Ér¶QAÞß"]CÃsœ^4_ðR™QÌjV÷þ‰dd‘U8¬í9CÈ/À›(Õºiœõ¢ü{rDȳژÒ3!xœwæ¶¹˜6Õ`FNż [MÍ4¢ÛEÔN“Ë/.¤A8iÞÕ;ä‘-úF·äT-ȃ ÿ•F4K·ú-Òy$9BÞ/)–|„-´MÓ)UZÀ¾*™J£ýKhÝ•À¿¤¶œ”û¼QJI¢ÐJ¾}!d4ÄZµ®Ö}Àm~C¾Ît¼â•Îu[f5-ÈçéJOˆ R=uT„Ôe´BêaWˆü¹PAßN 63ò¿èw6Š4Æ©~EM Æ›ÊóIÔl¶Õìè»×/AQƒ™qÛåä¥&¤çŸ…žïƒ” ªö «‚ÙÂÛ¤i:´’ëÏR°óûR¸˜XÒºÞµ!Óêï¤t¤o[Üæ©âKcn{èê;JC´#Ÿ v^FofL"á=>á?^‘T*0#“áYAúÈ,9À×ãh×vEçÒý”›ã´0+ßžõV+2eÖ9‘,Î9²µd îýŽ()¿ÀÌÚX㋾{bFþ³ÿ“$Sb²œ‡Þ~,&v|6‘Ù=H~7í“™L ·ßtÀDïÊŽK¥é™aä½ØÞ 9K«MI €c3…ðåÂg…hf=Ùæ*©n8+¹)Ò­·{?ïd@-^”-´(´Ù•ØÖtmyö ¦œ›³¶ï)é,jñëàîSláOÌ%ÍÔ•nß{º3º y|^‰í¢ä±º½^^&ü±IÄq¯áá®)ËU@hú!Nî·Ã^,¸·M]bc JômΩn·@Yʯ…Õ‡Ðo¼2½›×… b¶F¡¡|a-ff5Éw<9)ÉÁF ð+¹ß};ízX3d~"RÈb4| lòø…8!OàêøaÐo5qE2Áù“J->ß2B áí<=É‚K²#ÑÄ ûËNÎŽº/~n t•I–h2Ãå!œ¥:ÞN’¥õî5ËHGÛ@`}²ù“n}§¼µ­Ux?se²» ”ÖØq±DôÀÙ/2o”»’åÑu«AÂJæ™OêÅJo®K9@  QËñ™Êíª‡ÀËg—9ƒý`ØN­UmqîÝêJÓn½ûaÓv†¾LøGÑn'§È;›Çc¥~Î1²úIv&´ÜgkŽ #ó£ëˆoéP“ÚX½ìEsžŒk\BêFøÔvç¡vÿ¥¸9ÐÆÝBs:QÞ~?.JÌàöò¾?©#M¯½E È¡3ðó˜‹È†+–¯åºÊf kT$¥¼áÓ¶žkò󅣂圄aPb™ö!3üV¯Êf§žÃhHÛõÆîW‚E9ÊC×{?É\‡XÝ>_9*²B5¤‹1µ5…r¿‘í:t›~ƒ ¿6qTô²›ÅDÞAೄøšÄ8„‹ ™¼QÝNšð«–IdG€¿6ä|ÁMæÀsf'"ŸHÏCvÊúãx+HN‹i³6„Kã^Ú¬ÿgö95Z6¢›g} äÈóÊRÿ½õBŽ Åȳ¼Ÿ|ñBa " !/®ïSË©ÝFFŒ=Šauû|)/Œ«2D ù—±ã!¿OULኦÃl—Åß-ç.ûz 3žay[Â"Ýg<ËóCoÊ;•Ò£]ÎKø6âv,šÈ–ú®ùbÎíˆrþú_sЇ¥Ù&ë s%2wûþoZaüÖ†JÔâï´6=nüF–éœ7þìÜó®¬à'J’ãm ×JBBÖˆ³xÃÉÉ›Ó(ò—‚ÿË1üd/q³©±/ÚÒÈ®…t{+C'·fF-ž ´á$H]÷«öF§šjñ5„3!ÊÀzÅöY£W|RK‹ÙëA:süDb9¢t̳3MÎòª÷üEúŸ<ø ñW$/þ‡úŠ ü›dbD‘oü}ODÖçÍÀ:ÿ€·úÔ‘yóÏn!æBdãf³~ñø»/×cdà‹udš´³M}ÑYü‰ÔÆ.P¢®¿~&ÇËÅyü/EdÜ ,OêºF´Ø\*Tzq½iÌ™’­Dú‘~”æp§g¶t}3˜ A4;(¥u9èQ·GÖéÈ@\JŸ®’y#k³ÎŠAà%¡—Êci3á!«¹åxÝu´” { 9ÜÁÊ£¿Q†œu˜èC×Më¿÷_ µ,;FzvÌB±3†_ƒØsÆ\£\[õÏò襑Æ5jopÞøa9šž«<“¤|ÐHºûgKoƒ&&JµÀÆŒ«\µBÈLpMû+$¸nr"|GÈúQ)ălUŠÙmXqïwô´‹ÝÓF뎸…ù€å Ù4lm³^dA~^”<›’2ví¡µ@Èdüžª2ó•úo3±vZE©®%#óGgnÞXç j´:R]K $Ñp‰A„e\zw”"¥²Ö£=rœå™‰«'0›ÎnCmFçæ~ü)ÆP\Ädtßiƒ¾ûíRæRr[×ds¬£EÈXù$ JHͶÈ÷~VFÖ !„ìÎÑÍuù(ŽžIªƒ¬¯ßÁ£èrÂ^A{ÄoŒ&ÛHÕܵ™« /íQÈå%õ¾7&'´ä7:e’•㎗`]ýø„ϪZþBY7³ë¡~¼Ð]Š#Ð’(6òǨ¯Tº<+eéáÐ;1û÷—2ÄôC"P×€î ¦)&Åw¹ø‹Ç¬øy„gž-—S a#øùÂ]\€ÖÆ$Ò¶øëO”õ’BR¦Ð±Nõ;Ö¿S*žóø…ßߌÓRIÚ˜•6––)ËrktU}G¼ño ðVZŒB¢É‘1~›ÛëŽÂÒ ÁG’”üÊ´ž4ë ð†…Üóo$ë&ĺA`]–YÒ0íÒÑÊØDìÐBà½øšSãÁ­³›UOWÔõã£È1¤#/Ùu@º!ý ›–qB¼IÂG _ØÒ¤c§®CèªU î ­ÙHP;Q²)&4ÏßÄN6¡Á\Õ®áêÉB÷í.X§w)×ÑÞè&ðŠ!oÐç‘‚”»PÒfŸg„¼G©ÈšY:ÿÿ%S‘Võ‹â襷7ë*:÷Úû¥8Ú…ÌHŠ®„-v$ÝðFÅTÉ} Kq”ð<ï’ÍRh"éò”Üó¢k䯾f’}Ë¢8 ‹CÕ²†Xfæý΢8 •<¤ä©FVXÉ3^(FÛŽ´;G½ßÀå1ÎãBÄRb!5TM•1d#Â,y‹°sFžnl’ÞP)³Z>Þ½ Vg›ÕívB[Gô‰\ãñk¶þk éšâ,­¡âèŸ?YCUFÂ~ÂŽaæç*Ž&¤( ®Bjµ4%öYCÅѤõ“Ki[Õ,"Z®è˜9cŸ‰Þ-r'NÚ›šÚŒhæë3öIƒFI,Êhz×-¥BçG}.¢ð5C89ôn¼¡†ÆžGc†edeð­ÚΚƒ÷Ú ™¯qì39mÈÞø%ƒ[<N¶…mã×gý ¢™šÇϧÒBÍ-šÏúëW=IÑàßù}Ñåñœ¹9M,0ޱ í¸¬8ê‘¥4ܽþnt†dÅÑà‡Ïâ´–Ç-ònø ÉŠ£á]ÌZV~ç¨EKzƒÆ~¿ýª'Ù™ô6þ>þ¹œ¬Iß`U#šù¤8Aw,9u‚𥡮ëp›3 ŽÓ|Ú´vž‰7¶Üæ'RžLÏ ý8ªnG3ŸGÃÜÐb¡07ù—¢>ztµ&ÅÑ¿c‚[›Ï%34Â~á£óó˜óŠùêÛô–T·´B’â迉þ4ß2¹zÃÐ-!«É‹7˜ÍLtí÷¤8úï¿©÷dû6çCSS²êKq4FÃ}Sm÷“”)z㈲RÚ)‚îÍÇãW¹ š N*(ôN®BørÅ’AYÐ;O¦· 鱯{ù”@Χ¸·‹z‚œÿ+¹B÷ÌE*ÌXA\[È)+ çóWæÒO,\Á`wT±¬‰š0±ðÊÐvz6¦øîÕ {^J~ ”UJqè\r—Ÿ`óÛ³'Îu.³øÃfÿ'ìÚ–$U•è/uU—uyœ˜ˆ>ŸÊEP¼ jì¯? ¤&VõÞ1/+´Í‚$ÉËZñÂÐ׫ðû|„^³Û%“ÌJ'1³>øàÔTÙ«_8WEHÁwÞXi" ~PYPIT† ëºD½H$e®s‘ª+ppÚìoLeGw´Ú+§1æ7$©š(ƒ¢Ù0m޼áVòHü`ìÀ¼æ"[Ç•Ÿì¼Îjlæv3ä‚w’ÄX·¹Š•4|€Â’zÚ©ÝΡ8}–z*#ß··mGZ) ÄTÑ©3¶Tc5' ’zÚ¨P·©ßM*Ì{@ÃG_·ÓükHcn¿¤Ö>ìÑDv5^s`Ø;ZSl[Ýbà7’2I4F){\ÀÏä˜Û‘¿íWÏÁÿ·xEmL©áiþ2i掞Ûí4z ^Mk3jù›F ühžrš8;ÌSüjžÞµI[ðr+~5wkÚµp὿™g1šÉACŸ×í~6ØÍ#üMBõ «#åæiý»½yx‹¿™§šªÝ<÷¬Ž¼Ý¿6‡Áúªå ó§x>N Æ»àÚ:·½em0ðŠZ¿SŒÕaì²hˆ/oy#iôÐÛW+ï¡—–®o»7ƒ²ƒ p¥¡Ð¨};IÓ<‹ÕTÑÉNNÜBS>=úYRâ 2SåF6Áí‰ý‰lúeäíÀeZmRÞ¸ Ñ£$ÿSÆ™…œ+¿­ ¼¡ãäû(ó3®Y ܧ?‚ áo(¶—ücbÀôë×; óLÆa* |` |Œšï-—Ÿ¿ÙQY «ç•ñ5';nO,ÕhŽ-ží(#p!S?U˜Ûqóâè#°®0ðw;vPbBZFÈŽ±˜ì(ÇìcîgólZoãâŠ/Ò2Š %ƒ¯޹ïúŸ˜ #QÀšáuØ_]|e< 4Š_G!du# ty).o#F1´0u/æeUC‰×Œ|z˪nDÏüÏìX\On/íÖàÍ|D3¶Ië-¯X<*:ÈMŽJÎ5ÌûɵĆ%QÇF$eTc›¶àcöépj÷Ž®b? L@Æ”bè0ðû#°±Ú?qÆÀ[Î6¶e¼*üí@Aãbq;Ÿ ‰:gêçFðªM:È—âvVC€Ùa«±†dNñ6È­zmU5–0/UÜ2Òˆt½Ù€Ž‘±dk‹>>b¥ÎÇíÂÌfîÓÝ¿(ÞátåFÊñ—ø:G™_= nÅ™z: .Ö’#œrrÅÀêûM½¯ƒ[ ëgÐ NÀñwAÏÙJ̺¶%”êŠ=A eœÛµФP»zR¬H¤øÕßÉ$Hë jT™zR¹);ììÌb{Q[‡»zÒÖí[ò;“¡*3ORO átÝ–¸°³ê)6³øå‚ZÄRgÒÒHîÿÖäÏŽP”øêû$>·¸£Ìó¸ú5' J2KèÕ>vÝ;T‘àÐÇé¸Uƒ%Ÿÿ1·fÀ™ŽƒC®@çë?1ÕÔåÌ, Ð Ž‡€`&Ž+lÀy† nñ:·K¦5>Ùvz¿ÔÒ߈”‰Ò@Gñ¾¢í‡²7IürofˆÎ…“ ”Q‘2Q6N)Íjª§A˜oè\Ø'¦ÕK—äÎp¯2Ó”ýüÇ”COÚÄP—€Gªß‡ÃIëHÑi^–Ú…°ÖѼBz؇Ã]¿´+T™±ÖÑŸ£Ì?‘¹N=ÌÙ¿?× ”(¬u‹ð©¬at>P¡+H=)é&ø¿Ñéiï7o=´ñ©jÉ0Ž>2Éé8êǨÍÐÀÜâýÃE;öЖM¯Ù‹¬÷ü¢MâIäZêû¾“ÜeßÊÂXH¬Ù2ÐÐb²w#mj„\7dþÛ\®rk» aU†®¤Í-” '¤6”xdþöÛÑܸ–­JMœ÷p ¹mH¤^œI7¢sj‘»£‹6*K†!âuªªu]!ÝšCï$e変q¥›9ψ^‰Ø¡oS¶RvÉÿ΃_øA¤òa§œ‡9)ðÀZÿÚ›ÐÙÞ„ÞxÔ(›>[ñ¶õú§´6θ@<ÒdKn+pDdç÷ߤ ¤½ÚæÈói»YÞõbêÛ}…\3ö!Ü\>CO×VbàõNÙo 5ðU´Ù¿îìý.JëA¯rŸÊ@ÊU©^½ú `3’DyA:S ˜ÛEŒÞÑQqV\гŽ"q'ŽN ‹´ÐF|¿å´€›y"Ð_¿æÖ΢‹90ÃÒÁûgÅš=ñ–MýE†þÑ‘ÚoHÙcàÑ¿jÙÖê¥_¸¦xÏÀ6¿Á9³¬õ›œaàÙ%]J3ÎV´´› |"Iû´ [¦‘Ìzî·SÊïd6FOô3§ÉÍÍUû¯HËj5gÈK¦Ö±e0cª$´ë3!–jˆÞ™K¿ÌZÒäÈ=ˆßŽÑHÚè¯Ü´o—>ûuPG+ô—‡,¸½wóg™¢Êµ!]HúÁù~;w´Bƒ0±]Iæz©s+=p¸û†Š¯TÚ¶Ï­ô<в$WcUÒ±|Qq5Rs¦Îo‹¥Ÿâ¢hÍ1„jÝY‘¿?ukÞ€7¼ÈذåµéL­v˜kÃr*¡Â¬Å"¨ä^¼-õ,Í$­wžoÓè…³.Œ÷ó7Oƒø¾[´óÙÁ;šâ>$¬6yçNô}E j{ÇSÜÒDduB^Ž,T•òÿU5M~Ù÷,ÿ³C7uI¸²²>Næs†Ü9(ƒŠ _ºZ”VÁeç^œ‰šÖ¤Z*—ÌɬžˆšÓ!‘Âþ1Wç_[<þ"»7ñ‡ÞÀafô^ ®‚OÒ®-„éHÕí³Ède°´Ú‘±Uíéã¿n1ðêçÝb2àõ_nZ|ý×M+^ßuŽ—Ú5-þõø8 "oææY:ט€à}&€ÂÙãš1N“]'Dée•ž‘Þåñ}æ’Šã0ˆ½Vþü‰‚“ݳ2þ*Áü¯SA]ó‘g<èÎ9ù¿qZ¦i•ˆCË4"»ø =1N'à §x‘Ñf±Êã8n÷–ìX³kæý<ô#Þ‘Òhj‹ˆCÄ㜀ð‘·;oOܲú¿ˆ¹*•ñ¦Fˆ•p‹yÜÞD{R ä7Aá•ÙW'Ñžþ‡hÐýÿ'3C&}ªð9 G&sË@óMÙÄ\˜’5TÑ« fWB–à˜ CHë×xêaÄ/­ƒ–Éf.ܦ 9ÔÝ2ËJ×ùʀΦŸ]¼&ä\2öõ¬WH ZæcÍPÚ•9§f0ðº3îm]t[l磌Â!†¶KÀ¥rå°ÊÞÇmnÁÀÛ;»b¬M{2ãqÏ3 9 Sw0=Nr‘”':"n|@Ò­ƒÌ€¨6 ù#n*kCûÇÀoÔ§”UU®Rr†k=V úgOú¯ "@= dZX@£èÖ²åG„Z:òˆËZÐß­¢Éx¢GfUÄRàVBjA—¿ÉŽá›¸íéVbµ XHN]¼Þi1²íOÈ"ëIe¶u]Xë W$S Éœ(ËU12Oª×ù“Óé¬õ_ä1U—òdO<:Þ^ù¥Wj"Mþw¾>#¢åšýW¤0¹³o®†…ñò>³çõ‚ûoU­UÃdƒk#µÍ3Ptò·l­i3åoßÜÁÿBJsèÞ ¯’+ɾhë Ü‘±XeIJ?³Øs‘È!ènèºý‚òxþæTr¯ïÛ7d“üöÊÞüþ°}MؾúؾOÔŽ·¯Ú¶ïrlß'âÁÄÛWÁöÍ>æþaûªmûÚ}û>3½p´}Õ¶}y™ŸøòÊœ/ïñ˜gž54Â`Ųwóh}ææ‰úbÁ<Ô[‡a 6O:ŠýW/Ò[§œ0›'å6;Jgwó<ÞÌ IDö+;Ìó8›g/{'+džãΚ"xÈì ®š+)Âë´ý$ñ•í2‹²ZJ DLö"Šˆ„öRÓ:¶¸Gð¤¬RÄ讼ëkÆ¡ÓvÖå›ÝØËó™Ÿq‡l,×3H\žHÞ WåÞáZÒ‘­jÔb Y™Ep3 58û×Yô>u|KËûZ)k ¼bQ‡Ô ç#ã5ÐüdOü>lçp߯þœi)ÅÀÛqC¬`V=êÏ‚ÒjH‰OãuC·‡°‡b×ü ~ÈD ƒ2jÔI¼é‚»>M5Œ{röõõ› YE ñ+7É^^od`‡˜í¼;…Iý×åã«ÞNÍJµ¶$àH_—·æÚÈÙÙ™¡þìÞÊ×å\÷‰µ Ù˜™vÞ’†b`;á’’§¿1˜nšsàý£¨Xm;!`*÷uÉä·¢©Œ Ã-Þêp7¡f‹m¸-Mï†WóFWgóú¤þÕU‹r]fÇT÷‰„À"Î æ`3•-‘¿ÎÍ{ˆT-þFEz«E†¼¾K÷ͧÑ›,ûžËµ³í¨ +¨&´¦ÄÁ(ôë‚ë>·B<9;#úº¬DI/4Õv7´&Áv|èºü™wœoŽ„Í,ôïrÍÊü™,¾™ ÍJ¬µ€™Š×Ñlq’T9Â| <êë]È_ºxN¦FÁ¤ÏI׋TI¿¹V´¥ÞðÔ–øýëžX¡ð󺞫ùÑWù˜X2ÿh«1Þò}OhÚõhO\³¥~^ÁG‚ç…èì~pŸ¤?p1 |ÍúŠ¢&^ŠBoÕTf扜Ë éEQºÉºe²23ø,ËrA ä¬7”ˆò`è?摨PZ·=pƒ'$ªæï„’)Bô饄ü}˜§´~“g‡îÍH*ï—&ø½ßZrÓx•ìg-Œh‰GVmºžRµ–ŠeODÒZ ä|&çW¯!Ыó.­•XM¡ªsµk8fO1Y¦-!;Ñì ¨ÞÞðjoÅÖ8  y—ÖŠ Ëräc?Ï>‚΀Ïý†Á n˜ÆeTÎôûž½eô—ñÌ \ÆyY×Î̹Á¿àÝÚA¶Aà¦M¥üoÓdÈKβ5‰WÔߌÿ/C^÷¹œP…Ý.”›®¸n Ð1¾ŠÛ)«bºh¶v…ù¼×»0JܶÆoE©« Z”^ç¦eH艆¹¾t͘oïÝÍ¢±N¬ëX ,°Ôt²y«ðû ºz^Åyâ/•ÜS•5>POì‹­…"Õìχ*>ñ¸l܉¼!N0":‡¯|ín’^¼þ—äP¤~¡žˆÔb'cÏi×tÎiž}M¬Gy˜Í’ŒTd’f–Œc[¾œ±4«ëOf»Øç?÷7BƘ©žÙLì<Ð=ñ*r’²…𛯴ÂïíZ“ìÓ/ÅAæ'c/`ÍZÊ´ß»U¾ Dòó“ÚÏ·¥îz5+áfÝgÈx6þù‹"UÓ­‚JÂa#!Ÿ@³ãÝj 5[Ž¡¸œÑ ³<²XRï5Žh¼z½±<¦N¡ÔF Ä´þI-}²ô¹ÝÛ:_oŠî©¯R¨ªS]gÇ@Lë/ccãd-WëDøˆˆÖŸo”RNÖŸ ’‚²ybZÿXÞô°¨¥t_÷œÖ?ðÿoò‹¥ëXãÎO|¾›µôžß9àŒxÝsZÿè_Mun2ƒ}D²÷?òrù„©yû+1­?Ôª«E›Öô½sòGé1YÖø«Ž•ÂÐìg¼ xžóÔ<íoÆ[^åg‘¢nw„¾&ë4µ2ÿ!­äÙºô‰°Œ<=óqBÊÙÃ\Í ³<ž'AÁ¸­ë´öséXl' æBùÆÛ.,W^TdçY—tæ,Æôæ²óL…êBéOmƒGÛ¯dݪ?h3íÒr££ÅÀÇKý.nTƒ ÇÌÜ ð‰8† •j ÂÐFDÓÿb¹éÈaÌQhs9‰Â麨It}ßôè—o—Ì%+ÛÙ¨[­&1q‰y§ˆ¿±ñ3½k­û°ò­ñãò[…$çˆ¶ÓÆ¹ÇÀÏïÞÞJ‘Vëu/4ã|¼B¦©´ãÐ1‡ÏºO3¥ˆ‰-|š0ðl¿d¢¨œôá•dË(ªþviœ‰’D’Ò‡2çLŸZ¿#¦¯²‘qL‘„ˆˆÕÊæíVKΦ ¾Ã–¹Q³  æBB,Ù-DÑQwxv¼r~:D!;È¡1°Òý˽tÄbÅÃa`¥û—õ¤D“ÍÌxÑ.qêÝš}¢¼§#–rR¢–0à©“ƒM;ˆ¡à¸’øñË£ ÃÀ/¤’'ò·Þ¶ãÀȹ oø¦!‹Ë:ŽcˆjÖ²9éoò"»º >y{_ü´‰ô€»BĈŽlj2ŽOòlZŒj~ù«®ÓŽžÈq¨÷™&ÓuÆ_·ŒÛú×?°”ÆùëjˆŒ¾B~"m–ª‰ÝB ëȲV“tÿR@±Žntd§ñùÄÊ{¹4 b/™ì˽½¸E:¶ÛIˆj®ãÃQÎ¥¬;ÒWËëþe¾J:ë…ú8Hõ”šº›–ç$¬®ŸU½.°î+•‰qÞ…[×YUϳ© M²ó÷ád機gó‘9G‘½¯´F^ºYØ,ÿz¿s²ïõu>ïW±â°dßFÓ[^-7Ðý{y›^JÎêeÔ Š+}ðáÙÍáȧ«ýèööj(ûpGaÎM¶«v…Û;®p@Šð¥]5ço×á(•zÒê »W"TuG·«å9ÌÜ«¾‘v GW#ï?7G¯„RWÝû¥ûG³:n:žÐ.„Þîåבî_±ïI3„Ù”œ )ÊñÄF»ÙTûèþýËé4h«˜ÒÖNm5ëŠî_é`鬿ü® åc½ÃcOÉBhŽO~Ò1þ¯ØÈ›e¡òpÜÛÛ‰(R­bÐýK;mɆ¯îĶvÕîßÿ%–ØÇÔ“ÖaÐêy^º4 †GKï7︞ª¹Ttÿþ´2X§(Pÿúç‹ëNŒ²ëŽqyÔªïIt&Å[&ªþR²”ÓsƒÇO-™”c–ÄÎáÜsœoè^Û,—î0Ó1r®~úŽbë6óâˆDÚÞk üÀ´ØLÇHé0ðó²Ü¥!b «Íbà®;"»îTÀŸ]wæäº3cà«ëN¼Æìºc†úÿîºã뻚ýß×]wê1ãËù»‡-ŽPdÖÚ„èµIf@Þo‰g-Ïhü { wþà„ÆøâëÏo­b™­¥K[ý‹;Œdmë\øøÜö‡bۀͯ†Çwó|õ,)þ²c¤Çy5…Íw`æÑ½oØ%h¶h—ÀÛᨀw$X 1Ã!à ©õ~|§ªº3¦AŽÞ°ÀR¢3 šÎlÛ¼) ì½ö¡Yó&‰ìï-íBDê1ð¢žÑX‰{íBE&TÍåèÔLiQðælF¯9«€÷«U,ëµÅkœ}¿ù¾8j rÆÕ–Â4lf¬n& ÿÅ’]´ïÌ#³4]þ`à£j¹ës"Xµ†™Î ðý•eTŽ>ÃàÜ:‘±ðDd&^Ú­û|ôbb*ìåNcà é)ˆÜ÷;÷#õÕˆéñø³–ˆÓýfÄ1‚Z"qP(õÌ£ìŽ=|öáÖÚí™Ô–|%G'É2b`S«C$—ç¤Ѳc ¶¢/Õ3Cí±”¤]Þ_ÔÒ5&u†6€÷¦Ê‘d õœ(ÖJó¡7e) uX…yš¥U>ʲ! uˆÃr’:æ£6¿oPró °¨ÞùŠË29×Ì1ð€¹¾ÏË5ŽÂwTbàç%ßÃÊ E azG†¨¥«ãÀà g>o²>CÔÀªçøõ ð°/Àò­ñ™í›b™¥ƒ"¡B¾ÿ‚4é+d&æüñi}å; »!Ÿ–¾BÆ·ógK–žœDê%5ÞœËá:îýÙcðI•L7+—ðá«™ñþ?Ky¥fHé;U¶ÓwDlHZΰ#\o³VøãýÑtuƒùý lÎÛ)bZáv¬×íœÍy7yåÄ»Q ÝÍØøtÊ¥°Äèæ:×í`>S€Ÿ â€@¥ŒÙIO‹ÃÀG,<Ú»“øDÀR… #*?mf0ð HäœjG×1DT^TÀ4ÙÙçp%fÌÚͲ~5Y«®(± í`µ«Ð{óÉÛY·!2Õ3/Bñ~çk-‘¯5lˆøZàÛ"¥yfë`8þÂ×Z"_kÀÀû¯ì* 6ÿFšZ¦HS 6/º8Ù9ÞÌÈÇ b%d ÿ#gŠø ø¼(SB&¡Ÿp×R ±j7aà×o\PÃ(Œøü :ð‹ Ú cáŸ#Üøûó• šŠ½PÆ9‚ ‰÷Ÿ™›?™›øñ+sS©îýY¹È¤&øL‰ Îó æê§?37­€¹Y€…ïò'=འ‡ ðtÎ …Oâb×Gï•ê¿]K–ä‰#õašvGú¶z…ïòʱøÅ±dƒaiñìM½:®zB…ïòsfm¼Ã÷»=å÷Šªž±pë_H~ïÐfPxÊï‘S~¯ú9¯oÈ_¨$©)!z¿^€È›újPM.ÝOÀ3-AN›®%š„óñâ1ðšŸðÓd–r¯FSϾ²ªq ê0ÍU°ùOV„……ÓŽ‹ÝèQþ °R'(}àá¿ìƒêᮯp;[°’Þ‰@½µÆ Ø`cÄÌcVƒVNóeo¿´¥ ŸQºM°?#WãYЯô„Í\ì^ðµ¨p4—«qéãL‡èx9æM-ÃQÌßäjœ)YQzŽ4—i2Ëù®ï/ n/À–ψeY¡ò=£:ï-ž ÊkD?.³ßÝ@<žg\ÚûÙï½;*টæÄ°V­WdW¼~^žü<˜û‰·gŽ|¼xûƉ+cX€ß„^3·24¨iÛç}ÆÀæG  À½Þе4=EEØV«°ÁaàÝu© ƒ™zº[Vˆ(² ö2s/ô®WHG4glú„TÛÆp+Êaàã[ïÍ6uÓB-ÁÀ'öÅ·;|¶¶•[‡_sW³®BT×X4\bÔÇá½™ÍÒž[n+ä{eUœr§Ç(ÝÎV¹èæã•d-³h´‰3BOëê+ä Se²ŸœåƒÝ 'f­÷RM D¦^xÝyTÈ âxï’´G8[[Z!?±qVãÑbj£¨Ñf*ä!K›äÜÑaœ»Þ¶òy™‚=ŸåSØ£»jOÍÉ™cáø”x–ÛÖ¾zžÍÛ%ÛËŠìʱšØi,=Z€|¯MÛr+Pø0¶N+øõWå~Vô}£CRØ®ŽEb`뇲®PÌ:— ”Jì¶‹/eÊù~=–µ@ú¶rÛþ[º “–TJ:ûsVÑq4gÊ:ûÃÀd;àÿ7ÈmûÌŠŒýêû}pP£iójl,×8·»¦Õ5>Qµ¼ÄKÓ&–33À¯ÛÛ³H!Ã;”ÆPHƒ#+çB/§i‹|=Þ~n¸ì]5â™Ó'‘ ˜ˆªó¶Âãèd‡(§_L¤C ¢iI/ªQN?ùd !qB* |\‚•‘°˜­yl²"Âeó@9ý"$’Ï”ÝO?ý…€å§ð‡ŸÆeõ®Dæé·w"ƽB¢²:Hº9ÖݺsËxà²úßkJäÊB>8èN ­Ç¬ÝGs)”´-%]k† ùÒö]N¼Ê– aÁ-¦¾£ÏJ—&'ÙI‡iTõÞsYýïŸlˆž[¸¥ÝñQUï¨y¢…YšE{ôb×ÇŸŸç‹“+¥a=>]¨b_Ù4¸Jó'ën—2ì&õ0vðÖ¿*óë Øöºïæ Ø <;tˆ0:ŠÎ1 ï4_/Št@(bybõg©¤¹˜ƒWõ.%†Í0Úûê§?®Óàu”@?)Rø‰´DXñ"6ÛB¥äˆ”¹Yw5õ¨ZÕU#>¡6ÕžBçÚÈ­/{«FüBmPÅèv%ã"½äPm¾pDö¢ü$õ¶‰½~5↑[ngº½UJp$±›1÷8¤²n-&ô r‚OÀ”ìÉ©›šø°w›`2} ÀeèöjÄÛõ©…3D·ŽÏ!Àsðâ-çÞ¦˜%Õ~G¢U¬{–Ò5.ÂùÞn0ðìY"§¶¼è¦Èª‹˜ts{q)cÙÖRöT26ïãQR 0çp²°fÙ+—2ñqººÆ/äþÕç8=’hgà ðÎnˆéw"Óžž‚·E$ï¯È2f@nS…,Jp¹h!‹b¸ïþè¡lp{G9 ©æ÷M¶fµ!õÄÀÊ5 ï&!ä˜Î¹†ûy£fýÙb©¤„bЯÈÏŸ‘‹b ¯ïý¹&¤raHðjäSPó4¢Šªî8˜¨fG~ŠåP&Ëê¡ã>¨….c=×ß@½’¤˜>ˆûÑÝèb!ÈwÔŠy6s„ˆ~ëŠÐ/ ›Jî1Ÿ(Ìá"«¿ð§‰½´s7RÕn6 ³Aù"Ñ]ô©³Û°õÖÔ4]ž>"bˆ½›­-­Ìˆhº²èÍD !¨=Þá ÅóRcaDA'î žzÖ¬…dûH‰›)]müD&ëen°XŒ=XoªŸ~TÀ˜ŽL’»îÜ7š—8AòcîÖùdþ :˜Áã1ê8œ3¤ôÃÀûEPÁZ+aã¸RS?ÖA³ò^}nÛdïž"LÖ¹òÆ–ölÿèK(xûîÑ–OzÒYqLÇ!J|Ü‘¿ÿ=s¯q_ÝÃQs±™[é. @Ñ+›z ¬¾ô…Á®T¯ƒ,ííñr$„\rî®l¯€D¿šF£¼ØÔM-|éo×Q&³'â;\)½ |àêÜk½„³„ÜÛª·Ð¼…f¾‡ ïwƒ_XZžû#+ÂrØZ_=ð·J„>·'÷Vˆi›Mõı\}JèÆ.!–xiyu•ï î–-’Œ®«í]Ýxý+ٲŋÜ:héäÅ.¥MÉ:Ë;µôKýë— RÇrÆKúq?öØ&Á*ägÕ¥kˆ½Š:´ë*äãjâ™w ½¡ýÚKQŠäo.™OË{–¥ó}õŠpîE”ÌOg[Û¶«š« ‡r/g&mêmVã¾Vc6ï(KSšžC¼e ­'HsJƒ_ôuÛ‡¯Ùêý¹.P³Rˆ€/àªØ¶Á“AvCÍJÿ’ñ]—ù}Ãà¶‘C=bV5øû·Èɦ—î÷e½«G¼_Æwma¯‡mC;eÌÁÓ׋¿"×·i8ŽÖ!îoß$Û2+[¹E´û®Ì„M­“ rþy}Ç­ÄÀ‹AÆ@¦tfnüä¸ßߪú` ÇÑÈ£:D—À]¹¿}7æés˜îƒìÄ÷·:åÔBþY™NÒy¶Š`ൿœ‘‹žã·E`àóWãN;÷÷ÿßÄ$ä$ü“‚…P¦ž½\Y© µí2µÝ<…Ô¦r‹…SpšÂÓQ› ˜ÙY",„0m=ÇÀÛYÎïÚÒm"ÝHרi0ð~u>°üMêŽá“qÃÀ˜ªi}¶EöÎÏŒh ¼^áõC×k? ù¾7•.,ÕÜÞéÉy-Ú"ðQ€§ý$ÍX:+ËEQÒB’àŽ›q^.g l~NÃÄ[*žÇ¬$Ðɳ„Ïæ™–êsw\©ÊüÃ\*ÍâWç„’øQén¦=R:æöÅ‚´o~V)Ðü c ôäs±™nIN€¸Ó(»‘˜"T×`3Ý"U@.»Õó¶Þ.ŸJ%#δgÝŠH#f™2CIêpÿÒ÷{åG<3Ù0¦>¶?+qõ´UDAV¹ gíë»=oþʆ-…u’„‚``å]˜‹xÈ}—݆ˆ8 { WáÛS{¾ï7:{ÔØ17Ûq]1ðgÌòçPc;øƒ…ôŽd@.½çd…f¨ÞØAª»~œD{å4§œaniÛŸg•¼¸œf !®ƒ4éÉ€ü'—´ŠÔôJô¾„w8UüWÏÀô e$—Hè½#k”§ÓKœ[¯ÝfÈZ½›B‹H\Åäk¿ 6l(×¾¹£’VvÅʪ["”‰T£T=æÙ›õJ è»«ý€¯Òç7~ø™Z#£—¤oÍò?Л.Nïa’c/‚ ²Y` f¥z´ó†¿]ãªVDÔMþ;w̓TVnŒØT Òç5Js Î!›eæZVj²Íç Ã6Ë1¦Éö:ñÜÛ{¡ŽêþØ=9uj@8utvé,Õç§áëå($JM=ìBëÙ­ðTŽ&ï"—Âãî¦n†Þ¹{-wœÜàe9ȶ²å¼™+éùï/pò4,ÛŠfÚ÷5#‹ÓŠ\&}®YÔ.ù¸ì¤}‡>:p@’›ùVs\:oåÒíE‘§l•|O5èØ¸` bß]ùˆÝzVœƒ+@»žcÞñÖ²MZ‘?Þª¯-ŸÃÔCôÿøº²%Wq%øKÝvÛØ÷}NÄÌ'm ± ˜¯¿Ú Jt÷Ä9Ð Õ’•Ùš1+-gà³ ˆ¤Þ?ûG8)ˆi3qr äùÆR15ï'Ý ;ïI&# ÌÔñ}ò[ÅÀû94¦üUƒ#tëüþ ~†Sþþów}Œ§PBÝ®ºâ…Ç­Ô"àq÷‹á½v¦W}vc½=î%;2NhÆÏ•øSiÚÜñ¬Q`±Ç³˜åÏuòY'm†¬È|{ÜËvdÈ,rÿWÞ9 q×Õ™˜‚Ü Õþ}ØõŒóÇýêú žÑni·Fµ½ÃÀs@‘Áœ¿ïý6Ê |…;ÒcLÌÕ qªiFؤw¤Ç˜Æþò­·•H>×¢¸õûÜ)4˜¬öÄrB³ˆ1,8šN‰±f•\ü_üìÓ‡+ɧ‡(¥Ösw| ˆö­£ŽJž5e[­aJ ™<§qš;$Ë`ü3ß&Á&ϱΠÂ-ʸyèô)6y>Y³Á§;8^¬³ƒ3 ›<ÿ‰|¹¼æë0mjÞˆ.®xvñé!3bÉ$†V¸Ÿ…ÌHz%ýת(i§âŠÕ/À€ývb€L¬s>Û¤£K±<ï³ÎLãDG_Kÿyõ0+ÊEí9™'2mÈQC²¤ ä™+Qpëš—Mé~Ÿa ™[Ÿ¹R¬4ngk»3›[çQé”äïší¦Ε|P†÷gÎp*D»ØõllÕØ-ÐlœÜ—?ÿúW—1m3åÖQc`*tþ,('¼9;4>÷ãˆÅóCY’е›Š[¿Ð›ä'ýòl¹٠=¾¿ö5‹‘Êo¨ª¸âÏî&[ÓùHÿòh~t7¡Mð¾½ o?ú‹ˆZÓ”È;B‚Ÿ#a~‡þ†üúÑcc~ŸÇvjEwÂ`ÜZ ¾IícW ‘›¤äà]ßÔk½ò%ÇiêR¨gàTëÚ±›6º-Ȥ†­³¹–kåÀ7·xŠù÷øG²tFvBÀ7ö.· ¨"‡cL½­bwžÛã]Öu`§øàº¨ÞјFf,ØÉ ›i$³$´§1"áÖ>aZFƒg]‡ (uÄ“+æìÅ»±I³ŽÛ¶Œ#PJï‚•ýySØ‘ÄKèÞ<ÞU>‘uþ­L§;*Š+bቬÃÈÜ ÚwYf O4q"²]ÆÕu£YiqÉS•/hú¦³iïÂtÓ2–7ÿ,8±Y6võ'Žßˆ;[ ïEpœj¶¹zäV"Qᡎýjÿ•wà)§”t’ÝF eäÆõé!ÝoÖf–5my÷êÜŠ@²Qö YéÊXñ„>_¨ÌšÛ8>© ƒµj(Wþ8´a9ƒÔáN$cfÚ‹îöQ4Hò*­³O@…+‘Ÿ˜nÛÆcOìu¿ë¡u¼!íÚ|M3Ž›4lbm¼o{(Nji:§ŠUºa7ál×àß½Œ®§Å*ÝÎî+cIu©Y6%»Ë5Ÿg}‚)H7†ANý<’Æíï?i&!×·æ¥ÙõÜìo¿Ú6pê>?‹ÑÕpê&J˜‡ûiã¦àíâÁ(³nîÚ;5*Öo ÞP‘´¸šÉ5Ó4Ñ6ëç¥ßÈ Ü×ða©¿pÓ#óÜÚ«i«-Üú›O PxÍÞu0±ÿ¼_«yzJkCü³m5^ê™âë—Ñ¿íº.nýUØg»{ÙL¦™!ÙyÞË i=yk£Å¶Açáy¿TÌAZPkÁ¬õ1LqÅ Ûܘ1kÝé£aøD Ù¿øóãÒôs <õ'JÈòLBb>†¿±¶ýœ ‡aÁ?Î"O¬ë‡÷ÌöS-é³`ϯR 0i4Qò©Wv0ºÆÀ3û¦`§«ÄÒ´–3˜^@öì u³ÏV™V üBú,=l9éi²®?^Ÿ¯B+öõÒ{¶¯Ô¿·>žÆÀçA>ŽQcÈ̉«ù„ GD¶ðì±ëȶâÖ¯ïÀ±I»Žk |£žYnõoa„ì}„\ùoÔ÷®êýš}›oØžý¤%ûy;‘ìÙWêw€º;^^,DZÓiŸÛInòë7¤™æù8Œ„¦•é¥:^ êa}üK½IkÆÚ§=ûIRy@»öç³îÚò.( yâÒùe'}Ó›‰5´›6þšœóm^‹¿óöÅ R=>ÀOÛ&Tñ4oŸ¿"Ç¥DÞN­ø&W õä“ucZ`ÈÈû¯Ècr$#¿ M˜r=!m?O¦xC²í?PäÛ­õ*Öäç2òy"£“R¸&÷×T3厀ù¡¹4å×Ó¿u¡ôU _GBCÁÿ\ùÅê†k/#ߨò•Æ}³’uUãÈ‹_t?8 ‘Æš‚뎅øÚ?Ðùù‹"Ê,ÔUŸeâlgrpƒûYH§ää9Ög7 cgŽ·ƒø éfÛóá¶&0¶÷¼ xƒ•#>•1‹¢ø…M{D›fVD·Ð­“ðœò†’ñW«ÕYné0ð‰er²ï’Ïõ¨«Ð/y>‹]³¦Àòã⿞º^1ïš<Ó¯E9%²¯1ðù[Ùÿp”$›Ï,Šÿøé#¹ßŠ?ïšÀF¶Uv³½(‘7¨œè¡Iä%ÄÈ{ÁQÊ’CN*Ò¶ýV ±ÇD|Ód¤\õÖZ™~"ïÔ ƒ ºfT2ŒîÕ%²t|‰WuÛF(¥ŸOÄŠ À1JÖÔÍJ˜båz¾ŠY®tî³,þW‘ùF|"˜$#bçuñ0O–PäÅ·L#íf¾ Q KH6yÏ–{X|ÿžÈsLžÇkúÛ¹AŸ3PY8ÀÀ-EW‘¸/° ººîUÓÞâ×U©,—ÒŒl‰š¬öçë2ÕÄ`´(Ä¢õ81‚÷#>‰sR±®Jôû6‰õù*x¹¬‡¡Û¾v'Åß~"¯þ>Z–J‹Ù``õ+p¬ à«ì7Ä$n'ëÄuŠƒÚüÐZ1>€rkC‹ÿÀ¤ö$D©Ü>ûH¦ÏùÿžqY$¹QÀ- ƒÏó…C£8)Ož¦åû¬…ô[Wñ?ï%²=‚l{üÂZñi³ökd51—Åü|”È8Ë‘Ý J$>v3Eª^‡AŽcÏx¬Î ï&wü±;H¹é¦ü;Ïc7‡[ñ0×±mx‰ gÝ‹Cƺj^Ÿ§³náa³CFWŸ§+;¢Üæ¦ Ïg ò­ÿ“3«”):=ûÄçÞN)ËL^É •â«xa–Âj³f¹¿~NÓøø~"ùßnýçµAðóúíèªë Óþ¼pEÝh­÷ &q_xØVwÙ¶f÷±ƒ{a[½6Vlж \…ÜZO‚(1 ˜:9Ü/nwjnw’€è6rpGQ~&|Ô ¿úYn¤f&v;Òƒˆ6fÏÊ×iS ²ù½m,p…°1;t“ÒNA¹?2 Ñ â¶S69Ù÷­ÛÉ$L|\—bÀ;EZÛÕøÄ^wI¥H‘]w>¢ãë›…L k»ô$LùâǼJ7™|ÜÚ¡ïçøÆZ|‰“”X˜­˜Šÿ8Cbž×‡í”vÛâg~þd¤¦Ôâ³ól½ÈÛ/–kûàéy¿X®Åf–?3…ß-Hü:“*P- jßfßq­×³l–Çn@›†aÜý‰µ´J‹OÀ1ëPþöêô{†êŸ¿»m'k -/„ÌÝä|š ŒC½žerœjÒñaözf›NáîU!ŸÏ$oàFª„Ø L{U§*ÖfÓ`f³ÖúÃVóuå`‹$Lìs5D"hƒ·cR Ö £¦cþäõ¾–®Yž„ ó"8bàíäۋýDŒ‚øX¤Æ@¤ð.Ætø2æ ÚT¯wIŽåñ¬ "ønôÙŸ`Šð…X.QJWFöUŒ€ZJøÁ¢8Mß“‚ç|Î+Z3çwíýq¡EAítEËí¼@¾ô¾ŽÝe6L3‰©Ujka„èýñË.D"ˆùèk¨k ˆ½Qí ¡!Ý®ÍÚš žžßd#aMAÔ5Œ9uÝ䀨‰M¸Ãù÷Œ €(b]­ àíg ³NBž†L¸!¦™ÕÑ6¼¹x¿¤_p’ø°Ø8m6´ß÷ëØHñÊ ©ôYZD»÷ýºŽ¹’çܶoÒಿïHSñ§1sˆ€ÃôøÇâý(Ë Dõ¼n>?T@¦B~­‰WÓdUíº¥ÁÖ‹üZs€˜m1Ÿœö5²ëù ùµ¦A°Gx£„&ÛÆ1ð°P‹½Yݧ°½htqëöôÎn ße? ¨˜œ~­Ùv0Ò¸dÈü¤5nU¬ÝGN“ƒ?—.H`àëÆ!ƒø¬Óò¹žÀmûµþȧ9>…ê>ͤJ>Í»úVêËP kÂ÷«,&ɪPzïWŸçÛ¸»È$ðßHÆ ™Gx×Ó.mRwä«Àô«ÐvKšŸWj3MMÚ­TozŶ ¼•[3£G¹v™Ôèh&md Š©Â¹¯(;Ì‘9Ëdàý,̱<ÊëO…¦w«Í›T1á,‰Ð7lîšÁ‡ä9yÏÀǹŽÙ´ÎÿA‚îvîfài~U –F'™qLŽ#Ï ³ < œ„ƒ ›YPv¹ô“/¤Ã»MÑQ4vY²ŸižÅ쬭×q÷®\Š+žDš]Ìe뿳ÝÇäZñù‰º±¨·ÉÖ‹uζõ€<ùÒ±‡ëI³ëûݸ¼Yò~øDQ(¸ÉÑú<ȱ\Uä1Ãç R»CMD6NòF ¼_:íñoT¶é[4~Mñì¨Ôî|çnmM1ðq3§Ð_˜ð–ÐÖöøÄüÕ,µi«#¬ÁÀ TXOnQ-]Úaìâv|¦½[«^sÓ øÆ}ûô£­õ‰CK÷±+ü[|6™(BˆOÐ;ê ä'òøÌ½(ŸþÚr1ÏæóvrXö£çzÆ•×KyÍdÕì_µ,Q÷k›~õKV ¿™ôÝŠïRZ?¬y7¥Y'Y±à8¤mcimpÒÕnß'Y ?›JUâØ¥_ÿ=•ZO o¿©áMÒh ¼c=ºT< îkÓ×]‹_§Muæñ· iˆÿßÔðk~ô³Ž^%Š[6O¬ÇÀ"ùRðžÝ‡yU+0ð^J›ÄÉ–n¶›h6%0ð &[êÄ«O›3BDMŽ#ç]rw#¿8OIóÍÊ¡)€Oï9Ÿ i\Ž;V¥ mÊùé&6©¬ÃÀÿvmK’ªJô—¦Êºt=ž÷=s>T@¼ çëH¢™Uݳ§_æa¥È%¯k}Æ/Ï(ë`ÙÚËÚà뤉¹ÎFóMòzësúõ^ ݶøÛ–YQVa–è§¹ E µ“Û5ƒ˜Viªt!2òLTò½ª;¦)«eË«™Ìùåh$ÏŽíNCŒÌ¾®K‚¼adŠF$[¤ìZ‚L-v‰áRÎay)fÞSäIwd…˜–KQΙC>#Ÿ9ßÍ3%Ñ^W7 ¹µtÌ/T!2·\špñ˜‘ O®ªJBüqJ?™(·˜‡X].-« ¨¸ùiŒ^•Á@¤"œ×Ñ.ì䔉£ârycÜå·Ýš5µ“PY`}·£6¸-±õ3ÛÉ”Ìß4•vRÛ¦g6Z ¼¬2§õ9‘${2X¶í[&[—Ÿ±ø&Û–ÿÂd ™©‚H¢}ÇdË4¢Ä!!ÝÊpn*_NHí{Ê[NžññAm««Ÿ?òÎÎyÆ/|ÝAÉËj‡ØLÓ“·N‚@QÄ |ÈO;ëi®,ÄØ $ öŸ?ÀpFhdÁvàAsÖÆ¦sæ:Y+.7"9^fJø}D[Í•Û0ðÔã8è4Û¶­[d¾q.Tï´<È1ÚÖx£ûº´‹Ë:õUÓ› §ŠÆž‰’*É‚©]í|zÖ’—ù:³;Ov–Ò óø:y*PM‹?Ý´V*òŒg¢dH‘‘z1™Ü©¸à‹ßô½}°¦—ØŠË&JÒ"O‚@ª—cÓOd*q¢DÛGœËV÷ž‚¼ ߤ{µ…W& ôfäýÜ´YZn`¶gl1#™ö .^‚S­mûØ×TdÞ!QyNêì¯dì™3-}£¯ 1ȘÂë¶›j²Þ QãöoÈÍNd>¡«±¬‹Mh¿šMÓç¼~“5]rÖ4ïÈû» 'dMêW/Ëê8}Ïôêo’°Õ­šä¤­Ÿ0ðûôê²§WɈ·oø:ÞÈÑ ƒÆÀûgvÈyXòÓ7bÜDêêXUÍ1ð‰4æA )Üb±gÈ1¤S2ÎÿÏJ‘‹ÌÐË-ØÈÇUòÆ®£vÕÛXÖPäP`m¹=½*A°7ÜsL,¦yz¾>ÈWó©Q·š³ÌrP`M4Ô%Þ¨– õÚ…i%#¸3*w‰+½ÖáÄj1sªB3‹kz¡ÃeçW ¼SÝÓTÐk³q NÕäÒ‡{«¶ª7øDeÌ#"=›=~œ7®‚ó½uø:4]ŽŸ.%kE½•J’ ÿ…šaam3ëÕWFä©ÎÄâL•eO»ï£üqA&úUke$`µŒŽYü@¹8É6Ûü—×ßËK`(.ð;,­›vKiFØW\xóFéÅX–µÄÀëO=AS /®×7º¬"Wª-Y°›|7^‹O©E ”Ú6®ç+^ÏÆ¹¥F5J£ØˆGX 8ÔÔ û6ß¶×âÁdçÂÛ'<ò[N:›7§ðÖïÿý>CŠ{6¸óaù‚áyJPý<~úñA '³²³Õ3È;X#æˆßÃ<»@¼>øÆOVgi9ÏÃ.4bm^Ïòäø  ãfT¬ <Ëß0æ,Œw£?Ô æöŸÄ矮H:i-S¼Ÿ%Qùe¸[¸Þ<oð$H¬òˆ6l˜U¬¶é1ð‰ZWŸfÒL¾4 ~é$Z´' ì8‹ð ' <ÄdXJļJ_I.’‰¼Ì)&ÃŽ’1c6i\?w† /$ñ”¼Å¥g²îÖ¥&È+®J†´®š’6o®_TL†í×ÈN„`¬x§É\^NÖÎtöÆÚÙMeUG‘wÔ* ²it|­ï軣4U%sŒ6–ͼmôÝÏ›–K¨&ZMÉÖpN®ù…¥=S®qÛ‘ÁÄ‘­¹¾·]”²Iy¿•Ûæ£ýDÖú/dPC39w’ͳP‹'HÔ¡‘9ã¹ÕZ…ODÈõ<ˆJî5[ô–ƒ)ÖI‚,ÎâùXº‘2U+ë§­ªéž¼áó éy¹oÆ`'Ó1ï9ûµWÿì›h6mßõjiÈö½>ù Ù/ņ0º’|Íëó̓ń¾Hßh•¾ EDÃgý—Á‘ ߨ£¿þÂá\Ð_í[ÙöÞy2fñëìÙr˜ûÙ¸¹œ:W‘=\àE™T«„åÒ2g²;Š#F\ Qr4}¯ºZ̉RhJéM”ËÖ™ù$eþÙ݉§(}XŸaé•d-÷3Ÿ—ëSmåØZù>›þ€|äû4ÙOrŸ%ÖöƒÓDOBX±?iX!M¼)KÖR…þÔ^«Ðˆ‘‹ØÔŒ¬äâuvLGm¸½V)éaB׆ÌüíP‹ÝÕ6ö;µšd0ášU‘ù¼]po5œñŒqŹdd>o×)á6ˆ’²Ö‰·“öFØæÓe9ºÑYéœ —à톩•RNÆ„cnçg¡ÏyGKÁã ï‡Ö¯Sž¥×[ŒJdÕ2Gù5Îx‹ú‰E2·ŒшÅûšŒø“¡'§ j ,½óO’ONöh”OvÂev„Iï$¡œ²¨ÖÖðzž¡õ½@Ò;0  ­“Y:›eÙ‹7éòð»¡lb( ?}õ©vÇèÉöÞtˈT>YBɦ–¦@r®ÀÒ;Àà Uáß°ÍÖ,ÉŽæÑC0©£‡ (®$9J+þ'uTüEñž—m H~Ö®ó[ãHj#—6¥ÚWœÖÕ)´¼ž)µÌp³Œ•žÂÁ^s ,Žl½ÒÄ„µÛà岑o?ªo¹X  Iæ`¥¶b\õrëMåƒ_F4¢V§uð' ¼b~ Jr]×Íe—ú‚¶åG‰y%}©ë:<%Þ0PA5E½ö¾_@ë€wT ì:rT‹Õ‹§À¡¼ÚßZŽ­Æ–ÀÀç[>&&7¦E0 ¡U€_o:{[¾è¸÷'ÓóBÅ.@ÓÛôJSµ #þ óð*(K¤dž OG! ¨7Bs¶H±pòãˆÏì¦0dcFËš`–Ð1 KÇn¬1šÂ±Q¯Wy;7N¼Ãw²ïY&‰UyÇR ÄØTW›tÌÚ:r¿Ÿ5”¥äMÓK‚DÜù™Æó9ü§ýõ¯ {Gy¾Ô:,¸±$ÈS ØYâ»{ßvLq²„1™If_â ¶#ˤ+yÁʺ)k/l”ÖÕz ûçše¸ÈÄkt+o8d‘îì`,_³[ ȺUêAÛ± vó2Ñ_¿#d*LTá&½M#Ðodäƒþ“ªdÉJcl MùüDúyfQžc!»èzrqÁ•Á/Upn¤¥óù:ò<‘rk_MƒeÖ.“(ÉÁUü:«7kЫ™ÂÚ3–QÝ „ýÄÀŒZÃF&{³ø:‘I¦9ðS¿¶…¬¥âu"t7‰¡í´ Ÿž¬¥Û¯S|YÕ)Y9K>/¦T†œK»éè¯i-%ž®²ÔaÖ¯;‚Ü¿Ñú{ï®dÔ{í'‘û¿2²@E: D­Ó‹l·Š¼Ñí†Bz@Üdᢔ#ßývÔÔ龌©»™ aºŠ“ìöø™]>—CïÅ/RÍ| [éøñ/jéÕÔ·M´zÓþ0Ž^?(÷%^q©nÏ|Zm˜ XXƒç»R½ãeN ÿg¿e¦²œZµ†«º_0°@ŠÓU:—V j]–úòÎ)R¥SfÛ5—l ÙšoF”k.¾.ÞÔh>FäÐåXÜ®z"‡5ªÕ:e™‡âö–"މÄFj5ËyñÀâV ´Èùðö$„/>aØs L– É,jÉ€Sý`”g9 dBvE†ØøÊCeì Ütññ™¤H^Oðá$KYbàõÛgô<=±øQ¢¨ÌÉžÛóïEr%À¿He7 ‰AP¾Ôày,º5-õ·÷ŒKfé0ÑKX”ì^1‰ (áq9Ûr@ïöžqÉä(aÄÑ8Ö”ÞÎ@€€óÔ­MåYM€÷Ã0Ø‹LSКá¶u1ðõI’ýâ˜ãƒÝÆFcàóè•8Ø#ÖyÓÄÌ~á»(¢X·¹¹yë"YϹ0.úE×¥%þ‹–tìQÌÉ;¥·AâëF7–õ†­Àcó! ß›±wƒd?g¡7ÁÔ„WELCvnäz‹o€[Éõæ|ÝÞ:µà2?ïcÄ;Îóƒ„ÜZÍÁþ6Îa òfö¢çDð0ÌL\cà¹=à†ÇÎÉy Ro&©Bõ-¸¡õ€¯3,—sBU¸¹ÕÏž“ ?,åði ¸¶ë—q[SÓOs¡Èh ,3ëçqÔÙ¢¿¡ò®Y5¹½aåÒq3ÍyÈÑD’< •NŠ÷lP=AÞNK$K†C+8,ÛHwÊ—²çýjc)ØXö„ˆOà,Ûàä <ƒC‰FîÀ΄«Ÿ0±FÇ9isZì•– ¼|F„0XÓUÅȈw"T”na5y=q | ޣ̺7÷ªœJ¾V'FÒÞ®ÒÎ6’»Q´xœ»¿“òŠ]§—Úh5àë(EݽýTkäbëvJ<á¿pWiZ¿z³a—õ]®¼ÃÚ,»š@.êÕ­´Z¬ëF€ß’ XkÛ(ð$™ÅY7™ÈÐ4aàílØ@5µÔƒëÆ0n^>×7^Ó¸ˆÂÌú0.îÿb\X9càÏÆÅ ¼‘°æ~…‰ÔúÏ&ÙõrÈëìþoÀ¯$¨±‡T ×1L;c`ñ t,ålpxöï”ùR ?=H»ùžaàý/ÀDq%Õ}0©¥‚÷€Ï3 €Ó2Ž8láLÏ"ª²¶­5+Ëø4 $1‘hj¨„gߺ4fdä­ÓÿIf<§¿×ܨ&3ÃÖ·‰ ¯?!§wd‘‡Ø ÆÒ°°&ÉA¹ì7Èáy'H âa}7/½ò¹Ø“]¦“±Rµ}EOÒ]Ú¤îÒjc¥V E~ýi ’ð»§6½°„e¿r“Ûô`­ÿúD:Æt¿Žn4y9©Y3q×MºrKîýÍȃjœ§4­Œö›0¥/›– Ô›ôÜ“aê;?‘ù¼Þ>‘Ë÷ȳM¤ÊÌsáUX£VÏÈB¾žÉß2õÊ…3Æn|Û&žch÷Ç7µ‰°D¶Lõ=ôõwXNÊAPãÚ2Áúž l8%{º´QŒóãByç{­²KÔNŽW+kðŽm~™m~×€$ÀI>*0åuã ò…KÉÀdxG rI€ˆÀDw£SÌåšG$–@ø4ة੠B¦{Hj²²\›±] ò‚üˆÌSݲ9²ñ7. ,g$T亭ïÈ#h¹Ÿ[éàªxç\Y®Œ o©«ãOòb2•M[úp¼yGH²dÙþùÈ”mðF*©Ù®V‚|bd^n¬l|G—'Ùb™±ˆ½äôÝ_Xçru¬›Ýà‡˸Ÿå¼Íëä„Wë¨üê+±äûQòð£Ú`œ02ŸptœLqKNBõjjòÝÓÑÅ(w™šD¬Íݺ‘7ºûÍŸ½êdÞÜ&Y]ŽÀc˜‘w¢þ‚éK°9DVì-îOB›ÔˆûÇ\6Ö ›»î_Ÿ@¨¦ @+„µˆ©¡YðNr?ñªÅÀ‚Щî?ÝLÁÑ*ß) ¼¡”èÍ8^S8ø"ÏYLÁ8%ç1wÔ`á›Ô̽ζ®Vë F ¤Ò*P¯·H!\?6xCÕÒmþ`ÛÆ­ƒÃÀ;&þ®ZœlòŒÜ•gÁØYÅ–cv_Ÿ³ý­w ¨ÍÔcàõ‡e­Çå_Fä^æ–ÊK÷qý¡@2³UÀâÎ ÐÙr:é=ä ª¬U7•®sÒ q¡çf–$G9¿JÖ-ÀðÀëQM’ÊRc€M*ÍÃôäV0Lš:˜PÉ=÷­0|Ë^ç'PÉ ,›' ¼b PÀ ³¥v  Âù|û·Ù¬~œ ”{a_jÄÍRÓË4 äïo@hÎvË:çjóÇ“hÁñƒ°2V X©§ŽŸ?Õd~ýì8æ|Ƀ F¼Έj´»ÎÏ€W\mžÈµeQ1—Ëì‹ðÄ$å6¸o†.ÜŽ¹Òåñz¯šMG~¤vŠjÆ•6x%B%°¬YeȈNÙ§Pwµ,ÃÒÝÞHû‡cª?žñ(@Û¿à^ ´NŽm‹îF| ^>¨*«Ö>X0Õ ÜJ|~¶k©yžp»Öó×[@zDTÔqwе¹f‘úþùûä:¦¯x.hC¤¾)Á}DSY+}ëu®øF¤¾{ùÏ n=9øÞ oHÙ¢IÍÞmÙ*Æ<+É3Ò°L:–ip øÀÇŸ8<ÌàÙ²­ï$0øðyhÕ%R—xöHY³¦âô§Qÿ ¡r½¹nÕ sdÄ×{.4.q¥«¾_s_Lø/À‰fÙ÷]ksa /‡YQ­Ñå*m$àôyE9h†Ÿó¯¦ŽŸƒH÷8 lV‹‘À$_DÊGƒ;´Z.æ¹›6NFLÕ8 \bf±>;xõ-H‘rþ÷?ÿ=h˜š©tÂÖ^ôï„lÿÜQxÝZm€j±@俉É! Èl[0ù&Qæ&gñ&éùNqãV˜%ø[Šëœ¸{Þþ…âúXi7bL%îto.L—mÕÂ9…x‡A³RdLoµ¬Êì*>ßìñé¼âÓ±ÿp:k üöt޽)Ëf þ–iì˜ÇçÃ,sÍcã¦y¬ÁÀT´™x`¯SUó`ÖÊ»\çþüz?Æ¡K‚;Ú%ñ|ýÐN!»ï€WR”¾Ûâ{-WoÄñe^”ã(Þ ûÅÉ­e8 3ÇÑóõÙ%q4hˆØ Qaàý{àQ…=*¼·%£§u®uC^æùcËgävÈò°ãä`Ýh›I‰V:ÐäÈZÖk¡É3žÊ)<†Cö×ñ¼îyÛ­A KVg×ÏCŸF’?ENfæ€tQÖá yðÿ2èGŒŸQLÕ´™ã^z}êM©Ýà\}ÇäRu¹7}1<öÅpFGû+3ŸÁÐÆ&µíÿ„]Ý–¤*³|¥®*«»êò»ß³ÖìG@ùQÄ_Yóô„ÔL{zŸ‹Ysm© $™‘}O_X+xg#ˆ,ÎEÌ:×°? ­à¤ÜývÎj>»b=Vpô®=›˜c þI‹SÁt‹@™»åc_ýdX+Ëëã[ó`ö˜%ú¦š9~b¯0š­YäžBáðuaÛîjØqZV•_|#@4òñºîµçp\NàƒÚɉÃëÞÏý4W㚇æuÉÚƒ¦p´jùØT@ x—d<®¨1ðqŠFÑ·¶[ظ€ÃÀ«@}è)+ÒuYÓÃåŸXâ1Ei>,ºõ4ô?10ux¯Y·Îœ^Å¥[S‚„™A~·±>ïÆ¯çôVz»-p.~=ÿ昸Ÿ‹53ÊèfÆÀf9 6gÔ«s LÅÅpŰoG®^óO·În°V½.µ HXÔÛ¦Ãû±k0%¡u%¼Ñ×.l ø:ÅýO³Æ²lë ÇDÈÂ÷½^ªƒšÿBµŠ”[WGnÝ–+ïÄBûvÃȦÎH6È®º ‰ D:vj)Z5›©ŸòqÆÐÑ@rÑØÝé{çlúu]o:P5y=qÔ¯,¼/,ºtˆ;á¼ý¢Ùí*-iQ2Ú¡ö³2ÍëÊ‘Im˜u³-:,,œmäŠúÚ÷U¿ßô¸•#$Š–óážÕÃ×X6s ¿/äW¸9Ø^˜áÃ\IHë¼¾ùdŽŒf·Ëj@^èEý  Dጬ0ð…üP3Ú FLj¹ÆÀ7UÖÌ2Day¶JýHËù¢Á:L$®4AÞ~®ÀB»Òþ_]¯épìôaÜ%¼ò×ÿ„C*V N½‹ÇiVÌÛ X6éz qݘ–è,ôú!qÝ?G´ôó½òã¬aUCR¸¶/@ûJz ¼cáÚ<Öqò=?Úx‘fníßå¡®±hVT® 6Fš¹Q‡h7Í2v5ÒTpt@š¹Ñ¬å3í77ôáôI¯Xü•é¨1Ó‘ˆë^™Ž1ßWmL²´ˆdù.~Â)¬§dŸ? a¢!|þ—ñ¬°çyò8ID'£û~S‡Ìañqõ<2¡ƒrÚñ¦ÃÀû_€>ž ‹‰Î·½Ì°ae­ÁÀâ¯À%G Äö*éÜÛpk*UUÐlUœBÉ¥ô”ÙZ)mM€_˜B™J¸¦_U·öcŽ&‹Ç7½•Ôý'Y8QN=8 k<—v°f躥S±MOöo•o2~à¥Ø’S'X|ÌGåÊQ `èšÏóÓ‘uúÊ´N¯Že¾ D<•eTF-¾gY¼!¿€Ë]I"ÉÖMÝh0ð…‚¯\Å Á×ä¹ö[ƒïC×<†})äEˆ4V~¬Än=mMiIT?p­42² ß•HXX¤ëªÚbÔM€wäy~ô}·C/câq]D¥®­rmEçœêW ÄÆÁ¹¤lµm½®x‰çjγL[dO2ÞW}g0ðQAS›M³‰Òucjü:S;0+âÃ’Ò©_´U-õ4m~žÉëAü¦¦VY 8,f|«6rÅ44€Ê‘=‡xª\sÂ7ÌMÃ^P¿~î2Î/ßy ëé%SÖã1'O50@Ö` ËJç½=A&¡ÿÿ¤Î1ù°%MÛßâ©–ŒZ唈sk£¦Á•#A~žN/¶ÃsëfÁÀ7ònJo§Ž÷n1Ü$yá§»PÀ Œð¨:FYIyËRÁI.¡Œ´YæÈãdjï!xŸxex¨qÉàdjïîÀEæç¤­»¾&”‚äßQ§3îQû[_·ÕWñdKýP*Þ™ZÀºcºš +°@ÒÐɦh>|óÖ·­9öž×åD&ó6‘ÒwÇ@¾.}98µËÐuXe! §(•I DD6Ämzfµ^1ðµå'ÒI=–sWW%·ä¿ð+OuäøÊ‡ºsÇ+GrvÔ¾rfªòì+3ð}渳WDݶå4LLÌðß×TBVêÕm«µXºrÂÀûy€€Yö¦>,ûrÔˆìwàª[¡ãb½”X ·LAe]KÖL] sû¸èh Ço]× š°š0¶-Ÿmß去↺9þIÍÎiS\åjT[öðuc5a ì3pÄÀâ/À-É=R/¡dÌÖ‰IY.<õý•ü °‘‚ï?½äø€%Dï1w¹Öѹ7+#eà!“h,{‡7/ͦç>÷‡dà¹#‚®ø>)œ˜sŸM¥‘å²YRܰõÌc 0ÏÇ[AûΙ‹ ¾3•ȶZ–$%Àð*iáìíâø˜ù±»¥aå¸ßægÈͳÒßÈf5¯ŽXœÀ8ÃcÊañÒh=0ðI¨özBkuˆÌy®†§$i®ºFÓ´Ñ9¦øáèU IÒï æ)Ün?ýù™ètð0_¤üÈ8¿G‹ nH+7ÚTž‚Ó}ÙÆÑ¨J $ì|Eß©±+e^{ö+V!”cˆ—f‘2V!ÒC\³IrE,—Ç0se8<¨­TÜbàç©3že¿fð™ ÇßrÆÀ3YVÁM Æj¶¾¨ìØ®ÊÜŠèVjyoàÏDö½ÈŒË¶øŒÈ‹ÖÜOÝ{dƒ¾%J¸7 òF)§‘[Ówœ ïåø¬¬jZ0)úJòÎèÁÙ¡Rø„wñ§Ç$vUVaÌÀ4ŒrëkŠz-³³Œ‘ŸþÂÖD v:¹eaF’×ó¢üª}²…“%{rÅ7*@ä(œP™›ç:›à… dn^¬-c¤»…<öíFIKÆò0ƒýDülMÎ*Ê)Û¢'´ Мö™ƒŸšn%ØÓ©ÓCdáj6…hlÚ ouÿ¸¤1²cs´ŠœIY'ýº¬Â—©u¶&ä'Bfª`[ºÂ¦ÏÉüLÒ±™«#¡éÛ­jÒ£&_z’ŽÝÎŒr\âJÑm ë{ú–ÞgÇìžçŠ.æXÓ»ò€y™ù Š$©v66¬55}¢Sÿk×8L‰—^¹èîÝ’5éIÈþVÞ/MiEEVšÇYÅeŽ£›GAFóQ¼óØq—‹åì¹\M¾âÇ;WCοb]36P޹_Å/eî •a絃·  ¼c`böÈŽ±š‹™QYzkÆn†e´=ùéïÓi¾–5Ö…ºÂÀ'ÖòOR,áŠÊ.Ë¢È?Ñ–šÛ,§uZ„pý1‡ÏbÞŸÿAÇþz¢¡8ï ¾ß©3 €,z8˜óºŽcoT‰[Ø÷l·ìn;òÂ?”X.òŽ‚{WUóL^$qä¼±€ôÇ"sGî§%bLбY²¶cŠþúƒp ëDD,UïkIš‹ ~¦6î@W¶¼k³ÿeõÓš6£ü}ÌÝe=ãâÔßåØÑÚªÍIÓÀ1°@YÞ){¯ÖfigGîñ‰k‰)?€ËÜ6³òˆ =² b´fgíÜCšøþøNMÌÏJ”mɤ…Á¡|å¡Ì7]sÞq Ü ê7p>;o#F®ø@¶Îãݦ0ÒÓ¾ÁÐ 5ý;->U¥ÌŸƒÔáNf5ŒÍE®T»ÌGTßåÖÖeYJ ¼#/ÄR÷•¯Û©vGxñ¢ßdW¡b‚ÆŒcXŸùéËpwNÊðÚOåÜšãäz&Æ~å$I*Õôb)5ÛJa1ð$`Ø!+€ÒF™ð ¿Ð$ϹáõØ¥ŒEV |!`¦YöáÔ^UxòJ•%”¥fá=ƒ%÷˜>› ;UCÅ" çCEnó ¤ ÁE4ü4½æý´w%H;Ôn2ËÓV§½÷›èÖž"‹£×R@ÊTpÁÜ¢Ç#ª:céhîÚMëº ‹yI·OЗگ™²«Ñ[s5¼¦Oôõw¤_M{™Àg«'Zm÷ºTôšˆ¶s0ä}/boÂHIÀ"#sU= ceÝ@q™j¸cm;íʉUî¾^rŸIÀ‰ò‘1³ù8 P[jÛI¬ƒ‡ûâþ¾t ó¬úÅWuíè—.¦ z뵞';ΰÓ?¾5þdçù09\ÙÌ”:°Ì~fŸ‚Î…Ò]' p8°Ì>g²øêìÂõ¬gxJa¥±ƒû˜²UC®øDybúFùeàr"÷øyÑâHV~²ÊòÅƒŠ”Åž¹Ko#ó[m,ýHf?'JD‹ÿ¬³ý$½ÅÀ3bJ%£ÔöX)î{H+<î´)=5ƒEÕÉš±!ßèVxD„H/I7µõ®I¯mOVçíy™›¯Y;¾òÐ#‘/ÒÃoCrðN{2æÿ[0Ž€«lˆ×Mˆ ê”÷×w|¬ÑfªYïÓ>“+>ð^Ë-«wÑ羸ó÷í„ N%N]ÿRÝÕVè ª}Û¼.v²‹íÁÓykQñkCÇ:'÷îËf; D Š  Á¹?xáXÈ@Dû},µ¿êÍw,†å L*ìéq1ÃÖÔŽ\ñY³Kò^Çæí±kÈ3V@ÈL,{úÛ2îàÙaà«¤Ä µ„Go`¦©%ÀÏK^·Ϋ­k¦·b‰h$ú–r”çC<ãšaä…_’oQŠ2åE×6Eeì4Ü<Q!M;°½í‚LNhz•¹©Õ„:·÷ VzM¸’l¢Ðu]ÕÈy·÷,Ûi'ÈÏ«óøÔ{ëä¼zžò‹h_f›¹iY»Nq$t”êtª´å Ǻþâ:~ŸdáÖÖ±fš:hT~ÜßÍ5Ìœ“^ìVªúû›¹çh".ôQf·-µÄÀ'j+ŽT!¦Y—Yô[³(ø¼ÿkÉ;¿R.<ö­„Ÿtê]›z—-˜•O²&ÑvèœñÛá€nø¢$ïÔ!ĸŒsÇ÷žcàî›ø”§Ú䦑ÜúAi ¢¨^›f<—Ì›óÀBY 0J8ök³û ù#$”UfÁ³‡5n2H3q ¼ã’l"lôÖçàç Úo{;ÌÙÝ8Ÿ¬‡I©"”…WP¬û÷Ýöœä+º‚¢µ°ý©ÙpY‹/”/Ä´-¥ü~ i§Ÿ¿ý® õQ˜ye{7CÕøùñÞÈ¿áÖtÃ0°yX1ðVÂþäU†mè3Ól¤W,e¤£øË™Ú™ÕЄ†~§ô}""4»ê½)­Aê=‘ôk]éìAÌXá[§ ÿÖb¨&=tQjÿ¯s8×­÷ÍÙºNxC·VåÖ›¿õ^n}Ͱýù™%w’g;Ì‚+9Òçí¡†ŒÛÓï.§N¯çNxà#0þ× 75a"o£’Ň´Œ- zÞÉá΢È{bÆ4mר=“šeàuúêÓºÙõö0ufwÎÀTüq¿2WÌÇõ‡ƒ€è‰I©~fRÎØÁêræ¿u7b ÑxÏ5óØî¡7kÀÀ;ê©O®Jàïµ™g8Ÿ¨qíj¾#U½?º¸<È3>1ÛxÒzíçQ·Íéw V„U#eÎ%3ëQ¯ÐÂõ|¼1ÁPHxÆÝoÿžü˜\† Œ©"S;‹…ÚïVC€_*ce–=Y×*E€¹ ÈÄEJ¹…"g³ÊÑ-ô&;G7ÒYs­g/Dø‡ ‘3lÃ㮦¹…nçÅ‘w4îŽûnöÀàIïþ$¼iF¡·Lˆš±‰ ‰zdæ¸Ùý"šöÎH‚|Q}#㮽wºäçwT[ƒÞçvŸó9ò|¾9å´ÎMgÝ ¨?Ÿÿ“?YŠ=Ð"ƒý« OÔÁ·‘![Y (ˆ"%¢44“˜¿CÿcˆÞZ *BJDqߊì/ùgôNb D ÀJHgZ‹ž*0t䟘6øáü<…ÒXá÷Ïø{uöP*xR‰ûD²N·x§ª;4yÆOÈñ4*Ü×¶þ è »…•ˆ~'1¸´€ý±Ä¦µQ ÄJD;2Öùy õÉTPoŒu¡ª}2 fÁJDq(¢LEô¶'=ôËNwØLÖÑoÐ!-ÃNoÏ-ùÞÐÈ3©|¤(ßA>/s(în5ë·žÅp ÚØR³~vò€+Å£¬óùW¯Åªeñ¨r*mWÝSà ^e·erKxë=ðÙ=ÿRÅU©:VÑ4´º¯¿Ø€f!.·†kž/RÜåú›~ìzœ,bÏ×ß|v©·Æ“©}ضaàëjfÒ©=?ÞZ«ÞÕ'~–•!C)6zŠ–;p£Íg‰ MxnݘO×5AŸ…k¾è äbÎ|JÙc8¦–™ßÿ O&Ía»·BùÖí?LTA*‰ íâl'X“HR ¦%Sò$ìTPª~¼¹©áóå+áÂüpõƒÖ6ÃI‹›{-÷ÖÊ28W!®Êÿ$ÖÄ\ \—~Q}&pÏÀª8M©˜ˆõÙuÇ4c`iÎgÁ§ŒÈN‹=ך¹ÓàXnÔIã`~‘™e ¹Q Dj%)á—™›tëßiK^øï–Ï£ZK?Í]I1=,‹ã€eQý@µÍ÷u±É¦/ë¢úA+<%b‰:H"rWžóãM €Z¼]$!ìNã†ÁvȯW$‹pedºfï©íœZu# QòÆÝ¸÷6 x'¸LÈLÓÛž§i—uÓðŒ”T—%ÎáèMïí ºæ@*Äáw£ƒîc' m\=È”qŠ÷ög¶²ŠÍ+^©)ê.¸ÑÛ ©%À'©Çgõêšõ\òcÊ+«aLÏv|o½¬ÁÀk†U&®So#”öèOèίPüò'±¦¾…qåmþDžñ uŽ5©„?[ãü÷›î©BñKAÆý‘þƒÁ’êAÅ ™¯é‘0¨^¡øÅÅtckªÿÝÍÙ@Õ²z  d•Ó÷f¬³Ë43òƒP/½*]÷Z3ÆNPÜdrÁ~'áéÜöiæN·R•å‹8üþFŽ­ýí¯¿§ÛÒ_RAAõ ½ô<ÎÆŽ‘–·â<åÛRO–(ˆxK“Þ];ò±§k=Y¢¥y«$Ò’óÔ,ùä%œ§ãl0…W=®^zd‰ÒQ¶†b ÍUˆÃ/»vÙ„ѵÖyo Ï·¡BѤÖ,ïUúC¢>Ûo˜§)QØ·›h¸µ-0H§œ>6è2®°‚ƒé¨LÍ·-롵Iïû›Âu3.þ‚M±D¨£òçïä§æÈÖ»0»m óiô¥-¯Û:YÆOã-H£/s›åŽšmmjç½&H]U¯¿‰L374ïÚ®:|`iXJ-ÝZ|b³TUÞºÞÇÚ•þCpgÅÀç¥Ýš*4¡°°1Ìo6÷¯Ç›vk íbS]ω Pµ!i¹ŸîwJsGë¨þ™b¶!’–C@Á ÔY®)»hàN“X}œÊrëKÐ…‹œ 4þXؽk1°4¬1 \Ab5çbÖˆòjª‰´XæàûÒ.n* ÷A¨c¸Œ‹'سi]=Sƒ_{†aœüí·m#/üš»nÒfpþtïûUË× 9u©B,\¬ƒ³£‚Qîrê2Eº‰±‹Gîv´!ú&È;fakÒ`óÈØàô ™¯¦Ž‰´€*qÜLǤÕÑ+‹z¡¤4¢SSm7­yc /””ä-A37m[á_Ôç$ÉÊÔ1±0 Gû~{+ƆÞ‰°qæèŠôÝÚ1ç;‚üú¹úç‘ Yë— {î Ÿ}étí·/¹æ 5|B3·pB÷ó1C¹íu9uß+ˆÌÅ¡‰§ßÿ¤ð)w¤@3qØÕ7À²iÞ–o×ô}ûž/ÌMP @JŠqH(\±)!^ß)`#{¡!ñ?¿³}‰A¸â:Î0Ãù¢9ñ0ö½Þ0fÊ|X¢¹u™‰ŽU´}+XÛÊ™à‹MŠ7àçe~sOc£$gj`ÍNÞãî Ê”BX³I9òÂPdœÐ‰H#ùJ×h]]ÄaùÑ3Îú”0õ3æÙa÷ÆY¯¹EÞÿr$½ûçîsò1]SYNÈÍ€šEϧ­cå… +‚Lhé_E¾(2²_Dd_²ç¯ŠîÝäv§kò­aLmŠ KÛ{èY-âÉÿ4!VòòÞÍÈÄ!\¯Ñ#É5o©ó5ÇÃÓôš…Á }k)ƒî#"~„,AÞ 2W88w+³ÐÂûBó"™Ý14›GB)/#ŸxN¨IR‡ôæp_ÅNÕßH½Ë};Æò´ùºF&¤Ùµª›n#85 †4€,¬~›_ýÆÔJ¶Qj@LÅ<‘{¤„³f•,öèõVÌ^¼ª½Þ0)L\JM3tÃ8Œ—;ø^ I#J!ÚÚê¶õ+°ÁÀÇ;°)ÀrN¿×Bb1$…e“•®ƒÁÊ×ëmÐ-Êü…ƒeÙûÍ¿Gh}áZðѤˆPÊÿÎ<ãç5†ƒü¨–E DÚ>ÅÈø[7ó°äÖ]i¢oòCvŽ-P;x½Þµ}@yÛG·M,Œ“WþqÃíG×ÝÅaÙBï~ÿÙ÷¢¨Ì¼mùÕÒ+£áeªÐ½^ï3Ц¿-®gÃÁ`,,#+ÌÄÜ÷ãzœL¬dµ}¼e<ƒôâÝVÇN^|2\!_‹‘7ï +Ħùu!‹Ñ^¼)^6O‘µŽ gÀhGä ¹fÊ$¹ŸÀñãvÖÊv’ÛDžó†¸E΢¹eÕ;®†"ï¨:›8·,'óOèŒLÓþåpq•ÿ–™ËÈçßÕ}¢Ñ㩬ºORÅJ*%tZ´Þ‰²<¤·üëwt ³Ësž½¦?¯Õ›…iÂ,ÊÄÀ¯¢h© —¤kæC»z"P¤àŒ¦scÚ’­zsõuš}½MçäÁF6Ïrx»æ”e#4¨ñŒíÑöôšw`uâ&bêzc£;8B"gœV?Ýp#Ø19zwTõTɺú¤“e“}¡éÜTàR‰ž¼÷Þ£6b(AÀ-èT‘‹yiÜH“z‚üÄS¯)>žwå?|ÝKò‰>¾Pñ( ™†¦ ½œì@Öú˜)Äe£óíÉ€ 4#? 2,£ø¤Üß~ö';'w¿]í¼Y(Ýx‡Ð[¡uåÙ7D„ªrš#ÆíÍZºDÎuâ|ˆBUÑ?‹4ÞÑ ¢ÒýCfœê·o(ã—Sƒ]'C¼²¯ëçÇ{ÇacrÜ'ÃR²Fÿa×µ;®É“<£Ç}_Wy?A")*PªýúË ûì=uÛ&n $>íY*¯ ãXaà‹ÆpìCúõ×…òŒŽÊȾo܉®qŸ§ÓDydÓʶ•š ð…y¹©Ë뎱Ž·¯SJ÷&³±œXµ—ä…œH•¿áжÌG ;(è¼.”¤÷†Œ­Óyô<2³=Rø½‡eÓg@Þqe,ñ³W¹y¡“[ÿÙÂ× æ"Ã@"§¸@Sv^1%þè¸ÝÖ®2fÄ@$Πòb­K=ªÑ(Þaà)ΚÒ]zlB«ÆÀOä,’{ÿý=¶ë $~”Y$€Ûzs•&…וZí„.Þ8„øUÖ‘ïu¥ÁvYå4ȶÁn äaN«¤ÁTÅÏ­Ö¦õ{y‘g°Fæ6Ôcæ$E^Ñ:Ñ­ö£h€Þ××[·Kíñù)¾0¹“¯s¹ÿ†´­ È ‘±:ô]øÁ!÷gVúìŸ0,ã9'« ôí¼L#³±ñ|ÌÕK™¶¾}ŸÖž™ä¯m«?ô5ùÊý(‡Iaàí—Ñ6kÞ£@fãõæy(¡È;¶9 | {Ù˜5SÁÇ †Š…óbu°Aý¢ªá¼øzUZ}òX¢è†–Y½ 5^)02J†©ëôÐl&¶‰?¸›áak+¾ÛnSHVé Žª~PܱMüßy ª’—sÍ[~ìHëÄÉè÷'h#Ã6ñ¨bãN’–ÛöPÂÀ6ñ°œgq¥¥íJ¿A‡AlФÉÜ+ׇ*NC^øÉ=,†ºÊ¹n.gF‘gY–yY È©·4Ab›ø¯¿Aî1½¡@¯èýÇ"H:«cÚj¶kK÷?!÷£ËÛÄÿØ#ü?Æ èòB¢@!„#ï½[=)òÞ3ôpòÊåø¶ïö£>ƒ¬çmb9¼a_Ï·)5PCÒŽ»5}£ám¾Þ­àDʘÛM{î6‰ˆ ] hoÓl„÷ë ¡²§ÈJLÿˆ•­@Nåõ¢Éàì F‘5~ŠëÜããÔéƒáÆ7Á6×írÀÀÏs6&>¿ªu=“îÔ÷|¡šf Q±’³—Û:퀧ñB0©Y?êQøS²tÂîÝyD01z“9³ûÿ®ÄÛ Sâëë;i¥,Öd¶Åã,¹É ©A¦¬“êµ›ô°ôš)ÑûÖaêÚ¾±ýìFAÞy>¸rb0Jeån'xòâœ(sÚih‡­q;öz·~çCAf1Nc³¶ t¼¼PÜšéÑ*èN›®êÎ ïŒ[C¾v)óbÔÎ@øUs–­{ëtË<¯yÁ*>H¿&f1z`Wá[ñLSF!ý=ÎmQÕâdZ~o©+'«¯¶û°­³k¹âÔ× <ó`-Ò¿Ýuø@<Ÿ,òØ;×ÛN*pµ³jTeßç™X\ÞH'1ÆŠAISzàLïâò¦4„±n(õ‚vrE\Ô¹ÏÇo` ô‹âòCi"EÁr+Û®S æve+“kˆho›íûÜdŠ aÞ½ýÓ´xòŽX£æy7‹„trqyÏ—B2nf›TS ä‹âò¦4AI¼â¼”õJ^øJŠ´Ú~m{# ”ÙÅx͈läÒy=%~0Ò¦e%oèò‹Šß¿„µËs»8ü=ÞÉ1Á^)(À¯ô‰§+-L±mZ‡y«ŽÖòâòvö >©ÕFËzöw ÂÅ›JYU@zñ#¶ì‹+‰•ùÑJÒÜ-ƒL䊧¤Sì⃾‚M1=à™ãef®7ƒ­T¿¯@Í.®„ö|öÒ¥+Šq!÷ø‰#é ì^¥%ì$ÖM¾°pÜ7Z/½.Tq%±ò¹êó„Iû½î‘ÊpòÐ>7Z!ü‘·žw0e+îoþï±!:Ð`«E-»:tÿŠó||4e[vÑ6@ö.Îóñ¿_ßÈ b¬šeÜmÎŃtŠg"8ìÁ¨yqý2``‘~G.EÍïJ[8ˆ¬OC zµÞéYï­ ²ˆ<õi% *åÀZ‰WœEÖ¹·SͶ4”CŠÏ7…‡$ZºÚ¦w¶‹¡âùΚÌúPUÅ›fÍ1ž$盤ÚT* ÷í:·ÐU<ß ·ÅWÓîvȈí÷ÏW¢u%·UÜtSeA¹¼8¥Ú¨ÿ…ÿDLL¡ÒƒŸ§D™½kļ©šmeOæùèäjÕ.yI€‰OûÏwL|¦-‘Ï|ž»n9¦ÂÉö À˜Hs†7¬Öc·ô…ÇœïWÎä¦Wî˜d“³ä)æ,ØÈfÞORƒ²Eqª"2‹œ‡ã—?Êq51ä jQû)5ýnNv~ÖNä3æ…7TE%«u RÀVLäÑ/ÓŸ˜·Œ³`c0”ôÙ?±ÐC•ÿüà„&Èç›$D—–­¶ß 4PÏ9ßì6ËjÓ׬¯¡¶x¾å|Ë쇩ƒhä.„›d¬Ÿ9ßÀxN¢ú¥eLIG\ÎùúÈ©3Î`Ôo\1è‹çYao¥¥¢âõ#GóÃÝo@bu™rWã¸zÌ<Œx†þö—ÒÝzô±Ýx8Y/Úi! @Ñ€«Gñ¢¤— Ç{tV½\¡« V—,4ÄŸÇfÚæ²“›âEBqċʇÆ__ª¤ñBÿÇ9?ªg¤—$®r¤ÁZÖÏXf/š‡‹Ö,±€êxÙ*=ty“—Ãø•ºˆãÈF¶ŽãDžçrCH­låëhÞw —¥k¦^MrÒ#èßÈê20e•C"åg'ß{zŸŸ¬76›)°Õå/džqú–^Øe.ë)ø]¼ý©–×¶”p ¬–aíaSTž[æÇñ' Ë8;'0ðvj>T¹¯UW|ÙymAD¬(~ÊêÅýÞŸ]övðñ耢‹›^¶VHy狳/ti$ßâ¸fí¶ñƒXŒø„6Ç8ÁãÐèWeì°ñ<Á¤)ÃO÷ÎZdšr^O¢)¨—…0éã¬ÌHÍÀ·sA¸ÉuZ]e«-ïâxr#FÖ~“ªÕœ©ø8P²µ&Ióºcà'™d)=˘Tfè˜Å@”‘/³ò“ '¨PÄ0ðu¶ ;rßã.ûÞ@Xž]wA5n÷œ³FÉudä©Q×]È¡$³Òr-·já#ùíË…HÇÓô²¶k5T®¢×¼¢ö×<€V¬lÖÍnŽ Ñæ ’j)‡ÐÛŸCz@ÞqùòÐ:ß™Þ*$ŸÇÇå­,~˜ÚŸ*› 2i0gÆCV×2Eôzvx;Ç$(äÔ«ÁXw<(ÓO‡A)ÔáN˜“4‹êD`_ü g™{–§—T8:å•ÒŸ|ëæŸd˜G­Ù8Ì™æ%ž›IÐõLS-§Îìrãxu"•[ÁS›qÞ³3¼ð“AÉûF925‹Nv‰”UþˆÊ‡YÜ(?òŠ–SF3¼Jµ{ 2ù&mIÓü~97f·r8&82Îüþ7™•‰œ>±~¬M%è}>ˆ,yü}cLUã:Vù æ4âˆEGÃF7Š©^ òyp$Bq9õ-±>òMGŸý…m3SÙ*Çg¦» Qs-Ø"Ê̱҇%‰ŒõsA€FåÃ2%\Õg¿^02-˜J²>ð9òÈ+Zd’6¸GîrNÐ÷y½ë«ì²]þíÃj}ýé‘u»´xÅÀäÀ€íȪ~ÄÀÛïÀnðKû€§ëmì Ê©©@:a&Æíؤ=£i‹Í2=^Q±l~Zå,ÛŰ` &gfßjµ²ªl10—çR?jî`ÆôÂoT Æß ©öåF1/ÉÃ|’Vo*îÌÚI Ì&‰ó–Õ‹íYi¹<˜ÛÙ.öW2H«R¬ÙÂúNž:9Šþ•U­â®g óße[,y˜´Àd…œl Æ­ m5–“÷˜/Ò†\êt®u†U~ågo× çÛ…••Ë\¨ògÐ¥µ­'‚¼J+/aÑZXg¸ÜŒš òމH‰4ä‘{¿:ðdöŸJʯ‰´Ô0k]»»š¼vðŸJ*­iXú˜s(G9FOtËŽ%eüú̼ý:^`"·5ÈJ«²:‚,Žä]YæöÍ}7™ì áÍ#ÉÎpP°õ íÊ}DaŽUøì9úú7Rýs×U»ÎƒŸxKMÍø§µžØfÚmo0ð&:B€Þ£fXîÇaÂÀÇ á;„Ö¿nÝf ü^Ôc=þO/ê±GbM¤XûÏu¥©¶m³l› êÿøúFÀ¥)æwçã§qÿG$¹È$£Ö¶óÚU]K¯x‡£,‡y88n3½âý Í‡ôf_™©K°Bz|¼gÐÒÖ¬¢a²Úv0‹ÎÀ#;ÎR#ZW{YÚ¾í1ð†‰L€ZMzÓxÇæ‘©³­mmš¥<ÆøIõ޶ƒIÖ_±QëœÁÀ£,R©™%ôÚ²SvœŸ ¦éôC7 †WDÄÉ”ùP¦²Bw3¹âílè+ÓT/­v¾ñÌSz|”M‹h=p'@\F@½m[Î!=.D·Žþ4ó@M€'Å$HæU¹TËe²¸ïãry lUæ/ëY÷®W}Ö¿ÊÀ³žU‚à˜6zéý™)'A3ð4$áô@;Я™\0ð´p-sI°2ôa5Ÿ+rÅÇ©ÈQeí}ŸöÉùó⎟8»˜úow9ö®ã œÿ.W¢Gcˆ8¹ÊNÎÕ&W˜…ªÈ!ýŒµÜB ˜…—iH$»ÔǼ°V(½“+RG0•8U³†$ΆwÄɤ´pÅF´`ô•§]üq–][³6­-ùéOÌÓOéÏ¥o»Þ:è'ÈÀ'øerš™ÝnDã'PM®ø¿Ì Œþ]Ìõ¿ÜæEÚ>Rå;÷Z·ÎúÈV(òÔ`yõW{L]jí²[&³çéãr/yEÎvº½r]&xdà'yR©Æô½?!ŠÜí÷ e(¬ -ƒ°¬Qšó™ c¹íqy¾3³Å]9³2óÏ3ðJÄ“†ã:+;®bš0ð†ÛKë$Çfx X32ï?#Ëfg®ªºa$ÀµºJ¢3³rÚñŽaà'ÃÍ‚îþµgƒOLÏÏIž}^*½MY×$_D #nÜ—Œõ|`Xüâ‰U-›òË#ƒ2¤1\K…Ð…1íä.¸»æ,}âª+7ç:×RäõÕƒlÇ8ŠyfÜMä+"rT\ÒR³ª’!MqÐåùFŽ:U{GÅæ1¤± òA‘áÅËIuþð³sŠüÄÚæØíÁƒ_„» ÂBO”JþL‘Ý'%_;òâ/8uœbŽ‹  ùŘ $˜^§òW³Ëvº6ëŸÀXÿ@…·ÑÖ•ðq]ðê, òòkå͘yŸ!‚¸ ¢…ûç;!ãáß§XzÉ72Н7”$H§ m¬±>ú]GzÍ;õºñKǸ_ EEgï‘ze²:¬ç}H½o~M ÈO*¶¯ÉZî'Q•ëÆ€|â¨$ôŽõ[U†½ _¤ œÂËšùhO–ŒÞgÄãêÔi|H侌Yf>p)3±RB)“;)3GÔœ¹@Ö[U Œ®H7l´“[¹%cµäµîÉ›¿ÝpL”º3['¾òÚÐ_¿£iæÕ ¾m¡’ÚQw{üDºemB)µ!‹ö Wg³¶½™ÿž’ïäÍßž¤5$HâÕñ= Ö²º„v² ¼ßtž×z©Ëo?KÇW-UvrÈÀûÑs‘ÄæýOO«ßyªÞÂáõŠTxbþJfòö2wN.–«?)°>€Œ+ò0OÒž¦Ž+êžÃéàzC¾À¬ÿ,Ž:Tô4ˆ,æ~óŸf[rg¼3Ò@½©M]3A.y¹`êEY¥³ëæÃ®äuyʼnt•‹<Õæú…m+AžZ÷Ñ'0^“L¹RŒ AÞ12{ {l¥Æ¦¥×<)h$c•öß‘ÍkVbä'Ëm“«XédÓÑ_b´†Œä˜qâ>HsYI/‚ÔÒÒÙcʼnO™EÖ™¶•䉮'ͽJ'ͺY™~â€Dœâ¨ß×q)y·Vä»_Q(+ãNæOï–Û¾¶l$ßýzCÖõ¹7†«Å_›W­"H$[[æÊb³·“œ—f"“òŠ=9³ðÁ«{ÍÈ7º~"D>=Wdô]ˆ@I h;悪…Í.a€<Å…¢xxüEŽŸHŒŽ¥$~ñ•WTÊpœÆ{CÆü-õ „ü.HŠú'a¢3aF^öIæk†ƒeþ`(èXºaaõLÓ~ Ò&é²y»aN~™…•Vç¿ý¨É*w»ãrO<D¤1¦óFF>'i•U±yeY϶¼¥Û'Ñ8H®Ðf3µÛì/È\Cúú'W|¢’«?ÁØvíÈw¿¾Ð‘h›êZHǧ•¾¥â´·~ØjãÌo—œMd…ÿ qP”\éû©ªÖ©"¿~¿àúHO£T;çL2‹ïHÌDec[=ëÉÿ€¼Õõþîˆ •ìe½ žÒAR•©1IÏ»mü©l†UéAÆ?U>t\ÿ³/i f*ˆú’ü(Ž­zq²ò ë´màa¨ï/?Øc‚9dº1ðäëÍ"R0ŹÞ'rÅÛ{³H`oM[³¬knÄÈÀûo]% 83 | ¼C¿{ÒM?õôŠŸ¿µŸø+N¬™ðù³ýdøaW·%+Ê,_©»ª´ª.çþÌZ{ÿ@TPdÍÓ(™šXÝsöÌe,ÛB…ü‰ŒèšmÉ ì\݈ïïuüĬë6ÂI‡j0«ÑNdY×ùð„ÖdÁ¿Î™(;ælÇi²›¢ ß©KÇG„‰õ¿[:T”èy€ +ÃÈ)ðþK(ªC(ÚQàã?êɳ_CÑÉI Ìÿƒ n)ðù+A½_ |%¦¿û>-;.'i‹÷¯ÿ,አ{…wj4µ¿âh>d|ˆ¡ô áԻ߮‰ ´¦»®0Ú»ˆ{:l¾çíÀO¬ý4•Æ"ð~åFGÒíÉ𦛦%ÞðÇ”@³Úø²nÃÚOxG–H¿+eöH^tþ\Ꭱh_ t¬ Uà¬@S˜.üÏ0̹çi’ðþfF­Ö£ú* K5H×:˜oͨ;ùI¢ß*Ú…¬lÓ„¤@â"¥™E»Î2¼[“+Þ§žÈ1mÅT´†ÕÉç‚¶ÖÒ˾×ÅûéN~P}È]VSò§s"]hm?Ï ,ö2âNžš· k 1oÏîïOƒƒÚ”u×.h%žQî„x>E×7Þ%W¼ÿnß |žë>f¾_±¯B* Óì~!l@§lÿÓFG*æ¿ûÆc?óþ¾  ßøi÷—øúÕ7^·Éyÿîï“sZW~ðáÑP?xDþ`Þ>…çMÌÛùƒyû$óvDÞÕª<šR¯”OòQÕ…ØkÙ‡ìñý ݵ,§V ¼Q ž^a3]ËONb¾o p1E¯Z |ü”\o£9ÞÌ^Òõ÷q;)lÎ<®#ŒÄPgÔ]rÅçÏÀ¹zžÏ\ðPè”Þ©q1û®ËÉ…þ·Q(=ùžûÓ6j:¾K­6m†ôbÖ¥.æ•© dX9¤fÍ Ó¼µ @x)8Öpxw‰kßÞnh¢û¡˜/KlKݽ˜ˆ8“QºÉµÈ3$~®é<[ß—¥ «ƒ}–ÇëzB£CXíW;QÀã“„Ïáó²aÏŸÑSàÄ>huiu9”®G–á#­)îI àÚ®5“ŽÔ”¹…MÃTÉ=Òn*x˜s^ô|v¹ì£T~ŠáOsnæ ›6YZ*„ügÑµÍø`U(#”yÔÔë‘;ãX‘\‘º40Äg% ì€HöuQ¯P@ ëØr¹´ƒ¤ÀD½>ÎÓ gla¤€ÏÏ’ƒ>5= ¤q‚ÄÜ—ý =ƒì**nk­ž—nc$b×xgâÄff™ãÃØŽ“¡À;¶O/×®,:¥‡ÉíìôΜ°2D€=>i“^\Öˆ*ä} ÀC2ô|Ã7“B¯zÓ_ý>Û9ØÂtuÈ Ç\ºà_ɉ’&޹ɉ)± ý1÷+¾A' œu!”ós‹Á,û½¶ÛlÇxK=Ë£v˜âÖVeµRàý7 *U$â„ AÂBš·ªL€Yâý¾W¿Š¥ê+WÛVS åSˆ(?^…”a´Êc!3KÅfPfyWLcá *¹âëî:áqÁ9nÇ&¾Ït3Öe7 ©Væk°ßÃÿ"‘.œØ2ÜžìØÒ× òû'¤ÚꂼÑwª>d÷Ú1í ]!N“„‡´ýžÈCêºx;Á—–ÎËe.Ç?ÙôPŠ:712õÅÒÌó±­|rbÅMÚ—Î ƒ+Dõ2ÿùƘê)Û¬·HÓ˜í™ëÂs;68#•½R-J¬ÇŠÍÀ¢uÝk FV8P±ÅµÉ=>©ét½ˆXp—Üc4nû>¨Ý…·±ôGÅ2?çÖ¿÷’6Œ/°É:‚¥ÕT£‰»n%ÙX/Xädþg›–٥ѮDõ²e}Eúü;ý´‹cj[JQr¿X/y~»( Dú(yo-ö{ò[*áZc™ZÊžñžc?.¿%»D³íV.n’¶]]<'ï4üéFòƒF 3yÁŽ&C¬¶UkR²?4ëÊ®Ýzø³fyZú)*Ü~„BÊ9_lþ¸¸öâUø«Ê ³F 1xér¤åNTOÓB÷s楗Å`lxî ¹o8œ„¡Å0XnŠ ÙiðöÜžó̱àu¼E½“Ãi¶*>ÊÕZL ‰Á8ÉÔèW %³Æãy%ð£z_88Ë‚¯=–"?\§Dè @© Þ¯HJËókk:Úm·EÈ_M§»2ü£Ú£I•b£U…ÓAÄuê¯èx]q0®ûj7[œ$®S±‡]C"é &ºUL½ˆëÔˆ ÍÖ¹±ã#H3eÄujóS.÷è}8T /Cß÷HYôÑm›˜¨K7/"¹"÷âÐÃvÃ2^(^Pà‹ æ×Ñ&¹ÇaWÈì(ð}:É W{8¼ZÞ·¶K–çû뉩Ü>p¹•‰ìĦéèã=¯B`èõ5ÛÁ‡"ÒTüDCPîõè=n“Ïïk*"ÐøNMa#oSà#‰€8χ½ [[OÄ8¡7«jmGÙv ÖžßéÈ{¶+ãlB ­WüŸß‰ã˰ҲpøJl©Û¸àáO÷Ý„|›g:¯ À´ K€¨{‰ãöQÿÌÈQrnM‚ü&âbðÇ{]–S9iŸÜå÷í³ $/m çÿÛ’HL!& ×R6B#a‹x—_šÇ3lì ÞUU7ñ.ÃâJ|àË´Ê©®Fœ“9¼Ë€É÷ø.)!ÜÚëšk $’€Òo›¤í'\óÇgÇ8ó-ÂLvD]Å왥Àp0Å„ÉûÕ­)ûŽI€È! ñÞWª)‰Ï,ѾÝ{§(JÕ.  Àaº@ë[îç!œ*ÉŸ>õÇêÚB±2!Ž+扲!‚³³KFÍSb˜_‚4°5¦¦ŸáœML ¦-^¼S2ä`˜³<_iÉýðëÕË8y]yÜï‰Â‡|²øûÀa‰ù±@øqàPÏún?5ú&s¡tçVº¶qê9Šû5Ìã òÊÒÖé©°'§F2q^1K=Í7@q¨ªYWšq?Vá7£­çΪ¡H®H§ˆx¤ÔÈðŠ)9ê5¹Ç,ò£þÓj >)yHŽ)0'‚LP=ìëÂ{=U`”]Þè ˆºR{îWïdMô€Ýä¿eâK?KÓP`b¸· Å4Vë¨uÍ: $oxSGúÚ*¶¡‚Ñã¸ê+O2Ä­ºõðVÕ­K;/j Àd4t1FWrÅf¯(ðù9µ¨NræœCàó‡69|áÐt tx#y1t$ÂΤ’ [¯gÚ?ˆ5åýŠËbf×ã÷ºLóV¨5§¶ƒcu½ˆûíßÐÙÙ·½•-µ” c Àœáà ÀrhÝ1×ú:ó,âïóªá,d’ÍÄ$ÿuæ!xhF ˜B®;+Ž›ýëÌCbµ_ÄiðcÚ•¯lFÊëùá¤FmŒ- Íûd!OHc·.ÇÊJc´±éC¤’;Pð×Ý8“žçä÷œB¤Õabìs3ŽEŠLÇ-ö_TzÞŠ—s‚Ì>Uîì̼) S%Oü›Œ[`ᕽj½{þ3õ@©x®Ö…r®PE²ð߯s4¢A¬²h†F5­N¯ùþ½k„õ•×µ•XÁt¤˜ÕܺÊaÀûzÿÔ–[åZ‡Ub>É:{¨Ô˜Æµ KêT‰æ-a»òƒ­\e±‘𺟇¢lH.6†'7UbŠ$hé®c?¶¬™G LÅ@öÍeY¯”wØ}!T¼Ü]ÔšÛpÌ;M¯€ÖòR ¢Àãë‰yÕÎÏ|ΰ"YðÃ;º>8!½eVa„õ9t¥áU;Rw¾ÛDöpEt¥ÿúóçÐ|·C¬eÖ¶¼CZÑlÞûPp«]6®iT¼½3zÅÊie)ðŽAUqÌáïWlšÞ$ÀCZ ‹þ!m¨ ¦˜ãEÌNaç®6 ü Ìrc‘Œh6ÿ[`0L¥»b ˯AC<;5›Ýöy±Øßn5ÔuWƒIVöNSµãŠ#—\-ð-P‘áÒ†Xœ¡òþòÔx?ÓòMs±Ù'ûc®,QœŠ ÿ+1¿hʰ¯Ô#Ê—gïûµ® ×ÞO¢WãX) ¤•jÝ’¼Wa'ŸŠª¢À{bЂn3½4[󟉪H,Å =óbtàü @ RîS­Ðú×›K­ì2šßde#ˆ—Q¼rÚÖf5⟀=“RØ>Ia}ÂÝñ˜ìŸ2.;g¥Š:±äõˆ÷ã’K ˆ…møÜËd‹³wÊ0ù|„î^D†£˜Ô~Îv\¶V®“£ÀU#FfDÏ‹Þôµ¡À;CÀìÅ:^ËY3N±£ÿϟ̾—êeê¦EåâwžØ'”»ÊM¬0VµLc߆Êï ?Xxu»½=ÇWøL9+Ç×~Ðë* ÷EteŸì¼ð̺;^³gB¶b{/ö:».äˆÉÇï /¼F7LïK×/FÛ^ÚÂ,@(Û¦ðÚQ`wû츑v¶Þô0ú•X]—Xð©gè:®îÏöÍë1<™iàµnK]Q`û_ñë½™·ëy’é‘ôL›#Wˆ(š)ÞÎñ[,V7‹6+‘ôD @Lãìz>ÈÀ\Íãõ>j/¼Œ¿:ÿúºh\pL¡‹­L=”àŸS]Í¿Á¸?ÂïcNu5¯@]¶ÓüNKÃd³^„[Æ™o¿Î)`É"ÿº¥il…c$¼¯Ùj gaþu!H—¨ÊÚkÃ˰᎚©ÇGëÇÕÌ›)ð~‘Ùr‘¾æ¥+ÝsªÔöÈ&jã=ŽÖ™4üò/*º²—§"Gh3Þ0³·#Lää_÷«½#?ºù!çtÈù©Ô†~`]èþVÕa3KîñEjmѰ- ?{^ø¥`Z½;³|i½ÚªÏ0§—¥Õ»²@Í®UOle+ŸV ¼]Ë»ÆÃªä(mrEPwŒîò5pÌ„,ŠÆ[KX7øó±S˜aÖ‡u7¾î~|ì—) &¸9îñ¿çfødð­™öVv‚¢­ä“Â?ýú ›0p ð¬¿TQuI´EÈÖBB©Z¼Ç÷E¬°Úʈ­âÝW|_k ¸_Œ +3@m€©ƒÈË$êÙr ¤&«-ÊW/bÐÖ*3R-"1˜^µÀ途‚ ëX*Û¶ŒŸ›Ô…Ä}8·Š—ÃhD{|QþfÌ|v`ÈÎAï#ЄA¿É5+mÅÜ’,xœôsÿ"ÞdiÕ°Ùm%H¢9ÂáiW¦hŠFWEòl¾o„(- Ñ- _ ˆ¼ÿŽìºù8‘´À«ÍaV±uNQF¦ö1‰í>ër­BÄ–"s”0=©}!‹—¬iÆÂ'È'! Àt‘ÒnZÊnl‚Üõ,þ^QÇd1ÙZ†a‹Èí­`º +?†PiÍd’×ãöE)ˆ‘}ÄÆ«õÉzÞ¾©}j¼&cCkã*EÞΞÄí:{Çü\.&A’îÉνܮ¶×l7fNZö}øÉÖz8ƒÞVþÊbGàvHD s ’_ï´…åá°e Üåß´®ý‡X‚Ï “Ú‰:9‘k‹5º KPLr×9‰{?‘kÛccd±¶R6\;åK„5¼—YÃbve'Ø6A¨)0KÊvzcz6zª_NäÚv§¹©aïe^õÜ'W ÞnÇÞöV£ã¼Þ¤cÊdyˆB¦€TVû¥_åŒÂ\$ ¼F!…²RjUɯä.²Âq!-Wªïp@‘߇ÙÔÁ}Òe8A;îA>‘äáÔh£b­††aþ}ûè‚K±eáYê(ðv¨·n'ĨcÅÊ¥¶‰a¾@›ªÜ :áñ•¼î%•v³K9ôÕ!í–'Êwtr ,ž]”ÈË¿ä§Hƒ®Ö‚‡À¿Î`þ}–¶#;ut=o*Å,Þ>ÍeǼ©LËz ¤9üÑ7òJV¦T†Óû¸<1g é±)k¨Ó0K'[ ,Ïee ~f³ú˜½d¢¯Ž7íù+PI6]·ãkØ·Þ([¬‘ÃÔQàý'à&y|>ˆ|ÈèððìTN]EtºúÁÒO«©U´êœ(ÏDGÇ:žw!<r »y%)ðFä z ·¢ ÿi ¼íuXqaWfÆÖp¾¯ÎLm¬^ ëëe‘²N€·ãË®B£ïüf9çàÞ£€ÜÓ‹Q›eY)’Š£rÑ×xðêΩN tÁ#sÎ{é×RT@j̉N NVáÀÔ lc”†£æöÎa’©A ÍjÁˆ€·Ä~fµÂ½B™6ÞS þéac’%Àr<ÂûÝ)\žêJ'Ôp çBÌO¦:®WëlÇE:Œzo„Žòo 9މÉI,#›5XVèÔuÎk%ÒzòDôæ0ùüaW¶%+ªmig4FÄã}?5FÕ' Òv¨£¾þ‚°tafž³_öËL%fµsÆc/‰|ú%ï™ éMÊý§3¼ž×šŒ†bà wvî̓­!³òrö´ÅÀ{É5Ú‚vgXjCñêGÁÿ”ôEÉœÛ,r_!Ò›T¾QjwÆGb`uYnÒ`ï°æéÍUäS×™­+€?‹|Fv<‹½U˜ôæùÜ›Åw‘O¯Ë ÿ]äºã*Lz“szHä3Xn*Ÿ™èÄÿúçïH'žž9M¦›(…¢‡ª$½ù¡An;Þþ?ZîNà• .%ç6·tÝ6Â}ë±Îñâ•ÝÐÕ  Ra&ˆ¤@ ØñŽÑˆ¨áâ¬í¼®M?;ñuq+áÔ­­ß¶žÚ,j˜%Ýè^“fgÛñ†›Ì\Ÿø ‘GƒœN3Ña`…õZÒ¯£f½©»c˾.‚L"eáã¾™z§¹åøFÂ.žHÜžôˆéFó5×YåÅj‡LÛ þ§ &M4&¤6"8¡¾øÙ_EEwr+k»m«?£67L7º&E“ÅÆ­ïç¹ccDÁ<0 kBzѳ>*2“ ïÁ÷ØÞ﬽–*fýëY¬Ê$A9RĶХ@V§—ÕÚ‚kz«É™¾Ð.¥ËóHL|ƒÚB§ ß™ýß0óÖr˦ù9zƒö\Ý~xÒ ®[}±2o¾#eOŽРȯ#HpªÓ‰Ž5®)¾Ñ톅’íåtE¿ñ¦Xs·;–/M®êHFk¢±_ŽóQÈ—¦åIÃ8·ŽZ Ÿ§vTö¾#*cÛ kV QÝ mp©×iÝ:] _¸&0µGÖš =l]]¬¥DÄ´Ÿ®h<ƒ•AæÕhV>ó¬­` ÖÃâ®zÓ+91¤¬1‚Uk2wÎè¹øE‰ˆiG²dYîòk.x¡c¦*äí¤b¹Ï#Ì|ðDƒc[¬ÏDÄôïߨcåš-õ–¥Åù€ÔÝÎ%³¯ù‘Ž”Zo/¿èYß©Jndõ`xøú² „Í1>2Öõ´ò­8–î/D¬’}Q:„‹ ÙÄZìâûû;’äÔlõÚÈ&zÍ+D,á:×FñÝ34"'‘âæ¶š–wÁ©E³Ç¼÷»Ò×l3es¼•Ƚ­i M;v(.¢ÇQ­¦¬]»Z‹aÆ¡@>€jµ†¨`Nî7G»òíOhŽm((G¶„´4Ü]å¥õ¨¸oà‘‰Ô±Ãy,Çù:r;I¹,ég[Æûãú¿ºHÉHˆÎ‚Tjš¸UxV rŒ2ø(²gF­ÅïíÁO!v¦>~ã¶Xï—fxx%õv°SÐðV!Z¢²zc7™±-žx¿4`&: ¹’Ž:‹Gö’îFϾÓÄ0ÊH+‘ÏâûŸk´ ×ài,µqN1+d¡­‡ŽlÍEˆ ár/<‘ DÍ´xâã¸/-ÁkîüØgI¡ <éSøjgC%ñˆ ë ÜÏ‚ðÀHÊ¥ Tª®ÓYT=öI<=:º [¦ª©î_WÝÜ4Äðc'nY‡7\£œd\»:ÛΊ'¢þÔ¬¨~ ë¾-µÂÀbzÒ¢ˆÓÃìŽ?N¤ñ¦ÅÑô$®XÑ¢‰íÈJNøÂä7X¤v¾Ì­Hsî‘¡=ðóxŠ©’@wìï•Ì·“­Ã¹š ë*LÆ”Œˆ¦ML£ŒøalË1ð†étrï6æ:Yàûã²Æs¸`NtÎT5ø8ËQ‘‘:c…¦Á?,€O L…™Ø…Yò~Jêd´ÔÜ®=éØÒ7m1Æ×ÁΡ4 Qœ¹¹Þ–âÕopf®ó8@±A…¹ªþýÒ»F»ÑÖÆ´¤Ã@LìЦAÓÁ NjÉ1ðþ])&¿—iì%Œ÷ÿ½'òSC°\¼ó¨Þ¾‹yïÈl[;ÊÀ;; aÔ»^uÁÀÀªÅÈmô2F¦Ù(Á`C|ZhŒ{ÝÜXsxƒ6ßó‰Þ RwÎC(îþúqŒ2ޱîÃþoz |œ1d¨sRºi줒"*¯£Ÿ3ËÂ5#ÕÍ 6:¢òÊ@è;×öœ,s‹÷_³À ñT]¨¼RŸÉîÔc-ÖUÛõ}éb•½ÒK°+ÄÒO¬ŠT,p i{èãªîŸKgv“ïKàéèÑ”-Nüše˜1ðþKT¯Ø}÷2¹¿ZÈDcZ ¯~ü¹ð FvØüj*úðj·nODcIo8Œ1øní0g’Ð | †ù\z;‘QJ¿®³=xª®Õɳ"¼6“€ÀÙÁSõM‚ÛkF׿B§ê੺¦ í,Ã^ ª)^ý8dµ9´šÙYë~ê@¿¸:xªU;ë:Ì÷ tÕ!¿-²!Õö+‹½}Ôq |Acî3!ã¬f ÀãVvŪsË8‡óqÀÀ€ü —¿6n·ÿ,çâ‰÷éôð­ÉbŒ4¹?³BôSßÞ„£jÄÀßXQí·ÿË«˜žÇÿxu ü/¯Öï¸*!÷ÂÕ æ%¤ÎNЬƒ0é)?v f×€·B4Ý×^+õ¨|µÆ‡ŸÓÔ™<«á™ïëG<îWáÆVˆF<ÞßʈŠoC £úx—…r5¨ÆÊ´¢Y¾bौ(}›­Wôm¾ú –gR´nç)þþ¯Ñ¢0ðuJÛ‹½Ò:žgc8ûÔd‹_ý>wv“5bû<¬´×?G©IIÈx¿FV™i©E1áàs'¿ÖÅLÉÊOsÚ>Ñ)Ýê%u[Ǩy;ˆ¸wáö8ë£SK[NvFÞQž67^)bÜÈÍ8–Ï|\c5­d1OÅ5£Åd&IÓœÜIÂFy²„W 1ȪTèŽ:/›Ò½ƒn¡ ñôê û‰:KïÛZZogI8$6œnÜÔ%¸ÕãSXî '3Þ^ŽÈù8£¯X°BbE~6d²—æš}ˆ)àuìµk‹WWg˜Õ•ÞÂM8_0ðu6f@• ÒNÄ7·ßewØ>ã&ÜÙdY×¶§tíA¢q [qs•C\‚)œ)IZIgãY²dP…¸ å¤ó²¨uÞ›U3«“Kpû÷ÿþIÒÆ)C=÷¦©9¨ âŒJŠôèCŽqbµ/ƒ ý &‘˜µºï{â¡”å‰â`âïÖç|ä"‰ÅïxzR*IÂmX¹pÍ>Ï8,¥ fy×PCA}4‘~8Çô°0=ý1=g‚:w ç†4­ÃýÅ—ü¾ƒºáöŒn´a‡zÝ:áuŽk?¯Ì@™$\Š«^µ¦à¯\¸òâÁ›B¦Ý0.1—ñœç7ÙC “0½ •8ÞO‰7žsÁ»Á‰Ì` ¦ HDüíÄtã's$¦ž(¼P8ˆCp'ä ">¿ÿJ-nÉ,ž¸ZëçÞaàí(Ûë›ör-BŒá£?¦çyÖ¼üµó dÂ~뛹]§Ó“Ïïâ 2\Sk5ÄJN>¿Äaé `…ý)j`=0k]fU¨žU™!¾°ëg ¼ýÊQ,Áâ|ž .Yñ"“áoõà»y%ò |`.cãàZëZÓaà³ 2†F3ÓkkºâÇì!¹ÿI"èÙ¦iÂß |é­äS ;ÕºuÅëRôvur+ÚÎ6`þ Ž>HÛ$ÇoâÄÖC·Šâ‰÷"Ã’®Cb¥÷õ¾éóU, z(¿Éfœ„£áZÀÀç ”,óÁ6“á^ÈMaXzj{¾Šó¹içi²Å_¸vîá\=0‘•ç7£/1›‘mCÓaà %òTZnr#Ð\W!ÂÁÄ¢<¦J3¥ 5º6~–TY\$1x.G cŒ?Ç×ü|û1piŠ:X)3Ý"fÂ| C¦ÖŠKÂ!XŠ˜ 3ˆå´´$@”—ü«sš=üjÝ“q,^ªh@‘¶›j¹Nf=±ª*»uN¾¸EõK;­"÷Ìe òMùÞ¾Se6á± €ªÌDD›8™ãÌS¦µ‡ D‘ßÄ‚­¸ºég*Öâ‰O”æéB 7WÓOµ‚˜|u¥ô¹£ë;Ѷ—øB‚½9`¡õ4ND[ ¯þ*§'qˆÅl %,Ù£+€7Ìeu<1ôH¶UØø©õ(w¥Wˆm°$j1Ë< ¢– ô}'j1¤i ¼}/(3Ë¢b~ªSªKkæÅ#Ÿbÿ&—Ú ÚÍ*’A¶xCN¬‰7){:±Õ³¸ ÊNû©]­:O!ðSU¯?9±^Âæªž—}}ʸ„1®Ëba=–:X%;® …x÷J‡jˆU0ìáæªÎ+î›:‹›í2’ÈThr¿® ¶0 †x‡Ï£^›³æÐf˜]-/~L…V8nµàUˆþðgª×•„ ›¨ÃÀ޾dVØâÚÃ: ¼ÿì “ø(ùVP”:%6Õë[áò l[jX1ÆêBƸo® $vhcàëG`¿‹W¿Ñ…”$.ez"¡~ÃÀϯÀÙóbÂÿœ‡8ke>Â^%±ÅD~}¡ã>eKâqß4–\‘·_ŒûeiÀíªÊ¾ÙxúðœP÷L7Ÿëâ}9Ð6"Å9 ÿ”ÃÀâs'Õ¶øq´œ¦N``ñ¹3ÏjNn€‚êýís#àL§©xb…ã4ùN W¶ZóÅ_?ݯºcª?·:Ã/™1Ï„›Øv–¬àŸUgø%uPÊ0•@Ìþ#3uk@vìúÈ/T]‘idl~Ï܆yCÌ ¹ (Lx8‚±Ë ä=eÒr‘CÞŒÒJiôÖÈÇ¥Š8Z©Šø(+­>E¹qXk@/àbPCv®ÁÀ.7NûÖ,T-#M›h|bÚ&¼”qÃÁ¯>eqnŠ…rc"‡bŒÈþY÷©v”¸­“i¬>µÓµÜøŒ¤WŸ_«ˆgâ:¿uþ\ELéøZŒñZE¼“ÀíUÄô2á¿WÏå ¿~PºˆUÄ1³<•ÏLŽÈ^µ{Bö³é—m¢ÅœŸññ™­õ ïõŒ ³o:Ø·é¦ ¶Ü2×óG<”ëDjÚ“ã,¶µÝÞ~× ÉKÕIu˜¥ª¹d¹/V25t: BVƒá‘NËDåƒZ†¶žÀÛ™¾Hмa‹­ã0Áké1ðHÐíPÒÐÚì2" Kv0ž,C©—(غÁh´1½îg‚.*5Ü8³›#ArÏV˜‹,fçÂ}¾Ú"¹A³˜q rƒ¯{A…K~°pü k&m`z—ðŒqЄáÐÞJš¬DF´Ô‘/ªZ^££Í.,°ëAèX¼E0ð¿Lzuc©¥VS1Ægù w 'ÁDl8‚¿N²gHUµ<}k3Ì}ë:öN׬ˆn¼‰Ì&áÊÀK;ôJK¹èzÑí•©ˆ[2mÈ’ùNÆËò‰hzŽ ¯Å­ÝŒ¥ —1Æ€`£‡®šWõûE£ øãÉ>F_<±#°N¸Õn QTªƒ$#b —üO|]£€«Ïøõ*òéÍQ£'»›ÕÏcñÄ;{7 ìÞÆ¦PiÈ9Ž×«\f:’/-v$=¦`[”l8Kn•Y„½Œñcã"»UáìÙH«-~Ê#e¿7uŽ”y:Žd¤å í¼"‹†Þ¶ú1^‡‘†•=¨³’a&beÅÏùºÜ {°%‹\E?Sùuÿá ¢dYÂAÕ×òñ=©®üÚÓM%B¯÷É“w"÷qnë°y±ÒrœU¹Ð“úÂ4†ûkʺe€|adúE ¯çš–_F¾»n÷gã&å:†=~¤/2òs TÂtËX¯FÈIk}oµËmHJl”ÆæºøE©Õ¾D..üG”Íì`€¼!7šŠ†p× Ó;¸K®b§ CûpTj¢¡Méõ)ãdh§-óÜS»O¼ŸËå(‚½sˆïÀ9¶öËøüa_˜°/´iÅÀê§ÕNf»ù‚§/”Dò\2¾zÝêÍ9ŠG{Í¡¯††©iÉÔB‡ÔëSJ65ÀXÐPâÇÆˆ`¾.ä{ÙEj²r] Ï-™*ö_³{²n<žŒ×ç·-ÙZSŸÍTüp¼%£I¶9f޶ùç²%ñöé7¼}>—-‰·©k´}>×-yÚ”õL;­:¯Ï…º2o4ÙŽá<ŠÍò}Ô‡5R&ž3r;k# ÅàõA[²°ÉB‚µØ±a)ÖzÚ’ÿ9LÚX¼«Í¶ºùbæo_%=JºW7½°ü‹sª«æ9ŸÙ¶S°¦ƒ¡3bàíûú‡¦É6¸$æ+pÊÀ¶ž$¤ØI„ ‡ »œa`êÁp˜âÀеfTI»b`u]oñ`—Û"D·éûÏi §åÆS`ßÓ¦fÑB!{¾¯k¨•ñÓÍàHÀã\Í¥qGŽÁø KH?&m´´„Rª0,¡.¬õ`d•I@~!K'w#¨Õ¯tU\ß&o´¿ÒÛs—Ÿ«’.Š—o¿#O';"¬cK%ùt{—Éøúh5Ûê~ Î:aË3=uF [X”È¢dà3¥ `¶ÃL¥' ,JTÓ׉ŒFJ4ì1ð‰I0Âg‚ʈçê1޽§‘0_¨"ËÕ–-r“ÝÀ0°l•©Qt^úaÐ+Ç@Ü(šÙ½F£T«§¾˜pÜ(ÊS1«ëu ஜñŸE= g£èû«lMMž9 ’dä%œ µÐø9/»rœ§Ö^®•YŸx¿,~,‘G’¿>¾aYp_¯+x[Yt Y3BjbÂõÿ„]Dzä6ü¥×lËãÜ÷EHŸP°4 '†¾~aITwkW1šS›„­²2y7ÏyÔóÍ©PÊ bª¡PÇBQïø–.t¼]XÓ6tEŃM,–ôŒµ¨É:"dñ“_y…¸d˜ì~ÏÚM)„<4¢ÎeP´v—j O©TDÉ{’[{O§™±ÔJÅõ˶ϻmÆïyKÂD ‚!½Y³¡qì E}½ ŠÕ®¬’Ø[úE¢YY<2yéxÑ0îŒîºãË€ÏS'©ŠÆ vã¥ÄFí~æëm7w7þC3T 'ŸYæ{´E®)z"´ј¿ž ,ã©\Ñ~”3%LñID^Þv^§ç´ØD[ª5ÝÆFdžùÅ’g»(-Ój3¿Ôž& ‘×â«d\^Ÿ‹¬Œ™Ë@Qvß%Z –ã9«/ýXÖÛx|N5×¹ˆ§Ôö{;4ŽÎWñ~ÁG6†jìš$ ö*Þ˜ I‡šiµÛE?ý|ËòCJÕçYþ«Àû鑼WZvbçZ¡v,¿ds‹ ´ ig¼ ¼ŸžÙÜFa&ºÑw7!¿P¤mŽ&‡½“)©ˆÈâÛaÄÞØŒæ8ŒˆÈkÊ}BHæ ‰CÓ Ù¿[dxò“reU\Ùu+í“9u[éîó…Ê‘ÉýþD¨š&Q¾_uþ¯÷'ištþóºbû°¨áWbÙ™\Ù#ðþ Ø:àÖ¢w|¼WëÛaÎù"ZÒKV&‚‚n¬%]Ò€{g¦¾®ž§´k°}ØTC4¢^׌ùûw ÿ…‰#ÛÑ®‰ øºævµoÈi$-£éúæ×-$ÔÙ¸5€ p+޾Ûï¼&„éÆŠiì7ÙM !¯ßs40'òHD³mÂŽn[3Î[ÝÐ!ïßs´ªÙà/ú3o´DË5›Dä—ã ®`]’”Fäë3ŸrÈ<ŸŠÈ2Ë’¢Ôä‚+rfIq¬¿å>îEuåsŸP·Çã”%é”%¡o/ŠÏ³Ûj®» ¤o¿½‹¦¥µZ¸$’-é.õuû?JgéNæuÿlI&GýDÖêœOt¿õ8þã¸Ó9UœnI2<©ô™i¢£dIé,sûøÊ–éz+³Jä9Z¥ÓàÙ¬ŒTàשÐõ'2x®h)~b¨ô¡cP w7|âÐ’¶ÊÿÎ>Jäs—†ΰMSª#--ÿ7gxÁOüWÎp›l“™KÃ;gx³M^1Ì¥!µ£<Ú‘3zp†_ï·£2ÆàÎÞmZvHUjå{mW{ÕŽÓÜ4‰ÕTþ "PôªsÃÌa™µ‘9ðšÈègµ˜Yö0$ŠVyÒÈNéF¤c¿z§­ è‰QÝ"wÃð4;Ý6;ÛxrgB*ånP*X¦ºÓÑ[÷Q~úé¥BÃA½wüðÓáÞº÷ –­žÐsI\?­]UG×ÖÔæR]ÌÄBæ~zÛì`Ÿ„É÷L‘û*Ûà¢íf*¹87iHbu¡Åí.âÖŸtõW^>Ès'Õ¶F-1CjÇâkâ˜!hŒýqó„l‹U’Ù”0ÑÈ2ï…Ì‹Ö+íó4sŒÇâÝn0ƨÓÛ8Û|›æ@T¯hdͶ)]ð”vòË^à?òžÍ[ŸÊqM<çË Ã*0À QË"+õ MŒ$ølߑђ(Ë#¦IÄ~L½Œ£ ’Qƒÿdu±dÛt.»]ÇÈKvÏ“ç&鸩¨ÉcÆþO<ì %ÿ»\ymötb[™íè’•'/’l•“¾C™…ž¼'x:©¦Ú9£·x·•1išÚ†³ÝQ¡‘È®*ÈyÙžáË4Í©H?"3Ù tøÒ¶²Õc[QÔç—2aˆ­DÙ.‰^v„,s)¢ÈÈÙ×i_e× _G{º˜±Á¢]ÏÉŽú¨¸äêµîÛìL©Å&dè׋\Õ9H6»„ÁИ+rZy2õ‚f·ßNW4ŒCÆþ'¤y1·'³™µXy: È{Êíý¡JTwÉô´¢öŒ{º õ z#úQ„|&$llGD¥ ]%(n¥×'²ëìøèÆ®ÇÏ,±F¿'E÷½óLïÒYZùMÌ?»½kS‘{fÈb“Ž¿\¼È]¶-kIl¼†€×´÷ãLrņfRšäÀ¢ýûq´Îj1vÿIÝÜ%#7Ð7³9c³øÈd•¢˜Ê.ùÆxg—Ðä0’åu¨4olæJf±ÊøÊ õxë6(j¹î é}—GÂsTôEE'Æ·}Ö[JNÊk¦XŠb"¡”¦Ú5)¥–gÂ’|i‹gú Ë*Í´¤Ì¾¼bŸÔSëmµ!–ÒvV¤)yût¬ìÛµѪsÅþ(O {µÍ6j¢‡ƒŸ;ÑÄ ŠH ž·•KÇ\ʹ±Öax´Ë}û'Þ3ÿºXt Ü(Ñ:/[+Ž´ÁY“‰ S|"£»``9k9­ëœ.Ë¢Àº­"tw Ðárð,ÑÊwŠFÍíØÌ 5x¶ÆËµJNÒîãbšQC^²5°A¦ÙI7ŠÚn€‰”íCrÐßLÓVúðË 3 ëneãˆ7$†(™KÛ>ét‘}pðmœÌŽøþ~9ÁÿvF»M§ã¸[IÒÃŒ¢áÛÐ@ ‰#—; aàîfHÉ—Å•(´ö/@?}KñFЉüŠiY`: \rG¡àn\EŽ0'T“:&Îq@ˆ÷ ôÜRº-tHgÏåãM÷ç•W™T¾Áínß;)Iü1å7`ÛÛ½¶ôÓ1xŠÂ¼ák\­¹¢ã6aäá•Ç&ÚoSe›|1²ÀH¿…oSÓÀÂF^sdæí«‰TzÒGhû8뤽 ”ç~ÍØÈÖŒc£P÷\î§ôTï3{IHÓŽí‚‘ÏÀšl³¨'GúŽÈç;i,ùÜ Fꎉ š{CùK„è>]ã í*´¥Š¸Ì*ºûD“°¹Éº,,åê™7Tž:“mFØ“sNùDÃò ¸Â^!àqÉA…Å_vRoF×4>±tfbÅ{=$&aùÄg¸özÁÀÛY{Sòypn…s*‹/ß4ܽ½¿„s.)B€† wÍß…gŽr•jʬ\à+²Œ¼æÈ ø§f%çaR‰ÜVfr­‰lD‘mºå¾HÕyOzA€Ö%>v“°å˺ äã\ÓÃdUvJÖkW'áï2“k ‘Xé̶•z)õQ[fr­ÿD±Ø8‘ †m¨cd‰j5}TíF&Õ;M'|å)×êºHRE®¼&óœî?ËS®õ4d öÛPjõBfü†DÒ¢ç µ9 ê£âzœÒ8µ¬Hiœ+3MÕ3¾ñ ™“Ç ÛYe§¹“äÌÅyó+AÛ;V¯zÎ×Cí¶Q}Ãù.‡#R.Ññb\l"k–äPS¾ Ðà&Ÿ¨¤0$^¿í•ifôÓ·ö\ød$Þ±]v¨da–mØëø8J%‚z¼?SšU½ˆ¢ÌÏÌ -“ç&uØ !¾ãóç{¨;_m?Öœ_W/s,}f^hþ˜–¥v´Öw{<ÉŽÀ[ŒïHÚÍãQ±&ïß4ó™FÚôÄÒÌ÷ã€Í®L,qŒÀg¦¥’ýO'qoŽÀWªZ á‰J‹ž±5O™nwìBÍcÉ”ÝC»a©š5øV2t{®oÈegñö !úJ8NtÝ3›ié¢WwB) Ì ”VkKúðË5Õ§ämi‘Ð=rÜá¸'õù:GbSævï)Cȳ~Ñ!Cvâûª[Ôš—ÃÔ*ˆŠ ÈPwËH –™«•¯<‘^Æ]ÕQñÀ-!O=ž¬ÏGÑÚ8ÐFxø™QÜ:øË†°‘:@møˆÆúÏY+ü“›gDR¨C­Tä§TU(—ï[ÓK³H½yA:WÄW‰øÒh¹öuH?^¼©Re’÷ÝÆÞåÀ"ãOE"´M†å¸.MµäÀkFŸŠLi„æ›m"<ÚU/äQ6±Þ&cß)æÅÛñn]:5;îcjósŠm¨ž›Ú¦¬ÊE…@g­¥Zw5¬]<+:þû?‘³Àöž-s| jyÿÕjäk?ÙÌ~ÍOT-,Tm?·3€øJ[ p/˜ãÙ;CG»4·Ÿ›S› ºš¨X ­$œÚpz[‡¦xFŒÆ`"mx#íO1g–ìW‰,#<Þ3×ÑPû>¦*»ø@{NL`ì;Š™lM|žE‰>;ð·’+tJ--úêW®åÂÀ.H*׊À|sba^#q%@ jð|sâ)Ë ˆQÎ!/§.K0õ o¹*56=B92  Mˆ­]6„¼žÛXLwjM€A12"d~ìî0êA¨i«Q¨Õ/÷ÌÖ%†#D4n“fÑÔ.!2º— †µ4C]~yæµ›|'y“®bÄøuZ‚$u²é®cL«!ËO—KïyÑO¤F}6§xœ+ì{§Ng“Þ³ÈÍ¡›è¶ï¦ïՆ窥ŽH9÷³ØT…‘×ï&›“3ÙD}Tܾ#w‡\òžß)Êd³)ÈÂ×#o>›þ"ÞùlNéR(!Ÿß9gf`<ÓƒóÂ7ïNX~fvºg÷$ék[^;’d³ ø×Ï‹êi#2¬6½–6EÈ×W^ ü°áMș놴JëM®¡hß|üdæºQr¿Ù÷ArªZ—óÌÿûjS·6´s=‚|ÄŸ4‹#ÁÛæ~{5¡~\¿ö2Èà¨=·Ìï4f-DR-Ð0Ôžû7¤$•ø@>>‘Ô¦‰¡ ÇÈ(åoƒ^ÁâÜ-œÔôm$?^ß­}ÉèX_éM€Û×›ýΦm`+óÏIû¸·Y­R®é™ÏO•ÑÜfÊT Gæû|3à{ê–¯™€â¡ûè¤"G-s`nœÞÑEj„W úé#û ƒÃÝÏ•šZ‘'0Ü»r†¡mú#N{"ÂÍìä©ôçL•ð;ñ¤Ñþ´¨ì2DçÀ2WíˆRǬۤy,¹Ù™ê2rìÆº.§5ä%“úbɱÂ=S*)Ð_²·$´\sBê¦fGΖ›} &Û!og0ÉãÑ,Â𞉑™:‹%ñlÜêzÊò’'¾Ô/àšÓê ºñ°|fD¶x`#n¹ƒR€úü’…s"J%ØÅs»êËKyZÜ%³  ëuºJcýÍ..Úƒ¬7N;„.•sØ1o3¸~èÑø¼f—„,Œ¹Ê¨~n:”AÈó–^ºö÷;Îj<®g-õRÛîÚfضn{ÜG1ä6vXG;TÝÚ€ú=„Ü¿þ 4 ù¦Æ¿¹ßâI±_ÁìGià8+9ÍÎb˜tXÚ¥( ù~Ë„¾C¼m³ËQ¶ o¼.Ý Ä;©¢mا‚@½y»æÈÐïŒB?±îyË)*ápŒ8︾_ßÞ3+ ª¢i]«f³Â­t;¤ÝÅUq¶éŽÙÈ€¿èy"ÃæBîV¶ Ô¸ äë¼§”<4¥ (äÜžï·<œó±kÛð” ýèþóï_‹VÅûik¿=׸oßík,è=ï1œû“ˆ°.qÎZž”tòš!ãnè?Jjƒú(„Ü1ð«Rà7nf°Í‰æ{¹M\?ã‘ñhcÎù M$¤ï#ãŒÊÙ1‹ ¸tÞÑH!÷?anÆõÓ¹“ÚŸÓ!Ãmn!‰¢ŒjèU×NB–¡Ræ«”‰§å#qPzlP=~’£#£ÅZE£ýw- ±ô8‰ g56±=ih|>Š,@Mó½ªVÎÚ!¯ÿÊ.­!1äþõ¤Â0kškm–š¢ué‘éA'Ö½Í_l¦×njùr{ƒqŸCx!ãJ‘VÕWéCnW«GÛX GÛ­­´>äÖ¿â{ú–÷åØ;Ù~OOüìÇ𞄤º­ >ä6>Z#©llrÓÛ0àÞ|^þ=ŒçèÛŸç;Eª5€F€hÌ?OSžC‚ \žÙƒø=o'²Š:Y ;J¨$µÒóþiôc[’.’¢¹ù|äÕ¬¡åATWN†!Ÿ9['T24û${¾«.Í;Sa‰ÞìµsPÇyóÉ øu7œNÒÿ¶Óœ¢ò’3k•hQíU;µ³nDš˜åן®ŸføöÓÉšoZªýøéƒÅàÂŽWNr7éòåòƒI ‡]›÷u[ìæ;çrùôuó£Íûº ¦L“Ý;þþã­~’S½mõiŸöŠÇÔàRàr«p[ê˜Í »²%Yu]ùK5@U÷ã}?+¢Ï'x3šÁ€ûë¯-èZû¼gP…ñ É™)©f¹èäŠô¾Ó;¾”©Gµq&¡¯[>0­qì}PQ'{ïD5æ"¶kLÀn(ȳ³$šêþü‘¬iô1Ëï¨gûÏ…ë5®×l0ð…"¾Tê„[üŸSÛØ|ÿ ¸Í‚ûé=~ŽÊhã£òÓßúˆADñ;vÒ¿½±j]wÔ³º4Çi!JQðJŒɘ2¤Øå#±Æ¹¨)0ù5AFd-•¡ $kµsBÈûóLÏ~?õnZñ¶·¬$<¦ŒQÚ¶˜Žøà™UuOÿç‹ £Ó…G>€ªíýyMÕîVê7‚y’ë¢çÆ3»t«”©›†HKíàD¹g´m›”©ñ²î×–»i@âž!hàcDIÓÜVͦŽÁ¼4×zmü†6oÒŸ>'°ˆ…³à§:·¦W6‘¦ß÷üwwÀ(i7µ°²M„´ÄÞïuômÚ^ûc¬†Üæžÿî€ÕŒÿÒÐ5ø/Ý;òÄæ½Çͪm56§eŠI¼óø1Lµ`…WŽ«( LL™ 6•iA˜fp…’í?ý¦ÆáG/òÆ8·˜¥‡äþ& GOn~¥ƒ/¾Ÿð ißFwýUp/«Ž •öm´yU,§™ñ;jðóâÓh üÛ,ý$OÌ0B¾yôG»Ï÷0¿T@"€Ó&kØÆQ£÷¸O‰DÃ@6èÍ`à•dÝ©ÐObôgSЦP£÷dDP$)qïc×þh ò~¾ˆÔ0æÐ{š$lá6ÔÀ>EƒñÀAM*ÇЯM1ÝuˆylI²t¬erÄÀSÿZÄþuµø§¶©ë 0ûpõ'J£Ö¾„`ü‰n¥ÿĤ<žÄ×’±E•䉯ß@çƒÍPnä­ß¸ãœýè´øEÇ禣ãø}ŽÎá™VŸNª&ÿ‘è_UôàWÃÐUZ<Ï[éôÇ8YT!;ÔþëÐø8ÄÖ©û¥ª ¹ûñ£ È'êõ\¥fuV Þ±ŽÏyäœìð¸“FÃPw‚>3?eÙ©“»Âr³A¾¿_2jP¬ÕJ'Q‚<ýB2°³í²I¦U»ÑQúú{SÂ*û÷:§ë@Lñü\ç ¾ó±Î9´ˆÄWe²ä¼XzÅf¸d~“Èï~é± ÞmÌÍG¥êI³ ˜aýåzÓÓ'ž%ÖÓ¼ÚJ¨Áh <ýK£_‹‡úŸ®\1k¨!>QÛ”?bÑv/–`=ªi-¾PÁ$"¡wpDR¾Rtx²Û_†GˆN0vOvû0<Õ1<º‡½%»ýîC¥R*?×Åf¿ÇÑÿG2ŽÙÚ»Æ[>.¬»jdç8fÈAèÃ8nŒcv#ö®;§09u³œªCÙ5 ƒ»žV| 1yv'¹ß.(ØÏÙùH`( „ÙýÂ’±;iµSŒêµMj·w†JÕv¯rÂÕ• wÀç5hö@gÝ~»({HéƒØƒñ‘¡q?p€¨6Á$.Ã2"F'¦d5Ôi¶”Ë<“!Ã’™?{í0þÇ@1R›Oõ7 |Éöé<èOí¹6+ùG«ý‰ûÅÍþÄÎ?aàþ„1® Ÿ°3cø4Ö*ÙÛ ÞXí*È€ßð„Ltœm•Žmè2lã󟳘’ºB5þ”¯Až!"¦e¸FŸ´Œ ÙøúšDÜé7þô&cyÏ('^ùKÅÙÚ1úÌM_mÊjd=øÃòðgÜ;7í—ŧ$“%È÷YV’Ð 3¶º’ üý Ó20!fQt%[°ºŒÎD‘´Äª~+Mæúí e€”ó(›fÒÀÜͰO¼|ž«ßܶ AÆóñÀaA/ò•«µÙšdF ÈçojÂP÷M=÷ª'ïIK5!îÔþ§ýòe’Œü#ÿH8®´uAýõ‰FPÔ3ãy%{œ¤¥ƒÓ¢‘mlç‰,·HZ Ê?®ü}xÇ…Ÿõd&?Hù&RÂ…”z²ZÚfnÈ3UÂÕÿ¸lcMÞý‰eÙI$Á™à¥Ï…¡ˆ’ t¿Nö‰ßÚ•ŒüNZúpñlÃÅ3YÅÏ nÆsÅï[ÉXY ™ã 1æaClä¼hØ´iA*’êÃÏ{`ÇýËÁ%Vö¼x¯Ž/l_u¿Ú²Ç@t¡«ê¨8QSÂg˜ÀzÌžW·ô óÍ-¸a ¦Tiû°ë\øˆèؼžÄ-Ãß…Uö¤ÇéaM,ÄeãD׆q7LÂ0<þã`ìfOê–.’rgðbžWC Tºçk×)­{È3rmøƒxZ~$Ù^MdŒB £+l,Ä;d(裸'[-¿â·„.º6¤Û‘ðáÃÛÑóêÓ°5÷ËjW5ù¢[G?I8·K8³Œ*3¯‚ËãÞ2˨m\ú'"Áe–e&\®–.³ì¢Ì’E\gg§!.&Î8_67YF”™ç[ÅãPúXÆ‘¿}Ð[ú?‰õ–Yö[™‰˜ù…›W‚|jþ^¿ ŠÇµÄ‘¨dH™iÿ¤»:"l]Ï™‘»:Bì±+'ÈC™¹KlÓu1›xoýQI/"7W‰ü]rÇV Ë$äÓî#«'0k»®_Ž=ÃÊÌÆ.ಗjm‹F‘‰ ÊÌ+E¾cEÛ‘¯ÊÌýn ­ YrÎÅÈ;º*>)3/NO‡23!4xW5ï~>‘‘©þü(9+Õ_B~Òòùg–§–/m3‰;î˜ÊÔÄ‘‡ÊïÄŸdˆ&þߟŸpë)£+KiXíã×üúóŽË´/ìê/ÃÖ™>ó z6!EòB+­ßàí 2“#MœjÏ¢¢LmYÅ1âú¤•Zº‰>óõ›æèOTçX1–ô¾?G†sP‘Uœ”™{¤ ÂŒq,”f>Ó€£-'Ö>»Î%Ò›f)|à;©X ¼3|ª¯³žíxD>ùµº”|#û~Xå<-P]ÏrêaÈ‹:nð~¥9¿¿—F` šîòϽÕC ÷×Y~펓 ”jXõ ëyš0ðÝ{ëx940Ö[eìŠg¼'Ub§Ûè¿gWÚ¿_œI¡¥x ÷8iÀo ÝäElb"„Ň\n,Ȉßïg«D¸×Áÿ¼ä5ùqâµ[D^~ݵ¦e¶aB>?!ÑIý¸ºç‰ xs«„9.’2GBh—h¥ê¦mrù:IE"4ñâ×ÍðëÔcBHðàXÚJ;nùó÷}½Ï•êNxüöûÚT+k-XÂdø†øúÓÌÁÀ%ûúíê™l+7eVã€F}_øxê¾r†5l`ˆž]Äu¯}íWÚŠOjÖ¹Oô‰•“k5[00Cù~CÇÆUf2¬:^æ¬àÚ?‰Ñ±olvj•ÛüHNø·W&¡Ó¯dó$›qcŸì›úYGWçØÀW«¶ì¡džß®”Vù@!müQÜל²iC“ÂĬ0àù|k~´ q‘JˆŸ$"L.·“µ3 Œ»¹t‹ú'`~ Ã1ª›Òç>³ÄÀÖѱ]0S±#ÊËï—Jx²û¯yИ‡Ò´ÁÀ¯Sˆ¨[³SvX|†˜l´ð›P¬U ^üVµ[jt~£ÈX£ Èöäý3²ÛFè È2ÿŒw†! ÒÓ4T†"ŸÄ&´N…Oé·ôÔ9êäõcS—À´S²a[§qà™S‡ÝÝe½í]Û¶K“ÊÜù/Ò˜)=)ã‚È—E[¦c¬q…ë&L‰Ï˱¯Eí[·›ÀÀì⺔œÓÇ*4‡ÁÀüdBÄ¥ºnk6¥ÔQ/Ý“r×7ã¨ØF^æ})D{÷~kçªm0ð‹6‰nälr5ÁÀo\!;ŒÃgÖ™>y½Â€ÇÆ~¢v–¾g­(]c9AÞ‘ÅaºÀÝ\ØY¬°Oæ¸z w9ñã´¶©ƒkW*™ägÝ+–;«°[rN¹YźeÔøÀÖ¾ñ+N¦hì ˜‚M%ã0DV<0ð¼o/d’µ™¦Xý©Ø—°·Ðæà¼>L\˜”…d'](„`»Ù–"p"µ-0ðu‚Ó•wðñWKU.«ÂÀ7aDÇÞ¢ja¦sx´± qg¼ï¶«\]·4<å/Â’-Ü¥d£Ou¦‚üÇD÷ù“Ä:»ÙL¨z­5'È;ñWÜ·ó*FVX'¿¸¤ª#°œYE€BÃØ'Л®š‡ò¡ü}aÔCïý˜eí 4Ùüäk0±§ùR\UùéüHŸL¼²R†ÚKÕA&§¼‘wª­oæj†x.¿¼£×ô¾fa†bXZ XëiÄÀïX„HÑöõ¢DKü†#‹]ì]Ùy]»0d¼0 ý4^¯BýÄVlavÃÀÇ9ÅŽ€FÕl]X#0ðLê’¯xð!䣶ZÃÝè^*S·¥½ï„Ÿrò†êyd÷¾ éa´lë†Mµáu0+§V±¯½cÎñ¾žÁþêu#ŠyôY±NõŒµ+d"¯ú4?‘—†Ö¯šqn4<ñLÂ6NÆç!`¼.}õe‚¬óõ¸ôe"í–F?+ðñ×.J¬l0ðù÷.J•ÅÀìc¥©j.J xÞä픥˜Ñ™Öï? øb¾žª¡<ò¯ÖV¶tp%ý¢m,ØQÇõ/=µE=7ž4¾Ý}q?åZiG0Éú…ÚXÀ½Žê÷eËØ|¼5¢–§‰Sÿ»y«„X10?}ŽEÊOÍ4ºiè§ã­ó«âRÄM|2¼Y8&¸Ê.êý©˜Ÿ:Õ|dï/D° q\ Ç÷²ì4˜iª´ÁÀ SËãð„'úÕ_ÛsBcÙ_Æu=“ÛTÓ“Ýž‹"·jbqÌÇœæˆá2v¯Î¹@ îÜÖà‘#KŠx“5ÉÍ'_]¹qü>5œ»Cø¡™|­§–x"4üD2¿Š ƒ]DeéÛÜqŒ,]U_ùÝYÛ‘Œä¶ÿøPî‡q(}ãÔB4Ç^ŠêY‡7JãÊk móÞ¯×o)î¾v).³ ¤¸¯aßI$Ü´lžë×b‰OÒä#¶×2\ÛÍq :¿Þÿ.%0P£zѸëd0ûè¾an©!’{}} :ïÙWëó*Wøø­¶\L¯L0ê6øü°=â[ŠDóé4´ª{A€$ÓŽ&ü|•Ü SÏø¢½lÂê–µs£é]G^æMuÅq×-Xeü·&Oü:{Õvök3š©o0ð¼ ˆm ö·ÖÒ2W‰áõE ±B%/oíº¦iÙ ×M yÿ„첿 (³‰[•?¶Ýºjzù ™àÿüƒ<¸TÑ…®8x ¾o—^÷@°á«O]Úå8ÀÞ7z$îñYœOX‰ß7B¹ÛãŸä¶hgë 0C ps§ådë’;Ì‘»TRáúhs1ÌX¾o”½Õ~ غYú¶÷• ¹Ó¢ý@ÎM/›Ný?aW²$«Ž,)+‡‚\öþ]³ó  1#¬¿þi&"ëT_«M-Ü BŠy¸ïý5t+‰ñu)ˆK5ŒAãøzÍ©+ƒ/»ùÖçŠmuûtÎËãÜÌýÌT¦²U7èœ÷9çm>)g=÷G5?mñGØõÈb™ÕíG5?ÕuF—×´ü;?ƒòà÷>6³>†Ì`¨€n< ß»¾ˆv‘l­n¸šqKÇ¥ÝG"y˲ºþ²¦—m%;[Ó2ü;£Ê›ºÒñËíSçLú\°©€nü›tø#¹Ç›rÛç…¨ºýpÎëcW5ŸÝÎ,6³aäl.ì“Î%Ë0pNг'¯ûT‚Š”;wMÎw/‘‹ŸH7òéÅnò }C²×8Î=±Ü dlÌOÓñ«¦ÆC'W¯ŒŒµŽÿæ2f 0νrÏÄ7Œ¬Š&¯Œ†>JŒÚ©’”"d¼æ¢rëÍ—x”ÞÀC.k¹)"Žy6|FËÌ­¨×”i"Ö…Yë‘̰32RîþIñ\Šc³ë~B3äq‡~sI€“¸Ïíèôˆ¯ùøk¿B£ö^‹!a7}²Àm˜ ÉèÎ zïhëã&-ø¹mþ­JXM½.ŽkØA¶9¿wÐCÌÊs·„7<¦G#„@¸³DI?uf UYŽ¿úú¡ÛDùúiwq §<ù°$àóš¡ݧFd–’²XüÃty٦݇¡É\ª€$ë…àèÇÜ0ÉÝrœuªª¯« ÷'n±H)OJ›¶m2)¾* ‘{Êzžú Âcê´jñK øíïH»ü@~aƒ¿N鯅4¤i FÞaÆ™í{?îÒlDÏ“ÖÈÂJ ë.ëä.‡­gY}<­.öumÛ®ËØK|÷4+m@¦vÒbÓMÖ¨­*˜s$Vp@Î.–÷¿¶d¸@›8pbùÜ?=éAö>GJ4J÷W¶¢&åc“ë̼·_?!äw‰å#Ò¯ZÇ¡¥ìµB3$å>v ‹5ö[n–.¨ÅÏ^ƒ‰ÄÀßÇ}›“ïè3Š9GŠ+Sk›‹+Ý;hK•±ÚÄqaõ_5¥ËHO&˧YpAByÁÛ‰-FR}¬%T§nb{U2õZܬëŽCÍXZÛHeŠ-ßô ]9­(ål§\LÐÒ|TßPÿ¦,“ ¹"¤·s ð„»Tîûy6©o×N¸Øù˜\ò™“ÛÚ8¾~Æl(¸ºzHê²'åôÛ%_ɘ ÊjPÑù«äL®ÿÖ_ÿ"9“$êJ˜êøföM¬ÆmRé{¬ï?wû°jhFNë-hO¼#Ÿ§È€QÖyÏÍõòçê]j¥ó÷ŸøG4ÉÂ:  âÈŠwõò Âh'&É:7›ÎÇOõ øaŒZF¢ÄYªwõý³Ÿ¸ŸÂ15Ç9/< ÙÕ¸kµmD¢ºêƒE×vÖ¸ï:(': u‰¥>4à7°õ$©hyšÓk“ÎB^„Ø(¤îkÏÒ8Ú…N!¡’U•–çBõtQéúŽ Hê[é\êO…[Zæ£AÈK®ÍeôQsÝP;ÑIOjDÈÒãÒFÛÉ@9ð­P-Í‹UýÀ‡h­ËÜx;aà½øÂ±L—‘vÓZ.B#à^„ÝÄô3“C/2 ¦~|ŠÏ% -—$‡Àb¯ÆU3ѺÍb•õ©ý].÷\¯½]-Íyz}ý¡ŒQ¡kÄa[tEø0"!¬JÌË9æ~ïúùù0"Êítk'v²Él+U?ÑRÕðhÄçÀQúp{ºuYªÂ~Š“%é–¥,§°û¨°W»>±W™ÊÖõë/±Ygàç…kU¿>Ù«4’A"ð =>²ïl0iM#V@ b¯FRÍä¥ïxk,¾~Ò\'y«ýøýáHi®nñ¸h®õu2ECfN%‘n¶3ô05ÆïÐ}~„€ï+;(|Ø}:¦µ_sªSC¦}éÙïbϾì79B~$g©»p¸‹X2'µ~a÷¬ñT¢íéæ›[G„|`:nà¢:®Þ²QPý‚íð°k³KmÝÞ4!ä #E2 ²cä7h±gñwÒ–6ÍNÉŒ§%àiÓÜep,DpY,Ù²F|Ü4ƒÝõû} B¾3‹«)b´Í~iwÛã‚æú vªÆ°Å3È\3µèî1N¾8¾A”uß½¾Á”M^òžco·Qßýº¹/H¡w”âäÿfYlüiˆ=\숦ñýùٹЧÎÛål¢þÆ´‹²¤»atlÏÀêW fï%å ’2}anÂM9‰««åÒíÍ¡ZéV —Š –½ëêc¹,À‘r3mœ"  ]°T vùÝŸ²êE].néa˜§ÇûÏBàwu†Ì}æƒ6Gn¨©C¸M†Õ±‘Ö®›[9f |îC:.ÓäàÞôҠߊ~mó|kÝDoå!СU^šèÔJÙ2»åcºFjÓ‘X¬ÖwBÜRÄgôÔõO ÷6q±â™!w±¨J­ZV—_¢[ÝʬHì0_ÝÓã´¸¡Üò«”÷ÜÕ‡}Ô§x.¶;%~‰wp´Bãç@çs²7+B¦˜öŸhÚ†ˆiºrKu®-Öï  òÄ;¯:¦OzFBà=«Å@^õ*Wo¬€o쎭ã{²Ÿ™súþú_ÀsøÞ‹8Í:Å¡Àç7  3›I•¾n×Ú-z¿¿>$3óûÖn•ÚŒ[¯W|`šÝ¡ãdé$ºõw ’–¢+kÜ—0nE„ó ÚE\Œ®ݵÂÛiB¿±&~I³Î„J 3ƒÀw^x½ívò$V˜ÍÆû ø-ëzÆd,Nó‘nôåG^IV¬æ¶‰ÀïÞ²Ýh»g–øû~‰á d›¢‚y‘žªÙæDð]’¬ã¿bö;ÿ·xk6Õ¨Ÿyæ¶Å¾=žý¨3×°ßJ”%úîÖ«Aä ¦Ø<)q‡ˆ$ ²â+>àðDõH³û|LA`Ül"³ˆÇÒÕÎwÚÎ-ËšVï+6Ïã(Ê8º9”q| …ËH½ ‘¯Äe¶S>Èz??ä´üä!ž;ã2ê ¼_ºÙ™Ìå®x,ófËÿMìµ ÏO_éH{ð¬Ùå$ùâýQq¹|ÔÖPä<Bàý¯À³kp‡À‹EöqEµgyËw…düoLéë¼j©Ú¼Ï½+$sжYBÆßÚem͆€ß?Ý´ý©4G&°½ëŸ¶Û±/Ñ…²9^x×è©?ÆquO=Càã—qT`xjðÔ?ÆÑø¯_ÆQ¹q$ø]¸sE ÙM]az5gÅî÷û³ç%éJÙÌnÕe¹‚ñƽ“¡í8¸®r´;›EGy¿?Ú¢­€ïþp;ãq¨L¦zcõ»ÐE#b›ˆÌ9,iñ†êwÿ‰†¹±€á‚¤µóö¶ø ÷™Ãγ•6 Ò¾aïä?±9&„†JMÇ(‡¢5ÿ~#ÉH?Š$_¶‹}Ù²fÀûâ±ûSbE–®¸ŒL±%«¿=Dä¥r½ÊcqYp•HÈ/$› „ÒE+Óij¥pBB`.RG›[ ´¤ILª¾•Í=o³’Ug|—û|¦ãßÍ©‰º7Í*ÙD†$`_ß®(à'P{à èŠIjÌÕDø0Aàãï@mȲ|þ$ ‰ò^ßÇÉIzvA’…ÀO:g$6IV–zÇëÛã³å8⺙5–„í,σšõt¨Ù@à㢼SÈxëur½Q|‚®…tRۭǺun?D¿¸„pÜ“/-¸Öþß¹Ýä©Ûu\ŽîwèÔ÷–€€Â”ù’̪•moÐo„ ¦ä·çòòUõÓ8¢[¿!…(~ nÁZN~ÍÑ€ß.!Ó.ÉÂjql‚È=;2ò ÔþÙG ³goåiñCÐØg¦Áe1dZX²THÀ;"ç„r§9gI”<ÕâÒå㸠O$O—Ñv² Ÿ¿1d\Öã Ø‡æpkµìô\¦SCàý7*Í9&ByBùÍ.È·ú+þ©ÛŸ9Ò%mb‚y Õ Ï$¸úYé¾[—E°33Ôð ²)Mš›ßݲwݘ#8é…èbg®Áù$¥…@ åÃ+” ± @èøH:ÉÖQŽ'™ó­«I!R—£q3œO>)ÞaGvÜ ™E¿I¹|3Ï6·³墅ùXÏ,ÒN~£cñµ/·X|•ju¡èy·Ï³øýkGIfÆ×Ðgì/%ç2[,ŸBè(‰{ÒyZ÷!lÛWÿ)2TC·—þ©ÞÀYn4ô-¥Å ­®`õB’T~hûe*j¯Ù -×ÇU¨]Ê‹ÿîù½>c@ŠÉ/SíÉ|ü—'î×G+T8Gˆ‰©ßa­Ñ?«*ኴcøŠÏ¿(6íTXíI /à~œ"õvNtÝÅ1©›‘P7 Tzq4óˆ‘w£%Ä6îdÒE07#/ ªÇ}x]ç¾Ø¼ke„ØaÅ’ÑGËÞ|Í«³¡5È?Ñ>Qb{Û!$L&ÃÇ-ºiß]xº)eÉHÿ†þ9üjhŸë‡d:èžÏÃ3²H^4¹5qjÈ!ô9õ+B¾Ažç´á¹~C»|xIn7k™:HŠd3rŠÓ;rƒKPÏuDwª}Þ#ć_,Ïãl’Ù– úeEbÏÃ<»—6yßQ&(ÅÑÙ¡ëZ¶im7,¤\uߤ¢çÌGVîý@ÒϤ],\˜ÅmŸ#E w$<FÛÊùÔí¾ó¡FAJØ”j¨blÕ Ÿ—¬yîÊm„JYæÚÿüɶ³QµÎ=±žÖ¿!µÖ·ð¥F2£ÓÙUK’ó{ Â&–7¼¯‹ˆ¯Y°îâI£[|¢¾þÔe¾Ã0I,_? yI¼Kåá¹ÿï6›•Ãê˘ì#o‘'AyËeL–Z²/ˆ×Ø!GË ºâãWfÿœ#Od¼õfY~îÿÁìW¼0ûðf¿â…ÙŸ€Ï_yødA·~]ª"‘oç³!Þ BÑ>ßúù/6Yg~…¯±É*@P‹µÃ(š“æ˜9ò›©>¶šü¹6»Û¥Ë\Þ‘X’I²ÇB÷A­d’òÇÕ´ ëÚ O¤£ÐÅw½êÞkÒ [¿ŠddáM6ƒ>”p“‹¦HXÆÓ!/_Ù@¦Ôš˜€,гÜMwp-8¾b}¥ž<ù;5ûè™.G‡æõ×ÂùN"ëϲsk©`{ükþ©å ­±CÒšÉÈ/ xž;ùvb\„Úá‘ü‚R"¶Z6¤õe[’ô¢3ò‘•JÒBîÓϳå¦7í9!ä”&½+¥ˆØÔÖžy Õ?äñâ¨ï¢•â`ݔו™XÚDÆ–¹Ôå—¡$WràÜ”ejP̬ø@ºX‘»®¬î²åäå5Mþ)´{'šƒAà õ)Ä+êE¶›>è ßóI·Lš-X!`”Â'xt#¢¶¼HÔêÈØQ·7ohß°‡­ ùç&†á”^Ñð\]ÏMÑ^¢í0Ó1B~ýìv;ûVG–ù[jÁ—xWTCäÜ}<³‹ý6„|d”Òî8×RèÙš !‹>-§ëBÅ$V:Y„|dêm²Qk²¤)—‘ßÀ«=ŽéBå¸ñÄ£TAdÒ“ÒÌEÑ»!øwÖÀ™-õåÙaàÌ¥ƒJ#ä;#Iûγ ­0ãŽæú ( Ä’Pp4\E;Oiäÿ _šEÜ´”nwZsúüãQ -uýnž·Íæê(t Ìz•±NÌðÿ„]ے䪮ü¥îv]Ïû™ˆù06|Å7b}ýƒ°T]ݳbbÍKŽ]„”Ê´Ÿõ‰+\ìC˜õ¶ÍzhÛ …%ò´fg—Ž\SXr7µèÚr[!sT|‡—tÎ5^¹Òq!Xñ"þL‡ºZÝ ¬ñ8~Ó¨(Ãæ)ʵÊÃóõZiªâý­w1•Ïâ¥×¯Œ_ø!1²/»e‰çø(Þ þ¥’“e[%rò£xü«ÀãÄù¨sw"säh ,±“ÍÿÆÎBÀnRÐ^?<!¸!ñÕm[YµSWBäP\Ð^‹5XN·­ñHi6FÇ^òçe#«Õ¾­(‚ü:W^•¼3&S·¼YûŽü̸—H žÊïß" ‹[`©|R>ïª=(ïÈžèú¢[[¦bwÐ$jˉ- ¿Ó/½–> œ¶z÷+%˜dàöµ”å, ;[`©¡?I$<ŒœÌd§‘Õ ^1±5>¶1Š1Ñè¥ÆÀîS°A³F¯«JÖÏ xGÑZò±á f·¦æøÀ(é ?±j*ESH¬RRjd»ó¿#@Hº&‰Yw†-|±­ ȳ¢ZB¼æßÝy`Ë”Z~yЬå˜?H/‹ ™Å”tMát’&ôwç5³E.®¸ñ-úpÄŽÑÎ-K3Ö‹!ó˜ß@’1’„dƒ¿¨ªòö‚l2r–Š ïƒÚãîþǶä刄ÞCO¾ï$aeP~¯6úª?™ZS¬ûÄŒÿ?™õ¯ÓtHÂ:)+§¹&ÈO„×qÛÚÕßè÷ƒ$™’Úµ?þOݰ„‚1Açj ³YC½ú£}CÞ÷¯—–´ïÄŒˆ=½,í› @î—/N€XÊ-ÑV+ú£SxZúõ5¾þˆ»s³[C€—÷:JúÔQz`{YªzdŤÅ6ç˜6#Õ#KTØ^6’×s*Ù\ÛyÊñÆýÅ?P4чÃÿ€¶Ùö¶%óü®zT‰Ò¯ÖYõèíeãÚ.’y3÷‹µéô\ ‚|‘´)ôÐÀ#e02 H¢EW#²nõ¸Õ|!Èa¥|_÷inÛ!ú¼ü(ºäãu‚<5Œ¦"Ùw½*éïÄs••¯EÓ¸v ¿óþNž‰‰­LÒßùx/ä4ŸBN€|þ"ÏÔ“wýã'Ù£dùILŽow˜Øäÿ°¼Ix}­òaÊ•º k_xà'P¶\­$¿=õù™œ»É_¬ª*A€ÅώΉóÿÀÖÏom•wüzo«<[å T*ý£f|Nj~dý ZáI)ØÔ>>Xú¥ÂÀëÏîÝùa>¿= õÚÞ ðLJ)Ëü0ˆÂó7ÔëŽêµLÃ×#^p^Ìš„~¹¶–}m0ðzî»Ð[ª”‚ï ÈúÄÙã§€¥«1øuŠðÈ:ZA¥cr¶¯É‹ï@ç¸ýðÀò‡¬Ÿ£ œ¨ü¹\Î[½ÀꇜNîÙ*k©{ 35ë 0w&EkC•{®Už™‚pøX†’ÁtkéýfÄÀ –£©SºFI>Í£&À+‘£‰mjäÈ­i0ðFxàQ kã›ß›—D¼`§S¨®/źLËeœÈÃ<Ч b#H¨šëQ( †`§Ó`¼\%ñz?3å¶•mfħS`GƒšŠÏr[K“=§e¤©fwo>íþD1c`& ¤~X?>]ëï­š4<ÍõAîh3 4 RYàBiª,—ü‘Lr®\~s¯t²Sg[Xú]/ë g|ls†€¡¨hàÌ0ðŠ*Í'•Vé·ÿ䊷ïÄ×㊖iK€Yvó°¼Oµëzv“áHC6gGPY™Lg÷Ý/â>ñY8nÛþ,ì§%dƒÉ€ü<5ùóºýcj€ˆy¹ýcj¬ÆÀ7S#žòöÃÔÀ橹ý05ú˜ÛÑ+ÞÞq’{:5·¦FS£Ï©¹ý05½q=™šÛ?¦&¿â·oNQi®éëq·¶Sàu¹s}IåQD46žGüþ¢™öÿ#4ƒ4©7; LÉKÑ‚hÛ}µkm1ð‚èôò(L4ÖV~Õ³NH ¼æ’Z -FWÙ‹oèðŸZŽV­V;vw¢z4!l¶Õî£MçOõˆt¡~±T½Û§y•Xœ寥}U–sµb ®c&•£`|ŸÃ@\ÆLâ‡~ß\n-$¾/ðy ˜uFã²…Í2Ÿs ¼¿¤ÒÃÙß®þî]£J |ül:Ð_MÀgv°É¥%ÓWnvË’·Ãõº¹Ðë×¥ÆfíÉøDç§@JÒ”!ofòÁ¸cäqìðô„öÖ]Zx$- H\;ÙíÆé@ÿ*u6Cî|LFDኵ˜SCè¹ó%ùñtD¯ºÙ˜Ùµ=ÇÀ“ÁR¡Ó˜n7bd{Îî|ð’ÇM5nsÓ2˺,²;_*K‘òÞ“ó .+·²Ä@œÆOÉ×p<ŸË½íÒ^œÝùÎW2~±ë*F+ý1µÂÀ\‹‰uc$¥”L)ž4t0—b"§ýà?©m¨JÞ'I«¼¾Ç1ÙïÁäf¿‹ŒÿKbkIäxÜ<™&‰­=²1`>H¦DÇZ±iµå|l Ôƒ:õþ ˶ÑÖ#·Ž_¬ŸÂ¬R$ýÆ^ñðÄÊš¥ ÌÊ–càíäÏ9·•h ³1`üjªZ¤>´ÒÉ7-™Û1ðec »/b³®4B¾~“»MÒ*Úù1]5OÎ4ìywPôÁV2Ô¡õ`[·``Ar*Zøq9¶C;ˆCb™|7ëh…˜^qQ=ÒýÃìÌ. ¼áÍ+®÷ÆìfôЖa r>®#×"ÜzlµŽ\ñº2A)E‡ws´[‡Ï³LzÛ]ÙuóHü•ßÓ{æ/éÁ󲬉—©Riˆi¶zìmUëKß:¯“ð Ž Á–Ô˜ý@Nv`R%äq>’ ¤fšo<°ôW]øy-¾ñb^XVuKSÂIéŠÎ5£ïB¢@6 cl0 ¹õ-÷Ö‡‡ ‹_xÆ¥pÞ3±ºS.¿pT¡§æzžk¢øTYEAÞiD¹@òåZPÍb0sñšÑ*P4ð LÉ€ûó¡ß“_# #¯LŠƒ>®™:¶ê¶#ȯ¨gp eKU–M>tYfzͤõ4§vo7©É¦ý¾B(€ “ŠaØãÃéÝ÷l&I€éÖALVd1Y6XmÍ +*•ÿù{tÂ&wä}Ÿë?F_ù7" çݪ}ÆÀ"÷BÀa2´£úͳž º¾êñ¤¬ñá3Ø/ŒYXî$àYûjÖj= WAîxÇ­0Öý=°ªâ+XK!ÊéaB<@€—sÝMEÓ†7þ3gšåúþÌT§bJ0uÚXK€7Lኚγ^j9ç#æ|O¢d×k5Òi ^ï/†Ÿ'£ÈIÆ:Õ‘+>1…+RÞ…˹}ð>ÂâøÝèmh¤±­%HDµ‰;bÇ©ß'yÎÍãUT)MbbPôk_xI&lµÚåì¤sˆI\Mäõô<ض® *ÊW¤C»ƒŠûÔœ s}¼¸ $÷Wäb„h0ð†uòÀ`ZûÃÒ\õäaîØâüßz§½@íõú 5ÃØ[ †ä´€ ÃìúƲúj†Š7í6U¦ÂÀ—Îþ°1 vÝýbe!%ˆì¡Þž–üIʉÉ)/OdI»0ä¨W—óÈG/JrÕ¥ü©®xúèÅæ“X.<šn¦^‹nƒv 죶JG$ M«™jE·þüî¿”€fÓ+0Þ÷Ço¬DÉY­Á2-‹w@#¿‰CªÕ•~mžÊ âŸNÖ¾k°*á©)ññt©VH­Yã%×ñì`ÃW.W%dò”LÀ/ ŒW @5­%0&n/¢÷áàw’{3;×¹v«1ð‚9BQ+MSWîû IÆŠ,þœîÒ¡ZS-¥ ’ûRžÓ2VøCh\û½­¼çöè@.ˆbiÖ‡Ü!\i10‹|±Ô1O,xàMäaž8ky²­ö²lÇv$ž3¦±¤ÕËÊ2Ö,ù‰hLIaCLð– Þ *šÊT‡çy9s¶Y(¦Ý ê.t<ùj‡'|˜ÆÈ}^°¿OÜ9Ì’sJ y=I?àD=ŽRˆ¡ª@Ž#!oy¼DÙϺ^:Jw„T5Иêz¬jNçiX‘U¢¥q1Úr2—ŸObŒ´)–ÅvZ$-^x×?¨&xäŠõð±©É«‰Ý… ¤í¾/fÎDŒ„ü"ÈøI¶»\M¯gŠ,` Ï.ÓK'ËZ;Ù’'w!°<=è-ããØvb%Ȥôý'òN¡— ëXÕù½ oYž+—…}`«k`Ö`BÞq9–czôï#HD=&â&| î6>Òñ|¢´Z’ûè,ë§Ð6M>¸"sOCA!îa`EWM ÏXß©És†uB”þM!È/TjNùŽaªudíF~gQ dÔ#ÇuœVC‘1›°{h`ÞÛm ½Õœ‘o³ÀiOuHy4%«w³˜e¢Kì RfÇ›º€ü!‰Éz$#_Ü™U2š.F&6$7<@>ZEH}ÆìQ/úžAóâ-š€ dëÚyÖ‡"oQ ØÒÎ÷ÍŽyº¼:Å0ÔÇ:ËP†æf…EŠ1–k»wªÇÀ+¤ ¶TŠååŠ7J¤ ·nkÖéNmÜ¿]‰ |4‡Hr ½Ë!/‡×WÙèŒÓî´äC] È„4I¯ÆScð wëÚ`Ó Ò )Äm½5>Æk—¯¨2° ÀЉt\#“Лô¡Dùì°ù_”Ó­ñbõhM3ÁƒÊ ’;LT/¨8“;—pÇ~˜ÿ/ qFÁÙY8­¶ü1R “(?ZÐéà%+ƒ,®ŒÀfž×uïk Ì®Jet&çKÿ[Ù ®00òrw†rúf‘ó£·ó¤õgÿs”†ªTña][ëUàã-Ð…½©È8>:óLš^Ñ £ŽÒåmïÿcRƒøÎ ´Þ 'œ ò+ê0ü : éÃW«øÀ\Kf$ÖÓ%Ç·m“èaý{ü«ëBÖ翺N5þÖuºcào]§3þÖuJný[×)¾é:í_ºNoÏu’+þÖuJæ]×iO»NoÏ»N{Úuz{þ³ë”Üü·®S½ä›®SýÒuz{"jhàVaǤn™;ÓC¬Rÿ¼èÿhæje0ðëÕZ)labïô¸krÅh¬ñ÷¿¤Ö:ZK ²JÍžÅÉ™{\¹_…àôxÿüîYMO‚gqÂF <….£x®ŠVÄKɧdfýÀ†vïz5Ç C»Ù<£´ý~·>…ÿý—\أݭqþ¾f®ÆýõPì²oÖ¶k ·¾¼Ô_Ain²Û} 6ø…hÀéP¨üR>+[×  ÄQK%¾©c>Nì³ 2û¢hÈ×y•½_Z: ¼¾®«ô‘ª^1ðvÆ~9ÁïWýap;t…Ý/¹šsÔÙʺ‰g=­X¹-S7j <{HÃëX§ŽÆà†f!éz¿|ã}£ß¶YÀ€__“=‰4©æÚo³˜á~} ÌÒ~sgguøõE ãhÀ>jX>0¶vq¢W±H‹U. ƒ´ýýú2à'°\å¸1=``ðãCˆeŸÊ¶¢u ”¦îWRð>c£žõ<.þêäag+n…¶›y1›±½;1ðù‹°ÌÌíWa?“…ýN£¸oTØï4ŠûAØO üMØ~ãýWa?“…ýˆ­Û[a?rÅ…ýLöönßH4XØÙºý ì§1ðvê^€3ŸsC=X¿ÛÁkvF >A@¥¬Ûý£@žé~r?þ†øð(ž5’~Ý =ô‘ßOîNo—3â{<5û€i_G8¯œ&S ª•¯‘ïÊú“iO“©ý8|å¥Yðe1>@^É „4÷ÛÂØÔ3¹âå·®ajô#eÕšÙq÷üd`ê™âmÛLfÛÞ0Yøº4– 'rÏÁÏž7e” ¿qí&š÷üìÈšS†EÓô֯䩟oC¯»^Óÿ8!©Èa G ÀfKGi{Æfüc+»’É´”"_¯ÔÁY&MÓ¸mÐʈ}½z%Å”êlhž…V$d…º«ÙfÊŒÖP‹y¼6ãË´k*å˜ÊÊ ÏW™£Ôqàÿbc3§<>‰%i ÅÀ4ØïŒ£œ—4>7Rg©Ü1щ¾_0ð‹Þú Aø[WK5Ì-"_ШØö.3¬½_ýV ¼`¹¨˜ØÙV¶­M=Š”ª"žL¡j–¥³eiW ¤äÉD›³Ûw`6õJ5(=MЈƒ<™Þg$W¼ÂÛÃr3¨(™àÓŽk xË%HQ%AÃvôÂü¼“+Þ±Zhü·¶vjqà/€¨í¬†þNfeíC$àÚÝ®ƒý ÝVަ±-4¯£ñ5Ij·ezFP9> ðY÷ß0ÅXHç3ðûdLãŒå6JT¼Ò×ÙøúÏòÏá”ò˜hU¾_ß—²TÜ?I‹ŠêVôÄ[ÌÉ€ä.ð}%ƒ‘à~Õr’xò®–^’žháՉÞ½. S¹­+æAÇ9ʨõx?GÀשÛ\o!ð°_Ñj#„Ôr{™}g›õ̵ÒUÀ“Œwg~O=tÄfWÏ_ ›\Iª@M—?™ iÿ²mÑÆ ësíHµä<Maû¢Ñ¢5!…¶­ù¨ýÜ}€wÚ¥ÖÑÃUÿpêo¤’n£ŽøY*@j¡EáÍ—ŒAóñct*7ñ"+0áõ!°ÎþîÈØÊ6u)jÍíG×4KäâÖI#äˆ4‚›æ^ %$²h•%Ýug†fVf1‚ÛU(~š{¥ ç—" @P¶ß9Gw‚x>0#TiÀj~#ÔcSˆ¨_Šw‘KAIÜ`·j\‡pw0XÂŽ^úy°b-ÖÈ¥¤¼Xˆâƒ`“ì$)6Ê¥¤Vß\ÕljyT²›@.å:ŠûýÍѰ UP.Q¥¤ƒÀû»6~f†E`j ðñvÂBmÖL…°ù¼ª®æaöH7=´H”QƒæLAüÀŽ’ü2K¸"ÇÛ† ðù+%kÑH}I—½oyO¥¦òo~9š¯šg}ºÒ’Ú”œl„RÚšït<´pg3EGI V<é©ÓM›g„h|€åÙɗ¦@~YxøWukH?ÇrþCÇztx¯rë×ïüÞ:ò{ÏØü¿üÞ~,Á8"üÞÑßù½Õ$ °î7ILR"|•)åæã2é˜t"–^ˆ\•Îz P»HíYc’«1Z³eÍ¿uóq»$ÆIÚ•CJCài{ŠÀn?È~h'„øŸ° ŸÈ/†(x¨6Ÿ‡È3ð –wãü3¤2°Žba.BèÖLtZ„†47Ú)1q„›WÀG1öç1¬Ä² *’«Aàá =1ƒgž[au_%3óðß{?•[ÕÖBà󽨴\è0—[׆tOA$–/3'žå! ±ý…@žËm!Â\ENåpŽõÁΙ̩9å!.i’•ßq*‚% P}¨Ó$Þo^Û¾¤IšSõÞzßk»’g磪û[w%ôa!ºˆLÓ|ÒQCàã-08›áŠO‘Yšš–£µšÂç÷¾ÁÌTü¶IæÕ6Ãä)#bÍgÍEtM_Êx¿†·Éó] x/Y%À„ÿS,’“C©Løï#ãeÿ+Qø&ê$ßD Ä“m¶Rò ßD ªŽ@2ðM"ë$Ÿ¿+‘ƒûüžŠVø»§2de¥ |üÔ½ÓÆ b t¾Q¹Þ3šûؾLþgàý×TNç+àã·T×Çîùª"â8°Ñå¦Üy@"6Cà¡¢¼» ˆ|”Š$ðàÚ¯È3P´­–ÇOxZïDj‰Nr÷ºyá)‚ÀO…šÈŸ³)t¤›2°¿uñ… _‚ÊC¨ GH\s4wúK?µC×91@àý’YÈn×l5_Ëî¹8í8s‰$yæKR£: ÿýÏþ)¤´ï0¨Uµ ¯!£Gñ!‡•¯‘·¬ãëâçÆ3)^r5QBkÇ¡Oó‹ZL 1C§!ð€}šˆÜÿx¾¡êŠUt¡ŽyAÍ´Aà©ö×–ÕÝ#Úª+žjRm¡œT½UÁ#¦™?¿aY5-åvˆbå _P1-S¨Œ26¼ºu›íi挶Lù _-ø 5J€ÛÅ.]·Ò®ºwîëøsVïÔ:Á¦HæÄoA‚¹èÒJ™ØDçmîï*ÈÇež%Úq2˜[›§¨áPmÖuðþ8ÌvFW¼¾[sÕò-·V|žùì*àiV"óáþâD3ïG‡EkªÉÄŒk9ÏFç¢z|ÂYÇ´ÕWO·ƒ  •Ä/^œ”“ª/Hxž‰±Æ`í½ër½=›ª31õtcÞQgª?Éyî©×Úv¨ÐŽä­n€N`qf®íLõ”·{͹Wç´5[ðl*ä°r•9oê1C#ëk~‚ ܧl[· iövp…ü:ÅÞË”p›&– £úšO€ÌÝ–˜"lœ,˜ù ‘i&_šù|táÿSî5ËÀR´' ¶„L¹lUL^²<³â[ÿò\z,ÈÛOC< Ël7—¬Þ)¨<Û«nCKgœÒï5J¼¢—È;&P‰´A£#.w¥ù ™±³$óì7‡ Nnù"¥$Ý­±…ØÌ™P¢9u ›íέ°§õ[ܼØOíVDµ°&"k›g3ðth=páí‚ʶHôĨº=›#°@j ðP«€s§§hùÄvûúÖkÎÞA÷c&‡çf\˜¡ÄÀ@ô§ôç=¾mTi%H6+@ôçï¿E¬4 TöXÙÑšò¾ªñ\t¸µ#cË­›q‰ÌB †Öv,õúæ"í²·ÎíÇhö­e¾¡Ò.÷2<§E½{z·”¸H»œÚ)ßjQ8 š!ð ö¤¤ùàâÖ¹¹Ø| í’»qs«ILÂßy`ùX†Š©o¦pùŽ¢ºKn€n€"G}ëÃ`%ÔqëÇÇU±Ž–!äÁŠ`¡YŽ/u¡ =„pˆoy¡yÔEÊ`}xVkŽé²©ºâã p4zœ‘Ê®æqR¦$þ—T·Šê£S×ÍÌô3~ÕÀÝ«Å/ ÛÊÁý”)qpé,ï]¿,í¬h ßp¢:o\ĹãÊó²à÷¬–ÉR¬!СvkûïPí"=£¨›eu¼ŸÖì8¾˜ÕµãÌ2o~sˆÀì€að6 ŠTÀ/ÉÌ|DØ A’ôÕ­ŸÐf*$Ž”Þ¥~Cqœ>yÍ›e,÷¥6‡ÈÙd›¾×-ÞûW#l~¶wÒŒ¸×,·5P¸ãÏ~ÈÚØD8[ÜÎ(ÿ{ì bH*/Z!ð ÁÅÝÑýÈ]˜0™ 6?«1„}W'IÑÑâM=Õ‚ÓÓxÏD!ªe°õ3>k®Ÿ¸âó:-z"!ðò:¥9ûQIÏ‚XB§Ç£núN¤Ñö8k" îVOÝ Röãbô¡#HWoI·þî¤[eÖp›ý4Œc7TÈ@橨b«–<§Ì 2Õ †µx¥LWÈ:òßÏ!w‹K±‘Ÿ×ZJ)ºH£í6jF!ð^3[ît׫F=]6© Š~íú–áuløÇnGNøjÉÇ\Y!eQ¯†AN ¿7ÆA¦ePðÊÑñ{Ÿ¥øƒÀz¿5^ñÌ'gµ†@À_‡voÜ*É_J¬z µÀDæÖ™ž-Øü¤ç²’wÈɵ~™ÛGLMƒ¢cŽÉ¾FÞ.ȱØÖ3[æ¶BÞ/ìWñŒŸ. ÌÍ)Ô¦úÔÍ%Ø(ØTJÝëÔB¤"ßOÄXšYÃs2¼WÀtï´Î³ ø(ÙðÌ ˜¤+ˆ_×Õõøy²µw…·"Ì:Wôš ¿òÃe@Áe%¿äWJ.ÞXP6v‡Àï“Ü;O†M6;ѱƒ@0F½S1E»¦¸fBò¬EÑœò+§ÀÄÎÚ´JÕ2‚ËsäW -kêÈíæ#È®GEȯ€Pvï•bÜe‚-¨÷S´"™–pÙàƒ8Ë[½ÏíñSK•IÊZЏ+kùüÑd|8K(8Kç¢?J;eJ6"ÂÆí«TÊ”øùËÈg´¤Dß¿ŽÜðÇnìã*›Is‹7ÝÔqcJÂh[ÔM´Þ‡SlÖÆx¹IÃ19l9«€_ï€Þ²™`4A`æ˜üû_zØI;«V.âü†Ôv}â_èíp'7`ä†å“V¯F üºêÖ¿Í8‡ —ý6T6æ¡2 ï‡Ê&Ã}™qjN÷ëPY›‡Ê&¬†ÊÒÄ:›¦‰·ž—¬=`q¿íÄZÄÙ o†Êp*ÃÁPÙžRÚÉbZ³öãÚV·~—|¯aQÚKÝA`sÒkgÂ÷>6ˆõ«•myÆæ¢ŽEÛÔLFâDëJ–^Bàs]ʇK†ýn¥…À¦¤Žß›ÓœÀ?A ²M^~¼u ú7öŒèvʯÈè™b‘9;Ê|BêÏÜÚ ø$»Iªê­¿áçZæ?˜bNÊÃU:3ööX»ÍM']Û*Ö㪷=œekf8 ¶g.9ÉGs9·K™«ÔV³¹~›tnÇììvÆV-D1÷ÁY«žòv¯ØÔS*¼—È™¹Ì&7€‹?oå#1Êj÷ àâ ¥ˆ–üF¸”$+"Ë ˜˜b"Pé¬@Ð.þäJ–‘_¹X$V­Ü _'aMîC”ìÁÔmMõáð!ú–™ÎòêŠß€É ˆHt¢ëG+¶ øá6KìáæV¡J<™€ÍÙ{$ÿC\…ñ(J{J^ð86ž’¹ŠÏ[LÛ?Ûž@ÌŠK"h±¶¯V2ýÜþ^‘SÌ6º ù8‡Š]‰œÖÍ_6TÈßN¼¦íÌs ùuÁ‰w‘±£Å;ÎÈç)E^Ú:HpÔ´ÁFµî·ïêèN£ð3­Pm)ÈW5ޱû¨qX–:7ÒúÝ“LþÕÓƒF&+ÚUþͲîé+ÇcU=çýÝPŸE£¶X—ÞŽŒ¬¦A2 ©E³ß¶BqW§ÎHWZ7‰R$8þ¸äó2ò³ c¬œXUc¬,É¢Ç ùUËI°&¸ÔÑq¬OPPÈɼ±6ú¢¾æ÷YbYï‘f‘%‹ƒž‘¯jìzNŒ5f¤+Z,yru%MàrÌ·ÖáÊÌì^íßí(xE¯4Œhd3;\A^m–wKÒ6Áf¯ãZýFëMs»û!ÓZ/½«öÒã½Äøh;°L÷hâK}÷O˜sI¾Ð@"wt}ÍŠ(­|‹æÑ†à„Vûóñ¬²=Iº:‚Êå1Í‚<Ȇ‹´Mp9F„‘@Õëùªøü“~f»…ËOh*;äVsʼñåµUýè!ð^•ê &Wàã=pîÇ ðóàÆûÑAàWeà÷Ö LÑÊÜjº ø<[®bs×ø ¿8ò›:lì­b>u‡B 3²ÉIÖCàqdìÑh>( “­Òà ¿ýÑјüãdž,*cñ¤d‹K+#o¿˜âÖ)¢*äIýß²¢!5¡‘8Ù•öˆŒ¬£¨ÝFS< }¿Ð ùYg?öÏÇFQ8ïK›‘_gyŠe6ñÁƶÑÉúžoŒöŒ¶ÑåÝ¿ßí%ímÙ¶z=_¿Øy õs6ï̦A 4›·³¦ÿÆlrÔfóv©éC³©Û˜Í¨éÿª cÇu—k>Þ˜Í%šÍé4›·óÈxc6'´ø­B~ýj6ùZítd\ͦngh6oåÈ€ù¤Ý)n™â’Ùú×¼W’ë Ú†#hÓ“ Ù@äNÁÑÏ+Òɰ¨•™ù¨ýçø#Y×ÉHe¢«•ÜWpöŸ™œ‘ ¶+½tP1éŸÌg }Óùø8î—'–9Ú÷7š„-]@1) é” /e°×d™ ÀÏŸN,œ0äDéø„5ðꊋŽ-çR‚øa‘x_,’#‡EºW*(¹=7òFʉ›^U]ñU©‹&߬ïcn[VoY‚aÖnÁs¯^&×Àdñ ™ðÔWY:ßþ@ÓÁ‚éàœšúš÷ŸÂ±h–¡„ú ù^ ;Z¦•²ZFžå‰½d”DY…ã’dÍȯÊt¤fh:ÂÆ<>óûa ‹éÈ=1ÁtÌíLÇý0†Ë!˜§x«ßèõÓȸ1šqšŽûi A`‡AðkõFw T[ $«nŒ<;å2òö3iÝN(º<µòþÞçAŠ W}’÷¬?¦âõÄ\ð¥˜d²B~^|ž(øÜzªúÉð‚|T}Œ(OØÆ vcbêù ÿ¯+Y’œåµ¯T™¶sXöþVDßG`0xÏŽ~úŸÙÈI~Q›Zœ° â I10*ÎÏ=èÕ¤®/O<)ÄÖÇ× š”}¿4<æŸö`Y.ö »tXð¹xj›w|S4ŸTFæ«dᛎùOvzVQ Þ#7ó@«[ÅE ¼ú'ØÓG×ãíY¹®˜ðo´¬SŸ{U‘Áç åì~µZ V+*¡ûk`Ž)õ֢™× 3c»‹kµ­S FsžÊé†X‹8ny[3€,&ŽG%˜öÛ#mâ„èª.KËyÀâ¨*ÄQ½H‘¯PΖ‘µ¿ÕX®p¹kò_`6‰2›´\1ø÷Ÿ/f³‰wÄçg Ý¿›N<3­øì¶ âXŽÀ|Þïq $VQŽA›gÑ59”¡ÓӤ膺[ lvÑ1B+jáî-’–’-2°Ù¥gxHITÜlätFGÏ„­µN›A㇭°–îïïf³3Ÿý|FðÔõ¦©º `æÏžá±Ùä£2›ˆAÓ•ö.òm–Cp"åß½‹ ØÞŸ!ànø–w`•º¯ˆ/‚ã€g׌Òû¯ÈNºQ×ìÀ10Où+Û† å¾ú+5p샿2ÊÇVÔÙåc».äëÊ|ÃD|F)‚ç¬Ô *;/”Éó¨Áplêc%vlF%áÀ6o[Ô¡ù¢^~ÂR.й¯«Èš_Z‡ã¢Ù·F1³n߯Uÿµ}ˆüÀ—q£¬eðíYÊ]ÚÌ-!§»4ê=Úšž¼–xPÄp»<³øfÞ»!˜÷ØxNÖgöóåÈØÐyõÎOïâÇ‘Éùé]¼zAw¬®óh¿3ËGÑGFyù)ÿNdÏ,.š%n¼‹B²ß(ò.†®u”á‰"^®ð™ÏÔ‘±ud0vqì]ô’ɾŸ[{‹¯ÞE“ÛX÷{ Lz›™ã˜¥2˜Žmís°ãޝÀ7 ªÙe_ÆÀǧm[E uí_Ÿßü•j²¶øú毤£bà;Aòë¥ä³ì|P:îøštXÊ "¿2mÙS\DGÆ_W×Ì¥2˜ë¨ö°•ælVaB´æÄÒÈ­fµW+8dþ“·¤'™bÚ1q„#z$ÊÄ©ßЄÐUq Hßær4^Ù寮•‰kÚò2Ÿï/&®̧ËòmfœÛaÂC9*ª·O×x6Zœ1L\ƒx Æe Å&n 22qEÄ´¯ËA™¸cc?3†"'´‰OWœL;iâšì¶«wÑhåXÅØÞ-øF‘wÑù!+í‹›Õ„2m§€#¨RÁ½î¼‹ÿ‚wÑ„oVŒÐÊJ°’³3qÆ("ôCÉŽHUMK¸ß=`†©oúO–M’OþLC¸%H±Î0‹µ9 .1¶yK..8»»îé†"M#ÝwÅ0ˆ14Ðf·ëŒ Jú%¸È@ŒaG­%Šº÷rê8˜'Ú®Ÿ©å¥WRG=–# Qß©Ë CsËb`¨ðëã~cK…ïýŽ{,Û õÄ®™J}f¡àÏ}Ä%CMÅ}‡ä¢ìwõõ; ÷óìó}8Ò}F÷™€©¼eמÚê룤ˆ pù}Àzé¦@‹y¦2\»T„¯j²ÈPŸV­É¾mš+òU@t6nêJ½Á9óˆø³+&é„LXUt§^ÒãqÙI£¨®jõ¼ùèç}«ãöŽn.NÃÅÑÓY°²k=ºãølºÚÕN ÿÇÉŸ=ÒjHÙŠÔŠÓN'€ w]G‚›Þ‰R6Ó<—=‡Ï<»Sß—ìb&Ê(t`D÷ïQ¸R›w+ò¥¨Q{“.ù€Hãyo¥¬›_žùŒZo¹^/RP˜ÀðÝcNáúQìlè•u÷W<ò}¦Æ›â\¦bý\)b ÌÌOŒtkI} iœ8+9»EÂ=çðQ3Ôñ µŒ(ƒèÌÛ¥àtëee¡íŠkhjVHUõZ&°‹³<ÔB=MðÚ«MßÍ>É!ÏÎ"8ì#z”˜—b…#z¤^Ÿ¥›¥rë×Ñ—èqÈg„ä¥C–ˆöõéöxDüÙT™æ6ŶfóëÑ=´Ý–a¾ $x‹4ßhw÷PkŠ;q¬+Ü›ynë·ÛrTêíûކ5ÜC-òyAu9U‹¹DŽè•lg­îôÇZ‚]œ¿?ïË‚‹e+g¾øñáodZ_»YbÊŠ!FTÜÒÈmÁÈ' 8äí"ÎU±OË6Ô58¹ŠÌw`$¶>`%Ú:]¸ì£"º¹6R¢RñÞzö³(¾!§zÖ¦x$ƒÚ ?íà,=/H½æ¢ü@õ θÂF»þÚ™·'‚²·=ó×gñuu€¦vo§½š…kþ‘R")‹¯Níñóùˆ•HNந좨,€ yÜÒ°NŒéÂçaîÁú|d¾óÙÙX’ªµ‰ÙÄ– ód˜¾•;Ý7`i¶ ¼æ!Ø{“$æ+ž6 O„Çã,ÆîK›à’¯º¶e Çþz^ F{½IµOyp">aɤÈ]ÀŒ» ¸àŸ—žµæÐâÚ]À[¼54¸ žŸ¡ÿˆY 2°€'(™äj6j^½—\Áýéïq¸­çÓL/À(&èŠÖ¤ŸÛzå+bàë8ª¦Š±ÊuQ¦Ó>¡Xõ„m5m_Sn˜áO E`~n7àU0&N#·)’5Ÿí°.Š)Ó“§bêùUÕa~P!øŒ®¶Éß?ÀÖ”§ày†þÿ¸¢ãîh«Ô>v¸†lè?á˜GäµßùLi–JÄÚm ²g¤ƒr¾›Ä£}Í(¥„ÈwÂW°ðhà3Xë? óÞ¢V>À!oßS½@äý¬.â3ƒäÈÕUCwKÈ,éUPGÆxÏ‹§‚ùޱΒ9 À3©ƒ2þµˆ–åäãÓ«P¯U‰ÕLùÔ~‡¼6±1óÉÆ‰ñ¥3Ofb¡C}äûbâL%,¹®K7L`…¤uP C¬[G`â²ÛÅm«ã¶ýÒ6±@âõ‰AðPØ+]Ar¡èn $^ß«÷‡¿¾ä´-FÝ¢l¡ŒÅ7ñA;·K Œjßi'»@{¢ `Ÿ"…™ {_ß´ž¢6îÌÓ ìÝJ.ú¾­DÃmýE¡‘æBVûÞ¾îy‹e> ÛÏ¢–³¯š¿¾Cãb¥–`*¯ÆÐdž¤ºe×Ë+2†g&7\Wp´Õpe¸BOÐl2¤{¬ \l„œ ïEÓ7ÈÄÔSP ç+*É,åÚÐŒL{Ÿ™…ªiŠE¡¯ÿ…*JÞÂ]‘…êÆqºX_Ðm „§ Á,n[-9t^šN7]݇¬w` ½Ùܵ3¶?±¯Ó&ä£=Ú÷ ŸHÙOp–ž_…¦|Ï|¥ìA¶XhúJ¹mm®ö&o{hf~bù¨SÝ 4ëÀXM2Hp§z|a=A\€ßéŸòÑvî:oÞßä£VpÊGãúx |Tçªï!Zÿ†f3XÃfßP½}°†ïoòQ,¾Ù.²ÛufÛ%¬G¹õá®zfÛ]U¡Ý†Ð¶‡KØû’%[™®"ÄWéÎÏl»‹J\1Èu(ø–㆘P%>a\Ó8Nyûf:6LGª!¦3šbƒ7Äü4Š÷´ðíyÒ ôdŠ ÂÊGc©çˆø±àþÎÔ…zÐÛ¼>·ùY/µÍ%.à××Í;/ùNmÞžˆxó¾/òÑP‡c`BYeÄX‘|4\u¨úØxIÀ"Žå£×m^¶™”Û#’#¬ã3îÉ<ÖAÙðŒà¥˜ ëýª+¢,ËßÝuãàµí0XÊ3?¯ˆ³,¯@´6Í€c`2[K_¹VkC:†B½Þ"jZ €ú‰ 1Ðzõ)CÛ €ÀàÌoÜÔ Hˆû‹]ñséMÅ]IˆM¬ü`ëæ‚:à+*¤êÝ ì |˜‰¯aWDY–¶×žkÊgz6hq-ƒü„ÿĺ”]Õb™=ÃÔä™2S–Îo¦î@Ç„+´_±#ÓQÒ´®çhÜq®ŸÅìœìú3ªÅ6­#`@·Xµ'åÚR8·³ô{h¡G¤ËÉ]~çË÷Aq³T™5­¬_¾§ˆ²,aâ3n1oÕ襳E”eiýºúb¦²¨úDC_®àÙ,K½{u–%sK©»’`>ó#­7A#Ñ8! æÓ°£_}_2HËOV´ËU‘Ùæ'²¶E#—S]–Y¤n¿}/kQÖÀ vôWÿN„} GJ-Åièe–b%¿Ó•a¢8ÇR¢ ˜„û+í‹£3]*heÞŸHõ öf‡ì£ì'*-e›ÕëŠä ('VÁ²#}ÚÛ§ wʺ"² ð™÷Ó¼û:‚¢š¼r½²<2‹¯É®@϶õèP·¶ óO¤ÜÎ Di®ÞÛ&°ÎÕ2¡ƒêùÖW 6ø;ŸŸ¡ÿu'êÌhVAò‘æ2†æŠsçåâùöñeÃ!M¥Ã!kB}±ˆâºúX1£‘N{Uu{¹Vq»ÔàóüLÂêãxö·1^6«Ú'V!:WçQË,f ÿ«gŽKÝ×Õ‹„ ¡•ï2œÓÅ ^½‰mQ™ˆ˜b°KÕÇÀ'šºâq” 2c*/n?¤е›––…ÎEœùk\ ^1|¬²Þ¸¯>ýWÔ=#.¢|LÓĘ^/&$Ô£ºÑM©2ô µ*,€VAáÅ«E”yEê+u‹ü…¥ˆò1 Ö7)’Ús´øÐjåcšã’ø* \l¨ßéÙfåcþšÎY^@¢Nõĺò<ªˆò1ÿϺ”ÝF“ã^v{¨QÜ¢Ã%¡ìÌ3Øâ.¾Y‘)EC'Ît´õþs"Mw®R.›¿màkÞa»¢ÚŠ–Ù†H'jøÌ{ Ù tPYïÜ#†ç[«[/–¨Åðíy\¾68,0_6Ùã Sª6dTmÁ9Sœù˜ UZç©iò馦ö¹­‡¬ï©XŒ XuV$àB«ö’QQŠåºîëÇn¾Ñþkö÷wZÔu‡ì(Ø™V$³W´T 5ƒ,!òö‰T+žmu'.È{B}§LÜŠñZ‚Yʲéú%ÂÏ4ŸÛ)HCLµð™ô 죬ø¢èëÆšÃßùˆ‘v>E«öð¦h XóV$ðÏ5¶’O,úæš„äË”˜økˆŠ»Œ)úqµ‚kc—¿º2e+Üw—cÄV]¿®£yf³©[µºïݑߢ–¬®á¨ÄÐn­``>ó¯9>¬‡#ÊãŸà”;æR»áïÌ?³¶ã@AH·K·œówp‡L§[6wp‡|~:å6eÔ±Ž8K©tK®ïà]¸ƒ;äc3ÜKòrÁ«ú¹Y€Zå¶^åCUªk>‚ÈÛW-eÈÇuÈ{B!‰´Ò˜#N™"ûTH®I¼µH‚oTä š¤¦ ¡nðíÅ7òÓ7a%ßaÜøíNuqþKAc`L~BÿŸC14\}ÿ/ò3#*Á«“ä·‹'ù¹Ã¾5±PÇP-+ï -î òc©Š6 õé3Å’Ÿˆ%©NÌ’îŸõ‹KŠ‚¬¥O|§YÒÜÎAû^ÜSäçt¢=ŸûU.î]mº›µ õLÀËo÷MRKíö~îìMªE»dþ&•¨säÈÏ…& –&Á·#?›"?à“§ÉÏ´/ô8ÉÏ=&?^S¦L·È˜ü¸&DŠüPZR7EL~´›Ñš÷nÞáŠûF~¸&?@~!?\“Ÿ ¯ä‡òScøÌoäGJÈÏý“üœEH6uÔpŸ?¾Qšy’@>¥1FFMæ´ï:© __(M#; V²%?ÿŒŸ>ó¯ÛHGV€Ì`ßeù82hn±sÛνBw3cwäÄÚÔZB=R·V Y"Ö¦ÈÏÊ亃µt!?MZNoÒ=&?4I]›Mº§ÉEŽF#X!ßÉ϶¢ _°—óÒôÓª=Ñû“&)d#÷Á¯éÉÏg >à·¯4©¬À7Ê“Á‚Ê(Xàß‚%[°’ót°€."*wH~QÙùÁðO·T°`ÑD…ŸDå~’ŸD°`@u ,XþŠˆJåjßñ±Ãd`>3"?Ì5U‘êƒEµÖy’ŸÄ²€·[òs @¨©yÿôüµ‡Ð¤ÆN™ˆüp×ÅMÓ¤U‡ØŽü\‹Ï¨ß­ þÎ"+¸eW·|’lýúÌ@XášÌ±Áé•ô3¬ ó°‘¬*ÚÄÀ,T?-Ab]œU)>xš/ÀKzˆUwMôè–%¸Û2X«Ó*̨u´€×Á"e =„XnhÛpÙóuXbàëÌ|0b͹NwBê±ÓóþL‘àºr'ü'b‘æ¶jXd©Xi鋞L¯F6粂˜¹AŒ€áÜîIäÄt:úââë¿"ý›"ù’Ý ò"ä!Ÿ°é‚)ŽªR@Ïœ.$ ›ÅÖpìg_<Ób?+zÏ$’ñ™žÁ—¨*…ÿ{}¢Xè6Ÿ¥XDU)R´“pÁݾé ?'AµX̱NæQ}¢ ¼ý~O#g…d™¥å¢.båå™yY)äå™ÅI}ÄÍ$ûðmd;@>Ò¤ X¤n˜µM%û$¶[„ZK²Sg;ØE.=äŸO7M#”ÙjÙx³²“üh*ëÛ¨~š:ìkŒÙI~.H›.Èoí²À~d õ€»Ø©˜u=ßÛ!³Ï™N1Ûg’2“\Iâ‰òVPLÀJÎ POÏ~“”´ígð%;ÉÏ'•5:R – ^D¹¨iZɰBlz¤Î?vÒÎì +@Ošú¥š Š óŸ$²ÑÞNx å·„úB‘´MbԂߙߴ³U´³ÊX°<»øñ¼'mC‘CæžL"›Mñ?®d¹qYþ’mI¤tô}áùì$î ýõ;Q’<¯}éC)’X² Y™®2i—“ÍØÅ›ÈÛ›Hû]× #«§ÃA/ë†ÈØ¡†ÁßY¿T#}‰üSu7L^NðóŽ,×ì2·Bú Ž;)nÀ<º}–°3¤oã<#ÝãVïÛ×üá ^Îö7uAF övýƒ?,Q#ÀܼÝÞBYFTe/°=ä™Ü !È;äXÁ<³‚cäý èåô¢ô^ŠöWÐ;!%Á7ª>ÞÕÜdà7 òo¡Ú~…×|+TË.¡ì%·‡Ä£^¿&'Æî„|`­«®çQojÀÜ6=ê­ ØeªÛ+¹nsÆ»S‘Õ+{™ È^Ž‘õ[x8É0òþ7è°ð8¯`×?X7NÛÜ£Þ± | GäQï\¾‡ÇÈ£^x} fÑÁÑ f¯/¬›f'§Ë±ä:ѵ`Ý@0‹˜Sÿ'%¢ ÜúþF¤')é kƒÎYà7à…@86‚ÝtæüÈ¿¥$æ&ƒ´+”’xT”IxÍË_€Š² F^ÿ‚I¨cðî·? Nú*·ë_¬›¶µ_ˆ±³Nr…¬*bJdAOPqýߣӀà5ïáÝ îG¡>ôz8HÌ6ŽpV|ð£¬z±1Û¨ß õ¡ß‘GÔÄÎG…ö! ÖÝ õ¡gPáëcçA^¡>ôéáÇ #oo4…,üØÆí„¥úÐ+8„ÌૉÉ0/úØ‚9`„|=^¨Ü¬(Æ#˜GªhUpAz¯>Ô\l—¥úÐó&¸{:‘—?‰è #¯ïê$Ø¢ñF@äíÝÑG?D†:Àϼl8-é•9f©Ö9Õ*^Œ4I@]†f×CÂ§ŠÆÏïÏ/¦iÃ8¦YîýÆ“ÁÆ­z6©ÁCF*!§m¢yp­¿~UðàÃ29uGb—ßêg+–$yLËÌ:ìngÿŒ›¿.ijlª‘Æî“© í–ûgv·O:é+¼œPs û/g}™Dóæiéçu×vG'=†¥Ø²½Ó:V‹5êÚEV»¿3ŸL_Oõ O/T®Ü¬4C²®NFÒ·ùÎj~Έ(t¨¾ÝÊÀK’å°(†¦f¯ö·¾æ@çsãÇ.n4[±`«,o™ÅJ½§¤³Ñ[õ¬¥êõ^V…p3&_|G Eò#¬ FÒ7\.çÆ&$¹áª`$}'«aïG87È`›'ƒ§Î²ÈùŒú[SAYOÍ8ƒ[u©èí6ýi1µ»‘Ÿ¥óRÀn;ÞÄ,ùÈÀ¯ü,Ç.@¢Y„@û¾oðš—R”"6`/;Òöûy=«M"î’NÆ€î‹áÝÞ©Rm8oJÁß ZWç‹Üä4À÷žêRÞ`(÷ìXÈ--WŸe]ÊÉòX©6Ûa?$×>Ñ£ˆxcŒˆ½{0Ö?ž$\Žî¬|ÛE÷pV|–‘é}4w¸càî__ÙcšFC2{w½Ó}›ÓXŒ¤Ó:W+&q“JïUÁHú ª:ÞÛH»E#“„ «F’ë@ãÞ5iܺ†æ3õªd$ý÷l§õTa#k öZ>œØƒê÷ ¾¥Ðâœä™÷Âöß]°ag ¯ùõøCð@¡…Qwù‘QZfA3Zå>È|àC²Mé°;È–ª¡ÕÉHŠl—ˆ5ŠÖžI.(X».Ùú4ÚÜú†-¬;X“.ïòi*'O¸ƒ÷éëR1SLù߈:²É-[WV#É7-cjg ÔÓ“VÓ´,}=5¾»f$ïd3éŽ-xJn¡Õɹð‡ØÉWy^¿DÓÀgœ \ur.~»<c»AoíFíNP^3 =¹·µº'­÷·¾klÒiïѱ´vYZÒĸöl7 †ÊxßûvL$Óß«]2<±„óªBÙ;¬ÜŸ¾»[·S»L‹,³Þ`ôÎuæmvš“ÃŒmÌB*è¥êD”B¡e]Œ6KËx_~J"¤ÛºÇýÒM½hÊÀKe™toס¶épÅë«ó²<Ü€—†—·¢}RD[ÚuåJíG«ÊÀ`‚÷í\Ó 73jšqE\ ÉÄ"iGî1Œqx?yD:ò@Èþ?ç’Õé¥ ç#ùÚ‚úM fNd¡ªðR…‘]Ü2#vð"ƒ'Û÷oênC¯ÿÆŒ·Dž´÷àˆë|& X3ØÉ‰l†Õ"4Î(i!Þ0p$A䵬¯„ÝÇÈÝ~ÊE¥³£ª”Ñý„£).:ŽþP(u±W· íhEnA=“˜ì¢ Ì2˜ò6x -Š*Ö·ÒŽËÙäµ*ª8´‹º”‡a~ F¥´¬‚¹‘æá•ÛÃæÂãÖ20;‚{m?"m2¸.É"µÊ²(á#ò¤Ý¢õ±Ut¤)¯Eß~ÔÇÒ Å»”6W÷§”‡Å"s?¡i•¦I^UÎrÊ^x–]o ÍX(õç>/VëÚ¶5]jp¨§Ÿ|lCIt]Aì+O’5Õãô“ÿOéP¿3nÈlñ7+oiøÐÈñscmf¬kjÉ®ÀÞœ$¼d·c»PâUÀ§êƒ±¼ªt£ZÆ}3Z;ûsƒµg©–¨ÙÞ&e›º´™üØÂ‚h›‹r›Cñ2ð+BUÅ•ª.é Õ°ÒÝ:èи[3ÆÚE”g)6¸|{ ÖQJejõðÏÀ4@~ç`-Vl¿NÂ?õ‹Íd‡mšh…£˜ÕÌV#¿Rad. ngLû½ÛÁJs¹âƒq°o‰±‘$æX4Í0ãbõÉæ¸6-:2±¯þ€=*ñÍACŒzB[¸Äšf¬ã9•ÕÎp87/¥½}¬¬ŒÈyM!Åaä=G²ÿ)ßV½*=Ã' åòpÂZD Ô¬xŸ×'ƒ{)ìˆg½¢p/ø<#=mÞåÍÆK³£ìC׳ΚS)JW­ûFq "s¹±6*ŒBx@;\—®…_ ãÐblÑõ8È[áës;—鸣Qƒ„,¿§&‡ê¤;¤9XÓ«TÛ¨‹¢¬ù ÑçÄv{—Ä©ê¢(ë%£/¼ÝVšÊ$òZâ¬÷öEˆ£™©~4¬ ,l¶œ¶®ßÔwŽY3á¶~S”õ3;úcJùê§¢,M%ÎÙÀ ê))ë¶æ2¯»¢AF7e`Q”õ-éŠu©òSëzû#€£s³´Èî… xágÚN£G¬M`õbšÀ%‹¢,ñ#8¤ºzA}–l«ŸŠ²¾|ëǺ+ßbW¬Aä€M>ظ‘o”`Ü£ ²) ¯ uŠu©ÓÎbmÀ‡üÌc§4·+‹nŠSßÒ)(è"Û»ŽƒÊãØà5Ïf–rj»nÒéÔ¶.‹²ç¶îÔ3ÝïܱLѺ,ÊzštÄj5MÃu¢2ÔŸp öÝ,áÔÖf*Ú­Ü‚ýÁº ì'á$Aaä©SLiÌüì¢-úñàÎÉkAŒ.ET´ºã òöZfÆGFÁ4‡Ï^@ÊB·€™›yî„N†FuQ” @—w÷;—±Ÿ6øD ›%¤‰8B»Jj]eCù ïâmœn„î`™)t"šô6dVEtÆç¹ûÚETÔ*›¾)vJ„µÉëfØF¸È] r[rCë6mÀ¹\_Ë̸eÓ²#ÓÁ»CÙÇP¶—Xcsd¼ú,Êîßßq» £În‚Æ&«¼ù¸§s褅ÀNw™Âß ”Îèu­’#" 3î¯-¸'j™ÁÝË-8pmd³XTÑ¢t]m¢^W7ŽN»ÔºQJðæá·u»“ž[œ"/PQÂÅ¢} ãAضƒ¨%ýìú˜öiÞWy/ )¡<î¾­¾ÏljŽ|-•;äögšFÚ Ç˜¿_uá÷5»u¯ÔÀíVßÒy°Ÿåg]d?Šž¯½.²„´?¼DM·Ëqèz°Ìd?¿Ð?Ü4QBÚ„€ñI¦þ{…&'áÑ;ˆüz­PÛ°9ð>€g‡œÁØUä®™É1tr†ƒIokÇpá<óÉ(pÕœÊåÒ>QõJ_ì:sAä)‘ öhÜJÝ ‹àe6rŠWáØØ¦ý­Óß(à“,âìQ^m’)ñ2ƒï~-%BëtC…‰ÔcbRÆÈÏD˜vÚ÷mÑ=íwºÂk~AjµyÁ­9F4Áoð‰;ŽqoIO{±y}Ö¾wŠö¬CD¬ u×s­£,jx m'žD¾¨ iæ4‰=çæh”]é¥i±)ÄH3çÑïý‹™ÅŽro}ý'7¾†ƒëÆfËÞ³¦ ¼dœKCiÙb£Ù±ÕT³÷eàõ4ätk‡gµ);ÖW‘ÏïçA‚#§  2âyrvøjFºX¨bERhP€o©ôØ’>~œû×ÿhÊÀÜY$6vjšizY^ÊÀPO?Žºmž6º ÿR2ïFðÜ·³¡Ý¶Å%û~Œ DÇ´_Žnµó1ÕnîWHÍðjqîæ¦ŸAFL ðëiôد(j:9šjÆÏºIdtÛm·m“h`ÀËIUJ$ÔifdtΟïÙómÿþnâvˑÆ“IÆ={¾%jª…p›õ«Åe`ËþŒ·CÊ>²I[÷ýŸn¿¤L¨Ÿ¦qI†{ýüÔ1ÐýÆfÜÆÔv¯áÚ“Çq3½óA×”8ŸOm“Ó£Lâ#÷ú¤¸ü|Ç×saP¿²eÎv ÷Œþ__Ï@é„’žÙ¢’%ûW†‘síCq¯¹ßŸ¸dÄ#%#Šœzï÷—yÐê0o67ÉÊÀK)†@  Äm7è$?q¿ƒE*î 5Ì›°cçHÞy÷S^ÒñDVŠQÙ\‚‡© ?éXõêrôN×9-'ƒÏ=3‰d6·½?žY áS·Þ¡6e`![ïièÎésj‡­#e`¡LÒFQE»>’•s²‚ßx;-Óþ1ëÉâŽÍúññìåH£ç´YÖ­ç2ñÇ Np&ÂþŠjCiP<Š#ðHþ ŸÐnÁ[g/tLRE]ôN)²Ùuxû+°A©Uíq{š5MØ\ÎÓbdWžÀ®r•T9‚LÒ|<ÛÆ31yØåqE#e࣬G!g9M­ÝåðOc[^¸§ö1½ñ]j"ÏãU–®iðqØxžùuæ$4ö-3·¨ÕÍ#OÂ-‰ÔöÖNBÄ6¾$†Gqî ·‘im¿£š†¯}ò=xGà?ÿ~Ó‰‹«ã2£fÒ¡þ㣰‹I6°™!§V«½E02ÛŸjJpÄê ÚuÝfy?YWI]¦Wû!Ì–ûBù<Óç"³ÑÌË,UC^y| E0¿Ç³XÔ°WlÆ}[ÓÖýøúƒÐ鮸möCÊ2ðzÎ\FD\:LÈ#½ B¸Ãœ1Ûi—5©eeàôól‘ö9$Ó«*/©ÆŸîù7n/¸L}ƒ‘áqªe8óÜìÕ¤Qš`ðoiNàLW”DIÁõšrÿÇå Ùˆÿ£ëÚ’-U‘è”Îv¿çÐQ=@AQT”¸£oäe¦§nUÄùZÁòÁÊ•©É¦/vئB:ýç4äGDäÃtb4Ó0÷váx&"•Yú G‘k3¾‹ËåèØâTnÉô}.*gD}³Ý°½—’áûç4i%£EHmý7g!ð€©¦j=ô}‡fýFy„”Hzs’4?çåEÛä@„ŒËè#4âPQÒÞxóÙOl$ÉÓþúOTjW5uRбɜÏïóZ¦”~Û;§JnDoyÏ€RªÿÄV¶‰½æFï“ó>‡ˆßËýŸi¨éØ(²÷õ-Žß)oœ|¢ˆÍÙ57ü¾¯ »DÙX×qvÝ. 1Ã.üöºJÑLœfiíï1ìÉ7%H¨-JåÛ·ïûdØ6pHÈëÝ´z/ÉÂï3ì– úßËêÈ2Që ð y»ÒÝ9l¬‹ý|cfX™µtRæTÎa±‡˜ÊžÚƒdËgïMŽ™›õ½zˆ™¶ëý\²Õ=±¡¯”j6¤wÒ¶n4ùJ±øHºvœj1fbóxˆ¿7z»‘;÷ÞI3y+|/1¹ˆþn×ÏšHëöȰ{ÿüü\=D;~ûgÔÚ‡‰1ÞÍÀªðbüàó¥£dÓ<o— “·a:Þȉfm†aZ °BÀpê ‡Ue H´¥™cÛYj72@àRÒ#¶²¥‚ÒX–OÐy0Y®¾ŸÆiœÎ³þe K¨mGy´ÖÕXýèÐDÁ« ¼rä]´þ§mïÿij'0ÔŽI¼#Ô^ˆ™£AÊÀ'Èò¶©;bC¥PFíè_'_8—b/Ì.l"¤G?ýþÐ ^žd ÇWS©öØ¿öš:D?|ΈŒ9IÿÛ„(6Yƒ‘E.—”‚ iMë—ÜF‡¦ +Œ<öŒ¶æ0ï5ÇÈ;DFS#[CÛÍl­AÈÇIZÊ7¦Ú‘rš¤B¯çö<3§m¢¦z Be?õ F¾@¾†çW>ùštY÷;Þc¹ŽÔï1ç?Ên謰^ž1‚ á ð$»ÐT×ÝJi‡~í!ðqaÐÇrŸºoš¥F? ÿÿdQÐÚ·Q«i‘_åF™ær9)¹Ôdg-‡@Ðõ(V‘v¢ïk2j­ð3~J-pé×zä`TJgeàYôOó¥»ÿi¡÷aY,Zð@Œh£ ›VâJ7è·Óg¤.y¦–‹iVB7còŒSc0}„->ÐÚÉ8•3㮀£[€t÷.ùhcÐ…üF ö!Œ¨…eïNbÊ8¢š]Ù;\bUz#-rÛ67ÖrÀ3)™ß¶ÿ.\ï6»; /”`ÉæSÌ"q$ß9ª;Š £[LMß | ƒÀO.±òÇUs;z DÖ1Ë‘Q^럒-:vƒ_mÍǥтÿ³}¶g”uuÇ–!o˜vãâÏÓvŸt>¯žHh9væ‘à] Y‰<ï×¥~0,¶¹]÷2"®¶O·a+raÜFI>XÞØ(U/GƒÇam溆À öë’]\Gm„íz¼#·!ƼF˜Ñ»œfƒÀÇ%±ä'½ïùµ‚–ÝðFÉ/Vl·÷ˆ}Ô6k^ñ^ž&nzàìûMr0:‡k³j©ýÉÒ%à÷WÀiqÒmþ¼zb!/OÈ,ÏXOóØNxÇë'³zC>™òŒ KVx7"Œ8û÷ˈOlã¬'?âzñù‰Po¢f¼‹ÎûûçösɈ WÜÚÛ&™mÈíçRÉSŽ•bºvkÌ:î®öPòâv6½í ðÊžƒÓÍ*j7sç 𠪞ÓA®Ì¼ CSÏ„ |dzHõ¯»!»qÆ|`†h½i0=ã§PÌKFt7=qÊyôÓg+ú:6èΆ]A"ZðŸL‹éŸã)õfëëT¸Y·ß-‹f5*µn‹ÁcF«ƒ3_‹Ô’µ&m_ï¤øußA#¢ðúRïh,JÔhB·3¬;)Ê+½7>vÙò ûÌŏ޴«"‡xÊ€—À.¼¡ÞO¦ë‹^P¤‹duª$Nu”'÷(ŸÛí1Š'½ ÿa.dɦévü±0b׿iË(Þ±>GH?m“˜¸Û úéÔçˆ>g²]I uª¨cå?ÌqXlxÛFŠÎ±mÕ*õï˶Bt~ÛªÞŒøAÛ6ÖÂÛÖ0-шß3w˓߷Ý0m@@Ð>œ‰¶IT4³þ4yCÆÃËé¡ÕNXÒ!duÉî×(w¸¥ìG´Bg>˜Õ,Yˆõßv²!áв±aÝVó!ŸÐ¥Œ÷æþȲb6[‡?¶`t¤¤ˆD ïàdìvò±ËæÎà FAVÕŽ!ÿÒÊ‚ZêÂÙ›{„üþNÉø¯ƒì„7YýÆX(ì=È n;ÞÂÂBÞ`Ž9Úð­cÞ6Ž­F+_Uxó3"íÈ­;‹æ^]x¤y›û`‡Mè½WÈ與&ã¢iЦ¬ž˜ûäcZSûIņ×ùÊ'½çÔFÚM=ø“˜ s‡¾Ïê­d`ž+ÙŒÅJV8+IJv‘v§ñ»’r{ÌšîD4‹fxµ’¢XIe>.÷ØÁøQoüöÓøU+)²˜’[„˜w)[|aSŽ„`ªê®˜ª3ðO¾²Œ³Þ ub7?ؤ…œâ8µµÐ’øý½)Ô<ÎZ´3,Z›ØÕ5ýQÙFñ«¹½Åä3Ýó5hAVÛwÄEÑöÍûŠw`û’Eó¶oØ›v(®I…•ÒÑ6Åaû˜B>Ñöá&º ¿{]3oyµ’aJÁJ²Á"dÑð¦,çƒQ×/²ÏÏy¿°‚Cìj¿çuæ£j°ºŠSeãçã‰ïÐøÅÄÝaüA§bü.7%ÅqŒ6m™ŠM»£ÂáäafSÕ“ÓT]oJBêõ€ú-¦êm\ÐO¿ÿÕR­øA†*¸Z´ÒÉ!•šd`‘φVR¢ÛJnñvǬó¾Bð¥ß&I8EH@‘Ï9Ue¸2¶6œ dn8›6yõD¬-×=fh á9ƒí;Š=ÑÌoD7èâ-ˆÖ=·vVyµ’‡‹;*&²Ë !_˜pÖ'Q%[ô‚âœ;—Ĺ?­6†>·È NLÎH<<}ÙVí6gïn§ÄùÅm~Ö ZÞ;è+kgÒ!Ü®«ð;Ø[?„¼ýÕFû)ͬŸ²‚ò¯1:´¶¶e&DHèŠ'qo¤¸èí*B>.÷!ÁÁ>,¯ì„FÈçïž Éò³2Mäc‹ã(Þ*”ìv„„Vò¨Ÿ \tA; Cö°éëDiäÖ‘Íù©6¬`G㘠Û(övòKwlã„æ~4¢'’ï™àµðo'èŸUœc~=ÙÚ£ŸÌöüÆíD­tGÙ ¾B@JîK?wr0»„ÀHÄäw§ÖžÔÔ “À/ 7§d"VïnoÊ©T…Þfm5œ¯Þá@È3–,ºÀ_óž›qFï&Æ’™4Óºú(©ÙìÐ|n÷BÅiŽôaÌ ö»\ˆcùD²¹'¶ß_£?Y×ÅälñíÂ@lxJ9nGG™âq<ñ‡QÒè}f¥ ¢îbI¹¦_Ø ·Eí8$J£÷µ•–‘r¶âÿö`!㋜¼-† ß—“5LÆp1YNzü€}2}aƒ ra¬¬ãë²ÁB;—À+zIýNì &kºøõ*íb4xÿëÇÛLr&ýô$Et Vêœ´æ ˜]îV¾5NjXkH¿¿‰Úk>æÒJ~áuº¡… ™:v“©cªn ðs’Ã…Utlý‘Þ3‚&óEý»¶Êš~$Š£gLÉšôAÆ=Ûøð ÙøÈ„¼ý…ÁO”õ_†]f„¬€è\VÍq‚ãLN†&äýd ñ,%>9)·zÁKï¡þó'4¥L¬7"ó:,«"9§Q>_D=͘©­ùНÓ/üB29‚_ù u¨Ïð¬Ðü¾ÆQi‘üw)ißu%!ð¾&µãõh»r§¤ô[ˆA ø€EÊЭ‹n:øCQ£T<Ûe²BÖŒõx^¤²¼èÞ_­Ù²7ÅqÅi¡ª3Ðκ4ó/Ò¿ÇÞ@ *ûÜ uä ÖU h2gwø:÷»·»õæiàë_¬KÂf³³šIüŒùÆêOØe)ê°v{=ÖhÈÛE¦:©œì]½%½‚‚L2ÕÿÒïÇšŒ£jÐÄÃüßíOh#߯r¦íèh±PeB>P'Õhó&2ÑšŽYŠjüëI÷e+'jÕ›ñs¾N¢qP öÌìÿQlùÎHZ ‰×ÍûbÎMM¤B…üˆ©eÃkƒÞ%pCy.Ìó¶I ¹vGßúV¼ œn°œ2;—WrJ¼×;úÒùµßæ©xõàÒ#³@cˆÏ8Œ[WC ªœ;ÇÒ CÀÒ2ØÑ ±¯hO¬w¾KRô$§ü¤Ù‡ãëX!ð…B”Èœ&£%Ó¼—$ѧlŸÌm{Ú¥mÍæxù0?çöÉÀ.1èZKÕ¤ð =±cïøåÑ;Vù`-øÔƒ ‹CýÁ͆í BÞJ¿DÖ”yÖu‚Zü£lMÖì1£þÝ®xÌðvöâ˜égg£õy ~Î((Ç–{J„b3B>‹ËØ”储…ÐfÀsN€éü÷›wRõ˜Ê ò ‰F-§’Øú‚üà†ÉI=ekÜ2NxîEåäEjý`Dµ:•[•o«¼‡8ªDW/“,9Ĉâ"…HĈ‹ É…wW Z¥ª7IUaZª×Þ]vÚ!c‡R7ÐÁ¨asYl´GvÑüyWŸ2š³ !Ÿ@9>1Aí9cæôn?¥¶3!“6IK©6Âoß#ßg•]¾µäLLmÏIV¾úœ›ùn kä´uø9¿‘çþOO¹I-Cw+“ç~Þ­@šïÜ#!^EñXý\TXŠ‰Í¢÷ÆJ•Ì@uûŒ‘î\³ˆUvƒ6z°©Î ÊiÅ×d‚ªûåpE§;(•&nkZí‘_ˆÕëÎmcÓD7¼©¿›¸«ÛºUcítK²~ÎÍ£æÝ¤ÒáZ=~IÇ'–§›ý¼†Ú)LŠðÿû“fñº—ͦ(Þ/³îʬí–>ôê Ôÿÿ2JíÒ´ÃÞ™®…ÀÔæŸuñùÒ›aW@ÒàO ¤Ï@Ö+Õ7X]—§-Ë“o”«×_nîÒ:6Š]Yž’·jã!Æd2ÞµÍWÕ3Ì °Ýp‡À ãÍÝ1â6‚F¼ÿ† ±¨)„Ã?,î7®6ÛIO¤Ï% ©«!k¾Á©ÞHí‰×)ñ˜kJÖßù]Ÿ¼zçT³1cÆ £Å À(ôÊú»ƒÕAGü"=ƒ°¹¼›.¨>¤˜ðó;Ä HeG!uï‘Xýè=e©}l&  $¤ Ãz¯Ã(™,>`)WÌ®j¡ÈÐÖ£M'd˜"ûÿ€¾¸2œ×ÃNtÕUrïØ33÷'Š˜g„Dš$æ"u-Þí€ÀÆcMÈ¥æa2 ~y?»C ( ?½šM˜õèNoLe+‚Ï;Ý C?ýRà‰-¦Ž%Kjöþ¹ÿ\¹Ö©ÊV:#téê‘Õ¿tõp¢®Ñˆ÷"óªCq“ø°ºõð¾õ5'Ý‘QOÀ.¶(‘ÁÁ64„髳4"'ÌÐ5mÚh¼ƒ+„äU߬Ö$“}î7\Ö̲öÏÈ]ï=韰Ž<&Ž ±›^!ðäÇä*ÒάtëÒLß(A> K¬ß0Ø/ï'½ô•>2]ÆaXó‰{/ô‚ðfh®é¶Ý2â=¥Ì\ºß@Êå@ò&Êvw-—£_µ£‡<©¿g5§?÷·ÁR>P„¬ ªzt”¤í”X B‚ÞY¯ÐÇbVmdc !EÔ©¤G|$¨†™Î½Ç±¢ëQË­\GºÍ!K¹+òOþ×'µI7£Wè…Üàjî?á¡®ñ˜Ÿß}iü!úÒxdõ«M´òÀ³ÓÞ/šNYáןVõ03šÓ÷Ó]Á ÛXéˆ>SÍ珞/¹C±ö®-Þ÷“ò.ñfö‘æÄÇýqV#G%ÍT6¨‰^e=p~ºÔjÆ^tmˆœú‘XçÊ3>q7žr3*F=úÏ×¶+V§áæ±Jâèjdk§§²'@;iE“Ã}Ìω[fôÓX#ª)Ž72é† o7’± bBK‚øŽËèiigQû“œmã>:Bà©ÃS'Òú1ëIŒ¢“ÀŽd.1qZ΄f÷ùþBí‚bvÌ»vD5»ä®‡Àc Â)ÇOŠ™7|ÖèÏZö&E-‡QúØ‹g;rÉ¥F/û(Ò›z–ýökŽOw_%i]Möï žJýu×ÚW—÷³Ô?FÜ<ÅÑÚI¥t¿hO˜êÎ@ïþè¾6hDXêŸÒjÚ¸Nùˆ ð]œ‹Øc<”úk«Fö&'íþ%vA®%¥—¶m#|uýšOŠ/bÓ&Ÿ¹°kçÔ %+X€”*¦u™d1 ßk¥R’OÜ6º¸ÕMx6jÈâo~DFöVÍLAà³$—Ž rL.1ÂÈBë©…À×É€³VÜéÌxxüüˬŸ^Á¬?¿fÈ~2έç¬?¿fƒ¿€þˆ¿Ÿ·'_Œ!ÅÅ ñ–ûèzVƒezkrÒp¿ÊEQœ5ný¬ý}µxEœž°8Lj2l]-´ ï¥ÛON9C!Íï´&+|…wT+ùûç§¢A¿/ÐêiíåµK_­Ô) ƒîæ©a ‘“NP©Içhl»ÚZ ÷ƒN”BÓ*ßHÝJ“¯º+.&®=ÿýzs0&m„®}L5´û ¢ÿþd±Æ(¤Å•€ûxÄ=ÿ…«Þ)¥_ÔRibïÅÿ–eô dÒŽœýþ]Ô!0œbn[Wcà!¬°ppUB5P¿ûÑHŸ«YÛfë #¿—ÃÑ 0ùíøu¿›Ag€‡ÝNXóâUÏÏæ*¿ÏÕxÿ÷›æýõ)Vҳआ|åŽ%·²¨ˆIK=Àë§ QÐ à«ØÜ5¼$Šòþ{-w¼såá1íˆ[i UÝ{™‘GáãÔ9òI¬™H/óe ôèø×LˆuUnÆÀ‚lšêîBô¤në¦ÏWý@˴ڳŧáÃêïã„©³eœ›,m'‚¢ÂèfQ[–çª·ßØçi^0g—"TÈ-ì@‡š#µˆ7 | +Á²’°¨êy]æ­8bjKÿ/–Ñs&)‰&µŠyÆÀç'=¥ZªÍ¯lYÃËõ1OOÄݵæ3Ñ FÌXê"Ð2»·"[ÝE€”ú¸žÚj, ê[²Câq=í Àa£Öª¡ÍØaà‹¡¥&‡ß¸§ÖP‹E='ÍoÆUù ׈i9•òk…ž¬b²Å@̼Ë—t%fšÖ/ü8ؽql¶†ÀGeUkù²ñâ†}ÒèC•½u›jJäufóйŠ-iÖâå?ˆ6û`¨Ï8]; 6<®eŽÔ Bc©‘Ì©ãqE’©!•c¹ÒÖÆµòë)¼·b¬/©…Ç…|ôHÕ™O §èغ8=Wo…xGÆ[à@×óq+4ÿh òÅ:‘ÛÖʱ֑ ã—&­á…ÈJÕÀaD†ïþ ln{à¦%¯+ª0ðZÌÆm‰‰ºE3Ïð®=Î}‹:ëJI1ΛeÐF}<>…ZÒ̹O<¨Ž?gQbž¥6&*—AÅ`àýðB`y¬O˜UL>]Xá†[¬O¤6|Œb’‘ÈÞØ«RÆÒ¤`úÍ9(£?P;"ïî© £g#ka:h=aäM†Mb ¦Å°Ô£Rj£ªïàëœ&%?1Lzà[ß/¯x!™Tˉ9¾vÃþ_ÃŒÙÂkÚ,÷ĆWY¢Nš§<œ£ZÕê7÷;+0)y…0@¹mv*rVÎ÷±nv`ë¬^÷¡±8 v€Â¶`þïüÓ‹N°8b*ò-J zða{¾=Ø«ùtȰ¿/gùòÌÄOG\ûªÞ~ºä z©N,´Ïî»qœ ||.Óø}Œ{×ytN ÃÂÆ1—㾯gAt‘jµ8uÚ‡¯0 * ÿР´€,L¡™ óº÷A;_(Ô²‘…iŠx ¿7þŽoø@ƒm(ûëàÌ&¡Êövν·;@Úh½ŽËÀ1ð‰ÇÂE"kCõ¶öõ€/ôRTM–ª§f©¨®ò7ƒÝS“ª—&a÷Ô¢×çãkLe^{°×iÑë‹@3•@4ͲV®eÔX×YYc ¢Ü6™€/Ä8†ÑÓ`àÁ´KvG1^PÚÇ{z¦ß÷bCÊÊn‰:q]Mu{ß‚T d5¨®Þ¶ŠC*·{¾ÙŸHYIBV%ïÜÄ ¾þ „¯ß;i#’Žƒÿh¸5¤©Šcš›Õ*ÝW;¾ùÿ8-—½ä\g¶Ž‘Œ Üù~#éiïJÕîQ.’>a æûæÉ&5;7·+ÞŠg“Ô±Ü(¬csyÄ;–òƒ¾WoÕ6q˜ªÚ=Dw×Xh :B2¶@Vß=D·zý%¬äsê÷`Ix–yàóHȯ_+Ú¾´ná!~Ÿép-|^ÃæÆÞË ¹s"<ëƒr7 jÀÀÛIº9±™Ã01ì†ßßEÐi©öb4¡þCƒ8åÑ¡ÿ†ŒJ0ð wËЫrÝïïSs>¯Î­!Ëj:±€êË÷ó³Cž]z^--!ðz¨ã7”2íäØ*!ÿÆÚCò> 5ùÌ‚Ì-Þúyïcp³eÒ`àãòÌ¡e§ óìŒhÊ‚gÇF57ríܾӼP+é—Ú‹a‘ïw1k@I2¯ƒSÊ9>KÍ«¨¬”êç>—ÓÔ¬¯PH"{M5äã=Ór)ŽxÃÀT¹ @¿¦íå\ì¥ùË9nèfÙ /}–Ødµ”y7Ʋ¾+d:ô± pRq-k¡ŽýÄê%ïFÞv0—^ü#l ¢»êÕL¡˜5`àý(V4u²eð?-ÍÒº!gÏóv’eN(Í|xßäÆê7ã›çœhTotíäç‘Gu`ÆrßÙç*þb„ÿ÷U…0H-äâÂNÜ8b©ÃHvvvVmßa ¢–†&ùëÃ3-`‰|}å3“GªE.U=ÓüR¼.ŸÀ$z§¤¤«6€×3½X= ¼YՒ㸓‰­Á縶j’‚àÒ¼ng õ4¬&¸Y±µ ÄØm!çÀ~³¦Ýts£¯û)ûáÙ7ŠNk?uõž¼N*[Èv oç°`¦iµm\¹3óL9ÞŠ‘ÕH­ú¹íظSñ±åA´ á š0¹…Of„0Y¤ïZäï:jg²I(¡#˃z Ì•ÂÀ'¶ År¾JÎ_TlU„ûDRŠXÕ(GØt%~áë)Žxù*”XSó‡oCÝ-ÒÈŒŒz ¡a’­YB$GfAÝ\˦@^Gr7w'ä ˜¦Ü+ps¡ °}+DzË«šCŽomã—‚¯Ÿ’=ሚëê¯ïS6Û†ŸÔr ù:§ y (å\õª8G<¡žEÜç4Û<@£¹B `<DZï¶ÙÌÅÅD™Ü°<׉¥Îl—ÞŠô‚ Ê}$=¨×•÷åAJ LJ4>N q)K”¶Õ'œƒU²¼á_¸+˜éVCÚ×c¼œ¡UäXç_89—HTC~¢tʯ“ƒiod‡‘"†:ë:[Ò©FˆA^Ø €q߇)–ûÒëY¬$Yyå.žj›Õ ¼#Rf®;ûM³“›¨€.ûzf½‡"»2ë6+÷Çý‹ä]TV¢ _|„>ÝôËsÕ瘈Ž“%vÖõk_¨ÿ̾â€ËŸ?I65õ{éÿw4†bàûýåM”é õÒ†Há6þ*™A¤ÊêUþY÷ª"þ»­0ðе[ZÎ.v0ðv$I¥Ú„Pd€#¾¿>Ô“æBГt>‡#¾± 3ÐÅâûHשWj„I†÷å³X’ÄʦWG‰uxÅizÇj Ý2µs¾‘l—â§mê*LïqPx_ÎôÅñg2Ùñ÷þ4 Mƒ>a£ls ¼=‡çÀ"æm¬¶-išÁfÃÀ×"ŸÖv‚ ¢>5g)Óîº&¬§”_Þ×¢O}ùg ©« B´÷QNþ•XJ M{Ÿ\©_Ô®µ³;_ô}+Ÿõ™/Ú˜âˆ·ßø¢v 7ø¢ØÅà'ýÆOaªº‰‚ƒÝ™ùሳ;ߥŒodEÇ´F®ÁÅ©:^³#ݵ6m^©럴0Æ(h·½÷tÖ‘úI ÷ –ô·Jaàû·G8†G¸WÐÞ·ÒQ¼W!ÝH'Îzˆú «…tr’6[C7Ba¨ÿ°Zð«”_S<,»XC|¬" ‚­ ³Pëú ‰(h¾O^³5ä5‚Q¾0NÅÀë§p_'‡18k‚’ØûQ7éîî8÷>˜l3+ ¼—Àè@f p+b…1(™VM¼ã ð>BØŸ8ÿacóPöC]×Sq1O$â›oO†¥òš÷ã¬õÀS<.fJý“‘ žó~oÅŸl7—¨ÿMO™+VÜžTÀÏп=éžÛ¾Zšp3Kä6¯È‰ä±ÁJ õ7Ÿòâr)á'”²v «A;î¬_2àúþhØ&¢ŒgÚa›:ØŠßÏ“ûðyèÂt†®éûY6vöÉ5¥‚…]èùg૾=Ç¢©“åÁAVñ[W ôû»û:—UDîH Õñy[öw÷U´ŠÂOg{(»’ºøÈò zu0 ¡‡]Ó§È&¶ß¯R”áx¯Ö/¢ÂÀ'NŒÓîåþpêøßgϰl›ë­7ºm+Å@Ôœ‡¾…ÖšŒmßÂÌðû]|ˆÅ9ª°¨ï˜Û«8ʹUPuzÜ2ð}làˆZã«>øÁQa‚A·¯õßÖLˆ.øû]ˆ×ÓÀTB”UÝH søÂ &èÖ,æÍÚh |—¢`ñ˜>’®†–[¾á_ÿz4þûN1öåëëŸFÅG“9Þ—¯“xqΔü‚o7Æ·@cÆÀÛ?žá:­É €÷=CŸeÔøû£YÙñh2ð_Fh——Š |þzÇùÖ™%2ð…;iŸ”ô÷q†âß51,ÎQ‘F5\ÍãÌ àáuM"W6²@TØ‘üU³Œü¬;ág8Ïs×ߞ១£xû|†JùE}cDH ¼ÿãú¿F‹?8¡/ ü>Â$¿ø¤%rbò™)/Îñù¯·BJYüôë×·¢íð[q),3Ê#r‚ž!’åýõýÑy—__ ycÆ5å1‹Q&h¼ûÇ-(Ð ._å”}²­n’éÊ@øºÝC‚¾DÃòB~ùºþs¡aYÅÀ}Iw(Ÿ£¸+|ÅJqÌX:Bˆ_ûºä|ÀïOàâÒe|¢"5 ™ùŸöës7çøB..yx>¾Âµ8Ç÷oûû-nOþÏÑtýЗI$.¾½TМ"^CʱèÇîW\ôBó¢A)G~¿o~Qô ò~p7@½eP>jR#å+ôØ3ýˆ ¿.5ü>/h‰üþD©=²üõ'°³«*9ù%f𙈜±òµ«Ô»ÁÊ\/›VÃbp+e É,^Pí¥¹ò¹ïŒHÓ:®.á}ëU7­>{Ø0ð†=RòWÆmªÞxƒ÷ÄZùIŠ,I2m­ÈT­ue1𦭡”5zWm²;ñ»twŦ­}‡ÏÝü¶ð´ÓÆeq{^'ÓÖ(Xù{Õ A1ðl¿3O°fLÖµxqÿP‹'?E(s¦¥®æþ«óvH ‡tZaൂ‰W3 Ågÿ G¼í9A졼ªý"0ðþ™íóÑgûlÏö/…´Z#MÈg¼24z[ ¼¢½„ïeI®v©V ÜGg°—·¥²s•Qxµðˆ"Aóè“Te0ðqìòõÎ&ðç¸Ìó¾b ¬å£, »Fv^á§É‘ªf1þÛf o°‹‘ ¾.©œ5ë<’ÑÔÚÊÊGÑfÁ»ŸðBÖùb´?¢ Ö Lû'²2òX³òûlU; ?DAv`bŽànXg¡â 2R Àä3Øì0Û¡ÖrÁÀÛ¿¶Þúµ§az¿ê£ªü;Ð@< œçRèÊx-ý‚¾bà³ØgS}5lvÉ]\õ E~„¡(êÃþߟ¾ŠÙBqçø\Ÿ¥åÀ±Ñ¦ß6ÖVòRÄK;² hC2½’ÿåφç³?¨¬dÜùQñKÌU[®ýæ¤Zˆ—^Åú“öº låÂé~š¯rJ+ˆC‡½!<Úù]ÕJ}¶O )€w4îšWüe&v‘³]>þ´'`%MoyÃò²B–6„~“ZŒý)>êäRÀWA^M6£«0zžŒ†‹yŸ4›x&z8g7Úh\¾ÞÅ->í&?íZÖíê4ÞŽW Zõ®åný·Q;ÖçNǨÝ6ãÊó9^Jú­S5=h€»F‡À³ÁÀ,÷ö'«û%a8»E,}—¯Âi$Ý”ðö=I‡\M»Æ9‘DAö)­‰lJ­ºÉ…ÎËaœš¤,éáq2³Þ³cq1ßû~ W‘Üc‰µ¼8ÇçAäÉJ.Puãä’µÖ.»-KÛÀ%8² •“×+@Y”î˜ñ÷sÌÀÛ)Å€-d‘iùä·÷ DQ@*ŒzÑ™Qò©[8â¶MÐÖvöËŸÏñV ¼aͼÜhå„[ÐÇÀû.OÁ`tcÅ·U÷5> żÜü'”·ߟÌN}†¦WRSBj[Ÿ˜e>¶ÑÙH²ªìå¡>$øâ[”6…cVÓº2ÔØû:š&k¼¯ûxù•÷ô°»ŽÌ5íu=È]G=Öèã{äHeÍëò˜×CÙ ­+F†ªRE$Cý©l7pg»ò˜ÉÒ(Ëb&ò£^Vë“i·äãÓ‚®›ño?¯2kh Eà£R:פ¯–ùÜ Ð)ÚõFmD[Mh|áþDеÅ<7Øf¨ð aí¬ÄÂ|@Ù¼u[H¼ aí}ΔѦ®3jù®mËV þÒq_«ÏûôZ3Ÿ€ ((Šx[ýõÃ%SwîzŽòÂF 3##6 ¼“Î<È ÈàŒª#>ˆMZ[;n ºçŠ6Ÿ(ÊÏä³âf¤pmyeM9e²“KšLÚoÝ“vMb×XÃ>2;>)ÝMûD÷ŸC* |üñõñŒïzÆÝ?£¢ÀxFÜëŠ÷¿2îZ¬‰DîZUÏšSà“”/`A«ËÐòÊ4³ø:Âü úÓ&¼«Øê£D"âšÛLØfCwûÊʉo”ж;­Í¼[¾aFTJ£ÊTy‰·¶õhË‘LAô:§þ³:-C~ÍXÝÜ/ÇêòÎBÂÓF®ØU–†cAô:CŠßhët>G^—ÚZ,ßß¹¿@]F™£ÊEížFÕ0!CþRø=¾±Çâû&ڃѲ&y'Æ[3½nÈ|Èô:cÓ/|…¡—WÙ`ŽH´8§†‰­Ë´±¶ãøMTP®›j²áA²Rê¨MßáÜw¬[ÄÚòZˆ¨ØÍëúm³2–½Nq;‘Ú:º¦g3s;ÈŽ 2ë9NÁþÄ'Öù¡„î@DÁŒN-kiö]²Ivò4©Kô«PKð†Ýì¸/òE‘éšÃȶvQ~3Ë'‰¥pâqméüá%›—ÅÁb)A÷Ù‡bã´Ùv(Y>ò'k)^3©hOÆïQžšîÄûËQ)cTñª[E)÷ìó¹*Õ¡mÄ,V]5ÙÝo'å”DZsníºÙdȳ#kÆ/¨,}°³ŽÙ¤»åfཅ»÷¬»m²s†<Ô¾Y,ºDie±ÌÕª»IeÈíªI†ýÌìºÍzÈßýÜIy }xÃ4˜ÆOcö]Þ2:&X4ÁåLõX !ú¸ë_ôæX)¥fÞQàôR¼êžY³aìÿþ0PÛר1¸æ,x\ñ¬§6”_eæʤD¤6¿õ:,vÞý•H8ðñ³•äRíݾqã(ˆHíïNë²1HK$"µÐ­—Ä•›qüím¤è‚ˆÔúç¿)CŽ… «2ø"ä*Ø™Ö>Œð¿x̨·†'ŒÎx¡Þ&êä2¯bŸX6<ßGB(¥þ‚Ù¸éå>50ÿ‹GqÜÄ3ÓÖΛ7Ð (¨¤,4ØBP­6m3ÃÊã–±ÐÃ*˜¾›u,Ù`Öé.[ÞÁÁ‰Æo¸¼Û…DÃoþà'-«]VÝbLvÅ'µ£…ŠX9ÎÃ<Ïù­O¾_úå‚Z@¹6M=‚Æ ßäXç®í`•_©)ð+“ÜŽD­Ö1v··X&x¾ßFè«vàLø¸CdNJl™VÁ$ó+àœ! Ô€®ê@ÀˆÝ ®Y6wHWxÉÄä]…šnc#KíTæ×¼cÇ;<¡<’—MåpéÜr?it òoÆŸÃüÆÁ¼ú-]‹ 5~a‹P º˜àþa%ÊðÌy„svÒŸÜí¾[¶c]èñ¸öG¡f‘*ùU#øüd1'«Nt’íX|<óÆý*õaíc†1ÿÍbÍåñüÐÚI ´Ÿæ¬q“úÐã™éŸŠ.FïZn†WŠŸŸª3X+?‡¦‘_T”ûÈÅTû¸ñX^ù!õE‚ŸÈÖ•Û~¬}¯«x`Óà7ËØî—+K™˜eÊka*³ËIã”|¤2@Zͩŭ£Ó9=>a úVUе«CŽîãë£8ÛœkØÎÄ>ÏxϺç£z¨éàƒôøº¦…cÎä;&iû ŸñûÌe¦b7t{ŽMëw$cu¨CžPâáB8¡”LŽU⨩’b18:oÏàìc¼e"Œ‹M¶,²ªb~ëÖyÌEA“—&gûæØÈa© ²»C@/úƒØ–ÅTï3ßCNù ã§Î¾øOl§À;Õ²KÝzþ'd“?tbðKdwÓ OçÓ°HíºÓ»U®‚ÈîMûp¦ñ±bgYŸ]ñu|®I/ |…fÝY¥H,Dv÷¿¨ÐŸbÚVãT¡yjAdws¦Ñ.#aRíÙŒ„„„I´gs¦Š$Ìé aíÙœ„é—GI˜§öì…„i¬kBÂ<µg?I˜f+›mÏ^æõg-’YŸ?ðhã[-©Íy´&òhÕÁ£}>þÀ£5È£Uø‘ ]FU®Xïú¡“NÓìùQäJ»kéãh͆Ádoý&š!а"`ÃêãÏçQäBqP-œgü‘ÏžñûScPYµ4³ƒÊüWVHInn•ºœ™ÆÅç•>ªä”¶>Jÿq×¥¤ÀÛÁϨq¨ý4óÚ¶à‡ýÎìãJHø=a›vYë㤫ÚoÍg4û`¸ÁÖ¨ç×ÅÖ£šÐo¹[-ÁŽ¡x~}´(ÆGl¬´³]Öãr"¹ 1`x¾LûøËPàyÕp¦ZÉ÷#¯Srã!,V»lÂÉïâ”ÜÅ:äÁ°•z®2 ‘€Æ•tve¹Nœµpv~]¥°}ËtfÛŒªùBDú ˆs§ælÇ÷y0®¤À;á]¡ÖÄnlãW)Ìå½®½h܇ϲ^K±ATs*éÆþŠu]Û~G¿–ùPàíìgN&¶þ3 bEksl4§’.1§Bu©Ð'»xݲÂ^da§$ˆ¥dשÿSI—(ï'O­®ïôÔÊ_ȳ««Ã[Â/áK¹YSRà›*ý‘ì`µdS¼î—nx‘„!Úr©äJP)^úêÿࢬçzçx´Ý/â]aVÄzÝÔkÛj?äø8£C }Ör¥j«.>©»Tú ËÅŸfåC/‚[…à>”“S/¯ûÅ8+W˲.KÙ-àà À/ܺª)kó0ã(¤n ü>,Ñú}×ÁM•}%²ÿuê®4)4më^³º­ŽãÇ딄iÁa±ðKøRër÷ I¥ %jT_¯Ò-XŽ¢êÅÉL±i…wç|ª—ãܽæó£äCüb o·n–¢‹”!PIè™6ƒtb§@ÒÙD v¶b²Z°APàƒŠh%9§Î®²æþg)ð$!Õø+®Ò–oçuhC=¼É¦û}i1_Mr£.¾­tßÎcÃדPÿõ¿Äð‹YKÿ+U¦Ò ßú•©¦¦JÔ•ë~m-G¢ÔëºËQ`°âÝ2à¤éA€º3z} úR !œá€wfj3¸ãkxe>·©¯WDe5î”S=̘Ié€;ÃüAe’†‰Ò°€üâ,%c~AÿëEÎâ1›žØ…Á^õ»jvNß90Àp9´WÞIïj„ñÞ~ÊÞ†'¸¦KBjѳ yJ>„»7Çc ­·ìÅ‹{Ž<žS nËÞ-02í²]`Ý›Nc ÏCC«ŠÞñwëæü“ýâÅÙsT%»ëHeíF¶TbÍo’Ãk“lÑìÖÒ,e/ò»eÈ&!]išÒÇ&’xËtwçÖùŸ=ÏÛ¯l×Ò§ßuúr)s$ÝŸÀЧ\ø¼Ôû4/ò‡ JV½Ù«ýH3òžÙÆÞŸZZךReï~{¨šžüoÔ™¹_.oô¤ñG¤»$QfNžžKSëÞ”Ù¯y#‘2?CóZ5Mºóµã낌MijÚ¸R]Ÿ!¿ R¤UÁ#•V¶3òþ+CÂ5PZ×]¾ g[w-§Îÿî¬s•‘.CžÊÙþ¨† HßòäN%a—ôç¾ÈaÉŸŽhzÕDżÕÇY JÍ"òyö|u{ÛÍTšu2£3£W¥¤`|©eÝÚÙ–€|Ÿ^Âi…¯Ã/"¶í³¯ãG‰ßAàšòŒß,ºjh—üîßÙ¡#¾‘RÌúl¶p?Rî)ñ䯦²bm•Ò#wŒ#/Cus}•ÍÏÇíôÃ,åâtèå²/îq§Èö@®ÝÒ¹!Cr–¸¸ Ë]Ö“qο?Å™°irª¦¶Æ:l¦Á³f1'’K³Ï¦: ¼ó]ÈöøX9ç’͉úaç›Òáθø—0ó³N+bæW¼¾ÿÅÌ“a¯ï1óCvÿëûÏf~{§3?þ`æg¢f~üÁ̯i'jæÀÌü¬ÊÌüøg3?Š]щÿý×bu(ý4}dk Ú¢Å;/žÁ8F]î•U¬:5D¬=F=Gþ¨®˜,ËfÇêлÈò™˜ -ªfSó²`zˆµ_¶Ð1 |’ÞÜCknjT¯ûüНŸ:»ý'¦¦ ãø‘QZ¸ÝjüPà×Ý> _zlxŸ’'Ñö3ñdlPÓzoÚ|x@òä?¿iWç4r-ÍÒâCÞ2#j’tMÀ ŒX ªQÿƒ!›qw&õqærü å0Ô>°W˜§$õà›”:ÛeÜü(Z'-¢QÀ”h²óʶu\‡ìÖ¼w&&H˜]êÑŸ¹²+>‰hðx *]¹•Ù3¾r`l…fV–A(ZRà;Ó]о'D ˜­øE;Oá„Ç:á'y]gW$þ*’Cqo¯ë²ªJ6eþ‹ K´‘göÝ13¡`WA5êR^´ ó³åù« "X»?²ò‹Ç¦4wÛad[ xf* -àJ÷lú3çïLJòbºâRñe•øÄnÖXüHÙý~ïJYX0|Ÿ&9áCŒ‚ŠiFJ&æe²&{™7­Ú%nÃ2ùS±qA_˜¸øv.ýŒ\¤¯¿¹~TÚŠÃZÚ±r0Œažâý ÄÙdô&ê~¸mk.¸ˆ,È,‡äç¤È,'¢8{!çg¯Ôá,œ!ï9²M…*†ùÄx|ŠNvAtÒù53õ‚² b¢"ÄrTS©0átºœ¼ ¤x+-s3o‘£xq/¨ŽÏ¶ñ¡p/W…š#DžÿoèUÇ4ÀØ*ÞGÊSžÿ¦†Òdó:dÀûYj—@ 2zPze”Z ¢ºÿwJa§þמW‹9ìSuÿ²XfµKwìLyùbt¬ã+†ë¡ºO˯QÜØO!&†yÒï³Nòšu²Ì •µ^v&ÙZR`êçøß_¡C¤kf×ôš3™_ÄÖ¤q×rÝ%k¬XRÁÿü?ƒ%-ÞH©D5:±,ݰ2,ª¼©íC'ƒV¸X¿ îj¢ÀÇIiƒÜb°¬,§F˜Dz熫òèóGVúˆYRàëìpâ\Æ¥aŒ-2žõœ¤ [ùë~ ò~âÏIÚƒ\{±9ˆ^G‰Áézú›Ãrz±9ˆÀÈ#œÝÔ9WU•£Àóã*±©S(+ý+fôu‘›«Ð½ 3K=ø™«J <Ù›UÒª·6¼õ;¼Tø¼ôœ4!RmjÉzŽ¬ð¯‚¬ä‡ëOۦΆm•ù[‚ÿ¬AðÖ„îK=În¦À/ꤞ¦YÝ3£J[ãçúEÎ^ÿE=¨ùŠŠuûÞÛ1p°Œ‰Ñä„b,pTÜž! ªuꪡ±Áùϵ̯yK¿Aì Q¤Ùÿùº¶eIQ-øK{[÷Çy?Ñó ¨¢¢ (Ñ_@ÖÒEÕîéžy˜ˆ­²Ö-3§rå ™íä ž*ÊÖ£¨ ¯„h%ÐH1äkuðÞy;jã;ÉΑ9²èäŒÈ;Ù«€ÆÇk_5ÝZa0"r_E!&qkø»eë2«_ \ÁbÈVpñž{‚0^XF³œÃ»f(° Õ«4Õ¶–Q>¸*ç^¼/uøÂR_FíÎ¥^¼-õhAËÜñ‰.õ"K3Òx`* ˜¨+Ý4ÞIG Iý‹Òs/&Ž à“tŠ’¨ô³Ýæ+–0ÈÏ"Zviðè¼E¶xݲìŠ/R¿ç)h™˜ÓÛZNëš=pZ~ýþý’‹ mþµÁ)æy*J”[ÕÊ¥Ó,ÿ º,Á¸ž‡y›u“ýаÔcxÈ™èè  ”¯ò»_I‹ÚäÚ‹AyðMþ¤R{ÿಌ sŒÅŠˆÎ¿ûý”öàHÞ¶ÞŠ¹Úf!'ƒ¨¡åpÒï¬~Æ2äi(]¡T‰‘¾*W!Qµçùf¶¬€žÒdø,V¨ÇPä$ðÛ$j-P©ÿ›Ãü¦²ÑÓÐLÛÆj¡Æ0?üIKÊÌIKÝ NmÞs "Æ0?;²Ž©‘™`Icbh'£xþ,˜‘€NVKuÄÌäôN„ÕÑ-¢ø²Rà%¿Ûwuå{Îg§QåïùÓœ^\kcݦji%§Âó9ïØ e§Ep ¼PfNš„ Y¼s˜bQc„ô%uˆ‰êÍPàí“ ¨k‡vÚ–ï™c1|ƱäªVÈAx>²ô7Ú…%zL|ÖuÕýLÏOžwÎÆ¹73–Yž9™eŸò„ÄÒ…#t˜q ïùÌ‹t;*Ibj ÉF”ÏgVÁØGV¡f$º~)më)ð’pzÅhc½ÑH…¯ivkW‡ TÚpÞèaÂ1ÿøŠiÚ²p|õça÷Ìü…ßDðw*<ó8:.Ü4N[± G øG£±n6-¢…eM§iE%x*uDmûfšfÔü}¾Þü[8(u³«“ öÒž¯7ò?Î߆ůQÈ<û2G+¼iïi6÷áÿÁÜ÷yÆÑ»¹N…{îàÅ4násf_æIÄz ²ãÌu9w øúz@îr-«¥^¬ÅN]B ³œ~™Ò,•špÖQ`AÛé°Ù*îü8öxpS—S+n¤79¹¦¥ÀëÁ=´³BÔË|¹º©¡ÀŸý‘x¹Ff=R$HRptë4„Üf·¥a¦¬û-R/ ø é’¬XÔ¬¦ÀË¢<èBB;-ª(!‘=ð¯Ó1µÅJ)ÖvŠeÈojÎ$ÑsiòF·Èý}µ…pxñCø[ôÍP2ÍqÒûuÄÑ à €OÖ*¡›¥_³Ÿ1õÿÄâÿÞ¿ ¯±tËŠ z¯¼Ö …õ4<ê&kÓøž$ž OF+¥.$µh†óM\8>Ípd4ÃÙ(°øÁÙGʆÙÃÙ盘k|8û¬Q.Å“_·ÿpö‘ÑÙg£ÀËYÁZÌ$†ªbƒÅê4z žKñUT¥˜û• XT£F©4z ]g̺úÛþÔ¿ÔÉ9ŒÈ*¶Ž°”ø¢Ö¸¹Þ“UÉ*àGDWÿ8 °Š/:=žC¨ÒT¨ÎTP]ýädãfÜ¥P,¨ ºúïVßC߸ad·¾-X¹avVÏË4ðÜÒRô.q=6ë6Õ΂PA”è·ßHÍHW KWè]|ý ã„¢K³¬žð3’T Õ™Pï)Ö€ ,Šâë]Æ©h3ª3 gä¦(Œõ¦£X&a(QùüŠWR-ʯ6žyw$³QEÿó'õ‘b·¥¯\ox¾®ÄÆ£Ýx?TðúAšI j´œìÛðƒ;~²k˜pWª¶ÍçÈÛíÃyÔ³~ÙïQüŠölõU?öø sžPþ™z? ƒX |¹ÇLˆä¬0å8Œøú¨«V+Ú xÚ=•ØiË)„†bèÀ‘ßÇ^zŒ†7·ž;½´.C9õ!µ3™T¬Rõ”!i#¾ÛbŸðMxÇ¢|ÑÒT~‡»‡s½ñMÓ³ìçI¢¥ÿ@Ê’¶I712µ²dò~¶Fj`T \­«&¥2䃔ÓÀ~±«ÊN•¦‚¹Ù‚ê!ÿK;B8N¬‡öâÔC>”ßÒFiÛ­¼dMI™D\ªéàVùÁçW¼¢¸Xu´ {Íj_õ\¤ŠCùP~ÈÖv­¢£áâÐC~tÛG!×z ÀÇ©þ*aF¯,]ØÙ«ðY)ðIxh¹¶5Æ´À“éû; Ÿ±„–¯Ýbzt¯`qŽãû=šÚ´[Sâúý>Â"@ÃÖ8#xýä ØiY­Â'¡Àº*–iŽ;¾:L‡±ãMvÅ{ÖFÝ¿uÅX¶!®<>ˆ¶!¤åÕ ³”5ðMxf`²ªm9–­¨ÃÏžãéx¤“[3Ù7|à_C. ˆü&2 W1ΚEU•ËÄ‚Ûe ¹št¬r6C^HUªHl\@‘û>½ýJ¾ä{Õ-l¤n ¼R|Ÿagô~+mš X|™Y7n^FŒ0¾‹é´´ Dà:ooÀ+iSFUÐxDlU»œmÊ‚ªyƒkaÚ§»n6Ý hèß×4H€:SÓt¦ëÙDGá+çPù¢ë|ø£5^È ‚L)ÆÔ‡àBÎG ¤ž r×K ǼnºÙY½-5ïó׆9Ìû…Xvž{ $…¯}~.>Go˜‘~žñ »½±Îž¿Cô¾É¹îôBEÜ+ùØÕs¯ fª—I¸fl½a²© ÂÎLª$8Ïo@bŸ…yÈ—Ú¡u Ì<ߟކ{‰Cj5hÍ–±¯(°È¤PSEÀ‹ÅLuÙLx!¡±ÀE¡WÞ ±dÀk6ë²o]'Ë:¬p×Pà-“-l»Ò…ÿÐx?ØRnUnõ0ø¡(ðqP°##lºrž >ÇGæIò±Ü7‰qh¸ÇL–;'»M%ÕuýâévÞ …R\µ»œ{f*³¶5¦\äW2=J¯‚íMÔ Ò%>Ç×Oü«Õ Õ/ºfHúëû/ß™:„ïýjŽÏøzBØ[H„E±˜ž¯GŒÈ‘Û´•ÑqD•jÞè»KWEWpµŒÕPw˜œ-¢ƒÓ1Û¸†Ý¹Yg>ÞŸcÜšÃßJ®SöSxúÇ–÷ƒcm$"¹ìÖ/ZOJ…'žv^†¦Êø×Aõç5ä-áx•]X>Å×_G1Êð¡áÞTÏúmPa“•½¥À‚ˆT©eæJy¹ö#,H"Sýk—]ÃΨ7V­Ú5¾£À‚ˆ¤A‘¼t¼fª‘˜ÔQéýÖ±³·Xz%r r•>û€–¶}-ußj <¥,wÁ®4¨Ù¬áœ‘M<5à‰¾:·áoüŒ×¿jÀËQú¦Çpól~û C´"Öfž°:Fä•“Ÿ=‡¸4É QºxßÄ ã0x(Š{&™pa5ós;¯(›^¬›VqÔQëºr]u»+<§`ÓBñªxi8kŠÇ_ôÕí[ÓÎ&¿õ5kUï/×ÈËV®Ru (žïÄsÈ:Æ·1dú¾¡Àâ SöÁÂkáÄÌ` ¨(ž™2vÓCPªêÚ4¢÷3^Ï®€€>§¶•qܪ)ðF*¡M:»äÜ3UMóÝâõ&,u§¨äø,2;*™TPóî‡þx<¯¿õ•l7¶sØÉ3à•pµa&#Üz]­g¬¦@ˆ4xÙ6¥«KÓ*ˆÔݸc7ÕË@³pÀ!ý©ëµ^×nÅÂÜ)õ‹@ô«;¦­ÕÇFzœŸÀQóI« ˜²šèŸÂæµ`UdæV„nSgµŒ$‡… ágÁ°‘›s®¥ÀËùºÖÐÚQ“K?YYQàé)TÚä,â®2Vøº>ßÛOäˤñ|ý'°7Ç[øúáñì®6;°2~£ÀË߀Ö¯ë+×ã(Ä2¹vÙÚIàã9¤2±ŒÄœú±í•ÔïÊ<=Ð.Ùw±œÞ ¼scØ|Âg\ã\nÍWZ±Ü™t ²&m8k\ï3 ˜þĉ£fÁB`\–Á#iÏ¡?€û&õïÿv'<Øö3¶ôÒã{}}³úÞ+ i°­4ƒª,x_sçø*¤ MïF³°‹Ãoý._Èy›~z Ëlõ=pÏXœÖƒ{g'‡Ü8Œ¥·MCļ»Å›©6Ãüd’ˆT(eø‘•]m«²+ÞÈ ðì¹ZMÂÕRà=óK#Àóf;¥0IŠ-F PËH©­wز½^ßÚT‡Þ†6C»¶Nãg¼½‡ Á°(¶ŸUšš©Ä"\q™+¯šÙŠ/ùdÀ.>¬Ü$ØPb^A$sjÞ¤&'\9b•ÿ”X<‡uS¦Ò؉ùµá+’iY0oû¾/£¤û¤)ðñ÷¶26ü‰ã¯Ä\äiƒô²éÛ5KG}YD‹ñXüôL ¼ü½[Œõ¢Åøs·XmøÑ-޽¬Ô-ÆÞîõñ÷n±XÔÙ-¾>>ºÅ¤ lGæ²[ßH]Š·ØÞi_oš;‚§u ÒÂLö­D.N‚{dˆRÔTËJQ Ø׋{J[O3Ÿ6e>ðgnÒ‡D‰Δ“ÞV½lXd_úÚÑT½¬[Œ¯¹gK´ëL¯‚[F”ž±’¯¹‚X*¨.ºÚW¸¼Þ žpB‡XÏ/jĺÔ5w\y¹+y²¡åví(XˆœÍbׇ¤½Ñ-^Éþ!ï†Hè ÀÛZ?u»y¥³[ß?Ã멟õTölø edØRd-K9 z¢@Ê„¬%t+Xt¥Þ¬¥ÀWF™Ü73¤‹ÆhÙÿ:æÆ¶™6Ý»y}†üþa´¬QËä+ ¼òâýD†á¾Å!XSÍ«òïÑÏäÒ…:¥æ5øÁ³²¸}ËíoW;+11ÞM“Þ¾?8‹Å|…â‹[ñ6`ZÃîu EÇz<ˆ‰èç¯?©‰•NìYÍÆÌ[ø¨x¡µÅ´K•n,ËMsÐç*ˆNf^< ¹0s5ו¦ÀSÁt—ݿŸ/ ë@—S<55,Ú¸ñ…„i¨Ç–¯°MŒÿlÆ€¤À¦í>ë^J,VPÌ]9!©ù&àÌ—i()ðéèyÄìž³ÑYnGGOFÛ Pê.ÙþaCöx^Ôû¡q°k©çìQZp0 9ûÒ,Âd÷þ>™Ç4ßNâÁñŽnTC %ãÀN¹ŽâEÒdÏ5Ž~AÒ·W_GÆöPeÈkŽ”²ÔuŽ$ÓI"YÈîwצœp‹äÙê‹vʼnáÓò¾_¹«òÏù8÷53×cަ=qùüDŠQü„|ÑÉCóGÖŽ}cò• G!†ÞݺÒám¥ÛÛ‘8’šÍ”t¼æ~Él'£_Qh¶FÝÓºbÓÈÆQd‹3iý:¸.2  øŽ¼¢|D•JñpŒ*XŒU0åŠÈ1Õ‰ØÚŽá´gO³dH¢C…þ“ÚØ(úÈë»V‹»Ö°•ø¶kíô‚}ךçc׺fÞ-i 0u«u§•÷ ß¶[Þäí{¯GÝ„CÀR ºnÁ´x–ëÂ¥“æ·IìpëÙûo}ÿ¼õþeö[‡‡9Z ÌnÝ óÃÊãÌ@ÔHÆW…Yz#jÔ((nw5(ŸŒÖm­·;¢‘Š*| z`„0LH›]ñ’™¥~ƒTRñÑôxÅ织-e‘@cDzS\ÙóŠÑ³¥ì7Yox!íX;”ƒŽi¢’Ì)9³œ§=•‹Û‡Ï.!ù¬¢Ü¸§Àâ“äãýƬk‘äÀÏ ˆÃ6¨~]²+ÒR¢<ëèëðŽ)ø2÷¯Ÿ|Mc%Ÿ³Ù®áè(„½È ;Ývëj€SÁ×siŸ¡š†÷¶Üé@õ ûv]¢4— ÀÛ§ï˜îCv£ºkE÷¯îNŠëæy¤¬<î¼÷¯Ì¸soѧ©µ8Îã– Ä5ø$~œ0ëà&¿nâÿ„]Û’›:Ó}¥±ñxìË}¿S•ý:$@@åéZÌäûs‘JªVa¢ÕǵÖÃz~œœÆÿ$ƒ&UýùÒÓ¥—f*üË$fí¯].½h4…¼]U°òú uïc!I´ÄÀûYdÜnW÷tõ¶ ]1!nÔÏ­ عé|œ@˜ã¥½&Jº=$fàg 5©ñÐimT_<Ì™ûL—ÖÙÆÛ“æ±ú ü*LEr9•Î;/J`àël‚o!´2:B„.ÏsZØLÒ;ËK©^ÆbÁÏiùc[lÞ kV±’â±÷äÄ 9Óþƒ Ëóvå=áMÜAÊY.ÃÀÀ{¢iù"^35ÅÎrè¼? h<:fèÑ—\Ú†pn÷ÞЃ虦€sÂ&±¯å³¿Pº³ÉbPÄûŽ-™³. ß8ðOG·w÷ý7î¿àì7œ ̰á2áC»×ûNÚúžž÷+…D“¬ï6Ø]×nÍ$HwDZ $Ú*eeçÎP×9¨µ Òâ?¿±ñ ºÍ26Èü¤ÅùõˆLFîìÚÚ®†æ$-^oÇøGâÛWš,zg1iq9¡›nDƒÏˈu4•êH½³ÏÇ·õ&ò\ŠúvZGh¸x>.ÕÖ¤`ÙøSvÛ·Uöøø1YFð ÆóQÎÊ%zðoÐÛH«?—’Þ1¬1—ÃÏÊ]g«¶s¶êþ,k-@P—Z…ˆR”Ÿ p!ŠÚtF¤Õ1Ó.Pò&ªN=-«5XaÞ¹d§zçÓVkèï}–-/kœŒ¤ŸÌ$$Á@ÌÊS‰»~ 3 >±Æ]Ö£c+•þ” àÁZ'§*öï{ïy’.³XÝ1ÓnÒ­ËW¤–PÛôdi0ð]jG6`o{dß·¦/‹Yÿ¡ñ!‹wS.ä ³äqm…–þ;å5OQ β.ˆ1Št>RßLDTñÔgý¯û K“±@>0kbJëת‡ÚºµÜBi²=i±$Y’°5ľyKÅ äóTyƒt]íOžÆ‡X¶¼Ï/¬s”Û«œüƤå5™Lé¯sWÝvÚ¶ƒ> Ì´?3^ç„”–ëMºštÅ^ÿH9®þ;ªèVÓ~k ŒX`¦Ý?¹T‘7ÈFè>l|*¶\ŒBÞB¡ɘÍHÅl_¼Í{ýìäàž ’}z¡z¬ äy>Ý;L.š¢]Šg¿bm­|>J¿“øÐ±â½ßŸ'2jV„U’ÞÆÔZ«â½ß¿Î3WÕ@5PÒÔ¤¼OÜP÷ÉMEEieRGɯ¤z’)ÂÙ²h³7õ\˜™Ÿs|ƒ‹ ÞÁì¨?äøv 1bGÅ9>o\c´Ü¶`"vÔ˜ã1«SFéIõ`â^EÈ1aéZå½P;¨ˆT ý—Î£ì Ÿˆõ0°úhœöžÃÀª²¬õÀ‚lE;Ï+~"FíìÙÊ‘3Ë„ÜÌó:áN©øQ¸Éû¶3Õ¿ {rT½hG`!ÎÀ.Ë'a:£oÊxÃU<ÌGyM¼¤ð6¸pŽÃ‚`N DÐÒ‘¹ÞÃ- Ñ(e”NuKãÌR¯‡—óBÖuƒ–­Ø¡OÔ0´† ÅóÜŽüQMYžÄ³Ì‘ LÃeäÇo‹¶jÒå}fEÇ õª-–81c$#ŸWdpƒ¥Êû<;‰™ÈáŒáj]ºµk–yª•r4ý>Ùz+Wé}´¡e®®Hø¨ZAFˆíó^OÖõÇŒ ±ÑVÃâºâš÷[Á­~]’]‡$M±ARŽïOñùU«ÍXìh]ÿ+ˬÞíÕ¼øÔ¢u‹ •C¦ ÷ =Ïù‰‹˜0>âwŸ*ÛÏë\%D‡µ Ъ=Lnüo\MžåÂ]3Mœw ¬JäfBs´Q+>-Ê)¾ÅšaŸœ_ùÄ Ã~e£;=ƒR¹svÜ0µ%šùð]LjrJef ;¦"þïOÓŒ ÙMÞ0GñQƒ¶¢Ê½mS«¤åÁÀ ¹­µÈýN´]jj!¨vìwj!‡…¨vsßX6e¸â¶îbDµûc—ù¼À{)îš3wË4OôXðGY‘‡„€v‡uk¡}á}¥i;Û†¡9J€¯Ï⊩é9ô¶mÞËÞØànìºÆ’x2Üi¹:Û´@càãLl èwRÔ‡ôh[Et¡éÜ Á}²,$°ò6HBt¡IZäü›ìÖém¯ `QãM^½šµróÚÁõõ,9›(DÖpk‡y! ~B»ƒÿ óp¼ œnbvY9Ÿ×¼¯?;*;ÿ6uü:%†M6I2Ên;>…3òØ’ ÐQ‚"më8Û: |Ÿz7R$»Ë½Ó²€§ü…# ÷z«™,Z’9SlÞjª³Fß;&~¡þ62åk¢\©:Hÿý%‹+VçP£Lfªiêm͆xzðª›u# çJÛ__'Kjf‚KŽ" ÒŠ›qµÁÀgÑ€—L§µÚö¿_(ÓžÈñeòopÛvïº`àSçf¾¨ÎºVÝ"1°úÎ(á-@ËÂþ‡ùÖÒ—5êPùÛl àß~º÷?½aॠ#.N #.¯«ÔNtë¿Ö!iP³x¿V—ý=N-éõ°ÂTá õFo¿y…ÀéwEËm | _4yÈ*ü7¨‡â§Q[MH=cQo‘õ°Ê⊅t²:t:j>/ÇÀ3‘±¹Þy‡jnŽ™Ô×ePúz+µö³½³üDêOާô_j˜ qÅOM|0|,jéAfêufµä ¬ñ4”ÁI$þ¸ÙÁdäýåKf}>G‹Û¼UGÛgù}‡ ‘Í’Ãh3â°½…f©KàsD&ÙNáŽ03i D’¶²I9ÖÞö’× ‘–Õ™hÍ"Xüü‹È¡;D4 ÷d‘C6O{K¶në1ð^Å…°Yûm W|ÐÈ‘M3íŽùO—a žŸe*æmtÐÔ^ç‰i ¬`ð*u\¥zEË›E*ð”^—à”eÆÌ”‹w‚Š{Lû'«t§9m2ëiì×âŸ0ÊUí:÷-ÇÀ¯bæ+y!þavÿ?W\ñ…urRƒNKwÉöq(—©îe˜P]°Huü㌘8ê)äòV"kž y€¼ÿ¬&§ôÏYý¬&ùúg€ŒöZ,=X—÷Iëˆ"Ãwpì¼×½¬Qï;²G1Xiå­Kӯ༫o³l©sl¡q-€h.'õ‘†1~çü!¦¾+¤fö+`¨c£jÆÀ“Áö¯S5±ªUÞ¸Ë÷W6çaR”SÒ„ ²ïR (´cðC¹çÊfÑì{Á|¿íì‰,¦'ÚÈÞ¢œ:Ùa¨ƒµ¶®Ç¾ÁÀbì̽¦l#Æ’žB§ëûQ”3¾A­"Ÿ8«Ÿ œ¡²Ðóz‹‡ùÂ3/" {“eâð;ß${üP’⊧T!«su+É /°à‡Æ2×d3k38ÝÛLCÈÛ‰šö•êuõ )„÷)PåÉѺ꿆µÞ÷ƒ•òý@匟ãX"OªJ²Ô¡ÆŽisq(úÞšXÉÏÿ§l×µø×²ÝÖBúýyI×¹—É9âH;èz_š"x&¤kÊ‡Þ ãV ¼„5‡“áCÀ•øˆزÞÏÒâ y’ï« ”ÞÏkú4×1¨ã«™§Á´øYäY$xøÌ@h4Ÿ' 1ÔzœYÇ0Ù§üû"?&_²º˜çz6@að¾ÈÙeM´”kï] |#ªËÄF§{ÂLê£ åS“YÞ5MyWÙ‘Áy+z<âËád ? -;B‰H2X‚Ù´¹,åéúY¨È¬rb…bÜËCnó7ä'gR«÷6#/Ès,øŸ1¾P-½q¡CyM”µ‚A´ eDÖa^çy¦­8ôy,âƒj)ýŒ–HÒ Ë\÷mH/39B9ÖI,`žòï€Ìñ÷–'ðÒ*¹À¦ß³â‰îG>3dÓ{w£GÚo0Y÷Æòé­(ö{ãêaUGG0&ªNÇ^j Cfí€càý¢æÜ+{Ø~S྿.aˆnïÛuébA õ÷¸¬z®‹{üDÛYÿÛµw#: <šGq~oæfYý[ÕøurœBÎT³IÔV‹ø:€Ñé793ï3í–¯ÅS¿‡$š¶œØ:‰–-yÁ?Pº.¶êKíãÚy­×â·o˜w%þeŽ³ã³„Íö* Z¢¬{bçzÄ ­OïWùù1‡ßîru#Ýw ¬N ÌíLm;.vµïë"ð ýÐô|¥Îa Ê¢-V ýín}; ":å,ÞÍ–vµ˜1ð¤¥%PMƒ$VkOžã¡mߤýS}œsø0œ€®öGŽ™mÞ?¦NOÓ2Œ[gaX¯Büå0…‘ŠHû>mVÔkvh+Ä_~a¤dûžcÛê£ìto&W Õ:mÓœâªoü Ôã¾ö:S~W˜<ScRúïP;>¾ '现ÊQˆ6‚VßǯáâüïXŸë¤ÕÇçEï$“š5Cç8éj¾÷˜=‚ƒë.¾k5εÒyÐ©Â”ß…Ž½õ!µuR3˜î!wøHÃÖ¬e¹x^}”c/§Þ½Zz“Í Å |à™â&Ç$ýÞ®u³W,tÜ“g”¿G3 ¦ÇÀ'Ú¸")=yßXùÜåÓ&¿›¨Ò›Vô=Ðñ“/ä9ä{4rêìà-ƈoÌ7§@E{ÏÅû¬Å‚…ÀT#r\ˆ«ç©@úMY™=NO@€Èû9hÀ2I“±Ó"í¡t ÈätŸ2qF–ÅöÍ`¦X¢ÛãÒúÞ‘Q!wMMùDŸH ©„ž,†]·š»ùĤi·-£&|§Mnxä“)âh£”&ÛLùD/<ŸrBÝäÖ‘³³ÕGYwŽÂo±ÑuÖŒK×òïÇóˆÈQU7Û‘ô 2°*å-bº™6N¯¡9 ±ÂªÌsœ3ßd? 6aàç)"T:IJõ¤·Á÷øM‹_GQC©bT4D¶¿ð7C‚4µªç_ˆ³L%;ÀUÔnÛ$1ðò܉ý1,8µíò8M…øË£»-KÌmM¼µm %Õí£ì”4 èZÛ5@é_ÝJZçÕ RSÝf6‘»îª*ËoÿÁtxXG¾-i¶°º¡²üw`¿^€OÌ^lrÒüO[Ýó&'¯«ÛG¡ š¢-Fß«BüåçPmjõiå䦌äí(Ë癩ÓE-­õ7J‹+«ê¥PD)â&cŒ(.Y(åv×d”|_l‰<Ù¸Jƒz‘÷‰¬ÍÐk~*ñ£AÆ/¢˜q]Š×˜¬~ì¨srB)×ù³©Ïam…¨Ûã=ÏŒ–¨;Ý.3˜´Û­d½ã,_qöïz¶váŠ÷’–£ÞÔ@Ølôìmb–±ÓOÜ~76)“‰g2ð^4%~E»{×}’¶Ð㇙T7ìZB DuæÝþEs¥ßUKä²ÔX¸™:9гt›ÜGV\ñå^²}ö@ºíPT¨nB ì¤ð À:’ôb`1ï#  "ø\…€ ‰ØÊ§N–Û¡4“î‘¶dä´¸Çx4ü–š_›ÁX×:AtW,øB3—±cëØ™)BZ8pó%‘$»Ï“Ð † È;F¦-ÙÚ½ •ù½xðîåS©¨ÛîÞ^ÃwØA—VÇРCï³yekÎIW·k«cj œ[¼_kЬnŸ—ŽZ‘9£}ìÉzC»,ÔXÝ>¯m*Éñn´–=¡M¯0ð1æ&j£²v¦&7óV·+¡n5Ô<Ë¥ƒàêöUô³Ô4%¯ý+d¯ÜKþ*ÛTXì` Çl·|ÝÖã“EÅß?G;B6Èg ¼ö-d ¶aÉÀûGIž\üôâ`¨î8öü[§’o̽ïãí…Îsr¦ŒþZëá’‹wŸwæ=Þïż~ª?p:ËÕÕ]^ð“2ÆbòÁíc&nwÝ>càyÌ&v×dLï\“;dª{õ·úýê÷FÛ‹"ºÌ༸Ið,¹Ra‚çÿ#ìÊ–$µ™î+uµõeß1~! ˆÂOÿK(2«ºý‡gì›c(´æzÎO4”t¬œh[§¶¡¤À ¦*Â`ÓÈY¡¹r¹þZ¡×Ž«T}Å^}ý¸¨~`ÀÛ5£¬t¿Öxÿ8êÞ1àƒ1ïî;óneÅ0Sà“$Π¦¾ËdD0Ó~bØ{«VÝuáNâã%ÿ¦c·@OÚØJ¶jdÈOf}úµïÖZåDÊ.7. ¿2EF ìe¼ü D1zfGžÄfø=C[ HòÀë/À±zÞ0CËÒ¤S9„ÿŒøs>µï£Øû@Ðg²ÆúºÕ¥.û#6—£ÊÎ5Òl[$xæ¼øËý-ÉžÂíØ˜I.ÛºRà…ZˆÐÿ4†}¶¸µß(0£UÑ ';V®«„+ñÕ?TE#A‹­ç¦k+ ¼P`*ê÷ºèÊÎ7Ž3þÄÙ¬jT{ìÃçÛ«-ôy¡'í]ó$­Û!»–¨OœŸÝ¶¢ksy²¯þ¡9?æëÿiN.ÆŒRe§JÀ–¥^Ä6 Jc–½(¤—‰|VµÝôÐB¦2Ë>¹[~TÒ……+¢=Ýs¬J*ß;9ü“‹ôd3ÂÆügIí7éÊŽLZuaZŒ|6fþ1RÖ2V˜óùö1)€¶äc>ÿócÂûW Ìã¶ÀÇÁì“x˜ÑÜ4ÀºRTn:YöÊ6 Gnl¿Y'%F 5RJ丛đ&··e íå¡Dö[ˆÄÆ›¦«”–+²@ujÝnûÜÌÕP‚Ün–½ò—Bá… ‡èª–I9M"Ô9–¹ZE[u°¡ñn¦À`®S¿w‰¯Œ±c·ïW½.±NVxãGÊîÄÊÅvÚÐèʲ÷ndß÷éU5áµ™e/þî¡2^v¦X·ªÇ¹&6a7¾Z{äüLbo•ÜSZH/§­˜)ð,ÑÐÐe¬\#T¾NÇž¹ýR–\­“¨·¡ò^y©ËÛmF#ëa$ÞNmôr3™púä@A ÀûYꂎ©]ÜÆ¦A lÀ?h 8•vM± •AÒ&£´ÖkJ,¥(y/{+nðÖ$´ÖI•Þ{) ¥Û¶õH ê¡™n¶ªnÕ°LÈ<¨|hæÊ‡ vÕx£@»«#Mº6Ú·"ixÚÞ­FÑ*üO³ìcŒ7"±æCŸ¯vÀØåèÞM)pJÛ„+Lz±Îx9+|Tbˆ³ÛTok>}¢ÀŒ°±îγ)·nÖË2Ø™½úJˆvi­°ÄýX}W q–=£ÇCÛ­iöá·CÁ^}'m³‰°¢ì'±v±hTd$øû‡¶1Mõ8¶“qÇÆ~œJs)î +78¹ [G üâqç}‰7¢õ¦FZ ðƒÊÉìõ{Úf ޤËž!?Q 1ÊzA™V#U-ʪb/ÿdÒ:©:­iE³MÝpÜ Oæê& žý‰–n[y ¤š Ð[ñ¼ªR“&U»Eó¨^îdC×—Þ(‹OÔƒÃßøõþW·ÍP@½EF˜Öø]Ù¿‘ËL zKûolmpO ¤2S­X—¾_µUŸìúñJümR›Nné7hÐήïý<Øç_û¥óÈÖd„scÔ˜Îïæ²n: ãà©ê³h©ÀfY#3<I×Ëk•ŸQP>`==I•Ÿ‚›!ØÊ8g1=x½¼ðí©Ô>?ÊN4ÐsÀ;&%µ²ëj_w¢Ís |¼$E“nUÝŠiª)¢å06EŽUN¿¢§À/&R¾an‚räu`À?èAUB­Ppø„î{6>Ÿ$a *eÑß,T†‰#/¯I±Ël©Z5µ˜@$eA,mʶ +e»HPtEäõ‡\k>ÔÝTúz`È¥a0‰´`œÂ]*¤ ï$¦ ªáwFšâ)gSÕOs}²Þà ‰mÛ$T!òy¶îõif/¢+D°Ê_žùE¸œ ¾fu¼…Á,Xë'Xâ›ÜjÍ‘glN¥5Žürlæ`.-l|ïÌ2õ®`ȃ¿z'¤Ró:f¹û†}{"-Øm!Ò•ž-fïüŸ»f¬w+Fõ¯„0îN…ýjé«ÑŽmÓµì7ÞN W÷•r¬çãúËX,çNÈ}e0È|½²úÁÔZ¬M׷ÆfÄ«¦D²"ÒÍ[¹Þm~ÌíýŠæÀ_ž¸Ç+Qõ}1öì‰Ù;Ð9áê©k$+­Ãa½”ÅŒ¾-Ñ”øè(ðþ°ãO|ü=ñyHƒA .|õlæ*XÀZSàQÁ³gÑ&½Ñį¾ó<å;ÐQàÁÉ•+¹-Q\¶©Ý”ž=1#ZZÓ¡/—É•FRàõG`_Y×·ÞÞíO¼ÿüቧ¼[¡Á­úÍÔ«_ŠšŸ˜ _#P¬f6 üú Ø"ñø)ïfAÎTÓd*39ÑŸÌAØçfw"-"ùƒw#¾’v* ´Qq«ê¸sÌ]>íÀ+:·yÊ ™hÎE0‰¼m)ðF.؇&\ßá5Þ éP´›bÌÓ‹Åu¾ÊÙÇ<öM‚<ÚÑ&qÉø'gÃó|ß^2m/!ðë?€ìÕL£Oƒ›"nD(‘E$›sxyÖöí‚/¾Mâ ÐQà…*UØý²±Á`‹!§³ÿH&±8'ÑÇI<îšç/;1lÙ(ª=9þ¼>~Û7£Ã(üõɾl‰Û& Rø{xÿ×çËч¥_v¶ÂÆøê¯7.åT1`G-#—FRàIj¦±´ ž‘¦û¶¢@ÂYÈ£Åh| ‚zÙõUÙ’×mY)ðFåï Ò3NZ,ëZOxçå@)5#ëº*Fþ1Ÿ€cß eÀçÉ^}ˆ'6¾siš†OšëÝ)Ùëò|ù$•b~DQ´QId¥t²Ÿ½è/’µ£ZC_÷" {“ƒ~ûÁ§/Ñ`Xýºaôˆ*§@4J_´%{böŒÃ€P&Àë;}µM×TE ê›dÁp(—[7zíñê¼}¼ŠPé2)k»²žÕPb\ïöÁ †¸e½õ’˜²-C­TÕÍó$;Ù±WÓj;•$T'gÛÖ¬ÃÛçkÈãnm+W ò–ù>7Ò—”Gä퓱àò¹–a®eIW.ÌQî}ˆ½è«²AßÿöùB‚ƒ‘¦-#—på\·OBæñö!L¡1|$,€õÄã>l–7Â@þâ&]ÅkìÓ±FSà.Š\•pN5m %øJ±á¡=#çò©ÂòéÏåóÉIpÎÍ‹ÎÂf@±D^Î^4$›r-m;aË"3Êž¿p'*)ÝÝ¿ äl­í’~"¬5qз“ü\C©û3.¶(K‹íò¾Ø›[ݱØ./Ì1¯Kc(0ûeit1‰Nן¯?ƒ™…Û…SW¿œåNa@óvaG4]£·Þkto—×#ÊÉì8hŽh¬Ë»]XiçûöP~aÍÛQŒ†0ªjšŠ øÇ¹0° 3.Œ6¸ÈÇ1y!îã~ˆ‹h£`¯=ên^Ú™º„â1ÖK'–ŶlÌqéÏ¿H“b7ãfí†6U„úØâ]Ϫ¥Hôo,XU}kªZ–‡ŸHÔZþ÷Më l1 åœ×øá¯eìM3ŒK3L-m•¤3YÚÔ:˜²è;m•”IJÀrÐ;Ñ ;® ÀëO¥¼­¼n|CôÆÁöŸ¦/»uE÷3`„ZfµëjÓY¤àã½<×ëGÌÆµ ø¤w<(W† ÙfEZ~Ñòà¥34›8<¯Š´Pchó¦ÖhE„¡ó>y1-f[ 6ÂPE´QDmêt(ožZ8šVÂK³M®))ðö O4f´óÂ^}'R¡H—]e7Í#J·³KñoÒ<ƒó'/Äd¦i#ž w m^,yµH‡¥´·³K xRŽ/˜ˆfÚʳ¯7Ò¥xè­íÐÜ»Ùë¹8ÙÔgIbU„ýº9/ukW ¼°DIb‹ˆ‰’A)쿹=_¦éaÃ6˜¼¯U‡÷'éügRe¼µý¶´‹Å ƒÛ›´ïAkD¤¦ìþñV7]‚X°«F#Â/¥@ªgjRÀŠV#(0; 0ìÓa_#0âe÷·ºi쇛3k«%{âí½x9U% ü§Ùýì#ˆUؤhKoœó&œ¤TQ&i{§zÍ(T>«­ê@4)£Š2ß ]%>1 ¼/ÄV` *Ê€ê:¤ˆ]ð—ºJcT*Ê`KØN%&«J+¬¡!Š2±#L úTxâ8ÔCQ ÞHùÞI¾O7´Û(źQྻV¸SMWn¼aŠu À'iv²iUÔFÁ÷4ǯÓ$GŽ©©öñš0XCeŽÊn¨+.on—£-”*Ê€sŒu÷ý6é²¶ Ô’E™C–:åŘ·qÌŽùkÝRÕй Ÿ¾lšÆ§VÊÎb›Š:âSëZE;ˆb¡ÀìO±êû±]EžOxýi„Š8BGQàýòZnË=ÙFù0%»cíÉ=Jµ¤”=û˜Ç©u©Î<-ªï?ÿÛ¥ӶѽêÚ:r R!‹›'aUÝ GÇÉš‹»Þ„ˆu,#z‰÷Œ‰»E `ؼnz^iÁÝ.÷`ó¹[º± ;œ ¿ êîMõ\ýV§JÆ$vÅ¡ÚÝu>Ï»\HöêË­íå¬KÞ Ó-=½ðUï0I¾ïWSô@¹@ஃ޶tŠðÊ5ÖðÞ)§áŠÒ9Ï󲨹ÎÙ×`«éwªzÙ‘Á³h–rëŽÏ¹¾-¨”TÔƒ2ƒšZLçÞo¼àFªxk?Ç2•óØåi ‘Šöºjœë%î<-À}È{©Äf·Š¯hA·óaúxÝHõ€JÐIî|“‹ÉköjÚXlSÉݺԲ]òó4½1é—tÏíÞW¥"[²ßðÉ 6SÊ5ø+‹ÌA¯€_çÌ Q£V«Æz û˜³T,‡jŸ`˜zª†"V ùù+ÒyÖ‹K<ûvd^3›EÈóGVÌ8ßI9η‘öåíG`~t¤æ³È›pßXöéŸg  Dç<÷[>lã7é@ˆsc¬ÌÙÜ|^Hø•jÖZ¹\0dv"¡cЪÁûqu¦Îòzx¿ÒÀïÌ}^šEÌ›ð´y•# !¹i'± y§šßö@Î~.Kþí³‹5Š˜iZ„ü‹Ž–EhæÚo|‘wÓL2†ü:¬¶tㇿ¹±ñ­S’­õsóÅ·‹­2‘ª—-ÍËçIH¯-Tš",ï±b˜è6¡˜YªqÊøÂ;¶”’nÓú'•Ф »”Â7]øÛAPýûObÝÓb“¨M×u|6/§$(F¤J¿úZ˜I)6J—û‰„ž¥€ìÂ'-•äß~†=’C7{щ2l6ÇVÈåù²[ÛÁ—¯3”‚úR"¼XÄ@û©HçðšÁÎÅNŒ|PݦïoÒ°nüÚW1ÚÞP cØ. nóJ Êqv)–Z+d3–¢)ûãÐ|p |ïÞGÛ»5þ˜Éo­ÐÜkçŒË—\–ÞƒÛ'9?#±dîrgÙW?ˆOPåC,®¦À'¥JÌËU›% Ž¿ÎF µNñ‰Å²æ¿“ "-(¿5®ëˆùþ;IÇÊü¨N Ô…XÂ^ß66äŸ,±»ß>1䓇÷«V3ä!1r4Ý•ýØýâ\Á‘ÄéBÏ'øa©õ c¯€¼ V¼vNS)WÖѸW O›ç2÷fÖüÛgAÊ\D·´i'JÌ!õ/<_“oØդ樹C—wž×*’•¾Çf¬Sý+¸¥ÀE›Ü…M åÔM^i*$ØZzéæÙqà„ÆÁqŸÜèLÛŽXÒIÕ¿ Æ—ê§b˜Ê×íø_/mø#Pn ©À3"qtˆ¦Æ;+l¿¹ÛÆ©Än[n;€=^ëiMíß¶ÒåæŽzm*qôƒW,=Þ|Ñ‹D·OœÃOdÀì'`xâ¼ø½úJ©r9>±š§Â¬xC¯]=-• Ô¸ÉK]2PI?JÖasØßO.õqP““V ÁìWì‰Oêq@ ÊÖ–ÿGص-ÇŠ+Ë_²»±»ýxÞÏD¬ý ‰›@ Å|ýR”ÚöÚË1ó Q—¬Léô†µéË ë’{J_0m[Çú( ¼S È”Ps\l{í)ðþ»`6Ž.\NZ8ŸNëãŸs¿¡Æôý²³zn?ogó.ž¶ICŒŠí(ðNº|Pê2A­&°… ¬ð#ÇAžRu­aó"ÌžžIM+€—4´smº:àLýãU3Ù CÜl™XF‡ðEl³AN¾î5 ²eÈ"z¼ˆm6™$£:ÛsÝóe‘3¾´Ræ¶ð!.Š™NGYhoR‰6 üO1>Ã…Ç£7„6MêçøŽ5¡–Òkû´÷1ĉû—M XOÜ) ÛŒÁµ”úÑ|˨ÔžÒØ‡x|í@0²9>ìû¬R) ¼ÿj>mBqꊪVçõ“õÄÛv±x¥‹¹…”?U`Æ…ÕáÇ hQÓÔÖ.j°hG¼§þ?¿…â š&L ž/"Wµl É•Ð2>?ß¿1§ºÔXy?ªun›•o¤è‹R­õüRlÔ>ß S¹”3´“šæxÍj‰†Éñ7Æß; £…˜€;’0ø¦ë@Ÿ¿ˆKl—¸u7úI3¢ÇeFÜ~Z[—ЧfÄóöWq‰WàßÄ%ŠSÿM\BSàoâî—x’þÇJ+é´B=~TZÑþEiì¤îÄÓég¥•¡8õ_”Vtü‹Ò ªÜO§Ÿ•Vúø¥í(ðoJ+=þ¦´".¥•ÂÓég¥•½@¾~`$³y!œ{Eõ€E$#í¶zÖ;K·ïÓÓó ;k[ƒœÈgõÍ·,_w;ÔjX¸ÀFÛ³z¡²d‚S¦SøQÒŒÁS6šY¹É‰?_’€Üvk?l(¢Kl§æ@ÙÎÉ+~ñÒƒjœ—µQ’SÌÑpšá‹‘”››ÅÀ*‚KoÖÃSR¸ Y4—µ‘ÿ¿ì † ßâdÏß `uE> ˆ)¾(É9?¯úšø“ÍF!À“­Eß1äý>¯8åOÖ¢‚‹Ù&6x/w; ®Jÿþƒ •ô54L³XT›|ReÑÓÅøHT–¥Õœo¬£À;¹=˜Š+×êÙõMÌú•‡‘gn%YJ½5v]°ý||Ñ-ƒ‹¯×ó ¨ó|–’g¯1 Åï¿Ç8mü¼Hõ{¤ƒ´ëy8þÅÄ? ]”ô†Ð†ÞÎ-Ê<¿^™g*ëê lÒ:Œ|¨½N6-ƒP3îÍñïØ¡)ðFÍ»òÅ ¬Ù‡qPm$sgœ²º§ƒÍé¯÷ß┕ï&¬÷ž¯è$Ù¢Ž¹ePËàö|Ý^®:Ë#æÒZom,‰>)£ÑìÙ0°9½Ý_ì2p=ʱqKíF©)ðVlR‰ì¬¬è›á“'F3߇I8”/£™¬Üâ<½l˜`F*°©¼_F3ÙDø$æé¸À­‘ÆÀO"Ë&³¹boå4òy”U‘»[:ÆX&fíHd¢Á_BiUkYûq†=üô¸ÉRâ$‡p8ÈéÔãæ»u`ˆx¹ˆ‘É¿ÿ‚yvÛ³ý¾ñÑà³þüÊd6ãTŸÀÇ7¾Kf©îÓ°Ëø-FÙÞ¯R7*yÄe V†Q޵^(°ø‚$KŒ¸ 3y|= èúœmmÛYÕLÆP MJÓ—Pv5; =ì€ä¸SFú€ÛË9»Ža6~þÅðŸÌ¹¥|W™”!~7aD¨zûæØuf†fÝ›0B}¦"¢÷?yѰ©_)ðŋ渚ìEc5´"xÿ«ðÔ·"Ã>Ø)MºácÜ&å|²ŠˆÞ—Ú Gf8èE+IW»D ™ÕµëÔ³zÞ¯ý±IìÎÉn ýЕ§®NfA’n9¶½tj%HhåMþpDÑÀýÌ hÀO4âªS‡,¥1õ†]û# ¥Ä«:L®âv±Oº¸êg!‘ÂÂYêY»HyV¥fƒÅϨ¦ÜH’ÒÄS8B®ãÉpnI÷BÙFeöp¼=ñªAÛ €U7'¦@ši ¥çç4N®ýSñ™Ï*)«Ñ;TàCÆpÕ[?ò&M&Î×4ý@—GE–m‘86‹å *C/»Ûµ[œ‹—„ðó›“nöʰ0ö"ÒŠ¼ŶqUS_ôFDªV$ˆnšÚM ª·ÏWW±4– Ó1mŒ.¤m ä'±Yi.® 62éÏ}€º-eÁtx¿•[زÕ^Úù¼ ^˜ï;û;xè 7¦s™Tæb´«çôT¬õœÿ³Ÿ;`ÊXb‚ÁØRÜù¬7B‘]J‚œ–XyFäíø:­Àš‰]·Èû©÷ß`¾$%S}ËfU\û \ÿ|ò8û<1ùæ^ ?~Pçñ57ÛØ 9ëüûŸA(Uv k½™—¹xîIoçª!¥Œ»ê4Ç\Ȉ|â¨?KjEY…­+[°úùU´w2÷÷hïtfÞq%?~é@±¶vZ)ðö„OG ýÜZî‹#Þ¿·N"0¾í+’«·×Ž×Ô¥Çë~þÔÅìH •G ûA²-¬ÓøõzÕY2!ç<—ðW1QBÅlr5p·ké ä®Þß^ÌÙ›Ì÷SVwõØÖ +êu€”!¹7íg¥p?xñ:¸$•ÝSm.ÑÈ©½&ÓVL͌ѵ¶žÏ}}2v–´[õÐÀ;!„ãÀÆ ë†ÚC¬ˆ` LÎÕ=ÛD3À?.j ŠD¶ë"¦0 @@àç‹®Ùq#‡ƒ‚ÓvÖãû÷¦‚ÑÙ›ÎM|§ÀZÄûXcÓˆ²ñÐc©¨à?L¸´‰¡É†–¶üGýÞ´Âùjå¬úsáRÁ¾‡žß`—~rˆ«WTð?ÏzHìïÊÍmÚ2q¨R<ìÒù ¥·…&^ÚNgÙÖc¼ãVÔÝ#BÙäh7 ‘ßó½g|_YqÄŠÌõ4y“´ÂtZ\x üø½uÒá#üü­“sõ|~RÊmÛä8Â9_ñ>–ú‹iH)·–›}“}oìD·€­ÛPSà½ðÉéþáÒì ˆG¬~Æ#.߀…GÖ$Ý*¥h ü,:9‹ç¶]¤íz |¦WbU*µÇd1ææþ|¯I*«!°AÆWaá.~h5‚s¦ÇæzŸq»b^Îev¥Ò¹vÑžr‡×ûP×ųҞ=àjÔȶ¥Uøñó©Q&x¼_™4=€ ­RÝÞ ó1*Ød•]æ rîêF¥ÁÒ6ÉÍ)†¥u3¸µVDš¿”€ ag1RD (Þ‰”De§iŸbšro$–© tÞ”êUßÌjÄßxûé7¦G¨|3»QôxCsðëˆ!HÆÇ=Mß~£:~#ŸúÉ‹‰O>Vr€È £ §ø¨cLÀûK÷"9{ø¦`=W€”+6P¿±Ÿƒ™g×Qà©ÈÉ’»sZfë. f$D¢þH¯(PʸÒ: UD¢>Kº¢–5Ѧ“ÎÀœrE$êÏ;>Y¥1Áû±?WÏGñ³»½Ìîƒñ£n• øñ PÍ ¬‘¨×[ 3&ÜJ9oõÜSàƒÌIØíG~Ð,vQŸ„›}ܼe»ÀÍþv̓üóÏ1¥XƒVkb ¹pf‹#^îÎu>¹JÖ~v‹eC¤6â2‹NÚ5b7½¶xòϗϦ@.ì`×uë‚VøJ$8 ¢S ÙƒÙÌJÄo‹6A­ƒê½ =Vg)†£f€Óc¯W/lqêZÉûýº¯õ84aÄË~¼–´ êŠÀuÜã#Ú)ðv=›DP?ª’;ÛéÄχH>I([Æ,ÄpQ±"c5NÍü2nlÕ#1k ¾Q+cëÿ[ à%f-pN(~<!ÝæŠ«~àôX eÉcÛ9f‰úÜ!/pYÜé_Š;Ô>àçâNO¿wv ^©}@"ƒ¡Ê¤bîѬK÷ñë›®{–!Ï1 jÞß^n –~1Œ›Øä[èBW÷÷—ù¶€ž¯Ã4-“€¨ÙŸÊÓé761löl¦x9•ŠT‚>Ên¸w‹†©Š¨Ù#0Ïš7B01f†÷[±Ÿs™º¥[/i¬ÅÞo¥‹w¢×½ž¸<èV–/.Hj¥DWŽj”ƒ>©‹7P[¹¶]ü‹Õ€û­¬+‰S\o›ì #~ñ^2CH…¼Þ°}”†·ëJ­¶Í¡áQWê§0ª½8÷û%²Ø w’XU|Ü2°âäPW*ìO÷˜›í¶CûSD¾ØšfO¤Éu¬õÍR ¯ºR.æ£YÏ–I „bDÒžlÚŸåqEÓ*ºÐ—ȳ®ÄDV¬L¬GÉšeîÊeù¸ÇªlSw[HþT^ÑóÌ ó9 tÇ;/Uà0¯€È¯³AQ·"P ÃÄ>¬ –"î…Ž-:ƒ' æ-~û^‚z:"‰Ç””YhëÀåwßP odÚê¸óòP‰ÇÔ1`-~çíÜ7ê쥖Ä|œnî×âÚoUa!×f 9—GK±ào0HÿçO ÂòSšÛ§ÖaÀ}':¶)ä {W±íöòì`(°i89l³±mœË+:b¦›Fe|î,è:t]y̯’¬pÎúÎcç‹’GdNǹ´@EXlˆáo]ì3÷wœÎb¥Ùù„K3,“,Þ¸ûXÉÁN9Î!¬Þ/Û³•{ª¹îS­‡âÎß+Ú‘Cªÿab§”A$!Výù“¾rñMwÌÆmihp›« CÒ Øwll}ÛN*®Ó# ¯§!ýÏ~Ú•¥#¶í¸ÀŠx“Cåþþ™˜—¼~\æ'ðÀ¤ƒðºñ‘‰Í_5ŽOßc§yGKX0³È£‹=ÍM34؆¸W¥y{®u¤±Ž˜²-õŒãý£p!»¨Z‚‡^ò¹a+¯‰Ô|M9QÜ…wßaZKÝ+~ÐX`øšUÄÇ!‰EÛ“D˜…ð¼ÇÜòþx‘|”0´,ÚÉU´z¥À;¥ €}3=úžK ¬ y‡6s°YÛsž‰ä㑎 „àuÍYñ? %ÇÄ¿Ðñ…98ÃBߤI ²ªûó¥ÌR*ް¶žåS–"Ð\¤ëb (»z¦Àû”Y2â˜Gb1bìXG…4I>âRñÍ(MÀÌ-óÞ› »0ÆPpÆâÒýIøW¹øŸ¯ZJÖnn5º¸˜G9–‰—¸?¯­ÆºÖýY¨±¼l mc¼ß›=~ÑE‘›ÓÇ¢ÃÑÑ*nøÛwµ“ƒ³(c6ØWCÜÜŽ«Id›øMÙ¦®^%¾‡_¥tÂi£dÆêµf–/¯’óˆÞÇ#n~]=Þ ?¶çc@¨c1ô×XQ`æ#Ç#а½?¾;SÅߨÖzÕÃNŸ?;SõqKk |\ JHFt~q^…?`ÕÛ‹é¤*t:Ž2O ³ì_ác¶ÎüÔ–gžCc¸.ÝšÝ1¡€ŽÈ¯3þk°Õ$Ö]0e¥+f޼Áoæ[ý!Gãkc:ˆ|'²0§³,ǰ½ôK±’n7* ¿xKüçɗ⽸¯AÔˆä<îXÞ×0…Ȫ°ŸÊ†Vž9fGcGä_ë çë­+ÏþYŠü%ñ„¹Ó~œLÓÈ%2ç°é8û8oë\<#pȾ0…ÓÕ¬cl°kHê W×k&¦Á¾·™·Ùe…ºsñ¸}±–r䘰d…°ø·›­xš9òÞ!;R ã¹w»Ú p=y?;äǾuB“nǦ¸Ÿ9ò†ÑbÅÎÄxëóþA™Ï™å~È,ï¶±üŸý07ò³îŠ[Œ¶@>HœÃþ]߯—jµmñnÞ/¥1¨ˆï&›b5ƒŸ"¿½ª¦1—ˆËÉ5 DÄÇ(¿î(‡&öÑ.®·æíÕM€íÔˆ¦À²' Ô0Û­6LäýÛhA~’mÌ{œœoDµü²ÚEðA.N ¼_ -kØ®S›cX³8 1xÚ™*fä²5a¥@Ò"C•Ì]O=·S¨†!Ð\c ªz<`>¨TezÚÊ0aãÖÑüT¯µ>ŒOÛÑKä]RçŒ=Oúƒ£ºªã{¦ëº£Àûõ:Jbºp(yNHezAàÈáf3Xs¯ª×"l½a5ßövxvk‰ršb‹ïX_³`)ðRÓ8XBi=.fЮŸ–4ªê’­Ž±`SC¬Ü5–ÅÍÍŒüO¿SɧXkÖÏÂl“§ÀÛw ÖLÍœmû@wì2ç*‰’ˆÀÝD%ãæ‡í”í>;ð›©N¿TÁq=ȹ–^ØÓârPôȇt&&ó!zÛéÅ Óàoü¼ÚÐz¡vl‘îDï¯>X¼´BPàaðsÛ·µ«ìÄžî˜ä$æÖÆ|¢ãŒ‹IÛLkõ¢v—qñI£mŇÝúf⣛)ßÀa龉T{<5išüÉ´œÝmú¦‡¥¥À™€Áø£àá7é[|2ÏršÍ'`¿JQoTøjÏRz%­] ñÀàNo“ܼoK`u¹b;´ë5ì‹2ÄÄ…>òFºHµò­i‘.wš8ä·°>µ²ÿËוåHŽëÀ+UåR™ù9( ç’µxß%sú§2éÌ~@£¿®´-SŒ˜¦‰-ëÊ[ø\_ä+Lû»Ÿv6]°¶Ïçu^f:¶ÜÊ}c½{‰Zbà{ $uW»•ÌÝ Ÿ0ð–g´‚&p3—s_ùwêéÛ¡åàÎo#$`ÈQàŸß-9Qí–u¬ÝV¨("GLK SHžýlŠÁ@¹; üC}Æ6íÇ/÷û"‰\¹ßhY³òLK½cÏåXéOc$ƒµ¦k{ ŽÙX/¦>í\„;t»Î•ö(`ÕrYµ)™"W|Z‘І³¿°È ä(kâé¦+%F¦Õ® ¤Üñ‰ì7pl5tªÖÙµQ;A~#™e ¿ÒmxlXwòn¾ï+ºêE6Á5ËÇ;>‘%žilq(%7wv’^óF©‘’߈¢” jÒÈ ~OOŒû7 ô¯cy©Z3ÑËFúן§CÊ¥›…¤ ø‰ËŠIíݧð¶-Š‚ c}K× ½ª˜/°MPø¸£¸ÕU:V õdŠ¥nÉú¸d&‹¸‰•b,Ýùº$HÿŽ~ý2ŒÔð6=Ï¿—CŸ&iyÈ?"Q@ e’=- oùgóÈT¼wß·Ý×»‘wNdü5Y¾¦·ªæŽãù“Ç,ùQëšW^✠€<}Ü©•[÷W4v<±TZªÒèR¸À)Jú×Cõnû÷7 £\çÈÁ}É‚|áD¶%K=r¸ÜK¡öЬkÌ þ`“Zw¾5Ò hXH½$ÆÖËã ËŸûqÖjväV°®ÜùvQx9¦ªXó.»†ñ®k—vÀÀëq;àÄì¾ßm°ÕÂv ¼}2qñ²cÓà:ÕÄSð2°iÖÍŠ?¨{,»V“¶¾_jPy¤þ®;£‡V ¶i1ðpCñ’1r1#˜t]b jÍBÄ.˜uà‹QgrdQ±¹j;A¹Dí±'^Ä@¬´°#ù? ­“y¾a´u¥1ðpC‘àvè€î‡Z‘7‹Ü8ÿõÛ³ÿn#cÈÏ/µ“˜ùÓ¯@NÿçO†œ„/²eRÂä6¨øšsà+í#_ײzÀ\M 3±ø¯ç¶‚–èXºßÖ]GžRtŽ™ (ŒLö¼óÚä‰ic‰–í÷ÓÒí§Éüñv¿½í§‘Îá÷S¡c D†êáPjµµÖBòZ`ài? J³çýôF»…ÉÐÏï ûí,>‘šoï u £»X’Ømº^ïU7®øÀ;t|“þóu‡PòKÀg†¶t¸ëB¹§_à˜ŽT2JYÏ.Ë"Un'!SªD[Õm]ÓîùÛ1lÒˆ[–²é:.7‚¼à^w¤GûHÓm‚Ñk^†N%XÕL—ýÅŸ„¼H Afr¶÷iAFÒÉo² Û•Kì—ZŸžæ÷ñKK:ÕºZíºŸ~çšL©^ã5¼^Øbò‰M°S³cžYí>ÌŠ¼¢ïÏŸ¤ß\ŽOò†´š£[2Öæî ¹‡™ sÎÃ9ˆÌÛÁå2ÒÎ'äåsv½m“7›^’ý÷_QÀíÖº<¡VŒäí”Gù÷ó(1’r¡™xø† ¦¶z£÷þƒÌÃ’…;| ‹]uNîoGØ JSW’œ6йWf„5ØûÛŸÌ'¿¹°[«10Ïtr,Ò™–·Õ¾åMÙûdg‘3F9`à SZÒæÏü:f+Pwb‡ŒŽ¬ØL}× ùÌy'”„äüMXT «—nÆá„¼pz9jó>Ž=Aâš§Š› Jù-°Qï‡~xÈ™YõhvÛÍEÎ0Ÿ'—¨ñSEÝ_Å…eNE¯YN±5.»VÃÆmÿ`"Ó*ùÞ–¼…?ÛHô2ÚšMy{üù~Æ4tìÔ´ e““Á yý±¸k?ƒ;ív ‚!¯³Ùb÷ãøÆ:ÍÈŸ¾!Õ ß7 zbÓÚÈ$wC^gÿýÁ¿mçº(V¤µÃë,0 x¶¦×Ì»•0 Ì„BOzŒûwß ƒ’l†F%òó6àñfÂíÌ.šja’háíä ÆXêõÞAÚ‡ ¯9RÁ`rÙ·S5¯ÝÊ{ ¼A ê"ñ®ûf/ëzœàf®$R€ƒîx¡$‰Ø²ë™.ôä}dÙ> ¼ ëµZ±ï/P'õ¥¥æeáv1(«ÿÜNö0ɦœô4÷.Îp3÷óŸNdfOØ-6¾¼ÐÏýô§ËÄt¡¾é›Ù@õÛJÑ»V}áVÅc`ÈÇf¦g]]úø®<ž­asQççx2ÅÉE´¦q‡8fkH¦Þ$¹RƒÀmˆ~Īƒ#óωõudüéV»iºš•xý\™q™¯NV@7dV¸UÑX78F”cî¿ LÔŽn+lÚMCáç0«p9È®ÔÌ’•B0Q{˜Uœ€Ó<±Ò?DF÷CâÝ>H«›šüér ‹§Þ­–¶ÚÖûó<½k´p™[¸MÑ`à…©HÞ×v7ºå^)¯ N³%غðu" @à(¯ýÜê˜ ?GgøÏ‘ûÇÕÛfÒŠUÖ’+^qØ‹À½ï2SÄÄl\;Çcí¸ìÖ…Ü%‰ºÞ²qAj!+‘ü›ë²] _L¨1ðŠTïUT¹iæž Ë^î€Ü²¬b¤Ø¸96•† ¹$`¥“ßÍÖÎ[W$°1\4³nuŸLLoXpfU“þ»iÆ¢_Aräqù¨Éôî¶µŒ?.Þud|Týlį0Kø¿-Š…y:†y\ßÈ&™CÒÏÍùŠ×«gYìXërÃÇ•’MtœÅŒ:x·TxÇ›øÑtSaÄZç ÝÇõM!ò •kÏJÉo|ä ɳâŽäŽbÑ ˜|{ÐÒVjPU3õU·7ïTNM5 £A_ìq{÷è ‘ÔFï“1@±y¥-T¹Ñ±Í»™2×cGi‹–xp™Í® rÅ­"Å–]7`àó^U¼W©m¼ìðyÔw$h WºD×ò_ˆù™z—ž{im'¹¢Ï±"C̹½ö¼õ•i‚ K×Ï®¤æSì±–Ü.à: ȧ¤{@¥g™Wôu_?pØLä°°ÔþÊaKÔ4„yü•ÖÈnP,{üÃÖ'Èà<>sØÜ *×vÙ˜Yv üÈas羑çA®å°ù¨›ò\»Ëfó—ÆÀúeLi¸`5Ãwýs~< ènfww­ÙŠùñxFH¼=¸ØW4’s ·nUä7ÞCõ’¶Óe͹;ÒrÅRæ 1ÒeAÆ—é  œ*02.\÷+wÆ`,øñÈÜçgEà+}’ÚÁöJB5éñ cWG%x·ÖŒ{[Có;[_dbcÒÙ[´mŒS Q¦Ö†ËÔ.ø,’\e* äûl½û¾vx3TsÀo!i^p›ª®•3èå 3Ð ‚0as_J[òU•xEVt©Zív¯bl„éñ<¿Þþt*DÚí^¥éú²Â@Ô„‡ë½îÇ ¾™ç×9IŠ|åÒ]±w[M>X<¿N‡ñ0 ’6%¾›ÒóàÙ®sªÂ6L7ëÞ&‹Æüù¸)é°)‘›y|Þi´]Ú‘üé'ÝÜ£\ŸßÜ7‹âìã!bÅ©ôLÒV6K—DüoÈÇ×A@ª÷#›­€üìðñH  Épï—Ó­]i0ð¿ÂàŸ©¢©¬rߣRäŠ÷#4ƒÞ‰Z˜œì¾å7óM·ÿÃÍ099²Íöx|®Éz¶¬ÌèUA¦ |b` ö! pÁ’€'¸¡9ìš~W¥m5Äðç7Í+¤/0&±_Í›zn×’ ±¨t²Zöí­fÝfhe[’ó&W3fm­º¤Î˶$ÇÖòʬP…jaŠýIÓv·tÁlVÛ4®vldK’óÒsý¾€[®Ïë› vjÉ»“³ }™Âô¤Âu…‰»ç= Ëa& Y~DE18P.qýÐ÷¢éy•¶¤±poíò8.²üˆÃÜÀv_Í wÛÈ >vRÞÊaê0ðÜŒ\§¾m,³äfž¶mšð…»£yµB.#·ä} d¹¸pm ÏÚ&'ä^4oÈˉòÉ’íÍ éÔQZÞãô޼}HòîÂd[CæõD”– ,5’Ïc± Z¬ ñ<(-6Ï…˜1´.ªªQù@Ž2iÊNòU‚- Ÿ„;KÏ.cs9UæŽ=J UFzm®ÆJ²Ö¿ˆÎØõÅ8Ž=EÆoü¿€LVáÕÊ|‰êý×Ã;'ÑÑ!Vv^®D­äÞ/×Stó|‰²uËX0Uþ¼½ÙóÁEr½›|py"JËD/±œ]jUêÚKØ>Æ7ƒŠØËô:.]Ëæ¢æ r\?Š(ÌîÝ(–²Ÿü?~É)¯Õïa$ùùóî+k£Eíž"<èøùáI5–[ÍÔ*VÈ%e ¸wKcf^í/hÐ*uJÓ•¨UÞFoÃ1Ùm9Êy×0h•ýQ°`3Ízœ0ðžO’Övá`ŸX9-¹»ô¤]~ Õ¨­ÜtÕn3"Ù0 j”K1wܲa ªÅFÕfwG»a‹s’+Þ°…\Cq@1Œb]8~¬.Ý _l[4ðxÎþ(0}W.K1–v)V <¦SMÛ÷%JÙ »ƒW<œy ¦o¬\òI®ˆfS7Ïeæn_ÔÊoæEߌ×[SÝ–oS¯Æ¶å××¹%[Àኣ¬[Šx}ÑÂLWdýû¯ÄM:5PK}ÌÈk ¼ýÅvºÒ–ïˆô¨’ÕœñŽ&=‡á…×ñ£H+¡D6 =-L1¾ÐJòšKg&f÷ÝJ¶’»>H ¾%þ¶ê§A—ç+¾Î©ƒ?¸Ì›KF˜Èz}Ñ–lúŒgJïÒÂû1¯/Ú’ sc‘æÊ¥[Lõy9Æ`4;–ÆìF -ŒCùC<ªw(±­­(òvmñéçÈ7Só D:^XÀ'9ž´$cJ¶½ëà"½°0À–Lv¼jb¥ÜŽg½#;]–‡ÜS~JÞκpïh òù©F¨¥µ«eôš/¢ƒ¢C.ën³Ìýë4†r²È.dÑs‚üFʼnd¬fTÁLÝŠž¼÷H ÝüS’ GÖr¹°¶ë`_~!a€-¶Í½ì§„˜šš .Z²è@êDáã`V¶h'O)í¶Ä;ÌYl¡ h½ð 5ý–ÞôÛpyÆPX^ó=›ºZŒ¦"Oþò<Ùƒ{WâÖ­w¦i€|e åׇŸÂ%¬b¨vEÃLdè{Iœ:]B Âë $*Dé›åxU‹¦AˆWC9[Žó`9ÎÀr43ィ‹n®ëœµ¾¾ß9/pV'à…uzµ®-^q+ ~ƒ®‡½vˆÆÀÛ_€^ºžï ñTaã£ôª°.u‚VÀ‹¬„w4²mÊò:ÈAFFz:_ 2öL´bâ¹™'ƈTÕ=³5wïÄÀâ¾%áóÕmTµœ»U’þ…f"Ò¾â2E—~ZùfÒ !®çuEÐ7!$…WÖA>rÈdÏ„” ,HèøŒo`Š¢5}J‡æ!PЪºtQúrA>ñĬ`—gl… ZB¾:bÒ8«ûIi³eÍ›´Ö¿$¹Ø¹{ ù¤ß„ݬc€íY½Uyü5!Q«Q%6ý &V …uœ„ú×±@WºfØXw–•6òŽÔŸÓ†åâõæÎ}Yý9!³ì¬ßڒ¨ÛÚÜ[Ï“ y(¯x½ÇsñÚ“‘;S) ùü€ìR*òÞ£òÊ–Ï+¨b"ƒAÈ)â9­i„[G½ãd0˜TøÒYi›ÜÓÜšr%W¼’£MJ V¢ƒìD¸ENc<²¸Ó©Q«pÔ~ôBŠàì)=ݳ4®x?NÁtn]¦ºìX¯ûÿøº’íHq øKvQØ®ãܧßëù!´ Ø…Þ|ýhIA ·Ç§>DC!P*׈2I[SžðGß`L6rež>¹°þ+² n%mNè¿>nWÌIÞ6Ôxh{œ›÷Ö)DÃ4b*ÔµCèâÐÅŸ—Q~…Û:Ú^9" ¬10Õ··u;ÅÈh0ðê–fÙhmþXë·uÏ š¯"íþÓ|®X¶Ýõ™¤ÿõêÖ¿!s›t,}¬tLê00ío`“Mý«ÍÖ7¤;üÕ‹Ë*Íù#Y;Œ¤_ú<‘þº4§N—0£¥-?¿ÈKsêšLNŠ¥oì¡+_w•-ÁÕ€Ø,Ä[Ei‰|ž–À,±˜óZ°®@Ö'§æK©Xtãà¥@F'÷ß_§¬OL¼-­ôa ,‘XŽ"7Ù¨YÇÝéŒÞ…Î!›6áÜÚ;5`àñjŸ"E ‹1Öb ŠÕZ`AÚ;F ‚žXINaÄ\vš²YÖdr£×•°I„ð§š‘âÂèa}U"v°ðUò˜ÿ÷01„+ üDô\М¯½-ß=KÒ¯«¹ùHë˜èðB=Ó» Å­S=óˆÍœ úöÖ™9¿âb*ü K8¤õ1N0·Ù!æ¿Pss`å ÑTF!mœn©ÊB Hžó\ÝÂÌI-øúºÛµK¢{iµ”뎘F²éi9/¹¥êõUZ³¨]šÔê…·€Ç!1°F4¤ð-¤’Ë2À‹>‹Ê%àÈÏCì«ìž¡«%ñ5ÛA{tîÓ~}Ý3øÖ’…+ŠâÖ'¿¾uëo},sñÔïo(s ì™á¶>à]OäuËîæÌEècNO¹uï…Òn¿3o=\±S›ZÏÇ~ÝÔp²ÜK¸¢;ÌíŠOÄÔ Ü¡xÖBÉâŠuf'(€~Ï ™kŸ¯‹á37~Bm‡þ°A@«BQ9ŽHÛa^ömE 2‡õ%ˆšÊR@»µ{'æq„¹ÂúDMS^ zS»– TPËÁ©¬ß1B*»Â¼ÿ/íaéå>¯i°|"Oþ_ó>ÙõÀÀsÒ˜´0ZÞµƒ^íºí*ߺԅ‰üÿ1ÿÒǾ¨á˜ `!,¢ßkF#¸0v¦Ë~Ç,9tK÷–sm¹²ÄºY!6W¥Z¢Ö~][> `KnüdgVˆaà%^u&¿ýÅêCTIÿ8G“« õ[ýÿs47àÏs4ë2aàÏs4ûùëÂWú>õ2·®œz‘0ÀŸJ'Í%üü D 0ðÇ9š•ÃÔ˜£ñ&2ÏÑäÿŸ9š¥xšÿ›£¹!œ£‘ÓtÈ ùï,i?†'÷çƒÊ߉ÿ@N2̨Èe—˸K¼†|`ª…|`#ìºNsþAR´…ÒK ¶ÃÀB= wÅÁ)Ö+¹c`…ý‘ý­¼Ã $ì5–Tü•x%óküQ3Ï ÏÀ‹ÁÖdw>VÕ}&üàY H‡ OÃ]»ÒÞa*~ãçÌ_Jw“A[üBS/0ߪ´öÖž7cà«ÂSûp#­›ŠûrÖs@šyé©Ä¢à3l+[X ÓÊßrkþ-rœ%ï·/mÆßXkF”bÕX]o;VËâgÁ(݈9wí×·Á»€Â;ùÈ1 Þ žÓ¶´~ðéžëô^…8-ô×m")nz`×âØ€_4=p!Ü1 Ä/˜üüÛö¦ÅÇȤXð·ÎCK$šÇŒ:R!µ¨5Õ44æÈ"CÌá|`þlò,¿îWñºayšfî&³ÜLW%08"½Yú^š¾;0°*¬@¶½~ߘÌö @ôºýÓ¤‹îíom öbáäŽVÀ¿›ÅÀD¦Nœ´çfÖc_?‹ïd'7ï·ûH`ूÃá|àvðÛ‚Oýº pYo½çÖö+[IDô!_@.>aº@ž®MŠ<Óù)ÊÚù(ì?M‹$Þõ,ÕOHçßy|þñcó„S ëËÕGË®W-Q,;Ê9ÇìRøÜ¼U[Ôb3ÿ}}W•™­¤[æ?ËŪCaàé1Ñszãw˜ÿ„\qÅ*“‚74sëú(U ω >Onè8mc‚Æ…?’×òý­8J’³–¤ˆ´ºÁÀŒW}שMº\!×=Í÷cÆÉúý>|#Eª>É5ÄYN(ƒÕ%£•ëáÞkhÈtЃ©ß7½­ h÷ýð‘%0ÂTmò˜Ú†ÌÍáuXe` à¡áM´·A%ðyŠjœ ¥ÍAIã#>cà)ÏNN÷–:Ræø€gI‰°4i™h48Y%déøyq¶ÄfãP¹Þ}„Ü«zÏøu#gli %.³PÏ’Rª=ACc»ä ìÉh%żj?ÈÑ[Õ6òjV “‘‰{˜þúÌÂ,QF>´Œ<·<å4´£²ºX¬r¡hŠy­i?L|^ÝEmd`“~·öKø¥-JJ€LÖTô*ÎÂï¶wBfyöÐéLzÝlònŒc©L5- 9‚¨w<»ŽÉ)2MÞ’§™2ò…Šd,Í ®f즽xëPR:;™ãÀð° Úw–ëùÀ™„äõ{wÑZÇüJ-Ruÿü&§ˆC»ŒÂG¶Í\|œ—ŒV²m1)6!¶‰U{F>±8BòÐé±td\DùŽ ¤…¤‚×0ÿ}¶Dðâ½_%¥K=vò¡ÉÈÕ0+Ÿe´þޏFT2µOFž2ZÑ&$CiT’¾xG×…d- ºŒjØy3”;³zCH÷’ΛžO”ÈüAš!öüɨÍ(šÉnÅŽK¤O@M?͸÷›º©ø’«kŠ>Ù¤xwé¿É#]ù,­—<­×ᲇð^Ý´ƒN~*Tೕ 8“zW=p#ª#vÂÀËÓbÙû÷á ò–¸q->K Äö#ëBÙëïó{ic8›“)ïÕÅ’WÒ6«à“ú⊈Ê}Ò?ŒpÖ5ÇÀ/œ-€†¬EŠ0)•CöwÄ¿—²Б)Æ]ÙMJR,ÏÅâKbMª˜ŒûÞïëyTUßX|¡YN :t6šÈ«ëðâµ›"f9n[¬ Á¦Ä㯹“få5Ÿ¥AHÌÛÁ ù«YŸiHš? –7’MASF~dw‡¦‘€ÐÆiã¸Û—âkƒö©À.Ib6pŸÆµÝ6ȶgäWn´JG¿€í÷}'¶@¾¾„€Ü{=÷cñ­¿a¤úJôZ~BuQKâ"»íí¸ ûQ ?/ ³µÜ[•ÆŽ¤)ïþ‰bržÚR| Iê\®g:z“ôÊÅϨÑÞ©â3‚ÎÝ_¿‡»ƒÎ]j]y¯ŠkBÅ$’^Ôz´K7›\‹zÿºêe¡pÍ%PLfÎÇ™µøº•¿ kçíó*v.9O=£·I³½zàš^°. ¾£XîÌïõãHGg=õuû÷#¤Þô~8 |ü1³2Í‹:3+Ç7½$ðñ‡•&£.€©‘㯿ÀÑ Oydœ&öÀÀêÏr¥2È•f`…Ü_QH¨ÊÌF¨žv³ÊÀç .öǼ z“œÁË~\'É¿GÎï¦wr˜v•³ÚºHsÆÔAô€ÛÃH> ´Oõ㣜=lsÏ{{x¿›Oš=xŸ=Œ õM¨•óx•ÿ#QJ¸·¿âL §9Yýø¸•ÿc†>uhÆò”$XÿÉîô:iG ÄÓ2­Ï¶Î¡ÕŸ´Åo<Éšc;d\ÇmòG$»¿”8-¶˜Õá!wç‹[¿PûH\oÑmK/øl6è6Ï þ–Û€˜ØQßÞÇ£ª5ò½h—Q‡aÕ4e‡úñy›øÎTžùÝL>nKžÄÂ’Ï[qŪxœØg2ä|$w›[ªÒJ’^®ŠqW\±FÔf]bºð~C§a68Mî€iˆS´¥m^ò¯;¥1¨±£µíBÒø(ü†4×±¨}ÞN ¬®ÍÀ@«¥=Ì¢ÍðUèÉÄS>æ}zêö­XZˆët"ÊÛä}ØE‘¡ÅÀ‹ “Ølþ7†j¸`êŸû…}ýÞ4²÷i/n¦D~7 ÝÖUløÂ1AúÌp%{¯¦bÁßp{}:”ĨG6ò&ÝWI&ÇZhÍ”÷ÑQ· ¬Ï‰ŒÇëV®Ï9ÆÞŒaÜ| žV%t…¤t §i ‡;Å«(¡¦ ½pØlÝ®ü7q¶<^¥§F$v·uèvGLÎÍWoß(€óxàûлÂòTïwÙ;(%ÊmåC³ ÅÀ&“K¹¸yjÚ½_4Ö°BÊ\Þ“k³PIt~ðù3Idö?ª²&Ñ´G+5ïþ$ÞÍÀ0ð£HcÄ3Ûû ŠÃ$~bë ˜3¬;ú†tx™q–[«÷͘½é÷l|ªw4B~é …[“Ýì¤ÍÇêï…_0F­o[ÕûH¾Š Õ.~ý Ö§ËQK;£ÀÀª 䔿DdH–æ¤wõ(æ 0‹üú¦çðyQIí _Ô ó¯¬KóV™f¦¨1ð‹N Pòœì´vB¬ø‰>q‘F˜{qŒþlØrI¢z ½à]Ãtk™om‰(€¯+‹œ$e”õb·¿H‘Sm'õj‡j™vFÖ¥@âdL® XÊ"g ÓýÉËN/'úãûÏ;Q¦ÅnmfooÀåaRGn§õº÷l#Ùa¨®Lj¨ºêi¡1CuÎÑ⊟Žh àWfo™x8ýo$Ž5¹\^U¥B5Ítïc£Û}õNS,øÛ¥_H¡N&×eš™Øs¡zÞ’Üg,àW`¾Æ¼ëª.)7YfäØdÛZníiªJÆszsÍ«ÿ(Øly6~·¦Ïظ™ í°Î$“Uðq£ $luf É~–,Hmz‘Ý"÷½“ø(©ùâ,÷ƒ4L ¼•çR‘ ³6´Ïèëî˜Bõc›ü¹ºÄ$>0aIraI?¹1çy«¯Û±Ä³…f[³ÓέŸXí9q¿µC×îÖе¸â™ ¤>d¿ŠI¶Ù¿®p”Å Ý]öw§DÏ1ðì73¡©°Ûz݇ٹÎb`uŽ~&z`Òºuµ´£rÄÀgŽ$£TH‡ô²±d›Šßx= Í ½J·í4)üTõóò,@¼]&®¶vw¹9€ìàJbrEÈ<óÑ0Þ© ƒ¸;§ù_˜C¥çÛõ0@| 9I:R½ïºÖPÂvÝôª…1ë 0`b:”åLìêm”¦}¢ô€¹ÙKéFÌ=éñ©‡¢6ŒI‰ÞQ0ÓÑ|r>ß‹@)‘§§ÖëNµ+Y;ø(.%èö±hRÂÃ,=›ØÁó¾ÆJЗ¨% È(j è2ÔX :u‰‹‰m£ h×ÏmÐ9Ý6Më˜c|ÁÀ o…ì¬B ¾‚týD•¸,ÓÍSõuœ¼?ErÁáy¡÷'ÌG¦ôÂ8yç™Û<(_?«bü"J pИèüá1æ/)AÃø9$§$§‡ »-~}lͦZÕ ÇÀ4~ñÏ¿Iq E}ÜXëCI`<È þ†-@ê õËÓôZs ÎȤàú“­cŒvýÔÍ1•/ñ!9­9è*Ö—²µßˆ¿-ù0M~ͽß)1µ»G¢˜ Xaåš³—²5Ø©<è³Oƨ^öcqëçõ4Eú¡×K—k'Ïg9.Ʋ¦®s&vJˆžõ·ÛTìVZ©fŸ—ÓN}”Óg>0Ôw|(Ér_H'ŽõTO5lßc4'‘ä°wÇ7©Õ*Ôî›C‘æXæX]:@…ÖÍ¥G«¤Îû«¤¾³xá^Z ļÛpE½QrEsÃð¥M ¯0/\Žf÷»,×wNmâÀ…ú+6áÍÌaˆ}î:…5"M‰Lì„ú(ÈJ}Ó&¾€ÇNŒëÃ"žÑÌpÀ;_Ôéüº¸P9Ìß*IÆV0šs ϯ‚(ä&ôºçFòç"ŠK|ÚÀÃê_Šõ¿pR¼@^C",§V]G³Bœ†üUN“À.{ |\Ì’¥*æÖ;ªæUå4úîw Vî|ž´€Éó÷öûÅMÖXf1°¾ûÔ¬÷ï/ðsö;~ õ‘‰²Çøc‰ƒ8Ч¾(¾Ò‹jÆÈ ùH­­¾Ä›‚@p}‰7GW¥9¦½ã5Hadv"/ñæ€9ß~‰7ß—ÇÿMÖÒÜætŠ7Ÿì^àòuÞítdñ0xyÀ‡´Ö?L/¸)æŒbSãu2S½GoÎÀ7^ãŠ)—ØSäl(œÖH¤„ ¡äL”w7sØ%Ò £~TkŒÛØÐšìø<¥ÀÒ5¡sTjoM' ¬‹’I¢$Y&¹­­~|›;Ë,ë«n‡y,–ŽE¼õªtgé4°ü «²Jßæx3p¢Û XŸúx1Ö§7Í:P3r‹¸‘j0ݲ0M½ Dê Ú2~<ìÜöÿveK’›L÷•¦«ºTU—sÿMļZ6´AÌÓÿ,™R¢îöo{¾8– Ä’ë9ÖRà'ÍûCSýPöý6˜ZPàƒö¿Cï©L»ok æ¬. ó]Xï亘2Ãù‘߆X`ÍXd!hü®®–ã¾#h<2Ý¡pbb;y……_™îÐï¿ç‰’C®²e“Ìž˜Ui¥S|šl+*ÖKEŸd0IVVÕ´zO[€^̓ê!ÉèKn›p‚aí‘÷°”(ÊÅíj?êò¨îöÅßèãQ–‚_Tš$Y]e¹®¢w¼iˆîÐŽ¶Ô23^E]ÜlÂeUêZ˜ ×v#RÝ¡0Eå&ÅÖø+,CÞ¾æ•TËkÀî"Aß»¦¡Àë£8¨jd+įŒi!5k¼“4n_rÒd`Yj,-}|!‘H9#Të²xû*×¥B6ÔùI×xÿêšÌ#ý¿²W’úè:­ÝE)¦¶U(˜G"xtø—à/L¶Ç:‚âW«„Uñ‚UN5õÞl{öDÒ ]CÀ])'ºi¬Ê H¶Ía%©Ò_Úó¬ ’âÆ&QÊui”¬ Ǭ`ñåNjE`b­†}Á¼Eñq±hDV»Žm{©K³Qàý l%{IŸ§gN©ÚðÀÁºªÅo}Š2í63tC-Zß·è=ˆ(S߯ uýf.[c(ðùXy;aïÖÕ9 <ÌÒæÐ¬òû*Í( ài«æ´ˆ×zš·yËsš¥5Gu[·û¿¼×‰>~ñ‘§v« ÉÅ8•g ‹[V;ãÎ2ñÜ)W×C÷°¸]ä„¢ðXœLéç²Ú¶Žï´¯†ÉÉ›S…­RD:êߟèQÁΖ‹äeã™=‘òH&¾ñv5½5²µ®Èûµ Ö=Ðß ëXK ¼Î\¬îØMÚmý@÷ƒMznÃÁç¶iž%6#1ª…9Kë”¶nVzñÓ<ò¨ü¡ƒ57FØÎO%œãÅ¥l † ÀÉTØ.D„ž X’ÚÁŽþ¤â#“xÏ{—¡ZÔ˼µøêgæ“„rçZnÞ¸X{ Ìj°›”5åÜ6µUÆQà÷·ûn›JCŸôO¦37V´ýo_’Õ¢u¹kïÝá—y’›šsSÝ®2µTÃ0ƒÌŸ¤ŸêÛ ;š |Ô5h…\ÙäªyFàYð DN ‚¦¸©–ÝlÞÎhš€^¯ÎŒÆ;% ÈC=Nm³/À% Þ0•XÅÈrÌÝvU§ÖEc2èù™å)Pwª¹ϰ[ŠùºÑ;oH¬qj›e·ÿÚ¬‘³ªg4Qm³SŽ'ÑÒ.|á†TˆCÛŒÄçâ‡A;£+‰7#Ñ6»|ÑW ´´|äÔ5‰´+Rü–•´nqõäé÷“œÉ«òö ”O¢ ¤]y×fóûF¯ðžË+#‘€7ö˜=ŸßäD¹™sàO¯æþÕðho€2<¨×3óh'ü„¯‹@í‘T[ö]4«Å¼Íóu1(‘iŠ÷š¯]çí&^õ8Ü3«?wÔ\ÁïS­‘†a1“êMƒ]N¯_Ùža©»,RN,Ý¢%†bˆnÏAz d8$Ù*Í6™¾¨bûß(~d('ãVœ9ý÷'1C§–—À ­:… ¯¨|Šrz÷ÌŠvYy?¯šLG¨Hîb-7¬¥¬¸Iùb—&üÕŒ ÖQVÜX]‹dðÍv®:Ý8Ì#¾/¢C5V¢xàÜY=,H^ÁonK?ò¾Äø<årM@Á(˜3e½š4ÿsˆIÎlŸº•ÍX>A¹\ÿ&Áí¤ë536wþÏO†£Û7ðaÔb[·ìÕO욎÷+t¥,c?„þS <]ñÔ3"Æ•ÎÍ¢Äéyg‰Ç(€º(/<2âU rª@- Uxx?ç²vÞ¢qc=ñhÐ`Ü®N—ÖmãDÆ Y2ðÙ=°’LbT™¯& h›"ÃMï3¤œ¯H•¬]¹0nóQ¿h"ä´(Ÿ>Ä+Êó¥.Y™#ïyålÊŸŒµ­Mä'ˆü$éØŽõ,¤–¡Ÿ$C>²lšÍ†­½¿ëd™!I;ë!|)‡Ò_ÉÓ˜¿ýIú› _ÁªUØÝD]†|!©;Vp=W¥hzÜ‚ˆ<™c®.¶Ϫµ­™Êleí¨d9 ûì:n2{ûíðË:ÈCCÒ*êµ[²ÝrÁÂ8Ÿ-«˜êºvËwÚý»Êaï[iÖOÙz¿}¢NoŒ ¤BßY–¡4¥Éü Ô4£v”à‰_ƒ‡+°_l>¢tº&+ùWÞÍal]ÛjÍgÒŽ D_sbKSºC "Oí¨»&¸ÞõÊÌÎsäû§P‡P‹ä)¦†S85‰áT\¸²O{H9;{§pV#þêp pXfëoC˳P‡hŽP‡>BůۗPGâΈ¡}„:øs¨CÎÙ«¹¶bÒ[ž™ö·8H"¼P¾—>÷ Ì*6؉IHT# m¨óîÐv½=Þs6ø4k•ówæóê™9hÃÛÍ1Ÿ×ä9ˆW6Ž}Õ2›ï¹BZÎ8²Ív•š?IÅDóKc‚\¥+->¢Ìüß(3/ÓzÜGÆýWtf À°mþîᦈ§uº)تVS|Ò2È6¦¡”[›F‡ |‘ÛÄÄü wJ¹žOø¦ö9è®,þðWÚ„£~\²ìg—S½ Ç.§âWñC—S—w9ð›.§­®T·í5o(𿺜f ü.§9{bV£Ñ¦‰lJÉ«ªlñ~zæÊ9—v¨Û¡ Ê~ý/΃Þç7xÿÚÕåíPÅÉ~íP<Uù–þ‘ƒÉ~ãã¢w;ˆ\ì…Óóº(kó&¥Ê"°–M¤…IÆ·µM9[×Y]Sàý”Ká¯ÈÒg¶z—ÛBçesˆz+ÝÕû^!—@q²@û=ó'ì`2™J¶‹ÎMÍ@Å@çÙ`žg¸Z¦ËË{vF ;3^Q`Ú3á[s”ð{FŒþ()ð}²65rÌÌSÝê¹Åeö¾x ˜X¼›!§}ç5žÌÎG=κôš{ƒJ^‹‹\ëÑ’Õ¶A¥TA)tÿ^I*³ÑRV‹á=¿ðØB­‹l0lYpáÖÙ¤ô‚%Ør -ã@ªE6|¦îw›ýÆ×W7…np/ÜîÙ!¹h€¡Wz´ÛŠ¿ñóbK%m’´ôHÞU.çÚ›¹eÍJ <;¢““¾£7 ˱9>ÏflŽé‰L+k›•_„ϹŠDÿâ}Ÿäú}4ר=´—ÝÎÝn§ì‰PvÖ=¶±'šr(·l4¨lõ ÒÖÿGØ•%9ª+Ñ-¹lŒ©Ï^@Gô]‚’˜£ˆ»ú§)E¦]}ßOE}œFhÈñмcyÏ€,e)xÉä@¦2AÜú»^ðãd»ýÞœ"¯»îbXWÊžÒŽÁŽ ŸXÉkò6U£ÔrC”&dŽ=–¨ŸÔÈV {®Íã]%:m‰öfôªÇ‹ô5pûwœ±tœ/!¦óxoV{fû±Sâ1ð¿H¢a7~ÿ?’èÿ‹$ºÅÀÔÃâõ“B[WÝŒk¤ÉÏ3J€µOÕ‹a'ÐÑ䘈+¸,‘s¶=O3žÝÛyóìFKÃØ»Z[OI‰ *2z\’µ®M˶)–âäÙ§ W0Ôô¼»¼W­ ðZ°¢‰h—»õùnÚì ‚ —[>öŒ®Vyè(¨ Èç'ÒžéJ¸‹œ¬ø(7óײŒ<-óf­œyR9:|Å… a#pݬs¹;Á¹Ž>½H\š)ò7¨~Ø¥Ó!œ”¿>[¿ð^é‘ÌüÃç2œÝŠþ½IÍWçnM[‚üAÝ0†¬æðFD_çè;KrÐx§§¦obð§f#Ò:~ÐÜšö0ìÙÀÝšm8à3)¥‰ÁÙ¯L·=a`Nõø‚æy£¹S,#Î3ª½ÅKÈ=Ú¿åÁÆ©k0°À•U©¬R‡ì%™žïO ëû¶@ÉÈ£Áü‰¾2U±–CybüC¢—°€» -`Äø ![(w¦Ä¸\›ioýûe"MÍîH*VÁ:‚ÌR€~èd?cÏ$A&~×1âᓞœ¶ö•‰YÒÞúiós¯Ò~`ÄÀš­ ­éD[SiS–‘$Z_fš@7/džŽL¨˜DÚšqÜÔÂ舀v0ëâ*HK!Øüˆz;s¥ª¹){H^†ïÀvmçSŠs¼¸ÌEÔ ×»1¦ŽcÁÀׄè>ß×jµ'kG€ÅиöÚu ¿ádãJuõ®ÖEÔc$„ ¿¡3P†8—ô'Â8B+"¿<2hȳC©u©íÙ2ä"ƒÈª^ºE´²'H*¢³‹mÛ‹u`û<‰IÏJxs ­˜dÅ2”]ŒPž­œÛ\® eÞ€Ó¼²3\HòÝXvuÍX¸âºQX3 Œ5ÞꣳöÉŒ/HûЊë…ñ©"#è­SÈÐÑœtb‡ßxE ̯_Pèzì¹0là¢ï0ð%]dDÇD׉žË0#•1^Þº2B/å¸!^¤×3áz¿£,ÅVÚ¿P€•á ¨ã± ³2RoÊÞc->Ê5í²;D’!Iõ׊Š1É™i10Òu{ ‚Øû8Z¯ã’M+^ΖOӆꋙ™A‰Ø˜g™V¥òkzsq†c`ЍrÇÝèQ.ÆÚÊcI^&¿Dl,dÂo`+^‘{Ǹ,Ë•UäG† Ô ›pà hNv«T)tŸ]ªð©8ÆîOµ5BÎÉÄ(°‚دشãû×s¶îÿÙÁ›“âÊO „ž··Å[Eÿ¤®÷Z4ÂÌñˆÆŒ1¥ÛDmе›÷³Š=MùÅ™Úû∫YÖ³Ÿ"ÛbþüzK—‚c&ì’tñœHò–?ßéb›}Ýo‹n'½ƒ_öÁß-_jXFÕª¶1ðòªá#Ö}¿måY*&1ðJCuœ£s8W­8”C?滑ÏYñ¡k¯!f•×ç;˵€2tÃ÷r·wÓ‰÷ËwƒƒJϽ]ÇZCFçIY®Ë¤7è€Ú5°L˜%ÎÊ×”úy/\ÛE‹Ï¤¿YAFgóöÅVµ#æhzbdZËaß–u‰ìŸnj(•l®÷mÜÈËБ¾@ŵTNKu'OÄrÄ·eúbZœbã-1š —]ãZ¥'ec‹"oMo†Àæ>&év›ÈëD“!˜!‘Öš!ܬ¢«Èœ=PŒD.ªmµ¹šÄq0U(ПûÏh†²Îj¹6xÇÛ!ÒŸ›£çÊTø@¤lM šíDZ_N>ŽâzÖ¤õ=‡E‹¹™0ðID~£ÆÐØØ!ÍN}‘`9¶,ÿ¹åÆ»q¨?}fHþÉ·•#-qÁÙ)uäF`ñ¾&í<Ú·š{݃ý¼ê¡'~(}u?Òî.±Œ¬Ÿz2á7ìd„מ&ÖŸŽIžüHhÔ¾–o–ï Æf'ÈûÛ²¬ã²ltjkz^¶d8õ¥Š±Em”=ÿJYÒ…‘]4…"æ€ûþl; Ä^#ò ¹9—)Š\ûÖ)hÍaÄA9Az_Õ"ÍÂStÌW*ª-E¬¨«ªÃºîSä•NRÚízÛ:¤¤æ‡õZ¡"Rgz#ƒ`wŠÀ;–©Ž2¥ge†VëF†,ß?Š Ë´`†tÖct[™Ù„ž¢XCލinØbà40Ë$Ôl÷Ä8²±r-øø p6oÀìjâ¯RÅ!Û¬Û¦¶ŸžÝ0'ÀXgɆ^nD¸žWžêÏ¿!ýÚÔ[ë«5¢ëeƒÅ'³èy.Ó85z‚y|}Rú3Õe£% j‰¼ÙÛ]²·1ñêÏöö‚ÿeow˜$Ž˜¨Ê(­°˜ŠÍl†4Þ'Ÿªå<ŽKc”¦Ù4RN«pœóÚþËxT•ÏßøTƒØO ´‘áz …­ˆOõwðÿ¢~ëØñºt ‡9âSMâ!Q|Ón…ÍÕc`~Õ«ÊİÂÕ,Æ]‘ßøÂÖR̺¯ÍföšéxNb†Ö“D‘v'Ç, ?&‰ÎJÕ§1(I„X@GéCó|ûYCyâì ›ÐŠâ‰Îöö x–tàZ3m5¤RYÄÙy±—øÝ%»úd]9Gg6§¤1¯âÚ<új5ÕºÃæÊŸJþÔ«P ë>jþ¤)Æ4=JwÊZ ët™E…z6hi·õŒé«ñ¿Qîj«—¾Ë8§ô ©¯»¶æÛ¡Ïôežo¥‰>dâœÙúØ–ãè!ã•?iŽÔ‘9s¾ÍçV“—)P2=Fvì£å¡Ž]×ø“é*&‰:6)9ŒLøí’<Ž樹õdÏ÷Oó…õbB§œDÉÖy&ôuG}‘™Œ×Œ«¥ïôAdFdž+WA¹nz„ڈ̮öL ó’»uøÁì† Ÿ)³+ ‰\qÖ¬+ù>Á!–­ÌTiÕ%“%"_IT]ÂÌó~ã¬çlY$, Ñ*ͧúh¤8É'úúN<“!–¨œÙ;±µ4+´úƵ~Ãl͵ï|°‹²kÌfàŽÈ¯«AÇ옆mã §Kî~§ÍœA>¶;¦ña’<§=q,PÚŠZ&[e‡wÌ<èÑ,°góh½K Ä>hœ"7­ü°£J Lµk¾1ÍÓ®ƒÍ©õ¥z×®btÒ»–±ªÆÀiñ#ƾöe´‹¯3^}Ø)£Þ=—•µZ8[b,p’Góü&’LuzuÔ#"ŠÚRD P5íÝ0‹¤È/ÔÙ;I5¯Ò|¯G‚¼cd(ÆuÈ]s¡É ][’5:ì;‹ì5™ô¯ìBªØk‘®ÝäH!.[ù´·~£• “ŒÍr'Èüêì–1âjOtf‡Ô@ࣲã—„\­éÒ2Þ*E‘Eb‡K•¤•Ü¥<Ú£$+8lÉØƒ•.—%ê'3¶¤ù'Ü‘1epôš¯ŒkAHТÒ]7tšwê€1_´tE@–¦ë:c=B>Έ8'e0Åë½T§fû,0ð5l\@d´nºë{e3¬Ô$öÅÁ]˜>?Àœy5SC5iâ‚FtnÛ~k•Ð’Wä7¾.ñÃ$³ŒÇ TýÉ :R])šÏí54‡Ü¶†<úûSÈ­¥BnùÅ û7!7ƒ!†üç·gÐ •OÎ*‘¦’u÷^}$ã‘n¯Ý¾Ÿí ¼bàô¼„/SZ?}«A5'\²»ãFV·ÍªÓ,4§=ËódímÁ¯Û[ß+&&Á"mþ¢qO_FPà®ôV®‘Ä. ÿYí—O?ïªëš™àmÄxÙ·ÝÜ´ã0B¡Çëë³MÄošÎz´írL-ŒH{‡H]›—£^Ìwk¢–}(•\—ó`z…’SÌwß:v¨Øiã f—á$¢LÙi­ßa‘|~Äwë[Ec/dÝÌÖFž¹fä7æ”øßŸiõÀ*{ZAÐþõÞ *nõº¬ËÎ* ʸØiñSÙ­+ M}b¯Ç›F‘¾ÛÓÚ]i3"fäŸã¹¸©Ÿ‰uÚ÷хƼzj9+¡ã• \?€÷Ÿ€C7È’Ã.|e„¦Ñk=ÅÇÝzÔµ‚²üWFÅßS®Ÿ'³­&g½2’ɹŒÏI­Êà ° Ÿï"± ÑÒÞv‘&üIúr. <Ô² H9¿žD¾åb¡ßšE)§fDa+ØB;—­[!ŸúÊ߸; žÖA×¢ì5ÞIþ*„–JÓ*¾­iá"ƒî6¸Û»¡ÁÀŒêª×áÑÜ>{nWNšc\Ac°Óú}Ú¶uœ<:ÇÚ ÒWï;âædrƒÕƒÙ@)°ž|aƒÁÀ;šÇ˜ô廨X+ÏF,Ȉ¥ õ†coì;·±Y0ðNnUôãÒWóØCræUy,}i_èG–ÇP'-‘Ì’(”/hô+·á꫇“÷þú'òl:1Z£A³Vqûè˜}4eoëù‚ÿ˜@YìÂí>;Òbæaq{«›}4tð!–ßDÔóûªo—yš+ Lfÿè@ b¯Ö¹í1H{ @ÍÍ£¿ô! X¡¸Óûº”±KÝÞ3Ó"æi1ð~É‹W‘¦õ¬—®T§ |£š;ì%;ì× g00™\¢¬âoìN{o#ç%>¯:5h=­í6ªª‚^¶âNH¹ƒ’kL=hÆ”ä7“Ë^UÌ*ºÞ˜vW›ª¦‹÷þø˜°!ü…¹f ÷uAlË '&|é—ab ÀN:Ê}’}Ú˜£5æ$D‚ü;$›cÆÎ]Ãl°k„cà*-CVÚ/´¹•f’ÔºWj/}ë ýã¾uo¿5¢ªD‘ªg8Wš™Ó``¼rèP¸ý.›ØHæñ)ÕaõôÖÜêM¹•ŠLø ¯Šèñî\O=›à(Rj璘Í7ÕOy)ÈEF_ugÍvVåGñ¦í—ôÔ´¬zÐíB€wB#WCì m˜N‡EF»–ˆžVµfC딈1ðRðqDO.ÃêI1Í K¤Èˆ&]±N#–D– œ°óU¨‰Ô¹Ö^õˆQ”NDÃY6ösÖ90°ÀÀÚÇý ++{úôß*ÑŸ‹jιÚb«˜è~ÝpºB&7m۷䵿¾HbÚéö5rTŒm£Éë\štÜëÆ„b÷j9‡¥ƒx^‘½«Ö€ Â'aomÎ3ûDN“hJÍÙN' ¨éå’«’meE‘9h¼\F¬+•ú°[ _àÐE±)×ÐOv—õýH¾ üþן©ã¦®çóœkˆüŸ]A©^mɬœš±*+ ƒ×ÿQY‘Ð’ÿ¤²2ÿCe¥%ÀËürÞ}4ý´I0µ1-ù*+šs`üÙÇ&e™‚P¢%ÿcþÄ”KpʹšÇ-…á-ù¯e†Ê¥“3³/%”¼ fð«ÖÚ‹m·å°èn;j ¼ÉÒÐmÈF¶Ýž.ù‚Ò»;©øhWƒq´é-ˆßà˜ASq˜ÒKjÓ/ ÂÉâG …]nĪÛÀo( ÚNWUÁ¨jTՕúu@ÞR”Å òýÚ·6KÃΦ/7 ,ËÄÊñàŒ“G_+|›y¶¶ö¼”PQ  0ß§Qݦ{öÎT™,Tæ+x¼—tëÌdý‹j‚ŠÝ9±„§‰»Á~vn¿¢$ÈÇŽ±Ås­ÊFõ*è˜î”·hiÊeŸ&Þ’ï¡«§Â¯!‹dår‚ s¨Û,)¨Ù÷ýØ»„É'ÿz]^<„ÈJGgذXs"²€@Tm÷õlYÍv¼½Ñ7RaŒ uffqú Yë7 rŠy1_1ÁúÃñ‰s‚D‘¥ áà]~ÓžÖV…߉|gŠU`Š9 jˆ©¾o„•†Vp÷¨‚ûûFËÈ—*ìYíŽàx¼\üÇ´cÖ®kh½˜õ#'Vû7Ǻ³®jwÅ)"ÌGLçNÏS;Lf*ÀD˜m¶ ØÃX«×_aþႃÑ"ñ)ô™ ®¾ÂÀ;ŠtÆPÞ9éµU³àÙvÑ5°9Ûõ…ÛóD˜L;ßÙ„}L¿Øm±BK!Ìÿ„~—éI³n™ïçg#aØd%L¯ÓB€w${¸k^nÀkøý–õ‰å9Úì{Ø·[ SÇÿÌsïELËþc± l°oÊHEÅZvJ°‘¿‹‹mÜVÅ6†P-ë+‚âoTºmÕ !QL¢õÉ[’£=Zaz>µt?¹³ŽØ0 Áð}ݨƒî©dý•cÚ͘ƒm±‡ãu{{¦~O“Ö–ó8ž1YøB„ÕMšŸÇ“Ûk¬Që‰ñ"h²·˜ó_T¬YxaÂêPÞį½n_ÿósÀd}]$¶?ÄüzYò˜¥|ݾÞrŠé X;ÅŽ^ Þß)>£:¯cÙ­ËT{ûº=þR{»ÑÚÛ×íñ·ÚÛ†ÔÞ¾0A,©½Ýhímâ0œf}]];>±˜e¸=plå^’Gç?VóV¨š7_ô­Ý­£núá|]ÙΤ<²|¥®…â«Ë¹Ÿ_šyï€ÙÁÆš§?ÞÒõU©»Õ!(Œ±3Ó‘óÑÀKÛÈÅ„ÇÀä›'‡¨ò. ±RZŸea âþ³Ü\o͈qÕHÎ5 )pžƒNw¬~A9ô9ÍÐ"•ótE)è ˆsm‡«UÀ+Ô‹U~ÁÍôøD9S&N†R‹Œ«oFð2:Ƹõ«49ãÝ`Ø5ùe%KgÕ>–=æQûˆÎÎm×cà#xݽñÁ{nÿ¬ÿ|ØEKëx5.>¿ézy`à#xJç]éÓ¾Ær®‰S/A^cßkšœ…|ºµµ›ãä4‚ÏÀ¥,MJTá7n[›­52ɤÁ!¯Ƭß¾[ËǤ‰žÖò0àNš˜`§Â:?ÖѸ¬9 ÈÛozÆö½§ = ±¹³JÕçv¹“ ¢@>P¥#/iš jä¼XXu>'FöRƒÒvoEßÍ»ˆ;'¥ãý1ƒ””ÙλÛ;Å€“¥þØ×¥þM |~ÈïÇ ‘rËÄ<( ¬~O5¥>¦Úû× J§¼ŒmÎõh½ &Gïh^ 3Œhd+yfOw“l;>·sqóÛ_äŒ4Ðè[ßþáOZ0šsÁØl×bàk+§LÚ+©k†,œ¸E*e€m ß+9ˆ^aàóØÀÊ2 ËŽIž?Jc¦°&Di+9ÜÞ´5’ú-ÎtõÀ¥Þ¯N[¹ù¶J³íSnÙËÀ‚Hä*ív|ŸÀ芲“1e0Y&7µ™×TßîeE"éÅoÛçÇãpœÃó(¥0NfpÓÌá$|ËŒ5R² qZÔÂG9í¹£±FJ¶`—»ÜH×*ášLs®o¥ i26Y7õÑÓ9ŽÏ_&i’N)Óh Þ×·gA!Î!Z’ÔfeC.äÕ·ê#òRY|ŸŒRŽÙ«¬¾UŸ*ˆm*Iø‰«ÝÌ-…+¾¾Êª…MV¨™1š; k¤éšä}’ºzãóçÎìýD3ñ OAvjŒö#Q†íÃ:c *%—¤0{†oŽFê[©Âž%nâþÞŒþ¿t†Iñ©pžWñÖ‡Ëì¸S0<)Ëpþ7.j·~–À;‚Øæ¢;¬²>¾݆`àóŒ7…I«¹;öÞ*9gza"ùÎÌ| á8Ýt:OÀûï.¼T pnt„ø?#Þ r7êsÐ,»×Hw6tÁäJcîS\zÒæ£ã ,]…RÏî2)1¶ Öûû—Ü"/)œ—Š€÷âãbhn Ÿ¶¸]ÀËã÷.ox3°Ý lÁÀÇïƒ^­E£åÆá+Dâ¯à±…E±%y>"ñ×,ô«,ÙÁÀóÈ3v†¦·ÍÏY²‹|ŠQ#ñ×È N2¨„Øa·A„ŸNSL»B´¦Ù“1F|rè˜ÅÀæC§w=vƒOç6“ Iõ½úÒ{gø2‘.˜3Á€£%å¿G&½ä»H;`à—#Sêå;„ž(ææ—Åq̽‡ƒXgKÎ@åþ* ÃØIhl["‰ÄRüÆê+p3Öô™[—/(ºG×”¶+JgfƒX_%«¹ùÇ×fè¦Ü‹‘?è¨!·˜ù§ö«„î³Jl}/—½°š¥€ÏÛA÷mÉ-Íõ½þ=ŽpÅÝåý9Žua¼–&ö¬©IhÂÏè Ô‚•N61šFmcv ,Ç1~®áŠÃN—}ÁÀS"¦€O¨õèFåßk,PûopŸI»B°|ÔBÁWX^$OÌðu…ïZQÿ,ðq½¿ÛHN1ð OºwN¦Æ‡=œ`à)“© AK‡d¡ºøü™*CÉ,›>{N×HõÔáJ@Õ¾¢LjìëõÐ>$n1°¾J|*/aµ ÄrV ÏO¹i¦¾Õ°iÊ!K€eàûoÀih `>å³™ÈÆÿ“܉˜ñɈ!ÈŠéÐF(w^ /Õ¬ó(o4Á•OçgóÆ}îA [:{Å×¥@>O|¿Ó¾sÆí²*×ݨ¥Ýõûa,tšòõ‘ÇÆÌf—Š. ²ÓŒ¬¿"{E¡Šwžz#íç+ŠÎµºmô6F ò]8pÅ´aj§)8ÏSÌõKÝ•7"'"ÝÐòž‚ ‘êP›_§`“O2k$ÑkϽ;¬jY©änÍ<þI¶FaÅ󨡑ǶµL#êÇ­¤i§h X(iÖ¨™Ÿ»~`®oôbØä÷ÿ^ì,¡ï¸v¦LëÿG·¬ÈTcÕÜ­œ ­{%æ}_[ üx˜(!¤ÛUdÑð‘ŽC‚—œîFÏÓ!6ÙaàW¾Sø¥–½__Vxê秤£L½ÓjŽÖ‰w ,嘒Ç\Œ˜„eà™²DBžJÍ[h©–GþtUQ§f1£KþÁ›½$Y`µ.D`Ow‰˜qÆ÷Fs¸õ«Hý‚ÿN:ì\'æÖXÖ`àýä^ñÔÓ’€nîm_\ñqÉÊòÜ©²ub#½ü& ¼¦XêCPA­JŒ£õ17Vޘє‰"ûÞäUàQ–$“¬l$±Î=Q3ÙûïØ÷6‘ÓCǵšzBŠ+"ÅK(ƒLGCäºõ›ÁÀçU~–™rÊšI·$ìPxIÒÜ Ûî|êÕj$DUT’ Ag<‚Wð™mñ05ÒÉ,Íðλ%MqëŸOjZÔ¨±D²ÌÀ7:†N£Óª•L]Gœ™Šÿƒ[nR“"÷_ÁÖú-¨ø‘¨$ v¿-5ÒOIŸWíòêÖc© ¬Z¾ðÅXÕ‹b„2è¿Ym-ÎI5±ð¾›lGÈç…<»õK”î;¨¼gd…—Rç¾jɰCs ò…mÓ2ÉɪÙL äe5'´ƒ™v š˜UÈŸK à¤ðq?yG¢»òwÆ#øÿýSŠ \øpº+fæýO!CÕ$uk纞ŽÆóê?‰7—"7?Ž‹#û44lÅ@t>)ó)Xç–õ®Ï*5V¿ý'¹A§0Õk7œ+àeÓ©œ–ä¶n[–m§ˆµšlrCÕÖ[2d6t]¨ß&âAâ^ùeC·ݡPµj/kÙ_[‰ËðiÕF^0‡s5?}ÕxÏâMZÝïA,o ca!­ÚX‹9;ƒ'pí¦]À S0ȃû¨¾°µ*øä*Ý cr÷RÖß>á?¿ üB'I%Ö8ÚßwV\±þ­€ÊH7 «ÚŽ?˜YžÖ>F¶IÏ£‚€Éq^-âáÖAÆM\C™åùK†?siý›±«Ï0 ¬ÕG±ŽõBû~Ï»iê0ðRçPÍ£Æ5ruÔW¼t‰#ß7•–fX¤¶ Ÿ ¢CºÔZçä£ÇÀ wøËàä8ŽøB½Âé›õÀNYöâÖ56~Í·^Ô¶/>B-nýse–¼8Ô²,Êöm|<»D]s[ÓO¦ð?§B¡€s‘pêéó_­Hä Ä\jkÕº¼æÅI Õ ,³dŸZ±sµ¨J¡T"²•T¸»£ÄYU<Ð%”‘qjxdwX~ÈÏê3ħL+'ãÒ«+ 3Õø?¨yŸóiœ{7®å³×'á,¶FJÿ¾«¶×m–¹dbä'â›OÕmÛ3øöÆ]2HV7 vm 1-Ò†ŒBü\És®;5oÔ ˆºÌ@ÛzbbhýÒYÒ†ü7ˆÅÝ÷¡umÏ1ð 29ìô¾"ƒ°`S›fJ¤^/j”²¼ãÊ`à«x1C÷ïQÎNíku¡Œóéi"BˆE²âÖ?Ø»8qü¬nãZPøFÞÅYÅ-èÂUs1þçì\• ]7+ÑÓÅÎ{qI´…žNqlßG¢üQ ùe'C´ÃrîÃm<¯–|¬Ê>uAÜŠL«&å5Ÿ%2ųIÕ,ËkVß‘ UÀê$ÌÊÆ¤¹OjÎ`èjÉ?÷²ô*©°†ÉÜŸÏ f}Ðc˜ë¶‰Ÿwÿ4:»€6%û3rʆq5ˆŒ}i Ã0Ï‹9mܺº}i‡IŠÚ‡ýdDUšø¤Ð7¾ðúRBIDîNY-„¾ƒOƒ'XÖ«[Ñ“<ÿá†ÈÎYPÍÀÇ|kÙ‘P0ÏÀ‘Ôr©2þ<ª•øS†ç*ýFžû_ÐbàS‚€ÌÿS/&:Kž’ »ìö`%òvn¡ž+è’Ï$èÁšZÝ>˜è(9Pdí¯ä Bígv É0_ÙAF>Q }îÑN‡h¦£@V âDOië_Ðê×›µœl¯KÆIäzw³›:×KY ëó0[dûV)²Ë“¡|¢Ÿòl%5tMFÞb¥=*¨óª¿ Ú-6Àê^®îœå\EÇ%¹0 „ iÝ\±É1ƒYÿA§±ú°£ }FIvÀécéùüÕ ÛѤΥ”Cú¸™n–KqÅÓŽ&80¤EÛOŽn|lVüÆë`-þ'Cù‰Ž‘Åkä›¶ ° XãvÂþ\½ <÷Bù•Ëø±ß׿'³5öV¹êƒÕýZ´Ë­ÍÊá­í~-ÚQßHDqìniëH[^óqû¶µi¿µÑNÎ2ò^ #44‚©Ý'ÓÅ ‰‹vÜÚ‚‚mÚÚ$ÿØÚî°hÛÚ69«sk»_‹ö+û<׎9#t ÓHÊ»¿¾= ë}Þ{=3²þÛÖÖ±skKÈŸ¯›‹ › ß äûS¡=wÀx~×Ch@a ö{ Vy±LØNݪÚÜeVc©óT2-È£H·†ÖB |A_:õkÇnÖf-n]°_ÒBãc¾Ð MOõ%Ï7t?Ûy*ŠŒ‹Ûº•PÚcàj"ñp*–zGw¬~mZ» ص'åÝ¡/Cû±Ï•}$—|)êǗȈ4|¡p‚†ä’sI8u­øD–3ñª—\2ȪfaLŸ”tƒäX1ð ¥ $ÏÏÈ,-Ýä>``…NƳ¤…]sÜQê0ðu…;MîFaÝ&[Òí猬.køÜ¬“NH¤ß'b€ÝPÕ¿ì!ŸgYKW­Å6S<Ìû43õKµHºv]Û·ÆtP®®êŸõîdz˜p–"}<î§:)qZiÌ)÷)WJ‹›§BÇñOD6€ô[@#6ºÈ )¨'µÖo“zÑZ¯1:2‰@øœIf»yvŨߪß±Dm6}EÃWõï W¤\XX_¿+ÙNuS›•{ ßúç\02hyrEªÒ13¬•)™žg±îÚ =c೓d^To¬oF‰Ïº;»w-óÁät&eÏN4쑹M€wm3¬Å_…7µÈÀ½ë?5pÖH¦Áàê6ÇΑðu ‘+îl½Bd† ~—Ñ.¼™wɬgP³ < ŸÀ>A ÙÐX(3°·rä¼Óx1@J×/“c3¸nržŒp’zýÃÊ\µ @¬­Þ¥¶UÌ¢|ã±ö~Ù%M¯³&½TêNŸ k¡§±ºèr)r‰$Áã=+±›}ÅÀD¬ÍÇ.l`-™¦³]½‘Ñv:WH·ç\Jq-Ÿ—.xª˜ nÍÒúT›Â.òBºQI72þ[º±k³¶U}é‚Gn4‰jyñŠÂJ¡™”ên2Iño´ô³‰‰4ºÍ‘Ýëö‹YŸí¯4«‰òV–Œ£2µ‡…­-èv¶Ï'‚^|9ƬfRl.¯‰íurÁzß´êTO³MHýºvRd°~~e!#4H¼îŸöÃ@jÛ¬š¾‡Å‰±gBz¦"ÈYk­Ìík¯{ÑIAY¾B×ÌF|g(V…ðD\#6tÄB6úBê‘ÿ@'yœ“ÌDZ¶b¾®ÀÿŠèËC¥Ïu–âÖ?8„NÁ¶¿µÐp ùº:Òä×-8[;¿AeKZð?ÈV8ŸŽxdJ‹{ß°8kîfÌtZ÷²)çvÇ2®)Ò÷»í"}LùåëªØÀM$îÞ‘…8~0(‚¿îŸÆ#Qp#ô ô!–÷éåX +dÐÉSÎ*B3š¾žÇG£oä]ÿaW¶¤©Êl_©ê­Ë¾?ÑûPDEq‚ØOÿ3djbUïQ—«ô%Éq-û ïÜÊ1xxݳéKÆ1®÷a­¸D®÷…~Ÿa‡ Œ¬×Ì»¦ÀGF9”²¡¡Z·ЇðI9MSø¿.lÝýá„ú‹p¤ý±éðuÏËÒI*î帲Óf܉b™7Wvô‰qÃ.g–=ÌÎS$EþØÃlHŲÿ Æ7•£ü¥æåñý>¾M¦%*¨jÛÞt~wRàí;°wU«4ß0»øÊùÌNAî0'tDZmÿõÈ)ΓtœV²V¹¶ÑV=³y{†:mh˜÷ßž)ðF{ÒŠ À‡cG*‰2¿‘Â#ú¦"Ô·˜f³]evÅ b7±·¼Æø£Y¸RQà“^“ ÚGÖø€Ö™ìŠ/Rx’Ýib«÷ó®ìW ºÙ6ú’ÚoÞÕþXa.à†ôAªSÊùiªŒ\é£Ð¦›šMƒ þúF¸‘´-ìZÛz_ëŽSàÉ2pè LÊMbš÷Oja޲oè/º¯HÂ@xï“)0$®¹Êi.54åÖ!ùÎadExïO¥ÚHÛk&ajÅæ xò?¤‘!fXºÂ1¡úÊ{Ë£`Ö­µ?ñ¤+òÆú°¯SO)­ñž†æ„eÛþJE¨tÈöu¹,L¯“£À;Ö"Ê+`>„Ç^TÃFsn3;u©Édžk |ž©i”ernlÆÙh‰>ç_Ø?(¥XÆÎâÀÙIðí×Û¦Ôp2³õOÝëe Àûw Q?ÈF§8ÒéÕ2ÿ4ÒÍpkBþ™žúýù_@&%úîo2׋iQÇ-RE -e'²î}S_€šy ñ@K)%ü€ `eŒÒ²[ð|}ßsfŽšcÂÏz—³\؆ôO \€ÂÞ~Ú+“ ¯oow8¯|²C' l`ÆÄnMËw;ÞOÞ+œL ŠÞÿ(1l8Ù¡÷ߨΤª*Ù:- Gßg:ë7ä½ §äÝᘕî)ðE²:ØÍ–zæ+_²ßø¾šŠXúð»+Û(°øÜ&Æ·m›*KIºýŸßÿD¹¬“/rè6†’ ¸à§µ©W®n Æ€|]2¶&I•Û½9õ/¶á;§odÇtርpª‡ðHãAª†ƒ˾È*Òl(P¹v<WÑ7ø8‰Ø8hÞà°·;Λ½”NêVÂ.ðvbs骭:žúHé ;¹KÁë·ýðgÞGJçâcïlnX?éQS`ñÝ’Jé·à4¢T›°gç–Ô9ëæ­=,éÉž’ °¤kòN8â÷Îéãã§+¥bŠ[…ÞÔˆS sÞ—é­©^o-ã­»Um“¨)ðN S ;Wg¦Ö¥ú›ÒlÇu uéÜ.MmºÞPàí;½‰÷fä:X†´@„fûß³Ç9ö=évœ]yêâƒxqÐ)@ `¯¸;†uŠ«l:Ð&-T_µí !îa¶TK–ªkʺçÕëHi¶m"½’(6ÿoH÷UÜs°£8¸ÍÍT:Lï@ñ=°Ú6ÌóQbàËLÀÙÎ~˸æ¢×îØ(ÇÙnË6 ‹S0Ñk¢©B‰j-ˆDõ›½R‰êV¢D56l¢×Ÿ%ª—™)aNÕxç•ù“}¬)ð ø€ùÎ[3m¥lµ <…“¢ª_ ?f7 v2ØÂ[\›¾iYw–ßÈ/šO K<©†‰2»uAe&¡ãiÚ7¶±©Ëžúë”LGátë†F.K¶à'aÓ1…oÔâÄl}@Ö4QŒ€×,«¡ÁúâM$ªÿ¤ njN äwC×5Xe/ètˆ¥q`¹Ô²Ÿv±á‡Qd9ÓòЮsAÿOí c•“¹6cBN7¾ç-¸·;–mæZBýdišiì|¼9Pàƒc®­™VÞt¢£À'i§‡öнt>JjfÛâëBÛÈ!ã5Ívl¦}±Þ.ºR1­!ö¶W=Žå§1õ¸D1º§B¸)‘ލø"¼„—§\öÐì*õBÏïY'/Ó¾bÌW|]ÏÃü„þ²ÝmÓ‚^@ñum~„ßhMeë‘· l‡ƒõœ±HËS¯ruã\bjžp¢Æå©°0©»]¬¬q~ã×ç•1òÓ–Ç0Ø™§ù}Ρ«+•5¢Î7ä¡ õ¹äOù+:güuxϪ+`žýéZwŽò|;þonÇ=pÚªxN¹ràÆo'3ÏÞÙ•¬îW>0y9Rú£ç—ÛV ¼agHkãd‰ò¾4 Iùþzd«Tm’µþŒ­4V‚¿žÚ4SQ‡dŸ7$&}Ó´àþOa{';×1‰s 'ƒ)=aÃoÔ¶ßëeA¶¦¯÷å£Á_±îZæm|_Ô¤ÀH:Ü{Ù‡þ@¤u¢T§’ºIò+j»Ôþ7î šö¦Ä¤ßóx¨gR¼C¿è _xÿh|Ø×¶'Ú ðP®qߨ+ì„Âòê×W¦üp¦À7Iú´‰,ÜÛê}êeÚ…ÅGÎ[TU¨#ÆQL}ã@ü¥ t¬X+–G ¸óî=ðß”õ÷Ÿ?´V¬óP ->>³aê* ’¡ª\YÕ Hû”õ{Qy.‘Ì €Œò".O=ob.G¶e·~¾¿6ÖÒå^n³žÅ#¸|}/*+,*gW|/*+,*gÀ‚zS˜qºapN#ð–KÈbÙ"mÕØ.Þ2`‹ÎæÜ”û¬)æ  ‘ÉéÖuͺÙ§} Í{éŠ&”ÜÐì9\uÒ^w®U¶l3`^ø>®X+R¼ÅÇÕ!Æ yŠÎÖšo„¸Œ§Î¹@+ÙM[ʰÅÇ7º6d‚7׋©m8’LѦL€r½7l $"à³û§Þ÷•‰MY |U´ã,ô˳›I+ÙPà“PCߎ¿5–ù}H/Â2ÂŽÊ1oU´W |Ÿl%0xçCg¿ 6íÆSq,Ý Ù¶u{©6I_GÇQh*‰9±rfJùÕäù‚ű¤v[*‡ÝÖµ´» ™å¦°o—ªNX\ÉW®áwx¯Rv}[¶sßQàíçÈ«ÞK{|hïÿˆ¼êjÜíË.¤ñ™P)¹ÍNK9ðBÓÍ1òêí¸ùom%æZIƒ—Î-ë^®xö‘rPíuɘ*Ù6Pàƒð'ÃÎ^çm‘zÝZMOªk’2ÉÛ¼xsæöÃ8¹èŸ¦Á ·Ù=uªÂþóä±âW>—>–³Áÿ"|3¿ '*qê2æÃ)ÌWŸ—#é WÎÎ"tOÁ­O.Íä~€,¨ð+»™µAZä‚Z¦a?0*Â;47Î@A[BËä§ 'Žw5µc¼.¢âóžu$6øð(,e¿-%šû OeÈÑ$z5ÕNvÝø Ò¿å©ü'©¦¦  ̨:]YA§ˆ Gæf-¶å+Oå_Õ¾þ?AuEÿ%¨ÞQàý uQÌJu>ú˜½ã[°JÚ_¿°y3l…’[6”zkxôFvEiØátðþ ›/@ÒÒ’â¸PUÕë¸ÖØ÷WPBËXE%Íu)KUwrÐHëE t}°]¥NõHT*‘TN¢«üÛ±+>ÈdIòÍZÚí³ñÎÏHO’‘8o[v¡+Ì—|e‚êѬ¦iêÁ¢xAØ9S %¦¥\‡ž Û>’o—’\¤$Ü…Y[cžÉÅ }]ººblE‡æöqésj * À’­<Æú&æ‚òFð^Ó5HRÓ±÷$¶ŠL›2ÕDÐ<$X¤WK™—¾ÞçJ€à Ÿ4ë#塚Zv dÏŠÛçeð3+Dê£YÜò07~=ñ©·¦=µZ¬ B‘‰}/)´5[íª®VIÞH“9¼™­©êÉ)¹WÞÏ€Úë¥îFUÏþ˜ÁߘG¯‘¢bMá-në€õ© <•@–œ'áÀëXÁ¤OÒž0fO.ãí^/·¥Å]O0ů>žªº xöW¥$RN®•OªÂyúâ ´<±Bu:P«ÓZtÀ#Uܨ|{JÜ¥×;¹ƒ_Ÿ ‡CsL?„‰=xgÆY<]/´‰el¼@¥ƒ0;Ns”61'§¦M€}Ó#yiq˩ΓÎ{j;:¿W›®§Àû¥@ôËÛªm>2ͧÔ€õ¼:MO: ,±Ï§²[‡ìÖ/Ê*™¨Ó§Ù{¸kcúß§€žÔØtöö§n(°È» £ *z¼•¤À¯l º_™Öv?Þ5¥M<›D"ï›rbÝ4ŒÉmâïCp*ΉQT‹,sä-CF¦a¥MÉ@Ë®øF›Xc·˜ .ö’ ‘!‡4Uêí2üÎÍ[>µ2™ª“ .Р­u?Ú¾…v‚Ò&Æ™‹Ä¾ÅX™ÿÞKË–ó¤M¬0•ÔNMàÍ1fÌÞÒ&Fáo÷£·Ôº«ÌŸèë$2çv.;6÷ÖŒ@ÉPÚÄ8Š‹þû`#cvß “^ÚÄ#šf¶Âc'w÷_È0 ¬Ï¾¢ÄM}&‰ñ°-wo`§Z_"¿ÈLé{ë6u/6~ë—¡¤ÐmXk¼±ÅxŸ8™Ãé®^ýŽfÉßæí–!ãÛܦnbó¦XöD·;Ñwƒ;Æ—I–c†ïxÅו¶7EœG]¸j80K÷×7Y÷”‡Wtë4¿ñp¬ÂlKpêÓµ]E§Ša,Ä·»16Ìm°¸¼Â8Kf»7‘×5nW_´]Ã!ò–ÆuüºjÝœÛà’aâHŸk8rnlc3QàýocæÑPà㧇)ýôC™ýÆ'Uƒ(ú·ÕÞ3Åœùó›ÀAù‡Ñbæùñ×Wèo]†© ¼ÿôÔ.æ ‚àƒ¾ëԮȌ6£ÀË+ŒŽóR–aŒY·øúk›ËŒ–âùùS‡Mìa6KÍ„ Ó¸±™™™çº6¼Œß„TûXŸkƒÎ𓔸þÙBdáwªÖV².»"tîþAùØR)v+vï“Ôöÿ¥ûèKñ®vf2 ó¨„.ãFCÊï¯ xËö4¼öÕâ4@A™…ýŒ»«YÍ)*Õ*aòfsõNwâ›Õ‰±)y½äÙ­ÉÐb$C ±B]3ÁjÂi|ž™ œÚVþ¦Œ91e·NŽæJÞ¬í>êÞ¢ßDëu®j…cJÌH¤Ð¦ž›Ûºß§†kÜ…ïoùèÔÒˆËSe@*ÞŠ_SÙ•¢Fã‚AÄCSH¬ör¡ÝΚ™é0Y‹ÓVáa†ìÖ‡£™¸S"cª:´ BÛ£ìèðR«Æ~)Æ­ðO¨¤,ª2Ží•©2àÆ nŠi71tN~l¦z9±¦YʽxÃÛ³²?y·êmÍ' íXg:ø°¢áÔJ1ÖûÀ_(ðý·f³å(Ø¿>²óšàDNil=› LŠé6ý™ß¯øù~•ó;'wÂ…ßAçüÅÉpáwP9¿CA¸~ЕºÁ&2Æÿ?®mÉVUYþR÷¸ûxÞ÷‰X¿¢ xoÄúú Rå(ݽgô|Ëp("U•™?xƒ Í€?xƒÚISoСñçÞ H¼A_„Æ]° ÃälæZg_ë9—Ò€ ÎÔ·óºµ ð:q‘£sb I£s¢7gš/ïN“ZAëþTz¶u­®)ðšåRjÜLX¤@VõE(Æ{‹Ýq¨ˆ@fJÛ xA¹ÁHeO†%‹Ó‹[ã‘iéÊGmé—¹d÷/B1þ(› HŠfT¤ÇqXù¢Ü]÷s>{ïS§µek£[PYy=¨Öú®Þ òpE>pµÈš_ï”r ¡ëÔ†ƒB¿öSöÓÍ=Cù"œƒu»Î•Éü‹JÎXt]V‘½·ôòûs™róF-#¶ ½i˧eª7¶é«M<éiìI;=öœÙ¡Y(0«÷¦€fmu)Yå±xЖ0‘RÄԇőI‡¥æƒ¶¼Feý}Žƒú|‡õ"xI‚MSøßõåµ:¶‘“•Á?±Í~W¤‹Ýkø¬KÎ1íûxïØ)Û_Cœ¢½Reoù†ÀgV7‡Î§8àñƒY…ØôñÌÇ1 84œOõ4µÎó xŒãQ»PÎ,Qª²éW ¼½‡³ÈÊ)ËÊÒ”%ÞwU8#_?5rÅ£5ÖÅ Çñd7¸Ïq0Eí*`𿞧ÚWb"íáý¼Tá°NHƧ@)œ5­Wc‹µ¯ç7YT²”ï"k†œf^OÚ•–˜¾)‡ÔµX«èß¼Pí %d;TÏ®xýá§ãÊùÂç5£ï¯è; Ÿ×,¯€ nœ©’:„"ª~©:Œ*(¿y/ä¡ ±Øšp1Ž ¼Ps€dµ.¶n Ûð–¯TI(¥S÷+¶¦ÄÒóv1R56JϽñÞãýóåqÖÈã§ïŸ÷Ó.Zô:’{|ÃÃTÛÄÊ×óþá&W!+Fê·EÒëùøÛ"©Å¦½ç㋤=BÚ-’6=8 ¼q P¯ôʌ֭ãBFÑ”d‰°÷>9SÏŽ/‡rf™4`÷^¼ø)K×O«)[M½ž¿YMéÜjêõ|ejÇ{ ”Ç K,R„DµÛ°ËØŽýØ =SàÛ˜4¥|“Ö‡¨Ì­îP¡FäwŽLŒÉˆt-Ï‘—·iƒD#Æaé&ð$E䛩~ôùrºVKŸ_óFŠøIª»YÙÈ'¿¡²5"h…ë¢éÊ^ó’ž}A—L^~{òåèZyQVPJ¢§c÷ý(«Õ`¿äëò–nÛ$Ÿ>ï°É†AMwòØÐg{¼—Çc_N ØÓ9„=›ÉpU¼GÒòúŸÃ)<ù:øÉš¶^(ð’ýôþu3':SNÜeW¼9”AÂÃèu]µœýFÇ;‡~Û²T£“eƒU݃ʧô5“jTÉ{]Rà%+eÅ8D…0„÷áÅ`Ñûuÿ¬y©½;;^ñš s KÔb›ti˜q’ª.8ÐÆ2zX¡eæ2<ÌëcSŠ!Žc;ò꘯lö€åB|ݾ/n™™)ô·a£d?{³…S¾ÂŸ.NŸë9¦’†/$R¸}²¨îâ­¢À+)·cLÝNͶnsãÅW–bäujgrd¦]M’ÅW–èÁE:¥-Û22åfÐàõífŽýä»0–óE.Tв á]k[kæk•3m™]Ú.¦¼·NΞâ;+<±óÉ;—EK>K¼“p‡»âa£Jk˜ ˆûŠË¹²ªHjÂÐÏÞÁK8àÇ€'yisÆôz…ÕŒP»ó.z½wÑû¥sx¡”€Dáñ¾÷¥€Õ¬¸¶Ç)*8<¿)*¬Ë€—÷){Çje³lÈ *Þ‡¤&—Ù²U ã‚©â‘¥“Y:Æ‘Ô^êµåU»Q mq­UµÇÏ}—zÎÚ¤Q§Ó¬¼ÂÌ!¥Ÿ#&ùÎz©º¡ +RAwX{"°‘f.3à•hʤ5;Û®_|˜S"‚tæ˜ÁöÇ“6¡Ÿïž@U ñ”÷Ê–nìÀFíEèç{.r¿bƒ½>Ḡـ‚0¶OmFÆJ¥õ®palÿœÓµ¿s•ƒx²IÁ³kïëT© JIþw§-À©aÒBŠ*:?R au`DMÓd‡šm €×Ë…ÿ”cáñ·Ú B >ŠŒI!Ì‚•K "¼’D?Hýd«Y6Þu‘1“r64úOjМaÊ»øºÿœðøéû‡7;ÓÕ%÷=^‰”¨[;lsXÒ€¶PqNGÒ¦ 1•:»Ç;}…)zÝßL·Y¨Ž„H›Ô[+ôÁÉu³Œ_áó´_^4Ï»+¦_ÂS+eÕ¸âÄ-2õ$~Dó4,jlú>’)}Ö8µ,:ÁC¬øþhŒÂ¾±Oz”šAËßÁ½@›5± Î.¶5Ùßü‹J@ßÒX»¡á¬gÞP»k°ªYôbË™£ÑïS´F²ï².ÃÐ-èKðÕ~áÕþâûáG„SŠïÿ)œ¢)ðá”>Nà5[öI1éÁ‡]±¶xÅkÖ™ó*Œx·¼…‡£|Ú¦mX%6y\ñöc¨{ÏR¨0õ¡Â?ÿ0ЃßÌTÍÌ àȘ‚m°1µèÙê qº DÚ}‘J%ÆðRâýBO‡Î^Ùô²Tº ³l¥Àw?Â=ä2¦ªÃùlšpx¿þ´*ÃOcweA¨¹é§.lÃR´Z´¯*5÷Ç]aÅEêûc8Žrõ¾’-NÜW–×Û5ÔÛ ÀËg½]C½ÝmôáÄ\Æh/öåÒ“âE¾ÂÝŠ ¦YØ=Ã9J,»âÁ‘cßf?€¼Ô/“´¶ã^yï(0eÐ2Þ» oÓú®²8ŽEv.Œ¢ý ÄÎJ!xxžt¨((íâ* ¢LÞê:ƒ^TA(¥ÿü{Äâô±¼Õ|ÐÌRœ(¥|×ßÝ¡Uˆr—IAÙ €”¹œì±]kÔáØµx ¼ ÔL¼­ÔèpW¸‚rZ¤PÑÓrµY»ÉìŠ÷w·×ö#@ÓÕ¦ GHæšzg7ކxÅÛnªA7í!· ÀËO2P¢ÔÕb Ô_\>#•h׺qVk ¨þy›ñ- [–a]@Ÿ€×Lá Õå*ÝÏ%ˆi(;5wQN|xÅG~ÜK2ÏñÇÖÎkã ½º¸<>’{~/Y®«2Ÿ¹C…rÙáÐcÍ´0ˆìx¡ÂŸ)qõ,ä4Öº^N ¡“²ÇW£*dûð–é‚$)Q³²6,¤+þô+ÿ¸ :lÃ]?XÙÖ ÀLñ$k»©aJüfŠ õÔã[W ÕLÚà”­¬|9¬ê˜áÅi±G16cæ¶]غ2 üØâ€ÏµmïÞßd FD|t\Ú [& ¸…–[ø µ÷e;^wøÌ¥÷dÁÄ|·uÈ (ÆíQ%¬÷"µ=û\KÅ!K[Rî¦îç  Â>Üë*»;ÌÞ®€Êó²4xôÜ3ÁYê175’.¬d²ëé1Þ†Å9»âímV+ÀÛ[-†MÎ8à ûðßd—z¡B”"}ßnh¬”}øð´“À…îkϴƧ>qÈ+hÏ|î÷™ë)E²“öЕ³ÉWk ½âÅõû<ͳ#|\3ßÄÊú™oYvª¶W¬bΡú&3Q‰´ö¬›f_×ùߌdwþJ7ñ†¹D%øv›‡rNø¸8[¶Vø)\¿3 åXRIy\µ–­e,»ÇµKöNZ(ôKΔªj^>ú R9yš+B=Ìh×kvL)±+8.{Ãh)pÀoùQªÄ‰;nÞ¹Þ÷ ¯x?‘$ ÌNʹÈiQø¶h} úòµ¶gÏã3ý ÀÌiP½”|¤@:{R)RE^ŽlÖºÃ7sn{G5n®¤©œÆ#a‹1-ˆÖ‡‰«¶šÕ3NŠ×¹½A$®Ù„°¾ìèjø„Ä3î¾RX/ËøŽ $Y×}úì=SjhKÖbÔ|}ŠèøqŽ­áûµ¥À·lì®ý¿—å]Êqò¥£ÀGFØM¤pr×§@p+Jç¤︸e›¡.³ŸÎLiÒN³ ËÂÇp”](° ,X諘­M½†>ð¯ÏïUV¬“exn™!‰€»‚Ê‹¬¼A@Ygwùw³$ºaìf‰‰.œäE~â«Ð>"ŽP˜ñxÉ^NɈ/dž—³P ‘YÚ®hÊÆI– ¼WÈÚ…±Ò”må(,h >ÎY8'N³|œœ #£w1KÝ×k߇5¦Ænžå²‰m À×oÒ vƒl|qËÓ{g;ËMcÊçö|QŒ©ÙQ Žã1Ö|sþ@ù÷Høªdá]³ìŠ×_mA‘lPšÜ¶ CÌlAQ³L}Ø‚”&¶ É»K›Ž™ú°-MîG[PÖg?}G*_êíL{ûÌ”µÜ#ð¤ñš7MÉúˆ°o׿»ä°¶Ù¯‡‹õÎLŽëno¢Žºà‹ ÀÛo]ŠFðþ[¿ÖØñ‰ß¹óà gæÚ·~«Tö0O#”ù²¬í:Ì¿ëõ3‚Ò¾–,Z.ˆ.Xàé¾äœ}ê©ðZˆ!{h‰ ¡œ©Ã)iYשnOHÊŠ†ew gvY·½ÆùsûÈ#§ôÅpm„€¬_zà¡V•únm"ç™aŒ}»{0ÊÔî³òè?vgäýœÁªÒê³k”3ÝâZz»gz§»±â^p꣱¢Òó"(ðúÖ¿‘ëç²U­ ‹ÀF?X5îWä×Þ©ÃVJÇ §dǤbÒøµJ©×¾jÅ"YŽŸTô'­*aqššË@/Rr™y9°°'„ó¥À‚äÄÒwÝDÇjæÏVgþõþl*ôšŠbïvlšüÕ|Ùpž–‰Í¸ªí3䛟«"ý6ú)u[ų— DÈM¨7Aȉ1K”è ó|§þ¤^š…m]½l:C~eìð^Jbós—¿ÈïmÞN¥ÕiEØKÐj‘Ϭ'{‚VÎfåûùtŸ/äQ^&Õ†Þ]ˆ,0hIEü=,÷£Ûº²‡&/œë_¿ÊBJ…søñÙÒ»/»6£ÙìŠäó󰵋XÃárÙ(ðB(®Ð’°¨¹^uÙ`ºööÌÚcÖ Î5Ó!aðFL¹â¼ §fK $ÝìÜ#ïyö³!8¾Í¤°»]MeX†®Ÿ(0ËÌ¥Í[M›c7amŽR“ܰ-ÂK¬t52Ñ!°8éB€½bØ–Ô …WÜŠ¬]ípÓ¹ýmA¨™¹ý­Îío‹û×ÿ²¿…âþý¿ìo{ üËþ6»âö·ŽÚßð·5õm ÀßìoûÃþ€ÙßNø—ýmöÔÙßnX’Ý!<¦æ]ÏFSa®ïMý&m&·#˜¼_þðFÑÀˆáéýòg0é­Á{<•ŠsšpK$öø–/¿E~pÙ¯T%>õ~Å5>uÙQ ,Ðÿî­F‰H©M¿µ®n¡Y¤¸_ósâ±îõffº4ÌK Bq…G”ÂÕ†#FÉ^~(8¾Yï6—ø¹üÌ®ÅIqòs9D»ù¦D»±ÇñyêW­Jp9µb´CÓ½¥¸??ûU÷­;62Ûzñ¼M8œyªÚÂô‰Ž<ÙOߎÏ5¶¡îkJl¶a{A÷w…\€u<_¶È@œ0y@ͼSx‘Í6†ÙHÕø ƒÃ¬Ï¤d‹ô¨½dËÂ΃óç½ü»ÁNœœqŒWݸèy£À õ,JhQNÉMŽ[Ÿ*I¸Ó„Sµ¸¿Rræ.5) ù­í»=kCEæW½Ý€œÉÇj—ʆ/¹»´Läi»E¹ êWšt!“€½ Ÿ"~°Ô¯:IÚIL*‡µTð T’ŠÇ¹ŸVÂÞ5u“ÙÆ^CÛoñ¸äVvû3ïé(±Q—CUQàõ¬Å['×NËfj Ž=Q)c÷B¢®Î“CÕ6903æL½Xvœ˜®–³ÏÔH7E>ЫjL]›ine¼XÅ{>{¶¾´m(0oÚJµÝRLrìû¹£Àǯ¹4Û*(/ô§ÜÁ”³ÜA:/ÅÜA˜¼GîàäQ»×Ÿ+Ì„ÿGî€xÔþ˜;P}öÓ÷ßr0Rc@ófš®ÿ· 5¤€µõ›vŒó–Ø6£¦y]ÕóD”iúÏaÝ£\_Î^ëÂÇãÔ–ˆb3sgZÎ×Í®x!¼P(r„×Y>,Çì9Ñzn ‘ÄÉU9bJàñ$Ö4°¤â0K»Î5¨W÷¾ðÿ»!:%D¦éÂ]IåÇ“P¤w=Èo”ai.7çXvwJ?N2@±D=o3ÃüÆã•Ù9½í!¶mÝkÙ¶Rà…ÝäQ“û-ÌðìŠä´ëè.ˆ-ëYK7ÒñWßUÍÐÎÇñ4skÅ&™ýX1ù°N,õ€KJqâzIˆ*Lݳ®©î"—rÛ‹uSZ,¾x¥†Њá{Ñ„àà ¼Ñ|IžÙ®RTm‹Ç÷Gqf˜¤®úWÅóëOÂU+°ªôüú‘pmÁá cûç×ß„« S}ϯ¿WZ#á €÷3*XÊü—°³Y–TeÖð-­UÖï°çߎط¢ *¢ çêh¦UÕ»=xK„’Ì7Q‹÷/éQd•%úPq&VñÝCg=Ì4ÕTJàs¿#§1¯Æ 5†<©å|}I£âKN£Êþó=jB?ò÷÷=J…4ªÕ­)*“—ãYEw¶'KYr×竪PÝ‘Qf»õó?çÒ˜|à<*šuªT›„_ß·†è¡s5±ÉoXf¨(OΛRLSÊ9Hà$¯%+Á¡Þ?ã/®ŸQòtèãƒë[Õò”WœÀ{®v-ªÐ"G~dáTøhæ½L¸Å'®°ž^f”ck²CäçL¼ý­i¥Ù_æ‚ôáIÌ…ÛâW1†(TîÁàl˜ä"[‹ÇgØfÑR±º;2Vy“ôx“‘Hqµÿ±«këlLA²K)öñζÚiæ8adRоr3­ßåÕã8ô‚7a3Þ’¥mê*¥™%ðÔ›Ó›ogKšìzy{vÿ”áFJRæM¯ƒ pºWIZ®þüáF6ÏS¤¨ÇÓl.ƒÎÛË\œ÷3•AÅ«àŒ¤|š])BáÇô2e¹úßÙÔ¤‚`sR L¹Ž¤TmK xýÿBœÉñ/SŠÐ¶e—ÖÕ¦¶µxGHÛËP+×Ò0›÷gà|Þ%ç¶/cwÒ[5>?FÔ¸…9ûñ#jbP}m¡ó·+1ÿß¡/¼‹Ý<ú=Éû®p>C•òTuûè8Ÿÿx ½iIÕQKj^Fo§ö! ÎøAùiófpžÛ\ðâõ¸Ÿ‹%AŽú³Ë2 Hñ2FȊκ¤Þ—@ˆV§Ô(57ÊŸÊ9q¼}Ž9’&hBðÔ$y´÷Ã8úmZHK… ªeeÕjÿyE›½#ïoµ¬bìÖ0C=ë9ï²#øz/ß3˜Áñ™Ïu‹:üçOÌ54ô¨eDæÐ–DBe“* ÈËJ*o3ò­M"a¬nIíîbÊ2åØf2|e›Œ4çQøÙíÍŸ®(~úõK\á,{#yûgÞ•ÔÙP>N5<Âf2zzÂVçh=P;íSêŠ0!t”0­!˜œM­)%Ù ¿—#!“µX¼…ªµé½ù>äñb„º›µ?MæàZ nöÝW€ì£¼mZŠ£’­ç™Ö4»Aû!oaHÇšó-Ìóç,ö—2å8ÊÚË=U ÇÁÙÍd{›„_¨Lw*>³ÍF̓¿­Ÿ²£øùû–?²= k¸–•Iðõ>ê%†ÿ$ÃbF-û±J©Ï/ú¼ùÑ«¼ 9W|úìNz¾e¥²±•«Ê6ÉÞ½žøêÿH÷âCH÷2Òæ—¹¢ '˜ÅåÁau}ÁËIÄs«’)È:Ï"ßCÃzÞG¶ù’ ¥»‚—ï`@P¿"ŸOÃq`°nö>’€3˜’³f­g:XZ#ðvdæpÝÑÿ±þmê‚`§ÄÒ£iIÕd)îêdÏð“ºW¿2åGß‘¦Ü³„?éjÙ<ï8˵ÊésÐDzTרÅâý­}÷è­»'ìŠë¬¹«¤läÀõ>ŽÌÇ—´†ÄK)ïo[ AÔ=)®×wÓåÑ=w,ßO]ECÉþÖÌȲóÇÛåÖÖ½^¿¹AT«¬„àßj'çŸÿU;¾Lø~=q)ß°›«ÒnN ²q$ö¿~ÞŸâ>@µ½$¤js 7,V}¸Û7ÉÒ“,Ž—:•òögªÉ®Ö?=¿ïáãÛŠÂÇå´ùöàuAY3Lz½Ñ éXÊ ½.ç”ݬ·ÕÏïe P’,Y?±æfÐ&Õ/Màõ3híZÔâ Ä(¦bqc¨ý!Æ!Ï™×Õ/£rðZ:ÇUp[.|œ Ú/zET[lA->sz6Í;…F0¥„íìNz]Ž[˜<]ãZ¨§f­§.»‰S‡ÿ‰8¹˜ÉâM”tÎè‘ f[]¥tA*êuM™eq*UÉ·Ei‹ìuÁ–ã™_®V[ÅêÀaèzcÀZ©ò·¹~*“ÊÚ¶¦íç•+Á}Dª›&ü›L†™Å °•HjvËäºzIò¼ ¼ÂXÆt¥ŠˆÚE4è7BúdÏ:Á&˜ëò¬¹}ÓL+ƒfšjsŽÔëvš‡¸Ý8§üõ× —ªL2Ç[ܧ¡Šhª¨ô¹áöÕpõÌÅ<ëT†þrÃ1èÍý¢¿l"°È)dÇúêWî—š&Gö¾@´Èÿö#C¸@ìÍÀhOzA¤sšmßræ7ø.ƒÏóË$sê3ZuÙ[rTEßÄ·…xÇNOd±]ª@”@TñO$5ŽA¶ŽÔ90ä¯NŒ;Èç*$þOÊ^k¢ºT«dñ"̓oé«i„˵æt$CïñàåìÂ1Ž'œ8%6ªdÄôU \úeVµ­+ Ácig¹X« ³«beÙ ]¥àzÞŒÊ2—¼,Éo]|Š^Ê‚„£icQ/ÀÁdýv¦4«ßWßã¡ÊÜâõ?â¡: Á¿ÄC-%wi‘p¬¨S!åHVµBðŠN ÛnAÕþ´`ȳ32x;¹"“lÇÚj/W:“j!X€:9ûÁY !hµB†Úœõ®ÍÉéÀ’NJoÇÉp%ŽBI£RkÒYûéV0U:aËhè:´làh@÷!Ϊ۩¤ÙRÀ¬ýÏlWßÑçìfË4ó¡f…H`1XJ‚Ön"³kH­ ö !¼d[á™?prbG†ÈâH—Ìi$ZÞÉÖH<0Rf“ÿà{A[îši'Ûâ6odž.× ¿“ÿ3q›÷#ñ"I­'®x;é‘×[†°¬í©ehÆšt ~÷ç¡IÄx*äèß ™4`vò/?m@°Àš´1Ðîõ¢!x9ã‰\Ô¸tƒ­÷9ó‚}ñº>†qpuÇÝ’¿ ¸m‰-fgÙw‹Zú™Aðr”¾Îµ"ý¾bDçú´Úìr"Yç>üô¯œëUeR?9¬d"h/:É[‘Ìéõ|-“’º6=l¿p*?ºÀÚl•ÈûvbêÊ/¤*}™+VΛ©ðlot•-ï-/(îs{ô\QéV±äî94vÍœ˜pÇ{¿!/Íñ27\ôŠeY¸‘|½r‚Ž ®4ëQ&ï§PÉæÍ‡ZÇ)­ß¦˜Žå ŠëýM'zÁäÊÞAM=œ°2l2ÊÏ?ÌèÊ‚@§®sÙÿÚŒŽ33wl±ÙZ4šQ®½s¸×ßÞZ+nLKXI ¸GäZüÝpMºzð/Ó 7-ƒàk—hßÀ@FLùríú<% kH̺%ThAgAùû™]Oäe?ˆ§Ù.Øíèœÿˆ,à‰H5Þ=Dý¿óÔ9•ªÛÁeù^0Òßb‹µÐ,ÞÁØâ¼¾5¹¸®[MŸ=j¨J7ý£»®² ƒ÷Øì Óïƒ7>zí1øÄcr‹“ÚÆdÝîcò…´Î çLNÔ}Pnмqôû ¨>‘b:‘x`äÏmk80^p`üIÉòÑí6 CiˆN+2”ÕH·qI-Qø“ÕjÌ* xé÷ÑîÇ)iP‹x`¤¡”8ëºv†àõ}LÎ3“ â9jãˆ‡Ú ª›C0¶xP1Êm¿±tSv¤Ý~NÞu`'»nR6ÉÛÏÉ»žÇd—<Ôn?'ïúi‘&¡ÛÏ)BìDv݉¼|B´ÏCèå>‘­>‘W´,ïÆ²óÆÒ¡ÎÌÞõ³µì¬›*Èûû>[¶D>> ྠçZ™Ûü=Y¶c\ÐK^NkcXw½V«A`ñe­Öªœ!xýv]W®¼}4¤[{žW[ âòfIW‹ÁÇûpK-®yY*.ØÆ™ÅàëÛ²\û`ûý4€ršNäï·…™Ž½Îy¤Ñ'²€ËhŠîö˨5´W‘×Ï ®ÔLÞ>““ Ë‰¼¿/Íg œÈÇ»uÛZ…ÖíòaiF+‚Àh]Ð^žT9˜—MŒ—J Áâ›Ý°bÿ@ÀKFEæÆÑyærò§ Þ¾Y s|Èþ隄jΛ7ÈoâµèµÉW]· –!*3X’pßB×^Cðùn2š†X{ü,pºaÜvÓq~× Ë³±øÛ&yš¦ÒAðòm ¯zïÇâÍ“Ó|?rY;ͯ‡LB¾Ñz¡²$¶¼}›bß=Ü  ûôo,¾¾œðA; ‚±ÃÿYR¤|d‚0k{ôègKšÁš}£ã¿ËV¡5u8)×EvºÃþGEòôúQá¿´,Ñü¶I6Éoã¢KÞû÷õXæ¾ÄaÑh‚‰j"}à øu`µ ¨rš`n›`5¯ß¾w{,àGdÒû÷¦þ{çØ’Þ?÷¹ßt‹Ï]>êŸï=>ðÁ*ØãW Ê÷”œ×Ä.¶Ÿ’ìvûbúü¨Å¦ïtÑ”ævú„K·‡Ýn5}Nî_'Ÿ¦,Ó.óÜnh&¢)K†Š4û”½}8®6rÞ«·Û_g¢1=jñy€I"f›`VO)·7ƒ¯oSöÜ"ž‰‡}–½^KôÚ癘 ´ŸçJRȯ¯Œ‘MP6¥™yå‰xçAÆ­°²Íýæ~ÅÀâ³_w•›dféS"áyôzy޾7rƶfæÃ 0ðvôRsè)vC[Kf1/xGbJP)UšUÖ¤nRÁúóµ3ÀË€ŽÓRÄøòoèF#.es?aàW Çk…qó¼njIu3¯_'mHS£ËmZMË åÀ)£ÚÂË 6•,ÃÙů*ÑÉ1=ºøÐ¾”[™F®†ˆ$e¯CŽ^±J²šÊ¿HZ6xM·®t=sî0±Ö*»¤ŽË×¶~7»†ßˆ ¨»¿®øØ¤÷&îÆ­o©fÑÍøüÆh l™_ß ¶ìÑïëéuÍé¢KœSMãÖúÊÜç̸Äâg•ànçÌ­œ2$&Ó‘álÈØ‘N¤’î×íÔ6ç)VUàñ¬(·jéîŤÐîÝÒ¶^a÷ªÓ×íì-TÑ ˜8“í°VJ``Æ(×$¯¦Y©Ä”€¨˜Ô{‘~߬Î8Z37ÇÀ½˜4XçäøÃÝê]0ð‰úUÊHL.{ÂÕ²íeç¯ba<ÝÆæS|’Ó¡tÆ_9«º “Q:ú´o(Õ92Ö‘yž¸]7Ü-óÁøKƒÉH€}gk“¤´½a${ñ è‡1£ùóc3÷ç1o_6™t›lÌ÷o›ÇÜU†||ß=&óù}ûÔùW:´wñÐe±Ã¸ÍÎÂeÈ7º‚Ë"%•¤m§²ÍÖú/L¤í¯‰GÎÓ­îuÏ…âù›ç0lºÓKr麦ÈQ pn´»‡˜ÎyǯYïw0ÛVnz*ËD1ð:3B'¡a_˜W×ÓžèqRñ»ÅïÛÒÖX R¹(ª¤¸•²f´{ðõQÁ-ÖfKélªãˆnE™ú/ÝüU\¬eUbà^oG¢L\¨G^7­ØÞñþ:µòÄ'°«ÙqR& ¤i‰]×¼g^î%¢ðùç÷©½#̓ɥR=2¢ðùhŸÊÎÆ+;;'±ì1µÉ$6›®Q|³nƒ=Ÿ™ËööÔº‘ý„-1°HLïd§„×ÎåU£•bàõS^¿¿IŸ–ÙûÃ+ŒðΞo™×-¥bÞ'ÙK±3ÀñuÔréS óýøt×âA¶=k0°À$Ê)gSÍïæTQú>WGŽ^wâµõ&œýÙZ ¼¡&(fu@¹´k_+ ¼#úK0~¨íº‘Dƒð>J&ÿX|sèY/JÆZVbàßEâ!F•l²õTa`¦³@nVHﮞ$ûŽïŒ'/Nº¹*{ˆ>Þ¬ ›U ,xR’4I‹÷‡,(ôw¬ã2öKÏX€E ÉKì¤f½ôûk¿?©,Àœ1oÎx”öy]0¡Ì hƒÝkÉ¡ÿ¹ø-r¹T‹Ö³›Ó¿F.u H^~ý=ryÞ¾Çæ£v ^ÏmDpq7ƒR¯å„?Ü”ê8u®ñ ≉GW ¥«i¥§ÛÐX  L!·ÞÝ)û5}žû9’ˆ½iÝïœUD{çÙ¸œê¶!Ç@6ãä{ y%1p¿ÁàFà -Ô0Ò©ÆÀ;V¬ ÈC/ÓÂÍ€}áîGš˜…¯r˜>ѽNêŸG6¹1ñ…DŽád§†:÷‹÷]6bد¿ÃÑ•8Â)qÈÎX¸‚¥þ+c˜o3pBÊ8|%ä!«(ë|uÿNÈâ蕃›¹"}O¼ïùãwäõè!àpØÈÀKP1à.JÈÛ~¼KЊ¬¤[$$ÿ˜4?)Tׄ¦O»û‘gcv:ƪr_ɶV D„h%B+ÏÜê¼Ú†bàÑMÑ'ÿæŒs>ÒHÜš€!—·B##ðwWTTR‚÷#n’¦Ç2Rg#Û€o¡/³Ni/>?§ ‚»¢Q+Y£ö­¾r¹X~¤gì§ë¸³î\~…ä÷xWZ9Ìž‘º¨b<´«Ç‰Ê¾®8b–“˜«r?ŒÄ²U­xϨÙc²ªM]ºÍ8aàãôggEªIñ‘µˆšÇËD~7Èq4^¨_û Œ!F¶ÐeÝV  Ä¡|p-j61ÞÚu·iïSvP@`°÷ÑÃöÀIr9hŽ‚F28J°qFµÌ€ÈËN“mY³u%WàûÞÛÈ";ªåuk¼áø|Ì!øö;,Ð/Ÿ}[ÁÍžÛLuÓ‚Ó@,÷µåóÜ…Ì ÄŸxÅ-Ïõ÷lHµ 1y¹œjëX*ÂóÌî&²l_F´nÄôy®±w# ,°œÊîý„,Ý>3gWWD^çêÚYÙjÓ£ï?ÐóÄ«—û¢î[š D27Nw?[:¡g‘ýÑQè|BÄ4M¯¦jÃÀâ/T°éÑÿ“ Vcàߨ`³¯ß5>·<Ñ—ñÔY?uîæ7Èj"çðÿ¿½Lüöº/޹Ng¡{ô"jif‹Ïƒ(*UúÞªV5c‰0þüÑãE€z’w5˜—Ô„s†rR²nâ]ƒ;M&Ùs,ÃB¬6Â+ ¼ýÀäW6î¯åŒàý“ÉoܬLŠÂí€Ìäãg¾¤¦kÌ >Ñõb™˜`îÌž1ð•¢”…ئ*·—lØLöÖï<>:<¡Òò¦¬³þ Hp›Ý³í6U2{›Ë!ûÆ’uv®LÓºC‰f¿8g,AÆÒM£—+Ë‘ˆŠz_aLÒ)™!oGÍAÊl·nQT|céÐ.n¨࿘ 8ËÈR.¥ÎŸëkÿ‹$˜","¯_µÎ-ŸsäS(V‘-¯®çÑY•¥âF…ˆ’'­$²¯€©ïRœÀ"Õ£u“™µ­ÊnÁÀIWìIkÒŠ±-ÅÀ#ºRº+Í6OU>²Ô ÙëÏ0™ºªxÄhXüˆÎ»ÓíqŠ@TÇ}Ыä“Ð%hì$`ëÑbšN¯¶¬­ÙF8¸¯×“¦@ÔœShÌ*Fà™¸ Äá<ÎuìF=4°¯¯çèXt*ÕtýDÛMéÑüÑ{V@ù¬€^L«çùá¤)(\3Ú½ Ð;à+ïE%×[gX¹µ øþZr½…’k`z¾\ß_‹¸ÐÇÑaQÜ~ý†€ÅaHKÝg¯Ngçž—ðèÛå4×%ø+u-xK(i; ,²ªP¸ võ¨9»Ë­8ÝÒbDÙÙð¦ëèê\ |-ަyî¦F5vT¯X™7zîHшà¼Ç]àì ÐmUÆ×Öe¿ñ¾×ꈤ(;Ò6Ö™ƒŸeœ¸úd/·+¢[U}"nçGÖ-kÈÓ_n·¼ §Û…»÷}¯I3s?/3ð”–Ú™û²d,Íõã(*dX¨Ô“Txt0G“#öž‘–aàõ M–FL4RÄ…‘€ñ@Š#6 Ø”.ˆ ãG‚û¨k.ˆé!R“r(:p Œ¨mÉ}ΘbÑHE²ªÑ5‡xø‘jTSÕÛlÄë.¸Ët 8sBû™€c`)7/­´B6ð¨ë硎Ñç^‡ÚTu;³oˆ ¸Œ ×RçÉ´ý & D$ïÌózáÉtå0¤°Ï㙓ØrÁâ[» î0Ý$‡5 í@‘èÏÏ­×Ö¿uî‚›™oG\ ©Šs71ÍZ&³‡›…"ožŠC–Úôî$¬€,ì‚›…B¿WŠü…j&>QcXêÛ¥ÂÍ{w¾PéBêSêCj 4Í—£Y(î 6õ|¥t¤5)ò‹š… ê"Cä×Ü…°};”ùÔ\RŸ?Ù_G3Ò»%"H™!‹$‡³÷+‡Ü¼µ³ó1¯_ºŸ˜`šfÈ0=ëÎ ›l(Ù2Hgàx†Œî¦/2QƒHyÏpßÙDÆØÝº‚ªj\jS¯„SÞd3Y<Þe|£Ò²†Ó>Cƪ¨Ü•v¸¯agréÆ +¨~‡b2’ÏjbZ͇¥Ê¾RñëÔúå1_㺕34,%äåÇÖ¯JóºJ‰w@æað=™fíXë™$kð:oI ìÊ01¶©kÂÆ±ž÷YeiÛPŸTÆFqw<ÕºrLÞ¾»ò¼ïzáÏZÿ)yGxÃgZe~ ôùt±š’²0𹟠ÜsH¿Á"-Æv·Xw!QCkƒà>‰Ã0ðha©„=lÉn/aOüÿ »Ž%Ùu\ùK]®«jùös"ÎýRt¢¼¡¤˜¯@UÝ÷í³U-Š™_» tÈéâ±Ø¢ì$E|¿~R†Òåa´.sä¯Í•c,CÞ¨x²‰©ßµ´ðY^›½ùåžÞ“øPÑ…[îŽåoô ®7ûjŸΦÌ߇þ¤{¥⸵æÙ—ß…ˆDÉz.6î‡IªüÝ_T2 è,ºZ Û¹üÝaÛ\CL‚âÖJ´>"—lz$ŽöOýlqK†<|¸Ž ÿZl´TÙx¢ïB†l#’Él*%ß…üeShÙsÿÎó6fãyÍyô±häœëÙÆUg3dΣ3Äñ€tªo2db±ÛŸ½‡Ào\Òò‚*C>~ùý×k·p‰vÙ×L¾ hSžÊeVKé7.·ÓÄw5äÓœç\–jñ&κÜÁ•c£\:Óó­cú“VÔƒ7®ÖM÷½À«&ÚŠúOâЩ®×Û‡Õ_t‰U9ê )l(ðA½áÓ‡ô[¼åë¦öså]“ðе%küô§ÀÃX ðƒ’lÞd-¾~±f5=8¨ž_gkötœúMfnü.³_?/Y$šÙAÁ ¯íIÏꨧÛ5UHnŠÞeÀ=¢/Pn5–˜†eVXbz;Ú 2-°{kªûÖñ±Åìíy”ÖÐܺ+«ÅZÔêS–”Â–Ê²Žµ6ôVô0àÏ3;"3‹V³«ÊI>(A'Ø N)çJÇ»MQ¥ÕD8ø>ìmý —É)¼«tTêàý䃛Û30…¡kò¯H¡¿a†ëÍ•XN|Þ3bt ˆ{ wRûa´X«Þ3â°Ê)ôÓ ¨Ã:–eYÓt²Ë~úû_€-¦­ôoä¼ùÒêaîl³§yÏý~ÿl¦øÓïf‰Á+ãhk[Ï:ð/rEQ¦ÖÑÕ¬¥?k<¾Iotü4‘?w×é¾VCi)pgű'¤­ô4Ô­Áƒáù}¦›tƒS·¢áUÛ6¸|4$*r¹Ž‹õ‡ÍNç|~xÑéÝo¤r­•qšzÚjU“³í„O|ŸÚ²±ˆÒne£ªÆ køõ)²ªvƒÂÙ˜Äúºä5ÏÁ [æÀÊ€WjP¶ŒÕ¶f1¯Yí8ÑÃb8]lãRÌÅ´fl;h¶5r†½ùuûÈ Ò·ökA0«ŒÃ—É =EȃãAS«×an¡Ïèòºgö– ^»nÇZW•‘o{@çƒìĹÐZ¿ºU¼Sÿx´3cØÓfü÷=0ÙT½¿õ#7—“‰Ùåõ¢¦Ù…´AîG7Z SHƒÜÏn´ÛHWzÃu”YgPI‰À×Y4_¥äßL¢Ñƒé1}ÛcpÍø7¯Ì3ðýõÑè æˆ~n7”ø2ï\ZãÓÙ/¸¨u}ʆâ' `Ìø°b‚n¿Ëû£u¼LV@ÆíênÂ>Ú÷–¼\Ð*ÀùÑÕ%ö¨¼O÷¨8ÐA»SW>Ÿm' ¼SJ•2;°ŸÅ–=ñõ~0è6óÜp¼¼é=*Ì0Gm;1 Y!¤å.N z,èM´ª^ˆ×{:‘âù;¨W³"G7ÒÚ—~kn‚ÉÎ’ýô}× ÷1¯RÛ¶5ãª*E™9ªçaXÆðFñhâû³„OÈÑø çlèy§uE×ßH¤ 6ó±pwšhÍP™jÀ<çBlæ#0ä}é¾ï+íóI0&¼6ó”©c=xý¶ª+h à÷/ `Zôû'|{v­­ÚÛµˆýOÀñ¼eM'q¹N‹Zõ¸S¼¿Oöhn§V†Eà ¼fß:¾MÅދΟÚx£Ö ·â´^ÅbA1ÿB{ÑZ7ÇfÒ[£9‡Páý<Ó´¡Edj˭‹÷óÓ17fÅcË}b8sç(ð‡¾.»mZOþ©)ð~ŒcÒ2¥ÿKÖÍÕþÖÏŒ+ÊØv2åŠjnðväM*½ë?Äßv(&Âà˼Nýqè j&ës Wí[Ê+×ÿÁ"Lxëy©õ†÷Ñï÷Iÿ§î%w£uÐ\I‹c$šíö‚Ò×Lq6eÀÃÚçè ®ØRqÅ í €»g˜À]PÙ3ÆNPà!ý÷V©¨cíZ8M;-ŒÅ+¡øÓãÖ4k?ÀnÀï=·Þkq¶j\u/Z ~ðÐá*К.áÒȳŸ~,R|ë¥_s¬¯²áy^ï _¦êŒi”™²ŸNaóß5цSÑØÿ¶´Ó,Šl|.—ÚYÁžÉ‹F ™!w/†2<¦ÝfÖT•b}†Ì«¬`¹9éiQ3\›]¿h úHT€Ì?±Í€”B³¼ï¥ž­hz ¼evÏqòº¥gVÏýPQàI&yÄÅ¯Ó ³f?Κ¿ÿ%, U†…‹Eü:×\Qd—ÛNWr1[5SàA~”8äcSfl”Ê€ûËÄ-åÎSãs/]Š€'­OàLWÂÀVØÊ€r Þp¡¢j´Bµ“ñ/ƒÃCø‚?Ù0âð<þ ÈŒ™ð‰äXbëG;²|àó`»éà§døDqæ®ñª9 Øo϶5Õd,Þv0ùk!±ÐÆr­¶}½r òžüØ<ù¹’6ºŸ’Ÿ“^ÿ%AƒŸ¾|ý ZK×óË”_Æ"ðòÁÉYŒëξ^ÎÄB †|v ­7E|êë%Ÿ4Ù+|Ä«ðè<[þïOÒêbmj^ôz€o}!NW¡Þ”()aZº¥3'¶é§Y¾õó¬+¨%´¨ÉÚúa¬ñe^g—X â~…Œ5o`?_‰û729ST:s¿õLm+ ÞöŠj’*Õ!a=ojÝ÷x'Uh(óÁOs»©X)(Á§6CkW˜Y‿?úí[À´ëØ Õ‹ž)74íቲ«z4ÞHdí®µ¶_ùÂ2àœqÍ”K#7½@ €:Í`:N•f>‘ðe>›ÞdêÖÔ=«ê¥D>Ìõš—‡þjo‹UXfÉy½žkQq:Èv29;ç*]¼ÍZ'™;/‹Ð>ºè)ð¶_H‹]˜d3¦SC¥ÞNU$ìõU«pC·ú‘§À+ÕšK|J5ù3n« {kt¾k<\WQUl­0ؼî­U4h ï_£µ %_¯·Ü8ëÜp[Yžû¿6ÜŠ†MHhÒànìw '™_aÀ,¾ÒF(`]¤ŒX¢º¦Vø '—X0uõQéjôbÕ¼Qà•Ô`xøÌJËÝæF ¼}gÃÊz R\H2¢ vß|l(ðA­èa)ˆÆ .ø¦)ð›t5蘛º™³‹†Ž)œ]½?^IÊR@Ã-_•Lm ÷ËZEÓI |ÿp‡å³ë~c X8à_?\bI·ø½Œ+›!/ä Œy5cÌ o±I/$Q¡^p®ùŠ­Ýˆ¼QsùÔ^ÀKn§±ñÙ!ï;çBÊÔÝœge[ÕBŒàÿ e|bRŒböIoþÌoZÛ0È7Ù&µI•ÿŸá ý ú´œã¹Í}ŒïZ'pçä+"ƒ«©-Ø„?Ã@é‘ïˆ\bÕÒrÿLÞ ÌºÎõ¯ì¶/)YJU ·(žÍ¸ë…\÷A‹w!}àÄŠbX2ä5ÒŒÃJãû¤ÓãÀ”Z²%/×?IV¤ÊD»‰Áu5pmy?4<ÎV6KÉÙÌ4ËÿÏGvÛ¦AÎ’ám#"÷F&0´œ ë8ˆ¿æ÷/†çÜ?“‰%è¯×œÇŸ6£(G7#¿­wx#@Øý¹ëƒUÆÄ ¼ßM $F ¹³ø (Zñµ`«dݘýß'D¤:שnâ’w¾I$¦hå‹iVPà‹tŽ‚ÏUn®í³ÿñM€>á¯ø€ñÍõûÌ7Q =âw =Žmcsä¡^ºKÆÇm½ô3ŠeH¢ž?neâP* ÿç(GY×½Òu†ü&ž°wøÙ¶p7‰5GÆ/´bÜé{ßê*û”‰oòyû?óeló©þ>-ÉÈ[ŠKRaT sý+ ã€k¯›¾Úöñ|~v2™$¨ …ã|î7 ¤²AQÉØ2TsO·qëÆa?ÉÃHô4×]'Ä¢íŠ@Ú¾Ê<ØwÔÛjGÆyM¿øMs\; üU`Ø  æúCs$íïgSÜËŽá­µLÅ›²³£ŸìÞ Ÿ2Ýß4ÌŽM‰¡7iŽüûŸtž¥ÿQk¦f7š6ûéÇ¿\ô ðrjê å“TMµž› d¯¤•1|ÂЊòf®Xd¹aÕˆ´2Â9®ð‰ÅâŸè0×¹åâñ­)»b>’Ÿê æã-Wô=€-× xÅ•È < lÕ•¶«'n)ðö lØR`Ìuþ —(1ê\²bØüÑ4à~q»åuÞ¨µ‰+~“îVàãOßOúatRî¶š‘k¼¿žú2ã%j\°ÛVùøn˜¡UçJ|ÔÓºm‚)ã0ãÆ‡Ú‰®·ÇišA{‚k=ŒÃ†>êWê£þB 4Ý8û'||(%E…ù •dd„ÌžøMxaæso§z^á[Ÿï·*ªL>‘Põ [9õQÿé‰÷ÒÛó|ÆËÄЕÒǼ7¯ÝòZP*È„=·ë[Ô2cq{}XH¥[½Ñ6¬®ùìÞ2¯©DÀ×5׬蚒ïU±|Œ®ø¦šYSà㨟*X\ñœe}Óf/ó}\e†„#j»‚õCݹì|ävä2¶JÖ±9{â‹X¸èÔ‚§c}è}΀ïÒÙøi|öR޵ϲŸ ©X’Eæ«ò·k¸ÄÿF—¦E±#“uÁ²JQ&©:ãOo&3dø:CÐÍ8~o9¾²¶›3äý'ZrÑŒ½š¾Ñù&E‚ YškÜàaLû”Á< ~›³ŽÏÀÄäFN%ô¨L¯Ã™Ï¥„cŽï§01hrÈ‚ù¤ZÈ‘G_¨½~íûèY9Sà÷Ñ2Ì$ommå6I |Rþrª˜×~öÎU]¯Ùð¼~›æ~9h |“žôæ);%…Íü‹Ò‚Sáq©u­71wÙ@Ñ4K˜¿uxx†Ìš€ yÅO6]”µË?w:G’ü‹Ji¸u}Û¸Æ?4C¦“;(Ê ºRýz·ÖöôF™E1lCºî˜àÔÈZØÑò.i¦ø¿ Ûýë#î³]ë€/JÇ”dÕ]]ÍM6<ïlOM¬úÞé¦s+hìã€WGPÊô,uÁž=òBýM :£;gÉü åH¢ ›e°ö±ç¤Yöq.Çñ“˜þJÑ/…âeþÌ;QQ°[óìƒInó)ôÈZ›ônÛºÕ ËMwâ··ÿÝ“÷‹Zæb2ä37w„F—Y8¿Ö» ™Ù@*=Õje‹8MõwF Nz|Všw2Ÿ™ |kòñÆ=m˜ªÐBäoDXõq"©T*›¹‘K“!½袩“6”g|ÎL¾ÒEæ§@ÀÏ÷IrP}Gä)¨~n‚z×GH—!wæ-&Ù6•Â6…¹ì²ñ¼~SYØ:Ï·êtMe ,ô“VE¨ ¥®‹Âζdµh(puŠà;•bt¿Æµ´íœý4¹È÷À$8€µÝN€ý€ÅØSà÷﫤eø$rÜJ.ÎgnB1å(ðõ°óÀAåÀ7‰Ñu:t—…‹ÉCï;uºþa¡5 úyÈâKó1\IÆ?ÓóxEÆzT)ƒæéÎ-Ý&ñܽ§ë|Q„¼1[Ú#…ðÝh;¿¹î÷Jwât}LuƒS»Šç¿žj«I• dR’->ÆÌ‘O¢ZZ ®Ž7ýæp“¹þ¢jZW¬uÖYhN¼Ò( Þ ÁYÏ2i}>¸­%ÞÈ­¿:±åó¢FŸùðö©'¯S/ñVÍ“ž‰r?{>ëHE „ÐFO¦(þ÷“ý§†Ë“ ˤËqÀ[Öûý£\©Að µMÓ7_&¿;É[ ,³5¬÷\ß3 Oºp´Åf¸±³xNeÂüõkŒë& Ü×w|bò‰Oô!½•ø j"©¼'F£¦ [)®o™î lÑ)ÆiÊžø¤¦Ë©éÁª¥+ë]G¯L<ÅÊkFQ¶Ã@ïS#[ì-•«PBX• ø×q8"ÓN;ú=¼Ó»“Ø•*W‘—90±V£Äûêûƒ:Ù'rTsn®›uOîäî$ôê2™Îǰj…Þ˜³±„ÐàŸ¿‹¤0YŽ­ÂD>0 N´'mö47ù‡¼ìþЩs&üú4ûí¢mê)£Ã :tˆãÖ,œÍfkçÓÿ™Bƒ¿ÿM̃$s^u¦5kÙåãùÆö4–¼øBtëǵ)ZÐAĹþuЮ6~Þå¾Ä"ÄšZu!tœ¹\}”'둯¸fO4k±™ãJt€~nÕ xÿôë ¿Œ6?ñ< bàVÙ7j˜Å¸`}úNŠ´ÿüIœñšÙ Íj†;¼Q‹Ä5›ëÑúÈÑ!Aê~áºXaµš5~Íø@3.QEjê¢,šuÎ~ú›ê¿&…s?רìsì ZÒ‹Þä@WÇ=:쫜7U¨ÍQàÁ65h_'¬´[_ôuGÔçnï`ÆÙn¦˜(ðûð•`°-m_°­³·~RÉTgß&ÿ³e×ÌÙO¿¨˜-t_VZÎÒŸNðÓ¯ó'Lr&ÝØ`^öøÊºlŽ…ÝV3³E…]ÄW¢UÕ\…ÕÜe°Z a(wnKÒ¡IGw›¶’ƒ(æõqÍøŒl§®à:Ù ©*öš>`§˜DèùªðÊœJ%ÁI¨8ÏS½(Æã¥• úë7èh€œÜ ˜s>8Gé#göÑÿ1ÆÛ¨øÀ}¹&¡Ø4¸ºYMü|]Ù’ì¦ü¥™Þûñ¼ûDÌý@Z@ H᯿,URÑÝc;ÂOéÖ AQY™&DÔèOâ¯Iw…[îæÅãõ˜êa›Ø¬ÚV¡(ð¨<ð¨A]ØM{l“ÏÄî­H Ü4ònñøz%ò¸ûÝe"úÝs]8£À+Q5ïåÐþÐŽå=•¼;Eh#QýÌÆW0Cà.›nïÒýªO;U5â‰ízjà OÙ©u¥,7 ×À'¹|¹nšÊX^|§ëí!ר9]ïo|ÔrÚu]3MÎÕpº¢–ó©­¬Ú­uÑHPàéï©m}Ä7£ÀäÚé´% ã6~:´Úhf²_¼d”øÔoÂì2®|+³¿ñJ=6ÁbhŸ¡6}I7âûåO7a0¬Ö}S» ‰fWâÚ RUR½nºª,ýÆnóQïž(Q÷>ÃTÙj…$ÿúÌøŒ¼ªA§dã-÷Ç:ƒ—î»ð”°sFônÛ*m(ðLLM›t«ê·uí– DÛ+¥»AšV… †RH¾^¤H£ˆÿÐÉI-¡$”€Dó Dƒ¡¬€n©*='ùÜKq)«t+1š'ùÃP9Þ•š¹ÞÆM%ž¨mJƒ¬âÆŸí¬(ð¼Ë$•Ø(Õµ g%h6œ'yÐJFU ¾ñMoß÷Óá$ùu…VYk×[m›ìo¼²Dûl¦‹ÖŸ£ ¼Ž-MÊÍê¾dƒÝØi |[ChBâEÅæÂ/Â…ŸûºDçnŽ,NX‡£>"n¼^„†³²˜}x¼rºrû™Z‚ÊWó$§a•Ãížv¥Q÷Lôc¡)0Q~þÊR“¦mà"ø+ôH{bà…ë&Ëdo²_<²”HìUÔyl-hi0­ëŸŒCñÿ¦Î°u£ÀK,ÏÕVñeaï³Q?÷ón‰¤KÎcb5Îðó»íWŠf\Õ“˜dâßrdŽÚËÌØ‡¡= €ÏcÍTиg3ólz!³þ•7 ¤K¶N“÷÷óâw®ˆÁ¨³v®d®ÇÕuiM{u!m¾Q÷½¿¡§›•Œi™öYiKT|5Ú ÔÁåqÖšu+R kPAÑ>¢ø §*H*vI”_/j±œÖµ—ªt3žÞ»4Û¼KóDÄMòæË6ïÒàé7àôü[M¼Ë½¿Š÷ÃÁp°cÝš‰a‰ñNêø?±àŸ›þ$Þ+ã„´Ä{îrÉýqËîºB/¢YÛ@4KÐ}¯¢Æàó`UAÔTÕ“mÃð¦î~Ëd UôÂù-sS(PÀ3Õ^LIÅ<š-pö‘”s¿¿è4Ðb#õ¨gÆ& ¤œ}¸M¬j¶IcýæEYÝêªg…SK]Qà…ðJá†PåbÆþzîyïÃN~-ƒ„IO7z )€O2}$Á €÷£~Õ.à ÔSü¢]>Þ»¦ibŠ©EgÀ'锉|ZÛ™…)<Üï8û‰R΋¬ÛjRwÊÙÿÔ"Ë»+…\ ¼8¿íÅ¢Åv\±!–2ˆfè«üég4&ŠdÞtѼ(?Ñš‰‹w¢½ø÷ï¿$ö“^Q×*G^ ¤ ÈÓ˜X§»¶“ò†ô¡H}­ð7µ}Cîuç€ÄtE¯þt#L‘!‡GLBB>Ù×ÎØaeùØŸD´©IÁjd}/«1ŸGhÆý'U`cب:Á¤iŠ%{º’>4"þZ·Óu6åàJzïlˆFÀZwlXl—#Ï© áßÐ[u|cÅ4Ñ ß—wÑ(Áµ?„1WfËütÍ[½/¶Î/6|K7s‰:½N]®›Û–=º=^ZôqƒrÜONÑ(¼§»?ò½qg%ÉaîäÜ(–weÙ8;â¸Ã7ï|Þ‹yâý‘qe“Nª=ÉÞ•¼Â|ûþÈTÖY‰ÉˆOz«ª, ÏsϦFL2âÔ`Õ´OƒSwèy…‰é3°N9ÕíTn÷ÈË$žZù GÁ†5{á_GQ¹†¬Žs×JŸÃ3—!ã>±þE5ï¬Eè-åËÿ©ÆT9ÇA¶JømƒÌó¥d–ëЧÆÖn9ÇÓãë?ºÁË¿GΡ©K"£èVvÉ>¾^)æ¨(ØÉb)û.ûÈ•úW ︔Ø(ÿø~-Tƒ¼„JÖÍó\P 5oI\Ÿ`@XJ¿jð†åñÉKdcײ¶•'^r¾<EóÙ|ç¿(Ù0 Ùßxû­½{D›;Þµÿ–öãôªN” Æ <åú‰ç-u;7¨/ÀóÇQ#õ¡ªó©Ý¿ï‰¥-R¹/:§2°]MÖkÿl&k Ì«!1‰W>åõŸpçŒR¡® ¸x`ë]¼^uÔnñöÓLN»øvBèÚÚÿjö7Þ>†”º¦_æ0ÎÛ§YR:Ó¬b|Ÿf‡q^¸‹e»¦vÛùܲÓ(à Àçí„$¦ì…}OAe¡Í1ÞÿĽÒ^YOlÝÚyÃÖû1ÎÛ£3´Ô3Ǥã°‡<^ÏM%؉øÕÐÊIoxQþ¸¾˜]£‡õÄ—¥ØXƒÄžÇ5W ¢’ßè”eòˆ)òãú~‹€  LÕFÿΩÇw×—5óšo/K;Žš‡®özã·£Ã;æÜ@àh”R¬VªœO¤¾½>Ÿu·ûpïðFÃ,ŸYŒcPÖ:ûŽæ1µ.Bo#ÖÓ·œ=W¢8ZPpêTÙô8˜wù„j®Œ½ßv¹ø­·ù– H5 `ÜHÛË¡ú–Êý‰Z]…€;(cL£­•z¦ÀÝdªŒ-.ÑÁÍgSEï÷DC7RNƒËª ×écÇ”æqÏ®µS{hù¤|J&ê‚ï_¦Ž_F_æ~ÔÝ¢éFjäf=ž¤¾óÜÄT KašÄ̬¡ÀóÌZf˜´«dœ>IéJ]°q\ì/ü™Í³xîL6íšé‘c5Ràó}Bš8!Ý1!÷Öˆ3²mûv³g§š¨ßCfVûµ/›Xü’iøó³B“dâvûí½öÛ'<ýI¥Âr ÏKy×5fņ$*æ—Å\ùÓ 2Qž_™r6VÂO ÞOš³&Ièùodgƒu£ÀëGàhµ,DLÖc?Lm—ܧr,õ=»ÅLG?­¥ß{Ð\àã— } Ø(ðIô k¨ïîlQ0·f/ü+"¢.TÀfÜÙŠoE†ü¦ÈCm€Û‚‹ü7O¡Ùþ›Æøy¾²Òå¿yþ«ÔÆJ¬=÷愬ʳX¿}É7Žëû¹7'|ˆVi‹Ï¾Ï÷íÓÏӟͶïû{ªä²ŒÖàì|"ꢠÓܤ» Ç׊¹@¤ÀîÅÒÍl¬ IgÖ`SÈ“Ü\ÿù!Šû<8•øÏ£3àå—ÉÁýäÈþFJ÷Bq£ýÂå®®)ðvh©” ¥2 Í:­¢mÚ‘Jý7]ìËœ€ÚµÚT~>=O9•*ùžH0ù­·¯ÂžçÌh“¥· O•ªÀ Ò Bh¥Agâ,R5¢Ø¶‚·ª­ ¼Eæ4ÕBlª{ŽLxýÔ{G ¼e—)üòYJ½dH=é)úA¥·V¼žÆmÅ‹™ç™tUîW³Ñ¸«s3[ ì¿~Úæ£Ä^¼¦ wœ&fíExá_»5Uzx¨Öv^ 3ç?ùý«Öö\7øW^2ÿ,–Š·‘_\­ÅT3QàTŠj^³iLàº^J¶­ZŽ¿ iNv+p÷жlù¢a÷¼å•¢@§ŒÃ »VE¥Ü@{Ñ:f¼ñ¸´Ã<¨²è^H7Bêúí6•Æ(Ÿ—Sàu¯÷…¢[ºq)VSµ!ßãy{9b@s…?b,]W¸ ÝTÚ4ÑWá‡Ë~dµ+´QiÓ$ÔŒ2¶? ôìˆg÷ý*Ì«t£‹fã{ô¼¿ÑSZÅWÆÇQtmOWB5¾°¬‚Ïx;¤M#{-5¨G‡ ÆÕûâs¿Hq+ª¤nÁ°3ƒÚWö‘•ç©å—¬iñ’ûyÏØn¥4,›KÓO8êGÆ¥`;­(ýIMQà)Ó΋뵞WY ãh1<ß.ÁÚfsÊ-®[óó××+kOÛ"Wî&àRœ¿¾^¥Ü ™ÒÏÉÄÒª¦‰‹ÒøÛ¢ìR¨:^ˆæ[6Õzšœ_å3UUýÙ…”·›ÚÖÖõùë…ðÙa4ÆjŸ‰ŒÏÎD ôço๖@Ú5–i7W Bé™(Bqö…¡óéûÈ6X×g¢ŠU˜ ä º Eþ$õ±L|¸®í|À%Þ2`jA @.—QàùÂQG(~ #4(³@ é™j‹ÆË-¤×vñ3\ Û@'JˆMáÞg^Atrn[ ̘³€>TvË ðBMؽƙÙh R\î$}¿¦ösGMlkEö‹·ƒ[íæšs¿% ð~(äàZëš¼Ô¦®õiR$¾°µÎþñÙ/Rz:ã¶be]׃âùEQ5]ØGšB9ø„³_ GD_#~n9Î!(ðœYŒC®Ùú¹‘ø7^ÞLoR-bn—ªWí¶1 üühé½ì¾dßúp7žym ß;]_>á¢'Û°Šà<@Í@¿#šÉºM*Ig L¼œÝºÉ xù8æ£öÅõªŽI‚ÔÖIÅ3à-Ö;Ðy`Cwr›–λµö»`Õh[uø 1<]WjÖå¦åö*Å0¼M•t!66uUÙWxTúR?MWIÿ7Ñ€g LÒ«fiÆÉºì)ð’ãå…ö@ú#PG×(A'ÆÌófZ9CNÀM™œÚ#·0Íj$ºsðN^|BÿzÌ,F#q>Þ_}‹ÀÓKníì4QàËë‰ëÚÏævâÃyî=úRâÆU÷ƒÚ$“bvxɨ¡8ê•ûQ›¯Y*+¬¶‘ ¯§@îc?6s±´l=ÝãÏúƒi:‹ITë„/ü‘[èîÁž[ÅUã•¢ÀCP¦@¹âiQ“²ƒU‚ÏT<-iÝF`é—ìBÚ ™1ëì‘Âe¾æ RjjäjüÒ©)(ø +µò›ðÐwÝj(ðþÎJõ‡ÜQ®eDzÁ¿füíQxÿ°ƒ-ËTú> ||ØÁü'œ…ÿ†Ù`âÕ@¸à…/úÎÜ¢˜RvbÙ ÿ:„Ÿ*À «¡“åü{!ÄŒ³Jmb¯Ô‚öÆ¿ð_G^¶S†Ìz&R §öV•òrPT«*q¦áÊ:[ÏùÓwG[Ú“Ë›¬ØÀ4f²€¼QªxÚjµ?'6ÂU˜:òN:'¡ÆÉã²ðmþô£À[ù’àÁ:öþ´ó2ÕŸ»ì—À++Ι,8ëçìéèÜ›|Oë&9f)7¨ÊvÙû<}ç‰i¡qY.þ]ñ yÊB?¦9¹}8C9”7%—¦/×la€ÆT–Pkן}—¹dùê½¾Ê_ûå˵sÜV<ÿÍÛ^,¢9l@m™ú×òž‡£à˜ÿ;UÐŽÈÇçàá—ºêq½ß$(ýÓ ÝN6OD y ³˜êr2 ž3ñ¯:•O¸œ:ç0¿ú>çüòØLØš>xøËyßçLžíÂìÆôõ$xÉ’ÙüÔ°. éÔÿ ;³eWm% ¿Ò¶ÁÓevAHˆ1¨òôÑÔÐÂöJN.rªþò!D«Õýý%ì½/è0៿ 2ەठé’%D)h˜íúº`!B4B︟꤂î_ð_^ôß…îm¤¥e…/ÀÄé9€Aí¤[hÌwÓ•Ì5š”—à ñ;ÔŸ„^žTë!Or9X¿¯”S†„à°è©éŠ©™¥ßñýñÕ¿`ÉíÆÊg5$cé_óõßþ²”[…9c[ ”7ðÅ`îä)(íZTØ]ä¶$Ê{’„ˆÎ)b±»O^§£ôH_ ŸàMK1té~¦ûl¿Äºð‰-MU&ʲ*ˆ­oŒZ‰™tpGwd ‹ç‘]á qTûÞâ~b¸‹@§t!¦+º™¤‚báê!h(¼q}àúØÅÐuXPÿüAŒc??kO\…9¸€ @Bw-Ýcõ£×ps=w¤W™ý__±6ýÓw|`8:¶ŠµÑÅ0»’”>þU¦ØìµÖ±Ô »fgFO …ÍZo„@ò嚥ݴ…ˆhkÙÉŽÕ²‹V?²ó:´¥ïiïŸÈÒÂ5¦å9îœ:¤6•©·‰Û„?Øÿüþ¿³Þ¶¶à£i þ8ü„"n—YÐ#FŸ‡kzjò^ÞE4^?Um©•wEaöEx”wEaþ½¼«Ü°ðö¥¼‹˜ ö¡Wtjò±¼ >6×g²ÇóÜ¿6ÛKlÓ¶/ÍWtj…!š6F«Þè–´XøV0æ8B¡` –”ëóÿ Æ"}”—£¨ˆ¨lU¯ec÷Ê ¦î+u¹Ø#95œ2CiÀõõ~‘½aŸ6™‹T˜%§nêÀš¾)ç#f§E%ÐÛ=›ˆS¨6¶›eÈžåg“§O­l™ˆ4Ñù Ë~%D¦‚ñÄ7Jò­4käFfÈLå·‡¼ù{q–²¬[:Õíg)¾Ö5^…ºU›fª4€è2d}ò—ëùâD÷õ"ãH£­H†lEÂ&m#úQ”+¯±ðúA¸8a¿6 ³=­ê¾€Z”öÕ2|äX˜c.yèà’‹¦oÛ)¹Æ#3rm4„Âû{µÑ ÕFÉÍ<Þ«–emÖ~æK"|¹½"V3˜ÝÞ0™\ã JU–`ig#-9‡R• mkÓ&_«â ˜ÒGs9ÐéxTujì„低ë¶|q‰öŸ]# 7eU+,Ü{$Èî|ÞiSêR÷Š`aöƒ+üâý\1ãÒeZÆr&=g³° _ØyZ„€B¶#{¼—–ì¦9 ³PÙÕcNÛJÚjí6,̧1³•½FZ޽Ý0aá-Û¶iµ¡«$ÕŒ…÷ÄÕ×G%#³ž8›)>¾šC þôógs¨ʱ²ç›9T!vs¨r7‡Ê°‰L4‡*ÄnUîæP2‘ùhµ—c!™O&[›‚ýBöJñ2ÁôØM\C\‡¯î ÷¹DOÂ… …•Å–(sÔ½"¼Û*ÙP.œ¥Ê›7øq= ùb bÊŽn¢¼£ƒå˜VbÌÎÝ¡P±‡#;Ì-B÷ÊÑùå M„Ý‚%óòòÄö¾aEœévúS¢|½§ Ö¾{Cö\²mØŸzHïb&Örµaá ÷<Ÿùj*Ž…ÙG¡)ìà æ§f»P3bw#F4É/ÞBrç/Àø›!b–}¹O޽¸|Tã,¾ ‘rÆÂǧId7½xí¶ §^)7‡lèT®Éð¼Þ ¬°°¾`‰Ð¿؉ vûvtº;µ$ÊKZ‡âmTl +–>Ä+žB±ýÊM!·= ‰2Õ(¡cˆ‘²í·ª<ÛÜÏêÓe9În“ŒúÑTUìÄv)š ÁXlÊmƒ¯Õ!;KV5´ºÖ æÆõè‡¶ó·Ø µ}X7ûe¦ÖØtv }Ýn Û—˜ìK-«0š!¤\u ­û—~µÒ^åÍ¢ðhwgS>=9s=6+­òìlZiÉ6vpe¶|À‘kPÈ Q¶ró¬÷7"?ñÀcx#Kû‡mˆ1© 3ä„;/dß.²Öz–Xˆ{ßa´âóVSfçÛŒ…G€în·ñZp­’k Î1ÁÈŠG‹g~׬݋Õ-Ý3rRÐR«’ÎXxE-gñ…¦—› =Ôê$ÎÑ6ƒÚç,7 ˆØY"~À#öÍþ¢è+3¯XâGïÞ·Š|¢­¨7! Þa/½¤d2Æn£°iB†ñYGýÈÆnQ¬îàûp¦òM± li {™c¢Ý*–° ád´ÿ11rþ;6Ú/ÇÂìx]e¤XÚ`ÍuY,ÜkžÆJÙéÁk»cX¸—ÖyßM¿¤u³#²LM“\ãW¸Œ”°D ýOài ' ñŸ~‘ȈïÏöû”aD'ÍŽ¿È¤û™“A¢pÂB?à›gm{F†«QªÎ¾†°ù¼]ß:ªBZ óÄÉm€SÀƒýTÕ˜ŠÌ$Öuíš ñ²^m|Úéf\¡òð`¿ã6;7»­Y¹6PÐs ÝÝùɶÛãÉF6” än·wœ£ÖŽãcF; q;r»¿ñ"B2Í WS®ÐXxÅ$É2öº ý@êÚHn)ÂÛßøqÔÌ€ëý¼ì†¡. Œ~q(›u‡…áÉü»3Ë}âTJ-u/ãÚs{&Oæ8¾ØTcœ‰Æºbáõz‹U×’«˜q¹½ÆBDKvU}Á´`*k騱tÞ­&n/°ßú oHë·‰ £zÕ%×x?(Èo=êmj¡–ñöLëûm(pxÛ¸UjÀ‚6»½RÕShi I~CY<Ÿ°ñþÅ>ÃÑòUè%â¼²ûÙü(¿ª¶;J^¬p rOá[ŒUè8ÝÔhì½§í׌ÂÁÒ¦¶®é‰†œ-‡‡5Ü/z¥ŸeI¤‚üüýêú?&…0];oÕ„…7D_tQ%F¥\'´ÆÂûáA <ÎÈ¥°K)|¹î—sçn.\Çqk¼žiñËU×TU¨bÁxê˜{ G~]7vRÓÅÜÓ=ÿ˜{’äžö'ƒÈMÿâÜ“Òf¶1JU÷<=0‡;.T°¡Ç<Øx&®f'ô³kµηz^Ķé 1$œsÚ¯Agµæø˜ÝOôÕ½PXͺ`r؈…yâÕ†ÇyµØ1ˆ ôóa¢áAÄÕÔ6v±€0F?‡ ÷°˜É‰TëÔI:NXøÀØùÖö•á†ímvwÔ­ä×Ç2zLÌÓ ö|Ä=ÍáùÒQ†¬f哊 Ã(¼¢Ú͸‰µB½NÓÞzu¿Ÿ¨Ê{A&+XÕš&2¢0Gž¿€”XI?Œ%ámw€Ú…ÆFÈJ"ø" ïGÐ Æ(m%a>°±BXšW2PmÊ… Xø„IAãº"ï¨ýèÔñc¬OæésI»ÔXx^qwq—$´ZX¤žI"÷bíÝ(ScarBWcŸ5[Ý!t¾’@Ó %”­pÊ7{XxM+;CÉdotQ—Pÿz¥5ó¸©6n’?Cý‰4p»‹Sçì#¡+äþúP3ï”[/]E ¥ð÷שÑ‚m3ë¥jûï: ÃSºv ?Rª Ýu~ÍÚCYç#ÅFRUN¸f.gQˆŒa_謶hAE›\ãí(Ï’Ñò‚Ò‘‹–›iÁÂ;Â/—±Ín]³€f¥Ç¯_¸7?ºØ@6pêö@Íx×1ª —bì¡íãÀ÷»v/C¸ëNªD˜áúµI e7)ºm¡ãôq9ÌŽ–J·D²–‘ª);…³Ä›ÐûäáTK¶Ê¢€›¹& v×®úñ6ÙÚµÌîA:,¼bÞXøn‹ÙŠÕ4 <÷—<®ÍºoË‚3ØT nøo_'Ãâ/RÙ”KAŠºÃBTÉÊâ"5j»7ÓšÀÉŒGa|¹¬Pûáõëyz\'Ê·ÏøýõÈDO»r†ã§É}äRBŒKÍVóÁôŒbáa™¶7_Ó¢Ém …ÏogþÝF3QXÍo¬„Hý&2–#éǸ©x¼¾*5§C¥ÇëË¡Rs:Tz¼¾*5§C¥ÇëÓ¡’+מˆ;T""¹ÆÏ‡JÜ*- ¿*1t¨ôx0ÁE( ðµuv_¶ Ÿ{Â=”°‰Œ#IîwJú¾97ÍŒ I•„âLÌßýø¬áåÂÜÏ:Z:dÏÔ[ Y ×ÒY ÷ð^#nlô¢¶n6L´-ôT#nì¿ðUè=M¤˜l˜Ûa!~Ö1õ:/Ê.r…ó,o…ÆÇh\·˜‰‚”Ýó™úuï[{¹ÙéXv‹k|}J 9!ß&ç› xü»Bµš^¦q-û:ùÅ w’GXŠ^†Šw³©°e†E ížÆ¬¤0Ð?ô|%'¶tÏhÚí–Y[Væ‰"ÒHÐ køX cßOUÄ*e;àqçÞÅ4Ž\–E¬\@ ÷ ¯¸ŸÞ™*Îð×åÞXq_)vœ0è*v:Le ¿xýy ß ¦À¬6Ÿ7óžÌ~À§W5fŸÙëÍXlÝXQÛ‘,#ð8C˜¯£«­ò°«DZ‡ÖÞ×-áAœIä@["¡ñÀÂ÷ZÄÕ~œFBíD}ö:›IH}j3wm½×Âc„Ö ¯0>{=¿áÂggFT ¯Í éëù¯0> óOœw…9ïQxûÎyŸ4~`©zQ®n ¢”×ó;^! |†WnfÂGaŠFZP%êzi°0ûÎy׿Ÿ8ï=æ¼GáíÓ]jÄwýú„WŸŸé])ü¿.Hürå˜Þõaxv |Žè]Ÿ9ïq›’#z×ç]!Î{Žè]ç»®TsÜu~Â+„Â@x…ð9æ½áÕ„Ïì8ï9â½á9>G<°3ç]aÎ{Žx`û¸‘ã©’Å2—XxÿÄyï1ç=G<0x20Ã¥’xÀ/?áÕ„Âo@øóþ  ãAù>ýÍëW_°ëÈ]öõñÍ>ûzÄÎÎñÍÎCÉÕŒ‡ò(«ÿl>gàELãH›¥7Ÿ3ªSKDYåÌOú*KcôØéš(,Ìpu`(.¨íS´ßCÙ89B‚¡ö5ï®&ËNW\nXx}otvBC+-{,DDoX§jYhi¨Œ®»ùŽC‚~2Ö¥ ¤Æªî±¹‚Å.»›jj»Þ:…Ù_bðûÿ}‰7,<‚0ñ¦«ëqèÕþ"b<æïæ†èµÔixÍ±ðŠ „‹P2Z³‚®tÇ ÷Ê€`Ó­ÝX¹.5bdbüx ËJ5gÍÆ°ð†N}}úJVS9YiCæ ‘­¬+Mñ1Ò¼6Ü•6Xø8Ä`hiWQ šhžg²ÅM{~‡­©Ð¤äE‡…W$¬b$§©ì—¥ßŸõóÌ퉙3»ÔS1•TXxUBVÚ}¾¨;xr|N,Dø7”cgÅhìJ1I»í‹Â×ùf*˜=”8ƒ¾ý_§› F¬áí’6ƲSvοèÞ0sçùAÙ929>;äŒeÓéè@Ÿ_._ÜîÙlüðÂYŠ#&ØxQ¿›²å*V°sD°ñ鿨ckGRR*\NEb!ðØ%(ui¯Ñ^b\H/×OÃó. šˆùâ>^ ˜Î&D2û¯H~ñÓì‘rÀ³ç`¾œgŒ³‡`!º™X©ê¼FÍV9"F ›Ö¥˜znâF.¿dééÌB6<ŸYÈã0(,<’HÞУÕFÚ“!†çØ$m |æTkÒ̓ÁÂP…àjªÊ"’l¬Ð÷óÊÚ ³SãwåûQ§v-6ˆ^Q¯ò_¾cÅ7õ¹?m¿0=% –fÔ:úY_×Ë=iÕÃÂÖÆH †ùå~ê§¾¢TúT…–Œq>’Ò§*ü'É í*=ÿv­K²ªÌò•flížù¹`E|ç@/xc?ýáRhaϬ½.ÿ2lQ„ª¢2³ï00sއ¹zp¯h7fJßÌûúªqîÍìbß”9B^{!Oõ=S÷ÇÔx] ¼J×ÝQt\Fi`Wøü¾`…Sœ]¼nÝÚ“Ï“@/&-ÚŠÑ{¸@LQ|dµ¡ð®AwíÃ(¡Ç¯,nòÁu"?Ãë¶óF£¯zªvÌ+Ä4nsçpÀ+˜Ä“iΛ©¦|„c$VˆLü=65{Ú¹Š_ŽËÔ{?N 1ý8`àëÝ÷râ¬nëîœÅ´MC<Ì줌ßaAj€ß'+âr&5ísuHüã*ú¦r§›]¦N§•´@ò€ôoÆ­øtléÒv-xß&dq¼3`õµTÊ|2— <2Ýÿ‰}UÖpÊ] ÔK‘½ÆÏSÉ›Fj]8“#²ïÈÁó)T])ñ¼K¶õjÜ7·±£CË åNAôBÙÖmÙs•ÁÿóoH†d2P…8Ö­MOéóÍù;™LX«IZ­DœÝ(NÅ¡SÔÐ}Çl›¯þÆâ‚ÑÒ}í)1š D”fZÌ®„’Ý­0xV¼ÃcÇ­]í7zB<¹5¤C–-„yCTPÖà37¥ "¬a}-—-Ì áàÙ]†žì|xëoeéöv‚Ÿ~úñ_ý þ­¿!Mßò¿ú ,~-E.©Z‚Èqö¤ó¹íÛäGØŠç›m´Ð”«–½6bOW|Ý(©¾Ç€GO%ku¦ÚENáòûQ7Âe·&:F™ÿ‡zB†”CM1K‡€u³!†ä8RXSä²­öb𬖠Xe½Uá w»¬³¼Óˆd[GÉ\|]Ä(uªaòLf’«KFIίcJ9•û®•ÖdÚ²Ÿþþ‰TC¸Ï’‚bD@6ÿBŽŸ¦8Y—a¤$ï| *ôѺõÇdÈlÿ}y·ÒaÕGºÍ»PBx9aÿœÉнì1°øé “ë¤f | è<ÑfßÄJ“5:KtÀÁ½ñ¸¿b¯„¦£Ú1°BÛ"ΣܞhvÅçO/§WÚ}ÌFýŠ1'8 GyÚt\ìÉŸ €áu[¨oÆÕÙÅr½>vË üF@hr”>ŒIêHJü#)ÕÖ§)ƒ×ÿ¢î.»lØŸŸ'’§ÖîÛ˜[÷³ÿ<+¢0…V!åî6(Å@U ë ƒ¢:Íå»|’×ÎgÍ:ÎÙÌøD"´IoÑú—p´$C>‘ïIÃA:p¡‹»Þ$¦±g–l zÔ=[6 ,~2 Ñ`ÄÀSyÓÿt\Q %RYiËD©›t¾3wò躑@Ã!«,´ž´ÐðÑø|·è“¥@v/Ô *bû´Û–v=ítÉ€§xtí¶œ8-ÇnvÓ£] €1¬óƒ9U]6I…XG0VKüãÝ| 8Rxó•!?ß-):ÕºÄÀ)Ú °.Ô%Ôë®f¶„<™±Ñð! Û놂}ùø¼;ç€ óºÞõP§ãñy; NÉ˶n¢7†¤]çñ™9«yÐÐ5Ò‹vÞ9¶ÇgÆô¯k0Škû±oy³ì+„‰"k/¡gê~šŠÖíàÏSúðC:´ëÝó÷©…íéq³‘ G¦ÇÓÆ,ùã‰9þñøøÈO<*÷ǰD4ß&‰ó faÔ)£} ²…ŸåžÓë.=wϪï2àO…åù˜Ú¡[  ¶D §b8]Rª[gnéK¬»%'„ߥXk%âùŸ éaê|q·ß—ôÀ_7 â·5w1§æÇyH^ ÄP#ÐÐÞÌ&›‹óüC‡¹g%úWè¶åØ´Gšf7£:UݶU+z(¾—åãûÞЗü‚†~ö’VÐäUžlrä$ÂrÂŽÉMÍiX`<1ˆœ\*­§fÂÀÇ;áRJ3˜Î=üK¤›ŸHTбØÚÀ:ž‘{lüIW,~iüÑ­îÆy–müS?mü±7`‰Ô Ò~L(õ:gÀO(Ë»MvÊfjºFõb¶X C:H|;å2iÒôi(7 “Ó£ŒØ?€R^¼Ì°Óè5è«ܛ~O™ôEe´g=$Ô‹©‹ÆÅNbÄÀâòqh¢sFÛh6ðfÔ \–Ï\ü¡i OOb\­Ûµ5""C4lõÅgÖj;(p*àOg,µ‹|m;=ð÷n‡øåÚ¹x`WG,2EïhÙì½™ØLzŽ÷¯µQè]ïzíh·ó‹ÔÒïÃ…Tv‹©MÊ—Ê÷4(¾™µ>67Çö´â–÷ïšiwìu·Pˆ$|R{òH»2bºÏÝÕó[ciи}†´\3x…ÕGžüy©¿Ø’5OÝFÜ,0°x—ƒlšEM”°<àeÛЉÚÔ£Ttlë ˆ:­ôÕ+e¦µJç’ÕgvúuÙ{ù†çÝì¶0°ÀÅï¸Ø[‡Y]øÁ³+B›wPA†ª…ÛešM´ªNÀ"ÓW»³m»ŠÕð-•ªG¾‚` ‰âDeÀ«û¦ag³Y¶Å4Ð^RV› îþ”žu­ŽeÖrÐpëú;°Â«Yü\ÛA ÓÀ§ fxUæ=Ga5ó¿Ý1»ˆƒ‘uÂÀS\©fI€Y(©”ûi`)1ÝÒæ½[©‰’džyÓaˆs™¥bY×”¢Ê õƒÿ¹ª?­d.ý–†æWŒJ™þŠœ_W|Ýì§yJ©Ü)—%N¿ÂcàÏmç™ëY¦`I©~Ç‘‘Fݰy^[‘&Åw.?çMÚ¸>®ûØÉÍÂãy~¼ù$ÆÏÕv³ÄÚTcx~¼«9G׮ɥ*Ü}ˆ0jL<ô‰±Wo ³‡1ãývI·a`ËD÷Lû¬:¤:ìóְ¿Õe4JšìbIýÄ¢ÜÑÞÆEc`uí ¬ ÌÞŒkˆ‹j>/…Y‘Ò]¸5ß}?K†¬ð´Œó×OKA9ÝX†|þ®K‘jDˆ‹û³ÒÅ Û1"›þ¬¡ðë7¥‹\À¢¼¨¡÷À\£¼¨¡w¥‹”.2àãTD‹õZlbG+Ìn`ÔˆŸéWµ+‘}+ºXÒ%b*þûçO”óÜ©t”‡˜Š?í ø¸–h‡1#ß­°–® xkQd, /vÞ4( ó ŶYÝÚ†L<'Lóz¬9ÈH ¹iòÒö}¶klÚê^ü§Ïs ÝãD6ˆ DIšÔ3â»ÅÍà˳W甑ÙÒšã„UR‘`gž=J2ÖÑ*ÌóR+âÐN`w¢\ʰ+ŽHÔ€ƒ”ƒ‹úì0±³YïõfÂòmÔÖZI(í6xxŽnƒßåÖÉÔ¡ô*¯¼&ÕÏâÝÔk¢¾×m—åQ%Á} SëæÑV§ð׵˦%}¨å0‰M€ ŸÙæ'E­ô8Î<±^×.û£D‹Hg§/\ãûãk|"îðÒLÆÁš%Ÿ7rß[ÁŠ/¯×,ÕŠ?,»[Áòõz§âµñüÉMîÍ ð+/X6!® ©€Ýç'ëùQC/s¸0êÕ%!ÖÐÔnõõñ+p À6™ÂWŒ¨¼Â—il@'÷ñ­û§U‡]u›û¯,edP¦2¤>ø¸÷ñWµô|áh¯‡j©`@5)÷1È$°ÃóÒíG×§”êë&BԄʽ ôþF‘qNÁÊW‘ñ\éÙ«ãï‘w‹ð IòÏ õÜP!v?Më£O§ˆ$é“͸ï²ÁÀÇm0í9˜]eÀ¨`jÓ`bÑÀŰü˜S."I¦"VÔÉôD¥éqI§|Ó¡Ž‘—Wº8ÄdÒŠ‹H’aÅõ̧ø)Ð Mh¯•ˆ$c9­Lr—J7º­³Ÿ.“ä°×QêT®ÒИtŠöuÉ"‡ÖŸ:fs&.úª1ð™ Äçè3‘dV~Uo&±úê‚aɈœRoÉWuëÂŽDáÌÖzÕ[:_øªòF8 •~ë'žË|>FIµIó‘ +t€j¾]7s1È}1>Ïw ,@÷®[=èôÀßäÕÜÔL÷nìÇqËÈyÊ·ˆÙm° ³W~ÝÅœ®Ã»Îeø|K½hß·¨ tý,ÒÎnë„Á|ßÌšt–´ØÙzZ:°ÍËïâÝM ¼æµ·9ÈôÓyBN’¤v«õ.†mžÌ‚ˆ’ê>mÛô½iëtèýýȰ}ñ%ì\¾yÊ-)|;0_ì׃OÞ'º¦‹oT5Œœ›ñ‰óͽ#Tàó8¹?íðu¦õy<.\æLüÒ‡—cr¨ó¾jØÕŠ¥®ÄÏô*æ¤N*æ2s'Üc_00/XF·I_°Tv¢òû–fÇóWŸÌ;3Ì%’ 3)°Xír7]Ýv5>.J£5§NRÏä ,ß;>w|%aXÝõ=|+XÔ÷Ó¤xþ‡¾Ç¨0°øõXõH47L6ýÁXcNÆåw^ t¦TÅv\n©ä”±)±~øi¥ÀlJ›§8ð …RTŽ+ÃÀÇ»X¾Þ§ÖLóH\ˆM™+Û‡Fˆ•÷Ý‚ÕO}Џ·8§Å±)qŽÃ¨ý ïÀ×¥a—H’ÍN´™çZá«»ª (›Ê‘ÈŽ’•I üASqt˼K‰©0ð€2¾CÔã¼ ƒåMs6ªÓtƒÇêã#ïÚzSÅ‚T•‘$£# OÄM©j ¯¢Bô:D °‘#£-eðV;A;6=»tO-ÌѬÄR7`ŒUŽ©î87Ja`¼-â™e[‹ºŸHÝ­éŠÕÝã´x‰ça\IR53”ÂaruÍBÇ3Iþm'f½uûTsæÚ”ÑÌ> ÆCösª,ÆÑÀÕE „yãÆ¦{üÊb ßEH¶0142} ÕÇ×ý ­ÝÒèB.“]ñÃBÍo†NYˆÂÀ2=Ç:JØ„¾ÄM ÆíÅ+F“©?áluhw1Šd÷øü‹ûOšß÷Rž’w(j¶Ð÷[}Þõ¸‚t†_{ޱim¿¤Ùƒ™TœÅ¢Ÿ`nË/ðêó#WîKÕ\·†+7{i~Þ„%œ/XµZoý&rÕçg.D|VÁ´žZ2 o}è k¦mç"3‘ó"¸ÇiâíDl:ˆ¨×5lHPÄnÝå” …ÙŽ%Zìã&ìÕ\𵩇–``uÅág“¥ØˆpÙ̶aà|Ä#9¤Ù ÒtöºÍ_Mp W¤D"möº>­Aý`ôÈÓ`rÉÉx1œñ÷xØó#¾>„ã=Žv ˆÔR#º»¢%â0 g_]&½©Œ‡%zðÍlvjk ¬p®C®aÚY룳 €å½Å¬žý¨]מ¯°Ì⚎ï㨉‹î >pœwé^¹ØTÏ4ýtuK*DRJmÝÁ‡”´ú¼é>FÉòPèî'ÑŒp«Ï\÷‘Ä:eôÓDÛóŸùWHC[²×^cIJi\ÏwýÌ’\z.RÃ>OmÏ™fX¥+ûi;5GòŸ~þæ¡Ä•LKÊ+WUæñ£ ֪ʥ|M+Å×»Vj˜¶Ûì´›Z§µçûÝoMF>a”K ׯ®ÅÐ5vWïµ6Ùt¬Zaƒ»xÊÇâ™\2›Ä«â­›DF/÷m7ßIaÔÅç —H—ÛJiÇ” ,2çñð-èyïžu="Ýpÿ®ªVBÃY;ÑÇüÈÖ}f™— 伨DQ]ÆŠYÇšmŸ™¤æUW#4ʯCxíókeú´š=Ê·J\$›ûÕ¬ævLß ö1ûyc1É•’IµÒ~m00oFi!5ܪóŠÏ·+ÊóŠÓJMšá\B"ºŸ^Oàë/÷è®Ø›ÌS€P8ÀƒÕæàb9gÏ]Ä’ÁŠ+W_Öë‘‹ßÍ¡7®*o•¸7sÄX\22âlàí™YjN¡UùñÖ‚{º¶ÕºD·Ýø¸Ê<% !W䤻}f;æ ´)«òó}ç ól[·‘Žõ •áª,î<+#Ò~ä“¢®W ,Ð^a°¥Ý>ÊzÁ@T”Ž Šïo¨‹·`>W¨mÙÄŽ—XˆoG·, ¢7ýt…8pã®hØØë2Í[3Œ:èÐ*Üß 6¼pt>Nþ¸ðuÞÞˆ7öÆv úñ¾ ‡Gî¶a²¸t¼¦+ädÓ§(Q³"£%åÿ »²åÆq$øK¶$BÒc¿¯#<Ÿðo<ýõ‹£Š,Pr{g"æ%—4)¨#+ó`LÓ*—ãï7‰I×x‰ë=%|fv3+ ìfµú}OsóºÄ„Íêƒî5-²›’;‘e`-W²«ìKÜŒqwj5©÷©Dº.~Qà•È/{cO¬â#-¥ê=_{cÑÞž+¥µrõY 4’og­¡;nìÿ)M«èŠìäßãMt¶"OeÑãïç$¨û8Ù•Úf4½ @2·àõf]Çî÷[iÓÜŽ¯Ç©€¹Y+Ͷ˜¢“ðÍSkUhíÿ¥À„r5Äi½-©ÜZdð'·ûÓHEà‰N[°˜ $sµ(W6º0©õÚRà5: «P~£ DZ£Àiƒ†Æ&Œ¨uÕ`aèöˆ-JÃÜ’OS™v£RB,o0©Ä ]:-çC…Ûó%ûãZ[¹mBXŒ$„ËŽÂBa|Û¨F,ã.;RÔ¡1.Í‹|‚:å²}fåÔMÍ6ôµ˜(ðrl)È©ÊR§DœöXР\vP  »®¥X†¡‚ø‘PÔ÷f|¨ìM´K2ÚYB)ꡌƒ:7Ó¤¤1HE}gž»WSÛ¬=ž®”¢îšv;E]ª^•Õ4ÏðœLwÆP£Í¶ºè€×“\ˆ áÜ£Çr«Qö º+náŠ.œñ¥ø^Ñd0¯J(‡ºY˜ ,ÜFÙEÀ$yáÛCF5*W…ØŸúØ¡¹«½óÔT5ê&IÌùðTÿ08éJqMÓàNÈÚÔò´Ú-O'|˜ç[ËÓj·<5%aào°{„ÆfzSžcèš_8ÁãÚç™çû÷xt*‚›„k{Þ…VÒ6’iÝ ÊÆæ…ý<¦nMåû}”â¯8Ú+ŽxtrS,hèzÒ›S(ðzŒ€"‹¶nò:x†UW¯ïåÙÅk\ ì$µMf+Jn–Iˆ ¡VÿÅ!o4mÔ*†ýaȤØ[ ´¯’ƒZlP|êê¹Ãâ„ ¹@€7—ÎÅ)H©Y09V¡K*ÂëišÅpÞ"0–íƒ[¿ewÁ¡ˆ€—×[Î%JÙ?2BÝ.…ÂÚ¹÷(7€Oþa¾·à„Ιކ ­[5&Ô‹Ä'e¶J^KÙ¦prí„òpºf» £pQö/Ñð…³×   ’ ²©Ï;¨Î°wƒî©ýæ: @ÌOˆùË»ÁÎÙ`ÜCÌ_Þ v.ÆDÀ° ÿÖr°ׂ·E³w¥ˆùKìZëø=ß]kjþyÑ:í5w­è(ðN5âQÞ+md«« ¿ðx˜%Ý÷Dz_J™ÙPv J³…³0|m6Ï6Ý‹€;Í–Ì”%¹H™Ù”KR`ˆÍlræ7ÃèÉTvMÉå*(ð,Füë)AÕ0•Oy O}Ðl¿ÜçãýKƒžˆÊ¶Âp@ðK”-ŒË Wè „à£Y"àõ½{©ŸmøÆhÔY’ÚU-EL¨x7tI¦f•B®9¼jZ²Ïxº½‹¬÷Ûä~9æC€J,eQ lFÀ#ç¨~¶dimW"z‡%÷Ë–Ð6MKßãýò“%t:™tЀï,¡ÓÜÞûÈ>îGædå«ÔÚÚM Þ(ðN œ%zþ®9—¨eÀ%’‡œË1yWÏñÃ<‰ôôS—"-Öºa"_øÇ .£sC!üÅOØ!³¬ž²rn0…ä…~iU .[ºdm*#äõ²JíɾöÑKBW.ñJ} ;h›.º·; –%÷SñÌ ±øÈTªÁž^ëÀñæ·sÔVóE;ϪYѹ$¹Çåa6]§ü1Š&ïx…î=6w DmÿÖ‡¡äœ2ºõí§ý97ð$b±ˆ ÈߘÚ=r£À½Ž,2h/ÚÏ\ aÓ4 §qØé¿{‘…`{1p{v6Ë8SàåHå_ä4#L•*<çî,6wõBúÞ»ÌþÛfÅZi ¼­)Ô‰v­©¾&ƒ¸7’Òݧ앵yšFÀÐH²ñ+ß/»eswUPà"E`Êyçp1ðAxZ¨QxZ‚ |©oHAêF¦V¬²ÝÉðÇÿþûæ)JŽÔM*µ: ï Û áˆbÚ”Î0Ö”3.îGT™ÎC²âÌ í+å©^ÔB—ã{Ä–ü6¾ÙPeH>Ü üƒÜx•®SSR`°€úú&P•Ö©r…èŠÄIí!µwÍÃñ£xž\“`YÛý„÷K½ÔÅFÄ$wWïåy=‰Úl^©KM8‹ËiX&W„„ý™äüùÜFÿ3¶¦5Œ&”Mîv|‘C£}«õÖª¹ú~BtÞ7»à£ $ñXù'×ÙзռߚÎXÿõ,`Æ.3/³¶ÇŠaj£DPè$Ûuíœ ',³¦6ÕrÀÜk ÅÀÛYùÇñ†‡u˜ìšn¼*ÿÌNùG›Û>käçcì ¾3ØMj<Þ‘Ûè¶ и˜‰óÒÇ•,Wªçc†ÕéùˆèŠÏØ2(ê4y¹æ¨&WÛ Ô%0r²¡á÷¶gÁÔmã wøz’×:2ô}%WK×u:?ÎÞŽ䋆c£´l\£†/'ñ?æå #ðJ]å$Ȫ6cUw%†ÎvòÈÜI|™F³å¡À„,×"´½è¢˜sŒi,*žQé×±U“ÝÂñaîgØðЕ¨ujÿ½@)Ý'Ø>¯ê±Ü¿ÇØ›‡gá=ºT®­eÙ Hc#Þ<Ûæoƒ“õ&úNô‚S ïv»‚Ê®'Vk#ó\(ìÒ>ïo'u²«÷ZàØ—µÀˆøqE° Iã?Š.z=€ü„ù@Ÿúq¦_ŠHø m~EHb ô÷닌‰-uÛîº=‡Î÷÷…gˆ$:[rû?t `rÐ r°ñ³k†7Ç)ÿrø{Ãk ÌÁJ €wò7î¶@iÓ9ÅüÌž¿-.øŸ¿-®šÿµ¸¢+þkqõø~qmtq=?~[\2ê» 2…jž²n›:X3ÏÏ×Ý fµTH) Œøn ,jå|^OZäöqLj̺®c³ç'‘öÍ.ØJ³Ì÷2ެ'˜ú÷ܳ¬Ãº(.†¦¦@¨-~‹]gÉ~_“³Mmz ܇‘ûH>Í”Ûo§Àïñy‰ªHÓà\O ÎÀ½ª,N<[²±™'wD1 dÿX×øõ\[×=¾_×]×d â‡uÝúͺ®Oëúƒ8­ëþ´®1ˆÓº®Oëúy=m{/§ÞúöÓ©ÐǧÂóöÛ©ÐSà›S¡> ÏÛO§BŸ ÏÛ§B:ž·ŸO…ikÊ ¦Œx'R'eÈÆ›¦WNIiCÔs ÈR%‰u5çy“Ïx‰üƒ‚y“Õ6ùÉcàõÓ xkö•%šl³KÕnX<#óPf)ç±Ñj-¤n9+-¯ã\]j­§5°÷òŒiÀ/òR'6ŒK«K]ϳ¸T¾wœ„’e›Ã gÔÙé=©ày#Åί°•®i.4/ñ‰œ_V˜lÍa.}¼Œža̸66¯0ö®x¦DÜMPàtC4u:µ^ñe"(lj UÕªDO>•úÏ¥¤Z Ö…6…á f0ÙÇíeÔO…Éžœ—“sûL§Zç¢!Ú¡Ú¯xØœŽžºãcM j^a„7˜6]“jƒOÍb¯ÑLÂNQŽ¥®7n%’ùûî¶|6«Á»E†é†Ê‹ÐX “þ4x!ÔÏ<øgKÊ—|4°›1â<³åÜŠ1Þ°±É÷ –ÛhfL3Ðb¤#ýÌ›"ËÎ3¡Uêt»ý‹ÌùÊ–Ø¥eÄy†Ë(Á逨‚,¾ »×€Ï)©Îë°E/üƒš‚ç7o‹¹pdŸù#Ý5r›Û¹3°¸ëc‘'ûsò\*ý™ŸW2‘™\6º|“ ]EÈÛ1R ¥0»ÈÕØÇ×$r0… S öÀærX±Hö#r]cäý4lèJ†r…nã¿óñŠ´Oýù<6iOsv“<öŸ%uLËè[ÿ8{µ"4ñÊÆžñe»ËãªQ9R ¡á=›šŠ—5´©Ù1«òÕH׸:Š Hå©êRÙÛ‹,ÄœìóD›ðªyžêÔi›´#`dðºSc{ÖY„}Ƭ; ¾#Yª6å-¨³22Ô⇃º.u:÷.ÈÏÏ—yH&^Ì+VÆØá#zJû öŠmÚgÊ|쓆ä”C\Ç~¹ìóòÙ¸ŽýrÙiLæD6w¿\öyùÍ/w¤ÀÛ+źŽ]‚A‰)ÖuìÌ>c¡•c¢¶‡‰Ú槉Ú&j·šÉddžã‚m¬y–ï¿urRqÌÑ…Á³)›x¦Áׇ¼žr¡R+×ýÖÔ9üÖ@!ì;çnÝ-Ò„® £ ¢kí'6gàfÁ>©ª( ‚ùl °ƒ}‰Ó/Dé Fô¤Rõ’Uãf(ðè¹ï¦Þƒ·åÐHýð 9f9Ô§m앉Ù&Š Ó2±Vû š¢æà¬ @Fô ¡Uìžä4— |žê/.Óöüî²´Ë 7sƒïñ$‘êj þqŒ–ÙØI $/ÜF@ ÎZNE¦5¨½±“§/Ãü›(…M²oÑCmÜ]q)矚„»ÿý…ÙR¿ŒZHÁQÿœ ‡^ÄH–ØåãÅ{±-³l-Ö5/)ðòƒ|B1¢|»Äš‹!ƒ†¡èa(æj¿Œ µ¼‘O(m¦¯{›;SU/‹)•ÔxÃäݵºCO§Ue'ke€ÆèŠ7;ƒÅjc÷+>,¸¥Ð,ƒ*µê¬ÂkæòÂSr™ã¼"ª#=C¤9¦µ+€«Ä-.SŸô>},Ø>Ôržž•3x,Jƒa—Ø5Òóóƒ\¸”[)íG.(ðB,Þ ÝŸÊUW>ë ;nÃ×#\à7Zq ¼œ¦ôo= ‹›;ÏþÖz[9_ñ—Ùw³¯ÕwdP8׃Mþ \ ÀËÏ@0Fàä<Ç÷X;KV{2hN·è2!@òº¾6Ì(0ÁˆK0”µ<ìÙÚ@g€ }Ö(²Wv½%.…GÜcÌS´.3i¤6º§ÀËÉ^Ò[Sè¥ÍÖl9±³ù‹–ÇaS©ÎÔu½FW¼‘hÂ×ÂÓõ[aìdgs¹—Ó*…ÝÈW\3ÏÓØV5‹²àR¥K/)0š,Á²s‹fZVؤ®/¬dle;Ò}ª`P–ß…í eQJ³VuÁ' ¼¼]¸¾¾¯ï|˜¶yi—&Ø5¦´rßé÷Á‡1¥ÍòSð0c×ëYHøÝEZðyš2܉KB,.ÑK¹Ú ¯{Lq›KªÊäð†êdÂ3Тj¹T`ÀˆKà_æõX UWÀNA¦ˆV ü‡Ù©45¼Ê·QàðW;?×ÁscO¸u[* <\o"R^.M©sNǘLÞ\¥1|³Ùd “%ŒL…Àçø>·ùÙ²VÐ/a׸Ž%r,ß;6ß4ñc 2n´‚ºHì§#oæ9ŰðJŸ¿˜TøÒÔ³œxÙÇ1nþ²97·q­æ®êA€×ƒ¼$Céª%Üÿ¥ð[ßb™Çt¹Êɽo›ÕÀâ"SD®C u~_¨Ñ“Ö¥álv»ü„ ; øÒxPE(ºU¶ž×·[$µÆSd9õ6¦¨ë"›; ¼ìýä ]‡»¹“Õ¶ÔíF׃¬Q ¬oTYæÝÜÏxLóïïQ§Z›²o0ɽ%1 ܧÃ!jÖ[×4’ãßÈÎ|ñðñ!³Ro(’AhÅnÙÒõý()ðF3Mܤìó¶Ä\áöâõÍ÷õ̲àx ÓaŒ/äŸ]€iÖŽ-îìn—»æ‰Ë]G5äZQà ÷{ ©w —¦m<ânUÝç®Èþp@'ÊÈõJ,hæî¿ŒÿÌìƒTi5d¹Ñw*OÔ³à#x޲äDzñæTîÞfîRÓ ŒY³äóÅ&œ™fÎ[•KÞ¬Å!jö#¢osCWjè‹6~y]òb‚‰ZFÇ;PÈÝÿR•ª·Çk‰·>Ÿ…î„ó¹k*û®j àú±äú’ 稕Óö‡VK~ÑÊišx¡4ð°¬uU({¸‚8KŽðúÏFÝ‰í¯§dª*üöªaàçšfMÖ5o›åé^S8Uè´Ê`#¥Züß@]"Ìcâ6™)È®£â{]Ï›ÍFÉãÎÀÍG´|àíÍߘ÷¼sF´°¸’ç£J¸õÜL9‘12YrnجS$ôˆû"9—ýíª©ØÆ "öñ2fx[.ªš«av •èü;»Â•*Û§6Î9Wos®±/¤‚s†‡ËQˆJ¤\»ÙUlƒ°ÓpùžœM6£pÉËÙ>µA¦ÐC˫ǵ#ðx»¼ˆ †Å5O½œW1ÃX+c/ó¯|ÌÓ&·Åä`ÃY\AØ;®›åd&{qôdTbùâáæíªå¦Gyd§‰±;¬ŠA¬BÕˆïñ43î¸lá…OK3ȹ—œ©],Ô9 ç3c'=ŸÐ–«ª–·ÒðVØ#^l5 ŒgNðÏB2kü†,s³‰`¦É؉2•£â€1©in°¬Èî/SèÈp\Êm˜ø,(ðrPÐÆf{‹.f¹+»Gk&ÎÝÃØ-t–²î[¼õ#þÉrØš=P(ìPðòPª}§`'[mAsf­eª§ ÏÈýÄ‹˜øÄ°72«'1L°fî/¤—ƒË’ó |FÇP8?ŒcY }SÜÛQ(‡.ÉþòEåZØ1¢P¾+¨|,Ê ¦6BŠ¯Ç Ý*ÎUýG#iï}´Y5K•çÞúrªãÊ0S_µÕ²}—ƒ&»__ò¹´˜t—¸ãÞo'žñ^œø4®›‘ðòf][2Ï; <&“Q6®²¯[4öü¹#¶äßl¤ÕØkÉáäº'?m¤WüÐd;An-‘hl´é¹œG˜“àuŠÎ!#-µM%‹L—Ã@7bx.Ñ”½X;¯nÀxlË‹Ìû”tëenÕ†{¡Üû9]ô¼µáÒ̦{åþ ýÁƒÐJ6ôýŒ}®û©•킸 ÛŽó:•)æ\w2 êJMY ¥¦eáöŸoÚ‚Ûp}DÊí—Û-mÚQàõ•2Õe*ãx#š• Ð/Un× ÇÜõþü±+iå°ÇÇ?ÛW»V;É„¿¶¯°‹þøøM+g¤Àµ¯øù[ûj£À Îè Ç×Ú$¦WÓTr<Ô:Ýç3Äùÿ »²eIYfûJ»F­Ë¾?;¢¿G@P~ú’hbÕÞD÷EG¬¶!‡•kñÞ¹ŒûužŠ·‘rWÁTm/M‹ƒ$¼oŒ3_åÚRÒam;Uµ1tÅœòÄq²˜›BÙ¹¹Ì'bW% ŠäsRʹ›uȈ9Šåxû£µ²4vï­îM0[„ÁÄnV½¦“‰+Òê>»l ÞLÓÔBR‘?~rÙr9ÃÔ”lÒxýØ:`‡¶_š7ý=3•áE$Ü=ógZЇ8SÔs«èZóvé1ðºÏ–†º™_Í,WÂÉ;×Á®þþ÷ç±C³ip9»XcŸ€Ø:—«ž‹ºê";1nÿ³Kˆ)ú¹wOP7 ßü|}%÷Ñç3aûXJ¶Pæ>.LR ))Dî+¬k"Š)ñzÞØë b°ŒÝZÕ¶„!ÔçÁºqPAö$ÁX³ƒ)ü÷Âoã0p>ö1>˜¢ö{›‰.„e)wé8xB<¦¨ýþº{!Câ^x\÷‘Ìö<˜¢»ES8"%+t/aè€È¢‰C>S–Kiô4ÕÉ9æxZ5í‰rß¿[òcšò:¦wR4•Ö.µ²ç‰¤D«,Í\åÏñ$¡XÑ=çjx¥Mtœ|¾îg®Ì. ËÀûÙ* ßõëqîò*Öö¼ðp%ã9žøˆþÓ–sç–‰º‘5¢òlP öߥ`³Ëšà-9GPÌwÉTåVIŽØ…&˜ý9–ª²:Ò~-ƒ5œ×nÿ¨`̀ϵf«g';˜aÎdø¸Ž%ä Ùåòˆ4ikÀ=&;¨nñ§YPô“¢ýú#à®ÈBÊèûê^Dÿ°Ë!^Ì탄âV½fÛš&^+ D4òi;s+k°5̰6òö¹RðõØ€nñ¡5#›4mÑ­gvMÎñlUè!ùI>Öä·˜h`…Ð+V,–šœc†j{05Á[Uó®nÛó$Ý #Äk ‡ð•8 ‚ÿ§¤kŠ9¹Aà ˆÑ ° Önûç#Õད—ϼòÐàÍMè¼Æ!²“&t¨iŠMÔÛ½ºõ,Á&» íØÐƒÁÒf –ö.È.1ðŽÄzñÂ×¹¤mŠªI~úqè¸Þ,it'8—iz |"I„: vduy$ì¯Ù弿ÆõÌí®MKWJJ L„Ì™Cw‹äKAEƒh;êAuî–¦0<®ϳO+Œ´)wØví÷Ý·ò~¬ä*µ”sU¶ ÁÀ£"¾åHÛ­ô\åR¬"^Lv*Knjƭg!×ñßæOâØŸ\¨iŽ‹yýRœÌ^Ì0!oûi /…K4½'o?”*{'Þwí„ 蜢èëÝ€w3ЭÁ_  >ãr¿¹a…¦o+ú¦ÕL¿0Șüý$Ö­ì=¢¦XƒùOÅOo²ƒ¯ÆJn†ùŠ¿Ï·§ò³*x´†b7å¶ÄOw¨>¾fׯÄt-7Ê)ãÖ~ýúµ’Û÷à@d*=éÄ4¬UC\¥®—S ÜÚ#è"©‹úà>^¯fÕ·u¯ec;[;õˆ {‚v=è¢*gé D]¤ JC«u+ÛÔxÿH©¥*CTÉ(U þF©J€¸šÂ7C¼ºYØbxÑ@f˜]Ó¤ôÝJ©«øøVJ0É›]S§vRÆ%E*IšUV1ü¸¦1©nC7Â{OO3xÅ#m¡>3zÖr-×xÕÙ™ÃZgµû¶fMÈPh LZÝ¡MÂZåRCC T™ˆØúÙXj­»ÿˆ¤wÂä‡[õ”*ú¾×ºÇ@ä+Kl.$$…\æ…ÏwY™zÈfˆØ˜ZÃÊÔC6CÄÆOÀåÄ ©ˆ¼¦^jáVÝxÃ_ïŦ Y´MµVS/Ùíëì¤@ÁLÍW£ÀI€W< Àâ a­ ÞÐäGÍ`èD["ÄÜÁ#¼]N?]‰ðÓ=s‰ëbc_*CìÂÄ(ãÅÜ~И”©Æd†…Â?«VÆsÜ?®³`æ”ff·“üE°t縮lõq;Àw·@–îãm]ÂÜPvËßÖGiSWmSƒ&t†d½÷Ølkú ¾çEÝrF1ðáÞÒ-îÑ|è§UÅŒÑçþ%Äïž÷ëT)éìõ9’ ÄÃ×·}1 cÃ,Þp².Û¾.Ö‚§ï»74…6@íÒ‰ªFŒÉ9>3î£;˲ç+£ÉŸèb`çrO{ v€*™\@¨ˆsVÜŠL¥b-ìPj^,Ì‹âv7µš˜aß/‡2Ѳ) qòs˜TZ°âàý¨¦P ¦Éu6\jÙ³FùQŸ”ßZ9%²û‡ëð\Z–%nHˆ†˜·ë ˆ¢=ûÈ•)æ²^{xïosCÀ€Ü¸€~e† Ifÿ Sg‘3Bê‘ÐaªâŠÍÌÒk¥zJ& þƒícKÌ,Û‚Ä—"ÿ{%vîUvò"‡%…•…çr tÀÀÄÎ$Æá̽fàˆ¯·Æ4Œ7΋v1nBÙã$Ü´5T|¨0Lë å"blö¸ü¶ötní—âq==™÷9zÞ§nDžÙ3‘)åç—e] _f)²\í±u](š§Ò þû½ü,û¶æù2¯¥ê‹ød¤RQlÖ5þË6q Å4Rø¸ãìϲIAKJ25cßB1€û\e ìÔ‚¶6ohöWÿÓ«ûלqÉö>nS>ÅÊ©K÷ÊøØãð¤òûŒÚuîÚä§wçܲ„BW2—v˜¥Àýˆ¬Ÿ`F €ù^ØÊ€lëv%»F×ø:}+g‘#¯¤lÚä†í¯÷Í©‚ügßt”Œ,¹šP©XÂÖΩ¬mÓЦÉ_>±wÇ™ÔÚ}^ñz²ãCô=¬":ìxë“Q©hÜ Àëá‘'0\¶P “*æSöî¶ZЂOËTÔ‹ÂÀìÝŠ—U!`š?ÔŔ”ë.Fš”›!Êâÿ¥ÌXÕ~uIŽxÛ#šr |6§"Ngn;aà¶oþ Ú°8àä¨É”Gp_?|§Œ,EOAI9{œ=ö¢óW% }EAÙ&CLÄÐSe;¡Ë\¾ÁWõ£?Ž“ÔpŽÏë)÷¡à.Õ¸Œ¦^“—=oçÈ0øx ¢©ê€aœ=ïoû¦€¡WJ©ªV/EBÞûØI†—ây*ùøÎ]Hiô@J3ÏS¬óºi1pXïµn¹ndt‘à5Ñ' ÒÕÜ­&CE›xÃÔ¦ÀXê½Ctߎ ö À{긱¸qëc l@Tò¡0Âφ‚.oï(>Ñ‹ FNEåÙ’dÿ²£Ìþqˆf;¤nûh¡Ú”!—e÷¤p¿­|»{ž P̲矘ˆ£‘ûÛ“½a¥ .¾'¼I€‡D(±ñ-›²."•àÚÀF ÃÝãž·¨†b¤ØáãbƒK,º²í,>Âðð&¶êSš¾o… gŸa˜ýϨ„«Ön?(¤% ÃÀlŸêÜ&ýêã/¤0t.00Ç&ûQÓzj`ª3;8y‰­z6P3“²a gÙë” ˜ekš©’£S‡ ß-Ô¥äÔóÒÚ†‘2,úýg÷SÜ„¨5Íð3Ì ûþ‡jß1(¬¦ŠbÐ}ö†>p–ŸªŸtWì_÷)Ì2–÷ò³ÒRU…Ûãû•ã,L?bà5éMÃgU ŠZœóÛ¹i’R²¯í]Ÿ3,ú™joÏãªL©vâ’¥T;™Rí²ƒKöö¬×RÓþ¬óç/Ūäz^OfSÁʱå]Y ñ¥ÈN²ùg` âRg”)¯`æ…ÈIˆuŒ?æ–?É$D:û$.úo“ÎþÛvzüråݶ¦Eàå`Gpp@‰ÛíY¼ú7õ(–Ãà–<5‰xûE%®úun9G¡gÑ“[¯V/îëöCýÊ'Ä3m84f˜~õqªsž¦cRáý™ÆIŒe+.fU-»ÞYðIj©F0ØÈ^Ù»ÔÚNàeOã†ôÊÏô}Á@#»M602½Þxþ îW^µ”iÈsó¯Ï¿ ®”îehúŦ¦üë<¿³»7‚{Ehعò¯c,Ç—¥|í#¸%t- —gˆ,bÝÅ(Ýp-Xox;;Hl‚^ÙÈzæã’¯‰ö u·,m]Cc*ÿB³ÕÿCŽÊþQ¶­a Ï‘ÊÛ6<„]6ö®oM‘~·çñî`»½.u­d!–9ORk{Ç`’fiµ{„±{ Ñ-ÍKW° 4ùWv6»6ù$ÝØèq­0{ì…¾½ 4‡¹²u»kþ•¿™9ñåÒÌY×´1ðè¼”1mvG¬9µÑO1ÿz½Å¸0Ñ |´mkî½ÅЂ¡LÊJk†Žaà-¥_‰Ð„dÅJW¢”üòõöÓ!Cò?mlûŸùåë¬3/…±–·õd¡ú™c™ª`Š < 3µkQ3N5O1Ðð¨…-ÜSw«I€ˆÑIC§Kh:Êv{h8çH¦ê8ÎîýIŽxÌî=Zÿd*f§xÃ/h6H>!7+L%:5L¢ÂÀç/ÆbðR\þ§±X¼~$ÁÆbùåwc±.‹å—SšB)8š¸|}l:eÓr,Sã$á¥èÚ‚j—tµ ð<¬(ì™ÆepR+MŸüòHG}ƒ·ˆ~Üj"ñˆÏÚHý8—µæòòKvÞgàS0ŲøÛÆbàõ$çoO‹d<Çüw ¸QÄŸ>”ÆÖºVLdõÆüz–ÿ„]!•”d`IAýøa¾‘ƒBñT*ÒòÌørÔ?Û…•fâÓþ {ÓCKµVð†£îùÿÅ#nowØ!.Ð &•ðí%uQŒ€>IŽºçÿ°&^[6–¥.“#Þ±éÙënQH£æ¸Í¥\¯'±OÃÒÃw}}œx6ÚìŠu¤­«F^rÜf‡× úñkGëe7àîaÚì[ñJiéBñºÏú­O¤39 FښůðšäÚliƒByëΰj ¼R©­æ[rJ¬‹J˜×püf›n¤.)]•ÆÀkB¾ÚXC6[)Và˯Ùi!e@«TŠ5‹‡§w.ÐaÒéyµíè6QžID0×ðo¸4íWà¶knÀ­€ø›}F)Czj'o8êð)ºç^§®`S·û‡ÊGà!ªbî;>÷^q=|$rui~]¶_ç÷#ûøó2¤:ØH¥WMI‰ü~ýÔÖô*5ý¢g’–ž¬7†1'ÂkO‰¼ÕÐ`NÔö¤íõÐÄpæ°°þëäPCÓdÉHÖ䈘>½¬¤ìíÔ—°R Ãi_¼"æë$2¸;:,ªÄÀ+Öv-—‡350——#mž›ºE?×{šÏõ€`j¨õÌŠœWsìL‚a y¡M­ì— QÀÎiàUoÀÙí5ÞQö¼XÞ*îö£Òf>Þ5 MªI˜ßOßup^õé)†ªÈY"Øäܯİ’u€9Ñüž¿—âCÉ×mruãU¿ÞÔKc?¾0íÔ” ÷•ßߤ9ÄÆûð#ªÄÈ‘Äò¬¤3÷Gù‘.â–=XR•XÃ7RŒƒJÏïªQuøÏGLw…LJ]!Øp¹ˆJ ®À?.\Þ¾ë?.æq}÷Ä B¾ee‡Gß³üqC’ßÿÁkënO»Œªn«eŠçx?Y¹¨ÖnM© ÃaŠ.¤÷A«ßïÃÝXºŽ×`³ @àJ~ÃÛôƒ*:¬m5ÄŸ~œIl4£§‘s÷´wàó$3à¥/°´ë¸ùãyÞ>€êr™^û¢KS;ŠÐªTÞsÅtQô Jê äÐ á6.ø ±Ú]q"<§ŠÐ•ÕP”Αëó–TÐXïé¦ÕL“qaÞp¡ÄVnþŸ°+[’׿ÔMmøñ¼ÏDœû ƒÙ7CÌ×_K STwD?f@—ñ"Y©LKí7qÏïÏWŸ.è;ðLÓÌÁË YÚÆnÍ-ܑƤjÿÇÛñ"Aléu‘5 ¸8ÆÏ°á~Óžðâ ©kƒ°É&§ÀàúÁéTé"™RèŽ é'rY`‘ØOˆ· OÒp*ÙÛRè‡nî;)@.~>Îrˆ;y+ž—Pç QDÏ`#í‡~ÚtmRß ùêuF§^‚~ÖÜr·û.Šëš¡ZMªðT8ôƒŽÒ¸K E‘Ï6®Â¿ÿx?<.%UÙjW©÷úâ¥9¶Ë‚¬c¾ˆtÀoÍÎŒ-ü?™´sÒWƒÞA²#„Žàb^ËŒ'²/Ú`À¿>9qvî¤ÄŠ÷Ú‰2bjÅKœ8íâ'N ¦Ä¯Ç¥§z'ÎøæÄé¦wâÔ ~râLVOüÁ‰³ €?8qbÍpâ »¨"çYmŽI×ëy¾.Õ½¾ï«¥o¿^«‹°F<^_ño¬†’b5h ¼Š¯¾ôë°`Þüb§[—7{x5a^œìAšÀ$Ž¿~³)ðʤ ìAb¢]ôÁ=Bûøû7÷M?¸§ŒÞ>›.øÄ((UlnÊm´Ý£$§Àèì*¨ tÄp/&f—®‚éHÞFJ>A–öˆkjŽÕÏø0 \þç$p+už:m‘ÖÍ@Ï: ðÕ·ß: àq}KH‘Ä(ë´-*¬,Æ÷w±QTÓ…\%®BÂ`Á‹3@:6g!íÅâ^ ¢­ÂSØJ»²ê<]EÑ»fc5U)ÑlŒã×qÇiV'`ôY0sRÂ7AcHO.´)…*êNa˜BÌTí^ÿ€²cÈU¥bb¦êˆ)‰oŽõO”}ÖÌÐDS3Õ?ÞÅ—÷tÒ—vUX/ˆCÍo{rÉk–&¼ª`tQŒsÍ_Fu 5SëÓ°—ÏsÕÅ8j}º±•d M)‡jš¦^ÍBŸkôýÍh¦<Ç €ÚŠ.^©ÒßÅ«©¶Aø¢ðfˆ½ÛæªMøÄÛ‡jSsª6±ûoÕ&M?U›F $Šñ¢­›rňöøIÉ·ªKó‘²l®®g <>ËÆmÍG]Ú°ÝÖ<ã!Œ*?ÃACT—½TZw~köÁo@‡~ìëë7¿‘òÐø“ß@¼‡ò÷[&¾ÉßÛ°°à y \íŠm“6Ï«¤KØWôöe|W碖¥7kÅ9ý¹-g÷††M‘TÕQ éÕÄMßö휷m†¯¾½½‹ —sš@æÃˆBÎeL1ô8<·V-n·‹J’€Ï —KŸ7ce†Œ2ØY!Å”ÉÒ¨i°¯øDkÊ¡z*9Ÿ‹–7Y„b“Ûì)“Á¹€R`tQ;‚";£œ˜°$>%qF,AI¼ Kâì`°xµ¸,G_›tÓÜT9Ã:àV«ôD©¶L뵡Á¨Œ»‹)”›Ç¦+*›$FØ+±·ãuVU³dú±À×fÜØ¬«¢Àû!!˜C·öXɆÛ‚~F$`È7J¥´O\ňÀû¹ÝVùHÊF22Õ²× îê×™À“k^Çtÿ1¡ ¬ 졼—LÍ0É ôbÙ!…rD¤Û¯Þ"Ò²5ì=T¸ä_oöè3q¡„Mš³Ü|.9=±²OÔ¹åTöfç'®5IÑ#¹ä°*>áÄ\rXWhPcß?³b•ðÕì'²ëZ*0|eÑ×OdW,)ð’ìª<Ùu À@Û D„ùdgEºšEßgº¢_¬Ådó¼ɑ™Æ¢ï7}wÿDW~žx¢Ï‚=>¯¥Ø~Å¢è\fS½˜+“£;X6×$¤UãðÜ!!­8à“þƒ« ç>’²™06ûèm`í.,úQ8j ‘°è,`.!ñq:~œ—èÒÅ¢7î%¤¤J5‚;>Ç“ìû½Ç[)–®hf…Od§ŠØìœM†+YôÖ‡Pø(Î)¡ŒÝ(àÒ€>w…Îs8¹D¶È&™¦‰ïçj¼[ ¾ $»…¬¯MWÒ­•rî§bMá,äJ-ù4Ï–QvÈe1×íÍü<÷¿šë^Ú_¢ÀÝŸ€Í,… XÈe) nƒR¥)ð¶‹;úÎý˜ÜØp·®ñT¸íwRG…v‹Î´Z‹•øEÿx`ʤï4¾úyuÊ=îøp7Òöý  Àn¯Ÿ€Íañcû„Û·Þ<¤U:‚H »ÅïOô:åÔeÑáÁ~cç (Ën@UemŒu%/kËv* ³@¯»…vé‰a¶‡Mª yÝ¿BO„ívÆý“©NëaÔ˜’2jÈt\N@ÊÒ߆ÖFüìÞÎœË xÿ4q¾2Ÿ&îHôç„ôVb<ÏawAè<àë3p €{Ww²Û1è´uŠìdG¯6Ú'mýUÑBÉüëÙ\"ê9—[sƒ=6uÂeSgP™Fdtl.‘¾Áyñ¾ƒ°Gö«yÚ¯"@Ò5 ÔX»f…]³®Y@>Ž9”n†b^H°É»Žã/ŠN“íÀ]ŠaÛX¶9ä¶´{uUP m£Q¾–ìæù”QàýØ\øyœqhÙpω†¯~~ÚüœÎn“mñ©(,è¤Ô‰à"|¢W: Xy®Ṳr†K2ìGL²äàm¸Ù UwMôb‡ooe?bµÄ'Ûa¢à“ÝF'²–}ZÂQw¿Ú^ ¹Í ¥›–“j2 $ìØ\";VwõXŽ`[Ãîï'˜?:µýˆ‰=êÀ_›®Ö‡U¨»]˜mÐÕ9ÇW¯[¶yBØdw®PøQ:ùΨӌiY“4|…©i.`x2]%v„&_›$»ÿz /O÷‡m(ðv³²ìV6Ô­Á;BÕÕa0),ìÔ\{^ñŒÓ££&ç>aÞ'²;ÁÜóÝ^Dp i²¡é;Àû»Â›J¸–ÒÌ8©;’«óK¥eZÓÉ>: {}ýœÃJ¼^¤œŠt³ EZÔK¯~Eç{H´[°ÀZfé")ð"(îúdÌÛyÞ>¸Š]ÅÙIÂËe{ÁÚlÉì‰W%DâÂU|M3 DZCÂüùëÞ­8Ès°øûÜw÷RÚmY^×x?èŸ(±´ý’¯hÆß‡*"êm3<é¸êFѵ-RUmPÁwE'U×é‚ÃóVt7ìM0f2à±øÔ¸k¨ó|]ä¨3Ìg :žy®òZ)£ *þ0ÂYpR²I·ºI!†©•68Ë_ÂY0Λ\„ȹè³] –œ/yÙÚId™Rµ5¾ž¦_gÚ´X’'n|²­Ù?¡Í£úÉ?†}l{Éñ`k{Á¨9þ­íO…ø„ n>z™ÎÉÝÒ´ræø ïgå$TƒN{=ë´Ä—ò*.+º@¶a„W1…o÷+òÚ~f­3 ¨±øu–p9«ëHœ––ë¦/`ôÃ…%N³ø½ÔÀZ–ňŠ?,f—59Ÿ(¹ ÝP qÖÈ3ìXÓtœ«Ž8ÂY å@Šh¼b.c'š]ñg“b™íωpþû>“ðêqè2•â cßF³Tc sW¢ãñA`>ታ€"ÊìýXH|âýT`ÄãCç£*¸Ê@¾ˆQ†Á¿°ímóÑ& “n3cð‰Ï_x>@ƒbì$îâ™þîZ!3]m° ÀøœÚû.~µ4ýZ¥³ÉÈ~é\ò¿ìë+´ëÛ$ë!%ÕYWÏÉZðûM¨"‡®I gã›ÏøÁîYïvÏýf÷¼P`tí꓌ÝèY9x»´„q\V"뇀'彘\5庺ë3>~.8QàÎÿÞ:À¶îö–µÓ ªkä.åÿy.’¹©îê1F¡Br}/¼æŸ¾Ú ß³=›Ú¤+©ë}ÖdðWÇ¿i²k Œ±ìmÈÛdš§RN=*‚[®b7ì]™ín·3$‚H*ƒ9m×÷ Ußú;tðbÛuF=vER óaß¡N ÏÑÚä ^k15²N³e¥ÀÛy7'±Äý¤g>9³ÀÛ/åiÏý°ÀŸï…3üûñK×÷w{yÚ¼Ø Þ¼¼€:öB·Oióš øê_ô'äŠ@r·÷÷ïßmÍøìÌæì¥]¯‰þ¶½ànÖU¢Ózü>÷a*”Xr DÅ0Á|¤~ËVV•à—qÕ&…á°®£Ÿr¬ë­ “¯½€¥@µþîbl›ˆØ¤'3Õù@ûÄMM+ÅÕœío¥Hò™ 6Ò<-Fi†1ƒ­9zœ®gñ2>©ò™v5p ŒˆsŒ„älŠbYš}xž'e¹íPg“ÏxdH›l£ò¿ZÚmtÈànBúæÙ”‰iúŽïŸi'3ìfÑëÚ‰,)0úL™ÿBá G±­ãÆWK'^–û±wÓírâk¥Ë0¥@ÊËÝÎ¥ú.Yº¼KöE‹ò(Œn]\–yW’£ u'ÜոױӭQtos…Áæ\Áï‡K©„q)í^|éö}ršæ ]Z·uÝ´ F‡´÷™t9öì*£¨)ðö™€±ÿ˜èLÁÃÞ< 3™0ù´Rà‹H_ S I̼N ‡iv? ‰££ ž¤Ì“”£Xà8&mjn*£=¦ºí(ðNUVý&nÊŠÇn†ΓӀŸ/¯dF­¤x¯x L¼ƒ…¦ó‹Jg©¦Àè½@»]ãHd¨Zàýcv°ßÚÆ®0ÃïvBS?W²ŸS\3÷w1¶½oÁ®—jhJ Œ‚þíÐ즱éx•Ô’ Ït- µ¬}±ÎUŠ_æÖ¯E–úTÔI×M}_T 6WÙGºÿ¸š)ð¶G¤®‘Ìs‡Å¼¶FŽsA÷CM t©tfçn ›ýý$ÙþvÛ¡i¤M¨*|"» ù©´/¶Y»¡À(ÔrãØÎ¼ó¹ªaxW{¯çÖä=¨"ˆ;%èm³t-‹¬M2 ¼b•9\hgñÐäÕRQàýÊÙ×IKºøƒŸ€öÜL(ðyè¬ç¹?‡»ŽË!ïæz¦ÀÃt ¥¼vâ’ԅ膂ãPA@z}YÏíœÕÈö;{.…¯+4b.¤˜š&ð/T:sY®¿ŠË Q U‘•Áø|Ó0á¯S»®»©Ó%@ú°ekºËÅ6DY#šz®“"ø=ß7j“îCâMs4ïrŒÅo%ÕØVp§Ò»» ó1iµØ­öñGt’¶Å&ÙÎ$ë´Èy•x´bnËfëØÈí1Ó´MéÔãv¦!ä>|µYÒ´N2Õ81î§Ã=Ͻ8€qJ5FëÇ< äJåž|ÑʱH4Ÿ(0¢ ¿ëڗ׉Ûüa×}œ  {É@ôSÊ;^|õ+ðâvggybŠÌdmF‡¢Ž>>Än“¤,Œ4ûð¼BÕÝnžs=i™VÝ?â³€ªòÿ$ŸyÞº/?S`àKï+ΜsaÒ¬ÃíùŒ9¶éƒÍ®mrUržpG㙀Ž_邾R îSg‰NàRÝ–`À¥ üùu"•.Ý€O8àϯS¸”á€?¿ÂX|Çÿv%K’«:ô—*ó²÷·"ú}`žÀ#vô×?ávfUÝ»c&nÊ6<7dL}I«Þ«¡fy¹6x:DÄ"&Ï 7¢ˆ{æ¶'ñ²Mj¹v}«LÊ-K”`dè!†÷·ó§W̵¸RµŒO¼¤e>á>§s¨µ2Náu·rèï/£u?&2ÆqÄ.+‡Š½ë,PAæ˜Á¾!’Ÿ§! cžÛR—bñÂí¶—YnŠS—kŸŽ—Ï_Mâï{ 8\Ò*²–byWOZŠ ÉΤ0=•¦kK‚(é»]©®B¶Îu‹ç—>X|¢¬¬7²[%^R´ÉQ.¾ë+Ÿû­ ­žlpf×ãÔÔ³X¾L‹È´cŒÂæ²*1p×U4Ô´/ŒcÖä‰ Njç:ˆ‹(:Ìk N¡qý„ö&Gf–&³§ ®ÄQ–¢ÓŽ Kß¡È~UJ-ÂÌ V8¢Å»… O.Ç®!ÒãåC#Nß_siæŽûu_aØ’²f’¦œbÒ÷ ~±ïÈãÇÜ ¡1¬HÙ´JÁž¹§5›Å¦‰2èyœ¤Xl…“„Ʀ¬ JKëó>=ë­çb¾<礳ý0´F™¢ö„ »´ å0U6{!ƒ¬™»™šd½Ôà´?²7 Z_Úá´ªis ̰~(£~/ÙRÂæBb Š M×Ué…—]¼ÿ@\€ »PJ½Ì¼Vmüêô6—BËnœ&JÛj„˜æqûØþkâÖ¯(bòI'uüÇšÛ¥Ó4’Æ9ˆA–þ`—õ@ÝÅØTÅW?wO =…+ˆviAÁì=÷½£Bdb¢¥ -fï:Ⱥ)”JÂÇ<ßìëPà@×uÆž]Ìm3Ã]¿µ¾˜ªx´o¬qŒP°¹Ð…ü÷ß%\WFrZg=Ü|j10ÛtrrYöÖµFZæªIžWNY‚oÊZÊ¢bºé‰ô˜ÞòØ·ßx=tš ¹\ÖZçº-5c¿q6mýˆ&œ–¼ŽAÒó¶¿ )¨ðÄe KŸûJ¬˜³fO ëNFéyß—XCDÌX›—†W¼ÄÀs¤U“­éYµ:M$N:¸™z¦ük⛞ÛS¶eÝT$®žÃmt4µžOSÔ¦KqúÂMøþÆn+A–Àuë* ÅÀ µ£ãA˜ÄÝ#1ÄÌë Ë8`s¹v¤µSæ åÙ‚ €Ù!'ÌcÞ,Ël¬·Wp¿Â‹P)¥Gëb«qàegq·|Ê*&R32^÷ò’@CPsYHš“fàm’ÊpÑîNšZϳ ùÓ×}ÿj0ÍN¢«%£Ý<è6ÁdM3ëÛ¢ ø<¦ÄB׊‘Œ°i\10KU kÍÚ“^…þ-ˆ[qóp!/G%Ie@xãy:}}¨¦Âuy¢ø§Óé˜YSY±Q f‡F0ÙRÚ)€Kjè@ ‰ sÊc„× ýmè@Zþ ŸkœùDV Ì>õD$ž_â{ ÅPæ%¯D;/pzzUòû{vŸy ²štuzl¢ŠÃsÐNk6§$ºÖŒÝh Ü7£ ëÖ]þôñc9R>Þ¾Z–J2Õ¯}ßÇßøüø­«Y^ó)©»÷…å<ðä2ôÖãZXŠìô®4&\€®Âr†E‘eï€Îö,ÆW2%Àí⎆æH2 -U a “¬B ïÛç®ûùsߤšÜž™¥õp˹éK^Áó<ž¹;š²1¤¦¶k– ˜¸ßèï‘íß8v}Û×ñc^s½ü¶«]/PXÙ¸®Ë0—½â=ž=EôPDKÐÀ%Žø)“'^Þ© MW ×ç¡Ûo.«í»Sà=ôëýãÚðŠPÐÍÅPÔSä¦0È"BH⾪ªœHÆ9YD» ó hmmÈ$š)ð¯=w§îN…>¹í.O¡µŽ¨ƒt]7ë®êõˆY\‹Äî‘eiÚžbàùlÛ–”mMú䉗OŸ]¯Û×¼®J‘§é?&'“ÖÕªø@ÑPNÜfÇþf½ÅŒ[þè.P4›ÚGFà9‰S @!ë1·sÀç®B-¡mEד1²˜; L66pDíŸunš®ÅÀs2…ñ.°šUÝGÇ瞈SŽB£ék 7öE¤@ä ú“ç!U¾ÀEûic_Ä™ÉEPdlš†LžVŠ—ÈÉóO ñHš¾ê Ï Àkb*ÂQèL…õ¢©8Ÿ>O¡=Øû‘Œ˜eL-ÌœyòÄó; }´} ¼|Xf}_Å…‹ø‡W³ÅÎ O€Ù;Â*3vÀÉà×ü‡W·¹Ð¹]áŒ8bˆì‡ÇÛv4 0Kžè €¢í퉗žH[=NÓ…ë¿pµÞ.&~üï*ôÃ1ç¦1¸d§sÚ'ˆ/ú¾À,·ÃAÔë÷L ×gÌ^ˆ"ˆôY€•¹b=QxÞ}µ»¬Ðš¬ZrÆÀ ®PƒH¼& Yú‰Ä¯¾ï™ °(ªÊ:ª¯Û³ã2Ó¢ÐÃ<ñü@ì‹t™i¡YŽ—ÙãÃ2sÀ/³ÇA‚à „õ˜{ë#ÅEñ<¾º ×âºÍÇQ-#fö5oyÜ׈ÏqØ……nËm^‘zs*Tmßcàùýah©2—¯¤m ì]ßö°ïí)a™¡N/¡Ž>òbVS+´†«ÒÓåu½÷mc^Ĭt×ÑŽKÕs <'¯öÀ±â¼ÓL‹øjÔ;&ýj¦Ô*$3nÓoMfÔªk¤+nÇðk…Ûa$u5oçõåüéÕ~ÀmЧ0ð“Iá|3)ˆ+áõ ‹¨©g纩ŠdÒÓ%­ýFwÌX“K —ë‡Í5M„4Sߨ³w~=4{)•ÁÀ7§‚=¸’ããÕfï Qê$©9^?Øp{|lÃs{3<¥ÃSM¿ ÏmŸÒÜ\ûºªxÙhp /÷C-÷¦Ý8>>Œ£ðtÇq„³ts­ ¿M¾1¤68ËIÞ1`àå—B©óR^ãø8¸ (òé­%…Èçr4RÁìYnc©¶k ÜX,>}íW.퇢*ÆBBÖ?ÐÏ­·s?|ÇEÿDŸ½ê»ÖþOôŠçä@òÀHlµÂÀ Ž|Bøº Ú¸)ÇÀ NÄ›ÝÍ=ÑHY³²ÅÀÛæãB5»žUò–,k¼·«p$-cV¸0<½ˆ»ÈÇhù²øôsýÏ×åÅXª³±ÔÒÑ^$îÕPþýïO …2cGn\µVÉ#OŸ‚MÝêxÒ ’Æ»`óC¢NAï‚ÍWTz=}rá„÷D®xysbëÔ¨\O‡`3œ v$}Tº ¼£RtQi ¼ã!G’šÅÄ>0†¯h‘)ð‰ÂW úv³=!ÔÄ›dAƒÿÍþZ‹˜Õ¼f?í¯¾í¯ì—ý£€kvÜ_›ÃÇìf~Ú_nQäö×ßÝþR޾³í¯—ÚÐaUCz³­Š—ÚlD—O ±ñFÌöûëµ*|Rc›ìì°¿¶É¦z1t›Ãì‡ý5çÃÜ©yú4‰n¹»?³Ácë]ˆi(øÀì, h¦Ö32èØ 5Ï/VEø‘ŽêGm° ×&yâåó²ˆGìõ%Žº- „øeáà Ã$þ í+c°¶vjúµÂÀ{¼@wnWè†#Œ!6L€üj󯦌ôs|õå`§|–=¬ÈAñ!ÇÀíî>]hºm¶/‰öüFÇ a”’Š,Tc Ïæ.Ž_oë‡téú¹ ŸæÝñ- fîæ ÜÒëõ\ 4ãYŠU›¹òà Q¿¾“Eá†g°Ã£âWßžUñ5âÞÙÐêž3(‘uÁÀ0<‡snžçe;çî‡áãËOr|Ý®Jˆ,ܯˆ"uÇ×ÝýŸ¤CJµ¨Jõ‹ê j>RäAp¹ëš¦eµQq+æ‘o?æÄÙ|©Û›œØ‚äÌ.ÝÏǸÔåĪõ`®]ŒÐÀìÙÍ™½¸gîû ¦Ð>шA·ÑìÝîG}[¬ìadkÃW£W7ªØ^ý8t®®ÝÔŽc;vÀ<áöl6CqÞ¨[^ä,ÞÒÜqg·Ì°%¨lø\Pw‰ÀMŸƒù›6`§˜ÖÆ÷&O?‹G/UƒŸÄ£kûEî³}­bò잤pÄI§õ<-9”Wv­ÏœRL“T¦-ß~¡p?3Ëhò¦Õ›;s¿¦m’ãá*­ nã¢ãÌìq9û i#[ܺc¿/,=pMa8BJ ܳÎ|¢ÔE›\Åh‘òPˆÇZ+Ϊx‹}¿ÿB‚ŠþãKYjùu ¶A…¨×5RDîéE’?¼ß“/2­?ƒ©Ç¾-Lì;:LõáŒÀÀ sIÂø4jž4WÓ³÷¶Wûû!ÿjIFŽÙKƒ7ßÚɦ®5ò§½tÒžÆRÇÌ4&å†HðͦzU=[&+“ò@C$,Ì—:'˜áÚnè!:'†2 ‹â±7Í® GøÑ´CÙÅôðµ¯tZþ^ÃýFNEN†ÉFaxŽyä"0h½œ™­Ã'fØ\$äjs =\Y#!ŽÇ´ ™i'ˆ"8ËXǮكýd_#Û4Љœ66×㙪’l.G쉎HØ®¸ûP$Kxÿº®©µ)¦!ÓŽæç¶BH»¸leÇ‹"æÄžÙ/½Š£@4¿÷½ŠY…YÒZ<ÔÈSNxÞ°ÜcžQªÆ_€ð†73ñ6ñCßÕN\§:²¥ð;ø¸`{òÁîX—+©1ð°p=Í EWTxÅj•¡pÉHIˆbóˆ·¤c— µ´ã¬„© V섆  À‰¨(¥…)10c öÑUlZ+*DìH–èß7.à‘ÖLLáP;tzQ·fŬŸPÍ#£ë‰Ûüñš±a*ëÁUekÿ ïoÏk×7/œ×*Žãã—ó:¦>ž¨xù;˜ÉÀ¢e½°ç\«À&=—RÍ/¥eËf(;~“ý…¹Î¾~“ý%³#!ØO!ï¹è‰Ò%àî¼vå6"¬Ç\°†ÌP˜aâà·;Þª‘H©” Ù f¨õa û^“¡ ¢ìkOdÍAÝ…9Ò ›§ AHl$–ÛX»l_ÖIðvPÔÜè»s^Î8HÖ/úïËõÛèˆÙà¤l×øÈbðRÈbMäÐè¡ÁÀM¿ÝUÇ…¸Ðž2«1J.qfžû{y8Ü4ò…í´gvú:C?#Ô|©6`ªC·¾PU±87¼ ¦,ð0¡wÎêZŽ‹}|QpwºzÊ;0ge½p(ÁÈN¸AÊ_Ô¼Ž1׫ÃÚª€{'ÎSã…ëd3k»½úš2ÃÂõšˆ¼ì&»î &ŠWÝ´1 iŸxßp*ÌM>V%+ `"{‰…Ø5T¨”±BÅ5@à®AŠ+£+‚6¹“b´ï†=sÚ']¢;1æ™5f»Šv_[ÙÑëƒ` Ò¿„®äšóIð¾)1ð²i9_8Ü.:Jm#g×—2@r:Xj R°Ï,ûÚiˆì~£=910;þFmÿJô³T´…†¶‚«ºz¡F¶Pô–e‡¤1oVXØ()¸®¦KþQoíyAÛ¢Åöêó«PÔës¸:Èpr‰±íŠž Ìp­`ìsB´Î"è Fà«X«ˆ¢ÑvØ 9'° ±Æ(“ú´‹W”CQ®=qâ«" s9zjpÔŠÓK¬ Uå€*_çuÂÀ´¢]Æ'ö|m‡ÏﺳQJ¤h‹/o¯£î¥˜VàM÷! ZÔñÕ_ˆÕ i {[ÁFêü•Jrè¹VŠ|‚-²…“ qÉ¢œ·?¸dgf»ÁŒ»ðœýv°ÃÇ úÕ;W¡Š®Bv¾ÎkhCŒYØ”pW;äŽ8Ÿž]‰js¸hÏηÀc÷vv;¡¦ Êc³›lÇ– ¤&u?[ ëñ|GÄoµd%|¢óqÞW{8×uq˜õºê5n…ó}Ï/%HwÎ 7ÑùHö¼«à‹‹âüü TU, Ï._?ì¾zíÂËi祸Ññ…ôc/Eï²rJ˜Oª…XÖ^¨³÷Lv*(íâo<uÀÌ4jÈ[¦Ö.¾z'ÛÆï5ÊŸI«nÆÀ Ë€*² F VS&åE 1!;áÉ"äT@z6»\÷·)‰Ô¡„~oxþ,u×.Ùw?ÍXbžsSiÅì²×:õh¿{iôbú©Ÿ ¢¸Õܤð‰Jkqç•‚VUöDyû1«²%^> $*x}£žZaõT ¼ÿ²p—øêÇQÕ΀&‘&¶Àç ͬ”,³ë×>ã*J-Îõ FMSž’ríP£ê÷u½,µé(×ή§wÃ@xf³–_gˆ)‘Rø¨±å”ìz(„*BŒët–MÁêèÄ]1áõh4t4´ÀË/¢ÑS?ˆFCÊ.Ãש‰>púÀñ@z d„CÓ‚ _1å(Ãö?ììzÛWËÐmÉ5|´Ÿ£8]¯»Â<7ûlŠÊçżZ0ð§n9Tìå,\¬à#Ÿu-E#{šÇ)|þÒ7XUÙí냺´·¸e_Ï&»Þ©KoýNº9îBt»÷Aq8¾:K¥‰ vû§ÁîH e·ƒr3ÑÖ£šÔ°pc”ÿ0o°“¤µÖÂÆ?|×мf×óXOhlÙíº+Ât¹T7Ó¨¦qÊ)…Eq»íDÿ è’<”VyÝ·¦â²Þå²_e–~˜*g” ½ÊNI¡JšxI•¥B\د¬6ËžÔíþK5»Ž3óø­„¶ëíy8 ÁPZ‹Éž]°]ï_‡Ç†Ã¹êã\¿®]° ÃC–œñŠbàUƒ¸d£¸îzõiÿj¯îä_M«½:•ÿ?aW²-+ªm)B0Šæí¿#E°.PÑ‘_ÿ@ ¨±Oë4æ&V9§Ú®¹É’&e’µ «kˆŽˆæf_kFùeI{{æ´Bg 8c‡>¡ºCe‚¯ç|J]º=¢¾¹ å‘Ö…%µŠÞø¨¾`Zg5P—Dï8 Àv|P>@9 |]·’ò^;¬Kê¤]l¦ }*Ñž«½]߯ {ضå”k;UUM ö*z¿ƒîálWÁR¾fEkbŸ¢õ¾aƒ2dg×:dÒ°ÚVté”;µ#ì'írr±î€“MñÕræanµŒnh-[ŸÖ2ú [ZKáÒZF‡.‰ÖR¸´–Q¨‹àÐZ —Ö€·´–‹¥µà-­åÞ\ À_´–Þ3þ¢µ]àçîv]öÛõƒÿº]Kè+l;`ÝÉ™uX).„^BÓ›¿ÅH•Ÿ@«®o\ {+@2¾Ÿ—~P·òй@ä¶½[Ñ‘IV™,2æ±›‹³é«‘וþ nŠ¥nW–OyÓ4Þˆ¯»Fú² Ô¾’ž9ñ§'<âVðh#‚«ÊvtÑÎç¿ÉQn-y3ê© 4i—ÿþu2>šN®ÙÐSˆÏo$Á[–ýÕ[w…ur?‡à‘abcÀ®ªŒ’4Ï©ýpß¡§É²mœÒºÖi~|ƒ=© Ãæ«Ü ës}>^$η=³wîÝè$‘S³W?ÍSeͰÑFN$nOù¦C^h¼¢ïÕ±·‘À-C=÷õ87.0ºJ"§ù0çd„%üúÑ÷Û¡Ëú¾l\à/Íw¸>ÜÄâµæûèoÛxÏý¥K_¹ÀãÄÕ¦«‰5‹(Õ‘YÒè‹CÉRÀ( ©M~F{T+·5/„˜ÅXL [Gߨ'`¶Öµ+ºdDÍÀˆû$í¥™áë";(ܤ h˜¥V¦Â˜ò´göìù¾E‚´5!m]­V±"ú¾Ã¨KÑ‘¼R{Ì®up_§–»H™…,oÅ ‚<—‡çÂð^@ä¹ùÂÆkwÄ«¤ªÀ ò….)|=Oô—KZ¹À.éÒ¹À—T.)ñ})³?o#HyëDÐ3(Mß €Î¢UC¯óܬ<ñ+AM\½äê¬_„¤¶ÀÈQ mûvœdÃgˆ\Q&`ÉJAú‚%ò„Qz•B“ÞéŽÖ"…=óüx"8Ý$ý¯ÙœŠ¢Pz<ƒÊ‚¤Ò‘võëÒFOUn7¡µ(i-kˆŽ‚*}Nè×6>ªUl\ ¾b´Kiz0Ú0v(¨ÁtUóÝ« po¯ý gvDºd‹.l툧ÔêÎY."ÈÓ;¹ sÛ]ˆ‚:{sPhžÊ¡˜rÇ…~Nu{ 0–2mvƒ¹y×Kãú>Ëëp-êiÏ¿D==à/QOáÅq-0ú+Ž[¹À«8nëÅq‘«q½¶?þŠ^W.ðGôzI\ Ä —/§UV@û%¾n5ÙªqLñÜœªýš@:a앺AévJ#7‰l¸! ¨öÌ*—r´¾ö•ºˆ hê r¨‹Ñú3ø¦| ë.ҎȬ,<`äô‚ñÑKRIø”¸@ô£ÞÌ.á'äC™·rûU¤Äú3Í€•Ö5ûzè—¶žeÙf?î X„ÎÏö5$ºQü ©å¹2™åBS çcTJï²Þ];è2¶ýž‰£ åD_\ææjºf,;Þ¹@t)ë-–]ÖÛåáªØ‹¶JË”+#€¸ÀØ1 !–tÊW( è-+ òëìM…¯¦ç«Š´¬%§½ Œl¢zF¨“¢9íiÚZªû[aë‚ÞFT¦YÒ“¤‡vã@'ã&o_f«zŠÆ˜£8prŒ‰~k=ጠèüDnnØrЛFD­œ¨Ï>377 b”&û±²u”U*¨ýzŽèÌÿ3ªç–鼫Çb"\ºÀ]&ÔÔ oî^¹ ¼ïæÎ~foG&ÔMжbjrÖ'ý죣ô’r«ÊVvÅ2HhÉCñ'¬Ûƒ».iU͹¢ø{-\ª¹¯&ˆ÷ WÁàß`Ķ­F-D¯Çm´ó-D¯G@öaåVç>™e¢þîëyJ_m~&YÞ{@_Cm;˜Z—Eæê<`¬5wOÒ¹ákÚÇ2zTŒ»Œ!ÊàÊ;i·«ÓÐÄ)XÕé8…½†.ÿõ¥ÉlÔµÖ1UNßþÖñ©b×1êé” B¯“n5|º5e˜Šy°#¾O.© Ù-jýJrfWÆ/úJ¶â0==bªÅÒ¨»Î—ÕÞÓ:©}­ô~„Uv…1g4yW$9o#/“{ùÓ°gÞ‘WÊ¡k¹ gc­Ž€‰ ¤RÈË»z@uâ*ÛªÐ|ÿüŸS¶³fBVã ­÷ÆA½¦1µO'Þ‹ªHÐ;öÄ­Hf3¹íª>ÞZ»||…@fÄe0k(ë¡þyôW7¥‘›N½RÂÎ8|ïoвl» ”1L–¬@~‹>ó]È Pdó`‰ŽQÀA¿õ6ï#æjDèwEŸ‹•ê8.ײ"Ï$ËlÀ×å ?X¨+;bXg¯/…mÄV dÍ>btf¼ØGlô[ÃÊ|Ðí[WS74Ç[£–È­­ZfGÄw™q6ç¬ÏF6÷½€CÊIUžÈâšUŽZòÐç‡ýcêHáØãÜeS% d¹y®ÿmÙ_M–'¤,3;=¥n|p-V™Ù¿}f0â7 lJ9„Hê¹›F’ Hˆ¡#ÙddB™mÓªëqT»‚^)äªÇy…ºSþ”°»“lº„[-Ý4Y‰9H_¡@=^³6› ßl¡uÃkÆà¤øÆ^`(É(¬õTfm©^ £‘×ÏuÕ§iW愚¨UY(×jÉ)—¹:ñðtù<ÜÅX×Ušó2‡}í$r®ášÕÆ)¼¦ª-¶Gmê<Ó»aÆxFþˆú€4#v ŒˆïëIRAÀº“i¦–3 »Dð¦VAâÚjÎrÁ«š™pNcƒ¼«$rYgbO\úAO¸.ÅY‹ÞvÚa'‡tVó™óD¬5£¿ZÉ*¢¿ZÉZâ¿”I숡€«Öý2·+]ÛUY _W‰îíeªdhë „™ñã}.©6õ¸£ò€²JòÊFG£ 5 ýÅ4ÕiϧÌüø«J´pئeú¯õg¶¬\”«€íŠÝ6-/êºÉÕ # vDá¡ Á\3ê¨H’¦è9ägðóÞ,ì´Y8ƒYˆŸ¿ÍÂBB ~"ozür“Œ–Ékí$Iô‡»T™ò'¤u9­€Ÿ8?Ï8êglögÄ~[LðŒ½FK|0Æ[Ë>7¹¸6KFÆX?dt.$ã¦@}xU)·¾R®Ê@?ª 8S´.b-]sû2ï«.ßm+Ô,í˜Ìí<~þjO·EM9•ƒz<ŽÞOkͳ Dz²å€ GÏPã XÆrÖõB´¯]àqHée !—åBÅÚS(ŠÅQt6â oÇ&)”°â(°R6)ìcÌDE¡0áQÀ;ãKAJ Ä'`§YÞ%]ÚÕÿé°_?mÏÇ)M&a'ü}q»¶IJö?·À¦biÂö?çéÙJü··®E0"òÄQ7³'™3JÊ~†Š!Æð¦n©Èil4ëiá½ÔP¾íºU{¡§Ö¢¨Ì”ºu׊¶ö€‡,Ú~n\$yÑ@B €±ûŒÅv-ègœè´?#züšp–2;=èùcÂ3u}Û GÏ_ÎaÞˆèú£ÓdÜGŒB}[weо³+ƒÐ•aÊCÚßýZ™|œrx·2½èkx·2cº¯ B¾Ò¢q »n?]SeG DÌvMh=bÊW!Œðª¯Tç¾Cà…Q|¾4·ka{)äþ2q°„î×3Òñ˜Ç×yeŽŸ>å0zÿúéIùí… Œn¦g§Á??¦§)J–7.ÐSó)Œ­PÌý E â}ýâMýWÚbš‡¾Ssé#¸YÍÕ4wŸ%Ø{6%ê=àó8g0ºyF tŸÑËT˜{:ÁœOÊ»¶»§„méÝ «!².§ÞF–©vËÚ[*«níÛtõ€.¿ê¡Æ@“¶Ê!å‹ñ¥ïjúÖZ®*S±Cm‰§¬Žº:Mt~ou›ŽÈÿýûŸÉJm!dÙÑ…]JØøèbûG*+%I(XöÉ,h®¾GEà 4(¨²q³Ih²4À;À×%ñ~Ÿ´;ñ>vù¢O‹ò ¡ó;}qÿyLˆ 8ör$Yî‘ûQ×^¢-¸uSðûÆÙìǦ%M_4¢µÏø9iùu[¤i—+ûÌFk»ûÓ’.‰ tn×43i®¦mŠB´yi? ¿ÀïàªOÒ%S7ƒ“‹±_«îZ¢Ê­ÛRýºDŽNÄ !™2g$)\ ¾}Æ8Sñ‘:žÑÔ*$¤Ÿg¾?ãA,}~ÆjZ“ýãÇý3¦¤§Ä„qüð+ ¶ ·g:)(Fà#+užGu”VÇ3F' ÉÅ)à:¯,FÞ3rã+U–‰œ© D—Ó3dƒÿtϘ&uzüô©y÷ê`[DG-—GõŒ…«BñÄ×RAxý…8~îó™i`ÓðE‚mæ´6úíEºpÇ5>âÏ͈úæòFü„j˜·z ¶T@F„ãï½­p¾¯—q.ÃiøÓ‹ºdöŸ~=L:4R`¼À¯ç­ñ±´ƒl'kI½¢‹­ñážáéÅ„;&W•:FÔÓãˆNŸ™³gˆÂ[àï=3ÎÙäo÷L"¡ü »„›À2H!_8÷Ê´gµ]™ø$ßn’$2™u!ÉÜRÝ=õñ2ñý!¥Îžêx™cÏ\=Rc§iÀió¹k†´ëí3¾Nl†1©Ôý3’&öBrZD/Vf(Žg·+³è•¡ûÊ|îW¦­:çëùܯŒf~9^æsÿ2êv¥rN\`|óÓ¬:Füþ¼Ø³ã¿?/öYB~}¯®8ïܫ+nü~üºâÐ>ãûñ늫³x{Ååh7å¡\ë¶4i‘­õgøÛg©NSUàÊáêÙœ… t8|·ŠÊÍñ†”°tcñûyo|t yzÕŠéšÏ–•€ñ骾pHùðu÷ÖcÛ·Ž~½u=çû3F·oÍtP1³~áû‡µ§ŒáãzG÷o]MÊ~dÞOÇ7Æ°Ú ‰÷Ó¯3Uôv6½¥ŠÆotr| ‰óIÒ.Û? ä7tšµ‡DÓ¦éÊ1ó€èìøèûÚu|ÞNÄásÁO ­¯`Gġϕiæ§Ç2ó€>—¾Ø½ŸÆ7j‡ÛôŒ}¿OOücz2õŒ6}õŽNÏšgЛž#–2Õœ[éÿ˜ž^“¡Û_?§'_3LµÍˆš(€ÆG{ºm9ÙËM’EŒÌjb§=ý{óîF›ÚÚ–­°á‡÷ç¾®©«q"µ ŒÎ]l¥ßņ h´Ñô¯[íL-‹r™JHïãÏ#(²ÙŒ·¢/F”Ý:Ú´‹[Oaê{ ã“djK¡ŸÊ$¬>yU¢™eiÍ·úáºû ,û¾›ÇŸÇO|3S0nÿõ¿›ufª²rU6J kí¶,Ÿ#Í¡Þ' MUÖ[ª²ÞS•Nõƒ_P5ùUøó Ðão-Üú•ô<®2iXÒ'ÐヿϓļÙ\I?ó¾ê¨ }~Î+ Û**)騬ahØ•ÿ3ÙfS¯É ê²êYïÑKLÖ¦C§îWpÄ¿èF¾õáñ@+1ßúóØ)“¸Tê¡Ý ;Õ7Úß°ÖßÀtU[Ëlš4ík­=^Ùgüœ¸LZººd¨eÃí~Ã.¶ÜHƒ&’i™›ãÇã¤oTÑP×î«àóºæ&`ôW]J@ôW¥‹ú¼ ‡oésøÆø/Ž¡€¯?*¥Ë€ï»JéÒ«”ŽÝÊ‚‹JéÊVJðºRºu*¥xQ)]ú•Ò¼«”n÷JéØ)jð+¥K¿R:~|~VJ—¶R€?*¥!<?¾7•Ò­_) À«JéÒ«” SÊIEBH¢Þ¤ëLž+v /0 ͈Kë~¨#`äpÙA7`²IuKb?ЧOô£ëR84KÊl%ãBìˆAÏÙA)ËZQ.EÁ:L6…¥ÛJ®N¾zÄãgÈo¦ÉôÒ,ÃÜ +Y€J?~¢ )ŸŠQu»& ÏiÖÀ<>qpÅ1«•9+®eÖˆŸø¤™ƒÁžw”u+ÂÇNá…%7ŸIÓU¸psÅÏø\„h€ÊÅÍH9Á5 ÀCÑf;ÎL±Ò 6×P@7`ü êÍR[¤½¥º¤ „à•.ÜÝArúµV_x•¹@äÝ®›SÁ‡FB\àN¤»u_k:-ú¥Iížqzr¡¤:ÛKªÉ:ªÛÝ>cÐIrÎp>ø²€Qp±ó­YËÊh‚©c%|ÞðÙkÿbþÿ®,ÛqˆnÉ“Àþìô9/K@ Ð<ÁéÕD!#,ùu:ùª ,AÍuoæ¹è“Ûí¼g¸S¬ÊýU¸Ý?z†)ð˲É–›àã̉ó­é`Þ=Qkz³oMOnY.ƒÄ{£SæŒO%X…Žì …¤´¬z=hÐfá¼ëÎù µ”²-$ô %·WäÄ8OÂ1ÖC„`XJîÝaHw±ÝaF[€¾OK—ÜOKCRô*¬ H`ìD+Ä80A›ÜïѬ”wSÄ(rQ5ºÃ’û~B,Ë™§¬Öm=Ôº$ð #ÚO0KÈ|$áÄ":ªC¡se‹‘ÐÕ”„å}Ï›<½œh:jé÷x@øl°)#mÓBû|N,F\lƒê‚”ðe—S !³¢„1Îs·¦4¾º1 uC,IXcÿ»âÐOF‡yjíÿ `èBͶO-bâùï»KQ¸X¡-Xn"©¬wæñø@“pEdãë-Š-€Þ%¨•Ã(R ê‡ÎuC÷lT›÷Hˆvè”.‹ÖþõàAãBMM(øÜÜ“™ˆ‘sÏ:ž<^QtPú¼¤ùKz°3ÉåA+&×Ï=ðýúczˆ¹’äöyßÌèfNO0Ŷ‘Æ:ÖqÍyÛhêáäqòhx=ïG|`P7_Æx¥þËè¡1±mßĶI²Ç§°™OgØ;5Q•µƒÓ“Dã—ÎxXÚ-­´ä‹|âS˜;“êÔØW&@I%1ˆ78¥‰—¥éç1DU ìaæ¬k‰”06$è!!æÌ 6Ù\d5€ó'(¨Ÿw1)kIR íO Ú»\+²»3H•¦d6¦Ý?ú¡hyšL¢eªå_1‰Ü´Óx0÷„"h^€³7Fa‘Œ5 pi$hÁD -—ÆSHGÎ¦Š†‚÷7 ¤ö8™&•‘lðŸð³ìy 7hS0r’Dk¶OÊéǪ™H;Oª!¡àm'è‹­`:å{ÁûÑ£í´Kù~ôëÛ£‹)ÛV|}{´9<{Áû‘ëJ25Ž=0$Á(Ù^Ð\×,¯'Tž¹jª€Ê3Ág ò’ Ü™ ×üd3H6 þl³×c¤º`šKprÔ=k;Ó­ Ð\xAôM05q³ÄßÍÕNðv²Gª¹Sðó+ºÉèÑMüÙ¹ÏàPhà¥$ÏKPãPPÌ{¯‰Ê–$žË\ÐÌm„d\³Ò'¯’ÏÁ/Ke|Vu—+èuM‚Á¯“”¸3aêó_ˆÿ8 Eª8¥˜¸çcç|mæÒ…F›õ­èG* . ¡'Jr'‘)a\ö¶ƒƒ’â…;¸ÆËÌRI;Å=#0"JÁÄå´ÈòÁ4 †¸®.©À;2WPnñ‚oóñç¸ØÜ0P7w–NSÈPðóaýg>RÆ–©>xçH£à¬‰‚³W”涉J—Ñ]•wJ-aÒ—ýüü¬×ÕÙ£K¥VÛ£_(Z06ØÌÒ,ia÷@ðþÛT¥_1üúï'$4AJKGö÷Ú†À'5,X”_ñ°ÍvmÇ#µÑPŒ‚~áƒNéM ­¿3¯ƒöùõÎLcË©ži .×ëu ¤\7wËG= ˆ.¿…R Pˆ·w ÿ&ApSZ«Ã®R:ΣPD—{”ïa0~™Ê\’²(f9€OީϘYrì{fþ…N@tyù¸!W¥û>€t½\v“‚ˆ9y]Mèz‰€§\eÈ¢º)Ñ©´Ë[¼ö|XŸ¹Õ“ž¥_1.@0èBNg­Ó¶¢€Y‚AkÝëK©¦m8퀔E–݆ÙÜ­I–‹šüŠŸ ÷z„nŠRUCæWLNU³L…Ì<{ ²\1â…$æxû<. ²\€Ã5všY!Iî?a0ÙdSvd·/ܬ(¤ñ/ÀïA÷Õ&èF¿­ 7rŸ{Ý“gp(晘:â¯B¼úYÁÚ¨£‹1º'e””YNBÁ¨ƒ ‹MìJJ¨T yîd¨ ®B8+å:€± /ùêºZxá÷øÙ'µ^ÞcèR‚£‰n¯„1‡v£%JÉ´A0dÚAÀ7{xfâv òÍT™¸ã¢Ô Q85txg8¸A‚ È"@0«³²5ÿ€tÆ/혀YT™17=†<> öá†/faMa§çŽbAæf g›»2Ñ4¦¡ ·gç0aTÓ”r^0¢NÜè¢HŸÍ}^|E°e‚©šÌiÌûÎÜÇǨ- K 5g¬ªZh²A!gÓÏ ÃlK´6æó%ÉùGôÆs ò…cèZýðº¢&@¢¡àýYà¡ÕÒ™ó¶+ÚÁ¯¸§I78[×ëIð úQÛû÷óãQbl<#[*-þ|ÂÇ=fÞßl–|–”zn@ôx|ô}è‘ÄÝp][šÒR¿çÛ[~¬¦ 6벂:õÚ­–©áø·¤4Ü(·÷NJ‹}R=¢¡ª<_¿ +«~V¼3çŠü…oÀ÷CY¨¢JÁKI.ŸTž«Âèfw=H毹…í¢üë‰FòVsMù¨§…@i…^ÁȉQö98ö¼œÛeê2º´ÎÇ—½[¹‚õºöùBÓÀñåòÙ'Uº±óž­a„_¢Ù=êQ~ª'ºí¡‘üÏk¢iU)UšÖé8i`YÆa¢Ò 2 †½-’E x?ãXRÕë Ž•¶µˆ;^©ŽÉIê òqêä¦÷¹ëaï:Rµªàm7žÎK?žn¼=è"Átà›ù161ÏCÁÛ a¤®%€âKÄ~éûûlV!ëëb†L~g4áR¨J ‹‚Ä$›ý ÊÖÉXîìŒñDnÃv§šñ5bCX›×¬Ê&R%“€[ˆ¯×ƒ;ã vN&c‡¥_ñv¢q×;óÖx—¨üÙk3Õ¼5;£›q›d§ËÒ.LPàÇ×(XO¸ÛcCƺš!ý€#æ‹5²_¸±šê….©¿3Wtš§PÕ’>OÃæ¹¿ë ‡6²Üö‘]àüøŠ#ôyÊú“9¶9“dbþÇ5$'™8^ñ*ͺ<{<¸×Ö§0Ç}ö÷úŠÊ¾¥Z01O©9u(í‘o{4a!ì1Ìh®% ަ&`l) °ˆo×Zœ;g¿'Ò¨‰t9ñ¯çì< :5ÄûêPð°×U¶95ž³A¹×Å6±8döÑS ¾ÙÓ·òþÜ]Ög"ƒ~{žÝf÷¸t0í‚oßÎcjÎ#ŒÐã õióá¹,!­(;béjh(¸[‘tl+jbØã=ÆÇõM±©L™ä•€2 îWÜüðÁìÑkŠûõüÎ(eî ?qÈÎñÇépgâ:;Í´zp|?÷ÃwÕ|¿ŸvÅïª)ø~ÿ­šâÌ㤚"öÕÒOìª)b_MÁ;j‡Ã̰4ú-3<„‚·;#L¼—ëÇËe¿žÍ°;höYÉÒ ÆF³°LÐ6¾f¹Æ"y£y}³\o?¿ó¸`]sæ­k£Bëú¸~3qo?nŸ&ÎQXרÍÄ=bÈDßË%ÁIYx„*üx| º¦†¡ä&ZXF¿bòÛèŽß#Úã®9ÒÕ K‘±ä™4þÒ^“¾_f¨}àÇ3ê, +^±÷t¨Pö× ßUÌi8h”Ü7!öU7õæ]ÂÀ;>m”AŸÆÁÉí¤ë=Q6NîßûH—Å >¾ ¾WL¾7s¾÷ˆ¾´‡êAï ‡ùÎ^ƒ;c -QÌ{{ÉóäÑ–Ÿ'ýúÞõ¹ ¢Ëɯ†·_®ßÛlß‚·]ýš°» $Õ„‹ ~5ºŸ@¡ÎT*F_ P½ óQ˜2о´¨‰ ˆb¬OO?PÚÝ É+Œð‰’‘’Bϵ×Dj}×f[æãËoJ ~ þÕ ù¼Ëîõã°Ó¨|¤ö†·ÚÃûŽ¡4/27SôyWey¯ÀùÀÉÇ¡ð¨nŤ‰˜`DÙÂ4²>oê o0ÆçhdÅ<” Rñ?? 9n´QJ®%1ñøøõ[Ý£‘åw‡¯Øwøâç5îjÊ\òúz¦¾€q`üŒ«>=;¨aPæ‡ËõŒ°q ß ¬Ň+(ùâ oïŸ1ì™ïueߓޯ¸}™¿ÿþþ x¸¶Ýaæ¿^Ük±SEø 0zØ'ÿxÄ×eA')regina-4.96/engine/data/census/cusped-hyp-or-census-9.dat.gz000644 000765 000024 00006325217 12400005715 023554 0ustar00babstaff000000 000000 ‹_ çScusped-hyp-or-census-9.dattœI’¤¸Ò€÷ÿ)Ú쿚Þ®÷UfUG €RD d$Ø;ýÃ]ÂȱÞåך|v‰¨êOu»ÝêåõÏ+IÔ?ÿùçÿÅÿUø·öþ¦Ýßê_˪ªlo'økJ½­­—ùÍmÛû'üµ8ýu²ë_Erœw²0ƒ§¿öø×ã¼u3¼œvvƒ‰ôŸÔ^µNìZÄbG!jFç(Ľ«‘¢@ˆ{çÜÖ»:;ÇÄy¶8¢8ƒq¶wyl‰àjÂèØ®pWæî–5ÆwùµÜ‰é}L~Úîùü&föì{ªžÏ’Xzdc)سlŸsꟗ}ÕÄòS>êÞ'6m8{²"­OVçL6ï ‰¦í»æ=Áñå>¤Ý@ó«[Û•“'U”=L*êo=1yd †BÏH°ûz>—™˜>œÐ§ÏÌ9„Î¥{3´>• »àCOLžÆa™"¤äÆaÊõìvž}[AªêP æ×:CŒÐYã”Í8?Ÿ ±cÙЭëµÄÔQG}×¶ÊìçÏ_·•¦{Øyšˆ™HXQ+Æ•¼þ´b\ÉëϱX±X#±X¥ç´ƒ–­5îæÀä9Ía n6¤Í²uz7"?·a™;b›Ž—çŸæ˜‰B¡¥93~ΑØ)OÎÎRqðM¿Þôß<”}ÁvÑ®SÖæ±$ôìló˜EªY_{Ïb_3¤†÷•žX´¦À4å}Ó“‘MàœocÖmMxö<ŽYSYv=1¹ORD`Dzý§}½ˆéC¨ïË C½cæÎí`›obé}–Ÿ;–|ºê íò,lõWð6XËÑÇ2.–7.­f‡XîüýÃÇëLDíÓ³…ûXb:²3\ÉhK“Ý8>&c)’IÆ7'ç+㛽u6ŸÅ2{öK…ñ%+"|ß[‹ñ%ÜœÎÿrù{¿ºÃ8;û»Ç”ÃýÍ3Íì³­Ü^R–¡Þó”÷deQOLK˜Á•0ùÑ€=7ÛÍ÷þ@±nÀ|”\ÍàJ´¼ˆýïëýµv´³ÁÛY^Äv¶É¬ˆsÀû¾X´ùâhóh×[MTHF^·WžzÝœínãtÁ.ܨÄ0y¥úYb§§tûþ^ûF%8\ð^C ÉÇ d)'@f"gò˜—™àê3/ëc„2kgûý­’ì]P ý´’a/`/ ƺnº+b6Ù=“ÇÞ©mï1µ×Óœy4gOsæÑœ=Í™G±`•5Þy(e8=`®Rг3¯#•ó~„ã2V·#Ž‹ëzY ”N¢9­÷w¥ÙœŠñLÞB¶þÖõ©J.? ìE§¬ß¢¯è”÷[8Ÿ.X¹àùLÂÚ ¼¹)ömbÁ»meâXz@û4itWòõ5Mð!˜2ŒõÞ&˜w Ü ÈÓä¼Þ¥¼oްÏTpgwöÂÖnÞÎRŸá=cP‡úlË#敦¼M€<Ã{À®ÿF¢òL'¸WÙ¨òD¸Î\Ïwe‰j ¿ÿ–î¼kKØw]OÔý󷪫;ŒÆ²¶¢)ì~Yps²š§ÕšÃžÝºõ¼·Ž¨<еøþžUñyçQŸ÷1÷ü´aìnϰîb{ø¦x¢ßeìO¾íè÷ÇóÚ©] Å‰6ŽÂ§Ò+Íy:¢~EÂZ|ÝI4²œÖY3£Õ ήk%Î|ÐÑÎ6º‘¨t¶±Ñy]wž‰ªƒœ‡©÷¶!HGGY5ß +¡9EË z²Ô¯–óh¼+§}!iW;/³sU¢$I¿{ËY[¢5nTF¶ñ=@Ü);ö9ÌQyÒ¼i¡¸ÒBO”ÓÂDô|^»i¡ˆµ°´ý&çüJΖ('ç@ãu½œsZ÷'AG2¹Š“–('ARðú½|U±/…_>Lô룃M’¥‰58¥á4h=ZŽÔìXo9RïN´“|‚=ÑOŸÎÒpyA¦¼4\N‘'ÞÇ+YpÒè}¬“9/ 7VqQ…â¤J.äŒÒP|lÔ‚’ŒQU𙙢¨RÜÌcë$©ÌEvFIª 9cÕ…œá­u¢ßbcì¼íŠ“äJý‰ ^GÎê´àâÆè­n»û?U>^é„ë­N''9û=»Œ£åUƉJF’`uZ]Ir$Êe+\W³\G gu³·:r;{‹Õ—éfà<Ôn²*b›„™½Žrv즣ü»ÑÚÍE¬svef]¨ 0KÉ[ËìFð’töl—a{o“Æp^Ö{{6>è×M/r·Ûsv1­ÎäVçfÎ/,ý×|Dr±=M.b;æ…ô¢n‡û'úAG{¢2^í*U±#Rªâ±àû~Ïú"2¸=› ý¢ŽÒô"º™3^¿N é¥,QN (âbfÔ`–ðVçl#|>r’Ì.³FG”ó2¤êÊËf¢’É ýL_ùH23|Ìq:Ê2>^9ýféuçͯ,g"ÊìÙ·ˆ»Tø=ÍÐÀ®ò䪗„usÁRë:Í\ÄU|eß|vD™¾ìñCTÇôg$jδs]j.¶¾ì@g¸ßÚhFÔíªüø@›t4?Öϟݳ­Ây‹]Æqy>ÂX‘D °íÑ„`úãGÀÒ¥†²Zi³âáa¶žJnîCe×$»[[Çíõ~ò¸“ýDÊ´”`@9ãNø­/¦œq'K¹bÇ.®€ËW”@…3kμì<:ãÛ_UTN‘Oû*ë6P7`ÕDô,­¾q)<Wÿà5*ªìÝžÃUÅ© Æu ß$OØžåæÂ%¦™¨ŠM³ 3ëØ4±ÁÎÍÞ%v¦y 3§Óë»á§ÃÖ.7äÔ.vÜ%HnÈ%È.¡Š²}8Qq0˶ê7³4Á%Ž}Q³³™¥!—8߃àäéÕm…%ÊõÉHù oSSv¥¦0–SÓL”SSO”SS˜9=ERSv¥¦‰h~ ¤¦ŒSÓ¸©)cÕd75e¬šì¦¦ŒQ“»CË̯éŽ(× #-Xoê\!ž` TÅ´‹E†Š‹à"^±O0M]» ©î£¯VZœZ)LóëÌ/¼p,>ZºXZð‘vq—w…äJ@(A‰…à£t‹íAqÙþáºü•±´…ºŠ´a¬Š[G”s¡¸H;z9ê*ÒvDS&³àºæ*³tD¹–×ÕW-ÐHΓk‹twÕ ¬G‚/­Vë!*™ÖÇòaÇÛs‘]ÙsOTÅm§“sÆÙ³Ýäœ]ÙsX7e®$pÝüªu´D%sÉ‚c‹«öÏe*ð_‘$úO¡$n' ¾€-§’¹B*¯šÃލd.Âp¬ºhKÜXuÕþõ@Í…ÿ:i˜‹¸áÖÕqcè‰J¦…CYeW²êˆr:™Ó+MD·4ÚT.NÎ?ÄIÁ=c¸‹œù²9´D%s¹ÒÉU+ÕeiÔ‚¸Œ¢3Q.zÃyÅeô‰J¦…ÃuÕ•öå´'ºÔ¾%=6<ðªKžm°äXˆimÿ:\—‰uð‹5ŒuB¤\#m]å/vO aæŽfÞǺÒ5ið»æöYÍ™±73Ž-ΤQ–뉟0ë¾Ûª#JO˜h¡žÇ¥¶aæ]ñvÇò¬-o3Q*ÞÜÌ?Ë ÌM·Ü`†wæï0v-Þ~~ýÝè¼– öùAÔ·+­î½Û¾alxä8ê¨í`ÝðŒ±×Ñ2x"ÉZì¦#)ã™{Ò‘äë^Iˆð@âÇ6˜SêÏ©ff¹=ï{7üáÂ:öãùœ?-ÑÝÕ€+°mùfÖ$+ô£éݼ—™¨×|RÙ¹­ª¡3Ÿ ìÛšž¡Àöt+°×­ÆuëùfÎIw×n #ú‘4l32â5¨|ÍÐ-S ò ý6h?ã$9”^ûy<3üž¶uÚÏÙ<-NÎs• ß¡c†U{«Ûl²Úv¥D¬}ø7z´v%yí] ŒöqÏJî´¿Ó`ÛªÏr®ðÒP„G}í=ºÚ[°BKïê:¡ÌU]g‰J&N"½Š“sOôäƒAÎÙ•wƒµ«ü»4r¶¢ØNTð'j1Šªât"ç¿#f+ÍÆœÍÃÐâ'Aý“^¿Î6Þå×݆™õQû¯Í÷·öàìûÏÏ06¥ì’¿—² ëf®»ªç×{©Ãžóƒ]Á¿pà"ƒ£Å©õÞ"ƒ—Fr íü9,âæ{w&q~›±¾ ÍÞ¢®&]â`yT"6ý‡krEx];^daãÊ~‹\˽"6Ø\X«+žˆr.<å\8P}NvÖ­ÙöùûE£6|0t K§\0\q Tžxk2. 5›4rÞ\@Ó9#×ÐtK Ï4³m²XœkþÅ×o†¹j¶«aÛ|ù”d$Ÿ’Ú)Ð(%NG†ÿ6bê°”5š›y©\Ab4—’&Ÿ’ óîŽ?5ÃPiR®\»dK4.uüØìb,p“±Å¹¤&¿ ¤#Ñó‹ïV`›«o¹àâE¤û0KÒ;×"¥ì÷X³×`*¯ŠŠžhÔæøâ-UWER}QT Å¦—×#8ö*b*LÍ1^9‹µÞbÓ«ÝDz/d[9zx‰Ü5#NûiÁ5#›öÓ‚ÛÕs²„õ#_rdWßÌa͘ïÏàŸ j8V(h¿ëøeÉ$2ujd`æ¾ìÚŸ™¨"Ëqëúo@=…¨òó÷o¹¦+F3¼§é‡¨9EÂÙ—²Ùá Ñízóá®7EvqÝ«ŒÚÏRö{Ÿ¹P¼Fƨ’ñ×Þ²â*šÍD£Ë@¯Áœ}ÿæ'ýÞÕ ]»•l´Q7ruQDÙ@¹"j"ÊQ=ÑcÕS•««"*ŒåЍ0–+¢eЍ1ÐâôÌ´Q^qe?ÿÇ×—%;«#ÝNåÔóXïu"Î?Üb°±{CÔè/(%$ SûÔQZB¨ÉvexáÕ®B”k>\Κd#kÉû‚«ßàÁ@îèØ;’Ü'žkO0Õ)Üá`ð€-·¤MA-éå• ô`iݲ,rü@KTÁ(ëJ½¶îEщ:ÇĆڽQ!°ÙÝ‚/$–áÞ·PÈõƬ)kC½¶|ÁµõPäÅ6ÀÔ;Ý^{Ü+tì_¼ýÚzô[÷•kÝ‹Á^ð+ Bð«C+CÄÂamåˆXد­È¶¼(Žv ÃoÕ^g›Ë2\g´6–e„Eh™I–åø7r=çȺšFØ)l“´¯Xè™ã+ÖõŒÙÆauƒY†‹”ÍT×këÎé…F–IâêïëµÕ º×‹t»¾µW0ËvªLµ›IM‰Á¶gCˆÁm»¶²ƒíÅÚåXVàb0´æ±g.ˉïk=,Ïq1¸jêµõ`åõŠå ·rØ3–m‚éc{àsù 9®NNÖžÀò­: ¿ýü>ý­^[ý>ºÂµ2}ªó-ô,ŽÖÂ!´î쳺Vo´/t«»ßëï|Z[5œÎá~‡ße =›£À ó,ðUçæYà_ßúXŽ‹Xn§ä έzÅrEøˆ;û\­+¿êrÊSo÷Q^P»{y.j£nœ‹±Œ°žÙ‹[°/C½¶bç•ý-£Î«~mÅ,oËÍéõŠZÕVÎ\´•kÕÈ´¿Uèî¾ÃîÞX¡×³®­¾£}£z^³Ï»\Þ¡Õ§¹Ò÷øýõÃÚʃÔï$·çõ½¶Š ôÛ[£»Ÿì.ã)hÝ =Üûœ\“ËoE†Ÿu°&@ kC0\޵þV†šFíÙ>®­»³îTÚ´ó qô]¶Þw¹&í|—ƒõ]ºÖï²q¾K׺ó]ÖÎwéZ·¾ËëðKû…Øù.—y®ßr‰r­;ßå¹y´ßÇÚj]f{–DôˆÝûB»æYSw踶"”݃ƒíê´=„w²­[sn뽓®óN¶k+æÖVÄ;Ù‡žwQšÞ;éZÞÉú>®­[rå½uLfÔWXö‚DNà…ÿqú-'°DM‹~´¼‘ä”~Z¢ãôk+bïC«²Ùâ¼è–Ž—¹ŠŒÌÿ€™b>½›òñ|…VD›X4k&%a8µg”ÄþµR߯íwèß|/Ø*77¬ß¡­Û¡Rù÷Ýß’ö·š:‘ì¨ qzÃo ÔW .¦2"ÒÆÞÝXBK½î#ň.»r§Z—÷U‚:—1+*AËžÀJj»C•¦¼ÞýÚÊ÷µ³apYÅÚ(˜¢Rƒ¬ü¬Qͺê­Ÿé—ÛA{Ò 7Ú˜¦©Ô {;k<õº±ÁÌL ÂEX…Vvˆtµ.B׊¸á¹â(«X©ÀîÐ)8– ìj×qÊwi7÷"™/ݯ­ùúvÌŠÒSì¨4v"]¦öcGe(¹}X[1¹½][1¹=ô,É0=Œ¹ µíÚÊq°î+”£¶Y[Å1bÍ®I³Y“΂QÕîä79Ggw¨a„Õt´­œúí2FûȾ/fq…1ÛQ)Äšwr™Ì ²¨•Ÿ­$çïr†µu›&S­rÎßÅKØ3ǰöƒÙ7®Î¾a‰ÂÚ ™¡$ è¹ Üå}hëèì¡wƒf]àz·;E‹œ²ök+;FËØ¹*åä­×V†DéØVü4»Ûä VÂÒ ï+Ž–ÞÊ[z]ë1æßZz]«@n:ûF§k™¦ri5DkW-­Û”àÛ2ÏÏfVöüj÷òó²6Ææsé˵u›lr=Ÿ§îlßHˆ“mm×Ö­‹pasÿ¾Ãoù6^q¼Ü˱Y[ÅÆÑ3ëÕçZeÔºüöz)»ûÚª6ßwh~¿:´:IÕ~Þù¦«Ëî÷×V—¨r†{áÙ.Áè¡Õ'ªØ¹¸}?åï2]Ãldί9ÿv~ôÜó¬?‡[’k^¾ðÜÜGol]Hsói‘ çåüZVÍqÍ >˜›y–QÁíÚŠì´ÅÅ3j§µíÚÊŽÏìo¡m.:ÏØ6g`µPCϨt¾ѶUPöÜ~mEâ•;û\I—”v®n¯¯êzmÅz—VMŒ¹±¿5ĘÇvmeù̵p‚V§·r!Ï3ÂǰXŠyž{ž%ÎûB4>·¢6,§AqŒ„fò;œç ð;œçßá6Žo,ã~‡¿Ýç[Ë8è¢Ï¡„Ä_¾±Œ»~¥¨®ü[[Õ~¿ìæ˸ߥ¿Ïoîem5‡MZ÷á·²G‡0Ùq~¢fÄ32Ù¯$kp߬­l¯#CPÏ%ªSÜí ÎsEÅŽÚï © —zmÅ<#ö•yu‚1#òjë=#<7GÏHí=#<7”g$<ñŒÔ¡çgdú<ë{»¶bž‘ð[ƒh ö·”-vRqÔj¯5𽿠ˆ²§£v°=í"2 M²ºõ/óbã_n×V†$_÷kë1ÎJœå¸µßÚ|8cTäpheˆ'È>—ž {ö3Žû\ܘW\¯­X\±ý-âg0“Ęízf¤÷ª^[ÞØÞZ“8£ô¾¯m5”Z1 ¼_[1 <´ŠcȬ«‚ :í×ÖC> hîœg”æ>®­ìÓguF׊iî¡gxmÏ9åA®×V$r‘ü9g”–Ô¯­HÎŒŠáöFâ‚’tƵ•!ÖÛ³$¬+vM¢÷a倧sEX ๊8ëð[Äb`×´ $×¶j"hÍî}®  ÆlP­ßÝe¼ ‚åì9)2J:×Öc«Õθ ÎI»®DŽig½;'EŽg°Â9)rt®ÀKÈ#‚?­Ì(8jßö¿9Ý_ûzÁs7Þv]0ïÀ¨•m¼„ßóùi½„®uç Xô/{à ÜÓ7]þêµUn%¬¶ì^ŸfmUÛ¹êÛy{‡žõ^ÂêÚ!ôlBð粞«®z¿CkHPv®%Aõk+T _A£Y{`ÿä­V*ØxdÖ Ów3Ý–÷•xF§»dNÝG¡•!AÔËs©0øi ­ ‰*´=SAÔödduh=öl­Á ƒoW ƒ¯W ƒoW-Vj*ª][âoµ­dV¦}.bíü&\bY™/ð›p‰fe:¿ —Û¬Ì(g³_[%è¾ô¬2*hܶæD0³•F£‚™ûµ³Ùßr*ú+´2$¤Ü¶ ÂË`ï%‰¨Q{Ö~·Ëp¿‰‹´á O‚p»[t&ýû„T`eQUàV  0¯ DÙ-ó¬s*ðÛþ–Jc±«N3êÞ_¾¾æÔ½?¬­Ø½ß®­Ø½ß¯­±»ÚVAYƒBëqÿ‚†«%ge¥k-©@wû[ìÜ8¹ˆ&¾õª8Ïȯü´0æ¥ÑùµÏå÷÷lÖV¾Í;MwºíZb…²­¤E§_[âq³_—½ï6Ö‚›Œx_+#™üø¾íú¾[ò²õ}Ÿð¾&GßBÕ¹É ©Ïjš†Ò—= £,Xö·ˆ­h©Ô礑Lj¦¥†^÷¾­­l—0ÒBÂßpOù½à½ÞÜ ¤áKE<8½7L\î|¾Ö-$¹p³ÍævÒWÿzýÙßjœŽ¼»½×Ö#ù4„ÖƒÞíd¤-SÔ3´*ô¹ÃTßÖV¶•Ünýça­.FáÏ­¢ßŠÃšœ¬Ì` •‰`g£ 2–çn|=›¨³ež7ÞœMÔYheH\Ù°¶îÈåG.çZ1Ô²6ÈL+ŒFìûœ’dƵ•!ÉSËLîýD!=jX[’Õ®­|“Uûô(^ˆãÙ̾‘¤|—vÌŠò]Ök+C¾†µuï»ìýWPX¢èèN•BSÖëvmÅl2v& eGª×VÌ`[É{¿_[‘/¸¼‘È2â .¿Jü? kå[çÑ=ÿ–•ãZb­o–Öœ²ôÚžQÊøú÷í˜7'°÷©Mvï‹Åüb ùÛãZ‘×ßymˆŒdG…k÷ 抲]·v6®MXOdš’(úµ•íýéõ0ˆÌPÒ¦sAÙdB+C4ú¥5Ï( ÆòFyNÝ¡¡•ohå(Á:Übëo‰NþE*ˆ ~l _cø™¼ÅFä8û„_IY0ìoÕqM.Uþ®oÛª'ÒÓGSˆ\#o4ŸHÝi\[‘x‰åÜp­Ç»ÌJ"7¸ô5vT®-VKYç ¸x ±ÍqƒÃ"ç¸V„ÃçZ¢Å,³ÁrJ{ZÆÌßwž¾­ÊÁ¶tº›;cíQˆv6°’Ë>²wŠ`x¹ˆª»ÙVµM_æj^9óTÚ¹2øs­åS`Öið/£âx¦Xoo ÁóãûBëò¾œá=wð[Né°¶U ·¤Ýe¶-ŸP»]Æ%µ»—¹â ÿ-ìn®¨ûÈþÖP÷Q»¶b÷Ѹ¶nï£z½8âAXV»õ‹-L´ÚßÍÚŠhvF‘ùób·þ¼6~—믚[#kí?‹–º¸x?]?7¶kën&OçÏãd[3äëß—ÿNK+?FœVõ}-^\!6÷àÜx±§Y9Ú½ ª—uüv»6¢Ú~mÝŽùÆŒiǧ©³u!ˆ}4Ù½/4e%¶¿5G+qí­ÄB˜£•øé­ÄbC²±‡ßbVâЊY‰ûµuo%ö«]ÊJzÞZ‰ko%v­¢YÛÖ‚˜«…ž[HD®³ïk%™!÷Ñò¾Mh囨¤ïXV–E͵ŠÃl<›¹kÝ‘\{›¹kU»Ù(ÁfîZõÁfÞßïk«9Ä¢»ßæh,úËÆ¢ ™c‘#‹>hÇŒKîä—x1wkH̰ì»Ú£(÷(F«¾<ÇÛÚ$U…µT^hC+?ìP¸Ù·1ðѵ÷ï&>²ó[ •úxÃvë +5q"Á™ÍAÔɰĤ4k+Cä ÛsAÈ͸¶ |@Þg Ý)ëtdeš¬ü¼!x‰­LK„†ke[ßÓóòíi¦²H6s;åÚ¾_×ÅäZ-ÕΕʩÛÙ¶â…ëºéùZZÑzù-­œÒD–¯ HMÄ>w{_Ïö®ZdNÑSÚl/¡ Âú8ï²Ïï³´˜^ö¦þome»ÖïðèÏkëÞúáu²·=EuNÈÞ‹U͵"²÷bÁp­ü˜Ígå ½+àì +4&©.Vh†í…©³Ù½!Cm9'5zÿ:o‹Ð?Í`ÕiIiv&%]Û÷E-Ý0 ˉd2¢µ~/¿EÊ}‡wõµ{_G»èÒj-B»o´HPíƒçêmö"ü¶9U=½õ–EÜžHÏÛëW>C«D¢s—÷59²b›ë½´RßÁþ¼FçÖk+ßGç~lt®ˆŠgl£s›Ð*‘èÜamõqpã<Ç÷µ¬Ã¨ô&vwÖo vWDÅ3Ö¨À§Ý¡xÆ>t7¼QÙë‡1<ØGönBwûмÎ]å3aÐÍÒ» ޲ôœ¼Ã`A)Þm-ŒÀ“Å`Áo òñEY¯­‡”wõ´ `ï®~Âl>LV©ß$2ëe„1¯ÔéÛÀ%k ¢çþ¾¶²½±¨e³@6éeüµÖM Š sôà&p­‡à÷¾EŽªun®6&hp8,W{nŒÌõÙþVઠ°[c¯K›­/÷²þ[[·N¢¯°u­»Mz¿T5ae!ÀÖµÊíVò¶®Ul›ð[} °m‡µÕì7Rkãk]kq4÷Ùã®@ÌP 0Ú¹"Â?,m…( %øµk+¦ÖÙžc%w¿—ûjþ‚2Ë(µ®YZsJU±­ŒRUÚµSUÂo1U¥^[1U%´îUçºr­˜ªž«Š›UU\ëš aç¾Ïö¹[µZg)7n=ðàMÓé¶¶î]„N¹–[5ôÜ…ç*¤5|K ,|ë3+±ö‰œ¸¬Äˆ: Gÿ"'Zíy…2Ÿ{güHù®œzmGˆ]uB`æ‘L£RÊo{–¨a­)r|läçfC®œ%Fî³WéË:Mä6ôÚË“^êÃB¾[o†’2#ΫE#’Q’Ì2Ï[Ów,ÉÔkkºyƒSņÙH‰³-2¿¥ö’r—$²èkYk+߆QYÍz\[Ed™×s=+„}ø­<Èu oH‰Ý¿µûú[s½w¨ àP“’0«ºo¤Ê©ù|Ø{PʼiÇ\PæÍvmÅÌ›¡ *kC«8Zlì¢2B6[ŒÌR唦¹¼¯"%™vmŤMû\NI›ãÚÊ)׎JPRn½¶"&Y;Ï;³9˜ÜÇæbˆR)JRµ¿Å÷oo]±RÊl[àR.¬Èô½•ù—€p©sÊèºÌFd ÞNOk+ÛžH‹œj%͉“¿±ÏÅd†õä×¥æƒ%©%j tz™ÞÁ®:l §™Ö¨»iÝë°½ÓauLÅ´òÞýV¡Zù¦õÀ™ï{Þ$ ùjÎ/5öõ+ 5fWYü-ö+D&÷àÖlˇ-îæZÙ.açüWÚÛÙlïûÛ®©.å¯][$îÞ78áAiÉ$n­uD²ÒPò¤=Û·ÖZ'ɬÚĦdðF›×VLß·o„ÞƒK–»ÐëÈíeŸKìîÒž [Kolý°­~Âþk ®ÿZú‰SÇ8w›,ÀØÊ‚QîÔemàa½þœ,( Êîß‚SÒu½¶Š@´`I¥ª…éniÝÙ'/¬7œ— 2¹¾µ$ §¥<÷imõ_ÿj)\*ûW®­ËsÿùïÿNöfÿüf¹ fC¹›="H¼Ÿßóãµ¶*ßjí±ãù;œ¿ÏµUïž;U]U-­rG³ÌÕØ~ê¥f¼,vN|{ÿ¾û/HnÅFž ÒHßW w¸­e¡ éÚjå[Ú™ØÛb¿Fõôá²Ø9j½cËxÈ"NÿœS6ÀCBõ]t = DÿßHmIÑýéí$U•åž—UFé¿“ý-'l}m¿¶2DÇi–VAèÝíYRòs»´*J2·=“Îtû[Ü> ¶/•˜4€l¦òŒpãÚQå9¥Å„V¶KZwVD…†×ž]¸‹Ê‰yvÏøª{Öö·;?ÎJ…²H*—èª{ÙUçZ«ntC«8JõmU”Tß®­˜–jGEÙ'[ûF†²çØß”=gy.Ë(©`ù [JŠu/ÔV¢P,ÇWŽõ)Æq=t‚ž¥§ØßJÊÓº¼/Cµ˜¹u±›)¦ ¤gF݃ö±‚7ìä¶=e™gžže;Oû³âœ²NÛç bžGÛ*)Ýy™gŽÊ“NÚTœÒìYÇ üó¹Î­Á&³k]¨€iϱ_0²Øl´‰Öî}Ò&c¿ÑÖ&[]êµõ`SReµ (õ)ÃËžÀB`¡A¯[¹)aö·• *ËG»¶®IUö·¯Û¯)G‰MÙÚÞ¯[h?ìë:µåÔ¬­»R³£ Q¢ÀFuð%:î%üãÑ„V¾ ðøú%нѳÙs#ÐǾ㠂0Ô†¾Ø¢¿ö7¯ûÖ5¹ Fµt¾Jì¨éa]õÓãeŸ«ÚÄçý+Ÿ¿µ•EvàYí>uwæêZù6då~¯ªÓ}mâ¾Ïûó)ïµuë…¯>åóùø­­j SÁ ,¶;Ê7¿êzmÖVv$Xä+…Ð>=­„Šh72’%ŽP2Ãn«d$%3Ük©?”Ì©;tù ’Qwh½¶bwhhÅîÐÐ*ߢ}#NH#“ŸãüJâú¾“s¤:j¸×öòz|lÏš7ìÙÍþïßóÙ»º*˜‚¸Cí«rTK‚Âl_·ö(µ·«8™ßV…SŠ2Ze{&"¬«eŸCë1.¨Z4>¥fëÁÿëZÙ–<óíÈ3•Òµfÿú•qmejÍr¡Öt­ü`eêû\ƒÛ‚@žT¥;/ï«3|ÕY™Ò9q³[‰ Ý\$d;“+°t,D£Jc2ð¹v2¡Þ„|+q =«cBGW/U=—™ÔšUì\il®V-F¨õÃIA۳ɱ=Xº=¸±müËûîÒá#¿äòFF¶>«—E¶ mÓö,‰¨0{n“Ç£¸/•BNÂÖŸ„!y|w6¡U ±¶UcÖZ/cֈͳ¿-ˆ=xï×Vv°å¾¬|Uìtg{;÷5D¤¨mlÞ*3¸{°ØÚúì=ø[ïÁ"Ç<éÎC¤ F¬+håx+œí‘õc+mvvT’Òpm+f‘;÷n—mm#Q*½»IëÇZ±»»_[±»;üVlvÊ,õ]?E’ÙÄÈE­ßϸ¶²,Ú\¿ö¬+O= uFúa‡¥•ôökëÖ×zOœ>DßÝ`®¬'Ng óÄ=À§£è»­¯­ ­Û¤ªkÛ¾Êeïë ¿%ádЙ8Jnó!ú|½êµ•E2áíú¬ºy}ýÖV¾µ×ÝêËíZw%Zƾû,¡æ:Cvž>Ô\gr·l¨ùô+«~m分k[ ï«‘H˜%ød¿ ¡NB;uŽk+v6k+v†Vq”‚–G£6¨ÁY™ô6Î-¶BØß’Ö<û[NXòí\åh4‹+I£qúÙÅ’`[%eë³ÏU”îlǬ _ÛÛöl°‡ÔÖù>ØžÏ×»’ÒyAØíÊaák[Î:½‹F‹VŽý-£VÝò¾,§¬Ä¶•SVâzmŬġ³7k«@¬ˆvÌ;E_ågñyi¦¶çœ¢÷òuû[[÷z÷©zØýË$ámiì˜5¥§ØVƒží?{òëmÜ—÷÷p¶kV`§èç÷},oĉ³ÝÆiNíö|æùñëOçªéþl+Ãóº¿vm=ûtgû\~\9 !×këö·O_šMs¼ð"D)k.)ë¥mU„d÷×”Ô®­GÝ Î+nŽÒHí=éšãÕÉÁã©&}{¾´@äçK_VE¢Ð;BNë{êúçošNk+rïÛST0Bæ·k’Z4>û\Ai|õÚÊ| û\¬ôÞ{lú¿êHÝ5ÃÕÒ¥k¡P=<žZhJb´£2”^f{F#%œ^¦eFÏKÏ’´ÛÖX£÷v³ú÷ªìi¬™°l‹–¸FïN³m‘¬ØV°ìý­m$öŽk+Cî_;*,;É{j´$n«—Ý¡Ò{Ê‚²º,o¤2"Óg‘µÊñ]f-ÌZ1ÂbcåÉ­}˜žõëRŸB¿B9…fm<ÚËÚx<Ÿg{ÿ*Â[˜J-îÎ ,òÇ®XhÕTœŒ}®¡âdÚµ•!ÞÛZPVµe̤õÃ~AÜìö^°;ËM³»l±2é ¥Æþ…®³–|½Ñ—Žç‰~<š²±£2lK…±HæÓòWNk+Û´.Ž‹¹ó¥5'ž»Ñ» +ÕþÊoWÙ7ÚHŒÎJüû<Ëç´¶²Fðnç1?˵•ïìÞ-ؽõÖ 16¯Çù^¾ïkëîffྲྀòÍ|ný„V±mý[ZOk«D,êÃÚª6­­··»V½±×uïy«tá¹fÓú[Z¡µ8Ìäóù ³‘m·hûê`‹³Úv‹ÖuhÝnÑ%0¶¨&̦p@ë¸åÄÞ—M¸5E9±°U bÜ´æËå¯F·È|9Úß–këV \Žï’tq|®3¼ÑV샚¬çSY.Acz[3Ì Ë⸼×Öís_·¯[vêP)ËûimÝ:TË~„ž·•Ç£¼ºœÅ{Þ.Uù›…ÕåÄn›-­Ï߯ŒZÙ¦µZ~[>×V¾i]œ<ó¿µuó¿ÿ]¹0n·²ü»¯­Òµº«î´ÌdhU«º]¾¿Ÿý¾ë=Û4?X»°0;Ïòõ*KëNйØ-z:þÞkëZ)6ÿåZZÞ½ „ÖÏ®Uì³y6NkëñÁq¦·ÁL¶õ¶ÌÕ­\[õ¶çÛÒó²b8”³Îv-«ime»ž›ù§¡3Q-×F‘a#.yX9ež¶­„CÅV\ÖéP©×V†¸–¯_ÊŒ¸ÌFd‚Ü…ÂØVE9Ëm«FDÆö×ÈL[¸B+C‚lkA(¢Ëûš,Ã8eæå±¼¯É0Ud¼‚šj2†)ÏÍïÕ¿×VDp_ŒA&㔹§_Z—‰5¬,¢¹Ùr#:õipÆk“á\êbe"ÓØÎˆlgÃΘ޶”ƒp^W&'‚/­lòœRío%ª.cÞ°ÖV¸%M0`íoÉfmåˆÊg[a,°ß(—”©¨^[¢–Û7R8»‡5`ܼõ®,÷‡É ÞËzl¶‰šQµõÅe¶P±êµŒ*˜¨vªWZ‘P6»6u}¼Ñín[9¦>9rƒ&Lz×£aÝû .¦(u1´† mà ì+ë´6LêSgß×PªˆýmAœuv/ìÌL¾ãÃv Ïa»O¶kxކíÖ6l×µr$07üVl3/õ™mx–“ ÛV†È„ãÚŠ™N–o°vª¦}_®:8½M0QíNï1´"¦hU”reŸ«)ÅÌŽ»5ºríîÞð Fc¶Á=&˜¨öÁ=ãÚʎΘ?ÛšSŽgÛóöÙ¯ßÎÇ|ýȵ®¶éƸu4k^wËÚf6©z—§• v™m•ÔÉP¯­ ™IÛªŽ²wu›‚ïyiEºæú¨º¿µ5°´_¿üU¿…·Ë:SÁÑn„¡Œ2¶uë>ôçäÃR]™Q&›e6$ñ­ÙÔHFÝ’¶gŽíu9-†3³«ò¥Û-;TJÊ ±¼Q%¥tcÖÄj‡Q™ãyeÓ :ÛZWÝ,o@"Á’âÀõ¸ŒJeÛßZáüÛÖž9Ö¶ÕU³ŒY1Jê³­œ’úšµ•möQ½î#%7Z÷ÑÆDµÙGÍÚÊwò•3O%)“œý-åh·_A‘÷Ѳ6â™ÚòqyÙßXPÂùóiCëÖ™úmº©ü k+GîîåôÞ%v9çf¿ Îq}ÁÎLàƒÛ¯ºå4#d»5âSÔþVb'áÔÃÔ ¡1ê‘Ù1¾y¢¢%*2A³Žƒ>?@d´ØŸ97؃Vö¦8Ý:˜ C´Þí˜ ÂØ·h|ÆÅ2û:N¢èA¢0ü(Q´«DLr;‰¢¿ˆt½¬ “6(ûœnહ~í±ØVàO§®û;¯­˜äfG…¹-ûëÏ:ŒA’ˆN÷úyî~kë.Dc]ÏFë¹×Vvü öœ4='ÝšÜ×q‡¯àOQ£7‰Öþ*÷F†’Fìs B±§¨)P¹RõÌÖ’fâ¯ï0Âlk&î.Ï¥•áFäî·ÜÎENI}˨ êô^œÖ¦àø¹1X‰bCaí[o×rç0ƒóù7l¡P–ØÏcá5Ûê°6º~>í–`ˆ"Ë0þü|-AêŦ~Cd€þ-h³¡ó&æÆ‘M± ¬‡³ýú(«å¼ÚZ?ltÇí× ¯ÇRÊ©tb%™z¶C»f²È¨Þ—ã2ÃÐÛߊãÍÞ6îf/v.|Ù6ä·ÈúsZZ5Òóií•Û§ÒV6-²•»ËŠMÍúœ„\„š×Qϳ8ÙÛ÷Í7ëªY̘îy¹/­ˆµÇZ‰Ïk+vn,cÎ1©ÞŸÅ&'^í£ý-v—×ˬ-­hÇy²áÑÅšŽ“ãùþj¾ÝÒ*©ÛÙΆ¦ÜÒö¹‘úÖµ‘cò¤¿» –¡7{·²íî¾õ_k)P †]±ËÝ%z…1/!ãXpžsÃÁF±ßGËL2I<·±ÏÅï”ʦE ÙÝ aÁãbŸ‹®ö…ýÌ>I¿Ú9¹Ú›µõx/Øzωç.EÁq+q×µ¶g†îÐù+Øž©™ìmÏØLNeרuò/kRäǽðjË×åiŸ«­KòÃõk[ þÛ×â×(æ?jª©´ßH 'ÿ’üÿ±¿åµêì˜9–ðÜCÂs!ºSÜ^]9%¬!¨sÒ¾‘¿/¬gA8žëÑþÖ`ýç÷øÚ7*¨ï»´ÊŒØ öÆ‘9µSl+#Ælפ¤Öäbé-¤ Zí¨¨Ù€ÖxM:+Äõòx=>ߥÕýt³89ßûåÒŠ9ø§ÅÁ¿´ªœh–Xe¨Ç¬¦…×è«ù·ÿ4öÇ÷%Ïkù»½ÿß_–yyCÌ],ˆÜ#þóÏgļð-¢žÿ7ôÁâ SºÏ'HÛÍ´Á°>Îî)|íã¿ÿ.ˆëý¶ Æ¡¼Ôw‹+büíãˆêÝ”}@,Oùïf„½ŽfĹþÎ]Ü"–·×ì<Ž¥^Õ•U@ 1Í"ëŠGÄÐM¿K@(¸^ÝH/Mùn¢‘ê=¢ûÌo#Ì‚ø'z›J7µQ`3ö¬O!âïrrßåu­/³ü]Ä:cg÷”ûBÑâž"ÂŒļQ¿ß!F 3ÖÍKtEHtNŸ—€Pèœ>_q˜±êÕ”77cb±Íœ~›ù"Œ…[Aç“_AÍ2­€PØŒ]ä3¦Éݰ,„!vC¹ø@‚!OY6݂ȳ°ÖÿY×ú<„©gåv飠Çq¶OÉs²Ö=…ëãéß6Gwå4o|¿+s|W.Oy—m@໲ŠÝ/³°°"º_b„D÷‹{ÛuWÞÅí—<±_ª& ðýâž’Ø/1B +¹ž"Ñ•#Ôaï×ÃeÉ@Y?-ëjý.z]…»>ž gç‚PÔ|øsÝkû9mܚĜöAÌéÄœFbNë€ æ4B(ì]üZ/ðµ>†µ^$ÖzÄZ¯‚Xë‚Xëc@Äﲜ§ó¦nKY‚Á2b}t÷¶¬}—fŠÇص!q\—¬£‘“ëÃAÞ§Œ¬»{JN®wŒ‡Ór\e–’a"Ãúp2 ãÔyjÉ bsZnn vû×ÊcñŒizÆà„ašž1÷MÏXŒÈ8Ö¤ˆ“¿Ïn)zU_Apâ2…¹Ú–Y·ê¾…÷õ %}.¥5-¢Àf}Y§ÓõnŸÂÉuZ¹[çû³píãq‚>È=WßËŽ´iíH9µNË%©5 Ð>îp{pžrìŒqbö«¤ÄÙ‡›u®1ùþíÐÁ»(BBéÖ§ê)•[\šå¿>DFïl©ÀgÝöëCP:Ð< ú}~¸õ!¨ï2÷›àø|´«Ô'ÈY·N!ñ•Ü®ûV(BZO~‘Ø·°>DbßvQ‡?ÇDâsOIœcî)‰s,F '¿ÿr)y½ ôä÷_ŽX…㺠ejÖÁÐ] çºdè®ìÚuWÊœ¬dÉñûe\ׇ„”³žëR$Îõ¨â\ïB ãðëCÊÄ=7qÏE}÷\„@î—nÞtvJEÞ/NB‘ ûrN‚> ¹³.&)½rÇÞ¶@ÏÓH'T}:ÀHUNYY¼Þ 8eeñ2®š8öáõÅzCȉÛuîžS‚>OáäW×=‚þ¢$=8ù•¤úX烒r&ouRŠ|wß*MêÙî®TyÖ )ƒïýzÝû:£ouXš¾Åœ¬Iéb^BM@ ·˜“‚5~‹E÷¾NÈî)’’‚½,¥5%}ž‡r †É ¬ mȧ8©OÓ°[…šÜû^BÑ-Àd`rbg¯rÉH)ÇíC97RÃH)Ç­SÃç‡]§Fâ#×3Èò[B„„"%X§%E­±yÓÁ84%åøõa %åxYÛ\^oׯoŠ„Ì!v&»s½Èh›C䤬ít‚%ôJ;§ÇeíqÝsEJ^·³^HüË«¦U¨„¦UCûù£Ð¸E±]OÜ‚´²ø·((«“?ù “8ùë€`¸f±ô‘g„ý´õ»2Ï2bƼVg)­  †öq†§pR¦ƒ½Ÿg"±÷#Ãú€½Ÿgô×÷OQ Í3B`'Œ³²ä™¦WPÕº‚üH u:;Lžä)»2ÏS»r´ˆœ”µaWæybWZi+ω/gï[û.9ýå@BÉsAJ°£ò\R½;Çòà<Í {ò¬¸û6Ï5±Æ¼L—ç&!ÓE´÷õó"!;Ø5Æð}[µþ,ÌYFÞ· måŒöŒ¸uÊ8±ÆÖӉĽ}Hj}TpWæ,¡{ÀJf¤ôYÁ]™3MîwJ‘´ygO}@ ;ÛR¬ wƒëƒç¤\òXÎÉóÔéb9iýêœÍ çäyêô¨œ'¬´®IÊÚnïsAÉþ¤ã‰»²ŠØ™ìÏ1žÒQw”[ÉÜw”)i[dþÞQn¤„}lY…îË ÚnéNKAê„•ûr‚þrî’”ƒÜô—s»A$î9Ø·‚þrn7bÏëÉŸ°:„’ ú,t'¿(È3È}}™%Î1;RÂb´ìwÉÄ—«"6RŽIž8Ç"ºoÝ9&©/·žtR’'¿ûúR%N)˜1òËù•,Mb%Gt>ÜJ¶œ8êæ2uK’íâ7ÍUFú÷ϰNUŽ£qFÝÔ°N#úð‘;yd©Y%ƒÛrÂÜ—Øq‹HDî4÷€À,Få·úàqsˆoy½¶!»T ZCH<>(êCí¬ß¡¿^ßS„Ð{Ëæ»yVAäf‡˜ú~zÞã> ,ÚåõüE3–a¯ CòCš"C!Ó+‚ ñN‹Uò$|gÖ ª.‚ì}ç×îÒ”uÍ}ކ<È1‚ç꣢<äÂóýù )v–å©î»îÏ?³³ûo€\Æ¿ëõׄƒä;ȵiʲ­¢Ébq†^¾ðëá ªl¾5Q΂ȸ-îÞђǯsñyUÓ9 ÈÑ„Äc=Eá¡@ðº2p4Äþ Xôúõ Pt°;en]…S}}Nå8êBb?Š>ªè)øAPE}àAUDnPfÜŒeè¶Ù@rtÛl Ý6G·MüÆp¶ÍM,‡m3Eïœc‘'—Ò}bMùÚe{ ˆí2Y6E}žÒ6 âeâúø|¿nhbÛ,^Î& m3««eè2ºhè2i¦¨t™œâ>Ðí#rôDëÝ×Óa™ì?“}„ááð “Oéâx Œá((ßz æ»õ(ðS` §@Ÿc8 üÃ)P$NhÄ)=…8¢>ˆS ŽfŒ8bq Äâˆ!Ä)=âh"q D3‹žÓãd?`ä­Ú#^uÈåÙøËSg‰Ë3êCà7u@`§À|)5¡/‘?ÑtNù‘ü‰¦sìD›¢MçØ‰VE'šÎ‰‹oñËGã¢wo›Ó'Z?Ѫ¨üD‹ûÀO4ÐKÝŒá'Ú=†8ѦhFr<Ô ÔlÍ)LJåšÓ!W fkJIò!W¹¦C¢¥eBÑŠxx!(|Z$¾& 0—ÖºTU"<èÇËw KUá—o–ª"”µõòÕŠPÖÖËW«Äå!ˆË7)qùF}—o„ .ßxR‰Ëwˆ ¼uBkJöê„Öø‰Ø¯ê„Öø‰Ø¯ê„Ö”í/N­)=Ú_œZã'â–™IDÝâx"¶a™üDÃ23„NDCáD4‰1z q"FO!NĨâDŒÔ‰Mu"6hqˬ ´´u™è2ëÚ°Ì t™umXf¥¥ys.(-Í›ktk­íªµš,09Ãkì8LžBmy“ÙÐf4gŠ3tØŒ»! 'O÷ʃãNº T2xÜ UFßvªŒH|Û¨‡ÞÔ "µsÔ"á‚sà]d"|x < n<Ô¤¡¿¹!]Öþö7š¾uÝ84Hâ¿‹!ÃUüw1ÄѾ‹IíQy©»u½°kBÌ1ðÆQ$ÂUú€ÀÃwÀ„^d¤T!•y‘‘}´`B/Hó· #Ê‹<œ}°DHå Wó´à”¾ëÏÓ‚ã{®^ÏÓ‚ã{®^ÏÓ‚Sú®?O Né»þ<-Vó÷1Öz!k=Bà$°ç ‘Øsu@0<ŒFªÁ}@ 0RM†E¸=Wh⻬{®Ð‰ïõ!ð°ˆ: 0ÄŸ……Æ¿Ë@êæ´ ï8ÇŠ‚¨ußÖÐwœcQHÔ1lfA°,K„ÿ ÁðЊÞ"RÁŽM@ !@ð.,ã ,BàaD<…%4Ã: °O‰P×1 ¶ÛZD*Ø 4øä–)z>¦> ðЬ3 4=î»h\–j÷5‰¹& ðPx—žÏB¬p“ب‰û#êCz„%b[¾K½–Ï& 6t%¾þ!¬Ñè¿ÿ·ŒÃöÑN—ñ=ÖÂÄ}™Ñ´c4Ro4Ñù]fi¾q{ß͘5ýóO€œ¦ñ~_ŒFÿü»éå4þúÂEÔû‰'ÃZÈû`\âqBËéA)щ„úͦü¦âšZî½ÛþÜPËÝ­Ä$4½[÷”ÈDöÏæ ²õ{g„@½WÖVëŽ2ª§m{Z7• 6U»T°Žoˆz<—0c‚“âÙEtCÔUôm;7§BP*¿?R… ü[ëæŽ"3ã§Lu}/»onø.BÒ›;xbÛnˆú莉ûPÎÊj)ñ®Ë8¦áÖ>ꀰ›ûߥëÚÇé÷a Ä1ü0¡ðTß_{¶.Cw ]í1ôyýÜŒ™øº,]èÖ eȯÝ)ÅåîÏ ¿N ÊðäO:Y ÆÞHˆUjœGúúÖ7‹Èñ[l\çC1ü×ùÀãr«èöPœ8qï­›1•¸=àtP‰ÛcŠž"Bl» ±q˜ä?§ÄŠ[±Èçãòõ³Z w_NiêŽò¢²Âð‹¡Ö9ôÞŸ¢{?ŠZÙŸn:§Ì9~éœÊK¾C¤ÓŒZA—Ïúà´‚»’ ¨}t8‹s¬ã=®;[;{\wv,°_cî\ך2‘ùÛ#öjÿ³‘¥ÖY'X`†ÕT§Éüù3dB0“Q{Î˸”#°]eÜȸ9ÇÚußFÝ@~ßòsùâÌpêLö;ÛPŠÒ*‘ £>¹p ͘©¤N)/k”_¡ŠÎÂà¢[öþ<Ðóòõ»sÕ.…H-BãçǸž±{m{¿¬#-¨ûeiAÝQ~}TÖàº> ÂÙÜ®šE‘'ö-ôÁȵîvTÁ©;ÊŸt… ö­_A!ëÝPÈÄÝ!ˆ»¡ q4 ¬gPäèÙš@îþÛFnœýZwòia(C­?a"ÇÆN†ñÒgQ2Œ“>cËN’†wá‘sds{´þãýõÁÄÎ#§Ä~¤¥{ §Ü'NÊá±ëcZº§àwƒ-Qbçƒg›'.T¥{R›w2?\»ýâvÏ#Zë¿ Ï )ŸÂwá—êà±x†¼Ì}¸3ˆçug»ÅóœÒ÷¶ÆsFÝsîVç9'÷œ{Û\P¦\·’yd¦ßÝ@î”â9ÉÐáN)žK\’n×5–+Êã×X®Èqtîm5uº—G&ö­æY¾~{±_nž·K;¡ßÂH ³®u†G"Mœ3rߺLÎP‰m9qýcœ–a`¤LP;ÛÉ0œÉ„ ãPôí{Žij}ø]É þ.«ôÉ·l‰»ÓÁŽƒg”9ØŸÓáNúô{Ÿç¤ôéö>Ï)'žßsœ¼M]ç¤$íòÖyd–ÞÔíNí¹u¿DÖÑãÉê<õAÆçS\v¥_ÜP'ÿr¼ ßN‘%Öº1‘Sz”ß/‚Qç˜ÿ.‚Ü .SL‡ƒw¯q!ßÖ® AºýŒ Mí[?cÂÐ# Ê‚¶T¶`AÛŸcóž‚áûÖ·ÌëÔŽC22oøÖ>¶MGlÛ€`ÇŒŠß«ºŽÁ‘dÃ7D;&õù•,®ï÷sÀq)ëf ß/môBr\\…î»h*=³‚8fŽçzÏOYÏ1ibg⪿ «þƒMiëÔ¼{§&W!åx÷Çs½{­Â1jwƒb ÇhGÇèà£\qz¤ *‘ðòôÁψóqÊ4x{ÇRM]†`+YirN^Od‚®Î•!gÝ÷aˆw™ã3W!k¯o«3Êò½T𱈜²ÑÏR_{m­nÊGï$oµ5§ÏýÊÏ­Ž±côꜚÏwŒX£—«cÓüN¥»MwùEËC®Kûë7]`WÆùEñYX–~­ÇùEÿ4¶0㌸üMcYµÑ8 g_Ÿ×ñ}qž^Æ®ºŒ}4$š~> ûøeŽÑôí»¼B~ßäœxÐKʉÓÏ-Ê ;µß.BTí×êÄsLë|Ž!‘i¦¨…%ÜM°©H£¢7Np-Wк!4i4*K7E¨üµ‹àZ‘3ö™":cï.z ð÷ˆú@â^.€Ç9J›Y‡î+Bc‘¨ãr/Ç Èìx”£ôŸíBµk¬ï§e-F3–¾a>"ëôö)w¯•ê8;û»ÈˆØoÝEKN„`ÈMS¾c„ß¾gwÓTÃïú›`NÀ¼6ºGŒÀ¼ëðK'#„$w,1m·êÜý~ã!ôñùùkĈØÓ¿ó³Øg$é‰<7”Ÿe]§F'ÖièU応!5Lw4B¯ïW«•¸Q¯+¹È(‚¿_¨Äð.E޾K4§ág ²[A¤9 ³àäŒ9;i!è§À ¢&¢§àþsëWpO!5g%ç…"çí m²ÃîËÁœš„E&B §”[A±•|lhßVd}eï!‘eTœ˜-³· rJ½=„ÈöÙôŽ-ªþ^€-Ê!0-µ…,W‡¸ ú xÏÖý"2Ny•œ(#2AE= ¥›1A‹2Ö'2A‹2SC¦x2¦1êC!BÆé>¶¡QcˆFjÂÁ[%²(¤1 Ú¦ûk îÅÏX†ŠM É÷‘/Íå! 7§Á`% ç”;‘)tSu­?E¦éã°j‚áæg˜VC)ˆkíʇE”g‰‘Úçôö‡§äyâ8´ó‘'¢€ÝS8e.qÊ®È9u”ùï’ Ravß%—˜Ë¸ &‘+Òôã¶nN]¨aN‰@ÒÑ_1‚p-€y  ”K.Á²„™¢ 4cwr}ä´VGËÉUf,;0¬©ôæó-{pÄ "¾?îCÐ&lørŒÜsëH©=çÅ~Áb¿ëCÓâ6¬d‚ðvÑRÝEÆ ZÌ…•Ì3LÌm›‹×ÚÏbsZ,¢:Ü!8"¢Îº_Ô‡À÷¾}[žÓ⥣¾œ[ކ»z=é¸Hœt}@ ‚Žûú\Ò™°’·n’í¥ ß6r“CÄa¤”SÙ‘;škív7 ;G„ÀÏ1÷¶ Ç#ŒCd„‹t=aDžb‡€@i4Üœ –Q‡€À?7RNg»XÑPA‡ïZæF!¨õqv.c!èLÇB¨Ä:…qèÄ=×þõݬ›„a!Bà Š›Ó‚V¶`ƨ‚PaßÊœ¸M½ëZD.Ÿ£ œv¡Ã¹.9õõý¬ËÔ¹nï(™ia8©rp¤©¦t»>¤¦×‡ëÃÐ÷ |9Y$”qû¶*£ƒc`¤3fý¶Š>qÝ»(ž8!ˆµ¾žRJ&îý1 ð ørJÑ®IË^ ”JœtЇN`”Í[…EÊMßVÓßÅI°:'çÔ#=§°÷5OHc@`×Î]#4¥ô5-˜È„´»N\-hwMõ»kbî®F Ú]·˜¤»ÆëZîš©Æqt×T‹»&ž1Ü]Oá®ûC Â]³ú„…– Ÿp„&MÑ7!š>¨œr¡iÔ!ºHˆÊ¶“‘Žˆ7&§*a˜·>\Κëû…X~Ÿþ#ð„ÊOxBå+žP÷¡}¢t}´Ó§ºŸ> ̺Ìî7çü\þšh¤~!ž/—X•ÿÊq¸E}8ëÃ>粌:q •;H»0\&Hↀ`xÂüŸ7¡)Ã23DˆÿšP)LBžvãP¤»Þi¨&u/C´Ã/攼d—H‘áA­EžÈɶO)X"'»ÜÔ ïRpZw„3“ ¿^}‚ ¿^nׇ¤}ÂUÔî†/¯>agô+$év†ÃbM†XúY–°5‘'råÁ¹ò}@0\ök-‚'Žv@ˆÄÞ„LØ'‹P‰+šXëÃT6ð¶f“`z9»K·Ÿ. cÈÌ`Œù¨›•©1êƒow/´±¯/pi˾ê^—€«ú˜ú¾*»Ï5 Ô~ŽÝð;‰Cè â ˆP[ xó盬ˆ SóÝq,÷ñŒe±(c¹ +›Aò´3¯¡þQ}nñsÀÏnï¡+ø/†®œ†ó-‚ðrƒ@¼á[~‡!†ˆrCù¹»~Ç>~Ùqñ³_¬Ïq T÷SA”sұ\Ên£E…,Ľôp¹~Û÷;‚<óz)¨Ì9ç ‘’ñ„DÂÒá i‚ð„D}àž:êƒð„D#=zBV?‡C¸¯$BPžxR OH4ÖœáÖ?{Rä)ÍÊ.¤<¥Y‚%dx Op™@‚„³®A™KšÁj‰2—¤@ ÷•C m#~ÃÛO“«Ä}š¨k™›¥Æx@œÏyAttu•Ê|³©v$¶–mo¯zµÕwtˆ¯ÑxBDãE¯CEãÅC4^»FãyE¡a®-¼‘J„¹ö.¿ä¹Lœ@Êæê>±¢Ã\ë¨uÌôõ±v’$÷š2FàdVn&AfU2žÌÊ!óñˆ¶IYõAYE}dVQú°žW2+‡0‡å¼’Y9AfÏX†V6‚Ì*š3œÌÊÉ;¬HPDÕÒiMòŒ¦3‚%{÷¦5«ÁËØû»7­Yóœ ÞߣÑë!ddÒZî÷ŤU×·h@$óﺻÛf>išx¤z·ÿçÖv‹0(}È*x²XVÜŒå8̓-FIDoàŸ•Á^rMÍ©ógHnè9u3fé'm@é'‚H?‰DúI4"ý$Bé'‚H?‚H?‰ú ÒO¢—¡ÒOâyGrd½ùVò"a¾m‚ƒ¥z/ŠŒÌ¤sj†Èiް)B0¬¦mKÁñB¶!VÍé;EŽÕtúz‡qÍÇSM ʈàíë}\ûñy½Wb^µå¬©‚œ"¶‚·3zͯ2y pêýý;Ëç+¼K{­^£¥Ku‰ç/Úo+h:L'§Ä!› -[úÑ"$©ÜõîË)R¹s2W¨v|PˆF8R…ÚѤljC0RMæQNndm—‹)E*³œ# ",£]#©«Óã²h¥Ì¨Xk—E+e†¯äÞgÑ:ÇjÕB­C4¶3™'b‹#®˜Áù!sZ1ƒ5&sÚ¢·¨ÕQDlq„ШÆ4D#5xäpÔÇ1¶x>ö3–¡ÊØÄeŽZÔÚ[ì!ØawÚR22=µ‚ÃNîéÛ¢–Ïv Tóp„ iUd$O$ ÁP¶ÿ6Y;–1¼I "åc•Ê$E7äý]R¦ü]‚ðwµAø»¢qþ®¨…ÚËÜHÉØb/ëHM§YÁ±,5µ·êÒÐD•n&¡_DB¿ˆ„~Qª_´·¨½~QGú…4˜~QGú…4A¿8˜`E‚ ·T*\‡@ÕiwÕÉbèú•ìea•Ñ+]•%b{Æ€ b{"Û!ˆØž> ˆØžè]ˆØžAÄö´AÄöDã b{¢—¡b{†‚©õµS§Užà€¡02=R $ͪé])VM1(VÍ‹î’{VÍØQEO¨Qd.%h£¼{— è êp§†âãGcøo û!ìž«‚©$%¶2¥ÜÐu@à¶27§Š¶•¹ùP+o¸¡e(¾‘ 7´Œ ‡¹¡›€Ø³ò¶ZªM·gm®k³T:A·óa¨pZ—h#Îyg9fÝ—+höF¸¶UAóöB:£y¡a߽߷:§™\`Æ4#×Go«ÍR ú…æ4Ã_ÓÃyСz·šÏŸ–t¢¿´¢zu„`x¦]AZ'ò0ë€`hʈu:¡o¹/Gñ*†·ÅíU»Š¨x滳µ7ÁPæV‡É´‚¡LØ0RÃh¦AX†(·ò+Ié4<¯œ_©kWÍÐàüJ‹[2WB 7!:F$ØÖ!lëÙû>]C•`Ž„N0ÇGÜ=í¾œ!øaW¦)hW;ˆBxÖz2¬eAd%·>µQy"µ±ÌúàdÁHb· Nó~à *81ÒUB)ìÀ°> ‘’ˆDD„ $x™Pš€ $”1  eBB‰O^‚wQ‰ä¥q°¢–bYÕž?8a C%ëœý×§Â9 Ðàp(f¨ôάöh(A!V‚<ÁÁ±óçr ×>²ž%jÕAPØKW„“Žç‰šCð–¨9ÔnËqãHè 0뜲nx–bÅE‚¥x $¿Ò§ñ*ž¨){ŸÓ5e@ÏV\‘Îð|*®¹‚ð|ŽAx>›€ <Ÿm@žÏ¨"— Âó”È%ˆú <ŸÑ8(Ïg<©„ç3zßœaµîÁ¢¶äÛZ÷ ^rƒoîÚ›@Tˆ:Ôºw¢rˆÚ_ì^dçxч@"¦xŠìS}}Nß! 0SŒsÒ;z´» „®q,q¸æ£¬q— óÁ¨£ iÀ#8}ØÁ#8}´ÃÖ¾7÷)!¡DðE—sq}Ûuã(:˜Äå½*¡©ƒjò#¥•q0)Q4–O÷å ’Ærˆ(eçÆQ4–Ó*¿Ci,/>¿Þ!Ö¬‡+8á>]ù´cô.(åt9dþù_Ò´üM½ÝÙ!ì到åÓQäÑ'ÑP²„â8XíÉIí}@ÿ5©]IÔ׆¤v%y"©=BIíÑ8ˆ¤ö¨}R{’Ú‚Hjo‚Hjo¢#’Ú£N¨¤öBÐ&Á`E"Ê« †êŽpPIIÛÑà‘ ¯Î;®Vó¿;†¤!—ª“†dAWrƒ‹,ª¹¿rZ¿¢ë>Lpé†`c°1UNjìnû«œ´µ¸#UQÚÔjTœ¼@ÜE¦D"r®†Hþ.,J‘ž`¥”Ä¢ªå˜äîË: ÄñB°æ*•àÛ»€Ò »@„À-:°Ö•IDVŽADVöÁñª…0Ž"Qµpˆc¸Z»jdšŠh\52ME4®™¦"}l®Cœ úÈñM@0¼Ê'ôÁ(ŸÓBI”扞vN ?/Ôðl‚áÖK@ÐöœõRK²b‡ïc[Ñ'Vµ÷:(­i©ëÃ$êoŽÁðÚ™0§vgÉ)û€ ³¢>ˆð¬1 ˆŠ”öÛšB¼Óð™Èåo‚á¡È ßêÈuz¬³NGN€ÏB “ðYDômŒ+Š_DDí];R™‘N³¯%Y^ ;$«P3QGòŽRÜk×Ïe°1:¸,—sl†=µŸmÛ}ï—> Xp¹ôÖò}k¦Áˆ¾Êè)""®³ÒÖp)ó¤YDˆÝðtþÊO;ÜbÇßÿã3d¾~.Ÿò{ ¾"¬/ñ^eý½À—“„µgô…“´ä·õ³.Õßín R¨G_©R§R¨›ÁŽ$|½ãàÐ’¦­ñO)ô9‚áäí·%‚¤Ç~[ÒƒçÓÁ5Y»»ösª¨ÊKÜî÷ 8™ÜZ‘úÜÝésJßÅés‘ðH(ï"iB:Bàéñ R£ã*R£kz¼ÞgŒnäÂAÈ…u@éñÑ8ˆôøA¤ÇGƒî98a”¦×ºûr&Aã!pDã(pÄJ­Uq´ôÞ¡*«»=ÔÎn¹ÒAÎgábGålë¶V¿W@ÈQóÅ5;Ħ²ëÍJÁKe×> ôžƒù¼ÄôŸÏa æW;Dˆzq‡Ð‹Û,i¿oÑ|@èÅæØ¾zzeÁ‹÷Á—Ñ-;ÂÎÕY¢( ô‘ˆìî"n!픨!òÖu¨!¼?àÌÕŒÌMtˆ&|¼­S†Û€ * G¢Âpô¢Âp„ * G¢Âp„ * G#5x6|™È®‚ȇ>T"¼\Ê…SˆôF/y0‚ÈÓ†·5‰<íg”ƒÄNe¯9çZäMçÖ˜Éè5»aëÑÞ®±*ê_c0“‘kÌݧ&#×XÕF}ט=ë"¾Æâw1¸—Þ%' ‹Á˧ãZ2{/ß0îå«£>ÄF_ˆþyÜ!òø¯ \iÛ$äqØ &Èãp'û˜ëS3Æ}HôƒUhȘ*¿ÖHäœGˆC[ÉÒ}ýHšú×úïï¶þõ;ƒ¬2¹]\÷ÅÇu÷ÍoŽf?ÃIgT‚o¢4»Äí9£©ìçAX”-ŸÌGAZœ„Zd ChF†³9w³ÚÐ Š‘âîo±‚“¹¼û§ Nž…N;-™/îdØB&2Û›€`茹·U Ëvx ZÐÖ©/k>ŸCù|0“rú€@½þ)E"Ã~y“e‰ û> P®ø.&£üo~¿¢vxÈ+4£óøGèƒ'òø#áÓl‚ðiFîJ7RA–ÍUhè¬ãµêüð9´&Ó‰Ú> p»ÓóaÃc@à{¿‚>(;­Ï\6yF˧vï› ˆ|q@$N)7§’d´qk=Wäw»‚É)é³¹û·5ôw©š€@¿ ”Ìrô»@I$‡;é¢mºÛ ôy•Ü›€Ï´No˜–‘÷>h&.ý¶‰E±¬¿å§«¯Ÿ€ˆ‹rØr³|: ãkQŽË‚˜%ر|×mýˆ•£aèeñvÓ½¾7QkQŽó}èí;¼ÓýõŠrÜîÖ†6LÏ®·m‡Ð1«;”™joß:zÊ"Ÿþý3?hî—²»NŸþE@@‘¢ò[=ªû)š±l1þkuq;Ói|=.×6‚yÇv¬,Oä×ÁðÔðuù¶”ÝÅÙ/Þ3ày±FÆ‘øqˆÜwq1dM E5Mð6Ûu8/Tøvó†š/å€`x¶¦–ÊÖŒDª 4)»}yÌ)_5 Úàv ¥ÑÝçËpZ£ƒÌuÃinˆxB—•@ ÏÈ„.û ÏÈ„.°åž¡ ]ÕšÐe8­Ñ? ‰)ûT–0Ž<‘ý!‹Ð„E(Bt%Ã×猎wr}ðD~|DQoxŠHxŠÛ€ ˜ê IH—Þ®`x‹û/`o9Ýty¬÷RŒ»×éüg§Ážâ‚‘&¸†ú! ðŒqX"Kî‚ù J܇Y#ò„¿ž’ˆeƒoq˳ßí|ž(„=Áïï"è¼"ØûT‰û5¯Èà~`—Ê ãP‰TÞ: PÆ<ð¡ÉØqwâ “ð¿6Áðâ²0Ò‚ôX»u* J;õò¸Ì§& pVx á¶óá4߈ÛÙ’òžùÌECyFGÏïe¤Lð{ÇÁ$UB–_§ðå$5Ö “Ì„>Rù‘}@àY2°ÆT–°ŒÁГևʙ‹v>Kø=û€@å w&Ó¾S—ïe”Hä{ÁÐ5'¢Ù»Ü:UŠF¸ù mðƒÓ£U"ÂÎeY©€(蘘:Bà§¼‹ÎHš›uMëÑP¿ÀhÚæ y#FÓ6gÈ=1:Ç™bV[žÑŒŽé‡•¬yB>=¥Üé ™¿âV–‰Ì´: Pi<…F'ôhXÉZ“9RN^×dd…‹W0ºHœ–a²D¶Ž1“’ ê€`¨·¾~Ò[!oA„ ¼c@Þ‚¨‰Gx‚Óõ÷ŒCÐٰ爂ðpÂØ¯o)»Ý@ØñƒçØÄú€DÛñÿÍ)ÿÛ„ÿ-Bþ·> ÿ[„ÿ-êƒð¿EÂÿÔ Qp®y¢Ôk„ÀOØQÿ¬õœBœäkvrPÁéÆõ!(¶Ì²„•\(¬Sõ׿^° ·|«q¹Øªû>‚Ã4}"„ˆ£Dl¬ôÔ”MÓ„Ü!æ•ò/F(ì]ªÚÚ ´ÂÒtë?››I¿ Xê"–Ûû\¿q|—.ŒTâï2-B¡Ñ]p:dÔËq0‘g/帽_Ò÷î$Ç‚Ö ÜýR¤gPAyq¯•µÂYNÛñ'@PQÌ÷õ))^„ îÛÞ")IÃÎ.ï‰}Ûž¢è>&èC'|0“(8\Qp8B‡#„Àt ?Ž­R­R„ h•Ú€ h•Æ€ h•¢>PZ¥zŒÞ… UŠFjÐýk,ÏhŸ·½Š<Ål÷K‘3zÏuc@àñ.°òDAê*Bྑ¡Ü7RG}ŒUÞí†(cp#m­Þ“"—ÂùWú€`;ÿJü+E.Q^•wVäŠÎsßEÓ‘}x~$¬ÓœŽÊ¹È©:aƨót}–ÑÒÌKx,«AxÆš€ žD }0’0ÀÝ e¯u[Ú}«êîî¹!oD÷œ’ ¢: ¢è) ò€}«TÂðÜÃS`A›@ÝJÆßmtâRES×ÚÞ…J´´ãÐY¼!(gÎéÞ‚¡ad`ÒÑ)£à 7µA Tv†´! Ø~¿œÏSw†o»MÖôˆÉ"ª© WPA®—îþ¾„T>ŸAIùŒS>ƒ97JÖ\•Ï7ìÜ6÷ºîAj’5aïÊÑ7õ)‡ ˆ›Cü5uÿQ±»_Úêy?ý½£>̺÷gÕàºÜ@å’-´ˆp~Ì"¬u7cËPKzÀÝ0Šøû?w}ØÕgäšòôúl«BkÒ²è&aY„—)vå> »rÔaWŽúxV±EPñkÙÂäôÖ†mIT‘ QÙ…a‰ü4èƒ'¬ÆM@0tÃÀ–2è–ºF[Ê [ê:Ïz÷[Êlľ͆¹Á†1û-m˜!zŠD7Ìí/ ÔaÃLë†1ë–B6L„0؆`ØuKãrAÅ12‘ÜÃó9a [¬ëCÓþBbŒNdãÁHS& ^áV!Á»W.µÀ³$Ûfå)ŠŒ®í çG‘Ó§ƒC0:/ f¬HYóa¤"‘wÜ‘w<‘wõú¥ b¥(d"{t{÷m MÙ/çmi¿mQ'†âÚ7ϲ”‚Û¡àÖA(¸B`ã°Fƒ‘2ŒA ê€ ŒBàY´0ŽÄ*ì N[‡ô·uï"麻̺Jdã5¡ ¾»eÂSPe¬e FZÐ Ì!p¦jb¯Àt­W`<÷~-k=ÏrÜtò'ÌŒÈIÄß6gtæ|Ûœ'r‹ì»ä‚Žòè`¤2áA‹Xeð̈„Ï ªë|3‚ŽŠj«V´ì`}ä7äŽÎë„!7êƒ0äö!p¯$¼mAÏi!0Ž'PNóŒe¸vtÊ©GFØ> #ì"âɶsZ5Õ¼¥‘'nS@়&¬uƾ-;,y딑# æiFlïJŸµPÄÕ°÷ÙÎlí¼£çòù{vc@ðßòÚ¾_×Î1Âó f|x[™ÈqŠDÞŒC%ÌøM@0¼̘&2e`´še´-£Õ#ìü"jðˆ½tq»ág3µ="Dï­¥Â^ŸþÖ„Ä8J÷¶E¢È,0Z-[ÿV —îekMæY䣷^ëûíbÍ´U9¶c„`x¥(ûåȬA'åÌFg—ÀZçœ<“Ýnà ©Þ–‹„ÿ´ Âõ!ð|>˜mgR|¶Ó|ÍUEÈD. ô‘ÈÖsïb™Cöë'³õÆ€ r¾,Bd‰,(;c"'-Ü@”ƒnt2ÿŒ \ úŒØœVãÔû92‘eç”äB #ÕtÍ38Ç„¡Ÿ«PÐÕbÜ9&3Rêso+© Ágà›ŒÜÙo8“e"? Ö‡ä[ÙÁÅżË÷ó ò‡ÜUIúÚ_ïeÝEˆýÝðõŠn‚“»å|Íóiùª¾Ÿ€+û´s{[f XrÙæ6ö½Ÿk³ð˜z„Ú!º¦ú•C4UÕµn¯±ïú±‰ú0û¨†¦¼ÍûÅj»b¾¶9ÚÓ_„X#ʳ•‚om3ÿ†&‚ä!6âì¿òw_XV‹Bì”Ü^ÕãÞ¼#?°¿.®±!þz1A¬õ)ܾåå>Æ’;¾ÂgóùLF憻okè,v÷.XUÊ»«Ê{÷ 9ûQX]1¿÷ Oرƀ`÷ÓTw%7š*|[Cs\øù ëŠùùЉ¼*©IdMÁŒ ›­}—"£*TÎFYätxh"]}ÙéÅo³Ú) AÛ)\‚´S¸Û÷‚X;…»= AÛ)à„)ÄÞNáó!!DoF(*ûBôf„¤BôVÄ·>E“ŒÇî¤+è] ë#Ï2ZÛµ«0Ïr:Å®Âèšèp®ç{Çæ\o·ÈÂ:Í Éžû6ÏQ™î”QõD½E%ßf³m-*VæÏ Ž>°Ùq0FùYÝ”3N!Ü9–5ãNÖv OÙIô΢R÷UÙ}®Á0™Îu‡à¨ÌëB첪þU}n1ÂÚÆÅÔq¹Ûh%Ñà~êB­½ãW.å·}¿Båõõ„a*¡‹EBâ(¯‡†‘¡µ~70MÉRþt`†D¸† [©} Ï–Pûå8íYr{Žã¶ÁÑ×÷Ü?1D}*nü½\X¬GÔƒ'.*mA•ðe³`ù{”ð]8?è¦Öot¹½ÚK[>RÈEjÎCk˜ß\]_?Çúô±ËºŒ¿ges€ŒÜ#Ô>*¶÷aä¡ñ(aè#šïæCo{so+è·9Y úmoA¼mÔú¶î„ >Á=GŸ?“¥LhM@`u.œµ'—ŠÔ£ü®Ôô®tó¡ñ]9…=·KÛrçis©Ÿ—1 nu‚ïbV'xJK(ã*¡l}8¾þÝ<_Õ8 ڥK…Ûãêo•c©_ßóùÙU×G@c<£¿=T¾­Žy_ô—%E±›ÿo„G¯eéï•ãõ™»yNB£÷K! Ÿi#gÃ¥­z•.'¤‹u)‘Çà»È„<6!EBkBõìÕº¡mÝ=[)ÒºÑc@ ÖjŒž"ð8Q©IÄšÂS¨H°»¿÷“µ Ç€@ü=°€æ¹&¢êÒK¸Õ5Q×Áó•Έ÷ñ•WgŠ9Oÿu6ƒ›õŒœî`ˆ8OÿqOµþ× °Öut«ÿô7¼;8qƒ?êx›ÂÎÖ ç\_¢•aÖ#VÔc D¢9¼­¤k‘?ÏVr’4UÛn±ƒŽg:ý³ñ‰÷ãÙÎGœ?´A õÁöö ©n«ÊF”ä&Jr }Ø”M§½ÆÞ¦ bỈÎ<Ži:Ý‚£’#ìÊ('ë Ó•‚¡2]ÙßiÏq”›ÝÝ1ÏO”›M*mˆªËÊc_1ÎÙdžÛô€ˆ£ÜäÛ…M>¾ÜËæ1„<Ä$Õ>&É!TŒ¸;D¤9„>D-Uåõf£–Â쿵äÅ>&齯$ùÃ"ŽFˆ8ò<ªÈu_¦û»£‘„ˆ£%Îó¾ˆÛ¿ÏëtŠ![Š$…]>]× §"wUV/Ý÷ÕdzEÁX>·ïïÑO¢÷qKã·ä!ÛR¬óXÎÏ׳õÀAŠ¸ÊŒ~×Úý½˰è§Ó)z#–ãÑOÑj²GÇÐ&Þ„»Ð¦ÒÙ Ú²;õ_ hôSm&±è§¾Ž!êýôrÑO¢Q‰ÕA6É[ióUzkYíÁÉ[ËÝó†S·ÖýR¯ zS\ù4ÕﺬB`7péö˜ oàÉÍ™ *ÏÏÇ $E»‹‘dý«Šú@£è\löÒUD«ÚªQ¨¤ØÕ«¤h4å¥+ƒçƒTõH$<ÄÜÛ22ŠbcͰ·Vÿy îdÛøôüéøiª²{×÷€ˆ4M»—\ÒÓÙÅ–‡ 6Þ|fÍ·Öx ˆpd¹cbx^&ç£0ÛjU¶‹åëwU÷‰ÑlWÍãûlú! ô*Á:ýü•_¨CçÆéîz]*G_¿ýðQ|¤«‰õº|çQG3æã#Kxʽ½vÃPƒ¸iBµª]ÞÉj1-2ÊbúsÓˆE{k1½Å4fÑŽ+MÝ]¥©‘S•¦Z[iÊ#Ð]çt‰‚‘ò·ó”Œîý ')Bú.B0œ†Æ!I2?¹!»Ùø…a÷D]×%EκBÑ;×ÍAÿR/nçšÈ¼Å£0d–ï#ꆵ\$ü±Á²,‘µº^&h_,£¿~ížÂèˆÓ¿Á"¶zóÆGåú´ê5CýKC„àˆà4–qZ×ì¡T6c@0œ¨fL'HwÆ€8øRïåiºÛ“í">üŒ=æ m#><›æãvý\«¸ŽY+î Š-}ÔF×´ïåŠuÍ> ®Ó@yB§i‚Ðiú€àˆjöÎT+îBL˹£üHyBÞŠ ÏI„§ÈD\šýú¹H0¤C Ëõ_nñ±YÝøúˆûผ}PÖ›ù«a>ðˆ µ ¶G0„ÍyYTër[Û{YTëòX';êCý~Þ"ÆX–ˆ÷‚ˆ÷i‚ˆ÷iB '®óú2FÜÈ]7ÀÌ#×GÕÃ88¹ÆlÅæA[*Ý Ã$!UÐÇ–ní«°}=ŸÜ·Œ‘6ÄÉ:z6c¯©ž"°»²„Ä49ˆ´`LS~¿ÉϘ¦ü~¯®oB u]Ý 2äZïÚÁö•_Ÿå«k—zÁÑʯï ;„Ü׆ÊsÛ¶ç€PHmØÖÖ†õ½C´kõX0HõØ«­ë^_6Gž Ì~Ÿ×Û)z™<Ç+ÌÆóÎPÈ ÖZM6Uh¯¾ í xÐ ,‚4y–°½·…Jw‚ ò„ 3!ÈDŽ^!0%œÑbl+N Ü 2Ž ÜÕÊ8#-ȸ>•øîž o„·U‰°B@!Åíz¸s“pw4A¸;¢>wÇ Äq‰'\n}¨Š2,µ_áP\ò³.r‚kµw/LädpI â£ÈÉà’&F`Á%×/\!b^`ý˜ Õz[vÏ{—|ëŽBGþþ¢>×Þ| ÑÛŒ*"L0š2ÉÍÇVô‹÷­uèïŸ"¨§Ì;st7”®‰ïÊÞ1ezÄ)süµ.$Ð!8îì‚9U8éÅêìbDˆÓ"¦T|}M‡òž†6 ¸d¶´íí³^Ðüµ×> üµU[N[…qZ:FלIŠð¦[ÎT‹È)E¨vW{°³U/¼ÓE;!õÙŽNŒY”cEyô©™,*eºI}(‹Ê¡©`‚Rr] 7“2AFÒAFRAF=¿oá\—ŠºÅÖ‘jz¤°_öL»ñHaF!‡‘ÂÞ—%ëC ̇I˜ZQåî~Ù†lìRDû€ RD‡€àtM%b uR_ÇŸ7÷³]ØGô”ªé#L±KÐyUÍ_Â`XLñφ íûhOÁé¿0Š6çÁ—‹Q7éÐãÙíœGw †G¦$mxtO‘¤J_:„>šÈg‘|V¶ªÖ}sKçBYÒÔg µ¶ëçyü£>BˆµK˦÷éüþ ˆƒßïý{<îÃ9 äÁÕ6Ÿ•÷x¤1ÏÀÍÊÕ¬¹õÂ=QúËõwý=î·€À˜T«¾Þ¶@¹°_TA3 ÛЦ3‚Ù§ª2%RU£>ˆTÕ: °P:ÂÆß…fÆÝ¦:'È¿Vi\³„4ÞÃSªíY¨yBo—r`%§‚:Z@H:Aøyˆå)ÿü/„Uóß4ýbÝÙG¨ôZ“Ô+•›1C?€«iC?€«Eá{⇱Šú(˜G‘ ã¯Y+ÙtikÒ53‰•l!˜I¬ä*zŠÀ«"Ǥ­z­àDµ€> 8&K999rZïCЏçb§õÎÄñ†(*ì æ {ÖK5;gžˆ ûZĤ­i–¶z7ë!1fo5€°d‡PXàò·Žž¢ÚÚ¬h¹ƒQ˜8“ áTà -bqqàýmZÛÛÔÈDº¼‹"¥ 'EK·6 8v›‚žZ»¹ù å±×õ;໨±wä„`,§‡o>‹<5c1S !_!°Œ<ä+–1c°À²*–±à¢?&¤€Ud ÷ê{Û(]X”ÈKJ *D±8>^…í:§±NÛuN ޏëœwÁëœÖ×9-¬×®s§ËÜgЇL¸Ïš€ ÜgQµZ;FK›Ý•‘«ø˜ŒfO˜-­ð6¥ î—ÈUüï?p-ÒÅb1êl*ÏhBW°ò,'L×ÞÝ̳œvIÚwá;GðÖåTárŠúàxª;ô!Nþ! žâ5ZD*Ø`†Û” I‡ÖC@0´v×}(¢v×åù)û€ÀC|ª6 🪻z¡c—S s<ÜÍK©2kÈ[æ£Zîè£H$MÚ·Ý&öoÓæà»ä$eÇäVa¾M6Љ2{góÈE»#ʬ(“çD ±ÖŸ¸œHýoVk1ߦþ‡T‘n˜ªçÅ"¶÷íñ{Yé`sç'ÊÔ†8¾¥&Þ¥½ÀœšD)ôQP§ƒ³[r–Ñ®sXc,#4oå,§­£ý ukZ­€“ŽÏ³s°q–²ÒÚù û›èm©óÃk|œI:Y  ðâ:Ž;Oëà´ä¤ótjõ;-­ŒË#çéæÞý½Ï™FeËù=œìÀEü°ž§¬HØPš€`8Á€}[ž%¬=M@0Ôn sº+B»%l‚ ¬‚ Œž"‚õk9,ëW_õ‹sÊß°8‚±I‡öŽàöyñŽ`Î÷éз ÷Í+àYÇ“!©oî¾~\–õŸ ³Óq.IOöësž0– ã0ôÉïFZ~S';ˆŒ°Z¯·)Q ³}À,ß{½6³u@³m@`>>g“æ‚%lÒc@6é¨Â&=„À¤Пà‰`èACAC÷!ðJe€t¥2k1âB$ªzB’®êéú{Èt^áOZ¨x7ˆ£NØzýÅ!Ž:aëõ.®¶^áBá:áèõ‡àˆ”ó»×ð] *åT+8†– `ωÝûÖÛdÃ2¹Ì)]Ì¿­Ì,OcÀwÉ*„*BàD]„À‰bNt·©d4Ñܦ’¡DÝJtà{¢ƒ.8ÄÑò½x໢Àƒ·`¤œ> átd² ä„ïóû ™Á¥L„ Û5&©á8i\*ZÃ5FT´Չ¿m@Tf5 ¼Õ\’ÄSÎ~Êd³¾Ü„·ŸrY$ì§c@öÓ> zÂÛªŒ&½µÖs®¨^u ũ݀à”ÍÀQep%a™0™ËŒxXf??Ö§õa™\I,,³a™!‘`Ç‚¹"ô¨r–èARмo»ó2ï¸Ò¸¶¶ôñ}X„!ú¨º›ëÃ@mÇUA§2ƒE€H2…u¸Î°[l !ê\縼¾ÓóÈ—ätõÅÐïtu;ëš“ZôÞ%ªü¸/7QÃ9¦E&ê¥q æ†uªÔÜS¸4Þ!p¢ixEØÆ]Íß¡‰ÛM@à‰ÛuÔÇ>q»‰Û!ðTf˜CDwx6×î hWyÝ$äd8¥ %'ûônòDÒ uÃIƒC@àIƒpjG>œcÒ`„8%¼‹H$ÚÁHÉPè B¡¹‘¤…¨!¸Q”/Ú%¡s£é€k¸Õ u‹­VSÐ~d7§šHü@·âWÁ—Ä‹Œ&¾„ù(hâ:ëæ£ámt˜Càðuô¦É€vRpÊ¢èï¹Bз©{Ф @Á-V¨D¨&° ƒ‹è}j /Ðzß—¹k·JE"%¬ v´ÒNN¶YFZÐ@kYNDÌøèA‘1Ê*éâD†®y%Ïwº]…"ãô¾­a·LŒþ¤ùîÖ¶å­"£ˆQ½Í@d„|:z ¼Ø§bm,ð‚°ÀGO;2ž:ñˆ]:×–Œ§ˆ=Ï3ñˆÌ$Èxê€ Èx"Aƃ ã‰(Ïè¾¾!|â-”@ž‰{Ξt"§ü•þ¤yFÚ-ÝZÏYÂ[Ýá­n‚ðVGOxt)<…'¢K›€ ¢K£>i¼wÑ¥!PKï $e»pÒ§È]ÄÒ½-™[B¡C‘ëD¼‹¡¢&HÆ[ŸEÍð€„)„²}.^°D}!ð(y{ –ÑQò1’·ö‡À£äaGBavˆ’wØJˆ©qƒÆŸÐGNÇŸÂŽb¨ˆcì-&£‰cÜ|0š8¦Š¥…¹ö!PZ˜x¡¼µUpnK‰¨¦o¡•›¥7¹ü=”& 唺•PÄ! ÂRˆC±hZ‹ýéËߥù‹ždÛO·ÜÙÑëÚ¨#WHÏ;žïÛ ™í‚伞¦É½Ž¤Äþ¤ó&IE©Û€À®Ê!0wä‚)RH6Á4)L;ƒQ®SŸ‰)å¶ðY”‚¤sBƒž6ÏgUAf»à9üù}nU>Å6!¬„h¸û¼ûoCÓÞ" ‡³ˆº›'ýd)ßóðù°ÞòÚQ{.ÐjlÊùPíBnpZM]ÓÔ6DÙ!4øÃàµcá)Œ®kMý‚àͶ*þ½Pë®!8}¡BàžàœH×X/Ô-£õ.}ž"ð€ÊÇÐÔp”Eµ07é+½O_¡æ^=õë4J¡‹hÓ6ÓU¡èšpØqM¸½¥ÐíƒÆ)Bòð.éLt;Jd”“Æ‹u"§ £ÕõžB† 8%X$’¹€O@œVQ¼­ <:¦ñD,Ç:8ÃC`>ôÎTw¹©®w.! ­ÁYxàVŽjOÛ€`xhއÌH~f½2§C/lˆ9áôaßB2:ìö­dtØ÷õ‡}wQ8[Ì©ä ¶ª6 ÐjKî¾%Ý8­K RRPÎT'"7ÎÎ]àŒ$B*êsAUBÒ|w‹Q.˜•‘BH*]c½‘Í°éÆ¡2Âl0 pÒ©<Á«}0¢zŒwH:Á«ÞÁ«!^õè)¯z4RœWn1…º«~u7:ÄÁÝØ¯¼êQ •n¤œL~„»“ûM@àû *+Aì.`ß!€ýÞì;°!ð€ýø)hÀ>T:„A+òÀ©9϶)Úóá{N)‚ÝÿîOKEȧK­O÷Cr3U<¥@ë×¥¯ ,ôFú\¥Þ*[‚íU©y>fÄ>í¬tÞ¢ÅÜWB¥¡³-KxP¶§lél[Ùä kÝu'9ê UÇÆG÷èáüÐÙ^[ Ïϵ|½à<ÕYÌH)l¥WØQ8w£{Ô]4`¤X„)7!ó§}Öï)†äµïrÜ—q†è}Uó½NÎq½/zËHè}ÑÔçç=‚^òïQ„Àn]V)4£ëyº•Æ©TÎ(´H¸Ç€ ÜQ„;pˆcp^µçA’®c²pì0Ü×<€½©5pOÙ0Ňª¯Š "‡aŒhëBàu"„DM4R…ñsîËiôDì{_{Á! â¶ö²°&tƒÚ;@„6$Ó³Óé5-A8ǃÉhÚë>† Ö°arº h¨qŠ[lH]ëГëð®5Û`¤Œ°µ¬ú…á´3§Žh ‚;wHT˜‚¨0ÕÇëGÕ!/çõOº8sœVGð¡ÎzŸ—ýp>Ô*ÔÓÆÐo k̺º ˜8¡«»ÔÑSÊz’®)ÈÀmpŠˆõÀz»2âC=°^µÑSbÁp,ï"J ;póÕ‚¡{dˆô°÷c„8ʯ‹soŒÐY¢xÊ€@Ão&›,!vîâ -7ó‘Ü„ا¾«Þ!ŠœG5>›’áÇq<›ùë¯P'LAÞ„^ï;¸­CXƒÓ· ²J•¿‘ •¨ÆÊ~ƒeh‡q’¶àvC±å+‹l“u §eó•-´o8“‹Ó±¼8éð÷ºßNM„;^ôö;ÝàEwudëº;¸z‹ _Y ¿>žw·Ll¬÷ÌÞuÙ ŽÙÛ!Š£õÒ³vû˼Dvòƒz‰{hݧ3(³/ÜAnV‹8aoWél †Ù§€óNfÍygOC‡@ÓGÀ‰æhúØQ îî<‚ p,2c4K 2™‘á$.HCfd8É ìB!Г Þ–òø[[f4ï&8Œe&IR €“™¢R?•Œ’í_ÿYCÃ{k@àä!¼Wf†L‚ô3V$"A 0A ÐæcûÈ3šqÙj02Ï jÐG‚ÛµŠ«žë)'ÆæÒU«EvÕc$sÂ?6‹l ¡Êœ² ̪…{[E…^þîî)š íï­íQæôú˜Âе%[@¤ý¿%Ëh7½•%£‚™½T'Kø¡N}¸q2”ˆ>$”[ú niÉäÞ-½þϱ¬>_ø.H­^+]®Ng¹­Õ»±¥´ñS6v¥ïât~ÿµ!ÔŽÇÇ}ý¨Vodåøþ®åI2Ôê=¤)\Úè]Œ_…Γ÷ç#¹¯¢§ Få×~ÆP·t[G‚¹¥Î-í! z„)Qt4™z”L˽-ýR¥¢/¶:x mÀvK•cµ}p2žÈ e’S—áz=pFšüýS8jÔë/Þ¨'¹@ Oýô€ÜcÉjÔ;÷eu³F=ÉÅÞ¨gͱ³xqùY#ˆCˆÈ‘oåyÏÝ[ýÅ!ö4³—¦¼¿¡(ŽC¨=âo‡á=EN+Wœçõ©îã9 ̺©œp8oªñô=¥@ŠKüþî§hƲeu._(ã!yTVÇ’7Ÿêr?GcŠóD•wšÍƒBQN;i·Ëøû< ÂÎC¢ŠÞv¸Óðxvý_ ‘Èkô$ªua¥Y[ç>Ľèr‡ú=³ >ÆÃ5˜Ô •<¤XÃàÈúö¿©ü]¢Aqžäó»DSÅy6•w.—ên…oaXYOüF¶8’ù»G&âÓìYÁí=bs—g¦h›a<ÕnïÌ]7pÿô¯_ù€« ¸Â—Ó³¼A)’v±C u„ˆJ¿›[uþ[b¥„Ø9»áê3Kðµ êp†–÷¸ÁÄxhÀ|¦Ah€ä]Ö¦]$ÊÚÁM Reí"QÖ.BlÍLwçî°ñz2Ê«Ýñœ83¤œŒ±w"‹tXÐXC…ÍÆ!é@¸^…L¸~aŠÊ¿òjBäÖ?Ą²UwFWo¼‘Bã1¡+ã¨C<;Fjð ÏÑ;TeªP5ÜX©BÕ1‚Èß‚ÈߌFŠçoÖM@ò7ëÕ¡*‰BÕýš¿)…Áò7!ªØ}—„båæ4¡X²*ŠU=eÏžÚžhId¬QÖRæä*#£” ®6ØQ2ÅÕ6ÄÞõÛ®6)Q®¶:pµI™àj£q\mÑ»\mQ/Œ#å‰ÂˆM@…Û€Àã[C@àñ­ñ8ä®Ú`ª ÊPdzoTsÅeTdz+Î|\!A‡0˜Ù 2,¢Ø´Õýîý9š± +©s‚—îëãygGë¯Ëç!¯Ë½8TwñÎÂç!r§ÔÔ¡.Ÿ‡(œ€ÞHàì£>—R$Ø›€ Ø#AÀ^AÀ!c¡å2TçÞÍ™'`wƒ¦Æ‚µAJ*6ÌùäTt¼]!ž#¥|H>õ@ÊDb\f2‘Xú·,¨¸a/@ªŒ1yºT´ÕÔ͇J$áÁ2Tt^7Œ,¨£§ ÜN”‰¢ƒ©m1·FÁþV‚$sB—’ ‚:èC%ê"Û‰‡] Á“‡JÒqÄ&Ì©¡ pͨ‚¢²ñß–Jò^ ¤Î©~öËi– ^hâX&¢_¯ME(Î"&ˆCš²gzz1©){÷jÝש@‚¨ÔQ¨ Ãy"2Žˆ›5WhÊä#i%Iåëë÷H“a´Mu m’&KÐ6µÁñÚÛð”<‘U}02ÍíJÃIÿ 3x™MŠLâ^•4’Œbp^(£•—Æ€ */õAT^ªBàÄ ð Vˆ K‹w°!ª7­õÝ¥)pêüËBÐ?‘Sbç´ÈH2g",rÒ"îN‡‚‘EB V¦,EþãâeA{ÃüSèS¢Üd!UÆ EgÐÀ·-4yWú3d¹ŠÉÍ]Z¡²Â°ÊèÒ p&«ŒLõs¢¿ÊrÜ0{] ³M@ìÕºoP‚c†Ù6~Š@ûv¢>$.¶ŸB„òÅÞœBãw¦ãq˜,ÝÖQÁ[d釓¥=N‡Ø!•‘t&ÜÉ*ãd™X!*DŽDëÔz•Ñ4w¥›•ˆ„oG×tžÜSL¢¨ º¨ÁóìH?Ø:úA•'ÊÙØ3Wåy"?ª "?*êI8öÆ%‡xì9ôAšôJ0ƒ)Ü+Û±9 YÐÄÍúެuSÐ$FpÁ­ n~ƈ·¨*Á-žw"Á-†ð£8ãÜ ðzÉ RÀs" $YF]…%s:] D/™“©Øn÷J*%pUî$PÛUP‹RI’¿Ï”” ¾:ûåÇQàŠRRS ¢¿ž)âåÞ`Æ ÍwéæÃÐ|— BJƒ^ñÀwY„@©à9cà~P*¥hgLå‰ô;cŠÑD@ "l“Æ·D@ Ü)ž Šú ˆ€"„@«yÀ|¨TÍå1 °ª®æ²R©šËc@°½ù¨Z)6Ô¾Vil>œà)š6–7‚IiÚ|?Eà¼Wm@HœÕ*êC¡¬VC„Ðhê2œRjMõû2c3àÚüÅo[àÁã°N U•¨†ªDj˸|v ]óB^x›—:¥‰”ѵ‡Ò9Z‰ã{ùtµué(S.6‚ãIÇv>4KVÁ88 Î8¥9EÁ2#ìúЂŽ?vOAîÊ»KÓ°FÌXw—jÓù”Nñ¡ÂSR|¨‚¡\• Úë#f×CÙ,ûÁ16ËW!Ä^^:M·ÁAÚĆ výšsÓõ¡¾Ë®®£wÑh¬u2ùÙWP&KðÛ> JŽòÞÕ’°Õ޵Ù}ýÑÛº2ÛTM[>ÜæöË3 x0—@°osªºáÕ„À¸åñÐp*ªÌÕ:V!ùÙ+fˆ»·3æü›ô¸Þßç€ÀÒç]Íe‡;Ô¬0?>%œü¡>¹»‘Z·²ŠR¬Ý8ì|Ìã¸Üm¼2b» á„ùtýïó†Û#¤X[ãá²_¬ŽrúüΟ: $NX#%ëѹèX‡Àr1œ3_%ܹPƒI•HÕ‹ú RõÆ€ È•ì®4©ºgâàžjþ  å6\e“¨Ü ç©)¨J`.LGµ9+{‚+» ‚+» ×>‚qµQ”*¨ÔÞ™¯ –H)m‚H)­‚H)íB`Z„¥¨‚'ØÖá)‚"¼ë!ª]’¤#q.ÁBÑ0Ü8 ®N>MW«§ 眸QöagƒÆWàa¥ÕSEÉ–Žuuye ÖÕ: ÖÕA°®6A°®F‰ØIëªC¬«}@ଫvW:Áº!ÖÕè)Çô¶~e]õ7NDs–3Ôâ&>'ýdpõë ÷žÛeC@œ¦doa¬"Q‚~ †'ÀÁS$)*Wî)ŠâNùÝÄ+‚;etÜ):ShôÓ"öƒÑOgšÎ²ma¹§ ÁH¬gQG^ôM´`íýS:ò¢ïâ£F°•ë<§ãMí¥¬sFE&8åSçœV>§ÁÐïb*yÀ·Æ+_fGç‚*yêŒF:—‰„;§‘û˜Ò‘õA$¤Œ!ð {èCÓ©œ°£rC—±¿Bí)}›ä~KH³M,àrèÚäÆñúé@ðÓl£ZžðXS>[!V³-³ï¢áÚŒá{]÷° Ù–Ù÷ þËÑŸ€‘Ä!¢ˆ¡›CÜšºÿ ¼¤v7ÔÕó~ú{סïä¼1£‘nTþå]Doy>  ¡pŽ1–HH·%¢m<2ŒC$â‘#Ãâø JOã,Ö6Ž"ý4“d XP¤5¶ìrßu\¾5Z÷KÕn}ì ׯßÖ7÷mõn}ø¯?4µ[…z·>ü×ÿkê[Ô‡Ø}ý¶šî§Ó;êCb_¿í#„¾>0@:„FKà”b†.x '3´xévƒ¡ÅË6zŠ8~_zD³7pLÕtý.¾¼:%xê?¯Ú–Ôüèá´bÝôš;k‚ã³í:Ý«ÝxZ›(¤·Þ|ïG}~ÍY‚Ÿgˆ=?Ï3ðó8Ä‘Ÿçὤqàçy>îMó¾ÁÏ”àçéâÈÏóð¾K‡@ùy âÐÏÊÏá B0]üóÓu„ÀY™ÝH•ŠêTGÍe"ã "Ã#êƒÈðB yn¤ ‹Ã±J ˜5ß`ý¯K Ì!&`¨†€`8‹hÔÇYDÛ€{öŒæñø4Cô‰ºP‡¨…s„Ö¡qŽÐh¤fçA­E¨C¨µžB”}h¢¡nȈÞD†W8‚t…£ohÕ(H½Ò"#©q 7[‹œ Óê=-¦ 4-Uaq¾xa<Á¯aßE2X¼t}¤*£¶Á° TmÔ‚ªæ³·µÐ´Hþ¬¥ørGˆ0 ú6 šLàf½ ÃüAE‘žª¸epÈÈÄ·…9•‰o#ð\¸¨äÆr´MWCÒaÞîÛJš**NjIy‡u>$zßEn½1…S+Y*ŠÂ©¡ÞVÎÝZóaÏIM{Œ\&Q⤠´>ïäú ׇÉUF‘Îr®ýr /`ò+?õÞEåhŽø,„ÔÃ!8rµÏ›a ÓrÃH•xçB’µBÂïNEqã4 -˜ˆÊ¹@B;þÖºwQԌݾc„Àfl@‰Q*ìÎ^Œ¦÷éüþ ±ÊÞ¿Çã>¼B"ʾÝõ^G}¨cÙ˜O×Ç#µŠá?óS@àº/&ÈE‚ ƒ…# 4Êí Tj|ÛDÈ:\쪠© áüÐMí Ò£Îhÿ(Ê:£ýmô§æ"'Ó"€—A§jü0ê®ôidZ :̽mŠ úHq¡D†'eû¨D‰$ûm·tÛ~¿´¡D’ÞÒmûIu(‘¤·tÛ¾DRJ$i­ÉIíõA”HŠFº/‘T‡IZk²DRÛGã08A9̘¡“;A ¦SY+§JG©¬ãÿEˆÏýö#*nŸbR¡âu@0ˆH¢¨}$Q"‰L–'"‰š€@#‰Ú:Bh”­†§0:Q±>8¨h÷‹C0œž"iì0c’"˜­&÷]T"ž¢iGŽeJ2žòÒõå²”"ŠÝtˆY¶¨l‡‰ˆÿçô¹$£¼Úá/ zòÛe"gáþä‡óÃ!0­ñÕØsÌDI¹±Ö8tVú€@ë¯Ö èú«U×Û'*Öåëù±g¡ w«p“­´er†ëb£×MNdn¬,¦f›¶»ÉËŽR“‹­ó#Ðé@§kríÊg(øã3æAÁ‡ÇtˆÉóBaÆ< ¦tsåF#58UnVÆÏ}IÇÓÃ~É]„Íõ¡EØÚ€`GÍbr„&§Ir|E"=Ô¾-Ë”@¶†ç(„"[&ª5|LSµ#ÅJÞÞýt ã ¢l‡¤IaàÛ²}ò¥†À-¶uFÄ­+[dXª&6<%U»<ÖÈJ(O1½¶í«„sÃs*ÿÄIㆳawhØ °N’±O`q6œürN2\&Ø@í—ã4÷48‚ ‘@ %‘¡(‰Üž QG}ì3!êPÙpM„ExmÞp“ …çânaÆ :Œhâ6sò‡HeÙ>D*û(B0”£N\Á(²WªÚN9ù¶ëë·u6évºÌï 'ŒØÑ†DR”h4Qvá¿ÿ®9=ó—»»´]² %ë!PN÷.2ÁÂÙQ€q„…Ó`t„…Ó`t‚…3B£w! 0öATª‡>T¢R} gr_NÓ(nÖi~](ŸdH~]_"ÚÄüºû¢pÂÐÅy½,Šy¢ýr2£c¿á]dFžchdN'±»§ä‰$ö: ˆ$ö> Žk}Ír12E÷c¿é\¹#]h¸‰xÉØû2Q2½K¢dÄc ¼dȸRnÒܽ[ü´¸Å›¨=ÓkÛ´Có7D…•¢§h¬¨äÁ8„ÁŠÑ:IZ’%#¦KÏX†¨¯ÎÐï!¸K;žÕœáÑð:*m0ÃSº#ÇSºÛ€ ¢ ¢>ˆhƒ: ðhƒ:Bh ¾µ£§hù^ST"nÆ­1I,u÷²Rdl„«™Øï½FƒûAšê4C¥irTÐaUA—¥‚5¦3’æ¼A#ñ½»°Ö5#+@ˆ°‰r~T\0c;m¼’Ýõ %fñ³ë´)5x`wÔd¯çæTKÜâ· B TÁî]T‚¨úÐ ¢¾& ¢¾6 8ÆK16¥ M(ê¾\Gô¾Òˆ1ä×÷ú§A‹Îߤ®¦ïÕ"M} •¡óÜ RÀAŽÃͺ‘¤g 2ÐLä“<œÚ> pZB8ƒ •ϽjBGzÝ@ ç‡1‰²¹‚(›ÛQ6· JÂÛ4_ìý"£ùBàËm=Ž[â[Ø·‰ïè‹ç™‰ï6wÆÁ¹ƒ‚á9Œð45¨9Œ†òI®…MAE<ÍßvT²_LçjcÁö´-5»-ÎkóÊMa¨â¼‹§7 Åy»oSžàÛ+V ^\Xc[¯åv¶°)4=޲ ˆã8®MéîÛbIó…@ GSÐåA.,2šì,±ÅίÇgœ*@°}kM¸·+Y*J¨ ŒlÚñRTjášó[d*ÁÓï¢QêõÀÓQd:ÁÓÑGI~[©!ö@2(²„5Æž–Ež%JY´ÁpJkûõó½£ì dï¨"Oøy{è#áçíë€ ra¤‚Ì=ù£È%íq¬Ú€À=ŽS„üõ!ðX@$êHÂ*ÌU•kuMîðm¹IDõÁpb\˜õ‚¤švû…¦Îu’AÁrÚ·ïÂX¢ÒYh|× N&è3NÆI¦(` <ÙΑcÛáÛF¥W#»bÈ1‹¨ôê֪콅KDV0RÑͶn¶Ø¥ã9ºÙ:ÐÍÛt¼•n¶]éf‹(ïH7õAÐÍö±§›mÝlÁÈ(ÃYüˆÞÖrÊî …f f¶ ®®þàXêó0 &2à€«ß¥ï£>øŽùrj®OóîBœ×üƒ‚ V#ÛÏ¥›í¬óœÎØ€‘r–ÈØh‚áe`]^?wÒq×ÔÞ¶ü>ê»Eìv¶«Ë;ëQõýÖD´³ÝH«Y÷psºßÙë»üþþ¢>ò.óÖŠrc žWPÿY²Pë€P{¶©áT=†_„ðôÈ Ó|êK„0(ó HŸ¼H¤&·A¤&×A¤&÷!ð²`ö)džÝ"'Û>DNÛƒ@–Œ¶um@àö éD*¬'ÀÚ9%sõ|Šl!‰€(öBH´lGµ–í(„¢b€jˆ›)]`¦r}BÖöYAETÑó­ˆÈ{¬Mkg]ætá0‡dD¥UoQ,$'5q7§„çªùÂ8d¢šox5_X…‘_ó¯2E—Iƒq(’ÏÎCÓ…Ô@‚•‰Ò@pïÓ|©Î‚V¨ŒšÓÊiÀ*§i+`»Ì3w{,ùÍüý-‚£v‡yß:{a±÷¿@ÙéY°øÜ N¤ˆü/®V:ÔÐ~•SýwˆU¶Üd[ÀÞW|wâÆ¹‹0‚Ì]ÛE3ªV!ÓªP’¦ÿ‡ý¢ÈÂPŽÍ°Pš(¡¹Ê…T±¾~•¥Í– –«Bg ª;MxßzOSlùAãRŽy¯Ð‰27ðm5U0aÕ µ ‹ÁZ'‹õ­'®Vtv´Ch2cÃÝ„Zã6ǵh`Af'y[p¡‹Dž]Dž]Ô‘g7„8lôeå´F“Q²öô'É0‚ ›yVÚlœÂdÁFýùÔd;‚ ÈÜ~}{jN¤¾û"Kݮ㫼þQj¿NOÕi<öj²83 ¬äéï﯊úˆ6à”ú<ꈂ'Øh¢§ =/zº–•Íä„f½q £ìN_'çNÅç\¿pÖE9_[»SçåœÀ!zs€Ö¦0­JoO2ÐqŒ ³\ÜÍod‚±ž¢èl=°F˜([ÏÆÿbÃËÂ$ÊŽj§¥[Ëtd7Ôz/ŠŒ¦oƒó¡ÈñXg[À ,‘ßÒîäò_‹B$Û‡€ÀÛávˆ²±v§²×°°ß¶ ³!µ(è¬A§ÑhiÛêÜ{ŠÀ¢Ðt>Ø& ”OùÒ·Õu„ýR$¸–IJO"ö󜗑Ά=Åz`ú 9ÍâP‚ÓwP!ÎG2Z]äÊÚàg„L0cÀSÝGMS7:„!¥Kksž'Õ[‘[{ξmŽæ‹wk½ÁèüF˜Ó]ÆÎ&Gr‚q$ôµútQ¸ÖÎz®ÈwÝS¶™Φx¹W?ÈÅ›ëœ:ëçÝF³<¦ûð†uJÙàŸ&¬¼Hð<Ø>XFWiÇ€`ÇÒsNB9í…·exö³õi¶M@0Ô§YÁH9ÞÇât}ð× ¼‹H°G·Áð¬Rèƒf ®bC:ܬÓ7¡õßÏ{´m¥–: ^6úØÄ nËÆu@0´\[3Gã”xJAž¸ýdß–g”Ô²ôŒÈ<Æö)[’¸mC Žf1,A¨OX|#)m)¯Ê6 0Ýüi#Îë<ÂSng©Ô7#$]»Ä͇ÂãKmšËê£ñÌ’{i›!°bóîJÕò‚»Ap2ÎÚ6g„ wöo †s"ÙïBׂOG0”Ϩ9U4ŸHB%øŒš€àH•5à3òsÞ@ÄJ®×;[˜DxxÊn%{¿ÆRîk±;±Lóçgĵ»Ü_ÍBvéì°ÆúyyÜš€à«7¬±×õ{!vQßßáZ>ïã) "o’}Ê·ùVÏæ>D¦Ž—Ï·¯^í½ ½‹_2¹!dß#B9?9þžWán ¹%í½žÁRWÏ}¿dƒ{D¼÷-‡yÿ{|î°Öå–-ÀYê~ýïúæ%;ÜíþìÓõ¾øh$]ù nB©pBÕުΠTí³÷¡ªGà„ª1‚°÷D„PµBU ì=Q{{O»Ú{<·÷üýaï‰ú ì=S4e9ž™ìz1tfrÛóyáÛ4A9èûLŠMF_DF_Ô‘Ñ7„À™QìÛª<Á˜}°c^„ÀoP#ó6O(o’{ ­iß`çF^‰½fÙÁù )³U ‘E™Çøb@¤â‹û€À3\@–V©8çÁPÆ7RCQþ×#œu„Gxm:KdòÛwÑ9‘U|õòxðìéÊä`͈ýâ¼3‚“|ENçÓ"ÁtÙ‘í Iל‚sJï¿KT/ vTTOlË|ÑóÅŒÐxÕ2ŸU6# é+¬`E>‡}Arg#1´6VÂw19ÇêWadt¹“ê '£Ë½ÇQ™ýj#1T¹çrŸewµñ=—òQ×vÆŒÂÕŒ#C¤©K òÅZëi+_´ÍõS~O!ÂÊlï¾›.å_@ÈrÎ|«×ßË¥…gëÀ|hZÓ†»ÐÔBfW2ÜQ¦ #*m¢ÈèSÐñZOàŸ›QdûŽ|¿ú÷ª>pâÔÞŸÏBÐ-vU˜œÆ_¯¼3‚'x ú€ x "Ê[0ÂŽ*8š»lµS7R±3òµë󹈃,=^¿Ÿ;Üs…ØEUYĵ)¿Ÿ¶úûêÚkŒ¡GHœ« ’È:Ÿ&gw*ÍG–í‚¶;kÎ. Â}¹ª:wecÏ<;z$oKæ|Í›s•-Au WÙ¬YWè³wå»ÿ¾lÖ¹G¬úü²é–w±•ö]ò¨’“_cˉû(¯·ò1YDŽ}Ûo_Ãß8D\ÃÏÚj¾Ó½>M@ðuÆà ú5¿éñ¶zcžõ¤åöè¿×y°§T”IéVOjÝ*ܱހÛõÏß4u‚»Ý0k…S÷®^³þÚ„pþ7Û·°!vý½ˆ}¶ðõú˜UËw‡láñü}NÏáõ5˜ÒÛ½o†Ç÷òˆFjp²~ørœÌ„;;ßùh¢;ûõ®!è›°‡§–~ˆT›ŠöNðõ5Í*ïVm©‹ažÑ–ºÊ톂.}ï²Ëרœ§Ö—çy‚! j¸Õj¸!¤ÝôûÐÛùFÂiÙÃŽŠØÝö§eÓ¶Áñ xNÚœÁC—ç"á¡‚áü³Ð‡¤<ÚÀ?ë ešêá)*Á/Z^ÈÇ=%Qk² -å2À8 )¿;è£HTÔ¶–%*j7AðHÕAðHEfbÁ Š|VG>»££#¢¬¶–o}V¥³µó-v®¬½8gbke=û{¹Îî!¼K¶F¹ð6z„?µ—fÑ´f™®Ïn>‚d°cvü5°çØ*üóßùËà&üüʱoª¡v7åm<[I:g|1ç&;›‹ã õzÂ:e2ÁwóqˆaNx ê9…l 7§šò›/‘‘Ê®‡> º\ œë Òè Á qp¡R%x|‘žÁè€j80O Ã´’ ¡ß¡Iœõø‚r!¶Tb²)ÿiˆ„ÐEùl¢>ÐToPùs¡é`%7EÓ<À¦"Kð¸Ræ3¢H¶Ápjq‹Y‚žÜ>Eæ¤ñÊ’%Ò-ìw‘ ²ë²Î¥HžÀSd‚\Š&þ…¥¼wÂÄÄ¿S„`åÙé.©QâßÊÿz„8mO͹©¢§ÈCÀly:¬ $—š"þ­>CÔ‡ÆÏš€08áYÅÁ¸ii/aˆŠ…ÃË–»ö†ÑL±7—E"Qƾ­Ê$v*¡ÁS¨T‡@’œ(ôÓ¯$¹¢ƒ œ°¤&èLÍëwiàüPœLêAXR‚¦gƒ{[èg—ˆ •HÄŒx"&¨¸É2>§€ 1ß–ñi–2>–ñiã‘b‰˜¥MÄô<ÎäPÆç˜„ ;[¡OëµÞíŒ0;˜ƒ×z·ÁvOëµÞ­G Á®š­Gˆ}=ÓÞW³õy©«Í:# b¤®6«G #uµY=iÛG} #@aSjÜ\ÉúY®‰ÒÚ‡ïä:§“ `}h†%Ç/).¨.ת›|PCAu‚ã”&0™ E±+H‹D=uèCÑ…\zèC'èü#A¨ O1 BÕ! âƒ: âƒ> VÇÜZ¹.ÈT« Nm“Ñ´pš<á(î‚áTУéj`N '×)8¾ò”ã ä1“ ɇUhT‚ÀFªtºm@0”HÆÍØ&Å:Nç›ûõÍáF¾Y—ÃåyyÝ#D$'ßçwyµï€àGC¾#R÷eޣ订lX§E†}[K ÿæ­"§ÃvAº(X"l· †&(€)¦ Y_ }F§Xþ°EX@vˆNÿü¸ÅPWŸò N!Cíò*ÑSNÊ3–"åë‚ åk“”€”Ï#ÄޙخÎÄ<8­gb O_‚§hšÈÔ$ŠŽÔA‰ˆ»Ññ§7¢Øì9GrZÍgGÓØ]ɲMpÆùìŒyãë×õv²½{íæÜâSù­­É÷š•”œ£§*»ëô±' î5‡€€Úò;=*ìÈV÷Úßÿ ® v/¯ëõ/ ”¿®x—êݼß6€e‰¢V d"éæ#º+ÿ´¤n8Yz§Á°9}¶S³ÎéfWžÎ>´óò˜À‰Ç¢týœ6nN96§—xN96§U<§<1§÷€P(Eå3¦hŠÊº†jâ ŒTc.ÜÏß,Iƒi›eCüþ>ŸÏûÖD¬/“ÚÎ’ã©¶nO‡ˆù«ÁÄ^×·ºyDDçoµ¤z tµEW=BÆ7Ðò.óßósúPþ´¼:·ç¬/Ý„§ó/áP^JDÎOé"„Ù!æ56#ª& |­Û˳¬í,÷wÓ¾a> ,œ¥³tî}@°âw{TúÜßÔ¨Ÿe©eç6÷è)Q‰Hg»¨®ÝŸû¶Aß¹Ö+K™åju[¸9ÊçëVG#Õ+Âvq¯nÝ÷uú;„Ù•™lç%Øþ5M@ˆVå·æ9MQ‰Ø>ò•H•H„ Îõ!p*3û]rž(Ó!Nï"hÚÏÆ!iÚÏÁð0#X§Š–úZ@h\ê»>¯¯±A8¢ÃO×|gÐ~ýÜivNËòDR!¬v´öøÇëk9Šx­! ±§DúÖkˆCð}Èóq¯Ïï& Ä>d\C@BFûÅÒ°ŸËë³ù{„ÂÒÊ øádxõZFpp’ ÌÒÂÎAL­#Ãib‘J†·M%G¼\³®”Œ}@”ŒM@Òg/Al÷Kp&þó¿ö?_/Ý4ì»GàÑÛ;›g‡ýb¥œYÞšÜw¡)^ÀŠÏ8£SÒ[@p<¶ööuÆ]’¹†>d‚ŒÆÎ:Wt˜@O9Ð-7Ð4ܺÛPÛµ~¤î²é:õå^÷ï[@Ùä Åy6žþ"D”ðeÓðxvý_¤6î·ÿMåïÒ„Ä s¢ÀÖupX³}ŠÜÆa=à \쌉|/,—öbc;ÿì-¶Öbk…»ß¾Ãó2õïw@°]ºÎ·y|ŸMõJ€æóW~—øÑ€ðå$JWN¢¾v³¬_/9cwƒà‰’3M@%g†€ JÎDO9„­%gçª/9³Bðº&SApØÜ{·gç>ÁB”tœû+B0<»^'•Mò•nÒL‚'^—œ #32ób ˜LÄ1ƒØ/‰8æj1=D†š/\<ÑGl`Ž}×6ŽIA˜p`JA˜­;0¥ØgÈÚMu{UûøˆýùŒL)bw㎣ÞE&²Á¡•`×€K8½aûK“¨« ˆ‚沃ËPe f @ädŒé 6bd¸Â×¶âtþëˆí·Ú¦­ÓŠ)‰™/>‘IHm‚æëÁfhúÞ@¹PrŸÍiÅÜæs½öã= ÄÎy6Kô—ßÚPBb¬YœÁ¨Ú(kŒ:S©ør©¡ è Ž©"‘'cŸ¢3šy LB:§™—@ŒÑ9ͼ__ç4ã÷õ!Œ¬ýÅÛ­K*ä%ÏÚÃé!·uÑãëüÞO}@ðáò’¯ Äj¶u¿ÂúXúxÞA×lcF9C¦ÿwø–%Ĩ;D¸.í­=ô4Ýßçh¤:BÀ»ŒÔÖó_¹¶ëµjàÚDq@,+Ù:FýŒe»T‰ùÞþvwkýö=oÁ³}\¾ÍC‚¼ŸæóîŸ÷¬BÂWnKõž¿o3D3ŸÇ¸lÚÆåñ+çÅAö1õ—×ëú½Æß/W±ÕoÙ6÷[ùƒÄ@Ñ8Ã#Ì-ß)VD\§fé¾ Ø™—÷bu½Ž°÷´8Ô÷^÷g÷iAÕÕ­]³²TÏ™à*D¢N‚ëCSI-ð£0‚Áb€aV ™Ñ}wû·HpÙ·5Ù6–@× WÇÅð:ß÷4TÓõÇüÃz•ˈ|;¨£ã@+‘_Æ×­ìŸö] Z‰ü2‹Ìw#±/'¬#¯éóƒÝiDymO¼e¥Ößîu·®:‡;aöu]¦&zŠ<÷WWOrFH4tª·…‡€`¥+÷Fîò©‚èÞ Qb_Öp­éÌ+73É86˜u•P¡“Èvè‚Èvˆúàxn¼‹N5õA5Õ5 ÑSÎ딎½u†ô"£+aGXÙ­•f¡´C„À™{á J8{¡4rös;"DÌJcOö±º^Üm¶uöFü9ßKcùsX±g-rÁåùÏÖðóŸ çãwŸmûº8Y&Êa\ö-‰x_˜A@Ÿ*vÙ¸÷å]nÝm¡­á) ˺hÏïél×Ç|UÝÍõ¡±§ØÌÀÁ!L‚‡¾~AsÍÙ“ŸgÍždÏžå4{’=µy”¸gH8;Íðè#ÊPÇ}` %̇C ôÎ9ÐyÆI:8ÑxÆÉøÿó}HZk«`‚ˆÝ÷z?ÏÔ1ѺP×ÞæbóÈíxØ ŒÔltöÍZ/#CwCŒà8‹$ ( ÃU d<Ïè s» yž'x¡–¸Õí¬oF»[}v¨“°Þêq¸ÕÛõVwâVú nu‡HÜêc@à匛AÜꂸÕë€ nõ& Ô>Tù´²¯q‚Ò†õð]nÔA°ÐÂSo¼K*߯QP,-„ÄòØE¶=ƒnß:B`gÐ0Ä}ð]ðî÷ý{t¼ËCFÞ>ÔY0Bâl–€ÈÑ‘.,Õ`Yä ·ÆÙ§À¬G9{ŽY7N³Œº§ʺ0ù‘Ê?†ÝûL%ø1š€`x-Rûm™NpVA†¬Hzgé4'+çY‚Q9YB9žçfNÜŒynP}ѾË!ÏÍ[.åx?Y„Ä߇³£r.–’…ml|•Ýͺb8ßê «d~Ùû_GKÉ·,ÝZßV VŽÓtoÏ÷€ˆ-%w+õÕüÊBG'ô1kÀÌɹÜZJ,™úr7|¿€Ã£ŠAPa \ìõ½ìÇÛ9š±lŸcÐ>ºéï:Ù›Àt´Pø×]íØÂ1]òÕ4±'P©ÇæúyVu@œvÂ.TN]IÜ¡éMçÆaèMç;’ar÷iÒÐGA& ºkLd´Ž‘ÓïãŒÈ…ù+§ß×"ødcFLßþòj-¡!‡R¶ÔùxzÜÀ˜ÃŮԆ³pÍWró¢>ÖÅîŸ2õϲ9õ!;Ÿ®„ˆ$¾ó¢ÙXÅ|=ŸAOóÈÅaA Øy Ù±Æ8#è,G}š3\¸BlÍ×µúÐ õ2¡ž A¨'Ї¢©lAì(E¹3†Ø~.Šͨ1™Ñ…ÞàPÞæÒE‘È£#æ2'¯B§ÀçBãØ’"^a¡>MÙôVçRb‘ KFÖ|¢ž‚]9…KA“ºW€P‰¬P»+·.£M>˜H¸4¤¨´‰\Œ6ÑŠJŸ1BpLTÚD‡8Ò&¾\–¸Èa>Ô–d5•¯Ïöœ’„º6÷êšÚÅÖyÄwxô×: 8N5#MQÍÕÁ0ó9@¸Òôéð‚áYðƒe!´! +ƒf!´k'rØl(0Ê캕äë'äì;dC”M@°]–lÝüšsÓõÑ€ÍòiÔ‡@Omat¶%û€;êÙÍÒvc]ð\燼@+äÎZöoYÚÄÕ–U_EŽ“âÁ8X‚Búà¤Ö‰ãZed¡L×´ ì\­Äm@Dr0MäÁ]/~Ö MÌ w¥.°ø«kÈ£å&?ÄN-_îô¹NwPÌ.†Ëú×o×±ŸU±{„8éÛÅ4ïb2”âmA´mÔ‡À6j–ïK(òq­/ßëøâ@—ü«šè’y(¡äc¸¬K¢ºžš~ˆú0±l¹{[=–Ö¿€(ðb`öÛFS½¸wáh!âkÉÀr-ëkɃËêX¸‰% #Š‘‰Ò$ð]-óƒÄ¶Í¥[|C7Ì'Hi˜*‹0 :2;Ž"Kd"§CEà *MÛ ÷mÁÄð‚ ím%†‡¬r^p2c¯9/mç쨸´Ñ¡ô $]ú ÖX!éÒgõDé³& ö2]½–>ó¢ôÙ{*ìv-}æDé³h{*ìv-}æò]*ÿõeªôY<©¨Ü䮼 µu(79#4©»;(rã GØ]'²Œ&‹9§@ÏþK ‹âmâΨèè´Epô(¨Ao[GÏJ}4MÃ,÷±•rL¿\¦ß¯¥Ã×ríÊøÍž(ã!°w2~¯å¶B?9Ä~-_†WylK2ÐŽú‰]‡Aè'c@`úÉ`+ðyDv ¸‚NÕû]Wð¶‚6]º“¤.þWÁS *[ør7:¯T¶ÁðòX€0´;©†q¤û4~‘g(wÁRèkïB‘o‹|ž\ÆDýú¼^SÈ}º¼ËsÀ–fTDN«½î^FÔw²º¸Èwk ‘}ƒD&rŽId—¡Ÿúº„DÖ!‘õAHdu@ì%²Ksù^é{‰¬™Cì%²6Hd±—Èê ‘9ıÈAW•£›—‡_uq‘«„.>¡‹ÃœÊ„.!JÜÀH5MÜF†’ÿNu@p”ü·ŠÍ…êa¤†.GÙF†f\°‚HÜt†3ˆvÀÕ>BàA° YFŒö¾8%¦£Åƒ>òDaû.ŒÑ…EÆÝÀX¢°È„4õ±·Õ¡°ˆCÒTÔQX¤ \š²V6‡ ¤©:š1¢°HA6ŽñEf?÷‹:^Y§™ þÆ€À“ à– NKä–ª‚(¿ O‘¤ãìJ‚)2è¡s}hš9 îfhæ´j †'@œ(˜A™ÓëÕ¥ŽúX¸Û½BzšY7ŽvÞ¸õ{ŠúÀ˜Ó¦Ï½‹ÆY£‘œ1ê£Àl1È([²Ò­ì;—g‰Û*»Ë3zçZ½Ð!¢»\É·ú÷¸ßÜÎå±sï~çò ¡åJ0|ºî>D#Õ›üõq¾>žM½m´s­Oª-Ãèv.Ïè 2=§K@nçò@h‰”.ƒÉéD7ïd) , Îl M@0¼@+ŒC R,$!ÁûJü|X“'ÊZ®§ƒÀžç µ¡Ÿa…hÚ†þª·¡Æ€àÙp‘c†Ïû}ïb Tuûß¡üNííòŠö›ïí;|~sÈÉ´7Èý|ú;ÿ;¤]LUõ¾½â çÕôÇè)bÇ^1Mݳ«ÜJ5;¬Ë묺g Z7;rg믆çãR÷÷€Ð1·ž=A®ïù/B˜ŸÃç^þ>ý£Øå†¶¿nὋÇ<Æyv-ˆ:¼ #Vܹ×9yö1"O,å6 N``§l—N»%0ˆ '“ƒqðØ€±¬±¥HÒB+ÒC4’ûd{ëb[bŒëöÔD¨Ns’Œ¡-Ç?7‹UtŽ xÊ1.÷v·®ñïn¡pÕ ,/?8t…ÞçB<Ê4ü `Àz—aæ–rPÙ„ÞÇÖ€òð©.÷s„{¥nl>^©zLjì£å?yÀ¡*[¹*uBock|%Р²‰•Î4Žˆ\2»>ï[J6ª´ bójŸÇ&D‘ c°ï¹ùæÐ‡L‘–Ay¢®6 XÂÐNg1À*”"ahb_¯¸ õŠÅ6T ˜û×zÅ"„ æþ1 8î.„>í¶Kª„»0B î¶Žâp}||$³š¦AÉ•†ÎQ“ ,èE÷m :G1F Ô5`Ìw Óà *CçÔ Ó°TF¸‚;¯Ò«Œt·Ö¥$T¶%¤ÛÔŸ€qì¬V7Ãxªá:U» ñ7;ßþõ+0§!ÜÀÕ]‡µÞÍ;‰„b˜K© õh…â¤9Ï©R 5Æ´C8q·9½þĽ¶—ù‚wŸÓ{u'îïòƒˆH¡vÑŒž´ìwyžNBìÎägÎd%ñ÷·œ¸m@¨CÞøÃç;„FòÆ?7îuIƒ©e›9hó)Ö}?aЯaá.qsj†zÎ6 :wKF)Tf—,Ò7×G±éc3ŽëÃ"41Ž©{»>4™Ó$Bg´Ö©Îh#jŒàˆAØUx:a#»N„£>8j˜†³P³]X#q †z ¼„{N§(/Ç€ (/ë€@ò×<å¥C¼ d¢Ó e•€ÛT«DÆ?<ÍÖ{ P¡Ñà›y¿øà¡ 1뉫éà›¶ž"0zwòë?ùím!JQ·©.¨2TfwÖò²a†ÂÐÎ+¬B“S¹åÒ¸Éɰ)pI ÃYÇm@0ĬxsfEÃéPE” 'å¾­‘xžÔësm@ºˆCm¡M׳vsš¨÷FECó,8¨@+ýUÃôº@Ľ(òC)d¥w×Ù~—bsgòÅi¾/aGEy–òÅrAôÁ1ÍÓi$í®¯W+ Añ´8º}‘H€kHøF&t< ‚LëA™Žq4¡¯A¦b°âB© [ó÷d*B@ÂÁˆA¦" H8™¶»­`ï «û†°:Qh"¬®vau†ÕµU„àh@u³nÕm@Õ€(öá9Ôê/rÒpvÒÅÂäÒßcD¸÷ÆaF”³Ô!8Bb__­,Ɇ²k‡1 p½²‚>¶¼$Ž b9æY,wÑÎÚüX÷c@0$¬îo°Ú¼Œ\‹w8§1Bü„§ˆDBFk’ÖÕxJªà <%U𥠆޹‚/|é#„8è¦kÁ‡ ¾´A|‰ž¢q¾±è] N7=¥80ÛÜsðCØ”þú›å‹‘Ù΀zw_ÿuýÞÏ}@Ä™‡Ž·æú¼[b<¹%öÝç3ÞÿB2©žUu²$Ã2">Ü•n74”•Oež%2—íœæy"s9B™Ëm@p4ão£uSký’9Oä¾Ã»ˆDî{{RÿY‚õ¤þ2ßÒvǤþ£›1IÖ„Úª Xékð.K_{†ô5B v=>}M®¡ÛúßcýUU„Xë;Úî¿æú^eô‰³+(7‰‚bm@àÅú¨¼š5œc¹!‚|u<™4+|FÊÚþ~a©û¥¼”S Oa;yìîä±u1N® Á”S$²_ ‘•L$X¾ú€ X¾š€ÀIdaÏ1A{ò#¹s­»Ór)²ÔÌwE öå]ªé{ Ì«qê> ¢2LŽßéQN5œ–L‘‰˜À)™¦³°áFf{;Œ/Ãt¹öã- 0;® ÿ“Ìà,RkíLÉŠD2g ¥¨‡ý²uÏn)ê­6ïl?cïϯz[›Cð]ù£Yú<ýÕÖ¥éQG§ÞOÍ=îCbô•µ±9„B èá „F 軨ƒ‡Ã|0œÔÿó+O KqŽÏØï÷ù»õqœ±ß¬á¸·å[ºlGÙ?-úÈc|ŸvêèÿÊ èn%õ¿XR‡8ÌXÍGgìͧg N:.‰~t¤þ’‹mz#dƒOÓØu½›±[Ažöt´ÿrKò_GØQQøÆž EJž¼lžmDrIxV=OŒä*ÁÓÃà);míâö˼ý×7û·5¸ÊAÉȱ¾Óçæó4ꃣœ7îÛ4ëêØË Ø·©›ôMåÓ¤@Y‚ž%H Fàs,AR0ªŸc ’"Á'®`Ç@ƒ¥tâ£z¾˜ÆÎÂÀɼIp{tïûÛò);?Ü/ó·½X:uùÄ×€˜e­¯e?ü;Ôe]–QÇ“Žíú„í¢_-R4ð­ý^ÀË*¥Ú"@Ãùôßëg´^@y¼WÔ²XöÏß¼-û€ðUè—è(£R½¾÷w„~gû‚/¶Ø$È0Rí™—,Þå÷xtpZJµ·L,ˆYëºî]„Žu1[3èü}NÏaöˆñüÛ"Š¢ùM×éÍX¶ Û6ËÚÕïe!:Q)^ÆÐ•"áx†®ÙGŽf'¹)+·†ÏN’²À/œkÄ~ºà¾?ºFàrPYºh‚¤ÊµGìHÃÔ::Pwõl7*¼‹âÔ»Ô_ë“J .ÍöÕ¹‡@]š@vç¯C ™`>„"3—PNÎHqî=!šT;jPk¹º]‡GõjÇ& üAf™SæU6+§?G) í\«0R<Þº+yüQ¸k®ä8þíkGª3:Ûž\ÞÇðŸ>Bp4ïc/u  ”šÑ!0c{šä8ÐÀ!$à*LoØžš~–”@‘Šœâ[Qi5ÕèMÔ´Æ~á^]ö³ý.Ú n¯EDW³Ô„ Ü­'Läâ=2cØ>L–`Æè‚`Æh‚ãõ}í8võ[cQ©‚•l¶uþ\¦æ÷r}{“@ìÀ ÂTunK/L™U4øç¿óHO |Ì*òØ7 Z¶Ë‹+wûpºaw¹ï.v¸mnÃy°ÊÒˆmT\½æõÁ÷q¿çgù…XziPá¡»Í]ÜÛ¿€`»‹ÿ9_üÏû» Ä{~šò÷˜WK@ÄèVT*¯¿WwBî¯ä[ßý~¿¨…©IQ. Y§¼þöU“0]E©IäG;Ä1#ðåy$Nµì‚&`ÆÁeDÐDhÐD ç©1qŒû.?Þ%aêñ³Èù vÅ>äîë´9o¸ F«ópJmÝ÷[uvTÁˆ°NOù, ŠÂvÉ€«Û/Ÿß Æ!”­04Ÿ@kÙd‘Z…u@à«pˆè*„Êî!°“¿¥°Ð4?‹ëÃ$øÚ€@:·’ ʈ²„õÁðõ±Ì©Ê2j}T°>T–‘ëBUTäòŽOíÁªÀð”µ_ò«­ ¬2"Ô­ZBDà)huø2¬Á1éó[¯Ò§Ê8-}Žc@l\Þwàw DDEíc@ô!©ï2¯ ©J¦„¦ÃÓ{˜1“OlÛB@îÍ" , ÷ ¹u@ìrÛ…×o¨#ßÝûµ½÷aåvï?í½?Fv4¢,÷~„@ï}àfr&¯À—Ëó/†}—-åó., œb5pa&jçžÝdX·Ð‡¤3¬›> ð kXc¹¤3¬§6 Æ­®"•+ÒUÔÂúçWÜÈÁ1B( ¤"'ð6Älz¼Îð¶†1³ç©Ê bæÖ˜ÙÖ¤‹r,Ûú(¨»áöu_¿ î†aÆ€ØS-?jù(ÕrÛGO‘8׈E°,Á›ÓÎ5boBŲ×HÔ¦v ‚kd <<Ë[A‘Ûü`Ú<ÿ½«Sþ¸8»Cˆ}ÐÄû}ýUå) "™ßÞ ó¶zU×W4…g“Ãw9–б#­}î¼Ú»Í½%¯.§êõ³¨Š O1 {~°"‘Ìc<£í…ÐO([IZñüÀœá9Ï6RaÙÄw_–À®SÎi·†•é‰Ò€‰À>©¢øòþÚ{„`x`_¸ ¯‚£™w@’V\Ó…aî³xc=»½C‹Z=[í²x·L©ð.ö7[Ýy©f|}v BìBª.6ÑÓrÜÎ;& ¢ª¨aë”·V‹V[ä5\îýëžw鄨:ùÓ²ý³Îh‡î»X öµÎ?gË`ëщ»dµÞæýT»¤U‡Ð{}ÿòøÎ‡Ð- Ìîtøû{_>ŸWô.ž e¿VVÛš¸žfýsþûœz."תcݺÞýÛÂ9&rÌBÒŸåõ4´q¬ß6ý+HŽ"Çl§þÜ]æ1„ZÐÇâ`™&8 E¾Í¿ö,Úó‰Z×ö,ŒœÀÿ‹s¸?óµiCþUäþ_ü.e9Ku@ðCêr//þ!ö–šÏ|–û- ö§ößùý™Jâîjx÷ŸéRþ„ÞÏG_¶ßî;„9¬ÓYdvQ\ïñ 4]³ªe Ñ)‘m+ÌŸ!xcÞù·Hã‚oµ@<«ó¹ïÇ¿€ˆ’š!øüÝu;œ…bÏ!Ìnóé0OXbWX³º}¿{ ¹û.Ÿ{yý÷s@¨ƒ­›~Ï>©Þí¨Û­ùMŸgO¢‘J*a½íݬ+L‹®CºC` ë$¬;ÇyÊ Mûp@ÖŽõcZÚ!8j îà3´-Ø× ko vÜ w”Àù‹Á)ߥ è \Z‰žŒXÄÿcßeëœßm"ÇC»–`8ÐN$£ƒálÒ»’lÀ¾V!¯ArܺÍKŽ]7u=ÃÞ!°P·Î Ø¡n]„Ph¨̺dW¦KÃR’“\ªàzWR`ÉÄm3˰÷ž"édâªîJ+·ó«ö­M³QQÂz$ÓUÕíWoèCáÕ*_AI…VGè×ê*rßÓk¡M€½PI“H\DAɸÎ;«TF$œ®ö1•%¼³c@ð}hyµ+•Ó¡åî)9Ánî-›J1Ò²Ù÷}@0”#N©ÈŸ½µÒ¾.@Πvià‘Eq1I[ÝSd¢XÇÓ[à)‰ê* 7(½µÒn¬çöüP[{ò†NK…Û?B'¥ÉH„ù ‚í5¾>h|[–õ­ì+9JjŽnÓo÷¼|CåÜ‹3R–yõàœ¼MjöšEñmR‘Ç®¸ð–KžÂ\šu@\šm@\šc@<ªFÊIß|ë#N{ÞxÞ}£Š<ÞÛ0ÆÕ‡y¼³nW‘ä¬×nÖ%öëúÀé’æq|pÂ}´±-þ¨…Vd)ƒs~|eR+Æ‘ZÉ_ÉíøJvóQà¹õjý*2Âã½Þ¦ENÇ€m«È¾F@Ð7r k½`D<Ì|߂Է/·yïÿÜSiùv³^ÈD8v„ÀñÝS$Í× +(JáÞÞsó*¬¬Å¨Ø'¿¹ËÇãs³áØj[L×#®u×}N1"²»2s³~ 4EªP[íÕ……Ý4C›€ð §ötX´è¶™—P7„ƒña>4MÙ:P¡ÑÔúe> ñU%©:-åCÝw1‡ù¸¹ù€¢àÁww—ñµÌGû£ßϵ|A=‡û˜¼¾œ%ú¿¨…'i»P1W•£Äб×üŸ5tÑúÁÞ :Ëi>p{žêŒ%øÀ›€`ÈiéøÀuÆ0¯×7œR:#ëI¸SJgd= wJ錓§°j$ vÿNó2í"&ººâ÷û³þ§=ïã‚"±Öa¿ä©µõÁñ¤U@ðD¸¾õ- ûù IïŸqºÿÛ“EH,eyù.Xñuä5ÿ_œf3¯õÓé ¿‘a¤š¼‘Ý:Íÿ?_×¶ô ‹_)Áp¹÷ûWý¯`Núab¢ÆhíÓ¯2è Îpߥx†™énÉÆA­{§Š«¨P¬BzoO¬¢B± y&»Ó«âÄ“‰aVúè»*Oˆ3³Ué’Uï‰W¡±Õ·ù.sT÷´A9³=­3Û«C£o×B‘05­U"UŠýäÓ|0+EPŸƒ={j^ßéò» B„9éþ;¼ 'íIX‘x|‹¶´'>‡H}Z‰]q§Ez¡FDü§mýW´?ØŠÌ$¼9‡»ä¬lÔæ¥¿ ÁøMxJ¨êÜ[WÜŽ\ô°# ¶®C™œølˆHÖž±æ)“ÝÊ¶û§¸¸·~¦$¿×ix–ãYP7}bÝTzôk/{»~¿}éÃWP¶2#ûp+/oD¨°²j¶ÊªC豨tvO Ä$¿Tô+nŸòm<ÈùPŸ·(8%¯A—p;’„™ë¢­c3×+d-ˤ²0Õ¥~’êV[%x…„œ¯gñ¬îß«9¾¢m ïÝž‰‚òä Ê+DÓž†v'\ñ’}Dz8sY·—ùÌUŠ–„Ù6<<û»nÖe÷ç@¨ÚÒ3!÷û;ÑÙHJëû\+ÜEr»„é!BÜw> Äõíy{•BO}ïæ–f}û²FÄ!_Ûoî’&Q7(Ý'S¾3¦‡ý}O¢.Ü*`þŠûãïwÙwÆ8ļÒÜÅß„t¥®®f2MiŸóq’ÎÒ— G¹ª9°û  ¢/Ó„o¿÷²A„88µ½¹XrVÇˈ/Í#½”Þ]R*hÜÓf¼¨{–œÉ¶µ7ÈQÈt_ÝÚ"€ëßö>q®U– Ye dªø>u[U’)/K²®2U¼{ì«©Ž¿zFøÕCÐîYðf§ˆ{V‡ˆÐ=ëÖ ŸÎG$ç«û÷VÚ ¦D2÷Þת½ÔuADFú‡ÃÛÓ½÷2@Æ®ýÝ{/d!h^¼$ óG^X·öH$s¼0‘îÖäy¤ãåoÝ™CuØ/'so§þ×!BP½î  ýªôA FD˜GoP@îeÔq6ŒÝ:2®f4G8ÊÝÍ¿ ÈšÈ,R3ªFD5£‡{¹g~< ßäÑ~_—ß©×!\BwoÝ@/³Cø™å½/'î{ç\ô¿Ö{d žwé±_ί}¤aí5ò½—7Lg«Ž2\Õ¹UÊ<áÝ*á\Ÿ'l–Ü­…9'tºˆ…À³dÜ)Õu<ÊÿÙ}ÛœËù®™+ž-o=ßI_`Ý©í/ÆVÇeÀ*Þ$á·.ˆ`ï»8FD„]»8dàÊíb‡%ÿtw_¹¯ûñXßÛÚ¦Cr-„õC&¬x¬[ƒdɵz:× 'LF&ÛæZýk¤¾ÓÂÙy EÛà SÒ.€}ÑMæÙ!ÿBˆû«G1Uüë2c9.‡%s>‡e<„ Yø°WJÉæ[@XúRÛbxc:"PÜ ‚(®±ó,ZjKÇôÕJÓKʃ|‰¥–®ë‹‡!s¬ß˜cÒãPï g–•ߎë({ý{-ÎHuŽHçØ·®Ï’¬a¤ Ï’„o«’K²Fé1 ,I‡H1bsâ æ5ŒV.SªŒŽq·J®T)[v[%Wª”©\® Rå¬Â‚‹é3QÁ]rv¤»P¼<µ®ÅUr‹õÔ¨Éõ7h'£ruhÐ’F%'nÞ¶Æ#â oc)•œ#{”‡`œá=¹G3¼ò꣇xÌ=‹àã±ÊC?ƒ6o1K­….•$Ô*eP'H%iD'ÈC0:A‚uý*ÉxΟùUÀ]v{å9*É9V`»C$Tö¼ìd•Éð<ç ‹Ãc{ͪV©Œ”ü^IÖ3P~Šè5ˆ8™¶} }û*´åê‚€·ÎW¬j°²TyÂÆcÌl®ÚT¬èŠSìmWe•g¤=W·t¶p—œ´çZÔvçá®n÷†o?|†ÚV5"Ùýc3âzÿ{Ž0çò<ÐOpÖZŸûôé½qdtžÞ˜Œ¨CÖˆ`òt"È<¨C:DJwLÃ8TDI¹FÙ1 ú+j¯>¼ò òU®#¼AÁð "BÞ AÞ ÊC kÏŽÊv(yŠØQDPö:½¹/ÏÇ_éj|ð>ŽÚÂX×ÿ^$¯£Dæ“í]æ•nºÚîMµg|¢}Š©&cµS”ÜçO]зÈÛ¿°GÉÉäÚ§þlªùl2Â]R*Nþöís´ýRJ¦A­òÚýT¼º‹‡8hÇ>Šj­ù§ÂZ£¯¿RÃ0U]‰ˆì |Ñ}¦×ÓCäÞ̶šXݽø6o@\*˜ÙÓxÚñ× Bl_O;s»°GÉpu€ Úb~Q>à“ÇÞÀùY¾÷â^•DˆÝú±(pTóö»‡ ÍÈì8.æ]¼n¯ "Ò ½œÄ]-ZIÅ×¢aFIE©»5¨;¯dDwÖäPÚïT(Ç«hŸ5"ˆN•-ºP'Fß|­+Æø×2ùm7ƒRçH•ÆA[X£–®RIÄ<î’FÔªjDv!noàØ«›·Rt¶Øª4t0ÒœäB\ê±w9•s5-WåQ¿Õ[¥ ²ÏTÀ^uµÆÏpùÜ/V±Fí«‘7Òoÿ˜úæ‹Ò‡yþþßþ9ÇtµVššsŸ÷w.P+ðثNJ·Exõ¹]ÅÛl9X}bgƒ‹a8~«µ×1ˆ¤µDÁZðÖZpF¦mŽ Z|)½cjï-­ª)Í „k$õ4S V)¬*sð´)[ƒz¶Ò›{§9m%Õ¯]jJK>ó]yˆåYþùê.i冀 è +xGD}µEuvììÒ§‡iŽPl¯¤µ<3õÃ"Î|¶…k.Ãêòëš«‹ÙZÒˆRÙØµPŸRîUP+Ч”×N1€È¸oë´StPÓÚ×Å‘GX_‚ÖÀ†§•s6xcêàÂPcËuÌè=rËÌ+Ùpy/³AŸOaÏ„íø¿NÃ÷a» õV)ZcPˆë/Ï×ýë]# ,zæ)9=¯VLŸÏ”ÝÐçÑÃÏæµÇ’ôb©[¹xHÚ*±¦Y’ ò9õYð|NøƒÎ‚·+³³RŸùÞ¨¬ês±+«AWVë)¸KJéœÚîŽÞfzõfRvw|]w‡CÐZC "6¶SAª†Ã|9çÕðôIË}—œçap É÷Áð°GDßeåaë³$«÷hR«Ï¼åÙè¾\`û N0ß¾(†‹»‹ç Ú¢-Mdχnøf|#"!U³¬³…Þ×ç‚®û>— ÞÖB!صòuÀ ]ãuìÕ"‰ôŽDkâf¤µWŸ;ÖÄGD0N0Ҍⷫ¤€§%MÐUr‡‘æt@;}÷Xµ™ ^·õLh¡(ö‚s逑êHG·½Krâµ¹l4®“sD›«G3o "ºzÁwÚÃŽœ¶ÖµhÍ3ۜӘNÒˆÜ%ã;lH'y„É©ˆt¾K„‡‘RÄtôa¦÷VVí„loºDlÖà¾ý+Ëßè!hŽ=üé‰?­Á·EÒÿ‹3s”´Ø¶Ú?«M£Ÿçï»æ]Ûó‹N#'‹®‘EL{DÐ'‹ªC}²€wšf{ž-ŒôÛ‹[ù¶ûmTVQ•£‡ðO|ËʾœønD[[¥hÇ}Ï{ös* "Ò@öÝßb‡ÈKãß%LãLãëLGÒø5"Âïó=õÕtÿ.ˆüi‚·ãÈÏi¶‚qqˆÐúäæDKŒKÔé<áÓN0_ò ¥ûº |œ‘‡¦Åtņ}9ß‚èÂà<£‚©¶œ¾°åÔyÊ&Ø·^Ý«y·¬!h‘Aûõsɼf{Š}nýȹ ·­Çsš–†–EZFÚ!ü” |×n×ä#}½£m™G#}òè ë˜GŸô[Ë/[k¹C¤Qkݤˆì "˜½Á "¡È<à ¯±øúûmî·jj_?È”mû…‚¶É‘»v[¸KI+ÀH%ŸV€D®”‘T/Œ#òµ",&-;²+&i©iû”­˜¤åÎ{}Áï«/¸ÞS‰|û,œTîFøÐ>õñÐlï¢Î¼H)Ì}%ØãH¢iÅ´-1î’Ð)ç¦njK£Ð*¥P?m×ý~îixr‰˜ç·ëô)"jï¢ÏŒ‘ÇJÖZpD`g䡵`û EUë„Ó…dŽN#ÅÁˆézºÅÎ:eÅA]rœõ]“㼨ïšgD}»MJY{¢¾Gz ¼Óï2´¥» C¢©–Æ>øƒx!\ÛÈ–œN'6 ¶ÉàqŽóu!"‰m@$‘Ävc)M%_Û+B„çÛM6|FdÙð‚´Øè`yÄb£FÓ¶7""9ˆf¬¶­3"fÛZ#"´m5›mëŠHÒ°÷[1¾á.!Ý%êæ•†]"ˆÇ¦-›’mèoà:ŸÖZKú«†g½¬ë3" é¹V·úõêqDÄ¡•ºX W;‘tî†öþ½zwI©,‹m.ž‚=½vn‚“S…3ÐŒH"bjt”o.­Îïc˜wä‹E„íØžlø¯FDhWV]‹¶—–Ì‘Ðb70Òœ§rÕ‚"¾-¡pFD…î.’md«à_?«ÆC0òQ#"ŒADz4áxC3íŒà›i»É BÐrköÛŠSÄâË^C°¤Uˆ V„ c)@ˆˆA5 ’áÔΑFdß`¤YDö­F“•„qä‘v@H¶ùk„•NHÖ,׿¥f„âg6¬ÉBE„¿¡#dÑŒð—w„Ì*´‘ìþ<ÏÝ–óœ}–ä‘ ·ãHDÄ„cDÑ‚èòc3‚'X1-ªñ •Co©ÖÙÐP·Še͈œ—õªì¼MÂ|Ð*•6‚TÚŒPü̆¯ï‹u á.:Ò`Ø#‚i04ˆ` ;D¤t6Ð"Ò•qn¶ŒóŒ8G2Î"èuÌÝEðþÞ>KYa`uHS6vèaÛ[&6 ö»¤9iKQs÷„ÂÂíÈM]^æøãg9-awmŸúˆÐÀk>b·…‹‚¥âÇçcvJpüò뮈8Èh6æVãÝÍ/`â~«kQ¸l Táåë—Å­xÃÉÂ#òù­öשx™wƒˆ°¿½¶Eq…¼”gvéåƒ>mõ| £w”–¡/§#24 "D@_hËéS”0oÕ‰n¥~Cy¹ Bï¯çõýFÄ1_¸Š̈˜ÁˆRd׊¬ª:[¹˜NqY…vÍ*¨„Üo·ÊêŒHyòŠ»FJ L­âØ3"‹ˆcwˆuÒð˜úÎÊ̈°Yrlæöü^áOV‡fIKk­?Å÷ §F•‡•U9VCQ=ý»¤¡µ†y?Óð@„¥×þ‹õ¹_ݵÏ×ÓGN®…uR’êd‚•ÎxA­t#¬…JŸe5Öp_7_0ÛS;cáŧîä¹´w?DädìÈJ±Ü.¤4ŸrsN³¢¡.«Yš¶ïíZ¨ÏaÎÀ͹ëåkò^t³èÿÏ×µ%=ªëÜ©üCÀ7.çýìª=¾ „@ÑÿX2ØË]ýÐU½ÊÁwYZZj—ûŒ^ü‚û–úµÛñÞý>!¼äûWSN¯÷g°÷•„ò/cßt8·?¼’vÁ¸<øV/N&òõïj‹àç×k»¾^6D¸”"dHÊæ¾KÙ¬’²v)› áKÙÜw)› AHÙt!ç¶‘Òòê¸‚ŠŒNÄÝPÄ’$f‹àá0ŽXA¥ÆnžÞ¢ ’F¾ Ü„,\¨²Û VóKi£ÿ£«šN)–x§6Z¯ï»¼ZVtCl©\•ñ ¿q(K¸+Y"Žç‡Ûô–¹QÀöB„:ÚTâc»¼)þŠñÌs©ëû9"¢‰yªÙÄÓç{O,‚O[„px(ÈÆú?#XE°ˆàûU•]ÓY„[º­­ê56Ÿc, 3¼Ëúo°èÙ±üãë”1Ïv03×7ï¿ç…%‡è½¶Ö©äåsÆÙ÷Ka,©­ ,X–Ö:îJ(˜´þÓÒ „ï™Ð>|ô]„t &é7rûho7³>¨XÒ²Œ}oVxWáú†¾ÝþžØ—@#Úõo?XD€u³¾€ážcŒ‘礣¯‘Jƒ_qECOC؆ŒH? R± a Îq*ü«…{fÓ[ÏSƒ¶Ãõskè fNú¤ûêJÍ©q"$ ÌБE¼ ØÛŸ®³"²ŠmМÞgŽ*‡ ¬è g‘"e° 9){[Q¤l¶ˆÐ+ÙØ+‚’iÖVô–Ó…FÌiÉUHø eŠ4eEäTüV«Å[„Ö{îñ«¿Osòsy((0Û”%]m¿”6Œ)Û^i° =b §µ!x8"óRk¬ÆóT$)ßÎ"xXÒÆT0záZ<äÝÀ·z‰ß!¨4Îq™/ÁƒïlðÔDð=7àÝ d$r†} ¯]nE¤´0Üðg„0\g¡¨èˆQQF$6âZÇ/%K™¸sâsÿþ³ûסDñ¢^ÌI(<ø×Ëa»£lBáñ[>Ʀ3ˆýž»š×kÛ^ú®n,Búb£>“{çWT Xî Šå®Fq%k³÷å1'ÀÓ°˜Þl¾ß¡ýÜW|ß²c‰:[ð¤+»oõSöÊ&\~¯æmé{ám[—ßosé,B„w%""ïýÑA„%upÏÉ”Œ«Ïhã†.M’7¶‘G¢Õ³EÒ>ØFŒq•Ðò„hå(*gÄpiWÈ¿À:=f?^À3¼€™¢ÅK1ÒÌè8Ð8 íà–1;Â_ÉNv2–ãÖŠ\° UDvïJUœâû(ƒ·1wXšD˜;âìuÚÄnV‹ˆÝ¼-"œâóâI>š’¼ …%yWÄ1Öx5-Q@– úÂyI#%¬qöS¢„õÍ”°Þ<à_7±–…®†]èjCshÞx®§'ö eÊâž;Æ_Ž,Wƒ8òµ§%¬1*2² ~®)½NÅÄæìJ žJoô!Â%Ù`^2²U²ÞƒEø1ÝÆ}5s,B…z'x%å-å{‡s=Ï#ñJèm‘Dò‘‘ÜY„ðc|[ߊ r¼'“Ç·!™hm~. #ï{ßzœ÷¢ z¿\ÇÕŽþ=-‚‡ß·°£ éËYX™"\c…"eŠ OkCø2E¯uWNÍügÁ3y@Kšö› vôo^¸v^Þ—‹™Û<è ü€7^E^É·m%óc&†·’;‹ðWò×®dƒA!çÛ`´óâ x@„¹}}„ð¢o¯yiLô{¥®LDân£oÜ+uµEßþöèß}Á§ÈÙ #g<áãßœÚ<ô©mÆT’wßã kýu¹//ÈŸ[ñô¦þöëÙ€ë”[ó^Hò®¿7²²¸õ8â@ίœÊAßÇ_3ãß TøÝð„Ç¥Åo½ÝžÏ[žoÎåIe¤F’ê~mî]¹þä×_‰RœBx­CòúÕBž<Î×ï£j.¡Îþäy«Dö8÷‘í§%î[]ô`ýÔâ1צÿt‰Á¹ðË0c†nÓÿuÀª0@ôx~„f­sï; g³] à:qÆOEcáݰ~G¹o!N}Y-v´>9óýAx®×í4 uo{. )Ð~§ešz§¼´¯ ÊN^Z­˜²ÎK±—„ý×2fº_ÿj¯W±ÌCÀ¨×íºjŸÁOÒ×z}Ì8ûy$'ÑAð“Åw¹ßÑþØãbøÆÓ;¿çe,!«•³Ô?é¶ Ì##œù,Wãa]Z“ È÷øœ¿n1qnóøÌ¼à[¬½•·ñ;Ê/.x`á¾-" "A0ˆ:‹ Do‹ D³Eø ¢Î2ˆ " Øë¨!¸H‚½…ˆ&΋`þËÖØwéž=pá¸ðÙr“ ÇT02¢ÙàΦ²°6 Ìqˆ{þBSñÁ~°/¤4æx¯ˆ”ŒÌæK³;]®Ë„~).rÒ‚mðö°ùQ®Û9¬ÈCìàX°"f„8¬È) vŸý"äUXç¶é.ð6å”läÎâÇèŠåIïŒ*.yˆQÕYF?EW\FÕ`ÖºhŒ‚ÌåwAvw‹ayì°?Üsò8ê®ÍY¾Ü-†õï¡\…‰ðr)è/î[«¤w”h×?f<Ò°ˆ»Fà]éDWœ(±ÎžßæKe( j' Èµ!ø!R7Ë2ÞÆ÷‹T¡Ìéös¿UÍ»±÷®Ä¨×õV^~BxjZ´|üiÔ¨jµFœAiz{TMõQ5ŸÔÖ6FÕGK/XÏ-ŒºWØëÈÀ6¥wa<1œ6DXÄ¿C’QóWPªHUž'žüiJyÏÇ×zšYΔæÁt7ÁÃ<”·Eˆ Ûm©´ˆða`f Ép°c¤È‹GAoÏE¨œ˜"DȺ qùá Ç+þT¡g­‹¿·Eð0f?SÄnØ<;êKâ/ø®ÌÒ…‚ñ—ÎAœóJWwÂ÷ó;7²“ïqöJ""x%{‹ ¼’N"<·8û]†ù }!•Ò6=N—CÒJ€à”Õ·i.‚³?¯ÛoÓúâXêÛdCæëò„àeBŒª7ØëBÈP1_í3˜Q­@Ÿ£«pY ÔeÛAå2îvÅ”nWLŽïó¬˜â ¸“‡weWuOˆñ qR€%›ùöš ˜Í†àç »ïß剈ìÔ†®E¡Û˜ÿñr¶y9Û›Úæ G_Ê-¹Õm%·ÖA§™È ’ѯy´rhå§ý«Íq´ú ·Ž¯ÏµúºÝêRïývñ“Šb§?Ÿ~A¨[¬sï—©‡Øšð â ¡[¿´®_|g ™…£oËmyá:•Yˆq÷í—ë½>!ÂÜsìKöè7ЀãQsg3Y%‘3¹³Ë©iŒÏàq°¤…¯üdÔ÷õÝ`,GÅ#yˆˆpXñn ™å[ž–P*ĆúZ^Ÿ8úl(¼÷/\F•aC ªâÅžU"T¤Äe}‰½MqÔÃy'ºà+戔Ê;ÙtDJåÌ&P¤É©T¯Þ·—×Ô¢f—H™Ÿå V_;Ow³Öþº£”¦ý0Ý-锓ï((Ô¼"í!yã—ùR°_P»T¤¤e`<Î"âsDŽ¢H#/>ó¥ôÛˆ‚ð¾÷L A2Ë·œ3áû ÍùQ×½g‘ñˆ× FÌó½ ø+ÁÜ{­Cò€"©+B…x[†ýƒ¿r>xŽ· 1Sç¡»‚j3ŸnmË[3 ‚´>ÇÆ|‡ fùZ¶¾(²[¿·îÝ/¯ºjoÍÛÈCº´¦æÎ˹7¬Ó¶šÐû%š3±™°ˆw´¼÷± ™ý24û}™PÊ‚›ßR&‘¬Åi¤·8™7·Ö’î "§wäWÊcéóƒ uðÖ§eѯ?ˆ`^y:³~YJ@D,6ì-£-6äI&éx%X°’)º/~iÉŠ‡õÁ2oÄ? ør¤«a-i(ü4ßQ„,éÁZÒ’!KzÀ îÁ"D8mp²&F™±’³H&ô–s:t%%?e@˜5ö2Êq’‹Hä¿ôœë|˜Wù€â¤+"hõX§<<¦V¹Eò"ø~~—ûîJÉóð[]ûèì‹W“«jЦûû^/ÍÓ"x8ËÇ4r‹5.EBÜ„wC FŸR¸³}ï—Û•Ÿ¤Î"è ÝÎüJ„×÷FDJE[ôZK‘E"‰³E„½,f"xÐÊÁUX$Á8aýš–gß{E£s£Ö3÷øâ¨PdfýC²á3YÇ¿ƒÑmÜ^€à¡<œöo©ª屮gêLGƒoÓüÈ-¾`o—Ëýúø¸mˆ“%mG½H#72ŽXº‘§gyºËÓ"¸ç †èl‘wérŽjâ_T—E9t_T’DNÜŒx7l'®J|½÷Å÷ØÉØFXi`û_œ uÌÏ>ø¤Ñ㬒4\uøz¿.àRö½ïæ¾=ʲ¬ªá uæ*¬½íWÓ¢ƒ}«œ—øé”šqLs*‹bY ú¦üœÄ­:vÕŽwØûʾæÏmàÌ9^…cžÅ8bž…J"þ °•_nÓ«^ ÄÖ Ž:ä4c$@±c…K';®}ƒ-¥˜¯ÑmvöôXjØ ÊQžtrßÚïÔN7ÓÛŒP‘x Å“°/çµùr+¨[¬EÍ å×l;pŒ · "pωș ÷‹:½³]+~E2â~ÙêШý½G$ôw¼×³æþøbaMggKùè‹T~6ú¶ —yÀ6RÂBÙÇTf ¥·ˆ°ÒÄ£”Ì#¿‚cZ»aÓ„T*‰  í|Ógò¿<”ÛýÏãþß$Ù+í¨jBÔÞÖþùï?+ œ% 5&?c(nQÿ[Q[cU;딼qpP<€zƒrs‡(±·µNøe…áꊕå )P€’1”v½[|ý¬¿¾œ”ШÛªêPï¶+¿Cç äŠZûG{bª¬ê˧.cQêŒ_}ù>¢RDé±×»|­÷D·^ÐëudQYµ´·yõ×SÔm«Ð¨ÿþ³öúãu±¦¦I9£š°ÏÇ Æ°EÃú‹ ãÄ$ý¶¨ØTj¾šE™©ü×LåŠZ–a]9÷åî ¨©¼öƒ Må£/ë}’5•ß¾œ(r*ß.ŠœÊŸÛGr*×բȩ.SY?]9•ÃÏ…í;I¬ÙI½hÜ#uN g’à´˜µ¹¨,€Ò·¥[ÿö¥Y9y¦@‹½ƒ ž)ø»ˆ*Âß…¿¸Œø]ŒÅ¾k}¾!*‰~ýˆ#Áxìïc…(ê¬k{ç¬c2†ÚÎ:Fuð‹Mé¶Ø ZBu?ëXü¬[\yÖP©»Àê«Y‡«5òs¿+#PÛÁÃìYç¡2çÛϺÐxmÇS±QÝŽF;8ªÛ±ÃTlT·c‡ÅÅE‘ÇÎEŽª9˜ŠŽª9˜ŠŽª9Ø~ì,ùòÿ„]Ùr㺮ý%q&ÏûÝUû|‚3Y‘%’Ó‘ë|ý•L€„l®~[EÑ@Œ '˜W•wx쇟ùòLPš‘//sFa¬×ùòKPG¦_èŠÜn/ôEî­ôEn·z‡¢|‡èù;DQÌnOåEa·§r‡¢°ÛS¹C‘»C ½CIZÕr‡w‡Vz‡’´ªå%ùÑyñwˆ¢ØUÅ;”ÄUÅ;”ÄUÅ;”¸;´mZw²6=¯MçߨÕa‡¶/¾RmZ …·¹ç`ž‹@þ¹}×ÛXy÷üÑõôº|w;&xE‘‡®};Ž(ÏÌϪÖÒoijª5+™¶ßˆ’ »e´ãǸwVËìµtV¨ÃoY¸)&ô|m~cEõ]³VѦ‹)§íãoD½¼oV/AYn^g˜½çõõFPíW¡Ê í„y½œÖ_‚²Ü ó'k|:¬Û;­víQ{Á^Ÿ{8_¼¾:WëVóúêµZÊ:µÏj8ÑFI(<ÑXõ ‰N4VaÝŸèþp¢Oôu!(öDPž™=J&ÓI¿%“éXÝwžÏH&ÓI¿%“éDÉ„³ïDÉt@ù¦PõS¥ïã‰Þ¾ºskëoÔÒXïo+AqÖZ`ÆòØ~¢‚j[`7ƦŒ"àDìÒ÷:ît[7TPÓž6QQm}]¾¯ßÕ”óðzíÑ„*¿ózË6Ÿñâ¼ðzþ}¼._'Šbæõy‚jɯ•XÒ&qòk!V¹‰¼-ZDz‚õÛ¯{ƒžб~³ŒFÙjÞPímk¹š-V89ÖŠÚø¬µ¡æåxIN¾è…/σõÂwÅ/£X_ÇD| –Ý¡‰ø'l’ÆÂ[ë:Ùo²ï7É+áXíq"2Úi …·ÃiÖK´GÇjV‘ÑNËÚ#‹×)Ê3³Ç·Öé7â[ë '™VòÖ:#ýF|k‘µÇ xí‘¢±Ò}L²ÎD¿ÈëLå™Ù—û¥ßXî#ïë :“‹Òo,÷1Ê:¯3Q”çôÐ:¼`#Wéë;1h^X¯E¹ ·Ã+î‹›æ^^oI~ð€{ǼÛóDÞmoÙw{ÏË…WÁóÞôy./Œgm˜•xï|äêö¹ÏÖÉ»dé ×'Záäôh±FÇœœC40æä"‹Ñsò~ ò>rVÀNçXNaLÒ«€«šÔ£ x(?úç… n99©ÆzíŠÒÍw¨þÆÄÇEw®ž>¿ÉH¶èpÊkŸ$ÿDñ<¤*™¶{°ðãŸè~r¼”ë¿6%† š'šXøÉµ=ýÁ#’¼8/ðˆ$ÏûøªG$ya^Å#’ˆçáÁŸS¼>)H·ߎ$ÇðgŠbmQ÷I’¾¸öªëXÿ×<ÌŸO‚ÒÌ)„õR’ÆzÍq>Õ©ö¹Ï¯œ{Õñ/ò†‚s¯hîÓÑÏ4Õ³ªhîÓ ϪrŸª7Ju¬—­gUu–ó’Mõ¬ªÎ‰óÊgUuŽ·‘¯uí0/<«ª£^þÿøïŸ•²ÖX€êؽVy¯:NS¸¡@Þ«.IZÈ/¥DO Ü4¥DO H9Åå®ôÔ P\VJO- ¥$¿Z†Šd¥<æ< ­ Y)öØ Šäb<Ž…¶‚úK.FÖj•ò¢dÂõ ¼=D~cä$ÀZ½éJEÞÊ$¿1Ic—_båvZö›()B\b¿Jw¼dšQgRZIº/Þ­ëcÒJéÁ« ´•_… øWÆrœ&:U=Z‘Þ# õh¥=ŸýQôh@µ^Ñ©êÑ€²Ü¼Î0Vç•õh¥ëªz´ÒA˜êÑJ‡ƒÄ¼÷Ââùв_Ž¢x¿¬Db="Õ¶R†‹>P;M™NŠwàù2ZŽ[ÅÇ­²Ä4ò‰ib¬ô* d2Ž÷3õõ7z>Ð×õ œ^¸MD~QES0‚'°hµÊDö|MÁDN«]‰¦@âV­y¦`/lÕLæU4“øxZ}·¹XFá+j;î}\«¯CY-û:V‚Ҍ͇o‡eßÚ¼Ö ÙkåM#Q·Ç±Ê»mx·á¬ZÇë9×eÊ7%ÄÓú½üJˆ§õ=zù• B\3¨”s1ÊXQð› OTYæÝ¾Òˆ: ÚºIÝG×Ic¡ Äæ®%*¢œ×>ûÒ”íŽïþ5£Œ  a|H‰ñ!Œ,*gy?À\$&º¡ÀW«HLç1c=Êví«GD¹(Œ…å"oÎE’;É÷ˆÑSå’ô¦¡àe+ÖËËVȯطƒè÷žõ®LÄVðZŠd ^(G2ÐkF2ÊM×Ï{Þ—V_>D?Ü/I€b5y)«X`>ñöPÉÚTAôû‚¯C…NÌ€Ù%Z`0¯ E+$@½°x&‚eÏ*yù¸ˆÁõ`Q'i|xr$ÿ}ÉëP!°¶;Ñko¯D{lzù«díQðß÷ûÅiTQIÞN”¾‘÷vî‰Ô8k»¯änó^ë•Üíhy?@õÅÀ¾VÄÿƒà-~&âoŒ…~¹è‹•úUŒÒìÑ—ù[»kµpÓ’­9‘Ä[‹Ò7±·v%úDÒÜJLDŸHšÏ™¯úD2ÒX¨O$Ãdûe ;”äl?\ 9ÛWÂIñ|’—â('’ì©Á/F9`%(ÍÆða,ÖÓ¼Ö¨ˆîبÈTuÍ{š§ª›èN c¡n¢9Oó•zšuÇ¿ÛÕÓ¬;YædýKwb„¤œþ‹§9ï¶îœ Š9_(}uçå̋ˌ¸eñÀ« ;>êV_Ý%þn—S¨•ì—ƒRl¤lªRN+A—+RN+Ù/¿Q ^Œ¢i%x1Šþ¥•ãoG‰ÃhåYog•÷š«Ë¿Þ!­‚4¼CZÎÛ¹Vm[«(ûÜG‚â}î0V’¼`éhÝñчâÒœ6ûøàuךտ¦ª¥i­Åyey¯õ_ò:‚âs1`,'ÅÊo RŒ¢¬—^QÔ¶µè¡D²Ö‘?Ubrʌ›f:Ñæƒ•0J´ká7QsÝW ÊkÉ–ÑÆHz!¾0Ä÷ø˜ÇW^ㄜ@´Ê5ñv>ŽU^>cÅûˆ¿ÑKú=èÚQŸ€m¢¬Á\Š×``^IòÂâ¼øœù©f¥hÞ_xó3eŸ»–ü…Å2ÔV‹Ì céåCYh­ìy (Þó¿ÑIö#îì Äso=«ç¹jr•÷ÞäÜ!)³¾ä›h)³þŠ-eÖÏ}ÐNŒ×âz91’»íÄHžÖÇ—½üˆ²²=t!(Þ‚ßè$Í ïµ4¼CÎóvmÕ™':“KÂJ Åª=뫈Ãeç±PƒñJ 5¯Xë—H¯%/®ª<5Å3¯½¨àí𢀷Ö;ñ‹8–—¬ðˆhÖÇ—} `QüÅÇ:ù_|| M|âÏjÕ‚âÏjÕ'B'Ú ÁÈÞ;Ô¿‚¬€ÖŒä÷EYœä÷E¹D_-ÊÂàEYk¼( ñ‹Aô›Àûd ÿJQüû«*ø ëí<}Y{ÉØ—}ŒJü"ÜÖÇ—s£àvD#zïÅç¯V¯¢æ<[''ÉîÀ“½ˆ¹£¬,ÅÚpÓbmQxÓR'Ç.ÅÇò™HJÔ¶a½’‘¼°¸^I‹÷ÖKöËÏJ'+jîøE'Û Añ¾mKôßã y¢ÄÏ$å‰^‹#å‰ÎEJIòbÀûh:%yDà­5]'ù`ঙNˆ§•›f:-~ñ(9§ù:/Wa,'½V°ö¦“£óyÅëKFñÜçmº(kµAñZ-Œ•Äßk¯:éuÇ}äù¿¦zVÒ²Ot%(Þ™×KQÍzŽQVÖsF‚âõX 'éÑe½¼¤G—õ âX¸^¹ÛAñwV"µ9+_®óþï;ÏKË m9c¸ŒÆ×Ïq.¼Fkžua÷FÁXŠëZ˜J7mší¯û¥ÿºü•Æýͽ²^^¿.ã/AqÔŠO9³Ë.ž&—æBP–AÏA9Žqó‰~ѳŒ›t¬ÐF aTÄL¥u†êºþ½§³O åãËD¿x£Cl’|>`÷–Úmõû¯M 8ÀôC)ëëü²/à†D˜i×Å®w°Vùìk¥EX£~öçO¥­DÃHùÙOô)†’ò8HæÊ×åK,W)›îZ°±•"Lµ`ëîB¡gMk$Ýz‚æ'{1îÇðµ÷%0Caû…:ï°çi'&0Û`Â|­¤¦s¯æá¼iÏ2©~BhÀ>n,‡Ñ"K: ¿ÔÊ–+Ai–ÈPN"=Zð"WU¯èv«Î7Ôz:-#A™ãEî3êµÿ¸þ”mÓý}Ì#—ã—g‚ò,±Œå%ú§ž_’þH^õtÁ3$Š«ék (Ít­e8ÔJDzeþêg¸|}TKlOÓü< ØBÑýp>Ñ/u?£Åö~ ‰Ø-±}¾­ýï¾GtU»6ŸÑëér€)–¬ì—Â_à½n•¼À±ýï(òGŽwr¤/pd^``x]Ê2¨òGf+3ìý¢gy`éXA•­ŒÌVnËJ¶22/ðý´¼À‘{3õìÓöøïß$/p”_àëƾÀGûaì |„yî]z¦Ë¦ó.]ðùŠõ¾£–|­¤·K×ëatÇíÒC¤UöqcŽ=ŒÖ(c¿Óçïø £%‰z±\•G*ˆUåBP†A•«’Ú²-Ÿè]“Ökž6áHPž¥½\ *0¨ò^¦Æ…Ê/áü9~RTj(¡Ã|Þ¬Qºw²‘0mN_Æ”oŸ~ÖÃqjšéÏd/ÔŒ»Pw0îBÝÁ|CnODn·¸³ÜžˆÜ6ÄŒ‡‘p6Y…‚² cå lr?Ñ/²M':V`P(·3ª%·'"·3*1Œ»(·aU;ŽîøékÉí‰Èm€ñr›.† ·0^n`¼Ü>Àx¹}€ñrûp¹DËK¿ða8¹=¡Ü#·'”ÛãÉ$á Í?6# ¤âm€©Ø”`´e,eYúʉ ƒú„‡“Œ6i[ዼèZÚ ˜¿fÂX†w)õHJeŒi»öWçå2€}n,ÿfV½Ý0ä7bʧéw$(ÓF½A±  ,Gr9Ð/:– s (ÏRa.Ôz¢_< 3L¢ÿüì?W‚Jm²†—ÓJÇjÛ·*ÆÃâß¿™çÛ7ŸwW6…5̹ƒúcœÄa[^×Vúƒúc\[ýéêqŒixPŒkoePŒcí‰OÜHP¡ª¢ÂµÕŸëAý1®­þ\êqŒúÓÔãõ§?¨?ÆÉêÏõðQVý9ÂXõçcÕŸ#Œuª‚ÚxÙ =”fIDa¬ ;Ç/Å’€f| Ÿ}@¡fLÒòî^‘•x’Lä^‘•x’Hò£¯·x’Lä³™¬}•N\û$0§–ëí:‰¡¯·“XXËõv]ûz_á8×1 Ù!ç:>†S¯·ëøµ¯Y®ãc85‹Â1¾ÀþŽss½ç‰\o×1×ûzÇ¹Ž¹Þ×C8Îuüõž¯zUœ’‰'‚j_£±\#§äk4”eˆß§• K59”g) a,-7òJ³´¨0–¼PHŸlœÛÉ€KÔÁ;†äÏÆ¡õdQ Ê—kõ&:.£`CUo¢ã2 6Tõ&:.£`8;Ðq™Èì@çí@t©T¯ó¼«‡\o/PÒ¯óm¯]ðÚ9/Ðȯ]F9–Þv ¨¶«§¯÷Ñ󮞾ÞGßöÚõ¯]F¥6-DñÚÁªv,£îañ½výÁk0¶(›.H/:†]9ñJFéeCǰc_É•¼’_¾’#A±,áõvI~½/¥Y®Lø¢xÊõöŠwóÔëí•ìæYʲìœA9…Á¯Ú×{w”Ôëí…N7õz{Í9å'r½½æœò¹Þ^ Ì»åz{Í»yêõöšwóT§¼×¼›§:彿œò¹Þ^sNù•\o¯y£\o¯Y§üD®·×ôz7`aaLï¾O¡ Kfå&#Aé6ÙgQ\½DhZWŠâ꧸NDqõŽS\'¢¸zDZÉÑw|»*®ÞñA쪸zÇ)®+Q\½ã×(®Þ±/ÈDWïXÅu"Š«wÜ L‹0šÀd@$¢çž•(<Þs ÏJï9…g ÷œÂ3…ÇûFïBÂí_”^¶òJú(vÆ%ØK/ny%½À75ׇÀÙv³½G‚j*›óp:­‚2­,8b{ûÔ¶½ûƒííSÛöî¶·O‚ýWòAä@‡X9Ô¿Ïæ c9¢4Ë& _ô¢¦ Æ_ðr·ØG'jÀ3E±ìb¸Aîx5”f9Ma¬(1Ÿ® 'Bdªm®+Ñè‚Ю>k!qÛJ4º8ƒm%]HCrÑèBâ#U£ ‰\Tƒ-$>rQ ¶8ƒm%]HœÁ6.$þ¹%]H¬Á¶.$F£C‚Ä<µØI”fx,b'Óæ%‹J" @%8*þùXÊó•ü| e‚Dô9EÅŠVâsŠŠ­­5j™r}$(ÍRùÁ¼ŒÜàh (ÍëÊ ô E;Œ–5$‰Û‘§;ZÎm>‘§;ZA.Owtå>ÝÑñªa}º£“UÃ_‚²,íäDPŽAáÓøtãìƒôDbX†¥BoËKO$†e¢ˆ‹8ŒQ&°›ª}¾ª?9Fù| e»r·#먠w;2jùAmŠIn³O š×+)QÕ•")Ñ *EêDUg¦(žÊ/Ï>Ù©FQlÛa…IËÎ>ŠÒ,õtÞ¡d%Ÿ9úß“•Ú¥¡y•œäËGÿ{bC›+IøH^nn°O³B „b^¥ÀÊ/b^¥À½‘Ñ)pæÕJdt œyµgÚ®$œ’  Šm: ò+E9D}!(ÍÒÉÝ΄í:¹ÈHPl{ß|m§d (ÍÒÉ­¥eÓc"(ž~£‘ ½G‚b_âì­¸ö×… XÒ¹ŒåÄ31¯ÅØ]2ÊË”ë+A±®&\Õ ËÕ X]î+ey?”fIÔ`,‘j ôh@µåDÑ£Åˉ ,Cµo- Kî6”gióXJÉñÖ‰ Ø ¢:9Þ:O—×^i¹éÂHPlKË+ Œèš»¥YÒ9˜—]†óDP¬ÌÁßèdŠç‘ 4K|–Ï×8Ûb¬źq‡Äûˆr‚¥,¦z´Uâ}Dù¥¢¸ö=|1I$}`#[¡ ]u×ZÝÉîZŠÒ,ÕZž½@ 2º«•Ô£ÖåþF­Åæ?øE9ÿΗ6â}9¡å¼ œ—× £“èäÊot¬[”œ{íå–+Ai–Æ 2AõJPl£=¸CZÖ™@2é(Î î–u9œ}âÝÈU®šN&S J³¤`y%ŒH9…ûh”è7õ’+Ù@_µF‹²ÖK®d}Õ#ÞG¸ÛF¶ap½œè—Ãõ’m+\/áí¨2G¬q)º¯ bs<\U/¿A±ç ä„I²œ (Í’fÂoŒ²ü¢(v½à‹lñŸ^Š•9p¾¬–ß´‘ xRCKÉoí… ØûgÂZÙÞJ³´“0{#û&‚Ò,!¬½“é/Åêä8–—ïE±óÂõ òݦ(}8gÏÖØßOðÅrV3éÓëKɧßûùy"(]QÏÅKö;WT˜}F êµ´ßòzA ð_mЬGñ|£€ƒ¶–d©îcÝ~ã|q{@CvÍæ?g¨\¾®ÅT¿AûKr3×þ½«‚F’,K³Aó_{¬‚žœ}³sfãzÄX’ݸþCÖkÏ?Ý!hîÎóYª×šTXÚÚïa¬éÔSÔ=YÃHç¾p½aÏ¿ÿä ÞÔ_œÞ/Ÿ AéÆn¯{ìJÇ2Í:‡ÝgµT®~¹Ù¢¯/ý>ÖNw¶iÈ×A¹jwÍßPoÛê”/%27²³3R§ýù¢_¼£k+¨Ï*³µíçk/·É³OïãBQ™rà?ÿ}>íû³Ï~º¾ŒÓ:¼VµCØÓÎMÖ¿mC­óöC†ï S»QÜ>yéO?¿Óëa4]™ ¶Õ¿Míò{ºôÃJC™ ÛäÉÍ…wùÞ ÑëŸËþÙí´ãöŸ0<]×óµ#„=¶sç"ç· …ݶàß}Ó_žßnǬ¿,§ñùõrí¶ÿÞF{­}zºûhl_¦yžà2%é@æŒuI¸Lg`¶”«žŠ‚ÛXExÎa/eÈ_ô‚ˆú*"Šä8Þ‰ô…ˆtÏò’ﳇ®6Ö[y^ðE'ÎëBQwQ¤N[.¸žÃå}þ}] J7Ÿ‡åëbØ7ûƒH?_´í¬’ò ‘ ¨†ˆÂ‰f@=ˆô~¸ÎEzytß_2ŽõÇü‡*`oœb(`I¦Ña½nÙzEÀÒL£Ãì÷SXÖë.ÓèPiRlÍ4j ²i¤(Ç ²?#Aù¶ä™‡œ³¨Àžá°‘“;=+=È“ù2yj5MSžËößÿm¿òù „ØÓ¼½oŸ ]}¥›¦ªž$=åÒã&‰zJ¡(¦e€¶b–¤75®Q¿Ò´ŠƒÏÀØU¢}8ˆoðÅéý4}RTóâîõ¼p‚}¼¸Èñ±žN:–­¯9<ß­PrZÇb~€òÌ~Qõ•y±¦kÿò¶þÍ(ÔªÍ11®ªã®÷BWÕs×{¢×›‡›ÅI®·ç®÷@¯·¯÷@Qüõ¦óâ¯7½G‚â¯7ýbëzôzû¿\o:˜p½éÌS¿ZÔê¤ë}ÂcÁd» .¯wà:fï÷ó^’Aw÷Å…>±ãÊJ ’œuЉn%utEÅ §y˜¯—… tK¿šÉ¼të7‚˜!}ÜòIPy½#'ènï :’õ ®ïO?0/"èþ÷ß;Ôe±A7œO FËj({ôQšu4'WbNF'äã–SH»ý> `t$]ç„»eL¿_Þ2*¥‘ÅŽ‘3`bÀFV瞈Sû)êOQêÚOQxНíÌ*p&R×~ŠúÃS”:á)ÚÝJPìSÏGêħ¨§_dŸ¢+EŦ–_’Ft's"s’dÎÇëÌÞÃöøåÛ‘:ìþz|X’bsïF™7+nMž9êÜ+q£°ÝNnEµh­¥($Ki’'MV"MHúɽå7ßÂ7;Êu#£7ùUd¡ë¹z¥Î)×Lìþ²Û®c;í+–Ÿ:§TW‘# ·]E®“ª&XUG8ª\çßÇb£ 4qãë©;ÌulÛ=×¾¬Däú IÍh¬ø IÍ8ž êt$5ãþ¦ÍÃûGÎwŠé‚×SíH ÄÝ)œªÿÁÑ„„{»õ:ý5£¤3wÈ)¡oU=…JèU^+§<ûnï‚Y:å9eª¯‚#ÿ»×}ª¯‚#ÿ{;¿(€2ÍzÇò*Š7PF‚â ”‰ x…¢xe%¨ØÞíë%wÔs$¹áN2 D2©ÄI¦‰H&•jNw¬”«Ú£Ó =P‹æ´´Çí:NÅh¨Á8¾kóž Æ´Ó†õî™xø ç[«Ìi˻͋Ìi˻͋Ù(ÓÖïÑ (ÛÖËÝÖŽ•«UswÚ·×¾§š»ÓžÓåVrkuàt¹•ÜZX¸êrNN—[É­ÕAÖå.Åër+AñºEñº}S—›û/èƒé4§mïº\yuâöq%ï£f4˜žú®á<Ü»¨(Å|q¿Û#¾îFKöãœõhgtû]©'Ù‘D‰Ïh½C$QâÁ2,¡'@™¶þUî1m;íJõUg„.žU³2NÐ`ŠfeœP•W4+㥵[ÔÏõË¥ÚMÍ8¼û싦`"ߣ»ê˜$âQ—+š•í¤•@ÍŠ&7ܽióŒžwg• ßyOR #(èŸwÖp«º’7ÍZÖ»BÞ4k…ôòòÂXÇÇ ŠÝá6µyFÛÊY/”ä}A·9goIˆ#LcHO="ÎFÞÞ~¾œ@ØÈÞ´êT#•øV†º/M5x° Ë™p«¹“7ͱúÄDÞ4'¤²T­–¦<ê˜Wü¢>¬×Ñ{‡áGS ½wpNHƒ¬š»³Œ½}°X)YÔQ¬D8ÏkÛõäTƒ;_ÚDNŽtòâK”iß´rr\hë9= Œ8ya‰ö9‘¨î¶ôÖIîØ·v%o­gm¾•œ{¯„r¢2/¯ï0ú£&mѵzšKÙr+¿Biâ-Ók}?_~rÛçY¯ÏJ^Qïû±œh/u=­+ÁîöJ¬LÙd£M®¢]ë“ •7-tÒ™À7-p–Î^ Q^˜Àú†&òÂP†û÷ñ–&˜Q,J YMD³ †JUÍ*>(U5«ÀjVѬ‚a¬“ƒ¬` Œ† ÿ¹ßí"ïƒãl˜•È{Â°Ðø"Ú¢A²‡Š-ä›ÝÝ{, …;äÙŽì·’<¾ãJ³ó‚Ùy^‚âÌ®'øö®D¶¿^®ý5“ƒû;rÁ‡±`^þ0ÖóËësVŸ÷ª~…/¡y#ÖŒùÈ똵fÌG&/íVÁ…Ñ“´ÛÏðÅÔÉóÊ_LJœ×…¢Øæ¾Wø¢–çcn‡–±”'û$T¼]ëì…¢Üß¼ü>9¡‘ Rnxâgj5ŒůÌK:XzâS›GÃÝN‰¿Ó銿1 ¿q„>©zcåßXb4˜=Œ¥Äò ´X@ž×>t’œx²ÏÐIrâtG‚ÒÍ6Ú/ýÇ÷JP¦ÑÚt쇟‘¢,7/\ +Ê/Ë ôx Cçx/‘¡fßÞœ+@¨þ/,;~… ª~ä_ø¢Ôƒ etè"ŸtÆèVè¢Ô:÷‚û˜„6Gx·ƒêÄ•¸P”fgŸç¥”8û•¢¸þw8{¥9ùu©ô AÉ3‘IP¢”;íe)¼`Uá‹R/…r¾Zž-ô¸Õó¥Ä¶ÅeU#wîתOŽv WfŸ¤ßº\ þ¯{ÛTpë­sJ¹`¤ÞLå‹V¾iy·ƒ“$ÊèàÅF0p Cï#Ì^Ôøð} Ijß‹’F/®Î^ÒêXA<Ñ8–@ ZõÕùØ\•&Ä'JüÑ7ý~ûä:°¯mO˜(oÁ?ÿÒ¦Ãtcà¿¡î<§g5ïcRbÿ<Øí¤Ù·vNƒ’»³Áì“ÜBn-ë9…µÏç>9qíAb&'Ï Æ"zw«z&«d™“OŽà݉|áJrïÂünGÖÛ™×~º”æZ:çÝŽâs‡‹%;%(-Ž5R/`öRÆÿ2áì­Ø1¿¢±s¼^Xü9±sb»˜fïåy*È'zʨ(¶ê9ÁoLbó@©N>_y%”’×+ÏKiy½.ŶÄéa^FÒjÁÞŽJØÇâƒ‰Ê í›Ð7•çó ë‰VRÃ(ôÁÄv¾\ N4GæmYN0–”1‹ZZäý…·ÆY2EÝ MÄPFG­øZ‘ò"GÞ_¸VM!j-Ž5PÛ©çeI^v[KÍàPÿŠÚ‰-ãÅk Õoµ—O4Ì+È;”O´þË݆}Lò¹Ï³giçA䱌çÀ)4Zlo¿Ñþ…YúS~E£‘›ð€41VlvòË8YNÀX^²2ñ2Al“/Œ‰òɱ’|rV‚Òìªæßh;yUG‚b[³ÁËg•Øâv›Í—Ë4ý°^ö/÷¾h…*·ÖÊí áb½w{{Ãò"³Däp¢ó>Ú X¬u^Q8÷åµ²I^¯ŒrR÷åòÖ:%Ÿû|¢ÛØÀ>:#¯*ŒeåU½G­“õËݸ~“ZÏ€æÜ^$€ËU}ÕE>c¶¾î.Ší áÜ;ánÿjtI Ö/cùNœ×HQl !x;x¶æµF2¢×ò¹”‘åDÞGê—{àN~†ºÌØôËêsÆ·ƒò0ÿûO&ÍÞ»qï\ 7Í»CÇä õcߟ×牎eÛ²ëé0–cy˜‚ò와±¼x&–‰ ø;³â;÷*®Õ›½ÄW^>Ÿd)—çD}uÌ ÄfJp·ƒ–Ç”‘¥\^‰`% 5äàÄFV'@y6›¡æËÅäUT[.áJ$ɶBû‘oU=½0*y%ò¼ø6ÎѬ¢‘| ¨YE+¼0E—‹Nl…_ô’~òƒ¤!ã)ŒQÒåÊJ$±1¼¢©“OtžWRò¥¥×Ï=[{J#±1Y±œ¯ääó•W"yyUa,©¡þÆ¿œ{@ɳÌI¼Ïj­Eê:©¥ÜŽÔ)yöCFiùDÃ|¢á‹VþðE'ÿÆ‘ ØvWWKŠ[á}L]Ïý%£¢0{Ô}S'6Ý7©NFåߨäæf'@6ˆG8äl%eDx~k“’ñÁ™PVld•oZR¢ ’<)/iV¢‚¼ðEÉ:A‰™””3?‚ôMºÛë\)Šm6ˆ(%Ÿœ¼ö<áJÎñú´tÌ)¯„~ÔDÏÉØNÄÓAiN…[K˜ [šè•¢ì±Â¿ø5 åÚ¨õ|¾”ç´Ú_:ÖÎÇ÷ŸßÿÜÆz»eònc½lBg êÆÇ÷ûÏ u>¿åœùÏ~^žèz¥jîçßóJWµãéÃR(¦ùÃõ4öˆí‚EËËà²iÑ8qfb×q0œ’Žòõ†…Mòõγ7¤\Ἄ’Qy^l‘*üF@I=Ák$ÐûUE2’«¼\\!®ª†Éya^QzHËz‰ŠŠiÛɨüEÞ¶’UµZzŠpU%X}”­ø|àÚ['P^ æ%4uøEºd£<{‹kø“;ª½å±\'tTûÁy‘¤³»§{:ÏsŸëê`äƒÈ_~~~–lÊ6i'$r”c»³Ñ±<Ómúø$¨p@m“ÏÝÙ>ÆÜõP‘éÎvÍ}ו˜îlGTîòŸ}Á^^`Á–åzÞn]°Üä®;Êkíâ†0]* nEj›Øÿž—ù{>_(Ì4ú£¼ÕÆk³)/µñÂ\…ßòxÙtÛËrœ[nÊòßîšÂ}](wT;ÜŽ¤Â"ÓÆíýn»J»å•½åèÔ|}†^šxj}YFÒÆ a·]øßo°üK7Øð5œŽw€m”‰0%‰ON mgˆ¯%gÄ6Œ=Eéf–Ýr®†ä,?Ö„½‰õß:´ácéþÒ¡m$(v¬ÌëÑwFöðÏþý}!(Ý®súyYž ªÝ¡m¯; ʶ×kžq%Ÿ•¸apUƒØµ%Ŧ›ÌKîˆó"ÌhY¿ xK^ÊcùNÈíOWòr+Sxn¼Ü"l¥¨Ã‘¥Êþœfx"ˆúßÿ×þy?«‚ÊuaÿQŒb½?¿ã¼Jí[F½‚H¹^—××Óì7‡ž·ê×}Z{õëú3ýÌåŠXyÍ¿ñõò±žf”×åkŸÌ·×¬~?Ïþ\¦ýb8¶É¼É×M".PY¨,éþsˆ›¤P©!67ÔãpUo‚îŸï`Oؾa¹Õ¾ß/Ï(Ò§Ï÷bL? _HÁpò‚@ùBÒÉä]ËÀ+ÝÞ@ ñžïöö‚´ì‰¸áïŽØð¼a'Š2hnm‡úü–õžéýý}‚j†æ3ʱãV‚òÍÇþé<ãáñwÇ‚¼Î¥¿ "óN^¯ô7rïß8ÓyA_2h_oóÔýBìaŠy&ßTǽûá¿)”Ã×?3ˆ-zÿ¬ŶèŤ½ýBÇbZô®CnÑ (¦Eï¶lt,¶Eïe!(¶Eï•ÊýR¾þïþmýîéS»AÞë¸Ð±Ú-z¿K‹^„±-z¿éº²-zߎm·è].—ÃúS…ò )>¯‡Ñؽ_‡¹ùÆ¡]N—ár:|4w9ø÷ßÜšï a—;Xd;l,¶S?o%{›úŒJrçï|ø$þÜ\i$(͵c¹”ÐŽµXgAµ­³þ–¸ŠÖYF5¬³y"ÖYFÙvk; Áʱ­]éXž1‚ú‰ŽÀ*¶mlí ¨Ä˜6Ð!Wµ;X¼%벘âl–ž~3_¦–1r=Œf8cä8š}l9’°sœÍ2ÓU»]¦v»wMËíÞ‚Ò,O Œex𘂻7ƒ¬Ø½l¡ ìÞ·¿h…îÍW`†NÁò_c›ä¸hóT¹?Rð¢ÿ·(ˆþûž¢Xf œW”.Åô¥üD§‰oïB^ûÛÉO'T¶Oóc÷Ê3ðÕê ’ÝöqSɾç—7ð¹gT[%ÛÄ®Wb³?n¬¶t^¾kš¶Ùù'Ñù†5‚öOíUúhì?a"(ÓÒ­wó™¢ìñÜÃC3ŸWP(I>À#j|~^êþ ¹­*‰D"öÿcÐ|{²¾~ ʶPýf8?”; 2'É6ÖçøLÇòÜù:ÑߘóÕO¹ó•sÜ•¸óšET|Td?`ðšFÅGEæM›\£i–86ü/Ä1Ai·:ÑAøÐv–XI7¡â$¤eˆƒýSË·Zf1¾àµílÓ,ž)ÊâÙ_¬·Ol¯—·éýðEÇ™¨=ëQGÜDï<þþÎô7‚ŠHÞÈ=‹oBjE@EÎ….‰øhÇ"Þf?ÿÊ?úÜoΆÝDº, ËDÿxqûâ™zû"(sg°œ³Ys¾Ÿeï|Û€úxf‚ªÆ%Úy¾ôß*ëkÿ˨3¢†ËëüNPÇþÚYyz9CaþN_+¨÷ÓÓå÷€Jè<ÞV>ïÐÏøçg>x#‰ûÏíàƒ"öòµþü¹|‚â‰ûÏú_00z00Þ?¾£é6ìóçí3\GuÐÐc:ª Þiè+ÑÐcà4ôhè1púJ4ô8 } z ²†¾«¡Åkèt^¼†N×KÐÐ0^C_(Œ×Ðéò úa4^C?Ì×Ð逆þØÇõežwïfT^(ŠÓЯ(bß¿mÄ>0‰Ö˜ù×ÊŸ˜RÇVø/¥Â?%%q‡C¿‚”cç€%\’¤EÿÒ'E±þ¥+Eqþ%¨öã_š¾À¿”QŒé­‡ vF±þ¥Ì„ (Ö¿úLFŶçè}\èX çÓþ¸ÝŽáõeœÖá…ŽÕö/m?dÿÀXÿÒ+]1Ö¿4€ú °¶i½\ëŸ/Üá–OO4v0Ö¿ôví ;äF¡ÛIŸ_/XxÓ,6“ŽúÓ„G["Q*Á·dÄvôðâ$Ë7Ñ«¾òdY-øÊ“e|åýH|åɲ>¡=›ŒÏdÛ¾òþà+OVò•÷‹ñ•oo ‹õ•÷‚b}åWú¾òùà+OVö•÷XSO—"‰“Þ® JOÇû7¾ÆrxoÃ&ŒÁêJ?ˆËW+pïÈTùéɾ›ýTùéÕì[-\°)¥Ç0ÑäÛalAu]LJ‰ÞOÓM–!ª¹^{Ïí›Q† íÌË2>ü÷ÃXŽéÌÝéˆò¨l' ^®ÍDº\.3ý!£þ½G T||w ƒà†b{ ˆ¨F\gwE׵ׂ+â:ˆj÷¿E_¢ ã>ÎqDqkÿ}Ë1ñ“i\Ê·¤ùíðïúÅØÔM—õy ¨Ô’'%ŒQVµ{cÜ`—;ØMìüþwí­»Ñl_N¶çô¸GmÒëŸ?ýûk†ä ‹7”¢Ðd Q ÝÐçn(¡Õ,Òç"ª!v]Ô†òíÄŒ+¡‹BG$œs7TI‰‚b„ù©Ì+ò Ûp|#Šu¢ãª&¾mÚ¥Ž•$‚ã\|«:Õ‰$•ãJP-ÊîµPvo(%Q=Ÿáä°„·U=8Tš'8~}ÿ¸R”y¤ö߬÷Ï›KQ­”ž•œe¸”ž•œe$bɬl(+Sv/ÕNÖé§œI±¡ÜCaèjSñØm(/{ìF‚â=v+Añ;úÅGÝ@6Ô¹…¨sZ ~ˢβ˜G_cQç´âÔ¹¨sZÉê«Î Añê¯ÎÅ«sÕRç¢ÎiŪsQç´’Ô¹i9îûÀÃs«µðÀC?DµžÛµô@T«ŸÀRú ʶ#|ïOï0/Ãucö^¦x, o­ ç<2Ú°Ñû=&7e¹¬‚æ%g¼R›UÂ\KY›4ŸÊ6˜å¦Â×·¡\»>²'1ë %ª¨j/Ŭ³›Q†yºs¶¢l#…s*n© 8Û|*n)D5³„‹[ Q­Ρ¸¥Õ|üJ '¢\»ÿ(¸¥ŧpÒyñ)œ#Añ)œAñ)œ‡Um¥p.Å-U`| 'ýfÛ-uF·Ô‹\Ûöh;:ñªíèļ¸óD´mgžˆ¶£Ÿ›†•CˆríãEÛÑ5AäÑõª3|‹ÛR€¨G:ΞÐqn(%¶Y…4B;ÓjùÝn7ys^-¹Ýä†2|Kmò œLÃëü³¯ú‚¼ÎÕõf,ëþ™×gôÛv½õ×›±¢ë Ϊ±‚ëmÓV‚zt½Í×›±m×Û|p½6_`ºVï mbðpr&<«¤‰AË®+Òx®Hº&ú JsÖhÀÆsEÒK)’FT«Hz*EÒˆrmTѓ犤—R$¨V‘ôTФÕ*’^K‘4¢ZEÒk)’.«ÚqÆÓa)T»µI˜nFUoCø>›Ø×È!;òõe~&Šâù™V‚âù™.Åó3ѱX~&0þL57 577$Ôl¨Ä$Ôì¾iH¨ATÈ¿%Sç„D.qÅNydš‰+”ãWf:/Ïå­ôô7Ì'Ø­í]‡Ÿeš~èX7­âÿþ7¿ð}NfÚ³Vž&‚Jà+éz¨:Û œ–E„YÅÆŠæótí)Šu#J‹`p^Ùf Y¶>®¯?eø§óW7”eòWç©ä¯"ê1µ'ù«ˆjä¯n·óWÕ“Åan-«ž”üUDùF(x%:·uÜJ¬Dç¶Ž ODç¶Ž /Dç¶ŽM>*¡`D¹vŸë¢s['‡‚éùPð… øP0ý" 骶BÁѹƇ‚é7CðY"$”"ó1p†qB‘ÙJð±cÙ¶Æ5ÁQ²áíðÔ¢\q%!D…H” o¨$7é Ši…WÆrrk$x°Ü1|Ÿ\[ä”Xàz¡(¶b¼ôN“~R&Åy‰aÒœž„(ˤM!qú 'ß§ý Šó«¡Þç„0ézà‰tº}%!k§§c¥‡lœ=þ‰Ù8eU;.ç0\Išš7=Õâ™;š<àÄ&Z…{d0B×-Ñ*hõý=SÐ|^¦'‚2Œ¾pËæj­rC_ø—Í•ZåVw$ mòì°¹3ÕBPLï0¨_ßPNÈ-yÎ-Êó•?XM¾¡øÞ;¥šQºmžCÅü†Š’‘…B“°Ã½o¤¸oC%ÑéëEêê¦XOøª¥9טb¾cL±ì¹RÔ£)Ö¾*D¹6ª˜b¾cL±ìfù¥c=šb=á«BÔ£)v%|UˆJ-1Å|Ç™bÙ³Ó`í^ªÕóçåê' öŠË#˜H4Ø+¡ÝÚ°ÀÅõZL«‚H¼×QÇZˆ:6”á5u ªÙb{Þ}Œ0/+VßÛå˜Võ¹›VÊ!úmUÌÃõ®D¿­„©7²¨‘­¤ìcU#OÃUÓ9_PA¼ö/oë0ż«±³{'v5-l‡Ò¥…˜”­àþ˜ˆiÑ`+€Ò¥˜<[ÁZJãÕŒóÓÂÌ]rߥê}>H)Û= § œè>òyH¥‚(¦}kyŠ|bI$÷ ˜)/ì[±°QA’—ßëºAµƒ$s¹$ /™3c…»ø_Tü‰ü^Š–ãÒ”I ±/¼~B»"XÞˆŠFJh￉xüƒãcÆÕã8BðÍX«ÿÀ‚oç¾züonpœI=p“ú ~£—ùЂâùЂâùÐV‚âùÐè¼X>´áBP Ú”ùÐÅó¡Åó¡Ñ/ò|ht½x>´å°ø<ý&ˇ6ÞøÐ ŒåCè.ñ|hÝ&í07ží° |háC+0ží0·†ccª|håÔ6¬(‡V`|háC+0ÆóS,ðÕFç’Ò„äÉuÀ°WHB@ º. J·ÍæÚ‹Lh¯'ÜjˆbzmBVý†RÒìÑó•`kÀ†ÒbÚ-¨’Qs]câTŠ\ÙÉ-}Ÿ®h¤îÄ_°ÝÑÊ݉‚ÒIwWRß¾¡\;5ïJêÛÕ¨oïGbkEÇÔ·ïî5¨oG”m¡J};¢õíûXPߎ(ÏùŸOô7ÆÿŒ‰˜ÑµëÛ{Rߎ¨ÄùŸAÈFÇ[Q»–ØÓem[Q¥¾½À4—Q2%ßËûŒ:xíãQ¾Ï•›èX†Ëo;Œe[o/I“!u¹Mj‡• xj‡ Ø4™™¢lƒCh%n†Ûuä7«³„½"öZˆƒ*²a¯…8¨â_Â^#Aña/ŠâÃ^Aña/:{>ìEWâ1ì5Â^‘„½âè@'£º$pÝ" ¢Ú¥£5ç1u\â×Zède9_6ˆŠ¤_öv‰&‚Ò-¢Ìùuþø¾Ô½ý OÑËëôEP¶ù`=˜?’ÄæÐèhLi½”n&'˜¬µGæÁž0n(Ç«Èñä¥PûÇòíì—›4)Ù/IHn«Ù/‰'µ#…g)p’‰d¿¤ ž]Š/< ªUx¶ì—¸Â³…d¿¤@<$6Æð£ÜÆx$(&ÒSêWRâ÷qoñ;”æØ2Ju˜õüIQlÖs–_Š6Šb£3ÙnSw„Ñ™… øèÌ@P|tf$(>:C¿ØŠÎ 5:ƒ«ÊGgè`Bt†ÎLµËÀŠSIuŠ/+N%Õ)&8O5&¡:Íu‘® ·ˆbæ…î[ÕÞ®(î[@µ3^¾çŸ÷Œz0"ƒò†rƒòZ”¥Û™ÝÀ Œ¨ö³† ʈ²\êëå¥ä©Î3y骔ª‘—¾Ût˜—(ÛìÑRRóTËSóTd&lX‰(2a¯Õ¶"¯èªS]’žµÓ•¢šlßÏõv¨Nˆf¡B¤”@/Y"@µƒÕÈÕŠ(ÃÅfƉ l«|~žg‡J ]­Ê>²‚nɦà3P¤œï.9w­É¹JY>Ö[ÊÀ-Ô{è s^§ Úáëð5ž Ê4ÊÓÖj)+å¹"¶µZÊJyŽ ŽD%•òÜR-e¥<Ç·TKY)Ï1Á-ÕRVÊsLpSµ”U-úk…SÀRV´è¯NY.•¸pÊ×@Wµãâ)בÂT; ‚–2‡«•Å> ´ñ>¥«D Ô¡Òðà\jJÑJãsa­(E* ïœ K@)¶ÒðºÖä6ÅUî]NJJ±•†7Ƶ þÆÄ?Ê%[H©ÄyâsS±E®$jŠMÔékµ˜¨ rÕêª$g9q£Ï¸ýÆ¥˜ÖðÙÚ¥pH‘r†Çs…CÊÊy '¬ã’Wb.XÇ%1N5‰Q‘²V¶Ç•¢ZIŒkMbT¤là…IŒÊ:.‰q¨IŒª– Ü'1®5‰QÕ²ûôÄ©&1*ë¸$Æ©&1*ˇß֚Ĩ,~›j£:– Ü÷¥ÆÈ³bËnÁ T®¬g“75R«”º WTŠâ=±‘ïÏ{­_LbÆ0׉2(lªÿf„•Ô*å彇0–“ßp,Í}q ¾Eg¸‹;ߢc•÷[Û XUgå®q€rr׸… Ø k8†4§»Q êœó\6ÂTkÀ” b‰ Î+caV‰r±ØÚÓÄVå’X´œ[•KbÑ2Î+IEË'ÜÇ$$¶nD¿È&¶‚bë’˜ØÚÓ/²‰­WŠŠ\Åø®}'VüÁ}ô_ìS‚Ê+ž•¤„•Wœ¼O²×Rˆ=Éžc8ÙPÕ“ì9†“Ýp*žd¯9÷J\^¸ÛÕEáÐ#p¼ÀC*µSÛå*E5ûxWê>å W‹³Æ;Î웈òN“ünEy'ÉÎ5dqQžíϸåÝ{!hެ7ʇFÔÔß÷ùó“¢t;xxÍ}ýÅÍ_ÿä*å ßȃÉ]Ü|^|ñEf“i^™ò‚Z^òÊÕªo™j≠ç¶šˆÙ”ÀéZ̾ 5³D‚惭5º4l­Ñ… 9³o"Ñ… NÊc´¯ùÁHÑ>4òI‡¢{ê¾Í¸B#?Xi‡Êà¢À¼EE§ïÓ¾kI‡ ž Vɧ),•žP… —“æsÏæfnêoueAã«újH¼Pˆ@UHl)‰ÿDöµZk}ºŠë%N¤¨8£u"N$!ƒs¾~Ar¸ŠZ¬–}"Jéûu,Î]{{·ñ­Ž7KŠ„ŠŽu•Oó©a^¾MF }\ÁT# }‹NmaòÐÇõ÷wˆ´0¹ëãú‰}\åû¸^jWDùFIÇiOè»ÐÙ‡fáÇN¡EQ¥cÎYßeá-g}:Ì>*Ísöé|Í»ãíDg_ùõï›Â®ô“ÐÐâ¡+ìïÚ¡…É? Øa4Ól ;ý¢tŠ$¾QႪGôlC‹yøO‡}RžK 38>>R½|Û‹•x="_}^+ÆUL¬BZ+ÆUL‚H<¡ œx^(â/Kݹ~^Åfÿm¨ÂÏ«hsŒûšÆš|’4¯|Ô䓤Ţ_¸¼Éî€bÂ'þ$Q'Jtÿ0û’´<_‘YSz’êÄŠ)“‚È¿ÔS“F_ŒM’Ív¯¬¥; œÍUé¾ËS;(k%쯻ŽKŸjØ_w— ¿T?ž&yjw©ïC ûë®ãä‡ö×]Ç%È5쯻ŽK_kØ_×<µV ÂþšÝ7bØ9²¦»ŽK_jØ_w|™ñZäuÇ—O5ì¯ižZ+”ší:Ý=^o¤¯ß?ûÏ• t;|ðò³Ò± –ÿ ,–ía,-†e(6@Iu'¨OëJP”+M`Ô£-ÖÓf@Y.…çe²âí7–Ì8M(ìsË03Píü¦’¨fZ-ÊÔ,þ-Ô•›ï!ªmÌ#äJé΋M‰{Xû Rœ¬ÕÒáתwë.²UE5ïJwQxüðQÖ]bì”Ýk‹vŠî¸ÀMøÖª“B$ð­U'VNe­N+%VN¤PŠ¿=&Sh–C-ýé²TÓVSA´â“ík*ˆ¦9o=;šæ¼=ˆVôìheùdŠ–”áDæ4T+ ¿V[L+ÖZ^«-¦I–Ý£ˆZyÞÆÆšJTÊn>вÝmœ} ®q#ÇšvkK~…Ù“ÛqûÂöZw"ÉC.lÖZñ$/è ×Zqü¼¹m«ÅÏ;ݸÂ(ªÝÏwD­ÇÏ›ýêt^,?ïB¿Èòó AE¦ôBâš~7JjǙΫÉÏ›ÛF_1•·Ço*ÆYî$­µà¬@w’Ö¬–¿V£Ö<ÛHu1jmXçN jmyîÚâ~ÓÚI1p¿ií8‘?UûPkÏŽUíC­=¨+¡A­ƒ ¿c0Rë(:ב ÚV)zÖ$£êÁÍU•#¸¹ ƒƒ6/¯u,%ä`йfó›öLBÌoÒFóOw jcÄ2k‡†=_kujcùG¹8µ±|ãÊÒIǺQkí‘6ž÷?Çš6^d.Éö´6R£÷õχ‰ü¼J1¶6‚/£ck“„`Q¹µ2лPWñRh«ø\ñRh+)DeöVóîð’]ª­æWµŽéè¿Çú½’Q¥­¼ME´Nò6¡iþ%Ùz)ü !Km=ß”¡„,ÕÊ-[k$@Ù©ÝTs¥´ \¡ÃTs¥4冼gv.¹R€âIí‚âIí‚r ù5U‹¶Qzaðµ"É'iŨ°I즎óbü5™¡z i× eØkH»Žïû]ŠLeZ+AÞm§XOy·â9>KÐO78++Ç'ý´c8ç{Z3¬‘æ…:€³‚Š_4žœp%ošsÒÝÆ7͹voUhb’Üy±Î”dçÅ:_rÎKu¾0(ž ŽÅ3¡ÑÙóLhÅ3¡ÑßÛ¯B1ßfÜ5«rÓ(™cƒÜ¿ÅnãBPŒ™Œ1í¯ÖwÛ%áv`n¬ö¢‹¯_ûNHòØÞÚüE¯ÄÂ6Ð`X6Á\ØÖSKMoÏ&xK!ͦ¨PPí­ÀPœnÞqN·‰8Ý_q"ùÈÛ|Ugò‘íâXS´çÜ {Yqq+þÜ×ÈŽJLG€34×5nª]ãtÐ|Jb駃´!짃n±ÄäÒÖj¶êJœH‡$ºª¤…ñ†rl¼ŒXsÁóÎÓêú ^H€(÷1ö>÷#M߸wV÷cˆ‚½]4ä${5äð¨3AÖþJ4ÑØqYû+ÑDIúÆCNxÕDc'gíÅgí/å‡:jVQ VE/ŒZ@½y=´¯¨zaÔ$Óþßc…\µt¢¹Qp%¬Ø†d¥(6~ :ytBüÛÏéèø2ÿÒ~NG×¾ÛWÚíU2¯;·èJܢѳQÛš¬££ } CŽQÈ@†#W)´’WŒ\²áD\1²®]ÏÁµOí$È+M‚Ô$§á1=“ uLBà “ uå‰j¸Êª²ù´‚I'%lr²ŽNón¸¤« Um…døT¶j+$Ó¶ ùhÉŠµ¨`+$+Ö¢âJX©m…dåäò AñÉåt^|r9EñÉåt%"W§‰(9 ¢ê‰ñûÞ4˜â9MžÕ£kˆN2ÑGOQlÎ>Š^kðû¦(PË»Û}?«Ù’6]'ÒÌ¥9¢¬šN&úx¥(–è#¯„é$¢Ô} IBh•áì5o?²á)uÖêC6ûs¼Á¼¬ÐŸù}MgÛ©’ÛJT~_CRŽü¾óTù}MÇ·º–¦Y€rl¯ Ay†Fî â AÛì¸ØëP‰!ÇÎ)\Õ®ÙD÷²¬G˜âXoûÃiŽÎö°I9½±Eg{Í>ÒN¤)ÂÇz;Ó}j¥7æú$ÜN'¨æè7çÝ`Ũ3osEõ”+Êt}« ohîÆ]Dy¾%þdTâÍ¢¢:Õñ ‚ż5J a"ŒÀ¥Er”üL¥ó–²e„°Z½åŸÅih.Â]©5¨Mƒ¥§ ÞІô=:=ȨÀ—)ö CÒ·²k²ÚjTd˜Áh³v£"Ï—\Ìn£¢ š£Ùm” ¶ö˜gT2bN§Ë… Úùb¥ðÞpM䯴ðÞ&ò™…ÚÅ4šÈS:ƒ@)‘Î`¥(–Î-­:$Â0š§ëÜn¸ñÖ¼Z1cÝÑüí¨ MŒ¶b]1ŽeÅœ¥Œå¤œ%Èð0Úq»=Uã P-#e­Æ ,Gö2Z{±Ñ…¢8’› ølÊ/̦4íî×Ð#»HrS¦È/.y ;e:AQ.j˜Q|P°Ê/JhòÐîµÈ/£ùÐa•_†83îXì.&„c¸Æ!{ tÙ4ưé äU0V¬·3Á¶íÝåýXæåÅâ¸|¯×µš·ÆîM[«sј(¤é ‘bLƒ@=4ru¬ª•««à‹,Gæ À±”ÈÐST›"¸¸l=’ß§ìãX†o3ŸfXÕ»¡¤3æPk !ÕhÕ:ô­=B•GWÈP3ÖÚÄÜUõ 'ס•GOgÈQ5µGh³òh¦¨V£‰ùwÄZs@E,Ú•ßWÉÞ]öyS éoL\¡Ða^Íþ™Ó<þþ·ÅÏ9qÿÞ)ÜS¹kÖ>òÐÓ2ex”­Ë”WŠbË”qÉœP¦\eËr ­•cÈy •cÈXÏ{«ª#äUÇz¾t½xm B>zm |I}ñÚ8lª^[Só@š¥ë(*¢Xº¢ÕJ_õ7&®D|­ÞQcW"¾Vï( ¯-zGeÛu;0NªîÁ¨€a³Eú…<ʇl‘ÇŒ+8…Ž)BéiŠqLÊ•¡Ê0Ù[P„¨"èN¹GÏ^,øúgðå#£x¢W¢Œ:# _)JsŒx ž8+–çÃù"™'1ÿjrm1¡ž"ç{9¼9ëifCã‚Ðwêýòg (Í´ÑÆ‡Ô†™üÖ+ª)ʶ{E]†ë‰ ÜµÃjèAt”Ý>ôŠBãÐ…cÙíõy@ÅÆÅáÆ¸ø}ø©Í«þ:.t¬Zv»[}¯{§¨—uþ~é§ï SÇê\lÚô;}öH· Ø7åc¡0Ód`_.—ÃúÓ¾S‡†RÏëá'8¦ÔÇ×an¾‘ˆ¾œ.$Ð!,{ôÿý73º¿!ìr‹M?Ѽ NMYxîÑ—ÒhÓ¸$±)A‰qI`@š ¹×x–×z"în¯Dæ‰WŠb™'@ÃõJ`ž(înϹ»i2ŽñZäóáCÛ„>Ðq~¢_Í® åx£žJ·I;ϨyÃ5¡œnÀ Aµë9†âÑð†kB™=å[)(•]Ãx™]Dw"(ÜÊ»ö¥÷Ü 8–;\(Š­“óÄ:¹ž¢4—hž<ÏzòVâÉó‘«'ÏGA]+ž<¹@ïJ<> mES‰îöÕû„ä¸R_e‚k'á-–ÀMã™`&b¡S&˜FBÈ/ž f%zpbâ+XèÁ‰IŽ ¤ƒç‚ÿQoI*Ñc*dQoƒüjE½ ^0yŠw7®ây"Êf\ÅóJ”Í 4Ë©Êf¬ô%¦Eˆb>ž‰ÈE[V⣠‰O^ªÊ9Mqz ´,3)Å©zÌ"i7sç'"^.Êcs/WKͰ‰šS6sk7˜—‘[»­Å·v»ßÚŽe¹„68_l'Â=¡­D¢åýÉդޖ•…ĤŽöPQ_O .ˆèÄzÚ•¢ØzZ_Ñ õ´Å!$B‘hž”Uã1ˆÅh }c‹ÑpöQ¬×FT)mWŠbË€`öIŠEý+)±€ìJQlÙ¼iÕ ”j‰NFä•Ý$±TgoÅRM\ +¤³='‰E˜¨ç$'™H^,*œ)J?´v›/{CL©¨);w¨ç*ŠÑupz¤Ä9=Vò¥Ä9=&ò¥Ä'hÕw(%.éeªÚ턘L9ѶSB<ß4Ûi± ÇÒ|RU¹¶3"ÙÒJQº)sŠeh;+PæÔ•p|¤«œ{Ûy±Ô £ç]6å>Úá‚j’@íÝ뮀ŠWâN‘äA–ïý´Ö;dùÞOk½C¶K¼ÝQd´U˜b»­:Aæ”S¨8¾äÝÂ?õøEÍ—ÒMÈ^l•æ‹ÈKÎ*žvŠÜ¡»~M÷íþr²—UBÃú’ìe•ã’½Öšìe•ã’½†šì¨vÃú’ì(Ƕ¼ŸìEÇb“½cñÉ^t%ød¯‘®*Ÿìu€ñÉ^t]…d¯ÃVòÉ^‡Ñød¯ÃÜød/ºj˜ìõ˜CŽÛ饬ârá‚ÈU°RT‹¤qºõׄ‰ñjØ­¿æBPlæ4.YÓ¥à7j9Ù ÆÒªížë¡í óc'†J· ª¾À=(Ó&6ºžŠ"™ÓçW8þýëçü•M˦ÆärvÚŠ9ä3E=ª;ý3édkµ“öp,PŠJ,eß?®óõåOF1i÷1røk%À·:Éø+Ai.P\ ¤³ J‰„î Ðæ´ ‰¥)(waýJbcI ʑĦ+‰  l»sAåÃè6‰MOIlőر ¤Kbg5£X›+};`_IlÆ’Ød·Â8vAgŒ(Â@¿5FlïïK ²·wû*cY†zñ:¬û¢Šk޲ûF¦ËÓ/AÝÆúý—¶é‡×Ͳø¢cqùPo×h¾žp“Ü1'äöìÞîÚ¶ ó|Ê53¦ŒµXãùŒ©[Æ-A5÷*=1­aK£†Ï?¶4jØyþŠjtá¼]Ià(·F;;P>‡¶“¸ì€uߒ̤G&«y}Í*ž­kDi[3“žŸÏþ vÈjŽ9yÿ"t<°Öˆ_„}´†y>.»yŽÏ‡•ú?Ó£µŽ§"Ù©[.Õîw»óŠÃzy¾É/lØšÎòÏÿ'úö7ϧŒ*'§‰ºö˜|¯}!Fð Z›xiò… ­M|‘þN3”W Í"÷ž:Aµúð®5öicŸ3E±9¦ˆÒbŽéÕ,]ÙÛÎ…ë„ü¸ÓiÎ!jKR*™o=þFÃe¾]×:T;ó­¿Î”c2Ì P¾½#$qXg™Ä‹½ /¬sBA&^XÇ7§»VeÔ9®%üT/e¹‡+ý¢c¦œ (®%üÛH瘄„a¤_ŒM³nZŸŠJ-]¡æàªvy7ØåvS)~ÿ»öÖ¿½Þfvú3 ËaþJ·Ó…‹Â5Ê0°©:ÙðÀ!î=DG‚ÒL+œrqOÈ»n׈¢¸ Ñꤢ×7¼¸LÑ=ásï!J¿øØC4£†*¶y3ž/8ûÈg&íw’¢Z"lÙûÀ–ïâƒÆZöÞmÓ… l»ø 8Q\ä 2ÇBP¾ÍuŽÍw¬²Û|oÓ]슦¨<$f\Qñð‚ⱨ'‚bY‹À*òšg-ªV‘לB´«ÈsVÑ<«Èkv‡*µ' Ë€DçÅS{ÅS{Ò/òÔžtö<µ'ýb“Ús!V‘ÿ‹Utø¦Ò­f{h4`1«çŠ:¤·âáÁ™ E¬Õ•äЕ­¼¸Þ eÆETp;;ªŠ ÏUÔlw£Š B±s׿q"¢‚Pì<Ì~Â.@9¶dy!(ßôba••õA®,€ß¹Ê‚©VX’¯Ó¬, Š­,éX|eÁJP\eÁÐÓÙó•ô‹¡Ñ„„Tê±²` •€â+ èì…Ê‚Ãâ?V ´²aº¡ .D_ðI"Ñ'>™°*ˆ>q â@DŸd‘ŽÅ*ˆ(“¬ ÒÙó "‹W)ª¥ DA„Um)ˆQÆ(ˆ*ˆãdúœB'Ê:8¡“Ï(j¶ZÃ¥|ýºJKv)Jך‡–­ý×—gôŽg1É0k(ÁÐÆ®ÕÊ-v‰¶QðBìrÆ'0x±1ü;|1ˆás‹‚Ød]Bcøëi¡(ÛT×¶‡W‚íºå)$žÆ¥*O”ÒêNžå)$Î¥¼å)$6FH\Ê!q.å•(O!É.e:ïR¾ïR¦_ä]Ê#]Õ–¤ˆòÒ_\Êô›Šé3)Ñ6rš÷<Õ”hÛL·Ã±0%Ú’t»»Ž2cM‰¶•Qì1:PR¢-ekyS”o·½žñ7*¾gýÞÅj%(¶S;,kÔ"ã&ž¨åh@¹š¢n௠:ž£m«X=mTgiºÝc£º^#’nw§b­û]éXl£:pÉD'6ª;Œõب®§êÅ5ªë/A1ê®Ð¨Pl£ºÃì[êö¹§•®*ר®_é²òêf:3¾QÝÆ6ªëé/h6ª[ötŽÃðêŽ0ß&X*y2Ñ‹TyŠjSåÕXI ý\7+„ ‚îHŠM¾^Þ®ÛB¬ŠŒJm6QYp>Ȱ§õs¦ÓçÎÒݯÇaõU³ß# /%+—Ö-¥¹æïàMNlþŽcAûAü™Ö_˜×ƒ'¯äðóú:Pºe„ì©ä¸bžÏð™úG‰4‘ýçîmþ^ʆûÃ;aÈq§{¸^¯sOPþX§ºÛÕ›ôÚÎìóHPäm†±¶W·ß‹õ‰ âÝ¡îñŸèX÷Õ¬=$ñàL¤‰ììÖõã:S˜:½î²âe3^_6K‘þJE¢ÚoÐòñòsú¹ô/f†îÍKò<ÿùüZ„Õ«W„õóžÆ—H"Ì¡aÛ§ý›»à¿üùWÐ_Sm"[ÿžO—çËr€ê‘€ŸÐŸ–Ëï…ž •ÿ[ýÛÎì¸Òƒ¦Šçâéõ ÙÍ´y{ƒ,18µuI@på4_.oÃöêѨøŒ¦J'“ZŸÑÎH¯Ì¯Ñ¨$G£PœIѨù î3×iž`¬DÜ\gÄþ¼WŠÒíro ;8žÓsªawàô<„†vp NO; 5ìàxNϵ†åôl•Ž/å¹³:üœØTÏ„g)ú҅‘"ˆ;át.]a\ÇfŠ•Ø$±[¿ª%ÇÓ;.{³lüA Ã¬''ð¶ÑËpþ…}äoGÿ…ý8\í ygƒün×m@f% ×Äé$®ž‰ô`QÇ H&Ó±áï½X N´éŠÂ©K^QÓñEáÓ”Êr}9áÝ6J$îX)ŠíDçÞH~q¤evF M–‹öh¸„Ž[—{Ôáb+Ñ GÓ’»Üà c ^ªÚ£1¬nB´GcØì©[/:ØG+ö˜Â/Z±•ya¤ŠÂ•àÒcÖ+®óR4®•é•:ˆ=ÛÊ”:ˆ}׉:S–&¾“é0_Ò³¼ˆÛݾ $÷T‹$ßñL5•±ÃwF ×¾³âXý@PšëU•ï£ïœÈŽŽ+áŶ»ã@PšãÕÇ•"¯þûDP,¯~¿ëÎ@Y޵c”‚? =zž‰17T’θ(¼šóŽèøñŽÅÇ.ùÝöR‡Ì¢Yy¥øðINp¯´ÐY±?ÁJÜ%4Ü÷Ђ•PF(§ÁBv¯xÛj—…¸r§@¸ÛJìX¾èøT… R˜y%V¸-¸^è_†ºœWApü`^µ'i­¼ê+Ei&Ë\:¾vÛ,ùËYüîVùðv˶Ü0—·é§ŸÊqLJ±|˽2î2E…oâtŠLÊIA  Ëëî…¤ê’öº5wX ­8Fó寳(©fƒý^Kl¦èFöÚˆÝ ®¥9þz\ +ò×Ã+ª%Ën^;énãË'¥P ˜šæµÄ¼‹š•×2óî²”f@ð¬ê(%•ßȦ¦­55Í›NjЩiÞt‚–6ƒÆç’úUNÛ¼ Îj+ ¡´%C{ȹÏ~Qìsš¨7FèDRçe…Æqhzc…pS‘«Æñ–a_wHÐ`J`×Y†3ad=ÞDþúÆŠ’'‚xÞDñ>Â2Br±æ¼íÄÙšó¶; Àìm't@kP–ëçË*±wÈB«ÅÞ8/–¿l­© Þþ…¿ìBP<ÙDP<ý"Ë_6ѱxþ2:–ç(‚ØmååŒAž‰ï]kš®·Nìvþ]«eè­,ébwØ ö¢»Ã±óÎ+Šp^Qì|€óJ’7m–)‰½ëÄÎWŠb;<à‘ªV€S‹Ú÷çÂ'1/KaõÎH•‡PóÍ€síÁ çËY±KìåÚ;ø6I>ÎÀøèç<ºCéxÇwת1ï‚ØË΄“:oK|?œ}^ù7z‰==5€b;<ÁªzÅ¿ÛUðJà¦(^ ¯=Óa½×¼nRR­¼ºšÔÙ="Ç™b?zÁ#RˆÐ¼·¢^˜ãÞ;–u‰ø`¼W´ïÅž ɽÜãtX"v¢ßû(öòÀ“%¢!<÷Bx B'tR*Þ‚Ð 4òEF%vé€Ù%vé€û´Ø% ÞŽ ÅÎ £ƒ;k\)ªYn[J½ÀÀ³ÝŠ4 NºxkƒoŽå¿o‘¾!ˆ=Ypí£”V~ce4ÜÚØ‰2¤\ìÄ®&°|o%–tTBÄ üÆ»þg÷’î¶DiR²?|ºþb¿%-OÎ_õè(r7áÝŽ^ì;w;zÑb…×=ÑbÅ 2ÿ5Ì‹Ë-¸LB‚IìÝÒ7u¼¨/LbKu¦Jãilî‘(r}<‰ÍµˆbrÆ×Ø\“(v;)‘(f¦_|$ŠÙ;b¢@qD1¨Ë%%Åôø%%ÅfŸö¿áDQ,Q ô3AKÓöˆ%Š9ÂX¢˜+ý¡W þN+6&Åí´R5 Šêä„¶ª%ì‘„&58’‚Øœ —? m½Š°ãC‡S}¾C׉ÝV®¥™\PxrC'¦ós1tZìt3ʈ]sp^Vìïr…y9ñÉÍç+ðµ½kݡЩ ¸B…&hF†Ž ojÅÙ2B ˜ÝÄÉ‹ýórùÍC¡Ì2Qíý¾NÃÇHPä¡yÅTЗÓÏ5¡€"ýÕß^_3Ãûë0>åê2@Y ¡ì«u[¯—õõûår¹Ò/:O·Áöél/ÈÏù%‹D@y"PPœ¾ÞÆëZ¨e¹œ_š½3å]îçþzY~>ú3éÌ¿™©äŒ‚n>æ*A\ÕCîlmçþtžé`ŠËfÇýf+«i6{àš½ÁXp‹”‘òÁ¯8–ååI½EÊIi’x»¿ûJ;47ƒšr—pePA”'=Ì+Šò¤‡s˜ÄþGðu'®W–åA+)9WUk¾Fs»µ™ $h#6ÍÁ±dõv[[iíÁ˜ Ú‰k¿Ñ±¯ÚMJçÝÖ^<«8V`ëè/%˜tl+Á×ìâ±"[sHÇJœB½Ò±’Tˆ»Mkm©.p¾ŒâõŽ’êŒœ£¨£¥T*üÆîØúEËäÞñåX–‰Új3Æäéi«Í`<r¾&0Ø Ý%JOÕL &ŠFà _L\È}.É[¡ÖU¶¨ÔÀh´®ò‘J Œ†@ë*FÃ31©«¼K2øXO3P©óP² ¦}UŸç?PÑTàôüg:/ŽJmƵO•ÚÅR©ý¹Òé7©Ô–Óûåó㊡ œ(ØŽ –¦†ÞeÅUÿ`µàs*é]'¨»üS|Ь˜ä1÷$øN3÷d"(>÷d%(&÷d‚Ü@Ù¯{Í=Ÿ{BQ¾Å×^sOÖÉ=TäVD«õRÖ8d‚„¬ñ"¦-«,¬DÕ±‘‹}¬5ölâ©oK_¦@âN÷%f;!!< 5îÔŠXU L«H«v\”åD)ñaµ‰ô±jÒŠä}I¹†¸¡ãiEJÙtJ*›ÿ{¼ÿ}-ù[€b{á,t,¶ÎJQlÙ4ȯ ¤^8è J,›>ŒÅ–MÃÅõÂYn½pèÛjÙ4ÂØ²éÃü—Hˆ*+ÛÎ$‹VÓÁˆÏŽEìÃÿþ þ¹}“nþ9|Hk0µåŸûb§S[þ¹Óeÿ„Äe‰šYÚ=ëq,ÇuXa,ÏÛ‡—z¨½hâªzÑ><Œõhî}Ç«}¼`nçp"¨–}Øoö!t gS Xûp¦_díÊ·{º`¼}x„iNÖá†N‡\k¬1„(7¥ (¾)ÅHP|SЉ ø¦t¬fSŠ…‹(7¥ ³g›RLt^|S ŠâšR,xÄâ_šRŸoJ1Pß”âã›RæÆ7¥  4¥8ÀüC4eß?^† ¢!ñÑ”ßóð>MÁß™ØhÊÏT¢)µiÑÿý“çuSpÏÛ¼Þ†ëçB¿è$ìöм½a@5¦EÉ}Äö±žæÏ7:¯@®Òèòôu½Ò•ˆÒzC=Ëñ‹‰I=F×AìDµÞ!…¸“¢:ŠbãçPSLʹ~…6ß§÷ñûÏkF‘—ÈÐ{ÜÇ˰f^òP‹Ä :^ñÓvnÆ‘ L%/íá&½~¯Óv1 ÊRŠóþvt.§?—ËøLQÛnÿn/øŽê³Š»ý¾õóu~ Êsšˆ×è¤äpŒPE1A•פ´Ü2VèŠw=&É|ðä$©`ÏWê¤4f|h’QðÎ7‚¶Nø¢‘Ù:‚âÙ:W‚âÙ:'‚²Ü¹·M²bê1ÜŽäÄÔãŠçn”—rwS ÅØ Çú§“¹›@{:t¤hp7­Å6ä¼ÒÙóÜMô‹lCÎÃXlCΙΫÅÝ4Tî¦@;R4¹›‹Ï6äìéê·Û|/P¾~Ú½@ø3ƒT P®ï•%))I™¹pqc×IŠàwŠlÊ-õŠ(-¢®€2RÎm™—Qy%bÇâ¶_¸Ì勞oÞካ@êq,ž†þR:UÆ.J•üÙˆ]d3wð¾˜øðyñçªY_|«¨¹Ö¨¤xÑTP"[üÈ¥T\i5yTš'&?mÇÆâ»;­¥»ST†óbìY…ÙøTÓ‹ý>ÿ¾æÛ (ˆ©á‹–¿C%LIø}'²ïëÇr>g”{ðæa'²ñ:ŽãJPoÞøüjï3@™¦Ÿîåýég$(ÛN«êÁO¨c¿²LpºÍk§‰ |£ÅúôùþŒk€ LŠÖ ×ÞñÞ¼£òb^1žÕ æÃMSA¨8-òKE)?|ÂÝÈýë}TIü"H݉l°CZ Í蚊ZqTè7¯?œh­ùjòÓ e!©oùó':–á|ð‡±,#™ z5j#yeÁ±IÊN³Á… øAñ (ŠMȃÝÖ¢Ãïw[tø](Îáw:|Ñr yOt,÷i·“Y–L;@ݵõb&oc-ÓëçDQ¡UmRS‰¢ö\ZÒTS‰¢z4¿¸ökb´Ç Ê=’êûVœON` =΀ó ÌYÍæîzUõ >õê¦âXIpÑ £NÒ+:gµ<šN|Ea,Ó ¯hñh:ñí)Ê2®0GcMöºÏ÷œúËÓìvMöj¹Nð|õÐ<‚x4ËìµLz»OzKQ<é-E±†Ó4OzKgÏNËLÇâIoéX<é-«i8Õè ®jËpZjôa<é-]1Å©¿@ÔßÕcØ‚òšnå2òÖšnåTé]Å/c9‰L©üH'ªø+¬˜#n’—²ZQ 0¬Ë F…‘èÔ.&^„=‘h_:ø\ :+OËãg•À¢]°eÒ n¿ãÑžu¼¤AD+ñ–4ˆh™4ˆüEHƒˆ–KƒØž¢’-“±UÓ ¢eÒ vóª¤A*0É^¨Ø&gœO+|Qðo-à‰ÖÉd$ Aµîã@ÌdëE3ÄŽõìX•:+Ú dÛ"uV$io­°þ _Œb†,Ü4ù‡t{=:–áòUgŠâH±ÞqíYR¬e?Ð=Ë?ÆØŸIŒP¡Îšóâ/ÐØ±‰wn}¡ß-ºN,DF”â“qJ!rtéíoqnqI{H‹—£Š­«#Þâ¥(N6P`•Óñ‚âÓñèXUñx}y·Â×vÑ®oY29Çõ†¹9 Þa%¼P‡Õ£ÂíüƒÂM\ø”á\Wв -^ù¢‘¿€Œ&i‚Íâaøb”‹‡G‚Ò,ÍŒ•dš‘‘ Ø4AѾÓá7úNj–IBÑ+)ƒ ¯Äfé°C^‰ÍÒc=6Kïi³t@1ÍÒ{ Ó,½‡fé€b›¥ƒéá•Ø,ä„Wb³ôŠo–ÞÓ鳎0Í[i ‡/:¦ºšåÅ ¥fyPƒƒ–òUQ-rËÑ´È-7б“Ú÷t,ßVNxkƒ‘8júJ³|$°öVæ#Y Š÷áÁùÌpâà N0¦±3D ^*-DÃ)ˆÆN¹á>–„ùãÛÉ™ åY¤Ü9Õ8̪ôp:]‚9±«¯ »Ž§±¬Éþ£¨ëµO¿G”}lp·+sÿõFP®Ú¶é‹ | µéý…¢M3z}ƒ”¥õ2œ‚Š ÔuC]ž(*1«úæ;áj¬j™WâVu¦ë•¸U½î ÊÅ®êp!(vUß(Š]Õ· ØU}¢óbWu=TjFªã'v|t¡zÞc'ÝZŒE!e©š„›©QŒ’)j)"0ÀE-(e,#&oáX†×'ªœˆVÒ'PND+q“£‘h„áÚ;¹4 ¼ØNz]J׿•Ð.sO~ºbž  ÌcÓéét)M§uÿZõ˜<Ò$’Ħ}^ûMË·öe<½¹RP¾ÚníŸñ:I1ƒºœËÏéóÒ¿¾T<$SâÚnÈëA%šL™Îe>]¾. “G’ØT²)q°¯Ëó/] ¥(,ÏlÓ£—M¹¢«¯ô#lm¸œ/‡šv Ñí]žsB%˜NðEõˆrz ^Ê(±à³Ùþˆ+ñ„G!œ_=á1 "¥ø’ÀûS=I©Suàº%%d¯AÒ|TOÉH P(žjFe;ÔÅfÍ‚l‡º'‚âCÝŇºéùP÷JP­P÷@BÝÉʡöè©LŽ-› FwÈ kQLž§ ­Ôøs_½ž)ŠqÜíÄ“×D”˜DјèX†‹B\éX–ãºÉ땤„Ä’ì’:¹ôX‡©`©SbŽ¥Ä:¬Š­ÃšéÙ:¬ÃXŽå§±´à~8J”:Ù(ʦfêX§Î¼{”@Þ=`L3uVð¢z•:'$o\Á]“:/~qªþ0ŸÊn)ý¡œœ øÞw'Aqéïý@P–ÉφhRêþM Š&­ÅG“&‚âh.Þ_ä£Iô‹|4‰þÆÀaÌÔc_ö+-{N´™ÑÁÀêÇÝM4áõPö¼ÉÂRö ¨FÙóŽÂ²g@ÙfóÍRö (×NÖòg@5Êžû±–=*0)}§ž®DlĹW²ªã\•8wRçjœ;U–ºû8÷ZãÜ©²ÔÝ¿ Cs§ÊRwç^kœ;U–ºû8÷TãÜ©²Ôµ’.ñ¬V–º†±†TljMo¾®Õ›”rEЛ”øµê\ržÏ„’Hs°ä<‘dãfÉùHPlÉùá‹|ÉùJPlµGOQ|ÉùDPlµÇa,¶Úãðù’s:–Pr~X|¶ÚãcSbðð8) §,,ß©¨vêNê¡ËÝ2pÔŒð¤%0}z.—• t#}ûÞ²L A™f&ñN€DQ¶™Ú4Ï帆ÇìòúÅq¥óòb®e/æzž*0•eÃC[Ü<¨EmRQL“Zá‹IÜ!<Iô7ÁqÕB¡fñ7%݉þ&Pç´ýMðµâgŠ1´}É=Ei® ¢ŒØ…ì€b“ƒp^V4òAÓ–/¤+õ%I;Iëq½œT_)I³,I»ÚT~#aIºOc)IqI{Ñ|ÇÝ¢ù޳ú?•»¤£ÄËTÖ^ŒC–3‘¤hЩ £ÎÉt<'V1€“¸”¾0›5™¿P‰Â¼þB%:MÂÈT2BP1ÌSM½'&eòÉx¹L~!(¾L~%¨v™ü‚eò€z,“h™< \Ã&eò€z,“h™< ËäZ&¨Ø0¦I™< gh.°^AìKçÞVúÖ>½ÉˆÕ}@KšL”$tûJ&ñ %n›*g›;¢ Ë··í§‰ “ŽR®’q6 ”s&B²óßóì“ýK&ÂJP|&ÂDP¬<Ó±š¿±f"ŠÏD (ÖîéJD–€VBÉ<#Añ<Añ 6q÷•QBÊÎ+YvòÚjÔX8  ©¸Ò±XRX‰ÐqoíT³;RPRRúçƒâ#¥–3-u™(.a¬Ì^$C‡v‹)™¶¾heÚŠ• xÚŠ Añ´t,Ë2½æSø7¦× x¦× AñL¯ô‹<Ó+Ë5¦Wi¥ÉÆw©¬$¾ÏHWL±)ª…ŒV<ÔøMËÓC¬Øk8E×vH ”±%Õüì6cËDPšñâÏ”aê^Ê• bº+nej‹Q“D"‹Ÿ:‘jV"ñ}jÕaJÅüÞ§~%(Fà  ”ŒÀÆ]qS²b‰/~ÑŠ%¾°^$ ·Uâ{ë±Äwg:(%¾‰¤á6º5ÏvJV(ñ½®ÏÅ–ø^)Š-ñ…sŸ¬Xâ{@ñ%¾‡ãK|0>Ð 0'zF{ŠbK|A·M^<ˆ¸džoA]ƒæ)ˆAs<A&eª4¯¤Œ€²Ü¼F˜ŸO¹’yE¡‘T¹™)òÁü¹ˆÖGçX€äšå²i;ý{F%"Zÿ}>m|¹i{Šê¶‚bBŒ1¦»®“²z3«7¢ØLÜ+ ßO-¿ ¥¥~’ÓÕNOA͆2©Yc™Ô Ʋ2©ÙDP,©ÙBQ<©ÙBP–‹ઠ)^èD”æ|ýÓ…  çë\9:ž/ú›ç‰ 4ÃÆTÎD½sWX¯(zçð¬F–¡«0m¨$3­Å%#-0{Õ }gË)¤y±Ôß¼ŸÂÏ·ñ7¯ÍýßjžžÏO¥1βlàaþœ??)Ê´ŠßæúÎ"Ê2 7¸, ï-ͨ L»ÝÔýen>õ e¹æbÃ޹Luü€Ú~aÿIÇ:þÆ]dÞº¼oÇk$(Ëí#œ åÄ}< XÿœBåEÿœhå…B;‡;¤‚à+’¼&¶+Uà&¹Re$(¾R…¢øJúE¾R…ŽÅĉ{”9”Æö.ù´ø26”â—âË@T‹¹F€eš~$ôe ʶ+´À—¨òR|ˆj Å—¨ÀT{`íµ:xÞïyöðE-6ò„³J35Sñôm(ÃÕT,ÅÓ‡¨VMÅP<}ˆjÕT ÅÓ‡¨VMÅZ<}ˆríš°SÙ!ÃÕT,ÅÓ‡¨ÀTŽzº‘ó©÷°Vô©_‚âX'QNh'F*zŠje>¬ôÜ{Îk¸–ÌDµ2†’ù€(ÓŒ`梚ަ’ù€¨VæÃP2ÕÊ|Jæ¢S‘{ºRTdY:A‰ÛmÆ3Áeôc!ÊØPQÆN<Dˆb‰2®ÅePöPÏýŠØC¦­@”k ®*ÓV Ê3¿ñ ^d¤ß˜i+ÅÒVàìeÚŠŠýO+A±¿q=”çÞmØm¶Cý~k¡@`C)‰Ó°Œ¥yÛj(Z‡1’m5€$7æA’ý«žBšj\5«¬­§HLc¥S8ÍÅÂ#Ê2ó“Cùpç5/OÅœòE'œ#Ê2¼ (ŒÊ€;QŒ]Ûã[k‚à2,z¡‘z4õe^I"úAÍÊvÒìG° m'¦-Ûf•TPq‚wÈ E#HÅ´¡´ÄÒÙPLu\¹ÖH:9Þk$ŸUÎÛP¼[´P #Ч@§(Ög…ëee t˜—ãêKÉÜBONQlówøâ_¸<'‚â¹<)Šçò ŠíâìYRÿ¥ä“ Js±]ð®X–Ô-¤þˆ²LŠýä—Ìù[Nt”K„‚âK„(Ê2”9r&e9©ÝP¡'ü®ºkdR’Ø.®½ë˜3q‹Úf~WD.j ·ÃuRC”N‰¾GX §„²±SK‹¾ÇJ3zœ,0àeGÇN€g‰~LôœÊÌÀ3Ø¢Nôc¾_)ʶr@.ý×å÷9£s7Ágµ^^¿.—_‚ºólæ½ßì_‚jy¶6#`{®‚²íÜÍþ Ÿ˜áYlwç¥r6|E]ÊÙÊ+J8[>Q<9IÊ~Ä»-°ùÎØIsC)žƒ¥ú¿¼O!H_BÛòÂËç /M† JroyÝw)˜w ÿvr~†Ë ø#âU$„¬‡óµ±ž/OÞ¡#ý²Š~ Êrk«xOó塞WõÞª<Bº¡’T?üò©]å1êPD®4t9Ïzï*u(¢\Ë·ý¼{ܲ·ÃåÏfL•_…)›C?üô¦é‹ ;tÎ`Ü>‹/rèÞÈÔÝPJÎÔ] ŠÏÔ¥(&SwzƒU%„¬²±Ðï+!k«lìOOQž)»¾ –k¦.¢b;/hB hñÖâz^bV«)HÄÅj"ù–-ioZpb&8~Q"Cø*óùá®øÅ(ñ°¡×'ˆÝMÐÒ I(p¬Ø‰ ‡V@)™’™¢ØBHÐÒ¢’ !Qƒ‰J¦d¦¨v±ç{‰?FÅBÖî?ˆâ)™éoŒ “Æ­¢–Örò͆2ÃÚ„û Ëœ_ò'6”ÇÂyYÁFúð å„›V,éè%Òþ€b+3p…ˆTÎÇ(Ñc\”°'’ù¦Õ^w7¬›jµ–‚iÝ¥N,˜†/¦N¤˜@”)&(ÍÐÉ¢ÄLZjV7Pš“Lˆ2’o5ÑdE¯"Ü!6#h[¯ª=&/ÓÓçÛ‘d8~1H=vÊì£èKƒsŸ¢ØÛlwÂ?بכ{ŠâØÚú E5ëõ^°ï3¢Ø^#ùv¨®“inW‚Ò­8LxªŽ‹xî-@1â©:.âÙ/5ò£:Åeo¯5â©:ÅjV5â©:.â¹Ï #ž€jeo/5â ¨ÀÐ{ÀYTäN0–F9 ¦ :-qe‚¦:ÃeoOÕ#¢:+¼0èQ„ñ°ûˆêøº’ÒñQ–»Û8{Çsº•$Õy–<¢æ )ʞ؈ºáÚ{¾n©ä ÊrÞáÆ ¢wø€ÒõÅg5Jäמ¢øºÞ… Zrb¨]ÕE>ÿ +’6Ô_øSW‚âùS/Åó§NÅzšU³žxp«§YÕ¬§vðBP†¹µ )¥Ä[‹_TÒnçÜÎ õ—6‚âÛXLÅ·±XŠmc1 Å·± cy.çWÂp•Cõ€«Úì¼™ów[öÖ–ŠJDÙVöGà)šguŒý5ö«”“c¿Añ±_Šbb¿Ä~UmPÞˆýNûU¤Ayã7BôTцî¿bøJY9†?ç(ö7ž‚bãEyFÛžq·½È½o‡ò"#ð7M¦MÂs„ÜNŒ¨+e¦â• øg€Jr‡³‰ øg#AñÎèXÍg –? Šíp¶Ò±øgô7òÎ(Šïpv!(¾ÃE Î ã;œ`Ô´ÍÌÜÉdóÐïFþÜŽþ/AµÜëkÿ¹~ѱZîÇe»»'PŒ%¥-SAiXxë6”гox†$cER‡Z» «j¬œ¾’O!IäyHu¿Ž¢·¦!)+P •â u—Vsw·D µ¥%Ä­¬•™dåd&Ù… x†Û|&¬—n'‚âSà‹AtxæÀ®²©Ÿ½qx¢d²‘)¥Øç…AueS;¨¾£JP]Qú«CÐs“9%è ¨Ç úõFuAu@Yæ¢ôux aIHË9꜓[µÃz¹¿4±ÈûèŒè‡wÛQ’ãì­èUÇ91Dª´s¢NŽó¢n­“äW]‰ ±D÷”æî6œ{Å» “M{ÈR÷‘O{˜JÚƒòHù;ä;± ÖÞ+™ÿy%¨FÒìvÓJ‚¢”U÷ÉÏ% AÑŠC’˶õ>zÍ$!ì)Ò˜„(˦dÂìTú ITŠtämpI—•°2³3¬½“™‚bŠ©0Ry/þ¡¶í½DË…&‘狇çúE¡yËN1AQ,-ו~‘¥å•¬ãg¯‘8Ì‹¥å:|‘¥å: "Ë »eNð‰ Ú’¼’”ôœ”R<Un–Ï}PRù)$€¨ $¶o”&Aó ºÊƒŠT1ùY+­×ûH ¤AÇR« é÷ÚŸ`Ð 8ÞWÒ(Up àžÒôŒïvðŒ%MõMŽ ‰ú=MÔW|¿×[¢>¼i|¿×[¢þe™y¡k.i^PØ B ð‹A,l8 lÛ†œ*$±×>‰ÎÁÆÒe)¸Û±cÎûnû•D‡÷1Š!nH®WQ³![âyˆB:,vw@T;qÊì­T$¯UtBå€ç>z>Ä]í¡šÑLå»ÀÚG9•o$(>•o!(>•~‘Oå£_tL©!ú™b’¬_HtU1ÉíÔ2*ur;µ‘ Øvjðº§Nn§¶”e‹ó)LŠ×1çÓ+QS;r…×—mƒ²S÷óÏ3ñjjÇ6T~‘_ò‹üqžÆ?p‡’nSåfšbÔ¿’L¸á&–·çºÖ0•¬œ¶Ÿ6Ï…?Ï…O¿È§€Ñ±x.|ú#çÏÁ}t¢?÷ѵ“•vï]IVRÉóaéª ¥ÀSMî>Q˜}”;ÝPT[Ï©¤”„€ z´Ø“#t×I]`àUÐ’åà¢&éb* ÿÐ5£ÝPq (®˜*7TDT›úµ$Öi^¦&xë»ÔŽ»Uˆîœ¸ªó@PºÙ¯zgã”—ˆv@Õ]<[ ‰êNöF!J"c?T’JbN8¯$žÕ,´êD¢”èÅ€/*ÅŸÕRŒ [b;ÕC­ŒÜ“e!(Í&éÁ¼¬P$1–ß(3éÁÚ+/S¶OÅ2éÁ­Už¡l§%Zqö¸^‘·ÓJê¶V‰÷O‰©ùÎfCwhÍŸ‰jej­*yJÇ£i<íw¨BÇ£I<í@Çs¥t<šÐYÜûW+&t­ßˆ+aÅVœ ¿¤¨[IÒÚÉtÓ‚âé¦'‚²l—!‹¥F_K—!Di¶ÐBP†íDQ–míó rk‡• Ø°e"(亃 (Ë•õãnG±¬ÿ€Ò,Í:ÜŽ$Ó¬OÅÓ¬/ÅÓ¬Õ(¤¤PÚt¼O¡xN5íÞFI¡zJ ¨GR¨ž’BÊ2伸öF‰’ ΗѼ,ÖÈê‚Ò\œoõÊX°Û¢šÔQ5–©­ãb™Sejë¸XæTc™Ú:î­j,S7š-QÎ]üÕéó‚¶‚õ\|hªñ!mKE¤ãCë•üÆÀ҆Ò„” Q~ŠÒ„o¶4Õ„?ý·fK‚Ò\©4H&׉¥Òp‡\Ç6Ö©‰Úñy0ÕÞÖB„¸4“ØPFÊ-XzŠ:9õ9Q:-ë({ìù'ü휮›•óñþFQº¾>¿À¹?/םӸAP¦¢^áå›Nã°~_¿ ÊRT¿=ñzy^ ÊÔ ôýOëòöùç üµŸÂ—õúûv}›¯(e-äÞ-ëïÛûω "éû—QóØ??ï·¾ˆJ•sï.×·éÏéüBWõ–<øŸÿåe½]}Yßÿ|ÎϦötíœåùýíã0šFØ3þÌý£ÏçϞ …ñ¬ãω®™²ÅUö Òüç2Ÿ^.§ïÃh®Âίû|é·›D÷Iùìœa¯?ϧþ…ÛtÍ {ÿNŸô©x€õ·Ã±Áúët€¥ê탎¯×é½?ýï=µ]Í-}ɦÑ÷¸Ìãéò‡þ­,+Þ?ËåtþX>é.hyÉOH[ós¹žÎ_ËÓ…ÂL…_á|¾?MK.tB˜%°›þ¼¯Ûùé÷LOˆ.ÉÐO·þ·oû ÿü¾¬ëpø¥žÂúó 6ŸÇ1gV#,”Ôê|ŽÎý÷ÇrºÏ¦Ž°[|níãOMX>Hl³ô¿?éOpû.üþß÷÷o—Hìõcþ˜—ñ‰.ˆÛváwÓ=nÏÇùv§õëçýóm¥›å\¡ ùÝL™? γ½1á£NªÈ… MwAMp :/Õ_q,¡¸:Z]Œd:Ð.‰J |'„ŠGtÿxÕH¦Dq8ÿæÙSþ›{V¡¯þÜk®ýÉRÚŸl(!ѰºP½ꯋ)渪 v{/®Ž%¹­´R]åé€âÓëà‹Iî:±”n3î̧51t¼k·:€ƒj§ÎÞ\æãó3 4ÏUþ3|ÁF:ÐA9H¾·ÛX/ïóå|!¨lŠýÝR`m q¢_dû)A0Œ¤5ØhðvÔnvízuŠâêP1X—óJ\ÎÁòì=ŸÓeÌæyx¬í+¼<{aÌJPuöø<|>íœ óÛA™Æ­./#ÞÚà¹[;ÜníDPä‹`€¼œ·c8÷x&¸B™)¤\r烠t»hä¹ „›VO4Ë ³» 0e\ÇN nGTB1ËsAi!É“)u4r2%EñÉ”+A±ÌI‡±Xæ$¸¤÷W3™’ŽÅ2'P,sÒ¹B”Ü…×^îB‹¿Ñqý$&À")Kw…1 `EÏõ“XI‹4غI+zVšgL \k NÛåÞ' Añ½OV‚â{ŸPT‹ƒxª©š¤?ÝqO5µQÇ$sÅsS7/HmÔ”ÿæq^Ú¨©T Îæ xÎfв­ÒKÜIŠëø1·gR\ljw’â:~L$¸“Ï&_ 5ßNm­‰†:ý¥ -¬Ä_ºÐ.űC¡Ë9IìPg ù'ˇGª†œø@ѹ”³éä¥òRtަ %õ£s4!¼hÈIàN«¶BJ<ªX'¦ë„n|‘M§î4¬ø6l2Ò; ‚ÀFJF*Ì‚†$#5ûvÓ±ø¾Ýt¬fâ\-ß·›~‘ïÛMQ‘ít³d”‘;ÝŒut˜ß¢\ó4},CÖ¶M×dMÈÚãï ÔLgŰ ®„Ø÷ñÖšÎË=3‚ÒÜYa^AL[`,¡˜¸Ú®‹Õ®,·ÖtIìÛ û¨:¹ÇÈDP›¼µF)Iãƒp’QJb  £¥]c5S$ž ÚQ\:Ï~ ·æ7£,W¼óŸžV‚ÒÜXÙ±fh"ØÃX§ÓºT;€UÊãr‡ú [£¼Üz"(ö‹x&‚ðò¡ßĨ¿¤ýÁ“Tö iFý¥aFéN*ÐσÑ_ Y|F … %MÒh-ÝÐD ×ýh¯Ø/FFÏÉ6r¦˜0$]ì@1±¡*Å„¡ébKz{Ó Å„¡ÝZÅRyµ•ŠPÁh¸.C· 0–©í䎑 A1)—å…ÑBÁ’Bh´xRBØF³Ý0V"'´äUDÙ˜NDÁXFq)KkÕÉ1\¹ÑZurcŒ\nDÇâË(Ê2óÆ-Í l@ñåYt,¾<‹¢,£‰By¼©éOíÆÑ°^és1ß8z (Ãö“€yy¹ŸÄDP|?‰… ø~AY¦\¼QÆ„öËwK,¯•‰í×êVÜ_^+’pÕ ^Q“„±Ê+jšÝ8ÔçÌòe(]Åj†¤~cù’Ѓ2 ´ª‡v‡±FDÁÚ[+òÃeûÑ”¥f˜‰ øž±Añ]`‚âû\ÊË}.F‚âØ´Ð¶âI-†ê26Hú*Þm+è¾Åilj3jö´ïŒù[‘‰ ø#Å÷YÊr³‡ÝvŠK,_«_ÎÐd¤ÿÝ¡Š_Î8Í%–OÕ/¨f²[õËʶ£HE®:#tךû'Kê †Œ‡FŠ?Ö×Ýy&Z³—B£ɸÀ¿µÅƒd\àÒƒ×êAT+=x­$@1~Ì¢8žãšèNf¯†µ÷HÒ_ôDÉ1!J‰TZ”nwÏÅØ‰ñbr3ÊoÄDVDY¹×èHPLBò å„ýäàå7Åy;¼—ve¡#?§+Eé6ÍÔŒo%V¸/-)”U&tì[[)« é™Ñøâõ ¾˜Ä/ÂÝ¦Ä _DÂ-”D®„g"h¹áHPÝ5ÇEM0"œèÀ¥-gþçfoE²3œ—•;ÝÀ¼äD|°kƒœˆ':x&QzC}¼i!p¾Žák†á‹ î"×0û—ïey&¨väz ,G¹ž­ ½î˜(m¸nPfvmHrÁ… 4Û['¯WìDâD)‘¸v(*&Oa'åÁ<5ÿÅz;â_úŽÅÑÑgÞD+ù1Á3o¢ü˜EˆeU}·#Û`­]LüKW€ t“qÚ¶1Ÿ‰å\€Jr®• 8’,”÷©“ÊKO”nÆX«$OŠõINûI4Æ´0V‘Ñ´ŸÄƒ‡‹ûM’ü˜Ø%Í$+%ÏãÚ''÷mX J³½)`%¼D>%U&‘œÇŠ"9ÉÅÑ_¡Ÿ)%)ƒ îí:™™ž¢šåÞÛ™˜'@)¹xÊ(-ó±S_¼”aŠÂa%ìß:ÀìÿÒù`"(¾óEñF‚²… ¢D‡WÕñDMÅ7d;/3­OÅ3­/Å3­eÙ¾ € r߆… ø¾ +Añ}(Ê2Å×à³²Ôá}C¶“z„£oȪŽýÕScÙ¸Õ¶¥´×*%—ö.Åww (Ûð¥MÕ/g•æ´í©úå¬Òœ_nª~9ËE¤rÑøå¬2œ3T Æ*+RLÀíPN¤˜ÀUu¢5gUy‘<¿È±ž q‡UÏ*…UQ¤™‚›¦"ùYkäǪÄE~¦ù±$vù™jäǪÄE~†ù±* qQ¤ðµº“XPh9ª›_w@ñ=c‚b£º3EY–ξ¨e:ó• 4ÛåP†—õÝÖFÎë (¾Ë#Eñ]‚â»<.Åwy¤_ä»6!·­y^Nò,–{ä S#µMÖY¶Å@­“²Î2P;åÎÏð<Ô£ùJ+ ¬³.zkì_êᄱu‹@& cy‘ôä´ "éŽ$Jˆ-X±ºpX…FØßвdø9÷Ηï¤3o·g©‡ËfTdj.ëõáVÒ­u¾üÙ“u ª¾k¯¯è3|OKÿýCP¦Jà—¨ßšÆeýêéíGຬ?ÓrúüCP¤T¿,ýŸ½èå¾f?ßP{m}ñ,^†/úÅZ¨Óú^Þö–qý‰ n²õ·y½¾!Åéõú>Ñߘ¸<]¸ÛÞ15ŒZo%Dñ¬çóškf°ã™õLˆý3Ñ×ä%J'ŒÆÚÏ<ʯ~½.U~ù$dm }µ H¹2:t’W"(.›d%^Ê eªõ‰ xªuŠâ©Ö‚b‰y`íƒäÓ)öUp mµ øtJ® ^ª¸@û*ð~÷šmiCäuÃúІ$7Ëë;¹9ØHP\mž{ŽÒ¤/œ/!ŠG¤o4¼ÿ±zX¢•óæG‚âóæéX|Þ<˲m¿åä¶_AqONô"*ȉäV$ Aév%[Ñ cêÝŠ^Ø®ÖƒŠ±b' n¯˳—ºÂ×S(t…¯Ù$6i¹…Å… t;ÖW^…d…ˆ`yaØÞñ@… ¨¿Pa¯¥Ût¦%v•¼TñŠ’œë ^V‚Ò\œ®w<Ô¨Á‰NQ )+€VŸýç_˜WÎ«é¿Æéí6/G"o7’˜ý}ÉYóëŸþúò‡ @2ýKdôNìúý¾¼ecôÙøÈy®vr¿µxz}~{Ý>­(ï]× »OÇ“\¯ÕæHýÖcÎÞ!×Y¹E Œåä)AiFÏŒR׉Qbж]„\w”®K eŽ»«ßz ÌγW÷òMõåsJI¯(ä¦9¥y-­ä!¹vôª³ñ>:eE½0K§œX…3ÅÇu`^^¬: ¸ºXÐ ß%x­mMœâû½×èSQ¬ýÅß%/ågŸÄ"œW’hVñ¬²P¹V'¿0N37ß/Ê{§%1¾Nk±-¬½6bÝ"ÎË<ÄËKD°xðœ&¼†oî€Ò>°i<¯Ãò'»UÈÈNϯˆÇaê3• ,ç)ƒÒÕƒ×ò”}Žå9ØLǺY™¿™ê ˜cú÷?çß3+[™yöù¬î•¸#ÖŒ*Tn×ùûôòCWµkß\毯¯üÄèFßUL2¼n»ÿKP·ÏÛž?¸;Ó®§e ÊQàr»ž&xˆ*+xæu¼±Rîœl»i8®§A¹ÒIåå5»b_Ö×—Ý??Ô±¥5´9y>N=A…¢"ïq°ÝûýÝoèF¨L?¶w×ÉüœÛâ¼ìÝËDPeñ7u»‡R£i}ž~/ô7Ââ·Ú$Á'½Ü&i$(Ýð¼OÕóîtàߘâyw´Å1F¦ß`»KåµÓ‘Ó‘·7f{¯V‚bÛ©ÌÔIª¼-Ó™Nn!´T“åäùºÝðçŒR|kï?Óe ªÙÚû§ÿ3eÚB@µ[{÷W¨•”å.Ñs¾DF³LT· IQüUŠ»j¸jµÆîx‰^Ç—ëü;Ï'‚r­Kô=ï4ªå™Kt ÌToÚÃ%Ú~H0£rîp‰–r‰Lõ¦=V²Æ)»,5g¬ÜDl!(΋ öœ3N¬@…soþÒ–æõ—¶,AµãeÅnr&Ê WV‚âþ`%’ܪ'ÿFÛÉ­zF‚â›uѱøV=+AY–I/¯„å½Û›Õ·‰Œ2lýeoŸW²·v­qg¹èɶ^%Æâ,=é×Êç¬å²ð×=q5 yl>µ[É¥ù”kШc¬ŒHLëùJõ*1I…à}¥:‘˜Öó•êUbZߘàs+1zgÙ7Äè ¬Ì̵sÞm|XûÈ3ÃM{¯‚º¯ËÒwûì g"Iž”&®³ðAN¸NÈa+ï£SR»wðß9§eþ 4Ûž"ïß;ç?í“‚•prüÆòb~=Ξmì;Ûбúä„ ÒÚC5…sÇüTÚæmž±FÅñ­ª'²¾â5˜±è¼’ ø¥eF× Ai®ZfÏ2”³RÞG¶Ùóî¡ÀÜ'çÕÁ³êÿÒHa%(ÍÒôÃJÈ[œ}™‚ònû(í#ž ŸÎÔ¨lÖãNrC…ŽgtýÅt”Ìšg´ÌÂJQlÕ¬W0b5¬D°rľèd.`ø¢çsJ-› <{A­es\-[OkÙWËv¥µlŽÖ²Ý××w›D®î[–€Ô²ÝåF¬57Â…ÈÍk"¯;i^ÜʜǓ“$ï#î¶PñF$Û½µ=ž{©–moe—Ï=mÙ{”˜kmŒé¢ÄûQCM4z)£ÏjôrEñx#AY6ÛÆ b|×+ 62f¹˜älŸ¼^©ãØ­oyz ÕRÆ;‹õ|ýÀ+J"W¿ÿä}†ˆÇgÿ¾<ѱL›sw»he™¼YÔ™’c±ð*$#žBØ¡dŨ4¬jrœ$潸)ß)rU5¶þ xóYýKL W"rÕ¿‘˜)±LgDb¦ÄUÿNDb¦ÄÛUb&¶Ò`ªÑ_ßuBê¾S2³åDP6»›][¤‰ï4_ÝTü¾32ÇçBP-~Bâ%óCr|ÿÑo¯î@PÏO¡óÆ×Ëøõ>Ó±,3{\{ý—g~#M5 %Ñ×[pðk„õŠ^×e{hF‚²XjsKS»Ñ CŠÖEõëeQýçÞ4Èu1ð¿ÈJó$^_å™4ú1õ§Ï-»¦Óð¼äSHƒ©èüÜ×ëæü|_†w‚Ò ê²P”©év·opëûçK]f‚² ÔÇ÷†š(ÊU2#d¸Ì§óóW.¬”o¢~ÏGTxØ¡ŸËðò%Ñ€Š;ô1\^ Á+ Ž.Ò›ß]¤3„xpU;Nü‚ægþ¢çÃÑiØÝe#ײ‘^ÚÈ n¤?\[²øWºøÄö°¬uñ«v[0ôu_Ç—áã÷´CÜa­ Ê·O+ü}¦ ‰ýùö—wÐL¸bŶ?ý¬Ë;«hkûRdΣa¸þþë/ l}ˆ^²ÈÜ´äË×iìé]›b«ÖåÛQËM…‡•xÌý)u­ÅË Ç-Ôãé„–Š:Xuã÷çÐeš5²Ã X7e²ƒ*…ª•b•œÁ1ŸÁ1”iFŒ?{ˆ«ùÌ2 «ùúäjñXÃY<±x¬á,ž•X<Ö°=ΈÅclñ¬åšÚO'(„eôñDÏãEWâöºï=ÚçmÁ:¯¹¡º½È7.¹××ù ÎÉ5¨-øêCTs ZBú€‡Z¹×Ò§ž¢Lû‹EbÖ¼…–üúÄ•B‡ïrm;|ƒ Ù ®œÎj”Ì¢ŠºN4)à‹w]ûîû“ƒUçŒÜŸ|%(ÝÌóø3]À¯ãoÔ™·|Ö Aé&jÞ“œ3ʶ½R׃WÊñlýÄ+Ex5ê4«WÊ9ÖA¼RΉ^©žŽå”Ìþ d:/*™3E±JæÅ*™¸žaPëǵ?AFB¸Ëº8úÞ·Wr!(ý‡¿ñ¢`>8Ê¡ø‡WÁVéFTüu"(ÃÅ»cYä•FOøÇôü3~}ýŒ•MŠÛ™Ø…õÕü|‡/úf ¥ß”¡çŒJm“"GZ.¸ª©ß´ßڒߨ¶/yÙÄ˶jÃÏ›Už¹˜BÍe¹c>½ì==fðcÔî‹h¼ï»xåž§çË… L‹Y·±ÏTäô”ˆ%xÕf‡è)  Ù!zJÄ(ËÑ¢ÌåZ”d¡¯YF‡™Ò¢*´ëò71k¯Y&âÊ“¼×뙢øõŠ[¯ ®—‘Ö eŽ7üz‹Áí ¿^K]/S×ë1¾pIî-_¸TIîí]ïî*}_kLÀÛû³ú†oíŸëô7 ^ˆi~¬P5¼»×£_áÖnó ì€2Ì+ LÄ€bVÞ²«Æ{¶ò¸2:šwÕ¢<‚±"Ë+R9$‚O,;¹Û¡ã¾8‘»Mlï˜_&r·CÇ1¿Län‡N¼ÛW:–c)‚ò ¶–…ÜíŒ íHÞÎßœQŠ­¥ï«³6h^K›Šã7qUA+ïEñk?·ö('‚åX¿ÁJrò¸Õ^û*'‚½—$_áí O¡¿¿µo‘w?Óx&¨{¾<¸¯¯¯/eÚÌnÅóÜ óÎ[ÐO¥9oÁa,ÓæF›çu%(ûèõÙ“ ŠÕÂÁé~ï&M!„Ãë~ï&;  ç&ë'‚²œ› ¬¦ÎZ¢ór>ËBC³Bwç|`!$ÑÝy™J·×«Ø|5}®éÙ‚•¨lËMÏìc$T3kæeÛ¦¯ AÎ' ¯U›Ã:ñõôýzÍ(%œO°Ê+@ëL\(ÓþÓZZÒ\ÖÌJü‰ïþCüÉpY3ñO$6Ëh%þ‰d䬊r´ú._#ða‡d/ßÞ#èÆ©7oÇf;†3Añ'PŽ­˜Ø Ë%/ ‡3èrÉû =ßâÍ9·ÿrÁw»fÞäÄé6Ö>«ŸÓ÷<\×'‚ªì‚·± àr™W:%ò|¹õ³ž¾†©Ï=åi„åö_Ö÷ïÝ9OÇ:ôAêßnšÂyyy¿? *Ô-a+Ì×óõ<®t%REݾó­‹ÓfÕ‚Ž™Hbo6ñßPå{ÿÙщNL=ú‡÷XÆÛÏpXWªÎ¿Ö9¬?,YÎÉøçvªiFâ2ü(ÌÖ&¿ù¶ûËéýí<]èUî!P|#ØßDÙá£ûüþßo ’ék†ëyX¿†åðÑÐТa¥¿hX#AñEñÖBP¼†EÇâ5¬ |;Ÿµh·5ëµ­Ý.Åk·A™vÞhÑnSä´Û…hk$϶©­ÅkkAñÚEÙ†‡~ªlö‘fªùó×ÊŸ;%xèO×ìAç#Ê=­²W*R¶#£IîC5T3Ë®F€bÍmF€æ• ¸Þƒë|ÑʽG‚ÒÍlÜ=®_ôŸAÎ$¤¨6Gbéy;Ï{P'äŽÍ$Ìrÿ¶ö/¿ŸÃvŸG‚rѤžÆ¯bÄøU?¿ºR”iq-_Œbü ÷1ÊœËðÅ$r.¯ A1œË ‹­„s9ûÅi·§ì-‹J±|eÕ+ižíÿîªø‹W**ÍyP×ê•T˃ºV¯ xó@P¼Ç™¢ZÔ¡z¥Ø•€ßhÄ•x¦(~%‚âVâ‚+ñ_2‹÷%_ª½K]‰_2&oM5®••“·‚â“·(ŠOÞ¢_´M®¥Ÿz;ËZëc"᜹«j}LT¬Çy©õ1€²MÞ¹béÇFoñÒmºx b#Û"²Sµx¢â«hªÅUä"²kµxǪ̃ øˆìBPîáu¿ù)Êë®;¾;Îò…¯»J,/X-êŒZê5‹®¨Ükv"(Ýä6.>¢¨¹øûEõûRRTã!uö!fÞƒÄÔQŠ™`Ô‘É(éG"'t⺗LDNÞG9ÑDNhÎË2ODNèôÈ9Óƒœ¨rÕtr¾Â@P|¾Eñù +Añ Ûy‡Ú]à Ã6È Ò+áAÛþpíi‚í½¶½g¼Åv ÍݹÅ@PºÝÅtîa‡Üÿ÷Éà˜2}Ê¥\Î2ŠÆ·ó {šgïXýIéæFÊêÈ3œ§šgMhçö4Ï0֌˖G°_`í#ï¼¾¾žn±h;>ŠZe´Ib”d¡U2*K&+d?íyMyöÖHÙˆh5Y¡â«ZsV¶æ®#Aµrð&bÃü-o"(>o%(Ód+ªçËrçkgƒ/çËrçk;Ïõ|ÙÀå±Nä|ÙÐr¸Ŷ²²m…«¹y"/òÃÐá±¾È6 vZÑ\'÷Æ™J3–ôØ|Žç¯™J†jtJʶx»Ò±LÍ2zÁÆe¯ºÈ~V@ÑÔÿ·×[—åz}=¿üù$(‡ÑÏ/çWä=ù™¾Æ¯3Ayt>ívGöOl‹úö¶‚Sr,f¯… Ìæ‰NÎÓÉ1xàG:jóy<çè.GT£ÚÞþz}{"(Ãæ[Á¼ø§ùy¸®êT‹Ëâ¡sÁª—Eo¸µ_kqY$y` ½wÞÉ]IF‚jf-ÏëË;Ü4/ðâW?&í~Ïe_ý˜žt/úÏýšÆK>÷\¯„¬3=|±Jò»˜Ánõp·}<8½¾d¦¨íò?_—±Ϩêþ'{1rÒa>ÍÖyJ7¹âêËwÇ`EÙ”‰~O3©ŽúýBô{’IõÀ;Wõû@ôèFwX¯ ¾²dóÄ Øê¢›Ôì§¶§y (Ýðv®D7©9RmÿêJP¼u"(ÓþbÑ‚•ý«AévÆà„l‹òÂϯy¾”ó‚Ðí©/'§ÊÕcO÷yzž‚Ò5¦ ~¹íݾ>g°ùj§Ï=ƒ>±Ý¡¯m>Úé¡Á?ÝØql~™ÎW’ù›3**‘¿^÷¨~¦š]ïvÔrf#  gwLÄ#­œ‰°Ÿ‰@Q†©§º²ÙÓÙ'Î˶hLbTt€Fÿ Ú=Ö>)>§¬ÔëĤÄ>ðº'-÷X Šgp‡/Z¹WŒeX¹vL‹‰çy¯Óbr|Djï“ _dý&+yÝë7ˆ]›X¿É@ìÚÄúMVbצÀuÑË…ïð%ŸyÂy%>ª»íX™)µók÷•(²0uìŠ÷S”iè÷kÕïS§9[a­¶Bê”M™Æ©3\¦ñR3Sg¸Lã©f§Î<ȯʋ''±½82/~–Ñ©QÇÙcVi:ô⸷2Ï G§.²þÂyøøåÿW]¯À¬×<Ñõ ÜÉèz¡Ú¨þÆ$sìßÎ}úÖWM!ñ1éµÖT&¥ÚܳWš%™ø˜4É’L4&M³$¯4K2‘˜ôѽuA[4)Î;¼wj_ލ†Åºß~´X“²m‹µ§t(I1kOéP’b,Ö+¥CIÊ^ ̸LÊñ1JO¨D£”wº\í •'Õ]†êZ{B%åùÎ¥'TRþÑ«ˆ÷±p '8ô¡r '8ô©r 'øØoá@O*<Ä~ O29«QÐ}ëYìzѳy_G©^N4ÆÚȳá7&¹£ŒÅö– ´IIk¹GŒeÄþ± M´åc¬EgJÚòq¾¢3%íä>(+A16L¹Ú‹½{ñ‹‹n­Õ“tàó‘‹)é(wÐ ŠÕø`[¤<¥çEyu{^à™H¼$¯»m´ÜÝ/ï£Q|ß¾b»'#gÞÀ¶†kxžÏëæåØú¦Ÿ+t¡JFÌЗ Aµy÷`ù@P–Í ‚Ù{¦Êž—6.S–ä†éq‹+)gB«+I¶ù>?>éXmn’u³EG‚²-¿ï¼>ãËg"ëC®~ÌÄ÷ ߣ"Øœì±rß!x‡ÆŸŸŸ¯ì¿O´_ø½wå|OM"ýÂÿ÷ßÌsr[üáé:| @¯–l'Ví0–’«öG‚Òmö˜+XÉj>r½Gb)нi 3Y#Üí" í_úÙ ¥¹¬ '¬ài.1ü$öT)2Çz±§ ÈËg¦^J?ˆDXGÈΊ?:ÙÀÕpíõ¿ø*X‘Xþ:.¥Y`Ψ$e+÷p‡\'iÛø*8-w´ JskáLО*­.³AévÜ £[©›#‘ŒcMŽ‹ÃÐ^bãi4‚—Hï£oˆFð’ó¬¶]cs‰ÒØ\jÅ AÛ®±¹DyNþ¹³¤«~ï"÷Å•è÷.r_œˆ~ï8ºÃ[¯”ÑŽ£;ÜPÕ†qÝᆪ6Œ œ½½»í’سä—K<ÏI½C¾uLËÿ¥ ´Ü{)¯½7B}ù_oùwûú6þæ•ðnuˆš'è%”|«sèŸßŸŸOÕÖ:dO„ ¡Õ{ ã_z&ÂzyÁ'Zü>rþ‰ø'|ä=[Õ?áãc|›öUËRNêg3 N ÇúFxšRÐro¯ Ø~»pîƒâ­€ú>._n_Õ⃠Fô M€r|6iÉÙJAÈŸŠô}d8ôãÂõŠr?®• 4×Íl¾ø,žjó…À×8W{;$ÁV(övHœoh"övH\žÕPLR|ì_†±“ñz^¾‚¢+´ãš§Ê™’bÇëäÏ'ˆ%R÷þȆ2¿bŠJX‰b×F-ø™Êk­˜#>ZÑ~_»U}ȑ͡\k¦xŠžÖƒÜa.ï#­Ð¾›WÍyH‰÷›&² rÑ'’æQUŸ Ñš»|¢O$&Ã%·Â[KcM÷¨ª3‘XÓ]ÖÓDt&Z¡ýЄª¼îɈM¨@sOFÐܱ²1‘JèǺ䈑S²,1òXˆ‘õHŒÖô ¼V€òlWKX 'v_ƒ×*É}!áD'!B|z~Æóõ‘*ñÚŸ—í©ŠöCùµ½V¿¿oeZñÚë)̘â{`Š?O+8®F( oïíÛŽú|Ûž,ºÊ×:ûXoûGÏ?Oc¦4FX(Ý^Áåq½¾¼¼\ÿü`©|oŒÌûÜþLæMÃzÿ¦°T8C^ÁgóñçûÏëëo?ÑS»ïÂïö°æ~8ö…{Ùã/—ÃQÓû.üþ›wáüš]À×?óø|8EZ7ÓKÙqJLªä•9™®ëX7׋Â6”•×yó†âÛ6— ü†Šœ0(ݦ’9e÷Ȇ²âó<ÂoôB '˜œʱëŠy±¡äN7UrCE±kà˜ÇRÜÐV"ñ‰¨âncý¥Ëâ@Pšksýc ®4 ÕLÖùF%qCXoøÂ/XoÉÄzˆb‰õ– AY.ìgBYÁ¥ªä†r\ˆw*æþ†òl¢AQÆ6Tà’’×âœÞP‘½ç+n¨$yÎ3®W")ûÿæT£|;^ÆÓÒÿ”¡ô/àžÆeýêW‚²UòÃÓÕ_ÖŸi:ÝHOåjâRÓºçÍ,+Ës$£Ã@P¡Š}˜ÖŸe<­çkO¿˜ý§0†Ü¨§O®ïˉ ÛL6ŸhÝñA? Þn(Åoû±„5Õ x% ¬Õ.ÈÃà-¢,' á¬jÍÊû’¾±¡ ›??Y¨ùÛQ ‡ åyˆjº‹á€¨F¸øÖô-›ÊqÎÖ©ˆj9[×b8 ʰ=[a¬ ·€†µrF+‰§ß<–Q‚{·¬½é8'ÊZLÎ ¥ùÙù´ÎðEÃÒð¿~?¯ý@P-þïó¦ ¢ GC6Áì-›S3ÕLŠ)‰ˆj7 ÃÄ DÙf˜ñý³ÿ̧Ð8>Ôµí7H&ÃBÂÊ å…4œrÓ ¯O·à†Jr¯bX{>©ïRwÛvm*¿=å©ü6”âS8±Q¢4Û¾¨Y-H&Ë;dJ’Ú†²Üì‡ëg‘«Ö‰mÆ… t3õè å9¹:=ÚQàJD¡å˜IX6Ÿvy#a™J?’Ö¬&$­A”iºéßçì¦7WNnzÐ'H9a£µený±¡¢—r¢‘ûDÃXZ®•WÁ9ñå›à7ZáDCÛ• åùtP$yßP#y_ É;¢Z$ïk_uøÄ2$yG”m;éÊ«À•Ç[^¶Ô.ËІØò¸=Wä—WâíYxWDwÔ'êX–‹È 6ÔMdaöœ5·B9Άò‚#²œ/DùçËGA*;:ÑV€ò‰'‡ÁÖ ÛX‚Œ®7-(þVy„^bHÝŠ(ͬà FÐÒʪy·aUƒãtò‰èä­0ÐÂ@U'žÓÉW¢“ÏÑU¤Ä>æÌ« Îïyùn˲ïÔh‹'SCŒÅ‘\ñ‹‚=´¡à©굌¤ßˆ–NˆBùRÑ C3÷.kVõEŽŸ__äÈfP­5“WEÅ6 Ý›õ嘎ŠZ@õwW5ڜ˗ž__zliy]Þ×o‚2w¨þ|C­ßï A•ðÓë9{N§ëÇ´­XΆ”#~ò·[#¨þÒŸ~–õÎËcÎé–›~¾ù™/ËyÍ5€ºyÓÿù¿ÿÞ|Ûý1Ø»Kî…\¿ÛðÓÔÓÙ'¬è¹¡öÚÇOe‡t-˜z„ÍàF˜büéW:¥Î4*â_ú@ÀÕ&pÄV∪êDAmªªNôlÁ@U1È=Aévõ~Q¶C³OÝ]øäƒ‹¯—ñ ‚x€bÒ1ŠhMJpü’´PL5Ï`Þ1š™C‹Q‘,/vªQAºò>š EáNNb3Cõ$yIìL œR…\IÒ-õQ8]¾A8‘n©¨õûBQ¶–±¼¢ÃóuüþBãtK½‰°Ýkuë<ž¿¶«;÷剠{{Ùb¸~œ§"è2*< ö~»ÃŠTs¾½Þ¤áËv¶^¦—ë A¥Ôëò:¿N¯¯tU;Rôùz+ú|ÙîìËé{¢KQ«9 ìu»µ¯/ÛÛFaš6.‹q~û8}R˜!¢úíDõy*¢`ö6m°áæð¾;Ÿ—z2r5gCZŸ†Ã1 l¢»ž«9”ÖKLˆä»Usþßz«4½¹Gní>¾gºn·jÎØûÏÇ|„évÚŒ¾¥†/hu¦$åfôÙ§¬T¼÷¹sns¨vnÆùœ©‹õHZ¶½•O¿#ˆb@YN|Ž€«LOÙs£;A|.@污ŒP5‰V”î,ç#ª¥;ËùH—jEéVŒºV`Î#Eålÿb¦Döaíiï=üF'Öƒ¥;/xžÑ믻 5÷Ÿ²î]¸XdºK‚–‹‰V’w ­”TýŠ'Gi–ô§Æ¨µ2œÍ<Ô*S­¬H~2-Õ$?©u­ZY‘üd (Û²¢Ö½{5Ìˉû8Áoô}H_ B£IŒÌjŽè믞ªYU#³šoÌ9ÔȬV‘“SU ´J‚®¬*€6(ýòS¯¹–›Pk»­µPks…wFkÍ{±‹ŒÖ|ûΉH9mEÚÕ+|щ7 î‰!þþ³Æ¶—þ&Mæ!ç©i„ÊvT½µDáZO¡NBe;fƒhÓIõï)¡’j¦ D-.Zªê4‹œ0Vª£C™cDò“NŽñLäÏŸÃx·6AйBþ¯6¬Oy"çÞD~·w†:ø‰o³Bó£m'Ò~Á²bc|;¬è:1‚ ­‘jQ!çM[Ë×¢þÁŒ]£Jµ¨%ãP†[U8ÑÖ±ž®½ d4­lÐO­µ";ÊhËû5/{"$ ØÆÂÃRüaÚrÇ7ŒIí:.–2T’vJ@¡GI“F€-ÏM®ÜÓ¤`Ë'sËbC¡›åf3Œ×uœÁ`Ö¤`Ë×2Ó/–¦á7CþÖZ|¼nÊè5;Q´#ù™¨ë¼Ð±b[2a”W;-ÕÑ¡¾êŒ@>WÞg…ª¶¢Õ:'½âÉq^Döx»ËÚß­vAòOW˜}”üÀàÅÖ.r. ‰Èh'ùó¡®Ñ¾Q™iPškל}~Ú+¹]óHPm'J•r^¤¼E‰YcOÿüf/ßþ®óÏ{F9õýšQR]+4‘ÝPžãæY«+Oû Wi ¥9~x;|äZÄß/óåv(ñ2[Ä#Šk>:€¼÷Ç|üû¦6pVƒ”?·Y:Ai¦Bâ:(¹Bn!(ÝäÀùY€uG-UiKV“ ÌV•ØiAKUZs®À”eä=¸òt0â«Ð/¥9÷Ûa,óàqšÆa–?Ù%([™¼^u‡©Ÿ_ Êqn)x‡2Ês^©*pN©Ï‘ X/ÒLÇbHTvå5"|b¦8ØBg–]yÿÃ%ëóCúòþýúòCa¦{¿O/3…Ù‡«»=äêËûxëÕ V¼º3E¦¨UîàX¿?QßI÷ÄB+\Eýצ%OÕòû¿_Æáÿ ûº% qœÙûó4à?ì˽ÿ6b÷èú£¡›*¨î†Ø§?€%,ª,ÍÌìF_deŒmI©Ì .NHêì‹>« íŽð’<ÿ/?(Uàøžð¾?*ÛÈHx_ˆŒE™üq´Æã‚àĸû,/(•om›‰/õ‚Ò¬œÜîK(Ö—º¡×Ò\C=¼‘ê;‚R\&|Þ²m˜‰ö¢¼•Û0鵨6L8Bz+µï 0s$nðÐê+îKÛ’s2HÕºL…­½AP”\s¶OX¨«ã»ðÙþ†á³ËôKRש¹õU`¬[Æ -’š[_åyžw* ÙãBƒÎáð†Â[²i›]kh>/Ÿ^ëH¢[Mic’â9ÿ\š;¼G¾mu«ºÂVÊ·­FÞ– +ƒÏe$ïmJ Š•TªG‚ÊÇßËËì¯eóbIËôê Š‹¿»¿?‚ªÞEÌו©®á=jõ:sð õÛŠï‘ÈmgÞPôŒE”brÝ|µÚÈ.€â f)+«5S6Ž¥8ü ¡ PÛµ–5éóó³ý *ïx» 0ìšDdëœ8ÃùuXÅ’Æç@ïhÞFšŸà@¤å\$ì0ZÎEºªßs‘˜ë>í ­†O”@Óòƒ¢ úŸÚÊãx tœ$§ ’{àZZjQǽÖ© ÷mcå&Ü‘ x_\¸–}q;ŠRŒ  Fé¼(÷&7ïш–ûØK–Í0R”â¬-žA錓xò–^>ZÎ[z­ üà:aEoi÷ë- gL[ä´*]¤m)åd&¼V)JÍôZ¬tœ:(M(#]t@ÙÌW;í^É Jqä˜i÷JF”ÊT@ÛßóOg«yÁýåéàë°B…ªéðdeuF¨/Åm ý±G'ÖŠÒYËJxÈZQú£¥(Ê%ÁÓ;~ìÓc¹fhÉcÅf8\ë}‡Y£€´ÃØê­¶‰ß#É[/å”qõµ^È7 룓 r.[Œû£õb¶øJïhÙ;LØp VÖ›kášú:ý<}ÔöôÓ'÷ÇízÆó½}¾¤‚¸+¸B¼èJ±â,€*¥ÞGÌÁ;% {AmS;-åº1»ÎÒª¶\7f×a%»V¥M˜_‰ÈÉ1'pá[;Øî÷q¦¨4£OnŠ(Ìb¤fý-ÙÓjkzhÎÓˆù²Ô¬ŒÀÖ¾¨û£=ÜqïÅ:m³pA=– zZÖè‘ b+Öæ+yƨi½QUå¡êz™÷ôŽYáËg=åH;Ç‹K ó>N¬“âØÿƒ E)N² 25ŽcpDѨ’¸ ‹ÆtÅ5ÅEKW…Då„¶]²8q|®ª”lE Ê«+Å×o— o(‘ÂŽsbðïû ¹Òœˆæ<®MÒ#Aifæ`,šHaY*'>½©œ¨Œ(»{Å28ZáWVƒ ×bÅ `·ªl~Ú2nûCøM¹“è¥áÞ}N½Û)¢¨$Â:¶¶éJ ¬×i®~üÞ³>UàöÇùù;ãz_Þ[ºÝ×h_qí~.ô%JçB_¾g1¶²Á*©ÔLð¶½Ð²’²w^ B/ûYÎQèÎržmZ£¹moD¡—–¢²³D'”ßtˆNÖü×x+E'@jՉߔNàìëmž®e1 ™N{'ŠgÀ®” 2‚ýççHPŒ,ÆøùÙ”É ^<ÇOú\Œ,Æ4~ÒçÚéªkϾm7ÿýá©6¢ªwTß¾¡|æ °¬Ñ5æÉ#*dsµ÷º= XYŒ}ê¸TiÌÁ¦'…)V ¶ýda+ò^ŸØ ÞKj® ./Ÿ$RB(„"ËNJx–xÑåîŠ×å¦×2951òy‡RPÛ”P jb{é*”¢šˆBÉwu¦ÄbP²*ŒDÖשÁ$^ËHe <@+3pT­ÌY§(QI œu@½sÖ[ÊYÏYÏY§(ž³ÞÏY§×â9ë•ᬷ”³Ž°’ƒÁ °wÎzK9ëÓ9Xâ¬#̰Ê1ðlŽçLíâWš¨—¼5é×sƒ×ò²Ú \+HÙXh2'¸²|]D•"ÿQJä¿GQóf™ðX¹=AéLOŸ:L¡ùÏmï0…–›xF‚Ò¬\ÜÑÈÒ]0V"€S¤)xYÑuÑÇQ­$Ø,މ¶í¹Cw@åë£÷¡=  '¥—`SxI~N·¦’`(dFLYHBÀ­4/ì±CÃlÝ€@´)•¤_9"SjY¿¨#(ÅÊßÅ‘(,*ײùX¦¡¢‚¦t EMéÄ>F¦¬Ä¾ëJ±ªPð\^Öh‚k!†GS “%oÑù4btn’üK=†F瀊ǘ-p‰¨¾û—#Œ—*ŒI*%…QJä>Àx)-ÕÕj˜ÑJ²mBcS£,+E’Ž1FädÔÐ/`TÅg÷}ȼp2^eðáKSAbÍ@ó­Q|’¬ºD pÐ¥ S¾œÌãµ’$,põÕ:ß&Úlm¢ã\‹í5kOë3T^DvÙa>èµ4c €ãE £ß„ð0m´„p¼ØJ˘Žï€b„ZŠ2ŒÐ$®äZ‹]4#¿7¦~M`h´Ä4‘Koˆ`{Vêž+äûdà°Ä±7‡e¾Ã¨š‚ͽ?—‘Áš1%ËYìÖ^e@;s(‘ö£ûûŽòÖÆ™+ 5d›ÏÇz<'(E¥²!cóÝ|ž>àK3ÇVØxZwäá»?"Æýj`µRAבh~Ûöô¤(K¨l˜íÇî\_j+Ès Íðh¾¿ *æñ7Þ4äbõϰžÕÊã¡|Ùš(nöì¯×ûß>WØÈ§ëÓŸ.ñ76ýe™‚Ð'ƒ£Zd?î=¦3eC´vÞþ(Šs©ÇMÍðKÀ¶àÃ4d£HÒOnŒ Âµ÷“ãònÝ?Ïá¹D׸A&ÂB›Œñ¯Zìçh±¯½²8YïÑóÓC’ÛX‘VÚPy'Å•VÚ”fœA³È’AVÿP¥àRê:Æ*Ñ¥¾ J1äæ9¦*å k kdí)/+*ÙEzбNºcV[IúüþF/†'ø\Av”ë*ÄìŽr&ß2Wãî(g2zóTɆ®à‚ûDn6Ž%žL‰ÜlœLn†£‚+¹†ó¨"Ï¥dý#¸––Ê‚PP6|A¹Meó^PÞÉnIÚÖ‚rNÚVLRPÎIÛ6O‚Òù™3C©Ø8Ƕʑ°ÉUj›/œH‹ÆyYU Pm¼ÝÐâsU¼§Ñi/;›ªä¢Ç3D?õƒRbœ÷çí²††ÓÔÆ ²Ò²b¯Êðó~ÏJ›wqòu`VÚTVn•k Šo•£(ÈHcHQ9QMm„çbÓ+kés©™{C-7•—ÔÔp%¯‚¨Q[KŒ/dõ¹ø¶}™×ˆŸ7ß9pß1^I­÷P¸5^½%ve£½$Œ×²¦<—‘¨xt÷V((cƒ«!¥¼µæ½·¬Ïêiï$÷0Lùñ¬F<}%+³ÁxyY… ž>îèqaB‘£ÅßaS(å¬H?潃§òîñ=#AåÕFÛº†}ˆTc2OP/3A OX/3'@®a9|CA‹a9þF-†åp ZËkðÖ”áöp$Œ¬Â(!=œv˜à„oEÝM¨dýI¸–+‡°®† ¡€`kB½A)Š÷ Š÷¥(Ëjn¿Ñ’2Ž—ôW^«d«¶‰Àm3ŠÐUÏgDiAm)ö¶0lâ7Qpl!­˜8slÁøžle$žØ‚m»èñÄNÖy„çbÕúÆ”0´…—ˆ™T^µì«kñ )94à ½×U[yëŠuøD¯%[ ÉÇvŸ9eɵ¥¯Ñï)’·lÎC¢Ì$0bß[Üw)Œ$0bËc©Œu¦æÔue2ðÓ×Ò•sƒŸæu5¿TÎ ¾¯W©Á– rÒ!kƒ&PâÅI‡À¹PÕT†§×¢¦2|¥ìË sµ”|Y1»bK#PAg(@ÚÒò_ÚN?·¥ãœÆD?·¥“œ(*×àÔ&ú¹}q-~)J7øu–û®`K ³—2,ÕÙÎ)8F”*¸lTý\c¾ø=*’:ýOLQ6Ûs-k\ûì`~)Åå¿¶kqF§ÒOöZ¥8ÅËxµJÒ-Dº˜UFTÆ…7”Ú„s´, ëJ3´¬#Êp´¬ÃsYŽ–u@qš·¸úFTÅ¡") P>“y˜R›UVn³›Šo³£×ÒYÕþ]Ó*'ž£ñŽNJ@y>Ç·:9ÀùßsY0á{$­½(VrƒÌÖ÷ %`¬.XÒõ´ÇÈ€Ò™6»-®…½Cé\øRÖ½Íó9€²¬v1 J¾¸Ÿ¶­–TP1úµš~ÓiÛj#íCø¶yµ÷)å'¬f S"ÅZZP;¶ìµ‰k¥æØµeo"(¾e^Ëp9dX}ùÞ˜|Ë­ÎH_ÄÆ«~‹k#Ê’N->=)ÎåtjïôZœNm +“I³ðuÞ_–y?ÁKVRŽÌh“²Ã/3ú|»Ÿq~™’kpZ‹†/´F1s›j–o´íS¹ÝÖ{cøY¸ga­± ³°ÖXQÿ;l­qÑ OîFôóv­5^2>ƒÒµ5Ahª¬ÁÀÚBp˜wT)š¨ÁÓ*‰„„ñU²^: tÞwÞE0îȵqÂÌ!q‡5ù¸c¯wXÃÄk;ÛwXÃÄs{þzüÔ-A½ÇËÓ“¸Ãš|ܱ\‹ÄÖäãŽÈËÆ¸Ã1î˜)*0t'чí¬2ÿºg}@™|ÓÂmU‰…pX¿*vç›ÛÒV^f[v¥ †}UJÜË©;®9™¢úÁ²P‚UúÒ¼ ç²›Ë[¯E¬Ñ^ »{z.# Ð*Óz+rðaÞ“Bø»2ÄTr¬w¼2ÄóŽaéVÝX —ív[†csëàlB»Uÿ]‹›uùm‡ï±ùø8 lV?âŠú–t«¾+CüÌ8^ŽQ†x.!>jØÔ­šëÒÞßc%õrïï1K0ÚÖh˜K”€˜{æÄ×Púõ¢-"’C‘§‰4”&bƒ¤u‚4Jv}.»hTʳÔqà°‹6«[+î¢AåÇk¦V†6hA+`?‰f= SÁ°ï1)¬Ù`%…5 û‚¤7¾—‚ÔÑ³ï ¡Qpz •´Nà™)x©³áùOÄNC!ðºÞ+Õj»–+ Y»cŒ¨RÔîˆ W”ùrKµ;ÅkwP”á/Ä®4|ÃŹ»ýÊJY`¡î2ê脬Tãx9é$ ¤ WV¢ÓFL¹¹ÒK(HĺҋýÍÃDPló•SÝ›ÕÊ•A¦Z•7ú¬è#vJPÚsN•ŒžqÓ¥ä¼SŠqjº”œwJå]‡ê:(³cO®C€Ê¨¯ªŽè:(›KÎ'×!@eT×rS®C€Ê¦ð“ë Xס™¢Ó@ç/§´ÔfÐàoÔ’+œÉ2‚¶×8Å1§ùù=CÎÊe´Ý)­y†QiÍsGQŒ.Fø.Ñ bT¾&}¶^ÃõãnNÑ¢PÙ<æFˆïJg5uÌ’ê=ÙB±Ÿ¢,CD„"žS^v™ƒQ BiKjN’ú$æõ»’ú 8õ1È“ŠQÃÎe@™Ý£eß‘§î<¬cQJü±Ìê´`Ž¾Î x.Ã͉s÷ÕÜaNhÃÜdNhÃj\?WG!xz›§dΔ’é´“4(€’ (•¡Ú¼Ó,­fÜè-AåèíF/ ×Ê;Š-K¬9ïú⤮€~{N{æÛ^u©hòrBô§Á7Dˆ/ú2«û89SðEâ阒‰t†žD:¦d"¦#‘Î;í"¡'‘Ž)ó‘Îú¶S¤cJ©”Œ‘Ž)ùRrŠtLÉD:«ë¾™ò-Ò¡Êoý%•Á˜PLùwü|>Š)ÿ>ŸôŽïåß%˜è÷ò/ ˜òo?}Òçz/ÿöÑ£îŠ+ÿNãAyÆ¥c<Œ[þmésñåßþIa%BùaLkÿ À“žðá#úWÃÒj kl²ÖÕ›‰ 4W1èßMz06¡(ËUÂzGŽá‰Ûš‘ž3ðôåR cŒåzÙú”¤tÆI‚B¤tæí¨“lß–!þ‚§'r[¯Fëæ0ÔÞ×[c_o;Ÿ—saƒc_·nÜ”¿N§¯eSîOEe®[~‡ºíÛ}.›c#Ÿ§[;Q”˸†Ÿ¾ÇùU¥7´¡N—T.þžÞ¿m ›Qª¤q¤¬¿q§TD9âÅyL”@åŒûD TÎyšç(€Êª‰$J XJ@CŸ+ä;ûçQ‚þånnV•c0¿vãÏ=~^PA’qU5Ž¥˜ˆ)Õ«†Æ!Â_v…ž òþíF¢•âL\»á㯃ÜPEEÖ_}T–M Þ’NµeVJ _æ+¥e[â8ª/JTÌ<É+%Z6ìÏå¸(³MYÅJUb3ÕÅ6S5=A1ÍT˜U¬TÅgWv¶Jy1kÏåùlçr­PûÕÞ°#(•Ý– ¨êâÝðn‹;Vs47«4oÿ»¶áÁŠ™h[it­ÖlúÐýÏ÷ãëû|î Jå›õÚ¬_š”Y_›$žÏ©¡w4ù&‰'èqTš”YÿEÜ|úe±ìîçf&(·{þVŠÛpëÏU%Ô¶¬ÞÖ¾ÞÛ²£õ#Aù$ν ÃuÛa®_íô=*ä.~pjZf}í¸¸þ ÓV¦æÌ ¼ÉgýÙÞú'}þRåû1)‚°uüÿþï¿ëïln‘4ŸÚ{Ûý`†qp§Òšg¨®›ü#ú•àË´¢_ c´ ]»'u*]‰,8­½Ð]ÚÞ`+%.ó¹ Ÿ®&Àïv˜(jg¬i˜kô{ý|¬û$EYjRµ•*Ûî6ž¯Ýã› òÓzÆ!@å§õ°Lë'AynÂ~c`ækƒ 'Óz;íP/«±ý= ~~Z_—i}€©lÃѺ‰Ó—D§õ-xúùÖN÷v¤¿ 4¬©0Àxeí•ÔÓ‡d&¯+s´tß­šÛ¯:Y5WI;%;}žôZiU/e3“ì{›dôZîm’õë$q’ETõ6Éz˜d#Aù·IÖÂ$›*“„¸mÍóçÏ –[Iù$ÌX>&XmÊñ yÁ¦›!*ëó•T»‡÷dÛ»xGWäëë±h¯TŽk† µr%S?XÖ¥½~P¹Rl¤«G‚Êç4öú l¾Eë€ârÝßA½×6=\¬Ês¶dp\pJ6ÔŽsÕ±ÖÏmÒÖ­œœ?êïhÄÖX'ˆcDVq¢TîëHfI•“÷¬€ó6x„w/à‘òÎ΋¶d8£ËX…à!‹Râ×9ÙªdbáÕ¡x… Óàß[Ká)6ø-‹aÝ6¸w$v4 €öéÐ6Ï«ÊHµT¯q‹Ãú•"ùʉª¦°æT•ČŜY‘ÈRŽa~U‚¥e[‡ke™±ÏÍße9’ð@ïÈ2cq¼*‘ÛÑkùL«ö”IUåYêxb$UD(ã¥ÎØ'F t^×I€2Ùy7r¬ç"käˆã#G”ag䈫\؆îS:)øBà#ì_íåñzöMQùRô@øÊ+ …•¯ä&Æ– ø&FŠ2\Û$Œ½×<wHO¯EߥõXß%øÒ¼æ¼YH#Jå%g™}%çy%9m{ÞFwe–áo¬„]Ü*_ñ‚'÷'°lµ žl›ûúÙ®Ö,mOQ»àÉz©Ëº®>†ñÑ/áhKPyÁ“ûO{x®¼àÉõÑž«boÃáŽ>w²êSM‰°b^+)]ª¤xϪk· ªkJç5¸—½ƒ¢ÜøËöi?çzz¶§?‚²o¨aeÅ=Ÿñ{Â)ó§Nî>p¿ñ««Ûý7ñ7BVÄñ7ŽÅþF8ø þÆë ã6„‘Nà¥9V³JX™8é´i†k)¶>EªðAËâ)¥¸¦uÈaÑ ·†Óv0\E¬'~°’GFø9FR<­IŒ ¢ÌàxVLŠNBŵȵ©E® ×"7’x(TªM-r€ÊµÈõ©EPwZä•çÎì-r€ÊµÈµ©EPž5ø†; 眯W… »¥u¥Xàí=ú‚qTj¨£’/JÁ•|Á9* }rTòEÉ™íG%O„k^úq¦Ôã űuºf¨g|.Á_²ŸëPæ  þÊR‹\¾°’s=vÅ0=kà7ú±g“”ò”Ó“ÉFáo¬ÄlÔÐT>sºd<ËüY|ÆXÔA4™Ž+¹çíû” ôe™ÊêGàycû>ùxê“™…17ä‰gLfÂí©gL¦_"®Ñž—k!^\¾Ôb¿DŒš|©…~ ôâò„ù“…ÕÄæOFt¶ý (ÎON|€bEgŠ2¹jwÊbøR>ÕŽ€r‡r0¾„ˆwù$_zÙØÆ>H~Pøô¼”IŸX}^¢"¬¾ªäü„×dGû½<ÏYYï-ðJóy¦µÛ£%(ÅÚÌõxÆHRá÷c ÑᎎãA‰ÁåUʼnºŒ‰Áåß#(ê2%—'Œ‘Q—)1¸ÕÎ[òÚðyò·äµ‘œ»› žÞò\Üznà£eGX™tÅví¬{¢<»§}ïa^û|lµÎ¯½fèuàw…½f(ÅõÅj³7ËÏN]Àžò 2~*ˆbüT†S¿•Á{‚âüTp5Ùúc¢g ¢ëå<¯pG-1‰÷;š¼øæ‚J]o,»¤Œ®'N)/g¦)et¥ó"ö˜Ñ”É÷¢#kÀ' ©÷¥rî&‰QéMõ^ˆâ±ìV_ð\>wÀ P/'ýž ŽõGX'–Õ÷tº”Îé9lO¯™)ÿZ{˜¡_µ9-'_Ôs”Ý÷¡3¬…çûùVwoÊ!êx­~†ó—9›N›þãš ¼Ös{ìX”3z¹ÖX¶?¿ßË¥;\kÝù–X÷Çå~krè\?.͘ž8ª–]á¶íï±þ=w°y˜DlúûϺžœ®6ôócèNõ¦2ËtOÐ=@13LI€bg˜Ö“ÅÁ|?ÎÙ‚oMhjhOô¶äµÁW’ËHP¹æ‘‘$ ,g&¶| {óˆ'‚/Åþ15Jg Ó{ó LFñsmÊ‚¹·ZÔoà7š|‚¥e™¢˜²ê#zkòeUÍ·à¶ön”–Ã=ñã­•5Ÿ¥òí¯ËØÃH°É‡)yzx"H‘õôxïéÑTÎÓcLžÞV²§GGP6Lï-…ÞzÁ}[ ½õy­þµÃ[áÛN!‘cí)…®äH§”ðôNñÓžbõNq ¤m"€x§Ääi$€x§øh'€ÊæÓ¢HA) r ¤S"€Ê3¶jÞöNKækÞöN3æÊËú•VòÑ—õ ×UBÉ­_$/›Üúd%ïÌkªéоG|Þ¥¦Ožw©™Rc…ç]júÔXá}{® ÒzÏSF’ vNÜù A윴óa‚˜H†¼´L´‰&â]%ŠÁQÇyîÀÝ’Ô‰ó,ÝgsT‚k±ôÞS”âh°×V…H{€Q­ ‘ö‰Åªh{b‘ˆ¼Íûäâ«RÕö¦RY Ç«Ò"Y ’"•f… 6X@j…$_ñŲÛÞfê++ ÄÀœ¨¬$@qþ3óe²Vík']\'*Ç7£î6_UüYn7‡÷Õ‹ÔJQß@§¹û;àëxs©¹EyÄUf­þø¼œ JÂ8’‡Ÿæïz?TrJ9­£‰ìý³é¾èµâYî_U!Ž××ø;/§w8Už0q½eðÇÇßßý§#¨=Y³Î‰×§ûéÔ~TÅ©ÀÎp­£B=i8§öOè>Ó ©ÇízÆ´UÞäm’枸NDžãµ¶²ÎdÃü ‘ç訴'¤|)”¥÷¯Ã—R;'î<ݧ%ëª×‚rë¾®òB,ë¼ÇÀÜó;2)-xË–ú†ç0CÔäáIÔWR<2kÞW\ª©Me|ïEsx(ã{ï¹–Ϙ”´ñŸ˜ Ž_msî÷ñ€â ‚@Móž™… õ¨ð¡HT8WC!zTÀC!zTÀÌ Å±÷j¹Ò9F†z-ÚÆÂH(%#pèÉóA‰Mëø\¼ìa"Šù Å(–(QfÐo2„4[ã¨"v’[Ų>q¼²éÚ¿!ØEƒ ]5 ¯„î5ÊDo¼ØØÐT6A¼JAz;HVí5´?øà¥ö àJå ¸{#Êæ)‹'L“ºÛs…¢„¤ ኂûjûDù …TAÊo Þ?YÊï“ xÊoKPÙ’G¢üЧüÒ;²%ø†Å–<º‰ |&%½FåP…â„)×ò{O¯÷Œtuz÷ ƒ,¢Ð"좡0ü½ ‚…BèÝÁ'ýÉù ®å8rÄ”"ÖPT‚á6æ•~9’#Ú”{ EÅ‘#¦”{”aòL@…äQkð …ç¢ò.jC!|Ûû©6$‡ w¿žyù§ÞP‰˜’E5CD•¼LÑ0À(1åX¼ŽD???÷SKPy¢ÅmÄï1S–KýçU®ø4P”a$ @¤7”‚—O1Œ—N5¾!ÿ"Á¿1¶[ÖÃ4öð\Ù5§Á· £j 6v_÷ZˆÀl)ž†" 4Ø’uÛžÓ:‘3\h@û„¥Á²©–ìVB+þJ9/Z)¼R¤Ó ÙZ^öpo\ÖJûÐë„u‚ôñ¾YÇí‘Ö<”fª"5œø¬ãèÖ}ªŠ[‰Ô!˜«¶©C±ÚJ aU$¼ E ?ë%§ó}®1ÊÄY8¯]Ò¢\!µ¨áyÕµ°,¸RjÛ¯Åg‡WsLØÝ»ÿÁµäØÖU§9á…~£°J ,Á _G:u8Ëךêô\²\‹…·"¨<5½ ý˜NÞ’¦5fj^*±¯ÕS/~Þ÷Ê Ȟ¡|©×Nî;"xωUt$‚àk¿gš}攆Ùá5¶ŠÏ Sã9:7ªÛb+ŠÒy¶L]G®b'1¥Šg‚°Ç^ñ/Ñ/AQ&ÏgÚk'Añ¹´T; Jà<4`3øVüšdjHU÷]zq¼t^ºßD qGš^ãGA˜šÐð*+æ¿àÛNÌÁ 8©9s¢AîKƒP 1ò¼½àD½jðƒèW½½!S¼ Í²#Ç“û‚*yÖ&Vˆ”â¿m¬#ŠÄàŽ"k 2#Å2#¶/ Q,3¢¡×2Œ×€(ÃkýÖM¬,(+ðø†Èµ^Pž5²ÙcÑU‰r)sKPï§íUþc9mo'ˆÒïgòçz&'ˆ2ù炸vA9QâŸË‰ÏÕõÅ>×&K‚¨×ºhƒ£ús‰¨ H¬'Í UÜž6íÙ¨Ur¹Ç~Ï=.(%é??aF—šÝE×FOø:J>O¾Zu´ðô’àÈ€ßcé$Y’ó!Šá4ƒX‚ú±„ž x±„– 4c×…kN鯣¦$yÒxf2…*5d1” UƒY DqyÌó-(%ŽãlAi‘qã•Z˳Œ3Xå”ÎÛúÅSmߣ2bÝ ŸÞBýÐò ø®™µ;VLeÙH§_«€rb¥¿ŸŠ©ôßâ.ЍÌyâcnïm=Ó;NÇ^êÓ§±'(Åô5í#Áôé¬løuI¡w4¹¾¦© #EÙ<ãlžðm{¶v²3‚Tàk¿ÈÙ2…9[¸§éBˆ; ¦³ JŽ ÷µ3áõ:sðZÍã'¢ˆ`åÖtyº‚qìÇã÷ô#¡Y‹æåœ°c"Jßö2¿ g\Ýå†9¢Ìaç[1?±ö~ë¿çÐÔ•ï¨æùù¸t·Ç“ t ‡Å·ïþ®íßc G”!2刺]ÛëŠùpº=ûçý{$¨ƒäùšJ[Q÷¶~éµHcéF:_.výù½-_ÑAyºoGÔ³incÛST ÜôUÖn{®%ÆoéxEÉó“ðº¼î¦ùú;uW +“øÝ– ¼5?Íù|îû–þÊr'ü¹~{ºz^þh)lï"Œ*ýë[ºÖõ|úk°íü/¾¦Xëë»ùëë«® ³‰‰MôÍsy¿h+±ÃÜ!¹¸µ7õu3ÜîÇ›ærõúÁi>MÜθ`hËy¹»—Û‚rRguý(ÞÝ~ë† Ja7ôÞç|ië[½fà J¿÷L[Ï4l”:-ŠÇnèUÀ~jpÁ¨^Ôíönèqõ«léµvwû3¤‰/í0<–“$½VESÎÛióëq©¿¿GØuÒÙè<ø\ËAà«]ã'‚Ú>€ÿ¬¿qßÚ.Vy%èåÞGµ «"Ø÷>ëa –‡nîGý;C7÷S™vîóe‰©0mçnº¿ùðÆ ÛÎM‡£´ùb*¤˜—Š©´´TÿAEuA~.®ªÿñZÔ¥"Úlœ¡Ye¾Ï÷¿sMP/Köº´¬}}óì *ãÝs¯ïÏ'Ο—Š*íoý¸þàAþÅ¥‚x÷ÜîÝ5z÷ ÊíB[®e‹Írzm–¸“ È’½ZÚl‹Ï²¨´±¥Qž¤§Ï1 "3.®d¦dSËñßF I hCACŒ1”7J"ÆÕëq£ªyb/¦"” NIYDå¯õ0ÃñUt‚oÎ%:A`8i¸€åX‡éÖUñwHÍXP^L;uAåC¤J-¨ÀSl0o [ˆÊͬØBlñéµ8åf/[pí}«îN(¡¼–‚;«¸bÄ´;Í-(-ú…Á!—ˆäBX¿bï¡,úTìàÍÖj’ØA.tØGÕÆ„—p9îC¨e­0^@²[PNpÀÇ‚ª„¤ÙÜÂyÇzfì×”LûÀ)»­–n=¬_T. C.ã7äJ\ %DDåÛ“Ó¼wJ †¿`ýrŠ÷ÁFÒÅ‚ÒgÀt…üG»= äX½©ioÜ[PVRÃÅõÞ9AÍhßk]%8ì,“¢çÌs‚m ßqÞ;ÏykP*[P4|jFLã àû=n-fAiF;¦àeòL g«ªÈ3±I Q¬øÜ‘o Ÿö¦D©÷3À ìg€JIЬ¬«•æi¶X²XP’+Ξ֬XúïùïÒ OŠÊï䎂ÞT½ï|UÅ“°ÀŽ(®ÀÞÀŠIü"Þ ìÐ4‰(Ã¥Ãp$<›ûZÓaO‚Rœc3œ*–^>í …¦ð…P¾ÝOʷ ¬&¾dš&·=@Òß+ö4´·´,(-µ´DDq-Œ˜¦eø ÅÎrÞd¨,QÙíY/‘ ÞÇ»ÐÄÏ7œ[‚¢Ïîõ͸¼ì¿¿+A鬛ñ0´#½–y§ÇËOwe3ºaãÃ4ôéSDqºFU¯þòù¹ÄšO‚ªHâ¦Ù7mwûùøêú ÞÕž6u±¿Ãóêbóùyxú¨.vŒ3Ûùw‰3›Œi†zØm½à곎- ¤¦a€õÄ ÚÍØ(° “eY‰1{–%RkB ±P êÇîA ‘5>W¾¨Tûu­ˆ(©ø´§‹ƒ–¼¤X›ø{¿7 JqEWعIãô[ÓúÔ´°_…J,Áþ¼P†¢ãà‚ ²Âà†*‹BV|¯0x#(NapŠë ¸5 n(Š[ ß(Ç|·ÝU1ª€ÏÃ}.=tÆ[MG"0J¤°–„lQ×¾~< ŠQ×áDQ’†îœºvMïÈÑz€’PJ¢õL8^Jk ×âÅ(ÊäÉe¸'—…–Èe0ïË‚úé÷¶¶ed'ÄŽ £ï »mYX.ž[icQ:aA9¡AK³eQñ¹šýì^<}f9ŸÔOxCì 0¥B|Y¾I£nF˜÷eÁpÿ þT¾€Ûcl(ÍÐzàÔT–%›…Yå¸ÖÑ«|ÍQ6HŸŸçƒ ööÄ•ø~^ßÐêXÛÎýï@Pz_}—)±Éï—ÏsžÏ•„EN·Ëe l/·ùër^6[‚²D†a ߣ í¿MuGP‘D?ý7~CëH¬$ú5cÞTÅ!Ó¨ít2mg˜ó­BþçÏ×cø&¨Ù×Q/?¥ßGõ†£z}ÜEµˆÏ1ljNÓ÷Ç+‘’¶Œôæ&¿¢Ël£r+¢Ìµüûhúºíû©'(›j—[¬ ¿ß_߸ÊE”c ¥Xs"jÕÿ_ûÇ~~¿èsù—7Ôàú;Tàh*-Üш4•q"(&êCÚE™w@h ]N0e)KtâÌ9–þkûöçûñõ}>÷¥8ûôéIPš³Oǯ¶::[ý¯*¨÷šAÛMSw‡š òÆèkë }®¼1ú<ö= Ÿâ€e¢ûõ«»ßAÎ>ýðÑÙúͲ:zÄï°¼1z{럘ÊkŸ6ÍñjĽ¹ÅLò|jï-ff˜T_Ë9IJý'Þs+µ,›äyꟊRœ¹GÌ%fØâË t1Ôx¨H,'(]ã†û³Ä(ËA3–‰JU° ®çˆ .@élGĺÏO•K8¯š²À&”eÔb!(*UÉÌG`†/(%iD@°V*-Xð!)ÃvNH©,gÁÚo¼Ðø†ϤßÒ™ðô•Î3D)†mÛàoô۶Ƨ÷\€µ>}=Àƒ¤…u™{‚b{b"©Ô…Ð{„IõR9­˜"Â>ßu´qYž¸Íô]Û}¬ Ô¥^Î ‘ø3þÖŸÝ)’Jbzñ÷ß--ÝÀѶ~Lc”ƒGT,‡oG"ˆ–ýj¼vßõ7AmÕð­ËæõK­ícèÛïï¶!(›kÜâ—£U?vŽ—: ìêV}Zx.Íu~N›>-E16ì.ÁZ³Š¥«>mGQ†+ À\ÕFê i`ÃÕ–Ÿ«éø®y­ÝÒ}AUŸl@×KJóÅ𔦤\XùP-]ÊÜ5ίª¾4л_P¥@ÚÓn•’èC˜v{é±>è -+Œ}¥[¸¿¡JÖb€¯¶µj˜9l5®Ñ«œT:¬aõ­*áäÞ4DŠVó{² B"–3Ê*ð6 ëžŸËR9c†€h<¿íVؼ JÉêt¿–,;2<=)i¾RXÆË廑yüÒèG‹oÛ³IÖ)•ZKÞÈ|S5„•ÉW‚ŽOœÒW‚Ù[ÁHijt–#ŠË‰ò eçeäá{ AûTÉžv-¿¥d-¿‘ x-?z-^Ë¢L~$ö“hÐÌ®0ô»9ô‚b÷í>QðÊ`E ^,î–©ô–¡à!PóÁ²¤†µ”§¡à„Ì<àµÜ‹Þýyëëî~Oý NCÁzÈè)m·Ò]P‚¢ÑÞ…U/ë~Åë~? Jsê”x-ù$ §íx²ºyÆù¥ aO[-‘%iXâéQ‚†åíµnÅõk×q$)ªe”á$ªÞ‹j­îP:ŸŸh»Ë³»GË4D)F ò&ª0¼:ÒªBãe¥ëhò½ œ‹bô« žþ¸êtâ}ÞÞo¹Ìïù§ïáŽAÒ°ìq$—]™ÒyU½ôÀ¾¢™ö‚*%·ˆXU©$·‘ýZ¬¶À”h媔´0'ªJ-ÒÊa’2KŽV~@™<­ cwUš|ÜÑ€Ÿ ¬àg…g9U:©£J¨ŠU×9>|–C•å….åŠÜª RqJ¨Jbìã¥J1vyÅ÷ÓN‰¡”âÏ9{æA)‘ŒXÃ,$yßCtÒDsÕ~£•A'¸–Šïx6QJPPYžk„ñò‚&6è /(!Úcd¥ !·Ùt¥%Uº¥òÄÙ¨T‚_-ɯ¾ž:ú8«´âˆ³c~£Vœ¥h›â4¥âû+m„lAÝ>á¹,KZ¾\†¨ßލì“Zí—Çœi“ŠÒ•¤Ñ…û£öRPã’ó÷Í“ ŽÄFPZz.+Îæhg”)„ÆìýV¦{¿aO3¥àQC}HÅwïýÇŠ¶½‘pA'QœÊœjm#Ê|°N-E¬o+cĈµ§¨¼›ÍžåW†u¡kS–_Ë+ÎìY~Å›÷¶)˯æ½ïŠÞø è^JÐÍíÐáhAU¼WÊZ|‡çòyG¨þçüX>µÍ Q*ëât=·0ïç¡ú̓ îxG¨Õ]j"(Å)IÀœ°…˜³‚oÛ¯×"J%ËF¨R žbvXY^ñ/ÅÛÊêw’w¤Ö%]­e„¬u µ_e9ơݧ–>~ɵ8âªÃk¼ö© ×å”Y+¡–Ѥ¬zWõßÏÈCÛBÄýÒ,õŠú¸ET¶/žùvR©"Þ—9ò&ÄåÄû2GÞ„³Uò¾ÜÈ›§Ëé ¾É÷ßÓó‰3?©)7±©uóÉ›€²¹q"+êaš!ôâØ3¹S ê¥ß\Îà¹àTNÊ+6£³„™œÝý»œª(¥†0•©×Ü`»|Í?ßAe†>5„JgœÀÛÔ(¶!l wdÂà<äØ6ÓßXeÔŠºçrªˆdj@± a‡;² a‡§Ï4„-ßljCSáZÖ1+ÈZ`S’òNòs…¦c@1\«=wâݼß~¾’@? PšË×â¬àT%—3~}êþ`ÀsŠ~ºú£Ãç ǘ;nY‘¶¼ìʇkéê¹lÝ=E™ÃŽu…ÑôlïW‚²o¨aC=»?‚rù߸LÆxÇÀ¹8 —®ñ7†Büý‰ Øßç9ꮚùpž …øwtö…PJ¼̱†RhØÙ+#R+áÞð­^ÚÿŽ*Õ ÔW©Ür:õû©T¾eï{æçP©|Ë,BûŒ¢•Ê×Ìb½gˆ3•Ê}ÒÀjDþ° •È÷(,xFtÙ‰–“œtBÈì1À]õó·ki^­wådÖñ7jÎ7Æ>ÎM+‚o>w¨$é×6;Ú’p¿CÖM“ŠàVÇ_³§ëo°\Ú´+hÒžõÚDz M= *«²¿ñ;ã\-ùd-tdY‹‘ r~bÓÊ ø‹wTߺJ¶Ź;U“¾ŸnZ³Dä¦iUŠE1¦•£÷ž¢§dÛÀoÔï­öèµµD†1ƒ§iÍ6ƒŠ| ­L>.ßš=kCЯʿ' Üš=»þó“ öýq‹®¢lßœN}ÝTÕóšæ»mûã|FÆŸ&Ê¿kŒÿ2‘ÍÚ¾Ì z-›o½Dv= \¾M¸~âµ\®M¸¹m¿qù‰A)âÑtɦgSÿ<ÇOz-½ç‡>Îж¿|ÀÖIuùÝõâ^Cí P6ߌìT@¹¬ÿÚÜ_Ÿð¶ßÏ_7¨²<¾æï‘ bÿß1âFŒaù AeE–‰Ó÷•É#/ˆù¶?WxgüÅ;vËOèc5V«·zÓþô¿ßÍ¥ Šy®¹…=M¶ê™røšgþ°Ö¥$?ŒR­• ?ˆŒRÍk3O©«97ZtE‡kÁ­ °´6¢p>½àâ0€Ê‚rBõ¥­´®x~’/Z³BSóZãÆ; BSßÍiÍìVp^Åßè¥(r¿Z{) hFz­\°ü7vמ ¸(„ßÅEàJ(. Àµ0¢*æ+SDù÷ÚèrHØk£ZÞËm¯j´8ÖF—5g¯Jç娰6 (“=!£×©Ñ¦½N{‚âj}¸o›R¬õÁW{p&‘¯Ukc™d׈’¢&ä*h£óg¹ËA±Œåž^+w–›ÇUóIP&ËÞ{lµ1|ÍvYXc]GvDfßþ„³¯q¼2þªWc_˜§yÁÖèzÑ”æri°æXžc¸FÒð†¬ž~᫵•ÔŠk4a4@¯tôhžçá»Å(€Š¬®Êõ©bÖ}Ùi{p½Ð/ÝC]$~iï\…c]„¢øºÈ ØºŒª;Šd‘ŠÇ*)_7µ×EöêÉù~¾ÕÝ'¼G—D²^ª'mªžª"â7· õó|üÖm[Ó;úLåœj,€ é í"ö§ú6L0ïaT BXŒßÓ×÷WÛnY–™ŠM›*6Sïšò´dƒ0ÍÔl0Xl¥âX³ùëõ§Ð¡ÝÄâßJ;½´ƒ0—¥JïM´Ú•yúüL¬·”_ü”(%æÕ€­·¥™öØ'£b“»éñ‚Ò¢é1>—–Lq“wš7=nn>½æM›Š5=><gz Ti@1¦ÇØp(Ÿ'Ù#]W;#ÐuçŽî-Y¶SSyW;+4„ z°vN0ÕÞ“Ä„ö“1uñw¬ú[ÒÖÎq¥Š>5KhWÉüAñüAñüe˜í¨ÃåÕ‹Ôr¼VàçýóÞ㺄ð㉇j%½š¯|¬Z¥×­ƒnÙ@Úž¢L²9ß6UŽ%ZxônmÔJú-HùéÏ•Ÿ÷×Gs¸cÅPÞ1pe­¤7ù|U‘·ú¥ÖCº:6{롦^þŠÖCšª@o©¾¦<–ƒííãÞTÖ è¶Ê0¨ßËLPÔ (jeõÝm\¶£/úôîˆjfG€ª²fG#šÊ“fÂíRË=§zý‰ÞÌŽÔìGµÈ»Àía%gw4Þ‘ÊÚý ÝÂ4gw4Ñ_Pšw»£±;B˜%>FW$Ï\¿¾êŸÃMkwôCaUŽŠó=Ïõ÷'…ù¼+Òâ[ Œ+X1á¬-W¤®¥¢Šì"UJhÍ«AåQW|#@ҪוÅFŠbìuQ8DsJ襙ñZl#À”¤7t%‘÷ÁªQŠ!`bi†˜›gMðÐ\U±}Ý"Š77O¥x- ì¤í V¤+ÑGµ¨^ޤ0íOÁ®÷ä³×‚=倡›ç©ô$Íà­LEò’ö‚RêÞX¨½ä ƒÍ:‘„²Í6{/8Ñ Bû ˜ÝÖÐÖ­CÁQí¦Ô<©CÉ™·Ž‰,¡ƒâ[óê}N†¶‡:îñK FÖqŸŠ×q¿«ãA0bx gê`Äðt ×bÃSH¯sOkAn»[ÛõßQF PžêJ^¢®äí:u?¿¸ v8Œj‘bg7EXÉ)ÌO…±áéágòáé|¸)ž†6ž- Oƒ¡áiÆ2`V²Ì›à B˜NÇ—Þ]¶—Þ”ΘáµÉ O'¦ÓÑæîÜ}~>ºçe›;`aʽÙÜµÔæPÕ›ÍÝéî6w€òo.w=u¹TxçR“;Õ‚1¹°’•'§¿²d\$Ú¦ƒãÝŸÖx.VIn3XÊ •DúÅÁ¨$÷§ãµL.BÈÁ³B b9²¾p(`¼Æ,=¬÷~Ù%ÜLQ´ lù5Û&2%QS(^¶h 5…æGb§s˜ÂH Þ{šÂ2ŸåZs÷÷ü‹¨* ŠÚþ<ïÍî¯`ˆez<ûj~^—“Ìòÿ¥IÑ!¾¡Ÿî£žßsKP†‘™UI´h8ñ˜Âóí>ŸHíŠ-iàZA|C1“eJQøD8LÉÈumE‡二$PqÚçD©ê$’nM)fë è`J9[÷¤¨÷l]ÙºŽ Þ³u=dë(ŠËÖM‡çb³u8ªr¶®§(Ï5ÂDR·)­Ø.ó¾4‚²} ”;S:Qÿß;ªrôïûϨoíþò||veˆJ~, µó×8¡J> lž$ÓOŸô¹i—‰Mgý*Ö‡ú÷€zÑ`¿¢ûÔÿ”Ïçëñ0^ÑÒß¿4GT¹ß7u¬k#¬d2— ¹0•ç~6ûR±fÉÜ͵íMQ`8]ããûq#êÅpkÚ*0_Ÿçå‡v¥*>ÖÏósMäDo@ܶþ®ïòòûs…Þ:@’>‹œ®åGÎ?ÝéDPöZÚâô8ííƒ^Ë¥c0ܱ§{[Ÿog‚Ú»ùN›ýú’žÍϲŴôŽ>MžK”­ï»Ëóçç÷“Þ1äÕcŠðç2žþ¿ÎWÿŽÆÛƒõ—a™c_ãaðË]éø¼ÂØïrѾÃÅ5$Kâ(ˆ|‹¿ oý½»âjöc|Fã¨F Qï=x74SÝùF•‚fb C4hÐn-CÿøžÇ?ŠÒyeÅe…šÊd”ú¤ô`”â”ú¤ô`8nä¦i‡ì @iFM ”e{¤QZà’®fK%(4È¡6ÊòúRcÊ>€âÔ‹@ÅØ(þк­Œ’»­`ÝQr·ÕÐTbY]ð¶®;«¡TDù7k*,\7Ãý~o Jå¿¶åËí*²£cQ ê¡ÏÇϹ»ýÒkeøþ«>òý BФ¤ŒÑ…˜\ƒX—’â60DŒV¬¢Uê 0šáÂoœMäFmdÎfGPg³…µU™³Ù”aTë!¥d´å4Ú¦Çyx¡H;‰ \x@©Œ Õ”T¨ŒfÓySRã1ÚËj<-Ae-W“‘­ÑA4²Å;†œÎôžJ…Õ×° ¬Ófø(Öð«Ý ¿&‚b ¿×Ê~›áEÎ>~ã;w-¥—“[Ììê ¬Ùâæ=á®­uu?Ÿ›iÆ©!ܵÿm‡ÈÓ%=ýóï€2;¼u…޾t‰6“.¸–•zØ SÄIum ¯ìÓoL~¸£gm±/§îÁ¦á|QN}½>\OP*£Nz¾Ý¿@»P:ã°ª*Ýa¯µ…Pàß÷ZË÷Ö-{ÂÆË–‡®ød°»|M »Æ*Aky–Æj1cox-­SWp|'Z홢<$ŒuRQ˜Ö€ÊåÛfØ‹ò€Êå›X”o Š+ÊãúeT”ÇÏ:&¼]Sj Åå™t¨¯[Éêk¥=Á!òxõйnW$O j˜Ä¼Ë©¦B Á¸c_Ð óÄK˜ö½¬x­ýØË™Ëi¨½~SY£/±F~žæ¿ñzýŠÆWð 5—f‰þF‚¢«\ =æùòùøá=ºò`†µÎgˆÂ>›% ëèsuƒsŒ¯¾úñó6ϱ̨RðqZë¶ÎèïËíþw¢Ï•(çíh²éÐ=¦ÛéÞ‘P n°u<›¯ñvëntT‹=I¿ÜDâà÷åçvjè,KªÐrÁËý,›>Y,“¤Ðo›ˆKè÷ ÓY-º½×Ø8%©mA¯±qŠ?Sì~&ÆiÁI} ŒÓ¼RPJµ:Ã{ ¬½€²¢§^KPz¸4@Í1Îå»ð"µO}®’ëxêsÒ*€Ê¼Æ‰Þ¸¶º FòhªBP1DÊ£¡öòGævŸ(€ÒŒÖ!PÅP±SÚ’R¦S²U)vJÃêDHJï ¨ŠšªdUÊ×^cX+VrJn¦b”Œg°²…§×ÌɶéÈɶÒÒÉhd€z?Ù`eKïh²;üê„OoØÓÕrêws ª¼pëwÝj#i4¥²rBƒýb¦:ö~1óN/9Øzî,ÑKv­SIëeƱ‚®’ó !¡¼FšÃ\‘ºj %¡Àòz^­? jO`Ÿ°û´™æq^Bøš 4Ùocéã<]à sþ¸“-ºæ|i¿b_ ì^½] ®ëŽûømÎõ'Ô‹åpæÔ<]}?§ýKói'Œ¯SZaýtêÿ#áß*ç TÎãÛ&tœwÎÿr6 J½k!µuÒB”~§^Œ[åf´OV¶/õõñ E2»;Ãa¬Ç€roUøËòLöy¸VÅTᡌ (ÿV…ïcþp­ðV…ÿÚ¬sçÃHēǡ ߯2|C/ ÿó"ÖáWSLþy„íyñëߦû‹Ý†3\c@}¸š}ëÎj6Jvóø‰0sèÎzQNû¨ÔVSw¥wÃúäßúÔ¨Žf½Îë*Dê!®çÞ JŸ3®<Þ ª¡ó<À·[Iš@0ÞËz#A)fë 2"¤¯Ì*öÄu ¼Æ°>ÝÎÍ0 CMP:·>}ýŒëSª·dÖ§¿‘Toy[Ÿ–ß0R”Ë®Oã„Õ¿×[²š)‘êd^ˆm‡nïá9vUJv⸗wt–… pîoà,k‚ôŸ÷<Ë;ým'Ü¥æ'¸åÀ¨+Rü`N zìUP‰>vëo(cÞ»K›å¤ Ï%ªøâY-pÄ…ÍQf ¡ÿw¯|Ø¢à{ñöʇÍè4Qê¸æXªÓôf0=NñÔj‹’uõM`[pçäÕ-y†‘°D§éµƒvZ;hG‚²Y»µ#¡Åéeð÷*-4wU[âïòÒU=¦®j[h®«ºM]Õ¶Ð\w|ŸÚ²laͬf"(Žè^€Ê·e­†ÜôŽù¶¬áãã€bÛ²ÏÅ=†Ãµ¢žèå³ÍH;YÛl+UŸ¢[p„ôç˜4ëláòÍ[ ¨øÂÓWl#ØÏÚFQŠqoOb[xÉ3ˆj6ãÀCõjbêNê ¶5ØF¼–¬Á6R§ÁÖ^)ŠU_8Ü‘U_ˆQ7 X ¶‘¢õ̱ÊgZõ¢kœ9eÆ-*E __p­ŒVž ë8=ÛR¿«¶G—ÇvYQN§;Ai6ú ×â(ÝMCQ¥\:,¡ge(Ýp~·„žõ}œêqù´é=Ûî×Ê+±6çq ×J\ÛÃáýÜý͇Á/ÙÃ;ý•¥z£o¬'ß´1”F°­÷Ä0ôecØé€ÒyS¤oÊ0‡÷?6Ù‡ÌñFC{ªÒ–•`ûƒÖl–ÊŠÁo„"V÷óós?õ•O%­*lôZPfü-3öÍýyèµòR™u³_+ý§È µeäáFp-!^eäáæ™^Ëä÷¿iPE~Ø’}û"DÑŽ‹À‚jû"  –B°.#½–yÿ¼§íóžéseä˜Çíó†‘PE>mpž>?·ö€zOüü^êù«‡E%ÙCBà±îD#.Nª8¦ öðêk99}·1ýƒ£š#Ü7ëZq¸Xžpÿ›Up„ûM½òÜVI.UèØg•âNùÄ£Æ*ÅÅæ}r$²JKŽDàö (Æ‘)þ€â‰†Êä›Îb•‘ü l•ÔÐŽ­V`T­28]ùÅiÕˆ„}F±™…óêìy@½û¤ o7üÆ ú ÆnQ« ÑNÀºàÉèë>ÇK—#¡ÇK+þÔÚ ê–¥.hoŒ„3ž‰’ Z¦z€U^«µ “3 0^ZPZÞ{V[þëXu0)J1m”Ðjµ›@ál«O§êÍë¢E¶äî‘`õ?x$tÅ{$ŒÅ{$´õî‘ÐR@å<úä‘`õ?x$< Š÷H ¨w„–z$XÍx$´Ô#Á&µŒ?ê`ZS8•¯ —p#쬜veCQ©†UkÖÐ|y‡ 3c9vV|.Œ·,§7 YV›ϲz“E1Îؘ(“u–Ú-ïf·ªÄ‚b¶5Zp—l€Siaýà¾.—;¬…Æ +ù0áo´RK®Ä5î•ñ’©­aÝK—öfkøŠøim¦çòo9ÏÛ%Ö5ÏS9Okxîbâ%[W/lÔ·‰é•iÔG?Kk‹·’í'nYºý:GÔqïØ¢¢¨/ÑûµQ‘ Èñx1sw~Þ§>6ŠªÄ㥻|>†óX”¡‘|ÏÏîv;eÉÞãÔüžG œ,‰àãoŒqÀò¿ïÏ¿ž¢h_'Y§ñòƒ Ë€òù1ÊXÂy{ázöß{EPŠs…†üƒe]¡ã>ÔTþŒ¹ò®àކwšPY´VªÙ ˜ýµNªì`6Óó[G•XT¯µ¶Ubcχµ•¬Û¯;”É2´wÿk½ä5xKœñÞ¯…>Öɧc¿–ä†>ƒ_u… Ï¹GŽ“Xi‰(3`Ý?d›àZÿmzŸmº—mšà{tZòý©Šâ|0D¤»2^=ÝU1¢çáŽ>—ùÙº¬éHÆãôû£3Òž\O댠©™æÏqÞ¼ÆàZŽ?m¯â¨#Ae5ó·d \«b’5C¿%kZ‚â’5X!¢\‡dÍÉŠ2 ÛW9'¶ðÎøôžï:ÚåH¬ ‚/éŒg¦J’ý@97K¸`Y97ŠRÙ“]LžKú¿•õ$QBÅioõ·•‘|6±JTYŽÝ›:‚R\ïœå*¹wâÚÊqÊ›}r$³UÅ)oNÉ‘ÌV§¼Ù&G2@åV¦)9’Šw$£(Þ‘Œ¢xG²Ž ÞÉZêH(Þ‘ŒÞ‘w$£¨œ#ÙHÉÆtÎX£«<ßâÞ¢$‘­üûYa»Ô@ZÜmø~»?d©Ù*ðŒÝ½ãÃzÞü¹óõ¬/áŒY_æy½[ëý^aôŠÏòÍ´3Ûç½vˆwÔÌÙªéÈÆ[Ñ v/9Ìb‹; rN®+ |ËeòϵŸ‡¼}Ëð¹Œø\OŠbŸ+zYoX™ˆÍÞã%Ö~•Ž rnÈ-ÉòùŠ÷×!wÕŠAäÖzN­xX¹™>°g©g¹g¢¡(f‡D‘-K¼Ù²"[=A)FÌ 3†AI^ô¸š-xÑ#ÏP9>{Ÿxã–gõ‰7nƒá¤r§Ä·UÃîoÜ#h²ï‘Z°\¤Öω@¹H¯]Ø{ƒ ¢B:ô8ØP 55c‚ ©Öž±<ëIÖÕÀt¿ §–¬r!°gÑç:¡7”+—æµJñ‹HNðŒ{î~è®(¥®bpzt… É¾Æ;pG-¼GìÐp…‘˜g Câ Ë;‹ÍN’ˆ†˜+ä>Žø¥¹¢dðiwœdNçÝß—Äy¡·Pïâ¼mç= rÑ{Ÿ¼Æ\Yˆ^cqJ寅^c®¢×\«l—ÿ¦yÏU UVLWòó+1õ\©…^GÌ>ºRꄘAhÓ•†ûÒ¦ä”æJ+;¥Å;¥ÑkñNiA*Ù·jÍ®R³SwÇï±ä9ÄÏÝÅÂÉœ…c°¦¾ÌÓµ%(dn ä¼º“7#®D2çµP<ös®¨8sÆ©þXv"(—Õ{]¡ôZ[†â?ÿލø9öëÀ·ÑõÕl?g›hN dÜvf¶{!dDâw¯ WÉSµÆ7¸È¶O9J§ ¡#;ºïÍÖ&%§”€B%—ªåY¹"X “þHVˆF5élµŸ¡z¿¾;me9¡ÞÑ1õ¨ÏªbüćèÄ(ŸÍèÔxfr¼.Êê@ ²yN±Àmª²Jå…ݱ3É)+»PO•e6.§‰º…ßèX·T“rB­¿_N¢°×¾û©Ñº.îî*ðý—à n§ Nlz6Ó³ÛN—¼ÔîÎÆp¤>ŸëäŠÙ!§Y·)i`8­E X}µã5îCÚp½›3>× +žºP/aSô7tÚ±¨ç²2]Ÿ¥2þÒÃêB} Ьä·¬äÍ0<Ÿø!5½?מފÏÕÞ Š}®XûTö¹šáº?—e¼ìÖy?'ÖiÏiDM‰dètà…•w’¡#Š'/Qm":êéõæ…$C§[á^NÀ¢r¤Â½–Õ7ª5çî÷ïy@qjF¸b¦ ÷;Sa»tFîR½Ã(>ßÙ¢ó* wÙ}0Z|Æl­3FÈÖb×…3–—÷Þ».œ±R6Ð-ò°CýÄñâWÌçºwÀ½àIˆÅŽ«po}ÇØËâX]*2ï [+SîÑÙ‚WÙsŽÖÁ·Yx>#;êtïÆ¨=àÞO®ç-Õ4K@Š'Ζlô›8gΪ|Í`³mAæ¿#Õßwæÿ2Ae2§Ë¡}Ïœº—êïÑ; 3§Î~FïšÎZIS )J1¹<X'|~¶âÜóÉ ÙY>bÝÎð\ž×ðY½Æ`ìÿ\ËѾ¶»åð7¾7=³~›ûñŽN±½Õõ:'â\¥6J›J œ1WvÄýþ¶µ×Ýj|Cíç××ýPGm”þ…»z6Ï+Œª;j1ÅoíÜmÆßå±wÑ‘ZlÜù–ÁÚFb‰š>ž yäH-vßA䣞FÐtÄFiëZ 'QIªî›n<Ÿ ÊSÅk|C}½\l¦#’kÈö´e[å†éoqÐmêl£º‘\–k]Væk¶;O×9†Ó´ªjíõ_Ç›2õ©þ ¨|VaYá»}·n:ö™ÃÜ©¤>sPhw´f›QhoèµX…v‰JTh? X…ö™>«Ð~¸«ÐŽßm%*´7ôZ¬BûáZ¼BûV²Ü,KßNåwçØ^‰1•ß“{%zz­\¯Ä˜Êï€2yŸ=€wAr›Á”TU0âaQ7¶ÒŠWBOT]—Šáy¿ŠRù6Z$H¸Š/½ úð9*f’!SÃöÇzå¬ònØ"ï*#‘©HêTæ@¦>ŒýNFt•å’¿}RÇw\ù}=&ïêø®r²:þHPš 5÷·]åé˨&ú£«¸ƵT6c\y¡dƒE"W^°e/¹*ðÁíNßv¾Bó=%åK¾=àe]œ— a ´;Ï çnô!x^‹ô!øj½f ;kÉQü\ÝŠ1A)FêÉDôáUêòûó³ý J副(Ÿí¼c7ÒDv¾’6Ò ßc%’ƒgŠÒ™DrŸ7)Çæ7ðZAPpÃy/ nÀ—–$+ˆ•zÙM#)‚@ LÇÑP²ÁZ"R¹ d/ŠÊŠD-Çd\™‚ŠWHÈpAr’JOoòy!/ÔГ”g¨„ÄUó>xöZ¤yðy+B”ΣÐ!P&OsY>$øA à§8ªUQá6¬WEÉK©öø«"CsًɸV…âS±û:Q¼pXZ'ªBç tkzk/ÐU… t3E1×ÂÂaUX±p8Sëÿ†£êØùÕ¯ {}DU¼=ù~į açÛ ÀmݹÛK6U)ŠbCɦ"ÅÑ7ùæ½··â¼IêMRqÞ$ õ&©^¼IiʽìYñeÏ) ¥W¥‘…Ò{‚â…Ò[‚ÒùfÉåüÏůLª#(•m–üž!ÑW•–o©üF¯ ª´ù–ʘx‡}U:aýÂô|U:ž¶±{>U¥èù´ßQö|‚¯£¬xIÃõÔÑ”ÉÀx.¬JϯäûžV•¼ßjÙST>µ¸=*UHw„ݪRì^»Ý¾GbÎð&ø¹V¯¥øß.m\©×–Ú6àס²^x-(˜Wê(,öÒòöc…Jþ,·Ÿ£+%, û×Á•ñàŒÙõ*IN½ý (Ftò²1AÈÉ©ôZæ°®î¢þ]sUe æuú‹¨ È6¢ê@¥ Iuˆì•.DÕØR (Vu FM€2ùVOlJ¬t)7%ŽÅ7%Òk1­žØ”(“o Å&ΊGsMœ#AñMœÅ7q¶eòÄl^®´¨b D'•¨ˆ{ѶÒV6.x”ÊŸøêŸÞI)u\£µè™ mD•®˜÷r^ÝÜÕ{©’’2Ÿ8s‚”ŸñŽA§Åu‚˜3dÄiq0…´Nà)4ÐæÄiŠÊC{geJIºâŽÊåþ ÊWF½–œ`ð\BµÛG¤,WF¿¯. ׿¬öMST–¶‘$+Rª|Õ1IþŠ—ü *7ªm’ü#·ŒÆ•±ÜŒž¥¡"M¯­±õžƒ©R“ð›@ÜØ?fœ–Óé“ÈAeoдÓI*¾ÐÚ?ÉœðÕ5͉c,Z£ cÛ-g¡fˆþò•ÉêÚ4x­HȨˆÅQøiKô×0£m!˜¿Öà \ÑBë6ö°Þÿ¬ÍMxⳑü¥’a÷úþ¼÷±(“J\(Íõø}´5Ø*‰çŸn7TŸÿ­Û¶¦(—±ò}Ö·a‚S­-ÃqSXŸëtùüz¹–?9lM=¿ËÇñ…ë½-H#΋AïcùƒþÆL#Ε¦†,#й¥±é¢¢Ü¹¦‹ž ˜¦‹š.*ÚÈýÖtÑCÓEeK®dLM*•Ur“JOPìsÅ&@±Ï›Teòt$Tœ-I4ipTù ëmž¡•¥âÍKÚy'W–ÕÜÚv[|.Çê>õË *[ñt¾z5щ(Ÿçb´…âÊzVz³Ÿ°ü¨\<·É,ve˜E §Ò0iR!¹Ê©U²i•+ØVÕ¯ŸŸ{=¬/¤³V`¼\ɳS¬ãxêé¸T+§%{€¹£¨ìØ'ºhEJùï„èeZ9V:J²ºÕKùšJF’Ñqi'”T/åë#í3™)_¿4TM©¡ªroÒ–2îÅ|‰ÒùNÓïÏoD…wH_÷ñR£ÆÂlfþ ËüùúŒï‰T°µõ|¯³lúýlÏu˜?û;o¯õüMPúM:eÍõµ·ëï“ Òyçïi%pþ|Þà TD{ï?x¦»Å3]š‹U:ïà\Üçõýû%×Uqsñ‹Ž„§g'œ?Ÿ#61*6Çxv–óÎçÔþŽtT‹ì”ý=á”­ jôŸx^ƒÙxé:hšD˜z7~4ŸÏßÕÉgœ¨vö|„:i7Áîeb|wã³;Àlvn÷Îm€9®;¶úªΑ'X DV!¸'(•O~îÁJ¥…„eÝàãgÊ2W(“¦-¢’Œå÷¤?ïÁÒ­éVØà*>¹ž çÁË~ÀϪˆjÀ›hiJ·Vž÷cÝy‚U؃ݪ.oÈ\'ÍDÊ2¾”|f°,ãyˆÔISy%ѰÌ൘d„þ×R’ß×ù$c IÆ'A™|‚w€^àÊ›¼f ~.e…òv£UÞ‰J%°=x'P¥nÀ:T&‘ú1·÷¶èµrò­}Òp®|Åãû¤á\%Ú«|kŸ4œ+ÏêõIÃP¬†ó@Ÿ‹ÕpžéµX gXö}%h87I|%j8®Åj87ôZ¼†3,¬žcã -ÑpFXž•´‹fUÞs6ªíj£ú Cxó¤tÊ%†"Ç’q¨ŸØÚRQC‘ÿĬ_s-$çiì'Š2‡F ø?=æÄ‰¡Èºÿ¥¶Ûùú|ÖÔN¿Ü<ã¯ñ¸ÿXbyü¼“¡È{f›M«PHQfÄB™ip'0ñŽAÉ0ÅKÀÜŠ•€Å<(é3ªa†%}FÀK÷á'Ôñ$–²X-‹Õ”ÏÈÉœ“œ  B&×uÚr]‡Q-2É®¯ï¯UÚŒÂÊŒ8M›Äi¦˜/üïð3“yÒ‹<Íx„™lòlý)th·“Ø›ŠÍcW±A˜cº0ñÊQ˜bÿ`8¥Ç6Q«`x…æT¶ÇN¸=‰»¶¦$.G‡Šç5s¯B%¨ÁaRØÏ”zW*Öf-hÕðôžõ‡Ù¾àÖë‰&Ãûéim ˆ(Á}'ÈøBHºìÔP_hQ³§¨¼çÞå “O[leûeAï#ʲ½w©›ÔNìøƒ;ŠTG(«ú¢4ã†ýŽ|ÏVê˜õßåš(L¾”ú` ­û²wNj–€ ùÎz$Üz%è2íd¯x/¶DYõJôbÃu‚W÷Ÿ½Ú«Jö3¤¨jJ´oO<²>‹A©<Õ»#½òkM;Ž}F=(«D]Ök±°Ç|¯KŽþJTo½‹qûµ”äÿY¯µ°w`yÆSêËK+S*ÏJeŽùír̯Ïp-Ëv¸Õku|"¨½ ÆV€~>7zy}Ô§yQ%…3«×–¥&¬]ç8^ŽÕàY+ò°?êc£ mšî_G”âa]Õ¢# d¼öïô0šYûa¼øÀu®—KÅj=·¥'dð¥l¦;>üA=àUyµ¢¹7×YßmÇñ7šR؇ðäî ß‘‚so´¨+“1üyu/özcy%÷ÝCÜ' ÛŽ XñH [$léM>ï‰ ÞT¼RÏÞ0(ÅQ ñZ<µ=)õxBjÉ*õ< ŠWê¡×zWêi©R x¥zGÇ÷7äóJ=-Uê”ç”ð7F‰`hê¶…öIo롺©ÆßÈ9€O:œål!’ÃáÔa¯¿çÇÞJ^O åz{ôú[–œf[(–ð¥ùûOlOþ³õ¦¯%ª[óÆGÛM‡kå½$ï?íá¹ò^WôõVðú[v¾Ž^ËgZøúÔî­N0{œFœÞO {ÔdÙÖÕ>é2ykx’ÙNZ÷VÊ)ì1Ì‹¾UŒKÊÞ²Ù÷65*{ëdð‰ r:ámjT”áZaͱ|ëW¿ç`¼õy]9@ý<"JÒ ß3"Ž÷ËLŠ8Þ•¢"üFWŠŠ8ð=º’k:@)®gJµ<ï2Ô^ËóNóúå{£²W¾ß»“Fwü,\Ûá„유‰…j1þEÓþ%bÅyïxñÔ4èÔ×kðñ.ô$¾øªàgμ?WU²Ï•Ý|¥$G7¯TÎ8ºas 8G·ŸKå3"ÛÙwb¾¯ŒÐ°™žKKv“@ óD‡>ㇵ)_Y©BºªcýP’Ê®Ï(Ì“¹ *•¾ò²¦òHP*·+¤vf_iWÀ\Gd¯£‰ tFy¦MÄ|ï a$PõÇçªÓ{5k3uç¤ „ ïåȾ4oD‘ ؼ‘*·3>—+·ð©J8UëÛ²w¨ÖçIÝù½N¿ç:¼¢,z_±ó>5Xxï…æ)d?xøV“Ýч‚£¾ ÏûÑ}G”:º>Õ5}ÿ=J‰D‘ÐÝÿ?'z-MYaWd…=/ßí   [çúùÙCYÍ“²Ú¿ÿ‡ 38¥-ßÀ7½–c­â 90ÎV_«|&:[ùPfH€ðO¿é‹ $@ qµö4ýôu$â¨v_Óï… Þ­ÎÔÙ Pîȵƒ‘øùúüþ ¨wg«u¶TÞû|oIóAËF¸AñF¸AñF¸=AÎùQFr~Äõ+ðÚf«Fp¤Ûz©žVï»B°Ò.Чí 4ñþ6oËÿÆ]Ͷ]kN h€Ê5·´‰‚ ¨\sËç2b Ä¢Á±·IwÕ‡J’cð7JÍë(áC`Ï9IO1¯e¹S°CQòƒ}- …|QÇ)ÎèP±ÕúZ‚R™Q=O÷3ì€Òùvò÷¡86¯×Ûsmt’óchç郠ԛ»¹/´1[(͹ÍöpG+ºÍÎ=Ae]ØËéñ{Œ(Ç+Ù­Sb"(FN™†×ªß²dŒ½ç3÷;(ڇ ™‡;PÖQ¡ß¤VV6e$W¯ÔšñÚ”ÉçíáŽ{æ!€¯+Qu¹Ûi:<}>óp@FP“½ƒ P>_aÁ|t(‚ ƒõÚP ÄÃ>öe)p.17J%¶¥P*+¿³·¥‡R‹mé0WKѼBiÄvSx/êøÇ8­†ý1”–?G¡t‚j?Ö·ƒ,´ùÕÀ -Äæ¨\VháÔoCK¯e²c¿ç:B)ðö¼Ià妤#T!눎¥ò+6UŠÍŸ1WT)4׊kþÄuB•¬—KâÁRm~k€Ùy0A õ´9]Kó’L—yÀQÕáÇzÄl¶[v¿§þÔv¥³QæÎ”Šå)ôÉa"(Ëךv/— ,›NméAÉméxG'¹§Âé1¨*_=ÝØ ËÕâ.JDÞÜœvOP‚‚ö. t!¨Ðc®#äÕÞDżIЊ³_§öy£0µÞÖ‰ ßyÓ_†Uoèóp5Œ·zA­ŸTÓß·%¤i)Ìä‹]˜ê¶”Š©@ƒ VIšc@ VI.ÆVóEËu‡; ÆÒ)õamÞ˜f;„´í l%¢`ƒ¶|ª;‘Ù»ð>Mu׸PÉÿp´ã;ÿ§DK®8Øfn‹^<ÜÆöÙ~ª|EÝnÑÖðvoOÝ™¢è±zÓU"¾¹}@1"¸w]ŒqÝ:nnËÙûƒ  Y3nÛ¬^îø\6‰X`”=j¾.ך×hìïÔ_ *}ãÕsMj çó¹‡N @U‹±­{§¯—û‹Ù€òY#²u§¿1d-ÒÌ¡¦ñ>—ì§±å ðVéÓs§$Ç…!§Uj¯y¶¥Þ4Úš¨ÑsÕ¹¼’ ¢6NpO¡ß•Nƒó¬^RR: /–äG›,+'k¾Â7TñTƒD U)­`º¢*óÁeì©:T ©:ê´©:T ©zA%Ru¨¤.,$U‡J&UãHȤêŠ%UôéYRõáZ>×u”HՀʓªSò“èÑ”æîü¼¯þNeŽæÀØ?tÏÏîvûí J½•šXT‚dqEô¸h¹¨‰å¢†ÞÑ0; +•v$.¡e;ÑÔÕ=îï å!iÈÃT²ëa!ARyÁ¸­Æ`¥ ‚Õå|D1Ʀ7L§2|ÎØt>  g…óËœš~¿µ˜Q”Ê(Qöd•#%ý V9©•|@ÒXàKúká(\Á)yM!ÁÛwš-ú5qówQïxó½(|%¨Šï‰ïE+UØa|È’Ð.ˆîû›šë2WáZAð°„ouyÚ}+BP¼gWƒýVJrÀ2Cxß·c{Y™¾o×ób‡͉?Ïë¼›æ…`x•ƽ8‚µ{a®^6)é†à=zÔ³ yÝwØÝ×ãUD"ˆ&©˜bo+æZ‹X¿ÇŸñû·þœ·Ä -ˆEõÿþuX¿Ú®›NAmQÌÿþ»í±¤¿|üÃsù‡^Kg“@Ë{ìàZ%'¡°jPÅ$ã‚:J‡Ä“è ìuçk?ÔÑ87Þ±©/ã°•ÄÅçNQ!Qœqîå€âŒsãn…¨¼qn½L z­ê8ª[V£©Ûg:”ÏyÒô Ø»-(6i¶šÝFé%œWQK{AY±ÄÓöÅjio»¢töì».®eóQüººë˜#ŠÑ1o¢þ"¢8ó˜¦C”aL‹kü•HþÃ9!´`ëî‚â[wq—¤†Âú+¢JVû2ŠoŒ¥ÞÏ«m½œW‡¹#(ý®-0n ½–ɘoo(›ßפyKŸÞ½Yt]Úax´Ïõ*Æ¢+êL#Ê¿YtõÑ¢ëp­ðfÑõÕwk½ø01Mwðèj£G×püò]Z št¯¦“®ç¦³ê!M÷7÷fXõ‰Â,sæž`­+Ëãr6-ô;aþ‚òlßÞŸ(Å$PZX€µœ@™(JqÝ“ñéM!vOÂŒ6£Òl€*Ei¶i"¨¼4ÛÒlˆâ¤ÙƉ¢xi¶Ž Þ¥Ùz"͆¨Œ4[Ÿ¤ÙUeùji»5JŒ Ô² 4Û³w#Jåù£ ®9<ÃdsÚÆ‘xSQ:2õÌã– T¦“iUè`Þ›Šesn*opGžÙ¾{Ú/(ÉÓ~hZŠRYŸðº‰Æ²¶ ¬Ò½Å7ô<ß-®¾öXÔ\{Ä›¸m™¼VyH_ŸP.x ˆî§ûW|Ûö5Ió?ËJþüûëúy"(uH%­åʵŒÚÝcIQÄsüŠO¿*ìEýD™CÂ)*Ú6ßË21Q”M…ÛøXË­–7ÝÕßõޟ߯É÷%Ú¤ÏEûó£ÿ÷‚:?—ó@PùéZï£Ï8¾Ìh«…nù糡¨ûs‹53Dåב]³ ¬Ðî°ÇïÎ Mâ Æ1N!@Ñ‚ò,ñp™|.HÂsxD®D‚2f ª‚}C;xA•‚¯Q17ß–>ímü JKmüø edÇ)§¯eDæÉæ³ ØfvxÖ¸èTNüYv"¯J€ÀL~å9.U¿7/¨ r]`æøBàºyQŒ3cƒùGÏzšlÎ'xGÅ×Q‘$» ô —j׃ý»¶GÜ’ýѯw§¬.çËßD.õNlmžŸKw{L¥ { ïx»¶×ß3½£¡¯+p¼žýóþÝ”=0Á.ñZ÷¶~éµ\ ¶µd¹Øõç÷ÖÞ·æJÒAÄBo¨ònKtÅë Neh´¼±q†% †ޤD]s¶k]ºúçÑ퓚hÐ2ãWß‘2cp<¹µskx0­Yµ˜7( ¾0¾.t1(‹B¯(¨÷…n³i^ºž Ì›îÇ×2å×ìîO|ú×ýxLÝu?¥ÞÈ——H¾Äå0"ï­[|½Ö¥»|>†óXTþ=®² ôZöÈù‰œç‘ \þm÷}C¯Uemˆ–ñzöå™9QÏ8ŽÞc)©pDŠ&¢T>¬k`5) •· ^›UpQš'C¯—ž G9ħ7¼69vó.(Áô»y¥ò^E@B[PBi»@”¤ÒŽáSÉ«$lÔÑ¾Ç õÖF+AD)†5DlY öä "ŠÑ‚¹Á\-ËBrªc¡®,ÙnËi׌ZP¥¨7kNYÊn?Å»ý< ÊdÉnu(%4 ú̂Ғú „ç%QµWŸÁlrITí3ê3Ãe2ªÐSª–¥‘U¡)J寅UͲ´²Z5E±&æˆJ;_FW¦ ­„ÒñðZ•¨^ ßQ\Ȩ—BR­$Š ¯ê¥Ãª^ÚTF½´#¨—"ŠU/=<§^:®Uåi‚HÚ”ϦvJOI¨3oŠïH:F”ÊïC× "=VÌ2”h;°e†C´É!8,U)*ÑéC±m-ÉjwAiÞÎh§f•ʈ­t°’+'¢bòª|QÈ?îV ß² øôâsF‚i©øÐvCµ•'ë,C ;UµU…Æžr[jÉþ ‡¥.™&€%˜o×g/­^QPèÖ>ð~:TF·hè¿›K=”Ϊǯ=AeL­—-y.Í?Ýó€²LCÁb+Â284´´¡ $,ƒCºv“¨Á†‚’° ý=í'()ËàÐ LÛ JÂ2ȵŒGXÉ:,MƲªñÑŒhx„÷4²å½oyFQ†³fÆ;ZN@kÚ´”Õ2àø+2U ¨\ÿ´w·.(ÏõðO{wë‚:&×TÀ&ó2Oã°œm71[%‰MÿIÊM8仾\?Ïð¹â ‡¼»¯µËÞ‡ür@鵊{FÂîx.÷sMP†Ò¼¶6ߟñ÷ósª> j—âÙÊ­+êÑ|Ímœîåh]ó²>÷çꚀ"¬êKܾºÏù£?Z‚:T,7Q¢ág={üEr& B"³Õèkº®ûƒÃ‚£=>Q,KØÏßÇÏVîÊ3ÛÅ–!û}4õïv_)ŒT,¯7ü?}7NØV±ü¿ÿîºË‘î÷òù¹:«R˜I°[$Ð]>¿¿/Ýó0X±|cåCXéJ¶æ—zÄJ¢1’ëèµØ±Ší; ˜10hFÛ#v¸Û#«EÒÉöˆ®ÅöˆP|XCŸïƒÍ`lØñ¦l„=3l+ÀfóH{PàÔAxËÅŠä<žN/œf•l&T²A”b4j¢,"¢tN£æ5jer5ߨQƒ(ûÆrø"5ˆryš{Ô¨ATÅiÔLAù¼œ1òÕJg„’wKÊøÊhÁœþ"JVŒÐÁ1½kÃÚ»=@ÿp餤ÿšºÀÊ[ÞæC‡ª`‰Ó¿ß?ø* ãë:¬Iìæ³‡Ð¡â«úkèÐR”á´¬U •þÆ]bÑ}¡}¢ò-0)ˆª47# ¢Çìe$&DURJf¢*ÍŽÄ´Fòp-Þ”)q^ÊJ0–ÝKçeå^©Ú× ÕwÓxí¾ ]AÔT,­~ciý^¾ JåÕ³ºö‹^KIÅëyósçñ÷LP„z|•öórkÿ> `\U‡ÝˆjlÕ·ûµ#(—¡jÏŸó\_> ê¸NDزNL@œT$t¯kùŠÚò+ªÅTdDÆŠË2ÄæÃ¸—e2&0Àæœvɋݓ²¾xO2ÆñSÃ@éKVÛ„$¿/›„‰W\bpÞ­a5!,ÀL§þgCQy ·o[z#öÃJî­`ëÝ`AÏ[¡{ußk½¾Gdå–¾â Îÿ†öGïY[ÉÄÝ-}Úêæj8–\#2‘¬Õ¨R†—’ë^ƺ×÷ö ¬¤2»’  íoýhp~…B27ÅÂF(©_d—ATÚQZH} 7¼ Fbå\Ë œ=äÒ—ÁqZ0Sâå—¡záAVAIìý=Õ$ õ=ÕÍÑOPûk›ª(dí¯– xí¯‰ xí/Š2L²šÍTQ² N)Y¬Šòð\/ià±i J¿¥Öƒ9röe˜4ð0ÓkY& \®å²iàu¹ ªbV¦ï(J6þ­ ÅJ§òš*´ÐÑ@ÑRFTÿÃ÷h%õ?X1¡²¼šO.KN=Âs9AïdâT%qÖ!Á«ý–Ô{  /ýÆ Ç>ˆÆ@#E±Ziñ|¯¨FÏ÷J0ÃH­_ªTbë¼ÇRI­_@±! Ý"³}•)^Ü5Eøï[Sj»œåÎcyù€²Ù±ùÖMôé]¶AlÙocC0 ØÖ¯ÃoäZ¿¢!¢BŽP7XÒÇQ-¸Ñ_x0-ôˆ¢¨*5'{™œ±”aýÆwglD±Îذ̕&ψ36¢L> @þ¯*­(g‡ƒï„nìyî(Jeû`ÓPJ\püXP× Þïèy~Ó/¸X!Js¨‘ÞÑäÍðØ¡Ê »ˆN¥¸ ;Œªzó!ˆò![%uTF”% ¼4pP„¥rÔÚÏÏÏëÇ“ }˜^ŠºšP}A;ãX\Mގȸ©)ÅË­ì !¥ø.ñÄRŠž{k…R‚sñ~´”b“±q®öLV`v$(¶&ÖP[Ã9aÅšØÅÖÄfúôlMìp-¶&v@±5±ÃodkbÓŽ*[;Ü2/‘’jbSYËË;¡K½| ý÷.À¡”D£ŽUÉF#Aå­z†zÿØÚï‘ 4•óI™vºÂá݆C&ãÕ‡e¢w´ï5îqŽýA¹\»k‡–Þ±::W HS®dSe©7L9%ö†á•p`ÝCNK=k8 ~U»J(*~=ƒ¨x½ a[p<{|à€7T’ù¤+^ÌcMáÃ2W)±$3§Òb&Òº•::Q>DeŠÜ©„Ú`”_ ߟûѽ’:¿ÇŽC•Øù]P&_JšqFW¼goêFS¤¬žëFƒ%³ª¤àj//Š/#*ð+Àú\ñ7ú‚/„¥oH’YË•ñ7z¦#j£+aG”òbˆ5Ê¿×,˜õëV+¶z)í¾‰†'º«TÚÍ^ëP޽V3\÷k¹ ï%§üÊW|îw¹gOQ$ £ŒÍ€hƼ¨¯¹ÌcØô7P&6ݱÌâ‰â6=~ëóÓçr$lЉ²•ÞÕõßóLP ®.\]ûîç—¢óïÿE d I»ß±{üžèã>óïÿý‘Ûº:>þÆ{M$PÇÿ¨’Ûšù1ß–óaMï÷™½ßam*ø=ý^º{w§? Ô9úIû× 1ñ‰°íü/ö~ 8Pýù;Žß˜Å]«Ž[¾·føGHù#Ì!ìÙ×k]¦y íájùÞǵÑõ0 >·!­y§ `ZÈbcþPFô@kap-Ûxš ]üC‹äHP\‹$,ºø‡IŠ2LŽÂ6Ͳ^ÆXdï *'ýÜ&&§.<§*Ú¦Ö`]Q÷.æ+ty¬ÕèයÉ,ÿDW]|þ¤ëR‰âÜ‘,¡ÿ‰x1T¾]| Òa~Qoš£ÌK¿Ê¼œz‚bd^F`äjB¼øßvøÛ5ôúæþ< ôZ†©+T—’2áJ~#(& €Õ囬×Á= ꆓq‚/­”ª–à—¼ Dz‹t„RXMtÅ©ŽöIŒP†Ðû†çr/vToîFŠRœ4ÞoOPš“Æ›éµ 'z×P”ÍVSëæ‰(/i¬ã*§ƒPqA½vÍŠˆl 8ÜLÁ†&²NdDDpH½N:Uë_OC}êuÒ©ZŸY'°×I›’‘ÅYåzöSš‘åz¢¶6ÿ ×Ó/×3”ÉòOöŽ;m4/fµWáôKUü(\„‰zm¬¤à ·6Nt«‡ó„qùubMÈîý6ڈΘ ߠ䈇uem<«e¾JKÁ*g‚P@Ø\+%ž÷3“åuäoAS’ƒ?ë² 5-”R´• a$ˆ’Â[ 3Ö ¤­åùMu Ýüš¸?¼¥’îØ‹hë¤TxÊ*ŸJª÷ÓulÉbA‚ñªD—sxVæ©=[‚ʋԤ(ÀAtÛ§5)Z¾Ihî¥:íJAà û!´h¨)sZ–½|çþ0ãsN2yJ¼+-yDì¼+@©¬Sß^JÑÎ 5ýå O/èf¬ÛûDPŒpdƒ'wW ‘3ÈõÊ0å¼—!4)“¾É¥st%ð ÉsyÖ~+ùsè*Hª2ø}!1^ðÛ¦n¯¾!Ë~ ±•/…396`hÏØ×3œ½–0€Ïª_úd½ÀÈÓ/ÅT5ÕÃ5Á-×—GsiÞ‰â…pJóN/ì Š/ Ê0²öЪ_ü^õˆàâ½Z²óù í|ÀÏÔ>¶†u Ñ/)¬½°Æ¢“{KPY'÷~B:…&¹ï6W3~AÒX˜qÞ‡’oÀH§ÚÀǵI”_-‹òÅ‹ò÷Å‹òS”ÉXƒ)zõ„”/ –Ó‘I¾0X)_¸½Íç £=æ Ÿ7Y ¤pN¢Ø|áür¼¹Â€Ü~*Ñs ïè9ÕžœåHëmõÝE­MQ^X˜å7¬0üi=š'ÜÐ>Ù—âátÿ‚ïÑJŠ‘a0…æóLõÜĨÉF zaÏ)¬Àz­'üŽ_îØM` '­ð¶MÁFc’K4ô)ÛiŠŠW¸Ù5ãL!õ`ÿ®)‚àr5Ã,4eÁGs{ÞÄ”%Ë„^•Q"‹Ó”J0žàZZðJÇìŠ) ㈴>SZÑ8¥ßèòö˺šdM)hì2Ž&“™'Ä8XsLébÜ|iSz¡›`!WC'3Ý …jRã$½ãÚW<ÿ-wTx;ul…Ϧùl~þºn$(E,q›ë%”—ø÷ü#(íøÚ;«ŒâÎ÷ëZ¸ÄiñŽ‚¼÷i窥Þè)[ÇÇJO™zð4Ï{¢‚1âµ4—S˜R]Ô(#q‘6cˆOý‹_á˜h3FÉj&0¿”ãœ.WŰ‚6ªâê|cÚŒòü74Ï^KŒÓ kt!é"@ÞÄè‚—ß5bŒ–´¤f¨x’¿ë˜Ø££%»£´F~~íU£­Ð“‡rû†dÀßN¢Ÿ3œ Ûc¶}q =fGzæ&XßÞ"Ê‹{Ìh*}ýÖÉqI[£ƒ`ˆp‡xP{'G$ÿm*«)vw¥(“·:xt EíÑ´xA-€q:µ8öAèäxÀÙP³×B¼ (Ÿ7£˜A?Ř‚ÕÁ!sÕ”‚ŽF:†äÉ3=y ¾gÌË™ü‚öÍÍÐÕËb"(õFí¿ëäR@% axͲJ\Ÿó5òeÞÈ_ÍøýÕ´‘(Ò}±L›íbÏŸúãyƒ]ÁèÅf´‘që~º>éÓWÇ {€Óƒ ü^ù٦궮.Qæ´¿!ý⣸ój–cáó +“Iâ¾QnôÍnÍs9M<§ö0ø Á«ưNÃmÊc…ø~î0‚ÎÊ*<¿RåþÅ;V\L1n ½VV”û¶Šrwe¸(N™ÆK+}CQ¬ÁJGQƒ•>¬ô•7XYñ(Š3XéŠb Vw¬“êy¢(ÏòqTÃûÌ!ß‘Uc,o²–$HÅJÀYÁœ)ݘ$Heò]ÅXû1¤ªóV‰I1Ø‹µ<é›\ÇXÕ1V ÂÈ3´óð½y²ÛæÐyøÞ<«†tæšG¨¬>ZÉ7ÖŠ"ù8VÉG9@q"ù1”ÉžE÷ú–!•«žÅ¦~=Â{¬Ø5'µ¾RGʶ¾ô¥8k Xå,Ï_{îýÕÆ‚ÒfX çH>œÚ”a5Gòý7î ‰ÆýƒBbOP¹,r»®s§ˆ:îÜ5¶…¬½íÊÒ÷bôu‚lmøX×è+AíZ~kóHÔçw½ÊÝvY ¡¦_• ÊrµXØ;xÝÜ5ºjqìm>ºZ]×§£ÇšåmÝáø†DèTVEmËŠÂ{äݺ×sœ ¯å·šÈôpÇw²þ¥NÖ¦Ê)7ÞâIgù+:Y›ªxé’MÞÙ·Ý;Û$ Þê÷2”yë¸]õ¾ÚgÛ e¨Qà (—õÎÑ;PÕ›+öƒºbÊs®Ø#}®À¹bO­B[ì±ÅFõ»¾¢ßõõë«þ¹R˜bm±(L¿©Ï.°ïå[ûþ¤0“wÏÁ=a–qÏþkóÇ1îÙLl€UGV•ª”< åÑpUM°€‚u?U5óJ¯#A1 ®5f=^jŸ/ˆ˜ü‡FRˆ©¹FÒ-¦n0_VYÞt炚Š×€!ùEÒüùÞH³|O0ž­ø­JvÅ'à\# ðf¥ÝU¨™Šçž¥J·ñ…¬]<”bÌ1C'UHw½C*¤/zcÒû0^Éz#Aåô>Ú¤÷(“3•ý=ÿàIÙ‹¦²˜½òZb,`–Ûž«—²j^àíìã e‰5FãY¥«5c¬2ã+QL ¾!ÏsÆûSb¼Œ÷ì¨|Æi Ú"*B‹ßÐô¥%aœÑ¡”l0Ì5Æî `¼›ðv¦»bVm˜>þõfù|ž•9wêº;A©\#à×­³MмÒþ0L8ú ´÷0-Ç«º=~•é#ˆ¹·¯ßµtó$(•6S¸Ö£Æ%DœJS[é&Fçksî¢à¶ÿŽÛñ7~õýW÷<>—%uüj—ˆúïúóy¢(÷ÆÖ}ÜÇKl]@UôKkÀ„÷ùýwýÔQ›¦†]ym¿š[üö˜§@ÞòÊjo×ï‘ m@Æñú?>z-M\|"Gb›Ïiü¥×¢ò€·K¼cóø=é ì{Áó£ù|þB´ˆ< õ9OçîÑž¨ƒ=øZ¶¿»q6å)^&Öõë#®_¡”ÔÐÚØÉnq?›/1ÔˆIƒ—¬qW  oõ‘½:‚ÀwÅ]Ô_¯¬8ØÕëCö}ï‚°…Ô’‘Åb ±E²¶[”×ÒL®oî)Š1Øž÷ßh$­gU˪KoìfȃÙ ; Fb¶pb?HתøzÒ¾[ÙÂK=B ^+{dIÙ²9ö#Aq{è8´e!sì)Ê0LȌز”•ç(ŠWžë ŠWžëÊ0êøP ³¥â¸³í×årÿ”T 6eKÍd’Öp=ãÓ¡"³µåq½¯q$VÁŒk= €r¸žD7Q}(ÝKöZæÚbåîÔõøu”îXk9­YϨ‡Õvëï/A™Ô¬ ÔŸG½¬¾ÏEàâÙdSÇ¿=û?‚Úcø-ó¾…|óÜMÓm"¨*ÅÝ—X¥ûù]Å2ÀP~/œ®>>ãéú7TÀpzÛj7Ôó÷«í®ÏÕ‚„Ó¸Ì «ÿ¤°M4ö_1Ooºõ0à<„0E:¢oç(G6œÚþo>¼JSáÚJpôw–†“µoà‡VâR÷l *{0Oé$[ú|Êô‹ág^¿xOùÛCfFuœ^+§:Þ¦”¿% ˜oMZË^ƒ[K¨ïíWÐO¬"Aä{û´˜J³úëq¼T)é¯CK±¥úØïMmp„´T;§¿>”á|ãaATJ"í¹Á*^'-‘ö­Ò⑨£(öH®zóf=´ÃâJVs-Å”ÊHÐö©Â*+4`b+„U|"f%–Àw«OÎÚ /VUµlý å%)N\ÎUà­mf´a²ïM¦Ø€9¥L«ûÕ¦L«•Ü€9T®³M ˜69Õç0ão$’ÐÙÌž øÌ– øLz-¾s"(ËK{üZh|A²·åiW  VîK[½Þçõò_Ú÷ I @&ʼn«m^„a9^- !&à­vâÑïXIà>µÚ àÃ>£ýáCD‚›ºÅ²¬ÕAh‡Ä´®%´˜œÌ.¬&FhLß¶Q¼®Î<ˆbålÛÔÈaLŃ/íÝÅý@ІõÞXŽ–¼5 ãs9I˜š…­©ÄæØk_š9_5#qT½¨ý‰¨ÀêÆDƒ׊ DB›qK§dI/[òEå]ÝÐZ%ëOR”â ©f@iVÈ$RY⃞3¤:\‹5¤‚sñAÏRÅ´›%>è9CªÃµCª¡…3@òAÏ6 ¨XÞF¼Md6k-OM!°u¢El²ÖÉr=Añr#AF2×èwÒÂô ߣ’»€µA$ŽÃµÞéTó¬+…¦Ü=ý@ÚZsí ‘|b_¨HTëŒT\30ëÄ&@(ÿX'¹§ôƒsBë[ ë*®)7’Ôz‚RL3”’¬“Ijø\kf¿ž9ð=zQBN.ˆ¶ø\Ar¶Á¹Z½ž¿Öo{;-'€%Ž×ª ±YæWÅž1Ûaû( o«œPçƒéJã´uaZw…Çï²Ì}>á UÇÔâv^ÝÆþëü9í)–d„ ÕðSƒ±ÕtêÿÏ•%Ÿlí}ð\†Ø¾lÅ5| mjø²••¢&‚Ê Dµ©áË%áÌØwø\Nû'Ž—“ƾőpüدE3ŠÊý8ý=)ÊfZZÚTµU%èúbqÔVìÙ¤M‚¶òÒYÈÞ¶ |Á|®²¤|i«K|ß­Ö¡Ðj½dgŠöÕÖó¶ŽÛŠ ×’ á«õF¤õ™É[Ñ4¯e%Ó@Lþzûš€¼ñgºww0M”ÉÚ®ö O‚²Y;Àyì{úôDjÿÖÜ¢áõ«½v¿‚bM¿‘3 pì-c¸=ŒÀ¼e¥ö§äjaIõ=çj›‡w’«Åü¤¨¼«E³ ëHPyW‹æãã€b]-ÏŹZ`²Ã;ÁÕÕGå¹n;F}uàŽÊ÷Qå{QÉ¡Ü{FÚû´ÉlßF‚ÒÌÑýv¸£É ^Î_#ʽ?TZ_ŽîóáZŽ9ºc@äý»9Ý—Õ¤£OïólÃÏøàý2céƒÔ3ìrÄp—m¬Ë¦o;(Þ™zù0ïƒâ©W×SŠÒŒë0¤eÞ]OÇïÏÕõ”¢,ӆ㴠! +6Ia¿¡`„dí~ä FRXÁo(ðVŸÏ%Μ`]¤µê68Qæ*‘yÎ*N½¬8IQù®É¦Þ爛)˜«Nè3¿íIwGúÌß8èí[W”Bª .]¡U Ô\!ö%ÀÛv…Ô—0À®(¶w7}€b{wñ7¶›ºL]a9qö6u™ºâ•çr‰_Zó<¿-¤j­Ñ¯kô:à“µÜ:m\!ò³âŠJ`,b·‡+¼lBQ¼UHGP¼UE™lÉ`g—»"ê#ûÌ)%ëžô®“¢8WßÕwiòqB”fÔ!ÖÞ ¬˜;jhœéÚYø¢r{T¨?èJ'0ðP;Å••¤‚o»¬D픸æ*¯œ°²ùz‚âú—Z †©»|I7ЕAHdbHáïÍùÜ¿N•b—ŒªR³W¥8~D›:m\*@þû[ š“lœ¥å|QVDÅ`Á)w؇¶qØb^é© ,¢ˆî‘Ø}NÏødNüûÀt»~~öõLQ»æúòžÏ¯~üøî JÓØ|í£=MŸp-ŸßùÎÛÎçB—üZ·¹Š¬þ­pu{Žz-ýÎXÜöG(7ÊäÕö½ãTná=êBÔ¥„5Z—¿ £ŽwumSßiýbJpŽ|Œµ«òÚ}Á\ÕGMª½W¥ïþ®í_sù&(Æ®¿èµô1]w÷ïy]ÊÏEBÖkœ_í÷åÖþ}|e3r}}û¸_;‚roËšó¹~O<ßGØšrožôZÑn;VTtÒ©·váž w^…½C[é,šÆN;¡G«þ8§+Ni¢?û@³Lð5U3ãsI%uLœ8¶h{A`F›BRYƒ2¥“zé÷XÔ%)ÒàmøtzÒùqÆH:?>—u~à2FÐùÁŽO@1ë–®±lpJü:Ã$# ¿ÎˆÉÇ'¾!'%~¡Lé “|lžcJüÊržÇpª5R‡Í8á=Ûñ™:lœa:lÚ5axFŠǪ̀BJ×™ ê¯Ä”.Ή ¥t12Õ=¥ (Ë)1Á9Ç’Ò*Мå W©Tæ¬tX0ƒäh)ö¨ÅÖ}ýüÜádeY[Á1éù~'¦ ·PVT+†ùe˜ø…·m+Am ꎔ_úUÛ­_u"(•«{rÛÙOn·k7ØyÀßXïz™«1?á\!*†Du@©7£°>…Al劗Þt<]½ëŸ×™Þ1«òûµnÅ*†´ôŽyÅçŠ!€JŠ!g4&Z¦MÓç3A±Š!3 V1d (0Ú&Å9º5Ó2ªã%Šà ŒµÝÄ“ó°_¹’Uß\=W¾áZ¬ŽL¿±£Z‚ReçŽô°1cèœÕ ‚tFP;p•vFR;¥k@NN¿\7úšíØI.ÎY¾tµ«×9N“9žÀp÷àdלn©Îy^Uàzƽï üfþ =»ŽSHŽÊ O¸c%œ­ö~V'Éîê6®R‚ëÒ> +Í{O¤YXiAkU\e$Í\œ•Í…cç’«,ï{¾Åoþ:%"¢#ý¿/ú»Íª¿‹ÏåE­U˜÷Õ?hÓŽ¥ò=•5(•9_H}£@Wt¤4úFÒÛÕZœ/ó¤ uN §¿èræ²]¯Ktµfê[ÛÁµÔ{·ä»%Ÿýu"¨—ïq{}ß4 ½–޽ʱÚôs¾Üë;tp8¯^0@™ãÙü|||<éµ,µl¾ eóê3Y݉bQg¹Öåcœ Cô×–¡¯!7ï›¶WO\t"w£u” ¬[cÖ=°úm¢”»`$UVN¤+µ£r¥`þµ¿!Ç’oÚDM«œ–ôp:Áör×z¨œ¨â€£ê$$[VBi1‰[Vïv¯‚µ¿Kö(Ç[z¬ùè‘ âÓÓ£è¥=ßêv˜)J§´RðŸc½×;‚2;­QË9anïóe߉)?ËKún(GÖ{¤H×ËÉÖB··-Qù¿£LÓJs[ešæÇóðô>¥ÖJì6Uçß¡;AHáÜAz“°_ÇëgM=\»)&XdpÖôxG/Q;fœ9¼qQꨮ*žº½‘²ãµÖ±( ¾®¾Û£Z)Fzl[}1­X)æÔ±­ä@1”¦%©ø\Ïf¸µ-¤Ü*ul+Ã>¼¾k¿®Ø‡(K¸A°ü17°|Ô~êØÛå‰Î·g÷EŸk›롼¾leѵ?°ûxÞÛŽ^Ëg%¹–¯ãðô!+¸œòaßf…¤£9&œj«#95µ•=·¶2H!UGñTÚVÖ WL+’~ÝܵnpGË^kžûµ,[Ö]g!œW«Š/6íÍU%P2÷†‹Š—ˆ^ïˆ1 o¢Û’ô þœZb*¯d;»‰ x;»Ž x;;zGÃØ{c’5ä}Ž›À5<—J‹XŠ­Ä‚- žV^H[ïº7•´}†g4o|»öcŠ’k"\O¿Hܬ|Û·à¹B!6•À fî» cõbCûr‚ÁsNàÚXÖÆlc©‚‘i)ñ7+ÓR&‚ÊŽD’®®‚¤«÷´upü·½6fªâ³ú­1‹¢gÂç{Ú¬wŒÊÓj>CQ*oH„Åò*Þ0fŒ¸Nø¢4Óàüå‹ãþHRn—[Ý}Æó„/^Ë[xÎÛº™àœã u,\aì<}~>ºçuPíÙV߯ßK=Ãî(ªMW“ÇZ+_‚°‘ læœÓ¬µÌʽåÎÓ÷µ¿f/ÿçå7>¦GB“Ö“ƒÄý–jþûî>îøôúµõ$>ýW«· ŽÄ®Æq|úïËò~æîpGËEM#üF#h“¡…/¬pfj å 'ÿ´ðô• á;@àiñ÷¨ÿѯ$ãSKPŠiÂÙçêK¡o{AÛ9z¾}ÜÛy[É}Y¼4»Ü®@|üø¸ÿõñ4äËâí¤°Ù¤4§¦¹ýAé7›”¾»uíðléµÈYn툉¨¹½‚*' Þ-F¶Ö“ûßáé]îüµNº¨–¨Š!CÛSbJn¿7ú0Ì "@| ÿ4ÝÚ ‰Áž¿îȉ¾æK©i ‰¾ÔŒ¬ó2¿ælh}IZ<%ƒîcY¿ã(•W_Bâ/-gÇÙ'’ˆ/%]Ë4š¼`'œ„*|éE¡ ¼–—„*àüåKÏ U¬úôŽy¡Šáãã€b…*ÏÅ U@PŒPž2•þ ^O( ýmW0óe`Ì–Yøƒ f¾ Ùºûýþ3O Œß+˵F‚2\cVÜ·ýÁæø%¿Úã¾ío›âZ¯dËÑPŠ='”Y¯´`T‰ô"¯DámȸyeEòÌhåÄÖ“ ®UI×jq¼¼Ðì‚-^±f´.d‹¡‰ £æ9QOʧ/ÍÓr؆f=OÊÍÐun€ÆsŸÇîñˆ(-Ž=|úqáŽNnÄ¥(¾·%(¾ÆËʸÅ7âöÅ7âÒk™§™¢òÕ­ö„*eòb5®¾yõ^4Mæx^%Mª{¥líSßHõŸêH Œ'˜¦¾ŒÍµ#(†8=ñª$Ràå€âH#ίŠ'.g“‰>×–Ñý_4€€“²w§q:”Ï7pbuÞ›7 0Ôì“î 7|f>ézÃÒ€FÇž3LFõHPŠubˆ§G«$'†ýZJö˜Šwb (Þ‰!Žª-e'ŠâF‚ÒÛ–)¤½ÕBe ÒÞj)·yk¤ö”ïh…V*¬×z¾ª»™ØMð…*R³ÄpGÏ+™ïâ8Þ!3Í5Þâyæ—+…óÒ#ý¡ô强·ºx§››a‚ÝŠOÿ ÂÍvÚþêóW÷MP*WkúÞkMÞQìC}húéï÷3½£¡æ1Q3öõéÈÖ>¬‰u¤æyùí§"§Ù,Æ:-}®*¯·‰ÖÑÞ‰•œ-ï Çÿj“€™w–¯‚ïÍìÞ9ÁŠ mͼ«¤Æ&¨+xç›T$à{' ~εö.ä×Â9z±Älº¯ ¾¾½º¯S”JÒŠ¸~ÌKH>À:ALŽ×¸c뤈¶¸Í£>áxUÅ«¡'¶¶K úãU•ï €Z^㥙š(_ÔÞ†©{~”~k·xüýÖ{£! Ìê÷ïñxܯ°šTå¡ÑpÍ›lw\ÎB·þ‰ç‰*‘twY%_úz4õ7AUä”vƒöù~ æ¦X+”Ïœåúé:âY.¢êÃHZRš^Îr±&í+-刑‰Òtæ,÷(Š;Ë⮯ôaNļo³e}’U§¯ŒÄØø‚Õ—6ÿ2H`èÙÍ÷‰^+›õY—û±'(ÆŒÙ2žVˆ_“V ðÞ¶“P¿Šbd•žíWKPúÍÜ»sï‘ LF0iZ“ ŸS¹Ìm/g´Û©?ÊårÛ›8}®êXkZ®5Ï˼ø;W‚òy£ð±ŸèÓ‡7gïe>ÿìÎÞ8ª§÷½V¾[v÷Ѳ›ŽE´"{;J¯–ݘÎKß,Q>ŒFÅ»1¤Ü\奺4ž›*Ñð÷_H2`'ûRl¹€L†WB]¬æõ8ƒ B¹+¿ïhx¯>XQQNª^Cû†œ¬èºN×Àö¡²§=fOƒZzNX%•ðLëLs@)¦ùä;ÎÂê广“¯Jqæ™ñëE)šgÆñ ¬nôYˆÑa ¸ÿ#;é2ª???ÏPY/ Èé cÜ#C¡_]bÉ)¨Š{áõóÞ´Í™ 7d??¥3ý¿¿ó³«G‚J~Ûm™äG½¼.ü•ÕQó‰th×ãýþÕ”£(ØsÛ]ôZUvÀ®÷}ÀªdaóÒÇýùñœ~&‚ ¹>î©›¿¯_åzJ&ÙÓç'¶í#,¯9¿×àjARËQÐ…@›dt)ªßÄ€!hÅ)¶.û-ê9­%å Jm„¥]Áðb»zÔW›q“¤­½´4µl3kiêPN(4=ŽKüí],È®@u ¢…+¶Kíyu¸UÏÞPôŒX(•kí]õŒaæè èck/ r6iSR*¦àlÒ¦¤T (Þ¢®%(Þ¢Ž¢r6imR*”ež(qÁ”ÒÓƒR@0¥lòF¯Å›¼= *ÿô»"p0%§Ü&Eà`”PlÅÖñ@ ëö· ë¥C÷³6rŵÜ!ƒÚÛÁXQf„±w/jĉä»íq¼*Þ‰dè1<4• 5Yïcï%o üÒ¨–ôû×V–Áxæëج,ñHdX‘n#ÎÅoÈ©Á tò‚ ìœä‚`Å›\:±âͬ«V‰.0ª´ÐýfÌ6¯e2Áís n!œ¶ú%ž’Ü϶! µÇr%q8?Ûñã<”ιÌ·)’2‚}I?\nç¶Üü4íí¯=}¡»b»äGó1}@‚($[ßW÷~¸ßï3}.Îa`èès1}w¸càÚàÛ¶‚5öNÌ Öò4ɽ *X'] ÊIÁV|»÷r€àƒ3ìTPL±XÙ“~ãA ;£œïèJY9¢xå4ŠÒÇbØvÇßeFÞñéI™þ0ïÛ謣êÔ‹ÒÜ qæfX&kOPšñßø½ÌeÿN¿Nm‘T¶}iÏßhU(÷æÒÑ—@UoßcÿI\:å¹¢Ó•¢hqçŠU›ë×W=\é¨f‹;ß«™Ç'…•ùomi„)ÆÎ8ÜÓœÅ<Î1ÍypŒ©Ý+8Ay9$ã-%udl¬ Îî@ضœ=j`àD+Qp î¸+¿h~@B“´µ¿k6`rܱùqº]!Šüþ¼ÝG|ãîu†b÷Ú°ÞŸúAYŽD'HWq¤÷)•“‚óBëzƒ'Ÿ¥!Ùç‚è )'Ÿ¥[zG“/í :JÌ8jåI+/bÆ[rµUT)Hi`É,T‚èÃNý •æã¾½Ù6Ð6íwB8P.)‰g¨ÞÍ¥:;ÐzCeEo6øÒª*O!h"…à ÆÞ³*±ÏúX€Rø†b¤QÍ£9E ,@é¬ç€D@™ ¥ú|«» Q* ^)Õi$HòêR}k¨êRý³Rª¿ Ø (Ÿ§TûJÉ«cLôµ‰QPÛjþμnÎãV¾ M4 4AÇ¢T,·^x¹ýA)Îø¦>­®¿,;Éø6ø÷^Ám“Yo§'¨ Š5¾=Ü1c|;¬Æ·-L _ˆÆ· ½#k| a¤/ãÛtű„ñxèK±o–VÏÛÏÜRRJòä^šñ=z#t1£˜wðV²/ÅåÐ;é顳=øJ8¶¢Ørð^6é J1ÜXè¸>H}aÀË¡ª-XÕ%oA—jÊA½ÖÅV+šVqˆh‚–*$ÀÆ Aì<ÆÔU°Âs!!'$ÞÐ+ÿuÌûZ¨¼Ä*i(Ņɰ2© 4AqF#ñl‚¨œÑÈòß8^éY£‘ÃY£‘ÃÓsF#±¤‰(Æhd_ïU`Î¾Ñ îÈ•ZÁŠö4]æ­¬Ö/­YâL@)‰ú kN’éÎ(ÖíÏ¥ÇDƒp !»º¡(õÖðµ– þX¿´>ò2pN|­ wËœèʼw<~m=?é-á»Ý Èÿ~Ôm[S”£Œ‹Û¦¾{[°áÔNEx×þœ.Ÿ_íx¸–O±Õ%†™_æ³ùšúCŒY·‘ˆ¨ßµaùƒþÆÚæÄ‡,Ÿ’BUªfUªO†Úä ÝËJ±º”Nå ~·¤3?¦¯×rëc^ȾuTÕ‹Ö—5M]Ûሥt älãû^âÌ¿®Æ=&é ¼+×,‡ü)i˜;‹Âùb‡|´ÚüÂý]svß8rÆ”¾èú\P7fØ´ Jåÿ¢N7¢t^ñ÷Yjˆb¿"8±êÀ~E¿ëWDQÜW4Á~¥ƒô¯•ùŠ~???¿p÷ˆ¨ÌW4ƯˆþÆÜWÔÎòòý®»_×Áó›èÕŒoÒüC¯æHPY‘½/oA)‘â'n#Y=Í=¬æF‹Þ9Å?èŸÃ¸Êúç8ýóaÕ?o *£ÞŒôÏÅ꟞‹Ó?w¬ò…çg~Fÿœväà¥$q="Êe"x6üY"8š¬ Júgá -žj9¯ž¿Î·éNQTv¥Ç7ÀŽfˆ2Ù>Ô°]P^êdn Ž1Ad¡CœLôÏãzr‰§ä¯¶¾|öÃe (•åªWQYúYèˆÊ°Ð¿ Q ýYèˆâXè—…Ž(–…ÞuŰÐ{žßÏ  ù‹¨*SÎÇåüCP>o5w-}®·_𲂢ìžKsÖý^LZP†U“Û‹Iˆz/&-¨½˜„(?w@1 Ql1i¦(¶˜;Œ5b1é€b‹I8£XL‚Õ×±˜t@ñŤ#¬Ì)öbÒ‹¯òß®ÅF­çåûyŸiΰÛÇ Bª«„]ݔʠÖ*}ô]P.Ÿ€Ø˜žËsƒ½×+#›unÏ_ü•Õkj6¬¡†ï¿¿A1•Èa‚íÖVÒäù„€ÇVÒäi °•4yž3y@Ü QÜä™áøn+iò<(fòÌçñËV"ÏÃx;ŒE©ÒÛ®ˆ^$½}Q”z£â´ß+§Û¨8ˆÒ5÷Ïõ÷5RãÅ’ÞŠz'½5„ô†(ŽôÖtôZ,é NÀ6Ûѧü=£)ÐÆöŽAW¸BÒ²n &u¥Ø‰ Ù§¿ó?NR\ÜOùN4Ü "ã¬Ô}ˆµ;jkmGóøÌãéÔÁJýBü!ª¸_›*îDPŒ ÁGûÝ”¦{üöÛî㣮_ôŽY‚æz ˆÊ¨Œ›Âî¦B€(Ç(ì~ÀïŽ*G…ݱésù¼Âîíï0SØ…S¾sÔœìMvy€ä[â-e[‹!ýã¼ØZ|@)®å>['·<ã4 ’¦“«BrÆô;µÐ ‚Eý*XTcZZhLÿ…ÞƒE×mD±i)‰êxl]^÷އ·¶û½Ö5A™¤À®üõñ¨›qø>”M µ Œð³š¡,ëôA¹ÄxÛ~áð´?õµ½öô铯FjßPõOßÞû+A1ŒKL†ÿ<–g›¦‘þÆ/¹±è£ÃßïW×]Ÿ7:ª“{Ã:]Eø’ÿŠAiܰV×eAo0…Y›•îzŽkÅpjû¿>Z™Må éà 0“Wª;ü¡Çõõ€áá|_âžsMPL~º_~A1ùéç>‘ŠÉO÷à¥E¯eß¼´¶êzùþ"(÷¦ŽýÕ,!gÓ±Ò"í¦ÃÕDÁa raÕ¯4Éh¼:[ ûsN1½Ý;š¥×'Ì;W"53•“€3dÌX§“¯3ôð½ÈeÁ©#PÃQ‹Ó¾µ8{‚Rœ®'Ìi_Š °ˆù’ïÇF‡Å%;,¾ì%‡ÅëE^tXÄúšgÛ]íyAiI· «]Þð>ŒH`^P–—·>ñ‰ Ó~ˆ›¤wÒù s(¾z['b¼¶¬§ûåsN„wõïÿETä/‡ÌÛ¥|”¢6¥[¢è«›n÷{{"¨m™û7(Ý\¡Ai²çõNPf53ý,Ô[ŒÕ-KðoÓÞ>ÊrçQ|ÛV-¨ïˆ ¯רU°®Lí©;S”âNað=†â5¹kA ·SÛ~”ÉkA5ÝHïh3ZPêÕ^ ʽkA çó¹í'z­ŠSo‚³Z(ø P:«…â-® î©pô˜q©Ê+¹ß¤cÏŒëwåƒeøö°•j(–²5às9¡¡`ÿ£W[x1Ë*Q‹ AjòÙB!ˆMŠq.‹BPšcc΂*®ÖdÊB |Šö¡²P¼ãéZ„;ji%ÿ= Ó(Çä’z¾¼¬ä·Õ+·#(“wî:¼–‰ûø\’š%pv”ããéoX¼nÿHÞ£”H`.•/n.‡Ð  T`YÂ}Ì¥²,Þ­·±ae˜ÿâŒ.ËRh[ 6/K%¸Î8¿JýÂÝë;—¯ËmãÓ—o®u©¾3µ]¬ï”œ;IdA"¬,­Äõ„œAY:± £ZVü—6Ôø¶K/¹ZD=/DQ>”ºÚþóøsexí“©Zò¬±~×[B”b|ò ˆ,‰&ËkícêîÀ¨*óÜ2ô›ŽZjˆR¹ÚG}™§kOPŒøøœ)ŠSÿ< 8ð¼!¥xðJ¯U%½w´‰‡åÄÚŽO‚òù}¨m©´ Y6ã  ŒTeüjÅèg¶ÐðøMPŠS±új Js*V_A™·ŠRE#·¾BDY¦2<å8}*ø:"ªÊ·®;JÚ·‡ùÙÃUöy_I§àA–Ê‹ªL8¿ÕzGo•¼vo‰DTþékàã/¨R`íÏJqîÏñ$Zj%) â @˜q¹63/ÙédŠ9…’2¸2m°Ãh!*ßy¶¥v’>Õ>ö• ‰•çR{±ò '+-÷¡ô€ bgÌhSþûînþ/ö´,(%ô/´7xÛF³\uƒœð’xrdú¢Æ1¢4£Ç{-eá¼ñ~¯WÃò3—Aí`]5²æxŒÊ,C%rÿV®ú\KhÏ_fŽ©xO´µ_QkmwÞYû¥ñb„'>ÃzäL»È+ ÷$Ó˜;ÀyÂ¢È Œ—-„Æ\Œ·KËv9L»Kü‚*%—x`{—”½ñÞ}ÑÀ¹Ð–’K|gL[¾ò~ŽJîð\JRra•#Lƒ’{O”Ü•Qrï“’;¢ 'Ùg«¥û5_"é’à·à|ŽÇœùyšî~þŠ(w,AìJpË[<ÿ>aÞ[÷âSŒJpËë^íôJÖ=¿Ímª)ÊPñ³¸+ü _Ãß|CÖ½pbÂMóIPŽœsu»¶×æüMPÕ!ës|ôCþR”g|+ÛÍ·QÑö~ÂyÂ¥m0!ßÎÑ«Uæ»^VÅÛØïí»þioß#…©¤Ë°aüm>Ÿãï¦Ó)fâÏø;?~Ï8Ý^\€å ãnˇ{úkè+/íQvb[õWÙ‰ÏæNaŽÂ¶Sþ ûü­¿7­r å___õÏ@aDÀÿrƒZ×¹¹ýu‡g yWÀ=Þ”l“ˆÒ„‹z󣞜yc'B%¢êæ£%(Ê6ØnxÝœpî×'E¹TÀ~ÃÏóûûããy@U¹ýeæb6É%îÛqß]+³·a ¨@¸8W8Ÿ¯JÚ=ìIÎéÈÿ‹ëÓ5.cŸÝýç<Ñ¡ˆ+1¶ªý˜oõ掦’•Ïe»Øí÷ô{éîý¾¤¸ÿuLãjQþŽã×fHÑ8îÀ>»þ¯>À,Â>0ï¿– — =À\VŽ`«¢¯`[‰§ÿ£ vÛ_ï¿Ïei§0ϤŸŸþ7Ãô, ”Ë·n­–½u«d±u ®5%*ü5ð>Y³‚~7+XPÿ`V0T6I½šâE"iYùÆš%HšÖ ‰¢²4õª^¨Rºu«’k¹îS±¡¬”`õº§þ+-Û$M¥í> v‰žÍ¿¶Oé DÀn˜ÏSw‡êÈÝÌ·ãüx®&(©J›#¢>lÚSÿUJdý›Ò¿×ÆÆût{Ðk™,êï¼U@Ùc(wÏ0W«=‘õ¾ÑÏu‡#áxs å«|RTÞèùÄcJåxs ë´w•Õëáúiéçñû³éºš^ËrÄn˜÷U%¶Öõň£ïiñJԙĤE%ëL¡¡ò|€ºì(ʼ™a¬ó°¹_#³¸¬ÂÛ:¨éù}»~ÄuÂ|ÉTÉ ­§rW\r ¶ôST¾Ñåë”$_¿'S¼’ÁO (–ÞäKã-”Æ)J½…?-”³;‚ÒùBußOeÞ Õm,T? ʾïjc,TOåò-`{b†¥^l†wÐtV¨ï4|,µ§Mec@åHV9¸c%ÚôÀ—æ%ó£=•íƒ@ßÁW†B2 c²¢D Ò^6·¥­ÖG"c­Ce `愌ùQl'›žórŽŒß¶(y³§yƒÊ ûx…J–À}(x!‘…ò€Ryù‰=hžOd}ïEïไQK ûAL,ÃZ…HV‹ß*ÊüØoO8öªP甆s ^£ÌÖ‚ÒŒçº[=`ýRÔ4çÐl¹…¸Í“¢öÕd ybN ÿYöÿ©¾õeÞ¸¡kÀ¹sCU2ÍÁbV<¿/Çü®žëš¢Üó¹®9—ó¥nîO¯¤Z›£|Î#Ay†ñÙNôŽ‘T‚ïQñf>ÝÚ¦û×bÍ|Úzù…±ü¯ {ûgaûùõuÿð7Z’Ô/• pG'½‡ž T^Ev¡Kµ‡öûó³ý (õÞë³ÂË9ÃÓ{>Í»vñP”z3˜¿´ç[½¶è”~ïâYYØ×ßv:u¬ÉàQýªºto(ûÞyó³uÞPŽŒ*4›tõÇÇÇ<·UeÚsΗæñ<<½Ïi.lÝ9ôŽ!#í7?—/QáM5uw¸^aWPÉUSop­å° ýDPš~W»©V{I‚2D55~¶?ÏïËí>¶ô¹,IA\À{㻾µ§SOP.Jk`wWeÁ)Ööç˳ª|³,Caœ)õ¥©w Íî²ðuÞçjY2}iË3í}i€bš±/ Pl_Ú@Ql_¼í²ûÒ(¶/m #Áö¥Å Ø¾´ŠïK;²M©/ aŠÑp`•ÀµA]"Uʪ8üZû¯áZ†û–ûµ¸­•æ…ks¶]kŽmª´ï×j6Ê×r­ë}ÿ?aW²ì(®D 40,{ßÑï°1`0Ø€mˆúú(RF©®Úž¹B€”y‚ŒÎ XG‚óã2¬#à˜Jp 9\<ÜAsó9„j¥¯cŽ•úØè&ÈQ‚ë Á}ô0«ƽ¡ÇÁûñBw6ãvà8*Ä¢ãº*:–ÿ«.mª©"¨_«ixiæÓãFPÄjê|:oë©3}\@)‡küÀ«À]b]®¾©ï÷oGP—àO­ } ޏr”—ûŒ AcìâC}=ÀJzME(ÅÝ?5œ”æ£|–uïh¥9÷²îp/Ê“¹»—Š)^@'#~"†vµrjåš œÅÀMaÜ”<)ŒkPÓ_<·2u.n%C,*r爵!K ˜f‹OQ ¿½U…JýÞªAÙÇ…|4³é (jô‡ 6-ÿÐŒ‚£ÿ5œjí®C-§¾-p” ¤ËAzÍ7…½‰½ú{X«šÏ8?¸¨Bû;â0_g7‘År­ÐŠs¿­ÐÊãɉÊB¡µWYbGrVî_d­}ÊBp¬”┘8«þüo åþ¦íœáá»~=B'>¿`Ÿm§Ú;…a‚¯»Ny-ãzj‚.ÏÁ陣P’sì‚÷W𚮽É"¢Ð§éÂ;DCq±ˆlj‡¤éÂÍA&–;"‡Ú¸Ùm苚 µÃ4öÅ©nŠS; 8_µCÖk+"ýùßvH†´†å#ZÝõJPëñýŸ?›ñOŽåŽuR{Cjʼnzß ÊŽ5£Ä¬_V>\—öÅÀAûWD‘/7ËÛQìsNÇuÅžKdï‹3½}̧ƒS,"Oq~ç‹(õù%â>:|¼i|¯Æ?ÖQFŽCÖ‘³ï—ûmf5|ózîf ån^×#kˆíÄ©y]¿÷ë>îîøPŠƒªp.ê.§“X²7òÆŒ•#ül[ªÅçu©ÚAiÛ9rÓO¯°ç\ŒÏ'|­b}v/4º——‚¢äçªÎÕÇx6BU8𱆱:Õ×þ~#(m¡*PkÕó«n Êò) µ\Ž¿Í#'¨ØÉÍ>9”¤ *Áûc„—Üë;G Pé5,¨¯: 8Ö—4ØWt×çõj·ctwË=‡;yjH=8-ˆ˜×bŒPómƒµƒ ç¹8µa?98à¹-~rp¶u¸•1úzÏÁA”`nk,ybÏm†+{‘•äà8nzØGÂM3qäàœ)ek•^}ì ÖZ'ÍÌ}z÷ ð–þ¡GØþÄË2lŠ0hñ¹½s W‘üVX‹®·|ãt”`¼æ±r’Øo ’0¯ÿŒæQðƒnË´‡ëŠ8.ñrØiÀžM$¾æU6áL$¼»Ëüao•$¼»Ký]HÆÝe³# ›8ü ¸Z@,³ú)—-E_îÄÖÚù¿«UÏî¨ØÑâš¿ßoe]WrBuj®èXg.ñ«Î>¯ LžpVîã˳]öôòÃÐ2J2j̲ÃÊösNÞèîs9_jã@(w–âzXëJ2>X£H<Á¸z[ âsñ—m‹ÕÙð€w@úÛʇu˜/§×TÁT¤Â¢à­k̳¾msyZ(yjí<º2{-Ý@PêÔ³ioóhd¥í«i_¥¡ûê·öÕ„í«4üµþ"í«f´PòÔ¾zXí«ôh«ÛWè (íîKUƒ…Š8e:¼ )iæoÛ•T›Så9¿ïÏT{í÷³-%ÍØIÝê‘ß>â†áZ_ð½Jïú¹O¼ë ç+ñ®/\‰w}Y¿È®/DÅÞõ…¿{×—…b×þ±w}Yc±ëËBEÖ¾Ãìl›¦¿”O¸C²Ø®8•/fÕ62àÏÜ+µQü÷}£6w%œ{… ݵd ½1–= ”׊ÏÔke ùØÏõ…ëŠ|iep•AìóJ¿ Ÿgœûdú2ààÔ*ÀÉÞûqÙ©¿% /ʨ1eȧ¨ê{z¨§{…E†’OËŽ_Tnîº+ßI¸2ÔÍf6 0‘Û/§žx2Œ¼žx° ÃÈç‰úu@±žxÖXNO¼i÷ÄÔÙïM=ñåôÄkwO<@%Œ ¸ùÈ0æRu¦Cš!ÃÄŸªCQÂíE”«ª$úS¾c‘ƒ ­ =6›ë>ÇÜmðœ€ey™´¡»K é/æ´ …𦿘=“—_;|)¤ÏQêR(ž0ÞãNA íË‚ª$n¸‡€ËÞÔóm (áVDbuKþ¸aØ4Ã÷ü1+GxNÉ{FŠ„'ýõÙ~õ?ý“H3–¿¯ùLé7Iâ™!ô\}¶ˆ õT:<3h¯®Kò_«ÕÏËœ›¤l7vÝYÁ|IéùòÍ%¥ò „`EŸ»×6ÅÓ¬ ùÏš ÜÏú ü@IÆÁοRF^wxËÉØçNSw)cŸ;Í€w;æ|»‰;  xwú‹Œ;Mî4€Š¸Ü xËɘðWN\ø î!¿ª/ Ã%I÷ÚBõÅÚ[D”¤±ëÖùws·PîR?î¿øÂìx*Á{ƒUóV´îL‡eå™’öËí€ðéÈt‡ÇÈo@øtd:Hâ1rÖWc¦ ø€ð‰ ø€pzõ|@8Eñáôºø€p:nÍ*nÁB—túÈt@˜à¬Tp4å1ÎÁR¬TÚ+ % ©"϶›6Ry›6øjU1»Y ›wå#V`Ï*Uêã²PÒV¾Cci_°!¹%m¿Û¡¸Ãqä–‡IÊ™ù»*̓K"nNvÁHqãðC‡»Mƒ]~èJp>í°ôI+ßåÓn¡ÆL’´òÆLAÙ{¦½0í·øÂÕG?¡MÜ6>òùù„­ãŸ×´‘ ,ÛßûûÑ mCPbŸ¯Jê¯oöî+(ëÊ#Y»Æ@·»¢x~ŸW‚R‡ý˜oôÝòúšÀIÉ".Un®tâ Å…èoD1ôG$žIòº±ãÐ>A SË(tÛ‚…)©ËŸ&½m#XMÅDP¬`EQ¬ …bma[…Áe+@Ç:Û.g“ÃFP‰ÛR£e$<êž'‚r=§Hú a÷û¨|ax„Œ”× ¯^{‰Ù8«Ú“®€6»2м­7xD1Óz[ÄÞz“Qìm½Yc±­·™ŽÅ¶Þp}ÅÞÖ›5Óz[žÉ‘ b7µ9Û×=熰Ì»b„±RîØ7|Ú÷ ¯ëøò}ÿ1ß!¤ÃôÕ½»LåÔ©d«š‚¢1_˜˜ÅÞŠnfMÄ¡Ï<·å±ç@·Vuá¥ÇDµ—2æÓÓ®˜–±íAI’—]1-)y€*¦T1-ò€C1ý’¤<ÈNÅ4¼™yà¤ãœ—ÃübÄë8ë7´®¤å`ð£ã\#ÂéXÒõÆ\+'P ޹Ûq8Ä ’ó&XQ{ËYÆ _ÔÝuÕ2æ-öº¨LXEØpÐE%iä[èú² ! J’V¸£ ÁÒ2þ0E±ñÓp$J„/~zÀë|xŸ”>@­ àºà%ÂÝ~Ð0 ¸0´vÅ5€¡M (&~º(­¿ÑÓ¶`Lq®‡0?é †X }p>!ä—]ªi/Ê$òÚ¥ÂÛR v©ŠO<‚‹ý‰GÅîðá“üGE ·8ƲÊ$e“ïìv3Ž2 <4¶¾†ý s°Ì¤êÍÄ¿¶$ÌÁ6q¬WG óÈ4àÂB:RLC¯íþ¢ðÉ@¸ ¹8 ôâuùBÐÑ@P‚qÂ=_ªý­A ‡W@wxÈ4òš ãß{ŠX.ÓÄor<\ŽsŸºev•Ù©Ài2»dv€:ÂBr4 Ÿæ¹¦r ¨#,ä ¯‰OÑfC7˜4 +³›j×9ïcUS»ìl¯#ýEVŒgÞL€ÚÎ'ÿosMXÏiË×ãÕæá;Ñ_LŽ –Ü,§ìýxWeMPéŠÚÆÊoF;Þïoh%ᬜ®§‚Ÿôêz`IJ¸3‘ð¬Á9w[WÒ£C¶® ¤Gm€~¼*P>?^èŠõãíG‚büx±ˆ(ÅèÿàÈ­íí³|`QD'ÿ6[úÒ$Uý¤äè¶x[WÆð%(Éõlfú‹Ô¬ ÇnãPàã»ò#6rJÕcó$(ÂÃ- ßuåá~êb cI.™«†;”x2kp©yÄ^º}* ܇°­à‰‡0†Ì!¬ïŽC˜"fÖ!lY÷Ç!LqfÕÚ%ÂC˜"f' ¿å‘l%x£¿e6£*”Ž#÷r‹ú¾ëú²Æ±N9lµÙÈ M1” jOCDZ6jýòÎiJ:ÂW.;\—æË¢õòu¢<©ëÌÙÞ=Üm&|…IVV÷Ëëp‚ßüm1RVÉ­(ÊaÐ5×·ÇœÁNSJÎ/½>Žð€bð=E±Gxø²Iit’k`Âþ#¹–Ø$×PÔQÚÍ×83x¼ëzºÀÒ­ýÕ/j‚±Ø|›úPj+™ðN»ÊIÉÔ£…B.˜RŽÏÇúýظ™ØFU¬ ÃHrn•^§}xå+éñ(&D)Ö~óð(QJù”Ç ©”äÚÎ8ÚorGQ‚±ŒÏRÏ\^Ë»fªø§jGzÊVÉÏ~tmC¬G°fššÊ×êð1p¥]ïw(q—èû- â©¥¸,Ì®>åœr¦C» 4¯ç>8£ê H89£0š7Ä.j€¯† xxJ³ ôîH¦T”"áP«™Ö”ÒÒg|ˆµ ­|ƇÅe$(Gràòlï\i¥µóŽ›+íIËZÛo€Šù'mg7*øflg•N*B¶,/:–KãŸõÍòb½TÂåDŠŽX®tw8M¨Húœ&ðDù½@p&”ß×m$(ÁY$ãÕó¹a‡6\E×°=‰XE±Oñ‰ïœˆÏn¿îžz*J½&üpT‹ÒŸUHT­}_ÂÓž$bTȪ8ô2Ðáy$N'¯†µBdf5¶¿Ûjéëy=îFÿ®~ÃÕm¨ ¾È±²¿¢[4ø:_å0Yy#(y n¹ÑAtYSî×A)šƒµMD>•Ÿëüý<J(ÐÆ<šlª‹ös'¨è„z/¨á[(ó‹ó·˜‹×LP‰•ÊnT¢ûdeNPÆ’õ™/Ão^æëþiû+Õà[§µý……Ûœ LÆ{6•÷âAÓ¤œüE£à×K»>ʶ¢0š2S@¸¿eËûœÞ¥PÑ0š`Y>f/ëG5¡âÝ`´ö‘ÕYKïS9`ï¼]F³®->`å ~´Í«åÚ¬Ñ f$Qíí½Lã‡ÂRÒò6*™W3ôM6~èŠà§3¾,¢•pôZú—ŠÐò\4?:gås¸ &ˆë­ñªÞ\o»oIï©8|±9³a_ã4ÕÖ¥°6;Á4…U¦qÜgeÓ”ÖµE‡qÙ¶@Êå;äãµ-X|†½‡ìK̼µ_÷¡ú.;Å'…¥Ôà·2©FmÖÝPзBà‚=XmÁBšXTêg;ϱ±`Çñí ò責릎¾Ö¤tÁÞ]×ٰå܈緎ûuš¦+ýK¥&0sï—õÖ4ßoiÁ"« Ñd].ּɫ̗•a´³íü.§¬¡°ä0„ƒ×²zÛ².^t…HãîÞƒ…Q\dÏ®mGú£*@˜y9lñƒY»Üª†ÞzRضBÞ㫾MA¯M‘Ü%øÊ¾†>늯õqQòû OY …õ£Û]˜þ5b– 2^ÊûãÝ–¦ ¬Â(˜Ûøxµ#…EØC]>¡fKžÏýÜ?Kk!©øh¢B«µ›žŸ{[LôqVG¯Õ|aÊê;ŽyvûŽÖ_šþœ¶îÈý~ÇÊIìÒ •˜s þ‚ŠÏ KeյϚúĹf'Œmõ•fÙ`Î¥Š5GéHñ7ޤxR#A/R<©%¡ÊÚ7€| bQ‰ô—à‰(‘œ)þô^î–QL©D±´™U’ ‚Dù\Q°ŸœhŸ6hÇTb“E·!Ï$ú킨ïª÷ÜÕW‚\Ô¸fŠé|.c å^«G“ˆg©IU!I|UP+§[˶±š?·¡|ÁLð¾a› ÂÜGâñqª‰Ô9PƒTx\gÑB¥!@³ U¥,ÙÞõ!TQ©ð¬û {­©ôy IqĦeݯ,h §¤Ú‚‚¤2•F¬z´ZÕ£0«béî#¥RŸ¿3z ¨Ô.g°=RSšÑ9éöÕ·žÈÆp·Ë±Ÿí@Pâœa;n~GÃ… $“a U>@ýð–±–¿¯z|¯f·(}Žzªò<àITäJ}?YÖT|¦7w«ìÓÜ!@%ÎjG?5E¥§¯Õò¤µy1áXÂã¶Œ0Ð*ŸÕ.ëÇKÝ#JyiÄÌ„·Š 2h–×´õkàEž* :$ëÀëN ìMUÎ;$ë ùaàäèq7VŸúõê ŠÖÉÀçv\Œoãb I ÊA¯[¿¢M_­ÍŸAYNx¬ÕçòýèZ‚Ú%W¤».'½G[@}XÓ@•7J² b}T}ž¾x““dg;(­ë«Ÿ#+qSË+P™ë å7²eÝÌ£y†ÂE˲~”õloâä~95Nc]N%Ï àäSm„Øòl7Œ7ÑÔUä7èåù„Ú©ƒßì Œpé³÷ü4.€:_×6³Å~]}]?ó…3!¼óUŒÅμ}CÁÎײy߯K¸ùàˆ(驦au[ŸÝN ܉öóûò…û¨OL*Œƒ™ªkÓ< JpÑ2 $³ãƒ¶: ãß}2>ñ™h(Jœüéë ñ§×aìñ§¿>ç‘ ú/H4ÅùÓçMCPŠ‘gÌ3E9"@/ÄŸP‘{ƒB;&ç¸4ò‚wN˜º×ÄÚ?Ö„˜5±ÒÏ÷5!¶ó¾22:–{‡|¬ X¬RÛ …ÕšK@1-8éhÞ_¥;d6ZHΕ½>d6ZHŽð³yáÕ+oüêÔ¿ŠwH(oüª5–+~õ¾Å¯R”æüüMm^ íõ󇯻ÐL?pÙûîô.}N@±€Š½‚Ši"¨3££‚ @9ØTJYï ¨%õyÓ•¥A%6#«îùÔÅ¥5EZ-ÈÙ kÛˆú^2S›”$î•æz5ë©o÷Œ ÔÇ冺=ÆoNQš̰üö^©bAEî ã²Çµz8aBU S²e²òç— .ÙœN•rqÈ·†ÎjÀå!¿é`aÈ"éõ‡‚±’Bµ^;3h jbôógû(_ñ˜ÜõÏç> 2<…TÀ¶üry~;c?¢¥`õ—M½¼U‚îŠB*ôfã©@ý% R‘î†ÓÖ$ê>o³¨¥ü±ž†Éϧ!ÐòH‚ÔÏÒ_Çj Ž&)èu€õtW}>×{OQQ”ùz”ù}þæÖXG³&‡N>U¯¼hÛ;AEVÛ¶OSܳ7AÅ®æJUWÿ'ìºreÕ•è”H¶áó àH÷ &çš ;ú¸ŒË`ûJûs‰fp¨Za®ð/†è ÃTQÔÓ²©Çäë3*Ömݳª£ÀàbS7Y†a¨Q“Ðkêµ!.K óÔ ­‚÷%Šaý4æcØõ&þæ_œÌs‚Ÿ¥‹Ã…ú¢«·9VïàîÌDüôÉÃ(‚Á1¥/»¢I¦Ãž xRe=ì0á,ÄóâUœþæSÙWãªÀ"Üöá3K:Åu1x@<ç §ãcž¦ Ãd£ætßàow–ÎÇF^ù< ƒo3ÝÒôŒ(S`>n­ð¶­ÉÐÊwµ(•ºâ·ÿê:V`Á  vÇäþC?À¨㽦ì¬éÃÉ`LŠkÇrµ¤ÊbŠX¨Vù¤eç.CùÑHÛ÷_>eø_€vÙß?h˧¥è æâªäŸxúî;'aY°lþ-ÕŽ½ï‹EåbÉ\íöS'2¥ÝÃø~ýß¿(KbhÚbËÈèÀÄgæZ ö¢ê O€QSââÿi`Îd'Q ñCRÌ¥‚ª0ñ‰e¹A¦N|[>ÝqºäûßÈÃê¯Ü¸{3÷SRΉÙ„ñÀ!c‘Gf1r?/[’7¬H r§Î¾2gÔ®c;®+|§Ú Ü{9ŽÓe†»™çrǯuÜØ<”uKÞQ­½û–ÅcT`r¬++„"ÊâÃQE^çeÚ!U !2Žê¦Z0Šé6$³ÜRòÎQÜAç@}TγV!c"Þ YŠcú©‹®Ç£êà-è§¥¬æ~™0ÌÕf@|—T}Fž<¢eNQÄñž¬Êðóåî_1²%Wåm[•†½Ø=¯–¸U®F^äÖ¶mü1ŒJw%È ?>ñ²X›UfðÂ_ïùîé…ô¥7“•À@lÙ•êUÔ  4UŸ:žÇ­åB=z:W¦Dß—å:6囲øÄ·D5â&™ÅçG”w+½À€a»¸OåL…€åFfKŽS!ò°tS³Wãû ÙsxĨÚsxÄ6rQ?ßè?2ߢúf¦„¥Ž°(#ŒØòžAJ°™–ÎÌtB(“ŠE̘ŒÙGÅ7ĘÅE$$Õñ ¿½ìP„úáXÖD5E2ëæ7ØÔåëR´%‹„޹£~+ø:"çí0ޏ+P޳Rg<6B1]fœäË‘È5ðåÊIòåHäšüä'É—#‘k±kÜïÿÑÕ'ÚrË*ÑÓ‰<£ºF2@Iä›YˆgžP`ÖŸó}PžáZbWëµà]Œ¤µt|!‘E9w® €zê7ù”y*3×µéw@…z³Ü³jÐ ¥¸{›~Sh. JIRÜðT¶ãtD(½Ad¹‹µV¦$iS¡ÅsŒÌ»íx1u«Ò_‹:®>µ,›Ò">Ž1€ò^ú`èxNÝ< œôNQ‚r:ÿòe;N Bùo“€äŠN€’¬ÑÆØ·i¯ÊóM…^2‘Ù97}Ì["€Bò•âšLN1Ì·ûrG(¦áYmÇ?1BÝâ•$ÉùO¶}–VŸÏˆÿÇHi“•×›óùLÝòéð¨:RäÚ•ã#j׎æÞZ>ž°®¿Ë‚ïŸ×ˆþlùAà"â÷ËWMõÅ0_ãrð=Þ×Y}â)Ö¶—Ì··ÅA™šhz ],aЈÅQO¸àQ‡XÀ3ܾM´/\©ÃÌ‘ ãñÃKšÜ6¸­übdµUØ6„26òGŒ26ò÷¡½h¿.8—ºŽ±T|šfó-$E„²gPJ1´`Á/NñÐä;þEª·uE0êiÂ1ù"Y'e¿òM+õÈ»D ¨ãL¤¢<%¤æÚÅœEú™?õ–@}×%އIÜ=Qü‰nÔ²~¿ß’EÄÍK?Wkó»”CÉ‹€Bý _íš¬ëœ 3|Û+W*Ô¯ ¢LIm¤¹½Éµ‘æêy1Êè’_­÷¶®D&ž¥xBÔbj#ìjèÓÿê¶Ý+9½«»§z#×éÓ§O9º)dÑ˧çÜê…&WócP£æ„PÁ;B>Ù›5IÄÝG/®RΛ~EGµS/zø1ÃÝ·ÕÞ ”¯j_‡ß„P&ƒ}:3ØëB“k3ŒªïXdK{-P®>•á,ŽÉ:ð±÷ídQX”à5MVÏŒPúT™Ûb†¢¶¿Öb¦G(O+Hº6tEl’1ñFûÔV #@yï÷ˆ¨ÁÔgú÷1ö²ÀM}f(pŸåQাeu¿ ÜT¯iL4„û Å1ho[+ðü§~dEq‹,8f‘ÚÝô k“fõ }XQ=ÂWžYQ=Œ/Æc{ e:Ty£øØÄdÿºÉ¢}C yc-í_©lÇ>í_{iÿJ£r“ö¯€ L(øÒfìÂ×ñHØR‹Meëc™K?±(ŒRS;b á9ÇRl.JÌ•3šx”g h,á4G<ƒIìç4‰ç!d %‹:W1³Ÿ›y[„òô«•0‰”É$¶íñ/Mb•k“ý+¬iDò6‘ýkQ‚ý+ÌÄ™Ärû×ÏÞÄç9¡BÌï‚Á7Ï—oï ›Äòõ±/Ç9¯ç—Ñ$v¬˜«]“o3ã¯ØñŠ]n=gÝüƒ[CŸ÷‹¿}Ìs€"O…ø7/í÷Mj„R·À¶X{K„ò5ºÑMöÕ(ê™?}¹d %Ì¢"J{JBk{†»¬Î Fyú¼Ú4#uÖß:¢2ã Z@yz…¶¨³RäÞ¥Sõ”§gº€ªîžzf¦KÛü`{B=Óå¬zÙRߪτ±§MŸ)JMg«Gê($iSj*[͵ Ï¡”ZC`2§fß7™KÍÎV½tL (ZJcã Ž ”FŸ¼c×Ç‘96àwP“³x`ÂBjƒ)Ê|k 0,‘,°¦ @‰kÊ€¸ÖÛ‰œÏ&œ Óá#œé#§â¥N>\A•p&Ä–ÌævÛ¶aÇ×òu¥“¤™2®±¡(œ X W¹¶üÍU\Í?în (¢ó^êº91J²q¡í»*ÍÊOŠPLò×á•øÍK|ÜÌ&Œ*âÎÀ¿Èð계Š0ªäü*NŽuYUQæoO¨ªèl `.†•@Ö®šùS+0OÇÓ?®–÷øÖ°8 &Yßã?¸RXÀ°8 ¸vÊÇÕ–æ¦EF4°ãݯç¿RÀ h sjæ>ƃë2ñôÓâ'冊¡È º¡ï¡®°³Þ¿_ó&WÞZG…q ¤dÍ!BÀ\ÕP‰Ãú!©< ž§*]çÜ­X…1€ùª¡¿Ú¼WS~4ÐñiÏ ^ð¸qqÀë þ½껓Z.jôu0h–¶Yk.‚0†Üˆ„f%^¶¥]”ÿ4İêpK7uí€a‘Ø–]»X> K;5ùÿè%o#^8©ÙïWl9¾Ú)X9æo’‰§ÐLÍ7‡›ïìb€´B™9~þ:EÀ°ÙâçOËd„òLd@X‚Yd6K¼#ÐièX"ã…@š†®Å•ÿ^RBÏP9P² ¾+œ²T'wÊ +MjK!±Y‰Gø’“ RAýMÇãà(ª{NfÞσxP¸¿$êgq²Þí\D4ùƒ]ÓÛ¾ïÒ:VPÞÝ…²¡|½« 2Ñ04™Òló¡ŒD¦ £|}’ßI~4Œ¬I~=Fyú~‰Hò”¯ï—ˆ$?@ú~ÉwT®eJòËa»ÈQš$¿¥*+‘ä(öNß›Pú B]ø^z‡ï*Ò›B ¢ Åùo" &çhß1¡viɹ%Ÿ'É£]Ø.ÓohDÍ^Òd´êUØ FžÍzîÔL€9 Û |Û‘•ÂÛ.0 ï1çÀ;"6j±8h<2Û Ï¢2f´Iâ\øÒ"›)t+úã‘ÙúJ[…»·§ps[ ,“˜cë Òs<érì™ãï^`˜ã[bDeŒ9Êà]cŽ1%½–uv† Â'5+„ê6rTæP=ª­Óö×g<ãŽá¨/ØÐiå¸V†l£4Ô;˜7™šÀoº/s" Of_ù!޹êð½'bÈxI¡ûž™¾7Ý—!ã¥GÚø>k._˜ë=¬±@ |ŒUšn}Q#”Þ´>†ÛÌ5š ô— Fy¾”K˜(4ÜpûüÞº8ËãŠoÍÙ# í.%üêxž×™‹% HªÿŒ{/ß4î¹g“vCªe×YJøvÃÖ!”œ2a{×VE²}Û¡ˆj×Á‹i3åqPTU¯sT#š¸à´ˆ²SŠ«ÑÍU¦Ù'8Ñ3…Âsm#ùgôK³á&O0}¦‰Å…z"s#›K#´a™ç¨^ó· U;ó&Ï9Ê5¹ËìsÓdœÑÈ0í;§Ÿ¨OÙT#Bù:+‹ªY¦_+ГsŠo‚ET¯¸V_Õ¿¡p€Ÿ*Ò­ÌRá(¦sªù&=Ðêé@Ç}õè@ÙºáQu^cõ•1ïøbª»ŒùjžQÊCæÙ¤l| ˆõ¤á=Žâßôl¼G²1ÏÓ¿®<:˜] ™ZiÍa'„Ò§žA 0Ñ8UÊ™g·D…=¢gÎg–m †85W1:fDÉAëðIÓö—¯’WdþlqÚÖBaS>˜œæ²+jà 1lÒ„_×rÞ~ý0¤5BÒì;uöTÇɺ—#B™ƒ\f¼‡?gK¿M°‹—&M¯à£“Ú {DiÒ¤KÐÞÅÝÿGŒÇ†P&á8]øŽ5õšWØ;]íÕ„ ‡ù®åÍü æ{OÑB.Rœ§¼Yà-ôý§XçÞÅÏu3Áþùñ5>ç¥Íº;ŽçÓ'ÊÏŸ+pÄ× ^žPçâ7 ÃŽïK•áðfÚùmŒ°¬I_¢cšøÃQ·øÏŽ-þEfàûа™7RdË|bä3ÚÓ4ذ7»H0-›cg®¢|€þ+-°™ZxñÞG†´KnÀ™Ï ”h¬Go”c¼Ö>7ʳF=×øÆLL~Èãi“ᇠEØiÃk„2‡â_ 46“›ä’±Àd=zê„Í$ LÖ£<÷3Æ×Òsn›I@ûq±Šbn”Æ~<éÊÓ ‰Ç¶†Ó×ßoL²±ØÃ^YÒ×RbÇ‚ÐdI_K‰ B KHìX*Oè{ÎŽl¶2ŸaŽ,ö=wõÇÊ(¾!âÚ…×ü‰Á¼ ¯ðš!nÔCx=-­^Ê׳áE·…½TÊ:ÔÂúHë:ÔÖe\‡Ú¡Œë̾$ЯCçÌ$×!ØÖ¡²Á¿h\‡”_dú€ ®ÉÈC",,Ï€ŽekZ¸/³ ~|šàc”1Áæ¬Ò?q÷OËð\ôв6+6(…‘è)ëå•…“z<È£Ô aÐ0~ îÝÆ¨ceŠóþ!{Dþ=cÔྨg ±”BuFmYÖByÆÑ硹¤„¼'Ã(1«Øî*=£ÔHJ+Å3&eTÁ¿¡qÏàeq-fŠºœ¤•£¡"ΔëPwßx GØýOÉfîæ}jKŒò4¨ß\Mœ­¡…޵ §&æ{ k³G¨7k³oº})ÁÎ1×D¨éæ>)à¾VàüƒìÇŽ»¯“­ª —nnÅ8åy‡Q)\¯D5-ñ¸ÕiPØh–Ï_ǵº¡¢" è+Rò¸«nÙ@(† œÞrÕðf`Ã3ùw‹] Ì7>y=Byº²B<ç´ ¡üW®ÔY뛼Â× „qàõAB‡·úÌ÷¨zOkî\˜ÑnÍÞ E…m`,®u òx­6|_L¨PO9©ªã,=#Th0¢k-ómÑÆb`¡Ÿö5{È©goŠÞ=þÄ;A»Gi/Á,f"²É³ÅÅŠ¢ZÒP#a§€lBŠÇ\¨¥š%c‘¢ñ¼u`ãé¬*t` Û„¨g«Ó¶GT}MÈ«»~ò'„ÒT}~¶êJ[õï+@úwBèÓXèZõ0°'=k¤7¬¢¡¹øí~;×w0›åÈÝfa`Œ6¾Š§|ìCQQÐ,YHÍ:Š=µŽYYúâ MÖj_i­ÆÂèѱ„^d[—Ùoì¡gFVk5®ˆcˆK¡SÎB%YŽ(êº+g™´Q•³#VβÈÑ™¹‰ˆˆÔ`æ8¦úÊèâO;òl{€žcäÛö@”.˜j9vËb쑇²'¯›í¬ Á~" Ýbå E¾[ü–Lv‹#ÕP?¹¦ßvÚ¿KÒÆEô=å¦^ð}Ñ×) ¯²¢^E5* žÝâ»Ã[­Ë}à(xu‹EOù8~¦¡"ã[XàQuÞ¡‡±Éñ¹˜êX^£‘ûºW`žÊ„¦ò¶¤Ý€a¾¾©üMcü”Ýâû sòŒ1Œ¼O2'¬}Í(xNi ƒL–cÉ*àA1[Y\`å™2l`S„\_t¹3âZ䕃ïë µ•ˆîkQ³'’,ãG¡~+p6¨oj‹"kfÖÐqLx“,넎k¢mR":®É¯–ÁÐqÅ ) ³_$_†ŽÅ/èÖx„ŽÖùíÌAÞË&.9Ã;tž°ñúOSÏŸïoG(ï%Ϊ›~>¶šiPÊU@ŒlµÌP>T Ð€L8ÆŸý³!š 2NÊí?ùÜÿ,BQL .€ÜݯD¯Åt¢±8M§ß}¨‘8ïMÒ”#¾V„7ʰ^¦æ˜_g<ªÎmíh‰§!Æs] ¬86›11e¹f<×xI–¬šAù:ùu½6#ï= ¯Çˆg`ÆÕ2Mr5‚fàŸTŽŸi‚ePÀ¨V`V~ÇMùQ¦˜•µò¤þOØ•,;¨+É_bFZö¾_D¿O›á›Ñ6Äýú–P”@Ò]œ]p°jÈÊ<Ý¥ÍÃÖÌpÓÔC¡HÄŒ0µl +øÉùxy8Ŝܧ°2- AYÙŽç` ˜â[,à^P7Tdm¡ÊÈÂÀ-å'ƒ#Á²0tvö§×ë"Œ|ÝàW²Ð-Vvò+Yè´_¯Ãd‡…‰›÷©-W‚re+Àw”+[ã^@%#Zð\a”¤>^MpkBù=*Áº¬Â§’Õªµ–<Ú¦ "“R¡j ]ÑtC]ÍcÇøeà.+AM—G&Ërÿ1}.j߀Üê·ø6%l=áeäØ,2w‹WWh§@å´&£Ï@µ¥/PýÔùmW€ú~ÞÓûÑuÅÈT¡52ß߯}«§F çÃ$lý¼Pч˜(kQÔõ»¥°È 0©’kß5ÍPŒ}´VÏÿéÕÓ F×Ð} Øþ.àê ×èZ¢£°Ô.òˆWfŒ~­ ¨ÜavÚ×b.¾¼ÎÕYä¶s8…?¡CY…?{‚Š\6ßðk{,ßNÕFØ1V¡z¸Vâª_ ê>¾+¨P=#º4÷IÔc”Có!°Ùïm€“-rÏÂ…<ÿz‚²Ï,ˆ *¶Ÿl팿ÐÍ6ñ´1ù Pc„s³1ig°~gW>ŽŽCwû^ˆ hØ€ŠâX t¢«0`»‚Ò3KBã&J²±$òI²mÊ)ɶQ”K’ h‡,‰n4”C(êh´³$vĪÆ1 Ü„Õs Œ%©wl>î$ó9Íb*“ä^} ¼óÈI!ù•%Üh &™í² åZœŒPm°î¤‡º®ÿu¤ði`©;µ ³?uP†/º./í{’9– ¨ÄPõµá¾‘ü› RcÈbßšTõ¡¶7 2œRØC+­Å2ɇ/ŒçÊoc‰ú|¾cAïȬ«|ÿ‚>=·ÖÏ¢Aú}hf‚²ÛÊ}îù´k¶™¢‚¾ (5ɬÊöª* [fš8ŰΖKSÖQZHS·ôì1°ÈÒÌï@Q‘cøw€4÷·ž¢íelT±”¹†ÝÅ9ìÎR¯'´ªY¸$ÙZ%¶¿cæ¡:c ,‹\®Èâs¸§³Ì=¨«þEØï³Ø>Ø¥ß*Vê©ÖìRgÇ`Ë’›,«¡8Ïõ/ŠSAݧUœbYêòBg«še™ŸÖ Ï•{i­° 3¿‹4¾/¿‹4>Wîr®ŸO%,–ùöûs}q·|àA÷`yà—n¤(çhp (·`áI‡dyäq|:b¦P¤ž1s$¾Àù6ѾšrÛBP¬à}•¥XûWGPñ½¬8«²âÊŠÌ‘ôõ»ùx9Ók¥·iñ^™Ï0¨{Á°¥3€ÊmƒL§Ã  ˜C1¯Å_;ó¶ÀÓç¾Ñ–ŸÞ»ßÃh cÞý‹È,¿ô\I[­•- ˜Ç£eÃr'ãÎ,óT¹c„ds„÷ÅÃË \õÔ…€½É…íBÛ!ƒrª`¸ÊiiP@9å å‘wP"ÙåÚ¹?åu”Sÿä>('šž ¬ƒr2iZ½cîeÄÓ'"7“®•¸ r‡ ã©‚Ýâï˜yEDà|之ˆ¶“¡`_½ùöd¨—è *rø « b öÎ,Ò- ;,_íBÌNß+ÍɸVfºó‚íîëUL5AYKHo™¨UÅ¡Gv–,¡–¢t+l­Ðòû³ òÇÜÄ aÞ à0ò pégõ'Ɇ{ˆ1眳Åë9ÁǃÈo“)Êm“Ù”ËõHÄî0íPààAâWà (‡vŠyz¢‚9dž¢Õ‚rdž¢•E9ŠVþÚ™sâñ,ÌñÀü¸ \_½ê-n°ò€y·¦ž‹Ú7e}Ç0ð+ƒtݦ¬÷â#*YsÂj0{拌­¶BPTdlMÚl™»±Öz=€Š-öd‹²'kéµ4é³ǹ_^½Ö©$VA ü3n_y"Ã* Cƒà[æ~Çe)§‘^+wXÁÜ- ˜¥-ý¬Úº'€²ëJwýo3Þj`«Z)>7,°ð+°ÍÔÂ!Ã9­Æžý=tx˜ø½6¸û‡Œø(ÔçWB–•žƒ@ûw¢3צÇö;6%œóéynEÊþ+6Õ_!ß¼LÛŠ_ŒTd¼öW¼·ßïAï¿•F“öŸß÷ûÙüºšÂ ¿•ý¦ëº}v×ÐB‚ü«AP§æ…ú}t_¼ý{÷?¼ãù±é]ýQ¡Wt»ýðˆÈÌ Q~Þ­®:­Jì­ûÁs™,ú5/¶ßßø›;Ø*¨ Ý]§îõîê–>!„é4Ê\íòWÍÝï×TlÓVŠ0/¸–{&u›6ÏÅì*T•x62¶€°4c—™ êðRCëP vô DÉ„`Ãf ÒCoDíåêW?r ¾…ʈ«ñ¡´U–%(Õ ‚êÿ@yDÕé÷òÈb<ýÝoE~Úß©{Åm„°“ªÊ3î!„x¢íesà†r!ÐYÜJ xz¢Úeq+ýÀ>‘î ,╸¤ }Í}“;HÙãyä&íž½›Ö}¸}pˆQ¢B¿{ÊJP.ŸÚïù|j'uîàPÞgÞrW}STìp³5¯•ÐSt¦‡¿¡ÓNˆJíc¦ÇŽéQ°";fûvL]%CTlÕ1o×y†·šxøgýÚÂSÿì#`g"¾swþÙÒ®ôZDÃGyÿîŒxÕs÷ ÊÞ9˜€Ù‹¨Ôáoz¼ Ç>!ô>ÑQ”M[õ=VÖV•¨ü¢k[éBÍgy¾¶uúû#(ZP×õéÆê6dˆ"fò{¯h÷ÅlÅoé»3}Ù÷%A¥. ÓåAP™ó܆_ˆùÏmAP.ÒÂ&(*¶(ºo[QÌpZ…ü2Öt*EóZ€N…¨ÈF§ªŠ¢Îa›ª—¾±*ÞﯠwL,1“ªlM¸îù%;9ž~”¡èÖÑ;f·ú—Øë_ZÈ Qùš¥¤××NÑS#ʤfÉ÷uP³Å]í·‚>½nSܹY­¶·8`¡å[ÛÉYÆFÕ]Üʃ(pÜ*ümõ¿ÅÞ€Q¡7à6P‘+ÄG”¯8upÈDNédmg¢_E”z“iøŒ¢Ë„âN$TÝ{›·²û> *v¥Ü¯™ [Ê]¨”›¢œÉtKŸ+³X£œÉ4¢\É´Vu@”3™n)Š_JMh­å…$*s - †`QîZÚ: Á(§Rm敚(P—zVm?·»"¢b{#i›¸#óéàL°FÜ7ލ8¸§`Ô)ç{½ )cï¦sÜkc‰Šý:Ç‚ ÜúËp­Ä¯¿,*r=WOùu¡A9l„a4A¢RŸÁ¦ 'cïžTLP®•¨1A†çb¾vÀÛ4Q*Âtâ¿ÏOÿÓÇmÌ¢s›Êuf‚Š\°ð¾’À­ÏƒsØzZ  –#Q‘}rr”Aß4h‰ºZ;ÕšG$w¹_¹=¶‚ È0ökZ5RT–ôZw8¨Í*êï¯#¨Ä@µ5ˆ÷³þ”QÂT_‹ÏÔS”19Ù‚aý~ëÉID%|D½ÛVON"Ê- OŸø•úõ6¢Üæ§‚ Üæ§ôމ]éÔ«$Ê7#LˆrªWMåR¯j¡¬p2­Šðm'¹w@¾¡$÷ (öE9!ÐIhbnù:à¹nõ"cE_Y‰5ZÇ+ú:W +Z˜+ú,Í+Z˜+š]¡ ¢èŠ&Ík Ç÷ ‡IŒ &1ˆ²™ÄˆÃ$Q±qn· Ä]ayx§È[½rÒËÿéF|ÚDITì·‰ê ÊmE¯å¶‰ZÊm%Êm5”Û&Š¢Ü6QpDZ‰š ÊmE¯å¶‰¢×rÛDõ嶉êÊmµ”Û&j%(v_9¥JG±›Þè>Mƒ’Åݲ~g‚rP(Žt”ØZÒÑ— (g: ¥¦Ó®ÐšhB2}ÚÒDsÿjU¢ »/µ+¼¸(k‘‚Þ‘Ñ=§Æ=§þjÍ9DÝÇwe:ºÔG:š&Þttê ˜]…HäÐ{†6gSñ|.êÔÃ1šVHûåÒÂ1ÂÚ"¥\Þ9Fº3(Ǩ5P.ŽÑb \£ ziêæµãb<½•c¤ºÉÆû²Ó]'ðΖ¨ÌŒwšÛ»}0}ŒsW ·‡€£;åî ¤ø› ”½)ö’NÆâ}Œ¼h1 :‹P-+“LFå«èuˆŸ…×±)y)ìÈ\µ,4“°Ëµ XÈ﵆š "g%®ù+É‚ œƒGb%¨Ø%ݸÀµb¯tcGQ­ÞR@å=KncŸûÊ»¸S Õr*ÀwÑêU²M‚¢â›l“вM¼gɽެ9軾î¶Tj•Ìš¦ã×N.[ScŸï¾m* xçÖá·M„-ܺ?X÷§0à}¼Re}•84H:¸³ÌïBQNÍå7Ü1¿É ¹<ˆG÷¤¨È®¹Üv3EÅwÍåéù|оÚSdЪ“Œ¿cnÿ÷_ûüÏ®ÚeÐtÛ¦¹ìt©)cWwHû–©ø4XN#,VG5P‚ â[½Y ‡ŽC…¦Ärg6Ø(Ê6hºüz‚Ê‚…X¶Ê¸…ÿ¼«±4e_V]NËWØÔȰi€À6¿pþ°Í¢†«†ajŸElªlÆB›äÏÖ©-{‚Jéxx³—¶”H×P/+A9mz­Ü1Ò°<¸Ø:Ñp®Áp.N[':Ò-ôH7„sðVK<÷ÿ„]Ù²«:²ü¥Óc¿wGœû ØL66ƒ Ñ_%TB%P©÷ÛŽÈR Y™ûL÷ŠŸ´u2À([§á¤ˆQ~MOƽ‘_3â,!†ÄMä°”ˆü„pþõ¬ÿvJ;CóþÎÍó‰a¹—Ri´8% QFþcê¶ S¹µúK“ÏÝß”“FE—tS˜È•óèïúMDÖT‚•«Ø3•ŸyjÛ¡˜ö/MN*¿Æ©é_û0”Aé_…ÛM¥#«á#ÓÃ×Kt•Øwßh=¯a†©ïwoDƒJ Τ˱Ñ_ì9‘åÖ«zkj, þFF¨ÕOû`•þ…¢?v1S4œ}ÄllÜ‘ŸÞê^"ŵ ¨‹ÑÚ1Ï£\e§í• ŠQÚ'#íÃ=EØnš |¶›£²Ý Byl7¡Œ‡¯EÚnnøo$l7Ç^w•gˆå¢ˆ‡(Ϋƒ¢(ÎzTРœ~~§O¾vªd„ÿB(î?EgaÞ'ÎÇÏöÛá.Êw>öê||õåœÚefkÅ[´ÎÓ磩)ª <Ñfx®$äÕfN¾(¡P╨4¤±rìYPo„§ÏžhÝhþÆ"À3œÑ(þ£tŒ…D…¼Ž U=Br°¾øÞbÏ:ñý¨V‰ï#+ëÆ÷£@ñ}då`/¬Ëûö–•¬KüB­#²ŒW¿Ç—^…1§vÆãË °3 hiŒÃ²,3Ä^[×ÁÆ b»&ÌÙÑÝG™mB]+5cßu%¸“§¤3\+»ziíVZã "1ÃÓçì׌ÚDqÞ/Wx«ìÏÏ“z‚ûà„P± z^7Œºò¤pÅ} ˆJŽb…øYi/ENdåj..5œ|,Þ¢4F´>÷ޱÃZ²«P&Év2æ_…û^x¬Â“ùëy·M™¿Â*ìðµ8Uµ6¿#§y±á$G, ¢>_p­4<Š: áÌ7Ž3<ýÙùä ×ÊCQ­Ù1±Þ%~ª>Q¿æZÿB˜={2‰þ¾êüŽ^½Kd-Š2‰6ûü¨š“ ¬ˆ¢ŠDÄù }ì/„ø§¾_Hsu_+5ZbIWj"â]ƒ$¼D¥!¡  ƒÓÐô-_† ¤[øsǼWNíoƒø‹±ûß6U„)¡w!Þ¢ÖýS€Š »éõìÖ²C(FÕ¬4} B΢ך•ÌÔ&„¢D+ô¼AQ¢ÓˆQךհ‹VtË%~Ñ U³Úš V!ruE+>J¹ jCr=åCÛï÷ëœçʽ¿ãïø­³èICì >ØØf0˜7×y˨rä:UasI@®“D~2 É_‹ùrîyä:ItÒpu) ε®Ó¾!×I"¿£SŽa3Be‡ªºÖÓ¶ìTŠÕLŠÏ<­+~ý‘·3-¿7“‡%Ù™–‹òv¦e˜i²µ$(S0u¡¨Î4tåt¦µxà<ü?TêÉ[™·þîo„Ê.ý²NOø™.!ðôEø YŠþB&„¢¿|­ë"Ü/¤ð!ÂýBŠð‚ïH!øMÐ_ÈŒPôÒã·J!†]¿á~!Eà YíR /Ä#L¿xJЄ&¡é1þèDÛ=‘½ÌK#’á¯zþp†¤Ñét{þ#¾§zþšÅ¨«3ǰ“¸`üP©—õ¾û7þ3Š?à<=6ÔXYçÓdê©kÐub˜\,¥ ºFÅ’êñãGqš88I1ŸAù Ó1Ŗß`¨DÈ÷ÛSÉ3}§”ûÓP™BÄ]O¬ýéw/±þÑŸŽÒ„Žõþtd‰»×X_F 3¾#ÕŸžÌûJˆþ´ë§I(Ößœç¢b}“¤‰?Öÿ Ôë6o•Žõ{ #=^ͪN~±#L3F^ôÖd“&·»|[Xas÷z‰òDDðýG³›4Gvéd°ÿý™¿2DËëhÞX±iKû#Ü›‹bþê´á•DÙ]3ÛŽÊG¥RáóÎ"^ýìz§Lð¾2ª–§Äl N”Å1[3# (ZB £˜G÷`:ã$Š9_7¢î–/¹MC¼ƒ9œ¸g©f ·éù>æpº¨e~LX™;!&ãŠâŠùó~O F¤o4͸Ìómø¬•\½Ù»Þ²ú¢,ñ{³w›ö6(7»êƒ7»AQ¬>x'$o7øÒ²ÔÇê37¦6•ed6¦ªšÐÑÏò ³ ¢…¬ º” 2ä ùYùØ ¿ò„ß`ÏDb¶ÿ¸´ü±Uª±¡<ŒÝIÉ ‹_‹Óþ¦o†X¿í¿þå¯ýx<D¤yLöH¶MðBQÕiSÕÌãPuÚtRÏxÏ·­휅¿mP´ÌЀPĈxTKÁá\Tó2•µ< ýÚ£yIè×.kùíc0'ÊÃúp¾çi¨— t@Å>Aèg ‚Е…¡W³r²°di~í,$,ÙÃ{òHËïaÏÉó7~0_ZâÆƒ®Qdej/ü +!Y™Z/ßö‰ÜÃ×} u©ë·fAFÅå¼£º² ,ôúoíÉÑé|ûm·fÑuµÂ­VÞ; Óû}×ß'XEt•ãß÷è¹zµ2£Šòc¡3€ï¯rŠÊ¡bêZ žêUrM^kF(JÒÏDCˆÍê©–Šˆ†N(æë~¨¡.8a š›e‡¢"ìRÿ_lÛ¡8¯JºA£²“´™ÊGk¯Nk/&ØM,;ó¹èŒ8¾Aù¥,ËÕT°8ëY¤Rž´Pý¡8‰zÝà ÿ]ùÿºq#Í8‹þ®Q„N—è­ˆ³DÅAþ†þÒâ?!a‰ât·¨ù\+¹rè_èÕ=îýž>=÷t:-ãûRþ3FÅÖ=ô¸Ö(#|™ iú;ÃÓg¾·*£´Q £ŒÒ•_×—ÖüšÖRÆ_BÅ8¦ÌY•ºB1%ãçvüWøO>]ÉõN¨˜¨+”εüvãØ›¿ÙÂà}UF|v_#b_Õ,ØWcdÍ~8h!Rˆ‘بFµZám|jVÈ\+ H ‚=†DÅA{ xQ´Ç€¯ÃŠ^Gx¸0¶b£Þ8g…;²°,¹^Q‡ÓÁ—ñÐ[…ññ¼UoŸ²ZŠS(½y_ÜýjO“Î#üÚ‰Òyœ;é ¨ë¤³Š¬ŽIg@1/Nì¼8@¥¤åÀ"¿Žž> x©Ë×6 TŒ5¿´×ä0<íôÅ(†5¿ŒÄÅoº{P®} Õ•á3ÂnÂ2[ítXð7µKDõ=5јQ–ˆŠŸm&cFY"v“­œŠžtžŠû9蛉™ø_Øg\?Â>ã=BÅþˆïøjyäŸøÜ%¢DÅ~µ^™?ÚIú˜3Н0ØIú˜3Н°ÚIú˜³ð$=¾=I¿"”o’^ØIúkˆº“ôÂNÒÇü¢Ág"ÑzÙS'rk‡Èsx}S_ùISÎ|Ïi~ s¯uó…; Üñ¶µï¦šŠÛ&½™š~weÙ‡PÉõ’ßvÙP©ËyÕ £b, 2ƒRÍ1xÏÛoþUøZùÕÍó«™_ˆ#q”0Ëkx 1<ñ]q Rl}YWçå»â(‘U—¡»s¬w;P_ŸK5cs\×u³ÝÊÇk¹aÇ^Ê{¸P½^õrÿ ,9`1‡ùVõò~ßð[Óâ(ÿ§ž­2”‘ϸ}ëgýưÌW#²<¢©ÐžíN,(æ iwbyD1O‚<"ˆ5yä™u–øyD2R¶<"@¥Ä|;ðˆ•Y£Â»™¯š>Í, šÁÓSÄPÍaUòxö_„º*_ËMCî® äÊH÷V›W6ŠÊ©ÞWUU¯Ö¹#G¹2X‰Ï{ÑÎonãüƒ“´Ÿmë¤& ZCÜjÑ× Î#¤Žkâ 1ÌÃMLò!ó«&"µÁ ˆUhUŽU­GY7%ÐãÄÖ<ú¶Ë´;púÇÚ«zbP?×Ðß±>4o7ÆÚ«ÿ9øÄZX®n+¾–»¯ ‡Hæ1÷U»©ž+l;à&õð›~•šµZš–ùÐÿš^<ë ¡²k%\͘Jxœ°@5cëaÝ'îæ1ÝÚíÓ­æ4MÜÊniäÔD÷loo¡9Óq’œß*–žøZìÊ Ÿä7rÿM7„â>^¸„\Éz:bƒƒð¯Ó­f|ÇIâŸn1ã;¶²ž^Ûš ÒङY…aˆ°Ò¿ ‚  ’"¨ bPy vexYqJ(¨ìµa„ÆÉKÛŽSæ·¯­}­Dñ°}íŒP¤}-ìX€Òµ¯]ÆZüJ|G¯}íÇØ×”×¾VûZƒ¢íkñsÑöµ BQöµÐ™TáäX-̇óŽqJ©ÄèXØ}±¥‡k5Í‚ E2pÌŠFLh35aŒÑÄôù|Š£º4ˆ¸Êøþë¶¡Tq®Zƒ~õX"TJq~jüô™3ѤxvSƒP99_ß1_%ð|UœæÄtØ®7qüBöÛ>Yo Ë¤Š‘䩯½Û\Ã9”ETvŽ{aYLêÉwa²ó,¾Î J®.ż&‘¯4ÆVÞg“ÈÍÞ‘M"G|-F vBõ1Ï|‚æ}Ù:˜£Ü¯¦–¾„}"ù²©ëì1“¼±YŒ3âºM¢cféEI¢1úh¿yý®åQ’¸«éªŸKóŸ¢òáz„â¾StM?á;&þSôýsž>õŸ¢FíP™gM ûš€·šQkbZår5k"£ÖÄήƒ¼;ËÎ*1–§cŒÛ%*ótB¡w_ë¬é+³€¡¹ëIÿqÝ Í~¯f<ûmißwqG¨ø`z7`pWWÝ£ŸKP iéFÌ·[ÿ¹i¥›Àƒ–^_ËÖök 5Hl¿3]*ýôÕÚšWÙŽÅÐ,ï­Ÿ¥íûõ†PÜÝWÕÓ¯ÓÖÎÛ§C(ëÀí¾]“û<ë¡Ò« j_¶[9B”†Là/\üûû×bT~h(é§WÜ­‡S©Åxckï¯$é_;•¤¡èJÒ„Pt%i@(º’„Ÿ‹®$áç¢+IøŽt%iE(º’„Ÿ‹®$á;z*IƒSIÊ#¢’$œJÀ®•$áT’v­$ N% `d%ir`t%Éy6O%©–ü·ü6–Y.^]é}^_œ£üVME©Z·Þ9¿kY=¿BÅ>­›W+¿|-véFtóº ï7äk–] _ÜÓTÞ[7"Tbw;•ݪŸj®¿ÃÚ·ByOõ… üôÙ1-T鸭ûרÓ P,¬£OœÒŸ¦¡b*—S 1Ua ¹ÅÞññZ§Aïû9î¹þÞ—öûëÖ»9å×ó¿û/t¯¡¦6”ª 8 ”¥ÒÉ÷5ð\i`š@f®ðõºs7Q{ÏçÓõß/œ!ÅYï®Ýæeú>ëcû":C IR­Ïü»·¡˜õ*Ï(ŽfÃjc¸Z¶¢¨;/œL£ž%0*õ1½Pï©øóóñUÕv•Š?‚¯bsÃÇÉLJýµø#yDÛ(s¸VDM: ;éQpÒ b'ÄAõL:~. ¸Ÿãl&•`9z¨J‰[?¼´R" RGOQ×Ô¦yè—/Fe—©©O;Ëcþ;@¡éIwjêqLMŠ˜tj[çoôO:)188( jJ®Ó®†ÀØ)â‹Ë•þºï[ÿ»ß!ÃE|\ÐâÜ ªÖ‹q¨?Õä Îù‚9Ücv“©òï÷®1Š»½l#Þß÷»V[Tr­¡¾t Þ'j¨B×P1êZCý]ØjÁéêS˜jÁ‰êó!¿ìñ“KuT@u´D¨ôâ¹ÉU]†U$~홼"„¢Ó;³SJ1}§Õ:JEzÒƒ²”Lÿºa5U,dϹk‘íyeÏ“;q‘ìy$h@(nk6FÃbçùÛu¤õYÿ5,z5sð\Ÿå›ÿO¡ÎŠa= }Gu­ï:~Š#ß6àÿÍ2Ö¶_ëpòº›(ø9ôŠÃQö•:#Ø Õðô¹ó7îoUŸDãü~–=FÅWÍùô¿×j¾ŽÜÏT“‡öç{Ô˲¯« ¢®UVk…P š8‡htý~¿ªP)®qµ¦Æµ<Ý¡²cÝ›·úîÏ×Û0謲ïyJC~Œ†MÌþÈ)=§ÖÕd@Å×ÙªQØÙ*ö‘Ê_v¶ŠýEÁÙª_‹œ­Ò+‡Y5^*–Q,avÌ«ÌhÌ›`§¯"|mõù&ûã~¼Ýgð,f”6îI+ÂB±‹ï®ì»5æéZÙ·'½*ö:5ö—ÒG͆ý¥A}$³¿SWµdw¶çðz|ŒŽ ûË(fŒ°SìÄîwÜ#Ž) fÙý¾Ê!8z³ oß™*ît„Ï¢¿ÐTñ¦ó9†Xôž©bÅïÖU×ñXšw°ccXÿ÷ÂÐ`ǰþï…¡ù†&³ú¿>}è1²(N;›k†fžvf M;zÚ™EŒœ Ùä'x_Ü?á7hݲ^ T쯫Ç[MH¿Š}‚AXSõê; SS€Š ßÉVa”Òj†I '|!`JƒEY@ŸuuFÑÝCËgQX£ö‰¨ æÚ&«ËÄbÊ¿]ÍÿvºjíêÊp½X“ÜËÏ}€ÈÅ—é<[¾¦€b>Ôþuûj‡@qŸoÙÊí~Æ×Jˆ¼Ã¬û˜‘¼D¥þùð•2Æbz_UsG¡bJÇyƒk1z’îèå1ÆéI:ùúá­2NN'Yþc'e6c“;Íœ[_rëuePx:I¯Õ¥«Ë²‡ @ÓIêZz0™+È$¹½­•XT£ãÕe^ÊV)Î TêÔÉÔ›P®Òó­ñßhy¯{ñ½§o@KP¹E5-øXe×þ:ü7¸Ømk‡¶Â(]£?‹X-ŸdÞ ,² Ðw’û„ê Îo„„\QÃâ1€´œ1Ô?¨¡ЖëjNR€qÜf€ÆÆðšÖÆù1£Ä×fø•Û«vnšú«}Y¿œ—kÙžŽÞ‡YÔû0k6£õ>:S_d,;+"ÿOé-MóÚhTT¬ýêóˆÑÊÖ›ü↡bb"ØœÌ,váóàiÐb"ž-v!bàiÀb×°c™åöžlË/e<óò­Z÷ÆéèÖº§0Ì´õ¸§ŒøZ¤{Šƒ"ÝSéžâ H÷”?=éžâ\Ëãƒ5!÷@>Íýöà 1^\ùÞÚ›£¿÷Lv³äÏ¯Ú g¥Ú +Î é9_çÈJ“‰%„â²$>&ÄXòçWtóîH¸•vØ­”8Ç–ItÛ¶Ï*o,aþªzµªý|rÊo¿à¨ü¦Q „Â[½É\¦Ge$aNÍñÙä}ïð7ò“²§9o»{UÞÍš@:ºZÙÓt!–Inyz·ÚÛgÉ÷ZßôìÛA³FuhkifŸªþ|×iXç׌P‰Ù™î†Ã1®ß¯\‰°&–{©úá{Gc税ƣêáŽ(Šüïÿ]:°¢1Ùô¦Ô¿w±ˆöÙbsÔ¯»…*3”MFceÝfn°|Äøhïïv@(ÛÑ€Võ=Úß½þâkÁ‰Œé4WõùV†Ê¬ûäÊŒQm§§¼ìÐÿÞ=Bå¤O$üi Ó7ýp–œ]gUY²Íß}5_Z~e÷7z–ã1¬?s-¢ò6Üpå-)HF«åK2ĘÖ=ºC9vª¦uÒú²,®9ÃþîUÎ0—zÎaMÒƒÓ¾w5›»¸oÝ ¡ìºß‡LöÎÁT­³üYŠ{²WÙÎ?È&©AÚòþžïøéSÛW–ͧšJÑÎÍŒPÙ5Nò/™tgŠ¥‘ÃhEãЋw© ž™Õ$µù‡¸_åÒÞ ªEš¤nš¢$mëß Ö$=s¯êΰª ,öÀ¶mi¦þ"va_íš¼CëÂpA¦6ôŸù[~_ÎÂ8¸,7ÃÓ”9ç"†yu`©µwj5MElï÷­y÷? ˈJ(ì°ÔãÁwøæ•ú”‘¾y¯q¡RŸ²€oÞ8 ŒbkÄœ“)'çNí|KrîÔη±4!çNí|KÃómt¦áù¶ßѧ“-ì|KJ'[Øù6f5ZÏS7ÂNݰ4½j ‘R7¾ß° #6½Ù«#´ÔÓü3ïq„Ì„øð.Uß~„òxæŒÂzæ°4§T Wë™ÃÒ<ìÜ„¯E;7 ůµ[ÅŸ9j·ˆÛî«<Û@z©§ÉóÁNž³,àü+#Díü˲8ìXwd!P%dYP yY–Ð>õÊ1V¯UìôîqÄsP”#žÉê0ïûê»®uuŒUÙtÓôßB‘Žxа¼o¯#Þßñê+WÖm6ޱ€¢cMœ¥È‡×áÜO–sϲW§Q/eYNÖ5Q]'+‚¼18O>õoÌÖu²“f‰H;=¥ «,?««ƒáµèûA¥<BQsQ ŸÇ0£û4ñô»vÌèv'žä9:€êË]ŸÍ×Q+gÜÚ©•A5Bé5±ùÌE)32„ÚÏÇõ=ûÔÝqY¾Ÿß‘˜‹ê€ãÈ,£ÛëW}¿< öýà|Ì£_‘€N#bt«üãn®%©û1ƒP)bŽêß±Z%F¿"TvAÕb?_ó åÖF¿U]üÑš°ílÖjlcM­Æ©çTØ'Ó¬ßbÍàUh*Nõœä~Ò`XärG÷ȵ*×y};0]0[µ Ê>ýäbí:çÏÔ±&0øÍϺ½J˜qKð…ðP¾Õg³6s‹a6B¹kjO+o*Ô<ƒK1#}ß8«²«»ipŸ-£¼1ͳ1R…Uór¨æµ¦š—_5À`ZIFã'`ÎCÕ–íì´>–íì]w«z¯Áos3vÍZé|³=•Èx0ÛÙS¹é0êà 꺓ú«é1vï¾#¿pÛŸ;·½\• J/¯<&—vZß•â*P­9Ѫ¯÷€ÊMqʿ՟¸³{ÞíÖ›ü»póïûž©ücQGÛï× Tá­ïôG}§Às5ÿņõ¶ün‹³Óiz¯n»ïçY~Å{Æ÷Œ”ìuòX”¤®c&®6¹=Õõã¡ ¾Æ-¬ÕÎ3õãõªeþ7`XâqöyWXe¤"rÒe#y_ÖI—ŒÒNP‡¿àÔ\¼¼V?@~Q\sa£yaùǬH)ïËÁòYqîX·{ÅBÕ\Ʋœ!n(²ÓdÄ ÕúzT½©d!6°3Wªœz†ùý…*Y;[»mÕe¬2cÔUAìs¥7è•ÙEâ¿vù=§ûˆPéeúT¨éÓ©.M‘]¢D˜+¿Ÿoõz!T~Qv¥؃5ªðvÆmµIÙN[XNÐ+š¶&Š¢™òfQ„åáö…ÏÿþÂòpBÑòp¡hy8Œ¢åá„J1f(1ð¿($²z bª%¼Nïþ«E ùŸÛ–á_µ‡èÝSF wñ[*ö¶^ËšK€b”¥èo‚dJ… ÿã!ãÑÍA‘Æ£FQƣ㌟Ëo<Ú5S¿"i<êü¤ñ¨ó\¤ñh7!i<ê <#:£@Æ£]Æ1žZÖqƒ«%ä8F{È:ò?BÖqYÇ¡|â|ƒÕå§¢*ýB¥ü/#„p7}Jó.Bmh#„Ëÿ‚mèÒ¼°`zsP¤î8#)„ë\‹ÂíðÓ“B¸Îµ¼mh+„ ¨‚¢ONp­"P^x«Ñ_¨¼Þé·”mOy½ƒãƒG®ÈIS¬{,Þ:昲팓½·f~¿u·„Gç&Tc4íO4]õB(·1YCH*&Iy‹~z4mØGÓ=š(¿¬¶M[*½Ž¦Mz4 ?}æMÔhšÖåTNì¬0"É‘¼oDÖW‡F$;Ìð(ŽHvEHnó€P¸r4Ç>¥%F¥þáÇñ®éP€B#’.®-÷úñ“s-rDrÄï‹‘tþFÿþkG$ Ì[LµÆ¼ù=¢Ó`JÏ1‘ßS„0+,\„èB‘E8¢Pbë{Œò!FM/†;&ŵßô¡bŸáÝ8–“ÙOÒÓÀ8<}7—Ï—Ÿ ¡Çðî¹Þ‘†£¡€Ó©&ãßušV„â„4îñ( •ÃC’)%H¦ð¨ K®òž=FÅ^‘Ûc”‡ÇTJ·ÚQ@–Çú²£Þ5aîh¿}â΋~ú˜âòµƒ(9ŽÏ²CG,=ˆå7C8L?Zˆ®ä£Ý'„b”Á¬û˜ ¶ôˆGC>ƒ-çZ„Á–¡åÊ[0³RT x«6]îãq4˜]• faÆY`Ï1³<ÎΦ‘xÏŠ ¸ÏéÀÊPý¸Ñ¼âGÿ^ª£<Ò7³úÔ6Øñ㌖¾Yßÿ l0«# ¹¬ýð+1Êo0»ƒYóVÿ¼?·Ü,\˜ÿ\e*ï5QMG8I‘€n ·¦0òªª~háÉPU2“¿Ü€Ì»(œQ7ôK¾¶méa`4„ÝOþÍ¡bÂØFݸÉð´³; ­q“&UÊöör;lá3©‚±L~êo*È”[q§9ãi(C‹n·Û iÑœq‚<ýR(á ˜7Ÿî •™3î fŸÌÆL†Â’ÙØè b;`pH ½_ý4½0Š–dîµ8ŽYa¦áýx÷ígE¨„°]35–#uF¨˜’4§-ËNôPW€Ø¬‰<(@ ±ËýÄ# ÃôPM€»©¤û¦©“œ]a€<=årñTކÌÙgQ?…„ùàÝ«áóÏ»‚s õ{¨€0|¨ä"ß'Ÿ^É÷ý„JI£­:>c5kY ÎiëòlTìJi©¶Æ{Zäg«kx€b‹­ÁZlq¿@tŒàX·p@¾¶¥…q>ž\礵VÊ4¿dHñ*Æ3š 5—¯a‚™?ŽÔ‘?¥døxÃÈOÈí ËÙÉ|²j;Ü;¢cR«¶(ÚÉ|@(ÚɼG(îU§>X(<ÉhuêC+P1ÑÐ3¥â$7ôB‘eó&òPAyê0Êßгå$wY(¦T¬zbœ šäþ†ÞÓiè%y¨¡·9ÏE5ôLÛ/Éå¦u®hèá‹E‘ç (¡^ Íý¹IùݾûfÃwL—ó7~VùÞX&MÎZZ*fhºq»ßM*võf›ýØ’©wÿëŠù~ŽäÂÎx((§i`oZÍÞ”fÁ½ ÎIì¹€÷¦ÅÙ›°çÞ›gož N³K}ÜÓLM³ÐÞÔÀÞäx.à½éûèÇÞd=NûÉ„÷“4 z¢Âv’fk±å2µøhî:GÎ >Ôk@¨ØÇpš…™ŽâhÆ0÷ö2êÒUU5 Ð ¶“0&r5ÎÛò|–åˆPW}ý•Ô_ZîWPÞN†»¨Ì[€?TëxZøUë3ôP­ãéw,öU¨ï˜µk 5#‹BÄÐ:EŒ1_ZЮmÊÎÑ,òcTËu“ɘ@(1F¯Õ_ëºV?ÓNf1*÷ÉÍV–Ë’Y6§;í³Gƒ¹–«öm§ Ô[ÝJØM²óÜ@e4NÖ©7Ó<‹OZ€®£k‡ïȱG…¦|?m3?7|­GVýBŸí»µ“Yñ‰ÙWÚÂ:Ï·ñƒ¯•î°£Ö*Tî!ÀËÝzú |Ç‚j~lÎ[õµ5JÔÖÈbx °ÿ¢I1SÜé ©†îðqj×Ù]=^By\=få5iáyŽüMή7¹7Á.¹šºÀÉmäÓw¯åw׺ڀJ.;ØSï`+~®«ƒÖÞ=Be^bŒòþÀ¨Üë(c9s-Wk}ï›íÊ»ò¹¶á Õ‘,¹®|«ó…2êÕQåPŽ‘¦¡BžUΚ0ÕŠPÌ£ 3(—¦G(~%&.¢ìÜoE(Ç ãŒ¯E(Ljc×IOî‹®ÏVo"£æÉZ;OƳ,8Of>Œœ'ûód€"æÉZ˜'ÔužlÀód€¢çÉðsQódc‰ïHÍ“õ?}áu÷<8æ<#´EUþà˜ó,¿ób‰-ÀãÃ3±ä˜äYáäÜÇD©ÎG”°ó?ÿDé°Gs«ƒºN”ê¬u›1Êq rÙíÖOc½!ÖñnÐñîû÷Öö•8.ê'sySN/øŽîÈ“ú…êª.··ù…ìôàeÇŸåŽ?b”ï×îÔ†?á;§êC«ç‡gÑëMþó“'óͨñüêC ¥°í75 ì9ùiž?¹Õ»†G»mëˆP1âä7F7¢nß¿{Pg·U?k{ÿá;r[ïk^ö«^ZPÁTbU¢k}¦‰¾ž—ïòZ*õ9]¨:·y÷i ÿ•©2 ¸ÿ•k¢ÜDÛÂs%þI=Tµ[Ï“K‹d¿VõÛdvØ<¿Åp šàüÏd{4ûõ/§É ¯¥š7 BÙxÈ´[žÃãû¸-¡pÝÔªæGÙ7?h~ä‰Ó"¹í_㞎•üˆzü&ò‹Æóý]äšîeë¶F}ÛO-~«fcU3ñ VSŽß¦z|0,"Uua…e´ ±üÞ€(‘g´ ñ<ÏFùUˆ›ÅœD¹ÛÆÚÏ+8ÕÞ}S¿ž•x§ íþ›çÁéBÈ4ÑäÝeºÐîÒxòΩëvªëæ9 „êºy¬ënåÑ‚èúç¡Á‹?JE]ìZ¡bª­ ]A^æiïy믹f\‰•¡z±K×qs¢ "Cä­q͉ºò¾â¬ ñö¢3”_ GÒúwú¾mÊÏsE(‡2]ë(óÞ+—o|-ICóCæç³~€²™æÎdiÜÛŠÇ„PÙ%ÒÙs¢±ðsùs¢m2ÑIÁÎ9|CÝx›¦qÅ×òåDƒÌ‰:“ŒØvß £¬Í‹ ²vßZÁ©è}•qù2¿"9S½:-*6ËmýéDn:¼¤$ˆ’ »ç_57C /Ò QÍ|)ÏuêU=É{LÌòâDLTz¿ºzÒKoȽEÔû…H­(è4Qw=FÅ”ÞΧ“?z â£ô†BQzCP+Kþh {ô  ¢ Ò‹žVN¨ñ0!WNÓ?ÍsCM-c¯v:fMþØy¸ÂÉŸ=B± 5nx)]ÑISãÅ/9ä 5ñ]Q@%¾²T9$F¥¿à¡ß^òS«_•9$œ¶€Ê©²Ã¨‚êVjºQòÐWnð %~º‘:=ޝ#!Ý"”Féä%)E½6îHþ‚qÐKEÆ#FQqG'0 Ñg`èCùSȳšêði<ˆr/o§yì`}åD®¶W3Wƒ*¨³oRâ–3FÅÞ\m6¹ ügŸ(?Û„PÎÙ§T1ö³Oq=1*!ΫMw•úÏ«D,Egt¡ÈŒnÀ¨€¡ã$N úItVm¡ú Þ—XŒ" *ÓHÐØ—ö:mô÷¨¼N_¯ï€¯Å ¥\PkTâéª}ä₨ P)¡§ûÙðse'"ºúµ·~}V¾Vîñ`ÝKžÚ™ P8¢h÷ilÑw1ü”Ž(®ó¦… Ì“ Å17§Àâ ‡nÀb¦‰câ3íŠ3E‰™ -fš y:¯˜éŠP´˜)¾cꡪ­–É™D1r[C’ÿ'ìJ–%T±à/ÝRA]öþuÄûË*¥ÀyÂÏo…ƒì}†åå"œ)3 faYÍé-1?„‰È+º é‹´lŽéqò"îéñæ‡æÂÉë)³©Qv·TN*yy,Õú‘óƒÃKNN”ÍvÚé ;…w@(T¨TÛp_‰ïgC øÅ‡fë.¨ä1¹•Bù.É0Ê›ÜJü‹ÎäVÉ- ˆý^*€¬»¯™j'¯ô6éohKúL£ˆžK&çŠå'*pæÝ— 9ì¯À¶ÇDV#ˆA°‹‹! ɇhbÇö]«×+ìÍ“ÿ~ (-àÒ2»X±¯ð^ײ4F<ïw»4¡×Š•¸Êcžok„rZ±¯»;þE¯»õö+ö^hv bOpeö}=Wš‹B°±Œcß÷å ®¬g¹‚« ®‚èjMZÂÕÝŒïQ΀ò›3í¼/8s•c. H@nÖ?zçl «èæ¦A¨È3=Þ[¿HNOh{°|˹aý"½DÛu;|Ìð³bçmË:sÛÄ6©ËVà·O}£.O£.½0ç½¶*r ØÂäq2'@ì—È\D& ’ÛËi°PÛËñX‰Äo{yˆL*r…oq-¬Wê¿këXþùD&%o¦ÿÈÔç"2©ÌCF¹D&…’7u—7«Àœ?+òˆÆ" 1oõfgî퓳f³rö¹Xþû ‰P–[» Ëå$28ÂðƤ1æ§ #ßX¬<…”Hè7ÃØç² q ÉÕH .0"ABê¶qTŠ??aPñ“ñï„òYd@¨Ðiö¸ýpw„±ÏªrßÒ CƒÌ!lô¡Y¯ärZì½N¦0}bïeÊcqxA…ΖæjZš$zhiòn°Pî–&oÁ¼D—á-(ØîóGÁPjUå–œZ¯6ûfÚ* P Yö/:ÉÇí$7ræ€ò´4GTì)Øf¿Wâ©× •zX«À=$Ñ롤cF¼H<ÚKBI' žì%ÍÝö’pFÁmü?Úï$òJ¼É³ýN¢ËPìÕþ‘Û€cSEnSŽMHùLšÓP~S€¡ü¦¡ü¦¡ü¦øYwSŽMå7àxUý¦†ùM¬§ùMðð` `Á˜ßÀÚ?wS€›˜›’e¦|÷§F{sh£dÎtíÝ‚P¡{´÷×[ÏŠêÍ)qHƒÒ5¾ %§(~P²2ãË$z_†‘c=/÷å_†Qh=/¯”Õ¢çñe†Ÿå_¶ÞË«dÕã_Lïùí€óÛ(yÈo¥Éo#ûþ~Ô4òz–™yŠ[öö¯!:㥃ìí ùsÛÛ÷ØÞž?Keïb= ã'„¼ž¬Gk¸MéÑa=ÚÁÚßH{z®Pc׶Äñ¨â!s¦ißM7"ÁÚªÚŒo\W¶ì§Q§nƒV9UD?Vîʬ”ï7B¥9j„ö×õËÐæu«ªˆNE2UÝUc.K„Rºªÿ…QO=³ð™ëz)ü‹ªj õ{•ú™±z àë8È…Ë?êK0­mÖüS×õØ"Tì\‰½j£o‡“Jz®„RÔþm+Q|D(´û‹©8¬î¾ÃX–…VÂ(ÑnIi5жE({%Ô{e}Ír 5Û“Jz®ÄþZ?l[/0B$•VbÕØ¾ä+cï7~Vìk1˜½ùTlšQŒrƨÀwó=FO-†ªÁÏò¶Ì×]Z vó$Èdë¢b£š#FÅžæ¨Ø*Á4^È»¢˜»£ÜƒÜ{ÍÃZU_‹æƒ ì呱6ÌçAµB©y‰¹„' tE¶ø™Ý= ”ŸÝÍÊÏîÆ¨;»›cv7 îìnŽÙÝ€¢.Á«“ƒENN§‹ƒ~i„$Q/ÝlD…8„#aZŠ–A™›:æ$`zÛˆRσú0'±mC‰Q¡Ë7G²f¸}ÝZ2fbZîÓz%¨WhHù*B©‚".ÿ­{›™dŒ¾‚Ùv¬àܨÈ͉ìÍIÃ'™$ÓúpxOéЊ& ½Î„žjó+·ãI£è}rT]ðmVжø¸[ÛS"Tèi+P‘“•s6[(µ Ø'ßf=ù6€¢ØÍCKBîJ) L©-iF+Þg•È~5B%.îÎtpw•ZS1fnŸ«v1«ú‡lõ­Üo?)y£G¸ ìu&“ÛfžEÍ0,pŒ$”e›uþ3µÚ¼£õ´pühµùl=:T9D[å²aYÅ´°%Á¼®Cù%›»m 6!ÒÑÛ‡Ú˜âÌgßæ ¹SØíRý¨íÿ¸ÅW¼-‡¡È 5müö5Áè[\$+!÷Þ»’¥›¡b¼£õÛ,èû*9]! ]¨ŸÆ¬jÆâÝ TjV5ÿæúKëúAö tœ†éR‹dîK1|È*ÀúM: »ì;~ÙŒPöð«nÕMÛýhxéEðÙÇ·éy™ÃÔú…áö6¢wÛåømÚ¶iŠÚß¶Üc²s#†›fuѸñS·|É1*q;'C!iôàœlxî$œ“ ÏP>ž{܉4òðܧU 8hfÆA“ Oe:cÖþv{X¦3kƒP‘ƒë§LgÌ©“ܬié pýèièwãúµÜ¨eèw³“‘{z3ô³˜~ 1@OC¿«eÃpjÂÒ¿Ôk pjÂÒ¿gMX³ª©•½kú‘ ¥›Ó ”^X¢öΩÌÚ#¢#Ç%úz=åøSŸåÎñ³Kèëu'ˆ!kCXÕWðÄä‡ê=óœ·Ç(7¡®ïKÍö¥'Ñ}÷Á{EOw_fV5zÒ_î­gyõ—{Œòé/CP¾!AДWö×ëÑPuµÞË«¿l¡¼úËêáîïï¼ûä9îI_¶Ç–êjÍ*X/°-¤/—_›•4çÜ=i–÷ÐÞù‡ÕOnöNªÓû„_DDEª-ô³Ò µvضkºy;Rô l׃·)«ä<Ï9è Sl˦ `¿ÓäUÝ„E¶lÿÚRócŸï“ëY9‘ΜxµÊêuɉ>F¯‹w¿tUi`Ÿ'¹‰’«]”lÅg@…JpßÀۇí„>§.("ºž§N@ÜíÛÞÏ™Q¨¡AìÓÏÛ"0 ü4ˆïšwÊaéæì ÔŠÌÛ,Ô¼Ìs·p³ö±ßq;› z*×kcöjðP¹æ£ì1ÊCx˜˜ä9œø©EƒÄKy:£h<;H„rÞ}{fÞþ6eÈ÷8¶BFj·s®\ ÞA‘Eš!Y}õ¾gÝgåq!éÄÐ-…`2¦Qµ¬µw< ÎµG¤´µûI=LHuÍ(öÁð–uç¹Îòi診A¦™ý$‡L3 íMã—±½ýWe†¡gVJWbáVC7«Ó½åÜg§›†ä¾n:Ý4$n†QÞN7œ&ÈHí°í–K¡‰Q‘åî:Ú :o4¤–Úö©£Ý¶¹±P¡O!rðø† Ù=Ì”ŠÜûá}söÃièïÓŸýpŠH|—™7~Ú]RD¼»¨]5ò°´§'¥NYcë‹2;¶²ê7š“z¥²Ì­ih{ ž¿èêi…<3ò{ìCºîN/”º£7Êëªj'swD¶éõ~Ê©ÚÜ~Êý~k ¨KoAÍà0ð'(úþƒPÇ”A®lü|ñªþ¡r ðÄð¦™l`/\ÕQ°9ç“(ÁËÇÀÎOR74XY‰¹Ú«ø,¼Qf?òÛýÊR›ÇXä`Öf¿®·T#V<­Î;ª¿õ˜Y0ŠF½Ì¤y&ת··YŒ§˜Õÿs[Ý™ci-HbwPN껶謿ô°Ë?0%»)ó¯žÞiÁ ñ@‚IhvÌÝÁ®ßþÔq‘xÝ}´H-«gý÷§mÙ¤õ£¡{žvgAk˜g˜ ¹ÛŽÂ©ùlG÷Øu0_TxW¿Ó“ë{èj¢Äè~wA)XV™q[¡‘ÿî:§¡hôxwef{?Þ]‚ágùÌIA/FWâ²…òÒ›Í@}¾3r÷©`“ùEhöáisÇOdv zÓèa–kÍÀ¾›F>µÀý\ÿš$J=7œ–„ѳ\Ôò½»©|öpÑ?ïÛg{¢QÀîN7쫵è(¦€™³X3¶=ѶðÂŽvG¤:<ï_„ ,Ô.ã¢PkÇk„²d\TÝiGLèisŠí¬ìUähg¬hud7l1îÒNBQ›~§+$y›çÍ¡âãîÒÚFL®Ã: oätW_+#ïTð-/¨?åø¶™@ß6‰d¨Œû%ÄŸKÏà?D}±Ñ8œ±æ®\Tõ‡2ç‹D(· Uf\:(‰/ú9-Ŧ=ÏÕ¨Ä[­ÈÎ,qD\{Õ¼ýMqÓXºïFÍ­¦GQúºfZF³²|/y¯ú…âåý*Õ»âW7 Tóè U‹•Ìh¬eµ.S¶"TdúpG¸oÁËìßëàçì}Õ Ú¾ZƘõ½¡ú µ^Pñ­žôµêI˜»‚g„˜šjôŒ¥÷Ú”Š?v/ð·©Ñ¿»¸Î³ì3›ú ­9¬Ù>.c>e«+2UƒÏñû¡B³A_¼ß²Üv! /“D†Š/†ßbd#EÎàé °ŠnàÃï…•…K1«ªl#¾ã}vJå0•àÚTÞl|—ÖÛ§˜•Rèù™j?8ÍJD— ¦FšA¶<û”„Bᦊp·¿rdÕ2.Ÿf„ ñÆ ûÎûº…[^2ù¯q©~e.»ªG(âN/†:A”\m€õ¤Ç†ÊÚ¡…œ“’‹èÒOì³­ü;ÇÏJ,:Hß-R¬Ö{¥h’êÇóæÙ̪þ¹Ã÷Ï<àÓÙ‘#àföÓW‘]‘”ºIC\“† Ô…©E’^Qwj‘6?qzê¥qDÒ£ô¹üiÞ>y,B£„&OåOL¢4y,šÏ(q·²8ˆRÃߘz胖›n*ð êªÆ‚º+Œ Ñø:8bÿ~VhiiêtÉÅ\dBEˆ~ û]ŠÂZŽ|A([L¨X¬’Â_DŸrì S”‰‘žÐÍ:kl$F%¾F/ä­ñ)ýzÝ_§ì®YÕ?äXò… Oý+›ã¼È>*_53¹¡Þ"[ÄÅ”¹eê¹|·šÉ@‘gÜM|[}¨Ç_K~ /Ê+dj¶N`uŽÓœÿði{ªÊÓ€Oó8|:ÍÍ”û4ïêVÔu?Í›i-saNó8|8ÍEÑh>œæM YkúOólxCÅ ŸNó®ú"Ôý4ßÞžçÒœæ1všþèr`¼Ø‡eX0ìå;ô~³—¯Ê æq­@Mš"þš%#¹íÂí´0Ý^äôö¯Í¾ëËE¬Ö³B§pAÆ`ÊŸ"§7—x¢ùEò(žh¡|â‰&ã‰ÉƒxbÏ¡zœŸBÅqô.ý ÞMSýØ[QL>èyÅ׉œã*ÝÒHnz„qâ›îQÌr!–ÛUn¶ßÖ.¶8}’›5ýÙ“åvc~«u‚®QâwÚDÕŸäžË ÁÓ?K^vÿì ™¿ÙZƒ/ M^7.“öà²úHŒ ]Âbö*º {ìõ¹CØPÄ1)Ä”b‡@(zË×vh7ƒÐ'E|­Ã¶hûŸúº«C(›¯ïÕfÕwj*t2žò O€Šno_×½']rÔu\“/& F 1‡cª)#†˜kòEàgù&_LÇyÝSÏÉäýuT tµŒ¿ES¯+BQ”ëžýv&˜fŒŠoS4»ûj¹ææ¿n†ËÍI‡ɗ²´þF÷äËÜ‹¼Ç?ùºø²”à!?ŒšøH¿×…¢ÊÀo’ç0Ö•>…ùfj5¡Ïa¾@(_˜/ü¬È]ã’«yû‡çY'N’§:±©ö!îšÃ_çØ­éƒ)ûŸ¤Þ*$šCIÿ¼!(óºTíó#Ì·ØLW¶Éq¦áÛd’ÊÃ6M> Ý|3®ùf]P>¾™€jßÍÊðͺõ×—MÞ ”‹o&ß ¿×oÖh¾ÙˆŸåã›™( õ»ÊôÛ††YóÔÈÒ5®½&(‡u)yϺ ô¢J˜äfRqRÕ+ w²ß j8 hJí}<ëûªæYñÓìÈPc”gv¤àfícÿì q¨Èé(eX/¯˲]¿¡¯ï¼Wê’¯.UÇïpÇŒÿÛÇ~Ñ-X7s¦mlîßg]Ûedž¸®äÚ£«;¤ÍlžÏ1èM- &Õ€EdÐ[Û–±(wĤGaj(¦Â”± 0¢ˆ¤ K ³ ¦£Ÿ›Å¯‚ »èMþOßW| Yÿ€p…ÅböÕv=0ûÆQÀ®gŸ}ã(4ûÂQ‹]"`^ßèJmñë«¶Š`ˆ&ïD+ßÅ­~ ÀÌM~G­°û|›š[ûè*9E+¯×*»¯6¼aˆ&ošŒ›0µ».Ÿï«œ„¦>šRØÿš¡>÷¡òSðëÔo 0â”mO_W}¾×÷U`7­È=3¹ªx׌²¦> ´u?ßòû¯P*ÄVªèÓ(ÜabÅœû³ú¬Ÿ áñ(Jóê$þ8íu ¾9,΂‹,£q*€]Éžüá5|¡Å0OÞ£ø‡)ÇÅxÿŠRüÃyCŠ–¿¬B¥§Ê°s*Ø…ÿp¦(¿â¿y3¾#+á8Uøî Â#ShÖÃñ:>Ì¡hLP¤G&L¬1÷{d ì‘ ¨³G¦À™€¢=2%B1‹Ò¶^õÚsúõKƒQüì¤)‘“&  ÒI„m†íVš[iXt¶Ò”ÈJÓÀâ“•¦ÄVš–VšøY™Í0Í,#­4ÿ4'’ {£6’M‹6’É%v 5]ÃŽŒŠý¦´MoPñÉx°6ƃ¿ŽX’ú­žÃObƒ–=0œ7ô—{Þ>–;T·IBÓËúdø ¥yâ¨]TL Ôaì±ãv¬F^Àk凼Ça©Z÷È’ü‰ldìO-c*õ„«¹µš•ùcŒg³«KrB ¾…C[PŒ8´Ì› Ú.FâͬhÃKÛ}ÁÓ.BfSÓYÑÆÑÆ[jÇ‹ …ŽŽMÞ÷ú…¼joê5^ç u¯‡€…É1þÑù_[¨éšþvûA”.³ G6¹¡Ù¿ß#FeÞo{§í²”8hÕöÏp¨ÆÒ˜4ïÜZ~ú9¦Iȼdnìëã8‰lÌѽiob@¨˜èt°—±tu¯DÇüb”èÀBƒèêFÂú€]Ý÷ªJM¸¯<8^š˜Èè¼±”‹0ãÅèþ]îÃRLž=|ÊCÉ3`ß(2yƹVzn‡­çÆÈ‘¥Åa¼Ë²çrl »…Yºº~BØ äÖN͈P )DÔ×Ê.a!¢D(Zˆ8#ÔYˆ(±‘eQXˆ(Š"J„¢…ˆå³’ýû]-p÷B®VÓl›Òçk`‡ˆ(æzf¶½ºV3_+Å,Åü@'åZæÃÉHæ;¬M6©™1³£éŠ®ÌWkîY­‘Ý ¡ÈÞ ”­á›1ÍÓNý3æJ °3&ÊÖ8…÷` É,Aþt"ˆf&'q× +®gˆFœ£›²‡ä^–1Jà=ÛÆ˸#ʶ Òf° R–>{èZ›çìµ\îI¾±úÅü`åz»š†¸Z ̈î¼_k‹q}¿0*vRûtùû©oÝç`6Òàï-¢ÞÏç§^®L!Yû3±ÖF«=ÍÝ÷Ù7ôce$E,5”—a†_ÌŽ›ss†LÂXžû²6Êfˆ]z’¢|~/s-wëw0 •ðmç!£Ð ŒBYN… k (¿QèlŒB•zeÍ{2!Ã,Î3•(W ±8=Z¦éÄ.!-¹`”ŸJñ(¡½Ë0‹h­ô‡u2œÊc ¥“Æœ»?'}†Íô j_vñ'õB'ákžÖú`›æ Ñ3½q8p­8‡3#”?ñuÃaˆRé9/ï͵’ó{¿ýâˆÄì`#oeºc7Ïóæ{–ˆ—°…¿}×ão@(´™Ö0k7i½¼*õK+ÆÎJ\Âßc·}7XXêi¬h¢]]·4o„bnhP®^?ŠâPS¹³£ìÀµh\¶h„9š=¶hd츄ñ8†± ;â9¶Ê÷EØ`a3›‘À9º#žz2GDŒì˜ÍÖRœ±"l)ŽQ±W’ý®ë›F Ñ‘†úùüS †èg””ðÞóË©öµ¨IÂsäv–3‘ ûˆæÞC]È/Ž‘˜#e^ÆiƨÜÖLpØËå~Ìñ·³œAi¡¾\¾óôvPÕ_úœµ‘¯åaleUýdH¶gˆ(éM¶Ç(:Ù£èdû¡èdû¡2wg¸v¦ê¾¯ªt–õ^2(㩦Q¸å«¿Oï¯D(\3Õûµ–v1ï— ·9Çì(Ä««ë÷ÃA¥ž#î¥Tõ*|<=¬¦ÉU—}=×PY!¢$Ût{¼Ê²š^#BÅŽèKÛ4—¿JmNÌQÒ¢¶ Y•Ó|*EfÎÆzBý­ªZ">Õ7]Ù•QUBå>Ô§G‹P GÉèàuÿ~k°@b–( a?0‘/MùRs“ƒ*Öø—ÿ™Q]W«Ç£|Þ_e5àQ½ì)1Ú®i¦éÕ-K3á‹(oë¦@ ˆÄÕ»êŸR÷ßx~ؽƒIvßö¯yÍNF(' VµZަǭG¨ÄÊVa\WÙª¼? ÊDÈÉWèbô÷}ÖV"nC¸ôónÀac,_µœÌóÎ3L'+¯anGèåñÀéc¹¨ð9;¯¶Øü žQ6ÿjŠ6ÿš*!mÐ`ìyØmD(Ú _‹¶A*=×óгiå!“ÿSÕ´ZC峆*±×ÖäßµÏÒ…Îj ·úuí³$H ¢Ûú©Ÿ¶%–z·ÝÃÄÒ³ÞnqP¤ÝØ‚Q”Þn·ÐKO,ÔÞ-ÒËÀ´wöê‡ö®©2­½º÷Td_ÜÙHÅ)¤ÄÙqÃéc‘‡ÍéãÁÜ pl À‘,àØœYç±i.¬µ+õãn-Å(jf£»`°Ï,ŠP Y®2õþ„_ÂU¦žMø%\eê¯Pd•Ùà_L©úQSË•íÕ‰©;Ôý¨'0ÆÔ¹Êlp• ¨s•Ùã*Pç*³ÇU&  jg+`$"Àq@^q@ÂÆqd*~2UìÅ~_ mªXJ¨(¸efz߯~1¦ÉÿêýBÅ”U»yÚiЪý%ʧ¯ží ¿ö’óØÈ}$rj$dÝ‹}$ò½$Tø€¢ì%‹D¨ÔgÙgû[üÂB–}Ðßâv‰Íëq傚VNó75wî¾îuFŒ¢ö:cQä^ÇŒ}Aíu^v¯¨Œ" ëµƒc.èÙföÒ<гÆä”G1q:¤MÜ:øÅäÔmÂVi0cF‰. 4˜™¢„š K4cF‰Cë? õ•QŽeÏ¡rʉ¬Á×b”ـoëüƒePi0ËŒDŒÁ‚u(J1XêãÆ¨Ôcÿ‚ä„<ʃrBÑ ÔYN(°œP´œ°E(RN«B”»}¤ã®•ŸbF¨³àS`Á'²°àS"TêIrG‚O@Ñ‚OP¹çD1³‚™<)hqï* ›Ê;ßÏ»% ·¬Sß|žZ<½øö¢ëÉ©¬K£õâ–zÔz ªÊ­·öÞæ”LW|«œ¸i¦_kgc\ï âênwµ5»rdïm8³‹$Çiœ_p÷1©ö¬DúR@­è»f³¢Ÿ1а¢ïw¬èî*£öµ°*¤‰+þY7s÷m­}ýʧYE-Ï™Åêp9TS%*vøkúV™Ó„P‰oÆ´¦5œ2o^Ï1wÓŽÌ›}̘MÒ<`ÀpÆOCâŸçì ñ÷:@%^ 5C“²€ÁÒUÀZ‹9³'ƒ¥çà ƒ% ižrÚ`IíÜÍ›ÃýçLÍ"¶ªPEG=`TìÙ•ëªC"”gMºêÀ×Jøg³FÛº«Ñåó¦Ãƒ9bÖnæ÷^£Kž]Küg0RÇ”õ#BÏ`¤Ž)3÷¬¿ÌÚ‘%Çhc¸#,Ÿ”;¦Ò'î ØEó,#ø¤Í`ù¤<Ë}ÜT­L^càá¾­LV@X­2ÖUÃ}ñ°®ºE¨³®Z`]5 ’SwKŸî¾8ñ6'¦ö«ÓU3Xy~9ì‡îš¯ü~Íø&Œr嚃°2Ê[àslP­õg pØUQ>Úå’#ƒj`P4ÀD.?à åÜT»¼j’k‡¥_¥OÉÖ_|Üt;M”sùë*³–5À-PSê4©_œ*7³ïõ sÎgVël ýmžÇÇýãÎMm¦j€z5w+'Ä~˜mPÍ-ÇØc¯dtFq=L½vâ–èÛ‹ÎÿÃ^T"Tìåu”£y ±õã‘×±´æ-,ŽUíÁáG¿…EDËKãoãl^ bŸjQmˆ8A*Ž:I¬G cã…{~Ð#›Ÿ[¶ßôïÿ7Õ¬îªR¨ÕÞ*%WýXa0Ê¿ÂìŽn¼ ºókm²˜·°Èšñ\²x‘ã¤a&/XP ¶`¥3]dÄèS‚õE)ÁÀP~%Ø2_a\° ¬Á×"•`Î}qŸ®U‚ªð”·—é"Üß­Yg¹kÛCmRp·FUÈbá Tâí"õ}ÛŽ•Rv w¸û"hj¾¡"h •hN¶N‘ps¯k“âr DÂÕ¥ƒ""á*•žPc–9è3+ô›S æàúFWFs¹ö(>«†K£b?Ÿ¼k+õµ½Ì/Æþ™ÜÎÂÝ'AöÚ€Qä©bƒQä©b/*%u³FýA÷‡Q´î¯E¨³îO`Ý (ÝŸüI„¢u¡Îº?u€:ëþÖýŠSõýÿãÁ¼úf*˜f©«7¬CÅåä£ÇKèËoF¨Ÿ›l§°ÍU­CÃ$*„JN}¹ºnª‰z@¨ô亩P½x´ÃˆPÙÙuSê>L‹P¹÷Z·îÅ(–þ(dé;(2gÁ(’¥o¾m¤Gôt~Ì›ÃýŸÕpsïüîïü¨/Ív~•ø}‰pã)›ÔãKlÒ‚ôùÜbá4ª@ÜN§Ã¢Wdpg(Oœé³…ê@¨s‡E¯Û5(ôÞLÐÞ8Žm_þ*żGýu|~Þ© (í[µ¨å½/ñ/¶oc ï}φŒâÞþP³À.P…ÇCM¾²\^u:íÜžÏc=ã{ o}fUDnԺ킋á£êö{‹P‰‡¾r!"¥ˆ’ƒ¦·åïzz'æ/FL’욊èµ¾ó?÷òõú |­”àœšuójÝ}ÚGÜÐQ¶P?1S?šPxµÀ´\­ÕãénC‹PüÄ´\8ЛãF8V€RNJG¨–·ûÒ˜Ï6²Š¾3gV=Îßä¡óWˆvZD©G^ C«†¡bSê6˜G™†e'ð/’Ò¹VF=$ó"¦NÓaׇ4b;?¤ ÑaÅ=tØÏF‡Å#Qœ>oõ(gõy—ΨR²oñ?EÞÖ›š¾³(¦Ì>ÍÛŸùÏOÕ®ÛžŸQî??ÕuŸ4/YNéJf*QD,*Ñ"TLøÂ€µˆ8é Ó« –™7ùÁȸi”s­„²P…:9>®Y®i«¹V4mí%BÅD„„ÖqŠp’ŠŒpj1Ê×µÕá 3Bì´4‰EÎX®f¦Ž“ ?ÂAQüˆ^s©Eð#zpüTJ)ñ ^ˆÓÀ©ŽqQ.â4ìa/*!:(_ó?fá FÅTÀ|Üq ˜ë1 ûá›ðµ«ó*Øuä°AnýM DeFõP™»me‹1;'´õ·þ. ¡ Pùε㱵þhEw¿!ó»a›ÞH³ N–ƒ)ð¡7:Õ"f§çhø¼–q]ÄÕÕθ.0ÏØtž®{¤s|Ï¡µãônJóÍi&„’}om­uKEz UaféNаbD ©%2)üЉ#€¢#B‘Š‘ßWNjzà9¡é‘HÓS V¦WÓ3 ÔYÓ#±¦P´¦gF¨ÌéhêÓß5ÿhxërr91×X·ò}}ÎewX&½PÍ•›(T ”“¢;tküxg¾m×_qw~¯¥^*ù»!)Á“P»£|u÷˜eT-úaT횦ÔžH/ïk\;œ]Iä;ÅWyÛ¼úçüÒ»µ„ý%ŒoÇÒ×záf6ë¨éZ÷Þß¾V;åB%è9ês=¹^W¡Rëȱü:ý.÷¥p –OÁºû{5pf\`ÈÑ7}¹¬-8„Š®duUÐÍ…÷ð맡ĨÄåßl>™j«9>Ì7dWäy›}áüt'VÓ‰P±aé€ ÐcsÓlß“s­{ëoOèשÝíôžàZù!€F¢›?eݶ潷|’¿ÿÑ£ªÑç§û®iàµ=¡Ù¼9ÛãÞòCf3öfµ7”;äL+©›´Ï\‘ä''š;<¡Ÿ´O)ÿÕc_›±Ÿ§¡Êî”ï°ó[ÔäµZi „Ú¿ŽU´Äm\Þ×wÿÑg‹I|rL7Z½«í|]Ù«¸ü¥°Ãã}ŸSuç›°ou¾~l,ƒ ¶ß»€#ËR«»ÜJ„òµ©«Cc†ŠUÑö;BikâX¬s·Ï?ä^u$XÑß²'|ÇÒPGŒþóçß‹«/d&õüP1~÷Rb†¿û/iÖ ¡’×Bò•T<ôL¤‰B=ðb•›¸D_Ä*7ñ-!KÃ*Åp’«°æ‰IÑÁyȬR\«\òU¤Rüçê.ðÔ¾'Õ¸ØÛ¦Ê;ôP³0rWÞ[„òÍ“,Js$Ó×OoØÂØ©92`”ÕãNalUt¼²0q)»#CZÆ&†:TÞÃÔ5ÓêÜY˜:ê”J¹: 3såJðÎØY¹Š^®˜ƒþPÈÉ#+CJ¨Š‚~I†˜Íg!CXHÎ?oø:"]CU›¾¬›? #]©íÊÒ&YmÂOÛŒ'~®Ä\¡èk†Q©¥ÖÄ~úÌÒ{«Õoô\½·]CÙzo:*°Lª·ÐA‰|KLšecI!ÛŽ|[/|I†Q¡mzN=½›½­îèfoøZæ ú“½]ìm“•3L©eˆ½­éH‹oèԑ΢è6T×yúõ2È­"˼Îá$HΧÏl|dÁ‘ÚÕÊÏÌV•íaU ZÌ€zZUŠÕÊ–R­°ìáxu¬üæÝ“Ï8ü>=¼¬æOˆV„ŠOö汦ÅþNwRÒ²e…¯ …úÌ-íÚ¡Ò§9f/òw˜Tv)»ò+ª§¥á/cªð[}=<4¥`«:&Ì3›hN-dWóm[Ö€Í Œ«G”Ë5XhmKXürY‚äl¿,Ö39½¨Yì9¬÷Zƒ±;Tú,øŽáÓªçWTt}&„Š0墔"ðÕwíÇü‹PÇ[Ýdã\î TúD§¡’§¡}ÝT/N¯ôP+$‡¡Ï€QViØ@°8ýƒBp6€’—ƒBð5”…BÀ³0Œ² i*ZÉmxᔹnAæZ¾ûÄsÉ\ƒü ž2×ào5±¶v„ÌõÔbTh£¼B)9qQ^•øc¦K¼ý0Ê"ï>(êLâ0Ūku$Eò<ò{Ñ B<¢ïéûžiÒç·D€’bhÄá™Ôâjò¯=GŽJÒC œÄXX”0r´å@¼”î9xÄB±áŽ#Pz’Ø5˜DÚ ¡,ƒIŠR (L>=­ÞãH6ü&,ä“Zm£I¬yÆ9â¹ú‘’®žJx.N…Ìnö•ì³Z«·q/%ÛL… _;Bƒ‚BM¯â¡¡.C² «ÕgãKì=ø¹"ÍÞ³ñ¾Õ±(IÌã„5Œ¿ÚÇ 7þ^+„òMC]ÒO#Qz:zŽVÓc´zW+G·à¸š‚b´z›jŒ NTñ9éÏøšî‹ï¢±YmÆEÈÈÍ BEº¢Y®çy¦ã¶"TŒ3…¬»­S™B‚ÒQW=–×Ü}÷7;×ý-•uð£4ZWüˆ…Q–s8ÎaC#v™u-ñ[}=æ´gþ†SÝ·$CbØñˆ,‡Ík7k0_;ý«gâ)[!ñH®tT øËÒ%_'íÙPE4¬ùë˜WXƒEÏ“]A¾_qÁ°ø‚UõñŠï'Ó»Å0«‰´ýÒ—þõ*±²¦Û§z¯åHT–º³[X³HÊþ1ú]®”>ÒÀi+ Þë4z™ehÄçïyh“Œ~aš¼—à½É$þÙ%xolCé6\P ù™¥‘­ˆ}ŒtBñ3Í6(<th(Ó¥É#ÏÇfb FùÒ4ÂÓ:é(]–N9?ý€PšˆšºÖþ£´‚Óç@Ä)¢ÆX ”¶4ÑâF}WÆ4Tbàg§ß15Ju×#+&„ÊLdna«|6x«/ËLAUk0Ï6^eÆÔ=^¡žß=^¹rê¯à C(«`Î×ʬ‚9Q›!”ÿ jS joõÌ92}%˜(cyçÌTdiPÞÁ’ñ¦¦XƒPþ£)ÖhM±K2þÖ:cOThnŠ1ÕËT^Ù3@ß’µì·Ô´Â(½u&ž~ÝHÿÝ¿Ð:Ë^š›1\íØ®Ê;™g\ý ‡LŠP¶ÁUEÙË<«€û5D–9ï¯!²,ó]Cd`L¨à&}V‹É5*›eÁ½u¦zÆHN*»Æé‰ÔôfûÈJ†P¶QÙÎúhœîa# ;€ r,gÈ"»´_÷ð¥aÁ{<Ѐ”ŒHðþ&Õƒ+B$ Z1°®à^óøY¬-ªE,oâùGü=H6Ó¸W_ž."”åÝU¡ÊþCõ·¡Ó ©FUÏ’G©^L<Å…ê!ºS‘ âÏ<Þã¡â«ø i~ÿæŠ@BÍ­Dª:ÿ‚¸Ððÿ‡á;¦×îIÀÂ÷˜…9„Ê´h"Ž3sEöŠÒnÅoõ…;ñðÙ’¥ÚZ霬`Ðt‘〲\,ê1lj À|­? );BÿáWãGó½ Î"ôßÿ—à:œ2‹,R¬´l1ìÊIÕÕ>-ÙãÅ`€ÅFù›oGð¤ÖO‰y‹P¾AYRl¦5x2ÄðÕÕl—‘õ ;Ñâ]’o¹ƒvÇèâäAÊPç<î·ªg—¥÷®ê9×q¿1ÊÜU­ûzÃo"µÑ¾¾V†y‡ A-_ÝÑ%L_¯×À¯Xm5"”®)÷6þþùˆ¯u¹‹?[[×ß]7|­ÐäýZï+=ø Pã¢?4xj¬Á“e™M ª­„<—C·po¥Ú‚BYu |­À: ïËwMÃêMø7•]èhÏý-©á¹nÍÉûZÄc@ÝŽOº&¼œP(߬Y:CåÔ’º… å˲5”e9*¶—eË說ÌeÙ‰îFS`B†µjŒByüý>«œ&娛Þp^Zs¾/oúîF„ò5VÛQIÍ ¾*$CN¡¼…Å·9_»CƒG¡Â[%â@õ9cùŠP‘>KvÄßáKÊuduýÊ4ךf!e^á§Ç16@R,{³þÉ uz-ÂcþHOÊ©l*;QG€æ°†ï\ÉrñùVï1ñ`ÅçäÚ#ÙéØa˜§’`“ýÒ)'té·¿1guËaƒbU7M­Â?DØ>Q„òͶOŒÕe§ùÃ3'Í£…DÚ+µëaÎ¥INúò^ñ¿ºbr¹zžUȦâ òŽxàïy¨!L_†ó@-{’ …å[r¨Çío*v¸cp7“V£E#ú‡¼Ð:Z„þ¡›1ÄýÚ[„ lAS¡bgÐT¨È4ŠP¾É€ DÒÌ8*±ÛŠu0®¡P¾E`TÏ•ÚD{k覣|›ç‘QsTæã¤õãìóçÊÍqæQ¨'݆"1N…2ˆq¶—§B™Å8KãT¨§çŒÄ8Ê.Ɖcj;±AÚä¿'6°|P(A±Þøa²øÉÈ÷öp0¤P«¦½…ÍÏ÷-nüŽäºcà¾ã†PV 7õ&œâ ¬Æ× M„»ã (›í€$ÉA̹F±ŒRõ¾"—)Z  YÝ¥ïÉç7ð?Æ.¹ú¾G4de«''üØ.—ªˆ€ Zªá5$D~b6ÀÚkš×`QÆQ©U®‹¿x)”¤P6¹®v>d‡`ë¢5C¨Ð ¡JõeŽXÝ…òRiWòެRiWò¼œRi¾Vðÿ“„tXÑç”Æ1ÊBHß'H¥Ï*”$êž¿ômcA!‹UðÍPw»\=Ÿ€·ŠŒBoJb‹£"»Ð›’ØR(ßlñka­^£¦ˆ) Ê·I€«k¹%À5”M\‚Äy\ -B…æfqå¨Ô.žÅsÈs‹ ›— 269«"f`±a“Cµ5=Ðàé× _ÎC˜†²† £lÂêRdO¡B+G®å¹9-B=9-â(Ô“#Ð"Ž€BÙ9ø¹ zq*6­/QW‡ãhè»G?äÊ ¢Kª`fñÒã`þec"«ƒìíÙvšG»dß¾–é±bÔ®ßÄÀß¼Õè~†)Àعboþ? …óhqhý(óá)B†¡nÑD’Qù—V©}§š+íe{¿ÕŽÉaüd9J©íjãgŠêƒPPí*zj6F×c~õÚå-BE—Hæ<§5l„ºIFA¦0ˆ€‚PX2ª¢ü>ÿ~¤ÁÏ•šãÄJaç³q¢ß4”%Nð£4L.‹Ümóe¬#E¨ðA=nê±ÚkÃÔ"Ã3‘÷NÔ™/L2<Û𵣘Gß v˜0µ·‰fU¤ ¯B¬I~väÇhÑÅÆ\Pˆ^Ó—}ƒ;F/ËŽ<\²~å9Ç[à}áÃx <}ä9Æ[„&,B™e\EæÏå´›U{Zä;ÌáŠçØà†Qó37‰‚ç¹V¶)xÈÙ®:lfj6b”Áffø|>TŽÁ)”ÕffßÊb3Ã÷Ú ¡"7yÜd8±FÆ÷sFžk/BùO>ñ÷3ÑñýÁ¨KGËŠâÕ»+)B…O#ƹfüØ”¿*zò‰…„X×*TlL(0*±FªkÅ.~¿:?^Hæ>\+qž·7Œòg>z˜_ì* óÇIh»5[fþúeí4ʬc©ä:#G™½–Ö1§¹Häßã±yÐÃ)ÀsÅ7ãÊ“¿¸{½ÑaG(ÄrT¹#ëÊ‚!TðäÚàž>~i%|r¬‰Jcv|¹aT„ÇiäØ Ï–êMðÓŸ-È“>д=iùþ*yXdˆ³™T_v.`"QËü~9cø7fÚ—vp!ßUË7˜~Æoõ…Êd²k0ðã)æ8a¶å°ö]RR–¿ÃLôäªêH¿ãGó ¦óÿË`xi—tlÑþñÐ@*î‹}Ê)þŽ.°>H-¾5HÍažyÅÂ7ñ)Ö-Mï6‘ð…_“2þ'eC­¥T ¯#ê`ÜrTàYHŽŠœƒÔjÅFNYÈ£¬ƒÔ°¡I™³%[©ÉœuðVïð›qúÑ­9$Ê× bÄW™/üx8½ñµ‚'jjH5æS‡PáÅ¿²Nô=!T¤q|áK"yNs|ÇøaäùÍÅçFÛ¡Ðø4éê®þò]æ¶T¨ôj¡i‡yk× _ëâ €êÅß­òuÂOü?¥!~äOØáî[Ýc˜‡‡áà]ô¤Z×R»š¶Ã”#P5žœ/’,8Ûaj@ucä÷-¾›öŠÿûø¸Ü6’²˜·ªÂ0£éº¨CBuM4i#½bðWôr”­ÁÞWý*¶˜QdV”¾§YQ»b”o³,…3Hâ9,KkUONtÁ´‡Á6ÜÑ×çRTLœéo(ÖnÆ(ÿ‰j%Š"TpÊŠ¶¿pÇdÊ*| Z@u%NkvúkxL/µkÅT (|­Äp6ÚI]N?}jCmøŽ™Ù¬hP5$°÷H÷AÜL§5B)åYÈÎúAF±Äd  PùÜï¥Å:7y»¨,Iôˆu0Æ:“®íèŠP!–g‘Ʀ<°o“ªh$×´¢ä{©ñZökDK¬E¨³ÂdL) Oõ×£´‘ñà g`¤“ÆB¥WÜF¿#ß¾ËòP™F0“¿‘ì]7VøZ E‰¹5Y{:ü*`TWÖ4 ¾’¦ÿÒ./1ì8jýûšSuÁù[ïÚMOq¢ž­%Œ®ouJX¨"§’ ®iKÊš("À¢›¶mɼËÿç^lòú•tƒ£[›¼x%!õjH$‰“:`”™Z  ×`“y®•ÚèS2 *A ª€¾nÇ@5JÅØÆÃ5pBÒ×MM{X”ª\tyݘ<,Và¥yú$¤Š°/Žºtê&ü\¦çøgüÔsµC)8õœnjf¥öÑÆS‰†£W1b‡’kjgL‰9CØÚR“X®ôõíX7@ H£‡›­Æª%BY ³B¶¡‚ǰ.Gí3ÏåZœ„§ß1z®{þà±9*¾S=`E×ãFF~-þ#†jß#Bù¦ç: ╚¿Ç£;q…òMOÄÊJ‡„!Mm^Jíé¥ÄQ™­Å¶^J e÷RÂײ{)me”7@MªìåjRí £¬Mª£lM*ÕDÈ^º¿.èQ¢¾Z4Ìðô܉ºÖ­¤òsQìb}¹,…š$J Ö•)êUæéeE°¦}?¶S³ãkÝ uŒ}áßm‹Ÿ>~¨ÎS¡:ÿz|­ä!ŽqŒy‹PŽP©YcTlÛ̳ NO¬]wüå&o”§TƒÝ$(DúÁ¿¶÷»ìàWúVý«sè£ÙƒAk< Ãpû¤V«eÌhjFN|xÌÂ@ãЮe¡qœï,Òi/Z3žµu²ØVúÒ?\Ëåé5l°á1‹çYC,ÏR3#ZD+fÞxÓˆTAOÿ9…2‘*FY³Ìí?7"T¨ù²Ô‡§ê¯Ÿ÷­?}ïõÐE•*¥-«Þs—„ò5_9…[ù»“Ùœ÷òœ-{¹ ½—ïlÙË’Œ÷ò]Ñʃ€²¶ìåÎ ¨Ð”+ðœ[JpT`÷²«÷Q¶Ù=äÂcPñ–`ºý¥áZz¡ ò!IŽÉ©ÏÍQñÓS¢gÌIXl ”ÝÞ}êöÅ£e÷냧Oœ9ß×Ê\Ô±]½‰ìÙ†vPG7hyÞËÚšh-]?êÙše;V¡÷r´ƒªNcekðyW&mP¿‚ïÑó<—è…ÔW¨§ïáç1‡¯B=Ýx©tãÝñŸn¼Üx1*2 ¡ðÍcB(›èEË6„2:®l Ä£Ê4ss´z[ŒÊ >¨üdÅ…ò¯¯öÖ¦ÝF™wxžoû:†}Y6… Ì_Çá>U¶?ŠP¾E6HÀ2óxÊF(°ç…nð†P6p/IÀ2ó0’€[„z’€[Lönfw°úÒB' ¸Ã¿1µÈv ê´ëø_%.‘Ì "4R ‰£{Ãî¤LzÈåÂD™¬BáïQªe·¬²µäyñîú¨/ ‡­Žç†BÕÅ…G(m*0 [o<ã‘¥7ïæ_!tù B'ˆí­<õyþëR'µNØ…Va%#Ó0ò÷{€Èä¿îe?³Vù®j‡¼,ÕŽ¡½ª^ð2»Îˆ‰GáM׺rLmâ‘'LdPs‘^`Ë‘ç!ùôÍÏV ÜÔÒ1ƒ£ט¾Ê}ƒÀ"îõ»ÆôÊà&^Ó‹œì¡ýŽW¶DÎÚƒ†²fÛ;FYk𥑙 ;KâÛ¨ØA;î7 e¡wû„Q1gbc9SððZzܼ3¶íÕˆPâÄ·ò ¶ßvð1*±Í)eˆØH*³epÃdnCÖyNÜâ½.CÕ|*xL‰œ|)… S Lá;FÆLAhBá§-’Poˆ9A¢·m”ÔSß7K/Ô*½I8ÕUAÈ÷ËøÂ@¨ ¡äµöùíëšã;b¥_zú,¿ß§ZeW\Á¼³[\(Ú4øQ‘5Hqä!i®…^:…Õ®>ôÉ(”Çw’ÿÇ×µ-MkÁWRÐU/sŸ¿*yÏ.º®ÇÕÊÓdÐAü¹ìR?q=Ýí >]ŒÂB|;ääÕT”­n$ÃW‰Iï<³$gÊ<ƒÉ)¨“õß6Oà™¹MµD…¯…†}¡8ÖÍ:õù¡£PB5’–[-ûö$WP¡Ž:Ĥyd4K]…záñâãŽ+³¬–K@ÝÂߣÉW+˾VŒ75D<:ÙßÕ¡Ž º–Sü÷jñªzÏÆæÌ VMøô}]2[ü¢iLˆœ0òÐÌî„fö/˵›" ø•XZNlÍ´ßòÒ±ÝHÙá1ÊÐ6-þC¥ŽÅʈ}Ý¿¬Ì>;†Úji§¾¨Y>ͳöl‘ÅUÚÞq˜o›†e‚•ú€Ø‚ù·Ah«•æ©CÅQÔùöBÐPçÛ 'A@]r÷ÀT€¢¨ä‰0XBàésËRê1O꣹g3’18U½¸{kFöpBWq÷¿ótº ^w ¦D XÔ~;¼ƒ»ur©Jþ¿ŠýøÐ?§ N_Á»íZ„¢6_  p †æÇþÙ÷´ü ThVèí89ƒ—…Q;ŒÚ£"£$ÕïÙú&¡¬Dö°nfÒäP¡Ìa]õn´kÆ–¥hÕ*¶·,Ež!”¹Íx¶ýý q¶GŒ2·϶? è£ÈÓ™kºÓ=sQÜñœîôÑD€iºö=21MwÂ;t™<•¯ÄÉ$O<]ð8™úN¦Ð7Ï*Á¬¥z.âbñ·ð>†Äeþ3Cá3$æU3³#;W•ÚgfÓþ\Uzo}( å¥Ya`/]iV¸Ò¬Þ¡0¸·,U±ß”G…V·mÏØaã¦PF7aò7bñ?&‘ëß®öÄËÎãd @EÎÂú„QÄBwa@aû°—«`¬l§JíÂÄ0;بÙÁbÊê\û“%+æÛo#™Àþ;At‹Á$L°¿ÇtD¨KX¦Eú£i&˜Àý¯E¨ðZL³d¶úؾÁÐH…oíËs4R•ÿÒ“Yj§ÅÔ¼‡z‚òÕË¿}­jé>!ÒR¶õü…nNº2ä˜MeT†ÜÙÔBYíEÊgSãEÊgSãEî%:œÆ«hèE]i<ÓPÖ4~ègBµ*QsÏ oê™Æ÷Æã;ZÓxµÔœÆ3i#iü‹Ú”¼eß#TbÓxS9JÜ(c—ÙÄ…«ú¼Qbîñ´{îè¡l#Ð pâ_\î‡ÌýéPÊQ¾SæŠؿÝ%8,WBœa|Ë.uLn¥Û†šÃaúƒ1ÑXo™’`Q÷²4ëˆPÔfô-Ìø~:¾¥ £ž Ó^0LÁËM¡ž Ó¦ ¡‚+´—¬ÐtE¨Ðl™¶ƒl  ^Ç4•ÞÆÔÚåááŽÿF‹ÑË®vt|û†=‘ª=¸÷FÙ$ÇT(.É1•aK†›pêà"K†»pT›NÀqôãÐÚÁ7%Kä#¾ºn;!Qt_|uCw¶½³wÝ`xk§§Àj¯Æº%œxö£œ9ÅÞá4‰-Þ¶Ò½SõS㻬½~^§VñÂÿ‘a˜Du}Þ}¾  ë'Þ]³Vù#°á݃f­Ÿø· ØÂQ~Bì¨ïÒª&v¹JqFÃ[{‰Éë³ ™qqu™q©¢gBÝf\=BÙ̸6(ëÅä•°߆°öY’@J^Œð>&Á=Ü9E@·v¬*´Š€åÔTBÙD@Õ·;±”ˆ¤pÁ§\¢{¿gGv+ó¢÷g› A•XÞ!¡û,¬[B“†ôÁ•À(ª~PzÏù¸7…ø ÿ‹D@祜fÕçEºâÿ)v¬D KÑÖ݆Pé8%½ä'‰[z©E(»ôÒ„P6é¥Ví¯ä6[¡$¡>—ÇzL<{¤0*u…²z¬Ë´›xÞC öD–}PH"žï*$ÁÀ)ñ|G!©jeÃŒx¾ÓbdßÊVH±@…f:Åÿ#ˆþ4¡kÊvC(,`(wáÎÉbé¥üñ¨MžX|{ùkÄä6Ä«0)@¼À5)0Ëø PÄP‚0”E &Õïh„aR¦kŠZL!¥g¸BFvìÑA¨ÐZdçz¹‹,e3"©BréŠ?ç¹NÉD‚æy®S2‘x®\AI/6—ËÙñÖs”x±Ý¯L9*qŽèËø‹\lõ'/qL7X/Ì Hã4{‹QÄÈ ;›oÄ'vÝÙ|#Ú8L®ž‹š2ƒ¶*p¨î«o-ñC×·x¯Ä×Õí†ÓG †Sú†=áëRBwqå‘!j×àÐÑæŒm…, ê*$ÉI)íÕõYޝ… Î’£Íº7Ë¿i‹Q¯ZÙµ÷í¯âÇo™"ÔëÑ8(ûÏ{hAˆ’øwëÛZ)ËðoZ³ °ª±•s,(hý„PÎqs®}ü´#CÓ´ðÖb–ó-⻦i‰Ÿ¸§iñµlÓ´CúA(Û4íÖã;††ÙÃMd†ðµ"žkb¦!âBæPBúF Ë}H‹¡ÛD¬Ä“ Ìv{&Äw˜í.SÓ#”Ålwn¾–ÙlWYƒ)T`æßa~¹ï‰còûÜ”ÍCÑ„ºÎhˆÒyOèÄØwËSŒ„¶Ù|a0m ¡ˆqvï$"Úg÷NAdrÉ_g÷F|-úˆ:Ø1Ÿ8AôH^69za ’¯äÉ6ËÎ*²ä|”›Q=Î É%lmÌ ÕsÅV…=û ®•8ÌÕùÊJõç½²@üMU%+"„ÞlÙòªA¢ÿ|+"Ôe›%âècªev¿|C¨KjO ~ÔÂæ‘_ì'›Î€:§Q…¥8dåŸr©ó£NYÛLy#-óôùfU×#ÔË,ˆ¬m9*4A‰¾AõIY $)‚ÅÇó•éyÇð>{Ø(Ã¸Ó N¡«~®Ðj÷E¨×ÍžX˜¼ke‡ÁžBEø!æ‡>BÅšaœœdþ4õ¶©·(´Ûʵ`+w®ªÝV_Ì`+· [¹ö´•cÈVî„=måzd+wÂì¶r†Ýl厈4-Û~Ûj {Y}€NÐPÇŸ?Z÷y¬§y„P†>}t!.¾UŸCLõQå,‡RÒ2¯…КÄ(‚:ÐÛœWáMSÏE*’C׌Ÿ™}1*x²z¶ux×5|(iŒý?²y°ÿÆîS–*¡ñÕ1VeõãŽüÇ\¿Õ»E¨€‘N›6øZ±ÅùvRÏ•Øç[(g %|á˜jײ 2´PŒ¡‰UÇÿš gŸûá³ìPÎ|¯¯‡1ðí¼>Áà˜ŠZæ wNJ¼â²ÈqƦý¼ßLjj£J|­lå@(‚ÔRõ‹ŸÌPë‚¡; ÞÊê'£]Ëê'oí{å²[/ó òxkïÊ,µ_y:†Pë¿«æá>Ö›´\#ew¥×ÚÖmíRš‚Ü”Ý tÖëö]ÕEPšú%´>—tkUXÔ/Çz2%D‚×Í™´<µÞººí_„Šosbºb«yÊñ}îã˜!YK~ò/øéárÊñÕàxɾðÚ?à^š.‘X…Ò¶K>„V¡4v 3npîÝ*x Ö÷Ç`=ÈN v ÖoSÁÊ(;±åC ii`Ov~RÀ<ôìeµª~<ÁLn­==±c [>Wè?¹^0¾ÕJ‰„ºpƒð¹8NŠb{¿‡”i×¢TÉ3¶a!e»´ÝÿþG•ÇOµð5­ê_«ý‰Éûd9½OHäô>aFYš-ŠcWWìÆ+û;.vD¤×ucÙñh²E(¢ýÇo.(Ó¤ÞL߃²üZ[Q~›w3aT û1Ùš¾çß w$Ï J§ßüŸ¡L~ Eúeíœ#”ÉaLë dëh­Y [‹©4ÔÍA|§ÏÐsØŒP/Ü‹8ž¾K?ã»j³ ¡¢S¾Lé©ÕúµêBÅêðá yò Í»qüU%VŽÈßEü‰íÔ}†¡ê¬ª÷(ø m1Ôm¯Ž~Y){FrÁþ ÿ楇u• ëæú=!ű ª”çv5¤±ÿBá -×Oµe-B]R*•fÖ–ó: ÔËÈ~¯fÑ%qhåõí¸B§:'¢ȮĉX©-­s;¥ò-ŠâSkw4ñKXÙíË ë冿Bžøõàq(>á%ï@b;Ÿð’w qä6ïÞÊnÞïhn‘œ>$¶*H#i 'öé T;'±14ÆfÜ'`´$žÙ²ZÈaœÂ $ñír§pIü§vÌú)P¾Jˆ•“›¦'(!ö¡à¹»prM$RÆަ„:Ô¨w°Š!I`årŠõ‚bRZšE#CÍ¢äe-Ñ¡fQbbíÈ_ûü€kE.ɰ'‰#ÔSXûØa¨¦·I; Õ”â6ÑXùwC5¥¸ (‹9éØÃ2Ižƒ©‡rKµ¦ß š~Ôó¨Fjä6)?îeñzžÓžxÇ(Ìs”'Á‘ï«Tð0 fÒ,Xª¦*Ô™ôbÒª¡^šUZuˆfŒÅÆ~rÈP—íZÒöÅö.¦ ÄË? Õ†vbÙ·–»PØvM~­8*«æYÊt¨Uõ0S ¶B@hs ó5ž¦äå§E3¾»È.Ü_’•Ô!ÏC¨¢P8ª;-Œ¤Q:kë èš%9h–,ó8ÂÇM¢B'ª†%»IV^š^Ÿ}WµbêENïáþF›ËCÞÃÔ‹C©êZ‰c(UÍÃS/q ¥*‹@Q› ³|½©Ú.-z@*ŸúöÑÕK¾—ú.‘ßsOø¸Þy2ãGkÊ9‰nëO9Ïr§Htªjr{¨‹n—ôjz‰nÿ9ö—bÆð `› ¦XtÛ`JÇŽZM<Òâ#QÛo=}©øÈê©Ç@ñqC(ƒZC zQÛŸ]å“þJ}wWyÄ(sWùÔáÅ.ožóí6ͰöˆË¢,!Óä;­ó†‹)&š T)£¾Rü»\gFQ]`¹>*Ý“ú…®óV[oÓt'N@…§rÎ!Q|ÔÒµÙ~p’ÀLœ–ñê;DB»Ñž¶ê}|¹ìÔw›ö0·êÎ4&LHÄD­»ú+Ò„Vi~Ìü:¥~J §Ï ëY· Œ Y.ߺ=±¯UåVþvìùr±çvšµn\€T¡}Ãr )zÝ·S¥­£5ãdÑpòüxÆsÒöÄóöÍÆUž·Ïxãí÷Þö¶Ô4”å< vˆ‰m9Мk¬çi~Ý­Ì<§ÃXT»æÆõZuÖ™œ‰‘ë|æW7¹\Çk4¯ê•“”²Ù賜*Ä@›;Ÿëˆ•ë<—\G•y9¯ ´ÕÖ–[_^òmíC®üø®UV§Ž!^òúôW÷ô³~öcm ¬˜8ÀýØàî˜DÇ¡¢#b ùµ‹‡¼vt¨ÚòT€âájGë¢&‘Æ¡–y_ÎäzÀ¨”.œKüô1\¨^øéó&¬á–B…Çç7ˆN¸·JŒ :ÃX;ö­`­ÅmDä›#LÄ̃\s„!íë@Õ­…« âcÊöôT@YÙ/|-2ìž–}®„/IÔXå**Ãð q¡B³{)úS¶3й½¿9Ííýµè˜çU ËÜGûîëî~7î­"þò1ç~ p. ½êMÎm8K¨ï ó—75üåoü±ÕYz[ÊÙHíçUš„§…—ùkÖk‹Phf(×IÏªé®øZ,`pþ¹ßÕõG¯j”Q€¼/eQ… Š’Qp™fÊ"2 }g›\ÌëUu¡Ë—Xº3]ÞÔ‘/ öLÌ>hr+—Ǥ1k­Ü MîÁuFÒt³zÝÇMw–b¨ ”"€<9ýq/ƒY>üÓŒnVú,?Íèf¥ÏòÓŒnVú,?E¿í@ïêÏ•G *!dM£Ò@ò«ìÓíuñPv¦ló4Ús²H•ò'úÃ2$À±QînµWîfaÎqë$ž R–±¨r7¬¯,’ßF˜:`È^ì_ž™…Ÿˆ¤³íø:Åk(ž-Š:­éEñb&DñÌt’F(rÇ„3-Ë"~³‚¨ ñqÒS.VÈŠˆ˜‡“`ù)*;“ç½I3?ËÏ4iæGaù9’MÿºRyBÎV™_‡»cBв ê|ÎHQ?GÃ3ùx*8Q–G¦Zä]oPÄ© ]nëU§ÂOº…íXÕŠZçÖŸßïý«í¾šoYôÕló>ƒÉ~_vR“åé^ÖĤ.×z4ÓË2€ÅB¨e3Ñî}¥GنߵÆJã; LjºB_¿^/·&Òl¼—CO6¯F#Tæ…T ’Ñ6Ÿ¹lt)*÷¨ÛÕZ½™‡,ñÓ”ªûŽ‘Ý¤lè„ç"ÒySàßÃò,ªk¿AQºö®—œg™ÇÖžµ®u×?ŠÂ’ (R×þ¢ŠÔµâçÚèÚ¯ïÞB/ ¤d@å”赃TᚌÐÜ1§g0“Ô„PIð´úÙ<3$Å´yÖÞ¿~î öª`áΊSÌÂ|LEZ¸?ði w|GÚÂ}B(ÂÂ]« Š6-•Eš–*Œ*(ÕÈÞ‹sÌÈHl KIlóE’ØfŒ¢Hl`d (Nô<\Z^ì'§wâsvÝ#¹áøœ|Hn8(>‡Q´øÜ¡(ñ¹Î=='cr›ÀiUˆ}¾m=dÔ²“wƒËù°Üð^jp¹'Ä«EžËUx.—”Ú:q;¹ç"Д÷ÊcE´oØB5­ˆö ]VDû†.JóôLj³c+EŒù\~:…ç9”ïõñýò½>~ÚFifjÊR{= ̵̯v¹»S5ºªûýÑ|/ ¡’Íiee ¤º:ùF(pÊúz§,@q¤`¹ˆªë:}/õ¡„G9ƒÑe'| [Tºå5‚"…š—D¡ü¬HM,;@?ÝûŠŸÞîrÿ¬«ðêŠÈóMJ"TA8‹AŒÉ=_1ÀÈZ~¡Ž k`ð?ôY7ªð\"®º¡Šà¯8Ö?¥Ô‰¼yú4|­ÏÊ…6?Q Æ‚´‡™hîe}ƒ^y-ܑȚ¬[ˆâñÓqÜËv˺ç·éªËºGóóy‡ÚrÓ¬.÷R¼0¥âäÏæå=ÙH„ ³Î& g÷<Ê묛×½B(’uÖák…Ü '-»¯íâñ3ÊÀö: ½svågZ®íLçØ„ò< ðôràR(F8Ä•D¨ƒÍtP'©ñµ>rêêŠb° Ó€Pa›R#ì…gc°AwPEX²Û¹eòsT²[ºU˜ÆÝ2B1ßw³³‰†¬Ü·²éaÝg{eg¿ÒŒòö­Ÿ…zpúk^R÷_ŒbᎭ‚:?瑎íGmPDÇv€€ŸsŠY‡ê˜€â. X…ª×nÓ}ù¤÷º«, Ujþûë…ª?zª.'„ò̺¶=);'ÿh0 e† Gh~ÛïñVÞŠoÞª™ÌZ­6æ÷ôD(¯—UAKç-ß÷æòjB¥?9kØ|[õ™›ñÒÂùx.6½²%+·‚ªWû\¾¤[_E@/Ë –˪j|aTp€ÖÞQ'´£^û¸ƒMO¢Žz•s$â¼70L}Ø}=·öȘY"QQɦwmùÃå².×µ¨äл¶­“[ÙuÕÓÊ’sÄ(õn3 å8wúÙ"ÖOvf¡yç4ÔÅÑl;è]–“oÜ[M¶õç|^ßGóš”F¨;IÞœ“ä¨^-Fe›.«¿–³ïS¿Bå[”ùÚ¦ûŸ„*6âhvRµ¼¾çáÙã·ºÕPk­ gûýÌúaçí.½*b^Ëûmð“ ç6/›y7Âá°u¯øûÇÉpš/^š˳ßÀø:ˆ Ô U‚à֕׿}ëð8 \\÷óÏðî—\Ù]u›Öñ¥ éæqÄ"v=TU<î²{5÷¡˜ÿæ.&¾Ïªj|G~06܇qÔ–ù (±aâۥ헳­Ã¨@ÿ½+›¹tÑNÂŽýw«®WöÝEož+vé/jð‹TªUG¹K9Îãæ­ž¨):ãÑ):[>á   ÉU:4E×I„âáñŸH?=¸´Vp ¯*õ­*j.ÿ ½(F …j· 3²èÙþ†—•i{úÝ› ´÷úä<Œ.8¯O“Ïþ %pžÅ†fHêxDLÕ§¤|+¦z¹6–k¼|nÕ\ä8!TxŸ(p3#F¦µ[ÑE¼ðf÷Aû™ñk¸–8SÚ#“'q‘Ðd‹±‘‹ƒ„èè¢K47| R8H o}·û"ÞP¢kÂËð}Ø}¼UKÞôŠ‘]CŠñ‰]¹Ü;\¾ÛešáéÓ-qv# ¨ZøÚb[x»\`ê=™"‹‹¬Ä~çfÓ¦Çí[öMkµ€¸ØÅ¾5Èu×C©gùpÏ•oeekØ™Ú[9·3¸‹r‘SïËÄ_E¤±>Œƒ»cvP•ÖAZ(é)"ºÜjh{¤ÛSá7^¦ªyÉ}'Kºæé9­ãe7æéyWxóÍ‘ò~“ÐI-†Ðœ–ÆUºñ~@qJ´Vtš2Ͻô2Ï<% &/óÌSÚpÀSÊøN¬w?Tùc'€_Z'€•“ÆÅ  <—ÆÄ æ®Ã(Nåu¤YX,d•ÕûsJR¤ô¾{IÔd?ݯ6ÝùÒú7d@8–¨Ýîrk;Æ £qDµ©¦µ3ÃòhÓ(oEƘpŠf§MüuðO´OŸãþ‰uôO”Ø?P„¢ÿD@Ñþ‰øŽÇìDbÿD@¥” |G$òB Éð†¬P6×bTãÖjæË¬Aëø‰¶­Äf ‹éM(ËbfØñ !ý<d1§I?†LÙ!éå ‘t!ˆì{y*¡zðµ‹4Ú3€¯]¤áž¬ð=ƒ"vö¹qu^d±quW«A4É-Ë}¡!Tè´5¼ÒjEq°ö°”ñ®ª^—êÓ!Tð´-¿kz[wç_­Ùì&å KŒJßϳ^ºq@¨ãi«–ÓöV¾g|­|Ó·­Ñ~9]vU ‚‹­Öè׈+¨ûüÀoõä:¨emé[­l—°iYøÁÎ`ˆ„ö¿ËÉPš²†%;ûJÓ­[ÝŒ#~ýgކQâ÷¿jbOöÄuÂêö’åíÓb˜ ÄLì~.N§ˆ9ç§sLœ¨×ât&Gd×PgQIÔäK+„¢M¾àé‘joò%N,nò¥Š4ùš0Š6ùêŠ6ù¨4dðáµ”Å‰Ç >~_ˆï}¬Ô2/ü N"F-áqqÃF|-Ûy]¥=ÿĉöÄöC€â³qa˜8eÑzÀ¬Ь´ ¡éP cN:TËŸCµ8åq‡ê¡h‡jP´CµD(Ú¡£RJ ‡ç*HùM/ NETÀ=W¨›döÃnÙÒ_ƒ¤çÓa¬âz¾c5>­ç¯8or.®¶ðPÏ{==î5Bù1sgdöPûŸÛlP¿ûu^v€÷Øu#~.L¨²’ñË»¯/¯ÁO•TõtQcƒP£[©.o#¯FuA¨uQŽtí‡W)ïw„ÂÉ@³ŽÊþÙ Ë&ýÅoõDÊ7ÃãŸ*QV¥¤í¯#4à¥ïºæ‘%¤ÁâÌècáÖ­P A~è%<Úé6!A~h» £B¬j=ݺ‡{"Ü*–Ï嬦oPáfE«ØN<{9HÔ ÿ'ê¸7%긟Ú9NÔòœîˆ'×”Ì(ššUæèܳȜS9»¿1£ÊĦ®á°=gáYpE›•ÓÇÕìäçæìŽ+#|†P¤&+1É)ªÉºA‘NyFòL8Ýuà”(N(·Î–¨£œòðI§<ÛúTRÁ~Ny€Êƒ †<ªªë+¸ÔO$çXêÊH"9Ó¢_qT 6îaJˬ¸# —$Öç Î0Â.—ˆè c‡Q$…pÆ(r†vßDì”·íJÝ“x»²Õ•m.¸V¶÷m‡žÓˆŠ£" –v[WÚÕBaww˜È™Œëc~#ÛjØ®ÞV—rIn%FáÉv{p/Éæ÷Òt—B Ê; ö‰¤ [fןž·`§ÈÄ—KÎ…'áÚô=ð];Gt2î@cl_í@µjö° YÑEšK¥*¨cPšg‰P<´ß=œiŒÑ¥«ÖÕ’ÅŽª·Áî'X÷ŒGÔî‡nÒE¨Ý/Çã€P›}Ւ݆e_}W¶0"vd·ÊuQëAÏr|?>ud]›‰‰nj®B¡Ð\̵n÷wÓ#£žå%-‘­‹<¦%íº©B¨4„ú4;”Wó½‚%×ã½ì÷ïm¿*?0¸åÊàv;&~êûÀÍ~ FYÕ³#9[—£Â0rå»–†§°U7˜)죎q¬üN"±òçßÊO7äì­’T ß;Û6x mƪþÖõ¬^¶?"‚”>K¸è—¤ƒ"'u¬WXÓÅîŒq;«–óz±…hxœ =ê¾’ÐÖˆ†‡&ºW­îuÆ(†iÀþ×ËÁ¾Ž‚Ÿw\ÿÈþ~›aj.… ¦`Æ·æg5LªB(FÆ¢ö ñ$ª×c‹j„¢bQ˜¦§ î¹X¤Ñp.pFÌɯ×+$ÁyÔûÃÒ §wÃUí¯C¨M7Ì*Tëç·¼C¹_ …TW oíÄ­2ÛÉ£’£ŽµZþBg(¸;%Àœ)¬h¬}zTb™à—Æ£J,àý!xT‰¥ðµŽªgª“Ÿ›î®=BQªgî$â^‰e-óÕPs6åÃÃçÊ÷oÕ:'.¨iè C*<‰ðàíìµEog¥ŠPFZvC{GÉbä[mP„2Ò xÅNmõ§Y¼zF(]a߸³Ø=º~•ײÆ(›Å`õy3%ÔvÛ§'²˜/ɺ ùÌVîC>/É”lr«0}î}åÑÙ¾£È£¯Ãwô\»ê—;ÎË+“·×hQˆóøÕ³€ýd©fâìl:Œ"e©zŒ"ílà}!&nPºÙ~íŒnþ`éf‘%;þüN”_ WÜj®h¤®˜ŠS†vd,6¡Óq"ãÑzï™—~AœÖ½‰ô@H6»Æazµ²]Ñm¥-®Ó„•ì;XÑY¶µÙq‡­)ÔZAâ‘Zëiµ¤™ýkl1*,ífŒ”±„iYNS3ç^»§/H÷^?A#òSܳ£Âþ·¦>a¿öž ê„à%‚y4ÅwåÇ<‰ Ác%?)ŒâÁiû¶;A‘³£ÜL½¼ºù%ÖœG¦^z×àÊyXæ ÄpÖæ""Wj8ò4˜é]§‰¾k|Œ<#K}#¥Æ(²ôI2–>Ý1 ×®•Ç.‚Éó0¿ì’ !ˆ8—ç%0ñvI¢ &ä5²K9]r[VŽKñ‹ÿ »¶-M øK‰ÐǾ·ç´Ÿ`oh4âõôë ²è¢@ß'haw™y^ÊÈPˆý¬ÃPŸy@¨EÈÊnÛêß·é W¿±ÕKfþcˆÓ®ïûÏŠPÁ™)Õ#ßgïe«„ "L¥²üÏtîŒsн_ |i.ÉLÝác]8ªg¯G6´m£g!ñöªAA±Om½jß¡œ½j)¤äÅZ@Q{±¶5е)uk‡³X›: 6ñ5úëH¼%ˆ™ÒÔ+å %‘4õZVå”òdøŠ‘Õ ±êJe¡E®®vÉj¬€ÁMNw&6 v$ÒyòUŠâù]‹EuU‘Gà3W&>¹°åE®dÿ‡¬fLIp“GtÏÓôJ.%+F„ ¤ `’GìË·¡Kˆ þÝ5ß>;¾Éƒ^Ža™˜ÆoU-m^)ÔU$Ž®ªQZ·"”Á¬«€ 7¼Þ~öäVöÙg´@MïþÕ÷Ù=Ý˾*¶°»†—RÊeã€mŸõ‡M€ºrÀvçw.¢¯W‡P ž«Pm‘±f…xËm‹È}ZL?Õ‡Nuަ°|ýð­üUðÀûIø4(ÅO¸}g„Rüì*°¶i!y><-¤¿qÓöŠ¡ôKS:öë[ñ½)”©Çvv/É3<þûÍ`Ö}ó¨x]ý¶fš*tmjðXŸ8Õ¹ojmƒP)óý» ëú𸀝Hn[Ÿt|<¶>@ÑÛÖ'QÇÖ¨ä¶õ Ô¹õ*uè׊<ÃKqV0A&Œu_tò ®oFŒ ,¾dÝ(¶˜îÞÕÂ,ÛB?pÒGz¨¥-’>‚ÔC/þž3o~s×!TähŒ+ÆFvŸÓïL|j̸"±z‰‰e"ÃcQ«—Xõ;ÞcìÒe—Vb°Ù’S=Ôî‡ (â÷CÊ퇺"Tèt†…±¨ß–!”Û¶C(·3ìŠP‘¥M»“ª“zÍI|b£~‰GŒbõœH¼ª“ÜWê.Öª“ä¢jøg-%û©±‚Ç%ÜF®Ï«>'ˆ‰hqjö ¹kfj%øU*Á«²5A,½›ü°U£œr!úŠ¿iîþš¦;„r«k*òxëò bO#Kîrqùö5ú•«ÓÌ©û{‰B¡p±VUî®>ÛšÍ%C¨Ã“H®_{q[Ü=›·ÖÂÀ”šº¶öéçE½­}úÙS·ô Ò9¸¢S\a—ðÓWL‘‚<[„+"á:ÛÙ"|ÛáÃ{¶W ž³ÅÁ·>gžª}Qß×ÓÓ¾¨ùd€ œ 8F"–ÞÁ Oâä‘“¥gmåpE‡˜Žä§‹§³0ŒœªßÙ ™ç$ŒîÞöHØB?ÕøZÚRå‚n,_Ý+W§¬äÂÇz©˜,"s-¶¿ ¡,íTÒãp`‚ÅÓ,¨†!T„l®èü9QPñ­éjwB¬*ãŠäè²{C¦Zçi|wªÉPôìÅ«»@„ÛyùG<ÖY½¡}C\‘½Ë¥,*u,€ ©¿X ¨ÄU¬e{±fŽO¾§k*†PN™ ¸bôp3©­~‚`610øÒ®âiÈŸ ¥†';ÊR˜Ób`$ ì%  ÙI9e÷¤cd'QäqMÖͽ$Šý^ÔB¹Ú»Æ"žž˜jÐc™ o8žXkQŸŠõÈ1Ê%+å;%ž6BÝèI¢Ôï¾"Tàp9!ËŒ}.§ßæDìu9ÝÔÑ59YH–Þ]('ñÓW(çH?âV²Ì»{øÊüÐÙ@âÀ.6§"ÑV¹“{cDŒrF¢ð=Æá%–ÍiéSÕ°"ä8òÈC}tü…X567g}ų kss†¹ŠX5ÈÍYJ¢ìnÎú E7ÏgÅwª~†ï‹¸<2<uø4Ãñ)9Y5÷xâ°i&'«Ææô4è·Û·ºa+yÙe#Bv_¯,3Æ ±ãM Ömš%  (‡TÝ€º³å}° ¢ñ\´Nr©u{G|M¨À- q‰›Æ#w«ÖÕ˜ºû~äºÊ*°ÈsÊýq…Ý “}î¤ù"HÞîÊsíøky- ‡ õ D”V‰ùµ`”Ê~ÿ€|[é̈ÿÈAê„ǽf¥ ™r{ù~„ 0JúmdyÛµu¸uH.‰býÍ[„ä3+Òšq¨ª­*6º”û0ÖB>DÎfÖ]‚%‡Âï$¢½¬Óy-9›Y÷¨Cxä݇õ‹®çÇÙg Vr5–ÈN6)†‹ÇJ’Àj&äé•m‡oˆ<½¾qF9eÛá:åM×;¦\ï ê¸8d«8zøV4=DCHÂÏô¡}wÕ¶èoˆD¦û„äG–àHROSO5¼||Ô¤Dßù#TpïvY›_©»] /},Ð9³ß–\ß×Í= øÍ«jDƒÇŠ1§qŸÑó:oe¤@@GžÒo„Ä>Ÿ*p˜%.ÊÙSÎÈI{Ò”3e'Üþª_ÞpåéAíiG 4նߪËåPáIL«àdAä¾U±6BENb+6î~ŽønsU胅“¦‰i°­‡_Î;}÷är÷´mýiÇ<`ã_ÊYYyªUÙô­Þ늯9ék BŦ,Ú®–û™?åÇ[$ñ:v5 BáHå#$»JŽ]ä$€©˜i÷õ’µ!ynµ@9 `VYm½Êyü—j¡?5bE(5b„Š.}¸sR; F &“Ýey@*X©]‡¼Ý b¦+µë”·ûœS»,Âu+rÑ€$ bG­cÔÏ+t;‰m®OÐÈëe \~P@¾”Ãj`0ï)²é„ßV¹úüଠQΔÔ¨Ï+ߨOlï uíc+T‘¯kÊ‘‹P#"‰¨Íj/vTå6ã±äÝÿýç.m¥ó!Îež ¹ÕI_Ûýì”´ÕŽ’$½ñQÎJs®¾!šx+Í ÁF[¥Y¿¡Ä-'/ÖXïo~èØ7®fÊá'@eíñ:åäå’“‡®’<ìÎÝÛRÿÞ@T‹Inà}­ŽðÊi›‚ä­®…\r8ºÞª’Ãú•<}ÏKG0Ià{^«r>/8›Kœ=qÒxø©'½r‚‰|ü;òªQœÚa*¥J)rÈ;ÓÙè°fÚ¶ºÝÞ¬ã:Ü 9Ôå’Èsrý âò  î»"Tàðã<ž*ñœQàÇI╾‚ÚPB½µ!¨ç$WŸ=­ïµ,=˺Vå ’WE¡Ú-Ê<88ñÄ´:¥©êˆ/ßKÏÊbæQ}É~¾bd(WîUëV$¿kÓ…Ì<ã¿d[ßkÙ`±wk“$âb“$=WSOOS»Húðœi¢(At?CX°åóö›¿e®Öׯ¶Ó3' =_íÄ ”㫇£.óEóû"”£·ñØùÒРçÅ®äæ} }{·îÐ63B¡XNŒ´ÇrE%f}ÁñX'ËB>‡|§G~>Ÿoi\1²GCâ5Á“¸d|@ò­ìØ\dBû_l›_öáìÛilŠGÁ”b ” N¨³¯ÿ «Ü$>í‚ðm§f_ÿáò¶»cÊ„"È¿Mõ™:ÖÃ7”Æqè%ÇÚ÷Ž×oz÷ï¢C¨«CãÞ/6ñNäs•ž¹hYÀ˜µœ¿Ç?Õ ùTH›µsÍÞã‚aO»¤ñØA0ìÆ§È7â±Û»ì_"1E´è²¡`½Èf0ìpã˵^Ø[üb;È Cn| š;"-:(RyóJúË@€`¹Oc.ŽìÌ$©_bÑíoI0oðX¡E¾²‘ò•-C¨Èª2¾«ߺq'é«»qE¥L­ú»ÈeÃj|÷ÔN°—Ge±þäQJ@¥·n\¶wãêX žêÃÑŽÛtÌ‘iñG’&nñG´œüËŒ}ëûOìÂuÕ8gbÂÓ%M-Z×Ê‚je"Åý ”ᱨnaSÕa”9+T½I¬ HDdý׈šmd) ¡b„Rº5}¿Y‹¯H¬Æ8Òkzÿôá67øðª€r˜p0ÆT螆¨›>ž—÷ç¶ÒT­ÉAÏ…b{Ð Rü¡¢ùŠPSUÞ(ö·7r™‘o\‹2Ó‹¿½A:–c”ï@‡yÙó(½ôô··üG·Ò‡©”w3Tä9ù˜FÅN%ŠÓÕbOlóO™±A?¯«Jduû—V€†}ë‰8˜Šü¶é²oPHŠj£m—êãГ†»×uÔ©”b”µ…ßhÜWŒkD{¬)ßÐ:‚j}Ü›Y*,ŸÊ…ó¡‚›¼ô;nµ<5A¯Êu£ŸDrŠN 6`”K$넲eb² Á;†PÑYø(‰ÈÏZÎë¯PtjúH搜ÀËló¶i…¢5°ãûõ¼mÄFš!”Ù¦RÂXEÙ,/„Š0áž}bc+ U‰Aà²{òØ/|E(â$Ï+Ôóá2«\OÝútZZ®§¥%}þ¥%G(§Ú¬&ÏЫ¶óëúÔ6À<PhWøh'öuŦ<#Ô©¶¡×BÈ ZBu× d¯m<´ eWÛ¨´Ú îšb»n¡kåí°BTŠk %Ôª†oµw ¦±’Ý û´È*Ù/Í*p5{΀ŠÍž « Χˆi ¨joJ¨ êÞì¹·qêfOúŒ™ØÙìIÓØ2¿ é>‰o~qåTsaåPsáü…Qw5j.åRsaz¯šKÊ:âÇLÏâRsɆCýP©5Óß´êŬeìýÞY&½ßá¾’»¼~¥N>ûîç¡îÞïùØ®/Tý—>Í–ö#h;‘Ɉý–!Ô‘ŸWceùï="T|‘=–cÕ¿ú5ÕB«¼XO¾"ŧ‚ Ž<äøhñ“Hnnóm?Oe¿o„:ÚTv}ñ™~½ÍÓ?Õ‡N=”n¾€‰ l˜‹©þa˜]EîÜ“Ÿ©Onʽ'3„ríÉŠ\ì-UÏ ÁÃÇö vud`žÀwcõÉ<¡ˆ›mežtåbžüóP.扎À‚§QK:öÑiì«~kh—¼éS€ @·JA¡‚KvU¨§ºýš/B…·?Ó˪C¨È¦Í'=ëa÷ud}ÇüJý ªåRPÕ1òiZ£† ì*)bõ[Äh:ˆ~ÇËn·;a)bâ_­d@®åb@B‡ Â›ŒÃ2F4 <2F´ÇÒ0ðpA‡¢ƒûò(አ™s„º§ËvÏ2kGÌ&šqíšK1ÒXÀW‹Xýën¬«kD³AGEJ¸JZ«^Q‡ ;s…Ülç¦_|_±µ C(âÉ^ c¯HÃ(gÃ÷€QN‘ˆNöîMü‚Mp.HCbçìS£g!qz È5zí*´Š«}¯ÔÅýMsÈC3Ê”÷Uja®I„N0VzGíõN‰ªójA¨@× ‘/¶µKPèä#/•ÜÙÐ~ó‘Cm+L/RgÇáGä™FaEã½|W¶Íüí`•ŠŽJ;íGuö­[›};„¢ØwIÍèY$DõVâ±’“‘üÑè¬ÈæEωÓêé/½ÉUnàl®ç¹ÁWT±èÑ\¢DÞueötèsjuzŠz*vV fƒ²H¡'j¶Ê@VÔ¶UÍ‚P¸Zb£ÈðGÙ4Ò¸½ 6‰êBņ Êè¶ïðÒµ¹èì`¶ýÇ—ªüDOïT>‡4zzÿ£²I¡ÑÓûõ“xzÿãX ”õ?ÎCyüǧwƒ9…>Á3½Î]4¯ZŸF¹Ïô:…—uÅ ,ÅlŠô…ïØ–é±¢ûέÎOVÞèóݼT´F÷*5º¡ºE— ×­^ºnE׊Vò`5Œ"wVi4@¹+RøI8+R ß}êRmÖcÅÞ âG¤¡|犣\ÜòL¿Gb×]ØÙ`€M#rí Á¼ëÍ@ÙÏbŽ®PQŸôÑ(ñœØ|^¾G©ýÄf.øw)ËOƒP5Ÿë:°”ûÄfE¨û‰ 3Nl¢Ôyb³ïÉ ßÙ •6ùnV¦ø)ê8Ò•E5sš²éú·âpÓøiSdß;«wÙl†PáMèoÛx?Ž¡±{ò^!Ò‰C/ÃÎ@9sÖ£B gÕw^zò ÅoÙû댤ãØÝc.>ȈâØ-e&Ù 0–ÓœTÄiÕ ÑE9øÆéƒ»'~NF¹9}¡BKOØÈ ‘Á¤×³äãüWìh¬m ùSŠûÐÕŸ‘ñ—2ß2KÌÄjP€ŠîÙ•DuÇÝ_ñZxx–PÔcõ,aåö,Ác¹ñZÐ'¡±›1vúþPòðö @F„;{,¾?F9{P ëÃ=F"¼!òô2¿+B9Lyµô%=ó`FæqéA93g¨ÅÈ<˜‘yЛyÀê‹zP¬™ÇŠPîÌ£C(wæ¯èÈ<>:ó ¡?óÀWtg?Uwæ;Ù0Yòá²O¨¨·FíD¨çHCÖijq\G8í#×ó²£;ò³K¢«¬®ÄJO÷û"ÔùŽ@}·šÙ¯e|)G„Š/,5±Çˆ?Ò½–¾A(âÚ“a=!±OãcÕ(\æ¡ñA‰i>~í݇<€¸ówü%Ncné×ñ#êB±ùué•"µë9€,ŒE½½û`îKéÓ½ÙÔ‹LÝ= \J õn«Ú T`Gu¾â]OëDiUФƒá‹Ôç‹âåÆÇ:gN|¾ß0´Û¸(6+ ÈÙË ©ÎÀ¶üÍATP£”è!ߦué T‚úBÕ—VñïVp]W §ž–æ¦@·í0ó•C¥õ½\Q’“l ¦—RÛyó¸pà“ÐÐP·2P«@uuøÈ358ó¨éŽQ±U¾^ ¡ˆË!L¿ÇÈÉD’ ¨”Ñ+GØœ…pFOcï,ö½³P±wÂ>Jc£cý:¿8+Æ\ µ'ÏYQ.º^@cû,ó ÏÂØ> Å\ų0¶Ï³06s֋áþ‰WÔÖB$†m«c4ån0ÊYÇ€½ïÃ>³˜=ÿ-·éÇAДI{‡¿"ˆ7Y ¿*û!T`“!Þµ4`¬Ô=WÙfŠzŽlî’ðT“‡·KÎÁ’§{·Úž^8•e^åÇÄ©´s7aæàî˜+w³;¸›Iäánvš»™Dö3"Ý•¯žj»t_”l3 ˆK¶Y\rcxš¿ÿ'ŒEݽœgnˆºcîYÌå¨ôW#dIrYMJ•KÖöûå iL‘œ4ä:J£Hªd,Ò~¡ŽŒ…|Ý÷sA…v”t„аCM©líûºoÇ;”ë4#6}xEº!SKn¯G6p¨*¤ÁÜ£ûЦO{Ž¿s;&]¡H·ƒfœ„§.Õ-–}B€ ­}/ã¨çÄUæúìUÉçük¢kÙ '¨iä‰D‡ŠaTpŠÉª§UæÍWÌzþ‚ÿ{Îñ3]¡ÀÝ ·¾… 7hzåóšN|pΚ^ëÐiÃéSÌ3BE¶±?ŒÝ‚PfßÂ^µ’} +ôVŠ88::ÇOWìVæÝŠQ‰KCfÃÿ1µr©uýT÷4¹ÆirJíi23ÒdÔ4b¦É5N“qÓˆ-MnÊ‘&s&_›Ftš<i2j¹§É?&ã¦[šŒÇr¤É?&ŸM#Ö4¶>Ô4bM“<ØÓÊ€H‡oUÇ¡ µúö&+›¾¨G„ ù„Ò¨iD—ÁA äõê߯‰#TdkßÏæRSÿÓ ¡O˶ÊÂU&>^|E‚f…BÍÓwø¾›E-¤™R6meúT1s¨ÙØAa4M.ºÓªßVµñZµ†ê§úÀÓBMž*ÛäÚ‰/ù„¿÷'ï¿›‡¬oZf0)T›Üø©x¹, †…™(L¾€Õì§ÅËÞÕÃbKÙV; æÐ4uŠ2ʽ R‹4uJîzG%¸ÕæÐ@/”úOüåé§PÏ{“µ ‚¿U]Ž G¨ÀéÙS#”­°Sž…@Ù›åeKýªP¾ƒˆeU lòø°kÛTU¢¿Ôí­áqÞ÷$û¼ÛØÞðšýõ¤ÐBÄ3“L2ÉŠÚˆPT­Zë©Ñ3å(DtÛŠQ¾EÛ¥Ï꟢Œê,E*†³xÓV×ëVr„²Éñm'ÒyE(y¹ÉP—ô€¯uWŠ”d°šãßHo¨YëéFP£Ð­OG(ïÎ9j•ÎQL¡B§kÄV²6mÊs8*°/Fù¨ù;S©J±1,â5á;VéCÊe°‘5p­‹CÀ>%ölÌZ• 8»5É p1¸ãçA̯‚£¹8²¬…¦²‘±¨¸• IÅ+JV%ãA^²ÒñVòB”p#µÛ Ô.AÍ=fj—¡Ô.yQ}V„£ç·}iî9“¶Ã™´%¨¹ÇNÚÖ´%/zñJÀëÂõ\o·¯šlÈQ}¿ÝRq]¾)’ œGD×ò\‡åV¼ÇYˆäí»åue‹PžCpZòÈÛ™CVä<ì Z莼Cw 8dé;F‡,\ oëë@EYíhEP+ÄEœKyðjD(ï¾t«…MÉûãöã’2 pGwÂ\Ê]oð¶æÛÀÊ•þöâ"ã«ôž…ÞË-=Žp(%ÞÛuDÌæ¬) Ôý—åV_Ï-3zÚŠϦ©‚InÙ¥]Õç å[BQ»ãî¯nâ)y…PØŸÂé:Ëʼn:åeJ#ȵ·ÿmòX§2…¤T YN,‹ÙRÃjâ]¤âr%. ý\-\ÿÆs¯ÕÂ!û·ÝnbµOôjâùF³ŠÚ;ÔH$EñÍÔ*çWw™ŒDš¼d©~Ûå.(±µ±¶KÊt—¢ÿ”¦m×!”é8¤heù,¶‡¼E¨ÐRYȳyûɈï™ê ;*Ï¥ÐUPø ‚_ñ/îÓ5Á¿‘¨½(Ëû­(¾#=PE®VÙk¯k‰¯" × \˜Åô[ê!ð7–ºS3¬É§©¬•x¶†ywjª»Y LžðÉ,X Ä{Ô\…š |‡™îض¸ºò*˜ˆÏ]yÊÙõÉ0Êîú”„…£ëPv×g ]Ÿ¡n[èúdåìú\ñµî»Ž®O@9ºò¶‚wïÔJ‡žÂ‚¾mÛ’M_ ™ÖØRU²œÅs5 £¼›§oâªõç}¦PŒ /ƒ /\ éÊZ^)ô¿Ô}ax=´ØëxôÙë_ËwšH«kù¯û-ràMÕ#l>Rg¿(ÿVÃ4©ŒA–¦o)bd|-ßáÑ]Ä ®tìûOA2ƒ Ù÷Ÿ‚dè÷Ô=sñÐ&~ð¤5 âÏÞpÇðÑŸ¡…ß=ø30âû‘K!\²ÁfX|7Œ‹@fÆ(',ÊÁk‡‘!”ƒ ¦+¼€ ]ªË°ú¢þ…«Õô©º ([uYªªË€²k·¯¾ýÊõ¨R§ñ äeÀ:¼sæªNG‚÷“Öô«‘àýÔ¯¦“˜©~Ó¯ökÊݯ†ŸËݯ¶"”£_C¿ œ+ù€£«_­nñÓýûÊ£*æ„\ëºNÀAS*%I?m…µîTDÑÖÅØÈÈ¡Œ ºLûFŒ>|C¨ÇÁòo<*ÄU3e¥Éy¿ð.Æ×Š,z±é•ç. —6}L–#1§sž´P±1÷4¥ÀõÍ9¸íŠÞ¨Ù÷yÕkGõå(PWúEú÷f"jÉ3‚ÚîÌDàäNK›jÐ/$p;£œa¹ËØÒ¸ PwŽ5õÒ| ›«<{(3[s‘AÏà<ƒ v•Aßðµ|— zV#Tà’A7®u/ýp´“€ºƒÌ£õ˜Ôd­Ç$ ­Çp~ÜB©ha _nc’ó”Èñ7›‡>¿#BûE²Ÿ•u½*ñrm,ÿíæ>pr’á£üƒPþ}KôÆkx.ßMè¾z~…EqÞi&ig‚-4¬ƒ‡¶^ ¡³íIýÓBãÎVåaøà!«§HÙ^æ +°Öâà¡æDø=["¡ŸRr$DØ.üØâhû!&)WÆçmF(,ަb–´­lÔ¬ÊLJ@mãÐÇC¨Àõ é÷øü (×74èùEÅsõÛv|C`ø+fä¤\ÈöýÖÂèí:þîÆƒ°FGÞ#¹ ÞcäÝ7|ÉP”é‚>Ádo³öÉvQr†PÞ=jƒ¢,¹½cØ`D&æÍøÛð‡Àyãk…¶À¹Ø`s‚ °$ãÔoÓVê/ ‘½ïdÐU[9ÉÞ7Ò|ïñ${ßT!yZã;ÂÆ}aJí>Zp1SkâäÅÕU6·lj'ZlDН§"éñ;‰UÒQx§,¢IÅ«’`tÑ7V÷+w³éjåé‚P{ë=†Éšrì b.êBÙÍÉHzJ©#G(3U’sÕñœ!ÔÅ_BEMÒ£ ReÑÉÙ=mä °‡ b¹Ì†ïø±j2Fþ¦õ‚ŸžÜÉŒn¿ß` ¨å‰*{4ú\ç£ÂùfF_Í\ÿFÌ6<=“d8$öª>† és]Xa$Z¬M#üNÊ‹Ÿ×³tP¶4ÃzЀ²õ Öƒ”­Ýb=h@E×H’Ëöè™"‘+0”Û×c™§ä=äÛßöÈ·â—ƒºcxáJßâ·ö±Œ;„:]ksmSÞçñÖOyŒPþ­òƒø„ '‚ᦦC²o 0WOFøE‡ï: Pþø—Žhxzñ¥åÉ ädÿ‚‰:\•Õ®¢Ú‰èð%óþ¯Z2÷¯c©ã~ýío[iôÓP&K(äK N1jeÚòùWåÃüC¨ÓÉEå'J醖7¬„s&bn"?å&á'pòìçö‰ó#ýâ]SKj»mƒûµÜ ßQÍ1öMW¤êG];Eþºm*»RêŸSËd‰=¥.yâiÇÈ€}ÞÖ{„ÌÉÖãÚÂ,ô¬=(=gC"I{jÞ“»ÞÊÝIOý‹Pg sø ­\ _¥ŒMP¯Êß?ÿÃHñ þ—õªüûç_ðå×±øm±"”o?—š±J/PÁ9ª¹ÎQnsZp !D¦Ò-‰9NÆeÁ(¹šüݰ~Žëþ—ýðs}L”|ÛsœV[–-E4{(Ñ‘ˆLʙՌPTïi3gYÛ~RžàQ}9Ò+läõ`Õ¨[µ ²¡¸Ø¹eÒΠΙ'½üNö^W¦-z9H·ŠåWÚZAFLéš3)"­}Ê8Á(ïÖüJ’½W„òmJxÊN‹,@'û¬„Ý(Bd•õB‹Gñc/‡`CHd¥¤Õò+âÂz-'Œò@;Xs“$%¤ÓHtMHܹ¾LjH#“èÚæ¤›íf¾õó° ”Ù³'¤dCN ¶¢€²Rm—[ íj€2RûœcI%ño$·i«´¬KüôÔgßÏM²ç;møŽ@½ñÖöyàqGnBžÜ5B¹Ü¡\Gn›#Äå$ÏOÿN‚|(LõªMªWéd ¡êU#øw‚WCE1ÿt¾mÅ´úr¸î¦m,N p-ÄÇ?t:U¶¹/³ßÖc”¼ãߤÆJÄ ±Î‰aXñƒ‹–òþ©5ÓÄ3j‘a÷ت©Zøª¦4õŒóɾǨUŽ÷uÚN¡<Ͱ…è—::_¤ ÕI/Q@^fÊûyªx©‰±„>t¾Ä«ž…4p9Ѭ§×,¡á³×,G(ϹàÃØ?èR±\gˆéÇ­w0 «¯[³ø¤5Qò™˜r$EÆcæ{o’Vy“ B¹¼IjýôVZ4Uçß1o›1W#A_¯K¯àÑ‘35MÛa‰>wä@TNŸ;r¾–³#Ǹ–«#§-ñµBǦéZúz?ÐÀ´OÅ$\[k|*(VÅ¿q Ð£zõ†»8Pàk¶…TÖôå=Õ®b5ª€ri-‚Ò lmàVi(GíJvV„¢7w#7ný\µþ¦FU–Þ9ŒD`¹¾ Ž8?V,û!”w¬…ðiKU—ï°dý„P¾¡Ì®âÚuêÚî¿ñrfÍ5¿Ê²¦]T”IUwWÎÎ e¸% –4×é ù_2'±ˆÕ @1U×,جgÁ†¾¢§‚ $bé+z ÄMÐ=F_ŸÇޝaD(ï–6wt|ÑSÓÿÚÃØž:—zït.·¡N¯yÖQù¨-qZµ)µëø*£SÖí/n„ò.ÔfÕíQнvD(C‡?Mÿw¼Ã¨).ëù5ÌýöýVuïùÄFˆ'èûeͯJD–m¼cB9¼Îðéû}á¯`Å&V*Â8}{î²áÁÇ oK§ï Ìœ·S*)¢×Þé>Àüz›}t»;¤ò¬ã}#vÈY¡>÷Ôù,§”•IŠPŽNÇ/«à7:œ%ZÕ“§T¬éÛá,Ñboqúv:KÄ’çf ùZÑÅú\u°~½MÕÉT;`VŸ:ñÆ„BN“@9ÙÚﯩjUǧozåv@\(Q+84Ñ‹º6f>‰à¸ €B»(äa‡’e|Yò¡"œ-A_0ëÆEu'êc°¨Ôç(vQiá‹P*!#ÍYÁ†¯E]´_›P·6øî"«¢Gz¡#z@ ;RïQ¨UjýÔ¢#ãx¢:žËsÓÊe£DPžK ÆËóïKWí®!L깿Z9W9C¨{ŦC‡…"®¨Á†“5–Ac)bn^'ù™8¡ˆ¹ipæÄµÖ±f£eŽT«õ‹h»Ûi¯vïó ;û­õH§· è)¦qh£)}.}­«&þ¡Ú8JÕÆ#”c5ÙâºF(‡>×ú\€ îWrÝMý×SG4¸TP¬)}9‹ÊþqØý÷}ÚO9 C„ì{<ÝI—ï=ðtǪÆ×r8 ë= ‚[E‡x€F/êûÏ 6@nu°`½e»ë;®9BÝ•Åé^—©Þë}2Ðûl*@…]`,Ï}YèÂ. B—?^‹Ÿ>ºa?ïÚ¡=¾Öç¾7\òŠ8z×µF(zÛ°WëÞp=ª/‡x(cìírÚR ;ÔvÚ‚xû½zhA¤ã_œ¶v¢[M¹#׳âÙiËx®ÐtúU‘N3¶ªyPßlm?`Åù[»ÎMW~êÞP¡Ä oæ¤A(©º¨SŒôo{Þ*0,Bäýf6ñ·V£óSoôG*øä^dßßµþõ¯Žf R¯`ôžÙÜ6[y0›©Oýñ Þöé³YgÀhðreÀ¤Âþ c<*ìƒ.( Þ9J˜9˜Åj6„­{C˜š«ˆái5„ Cµb”çÒ)‚oÍEXÜug5a‘þÂ"¼íÀáI+Õ¢Elj«ùjÔ&QC(Ï¥ˆ ßR󽻣ҧ¦AôxG¥OMƒÈyG©O­ï¹}jÄNñPð¹°IÌv6}-òØÎf \-í£ÊÍÓàFr[_ñJ!s¾.ëNuUî~ÃÀTN—žôADùÛ5µª©keIK m]+Ÿ^ÁÓ#’á5Ÿ¾³oj„òìÕ$ee\ËwR$Õü }ëlxÔ’[]K¦apšù¼uEº,åYç®8Ó“dx©K×6*pÔ¥{X¿Âà^5š*áK ÃG‡#ØßÃðÁŸ[÷oÐ0zêßб{YÍ‹PêkÎR½jëê’Z‹K}ÑMŽ7.©ÑS[÷¦XÖA±Œ"m]£XÆp±ŒžÚº7Z_ǹ)4sóižª¶ýA„së:B&+Ý‚0†lñÄZ=W}h…œ®J5³–¥u³ÌBÉ߸®ÃhäÁ©a8Ú—GX£#çnµžõ½õšª×ÐèýT¯ÑqNôvÖkNê9¼‡|T[*OdzQºÝ½ ÷mhÁ/ —ìHøTs_ÇcÞT…r"šêï¯iãé‹P(–óË›¶ŽB*KûËž«)ÎE³ TˆœÊÁ+´Ë"ÜîðÓ#W8ˆ¬²U ȸ®øZØNÅ…ÙÚLk;²¡ˆågž—ßoÝ•°D§¾>¬L ­=Æ¿r-Òê˲*Ÿëyª»µ3`oɵø3EÄ™¼jòrÁ÷|{N.ÀBW’b—Gƒð$ŠÜ|÷CF‘“p¹„K}œ„Ëü \RDb»!6ÖÎEÓZ¶«&€üˆ“,?\ý\˜ÙÈbîlÇ¥}jÇÕmDŸÛq[„rµã£J Ql#ˆ)FP¡Ÿë²SjFoÚÖÃüÃ(ϲKO¼Ž,À'ýÑ ˆ2Ù߯8 aÔØÜüí}¼Ô¨~¼'ù=C¼wÍx°"šáµŸâlÆ£ˆfh4ãÉòhÆ£ßaЬWphý<$Þe_C(§´¦Uó{<õ6¤œÜTèÇ¥~Á‡Ó®Ž~"—2Ä.b sõóq1’×"”ç(Ts‹^¨º‰âL\}èxµ›óº®”R% ½´ök3óvåB!ñ@`\gë6” ØÊ¿SÉY¥JŽš÷äýds]=€r„/ïL§ˆÕ{$þCz«Òo›Iéãm“àBQß‹âwŽâ|(_¡B÷اé1öÑ…æRjáÙ­ÃÚ­åYZ’øÀ’YiQPÌ»)z@˜I>ÎvoYô€#7ù˜täKÑã»"”o•3v¹Õ£œA΋QÎqûYÎ Èâï‘°Õæ„ƒž_ּǥJ°] 'qëVWÏ/z¿ì‚’ ‡S°”»þMPžÓT*};EÞ÷4Œš…)RÃêtë PùPÃÎf;J‘ì7@o•º²p”ï것ÃôI}²ÃP‘›†ÏfŽ+ByXij`¤Ýq‘NªÉ™ÒËבåj³ÍÖ¹ÏÄŸÊ»(XVZÁRì)ý{h@‚‚å\ B¦q½BÅÝÜ5B…†‚e¥,«¸*2,+¤`‰Ÿëƒ ‡êŽ"dëµ€”á)2 8)Ä壸®;þcuÕ¹¬´Îe‹¯eé\VZç0€9 5ÑÅè…Æi+ (ò”‚¥Ä]Ëó¹êG莥ôz …µIRXx×e…P”L™ŒNât«+BÝ­`l÷„ᘑŽB±4Y`m¢&õáZDÝ£úz½‹¨û©Qž¹'Ëy¸ïÉi[*ÔÍí”»iœç´ÿE¨3­‹{ XºV#B]Íxv§ºXr7ÕÛ~{îbL·ŒUPžÓ@FÕЈÕ œ‘a|Î{Lðúc®&uZ+ :Rý±š¬û®ÀdŠ_Ëw}CõˆPý\  ¨èI#RE¬…ÏÚ”sIY\Çð¶?–]š`å´Å`D§QÈ®rý“4`S;: ;ÒöíïWÜ-Q‰d"¶ž(wõobByFag_'Š|Î’.f…RžP&§…~èç5F(SX>×Âòm×r„ ñ·]ãòQù„PgÊS§O·mž¾ËÂG„ú`B‰x˜½~½OS÷£•P† r>³61PT—c (â@!Pz5!ˆbðWÕ¸ÔvÕnÛš¤ ~0¥¨§³5•:†Ésùh¼ûŒ uדu›¾¼—³Î}(xi”³£&¢‡M‹©Õ7z?0u¾Ü@9˜:lcå»xl+G¨À%®K…[¢sOþr†PžÃC–ÁÒêù©Øm……Îó-áf5_÷-«ƒMÙ œPòVß1|èÙF=–V@¡ƒ¾¤-~³ú¼½È%Xž}3™zC(ï¦#·™Wžêñ²ú‰+µwÕÄÇc$"£®ò•Ï"®«“¡BÔ‰ZSy9–ŒÕ%BE÷̹s¼žºlÎ7dJ¢È0`¬Y馺„ Ù#VJ׬ɷH»¬F(Ï )zÎâljÚ¡ÌÀ£‚;“Ò‘Ó¨ÀŠVµl\³®É*´ŽùÙÚ)ûæ?„ŠÎc>ðŲu­–æ„]Ù¬¨ü¥÷Çy¿'b~ÁnWhqk—˜¯¿ …– œ÷ D(ª²2—¦A¨%t5IÖ”yG"A¨Rß±oªbW¬Ð¨ÕÂTX.ŽùÛȲ/~zuP†“&BÖ ?˜çá:—ªå‰ wÇ£ï‘G|Õ—cÆ›|É0ì à Ƽâ|Ä_É tTôÑ¿îЯãô™fŽa!:ëCÕOl M?C`°èÖPt /Ô9…¤Ž,ê0Â>ï¿\ŠÑND½4,Õ ¢sß¹Tó ʺT3Œ²Ø ×ëe->ÃÖæwç´}ßw €ª*P1ïYêiH—¯Eߌl!¾ÕÜ.;Ìí4 y#½ëµÖß1¼Ya_(I" ?ºå“/4¢Û)´ÚLZ œ Jô‚²ª­e5“f¡Œ_[êõïë;‰#D›XrÕêùûj±IÒÌœàuß mvÄx;5BùO«=7òݾu¶È+ )çÓ„ïˆ\yòz/zKС”À"Ǫ\eYý{~ÇØ¤{¶›ÎÃ=—F‡yØÃƒZ&P7¢Ä%—Äu.)ì¹$vä’÷?´©¹¸ÿ!÷?éIØ3;œÀHDÖìÕ&Æ r6AlÏq œ–o$»ûQ?}ê8#9› }ž²úœˆ€Õ;"¾+}ŽÏòV;eD£Ðµ*‰IÒü¡g£gŠ‘ÈôœiYkŠPOÂÞ  Ý/P¾³æ=2°¿4ÀSÖWówëñµ, ð›jÖ¨àÑdVOŨ[ í &ÕI5'ÂЭ:ÉÊ®:ÉÊ®:IÊ®:‰¯Zž>ƒ]Qñ Ï¥wwDÅ3Üq» |cî¹·Ðn³¼+Âs%Ž6y°¦¨ÔÀ‹ïÿvhwhÎ&z¹Ì&GxÇÈsèIB˪FY[Vá#ÏÁèùé½6"Î;Âj¹mõ¯–Í7‡›D¶ƒ+Pôù6±ë]8Ž~QàÔw…5: ÜÕbxz‡îì9s"» îA´¨Ø™_Ô#‘8ó‹ð§!6•)¿ëW”8ò‹c ¡mö!l/~Y1§ñ°bM_ˆ'õ°b@wG£¬N5pÇ›½ø#û®’{qÈ«K9¶Ú5Ê,”!»{à¹|§Òä*ãàÙ„½o|ïŠUï­oŠØô€|-ߦ'Š8¸(ý¼µô´4è^§Òìµq`“žÎØ&Y eQúùŒ~z›Ò¯ðsa¥0ïëJ—mÁÏej‡âªä§~8t‰ëêƒG¹»G„²w;3„²u;¯°½ÇÑÅÒêÐZ¤HkQ n[ŒVw¤HÝQ b—º#/(BÙèg#lW._j-Á«QÄr°Uô³ô•\UƒÐÒ$~ª ‰î"Ö_=^ qëša±<  œ\ ™î¦Ác½¶?˜`˜šõ?­Ì¾Ôx½ðù7#¹ T¾©šiÁá –„·R·îmg⇵*ÀY¼Jgñ:Æg†P([Šyò¹J>ÌøZÑ%§&ç—¼cÕökP([¦ÎÈâZï¾j×£ÌÙ²¼Ì{üŽé3#õóQœ3;<ª/,y¢ØS›}¦-1ìÔ~Ð…”/Ï~¾B`WQhXùò®¦À#Àw¥-€š¢ùUÝxy¶àQ'•Þ¨y¥Èï]õ5MzI§ÄXIín–+Óê0©Ý,W¦Õ1Êl–+ÓêeÖ*Èj éØÔ¨ÚPë°[%œ¼—Cª>‘U(;}\U’ÈCŠe­ä ´’Ê·£ÄW¼ ˆUQ™#”oD1Ð]֨੻LOÝe mêÌ £"ƒÒ_µÐ¾@¡ý­Ö£<½ÎNúÏŠQþƒØÃ1±Ç{ýŤ®¹“}0ª±+Ù7Õ¡ˆ59º*Tb·«9Vï•:ç—Zå<Ï>WeúFÕsÅÀºÊëyö¶ùÁœð\å$hˆ¨à²+¼õZ(•û¹à¹BûÊTJ5K "GÒC–=ÏÚØ¢þZ¸Öõijǭ*­žw%ÿÌjæÜ8#JGIƒsibO ÚÀKO–çu¨0ʘØ÷ßzh'ZbT`( Ì}S©®t ϨÉ;ɼ˜2üôÑ‘ÐÔ¶óâßæ®ì9BÅæÒSÆ=•\æZ½±XjX{æj™"Ž­]TòÝÃŒ8¥@ ¶MRȶE¨ ×@)p4ãy5gå?v÷¯Ø6>¥­¥QÁ¥Ú_®¨Ð\2“Y5„Šl(ø;ˆg8ñÈõKÄ_¬Ÿ ¡ð‰GÕêeÈÚfý®Ù¯QéUˆh¨Í·jÆ£ú:O°®~yÞd?úÃÃêy¶ÁNæ®ÆŒ~?mƒa—Xh^m{qŒÿP óo)g.KÖà÷ô ¬¨s ;E¥~Ýü÷Eì´Tá~Æ=».©IÕg¤o Ãv'Õ.b.Ù=4{ø{zÉE\}Ï­³ØÜ>»Äÿ»¦‹ {+†&ÇoJ^ˆº£~ó"oÛb—YÃæs¡“ˆÓû7QE‚õ¹+C—{¿8}óIüÛ†P¸¸K_ÊV«a[ Ö”ø´ÅÉö*ƒ¨#¦ÎJ˜ktÞ˜ˆÇ¦¡BKºžÁ*E†SÒôhD(b,\HŽP>v©UNŒ½›©áOy^µû^Ç»mn éÂB£‚{6—õØ ”ÛN U4@韀PŽõß’A¶Ÿ ºº'þ *4h¯IÑѪƨèœaÚþi.íß}Pñ* ÀÉ¿â)Þí†P˜®©VbÞãÌöE¨ô`• [ÂsF?ã41<ª/ƒN>“:ùÀB³š>ÔˆPf|©€ÏÊ7 ÆC'_£›šžø‘S 킲I¡ £,Rh ç¬QEÄÒ©–Ç3ˆ¯¡ˆÁ³I‰¯õ1–ò+ˆk”EÄxßøŽ¡¹‹}Èø„PVc†ïø1¦JÄxee±R'üŽéãÐáÚHâæÔÃ;¦—Þ›[5¾†Ì9ås üCܱj<äs4Ê·ÔÙðwø6SVÙg!B¸ãÝd´Ì5k‡Ó¹TlyÏ'·NDµ+(&y5A°ï“§uk¥¹=ëv¹î³€™óîŸîSâk=}ÞÙwnègZ*2í¤Ì$BÝÌ«”ƒûð-ÙøF¨ä"@³3“²¡¤Ý÷Û Tj3€ÿÑ·p/q0ÕæEtD•pö±ïû™eóŠP6óÕɧQ¶õë¸càZ¿Æ Ê*åH1Ê·°!ü~àҞʰwg÷zâµW±y¬èyo—ªC»’ª{öÂuPyõð? b«>‹±Ïég¡B³Øy¹ÁãßTKòJË_×Å0¬sPx®´ÿ•L?W|—˜<%‚(›9ÌœÔiö¥×œÔ™X”ÕZ%Ö.([bmPÉVïäkGqïÕøÃîO <ËŸ6áu[OÃwÜëiØ*:BpÜBädqø·©Y—U=B‘K zÏíÈtõ†}; 6aÂÝ&väÀ¿Ï dd0Õú¹+ó-;º£¼ t&Í롬Isˆ¿‚Б4׬ @¶„ ¬&Aä™=¿Pìl]¹ l|èöí v´® lÅ× ŒNÊÚ¢^ ;Óf JxX£ˆ)ž8ûý<$ígê÷0 ‹ªé’½<€é};|9T^ZàUy¡çê`¥ …ÞÃÐ NÔÕüùl­ ðCò4®Qó¾húeK„²4PÈ¡@Ù¹P‡s«@÷Žrhƒ)í0彊'LÁJWô†¢bv+ÄÔf…Ð\ÌUµÀÌALA@©RÝÀò_Å>»½F¡ØW_k(¶_µ|ðÃ+¿d¾Åú^TS  ¢¥Ûׯß|GŨ;}ŸªR˜ðKARHÁŒùçZgõõo5àÔSÖŠ§«àk.û¬õzá]v ~™õX)ƒì¢k>ä,¤´G(b6Î[+8GžYVEm#l˜ˆùç_Ø”$WVð©€çòŸ®¾õ¥ô;!Ö¶,€ Ñ~,«¿u!0€kCÛWÝ»ÃwDÇùíIËq…VV[*ÿ ® ª‘ªÉ'I!A¨È€jwT…P1ng7¬z6~Fm<Þi©üDMRW¡R³sS­ñØRùiÊFp̳Á O °›è¼Šf¶jYWxÍàf{ÆÁõû-ơΔ½¬ÞT*Í^mü qpÚ-žÊz…˜'²kI/äcö é»s;OP”5D1Êr‚qÊ„P(N©Ôé•2þáâM u7þ“¿šJPÝÄôDDœÚÇï½ÕP˜Œ;ƒú`‰{‘“%>A”¥ÓŒLWürä¯À ]£ÌîëìÈUÄ/›üþnÜPã;ÉüIJæg3B…6É|ˆSNëeƒdþ´À =~ÝóW‡dþTÒiÃïhÉ_‰à£R›D,l±]"–k‰X²4 OÇòÌ'N®Nœ°É`ÆG´|üCñµÈpåËgíž½“GkÖi”ÝÖP]}T ï ÔÕì YUÁÚ-ãPwe»R%4꺭›ê]ÂHÄOÅ­dJ?ßl@(bèí(Úµe?KÂüJ¬úbÖÿzµH#åÄû:±Éu£,ëD]ÃÖ§vQ‚ú³B¶2y9{/([ïã°b”‘¨¼Ÿì8BaÝ UVæš c¯š³=äþ+窤-Q\„襲áÓ(b&îÔ#ì­Æ³/ÐK|§“0ÌU›V#˜ŸhThGIšúމæ€HIlýÓN%*/¹Ñ ]x­;Öu%ìµIú¦WùÑ_Óðu›ʤ*ÈÏn8ÑíLÝp°b¦V35~’±½Ôs‘±7ØaRë×®ësìSb7Ø“ÅH5ö©ï²áÓó>u–,'ýôWÙûØé ½Ÿ—Aó¢/YKÙ¯ŠØ¾ì§…«¯Cóí½É/k4ÖD”넦…|y;K÷ãE¨ŸDU<Ã(u"VÇ%ËlD¨@gdOí«æ[U]yA…—YŽj‘o™8šÂY-Egoƒõ‰ž_‘­ß‡Ö'uW®}ØNœì´µŒ™`MckE!õß‘ØEUÄ¿­Q©‚ÙÐ!I^¯é²ôõPMJV_£ˆÑ^K5'„òm"!jæ;Õ1;û­É˳w°ïH^Ä,ÇÃAŽÞÑ·Æ&ÒÖ·Êb±Yp=^ëé':!”y嘆‘ÂH„÷HAGµH¯Š¼"·^G(»^C(ßüŽÍq­Øf€¶ÛX e5@)B3þ‡¢F FrPä7Ú»6ºBa³Q½’WûŒ1ß\q„:¸ò¹öþ™é˜·aÊDZœR ’Zòï÷Ïõ°$­jeÅ[uÍog„"׆¬Z7dm*â#ÞsOS6ÖÝÚ})éýûŸ:p+ qxÜ‹Ýe6 Ý†qÀ¨À&iÅåÙn(Ð ±Ø›y¾QeoªQ6ñ%žÁ;úæxBìÛÝ4Á®(r©ší‘è8lÛ{Xñµü‹ ÌËóÆËeª iàB[ê~Tü‰#¥cH§iú>ñ}`¡ˆ¥_3¸cø\¿Ô 0®G žœz{¦Z÷geåû‡µyˆ@E.««ice±ºZW='"«‰Ü­(|¡ØÕX·Õð\&<­²¾AoñRkÃ@}Ôw¦ÒŒªáß¶Ûˆž Ñu;I£ú¡Xp ~Hˆ¥~HòSCýWý°Ôk!!·]V \4bT`$ÚSÜkeŠ…C-¨Y M6WÓBÅù¡|Ü¥´ïy=‹?sÙ͵4*°ZÅÀÓμì¢6a5qî8ór„Ü Ä.­&´TtQ ΊJXéVMÝ Þ3³®ÉææL6›“Í?œl&$¶&›‹#ÙL0›êêÏ«Õ,,²iF(!Ü#%)i‚ØTÆ”ô¡"kJºB¨Ø–Ff#B%Ö42G¨ÔšEfxT_׬³|¦¼Ï¡š¡afk3¹^ÀX èWë9ªí¶¨×©«>E .âJ¥2ê¨ÔºêtbÕQ9â¿\«ŽŽæ|kŒ¼ŸËõµ<«WA-½ àZÄjÆ[¿D™ˆ›õ°Ù­JJñµÌN1‡°%ñ}çÉv€;.”Ž;üÀq²­3Füàî«qXFÒCJ“ø¡Ë2’+)Mròƒ –‘T1ˆÚ³ib›àéz‡*ñãg³œÒ« Ùý–ê‘›¯€sQ1Þ}š¡Œ97¹ÓPŒò-Lh%¾“i wnÄü1é–@¼º%…Y¼œç&•"ç”Ò„]-ð,×BfÏE\fÏP Íp¢§¦A<œ‡¦‡<ãEŒ›G“ wÙ®ºuÝ9½µô¨ÆNyUX¥/Ü¥õ¦Zx†Q6®è‘xøÈ=¦Ü3“Ø&„"–æ/ÈÍ“ }HA¿1¾_à»ðõhŸ‚öb)þíS$|YTÖÙX0­](ßÒüÅš¡‚Ó7àt*Èš•æøZ!VŽTZ#tìJÌädØüùO²3µ ån36 »c™@ùNÔOE†!1“öù¥YÉäax‰­R¹²J(—U*§Í…±J¥åÛîøQ_; w„&ü‹,F™ ö<‚è-.ÙÖUëŒ! ï3ZÉMïMJÛ í²€Â/êZ²1ªgôr­Kûúþô¿¾ÈÚ律0¹+‰é68–I…3ŽP¡®*v“œÑc6‹Ø}À¨Èb@Ëõs¥Vþì\´W¹š^Ë8­œ³¡à´€( °w>eãF¿›  @ï¸Ì¶Z·´Ê·Ôô:=lè/ºq°ÊE&÷ ÕÅ'¶öœ© m(ä ˆëZ3SèzÆ—ºîûT•½Œ2ÿP#y ê™õÃgû¶ åÛ[I%-H}¡(¶VuÎú‰Çé*Ó¹¤fe¨©D¦¬Õ›ì2B5FùÆ.£òNÏ ±K`A¨ðÒ9¢þ!\)D¢ÑÙpú¬¼Ëƒ&BÅ–Ê;ðÿ• Ê{•CåýÃùr¯ÔX[<*ïzT_f =­Mâ—S¶wDh¸.`2=¤åjɽŒ¯º,Á¾¢.aê 2þ?êHË Íæœ-ðÅžÝyywÚV(‹6ÅÊE$&—‰”ž¶-ÿ–°ľK)‚Áñ=öoV>Ø»1ãž`)ßÃkGó¨ß1yJ©r€´êÛ¡ÎV_ðÜ+\ÒõoB¨C‰]©YÉùÕŠ³Ù ÜÆ&Z‰}OÃÐlšÖIÇû¦$áï87Íš}g„ò2ºòˆ¿v £ (” .ÔÏñëšíÍ © PwboUÿÄ‹0¶tøé£#…ŸC¾Dý–îGê$ö*ްlîùÎýÔÁbŸ pq•˜R‘åb/bï7B!b¯4–ó~nÛœ.Š ­Gõe4¯buË“µñÈ×ßf…x;±™WHEÎIŸ3‘w¦IW&+âcÜûvN]EbãcÈò̯`é5ƒ;d(lÞ™ Á~AY{FÙzZt¾ ñ/ÝP¨æ1v“xO5u’'ï¸êßvîØm[~eDUb’„.fÊaT#Gl(5*vdÀjéOb§‚©¾VâR0…~5rŠJT4· Š$½mÐþeí\±·rº"éËŒújE(“õÆ0‹³û‡!”oBmü† .>7ò驈ٶVB…Ôÿ »²¥iQ%øJÝ‚Ú^Îý?3 ¶Ú¸/qžþ€Z*0ßu†úÙµderEßP™MR1ÈËEÏîîÃÚ\s"¥¨êé-­z¶zû¬®2#Õ±h„ä0ða› ß"f ‡ìE÷ï:¹ÎÔN±«}ÏÙ£9¹&öW7^®ec¦€P‡Ø7ÚîŽ Û6iì"zìÅ~Œnõ¼È<ľ1ì˜ ô)NöqÇ„½0¢ÎÖ}D nçW‡5áߧǨßáåEþsv\ âÃÊ‹“/zÞú‚ë®bßì½÷T5¯äÊ‘Î%å#”òç»rï ½–aèyó-Ë¡°D¸ymýd£’{”ÕQêò?š¥d*š”ø<'_â¬êÀVð¶®yŽa™·^ŸWQ`ç¦HÞ,¬ÖÐÅMõך¹ÔìÒU‹>ήÃ(«A’¾Vd©°ì ú‡ó'JPØ Aì¡K½cf±ÀÐAì!Ã|58Y’×Û:_½Ï†b”gö^×Ü'‚ÙC&îÓˆP6îÓºb±y¯«H‡¼ˆÃ{½dl@¨#]H´ÈÊÎ3®Êí«Pô2"$ƒ>ȺÅn¸Â¸y]9¡G^Ô<½ï.ì9‡_ûQ‡Q,±‹—õ§ðô¡í¹¤­pJÉ+´øV eÕÐI"¯+´k–Ôü·ýê&°µŸCù>dSeÛª4«É¥“¦¹f,ÆÓ–ÀÜ$yݶ Ùi:qÄ L¿Õkº ×ûþ+ž«¿h‹ŸË·0k`rš`‡M̬i0³†¼ÞB)hMdìpX ï·½>$"x«Vi¶aŸß‡UhsŸTÃe°Ë‘7±¹›î¿#|o;³YF¬ÜñáR¢v€o]‰k1ýôÁcþUbGý&³—I¹² {Îñáž1L¯¡ÐÔ^_*íkxö­’D¿‰›/î~ÚʧO³ªý\á?Þã¡­/wôM®sNž¼?Î9yý\sA Ü-ô#§»Åeu·¸ lÞ úém,%â sÌÄ{Ý#ƒ÷ÏÞ?ñl¼†xÿÄ{?]]ÎÉü^IÏsy„—*Þ&H¼êé.âŽPF¶è)N<útÙV¿ÐWã2ÃûòŸ(5c'b¾ LìfÖ@FyæW¤¶õˆ¯E.(u­>.òuXŠšP™D1„BŽM ±2Õów¨‡ y8ƒœÆ<üf>ãŠP!VGSþòñ¯¯ò:É E†:ÊíÌ»â‡P‘¦¦êÔ<æ}ßrŽßêÁ`É´&X=4¿®+G|K˜‰~ÀæR©ZkJ”a…±:Iê.é7 Ô•È4UQ·E6 Ô,èùyÀ×ã¦ôÎ rŒ¼#›¬K#5[´ Ç(ß`y ¾Ç!^8BPh˜ÏA‹— l†Pž™œ=˜xz0Çô`âý=_Ë:Yµ\ƒšˆ(Ï6ª¥ILÔIP+µËVöu/I•Z¿ø‚"¦L††ŠÈ (jiÒë`áfWxkÒ'3FYšôºYIÈûVÅÇí÷‘}BQ›¾,|’Ä{VÞs]yA‡š;½#SdÊ.§‘-G(L°Ó€8›ùZŒujjë:±¢³¹C(jtu85¡6z‡ò·”o^ëkÀ([+ DÄaj(­5*´ª ŸúÅÑšLúÅFy6kMµó;ï@Ù«+B|ßÅÙôµükpwÔ¸‚a”gó!ƒôÐÿ<È[û%y+Nt,Šh’’cfàLUUâÀj'Å ~`™ìüMZ8Õ0MòÒh‘¥ ÝhÔ™]é|®ªâ~JØ3ýà,êh†Ä~Œ6ßjecНu$ʇ™2¯“š¥UÜ!ƒnå(Ó!I+”±…Ò3 ç€2µPÄyÌ“_ ¾µ¿U•µTòÛ¶&é2bØuˆcÿ>ÄË_ùx…yh¢EuHEvR®y­t…ˆïìUë’/™ªÏkŒ²’©àð^†Nd©P"õƒ>¸Ö›.ΆÉ2( ¼/È=8T}z+rz oÓ¿•Ò(Fñ/G(jvIÌe(ßà8÷9Ž- £6ÄaA‚aì®(âV `eP `H-€ /£Z@PvµŒ²ª¬˜† $ ®Ã{ƒb@@o‰b/z±n² ¡Ì‡7‡7G(ú“wÝ—ZÞu)qoðyÔ¡Ä=pÅþ”QÉhÍ™®KÔ¢d4”ýÁT„ë¬À¤(û‰oªÙ7ÇLÝP¬èUª…@\;ÝIá»Þ¿œC¢ŒxÄN•Äb¯gŠD Ž xN'y.Û¡Ã×2N`obÛìñµ¨I½cm[ `e1C_ *Έûkê«éÿñó8n/“ð\‘{ò£ì“BÙ'/8BÙ'/Bùµ]2os#ºü0‰Ìcl™êæ“ðýà@…^D'Yüãå(ÌYÊÇ(b¼c;cŸ„ÞC- ÓÆuTCzæôp·Þ‹ËµÈµ¬›kë½µêÐþŽu¨Ã*I§üAÁ6$—=ú¤Sñ8²NLÄ=´v}(žv¿•ýêì dªi³sJbž¬øZô²©ð„-âh2„Bi…ÜyeY~ûŒ/Ð_Ý×<µw¤N›5o)%ÿ£Š¬Š±ŸWÓVô™ ›ÅÊ5Jõ¡9kó%eåÙ¸A$#"®iÞ¾Ç(ë¼=œ0á]ûûª‚®Çë>q–úehXÄ FyFo 9÷¶"ÔÓA£OÙ©¨(ú`\1Ÿ‚}‘zM¼,ý;{Ϊö/X«Œ«x¢F(b“4…àã’4Ý@™‡ ý±K¡¯שmÛ¯zzÄQ5¹lcžUˆ¬}K–âtÑåùÏûŠ½Ù½Œ~ÞNcJH*ßÕäJëëClÃéJ@ß"+utÅ·Ù:Œ²¹ô+¾ãaï–¾²8'Þ•<±EÍDïŒ} ñ©Åu‰™`Ý'I+ ŽPk´ Y£äNû7Ž1g6÷±PD(ß&¬ Hdº|™Ò–:õrTžëÜMn’¹ÙnÛ³"Ôs–[JCµf[|‚g¹y¿cÊñÃûþ×J9¾Vèì:C!k¿ýÑÖÌð ß|RýäÏ£õÇÒ¥Ë×¹¯Ê{("4ì+â/ž·…ÌÀ üêò©/R],ÿD/5q”n“@Ašü‰n"½Y&qåwu6ú¹®’#ÎO_$º0úA…«ô$§@ý–|Xþ«ꪛ Æ D¸ºmE‚P‡nÂa±Ýq2g Õ¢ßê ëSïGLÂÛ*þ+¾ØÛ¦dÊë$z¹Ø5À4$ÑÛÁ®ùJAa¨…›"•ʆ2…`”¾\JeãåZ¥2íI±ÇêS© *x€òŸl˜]©lQC€ l;\ë}9an$ÕXßÑ{x„•9x„­+x„QDþ zI&o’ø ñ%O'ž\;ñ ó6#”‡g9Õœy͹ÜJ„Â#¹r8+·j.XÑ”\ˆÞû¾ª®µ}+ž  ü“–%«ý׎çuÐk‘×ÿQÑYbtv(õo¥€c§»o¹`1*Œö[9Ê2±.éà‡·¥¡Å[jBÞR”†.o©Z?}hUû;\(ý¸\@KÒC;ôˆ¿h䎿0Êú×¾w!óLÅÑõ Bmˆ¢7¿ÖÅÅÊì»Ë2„"æStŠ*õßöjs;A•ú6=&O«¾!ÿ}l:YMrÿÒZrÔwxÉ]>Ï…j™pX‰ƒv›X7UE0j¿V“ös%¢Ñ¡a?S™áw­*x\žË ösÖ™´ïýƒzǨðR•áPò©f­ÔçèÐiÝì}_[¾Vt!fª*x#¤¡loõu4òäè…ÜçÄÅXZ,¾¥êÿܸ[" @ OÃŒ’:R|Rn#XIÝžMñˆMMð±ùÔ¶Äô!õ]â1ØìPÌ×}Ú.”ŽúW™÷$;äVsq`•?Xˆá…"^]lº:åÓ€PžÕz žëc¶^šóáW“¢±Qÿã¶^Â×"§­¶N¯êDäD?½UDvÍ9±w ¼Ìf² Q3 fÒÀpŸÒæ4x[+£§1 <ç/¿và9%ž!ˆ ìmµÝ1…!”1Ùa"Ùã3ïÉN-Û 5BYÒE¤ˆ˜y{AJ’OW $ÓÀ·J)—cªkÄÁÕ˜:Vhyܲ¤ ‘Go¤ÅÅ5"Ôñ¥ÉÙDE‘Ñ=¯_;¸Xûסh’¬ßr}|ö™\)h_ZðqÉÛ€ØÅV¡÷&WÏÖ’#”¹,:Ž ´F×½,š. žBÛ<íõša}aeÍ{‹îŸ§wBŸ‰À ‰@è9CH¡ï&éÏNêET=YdÃ(“ð?; QõLè°G#Í̇øÞ!€NCêýŽALŽ†Î‰f†þs/Ô6ý+ô$áÝ †¹_ÖB‰]Ó“„g*À(> C§(¾þ…®’4÷™\r˜¯3¹4ü8ÏHœÂÿ°L\ʳ ­ÁŠÆf›¡5H¯>/§ÐÚåZÄ8Ã,:ø?ÖoHÃ6ФÿØÚÜRl†õ PÞ°‡å¿ªKªX¡ÈƒÀ Ý«&KÆ ±ˆÆ¶]|a²GÊ·æfcè‡ÜS"ˆŠBlåÛ’"E‚%Œ]ls1®°~ÆQ[Ôlzw¼éÊô ÞªïG\uÃæã[wPx«‹XB×öZɧ@ EâŽ&á-ý\á-AÁ}Ïïôó±÷=Å ÅùÝj@Æ…¯~"çD›þ…"§x(¼¯“"eÚå@‚º Eõ.¹ìcÿ1òìâà§BDÓ£¥n²DÔñVµ¸}˜€¢iÂlû2ÙMf÷’ŽZ9Qàm åÝè®_u¦IT^åJAÂÇ”Ÿ¿L©PkÙVK‰ÿ²Êôò3ûõ_Îì·BÙ,L?Wè6£†çú8LŒ3ˆýWä(»k[ÿÙwòã|ôß/·`±ºãûýŒ™“° ?>–¸Ã&a=6 óßž¹ ‚sêäóowwÁ9xˆ¥cœSû—í* Y¹¾uÙúŒú}Q»ñ’lŒ¨_ûí»#`Xëc2ÉE—}$Ú`M¼‹.û tÙ1Ê3ŽAŠëþ;°8Œ7øZÔ¬¸ž,mP¾Qq½YÚ £ó´}?èõÞÚ†EÏÕü~Cû…÷…pöxÚ¤ÂG4‘§=Þ EÌ(ó!ŦD…*x¶UÛŒ~.ßZ½ƒ59õ{ô*¼êVź–&¾ÆrmÀà×G¢zúäƒÓª˜ÓiQJ“#þü{’¼§Züùo®Šèõgp-yÇßüëS„¢¸5ª4°Æ>‹Ç¸ÇwôQ9Ôôýq÷E¨àhYä07"BµP’€Š¼¢áŠt;.Zý±Á[}­ÃïÞ9”»¹ Obú)¨(çï4­E{y6 ؃Íèi¤‡Ñ}Ïs £AÍdž´†at8g<Ï=ŒŽŸË>Œ>"”e}„at@Ùilø´ÒØ8~úÈfý¬rMß#®\r'ß#qMàl²b½ï=ÍÜ”äÿùº²e U$øK§UÀ~¼ï33Ÿà®ÐîkÌ×H¡åçõd¨EUV¦Üã—e„B|]Èp—òcKxRÀ¨’ k|/jª7Ô‹ZÆMC“ ”‡-ÏáÁúRu{Àµîöq¦Á7Ÿå’?˜‘ W+ã£|” dù­uiöÐì”±¬ªuša~±g^N¤•|[cÓ݇3#fâ…ïFÌ 6b&Hò͈Ù|¡-VÓù@˜9_{£Êb”g3:ƒoè¦'f—£±ïËFÏ ¬ÈxGÉeÞ6Vd<ˆPèæ£€å)2¾ÝQgÔˆï9ï¸`”õŽiÚìh×ßÊìÇÛ¬IÛ¼I~pÇàA’ÒŠSãœÎE­å]"}"ëYÎ Œziýíí£-FORÙ:wUQlø¹ÈybÈôî×õ¿:ËÆ£èA¹4­¨<†Ím®Å^ˆ:‰4*ñs…¬-†;§?¬˜ˆTöæuAù6}W3£©«¾†í€²ÔÔ8Á–»OÃ2ÖëÖ¦|114Ï:M ͨ†©E3ŠÁ¼„ ºØ¡]¥Ö¯¹˜£r¬WŒ²(2irÒÅ^ònr5Ñ(»1¯:ɘo(øX­}VÑC <—µ€§¼Ûê y$•Ÿm’ë•)°µ™k»'û °YîòÓî‰`uGOÒ5úv˜WnΚ¹Ÿd4ÇK¡–•×#ByX< vQ±‰vHñµ|ó=žu–5¶"ƒ·Pgÿ&‘‡Š"®r  B'­ÔÜ1tu «„Öl“âZ@¶ + êó´Žäe±Ørø)u3!@r`/ÄLsæ£ô½žÑìÄr Îê2{V3s,6zÀ¬ý‘†fMÌBC‡XÀ&àÌG­Y|$5C˜UùTGz¼ØÇQ«ìA4Œ0—QQ%ÌsväÂÙÝé3ËGXð"TXj?×C²‘`¨7ÉÆ¡ì’ BÙ%ñµì’¡ì’+BÑ×úõ¹’ŸÌšªWÍe€b#Íe„9Ú%y×\P#͸O‰M]T†wh£2LØÔ!R¤ÛÿÒ6Ê¢”#”n—ÄrsJ, Ð4(K»ä(4 PÌ¢2q|­Ð"2,Ö¡¾ï{G®„}­_ªb^Уu)3cºü¨ûQ“ƒ ¶s½ïª…VÿFÄøysï…jè9Ý{!J ½G•h¯äs9T|ë´Ü Îªm –¹é|X êzö*Q#–ß‘ØÚ `½}×Zhª£X¸êÑLÜ£Œ„ÄÑL<ñ ÊÒL<–+F¡È\ð)DÖ#T`ÑVAS@ϸ„ñ¢ÎÖ8ˆ1C戆&0r#v±)‰–£ùws,HÎ+Î-éªR£B l˜«u\´:9ÙCG“ DîQß.IÛ ”oÚûw»7ݸÉ÷ íý€ Lwü²i¢iîÀYPäÝ–÷Ø_éÊM” ±¦+Ã3A Oòµ7È;B³A|¥7_qؾžÕùCî Ä9ˆ‰dr ™–t*’FÌÀsù÷Æ+Û–¨¸kEV#b”×UµAuÃgddˆŠÄÕÎ7´m¾ä Bg½ª'¥<ó­´µEl\ ˆ¿Ä™å7cOž,-Hµ*áÝÌBCêß×ê¨è’yL'„²e‡'3ÌÙÐ « â>½µÙ™k}­™š“óG«éÍ`NŸðéß›nJaØÐREÿ>vNÖ8B-œ>-9¯oP¶N`óÑ¿'oãý„Í\ )Ø;ÊxâfôÇ»Ôt†µz5ùÎSS ×"ÎSÓe;5•£P\ûŒ£ÇQôÑŒPç©ÉH\Êïq"×§r@Ù¸]ó:oyÛèÜEB@ǹ÷f¤[&HØ!OÆÉ‹æ¡ã¡‚‡šáTGÝ/a‡<'5Ã,*x‹Qô*f(o©¬‚£*†9q0NŒ–!¨‹®ƒèª*Ïño ­=o0'¦‡<2õ©KA5× ªÔgÖÊ•ª4pGGïÏÈK#ñµçF“C¢þ×ÚewŠ(Óà­o¡0Ý &: >ö}!ÏÍ·Ü¢ßp²³+ùÃ$ElŒ£+Qg·³’ƒæRäîù?ÐúÔ¦¢êåQ:ÇײJàÁW{2;®xuJàÑÀwVçà\®n¶¦„QµŠa÷*cßv@ì Gÿ ¨û é™0'o¢rÄÙ¸÷qŸ¼ŠÄhÚo€¡K zvéC²F“#öLÑj8BÙ"0~¹–%û³ðëŠÀ@´Šž®{„‹ÀD)ŠZÌÙÀ‚’¿§Š†1gã}; ÁÝËèŽó0Gj|B½²1zÅÆ€k}\æ ÀÆ ˆãò’/€Zй$/´ÃïÝY÷pq˜÷ÄwÌû~„(“ø·óo¦j[S¥[_úŒO‚Û¨š|zÒ÷[2u=BY2å9dÊéÉùÏ¿V]ÝÇkk”3K ß¹îV‘±ôኇ<÷Pä=ëþ“ï ¡è[Ö};²î€b–õL^(!Ψܼ!êŒÊ/¨Ww̳~JÉ­xé³5JnõÓ›;œ3‰Ó®+®1ÊêÁ+ù:=ØkŽPeßa%§VâÎ8œ.ýØeÅ¥Jírø}ß@­ŒRÏîLª*Ü€ò, t¿;FEpÇ{:Ê´ŒâxÊ{Ém-Oç¼F¨k䶆bœµŠ:E†}O}ôc Ä¹ÀzOm6ƒY}¯Ø6ºbkÞ#{¯ØþtÅVsIè—¢W_Å—1SµFÚ1Pþ£ûOYp¬m?×à ÕŠj‹ÔúEÞ»ÿÄ㧧DMÆ\P§ª>§©)vcwìÙ“u[«»k[eº¯Rî ñ4ÎMP¨–éþ ‰rí2„ò-mÀèT`±^k/(ò¢Â*L€¢‡b˜9åóYµ»D]„P ¡À_cÎæWBëN¤Õ ʢɊ%y#Ô«|é]&Û.ßy‰GõÏ¢ãùƒ­1ФkNQ¤»ÀÒž@…ã «S ­ó*÷I¸ÖMW7ÉŒk>Žy Dk: É[ M&ê*Ħ‹‚}_ò’`á]3´õ•¦Å¯HáØþ=¶x½ß ÑV‚ÏBù×ɺ£Æxnx_#nƒ44ÃbhDÙwõVLš÷b~zŠ•Œš¬ÒZO3ŽPx‚é¤NóëÇ8ë¾cˆt Ð˸)@ËP_[©æDè8:Éч½Èæ…(ÿßÜê;|x¦êÀI† ¢ˆ7(ä…¾µ°ŽÒøa`§om1“²^¨[ä‡ÔIݺ lÔ-ðB¤Èµ†óRS·”…ž03‡:¨[½€4¤·"êAÖÂu0ö.¢ññmÛHY½NÃ:èVW0Ž<Â(¦5½y„5õôãØ#Œ"ÀçA¹‡¶úýsØóú½w«çZÚfU'#j½üÞ]ïv/ê\Ë|õ…9||=+ªîãå[“M½²ÛÖ#qR¤^%5!ñî¦"™Cä—Ü‹•žÛî^­IeXáöŽpSjÅT¤gû èáÓ/sµŸ˜dÓ×EúëÁÏŽ~™Ý-½Çð©ø ‚Ñ&ƒ]rú~n•{@¡¼·¤"„²‰ó‰h@(ÿ!ì*7¡Š “<ù~ïä]˜*KåO.ZPÄæÆ§W&ö÷çL–ë9Á‘êMÖQ' ©Mv‡¬#³©v^SØa¾}®ò=ìïIú"B±ð|Nk"OMö އ|€ã! "½ÞE*)¢_ŠP/e©ºÎ¢ÜPÙIXÒ‡[9ŸwqýŸ<O#¨Ó³“°t–¥ö4Ò/ê3¹q„"gÁé(%ÉYƒø (¶9Õ„¸¸‰²ªY[„bX A ‹ ò¨3.1¼í³  x ý²>KE’„òN”æGY- Ä€ÚGb…cþþ\[ºEõ".×:ÈÁ©"º¨;¢/ÒŸ EŠœ¿úx3u‘ŒEc„¢ï%® èVìóy?«vüµÛ¤QÞDªž7]É1 Ÿ“áZò”–WÇüò.;ò!˜®<å-¤)"Rý£1pGy-ÞEk…Pû€kóB‰ß´Õ¡èËo침xŸi”o‰~L:Þ•uùÇsµS¹âkùøé‘³uêêêu©k1”õº ÔѨzùuUÖE_¤¦¦ºnà0Ê¥ìMjªáe•š‚û½IMqP6©©¦ÀÏE®~D¹j—¶¦|Ûä%§LYmY¢QôÙp\Pì²qA(ÏF1³^ÛˆU䧨"¡ U¤¯9B‘§[x3÷s+æ¡è{¦ž‡¡˜…² ü\áµißÄr?€iÔ­¸ ¨ÍÙnÁ‘FéÐ6By—"·>uò]……}Ø}¼ |ÊŠf\V„ÒãõÏ€d¤½œ“e½^‹TbPûü*x#=Fõ‚Š 3 Ï„í®(9^M+ðs…ǹ#ÉÌsõÅ"®wü¾´—oª½¼ÁwÜ'{¨¥ÀYl¹‰Kü#?ŸWIÐÉH‚²Oøð$ÓB:}šÖÍ2À“}¯‚ßÈÁIu—– B„+µ‘î¯HDT¶µN½³›~×1+䣴1³Sõ®ï{ëåû†½Qõà}k €½1¹(`=AT=õ&YÑìÔ³+Š˜™¿!öwôK«• ~.zñÄØ+£²˜†fO†ô»VMw-ÁʵO›ùW¯>Þ7¶^½oŒ:gÅ‘9‰úxŒ²±Ã£úœòbjVlxÀNý®(Óºnߊ6^ ]`X¿ëfè\«&í~æçÝÐlÜ4¯ŸyŸ{W¶q‹Ì“}žn®§›h0*xX"óè·ò„_®õÚãtêN3Ïsô_÷¹~ÿÕŠ#”¥ÿº‡ú. Îð=³$eŽ·rèÉgÖ%ÖœÜQü7 ”gK#ÁrŽí _ºK6xCÔÑ]"•¡<+KîÈû(s1/¼q¯G µ<†¸z†ŸRîƒ?6ëÐæZŠa£½£×CW>ʵ ~†4¤Œfî^[WICž4•~z¤mõÔÌ•«0G¨·Þ÷½V GMï몛EÓûº\K@Y—ùnטÑþ5L†®ã}ûûMƒ9:ùþ#ý*ÐÙ¸N\û3Ä44ÕVè ›Çunë¡°€¢æíëÄÒéÎ1@— l/s%¢,êÂdß¿Û À-¯»4Ž&|-z;NïáU$­ZWPìªn—ײַhÈùØ"TˆUä4O=Ÿ#¹}Œ¡öì9^J«IŽ+Ç£ú‡ËùÚ™püEi;ÂÒtsLLô€©øêWÉusÅ(‰tæûÙOkº´ãÒ ÔÅ:]ÏûIÆtª~€PÚ? ´S©äVyA‘ËÓ—ðôª³UGt)³CU³žÒqÖôæ·¦ÃC®´ïÖµ……I™¦šÐSË`~ãÓ¾œöê4WÛ2B›cµ¹#u;V „ò¬™QøÔ˜]{3%ÌÝîžð¶¿V‚Š;Ñõpü¹„ÅzÈ,`ÿÂa18­§°d›«üù.²ÂsyÎ üF,Íõ”~“‘ŒFùNé7m‘â›ôljw0E÷–ÃFïò*àŽWŽe•W„z'zç9´_²€Ü™‡HY–õ2ºC(ÜXY”z»*šiцP¾»³9&¾zZÂod6ãñ4þ`Aè2þæm_e’,´t?ÈŒÄXð0–²Ú¸E“¡‚±àû`Ø"‹¶Ïcí|ÉNÊèòß]:×äì¦ì˪®fŽPj5Yÿý/T«äÍ>`UƒPj5YÕÊfV Õ$Ó¸@¶ SFŸNŽ@“bäÏ)=« òU¼´V÷cÆáMF¯’šµŸ”³¦–G`¸ã-|4ùÓm›§)Ý´¦1CtÊ]ö%3¤K¹ Wu»ÂI§Ôó~'–êêè¶å±n¶e$¸ø‰j14råã›- .m{{0·'ûU»7gsrÊM^P}òD±½]Um÷-Fs´¦] ¡9å&W-p™ïË}—fý¯+`~‘«oúy ë7ùÆcÀåíx5u¹–BQØ­äp­q’‘»šFÉÉ:Ž+dçŒÜí=Vª5´„÷è¿H0ÀØrì„ò^®•Mõ9'ˆýZy¼4-B+9 ª’;颩ÔΗ “ÿÑcÎE2À„ù:n 4UU‘ l8!áºøG3䵩Q@­ùý"ùw½#y ¦é‰¢ˆ>¯3}û¼¢8A(v|µ¦SUqÔ-¹y®ïû÷(ÇK~¥n‘gäjŸµ¯˜úZm[½¹ÖÍýÚÜQm}iR@n‘Ü„ ªëbùìÃåZþ5Ï—§§HJöòôjæOOÏ·1²P=JT~¶cƒPÔ†ZñÓ³ÇüJåüšù…„ëžsâxôVWÏ ¡Ž¢½ öá7†OºŽ1U:@›#Ãæ˜ í _GV%‹É’ðÞÌ]—Ö9-ÆFâ.& °Ÿ¨çBÄb@(‹˜t­‰ I þc„Å4UZžÊ—¦Ä× ^˜†Ý`»Ä¨÷ÞÜwÑY”s›'šCÈè]±aþOØ•&K "Á+u»ÂÏ9Àñ®àŠ¢í‚kÌé¥ÐBÅy¿3h"PUY™èˡ܋¯õÞà°ð¼žñXÊ”íêr:£â—öý„P>–Eƒ|Úº¦u®ÏÇW‰µªåDÉ™{üïaœµ·äË+•y4 BÓ¼©È÷ûêÏp¢ää¦\rÛ[õWõ¨ÏçMt^ó•èÛ­VKÃÏ÷U†/å ióuœYc97ÁlÅèÇ‘!ùüŸÈ£ì‘!G(×òmƒ|"ùxïöË B96u*ÿ*^«î«äã¿Ú(ð¡\›p°€±‚kψ~{øÃçè—×%¯ZV.e‹~Wý†Â·è·aBáèW]¤›®ä|‹'‚e [¹M°bÓ‰V(ríºRQÓ&Î×Eƒrn¨]°"…¾Dò!ÏæsMÅYu5Fy·nïqÜ+4¹Pþƒ­\‘­"1PÙY¶ÍÄ ‡ª ïK>ûÓõ"å6E(çÖX‰”ñ6/„r/âE1±&’«°ÃcyFd¸GMÝ΋x,õ²åÐ6Ï|.”¥9yÆgוêxc‚ÇBÏ*5½÷ÊõVY™Ü(„~ÔôJÜ£“½ìÖDò.·„¢gÝ]G†U7Ê÷5েR?(|ìס1Y‹ug û"¡BqëOÞ^tOeò¦³xðjÈ7|Õ×oˆ¼+ïÁÓÓg&­YAëÛ^Nõâ|í%Û-ÈW3á¼iVp(ÙçÂ:ÈÍSÔ ë¨Bâ\©ì©NŠ´E;ÍSP—¶öÊ^DÕ¦¶ŠP—¶ö½þ‹Z]%e´µ3ý\YÚE Bùúy«ÐqM ´I,‡+ Âg”Œ„"Ï¢¾‚Î1U¤ãm¾äᢠKïàî$õ(«£ªí°››A«P®uŸ”Ý]c÷I‚•^JÔåjkKLp× ¹;¸}=X}iìÓÎäâ@©Üœ÷ÍM ä§Bn‚(`G;|sH[÷Ú0 æ¾¼JDÛ”°ýº35‡Ðr›ˆÕ…PÚ¿”bDõŸÅŒPGÉ®:Û/ÎyÅê,E¨ûѽûõ‰¾m÷{oAƒdàÂÅ´Neü QÔ4[#dP.VÌÔ:ô]4r„òžuÁu"ƒ¸ÎCà´ó×yMòþG×L¦L+Ê×Eœ´p(»®Ý~ `&¼·p¼á‰k^¥/­„^–/MqkgåX¸K-ʵý¢"¹ é,JRÝß,Ýœ+"qƒ‹.šù\pò¹½å˜GÀ#Èò‚Œ' L«Z‹¨¦\éýʽy qåVà_ôžÕcPw”sJSeŠB"7´»*üTe×mnʪÛÌ1ŠÚî9zV­z¦øžã’Y)׺BM»N°çÜt•èVÏŠI4É’ ”¡õ¹£º¤îâ¸â-B¹Ï¥í¬Ö&Ž•Û  !H.S×F3%BMƒÐ™EÄM[ök¶›d«hr„rn¹&¾åšD1ã±°áU¾×¥åú‹#†¶Äw/,c¦xMÅr‘ƒœ49YzûÑ·q;ªï™X˜r-‡PÕ~b³^å`Ú«Þ£ïÛÙ©‡ˆñý«­2ÓŒåŽÅ`oF§ ½Ç̳ Tï8¹qšöÆQ¦¬sb+&ˆçf޵ñD 0#~ðœï–• ëù"7« L£2n¢ ¡pÇ…Z÷u’Ž,©rŽPgÏð»Y=É ùpÌ1²”±jØÛ©ˆé´€œ4 |ÔݯÖ}Z”}Ú °cú§ùŸ’ÌY±®˜äF14j €¢_yØÎ ›ÁpP³ö©ß²àKÌuÂøôú ©±ú$ê7ñð¡$T¨Î´²Œêziâ ¡\t¦©™XÇ1+çY$år†ÛX2¾/Ë­K ¡Nñð¬Po¨üÕ¿rnþÅ¡9­ÌÊqÒŠ€:ÄÙXÚ9j–·ENiW¸ºÏM²¦“b„¢;J®¥9-¿x7"5„'þq9˜þ'ã8JåAjLë÷I†T,›*š‚!IÓÿ@mwûr‹n]ëºý E#ñ³UÐW"§m/’5WtäªhRÈß Û ²¬…Ë0™U PmW}Ûê‰ú˜Íåj4ÐÔSlü5ûcg+ä´z’Àµë+íýÐeKàés!ðìÆX«6˜%ȶúªÁ–°-²lnõs½Ú‚º ^m A©…¯¶„`´Ikî"˜nr€ªäU/Sÿô%õ«{HøÚÛ<~®ÆXl§±ÊÝÊ+ŸªŽ’ðkO‹Ê»(TÕNFÙ=-z(¬‘Ðyµx€ó=t_-à ÝW‹c,÷¡gl9ÅõIèÙos‡1 ý·ÔT¹I¼Œ¥ÍW b=XhNVÉMˆ8S]}eTãÔ+µöþÉéJ3ŒBœ?8"ÇaŠØR%¡\ŒÚ· y&¯\žW By·ÊÎ>V³À"4kIŠe¸÷J–Qpc ÍZÒöôJÊwø•ÕC/¼Ö’˜êº‡nªäX9BT%Ž7Ç*I qžµ$õÁ­iª«ª‚$xx­W‘Ÿ4ýU³^ÒǹÊ<Ì«üʦ_*¸sî’X\[lˆi@ ƒ'ïâ dœüÛÅ2Zç|NZ†PÞ]\aLåba›&(¾`œ‚äœ|Ô¿èñXáóñÑë 0ù¾ÉóAç;!ß›¤ Ì×2¶¢…| ¢±í‡Ÿê&ÞÂÃ~›YÏêÅ(÷]Y£ìÊ BÙ•„²++à±|‹B½Î@«oT6e?em=æÞ'\ÁÜ[½3–Ó;ƒØ\€!ß Gys.Z¨„”¸GGý?ÒgG’^ðÓ‘„¼QÏÎ-Ÿ~Þ*‡:¬¸ˆD¢†VåC©Þ6‰|ò¡„*$un„ÀèÛ„¥r‡Î„ÂÙr(9EÙôË—X Ô™‹Íuƶëx• Š& (bqŒÐ êßÞö>|ÛÃ0ë·¼IO F9†äl±{ ð¦+Þ!”k“!†‰F†ûp@àò¬e$~åŸ(•–7ßz0QnJù´^~‘åoA¨ +ÊÚóPu~ú»¤±ÜMNIc@Ñço[{8z%ƒ›Iiý\çþk®`Qu<Žg„ržP]Äó¼B(×LRlÈ_6ެ‚Q5aT¡6Âh•Lð?Ò«ŽºEb=Tœ(½ù¼dàó’Š…±¡Ü»œtÔËQ?„:¥/òj¨QÍùE5BùFÂv¹W6Ïò„ ¬òûsÑÏç]Þ£ìò¡îòË{ê.ïÁ±¼ ÌK²~z¹µrx®ï­å…iyvrPfËËžˆº¨aƒÂª«§*á!÷‰(Ÿ[QžYÎØÞc“,›Õºvâ ¹c¦Y´`Tp:Âå*‘1°”r&…J#yª¥ÏùQ¡Ÿ›¿¯*%­U‘®}3a”óT@ÙÎm• Ô]~Ö)<úq­uõaMäÏ"”õD.„rŸ…ª&âåJ:Z:¸Ñdp@ùÆD"ÙT¬©@¨àÞdSµC—ÇQ†Pá¬+².<—)``Òp‘b”ÕcGϪÿ"¶®Õ¨èÅëÜ4þÈ!…G/²º»"Òî]Ö¤mÞ$Ó¢P·t38T S:1ˆNè•Vš@qA¢~ÓÒ³ ¡°7©z]]ô¿çåÝÏÇeêJezÒJ!Ý‘©»Énü‘ ~ú@K…R’Œ‡¦6ïB…ÎkIYnug„"½0>À/Ò;]_Éê"6 ½Hl˜&Flúý<³adèx²aè÷ó̆Ùü£6 }ò:×ÎXýP(ß%Šø–†}@íè×’ÊÞFc¹/¼"Z0ʹQå=‡åQßvD¿6ŽIÑ౫)ÓÎãÛ»#ú½qëP{iÁ×qÊÄÞyë0«4  0oÊ‹E Ò®€²ð6 [µ$·~ ¼›~_¦ýÜ›8Sqýú„÷ýäëΖcúõo'ŸÑrÌÊ}l9^tË1E^ç×–ãñh9¦§×ùsË1þÅÀà“¨ý>ý%<€ ÞS¿ð¶C{bñ°[ _bo¨(VÂú²ûön;€âHR;וï‚òj,çkëhþ¡Îk+¡>÷5‡/ÍqíNˆ¼ñ.êX“º[»d+ÚñžZûBÞ½’Yeú ™Í?[€P¦üB®å’I5„êÒ’ÀT31߬Ú ­ÂTÝåä i†8ÁÏ…"i3•¨|EMÔSÔ¥ÍX× B…'ë7Ö¥=ƒÔ++êøw_B¿¹P#ê˜öY‡FáÖ¸ Rà"Ò+‹õ¸ç$s—/SY"”sko(†¶d]¢Œ¨^×À¶²ŒÏ |µ·ðXË<8oTy‘b·pàHîÿc—×=[ =‹"·pÝ’ ’Í"¹ˆó¡ÙùXßÉÓe£IŒPgDöH'‹ºgŽŸ‹ž§ì…eÙMYÓÌø¹ÛÊEì†(ž¢©0 G£jþÖ:ŠXR sLØä¤Óåñ‚íëbá|uK.²Íy87žÍÃõÝ=èŽEÒ§òS¨0ÌÇ’þû’›¶ŒJ¶àYû_Œ‚Dƒþ§¨ñêpX[1-|(à7ÏëÎ?EU7™ 5/ü· ԩΕ&zC¯ÖªiƒPîc?¤Ü^aCw?vW¢£JGÝ ̨.¬€±®¶è:Ð裡.ØÆùW;B©+]µn!C/ÊyFýÒ©A(÷f&Æ7Fr2MBy¥Xq¼ã‹)7P¦ŠŒ ý~ë:F¥ÚT\³%$ÑôífÅàCÝëv©>yžÒX@ˆå^ºÚt¿,£~Œ¡Ùƒ"úì­„Ât …"úìΰCc‘|ÙøƒçY˲E¨ýö÷gΪ\FQ!yp/û­YËæY¡¼»&µ)Áw¡œC».;\~ó(X7 ”{CmšT¿8‡ i‚Úùûå£-ú¼‘qBùOkµ®ëAiHP×C*  °ÿb[DS vÚÔõîJ_jîóè× ¼ÇàšJVÏ•¶cš7B?W`:Ž¡÷˜M4ŽPDõ†°úG嚘·º‡Bù/×0Á:‹¼í\ïÔ®hz´„PÄžÝïÒŲ ùT°r°AüŸ©q)ãù§Pß·“AX„5A¯;æ wÌ¡œG¿´µ©ôXžÝ/MˆêÙ/mÛÈ1ʵèdTЍ(ÏêJ³ê¿)Àê€Ç{MS@ÿ(½Ä›éÍDÄßCxPP¤ž™¦8o#V3£7ë÷‹šY…P53®Ã"Ä,}T3ÿèÙ8ɰ¯úŸ·ð£‚°Èt-4§Â[ÿÞg®š¯âMpÀñ<ßݳ.ÖŸòÙ¢Hñß± •ÈZý Çru*æÐÂÍ–T¬¬ƒD’K–©BË$¦qâk ÿ£¾¡?ø:ö}9Õòm ŸÈ º˜7¥Œ5‹Ê}v¾l› ~1xžUÅ×åzVC»NÆáÞKýkƒËÁ¦5U+mjêӛϔժß\U«@¨çF¡ÙHÔ°¿éðl@(Û¡ª=º`­¨fXÑ'oÑ,˜m¡ß²@y”ŸË{Ä)[Þ(+ ©kàmUçn:}Ë‚9·Î8ùyüðXo™}­ÊµÓMpÏA¼?5DbûšˆWezvmï1KÑš/–_›ö2§c-åŸ +4p¯.­Ú”·ŠËá'`&nnoº§:ÛqhàÙ­{§¼%BY­{!éx¯Ö½ÊjÝ «0ð,6SVñ.î2„ ŸZh†£…PØk Ÿ]/¦ª¬j„zj´©ÎF=«Kn´àEú·¾Ð\}¶lŽ×dUÛIz’2{Nòz$ ›»=ZäÂñž¸²aßB“þšBJ1‰¥Õ_­#„w胔5‰$ù,Ð;S»õÒLÒ‹Tº]šVâ}ꬃ+ÎΧ‘÷¥–N“÷IèÜv N‡Zì9 BEØÚDO.äm³‰ø_(±…š-ý6´jF|­ó2Õ™¶òu¯ûªêÉû^ÈS¿+ì9ÿÃJÛ¼_Ÿ§!:Ó‘M’ËzAL>Òz¾Úôrn›¾ZO+°ÈM“Ô?áß·æ]MÏûD©½™D˜–Sº)¼Ž&f¼…éŸ/È”£‰†é‚„¯Q;Œr¦é¾ ¨+ðz¨Ö¡Bq®Ý I­ 7(ŸDTÃ1ê^"ª™råt´É,Ù—žôZ5EìMû¥©ÑWù¥õ=D0it6iÔáv‡mmÓƒUêÚÚ.ØÖ6=X¥.ã½hºu˜¦ £¢‹uï2dcW»¨S¡_ŽhÕl(›¾Ç÷_Ìo%“½X8tmÒðdð{2¿eõñ =”¨äÖ|±«Á45Ţ޴| )pˆÓ4¾7ê)›š’dl¯Ž‡^ÔûEgçZ‘g踔€z݇è1ô¨øjY=ekÃ7ó7Æ÷fÁàÅçö™/š›ô—KI§ÉìŸs)âh:5ý4Ùvºc¾Ì-ì;Ç׊nµ¦öDõõòÈÚ»²Ò.Diiú `;r`±¥©¿Ùä*žþþþþü…̪%ê¾9“cÔ]!s”§»Ü¿,êuèCAoZîäs»K®ˆD'‹\èÈJÔ0–í†P¡G­)“Z@å³ÔalPæšõ×5yÞÌû¶kÔ‰ÏWB I3t•*ZTèAh+Ú¬œKÉ¥´¨èÒú¹UÛrÞ„z]"…bÛï—0ŽPñ±G]޾,YßË,À¢Þ¨»«ûïÅ´63£ÎÝ.¨’µ í•PƒE%.W¤Ñ\‘žlùŒPéUZ›’þ+£iŠ.Ƙ÷ÛQ„ºgôΓbôZTd‡ß-›Z|Œùe?„:¦T*ÐÒ`ÃÈÄ/ㅽиڛD–#Ô±ª"þ4Y¹ø²I+ñz´£°ªÒÂßøvÎǬ¬ uÖ²½f¡_‚PÖ æÈ­¦¢ÎÄÁ¿ø9)ý™™OYSífø8¶E*R»\‘‰ãq˜kÝåÜøYJTò¨#g®ue6:šap-?3H©àé»?XÿüçŸq´öo% W¢ÂGT¡ß¬Œx™ýY&X/Ÿæ!È&Œ3Bù¤VU¹Ó¢"G¾ê}½O%Ü×E6ßÔ:¶bË•€„E…wu&#™+Qñµ€v¦PoÇFì ÔleG?6£Ôb”¨Ï#JŽ/JTâ×·ëgóNé½ ¬¡í$0Ÿ8ÝúC¨èV+o›kç_Ó8±ö›ˆ'ÊF¡õf„4ég\V‘ÍU“8•á" TPÑ!m‘¨8ƒdy~›êåL]¨,3+š…ªÑQ‹ŠO,Iyºtž‹vG¨·5#°öŸâ6ˆø?Fw@§0r̦ʆn¾û³Å rZ³b« ý¥…Áu½ôR¬ËX³jC¨G ÚxQ¤RÈSiØ}YkåÕÐà®æ|nk‚PXZ‡ÛªI‘mœ!TtŠ%´žÅÚÿåÊ­ç9hÀÊÖ5Ñ6¬ªû=æfލá¿ub|ª*ôµüb|VcušÒ#üïǦ´ƒò5¥GŠQž¦ôHùŒP/øj‚IÔÇÏl”jGB…7$‘Qä«Sotržýþ6¥kÖ"Txá,Ê“4•yB®‹™€·pïÍ4#Ô aÌŒ +†ìG*¾¿èiÓgö —£®cL=ó6‰EÍ0 ©žBÞ!OdVÖ«ŽM¢¿3Q¿_rÿ¢ëZ¯:Ü@ÉëïÄs„аÀ»Ú1›¼Éê‰ð/B½çk°\™I¦ô-*¾ò ¿¿¥¦œÈH»ÒP\4Oš%”r„r´ßjfBm‡P ÖM”¯n2Â)êÁÓÒC”ãk9‘¨1Kä$ï2ýæÄ7óM h(“½#?„ 1½¨Ö5wql—âÏÔ(—Vw(y«È)”†²E…>ýj¦ï>öîršh¥÷Âø¼…p­G-ì ê&ñƒBïD¶fF¨óJÔ°ã_ë^d$¤$êý$!¥Tb-êV³9"¾ØÔ1&HÒm¹›“¨äQâǬWê·g…qÂF¨J‘:ÄRòpø*-l‰ .›2ΩGi°ÓW}…P!²/ÖUþ‘­ ïkº!Tä«OÀ7„å»nêÊ[ŸpPѵN.¯ÅÕ¼¡D«QP'_kž‘½¢¡B“[ÙªµÌ'¤¿A¨è¾£¾8ùÞ¯ûŽúHlGÝ¢ÂÓı2B%íàýÂfœç½°aäµïØ?“Tfÿz?¼Ñ0“dQ¡OË*"'ÌYËÅAy$Hµ…›D%OnÜÜ×ÉtÉÇz—¾‘#\ëB:ÕûÄHË_Þ÷Œ"Ô-¥±ëV±ùfËàýüùÜ?ž#2»Z*rxŽ>!3ÐZ‡Ýä^fÁ:gúÒ~4¨èéÜá ¨Ì뮈ÈÊÅë:ëwõóº·BÅIUάà:ñªž@ë¥ìiQ TdX<8Z«Üdì&×ÐÖöåàOÉM¾ýy¹ÊP6öÏûKÊî‡Pï»Ø—÷lêã¾_2‡©‡uýî­ŽÒ?ç˜{WùcQwãZ„ò1»Ìþõyû=R޳³xŒ)H” õ—Bïs¼Ô©ôÜMÍáKû¤Z0èÕ,£L)ByHó¹A%½&Ò2å©ObÔ}}"k(ĘH-ÌáHuRµ«~Ú·æ’Ö#…@F‘\-­õ¤½xÚ_™ShTt#§}ÖEžXTˆçñÕ7´v?ñךêJ§öõ0’2ÇÍ͹D÷âvøÅšlÿbŒë&Z7~¿ß¹€º\];ýª_û–¼Ï!JõIå5åÎfi!ëíڳצw¢ßûý;ù·¯*õúÓÀµ^Ï6bð7Æ^­3c#fQ~± ¡ü6bõº—vÖ6bûjîæ ½¯o<ÇaiM)91ô›TÎzv»xs¶¼G¨Ð÷¡¦\‡Ê´ÅÖ:¬MNHŽP/—ÏT§LM¸ûÄ™8Vº| 0¨ªv'º‚„¸>ŽA˜ò[ásF*¼©ò‹€ÂVù“ôj ¯3.«üé$nÖŒrñ®²¡#“’œ¶¨Øõ>—[ľ[ïëër‘ ëBK¢»ºéßMuØFîbLÄAr&´K^lmÑõ¡¢»¨Q¿8–{NÊå ©ç(NÇ®T´c«Gõ=vÅŠºÜê}Ù¿:½Aµ3ýsœìÈ®bmÄ1AU2¨²þ×®Ù\#Tj×þ ûjÇ~#ÏMŒ‰T©WUÄ_÷qŨðç0ˆs`½ÂÇ8vòô¬¯ߣÚÉí÷˜^:×°ª•¤W¾:ÓÞ SÚñÎÝHžŠpuª zL£ËL8ˆ™îÒ€ÎG¬Y§B­ÍЛìËç|B¨÷šS“Ñzž6„Âb¦£þÆü;÷øÛW¨rU·lÌÙÝù4:D®ñ ØÆ³¡h3VáUýs³Å:Må:ö3^ -fú/ã¹$WŒNE¹4K…×U΄ƒ “ÙPøWlx‹9Öæ‹Þ©Yÿs Ì5#€êCúPkö‘`TèqŒ!s§o¿öœ–Â(/C"Èôs®×jÓ—z.ŒŽíÜ3ŸŒyÃ<‘ƒùtçdc¢Ñƒùt7Gà,JOc„îPL§2R~sUrr6æZ%Ç¢Âû¡=‚nQ‘O+SïÁßßã`™®o¯ê6q²ÓO£Â§3²Ðgd€õ».gägdð]U&”ÞFÎB;Sgæ€=Iùq’'ý®óIÊ_NÒ m÷úû0FuœÅ–½®ò¦êc¹¢¹´Ñ–çmßüDd®÷|@%—S¹Ã§2 R_Å`‡ûz=ræô[üùº±bGñƒ)·ö7“(®6Úª[€­oÏ,öQÛÌKTòœ¡À/¦¾Z¹œ3€ºBpðWnç ô>(Ïœ‡ê ì¬ŽÚÍU'¼Y‡¬kt?3@ªUêÛ.áÛîq­ŒéèP®»–ü oý­*r,Tj.¥¼ç1„z9UŒ5Éi®QçQIèŠß]W¶.%ByîkâG¨è–õO¶¡[4êìf=[‰ªÚ¡*Ä(u’ʈ{ýº³œ”¹´†§î f²úE¨×ñ„´WÈ!ËlÚ߀PñeÎ`™íœE½‘Uh[ eÑÍÛwF¨c̢Ƽféèû}`ÙJg¾unùÖ…V¢„¦'k|£üñ‰-ÜÇfÝ׌V5E¨ó­uä1í]9”}Pþ¡d¸ÖçyXPïçai‚P×Ê"9†¥-*rêiš4Èrà¨äf€^1Œ–ŒÓoÕ#”«»©k:]Fç\×Ó…9¥ñÖøUD™kXòƒ~çH›ÉÌJ©þËÔXÕ‹Øt˜L±¨÷Ñ[FüH».§ó\!Ô[Á¨T`_Ú_Ë룧"UéÚï2LYÁYI¶ÒFuâäû‘™Âùþc¦F}"fZHGŠPá}ÿdš5ã/¸°»ríÞ">¾¯¶*G¨—Û?QÝ_ÃɦËAøwš+;:‚=í›î>8{ÖšÎ;YEª™"TxQœnærmú©duËu—vW;¾–ÃM+u%¶,ÇŠ8¿Ÿ¼}åý˪jÓ–ë°k¯®[É>+¯8C¨ÃxkÙ™µïgúí”}átC§Þ‘•FÒFD0=›B£¢G¦~×z=ö)8E¨ÐÇ(5wûµæ²f†¨ã¬dVB?Sí"+"9\ë}âßIw õ¸åé>Q†P^Ý:ó´Ø]RrdF¨ûYV¢€JT÷Z`°áÃüƒ´Ràz#wý7FOÏqÒ]â žtþ JDwŽ1¹ÈËa½¢Ð#«"UÈ'û‹ác_Zwœ…*xÀ‘^ÇNjeÂJDáe7ÑÞlorûNDáy7±œ9ÊšºÕÑPt‚Vï;EA+8E£svÕ#•œ“Mó­ƒèª.¬÷ûºÈ–øÖAtªwàÙòz£SP1Žøô\Ƽ¬"£€s(rëжUéû*9ÝàŠ"gþAž jû+!«‰ “Yÿ>⯦— FéêÖþßøÏÉÝ·]DZ[xUÿ0éWý•r)Ø E|óLTN\óƒè埨$z¢Ò¢œBÇÈMµò¹‡l!Š/¬&èÐUâ@ÎöB…÷QÓÄ ‹A>ÇwÒpðuGï[ñÊÂ3úøÕ @èÈ¢®,°¦éyßÛoÍÝuœþu5›½{ížú×EùsQ¡Ï[C×W‚ן?S³sÁ+xšÏN|ð Î<*ðoŠâÇ6ÍÂ^¡×¢5¯?ÄC¯Ð_"ídPÑC=ªFY€„´Î0Iùáð7¾ö_»ã¿â§ŸÃ>‡ex6kßò îþ}±ö4®+aT³æº®jÓYË|®æ ¡°6j µ@±göy ¨·¨Ê`¡|Lpèä¯Ä÷æÈ ›Õ¬}úÈ1«šž*ܦMŠR,}©÷¦øïb×¥ëà½8e²vÃø¬˜í2çußPÑeg¨v¶¼E¨×µ{E‡Eü-Õ„P±“ƒA§µÙ7'düwÑ’y e¶#ÔçF4´\‘@ö…yÆj$ßßWzÏtÏQ¿_ƒY=Ê&¢_± “Isë‚8º™!PÓ¬r† gú´EܺþÁgrÑì¿mš{„òöèáˆ_=zåëÑÍÅÂv–ר{a; ”¨øI'¤„Rüö×É@—@¢übaÆ%I¢¼îM2bÌߘ>r–a~?8.5û µ@l³yS}„ 1ðî8lp½ÃÛXÁÝ;¬¹+‡ÍÜ}x­‰4ætoY©ëQo褐̶!¶z¿Øî†¹¼ãÇ<ÀÜ×ûáTØgÈ ßïûž æ>5p"¿?O>V#œÈ<"Îràg§j$žPêg±Š¬âœÏŸG)¨±JAz¤fÍWû îUtT½@«èX”O¶ÏBENªèL=ôEN*M™é/Jå®v¦Í‚P±GÜv›ð/¾¯Š<™RäÑ b@}îy˜TäÁ÷…¼”Œ51ÙwþÍ·¡Ò ¿^ž¢\Då¥cwG ˜jÀözV&åWfåWƨ«09Ô€-ʯLêªL5`‹ºª³C Ø¢¯ö3ü¢Gû™ÚÏÞ£´ö³E]µŸÙ¡ýlQWígrh?[TìUð…_Œ|‰Rðµ(¿‚ï„Pw¶?V=Y¢ÂgõdŠP~õdŽP~õd‚Põd2›¿1|VOÆ×ò«'cÔç¢eL-c‰zûèµ3 ‘?Ÿ‡!t3R (‡¢[ù¾Šs\ŸäœpvèU¶Yw„r ;µ ñ#Írýæ$ç±¾ TŠy¹Žƒ”â I¹N0ÒjŒ2ñÍÂW‹,Uÿkઢn] ð7¦§Z[.à¼"ò"Ô¡Ì))±Ú °‘ A³ý"ô¿ qVë§3ÚÑ.C¨{JÙVs($g€ƒÓ“­a^¤\dëj¦Ã$ð H7tøÅÐO¹–ÉÚ„Pámò^ѯ¸šœd¦ŠÅÕ`Äd(Ö¡i÷R·°¸ÚÐ Ž*‰ å¼!”c.kÌ5 :UP~Äâjæ«•=È…®]/¶œ ¡Nš®:mâû0þ8Bé¶¡Ü'ŒÉÓJÖqí)ì…ÉqvüsÐÓji]º¶"!õqF*5 ,ÛáN1*¹%@Ëmî>¾ƒdx 28—.œá1È yßA2< 9·;"yW?~ŸsñCB”Ü BË_œE¤S›öÜE\ ôÓKRÔíTAó:I.Æ&ªw]ÎÒÐc¢BE±k‰ˆB÷Ä5g<ªS¹.¿UË**F¡&6ŽƒHvDÒÝ"ÔûBc]ñÛdÛ8B}î }N0*1ïªéÿê˜o«!¥Ð¨ôBv–lD®0ãUýs?ÈZ÷›Úf(àAºsÜ_à§5²ßDʺ(*t;\ª§ÖfD<ü ¡"ŒRryy>Q¨ß!«»ȼ|_rŽP±ÃW¬ éÍ6×9E¨£ ^Q ÄÁf Éaan§ÿjý‹ûÖî^‰äþã^£Rßgžñ}éÅ7ÏH1]“Ý´ÕøÆtüºUì0,¼ÐÁ‰¦ƒ/úkCt]‡.¾6 Ö×^ˆÞL½› _+21Xfâ&MðúÁ;–N&༈2г(GÄ,mY>ü¸¦7éÙó(þfÙô…‰Z9 M¦]‰PñmªYN›&ƒ‡àMYd™™ õ{Êâ‰Y‰è¹\wÿòK"$‘‚4>K"é—‚íõÜs o'Âå)éž ZHß~yÞ#Í÷.ÕžoÊóéÇ?²#õæB…>ê)¤ùy8,ì<2ó®¦O­CÀA$ÉÓ»UÇ¿áÙ† ªdvP%¼±{•Ý÷ÿvmK¬‚Hð—@“<ž÷=Uû j¼#ÆK¯_AG÷½K á2Ìôt—M7ö%/M9™œì^JW ½Y›;…f4¤<ÕæôQ›“ÙèÈí~¶3¨1㼜s'"·ÓŒ~[kâ,oÒ4ë8BÅÇv½iòd¤›Éí~¤Ø;ä»iò_ZKüõÏÝ:x˳œÚvœŒ, ¼&Í{Cn$t‘{› ¹Ñ«6AˆY ¶{u"Aä‹Ü˜#¹.µ@ä2göìJ ’žˆl@P!ÈÊ~=;È"k;WÏ<ön;Ì¿®ëxVtE4^zPÄ!W™H²i©z„¢þáð,¶Ý¦qj[@K¹Å§•Ç·—í·MÇ¡ˆ×¹¥z £ú8ýú¬*V Þ§ž` ·ÓÝv½„•Ff¹åè#·ç¥FÂ*膱àgѸ]> TÈ £¶;ÀɆöx*¬Æ‘õº(&Wö»î· ¢¾6d}r¿åyM•ø=?Ù6£AÝÝ­uÏÑÒ\©HBˆ+t\R D=r¿ŸD¢¼ùžûœ§™iõÔ¾Z‰²F¨ÎJ* ÜÂZK*„V Ço|llPÊ,*›Ë®Ã¿ñé4JÓ(aÇþ¢Gý›3F…{*“n&wz™Ä‡sèD¯Å¥JÉSÙ³˜CÃ_߸š4gŸF":Ÿ8àNa=Þͽ¸1±æYWa „Òo.Šùÿ¡*BEGJar:|†BîèüIeª° ¾’o‚P¡6¹ Qó¤]ŠâU»ÒIÔuh*ÒºLŠù]øøØVy©ó:‚ñ:Jdì&àuÒ«È v¦³° 5ÛÖV¨é$Œ:P·LÓ^-s>ؽQb6ú½ºÛJ„B”Øò“¼gY›¦$‚¨§U˜©Š@Ì”lR†gÃz‘üòO?ÕE7Yj» C’ôŸeÂodþ²”Ú¥ÍÉÍñ§:X«ê~e­.Þ¡° ›Í,ª}¼È¿ƒ"a1f!¹‘ù#ˆâéXÔ]q„¢üäEɉ¼y‡‚* !ìr~Ù‘ˆ.çœî$ºœ_Áèr~%ø ÛŽ¯b^«aH’ÃwE!Ø'H|iÒlçÄ#lîÐåö/æÚK»„¸Â\Z鸶3Â\»›ºôGûyó¢XŠªÖ´pz ÇLð˜t¡Nq4‡Sk:Ö¦AžÐû½D%ÉÓMÂP-lôH‰DQY¡ƒŠú¨ºK2KÉŠùÿ!c QôÚ£Âö5B…ììÌ9ù©žÅÇL€Ð°4r¥.1pòÑèTAÍLfQm:3çÕãuj£·2¸êïVQÎj²¡ˆOÖµë‹tÁ(4ö@Ã×{ÉX×5G(æm[mßX#Tä$ðÖ»ûÒgð¬Ç匆Ñ}é´Y"õfÓ~¶õ ÏX¯ |×óZ£‚·C`!ôu};Á(h²aAÂn—y&ˆ4Ÿ¦êî©Ì¶YæÏh$b ¢HzRE/ ë¿€b2’ ‡ÕÁ¢K±É™#TPlR`õHÎ÷ÉRGsÖ²ØiZc“hù®¡ BÖô+éDë‘WÇæý«ÛF‡™¡=^¿K¡’®.L  "‡Z÷Kšï‡wYP®P±ÖWû}ª¥D¨5S3¯‘(LBžÔ|JëÿÆgˆô ' {\’~¨ -dDØ-h±·Lö W=%Ÿ`¥!R¦§êYBÌÝB\†Pfv€èJÐü69Ù(såõÁûD]J•C,Å~¾vŒ¬­ô‰bÞDÈÏÚ-ñl½ÜTÂçF  å£í³‚Äy”Th'&âø©B̤éÏu% fŠž~{=…JEU›¦½ÂI5W!R)×ê|W|¿¨þ5ãM†Û2Â+u_Í$Üšâ³ l¿aѤ#òEâsc/øX¾çe)e1SL}Õ6q¾KÊaÅ {뾪îV_õ‹Mc/ FÁ?ôýÕåÿcLÏp¨ùXÎМ(,Æ\ù§žšMB=p³7\ÀòÏò{›g@=±Ù|ׯ^šrâs‡P›?(L‰²jšÏ§Ñ¡xToèúk}³’~lªÿHù£õ=àôü-Û&5•+ #!}¨ ?ó99B‘€òSe ØY½Ú+äv¡kàe’ؽB–ßç,8ºWÖÞøùÇýd˜~R’4ÿ#VYô)Ib”·ß{W’$ˆ‚çvÏ,6}\'2àbލ§>ïO‹Šüº6®µ¨øR×F„B´cG¤fôÜs‘•ErrMßÖ›‘çý2ÉÏŒPþ’íÐÙ ¢àù-Fÿõê×Ú¯GtœÓNý’A¨ƒˆz'Ck£ìa=Ô ÿ:´ßPgÕySßRãõû|ebø$äééÑ^ÃM®Ó\ Å ,¥U`™³ŸQ¤"»s©qƵ¤å5€LÇOP‘·“[á' b¬¿¿îÒ*xÿôuj:òõØ·|ý¨BoùUÞ”jÓD¨§ ÞÚÆ*¶Qi8üž÷MEÊh9Xú£äjîÏS‰Gõæ{åGm­ÙùžWJ!×Q>ŠLð™ës’u˜:`OÑ/ãhsO⊣V6{ZÉæPä(¤vÉ—ÆVŠ«ð³ÜMZ—¸ÖÜ®A=\±A µû6#F‘PâÝ.¢çµêF…U÷B…T÷¤À(æ!©ËµÃPá>amˆaÇëåñ]\iAɨŽds‰¤ˆ*6¯mÊÐ:F|YÌ–IoWDJ DJz»…‰"j´ ¹ƒî´³#ååo@(¿òˆ:8¼‘\&Áz@QçÌ ø‡ Ô)"[yþÇ„K„ $ÁªÏ…¨›ù¦…›þn¢9z øþˆÞ©KÜ2•¤E|zâæE=´ø|–üÛTÅ\Züˆhñt'nùbwðÍ ·£Bº£+Š`?cP4Dk¬àYñe°€ïòÜl*Ú;ÿÍ¡ÍÒÛÓÓo ­}“ ãˆP®¬~Ÿæ¬D(ê)õ³J^¡\.PãU*1*òõÚÿ¦Ffø»ýñ&¬­“ñ;¾[üÞ0mî L£ˆluÀÔJƒ&.@y»œW‚Aݽ P$®Gsǧˆlå ÍM"²•/0„Yx¸u™ÎäÁœVôN\w ]W èôîÞËq‘Û¾‘…´ô=Âþu.} `Õ"Š‘àiQq˜àYÍÐPAïñ%Áóð¬ ÁÓŽD|Ið<<+Hð„U{ÚÔ9—¥mÛB˜|½?ÂzgœG¨ ÞÙwF¨ ÞYŸåQà—¹zãTêyJ¹ÊÔv‘M¦„ÞŸ®r»¡,/¿‚¥D(z¤?¯y²©ìºÎ´^Ò3Éz/kE殊¡"Tƃä¯\ªR­nü]±ã]:–¿>ë@›îÚ|ÿùwUù}'¼ü „Â:æ…ï¤ÊÕ™Öág½°^ãºLS¾ôêÿ®ñ¨Þ <襈muJÖ,Ë’ÿ™"îÓ¿½†ªEƤZŽQ%E y ·IU@Õ–’›#O¿YOlõJá`Û™¡¹ˆãP$\õPL0BOµJ~+íáZØÝYM³ý.ÓH4¤¢n‹þPÄÏ ª@Š‚’sýlrïµ²|ÃxÅ~ñXÈv*KÓ%HÉE%Lˆ¶L_0ˆÏg„rÄÄBE'qýÒl™ Ô¸(yœ“Í`D_«ù[ÀñNÎ\j[ÉŸu%ŸÛñzœDbµn¬#·ÿãÑpaëûii…r9¬€ucÕšH#¦®‘›T(žuSY Ôã0£ X•‡g=C$„i! ?àŠÁ±’ð[¹bVŽ™’וh ”c„jê5Õ[VŸ¯Öj0¨s7ñü¶kð+Š8âÛºRmL°áÓs-¼4=íÚL¥ËRSH¢”8&/æPûU};€-&8\’Î'I ®e¨‘àtgÏ+)CiG"ܹkЃq¬cq ÅXŠ¥ùœ˜i((WJ–ƒÅ)Fу­ß¯®_¿Ô©AÝ©šyÚ¬ÌÓ®`ÑýØ=g:¿5¡öS€rù©?Óí #%¤€ êbPcjÔ•häØ*¡) Èaê"4:Û*C OÔ"ãïN…(`«¬/Ü›­2Nê7¶óú§e7%ÈnR$àç‘Ý´iÅ0;m­ÎA$±K:$£Èo@gOdxc|}"Ï>‘B¹'2?œÈQHNä(>Èx7Ù¢Çèq=ó€PžÎATr›Þ ÎÚ=Û×ËyÓî¡Ñ+l&<[™?@¹1€8Äñí:¨*àg…c‰Pn 1@|»Œfü]qHÞÒ~×ý¢úkÅ))ôˆ:~auÄç{í‘]kQ,,â;ÒŽÄ¥° Ý£ƒÄ'‰O+$,èã‹Ã©ù–øìˆŸW7|cÆÁ[“æH0öÿcWoFâq¿¶Ž6ß…UÅ5E½eÊQð¾E(T¸*÷l§¨«þ‹P‘ß ¡; º“Î6åGÈËõbYÞç<ª‰í+áM?¤y_ã7"ŽKiæ—ZÛK!'Ÿõ ‘ya/|’K2¯é¥·ëHæ…3íI.ɼ¹?I°¯®.xbè>ôd§¯‡¨ã=ów9sØ£ŸÑ5ªF(²ÙÙ8Gg(UÄ}x ¢B1GWPksª{ÜʱÑîI}ÐAÅ›^Xc¯ÞX‰l‚2åó˜©qP¡1Ìû¥ÖÚE”ð ü¿1ÕmåÿgTìØEý¤ÖX­ß€rJe`œ5¼Û2› %“îzt“e>Bd®"µ¹ãECäˆßøk9赦*Lëå¡ÐÉgïic^óo3…í|`ì¿j}Ôi…ŸÅõŽu¿×õŽèÖô¤ZwÒtíŽùºÔt´«öågþúw²±éëvVˆ…ƒ[÷\ˆÁtzRÄ0üûç -ÜO5/á.Іg¥ßÂ*ýÒÃÿÞË<§¿1ò˜$­ÜÁÃc‡;(´£§åRdìU<¹V<­ÊU<Xñ”¾Èµâ©ù_¼ÇЧtW`ó+žJ„¢¾U»+žÒ]ÍeénŠôl&lÏ´F¼?IÃáÆúbgµ­Â˜] í·æ“Uæ'>®$‘$µod®âjs>cÝePŠ}1׿¼0‹’COîá4qNþnÛ|’…D¨ØÕ)Óo®6øúc3–ŸøjpPÄQ þv¿qL¡ý"%êI\WG–-‹én¢ˆDéÙ¿jˆÉ_nÿ,tp5m); ãõpALgöÕ¡H ƒËÒ^G¯u¥v5ÙÊšïR„bG”ú'¿Y£âÕ2ó¯Ç©Ô¿™N¼?²:üõñqNhR,¢ÈÒ¡Òÿz($ßOŸÕS‡POló¸NûIdßñS%B½ü¹ÚÞù°ú‡zçöëu¥ýÙìv»ÌZ›™ÝîWÆËÀ­g7ÇtÜÎ/žÖ¢5Iì¤æ–e…s’ß’‚™ ðÙu…¯ºnKnb9@!nÄ«êú¿‘í­'0+Ôñ(³¬¶o¤ºZS§ºË Ì•aý8›^w¹e©x^ ™A1·¯aý‡²&ÉñŠ8ÄZQwºNiî¢ éÇý5™‡Fu”<ù\v;îLºo¼0 *ã¢bc'ΰ~ÜÒXõuÊó¦E¨ØŸ¡\Ù#Ô#d`QèFç‘0'L£î0Ÿù³Œõp(A¥Qû$Ô•¡ÈAÉž·j(dPê ÛÏ,ß;gÇj-«QêL0Yv‹Ïêd`ë«¢Ç2ë$F…4µÇPϰQ2CœíôHŸ Ô Ùíd¶‚8K­£eæ×ýv‘ ä Îuð Ê÷“m’‹ÁÜÙœžµ·-ª™7Bíÿ=ßsû¤…I[ëQ[ª;_&ëÙœ YyØ„µê–©n•Ĩ]ÍmWíÛ´*µÎ-ðéývú-»Ókú-FQG _³e¶l:ÃÚjò ÌÕ^wUÃÚFÚj>”ѵc÷8l¥¦"wØ¿îKew˜…÷«®÷rîìþtí` £.®›bÇ¡ˆË.Ò6=U5Ã_NµÆTXÖì]jn¿ì~ºQ¤`Föߤ©Áa„Ý_gs­K˲K¾°ß#°×ç›/CVãìð²ˆ=‡Ì°1.(Η›â¦ìóFr´ºÒñý:‹ÚX'ê i…ý96¯ëÑä ®ÇV¯Ç·D¨@f^OF„¢¾ß¸gÀ¡×4Ô¢}§¦ÿŸvÉq³ßÅ.9nÕŒP4¤wœcTˆã6e5BE¡rXC¼œ˜«äÔ²¤yfk¶ ^„š †lͰµ¬Éc³j.FCg$:ç snÎÕŒ®‰Pl77WQu‡éÛ-^eHÃì(³>$ºáÝd1âگ߾K­Q¾a'3[œ³ú¥Y—K„¢ø7n#Q~ Ó™Év~á^QY‚ºÿ~Þ)Bš 3òW7½†ø…3®wè:_9 ‹D(2Iƒ1ô< ¸œHí¬€Ûgr|÷E<ü‰dµôµ7\ÙH¨×éPÆŒVsûgwò5K6Êqjî+£·p¤°iÚ0ê*RoÑP)£Á(ù_Wºô,«o)Q É=¼_Õs Æ]Ü—:WÀ̈àÿ.5a–žîS4d"+…Zä› ºÕ8*­·è¨Ï,¼`˨W´mŸcµ@­èîÓ øÒ,¾ÜáéGc—ÎBfqN3ØðUÔQ&êÕFe”ÀàI§òG)a?¾Ü/.ÔÁÉÊTkáËý†E`ÝOí'Iès w¥¹ëq_õ±êp>ãèP\t<סGÔ㢫;šÜ*¼b¦ŽU7Tà¶Ù6š\ˆ =¼4Td{mÏÀ@±«,|Yù#ÒôU#‡NŽ+A…¿Ê)¶kU´=Œý¬êÅ(ÿ¡µút]×ÔQb¦|©² †ð»Y=Ã'Þk™Uc"'‚¢ŠO¹©€—E =#¬ºCO~·°‹áË:xŸjëàO±³3Â6ø Ú¶pF`ÌÒ‘ã<ÌTuí¯9”»ƒ'ëù]w®Õ}d‰îX‡lgG¾íršîïþ ÷|&¨€g*Ý.1ç#æ¹ÿA¯ RÃm/Œæ…^Ë£vºiŒy Ç—©-÷=šYºè¿A¸,MßùXuðm׿­ŠKöG…Ïee¿cïFÆxǧG±.£ZVYEPGe¥ Q¹Êb‚ Ϩa,óOÅ\öß_Ͳ$(¢¬”ªËˤf›AÔQY LjUöT7ÔÃ¥¿”äCÓÓ§’¸ÊŠSœ®SU·’ ^tœŸ«ú~yÞêí Ón°ëG`ôb÷ûÎO áÓÍy5‡«9Ú™à|áŸôò,DÝØíqbŒê£ËÓ¾§¨ðMQ¦¢š Ø¯±kʵ=q¾GßµPLh¨²¹vî›~$÷4Õå[Pª·¨»Ç–iIæ¢îÛ‰ ‚ƒÆlÓm þ•AòGW|¯y4­ß˜ Ž ݨŸQ.ñL¯eQaô»oõÏX€h¨³À¢Œôüü·£¨‡[r¤ÀV2ãºQ·ÔàÝó ûŠÎ´ÔÝ[þ6)¹¶`=żÉž#çW4Jl$1..Dþ”aüq!Ú£ ã~áÇŸ02£CÓ°qÞ¥®b jHŒÏ^âÚ• <Ö4#Rš˜¸_DTà$[þ"qw m!Xj¾mø‰u;q“‰àDC‚Ñ2­MãÞDü†ÿQÙÝdMײϱ,ú“ÜT†×Z§dZçx© *<m~ÖŸ¨Œ†¥¡wd»Ìœù:–¾«£rÀB†ð„šÞ‘]7¸*‚ò7¸(êÜà’´Á…(¶¤L2Ý.k¾–eû—à§6H‰dQYÊ“ K‹îmè>c•|ªwŽ)Õ¢Û‡´9B=MºHÑ;¨¦¡ØlÙÈ"q44Ø•ÇbŠ>²ÂSAp{Ü Pí¢åçŠ^ë±ýƤG¡êli£6ë)êé(?FZ$¯Ç÷õð)£aíŠ7E‘VŸ^_[IzUn/úîÚWLˆË;bhH]¯wì鵎ֲ[¨£É–K½àÓ?½-¢BŬXÏ+ «Ê ^z{ ïþqóÚÂõcP÷K W ¸dzömâ ]êX³ C‹èj žb¢ù¯OQy¢«5§^nsêøôÌ;°®6œÙÉ!–_êüÃ’áƒûO¾È¨±÷ÊëàK'q%Äjþí“vè"o£¿iž’=lÙðø.6û¡džÿ¡8ž‚ IÅN‘f—›°¬Wt¡i{Þ® ËA9Ë!,³çíš°\”Ÿ°LQ^ÂòBï(L¡ì¼­b¬ßŰ|±Éò¼_ŽáaAŠÐ-{BÛ ˜;^‘ }…=Ù¥t5¶çyÐ%]éèóÚ¨ÓѧϨ¯ F}̲pµíd0M~>ü¤]ƒ=Ÿ—vkxn?mÉc4n’µ¦*íÿÐËÖ93£Mù’¯}ñ%(ÒþMs|_ÑôªATH“首†¢_–j£c°×Í[NÓ±/îr¯ûU¼ŠƒÞìX6vÕ‡4Òð\¯Ðoø[9/vµßOø½¸¿•\ô(pÍ^Ü'²üIò¾ÆLçDäÑ÷Ó׊‹hž°Tf.m2}©T&©”hæÅÝç `–,i¢²ŽwEPgëõ©}OßmàØËnãg¦\Ûér-î¾?ºCμè±=÷²•‰`4c4Ud†Ü¶x´ˆ)På·Û%1(Òüf‹^ tµ.,æé÷=)6c\¨Ÿ«~×3D¯—Uœ7ÆÚª êÍ[}Yq¶ÞË|úörÆ3íõ²ˆÔˆãôûɿߎ Ø‰ ×6Ñ7†Žñz¹3é6êÊï°`ãíõ:k¢n+'£OÞÇô7L%·fUoµ4ª*ˆ"$*$Íæ}$Õë¨ès½LT‹á}^¼ßïbUhLßêÍç½ I~»ö^ï*‚òz¯Ã¡ÆowŸÐÙvTxÇÀ=Ã]MÝ4µ¹Vèð€Ù9MK±TpØ Ag)T‚ßPTèä¨'ƒ-“ß.¸ •áçÁ/'„Ío—bÓðÙòÛãJã¾®uá«Ã?n¿Î†·«Š ×FÑêPwÛ ·€·€š ·´¸a¦ðû…?ðîÇÀïw·‡‚¬ë¦2:üú§ g‰§®g…êÓTè™\F. ¿{|"T0·.úD ÊŘY«ÉÖ!*t}ZدÅ/ËdEOP'DÆ"~?Moc8®á‡ü=ÀŠ&ÜÂC‚·\WHñy`ykÅØ±)–µÏª ¿GÂrÙýåÑÇr˜V”uçw—]ú6}VFY6çˆzzDۻ߸ÈzÝ\N™<¥íÒ³%[$AíÝþÍKßQ;p é>KÞ+6[y[|Û6Ÿçš (·+'*LS˜¤wt)óvš]ûÄpkü µPÔóèl)ë-sŸÍ€z:|Ṋ¥G7U¾³•v£ä>Ê(ž:d“ð]vŒ¸n« >]ÙÅ‚®ÑOЕw· k¢‚9i]¹å øCéµ:7qCPáIöu¤²¯ˆ:2ë€QªVt×A©Qüàè¹qð[š)ÜÅU­4Št%(¯Ó(ð£xØ!ß.×VÕ +¢ØA„-ÛQ}w§>]p"Çk¡6ÃŽ>½ =[Ó%þª4ˈz¸Ï4=õ¨ÐúnDIt#xÀ®u#z‚ ÇŸëqåÁgN¾àéî^Ë­{=âÉGÝøažRÇ9kTwœÝ–Jâ¶Ä wèdã1æ ”À9áýïïPDÖR‡3$£üÇ :Ú|¢ORöK<™42ìú5—Õ{Èr‚ i« x‘.[cEPl÷ƒ7j{q­S7áÙþöœS)PnøôfÏ1Ƴp¿S[æx­s‰gË+í eErµÁuéa~«s%¨C!sC­ë:­¦—Œ¨Îô¡õF×¹‰C~\ÑûɧãP‰ÓgˆâgMú.Zj¥w»sf ú—˜+ €7™¿Øu5žÈ¶_$Ì$lzG˜Ø†‡sfaœ3×V4a9äh±)͉Kâ6n&Ku„üîûh (§ôh´åD1¸5*ððåÏ*•|Àš`· ³¢Â€ð}œ<]Dݯyº’ Î<ÝŠòt9»,S Q¯4¯M(Ísv²(ÌTœZC•*¼T{ÁwàÕX'ŒÎ($Aí‚s>¾9kÌ(ÄÎwkè|h0Úœñ+í“é0îf>}P» &(Ÿv*"Jø&.ð«eWÃåãìqÕ ªñ{¤Z['íNîçìåñ×ÔªœÑp@nUÎdÀx•yÙõ•f×c,÷#œ8T9×UÒ;r§ÞæÚ#Q§ƒ¹¿vr¤Fä*}%ì…ünçîèT¢î™ô8“ÌùÝ.¦™™äµËå~GBKù;LwÃ[Oÿ#(h)”–˜; 8UqÀyðN~’¢˜ J|êaú¬ëß麜ÐRlדUO.×õt¸ž¬úÙ ú_4€Ü]ÅM]Ã\™y«7·¥gQ×x±àŠg `!ª•¢Âצ/µ}iMƒ;áüõ·¾ÂTôñlÞWèãY€Ô¼¯sÛWÔnœ?¸Ÿ£·›3ó‡¸6g¦(¿9sMP>sf´õæÙ°¤~9üñ¸öË¡(¿_Ž$(Ÿ_΂§èã$„UØqi#-YaÇÃ*Šš’îØFÉg˜ßAcÀm}EÅ·Xó¾HQt+'«ûþ;UNïÈ~(,=ÌKÔª?˜ œJ…AÚãTZ>®}›4€p\ Øà ± ·mâžT@¹Ï„ÈS±49 ÙòƒaáYpáçíBps€EÉŸ7k—Û}Ûꬖ# òçݒ±–j‹(¦(ëéu’,Õ«¯æl!¨ðüåö¡‹ÏŸw‹ž§FÐ5]êÆ<ý±³}ú´š’t-&2æ?¾ŒUšïÖâdþä½lyœh“ÇY*t¹·.ù»‡QIþ ÝCDZohq‚(ç»—³ž@!¨ð$¿$kÙŒ2ÊJ‚:Iº'Ý„EÑgxÎÜÎZxõQ;¬#ž¢Ï£ëÜÛlÒzš§” ìÖ *¢Zs*¤(ø·‡2jšÂÅhë'7Ï•&m$ Š»Çìu‚ „{̾[¿ñáÆï€ƒ€¨§Çn¢À\áÉÏL˜åhw» þävjŸ“å³›0éï“_¥¬…ù:¸?eUGß%Ü xó')¿Zu»¹Á6’ŸµEÛàÏ‹rn–áµha&<àKëû¶Ž%’k[«Æ!Q}éÐdx­³5(Š"×]ñQq¼Õ“‡%î9²Ž‡®Ž»‚ Î»\qØå^ž]®;ìr/Ï.×v¹×ýÈ£>šÊÊcà¶?-†ï7™÷ßÚì;”Àî’ä[¡6±K l<Ó^†3»¬ q¿Äú.Í_âÒ\c9Êí:Š5ëø¥€ùËÊ~‰cQý·"¨Àé64NøXŽø¬ùëiaÇS s3Ä3žî™£¿íZÀ–)ÚoÛµÝHPÁÁÛ ÿÇ)¯L3“²£lk(”‹ÛÍ˾S²­á‰m>d)êö”eÓ”y¿QÜ,µô7Õ%qç£ bHTÛ¾£ÈL?"†t@MÓ;jçì€bQ÷­¨ ‹h‰‘E‰(îC-=A‰}T2MQñ©PQšJ“ñŽ÷ã@¥A•e¤²Ñ&ˆ¡P9P5Ô`Ä”Ü6Žì>*·²îÈN¨q<£~ÆAIŒ®`ƒžÞ1A‰Ó[-ËÃ[}]üÆýŽTZñVŒê†T~t±D iËEÔ„Øž+{g1A4ö…hhK6ÌCCPá!BÞªÛ±Tã\õÅN(}-¥ß×ÿt”¶©4mó<Ñ’´E' J8ŸKíаG "¿t~ú÷,ñéŸnŠ‹¤q³$GL3š´5Ï8i)ÒÐR„íùiÑR–… ˜E«ÛØ>šV®sâÚ¼`4 WA¡Œëy!¨±#M6†^¾®U‘õË€k‚_I¾áž¸ß½rÇÚ3\êÅݶˆøµðæJE %AÇ2?´úõdÐZ÷“_ô>f/Uˆù­ й…ÅÍ솸‡—³uEPÇÆU«µpjQPbš]ÏÑSOP¯îk¾Z~Q÷ý~$EQ’[fÌ ²lŠp}ݹ».‡ ÈQâÊh ÉŠâ.üf…Š ñZ«¡†»\²Èµjëo¨ç©iˆ$·|èǪ- *p7b FÜ_~Ù±,ÃjºíÈÓ–E…… ž.­n?··²âÚc&(²Ëau¸«Ën®Ì™Ü|NÐË`(‚û•@ Epž[F"L›gkŠëëGŽ:¹ëþÄ£Ä8äöà…¯#`çHtgÛióy”EãÑð“],ÓÇXÀ "`t–…Zׯ%<Â7CÿëÈàq’ÀFQ…Jkü‚¶ŽyGl¾4[UÆÑˆ ¨Ô´AÙ€a òDF:F‹H‹u¢(21š˜Ýw›¦IEè2  ÿíðæ6PéâJ%ÉkÑÔ™ 3náp-ælâC)aÉö€¾L¶M–ñ\A#ˆIŸ9EAfRŸÛÉŠ" üâû”º8Óe#…Reõˆ¢‚RIN“'fÒP„gÉ]Øåê¼–M\âoäÜÆ¸QPêÍYŽÏDx²uÈ éaQÙ1dÛÛ§EoR÷¬¢6"¨€ Œïw§Îöè»THeÇ 1šæs¦ FEÍ~àŽR}þU5} ‚òdehÛ&BKn/5©OYÅM´P”UÙDæÊdíÊŸ~ÿ†þþ-[5 Þý*uì[ànòäùÑêÒMTí]N‰Ÿ «ò€R(‚Ýlq²ûߨŠg/–ð œÛ?©óñÆ‚Yæ”@WÖ]ʨ©ÒQ~*tËí©Pg!(ß÷ˆ•-á'ÕôµZõɇ |ýìe BªqÕ¶;|Ì]ÛÖ|‡½¶-s×¶»ŠÔ¶ºffu9@ñ“ T‡Uˆ¬³€ —(Œzñ½ì*$Ó”h¦ÓQ(ôE ^áKûÉ”äCŒoÂ!5½í«µÊÝëwÝ™vSGº=|·æ²Ç½Ò)•Eߨ¼j7¡×b´þ•cýKí—UŒ+çqª’QFîìqˆ`È\©JE—Þ<½·§£»(°,Ø­N}+^Ëï>íóÔ‚ÙC1|Ýò.—1•°3ñ£8ìf9¥Ÿ}ûä+»¶#(2‡Yºãgé˜&¸eܨ÷8 +vkÔ÷¸›ðÛ9ÎEøí=¾APT2|Kš6Æ~X`DBü¬ü\Üì? \tSO<¼Pì0Ú%‚û³“Ng'°&øUv²ò+Èç¿ê‹Z(˜› ‰z‚ Ýy¹ìÝyAØ2ŽUˆ$]A,óN«P­h<ÓˆežƒÒØá7ÄþhhÞ£!¼9ð:ä¨vñ%ñŽO7¯C?h^GMPg^GÕv¯ƒ^ëh™!å¿©M=‡ð`N•‡¥7•ƒ±*Ño Q¡ƒ¼n´àŠ Ø‰±¡mµ¶ÏmC‰›Ý“Þÿí¡Òñ/Ay4 ÞoÜɉýž‘sÜþÆO“vé*WX9â~}„X“~lT°³‹evR[9îrânMØZv…±Ú\ª—T¯mÿ%¨À78‡§‚ÜbIÅ…/*óF\QˆðJ\9"‚ð†¬7Qê7žLÄüKðŠ¢âý³úRhyÁù^æ!CmD¨*²2{¨¥‹Ý„;5¤‹‚NœdfWXÃÑŸùä®÷¦˜ˆ5]i6ƒXEêœÔˆÍˬ¨‹ _k3€úƒµödʧ¼ Pj®.gyÕA4Åé†>ÿ°Š|Ètd¼ oȵ0yŽ*H'f×5ãÔåˆÿ,*Ê·--„Ú!Ïí)ß¾ípA¨“*Iª×¯(jäkÅ×úݭǼ«ž•åÞ¹°|êB4 „òls¼íkpE„p}¤tzC"B¸>2nê=3»d¼*vã3ÿ`Þ˜úÔúu]¢lj›…ÿþ­=Ý(-—Ša*?õ.»(3 ª:eMÜÀýmÕØ >fËœ™$ˆyãÓWŒvwJï–ëZ¯’‰1+µÆ‘Oé Ïý˜«W%¤Ã6DQmð±EµLEµ¢F(Ǧ0çVÁµ!†iy5YÓˆsýuÎsmHYDDŒÁ¾\ÍŸçÆ&‰’7Œ5”`á«­335~_aÛ±ºÅÏå!o³à‡ã,'H„Pþ“šÅ¯kÖ ÔNMÝé·õœáX³¡èÞ"±M|MãI øZÖzÑuëeU~r!L«ÖË:ÔŠÙŒP§ãšmR$eQÔ¡Ü“ê(àI(ÕÉ:Ï¡vœñ‘l×£/࢟þû"D'÷´R£ì*TKÓ@±ƒ`ª³RMòlÖÊ+G”jÔ¡Ž ‚:' }¨Su%Ba*¯^'’>/Ú>Ôœ»á]tcT$Ç×òöen—;ïûvMã彟š6#òñŸ;ËV¡"6E+­B]êäCô3䃵,¬†>6OӳѨ‰…ù2då‚PòýÕ 1àJ±n;Býn(%Ý),óôôä1¨[åly8•ÍÜãçòî¨>œ–f.9Bù³p?ð ŸàyÊçn†¨$äûy‘;7 1äû½¯r[èi^}Çï%ÜÖ«|®y —fÐÚäû»zðêðQ¬Jõ¦ä1B¡’)ÕôãT5à!N0ëìÁÛ³†×šèN ½m9ïY(£ÚE‡V;ëýŠCà—S¥sh®uÕz1úeú¹º¡œsÑJ‡Û-ãÌÕ¯wÓ쿹sðHÄʽP¨äÓuXåUØ"Ô¾Ùê̦«&*6€˜6 °++ˆ¢—S"7¿F Á¾“ ƒ"wªjÑ¥rÐĶƦ0=–¢a%ËÊyîêÏ ‘•|ý×c$ø†¾äMø}áB9¸Ø¡Áeð;k×¢·’ˆNl‹;êäXª)zòZm—3Býn(u­+ÊâɆÂPOÆ®ãek)é–¡ˆEQ›±^\lMÑ8Ÿ×£2ØÓœÏkiæ=¢œ×­ºŸ2ëu{¹8þísµeÓÄÊ>få3¾´–%©È˜‘ Òö:)û(ÚÀ"2Ý"AœïÕ¶í°Kóž÷øŽÞaÀ€Z?MÓª2„òÍ8béË(O»>¨³gËv­fÌe®ûãA…ƒ;šyÇ‚ øj³·yŸ#K¦p Y¶4u˜¤à%SM2”Ëx¿ ”{X€¸j%—›JÄÀPÞÑÚ˜ÃP„raêÏÏåŠCð›¡Lò$Î2„"XÀ?×î5a˰ ÆþZÐAIrÏ9[ÊA‚¨º€/_fˆÜ̯³]X?ÈñJÓBŽª¦ŠÊ=¡Ôs­UXs1¹ó»Ì xiÖmÉâ¡|4st)WÕ±eýŒQä†J»º^K1„¢èmC0'ÿ£ÌŠ8BÇÛÎÁô³»jàËiT?»'E Ü®xÛ6 {<ß/’…‚ºÇ4íb<ú_çÐ…«-Ë8NEÚàŸùýíó´•ÈÔ<,ªx9]͵šåɵo ¡j³E(çù„®Ë šÿÒÏÞu£ÔµþüÛ$]ݱ•YU¡U£‚'žKnx.f,ÈÓóýŽB!!-XêÖµ.Šc±¸ù,h’.îÚe‰C¨CÈÔ,uê,£Ë×qD¨Ÿí7j> ù}Þ¹<ð"=›FüÆå1˦÷¤q°ûýÀHüÞyƺ~JÃó^¹ê€#I~]DlK[EXgƒ¶$&˜o Ui@…i]BÏ>¹ð-w ɪ›êªÌs!Ûr¾ÖØñ’ÈŸõvÙ¯¥ä(!¥û¹ÏÔ2mmë,›à7Z'¤ØN~ô~®Ùî][¬rѨày®no2/åØzì v_;Â]$H,ìZy¯«–Aã~­•÷­Ž$ê±òÎwi8‚ÅÂν êÄœA`~±êÛ]ºT‘bÍÊ*E(çvzbÓ¡@¨ß­,¢ÎPãL åžÊ"9ܱN*íV(ï5¦%¾–ÝÖ´ mÙ"š’¡Èݵ¥ÏÃ!à{Ô(j;9áþì^^{‡ qí,ie²÷å<»‡í…×{èÅÕ)p:ˆ¦Ô!‘ûâÒ•e&LvÉÕd|£'Ä}7æõä ŠL£õ`-i4 ì¦ÑøŽÞsän\§È Œ¦Hüw&8G(çvb®ºYå`@ÔqÑäÒ3GeQ=²²‡H”\ á`z\ÚªTBZõ;ñÅ·9¡Lçʺ¨ çôn•$kš,eÖ#”]]Æ‹¾«+–eõ#6ßл1d:‡Ž–YÉ/wä<í`]E:ZO®Åæ=Züˆ;Žüˆõh7¾ ¶ë;ÒÏ›¿.t.ú}Y£…‰Éé÷Rê7G¨ežL¡"®ØYÁ(îUÿTWèïYÁHuSð)Óbù„>ìiZO¨Ms(àkýn-k´ ì¢Ñ"jŽPw½Ýõ¾À{D¬¦³3 Ðž¡œƒ ÎôG$J–õ™YsÎÑfžmTtD×±~a'”sò°Sm^§+¿k‚t¡þa—Ô)›ê¥PŠEì´Sat-¤]Ìú…Øiç’gVaé¾8‚Øi .f®i˜§³˜g„òn^ª=ŸÇtŠ"|-ÿö§|¬~#yþm¦KŸÁ:AÉuæ˜Rÿ”N=ØÄêúUI=­B–‰¡Žby .p]‘‡µÙ€P.žnþÌúms†ŸÞ?ÖUf̰ږE òK.S¨>ØV$ø¼  ÛŠŸw¶G(+ÛJ 1Êζ*ʳ0O¡gŸ\¸uK# Î[4n~$pžýOAÑÖû>œÚkaç ~w›+}´›J˜‹áæ;Àá”GZK€çy/•W"-ÒŒ…;PÁßmåÉÐôð¥®UÄ?”[¼/ï–é@dÕ/¢4k´]ûJ»ðмpÏP¬#}ïÆïʱÊ¥úë‚WC9؇-èÉPÎ̉À¶+l+¹ Šè]fßÞ3é~…³ Šè]öù¥u…׬Ž$ý\<^M<¡Ô‡³Ü[)¢w]ªë “d½ÞÓÏ›Çë¹(Eô®G} ¸Ö÷]_B ”]_Pγ¾Çúir™ÎÝñÖ)ž1˜ÉÐÏå°/…>U‰Ê[™-å ”> S5÷Ž Z››~~/ýg†`@?î+Á@Ç_ôs6c€³]ÕyÇÝ4ep-ïf ²%ÒU3ué\kMg@a¢ˆ¯ªéºŒgÚ>Pêéÿj•ˆ†’^þk„Àwtc-£‰*𱫢¡G¨c¨tÍæ¡üý /Iô¾]ÆýºvBàk‘ã/×§És/×Â)%BQ„Ò´ ‰êÔIF)çIùÿƒ^LÉäæS»ÖºÃŒê—Óõ4TurKEŒ²£ciIxØv-C(»ïèÉ*rù¾'|­ß½õgèxvu„PîS©¹ÞKÍôsmÆMŒ­lS¨Î«¡Níø %0VYij¡~w)vܲK?––][vé‡Ú¤ØQË.EL·“Õ0/³A†ÑšÅJïl§ô3{H¡ùJô\qà`—"æÉÄV„ú¤ôt „\¢ËA åÚŠÛzã¦ßÏ›ÁbPÎ+Jó¨è÷{ûa\I5ò¤)âÃÝqB¹—r„r,&|”û,`±€ ýº/MfK¦_Ͼ%+m¡,ÏÕÀEÌ­‡ÄVÆ¿åÜ…nperè êí0Ó'ôK_x&ý¥ßàú¶s­È‘å+oœP,·u5 ïDŸê;:vÃë|)òü{’¡èàZ¿WеG(ÇfàÜÊ}8~Èuûœ|Ÿš¨@ov´² kX˜°–:ÞÍ.c[¿Vùñg2~, ¬Æ<[+ïuš (œ,˜fÆÁº ¡¼£ÌŸa•µR͸¡|›¸Z #á_%RåªÆgÍ(£ÈÃ¥¿,Oj¹]10J¦ãÌKêºMØ2g…ÙVz-¬dŽ\EPø”{³fælâc‘iF, NIò6ªK?uÕüwP‰9Þ©(ŠV$©ÞaZʲ½!Ckj§!Ò´Á¨“PH¦û.§´ÉfÝC@kû ´ÏÉÝ*eå< „rp2 6õÉÚÆ% •ä϶»CzÒµK?ăn¡HRìÔz­¤ëwé.z‘ÛŽ‘´ï\_Í2c…kÝÖ]zp£õ(Þ§×°š`°Ù´ žË}•Më8BÝeÓT™l—M”U6ít-÷y]ÍKæ~V‚ŽD-ÐhO¾=é“;Œ>P£?ò¾Ã`Ô“x2NÁ°ÞS V"”=Êž‚õuOÁÄ)ûÑ×lÁ×òmâ£æ VÊ™ÜÓ:M¡¢î畨{‡û}vå ÂTK°Q÷v¨ò°%ëûrš:„z–˜²œÃW5óô¿W5]¾”ÕGMS‚u÷Qà£ÆÊê£Æñµ¬>j'”ÿ<ïyûë>7ìL84ìQDK9µÏ‰1Y.–Ôõ,¢6«6‰àõ j£´NEÔákYÚ¥³ÕÜÑî­—ï®yKw©¹jsSMõ ”3êÒ‡˜)71SWŒØ;vOIê½zJšb–µ:Ä,S[ôLâSï"¨­õN¾V‚3Å¢\g‘–E‰´ÀW‹ˆ07¢h·æuxÎ q…ÆûÙŠµa'—h]¬¥žk£œuÊöS;úR-,AÌH¸×P‘•_ÈMÙÇ;Ë5cšXÊ¡¼S–©³¹Ž%ŠïŽPþÍ8Dæ|¬!KŠ<¯rCÙÁÓ{WÛ-¯XuI—p vPDª9üÁ·ñJ“¥Ï´[7½a´­Î8Èé•„|D(\ª›¡*z. .ÄætuÔ6¨•C1sïè{-,˜I†i# „ä‘KÓ>œ?ŒCRp±˜;ú§x56Ýc[w/gŒBG×ÌTDäSÕ¹Ðå(ÿw‰™`NȰ¤ÎçFSo¨ÿ»Ë[ÃÁU£¤¤K„ÂòÖÌ4{WuVøŽîÉiÄ“Ë(øgškd$fÆ!Våa£Q¾-w—QÕPB\ˆlÔÎ?¸?ˆúwá ]õÁ?Ëm=õôp„úY{z„rña€.еGêêÊÍÖÐеà7]m c½Ú³q¨'>ÌQP?tˆÏ`T§N&:æë Ïx¨ÁÈkÕ ç%¾£·£­ ©V&¹°,PÈôèù/I¶Å„µ[Ý„iÚ ÈÍnqŒ‹Še‹ù¶÷fo½ÞÇ©!¯¬¹ùpA¨à@ek+_ã5ífè76£ú9ie«¿–µ‹l}ûâ:™^ÁB¹þm“cØ‘&Э.q™ûlư߹;CeaU‘VÙ"ð/€ˆ‡É¯›´©ï½N~H°ê8)mO¶6ýÈ‹jÖ?qØÐ´ÎÍ´6Ö9M~Äߦµ™üˆÃöï¿£‡@Ý1.ënB¨ÝoiWÔÜ”¶à° |®á•ž°]"ã…¨ ·<£&…âå0#Ô©òž›‰ÏÙ0 ÔÁÈ0íJQ6šç_˽¥ù#¤ùBy¨ËF—›ç(ŒqßÑ?Цãˆ7i7ŠßUÞµU_¾È(Kù-á;RŒÚ>Ê9.Ö°®Y†PÁÑ •ë‹EÙ4ækÂ8ÕÏ3rÌs!Ÿ¾Ùið¿¶ædø’ü[Ç t–0¦BóY‡;6Þœ¾–)Ú<#µ:ŸIÎÉÇ¢‚WnÒ<À“ï j£ÌÖ‡sÛµì™I\É÷vf®N>d¢ßÉn}”|¯:¾g7[xzçÙͶÂn¶”8Ïn¶©§¨7[zu©<©5ŸZzQb;…aòKƒƒò»¨éìJ’bS’\ʱX¡Ï§k».6ud¥S8 p„BžBàt ›®ìê‰M­Ú“K8·EL½'ó½WHˆ÷êÁ'ŒÄ{õà9ÝÑêÁsBÝ=xäšyxðÊ·y)™çò_½” ¤CÜÀ'/¥Óµ¬^J'ÔÝKI~Û‡— < Š,eõ‚;Òϫό*ý>û åCÚï>C”Ï>CÛØŸ!ŠX'§U¨Ü}†(bý}†T9Ó8уõwñ’£pEY}†rŒòŸk÷¢ˆãyzã3D µŽä½9¡Ž½tÕÖ2Ŭ¿‡uâ„:z WD£–J ÔïÁû VÞp¬FÝçž7µwt¦çRï¿Íaï þíP;7¤ú¢ä͹Á”èÝ î8`,Í#¥oŒ%0ZÕÓz¤ôGi`ç[©~ýƒÏ«‡¼!›zZ‡».(bxmœþD/ryZ&kX¶«N»‘zšŽ !R˜z>õ嘷åœRø-×i”qzP‡©IêÚ8œ›4Ò=o©§ýÁâCíF2†Ôj`€òŽ]öÚv©Â…¶  üçN¯ÎÚØ˜gÚÛ̯À}înPB3I•ÁŒ¼W¯Á¤D(û®ê‚ͶE¾v:2 ü‹ïªÉ<”¬PY¥#B97GÕ±ÌÃÿveɲ¸rK‡±ŠÏ^Àè-0ƒ3Ñ«6’ ¶ß‰ó™á¶,¥2Ó‰ã})žé\3Ž©!(ŸhsI­ñ b]jæd&¨@ÖQ2ßèc91 qßè.‚5MqŒw|_Z|sžÚ‚H3’Þë,['Šr_I)Ëù„_D%Ã4ÉEX£#êü÷J.ŽÕLQ$]^ÂÓÎÙqtS™!Ê}ÑN e[LÝV–ÀÊŠþ,JÞœ—°‹FÄ)Q£\Ç`½þîÒá: «²Ÿš&¥¨àš tó`M“ì¬Q¿èÙüÈPC9úóÌÞŸ•¬ÇÊ7é« ùµÑ_`¥pD=Ka¹£Öc—PŸ·‚jB3?ûè%HEtîg¥sQšŽFç^Ýãרs?ÿt¯^}»¥êÛÑ_ô8wÜÔ··™”«QßC¦È¦Žþ¢gºé®¾MÇò_™˜j:ª²™û ‚›ì˹F—]–ŠƒýEˆsÔ» ô¡!‹ª,"êsÓû.±ÔÎ (?ˆú’Þ\1åîÞÆ 9OuÑ\õ7m…8è´ðNèèC¿›)ˆ¢=‚¥âR.â¼°ŒåݘÆjç«yLãÈqqá×òrÊA¹:ïâîç]ZÓ«üþS>„¥“Çz+‚bú—Ð"'´Óf‚"úª+±:*ñA¢2rž»B•éS|hfÉNP®‰' iÃèíü§äË„'9p#'2 ýÅüÇÈuÌBC¡¿ÈuÌBsÞB 8ºäŽ^~§ÆLPWê=WþZR…i« P/½Ü_²f3ƒ>îÈ}kÜv/—ÉŽoŽk+…¨ ¹ž¥Ì=cwVäú†Øk%/v&(×ÔÅðƒ—CU¡žcû¾mï•}Dé·A^2(÷EÞŸÁU½©ëad¸FSZš®vÙR…Ú$Ñ¥1_Zš¡(Ò>±´ß ‡(ï¦î^¢“ÊÒŽõ±¹–Å '(÷ñ˜Ä_‘ûy×!3{aYË6T‰ž>|?þöPÉM--ŠŠ5a)¬ñ¥´³$(ïb-c„XGòuìb€(ÿÎm–VÖ qÕlt¬‘*Sëý4ÅíØ"IQáݽ\J¶–kÖñW_ï•—ûéj/lÂ.ÎÈ{ V°”ý—}šR”Gc€••G]d~uíy×_×mvLœNE¤¹°;kG¡nG'tDýrÍÙ‚WÆ|óe“æ*Qš+r#¹®=ÉuA¹/r]ÇuÝôEBPš¾«:—ú‰=Eù:9­î'§…¨àbÅã¾]4q³Æèù¨P£Y_šUˆúÐêÉO·{èBÜïK+è\ðÅkß-ÛõšˆâÈ €ðªJJ‚Ò*&ˆSÚ~àšãÝ:8~}RŒµIù‚OÛ·P·X…«¯÷è[€êÉYe±ö„ë—÷ì%Ư-Öx.QÁQ.!-C  "Ñ´/cP™B”GVò³þ.KùYÇ68§E„Rö¢ÄÊÓ‰ \SŸ®…Þ×êG¶7¥9Íâ4ÇÔi΋Œ'Š‹|=ἠij¡ªâ QO=ù¼6±PÔUtΰ0Nl­×ŽQÔ"¥i©æãþè;ÆŽ½+‹ùf:Œ$º`|Oh`Z_&DùV e|Ž~ðpK¾wãI‡êû<~1Îù¼à=~Þcåä©‹[Æð$Mô}Þî¿âÙ”g=ž&¼®¯^™€ÕR™ SÏ1Ò+,S<ÏÛ\q‚º)`$Úôs_ƒ‡+¢¼wætoIJÊZ:Ö[™ —Ø$[O¯ ò_ÿÔ¹àKý‚vKFPáK3EvB‹ï Èuñ-¼©¡ð&ÛÇq¢àÏÜÜ0Ôù¢ÀFÃ?~¿è¾º³Î±Ä¾]¯ :ŽGÁÝmôT98O¬}•çz*G¯!6*רµžáp–´®±¸®Þ5–Iר]c£‡×àyõÐ;êUùðêC«ŸÏˆ3ñyúæÜü|–‰ \“ŸO¿”GW&h#ªâCž(ÊèúÓR”^¿à'ö_›úÃ}(°Tˆå;÷HU€tZz0÷¡cQÒ:f\BK½c.°õ'¢t«wSÊl…ÞƒŒxÏ’áZZ}1GÎÊ5Üù—ä¢\ŸÕI¹î0#†/×28w ëщh!!¨‡—%h¹HñŒ`Â+Ð ñÛ?¶YåjV­^Ï¿Y}7$`F7?†MÅ…aôöÏ•…äaŠ«©˜ ‚…O¿ôb&×òH`V?÷>[êÍØ²ß/¢Üse}@Jþu1Ay&ÝÜ·?6ÝŽ u;¢óªÀ¹v–Å$‚FŸ§$ö²fîY¶AÝ©x’žÊyG‚òŒ5Cœ‰g;ÅcVåÛg•Ô{Vù}VýwåšjâX»(E™µ@ñìZ x_»(¢B[ä®Î|Ÿè¹C´-"÷‰«ÈêÕн#›ã‰¥[ËÊ357àûõý3(äHbö^ânõµ³ÌlÝŽŒƒ¯Îqéœ .µô¬_¤Ú¬NåXß>ž6[CP®i½ÇxâëÛÛëÈ·½ãZ[ñÛþ~¬Ôy5_ u^™fDß]æAæ}ë¬ã 憾¯µPµ%g#céÔ”«Ó‡†ãàåÑóÐÏs>Fd¢·{f©PGÇ3A™H¸¨¾  #¢`òFãm,mlB≫¾}É£Ÿ::âXÛm (E¤öûï¿D‰æÈ*B—·(zæïQ–¯šÖ8kâv”ï3´Ö¨nžf •G—êˆ&Um1Ñ¥:¢4 9!Öç>á fɈêj[±íâì|w‚  «H]\ úÝ}!Jßõ}‘1&?¤$å“+”kh.­+2x˦lLÑ[V¡®È=Ãs‡äúŒ;8{+”gjޝák }SÃXŽóvІç(ÞÓÎ0ek»BÞ¹B¹·ÔÓüs–Íì=TJlVK7ÔíW?Åû”§S}[Ä„Õ;Aùt&~ó5ÕÕ^TðcÞm¸aûGCP¡žÈîîĵ¹dŽ’m¬IA¹z)Ìû ”{ÛE;úiÝYYáuyO±lg(ñ‚u;A¹¯¦êÓ蕼_žÿ`ñdÐÏš¥I\¬lêú†”ÏÅá$O‡ƒ îF¯h›g3Ÿ'‚òo®øuH WŒø‚òµjÓǼaíFÅvúN„ψ/CžhÉûfÅhÛÿXû;ÔúÜõ(ïò+*à-ò+ã|C™äWFÈþ×,¿Â¤C AäWªƒÑ_4ɯp\s|ƒå-ž¤1^½É‰¼tð¡ºåü¦“Î.N: ç>ø³9 AF +¯v€«8æü4–‡ÓôzÂ9ðŒLˉ%SÇ ÊÕ0-yU&=~Ä1‡ÈòUJ–¯Jå¿*xE¥dù²nãåÞxiùÉKËê’‰ @=µÅ‘).ÎÛq2³”¢\ J¼]éVR”wcQÃyH¬â+aG¦.7¯¼ï8rœÕÏ uÏèÆñ åjåj*”«¨;³ëô¥€<ùéK+SðÕŒ¥V9Õ-zó:@?g}‘Öø=¾:ÞoŒ dš êªÿ¤@ÛZœúz\ïÃ?#(ý6ü³0‚ÄêË *x0»J)>Ú7{\âÕ;7¦8ÒŠ¥t ®_¡cv¦©zèGV(OÛ[#®]Í„kðè9ù&)®&¡géçCA4òÂ*ª«¨‡v›zxW‰ ʯ€@á2HG¶¹ìÚb€s¢¡ål5òO¿áçU¹F«“] ¾úNvF:ÙÊÜÉ>”±“—u ÁêüÐ%‰ŠIE]fšãTI°‰Hˆ kº”û–­RJ°Q”wc*É›\Ó5g¼Á5:$YðºÄõKºD #îCadqZA5éªnýj'ëcåñ%éLPš¯v9ÄW«2ÇþÕr‚2µAêVX‘&œSuõm7ŜΠ~Û¤:^W‚¬§3Ú>âf$(Wï†U¯·±hôˆª•R8‘÷-^½ϯf(0\6ônÍNP磞aÎêX˜$…³êW“–8~)”ÎËK²×ÀËK¡î}s…ÚærÀ_Ô¸W”à^±Ì¬ìAÑ+×q¾vÅ^îuu(†¾aù:”ÿ2=Í¥K§LÂ@¸õüŒ3ûInJQý'_î’£lKàËI½f³ŠÿÄ6œû¯£ÊU}xxÎÜù¾õ„§€¯kæûJŽ÷NPz%+€C)µõW:ðRý¢©Gýt*`!“u³)f‡ ·àélz 6et6½åiz‘꘾9Ä'æÞ‹$¹ÓœNå¾P|ªÀHáÜ2n¿Ž¥Vöç­š¯ÀŽ%‹/aô]_“DíšXx†ù†h¢jM´[_£¢ÞÕ¯U!D½«_«B®÷߯U!äö‹F…ê­"¾ÚŸBˆBBÔuEV…õ#«BÈm,£BÈ õV‘Þ³J!D¡J½‘U!1ò¬ !8«‘¯Wçœ)…Ùº¡W9çBê­"×U¥¢P…ôRQ(BÈÌ^(£B>ÇK·à}]J!D6ÅêBΫG…Ùiñ‰a*{gbl “"~µ„±¡«o8÷}}[Ì©oGk}[ÍÄç¾~=#>¼®¯=âÛ êññ[Äw±?´FîÑ×ña9ºËò‘=mjX:"’JbóxUU·(Ò0y1£êÛ&¾:J© ³Ö]VÎÓÙ;/i/=+Õ7—•);ݰê^Ó9Çj*^ò6å>ûkêà)ÏÇŠ Ü[åç+†‹CÔ (9ÖXåEôÞ*ÌGçm56ÄLÎ¥n°ýƒÎF,\¯mÕ%åéj¦Pá­¦£®kçËiª!Ëͯ{ü]çÔùœ?çuå5V·P”§Aɱê#&¨÷=Vm-îqWÏÑyßãiPb¼4í *¤†&À šÅ~,Žî  ¼ÛÉ0Qv‘gµf› ztoèDåç² 9˜±Lή…Ò©ÿÔâ°€,çïaª¡òL"âÛY]d ‚Çj›¨ˆ™Ö±`Sº¬äÿQ2ø§Bíÿɱ”6¡ÌZ³bßq¬‡P®|¡¡bPw]Á'¼G‹*Ñ¡*?Îß÷Æ$yòøZœU­*ѹ~í¿<¹ãüY×/üEçϺ~áÜ;F’«Ââ¦Òí¤ÓžÂû½ËÖ2ãŠé8Õ+qº¡Œ¢#(ÏÐö"âïÿQ«·* ñ¬!(Wãû]Fâ/|j=Áú%…«{~¬AÝÔlr‘ͳ->*‚"ÂÕØ“1N]˜ÏYù«éŒù°6ðÞ_,ž'ŸåŽÅ‰"Ûw”·V(9ÿN>y‚ìnš†.ÇUŽô»ë '+z¾åIM(Ö[ sï½_Q±çêð(ÇÖáÅáæ˜Y)ÐÑ‹c=ê|wsº¿¡‡M t\žµù$‘­TA¹/ ;qõ? ;…ò~îÀJ·€‹'Ù°#>ïWw¿Ýñì2ºS¨àetÇøet§Pá­kN¾°¾)p&|3SœÕ +P%/§x|ˆ2ôwˆûDTh«ó¸æ¾‰¦¿#nAywíó—ºÞ÷ÞBï£Ïˆ k2ÄýtàX¤ç¦`Ê!‹1ÔC»èdGvUœ$ õ²Öƒª®¬sì®S(W3íÓ3VÊKY"wŒü¿'¢@3¿2Yú´^åX:¼¦RåZ­7ððŸJލh·ÌÃ8ÎMŒc=jå¤âY6}¹4¥«"Å¥¬?2‚ÒW‘ÒyCÎÅ]QÒïÀ7áq»³”ÝÆ H,§<ã·¡Lv…º÷,&*þ’:" …rö?‘³²ŒçyŽg‚ònüh°l¨–jÛSœ‰àÍ-NVp¹³"Û8AÝÆÀÑ=–£L|BZ6i ö]¶­õÎÌ3š™wü-3?ï;A¹·>ÃsGnªuéçÇú¾UÕ äu°”×0_„ýñÖ_=¨§9ÁŸ‰ +ÕP±^ëø‘±^+ùê&9Ñÿ -XV^ÕΡ缘$%|Ûù\WÝÆm åÞL[ÎNªbG±ðuãB¼:äq7ƒ ‘BùôT~¾\²"%V&\1çaì€û8”,í§ B˜…{@%¿söOó4u]7wu'z®˜EJ?Åg°;ŽêÅ Ãm=ËXǘ©þï þÕjäé_èa…Ëô±Hú–WFs=°ƒ>SãÀF;9]D½ô¤V™$(F-`@ì°m¾b‡ÅݸêVÓ`CÕ5¾íü¢ðGz<»e±Sì(ÛnG{pG™Ž2¸TÄnb÷'F'btu?óŒ\‰Ûå”´ì Â¤eEPü€ NHˈ ’–[zÇ i§ëíâˆ_¹baFP»Ã-U´xd¸±@IÓX±Øv°ë-Üκ5ãµDX`â[j½z)?ðÀ¥õŸ5{7(ÿ(R‡K>~k„ü´µ³ÚvC œ>3¦Fo' Rö8 o÷Ý!¥†¤AÕ=ÇAA@—\΄¡ŽD2Êh“°póþ1 1Ëc®ªì *ļƬ!¨ƒ Ƙ¼SháBT´k´7-ôVþN£òw¦ßÊßYTPþçWrÛ‘Ïió2†:?’ѲÍ/›fE=Z ’¿csŸ3¿£Ìj¥0¹˜¸óÞPÝ •Øè$n\îy*£{›Ig6Í‚…¼Dxþß5žoÁT}¡(FÓ†˜zïŸBbö5q½³GÔ¥6þìöZñ¡‚¾¾Ö…¨d/²õÔô|É“žIâ“-u¾ouìQ4Å¿É +ŠÚ¾ú9+úæCP"$Á†«\âz3KÞÜÖû®ÅÃ9¡Šx”Œ¶,%ãz¿îÄèPˆYÿŒí;…=í~$E¥¥ZUý&(’z/* Ó)3ÒÕÅC°¹Xßôï¥iqTï;©  ×Cú®Œâ1AíʼnF'Âk‰3y»FߣÓ65û{|ܦ֚6µÛÔ®÷8Xø4u”Ÿþv&»­z¼cö]µ¢¨ÅB² ö=£¾Ÿs|ÿ\ÕÚo§iv¹ìQ0sútÍGh©d„*âÄ9«ñôí:hýAw[ ¶/{zÕKSÍ%\É`cˆ×¦eJÕTØEqOc{â6$T:¶êäfɦQ,äÙ]ÙP|>åšÜlóˬ÷Y &ìâ’ÅÒÇ¿½J,ϼ~1Z±É~½weÛÎ s£úû:¼RÅãWª`Ä Ã)BÈ>Ú~ž°±qÃ+B ¤¨€9]){¼–p¥f}Á—P|i* œ¸®ö׎Ï"+<Ú²Ë_â|úä”<°"ê~JpPl÷Žr{ÇÁ¾ã=(;ô+r±ëåL4©Á±¿^Ϙpßf„ á §G±êŸ Œˆ´¸´_$@SÔžÝ"Zß]Ú¾×£šÁ¼¿Ø‚m¢\¦Ýp® ø†®ÑÞÚÅ ïËçÚà;ºM_»ECНºN)‚bÇB¹yâ ŒP¬ôàö`¯:}Œj^$A‰`ºïx;Ow´ÅBÒ©ÐôÊ®ÉYC•´ïè¶gþÆKßÒDEðm¡Û sÕ|ó¢4F„B[3à¹Åà 5£Ÿ(Š…Òµ)<½'åòsB/›wÕŒŸž ØqóòZC‰ytX1Ñ6SNåæªnQì°á¸ò…^‹( Ê£ŒÈœ|iÛÁcÐwT`r£QÑN¦Ü6„~eù4*>–åk‰,ŸEeùZz­°,_CPAY¾†^+ Üãy›RìÈ?ëFCGžàÛæÌ§º¡A=cÛb @Œ<ÁÐ&-æä1çÞµ¬è›1¦ÉÔ’óȆf¨ÌÏ4 õ“ð.0Q¦¢ýZb¡…qîч0ž˜šç¤ç®¾üâ[6X’Qÿ’sµÆ/{É: ÃL¡‘%½w©HÛØ*R3àµì÷øK¦ÁlIMŸJ;ûš1XZ“öxèwGP|'¥÷©ÒbQåŒ_í/½ýç‘WÔZ1©¹ê'ïS Çyo´»†¡¤¨Ÿ ɶèaUú~êª%(áY\ÔÕúLÓO7ˆJ¼S&tõ25‚bŽ ÐÖòfrQs;ÏÅíxV8Qåz(ú ˆÆˆÆ8°’У*NŒ:K‰_˜¸AN†ŒŸ ™êp¾Z¾#âD¯QB|Ï“ãVk½‹(,i22H3º–:Rh êÀ -íM¤PÓk‰ƒŒ[ûk"`ü~*µg>Fí¤6 Í–‰Ë™ÔF½ÐkñÃŒHªƘ%c#¡˜@©J$‚2á¶^§–èÒnœ¹ÊAñoÉ®rÓ'›Þ3£k;ËÇk¹’ç™IÁlÖYÎxÂÛ‡6£Îj‹¶m@EǪíÖ¨ú¬(Ší¢í-žHm´-\b¶;ïmœ‰ðŒ6²Ä‘¸ùQÇWlz|M)Ðt˜HüÈÝ¥ŠàïçTIPaªÈBP#½#ejL_"_ð¼Md(\Zà›Ðu ‰Cb–ŒZ‚ù`“ø ¡Æ»U¿¥!à¶†Ñ (**¸ECÏ1äú|ÕS#twŒ£`’ªgŠâAéAø†’¿H.dñ4ôZaéAEPaéAzǰô EÅÔܼ¦ÄÏ2·ö{ܵfÀ±VÏûg›Îí“ Üš4Ðï¦Wµ4ö«õÅÌ ¸V_= U©¬E‰]öîeL×›¼› *"²C Ôó~ýTÍD¯SbݶšLÕT›çj êFNs8'^ý¬¿£¨Äi–òà{Òs_A-“Öðÿqâ¯÷K¿¢* *`¦œ¢h%£Ü‚™òŠB“ìî‹ ËÂø>†ü »(«X¶\-6ª>Ò2-ûñMPlg ò|¯×0cù~ÝI!@Þ^ºªnÉJ‚¢4|¤wæEšÍs›TDEw·_èù\×97TìÔšçÚ jËZcEml_h$ƒŸó”M•QÅÀÔ¦iNßñNšÐñëèôºª*h©´£z¡K(`ÎéTÍtÙYØõXPW‡ax5ʹuMÛ(¬×ÜŹ9(ÌÖÙRߺÇÇV+À{²ëÉÝo÷ZqpÞÏ[qAÑÆ«Ú¢t ðž¡B´3)­ÑÕ8êq•3AQ+ŒMgêb™³ÍÔûÊ/—S^ T®øÏàÕbWjB;ç5€â§Môer*Òà4—©éùY°‘ˆ_"/ñµ>ZëeîÔ@PáF"|®øì¹ÈcðËídæØ 7'U|µ€¯È›‡Mür?`➬ @¥æ'•÷z툤95Q¹Ã zýøõÔŠ…y›ß/_O¾´*CF¿Šã¶×O¯ÔÐ!ƒQŒÆÈ˜Îô}[bUQTÛÝ :<¸p›¯¿(Ü­ ÅQÂ1Ì0ƒÿ©ôùE‡ÒôŽ‘·ÖÀ:MS¨Ä *,Ö¸Nˆ}¦¼Þâ‰ÍOux-®f¥ÂoHˆüd õï˜} 너ö–9[´­? ýý¿ñŽînBÒæwlõOÙ-¸’‹8,ÀÒ¯ ãUq;¿#>}¸£tî˜xò¶Øœ¹±;[”ùäDÀ®MµüWŸ÷ÔŒŸoÒv\Ü}Ñ:Ç(c_*`p`”ŒÑvä©ùBsø¥E×=÷¥B–&ï_+AyBs[ÅÍ•pÊäDtàHhn%Ž$0É ±p½fè°^ÃIMýHÂÄ^‹»FÜ®šSñHøæTu´k¥+¬yr¿éÝé=+WûŽÑ‰´p“âºJšÞDSìÓßNES윸tÜk£ÆrécFÆî;iÎ-k5vÓ£” ˆýsÚþµ†¨v*«lŠWl‡ÁA‰@ÖÇ~Û»Z¹•ú@ÊTÙ9A«øâ8ª¤Šoy®p†™ŒgÖÚCÔ³cS¶Mººy#A±]ýôÕÔi®ZŒãïyèÀt9]1fŠý®ŒÊ¤ð Cºf5`¦&öº2œ5Ú´@Šï™à[ÿh–æ±ØåaAP¤3aJ™ò8ÚÉÒoÑöTMïrÈ °£°ë‡{V»Yˆ¨Ûñ,|9³0œYX´:ômì,ôßYørf!e™Sásuet(›ÄýZ¿ÃN_Ð8€“Zÿ¡qEñ€½f‰§ÌÛå4‹ë×í/ÝH0snn$I»‘îFj jßÔÒn$Dí»‘ZÚ„¨èÀÒ$íkýkãÓó}.äú¡ŸTþ!(ÊlÕôZ¤³•2Ìz?MCSBõQâ(³U«ofëÆ=1ä*iTZæ³E Ÿ“ñê0¾ªfž‚bÎss{zY™gÅCV¸æÜNY”c…#ì>ÚÍîCöµ·ûh÷Ñð×Z;£o¾ÌºÛ· _Ç-9ï[n *hŽ+Ó-ñl§p‡iDƒüæž;k%ÕK©=`•›j},¬‡7DÈÉ%ç,ß8'¹žÅ9ÎÕÄÒj,â gÕ!OŸ'~_ãB‰¯¡žäç ¿cÂÄßÌ!µ~›å/m–n»Ÿ+:«+ØØ$9휳çÇä’nrÀœÔ›x<3‘zóWrRoöX«±?Äh›Tâϰ?¦úÇ^(*`tUêX"ZêÈP^?µ7£±"Åéý½F »~j:ï•÷w~6ïœ÷w~n~†w'±\cç=é>²?ÄyN¤9õáŸ+öks¶þöu¿(èXà÷›wFƺ®‘W[*…Ùab@ÌÏ kÞ¨“¥ãHP<Ô×âs%§Y `Qòû=Ô? ¶þm$é”öYºÆj@ÔÕ× ±²=c‘Ë8Æââ×翺1E1[qqaÞ>„Ç¡QM¯ª­Jz-NkÄ[ô8vëKŸKIP¿¾ðÖ«ê· 묅ñߎäoo6Œ½T©i°‘ôŽ1éÔAE….­¦G3Ó§¿{p¼ø1›_R6¿¸ˆ]çv7O=úPÑ™MD'Aª”nf~J×ù±B® Rò6ïETÀ&bMz­èØÜ¸–>½gbgmY¬•èÄD–þȸ“ÅiÇÄ_U•V*K‚!‰Õ¯u;Õ%A±W×JN ¸dKPA®…^‹¨lؾø×«Ó[mU”Ôùp·¤B¼“­Ô8è¥×KØŽ´©Z°#T¼~w­¾Æy=ék$öˆP…O'ÀøWèÞê›’üB¤ªkæjj{Ûñ±.K†cOªº~×Ö ¾T°ÇË>}ä²ÀmãïfæUϠ⃯¶f^éEPlWéߤèl¥_\ãckSI­MÅõæ32­ŠK%å* DäÉõþ¨ð}• ìçÑK]Ú—ÏÏ–ì²—ÁÞ&a9¦K+AFV°‹Ç$±çŽr–®…Ì)¢\þÚöu”ãÚ´ÈÚBÔ­1üµì+…Œ<ðwd×SM(蹌—jñZÜà×î+“‹ê@WÐ~j›©Pÿ'“‹Ê ê·N”–?é&/›Š¨o_iaùXªÉê¢ÏñÛfâ«Jò¿ÿ“çšåú*>È¢"*Ú32£ª„ù Aú¼ÿ¡Ê&?QX&²`žæÅÕJ?ˆÉ‡ŸÜ´`ñéÆ>W|=êhQ·c6¼#ö æž¶Ú\i FÊÜ>ýÞ†„ ªGKP<ÀC” ^ë`34„ç*éÕÛ±mä.ØÝ³‹´AæPÅ"¡³\ðËYôØ<u ®µY`¼Îª§]ÙÖx-¾Wh‚•)ˆO†cÏÅÁ>Tƒ*I5Ö‘ XHÄ»hŠD¼{à !JD¼ç–¢¢«¹ÝXÍ)dÀE-™læ3 UÌGÁ#ÿa$¶þÍ~s*Á£pFï¢+¾£oüëð(›vœpT]#нÚÎ|ª™ë4§(æ2I¶êÖ»^ä ˆâ|¹©^º W_~ó-øp½Wi±4¨ª„¨(ÐU&í/”ø(ìÞôzÝpÍá>;ï(›|è›̼ÄOâÞ}ÇZ9ïx?~Ç^:ïx?~Ç^:ïxwÞq×ç Oÿ·>ï… Â}ÞôZ|Ï 4ÙΪÅS“¸«nÙάÄo[¸ 'CoÉPZÐ>o× Ú ÎÀT¤ríhš;N·¢Ï£ÆÏ’TìTÁ·®ŒFÙð„~ DÝûiÆÕã•.²\•8=ãÛÉðýzïÕŽ=Ûw–og÷çÅÕš´QÅ÷ÕšTÏ­«5ˆ;=ÁÇ”šv$;;³qˆ†ÆiLÇRª… ˜c³±ž^Óôšå@¯Åª5zú¦W­Ê®%¨_å4UÂ<€à^4„`ŸòQ´U…ñ=±cø—f ôÙjZÚ²ZŠù^«Ø1µ’j&(áÆL†²•/ÓØW½cÊc⮠δödgd{¨¢Àù3­²ž&"wà 5¥l?ˆÜiïÿ·÷l«¨SÕIŒáߟŠË„][²ƒ:ÜRØ„=ÜSug ¼‰!æ¨YýØHlæÔùì~HV«[÷d±¥…Ä.óŽ-^Ûajóõƒ×:Z3§Æ\Oå|:G®$Ay.f=Îö¸©\/hÍn§€‘ûÉЀtouï¼—˜[1ÏÕ‡;½;5ws‚röÅ›;úvÕ.‰ª]  »j²×pD>€E… {³uíHžPµKTpP¬5½³}‘@—gÀØ%;ùY).ÆJ1`üÞJQ”ÓJÇ×.¨oS…3Y&á)X{å¶Tÿ‹y®È®]"@»¯Å· 'O±ùƒÂ‰…“õ|{ǺbäÎ/,1˜z®mg€ºöþã9À;V²§¨=HQP´‘qÞ5퇢HQafÇô.ňçrÜ;˵ƒIîROÛq (bä|€lù¨ FBÿ9¢ö®EccÙ‹®Ÿë¶[*¤ë`V’½û¦Ò‚ ^ÔöôqS½¥lk‚Š*³cOaŠ›.¼OW%¨{6߉:à<'Ö¹J‚rªYà"œ«B9¢ø½BùBPîÞÆ Ü ååV(§wt+”S§•k0xªXfDÀÃ;µ§ßº­º¡Æd@˜—ªÛÏ4àÑ™[ç¦;0Ž“v…³:¼ŠÜ ª)ŠÚ2šYÛ¼‡ðƒðmÿâÂCô¸ó'¬qá0”g …‰ C O4&ßÙªÖ Xï©îûþµaßÖ"ZAy„çnr¾Q¤É÷¡Ð;×·–˜m¹xªžMÐ] ¿PÜpÜ’G¡Eß`[Mæ~TÃë úAÈï”­Q#$ Ü£'ý$×7Æ9;·N‡†xsÿE‡YùÞûoc£õd†·U7Ìkízô˜á«]¿cteß‚YoõN¿«"at£“¯ßÙ†"¬›¦ V^÷G¸æ¼žvM•†jª ÊÁ`äþzTÏF}Љ‚ͨj¬ÑÉ·õQ”o©è +v#„Ípbßöš}ÛK‚ò\lÌ^Ížêh/v§‘‹J"Á çAóÜÍ×Ý 'ƒÊõ² Ý-[Ù"êÄ]É1;Y×~êÖwSéðÂÕDÖjH ¬dÂÑÖLï5Ú¬‘ÃÖLíÛý{TË,AyvÃ2£îDGu™Ät§äËP%Z‘´ŸšZ‘m{mm"ÒOý÷G­wt¤Pʱ$(~1ÛöÚáøëyØÏÕ‚æaé§>)vˆ]±#ˆ¼»\{k‚È·ó §_hò²°­ä+¾Uv57Þfšz'Sݧø¹­r­®5¿U,7à™hÄ/ÈÛ)l“t±nå_P¢‚"Q­žØ[Tû™k‘€" ¢ös¦×Âu²Ï§ÀMx^šÚÝw^Z@¸ÛYZŽ<µÞçj@K|«Ñé !J÷”-^‘s%'; #=×'Ûu¢FÍcÃYõx-ï6²‚ø‹íŒ ›&ç'ìáTÜÖ\R¬Ä²kgöÁ¹¦ÂkÝj…âžÆgSÉÒhÈ˯øT2Tx5@%úRæ7†g^m‰'§kóù  ¢ü«Mò‰§<*@½JnuwAyŽ9´BÞÁ/{/%è½eKPdÜCP6"‹Å·.G‚b½·-ªÕzoß±.Š»N¶|.›ÃVkjâ¬N!“fÏÇ- âBDy.¬9ˆò¯uäqúµÐü8"vMuœWŸjœ ê—éĆŠ!Þ][ˆ´ÚÅ•ƒ’]®¶íOœT¸GFkn„èÒ˜ÞñuÑí›4ƒ}i¿ø¾N<« ½L*ÝÞ•,IBP{.š$¯R—·QÇQ?bò3zòL·±Ò;:t߬ž2Êë¸*”Çß½C¡\eŽÃO¡œ=oÊ¿æéý³Dàw0›‘¸ô7¦%pÙ3ps(×b4w î4Ñëß³wHô´C‚=¹Ý£ ËòOÓ™5gglœ"Ñ~Õ+¦eé‚õüKç™ÎEÛ;Ïa×híµ(“z!(‹+‚¶£PwåÓõ«_ºlÍt¯cÏÈuöø™Ç!Ayõ"‰6ø˜ñ]Où7Tz;ÖY³Ô¨ÚÅ~Š'­öZ,ï¸/¿#Aq²ÃÀßï|íÆø«Ì;ç|=jå(Y пf„á‚Üt²4žbÝNPWg¤.îµ.ôŽ?g¤ÜÄ«c'U<‚j£Š‡Ïæ]‹Uc˜Ýp¶ t€dþãŽ÷ˆªƒÌ^¾6ž¹æeiqð½ëû‚“šæ£òŽ…¢¨Þ®9¿WcbùŽANsÒü*6QÉa‰Qšï]gš溢ŸÇäÛ.u`¥TÈU¬Õ¾ð~ÿù1™]X›cþ‘¥Êd%dÒMƒk4Q7ø;\«îD<¬pºÂˆºMÏWLÿ¬þC<0â{ Ø©óöÝ=PäsV'Ey5¾ÕÜèiž+<队îïžö»Ûî(Ê}Ç ˆëFŽ©üÁY-#\Œ]k[~?ŸiLq%§*ÇkimUd¯1ߡ쵮*bJL\蕽t7O…|“uXFèËdÁãrêû6Üu êØ?„Œ32 Q/û±RYo"äoòóOûÅ1,‹QxE+ÍWËúÅßxt¯K O4檔Ø!Á|nQÜÖQÚ«ì±(j‚ºzs$rͪ ª™Ö|ÅÝJ÷à©eÂÌmvêÁüCÅѺ×¼{võæ€æÓ*îtm‘ |ÊÚÜÖœ¤Î§8‹KAPÓïG¡oïÔÔï€þ½ß½–ïÌùpv÷9ßBP&(gÎgfZ`ÏùšCÎöœOr¾ °ç|âóêšóÉCΨ×ÕV{t¦8H,8Ÿ¥a÷€ÎÝ߉4+»DÛ-›4›ÊT’ (»Žä*dú­eMPkW0ïžßì ŸF‚:x‡ßÖ¢˜QIQŽZyÕ›ïÞ²I{¼ÖËÂÚê]&Òo s(ˆî½0a²‡Ý SP/LF}+®z Žhö´ë¸I`Qã^KX)6Ÿ[¨o3ÂJÙæ#­ÃÔŸ O™wÛõ‡ï‹ùw'n挷.uUg­'-\TÏÆ=;±ž6—ñÍýi¿©X%Ay¶ÖÝ¿ï¬1_ˆÛ4áàä´ŸW\ï?ð SSÝR±KÜäs=39rjú­&…’Y™¯Å/=ê ô¨èÃk`Sìѵ€,Æ,“q»j#ÛŠ–š "—¾ ƾ,tVO›^E`ˆº0fË-0ìÓn®ÖÒ ¢›NPã2ÎNl™ÓÙª °ábÖœl›R=¼Ú÷0‡áÏ“²ÑBLÅîåËøYE 0³C$µÑKcÜ¿(Ðl§ü*¯ý&}Z­åQm{T´…¨ãV”¥¸Õï°ÈvŒs50^ö3~éÖß«nÒ8,0\;g5Js‚ÅÚ€r:ãì„úÕÓ–½žÆøq¦÷®†qRš3~9È¢;MÅÀ}›¿.úL”Y?Q”ç`ÖÇæM¼Ü*aiYã®À‰Vä0 Ž'ãfj ×Ú<|ˆw•z.)RµžT8r"{?² }ø,|Ü÷áK‚òšpæ¹Â ³ µÔ|ìjN±Œz`àSéåWÂO\(AùÖJì(Pg‹]|+0fšêÏ\Ö îî¡ïfûÃRÔïŒï—él¬¯ì)Êw9ybT^G4*”m­²V|÷Ìñîu‡ÀTbáUá(ÆYÞ©iÞýÑû%Aikõî{••8¾ˆ‹ÄöÍ.š-bJÒvÂk½.׳¡þS,¿k½¼ÇŸ†ž =<« -=ý[èžÆ}UÔ+Eyu¼Ê¼Õè˜?Ò÷õÓŒ`¯Çõ$p;AJß³šMøô„×ñ=½«ÆnªK‰'[¯çY!ò¡)Í›Rˆ6!(ÿˆªôÜÎg!FÌ· ¯ã×ë¶U¤êx•Eš,ÅìÊ8vH°—gס”Í[¤-jm²×QS‰DÛZ+ ýÙÙ·ÂøjŠi-’©xêÇ"½”ñØÅq—Ô)Úå%¡ÞÄáŽo²«_³#bå›T’ ðc¾¸;z,ÄRá›îO0‡*œCsWC>ôz¿6jËLk[/&û¥êø…¶Fíì£Þ‡$A9Ô3ZdZ²WtÑpù­_â·~¹Ô3Œž;nôªaÀçú­9ÿýûw×ÅØÈ°kzÈüÜj-ø#—·EVõM•up-ïöް?rÂp!¿±2¿Vþ|Þznàøz27Gw4.„üÉíî®S•õÙ€œ@þ ïṮºÅŸ/—Fã¸üTÌùóeW1×$ËÁ¨˜sÂþ°œñ%掑³:k2 ŒïqË „XŽ{O{]¡æø=~Á¡€½äòC”TS[%]CPž³ŸžÞóíý|íçãžßÏ·”Óat‘Øõ™²y_Áµ¿c×gªÌot‡Gã½Ç=vqÃ=8ƒãùmwŽè]‰ÃÚ7w@ù.÷$sÇТ¨²Eµù[Åç¿6á3]A ž=òÍ;_aÜ©g]™uJP4þÚyþ™³¼“… Ü|9¼cteW%²‚‡¸ü䜰)B*ŸV9@W)¢uwÜaÔâ[åosÿy“è+Â}Ï®Ý-ë¥ýiwó›a_szµæ³æø§Ù‘ƒøÚÖ º& tŸs·Á¶˜§gwšƒXaá>¿ï­Á·Þyx!󙟔%päèk½ßïÕ*¹]NÜ0·jª±•ãHP=ë@ç..Ó¢¦(ß¡ViÞDð¸v¨HðãññàyËãÃ`g \x|ËÇÇw«‡Dî<8vàûtÔ·OïßõéÄ”çBIAPþ®R¦AU¦²L!cð!åÁ%¯Ísp*ÕÈŸ†7A9]Ìodw%ë€OÏOç…¨]¤û¤ÑAïBw¦_KŒshO¿Í•QÑΩÙEÙãFeºÀªgO‡§ =Kã§ûc©*qn3Ï©[ð2‡Þ@~ª?þÜ$ç4_gQ¿%AïPÜÝEœÕlìk‚òí§üFu”³à^uT”wU„¢þVü¤Ëò·’Ѐ¨«¿• þVˆrq£–Ÿ‹¢Úƒ#ë`Y9û?ެ Ayí"tdE”Í‘uoà€™4g/—kÅæâ·PÔÕ-Oë ­¢4£0:±xU—-}¶³Ê±“óiVšà“ ËP”SïÈçE†ý¥üÕÓ8íÖ·é=Â[åþ½Þã@Pn½Çš ®z’ê=rîûÓŒ{0d+æCü¦l4œÎû|ÌŠO'ß ÆgwÎ/ØÈIýQŸènž…ñlLe‡w ïzÊL–É_–³ð¹³2žð úN~½52ÎÔþ\ΣkO™~­ZO!m \1ytí)Ô«J´ˆ¢=e9ô§µYÿc€"ŠÇߢ2=ýu;@_¢øî@V@GoӾߋL—„ B‰ þÓÌÝR‚~¢^—FG {>nsÜÓHÅóØ(i>Ü9L£rAPáÂoü‡/ðÜ9©ž^F=ƒ“Šç%úùéðÐwFC»Ÿ?U<ÏÑP%êuè¼vûŽÝ²–j»Ÿ[^”^à|µ*@N¥y«ÁÅ=ø ‹¿‘Ùr%UÈE”[!·&(·BîHP«Ÿ׉ß*_b„Þžú ›7§ýî‡|û8V£û|»&(ÏÞǺÕè~¬J‚ \õGàlñ³âþ±þØ/udFÀ_V6ý ZÁüõ¼e€‹=]ó4<_-¿‰Þ×å_y¨ƒ´öUµ&þòoü a~cpþ~㑵Iø9p¢ 3íå8Ñ•x¢[”wp>Æ#·©R‹œ (+?§Úçö‹ßòszz-æà€×3½Ø¥_™7j:Žß¸#(ÏÎ/‘›Î_ìêTh˜âs+Ëš  |úLeºÐk1§Ÿ!^+¼öžöÚŒoâuÖs¥öa)Uüµ”çŒàŽÑÓþ¾td•} ÐråÑ%þú)U}Õb’ãX%Îh4+W_JMѦõãOÄ9úˆ¹¯Ç1{¯µœÿüƒ±o½¦ÍÇ*œv&²h€Ê©ÛÁµCù…œÔk:$pýÚëµ °o±²(7{¾±§([ö;ö{ö5S 㦑«Øwx ‚ò.Þ®¼]1þŠ˜]ûC ·+EyN~¢ø-?Ôèù¡ÆjáçàµÂ[~޹é­ºü·óBÄx­—Å3ÙkµHs­ÈÒc ã/Ýî¦òŽmv„¤6wVÇ«´:žTt©žâEÑÕq›”EŸzça· ¯ë®€õíZýňâìuR£¶Lø8ª.Àf¥s˜jî´ŽÛ— ü#›a»c­ïy¸c`;—[Š{·ÂGxá*b¦]Æ{XÂGxÈÊ)ª&(ïöMÀZžjsз­«s«ßHQžëéáä4$ÏŸ³ÐæÄT®S7tó–…ç~w :Ôž?½aÊ£ý ÛµT†?wjTw¥ßýßWÂdk‡Q‘¨öX3X™Â½ß}9iŽú¾ý:ÅU*DKPlg ˜¼£iºFM©” ¶Þ‡¿Éê«KÕ€ñW¸÷»/ÛÞ‘àY‡žþE×-ôé_W¥P•xçY숊h× ¸jóšŒKOÿY¹zï½Êm‚ò(úŠ©këöŽðqvÌÅh{M›Ï˜Ö 7 TM6~å2Y\â»÷ÎsÛœ¦_QÌ…Ïç¹"UaôØg‰˜Ê‰ ¼ãn¥Qê[÷º€ |—ZDCáóöv= œjI߇Oÿ¬?‘aWi&«4¾\H*±fõ…XN­¾éy0á3°0ô¶Y»êÉfF!»ëXBo±ðéòÄ[,|:¼Å$õ ‰¿Âñ¹’Ãs…7õ޶õŒðy¯VÙã#G^ûÖÇ>˜×†{]ôâ»óMBïqë ç_¡÷p¸N§Ãο½ç]FÈá¹ÆzÚ­Þñ^f¡(Ïá>":üÁáœi×Ñ?Óºô좻W©À;r—JŸ«T„§ZæE¥b (g·+ä¡wï`û£÷:õÖ¤¨¥ß½ìç7 ¢3'»õ«&o9´å]ÇÔµvűиµÄªµÆ÷å?ϵL89Õûv5 Ž’Ê¢éʪà챊ÇE€"TèŸ|OÍéŠV ¯šzBRYܾcн5Õf|÷´ùø\R=WeEXÔ9ä¢*^绲B?¸œFmÏ¥V¦zîÞIP‡x5ŒÅ$äñjHj™t-lT¸=ŒCþ?®lgVœ¾R7kr9÷3Ò™G`‡°ïèú?`§10:Ò¹*Ñ|ÛeWQ”edúå½3ýõ‹}¥ãc. Íë*Sñ×ešZ1×¹rYC-jßf©™êLEŸE_ãEa†8‡>‹½1•¢,ƒ 0V|çóRAÚp®Ü×ÝÖu7 xCŽõê¦y­Oç·Ü4Š:§ëT‡Ë^ \"T'ö)ãI{šíiöç¹+¸)IW°ï¸Ï¾Hè/ŠQ­ã=ëcîohl1ó[¿ÜÏ_´Ê_Ôw¼wÇøÒt.SÍxVMR$a¶!нi¥ xQ.“j¥È5qúnùº¦øµŸ©Á'á~L8ý9㻟— œ'pueîÈ2[Eƒ>“ïZOÕ» :Åëx™uˆ}“ýì[N‘e0aï»ök?y‰wïè52™Ýád¶c)1B–磼«Q=/ïùjª"ûilø„Y¼°[s:Çc)0‡qÙ WmÞæÊë% Ö2€ù4ÿºý¹:¿ü¼²|ïÊdœ„òpŒ~Œî¿}ôÃ~/·é3 :AˆÖÇ~/WŽLth’øž­õÕþü ã}xOQmžï§‚²m‰Ì*ZðÕõo|êPvÑ:åe]â“ðÞ:zàÝ}¢ Mê乪“ã^èy÷Ú£ª€çò¦åœ×ÂLgº¤ÌFÐõñ ƒwëÈé’!Š™;²Eƒ<²O&oÙ¢ÁŽlŸLÞ:²ERA•̧„œ´ ¨ÇŽìƒ¹¦(¼GÌ~eä^Ee‹(þ¬Ó—y–!ži„¼(äi SŠb,ŠèÁ ’v_Öý24Xg"üãúqY“¿Xoí–Ç嚺xpM6ð©— ”„|ÿû® O·ÞzW;ñ}û}ÿÂûrÞ´oQáÛ÷Ý7wA¡îK‹ïU‚Œ¶E»öø¼NÞJÛ£çzî²a¯Ã×»Ä2Õ<,³òuD|߬…Xă:}®ûà‘ŽÆ;}:õ÷×e7Ég™R@ïÏ>7_$Pø.÷Ȫ©f‚²èi•boTÛäFPöeÇDW¶èÖ‚(Ç8{ w¯±[ºÓÌžúìû>{J¯e?Æ«rUc¼J•¡¯+23ÌzÌN˜ýªn ~Ñyéq“Ï Þ#ᇵ¨)Ê\]) Ê6õPb¦C§ë.Ú~aÁ}æ«û.WõX-,8¢ìǬ¼É†¾ZÂ"¡ººª’ubÎãW7ÕÜ÷êJ S’>U†V(ÌÀ¶m-AQÖ-&ß3Ã(ñ=r])½ŸvæzŒÐÛQŽ‘1€7Ä­ç»”1ð ¦)| ’osûÕY÷/î<ûx êãés³îÙï¹÷º¯B¡Ïý{TKc_D1ç˪C½@Ãïç#¸ Dɼ6ÔÙç£Ï#«úÄNM-ÐÃÈ\FP{œÊ¼YÒ¤ËõÕc“_·&ª’u&¨ëµŽ˜I¢šx­ @Y×ÊàË-(êžoïú÷S6ÂSe[g‘ RS¥Á”eC‹OÂyódGeöqß;-7@yÏ]]Tm]V‚/%ûxÏ– í´dŸkf¨ç pº³Ïmåü´•÷‰Ëïž(öÐú}>vq ²Qü5Ä_¤óCZ›?²ïÇ<ûÊ?Qê{çÊÓjÍç~¨ºPÖC(¸¶Ö[ÑÔARÜLò½ˆ±ôÐ_ˆ(Û8¡Š÷e¿O¨–e=Uæ‡_ežÑªõSe^”õàH*àìëé9 ªÙ c-Ö*À_T+Ô*Ú‘í°ÎU…Ù/û:šB[†Š=å<—"ðot5‡;Ìaº8‘_¶€ %ûº7'¸/ª­Ì4%Ú‹¶r¦´•Q¢Å=Øï§6žä×Ñ´e›˜Ë’ œæàT`f?%Z)“ûjŸGKDPÞ¯b¯bRIW6a(¦EµÈ5mEPmÍR¶eÝôD³5­’)yö}õ¯a†…YŸ·ºÜ=Œx@ß+n2Ð, êYÃøç0ëûÚí‡;¦õ}Õ0ÎAÙ7%´õ1ñ_»?*|Û–õ¬‰Ý¸çX÷‘†º0Ëà>ÒP÷ö¢ï[7ÁÒÀie9·³*Í™Ü(Æß¶¦¶ûsÖž¢ÝY;j)Ê6õòw‚ œßX¢æX«^æ9r/'(—º(c>TnY;àie¹/s}6àò^ji½:E-ÿ%£L8al_{^ûœô‘+l½èjÎ4]ØÜd÷ Ò®0ÙBTËlÍí JT…rËe ñ*£žÆ*…Pa‹¶¤W mÌ&úäeB¨lÉ=„ùåhc®þÆÿF®ÅrIŽêê2רË1M+ÛÒÃù¥Îµ¯ZüÙ_¡õ ñ[=š>U¼–}S¼€Îˆ=^³\>˜ý}®ÂîÝB¦£1Aý\ºCl³Úû:úy À˜ÙŸK_G©sìå;ÊGØ1éäÙ*Å÷xõ ÕDÉÑi9âD »yc,·»ÀoÃ<³o:[WÅDx^ÎÇìà³*Ý(vãN®ÙôO0Â<Ö£áotìûÕa¹êËhðZŽž(¯5aŒÑ=4\b•?ÖÕ²7êWEt ð䓹P*Ò¶ Ê¡úL¸ ça^êQZî~eÝbÜ}7Öm7,{ïçÃÂôi1] îËÿ¼é£f=ó¿¯Õ;˜+g¾¥Mo*§,.ÆA@“ù¶¹ÿK *Óñ׊.ž ¾óÚÿ…uß¹®BݯÿFW«¦_cr¬OøÞ=…*lØMQ¥x-ÿe—Ôùxq¼3ýê©r£rIûS.a>7+—¤J¹„Q†…êˉC_nƒ™ F–‹¾\sèËõÀ•3öyqjѧŒQ†åAg ø!ƾ¦©™òÔAb”;y˜‡Á\ôäNnó0ãOáˆƧ¹L\9Ìz`D0Ì~`‚²Œ+¾Gæ˜Õñdƒ‘;sïþ¥µò€Ò&#(:CŒ~kŸg&êùë"ÇHé~†gü%Îø‹ù†øKÐø‹ù=ä±Éw1mX«Œ½Ï×âÝó÷îxö„a¹(˜ ª`Ê(“qW0E™L‚²/oT¹“©8'0n=w 4TÇqÛ8}~ªª1¢…øØí‡(C·Ÿ Ý~ŒÿG·|iü?ºýV‚²X$Â1ÂÖ\80A90¦MÍÜ8°’ ŒXCÑ9ë…Jßd–yhÖ´x÷®<Ÿ§…5Qn8‘÷n¿óDæü™Ée™Š¦ëŽ2ÿ<¨Ú‚6Öîo% Rà ?ôàI…Î/ü£u>_f›WœåŸ…Ü,[DY 9°.ªò¬\!Ëä„zÒâN8þÑÝé3l ê<.Q•›Óé­g>ØÒ/Õí×Ȩ©¬Ãb&¨‹S4psc½Í"Å'aÕ êS ‚ÛÖ{V_­í¼«—Á×a»Oýr¹Ò„ƒ:9w¼§~¹\©½]PÖÃŒ2†™;n®ßY¤±ÄHÁñµúWŠ‘UÞçÓ*p¿w,³&ï’GÀÖpÇÈ÷Õâݳ×ûZJ‚²Œzx-÷]C¢hogªTDµ=ìŽ}ÓÙB8efÞÔEg Õ¸¶xi"1”}ã2óp‹c¥‡Œ(‡¢p­n2ïp­:Ä)çήÀr÷Q#(WA“ß<¼Ë”Ëä·‰%ËÄ»ÿ¾s™+AY&í"Œ¶þÆ#¯À#s÷?xd¸–æ„yã‘K‚2óÈ‚ î<² <2¢œ[·Ÿ|2ì¨SÜM Ž“{j8e#~Ûšã$< œ2 Ë&„·mk®a îä Î‚Uî<ìLÇZÝuWÂ: (‹FîÇÝ'M!“dѶu™À_ ú) ‡ 5C Uëüà’dIªž \‚‚@§:b¹+Ê3Õ™F\÷öƒG\~zÄAìK'ƒP¯Ýéç­–;]HPšwô“AŽêxˆ²MÎU¸¸®IµiÇ;ô¸ë½3ˆòß™ APf&£$(ûÒÿuœ|¹Œe–¿m—½¨K8È]cÝ]Ö€šŠ Ïp}¹z/jlÄk¿ ´a<¡é*ñþ¼ïú¢_—%$(Ûà" fŽqšúT¶çÞ÷5^]ñZÖ»ܽgß&©PÑ.‰×2-å<÷PîzÁ@%שÊÙ4vØß7A=éñõ<Ö QÄ3;†N¥*]Æl]0R𜫟ª=NcÑ7bNØ­ÿQ͈9›ëu†† ¬ƒ“ ÈüpïÉõðè&Ý×=*—pÏeu1þòسƒ¢úEX«„ÝzòæÞŠûOµ´Cª˜³}®¹ÿÕ•´a­N2kªÖOî_Ù‡Û\‰¼ôòæ§›™rµ´©GÌšüïe¢„f`$¯õ­ç¼V\òZßzÎkÅ%¯õ­ë>¡Í±â{4© Š­?¹rnâæ@­eÝÝ€èÜ/÷Ýçê¨EçøžiBB¢ÆAÝ—Á·f¯§í Ö„¡:ܽÜ$–a!(ç®1çÄ%'<ß/·JñÌd<¹6IõÛ£«Ëýª(ÎJP÷ 8|i® ö1¨.`;¼mö’»‹T=/f½ê“cµ@÷SÚ~‚:;rv«ú\XpÜ}ï*tÀ§íÙ‰èqÎk¾[º¢°º{ÿ-cm1ceìUÏ+§ú4Ï¡iy|is'#~ñäšþü½þ‹j•G¶‘)>ÎôósšG9ÒìRÇÇÙ>.åˆõU2Íë ¿eî.Ï¡kîükè|âNþ*ôYqþ}p®úyŠ ïÞzŽsvÅ‹¶M¼{M]J ëÏéP‹l§ Îí.@¨Zw^V°‚ÄoNѪ֑ôÉX`µ@›æ!³ÍS/þ”Eçæ £ê¹ÌÎs®ÍAþ¾Vå/n͆#ÉðÿÑ®µeÍ6”e\ÑøTÙk÷‡zFÆs*Šuí÷_´>ŸÏóžsÄ…!äõ}é ¬ë#.T(Ë Ä+Z¡lÒKv‡3‰ŠÖlhé/:· Õ†L¨J”õªfSâµlS‡Þ©f£Pæ½ ìg'“œ9$êÚqv°§G?f)£ß­Ÿ‚2yfƒ"D¹¯“A >{ƒâÅÞs:ŽË±&$Êc·úh%(‹v¦¢^?5[QS”M4»p†xî—QtÇT©B9×Jó¡VYäA*Z|§âŪ\ŠŽã=΃xÍ• È< ò }ô2j Ø9[óqèÍçÓ|L-+”E&JPksÝÙòLÝ3L[ *ëó}× *)Ê8Uº5eßÎŽ†œõ}?;AÎŽÎ…²ý…x­·Ê|Zæ°V¿ö»Š¢³Ë­r–(÷­×tÜ$Ê{MpÝý‡¹LpŠ®åv$€âºR(xfï|Ú´­](ö’?Ê´~Ñú¼Æ9‡†±D}Ÿõ:äµ~.e£´Ri’H”ž‹þÔP›ŸˆD¼@ñQ(ë©á7K)Qîû,å@PæYJAP¶!çƒ~_‰z}Ûe+çu†E®Dè»®¨ ŠvPwR7[Eàü¢PÔåµô³ºnåVÞ”K4Œq~{®˜« ¼'TÔò?‚òo]ˆuQuÓ¬)A±Ç÷˜*Ž¿½¡¨ ‚dª1WÀ§ú9i ­Â%æyéùýž0ì|lÃ~’¸ÞÙ׺¿ðY¾ð½òNaöå¼…JlkÓÀê¡nL;J±x› ã Z Ê:çç³ãeÊTA.1!¢‘ ÎøDå£UÜ]Äí¸Zåú‡ÚYƒI~Je‘w ¦|—q7ÆsIP6yK9É/ ‚ã×?¿£ j’.(ñ›týK¥ÿ`ñŽÊ¢\ûI6àzõ´ÎMu­ª ‚Jnˆ‚ ¬jšî¨3ËW¨|ßèä'”ó;IãVuEm YKP.]ÕGÌ:Ó<-éÑÁ¦Pg×YŠ5¹µVq]PþoÆèñ¾,EÅ2»*äßwP‡a:âúrnµ“#Í?öвC‚²Ÿ} ˜Cêì¢ÚâX..ù“ôZ§ Fœýö`ßwA¹·gü…ò¾J‚òöŠ©ˆ›Ÿ= üÛS­ñ©R#MA¸1)ÝQ †¥A¸ÿOÿFØQ~ÏŽ Ã@~jsxl Dj»¯iÞM!(4XŸ“Ù9ïÿx•± ¢†¡) ê®b¸÷mÈPwjÝœ7Žu(Oä.Í0”u®ÁŸÏÕ·tÕõÄ:ùÄF|b?Îfùûù7&ê¾Ú,’ #(ʾFšG™5(‚fláyîåî£8;ùEÊĵl êMÿ®5wòÑ/ÿ'ìºÒ&µà•~DœGÀ‡yÈ0¤ã[¢[ÐH{×ûT0B´:Võ=E¹j¶A5°Èã( o Ê£¨Ã'„¡;þ'(_åk2Nâ}ÿÔyƓ·˜‹ÇZq2ýŒ‡.Vñ­íMÑcLçk<4ÊJßš¸0'(jñá7 k¸ófo(Ê3PÂ(ÿÌŒ‚YÈ/rX’ä·T@¿Ûcã TÚˆßXTù@ºö¥8¼Ë¬¤wŒÎ·Ã'e:f¼ùukLP5g©Ž’_¤úˆ H¼µ™À]¦‚]_$ºjO‹?I¯¬;ÏøãÈÊæ*?p¾Æ·›R?Noi-¾Íi-æcéÆð´Ör%6< 1—¶‚¢®ï ‚o±1ÄÍyœ”kÛdsSL¸É¼}cˆí#7†G$ñ´í3K¢jáÍr»Vhßdu‡¦Î»$ñôíÃedG¯en Y ͶÝWõX ð$ÅÇ͇uE˃0ÇxãùñÆóøcÆ«^$y•šJ%]þ¥):\þàOÿÆÉòŸ ü=~ãda‚gYØ©"(ß\²y¯% ”~ˆ¶ű§µ;õCN …ÖN˜‚´QQˆoT•W(árSÇ9A±sZM­—|zÞ­Ê ¾òo·m!Q»ðgJ‚òl¨1ý˜aðýûJdhÑS±ÅZqÐĘ(áÓVSTx1eaÜÓ}Û~‹¤ ¨ˆ*õÈn%öD>©×:{šEœ¿Ÿò•‰.D€˜ÁÇt/<Û®Ž$ãÌmæªÎ ‚òŒ@ííTÅåß÷œ€ÃÜBw€BƾŸ…Ùá§ÙѦß)J~?в|óaœÔ×aöþ+!<†v®kôý®^#È™¥  ö$‘9³d%(ß°¯†~]éµà”ÿ§Zócõ½xÙ=¬„û¹ë e8 )©ƒÓ$J‚bJš|óc†F¡\%mΰ‚f‘ByöÈh]‹• |{d¤¡‚Âúç¸|aä&‚cþXÌ™ñe/‰ "uX¦áŽú\¨<ƒ¾Ë†CXJWõπͳæœ\ËY†ßšŒªû¾£Ïï0{ÇELa‡‚Ó±{bu0/\ZDܳнØ7˜O*^¨}=Š­ÿ«·›¬“°Mƒ…fÜ)ãŠ;™gƳ+ðD؇äp¤qQñîHÓ›²?"¥’Å´TÃD7$s.Î">ê—a½Á˜%ܕôÙ˜K’8ÍÎäô2ïÌΙñ¯Ø’ð‡Â|#ÒX¤¦XUáËò¢[7ݹAßAüˆ˜ Ø]» ¶ÑæIMQ–xäîÔDñˆ¼£o‚¢ñí÷ÛªŒWpfKo••TìúaÝT&.¸eK¯œ*: ôŽù@a¥ï{±ðýíéoÙÒ+©*®–Ó[:Ž5©Êå¶ 0F`Ð"*®&v¿½$ǵ:Ò?(̳&ÚÄÕRÜáNE¹ Çk/³'(f}üÛ~éµ\3¡%>Ê+¡„7ót´¥–æÒšÒ™€âü\ÙŒ+ÄX] &8tŸé%ë¢Ëà A5ž:÷4æ`žBßbÅ×ö›mßl!(2N’+Ôü-¶ kèߊÛê¥0WS wPÙfY"jœË®'(Úþ‰Ô×]\~‡Û"h[½¢6POŸv|†f€PoÐÅœ°DåÛ–wEpíÝwÙÖé—”k¥o(; o¨ÈBß ¶ú†Ë4adážòc]=aLhñ]ƒ§m²Žð†"½Ñ/5Ô“°=k£?­Iû¬ªZå A¹–áÇ¥m )U(sðtOš¬ýÁxªBùRyðÉP€m°Ûº¢ûhÊÕ.‹Ä2°ªÚPÀ9~3“ñòìã7 ¿Q(ËøÍtß(”9~Ó‘ñ…òîCø¥ÂW+‘Fot´~(B¸<Á=AÅNΑU`³\ä?ïUI5‚«Ø©F:B5¢PÌ©ˆôˆ@…ïmâ5Ž"}œÃùÇ˪ D}wtµ&êø‹>ÆŽ†0¬žjáèçA¹–!é¥ÝóŠSÙÑöûÇeú-ÎM3(9}œ eº m£ýúüé6Gpŵâ"¯*‚b”¨NIÔð- ÀúDuw:;X¯³ÓÙU„ÎN¡˜e¬ñ¢³S(×BLzÑÙ)”g”0…c•~§ “u„H ó#Xt{ÑUñ“›×ØÆ)ǬÈ`ƶ-ÑN|\;±ŸiÕsù†<ްU¹xXØþøÄ~G£5E=û©µ÷o‚ìPl(Ô(u­ÖÞ"«}´*ËQê"ž)ŠÝd䤫,ÓâK_A¹·ß”ÜqRe|Ê{†)q½‚W eô:>¡I#„gmY®cƒ&ZC)Zç¼ÑúD»Gþð7~Þ¥Z”ó÷÷:*v  ”ó*& –ÜùcoĤ ”%Pî;Õ.Þñ}ÄVÕ!7*®C¯i~xÇ{ë­N²UQ”Už`îš©>JÛHB¸±T¤¥dJD}-* á¨ÏÓè&ˆ+ûË¡# ÷oÄ*‚z`Q(G·«E o¨]ja¾à=:ìIº²:)Ê}æSwôÞF¼wð'Ç×éì‘kÚ&ÂþÖ€ ´"Tƒ )@Xu=429Nð<ÂVUU‰× _Ú‹‘4] >šõ•äò=òª›êú†ºÙœãL;Š3ë –Ü!à 7Ÿ\JÛpUœqœè•ŒlŽÃt¢ó\Ìn}ŒÍNPdœ÷Dåk•/PHttgV͘ÆÕ\Ìu;aÀƒGau8ßÊ¥MîèçtI•òŸëÁ«‹âP \݃¾ü­EßÇìUæ=‹‹( kÂ|Û€Á1ð“ôoð7>×Q°@½§Š {‚Eßöe£öyý¶ÑÊQ1 SÐevlÇ5Å2‘nìtžçVØ@B®¥z5ç@Ç©PTL§@ŠvÁ/®—{EŒU‚;ÛÒiJðW'¿? ô†¦®&H@:®NÛ›A"yž^lœÛŽ«S˜c2³‰^HÞd@¹†•;†‡Äáô©;ºš°+Ò¤ÖCºâJx/gǺ¢p59š#é&‡2áLk‚oÈ·¹t„ÊY û˜KE¨œê™Êy#(÷i”­7|$9=FŒàL£B 1ïDPæˆQEGŒ:M~81Ì"|G<HqÙJ (ï(€k‚z¤†‘RÇ»ì×ö¢ì;üÂqÏö…§÷þ yahŽ©Åß¾‡¤¡ãMîýÎ|žÅ¢¬ÅîMˆj4”kkf.—‡Óœ™íM—¥lø’”¯‘¥@ïØní(fœÈP.'òVÕPþq<¦¯*Ê™òe®áw&(÷Fzw ÍÔs ç§Ó½#ÎÄAÔNØ èxwñ´•Öów˜Äv”!"…# ù<õºâÎÑ‹˜{ܦzh›iÂß¾QíÖ^ëM%êó>>{Õÿ{kD›CÆInâȈ#×x-ö.¡ ¿Qw¿Y )¬@yöÑÍŠŽn:~`ä U¤#IùñõßÄ‘óí„oFM0¸õk³¥ä ìB•t|2™¨HDÄËü~õ¹gN5žDY¦Võó ÷MDÁ™<Ž_Ý Å2ÍdšB‚d•™€7DnÂ)K1IסÅ$$H¶XWUoL¢ôY[…ÃCN ·´É‰e±¬ƒð—:á¥áo¼Qê’cVû®î¼ÞL%îBRJÒd¾Ö±ú%#X€ zOƒÖo't^(«*õÒȆtêE<B×Nì‡wT(özGô'4Avô†äŽNÉÖ¨=$/Ü)Š=‘¢÷xÕaì”¶ð†BïIöXRrwœCF½ûöfáÜãc÷P18rGÞwœ«©@_îªwœ™-ÝÚ‹.YkôWCÿF>+ÚËù÷Ý¿c uG#:-€¤ØÙ§Š£©dÜ,ÀBYG…2¥Ç:mŠº‡Îc'ŒŒ¯ãøcÁ—I”:¤Fq#rÞÔ5–ûå>YòWõ£ßr|¥¤K°§Ø9+j ëVuͳ2Ýa´À‰ŒÈP忺^¼Ê|€Èy¤i?‰žŠ=É\DO õLôTÔ#ÑS·”÷$…qGô,JùSòP e¶¨®±'òtÏ)Pš¯8¶y‰(ÿ5æSÏ<Æ|ô¹‚g¢sY)Ãk…öJYG+eNê™-õ‹"•Ì€²fËM!¢èFD‡ ¾!’Uüç €ÎÄqj–}¡!ÃùPq+B/9âV®*Éßoe¢|â$V´À& ç£5[©oûbë*9šå·@£Å¼²ü-á¨ÈÒʵ H¤KˇbÚçã½K0àµ|»ƒˆšYºŽ ØI3žÈMÐE#„S¿QóWUó2§­°qàû²¿?ã7‚]mÇa^khNfúUylæ+Îǵ>È Ê¥MPû]„;Ô¯PûE”G·Ž?®8ŸÓùW”o<ý0ÕÚìOßЧG”ùô3}zD*|úòפuµ¢Ç÷1¤Š¡}0ã\C=t 8ŸHËF»š×¼žy²ååÚä«O‘ ±¯ä˜û†ï‘=J™R/ ”k­Ò­ù¶=FMŒäÜÿEAPŒÓb§-ß‘ ØˆR ”ÿ&J¹ÿ(Š=Ê1ão´\9f8ùØ_`»V©®5ão mÏë5r®®>T· 3_ãÓG¯–|ìê&3q¼G™ÿ+>áµ>o1æ'˜ógc•Y²fQ7 […øÈ® UJæè4íX”¹´9ãS (f^Kïp„OÛýê´ä§jû\—{Óq’aŽIŒ•ÅA¸9@Ž)P&Q0XòaÙ×¹í(Š=D¬ ä-P¾I] ÄZ÷[FØÑNhÔPxàw¨À.î¾|³F¦D6‚ºV5K ˆø•{Åq^µ[õaWOÿP}¨vR}`ÎÇÌc*b,%ÎÇû{çƒlcïÄX‹2vÏëb-¢Œºä™*áýöe|*ÔÓ{Äq!Ƙ=:©ht˜ûlõLeF'NåÝs2X,¼¬ËÞ6»wË(þ†ÃÏ'é Š¨¡âbÁÖõGPV!ZÒzáz= ¨ŽWe‘iN´v²ÉÚ ¢ÂwQDEf¦¬\{X9°…T|ÛB-zŒT20j:^J|4âÛ†Ê5»ªÊ'BÅ ëªdÿ­à“3—Ùé½›n¯•P©@¹vc@m7Ô9fµãsyïU$DY„JÁ2ýª¸Ëv°˜n`ï]© w²+Ì ;6’ºàèñ¹ácïÊåû2B·¯÷®lgÇ#tû7¢`©l§ˆ‚*zÝP\T >¯ t0*n `õyÎkÏC…(ö$|^qù>9 <‹ÔÁ±£³½Ê;øgu¢>ަç¾X ŠºÆ7T›ñ<ÏMSà8óî=nD¦â}ƒÌsÍ~L8݇½Žs¨á3ϵ€c¶³®±½žy¾I¾Z íx²ýp¯j9w½o÷„=uPGE=vP©7½îBÜ÷בµo²QÌ @E¿Iö[¡Ašy–x›t A¹ÝE8ðŒ(ψÄÎJÓbBûuÖÎ!8ùŠiüimàŒˆÃX%ðŽO$„n_ ï¤üE1-×qñ‰I™ï¼vl ½×I à|‘OŸ-"®íñZî­Îw|G†²Ÿæ^˜Bx¾÷*Ú ÙNvQ¼ —V*Ïoù­7±f¾)-ñд\U$vU2Ôü_Žƒ}E¼¥YÏ ŠÝ³éÇ© “HH@ÅüðUDO>?2mÎoK¡øµ@oû¬d ­j†¼„õ$–uìñD¦r ?¦:ŸÅÖYsÈ›0}„ŸÖ~ªÀ}” À£Z3Œ-¼Ç€ÙãGI×O8|ÂiÑö/ˆxâ8­8ˆ¦zN!-²TbÇ/>—kXòÓbŠ-¦.úféä|ž…ÙùÔC\›¦ø ¯q­ò†M~L÷ÒðZÁƒ¬vK(mÙU оZ ´­(ŠY,æ!«¾ ©¨Š:Vð–iYÛ¯=y4ú >¯ùUŒ~ƒ¥&_vR—Å:Œ`}Ã?$U”2Ûš1j ûç ÷´Ûú• Øc½ž>d¯žz¡û.r]Ô³È5½Ö³ÈuEPžuO\ÑÜ£œ‘ZW¨Ç=þý%µn—jÁ§÷ߥZðZ;º»íèð}G×e}ú‹¤™Ý&J Šü®ATtï9¥žB&6¬W¤S#©µ8ÓæºW‘aô§p‚ÿUÎeÙþ~E1Jƒ="ÂçkP2L<×Ù¶°OÃ4©UýÜ|€Xõ›Hi¾PcÚäV¹ìÑÍö¦Û0‹ÝÇTÜv~tòîß%®ÑÐfEôì f"ïQôáQÇk½Ô‘'UGfÑÿÔ‘7‚z ˜UudD¹O’(èÁDá{¬o(ŠôŒ½ÿÒo;o@&Ê¢û{äJô¡âu×5Œ¼22maËœb®ƒÖN,™Ó¢lÊKX œ×<ÀFQ‘kе9ÙÇW$+ú¾fñÐÏÙN?窘T¨û^=»ª"VÔ 'òçö|iZU$Vº®ó¯–2ÆX”TE9æó7NiQõ9ZßOô”gÚù>ý°Þ¡‹‚«Î.qºçñœc¶óó¹É}ajþ8‚ÒòL@ /½¯Û½GyÎc¯º¤¦s“笈<§BÙ¤+G)¹Å€rž„$ØB÷ÙdLÊ"]2ÞÕTʳÈV½+R¶ªƒšŽkHC õuE©¯]MÜ ¾®ÊN}=)êk÷ï>qgX‡™›|^û(“Ý¿à)[ïU…Ö×ý ,]®Ø©TôÓ„ëêóª¶Ë•$A±‡žSìõqÿ¢W¡åï¨Ï› w»Ÿ7A*$îFÔ)ý¦ áNà ¹Ž–©¹u+·MEQ7ÙvÕóç ê×ÑÅtH&°V™@×qì9¾%ßkÒq¼#{ï¾Å;ºïÝ·A=“ÌS”{Ë‚”Ù>çU®î¨å E½+ n™/³8E!jrÝÀÈœîö:e|lg UvÏ B¢#7˜@eÚ$åZ#Ö3ÞvÝð5Þ®k‚zŒXñKsIæê8+Žéó>'\‰è¹?Zʬâµþ#ìZ“]Õy唨æpOÕ ¯á¨=úœ¿VíZûWclYju§Þs-Dî»9­€~5ÃH7“¾æ}3àbD,ÔjÒªÃkk>S…œšèW£ÐºÅöØû9Ï+A…¤ù«ã¼´½Äu‚Yú~•ÔŒˆ~• «fÎ{æìZ&ðˆ]Ù·ºAÉŒ(Í@5/ Û¹Ïû|é0ÛVë_ÖæòÞ—9Ü݉Õúÿ]„.óex½²¼%¨è"VLêý^õ»Øð{¤ÒjTèr8D?W){‚â—•©®uÙzTzéøŠ€õ]³äÙ .¿ÙÍ‘ÏsÚ$1à"*ôæ¡rq7·óWŠxd«d€qÝoýâÌèãè\)^¼ÚÏôÌ-AE—ç:9§Û/•=dåäûB¦&â©wNÔ#AYºþ^¤ë/Šoþ®¿• ÜL8D~&\CPW6V g…e¾— ^Kgc•Ð{ *ùY)ÊY¯Å¯#fnÖ€T¬(f^Ö@C¯åT¼Ào;f~DE~ŠrëFIäètÙçê6¢¼j”0/— ¿ÇÄmØøS‰î­°`$šÄÎÈj”÷w…D·Ô,”¥f³¯Ñe y“$qrD~ü¯(I½+E…—ªäWó÷KnÐo‘J†Á(÷€Õ$5˜$êZÃöx¬øu…ÎØŽ¹ÔOŒRejÞý»x×wè€F»äÒP¢¾È×w¾4ô©Æ4¸æ¤¡nWsídGTäe@ý1¢¶ÚëùQOaž²r©!בgdÔfèÛ¼«n%(Wþ«Çu5}³PeÉR=k­ì§¢øL=(qD†vŽý<ÍÙcÚ×&‚ Ê8[w$Yë—ŒÛsÞêÏëÜ·™¦]¤+½@œÃn÷7JD…v>f×LÝ—Éô>ŠcèaçÛcíO×൘o-|Á·Í¼{|¿TèTíCTìÊÊ_V‘iÚE†5ÃP 1¹6M–A™–šÇùÕ »%žÎÿ;ÿÙ-ut§4¤;…ÝR{ç!çáÝ¡>£5 ê.sĘcYƒŠÚÊT =çóÙeuÿš‚ FË# ®]’w”J€úPÞå3 B…ßÐ%íg!¨ðR‘:çêQ‘ªJЈGÔå7¢Lî~­©ì'‚bŽ®ø ºâUq²uÅ:s00ïæíF”A9G¿Z[çî|ýþW㵄ÍÚù¬7òµT9 b3'üýÔÔ—Ð˂Ē{<{u‹ö¾Ÿ‘;‚ ‰ò%ênC¾”¨e"Š*«–“¿¶E–^+u1y_?&/Óí«Õ—¶G¢Õc W—‘ªÈÕš~$Öô,4ÎÇÌ9fáÒÞ•v$ çT0Åy:Ψ`ºÑkE_N`‘¹m÷ýÙs¨0=ç®V¦ãDñZW¨#3j«m©IC………Îzí¡K†J¡,L¼×Âo(v}¹ŽêË1½ú éË5šoh:ßÄ,òiË”%ì¢, Üú&ëÕÂü¢½4×ÑÑ\ÓÍ~µ\äX¤™±ê¦àx-æê€&|qï¾óëÞœ_‘ðëvR”[·s$(·n§$(fÉ)Þy%~•i|CîÞ‡Ó:Pìf·—Ô:œ1¿ÚÔXÍò›|9ÙâCïYß#éD°êà™?;Œ×ânUÛi_™à{¤\~‹-¾!˯+Ñ✠\~í4W?ŽžD WgÐ/¨Ðàbt”‹ÁXâçbŒåæb4|€–òK½|€i%¨ðªë»èþø¯ÖhñoìÈp-R ør}Îr¹äSƒöÕŒ»V&ª½Æø+“$¨Ð‘©Áºã×Þæ¯êè<¾–V>¼Öo~ý÷Ÿ†Úª÷m­{àÛ¤ÞvÛsn+0 `—ÿ§›¾Èi£xÆK ÿ(ÄæËû]5Ä&ܧ98õ#Ž}jôóaE½ë§ifßì]Yõ”½Æõê,,œ+ù/çÎbgµ˜–egd7Š‘Íâȧ§€–®,ÖU #Z-b‘rj(*¤³º–›lëÖ0\1U³ÞfaÌíw|?Ú÷Ñø (óŽóõŽü¢obäsp$ôú¶²Þ‰õ‹…/sºàœ ùh«*äHPnUHIP‘•U·ÿF|„¥¯"dHdfK^ß›{GPáï¬Pc6ý¹ÇãŠ1ËDp±®ÎÔ‘µk†ûû™+˜ 7Ãø`ûá¹C\»p5î0rܘƙÿÅ9ã*tŒM»²ÎÕyÛ†l¨È!3M#èäZU¼.ZùÁø^DvÔ¶eEÛ7 >½Ö³H9àC5@‚%‹þÌ–sVŒæWÿÓ®U«îM–hÚXy¥òÑ{ì>Và&ÏÏε$Ž.e ,½YN¿Ää²(¼czåèþNÒ;jëñ„Orßóv¥ø˜ý6Ày;ÕÎ ÊÀô8IgŸ¹¥¨ÞOåûµŠ w>M7ý¡zúŸÏûœïkþ‹ ˆ1a©2E[Œœ_éO}Q‰#0"KC×Hì¨Aªßꊴ¯iÿ¡Ñ7„w&YHœ9i qïp$Ún—ò­¡¨Ð’SØš¯Î#J-§°£”Î#ÊßµÎ;ù‰íƒ#ÁÌkÕí³:–XÊœ|¦g6¡í6#݆íö¢l·™Hí¶Û§Möç~¹–Ãvû¶ÛˆrÚn¿ßÅ­öé­²OgIè·O ŠÄ_;¦g¶5#X²T«HýŒ–^ÏÃ$¾"¨Ðf}[|­oYMmej‹(§]í2”Å®öÕh%ÈÔVFû#Þ)J˜¦£Ëýõh:Ên‰–…²Dãu(£Ð™…2âr5÷¤®ˆb†Zø>sþx|ÅmÖžÅ×ÚQ±ÝdS¹g"Ê4Ïl©y&¢‹)¦ü™b"*¥Öað=K¶U#¾!­3è:ªrê$A™ºéCûž‡ßH\{çOÿœòô?nn¶û³›g©3ýÌvñˆ ³Ýó )³]DEN#ù‰ ˜ËHþÞ”iX·Ëaþ^Ý *6M¹ß÷¥W¦ÜL§)÷Ïœ˜i~Mºu÷DQ‘˺ÇK‡¿:uNG·¡~ßˆŠ±?çÄwì…ðû«K‚JLðö}Ø€WôZ©iœ~¬ÑýG­÷âgÉûïkŒt3ßYµ/sÖR³ ÙZïÇû÷¶Ï¯œ ˆ0Ù£AÂó4ä­êrćǯ‹ì¹Nø©iÅ„ ém™¦GCPŽ;®«:\¥I*êãAþà”NLŠË‰ÚCäaš>˜¢LˆÚé2Š‚µe³Ÿö‡ ßÂû÷¨Kù:®ûA~ì{‚ ¯3….Є4‹:¯i‘ ö³FÓ^çí¹OAEÔú&Å2ŽS‹Ö¿,‰õ¶eRlš¦?îÄ0ÕS‰ÅSޏ€¥‰±qWjã~õýCa,¬j{Ï_ŸUŽuõ‡€õ¹mÅŒw"4÷SÔM/÷µÿÌ`ÓhÔûÜ9¼HßO\š’ŸAœ`RaÍòçþ7~*6¨õõ¸©Pèã¤`‹ ŒÓ¦m®š$·ùíf2Ïå¼­]‡ÇrRH¶%ÝA‚™ßB¿|ƨÈ/ŸAQÎD¹º#3„1hƒÚˆ(î?Je¥;z”æ¤ÙÍFèðŽÞ¢‚9®’ó\•ç×¹_ú× ¨kºó›99Ú¤+ó_!ÙnÄ‚wtI¡Q#~KÝc_(²ÁUé•ão ü´M(âó@Kc|‹s”ÏÅß+¾£tx„f³P²÷moè TÆiÁöZºn²¡›AΆŽ&–z,È—0s]-‘œþ)‘˜†¨KÚçŒ ‡Ç{Y D1R>Å’Ô´mcy‡V=Dq³¥„ éò€ûåFpìc·ÜH§äF8iv3åFT£¢"kR´SIQ•d’¾íĔƩ¡Yw»O+„i<͑⯵YŸëÚÞQø)8ª‰Ýª°£V…ᨦž¶ÒQÊ/òe–Øv¾äæµ Ãu" œ’œM¹½WÕ_©Ì.¯Ž×Š<òêß§O"­13ûÚ;ÙØJ αT–¯ÅV}:Èñ„äáómùóµ¬ WüWð°ŒâÓs=ކÝ>žËþڮ̵ å]¥­Ï zo°š¬âWùÅC?g¨ßT8ÙA« N²ÃÖŸK+Å~­ö¥iiz…ùïkµÞñ¹˜Ã§^Úóƒ׿Zø¶·î™uݸâÓ;Ú7Áì†`ñÍAU_ǨÄ/cÞ*õ PÀ×7‹*Œ„f’©–ñƒ¶¹É] ¨P§çh±uò½æo@i¹Ç¼ŠU¾põI³ˆºÖ5-ó:Š×úÞ±Ÿ×–¢tùkEGÁ¡XËâ~0ª4_h“9„·/ñçDøålðŽ©ý{T"Æð†Â›??× ~‚¢ÒqûöލÐkaÝ!*²›xµÔÄ+M±‡©ÞÑ‹×âþl|ÞœU×áÊ ]æ¶Ö=Žjâ}.ˆ:bbÀýÿǵJ¬ºí7”Õ\A6=Žn¾ñÂØ$޳…"d’¿ÿ2¤€§ÿË‚¢,Íh¤¿ñ›%S•Xlx›{] ãQܘ_õÙä»éG0ñŠ£ØßàÏ%´•\}Û)ðÕ@{]Ìn Éw1­mr@FkP DÏ×AVl!¿ÿ•Kƒ9ÁBWsàA÷»¿q$"¿à|š©ñ]‰cåãRßïjå1i¤À¯wÑÓNV}µÄÒÁ0èk«+*r‰Âá·Íþh> Êmƒßö/—ffÜöÕþýTâE°würiÖÊ"ÎU~óT%žbbŠ`Ú†m®L$Kv’}N¿Ïƒ§°Ï‡©‘£$¨ÐIÓÇké;2˜ÊƒØ8@Å &BH—õK^Ö/’K³5Bµ&Ösi_+òü½¼û¾ÇçJý&ª°šðD¿–â)¼òçIÍ1Í’)Òü™©ùìô§i>EÇeûªêàÕß$¦rIÿà{<ŸþÕ¿æü9B~"&f ¶¯ß¶fаÏÕ3ÈŽÌu¢R±ï8CÓu¬|3à’fÀc’³²¶àÀÛ&9«K†RÒ ek+y^(ãÀ"_»îŽOoæ11‹1<ŽZN–¹ÛOs0'âÔmÎóÍZÇ™µ>ê|ho‹ÀÞLYïïñT=M„:as0ÃR/Õ:–^Z.QüUíçGX}Eä>Ôß3Œ`n†‹T —˜Jî_N¿T”$±_”¤!(73æ½ðžÑt#‰ß6 Q©Mz_}Ÿy»u [ÇÉÍËI*'Ó,ë'Î'1êÓL².^óºâWkd}€ ·G0{„©ŒÝâ„Ù;üó×k]rxyxŸ÷5f;—aWÈßÇ ¿ÊBªl¤Ù‚8‰Ýœ‡ý0 &81ÉÔèÕæzX±Ú'š€´öiû|Þw¡Ç>µ[šæKQ¼«Qâx%ÚéW¦£Ò¿­Èâ‰S‹ B}2›lxÎSKPúê[«sî¢iàɬêòʳì‡w¼Vä¯"Áx¥Ì¬6ñ5hQSŸdÏÔû#NÿxxGß{œÔ{Lµ¶R%~+©ø­¸Ý¼•Xˆ¿ÄÍ3ªe‡£*nדá•~ûù@¥,NSõ%n>—‹5ËÜSÚ¾B Å£=»ƒ;ù¤°ï¨©AÚ¹nvT—™¨ÐAÉFs A¸wòp3âxéÙÌœnr|Ý‘• ¶­6¹¼£ÍDâøÒùy^3@qûØŸ´s5öâËöÃÓÜ‘å?®õÃî!õYÜ„ý áµà ‰¿„ÓáZ$7ti“´ O‘;^•+Æ«‚d}¬‚C0^7ZT!å6åÅT5ÀÆ/[°/äð ‰Ì“KZùeñQ3'H½Y Í‹Ð_É€Œµ³Â]´¼› m§Eú#ŒÍÔØ¢Z¼£ßXÇ+ÔbÐ2w®—º•Ÿ|iá•'jd`N¦’U”æ—+S£ññ¹R#>E…®ñÂ5GÙ8£Úó¬Ðe¯iÅú¶ˆ´(­8Ï…G@‘¿Þ¥«{D])N!ÊvX^C5AfKDûŽ÷{ƒo[“âPÞU>×Y^SIP¡¯¶4^QèßÓð7r?£Þcä7ŠÍðZŸqÃk%Þ;ÂùQD©]ªj¦RU‚Ýìv-å ø9’ L’¤$ap4Ö^ëÖE…. Å;¢˜ýlÕöÃPɲƒ·ÍôH{ æ©8$L{D9„†¦.:9ì ĘòÈñJºw›÷+{@@°ÄQay½Þuµ~ðŽ©×&ª5‚ß¼œæöZè14Jï‘ÂGÞG ß#RŽ´f(xä_ á7r£ŠTŸkŸC=šæç¶8º®öoü9T®\³ûT­Ù÷O¶‡ùTÊÊ¿¯Õþ¨žëÝ f×âûR2ó:ϪìwE¬™ê¡sUµ/÷ Aù‘»ðÉuü»Ú}fu©,0Dy÷4ÈOˆ˜ù£m˜9±…)~Æ«ëý¹6Å3”1ï!þ:öZùø@n[ÄþÝꉿ1ñË "*µ× g*ù*ÄÍ•õ9„Ü2`° #‹ñP¶{d5ÈD0"4ÍS*Œå¶NkSffùÏŠçÖme©važÔPñ¬‹µùH|z~©+äê”Ùõ[—Õ+HÑ Ò•ee°Ã{Â^ÕíhUWmÍ9~áùøëþß8‚u•Ð úþÇØŸ$IŽë\ ðü­â_‚Ø“Ão~Ë,kÏ1ðÖdÿÚhDª±ûý@‰b tji÷:|¼<Êgx€½)/¨ç›æÛrhæ½P¼ý:î^”z¹·Ã¼Ì¿?®_·#ëŃ>'µDÿ¸Þ~n'Ê–ùí£]ÒzœM¿ßæóîïÁœï˳àhé±ÓF¸Ó¼ì˜6ÄÝ!‰ý8¢&Ël̃—‚·9ÇÝKEhɦMKv9Z½x)9ÔtÔÃXº³ÎðåïŸõ€£ç³nç»õXa„±‚W{­cÔ„WâaäÑÉc®Gíx=mŽ’uÔˆQŠÿÅã¡£ÒPáh•àõÃè„44èOäµB P š¿±ׂí[ðúrÜ—}¼¯TWþû¬+÷ }l ýçl í•+P°!Ìß³!Œ×º¾·o÷Ÿ×?/?·ó iB°lr€sœ¬WžE£i=dð}ý¾|ü^ÿ9î+V?¿Ö¯} Q^q—?ëß–•(ùÿ Û/þ÷ïù‹›~òøûyþÿ}…ÿ·ÛþŽë‘ÈuœH‘ÿ·=Æå9BÇû8íЄ”ù”.úÒÏÓþ7#¤¬!·œþF¦D¤J×ü_lŒðþ±"·¾ —q×Uw"5¼®_"__ßùÓ®Ã<ÖÔ¸,ÃïËpCHuÜç¯_OljÐï"µžî©7ä)Ù›ru5À÷Ÿq@Hƒ‘+îDë‹vEn?ÿïYÝ´^suú†­ÖëÒ#¤#ëZûý‚žD.Ó!CyŸ–iyù‹ß|·Aÿ÷Ïj•×ïõmø{™ïCÿçC½÷åU% þà*Ô]7ÑÖ/mïy³OZüï=þNBCèû[‚ÞïPSƒ.—ñþüµô2]Ð 5eºšˆ$—é뺨ò\¦'òxSû2½þýÛ#$½LŸ¯B’ËôëmÀHf™N B2Ëôó/B2ËtÁOÄ,ÓÏâÍ3ËôõC™eúûC™eúýŠ¡Ô2]½ª¼  ·L¿îoPb™þܯj‹…ÒoKjX6UÙ’l¹¶.© >ª«!w9l‹oÎ6ÒÓçÃqèܲ~>ôøÌ Ä}ž¿žïStü}æg¢ñDK\úBò¿þ÷3ý:yŽ­¿ŒÎ1¡yd>ÇuŽõÛ7‚ç˜ Ï±ýkÞ¾.#BÖ Ä4âsLçØŽç˜ÈçXÜ!«¯wî­ÿz:D>ÇjHp:ˆ|ŽU‘ùpù«Ÿ ~öh jgC ôÙPB%ýéÓÙ LãÓ§³AöÓƒ³APgÃr.Ñt6Ãú|6Ã~zp6ÓøôÉä ÓøôÉâ ÓøôÉà Ã}úÕÞæd¸O¿ÙÛ*h{[B«Gøö™¦ßOÑâ ho±§¹}&¸C-éì×|Í;Ôñ6|z—®Y.¼[±D=¹DoÅõä‹%êÉ%:KÔ“Kt(–¨'—èP,QÏ-Ñ.QÏ-Ñ.QÏ-Ñ.QßZ¢ø>Ù%Z@¹%Z@™OŸ¦Ðøôù` 짇S ¦¹8˜ÿéÁÁØO¦Ðøôù` OŸ¦Ðøôð[â&|ŸìÁT@¹ƒ©€J&²ŸIv­ÈþŽ\dHѰNÉw’’ðÇNdöÇdö²òÂûˆVt¾¼Þ¾"RsövÚ{(@¤<–Ó1;2%×~˜†mäD*yº!¤&ïóó™i8s¿§o„dîóë !™ûœßRÇ-ÿô·üúæ±q‡d6²v~Ï>MèY’}ÙæÂÀod³q˜÷_?Ãv ®Èø<#¤ÁÈó>Wä<ß0ò4¿Ž¼±cÇž[†Ÿë !…¼ßŒô5ä²!7]DúͧYºÆ›O'²tü›«Î‘„Âöæáªsü›¿þàk’o~˺#$ýæÇü–ÿæß¾0’~óãFžoþÿö÷ù¶5ÿاS¬¦ö3riúBÈá¾üÅÈÚ¸îbt JO¯ùˆøBó/ðæ7äírûºÏiHämÆ¿négÿ9ÏžhØg~  ”¸ÚyäÊÀ?ûÖÉ"égÞf„´õÓpÿ‹o^q§!b¯w"F\‰Æ—XŰìýþëB, ~"Eؾ´6JóÈlm”&¬ÍRZ¥é[¥ kÓ—ÖFiÂÚô¥µQš³6ÓÏ¥9k3­Ö#)k3­Ö#ýæÓ «LãͧVþÍçVšÚçs:a•áßoýíöþ„ŠDÎ?W„Ôä}‚U˜g_Ъ ûÌk)4îóyDÈçýž\›¿´Œcÿ'Ææ:Ûù ò:öÉÐ}ÆMËíc=g’ði×ëæï~ ëgÜ´†±ïó! ‰ÌÊ´ô³Ä¢EãÙ“'uìij¿\愬Ÿïk¼ ö‘ü³¿} I?û-1lÒÖ~}Ä MÇ›#Î’hÅ[†­.øDjî|ŸîC ˵á²Ó6)"-N)I¦]#‡Ÿ<í‘~òm´oDúÉ·Ñ|¢gˆL×ÊÍÉeˆÒ5YýôÖ «_€ù)ÃêvùDD*þÙóZ2šüš3ÎdÓúšq-ÛúšW„ä¾fzv:Þ±¯h<̾¢ñä¹9c_Ñx:Õ}EãÉÈtľ¢ñdd:b_ÑøVdzEH.2ÅH.2ÅÈ@¿ùä+šÐxóÉW4óùÔ6ÖÂ`6ÆþÍg_ÑöÍ_Ñ„sEHŽÁHŽÁȪ—>ã5o;ÒKŸñš·é¥xÍÛŽÎà5o;ÒKŸñš·é¥ÏxÍۮݒ‹0’‹0’yóiÍ[ÑxóiÍ[Á¿ù¼æ­ Ó8>²‚óyÍ[Á¾y°æ­hÅGw„äâ#Œäâ#Œ yË›è4´ðܬ •çoçfæü­&ý¶ SÛ6ÎÍì ØÆ¹ ®Ù87Á³ó>`c,ïƒÅò>à—,©“)õ<ŽÔÉ”!'¹‰%Ú:'yŸöžžÈ)‰]3¿ŽŸ¨áQßÓ.v–ó?!_ç,+Ι}GGú3Îì;Ç_3göé8³ïX%ô~]à#”[ZŸ¾kð!ß1êñ ípŽ|C;ܧýîÚáËxErÔ3f³½æÍö¤æjc_!›íIVsýFˆÍöšŒvgÌf{MF»3f³½&™üg1¼i<û_Œ$Ÿd1¼atÓ(‹á ÿì9‹á ÿì9‹á Ãä÷Ð*zÖÎ÷àŒó¬‡ÖÛ»Æ>º¤_çô äç=·‹ÑYì¹]ŒâÍÀíboA¬¥Ì É!á> ’²ueV(Ž“®ž\hÈÊZZʬÐ4$2ï£iégOû(¨Æ³ÿÅHòÙÁ>ŠƒÀ«ºMT‡SO”÷QN!ó>:¶b•B`¹ ¡ZMqÃ*…@«)nX¥h5ÅŒUÁpg1ŒaƒiÜç#™ûLªm]¹’gìƒKú`3öÁ£ñÛd9™ ž¶ 23´!…RZt¤ )Ô×¢ã4Õÿ§©†œªèïQ'«(:Í{ÔÉK°6¨æQ'Ï_€BŽZ^;{k¢³¼§š,؉$såÙ«—?Z–lN¤|dòû"ß!€>¿‚ùÑyÚ‚¡|lj$2Œ}ÿ|§á‰¬[0”ï8‘†D¦½y"-ýì1ß!@AýÙã'ºÀ>{ÎwœÈúÉ…ò'’~ö”ï8‘ô³ßò µ|GÞʼnu¢Åº§}$Z¬{ôX„|eÎ×”X&rBPê¾#س«Bh6ÃVÐlv5g…0¼]Ê_ŠókyØ”—ÂrÞÈõ¨å.UßÓü%!<}Ÿ«O ¬ÀYàãä:ÎÍë²qo_©HäýgDHMÝgöm„`²Àë} &Bã>Ó~¡qŸÏW„¬fGl$±etxÆ–Avtlˆ-ƒ¤³À3¶ ’ÎÏØ2H: <âAŠÆ³§A öÙÁ‰ “G€ðI?{>¤àŸ=¯)«x*óŽ“’ÛGpWUÇ)¯ž±Këõ€]‚ªãRÏ0¡5UÇ5d^óUÕq¾O¸>[·Þ'\Ÿ¦qŸÉ†@Õqõ>“ ‘”Ÿ|Öƒd¯R’öó@fOU:™OCÙªRÌ×lU)&ŸVÞOÎgœêxß;Ÿ›ŠãÖö¿„”-½â!%Éä·¤û–2#!”bßRf9„b™|Pe ”!uþ3ÒY eÙˆXF»5#=˜PŽóX 'µ[5k“˜g¡«.qVB5V]bt… 4“">¡;:;€¢H¡Ï/åõ©%Ï/å5¯Î]ŸÀ&kÍÙ¥ØdmH_qDj4¡¹ÕhB[ÒÖÍHv"‰Lj´©ÉûL‹Ðܪƒˉdî3ªûN$sŸ?W„Ô5vkD<˜ÐžäÁFă MG‘#âÁN$Q&y°Y¤FăHC"v"-ýìÉÔ¡ñì‘ÿ:°ÏüyMG‘3â?O$ýì‰ÿ<‘ô³'þóDZ:ŽKožÕní§Ìˆu}2â…ܹ ×¼_·•$^ñD*™xÅ©ÉûÌ6)Çêë¡ ʱú}Þ1’¹Ï§BjF矮©Zð¸ßneÀg„ä2àé>IƬ¨†Ærï²[Ʋ…ð€…3ŽÏ€ç}d¨S;úŠéŒ3dö¬\NgPdÕj¯€Çb;..† © :® <+x–8{,PS­üŠ9}a™œþîÛ$?ĶV]òëlkÕ%b[«.­y ú(™½Gú@õQAÂHßZÚzãHßZÚzãHßZÚzãHßZÚzãHßZ’ÿœq¤Ô)õgOç»u쳃h×:F=…¸_ëøgÏ‘¾uü³gûiyríÜZö½-ë{½°¼š"g–©·9µîÙ£&õ6'2{éNб!æ.œ¤ÏMÌ]z›3–¿®ù¨<‘iÔ¡$âüg¶!αÑnÖ˜ çÙh|#N³@•pÏoæ÷é;N·¿ÔÆTš$€ÓÐÓÞÅŒOC/ÙÆ à4ôŠ< g|zEǰ=bò}C‘•OCOÆïEM“ð–9µ‘è©èl)jšN¤"‘9êñTtÖ5MÂ;Æc™eá]ã>Sé]ã>Sé]1Ë–!Û:ßâÒš÷žVÉbï×n}Bï×Òû°÷ëéýØûõôÒGMЊ— ×Rè÷™¢‰Ð5î3E¡c¼t¨…eö–¬hWÞn-pª9¨tAµêeâîºU/3#$W/¿f`bœ? LŒ°•)%Ù‰¬å¦ç‚¥òG2séÁ\z_æãh…F™ ®qŸ‰K®qŸ‰KŽÔœà.+‚Ô‡ôE—­|X_|ÿ;cHRròuiÇH²Š°ÿˆŒ„DJ’Ç Êlie'h6{ó¬’Ork~½#BÒlvÚG²¥NIQ¹l©SÒŽ“LçÚmÕeŸAv†Í®æÝ!™6£û5“Ï ¹ž[)YZɲ³-]zºO×ȪG-±ì<¯ ºåoDk GÄ{KAk GÄ{K¶'$äÁ¤àû3dë}"I,s**üRޤN$yÍÌ H¡9>pRh¶Dö½¥0|„’üy),¡¤A ×Èså_÷<×4#$a& ¯“"ðk>å"eÑ#ëq¿§û”¢±ßÓ}Ê–Kk^J>ÞÌûHªF–-}#Éåã¶]œ‘d¶¥`·¤dOm¸’aŸ¨š^<{C žÝ³÷ v‡ |F,ïØß¦æ/åÝÁö™@ŽOªŽf5Q¦^*†!G™úY;P¦þD*™¼‹©©ûÌ\T C¾w$VS‚tý>ïøšÌ}>ãkjÒÿL‘¾TŠWOåý®4ÇíT¦k¦k6t¿É“ªa³¢V¬OžÉÚW©èÝ1ãsSÓÕd3>‹uC!œ½5Íž°ð<Ò’Û›ý¶A"R5ÂÉÚhÅÖb€ó]7ìgÒUJmXð¨5çƒõУÖLŸØíšÙ£ÖŽU%åø]jÇ¼Ï äø$ÛGF|R“µÿ[~ÄïR3«qARÒ†Œˆ ’:6dD\Ôä‚fÄIÓ1|ä‚$È„Öï3rA'’¹ÏÈH]g aí€4‚a5a=‚d:cœ5¶é>U#ŠL~2—aÜi†´Œnô1KûÝ~w$žV˱î@s" [· *¤ñ|5YŽ"ç«É²õ6{ŸÐ~ÚŽ÷ç³M¶´¥QAZZ9£<‚´´rD|ˆ´š»&àC¤Õ¤î÷†ø©HdöX,­¿$-S+„ôÉ'’¹Ïä±XÓ¸Ïä±Xƒ<–JmKz"Ûªm¹!$WÛw±uœ ­Ï+4À ¤ï=âh×u,Ÿ b×±5ðçéZõýšÀOv‚;ã6k“®ÙÒU&–ÃIF¸€ŸtŠWÞæ]ìZjÉô•ãÁ1Q9>œcò†Py+ÙZu¨æ•\úñ¥ïîZ£li}ÇGg9Öö¢Áf'›ìeëí¹ssõ2ÒsöE|ž³Ÿ(âó´†|ÆŸ§5ä3Žø‹­!ñùøÞh€§ ²U)?"$W)ß|P·”¾—i:úrÜ’ëw‘žÝ4bít¾ÛòTg„ä<ÕtM×ÈŒ¤ï<¯ŽÎk‰ÉĘ̈zTu§yŠÅäefT媺F4‘ü:ÕQ³¥Pq«N2|2T†«N54ù‘Tæ/‰WTá5'‰5Rå5')FPlfV"«®Õ/¨O¿Þê4ÝRRYKø5Yþ}ÍÀ_3¯:ѱ[°êD×È¥ï.ØU¢%$cm`$¥„â4'ÀcQB3Ñô‚]=ZpÔJX¾j#¯O²&tçÖ@Ì¥„çÎs)º&tPÌ¥èšÐ™|EÖ„÷™c.%% Êé+º&ô¼Ïû€Ì}>_R“1B^K²ãθ–¤àÏâtÆ))[Êœ+B2~HÚïRñ‘~:;”Ô|¤ŸÎ#%™Ú+”ëQÒr4P2+f&ÈŒò2ŠÉõŒ(/£¤#O™E¦Jz®6øKJ¶ª<»bOXÃ*Eưû5Á³«†­ËÏ®è¼áˆz)~š¨Pü4Àý*&‡2ãóÉ¡Ìø|W†‹7á7bºµ¨ú^5s(éÔnæP’MnæP–ô>«òÊ1¬ÒÏ¥g?D³ó&@†QÑÙ–Bu¬È:¾¾P2+­¸“ ð JkÞ»È'¬6 5Z²uÚ¶â÷!ÉþKÀcѬª¨h”vü5³g¥=Ï±ä³˜ï° ê‹•<“bÕè° vq£Ã6° |‡í-'Wßa{ÊUŠï°½äJeãAFBÍx0­Œ¦ó2ˆ‘8‘ŠDfïÂhÆ ‚ ¢³[…`xN$sŸÉ[3¦qŸÉ[34s²çµÁZjtËÌQ±|Tž£ãÝKb®\ÏçßS®\Ñ9”3‚N>˜åyE`?aíUµ'sò—lËL֛飻묲g+ª&;SlEd ª¨zÐnÁXÆ^Ñš­7“›8ò†éÙF–mÊÏÞȲgodÙRÞPq¹ 캎W>ä½éøþÞÀWt‚‹z ¯Èæ&z臸Æ,ƒü>ÉÜÄ^‰ Om27q"ówgs к+¦VhD]S+4¢ÎÊ9î„…qœó\fÆq®ÑK!{ÔÍÜDZu¾käÒJöL7-ì­y¦›öּ⹋lç½nø ù>uÃgÈÏÎWç-ÿ5óŽódYôSjà xÇgîÀwoTæ3Î7ªó¹éùœGrNJ>FqG.@‰³ \-ðtª*y®¢v@‘=E—¢v@ÍväËJ'E÷ÿÜc™¬tRéá¶óŸÉ.NI2Íž ¬zöB#«ž½‹ÀéC`\¬»Ž¯¤Kq±îDã>ã[Ò|ÝÐk¾näauײKKúuÍó´ééΰê”i¦ÆaD¼·î˜ðˆ÷ÖL¯ÎÕb莴6G¯tëÎsZ8àƒé.ð‘~²`ºÑ2Ÿ\ºÑ2Ÿ\šæç‹^ñšæç‹þóZ¨ÆŽ‹'—šg·’UÔ|`c4Sã0"ÎJ35#âÁ4_ã2ŒZ´t•Ó€’ñ½Ó…†Â-½%~8\!üp¸B˜9à#ÊŒhføˆ2#šìÈwt#̧ŒfyoxÊh©Ù‡ù”Ñ’U>€ 5- Wßr»Z¶t¿ñDÐÒq|\uÒs–®d˜ªL¨%ÖªcuþàÙ5à)Á?QþFïH­$oç³ýTŠç?óúTºaiÓúäØll“•mU&ÉU&¦_oöRHo¾ÙKáŽ\/…¸–T =À1¥Zw|¼™ÏbrþæyÍ|kÁi³áY¬¹ ò‚´lõ¹"$×?$ݧjñ!隺ŇÌÉñ!ñ»kÓª.IoɶªKnÉU—¤ût %Iòë´çrúÀ÷Öº¡£Î;ŽïcÔæÚt­Ê¯øìF´*¿îÉdÙÒ¹iÚÂ¼ê ›†^¥ih³³U4¦Ñ0GÆò™»|ÆÇײ%îBÏé‚¢M`5À2ØŽÕduжôÉ5ãh Ž-„Ì Ž…L”¶’³Š€ÝÒVñ\P>¹¬nœGé䲆¯›ÈVÑZ¾J+±ÙÚZ>SŸ×’u|¦>¯%ëòºáU¦UçuëL+ÙV?"oY]zæµç¡xN•„"O©’ÎÆyÏ}MÈìùÐP$)t|%Hö—ZÊð¼’[Êð¼’[Êð¼’ƒâÎ#™Í¿ùü>ƒi°Élé½ÁY¾V(ï£àZ ¢!¹ê’ô–<_”žÀžq .6]Ç{,É4à5éÜ4ôD§³ö*žÅ†VqÙC«¸‹ì¿éL­¢éZz†|Í–ž!?»kD(ù×}«oÌŒ\?–tÍÀ³Äù}Š®qv¤g¬žDFH^uœ×’P¼6;¯%¡È´–„á3#Éc1Â6â÷xÊœH&~'—ŽS6¿Î0ózfõ˜O›mˆ‘­N#Ñ~šO›µÄF š·Aü§‘’ÓYÖHÉö’Í'¬‘ŠçÒÓ {"%Ý12FFêÆ I_Sš†­»¤g·-öà†\¤Ÿ®Ùàëòú” ¾.[0éùð–_ƒ“ßÓßæ¨mI»X ^)š­’:”dÁ”jÄqé)ÝRhÜR’Ѹ¦iåÎnÉåÎÒ5-«ƒH×è™ß§oÄ1Š4<£ TF…†W™Î8ÝÐ×åûÔ]ãŒKk‰é3£¾1¦Ý7æ†\—t͆æ<{+™Þ§nå"Ó7Ò†×Ï罩m#Ï•ö»v<#‘Ïbíy–#ŸÅº™aŒ×4Í ã !¹ cüFF´êøâû4²UÇ7#$WÇ—î“×'ƒ3Žf_w}28ãŒfHícXÍsÎÇcèÈERÆXn…€èÌתqH¿î[5W„äjâ>2W÷å•l»†Æ,­d+xæ9[ÛÈ e fY¡l­jœÅékZÝP2'Ë`ݳwaM‹áI¿n[ Ï!9†'~M®' Ò˜®' Ò­Vò!Ƶr‘Éq‚϶äÁÉ–~~FHI÷ÌÉ¿ÞÈõ€'b4º=Ì^g*Ä´–œm¨Óç,ïÀñ£æq|äX>¨S £æqlȪy{¸>Y5/ÌØž§…q‡—ŽgéÔöªaë’]òºá¥}äuà JkÉ·üü>m«Â⎌]Êï³uʤ•ì[§LþõÖ)“í6 mHèÚ´‹›à“¿Ô쟞½Ù>Y› z›´ê‚æDy%Ãó!y}ÛÒQß’ÓQ§kº†O69´X¸üæ[,\²`4ûz>{Üq–é—>£“Ëv¢¥ ¿G¤l)ÃG„ä”áCD*žLkÞvºÑy ®yÛ™Æ5ã7²mžvDHާM÷éüR\ó¶ó¼þ3­yÛ…o¿‘èZ¼ÍˆLÜ‘žˆ›ÀŽ"S+dK%;"$§’M¿®9Ó´’…æö&ðÒ-Çè"í-íAôi­àY¸ìÛXáZŽ´’…ç³-yw0ÝÅGdi­ìøŒX^u\Ç ä XÙâCÒ×”->$­©»#}#ÙŒP®ÉE(qq<-^ó-ž6†¶ÅÓ¦Ör3¦Ñge«V(¿ùV­P~ó¡Q5œvœê÷™vœU—¾f£DöÖl£8¹”jÅ隺wÌÉœqék*óyÇ)ÛàmÒ.V®qÍü>}˂ݒ³`é-¥²ÿû7?^–iÿç)¾%ºk÷9…<ªh¬¦”¯¿¯Çò!+¹òá˜Ù÷ )ékîƒd“ý<íÿþ·÷öy}ß5<ëA4^Æ1ζ€§­!?Çׄ$¯9 /¿R‘ÈÛ7¾f½kâú4/—yDHC!_†„´¥~©?ºç=¯÷pEH·#ŽÚÿ×>M6ÿ¾¼¾â_÷Ä´ô~LÈ(ä×õ‚¯)ºcDVÑô¶>¿î_† íÿw…^ÆŸ±€J MW½|Í÷ª èGBŸïCÕtx.¡¦2ùkƒöoÃüŒ¡Û§ÚÞÖú^Oè÷ºáûßýô÷CýîûK¡ž€.¯ËË_ ´ÿûïÙ‘Ðåó‚¡‚†Nø±¤¬B¯›é)îUª*tÞ»êâ7 ·¯µî¿ÿû÷ùåýµ{[¡Ó<}Ï÷ëTlUiôí´Ñ÷×Ë|¿?@m گбÿó¡Ž‚Þû—W õ4ôµx„~ËEuôŸó lFàxËõ%è¿¿ž^·­õ¾o˜ëçó8$Ö>Be„n7ð¾ƒíe÷ç{Í€R5hîר®C¯÷ûÔÔ Ÿ—ûýíjÉ£j̇…njÉ•Ò̘­Mçü1¦ƒ’Üp ñ¼"¤ŒFx3Ñ\_·1…—Ûˆ !O´"ÿüî—g„ÔÕÁ ý^ÌrCHC"ç þublîÞ"½OnxëNžùð>ûù¾mé>=&{:9~!¤$‘ßùHuè}Ç_úF¾¿/ø×©÷¹ n¸"$õ>§kJ«H[;ý®ýð2ß¾0ÒÕΞÙÏÏoékGÏu}óô„Ÿ(Èç¯;~ó î3† :ã;5ojÝšØC󔇶#¡‡æ)mGBÍSÚÝ£r(<4OxhzhžðÐö:zä¡yÊCÛ®ùú¹\îé‰Ip ÜòžòÐ$ØòžôЦ±ðÐ<é¡mPä¡yÒCÛ¡ÐC󤇶C¡‡æIm‡BÍ“ÚEšÏZÅ“†©XRùo¯Ñ“XwÉÔ× ëá8@OÂg­…ž„ÏZš= Ÿ=´*x>{h5Obº>ϪhOb* šö$&¼¥¡=‰jiO¢„:Ú“(¡ž:Q^R‘‰Õ=¥^ûgŒ¤Ný+<õCëÔ¿!$yJ ïùì ì)5Üóy’©* å ›i Щ!™˜i0ܨŠÌf7ª 8fú@ Ìô¬šé›éY5Ó36ÓÒS#Û™>Df3}¾ùª™°™>¡U3=`3}B«fzÀfú„VÍô€Íô Õ˜éjˆÚÐLŸPÒLÏS±¤H3=Þ ”™™>¡”™™>WGC“™>¡‚„f3}B93ß+k¦ (g¦ (g¦ (g¦ (g¦ ¨?ŒÅÿm›pÝ/ïGWªût¿¿~&S%€©z@>Ý—¿)©kŽýï¿©È_ÿûç!uu¢uM• LÕŽ„¦JP¦jS¬#S%HÎoㆠ©$ç·©w¡©$ç·#©ÀTƒZ†þ¶ÜÞßðž¦*Bσo…þ¹½oz¶;ýuB㋺]no3¾ÕÓTÕ _wüü§©ªAooÅU ß‹ÇJ'ê¶PÞ϶Þ5 D§5$ãOOÔ_Ç)µ"ûãD]î×gü­â‰Š¡ë!±Œ?×(è}04ž¨è½XªñDÅÐÏ úV^•ÈK¡ –QL^jÏ`ÝRÒÔX^¬šÉŸí×ÄÈ ‰¶[_´QÉiÜ{L¸Q 9{`G‚jmÿu´Q9Rr™æç”7)¹"oy£fR²rœôo`ŸšL¢U·ñ?‘'‘·+¾Ï@#oWüæ»ÇMºC_×­ÿŽ¡‚8K–÷ë[ñ=¹Ôi‚ÚVêtDHI ß‚)^ãZ)Þ!+çSÿpæyâÌëÎ<Ï^žyž8óú‡3Ïg^ÿpæyâÌ[Ι×}?¿¤Oæ ?¿$2ã»*äû>¤š^/3ãY?2Ýß0Òò‘éix»#d Ãd¦¾Ú>péÁ¨;8ÞpY¨-÷¦•u¸!$7€D–7lÜYÞP ·²š6‡ª!sL›CágŸFœqñ–zö 3.ÞRϾ‹vàö´Ô³ïH¸=mõÙ3²À¦wŒiêaÓ;º:ñxÿƒuÑδÀ¦g*ߦõ¸ËAƒg*ߦídNAƒw´hgÂfÄÑ¢ ›G‹v&lE-Ú™°qŒhg=>†û׆ "y¹|OÅ÷¬äÃû2Ǻ’U0Ǻ’U0Çî=‘cïË»çÄ0(Çî=í<á»÷Ä–_Ê»çÄ0(Çî91L–('†éÑõŒó„sìÞ3Îα{Ï8O8Çî=ã<á»÷Œó„sìÞ3Îα{OÇLEý´çÚ©¢»oÄ"ùšô@’8ìwDHIiŠÁ ]µ"Á M¿¬Þå2ß²B¿ìŽ#¤_‚àœŸ[Mœ¼Ÿ[Mþ¥åmðÆœd`3¢ÀæDJ™¼±Y lfØœHêHÞØ‰4$2yc'ÒMG@`s"Ñò6'Ò?@`s"‰LM|ó MM„ :ã;ÔIÊœ`OzPÞà„dü xxN(6_™=¼IQY·LeHŽÊ’ÌWf•ʉ$ó•Y¥r"+ÁRT1;A èŠ*æ)I$ØJ¤€®¨b>‘Gt'ÒPH`rµEó‰t26'Ò“ÈØœÈ@#oø‰jÍRT1G¨ Òô °‰ÐjòbF,¦þ+HÀbžHꚀÅ<‘ŠüõÄbžHB„YÌi¨ñ¥™Å<‘–BfóD"|ÈbžHOYÍ ‘(dNˆÄ7_wò‹¡u'±˜Zwò‹¡Š„&3B5 M,f„šX̵㘠NX–Å̉'Øt5HÕŸH.]}CH’Å„ŸŸMWOðó[¶ˆ>»£Ÿ%YNdídÚΠq=‘5k‘d9‘š*w‡Ïîèg?’,ø> gtB'½§ãï}Òl>é=9§+“œ ¹¬L:‘²ÚU)“N¤ª Ó¦ èQO$õ>xÒî}.ð¤W(“N¤#ªü2éDz¢ÈH Nd YRß|GCïÅG$4‰ "T#£a¬(¹Ñë(V”OçdŠHrc*•%TVbÄ”,#žU«®S2â™w’o©“ëSœdZêl±bÞžäXïU¦í)5«¤±·4¬:ÄÞÒp±÷ boiZ±÷B’ê×Iês@\'aŸïÇÊ œ‡qÒ²•A¹ÚÈIË­%PÁä¤c+˜rnçDÊjÀ€TNzÆ„B•“œY† ªY‚êD&´9åiHäý‚ïÓêh¤ :‘žF&k'=0 U|óõ€)¨"TÒ  ŠP’"Þˆ ,í¼ÉfB '&›™B’´ ðF$› Þˆ d«†3÷ªk‰P1’ËÆªDK,; du{Ž8žW’ŒçgÏ+IÆó3Žç•$·çˆãy%™o„ây%™o„âyEj¯7æÆóJ’ÛsÄñ¼’äöq<¯$¹=GÏ+IoÏÇóJÒÛsÄñ¼’´‡ƒ›Ü9¥¹ôtv+ÕÈ¥'ÏAéF.=yŠ>åGì„+ú”±® Y0c'\²<`Få'R½7`ÒF1ÚkTp"-Ѥ:áÊå#v•!ËnØ W†,¸a'\º<à†peèò€v•aØÛÍ0f‡YY&÷»Oõ¼"$Õ8:áô´· ®I'fTöîšQÙ»SthFeï'²Z[:£²÷IÉ=¸DY¹Ç—(•ê˸[fþ'Š»Uàd>ðšºãJ¿á5uÇ÷|"ó3ñ@FÇÏÄÛñkò3ñ€ÈÈiÙÊÏÇí©[%1Qâä´b¦µ#oD7u3B’ÜXó䥾̂hÃqMpÍkÓâš„$¹°æé!K;¬ymØ&OÀ³Õ–.Â<²Tîw$f>‘Õ Ðˆy6m¹# ˆ™O¤!‘9¨Ñ–çÙr¨ï6äÀS;ÞmÈ4‚ö¼ÛOÍËåà7 ¬~£ÀÙdÈ…¢q U›üƒ¤DÌ8Õû;Ȳ¥Ý`ȣ˄‚nÃ4ÞÃA7ò ?ÄA7ò(φ)8¤‚ÏÆTtÜнã@jHàÞ€q udònÀ8*2;7hH)?ÄA7ò(â†A7R«fÙý‹<ÎÚ,/=LN²Î¢èÀãŒà´09m— …ÉiCöG<™ØdÄŒlE4BrMºÏV{ñä6E3ŽhŒ¦%¢8¢1šL+Œ8¢1šL+Ì8­`è$úŒÓ †N¢Ï8­`4™V˜qDc4™V˜qDc4™VpDc4™VpDc4VpDc4VpDc4-´Q›gL«Íà !¹vé¡l«ÅŒ’ä¯r”d˜( §*Œk5³JoÔ·šYÝ’Ž²7bšM·®)©Ž{Às°Í[bï¶­-L茳¨¶#=Û{w¶ã¶'ôlÇmOè9ØŽn1»±7y}ÚF””ÓI¶%åt’mDIÙ$ÛÖž÷™ÓsdÛÚøDiÕY²q@Ñ‚ÅYÝØ›ùÙucoæg7½™ŸÈ°z)¸>-«Á‚ëÓrG<Œ>¬mñ?Ij°@ôa-«Áчµle2HùYG»7Xnk9…CS~ÖQ)¿ S~–S8ô0åg9…CS~ÖÑÕØ&[OWW`›l=“–`šÛN5ÓÜlÓÂ~«çŠožmZ¸@Y°ãª@(5v¼]"Ý´ð8‹ó³;ɰL¨ZÅ5Rçà‰©ól?×Ðdã6“såøi4À~:Mç}p„è ã‚¢ÑÆ­E¢3tÞGˆt7¼íš0-KwÃ;Ù†8Cç}p„è ÷Á¢3tÞGˆÎÐy!:Ãä}p„è “÷Á¢ãIu¨Äp,©•Îrý?¡irŽëBMS£s(ijtn[¡7„¬ñ¸bÁµ*² l~ DܾcóS âöGˆÛw-2p@H2?¢9ß±ù)ÍùŽ<’p³oç[¤zúš¾Eª§7ï[¤zr®<ÓK')<ÓK')|#× ž¨‘ëÌëö™ª¦HÒúô¦A®æ·d·%S¼åªžÐ³[:á…Ý0²/Ò‰Ìn˜wÌšGUOžtÃ6$¬zbú"͸ê‰é‹4ãª'ïè„v¼gÞ'r<ç†õ0Ñé97¬‡‰NOÚ¥½„Ø¥@Ú¥™íR`ÂXÌÒ.mׄv)tœ´Ú¥ÐqÒh—BG÷,ÃÊÀ XÕXŸApa\Ÿõn30L¸!$©:ë3VuÖgŒ2pwÓ³ËVÝ! û‰ÎÍ Z•~W„$²Ha4“ˆG ÛvωtŸÍž7„¤ÂxÆÛê1#$M…eçŸï91` öœ¨hy-yž Ë„L ý¥Ÿ›NîÏøÜ ÷ÁÒ5}×1‚¨ö]Ç2êÙÖùN°Œz¶u¾e’Ñ'’£ì„$õœŒ>‘$£ž“Ñ'Ò’ë3¾cÃXà{ûŽ—ðeŠÉwŠ•fŠÉwŠ;;Åt"¹³ã!IY`O$) Ìáቴ4MݧûÔ š:¿yÍû`É~úÎ4hêiFHI´Ð@ßÝrÍ6Ðwçâ8h“}ÇÅqÐ&ûε(ÐtŸ¾EŽITg@ªÖ·*ÏûlCB+îˆßˆ¯<9A/:þ¥³Ã‹f|4#$™ˆÏ¾’MîgßÆÃ’æGßP '’ó½’Lîg ôD’ÉýLžH*à Î#/W•Î#/ïÛ€kj&6Dç‘ÐìùžIH/ _‘Îb/ #€µdùêŒä3xÁ‰!ñûäÄø}:®Ê ÄGž.Ä+R3ž,Ä;êoášt,ƒâM/s¾÷hÍÒŸŸíï™B¼Ñþž)Ä›íïÝT §ä¼ì)¹#™”\úîR4Rri-IÑð½Óy$eÃ÷ο.¹”´ŸR5|ï´ê$×T ŠŠ=]‰VˆŠ½Ôüy”×<¬D«ž\iÍKÃqAð,––Ö³˜®ðÚWðC¤kñŸÉñ´qÍË&O{EHú»ƒo8Žú62´D†ñ-©®%2¼#$Í+æ÷É•ä â¯D«ú2>»’­êË!éX;ÛF­G“x¥˜5|Z¥[>-F2‘´–”iùÞW„$¤,h¿3E3ÞïŠõ“ṩX?ž›tÁž>g]Dp óGlHÀYyå[gÜ !É”\æ¬<]D°#3gå™"‚¹ØG¡Å{c$ÇÏǵ¤[û=}wÝ5öfúî\Á¾7Ó¹©s彩[Ü=FqŠã´bbCÇiÅûŠùiݪÆHÉT1§odZUÌW„¤ÎwxÆé_—=m’†ü>]CÒ<íøó|÷_—WoðŠy…„¯˜Ÿ(ð>C¶u†é„€ã#Óñß\“ë„° k6efñkš¦ÌlDHJ }o£Zr¸!ékæ½i4'­„¾¢iñÞiw˜ïïÓp>-ô½M‹÷^0’ö½Á5]CÊ’ì'/+…;Ž—•ö`wp²Rì{›Àå‹¡ý4ŸÙ±\GäÓÚŽãÒ¡ocÇ¥C߯ Þ·ÉöÓʆϿ.v>½O«v>}MËí#dç­nIÂ0’“®¥_7-éÚ!‰â;äZ†§Åþ§µü³gûi9y6²ŸÖqE‚Ð.ñòBh—hyáæ]@?™–HpŸ÷ç³ áä…(ê]×’íÅ7ïDK¶7 $ý>óÙÁÏD…œž•îž@úuÕâmf„ä|ÚtMÝòig„¤ýOðì¦åÓÞ’ÊEB›LëÖd^Ÿ´nmctáÞ¤uk2ïMçZ¹ÝtŸ¾•Û’>Àû ­Üî !Ž:=»ïuÚžqå½ÉêÁGÝЃMÙ»hèÁ@lè%g“áÙáU+F¸"$}Ílë¼æì<´É¾ågoÅGùÙ o“Á³ÛÖù~EH.îHk©¥gÈOäøýž×¼oÆGBÒg1XŸ¡åÎÉùŸñ}†®åÞ’Ë¥kŠVþ膴­ËÏd+4#$BûBûMpŸºeC0’³ué×[ù¸´–‚! Ì·i—ŸcÌ e]ÐvÑŸ^_Ò”úáúÑOýÇ+BÊŒ|NÈùgBH¨«üçàÖÞßÏ^mýó=gÓîrYöî¹Y¾ùˆüZ?"{ͯ9ZïÐÕKäúã>7ºò‘=ÑÑÚëx¢ë&îK§L¨ŽïøˆÏ¾/“ˆ„ðÿpÏý£¯Â="ë­ºûókNËý‘°&÷xóòž¢ÈUäõ¿Qè Ó||½ÑôBg˜}}ß<µ±¾ÏíÇWäúÔãeÇ)!@þ󀼎Ó!%Fî×wäôzÁ×T¹}õãšóû÷xEÈúÔ¹õ-].ÒÔÖü¼7LÎ+Ì.=žýå­?·~¸|Ÿ7„,ºÞï´#ç§+~"¿ïÍ}ÌÈëKÿ¶!¿ï—a¹}-?ÏòõåùíýØOãûºêžŠ7ßÐŽ‹¾¼Ÿ}[nWüHâ´"ÿÛ¡ÇU7h¿Üž~f •º‘ùô}žñ­îýš×°ÝëëþüÛþ|¹^>®ý\\UïÐÿŽÇzµþoñXÛ—Z±+ôåýíµ[ßÕË<­O8L× µô׿Ï+ôÜË÷þò=½~þ-®êè¿¿.Û×ßÍ㸼\Çyx)Ö©Ø?Öÿþùg¿ê¹MÖ«Î÷Ÿëo¼¨DÀÐ=ó±C¿Ìñêïè¿¿ö£a_-ýýÏ ½Ï=^VrÿZÿüók=qöcd;q®ë‚^­s±û¤< ÿýû½•ÐýkýÚ&¬ ëø°»Ëzý¾½a¨& Ú”?¬g ÚuÊÛ Ê0þÃmT÷óVåzªÀÃ1ˆ*Ùõ‘ Z:t‚¨QXÙìo\DJò×·ûüóòŸMh¨˜”tŒNüƒŽÑ 4={~ŸÖ»¥(þy<ÄççK?"¤¬´k?|OÏf„TÅpŒˆœ†Ûˆ¯©kÇýˆŽû@tJO´ "Ò±‡øúFÊÊñ´^ O@&TO;O@&TO;OÂSÇÓ†„Ç“`æ+ããIxêxÚ‘ïù¸ž:ž¶ÉŒðxž:žv$8ž„ÇÇÓáóޝH“¿ÌÅ›ïh“_\ô8žêÆy) ZÜ·×hœ‡g‘ç+h4ÎÃŒ³Èó• ãœÌ˜Èó• 3:ÝGlFEž¯ü¿Ÿþ]¡ÛïïŸj=J‡ûüüS\Õaèq’mПë3þþ“ý¿e=íé6L)É­wIפ;–ïU{÷kŒ†ЉÑjr­6$_èÄþ·;2i>ÇŽ¼~¿þAH‰‘§1Y‘¯·dœ¥›ôß_¿~OÆD j“À&•‚ô!‡mR &'Í¥É?/·O|MWß¿~»ÜžŒô5£wÃFhäJ£wÃFhäJ£wÃFOJÒèݰѓ’ž¡‚ž”¤Ñ›±Ñ“’4z6zR’FoÀFOÊ–ÑÃ÷ɽ¿yÎèPÎèáß'ÞŒž”¬ÑÑ“²iôŠU5z6zRrFo„Fï„Fo„Fï„z‹xT@!æÌtÍxŽá½#B"¿Uä1g4; 7”~0Pdž:pCi´¡vdúØÅ†Ò• •æ{AŸPjÚ@Mô ¥Fê0;§ß¾^òõëeFÈ¢•ÖûGDÞßf|ŸžÚ&cŽdj¥U_ú{ü>6 sr dn¥õ¿_ÿ­W}^c±ý釧i¾_~ß–â{Ö'/níå?îi=¦  F$íèΘ­’´£{ÃlUuÂÞ™mo¯Ébý|ëóóm¯ ÿ&Ákçൠêýú¼–êØ'‹Y &ÀÙ¤‚éËÕkZÌïÑ'¹õói«²WhdäxKœžÕMÏ&ðÝ•$‚ÐÃËzî—)"É€ñpòs°¬4;CŒ¨ÃùEShÄR’Î5ÿ÷û‰RËz>Ñ-ß§#Ã곩HwZñÀ³vl2|ö@5¢Ù‰°>uGîŽ󮺣ª÷ûß] Ö~¿§õ©%3½u‚ÖF+.X^¹kºOMsCyÌiMs}yÌ$>æúò˜Ó†8æúò˜Í–ñ1×—Çœ6Ä1·”Çl¶\î£i‚–Aâ˜ëËcNâ˜ëËcNþ˜[füëÌ1·ož9æ&|£Ü1×ã¯$$ÁMïÓ·'ê5]²sÈŒ‘*¦xúB˶œÒîå?ÖÈÛŸïW„”Ù§kÞ¿¾„Ëä»c„ÍzgGÈIvÎ  .$‡¾ }(•Äo©Lè;jÕÁT¶ N³Á° Ž^uÛú«Î”Ї ƈ@gI®cÄN @–\Lj@gI®cÄN ³$×1c'ÐY:¡¹gI®cÄNà¬r#v$Çuàûä¸üë,מå:ðÓÓ³ºÀñuªµ…—cÇé‚ÐqLwM<ŽðëìA £ïÈCać‚'uAÛ ?x(xÁ ýjíÒõ’9ð5%Ëu€Ô§W,{3¤® Á+zúNC¥èczn ­(^`‚Øk2A|à b¯‰ñé´d·ÁS¦i›ÎŽL“·d|:cÓä-ŸÎØ4yKƧ36MÞ’ñéˆM“·t^ǧޒñéŒM“·d|:cÓäm+>ÅH.>ñ›çâÓâ#qñ)~&!ÉeI§§wœÁiǪô7¶ PzxOÓ›[»°å9_hA[ž‰¼°w‡'þW4NDNµÍ`ÖÃEJl„ŒmUR›‰;ð–‚fã>@*ö9"Yà5KzM3öš?Vþºcb ô݃g}6pÌÑRÕRZ Ó•Éî&»ED­e²{†É&»g˜ìŽÈj²{†É²"3LvG$!˜ÉÙˆ¬&»o0Ù‘Õd÷ “Ýé«ÎÀÖ|52W+RÐÌÕzoë)Y§%펩héï%޹"5¹æQ,¹" ½ê`,‘Dƒ\G¯HK ÷¹oùk:ŽçÉò׈”Df𵟿ï©ðèšS-¶b¯ÃmFHR•bŸÙØ›S¾OOÚùÚùxG(r\¢üDÈŸFdãÂjÆ)Ø´`rW¤dÓ‚Iÿ‘’ŠÍÓ¹¹"Ù &ù܌Ȋ[°\gEj‚-X®‘ ¶`¹NDV,Ø‚å:©«CᱚÑÔõpÍ MY°iÄLh‚-X®‘¾zmD"g¸" ËÉÀbYN&… I5Õ‡¶N8Ɔô™'_‘žcZ¾®—|MO'dW£ø=üÁ׬'d'dCªZÊœJAߊ¤¼µ3WI´†C–VÒ<ù yò)Ø&ðÀ†Hº¨jóiSqE’¥(˜çY‘Šf{à+®HÍú`×|¾“mÇvO5{AYgþW?œÅõ¶cé,î“õ–T¾©Çù¦Iå›zœoŠÈJ¾©Çù¦ˆ¬ä›zœoŠÈº]‚ù¦ˆ$Ò—=ÜG’Ê7-8ß‘•|Ó‚óMé ?yê‡%Ú%øóè’Ö¼êØi×à”¡åXß¾"'–ÈAtDJB鋈¬Ñ2ÓY³6û\W`m—Ã꡵QìÜ1¸ß•b&}÷Ð.)Íf|’¨cE6¢³ìƒ)>:>˜²$§=CЊ¤©Å „"’c‘"¾IžGͲä7Ï76Yv^øFºã=ê)YÍfN`?A;¯2·>b[$%en}Ķ´ó*së#¶uZ’¹õÛ:-é(Û:-–äÖ#²š[Ÿ±­Ó’Ì­ÏØÖiID‘ç ›£HMF|ûš'¬Öìi<+Mùu‡e¶©/bmhë@3±Ò³š¡Ô-"«žÕ ¥n©ÉH?ïwÍ6òE+Ù‘2ªʨV¤g¹µñ’|ZÍŽ/éÁ.®ê2”di¢3里¯[‘‚g ûô5IUÃùD}²uFÒ6Ì:A0böÀ ,]‘š‰µÑÉ…W<ÿ%­OcØ3À¨¶ûHvø!†ôq•ߊtäLÕ¯:RÿpDúð»’_¡2Jt¶c<–žV° ðÁ>²‚n°þ4x"+Ò(1‚qü”eü>âøÝ*2~qün¿8~·Šô“G¿[Å”‡ øÝ*2~pü~ «ñûˆã÷IÄï뉕©Ùx°1ÖpMË¡Ÿl 9cqÀž•µô¯cÏÊZ^÷’=@ëXÝ ða㯚—ž}0ëÙaÀz[Ok?0ûj+ÎÑ®ãSÆà,¦õ$ËŒãGÇŽ;w 8îp‚J›s™³]bçŠ.ÐOv´¨xÆÌ £<™1sâ8EܲºÔɳ¢g€î± ˆPœ¥µ^˜#… KɃ9Gå㎘+{€UICΟÁú”j+Ñ1B…s¿ŒPaÄܯŒàyªEK+ Çú±©èš÷uyÀ'Òôiˆ™(oXÑ;øîÞòÖ&3QÞ±ó¸Á¹é»´q,ÙcñžmÔl²÷œÆï>б6öëBGÇÚØ¯ 7£û=6'NØ ieš`Ž4kªéaV(H*+48+èBQ$¹Y‘ŒÊJn"’ô~šóÖ²<&"+1ׂˋ"²s-¸¼("u=„¼Ê`HYÔÜ£6Xֻ볚+O6duð$Ÿ3’úÉB0~2òÊkãï>"_QÒcÙϸì3!ÙÜY>ã„Pôx²}wÑXK‰_°#˵ã´j1B¶`²£Äà5-«gÈþ§ŽáC õ(c[ªèôæ]·‚Îb!™RJt Ù‘gñŒ˜(!“q€L”¨çL£Úè‚„”,ëžyZ!“]… "!5Ef^Hà ³?/$Ƀíç{Ö Iª}ŽQËÉ«’ŽFÄ Iñ´2óKBzÆ‚­þgŠL… L y0Aæ VÏÙŸª£3MøAŽ@:ù|"(ZÍ;ÃúšØ\ä¼¥À޾6Dwü5S$%˜làK'"RRlLæ…–ܰè±T‡û|$$°6ZññQR¼`/]k.ÞÃ÷ÉÔQ¢Vp¹3¤lµÜY®1¬(rg¨ÌŰæÎ*Öx€Úñ'B¶!Ú³#wá×ôì ›£]¡Y› ¢]rg¥Q´{"«lDÑî‰ÔTV(G¦‚ÎÇ|0‚á¬&èÓIõÄ1]eŒ_¬HÍrªÀ0†åT3W)Œ¡kH±b,í×!•0Ž×'g«h<«OVÑx’S±õ6­Î ¨Ž­ÉÙ`—¬`2õ9Vr,<,ÉîQyf9„ÕlN|wkX]øî–Ô{ãªíié÷‰¸tai†g·´9F°žÎ¡  £°ÍZëí:6‚ûÝ‘•àûùž³ÀÂIFí]á; ØOT“û߃þ¬%§éìÀé§|‡p†ÍÇO€52`OÀY>˜w1—Á¾ ÌŒTâwà]8vd<`±gm̓kÎ B×dY€÷ž³!S"h/Øhxþ^rl dἤ•9Øó÷’Væ`ÏßCÏ¿b“óZòЇ Ö’'ëР9’òŒBGú^scéà~÷†ÓrÀóÝ[¦>qžkB+A„÷,»¬·,»¬·ŒB£‡ÑYè†ñ6ApÝ9àÉ$›i~rPœZäzÈ¡TŠR¡Ÿ™ë°Ÿ¥1;"è̇Í›–!p‘)ò‚‚ac.pr†cÁ e'Ùì@f_e§¸ïØWÙñãó[’duÞRhödgøûLÙ6Ømˆì,«¯Ë6DVó©¾XÙ9F¥î­HþÔΫNvØ0EúR°|ˆô¥è¸*là×I!86Ø:Ivæï •‚¤³{Ä—ýd)4ë3ä³C2Ùíb),¡ 8N ǯä/IáÙQõÙ*Jáiý<²uR–gO$™“ E|R –W¿.%=ˆE=R*– ÊÞ¯”šUÉfïWJMžÚ#Šz$Ývgö2Ï «5Mi}B«(ËQ«(=7:ZEéY¿.û´’ãç›}"ë\òiOd B>í‰$&G@€Tœ¿}E©XN®dÕðç—ŒTìÐF°ã”bø ݧ¦9j|)ï|)ÃZZ°ê”e³-`o*Gköo#ùq| ôCè¶®Gž+ïwº­ëŽûµu­ “÷+é¶®›]‘”Ô‚ÉÜ¡3ŽäçÜÅbE*†¯ƒ ©5«‰+Dk2û™R©Y}2<;´e½5øDŽõá[ò¼õß(°ÃÍá7 Ãcihö`FzoIT‚D–ìCϱÇRgžcž°¦ñÝóÙa¸¯ õ Ò6+Ÿ>ãfì×ÇTX ëM×b\¥4­ï+ÙvL.2V0¾ ²Þ–µ]²ŠUu»TDž¹ àÏ[ÍU*ÁÁÚûÅÖÛ’-ëw Ä2Ö± ËУÀwX†yž±f9m!Џ“Øà˜gIU•öÉ~~I:Å«h²õvšUÑëÍÃÆq‡3ü7ÊÑ7äGˆy®¬äl“é!×ûÈr`“ã”NÐcqž÷Tk$]`GÄÂ' ô¯#&_úŽe¢À›÷¼ÏÎM/9;9¯XÞ^S³õ™”Uö5± û/iMþ~n‚SÆs ¡xÇæ¹€]òže9ÀŽ£yÚcåû ¿Ãû íb/=þ-å]hÝÚˆÏ÷ ¹“ žGl7´‚fy`“ƒal2òX‚¥9j|Çzk`%ÏZZ`“3#ù´ªëX/(?»ês½©:Éd-a¤¯:ÅêçóÞTfÙƒìY©Î°‘i¶Kª³t^ùKªc*¦:®sx|Ä—¿»"TÇѧoIÖÚ€¯)¸S»þ¼Šñëà©­ŸËû] ÍpÔÐQÂpZ8¸ê„e"˜ßT‚e‰'øìžzò‰ 8¶íb%;Ö¯«ŽÓý"ë­h5ïfiõVR’\úŒ,­’ŠóÁi¨¤fϰê¤aYÍ|Æ)iYÿ3ŸqJ:nÇMð‰<ËÀ½)™‚§Ø¸Ú:%‚V²’ìJÏ®sÊ ›¬4«áOdX_ìMe9uÊïÓ±Ö¬%åÙUöf•1˧ 8tÇî°>5«·'¬Ò’õÀûÔŠ]!ð>5÷DÐ&kÃeàw×–½&xóL÷’­Äu¼Dë­} WˆgUμc­V$;n/O„\‘®5ò†ô}‚ozÍýß™¾×ÜÚ_7ûw‡ ÜTëkÖ œHI?Ñ5>b·ªÃ¿n)ë5àè}ZÁ }[ÀJ¶²5—$!i>dØÓ†sºOvœÙVÿ„‘¸ë™›¸ößÏ)v/Q™Û.úïåùõDŽ×׿ýÒ/1è²sG>½>§kÎ÷Øÿþ‘¶ñD÷tŸìªCOVÝ㎻^–1}#Ïí÷íšBJ¦ö?!·ß7[üu×qûþºë؉EÀÚ8~ˆÞx½¤_g'ÁýîZ`ÓŽsŠÛïûlÛˆÔÜšGÏNwýÚºÁû´ì}ûélë}Ƶä\ã-%â|Æä_÷Ü tÍÀ^>QàŸ([ßµVHBÒçæ Ÿ›¾ynÉ­tMÅÕÂïîuk}ɽ¥ôëì¹ ­·\W¸’=×x‚¶Î{þ‰À¯{diWÜóai§ç½M@öë|hœ2)Ö]ãͧõ‰t•Õ5? ¤¤Ÿ=\Aò×ÌÏzhë3ýºjyVIó–6hn˜/üšÁ°'×”´…'RÒ×Ìoɲç;¼¦å<¸’ƒkô·É+Ä·ÖRº&¿êúÄðèŽí|ZÝ5θ{üšº“-䑊¢´‹5?¡|wÝ™Æ.οnx«xëÓ5ÁwÿùU ´]Vï"fuçX› ß¼#½µÛuê§þã5"}k…¤û ìÈãõ‰â}ŠŽë—þ•ÂZþ|ÏßvH¨Ü'xvÁϰÈû] ÅÎ.ÈÖ ‰»X Ó°ui…ÃõúXßÒ==»å}ð–€e¨®¥[úF޵Ÿð}:ÞO¿î¹•|Ÿ.±VH‹Àzé96Ô°ÿ|Å«HÙµ¾füFR´VHBÊÖů)Ùóݧ¢Î¸iD>˜–ºáƒ¥o$Ùªa#hľ–“gWO ÕsiiÙ!ã`wH~òüu¶nî8Ùðm–ô>U×âCâ×T‚_!É£ÖŠí ¿¦R­kƯ Ù×r-mu(ùÍ+Ã÷¼ã ²±¾–Ò6ü¥´–”åvÜ”½5ÍtÀŒ™Vž÷À[ Üt`hiu×âC®)™U—®)ØY09’Òš[!hÕiÕx¢ä]hÝâC®)™—îÓ´vqúuv¿ƒH_kÇÛϼtûȻ²ÄÕÝ1F¤éø•œw‡é¸·÷&Í'O¶ÉM>9}w†O[¨â­"@jNç×’iyªi-ÃÅ\€[ÓÆ¶¸5Œ¤½µlCŒcgçUg|ë-¥oZv)þºíøýž£ +o>Ù%ÛŒv¯ɼùÈ+j«Z¼"FJf%ǵd[¹‰´’mûÈÑ™5-’Þ'Ûõ žÖ±=íÁ ±žíîüËv…ûˆetwþŽ’òC2³§!£û`ë–ñ’êvµã­ ØGN’™‘mÖFæÖ4Ïý.Köüj\óšÜ¸fãäÊ;Ι–eHHËûŸy}ÒÜ隸FoÉ·˜ç!%½–’ehp¿p-’OŸ¬}×â“„”ÌŽ‹÷éË”f&J{ÙÚqé×UcÍé‰x»Ö<ä~ñ5·ãMßò¨{Œ”ŒµIÏnYìw’%>fC>„g‰—)ÇÞ³^ú”OºÓòùë‰g¼G ~=t\…/ÜG¡Áðä¸#¶w4°ÞLE?Ιj’%Ž1BZÉîù€³–:´¼ô|MÍNJ‚Od¨ÝWrºf#ŽË+9ØÆ7J6$¸† é1’U|°ÀF|ЯãùdàÛV§ ½5Ó no f:ÉÅ·þ×’éïý¦ýnPõ}‘ÈHÝb9Ò}®j¼OÓ5x›M˜ÎµÞgBzÞKܯéWl]ƒû+Ùˆ®Å@Æ_¢õ5¯)y:M!ù!1ù†™$;£<¬aùdÈýšŸ ß’áW]:7 ä“Y#ñá_þu×PÑä÷éù¼ÏÀõ«6ÙÈ®•»#$g“ã›çêôge¤lå‹ã³KEOÄë·¾¯éIÍj橹 ƒà44Ò´2Œw„”ŒõNÏÞZKCzv׈aÓZ’Žg ·fds-¥_g»7C»¤Zv)}MØq÷ѧ¬‘Q‚ÏwäóH v¶#xóJ¶¸µ„T-åC\KJ³]R³Çb…0Öšy>vG¶´Êqó7áJV¾å×Ý’;‹Ó}žÑÍöS³¬Èb-«.Ùy-[9¾!%ý–’UÔªå©Þ’[É ©ù¤Ï¿.»#ÆïV¨O;#$Í@¦½i…n†éš†í5—m²³#2V8¶cd>¹¬hžqÇÑ3ÔŠL¨m1ºiÞ™•³ê vËJÑPSLI³Ù)ÙéKàÍKÕ:7Ó55—mµ•¦ñ>Óú”êð>-§–„ß]r±Ì¾’ÓùÖªK¿øÄBåméù#6Æ:Ñbc„¤ìpÂúÐ:aãûlq•ÙÖÑŠâ¯Ù:µã›Š·ŸùÜ ºeÒ´x›!¹Ê…„ä¸Êú ®²Oy ¹ÊúšO×ô-ÍÞ€´·–OXV} «u\×5b™è3¸NðlL:‹]'Ù‰9ÙÚ¸NµÎÍôë Öüºi ÙúîCzK®¡Yn)©‰Ù§ug'æÀû -ž6^Sð]ÐÁû¢õ>ã7äÝ 9üþˆ™e'ør—Ë8"$®çÚ~û@þýÝ¿âkªã>ÏN¡ {Þ×|Á×ÔdŒNX'tCI’¾¦hÄÉqÂòì@:þÜoÞ·j1Ò5g?A´ëd׊vG„d4'iÕIÑÒ˜Å}ÄusE|ˆ“ u_âçÝ£uï– vœ4­  „l~͸–¤ã2¶ Ïå¤oå¹n)™’¼Ï5NñݰÁ[âf*!®Ò±¼"<¹œRÌ[‚l¶SºÅfß’ÊÏß)ÓÊo¦kZ>.λX¹Fæ.í#å[§aºfhýz|Kºkì÷È8-ZìÁˆ„Çu¿ŽUuîù÷;BRõA¼ét+ÞÌ÷©¸ÜÈǹ†ªì8­÷yO÷iZ‡!%ÉÓ¦ÅiËN‰ÊµÓ®µ7Ó¯78ê|Ʊ $dœéZ»8~wÓŠL'ŒäV]BÊ–F#ÉìÀÿ4\yŠœÑ¼W ¦U¥•î³Uk™¬·q ~>†, £rgZÊðtŸ–Ÿ‡Þ'Ë+B†ÇYÙzŸñ>mƒOHÝBÆodù!×9k[çfúuÇ3'ùÜ´ – C#‚Nç‘ëØYàÍ;ÑÒQÇgw­~AÉÖ9Õzö„Ô|„’Ï8gZÈôì–çó a9@¨«tŽ=µ¡¿ä¸ù(Úõ¬’z,Ü\!lç}ËKkÉ+v x"ßÈËäõéÙXÆ›¾ùҵΣôëø(ïbZ,þ:7-Õ^9ž1µ-ŽfÌ ®ÒÅNN+$4¢pŸ¦¥–Œo)Xv¾ XÉÁµž(½OÏù €[s!´¸5Œ”̳Ÿ+ijìÜï¾<•¬ïjŠ>ÿºjEg ©[ÖfŽHÓ²6é>mËÚ¤_w-ž6!}ˆ¤û ï¹5ßPÍåïîÝñ +s¼ Ë÷¦­¼vä?½P¼'vœº…ŒïS˜•žÝ¶,Cº&?u+ïM/| ™Þgà#”üD²kù´ )ø¸8ï8¶í8©Z,]S³“SòièeãŒË«NÚÖ[Š+DºÖ5Ó}úÖ[J¿ZŒY¼&ß[èC¼jtœÈ»C5˜½¼–”jE¦é×uKs’®iZ¿žîÓ²3€òçY†j_½jøŠù»«ÐZuñšºk]3®y-x)¿y¾»#üîM=XZKZó§ øuÓB¦kÚÖ%¤ãýº¼´o!Ó}†ÆšOOdº–ÿ™¢µêâ}ÉŸ°ù»sý±ý4ºu͸>áO™ü5mýzBºÖ5Ó}zÞzƒ' ­S;>‘å'dg·¢õëñ‰¬l]3~#«Zö3ýºæWH~vkZÈtŸùýúÎ*êûáù>å~AMy®uðÈ¿î<Œ”Õ_ð¯ç¯9ÏçdŸþýÌΫÏpÃHY›úºå"7ò÷D:~êVî4âA‡ÃùŸ£wô[ê}Ûò\}D ú}®O”'xÀœÌÿû÷×ùDï笢­ñŽõn„{ÎôŸÝ±]VæÛ%­d ÈÚ&%íO´¿Ïí-—ËrRAdŸŸýëíéŠM_êã4«ásÊ–á@šù+ÎiŠÈiøñ}ZâÙ7eNºOÍÔ,ÃiVÞiºÿü.zÉïÓ„7ä=ÕAŸHILòz»‚_·ìªûʶÎ9nžÔÕ¼©Ñ*k>±Äžœ×s®¥éšž=4ÖRÚï@·V]K}qMz-½?Ý’YKyo°–þÙ¯ù¾^3ö:^®oÏiëÈß«YŒ3åO¤ÃÈó>_·§ÇHO¯ä+~¢pX°JÒ?_oø‰DGA‡¯ñ CO»øë|÷z}{ÃPI‰4^¾ç¸D}G–xœ­ò„L"ÙÄEòýòúНIŠ4ƯœHM`ƒ ôÇrz/¾÷_÷9¹L€ýß±œ¶µ¼"×g/ãÓ8a¤DÈíÉäõ§o©ä?µkÞRcäöä4÷¹/æÿýü»?ÑvÅ÷ý‰¾î_ÃŒ‘–h®>\.#FºÚFž×—¿$#v =Úžéš¿ÿ¾× µí¹.ºËËð‰ßÒ¹˜‡ß­C„ÎOïÅGJ‡|\÷G¹ç×zÊÆ’Ç=æ¼ì·úúÒ¿mWý¾_†å6Nó;†ªúÏ.OïÓ¿þö÷ò犡ú€þÚz?<¿÷§¿^Æ—¡x,sˆÞÿ·ßÀ±ö¶è—Ÿç{q¯C7k¡ÅGn‡noàõ5¹9¯×ËÇêêWõ;ô¿ÿÛë=-þáöññ†?«Ø¾ÖŠ]¿Ö~«oëø3ݦ?«§ñŒß€ìèúµ^ÞßÞú}ëßûË÷²|/Kî²ÿÿýs@ϽBçûÛ}) Cw-×Ý’¸ªèêm‡ø¾^úûË ½Ï=þRgèzÕcaoW½mC÷¯õÏ?¿Vçàå´«?8^79n±ÿíÝ&C¶ û×úµÿ—ç·ãîþýå~ÿü{+Þ€'f‚^€§‹fÅ=œå×{>Ës׆Ǻ 4™ÒƒlÍÿ~ý åqJÜ_¯ïÿ)"ó\Ìóû¿¦ï¿¿ IzëîNëÏrSNosö<¬Èú¿ó8y3ZÖÅ:$“꘸åÖçIud€*~öêÁå7ï‘Wx<›·—8†jØŠ£§aDH*y¿f’ÓaïÇ^Šƒ`³qLÇI€ÇÞyðìówäð:^&„”Ôav-¯‰½|@Îï¯1[s"5uD-—iˆ#êùžã– ÷xð|/3B:êܹ½_ñyâ,™‡ÕB#dHÈcÇñÿí}ž¦§âÍwéÔÙ.ú¾äÇE×Ë^ñ# A%·§ärxìUŽ’÷ùV\UÕŽ’—ëåõÚßð›:=t”µ,åc™x”‹ôÀ_¿»Üž (épNý-Ý€i8œFŸþè¯þÉû´—cG¤å8‘ù’9‘ÀåósŽ·AX…äúžž¿o©HšévÅ×Ô4ixOHß 7³…ð J=1!4(õ¼“CÃÙŽDyª³ÝÇ r" šþ Ðô¡Ü v@©(åyÜJ«_œïS4膄”ú‰¬Ð Rê'RÏÞGzïOÚI'ÒœaB~Ýbèt"íã[Úžý†Þ’"øµõ#~-tš I6à×Nd_ÛÅ™_;‘5c¯yGÈ¿¶#3¿v"+üÚöD_;‘–‹Œí‰¬Ûc%c{"kÆv# ±=‘5~m¿ß|_Û¡™_‹ÐÊNZŽý‘øµ•4ö5b¨"9«¥x§µ@#rVå è翽Æ`2»¡C#»4 ™]ŠPG³KSñXžf—JhxtÞ§ÕÏ‚?•a&Þlyª%!-Ÿ§šòp<Õ„‘šž’…AñFê0(;ÿàç×¼#¤ÂÈmKHhP|6=§Aùè߃d¼þ\FŒ§þ¶k‹d»æßé/~öȪíšûýž×]÷=¬v¿ù.qPϯç#mÐ5Kò‘-™Ý”$¼=W•t~~/ *zQÏÉ‹úÛ¿?ÃÌ_„ž×ñ¢Ãõ~]ƒ¬ü¡¢ÃuÈÓßy¹\‡œM‹P[ƒ~\žî?Ð"E¶Õ#Eö玿êápÕ ßßïÈ;FAH.«2Ý’†;ùàq@èiÓg¥iÕáþ1ý¼&S.xZ5k’èañäÞV=ÞRײ~ãv[ B7òD)05õìO”¤”áõ2"$'úNžÑÔ´”!ù&’ÉMøšLžè_“Ì OW|M*O4~-Ùî˜"O´1šÇª[(ÈÅ7Oå‰Þ–ë¿P.OôsÇP&O4à[%óD«™,V ßÖ áœòDJæ‰^?ÿ7à"©}Ù¾þ¡ñ[^®ã<¼LÅðtJéwq¯R'ü~¹ÿÅ«¿«§”ÖøqÈ–Ï´òD^\žhÂk€Ë]ß0Tר›³7 p¨don8Ø–don8Ø:Uö憃­Yeon8Ø:UöfÄìʹĨ0ÈÞÈ*{3cöæ@VÙ›³7²ÊÞ ˜½9ß|•½0{sB«ì͈ٛʱ7ÅU9öfÄP޽)®J±7#`oN(ÅÞŒ€½9¡{SÜÇÞÐ*{3`öæ\ý{3Böæ„ìÍÙ›ŠÓïÉCÿó9½&¯ßñìÍ%û=Ü|È~º_ó9íûlåŽ\ÛLª´X7jÉš›)És:“û’ëi §}Ù‘÷yCÓ«Ókêœ^5 $¥ßú%Ç·ÄÔóÕüHù’1—ŠÍPŽé»KUÉPžŒÐŠü¸½ßR‘yÇ{ñëšÊ&fuΉ4T6ñ=§@dVëWŸ—Ûoüëçý"%°å‡cO—险eékÒµ€xjY“ck´ XÉ’«è‡[_ %•ɪ¬ -¥ÊÚ@•¤¥TYû5¯å5kÞö†ª¬©©Äüî–úî;~wKyÛ{"«²N¤£²Y•u"=­µzÇ¿H¥Ór+Þ|G+Š‹ A% ²&)Bey„ì0dMR„*Z“”ר-ËR“TB •€È꡵Tâ6þWuz8æt\7)†ú:µ…”5GnóµÂüvý¿RÿACº!—mOÏy,þÿ !=ë&Rcdüõeœ®‰¸:]_ùõº,c=è.—ë ! º~¹Í—ÿºG=ågS~óÉ)©æåŸçþuÑQñp[ èA©ü»]õ­ûØ)¸ûåï–í (“Cϯ”sJ–÷1ó*%µ”ïßÜ*’9ßñvÇ¿®©²0@+À¶0(=rýw`LjÞð² dÊ@ô†—½îÈ@ô†—½îÈ@ô†—½îÈ@tƨîÈ@tƨîÈ@tÀ¨îÈ@tÀ¨îZ(¾O.ñ›çÑJ¢#DuÇ¢#DO(ˆ«„ D ¨¡¸TˆžPKq© =¡D :Â@ô„zŠÑ[ßnºj]¢×¿×;BEî)Âùóýߪ`]ë{Þ&,þJ,”£ û„`UÆÖ'd~btdªÉWÞçûBJ 9þ¤DŠV•S,ÌÈ%Ó.Ù[dÊÆËø;ùºá’eöMëǬx n×#K¿uvÉöç—u[ïþ³ÕÛM7üë†tuR•ç‰<*X¶8pý–ñšÓïõYŠgßèÿþ³]ó\óù¹¼f½xÜciÕ™Êû|‹Ätפ+qgÔ&hKv3êÀlIJ§ÇˆúÜÈjOõ‡9‘šÈɃþ0'²Úæ†úÜHK÷ÆÉ+¹U–‘R·ºU–ñçŽLYƈ]ךoŒhBJ€]È*yŽ‘ÙIÍèD¶Ž™µû.п´jÀsäeí5M$ål ëÙFœ)tYÏ6âL¡ëH.zÄ™Bבõl#ÎºŽ¬gq¦Ðud‚|Ä™Bב1ÚŒ3…®£[Õáz6בõl#ÎºŽ¬g›q¦Ðut=Ûˆ3…®£ëÙFœ)t]³ž­€rõlø©Øz¶ÊÕ³á·3…5á^^¦¢!Ü[0’¤'@â$W#…Зh³›ž^‘í¿n¨ÍnpŠnÞ²­f·¿´í&Å€3jWœ!Å€3jWœ!ە̨]ɉ$:T"UŽ3d»’µ+9‘Õv%3jWr"«º˜µ+9‘D‡J¤Áv†lW2£v%'2ÔûÁv%ñÍWÛ•ÜP»’­¶+™Q»’eúã%a޳šì#%µéÀÆõžz(JrLlÚÚÎçìé"ÒézJaçQ%áYðyž‹¿§·;FÖ\LÃô9ü²ÞàbBƒó9þüç¿=þ<4AÓ}’Ùg9Ûãxy—ô>=×+Õ‘Á–¸¥;ˆÙX/¨_ß;=]ŒÔ›/ºuŸHUUÐ`6Ö ŠÝäõ‚bc7$dc½ Z‹ìÛ¶ñl˜ +øè™d›…Þ<ê2ËÇS–¤À~˜)üËAÝ[®ðö|®¢_ŠkÖ+øöp:•X{Ø®63ö½!Uc3ö½!›û‚Þª±û‚Þª±û‚Þª±û‚Þª±û‚ÞÐ…9X5æ ©›±/è ©±/è ­›±/è ­›±/èMS5†o•Uá/ʪƊàTcøý×}Á£È6Cm£È6qN¨ÁëOpŸ.IZé[leÞñ{懼g)vÀyOømKÑf.€V°Øo[Š6sÁÂo[Š6s'’è|„ü6¿m)ÚÌÈŠß¶mæNdo+ÚÌH¢óì,~"kÅ‹6s'2ÔUxÈoóôÛV(òÛ| ü¶¥h3¡úvïÇ&x„PcîßNäY¤—ªò™ÔÊ*÷ud_‡ ú:²¯Ã.W}Ù×aG‚¾ìë°!a_‡Ðêëð…ÝÒí|MG÷5H$€¾Õ¶Ïø×ÝÕ`ÂÈ‚ÊB] J¨xlUp6|Ê] èëPƒ‚®!÷u¨›§|⮫ʽ‚¾ÎwKä¢Ñ ø 6«2@³Øª+³sÜRÌΜeð=àà;˜Vð}CHYªGNÞï?¹6 X¶}è”Õ)á¬È*’lJ—;%Ç×nåN dsÇØ”.ñàµ[¾&S»õ‰¯IÖnN Á’¹²ÿA*³ Ž“Ì}\—;¾&”݊̕‹Æ–ºµ>K•t™×ïâÕgô 8¡šî0áÏÕn¥ŠþJÖnžJÖný\Ÿïê)‘hÇv íç!mÁSe9ÛR%Í!ðEAñš²ë:NÌSÿ+R°©ÿT‘>Y,—ýzùøŽHYñó>RaíçüÑ#¤$¦÷,_÷ÛB*ì•D âí²”#¤.¹MîÛÙz$"Mí-°³éŠTŒ ÐY%~fØÙ4"«ÝÃfØÙ4"«ÄÏ ;›Fd•ø™agÓˆdº±-é»k2ó>ÀÌ{DÒâºè¾¬HÊë’8?"%!„Ë}#R‘B¸Ø÷7"5}Ÿ×ôÝ["Ài@HZØפE€±k\D2"ÀË!«ƒ½F8Ø+"m úËEdu°×{E¤§%ˆWüDÕÁ^3ì•Þ|GAÓ`¯­öšá`¯•tWˆ>}&×è ‘·¼cå ]‘ž(èíqAoDVD=.©ÈJAo z#²RÐÛã‚Þˆ$*+¿^€aAoD•}æÎ#²RÐÛã‚Þˆ¬ôö¸ 7½ù®Õ‚Þ­ô.¸ 7A%yÊ;Æ•é‚&#)eä=–‘ËNt„Œ¼Ç2òˆddäý!Uý•yDR2ò5Xñ¯32ò?-#å"’‘‘×ôTÉXÊ©®HAs^[J½Ïo©!¿.)IíF¼dImDJ*`Iò×IÊ_ñ¨Íˆd¬ôé>ùÃ÷é…F$Ù`åõö> $Ó`¥øuMkÈ«N7¬Lø×™+Ÿø×=XaÀH_/ॗ+ÒPø–Wƒ¾¥ }Œ-ð‡¾¥°djk^o),™Úšä[ ÒÇØä¯9µ‘ÕÔÖS[YMm­¸e›w‘TêõH*¦¦B+’•(/i(\DJjw\Áû¤ÇÇ£¡ÆIJ’’¾Nv²#ËcG¨¯‹HR’t-¯Y-¡¾."5)ʸìèö°<6"«å±#Ô×E¤£4AI_‘\y,¾O®<_“-- \yl¥ûec+£pëG(¡^Zâ<yE>†Òy‘ ßvÈ*šÅŒØ·”´ wÄÞìU4‹±o :d•ÍbFì[‚YZ¸Ê¯×E1Ø·²3h‘Õf1#ö-¥"›ÅŒØ·”Šn3cßR*ºYÌŒ}K©ê3ˆ£Žø°™×£´úRÓå›ò,QC‡?Ó²UfâMÿ•¤Ô¼{‚:©y#’ämSVcE*Vu|Í;ö<ªHû@Ô­4WÙ••Ì)©ø°-Š;½&ȶ(C&h÷:“%¹ÊÒåP\‘t$U6+Ò±‘ü|wÇ$§×àoI¬ò|Õв`dÙ¥%îâ—þå3"#‘rÿÙéŽ+æñÄ)‰ú·×>JÁ"RQõo뎿!d-þÁ³êV$'(åýYcöñ¬ºˆ¬1ûxV]DV2: žU‘•ŒÎ‚gÕE¤­é°F¨ÃZ‘’ÔaP‡‘UÖuXIô0GŠ–¤k„:¬ˆ¬ê°F¨ÃŠÈ* =BVD=Ì+"«:¬ê°"2ÔKˆ+½ùªk€:¬­ê°F¨ÃJPI¨aòäôªØöõI½±"5©Þ¸AõFDJ²)ýk2¶Zó ¾ó+ÕlÃ#@jÝhx4ák2 >ñ5ɆGI½‘œz_“Soà·Äª7 (§ÞÀ¿Oª7ƤÞHPJ½1&õF‚rêâªLã높 @D­5ßð(©7´Vy»ÓëIQ»B©œ/©6”‰ ЬdEÿ¡V÷{Iq®(“Öayù½üÁH¢‰Òê;~]n©)\*‡Y‘uN6V†¿|'N¶_©5˜ÈlcÑ~>ÑŠü~y}Å×$Û¯À'‚íWĉ™‹íW¦¸Nóþ9O¤éèÉÅÛ’ì >W4d-Ž|]ÛŒ³‘l][jr‘ÕÌ ›ÜG¤"«Õîůkª øxF2£…@¹ˆ´D¹Xnr‘Õ&÷3lr‘žnU™&£HòtÀG˜Q. ±ÌG˜Q|«Ê|„Å·ª¼ÌÉ´ªLy2£­*_ð5ÉV•ó[âââ¸ø1óŒFe©vØüMVÑ(Ž‹ŸïC¼,*³ŸÐÉ­Jå(•[¡ší`½,IÞºùTŠ^WÏ)/nÊ+¨(\‘T7Õ£n¤‹Œ#Û1Ì8]d[µt-¯YmÇ0ãt‘qd;†§‹ ­‘a;†ˆ¬¶c˜qºÈ8²ÃŒÓEƵÚ1`$׎áŽß<׎¡øH\;†âª’r\koÈ ›cšRvÚ§«v¦eët–î”é|º%BúšÀvÉY.)g»F—œdlÇwÉéïIwÉyšR—1õñë¿§åþvGHSG.Óòô…ŸÈB÷>NN½./›ÛrEHG÷èùÒW•¬ÓºðÆÿz ·÷ë;~óÝøgÆ7Z×ÀíWŸž0”úô0ényq0 ’@Ó¥JýÀçëò-3jºô¸ìAzÞ’Õ¬{i2HÏ[ªËÛrÎßN–Ùj^xšÝ6k¸¦ ÙJ}n<´"-W?þuÍyJÐ|§Vëý=|\RQµÞ€³Tpôo‰¯ˆÇz.ç ŽõœÔ»¿>¥-Üõ òkHÖtŠ©H½×Sáç!!ÇI%×µ’JI7/Ë"0'hšö¾‰Hº˜2 N²Å” XpT°°à‰X©ÈÉ{ñëš*|Á‚“LuM aG ›T Ž <+"=Ñ!ô hs§ZÛF„”d$+Yæú~Â4„Ó|'„ì‰9ÃuB€ž˜#¥ó[Jç)?ºdé¼3DÐ}0i‚ÍŠ´¬à5uÞ\‘áp$A…âÈ~¯Óû½Fd­ßë†Ìý^#²F8ìVγœ$Hë¸ÀŸq`¿“ìw™ H“ùŽ+Ài2ØU£Ò#u]‘‚œ±­Ï[¦PPŠÚ—$’^5z¤$…‹W|”)yÕþ±Tæ=¹vÓr½þ ¤®#×m<>=#¤¡û®|á_·…Û5‘»èÕ£»ˆ:´|à·äé-3¾f(èÑíïã~öw1fСê‘é œP¯èˆµÇY¡šÑNôP†Z…<äÔ`{œˆ¬´Çéq{œˆ¬çÔ`{œˆ¬çÔ&¤ð9ePË##æ Á5ím=`þ t€(‹@f,Ô Ê"Kå¼%‹@f,Ôó–,™±PÏ[¦QIå×ëÙ7,ÔóÌa\â-Y2c¡ž·dÈŒ…zÞÒE #êyKŒX¨çAMQA/ï^è’Ó©žö«ÇɽoÍP½"¤¤Zj„ìÀX–7xòT:ÓèÉÿ]c$LºÏÐ5FÂ$^(t‘0)é:¢ûAwŒy9ÁtFZßQŽæÔæÿi‚N ÏÄ‹ÊS>  Gd½Œ‹Ê‚")”‹Ê‚" XTÙhø†EeA†ñˆÍA, úüïØ¯)ù2îÍçÒ°Ý«€ß{ÔªãÆyÁ¨%q[Gd¥%q[G¤"«ã®Å¯kª:0\‚©‡ÌìAPÆ>°%qD:¢Ž-·$ŽHOŒKþFž%Ç, ”]Ú…PŠC—µïH Å tF,Å ”âŒXŠé6ŒXŠé6ŒXŠå6ì½<òîD¡~, LãW¤àÒÇ÷ûˆNpéã×éóœÉ‘Túxž/3Bj²T>ŧ¢“\©<ˆO*þ,kOCÂ"RQeíiHXDjz.Å’Š˜K±à¹) q&P׈N³S¦8µuE²,p@e¢cÙůõÓ§kZ¾•Ã’ŸÈROT)Y½BJÑ96¡£cÑy¶\!GÇ¢c¦MlbÂİ ®¼všr÷œˆ”t ˜ø¢kÌùˆŒ]£­Ú=!EcrIL¦!XÉzN$ !9v$’*1Å’‰I&(1­Ö¥VºéÿˆNX!è¦ÿ#:a… ›þè„LáèŒNXÁŽÎ°éDV›þÏè„‚nú?£V ÂÑJ¹]¶K‚É; ™ñ‰¬Å«]‚q‡@%¦5vñšžÈ5ú¬NBÒ}VûâštŸÕÔðâD2}VÓ.Žhx±³Ê áʼn´u$lxq"+ /6$lxq"=ÝåõŠŸ¨’ì;仹áE|óÍ /"´’ì;¡©áE„’ÄrV4 áY~Öö áYÒ8‚sí3 IVˆ¬>‘ЬC¾å-hg`dêv+C•ö eI™e ÙJž¦g—ôÄš1lB2Îl@‘õ>Dˆa;‘ÕÔ#bØNd½bØNd½bØN¤%šîÝúKþõF‚|MÅ%æ.S":Y9yhnÙ,Ëz‚&j´€£+'km/óŒG}wZ £. í¨ïJsd@|"™ºÝCãLÀ e˜*?080"%©°mCW¤eRÌ |PUZ%qœ*Ý„bAT9~\e|”oŒ«L¨J«nH6D…™%ª$Jb ¡;¶â)‹%„îH±ÄˆÄMï®Ô1Ý‹_×TuRKvz7KÝ‘b‰‰%œÞ]†#KÝQ4`Qå'¸ê¹™àB ¢Ê¯/ªü¬ž«T4g!“€¡«C=Í*݈jÙôìä웽æ?WË ­X¹W&K…Ö¬8*“¥Bk¢ç×ÞáôüÕQÇ14†=¿¨L!FGc¤ª·º€=¿N$3:úŠ¯ÉŽ¾#$7:ÿ:7:z@HOEËHÛж`¤$%ÐÙ~jÚ~Î8„×®1N5ß§oŒS]0²î­Áù‚+2´æ ÞRR鳜š†ê!ÐÝ„,2wFÝú¢ÛÀ‰¬tè‹n'²Öm`³6 ÛÀ‰dº $?ĈF·ÉtH¨D·©è6p"Q!>÷—DÈÉÏ‹˜&Œ¬U·íB¦,Íp$s¥)9HOEJ³$Í Ö¦”fÍHš%èZ›#a £ÙºïÜ÷êDJªF¤'Œ&ÒË™°¾ã_×Tµ`®­ÆðœÁ²¶nK÷|.É÷6†­L£Í#RB; ›Æ6d“éÜ4–Œ¤62?Kp…q¼ø¡Ï»ÃÑÂo¤Ï°Ú¢¨ýœQí§0¡Uû9#¤¤“biÇ15GÿèdçÉгt_\“îiUTC(н¦¥¨†¢D"²´¨¡€¢¸¹Gd)¬¡È}—Îér«I|ñ¯ûJߥù3þà' r~ŸñûÌ÷ͳPAwÏNÑ ª¡¨´Ç ÏŠJ’G>¥–¦TFàéæòcúyM¦ÉJ~ÒV>¸á8êr¢çÆ,öiÙƒqÔ óç| §ˆT•ŒÏÙÒgE~~<ÿAHI”ºÀCÖ*º½û4¬GW¢­¢Û»o®§Ÿg„4$¡ÉR«¹F0Ë WךÀGȺ8鲄µ4…tYÂr!|ó¡–ÉÛbZÀ’!ü‘»Ì¤]ëqæ.óúôt5Ð4||N?#2•’¸˜W¸ŽXâb^Qõ{LmÃżÂuüàêTÌ+\Ç®NŠ8áºÆàꜺ®1¸ú_“\‹y…ëøbÞ%í#×5Šyüë\1où‘˜bÞ´–]ÇôÎÞûä\/B ÞNp†±ž­“„üã`OsZÌN]’ú¢K’pŠ-÷‡Yr—3âø>€ϧG£î çØþT0‡åžXæ`ÙŸj3M0ãý©À}Ò²3«LÁÅ€™UTpñÈC^/‰—`ƘÎ{ùaZŸ°à¢(£ØdT×,«ðŸ2}žãó¡–þDÖEq8Óç%©¥Ÿq¦ÏKZ‡3}^Ò¢8œéó™Ï/%%‡h3ùÀ¾æ`¼'Wdü“„"pŒi!>9äßW„¬JJÑfþîŠîE¾«ÙÓªó\߆MR’"XBRvß…ç7üìUIÉ!Úü¸!¤§²œ Jò\–s‰…×|ÅA–ýÀz‡BX;cÙ·Zkg,ûãVk×â×5Uqd?`Üjea­ãVxr,ûãV+µPöã '¬…â=oùþæÙ‚yËå† é—‚<¤gò8Xlæ™<›yÏtVìaþÎ3}ØQ¯a *z’üì¡ãÆéÁg¯ÈNu\·FPÆ+‚à3ÑY $›‰bH8ž°&Ñf`ü,Ú Š¾&£¸"9ã‹ … ,‡Á°õb@’WO*¶r9ü‰TTmÈ"…lCʲ•íˆ@ËçFÊG†H#å‚ãXzÈGßšî;#$%CÝJWÒ}Vvþú÷zGÈ‚]LŒåŸïïÏB’bòçÛe@H²,"·]ÇhT`?“Y÷?§°ß’x·)Ä'Œ”t¡ø5eÇöÚM„d'yYo² ²S¬¬7[Ù)n (`k%œåVgkg„”}‘ãÙ–¾È:"ÉHÙG”_–ÜÜ5ÔEVv–ì";¢ü²ì,ÙEö†òËÌ]«Ü'ˆdçZ R®)Éèì’ß’çÚžë-;ÏñÏ€Q—]hMyÄH’Óß‘ÇpÂeD’'Øï‚k”Û‰H!¸¾Í@!#…äú6*L"y|E"žüd)¸z,R(¾ *åq¤ÐlTÎLIAg¦F”™’‚ÎL(3%¾œ:6#‚†œ:6#‚-B²6ÂSÇf¤@8‘ÌÔ±;þunê¾&7ul@Hn꾦'ÇÆ$õ…–ÛG@ƒ*…åÔk I2þ‚úf$P}ãôÄÑò%§'$ÐrãôĆ„é ´ÜõôD¬¤'ŽF.9=!9-÷^Ø•ÖRMË}2{3*ì’HË]é»®)ØÒÔ[RšI¤å~ô³—.¥¤í<òÒ¥”t¹òÒ¥TŒšzéR*޳Z_Ò5ýº¦ÊœÏâ¦tnJÃ&€Ç" y"Ì(Þ”¤JùÔµæ5UÊ…ÛýמÈÑ,â?¥l•áGÖHJFuƒúóKZýù¯É O§¶êÃãŒ$üä ¨ƒ¤ ½}úšJð*Ð)ïJ²*Ð+x"Éð´p²¦dÔ¿#š¬)ú÷¡QšK'êß\À+¦·˜u·î8EJeéÞ»B&ÖHå¸9ß[Aô !뉀#BV§ÇDÀ!«S‡¯ÇDÀ;BÖ&nÈm" ¾¦¥Ê3áûôäDÀdžŠÑðãØP.m Šï¤î¸´)`¤îÈ´éˆÒ¦R š@iS©E£®*ŰZ6fF¦}¤%?3²/®IÏŒLz &8ÔgF¦SLp(‹ïfT¦'Á‡G$TžH0Á¡,Ó›Q™žDj+¯ø‰ªez#*Ó“x‚Ã#4—éIj‚C‚¦2=ÉLp( ¤V\E6<âµbލZ3!'T H­9Áêû˜ÝZm8Á*t™4ÝWyÞ{‰äkZ^Ît/HpË‚¾ I Á­wqLG¼f©o@ÿJí9÷::´Šï))æ¦cIH˜›ŽK°BÁˆžÝðÅŒ™þ•†-f©i˜Nˆþ•†éè_ ÛÝWHòœ¬—PÚZ á3ý+fúþÁ4´4šKÀbLkðí!+p_t.’ÆÒbH”¬—Ƶ’õBRP$(M‹ÐÎëÓ³k 8dãë œ²ñõP’mîÈ\ä"mG¹Ì˜„´ä(«½ü ¬O Ú¬õÈiK’g!´»`I+¹®bÐ2XÕë&;o+çÌjVÎ,˜Õ´z u.’Öðo ܧáºICË`-+L‚߈/©ƒHÏ3Â_TßÔý‰>~Ç$Ž„=kÃã.·B–%É1aýúñ¹`$Q’¼ú ï1Ý#³’ÑèéÛ 6Ë㥓\G —@¾UÈã·ky¼Ýk`³<^V»ÃrƒäT;Õ3—ì§Sü˜¹¾¸&=f.;êNÂï£/:p¿"õ ‰ÜoGuCÝÈývŠ~ïI±,ü>‘5á÷ŽÌÂï(d~Ç7ßÑ3ö~PAÙK¤²S´ð{FC@¤Ó$Ë„7Ig›’Ûà ›=ÌS¤³9¶‰ejÀêÛ4µáDÒslÓÔ†Y™Ú°SN¤©#áÔ†Y›Ú0hjÉtôÝ!}µç šÚp"…Ì sã›ïèѼ3¾Q¢‘ šÚ¡’¢‹Á¹àzfêÌyŽ.†Ô™ó¼@(“À.°!@»À‹u3ýî;ª[Ú6Fj vGHIJJò)ïç ÁžD„¸Þçm;ëÒ™Xˆ6a ˆëúïœ=1 Ú¬•ˆÀ+>ž£x¯¹ÎQ0Š÷š‘!ÑsݨÇè S å^Ò[&ñ’§ÞÒQöî¼cÉ@àÝU¥n©íInä"=]2¶ñ{¹¤QzOu\,¹œÈº±eáSÇÅ©kiÖa\>ž¾ów•^m¹ÇéÛ-ÍFb|#&1·7 ¹b$5 F²¡kD²é‰BGWÙ`1æõ0íZE¯ FÊz© ’Õ’Ý’–@ä•4++9°ã°Ÿ‡Ì6C¦ðFœÂ –%«õlS È!×jÜ4 ¤$=GÜÁ3 /”è$Eq‡Tp!0¼J(Q\=¹ß¼"l+’“ûªë˜¨:–ªã‹2æ:¾ˆ ,Ù‹õñg†M‘½Xdf0T't€U§ZKG„”¤H¼O–Ó©Õi:Õˆ¸wÕNX VêhaD‚ê,û5óúTcRáãR£½ Ä6¨ÎsƒÝdTu”dôKdɨê(Éè~M =‘d[³Ì!œHŠC€ïSt[ ˜+%šœö !%Á—nS Ùâ6G„¤%É&+¡X D¶ÉJrN ÍIî_§„f²3h-AaX­ % ”°œèdR”r*Å‹ŠÁû„ò¤ÇÆ#@p¥”n ®nY›ƒ¼É >^úï?ix»”¸ E7Ü€ RÊòÝΓÜK)Çv;Ïr/¥Xy<¬*ÅNœü³¤Ë]€³Cwœ4ë97ùTšZKã92_³Y<×§–\ë9P<¢´dÄ¥·QZ1'äm”¦}†{¿œJ{¿šñð‰ ™È1ƒXè4j²É%MßPFsQ9ô~áâ8xj›ÖœŽdŒeâ8ȃ)ã¸Eè×ßÊ×c¤,òw±ÉÒÖý÷)"ÁÄÞJ;¦÷ùþƒ’BŽ?éì0ÔÄÞþldl²í¸&Þ`N‡²;e^S°Íðs3geé#Þ¦Òß)·î„Œ®²Š`tù™ÑU@SQgtÓ.F–ŠNPˆÑU Ãn̸7#-ÐiÔ¹…£²šháx´Í-Od¥…ãÌ-Od­…ãVкKH¦…c~KºÑ±@2-ó ÑD Çþ~C-Od òІXÓj0#d½Ðc=·†>Ù:z:ùÁæÖr NQMv—:àì »KHpv€îRDëøô>Ù:~F*PeÛè2+O”븆<@y¢\G*Of¤¯š$ÍÊôƹ¦—ï#§!éá}qMzDx*£8‘Õ2Š•QœHSGÂ2ŠYõîFTFq"«e*£8‘Õ2Š•QœÈ@!sE|ó=ýwô€ôûˆ¡²6üeF£î<9&fF£î<9&fFã‰¬Ž‰™Çx"«cbÄ1žHnL̀ܘŒäÆÄܲ:&f@㉠ÔÀ#h™CCÏ“¬½è¸Æ/@/¡Ù*yW¦å »f[ÁfGZHFö7~I¿®ØŠ¹×¿wŒ$4lýçß?„$ëà²báDêZ¯û1Zh²×ýŒ-4Ùë~FŒ‡†3µ‹^÷3bgϵæÙ_ÿ¯uGÔÒϬך¬ÓìAö±ù¡Ö‚<GTK«ÁÀèåÀ^Ÿ"/80º¢Ë¸Ö’kü8p­ÙFî@5¡µ¢ší•SZSQg_TNH²Ž87Û?‘õ1(¾÷A)´9súuS9:϶Øýª]ì~Hà~kK¸ß{è~kK¸ßGÓ`à~kK¸ß¸ß:›åZ·ºç[ÚG¨³ÜÃl»?/Ëïè."%ðÃôCè*ëÀ"« ô½•é‡ËͲ†µu-‹Á¡~qeERC#ø\gÒÕh#Ùg9‹§Ñˆá2ðY@Û^mÔc«êxxÝû¯û|I¿®rµ`'²>ËÆ.fþÄhä.îÈÝڑן>íbƒù“æ55Fî”᎜¦ ¾æ¾êþ÷óïþDÛß÷'úº À–j±»ž†éˆo4€ÓÐh@¹å÷ïß·ä¨ èâ‡ÌõåeøÄÈÓHlõ{,M¹ Oïøç…¨Ï&]?üT<Óî l§ì }}éß¶«~ß/ò1gïª躗^Ÿ÷§Ún`s¿ÿ^þ÷ª躙^_ž£/6 _/ãKò.OèÎu¿cím7Ð/?Ï) ;¡C·-¡åc¹ƒõz½|\û{±¢²k“¯uR‚ëc ·7¼¨DH-ò÷[}[ßÀŸé6ý™®ý3~ò`»þoýZ/ïogdsï/ßËòñß«1v@O ¹Bçû[ªkˆP‰¡»‘Ú¡kÌÐc¨ªÑm/+„k'TgèzÕ“6ßš Ì÷º­þùõër¤’7¾ïz¯R¼{@ÿû·ÅïUlü–4Ù u[úÏ¿×⪞žC™ÜP6P–‹à9”Ú®¨÷†é4½Ï+J®žq¬t~Ýѳv/Q½†…ì,Þå†L+ÆÄ> öŽ¥°wðëîwŒS¿ À ìf5ãÔ¯ d7«§~M »Y8õkÙÍjÀ©_ÈnV3Nýš@v³qê׺ß1Nýš@w³pêצß1NýšPî"5™{jËö.œ/—´ë,Û»ð¥ÿü3#$•³é÷ ºp>;5Îù.ºð̨fC[ÑêÂsGȺÖÕlœHMQçÀ8XIø¯»O ÉAËÄ-¨XÃ~ŪUkدWoHP ¬AH¥#蔤-ÌWýWv„„£5dþo£Òk-¯öËø[ÖR½Ÿ6$$p­e”îë]~%Ãh-¯.Eg *10ÝyÄWàü´ž ;$ ;­'èÎ èNë ºóüõ{ñëT—(ÈæXOÏÏÞº–gÿÕzŠîÜTSî´ž ;Ï80ÓÖWéÎHñç:mwÈ‚:mU²!¿_^_ñ5IŠ®²ëÖn?óZí:NÍùuMÂhí:²Ëö1d1­dב]¶!‹‰õ*E¥úÖ¯Tªk'xµANg:Éuò…‰OGÆ–{~XP1R¯pH«Îi®³<¨pР¤^³‘œ+ǎЃé g¨šÌí}‚šL ê@jRsM¦F @‘¹&Sƒ 5Фrã†ØÁT®sÜ hëœgõ©ï÷äº@§H÷k!´ïuì>œ#ËQÓ±ËÞðñ7òh^TF#ê¢ ùùñü!%ÑTª‹¼ 9¯Õ¸ÎÉ­õ‚æ¼¶QÓO‰óò0å\E™R;^²£(AjÇK²»âˆaÏöÅݵWdwÅ3žfEgÔ]Qƒ!ß„67ýº&µ¹ÖæÂ®še÷i#µtQ3ðÀ°çd•·ÜzÈGW{e¦Ží0•ëW!ê¥5ì•ùX;:Ý23è=×j†|`:b/P3äU/±Ù%P/¡a·ÊbÐˈê%4êVùÐy qÅŠž³1ò³º߀ê'u¬G 2AÒ™T?y"I?Ä2!×O–Ã݇}¸{²uAU,Ø{²uãŸ8²]ƒ¾–åøaÿ}EÈêp÷ýš×tvÅŽ¾MP´¯¸w_0ÒV=ÀÍ*>ßð³W‡»ûp÷”L  kyIMÃÇçô7f‚æÎÁ|^0läó=5gس_iKÉVvßD=°Zãq†”­ÔÆW§ Šz‚cÖge+ÁqµÍ—¡Dýù-"¹®…Pžh:ExVG·‹ìYPU‚=«™=+ÓiŻ<«Yó!ÏêDÖÅ|ȳ:‘†´E²é #)ë"ÙÀŽ¢å öiŠäI²[Ù :‘šî$;¤gç{CäòZC×Þ¬ ”טΒåµ#’טΒåµ#’טΒåµ3’טÎÒH^c:K–׎H^c:K–׎H^c:K–×ÎH^c:Z^³°™Õ5-¯Ù¡™Ö5¨öæ±ÕpVMG'¼Wƒóùº|¤MÇN.$¤¥õüH4õFðÓ|s~ĈŽ\ž]P#¸46tAôà±}ÒvtÃNd}ðØ>i;¶ˆ=‘šÒ°ŽÉù7Br£€ú|$frù.JnƒŠ›d &Ų™ì¡ãÌ®²å ȱ<Ìrv, T·#ÇòD&ÇÒ€ÙáØ±<Ù±4`v8v,Ïk^óZ2´æ9–&ϯO‚ßÈŽåy($ÇÒäÙá…c¹#ciÀìðR±­ÏL[AeúŽ5Ÿƒ>#7e}'’h¨ #<Îì×ÌÁ¾5t:ö lûH§ƒ`߈ÀÑé Ø7"°ZÛLtÙq‰Ña`B•®ÌHÁ¦€ŽtcͽU}”É–”ßFðë’ §b›VsÞ¼BÈæ¼ûq èJƒjг…HF24Q²ÉÀæ¼E²i@É&›óɦ%›N$Õ€ ®%iYâ8ÀÒqͧQlˆ†¿q4]N†É$éA2ÔÔë bç 5’IÒƒd¨uà6O8ýz É“¥äŒb›\ƒÆF±M®A€f”`Bã­$/ï ¶^Åtú€ètªj³™N7pÊx™étªªÊþ|j3óÈçÎw7tkàí×AÂÅ(Ã6ÚÈA£Ø–R@>k”ㆺÒ)v)!‘„Ô(OJHG$!5Ê“túˆ$¤'²J§HBz"«túˆ$¤'ÒE°Ð_Rºè £;¶¡j¦ƒ 1<®¥œ¸4Zp>H\$Åþçá,Î ì 'Åîa;£I¡ÂY~œ<+zÆù‘¸L­-VìÈL°ê´âƘªÖhM·ºC¢m£5ÝꉶO$)XÏ­îN¤&'ÁçXFn<Œe4Ù~h³ €N?‘Šœ›žèô© b½OËžïð}Z’úžõm4jƒ“ ÁK™ÄˆdF;R&1"™„ÑŽ”IŒH&q"«2‰É$N¤¦5e™Ä‰4äp÷Ë„½*“LâDVe#’IœH_ÔŠ*!f‡¨!Ñì5@)ŸHªøiN¤&“MÙ»ÐÐ ¼ $ÁÇÍ#p­¬1U+{ ‚LÆtT­ìŽÌ'RQi¾¬í4Fð§v¢¾ Ù^Vl¢Á°cwѯ+¶r.":‘²–F‘ ÍÐãÕ÷á% 25ŒÐ {Ô†z¡ÑÈÆXR^8£ÑÈ'’°óp4ò‰¬H×–¢êÛG$޵ •`<‹©Øàû±<¦Œ¯ Ïn€ ÚߘÀN^3^}ze߯ ¦/ò~­hŒO|ˆ•ìTÀ‡XÉ UíÛŒU¼·–ä1Æj®Ì¬‡OÄ 8ÇÜ7àsÖ4†¹ækZv˜+¼¦e'ƒ“Ë:v2q®g6–*×ì‹rÍ©¨‘»Yv"5Ñ€òÞü öÄG¨Íôƒ¤2äŽ42#‘†qkEÆ‘ è÷R+pŸäÐôslyö*cËsSKã98pÀ 9[^² r0¶ü±¡'ldé¥ï÷ X#(±{LmƒTgl?¦¶!é —Ú¨'RS)x9Ë}#9Ë ¶ï¬Ô8˦à¿ä,Ç”BÞ9–ûþ<ø‰ËõšÐŸwŽet?ïÃÂÝ·1< éYà‚Ñ`> |ZßÑÒ5$“0¾#×Òˆd'’ˆe LâD’Ò_À{Áö,±'=À»|—,ÃÞ§WÌ@k{Mdž8ÖöšŽ q¬í5+kÉÓå3zOz•…8ÜxKûÉHn<³‹§ r,Þ²Q\!$Xº2toÃ×¼ãÚ…C=CpqéIH<;.}«Î3Ãó{@ßùllבí­qç2Ûql ì\f;A·5GùwÛIî„qœíøÂ9޳pÀö£ˆøÞ¶ÓLÛ}IÙÎñш²À–†[yÚÎÑ¢VÔÊÓvŽiª[yÚα™Ðœ¶cùù̃Y4`û±oZæÁlçIÿˆbCÛqƒêalhá(îZv íw+:¦¡<ÜïVt\Ñ `5­4…ÚšX!h& µ5±@gõ¨[ëAI‚’ëÆXRuðuùŒ³´&j¯˜Ù-+4ã+Âg+ —Ó ¤†ËéÒ Ã­dÀ@Z ‰ªŒ[l¶–ìüx[ðw·dçÇÛ‚¿»%:?¦¸#]Ó±‘~ެ öû~M#œH2~‡oÉQñû΃åØÐ Ï5º±¡žktbÃIå Alx"5unf?ÄŠÀÎËÉ 7+Íð ²P+Íð ²P Y% ‡J¥¬ìhn µ[²¼Î žÚdÕS–òï–ì z sþÝÖ:¨fíàçmÑAµDf~Þ"õÔƒöðó–è ‡ãk# SvDVÒÖfF ¢IÄÚPAt"5Åjf%‰•Œÿ‰”$VÒã~g4î×JÇ4¥‚E©*²*=L²JÁJÏêi³æÙÊÀóÞy-©Ž.î“îµZ4ϲ¤zê(oÉ,±E½VË¢é]S‘\匲-–í ³-VinÈ4YÅÉËö… "-ì ú8fd,ì Z™ˆl¢r|ǯg~É*Çv;Ñ3}DQ%[I¦Ünºf`s¦À£VQ¼ Z6šòI*@,Ck¢v$ˆetGêigiöì€ïj¢jþ|>7µäª! Ó’ñÒa&ÔÒJ§}Ø0° U¥˜­’r=)g«ä\ÕšôF”ë±Z“žÀˆr=–T:'ˆ¤4Û$è¬6l.œïäPù¾Ð×Ym©V§û[Ê™&«—™&«—™&«—™& D•Ì28´ç›$¤QñV¶IÂì¸Ài9@&ÔšŽÏ0æ¯iØì?ŒL¡Žå»è>ÙÉæz2“o {Æ&ßÅŒû…ù¸Iæzr>îDjª¾ìRs Áî0šR›ïç&|vÃe«Ñ³Z)ŠZÜœH2–Ï^‰LÁx*oKÏbžÁXºxó PÃSxV#ʈYØCï‘‘Ùk<«â{ÓVÑš³lÖv¬n øuV°úà'[É\ùɤ6æ`¢€?o™“ ûóVñŠ—l½­æŸ([o«éÞ‰Øû¥U4Ç>Od¹h=‘e{'Þ/IO˜1kd9ž¶Å³Ösº5ÇYŽg€mñ,×Î 8[X x•6м *p¶t›¬sw\ð5uu¬;æm\ǵ£:Uë:® äm¸±îH§ja›¬Çd…s‚Ô”˜…s‚Ô”˜…s‚báöUX#Çrª {eAë­ÚLÀðµ™ ’Bà+ÞZ¶`ŽËZB}…à+yX`i³ÖhƒnmuŸãû¼m&,µ}°Î°Ü¼¦e3bÀ.z›˜ž€ólvxÎst!cæ]ŽY8Ï´›ë÷H?>P§”C:‡e¼,©¹¥õ‚í "}/Ù>±Y[h½$µ…3Žô½$µ…Žô½d"}ÄÆ æW¥¢¶Ú·^s@¦ÞzÃ$ç‘7$k4bF‚l?µc\­wÜ%ÈÛxϲpðš¬îæz‡q!20ã'<@Ÿƒz† Ç¿fà<@¸>%Ÿ?ëSvœÚÄ›N2½)cæè/…zßIÉ*Áׄ=^Õ@³ç$wì÷™¹J'5«‰o^²}$@Œà¤åÙƒ%_Óqûx€N:®KúFž‹ÊÑ7òtE»NòsIrNß19ýù`Nu´MFugæôâ8o:ÅVm@;¯ØÈäP“ÓǺ_§ wCë­ éƒ]¬,«h»XYfwô艛i‚oÞ³yXø>«‘Èљӫ‘ÈÑ™#óÚé»Ç'Ò‚=〨™h{€Z°'Wf_ÓëcÄ+YK^ù­¢V¬òXE­85ô?µæ¬7ô?µæü%xiïÏl—´å2#Ð.iËd[¿¤Ù9îpÇiÇL•B />¢3ðÁoëlˆé¸ó>‘éh5âœì´{ðÝàl2< dY8ˆTlTÞ¼ÑìÉ‘¼¥;õ=x°Š0Þ4Ž&à5=S€v1Û%íb0Ï«¶’Á¯ÛŽÝÅàÍ[ÁqÔÏ·K¾¦d9êKö—@&Nþ:ß_ß“·µ½…ïýðù='ûi%h{ûl{»Y›¿ËõþަÒÌvE¾~¬ó!muÔhÿÕ_QÇr"Ýã4¯y9©é)o ¾yÅzA`%[ͯl,Ë{CË` ÇDÁ}d-kmàªc--zvÏÞ'¼f †:õÇX¥9íµ,gØïC–©Gȇ~ký‰\¿ç€ÕA§ã8=? þu]›v_½O4èô½?ó\÷áþõUüº­öÀìá Óéê»xƒNOdeÐ醄ƒNOd9ètG^ûŸ¾Ïõùæ»J[¥:ä¶J*j=bñS?”‘ ÄžíΉF¢­OϱÕ]¼!¤„ ¯ÝÈß79G,ÔrN=,¼c‘lÈe~zJî H°FäÞ¾ù¼æ÷÷° ¤Â]èãrúý‘{Œ;Ð bCîKôìW/—1’.OˆH%œà>ßß‹û´¹^ó-þúõïï×ù§øuW+¯ž71q*:‘ûÂûù¿ýÙß’ù= /=~öp ÈØþ{¸Ï_ø‰Ž…— {[Ñ z}š¯†î_éçŸý÷ßßSz¹ç—C%ÕQaY’ `ý:¢Î÷·x.l¤e(îœáë‘/ùš–Ø<ŽéLt¸?Ûñé?"r~/BJj`óµ¼&¶xyôüþ:ÞRSc˜—Ë _Óc˜×eÒãkZj¸ò÷ðrGHGÍV¾¾ç/Ÿú³Õæ%¯çB¬‚?‘!!_Ÿ#·Ünïë¡ü„¯¹/¼c²òvÑ}åí]/›£K ¯:.ùö4ßSRã’ßçòªª6.ùåzy½ö×Cõã¸äã±–¥|,Ç%o«ùu—ü2O^¶¡?jè¯c\ò¡rÜÆ%O>ÿ÷ê¨qÉ?×OüýÑÎp\òqÕùþûå³xY¡6.ùÏåv¿_‹UuŽv~—<®†ª„ r\r¬¡’—|+¡Š—üú=àu-5)0ÆÇÓMªW_ š©@¶9=›Å;e%+뉟Zh:ÐÎ¥.¼"×p »  6ägÿzKëÏCéW1uqÝÖ²á³õ0uq+K¢úikoi\£Ú>•;/8}‰T/øÐKò7€'¹¯± ðÞÝóròŠ2ûýúÚǧqÂH‰‡‰Þן~²æ¾Ö¯©1r×síÈiºàk"÷u»âûþD_÷Õ{Ò³À ûêå¾FO#kîëŠDî«W5÷5ÎA»¼ Ÿyº¯ø,Ù¡ÃÓ;þy!jSˆ‡-ƒ>ÏtóuÏ?½¾<¿ŸõSÃðõ2¾|áWZ7æ¯×ËÇu¹W­óu߇Ûj|Še -}{fwò”úµ§ÔCžR¡ŽžR?åé)õ%4<Èé>¢yòqõïÆüçŸWèv«ÇU×[½¯†ë0溿ÖúvOf÷„"w?9ñÅVÑ[úØ~;m?ýàî³×Tùqø±ÅöË5Bqû}ôï‡)¯?ן¼ô£»×ß8ÏCʪHKŒïEǃ¦ãÌ­ÛBö䤯r@Óúdó€=†¥€îu "VŸãí¬¾zóýòû¶àw%,F䓇.XÙ§PNÉAö–žŸõµTÛì®ûžž¿¯Yk›½!§á–âl¶A×}Ó§=êÈAIóœRO&Ù:ï«RÍþ$ö =÷Ü5·Yõi‹ž(]nBÒDé-[½Ð J¦zfÂ,“[×)ÊüŠV8†)·ž:‘’ân}‘ªÊüù½<Å5ëß}3$å5MýÝ6âùއ¯wL#|M„îÞ 1ùeŒÖ•ü\ >­®~¸!¤¬ùz#öõíëÝðÁh_@ûzÕkV}½>líëØ× ´¯7c_/оތ}½@ûz3öõíë Ø× Œ¯7`_/0¾Þˆ}½Ðöõ (çëá·ÏúzÅU)_o¾^à}½øz¡íëWå|½ZõõìëÖס¯X_o„¾^¾^íh\CžtUͲv×ý8_鼿<^–l&`ŽæŸõ´?xƒõ´7Ûaw¾ ´E¦üÆÔ‚Žjw,®©êúhK «Ý{lƒ9+ºº¡—×X7tßÇ"®nDzj²Õ–<û˘ÞRàÞçö‡‘•®Œý>°5S¾ëT@|vß‘ú“}ªBîÕà¡¢ûá>7R9:„¾œ«1?§!¾c¦"îÊâ‘ã;z*âÎÁ¦ÏwL.~Ùú*\nIÄ70;æá°Úó yûøˆQË´üŒ)kó÷ÑØÉäx0¬¶œŸ¸#ÓZò`X-èÂzþú2N×ç+B1Óþëw„´Ô|º¬ƒ=‘DÌ´l.ûŒe®ãûœÖ/uv=‘¡TåÑÕó4%ÕS|ó]5á¶·ÎüÁ/TˆÚTƺZü¾€JÒkï3ÔÐãM7¡v‰”¤±½äeÏ” îíD.BRË~‹ÒËw¤Ÿ7‘Àˆª /Âzßy‚*è ªÀƒ†‡x+׬P}AœÈ UÐTÁ‰4õyô*8‘–¹’©‚éˆO€I>‘ª /¨‚ªì¢ ⛯P}ADh…*è ª Biª`É;Ô³TÁt»Ý‹{e¨‚rA1TA>Â|¦ j„rÎ#ú.PyÄ òˆÔrÔåkyÍZq¿fÎ#žHMÑÄ9x" E¿ƒ%¨<âÎèæ<â‰t÷›óˆ'ÒÓÙÁwüDÌÍ-Å5ÏJL>§9 `ðyÉaß6‡øgÄׄ¼ã[lv°žô…öÑ#)!p(‹Çá‹Ç¡¼#á¡,›fº–׾cN]ÁCY8²Ýîç¥ìÁ‰4TJ(gN¤­5”Üü¬×¯O|ŸŽÊó\¿fŒôÔQ;¦Æ'2P©›çùŠŸ]tÔ™8\—z°NÿnW}ëß>v–ò~ù;,·kñF…¤H_øé=éÝŠOïIìV|zOúc·âÓ{nŽ):’<3wIžôÇì OúcöÇ„oùcø×9lÄožóÇ (åÀžõÇFà ßôÇðó³þX5å ü1á9l„þØ %ü±úc'ÔWµJ#Ô*yP¼Oð·]S¹S0Ë-Ód¹wA&NÏ{gâLIVÕ´µIÏ$q#žRô‘¦ö>7ÙëeÊßÝF“»+T·ÝÑï†tÚ¨öi¼üþAH—’W›–u?w-ë2~þÆ¿~šÜÝ8=f|»æü=~?á÷y˜Ü¶'Úâ…÷$z]¾&|Ÿ§Éýç×ÿè‘>ØäÖ/ƒ¾î¹ÛmYýð~Äw™šÕi?lþî¸îi¶[yÕ##÷߯ýM½ç§ú?Ч:Mî®}{OúØþeëëŠ?~”Òþóï0­oõÏêþ™–ß/ÅUO)íz¯ÛU÷5­Ë~Ìñ uÈæ¿½')ííá±üaó7ès\~›æô瞺Eè‘‘Ûb¡­›Û[„÷¯‡ÕßÐ_ôçþpÕ##·.ÿ úšn`O‡÷ø^emóo51È€jø¼Qߢ rë;="¤$Žœ ¼¦§)ê-3Òç ü­_X`0ß_Ok,‘ç®×¼ [ö,^Su\GákîˆéUÇ…XϹǼWl®iû»!d=uô“K×dޱ­MZ>Æ”$ö-åpÉá’a[úõï¿ýütEHM/¹G݉4µnô×­+dê¨q"Éú*¶)zöÅyàa¤¬õ"ÝÔYüãaÏ€JÞ®|4Ö%Ry…É–V˜r9ޝvÈîKž¤ç•eÖç^\5#¤¤*BàûtLgYü>©dËvأĈò¤.sÄÉåÉ€¹zͪ.sÄÉåI]戓-Ê“9Æ'[”'u™3N¶(2ÙrLHÎ'ˆò¤.sÄÉåI]挓-ÊÓºÌ'[”§u™#N¶(ßÔeâ[eu™ÅU9]fåt™øëçd d|gTþéU ùæ•©zÈ2Õ•©zÈ2Õ"¯Y¦Z½Ïj™êŒÊTO¤¥FÁ#$ÐË•©žÈj™êŒÊTOd¨{İL5¾ùj™ê •©FhµLuFeªZSþL#RªxØÕ¤ªTI_wt/ˆ­À$3+Zp3{ ÖÐôlô£;zúôš X×s$#“ˆGZ­¸)BÓ{&+@’Òsš±/¨ á nHä ’S0–8 ,]“COËDÚÒP[“ìÔKçDª¢wÁé»üýžÞîøšõ¨i˜>Sß°Y/€š—£-Øž•’®T¬äA§”ZIWîBìõã©ü–jاû5ÁúñTNeÔ#,£>‘ ˨O¤ª–Q°ŒúDjRâ ¾&8•kç%ï8Š£Q:h\V³xÁHG AÁõ‰ô¤lú§¸ÏPÁ°à:¾ù®^q=Šëõ’ëÕ·zÆÏt˜»Ç’ëéúóœx/Oåÿûùß~„¼çZÿéöt»P}ä®vÓœrW×eZÞŸ–JÉÁ—ËT^ÕR9)àäê@ þnh\´×ôÑ]„£aÇQ@ãÚôÔòq@#eÊ™b>m3øiÛ›†ˆ0³d¹MO)Ê|Æ¢LŸÛôYàñúñ¹~¦)1%Fóu¤™ïmzªF'3„† YŽŠ–ìË ÔU¬ÞFü¬ÕHÞƒ±TëŠDFc© ã&)Fc© ㆄF“xMs’G†ÊöeÞÐ8Vsv-¯YÉöeÞÐÐÀ‹¼¡q´˜gš +n¨¼a_æ •7ì˼¡iä Áªcó†ÓóœEÓÌN”ÊN·ëX@iE옳¯Ì}OçÍxÿú˜²˜ûþñ‘Cœ"©ˆ½¿®)EìrIJã™”ñrûʧ²ñ•¹ï§@eV7|ÀOäíêïKöœŒ§;4-[¿Âä»ÀÎ\\Î} þ#Ò²ž=L^Ø®â9E¦` 3—¢ŸÑ‰¬ŠKÑÏèDá(P´‚‰û¬ŠKÑÏèDZjš$QÞÃ@ñ@VÅ¥ègt"kâjlQ x¾ùZ ¸BQ xB+âRô3ŠÐªnxÆ´“•¤nxÆT–•¤ ¯^³ªž1•Z­•ºáSY ÕZ©ž1•e%©1•Z­UÚȳ´Z+OäSY²ª1•u¾ùªnxÆTÖ ­ê†gLePN7\@9ÝðC9Ý0~¬n¸x–¬ÉΨUt§R45Ñ[Íò½yj¢·š-Ý}Î\7èuW/ÌL5ÖМü–㘲·Sø²­ãÌcŽ_‘åvæÜ’.BÏ{Ó¹F£»ú:Gf‚FÔÈ;fÊ jäÁ4­2¨›Qs Ym4£æ@'²Êͨ9Љ¬rc3jt"-‘ƒUØŒ*à]\`Â*äcfK¸*®/«â@³%ôeUœïˆª¸¾¬ŠÍ–pU\_VÅfKåA¨*Îw´‡‡«â|Ç”õgõQ×—Uq¾#ªâú²*ÎwTUÜRVÅùŽªŠ[ʪ8:VV*زŽÂ rpÍžzÎG§—l꾩’OßTÉÏÉ©äïÉ©äG„äTòø×«*ù«ä}K%ÿΩä1Ò“o>›;¯™2\”„ñšä°FÌayÃ^ÐØzCrX3æ°¼!9¬sXžTÉo2\ÈayR%¿!!‡å '·€¥ÒÞ²¥Òð»[Jä³Élà!ë_Ò+C˜î1‡œœ@ïÉίcaêY=¦>ÐcaêY=¦>Ðcaê#NÀ¦žÉú¦žÉúâhÈè±0õ,€ Sèè¹0õ.€ž SZ¦>}úê<Ƭ´ÉÝ&|¬ÒfÈÞr¤lØ' ¦—˜ãcS†dõNÌ4¤ ´_](Á@ûšz+Á@ûš‡Æ~X Ú×Tè`¨íkÊi¥#V‚¾U!P.fÒ V.q3$’T$»Ä&TIYez=X¶È ”åº©× 5õònêuCM½<šñXFÜ[ø1$¤ãUp`9¦éæ6Ã$?‘çŽcØ x.¥ýÿŠÊü5ÉðŽˆ9 ]G2¼#bxCב ïˆÞI´‚GÒ‰¬2¼Õû¬2¼#bxO¤¥&er"‰6Pá=‘U†wD 2¼bx㛯2¼bx#´ÊðŽˆáPrülöîB'˜ %¬  LÈ}vOd­²è³{"um<î³{"Mm<î³{"-%$Î&4ÐKãcš0²FÜí69'`jZS#:Åf‘óÑ:²ùÓ&욀Ði–æÊ´LèÒrzßFt\R’I²>¿%vpú’Í]ÝPjbÚœE]}:¢,rè+¦½–׬VŸŽ(‹|"5)|MÇ܉4”ðõ˜ºútDYäé(5kÎ"ŸH®úÿ:W}Z¼y®ú´€rÕ§T’éöÄî†Îs3 @ÓšÇé[<»¤EBN¤Ü=‡~Atü9›ü :r¦Ù€4’™; d¢á³õé>%ï³¥æAȆqˆádÍ ªÆaº)]î'(8 €¿ÞC.?‘iô›0’é!×_RUëÞGPƒ@Y~6±G,Õ ÂVÊÿ¢"áå2þÎOÄ—êMI×ëîvÉyŸ&ÐþüßþìïÇ5Ww~o‡Q M½G×úBûdF(Õ{(k{zŸRYÛ‰t±þìùååí48÷·mîX!¹T¯¬þû¯ŸÜ†ãD†Gätßæ=üLÅ[:LÓ¯ÍkZï3þü´¬¦v)?ÒYüõ(þÚ¯úüüpUI´ú­ƒp­Ö‰#BJJŒ²núôóž xʃbûšØ9§ü9€÷ '»ddž“™Ý äÞÃŒäð'H&=·™†ìHÁ†“™šE s©Ì0ƒd†Ì£P:HÅ ù„¡tŠcMA˜¤n…iIª1€/ë EÝŒ}¡¢Þ¸¼æµ¼fUQ7c_HRQ7b_HºRÔȪ¢nƾÐt”øB’SÔa$§¨»ã7Ï)êð#±ŠºâªdÍcîp$W 0ÉE”…Wê_טrDHEÕ'^‡ÿº¦Ò ÀàÀÑ•ú`î¤g‚/ÔÀZ×ZIÓß=_Ò”[hÈj ­µÐ:‘Š,Tº¿®©ò#ø53‡ ö+9‘–¨-´Ndµ…ÖŒZhHOM;Ï„yPïö€0ª£ÉTƒr"+5(}Qƒr"ëäªA9‘urÕ œH[7Œˆ••ËeN|F‰’*—ËœøŒ%'²šŸQ¢äDVsâ3J”œHBú%'ÒR³‚áwŒô æÄOd5'>£Dɉ¬æÄg”(‰o¾šQ¢$B«9ñ%J"TRUÀˆ)IO¬XO:àp娛/Ô祸’dx²åØ{{æ+Bn×\[ðõ’Hûß4¿Gdòäí)"Ù›è.½%ÇûàÙ=×ÈòÊsó¬Þó̱@Žp?ò×€=Ód íM¢z„û6ü’Æšé-ˆOA ºsJ<-È#J<-È#J<Èj ‚Jàð²­6Êz¿j²*ƒå€Þ/¸Ž>ŽqhìhAQ;AËÅqhì©Éœqhì©ÉœqhìÈÐxphì;a©O5“ÁI6…7æ¤c¦`¡z´à˜)XXá—ß“µ‚Ó\¨2 ®Ññ/kÓñï}•O$]ç•`ÇiG‘ì,˜Ï¨añ‰TTMVnX|"5M…åoD»‹3굜oõZ¼!$Q+ºÌý%%§ØŠ°i >’s¢×ÊÔ­ïh¥ NÝ‚Š°J×1˜4÷¢‘4OAŸç{çßó>àüâ¤Z9C>aaQRѽbÄ',,J*ºWŒø„­%Á_¿¿®©rp‚¢¤Z9Cî^@QÒCnŸ° (©RxOXP”TŒ¸Ý4-Pùã5Yb6£î¦ÁÒ~Ψ»ið†«;€‰øF Oî©@ O)òœ±ÈÓ»–È#%9b$ÛO8º2b$÷< Þ³ö„Û>0Õî°cjðôDÊ5=•aͱ9ûŒšž‡Ð1Ï«žCàzªç@Ö›œekùì’ó‚àÙ$Iž ˜< ’$OLžɶ)¤ XJ¤w¾/_kä•®Éï=â2µ!3Vc¢i±y‚ýÀ·Ç‚ÏnYa3óÆ÷Þv&?9¸†÷›TyÁóÞoVNÏ©1Ñ[ \«5ô–-)_úL1©®ë>ÃéÏG¤$ä^9êY‘­°ç.ŽHIž°15³"%'÷Ê©™ˆ$%åI º"+JT0_´ì"’®v‰©„©Ùj—”JˆÈj*a„©„ˆTd ˽øuMU¦¤TBDSm@*!"-QD’S YM%Œ0•‘¾ñºrE2ÂP%‘õ´¤+#²ª™!]‘õ´¤+#²ž–‚teDZ²Óø%ï8¾äá|wjâôtGCbV¤ç{’G[·"y'Ô©Ntl¥ä{ÞÅ@Í^©jÌú±ˆTTUcJqF¤¦”ü)•°"™vë—R3+Rò¥ÙÑc‰H2œâ÷©XMZŠß#R’i¾)¿OÍhþo‘ŒUL«NÞ*ö×;BJЉ‚oÞRÊ=<ƒ`E:Úc^zDJª|&yª+’?Ï01‘tiÛ”NØÒ¶T’‘’*Cû›í§{°àqG©k FØ=Zu²#'‰Œ°{tD’ÏÞ§Œœ»‡ïS Z¤S3+RòÞZŒ7W¤âê\2{‘’`Nr̵"u«³!FÅz}fNV¤iÔü&/HVv‡¤§TŒóHIÉ¢ÀÞ„ªÚÇ.[™cY‘¾Å±ÌIõ Cß=ðV1wÕq§aæ½#’ÜõÙÂ)ø!±¤qEJ>‚Ž­T#R’¹‰%=»bV2,iŒH**όĊԭNI­:èÏ+ÓªV»"¤$9Õ¼B”å¢ò ~MËFå)â[‘Žã]ó «™¹›ï·Ü_|E6¦&g÷¼RwÌÈ@fÙfÈFd5Ë6C0"©Ô½¿®)¥nâ#’(µY¶ˆ¬fÙFÈF¤#4µ™ŒH_eî€5R-Â<šÞôÉÖéŽf$´>鉮O8qâ!³ º@¬HÙêqEHIeBS¥ÃŠäPØ‘”èîwÝ Ow„¤J×snbEš†”¥¿"¤¤J€¢ÉÓpG?D[&«Þ£÷阬zÞ']|7Ãæf+Ò³ÌsÊ#D¤¤<Õ!{•ÿ®l9R]ÙþhÖã}?;bŸO¨öP˜jã†r›Šóõ—IÊLJ™êp¿­€„2×`"?âJB*öì°;cInÛW×X¬P}Ųý)T_é7ζâ3Bó’U¢rä Ö VñkoL©MHÍ©<Ð~Ó²Q£ë·X R É-Ë'¾2V‹p´´<ëc¦+@k¤õ<^3X[Y3äwÓZam3BÕ}A:I_w¦ÖIµJ`æ,H_Y¥çuõÒýÄsH±Û 'w‚ªÄðÜYGõµ¶†«¯®Z}í R±k󮕸xfp­˜¿„®Èñ¢•w¤÷Ú¹ãÜü‰Ÿ‘35£¼;Aòì)˜“ÙShNvòî ÕÁœ“„¸¦êxå@ë`Ž×QN´æñ@1ÀÝ { ,Hϸ%l–Dœo­Å¶îw{‚,ÅŽNH!ø„´e/{œŽìé1=®Û%©„ \¶îpéÙ#­;Sä!õ-†àžš’×÷Ü÷·‚Û÷97CUÑ܇àf¨~Á]¡(7CÍsî E!¸jŸCpÇÕ‡Bp3Ô±ÉB°9Ǥ´ç6'þ€¹XiÃíŠb{Md¾ÛÛh"ó|ál¦EC‰¾F‹†˜¾VÐà¢!¦¯ô0¨hˆèk%òZ T³™n*<¿Qha×ó•vyªÙÞš‚ò·—ôZ¤ü Í ¤´Lp\–ûÔmÏm?¼¤ ePÞÐ|/£±ä¥‚>ÞvzÙ(pºäiѨ•ü:Ý£8çÅâ;Ú*)õ‹lò¸mÒЖ& º¥á)\ÔWzA*ùŠà3ï{²|“Ð B ÝL!‚n&‰cra¶AwÉJ›4r—ÄÅ:¤“-HÇÛ¯ëZ%®¨Ñº®Uâ~í‹[ÕÖ »Aò„¼¢n•)7tLaoHö›­ö†d¿Ù*-|È\§Œ¸‡E3­VÔt¦UV¢‘;_L©8*$¾K^(ýwä. ­):ª ß%x‹UvåhÛª(íÊG|?ã“vLNŸ=¬.4¦1MN/«Éé@§6<ÄÃÎSþÆ!³°R!²{œÎNìPJØ8ü_ßûŽ³Û½ÉS#¼Efa¥4ɘ¤òÜ`Æ++­jb-Šää|ýÝyÍ;t¬ºéÇ"¹¯6þÂV\¨²ð/!9Ù j0·ºÚ`ž’¯YÁ\§X³Bsv|•ƒTNZíb®œ´ÚËMkx‹u›Öè-ÖAœm`Ùê(¯¡ÉÚjžà8]d«y‚ã@v‘-&©èh½„Èç8É~M=]F}B¶Òá íØÖ(‘œ„Ï®ÅfZ #7a„+µöñ1V Wb‚xkœX5ÂH/W`ýi¤õY×™ PÛ¸åi +¯ÁxZÉ8ØZ©Âƒ‰ƒ-Ok8zyž·­õ ;)«Ä}K–­+®sÞ•ÛZC4%kdbÌuÖŠÄ4×Y+ÇfDkï£G×KbkëàP$ÛmAûMÄú<ÚoZ–®zê´6 ²‹tM­ª9$G’Æ+Ç fú…uUÃLŠ#è ™ÁUêÞð=rrÝ}œaßâ™îœ•¾›xä¬P%&oœsò˜‡9™7ÝXG2ž“QËü„¼F&@¼ñ‚ ¢ÛxvZQÜ¡¹Î7ÂüIö2^¬×¡JiëÛZ¥ôFÜî 7½âç:ºCñòÞ%Ò7,ÍÉù~úÊøD÷Sú“o‡ç¿ÅÝ™z'îôÑç½d̽öLó1ƒ¼J喝õ'þ4~{C¦Ô:ŒùCÝÀ$¨Û¹­¬îÝýëþE*!÷õGòæûs¯ô˜ûZq·H~݈'»AÆßée"H“ÄoÈöv{ìŠy‚´ìšÆRh¥÷¯m‚èÿõ1£cªJôH~;ˆD)zätÌâvž_.]–÷HÃÆ„Êõ7 ”÷®ƒQ‡ú›E$|eP×ò)Á”&ÛàXÁROH“­”ŠJHü-êE–Iüpv/Õ¬ðVîZ®¯Ç@\×Ï A\]àY16b-ÍŠ±Ö6¸{ÕJF t•¸¢Fó|ÔbŸÝˆ_.|L+_;ÌÞÑIgdz7X¬“ÈšÖ,ÑïÝJ‘ø|ÍÇô•]d~ãbë`øŠ¢¸¶»¤šFrröö‚l™/B·™æ¯ò?‚TY<üöú’wЫFIž¡¨ ®jÔm¾®Ùp$!·ãƒQ§#î7ñ]²âj Ó‰ßwxFªç.{q.Hœ—üïNÄ\½Ð?–Oöp龦!##[5ß/÷¿#E–­²úmžŸRH“k|éeõÑ&Èý»¹"—ç~ØëÓÐÏþ¼S¤Ý‘ÿlÈn! rœ¯—+A:ŠüèòóqùE;óŸõŠÞ^÷Úï÷ý²¼HïzöˆùÏ¿OÈÏ32–(›k:Ëm:!w"æÿýïÿÒ Ïÿñqºøƒˆ¹Ì küÛÛ67¼ÎãŸ×îñç›ÞûV%zçÆÙ¼&Îæ÷Ïðçq‚nDÌeª_~ÀrÔÜÚ} ïÓ¼!ˆ˜ÿù‡æaý\îÝ{.‚&¨-bM—ûJé>=‡¡×Û»@o/îçßꟙ ÛQïÏG |q µnOOËàÇô…²ŸÍuðßR‰Ë64E´â‡ ¿ø­©L¹pEVžrCOŠ_Œå‰´u•)7iÔ-N¹Y¡ªPK´ì»—§Ç–W?.ËËõ!õÉw«…j£ä»:Z©†\Ê~–uh~E”ìu‡ÉYµò1á.©VL^§ ¥—ÖsçÅ­RÔqŸý¶üÒÕéˆ YGP&+Ôè<·œfBÞS8 ìDT)Þ+m£MÂøTb¤ÇúiÊwéy|¦Šþññùùk˜ R1î߯ËÜDäcw=æÛò,¿o_¿Ò”·¨s7ͧ³[ŠüH–ô7š;vm´ýãï+H¾lT¼…nô˜¿óù}G­Û³GÞŒ=òd”£ˆa$ó™LǨËgGMÉâ¨ËD¥[9âæO­ä%V&Þ(­Ÿ(Í@C}ý³6-HP«ñ¬"î‡;¢<)mY﹕ò4¡ßi+s]þi'‚ÂJ¡¶àSÖé•qhåï„ò!)PŸœï–÷DŠWÎTFHž—œ•G¬mœ(±AÅ@åd7Rhö)Ôj<çÍÏÛ-íòURNáí@ Äñû‚v(žß•÷/dW.ˆW©Ú{Å8Êu'ŸM%9ׯ±èwêÊÙiä³g?;å¸ãCkooå8íK—é*c>¹¼—Ç|ná)þŠÕÇ1«•rø4Ì`>ÊÝðv„F¬Æ oq !:X‘>Eº:µÆ°"} Št…[c'EúLé µÆÎŠôž(Òj1Štú;‹Šôž(Ò¤¤H§¿SP¤Ÿ¼"½éÙ%E:=¦¨H?A9EúŠô-*Ò{¢HOТ"½'Šô-*Ò{¢HOТ"½'Šôul†'L£rgt„žŸâ;£ë² o;ƒ¸©À[îÀ•WvÙ¨[™FóÔŒ»­§Ã@·ÇÁ³Š nƒ·Çhaj°<òzÎã˜ùì¨3ZîIç+Š­há‰JlQÉwCQ‰!¨ ¹FwRÒªh$F&2´V‘·nè‡6ZQwŠ>ŸÑUÎWäå³Ã‡6rö{ۨÛŠX±ßƒÍOõ x##»‘îéFÛ¨g†4BtÓˆ\.X éFô€@EÝ(ùwæQ§)ˆlB[ÝHAdÛRt HU¶˜Åì ݘ»âNÜ1Q¡\7V°­Å,ÝXqû‹6z½g½ñ@Nºñr’d.ðé&È!l¸óQ,­ÂÒV·R\ç°tEm+§S>©äLéüvè–×{ dë¥%›êM”ŸQkøù“p4R*>±' ›_·•8¸ó¨…–³¸ûž,Cu[úÆ¥’åëeøÌoGË#­ªñ2Þô˜¬ÊÜ $QíÇ»Ûrú[É­Vå­Â|¹t‰¥t ]yqùkY\ô˜~_Ò&óûeµÀ›éµ‡¢ÛP÷õƒÇ#=!×îȹ/Cÿ];cËïL§Ë4×í´Ý—vÿP³¡ñöòòtTÅwàæÑS>²ºò`~À-¢©,´j*¯gžT+¿žy—¨U+'äÀĨTe¤®Lwð;œVŸ$U H‡;_í5Âý¬ô§üŒª½Æï‰ 5ÛÃËËz¨¾#טÙGžpT*àŸ#uH~Y …ÉvGj6è5ï{¤)¦êÝpm÷@Z¦ª~Þtüs‡Rû æ³kaIß¿àeé+ùÜ_(’Ï&‚†V¢ilÐ4/•ì²AÓH*y®ñ-wéU`­Ó~gíƒwÉU®(/´—¯– ‚£v?õä ›¾e E³¢–dc¸Â¨Q§óüAœÉÆGëX9fþ¦‘™·3õDK×áú$AN3A²¬ô¾;Ùþ½NìÐàu3•w®ÈVÞ¸<ƒ¹Jº/ºó•Ä!ønB¿më5^6"r·mÍ>~?ÆÇø+_{”Ól`ÔyÙÀ}DóPrE¼}çÉR‹â:2ƒy#vÑZ‘í‰.0–Poìy´†}&žŠö¾rL8»l…€ïg”„7ô= ÏëíÈ{9ÿfÅÐVÞ£|—‚ °ÀŸÓО8÷Â_h/\Sy7ós•ü=„tüZ‘®‚“S8Ð]òr²Ì´!Ⱦø0/…X‘·edl*oG~ÃGÚÖQÕÚéÚqƒ í"¯™Guç$AÔØHñ@vGs_½ádæfí{Ã.±¸ÃOG©Iïv;û2Í ùׯ\ÔæÉw|j®Èqþþîir¯om;ÓeZü“Çg„ÌÉCBó~í€möò“wÐ2'3òc7ǹ­%ú¯Ÿ IÑ„ûy{yéè1#kKt9!·²U®^·ä›MÁsYå¯Ú’„8êu˜ÆÓóT õgYÒ?NPÍZ}žS»×ÿ³)j¯ï›.©Û–v}ÿ>S(gcôX®ëuü‘_æhå XÑ 1(ä£K2IÿRG/EK£þ¥Ž^ôòASI rà|ê$¿O²ý0MÃwdca«°l9ï™¶`šVöŸFÇT•ÏgÏw’ž7½¨?d#‰ np?McäX™üNË-Ö+àSg'‡ï<àÎû ò‘‘²³,›L+°|ö¶©Œ¥|—ø®Ï±O³U²ÿt~ îúœ(ÃÃÓMk¤7-Mkk´îž ùØ£ŽéøQ÷2!A’i}eAw)°á&ý^¿%dÉá# ¿/oo_Éùüþuÿê òûþ‘¶ÜïýÏ A|~OóÛØÝÛAZ@¦Ê÷2{wîñöM[è?ÿþßA%{ßé“ßÃKïQ ÁmT<´~é¾ÿvãKóª‘Ó`Q­œ ϵ(ŽÞíÎ<Úî|z·Fi9˜Æ’2•99¿ÊV´¿i!h”“}Çá}W^Η@¿SŸ/Ë*4ß%Üšú—„Å,céïýúB‘êy„¼þ,#dLŸ¯©ù¹._»®$fÀ¼¤[Ù•fZ]ñï‡û©ue®Ë£N›Ê3‚³[ÙÇ]‘“]{ó*Èh_9f~îZnIÂÆÏà@É“j \"c9¢æOÓÊž¬ðí05ÙV¢ŸSØÒ±ymŒåöŒAeågeüÚË_XcØÆØ´5Æ:Š,6Ʀ­1v:&Kµý,.”çµ1Ö%Çt¼4î’•¥!$P0ÆÊž¬0>ÅB9nÇã+H8fm|2Êε0–„BùL FṲ́im¬\CoœÕ¢·4]ÌIÂBKÕ+‡,•„Œ5b©Í!ÖVÞ¸<ƒ¡BùÓþp-à f½TÐ_‰TYääõW\¦7¬„e“~"ŽŽ±Qö’„wÓ5r2<#ײNB‘¬§*’µüÆ9%ûSÂýãíÈ{ä*þÓðv8[y;òswrü7ú:/]ûû f0^D²;×¢cÆ 2ß%);‹~a}[!yÔy%¤‘õ§×r¶\–†Ð‘¼¼›d×ã­ì° OÓ;âþ²}¹¶*ËæTÜ_ŒçØf+òã2¼æ±ä½ìþò8!u‰ƒ»2ÃÆìêw M‰ïõsé`*r wO‘þý÷åíå=73>ïïŽ^‘Ã̬ä2Œ÷;И¤Çô|ŒìÏÈÀßy¸vhÏ”<œºÏ×|E¢ê¾e‹]žs0ÖÅ UY¶E*DCüÖ Fªô8d©"´ W„,òJ;LMŠ/oN›E~^ €Îçlrä ”^ÒþèKž>@uLPÅ™úܦóÐÏ®>Ýáêsºª6W÷7WŸ×óº|“_—g?”Íeó ²ÜÕ?ˇéÏê&u‚º’WÐ2OÝo—îô<ö :Fʽ»Ì÷é鲊ëöm5ÞjŸ½‚V#òÕ+è<ú›²gùêÔÑG Úg¯ õ¬Dëñ-g޼` «à%€³M-1ž-e›Â­²L¶iwÊ6=B¶)üNËe›v7’mz Ë;[’mz ¿x…i‚—€ÌDkµÔ-{|üú€·Už÷a)’·…±¼ø{#Dß(Ò°bО¦hËŒx±‰V‹•8¦iäÊ ¼ UÑj!¼hu3!ѪE¢Õb_ ޣ侼H´ú\C$ÛZ£%›VÄŠ°Æšé#Ú /°pG\œc‘ýv©­æû4_n©h5çzð#?‡_?‚ÔçºOB~þŒÒÐeA>û€–¤Æ¢„ŽÿÛ¤iûG´¿½ý}¼/+zöü¹ýµ#¯Øãw?þ¦WäÓGô»uû1_ï??Ÿ3A†ôaZ‘W„†2î_õ¶dl7i ȸýy»Ÿî|Ë·÷··ãk÷ñÖß~Ý¿éÅ'cºÅú–L@ßú¯[÷ñ›B^×'¿½ ÷×Ï¡¦ÏÓQ·Ïí²2X¯ÿ˜G–«ºOߟӃީØ.ºñÓ½Î'¨-WäIñÅð¾53­Þ·f¦õASõ­¹¤ä[3dÑ·f¢õAÃûÖÌ´>hj¾5=¦à[s§×^ô­éi}ÐT}kèï}kè}kNGeã¹_ÐO­ÿ=fŠTÅ­¦™(W@`AfV±=­´(vËѺHmim[‰ŽÊKWÛò” ¢µˆøäsN—mˆøô¹¡í+U<\ñ´•ŠgŸŸ¦µÒGO­uR1^QR”¾¢D‡m ÅÓ.÷À¤b«—9â@28œ²| —Ô®ásâû-KuR•I ¸ûèU#ÌQd‘07“îã”sw‚,æ&Ò}<åJé>HÇ&\tpL-j–m E²Ù´`fãXbwâ86À+Ia|ÚŠÆ’eóÂg’î'¬\q^ø”òÂ)R3N(/ü@Ƙ™F¸ÆË)œÝ³†—›áPVù¸&0‰6+òãóóüÎPJ´ÉÖD]^9HR{ÏkätLC‘©.6<¦Û@§ÅÕ®ìñÛu¿Ç—¯_é(2UÐÞþtÓ4$W{û{¿Ð³Ö”ô#D ”| Š¹ÃrÒÂø¼e½kŸµ;]Ò« ãÜ_þþ&HUò îÊÉ4rwWÞ îÊÉ4‹–i¹‰ëL³h™–»DdšOÃæFp¡HÏ çëõtEµaû9ýÎÈÚ Ã[ŒdšË¤üÏÞ÷K…Æ×÷ÚÑÛ´·è²sA—T…cÿõB¯iÿÄc“ƒe^\¡·Ÿ—Ûéè’ËÁ¼ºLÓ jJ.Óærð8A-?;êxêPžp…ÔÀžP‡\ÛŠ “_¹aâZ%4L–©ùm¤H–Í©ùæFžžZ1ÀùsºV3ªî$Wt(Ýðì8:¯Ê\HsØ÷äø4N„k­@°Âœ×ÚšãÓ 5§¹NÄŸ`4Ûšã=fÑñi"œˆYt|š'â@¡U•‘ŽmUõ¤Uu …Æ8 ½ÔþBqײ’ÒåÃq ŽÜfônF6Cw«ïïY.Î]q¨Sê3äùF‰$M¼dTܲþ±·|3%Á)ݳÉió˜GBfº´}œä´R …óŒÔlá¼'…óYøÌïNhªŒàDA–¡ÊT–¡y^R†™ë» ,C•õ%P”uÊJ~¼¨tí_èID“SÕˆ¦ArroüñF"îg9::%úà‘k"1yD÷·éž-¹ð|¦;‰Ñrº©ÅhQ¤*º©I¾Ó-˼›éWF+A @¾25u0lzµb™w3ýÊ up™y—¿›HÌ0ï(²È¼ëéW©ƒÏÌ»ž~e@\ŠêAMWÇÆ:®HÜtuZó¹æË?M#‡  ¦äËú3§-cqvxéÀFE;f£²UñFE;f£Òfh0B³QÙ‰6*Ú1•ÃÉ6*Úq•ÝÉVAÚ1•î°M»P¤gx£¢·QÙÝ~N¿Sبtôì¥ÊrzºQ9 …ʶ •Zبt‡[^ÚÐÂFå±Û±ÁF倖6*ËšlT¨å¿_ç£J• õR¼9Þ¨hÏÖ©8Ô±âÐî$uUqh^²âÐÇIê8´Ìƒ‚+Š2ê74Ê<¨)/Å4RùE0 #¿È¸OøC+ NWéü4M%·ð’Ÿ‘‘s ѵ#Ái‘³×nÚ g)Oަ•Xxáb”ƒÇ§QBoK®ÎÇÔµäêAJÉÕ)%Wӳޓ|G×ndNòØS¤Ð'É›Ic%Ûhr?­¸x ßéXFÊ@7üÆñ|­qDŒ)gÒV6½›¶‘¶Çx+k›Jzs¾óV*‘M…­müàw*¶§1ÓŸ}–6¼ïê§q>nãï¿ ©¥Ð”x’øçf!@÷ñçÏíåNš‰Wù¸Í'¤)o“~Ö)„žÝB¦h õY¶ÕÝ ]!²eXãß!²å@úŒ|MÇ|LS· ºñÏA@B Ìc¾ ;Ëy°\–÷}g¹|d›’ÌKw¾êÊõí}·—»?.÷§KÂ,—Õ%d;ÿ2-½ö—'¨‚}Åûû!¸_¾ïÝãÞüÄr9B6èø2þýü·…ÝÊ[†.ãsåd¿~R¨EÆCoëÐ_¡?/÷þv:ªÃEËïÜ¡Ÿ/ÃÏp|É'åèMd‡ñr¹g½i‚ ŠX˜ï@w™î÷ÏóàºsŽè×ýqOPiô7Úå£þºßã º?­³13æùõóB¡ A»î}[‘®~t·Ëô›^–ÚŸÖüßB’Žz¹¯²ìŽB·§õóÏ ]äûe-7`¾gß­µŒ¹â:kØPš­ð“=¹µ•"w^ÁX™9‡JÖÊEîL¢8†KMEŹSŽ6U˜âœ˜£ý wÉKìÛ—Û=qm¨ðtáw–µsjóöiƒOÅøÕtOóË/DŽl? Ó5UU.iH‰ÛDï¤ÄmÚIw­¸­ï2—Ú¹Š¿#”®ca@‘•ZÐZqFL4F£ÎY6g"‘8ÎY)m±ZsbÈd‡®]Š-Â<]缆‰¹+ŽõV8å>;WÉ)ÒÑÀœ“lŒ±Û,ÓÀV†0=\äüÛÆø·HÁ¿ítvËÅD€Ût¼×Ú|#HϹ¢uÙï@ÎmÈ–X2òžh3ýi]Rr/;ݦd(³»—íÎúMê{p/KPÅ»—Ó¾.¡îekPv/KPSΔÀîe jy÷²îtYŽ'òç;@$}O}RDäw¾‘Eu°„ómET—7‚¾­ˆêòÇÆ·QÝé˜Å¡?ßüIö­,ª{dbŠÇ†¥O†¸ì„Ó‹Nžd-;yUó$£H͘[ಓúã[ß®]‹BÔ7ñ"½ ×Ͻá{…”è ù^'GìËå<ë˵N¸È—ë@|¹¶j3òå:_® ¾\²$ZÏŽ|¹¤å=´^{‚t¼‡Ö éyc¬7z—ovõ›"#ïuï»}v@Ý/i‹»A^W ÊeJ`ÊœwʼIŽíÓ´Oë%A8éÓVòµÆfÏ–zÚ§EÒG†œÏ¤\öB’² ®H¢cAøäíà=Ïô¶}Ôo´[üΑ„«°´lA~÷óëÇHç·3¿IZS§ïÌqÌÛüûû ™ñ: §cZvÔÿÊ£.€÷ÇüV,Èixûòû5u!¿}g‚’sÑaÔ%õÒ‘ðÒU„—lè‚%p¨gÅF<=Nùí.¦ sX}Ca4pž§]2²h µ{žÂø´¢dŠÒ°VßýƒÓ2¾ŸËZ oÌß%Ùç˜Óçoµ±Ð€•h®:,Ñt!H™‡x›"/!¦[Ô ¸Ž¾&›´Ì6øŠb+å·c®GT•‚üvDžÓ7ÓÔºuŸÑÈtë)—e¢‘éÖЬŠFj¿½ý…J4l©g½Ÿˆ/-¿E%rt-#´~Á—|ö; ¯˜ºévùýIªA°näÃOG© ËŠ‰ð¢{Z[í<‚Ix±vdj¥/oñJ&Îü»ˆØ4Ö`s°}ùÉ%¾ˆØ ¹ùmÈiþú2< <Ž„Ž3²NЗòp" ›6w•*×ȾÓx‚*–žìˆÙ%7è¯Ós:Ø$a#ô}ÿ>S¨åäý êÊRNR‹^”rN𱉞­rδÊ…Hëödr1rÕ®e jWŒ5äñYòMà ÒóM#-gúoÚšàõF‚Î!Ý%õWEõBºK믊š„ŽSóš„ô4=Ò_•5 iˆz¤¿*kN¿Óñš„ÓïôlžÈx:{1!q AFV;0Oôw–wíÀx‚¶¬vàq>ªb,”PAÖ#ùY©Ð 6™¾1rví' QS±Éìè1ÙìZ°É<†·´œé1¹Œ’![™HÇ»OÎôŠ»¶;=¥VØ|vù •xxóé+-ÈzØùƱ݅Û6ßÞîÉ“„Ñò"á´”^Òé­  üNÙù’—ìþ¤Ó#LŸñ÷ß·ë}&H}f9†ñ÷ôÒ¤!\†¤©{¼~._åAžeÞÇ’}~}ûz¥Ç,ú-­å»éz»dÑoiC¿~d`ÎÛÅ7±âÖ¸‰‰ ù¥ŒOÕ°2ÆÍv$³1$+cì3Õü@ZvÉ”wˆÒB>×”×ÓÙ}!Äa=&29¡ÈYY“p?[ÞáŒHùü)ëóô•Aܯ4[wÁ+-ùn &¦Ç·SÉa&ML_¾e §„oibz$|cš˜ù~ZQôML¯,×ü8q~½r¢ Ƚò•h#xF^â‘§x®i¡zxFá½yÅ»N®-"ôÝÔ #JíN¢T¯‰÷†¿Gº­xE)„_åQWŒÅÄáWpEŠãëìi_ùݬæ-æù“Í[\ÓuW¾NóÕ¼Å<jÙ ´¾–·˜åêžÍ[ï4AÂËy‹á÷ç@…¼Åõ˜ØÏWóOW$å-ž¡|Þbæ³ùzÞâù¨…¼Åíª]Ÿ—òÇÇMøZÞâãóõ4öŠy‹kÏ*Ǿž·x¾¬ÀÄMü ==oñ<ú…¼ÅÓQËy‹S÷uŸÏ—¥¤.e†ò]Êt)½6¢2Ì?=VT>£/ ôðÚŠ“* j'[ã¢WºVÈ€ Å‹ TÈÀB¹³ÞxeÀ¡+ ²I)úAêâÍ<µ©Á3éAyÓ0=¨Í}õ ¼i¸ÔÊA=¨YêATËz K=¨‘jYd©ÕM¤u K=¨á=¨YêA­HÔƒ:¡Â=“ÔŒl´Óå„”zPyØ™†ëAmGE=¨zPzQÅÔïôuzN¥ÔV9G=¨µ<[®?A³ÊF] R*Ò•&îySs†‹RüDFwÿDUø¤?Äk=)s÷ÅÊÇ4Bíì霱ø7¶â ÃÄI­|\M1üä8Ϙëî¯pÝáù½*ß%‰²E*܆WoÖèwFÙÙïgâ1èâm#ûqà *äóÍ„Îé-oý2нR*sˆÆà‰𬛠; «D›Ô¥´šéR&ë‚ü[ÍTO“!AG©yC‚<>‘°lHßwP2†§ßéxC‚Óﺔ§cº”É9ž¦fº”‡qt)‘1OЖ5xœJ7m‡YÿÊ| I¬èmÁ !ÇÛ¥#È'÷—Æ~Ù7åm“5Ä,qŸFöæÆºÁºO¿(Ò< 5·}ËØÒ2Èå=~û HWDÞîñ‡";8I*÷@ß]8$ïd,!+òÑ]èoˆrâš•Ó/è=Zó,²H;†õ¨ÏPáÑ?ò°•GŸdÖŠþqy¿$ÿ诹ílmåÑ'Ýåý÷‚}"¾HáÑA ~¤÷Sxô§ûÉ>ú댞§•ýt¿>A™SG>"Ž/yÒöŽu¬Î` :oYo÷n"œçYÔ Dgp ‹:ƒè dQg0vô”tôwJ:zí’Π'HIg@‘’ÎàNï|QgÐA‚²ñR”›mmU@#°•…ìèm¬x冄[Ôk˜^º÷®‘'´¨]#µq£Ôµ¾yõ®åËâtcá[!ÙM‘©Ù˜¶˜"{§Q2ÙX8Ã:^ ÄñÊ;Ë:^ÍÄñÊ;Ë:^Í´Jà,ëx5Ó*³¬ãÕ@¯¤e£ ¡Iì,ëx5Ç«é$r¼:;ü9ýNÉñj¢w¾èx5Ç«-:^ÍÄñ*A‹ŽW3q¼JТãÕ@¯´èxÕÇ«µ¼è|T'$Bå›%w™h‚ðrÖ(ž¯Ð— ¼ÁẄ½ª«°r8{¥+h¯ê±{"ï›Ã+Ý%ߊŒZTõ-_Í }3,å<åf D”á½–'G¸ó^°\©mð:y#ïýá¹{+'¼B¯ ‘Üm5Ö±„SмwÏ{ê,×Â)hžÈô’\k÷-_ŽÙ?Þ_ RO–k=ú¯+\‘„]ë<œÎnK¾v/TÛH½K Î/w\qB‚¾'ëèÕ}ÈÒi'ʹ f$tÚÐÔè´Aêrõ’ÐiCS£ÓR$O§¾^hjtZŠ”è´)Ñié]’è´Y¦Óö”NžNÛS:mh [Zl‘Û|h+Lê<ðB[ lËShhe&uló ¦dÂÕò2©)ËLêŽ"Ÿƒv:»çËFŠ |^ÙD¯=òqez?%&õéô“úô”ZAæžç± *2÷‘"/IÏËÁ *Ñb¯ô˜†{½¤åýÞ‚t|b×oŠô|`WGÏø¼.ö ´(0ç%h–ó2ÓŠ4I0ýw¿ó[j«8`Ì샑“ÿvÉ™»_ÐW>1yq=2Aæ ¸Õ®>µ?§åÆÿùóÞdŠ[‘ûfiEŽóãõr%HG‘]B~>.¿’O^¼wôwòÉ‹g$—¼øv›NÈ”¼øÉ«?_üÇÇéâ“'Ý)Nñϧ8S¨J³­x}ÿ ÆTcK¸·½Î¾yxŸ~n'¨— ïËœ6.Ë2TŽåëpQ|òâŸûù·òÉ‹OG )}°RÂð•ƒç}pbÄòe„Wï9<{ã÷²|û"Èsø±Àþóý:}Ñc–#ÀG"¡(|ΡHÇ1_ºûðóC™|Gî¡H"¡BøØ~ —‰ ãð@î¼-Ñx%Ö|vxà©©;Ýï×e<$™ RóÔïÛ×/‚4ÏqTëïÄqTÒ>ÇQmÁ(Žê@žC¦Žßùñwýܤgìà¨âsç·=ÞP‡(Yá]ç9¯ˆbsþÐgËmc±äŽYlž?ôÇLvˆ/é1u‰qrÛ'¹D1ß…òHv-óH‘–ux¸œî™F²mXVÉ }‰E²+™;zíI`@y—2²_§»tÔ§N’e—|ïû÷B™0Ãþ±ìOPŘºàzBl {j! ¨*¼û¼JÞ ¥dÞýØÓcò¼ûây ù<`xA¢’x÷(™ó@x÷Û11ï>*DŠ*ÙÔÀÕB5ƒ¬™‘qDÙRæ„Ôûªu[]ÓUë Ï(3Ê«Ö{G§eœ?±z&òIŽ3UÏœl+°zf¦ê™hXõLOÕ3ȶ⬞™©z&V=3SõL4¬zf ê™hXõÌ@Õ3Ѱʌ™¸‰úh%R)y‹Ä›ÂŸã(¥öF ¬ÏøA*ÍHNåóH¤Ò ™:'^6„¦a>^É0¤ËÈ–ûx6 éì¡i¹×aò ÇÔ¼eGúHÃqŒiy#ŽÓï,~¼zâÃq =oÃÑѳ–“ÓŽyŽÓ]*}¼éãEÊ0mö× *°™á¨ ›¹’ó†úøõýÈ7 MËǧ÷œÔ-g ¢Á,D lQ¼©ï{ ‹¾móOÔÈ é˃"‹÷s&/rbsgò"A:¿ÆiÜ3;<4Žßy­7*3¹ƒ\»Y w€¬Œp—øÔ¬¾¿"q[Üí6³å­›ô¹‰ ËÝñ dCË¥t©¡6$÷vàQ×*±¼¶À¡ÕRyÙ‡V‹éð]q9E[àžØHÉøF–md[à)Ù÷)ØŸ¼-pßÑß)ÙÓcжÀ'(g <€-p‚J¶ÀôF•m{b œ ¦Ü_À¶À *ÙŸŽº?ªÏ·Ÿkÿ'¨Ý ÈyèÃUå)ï(½åë½|÷3LŽm^_®Ÿo‚ü¸|ÿúé©… æ²`þwÍÊØ¯¾¿]†×ŸÏétL[FŽ×em=$-‹A­ë×u<“TÅ Ö6Lxœ båÿý»sær¢ÁÇŸ¿¯ŸùÖçé>‡/@öÁrÌ¿¿/©hLCJt¸ß¿—ýAêrÛSu——ûøÚÿ%È£Ðøoâ%ìÈ·ùö÷ïíƒ -Ä9ì±+ÝAðz¼MAn÷sY»lÈmzXoŸÃ[ÿé12óíó¥ÿXVØù¾eI¬ÈËß{÷ògx%ÈÈêài ÎòwœZÏØžv'ÛÓÐÆö´;Ùž†60¶§ÝÉö4 ïj{ÚlOò.xæ‘cÛÓÞŒí)|BÅöôtLÏ;äÀ1£ì3ÎÉ;äÌ÷ž 5ïfó{"HÃ/›ò ¦‰€wJH¿_ÈnÂË;¥$Ý9¦Çg—HVå9C©Ð”­p†àwÚŠ_üN'ûudûË œìב³Ú¤àבgoå*9uð;}%§./C‰*ŸòÂûÇž¼˜¡1…9’( ­}1Ä–õHkÏ*3²e •=!TÝŠÌ´Ö“.— ºø4–º\Öš5ˆè3hÃDô´aG{"údÑxt ¢Ïg$úLw^2¥§o9$úLPÉxt¦Ð¢ñèDDŸ Z4ˆè3A-ï.ÒŸ Ž™ò}XÐVÎ>ÏчU…§ìÞ<5#UøózA¾ÈAûJš;ÜS/úd“‹€CQŸj3¯ÈÐ'`­÷ÙäbÙ}ŽY P(jѺM%áÉ{?æ2+®Ax°£ÕEÓ:d4ÓßéÊ{ÊeUŸ !¤/µ5Þ‰Ð,ú& Ý×DKȹìN‡ÒoŠvJж`=t§ÖC ª˜ZãˆJ:V¢'${Lô@MSQ²vY¢ÝÉs*˜– 5§žSÁ´Ï©üÒáLØ'_ì9 ¶jÞg¦ä<§ô˜¼çTΈ<‚çÔé˜)àM·ì׌œŽ±óf0ZžîÐ]Ò’KæªÊÎWħÇn‘0Ý4$3sEEVcù•(qÞ (=ödî~rÞ<çÍÇÉyó@–œ7Ç8oÈ‚ófwrÞr÷ž"÷én7‡}íò1ÇîwÖTdoPxF«¢i HwZФ"ÎÛßÛ…sŸîþ‡éÛÔôùûåë oÛÏÝTlûòÇËšŠ!Œ[1¤ƒÂ¥s$g$8¦c™bm¶•sÉïèA©yo¢\š±ŽeŠÍ´ÙnËh³ÝºJ³î¼c™bm¶[Wi¶ŸŽy·¡Ó]*3ÅfÚl·N0ß§ÍvëÄf;òø HŒ^Ö~噙Ȝiòû@´_Á)I‚LŒ²V xjÁÕ´Jù›èšš`åF¼V ¾t®© VèÙ­RGÏ. Vè1%Á EJ‚zE’`…"%­Òx‚ Z¥ÓSjÙA"ÎàÚ‚";+ä9ܩгÂH‘ŠwAÈ W•¶Ì)I[(R’¶Ðß)I[(R’¶Ð³KÒzí‘ÍñƒuK%&DÆÇD?KHתyOÅð˜-D=Û2W Qÿè(’Á ¶ŠCÔ—Ù6—Y‘¿Xo·sù,\‘“ #0;/;Ed³£àüÓýì’9Íûø0ž+)p»ç¦ã^àÞ‰ Ü.›«SlÏøHÃÅö °Âqã¹b‚Yãùûù6ÿœÎî™Æþtº€l®° ÁröuwžMd|ö X ’ßý}þ¢W”œ °Á½ýšoôô‡³Á?ÛùsnÏj;Ì0ßv=p„¦ÂÀ‹KÜÓâUøû1áUòME‰ž? ’ &%k/‡þ¡íWR×e·/]öPåóZ8í^zX ~êç}döÀå2e$®5ýK=kóž»5¾ä2…Ž9N©2ã]å˜Éü" m}ÁÈe™êó°Ç¸ÅGxF¡b¥w>²¾z3ÝVøÈúê ÄWï@jÞöÆgdY3ñÕ;–·=9ýNÇÛžœ~§ä«w#È¢¯ÞL|õddíI²¯^ºó oO2ž -kOò8U ¤I—O€‹47‚”i‚”iè1¥@zL)æNR Eú²öÒ„À?Ì$ø!„VJ½~¿Áj$HÒŸ•=_PcOÃÓÔâæ ­êC…=e:ÒðZÃüùFÖæ„ÕLEkø=¤f5|P l˜Äc^ýÂ`ól%€ Ƨ²¬Ws@ºçgD,Oài:Ax´ZžœŽ©}íZ³ÜAÆ:Ëõ=šV–ûD깸)qC£Ç¤úÚün.OsÎ¥‘àŸ*‡×ôA\¾ïßÓLÉt{WZUOéÕìë÷|¡ÇvjÛ!Öb'ÎGÕEîú„c'´;Ñu¯Ë}è­âc' ŸOcxf³Á$ rš¯ý@¾h(ñB8ª1ÆŠ ?èb„ÞFIÎõ‘nT‰wYÎõš&‡óe9W¦ÏH^Εïýäå\¿NÇäå\ïij:E9×ÐÝýÊÃé@òr®îô;CYI÷r»ŸË{lÔ›–¢í°QCD’ùÓYب!6mÉãèðÏÁö IæÏGs‡í"’̃õýDZ¾ÿç—á… -_&§Ÿñgø¡¿³èq´|Œ?>3Ï#6-·[ß8ÄÉŽâCI';6¼5ʺó ñ©+…Ó@L.ÈÆÆH Xë`ÊÏÝJÈùúÇ,:VYY‡ëçŸW‚$Ÿ÷Ž€^dÉy~¤F¯Ò²ÝÄæ'Q;Ø©ÆÆÉl­f0Ï{š¯aI¹5ù÷c,Á[ä±” ¯± "¿Ú*‘WÁ1@yÔµJŸc€bÛ<-EÒ’i ÂÄØ¶Œ0qEbabl[¶†5aâ,·c"aâ,ÚöD˜x abG‘‚01}¶¤4é!µ>CcÍ÷SWf§ž …¨¦üv°AâÝ)ª)¶F Y?¦¹ƒ»dÙX¥-¸õqRqKeXüÇZø¥»$OáÍ„¡Øú ¹î’¯[Á{äer6¶:<¹?S‹¤`l#ÙËÆV¹} c«Ó1.#ŒÏP‹ RK0ê¢<–:¸¢ÈÌKÝÉ€+â ñ¢ :Ï`(H¼,n>!®Ž"®ý–©#FrT­\ Î>3RòØÉ¿³ê±3$'ôD™%äÅ{¨ÐÛkn6-CéѽþNH#¶ä!¼/ªÛÎ^IKÍE»¨*i©¸óNÌAÁ×î+ ï<Û(_1Û‡cò„Ëž.£ ²{ |XÑp&‚$¤n*RàŽ"?’óïÔ•‘œËVQ è~Ù¢ó1ïtÝÆgþòÚ{ÌŒ®¨E¨­Á´ei#ÌKºÈfÛ÷G+›m2Ò }šñçm¤HÞ« ¾ÚÚ ]ÌiÙæï¦æ qófºÇtüÓ$⨨kº0qÔ,ˆ£6Ë;$Ž:%qT7qÔ´%#‡ˆ£dAµž‹£dAu ³8ê@î¹ßШóÂsÿñç âÌ›à}×þ©?—yo+ eÈ_.íE¿&(lHËŽ¥\‰:Ž›mÐ>NJ†Þ„að;“³¶¥8¯là<–"Ç5EªòÎt[3ôY`÷øs Hƒ‘;ÛrE.»È×ËAfkôùÑ%äŸéÏ_‚tÏ ãþ`ŸÎî±]Ðû5ö|ßþ¼ÍôŠB™‹<Ý~Ý¿'‚ı}oåÞ}O_·îã7½ó G[î§OzнßIyËýÁ[~ÐkÚûtqÕÄåüéÔÐï|Ò©DMò`"ަ‚ë” þ=‹EÀRÁ˸c¢{FHgDÀùâM#‹€=½vA<Ò³¾y ȶҼ„û)5ïÈÅ/±ÑxE«+£¹ðìåÿƒØÐ ‹Kõ `*E!¾zmM¡ýŒ1Rí±¶#_½î9h}c\…/Ÿ÷rÆ ë0Ü:X2K[§ ·N£ñ¥ÖiªÕ¢ ë©K  á¢Ò”@s‡¢ÒÒ†èõðyï~/©{ Ï­Óãw¾ýé¦\W5^ª¿ý½_èÙcV‹ëª&H¶¶¸®jSW]‘¤®jWWín´®j›èy£uU$~n®wH  k¨µ5ìQ/ÁpݦIz &2½„Iz &2½„Iz &r½„q ½¹^†D½™²ÅGã^‚‰Ì¬¸S¡Ñ"(€7% |;]ï®*Îï»å¿z¢*ŽVɱ)qÄ¢ÕrœÌgž—¬zW¼7& àŸ+ï@|æs½P>Wp‘Ïõõ¸ÐßéŠÒ=ÂçŠVËq2_Eòq2g$'ƒ(Zœ?ë E+Zìz¦h}cŠVDçÏÉ3o[òLO¡š“E+A §3œnói@ë›Ó&4<(>Næí>ž~+'ótÔÀkaá%­ºÞåƒV]ïîÉ»æÀVÍºŠ¾6—mMWTñÆ€åõ’ñÀ;DËì"+6²î=‘•GY÷‰è?¤æÝÏr ÉFÖÃ} ²òiyO³Óï”<Ü)ÒóŽf=»äáNy?³Ó]*{¸DVž -ëg–eå ʉ„z´ÂDrí²4w[]+ {¤$Aºäc‘÷ H\ô±˜ó逋N]®Ê9õL#NzvÃt…ñ:Üi–Â8 ctš¥0ö„Âx ‹ÆžPd‘Â8 ã,RgBa{ø€aÅô“êš(¿’ ’ÌÊæ^6MßÎiØ€;h8û põ(Nó@:þC ÷3òî‘ã¸Ò(Ó…†w$N14E¥|wœ}óBËfö%Î[2ëo¿— m&äô˜®ï_©OažÉBäÏtÞ Ò<7 »Õ 4‡ƒ>K¤9T¥9œÇRPLsx+xáæpÀKÛÒ[œç E߃±ËÕŒ ;$@²}$q¯àÞ3ØZ©H OsoÏ.È?ßß—‚TÏ«Û3z›æë u©å»>÷ëítvÃÎ!°ù ^ /`Ép üþ|—uÃÓ R³¤¿¢÷¨öÆå÷=VÞ8 'ÆFòVÅtõØ2›´îd6c˘ >NfƒRµVÄlð@Ì'³Ái™kGfƒ²`6ØÌdÁl°;™ ÈÀ(/èË•ô}¿¡%xT²·*ϰnïDo™)qXÐíÍÄS7Jy’”6RÊ“LÛcJ9éö°§î@i#'ÝöÔí)mëöN›Š™ÒF¤d‘b‚¾AŽà2R7–)ðpçy/úRàc¬h©µiÁÎk©’ iœÀÏjA¶BHãæ½5$ó…íÀ”cA*¾‰‹Cï²zÿ ¡÷ Y½ïhè}B–›¸8ô>! ¡÷ ½OÈRèý8àÐû„,7qqè}B&v‘ RWwi*k°ã}_V´qÎþ« RÜ™BtAVs‰&‚äÔö°V\A,ègÂÊ‚Œ¢!a—v ©_8¸™¦mxÚòî(›ŽÙ¶R4(Hñ¤’©Ðc~7[]ñN‚T¼aN—Ïnž s¨¹Í} HÅZÖ$½{BjÞ²&?#H=,¹üIÔ‚´â¨Ë´ÐéDªþ€Žé¤½Ì„f°Ö ‰‘dଟ–7µRR• ¦ˆÒ”JÓzvÔ IÈ¥i£Ë@ƒ$!K”¦õ¥)!K”¦‰(M ÉV€Ò”C:x;¢<‡¤=lBrAÄxþTM¥®˜©·\WLH®)ØßaVTJÌ\63)Hoኴ˜x‚æy>Q¯&z—l%:¯CäD=hº,H'{¥$c´„¼R¾'‚Ô¬I’£%¤a2Ò!¦{AzÆh®£1Ý )Ätõ{þwâ˜î„4i8çƒ,È †Q>HB ù ð4kù ={1ܪÇù iY"rj¶%$n•X ɇ[u7zL!ätí±èã„óAòçóARß8C…|‘^S˳á3§"[fYýÐâ_EIW JnÓ覢bÏÓ²nÑ^(Îj’Ù …b¤&IÈ’šd°š$!Kj’qÀj’„Ô$píBy «IÒñS}~œº2Õ÷;A K‘üÒi--Á?`AšŠÀ )$ÈäQ§-òú £N[ÞÈwÁšxAº_áã˜ÄP‰iAz¦Ä´©í¡Ä”…ÓvL(1%¤.ùU¸Ä”ŒÖ•˜Òré„Ù qAÖÒ a,Ñ 1§&¤f»ŽSH'ìè1ùt—Â> )LàÓDB:áHïgyÇé„ùÎ øéôå |Â鄪ÂY†FIV „³„T¬]'ì>p:aAØzyäµ:©iÃnÎÔ¤f,jWs¦;AVv{^Ó²u‰ysYËwÉ(ÞLˆÖŽ W;Ú£¸vd¸ÚѺ!µ#£x3!Z;2\íh=&©¶v´vïpíÈ(^"BkGFIÔ´}â–Èú¸ÖaŒœÖ #|hÒXIN÷}Æ='òdÙÉeÌݘ^D.ƒ¤#ÈBúõ¾Kº\î=Aj*çHþ‹ýå>ý¢HƒÄˆï+±=úîò HË!×j1Aºò±"Ý… ‰Eiš˜–cN¿îyÉ"¢ŒLDõÇe¾?!ãIØúq츗³ùŠJ¾úyÇW¸;¿Õ!ñRwû2½ä½OInDFÈ#ߥX!‘ Ùò¸¼ß ’!×üA3BÆŽ …2Ò+FÈ銸rÑs™î×3R!ù³Me„\F‚dGºó¶‘GÈOÞï[ô=Ú+Wéæ YŽ_S^ŠXi“rù¸ÿí(’ îA Û²©^ëY«R™%Ú/o¯/É#súùÏŸ\Yµ­”êõ6Ü:zÌC¢½ósYÜÑcú¤¡yY®ümOsXàÃûô3S$’hãNß}|ïzörÎæò®ß/§ûYNõ.·—?÷Ó -§z «Øæé¨EϧáŽ<Ÿ(ç@³É3VïŒ kç …z¢^;å>¬ô¹Ž©¥  Å%¤fÍ<û¼ªGù•Éo yWÜ–ýíò;í}ì“cß>šÖßùçñ{º||¤Â¯Ònκóöö6©“Ü…$nÜ·Û-/Z¬!˜…|XÃn‰Ÿ3AZf—„ wÖ0˜ÍÂv]±Ò³{’¸‘’·áý‡ž=äDZ÷y|Ì÷÷Eîãÿþ¥Ù˵ÃéÚyWüàͳkÞ¥}~|¼ßò’í€2F€HX»@-Û“°°6!‹ÂÚ k²(¬°°6!‹=Ù k²(¬í±°6!‹ÂÚ k²Ø§°°6!ózân#RÍí©`Óml’„¾ ^R¸ð{AŠZ8~'dQø=`áwB…ß-ËX^ø=ѲŒe…ß»Sû^ä(:µ£¬em†wá7ìd‘fï©/¹=wxç"Y9lwi—­­8^9¸F(à|\†×ü4¥<ÐuåÇÛv¬Å–å£DÉÚv¼wÓ wîÍ?Ë·óíåð,YK=á×wG¯ÈábG¶^–lwøÌ9lÛñï²?#ƒ}–ÏÞÖ²Ïf‚TœÇ;Y§d);ì:«# –« )Yåc ûhÊ b°’Å2ÜO'[,C±Ú9ÙbyÊm Ç{ÏïÖÅpíŽ톯éYÃ×ó6’¯›A¯ ·žÍDÁj7!Ù°uÔwqQ`kÜG4'û¦bešŸ‘—31Ðy)£c—„T¬8¼q ){/øy%«¸¡îužŽ)«lnÀçñFè`’ž,VÙœ”&íÉúŠÝãtLÍDY㞬·Œ2â°Íƒ†—wÛ¼<Óz'‡”¡ßédÛ¼Gî›{ùÝ| ±äÙ‘»“í¥¡ë‚ãáNci·=‚§éÙQ·ÛÁÙ=;êöâƒ"u©Í:opíœ!ñæ°ð¸ÁN.„ÊXÊc>Dy,A-DÞÜúŽt¦‰M…9™¯+b nˆ9[Æû`ªL€T{;øªbƒÝÑcòövÉ;!y{;àŠDU±Áέƨdl €DU±ÁÎo\TŠ}¯r i_šü;ÛŠÁqÉD—Q2€ƒß©ÄP¨3´¼.c­èöhfP†5Œ^ ŽÇ¼¦=B]1Ç@êŠ-¯à8~' ü;aöVN%Ú©VyV35ÍT«XèµÇ‡4S­ò¬fj&š©VyV35ÍÔ,j¦z¢™:EÍTO4S’ëE"ÍÔ õ1÷ZP…”C2ÿÀHŽrHæïîN|HfÖøH>$s̳·ŠrHæt:&’y‡·8¢ÌÕÞë%µàïÓ[{ý3S¤O;ýugÚ½ï{ØÇÏß[—ëÉ2”ªîÓåþë:ž~g|Fn ••ý|£w¾a3:/§ÛÔ¶|Jžot#G¡dM«9 %™Ú%¤æcK~OiøŒçî´8ÜäY±„ú-7!ýõ˜¸?вá&Ù™&O[épB½Ð¶"“%Ç%&ä‰/ùqœëZL$/ A‡ÔZUtM]¾Ë%ïb­*8w$å8½÷y¨LŽ µ±¸é<–ÕUžm¬B*Š|,Èû¯Òñמ6-&¼¯ý1$íãô‹ ùk¿ÍÉ_û¯y"HþÚç+E:ÆGü#¤aý#gÚ™±†õhgÆÖ?r¦D¢?ûG´3c »þhgÆÖ?r¦D¢?ûGδ3cŸ}±›0Úb¦ v³Ëko)Ód̦HÞÍ.3Z`¦3ÙwŠ”³o)f÷)fÓc>Ƨö¸ÿßZÇQϤÿ ¥ ê‰ ¥ ê -ïð”WªÖWž`„øR=;ñÑî7X×}æÅ'vášür#HÅÆ£æþ‹ô¥xTôå ’µÀWßô˜–AÎ×ë銹úsú¾ì ~‡­„ ûn÷_"…Y^&zöH‚__²[&ùy¢÷óȈùgÛN\xžn¹Eë¯ñôZ†ùXÖþ§£ ¹ŠpT¡}‡sR )g¤k$»GDRn]#{oÀ†Âñ´‚™Ó[BòÞ˜­@¢ÆÓöÓ´Œ‰º-&¼ŸÊ,3!êHÉ<éNš BDÝiØŒNtí|Ѭߋf7‚T\šg—Å(’“˜¬E³™ ›Ù÷€ûùœüÒ%QòuœûËßß é™Ilóz\&1¸ŸÏÉ/‡žo;æ÷wÿ HÍø÷| í N~)ø÷ èŠ<3‰í¿óz=ýNWtúYuNg÷œ !G“Ø?‡òïºßÏuûÚÑkdºË®ïþ>Ñc“š?º zû5çoüÝõ|ÿlç?滘õ:̯3…*†×i 4HÊd·ÓJZ‡•e•U_±ƒšrmÓ‹µ8\¹ò­ìÊ µ8ÏqKcvAk½¦&ì‚ÖzUqAË÷Ó«Š Úƒ³d¢ÓMÄí@Z~:Óc²&:¨Jï•d¢ƒ×«^U\ÐN×^To÷Ä-ÝyÞD–¶TpA;¿eÍ_ÐЇ­™"…ob^²z#¾ ¨½ï­,#¸w©8QÔ`÷lƒ}³E vï*Ç„êåcÂ×Ó{‰r…̧[*æÓp—‚= ß_3ÉΫ+¢¥üz R™ˆ–Ú æª¯mÁ|ÌV1A¾ m%†"_QPr Åœ‹«Ë |ЬÀ„Ô|\‘beC›ÐÞ¸€K=ÄTcÍðí¾¦ÜÊ FÎðý›Ç|Ö=2ÅOH6Ãwð ²`ª±ì>¦ÕTãžÝæ´ßy¬¯ä8?^/W‚tùÑ%äçãò‹ ù _Øö#gøž‘\†ïÛm:!S†/vÿØ/þããtñ)Ã÷Ìûçu ©¹Q(â€`/™ïŸáÏãÕS‘±ûèßÁ¤%A ã*Ò½Ãâú€Ú¢»Ûf+rQ|†ïŸûù·ò¾OG %'¡‰Vƒƒe=‡&Z –õš‰+Õ,zõÄ•ê@ržC¸RHÎsh§Éy àJu %W*ú;%W*ŠŒüϵèà*w>×¢ƒï»=µ¹ÄÜù±#HáÎôŠ„;º"Éí‰þNÉí‰"#7VÁ‹É~ ÔlCøÚßµ cå˜yÒ‹¨žýP=ú¡6¶Î`):…§åÂú¡¢SxZ^ª¦ÂWÉWt y§ðGrÜ9†Ï\J÷Sá\—b’\QËvö$¥Ó1ev‡jª‘ßX®«†;fà» +ù]y7­šJ~Wæ:ªÆ°¾3á:ªÆHáÚèS•ߎüÆHÅVfÐýäÕŠÓ¶E~LÉiާ¯L S‘¤cè∊| ‹V%3¡"ÈÀ èáÃå!…¹zˆÊ()üY|)£å¾$,k±D¢ØdÏcÉiÁ†Êʦ;$¶NUC`Ô¹ŠÍ ½`3° ÇÒûnx;®~™”&øÊ P‚ç³ßÉýŒ¢IÌÛ.Es °øR¶eLwÖªA ÇÌï»måcv©ë¢­ýŸŸ³­Èîiý@¦ÊJ¥› —n¬ðÝœ_:´‘´º2êàŠŒ<êr‚–²Få£ßi¥².[Y'õ¸qIÄúZˆk~î¡–’g†ÑYc" ¤²±"„ß än¢ H…Ì’ËÈ<3 ³ä³3}O$Ò²v›P<± $)§œåcº¦bÙ›G²k„Óoá]+‡!õ;áíxÁ¤eÅò'“Ñ) MÅè4?#ž?y””áwÙèJÊÎ0%å”±–G²³LI9%§ÁYÁXŽ””²œU˜×ŠØ¹h #„m:lŒPô;/=MÄQNÊm[žæG~‹Ý®=#ïÔWþNÞƒ…ü,¥Œýcyši˜òj¸(/™¿.W”7‡^ï¯$ºLVW¾Ó- ì@j.ã ¿†µü7Î+iÍ€Œ·•W•™!¼½ŽŒN•À"›o8\yË®Ön;%r È“”ø#dÞ_C~šN*È +…XdO¹‚«à ×îžR7ß“ýÞ7¶bP’ ñÊ>OHËy.ãþ΃{³¼ì­™ñ¾ ¦ïá{¦H_&O®;™^Q(•ƒÞn—¡?Ý¥{³&{,g¿ÂÙ?†ÓÙ÷‚ÌÊ’Y_Í·}úµ†sö—ÓAîMj׿åvý0Mg¨b*B?w˜š¨ÞË<ÿœÊ<ýýëüìwîÍsEèçþ|Tûl(¾‘BïóåôL[ÇðËËË&ðHW>T<ÒOHÅg ‹ålAXŽøÈôrRbà"5ŸÙ.75oŽÍx9šŠ·sþعp†zc˜nXòøÍ'è+° ¥ØD<«è¥lÁoE)äý´ß–b0B<»¶¥Ü%Ï oaа¡Â.Ð…¼ÂKw§ÈÂRlY¶LÛRŒ^¿{ôôŠø¥Ø­£g/,Ŷ³¯K1zÌòRl­NP§^\ŠõÓt:i)vdLCm‗bö;=ûòRlØ–b0ô<·[ÀužÑ<æa)VU£ k bð"MÄÀR!zBÍS1JFØhᢛF6ËÃT7ã¥./!I·n¯†$’nÝ(FÒ½i‘¤[#Ëì’Æ$ÝYfhtHÒ­‘ev‰$ÝYf?©!‰¤[#Ë첤î§b$Ý»B$ݲ é^XÒî|IÒ½ $,éNЖ1çB’îårÐQž“n´´[@¾Õº1"øÅº±2Ï´ƒ³;¡%ŽYZ`çÍkáýNÏ”öwhè†w*šIÑZ7¡rí0œ¢äi4¡+jùwæÄT%ôeyJÝb¾vö+Oëà¿÷ëË Õ.¦ùßWŸÐÝMjYÖ_¶ŽÎ uBî²›ù:\îÝØŸ¯i2ò5!ßî¿—™áÑýý$ȃ]²\ûþ û8Ø%·.ùÐH—T››èæ}ó¶™>ÞŸ~'Òw¾ï§e®ÿ¾|®n/™Ž¹~Áºe}ï 2&ÆÊæ.x”c—EÆú"Ÿî|C v™rÿ¾ Óýv‚¶ÀnY}_÷ó—û×òSªˆ !ÿÔ¯ûK÷ç›Bw!Ñ?ÿüw×)$èt¿¼ C» ýu¿?FúH÷/è2¯Ðåõɵß×õðeúý‡B÷G5ÿwÿ­ûví¥Ûe³…nÏjÙ®Ïêzì×î—áþrÿ9=ÿ– *¸å%¾n•°Äÿ\+ÝA–c¿~›àk‹§çïH¿~G†îF†íÁ÷®U¼½Ð¶m˜z‚t<‰5[]1Ö‡+ÒÜšd™"–5É&(ÉTµC;ºµRÜ*Ðè‚a=ªñGcúsµuïÔ YìÔf¥3Ajn‰EŠYìÔ {§ŽžÝ2†µ4FéX¦|@[É¢‡Iè6J¡ˆ¯U#vûo™¤U#ö‡Ñ Sµ)ST€.ºV‚ègcâ¤=ƒ&F𥀟$è×Ⱦۓ˗Ró±=p?%YÖ”keYMyO4åZYѺýš7—ß™KNZ9iñ0w¸K^XºŒ¨è£U#v²[#bl1ä&+°¤æCnô솟màE‰q‰ÊëZK’¸ù(hÝòF˜Ëfyy“‚äçoÖJŒñèá}×J*ÝŽ ÒZËÖ_ðíК_Æ¥ÖFØ¥ŽˆG©µ»ýÀŠÕ,73î’‚4^QyH F×ó0^–ߤ`š>RdùÛqPTë ô]·ÐÊŒŒÌýɬXm*!"ù~šFtswmÄ‘Ç%G@iÄ:|æÏ.#®èdö¼¯—Òäõ1ô¿3RÄÇ;mœ2m52f>ÈõïGk=æí«ÏsA«µÿúÀú ¯Î)i˜0òÏþw Õޱt}? P—­ÒòÒß Ò±LÛÌJ8¾¸ºøûý:|®=°¬xß–"LðšÁɀϊÆVšŽùí0® ’çã$òQÓFIßÐ×Ðx^&BWA,çqã×àU <†8Ãi#ŠeqÁ6R; ùåhÛʇ¿¬2&zLË%¸ó¾&ÙL#YbGɦ¶µë FÛ(DI¬ö`ð;#Ó€Ù¸o«=Ej–á+ÿ;2ÙƒÝ6{°ü³Qˆáœ×I™ž·ËþC’·a,EÆl\Vu[ƒž½(N6{°ÇéÎsö`Ëé{úCKö`ÛùW{0zþVñ/rþ®©åØ¥›ïZiƒ†+œNVCÎ÷Ìœ€ýwî›”Û¬•‘ZÚ¤àm—3bÂÐ𵫢óuVHÄr휜ԕå,Ú99© ÊAÎI}q$g9¦¸õØè™y)â|åiæWÞùifòÝdÓ»¿àïjéÝ}O¼o"lR|Sq¬ÏŸNßH™²x»í[y,er½ö² h…µWBç»Åh/õh°ˆöBÆäFºÌãÓ‹j]d$¦½°´[uçY­«½có 7§(Õ"6Û9rA¢ÆÁZ¶)ýו"Yª/êdù ò´ÐÆÇG)[yÕèÐT\.’’^‡¦–•ÉâfZjŠ- Ì´Ô”ôvà"a³JL+c%gôêÀgô.H”Ñ«ƒ‘žû÷=s¿46º# *r¼_{Š4ü{”ßÍ`eY-¼ÅÁUì«á¹W2za“|ž:‚gÝwf"•ЈKW¶šÎ_„jî;É[Mg©„Avã€MJ¨YŒçY1IJ'zå1ÖÑg&ò ¸t圮Ó1uyˉev:¶â–dvºâ¡¢ •àÊ0¾FGjB¹Ý¥=Çc]ü#g°øÿ¸ ¯ð;ìLO36Mb]¨°ªFL“xÏr·6ügÙv½½9 ËÇíã1,cžžÝá…r& -_ì;,”£Aiÿ>!û32”é"X¬ £­øLÒIkZÜh‹¾’˜”ßâ˜æHJ7Êeÿ˜æÈ‘YÍ‘$Æ6nŽD,OO³Íõã(_܆.‡ë óRF./Hr+Ô1r„›ôäqÉ_„ˆ™åÿRÞð2/õ?à …ß™œMѽ ÿÎäVhšFü—KÚœâ^Vø/©1dšF’§£çnšVÎ=ËOÓ ÷²ršÙ"5Ÿ'–Æçäšbˆ­n™7 luÓ(a7±ÎupLÑ Y›¦’D”X¦1¬…ð@X¦1¬…ðLX¦á×!3)ÕšFÜo"ºiœ|?sCÐ &£|ÈÇô²yó®Ý3Ù_Ý)ûË4É¿êNÙ_²äätÊþ:…ü«î”ýu ¹ü«±¿žŽÉå_÷_'¤ã¯ý‘çX¹öÇHüµgg¬É_{Îþ:üµÿš)’¿öùJ‘ŽñNC;SÃzÑe×¥ô¾·­D&A®K¦mÙºÍ<á]i•TоAÅ´bbýBa#PnRN72‘æÍŠ­åë ›?èt'HÖÅjÌëOÓJn[ݰÜOŠTŒK%jy˜Ö 3-6o0ˆÊR²!6æ<%P¥vy7¼Ü/iÔµñÜdD9±[¢E2‰²[¢WO:9c]v–ã–›þñûµ†WŠÜYŽÿûgC^òççõNÈ·øýííàß|O·_÷· wêÜ¿{õ·ÛÉ9÷׿CßO¿)Òïyb{û¾ë÷<±©£gÏybýž'öž¿†mD¾Å¥§™Ÿ»jä§™9«F5ÒÀì™÷ìй2z‚,¿ï¤ªi”’<ÑNß(®vñØè1P»0Š­]¬Mð·ßd“c”áÔh«>ä÷¯ûWOúÄ×ý8Ý{ÿóB†ñ-^wùìBíbõÌ5@£\Í’!ß%/É& ^*HKQJfFM1£ESD­4º­øçk×­¨}Ec^+Qû ] £…iâéhtiÔu‡_õUJ6L¥tC¢J©Ñâ¨{û<ê´)x´$ýÒrëß)Ò°úÏ\1šu[,ÆÝy+u¾n03h'ù”/c>¯Tµô=ÂæLFÑ ºBFékˆöïF‹œü54<–rÅ OQ57¥=¬1­¤šû¸æ»dX“‰ÕhI] ÊW/+ÜfŠ4…Û U¸HÎQéÖ¤+èÖ^¨ní@z$[{»îßÍ—îï_$[;Óó¯Ý^÷îþÎïÓm¢g¥´R*ZKw¾è(9\n/o¹!— mY´vG¢µUÏ¥[D0^ÞÅ–îaÂhyƒ9T'_™~,¥ÈB`é±À˜á–*&°ôX`d9±Áª’I÷‰u é† ™'£%&$Š0ÆÉØÝÄÖ{ò0ö†³ÛÊ„Wää '·q•‰Ž)NwÈ Ï ¾SÙ(sdýAb”n$ç¶Çæ¾Ó@Ú‘ÆJ“ØçÇÜ’6°ž²33ÊXõÄí$‰ˆÃ阚sßéÎg7|®]W¬ áwjVȽ ¤ë<çQ‡ØV'våêxú~Ɖ U]¹|>°¢Ó í»r39~ù¹õižÙ•Ûï\‰'i™PˆO0v1(@ûÌ®\…h]vD3(@›ºCía C–+•èïÈí@Ƴ»­*¯Ó]:tšIÒ¹ÕD6Iç½ïß m™PŠÇ%K¹T1ÓÝdHSÈúNñaKr†ádeB`&~ë¤|<تûLF†JŽ æ öCQ¥ÅÆŠ·73ÊL˜À¼§¾“qmŶ9ï¸]+¦Rȸš§Lâü'þ™Ü8Þôt¾n™=A²ÔV ñg*²¸KV6„Ësã¤Qסޥq¾Ò…ϯ'æ&í¥ó+ï82ä¶dÂëj©ÚÇš•Ú$¿®Fw>2ýÐÇN\̦¼ÆE©úèsÞ´ìz–7ªLOÃÏu®=ÓH×c¾¼œø±”Ÿ‘o$‰"®{1¾×!y㺭Œ–v^ˉè˜ZLÏÎñ¦2’óÛá­”x€G†e[®CèwúÊýÌoœ<[ [¹IpE¯#õgϧÐÌ„Òl$O®u »ÎÐ2U‘i¶j2Òï J’¬‚”t—§­žV™‚‘ì{q5,XYZ õÀ'± „¹g$§­ÆŸ)×ÞA iB`’3á˜XäL8&©Œ8&H2(ÒI ±"Uƒ»…pR“9eÜÃP}ñsÎ~dk„q÷È[câuEýÈæîÞÝ¿RbŒ‰Šõ#›ºþÏu¾ÒcýÈ–ïÖßée"HÃ[,çµM%´¸ÂMå.å;ϳYŽ‘œßŽè„ŒqlÆl¢¯˜1Ãïä$Þ;{ ̘Mô3æ‘"Kïn"fÌ&z^°O̘ ø=•ã¸aöŽAŒã¾d¹ÁüÊ$_[&Û ™lÛêbÍd£HÃýÂXŠüªr­ÀæµmÄTIT°M+®`Å4<,#µ®˜2Á1+ÙGyÅb‰ãÍ™ÏÜ­^öùЬÀgî~ÿ½ü}!HUL1Kù@žy­ÉXàwÿÕS¤áßw¸ó®òŒÒgIÆéPìl+tíëP¬HríáùÚ3û·í3WÁFÇ3jU,ѳsÌ(¤F±M™QÐDZlÂÞãdnÛFZ©¢ï‘m[‘±9Á{Ô*V`ÞoIkI®eW¡ÔéërMÀ¶Zâ ®œå¹ ›½Å­•öÅh¥jÅ”9¬1±8e®ôŒrÄžRæž²aóÊʶĂ½äÔlÛÆ¡rEn•=Ažû#¹ÃûEÁÒðw~gãM wiUS‰zHL«šÊHγ¢j+Ï=?#%éV°Ù‹UBÌÅj©WVÑØ{ÌRt« {EÙwX)îŽóè¬r²ýB®ÂY%pøW¡1º"/Û­Àû®¼èl·VÙ³=£XqÍ3ƒŠ•ja>»n„ÖLZ3V·•’GyY«QFj™«ó¼6RlÚsYÙ¤¢ƒb¾•:Ñ$ÑB'zyHëÙWÑŠü¾_úŸkÿÎä<ô¿á.åyiërî~a;èõòÝÏyímÁ¤b­ÐäÇåû׌0©X®gmÞ½ —þv^>§Ó1m9^?ïù}‡±ÿü»¶Vý!ÇžÞúÛ럙^‘O5+x÷»Ä{:3”„ÛÓåþë:ž~g|Fn¾ï ò|ç›g÷zÐaº]N·©êšpÔXqRÌó·i¤™qy,Ž•t3iÜUqRÌo§]Ê‘_´5ºò&å{oŒ ?ÃÌ,k¬tL´ó°ÆUîüN_±Ë‚;„ÝÌVÏο3²í»~÷Êž ’Ï…³ÛFÒq"%¥µÒAÛÖÚV¶UxœêÙHo}FãýßX«¤hí©­£ 'XÙYÖHoÙm¯Fz§c²‘Ýù˜å¤ÕH/ûbHÇ;ÞÃ]Òƒ =¬‘ºRx$X_Ì›ë{^_X^MØï®ï7‚dÚ¡‹b­Íù fÙÞÝV CUUk£À1$WäùŠn'$G¾@uwëZ‘Ý ÕtëTåÚóýtR"®»[''2€.Ö:[!pE®2êòLË/=æÕ§V .È oôŒ$óé±_Þ¹A*nžõ›õMÅz ÒÎwQ,«˜ßL†ðçµØA‚§õµ§™Gˆ·rPeîîZ¾‡sœŽé+£.Ïu>È oø¾û(+¼á¹ãNrÝ8¾Ëþ¤[^ã4–H‡²¤Â’¶¡eYÒ3aIÈ"_µ',éYdI÷„%} ?Bò”@ #;¹ eË(XÛÍøìnÀêµgõ΄Õkƒ‘îbõÚÀ³z{Â굂~&]lÅT,¯mpÿŠ˜¶Õ"1ÙàY‹¸‰˜lð‰i¤¶ô²DbÚô=@b:¦d7Ó´l¨äå„HL0êð1ؘàã…ÌÎÊàáŠ368·ð¶Íéì–!’;ú?š©¸×ÍÇDÏîŸ÷ëâjÝ{|Rd`eX¹å´•­‚ïyëL mF:VGÛíŇ5ãZÞܬóXòÂs¿|Üÿæ÷]{~ãsÅݲ$ñ_7>—µÙJ&Í´Ëôù’ʰSßÏþ¼Óß¹Kü×Ù{Aîûý9Î×Ë• E~t ùù¸ü"È=÷ŸNõ¨îñ÷ÞÑß¹ãþóïò󌌌ÁÛm:!wªÈÿýo¿øwtñË*ôôöX¿uw¾Æ nÒ²×yüóÚ¾ïŠJg×\hê.ß?ßñÕɸ`5¦|ÛSG—#OïÓÏíô[ |¾°fìÞ½ç~x‚Úb2ïåÞCý*AݳÉÁ ½½ü¹Ÿ«69ØŽz>j(…Ó$œÖéÀ—†:=6œv á´…ùÑôØpÚ™„Ó:àI•d" |iˆ„Ó:àIqá´ôÚ‹á´3 §uÀ“z §H8­C<©§pÚž„Ó:Ì“*„¢pÚå¸4¤#>±¦có‘¶ 2Aq|>R2A¹¤.ócùHœ JO¼ JßÑcJ&(ô˜’ EJ&(AJ&(Y6Aé‰ J‚MPzb‚’ «ê‚6,¦•§¿3­ Y$U#6€p•@äÈá©3F´ ÖŸãÍEŽÎî*Ç„êEýÖ !CÅ×®(VŽ™¯È6•´|LÛJIˈ#çlË×åHCÍY%²kðï|¹H‚³‚/I0p–s²ïN Î.Á`5ÁCÚ ‡¬8§|í¶âášœë±~¿°£¹³Žå¶ÏÄÑÜYºÄ÷ñµßÝÇõ¬Ú~ îãRpÏS¨õ¬Ú~ îã’UÛ¿w·;A îã§³ÜÇ—Åq?÷ñÙŸ‘c_ˆ#\¾“¯!ÉdpØ]ãìk8Žˆ±ã»Fa$£Lg#“ÉÐ2 }¢N·{È08Ý:Ì$¤, uÃ2ö÷—A*ö˜Ù9ع¶rÌŸ ÇÛHF.¿Î)ÆåwG‚˯éGçßI\~dÁåwÉàò{ 9—ßGÿk¾$çòû¸ÏWŠtüµwùŠtåÚ“»³sZ¾vôŒ´|íÙÝù@ò×~ÍkÐÉ_û¯ÒqZ´pFT½ Õá…b‡øÝç`|¼§Ù†ðB Èe„&¤—¹ð…%9NOF_ÈoÕ½RRGiKØH³‹LÂÆÖñ\6z‚dŒè¶„ zLÍhUQ¢Žó‚«b‡uœoø¨[º â=H¶Ò%*r 9N3- zYOÖ!ÞHA‘pwv2+Ep;ïæ0¶ÁsÞI=\Ü•ö^d䢷ƒ÷ 9Ž ÈX9f>{8Æd=Ú 2Ÿ=(96SˆzÖå-áíFª ]¿2߯/ßÉ¢—û>ÞèÙ™Û-ù'# “ü³'W¼C±+qkŒ:³ÁðÑÁ{òEšgMØxvMXþ–„y>Å~fgk,æ¹yi®š°™ ù0Ïi~ [jøÊ¥†à¤RÃ7uŽ ÉܨJc7ç÷=¸'uÌ{Ò)|ãêiÊÏhÀå‹ùrù"å{HW(_ÜOå‹Í¬ç8Íå?fzE¡Tèx£…Žà K ÷S¡ã¸ó ªt\ßöÇ׺=A•Žºcÿ9*¬o©ÂÚÓt:«ŠµPZë8 ÇxúçTÀèï_çg¿cŸk?¸Öq@m)HvZ©Ó—óoul´"ô†ƒ£/¼@4k³®0¶ zÌbP¿ÁôižÅf›W$›¹$çO$6s!p=­ÍùÄf™=9±™C&Ee±Y^6…ÀšÀôDlv ]aëµ1’ÑÖ+°[¯u‰ƒ·^ÝzmÊéúþEEÛùgºNïiJs‡å s¬O ;P€ÚÙâc9ûÛ4_ïY´øX¯èz;Ý•:²\Ž-³\>°\ŽJî¤é0jÎovï¤Â‰šó›Ýû£Cþ|FÍ›]Ü¥‹š¼G˜(6-·iš.iÎô}¾]GÝÛø}ËÜÐhoc' ›ÞyY ½]¾ òL-êò÷ð{$H,«xÏ]ä¦ö9¤-ßù×ïš4ñÙ6gL¯á}^ÚFä ›hjùìŸ/ן™"%´ïæøyïÞéÙwŽÅÿþ!„¶õÎ/³òéÎ7…¯w7ý^¾Þ/”ËKGâÖå^ ‰.ysmÞ†0ðJ”lá‹iÑ Ó2¡YDW¡Yä]tl^dOiÑ 9bØÝÅE/¦©‚»‹‹žuw™‰»‹‹žuw鉻‹‹^JòÂûŠdwAøÌÅš<÷(ìfñNÉ7eýÞáÁ¸Ŧ„lEäØýÊHŦYͤ*ä-"¡*äÍæ^ ¤*t ‹¹W3© H)óëNRæE:þÚS5Ð7¦rí‘ ùkÏÕ@ßùÚs5Ð7¦–ùu'H)ó‹"]ÉAwXvJ«9WBZ¡¦ÿz>»‰ UqªÆËx啕8{äŠvf÷›ÓEZ®OpAo‡…ÒÓþgÙxv0ê,jÊÒŽÂûZ‹Ì;ùŠÛîëíd¡)»l)v§_z—ަìÙê÷qYæN©}öúÝŽú$Ò-’ˆüÛ7N0_† ^2šë°é«'Ñ8‚sãöË8ÍÓH”÷û2¢²Ö¹­/ïw‚äÖ«àáø&ö>øwŽÇJÌ·Måw>:‚dçårï ’ÿ/ù~¶ ¿÷yYu†y൭d‰‰¾•b•ÆŒ£}«ø¨;bbæ[Å\û+ψˆ:ž"à—[Ÿ?^­‰ï§©s¾¤*E-ϤÙé[+X¤âf§om-j¹'H]¶ðÅÍÎ)D-ßï)E-Ó³£–{Òì<Ũåž4;d(ð#פn¹Ÿé䤿ð;ÙÅêjI‡öû‰dJHPêò­cø‘Ý8M+?²§¿“cÿ¼ ðIjQIŽÐ÷c.Ÿ/zL_àŽÝGÿ>ýÌzàøþèÙ‹šacžî'ô瓈«D =•MÄޝH ax)I¡ëÐÀ ¢K*¨È|Y­Ý´jírçÉ“$JÊ„èé`Vœ;ðšï(Ÿ±¸æÌðªsFX€F¨Ì„Èû)¡Óä° Ñ A‘E&ĞÞ×- zbBì9ì'dàü*Ñ3Âù’OÌD¬ôóª=F²3ÅmSg%Q‡WꙘ˜Ty„² UÉ™â¶)©nô˜ºäL±ë£FŠdz?È™â@ZÖ™"ïd¤c)û°`SêI•—ü&†MuºöPbîöû]ÊãSËñO8»‹ÀCvŒ<ºÄÇíwa=»aƒ¢~Ng·œvjÒ•ø¸ý&lÈ“íŽô%Qu¿ èÙ§@"¯Œ¤@~Lè.qV±„WVL»˜Ðá³È{Ò÷Ê÷¼‡ûý2…åEµò%¦Nê¡þ½__(RðãË»N$þ"âz$y*˨`^ЬßÙ@dTœW—/ç´G<0sОqTúƦ‘|¾_~u¯‰Ós UÉêbèî¿~ÁÌ ¶3ÚoVŠ4¥îÔnuq:¦\öòµ¢, œW=N_-Ũe‰Ž×ŠIöéödŸÜÁõZ³Ëï~«KÀÙ5ßÁÝêù}×|IëË¢û©¹ºDwÛê©~ miI¿§Íô˜l]¢ƒ¥ÖR]bå„Ò+ l[t<]{y¹¸U0ÆÓçêË„7Ñ‹/Õ%¶ó/ŸÃÓù[ÅÅ颂65ç”|£¬CÓˆ.ê`?Ž¢:®KhÇì÷÷ò;ªKhÇíO·ªÚójÇì÷÷¾$ªKhÇÔ%ÒïÌu í+¿3×%´'ÚGc½YéwB]Bû"%´;4–Ð?õ:‘ÜÝ÷åíí‹ ýÓ½õýS¯Ó?ݨêµpƒb,<±>WÖæq~ép@ðs<®6˜F¨`¬Ý”DÆõ¦­3WEˆ@‚^ì£6SX A/V$ê{d7L;ÂÛýDao”4BPGØnÜíä§üéÄy²Ï©‘÷aÊË”'[lcÁn4ßÆÚ¬Ñni8 z ñyc úMyÐ$/ŒO§±’M*^Þ+§¼qÙ‘ÓI1jÈLÖ›çÙæØ"ò޽ LÞqwÊ;>ª¸ø'yÇRÈ;†*yÇzLËÐQ»ÍD¦Ý¶ÃP» IhŠÕZŸ’%ôu‡äo¶„.¶˜ó'Ö*)F µ˜½UÌ’þh5^îùìš77_CÓa o¦ð¸e¶†·†/‰Ì8rÂ[+™Þ¢X:o´f@jvo½d Œl’¼õ¢õ¾ö E· hb©½Ÿ¼ÞP˜‚·‘u[8héì®ay2 `&HVyŽî¼kxòèN¸$l4" ¸w|‘‡†æx'ºB  =CZŸ•üˆ(ï]eë‘uªÞI[*ꮄŠ>(RóÛ„ž"ÙÊ?Zü#D9TôA‘|¨(¬è®„ŠžŽŠAD†çaƒ·"Ã;¥àº1G2¼Y’á­»w$Ã;†£é?àsV´éG¥Zgù’ny,9³Ç¯~“® ·dA¸µ!‘pë@2N(Ø,Þ Ò”ÝÏ4;HŒïs,2ø™z#r²²r’6YY¹È0z"Eóž•¢­½!$Eó¾‘ „ßVŽ™¤h’‘gà (ïOŽ¢=V¯ó¸Úè½–C{8»´¢œà@j¶¤œ£¤¡b†ÝsY ܆nLÄ_’=däêÜÝdy» 9´;ó†ß¡,÷³I2Ñ)üÎÄÆôXÀSü™Jä­ø;ÑŽÏ[ùwþäï‘·¼œ Ç²1ï,ËF™Þ;é˵ ‰óïô’ùæšÚx#HÅÈrÖâs>&¬¹Üεø|#ÈâL»EdÁJÕGÆÜ|3+Aææ>ð=17?Eƒ¿‰ØšÈ’¹ùV‰sóiJ{17?– i½œ‚¹y~î¡aÌÍ·c"só)˜›ŸŽÙÖ¯Ó]*™›o¾&ÈÜÍaí7 7x)íîþD'<¸>A}ê‰|æÌœÜ2”)²˜¡ÜoÊðÒ‘c‰ï|`3”o[†rG‘–)š­ë†;A:!O+(éiq1 Ég WÔ¡çż¢TBŠÍë„)4¶b^'êãÄ–ÉzîNYϲõܲž¤ar,p±‹bžÓ)p±4ªJ±î’â­´XJòÍŸÓSP'J.-8—ÙGÉ¥ç2ûhøÉeöÑð ’Ëì±(¦d@‹«h9‘Ñn@³ Vp”lå‡Ó15“!‡‹ºÑrŒÕU/Ø¢ìürƒRXt|+äG{¤àxj%ühçVÉöÑK `”í‘‚£T0G_€WþXžm¢œ8Þáγ[ÎM*ÛÃÐð¡y™”¦ùþEü1ó664må˜ÉÛ04­¶Ü!ZohLj[¶ ˜%géæÕEh´œ¥›W,¡›8¨ÔS)5 AòErô;­ä‚œÈBcÙíÌ–ž¿¡yæÒt™¹÷ùñ1÷=A*&7üùæRŸ¾qGIy~û{{г³ ,(p…ÆËÊy®;êyû}eÐ>`Âÿ3máCxz<ÙÂ!Y~&[øÐf Ÿ~gÚ‡&V~çãBìï„-|äd @n°Ñ½½¾&áçt_v»o‰ß@nðŸþùß/o¯ï¯ÛÙûq­Û¬C™ ëÀo\Û²ëϽ”߸¶•2MѪò@jÖ½O¥ÅiSu´ö­bÇçpßÓ ²ôŒ62 ÈC«9¹ñŽÌkÚ@’!NkRÐHð” G ÚIÎn\3)h" 8eÈ‘‚vh­è+iÇ¡uìžk&<·€s) N¯ 9 ­œ5°æ4´¾¦9½¤æ}IáÎ#Ú Üù”°²¼—|ö@ö°Ø‘ªÜ»ûWþ·ˆv²Ë_÷l†­ú÷cz™²ä˜¶6Å>§ûÏ;Ašb#i„–wv›‰³[h£4–Pƒà@ÝfÒ 8%éú²’ÇÒõ Fº¾˜ þNàÛäß™ùöÁn$oF–P & ,&\¦>e0R¦>e0R¦>e0Rª Vð#¥ÚYö#¥ÚÉ:P©ö@šËn&Æ#Á¶‚¾Ì€-<è1ã‘ünÚ–øLÄxä@ZN³Æ#’ød÷¹É |ÆüÆíÈP´!Æ#R09!ã‘LFLPÁxä|TA¥˜?ˆVI‘cH¥¬fûõQ)H–l†¦z+-íHÔ n?„°ƒÿ‰ÖbX°V>&Tþ­«óåFŠ!ü#š_°bwûR+‚ |âîl–¯]ÈÝiçA Y¶yaé)‘´ƒkÄ-'ôʼn~|v!@¯§«PîÑ1•䃌» NI•U¤» ˆ~\4rÉdÈà4Ó¿ëvR\—§egqÓˆ« ¬ïyw2] Îq¦++ëÉ ‚s¢‘ ªÖ:/ž}â µtö¼Ùws±ßÄè-v‘éµmâ&Ü¿ci¨Ç1á-öM嘹盚Ð#½ï²ï9b/Zýà™ÓPŸ8˜œ¼’ò°ñöÐk& ¼;e¯ÙzþL«ôÞ°#d¦•oåÌr¨Úäa®›üîÇÏÏù>¤âÒÍÁ£ã@r6¼¯ß3ÜyÇI)w!R¦8ïżŒ •(ÙÐרhX'à ‰ qˆw¶šˆãJJËöA!¨š}E²áa`t %û Šäíƒ2ó@JöA7‚ìƒzz—û Óï,/‰}PºólxØ%(ötÔb›uýx¡ÏqмcðŠ|äÆG0ü¢å;Ú…Àk=6þ3,o‚“Éf°SÅ&Ú>…®~ÚY3‚”ú9‚^,œH†ggã fÏùiwÓæ§}:&kOêùÁ3„ÀݧŒ[¤cõwYëB4}=°ÄClåxZ1"W°°Œ¬»„*hl*ÔÖ|—0uðÙNQ[C¬‘Šá˜R¸&‡¨¤z¢8†È…a¬H†"†±êPFˆ‚Κ„a„(謷°À§cFü•é’éK7Ý.¿?2r:—eã±Z¥½Þ²¤sw0¸öXjÙlyØ×qþþî‰ÃZöuåö=ú^þ'SåiKökÓf¿–;ÒäÞ^_‘Ó|ÍË›éKFmófÔÖÑc&Ô𳿜ñYe³%|¯Fm3½ó ׇÑв?ëêúͪítï[ÅTEP'6P\Å|òˆø¥Aâ“Ǧ­™oÐcj^ºsë ’ã½# EÄNæE ÅØ¤*e) DCq  Åéì¦øˆ†â@Z†K4Ò±éPiàÅF³œÿÝ ®]‹{¨ÅFKéPpu‹àÍ^2 @…Èóu»ÛÎ×½¤b4SÈØ!6Vª#Vs<±pén³šcãj äŒôb2+0#bÌ®m—½²ºOM·õï1ä;D£!ØÎÄF¶$‚-Rl»ˆÛXqAŸ¹‹¸ô©qLÚX±mùÆ1icEÄ-ÊÌó"0¶J®KÜóÇpA»´`C×.4£Ik,¶B3š´Æ$·¸B­±ÉËxs‡";ë‚VnÊóRkx,1­Š­åëÄ´*¶V<&,€cë*Çü5d¹vD¨Y±õ|íˆP³bļjô·QÊ–Fô¤ØFÁ eÀsjj† é쪭Ì!‰p•P­íp¢JTJLÓ„yDô¹S¢Ê‚ĉ*Q)¶b¹lö?>ó66boÛu¾2J‹s F¥…Jõix£2LUyÝnãªrTBVbmd¢²²L¿Ó2Ež®¡iQI„84-*Çúåö$4í@CÓzšv ¥Ð4Š´ û…¦HÇ䃒gäù¾-!†Eå%£ dUà=¢I‡"ª öXÑl£";Û ¤¦uÃØ lŽe‡–gÝJÈU’=$ÝvuǪ’d÷HÍÐ;¯ÐšÕv-‹<Ûh>²a ½¶¨ùȆ‰ôÚ¢Öâ1¡{µ©3´a{m3éµEÍãÒk‹ÚÊÇÌ=Á¨]嘩'ueU sö¢_.ô\"²îüÏ>/å±t»=n·¬ËˆÓ¨qñp;ßò¯7‚dld^Q*mD6›ç o¿¶¬§ÒPÞûÑ{|Ì÷÷~"È}³ÿ¿IdÛzEÃpº"ÖíH°Ò—R„†Ï÷[GϘ6¼ïÐQl@¡8šFV’ÎùìŒh—M²z:šV²…Ä;}£J6q¹éð ö\F M‡ñç ~§lk ‚h¤,äµA0 iXêunDS¡^ÃÁTUŸùìVp!Àð\Zò‘¥^÷´ä£xLT Må˜y KzŸIm -Ï$ù¶“K HÈÌ„‹XÈNÍl«HLŸ³SÁP."EÊËZ‘ØPî@ å¶ï;2”;†3˜B%Ð`Ù0ñÄŽÇ %xb½m$üÆgk…®‡;ï9½íîmõ¶ñËzÛ’q½&EbÌX(…M"DÁQysæ™ ’uTѨ‹O:¸lÕßNHÃèëq9(6ìws _Ã(~pA&*9Ý kccT²n¶ÛQËÉM蘚gRÒK4U+sc䕹3QæÆhå (E'|7;Äk‘k†+xã¢ç“GhÛ4Iì0|=ò¼ÿ‡µ5“ãÑcŒ™|?lƒïžÝ<6·6‚Tllkš?d˱U$b«&¤â^»Ô MH®Åùö÷>ÎiJnÒ=n÷,HÅúN÷¸Ý“¥vOwÃíž„Ô ûf°©åÀÇ œÝˆt— Ó2^‘¨eœ…û¹‰› eœ†i‚hhAZV44ãönB²IXy%° G¤Ùy¥º ½ŒL+ÕY•Øä³GÑï%·{ò0ˆþ÷¿[´î^Œº÷oýíõÏœ-Ž›¤ÈaGΙM§Ÿ",§îNú9$$=¦)ÙS÷+v)Ò¬w$=»cÃ./Ý@¾øÃ{ÃIåE8í:/H%g¾¼æ¹®­È‹píJÌ|Éb±„äÓÞ“)!…@ç‘"‹iï$Ð9!‹iï$Ð9!Cy=* RómS\‘HHÅ3WN¤©ó×DE’F•8 ÒJ¡Æ ÄIH6Ô8+q²HÒ°'!%Œ%Ë[sc%NB:îÚ¡k—Öó¨!˜BC~§ô ¨!˜%‹¼}ßÞb/­ëðš¡ ¬Âe~56ý;)\z¬pIHÆœ)\Òp¢à¼Z[l¢Üž¿Öå÷H5¢¡qŽ“^­\éó]Rm¥Å™çy¥„&#jq&¤b: `¼¼ 5O¹ÁkÚiD$¾K–¡¿>¨~AºJB\»îü  $¤*e#θmº ùlÄ·M²˜8ã¶iBJÙˆAJÙˆAÚçúçFT€΂Œ…úgrÒ›×Ø•+AÒÎGÚwŒŸßýKO´ƒ“iÏóëýkþ"HÃÑÐjM7,•zÀ5êÙ Æõ#^Ujů±.uAj™(v ÒHöÔàz· ma,¡NSŠÒ^Nè4¡(í„¢´GzL!J;¿(Ñø\åèq”vBZ¾{5ÓßÉ:íŒI朜Óô¹²¥²2ò¡Û'¤¥Zb*DiŸžR«x}~‘kL³;Ü|/(2dà9ž]~ÜQ‹KBòL](5˜FÛN'$ûIÊ ®Ù2¯ÒnZ•›¶ R ºªü*U‹†R³ScO)DCÞ'‚”¢!o)ECÒ³KÑô˜É|’Ý‚Ôr^Cj÷,H9 M¡†× ´xb¸eÃáHËã„Æe‡'pãe$|L†ð›(;Á¢ÚD..ûÚ¦ÄàJžÆWm¶ [i‹ô‘}T’Ý" <3 £¶§èçåì×k¾vdÔö´™Zm?§³[Ž/:Âs£¶å“ô/åҌ߷_óDϾ3KÿÙîÒu—Ю³b÷:ÌŸ˜˜ÑÇÕV±6°kPò„î’“ÐX²Bƒ•.0d®^ÖZ¾Y?Ó%“u2–a–/¯ ´¼fƒŒDgìâ e@B)D_ò˜w-“èÑÑD„TL¨1$z$d!Ñ££‰ iØðPØð:9<-™œbS«fÜdLÈbjÕŒ›Œ y”÷­)¦ÈÅù”gw¼ïã}ø~ùÕ½ÂïÔLFÞQ0¼ä¯6D*? ‡M\ßÑcšgqýZàZÅõ§cÚÒ¬8ï³b~FFR÷¬³bO¬º­¬P¨ñÓ¦oŸéÙ ›0õs:»e̱!…!!‹³â¼ÍŠù+³#‹³â°ÏŠôì¡´áíiËà :®9ù®ÿºÂ˜·ìÖxA^çátLÍø¤á•C7JzTjp^D¢ò…“×ɨtã¢@]C­Ã„dš¡d{èIóˆ×`¬›ÜcwsÁ+öŠúë¯XXÂÏN]Cß#od$|㼕øöäÚ0Ïw_hÅ⽘z= ·Íqyöþóý:å••÷|Slì??†¼¦õ^Š&_‰fùìA^3tyóAf§ÃNÊGIc‚wg@ãaÌ^òscö’ÇÐx³—|vˆÖeÌ^òÓ MÅìåtLÁì%ߥÐTÌ^NÇÌ^N¿3”¾G=6{IÈÈØ’ƒ_ë‚äÊV‡òVAÙ©ÇJœYÑ<òHZÊBMÙ‚,E~CÂé;4…lÙ­éc¾D‹Â¹¥Û «‰@Wd+Êe¸K\º£$Ìé¤/þ“Ú'G_ün1"ÏÉ!H }›QAªg‹¡ÕFY -È(Di#‹¡„,Gic‹¡„,Y -Hd1”%‹¡±ÇC iËñÜÈb(!KC+,†Òƒ¼±ÅPB¦jC )X =èÙ%‹!x‘x‹¡nÂCªJtØèïtÔH øÞèR96gÙN¾ùÃvóóë"Û!\ší–ŽiØð;XÒGE³Ñûý–ö騥rwBz6üîëtí¡8á¼ aׂä­Pׂú×4ä³+¡ ³Z¡æá$DÏË6õm#o…:¬V¨ÝL‘+ÔqœúÍ •ž·B…Êä¬P÷c.ŸezÌ’êŸÞ§Ÿ™"y+TؘGÞ uجPO÷³l…:lV¨ð8+Ôa³B=•E‚9œÐ& aXð]ˆ¬êú]¸< Ê­è7Þ5+ZÑi}颓L>!´kAz‚û` ²’¢ÞÃ+Oø•¢W¸ËqØS,g‚4‚0!Ÿ=J^" LHHÅÅý@µ¶Å~nÏ_y´ªo›JX[^5µM+H­møFç@ê-v*#„«-iMbmc¤ç¾,×GŠä'±$×JH]vçž—õUOÉÊßÞѵ†pµ¶/WÂU7dpÕ„«ýÂUw®NÈPPÑ.Ë0¤¢]–QÑ.oVÑ&dIE»T´ YRÑ.H¤¢MÈ’Šv$ùŒ i™f4¨h²¬¢ÝÜ':zö‚Šv¥!mB†’OÅ€U´ YRÑnמU´ùÎ *ÚÓ%U´keT´Z6 Å–¶q’Ùã'N¾b¢·Ô3&Š»m6QLHÁD1}h¤).C±‰bBZÆ@LÒ±¡ç¸¡7le¦anXÛŽO¾Å£Ÿ¼%AÕOügÄ'o!¨ú©Œ0t÷e÷Ï(žKåPpØ‘Aª’gì°Ïá~¢-U¡ÐMŸ¶m¤BÓ8åõjËÆO¾©ð;«ñÓùUã§ó]âã§w×Ô¤0JHÃÅ:Ca¤m•PBÁù¶Õ’Ö•LÛVˆ« åͶµ2>I­«0à. eBÀhù°æ,³Mävp—?ˆmäÔ”{;–"Èv¯Øäò'E—ÔU°£iq´qi gW²'Ï6È!°hD;ƒRsžYý-dc…vƺ…Ïã@?Qô·-ü ×ia$™Ì–µÆ±[øÛ¶…P¤å{²=ýŽk‘<`ž7¾Â˜…;d¶pf̶‚;âL4­‰Rh×ú"ئb#“Ÿ¦m*62§cjÆW€mó‰$¼µ­˜® ¢ÂÖ¶¬$| ’ðÖ¶lId ’ðÖòûHì[ËKì"±o-/±Ÿè Ð*¦$²{˜£Õv\,l$ѱšÛv-Ï}Ývå7g“Ïú5ÜÜz{‚dÌ‹Öσ"u±¸·m|àŠÌ³[o>ûºñ™(Ò¶3ÛÍóéŠ\a7ÓMÛnf¤HϵYñH6¬[ï&†Bï‘ÈÖ³éÊ‚tüfõ¦í¶õr/¬­=áArÛÚ °F±ä¶µ¡&¹½¤fýÛa®³lk»Kh€Í Ÿ¬ÒÈzÞñîçYÛ½ÄLË#ĵüΔ0ÓZ× w‰”nœ’c¡ Ml÷ž\[ñ¨s¢‰ bgµÎHvvxäŠIâÉ&îïýúB‘ŠsTFOÓ91ñ|€¹Î9ñ~‚fªu^v½¾ç‘ì<ï~LWécvÛE¾ØEy U'dŽcïeÛúFàÅ‘âžoåŒdßÖRéÓµ{UK¥ï ’O‡ï‘ײ„Þ¯åLgØñyÃd%w4+9!—þ ö’cÌBVrB~ÿwÉÊÉì°ZóVÎȆõ’wŒ*dûn"UH[ʉ†4m¤ iK9Ñ`é†T!­=:T»ð^®Á:Ä{ñíá}祷úú²‰ÒÝ‘( c‰«/íÆ¨ª6éŠB+³/ ÙÄf^ù%Õmzæ¶A³¦[‰~Ì%å ¥† x×/HÁs¬}œŠUSÂü¬˜®5Þኬh– lá68Á,w]~æ99HIÞÇ/¯ÖÎHÁ¨ FH¸µXmц ¯.2JhëÅß’Ýo¢ÝnlDËVà*·±•}æaöÆÄÿ!5=-"SòZ–dx¤E|À1eC¤Þލ¤´ˆÇªš@2,…¯{ý|vÍ7ÅV+¿¬°o£–Rð{´¦ELé6öÛÑo©Upí–M­Z¿†]²ÝKHÖ¢­Á¢“,š7XÛDÇØ’ ÷lѲ|¼‰Í"¤`wÉWÌ"àÎ{Î,¢›ˆYÄ´¼j~¦¿“5‹@tŽÉ™E }ý ¼ÄéÚ‹äÒžØJ¤;Ï›Ed)~‚ f§ó·¼@ §Š@ § ¼Jd¡£¼=„…zŒü‡fB®ìV5$X7þ„ä[HyI¯šVvÏýzÅÇà&Ë‚|L%ÿ£C5J¾ö¼¡P ¿å6ßÔŽ"ù\ø¼¸RaƒÕzìŠ cÍ6ÕX–m5¶•j,˶ê ÛJ5V*-"¶•ÂtÄÒ¶ =wykÜ£;/†ø ²•j|…‚ wÞKEÔŽTMl3S^´ÀgN55[‰‰"'Ø|—ÚFr!CN° ñÇpëÞâ\-¦Ò¢Úö™Tp˜,s⪋¦Hâ1u펔ñ­ûœ¿f‚,§„ŒýG?ÿü"HÃR¯a^Bü±¢dlúï—û¯AòãðŒ´ÇsbBBò SèÚ+ SèÚ 5Àô¥m…sB*Žèô˜)Ðcò—K[Ž3ö„s -O Ësˆ¶ =æ[‡U¥–[Ûú®ÖŠÍOÓK62¨«HT1Õ/ODú§´ÔÇúe¥CM¿|'H]ÞEbý²‚¨bN¿<$¯_î;zLI¿|#HA¿ÜÓkôË=={¹ÄDôËéÎõË=Ñ/'hQ¿Üýr‚*^à ƒ$ʯgÖð*‰]yð¶KÇŠ†÷AY’m:k4…vå¿yºK\Äûmz!HÅpPQY)ŽŠyŒ’ca+g„ÜØ\µ 5ßM ‹«Jþ2zšà´ÉˆÚà˜–µ­UP,jSÀ®dDmùi¬N%øntŸkÅÊTŒî?à˜®ÒËȣΈF÷¨—¡ŒÐ·Ýáyá­›¸KAÎÈaÔ…ã=3ÊÙÝ ©ØuxFˆ ù¤HŒÄ•m#ñÇÉH\Ù–3_ŽùºŒ¨ë FâÝÉH\!."“öžž‘U¢£2*Äa.bI霹NJd:—¸Çù=²ºÂ=~ÐcjNi Üãiجy!ÖHîÇHò©¬­H>;Š$Ÿpí–›çw›,ù<† ˆAl+e˶ê ÛJYWKýÎWäå\ø3RÒjå§YI{‡b ~ú?ÖH»|—°Òá¿gä}˜àwFqÜey¥C¿fHB9ÈÆ§¢ôÁ×0 Ÿ}I¡º§óP!—‡&´²M4|¼B+'5âZ To)ÀIûçlßúAWú8ùŒl·}œÀGÉôtkŒSÔωi»EF¾Kô=BÆÝm3¾¸õ¹Ûnÿó¿å˜;qñããó×Ö±Ç Aê‚‘`’åcznûžýï^ Tg;Š'¯×µÙŸ¯©Ù b4ꂘAŒºH!Ô˜{ùŠ¢l•ŒÆgØkdÔņeÄ ”Ùøæ%ìïJ¶ÛݱÝÎW[¹ ¶ØJÆ×Tèˆ-_ä¡ýå¨D¡Úôêõ“Ôs½p†ûéíØèþPŒ†1Yg†_Ënê×L%™•rÿ1Ã{ c ³³ûýÖ÷/ixiUK’iê åT´5Ž_!N´t@¥Å(tt¤¨èY#‘yÉã"kÙŠŽ)~¹pk&Æ #ŽÉ—”7ž[ÞjÁ õà¹õ ÙÊé¥yƒ¦›Vfp寶nTÍ~&Hn¶AÝð†™H4Ïéݘ{_yk¬Ù´÷n ¶xä„DÝ~Í@DÖ[Œ–8TY ¤Y 4 ûéD¦ŒÝøJ´ºÐˆûÏÏ¿Çü™²’H¥ƒÊ%ȧñÙÒH¦B.š+1ö$WBck>š+±åJhdÍGs%Ö]9Ε8†uµEWä*¹½"!Wâ„ô¬«í×éÚÓ’C\/MX OÒÔµî?$¿ƒÎD­‚lŽwcéûŽÂ´ŠrhÌ!ºC»™¥uSá‹æ·X¶%|Üà‹ÀÚîW„ÖŠ¼-á?ï‘Ö²=]ÞEjÌ™<5m²‹ÔÚTv‘pv#ÙÓ¡]ä4|c(?MmE.h imåH;ôÜió±»ÜóÙ#o½;bŶQŒ›K1ÍvÇ—+ßO×ô­ÕX5ßO×V%ò¨Ã»b¢Ä阚 ƒ¯ŒkeûDØ#8É|5NÏo±Ól€æ‘·˜§©å-ÞRÊ[¤Ç”ò)RÊ[¤Èâ¾x y‹Ž¿qÝ )å-Òkç-CÑ·ÌÛÑôtÚ9NO·lžÉÛ᜼ÛEãÓ‹›èÛáB…£ǶRrΰ‘sàÚ#¡VbrÎP+5¶O,hÃÙãµ2×C¶¸.xâ3µ2ø7ÊÍ<¤-Qn†ró Çdk,hÏåâÓX¦ÜïÙ@û@V¸³·—ãùPMÕ·2Ƽo+Õ˜üÕöJ¶:„jŒW²±ÿ#¿Å^‹Æþ¨ÆB¬# ±0{ã¨÷3GbµÓÍ1"Ú[F ²ÎŸïËùýNg1HêZ¾þ™’Pë@žÄ ÇÙç¿÷{^3xN‹}ØÂ~ó4ÿd ³=aköÕŸì"}”ÆÒ-³}F´›àÙ>»9ÌóˆíSN¤ªYÖO)¤Îå1TͲžž]HËw>(9u.óÖ¤c-Öáiò†›Å:0^´l‰Üct0›Ü¼3 ¶b“ ÷³#_®P‰1l‹{íÌ[ÓÁ³ëºž$…ilóXÚAp—|-)ìNœï¢‘kà/=í&Ác¾Ÿâ÷¼GØdŒ=AÒõüჴº‰-Ób:fl*á¿ùÎK†[ p~îØæ±pí¨šuÅFôªX Ï "ò@ù/ÂLä:ZN¸2>¿û—ž òÀBä’ñ€ºáï{tBcíEæy)z9Í-[ÅêXËæƒ§dÃgôŒbÅXž‘PÍ&†ùF )¾!^áCŠ×³#ö”i”Tu_¿2sBjö+sHo©Ø™¡ƒ³kVrxÛ¥å=AÞ¬5ÓÙ}+¯ÖLcj‘^ùÎ[I ‚ºÿ¦©1ù.9ÙÿêÇtÂJ ]?{„ìÜR Ù™ Rszº”?[49ÀƬµ;™µ *˜‡wð4#ÏÄ#¬ÓD.no-ï u²!n{$nï1læ¥?Öl|íN²§@k0ÓzqÅ5Ó9Äd„QWs©…gå@8{Á—:‹æ¹N5ÒN uÿâ9ä3éþUåÏÉù³¡îÿ”ºÿùŠdç[èþ¥¤û‰ÖŸF=UJÏáJY Wº¤®4¤®D)…+ÑcJáJw‚”•(Òs5ÕÇãô;»¦…·CI\wÌá1ÊU¢EáìŽWÖ¶¹Qž_U^±Nʈ¬$Ì!7*JœR<Û°žo)Z´£H!”0_‘nå+‚µ¢Vò:®H늞 ~§‘½rÓ`×µB0ìzŒ¶22ï;Œ–y=ºvdž÷D3bH) î‰fÄœBHqèð@4#‡žB‡{¢1ÚKq{¨ckt`;¶=éØ*ñšyöÖQÌ.‡½¡1gwÞ4ÏÜWøjßÇGþ¦+QP³2FÉü:X+Ê–V¨gjÍ@våÆÞÈDkiŒ•D¹feŒ;¡è-6NöÕÏÃrcŽU¬.Œg•fR918 ód¬4ʉAŒ—³±ÒLŒ•Œ ¬±ÒL*'ÆyÍ++EÍ2TŒ‰’•®3ئ³Êß8[ñá„ßi[©RŠ”³Æ*ñìÀÈ2VW´-pL-:d b¬‘ÙSg¤ÄûMwÞZÙ"ìrB–*{ía­ãËE4Ðê–«ê¤ò]r²AT '°NÊ8^'5Њ™«ê¤22Èç·R±ÕlØI9!,•®çžÀ|ÅLfãE×¼—‘ºÿ[W(_‘¯X€Â*ÝW,@Ñ™Jk~‹½­„ÂñŠé­¶ßbïä ¼ÅÐgUù=òåöDQu kjš¹…RPTÁ–[ØEÕ´ìÊÖÞ> ±éšJ,`¾K¡©Ÿ²•ƒÏ²Ù„J˜/Ì´AUBó»¤Ú/VëÜ©/ÆVægžb¾3g¯'Z6xÎÞD´l&𜽞hÙd‘³7-Û4¬]'Œ¥`*Z¶E Z¶Ò³v_§kl f° (Ð_pЇ Næ×¡1ïe~ìLƒ¯hFàwÑ­Á$ŸZc QfÁµÇ¦Â1Ë#9¶¢“:; Ž$ÜÂn"ÜBƒ”[8RÛF+¹™[hPpä“ñáI¹…ë×s d‰[¸]p ¤À-ìè1=gº Ü úâÍ/Uc¢æ›kMu±’ã–½> á]ü{êHg$Ÿ“©/÷’RŠG®{G'ú3 99úJ°)œÝËêXÛðî%›×ªýÆX3¼$ÿçUʼnbku¶i+¬éÚmÓÊö¼yf8|k6ž=†éA£ú’Å)‡O=h\}µÈ¥ÐƒF5ÕÉõ O÷¤‹<†gÍ©E÷ØsÙÆˆöû°3µyÒi8›ýpûÌHx@{uôL?ÖUòßW‚T%KÕUø¿l¤‚ÔBÒJFºZÒÊ Kå•#:˶ñL*ßã”Êg—ƒv–»S*Ÿm<_·!©|¶ñ²#µmä^BÆJ(¼GU-[ºŸm#DlÈt—Úš¶%䶦m9S³!¹hqÊáÉ–¹'¶Ì¶U¬-óL¾ï¶UÿÛ2ÛV±¶Ì3±e¶­bm™gbË| ‹¶Ì=±e>޵ )R²e¾dÂ>2R×Â>z‚TBP¾v#özºî„äsÁ¶VrMDuÛÊ»r¨œØÖ³ µhp,ñ·¡™VÑàØVÌ BªaÛÆJVéƒ"ëž×®šK6SÉÚUèwXUñÕ„g¤T-@$Ý%¥k"ArI”È!Á*SI¢)RpH€³9‰2;$Xà]”“(3Åï‚qH8]H¢„ûi*I”'dT„ifPÔSô¤ô\mxòµ;¾HzåVñ½òôÊ­â{å=é•[Å÷ÊÒ+·Ê×X²ùìAöî»À˜• ;@F9Ã.ûìYeWäÌå°ºa™¢3©¥[ÝpºÝÕév­n ³âÑ_f`dÙSÒß±^J|›·û-õa­V|Çáºv1Ò~ÓJL’Í Fä@ÖjøiíÊ/|L[Ѷä÷H»Š¶%?wí*Úxš¾¢mÉï¦ö²‹ì¹t¨¤FæÙF99v‘:Êëù¼Ûµ:²LÑ™¤l[Ó°)Û3]Ï›†eŠt=o.1]ÏKLÛ­iåõ¬iàê¹ìʰ3•ï&ÜOSùnÂH6šgь۲.dcžçùý­3RYc™™aïõ ™Á8VÑ¿,~ÿ¾ÌïA*Ö‰VkÆK®_¤Ø/Ôý·& ±_Xéiëƒ*='¥ç,(=»“Òó@ò‰Ã0ƒÙ¦Â[˳m˜žþîFˆÖ´Ä½„êÊ{º¦å9'»W<Œ:«d¯xx;÷’]×®e¯ctv-{6Â:ÙÙûÝO[á˜Á1]…c–gZë8wÇu½„¿GØ—£W”ÏjqE7‚”⊂”âŠè1¥¸"zL)®èNR\E ¬cuœ³PrHÈó<Ž'+Æ;æ»äšJ¼cÉ®©TJóÁ5r¼#TJQ@Ø“SèZUóìíÚšSh>¦ª9…N©Š‘¦Ëì /Öi>Òtì¿ç!¯Ò–¸[x7áŒÀÝ"» ÄN)p·ðÁ‰»…k¿È“äü;Â1³Î²¿s&3ë,û;gÂ1;Åß9ŽÙ4¼N?Wž«(V`„øŠbÞ_óÀÌÏ(Ô<0ï©Xxxß]¬°áŠjÊš<Ïûš²&ÿNßHê<ä“o}+Ze5®•|9Öþ|e€™³%h¼äßÃcK<»„Ô²³%| ½‘=EÑY‰‰‡WkÞIþ!éyÏÂW´>p|ŵ¶†øŠÖË~Ô¨äk1jðÜc…•”‘¡£–ï|cÔлZ±ÃˆÞ÷ j‡=AªBM`«¾¢•?á±à•ÿ6â•?ï8±sc`,#ÇüÁ×0ñ-F+ê`+3¸óVöÙC¿ÓUr¯òX NJ|ÀÛàå,ƒìÌfƒ—f†Õ½Cg0ð1³ˆò\9éðê9NÐÙ¦›WãS4Û`~Ès$®èƶÉ7R¤äyK‘|$Tt!³†ñ¼½Ï)yÞÒc ‘|ùíH!’ï„ ‚ž+ÿNÅUtW¿ \ŒZÔˆƒÈF#ò‚€!l£­¤nÁ]rrêTJ£“ü*‘ºÙ²~Gö:¦—çtçCÍ5q"H>~]{¬ðÁà˜QÞÇåú’køã~‹0Nõ¥©Ø=Wf°HÁ~:»áUÀ|p°CyÁý#×(^ AXI®Ñr–Vf%¹FWjªpEµ·Ž"y®ú¶’s—Ö ®±Â·×~]%§Ggwœ Ð:3  k|Ï*Éhð;Ã{œø`®‰5ßÂô;Û¦æ[x'HUvbÄ>¥®mùµ ñ)uˆ#ñ\}},‹ê!Ÿ]LtB+×êŠó@~7[#¸Öàv‡ºêåT¸<’[[ aÐcò©p9„Ý!†2‹Î¡ëÐ]ò‚Ö=»6ˆZKpÏsõž~¾öXɤƒ³G)èd’YCk,ëwv=Žôôie­ºßo©FíT+ªKÐ\Ç÷ôוZ¥;ÔÓ/p·P¯Ç)ø‚&‚TBÊI>fM}Ÿï’iké!ùìªÂÌ«5£x6]ÍwÕéúÓèJ^dÉ¥î?ð‚ËËÞ±|&ÕWg[}íIõÕÇözÒëqÆ =ÜëqÆK=Ôë9\õz¤áÕ¸yÍ`Ïå »]E$ó¼DrºK¿Ó¶•|üë‘Ièn‚÷‘8ÜŠòµ[]I«Ìo‡eÙ)-7%{¼8Ò©ŸäÑ7캗ûOŸ Y„ÿùïÿþ»}?Õñíïò3Qäñvü/ä#-½ÿýÙ§•Jú8U5רòïÒ䶺øgÍ+{yMü¥Ë¼•JÒ3iªÝ‰æl¨8_Á•üMKQL³B«_!Ac&þ Î5Böh‡Ô¸Îµrv^Vã:×JŒÁµöœ‘²K¸Î:§¥7ï"‘”žËÌǴ⻉öŬGAwÊ3uŽå‡lœh„8Ï1²N\MçÃÕìN\M'uWéŽwØ¿Úpí¾òÕ†+òT9A5jçYžêÖ‹D×î[·HOÊy%ßÑïÔö)\»–=a]çEŸ(¤‡uÞÖr‚ä˜xëëÕ9Ó]¹w“ìʽ“˜xWî'Z‘ð^ÎPƒ¯¡_÷Ýymjžö=A*A”ie/YXÛhÇÏ!qN¼ö²û=Ì´ZfdzÔëPá@æñYЪSd7¤*÷e0×Ý›F郳›VÎGÈU#oÚŠSh¾KFUò óH6JêËàÕ¯Ñrâ¬~®$ŽÁÙœ8–R±³ÜmñÆÊ<@xŒüëVv4Üy>nØØÑpE¾âïß#ãÅ*ñ8žÎnx¾"<÷_®=ðúbº¶á{л8Ó65?ÿ;A{»3éízÛòÌFºV´Šg6Òµ¢UwÇ|íb·»;z+&6âñi ×ÛÝü.Ðb«©FéÝ´®’®xB*!W(#}%]1dë9ЦrÅ÷3°½È®I·šö"gºV´gKX]81ñi½kky(w‚dŸ;xuz§äÕìµ–¾›x­èŒ°JÇjïØj̺NÆ«_çjìùwúšûLR&H¾ŸAæDÁlãxÝÙ@¿Å. 1Üeó¸]L¯ËcÞ75®û@|z]î²H!å9_»oÅ™­Ö|%ç.×*½W<Œð~½9<ˆ£ëÙnuö¸Î¿ÓÖ<®{‚T|š œfµ ïd®;Ì!ÞóÕ-£ö>Ô´ù˜±’pçOÔ]}>;ÖŒxIáKÒÖ|P•´µün%çIÁÊ?hyþ„}qÐ5•A>¦8בk·,r¦ûŽà*)ÏpE^Z¥#Æ‹¡’1 ×.¦rà5ClØŠÙ@WA±å÷›t[黉×ÉQþr'ÊCƒáäçQ}.ÃâFå ‹Ëý×5³¸¤Àɇßijô˜–ýrÁÓ|È7¶ìø¢å×Kt(dµÏ„5çíê@{X»ZΆÈ×jÙ7‚”²!è1¥lŠ”²!(R`ïçoq öþ )eCÐk—ØûùiŠ&ô4CÓÈùGùi¶Ó”ù˜-?+’Šnh”¼ºÈ+ÕÐèJ"^7$ï ŒŽiÄÊÉãŒäSxòš*3ÓUòãàŠj)QpÌJJT®r„ÆËŒë¼ ¸'õüC{„ÐD–K<“urhùË•Wé¡­¬.àÚ[UI[Ë÷³U•)œ]W’¼ò˜oµPuÇLÑÐQÃû¸€õ°åœ‘>!]-gäFRÎ=¦”3B‘BÎH?¤”3B)p9:zL)g„"ï) ÏÝWn©¦}þ±’àÇŒR·ºƒNPMÅÿ3_»j+þŸùÝ”\»7§¦ü;•ªd½ÁÙÅ7´ë ʈHØõ%®¬W|P®ÆóÏ×î…¯!®œ*¾ùíP±Â:οS7Öq¾Kº©°ŽOÇ”’îÉ9Ù¢|™€;båÌ…ü;«™ 7‚”2‚”2è1¥ÌzL)sáNRæEJÞ’{¾"±vgAWÞ#XêJgF²vâÙѼ$tîz :ˆÕWØEÁ;zO)…ûYËYοÓ4rWæy#y£áì§`Ë:î ?9]á'ç+‚ÞYagŠùÉRóŒ—ü#Íu¨rŒ•œ1º$ÃÑî ]»¯°£óø4¾ÂŽÎ³"êwgýƒ" ËÈ‚µÇ'ʨ &ˆì>4’MØÛ]J¿ÓòþK3á+Už<æmSá>(’ë0¢´ß`Û g/ßO«*œ=ø²¢ªCH-VÌЗËÑ' ¸…ÁZ!3^qo.1^òA]¶2ã%”^Z'ã%XWãèæ³{QÈfo*‰9p—¢Ì‰‚gädïÓFÑ„–’}ò]rmÍß;#U…ÑzB ™5€Ôâ­?‘z¦ø~:[©±ÀÙ]%…ç„2Aàì^Îú’“wRhõë‚Ì¢õ¼ ò Þb+¹êyÃÞ¼¥ÕÚ0R¤äJw#H#xÚ§;§ý Ù”ônúZή*I4'$_ó‡§É'qïœX×y#sN`fðFJÁ_XoåÎ:»«ä•çQç½¼¢†9Ù1sÍ´Rn5ñŽ^öòBg¼ö†uÔã#ɼ!(Á3BÐHøºâ™gÅ +L§ü4ƒæw¦$¥4±^‡Xs!Èž9èñ‰Ìûʳ–3È 1ˆRò-ÄÝÕ+³ ¼q±¹1h«ŽÐéÎǪkMO‚#¥(2Zñz)š [~§•× è~Z¹‡o\tbB+úvĪ'óDŠÏk—üÖÈê"ÆJ:=6¸ãƒ›¶Ò+OÏ=6Jž?óøŒMÅ!!"ð;°“Z× é~Fì¼Zäj±¶6¢ßix mžäcZ¹V‰Žé*{™1_‘—ßâü5ŒM¨yS ©x?¸óQî¡À¨k›Jš@~Fm[a›çgÔ*¹ò #„ïipLq‰¾Å±­eÀ1+sŒ¶2‡ÀÓlå¾áˆ~g¨ø±À?8f¬8¢d¤j*½Ý|Eª©©Þ2²+{°NŽRö(ùE¥+5@šZM5_»­UJÓÛ¡*é´ð)/®:ô;ƒ˜Æ5Õ¨Be¥šÇ§ŠFk~šº©¬Öò鶖혮H+ñûŽ®M–<ªFp?µ–Ù`¦ÕFÜ'IÔ¶–„8¤àwÇϱ²‹\;ê,ï‘·½³¼›óð3Ü3¥„ÌIñóËðsBÒcî”üyÿÞ rç¾î¼ ìt[ÓóÞ߿Ҝ×ËÛëÖ°ýø³&SÜæËËA† ùïÿþ»ÌòoÛÃüxß^Çe‡tº¢ÙËìù¶ýÞ½¾ ¿»ë/zçÞj|¨ØäÏŒ›€Ó1«L¡™Ïk˜w‚ä>¨X$äÃ-±h*!ðÊɱšø.-.jÑÐh±È‚ ÆTZbyª5¶ÒKã©„ Ð|vW RñöÍù¹³œÉ¡B*…k• ‘|í¶‘Ÿ&ŒO+owÑ'A4Áœ•$² TøÎc 7­˜uÒUÊpp?}Mžjâ–üÜ+#VA¾© ¶'‚T‚#ÝOßVHfùÝôª’¯Èëš÷NJ0qË¿ÓÔLÜn)™¸Ñc ÂB*=‚‰[?¤dâF)„Q¤dâFÏaOFÚŠPž‘cÅêë—kYÚäâÙp²ÛÊÍ~ÜòÙC¥$‘ß8_+®åññÝD_„ÐVÊ[yöJ\{£5mÐò*æù`*Ðü¾[1%ÉO38a„MIbpâþ}¹‚«˜’Àµ;žlD¿ÅÁW¤_pöP)kæñbÅV>ØÔ¨·é±m¡ò—Îη…Öû¹~ßÓ[,4{fkc…Ä߸(¾ÅÈR?FW£óæ»äÅ߉ö›1Èw 3Ê-Û4æ]Ó4•"à1+.H)˜¤ªYöÜR²ì¡ÇÔÜœœ L i„6Æ=!u¥] ¿ÓÔb ‚”b {‚š=Ç[œl»:º)òì½ lR0Âïô‘m7¤P‘èò5#ž9!c͈çNЧOåkHw(|/ÈVn$Œùη­fpA£®U5ëŠTB?ÍÔ/ž:wp.ïÕun–?Oõ8 §ç!Õjö.ƒg3²ŸÏ¾GH½ —ºâå}¹ ²ùª?j|ž&özNÓõ,Þ}÷vü˜ö¸ö»CH‘oçëå²T /ýåãÒ^.}¡4]ÑûívY”߇û×{õõóuCH‘Ói®‡¼}õÝ×çרá+ZšúsÿjúùÛå²´îÞëñþþÕ~m.¾\méþüYúW—ë2 ÷¬NÃó{èñ½/Åê`÷gZF¦õ&,MãG׿Åa…Êú÷ïizïÞ—·yzoõm8å/d…ªÕ™îßÿÎï—µ´Y7§¶ézsÔåIýY¾‘÷¸:ÝúÓï£ÿ¨ð“*ͺ8þýߪdz^Vz>O§aµº:7ÎÐ÷ñçãÞaèò°þûï3´Z=ü&èðö{ûúª0Ô3=ætüÁXúžMqPaLß³)*Œé×Mq0¶A*Zf2e_¦äb—LzšG™RZõŒäëÅùåcûX€˜6!yzTŸWg²"fðëVðy7ãË9Î0ޝZæÝÎx¾“”ã [u%ã3²åQý(^»=b´¤ûÉŽøFKD2[ù×ò5‰Hf`+_»:ÁHÅÔ¹Ò¯ëƒÑ™Ù[sÔM‰Ï0‚±‹uG#’O„äÆïâÊ`ýÑøÝ€‚4IçéŽMÒwo9’ï’;å¿~ ­šï§GÃjé<åѰZ‚é¦$¤:’ÌOHÍŽ&¤îTD’ñ:x?E!™? ¤b†§Ó32ù~Úƒ:l¾öƒ4@ºƒx=Ÿç‘€bºv_ F¤ïÈ—Gõ!MäÏHq@äϿΙPµ°*ÄwÑ’7ªM}¬ ÉŽLÁŠXqð®öÈ?ýÏéýÙ}¶qË]´Œ\bëï yÿü¿[„y[ƒë y¿ßã[kdûïœ-ÜV Ä”-|ÞÏÇo? ¤BÈ…· ÏáÚ ¤†Èja6ÌȦn¤Èé席¿~®¯u ì}¦ÏÈóûû„œùÕôÍçóùñ8!äšüY“…k<Ï÷ÛØ~ö„\3¿3×mzDKZ1ߥá÷6|ãkH€®IÕôÞ›ßçwwÇÐõ)ý ¿¿˜ÍL¿º]¦ÿ…¡"B§‹º­§:]Ô”. §Ç7†.Ïi˜BõÓù=Üý ×|ŒŸç挡Š&¤ÀÖ»‚A~ñýQ ³,ŠƒÀ6.xeÁ«Ãäà®,ÄA#/óP-·FHjëhY(¾­Ðe¤æÛ é~$ùëyÉ)ù&&h^—…åKÖà<-?=Îó@i¨ËÏý@i(-áåA3'^eY(7¥+*Þ¥|—ØÙ6Xj+w½µ‚7öl}Wõ阊R¯šY»k„d æù<õAÁ<ÝÏ’1ÀÓ,ÍjÀ˜®Ýò-ªT^.Ë#-ª1!´¨ò¯soÜfK¶Ý F&dyPÜNo²`§¡@r\ yÔN¿®ŽÚ²ñMú¨)œ®Ý‘ãýü,+Xi…e1ðܯöØ‚cò÷`ïþ@m'Ý%y4kŽ)K>«ò1ÙYk„”¯¥à%d[JÁíoõÙE¤b‘Ãý#Å–è‹Æ—Ïî!eœ°zKVKÑxzG„UDª„¼¼¿¯ÄÑis{ÔíÇÇ£GH §¶VäG;nxok„4¨dý·îÞð1mBN¿^…ÒzÿÛï÷ÓB®“`sÁür~_±¯®ïÛ±$ψôÛ2ø=”ÁßnÍ€ï|±Î<Ì]¢÷Piéúúc¨ßùQ dûg-‡šé³:}tß|õ!dõå{¨/WÍ£_5ÔgÍï¹f[­Ðþô¬._ïg UÛòn€>ß?Ï›sÕT²âÉk}æD­”†MkÀ**íAA.­9’U~«¨ôttE¼h–ª<(š¦=q§‰Œ‹¦ù×Ue¨ø3!%»+å’m©Ô‘îa|ð¹5L©¶) £óÚ¨š§¸a£ª„Mä _ «n~• ‰¼uEš~}.Õ·)É®JŽl•É å^S¥Ú“n”|vøŠ–Õé÷SòµŽ9-cVÕý§:Ýšo„´ëýüwþä.·Ð(j»ç\JÀ¿¾vI†¥KrYÍCgä8Þ¿>G„ô{ý”vh~Ûi=Ãw¾ Yb) U–qòg¬Ü‘dºõþH"±GHN"“’lR1³[ñ˜º8šÝz"¤ +ðé3æeAU¿Ô%+0>c-Øxæi•ZI$¦kWÎ|žê Â™ÏSI$b¤BrÅK82.Ÿ¿M÷ñ‘š6­­–v÷€"öÎ!NG¯î__MÚå´Þ™«ŒÈúÞ ¤ÚK½úêwÞeð¯k";Ÿº:@ ¸`,¼{¦µkü¼Oê!ÅÞy6Uýó¼¥ÀˆS¾Îj>ªsÓ7©I¿„´¢ôÅi{$éW#$ÇØÆ¿®Q¨tíîHŽ+!ý‘Wó,ÓœþŒ,&^„ä&^„d8ýé™’–;j!¯½<°¿ËUýÒ̇äÁ¨ƒb\>&[˜€;—1…³´‚{P8Ë÷ÓòýtGÒYéÚýAá,Ÿ§çB@Ч(mq$ÿœå‘L§ Š¿þ¯íÏíý<à;_ÄŠé”Ê„ƒ~4§¡¿~þÜžZ¦âj‚vMu~kîß¾OkqóŸÿfBð|KçhÇSuÿù<ø¢Öâæ ]Î5uh¾ïo›£®ê¿¿³øL¬-Oçz»~¼÷›£®Oê¿p®éœ?nŸíæ˜,Ts¹]ôô]}ž/Û£ZĆH}þ{uýZ u‘i<Ó âö}žnÓj2lNÀgè5å<ÇÓ×óýôÄ@þòò´Bú5¶÷êô[O/"†–:õŽz:ý¼}}n.K„Rô ­b¥ítû}Þ¾6P‰˜‰2ÅŽõ}]«r—Gå3žS*ßÔí7¾BÇÞœO¯«Ïwû9~߆Sµ¹&Bs1~º¯Ÿ·úú5â@X ¦šË#˜R»·Í ¬Ok©Ì]£Wæt³ú[óøÙÜ×åiýùwfe¼Ç§Õ4§~øþh1T+t®u^BMv|ž>ÛúÚŒøfÉBÃ#¸ŽïSŽýì6P¡aªšóo³¹RFè9¼ZÓ·5Ú²Úž€Ê•ÑKLnÕé>\ï[¨Ž=†ÓR?¾/ëåtaÝwÓàû* ‚.‹ð”®Ö§ÓØl>iô¾®Âcsú¾4í†:ÜäX6ç´L;`_ésYü¢Ÿþã§½þ^/›]`yZ—šk8×ù¨·Ëøù‰ï«*ô^hÿõþõ±9ªØ@§¿–£~ïï7 ]Û<ÿýÝœÀóëã範jõÊýw&ñ¬åéj¾YïM÷>\¯ª´ZkPtŠ~¾¾6@]èV tüúê7'`!ô¾P³fh×Ý@9½¯ëÀýl¦ µy`¨ß@×øiÞOÃæÁê‚€Žãù¼–ºnF3t l› Tl ñ¨Ýûm{óÓúÖ×ÿ½UñÍzÿ¼ßoõpm7QÃü´~ÿN üéš¾‚)¬ªª¯ïÍQõO`aðÍk¦ÿú¼ÿnMm¨à.3D¡(§êqöRìNτԄcñ\\æ#DV ùQ]ú|ùz/»…”âk¨oø˜Š€MÇ4G°-B2…–Œ´Gƒ¥ éx’>XVYÁÏ"ý°IZÕ˃Þe*÷¢€HÁ½!Óß}úuÀeúýœk«PÒ¾¿Og„DEúX¨žžû©y>j„ܾ!IšéÜ_1RÑ´Ù|—Ô7…¥>`éÄ¢ˆ(ÍÏ0Óu¢Ó1ݳ]LŽEé éý¤½S%=wQõÁã qÄãŠÏèˆË”¯u…,Á 2 +2|Ê[åcÚ^Azî¬Ìd áŠ"é”ÌW¤Õ«¹EH&ZËÇ<”¶‹o6Gü±ôëöˆ?Ö $GQIHwÄ×}"$Ç×ï¼>j;äc¼Kù˜ µ>G•s)ÍbgžÊu µž|sgØ‚v“0âh‡MHÌÂÍÒ ÓZ‡ØkÂ(Jºa.?F\@îI7,åç,Ý’–D¸µ©hõ‚ R#ré*‹ú¬NýPÕihí‚ #--]vX“Y¸ûr)1™…‹ÕÖJNV#ˆw¾xU#˜¡P B—„z™–jÞeM8Ÿ§zŠE†¡ÇPñJ´›ŽŠ„ "T2Zz¢ú(ïJ×o¢«´Ž{ÔM¿îø|&GBæ ZM DaÖútEö€%Ÿ÷{´Öç_?«L_²UG¹\¼Ÿö £çùÂm½$nkûþ¬»Ôr²– °Ík$°$&°…¦OS]~ºþŒ‘rOfžšÖ‘'Bª 1,Èý÷—gsíR3"kéλ£L2=w§}Ž“BÆ‘º+²¾øëNårñÚÝ£:Wœ:˜J+8$!l=ntÂ!îM£³ÇN@BØ6:{ÜèRÈÛFgY yÓ謷NgŽ-BrÎ!¹F'>&×èÄçÉ5:ŸøÎsN|¢l£ßQ¶Ñ‰O•mtnŽÊ5:7çÊ5:7w€ktnΕktöÊ4:Ÿ›såÊ6:ñ °ÎÍQ¹FçÊ5:ñÛÊ6:ñƒe›àøi±ÎÍ pÎ ”ktâGÀ6:ñÍbø²ØFçÊ5:7'À5:7ÐFg½mtèN£³Ý6:t§ÑYoºÛè¬q£3@¹F'>ýFgºÛè¬q£3@w5ntèn£³ÆÎÝitÖÛFg€î4:ëm£3@wõ¶Ñ ;ÎzÛè ÐFg½mtèN£³Þ6:ÃN\PØè ÐFg½mtèN£³Þ6:”ktâw`¯ÑÙnºÓèl·Î5L-=X{TOHwTO?ïÚmñòýÛ.ÿ}yÐPH¡¥)Z*¶0ÜÉ< ¿ß¾`Ã8^ãäáDÎçWÆ[sKÁ°ëÞAÖÏ-Rn“¤ˆ¬ªëoDðëC( ÝB±º6íu@HA ûa‹”Œ–OzF‡­‡tE‡­‡ôëþHË'f‹œPI:¦8jp§cʃd.#Õ¶Èše˜$IŠŸ¬SS ’$ ÅO–!A’$! !&ÇË>²Ž¶M,4ÉLBØ0T,ç÷yýHºÓíüxæ„N¯ÐßÛ+T½Ö•V• * ÒE¨†Áx’xv·füLçj^Âv€lšûû'B „\ƒ¼ùü:ßßr³ßÜ£½ç´×õ=B*æI·ß"Q†×7¿} ¤x}Ÿ«—÷Ù"û…ü–V/o©Ý±_@o)>¦Þ{÷ÆÍ»ÄO÷_½„´Ä;‚^§,~ºÿŠä8#‰ŸÜ:!ÝK xr›ýÛÓ|ä®CQNއ’ÉyA©»éé×ù.y”"‰±~Ú7|LµÏ>»M¡ãˆ‘zÛù«Ò[—®]ÂhìÕÊã4¤dQà­‹V÷[ÐEëOý㉒²òx<Ò& ´¯!Ö=ÔõiÑoÃç©)Û‹Këöï£Á{0ûºñН(÷'¦W90ëzüýí’hH@:ÊbºW=Bzf´5çA±-—(¤x-Q¬ ‡Þ•|Õí‹…ùªÁq›”„ÞUµÑ» HFï* ¤<лJž”zWcæUŪۨX¤}U±ê6*VéöÉ5PÅ* =5pʳdgYn`ezgOs'?yî$ }ÌüÎþ˜mÊ©€™˜“ˆeαêN ¹³å‘ûû0Ü0RÐÂCù.9Fx脇¤tGÂC-B2ÂC×!ÅÑ;7Ù¿Æ 0GMû¯p±_3ä)›­ê!ÉòØ’™µMÈvÇaV™YÛ©gWÅɸæçûtŽ#º°¶·W4LWÔ6±¹&û÷Ï‚¼ÝVÈj¸Ï<”Ÿw„ûÒTÃL/oR2•¦tžò¨Ò”jG|L ûë%ªÎÖuV•@¬‹Î.Ô\ :+X%Öœ]I¼YsV"±Ê´:¦ñÙþÜcÅ*÷_?)69bä=žê[ó†’>fþu°îóù†‚Ì~ªgz™ýÁŒeаtÁÍX~}œÿzU…]±ªò|©Ô%ǰo2Ã^jºÊÚã,MÓUÖWY5]e­q•UÓUÖWY5]e­q•Uç*댌‘K¨"L÷)}œ`VÇM3ò§š²þ¸ŠiÍ %=+BŠí¯‡w©zÿ¹ ¤¤ŽY×·øÖiCÄMãú&ç(L•à(cBâ(C[*ʘ;eiÇ×H°Ÿbüsºvøí"c ¦JößÏ”ICÆÿ`i™"†{ʽ  cBªA;>ªáó!Åf2-³½ÝSEÈ0¾T¤ºú4ôùÿ7¿É3¥~A>ªïGsÙ 1ò)#`Ükg<éç<Äñ¤€¯m‚jÛ&°’تm›¸¥â6AµmXIµ º· ¬$Úã¶M`A›ýõ9¼H_÷à˜ ØU䩵çz8'Úôj È{ím>æ!%¾öÕÊ`ºKãÜ•GHµA†ípB>ó]R ¤Þ|Ýþ¾=Òlîç=´]&ä#íŽ@×"!i)!j#$ -%$0n„RRÏèž‘aŸÑ<#Ã<£¶®Ÿo=BrϨAHúµù™ƒg”ï¼9xFoi·ëRàQN«w +Á0äKÒ5ýú˜ÉO–¥I Ó‡œ~'1Žiyõ1펄DQ½{KâC¹M8ã.S]ëß!A*‚k+¨€~®AzTdŽoÈj:\ Ï¡ýmSùC¢wiAžÛß róÖ-7~F>¯¿í!wÎ~QûMoˆ+_ߺûÒ꜓™ÓX?{„Ôäzž326¤Ù{?‡%9|Ãçi)Â@w½Ç8‚fäúÖÍÔ‚Ÿ·;BRiùûéó#%¥N è7Ž×±ô')úÍRYô'è7©pãäýfƒÔ8øŽ„º\'_¨™c'jÁÌTIѯ“ÀWu¨²AzJèðTœýÞ‡tËŸ‡â>¤~HêàCº]’ù΄ä>¤!é©É’:úni™W9=xM±d šX2Ù›`Éä×.3Ɉ×î!ÍSɯHîåì¿")t©—³åj„kO™±3Wc¹vÀÕÈSÚ¯"Uy¹öÌ‹fÝ\|LE³%RȦ´÷Ô3[ þßm±žÉÍ IoÛó»4æ* c·íó´}¦cúÝ´§ i¸óP~~ÇlJ÷[„Ô]ªÚ SRþ\Óyâc*jð,ôp€k™z_¾&œ±²8]Ñ­M_‚7dgMFô©Èt‹\ß99)_Óõ·[òã HÃ\{º¢D]Qê·dãôý¯œgÚb7çY ýæëtE{£së]jþ{î’!YG.Ey²Uõ¸å-É:p)Ê•¢*üëë¨GHŽuÔ ä.ë¨Æ¥(oIÖQKQÞ’¬£—¢¼=`¥º¦w¤Æ]SShΰѸkqjê=©q7àÔÔûݑɜ ÅõS— }¿§) Å^)ªE¬UÐk]‹X nÆñZÄêÈÝq¼±:’Çk’Ç«’ÇÿÎãa$7އÇ{â;ÏãáƒîãõˆÕ¡»ãx=buD¨Ü‡BVG„îŽãõˆÕ¡»ãx=buD¨!ˆÀ€î§ ¼-mè½ßççFнæi‹š§ L·n›§-jžªB’ÍÓ5Oð%ÁÃú1¿ßŸé>)4ÿ 7›yN›*¨ÖØ2†î’Ù!6¤®Ÿ<À¥ Ã’"ÇSŸŽi_êô·TAyÿüy6¿)`>Óù‡êÚœ„܈¥mþ§¹Ýð¯+ºÝ$¤ã+ÐõµEÈ6ër?A›U~'JD‘ÏþY_Rd P=R%]=ªQõ( AÍU–‰tr§óPm:Étbý; ™ÎCÜê’馦¿Ñ'Fî–ÅzTœQ¥&Ëb5*‹$Wë’)‹5ø˜\Y¬AHMöæ²X@J7&+̨Òé|ŒÚ~Òî$€±ç7¶}ÿžî§{-ve‘óÓ))x䆞;Žcû~ïcZyyß ÷i³Ó¯·áŠ’SP}¯™Àû^JP}¯ ú^¹S®_ ï{åú¹À ú^¹W®Ÿ£KP®ȽrýŠLåú€Ü)×ù†ÏÓ’wé–¯]pw©‡wIÜ¥Û!™»t~ $w—z„¤ïÒï’8ºK7„´;Åíù¸K©®hôÁ]JuE£îRô]ÊuE£îÒ !íÞ×Ñâj¡1»“Š+ûU Á4éî˜û)u…ÌŽX^ÊzPDm<3£•ñÄ`ô¸ŒVûÓ‰bEã‰Áèj3;R’ãFJR¡‰Ê$ŒXlAD,ãFJ2 w"–q#%jÏ¡ EÊ–¤CA ˜çÜA‡•ç9_ÜäΠ¬ 㥹3(0Q¹ƒ„‹ ; ÒVš½^¢ [“ª1VQ½³ ©©c.HxLC2ž$ƒ­¬%óŽÉ`+kIìÉ`+hÊ·É;$ƒ­)ßë\×E12e9Üb.õ,pyàÜfЏÅ\ž<GMÉM×ÉM?Ò¼JzTIå BÒ£ÚHz(8Y‡ê´ÕFÒ# ÷W$銞¨L‘•+iá“ÅKNЫ7î88I½É3{¾Éhº ½É½ÉNR‡¥’:yºl­­œ8­«„Ltå™xmˆ2zéÜÁ^ÉÙëE¦]ÛYN&äQRdå_…ËÕW·ËŒUŽª;%*cø€]}¯‡þ !sEq ñ Ìß;Š|Éô"Q$ÇR6)Ž|IJ¤ 8ð%)‘ÒâH ¥ìŠ$fÙG…†M^¤ì£ò{µ‹TåÒbÊKRZl@Òb¹Ë‘´X@Jú˜ù×É‘´˜Ã&[¡£¯Š^“BG-^OÓ¶{ÕâUÑkºÂƒWE¯wV†È®¦ø¿KÏÈp+ì ›Q—-ì†Þ±H°zG2[¼zwÄlm’c¶6É1[1Òì)´¸j‡M6J-®a“­A‹«F`Ød«D0ઑ÷¤Á€«FÞ“J®yO*ô¸j´"-u—r-HC/­»”kAº(˜»kAÉÝ¥!é»”jAÉÜ¥xíÉÜ¥7Œ´»Qú|æ]”4ÃmBæ¹]²BŽ{‘ºT´éEêBRL’MÏTŠï¶¤]; ÅÞØi‹ú›ÌOì)7åþ¦.ôÑØé€’RYÊýMÇv¬r¯\†Åʽr ¦7¶Cš-ê•$7vÚ $7vБܨifwÜU ua‰ºârE ®¨ wp—¾Ó]òä(k‹úÅ:OoP£¬ Br£¬5BîöL{×é² {¦ê™ê² {¦5ꙤÜgóži@îöL[Ô3 HM°§@ÏT—%)¤Þ#qv]–ÔÈíÜ5] ²Î0 :ƒ.%9œ;w…ÀZWr3Xãô‚ä_×Ώ\;\KÃI3Á÷€ôýL«biùû™„éRеô´*–ŽÍQº¦íËféP¥kd_öZ‰Ê5+-Šƒê´k‹’ˆçǨ°‚G¦È_ ADþãFTX ADþãFTX#öéÞ1Ó»$$ýÜ÷@ r7œ#À=ÐÐlGØ!‹àjšÑº±˜ÓÂPœ“Åœ†â@n,æô®åÏ-ò~AmMËŸ}Ù“Xш}º‹¼F¤;¨]¤•VÐU÷Õm´$øªÕm´$ø&$ºK² ë65ªÛhY¼fg(çJW´a´nº £¥`‡µ@Ä"å2E,È(s·±@£”}v_»#9v_f57à¨R*’57à¨23Z)ÖFJJ0D•ѺÛe‹3-õÑÓLÏÈüºÇKÒñëj„äøu=BrWW†¥ ”ñŒ·–<‡<ËxkéHŽî€d¼50JÙv¯ZÔçÒ{ö' ú\ð?·}®õ¹r·šÝ¢>W@*êڳܸVm§‰XˆZ•t±µ* bµa!jU,ÄjÃBÔŠ–ÜžÎó Ïs)š˜xLAq·f^::&Íê©V¯õù$3ß}wS”~]í24báòýù…‚bhdîÞ°:·ÈºŽÊ¶ZiŽwL´2¯ÈP!ï‘V¯ý¸*]ûG7>ÏqSn7ã Ïè£úøþ@HAu[ൻY¶ÈöÓyZyb:oÜLç¤ ¸š0ZÓY»¨q´¦ bâ¯ÚLüi]ÕfâOë’ŽiÑÄ_@Jò˜à×Ó¢‰?­ûŒÀ[§%É|p^¬Ã’…ý 8{[æC‹úZ+’ùТ~G@ªýýö;RïñÖTÑÕ p@]ÍðTÑÕ °E]Íð[TÑÕ °E]ÍðkTÑÕ€¸w—@EWö.Š®6Ì]B]mŽîRƒô]Ê]mîR¾vsp—Þ0Òîñë\Ó–d÷µ¸¶¦÷2ýÌûÍúªZ{R_u@úªIÅK@_5 %ÁüOm Š…8)ã3åò-!÷ûï±îù6Ú0üäiµ Ãð“§uá¹EÊ=®ÑŒÌ\#m~òÛdv´6 ?yº¢~‹Ü7߯! ÊiÈÌYOPàýlŸ¿©Í7B]ñ&R›jú:’¹š6`ö±¹Íº«îAU_§˜ú!÷¸Ëdbæhc¨ˆ¥kSTKº ôÈ]@ÚL±Eî)¨:CvÈç¾2às÷Çl¾"À1ÓÆS³ 8fÚxŠ¿¨€wÞÔ[·¨@wÞÔ[·\Ñs‹”Ô]ÊÎ Ú–„ÕÏ2™:àpá¶¼ uÀ5tØð‚Ô×VЙꀤ"¦óÀ̈¶{9BüÞ‡Ÿç3å–ü3#Ú*>—iÒÎe=¯Ý`BM[MÏkwõwž¬Ñ@a?GÈwi§ûŸX4à hké*ܼ*v©kIkÇoü'´õDv6nü'´õ,§솮 vÃq£6® ï†ãFm\6ÚkÇvìù+v\Çvì¿î}Œ½Çlëœv.ÐÅpdgdÛvŠÕRõdÈòÚUrH»¶3GÈtE–®Q£¹3í]£FsgÚQsgÕfî, ÷kÔhî, 5+ÖOç…Ôïð©0ÓâÖ—¤ÂÌ€sX_’ 3-Î7½ fZœozA³§p¾é©0Óâ|ÓKš=…óMÏ0 p/Ò+ªw¶($€Z:”ÿÝöø0óÁ“ïüÜY†Ì¯z=iø^Of>xÃr_³Fö–Ð(¨6Ú[zC:K ¿|›-îyúÛpÿÈ;²4àþ‘§¿Í÷2wkWô7=Ý߬qÓ{Ž):v§XÍ6EÁ1E¿êá#™];®`¦(Ù]{h£%¦)J‚-4PSÏÔtÏ´E=SSÐ=ÓõLRÒÇÌ¿N÷L[Ô35A´Ñ·f§)yç¤Ùi uPûï§)4_ûMÚ¢¦Ð Ó ª˜ÂÐ R 0ir™¨i Ks·KÁŽÓx,ÕRwWÚ!Ýyϯ´m¾Ÿ{<ÈЈzk¦,¸©á!çŦ,wcÅ5N®ú®‹5S &×í£’ȵÇ~Ø"åîô„„¿ÎÕ*ôë\¡B¿.I ñupLIëH ¨ƒcJZG¢ESÒ:-êà˜èHìð“óÎeJZ]§E;—)iuí\&«¾TjT=0¥!fWW•€\‘0%Õ‹7–¦tìŒCîEšÒqÙèE¤$æ¤@d‡çe¦ (C›’Ÿ\È}C# ¢¶¶è€:ƒ%YgPÁˆ’¬3 ¨Î`DIÖXTc1B5–ÕXŒd¥F5Õóvf«óä—ÙS¥Ã}®SDrý+¡ùNSŠФê×€bZ# ÉæPLk .ÜvVh:dÕéq™þ”Çå/N8:7D³WFødZi9µ7¼Ë’Þßñ^ ÔÞö+uB ŽÑ êÞFJzÚe»F*zÚe»©¨a••e»ª¨mW”횊Ú+/==#©©ê뼆€ê«‘†ârl¼]4DõuÜx»iÈx?â7ä¨ó#ÅÿÜhÆI͈Íx#)Íøj£moöU¿ru+ÇŸª`ïR®¾Ur×Þç*œQ‚Tr˜W:°*yÀgè¾"’fÞÈýÀ(MVNä¨`”á,ê±K« Ò_z­fƒýH¹ƒéæX·1Ê“‰fæHœ¢zžÑÇ-„»¶&yÔ‹^P®]]üÏUÍ ×ëŒäúÙ¢zÑòßdØ©]“ÄhMÝ¥ ˜$F³3àp7Ô–m²ú¨Ñ–Ë"án¨—E•Ô€{Ô¨¦kÔ-ªQÐ]ÝòXT4¦ y,-ªä.çd@5@chÎÉ€j€¹_@5À€”ä1Á¯Óœ“Õ’dÍåJ¾1’¬ä·¨’oŒ$cïUò¡r®…'s.£h†0ιŒ"YsιŒ"Ysι€ÍþäWʵæzÐ0×6†Èµ«M_Ûj¥7}í€ôµr¿¿‰zúÆ8zG=}cÝßD=}cÈœ+¬Þi]2ž_½s=Äx:JÇu˪ÒÁº ìØn»–Ë1#ëØØ’Ý7Áûiwgcu Ö?÷:¡™9&啳ÓîuBaÅ,g=°Šc›ùi‚Id5Iðtó¦ki¬!c›iók9>-ܬ#z»Õ†§‚ŽÖR¤j=7ߣ Wûæ¸q‹2D3Îñl—éZÈIÁ8Á©ëwã$=ßsC§)òwš‰i+˜Ã:Ãå°°jä,}í¨»j¹ê&úEs»ÆùƒÈ*åqžVfp¾éK²fÕâš•dͪÆ5+/¸}Ö¬¼`õÁ@}ÉK’åUã|Ó«dzîžä<‡`¾Ÿ¯ÓO©²‡XÜÆ[be7,nƒºl¯¼µÌd6ÞR9ì‚Ì|Z³é²½æÚ©;àýÁº÷#»ß½ÊëRâœØ¢ Uå7Æ%Á©6Ü[”ÌZ7W¢Ú›-ŽfBcvf ÉU AÆg E®Ÿ-ªÆØBÓýMT±…&¹ªÆØBÓýMT±p®|‡é”kéΕoºÀª¥[4WþÏ–Ñ jé6Ï•µµ|í–¯­¥]Û–ì®H‡ÇLv†¢ [8ºÓ4ÅuyjØžžž¾ŽlþkË‚˜q73ÎA¿ºí[–tÝÍ8ز$øuã†io‘3Þ’ÆÙ«ª~~·Ão•ÎSn‘ׄü¾\Ú-r͹7±ù˜×5ªœ‡ß»˜oZd϶ÑF›Éû]<ô¦+º¼¿ßB¯§šîç’Ö`Ï‘Ux—Ú¦zŒ]œj·ÀžíŸ?Ós¿\R$piNS¼]+-°gÃÈqüNÍØÝð-ölÿÌßæ‚\ߺé˜ÍÇøÀ¿¾Ø³M÷sF^£ÒÈÜ`œ©éøÎZ]o+åzú”ú¶mZFèùr»ÜW竪ë~ÏOðÞ{¶ÿ¬äÛêÈ·Ÿ×ºNä[ íÙf®éžÎwô¶vÁŸª~lŽª²×û5|vÏëéYýŒŸ›ËBn‡«·êìüÕ<†û7†®Nz§Ûúžî@ÿ3Ó:Ú\0Ô&èåz©ÂÍš_–¦ÂP¡óͺ¬&eSl×=ÏÏnsYëÓþ÷¿e·YßÔþ§êúá2àËÓúýß|_§Ïùº|ÐÏi¹^»ŸO ÝëŽÍì¥Ú’æ~H›Ú–4÷{@ÚÔôd·ýèérÛR3:“P—Û–š™î‡ºÜ¶„°8&©Qýß–tý@õ[ÒõÿÕÿRRÈ\·¥%UVOœ¼š9n ô’lÉTùP/É–ÔdÙ¸ñW²‚ÏÔr…Ó 2ëßø@YQr} Pá´b§çj¶5ªÙZ!¸èÔ­ ™¨-Ê•¬ ;KW4³[­ÐLOj‰Xa˜,j‰X¾ƒ9€XT8NÅF×â œº9¹û4[Ôu²² Ÿf‹ºNVLDT^±•%œ¡[)8¾.ü:¤¤ßdÄ<·RçùÏM:OnvfZAOÆ¢Yø`.tüêççómÚ"òU‘2üø<çrêêç!¶F¬ YºÛªR}:OZ§b@›VzŠ©²ðâroÎÂ)ïÝo3Å$ªätzá§Í'G½9«$;­–+H–î .]Q‡“Áq£flÍ`É kq}ÀÐóõ®ÀD}Ý;@ïÃIõ>æxô>¬áëêà­3šÞ¹Ðl—5ô¼Ø€:/ÖX®ëëBÆq]'Àº·ÆÑ±7bÝ[ãÙˆ%³î­ñµ¦T´ÅQ]è‘%7• ë–VûÑìšµƒ¬•;WŠT™ÙÃ×-;;#U«ÉÉ×­¦îçfÎ"¿€í\#UK¿Kê`ZK¿K-®1ZÇ(„ Z¨=È s-ÔzNp âÎuÅî%½ŸïïÓ!îWqŽàÔ<5BnõÇ¢Kouv÷ͱ,2ëH? Â¼uâ`/N‘•c™“0ïpŠæá¼Ã)ò+n‘z¤ul¾ ãdgâä´Ë âë”7x“c8pÞÁîÎÆ Î;XçœwÈýXÍ;XÏ̘£y‡€$8pÞ! ™X1­K¾dcEP9ñ%—kÃʉ\® +'^¬é Z/i.=Ž—¼¢;Y8^òŠæÒãxÉ+šKcEOV çó„±¢'«…Ëõ[$Ť‚™”7d_rÀ™”7Ü<#`¢ZoéúÎv½£kV8ÛõžéïÃ)oW gîq®(I¦J‹â%WÐëç€Ø/®`g‘@åÄŠÖÔ]ªFM:OÍÕ.@•Æ웷¨râ Köâ[”s¹ÂÑÇD9—+Ù‹¯QÎ’BæèמŠi7^ ε½î› Nvp®íµ+ "W ®+ ¢_W ræt@ѯ+%»oæè×ÁiµíþަB\©˜ýÎa9Ruyy“ATéJC² Uº]Õe¸ÚÄèו–_mRôëÊ}o©õ­ƒŸ+ù(ãs¥£û(ãs¥£û(;s%©j»TxrTéU.HU:±3q'«þÔ·'Bn¸ ÉÝ~¼][üëj—uºöN”œö¨ù;!¨zȼ¿ƒ=Î Ž+«[NHfZ V·r¯² óþî„¢wXTÙsBÑ;,ªì¤¤³òÈtB3U#UºÝJÚã@\çà¼Ø+ÄuNºk‰¢J',S5ªÐ¯[¦jT¡_·„;Þz?á[瘘Ö¨ðGžé;Yp•I9É8«¢ª¦“‚ÛekÔIÉUÝ#ÑIÎïFANjnîä2NšƒÈê7!Iní²oN4®ÞHû9 TMõ;§SO„ã d‘NÒµ e‘Nz²{5 ½§ ®û*íGŒ«ì€8ÿÎéƒ OŠCœá¢tÓÒ“; Ä´Îqñç|Qé.ù :æÅãûÇשGH±S»Xòâþ–ª[ÎïM}†gÔWr@HEG)fð\_²§œ/™^9dd9/¸ð|êò1%£¾ûyÛö!7º4Uô³øyÞš! ÚGunÒ›ì%}—p%Ê+:®Ã±·×ùQZ½½áX4pGðö`ËOÓ‘žÍl1¶1ööþ`õŽ_œ/¯.´wø¢äêÞ ºð…àX nã I›h­ód:ÖÒ›tžš«]€wÞæ`¥mÓ¯s 'ûÂq„ôL^ c0O{.Æ)‡m#²d"j¸û’ë#ÀüÈ—ò ºHwžæºo:¾ÔÜJ ÖOsȧk‡kˆ‡ò'NSývÃ-z%ø}y\“ÎóEHELOßæÐ."¹¬æ\žd›/ÇlNc~Ý“znõüثቂ¨ýN{qº"A:šÍ¾oÕiLW$ ¶ÃÞdQ|ÅéMGo]ºKBìÚq¥õBq]°ÒzšC¾Dk9¢ö4‡|A‚UQ؃õ3}‚㡯Cxz~yn qbËËâ 7L¿.K.¢†¿.·ËÌƒÞ )Ö¥¨hᙺâ€ï’Ô\ìÎÓpýŽÛxŠ•(¿ã)5ŠçwþÚœ„˜¾®6MõùÕýþ¶¹«¬5¯!õ9òTRÑ}™6Óq}™¯ïï3B’ ¢SW§»äi´ýºb¹Fð×UAj«®qrd›{UrqòåcünrÉ;þüùï§Ëûu%åÏ\ÞçÒŒH† 7-È9J÷¨þ¹ùõ®û8].„„¶ÿ©oÞ„”;µ ÙýÞjŒT„¶*èÇy¥¨ç>Ã@?Î+E±¼æypÀòòÐ) ³¼f$`y¤"âyt?5y?'$ºŸzç<³?Ý8O½£xkÕµNë¼Ò´CÜü@Oiçb*ÏKw ižxeh§†jvgN«zué.*Muÿújι›Ë4U}o† RçÙÁïÈæ)ÚyŽõçXß?§ ¡ê>ßRSÑÅ ¤kw|t1>k„ô’ÏÓsoÈ÷;xC<Å(˜W›y‹ÇÔ´ÒãÊL±¦5óëî6å=cÌúÙ&䮆özÌçýù;|Æû©%ûÖMÇlr­±ü3!/×°w|WïõÇ”ÅÆiÇ€ÜeOÕ¨Ûâµb|œa·ÅkE3Zñº¤5¹. x]Òš\—j¼.Á‡ÍºTãuIkzßœ"–1Í4ymè}³¿N?g„„rû©~>„Üç3tõøxkð¯+Ò•»z¦cZîM†‹vŒÓâgw^ŸIxóݺsÛâcÊ=‚fq0ŒŒ—€TÄ[³3í…O”iO­Š‹~x®ðxíi Tá HEÜOø&:¶™ðM6 T×~xCÈÍý¼Çû9Ö[‹d¢5SrNô3‡=>M#¸¸®ŠFÒªàÊøŒ$ý€æÈÿT¥½#wš¦eñŸ Õ°æ2ýyì›K“~=­!/qÝ´"¸ÎhÎ5 î2ÆpqÜeŒáôíaôKÌ¡„ F¿HËîµ&0žÒg^Õ{nÑ­µº|ÿ Q§ÂC÷±·µß¡ês†bÜÎú3”ú§¿Ýð¯«]%ç í°†Õ‚ -¨;?G îí-õUÛˆzÏS,EÔ¶ ¿÷vDŸ-É;ßWïŸ?ÏtçmIÞùùë¹!èñmïü\£nò·%·~¢û)èû9Žè~ *¢^”ÛADmQ/‘?ˆ¨¡÷ÙN%z£Ò¯“³«Š`^Á¬bö¸¹Â“v4+=Xg乫šn@HAFÖ0ë|#kè¾L‡Vokè¾ÌÌÀ|¤:˜5Ôs_òbP§µl$×%ë¸ ®KÖÑÜW+ZÎÅŠ–­+Â8yR)fúpçr$×}åQŸÒsw‚^—pÞá$÷Á:ƒ“œ#Ïô.¥oÓ).ªüøùJï’SÜûùO±é&ç‹ëîþ9ýø/BŠÝu‡¢5§Op:Íy¬Ã÷Óòη8t–ÑxA #óâE1D€Î2/(t–êñ­uïSz“­º0!Ÿ§1}Îs ÞðÛô—ÁoÓó3P)õ%ûë`¥õ‚»¢fz“Ó1宊`x,]~š^qÈ®Ǥý(Ä6÷žÌ"g$Œ½½&³³±Í½×dv6 ¶y@*zïHß»g÷ø½{í´p÷–\—¼¿CõÈWí_¸¿CõÈÍþ^ãýÝ[ÂÛ´ zAcz“WS…{‡gzRÝsŠ*ó›ì9wÑá4†UÑEq]„lB–dobq,=e$®ÛÌ|°µ^7óÁºó³›ˆ”/Žä·x—žõóÑÖ¹§ô8÷"??cí""%õÅ%§ïˆT„OY~—&¤bjkà]ŠÈÝØf€œ“ˆÜmÈ9‰Èýj6¬ÂMHMªÖ£*\D :ï¨ÒpyGÞß#Róïè~Zú~Âî@D bª=ç2¹Ûha.‘Š^Còµ;n A×θ¹ÁzÈ„ôt¶ ë!Iåq¹‘{õYÕ6GÔ©Hä.½ueAtîÖÕ¦};·¹žçú¿W Ù]îÐ+ÈÍ3JžM—æ1<’‰—žñ~þt‘Ï2© )8oøŒJIíGxJ+"¡ö–÷͈ÜÙ7G<¥‘ ñi—»4¯ŸŸ×¦ûø‰HÅwF®ç'BŠý ùÌøN_GV8\ûïïÑݾî«S7v_„T±–>ýöu±¸_¦½ýr{ŸÞ;„ÔHaó>W‚ÂfÝ·D+ÿwûjå@~·Ç{è¶D¤¥¢Êé%I×®é=Ö~'¤ahAí7" ]YùGä^íwþ6s6‘jwöe&¤¥ûïS&uªò±¼µ!1^&¤çŽ™«¶àx,]Ÿh#;‰Äc>¿Ûß1íï€ÇòïßÿrÕ¿­b'"—cþþ»¬6sShí ].í”ÆÕIôøžè^•"Rîö±"1!-÷çÜpB:n‡Í¹aD ÒÙjÌoˆ§3”¥—éÙŽ-¸Ÿ² 3}/É’ŽC`í7"1¯ ã%Y’µßÇK²${(dÑLHÁå›ðÎKÁy´¡kçêKŒ%É$Á|ïˆÜ‰½GÌ÷ŽHEèYåúç„TtÌ;¡)5­Ü Èý˜vB#’êse¶ä„d§ad%ÉJTÈòµ[.?‚q²´¬+wª×MHG3Ǧ]æ÷ùx"$Š?o©žü3~ç!%åôÝŸë3B*Ò2v–'¤ç2h]¨‚êŒLÇ‘ˆÜ錬;BêŒDä^gdéí¦ÎHD*ÂÃ:W‰'dy]¤¯C1Pœõ(I3ÜpÖÃðÁZœõlø`ˆé„³š¶ðÒÁWLóÁf$üŠ•¢+fø+VŠ®˜á¯˜äƒ-_\®MHMNa÷p ;"™¬<_»á²òÜÛHAgRiGP–Ë¤àŽ ,¥†½ø,&ŸÇ éhuñÅ{wL¿îYÒ™J4Ói¡Fƒ7Y—äµ87Ô%¹Î·87Ô%¹Î·87Ô%S ªà›¬UðMÖ‚Þ7;ôiAï›°‘Šš—©òª¨åAü™ö#­8†|îšÜã0KvB.º€ï¼&Ý™ïrñ\£ÜG˜ŽÛaa5†fûLûèõDäî,Fg1"rwc€³I²’@Å;BZLÉípe0%ç cE#˜zŠ ýη8V4ô;ßâXшƒX1Ÿ§äbÅÜïˆHAçéM6ŠË` f"Þµ ÃBÄ»¶Ñ\Þwm£ÉZewm£YŽÈvá:w0×6–ö Źö.×(ï› 3ŽóC‡k²ñÌ;ÖdCÏ®xM6ôìê€×dã¹<Þ%KWxÚÝ%[Ð}œírn˜Ó]5+ËF•è<%É:p¿¸aþ»^Ñ%EþÏ÷áÖ½F¤¢&åW^ú)Õ.,ö‚dznüiš'BJÏÇêA;¾ ->¦Úãä7Uýþ¬„Ô1ž¶sGìã~ÿÁ¿nP}>_Q×õ·BZ„\ê´k×òÔÔø×Ý«›ð2Õ~z W|E~— 7k§.ÅuöÀC0ç\Ö°l^íZ®jTÁ5ÙrU£ ®É´.ñRû»õü”V—ª¯®`#Õ) ŠçéJ.¶9‚TްòÒsŽàÄÁWœb0Rxek£ë!-Τ]iq&åèzH‹3)§¸‰•¡÷Ssw¾?uéÛt†VMÄ´³œ~2|ëœãòMøÖ9ÇÕ~aÁy²ÎPã:THøwÛ :THØÔj\gp$3K´6mré~:ާ Öº²`ç A´V’jkdz,yùÔ7,IÖÇ:Õž#–’d},H±”%ÝijQvV–t§©EÙYYJŽ•j,%­ó¼têÁ×A2Æ O , ïa¿£’\?7¼ ª7#^иáä/¨Úð‚RÑo]zçóáÅQ·íNÓ¤óô4÷`BV),³ÖÇ ;à³@Âj’úyž–ú|?S¼4Óh–øšõt?]õ^Í#îÁßé×OçËu}Fms¿õS9`äÂ=øïŸ)ž?_B¶ûl2E‡ÏÓQÈ K䀉ƒ-Ê K䀹QÆè:Pÿ,Ey¤S×:!tJc®]2Ì4Û2!%1ÛRáÙ–ˆ¤4»Ó‘Šå€=NèƒÝ0}›ÂÄŠéMö`UÌHw¥]†æ3ÌH¸ËÖM¾K² }Û‘¾MDR:ùp]’åÁO÷S vUœÝ‘#Rr9ˆK©H>X‹bïr¯§ŸÔ``ì]JEòÁj{—°§ÿÚçùf)ù~Ø7¥a}WA &íÁ¾™Þ%Z;eFÂw j§ì9u&Î^ÉuÕá\-UAzX ¹žˆ»ÑZ‡î¼*HgŠvDOSlÍ?ç†%ÙU_ób°†0]õùÚs¬ÜïªGn6舕›¾ö¶¶ž»Ú©ÂWâõaKe¸µ~GŠŠ*¬‘{9×ôë0ç*•sX("ýu¤õS9ÞË5g=ʳðÜiåêEã:×?K]ÒOõ7KÍUÈÑn¨%9éÙâÝPKZ—ïqZ±5U°zk}ðΧû© çò òâR[²ªY£ªf©-§?ÎÓ±]Kxžþ@3Ý%S0 œw˜oB݃}Î!ÎkƒŠª €Á”,SÜ%èªùª®óÓÞ"Û¼ÌÝÕ­fÎðÓÍœˆ”7ä†DÏ4ì\ã´Ú¥k?z?Ó·iøÚoUEÞEi çh?› i9Hø&Zh@žÒ0šcx74žqÑE»án‡±ŠF¸Ïxã¢ÝÐxn7„ë’ebEÄ!/mÁstsŽ`ùÚ/ø6Ù#ZÁhOÏÕ}>çÅ–®/µ¸¾déúRëK–®/µ¸¾d7ÿs.«yÿŽ:­ŸV³uE°oÒý¸°Òæ»d¹iGXå°îài¦·ÎzÖÿ=ÍÛÒÏ=§+Yÿwí:Á»¾æ7ÄIr¢jÀ•0)¿¨påÄIr¢ªÅ•'_Yaýl*à¹0!ïzJõÇÖ—àºä "6o@î°yÇ ›7 %å œÙ¼I±ya=ÙY¾Fjé¥s\lóbGÎíNßÊ‹'§!\Õô›Ì—d<_ãxÞ³ô\ºI¿Îj’À]Û+®g cZ¯®(}GžìÃ.ß&È‹½åj,p/fº--Þ‹½ãjp#çµçoíqÞ³¬øœñ‰‚å©‚œK%ùÅ (ç ÈÝœ«F9W@JÊõ5ç\©H‡Ö´†ˆBp_Üü.%ä¯zú:D¡X¯Ì¼#ˆ=WMàžœ×y‘{(‹šÖÛåÔ´¦§sïˆd+'à ÈU×*”‰Â±Ž·IqbBzÖ)>sžEYÐ|ZT=Œ¶9®ýŠRéä§_g{å`ߥ";-Ú7œrÝtZ´oŠR‘‡훢T;S™À6¿uôœé¢ÒŸwCQºvCQr¶e@»¡( ݃F»¡( ©M1@mŠ i¹úXiEÉEkºvÏxΠE”ž¬×µ(C¥gœda†"JOÕT±V’‚íE‚HUˆ’­åèBìi°/×\ B²ü¼Ã ¡x/ӈ ¡Ydf: Áòiѯ[Þç.ñ¬„p¼‡Zªý áy§ãŒ”çc ßdY²«"8Ͻ>ôÎß»”¬¸ŸRqùܤ¦cE3$UK‡;‚4Tåd®‡€Ê‰–ã Àç.Ë»_‡ôÔ.ƒ•p¬PëþU²ÝjðëJð~|)¦Šï kWêÀA#S3°(j÷®ƒÆ!9!ãL‘î’9p¦ÈÇ4¤u‹ã%eYß@°#(GGªx7TŽÌ [¼*GGªx7TŽô*šßÜÊón©Ã(˜š‹ã%έÕ.„¼·cލµdsØ1UN„V¬ÿ&øâ=êømf^ІÝ@ü©-½X;¶ò#ͺ/nŒ0dô»¼Éà×MÉ­ŸðÚ «0×#Y—R°w˜·üÖÑÕìÕÍ*ïqÆð©9f0–÷‹Ì»¡q¬ïøŽŒg½GÁ×aÙz|î¶Ü²}®×%\ºlãiÓ1EÖ¦ø3å\—÷ÛŠœŽV=êç£ÂH±2sþ¾Í‚|¶—áöüÞ %é$›ï§•¬c#øâ,š{“ák /ÁwÞZv­ß‘ul…ìÅÌ4Ä€wí}EÓ¸ÚÀˆÅ•l¼!N_ñ€£ Ç~›p•ÒìP] »gÓ~¦+Ò,²m~„¤”šN§43"ú諦өÊç©Ùiܤ›=! 凌ã%Ç{ ƒøÓ9ö˜`epž­nõÓ¼Ë^>O_ò¾Wyýô‚­H€÷Ô?_¸…·±ë»´*zŸÎûLìí ÏMe¢µÎkÖi¬ Þ° xLË}pó¬‡Ú|õéù—¨øÖÉ¢`]¢’{D.QwP« HÒ%ªIµÊ€¤Ü*ÁZ'‹’÷ÂN÷S‚Us=¥ç. yÀŠoRñ~R)f…f‘§èÂ3!Í‘ÃKBZÞáå9Ö)ç”ô4ÝsJ? ¤ØýâžÓWTUé×_Ù¼·kÔ›öÂTó—H_ñeº¤ÊÓyj!î Ç´ÒÊ’íV7§Sìɲä<€N§*®K)¶,ÄùQ]nmƒ”CÁWývÃ¿ÎøŒÄõS–‚ñ9l@r>#-B2>#×!íÛ’¾ÍR2¾-wÀÕ”»ì}äÛò†œoKŠ˜ð­¦Pà‘û_ñ=½!Ï!Ńhʤîc3ü"äæ¹§©á¯gÿ†©ðÔpøŠ«÷ûÇ׈‘šœ¾^1ÒìO ŸÆS“¾w Ù¸35\=~ÓZWæùbÂ%½ŸšÛeàªX²®…pUuïàî=-6!ZûzïžÑÝ{B¾NLéDœ[R)„ îÞ‚»÷²Ë,îÞãoÓ#¤$gW»&ÝyÎ »úÈó\²dU鿨&ž§`oëÓ)öã¤(|ÙÒ·)Ê_¶ ’öeK±¢%7 wzÊ x.¤]L¼ªPN)BÞç86o3}‚qåH×®xWŽ>½óB½êj¢lâ3'ŸwôÍg«®æŸy»]ûô9_ÐÏ;BÒyGâH¤¢‘ >OMªôƒ;æLƒ:îíºª‹×í©~´ßéŠì+r¹ó ²}¼çó´ä$H¿¼òUƒ’BNϨEH•Ô2ϳ¦èâ4÷<Õc?T±ª#ï·€œÂßç!ÍÊ«ü7ð*ç»4#«ññÌo²+í.òùð]rQÑôt¹…˜¡?ÚaœnçBú9Å—ð½ÏƒluûññÀ÷³,ÖÅîŸzÐ÷÷-´ëâõ×ÅÓð¼ =¾÷¥  ßý°®óWÿûw^—¡„úÝÝ?§r•1þßß¿§Ë|®ó'RÏÑïmHĨ]žÔßyÅ{?_ƒ#á³?ÍËýcsf…þ]¡ë2:CŸ§jó¨JKA§Kۼю´M%>¹×nÃ&éª<7l›M‡­äKqÐ(KÆš²<²&i’±&IA#)Xš Úâ •âÀ -c´`iHjÒ¦,y3Ê.•ߥ”/2È$ØH©x‘¼ÝÈ#CœfHÎç4â¥<4ÄÁÇä qÞR1¦Eé]2t±eNýºŒ´Ì çtÌüÑÓ2¤Û´W:ÞR!§½Òñ†w9-Ѱ)Ï3lôóþ9V™[¢ÓŠûg.V¿ßBY{Úš¾JÛ*Ø_Á-'ïYM H’—JðmÁ*6âR0"ü阒 RŒ‘°ð‹HÒH”v­™³‘\²ð‹HÚ€ $JsíàlŽÓé]ZŠ}Ó>×µÏóçÏ'†’Î{`ó²Þàyór{³æ÷Moà6Wò.£ysâ™ú“ŽÓGì`(ê䑲oü@œâ•}sà€÷]³âýtì–K#ΰÞ#Cb¤Jgï‘oÀH•ΰÞ#mb¤JgXÝk`¸¥ù`8ZÙ¢ÅE>çQÕ<ôσnª¯NB¦r ª¯{˜üm;ÃéôLaƒ‡ÛÜ+rÚ0’.ÛV›cêøqNaø\µ­æ w;ô}?lËÒôßR5žu»ÖJl;e5Ù…, -…ìò–´"Ý«òôtEç±i’ò´L%p?æðÓ>sÚíË—~Å-|Í«æ+*i}\nñ‚q§Aå/XwPnñ‚u§å/8ç\yÉ8! Ò²—GNg„äœj„TŒ_Y\¼:ÒiNwIó:Í9 ¯;¥ÐÓ}D–Gêëé˜â@[;®SªŒ¶6, «Bik¿!$§­Ý#$çÇ‘êÀãY#$©UžK$Šáˆ.*IcFJA":sµiÙqNÔUá¸6hB©Âó-ÚÔ„R|Î1½óêˆÏ™JNŠás¶H@•¬ú|šQ¹§¹šr•„v‘òÈ'ýº:pÀIïR©8N“©R3ÚÚ0& HN[ûŒœ¶vŠÑ¬NHC3çQ®¨JË:wt§!Ýyv6 :œ|ßS¦Mü.t†g­‰9cYú9ï^'uR¬²wΕ(y ð”+*!|XÒ;Xp!c¹ÆòPû3žnãÇgDªÖÖW‚@r@Hš‹ÕDÖV@*šµUõ© ÖÖs8E.V@9Ù$ÍÅz6ø×ìñ­­¥¥îp _ÜŒ¼}Õ5¾K¡µômfèCKÀ»¾/Ðzü¸µ€ ¡âÚNÐz*SËb p.Ë—üþ¸Œï€ ¡êzé/Ý¥½\ú T£()ù-Q~õóó³š=èçýúùºa¨ÍÁûúûkœß}~V¥Ûþôß_ãÏØ]14eoçÛ岄ÙïSþþÕ~õø¨k<Š¡—ÛØ]¦M§Ý@IæÜ÷Ðà·EÐ̹a{9÷gŠG¯q>òùýq¹¾uÝæK…%˜ë{,ÁÜZÀœ‹Pý m'h½5ëâ÷ï‘ߪ‘wG½ZÚnÎuyZ–Ôù=TÜÇ[ú½õþ`„'©{§Í·% :à%„Šþ}¦¤CÅ>ôòñóqÿÁÐåiý÷ßÿfhª6Ïþ÷í÷öõUa(c‘’o–f-RrG ÍX¤Àq,…Hï)yK ÆöoeÀ=5üMbŠ(aøš¾ÅÇÜ”¬îQþkho©Hû.¿§öHÐ9Óq#² ÅRÂóöù×yÖ&<¦,„ÑÓ]’‚FG‰“GÂèoÉ £÷É™è¤+’&:ù˜’ãwÎ÷3!ÉPfJo`\IMÐg$(+Ȱ|)Bº‚ Ëd& «Ì°$èÚ5>¦¦ÙÚ5>¦AûÈú†LûH?Ô÷ Òî#‡¾þÚ Í¿®žé_é×ݳEôëxçwæ è×ZRÐL¿ŽPƃ- †ñ`ƒÕô€$=ØÀb+ ëÁ–«é©ÏÅtÌo °Œ8Îó<7#Ò³Ç Žâ½£@ö¨çãÙ-¥X ˜ +yàW‘–eàI¿ïΘ²AuèÍ“úH»?§9ðBHùƒ²Œ¤t+¨³¿ï…€Éy!¼!¤¢¼:àÓt¼«xšží[‚:‘.Ž4ñãÓ´Ñ]Müœ‡ë’u__‡fµà;OúwœÞhÅ»ã令ÕKx¡jÌÛœÖ,eÔ³´9òŌ˲¶ô d_žcz“µcf³g2hþuGS~ÙJí8£#?ªD¶RÐýÕ ­Ôž3:ð£Êd+¥ý‘GK` Ãý>pzC.üâ¦g„úÀ)¨înÕ¶™¼ÍNç[à*·M[×ÍÏå·AHEõW«æŒ©é¦i$”¤¤°à{ý¬ºÛíñ¼àcZº»ºA:²¹š£Åésouþíõ<Û±¾4Ýæ˜1…=À9®„=À-#MútŽ!pیòœ+|GKñÚ.œ Û…*·íÂ{Û…›'ZâÎâÛµÍP÷?§îs]]è–;p 5—é\§¿Ç¤X¡+æïrYÁ°.@ûqµ´3TÞhqà:”bp+Y×!Y[ɸ¡2†•¬ë(cØÜÝÛ›%ÏÃhÊ*~–¼ËoŸ:ðI‘ ÕŒŠ­>òÁÇä|@ÞRѾ*©Üh ï”÷%Ë{jƒ}ɺ#¥ôë{ƒNa½ÞŸ¿ud\)W°C™†©0~¾\ÃòQ½×Õ£º½!¤¤½ERŒãJÆ[õ×\yä-rFHÎ[¤FHE;ëõñÛtl”cp'ü_Ò®è$íâ„sD§x·©/»C³ôëæÈu(]‘e=¤ày¸MóôGn}qcü °Š¾òå‘?Q:¦8ð'J+ƒ'ûÔÑ].ÞOÿÒ1¼\ãâôÅ5MÚîßÿ"E¾ŠkºNÑ%PN ã`´hÚ4¿¹¹áã'>-Ÿã©()°.yÍ»MåuÉ.—…Ý|o<ãÒ±œfPZöþÀÛ.îÛš÷˜]”Î&Ï!ÅÆG~eÁ¶ïmÝý|D$xë£:›ßÇû[>¦àXÅó»< ¤¤M†„dýž@\¯ Å"s´® }ä‘®Èð~}¾"èÂÕF³npµÑ4'gÃ×…gÝ|2?^žqóüø€$Ý|2?> ãÿ¯}ãpñ2ÜU¥7¹,Yg¨ü½ëRð»)y·©1#ïŸúÀmªN×nx·©TÑ;Àm ÔE4ò˜xu›ÊuMzL$o‘tçí‘ÏB:OÇE€ð;*œwò1=Ú¹vü‰âyŠâÈ‘!ÞyQù‘Å_'ý ’ËXBÊ—VÒº~ά´~ õªÊ†÷ûêòÓÕç!)Õ£ùO„”ŒRüŠ…>ðQz„´“QÌã´0¬“QÎã4jónŒ`§…aŒr§…!#å\ZXÆÙæ\ZØ#g|LÎÙä !ÕglŒ\ÚˆtGŽ`é.yv„xzFñÏì‰ÕZá›§4öôyGH½+"4½žÏ„4›â¨QyúýýíÒn†ÌC§ñsú÷g‹n_yrœeYñ­|¹Õ÷™UµÄŠýåÙ_ÛüÜÁØç2óúþCÕ¡?§‹úþÂÐòUµá½9݆¦ë®øê3_îíêZ¹üh/÷ûÛ[Z‹Pu+N³Å}­‡¾½µãÛç߬À—û»Êj®—5 Cý>Ÿ?ï?ZfÛõ¶\×÷ùrÿ¸5?›w@ÆD-€'ÇdçM´K6fzcT¿ANAQÚH-§£ªäMsà¨Ä‘URúõ½= ,¶Ÿ×¦ûˆw*4%‰Øhº0=ß~@Hª3ïO5BJÆX(¾%êÈn-ßOÞn ¤+г[CéŠâíÖ@º¢ ­Ç€Z„ZÚ/%¤cé陳¢÷Lk°ib¼v]ò¥Y—¼!_N-@}Ǧºd ù@j¡K& C¸\ë ´Úõ‘îRXÒZ’HXoK³æ:Bj6x!©g3nš‰ZÛ# Ì„tvkuzFž3wr±IÓz6Á”.Úô¦Ùe–7(Êh#ØÀ„˜´U|4ò'KHsäš®ÈnEÃXÑ¢òlî—SDºQ®PÏÛñ¼„ ÉÛÓâü‘+^<&ßq„oˆ/y©­4Á«}IiùDÐø4½8òLç)üÉÒyªå›8£¨½æ`FQCÅŽu‹¿Æº-ž HFù¦Ã¿®HdR7HMÎr%W¼€4ä(Wµ9¦%'¹¶Hzäê³ÃwÉ“j:¹ëæ±ÚnÒ²qÿ7,³Q—ÐÖ˜ ãûýësÄPA@Ç{.Žx ”¹¸j‡fhï_†*Ê&,+WkolÂò 0´<"˜kÆÒ+ØV¦;åŽìJÓ¯{Ú”e?¦(ŽÌþ²ämÂ’¡˜)x3ßL‡0…|½ŸISrÚã“¥—)‡œîS”93…" —”Ó˜B™º¦k7cæÏtžöÀ|¶OçéŽ,Ó1ý‘ýk¼Ÿ%bÀk/˛ژ˚RYL¦_—G—é×Õ‘Áeúuj ¯62g¦4„ÌYµ‘93°‘ú2àeÎ j¤¾"³Ì™ÉTBæ¬j’‘9Û wdκÌY@Z ™eÎÒ1ÖéÎÛ##Ît?Ý‘ùl|çKÏ&4SÏS|B³E Æ¢7þº(ìJã q`曾b!LrÓyªÛßÔ¡ .Ó1Í‘™o:&G/!°îÈV5!Yù é†¦5D¬Êð´ÒÆó”%¯2\m‚±èMHqd¯¯HJÞº1ïû Ê{Dúùþþ8#¤` XÓ1õ‘•pº"ÃI<Š©‘–·nL´"½6v­ZÓÊ ÝùlFzÆ€u:ËÔK2ÀAc›ûCË1¿«Ë÷c|ÄR‡É]—ÿ›ûSËZìžÓƒ/ä>pnUé‹S%×MÈ1ц2Yz­µÀû"{Ò¶÷·ñíþ‘‚Ä\ý&N§Xº2jO¨1¤’Óû6´Iþžžçß'Bª}Öê«;ç+ 5 Û¸óy~~Üï?ø˜æÕjp¹¢)¾¸ÝÒVƒó¼¾"·kòXõ—ç£~ ¤§ ÚÀ¢$oÐÖ¤8 ŒîÚé¦wI™#§_×FÆiï F“MmúuË O™yŠë”;2NçéYUq+ꂽ"êWiÔ$44ŒCN£ èùlET‡çgûüFÛ:}lDTûiý:åÈ 8}ìZLæÕ[Kbõ^põ}¤­ÇÊ€¬Ã¦MÆdnàèËÀ(´HI ux@¾X‡ßSÏ'–´~µ¼EÂvÛŸmzC@+’[e¥í§ú·EHlÙ}~~þ>1RRy\î®$¥/Rƒ|S³"`u3Úñž_c~ç]'\û}_Ÿ¯½¹6¿)3ݶD€O£]{¾„ÜQ7Yûð÷á#©kÌæÈ¶îÚR§wɬôD–¼ô\*z°u¾Kä@cW¤f©f·+ Æ÷¯”ñIÈìÎß”Áæèôñ׊¬ ; E’Ä]d×óì?ÏÃô‚Ô)w‡&«eh#Õ: øß<Šzhms¿Mk¸ŸYÖ,Æ6¡Hÿl¿Ûß1I—¤Ùa©Ìú"€ÏbŒ¦ø,3~q»-±ÍzESlóQü4 #:ÿ{êRÞÃÅ6ÀpÙ^ ÷èw–k,¨ËúgCfƒ†ËuY_â¥î­ÿí’1\>a¤&£ d¸lr—u7 :5) Ê]VÐôHQÐgsN™~î²æ}3 æ\ÏßÏ„t;ÞYMÈ®FH±O䛯,E€&S÷ˆ|§¦ÁÇÌŽçÈÎû>Ÿ?ºé¿ÜRƒñßëªBÜõ‹õS÷‘&KŸ‰÷áÖTc‡³Í‚ŽÚw{î†|çUY}îò.cðb`ÁC´o±ï°wÄg4<ëçôa$Þ“hÚ7ûô.A_™þZ•døÊ$ úòuÌç yaÆÒÆÐ³*Ø×õüDH*bvÆ–ÌÏÌåy¦k¼dHú0–’¯œVoÔœ1öHóé«FHA Ak( i%§$_ŠÖ|ªz„Ô´ÔbÚ‹­Brê¯J‹7Œ´´xáéhíÂ#ý>û£²:T¼óI)ùªñÅ—%-]XmŽ*héÂꉡ’–.ÜB-28â×$:£íTå:¹U”•p„›£ÚWåÀ E#ÔíC¡È`„ú¨0g/«$ÞsZHŸÍ0àG°Òq÷ ý0à—z¥ãâFÚtHº0Bióݼ…ù÷Ý@<¥”ö¥3'j¦NÔk¨‰šÙLÔ$%ã&jR’ÞäŸùñ¸˜¦àɸ˜×)lµ¼‹ùièð1áMÞžúÇ!)óþÔl´‹ùcsí–Fø˜.“Ù¢?CW7'èM~ÙÖ{ÈÍÒ­Éû¼ç¹˜÷Ãæ¨‚°&vã?&ÒÅ|˜ ›£¦>Ñj­þtÆßß®Ý<ÒRï@ÛzJº˜OU¡´‹yÕo.ËŠ”°Êlɼz•BÊUfë8¡öú”» Ö“5ÙaqöJ{+X䘫$®ØÉV*ÎÌbÍ\Æ•D5gäAu'X$¨û8AEQÓ²ƒê>NPuŸ ë>î@c3?#w ±™s6'_È0q¬¨ù˜‰ÎÑ É8Å‹;ÕŸ5B Zês@HFÜ)ÅÙ€¶‹ìS¶ìR¼µÏˆÎ<§OåîY·ùiÙ´?5BžÊÓs¯Rhä Yï[‘i[æc[úÙðü|N1TŒ œ%ég}5»˜Gjh@’q r¬Å \ç¹Y Xuòož‘«$À¦lKëj1'`ߪk=&æ@«®±AÄ ð%Ik1'À—GÖgø×9ë3ŒÜµ>ë1'À—¤õY9¾=˜×·Ô޽`û£™l¼ä ÑsW¤Í&¦¯xÏÒ¼ÖÑV]«$cšc2⬒ s•ä|JH³7êy¿-ÈÇóV¹“ÕÏ牲zoÈ:ï´sÁz¶êÚ³BAÏȲ¶ ¯öŽA=¥š‚÷¼7ù¿#[D¥uõ¯R'5 å#Þô¿ø˜’ôüNëR@*äù„+/Í[Û&Ïï€Ô{òOUÓMKXˆ Hó*uXm¤-`Èá=®ÚHÚ¢$æìÆÔa@J ¤’ó:UmB ÒÕvX\m»ôŒ$Y=Ãfã¥?ÿ¡z_µüÉ#¶63ùd|“mAW®kTã¶…á ÆmIA–ÀðH"n–dYŠó f Ç §+ ésžº ¶ðddB~¼_.„Tl“…clYð—i×¶%ŇXäó@ìm‘IÒ+2ÇÞ¶¯¶OIJ r=mI±B« ×3 )­Çôëñi–Š·¼×®9Â<è"ÛÒP]äºÈ¶4œEعliy“É´s¤ ž&|—JGwÔº¾K¥#"«jPdeKO²-YÙÒ“lËEV))dެ’c[âó䨖¹Ë¶¬Qd–BæÈ* Ý>‹ìYQð¢c©“jÅ.Ç"ô›¿ë\¹¶BlŒé×›®9wŸï¹>£ÿB(úœÏCL§SvÓU¶›¶BòÆÔ)V HfMÎ×®8þèmLîšvãDøç_ÿinéë n€Lzî¼É¼Î)bº ëµÏÀ¼~ ò{ŸÎ³¯NuúÞý½(Ó·Âñ‚€à­s¯ÅÕµW4½Ã°Wd…§zE‹ôjî$Uå½¢€¤Ms\' ^ª)MõZYr<ƒ¹]y£`¦f.÷銤 ¶s±zn!ä®AñÂfkbÍÐo”=kÃ*Õ¬”¬ b•jVröãpÇTÜ,Èã¬Ô<2Õ묄VÆc¿y­ðLO¨Kem+-³2ô€…c'u+3ÞâØ ñlêK-޽Ï«e=нÏÆÞ@ˆg[lQµÐJOV [T- H±_S…Õ€”T Râh0¦…*(/׳r« ný¼åޝUåΚœ<›~†:­ÉªäZ$3q8Þ%ÅKÙfV¨UR¶Õ)(±NU*ÅšJÂ_×¼©d⤤ØáLk2äXežÁ\y†<«ÈŠÄ,Õ*ê¥ìðŠ2ÏÀ*ÃÙˆÀÕ[Yze˜Þ®ÉO3Å¿ÿ,Ï=¶<ºv–H{K»¡r™§õ7«?MWT÷ãÛ­Ë™¾J_ñ"Ú¾6<_¼zôÏ.ßyGKu+EÊS‘ÕF&Õî,–I72©IM%™Ô€”{Ö›mûÑ×9Ô%]üž¦GÚ ¤ ¥st¡/˜£ -£ßqÿ·ZÒY$âß[-¹ îïZñì–æŒ‘1ïͰA|Üß.ÏÆXÀÇÝò›ë…ßœvýZ«Œüæfá7§}Së,YøO×*ðŸªëu¨Þ?RRlˬ…aµ¡+«~ó&[²½^£öz@R*( ½’”äËYv{fåÚ“Yù€³ríÉzòjä‘ÞOÀÝ2Ä@²¦¦ä:¸04‚WEA „°jµVuFªÕFXÕI¤‡ÕFX5 %A4ª©(ZnW¥eÄ(.PGwIÓw b:£ÙáÎÜtÆð2ÎiùÔ oÙš7Yãù¾\~“mÁøe}>›$XâŸië—µ– )HQXÁ—sáÈJnì~q–´ØˆH;«¸àÚSøm5q—–‚6uqHí Ý¥¹  d]`Õ¼ ÕÜçU1]{~C¶k]=ß¼ÖA ³b~Nr@Ãl΢Cï4¤H÷vßÒ¯3½èù:¦­[œB©õq‹KôÖsca°Doé±Å‡ ®8൤Ö•œ,};AÿN1ä39'I>S‹øLÎI’Ï4 >S@J‚øL©èRm*:u ¹”ÞÏq¦¶ù©’–\êR‘ÇiNr©kHæô¼”è‡çûpK²XÎÂú! ©$ëçÌ Ë3¸”-ƒ?M*Bi($¤<¿šÐ$Âi(Ð’ ǬߟuÚ !¬ùY`ý;ÖË뇀ܵ~‰àÿºÃ¥ÚxÌÇé1\ñyÒ€ ¸+½Ø9ºl…Û¦À•qo˜;›¾9çÙaî. s$] K\"G3_6ÂéΗ J†8_’ÜÍzán¦¶©lc(óƒ2 äæRíÂk?Þ?§¤«ûº ¤$ʰÉè%½Ã"–¼óž¥yM†rS¯©1-u4Gf9ÊE ÏÚñÀLÊÛƒÂ{*žxǶbA±ÔûƒóŒµ/ ¦x³ _”´½Ê&< ì™'öU•~]p执1e¦¾œÔ¸Ÿ¾\¤ Þ%_Ðz—|Aµ8C´–Þy_hŽovmO -òÝ™£ï {€ì{„¤|¤Ñµ;&7¬Ðµ;.7DoÉBž‘è ñ[ÞäÍlD 7åË‚‚rSIOÚ¤1P¿'e#“t™/Ųi’&ç¤*‡/åAΕ©dD?R³È\»ð ±Žãù ‰jI Žæ7¹ÔTí" |žz¿µýÕõmUE¤aZÛK.S#$5þ{>¥üÝ—¯²—`¨÷§½ÅÆ/w'ÖáNTúö*°ænQéÛ—Ž=¥ï€”däŸ2S_zÒ¸§EuE/ Ò¸§Em/ Ò¸§Em”€”ÔœOn£¤¢k€é.‰’³œ¾âôÖ‰£ü½Mç)™Ù¡Ó©N^Ê^(ZªpBŽy¥yÊèÏÒ2ŽbSÆñ|L×>`¤|%©WÏöò|Ë$õ€TTƒìq¼$B¶v¾bÖE‚Þ; v²Dª^x¦e #U¿z1æË{±,x ¿dg‚ >umÚQaC3ëgå²hlêA[O›Ì¹á”n¦'/Aœ<ïïÓ»T-‰ÜGÛNiéçg‡‘2‘f¥öû¦/JíãýžÖ: ›8ÁB%µQ¾ûî¾ùuÀž•ÊoI©¼¿§uIæ&ΟÿYÞùõ<ëæ4SÙGüëvEþ]‘ËÜ‚OÉd' ñºT È¥‰ógX}]mæc6]—&‚â/VèOŽ.Ñ $G—ÀÈ}ºDèZÒÐ_SI•îà"¦4]rÀ%¥éѼbJw¨é•=@æêش攋=Êsm0†çwtÄb#k™5©{Œ‘/Œ&rÆú}hß„$–¦ÛÒW@HE#Çüë%_ ÍwI ¶° ",¨öÚî@y@+¶–&@Tùýgy—æµ6´dgµÊ*îòÚP“〚*dmæÔlôP!kgø37½¶œìt¢C:¦ã&àwÄ)dá`@{¶6S°4ˆ,ÉÂL³fÒ²vt«$Sã@¡È/Þý÷÷÷#éÜy#ÝÀÛ ”LN¿þûßßÀþNºÏó©j’RÝ-o$?_•Ë–F±¥zx?5».r‹1l“974¼±ë~GÆíèj£Fí ¥™8nÔ¨=ÓÁNãF: %éü”ï’=ðˆÊë<ÞIA`ä̶ï·ôA¢Êëú9=÷Hò¶Dκ+­#8ëzË¡§w.‰M$µÇ%D%zö´›“¢·’šæœ6 „DÁ*!¤¢$²~±·Šo§äR¨ÕÛ 0:Tu-r¨ò€&³ëÉ‘ª<¤Éìºw|Éxr¤É¡jÜ8T¤F4™À¿žßºzL©¤¥|’ט!û${k ïåYwo}¾ŸØh¹wSûù= ¤Ún!¶™Í&Z„Ä>ÉÙu º÷ý!·>ÉaëªêQ?Ònb›{Šmn7|E»ä‚éÛ<Ýžoø×=U¶qˆu’Ç™“ÈŸöyB¹×%˜ŸåxŠr*I±«gÓ>"R’iJ;Û*Å 9"7¦ÌáŠÆé^5Ã/BJl ’˜Í_Ïþ Sí%4Cõ~ÿø1R“Ìæë#Í>³ù4žš¾AHK0›«ÇoÛ"¤#§MÀsW|×%–`'¤fX ó’œV›Ò0 ˜qúS×)v“ÎÙä%š6NHKðo–ýèTƒwÉ¿¾"“ DD’2cßãc’2U,uD$-ͼ"’‘„4”yJ—÷¸Òs±ÌòŒHAEÒ»$(“‚éýŒß)`œ¤IÁl ’ƒÐˆ¤dJ²õ@DJ:MI«¢ ìGç4ðA'¤dÔˆ4"É’Ï«·8J:Óº$øðì2Âð -píö™vá¨WÕÃׄô¼õU,qE¤ M²>„d¬¯Ò;/ÀWDjº0î<ärmÓŽ0O_Æû)Knª+˜{qzFõÍtn¶Zž¬¼Bf£NH(†õ"âós®¯=BîYòMßæ´ÇD6ê„4ŒØÐûÏ=¯uÒ0_q½¸(#$=›‹ÊÒòí»ü&K·ûŒîéåçîùö]ÞãbÏFí3>MU²È>GA@RdË–n![:"iõ.½uI‘WdƒÏSSö¸iê`BŠƒX1­KJ²v™]—î¼âà’¬Û„Ô\#~tk=Zò¯ÛƒBKÚã”#äÒ*,—6!=Á)¯°\ZD ÂÖ3ó€]¡wÖ¥Øì¦T¦KQ¥.9w˜ÃjÖÀ.Ø&$Û̈F¤Ùo"Íœ†ôΛ5|âj“ÞÏØð‰H‡©Ùu>õç_Œôds;ï2Ë๔9©†´ÒBÂî;_%¤d˜âè7’7&>¥5Ù(ΘøtÊ»¶QT pB.BŠ=BJÂ@ùkx»á_WäTaÎaæ§õÀyNÁ~ÎÒ1í‚}Z½³CÑ«‚ýçﳉ ö)éØ&íÚ¤RF˜—×îò÷”Úâà.¥¯Ã–,MÜO+˜É:@”˜ò™®‘`”¾´m§79å†VqR\0;³šÿŽº”MXCVêvìfEo„Ü3ÚëV½÷ïôë–â–vKí÷==Mk9ƒÚÓ©®ð1%…¬úS%’yÞc6Zç=Ú¡z<RcäL^[CÕ<iV¤äJf™‘Õøxöø˜–B>içÊ­õeÚät¹…•¡?úal¿û7„ô™{yØé…k?>øÚ£yß? ô  ïï[h‰X°ÑKé4˜÷ý»ÎÐ\ª8Ó9V¶¹9ûXÑ´dž»M!c‹¡Z¡RɳŸ+qýö²vÌûè,âj)èti›pta$_–cÄ æå¤K¿ï½´-º‚Û˜æ4ž¨+ÉÙ˜zÚNHAZ?- ©&œày9s´ºñ\Ö£§í„TTù}Þ˜²ȄԄHàgò]ҔȢMŸD@"r§ü>ßv ‘{" s1‹€DäŽÈâ E@"rGd¹¢,‘{" ÓyÎ9âæÚwx:ËÈw‰HOr@rØæ ϾHË0P©Ç¹ƒÒDÚ¾g7;Pñ?„™ƒ_rj¼5X ·bO7…¼ ¹~5äúE$Qî\¿ˆdBÁôܽ| ­7mÚÁêsD*RLgIýòwä÷ƒÛ`ªÙÝ›ÔÊñj‡ï5ô/Ÿ_)ÌðŠá»¦•¾nR“,¶·7|L³Ÿª ïýµÆWd [wûMoWD#©Â< ©ÙAÙĘ˜æ9ÔIóÄszî-?²Þd&•Žü„ôä.3T@G>"wÓŸ¡:ò¹›þÌ­Æ:§?ÞS²Pc²eQ0n%°![ãV²¹#¯Vayµ Y2ë@^-"%³Õ´Ÿ )XA®¾ ƒhÉrŧYâ@+¾ó©èbK›ÎS2v‘€¦2!—þ€¡,4»Ëä7¹, ϦóYÖi «štž\´ö»l_)¨ï(ÍMȃï(  D$ýE«¯ˆÜ|G÷˜þ| í #½o¦_/ V¼µnÓ[W–,²ij„TÓ'ÉÀE¤¤‘1™ HE8aÜ’®ô„„1í‹!ÚÏÐÄ4­,'tÖù²ÜaýÇ©©q™šJÇT$s³…ÌÍ ©Éx©†Ì͈ aQ˜ˆHCĦ5¤Ë1CY6ž‡È£]&ß%wPšx&¤g›)à×EÁÓÒRüYŠ’Á &ÄAL›Ö!y®4@*v<7±¿'¤>@ƶÜqjkHö‰™†ŸWËë§°ŒOL;åiMŽ™ž?Ïæ~9E¤'g û ¶‡JØ4ßx8µpÂÉ•² &œæ0á‘»NœpŠHjÖ$‹•LÈ]ûR¼Z©/Ý|žÕ£w ‰•læêf±’&3¯6¿ÿ,»Ìâ$»4£¿º÷¦Nû¦”ìøŒ$ö¸Å«¯GHE‰F7 éX©Ó¹[XžkF™þQJÏÓ?Né~ªâ`µIOS•¤§K‹¨Â¥Èt?•àœ0U8 I=—LHÎýŸ'çþ‚‘†’IÉTဴ4²Ççé^›hk›Ä!J2Nl(JHó5"G•Ð×dϺ7‘£J °oòû9 $cÝ;6©Hd"G¤&槇dr0!CÞEÔ##íN%µƒ»vhnéˆóR9-æ€Dûû-ÕXºÏ±}þ"$Sc9Õ©ÈÆñïo‹šªÆLï3>&Qc9W×ói·Žq¡Å|oÏi?RŽ ½xBzn~9—>Šӯ뽹ùH£ª«aHw^ V äGЀd ò#h@²S)ù‘æ&ƒQ~¤%é·„ÄÝ&$“•Cq·ˆ¤ˆ"0Ûä“]÷ÖºÇÈ=E®…ŠIDk@Q#"--—Vm’ –‹HAÊ«¥¡Œ€\e ÿ]üéC«mÆ~ÊÏ›_W´dÚ¹ì2¿ÿ›Ûë×êºj«çiŠ•êí¯¯»ÌßYÜí’ÎsœÛ¶Èu—ù»œgˆTrè0Òó€ŠYjRtÎe²0hDRŽq°¤©0à(]{F/8ºÒt§ :ÂF$¡—a#’ÔK¨òWlJV/¡Ê_±)YGXÓÆ5 ×Ö Gü†t…Ò¨dнõåeØaÊÞ§{•š!C>O]Îa³MËÒ ›«ë:H;ݤ6  •Æ0”ûï&÷7KcÑ÷ŽåæO'©fBË?¿ÿ.+X•z¦SÜß´-FJB˜þ”4#RívlgúEÔŸ˜Ž/ ÞÛé×_eñ¡•ΩJÑoVþ˜–›•¢s­E§ª¯mõþr/ÛEŠ®´3¹þ;­Š±·[Ú‚3Ý]¶Ò–t_»{Îm¡!·ÃM!¶ùùoÚòÕç5) ïÏfx $%° «ÄV0TöÙ×¹ÅÈÕ“ «žLHI¬u#V=‰È½’!åwþˆ 4àkß!ÕãG B%Mš^yH*‚ÐÍ¡ò˜ Ôà3åBÃæÑS¡vÌ•#š ÔÎu0@* BÍcs® A¨ß܆ To.ËíÍ;¸Üa9=àr‡eÕÏa¹Ã:Vº”;¬;šŒÆHn2# ¥ÊÖ‘“Ñ5.wXÌn·^¨m=ãà…JÐvon+:áSWB9™dR0HA–“‚iD’%è¤`‘Dð0¥4iÒ§¤Ål–jÐz %j2µÝkë7ТÙÒ½6~-š )¤õÇ—9÷Œ¹£9÷´è8EÈ2-$.0C]²7+ÎP—ˆBg¨—­ÌP— ˜¡žÓ0C]" š¡žŽ9ÏPŸz„Ô$1,ÍP—{2@ ;5)`†²Wb˜¡.…lN¥×í{M¥§€¹zæV£3dò5àV޳¤X]‹[9Î’ÉW‹[9β  ¡à9™Òâ†ÂžàPœrB e¦¥ýùïÏœþ¼§æÔüg ãû™iiò÷‘Ô|ÄZ¨¿î4¶8Aö’L{[D°,IbX Åò¯+’`Y#‚eéI°Á²„İ Á²FËÃ6Ë,KH Û|G-"X–¶ùŽD°,1lûµˆ`žšöâtžš¸“h¥çŠÕýé”XÕ¥7”Ãñ„üþ©†Z{(¿·!KtõÇÐÖg„TÔLež+½åZx`¬ô–Ü\´ôŽKj`ÑÒ;¦}yš£t—åï§ßßßßùb—›U}NÿNA˜ÈÍ”— ©®Æ±JÍ”]eúþdoéF=¯ãôžVß_*#ôœ Õyºþéöw†ªìØ1EõË­zœnCÓu׆êÔŽ?ßn—jm}æIòçæ˜d™87H–£~´§ñý9=àÍkj³»âûum¿nçS=G¨ƒFŒ—õ±Þªii>½5µ¾æ<þÞ¿{÷9v×ß±¶¾þ™ŸÖ-h1O—õ3íŸ]Jª´ŒÐù²VºÎGû~¿¿½å˜9@E‚¾Ï™Ú|²ßçϺ}9êÚúúû'´åáâ) ù}>Þ7_ªºÑð¨·þ§Ã‹ÐD5ÔÁ… é‰C5¢×Quð9&uð€¤*ÓÞüÛ#$£%zÂHMÖR< )-QPÈ]zâa6ç¶EH·Kpyާ ¬Ñ)ΛŸÒü<çPøºt=ÏG=ä˜,2¶*™ã0m&c‹‘r¿‰øÅFÝo“]Ìå®!¡søu?˜Öž¯÷®OJ‘‚sj=/•$Œ{yHݾ·C÷6 $a½4m÷UÝ ¤Š½éµîåžç˜ê’VyP@HAV$ÔR{óm€‘¬Jqd0 ™cÛÈ`@2±±*Å P]EHMÒ屺Š@c[‰‡¹+œŸ»fTÉféûªGHZ´£Ú3O—y½Ÿ¯¨û¡ïûí¯ïÒå½ì®Å¿n)d—+)2w³¶# ý²Üå»dè*|5ÞÆSŸî¼eÇ ësŠŠ¤åìYYDÀqŽWå8@¯¨÷ÎaÁå=Å%çßÓtgÇ."óº4oõçYçwÝ>¿šÓ<à7Ü2¹(ÏÇ\û¬|ûë%}yðãß?Ó¯ÏOs}•§ØmŽÛǪCHAŒ™M/}TŠ¥nQ@(q€LuF%ˆ¾Â¸ËJ²dè<–»¬°„R„²aµQ6гbk6ù|‹Ö¹›Ï÷ˆ`D­ ¬rÍÖ~ÿnj—ó`Rzç•庭 K$”;@æc:Âð«Â†_Ò3'`ø‘”Æ1¬ô!JTé›6WTéÓé‘ÚâJ2‹„ßûR5†•>h¹;”•ž»~ÙµQ TxóHÜ*þwØ`G2‡,SžšÂJ-@IJ±í» ·çeƒ”„²6|“5'„òy8&±u:Q>Æ$ðš<Åu_Ϧ?#¤¢º­§SZC´â»­U$G ­ønë­~"¤ÜÆŸUÉw vÄ«f©±f6€€ºŸÑŠׂµaÖOT Ö†\?[ÜÿЖ¥Œƒþ‡¶œt › 8ð*sð3ԩƪA5öu]zvcþŠ=-P„)øzS@¦àëMIE˜‚@YêMYE˜‚¨7-}/Xo‚C/¼+To2%Ék¯E ëOÌxpï*oî AïÇHΞö~ŒäFaïÇHp—P?¾jp?Þ‚Gë:Ÿûñ†b’ÍOõãwÕ<#ë õã¢úñ3öã Åk™Ïõã ÅkY®öãb„ÃÆñÔ¤œË(¢ö£\³6™×²5ôlµ] Á—èPÛ…Ñœ6ë-Kw c^Çòg‚ÔêµÐ=)‡ƒÿýäòÀc«~gõw„¨"y £ãw›Ò„$Æòçà;Å´`ðãÕ<òV…qŒyÊ ã² ¸sÁ‘]Åê¼ÖùÅꃠX=â_W;µ‹¹/ k–¬]¬}Ù\»°˜+ƒØ½H~EØ’B[8g°féÎÓ€ø Â ’: >h@î® 5âƒä.t@|ЀÔ$-×Á¬ ù âƒ¤%xl€„h”åe°æ°V’¹á‹¥ù"æ‹XM÷¤‘~®È£,ÓõÌyñí}¶µ™Ïs /¦[šï’e9g ‹´î™â:ëx£áÌgBŒö=£á´*Z`4¼AÒFÃIŠ" Õ>»ño=ZÙbþ+v/âß@–üK †ž»+I?Œ~àŠ+ƒ\…§É¦‚0]Ä5ò:¿Çhãš ÛÝc´#dZi£ýuÀ¯«R¼ä4ãY2e¦ubB8ÃÉÑ.…„Ü—…Â}YG U-îËBV÷&Nnq_²º7}Ù÷e݉ãèl8›ö÷=ÃÙÔÅl¯×&­óÎyÜÒÈûü|»>’ˆæü¬ÁHE°€4§ ¤Nà #Uç iÎq#ÍrWŽIs$Á„€Òœ©I~Cóû‹;²ÕFš3 -ÁoÒœév„H°CxÒ÷h^äa½Î—;BW)¦…õ%/˜šª/Ñf»Å[Q´6nüERìV¿H@™Ð_$ )’˜Ôä…W¼HbÖ¯8i9¸†xZ6bÀUMOËFÔ¸ªé9ATÕôšòš¯hî ¥_7¬|jfÞr²@˜IxËå›0RõTÇv\w®©zªc»D0RõŽËaaÇÖ»ƒÉ¥ÿº&3Ó©zÇM.÷Ç€ÜéØ.™)ìØz<+ù ýæ+öÌâƒzOv[Ô ”PŽvÏ'rŒ2F²(Ï’YÃ)F€²(éXÐËBÐ5+4B/ Ap߫ͽ,1B_mFè%Ž}Íø`×Rnü€ÁÈ÷Œ]KYH¦–=!$d´ï ³'„„Œö]…SÓ u‹Í<¯kݳšvìú^ã_·ûÈg_mŽéhK„8;þu๛ èˆï|ñ:ż@Ÿðe’yä{šû–*{ªU¤òN‹¬z$´.~mÚÎŽWéLwôÈ¢Þ(*FÉÂ0#s°%ÁÀn˸z¦ó¤Ýç1ICŽÔbÃ. ²p {¥g¶„ÔÿW’Æ\^ŒÇ4ý=êEn°Ê² õpkÔÄ‘eÉ rÀà_B-àQzš8iÃ&βԃ&ŽZÀ[[ܺֆqLÇŒ±Í Œ¦ÈLÓßÓ{‚Ër¦éï«8}o~]íYܵ¨,KI™cmtý$ÔFÔêµ›©Õ²Ô´i4¢VËRS¡ÈØ"ju@Ê]ú¢Vä®Öÿ€¨Õ¹C­^Çr2µ: ÷¨Õ ²Jeê€Ü£V¯MðD­H·k/¨Õé)ò}eiÈÒ÷œÎ̵+„ÜWvž‰,©i+KË’r1J–bG“Ä€,™ÕfUX‹k4N~Yç¡ÂZ@r k5Bî(¬Õ…µ€äÖðyR kmVX È…µz£°; kõFa- 1ÖFS$äxU2º<“e ¯N·~£¦˜d‡.  ¢Üºˆ‰94A”{CQ‹ ™ Ê¡‹[*t@D¹3t±jYVD¹7t‘ËÀQn†.P« ™ J4t±-_@D †.~ÿù¨êñMžÕ‘’6‰ŸuÓÀ×Á™ÈÎSß ¤ 4ÊA©A M6†TjB“¡•’ÐØ…¥†€TDÌ“)aˆÒͲ΃b¾Ü¨™o qÙXB5ó}3¼tLOÆ Rµ–ÂõµÄ”ëRœ2>LådIÒjD7’’´“_ü2ÝHÊ’¤µˆn$eIŽ» ˆ~ !¥ö…Ô éR Bpg ‚;Ÿ )IóõzQ ޤ)%9Pº î¤AJfhmÖîð¯+Ê"4+JÉZ„V§1½!R1;,T”R“®T5Ò¡“Ò0>[P‡NJCޝ#)úÝÓ= þ¨Á*%óM‰T#@@].·¥ð>ý=…ýß1™ J@@ýo™ž˜ ½a×¾Ïþã)N–˜ Ò-ιTÁ¸Ô œKQYÏB 4]‰¨ª/bßÏ6e¦ªÜ=æ=º•t±-%7ºç°xÒo®H’íòµË% ªî¾F"·TŠ7|íR¢gøZÉð5 %Aµ-c©4EôZÔc3ÑK*ÍŒ]Ÿ¤2ŒÖj 4L¥2»ä±ðŒ°)Ú3£EM µ¿qõ`ÎÈá\*Ï´Ï`‹SrªÖˆº&uÉ·äR[* é–\¢®ä.u­FÔµ€Ü' wómŠ~©¡¥>n´Ô%aÓZ]0RÝ!‹¦Ò7ÒR—Z4ÅN5B*2þLZê©©öYÖRH¢)µÔr¿ô´ÔÒc#@sSju06’*fÈÌ~glä™öMÖÌ~˜B°T‰Ê¤Ö})Ç46;c#³w/ Hfl¤ÆHfl¤ÁWäHºû©Mß¹kÏCj0Ó†ñ9€k‚0·†ñ¼¶t BIm©ÖöF* ÷«pH* Õ-@ ©C~€mS©%´4í†(‡Õž$vˆØ»¶;’ oAbg@î;kDì È]b瀈¹Kì±3 Á2Hì È]bg‹ˆI8ÂB¢—„é×@ô’¦ ˆÇK¢JHfÞŒÌ ¸R (Ê{”ïSjÚJ#iIÜ>3t÷<"RsH0 -¡+À«¯óOsK{±e=­agÙZ†ò:ËÖ’åw–-Ó¶¸³l-9n9wÿç>"ù£7ÄHÅ¥êõRq) BDî=©¸ÿºÚmPÒ±âbð¹»òÀ bÀHj@¯ýw·×Ýã(_Þ;Hzö­Á®¥£…êZÜGTê}úVúŽç …è[ÎC+5®©:K ­¬µ L”ަ¶ˆ (MlP:Çe=€ (;Zñ¯k2—ITÀ€¤†V0 wë!-¢$í_•Dú¤óþUéÛtž'ãåïÝ</ Ñ$CÆ{`äŽmµ¢ HE‰MŸR¼ŸPp|g¤«jR…Ǘܰ<¬r ‚ôË`;¬rxñ"#:w€|+½ä\ý`=R”7Tê÷7¡ˆù¶#†û›^1¦¨¿ DÌwꟳOw:¦æúG§,+=ç댲r$ºýB†Y¹·”üܼÃÂ>¬wœ#ìP%léÆù¥Úš* N¦¹;¥÷Så$4“EAUSå­´n’¦•&'!¥Ÿ÷h¥©¤Š’¢•ßͯkÚv§ÆÇ$h¥íL+ÅH‚V:Ì´R|EŽ6Ò‰´Ò€¤i¥ÉG'Þy†VÚ×ÊÐJ7gZîh­ŒÁìªJ' È~™OL6•¹Ç«rÎB"ª=»î9%ÑÉMeª*üùŒHM¶{jÔîQ…¡ÃZÔBR€Vº“ O^!Zé‹êÅÏÐôO„»®ÍÔ&²¨*<9á2ëádM-Ux²m: 2µ* ¦}ËÔª,H%•©Ò‰Þ\;*S«²`–åyˆ4†ÊŠ$µŽA|HHÁµùxLI¦ ë|M¾öƒùš4·ÔŒ|CJºÁZ£«*5«kœ©ª4$íy@ k…(‹/['\BKËÍæ¢„‚äÆ]£Ù¡GHÆh6}¥;0š­ð¯+оU%* *=OßJ¥UÒe‹ÊÔJÐe‹ÊÔJÐå€ÊÔJä”Ç€ÊÔJ¬9ýôëé˜åÁülúŽDÉ•UA#XÑ”ÅeµÉ¥Z%iª= F°ÚÕ‰†¥ïØV{”EX€M`%iª= F°‚”Åײ*h+!hÕJÔV²øºÒ‚¬tPµé""¾L‚ÀR EÓáP»Ge"â¢#÷v9_cn<ûÎ;|D´ŸÓ^<-`Ï èÝ)@ÜÕÊ«·plq«‚üŠŠ]¦Z)á_È·‰vòünÇ´sIº\9{uT‰ª€b'ÐJ^i—KÛ4Qƒ8 å¾5é¸z¤ÊZ³™åzž—æ­oÓÄz@j"áIŸ’E¹ÚP”•,éy:TºQ™^ž{Ò4š÷é&U÷KDJ2IYÆ…NùŠý†tsæÛúJr T/TÒ쨨záóþü>Ó·ÌŽð[ò»”u#WáãË5Ä6ßÕ{ó1}œQø8 %áÚŠäJ:Z5•¤çÐ[ÔdT’žCoQ“QIz½EMÆ€$.°Éšl£¤9ô€Ü¥Ü ¨É–h£€&c@ºý7–U "n*VJXR¨PŠLc§5á³~ä7D ÖÖºJ¶Ö (aîÛZŸ1’´µÎ—¹QÏÑP]SJ²ªª]Žü•bhp†T)M&û=š!UJ3é]‘&“ýÍ$7CÚ#$7CŠ‘Ì iƒ™!Í‘€äfH„ÜMök4Cïün²_£Ò-)(ˆ/t—%²H` )õPÌ>Z”¥ÙV8hQLêFû,Ý‘†>m‘Ô%LÐ`éËÌ#Lá•§L8–ícÊà#RC{ÚçR²¯É~hHˈü¼gê+-øyÏÔ VZ½à8ÚŸ ZP]¹¹ÌÓm-y3Å\]äå=óYiµÓÇ2;çtíú@f'}tZS¡r´MÇ4t_lqvKŸ¼¶äÓlqAF;¦… 2š”Ä™¨ £ÝcÅítœS?G¢“¾]Ž_ܸ!?GiOΩ ˆŸ£´'çÔZÄÏQÚ“sjâç¨}Ž_ o?GAŽß–¹‡ø9jã—ÂÈÏQ»? zœzXʉ§r¥9=Ž=AeŽDkü늘–‚©‡)Éä´Eý&eJÒtg–÷»üë‚éƒWñ”BP#dÛÓb$=cRAæ‰2tñynCÝWL|2pÚc7S®ÝäÔ8³‰cF«eÌÁ1«Bî+?L¯ržÁWëµ-šÍ3ø¹(‘¥8Óôîí’ä¦ëçw…)÷¬4îý”öåDHq¾püF8‰£ »*Ââ‰ñ\ô—’¸Ü3–Kß‘-Ø7$ós`1íÍÓõýg2q¿äíb°ásºýÏ;BŠ}’Æo—µª’TPÉ“8º´ÔÖ2¿'°ti¾ýïÌΉß{éÈl@í]]zV™$çÅš£®¡Þ™¹Ò¶#$çhQrÖ·ó ’Úãàš,S¨ED É5¬;] uаο®ø†ub§kd`¿Ó°NÔJ-Ô;“c§c$ÃNoð¯3ìô“c§I7¬;=Þy¦a¶„eÖ›«/)¶*ü<¡àÞ®'΀‘”TÐáׂ”ÿZ_ûTZ HA ò¤† –ýË< -×`Í-<+–ÕŸÓ‚#7ëÓ~¤¹Hà #mø“ü&kËϘ¤—Öö`Æä‘»ÃË*pimÉY­1´µ¦eajÔÖ×4‰hmŠ¥f¨6W<É©)ù‰¶\èØ¡ ‰¶\è0%-‚ ¦ÍÐ¥a=sm†žÇ~ú¤+[¯Ãë{ô:œ"5xí‚£A‚Š6’sRD ½w_™Ï Å©æçéRGCØÝvdJ‘ÚI‹Ú‘ÚXV@>ww  é´Ó^lÜ€öˆ]Q#ó§¼sÏÃýTv¸Rì =Xw¸ÒÙâÀ«Â¿®ÙtÌ’±€²)¨¡õ<§¦­`ŒQ¦õ»J‘ò6}E‚¯ÃJN*îVqî·°|a⢄Õ,1 ⬡¦<áJsYËÙˆÀ•ÖRÒÐÕ2™Ezµõ¤EEDzµõ´HïÂeNkˆã ° öv%ëLIš“¯YJ é;r‚@€ '9’0°"ÒN±Ç §©bT×¶ßMšŒz#_³m‚yõD…ÔmèéÕ© ®Qáµ ÞÕ¹ ®Qa¿ Þֹߟ~=7Á5 *¤&øý›àCšàvšàYÊCC¢Âë3Sg9í™û›î’{!¹ÅV×ðõÞ=SÉÎÑf+ÃsÉx1R€òÚ¥ ’¶ÕçïsLóJ8îNÁŸRMÀ¼¤m"ih_HÚÆ)cíK’¶7 âœö‚1_€Ä9í ›ð19æ!5Y*{^’…÷Þ½ÜTÖKŸßºï±éÞ?#R1»ÇwŸ¢J¯ºæ|ši ò5;ôX¦>¤¤Ýðˆ~¤¡õý ICk’~¥¡+üëŒ4ôÉÐjüë ý ÁWä¨ÜTöÏЕ„™"oÙ1°syÇáÀª‘w”Áª‘wmïYoÓ/Fºg%ÎÅ+2EAUt76v¦(Ù™Ü|?M!8!PpE†hÁßC. ¨ô²Í¤žs&uJHMeRÕ\ûÌ™T@îד§»™IfÏ”0 pMïHúŠMaH;‰ÙI¨óJÊ9—!›õ‹ÚÉ<@›®ÈÓ÷ ™²`µkòúiÊ’Õ®©Ï1›0¨ ¾W÷Nïg)êÞé.•tMu­{§7¹duÀ@™ú-;Íå,§fJµµç‘Àô½£HÀ””,áL¡‡‘€ÉMðÝH ûMO4Áwln¦gÔ¦+¢å=§Hõ§O{œ)Y£ýšÒr3]dc÷"y( ¦$M37ý#SÒ2eC)7&7¬…Šy—YÙcÓ=ûé?U‘%—wÀw^ˆáô#aÐjVFHŽ4¿ 阊­ ä]Æ ®å«YjÎÌn×2ÅK jd„ᨠjd„åVoГ2Âqê[ jd ¥ª'/¢ òl :Ç2Wž,¨Êsעʳ¡Õ9f$¨<¹¯Uuä±Tá1²${5ŠÒ<’d|¶Iuá¾)%;jš+f†¶ÊZGMS¥ÔìXe¡QÓT) Èýþª”¤¢ç¹b¤æF<@ÿÈHÃŒWOkC^“¥åS>¦cº]üY?®Õe^ë~ªïË\àúù@H±›Ë¼··<"rïi¨·k¤‰ücå¹~þ<›ƒ©‚ÔªÖA­fÄHA ¡Ïßgr?ƒžS¾#EÓÍQºQ%+œ»-F‘Ò¦k'ñ. Ù± •9fPt-}@õd-½vKë!ÁÒ/)y X:â_W»æJ8ªTŠ•¦Fq¦Ãhç¢;¶›Q}£X›0ªo”%ÈöËØ ÛåH#¤‘ír¤R‹Èö))d&Û$C¶ïð¯3dû rשGdû€´2“íÒíï°j”glצ51`‘cÞ Qúµ+”«¯F—œŒ5§œSÍÊ9é<%Ëö9%¶Ñ’7`Ío²Vœ)!Ì´"ûê#ZtbÕ(K}£5EÉ¢€o´¡¸13ã iVµäïýtªé×-¯®9>Ó1ÝA_&?MЗI¹¡ö\îïLx¾¢SbŽSR‘êÚëÉy±t×r&Bæ˜3-š;8à˜jf9Û5¬¸ý¼§cfTÊyrõÀVâd=Ʋ7 Ó7–Ù7Q&eÜØõ€‘´®)¸ŸžN¦oƬvbæ@[h'¦ó´%Épk9yŠ ºԵܱ¡OC@v-_*<êoH‘ȦHQÕœu#Œ¬ÙÛ‹Ã×ñÙ>?Óý´Ì a7žò¾i†^²¸VAÈ¢º^ë¤öl€9Èרió¯;–•Ô7?B2¬¤´sYwÀJj„T{ý£¥jÔ¦lÂznµ©¦¼£GÈÝŒoÀù&Ý]] \rõÀ•cÔ¨£;õ‹ÙJ2î1Œ9È€8{ÆI~X>ÅNms`’»ÈSÄ»„º«;YÏIg=]÷DH*ë1­‘ãÝk=ä7ÙeÛµxž±š=ýò©Nr Æ™—æjᬦ°F€ïÝg=&~ˆq‹ÌܲŒ†=ÓW³˜ù‚ª‚k/Þº”MÀNèî[·A2o]zî^ðo]•vØÜ Ý{ëž`ýôYñxo`ä†þ…Õ9¿ ¡ß1O UD*–‰"jÒJcU<ߑל ¬Q{ÃÕ¨a•tî^ÖäŸ÷oøŒ»&g~“;w¯•ünéé÷) ¥V3xÏ®Š¹«n‹‚ÓÙo²Ý˜n`Óáá‘tàmñbq~ Î]û3~߯O„$L‡ç¢f¼Ÿ))eÑ,*e ÖTJm¡Hщu’Ú7Aäo ÍÜ¥™™“ïÃÌiN§,Åc Ãkº&ã³€$¬™]Ó!Õ«¨Ô"ÞÒ¶ýg:¦%D¥Vä0¼7)öÅpfýÕ±GHBÚŽÚÿº¢$@sìm w šŸ¦£Ÿ&ª{ÛÂsÜW{Û²àÅB“ÈŒ-a¥ôoX½ƒH×s–LÏhãOùŸ=ð±eIV$æªfîËØ’¶ÓÐh¹-%e¦6gR§n¬Ò)nn~q¥>ï{¶I^QîÙ’­]€ [Úƒ*GÓ $5ߺұÂJyêÍ–ŽË¹@mÍ–žíså:˜wa_×ù*気ǔæ;ïv"Àˆ¬¹ûbÏŸ¢^äb¾rÇDo>ϹpR#¤ÊRQWÿã|þ˜uõ/w„Ô ¼^ÆK×O¹D['ÑÈ€4»¢‘ïíNB”¹Žÿý²òÛ|·çnèñy:JF#ÏYáy{¸+ZYp~4 újeÁTta7Ð’}Ø1Hª>ãy¢éÑá>Å R6 Í:#†‘»6 ARõ‰Š”yI³À–÷S˜ç°RqQ%`ÑX©9y4UJÃ˧$>ƒ•ö RšöbÉÎ,·¹Ãh¥çE¡S5ÆïƒÞîô‰¤ØF Cxz=ó1UA³’Æ >#UÔÓº»–{5À!f»–ìZ®Ùn®¾ZصÜ¿Ê]«$s!^UŠ“9—Uš­Ó‚\FÞI-ÅÊ2žV°ohɾá‚}CKö —©7Ð7´dßpE澡=ìnœHFî²dkÔ7´dßpE澡eú†ªðXÅHéâì õ _¦avFÏ®æCZ—tɲÑ@¼¤Ë·ÈÙÕ+"' «-˜‰œ€,èb' é˜È ( ®t HÚ (y¤&¾MÀ‘°Z“~I-Ò¦°ZóÆÐInÃj6{æZºÕ–Ëe`Ì ÇÍ]K«a-}';K3#Öpz=¼vS0¹L:ŒÖ”œQ,è™ZR´|­Û€ ÅHVø d(F"O« \¦Šºó³M{èEþ»ÆŸ ú­Ÿ$+b?Gøœs„!%#¤xÉ(B¬iåì厅ÐdîàX£Ø}ùŠô»/íïF“æòÍÂWLQ1t¥t çǦ«"Òfû‡\Þß“0òóÑL/S7L‚XsÄI+˜9àÆ<ó×qÀI“ Ö¸ƒIÍ1™I ’áÆÔø×nLƒé¢âòu,¹Ìüu|9Dk<“íþž:ð{ne€‘ª-xóî4;`Iaù` ’ó#[²ø¹–ní'?O½ÍÆ=阂7°Î1˜e•pÀ$ˆµê€k”¾M«¸FéÛ´š™€b¶ÖV-÷;¬µŒÆ ´œ°Ö±ø$€owz»iƶ…øÖ²³u÷ÛàcRù»e]ÁÌíBîV@îÖXÚš:YR´|íˉ!߇8Á™)4§SŠmœä¼JOÙÒÊÑr¬o3Fc£!w•‚±QƒŠfŸ¦¯Ã©öiª';ŽÉ`ÒÓæ¾61ý”*º°_ü¢#1Ô w†ÍaA=ÙYÞ41I¬s ?ä§}æ]ÛyVhúÔU BŠ=÷;@owk¢Ñâ~‡/È©Ì÷;|ÁÈu¢~‡§\wǃžõLM`ãK¿.بòT¥š•\&ØÖK.׆OÖ~çÉYÀB´›Þî XˆÖkÚ‹™§XoȰE“ õv_‘y$ žK,œ HI Á$H@*{ß—Ø{žÆ›h’e½Û™ÒZ;¶}UŸžçß'BîÛM7~ºõ'„”r«ŸO„T„µÐôç#Q=ù²ÎAÏ È'¨'{POÞ Ç ù£¤j@ÚÈúXjÔË1ïÍ3U9¼Ëò’¹ÆÉóâùœr” ÒÓwþû‘ž¿óMþ:üÁ̇€dî|ä]$sçß’¹ó_øŠ˜;ŸŸ¦çîüïÜOÏÜùëó±Ezš«¿W\µì›®(*q?rEɪæþ‘+§xê ®`ØhHuÁê Ê×W°&ƒ òw…ᘠúê VT_]Ázg£cz^.U³]Y°Ç¿^–Ä„oµÑÀtä,pµÑÀt`øµ&¥žè€c©ç ‰¤ž’¨@©ç€”¤ºcêw¸RíMi%Iê¦Óµƒ*ǰø(È=ê:²èª'å–¨9V½7¿)Jw%ÍWæ }Ü I†FŽë\i¸¯d|®ä+{ð.9V§4g®ô¬Ni®ƒ$iW”k¿Žì¿Ç9”Œ,YÝW°ÚÀ©á‹™5³ ·‘¤†oH½¾!ñÚ¡$õæ ©×7d@ÈÝ7¤^ß!%¥„“«šNPS™KnסyC«ü. Ã1à"Xµ ©:áXdŽ*ðôœþy™VŠHÉdЋoxz“Az‘•mþœ,yFV²ùs²äYÉæ/ iFV²ù HEwBÓj#ß M½'«Ð'Ž„“’»ó@!! ÃýDS®Ó]zo‡îm@HI=£SªndbɮֱÂ3…6Ý“´¥Ë5'9‹ÈÝrüÌ2|?¥a}ØÇä,ï¤åúqðÛ”ŽE‚/N±æbŸË©#Ö\úÞUAβՈååTyEÆ S%§´ jN ¦s5Z’Lü 5Z’µß|žŠ¯ý6#F ¢¯ jþN郾vzç•æûÚ©æï”æûÚ©æïÔ¡ú>ONý #™¾vék7øŠUÁÓ4Ï®@óS§,Yûm‘ù©ƒÓÍ[5d~»+X‹ÌO’3?­R“æh©å»2À(Hy6ÌUw§ ¦ê»ŽÓ£F•|§Yf#`ó:-yû’ÄæuZ2Ïj`:­ÈH E˜N+ÆjyöîK»¡ÖÌüæ´q»¤õ¼y¶¦ÆÈ¥"1m›a^f‰.žíwÛŒ9VÔÐ4çµ#6&^º£ç‹×ŽXbh8f¾xÀ ¶\¬zúN; "Uí¹w æïôÔp˜JçiŽrØ´š£6½ÉFpSØpï0ò€á–¾ÍÜý_ûGóÎqYòŽnZ@æ4§³W—NÓe­Ï?«K;g­9qÀÈŠ=>·éíâØ2²œ“d °E "‡¦†_‘™Aäœ:è ¥/Ωƒ®PZ—\®œ¼Æ °Sïœf¢ Ø©wŽÖpÃ\8çuˆçØUÝ3ý:ÛÛ…ë’s¼ƒF^mœç4rÌ@öv—IÐÛudowEæÞ®#{»KµôvçÔïao×y¨~ÿ7ؤ†nõpZL<"²’¨QϪžñ¹¤"xk`‡õ…än`‡õŒáïbm™Ö:ÏôøŸ¦z¬Rª ¿ù~^$ÕX|a¶ÇLÃ󽾥Є/,ï{€:ƒgL„[ÓúÂ1K…žEæ]Æ—"dÉh%€‚‡/áH2ߥi{¯bçs‡qaÚŸ§\»Zªpm;Ý¢÷Ï#×îÿb±}yŸŽ7éÜýÇûðU#d°õ ÓyÉXó»ï¾6¿®ãÌÝérY^¥jžé«Ûpj„\»ÿÿû³öô/k´6s¸Çø3 —ŠÙŸéŠæêAµØ3ÔÍi+G|žK÷ÿϰ"וvF6Ó]ªñyúù¿¿y[Ùt§×Å;_@ÐÛº|?ûÓ[÷üÞ\|°õÜèeö§þö¼l®©¤¼žgŽF:NJ0ù=QèÔFL¾T¼edÃñ¥>H9‡ôëæ åÌ÷É0#‡óÊ”–zhz¡åg"_Ò2nJ}éY$XlKÏ ƒV‚?rNIŸg4WÇó%ïÞp!hšî*7IþÔæíf©çþ@ „’ }Qâsg¥žÑ*4‹ £0Qvú>†tçíÁ]z¦+:°õ<åk÷ábzî{ V.Æ¢™‡ Ö`Ü×?a®×Çïã‘ù¹Çñ«å4Wêoß¶ù×s é÷ï?©]¾ /Sìù©RÆüíæºÔÿ3¯6s'a~뾟ïã㑚¡ ‰^—k¤„]†·kH‹U@þÔõùëþ.o—ËŠ|7÷ï¦ÿHKíŠô‘N¼\Qà4LYäWuJ¡]¸ó‘sžòô‚ÏÝåé.­|¸õCš÷Îç³Ë‹]î.Ï¿?_Òô]×½óñ|´ºFH ‘!}VÓ)?Úg¹r¾ûèïççýöøék|ža?ž>ãËLÌŸ?㯮ÿj‡¾Âç¹>¤!œgœ–ÿ¸Ý>Û͵Û×jþ¼w^¿«íµ;z›É¯ÝÑ&—y°É¥c/5‡y~4Õ˜¼ä빪ë¥9¨t¤øFšƒªn›Žiwfõçfì¦00-a’qÑè–îrºŸžÝ8³#µ'œ‰ï ù?NUdh)áÔ«—nSÚ•äÓ'—P¥Ø,,µ;ÝeÌLJoì›î2“N BÒ̤>mÊð̤nƒTÔ[%}s¯,9¡7À§¬eæs7tB/ͳyå§“¥_j"^y²34 šˆWþ "“Þy]µïµ–kß^—|Õ,Õ¾’®š¥Úw@ÒU³TûHj"ßZðnI©n‚ÎÌÓ÷ΨB/™y9v^KNoST6óy*NÍvVcL÷“c ÿ.…e„¤«hª¼{m¸ž µå½-sýB[^G£ÊHDZÇNcr"H¦²™v.í*›iUÔìdæ#«³yS¤=i‡Ý룴''pÎ]‡ â1­Ÿ¿ÃOúuÁ¬É¿Óµ=BŠ/.ï—Õ—®þ˜+cš HIºŠæ: ya ¥¿é~"¥?oéX‰Õ=šùâ¦|3¥å`b|×íœ'VÄ^}Cšá4×,Ó]2ü¾™fw½±ì$a•Ô1¼q¤²ç€¦=½ñ¤ƒH‹¦=½á§=«¤r÷‹{žº6Óœ8`¹y0cŸæ±ÌQ÷xmºŸˆ,_#«T£ÿüúºžŸ)È}ò' H &v®1LŸíé¦Fý)O:þ.» ,IŽ¿+”$¬<صÓWlÕÁ®â%‹ãdð~ví¼~åDÎj†#²ðxj„¤sa.0íèqÇøsŠÒ§¿£c¥·{Úî÷¨?uz ×!}Ìèpã­cY©—:믽X8¹áA|;¹Ñ¢É ±wúg`rÃ[ÎQµëOi&Ö»‚›®û¦;ð­ÉQº£w„yä·N×îèaŽX@Þ Ò¹°Ÿ…»ó÷î¸(¨‡û»{q?ÎÄ@ÿÔ;ÅE,§Ü×÷ŽãÃu3.ýú®ËÏHƒý\dy_¦þfdÿyªÄ]óY¹ûß¿K®}¹^sî~›YOŒT{̹~êð¯ë]Ç_4?àab8?ày]“ãJÛŒ·¾?¥7æ2×äÒ\:—Ýã‘V0‡;—‹+ó’õÌÕÇïþÖß„”û^ŒgÀð HEôäfÝÛ¸*:G¨Š”wŠªàÛßûfº¦_§kâ1!W Þ¥0í9»d½Ý/§ˆ,™‰™b7<RŠØÓb“²H/è,ò¼d‘-BҞ幨ê9ïÀ™² ¯8?èë{¯9U> ‡è½!#~îÖ7é­óæå%ßξ7ÃI¸)üÎ}ý!éâ–#@o_Ô«ƒs×"ÿfïáß\mü›½wÌôoöPã{w×NÙ„÷l/vúçúë¾( úë8/S‘åöÏŽ_c»½5)÷÷š"Àn|«ßB´‘rßåú«?½5ø×R=[ºùë8ÕuÝâ_ר×ùÏϺ‰>èiÐ ¶s^Á¦¾yâ_·ûʉM—æ"Ò­{LJ»¤oóó\ߢÒ_DúT ŸÞøõezî_ó²?éÎI*õ2åsbÂ}~µ]ÆÐ´Œå¥ö¼ÞŸŸÕíÚÆnl‚®„¼y“]êÄ+U÷t¯oíssªåüœ¦5=ÑéÚ¯K/úkìÞß§}©ßU½JÞ­¦Müì&¨ 7äYò.6Í#rGò® ’wù5äGßTÏ,¿‘m2—Ž&$m3À¾mD B˜å”ˆµRq$®\¬ìØc–š†·Æ«ò‹oÈÁ„¹‘ÒtùÉ[6hš€BÒAÓËM#¸"KMÝ<Þ«1_‘¢í$æ±ñ*}Å¥f ÁÁ·YÞ¼ÏwÉÓæY²Ã˹´9!ÝAñ{RÐE‘ü~úƒ¢HþuÏ‚çBµ/DÁ¦§]—î§(Þù.nž€§±y绿ó¢dßù.?wQïü”Ìáw^”èߴ列"õRp-Á. MH¶›𠩘çDç&¤æFrŠ6!q¨žÅܪ(˜Ÿ®Ý‚osY'ä5æS³ME:¦cËOU›®›wã±²ïk÷Hû4ïoH$T׳×tÂ+ÀýˆoH¥éÚ¯î½ytø˜„ éb`Ý"¤Ú¹KÕ’ÌÕi—‘Œ¬ë¥ˆEyÞ6½K÷S³ƒœ0ªÔ%ox—#+ýš#¤Ýð|Zú—Iæ];m`×·#©x©¹¡d¼´ä§Í¯«WrÐe‹ÒµK‚TEÙ¢'BîƒÆ([Ô#$!~ „­"RíÙ¿þŸ°+[rUG¶¿ûýžˆÓŸ@yÂP… ¸ Ñ_%R™X©Ú½cŸ—Õ˜QCævóð¸¢41 B <òÐÆ¹Ã1/ýëÇ#ã„8×[ß®÷Èx{d¶” ˜tñG™¼§H.š6šŸ Z9ÑeJxDëY¥wRÞðÄ##{„ÝÙl>à×kò.í¡„·½Åúz½Ì2ºN¼ó¶dÝÑcîV ÿÅr×ñ4X­zçkV^Ôa*bY:°>Œ!$, Xµ L'ùX­¡Æ¾A¦ä„ȾÆ#9f>Þ¡íeµ«ãnj,64í& ’áñ³(Øv »ò¢`*{{`}³ÂÜQ”¬ÒaŒíŶu8¶á×ë?j€ðu”Ù5@xFšF ç$¦çdέ?ÛÓsà Vý‘ïéÙII;·Ûk¿q:¶B œƒDƒíÿþE)?Ûã=„–GiÉA*Ík¹-·… %çïÔ†©³Ÿ‹j¿ñ±%¦h%?zÑ!™t˜ çˆv­‡‹ÙÇ-_AÊXÓa¸m‘äAªX;r¹\Ì«ü¦ÇÔ±®õ¡Ã¼#£½èC{G–ñ"ùŒ§øY‘RX{õ¥°“ÙóÑ»Ä÷¢ØL¹;Ÿ± æa¤—´ ÿl.›ï²ùh›û«m_ô÷¹^ôõ6Ì+½ù¾ýÏÞ‹Þˆ­}OÓá\Ut•a©T+|Ì#ÓÙ-7Kóȳ0Ó SfˆŽé‘‰Uø@‹ôŽ*Ôk1å븟³ Áös\o޹ÛÀ¯W¬Áê0#ƒUä(Èóø¿Î’Z,AÊVµá˜uâÝðZg©þ¡ÝÓø_¯óÄÇîià¹×yºÂú µà åöY†·®–ì²UøÐIvÿ1¬¤wZ«tŒa˜xz–«±ÁàDèY‘[˜ê"%·À;¿ºü£ ~½ú£ Õ¸ºâH«ã€I«™êíO¸jX׉ø_\™È³,½›„Ê„C&êµþ{ϳüz­¯@ç©ÈOm‚ ¥l](åç)Ó Øç™üƒ¡ó^’cèX7Á Ã:ôru½Ó×Ö5>µ·/‚Ô\ï´õr ƒü '¼{¡ Y § õç®w[³m‹¦G×|¿’î?Z\o]³6)½ít@nË+3}Œ+AîKŒÿl ±L³÷$ßÝ×ãJº›§ÈÝW÷~dôè[Át»öµý>5ÃB%B¶ŽæØvçv<=¿¿ ²ÂïçÍ-Ä:ëv:ݲþ 0ߌyÌIî|Æ$˜[ò"=ÑüvÑÁc¢WŸsΩAçc 3!šŸÆŽãY²1 v÷Ȉã¸Uï Çq”«;ò¬L;ޝŠÔlN2hQ*ŸìYm£WedÎé}Á#Ïùéx¸!¯8ƒÌ98y{$ãót·Ù¡þ<ó”Óü´®#¼M¹øCýØÃ1e*í<$Ö¤âl-\af‚cê?Ú>0ÑäÅmŸi"H6»~E÷³Lñ€ÇЖÌó*‘"n«ÿ-EЍ‹äÚnìA¬Ó.’°ëΙ(î"y9 %wEk w^d©+×y¥Hn’EM¼\ä)?iTØÎÅiÒ°`ËE2Ÿ0èö Rñ u¬!1È„·Öx$›Êê¹(Ò١ЖtHÁ×0à;%«÷°„¯%ŒKLe™›s®ÎËÊ2ÉÓNøiÖ*¤:ønáÕ)_‰6Yç2ã›Ì-J›ôÈHÚ¤E¢´I”4…ìæSÈžË×þºŠå(.óÏ0¿a:–y²MÑ´ð#Ûˆ~CHúÇ1 7^r)I\˜¬‘#ÒÓg ©w RñïÒ`ý­Âý¥ OS# ðî}Ù‰iϱ}-k¢Èý¹sš±…"ã¶þ¶BQ‚Ô¼ó|ïò/ç¿‘"cÝÈd"ÚÊå„Êtl›ßƒc®AÖ)íúˆÆDeНm` Q|n@g³Ú …˜«¿œ)@F)ï7ïLÙÁ¢þp¦ôiçÉ;Sއc²‰ h~Wòk÷Ë\)vh¶1 ¿®c2Òàd‘ökX;Šd4¢/«dº™Æf™hæ ô˜l3'´§rQ*M£-éÃý¬þ(È„÷³Nå¦â5ƒÎRO‚Ì“™Ûè ѸöOw(ÝpÇ;-“…8´CAÔ›åî]rîY[˜¿pž*™èf¹ÖéU4srBiù$‰·ÞiÈ KŽÒN„’ë2IYÛpçK†²‘ÄÍc²Æù®«ý-ì7¾'›ÇjX­!òKp­º¹6ïåwì`Å¢“û8sVŠäóœÃ8_d©;o^O˜¹ŠüÕ/|…Hùt˜}ÜσóRi¶Vi¤bÈ­vWŽTšÉ8÷#•¦GÊA~!ù¼H‘11=?/Š”5#ÞezeŠ8×"–]æ÷"’¹í’£ˆ?‹AÖw~/ǘ&¤’¼¨Ùä¨MÞÃ;Þ¥Rý± ÇT¼K0z㤎ϬK$bÈË"•ÿÖà+*ÿ8&ÌGe•ÌE+À²N­—ð¾£Ê’¹”hæªþš‹áý¬DŠÂFŽ)Y€?Ñ'-N(•z/•ßSØU|2ÏB+•þ\+úqÞæ„„n\R„qhÉî¬JÊÚÈ]ªþX3Àºª‡¾v÷Vð}uZ‡ŒC¬ê,±ïhƒc‚A扬!¬ÆÏëÏÖÌž7¾Õ¨CÒ»AÊϧéÍeÇ¥™Nï‰ Jdºº„›Î½vG¤üDÚ.[·ÎsG‘Š?O/HÏk•>Ï¡Ÿ’?Ï~ Hþ<¯ŠŒ¦uÃËÜ|ØõÔIbš:‚ŒÊÅ:+ õÏZ³Ì—Éî&ÂJµÖ)ß³P†¡Næ$“·®L'ï…¯¸®’²Ë Íëú_÷‘eé\tiE–§²›ÐEðYënôöOSd25o63Ì›7#ófd;¤`+ÞiÈ á]‚º«ÆÌÃfEåWÔ"Ó©”QrEÉüv´NY™H÷½Az=ÿÐ1;ÛdêM ùHä)2òÀ5È?R¯Ã»”‹´[îè÷Ú"—i-ˆEÎ{Qu[ê~]%ü­:»‹œÒ‘1ÿqdÌÝÆ{>›ùA;óŸÿÛÞ!º1“Ü<÷=Aî¸m¥zq V‹¼=»ïîDÚ·Ës=ç Ù­ß·n^ÓAÈnÜeô—ûy8ŸôÚK_Õ´³ûe“¤œ—Ÿç¹ýýý¥È*Ô?Ï®µýü^Ï×ï:^ ² óÓírÙv¦³=¸¬PnüÏ‹èzñ,¢f™_K€æ(5özö©±·áfCA)t»47Ÿd÷Áâ  Ž(þïwáÒ~SchÓÞ…¡®µo —ïßöþK¡:F-°³çõ|yy¨fÝŸ·wÏ»?{d Ûu‹ÛïŸÞËÏõì«7)1²u-û/3Ú^×ŸŽ AJ{ºœÎμ§ô.U¹ÿzû4OÔ@û ëãww‡ïî}¢w~{÷þó¿ý’ÜC2?ßvëøEOt÷þcY³Û»o¯É^}û½œ_*Àß|x—=9þþ|ÿÌMKoÔþîýcÇËÉÕôÍÒö÷d†ˆ–>Qúî9ˆ{MW Õü΢‡£©U{DÎVb7‡Ê yJ¼Õ¡¾È+VR°´¸Š"ò:EcÃ3£øk§×.rÖßm™æ~lG¬¿ÛÔnsèB‚Ë7;_!dª3â5 R±5ði„R'] ¼ Ôçý¬ÙšMÝØÂ1‹Äyâú•)?Ü!dmdÒªíú…à}ý"Ê2K˜`Q¾À1 Ñþ”—u ™§ûSÀ2gý[;BR$½g‚(€Å&Åì,V$0¾î)cH³›îæÕ¹Üz¤òÜ›==lß­äЃ œCjŒt3’ÙwÏswDüµûú€ˆ¤kkïa 3˜kÒc&®ÝW¡’»ö÷ ]Q™¸öëü8" ~ÿ¾£ïoŸi¾8”­gu²‚ìO„¬Ù¤îUöǾÛïú…ÊS»~T_¸~•.¤þ/”dE¥é)8¤`ÈçHTê’1W»¤ ÖÿÂHëk¡=hH„RioååÎS§½•ÛðëšM¾YfÌ?ªHeºUƒ,9Y§ùŽƒªGÆTíT=2jº3`UTŸ"[´]û «”ýIüF²Ö°ÌŠÝEÔ;¹¯ƒÍ’'H‰‘žÕ?Í€<œ‚¤sǵõtå~¾¾’Òª}âh;šä4dÁ° ú~:Ñó,C—Æ.IJŠW'^Á)Û ëÄ pcAteA ö<‡"%³V îÛ«¯šq×W…Îþ¨¯Â15kÇež&®¯:¤d2½Q}Õ!_¿‚‹ÎÕ3ÜŸ˜/qPU§lƒ”¬ªrÚT•MOQU%ñÔöH¦¶lFE0òت$"†jÁ´L$­Jfd'´âN·Þf4—ö´ûòC¡ ÖÐe!†.B¬¡Ë@ ]RÆóÀ°¡‹C*þ¹ÃXwȳ!Ñ ãh¾8ØÃê*•4‹×Þú#ÛÃ1¥·.Þ¸†=fVFÚΛEÎõâGjð ŠœéÅoÂ%Ô‹wH.UÏGE"cl´<Œ …ˆìô}/þ÷5.Š”´—tó½¤ó|]©âÆ#eJÔAC N¼óñŽCJFhsy4°/.’8"´™@hã:!´yd‘Ú Yò:›ÃyV¼Ìf ¿^Çë!Xé. õÇÎÆä„¡‹åu MQ$˜üÖpªÀEÒfuhÁ0£ÆÝ%?zwã}½÷á.•„+B:ì#æŠ8¤Œ¯N6S¼'Hn\Bý>QT)S¨v û£¢N)b vÐÄN†r¿{ë7zÑ«(s6í©{’Ѧ);Ã`eÊTïm×K=Aʘ/G_ódv† a| ’åó!µFŒ/‡Œ¦(Y}SïS” R%ø{2ö¥bµH[zA¨­áÔŸ°ž‹Y[dñÈâä×Í#K†ÿlí!­{¬T±UÉÿwqË9èÑ3ª>gí=Y¤µµ nxw·a³w>ÔÁ‚UITº”z¢¬SФÔ(õ‡ò`í‚•z¥þÄ´3hÍPÖi¥ÞsÜŽÔœ&’ÃjQeLr˜ùuœf9@½àä0d“Âlß!%“uŠ4>¢ ÅVîˆJ&ødN)*•Z¥ãÞq•â¨V‹åßä*¡Œ8mj=¸ŸeÊ,Â*Ëz‚ü 渪JîôGt?YeÄnK?†k¯Y ˆ…˜¼Š:Kð`±É«¨9“Wƒ$&¯)¹ª{0yuÈ„ÉëHÏSÇ…‹å›…w)p®âŠÂ¬‚±C\Qø: %gÝ…¢IëÖv‚/®©T»‚_Ô’›‹-ƒÙʼnZ¥,¥‘m­¨_ÇfIó{]¤lØðÌUĆíhõÔEJÖÀéxL7WÃVK¹Õißÿµµßk{½ìæUvÞ¸‚ºÊ!96dÄëœ ›D(²ŠkØ42ô~–¬IvgVŸˆõT—Ç÷3è/KgÞOzÌx°ÆdWß0~ÖŸõ:HV^f ö‚w ­*c Žf¥ÈHÇvÁpǶ®ù‘v²^Éþ˜2•NdÙY£ßoÊ,K4®`"y¾Ù¦Ð » ™‰d6DpÈŒûŠ×Cð‹ÌdbE½}ŽGò†—fÖ´+u¸v`Jã>¬ÌxNõ@8Õ;|$3™uòWçY%÷\aœwÈX¾ÚذÌêHÿÝ›Žãº¢$Þé˜MX×9¤ÀÇʇçÏ:9ºCJ&GÓ v~dpHµ˜Ýì Ã1ó3mBÎ2§9p¨w6îÜÚß\ïlcÍëL;;èŸÿ9ÞKëX7f×~ÓcJiæ¸v%HEÎfh0ï2AjÜ»\}çn™»ñç› ‹r5Èy|= ²d:w×Çìw(YÅ:wkóž‡#²æïü÷Ù#eúÎÏÝL‰;ÿK™¸ócC‰;¿RdâÎ~=qç/w‚äî|7£û)w¾ŸOGdÍÔiC^抶q‰Œ :a®u"_±N¬Á°¹¯Ì‹„.îËÈ'Šôe2Ò—i÷þôeR2¦U¨/ãŠq‘DÕ-ÉFíÁ/fÏE‘qýòøúmo0Ëäxÿþ/pþ÷_ïîÃiRÅîRG »d^',Ȱa—Ìk>¹–°Ñ¤Hva6š©D¡šÿz\q¤È#*H,n—åôöHñÒ÷‹¥Éô ýb‰þwç!>£Rè”Q4êõHQ$uÁ×õ ŽY¦uÁ 8pHÁXž#¥žUR\2¤¨— ‹Ä.sɰpä’á*Úëiís÷û#)éì7l´/e–ªÚÞE ¦† ¥Ì#¾ .P'@¤HV“D"Žæƒ9æÃûÝÜG”1ÇgènÓÛ³)RøNèvÌ»«3ÜVóÏ×JÑʲ¶¯˜:;d´‡²4í¹k~î顨;{(YÄ*¥v~¿ßA–ŸÝ{LÜmqÈ*Öm±ûü¶ëéëétu»Ýïár¿}ÒÄßù øÄg;Û«.÷ï[ÿ{„æLè#ªRK©®'¸c,¥Š¨Ì]·‡(H¤Ô ý™Î\Òÿ6SiÇÞ²7hþG&Ü׈ÊGÊê}$Ì ²â6‰~EÊšëÿ[[|Ôÿ—$B‰ôÿ­-%êÿËÏ¥ S$ý©RÜÜÿ—*K¥7Sx›ª™m1³·-€Äü}µ—×c}t=AŠ˜ÂiÚNô˜’1°Ä;ÎOîØV óïÜCœŒ$Ü1\ù6È—u›)’Ól™•C8O™ð\1 &ðópH…vœW÷Ù¼¹"xë”b-ìÒÑ '•~›ªH›#|qÈI%¶/Ø«2eó‰B^e`o}†¼^pÈ« ì­Ï¸ÍÛãB^%boÅ:±Á\ª:QUµ®Q#EFãÍ —:K*cn¸ÔYâ]Úfx—tþ‡Û ¬ƒtžªZÙÊë´H2èCOLê´"{ÑŽ8<£2eµiéV°\-EЇ¤²¤F!£×)l¼JËô›¤¹]‡_T)ªYcÛÁ)¸œÄnø…+Ò©´)$¬rH%ËŽd‰QØ 3A&l…H†[û²,ÿ []}¹¡¬þ@¨XÖ¼©¡‰È*K¤õašˆCÆŠ››Ô7«<ÐÀ3ªÐc—}XbTâ‰àWO¼D0|›(H(.|Ó_g$‚Ûƒþ:#Ü–ô×K6á è]ª¼™`³_ìsï¾›ëÁá)›YÛAû*»–ÏɬF/2ñw>‹­F~ö,zñÎ4៷óÆö2wôþZ×eñôcÌÂå=„ÜA%»Q¡Å]ÉÔFÉ xPlÁ1N+DZÇT\~m;Ù;ûÞf•ʯ5ïàD‘‘üZ3‚ÙüZH+tHÅ$c"@¥¦z¤•T)y=n%UEº•4 )!¾™Ãã,X*½mŠ>~ )Z•I³ [-'HšZL ú¡ñtH‡”žv²­Îmþ°‘£ËkxAó¡*QSôÓÚáñ€1´ RÎÿlcýÙ'³öC{: våÁ(ålu¤ö<Ï˸ž1cG–G§ßh½LÐ6ß‘çÕЂLÐ!ëX®á~ç¡,SUI‹š¦ƒ±ª"5vÛîüÐôáÎWI‹šÇ££Hå ]¶)i_ý[Ñøðýý ¿®9?—Ë4Sä~çÿû^ÂëîçË|pWŠ,½ñ‹¼Ü÷>ô«M<\{Å™¹˜Ñy È:¾™Å2IÆÄ’1å÷ÆÁýyÖY2‰9Ód·çÛï°²¬ó´í÷ “Bsa`k¼ö}8OÁ¶¶fΣ늌¶ì ãÜ¿'¸K5o}½XÁÖx@F ìm¹ØË?ˆ“ÁÀ^ÖòóÚ÷ìИŒ)–1“Œ0ÉÖŠ4ñŽF!›HÖ|ˆ•/#²[Í›YZÖeJ†56@/•u™h|†p²]Ä6«§l›Õö`³*ëš³Y5Ë ,qH+ØR›U‡T1yý@äõ*Ëø "¯W„fH-Ó:ÒðRYž"9ZëÖÞ#E"íuT!šatÇ ß»Êdz·cÊ-’²Ž™j 6è QÁ*ï@Yeµí’¥¬†õ’Cª¸-nÌ)B‡¤u«Q¦C~Ð%0!Qa:äÿùÆ5f×iðÆ Ó!?£^­ïaG"NÆÄ´M•Õ©¨WT*WÄ~Ú~OÖö{‚çžg¬¸j3}ÛoEèTÖ¶´ÓeîýJ@!:dŒ\Œ$UžóïÒl‡d¸óäh'x»°'yÝÖ ÙÌ2EŠX°Æº ÏýºH<±y¿J=u6èi…‘Ø «HµTåé:`ˆwPyºh‘ E¤in[h¨i®ò2e:‚ÌæU^¥MG`¥ª5,v—Ì(÷³fe‘¤(‘%„zX’¢'I1H"IqHÉ5ûUÙ!’”–"u|Ç‡ë¿ SÂÐÙUÍ̵÷¾Ý¦Oìµõ ¯é=ä¡vãf„öÜ~?Š”q±oÓ6}¸K‚XÙÿ)LL#â¿Ý>?ˆÿ2"þ³‘ÉXüçLüÿ9¤âÒ>ƒ|D •Lû æg‰É×öÇÝ×l eÔì8?ªJÄauDÖ¦D™jpo[¬« 3Ø@E‰Äguøí0$w¬…f»ñŸÍѦö¶ÀJÕ!]=äŸm'uÛ®È<Éækœ_‡c*_9i¶]¤½OvLî­eðD:&ñéšÉV`‚Œwº]ŽVk;2"Üév‰T9²Ší:"®R2KW¨±(™§ È-ŒŠÁ"nß•[KN·ï˜Ì˜ÔÞžRÉQ׳'G5Ë„Æyb÷ÙÁ ³JÊÅÙ *™/B¢’Ÿé©°žï×Û4Á¸„©üýÜG†•Ú¨(I«[[v#GÙT LŽR²HÍïx¥*YÛ;sÍ P5&› ÖU´C5%«ˆ¹ÔÝÛ4Ó¼Ì)øcza„"`ŸÇ¼Í_3A †Ð݆ª¦RYJ…zHJå‘ù*{¿Ó­ï’ËF{C¥DB싉½*œHLìU$8‹ÏͤõÓŸæž ÏHÎS&%Sø<%K@Zzž’% w„€¬>Éf4ô&ì"ùØS1…Éfi×嫃c¦í4 S8¶ë³¾„$} “ÍÖ€±Tªb­;b ¨T•²‚5  d³˜5କªþ²ì2e H‘íÞRaª[ìÚÁR©úk‡i°õb®F0Uÿe ÙdÊ’"‹hÇj–u½—‹)ýGGÕƒ%|[-Txtj.¶]cÁ%ï(R$ë:-ŽMƒ¼§ys±–¬ƒ‹€óTI îø€š@°à:PpG2ФŒ›ó}£N“ÂÑjŸëOÔrȈIðzvSºHí ç@‚Uc­Oi,¼Kºb‰µ!Ö*]'k•Aì« žJ­ƒT‘1½ÈÝNÃL5þ<1/ŠÆÊ‰•SEžŒ• |#,¸±rãi°›3pwȘxe " }}U$,:NÖO# SoòF&‡»¤þÁwI±k+V `Uè”X­ ¦Ë)âï<ŽwP1Ë(xçü¢ \c‰D ´áÚ ôŒl÷Ê^ûÞiÆyL‡Ü#^—ÿnHG¹1Èõ| °(PÄ+ô;î>r'„¨¢ŒŽupEaœ/¥nÌúÚ*Výß?{Àfœi¿¸¯g› öPÃ*ríw¸vÏzqȨ}·Gdû¯¸¨ÕÂÆ~rpçySp[u´sU°2ÁÍ–;PÄU™%"õ°LP¦×gÐý &ÖªLÝ7h\*ó¤T#Erì TÉÛ „¥ J™ê,›…tJ•b&!朊Vy’6bΩO¦–,5ý crY$z(f«î|ñÉ=ØF†­¾<Ÿ0&¦—Û•[ðÝÞ§<öðΗªþ»s#ÕnÇ|¶Ë“BZ¶•ÕþÜm_ÛçYø@•æd…]vq1ôËÒ?^ÏïӖíŠ,ýølné1+èÔ_|§Þ`ÆçòlǬ}Õ½9ÝlÆÖöë×nêÛŸ‰^‘ãíÐv›;îú;õ¿íÏD¡¹ïÿ“ ÓÍL^`[ï¡®õŸíò÷6t×›÷ãò¼¿è©îAz:Ÿ¯;GäÙOÙ$<·PPâ²}©peŽºœî÷ÛªÃJÌzaÙ;ðl§çðn!ÙC÷GµüןëVº=®ßMósxMKêa-oÚÍØfϘy¡oÐíaý³ügwÇÙ^•-¦¦iÂ"ÇAëºuÿJ´)Td¸t·?K‚hoóëø¡äŸ9 nÁxÆCKm†,QU–ijóZòT\â5ªÊ„F˜xª²b¼Fۃר"tØk´=x*Öƒ²×áªÿÊ^ïRÄ]^19LUïÿLÈaªÊÒþÏ¡pYe¬;å@Èa©ø&7¼xUžð"Mî mÀ> ë¤)[ &}²=¤OªJ&èÒ–WSN*%sÄti…R2>4/[Ušo¤‘¼l‡Œ7ãgk9 ^•žðV¨*9áÍÏçH)¹ilœŸ© kÌŽ ~} ý÷ ¥Ã*9á™ùöpžElûÙ¦±ýõ2dÝlÃ*oŸcóZÆþÔdl³©dËïs¡ÈÚGì¾OcƒYÝžÍve:Üù ÕQnî™Ûo3KÏ/zI± ÏnV3áMô>… Ìb7;‹}/Š'¼vçâèWÿµ‘­#t%±t%óÖaº’ÎXºÒN-º’CFèJöibº’CªX‹´·Ív5"ó‰b iöëL0é«sŒño²&µGYØhsmà"αH,ÎÑØåí`!0qŽC2žÿXœãŠÛ©€–:!e±Í~?e‘Z'¯ .µLU¡m|nxšUJj…ÚZšPô>Ò©.Ýcé ’—ñL0Ö©,á †+´ÊÈšæi⊱V9+'îˆ3­V9+'^ˆ3­&.oî¬È™Ö!CÈ@¤C­g\a%a¨«•`ÅáqáÖ*-‹WØñ)Éz[ïw´çÂÄ»O`L5ÐJ'hèÝñM)€Ztº^öÂÍùq¹Ÿ‡óöqJR×ìH{»\¶õÒå¶~_Ö¬©ˆøv¿ósÛ K•X‡Ô,Ñ¡••‚Üäƒ¤Öæ2ØàùŽ^{‰‘ŽÏf—ïßöþK•/ØYKËËÎÀŸ­½´í~d‘¦o)áUÁIÓ÷;¿>ïªåvèÖŸ§÷òs=OAJ<]NàJöõÕ™$ÜOÜþÏV…Þ­Œžf'Ó ÃÞùP-·-ç€lŸ½¹»o몖ǨMxçCµÜÖu-uÃׂ¿§yîWzEiºš+AÖŸ—}årÁ4Î¥ý¨œànŽVUŠh‹hèZÕIâ2Úéë,1ο­s ƒ÷%õTÿ¶qFk»Â»¤#ãÙüõŒGk©yqÎåþ½~)qÎÚL0.áÜÏ#ÜŒ`÷@IÒ­' ™éµñ.ñZGF0dßÕ„^kÅzwóøžÁXÒa ;äô¼5O‚TDrãü{ûg»¾Çç™ 5®±ìäH{žçîgð¤X‡ÜɦÿþúõíÚW³ Z²dò¿†“ÏùuÈêG¼“MŸë{x?NYÇ\Ží¯›{¿Ò;ŸQíšœc÷Õ½¿(4gR%¿OÍ@¯>\¬äé¹~S¨Œ§EÚù¡×ïüà¢q‘=}MrÍPN§òeô_”S Dh ‘”=­‹Tíei]|:lC'÷q4"§~®[p^¤ÆäT’¹ò"5qµäé\ÝáfU<Óx=@kžÎu|û3ži ecÄÑ:йºÞÚG:—‡r7f$ÃYÉ‘6¶-½MôõÈŠuOˆ{Š®ê´§ThŸcg¸ƒÓ ZÔuZ£üK4r†‹QpP›ªÎEIÒ¦ªù°»ÀEšZð‹a´‹q8O™¼¢R¡k•ll …x­YÕòB”|)bN'{Ìy×^°N'{Ì9<÷º`NºËØ¡vZ]ðË[ …øûI*ÇfmÃý,SÎ1m?O¾HQó…Ðëu]ó1¨„^¯±‹¡×Ûg„éõš¸¸ÑfÉ@èõ¹¸EôO¨aPDÈd¨È‹\ L&;¸÷-D½ZdyÂ9놋쯲àüöÈ?Ë‚A¦Ê‚A²eÁ Ê‚©¢Ä Xd*¢‹Lq^ý‡hÀ"KH4`üÞâÎ#3á›hCÖÜ_`¿7øuçÀ4v¯áγHŠOÂøYdeJ|‚’ {1ã箽bæ£mbßP@ÖÉ_ñ Ež%%¡@P¢j‰(>¼ÈE*˜Ð’¿à×e’r×ñ«ÈUÚý´)2Z\lh:¦N3¸¸9_š¡ñ¢E^$F†7"Îy‘ul!ëp?Ë”W*\yùWÈúD©õŽ UÜ ‡¬;$²>„u‡ä¼šPȺCr^M(dÝ!«há’PмbýGBq(òŠõíšȫ„‡¦8$ÜôóëÁkEžP-o®xpE¬+ÞF¬±®xAF\ñ rwţǔq——ͯ'HÎoZ–‘þºŽ³[Ç! óHìÛÍ·”ÌßçË#ïÔNÍmñ‚«BÄäø˜÷‹GÊä1Í%-)¸ÂP Ù…PiÎfX¡“êê@)„Ž„‚·.šzKØgT° ;Ë< „BlÂβ'ìÌ)9úQð0.=îýŸ\“Ê•à·$9ïƒ^ˆ’ ,D$PˆŠ tD$PØ# ‹ Q±"ˆŠX¬'—‘a(w±|p\+°ö­ úûB&ŠwÄQ H»bGB n×c½l»4ç ì sy`«BJ¶¹ìnÇ€TÉ(ÎrI ©Ró¦}•©âRLÓwÈxÔ·ÝDBƒª@d²ã›¼ÉPgx“e™Ø™âÖ`!¹Ö ÝwàÖ`!¹Ö E’ùHV ±.n :¤Š•ÆÝåÈ:FÉç"Ÿ<ÐNÉåæ4-Ô£RÑŒH‡¬í/Aj&Í`6ÃÒƒ 6Í`îé1K9CªCV ‚µž»Û,Ó™ܲšÏè‹ ëp9û„„qÁ þÎqé×Å=øz>¡9›¦ýxô5Íô1¹Âågò°‚3³‡*Äs枃mnvÄ£P‹»ìdË^0Èñ² .¦Á¼)hÉ&:4Ýá*Ælu¦ •Ŭ¾Ýblßf[å‘ùÇT{wŒùnæùÚäG‰o/Ý¿š¯ûJ8÷Ú®ì#ÙìyoÞ ´@LÊ÷¿ÿ@¨Â>ÕÞ›¥¹ü¤ŽíØžN7‚,¢¥‰ñ>þüø²¹C–ti½÷!ÌÔ`žÿ@ϳ:,­ï.€¬¹Ýzúë|î5t•üçs¯ÏíÊX¿m 2¸¦Óë œ@ü?PQ·jy¾~<2•fÆæ¦õñ9)ǼÁ1»?ä+°eì¬M@O‚U†M*aHÒ$o³M¿P%£úÙn#Z¡´àxüZ8Ïêøµ2–l™=x󧨲å–<t7…ªYÝÍBt7…ªÙòÕ@t7…¢*ªC(%ê':c³u—-[×+ò ŽlFϲ.tÎl€6³0¤·*0›ñ°$1_üùþý)-Á/)öþâ°1â!Pn±rè.ñáÃͬð@K^ Žâ1üm±áàÓ›S2&\VŸN‘ŠdÁºEë¥ÿÌ ²¤Ž•ê¢ÿ-4W¶ÜdhÁ®Sâ˜YThžÔP¡cvÆÁ½äº~Á¯Wi÷ОˆÏãȦA¡kÖR&y;$c,»Ygzd‘¥B2R£(rÖãei§ßp’‹"D¡îþ ñO(KíhŠuLf©}ƹá’X!wiS©Lɨãq(eùlŸe +Õðë "ÅÌ4óæŽY¤L6»(xåBšxáž}”ÙP¯ÀѲŸºZÔl,Šš5%(3Ö”|!ZÈ¢ÌXSò‰h!’á¢`-¤C*&ÁÝõ[HSÔ!ã¶õ6TE™Œ C¬¿;³}®ÖûŒŸe•Æ.¼K£lÝÞd;Â¯× kW3‚†·;žÅügÀÁ ¨ò´ÿ P0 ì9á¢6o%ÒLÂÖ›û•d#âÂ,*•*"/Ž¢Òli¹ßÔñðU©è E‰(44ðl=WŸ”–MJË kXÞËð’¾óþ˜fùó¾R¤ävgø¹—qß òÛ–!0!’Î!vöØ ÙØ1¬ëP&€5;”=¶'H-FZIAXƒaÇ'}lãZ×évûê ·%]œ²YòëW÷îRØ¡|’‰žSóÕÓ_WŸÑÇvÖÞé¯ëXÀÒÖJz÷ I¶v:6N™þz'þئÓH‘Ótêl. AÖ±äã»M>kï —Ù6Îyš[yŽ?¯ç0žï¡9“||Þíá¨"¼$Ûúb{Iš{wæðɇ2›¹Q扚k¿Þí§ü\Çóy]NÓᨊëI‡Ä™¢ÎÒ=é°Ä¨³?œu½€¯¨SÆØY·¨)6Ô/·íŠ”ÁÛö¼oîC?¿»þ÷òî R]pm÷zwÁí)Rk-rw¬ מkÌ…¶= ËÀ"µƒín 8¬Ý¥_ôŠ"ÞuV:‰mU²þLDöD¤ÓH‘ykÈÄ€ÕC)-rkú™ûÔM¿ëøCïÓþ’Ò–ü°µäƒ އÊÏž¼ƒNÇ·D14BD¶,09ð|½¥zQK^©N¼M‹Z¦•ê葬’j!Þ¦Éûº0‹Ôêp]˜jÅê£:B¡,Ø0Ø­ý„ioØiîÓé䋺`÷ç ¥ÒEi„Pƒ©t(66®ááIM !1uØ` [™e©ÈÜ>¸–Yžòã³õÿ… 3[.pç‘"A^íí•"ë'~ge&“ÎS+ø•YŠ`Åv\‘JN‚þ¤Ìô“íB"Ö˜^HDv™‰U8ŽÈ.éîØn-³ ¤»Mµÿö¶µµ–vXGøõŠ'¯ZTÀËŒoßw¤}_b*]¤†b•<2ç²¶þ9¼!(æÔWÀ!.ãµ,|U"·µˆ"}Åe.Yº£­sõ'?Ò;¤à©J-\»â‰|6e ÝíL³Äj/ö×Ç×ÅlÕ ]ÒÝçW?ºÚú} ¾~ôÏ^?ÚÔ½[ýè¶ž¦Ã¹FÌ7¾ç: >!²Ä$ƒY“kÍ= h‘š‘-s©Ê„ÝNé.U•˜(= Ì:Oi+‘’¦Ôy2 8˜H”:Ùò³3¢¿öOÂX¬ $ųDI–ñO˜ïºÑgç–e‘J>7£ØëI\òùõ1Cq'y’Ï׿=GdÁ_;ŒÞe™¾ö¹› 2qí¿ô˜‰k¿Ü ’»önFWT&®½ŸOGdÁѵá¯dC7º6"¹–e’fŠôþeYóFæW–5OeÛížý¯2Ö¸°#tí²béÚ[œX k—UžR¥$Œ!•`IÃ!Ò••äï'!Ò9dÔ½a!D:‡ŒÓß ‘Î!WliÀ–º¬‹²Ø·)”ã*XƒÙ]J8OÊï¶=tÞ¾¸v§Œ˜ Vk•æƒnS‹V U°Ï¦*ãÜmLõ‘þºŽëì¾Qƒ»L´6¾FÞ"EðE9ÌeU&Š–Û4ϽJ‘°E¬g¸óüÈÔÆ î‘eRϺnË¿Ùô¨‹Yek¹5^o•0½H¯×!— gUž%BšÑgÄU9*œmå°ËyßrÛÆÓò^ðëy(œEKl`Ÿá$›åºÑ‘÷íÜeòÝA‡Ô\FG š‡,"&îÚý¢­Êód.5Æ&HŒ ¼««­\Y#ƒ®'HO›™§îÞÑc*®À˜£©¹´ó5 Y°–[c¸"‘èã¬Å*ð®âY‹k¸vñGÖâá×UìýœH‚M•KöýìH‚M¸\\‚MO©› S 6A¦lf‚L%ØÐc¦lèyFl:’`ãuò0‡õµÜ–=&£v:!“¦*˜ñE¹ÚøŠªÔêb M¬*O˜E’L³Jdl‚â2Ÿ»ä"V"çy–›Í±ß£8$“ZYÝ•|IÈrL¡$T¡¼V?Òkö>Oý!y léJÔmB&äëe>ã³ÿŽŠ”!²yF :¨p6]„fØ„ç^d)‹gDú©Š<Ù´zÎ*F$ 9‡íͶªHŽ´¨uZŠKƒ7ï'6r­0‘(x*QŸ²¸l\LX3E"àdhBë´* «]+È2•Õ"jU”)^±'¡C噘þWEšº‡fí¢N®*ƒ•UfÉZe ÈTežRm¡vl• -$£¬*Ùwi[ƒ¡Y»L„=§À QybïghÃWeÁ¯¬¬ 2ìeÊ2Y%F5ÿ²JiœÖ`õ[G™ÃYâç½ÊRÙžH—Rá,5â=Ón}¶w÷ ÇÉ–yQ‡’fó·ØšÁ¯óÓ^ÒóB2ž4މU%S¡>ˆXPUòh,îu)–¤b.}=R1³Ì®½ ŽqU¥ÓÚ˰?ªtb.ƾeUU$‰/hY•)â î8 —š¯cm‘Ž·ª*öiN6®…UeõWÖì7뿲þ`æª3V¥¹´¸·\Õ9—h?®ì¨8Ð~\->z(à=C¼$+B¿ FíÃæNtZ’¥³Ø@’Ï·„‘¡VüXgžfp¶«j?ƒ•EzõÚ:Â1SÑ›­ùBŒýú³C_qýGÂd3R¤àú°hæªë¤¦±‡c¥*'ƒ•PôÉ)-YvöÈœï0n„_³ª3ÁVáºû@‘âÓªÝÈÇÁªF}ظ/”_ÛÔ™LûBA¿£ÁKŒ/Ôá×£þUV¸3.II½›Û“[­™Õïëq ÏH%Îó6­0×!xÉ’:ì¶ù4Ž©øläž»æeÉʿΠV'¹•= €%qo}$Ʋø­:+Sß;úŠë¬Ju«ÑZ±Æå£cY+ÖYD’Ñúéå1¿=G£Îcµt4·jéužÅÜòœ/©½¿3AÊX0˜õ´húžS1Dv»®ówþÐÆ:ó…èÌë\$*ä8­ÎùõçB4·u®b´Ú»O{Ð:׌ÄeO{WO}®‘¯D´Ã¾Íà+ñÿìЫók¿ž½ùà{Ï ‰L¶þû8›C^©c>Gé0ÖÄ«âHÄ\ìF‘‚íñµáŒÆŸgG¹_Ñòß iOÒöøÌQÏ÷§§Ñ;¤fª…MX'×yÕ0»*Ç{n|ß°ÆÝ«Ðߪ…ƒÙö˜‘q!HAy÷•“éyû}¤$kZ_=x¶ëc|ž ’X«]!‰ýÜý oúëûÓü÷ÿþæ‹™‡CT¼áÅ”K7œ|uË!ËOæÚ~L³¤] ²úd®µ–¹vy@UÓ!ëOæšAž[s›Öozç³ÍÌ wD3óÐ<D¸ñÌ: å´¹x°Íyvþ@Z u^³ú¢XüÖ"cKôÑþÕéÆåÚB+¶"™Ùí¤òÅ•_.ÖB¥Wáó¼eØBìj¡ùMôºd‘²’AÞZDšà­'lâf}M,E¨ö@šõ5ŸÒ´ßÏ%<Íšµ‡ïæIãÏSf‰m—Y+‡å¢ÌX{øn³‡ïé1%·AkÀ´Ë!Õgk+£V-s¦µyPË!³IAÛ™ZŠ4½6)µL•ƒZ¤@«er3…JLõ!{‰´8‰y-‹D‹„ˆX—EbdÀDĺ,>WPàÂíȺ,SJcdº]—er´ÁoH•|—иTÖ웼ÓúÊKlzè‚»óhwV¥[r¡5SW"EE€ºŠÅz×óLg—*•òpAÒ‡<ÄBË<úÑ͘ö.¤RuK­¾{‘¢™ÕïúÑ狺Jº~ ÁùÂ!9ç‹!8_8dÊù¢#È”óEüµ{*`]•ékÇ“º*ÿ¸v(ÕVå×îOêªüËñ¤#È”ã EL³×+žœ3ІKÅ®‚ÌwDª[UÍ›novh2ÖŸ®{Ôâv¦uþ‡Å?ÔXêœmï.„”Uã|ÌîHYu-ØkïÙ¾®åÒpž*eœŠ¤u"´`!䜺NÙc—Š7Öÿ`;‘fêá˜)JØ9MÖu™ât]¥æMÜ:¬k^Žò×ó,˲”Í=H{)x9p Èœ¥ímùëN6b‘‚‘BÛšžõiÛI3…¿ûðæ[öù‚?æN´H•<æc¹.)8J­wõ²H¦Ôºv9 EŒp>l»ž'Ü¥T(–Ýõ„;_Ê£» ­ûóy๧ÞO³^[Õ¼q?Ú™ZdÅz ÈcÈ"ëdd±÷$³ò&Ñ™g)Á>ÏC¼~“'ädg‘"Q÷Nv€qù€Ý¾à³@3R‘ýfëVþÏçÐ CGšÈѯOÃ×AîöÇÿü»×¬în¥:þ.³ÜdÉÈ…Ìíé¯W1ÇÖ]:±¯Ö,RqÐf,þ-R§ö†6ðî|‘ª”Õ"Ëä˜ì;Y%hÏ@e‘u:‚¯)RD#ÒÍ ·ö;íÄ Ahµ¶Ñc¾¦n"H SoÏí÷³é RÆÛ«Mëé€TÕß“0-2OSý œ÷Y㣕-R|¾!>jhá S¦(A¦LQz‚äLQoŠHÍÙ>xS@ñù¨Å£Ô‰ï(ˆ|-²HîPÚ5 KFèºóÐW‹ßÀ<× $óujºEÖŒwûf)Þí:¶Œw{»¤ˆÒN[‡ñä]å)9Æ6-¤àžZ©Fä«-ŒÉ÷ŸŸéêï§’)ÐÈè-³-UšV)¶¢k úâ”"–,§ÓùÒn‹†ïahÆéü«t…¾Ží ¹œÛ-ô57ÝÚÞØË(ôuüÇUx` yMíóðëÚggÀi¼-Í@=X²l_œó­7Ç\î‡k/=aÒšá´íîK¸¹ë¼[zž›1È?ËŽÜï¼Eö ¯d½#­ÛÞy?Ñi;é’11ámœóÔ|µóëpñyþé7h¡Óm¾ŸgL cké …±PÐý…‚ŒEüK‚Ò-²LMˆ&HÁyZX~«*¡JØšA ®d‡6}ªæ)vf—°¶ð˜t–Xü‡Ö¡E扬£þm‘"²r›)3yõ—»ŸpkÛ16'äö!?Ÿá×%1î´Ÿ§Ä–þlfذÀÐòóóÜ&Äíó|vßçA*ú!ï1›ÝÇóþEÛóŶýy~,Ê:8&ý盿/šÙólúæpž%8™7é²çyŸç¶ûž¯YAüÅÙ:Ý÷aäDz¤ïY‡ò/Äôó½¿ÝÎ-½ŸûçùÏÿýãFûóûèð3í‚ùÍ=ôd¯~_4õí|:5ßó@¡lxêV¶Z±³Ø‚À"uº3Õ·AŠxÏÚÒ¹¡.¡‹(•RÎE >Ö–!{$Šûð’dÅhF{ïÄjK·}ž¡—ñþï¬ð𺛆š…È2MÓr@l²ÂØÑ_/9䆻=Æ\Cí§tîü€úŒY¥$´Ðg¤`¸^6~ŽY3•êÝZuèüy"NÅûŸ éLh Ò>ýé÷LìŽUà žƒjLàym‘y2±` uÈBü±^íü3Âì‹ÃŽ»ÛwÜpžŠÝqwvÇ=ÀŽ»P쎻ÛwÜ AJ&Qƒ\‘bÝÆÔ5¶ÈTÀ­Ã[W¤¬f–ÑÛUYdÂq{hì²Í¯‹TŠLƒ{AŠ1|˜¯c¢HõS¾Ì_>QL]¢Çu‰¢þÜG#žÛÏå2KT0H§ÌŽ\׫›¸³{„*h™Ç¸ûs?ã{œF‚¤¼A°hæù:ÑcÊcßaF÷¯æë~&He4fe÷Õ$­ëîÂX³-oæn€7¹ ¼Á.â·å"6A–;òŸ¿ñÞ\›Ë/AVÑŠåØŽ­3d­CŽ÷ñDZÃÏ8Ú¢½«zL/Úë «å-v7 «·ùxïk¡çoÓu |t%Jœ?ÚŸ­Mqèx•!q~‡"›âïŸïnø8ªŽ9èm:·‡£±¢Ø‚ˆG*آ؂ˆG€1HÞÀ¾ßÛ9AŠÏ`»í¡®÷¯ÙO¥JE-¨U€"bÂTçWÌã|é_¾áWò[ mœg E¬Ñk9õ?ðFÉ’±×í2îQbܦ¥²L¸éwW@òî®#LŠ(P%îî ¬¨ÛûµhOUVIž­oi<×évûê ò0ŒîƒN‡2?)ã­Ö§Ù&÷ô×Õg>çæc©›€Ô¤=æËå??]ÿî)2–ä9v(ó%·ïmæ‘"+_dÜb=|YêçÔÝ–’Oò\[z—|’ç?[Lùm«2>ÛŸ×Ó¬_ ÍÙÐÏ7ì»Ë*•äÙ݆ãEù$Ï÷$Ï­ä³%yš7e:œ«BÁÉf×µ'[rÅÔhÍY£ÛæTӻߌÙ1 Ê>€?&ðpòM䘈PåŒ*gû”Aíb‘‚Q»lrP»’S»ŒÝé=$§v=ë Š?OxK*™>O§$žý0$ž×Eª¸­1Ù+U)[ã`HÁÕN=Ö"5×/pȧŸ<«"Áÿîè<Ëc§fÿæì*ë¹¾në÷A2»iëFÓBU&{ymØUUkÜj3‡ºêU0䪀dÓ‰Ö¦…ªN§µÐϪj6hØÒ‰`1T¡Àаޠ±2È:KXB-¸È‰Ùq¦:bõÔ"ÍT¬žZü‘)ƒmà¼}áN(SŒ¹Y³·È^»Ï 7' o_íåõ°츃ñ8w›ñJ‘2jŠ´É©“;Ê!¬‚ë"¹£\÷Y̧Ûv”hïYÌŽr3Æ;ʺø°gô±3Š±È’YPì £±3ФŒk.Bì £œ‚tL‹¬> jÀ¤ÅzÁ†%F]':JÖrÆùºN3Wá;ʳŒQ5nZP5Zdž6&jýyæ™H,×ÕgRDÞO[‘³ÍÞÅ#%kØ» å”E*¶Š² ½3 ÓoE]þGŸø?ÝÆ°}²Hó'›‘"™üÔ`ad‘eš]<úåžU)“@óó ÜO¶¥bSÓì÷¿žg¬@z|‹ÌY=~‡ôø€ŒëË Ï"EÄwúaõÛ¾<çY¦V#ÐÍóL‚?¦ßpç¹Jó1_g‚Œªð†©mf¨-ç¹N%ŸÞ„ "®­Ã¼Ä£0ÇåyÉ0š¶-/b4åy•PaFSŽlgÞÿqÖ×B-0œg"^ÁÖWÃX'¦ HÁm‘9?Y_7Rðæf?ÖÜlí2nö¾®–·ë¯HÈ„Éÿb¸KB&<=Þö…‚cªÄ]šÉ]ÒiÍ﮽`|BÖÍ'ä \ð¡Í'¸Žñ YOÈ›SÆ»9³¾'ŠT!šçrv6S6!bt©£ªpëÀÖ?àÚ«DßÇ®.`5?.Yqôæò7ºcÁ–Lª´yí–·ÿu™'[½’8Üìïº×åòxû"h.Eb¼9áÎÉì&Ö&0–óÀ÷Û•S3(]ì|ôÛ¾.fÕ“ñý>˜%çáÖÉyàû}Ä(öÐ"{8 ØC@Fc{Èhìá€b=Pì! £±‡Š=d4ö°C±‡€ŒÆ(öÑØÃÅ2{H={HoSÎĹ?* ÕÉþXÖL´Å¾{œcÏ›Uí¶…cV¬ÀDx¹¬ÓÕ !³fÌhwúš9U–êÛã_Wyºo,Œ\ål-ªßY™þ›KD[ +ÞóåJ¦gã°?S¨*°×_͵_!‘*Ô_s¥N ˜-’«‚e"÷„-â‚éƒwY¤ÒpD¶=¬Âb‹l+P ß ãý©a\üº8·¶y>Û¬[$Yvï诗,úÙÑ+ªXVK;¤YcjàÞ–ÝBÍkò ¿îY„Ÿy‚æ> 9=Ø®>çƒ4դݖ–>?Ê"«$¹£q–*Y§h f3‹;}&¡ùNJOµÈ¯žä›##Ÿ¨ìx|92òùüäƒÙ’E Ž„b[,÷Éã/š^rŸ\K¦Ô± ƒ‡1׬(ÊŠ~ñp§u‚Ã8ám4KÛ½Nƒø ×eÒÔö|RpBv€å¿.“Πm;Ñc*Γ5r]%=Ysõ)Xúÿγ¢ÎÊ'àšÏ¨¿ˆí*žsÕ­hò d®moN7÷Î}×™¡ð@æÚm«Í‘P~ÚåõZÏAŠ0ˆ]\ï¶ÏÍlÍ(’´q€kÙ,½ù:~ r–ÍfΦ)¶î]š›çü¾…¯¸y°{îâ¶?Ü~ý² ·Û°Ð+*PBãöÎÝì1—éÔÏˉ K„¼»”ƒÙŒueé‰R-l[†Î¿×ëµ¾ˆCÖ[—Ó\Qã«Ï÷aíçGÿ3½^ôλ…Øÿlíýì¼ F'€Kʹ!Ì*YÀšÞ"ë„Ö!kz@r‘`MH¾í 2Î0|IõÁ6Šx¤Juж¡É#yG—ù.Zd‘𠾋€|· Ö E™ìvµcxFeºÛš‡d»]#ðÓRÅ(év9¤fˆú¸®‹¹y‡hÅF{,°û8„¿Ýš1\QÍxAX7°ñ¶,¿KØïè$ÐpsÕ빚—Ùgdç¼µÝe4_Ô%ÊŒílGmG‘*Zç!ÌÀ¼Lõ,avÜ¥Hªc‚ž7/EJÓýü„k1uŒ9ÓTÝœC²ê˜ñ~øuÍh^æé‹†YÍËvž«½oÞ+=¦SÇü»#7Jdž\›ö¼;²bºrÍØ.Y3:+å wÉÑï#B³¼ê)4g{}—ãóŒê[W¨‡ j)yúÇhæØZ˜ÅöY²i)pùŠi=ø_ÿñC=á¦}þúmþš R0FFæ×a}ƒ¹iÀ‹ôM3ݼ¡tV–)Ã%»÷2Þr"2Ἤ‚‚Ÿî>¥:m— ¡eýi—çì l›`˜Çdíòš%|ž5Z‡}; kÕ «ŒÉIlIN¢Eæ,ç$’§Ó<<éÈ!¹üÁqîß©øó„7$AOÂ9‰€äÏs†âU‚ž´çp¢HÅ5dÑ$[ÉtC6Lˆ•dÛ‚69ÿ«$ÃÔöÛà×5k’39C~0Ãe¦H¹sbŸE-P³ï[À+¶fb–G(HUuÒ(¦íá¯êtó4ìxë,± f¼™'m”¼/ EÌèuBF¯)X£×½2jô:´ØÁ!%'‘nCU¢G#Mhš›%ìö#VH~kXÚÕÈoA ×IùíòòÛ¼V©†ùÀ8_ÿ!¿½~[`,ÓýpEÜ£kÞ-ýun16Œ`µb›¤YÃn¿VéÆ8Ó+J,0€i硌üÖ.0ŽÏ3æ¹d>dì.’×Éa©N2Biß8«ˆÒž×CißxqˆÒž×Ciß(í9ï]¶'ªV×ë+x¹uL^Wl´Ê²÷’~ RÄt4æ±:š† åg×É"{Üuª+V3Ø®Ó ]§úƒ*îÔ1v „Õ1YÄÂM³Cý©ºBên²4í¹ý©ºBê˜ÿu̲÷§nYGúSvÇmûS½óY<ŸikPMšsMíÒÓkJ¨cB½¸®þPÇ„ýy]ý¡Žù8*¯Žù=µˆnh‰OŽóˆ pÝ`Á“Gèq­/%¬t¾©ù -±àqH˪ìl"òêõ"•r·Ù$ù³Èxãû%TYdζò”PÈDBÕÚ$ŸPÕúš±CFªÌˆ‹ª©ã ºPe‘"Ñ  U€L$T2&žPB # Uª©c± !PŠ,U’{#Û‘©t]Vx"Ku:$Y‘¤•"²Èþ*´ A Pò_¶ê²Ý-<Çöeöü'ŠŒÚ:Wh[f‚TŒÖé½BéÐ!õ§muz´ð4«TOÃʃ&‚ŒL/DÌ Hn߇u2~‹¬NÄ)a‘Çö¨ÞD¯­¶Aôk뻫YÞËðR| kíµ›±î}¥HÉÉÑ[—çŒIýºmÚ"r‘&‹£cŠj Pê/K¨-/ÚNS¾©"v¢ö×Q±^`òèç»t¾ÍA²2~Ÿý H§ +¾v•$½ùlo‹Ô„»Ì€,™Ä˜b+rÖèmtQRpž¬ÑÛnfºÎ=A Æ¢Ôîùá˜uâ×_Ýú€ÑFd 1±µDy;# )01Ñ $Æá9žûn¥Ç”ñ+šo•HÅ[èÂ,#þJìþóü#±h|B 9î?EÌÍïßf úÝ>ÚÛA2+–2g‘’!’$!³C6ûsdgo‘:aìì)Ø@øŠEÁJºÎ Q&N:H·È*]?Z`´55±õíC7^È,áЄEB扊íÍJ>ü"EÂâ[­ )9cÜ­9‡ž‘L $°1®@„¿H|… —¤N&ü½Ëâ¹ íZoß°¤ü´Z0¿þ2³û­R}Z-´›ÕÂV ©?­Voµp#ÈâÓjaõV =AF¢ÖÝiaèyV£󭇀(@òdG‘ø;Ï“Ï0(K´•ýtDÀ¤z!ë„#&Õ Y'¢C°˜B¨,EZn‚†^ +Bû6íÊø»«› ͳ±ÊH¹ÃwlÇ|¶Ëuu‡¤Êø«{GˆDÂ!©2ÞïwÛ±?M§‰ ‹Ï ¢Öèy– »±|C‚¬âUhÌ=*@‰mm„¢‚*|°C-Œ *! ”~¡x‹éް©!P~F3LÀgªà[ÒÖô?Œµˆ@‰ªn¥|–©¥ÇŒ[¶‘ÖÑcªxtÝ¢ë,²d®!8ïEÇlq/‰º™¹³!HÉGì-+AªÃ×±¯˜žë{øzœòàñàdVíøõÕ½¿²àÂøn.Œ%o€î|ùY¸£a|ô~Ö‰0¾…ÞùŒOãèÏç9Çמg¬ù2îÄðâ}Nt!,¾›Íªº#Hw4ý±Ž¦=AJÞÑ´R1Åäu&yô¨ 2ŸóF]¿`:.©ý:ξågf­õk p’KÍ ²Ÿ†ö1Y/Y‚TŒ¢qvô%„´`¾t³9~À–äþ‹ÆOËðlßPe’jñ\†Å°¾–›ùA2£â» jw‡TQ7BE‘"ß·M(—eâ­Ã¤vQ$3|/Q5ëqÝYkhˆ2K„l;~¢HÁev£ñ³Ì“™ÝA (J–úoDH¿/Êô蘫¢LŽÞ(#@ĈdA=e<ü¦³T)EVØÅ¢Ô¤ìý²ˆ Ý6Ú —îܤàóøVŠ”‘¬™ ÄUŸ´+ l`GQ–é2d(‚–Õ9bá<딿äˆR0®;í ÝpÁä0Þé{ñ¢Ê™¯ÃŽ Ø^T"•-Ž ÀŸ¶66¬¨ø÷s+q…MJ¥R^n‘©žáÎWÉlqäý"ª2á˜a%4°ÝÆy|1ma³RdTBÓín6pE\Ñnw·0—îÉ:¹mlxFuΖŸ-·!0PD-£¢=&ŒŠ˜øôñ4o«98¦L¥¥[¢<œ§J¼uö¹wpí 'ŠÓ¶ôïR]0nKÛÓœÚJqˆ©r´ëë~~ºa€fBmú&øâ ìùsÔ¾Î!Ù"ËD»‰¬çë2¡lÄR*rä +êtê«OâÎ3™%S_!‰"–ËÖÍ?ÃüöFž2Ë“¤Ä2þd–ó‰áÖ«gª}·šY»ëRÐ’¡Ûì¯Ö×îôöHêV÷‰ìá×ÓI²æ²©ùó´²hãÈзeHK¢»›§~ÝHtï÷Ð-አԤmÆóò8àœà’i‡®ø¹—ŒëÎ6Ö5+G%iYû¢8Ï»Tÿ„;ÛËdÍк5ƒ_]È=ÛMæ‚g»Ùcõ]æIç„u or.SIˆM`åÉ\±¹}¿¹ø§‰Z¬‡LOëI…š2/X-XOä¬2/99«y‰±œUæe2['ÌG)™yî>ñ@’¶m ¹À]ªÓ+hrJñ‘cëÔCv\:w·w@æ‰6ãÃÚBM)¢nKf½4ÌËÕ#¯Ÿ'ÍCÉ69÷c¶á ‰¸Ä´pžx]'…NíÊQ²DMÎPª½ùzȵ{ž¡Ä~2^+ÿq8ÝšŽ ÿ“»õ?¡HÉûŸø}‡CªøŒ`-V¸K%»“êH‘ˆËú˜ˆD¢u¬ÒGëHäfc«Í 4ùýº˜ç>Œô˜:êQO2xrOšø×’/@W^‡m.¦¿¾'Mü»ýº[nH»Zë ²bùÍm1)þplCï'ï¥Ó-mr¥Ìdþͪo&HÁ´ft_Ê<52Ø+òw>´¬Džqîˆ7¦”‚Ù954Ú¤”l*Ü@\^%“×VV‰–õBÈR Çk ¤0)K^ e}ØÀqHÊòS åÝhmKÖÉ)ãÕÂÉ®‚z‚TŒ{*ò‘2±×ÞfØõ¹«ðÜU–¦&ð4Už¸Kv#ß»Jó¸Í'ICð Þ!4 ©>VW·›0÷Ó®Á`µÆFnm.šø~ª"Q%Æ´V©’õ:Dk•ªüƒÖ « ÅÛ+t„Ö*UÉÐZ-ÓZ%jÉB=–Š7bXõX†NC=×^¥©Çë0d„zì¯ÝSRs±Ý;)•R[[k X/©:¦õpz«Æü P'ëK显Z(u–”ˆ=¾ÔI³=wÔ½:æÔwÜxâžÔ2¡yãñS'Åzk>SR«Tõ…H­™Pó.‘PIzR$”Àæ%¢P‡”q§hJà‘Pû&ãP‡Œ„$ %pÈX(Uø P‡,¹¾a%pÈD(Œ ;2J°ôÎÇB Ɵ׳ ¡š%hé½O…N• %X—Ót8Wã¥YÃü:' –ÖÉ~ô© ~Ói °/uªÈ´%|ôÉ`[î",îô aa«K®-¶Û‘-á‘Vl Ã@Â$i]Rýú@¤®Ù@†„<È"K3„€¡.‰¥ m/÷[{¹™2Ú^îÖ—¥p-)9Î} šx‰-UˆcDë#`ÙR¦Ë{æv)`ØòÞÛ0ü]Â-VRÀh]J†¥` ûyÞ¿Þ)¹ â -Á|%Æ“F*kð†8¢&ÉRñŠ©ÙÌÝaëSêDæmc[.ABîëfÇkeÔ»ï©íaÃ]êàÄðŸ-ÐÔuwýü6óÇ%Ü%táiyµ÷­€±,ýãõœ(Rûâw³é>wäµ›úög¦W†Š¤xs³Å˜7K ·òÉÍ6]?¬Ý¥_ôÚ+\æÙi#ÓÛÛü:Ü¥ú³ÌÓíeôw>‹Õy:[çyA]·DËë¶]ý6ytýÒM¿ëøCïÓ¾l¡5¡n«ô„•ŸE!ÚTʼn÷˜+ËOwiŸÚÞ ¯ë’Y–‰ºvÓ*ªDæ/öÝ¢¦!²þ¬Ó;Ü©2Á¸2ÓÈ‘$Ž£ñÕ¶Û…â«eY±™¦É4•¨»Ì4H¦©®Èz¸z$¶‰ùL¹03"Tª<Ý ý¡*é ;Þ¤¬DŠÅ…ºûñ(oÒV[ÖÛ Ù?²Réi6tª„x‡‚dU$ä3§í²<²d-H†Í‚:˜ðÙáÞ¶Þ¹ËRÞû1ýòÚdùð~Vuºƒ={Y§˜vXœ+ë<¹¥A‚'k‘p#Æ’Yó‹Ð‰Hd-9Ée© ÉCF¡‘8dt:ÉCF¡ ‘8d«oDrà%Ã÷B’‡¬b§a£fÁ·Y«„%-Nv‘µú”ÁH{î~†7Ü%ÛR ¶ [´Z³.6=b4Y‡”40ÞÕz Òl;{‚dHÿ}gfºAjZï*ÿü¸œ/YÄjׯfð µ¹“éÿù“Ýy¾Úñ½þÒcVA¾´¿YG ú÷ ¸óYœwÿcy÷…æ<ï~:U0“²t‘u‘05ÇÖÚ².Ykí‰XkË¥#ÖÚ²f2XkË:ÅYkÓc¦¬µ)2a­ÝÓ_OXk÷ô˜)kí… £ÖÚ±Ööw>j­ÝkmÍ9h°ÖöP×'´CƒF’”¤ôdË}=A2•Ówžê:1×ôcÜ#•e‰Í ._©,O–¯BÏO!«X@m0?QÈ*$’hi= A*†©cæÙÎ3%ŽÞ”¢A > }…cÊ?²ëú‰ Ù4ô]»d³ë&’†îöÚÿùß?ö×Ïࣴх×éæ‘01È/¸Ÿš1.°+Fl‚¡²"e¨‚L0TV°¬Äh ¶ 9°Â(R1 ¤OŒ"•U £ÈE*«ùž a©¬f,1ÖP˜#uP° ÄXÃ!£ –k8¤äaî*Rjj{¢dPØ„–šÌÊ+bhÑR“í c%ƒÂ Ÿk`¤dPØäP^ˆ¼ÊÓ6>¡Ä¨rñ‡|KÉÚø;y1ÁJÁN^å2i ìäU.ÿ°“ç)ÿ°“÷N·©Ø~<äN)Ìc;x±uó¹·Ï_Ô;/4Û3sG»ž ÷+"£Ík~Ø¢éØ®)yöÈu¾Žkìk’¦·.C׆N TåÅ_ëêŽ Skõ™ %¿÷†*ÇÌ§Ø |î Ró²[¿W(».¾o.Y&Và+AV$·ïÞzK“G÷õ¸dÓ>èϸeý –õšóÂÛö—BEBy»P¨L,ìP•Ô šMìia–Ï:Ày«ö²J2#ÃÞSCœ ׺d8X·ˆ,ÁZÞ’á(2’ ×úd¸… %³jBNñ*Ú,e^:¶'°”qHͰ¯#A‰<©W ©Jˆû q¿” ]]8Àë$T² o¹Œ7.k6ã2Š”~£d‹ëíö† ým:OýÏýu[ª³e½9ÓÕŸÛí1_:‚Ôysñ2sûmfˆ#2R†· Õ6úg‚,ãÅõÕ×éUÑâúl‹ëžOæu¼¶ŽÓæüÏHm}K©2ïæuêÏ?Ú³µuØQy¨`këýz€J& %3+¡ö7˜ó¨bÆCÞ ƒdä*ÄŠýçý/%$´æ4aC©DÅäï)ôkXá‰:¡´¶ÙËBQÛŽ¸Ø*™%í„Ю†¤,R5IG,®•Ì9¥—ùê°A§’‚5èˆA§’‚5è\ˆA§CJ®fö¨R|«‡öÐUR&ïRðÐUR²^¿ñúUR±ê‡xý*‰S©cl}ÏhS˜ÁEÂz]l÷¥#Ü7%“þÁˆû¦ˆéæ¾íÇ Ü7%«”Ï1â¾)lºô¹“·E9xëê„n_*•%ºØM©œQÆïÎ-´ò”J+ü‚q›Cƾ#Û«@ö J±ö [yÐú+ÅkY&kE=?E¬¥C¤¡WŸ™€W·‡×kí,¤TÉh÷ܘ״ôɪ›!üz(qºY6Ù¹€(•R±ã|`…|M`½¾ß$ó~.Ý{ÈOãà»c†äÉl+z‚<Ð!¶Çn‘óõí­wRÆÜ˜mú:ÌAªÒ­× réè¯ë`*9oóÞšç¸öKãéOY?†‹ÛÕœ—ËÓ:ÌÁ²#Kb*¿'_ÍíùÒ}‡UàŽ¬¸lŸÔ¢*ÆuÅ¡ nTúÓÆ=£á}ƒL‹Ô3š–718fd¯Œ„88¹±˜‘µ{\{‚äbFÌ2ôM‘Š?O¨8`ªgìÒóèúézE=e¥Íøs€òÒ˜=4!=XÐxÜr‹õ[:KQб%™Fdª÷ÿq‹&78Yý~^%¬›Œ/”f ’–·\tV°²sk ÛÂÂVge‚ l‘œg•B¢4Y¥›¼aѤó?š¼7¬ó?š¼½Ÿ@tžlò6a£ óŒU‹Ú%°ná×óD ¦UpLå¸î&Ô›«xã‘2²ñq€K7œ<ù_çÔ 9ÐE6cÖéÑøå¿F©:‘è¾Ë£ñÛhH5Ñ}çvœžßß©?£û6¼î{dñ™Çg‘[ß@%Çg׋ô<«˜ÿ·]Œ<ýõú“vµ›2Ú•ÎUÒf"Ю2A»‚¯8WI›‰@»rHÅ™GÚ•ÎuÒ<"Ю4&)EiWá<õ´«µ'HÅd9¡aͦ)Ù&6ÏÕ$M —Oì;o±Â¯’F¡‰¤ó*‘]ùçšOèÒþ¹Cr9VMØ;¤äfG3¤byÝmK}[¼ÿkf9ÜsºÕj§å€,boÝ`ߺ±£¿^rȱèUŸ6V!mm&| K›³‘Üf´†´_Kç·æZdüFÁš\íG#ŠNÌL³YzŠŒRl¤+kH1¤fm7ÁhÌ!c†£ûC ‡,yƒÎ‘"+ÞÒ¾‘ÿaþèÛ#Zˆ„æ‹§´ c¬-~ HAHtÛŒ`'±ï:ß”sHIîçÕ·ëÍ4wêN©>ÕöÖ²ä9˜GÔ¤&wýzY9äþŒþùwgÐÝ]ÞÖøkVŒÓB%cõe;æô׫¸‰ªu‘jɧ\wóf–=¤ˆd«˜§¹¥ïR§l¤Ì`c"Ý­jbU£E™ i`«-hºÉg û®½ú#…=œg¤Øà êí¥gÍ¥½ß6äc¾u]G"n-£8RòÖÒ‡cªOÏŒ½%<34!Å0†È”ÒÊ£}‘Iˤ¶ÙŸÂyâü²ÿa*Ín$j ~Í Òìòd_üÖRE¤78æ0áŠtÒVuR³É†Ö _Q‘,—>Þ°¢–eªÌƒì5&ÝD’ø UË*•ć,†µL5(¬²/¬jY§ò G[¾rHÅ˨—©if ¾k•³£Íb·2a/£pÃÒ|Vý÷04ãòóÏH…ƶùýr¶Ç»Ý_³UÝï=¦"MxЬ½¦ñ~øuYmÛõŽÞÙ¼–é~¸¢Â›—5pž6ªÞ¼LܑÿîÈÕ°!×f‚B‹ Œˆ©Úê[ãŸeÿõýÙcö¶…E‘{ãŸÅÖÎ{QÆCA‚è¡yTäÔ,_óåø<k›1†ÇÄ×,«D »,ªýZÇ+·dš~NK 5`‡Œ‡ÃÞ¦•O”`‚†Ç=h¸;œ§Ž.0Hv…V)sœ]á"¶M°:ŽàŸ«UÚÇ¿ …¶rŽÜî)3m¿ç¾õõo‡” [±¯u’A†}Òµ*’̬b«UÉ:íÄiW«*YueÙ^ŸeZ w±ÏwébÞ¥)³æÀoÖ|¡HùÉRÙ7¼M£uưTö o`Óèàc©ŒÝÃs`’c©Œsÿ¦HÅŸ'lÌuž>O`Ó8$žañ¯óôy'Š$ê¡«W·õëm/yažO žX1§/ –ß[ÏܾÄX§µHaŸã¿Æ¼°pí»M±‚_—É"d`^k-Ù̒ͳ\8´Nð@‰‚Ö:Áˆý4òU<aDOªu‘4R zR²Ö»a‡ܨ}»˜Ë¹ØrÐïøº´È^N#k½:ýk´.Z–W S<6Ì;vYo£œà˜5Ô¾=©.26¨}!zR]dlPûBô¤)9¡ 'uÈ„®Ja«ÜÙ²ýBf‰.D ißäž Ÿ+‹†"牅úC±‹êB'¾8KæMtQ$~kGtQ¦"ž‘#°.>̯^8<××mýö3BQ³îÒVòwi‡ñbþÛòÓ{‚”Ÿ±¸›k­©ûó,3ÆZoK;°‹0ÿÎ&‘ÿ―6]–›Y.)â®ïÇ+Œ!¥Hf:6 ¼Ÿ¥Hy=!»>]Êtf^x—°ÁÛÁ̲#]j–ÇÔ‚.5kÙ‚.‹ä1A—ÅGù¼n 'N—|ÎDGr&tY&î'CˆX,_Jvå_™%°(ë# À瘶=I”ÔUÆä˜Úû‰sLRÄóHñ¤Ê:wœcêŠa 壮ò¤z#(umŸ¹b”Õ;ÃÜQÉãÉ]ïl‘g3ÍÁÜAØI´-Õ­ö üÎÉpÞ- V¿•üä–ýþâˆÃÕ¸ô›Æ6¼ŸÓ3X Ah°VE‚Õ;ãâ^U0…÷uO±Ï}]¥”+Ï©ý ϽdR¬Ú­œÞ==¦Œެk3Œ`ñsm6CHK‘šÉÌCÚ&¸QÇô…xeèªæõgÄ+CcÆÓ!%h!žºÎRläé¡k>Åj )VºæS¬:’båqFžÍó #XLƒk®%ÏÄܰ׮ùëÖ:\`­Xk6)g I9º.RJ5””£ë‚)Ú˜”Ó‰hk»ÎIŠùî]ÚxÊÖÜÍ#«t:):fý±;ó> ËißàÃPdŸãüÖGØjAƒ™dú/‚1Ï„a¸5_Þ3Á!ë`y­ãrk‚tTˆ»Ùõ4Ksù%HMs&ÇplÇötºä*à‰4w³¢¿÷YƬ 3&šÏŽžgãÿN« ï鯃óûétuû£ïÁÜØ¯/h—û;Ÿ…ʦ-SÛ—éuºÜ¿oýÙoÏ<”Ñ®à•HÓè"ÜÀÎ/²œÍ'];¿Èò#´p‡µ”EöQpíå­Á{3k+8¦ŒìϼmºZ‘ÉOzŽoÆ®M÷€D÷"“I]™í¤¤‚’ö}óúX9¤n ö&ÙÚÞwk¶úíj1‡,"žÿÓÏÝzþ‡»$‘aÛ¿»åÿ¦j{¶?ãÓŒ6ãJU\_„u;E¦8<3·ÿthL‡Ì¾cVN`T;d"+ç4$›•ÓÀ늱}GLå"Kyn*‚… ¹ ‘ì 6pË'µúz@V¼¿¯õɽA‘ÕIòZH.ò,ECÉÅEžó‘Í‚ÍÏÆE.ë_kæÞS¤`²HP¾^‘ËØW¼ŸçeÐ0/XW$»K¸¿ßÍý— #Þœ[~™™‘¦† å¡mëvýmzûŠHéNÿû—Ôxl•e¿V‚ÔŠß~Ek3wÃu!Èâ“æf~Ý,XN£oÆ:dùIs[­9ä¹o~îYEhn¶Âcin7‚¬¦ró~{e—¿óYdëa·]–7Qh­ÊÛ|ð=½ú\À ¶qk÷ˆ‘çoÓuÀFôP›éÎv¦§rP4Ó}ÿ|wÃÇQulR4ÐÛô».«àJgA¸_ä:)Ï "§"/R’ $r*ˆ…Ñ!–øf½*`xB|³÷¶ÁÑ3ýÆÁ’»¿ZŠd¤Š_·â—2pí6'M*N¡Ïë곿¿Ûú…þ~‘'mýP¿Èk¦¿¿3ô÷ ‘%µC¿'"±-$Ï-DÎÈs·R9’ç"g¹v ‘ç:¤Œ£Ø†º‚“çšA|D– …HE†ßT±@ü¨O³Ó™ŠB%‹ÀÁ"¥H06\ą̀¡zG‘‚}8Ï’O±… ôëÃè¶Û´­ W”ˆŸßm»‚Œ0ºÍ1wÛ.zL/Ç͈ Z>϶dÜdnár鿶מ uì Yˆ©F!³TÐ2Õ(dÆ–ôm˾ƒrq!óds¿…¢ºCòÍýi H¶¹?ÂÆÓ!U,Oi"Í}‡ÔQû""Œ.¤`„ÑvdÀÂèB FmŸ;F)û""Œ.¤à ˆ D!eÊj™@ˆIuüÞ͇¿wÉ}Å[@l3C©E: ¢’³Øm‚ Î!e4öuê×ñã§,B@ìGì«å©ÎÈf‚o¯—]®×Xj-;$;‘\@¬].÷YEbÌvþ½÷¾P_È2ÁHì¶ )ªC¹øu]á{¯X££MÔ±â†ù5Ã^´Ül'Ïýc¥ÇdÚ¬æ cø6+¾)iÇ5\Q5ŽãL‘":{YºÐvÈø2Y‚Ð@‘*fp5ƒ«Be©/\9¤àLÈ‚W¡ò” 2â*2ø%:¬Öë°à˜"nb)ÿð4•L~Å#ØHJ&2îM° pÈøWlã“O‡_W1¶Ùp!_±’é¯8¼uJ¦¿â#’ÿŠ!4Ä!«˜B·!ÀHKH\‡fŸYvó<¤àùòÛ9¥“Ç|Ì×™ EÜ, ‹× õÉYeÄÖÄ‚õ’*Ó†ó¡À¨ªóE~»­mNÛÚfÛõ™aa²‘•Iž[ŽÖ†|¶÷‰")ÃÓÉ²ÛæÕ.÷ïƒDõt¹]:®íëß?KCdenue[9³=Š÷{Â×Q!†ç?;ÃsÝn ÏqœÞô׆g×óR‡džMÝçžVp€ò Ï×J¯)Qbó·%6‡—¤N›—1ü~Xdÿ8îâîémn©Ùûôô˜òÓûdÛø ï“Bg YìXV`²ÿ#>ö¶~4¿/ë+´HÆÝB ÎÇÑ©½}ß¼Àܰ(6’Z¥Êˆ|^_GGŒ,؊핉®ˆO7Ÿ¶ŠmG‘‚MÿN)ãœ–ÉÆ ôÉH˜”ÝPèŠõm]ˆok¡?]$CáÏý¾xvQd©ÎàºÌE‘}ŠMvy¬õðGòØ¢Èyìº9y¬CÆä±ÖíÉcR2uC$uH­y¬CFä±v屑ÇZ$–Ç:dÉÔÍ)ô=AFä±û;ä±Ysl·>lö ‘,‰?•¢I/ÃøäE¡RH[ºY2V·Õ$q*Š”ƒÑÛÌœ0ÉŸ¼MÏ›¢Hz` Ï›ù{Ã?â%S%þ¹/™¢(ÙðÏ…xÉE™ä¨£MQr©{@ë%‘¢Jø¶Ú0Õe&HFÅ`Fù0s©MŠ™d€_Z þ^$·®_X´”YÂ0aãú§™ˆrˆ]CQŠÄÜñ°ýNøu™èx-ö­ówžxqýCõ69§—¥þ ó{YüòìýT Ìv‹"¡Ä„™iÿ‡ù[`8*Ø7+$¸kÇ\¦¢ÊR9€ ÚHnß;âûR`çª(®pÈüÐ&„vAÒX`vVÌ ¬)Rp95Á(£¨t*-™oUÁõ/ÍÌ…½Š ÄÎzÿç7sÝ]‘ÜòP} IQU+/½œˆ: ¨jF°y"u@QÕœ:`¤)9ɤù`u€CÆ¥—#ù:ê„ôr$_GÍúbšuöÅ,êÔJûb5NÞùß¶ñqN´Û" uŽ1?ês>²šx@*6÷³#¹ŸEô¨F¹ŸÎUüd ´AÅPÔë]º´¤ô]—¼øJJ߇À¾02ì!äMè3Öìh³å´ Œóuò.EóQ™e‘‘áÞú»¼KË,g7æËæåG°2é96ËL¤6æËóéy)¹€k+²'HuØÂ›å¶ðË“S³[øçá<‹cöæ³´Eaô×K´Ïr§Nž—ûóÜ=Ÿýõ B·ö„EÌø\ž/’;d}Œ×¶¿¾Çkûçîï|† »o–Ù˜_§þ·ý¡?Ÿçl7¬=Të,ûàwåé­.Ïû‹žªëšÿkï©5àØ¸?ýÔõÃü8Žª|µÃõâÎõÖϧûýv8W …‘‹ÝÆÛ;`^çôn×â¡û£ZþëÏu«bÜ×ï¦ù9@]e¯b´ÎÌQºþðöåS±ÎH3…Ö\mÄ ÒèÛŸ}ÙÚˆM.?~(LeË#?@æÖIYîó„(—™LI@ÍÐ^AIè-8@n"^‰‰Z‡¹ŽÈ9d4@n!S£CrÝk çÑ©q ®e¦Ù©q ®%&júñÝ&] J™"ïŽÁ5Ã!ç\¦‡2c‹éoDÃn4‚j™ðÛ{¨EÆÚײöž"Wï°OSÇ­‡ºPd´‡º ¤—ÃyêÍ]»/¸”yΑl.cs7üÀ¯‹$ÒŒ‘A²Ž …–¹`}Ó¬Ux0*/ó„¡¥zAo²ÄÁR«­dîߺ\±Î&¶o¶ýe®y)õ8›Å0, rÍt 6 ê@”yÁ[ž’D‰cö¢Çôˆ2/“Ç ‡äLÆ Ë<Õ-°¾ÅSGLH–‘— £B‚@*PbFѱCvjÚ°í/Ev”Ã…• ^Hf[……ˆ¥àí^+˜„VÉ»#Ù^ïÜ‘JÞi£Ù®À)yw$ë 5w¤’uGÚ"‡àŽT²îHu׺#-sGÚ~=¸#•¬;’Ýxÿ.Ã4Ñc–x„hɹ#}0`ˆµ êÉn­F@&ì­Ë8P$o2 ÜŽ2p¤vfž]amH»h~b7ÃÊ¿H°ä‰MLYäI>=šŠ?ü1C>Úxc»‚v©,Tê{G ª²H»^šOŽY¤mwVX]l¼e¸"S•²¨øp(bªRkª2S•²¨“Ç ¦*eQÿQ‘€w©Ì\Xò~–œÍ}ŽÖæÖKežØõX›˜a±™Î§w-ÞéãÄ»ívKÁóA×Á¼KP BT€ˆ/k–¥JÔ.Ì= µ‹R³ÑqÎ-Ë‚qεHìœ[–E"l ›¿8¤äöÇTQÍID(Ë2ÕG‚Ú²¬R£7é–1"aý¯c"B|†í RÄþ¦¬ŠÏʉ»oßûîR™¨]œš¶)2B8ÛÒ¸ò\±þ×½5Îʪb;#‹m²¯áÎ׬ÊȬêk +À:ûƒþâ)³eý¥ªµHØb낲–©”%_Ö*š²pwØâYógá´ X#K3$?V‚<ÆÛÞ9fßM7-íÄÖdñãú=_~ R} ˜‡~7#Ý:Œ;’Rx¢N•屎±«Ç\ÆïgÓ¤ˆ™Á» z“ [äB°-uózê(RqÊÓ Ž¨H"X,À“«Lþô«›*c‰£ÖÈÞªLÿ<Áý,>ÆZD¶Ü‡É#KŽû`ß!îµÊJ†û`ûÀ¯å6ß‚”,µ´É©âØD©Ê*6âx!&J)XR÷®ë4Vv²é¸Ÿõ…Ï‚Yÿ×ôžRD­®ÚskÞdŠ”ñT¬¦mú~!HÅt{ì|ì¯(χ]ScG•ç©~ q8¤ˆïÝvÆU.x2!yV¹ü ï|®Ò⨠T¦@ £ùˆû+\Q‘mÎ?ëóÙ$;Ú˜a HëÿÛÊâíÝÓc*žþÝÁ•Åý°Ê+ÞŒ—¨«¼Nò)ƾMärX«ÚnD­›b"ˆT÷Hª $qTB$‰÷ 8uT¤«ÿÑí±!pE*Iò ûÝJ¨És¸?GzLV}9Þ{ŠäÔ—ër?üzL}i>v¬¾tȘúrh[¬¾tHV}Ù‚ªCVqsg¥mAòêK¨®ù;Ï«/—õehƒóWЯ{¨`B¨] rhGMãJ¤œ'±®°"ýqñÆ,À~ú÷°Â+ZÅ’ç½ös8}­=AF§nü1 Û=¦ŒMkcË ©8ù<¾¢:µåEœöJfìÖ| 1|6?!1|ÅðU’³Ú B¨ÕVÉœ‰áÛ‘!†¯Bæ'ñ¾Ã11|d$†Ï¼ $†Ï!Kbø²âHv+xüVR¤2Õ-§Ž)™gûsi‡i½? RÄ \JpHw}Ç”ŠJ*†´¸• ½±Âä‹2Ð+>pj[ z£CJNñè©X:É®½à§9ó%…FJ%KÞE¿Å~¼•¬’´—ЬdÒ 59+•ñV6Ä«Ry*àÙaU*´|ÞïÜù¢"´‚Ϩ/3/ÌÉe"l n‚”ñæáÐ4P*®”HÑ2ºR\9Ûœ¢r~…Ûõ¡Ðâ—ßæúïHak ÿƒ†k ™m ,í”f’M¶M ¢;ULËúHO¡ª6ÄÓ>u ãUªJès;d­V©ŠM`YH­ÂÍ툭Ú&èéfÆ-ÖJóhÝd ïÓ@Ñ|¢už XiÞ8Ëò4ưfÐyÔñÞ»…Bu…“wƃ[âÈ*-‰:x#t¸¯£½^žQȾ‰­n7|E…“4ŠÓ°¹vŽÉ­§8lRø<-ç+¸jWZ'ŠQ8O§Ây:~æØ³¸ÒEâ¹[kþpÌT iõ‡{ìÕ59-ýa³¹õÈšs¤Ý²–«à‡68}CÞ(9¢Âþÿû(t "yEÚà‡¶-!’W8S&zLOx¯ˆrÿó˜ðî"j¸)ûà] ­õCÊF@¤ïªP™e˘y:U¡“y%!O§*ô‡y”ÞIjFUlêP7ô}HªŠ‚Mê¶Ô¡™Sò Vð1ÎÂéÓáÖésýº®ÌReÔ0¯Ê<%šðUÌ މU)Sô[»CñÏÑŽÔ¹ŽPçªR'Œ³VÛL€c ZÖjæb([•E" “©«òƒvíÚcÛ‚vE‚Ž"¹SlЪÓ®9t‹ee…+ª$;3uFUò"¹†ª*K †Â‚‚Í®aÅĽªÊS­`+á¤`KôÝæ»»Ý*eÃÛmÌ‚ )ÌÒÇà˜*E3Ë XùWêSêÌ!í²‚0´ªtj~·"™ cAŒìC+Djˆ+'³—c– ‹Â† çYý‘lîRŦÏtDŒRU5›>31J…ü">)¨˜ŽWÕY²PÈ€"5|ÞO³å «Ê©Á|›H¶RÕ‚Ýsu„`XúiDo™¨1T+–š´´—{ &9¤`Ú=æs‡ï½Vl+Á¾É÷@©bDÈ«ZSƼ£H»-¨'˜ê"™K…ŸQ™Î¥£æ*øE8-¼•.;õØÜÍ!h᫘_$?bòoU×É&x ÿ:¤ˆ9Ú ÄѮβ„Ñ(v´«³Œ`mj:_娳?B½a§_gÉPïþü3y õö~ë}~vɇz?¿~Á[Á¼IS{[¿¦uÈ‚‰ÿ–»_ù;dIâ¿‘[Áò^éy²f¶ïAœWÁØ -=ÏœxÜZïUð5ίÃÅsM,aõPÁÔø®\b À:“üpGܧëH¨ŒîˆáOi6x!þõ!TÇOÄÕ Ît"nþÔ(TæX^[ˆÂ»ÎR‘£Xá]³¡2.`ýz™hdlA5ðâUlµ#œŠš„ÊÄ~3U“.<5Έ=N§ °Á|¯ÎEÒ|/DŸ×¹dÝ–êÔ¹úd‰´ÞžÑ|LÏöªóXaÓÀ4íóé–uPáo¦7vs½õ¥?«µ &È}³CèÙêw·É«?Ïe8‡k×ÁÇÍöOÞ³1ß=EºÎ©Õž]ymìç{»aÀÉ»·õCmܔۘ÷í|:5ßðmæ: bv’5ÇtŠÅ<÷¥ù~Ð+âš8f–ƒ7™Í4ÙÔ0Í ¥Å:/Sã‹ÿú/·(šÕØ-àè#2Ò7¹æG££Ù›¸ó"Ok`“R‹œeòlš ØvÕ€ÀBݹυZ ɱP­ab¡ÖÈ€²Pí11 µÆ„…j¿wÌB­±À1†°Pkä@Y¨Û1 µF”…ºë¥ µÆ‘p½ÀB­±ÀA×µªCÖñÈf«z„¥ˆPÉrÐ ¦ µP)ËÜ©VC-TÒ2׿m¤bšwh¹X³^{ôd0‡¬EÒÐmökQ& {óÎ/píϺW´ñ©EhGÚE}?¤ˆ´âISË,áè0¶!ª–ìÍž'b²×RüáZß»” =»²ÆÍeblǺå+Ø×RGË•.RÜŽ /‚¤ê¢Ö#×[göh)#ÄæM6ÃXר¹ …Í»û:žã»ûz\ ’jmÁÀs쾺÷ƒ #qhiãРë‘84ƒ<·ã l2‡¶+ŽCsÈ:¯<¬8ãÌßù,¾ãÅgÕ‘.›±ñD¯>Œ09ÇÖ¤_O½â=Xj°dídžþδJˆWÞcYE*l˜¬ ÛYÿAë…¥ˆÊRž½xS)Ù%æiÔJ°áÉ_¬¿IY¯ V*åÄ‹xµRl}ÏÚ¹µ ©Õ .àiÔtÌS¢V%?ÔöE­¸H,û†¼Ì5\{Ijt4éqýZÂ[¯êcþb˜¸lV¸)£õ=³K&©>c¶Ìy^.fâ„¥ª?ó!Ãuìû~¦¿^íáîA`–K6Yäpíeüë°‰G‡ó¬¸ šyñ=Rg Ìè¨užª¶¡ _k‘øŽlL¡çÔ¸_ YצF\:æ»íÜi¾s½Îã¯ÙsvA Λ}NZ­u$ÓÜUÔ7AáüzK?¿yäÒyéa­‹ä¢ºéVŠ”\•¾™Ây"J3±Üò‘Ý`­Ë”y²¬uÊSÙk]¥¾bDe¯uʼn)ÇŽˆ)kÄ bÊ=à,ˆ)Rp®ãALéò öuì ×p ¿^|°+¯À,××dÍÖ$aÁy\xwkú¶oZ‚”þMÆNÑýÒžúž{‘{Á×ÛÕgšœ/—oX.Áì0l|®û¸dy*Pø‘ßÍcñi¯’˜muq—®œ¬QCw›è1+ÆuÜl’|­¸.rŽëeW¸Uˆ„3}Ö…HÙa® ðsêBþ±…‡­q¡þØ÷)b.îKKÖ6…N}¸d—NC@ ®:bl¬n0û·>°ûwC"öo]T©`PÄþuHÉ!û×!ìß2Áþ= #ìßqîû×!KØ¿YÅrR&Z¾ÀœŠCNÊ@rRjlêpÈIéHNJ9‡œ”ä¤Ô˜SqÈIHNJ8Çœ”…ä¤ÔˆSqÌIYHNJ9¬…ä¤ÔˆSqÑ$'Å!k†Ðô#<÷2ã£NkÊÛ®`} ñ\!óÞ!ÙOT +9Úq7  ³vÆdje·îVvã—ëÊ<Áè°´Ex“‰ñÆ¿Ç8E³P×.Ø”ôÁv»z( ãhœb×Òc²qŠf;ѤâÌùB_Í<>Ù–£ÇŒ•nž?f“_©Ùä—Måqk:‚ñ¬¥»]ÛP¤ä³–Âk¸xÖ7î˜×e‘XƒáŽy¸4‡»dY s0ª±íÇÁ\ª#æRõ!ä ¥lûyò…ͲN;dâRWÙ–¦ Xäž2eÕY°É QtÈ2Üopè³/ïÇ×DÕ§¾ ØÅVøYGã>—~\OáM.QÏú#µ›æ{è¶ã|ÿã®~{AÍí¦ßuü¡gº§!D?ñ0â ’‰ü´ÛÓTEÜ‹ÖïÔØK%æR׌Ë]7S7VÖU ~cÕi]Õ ©y£ó äóºÎøÞ)¡~×užt/ JÖº)7¨q’c]Ë…m°¶ž £ô“ÅxèŠT2;7žêZ§¡ÛViWµŒˆ"ôá™EYu•p”#,€:á}l]§×ðŒRޱÖüx HA#zœ7âŠB±ò,Ëþ(ÿ2O—Šýî‘1a„AnˆÅ#EºËêß%ƒ”iÂì8wÉÑó­? „p©yBâm[«Ã1‹?Xnš5Èò¤›º ²Jù>QˆAÖ +" çYžqdᑸ9{$#cEda”Ñh&Üë3Èf+˜º·nS_þúcyBOú'd¾8Ú`a¸j Ø.ƒ”ll×€c»<2Û5àØ.”qÆŠíòHÅ¢â’PÁûª ØWÍ u ¾j)¸&AFÅ‚÷Uë°¯šG*Æ<£"Í åÅ¢ü£¨ kï‚ +ÞšCY±:b+¬kWXƒu i'í… y†ç % Ä*9òÌwdÖÉðÜËϸ`ù`'›ùÈ8ÞlÂ¥àxã‘"µ„o÷Šé³ÉY »`K¡ƒ•@©ÒÎf#<ÍR³ìÁŽ–kË"éÐMA›i’Œå¦ŸÍŒø#–s¤È¨Gßb=úV?±£ÈÁ£oÙ<úVŠL ¯ÝËu)™æ¥™ä&ŠT”!ïJ«´pVeQÖ½Sî¿ßÍý— E4 anl‰­!HyØ»Q±¿™åçLÑÂÙb›Xó×JúÀºwl7R8«2F¼³qí¾OãÐdåÚ5í¹o~îïØ˜¾ ÞñÈš‰ iÞïwGï|ŸäΠ9ÃË :€ò…³q<œ_8ÛÃ ð…³£ò…³ß•Þÿ½pö™ׄÌ8kªÎŒ E®ëz™lZRFy ¶—õ‚¥X•§Üá›e…îq•ôÔ¶i8Onƒº+ØÇŠÕÇrRl_e}õÒö”k8f‘´§‘•G2u}¤ó·.J<ùÉ&¢w¤J=[ôŒª4Ñs‚i©ª’DÏÑsU<2Bôlç ==RsF«>ÜOÞ@jû8Úð.լтI„Ö!•%H„É‘ñ‡$‘<†MІŠµàlw ¥,x¤à’s!eÁ#eÌ$±Ã¶;©˜d‘±ï&8O™|ë–°é­Õolü‚‘Ð.42_Ñeïv>Çöµ´ýi!ÈÈ[×¹·n¡Èè[·Ñ‹Cÿ¶™°ŸåZë£:áG`Ux0*â¼§}³…o³.xkNìmaÙ£)ÙXÈä²ô°Ô<\-M(Ñ™lšf„<ËÒJ8fŒ„Žþ];¾ßÖïŸ e|îèšõxLç.hîpH–q…’¥Cr<³÷: Y„Ù}Qd7D9‰– À6 †ik)R¤­Ð`¤uH£ªo¦½] w)aÚûmM{}ñ=?p©Ž<À¾É3•(vlN€Ôœq­ÍÇ ÆµvßÉž·¯#ˆ‚ì‘¶næŠ`¢Š«íº¸ÕÎS³‹«“ß ²HDÉ#͉A&ê\Ë6wÁyVŒÎj«Z•AÖŒÎj«„•GŠxÒYy¤äãЦ… Þvyuôò<›¼! 3e¶Þ0ÚÈ,årÛ¬a’•9ëC±X èòæR$|<Í`ÓÂÂRŠÏ`?/z°ÅÀÆ)¸ê¿uü´}zL·…Bѽ)DÕ ï¼” ÷Ån‘ÜÄ ËO°ÜÄ#ã›Óµ n¼©SŽ´ÁðÈ ‹Ä;ßšï(Üù2S¾YüÎ)˜06<ÖÉŠ•°t»Ù y-q‡M”Ìt”q&J–`L”<2f¢dÈDÉ#c&JæZ‰’GÆL”Ú›(ydÄDÉÞ%d¢ä‘Ñ:l‡M”<2Z‡í°‰’GV1Ís‡M”<²Žiž;l¢w>‹×/̸´øÆ‹‡æÑè`l¢PKm^°àÜ@s6µ¹Ã~yMm^°_žGFS›ì—ç‘ÑÔæûåyd4µyÁ~yMm^°_žG²ÙÁà—ç‘qÁ9öËóÈ:º÷™1g9W‰¬A®a÷ RB®m#¸¶¤äÉv'”$j*E˳šxïtš–WxÕ|¬aÑ¢4£ùèœæ–"J³µŽÎÖ:€lç\­cèÚ…ž'KËHŽ–g¶§-½K¥·‚–irU$ÚÌ'ËXR0®ikß?Y¦”[Á8Ì Ú©Ñ*E˜꣥8òËkºÓyô# |¢±XfýýÛÀs×ÙGîæþm¾f³å\Îç"%ì¸Ï—öúêÍ®ëûºÂÈL»DÙ³½¹,O3€¬ž 5FnÀ}o¾4熳ˆ!-âunY~úá~›½ñíÒ_×^‘Ê€ÿusÔ{óý&Èš"­ìyGþ4wzEû>ÚBƒÍ­½Móµ…æêŽjïèõò<_)ÔñªÿýwϦ²çz^:óäOßëá$x÷ží—ìOàz]›î…‚‡}™/Û#=/÷ç¹í›½U®÷g´Û Ù:Æýy?Þ‘j¡¶Z¾-‡æfœú×Ïá”Þ.æ—õì§×´,íz€V¸<²ïAl)c¾üÜžh¡7íÏ¿÷Çm¡oæ¡_{¤Òþªþ\»yø™)4§y®öfmõ™Ÿè=yè>ìš»Aïþ\ÇóO7>¿½Æ¼Í—«Ï½¾†¹' <Ô¼Ønô= ßý|únéÇ"ô>îÿkë>W?š7ïëë>¡Å!/É*÷¹={h}Ý3ªÝ§¯¯u¥—µ*¶T=f~nô¸AÅj0¬¯ûÏ×áÁŠÂUd°î¿~îóñ\K<î>`vì'<îЊ×â¨HëÇ0 ¾DŒÍ. ’uù·–v¨šk•J|7Ç k*3ksÔ(dÔáp ä‚Rš%ì#t™ÜGŒc8Ï2Õj‚&;$éÏ}İiÇ'‚Tlÿèr8O~1†a¢Lï#ŽH~ŠÞºD=ÓC4æl©9PÎÕ)G ,½ËuÌ€ØY2á0°Kî·‹/¹/ÄT{¤ˆÚMŽÝÚ/ó—GÊ„u”¥D…_çÌ6Ó|rþ}¯!ÒÏZ7™h=²ø¼Ÿ­3Nïs߇c–ŸEoçoëÃZ$Vyh{îß¡ Œã!?ÊÎóˆHÅìIÍî°¨Òqq+¼óNí¬£Îgo­;™ï²½Ãn+¤Í´ô¿ñb—°[m©é†6çË,UÎÅ­–2ÿ#,Ö¤¥H‡%¯°(,c¬žÃƒŸ9¦¸» ÁgN¨Ï û¶`¤EÔgo¨ç,ÇÁÜ«ëW¸"•ˆþšÆ&ä’zoØ/îêGÅö1ÍÍá×'? .2y©SîA#ê—IŸ!Kûî2úÜlTgeÂ$ÚFˆÂ‡%^ïјAH™—uâ_l]ËU–úŽ¡B8¥1g8OÄêŒ$-!zz^É´l˜;«3b&ˆ›ˆÕùÉîkƒ‘¢A)^rže*ƒüzÅ&MD4ž$M0p‚‘G¦Œ&‚L%u™J0¢ÇL% ™J0¢W”J0¢çYñ¼ ˜ Niwë¹Èœç×áÀKƒ [a줒c^å!ºu"î,y-¶ÂØÉ!%Ç%KzƒT±vØn]:Œ'[ýôHýÙ=ãÔswÞ•™™k•-)9ÙŒy£è1ÕAá×6ë¼<}‰‡>ÒïÈ^Q÷u¹)bµ\kQ}¿÷3AÊx/–GæuBÙ[yä@‘¼‡Ím»ºdM¢­íEÍ8¤âåg°««?öq0z×UÊ…Ëú Áy¦æëUæ…©‡SR:›Þ‰<êD–³± ‘ Ì–<Ä,Df,2‘ðmÂ2c‡” ÉŒ2zçËÉ>­`Ýì,Òî —… Åça‹¥ï-Ç!ãœüi²1A*FØDã"S‰ì(,wHÁ‘ÀbÕ u’$Ð,á.itŠB^LJ¼d‘á^ƒ,“¾b2'²*í¶èÂ=’©r`>‘ÕŒèqcÅ#Ñ£ÀœR"zܺÏHô(°?ßGÄ,=ŠzF¹bL"¶.92‰¹NöI„Èõ‡Œ3Ô.Zò Çü$+/(sžÃüöÈ2VsVD—ñûÙt)âVPf Š”ŸúŽ}p=u©˜ˆî`Á°¢Þª…AŠXæwgö°íÏ…SÆ2¿mWÆ Þ A*ºƒÞ Üf¾½qo÷£iu¦¾³, D½²}Ø‹§ÿ˜Å_ߨ<=¦ô4™Æ–Ò·Õï°¶×y½®ðÜ‹ƒ.r;¤]3|·ÓÏ·ùBn_©=Ÿæk;æ~?­ëšYWÒ_/ Hf{–[8ͺÎýO t‡tñ„»*Ó½Ÿf;}YAV>rÆ"/ûça‘Ë|]²ÆHcc)Šmó°¬pz?wꕇº¨=èŸ=A²Û}³"2nü0vãíÝÓcª˜EtGˆ‘" Idz! Íš×Otª)ŠÔr™×;$續H܂РŽ~­Øâ_U [ü œäx4iØÒ—ÃëÌfÈù‚;Ÿ(3–p4´ãŠ>Ð`!AÕ"*ïpL‘6P“(Y‹ÿmR ~˜¢”É d…ÕR%t®¸+ʤ,ŠLe‘–õ‡¥PY¦´³H: J¾ÄeKÅÁnD$“Ý6‹ˆŽ ™FJ×¢,ñ Ãe³u+›]¦¨x3‰Žè2E• êûß9ÆÓ}x6)™…òlǹí~šï‰ EŒg»#¾Ršm`_–ö÷AŠ ï7OÈý]Ú×L’Ãyœf »öYæîŽ4Ç~b8dé)¶´i‘ïóòó¦¿^Å8ãý}™¿î-½K.1íßMÿï þS3ŸÏÏ =æ®;ö.ÍCú QI†°éPZ3w,Iu(p›æ1°†RFõ«e ÀÇYI¢C¡·éô»|Ÿf‚ÔÜËtn¾oYð/Ó™^QɼLOó2] ²â_¦;½¢Ë@¤úœhžŽ–®¨úœ>î^ò²^ºçý‹ ‹ÏÕ€ýuûÖCS²ù”êvqT7”ë*l{Ò˜óóÜvßó• ë w¹].^Ã2þþ|ÿÜ)Òo{1+î×±âZz¢9'Œ†¯…ŠOݯcÐÍôæç’ó~Æ£Cm7ˆâ)3>UöíWŸï‘‚oðûGfyrÄ ~‰C'D„ïee&-·µsd–¦5ãkW¼× 1ò“ úËd‹¶}¸ö"±çÆTT™•¬QÚ@ŒÒdV%“¥g˜?dV§â‘ÌFæÙ‡{޳T°-·ïÛ—·*,b.É>ͳó?~ÍWkÂ:z!Ì" kV íF™§ òFó4á ÉEB®o‰ï EJÆ´´_Aœà*žŽƒ$"µDœ­Ð®W&B'’N#sÍT;ì܉Ói$¢ªÐtƒ$é4ÉÐÝp:C&ÒiÚ‰ 5“=‚ü€$ë굉»Ì÷>Ã%ˆ\“ S‡79¯Ò!žP¬—9—³4ìÆsm¿d4giØüÜÇTѸÏÙæ,ÎSÇ[ƒƒ5~£¿Î†x®cxîUªágU}YE[YÄ"Yæu²ÆO–(³ûÇR‹dé/;5-´ˆ¤ÈÓ40ÿ•1¢ rp_¡&$…`ã’;BE•BrÎA£­/~s*b'qsÈû2¿Ú;AÂêj_Óß[OR7£ÝD!¯.$Ñw¶—éçB¤ùÑÞ=5íÖ=À É!uÄ·Èþú#ø9dÄc¨µC¯à1äà1di¶s¾Ÿ§Ùœÿ> 2æõn[NßÁcÈ!ë8¡üç;x ù;ŸÅû9fÝõôDcCÑy y¨`Êl!£Ü@u"´3%f>kB[8´Ö„Y&½ÎGà+;d„Ó³g¾ã—ù³+Ìm…_¯#Ñ7o49œ¾Â¯× CËà?ãÏÏ‹S2Q–åu¤bTÁÇBÊ,¡¹mÇ`Ï'e´ãxóŽðAý(ežZ†!~˜”"b@¶;FuÃ9FI)c‚‘I ÈdÄ$îæ¹›Ä€L†ÈÇg«as¶ZV‚„ÁaOzݓLJçú‚MÊ”Ù×W÷þ"È"æežæ÷ <°²ä³VÛŽ «˜V·{`ÑûYÇ<°ºÝk¡wžMP5[_úóŒÙˆT=”3JF )›Jºɱ”:áú‡%Ç2’¢¤)˜ !e‘ Xœ³û H:'º¡©ožÏk¸Oej?eiåAŠ8Y,¤LïSH’8õñ@ÚXHªŒñš´8öš”*€A¼&ågê£óš4Ç$^“’¤>~$ù ¯I‰Lâb«e4}(“[»+ 9RI¦7¸n½ÁãqOa’ã2~ž8!Ç!‹jl²/•úƒV¾t)Ò0’|H¥ÙŽ_GhÐR\öØ‘$©J&Û&ˆâl‰Ri¶íHãl‰Riö–¯‹"°%J}¤I>›|E`;d,ÛJ—P’CF"°Í‘l‡ŒD`o.´(Û!#Øv)‚#°²Ž¥l-$Ûßù,ÆZH¶‡rFxwÐDvxEË¿"°×à $"°GMD`·ôI¹ljÌi‡[¤&‘ªbè%‰Õ$‡~~ÜU¬&qHK ˆšÄ!U”ÉhÇû% :5ŸHðz½à(UÐú߬Ÿ5=æ^Äùï¿®ˆZÿù4Ž©âeL‘:Khƒ0iDꌨ^v횟>í°obü…'oû1c]©<øîS¢+•Z0ºRsL¢+uHWƺR‡TQwFZ`%ŒËO2ÆP©»«ˆ{Ô:²Þ•ÇfÉtአÞi`jlE ì0±°Ì1Ÿã¹Œ)cW4YÚ8˜õ`y¾¡,³” "8È2O"ÁÁ!yýÁ[/â$ô¡+E¹a²L¸RmºRCÊ?(a#O?”^f–`..5\°%äÀ¨X´ à{=ñŒ 8d¢Up8f¼U°l­‚ž ™VΈqÈD«ÞϲH· ÂJ ,øœ«-{0¼Ÿ©€ã©’Ï\æŽ ÙìATÖ/K&nœ»={ž§f²ò¥H– ™Y·ä.YÖ¬2~ ÊxYe)g;Do–UάßùmnY‰ˆ¿š+—›5m?Á3ªÄgkpÛ šc^l·WiÈJ$´Ô7+ñ£HÅxÏ 7YÉA “ê%I椎ã !–ËJ'šIXÃä‚ÏD…­\Uü‘ñE®áÍDEï|U°_ÉDuHW Z+ŒpçË„ÚiB„m‡kbG¶^°7¬>£l`m3O×k?S$¥hAËíççç Ê U•XQÛÖyO‘*¶ç²«‹ãdU§ÒF´V¬3&v#ZÚÖßO’áù9˘µÿâê¤.iÂdÍRåÍ»aö„Q«Ô›Œ(„’¤Sþ)Ù(ùûZ˜Èö?-m‘m.É|a ¡¼‡žÍ÷qê=‘MÖUÂä=6a×SøF@xÔ@£d]'\jpx”CŠø^ÊU–%v¦¸P®þ"3k…ÊR¹Ê[–cGL;Ëv<¢9[¡í¼GŽ"žCx]×îD®.\‘b÷ï“uá€Ä`•©Ïx§Âœ÷“¥=íbPa*äú ø‚YFeïKJ²š!Hù ð{ëe,Ëâ‰Õ*K­Ò7Ë88Ï:­˜ Ï=Ϣݾý‹Ûvgþi;}ôÅ©ýzÁ¦£wì à*ú“jŒÂNBÄñÈ>#ëx´ÀÓ¬Rž.æ¥ ×^ñä’!¯ò:íp»]¼|˜»4õ™ÈçYó-´ÍÔ§û*ÁWt7…ôàWJ䬴Ю¨/_~¯­„HÜÏJqW‚Ëìuc2TN”HÕTí˜ì×K߿ּ5Sq=f«iå&¾ ¢QŠ®=Ón¾;AŠ8Q}óÝéR22Žv¹‰Cª˜SõB¸J©ñ9a¨$Ÿ¦C•|%JÞ±Øn& åU!>Íѱ¸Û‹Ã¯ÒŽÅ°GpȨcñ´9·ô˜Š /Eµt%êTt*"+(™±5ÕMÈ<ùšª’9[SuBfŠŒ‚ßÖT'‚”ŒëùØAMÕ!Õ±µ¿¯?Ç÷ÜÜ=R°^§»{ŒŸÈ(ÓïzÆéyû}¤$k0ç!:=Ûõ1>Ï©bþ©ÖágxÓ_×±õü`ÖŠM3Qdñ{hÏsé†Ói"È2Þ66“áÜ­YŨ~fty4¾ƒãõgœ Až[s›Öoz糃oØ,a½:ÚCsFîbþUƒƒ ¦¸‡‚Ý””2ÀÂ2®¢ÁncX´HùG°Ûá×»Ù¿‰@†…þz"á€L»Y±IÑ- #R¥’¢›`8ª¤âôÛDc¥!©6ávw~½HZ¬…‚¶Jò“,+–ß²díÐBT)»©›YØÁ^IÎòs·K e¥8ËO‹ìÞÁòS)Îòs·Kùy_é1%“¼m-—(R1¿vÓç?ùƒ1ö#ô¥ën1úB‘ŸÑ”˜~àQ3Ë…Ð2Î:"á ›HEÚÐÁvH%c$í S|$Foö ¾#HA ›žâ‰Mßæ'Á¤à‘cs¹Àò&˜HÅ­Ü`šSaë5hÿ…7YÉEuÐb)U2_‡#ì†1YUì]ZÜæS*µõÀY÷JÕéLiàÓ+ýaPdŸ¥{îë×DqEèÿþox‡Ë8Ï |åGrªC IéìhìGrª‡¾Mý‘¼Ÿ¦åMšÛÙCVi”ìù^»c²msu£TrŒg_‡B‡F9À KÌÚT* -a*‹â©,¶Š Ke1¿n…§adÀT–“íóÁ,£?FWþ]7Û¶Ð`UZ&Tp˜&¡ØXªM/‡”KJë”É™UXÁ¯óÛ™Éî¦Â:D— Uá&©Rp6ÌÁÿDE—Zç1¡Bé:1ÎcB…C²ã| T8dÜ€*2ªáîˆÜBÅâžH<¬.Šüx"or¦Š<O6¼EžŽ'HmCoÎ3ð½"Q¾0ïgØô‘©¾µ ÏÓc>ý£PØ”*X ³¼´ßë~]',Öš6è×U¡“%&4k§("[K GE‘ X³¾)ÙØ´Pb* ¦-µ~P[J%»Vˆ|EUZ¾¤Uð³áò€ŽYÿqÌpç?½‰n°Ù·ë:(’Ü«èf[× Énöͺn!È(­t3)[¾2KÅàï½ÌùuÈmm¦ð.•ŸQlðÜÏÃ-´bvÄúŒFG4HÅ;bYêÚŠÞäR%u’¡u¨JÍ¿ó7²^:„Mç÷1¡Ê‚¥Øu öQ%"PY/„Ëõ¼[¶­ïgY%]Ì› ç™°ã°dKa﬈éævѪÊx5>!P©*i»Ž|T%¢«Ê]þGJL•äJLmOKL•dJLÛ1q‰©’\‰ih‰©’\‰Éü:)1[¦C‰iß¡ S°e:”˜ìy’S°e:”˜Ü®'”˜‚-Ó¡Ä´Z5).1[¦C‰É i‰©’\‰©u©CPbª$[b²o¼94Œ‹+îÚœn‘€DaŽJ¬G0ÁR¹Ò©M•YR0|{IJS ¥6˵âê^‡TU&MB>§CÊÛjØÔU+=¦bÌ–pw&Â<ñ/Þ0/_ȘUUsÂlÛ‰FŠJUÕŸ=kÈXÊJòÐŽÒhsÕ–r?®©ˆïûÝm|žã»ûz\ 2ª¨Ìa¿º÷ƒ ‹Ø2¬íw[«‡öñ æ9=¿¿ 2"·¶oòعµCÖ±/iYÚ ·öw>‹;Œ™/i•ºƒrœ8$·öPÁ¸‘!Jžª3Fvk×Xv«êœ‘Ýîî è%©sFv»•ÊñKRçœì¶ˆìÖ!c²[ò†d·yIìZËn2"»Ý*Hvë%¯ï‚s3²Ûí˜Hvëu̶y ²[çYÕVÝzhÎMjËC³õCö]ª‰’”¥ŸÀ¾– b;Ïl…Ó"¢Ê¨-T­#3UªZ%có§ÖéLŒP~¯‹ÄÄîT`®©Ë·ÁÕÃý,?GQ—ž1Å:¤ÌK=m(„"ÆW¤ÔÓ÷t¡ê*Yêiº¶'HÅ<Í•a‹ŒZ䘻ôóóÕP ¬q¢æÁøær–ÐL©é ‚t;› ;~9¤Î²D6ìml€É¯ ßìP2݃Gò*›nk|ø ²&|3ꆰgAû¯Cg‘e°÷w˜ïó{ù…+’ Ïmjt&Ù…e‹[áŠÔGŠÂx2 ²ÈÑûY¾—åR§2î"Fc¾Hyo»íåÜóÛ¯Ft†N쯃=èyYß×õ ¶´ é¬ÍÅ®¯ìXgSÖ–ï© çY~Xë¹-ÀÐôÝòü~S¤"Èmú°†yS?>û7Ak½XëÖî¹|än­÷Ï¿Û;ïùäÓó§»BªCîÖzïÿnW´óíýþŒ§‰žgå‘_›µ¹£w+äün¾ïEÖ€4÷ó¾É)¿ûf¯?¿wz?½3ë¿t6èízyöôDó°=Ý\‘ï5ÿ\^§æw>@‚^/×ݹìçþ4kÖ=Õ\¢M²3 ´/Êë«o^O Öÿ{¶ã¦$nÖçpnºÃei€Z÷{ç¾ÿÛ¼–çÚ=(´ð”»Æu;ס¿½§þr÷+'ÝÝÿÿcŸÿí¼›EšË2ƒÉÏw;QhÐÝq{¥Íæ³y‡‡•×z:ƒµc?}/ÍüšèQE svÏÄæÕž^ßý‰BsÝ}|§ßûý÷úã—ÄÜŸж—v½ ïÃe‰ æ>û$cs®cßÌ¿§TA¨Âéâ£ú¹{ü†Í¥‡jm÷6L7-çæ¾\.ß Q öͺoYLæÜæyX®ôi‰AÛûv²:<æ¡»εBл9®9]ó¼¾QÔ2c·=ûyù™—¥ë_Ìô¾9UèxëûÛ< 9@w¾Á6^ü¬ï¯Û´Ð±R Ý×›jnîa”z:m(+à¦aþ]!{ÄCU€nsôömýÞ×áÚŽªôê,Ìg8Ï×á´tZ ¨[¢è0,ÃÐÓG K½ÛU¼=×f6‹‰ùð$<-ÛƒÝmÍKؿ߷õq8j y¶Néü¹Í ôu‚ôT? d(ÚÃÝ3÷O·Ûm¥7Kå>†jÛÇ}ë_ÏéL¡;l Ç>º}›™úö2ã…îOëß}|m·µ—y ›aÚëª<ÔÜvŸ^ì迾z”§“ÓmOë5Ø<`ú´Ôþ´þýw¿YÛa ííõ:«ýiý÷ÿö›å3K¾-)n:ܬÊ;5Ø–‹ÛIÍí«ë›ö0×»#ëæ»nÍ[÷ùu}Ü®óaÞÒ™‡:Gñ»½¶.ñX¿èQu™%ö¨·} ºÌ¯×Ï2Ž*<ôk³,v›óúë÷$”}6¾î7ë5O?_¿×KOß,½=­Ç;joî÷Ÿ¯ûá¨zÏjßîÀõâïÀÏù~=ßèÓÒ{üV<ól&«á¸›oò0mèíiýûyZ—“Ï¢ÍÌ9ü¾¾GÝžÖ¿v×}¾Z'ØÂ>­÷ÿÙØ®ƒšZÿÝÏg:mAͤá Çwß¡*Ò•·ž…˧tV¥ÄNHô¢³êØ3¸º ­Ý¤šEó ϪN *l–›Gæ±:ÎÍOßÖ3Üߨ™oB¼¬PŽ™§Òš¸¬±ëª3èñ¦ýóÇ|¾àâ ã°³âÛ™ Õg)¡ÝK ”Dʱۖ` ‚¼uÍVš±w¾{ŸVÏñ¼¤dÜʛڴŒAÏ&s-à®§QŒrH¦€®üØ4žÛ­QŒò§9kßM·ùFš6qÁru~˜1… ‹OǾ ùÕ Þ±O£å÷?{÷ÎóÕŽïõ—³âŒTçKûKuÔHõ¾utw>‹û£Ú|Í{G¡9ï:Ž*x% M²L¥‡#ЉNÚ¨‘ ¨ÃšÍqÞva9$¤_Ù¨‘ÖmÚͦy:ÿ@9å8‡¨‘½ÂbÅ÷å¹d(Ýw»À-ì£yMíóðë:î3Þ–PäC9λàíºoköc.÷õ—~³¸‡‚\[ Ò½[zžUتmõ­úf¾ $eqÈ}¯ºlû”ýDw$JN÷w>û´´±if_íü:\|%VM›SÍñy Fûa¦&xT–Ò~4h%´ ¾zÙåñC¿ôo3¼{‚Ü^’åŸíF]÷5ôv½‡¶ rrý\Wã–’Fú‡cêBGZJZ‰?ZJ°¾RXl†mvvûòwI²y‹õ|="Oý$iÖóuóÔ·+±ž 9k‹Ú*J±)M±X ¦†<_#÷³€Mè’áÅZ¥2=¦Âåú³ç´Ù>"pÚ´Ò)N[X¤Z‰$œ™.i¢Óø4uöçaCEÊ8r~¬ ^ÓA§a'ÏÍ•_öÉæ¼Œçeæ–S{¤=äeûäŸãô4/çîR°‘:2h›áúlçYÆ‘—¹vzž£äAÄ&­Ê”AbákU¥ô9¶ÑW”¨c3‚ÎÓܰÙpÃ^2èIíI«ñ[n=¬ƒžÄç_ܵϭEšñÞ#ÑößÿYÓºë+eÖlmcN³õùO¯ Xûà›j¢¾ ²óå¶©ì)ÓÆ¬ÀrÖZ¦ŒYoŽà1cÖ“—f¤HÅd}¬!ÙT§Ô[»vZ§ˆ Ͱ†gT¤ô¢6d H0ƒÛbvÍd‹7ïw Q:‰ÆètHÑ¡uÁèEGƒ[9”C²zÑkØqë"¥µF¢ÉêE×ÐfÐÈ Žzf·ñÌÖšó̶¹FØ3[kÎ3Ûg¶CÊØ |!žÙ©bÌÔ…xf;dÌ3Û|CØ3Û!‹Ø | žÙñÌÞ² ‘g¶CF<³íX‡=³²ŽEm Ä3Ûßù,.»ÁžÙš3™àˆ}å¡ Ïìq¦Ð„gvKïiÊ3ûxÔ„göz¸¬‚ Ç/­«t8vNµJ‘‡@ÔºþËu #H‘p2 RòþÍ“ çOðò¸Cê„?ÁLïOK1Ø©‚¯@wÈŠ%H¾=AÒ!kÖÉ`ð4sç3†KÙ.¥‡æŒëeÜÒ«ß÷*1ÛƒpÒ=T&lèõ犷=èék’ë¸9–é"KEÛ"Ù®.x¹Ìb}=ÁÝG"!Ûm¸D¨ˆæ¦±ÛÅ{ö,™Æ‚ŒûzNÖ׳£ÇT¬Ûqx÷ ™t;nË©‘Ósx÷n{GѬn§”ÆÓ³G¶¾ˆöl—é ï3rzÙîÕ•rÌšÂÔXDrvv!rkýi9³à]™OôÛæs HㇺÍ'=¦Œk;¶ÍgO\+±ÃB¼ÌØn·1ëàë`EoNn*h¥H‹ïGØ•âƒíë}gû~½Mðn°èÍ7Ÿ\ÜI7|Ð|*%¹ŸÛw´¹÷Y§Î—eí/É´”N jd–’eûnÂÙ5\‘Jèol’6ÌòØgú3Ž guÊgz¶F{áÎéÚeØ$#ŸéHírù µKä3j—æ’\íò… ä3­]Þ¿®™Šä2ÝWTŠävž[E²kBEùLïì•óe¯±îµËfzwYq6e]î‡_×A¾p³Û­‚Ñš¥À÷ÏÒdmê´o³ø>üºÛÑüãØwØÑ´Ó{"ÈŠkÿwù)Þb;šV¼Ev4Mˆ/°â-º£©»ÈJŽÜÓîäè½ßsöOn~’¯¡Äç"°ôÎg¿VŸNëd¬CÖ8ôGÏÐíì÷±¤øtÿÚ¥«=p‚‹œsÿÚVஂŒ¸Ùø¹/žQ°üòuã26ë©ë¿.Ò‰ÆàtXä’q:ÜXeÈé°ÀürâthÄéÐ!%—’œRq)ÉÁéÐ!#N‡ö­ÃN‡s:l{âtè%›¼>ºœŽBi@‘«Tq ëÀ"×éBÓÐvÉšg¥È‹?¢Ú´ ψ­K4!¢­ÄaoÜzìZ •¶‘ á·¥P¼D£8¤Œ7)pø­Cª„C0ÚÍ•¢8fˆ£ Ú/3Ô‡³—Ìž÷eƒDz‚ v»ia´ |ý·&ÚeùùjÃ2ŒÄDêëψs%´ý!?…æuP;*E`·»Ê(ÊCÁ1ø"ìÍRÄÛ—8œ¤”9ß¾ W âá$Àä+CXA"œ®„üçà÷Œie:¬À;Éu)wº‘ eÚsÎÓJVðî9h%+ˆ{ÎÍY¦=çàëÀaïžsˆ6P¢°‚mÀüNL(QXAÔh%+8útu„6Pâ°‚ˆ“¢ ”8¬ feh*+;zýQÚÀne´-JªÑni=T&C«bðSJÅÇ’‡U“TÉЪD —R±±ä!R¸DJ•7}©¥ß0×È‚ è þ‘¥,?„€Ípö*]Õ'‘ƒ¥L;w³xÎpvf—dÁr¯D†#»ýÕí8yv{)ë$¹Â yˆ¿["aC 9¶ámFd¡¨¥\{„¯óÈR«$Éﱡ\ªœ[ލ,£c­Ô#ä§D¢&ÑZ]Iž`v²Jñˆ*“ìö`Їc¦¶²M©RÝœZ*nŸÒYX¸v–Ýn¦ùÎŽV#Èpµ:‘’ s†™3¼IèßÞÅûµõÈ:(ýþÝ|. ©8ÛÜpÌ:Ýâ·ú½ð~¾'_ðá» «FØ vw_Î'¨Êyº›3~ßß¿ô˜2Q/6ï§ç;d\¿gÆø–e!x–sX[âP“ ÊÉk:·=¼ÉÁ‰ßKWïúåev W—‚?xÝí”l‘Kÿóûœ(Yêìy릾ýžé•¾ÄGW÷ñ¾´>RØ!+ï:²>8•Ùp^ûñ—^‘~ׂZ6¶Õ‚îRM²!Þgxë dToï鎖ŒEXcxkŠÍxçÑšûÔMëøMéÎÊ‘¼ƒ‰¸‡ÊËÛÊ{P•¶q€ex!Ó±¨. ŽM†-ªR$ØŽH`[&éýë^<§Å²`Š(Ö%lJL\§"ˆq°"ˆ3 ·Eʼn &´í.ª„b3=˜Ïãá˜é°Š5üN},…nf'Ξ{@¥Ð¢æ„ÿ+êÄØ£aye3‘:‚ïÄ–v'¶„!§Ì?HÚ¡§‘䙺QX¶àxOppd„©}<Ÿ7˜äKÉf³éz‚‘Ö½½ó¨u_¦ƒ 7äRÄ×ê¸!ï2‘IòR%-AÂR¨üJ"’Ä0¼•šFTH@üÍHq÷§ï_A†ÎÏuëülwþÒŸ¦=M,ë~ßÊ£euY±[ùáé`:$ãrY‘ÍDZ`Ü„¥P™V $i¾,ë±á˜|r*~“ëIóáÛ¤4Ç…”UÚ±t ¼ò²ÊÓÜU»ÅòJ° }(…ž)”-„ò˜‡þÆùJ²¥å@Ñ*+&Ü‹P´ÊJ¥ìÌru³?òwqBÅàæÆOsE-<#Ä HŸ×»6s˜ãœP;Ë´›ièºLcÛßCCsBÿ±üÍ«Ÿeúö¯yÍ¡•„8¡Öß3 Ûùñ¼ö÷gKgä¸ëþØÛÇ—m¼˜«oé1ËÀ/Ø«Wæïí÷ïÞý´'zE•!³ËÀý~ý}æŸïðÖNè.Y½9{Íßör¹ Cw@Ö`Óf~¦›7—ïßuz]÷s_ˆQÑWÿ|~Ý ”Ôy†nóö}3à3÷éÖ6«]?ŽºïΗÿÛšÒmëè¶×lM*‘Kšû’¿ÌÚîïv \Eº@ûœ¶u3ƒÃùÕ@±/ïþq÷§16v‰÷¢ïIî”Ö\óìüÌÌç´Ì/³r8ü€]¸]ÖÙ¯1æa|<Í»õ PØ}ÚF¼*LFΞ: çOÓ[–=u’"Eœ±åÿÁЇ€™u¨JêŒ7³¨Î+‹‹Øž¾m¥·¡ó1á)ɾßÛ÷›Ù{8wg‚T1ñÇò|d;$Õ0Þœ*“HOrï£þó¯c6yjÏß|š&zíUÚt{¤g×ÄåÕ­Cæe‰òW óÒ/ræév ý^qrƒžÒ· }_2árc6mO‘*!ZCöL©“ÙÖ!Ï·R‹w–[ˆš·ÎÊ›á˜2Â2ð.v_?}è>iù^Úõ°f‰eVàÀû+µdxÓw$)IN 5òˆ‘w©c#޼K­˜N¦-KÁହ…hÓ ¾J`dÛbl:h‡ŒÔ8»M@Ö†}¿.Ðs9ÀD‰T K¬©/5“yy·î)°tÑh›öïFAòŽI_íõ÷gü Ï(ôè"gt‹œpvMÞyºÄšÍ´ Õ]'²‘öMMÈâ-ëTŠÒÎ\ÆÈœ‹7À‹ÛZ|xîðmÖ"ùܧ]8ØdR8çR%ëúa PKNlÛ*~9Ts_–Ä•5+‰Ã=äšë?Ø}l"<ßpð·:Üù÷(çIm?ó}øé26Òšs“‘–ÐBß3×°9Ä0“,ÛPF¨k6ɲ œ‘ºNrðmIjºeEÂÞjÛVV0xdΦJ‡7¤ÊŸ* ý±*Éêò@d¢…=Ê’dSaZ(I²Ù< Q’M•©„H}ÓI $‡Œ%ÙŒI²qÈX’ÍØ‘$‡LÅ¡$‡,c¾g I²qÈ*íºÐvI²Ùމ’l²Ž¤-$ÉÆßù¤—BH²ñÐ<‘ˆ¼<4ÑÙ–ÊpÔ"©—6òW@–¬¨"äTY™òØiKyª¬JÕDÊSei‰Œ]20ÔW™æL&­èŽY3YC»¶}O"ª*¶ òÕª<ã«‘@„©òœ'Â@ ·:ØGÚì€lbÜïäÀU.?$Æù)©BÎõ¬úU•§U° ixVyÁFT†æy•§mslc6ŽVyõ!¼ÖõU^%Ãk­¦!XñT˜œxhÐu{ƒ®½N6躽A7d´A×í :zL;]­=¦z}ßúà Bß+Bxü/‘Èì¡ï~©\Â#1رȶ{œ®)ßãá¯.®=ñð.¾#¶œï‚ÅŽ6pÌœs¤@íÖ ÿF,—ØìW‚Ií"vs•H7äb7W‰tC~ vs•PŒ,¶›«„JÖW7=Gm‘ðdã¼IŠ‘Ul%J&h¶i%¶ÂDBjã<ÖÆùµv)ãa«]Ó€¼Ò!U„ðh6û˜ðX ŽŒŒ &'ˆíü…I2M«Yî£ë† E¬O1\¯C‡”‰Ü,rí:=nGZóÚ…³§¶]öMn͵ÃX'³÷b”3Ôê =°’ù'CÝŽ cÒ;¤L[ïÎ#Aª´õ.ÌgפŠÉD†]&â×"Ež”žLÄ@¢*òÈZÝ•ø6AÉß“ eLPÒ=Ûõ%¦¯%1ºpÈ"&(Y6AÉD‘e"K¾ ‚‡¬âV±ëj¦£• u"£ýúÓt3AÖ©Œö ”þÎgñèõMù1PhžŒ^a­‡ÆõÜÄź Œà„‹5L…à\pV³Ë—où 8ïïéˆb–Ù2LAŠ”¿}ˆß®Rè@â·R¼—ì£Çüî ÓGIùh3ËDüîª(å#[Æüîª(壭´ŒøÝUQ&(vŠÇ1UQ1Ú “Q!òj4¨"-y•òúÇy ùU ¯ØÐÃΆ`° ®Ëïú9Q×åÃrqØU×åÃrqØ–SK‘Q×厸4U…N¹4mœ–àÒT:U64“áõñµ~Q¤LB×f ¸æyý#lù ŽF8ÚÍÔBl6ì²ÁĦïób]z 2Þi½Oí ™YU°>¨ŠÍ6áwx­Ýáw)Z—ËÁhC¼¤éÇnãêeÎvG°tÈD;ƒ4SJÁÙ袰›ª”ÇÂÝF“,!{Wî‡Cvfi ¤²8&LÝî®ÏÛÛÅÀ°úg¼ºàý·YV| À9Üyžf„2E€o=žSÅóA¾~®§ð45ÓP¸[–NG‰†Â´¢ oY3øÅnúü﬘FÒ¹±#¸ÿûN0¾ v¬£È©ÞLÛ¡ÝÆQgçÍEÀ_Q%ù‘’«@ÙÕŒ¡¿_U2á"0î.Ýáì*_®H}ȯ9 ™üx“+ÅçׄM_¥Ž šàƒò\§û}kSü;o•͉y«8¤Heâ;j‡”©Lœ$½©¢Ž)ÄÅ!‹dzÎk W÷V!.,Y¥svFŠt3ì¿xÛXy˲ø¶*SḻەÇð;«´òز1Êy©ROˆMy<õÀœtH™˜Ì…·îÝåîæêÚV¡þÂ]BãÒaƒfVv2ä>~ZÑÇucWo5·Ó²0è1%X^m@Ë/ýj§?ó¿ö~"HÐØ\pýÞkœ1BAfGj·%7o;k£e–u¡Õ¸#µûîâÝ-r:-óu È V”äÖKíd^¥Ú;R#oZêlËÄÓüø½d‘ÎáÞ}žÃºÎÝy‚n‰Í6¯|‡ŽA.㚨=¦¿¦Óýg>BE¨!XR?@çe^Ðý9ýÏ~K÷ëcKà»­tôzµš¢%6!´¶ªj&îÛV:‹…®xMÃúZžÌ#Æ%¾ïD:ÒØô:?Ø|W×wùëÛù|n¾`£ÃޝÜ]ºþÌ//Ù¬°5ð±ÝØöŒ 2\‘HÕ„ì6ÚþŠ… S[ %á*ª!6Ó•–¬>&ØLW°µ™_á~"1B`´‹lœ]aòa)´ãìŠÐÿ»OÈ.C¥ÿúmï_×o,H}qGºeµY^5·f%HI´wí·yþ9Ÿ»AJ¬róJÄKÿcþ„+*ÑsGüß¶¯f¼ý¤˜÷¡éêãÂÆæqm›3A–¾‹åï¦yìf­hÞäŸó +4„ßÝgn¿oÓÏOø: 40o“’+Û­ëå²ö¿á )šŸ´vïu~][zL¬¹±4è}½<¯æ¡ù¾ 5ãâ¶©Ø:=_¯Ÿ_˜Àt_±Ú—äb÷²ÚOÃïñÈt3,]tÉ2¯}”À#AêKøBt*H}¾qz¥õåðœjÖì-˜gTØ@š†<™I¦3_ÞÝ#kNðb÷“À¼ª“[i+AVUÕs˜¯²뎪IÖٶ廚ªfLÓ­IØ|Õ’ÓÀš‘$\‘L ˆ¦í˜þK®דmFH8d¤Èfa{_7¯VÉ"[לF³W¢ÇTQËÙÙVŠ,âÝ[»ñ„‚C­¸ž¬ù< ÔS+®'kG(R“…ýmï’˜±©Wu‘¶ÙÞÖ¬@YæÙo ûn[Ø2ΰµu‘ˆptñЛã‰ú(v°ª™ õ›üUµfLRG$(¨s|{>P¤L”ãìö|!HÛ|í¶O°å¯köµÊYÕõ‡gt2ùŒBf‘CÆÍmP”ôu–¥íjfëŸÐSd4$¡#! :ãÆ:’ ³<é Ý‘  f3km58¦ä‹–`–é±¢¥Ýr£÷SAÁ‘ùóÛ­?áìE:<ÔŽuð½;dº¿ß­™ìïã<¤J¹‹ö‹>¸\ÜEÚPæÒY™zF6<Ô IL3–—֜)ò.>dý.á¾äß܇ߙg‰‚˜AÚ‚4¼tÎX!ÞqÃË!e‚Qo†Ú‰"?ê<ÿ`[ØR¤ºá›q`è†;¤HÛáùn¸CÊ”^pØpH•TR_Bç’5¡4 ž & JÔŒ…ð2cæCŠ„¸Ï¶3àÚ™*⾯óòƒ³J7dÂ}›µáŠ*.£ ¦h:¯øŒR&b4š ï*f fŸû:­GêäøÙï¦hð;ë´ p“¥Ã&2&uaÀ×.²”@Ø–v»° Ò˜'ÿe{ö#EŠ„bÔkñÖ&¹¿f5úåWéZD’Ü\à†y“û¶oZ‚Q Ûh.¨CJ\6ÜŠÆóØt]7þ>RábÜ.y6»­¦3w¢Ç,€åˆk 3Ú-0z ° ßÖɤåôÝÝæñpíûšvÛœÒæÔ v©ñhÊ©ñ±>Ná¹+¦}¹ŒÁ¦_ õ>ÖùÆÜöØÃsg"é,`×"c›’˜Q£E•d•/„ù£E*:f熅臔1®ø@¢cRÅ%8:Æ!‹W|!Ñ1YÆC¢qtŒCV1Z÷@¢cR§äŠ!:Æ!ë¨\‘DÇø;ŸÅUˆ8:ÆCó´ q:5íô܆×Is™Z(’E‹CŽœ}œ×ݤݬ?aXÂÿ!_¯¾Ìt–àá"9y)QË샆;™¥lÁÌĶ`ZrTXl ¦#bŠ ÌÁ‚-¹òÅÙÆÏ)’n»M8¦dÝvCÑ!c‘¶fÉ‚#m2ik¢Q¤­CF"mÍï$¾"‰´m-•EÚ:d™v>ÓßY¥][zL0’Zƒ$JKÅÇæ„¯#æŒ2 CoNËâÝ®ź6 lÔ²ä} ¦eÅøÞX dx—t²o¾G‡ï¨þu~gyçý`‹)»Z¥äŠ{ˆt ìê@SOPvGŠd(»0uª,áð°=#DZ)’‰C¸¢‚OìÞ‘VE"CÃ%vBñY#Jy,Tª¾™CªˆÀm¤þ÷Z•ŸRì:‚L2ÞL2wçn©ÒywPºQeBàfÏŽnY¦óî¼ÀÍ!+&ïn%ȘÀmìˆÀÍ!#7;†`›¿óY*D/Ü<4O¥è›‡ŠhŒ¸y¨dbôP•ŽÑÐ""ÃÜxžÁÓF«ê½ˆqó”~œª•fÊq¯fDoiÄYųLÍ]§ £rQ·­¸|¯Ï'EЏºÏF×tAÆ Emƒ²2Ú¬eb(0é4žaÆi<ºÈ’fª 1SÕEž4S]ˆ™ªÆÎÙoôwl¦ª±sö1À˜©j"=ÀÒãŸöZ8;cN{ß,R;‚ŒHÍ17é1l¾ ‘’›_9Û¥õ@*i³fºBr6 ÈÙÝ!Eª¬ZxºàrP--V#˜{OR—í§.ëÀ¨¦.Û47‚ŒgÀîé1p?+>Wl«uQ¥ ogœ±£ Íøßã4]è¤ É@,¦5fk¶±˜Ö˜­eØô˜Q†íD,¦uQs ¯³dÍRPȤ.s¦¼9ŽÁéK—y"—oÏÔ:õð~–‚[[ÄD"nSc›ûáwJΘ¥íéR%„¢ve‹…¢º,k\,ÕeÁ±Ê‘ŒZ—%Ó@Ü2áwVlay.«d"â@5¶/>$".$Q—:™ˆ8DD‡L´p"¢CF‰qˌӢt™v·[ˆ»®2®Aƒ’[tõ¶SåÔb)Øá ©Þóš<{ÓÜËû‚A]EŠ«[ys[ÿ·??ð&WÔûqÛ›oemû³´\RÆ™êgû.õ©ÒÙ)á.)>;¥(2ºûXH‚Ÿ®˜&IðÓUz÷1?]¥w IðÓUñ–¾EÈvà˜§1™8æY$vÌÓU™p̳-'옧«’IÅŽyº*ÓJb®«OèýDiÃðÐ<­ª†á‡³«ÄšyüjÌ‚~o…Ûk‡ßY'²§6ÊžÒœ/ÉžÒØ7â²§´ÎØTÀ=¥u–Ð2ìù«Ë+ ódë¶Û´ ¤HøˆŽ]˜µ5—(;XfXO*a°ÖS­¯L Ïûܾ7ûVD«Ð’©`tH•£µüÐ sœVza ŸÐ Ú:‡L'ôޤzoÐìZÚv ¿³ø`Ñ~gºAC…á)ÒÖ/WzL™ØÚÏ}!ÈôŒ*Bºâf¼VÔeCåJk†¸ˆswµ®¹¹¥~é:cÌ:pê—CŠ„ E]hDqŒìãPÔ…ÇxÔØRÆw‘8íMׂËö¼³)] ŽÐÒ†˜q]KNÝf÷›pEêƒí¤ÐØç6–9Öu5—xÜÙ>/ Ë”êvË…ëÏÓÙ#«4I}tÂ[WóÝ®60#î[eÕRäÃú³N¿ŸE>|GuÜÃ.›ØÃ³Î2®Üš¥ç‘9W³Z~ŸgUc÷ÚHÍ*Ð*êL¼¿ #ˆÐ¿«#îµPc!^îu„–ÖÂʯ—2êåÞ/w‡Lå@Ž!'¶ÎÞu…x¥:¿Z@2+Õ-d¤H‘tl†Ê:+¹Ê "T×Y¤ßzÉ|õ©’Ö Hš™ c4*' ùêRÆ5k6y©§H…I×=k`²«@êpÈÂç­íT —ˆqY&Û6&È“:Ül8·¿ÃÙl‹'‚¬R¦a¡Zgõ‡´_Õ9ŸWvÐu5iqÒ€±Y¡ÎPçŸB¯F8»à»ð`7Tç"9~nyõS8æ»ÿøØçÁ«/ë\1•çëøõl‚LVžG ^;¤$>È`·´·¥ë2J2v’¡îyÁÛpW®&T·£Q!îÊÕy™¨×m´ÉÍÛ#+v=ÿÚä:ל7>Ò&;$1ÒÁkE4ÒbZ(OýZ±{-°V¬‰uí?ÿw\+~¿nô˜ ÃÏÅÚ5S¤ŠÖC6|GN2Òô»,a7Q3¤¸…ÈÀj†7X-rF¾QÄýÓâC¦ Ì"¹ë1ë^ì,Q‹$I{_uáìx6¤ÊèŽ(£k¡RýPKF6ݵ(’6ݱévH‘à“ ÿZ”ÉuÈ@ü7jQ&ûv=ß,Y¥z=æÎ_Û¯õ î|ZCmo|3õ=AFåE‰0«EÍûo„ù]f,y/ä¿ÔSV¨/mù/~\ãtw’ÿÒºüxFR$ò_lÄÞ8wá{—"½‡µ&á@ë­Qº{$…oÖRr»3$+«¥b욱ܠ–EÄÎ÷ë1‡ª–%“Ú9Tµ,¹ô™µyj-S©›4¢àÖØòñMtŠ)¸µÔI›S뿱€X¬NZ>:G&t?Ù€¿&ˆ°jœï}ôYšúu<Ã,Cò½0[Ùï‘:ä{Ç <»v‘™tdÈ”#“yéZŠÔïVuíV[뛇# ÔêMâ¾í{pÞi¹û yMŒ1ÿõÞ8»¸imûa¾ÝR¢ö¶ JÛ1çn^è1ÁÆ‹Û]lü{¾ÀÚFeGFÜFˆÛ÷ØUÃ!Kjwsý8³¦†š€CVÇïýáhçMXQ«,ÁˆóÂUΧµ‡A13¬µ‡ªV‚{çÛP©ƒ)èÑ´¶ÛMk'Š” ù[qu0x‹-(þÒ!“ïüm=3õÎ[Ê=E&ßùÌ`R§Á– æ%.¢çaµFÌK&–{ÝÆq*é¼· xGAÕJq¾Ö*Ňh—TÉG{„õçÁh”†¯MÈõ«UÅÊ3›°7T©ÞÄ^K2½šX}:¡Ü.L°5–ñçvg˜ó¿Qådô½†¡™’òC|¦ýúkc‚”q>ëiÃÇVŸávÊÕ/ÜA¦Wc«Ïhмó…àSœm ‘®HŒ—q}>ýÇ<–·p Ûâƒ1¤Çq" &ºº(¸wGÔ$‚ü:ÒŽX2_éµMgö2øì%ÃÝ„ÀÙºH7´½ nŽY]”L¸Ã륃‡ä[E¨HiÃ^ËÁ<]~–)b†½N44¬f¯ή™°»®®)c,P×CßY'z(«ï¡P¤ˆ± ]e"ÈD¤KƒÈ…uQ'™cÛŠ%ÔmÊŒI³¡PÝ*³$s¬³Ì± V€e–dŽõ[hEGÏ®b^—ñº¬‰;"õºìˆ×eMÜœ=ìué2ÁÙC^—™ˆ5·ÌXQ—âƒýìzJÁxœZûŸçŒýÂá˜qû…Íãôð;ö Öãt¤ggìÂ]¼ýB¨–"½»/†g$“2Ý>ÃÂ1·1¯r×ÎJSǨX—åæX¸öò½b»H‘S—Ur¤HDN9Q‡‘v"9uY%GÚDäÔØÁòè´¹ÕõëŒ÷é±n ýâºLué×ez¬[H¿¸.û’×\31ñÉkvÈ”''®äcF‘úîœÒ±_[ =ÓMcr½\ÀÿlK,°¢®D:0în‰N°G Ü-Òe³Gˆ^WŠ©bfx]1ïmý ;èªàô_HáRW|½Õ¬ªôŠzÚVP9©*®†{‘UºrÒ[)ŽYs« 5(°j1ÝêÅêÕ:ãÂ-ï×ßO'­ôºv@Œ¬Z³«æaÂè­9‡Ul1Tk™tHüG­c=ã?j­>¬¨¯€,Øuˆ²¬±ýYT§+UÍ(ÚlÍžfÅúж`Xëom‹§±üŠŒÝ´»íp8{\)f9ã ÏHsé±È8¨Öur9»•šØjL½£µ®ÙDZÄ·©?Äòç›óFÙVKo¾¢éÕ¤H3I` ÙÊ\«ÍÄ.¸u-S.¸cG\pë:§²\‡”©¨¾à‚ëÜMƒ„\p²H†ú ®CÆ\pÇC½®– \ÿ7R¤Žq bT¾Ígf'+l–EvR²íÃNª.[ÛƒµMÍVcšlÊ2¥.Ѫ²®#&%ÓSd<Ǿ!`-U×oqŸð~î.Í§Ž }?ï›êм!§þÔÓcÊx$«yëN=fô­ë6?‹"‹DˆO׿`«uò­¬yM?Sd—zÄ«tÈÝÀñ?ÿ·Û2nÏý²|?mÑ,Œ6ÈY÷_{Ì»ëíþÎßíý5„ÕoœucKjäâW×5ÓÂÁ.~uýfp)q?TdY–)1ã6)ñÈXrU;áM‚Aæi÷Æ-¹Ê-Y<2æle6 [r=f‚À´%WÑcªø`‡lî R0I`ÈæÞ#EŠX Ë ƒLgïMæ¨lê-—”¦‹}Ã|º˜/ézäJ⟻¹«¯ŽY2b6KŠo‚Q©§¥¼´á.UDMáij¦DM÷}³$Ä1ÜÏš!Ø(‚Å3’TlîC¦A¾ ܯžÆ½ ÐððȸÇå<¶`‚#VÚ³ûw)—ì@oÖª)Ϊ¡héÖò–&î¸ ²àœí2®½dÜs¶eúD .3Ôú…AVü&¡…1$×LÑ É=2µIÙÆY'²mÙe{¤ˆ…,8ÛØ#ebã²=R%¨x#¤ß‰Ld<o„cŠœukmÛ™"EÒŸ.|ï,â?‹·»ɵٺ ©2È÷÷³uf+ –vd‘ ØY$’v{¤H”c‚´Û##òæ-Q;H»=R%½wÃX'JÖ{‚OÏšéÅ[Ö=TZ8#*Kí Œ:ã³£BW´æ»¢¨ÆUçlؤH/•-±8ìâkÉ,íˆGÆõÌ×~ù{ôáÚ#ë¶XR‚ K `fœÍ}Óa× KÞöîz@ŠDFw ¦fY1½xÂç©5Cí%|Bb{£žƒ'ƒ¬Yê9|ñ騵9/0.#¬ÿþç›z½úîzû×¼fà_;ä^ùç_„´¥óŸÏ–ž]A4Ìu_4´ß¶ßLÿZz̽(òóäÍl¸7mUÀ¶ùZ‚,ƒmé>q¶çí÷ïÞý´'zE•ç 4ç›“Ï ý}žæŸok%ÚüknýÕÜú«}I~ÛËå2 ˹?Ï-aÖ?¤¯åùüº¿.-Eºç¹}Èþô­™8×{=ܦ½(²Cï·~bU³Ú­7½¦|¯Y.æÕ»^¶ûtßòí}šèÊ¥‡Ú£¶­³mm-E¨=@‘ÓÒÕm¤ŸKóxþtÏãeÞâÀŒO-˜C.ÓðZþf unÿ¸Gµ»Á6VÕùš(ÔÙ!ü»Õ… fÔi§þð¶‡õ¿í²Î×ÝË@ÇÇŸ¹g ­)tû  ´yþý5 }û³ÔŽQÛQÍpñ Ð#÷ê±ï«¶˜x°\³i@øì‘‘dívOÖÎAÊDói:Ø)Ê:i?`Óu‘«Œ ¾A¦ë)ÒÖ‹pv•Þ- ófãé¯Hñ‚ø†¹JÅ­º€ `ç ›¬Ãq«‹[Ý‚4!nÕ#cq«–ãâV=2·j΋ãV=2·jî<Ž[õÈ2„q¦¿³Ja´ô˜:íÑ@M.W*ÐcEר՜«‚©O,ÖFΞ4‡ß *ÁÞ «ˆàÝÙ Y®4Ó¤Â:³\étÕö¾­îý8ø\oköá²µ;‚QU%ñ-ðÜ‹ìCZ·çoæEÎ&€þf^äÉ€‰†x¤Œ§P#ÃT±èÃècòB$ ¨¢É ‘4 ˆ>&'±z‡ø?¢É‹Ïth‡ƒ”lÅÚ|píŠkJÛ<8{ÁFàÙe&AFC+ö¸:m ÆNgÂÙ¼(™ØdëgU‚8°iUq /4ÃHÅļH×¶§Ã1kưÙªx¤HXœÙÇߥ2­H눶2/?i+ȸÜÞîûÕž—‚gµ¹#GV[#ñj×BûÎfú>/ëÏX÷ýw»ïïé1UŒÿÞÙÄK` ç%ÖÜ`åÁƹ›o@mÜ.ù"ð<2n&I”²yI¿£Ý¾ÕÅ«µVî|‘¶gÿÚìÙá.±µ[ÃZ2DÞoá.’`|uã«§Ç”ñamú0#úϾ1û…öjGÅçø}m‡i}< RD-L/ÓÍÈ–*nΞ¶¦_pô¡AÖlIÛìÍÚ=a5s^å¼ê:¬*+Áu;W´C&NQ%bë*É2åÁÉ ?įPG©Ø€x«< ÈTÏmmCŇÐí[·º~¸Kc)ƒe RP߆+ªY#£ ¾uH‘ fjI®Ù`¦`hã‘ÉNop/Èuºß¸›MÁ\¬9«@[#€•*"ËDÒ§~€ñ3evÂõr“±ëyXÂ:9I–q6ò¡Þ¢c½öÇV¼à˜E2Îf 'z…³—|8QèTè2ñ~®ûÙ“ë*ê7¢°'ƒÔzn_p̚빫L­Xðj­ÎX›¯&t;ë<­²²Á #|qud¥êãB!4¯%÷4m‹*ýÛ†ô#-³em{Qm;bûCCÓà IÚþ8}zòºLGß­µŒ!ˆq %Ž™éºS¸¢Š£%ÞÇP娫-q‹6žf`ß8dR±·†÷³Ö,u_N¸ŽÿîjŒ½Y_œÏ?îÚE–qö×Mï’Œ XƒA5Ì.¬¾ý»$0câ°¶lôLïË»"Ìü>"n…ȘÀ8¢MY:Hh ”v‘)f‡)í™ÜÇJ»CFƒ„BiwHEv ZÃzw‘vÐcG"µƒŠs‡”‡n§›eì¤=©âÝN³9l|OÃ! ª Ú ‹æì·Î¬ïYRæhýçŸks%ÈêÈQrÈS3xmŸCêý+ÞÞù}Û±;ýt§ŸAÖ ûéÔ½~èßõîÿìM¸øßv¼¯ô‡;þɯ_f-þG¡XïnéŽûøZÇî>¥"¢w'•ŽÇªâ/é| Z¼Ûeok6¤˜Y1yóȱ¹^§Ž EÜäÍŒŒÓ• eRù=.©’:È¿0’”ÄkÄ­ßý˼UYEBÒ‘"íŽY%çvÍömîþ/=f"Æt›ºé1ãAáÛì}2rt7¨÷Ü)âHÛCîáÕ¬9jêF‘g|òè9s…ˆЮÀ±Pä"¡ܘ H (r‘ÐîUРtÈD¬6Ö:¤Jê5a7'rùa77Sd"¬ðéÈv‡ŠhǬmAŠ”4'ÐêE^p•ÿŒeeò¹/8Ë##Jn;ˆ`%·È+æ˜XÉí"V‹³ ˜P7Ç©Cds¶Šyèe<kÃÒ…Â3Ò©^FÛÛ^Æpž 2ÒËØâo¦ÐËpÈH/cS"öçþ<dùÞíZ÷nô2²J„P£:¤Cê fØX0°Èk΋ Y„Hï>"h"çêÁ`Ù ZWÿãX.4d´ì’ÖÏ2B¾3þ@qŽbµ 2«½àXmŒÆj8VÛ#Œ?«í‘*±aðúþÎ^°ñ7#ìâ…(9ϼ5pÿ…`ìIí„°†ß©¹Šz|Îö¦‚õ*¸C¯ŒŸ¢föÑVºæ« Bf‰§¹×`OP‹w¨ã®³ñË™ØïcÉ 8¸Cá¨ÙÇÛ¤LÄÛí~–oç‘‘x;«âí<21¡x;L @ƒû‹`=rlÛVR¥ƒÂ7_®Î^|ðåZz‚ o*äI 0÷ê°\ˆ'eR¨º¹¨ŽáÎ3±KcépvͨX~B¤¸A2í»†ÆSeœçhèâ@½ý + V—€ïuörÉžÔ%„’l]"øÛ‰ÐÙ“K¤.!”dúŒX&+”Jú ÏË8šA¨"Y¹²>‘SëzëþGÆ»“Ì(F)ŒÛd¥ÇLªβP%·úE}F¡ªˆŠ÷šý¨m ¥Ù@ÞሉN_äõH™ˆ®hÑÌ¥t"ÃÙã£÷³þêíI:ûÑPï… ¹Pï Ó¡Þàp&B|X$Ô{ ¡Þ™ õž|¡Gr¡Þ=AV‰xzó¶È9&²UBR¤»ð«ø…w¾œ#/— •бapË(¢DQ0l^i×4;~ŽÐE:J~‹cƒ(*>Ž T€¢¨GÞn ½uA:ûÄýÅŒ4ØýE5ËäiFÏjeÆòÊÇ0*–9èƒ|LE)X÷ñÐs¥àâ,mŽ)‰0檋R&£;×bŠÝE†Ž¤(72¢8‡Ð%ä„<Ú ²d´hÈ£Ý#EÊÛŒpÌd¸³ C*+Q&Ã7Wª ²¥fB½íM ×^'+êÓfSó{YsÊ-¼¶©²d¬ö@lD•ÐcÁïLv·ëpçD%“u•h*ì²Ò¨D‰ˆ7Äéà!g¥{X<³Ò´¨˜ÈfÑnÕ‡)X'cÓˆ÷ˆÌ1xâŠJ¿Þ7¯Vì×û4Án·ª6-íJB?=R•À¦k´R¬ktÈD/غ,ô˜*mwï’Îø(¥°Ñ9¥ø95tY?GhÁ¬ë°R`#Šƒ#¬]×½ÂþH«tµÐæË…¹C«DTâºG%ö¯… e\ë3Ûùh H«œ¸½6œ½`ÞÏm¯=¤ˆîLglM$4ãO?“ý¦.“Á¬ýîy ¿³b}µÇF0]¥GZ§nŒ×)áìš@ÔŠ{¯-¨H"jE‹ÄjEQg µâÞà jE‡”ñ9«R½¯훼6ýsq` D›YZ )Òña°7¬Yë—æ‘Qž°­˜A ¹AJ>6® ×®ØØ¸àî j•Œ–6OsmÃ.².¸P0¼çªK>:-|›5ÇVµ^0~ÖÕ»}”ó)ïh]±Öœ!òWuÍb=|uý!,Û¯ieÆøûž·ˆÌÉ#óôhc9TÀ—¬¿‚µSô«5™1ëƒêÇ™¥âúY kZ‡L9+¿VXÓ:¤J²˜`\’™äYL ž—™|ëŒx¥{·Õ*ø*Q«Üý){xçe¦µJ;ËŒ]7¼‚LøhÞͪ¶£È¸¾ÆšB¡+*ØhÔPW”„«€ë!ù»1`á )9#4ômÊ,9ËlÞa×#³ŠwˆéÛ\%×ÞažÈŒÓÛHÇ ®½N×q佇>ì[ä=Ì\2ÏÒºp»†¡Ì™©³û‘Aæ\H:îÊ\&Ç¥…pãeÎí"1ß^âN軽2W“yÁö"ÃÎTæ%gRˆ4;2GÌçÝ2ÍìeœeÚÐ"Ë4™ë»ž+ kv×q–uÔîÆÇåá#Þ„Ã|6k†ð&‹,åaö°XÙ$7zw¨{%…ø 5_àì2Ík%ÌR|  ¿S1úëÊs‡(XýDyzd:Ês ×^|ˆò\é1U$ámv<@–Ivå°%¼yŽ´D™6‡„·qØÞVzLWÏ›ƒ‚O‰CªtÆÂ<ÍŠËX° ØŽ Ó~k¸"ò›?˜hJQ3_ñ‚x×’ô"cI> N¦“jö$ X{KœTËÁ¯h)Ù<ä-qRÍ{ñZ%ëî0#w)er·³Âü:Œñ¸Upà’uifp‘²àô‰ˆ{ e™T\ZõÙÚÂü.?Õë¾àìl½1´¥ÔÉd¿…(.¥¬™q +.¥¬¹;ò‘dºÃhwú(I¾ë‘i–0oªœO³„î€CŠ˜?zG*äò­AÒlpÌ®A&cvmž JÈ‘Š–1»)S©q³ë‘*š{CÒl¤JÅìº|¹×@¯(žC²t¤JÅìú$º‘"u|U‰ù62Ò]Å}ÃÈXª`•bÁQâîjlÖŸªLsÌì@ÞäŠÑ¼àD9dÄgÔ¾!¿Ë}öý8‡”‰¾axé©¢õ䑬ë*ÆÈœèeUp>y(~DV|–Îïë¥êS–ìa«¤Ã«uRlC …¬Òº‰~»K°ª¬ô‡Ìdx땱õ^î2ô7ßÝ®g3%Áµ#Kþ·=×ýç\2•w„ôÈR3›Ã+|›Z0ãÒ`vð.%;¡¶¢»M]ð;™@Û ma¬KvB-Ÿö:ô¡zî„n<Õz(R«tzÂR©¹¸ ¬Ö—šQÁÛ1$Ô‚ØN¨u;:˜fYÜcP¬H]³ž@!ØMw¾Œ_©“ޤæì_ ô;´~ ØÇ¥ßyì^Ëåòš2’€÷5ôÍýÚ_ï=A*ÿ·d¹ßÞLÆ·v¼Ñ³»<³JßVÔö˜—¥3tþ‚UºÞwÿ±kÚËf¨çŽy»­·äwÈ*8Êùc>ûéwZÌ"]Þnó¿_‘YO÷—¿ÇÏBç°gúÝ|lÂø}æPSÕÈûÎBÏ»ùÝv›†¯~6—4PhP¸¦§9ÞyøCoò¾ûÇܨæì…oæ§¾n¿áxÔí9ýó¿ÿ »ojÆÛæLïéî}÷Ïÿ ¼ÀÝ€åòè.‡Ë*È»w‡wïçui/Z§ò$-rX®>OR-<¼{7x÷ÎË××y"Hé‘go}hoªY‰üþÂȬk’¾Hß“îÖ¬?3AFÒ/Ë:w÷Û_ÛdéßÒ}…ãnSóû¸‡׎¬ö·ôøæÿÜP|Gêša7æü×üÞþþfzöõëoû 2NÍciÿ&zvì£éßóê?¦Ó)”V4÷nŽæêïWwõíóïlCm(Tø×”¾%§ïÇüG“{÷Üw²³OìwÒOø;©ñ»wüøþ¾·Óáþ5¥ßÉ0|¯?h™2A T?‰éo6%v|†¥0¶W8[ `" „‰XàL2V 8w[Ÿ^©: ãóÑŠ ‘SÊZ$£"§”µHF+.DNé 2=–S:¤Jl-ùF&­%véZ²×œ¥ˆ5I´N“™bâ#ë’‘ÑÚmrg¯KsL“I#†u—hUÖ5·¼FB•±ö^¨Ô¥2®¼‹-ZT L˜‘$lÕ¶oÎ2ÓÚþì‘’ Oû'÷°Ãƒ ¬X¯!H3ªë¡GeŠ[ˆ£2´"ïKÌW³ÀµÇìï.1p=õ§~!ÈHüºAnñë§ž ejÙy*ÈÑ£ËVËú"Ȩió°‰}gzöXqÙ’mÁšž½J,…mj½K¬˜/wçÇ{Y¾Ÿ–gé‹8Y{;àÓù~Óæön¶©#=»Ê|Û1 ¶ˆÊ*æ¥Ç5•i&Tó…U–êœï¡’/ì"îÁ½œ^|ré䌭*ÖL¾æ¡rŸ¶/\,à·þ¾Ìí¿ŸR&öhQyžv“ŸlÜ¥Vq<Ûwëü7šm+¹—AÍ¢r!GË!U´{nワ‡ß¹½O¯ÿ³µå[{»î11vêê ÷ä¥O´1g‡º=êR9¤K©Ù~§+—:$8;¤N”â3R\Ñ{ö*U2îI¶ã keÌ:{óU¶ÉŠáwjŽnušpöú¸Ÿæ`íKû0Þ:×-^{û—þdm<é1eªÓ Õªˆº'¹bØßÜC·W‘¼ŒwͪÈ9MºMéR&² ÍKw1ÄÞݽ¬ ¾8œ—q`# Dݦ’-Ÿ;®ˆçÕ×\Ui­ ñ'Wç-ŒUª¨’yž qóV…æ#cà-¨¢fö‡võ¿Ì™ô”Y6ªdö±+Er‰…wü½— ßd•+΃‚ä%ªR1\qœ—¨JÅ+¼B-¬,X…WÈCvÈ44kª,Yç¨àí Ê*Yèöº\;ÇWé?ŒŠ8K”«ðu”5—r…#ªŒdk#Æ]p>Q„O…Õ{Û!¨3T•óÌ«Ö •àU·-ìå*ɹâÁëRU2é69ЪD¥Øä— U•âï|XÓWŸ/Šô$aáÝ›qÂ1Ë”‡ËT‡}lU}ÈTǬÞsïï>©äûù¼yÖ€ª4§ðBšt…ùTÇÖÉ„RUÍèË,UVê:ãVk–ÓÈœ_­…zzð‹Ø*ÅÍõºÝ$³ ×i¼/оsH·Z³½øóöˆÚm vjçßÃ1Ut]·˜ç>Œô˜E|]7áJÇŽL®ÖÐ>vG¦VkÖ¦„"u"­¯C´`•’h\Ò\F=ö3QœW†u–¡fÇp´6g `€«ÀÑÚSoìS¿î2ÍvB•(ËæßÍÝkßF›ÝÔµ[æÐìÒÔŸðèî5áUéa"³¡fªV *<¥5çòÔ%¯Ò5÷ηÁ‹@!îÍÖÙÇm…Ë–T_/ó1M)œö&¸(Ľ‰îP~¿3¹C¹ÚE!îMä7þ€LîPì‡ uZw©þ¤Æ‚•@q}x%P§rF››€\žT§Þºí; žrªLâ¤:`=_§çÍŽø€9¤Hx ¯ o]]ðš !ü΂ó X›°‹Ä„ŽCBb7>/ØÃÖ³±=1XUÖUÚAˆø=ªtÇîÿ¶†³×\J êmY–T…¤·í"¡ 1 Eã¿1lnTEŠÄ®­‹LpäBV`Œƒ+æ°¹bŽpEiuÛ°¹b‰kÇê¶"ãüœäÃP_ sòÿÙ¹ãrÛÃpÇÖsÂWdŇ^ÂîgÉöB C‘•\˜%ÈÀ1¹ £Uó‹LóH +²š™µq¾@‘Õ\Ö"[97~¾ÚàC[ä¬Ãi‹ˆ…S9ÙNÊ0*rÉͰfæê©8Ï+~õoÝ{>h-` È2ÁhçÉ2~H‘rlhf?w9M&r9í>—s4WÇŒÔÀaà«[¡ÎPä5«–EÎvﬔCDª{7ºîŸ¹ ƃ¢Û<(àiŠœñìÂ~ã…œ.1 !ÙzHHµ(PÇúýÎ7öÎÃÙ9'í"¸»ì™Iþ˜CßMà ~gõ†ÜÖ©òÜ-·áDâHÝy·ÇœRÆÇ¥qmú…žý$ãÆ:ƒœ§ ‹øMÝÏàIvv¤»¢¥»Ãi抆®›O3A¦¯|2}EC·d‘LD ß»¨?ð¢ÂûY'yQfdèÐÈ êt"êÆ‹Zè1U¢þ‰çb™1¾©˜.ZŒC1¡vR|XÛxþA»à±ä,àÄ­"¢ßåi!¹¾Ìˆˆv«8ŒŠÝðÛ­?áìEšn»ËýH‘Qß•Îú®„ÑFŒ^ÏzÏ AªT¶B`e²Lú»v$û£ÀÝú7ÏìRRHÍŒŸØ¥¤Lró ÈšÙw`°BÖ¼Ã*Tx Å%·6/x"ȸ_®MÊöX¡ò´wý–M 3¬,ëeÂ{ºË‘Þy|õAʨ.{s> ×þÆn U{òž»R|v*ÔT U°5Õ@ö/T‘X±ì{ÃÀ¹)“KR õ)uö2êCêbX'«O©‹ð~ªêèÃXYã–ÂÐz¤æUáPû-T,K²ÿP…¼Pƒ ³o Ü |KD²ì_[+ F?mÞŒþ]*ëÑzgί?v(€ÀÞOs—<Ý~:›ö£d`ʺ=×í²ï¹Ú¶é&´ç*Ø$,[ó‡k/Þ™I¾7AòìŠ"•g·y ¢<»¢HåÙmH”gçLž]¸óŸòìàë(Ryvöì8Ï®(Ryv.U òìŠ"•ggwú8ÏÎ!eœ5ˆóìREý]IÍ¿(4« Ào]ÍÌqØÃ¼(™ôÒ½RꯨdØösƒ¸¯”޶RÚQd²Rê`­”[¥t¥ÈT¥Ô&C.©”{¥ôˆŒTJW)m)RÇø¯=ñ7(pøÀˆ¿A2 Žü׎ø8¤Lô¿C¦²iÊ¢(%ëÙúqêÀ.Í[]Ѻ4²`Ýç‚@:Ë»¬êìeU–6"YU:ËïÈÙ,XÚËAŠHîÉLsORâ4“°éæfâ*ý;a6 }íÄïüû&Hæw>¯™þ§{O*^99o IÔœ§eH]ÙWæüþðˆ“ö·µÀX2®Ç ©UE•³®×è+®ïz݇ß)˜4mœ^T2–,ì\_¾»ŸÑs‹*]ólÈÒ ;©êÍÛÁÜN·ž>‡a‚`¥Þ9Q¡Ñ4àÐâñô¢ûæô×^p,\S­Jέï‹«ŠÈý.Ò)ܧÇðô_q…ÖŠ»ú²ÏÅ¿ó8ÿ˜ñΫы û08óŽì[3Á/àÃàûêâÿìs@¾.Ë÷@‘*fEÐ?–ùôÏ=ø0ü»96œoû¬mç£ùry^éï,#Ìc{í§>¬¬ˆGŠg»î¿™aŸOØ•Wï>w¸K³¹÷sGq k¯º†÷ûïÒùoù‚½aU¿yPx€îÙ—ß‘þNêAÇì¿–¿3=fåíÎgLó;¯÷yº†;_'}ÿ¶5m¸ötRÆžŒöÚɤ —ËÞdœ”ñä œ“B ÆÃܺ¶ÂŠEKNŠGZÜý'|÷­&€øî….R|wóÖa¾{¡‹ß}ïo¾»CÆøîö˜ˆï^è2Åw7HÌw/t™Ê53ß:æ»;dŒï¾e{¿\‡Tq®¦¥r„;_1)`ƒeÞ.)âëW;}Í$ðÚÈ‚°¦ÕiO¤aw¼ñÈ:ûàx׎“2"=èÀF+°ICxš›"b°3WóuñHAê`»;¢»¢¿ïë+Ô‚M‚Mw5ÿ=ÿ×Ìïóìyù²IpÈ;8Ú™ÝÉyî^©H*ý>ÒÚŠæmž¡ãP‹X¦°sÉ3Ëá|&ÈÅÇ·æÛ|øã ܇¬Ž³áœŸa]W‹7ŽR{š RxF2Y1ëˆ~µ¨ÇEúÕ¢þ°Ó»3Ì(xã{oæ¡€,“ëî}.büà¸p­3üh/æŽZs}æ&Á®§ÖlÞ ªÏ×5›wÓ„ÝÊé ]u[·¹ôwðä,³ŒÍB ùAe–%“Xâ!Yf9Ëú¾èe&XÖGpŠ+3‘êZ>ê–™LçS·8£¤ÄŒ‚c®™­@v# ‹tò{ËWíR¤´»¡ÿ^f%—•Ö„^y™¡|]ÛcæƒÇmÛõ¼^C·,AŠ”;w¨:d‚½ÿ³†ja™iŽëŽúï%æ ¼qݱ¢Ì3nîXÃW\æ9Ÿ%½zwî2 ŸsòKÒýUžWøêC®nÛd:Wv=Éäêú±Î!UнzÐe^p=”³Yæi×ø»–yŰ>°¿Ì5›SöÚ%b “Ú‰&•yÍ&­í@1LÚ*ùó¹9S¥’Ú‚?a)2>© Â%b)D“Ú`µæ©¤6äOè*ºž_°aR)Ò.Ž ±*Ÿgj¥\†r‚-ãâh`¡kY­þ¡¯mý]m_ûpÌd_{”Cª”]SÉb¥H¯¢Á)E™Ìæ>Ìqwçð\aî ©1 ŒuBó:¨/•BsºäÉYŠšËòCÝÿRf‰Õšs”¥Ræ¼Ût–K™«[Ô#!EzÍ@2ÝJ)ÙlÙà~\rÀî¬ÊrVS|·ªŒÏl ™DUö)³5üNÁu–¢1x¤Ldí³á¸ø>l•)î;B©jÕÁ4}ëk;çp3&™Ÿ°ŽY&¼hlºÖãû{ºÁU¬?¾ŸUÂee›‹‘ËJ•i6ï;¸¬8¤Hð‡jv•Õ ¾÷æ€ø!éIýžûŽ\ÇÇÃÏÚÎO'|ï Ùv×áJòÀšó9›ˆIRåù;ã¥õIX˜IRåy¬뜦¿¿ÛïëD2‘!>}q…=¾ ‡Ü>#Ì!¯°Ç7á»( àW¹HÔ—lÅ sÈ«\$ç@8äöø><Í…°÷+ÒãÃìý]ØûU.“Os!ìý*x|'Øû#=&ÃÞ‡‘!—„½àQ#ׯ*Wœw rýªrÅ;ÏB¿£:h–ß=jÕœÆõµ«¼Jé‹Ía%]•ìz%]ÛdLI×öDIç f8VÒ9¤JÌÅk žU^³!#tš*âNõQ W"çµW e«çªo ä^ÛR ‘ô‰g¯2ÍÑÝ8' S)µ pEŠq‡ÀNM•H¿uñ ¯DÉæSµc%J†¯ˆ]é*Q±ÐP!¯„æWÔÐe«">×”uì+Ï•äø6ÖÓ×ë*™s*˜6¸ëTRpÙÇÍ+«JJ¦Î€‘+)“Û=¡¡¥ÈdBCðqH•îõÀW,9>˜µ=÷³`Ø>‹e£²äké¬.dÅÔ¬pÿ½’šåÀШdÍ*A›¢RY²Ê1lU¸ó*OV9hÆh…Ü–UŽž(k*•sÕBÄö©Tþ^SE1ŒüàÝÆ:%Ù±.è¤*”qÀGNb•RLÿÈ*åÃ/x¯$p±¨TÉdànžcA¦âsVþÉß¶fXÑ,S1ìf•Þ…gÄôã,W³ÎI”ž1º™aµV ®oدÝáì*Z«\mÝfôµÊJòÎ <÷ŠãìaQU)Æm‡FVëëŽWUÉ­ü÷µª*žûºÂèºl±Ä«iê RF]R¯3rIuH•bŽí@Ui–ët(UU³ w‰çfålU%¹Ùç„ÙVUMz¦ïš˜;tÆkFŠZgé\ºó–KÇÌëºu_×-ðé<±®ÛìºaðüÏJç‰uݶ^²–ô˜ñJÔ–;<ÇË:¡•–ì^¦ÿÏJ+¦3²ù¥/)âwi󉂳ì^».[¥‹t%Ÿ0Ø+Ôߤ<Ö9BµPW©þѺçÀJkÖ½Éúvw]};®}îoþ—ºßwf\<-ÞÏ¿ª³”&Ô¬X¾¿‚&Ô!SL's?a~¯³”ÛÛÆá š‘ ÷LßXñX­SÕŒÂ×vÙÂn¢f÷ï6–™"E²ºÕBm­VœÆé «ºHx¬Î£žæ¡J¿#ëQ#ê„R‚uó(è¦SÆwú[Òcªw‰}Þ쇞{ÅøHüm©¿)R|´þ¬uºò¼QJáë¨ëÎÀ°¢®ßØS4ý¾8eÉôÓn÷>íRÄsšpjŒÎò¤þ}Øôï¾¾¤3ñ!Ó´ë2ÁÉ·gǹt÷» ¹n‡~ùé~ŸCG¥GÚ9f+0mã3„NôÚ÷\:ËÞTùü›~ŸËßóN©½¶9ß­¨};û­»õí÷D¯¨FÈvçäß­ÿ3Pzç3O? QæÛ¸›µj³ÐƒæÎaÑÞ§Ëmï?ûéÞóÏåpÔ`¶¥ÝÙŸºãµkx™äÒmž,vŸÐn3°3‹@`?xènß²ügßRlÊBÍüE-vè~Ôý-uÐáøJa²ß³ñkZ34^E÷ÜÍ€GqÕqÃ=LÀФ [L/"`hbýf¸‡ !`lgG — †Eb†ÎËÃ㘀á sÞíWd±þò÷ø±Y„ÿŸÝVëæ§Åñû4ÌýJ‘û€ôÀ¾úÙ\½õ.ˆô¿øšžý:‡¿±;Ux'óSo>Ý©yÝ~Ãñ¨û€ÿ¿ÿ »oj6ÔÍùÝüÿÁ(înÀry˜á‰B òîÝáÝûy]Ú‹‡Æ¬“î9,×ï'A’wïïÞyùú:÷)=r{÷6¤¹©ë<ýþÎA*bkïIwkÖŸ… ‹wÚÕeYçî~ûƒqlG–þ-ÝKmî65¿ûx@Vû[z|ón#cR‡EÑõ¶ÿÎqþk~o3=f6k·]v:NÍciÿ&Št‹ÿ`~˜yõÓé†{u&¸ÛÕ߯îêÛçß¹‡Ò©‡ ¼‚oÉéû1ÿ ';¡ß~'ý„¿“¿{Çïïëq; …Méw2 ßëÏZ&vàkÐQkQ2;‡ï—Å…}u’´óGH Ír¿B¥@‹šÝ³M/øòeÆôÅ·¬’‰ #Sc»wgÇ=¦L¨’ð.TfŒ:»qéÀ@йÉ|µS­‰Îÿ­†Ø¥¨F\¥HýôÔ=E‚ïá¦âö=ƒëṴ̀€éÁU§-µ+\»d¼>mj×™òñ[pLÓR±9O¡æ¥“\¥Ýk¾n–%ç³*ÂZV|þqx“#Ž-8Al9£~ —ìrÐîê)2¾³p•Y«ŒQŽÙõ-,ž“θyÀÁ’(š!ì_þ.!RDÁŽ<õ´Šìÿï~ÿO6 ˜«tðþ›è†p•¨÷ßB¼ÿ4v8üÎ…xÿ9¤Š9$Ä!Q+•tHœèL©¤Câ@µRŒ— öwÐê½&ëÜÉÛ¨£5æTn QGkU&ÔÑ6u«£2áÚ€ÕÑ™VG‡ÑFq0«Žw©JŽ!}‹uéZ1]:[ŒïÂwÄté¾6¥ž EªŽ\EtÁd?}.rN·†XàºtA0†òÝÄ?£yªÂïLg‚Ú\·´…ú}…sÙ‡¾‡7¤H¿É-{ãP*²EwoñËÐØ‹áí+ÆÊp]éºùºäÀ]zÏ ƒlÈßeAœFó‰v‹.*Ö':ä^ë‚÷õ˜ÖpvÐúLe¨Ÿõ‡Lå‘"Eâ+FÌrYM‡¯Worùƽ9¿K3k¯§þó;ö8pHïúÝ]Çy^`ý\þ£®acè.—ÿ¨kØÐ½èÙ ‚Üš ÛÌÕ÷ýLÏ^Žï.ò2Kä¦ë ?I—ÿ˜™•´Ò»¤ý>ÅöùÝVo·…:EíÓ¼»7ùwþnï¯!ŒKîÎgQ :"ïÓ¥ø¢Õ¦Rr„GÜ (³`ê­’"E:è^вàMŒÆp›X‹$ÒÕe,¬Ã73Ãm<Á+¢9ëËñè R$Ï‚]Ö1Á·ûþæ>T˜«,ËÙÙXΰ=«Ø \›¿Ü¤LÄ75MX€VYÒæ Ô3]¥å=늷" ­T]}°" N5ÿ^úzÊ´QÏ Òö5Oš®Á:KWgwd3àì%7(#Q©®ª ØÌàXøC€ü´ÈÃÀt08Ú†+,/°yÀ» p̧õ.„èö8V˜°yÀ»\É56G3:ÅÖÂvÜ„FÑ´¬e2n¨®™i&‚ÉZ쌊:Hs¢Öf¤Hå+¬®núh}Ý4là5ãeÓ¿•þÎ2Y =¹Kpí¤f1†ßk–×,56dT ¿a´Ñ¨^«®¤ŠVøÚDzþMY$ |c¸ó¨A«ï…¡õrÿŒö1ÙÕìÐ3R‰è€-ô™Fè˜}¾“ŸNDB¤±Õý!Ƨ#1>Z—ÉŸ…ˆ4¶ºñ ­î©(Ê,j±(Jë*!ŠÚ äŠª”(j쿳Jˆ¢ÜR5lQtÅY¿´ÁVDcûü˜”d‚ˆÖ¬”dÇLII,µ'È”¼!5c£¾-nüÙ“ÆŽâ"]³ä¿ù€lA§kÁU±®ERêÔ :]‹¤Ôi tº !‹9ïNÃñϨ–lä#êvÖ2m e¥¢á{¯ËŒ(t]|ˆå„ç^‰Ø'G «_†"7-æEFÈŠ±ÊÃFѺ֌åùfs×^óžSxî5kቶ»u´ ¶›ä7Ûuö!¤ˆØu–qÖncøŽê,gèê›ÿ^GiÛZxCêL¤Å³åµ$'üÝ~ç@ ÒôÇ WÄ™æÚÓWT0T)l·YgŒ ÌRÁʪÎ*noØ!K1¢“MÎ;Â1kVv Ûê<ãvHdV3ö 1Þ®sÁǘƒP &Ô3CÑ‘Š:Wìôÿ:O™:S|ØñÕ§ý6Wˆ#¨ó‚·×…}\y:Çñ“‘Õi# KGtà:¯8y4²Ö¨sÍÐBmO¬[RÐõ§Ÿµ±¹E×)µ 3B×ÄÚmq%Ýç÷:Á|Tç5#ÎîH­îc„Üð&‹4!w FæµÈþ &{Ö‚3[‚ÚZ|j"Ugø:C4°ß‹é¡Îà1²§Ù?~uÁš¨NÛ`X±QÓ‚„¨ió•Éú¹;Ž`ÿ\‡ø—ÿl-xGÌ4ßQß­à=ÕÄ㺋Jµ¨‰Fg{wpLÍšlumx—êôÿy H‘jšŽaü”\ãÐÆûµw-sÎrÒî&(2˜,—Êív›nžÇp?eŽö†1$|ï2·º›Ñ²“gæŸág¡È#]Iw6KÖûÏpø¥ç¤nEÕm¤ý¿÷³Ý¤Ç¬ÒÈžSûBíÎHµoòsœžÝËÀÙJ‡¹³œ­´µ¾¡H‘Þ#Á>7Ì©ñ£%™!ãǺHu°|/ÖLEÉG¥tYq¤;.Á3ÒÇwé Ý‘ùwX ;Ru²Ûdû(×;Ýq¥.ê4IÄvÅ€Q_u¢º·‡A Ñ¦ä m°±s]fÉÑf!&cuÉU^xý] & ÍêR&Ûõ»mï¯ÿ6KÅU÷¬YßD"s¬ªë²`"3°Uu]dõ¿¿ÉÎk«VÂW– Id3Û‡»TqôÆK°×¨Ëˆ…)ˆý±5S]j.¤…_×¥N K~]—:),HøµCªDXªÄÕ¨¿ë{]NÃbF›Çåq‚¬âìš—1„åÕI+Œv#–á‹«òD}ÍZv vϹ¤H…Œ@™¬+¦vÇ\™QPc3ic“º’Ì.¥C¶Òu¥’Áß þ®«âSð÷B\ð÷@\ð7ErÁßAFƒ¿;üíeœ`ˆƒ¿kb¯Aƒ¿ü]»ûTð7ErÁßArÁßArÁß3ArÁßô˜\ðwG:9#„*O±Z½?\”OÓ·}Óz$5rw ŽÇ.5ŸÑøû HEÎÖòýy%H =fg|݃ZÌn{™»umR½#G[U5Ïs¥¿³ƹwÇ›î4Í0ËÄâæÉµÃÚ¦ª?\{¸¢úõ‡»T¸ö–ž¹ö±!ÈÔµ/wtí5ºöH‡µ#&áµÎ8Ûó¶ ³¡Î?˜Â;¯9Ó!l~XG¢`·;`Rm­ }›¶4ÁÞP+6œ­Ö´bVVXäQ낳¥Z{dÔé…Íd,˜ùÔBÙ¿Öšï£;§ÖuÒ^¸#öÂuý‰õrõw©æY/A£Z×ù«+¸K5û† ««ºégD4•u–nP«–ºæVª‹ÝéûgTsÏGÖu™2³! ªë2T½õËmä¥ÿŽêгb§vеfê6fc b”ºÖIÓŒe¼iF]×lhïè`2C! Ç(Ši Av¿Ó#Ó!È~‡â‘Ñän A>œ=e7j½€;L² l5¿ï<õØ [ͽ٩GFã–m\ ×.?ÆMAŠT¤ Ø•¤ú)8PdüÛÄ1…É„Nâ˜BiYÕ×^~U-=AŠôWÜÃ1+ζ·iÛžf:~ºÛìÝZ8{Í TKf8 â-h‰f 2OÆF,صÀ#AȵÀ#£± !¤HÆF,X„ä‘ÑØˆ»xd"޹x$Sg”K¾â4=R$˜4ÍÞä\qö/–'1{dÁß ÷3OÛ‘u¶»ìÍö 2])µæð+:fů¬ZCrÍüNd"ê‘"•xÏY3¦w³ªk=Rd|à»ïŒdÎÓFwÁ˜œŽß"ì¡–nòŸ#üNõÁöFo¦Ã:`ÛLEf¬À;1H®‡ò³B,”AV|-Ý[œ¤æËš~gÍ—µ+Œ6‚oB±]àbæ8sùç™"%F¶¾®ø4ÓÜëL‘T¶rs<]3kNƒ‹ŸöÈ‚ôõ]åÙ ûó|ž²L¬Î^¥ ÖZzL¯äÛgߦ̘®237Èüƒ‘f@Š”D¯°‘¦G&4¡Z葌‘æH‘*!Émºî’”Œ)ÖÄЙ4…ðkŒ˜ÇšuÝf»ÒcªôücÛ]]B/Ò Y6s`üdɬÖP˜ŽG¦ŒõÈ]ªLÙ-¶,0e R§Bf”ð ŽYsR öÈTüJ0m“Yè®nŽæ©›³oþYm;l»hçUÎÝ¥°ç2HÁ˜ Z%á H™Œd.6XFZ%ÓÜJÛ‚aµ¦ S+GW¤<íac‰4Y2êă4ÈŠÕ·€ Ø 5gzl' ²N†žÛîjF›"¹;óôo'X'ì>nBï|‘ÚÇ™…’ÝÇ5‡³«Ôü ?ƒÌÙP•6¬ÝÕCàf»„T!ßäžÞr³{®Óý¾À½ÉåoûÌeäzZ–~!Ȥ½0š‹‘È8f/Ü,SGê]îiGÅÕŠ8éï,’Fį©'Ș0Ôì5G+!¥WT¥-‹Gú;uÒD4ìß‹‚3m×°ª, .Ô¯—"ö°¶YÖ›-êzdõÞ—qUbÛ¹[gg#ï‘”Ùéßûz›gØs¡{÷ÖY÷Ãý­ûûþ½† аýóŸ=ô|×$Øòô×é4.¹?Íwd{»ík°ÕÞø‰"KÌýÝí…7ûf>¿f‚¬’Vê+¬X Íú¿5-Œ6EÍqýñþ½Ì>ÔTá{/9SÄ+5ÈT¤Ë®³mÂÚ&ãîçb¤ú3H•¨n}Aõ瑉½a?6aUYlÌkV•e™^+b;LrNÀØÙ +>\Ø×¨ R³Œ—6¬¬ÊúƒÂöÚZ]lŽ—æ¡_÷Å…mR‹?fZ‘»;‘†AŠ„¡·½väŽhòC !¼!•âãh²8®—î¿^²¹Háý¬Ê·°f¨ª$;¼Ãx©.ª{¤ˆ9mv¸k5£5µá˜På Vÿ‘NèÖK¨#ío>WzLE5±¯Ç½r™…îU¼[ý Ç VÿÛ:äZÓßyþ¦Ó7Œ´:Kª€výÌ\¨#fÇä}{sïçæaï¯uÄrÿ:,r^Æž (H÷£åé¶½y×Þ:-P‡Ñš¹Yçû;‡þtê–›g)x¤ <]séW;ÚüŽ—Ëe–•" OÓ=]/ÛÜ~w±;?ÃÒd‰½f’ÙÞù¹Ïæm)rëkÿo3Ã=·>&fX¦áµ|ѳëùïŽtfæÃ2¿Ö°—Ù‘u,¨¥û²\ÿðÜ%}hvðá.Inåz=ÉØÌàhLG{ŒáŠÔ‡h´"J×÷¸d˜¹b! $.y¤H‘ ÜDý)pfç#¢ê7k¤ê7ÈŠéÜ!U¿G¦gØVªZóöaL&=Ó`ŽÛC–ñ5ÜÎÉÓ/ØûÀ sn–Yi"ÒG€È 3y €”L@ä¹A{íšQè™ik »³Zqº&¼²â:¡ÖÈ-ÌïX 9Áê¢æ&w;Å.)šm\·©5g¡”Z)·A¿j5»fs#™g×G9ƒÌ94Úä™àGxçóЋ|ïA_mÚ!)cÌÆ-’µè1Uª#:ƒäVVHEiŠy“;´Ï“]KÇd†šžq vÄ’5È2Y§]pØ“A²AÀënLdä2HN…¹<2È…Î^äò£·CÆ\̪¹$È<ÖßtÚÈ»$xd4:vÂ. )¬cÔvH•p,ZG¨nåy̦ ê6÷»7ß2Hñh¸Q -Í}žî¯;|G¹x÷§ð5–µé~º3»³ñ‚Tà{|¹^¶©ãq™×Ÿõçu=MY€Ÿð¶´++³´9)íýDeÄ|k2?Ö M~–qÈʇ¢n+À-NñÙ~Ïögòõ‡Ôï‘VáŒ"/ R&"7dˆ¼ôÈH@ä† ‘—)ã6œ( Ò#c‘;ÒDzd‘¸¢yiŠ»¢yé‘É+‚ÈKL_‘¾ydúŠ|ˆ§GqŸ›ÙÂ1 N @YrñÓ-è ²úP9¹R³•“ÀÈI·ú¨méì  O³æu(ÞIMæâCzCDέmš°ZË…àãÑÃ&RqŠ õƒq^ˆäʸ.'`Žy¤JrFø:„än6LŽ©’¦¿6ý5È‚uñÓ_ŒúŽ-Ö´2̆¢LhËÍ̵iËaæeBøu¯‚מAVïb¦AjÎû D8dÍ3áiÊŒS$Ì2gÏžk)ö2Ó5HÉù¸YrŒC¤Jèz6Ÿ‚à°cEÚaÇ*VÐÙ Îagê'Cd‘P¬8Ÿ‚Ö`²HDˆn†Ç!BÔ Ë¢°¢–lTtÐñd•dwg›£~§Nr {Ò;sÈdï¬]ae%u’9Þ™C&zgóuÔÕU _KóøsH³J}øZåô}ÿ{¤ *›ë8<Ûõgtîl)c >6f«iüžË!åÂù]¤yDó°djk­?{wmÇé¹~dy°ÄöûâçýùúöÈ<‘ºb‘Ïñ·9 ò-òÒ]Ñ«9?G‚”¾×ck€pÌK;¾ÖgKŠV ]õu\ÿ^—öJE¬z0`·ƒLwB'ì6â‘1·‘vÂn#™p=Cn#©¢»ë¼ö°ŒÚº9&Iºÿ>bìº3™»þÕæÁ¿z‚ŒîvÍfæ jGT)äØÎ^¤f™Æ3® RñQ}ŒÉªà£ú  ç© Op1È’SP¿ƒ¬8γÄÂé´ú{Ød¬ ØÃÎ#£±¹ö°óH™bŠ6a·«ê$Ói™·u¿¢‚«Û4mVVˆù°u¯lv[ÓZ›“׫|m-ĠÈþ½YÊ:0Þk¿Í‚j¿¹í _ÿgw‘·övÝØl#òœ(‡,}Õݼɰþ4KàQë‘®>oûWW=Øv;A‘:ª­þÚ'£»Í¦Ï¯Ò“þæ®#,î¼âÆOË ‡Y›04ÞÔÖ!³f£Nzèñå:ã£N·©3>êºê¹Î¸¨“¦ Mëó‡Ž-b\ç:gH·ÎüN®¶¶­i{‚LÔÖÌìýÍq$ŽlóÁÞÎÖ!Z¤ò@wOP*åš÷ô‡PI†ÛÎN÷ȽdóáYBOJr, ö«K>Çô†¹.¹.[3$ã©zÆÝ\ë$ëØÂØß#k6w¡ µµ:ýÎwØoÍ sfuüÖ<2úŒPf‚>Ç^ÏWè)¬.jF©„3p=2ô·à \LDZ¡ \Lì¬,2\{Áùuš/æ÷ºHkWíê"ÔÒë’ùް²&¯+†!<á d­Ù ª ßÌëšaâYm ÿŠE–±êû¶H&ÑØì"X3ˆHOŸÛõE œ—ºçÕ~Ù׳¿|·=AÒ÷­}µÅ¸·ÙÏÚ"ï1îûwdcܧöy8{áw»$ó|²™ç=;¤lÇtª sÌay®½ÂY½$ÆüÕÒß©S)æáá‘u"Ä|l@ãàï|†CÌï­1?µóïáâó<b~=>O‘(-Žó8*™Ò¢Ùs6žð#° üÿH˜ëüó}¹¤L!OM÷¸¤Š!mò¯%È"Q„ü¯íA–‰’òí§ù…cFìæ|¡ø²Š RÄ ¨ëßãûv"HyMûkÿ:Ýž+Aªh¡ø«oë“ ‹ÕÊZkÂ+Z0ô­­ /^ÉÑcl¶#Èh¶ß °AÊ‘IäR%Ó5ì$ˆmúaù½K¥:‚ ëu@WÄÙgw¨å©%SÓCÉN"Ín›c³N®–Pñ¿¯æ§®'AŠhyí2ÝCƒUd5‰y#ü€ÀDäYÂÐàÖ®T(UuÙ H‘h룲•È™˜û­å—LO­´¹‘PÜyR”:v›(Þºœ¥¢·.O‰RÇs·‰RÇTï ;qcá†È%g‚,× R±ä‡@y‘4Ù›¡¿pL.ôb³ïÒ­üë¥==<Æ Ý<¤$E7.™eÐ0œ»3Aª”%`ç#L<² ¤,tö ÄvÈ]üõÏ6‚™ä-ãß2L=f_ÙX”ð&—D^èÁ1«t[j3CÉz‘¸Fä5CXÌ^Î.2ÞTjð‹U!r6Ó5”Y2õ›Ýa8¦HZíBWø6‘µ}¬d8?ÞD©Xb,Ä{[ʧVÚÆz[c!°¼e³Å»»˜™ù2þYG׉ Eª$Ò€Ð@ˆ’%TⱜM6ÜBs„µ…¶”5gë´vaæ’Wµ3—š2ÿ@†Å¢|ÜØ’ˆˆÉ–­´~§â2±ÍƧ§Èd¢ì !‹eÀ+³dË€è%ÒÔ +ê·Æ³~ü”cÚc—!ðuH4š¶ Ö ¬BÖ\ñ5XÎ-Ûm÷ŒÌv½NÎÅ›$víè1U2Ë7Ìq*¹Ñí´(Šéxx“©éï._<Ø´ H„ób75H -p3”Þù±³wþg¥Ç” Pó8aWRJ-]×ux'•n†nx´¦-UÚ‚É ‹ 5#JÆv ÛÅdÉø!»xLE8#C-ÁÉÀWŠÔœyË,×DY3Vf(pNŠ*ãç D/Ò-Î=˜9¬«œ#7Nóã¯ñHÁ‘_ß?#A+{yùyßÉUö¾Æõñs"H‘6³…1¤RlÈK*Qc>€ã– ²àöGæõ Q±-xD³…gû7¹ŠQDÜ÷>?æW÷O“¥ˆà~U3Ô‹Æ–9üÙuÆYúA¸GŠtp8ŒK:g¬ ±žÐâÃu0-? †c*6fÍš%ð#£|öÑÖåzò¤k¡«ä·Ì—þÕ>}•X¿‡|{¤Y­¯¬“µfèFäMÖ5chù¢ÎÒR¾q»vö:ÿ`Hψ‰žíË*€}q-™ys² A&Ì-í µb¿â6Ìqéî» ŒÉ5îƒh<¢®¸¨\Ñ­Y ¼Ä-9ºZ³k†®ýñ»H™eikâmµæ×!ůF× pçe–±k†FE‰ ‡éfßy;‚}™3«ß½e–'G›ÍÄè[’‹tݪ+üNÉo!s6™q³ 6Ô’YÁíe,W®½$‚ˆÝhºu†0ÍØÍáŠ>ÄC3Tf,‘Æv¬áì5OZÆ2Ï83TÙ“yÎSƒ`Ö–9ûµBM@&«Ù.ˆVA2T³ÿûßÿûŸµÍ¹Ü®­7å›BÅLæt‚ä2/y£T¨Dɼb rÁ*ß#£öæ¡ÔJlfû.1F¢~™³ã<õ˼歳¡²'9y ŽÓòÈtÜ2:fÎÑ9q·âƒÉö@‘"áB© R2Ŧ ó‘oÒ 3*>¶UÐòÓÿü>ûž ¥¢lÎè·îÖ·ß¾×ãʹ Uà>Þ—ö€,p~Gš)«iïóïáw–^ÕlZèûfqc†ãq=ûÙÐ!«¨ˆÒ¶êáÛÜ‘ú?lÄø5Œu;²~'Æ;d¼óY"ÉÌæmÀ%©d›m°m¶ó¸dªÍ6a‡ŒµÙ¬Nl>‡cªè+b«îè! ?ÄÖù!ž:‚Ôñ¾¥û˜GtêO==¦ŒåÕo.‡PÞrȈˡjërH‘—Ãvs9ìaYé1—Cë g])²ŠOr=bÆ;¤Ž(ð—ïçVÙ¤HÈJÝòWo»ÿÔw{ Àzñw>Kôê4ÖŠ’éÕo5³Ž ¶?Öìo&ÈT íO ô1‡[)s“®wwñíe™ú¹¥g/A±ý2…4Ä%E]Ÿfª£Ç¬âÈŸß †vHŸ=0ñYŠŠOØÃpLÍÆÐwèÁ׬ük‚£”i–p—d–èN´®;g—Y’ ¸u'ÂÌ)êöõÿ¸ßyóëµµk::]ÿüo AºÀžÏ:ø£§"ÊÐéJ —»GJ²ºÙæ8gnû\h>”Š xüyÁœ V„:rRlfàƒ—%S ³–oY%BäÚyÚC䂌„Ú߉ Rs=œè‘‘ð@sLè‘2ÑíiÐ`÷.2>X/ÀÊŽé³Yzãî<äÛ4mX}«Œ#Bš±Þ!ec"¤ùâòq8fšyD z£y¢‡+* ½qû½±oÂ@¯2D„üwGn„ÍÙ ¯… uÂL¢ Tn‡¬”Idáï|–âLBö@DÈùú‘Êd@Áë¤r6 mÑC©Ø–À04)–Wk}­&‚$ùûcÚ^’ùù ¿3«݌Y6äs^­T^­£–š—Ä|x‡³~n× {[7\ºçóNé<~¬sÏŹ?ÿ¦ßçò÷\èµWžgõímçÕÞ§‹p&ŠÔñ¥úz_Xþ+V-öŠ.·]Ï÷ì§{?Ì?_3½ó‚¶ûè` f¸ü´‡‡„`írÀÎ {Â|&:%PÂû÷—”…ûÃcÊeŠ-Ü„)ÄAUâÕ·Êà4²Y±¯þj6‡gš—Iº0ðy<ª´Aà`'PxIUpl&ÄË“ªd¨6£8‰]‘*¡³Yz´áì(ÒÖù®Û‡¿™¡^úÓ¹íŠÑíeÛÑR¤LÄ)÷–mèL7~³{ µ®"b¿áv6ñ6ȆI"ä}VÁF¢û[lé÷[Údòýœ@Ã!µb²›˜w"Ȉ ÓÞÏ˰Œ'zL™êT4¡®­Áß#ÈìRŽY°ae!ÜUêòC¸k8fɇ»†±N—Â]aU©K6,.J]qvzÈúNjÍó¯Ñ3ªùÞ 0P$âÄ£`TçlÀQ2H“·çÙn<÷­ß²NëÒ4ð×yèÒB¦Ë pH…Cö  øy àÅ{hÀ×!4À!SQSˆpÈ*iðîé1urüœÂ Ž'Žl«$–e¢Tz¥r†ÕbaD¤Éˆ +YÆf gW …h3¾ÌšÞ#˘¥ñ®}¼šhw$Š’­h¼™/AJb~ |öκ9/©r–6…èõçüê(²8Kì¿Ó¼ÈÝp£ÈDÀÔj •éï¬ð×Ñz.ÿ—Y÷ß`\ªQUÿ`.k0ivÈ­ˆñŸþg+¾ }¶ü“u[zç3¨àØqi+C —õbfØ;½õyŠ=×öú»/Öƒ¬(TøÎiÛmï"ÑÇø½Ž¯éB¡J[aÀµ‰þš®Þ—‡*ÝMìý=__h‘ ß Uë:Uµ6#óVµ†QYòǸWˆPk>¸5ì:ëš7·€ÂÊ2ÎܲÞ(R¤|üŠQe9oä»N•q/\T™H¬¯Ìå‚kB ‰S ¢åª£õ•Ê$Ã;³ë«¡#Ȩ!ëò|ö=èRGjÖŸ§'H•àÚ=Òó鑊áö£­¶¤Hðvçûc½zd‘æõ˜§d–ÿð4K®›fƒíÉíûì»4Pd¢ÖmoT¦ßBE|XÜ@LËTÆîâ‘i™Êê„rËElAL´"êä· û.DĨÄr<œ]½«‚¶çŽTA*/Ö0V©<γ)·«Håå‡(0x?ó2­$zk˜_oZ´Xt+Äüzýgg »:äºlE‘võH~šÖ§ gçâ'ëÄ0¤HYRž©b˜_ÝV‚»$òQÞ~÷¡„àìâÖ°ïSâ=6!ôî{‘ g#ØpòÜ-·áDâ=¸À"ïö˜AʘRÓÿ5ýBÏ~x“ûøi‘³¯9d¿¢ÉŒ6'¸KsEKw;‡+*˜+ºn>Í™¾¢i¦gO_˜)*D*z÷°[¿pLV/hëA¦ ð '®DÅÄn¯ã û}‡IC¬q†³kΫ ÁD™2ÕC _…˜-”ák¿wkºkù6ÝöØ™-2÷÷´À×!ów¸c½7}k6“IG07Òv¿¿_¾"ä’TZÀKæ9Ý×ï/‚Tž ¶Ÿ½õ*ÕÓny0¿¹1ÄZ=Môì{ëò¯“Ý~ʬ.îáM–9jàþßÎ1pnf;sšÐýÌßÂu±J ¬çŽ ŠR[]ÄŠR%9[;¬(UR&õÝ8 ÇTŒžÀL+̆²HÄPX4¶ÆT²äÌÀ5¦’%¯]Ž’¯•„z©Â ?.=ì µÈ~˜_g@¢îá?ÿÚ8o1»NÏïîöÝR¤€=ßu;ùö†\Ûõ>¼Æž {Ú ©Û1¿××é>MA*pÇÙˆ‰íÎWùšî÷;ì¤v¤c¶üwGn­h‹´%¶…"ÁâˆC^ÝÞ|n·TR‚DÌ–ëu¯\ ýuþýý^~è1µGžìâb¿Ÿsó=´·¡1[®ÎZØóçñ}ú¥gwÌ–gê)¾võù¸]Ÿ½¡û.þ¿yŸfî–ãû÷ÿ®Ëáyné[él;ÿN>ý]¿¿éÍÏe: f•±†´Á\Nqt™kÜC‚± úСQ*í+2_E¸ÿGÍ©N~^ñ ”Š8bÝ=rX®ßO‚Øq¹^|t¬ù‰÷`êÒ‡Ìîü§ûÎi~÷ð}*…(8³á¶WÇé¯},íßDY„ò‰„}öÓc:Fm•¢ïýåêÞûËÒ>ÿÎ=¨_¬íN›)Õοûi†Î±Cjq ÷³;_F?'^vB³Èksç‰ Iï~E—¥3‡<‡QaÙãi®ýw²¾L©ðµ7E§_¬™Þ¢x‡¯~6g_²ôAÀ Dñš§ùºý>Îd•TÇ€—R%ã]€µ9ŠcнRšÓÑ N¼Rõ'ŸpöúX±G‚žhÜTñIãïg‘Ô¸µ=Ѹ©"©q³jb¤qSE– ìN)! RaNÉ[Üçff>dÔ̼ÛÍÌ;‚”qnA,vR¥"YƒJW‚÷ç~’JòT\lDX]%y*çÉúóL™ s üf‡ŒZw›ôáì*V1ì‰k™*˜'âZ¦PÐÀÁµÌLEصÌ!#®evoŒ]ËRŸÈq-sȘkÙvöàZæ×2»—îeYÅgXìZæ:åÓ2‚žB !Ê•ßä)ˆ+¯ŠŠµžý¯¿ŽaÆì‡L³À-DŒµ2±åWeÆÅ!/GUæl4ZÛ$ö lˆ¢PI.‘«À‚•º*ÓŽC¶Ã=†ù¨|[±Ü Êó{½ömJuÜsÞÜ\l¶ïíí'ÔjËPg±»>ûu´n×g•c38Ë9¤Ú®YÙ\wmã­5/ˆõ5!HvæyìËÊ{wû»gzö#÷ïÝ û¡°›*ÑŠÅ![ËÉ O¿ýð=Qdv·]h~ê÷à Èý‹þNí‘Û>ááÿÝݬÓOY#"²k¢™³ßÌ%µý™Þù mS¶[¿m>ÚûÔµ‡ƒº~Û?–yßWæÉ¿kû]’ƒŠÐä67jûæütK–"*Šlµª>~f½/ím8ü…¡Ž |k×ùÖµó ½óíؘ ûÌhßwÇ`•}£Ì²É®¶É{XÿÆÞLa3…VɽxS©²àhZüÝ—\Юš–ç…âfÇyG^p#þZF³qôHÜûÀÑë+r=ŸÃ÷TG;D>áÕÀ»_e‘îù¾ÿXˆQUÙÑÙ%8 šeõ ÑÁ)Sa ¨ïSeïÂE¶0t/zö"&q\ˆÑ!£Âʼnˆ!²J8àÎK•ñÂÅf¥gO ìXeX¸ø^F éªÊ?”ËR0- LrU•äMCïRœ‰"Pªª`më‚ÌOUeļb7\5KÁn¾>F¬>´²à3®øLIÔʪôê,𪙒¡•UibÉû–%Ú…k¯9;8»¼ôW¤³)ðlӜق¥àÀ ªGHE¹K ›êôÇ É]RZ&¶*Ir—R&H®È¸Ã!U’Z Dd¥UÊ<Í.ì‘yšŠÐø¨y<#]ð›ÄŸ•3¹I æi¥ZÕ¦¹4‰pvªå@IýX°Sºb2)ÆmfuÅsÐ15{̬IÑ1U| 9é ‘©âÉIwÈhªø@rÒ2š*¾œt‡Œ¦Š/$'Ý!‹xºt¿6¡E„sXÞ¯%ª+DvŒ\;JTW8‡%rí!Q]Õ9í¨®êœ¿vHTWužHTw)EaCWó CT2­Y…áðxB§Ž* ½`õÙ>zŠL) Ûåq8{¹Š×»U—î+ûa¾¾—† ËH¢å`-GHÞtHWÞüÇ%w<@°:/z—‚Õ®A-ÌZ°‚UÔ~¨+X5ÈñM VCA®&É‘XÉP¯%+ÙÂt\³2<Í‘ #{µA*UÌ$k¿Â--Ù•zpáVu•Žíg°¢¾wÿÞð;Y7Q¤ *²ŒKÄ@<ì"Ë™eC‡4föÑŠé‚@ESd‚eëü½Èd"”mÏzèa ZdL=p e&‚Œ„²™cÚP¶>\‘J…²µÓÊÖQ¤J;úEK‘qûÃf EV&Tsö™cÕ\‘±Î´H5W¤sCvÏXüÙ»gàÞï´×~ù{ô¾ÛZ¿¯#£Cuà"«™°HìãZäë]<‚‹WAXtDkdN¼iüå‚ñÍÛ´F=A¦}Ú¡Xä‘Þ\È ¹?ž¿XäŠÏ &Y‘+>ƒæµ™Ì  ¡æÆ½ó®¬FÎ^pÚ×v O3gÔ}ı°È9ÇÂeå¹Nd»Ø¥‡-òšS£pØ"Ô/`!„ƒq ‘±®}A«Yˆ,ÉÀÞSŠü‚­ù;u¯‰Øoã±öóË#Å»K§¯…š³Ÿ¦n"H‘ˆ9~|=›ž e"æ¸mzm„xïhl÷Óò®¬JHÉæ°ï÷BHNcfÆY__-D’½»F/mOñà<XÖÍÞÞ%Á»ÙVw!Š4“l“ÆÀ·)8®ŒY^„±N”iMþ¶…ŸàÚ+†£UÜEàœEr—l|Œ`B'; ”/DÍoá!PÞ!“[ø(ï©-< ”wHQÚ[W#[ÈŒs=Åcäüf7F»¿KR|ë|U¿’÷u„nN!Y¥ýÚ¶áì*ɦ²oˆ9¨¿ó’]] BG!ËDzš=;öç/d•Ö¾îéiAÆf®±ÛÓÓz‚” ¶´Cf‚TI]tvÆÌú÷B~Y=’þKôŸfFø›û0z«Œu¼Àƒ£P32`ŽB¥}ÁìÈд¾,P¨,Œ»uC¯P9³ïÀòEÒÐgÛI!ÛB V›² %YeH Ž…R<¯¸ïEàÞ¼©¡âáU„‘ãw„“P Å%ˆ™Ÿ JÑBU caóqdJmbßd¬6)礊Õ&…ª“E³ÝõÎ^¼—ƒî lìú~9ûc"®ŒÉ^;d` ÌÚ˜+âøµÐú2KßõÚ¤L»Ý·YpºtìîWéBq7|ý\'x— ÅêüØ¿§’÷øŠ‹‚óÒ7+ÿŽY²Þ‚Á7¡(8†+öMpH½·ïöï…fVé6'(\‘æBê‘ûzQÔéìÆ€³—³ßd1AŠDxq8â6Äy¾[”¬êØ,Â|I¹ˆð¼—¾ýÞÌ«Üz¤Š(Ã[P†ÿœG8fA„‡Ð´6O~&Hà7+og,Ó­ÿêVzL ]û^kUÜÝcÖÓ4N'‚ r« ßÞºîq½w¯ÓW¸óh•á–1üØœøZ»ãj~n}KÈ;ëêÖŠýßúüéž-=fåý{7 ¹s&lxñù¹;ýnºô³¯€ÎÃØ<Ϧ!È:áÁ4EÚMf¯±„Ù°¬øêVøÞKÍV·Ìޝ'HwÈÿêÚ vúeÍäÖ½¬oÂDé×02T›â|( ÜYÏÛBvÈn4ù±CvȤrh2:dÄySë!;d‡T)×›àãSTâ“ ÖÞ•d8U§ˆµ¡‘SðÜ)pUx[xz Oÿ&‡6ô ·,óé7\{‰<Ëì;ïY¸¿óü5L§ïðŒw¬Ò«|ê¯Õ#+†«<š!æÍªzã*{îw÷ìÎËfí Vé[ø|öHsE×û<=áUzÌ«ªE¥y¯º°‡­ø,’À.*^ÇT1…ÎÒÒ*Ï:Ogò~m™¼=AFÜdì ·ñäï’œËm´xsüqº¾-çâÔ‡ßÉ:|¡Öa¡e²ú:ìy[þ¹kÅŒŠgÜGМóà¦õofÝ_·Ð㜵¹ÚÁµë=¨YáF0Y ¬[&DHÕ)°›ÌAYב쌧ÕR¢7.jÁúL½qQ‹D:Õ–¦d':8¦dµÖ·|q¡##¨XÛä™ ÓZëæpv•t‹ 3l²Ë¶}q(ÿ±¨yUvàÉ.›cžƒâ ¨«„ë¢Óí‡Ñ¦Ö¬+SÛÃ:;eDÓºGŠL§uÃÏ!cóæy iÝ©b^Éð*3¶š”Ê,cú28ƒ¦ÌrNˆüCËìƒ*Þ2cz»³e²¤bsëÌoR$”&ˆfVfE²F“ʃ«ÅaµÖ¹CFë`ÃVóߦCÊĺÎr@‚TñvH,3†œc9Dè.i.Ãup’¸¬Þùa¸žÆù÷pLùŽ´ž§vþ=3¡Á½ò2«?džúq¾Ì3Σ° ù;eþ!/ê´eÎæÅ ´šò½oxвú1¤ }ÃÍiW¨î5–éù=ãíÇ#©_ðömÜ÷­Ôwû8ÿš·„ ‘ÕÑÆ'ßüþGó÷ûû§#Èàt´9þï«5ƒüùBZ™S†;Id+eÎ¥:®!‡º”‚wjod…¨_\Fúq¨ViI­AŠTäT ~—%îÇÅ"§ÂJ@ÖŠ=ft­8íkEŠL§†´áw–\Ž*òÌ-Q7pùç¿nLvžíôì—ûË#uÊ Ë¬+°“K)kN‰œ\JY³)¡ZªŒc ¢`©r.ÓqJÜ{÷9Ežã¥’ǵ¢bm+‹­uç‘|†l 9R¥*Ø7yù@©JF‹]l2Êt²¾z¦¥J{QuÖ‹êÞ%U¥úHJf©87X2ÒªšK¨oV¨ð”8à8&_·1™"eÌü1Y¶äB‘PÝr*ÅÖ»ü/“ßñ•E–p`°¿óa†ïÀPù»þʯCÌQOSw"H‘p”¶+Pÿ4 ¦¾d]¡×Sâä€Hbu¨­•…d\é±}Y|J2õýÍ’í²Íæý\àì¬ã ^ éì…PèËB'\Àìû‰]ÀÊ¢NxfY$vsȈg–Eb0‡”1ïÔ…¸€9dÄ3Ë!ÁÌ!‹øa°²Ì˜+Â.`%îܽ]vsÈô ˜C¦¯¤=YÄ#Â}-Ëœó”@ÜײÌÓ»³óhw þ~âã[RÈæ ÇLsáúÍoÞº2Í…ëv¿uŠ”‰Þ.ž K™˜ßmUÓæÓÀ*¨Tüü>dÁ|śƞ{ÉðmÚf†îU‰ûqÿûçà¶žÎß—Õ#u´ûïóc¸4)ÞûòÚ|ßü:¤¬ß5±ÿ4×ëëÔ^ 2ÅŽÆ3W•1•g;ÚÀøYå w-»7Üܵüs¯㸹kõ)Ò9Ô°¶a…™6FÞ¥*ÍF³Y·ÁÏ®¬¶¤A¯Þ²*ŽY·×³7ô¯Þ¬ƒøŠ«"9[ra¾â*tÀcȦéEÒÿáï|Uòþè.•©Jé¶/C¡b9ùˆÕYVš¹óÙòA•£ª¹ÊÞVxD÷†ë4<×ðW©UÐ`ïço 1W³dzgñ-5¿ã®G+&YÛîøŠ¸äw=}Û5s÷:{dA*{ 8žwÍÓ¦zÎI©ÑŽïŸ=íuGþþ4?f±¶^ raÏ—«wsž¿·aépv\¯»>¼§ÂðÓÍ ì&t‘nÙÍa8ÏI} n®SOœv’,ogß|~úsž²Œ¹ï«‹3ýU¼eW-=¦Ní Gô½×i›_篽ΘN=ÖM”uÎíš ¹+kŽ›myAP9©%khXeÍÚ nu‰³%Y2[÷…µw]²*ÂÀR(ë’ÏÄ »òºbj/¤¨*ký!a+Ü¥šÑM`·Ü*˸Ô{Û?¢Há…®$öÒ­`ìñþQ³õè1U2¡~é1‹dBýõpEe"¡ÞŒÝ¾{åU*¡>xÄ9¤ŽWxpý³Êò¤ú©›‡X4î®F”³Ã™¨`¾CÊTõ ž•CFêâ.Ue’Ùw`w© å%¼û¼lƒ Ó°¬¥#H›’ëP¥U™{º3Ô.2•ë€r³2™îr³R%9ϧžQÉqžï·ÊÊdÕÝ2ÃJµÂýâ³qØ™pLÍ1sP"T•é ÊðÖÕéÕżñ.üý$É ÿ;õÈš£:ôvß:õ°?ªp²B¬S‰Ñ™ìÔ7-\{žòEtl4°O©rÁ­Øžœ]2©‡kƒÆC¿ï¹–þe^çEncò²y…]n^þ鯬ü+Ü/þgï,·ÛÖZíL¼Â›Lú°ï©Á'«J«Gmæ"Ò¿WyšÏ`sÝÂj­"êQì*eõ†ët¿Ÿ:‚<¤7Ý7Ë Ž8U9¤ŒylÃsjÀÅÛ!Õ»«”}îØ+Ê!‹˜ç`-n^áiêdzSGœª²JŒ´Häiÿ)X]8dÚ ”ÈþÎgq:öŸªÒ­åýÓ‡*´–½Æ­½:FCcµ–pÌÐZÞ^P»í¹zËí«¥¦7 AŠ”',Â*!¸ðR´I¨„d&CDaÅHRQX •$•.$¢°*-'#…•H™¸ˆhT¢àý ]]‰’ ]DQ?•à "8ê§ß”ÃýÔ|Sêή9 *íU¢æ‚GPdnÅ M´ ÂBShšzÒÉôì»ÛÝ#E:Ôμò!µÂ¡$^Àn'l¼ R1b!/÷SªäÆc§OÁ‡Û±XN T²äc9Ãd,ËØ;ïZæZ§C¦b9­1=¦J,¾Q B•–¹:k ø6¥f‚­‡,×Põ ²öå»qæÅ¬Ûþ/ Uö Ýh^¿Óßã±üýÂ4£ÐVj›<6>˜9½”ï?Ó dØUšÒ*€¬¸Av·î6¤BH;Ãݶcžúù4,7‚töšöÚïWo³þÝÜ»[{£g/d8dá]©üC³Þ%8)2²Ê­”dã˜B3Ò!¶àXØS)¶Á‰„=•R鸰­1ß×Ôš¦"K•lêoDjT’¨BS?nx „E‡d ¯aTTåû¢IÐW;VªJ›[ µÿß‚\š|w¾Ž ]4¥¥H€¢BíÿÿØòÁÜj޹·šw¤¡H‰ãX÷wÉÆ±vËí+¼u(Ѓıþnq¬¯%<Í:-º3k–3ˆ$n½BôÇ÷¼ÕᲊD¼ÚåÂk€ˆW‡ÔqyÞÙüίž ëxìùÕÎ ½KûÂ.¦/AÓaÄ5ß"Zû@3ÒûÛTäl²Xœ—ªÈß“±+IŸ1§0¶®$P˯÷|Ö·j×Ôã-ø¬;dÄgÝ^{³Ÿu‡Œø¬oN'CN'óYßøK¡úëÔgýæ»åË |Ö²J»§À°Xˆ5]˜b šØ‹jQ[M"p^ªBquM«ºëR¤’" ²*Šô`wßíàÚs3ð»^®w·?›®g3â„ç^&{b—ûÏem'zLïpÚŽÜ HfojC@SUmw¼#N‡Lvä‚2Ò!“ Ýøgs·›À}¨ŠL«°d œ—ˆÑàψ&¤÷–€×å8YUQpû€é°ÌÞÖCTeÎõð°d4+³Í–…%K)¹Ê·5ΜR Gv«ßWîÓeê¿a#xÛv—ÔÈïÖj÷5òiëÙë}þ=œ½HÖÈÏ-E–É9p™r›^ÿX‡û=µêa¶Ómê/ßP¹Ù‘:QM·E@ЬSÕôØÙþÎg)1]‰U¥ú †É£,¸µ?"TTÒ ¡•†•]Ì´ ÛUµbDè‘BW˜ÊrØuuû®ËÿÎ*ã✑éD…ã‡]W·ïº‚”©àç„„U•%Mº:"¬ª<-Õ·<ú‚ þ “^ˆ¤Ëî#±¤«ª½$]5囈¤Ë!e"¤ÊU2DÆZ ô¶ií‘u9B ¾ ”›Xð"rWUÉìb7;@Ƥå@ʘ*£Zy^Û_»+AŠÑkxü´¿Y°û€7Dg gø+Ò9·XD–A•þ$c„RRˆí"lÂs×êà myu ,Ú¨K(§ë2iø6\H‹»|“Ào;u]úWûüóÈêÝp¯ZY*àú ejìòýDõõó{‚% ÖŒuÌ7G´f÷ÐMX²è·°«ß÷L¿Ë‚¦.ìòíeõwgÆ8_ºûÅ[Uuö¾E[Ñn]Ö™ ”mlŽí;šÀHÍ!å!Žt«g›A©ùéa!R£zÌ?ÿì»Ã>·¿§“5œ&H!ù¿­F~½ºƒ6VQvºd‰éh's{=Mó:Â1Q5s4{3û~.)R•°`¨UÕìw4öaãQs†Ö8f™ZrÄxü\ÕŠ³dƒÄ£ª Öpø–•uɇM,¢sD ‡§×B)ÃakjJ©Òt÷ îÒ{ –Zéˆè¯ªÙM¬ «´Ñ´kÞùj¥Î²„o‰ä‡ÃWlkQö+^;‚ió?†èL0DÄ—ùDü]Ò ¹w3ÂÝW-oÑ#™Ñ›"t–z—v:G0¯ÖYº¶×ój¥Þ%sLb^­³ä»d¡È¼ZgeRˆ½å}€eÎ*^vc²Î4Ó´µF”áì(¬×Þ¥«wàoÛK:›!¤#Hñ¾í±rËÖlQÇ”© É°5ÕyÆ›«‡÷3M*ØcÚ`¥ªsÁÆ´…ŽœÎcΆI˜:—1áÎ#@\” ßQ®’VQ–ÐV•:/>Øq/pE%C¾µž|á˜Shñ’§J']ÿ¸Omè³é ¯ŽÕ³_+Äè¼JöB;b.¤sƒlä$cÔÄ’úMäkcC'‚IZ~x—DÆFƒ‡õ’ybœ_ý8ïÏ.Ò]”˜ÀkÁ½u¶ oP‰õ§}ëlùÞ:¡>XgO€d…ØÖ^%/B_1#¯ÞLam£…æ‚í4Ó¤HÊlÇðŒj¦&€e8ZfL‰›5i™s¹9M°ÕRðñ» IÐX4MËîmOÌÀõA4}Œ7 fàZª$q®#fà)S±¡Á Ü!UÊ( ¬ë´,Òµ "Ô²d-”ƒe¥–ÿuŒáiꤙm·›Ùv)ât#lªeÍJº‚ý©&¢é73’ch•q#ªƒi•3¦¦ØöA+Á¶F¨Âi%Ùt¶$¡±p̺ª1š¿ËêCü®FAçqYýá˜*%B½P­XZ)2pÖŠ³´ÂΚH¶ûkVß&éľsŒMŽÉ˜_m¦‘0©š748ÃX§Xó+«©¢ÇŒÜùMâ1ŸÇÃ1U|´Á¦(ºÈKlŠ¢‹ìÃ.fÃ"çÆ:T5ÒXˆíåBΖÙÜù¯ûéçì‘’5ÿƒq](†)€ Æ5n³½ñ j¥. N^äWºàÌWDõ×EõÁ~ÖŠI!¶½",ÄÖI!¶Eb!¶N ±- ±uRˆmïbë¤Û!Aˆ­“Bl{v,ÄÖI!¶Eb!¶N ±- ±uRˆí~'±uRˆí ÄÖHˆýN϶©¦ðÖ%éwS¾Ð²ÕgHNÜep̤Éa;m‚2X ”¼Éa»úšª.eRPÖm‚2øÞKɆ:Òµ.SÕÀþ½,"¹Îˆr\OËÒ/)¢dæ-"w¢H™ªD©”.‹DDî^‰:¨”E""×î‰GK<¦gS”­3[w¸ö*§uü:)5 3BYrb%3mBí¢¬x±02ÕØn‚ ‘CÊh{ÕŠ€ÀBÙ!U¼½j>áëáwnÝ×ÿYÏ­½í¦þscog;Ó³'ÅJã™+ÙÉ£'H0A‘(ºÔ\'u[tY§«[ÛNVÔeÍïôC½®¬“;ýaÛé‡ûù.[&bº°ReM¶-7êK¸kIÃhÆŽ„Ñè*%ÔrÆÈÀv׌T ‡ÉÄ&Âj­Rbaÿ^½E$x¦]-!Ã"]±ŒEdù«Yýn¸k°êM‚tÛçMó|žf™¾ÀJ J›·tC÷ƒfXÔa<ŽKÃÚt? ÇÐ!—ùÍÀÄVN09Ô!—ù(˜¾Öñ¾÷J£yóm¥Š¢FtU3;Xg uöa§WDÌ«©(u –ÔZ †•-©µLbaÍ y™-þŠëkÁêDë"ÙÓ·öûëkÚ˜Ñt0¯nðï,?ÄÂEó‹¡·«µfúV«ë%]s±Õ¬B/2æõ{@ŠwóêÕ›Wû§Yç\íbìÁLL×L¥B-™WÇ-jaüäã\×4­kÅì qpŒ®‹d§iÙ«ppÌò}µæ¢-­¹úÐÿÁý¬¸þRÌ8¤ˆY Ä|@ך‰ÂÁæ3h'b>à1óv"æ1ØÖuÈ|À!#æv‡Í²LÄü!ó‡¬1UÈ|À!u*ôÕçkÞ| ¼Ku–¶\î˜ÞW¿÷")›Ìîê,O‡÷ PýnˆM5P[«3ÉÚÚ1r ±ßÌ«±v¡Î fmcFE°P®³‚ë®ZÝœ=ejÇ%lZ‡®ånŠrSëŸÜšþì‘'t]CG¬Æƃz·¡Ã3ª9“D7¯³š¬¬°ÑŸÀRg AÙ^üÎ<çäêh_\ç9¯¾ oH.’¢i)Õ9»Î%kÓvÐ)ÒqØþÛ¬Q”- >°³Œ >€û™\г¥O )R«Ê Ï«“FGeu`ý¡ÃØB¿£Î¹Ÿíá,AFö–kdwSá¥ÉÙÊwR5zÛm¡·áŠxmb<štßÌlÛЗ©Q‡ñ(FOý˯ëzkjmÃ}ÌFµïî ƒqH™Ttµ™³Q#cxFB°¡A¬TëHD,±Ê‡êA-F¾çëeGþÎf×ñƒFZAmŽÈÀtrHP ™ë1ÓÑ.Ùn/ËÔßà­(öë€ r¸Ál(Bì×ño†Ÿg Ð;d•B†Èr‡Ô Ë_Äh­q­EÍv«;m¬%ËSm§0‚1µÝ®^õW„ ±ýJÀr÷ýQûû£ZJv¸1)â÷¯ik¦ Ü-V4ήÞÅW»üÉrÒ§ ¾ªQ˜Š¯ì p‚øªF]`*¾Ú,Y†n€Vª”øj;{Xý:$_=Ü3ÿ–ÄWYÅߥÍ/©#H#$!D5ã‹Ä-µ,“ô1E©9}31E©Ó1¾;×LQêdŒï¾ž¦(õ!Æ÷]7« ©¹*œå‡Àï|ï ¹&›Y/Ýn?/ße«ÕÛ·7Õ·¹øË|ð~¢_¹ï®k3\ÿZ‚ ![á¶™c|]V3ÐÃauõÿýóïnß·Ùhô߯~ú‚7D½w[ »9dÎ0Z's—|¡V [’þÖJ°>3D1ÖJò†™è˜’1šÆâ«Z)^ƒÖ ªHÙq é;jU&µƒ¥@öᕤr²K÷}¬{Ž—¾ké1eB¼jÆÏ¹'H•îÃÂJ@1L’a³v‡³knM;†Þn5Ó‡^Ow½þ ý«#H·®ûc`î:lËÀ\Ú"eÚ*žf‘ñ«5PëÔ]MêB|0„uHAãuÐ~ó´nz8»âlE‘ÛG]0¶·wëµ w©(ÓýMÒ3­‹*6wäìÕ…ff„­ž Ǭ« ›ãYµ}û»gøŽÊˆ¡hp¾»u~< ’z$Ü]}þ¾ÞæÙ«êëò}åw}„þïû÷Ú¬ ¦gû1¥ª•XÜÚ‘ ‹hänkw|½¢òÝT·ÎžÎ¯‰ «è^{뺮Lóë–M _q™“ïÈÆe¶Ûé¿Û´üþ)R‚hÙºl>vå¿®¼ŸeŽ:ÿÙÔÿ®Î`E Óø8œ½³ŒA:Þ¯AÎÓãpEûÊÿ¿›ñ—ûv=?ö Ø:9ä¾ò7¿sCnäƒ i¦Co&æ:Õ3 =h‡Ü¤žÿ,ûÙ½íX³u-ŠÜ¤žº%(ï’X]Ú4Î?Ýú«Çç™JÃA¤ë:©ö‰0Í•’1çÀ‰u)yg¼6¼$ê}šÛ–ô›/ßøNƒuÚ³}óå %åš Žej²E*KNn‰§Î²dƃÓ`MZðÇ{ýÕ‡æò{;&Äò=Ùè…¿×kbi•½5]–®Ùïµf¹xRDœuµzLé?O«îÞ•ZC¿-ýïêéFu…»/ßmB ²ë‡ «wÈÂç¸Ùùº=wóá5kkyYzÛ{ö»?»ù;>zö #[ŒœAž~ûå{¢H V@{ŠÜ¶¨næ—†eÃŽ¬rŸàmŠÜ÷2™J¯hÿ-õÝ9YÌmw_z`zyhŽôòÎëÚüÒ©›ÿB©ØAAZOÂéÚû¹kGEf/7·ßÚÙ‹‡*½ï3˜þtçþï-<ô´Õo\Jos?ý„‰ÞAKo€{¶qÞ˜ûë¾´§ù­| gûím#kÜçnì§ã°˾§ÿžÏ>JoÖçØŸ[èh8hNå GÍYáz ·Ö•`(òÖËJ“"³â”£š£,ÜÐúCZºUŒTdÔ(™Û¿¨ærnÛcú™ºîpÌdbAȤtÈtbA(ŽìÈ"‘„jVáq²d&ó†³WÄyy3‘ÙÈ ¶ûzµaëKҾߊà6×"Ód¦ß•ž=Ifºµ3½¢™iÈ$™Éì)RÇIê8 ´®ôyÀǬïø-ÂÑß%L׈QùÁÕ·Ö9GåG®¾µÎ™ o,d­µ`DæØ½Æt 'óÞÓ+í1/Þ7ë4]cKýZ+ÎuI4k]°™èhá¨KN`÷kþ­ÓUºJ2Õj­Yyжiû]4’­ºfZƒóÖôǬsn³Fm“pØ›Ž|Þëš}î¸àRˈ¼ÿáÖX¹§ÝÝ#9Çí9{Áš¦‡èº.ùü]t?+.‡Öu•.6Öo6еæeŸ@ ¬ëš^šÊ²ŒM¢’A2’-Û‹÷cˆAŠ˜8öîK3£½=2*Ž.kÇz¤Œ¹/Xbd’•«ÄÈ#E⊂–A*6µ X)ÒÙ0 ü΂³óhAàdŒët‹FEƒ¬˜7¹ ehƒÔœ*d‘d}¤âÂe(Ö«,O{émíFï›ï‘éÂ¥ÏröÈdá²ñã’Gªx-ò÷7Hn­ˆüý=R$„m;À»„È GÊB·“þ'‚L’þa6ôÈé¿§ôOÏ®h©ëáZ˜MßöMë‘™N»ÒÌn“aÖ”]×­kCâ9ÎÖ|ö™@ û”½Ü³¯¬ ò4Íã@oÏÈQ@lÅáæ‘‘:¹"GV6ÈâõÉ\ÑØdꊖ;º¢"åý¶‹Û€,ß³3}ár\ÖùçÇ›ù'SßðÜ5“»Œ\æ ²N¸ÌÛv#r™÷ȘË|;a—yLŒÉÈeÞ##.ó¶z…\æ=2â2oØeÞ#c3Î"—y¬ß{)z$ã2F†úƒË|{¸óYÊ¡dðË5•‰Œé!fœArf¤ÈÕ×#™NÚè¨L¨…íÀ% ùÁÆ&$Æ;¾Ãwƒ,>ð Â]*ÙE-p' ²J;/oËßÕ¿"¬nÞjÜáõ›³‚ó¸7wéo•aÆDDE1ô+E¦Ø‹AEá‘2å3Ô¬°d‘ã›ú™3®{evR$ý†Ëdë)2‘€¸üɾKËï‘ñ’­Ý$Œ‹ÿ:0³ã- Õ2zžþiÊ‚q™ß.ž"I7é3—îoxÁ/c>{ßiÏݰR¤ð[ÓÍ ßÅÕv«¾:‚¤jÇ}W{ìãïn Ÿ/ã_7Žð½KÞBÏH`5c¸yíL‰9ï{uwè—Ÿþç÷9õ)CÁx7ù´È[wëÛ]ÅmKm´Wx—jdFJmK»fóï¡¿³|×Õuζ–2¸c¿i#ä;â‘3Òn·m{ú;#f¤Ù·é&¤7«I2Í(6ù.°=R$óƒx™2jû—¤˜=ùöûÛD¨ÿä3ÛÎÃ?ø÷äz´3ÞhB3AFiBýNZRÆ)gMh"H•J­‚xƒTœÝ¢¥œÁ1‹´ÚFhá˜Ìtد úà#&÷-Lïïé÷S3D3à„iFé£àµãÉÎCÕǸÛ²¨]S¯Ý}š’9&¬ý‹Œ?æ žQ‘%“Åld9gè )Xë¤v‚% roÒ×Ã>N;ØõÃü:ÃÙ1 äß®ì̧çwwû†÷³@û3»V½ú˜Ž¶½¶ëÒô<2Djì#ÃvÌïõu27~ H…vH÷›$ú2›„ûᘮqÿß飾lÑl¦¿³ô-~Ûoºº/nn· ‚DûëµuÝÆëüûû½üгkû~?çæ{hoCG‰÷W'›²Çüy|Ÿ~éïtûm;ãÇZKRܮωž~ï÷ýo›hvwƒ»lÿãßu9<Ïí1ýoëÌmçßÇåÓßõ×|v*£Ä/KÛ`+˜eµe•‡]gÁUª­Že¢H‘6Ø‚ ¦ y9ë^‚5‹úåôº‡g_½‹.²ŠÌP½ANóed‹¶Ý¿mo%ÔíýD’Î Žì84Ýù2~y¤ŽX{äµ¹ŽP3,4ªÉ˜;ñ_ÝeéÌ!Ï-EîßÒfûâ‘Ï~ú‚áŽG*OX±ïhëˆòã÷i˜}z¨G;Ò6D/nNú2Óq?Ÿÿ`£PhDÿ÷ß-ýÎ-1š×í÷q> +J“‚»ôóº´¬#r¬»GËõûIî.™·îr½ì¿ó²¬sw¿}‡/¹F"wŒÿÍïã¾ --o{Â8ýµeý›(²ðã¹ó7¸óétïéˆcc‰ÜïlŸg3}Pd…Ÿ‘¿û ?£šˆ„{nz˜ÿ®ý ¦])Òö° t.Gv¼\¶‰ÆÎ ?ëÔ7óG ÞÍg¤äMÐBå±Ù#v*Ù#¥¿w8{Ä#£ô÷gxd”þÞãìŒdرexd•6kƒ7$¤D(w s|©’ëºâû©’Öf¶63È‚7š•À’·:ZGØ(”±äT—"9<º¹…ïXücbâfŠdüt#HA‘ëÖµ¯Pµ+kF¼Ô6c •ÀŠÉi¶ÉÃÌ¥3.è3„z¤ŠZ.n™]PkÀÌ“w^0à0HñÁ^Þ-Y‰BÛÂ[‡ø$1‰BßøDø$Gƒldzh'¥À]$]2¹@d¬ÓgÂ$ ©¹YÆZ,À1kn–i“¦²:ãä¸sŠø$G»´žvNëüƒ]Ôƒê˜nC¡þd…o ˆ­iµhcWa™'áiêtDÊ&R…¹#ÂfÁ­!ˆiVyÒ,ÃY°yë(ƒüdüç7ûy&ØØ0¶0HÉ4»P­Aò²±0oæYÁÙjŒ+ªó$KdŽã?ƒ¬ÒÖfVâùN©9©¹b;‚L Èç°¦uÈ„€|¶rzv•”…Ï+=fÂ.mNˆëžíôúe ÷S3òÛŒ’=2% ÿ ì ‡Ôi“”®ˆ—[Cp”ÊóŒ[Y5K8fž§ç¸M›á¿¸<lh ’3séÍùq>ÏgMnãdü]B¶G¶@7<'³ œRÄ8Ý÷w7 ~”žFÌîÜFÒcª„il°¼1È’ ûû‘ç³»³s·ña¬œíË}m†pö"ÕKØbl€±iå{/L$‘%½AVÜÊ¿Aß šVN¦S&öMÞdAm_Ž–a-:;#nëÎÞúÄ ™þLFÉ›¹ ï]¾ÇVÝ!.âñýýò•¨\r-Kàœ{d¬ ·Õ½C.—‚Æñ†¹)†¹öÎ#Ã\1^V‡ s=R¦âv€sî‘*·†¹YÄxY6ÌõÈ(۪dž¹Y%#|Ž¿S;é‡ÛMÌËlnÓÝ#Õ»iÂ>†ä|~-ó™ EÌ^Áó6y{”ï=9wö×áìŠh \[o'Øù<dA,ÔÙµÓIE¿>Ôͬ¨»á¶dåƒÍ»ØêŸfƾ›õ¯·¤÷Hí‘Ûltw±jí׳ýö=‡¬Ó±0.ñ¦–¥ ïR™ŽL°3lÞùŠ ![Í^;|Åš±2œCLˆG¦´ Z©Êš3•C½í\e,¿™ó–‹aœWŒ]Úæ»+@%x wøŽ”à$ÜýåÖ!JÄ$Ü÷ÖK¸çç@i ÷ópöÂó9•fjïK3‚¤/s{Ëãpí{·7/ö—×J§N³m=™þÎ:¥Ën†–"÷N°çüÜ[—ÙÕœÆÀùñЄ„ÛFXŸ§H'æÂP¯äß„ðŠ*&þõ-Üü‚'‡Í©JK–:Ò†ÎUÅn·‡¶…OGB>˜ýÔ|ýzd!ýÜòas1Iyn¬ïûuü—• ¥oûûé…3fŸ0¤¢SÒ6š³÷?çûp'È}êüÏ'”9æ×ï:|5YbwžÖçÿ®ãrw)•_ÿþC||ºñò˜/×+A§Q¸Ÿf{öûóCgM8†hÉôûýXèÏâ–Ò«y™úCóÃòßùÍÆëîeX S»›ôSÁh‘¬íN¨ DâOÉqó8€c~0E ßgÁi=PA 6ògbo^ðQÝ)“‚¸£Y©øf«-bÆL08ɨÑ=xf„¹»P‰;¿îÆôP‡Ì‹"ióº`Ã#ƒ,¹zi´öÈ{oìp µGÊDeu·R% òa`,*ÖôÕÍ ÍYM53t»ò¢Žrûbz O?Œ^ÁK¤7ãâéÞºÀ+ØÞ°D~çùk˜Nßð†`ãxFÀ9õׇB‰¡Ì‘K3šIÖlØPÆqi– Þ¥’ãËâYVTI¶î°³u‚ ?;óÆ÷ðŒø=ÒÚÁǰyÌJÝ*ú§Ø<1­Ú´jqtBlÅÍýN³†~@Ì›€t•8›e>À.Q/üŸ=¶ÂÕÂúö¯yÍa&Q/üŸ²ÏkŽô˜H½ûy˜¿·ß¿{÷3ž(²À6¼7oÃ;óÏ·ßñ:d&ó_íòÛ^.32Às—ñ?ìÎüvwìÒåûw^—ÃïÔ¡¿îÃ=¾úçóëþº¬ôìu¨ÈÜo{ÃŒ$ÍjþëpL¯ŠþREMëßí^zùÖ ·7t»£73#œ_íñ¨»*úßÜ-ÝEš¿®X`9讳ù×jüÏ­«vÌÃ2¿ZØÇ{èö þ·ØeÆÙuo t|<ÍKð Ð"Ž.K’µ5Š×³|̯gŠcÀ –¼ïõ#ߺ¶ûŠÙLóY¾ÕãÀ1Í CëZ 3™ÀgòaJÓyžaÕˆÌd0'ÒµØOM÷¸¤¢hÛ/?¿×† ÷¹æŸý …ßùu_ß.‚Æ#ãíð‡GnÍ@‰vøã{j®ô˜šð[ǦÛg{>ÿ$m‡·žåùx~?:zç“íðµ›è ípİmû·Ã=4*•´¢Ê×+µâ|®PqYHÎK„¬Ùìà&Tö!ÜX…Ê?d€ÃĤrN¨‰K J|HcžàwJΪµ æÊ>ä¾Ýdˆð; FòéïB•œ)*jP U ÑmúÞ‘ó`vÈtEhúþç¿hɺ-œ.ótó/“Òœé9/ U³´Ý&lÿŠŒam"U?Œ`£”ƒHuØEª3A2"ÕŽ3*Rv‘*=¦ŠßyÛðƒ"N!b·m ·)†.fÉ’)÷ ”xƒTl.n(X‹¢`–XX-Š’±}ܼ³àiV1+^{þÍŠ·ía£„ 8Þ|®.-²âØ€#V°#Qh¦`=âïp¼•¡Í Fê™Ê2}­Ð8Á€#š¼(5¢HfínäÑ@eZ`6XU!ˆ¨E™s2fK£ë2.'°òõP*EJºo$–î‹R&¤û› 1’î írtÛÒœàir[36³%ó&O]£#HñNÙæ#DÜ ¿ÀÈ¢]ôÁÊ2AÙÎŽè/‚„ÀÛ¢˜þ"Êêý%ÜÏêý%\Q•,ZËõ@˜¥æÍÙÃhSêdBéDlÃDY§\IG›×½ú”N%ªŒ™‹_¶A5¤HJ%Ã:¤ÊóëMr g 7“Dʼn½m# æ÷@Âx—Èn´–"Ó4:¤Šç`[Í/l(*.¡ÔÆê„;_0ä›Í§d&HA$ ½•eÖK_f¥ H4˼Ñ5à 袪Ø8„`€'ª*I²Ü3ÀaM‹Hñ pøŽ*Íȱ°DV¤éÎÞ:1Xf/t΋„!H¸¬èpd…AJæi¢È ‰ä[+´ú`oHÒŒ`'D]¡K6£Þ(滸¹{ÌSê©«Ú‚ÌKƒ”Ãuá¥RL¡cób€³L²ö’ªdJ ÖàV€ªLr߇;üΊ{ëìN’"EBˆth2Ö:D À C“J³ù”MxçU²°WÓ4Ydéâ‰m`…q©ÈYu(Êâƒ;$$<È"çÔ G’EÎ¥»¡$6Yˆdî½™7ÍQá+.$[$,GYH^k Ž“’ÉØUp0*ï€Ü‡gTòÈJ%‹2ým[S î|Åùœ¢"¤d[‡Ø£P¢Öáû&úÇ~ AʨÀu Щð¬íL,Käò8Ípv·wÇ>¼!53*nnqþ%äw'ÐŽ”eÎ:´=¥ù¿ ³‹”òyïH×çiKØs•’!TXJ"|G%çì¶ù R¤Hø‹Y?ÁŽ e‚*`_О U q,eɬ‚6ÇŸpÌ’‹Ä²ŽçAŠ¸çŽ¯ò¬0Y¢Äwbec£¦Níü{8¦JÆW…:CY†H¬X|(X²LÄW™5̆e™ÈGßã«Æ¾¥wIãõüö&m±eæ€óíæ‘oN÷ûØm[Hօͬý sçnÞ¡[¿úaê)2Á{NÍòø%H… bökw ¬_ÁÊê=á`óA³ £Í…­#Èò1k§õ,(²ŠòÞ7ßmŸÞê:Úp™Ie¯ÔìÚÆ¼È=AЏ+è8õŽ,ë£Ûy§†¶Êxµ3Br+Uk0æép²ÌÊ߆N˜\ÉDì£mXãØGY©ä Û‘ØGY±yóx†­TZOb%öîð…*\U¤]س)%úÐ2Ž’sVtö"AÎ13ìFÎ9œ]%Ü"‡»¬Þk€¤ Ãs1jCCNÉ^<;6Ý VETšž­jæáŸù5d"xÑ “{zL•6؂ٵ¶—þ矦 ^œž¬C*”™æýÜïlí„©H²B!‰ävnhJìDð–Þ4Ü_ Å’Øg?’Þd>£‰ ÷5ÃòïF3s¹a­lÌð}^RúÖL³‰ËlE׌ݷy½Ÿ Cª÷D¨¯vúþ2¿®]çD‡vr‚µvs­5ÛŽ°NÖ9Ñ¡5>2ÍœÝÌqßMCtŽth{ É5ëç¶™NËüK¯thŽKÿØ‘Ã2?~¯Yc¤ÍLÛ ÏÍ%òôôÎgê6röôó<5‡‡„2ð®®¾ÕÎccàxã¡ÇZ;êµ9êi^fX¨;¨„,¶ëe_\Ù;µZ©äýN¡*jBâB¤œA:Š qȤùÉœb©Ù²..i¾'‰ÊºšíIÎÏgK‘Çž¤7T|¶ó“"S=ÉvyÎ^óNmçòNa`FÖÛ‹o6)Û¬´ÅU_ºçs¢ÇÜ_g;4^†åñü›~ŸËß–BÉ*Q†ª=ûž¡ Û}d•;²uƤýíïÖÿµßôìáu~‹[mfzP÷:ÿkïÓå¶K}žýt7«»ŸË*B’¨kÚŸºë:Û°«Ð ¿Î{S”Jö‡'º‹HbŽ’ $Àxh‘jµ6Ãx€–ïôZÛjµôÚÃãÏ«¤¥äïñÖÉÜÐw ¤žXêj×®aä+“Uœa«â„c¦Õ¢1Ÿ”é„‘-×&x¬I͹³v–W3¤Ht;‘‚GÖœƒŽ–uÎ9ÓšéÁÓ¾d-+P/ËÏe ûÔZ$*ÁÎÙd-Yp´óƾ +Ýô.æ™SŸgŠŒêJ«+})2ª+íHΚCFu¥ÙŸÁåØ!Ë´WùáìUÚ«¼¥ÇÔYgY¬ jÅxé[ÝJ‘"Qƒ_ƒ˜@Ö»Á¯`u_oÏÝ'$1PÖ%[±‰ç°¼uzçqEoH•~çGRCªuz_eû¢aRsP[Å>^ÍÔº6g*—T÷msdØ1¸[«,çŒk¨ªL|0°õË •ÉÊc_R™bH|[¬: Þ ÆO…ù/Ä_zÏ”ú¿Å#+Žhi9Ã=AЉI—T„)Óž§A«¬fzƒ8 Ze5svLÅUyÆõ^ÐŒ òœë šk‚ûɱZ¬¯ tãR¤ÒÐ%“PlÿÏ*g–—$ E%“Pìµã$•LB1H’„¢’I(›d %¡¨¼HºÂnîµÝÇ,Y vp¯uHéÛ[ïÔ·WyÅImÆà'¯>:LÀ·É8Lt»ÃÄDÑJÆî01ÓcFéüÎa¢'HEkr^@³6?§ÑŸ±o,ÒÞÏövۯ݌Èøb)’ò-,oû6ÙfÝú/99¤ôûÔ}em×ëÝ÷jÛ^ãt"HÚt«8ß¶TÝ÷õÞ½N_0‚íÈ}²üß¶Ÿ¶OÒ¾¢Ccvªf@PßµÚl—b0ËÏÏi½~d…‘ÞÁ쑇Wëv¤>ˆ¸íMš‡±ù{<›† ëwˆýŠíÌá÷ýJä‰ûÅažŽb¼(&’ÃâÑnü@rXR&ÈÚ(‡Å!U¼ÿÐ!+%8"NWB1Žy8\ •¨Úni_6 œÀkëTP¤ˆYéWÛ8SFM÷7äá˜*ᡊdšJ”L !öôV"ííìráÛÔÉcÛ1ÃwT§fX³Z!3¬Ì~ëdP:‚i¾ŒÞ2g“¹Â PIñÆ‚ šç:Ýï~oª¤8Zî;?›-åÚ¨à®Mûj½ƒ»Æ{ I–QÁ]#ž öšz‚Œ§Õ\Ü5 b#ýÚwPwrgn.|qR²ý‡¦ O“éðo1Ô°N–Šï ¢7Dqýp äávg¶©â™ïJ‰chÈͯi§¯ßö:}_ òâ÷Å÷îç|ž ²ð’Êýwî»]söŸ¾ñndJ‰c§÷æ<‡Úemϯ ¨•ƒV•»÷ÉôÕÚÚîAÒÐǦÖñk<ŸïypIñ]Ùï¯Çã›Þ¥ƒK \×Ö­)4böRÍÏÏôC¡"Û÷ ¦?Jɱ}0„*ÉXòâF¥C›Å!Œ a4 Œ×Ò<àæ¹ÉÃÛzOß÷¿'A ô2ß\IÄ–ìÖŸÑÛP;¤¤ªtL`sm`q¥Šw#Ÿ‡ŸŽ×u‡• ôâµûÙ­õe;NÏõ‹ Ëw£íŠž÷çëÛ#S&Fù›Ó™ Å;½bû¯æü R¾™c^Úñµ>[‚. u쾆ùçå‘q[72Ü~š_ÿÜ yœæÂÈpÙîü/AŠ˜_…ùŽþß·AJzç[ÿÅ}nÏ• UtdøjÇÛßú$È"12 {3U(fdÀöf ýïŸãÍ?ß—ÿ'ìJ²Å•è–L'İæ•çä_n1‘¸-—¬ì‰˜sÉDf«}‡7¼Ï¥àd[H(™óT+d(žoü“h Ts|¡Š©VÔqG­Á°ãNÎÄõÄq'çb:rïR¥sÊ ¢ˆT)óu;¨Vó$ÊÉ«ŒÉ#Ö¤¬7#TùNDr³~i]£ÓË…)¯ò)Ëš«•Zwê(fØõ˜ö Q Ú¹½> ÒŠHþ@ʰ‘†|Þç'Pƒ,rKÊZGMÊçA†E$µ‘ŒYnï<Ȉ!<Á"exLÖá 0&Wñ¯cÔlm¿ ªbF¦Á:vý™…Çy­±‚ï¨*8yÄ0BˆU^ fõ‹ÉNy%~ñ2ôoò/.h~L®$c3è¥%¼K32`¿ÞS­¨°‰_oá=®‚~½>€Æ"CÀi$~½ñŽÂnmÅ!áZ]Ív;™ùAwŒ¯+«÷6žÇîq¤ÇÌÂäå6­Ô"ó n½Ü¦÷æ×‹¨`îÔP¤ˆ æÞ›k7ûŽïʾ¯cw~¸]¤EÊHû̬첊Ië Aº;©˜ûUÅ —”Fµ`ݪbî 2¬#ÉÅ!c,õ´ÊÞŸhÎæ+Ï¿õoÔ ‹Úâ æ±nßðÒ—Œz}0"]‡¤~&ÄÊ[MIßþzrHÖÌpñ)ªNÛ"…EkÞß¾™°Ü5ŸûS$)“:£îráùpÿþ£µK狽¢ó¼|Õ·¹8µKáùpNAs±Š¤©¹Ì}Û\î™zÊ¿úŠ/©¦ãïËmÏŠMœûAYd ÃÂ$v—E"8fg=³³HÊø[güLàýLõújà Èx‚ìjÏïRz`\‰Lz™;&b;Q²F§—=»Ñå±iB….#t1ÏýÜûÞßOœOôjƒ!,åÞ¥^³™qNäòT¤y(/Ã=£óó;<²`Ê?Ãr 2YÆéþ©Rp­‘ïãù2 -¾GÍ?á áøFšs Ë‹"•¼}(l#‹´úeƒï|vøE¹£M–°™÷hœ'^CÔ•¨%®DIT!³Œ.#¯Œbã5´-{¯Œ"ËñÊðWÄnÏjômfâ—/¾Äü~q‹³)ˆ+ÑÞÛMÛ™äÍŠáWdU´ ¼Úœ2ÿÍæÔYŠüÀyø,Þ »ˆrDÖ²&ò”³J®;?Òú¦þ®øÛŸG¼`ʳx‘Eó~~Ïs†Ù‰%‹ÛýеN¾â\ðîˆèÚ™ ü„µREεF°Ê¾ðØ€¦k%§;dÅèt±+²Å IÑiG “8·ò„·(E‘²‰¼Þ[¬(ø|7ï Thu¡ZuÛ8Õí½þœC¥@m¶òõiê+A¦DŸ ȾŸ>Žod‘F6+‹H!§©îï5Aæ1äû¶A¤ˆž¦KÓ.)bÈáܲôÚ`­µÈË<}>EÊ r9u¯—ã|[doÝ*4Èócj—Ë÷NïüÁÉ!ÑÜœh;Oõk5Oéû…®³ÇtYúK»ôôêWÙ§ƒú8µwõæShæ¡úFÙÖÐejN¯çš»×ʸ_”zNÏééZÄô„h]Û±{#wä¿W%ë•7ú±±ŒŸ .7›Ù7 à Z콉¨ÜšÖãM4oB$lVº7‡/˜X“‘´· &Ö¤'±&…ÈÈ<»qÙÒÃüz‰9Ðk!sPˆ‚Íž÷…ÈÇšÓ a͆bMÂiÐdÌåuñ…(ãëÀÕqÈ=÷@\iñBé¿’qjn34˜-2è8Ô×ÇazoŽ™›ÁÆqÈ¿u2ê8Ô×ô.I¶Å» g$¹ïâ¹­)·w~u Ñ$ÎK§·ëD>«EyˆìhLUïhH[nK‘!;š2áȈxGS¦ïhÊ4гû>µØøYÎî.áf[ 1Vð†fuym‰ËkQæ¼;ßû”¿4Oýþô<¹ªˆo¡­Œ“«`¼ŸËD*%ãkgìîauW–lɲªDQ–t͆mä‡ï·é¡ÂVâx ½9ü²=fœ¾veç_!fË"cìüeØ"£ìü’L-RÙä¦TퟦäÝê€&Røð—p´‰,2-ךRõæ˜y˜Æ„ùñEYý‡U½÷çÙò㛎ðã-2‹¬ÿ?Þ"sJc²D·a^¦çÓ½ŸòÀ¯àh¤"ÚdµN’Ð’,dÊ  ïÁBfLOKcaæ"-!ŸUx“eÁϪE†ýKI¼Z!|ãönÇîkGÓí¾¸1·c÷•+µR|¹µ ‰³ÙV®šAO™F={ý¾¯:pž½µ÷Æ,ªx¬É1»cÎ#ƒ„‘YäÖÝ4Õý<µ@é(ªý ðj)}n?™QT)CÔ¸›ð4‚Œ8wKï– ó¨‹;8tŒC‡qq÷Õ0äÐ^dƽJ¯åÕBµõwÉp©™^ÓÖsjO™‡Ü4f­8gøbãÐaôo昃A—G:þüµi¼ëJ >óÑÏÚØ¡#è6ë%äÐlíû^F•³­ýÆ×ŠQs}O³kkïQTE$ã@?òswƒÐŸ"ê»±¦ŠÔ¾¾‡[¼›öv¿ºâ»o“ønÐV´é‹þÚcQhk/u»*ɬ*±WBQUÑûÙ÷œ‚8tlÞd5%Æ)GM‰Ã÷ý†Õ¯ð-ÞM¬žÞõà,{q á˜›>#zCÄá—$¸KâíÆd·D Å!çz‚Ú¨z&Èp,”!Ë΀Œk§W·‚®'È4ä1¤Ý ¼Ý"³ R» dÜ¥æ8AÜI0éÜì‹Ñ®\w¼+7Yêˆt.ûwê¥kttHÉÔ r&È4¬ÇÆkAÈW¬ûˆ8(pu'ÃÄA¼‡‹[ݧoûc&LlÙ‘ü,2x³#}»ˆöm/(r'IÆU4y®sÈœ­ù<‘0ïü GÜŠ¤`®]³iúŽ C´U— ÊXÝIv^¸KÝÊZ$epÅrwN"Ðs(hMr ãc9w? EfÎzo­;/ÇËò?5‹„\SÓÅfºeÓ" g¨wR;³ËýföCÓŸ¦ÓÔ¤ð½õëµ±öïú8ÝÆ…þúZ6»ž‹‹›t0ÐuÙüºtq´:6÷¶~›³ºôñÞmŽY­um&x²Þê=ÒéUóýNIÿU›íú›Ø÷y¹½Õ4C/)‰u‡´* ’™·Õ[U+‘pâú}T\̬Z)Ãx“~ážÀMÎ7 EÓ‹4åɺè˜/UCÈ<Y¬VÞ—úqý:d±Îx Øå{trBzæ4šÞŠÚFW‹¸g¾—kOóâeÐ É »îý¹&È4웄³³D*£¢à™dgYdÎv[Ô:È?£Š£äÕžX+²¸HЄˆ_dû”-ûu6óë<Œ°VYÊù½4ž$°GÇ®ž}îg¨g‹Œ éÜ0ÿ~"š‡ÐØ<Xeã§óàÎg”r¿qçCÐ{_ìëšh·-po_UE»m‘q’d¼Û¶È4æ£â «"+#¾^«çIs„UXVF|½V'“®÷w¾Œøz­©;õìïgK$ÐÞk¨–/2ɰL \QÅeCíDø¼£p ‡_5dU4…£5)MKù^ÐgÒl Oä1AŸ^1aAŸÈ±øk“åã¯Ežð¾ˆÐE9'‡1µ“ž ÓÐw4“\‘gLÀ/ÎyÆDãú–È9‡:ìÊ/ò"â\¤;œØ¹HäqïÊ–8‰\ÄÝ¥ ¾£¼ä9q~’ËøÊ®4oÑÍq9rR×éj—‹]ݨ¥¢ºž±÷O“Vj­ó†åWª1L²Eq`vÛ˜1*Š„ΨYÆï䊔ñílÉ1³_ò6aî(rÆÕVß%¸óˆ+aì¬Mô:ÃŽ—“ÚÜ›žoÚÿÞy•øû¿õ·Í7×hÆæèW …øEº+Тü¥ÏÖÀ3’ÌI÷î&øõŠå1 #Œ´âÀ‹ï@D DÂ{úY[¤¿¸÷À3>›ó¡RóÖç;Â1s&A´Õzƒž ÓhO¼@…(˜}9ö¸¾Ë˜]w^P–Ä¦ÇØü,– ÓH±®G˜e°ˆuŸ@Òx!’ )1„ñ4´†ñ䟦dYðñ¢bhQM‚ô)ĵë ܆˻­ `ï5AúÀÔÏm¾ ÓE‹ÌbÉÆhÍP&{—6”lÜ·°‡.“­ üÜfâ½f‘A—¶‘8¿YdMKÞž§Œí¤fˆeÊŒ6Ú+Ì?£,À¸wæóy¯7‡ä$ÞZþ6Á¯#Vš¾öóí~3FTÍÔ|¿j#+@”¾2ÿÁRJ5ÒvÏæ>ø;_p¥'8¦ˆì ï qg{/Ç{Ã’•cãéîîäØxÇWJÎÍÉ3EYñRJ_{–‡xGSÿ+pþI`‡R·0# ^è~Í {0ÎˌˋÓå÷uà^h0‰ª•²ø%‰w ÈëQnÎéqPãüÞOÉ©aÔúsý‘[; ì&wžN°/$£›Ñ®¡~-KÞMî9ÐcFÝäêÆ_Qld|ü´ðŽ)ãòaÍ]ûúk¯¸ÚE:ûQ_ Õ¼ £7î¯þG¬4²é.í… #;èïàœê¯z£†Õy¸­ÍÎÇ];êpz¤å’ëüp­¾Ã¹ú Ÿn–›ÓwÇãóÛÿø_÷¦j:ú{ÒÎÃý܆óùÜg˜7}‡ÓFµfȲP5™¥q,Tá;œ©¾ £”ÓÕo¯¾c‚´L–¿«óðº+Ÿúyü6ÓL¯¨Œ¦,°b©r6Õ—ªEÅ"³0rzªM$Eæn´QW~Y=\ÎópžGu§è¯~\ÒùAú+~ ãK;­/ôŠD¨ºU÷×W³=Ï2Œ|¾X­Y¤Œ¥OûÔÜëMCîåÀO)’u/÷ü”wMi‚Œš;p‚ŒE†d´ÝJ±È@‚Œ:OÂ:±È@‚L£ßN” c‘"î²¾ùõ2î²ÞÐcÊX.L ë’QåÎ$¥¢ü-ÏÆÏ2I˜¾®Æ¸ÝY™p]!œO^rÝÝΘ-‘*wW}=ãìÖ2É™|%Ìô/“‚Q»šü¸KŒ©‚nêƒr¢LgåßdV•‹ðËhßк.#EÒì×çššç´,µCV»4ÅÆqÃ'µ‰»NAîj,ÖbèñgŠÜîã›9©#\Z‚Äê¢Kã5­ºÐY„¹Ø £Lãû£žt”>¥bcÐaÒAGéS*B†ºÈ £L±MÄ^9Ý€E[™25U­±öófš°Úд5%îÃnž»ZZô§áüpÈÌÕexjû¯ãì¯(Û›7ºÝîMÓê† 3T‰º¸ÍqnNôÎ,’äiCßðç|¹ü¸U¥E!–„úBÌ"­MÙ_´ë±îÌóu&H¬*Ó{ ½ã;éMq{éyʃ%Ü–iÎfK ‹îy„CdU¹~ô&}mjxÒýèÌsÿŒ n­¨]ndð}mËæ¸Øñó=~ê{wúñÓ÷µyá”=çú®_¼™ S¬RS¿}3¬ü×8Ün°ºHa·ûý«¿w'­ÑêóÜ ×úLùŠTÏèdC ïº10õïã»&Hý†|ÿÓÂ7Cæ0ç©¶…]7Ï3=OŽÚ¬ko>V¦’SN×¾zPúþ{Ø ̈,2h׃8?et/c£ÿ½W\b”Ö‚O™ÆTøÔË,ꮯæAÌ.,³„ÓÅ"T‹D> çs³æì4}×<¯ÀÖ,³”Ë:\|¶Ì2vçw»e–sû8mR1dËÀB³ö¾S¶„=ɱÈP戶9Duo‹Ìb¹Z>sÄ"™#fôF•g‹,¢ \9b‘¡j¶f䣺·E–ñ¬®ž§Œè6Pê\™q»r£_1a)`~ôÊ¢ñ9&e&Y­§Ï1)qJ…›ãÌŒ`µÈÑ¡Ì*–Q;øù(«†¥P%F³»Š™A¢ŠY‰] ö•gT¯+ó$Z쉅`™ÇyÇ=éñ•y­ ô$ï¯ÌsN;‹òþÊ<¾Jo›§VžÁy«þ*±Îµdzú=ѹ–9c}f´È0&ç%£4ÅZä擺·y—K·Ì%SK?!®}‰-ëƒ.PÉô4O¶ZPÁùñ,‹:òLi<« Ö!EÂguGØ"ÓHÖ ªì•Ø^~ÃJšIÚ EYI3I´È,’_ƒÒ-2óŽá )2ö A3W‘ÅÓZWËP¸öœåG{¥~YœŸÙà]7ÊBðŽbP«,1Kè ÌH‹W…ä˜$HgP2š&<“$»²¨˜>N²+‘ú?¨+‚$;‹Ì"Z”dg‘yÔ½Æ×C© Ë…02–‘U{mb)⌬Y¯?™^z‹õ}…ü66^S Ö ø»¯û< Ï|˜Žßö2‚ÓL7uÝÁ*Y¬ÿ£wg†™Þ8fz‡êŸÈbÝÍ . ü4ãçG½õ·#AæoKªúΛþo2²Xwl÷ 8Ž4ÓûÒÑ+BÌtjÙîãqž.Yòrsª®Ù©Ñ®&H‰ýN.`#2ÓÝ)¶-²ÂH;wè_Ÿ¦±¡wÉEÒÿ5."kl§&Æ+$4¥4ÁûÝ®éx{NCG¡Ð[­Y:ÍÓ²®Ïé?½^¼]î+Û_ LÃÒ¿ …æaA~ñý¹æŒÐB³`REÄ4J áoíYå?PÁ‘ÓQ A)DЀÀ‘Y¾~¸eü½3;ŠLcÄ“nüΙEH"HÎW"—÷ð¯:I)ØZd8÷ø†«I£ãéfzöcëLr-²&$ßpÁ"cÑñ—çàVÔYF²”Ï]ý¸d :^À8:Þ"«§d|¿.|ÂÝùÃÞËM§Ì;hI™WoÝæšÆ^QÆ=§'΀2É¢}9­rn€O-“œ+Ä ø-âÞ‘$ÒM&"îo¶± ãÛ™™(’e"¯‚ŸçeôWÄmRnz>ž 2Ý+Sõ'•©2=0þX™*ÓCthÒ}$¯ç“ØmeÇR¹éÍ>3å\ ')÷n+› ˜¼Òü,8¦0J¦‘©à!þ­ó¹#÷…‘"ƒî ýê¾0dÀóC:°WLKÆ!{Hìà²]¼¨L™Ia ƒ»T±‹ï\)=‡Ët±t\ØÍt±Ún~vÏ÷«ë2sêLÃ¥‘×öÚ5y&È<,6Üf?q§Š £Áb}Ýܦ÷æc?Oó·{ÐûYE‚›O’‘Y]÷¼ë“YÊckÍÛ{ÈŒ[Uck™eQÂKlLd–G k€àY0S‚žfàUÎÃþIöÃËí4 ¶Ž Ì!mžÔ ¼š´ýh}Ow~4™í†úàÃÁÕûÃ¥¹O¯™ shîkêõ:€ª‰ë=6¯Í¯aÃ~50Õ-½¢õýüßÓ³¾^\ÏúÝÏ÷͵¯ûÃ]­V×¼ÅZw¿ =ÏÕLn^‘.ÿ·î;DÀ°ÈjEš/n=Ñ9x2¤»ó‡}²€ÚNÕÇfzo.> Ç*˜À€íóL£Þ,?Õ’]‡¡•e¶wi ¬¬¾¥ÁYÅ84·‹W[HćÜ7­GTЗ9«EBáà2OîM‹TÞ2º%˜•P.2Ï"¾¡†gˆ|C%a9nÒ<ˆo¨Ì­‰m…;Ÿ¬ŽÍsyÁ”Ôû¥†²ˆÌÅ6ÉðºæÓP·m;¼Ý6)Gœÿ¿ ÇiVý²šèÀyCæ%‰.ÝóuqHÉóx› 2êvèÙn2¯xZ¨e€åT5zF\ùûJÏH kýj1·>“¦Õ×:Ç)lÛ0ÂX'¦½]ã°HYu¿w&”ù¹–øê|ì"¤ø%Ù̹0…kï=Œ\¤(˜úv7•˜Âµñ„l5÷{8¯ÇßíqT7ÝHi´ÉêwÑB²MVuÌŽ Ó¸‡7,™DÅ¥ù¡ yY¢>*=á“Ë2a<÷0Ÿ\–Ádƒ»u’~k—'7I;8Ûªëï³Úoß š¬ëÝ­Ž@“Aý¥¤¼¸Rd,òçÝ\ÆÇ… iyñîF°[û<&‚,ܲžçÚ V¿þTK¶… åEuÌ¥yŸjX±¬È’n»në1š×üy}2T^Ôï./®È*P3Ô*Z\3´wþéIâš¡…ü#×±öùŸšF þu Žš1¡‹Úý>¥2¢ŽD>#Ë‚•Œù@TY2Ëb$(K6ALð@˘ùðjï±Rr1Z¿7eéçç­r9àMJy`Mãíð¥L¢†±=‰á’’ãà.‹Œ1Q —”Ç\D1\RfQ¡MO¢}%â}ÿç¤Áv:ÖÈODzˆ‡í‰Í  ¦sáZõ v R†º>.*íÙLýu&ȵdùG/Ã.×ó:Å«Må8¢²ÝÆâ ™‘ª÷óþxý1£¡ÆØ¡ñK&)ã˰ “¥¬ØX‰Þ «WÐG¯²Jx³?ÍU¡é¢¨¹–$Ñ4!s-Ø ‘hš@˜kIMŠ¢òæZ²Ú÷/aìL ce(ò$·Ø0VVy¼X¬Õ‡”V=ÿcoF:?ÏCãïßéô1›‡Ãl·Æ‹1„‡c–Œ,ÛÊŠ‹[Ä"w‰Í‹v¦@˜Ç/¾‚±Õ…-|…ƒ\ò±ÜÁæü¹wnÓWf ªÞNªM< µÍÇrãêîËfŽ3Ë04ÇU‡ŒCy‰huÈ~‰Ù\àÚó_b67È4ÖôL»Š r™p'¾B]sÊ\4&Ɉ¹X˜èÎIë«üyJ¾9ø_—\²}@²òV?¸©®ÞÖ!Ar[y«Ÿpò¾ùõ"R]œÆû抩.šó4ÕÅ®†êbå­~òïŠ4õÒµY÷_úë2ÒSÓaG¯½ŠT,o¿æîü!V²€Öá ‘:ätÄïÄuÈ@‚ýâ/¿Š¼NÖ´‡×)9p.Ž(s¦úÅ•È'´T¤kŽ=$M—yHV ÷!cI‹L÷Q_Â1ó˜ßŽš¸Ç¹¿á˜ÈËÚd¹œAç>¾íõãšSU‚Hzɤ}À¬›ÊÔ¼Û¦x‹ÌB¾+í»¾\@HP%ô$÷Œ&ìúR!§£]ŽMm¶û3Af¸fxY[N'-YóuH‹Ì-£ ¾ô˜E°ºxžoËìßAº’>?S­êÔíTC½ö•’h>y„lžÓœO,RÆ|’=³¡JÊèbµ7‹Uø:0³a¿üFiönÚ/þQZD•˜Å?N‹¨0_H¶ô;¯î=œ*ÏW°šJmd¸ÞùóðPÛ^·I©þE˜ Õ‚&½b˜ Fm ^XUšq™Z½ÞdwG„Ñ.Í9zJ?®¢—O3‘¤8]3ÄIqU*¸Mß2ø‰;9`¬bï€Q¥œcvÀ¨PŽ ­Xš±yDWˆ¯@¿÷Æ´­Gðv¨PÓÜ#ÓûRO3<÷ì€r«ŒÀÉ^ѧk>õw‚ŽEfnTôH“[u½½zÌÜ6kxgs]ߟ[ûŽé¥P''šê»Û4NχkÙ[¤Ø;Á¾íÛÏnk‘¥_6\­¼êg~½~nßóB)½Ï’—l Ërë.›+ª<ÒèˆõhskêEýkƒ´­Æ¿Ø¼é5×÷׳}m~~âi+~Ðþ²ýwþÐkZÕÁÿýýcoéúÉ×µrè–ÕA³½k­>êômÆns9UYbÉpÿ¨ë;QhA¡fW¡ õëó©k èÝ,€ÕQÕåÝ)´ŒwçüÍJØ ¯ÁWYÂäSª]"d•TYÊV¬ÑÂ!#Ò2Pú«,ž5ô*‹ggÍĽƒ½äù£W™ˆºJÏĽÂÙD›tau?—ïé©$©ç'KÔ×~É£º›jÄ2¼¥#Tä*#DÜ_ülÍZgßc¯²*žIzìÕ¦ËMgìÍYå Êĩ¨™Ær²'(T›ÌŸMpÓ@÷¸â“|ã{•çl·s²L•¬qçW9'…3I‰pžlC»»R²Ty´WÈswk)2殡ÝÝè¯çÑt Æ#«hÎëLüWªâÀñf‘ÿJE¼|Brx늨œ¡éˆœ¡*’xB¹Îø”ªì½\&«ÚŸ/ÝäÆ%Ò§™*ss¾ÿ¼`eÜtöÔêz©;ØÊ¨¸sˆ|j×õž ƒÉô3!ÿWEÎ&õùL•ª(˜T=œÐX‚K_Ñ9pEå/‘þ×KÞ{ülªB2#ƒ. ÁW\TLCà  A¦1žNí÷ âa"4ÖÞö"aRàtµF‘p~KÏ`®˜£™¤îT"‹8­êû‰V+‘GœVÍ*9­V"8­êçNöÜ"9­ên'rZµÈÓêÒž^ïFZ‘GœV³ŸÑµç§UÛm§U‹Œ9­â}üŠ”‘†’ÆT¢àØ7µ÷ů|‚SU>@cÐ"³`™Ë°Êý»TDüÀ¬ÚâßOÁy¡iE†eþ½Y3À¯s¶3šŽ #톳°MÂ×.Yâ**‹Šk)4è×Ë“gÒ¯ÝÈ@Œ_6œDâß_•i„aìto\;ÏI¬ñKÐzÜ ³ˆñKí95™GDQúuUæ\ž7²¡¨HÛ|Ÿçím(ª²àƒHp]•q¸v}“áqœó&Sdºçêµ"æV%ç͉y£U)#>šf7|4+ÜŠß$ÏÌÄGÓ"cf2ÈG³’Ö-Ï7Ü*™pI’¨åUÉtßȲ찮¹k«· ’aµÕsÝHCf‚´Ú5¥P]»AžÎËszüd†’».wW1Úv—Y‹Ì ­cuknÆžÌG¾i¿aƒ6ÓR·} ~ó•7 ñFuÙ’3ÃVdNp­Ç2©*b:ÏÅí eñËy6ÉœçPdì<ç:Ï‚Ipêð;/E$±Í6Ü€?XIΣ›´TR2™“ؤ¥ÂäjÒ¢~›´Xdî´ä—;_|ïï[#Ÿ×J"–%Ñ5SnnÓeƒL#Ù˜xE]¸‹š8¡ÆR%ÑîК0vd홄1`ìVجcÇÐt 3î!bE¢!ø;Œ_*LCåXÞ`~¯Šßr,;‚är,é1³ ÿ 6g¾ZŒMHµxEN=¬T±i©¶Z o22mØV‹ï¯Kw{ùû)"Õâf­7GŠŒT‹ûéùXèyÆ«Åí Õbýv®ìÚe~¼—ñ{Þœ§ Ô•»µ® «‹JĪÅ×µZ¼9¦mz­×ýŒŸås=ûòAµ¦èjîèU­¬Nßf{ÔHµ¸í–þ»yôY(ãl4Õâ™>ÑmµØ¼ÍÓ8Ü_¨®k¡E¼ŸûÓªä\“ÕFÖ¿{’uMFc8¡ÀìÜ £Ë!+.ÿÐ ²80f³¶^t«P…L¢+ðÓ'2ݯBÍiš¡qädœ:εí2°®6©Gjt°©G™… ÖÆºv»c‡ Ú|õÚæë둜†ÝP=[‚LÞâç~vžâ™Å²w@Ÿá±$º ‚²ˆ’zúóxƒ]§C¦‘< µìÉPu†öGO_‡,£9Ì3V»+¤d,ãÚÝ!ÓhÞ”ÛS(dÅrÿAëS’_Ô` Ü%Âùï5¥èçþèÜÓôC)2³¾ÒŽCÍÜÕŸ AZòу\×yžŸÏŸ‰ 3‡4ä#ƒ4䣩öo]’ßbK>r”¢Ó}ÙœgáVõäuX&úë”|d.ÉPŠK»9&%IÎp~÷Ç‘ -ùè¯;÷зïWßPd匦Ëm}‹Çú:-Í“ž§eµïC½}Ø«‚fñ,NQÈœå:S]!‹Ð`gœû~8{ÿë"êÀÒNŸïT[·‡$²W ÛëíGÿ 2ÛË'g È<ä–ÒN‹6\Z²¹¥X9ÃD" gh:#g¨?YîE ú~Þ½HÁ!ex!¨Æ¥¶£÷³ ‹¼tì’ÿŒËeB‹s  "͵BÊØtØÌXˆ§q;ÍT‡ÆmqH¼g±sPÈxÔW¯¦„Å•VÒL°ìá>À@Ÿ¦qvñ„”é ÉhØuИ ŒvÈ8K]Q_^à˜…,~1+YÜ3JeºŽ„pK+…,#æ/kPNsôWTF"!Öø›®‡i;-#‘kÛ¸žýy–h‚ß•ku¥2ÖžÚ÷ûý<Átˆb¤ö>tÚǦÇ\—Êÿû‹ÈiƇn: ›cæ¡Ø÷Sz²b£èš&ãìÀ¾KoçáøEì¢ Ùú+ÊRf{Œ|¾2ûůcdþ‹_ŒK(*ì×1Œ÷ëp±\õëø™zÌÂmPW?‹Ð>ÔìØ9Ù¯CÆý:~6Wö먑_‡C2~z?«ð‚H* YpNpšLÓdix·>…Ñ&ÁŒÕX É™þ ±¤C2.ÌþÉx3c¢çY1:8}ñ°\Ä’ˆ»×"nGV(ùMDè»…"c„L¯rÈ,0W;GE‡Ì·¥ÿÕ«dîãÕÝÏ< ”™l‹w¸<~^°@t¿E¹¯«‹AýxófžD[ûšDÕ~á~æI< ó¦c7a†Í¹`kÍöòw>eî§¶iw “iHyÑlº<ù\!s†ÒÈç™ÆýFý¯ñf†Þkþ ‰ÝjïÚÁowsÖºkÌö¶Píê {ÚüzmÇ^6Ș#mßúù(GZóëj\Ú Ž´éw(¹ˆÆÛõ8K!K>º× 2>ÚŒ|›ò—8¶|GdžžQŪnÁ6¡8D)GkѪñ«5l—±Y­«¾#¬‹”³ÀÓ‘-AÆc¤\¤¸BflŒTãWþ8–‹FŠ[ ˆwÈP¤¸Îáð‘âˆW¿‹#Å2)®ž&ŽwH»Úüz»jè1e¨¤šÑ?Íœ{îzuÓ¤÷ªÖ÷ý²–jÕj~„pg…,8>O1THñ‹ƒjãVVEù‹±¬* ÉíÎðê·¨˜t"-€ì)2kiáÚÅ)þÎÚâ §Ö¼0÷4¢ª×Ó|"ã"É4õÙ=M‘33‚N€ÕšÈ#…ï•¡vRpLV¨éVpLÔÚìãÚÇãØû‘ Ó˜¿°šµá×K.ñ¨†šC†C*5ɯݙ¼MŠ/€z}Ícp×^2PãVëÏ’3&"orÉHrz#`qçYrQtz%à‰£è¨Ô¥¿ ©‹CfAêQ‡ÖÁû‰ @v6)(™I!9š2JfrÈ4juêŸQ™Çï§&b0*–H¬§ÇOmÊdç¸ñrR»8(¦{‚Î^ë}ÓZïy"È,Rðµ †„Šr82j½Ñ»T²ï’úê{‚Lc´†zo³dšgú~"¤'Ìÿlë`­‘†dhx¬Â%'&-òo9`a€B&¬ÛþÐÀyÊ”Cj\y–èëØ˜ÿõ—ã0½7ÇÌöHýi›ÀÍ1óðj Ñì2‹ú-«¡ßjÔ2g¨Úwž»Ì ¥…ÕEԩô-5¡ÎSœdn6™©ntfˆC–ô‹Óí£2í–˰\‚L‰ÖÛfM5õ{9^ 9á:Öl‹ù6Í顿è(ï™#¤kØ/Ãù<÷~§/QΖ¡[­¯gsucwüÌËs HKÐ’×ËÅúÔKóí¾=æZ·1íòóú ëc¶Ý÷^?ÒÔmfcì~]­}§Ÿááëór¶þÿäÚ@ê~–Çm¼Ñ;o#IIWr"ÿoº$gñÕó!<¤*Úáì±Aq¨L¿º©ÑV¿J˜˜/óÛd q¢ýÕ*e (K^!³H–¼^У,y‡ eÉ7#Î’wÈ,–š Yò™‡Brfœ%ïE4_ù œ‚*‹eÉ7#Î’wÈ2žÄ<Ðó”ANœ¾óãÓm¥ªœ ~Ôï'Üù_¸ä|UYܘ’DzõUÁ.n?ÁWQ> N½Y?|W"¾XÔKUô~–la±:ŠLcAp \QH@ÑF!¾ÿ_U [¶ÀФH<“%ì¥xq‹0‹ŒûJÀ4“˜|åÕ7~=圼¯„Bfœ¿­.oÁyæÁ†ñ:Ö Xë³áT» ôëE$Å,ZgÑâ2´µÀbÑ"£-µó»„;³hQÈa[´¼·Ï3j…à{ð öñÙ˜P´8F!eÔ®Åù3L¯íqþŒCÓk[œ?ãüýë(Æ!‹PÎm‹óg2féóg² e¶8Æ!‘šªŒ "2”?c<Ë î| FyI4‰xIjžÆL¡i$ž±ü’§ÿCN¯E’ì[SÀÝûœß=lP“$áè ØÕ9dÌ mñÍà$I™,Ó`$§°7›Þ‘ #Æa³W¡)$£ŠÆc ÉQ%«ˆB ž'¾ø+*Yž8x×:d÷^1<áôÓÈ{Å!ÓX“`Xüýäm }Q&Á´bÄfZ¼ÞˆM!V Fl™Fò|)-IS†H„´Î ™1Ê6äì¬ytÍÖc÷(…,¸Êâ‹›I*âEC­°÷ßQÊèæµû¶_51n2­öknüý”q_éæ©fZÀ1õÄà÷+¨zP' ¢ž„4KÛQdôÛlL"J‘RÈ”Óyû)‡ :(iT;šÄ“TJõqÂÓäÂEtzß“ »Ã«·î¬£o&VqùŽ×ëg€c"-Ô¿†üqµb3=ÛöÚ][‚L=Ò¤Ýô]z,ãqœa½š[mÙÕ‘ó›ñzën׉ Ao¡©'Mã<˾]w¬é1!¨Æ²6šørž‡×|êß?‚Hm|YÕÆê—¹nun‘¥£ÈOfm©•Óãr{~O ½v ȳ‘[Üì¯ßN_ÿÜ ¯·øë´Î.ç`üù¹Nzçª%17U/Éwúvš€2ät»¬…&}¦ïÛ©iè™®z‹?æÅstÝ÷4>žÇ룡7?É"Ná^›  â—1ÿ6ï—Œ(.Ü[½*¤äã¡~d‘ñ¸ð/¬m3ÉÆ…×~¯’ÉøþÇ„®ÂL“U1»h­ ¨}3'É9]†ÞN­ϓíJèI j¹|C’§ÌhûT;yØO"úI ‡P»hÁ¯gÑ1TÓeëVy(ÕA™ ´“<®¶ÐÕÉÏ4yM•™±:X!C—@ê`‡ Ûbo’—¬¹rí Gò7_ ÿŒ*v%¾@SF ÆuRø†PAïåNÍóWT~I̓ï¨8ìµ´Ö°yÄzR…LâvѺàÐÁ]Bþ0[ÃæQ6· =f©^ÕÃ0M™Çòß#|ïQR‰Ë„Ñ&D*‡¤ÇWÈ,JXÐ$u²=AF¾£F·’àYÅ!ã~&#ìcË„#éà ¦!l¨ô½v::Á[Wî⠮м}‡þ«UDøþ³ö]nNdÓ ÇÛéÙd$tëD¿£(³Ç­•㨥ÒíÔÇ™ s¤#¾¬£¢ÚôŒíÔ>` Vf;ÅñÍ)ŽŸí©;o@ý>šœv«€knGðƒrÈÒi“Í1Ho¹Zõ,a>*¡ï¢/ýïÉ4>ÌèÝ/¯¡;Õ ½KU,®¼\2<ÖYÒýÐ °.÷k†Њ‡ÇÒÏ_‡¿ÐŠëž £´bµ°š 2 $¼™úÅu†zq)v¢ß#Ñ-n˜ãÊ2NÎÂ>` )£>Ù3¡6$e½mWzc‰<0Âäö£IÌfXgCG¥OˆŸÉv–Ñî40ÎËýÞØ9KÌZà }¬DfL'IÇõÁÌ…£E¼†×êCÏýìG™EÈì+M¦Ju‚OB:V¿”9;ÒÖ­?Ï‚]Ï7¾z"EÔm6h0ÖÉ’ÑÆj½Œ ²Œ§/Ò>–”¬rÜS€YquÜE«qö‹j¹OßöãγJÒý—3ahG“^Y¹ó¬R&A 9G)$£pÇÎQW¸dd¯œ£2’òÌ™=ÂàÃ2 v£oc3éÉ"–Í4¾ûï²6‹ÌCA-âPÈ‚é  ‡ K9 •)©Ëê@]IÒ ß³:<5A½ðóvRH”fIí&ãhw„5X%9¦uORÈŠ?¦sÉsÈtãe¬¯×Õ½óéáÀP•µ|ÄíôSÜ_ßXá¯#=$œg,ú:R«²õU›ÿÙE<$ë4æ™Çº}ó2ÅŽ®¦¼~j´¹^ŸßçÉ!³-­Ø’žô\ü3ö½¿ŸYHü·æ6\Ô&òòiÒ“ÈNΡå=i#®§óõuÈÜ{¹\ì ðÝÝß?Ýø³ŒY„ý3ñ¾8=俸%4pç 6$§n=2î)ÑÎSz(¹\VÔK’Ée­Qí"=l¤±'³¨µD¿ç4 ·ſ쓺ñsO¹[ýªë¹¬Ïè<7çy§†þzá=|tÀ„¾K¯a|õÝ 2‚Ç¿lª1u}5Ûó,ÃÈçâÝRç¸Ædü²ÚÏqVìÛâDÇ"M:­K A‰Ž‰ÙfÎOOwX‡ç0/™ÑìGÛ´îtÃÞÕ~-r“èh:ê×»çéÖßre›ý³î¹à˜?ï¥üÔ‰öz+cÓk—a¾ÁÓL¨aÿ‡~ÅÃù>©/ iÃÞÝÏaYÞÏ'=Ošèþ®÷ÇûqŸé?ì7‹ÑHª÷“žh$ÑQ­Uo·–þ~²UˆZÛ“ût„I6M6)±Ecš0–¹ždáMRÆÈogÒ@s'}5.(F!9Ù¡¼‘øå‹4¼AãYÆšI³-%Q-¸Õ§= KQÈŠ Ki€že‘i´øì¯(e¢­5¹ZÑ©uq)¯ÄªMÒ®{š8ÔŶÐ.ÎpæÝÏS_·™ÕWSeØÊ¥i˜{wlzØz¤¨e¾ZêοKީ†#9-©zºzî>0u¦x:Ö×¾¾òÍý§??ÍRÃàf„ӽƹh‘fºúFšN·Ñ]Ú®õ°ÌsÿlŸ)|9èjôú¹¿ëãtóSRŠ 2ÿ³Æjö×5«à:l~lytŸï¶.Ôguéã¥è1W[ž?j¢¹ÀDó>/7­M¡wimIª‘IûʹÛ¤yis»9h¢ö“Rš³AÔ^Ïi‘á€&}=’Ñ0k‚lÍ-2bK?éå*¼w‚§@øESZr@îñءœµ×Bä“4­~Q‚ÁØÀùt%XJ|:vE;]vW”íKï \;Ê1UÈ”!´ S‡Lã:píYÆhƒ[Ÿž«»4âë:ê|Ðåv›pÌb·Q°3§ÖŽ?Ÿ½³K3JÄÅ„önQËж§ÇÌÂs¼™è1½†ä|³F’çñq7ŸÒHE EuЭõå óv'Š÷&EÞ:½²iÊ ­IQ]è1³p+CàSKy¤ÝÔÔè]*yï$ÿud’KùE–‡iV1…U³XvÈüÀШL2+ B’Qs‚¶_¾šrþ÷Û·mK‘ÁB‹Ép…ö]м*‚š[ \¥9§½ÄO)¡ìµmž––z € ÒÑ¡uayž—éáƒt2'H·M1d=ÌûÕ"v Øg`£Æišl6™;dÄß ëNÓ\pj=Ý 2øŒ–±- 2J±WÅ9÷o5Žõ™ÇbÛ¼³Cê nÕps4*uŸŽ·ùH¹Aê‚к},óqžgŠÜP³Lé¹×ßnš`Å„jÖ7Y¯ëÌWoòômOþMF›cKâº8½\Û~§Óæ˜FÞVâýÔœN§Û8Ñc ÏMºØ1y¹]êï³ízÌÒÇ4‚Áìô¾Œ§ïäߟªF°ÿYß&3Ú|Þýé:ÍG‚¬°½ìz?‡®Wk¦Ûù{¦w^¯ƒ¾te`]…éƒÖïwÓo ½$³úþÕWÒ÷¶Æ’N‹Œzq¡qI¤œ—V'P¤Œ;[ø_ÏØ½±w¶°È`XÞLÖSìä6Fs~ç \åR!rk2´(èü¨,2 ÅFÌÓxSϳ#È W±ŽpZnÇš ‹½ÔÜ„+ë]4=O* 7kP­R¬û¶‡Zƒ[ øÏKósjzzž2B~®Õ:¬'ÈÊ·ðn7 Ýê¶­zLKå7R¿!îý”ÿ.ùʪ¬¢û]Ýi?%0àÌ~T$Hk.aHÍ–&c¼Õº8$Zd7Öµb¸ó%žÓî¥>Mø6‰ÏÞGÒ›Ÿ¤UÆÉ††Þ×NªœíÜzIxZåLðK­cäáÚ‹¸0¢Áf2i%8Š®²T%cüBÖ¿•dzæØq2­˜–΀ýY†,bÜ ë:¢£±·uw>;r+ögÌÉ/¢l÷Œ²CÊIÐP×:;d±¾˜Zà¾XvÈþŸxzTvˆz:¯>§ 4ÉEôŠV …ÛqfØÎ%}f‚LC}œn5v€gTòb çÉò—¸ûγâãîa†µÈa ±‡o3#¤'re;ˆ•a èµÝ,Ó£2‘q¤§»•Æ6ZމéQWKäWsÌ»¹Œ Aæû„=2˜„˜‰ W]Ïs¥G©_vµsʳȠŸI¿&ÄÌYbÔyꄘׇ ~&ZF€ýL,² ¬ü›”¸;™”̺15»¥¿ƒéQÚ—þùŸšFˆÈ|0K¢IhMG’в„I&IhYòKÂ0hÒ-2 ó1qšEæa'½;t˰,aœÐHèN–¿„îliÔe«ñ`ð<_8KJf›€]²$è²zÐù@‹Ì"Îr(ÐÅ"ópƒ[ w0uf‰äÆ–”—Y4FÈYˆÂq4®ÕB”" ÑÍ1Ãå½ÕB”"óØâßçf)ÃþVSRn*YÔ#Ålc›ÁåE+dÆ;õÁ>Ks¶Xëc²”W<, <Í4náÛUñ@=oå´ôÞù =içc‹«,Ýí FÊ{YZFÊ{¦}‡Ê{YZÆÊ{MGÊ{Š;¢å==*âò^†ã޶ÆY¤¼g‘EÈI²%å=‹ •÷4•÷,²Œ˜q¡òžEʈŕ.ïÑ_gÊ{ýu®¼·…ÆTÄÈ*K%g{Ž,ʳM0g°ƒi†Ýqö³r0Ͳ¸Þ£#º¾,K~I‡¯3K8šÚSQ³,TârE¦n™®G÷ufJb~?.#An·î˜ÍòŽ×"³ˆò°-2iðZ­ÁBb–ÅzîCU²lG“±iŽZ½¼~†ÇÄ´M¢ywÃÚ¡,ÛÍÆî<—öó~ÿ€ßO†ˆi(èÊòþ_ãm± ñ Þ >$Ѱù3Ä1dˆ˜æ ð®¶§›—#ýu±è±|öÉ?wê̓òÔO6÷SÆ‚¼[[– .¸¡öa:Y¶q²¼œÏæ•בX]ó¡l–e%—`Š|ݲ½ß õ‘ñs …À²üÀ½u‹'@dy÷¦1Þ±ð4ó”ñ,ÐPÿë)#Ð…ÀŽ™‘M'ò»1º”Ù!yÎf´{­K–çqj‰SÌ<Ý,§èg|×l³Z—ÕevÆÁ!E(eöîüh½Ö%CÞ4 C³Nuj*ªŸñ½ … "±Ñ\°~ÆAÓ½q•‘#ãª,/9ÛEd\•á'j\ՌĸÊ"³ˆA#2®²È<š¹é·)¹äsý²sÈHîÞxa»Ÿ¬8põ›ÚgœeÅ!jÚÕêkIgV¢¦]Z”޶ÑÅ!~íD““!ƒ-—üXŸN§Á=£=‡ žQû>_.gØÌac µÎäb˜ÕÄ=4ßïæ˜YPÁ²èblS Ï«°Í¥¹¹ªö4>Ÿ÷‰ Ǹª±«½6ÕJ Å@áy..úÒ8 :µç­‹E–>wÒ[Šôj*žÏ0}>Ú²V¯. ø²|¯ãñIïR…Ø n›ÔL|T£=¦]VÿY°Ú¤9··þø)Iõéfh³÷¦=š½øÚ5u ê¢c¬§=MÞÇŸî3lŽj¶~þû‰¶þŒÝësj6oI¾îtëz³Ò-uï¯Íö‘&úIiJý_s¯ uö¬Zóòv6*V¨–æ¨>×fèºï2ôô¶&e¬°4#œ@¯Â/Ø”6Û˜MmRÑP®NÆfsá\‹L#•}½ ƒÛ/Ø^E¾æ2jª¶}ÛTÄÍÓf>Fϰ–X‡Voè¯SO´„dõhZøTûi‚Œq´\r$È›KO903‰á¹OYQÅ­ÃHþOÊC! >ÿ'‡8UwtüÒI$\—¨îÁ&>ã¶ð[‡øi!Ã:´ Çü´P$d€g" 䎺ªZZ0>‰,´õ\­f›¹VÀ‘ ‰Í‚Cv þœ™E¬ot*œg,@\p<@& .u Åd" ýÇq<€Ef‘,S`‘ù~á¦Ë(êl»éë"ÆAQÈóýçUw™†K3uSw0‚ Éq]MrÆ/ ‹B°E[´"œÖ3l3Ï¦Š„Rl±Dbdm—‰ŠËSÒ%7ÚlØTÈÜC=#lî‘•œI6÷ÈÊ$«Ó’X¬L™$@RÖ/36 p¶J†“ÖBEàÉgå/EP`ZdlÓ©}îΗ«1ó¶~Y) ÓZMqþ¤ üó;¯m¯kÜšc›ÓiìjŠ,HyÙDƨ£Oã£ù$DƘš»Yˆé¨ áù3Sdé±Ö%xcü™nÏiñ_‡$þLµƒê»Ôµ÷û׿KÞ—`õ:8¹¾‚Žî»=À,<§YoNÕêÛ ©âÌwðÐ8/}d”'ñÔ’ž¤–ä C›&©%™î#m^f}¿8d`JÝÝæë8«å AþÓê³ [/jt˜®W‚Äü'ð~ï‡÷ÔN3=&fC\ÝòWoQOç¶%Èÿi-¿›Ô[Š{Þ„¾óÆ‹þz¹½Ÿw»øÖ `‚”aÙÉÜ ÀQË“œåùÒYž0‹ï.ç WÒŸÕYNð.•lÀøà§̶ ¤sùŒ<©~Iç‚OÙë…ÞOï§Ö„Ðsgó4a„4ئ'÷ÌHkètƒÂÔJõçÇÌ~Ã›ÆŸæ¼ Š[‚L#›.ä ›§Ó¤À å<-bF½QoLÛ©à|Å‘D$OK6±e€ƒ[§ýûgóuÌ÷¿ž2žLÜjM¤–äY,™X3¡Ç›/²åÙ!þ.ÙIž%LyS÷gàýÌÒ€üòw!Ï2†×S£Äñã‚ù;Ï3š¿SC10Ï2®á¥í4á×9æ®±‘¢È4d©ó†—Æ%Òå(»¥»EÃk\èl޳ëþÑmöËÍZ6Ƈn®{‚̶yÃk‘í­¶Ñ›_÷›ØµgFÚúñ@pÈqvYúŸíŒðÒ½™Ï¤1‚>îܬ}n…¹ãê¤kÓgêü·‰m¾H«Q!ߺ£ IdÛå?¢F§Efáµ¢^{øTÄfÃU2ùµb‘sæÒˆ)Ÿ#âÍ÷kÚæì_ôj xÐy!"önÎ<¾£¢üÅù·ÎwH‚FÔï¥'H£búªŒEV1#ê¥ÛÞùCäCRKÿó‚WN þ¥ÇÉ%Ôži¼Ì½ç¡ZdÐ%ó>j¥ìLÚH9ëˆá~ÿ|=’kÈj]Ÿÿõ2f ` K|ƒ¦8Hְį؊ƒŒqWc`2¡LHB¼¨/îǽÊÉ!ªž§F!ë‰ #ÎÅúËÿi 2ê\¬^ŠÌIY4ʃš@†t ¨ ž§ÅÝù„êVï¶•R¢d{hN Ò˜ó¼Ø-nž~í£²óôttilVÐëÜüÜ?7‚ÌQÊžu£{½ÇåõùyœOYoòt»\Ìýüy~.ïWÿrM ‹^£¬E«Þd¯Ýô& –!FLkíýrk¿Çó@¯]B›UaëÓœÏj k»KG–›õw˜Ö%Ë4Ö?Ãðø ôÎtŸî³¼žº:A¡ÝÁÔ罦$ä\›–ƒfÑx—ÞÄ»À§Äkj¿Ä¥#È`¼Ëlâ]à“Oòx—DÇ»YÙ"Érùæì­û¾®O@‹ Y<‰ˆGÛàÀ")‘,’è fƽ¯L‘H6a|ð+ŒDF£LqöçY‘¾þ­+Y3>î÷ëqè 2ÜÉZEî½KÙè Ëé!.¢´ˆÂm ä1Qx{‘¢"ŠÞˆ(ŠŒÊÖ®À;²È˜lm¶È¨lm>¯EÊÈ–[Û[2áÖôgo0]¤É/‡ðÖ¥)„ؘEš1–Ä5âGiÎH#&µžá< 6Ò¨öï'Ãã2¡žƒCJÎ? ‰£ ¹ÛõÕhÑ’VÌ]£G`þûM²z´ytßÞ¹A˜có(úÓÑq„ âs¶%j?†ÇãEq3©2·¨k_d)·]<#±È2FD¥&EÆŠ=ôþ®½qÌinCÔóq®¶kúþ¼Ü¼OeÃ27èÚÂHØÁËVW]O-j_ÃéÙd`Á¦û§8j¢ÈÛ›óµÕÂ[*¨¡‰»Zù2¾×ÇçHò÷φ&n½è†®9Í_5:^ Ò3Ó´ÓìßÓ]ûŠøZVÒe˜É¤»[+©ûé ÜE‹ÌQ?Ãò´ßÓÏýÜw5ÌYI˜ij[_ä{;Îm}¾ 5=¦ð0V~©Ã_ít¯ôÚK„Ô¥†ÛŠüNÓ æ÷¬$¦2']ç0;Éá4|ÛövìèyV”ô勞§S{ú¡Ç$¦2«û‹ºõÃcîô†‘BOû_+|æLëåø³t …¦”÷o3ëo{W##…fÞ¹îlGœ÷8=Úù§žZ ÍÝ4«VÁ–ù¯38ŸSwýé)t}Rÿ™'e9„êI=Õy9oÞ=á '385+…ñ=¿÷å‡B-‹ð¯™?ͦf°ËT–k·9UÏð5'`¥ª:\î§™¾ÒIµÚêè1÷ìÌ‚¦ñ1ž¯ï‰5]§ÿüÏLõwÓÏSSý·Ÿ¦¹§6M<´¹ØêáTÏã÷:=7G5A‹ÿ¨ÝE}1Ë}Y—AmÿîåF¡úi}ÕÓú_mcìÔe}n·þÝÝÛ…æú¿?+tu`úܦ¹íÞÎöÌA‹—Ñ›#žó\Qôný-OËô|Âså¸ËÆÈÀ]~`"p±È¯È“¸GïÊ2qç™§\—9ÚyÆòºP /ÏÙŠ¬·f(ò‚c®¨u¬\s±¿ŸÞ:D­]G¸K%Ð1#gè"—Q_jí^x9:ÞL‘s‚ÑŠ:/0÷.´ùÿÂê [®ÇN½.YN§e© r³[»9d×  ƒk„lÜÈW¤¿øFÂ3ÚØNm$qÈ7²À›užçž'gGh}å×µº¯=±— ¶èÕ,E!ö+BÛš‰ÇcAxrÿR&:ñx,Š2âñ¨KxØã±(ʈǣiU!Ç¢(#¦ý…<‹¢Œx<ªó$EQÆÛJÄã±(J¦­„= œ¹aVG‹¬‚|)âñèî|´­ä=4äñ¨ÆDÜVrÐ4H]hà•ÌpgœhZ‚ ×:uħ߂³¹ÒJPpŠŠI½Ö¹IPø‡èÔ¤!ùí"òü Õ¾†(¶†Øú"¦H†kˆAf~™{±ÃÝO[_îêŽ~é1óPµñ‡VE‚jˆûjãÛWEBiµñWE²qDÜTk`‘2Pm|lª"ákˆ/¨! ßM gT ®!š£Ú¹‚>»ïãr](4´RsâCW(á%Icü~cÑ¥†ü™ Ã^ß$ ºgòÂa ‘s,^¤7+?³$W—÷V ÏOµZ;MØZe÷çᣗ-=A† 3Nu(0?5g牅(‰³ƒO^”qÓ”†ÞO±î0fˆGµj†»T1j¦®Çi$ȈúeY|ô\QX?öæ¥sÌ% ¹¬·mKi$©Fý7¸‹¯l‘áZXŠt¸Óƒ-i™ –âf¸zÚ2ñ,ÅHÓâÖdoZ ™Ç›MGE¼iq§W$öŽ®´’¦ÅŠ,ã= øŽV¤ÜL꘴e±"«¸yôAk6à ð}ˆRp µ£)2¸Á«?þ­+9ukƒ‘’ ©ë{¨ó"{2Ïc5ƒb£UçÏïÓMIˆw騯ëU3~ÆÞ×Ñï½ÉkÈÒE !XÝyÞe˜Çê÷hžwæ±þø;x—;ŒiýMþ¢˜õõ}yØÚ[;LÍ·;º»$.* W„e µÉæYŒD±PÈŒ1ËÁy1²ÚV®É‚Mæ»ÝÇÍùŒ“°ÜÇBÒZ§ž7q­“ÄBîfm\Á”Ã!LYpUfm HÁAþÚY  Ò.dÉh®tŠ·?¦d:½®G™Æ5ÕÐ]Õ/1°ð†T‡_b`ŠL#†äHÇUT §zB~ŽšÜ˜dòØÌig\h ·z‚ŒHêýtª<^½ÑßÓªŠ =s­Šàœ´¢ŠSh{ÝíwQ(´ÍÕå¤õíè=N¡ÕöލÒR‰ˆi¼¡~áj1ˆúClð[b)TTñÃÞDÀWɨ ~o" ïXɨ ¾¹"ß ¨d”Ü’Ä“¢bõÏÈÓ"CZe“äµÊâpà*-H«,°‘UÐÀ´âÀxgwqHv¦Ìη%ö¸bÝI¿8lk‘i$x¹ÁÈŒ³ÃFªQq`ÜUV…< ι£öA—âPĵߺ7Œî’àƒXṋCÉv=R ª5?ÕcZ 4þ˜UÄütEN}ÓdÀüt°æ§ =fÐüôþºt·—ûÞ-2`~ڬ槠‡´Èˆùi?=þÚ+Þü´Ý ÁüTÏ[«:k™oõ¹Ÿ7ç)6©Ýj“ºÐ»2?½®æ§›c®„?ÿAE]üÏøY>×3pû4ÁkÿÛzG¯jL>}›íQ#æ§m7ôß 4`~:L­1?7Ð|oSª ÃýåmJ´ÑïÚá2ü¼Ü>E$n׉¬ÑDrØÕ@/møRðL“$.”1|)7Ú KøRúÛÔ|)x¦( vVÜi+vzÌ<ìY;“ÿˆV\Ï X;*WŒðºŒÅà±ó×Î…?ïä%WÌ[ð»ùëq¿¿ðŒ¸nN‹Gû¤ˆ)B‡–šŠ$`h w^+BA¦õ¦úmlhj‘Y¸= u;ÑcÆ Mkÿ†´Ÿ TZÿ4K.µiˆD2⛓–AÀÓ hï]„M£Žøtem‘"1 ‹©ïà@$Rìøðw¨ðlžc‰³“·N×÷ô[_GÊéŸfiKilžõ,‘¦¼g T™,2æå‚%·ð¬M8ù0õ$œÜ"ƒÖ§=©.Š4Ç6Íu3#dÁTVu¡fÏ”õCAŽ9™Fú¼(ðC¤Ü¾~ˆ´ä?@&Òò—ÀÍ¯ç±øz|?e`FpVì˜à.RÎ?Ü-2X7hÃü³]ïø¥Ž8Rdq¦hûÞ©d,2‹Ø×¾ªl‘ydw<ôŒK&¾Žlß#°à¦'ú$Aøg[™#Ö'‰,ãv ƒw$¿øˆùŠ >b!w›~½`;×^Š*pÎæFWÝ·J‘‰ˆ[¥©?#·J²¨[eÓ·J˜jÔ­R»UŠLÄÜ*‡ž¸UZdÀ­R׎°[¥EŠ`Ê'q«´È€[¥a€ ·J‹”1w°ÉÏqÄl'F•‘I&þª7B*‡¬~qtr5=¿‚>MdÂ"Ç9iÅR»ƒumÿvïgž2üò/ªG ”ȹw ÒkJW yÆ;ù9.Ï™½¹ŽZ;‚ŒŒóZX›e¦È,†ô¶î™»ú‰ºžËZë8ÏÍyÇë@‘E9(dŽ9)B£MÝ?_ÞßÐ"ËÒ;KZ¤Œy“¡Ñ»(££¢^YùxQìûõ–´­ëùãõy}:d 'ØX.èr>Oý‘ 7=AËß–Ë8Ô‚ÌÈ,cÞd=Ë<ÚgýcùfBЕªów1½¡ÏãòOO©Dÿü‡•u–y´ãYd†7ß1KšÚ/AæDQmzW>\§ ê!â°]±øc6jOÞŸNñ×6-‚ž Ëís· ®Z?O‚”Û*ÇÝú4ÝÇ+Ü¥$0ÒÚþÝpyü¼`/#’ýH ÞOºf« ‘ăñÔhÓ~aÏ%pÕhï…íÕAB¤ñxmãW&©çû:ÃäéÍø ³6bòì=¢æÁG QðIë~•N" ±mÉÊ]ô¶%B”L ¶-¢äöŨ*D,ýi|úO™»!tÕ¬}×5ý³‚,ö>ýꘫOK"˜ä`|úïw‚,ƒ«@55xK}‹”íŒÚmo~½ ?#½€çží²…tUd­C^.Ͼû¶郑‹ÖÚ™Ò.Z30Jì ¶sDÆê•2KùdMàü—YÆøÁuCíw˜måV« ˆÁª2ã¾bm!+u¡úÇq“ÖÊ]+o8Të›l{‚t­¼OtÆKÿyë”Þ ³›Jß¿ÆÛâÛË=‡êâ|¸Çn9Î~ω9TÛ>£¶Hoïq¨èªÚZ Olj Kï"u³WdVÕÇqÚÜ%¹ç]›n,â]—YÉ,Z0ïºÌJ&}ª_ð['Y¥‰÷,³*®#~še~`M½Ÿf™ïFÀáoßõåò€šHžDß%5&ãw %,Ò=Ò²V ÏÕ"³À3í3¢H0úRÈ‹>¤±;kUW ³È…ƒÎ¥´×©Ù\ѪòþÏņ¯oH?DZ†w>÷•Õ°;*Œó—'êŽ:PdlÍ 6>0ÃæS•P{x?såL&ŸÉQóÏ=g“‰Ñ*(÷—{Â/ó" ‰Xwhj†m[`-–ù¾rúeíÝ<¢gFþ÷ÏÆ}r9ŽËLÔÛÕ›Õ§Þ–(]2œeëï’DûÃPB­šÒ×Í|tïKõe^¯“ëY—žÁõï«càýÖ¬6p˧ùy½`´Y‘Eü~6p—*®/†¸ eqˆsÎ×”Vwí˜ÁõïêÕx³|¼ñ¢&ØÆä"‰°û5Ïø¢á]·Zþ箽H94äæQL'Ú¬.`ü,òÈê¢YW-¬.Šœ]]´~j‘Y8 Rszaå_l²»ï‹•…`mâÕØÇ,ãÌ“Éô—Ý[WȈj~õ”óªù’¤K‡Pa†BË¢ŠU —–8„–EÅðÔ·4Âʪ¨âZ-âSWŠ›ÝávK‘0)jjœ´R0uU ៦ÈXN¯ç½Xd+{¿ iEáôS«æ˜eÞü:£J€ý‘`’X&Ì)Ç„4ì‹– Ó0?G_:ÌÚÄçÇíœ#ðÏsöo²ˆ¯¬ §×ïv9”ž³êK!¹ÎÐ↥¨˜0+ìlP–‡_²–ŠL·»È5«ûË “‡îÊkÝÅ™ 2ÕŸz‚Ì"û÷ºö{„2¦Ž\+½²©,SæµZ= WÄŽ\Qã½è²•fp ÜcÇA5É!æ|GeÁèH¿§ñ7„XÏ•%—„LJÌùÙø¨tD•P–\tÇ—¼K’ÉØÆàeY…VV(cq×eÝè‘káK.¼î„3wK™23—æeÁšV¦q®—ž¹Ì,¾+'>i¥Œ»¡öD÷WJž éVË‹ËÆ§bñK¥,™ý»ÞÇùc–œW˜¾óî—’x¯Õ'3u˜´œ¹ûªO ÚžÉóïüGûøŸ¯W»ª´=ñ¡-«”çIøZP•Eµír¹ÿ,g@æ¬_=B·©Ê£a€-ñM-Ÿ#ì¨æœôKÄç:ª©o„ Ó˜OÚi½ßKØ'í§¡ÇÌ£žf¯¥%È"îiö¡¿.6VqTê×ýU×YFSØ{ž¿¤°/þÚ÷c2°ÓçåÚ6PS­hî+©˜©Y{™î/‚Üô¡-+ì¶\§©n 2Ccˆ%F]Àû½ùÒhZÛÄY‘Ëðs<ú+’¤bF,Fui)R„Ó¸Çz:}'‚,ã9oþ+®XÕL¬Zy8pš2­-¢H’v°î‹›©¿›é½9fB޹9f0šk&Êe‰?;ŸI¬\–‡$ʹé45ò²;ÓêuqƒB;Ó®ëz‚L#‘·È‰Tâ#ØLœHå!;‘êÂa„c[ÕORDƒOg¢ ‡’ÉØÀ ‰¸A¡ñÓðÊÓÎvüô¼ò 7é[[ÝSOYÜ÷F‘yÜw È"nëvRw¤ \‹,#c2rÀµH¹7ÀUHb€k‘U4ù¨ò°_34ðܵá‡Á¤çE|e­Ï¦’É!Þ $Éê2I"Îä«zÂ;“K ú—T {âL.“4âL®÷2Ø™\&iÄ™ÜP3¹LÒˆ3¹Ùo"gr™¤grc¸œÉe´õ‰3¹L¸¶>v&—Iq&×£"v&—Iq&7žÈ™\&¿´õ½3¹LÒ¨3¹“q[_Ò˜·m)Lë<x W^Ókzøýœ³1Dr™œQ¢«Ê$n$Ò®8fùKAfž 2ÜJ0–#0y%’§>/SGQË‘6h™cBWË‘– óˆÜ@íbxFo…zÙ ÓAÜ/KÞFHÒzÁæ„2Mâ2ÄœPb%I7#1'´È,ÜFÁæ„™Gýðþ"Ó”õï§¥#È4$®ïI‡L3FZ…8dš1 ¡fñÑÍ2Í9Ùãà#eZ°6†ž€k‘iÌÜ·¥(öʦµ´¨wjç…0!˜U¥‘Ãy–» Xâ Ãcég¸Ÿò#&(- É1©mÇLmïºç~j®³ç%ÙsÈá ©~ o ’ §ÇŒþUQq»–—7~UY{o㣠do‚·Ã­ù~aÿ%çØªæí2ãv‹§IÈ2g¨ØFOFƒ¨¬5Êà)ËСAí³²dÍ„= Rbóºƒnô+ïMãeY±TT[“ŽÊ¢§™™ Ó-J´á˜q[žÈw¥ŒÓÈûÑüÜs—cFZ±>ŒÉPèëËÅZ°jºàp›ei°S[“V¬Ì&&7ÊM¸Õ†b‡hfÑ¢ht‘Âè"‹Ì"d<]d‘yŒäæ­¥¤”Œ…56 “’Ýk«¹ãíγŠEiؽ6DiÈêðK˜5ŒŸSá¹a#zYqñ=: ´§ÈÐnWíŠ ©€ ̲~#3AÒŠ®[3LZéú_ϹÙY¨È*.‰í‰=‡ÜXçlMvP¥´Ü^[³iÉî&á\V\ö19’Uµ7ò–žU‡3.aéYEB£vo"¨Tžô& A¥:$\ž2Ѝ«¢¤—µÂ£ž>EƬùÐs¯+Ìô¹ê³v”ø˜E”òMÍëƒ`ºl'wh‘idÖV/ÈÇ,ùYv‘Õ~@Ýꀢ¶s±ž On.®¼!N`.žŽ~.¶H3kÿ§k׿zY©VµºO-ˆV,2:k[dlÖ|uË"e¬7á{åÕA2'Qa‚Ê®Šã$ªC‰“0¡¥(N¢:TY“"êýý È[àMÆbº*90kELÏ®øp%[%œÕ6­’4n> ×´ 9¬’,Ú7Ô_ñ1LUÂt'5ƒ¸¦J N´‚jU"8""²É­Ö”{j "Q%œ)÷ôôÑ™U7å6VÛÓÒdáãÏ´~U!¯f|Ú¡ÐcFL¹¯È”Û"c¦Üoo×o‘2²¦E¢ª*)9ãt$¨í¡ô$@¼B\ŽP€¸ïWIEÖ ´º…Uzˆ ß4­8p°Jn‹¸Fñ™Ádûe%ÛaTLY£CM™œ2$•ÒB$•ªÒ<¸±6ãÈ”»J‹H-H#±)w…» 6å¶È,,êǦܙǢtÍ!¬è¶\ÕfâWT2vfêDÛ™"#V'Ãà;¶UÊñ¬ õîRÅZ^tÌïiÅ„Wª}1Ô.ªìÀÛŒC5»Ê¸~1Ž ­²„±†ÖµtxîYÊÇ4{ªÊ2ÎN±S*¦Øõv‘™pµÑ°†b~ŽËþ¥ÕWþõ,î [4lâ gÂd®DÆ|˜É\ –É\û»J䑘0=wà‘*Ô±m+ LjT¢ˆÆˆÌ$FÄ"c\##b‘Ô7ÒH{ôêâ{ú~'·òûuò}½ŸšŸ¼Gn„07‹üNÇi¾d lú:ÙˆEæ4Œ~ÝwtžN#AØ–ä ÈoÓm‘‚zAZÛ5Št`­o‘¥ÛéëHtk‹÷|}4ñâv$H¹ñ µ}Øn™®Îv¬å~öÙÚßò2dJc@Ý1›å1>;‚Œ„nÔÈÓ"sl Ü׿½ô'Ç©„Ü«!` ÁÝJÈÇÌŽn%~áèÖ En¬áî–)ªvï×f È0G·1]zE"Ì(hëñµt! Cƒ®Ò1×½k˜é»-Uy` 3½¨*ƒuÃ>Õ•÷Ü}÷?R9UzÉÕç5ïfí’ q6v=AmtÈcÓÀ]*ÓC¸7!Ú ™ ó½Èé£*³_´°Ó/³_´ =f¶·£i¬?fΰ)ôâ*2)dë¤Ï“þz¾ßo®Üµ`t×.LDš Bd0ÇZᘛ sN,Ò_×7yVSÞú¬Òe@{wëºzYnÇš wËš|:“@‹¤Ñ9f´1» ²c‘åÞJW»4?'?‚É4f{«]m:úëñ蜾w™þ³ƒÆ¬kN…˜A{Î¥ýªq^P¦5ö_ê Ì¢*ÏyYg¤•­îÔ[ïfÝ`%Ho7¢3çÌ%µÝm§çc¡ÈÜ÷FÔÅ›Õê»9ŸÏc?o…éÑmš_¯ŸÛ÷¼ùuáxÇzN¸þFkšê§ZddéÊz½t] ó›“šŠ”[”yµEÙüzµ—à7“¼‘-Š»ó¤ÁonvŠïÕ'×øMŸ…&{ •ÆX¨|ÀBÅAÓ T/ÁôþQ§|§Ð,\“!{^ÌbÚX£ôý V–.Ò·’û=…³°n§vz^aVB<"º·®ÕÇ8Sävï³î)t¹t‚.’Q•±Q›úyV–lÈ&ê­Ë2^µ#ìÊJJÎX…)W²â,GÊ£ªXÓ9¤C¯"ì k—ºx‹¶ªJãaHÚìeôÇÌ"1?šÉcb~à˜y$ægYíпõDA}M»Æü´±Ž4â3ŠŒ›"‚¶¨ª ÎlYÖW•`êäjVòu†dm~îÆfDD¬ßº¹í{˜xìë&©õêá dF=g¡Þuë'‚ŒÔÌçN™GŒ©‘-LE쀪.gG)‡k×Úa‡ Ú<öØæQ!c+õÜ?¨©i4B±úÛ÷6Qdº_cè=š®CnŽ™…UÛê~¶ö~:d±4ç‹‹¥™–çò<^Ž#AKcfY='ý4¶{vu ‡¤¶inӥܛ¶ýè¯û!=Ë)ΧyŸfºZõ®CÊp‡bô É0ÉoC­ã 2ßù98µiž[P›:d±Žôq Yì+W„úýžNþ.‰m­YeHê^ªïèûµU;‡L÷A Y¿†éõ³dæWw°™~ÎËóéÌÇ2÷«–‹üxw÷÷O7>ü];Ãg§ì1'M!9;JÄIsÈ å¸9¦d*ÈŽÒ!#KÔMPÈŠ5¡‚n‚C¦U¬öqoH¶[÷§:¾Ñ®.rca­µofGc´o‹¾™F£^>ðÖ%ȲÞFFYK°4÷ͯ›çþGýºÞ!š¯ÈðsÔ²ºûöIµofŸbµo |›I‚´o;€Ø• ™RÝŸ±°^Y ÚÂZ-ÙZ‚$Æk«.@í£ÏËmzoŽ™THš©ëUH ™±v¾Ã£b’Ç»œk4 ‹_‚¤»– Ó¸¿g$XE¨¶’›ß5û׿!’ ‰îœBÆÍ²V:Œ )Ï»B&¬0`2%6=.¹ „åso¯Æ]QÊÆ,µ[ý*äo¿γØk ×P1­`Oß~]87ýu¬õçö¸¨ùàx„¹#Ô¶Ýh]o–¹·Ü§æN‘UÅz¤ZƒÒ_Gê]ýiš+R×s:©UàHV½k"*쬭w’ã©4‚n.Ö»Sý~è}Ÿ^Û<&ŠDÑ€ë#ÒßæPŸ“3²sH¹Ö£þþ­Tߥ®½ß¿ ½¢ d¸¨Åi¬§Ûãuœè?„ R³!@ø[_2rS íF‚LcØÁriܳ¾Çžõ ÷¬o±g½C=ëgìYï‘…2ò¬wÈ<æeŒ®(`²sš’\*dò Í®î 2J³É¥C$—«Ü$—1ê2¹Óðëˆô£_z}å—µÔИ=,<ÙË¥\^lêÆÔ\ÚyêkŠL#ö[ÞsY!9º?ò\vÈ5_ü1 –üÉ=™áºÀ6ÀÄ™‰H­±6ì2äçkÊfºj¦Ï³ïŽÇv¾úÅb† ´l6œÏ羟a’ó9LGH]Žú¡Ç,öÕ(ãù]ÆŽ"c Ÿ+ ”œd–þ+rïó÷>À0+£÷s^ –p—dô~ÎkÁ²'H»°ûƒ&¹O×|êï4,ô˜Yh:ljõÏ—“åvJ¸­Åâ×õý¹µÏáH‘žÚÛ"h3¤ˆAõÓ¤Èr_ý±EÐ…^»\‘úŠÜ¯«ÉcYnÝesE•GÞ®kÊ¥º©õ¢þµA®KZ}ÍõݘCÓŸ·ËÍ{×®eЉBׂåß?ö–®eÐú£–ÀýwsYèm׊éšÓ2¨Õ±÷º¾…!êVW?¶¸ P±/®®GU—w§Ð2œ@¡ËG#œkµ7vXÅtj€7‡üÀÐí±˜C¦±¼0TlÉ6/¬öo_ž0¶{H”­lFõÒ-PʳØ\§sd¼üP!9WvÝ;‡±9šZe­?\ÃQ! vq h…ŒÝìe) Y²ôZ*d`©©ùª­šC2­ÉiÑT÷Œ¢OzK¥‰£-E¦‘Æý«ñ×^¸ÿkh`Û[âfLêVÈ„'`70”)S¨G”H‡L#›Äd> ™rÅѪ|Ì]RŸ¦®;dÎJn!wO! NrK®½ˆf@¬Û^ø6 ÁÚÀ¢r\!øuSßfQ²ë&°|qÈXÖ\À¡¬ kst½¬6GCÝöí`m£ ‚¶Y~Úçxk 2óí†Zqà9ÃsFvªíìàÚEÂYºyÁ…B¦œAÊðó‚±NdŒ$¼ö’p‡L»óŒÀüM!óXª…:Odþ摽2sÈ€ù›Ù©xó7‡ ÚÕ¶8CG!9“ddÐçi(5uÆ– )˜r²,pȔɹ‡ûYî]ÄíÈÐöçöÓ)2Ý“ýô»ôx4wK­’„Ñ›PøþôaõÅ}Ÿç·+z ”;Ö¼.bœæÏçÔ$)Œ¬ëå÷¤?޶öo2Z[ä ŽÙªæ•3'%0Uæå\ß²#—ù}®Ÿ)ò¤×«Ç~ß«C_wô×KRÚ£¶¥}Ô?#AÊò]ÿœ²¢ÈûZ2Ç|é?Ä¡/zÐuüžåή´|žSº ½¦ÄjTI §«ïúôÞB3ÕG]×Öçù=©‡ÿößZÿóßö‘vê5ÙÜÔOzæ6›uÔûëÜtu·¹,.]=Ñ‡š”ˆÆx]Wì÷ñSóð7' ]È‚ð×u¸Z¸¼ïj¾¹¬jÕsƒ‚^.š"zÍÙj+_Ý8Œ×ëg¡¯šxèŠcuýž?õ¼zÞ¡zW/ö4¯ó·«aa¡™ß_m HÀëÛœÔ  9‚^úxvÓeó¤–cèË.ZŸk÷Ú~-éª*þ: ë›Õµ÷Çñ¾¹¬CoÚ÷鸹,é Ç5iw}³´u[÷Ø\V†~O;hvpPÝ']¡¯®ŸýÃ/J-4Y¡Ö‹kœ¨ýýcìéûš¥Ah¿, J‡«,sPsÍÍžÀüólZz_3Òãñ7KÀµ£/a¶6yŒ=zj%sï.›;°>­ÿ\€ˆ{Zùñݼ¯YI%Ó0[ܦóÏà U$ñbm›}~üWXíg 0žóå2Qdd¶øÎÇ—"}ó®^ì_½s¥H2[Üì\U·ó§=Ã.kEŠrh¯j½{¥È26WÕçz&H›«îçúJUl^9×?7zç1è½þ¡'š$ñ‰åLÏÔÎAèesÔ O,ðB ??S½l 9žXÜt5¨‰åô³…á‰å9¿ß›÷$:[¨‰z¡ZÆ'––>Ýl±v°ô𳽯Õjg‹×‹Bñlá§€ŸúýüœŸ›…Ìk-nP3Û}n? }ZáÙâó:Ox¶¨ö³LWõø|þ,ôf‘ÙÂO,ç¶»¾üÄRáÙb3±\ºNûQ¨ðP^õ»}½ÚÍ ”Á‰¥ïÏiØ@exby5÷þº¹‘ÙâúijEEg í»=4 O,§¾yô\#³EלÕlñ¥Ð,2±4ªž-º×åq{Ò—ÐÍ–<`>nC¸¿¿ßÍe‰ðÄ2îÏóZ:è &5 ßÓün6çŠû‰WX‹ÎÝò¸n¡UpººÖßû¸y_óC“¬ëw~jõzšu+p^ÇÌÆ²¥Î?Ðwõz’©MXôò²ïºSwj<× <ßb]Ž¿i’¹.Ç?»ëû³uy@šÑ?°¸4’’Ç`jh‰»¾ö™êÂí§ rðÒ¶P üœï·ziFúëåÞK©ï†¯ö‰ì&‚”1)ø‹(d²†§ÖÇÃøÃ9‰j}ü¥è2Ý—<÷­YzèN—q.zO[eeœ‹ÞÓV ·Êüå¿´Êúëyˆ¹=ÒVY™GZeIZee¾k•áÂíâ‹‚%ò)ß;Mš½B©{ëŽ'ÍB2<üéq¿=ÏGØÐ—ÅæÚ±óº q È<â<ôF“²ð<µ}¦&øRð™6}G‘iØyê(d\uÔjÖ¡ç˜xÕ(o ñ©-MK¡ –fÄ, Yýât ß»dÜ]¹…§).L~¯…L£A‘j]þì;XF{κ47ü¯5 Tó¿æJhŒFG=Íã·‡žÌ¸P\PÔd˜Å©ËÛ3Ì2g‰#ÃcÌ#Œ`ãÁX©°ãÖ>J!E”<¯×÷³d|Ô«õ™Rr—_¦Æ‡SG‘™Óá®Ç´Ô…fçöú$Hë-óÇ嬭Ž1Ÿ÷ù9À ‡•oS6ê¡;ó‰ ÃÞ2µñ– ²Ü6þœÛCí9ó•äô,:SÞ§Šs‘@í%’ÃñuÔÎKn¬O‡hV£ñ—†jvrH8§tŸû©)£þ@¹Ÿt'h?çwß»ù89Äݱ´]z–äÅ)“KÜŒ˜ 7怃î±ë;Š´«Õÿ·{žËxQï‡óÖvÈ,ìÑ4û@y…,˜•%rtWÈPBèݵO­Ö9d¹WÙ–ö=èÔì/AnÈŒkê¨ë/ãp¾dRӴ˹Q«@¸vÉ­¿ý)9Hö­ïw…¬~qEƒçÑݬ‰lÈÍ!Ó}j‰ñóô©% ™°iÈÚJË!™µYa¸µ]’¤Lž¦Ni™1t”â9“Z¢u7ð'¯»7È î¦7º› 2‹Qª@}¬‚Ûª…:|ïIÉ=MíÏñ2Åy¯ Y1Nþ(ïÕ!Ó½ŸÒš–~J"I?%=Ö!?%‡ ø)5¦~~JÉÎ@~JËð®} ™0~‰˜ê™ §ß]’TmªpíYiGoíßÁ›œf|-ìg 2Z ûuÚ"#´ñ“®…u¡Ÿ¾j“BÏSDœü½¦X!óx±ö%€ªn’¼ß,ÐÞ’4®öjõ.ÞyÔ+dÉ%y§J…”ùʧ(dõžqˆC¦º£®²¹+B‚:êó4Þ°0fn†ínP‘±È,²ßÖ‚wEYÂy hÅ’%ù…?½×®B¦Ñä÷qM~Ÿ 2%M4ί[!³h}ͤWøÙIOþÒê,á]ÊÂïçê\Ñ/ 좓¬`v§cûìaüÌãD­æ÷ÑíN“L0´LM'ƒ ö.¶ õNÙÚý¼ßÏ“¿ó%£ÀÕE”Œ;–^ªŽó›ÕùÖp?«@Ý¿º¿:Ow—~»7×½ñDé~Û»}lGÙ~wÚºÝiOyÀ¦³.03Aá^Âä]`R„6‡£Þ:g‡,c;ôÅåœó<Ê/sÈ4¶¢^ ›ä)ç`æS22cÒjPJ¦C¦ÇÂfÄŽ… ™G ×Ì)p,tÈcá@RÅ2äX،رÐ!CŽ…Íˆ ²¾ŸØ±Ð!EX‡ ²Œ&€0zçë´†Ö`y!ÿ·Ýý66h·›œƒÙw™ýwTì¤~¤Eùã ɸ¦¶8dð<¡_ùç"šT®} ê[dYÏã}ï­ý3@ç2ÉËè§´Ø!Y Ýw;_ý²ƒÞ ;}uL½Óÿ¯L:€Þéû¯¸8Äý䉒=)9•ÎMt8-Óó ÈËúŠëN—7r'Õ_Q³<[µ÷pýòd“‚½?æâ¾M”‚<æqî2 'Ôë]|GE±—®ð.½ÎÃ÷ó{!âU]õÔgèï&8‹YK'Gï}ÍËx:yñTRP’ÚpuL]µù¹ŸÚš Iõ*[Ô-ÎÛømŽ-AbÙ¢]+öÝml-ˆP“Bªî*¢YGï¹Q??o~½tûýе}Ì®Ž-¬ë d‹4ÒŽÉ ùíÚñµAꪮ¾ê.iS³Cé—×Щ¹§wþ×ÿúƒ²c¤ÿMŠ˜™¾iÛÖ34¦’B2 ^mYKUoª¾1ÊQËÜû¶˜E»û8úÈ+‡ÌãÑ2þ6U¿DËø×®bÚõßÁë.Á”Nº¹ [h‘0Å‹ºA«›ˆø&Á4/d)úp…̘H!ãuàž‘È& {pHºvîÐN—»˜6†.W…øóË_D†Þ,/‚_þÎðÎ [þ>ÖåoCIŠ«¹¶Þê?ŸÇåòCE¸| –¿Ý‡þºioÕgôAË_oØ2+\зù‹ wó¸RrŠ,½^j rÓØ·æzËÒ ãÞù*à\q·öas­€#A¦›výJ¥iÆåÙÁâQ‡MÖ`{VظT°+÷±£7Ì®ÛÓ–ÈŠšÚ‹ô±é lä­¨ÕbÑ­#Hæv.Úç€"ãŽò~š©ò_åwPZW±=J]UPÚiCæ½}‡ Â ¶¿~ñCûz,ã×sÞ¶ïÖµ_¬VÙÆbŽv·r´ɺ:"ㆤ*™Dº~©} 4éNxß~³YD à7[¤A«lºûÙ2“RÌ""Û„µ‡¤¶ -A¦4MjEvÍ·ž¿³Cn¿ãƦ l$-2f[×@N¼B&\f rŸLhcn9 ·fu\ê/ÇÁsRÂL²9^ŽûëkTƒ=E¦îZÛ÷0¥r¿¦õ9ÇuÝÃX—ÊèÓq^‹BV,‡òZ2­=—:Í¢•³ ò¬¬4cVÔ8%H!ÓØžkõ²µkšeñ•ªN¹ƒJšå|;˜Üi–3)wOÔ µÈ,¨~»ÌG´úÍr’ùJtœÃ¸\ÛïÓ! îÚoCf¬ÎX+\à~2+jý0¡›f’ÏhÆ™ Óˆ;?b §›'ŠJß)b¹Ñ¬J“â³*2aòPV¥C†µw8ëK!SîýD1½¶_qK4©gzE4Ž+`‘Y˜£6 ˜Os&o@óÝ!5$ÍyÌ6»¢%ÙiÎnÖîyɽ!µ·’L17(œQW$Ë(š ’Ë(¢Çd2Цž EçMF‘E2ŠÞ›Œ"‹ fÝIF‘EF3оQd‘2˜œaº=0Òæ“¡ûPƒƒ“¹q¾j?*œ²+‹Ò/Ê«±‘&õ¼¨?ÿýÑïÒÙ­µ“Æ‚Æ%Ï‹Š B/-rÆ–ôüX^÷.aãÚ€-©o‚§Ø¸6Àf¡þšTUµÖtW½i÷VƒR«‹BìW6Ò³m†ÛÜ}é1#ª\ÊO³±YF+7±rZÄg­Y_üYÜnW•çùyöZ¾´‘»¤WA¹KUì. íz—(2p—LÆÛm¿™EV€:bº%È<âõ¢–¿píâ7ÃÕÚ ÿ~Šht…ŽØ@vÞ)¶Í El€ž-%4žÝê©,RÆ`·'*‹Tp:ÆA_;3×½gÓ´…cQiMSb\‹“&Œ1&SbGûg:ª½ö»ïêûÅ!e ßrw ÇYÍ3Iú-·Õæ{j§™3Ôë†öÇÔëZ‚Ü%ø®Ï}PO}¢HÜú±ÞÒ_/·wÞ†ÅÔj 8¤Œ´õQ’SO7ko´ÙPn6†ïµÏåJK6ØYE§eÊè…°UtÊø0ÍzJha¯]fý@ë1Üý,óX>“z=05(-‹H>“ÙÇ#Ô“‰k!Œ:KiBEŠ]‹vÍúÛ³]ZzÌ‚Êa¿NÆ®Eê¯ú2ŽèÎWé~¤½ZµRÿÓ>b—VW_Ò é– ÃL–+]ÓŠKìÓªøâªÝ»d× ú˜dÍ€ýx€ÍaVꮓuòãÕ…S@-?]?v™mßµòëùþ&HëK²¤×÷seÜ\ß°Ã~<ˆÍatR‰ˆ/‰>OãKB‘uȪ»«ýW\ âK²¡Ð7¨ÎàY á¤F »§Š0÷S[â8óäéÞ¾9<õŽ0nÿnßÏ×0>^ϰ\ \3õ·±6#Ïóò:7ÃújŒ¥ù)ë8?Ÿ?ãñvÛœgáLSg3x›•Àù3ã]6äCÖ„NïVU”ò=§‹ 8ècb§‹Œì¤°S€Eæø{_÷qú+6¡öŠ2œí¾w§N\ƒ((2ÔçRoJIwÈ,²ô)é™Ç+Qn¤Í¹Úkzn£½cÚþ;Qä–½µŽuç×Óó¼,2‹U·ú›[ÛXdî|ˆV¤å Lõ²ÜŽ5Aá:˜ædéyRö–Öè_u7ÏË"1{Ëi¥šviÞ§¦§ç)Ãs±Ú#€'¢E†Ù[¯ºmQàî|”½5î I¨š>WÄ §Ÿojf³) øƒfLÍì£e¾™F#œ@²“r®«4øÙ!çüþϧÈW¥Fjh‹Œ§Šç%;ÖŇyf‡2êikãá.PMë6Þ‘ˆŸ%%ëaí+7Ç£YyIðëûÜ}ðbFx44Ìq$ü©,=0e8Ì1K±cê]Bó›ù,MbÇ\w ÀŸÊfÇ›[ˆà×ÓˆQ㜈(2õNη]+——N¿#Á~zÌèö…ª@–¦ü6Ï AâLuMj:Ž¡£È20ÖêŽ~G?Ö¥ˆ‹·ëNÈ=Ü"«ðXg“6wþ+5`›¥¿™¬Ã ’ò&ë=˜¬[$1–ºZ)øñøüö~Ic&ë?“u‹Ì£Öé§®%È",JÀ ¬,e ïz¨]`Á†)73cåé%3Ôzq ŸœdÌV0m/#IåÛ6 &œgÙ!bfÌM‘MX†È$Ûs&6aY–üb6P$c¶AF,ó±M˜EF,ó±M˜EŠ8ñ£k-j—U ªíŒ12‹h%dV†MÙe=OCT˜µ38AóSÏ·çÙëR³ ÛV’œW--B¤—,ÛÎA,Õ¾ëËåo]&¢DÄnÂDÄ ÙEí—ªº(SBF•àˆà7Z‚EæÁÄÍó<.¸™¡Tq[x‡òEÿh¯S³¹¢5"ã?W¢7ÈS?DZÞüzù6k¯oÉPþø6 5Ë C²2Nã!öp6À |Åž•e“´ŠmD2Lø!. ê˜Æ¥ÆœÉÍ5. ®ìŸåI,Ödsz’p–§LަÖÁØœ§¬9ݲø+ÊXsº¾‡…ržÅ“ª;#spÏ'@of„ÖXßÂsÏóèÓ4t°ðË5hÛ’Ã4‰,lKΗ³\ì 6T¡'¡ Y^rKjªåe|Imˆ þ~JN|V“ÜDéžêohfx©šso2¦úgØŠh³Ùn‰82CDš°8f®âÀ¿É ÈŠ„}“=)Ë"ÓPövO("Y šX ‚f<+2.{{ðF±YA7]4s“E³"çôäŠ N‡®‹›ð낳×D¤Á¬(Ù_G›.ìrCŒËWƒ6o\žU̸\›¾!ãò ‘^6Æå ‰Ë3DzÙ—k‘/2.Ïéec\>´Ä¸Ü"Æåze…Ë-2Ü Æå0._Mß¼q¹Eʈ;‡Z1Á*¥_Ó&x{¤î™O¿ºs¼>®åa‘YX\£kQð&‹ßÜü¯§œ¸‘2–ƃÉÎÉÞµ#±7H&ù— @P³æ}çõ_÷„÷ÓÓx *ájßÏGói~ÆéCëŠú_³9l¬YÿÔ´ßþ;BA[Rë*ØñÔôLˆh‹³'æòY ÓÚ…zõ$Ô+\Ó‡zeâ·Äwi…d?0‘&ëeáiÏŠ}C*F@ÚÞç¯Z†Î™F µH¾š• ç ¢õ°®ã|fô>&Y”HcCiüú³äÈöº  ¥¨’#ÛkzcO‘1CÆné7¿Og÷%ò’Og÷¡YY0z½Ù…÷³dL'M&é(2H¦a/ŽÿÚE6ˆ !Ÿ™mcˆ†½Xd¬}V«÷{‘…Eá°Z±Àz¾”Qï¯ÙXß.pÌ*êýÕj•XafÞåfÁN7Kùy~.ïWÿºQds û´EæQ“ܳ¿"Ÿáû¯ÞéëV׺¢žÏ¯±k»ûD‘sŒ þšK2µõÏ0<>A–QãÝ»?«HNÓï>èyVá=‚Î4€û)\™²d/ ¼RíÍž V¿2eijê‹RV&S&žGd2VllS ¾8«®HT”¿Õ¡Æ"«BÝFÆj€ÃÚìñ5@™£ïh7w4žZ™I>zA-½G‚ D/¨7ÄD/lŽ™íe8Æÿ Ép2)™-–áX$Ùs]x¡tß~€cbóîI‚õ÷§cÝd ÝáñxÑcfaª¿ÙjSd+yc&%Wå@ÒòLV|ί“=)ëßùC+½®ÇT{Ø®]î~¿‰l{è•€¯æQ惩{#Ñtží;¡Ô†ÈÕ“ó,ùņh ÈˆëoÝ q)Kãòÿ ‹úó,cXØ-ÏrÖD=|÷.áî?ƒ4ƒäØòbß?Bbuÿr$Jͳò—p{E’ DÔaþ˜¿‰(aLÎq¤þÜÁ¡7Ïãö«­‰.‡óÌS†´§ëŸþ˜u<>k+aƒ<-Ýi¹¿ß€Ì·ôhÓ]½ß?ã§>O¯Œ`yN«pk¾vúÓËõzòUNÔ÷®ã1Ô7¼Æc\¯ŸKë:b¹"2Èãéfû\çïãö<=çkG…sQ®jäÞ¿—Ûi~Ôß#A ‡T÷ý²¶ÙÔ\ô^ºës™  Ì›´²SNµ\ûúo3Ï}ŒÇÊñ‘¥½~ëŸ;AV€t &÷Ïë|þ´ßáB‘–o¡«BïÕ<Ô.±Ï…&®©+ «éòü\ºÛ§éÎjÓ÷ïÿV]ªuÛ»ÇïxéE™pæzÑ$ýœ^…Öö³ôÙ'æAÍú‘ºu˜ºýu;7—år¢Pý¤¾êÕûŸ6Ž4E»ûÏÏp¹µ·é¸9±*ì祖NóõÔ)´ŒØ‹6㳇§0Gñö¢Ã<}[‚Lãö¢®VçÅNêÑ\]•ëÚŽÊžGY‹±o¬Û™"ÓH€#^k– A{[A #dž+4 oèu@^ïÇ’ð~Îf èa~½"‚-]‰t\ž¡ûÌÝV¬ž+ñï}í³•5ûx56©?þ}òuz½ûÁ"Z5–´ÏgÓd‘œ^¯jÍl‘EÊn×Ë‹:k¸óE¼21“—¼H8K]¼º,Òè<ߒȪ¼ø%œØy‘Å92ú¹ƒé]^äûruLm_>Â;_àpêÖº²½öswì½øÏ"³Øûééó¢àƒzý Û¨lâŒÛÕö®¨ä¸'j‘ãŸQœ¤]Ú|Ÿ3/6‚5†]VYÛ¨«µÍÏÈhÇTôoV§Æ{w¼u™úA\½I;)Õ\»80\̞˷"0÷mŠðún]3ê~ÂމePæ¹ßÜgÔ™sC‘iÌR÷èWÁšwéêlõi\¯~/+Pü®Y\î7[íX>ÍÏëå¬-²ÀkFX×Ï˵FI.ò€5µÝÅ|“\d¹¯˜7D‹.ý»Te¼±+0Fó*çx‹ >f±SÃX†¦# y%b ‰ òJDºëz/ƒ»ëy%£ñeñ´9²'Ùǘ..×… «p'GóýûY°Ú~­X0 “ºŒÞù½¢î~u¼ï¹ïn £¬µÁŠº")SFm~æï<ÓïZÍbáiV\¶*êØÑÞþŠô;©‚X:øJ¾ÔžkœÛ§C¦lÏÜW ‹4ãƒü¨˜æÌWŒ#° ß±D`ÁWœñ~¬a@Lpž‚×´¡_/9Vbº©d± ‘V«™´ÙK/GVH…ïZïg“^>Ì™†‚˜f¢Î,2N¿‹Õ™™2öcî.eYlEí,Í(’3*ë ’1*›Z‚Ìãú‰މú±f¬Ó•gkFô>f°þ-2.ÌM}™þ{Ï•½;hï¹iôåAËÒ›¿Ÿ%âѯÝàæ~]ËÉõ ivpí1EÈêÏáÓà‹,ªiF’o‘L¼?«_ÒàaÅ’U‘4xíè€Óà-²»Dà4x‹ ¤Á+$Iƒ·È2RA<å‚„i`{Ñ5LÃÛ‹$LcÇé@ö¢Ež0jlÌd/<!¼RF^‘§4xÛ¹S»Ý±ëáŠ2n/ƒT¹Ež3ü ”ëž&êo™D«¼K¨cKGVäŽ#…ïØ†µ#?ðuä‚ÕŽ|ç¦'ȈvdD>"YÄØK{®¼äFµR…wžhëñè­ÞO³Rõo䪯xÍ€úÅTÒ¨y³Q3ÂæòŽaQ8#;do_É/Î0Òé/Îð4‹”©”bnT{»n]çÆºþû=\H±ïØ6N¿;«gÿýN_‚Ü[YÖú5L¯Ÿ… 3oÊN‹ÓÏyy>¡f‘ëzÞô;.ÖGäÝÝß?ÝNHY„÷ïcãdE(v·×#¼É…àk¿Ð( &ê[KÚü¶ˆ¯~{žS„”ýT¹çYý¦\™ ’S®ôÉ(W&úëylTDw^øH[èM¾³b^k>õDi”O}…¯Cxw¥÷ùå™n™ÇtÛÞÈ®ØhëiÅ ûI"lïy·‘8KíX½VÌë^äÅ.CtÞµ&^ƒyy!r^ìW¿‚÷P P1 m]§Eæå…œ®‹³dÖó^'ü¿ÿóúÃø¹?`†’èq°œÕ:èL‘i”uîW‚V_m?nÝ#Ô×iQŸAšqéû?½²j.kv8ý ý<¿{úëÅŠÔó¦.éù] J—çsüéé1E¸ã %mþiVŒ%#fõ% C´¶E™0ª5,‚¾§(S&Ä÷Ί2‹-.†u>u½ÛA—y´‹az=Ð?*Ê‚ãÀ6žÙZ”‚ÕK ¾òŒÕín¤Öæÿ¥äú†µçÀZd÷••ïEFÜA`¬CúòÿÌB‘÷-2‹íµ½Š´ ýÍ¢ÞÜß\Ÿæî¼îs¦@]K`ñ;éæu¼ž™†vRê4› ÔEi6jhf}?µÅ¥Þo6ô˜9ærXNñÔ ·Ó‘#ék€ês·!ÒÝmnOÝVÔWþµÈæº2…mÓP‘`\©/H§.Ƙ:C¿|†îToÎSFxk(Ü©hî Ü->Ö«­6Ü¥|·ƒÞ¨œá׋ßTÎ-Ar*gz̸ÊÙw…dAúq˜í3›ž)¬ë¤àºÕ[)¤ˆ0E rPçpuÈ’QgvF¢è’[×im(œgÅ))ëÉïeª£YÇ=ý¢JöšKˆ}ëÔ¸u°*eÜVŒÏxGỉsðû÷*ãuì΢ʙu]3 •ÕF9½õßòšŒ‚Q9뽡çU¾³ô]Ã÷Süâåëþ k`Ö®Ê]÷B͇ÕЉ¼×P¨dŒocu=+©¨88ìfQTUÜ4ÞÔ“Ýû)‡H=Yïµu=Ù½!âpà¢f´óÙè ÇJRë ·òØ0ßÏG7·çjzžcã¬]KÇ&;kÄè¯(°ô.f8ÞÀôXv\MÔpi§v:d<~¡ŸF‚Ìݘì×Þ¦>ÿœÇl´È«ßœ—[û¸§i:¤ ê·5uèÃt½NôÚKÒ­¾º:XÓ?'§3¶HŽtxwc?ÓcV‘H‡å ]uwçñL‡-4‰Åœ/ÀT\XÁsÞdÐUVÇœ7 ·È,Âã~PY´È<Â`ðÍlW_gïN€,·oèø¼Í{éOþ •»C¯0Ǽcqû=Ÿå挄w,’ç× Eâ`B÷ëzÚ.×f È0ï¸1¼czE‚»Bp{=ž¾#A–ѶÆßyf/E”±÷ÿ‰¶f±Úšñ¸ÁvPÒëN‘ixÞ®kM=&Häu=»N­o»è ‰$v'tHð ªu´ýÆ@K¦øÛhaWßOxç“”ò£/WûÎÿü|ê×8‚‚×"½_ÕÉÉïúî{m¿ŸKG‘xõmk{êŠÆ¶k6W$@ÿfŠAu„¼Ÿ×†^‘éÀÿ¬Š>÷ë};éÔzzE2¸N©uúàúYÅxMã™±¼®óמ1ÜœÁd§;déchÿ…Ö”ß 2ÞÚ³H Ök{ÚžEƽ¶Ñ»TÄvœfÍâ½{D"˜úv‰`Ö,ºsc]R2ú'¬Q„S°ç›«‘ ~½úE£æ½â#÷ü:(=Ä}ÊCY¤ ÃÉ ^‘ò^ãÓ­¾Eóòè­—Œ´)òòØF÷ÜÔ´ Þg"Í¢|Šž0UEšsÌ ¤Qi±ó pÕ îý~÷gx?Sõë×*ÆiéF‚ô=1C—4Áƒº•7pd‘«Ïãÿþýߪ±°1ÍS{®PdR¢¨Y¦[:ç1$Ò2êá²ÕˆšeÄÆóÔ|]_]¤2¢w\–fºèžXKiü<·®L+þ<ãH±ø[T/Ùë….¾)²¸ž¬7ß&¬Ó±_ý6›‘èGE–Ævœ«“28-Š,ã7þ+F܇­»}OB~D–ïøSxÍðôk†¬ømÍÐ$·fè2Ûï¥ÖÚI3†˜!Oðë±é2@;ކØs4¶´Ar´-Ar´ m7´ m7´)¶c²íÄêjÐ×!åîÚ±6qìaœÏ$¼¹"«8Òi‰l7y-ÝO­9¦î¹ç‡xœšþ2­i‘ˆÉ‚j¥S7=?e‘¨»kr:Ådz©é@Šô˜9 ç»8äãþ™?îÈÂgóÝô»t[£ÏêãrÜ\‘@ÕßT·ç¸ÌYBçrYÔ¯?ŽÇ©…w~E¶æíÑvvNßê`¯ïø¬7¿^9%_}rϽ=.7µ ©7W´º*8hc—ªç[ÝÇÍmJ’ >phucjsÔÔCuÅжžÔÒûÙ=7)A~Æ÷–Lõý3Ž-“?®ÖBçÔãûx¿ShT(Ö§ZW[¨qUP¿¯>G>9ׯËrVÃýD¡å UëP­à]סŽ(ñµH•qz©I\¤Hì&Ež2%l7)HPGÀ–}ñ×Ä ¶0MFä9»ô)Ž"/H‰Ñl©ŒûrÛÍ6æùv™F œ~C‡-%ö™ôÈ_x‚Ò&“^½ü$“^‚ɤŸt&}ßùû)˜Lú¯Î¤o 2Úñ7¿Ϥ'‚‘BjŸŠ¼äÈ×Èh^à@B©Öo¦T‹\r-Ùº uÁ’ž ý/éƒÒ²`¨LšÒâ)Õ¢8D ³4%O01!¦} Ä QìH¸6÷ÚÐOPîµ †$÷Z­opîµ@ô(š{­‰s¯-2{­·ü8÷Ú"C¹×ÍHr¯-2”{­mÈPîµEŠôLr¯-2{½ZXzs1‹Œå^ äÇ‹5Œ–¹ŽpE9gñ¯¢þŠâD]þGÛÞ‚±Ÿ#4.QÆ’~>ªWÄ}G$L…Š«ææÒü,– Ó˜ˆ¡a;Yp涤àPȈÁëJƒõ¯¢¨±/6x8 %0.¡²6C¹Òß»ºñ-A¦Á`3ºI %(YB£7‰mëß:L΢¶ 9©A†"Ð4ò8Cš@ä¬ðy¦[¤¿œ§³ä±Hæ<ý¥ÜyŽ7tž)wžx#¨aÁü ¡Øòd^=³,S͆‹š ¡P,OfC{w6*ZŒÝôß/,nEÆMÚ}Ï!™ÎÐiA!\{ñK¸ÂW$øp\BðTz¸BĨôkdX‰dæŒ7xÁ:™y„ã >ô˜*½BõËSé…@qz~³Ô5‚`ü1{n½MÃöÜBÄì¹<Ùs[d7K€õcæah›¾‰ÇEÎ(¤BY$ XvÔ6ár¦÷æ˜Ù©¥œÇfzoŽ™‡šá†Úà‹ê%#¦ÚˬE™pE!("Ê””P¼a®ž¹´åˆGr%SLÊeü‹ë‰µ•( F¶®›hþ×'cÅk0ŽÆñûŽRü³ÐcæaóP]*‡Ù°,ÃÜÙ²‹Rò¶^ ª%µˆÃ¢ùE‹æ}CèÜ¡ÃTÖâÕ|þŒÇÛmƒ\ï’n³žMEJ#ÇógGO.(ÜË[Ò;ã·Ó FB&Q»¬–P™„L÷„¯Õli‰ƒÀ!>(έÁƒEmÙÛáñhoŠŒ¾ÌK?d›;êÁj¦°íèÓÑG YpMóº†x¢G´Ôøt1šê~¾ ͰoœÜAȽâÝÍ\D!1 #Ôñˆ0BHF($FX$#Œ€9NŠ_„þiЍ0b&Ö€ÂÓâ–øŠ%j=˜»¤#¿Í¯k»ó{ûj)ßyKiy ããõú Ë• 3W»ÐïÜÅÔ˜ÎóÏëÜ Ã§%ÈœÈÁ­p¼¹¼ûÇc¢È"øm^ô·Y÷?öã’d-•‘¹”À2[á‘ЊE•p2d+,1 Õ­Ñ8^T'ª”‰7À¢:Q¥AyÓº?z6 XÙ‰*‹J‘L°„‰}˜ Ðâf-ª"ÔáGÅ'Ô—*ÁYt45˜yˆªäê Qñèsíó k†Š ÑY¼¥Yy8°Íh?k—&TØ„»Y¦<¤b¯‰ùDñE% ¡d·žÄ•‡,j:2“ø"‹Ì¼8¾È"ó°¿•ª’zè}1ú:ÊCÁ é¾<{™uÍ©öôà×cµÊ¾³µJŠ Õ*G]«¡a‘‘ZåMíκ™ µJõëk­r"È`­²ÕµJ ³[¤ˆ­i½¸ª<”Ñ OOL‚ËhìŠ~îØ$¸<ì[Ìn/3OÍò=½îYqf ˆö^&‡ß,£ÜsO’ßl¨(’3—ê 2n.Õv-Aæa³CL¼)θKgÊ$ûŤÍÍÅ%‰HÁ’)Ô’)ø6 íg}ç×]dÛi%|ÿª‚ô¶4jÚnnN~·|Ï0—žöî+ô¬õEÇág9dAq©7Æ+òsÿ< ²pô$ÔGPçyîo·Í¯ 2éuˆ¹"}ž×s{ïé1KмÛ+ºžï¯…"åŠÔÍ>³XlÖ+ºøŠW¤iöýóßzE7@~ÕMô<­…ºuôµÛ õ0ß§û²}Hƒ»^ýþÌASç :Ÿ1{7^~¦¥v‰eŠêVg{T ýNzÚ5÷¾¥Wûš4Sý™ºîã º¶eÿ§WŒnSG}«Õú°lŽ*|éÊÔ¸ì Lßs½½¬5¤Æ¿§ëóZlnÖÚ™µ¯JšÎáüþ7 Z¡šðçd€?jºùÞÆsCŸkzÀŠA[@ê꯮—o¡ 6rA5jqyŸšÍ¹¦iláèÆÊDD] {£ ‡ /aÝê†ØeRFÐLqÄO‰üÅûÅR£15÷LÓë’½ø—:=0™KÓä·ýË\š<Û"sHZÐ~fѬy·çytår‹,bÈÏq¢¿."éL_ŸQi‘e9Œ¯V!úë2’ãôn@µg‘U ‰žfz@¼ú€¹†·Ñ,SÎÀÛ¸—Èðˆ]Õ1‰{‰(‡Aw¨´•ˆrè~ #¡2å„I‹:ÏÎ3ç^;µho)2›øÏ“H¸I™ &Z¥ÁŸ\ZÆÑŒCAyAš7@)SÆVO/ýýÌlïÚGæYd_éÀa*Ÿ¯6ÝøÀ‡C•Ù¾k¥,ZÐ0Îó©'Hèß®^g;¾ôÝ©£ÈÌ…“®Ç´Ü õÏíõI¶ûÇÙ£¯]ÙÏûü f‹ ‡CÕCwçA†û·µéߎYne'h¨açm‘2fX<´0(glHº¹S™³Aáø¹çñ~#1•.³‚ÀTºÌ ¦'¬ïì}3ÁTÁ±¹[™•œiï2£cJ.0—YÅDAàè2g¬¢‰™x™'Œ›‰—y5Z ·¢ÌSF‡VËG‰Ðêý]"%*Æ3f: ‡+G)dÎî ¤e²‰Y)Û31<*ƒÖHV$L JÄf  ÉmÃ#mž… ,²ˆtÒqC™³2¯¥îü1K>Ž­oà.I>Ž =Í8ÕÔƒB¨Ì«(Á¹] Î-A¦éoí#ÞÊ"¾\åݰ+ž³ö%f …8 À¥*‹ô7HG„3 Žó&öVE}×È bßË"Û½ÉëÓÔor;_¡®o‘7ùíbßg‚ÌýëQ½ó?-A!“¯VÄE ÌÏrþöµÜnó®(烃¡ŸSb)7wÜÍ#ÒÑÒíˆíe‘sµm6:¤§ŸuÏØêÀ¦´OEl–ñì›2n e¬‘¼ô¡,7&#ø²(#R=sH(P’ îªÕkçïR< ÙQ4þë¨8 ý–pd ¶Öß»;Oq࢑ð¢LxÕ0"èǹîÜ*\ÓŒ õ69æf)ö,6Çõkû¾®O8fΘé`ÆY¹1QÚšúyk¹RÞæÕ´¢dÍÄ}€l‰XA3ñï8dþâæ£ê.±‘Ðî;ªQTw)ªh\OÌJÊòyFfLÆÏ¨dÆyoV²á+ØÊ§,cÏ]¯TÉs/svçù×%Jùg½±H«Ñçýçåbgy¾—˜û2]ÕBè©þ"H[æøƒÙÊS]Ÿ?„1”%Ž–þcê‘ëè}þª½Î–î2wHÜ¿}¼šÛ\o…¯Vpsþ?Ã÷ $}‹\ËF §¹F‘}šû´|ü]òÑDº#}<;ÖÕ2=~†ñ{Þ\‘ôÈ›“ûŒÇ2}ß›_¯P—ÛöÃ?·Gýno…þº­°šú¢.‚?Z]W×ö± …®1Ôÿñ¸.Ÿås=7íæ¨)&ˆÝÖ[zSŸÇéÛl.ÊÊ)6¶¬½±e]Þj'äÕ äfSÛêËÜ-ýu¤Ð"´ 5¶›`Vè ”xf ìZ%r?þ\î' -75½lÒÐ×ç>Ü)TbèÝ6µúáu|]Λ£Vñ¨ñË’³£CQ9eYF¸å¦Kˆ÷?Äšk[^ÅÜò²”qñõjF¿^1öi˜ñXÊ;Ó£YD²Fkêà‰Ê”‹è\àÿ—2㘙jU3¨Ì© Áš@ÆÖæµ*ÔdWˆÀGâ93{ÝÇp:u û(¥ ¶Í;݇ÿFgF‡ûíÔ—‘"ó¸îcƒ¶g­GˆÆögûn€½`‘bÏúÓkÌú+%²aügvt&vÝ2η´f·Y"f·ƒ3»¥È4óŒëÅW/Æ‘e•r•&͈p÷3L[~å·x¶|É…¶|YåñªåŒÇ,~ F)2V£ žýý ó-ï6^¯œ&«¬Ê_¬ `GWÉ_äÏð†`+)ÂÃ1¬Ôºüý¬{ª‡¦¢ô §B\>y80uíºñÏ]nôFŒyH9伇ìîîÇ̱ep+y(8ëMÄþ’ÁÄà 3yàªÿ¸£ ’ë( )½Ï ó¸¤ÈâFØÚrqœ@)²¸iµ ‰‡1Yä|ô„pKQðÑG`Ú'qlI ¨²ï'¸vA °!r«ûÜWçŶ †ÈújžÓw"ÈHÀîGK¯8ÿgþóŸmÖ7¤_÷«¿¢òmŒubgô v‰íûréÎþiƃëºÅÄ-PdŠYè«Rí¹kýyÀø‰ôÙÚ~Rƒ©#Ï¡[{ý\úSO9F:sÖ[×wÃ}¦È#ãÞ]ÿ;‚iîÑ\×<î}ÛßÌ"Kd“y³»®©iojµt¤¿.ݾÖebóÜÕ]Õ%5݉ «}€„B>Û¹û ô×mÊô|n&Ælö—ÛÜ\û 4ÁPLvU+°këW šîs)Ô L­zœÛÈ¢ÁÍæ‰&y(e&Ò,‰…ô{A ’fYdʹë íË=HÔÞæÜiä´/‹Œ“e~à)–,óýy& Yæ¤É2ô˜²Ì Ä,R0â=8fú›x¯%HN¼GïA Í"óˆB ,e‰–6‰$u£Ià˜y¼p¦­{—Mf‘i¤5U£â&—4š&ÖHA›3íê¾€í‘EfAäÜ¿=ùÝ"ó°1¦ŽJlµ–ÜÃy–¿Éø)’ç·ɈóaãU–Ä”a'~öEØ’MdFIñ²¬"ÔÑ•*î}–¥;ääϳˆ§¶˜]ÏHÁòŒ ³'Èh–ÕéuͲòÂ>‹Ìct+OÁ®pK€¶8t3\‘dr±)mEÈ ä­Ó» ´º¨0Ya³NîÉê¢J‘÷ÓŒŸhuQ!²Â¶l6’ÕE•~Y]4ô<™ÕÅ@x?µ ¯.*¯4߯çOÚE ÞÏ4‰ŽÉ½“/dÌ¥hšŠ w)eÄmËRNìR¥)+PðÖ½I—!Uu×±l«Bý”Á˶,2 Ë8D¢ªÒü†ŽYüâÃàïgÁÄ£ÌÄŠ“w ’›TiÉÑ”ý·Âòñ=ÑU«´bÈsz~‡¹#;DÞ%½fÐó;ÌX>î(\w{žÓ<çùæ #"™NßÙ¥+Z$-ü¯7Ió:~ŸI­ýVºÕúëßͯçŽÐ¡Ç¥›%‰ýát ÒŠÆþZ’ˆC¶Í¸EÒì:GwuÚ*ÑV鈞eðž %èžKÏdÏ…äøtÏeÖ´xÏ•söa&àÏ]QŽlÊÍ3º]ô»´fÛ´­®9dö ÒQK«Ÿš׃'tTyÁQ«ÊCblÎYþÒ4î(21yO•sU,ï©Ì=@¥A²™ ‡aìD·íÓGTÅ[Ó>ê *qÂ!…ULÆL(ïU‘r2DQ©ŠŒË­þiš¾#È4VÙó4·*Jèp‘6°(Š_h W B™ª(y; vV…äˆf(«*QÉ쮊ŠÍìêž"Ó8¡ž‘`3 Qå¹ GQAR±J¤,íÛ‹­+‘ñ´‚Æ#snˆÒ7+QpE z—„àÒ"‘t¤eÔv¥×k;?k ɼKØ<©\OªQ$X©–N’Þ ZP™DÇÏÖP¨à<Ë4þëÆLÖÞHÄNãóÇŒÕmܾö°eþ˾Ø_{þ˾VAeÎï‹ý*¨ü­n_qù[ÝF›2ÿe_ü¡×^†sû°«*Y«YÔ‹¬JÁØZ`둪,ÛöÉíaG‚Ì¢Ò&?†”2’ðçLJü›\±&%=˜”XdÜnç±ÐcFív¼I‰EæQë‘¬Ê ÙílÅEz_ õ%y`«¯ƒ?åËc^¼D°’ kíI‹•Dë:cp5w^›“Þõüêgm™m·ËJ4ÓI„çé3<¯™nÞVÂQ׫w ª[2#vê†ÄdxnšBÕ}ß÷‘"s‚4Kƒ|½/zž̆k´Ÿ±Ð|ÜÏóýÜR¤¤ÙngÒŸ±yuMíÈÔY‚™»&š5«ì²œë$Ê[¤DæøÖÊå=ýÔççZ|‹¬|ú¦¡™QñÒ\n'ðÏtwþÁ’',ùÓÿÜ›þ3oš$¢[Ó¬D·Ÿ‹ÿæ,‚ÕÕ½› Z£èqDNuš!Zšž»ÖdËvz~§Óæ¨ÞÆÒmáµßìkžëaj(´p¬ýL»óºs÷ØÜkÌj :kPª̼>¾Ó0P(IÌÔC®yOϧçôÝÞ5^]Õe(«{ziæ÷|«ßªŸÖWML êÞéF½ÐóÜ|›}ûQ½³/{ Æê6¬}'Í}5¾“§¦k)2*£ß›cfákœHRÉ‚S5êH¸Q"ÊîmÕѳ{+Y2ŒáZ¯Z;‚ŒÑ%ðvAòaè^eT!bEXeäÆŒ¸aWÕ~ƒÞØŒ¿¶ŸZ¶áÉ>kc °nÚ÷Ð?»ï— ™ úùBYœ‰ "¬^ëÝý¬²ß4•É)%{‚Œ+%Á‡Ü"ó~f&ñÄU•ÿO Ì*ç¸ïˆXU¿Mô…m&Ça&Þ‹UUr%äÔQ±$¬£¨*Æû·–‡ÃËiò´#…dR¢4 Âm•2åj·`ß%…ÌØï]­Ûf‡ÌYWyÐ¥(d¼hÚbÿV…Äψ¶;µ¡ì]a[!Ë@‚ÆŠTß‘–®3A2:4ír÷¹ì¼g*dÅeüõE豌¿²’Ë"l 2Ÿç⎙~9O›EèÌyÂ%‡ß²[‚Œ§Ï"TÈä·,ÂŽ ¹,BŠä²G‚ÌC¹k]2e4þHëâi8K i/2è+í(–êNÜà~²žqž§k‘T…drÙ ²¥È4Ò´Á¨èY9N™G0ü–”\&ˆoï+$GF¾+ YE=(Vg ëƒ\Ò_µ—î I“ßôœÉ©4[‚dTšpíiœ‹]±¼ù?aW²Ä(®ÉH€àøîÓ3Ÿ€70ØØ€ Dý“„TªÂ’Ü=Ë%³h)Uee®#üº;&.ÿÓn×m,ÉCj×ÊÐaé ’º¡œ‹®Dzºõn@/mÚ"¿"«Å¶ÊúÒ[Ÿ;‹ô®•*Ñ » Ëb -®óS"ó¨×ðÓjzH¤øá5¼tÉ.Q*¨…k‘£<2%H·Ë,ð7jå7z7·o²2¨ ÔcÅqà!ñfV›®[»&ãb¸ » g¾$ß HâìqœÇ’¦®‹X"ÓàAQ@•H"ä§V«Á:Ï‘¿ŒÏ‡ñ« ÏxÒÁøäHMÅë wí’…]ázMð*r'>‰ÄŠL6õӃ׽ßïþ;/=íMW£ ªoº‘ ··¤èQgkòÐLªÈ¼î‘œ¤š¶ÒñUiŸ*úë8ÙSC²géÖ÷ëÕdæ:ët¶CGkr­9]Û™^3÷¦0žS??Ý[*wVòm)œüNË26ô× ä,cH%¯zªú¥}5ôšå¶~þ÷ou¶©ey:i¯ÏfYé[Ú’=µ˜¥ÍJ4S/ïTâwPõ•æÿ©7zÙz›Û¹:_dÐÔ,ôNu²gþßùJõôÐ x3<å.oHå­îjj`†-ùݬÓ'óÁîܸxí)È“ùB!w´å4ö‹¢’4uGkÄÍ"™Wѯ9zëŽf‘<¨è·véqG“¿ŽÝÑ,2ìŽö:Rd¢‹4.ºJ­Œð9Ó4¦è·‚B¢DFèaYî3óÞ°Ë"Ý‚õ¾¦øE}o 2F}§× SßmáÞ"Óï,ŠZP–G"‹@–GFW8Ëc‘ê»ÉòX$(‘áoZÆI .VŽiÞŸÈXš  ßÊòŽö>³$¦×¦öûݳ°÷N{¹<ûæQÆ"º‡Ê·Û]3ÜÚÖjßî‘"½¾Ý£öíÞ]ÓëÛÝkßîÝ5Ó€^›#lHdÄ·^JdôõTD²irÈaSõdTÁs_‰,âÍeî4••±‚¸£nŠCmXS fö-åI4ÃÊÖÉbúß ä%’ÿhó8,O}Y]ãjß^•à¿EzZ]¶¬®üõ×R?ë… ¿œô›×νæ>[ÚXOh9õ™B̤ÝÃ6ªáÔ¬êxJ¯™‡ñÙ–çíêѾ­{´EæiŠYòSÞ†[ó¸Ó'Ûj£”­¯Cš½ïÇq¾À¾™ƒa@‹ N}Du~çÖ‚[n%Rýýt9›-g7ŒË ȉ8rÅág}¹|e^Ò¤@mÓTh‘ÜiK\¬;Ót®.¯ËçSdêA•Wé“ÞgæbÐKcx£Ó¹oçqêé}ºz×iK5·ÏõQmõêî)\ÄbŽ3[ÎnšªË› Pl8]ìXZrßðA–NO]¾O;–ª·œF¦Ô o^G«³ª‹]Ô)a ×*€Ë'¢´•&ç?ÿé;½™U¹’°¥7>˜eºIKè©ë—Ý pµ’*S5Oò` 5Põ¡æÔ½ªŒåfG~—A˜¼…Ó*¿”Dª¯¹Ÿo¹Ž¼§ºnaG6Ð\Cÿ1o`3éUmAÃižw÷*|Î=vÐ2Øj¿`/q‡`ûþ‚u¾,ÒÛ”¿`/‹ ÄMHçË"SŸƒÅ‚ $2‰5é:²’D²xMa„Ì¡àÞzŠ^›¦Œ±;}·XaX"³¸vذP$ ùö5.'†¬±êe«¸*kØÜpMÖ‹ÆúƒYHèZ©Ðù¡Kd¸MvQî <9Ø»wôªaqî:‚ I´õ2Ðkò°g=DETÅj±:’D²:RÓau$‹ô¨#©·„Ô‘,2@…VjSOiÐõÊU w½jÜ[âAuN¥C7>a̸ŽFÕ9ÛflžûšiDAµq»ûÌ¢• FJdsa”Ñ:œ* W)·ÊçɾUÛtÆØ©¶Id.W8sÁ6YíëƒVO}ßþzÛ×ý±oí>ï‘Xh ÃÙ·×öø$HO ‘E¶IÛ}€Y1·Ó ¢¶µûì+˜C½ŽÝD‘™E’ª¨ò Ü#·vŸíÌ -Dª&9ì‘b§¼¹'`'-‰dQº:Ê–—tnj_­,¯‰´,’‡‰í E†´*ˆK†z>¢+œ~JþÃ5fqɃgYÕ6׸\}™†Øƒª]…ˆHVüÁl ‰¬º¡‡ 'Rû§l µ†ÜîÀÖ°HpøÓG ‚LCþXЖ$‘yÔ#juõ>Ä—ðyDu=ìq¥ˆµ)8ŽD±š‚’á³5…¯ v¥m@I^¹ÍÜL‡¨ŒPc}Ñ$2씩éÕV=V"Yœ®'ÔäÀcÒDj‚ö™îcE§þB:á™}!A'üuYj«çh‘Ì«~YGÐ ·Hî× N¸E¦^ðé„[dÖ ï{‚ÌÉ¢×deòî¡aÑ"E@'ü:áYe—–þzIGÝîÏîþ†'Ê=£ÎìïC;,'÷ë^¥×ík˺چo‹ôêtËQWÕV…Ù"=êôzn.Ë©'?D#Z¸fkâ9»ú~rønd¡.¡+üzùÃ%tí’…ÛOíú™$‡ ØRå$2‰û•œ`nŒ/r·“ëHÉv f‰DgÂôSU<¤¹)‘iLoÔùKä·ÜpBµ”9Gx«¬6ˆ×ápz}ܳç_ôÒhõ„$Qn44Hd¬´®[¥®¹ã\T$ ×ºåüåah Ò_iýèJ+½&œ"]cºHØ!®/ ‘jÂ’(ÿÄEª £cÉä€ký6=¼%ÆÃ'>ì¸$‘iÀqIµÅ#Ç%‹dß¹êí¼¹,6ZK°ÌÀ—:ýÍšÛiB)÷ÚlLÂÓxs!Tž}çÁŒ\Eà$2Š1´JŒa6b éQß¶Ù÷iv ÉüüÒ¶é€_š`Æ¿ô¹:~©AÿË¿*¿d]žŸª™ÈÓdærÕgËoŽra¨÷Hã)÷bõ67-`U©Þ׎ …EêYdRÐMs?7Ý5‹m¥ýûß¶#(d\õ˜›<¦#¯Qn,•Q-uh¨‰§-¯! ¾"‘I°qmÁâ+ÉB« ˆ¯X$ó fHYôlèx I©sbŸc‰äqŸc¨í'ȽàÛ×5ÐKd©j™¸Ï,æŠå|M$2úšÈSBKa_“ÆVÆ ’‡„Ð@\M"E,VT þð>‹ï³6a”@ô›–¿œ[‚Œ8?véu~l±ó£E¦ažÈéq~l©ó£EæáL!Ùá‡Ç³Í+&YòÃãV›Ì“C{±cJ'ûµ÷Û‹;‚ä!?G´Údq&ÛËÔHPm×g›0YÛ‹ ·ïßa mßÛ‹ ´ïÎ Á"³°¯ œßÅ®-^GéW”‡rÕ+÷™xv:úE<»Dd7^ÍcªPì-òcîÙópµKRI¤ˆUQ¥>EÌ»ÖɨKdùCF"Q;¡ä®-ï³5tФ8üï‡_÷U–ÈVE¶$’E¶,²e‘ÞÞ‹lY$vS6ðìÊåwíXò8¤#.¤J ´ÉìyóxºlÌ÷Û{’ëÂ4¸¹é:Ç=Èé鸙B‹½¦½ë•aiÎËØMîÍ#¡=7Uã¾Z½_Ãøj;¹Qd¾e ÝySíqUU]`ô×…ù|ƒ4¦EÁSd g.R÷ž"[‚Œ"G‚äÁn‹3¬Þ¨ªî鶨–Õ]3§«¢Nj3™a]ƺEcÉuÕùÚäìì 2 x¯({€kú{§ûå2ß¡ŠQášÔ°åËo ÒWú¡êæn¢×ä_¨ª·bŠ Š 6Fƒ|I ¬uEAÆçv™÷óÓÔóìN|bäm»ŒÍ<¿ÖÛP÷}C¯)l.}ëˆÙrÔò¸;uwˆ— `ä©GW&ÍVf{½ŸÇ±zÍ2$³ nyYþðg‡]3¼PE²€¤ôŠ2ÏeØ}»ÇêÉb¤ê¢ðë<â'®eØ™FªWÊøÞ’«ªûú×[ÓR$ 0¯W”·‰(´+}v4ëh§IeÈá}¹â¦ª:¨®–˜Ùú¿MÌfòiÆÏ]¾}Èì•EX!DÉ›¹ù^~³ ÑJí\¨Ã{¥ë&;£»¼‡öhO=É×D]Þìð£Ëbƒdáû´½‡ìÀâ÷Y/ A² ÿŸ5?‘H÷ÿ³âÉ>ÄN†M"Ó˜”£s^”È,î‚ܸk濘¢pMñ‹}J‘1NiKN©{ó­Þÿþ·Í᫵í’ký¿^Äê¨Û€áʲ×;Qrøáæh×:–HEl«lÓ¸[q÷K’X_‚3&’H󶮓ÉãbÞ °„G´n0ÿ“%aK¨–ð?Y’þà6Xm&Õßc¿Q’E-¶†Ö½ùh7ÌêxA,AGØ…p YRÄëqÐeÂ’2–À¨D0"ó¿E€°s½ëü°äxÆÂhµì”-^R|kËòb, XêŒDµ@O4cI0¯¸`çZ‰d‘V§ÂàšüG­ÞK#ÕjµÑÁøÜÉÒÍb8k3FY4m3ÒìäÓ/c Hcu¶ÇþX[äw.¨¾Ù~©úø…dþçñÚZæÃUà]7¡ÖŒªOG‚ °:1WÓ ¬NÌÿ4È«SQ_wH2p½ÛŒ•ö>Ö+`¸Z½ì• ”ó‹.®V{}²á»söÃ'fWÙ”±«k3N«l:#±!§þ¶Ì7о`œÇlÐPýˆ¹ºv€ãÓ¹ÝKäŸ/ämäÞÁf¬TöÂ"³ý|°ò±3½×H¢‹ôKÅà• ²<Íßa$§<{/SÕ5]Õ$ûO•«R²–‰ 9VmÚúº†ÓP-S;¼o™zâäqÐqòH¯™!àKcÏÚç¥^—±#ÈÕ7á\Ü?Úë4ìž]l¹‹?Ù(ÇþzæÓº7ŸþòŸ¶Ñª€ûü§·Ç¥9s)Š‹õо.Ý{=v¹:5ȶëAlÞ"S§uM<­-2ó;U×ΩÚ"óSõòé} ŸSµ\!ZWm1È"àT½€SµE–È©úNÕrǧjxódUmÂÊ ÚÞ‡ÝGJ®Ö'pµ(óºZße¨zœvP´ª÷WM½VÕ/dU Ð,˜—öûÅ©€.$öƒS±B Ü /#ÎÒ¨)VÉ+ÏEèÔ)OëñI†¶zn¦Ë¸^’¥8Ëúîe¤þ©îÉ}ªD½R%‚¾–…•Ž6d³Zd·ùšaÿÊÂJGZÎ4‘VA ¿ÞlêIè×yà>-Ò=Q7;E÷™îÓØå¡ûÌ"™@%ç¾°bA3Å3OPU$èd®²¯nSï `s›úîS›'ìy×[wuY\3öztOT†2ÿ[ÔäNˆù!ÌúVÚÀ¦f„mA¼š³°Õª>%ÁN—ópXUö[x¢isøõò‡aÄ-y3ôvƤ‚‰ÃcR8G“þnè1i¬>a¿tö$+bYz¬PÂp/ö·u˜Œ-–‘^ì/ë0¸]‚d>=½ž0´™H¬051C›!;ˆoÍCÌÐfŸ§hßtOú¦Ù® ¿«;¬ŽùÌH^OË•}OÏf•?‹q`Ù1Q½ÖŠv-ãþnßéÃe•qmý²m;‚Û;ŠCÜ@º6%0»v =P·cw;Û÷Y$¨^óÄ i¯tK*9è‚仜¡ór¹Z>‰Aî{ ì³·­5°’Hö½o$T(p½þ«×UñˆÜ}R½™­ŸN‡ Cÿ–Ó­;MI;ÖuATw¬ËÀz¦× tÅ®ˆ›ÄŠ”è¦~Ûöº„ëàÞºÌMÒ îé.Gמ8ľÏs[Ÿ/ðæ‹ï®íÚÚé´ëú\'‚ôôËoL³ñéž½tÉ龕êÙ¹'*¾êà8Oî8~ ëÌ{òä=ú›Ï¨ÜãÎPVFìš§Ê™™KdëÁWLò… Y¸cöŽ’ÅªÆ«ëSc%2ÉÁÒP"Ó¨ùŒc¯±2‹)c;õø}ÅÜqiøáðCÞ^“’ ¢BK¸§Ç™öý­€äý³m/v=eüÆb0g,‘YÜèõ²C†ô[w~íïß̨ L-’û‰â“è¯ùž·úù;ŠäfÔ¼ŒîÍçHiò‹õvý ™íïó÷isÅü Š4*MŠ4ÜUx·ÈÿR_nú>¹ÔÌóõ9õÉ÷Ï~ƒg¿½ ÒðÇ67³NÍ»Ÿ«c=d@¥A¤Ü[*¢ærN©€~Õï,?‡'‘žˆ“²oµs“Ç+¼¨£'ìGï ÷ë,‰P#Þ Ç&áh­³f¼`ð+‘<+êûD±"gé¤?9Ë|Ï~ƒg‡(cerŸ]Déœå±Žu¤"Î]åÔ¯"ÞôÖZ·FšYDùNއÉI‘ð0e´vnî/˜›,œ‘›fUu½&û1Ùˆ…c“p¯ËÒéSøQ±3 —ÈIøºõ¥Z“p‹ô˜„ëk:“p‹ô˜„›_Ÿw¿î3 —52 ·HŸI¸Š½I¸EzLÂuDíLÂ-Rx™¥æ±s΀ZñCQ¸Z‚d~Æ{µt÷^“ã=îj¥3«Kó€îƒ„N‡­.fÜŪfºº‘ÌUp¼Ô·‹~óZýö4,[Õ sWk“?¾eݧwuœjP0HáTÄmS®ö(™®ëî× Ë,=žÎÆ©Yä£7èž0ÈrÉJ¿ðdœÍ«¶•'„Û¾y]sùW5ú^ ¼xŸ×úíJæ°øÕ"¸0Fx@yB¯ôíivï> (Oôݦ<»©™ã꺌ìäý|Ü»O¿³Î.ñì8[i:Îç9íóPõ.ͯK§äq5ïS^sé›Ss¬é›? àDzLò š Ž¸1”Tñçi¨zúô C>…[ùPZGå¹Óœ(uû^-Wdºß¦ç¼Üw£$õÉn/¤ˆó²wÎeÌXi`£M?ü²aà§IŒhˆ ]ø®žú¹«*ÜgÊÃâ•ÊÏÝXiI 4k5.pÍ,Pà_MB[ìoÄ­ )P® Íõ9×=A2`è7*½&wEný’ôi§¶{=à–æˆZñ?3ð6⑌tNíz¤Hç2Œ®9×íü¹t™×Í{S7‡ÀzC „4KŽ’dooÝþšÅw½7öÝ5K‹4"Õ[°^ÕÇg˘yó‡ïúzoê뻋:¹`LoèÛº«ªž~¥ÍÜ‚–â[ŠßÝÿUÁõÒö5l"¾b8”ûV$NÃ=Åp×<4®‘—§EÐBjipƒ,OËxbÒ«<;›Yû¾}ºò>Ï’˜)ÖàÊûQn%gtë¼¥Þ,ª=áA‘Â?B°ÔâKÚv³.𮝿çù½ZdATª»M‡ÕïI °‚0H†‘Û!Q¥ÀÛåõ‚ŽpjvœÔ D_ó®ø^k_Áj# $Ù%ÇÒÙ¦ÎËcêOõÐP¤IÀÅ®z¼«ÓŽòµ“*¤ºæö>åqR®²ËÒ–w8û3Ÿa–>—Ëå9$ø¤j–Îr°¦™Ânwº˜2®Z#®kÛXƒÌì|®Ng8- ëç#WSúëÛ,ý»_MžËû½»OgÔvZÆOs[ä‚4¦z5©/fæ^ç©«Vú–J4õ.0Ÿ«ñù„Frûæñ,½À,=·ÝõµÒÝf©zn8¿š[ÿ¤¿ïf)z×'šz ³TͧæÓ©o^ }~;K÷“äuy/ÀBÝ,=ÙÅG~ýÛqR†kš£<â–Þ¥[×=t›¥:ŠÐ‰—Z—sÃÔôý‡B <÷Ý:5½ãk÷²Ê º_|žëíô¢/‹Ôn»]u­æÛØì&Jb¡tZúê}ÚAƒŽoŽ™Á‹ëTNTç Í  u1+…,ª3‚øNÅ«3²º SÁ‚:#ÃYuû­ô×}:#Íøê;BÒkuFœš€AuFœâ˜A Ó€‘qmÇTȹs yÊÂäOyÊŽó”¥×$]» ¨ä¯òÜò„'Ê‚¬¾¥Yä25r¬œ‚º7oZjMž€'H`å”ï.>•P_σúÅýyEúżÈ=Œ1ëƒuÿy!b‰ŠªëÝXúÁÝ 5^î¸"¸yTFô7±&/cúGê¥B˜_ÆÝW¯GØðvŒ1¢–®y`°•,–LB ¼ä‘º;îçeóäF ¼Ìb.‡êFášyL¹O9ÖÀ5E˜™!.èÈXîŽ#—³q¦[×ñ¹öc5Ù±TÒ#¸ó°{7rS짪?¤Ûkñ5ûõ96õB<Ð €ô ÓÃ!Ôƒ½ù|ÿ/=$a·ž w(¥Ô×^{;Å쮦gOØÛ)ÖÅøÒ†Àìmƒäá#ø ÷™þ8‚»gOÁ‡‘ ÃGpÐÒ2Èàü¾ >‚ßúD‘#ø‡"…W«øŠ¦‡,Zwav¤˜§WÚ˹Ñ3î<­Ïõy¾W#A2×ëx©·zYßu§îÔ6Å8ëó}ŸïëûÕu™zkùrÏ® –ŸpJÃh?™ \ó¨ÛeÚ!óïÂw?ßêJ®!ô×ÑÛ5»ö0«žÐq"È"¬õ澦ˆ¹Ë(ÝFxŸEXUshU­l°ÈÒ§ÐX½òE=ƒ 0ÛÌ<Òi/‹üµ2ÀÜLX¬KõŠÛïžð°ËaE§I¸¤m:ƱÈ,¢”¤³áA²ÓÚEki’Ç<Ìç&y¬›i&¦‰ˆ(ŠªÊŠÝ7Ó¤ˆi¤"µô4)c½vH%e‡X<¿&KânËÀ:M"‰/ò¢ùîI¼Ètl 2¬0x(2 ž®ëHÈÿùr,Iƒ Eþ/×ùcEh7t,ó”±_»aO±Ý°#Hv¨á×y¬»@™jÚÇâÊ’.ÁŸ:G¯³Œ Y^Î5Ð ¹¹ôïÆ­´ì»S…úg¬ðëYxnžè}æq=ýƽ¥°Fªî‚€³aÊÄRÄÏ^D:jä‹ïz@þÒŰQzÊ‘¢+æÕ¥<ù¡ »!b~wgMU Ý­)g_'>èøRÕn` ¦Hå»kQÀŽ yØ¥ æ;f–y]š úå<ü5Õú úG)OcÅ·Ê)§üGwÁ{‡dAž÷êž(ÿJ›:狀=` AÌ2šã’qHß¾_èÙÅ7WÎDAã0 W·s!ç6ÞexéUÖ1<{Ôìn/—gßÎ-AR•üæjUòO-úõHáqÁŠiŒÚ¤øýÀæL‰wÈ—¿KÕº‘Œ¨M—fÎkê^dø)ïS†Šçmnž/*jp{qÊgËq·ÝniÊô~Ãj“¦?Nåî׳¨ŠÓrMÓ<¦‡Rõ@I‘&ÅÆÔ“¸ÙœÐë¾3ðÓ¥lWÉMmœº«ä´t§ž ýZ®¬åšbº”í*© £ïÝwÕ­½d,=yæº7SLÏ' ,¥iîe0Û<ÃÅö”ø‘|gNÈ@¦iô9î‰Ïqš–AŸã‘ø§HcïsÜŸã)b|ëÜaŸãÔù‘x³Ä+ßÒ wˆŠ“É[Ê?b«Ud‘˜Áf 2rŸ©fÉØf‡#@};.l±ÍD<àÍ î³#È4à€ŽÈ™iÆâšžnïÈx¨SEû³:"eêHU»œ•ºCµ0AèHU_Ù­þ)ÏQÝJ3ªt¼šµº¦|›sc³[ÉÞÞˆv—fyŒâ!ǧûF9ñàÁ:¡ƒÊ빜@&ˆ¯Ï63·'’WìzèÒI³"®w†Þ|c¸#oÅÔQºÞŠ×å‡(ÃÝy+$DªøtæhbߊÊ{ÉE;?LVj•à (K¦9‹xjb˜4çq¿[ .§yÔPh+¥¡ðøXdöƒ*yBÔúºO¤„’æâ‡fŠ»Ï"®ªii^ÆhbŠ?Å!æ±W¹~ÝTÄ•¸ÐðM1©Êãaæ(‡©`ñˆº%RÁ‚_útJ=)VñzF8õˆô‡šDkˆ~µwH•§‰óm92i‹+]øuq\PiÅž"Y`?z5@ 5ÈÐÎõ ‚cé÷º¤W°eÕ§4¢²Û4¢ÒÛ”P@ö~NÕét‚ÙQ|EÔHµð,cv˜qÅa¯8`Y-M§v„ywMîÏ<«© ™gBìлŒ*í­ái|>ß™í<ÛW¬Úš«†"s …j¶ÄvŸr]'è¼I1±Ãô¾Øuþ²Î×ñØÒgÇŠx×­÷Eþú±?N=ÄK˜Øa{OLoXsnëþø HK˜×âyM­_SßÕïã½{ ;(¸YU›Šé=ÿ|êz¸öôéMGËÿjsÌu¦g¿ÿ ®£Eæ­:Òw·îù>/{(ØU]D‰çM«\ÃW`¶¤ˆØ!Û?ÿUfäËÇjÌU·{¹†þ§RÖÞç\/ëKé[R¨{éÂ:Z$Ñ,ìÐAîª`QŸ,盓<æÓŠ*¢i‘†õ—H'rZ5ˆÌžìž(¬·Öu ÷)"×ÔÝâpÍ"BÝÆú6)®ZS}›f$ú6iQômT%ëÛd€äõm 2 ;ŒÃ^W~8ŒC|‡¢«‰Y«ûías‘Ù“³´:ûéàAž¾äåxþ\’ÙúºfEêo¤çåù¼OÉ1ѵRê:)š AÒª¹9O6Õût[w÷I"'„¼ÊSâB9¦6@sNÓ æy6PEä²|¤÷Yø¸›:¯ÝÛs…A–;ÕvËšžÖæIïSÏxoºÚ%²CMWw %‘!ªˆßpd€‡Ïâ"Hƒ{¤Xg¶TÈ‚”]Ž®\GMvˆ‰±«åOTÆ ùž=9D 2p'n–$‘n7LLË’¸}¶#¦$û&$jƒ 9•NpM $ê¶J‚dÞ%Lž¨ê~ ’1ö${Už³HLÆT‹K}5Æ(Ãù¼ôµMgI3dDŒˆöüFræ€ÞÔ÷ËÃ"sÒtúÉ!_]«• ÙÎöÂ,a§çéÔ ’;¾zmŸ¨½=Öi¾À²˜`¡*ÕÓb]k;¾æùùÞ!3ŸIÄBz,³DDBeLÌ’¨í/2ÙÉâ.êMÙ7ÏqÁ"0ÙÉX±¶Çý¥cÄ¡¾O$‘¹¢}@c‡d>㉖Hcd ¨Æå茅»puA£qÈ(suý˃Ȩ‘"8‹ûUîOKÉ Ñ~+áYˆ,É)1-Âa¡îï»~‚¯YƬ4ta†‹¾Õ*u °¿Î?l¾!¸áIÀVU•£±Íw†ËûÞÕÛ¦3Î~tN6pŸ<طٳéŒGH%ŠÐ fÏ|=«µ-ËÓ6E2¿XÓZOï2B˜µ‡©Œÿê‡5™‹å Ûd¼ˆU'„žñ2(?Õª.ÜËÉ©RgiDV´Æ©Ð,Mb4™³K[fiÔ¸\Yô¯³äkXCRA*V‰C¦AÑÝ…èdiKÈ ½ƒ,Í‚Í=iÈÒÂEfyw„¯ŒèqøÌ»m»ƒAÌ»WeÞÝdؼŒ 2 ËÞÂÜ,V´G2™øê7‚™ÙºƧHƒ6@m?ô§ÆÚ®eØr2–+ÿÆg™ð õ7[±I®´ ìq"EvûV“ʾ™ÅN(­“TÍD?¡€ŽU&¾s›ÌŸºæ|šg+Uš 5Õ¿þdßo^_s’ƒ©&Ȩic¯9^çÓ“ }¢¦ò‰ È™ùíKæ¦Û#s¿}‰ À€àiÂ'kßYûLD-eñÙP`»¢vÍj˜œ¹ò~€ìÆ| ëœ¢gNá! õ Y¸â1¼èÚ'³`Õ˜St0ãŠèiïEÔ2‰gÑfôi’kÎH<Œé5Ó´ûù8Ñkfa$d_Q3º§m}F'hÔŒþ’^³ÉÅËsE–adOŸÈ—L7Áâê.Êðâ +Bn©–ífë¦YrKÝ·=’‡Ä‡œB­¬+-8ê!ßt½%œŽn›)Ä·üJs3ÛL¥x #AÇz#þ)Ï*¬œ‚¤î}[¨¦ÜóTO5A¦ÖmÚ‰¿(äùXõ·• 3\‡n€Ï³K !Ká–ÅYsJ޵„;ߦêr!Hñí¯Çûq£×,üÜ‹U>|O‘e°Ë¦qƒþ+Bꢌw)ºdæ ìu +“HÉ¡Uµ »ˆà®ywض¶u…^ã¬d‘âD=Ô=,ße¸ l!ªÌY¸]9+£]`8í^f_I«º1i¸Ëq˜Þ;$ ú¸¯Yæï[½†ÈÐ{°AX‰™½Ä§VníÚaù.¿g½¦õ8̰#‹ïšõÒdèš§f†p ë>‡5ƾÏ$ù@à:O¾3ÖË¡'^yR½zâå`^/‡žx9¤×Ë¡'^éõrh‰—ƒAz½Zâå`^/‡žx9¤øNˆÈ7¯"|÷hë ?}OÌÛU'÷¸¥›L:gÒG:õÖ¶ê÷Hr;vr³9K~¸Ûu>g Ií¿áMìV—l+û–\q÷‹ï£|çêCD¯Ñû¦fñÜÆêÖ$HàA켬S×]Öš"SŒÜR ¹¨%dæcUr]¯ð˜;¢ Y=ã)õ¼µ÷ã• EÞlwÿíqn(²—k­%r3O´v—Ïî×ËM€oCÖðìÇî6Ìi˜ÒF'ÓpäÂð>Ý>6P¶ÐÄ¥ý/š ¨t°†ê$£5«eb¡ÌQµR…Ö»õ7¹äÌÊ©£€rˆKh5žÚGC¿}’ºÖ¥³¾h­Ó—áyïvÐÌE#ç«Ö“7о«Ž~Ó$wÐíßè7P?'£²PßT=áªÓ¥êwWÅz…&gz^šË¹ëÀÞBý‚…¯S †ý~ ¼îqüÌ»!Àç©€•2§ú1Ô…²@µsmš +d=·U½œDNäA˜jçÐ2‹å''[fΑ^mb—­ïC9Xªr§Eæ!myîÇ:Û9Ѻ(^øD(k+·E¬³#Æ„¿‚ºPdDg{¥È,lÿ램ˆ63»ú­A†ø+Ç'ÊÙó7àþä11+Ëy©3cNMÎYLô§rF‚9ç? åøõOG‰9üzstÂ79Ï¢mº+aäŽ[ámÓÅO”}‘ôAg›èÿçÜsü»C ±ír.~°íÜ×ô±„ÓÀ?Ê#‹ûF…'7Áhv÷we‘e(¼ÖÂLîØŸs¯ ¬I%¨cÿº¤ß®v¨+wì7È4ÀUA’Cyzˆšþ¹¤XŽv-v½®ÊBpŸ²xc'4Räi%¤öE¤îž§i0á²hº|Í4‹/>ZÇjɳÃU½Ìý²V繺Y$8ûׄ/–V=?düÒ¤ ÝÔ}^ŒIB.Ÿ[ÛR¤É¬ÿùwkPØÄݪ˵º]Š4ãÿlÙÕäb‡û½þKžb“Ïl8¨„ØäÙ³=Ý?;$Ñß~ýÝVÓ4O sœcWeuV-V[˜u{›ûýC¯Yì¢,cÜ«÷s¸5A–ŽR~1¶IÃø‘Áíù3Òg7¡›Üª‹¡Óßúûí$Çò}÷š’„@õaMC/×û²ƒ29m/JF#—®_«ý p'ÂN;÷[}Z^÷SO¡ LU]l“›„¶ê”¾{©V½ø‘O6ñ£ï>®¢Ðså¯6ïûÇ<µ»« ¬3¼>­†Çã¶{¬Mc\Õ!t{ŸªËû8_ÖÝcé¯õW§^N©èMcw™ïÓõAGÿ!ÐiV¡0'Au‚–¨äiñƒ®äž2âŽÙ<§Õæñr1NŽ›Ï¶½Z ‡Ü©R¸R®µRYǸPä^=£1¦@ë:ÁÔß©Rì|²U—ݲx§¶|x@²h.«=š…³4íÖ¨`¿QÆ#åa¹‹€2mž¥ñ0¨oyÖn‡n¨Ûùw™ó“JiŒÉv}<[ÍBÑM¯ëD<˜Iƒ{ž‰yéæåÙwæÇX†ÉkÖý±oí²—•¡Q'‘}{mO‚ôxˆZdK‘4Ge×¹NÖÖÎ S¯7çP¯£Ë“lÈÌ“QzÕëµGn9¢í}Z½/U¯i†=Rì²s¦ sΟÚ~#LÕúû?ê Ú¯óìfq~ø¢U!º<ÒÙȑ҅_gv§tá¥Ë; ƒäA×^ðâÍs÷÷uk]Îãþ¾àœç‘£'¡àçy!X«…V›<Zïõ„î™#bÓŽ¢§fÜýq„_Ã? ׫\Ä,Ò«nmçæår†ÕYý£ÕneDrÕÙ”I®aÈY9wĦÞ§Hâ {.hõP‹\‡ɘZDF²¶áÂ#Y =:B-ÒŠÄ]çÆRPèϰzcÐni•côëÙ_·Zy@=à ‘±X.Ä}˜q˜ CÈÐ[§¬#C碌µ Ǽ8z¢éÜ*·e¾¹«R|,†v‚˜­H"†r¸£7/bä3­ÈaßRT,úM‘c"HF ‘êÛ–g¾»ÛÙ~#¢ °¯ì`bh^¤Õý¹Z@,/<®¹f‡]TS”Û7‹°J§úFíàž= .Ûp9$û¦¾m¶{Žú–y$VTtO÷>E\­ñ²C²€þ$ÒÕÉ‹"¶zãµ®­uzeÀkÒDðTʧ¬˜—h­ûC‡r•Æ4¯rÇI°Ulã !WÅK»L=Ô,°æÿ—ýšÖ*²Ï^²¬wŸ<¦§øÉ|üvãP$3 v¿žôQûk¾ã9ìšoQ¯¾ëËÿÒót•ñ˜ãñ›Ï{Áo»·C²ÉÐRßϾºÛu÷Ð[f°•Önî›– J-©[T7Üs%H5S]s b-éç Ýä0¾B ¦,"¤Ûc<_‚¤¤f«·Ãã…ŽÆeå ­íH½¤qò&ÂØ¯¤PP–ûcµË¨?»*ŠÃ!žÜ…8D`æ†a”ÕÀéNªŸÅ"¿}¶ö…ì»So+eɨ~¯}Ÿò´ )Fƒ —åŸÑ¦Ù 2 7œÛ‘,ߤڢ°³Œ8¤‘Pì,#P[þw è¸>»¥%ÈH è ×Ìb:„è\,p¿GÛÐQ±ÅADµ «q ’ÚBÕµ¿÷Íéh‘;/\ž¯ªõw$Hæ¯ÏÖ÷ÇyèÒ)L¯‡íškÿ>Wô×SŠ4•\‰¼¿«… 3š^µOTÚW7dN7›ˆíå}>è¯ gÌhO|çEîïÊ‹µ%ÈŒÜpY¾¥Çc÷–JÒ b*øu×-Õ¹í雇гâùš-¶o>ŸÓð9Òš$4mª‡èt®Þ­\vß“ùêØ·êÝ­/[ǶPŽS¬Wãa/¡/ù}*“¶üÜ´·Ç:ÍÝë1íî5ÃЛQã¨ÇÏÒ½öЄ‚NŠŒ³yî=êe>zú¡›ê“|YuwO#ýþ R;›®¼W7vòªçîª%‚6[v@B§îÚµ…ng-¶wº˜Ívõ…«euz¡r Xèy8=§j¤o€?@'QtÑÿ¼ ¯eiÍ™B9…j!3 íÁÖBSëà:6ý­©Þ»IMùÛPÐa~€…:~Àå¬ku:Œ•Üñ¶·ÅB µä4Ý\~ت~ÎÇ•ÎV`èÖ›øžÞ•Œ N»IÈJë@ÝëÜT»á½€—éYÞk==×Ýb•x ò±Nõñ«…2à2œl½P=Ö»>B¯–…rÕ3æ=]ªË< »Çâ)bHÀ2t¹4ˆ!a¡™º®ïëxÙßkn¡ˆLq?u_AöilìÚúèúXGZì A©Ÿå2xÚ=VI z*h}i˜,TKv5›xëøxÞÔ[ Ð„@oïIB‡ëe7·RfÝõòÞ˜å}=5Ó뺻n}P?ižÝ½ž†ûiwÕM¥pþÏÝ7C'¹uÃðÙAõ×ú÷ï¿:Oh××ñ²|Ã@?lª¿Öòï¦/ÇpNóý1U»«7!}Õmª«¶ÓܧÞB Ý–W½^çîâ¿ ª¾Öü÷|¬“R–Óû»œZí³ŸtÛÈáÊñ﵌â~áSÂb}Ðïc>%eÔƒÀ }U[öá0IBI!ckAƒäa]½“PBW'áPZQ$<˜þÔé:Hì‰ä‡)ðVòþºM‡l|´#{Êg¯ {Š$˜¬ÚÄ`²§Hò°ERMŸD"¢òÒkãFˆØÓÿADvyË1n¶Ñl÷2‰:«ÖXÂÑl­‰2t®ö: »kêâ¯^M²yN3°y¢ÙzÂy¤ý"’òG8¿C†Þ§Ìh]âÂu•þ÷a÷>Ms›àÓdî‚Lk)¹Nû0Îçݯ ¶ÛøPÚnïݯ.µþæŸZFÎmýh诗.³f‰ïñ³~®gP)´oþàòóê¢ú5ÕUµžæý ÝÐÖürÛ»†©_žÏ£Œž)t«îþ»‘Ãj£^]–npÛœr_éw*¯:Î hZ¨þP6šæx nÇûåv¢ÐŒ@·`DA_ŸÛp£ÐCuФ¯ú:¾.çÝUE¸AÈÍû"¬¿¸É¨ÂS•ÆNÆ!«c‘¢VÇ®,g,”RGkIÓÌÆR± ©B§\󈡔HYÜP Jæ"ý¶C*•¨5K¤<µéBjÍiúcÅ…È%¬dº=Éýz¨R Pã¢H£ÍC[[“A²À5Qã¢H‹‹î>‹Ø5QÓ¦p.ÿ}!”~Sd§ ‹Ù - ˆìEȵU >²ž°¹ d/ŸN$ìK˜ìåKPd‹é/"N»p®–ÿí•rÚõæâ»Œ‡Û&•é,ìE–†¬£7ͧ¾{–Åõí Ø&²Ü§í§+ ZÛ¯ƒ"²öñ*á½w×äßš%jcÍ‘‰`ó^K4K ’ùZòZ¢Yb¾Â˜º&Ò,1Hoó^O4K 2óŸç°f‰AæþóÖ,1Há;M¶„œ$²"xêm áIdeŒôƒhL"?ü°´‡y”'‘Q§*§0êruƒRU´ÏNÔ¶hCuKªEî-85¶­×5 D·Úå{'ÑzžÇÔ^‘†pt«) NT¹ÈalÈÛɽ´›a”c©µc>/¢{±ÓúyÝ‹Z¶È˰±¦¯ÁºôÃipçΘ­±ž‚Å$â+tN¿ZÙ!‹ Òâ/‰,ªËå º„È´s»kŠˆ–'Ö_¢ ½ —óe‹k•eÎiYG÷>‹`§¶_ƒä#¤*D6Ëp³®(bm½¸X ×^/p!zQ¸|–Ì®¿L —OEÕõ—‰‚}åk°0¸½^×Ól‘~:õQk6ÍB,ü>­b´(Òvk°kYŒz‚:¼D7Ev}[ÉöÄMæžd¬6Ã)DðÙ[­w+m!ˆ>Óér6–)ï¡[‡n®O‚äA*$Ø­‰¢øAÙ„JL†-‹ò³êD¶…¢LbêøÈ¶P”I WÑÊvÀ %F·"š¸‚Эög,‹ Ê4ÞháVÅò[anÓ9Sß}9vŽ&RæksC»i.·ûú HŸ µDVU5ÂÙ°Ìh’Á˜/EP×py_.Ý"5ÊݶY<4×ç\÷éSU'3•‰¥×äÖSË/×­îS_—î ²ÂQ£,±àj[îëVž´×®#ÈlW«ßòïp[è5sRª×íXy|wËc¤HáUºmjy.>Ò'*‚J·w÷æU§tûÙ!“ƒWê¶RR·+}õÖÆìKëvèÆýUÙ·ØíÐj±Û6îÒQ%|cÅ›„ç/˜Û³\q8ÄÉ­p66HæÓu\¹µø)Õã~ý°C´uÌâÀ#Ö`ëê²åÅ!ý¡ïgG^qÈ¢®ÞW²˜±¼jš,2Ö ´¨f ž wúçN{s˜j¸Oá»OóëšËÞ$óÛµÍô´{|q(~˜9¹oTiï ¡½É!¨ Üg„",ê£Úv3B«¢û^bâŒPª¨§×|.Š„ÅLàWW!*þÃÅÞR’\ Ô<Â.ªŠšÊ`S›u¹%•Á"Ùë Ë™©»Oû®;©Õv‡d±»œD•3p6HnsÐd¶ûn˜;dˆmi¸’ÕÀ7ʃÞ.Ýæí²Z¤z»(kͪ®(ÒëíÒjo—þHgK°bsîžÊZ³#Èìy/g ½_?¯c³>[‚̨Ü×F}ÈÿT×¾!ÈœÚu6¦q§úœ›ŠÞ§ðU4nª¢ñXG‚,| ãVCï³ô¸ÕŒÆ­f¢oþ(iLgôáEÐ<δ}Np§E¬…ƒÌã2"Î5+q®– Y¸…c]’‡ÍÎ`Î1ªšRäi7¥,Æ×ÀM)‹ñ5pSŠAzšRtŽ 5¥d Î¬êáv‡/óÄ«†¤¾Ê1 2I 7Ç*‡Õ/Ém!ÓºÑK#Õc,vV°ì‡éïo)ÿaúksÉ‚Êâûî"j‘ºY¹`E\SÅ­ô,ÜÜ¥ì7p *P•²ôötüx»ÙFËéÔôYÒÚŸÚz±§9ƒäþœLÕ¸“WÁ“˜N‹:yÁ}ÆNœuwÁy,s…ÌÈ‹h=|¨&÷>ykÞ–Ãy‚_Ïãþ* \p8GÛ&^÷ŠØùå£ þËq ¾QzøQk³çÓ"MÂþ*$·Y¤,ꃞ=E•ŸçdA Ò+Ù“\q‘Fšx•0¸‘iО×^ªW™ÇÚ§O'ÈÒH‚ÁMËU)Ò"ž¥‰ç"-ãæÉÐRd‡È<ÚP‹Ló]þ®žïð²$Ò,W­ŽqVd,VcE8EÆc,¡Æe„ Ÿ‚ã|­®-¤È²ÈYJÕ.aýÌòøY êŒE^½uþ˜2E&¢¢.#TàŠoïèÝ5‹`m«œÜ5Ë`}DÉ5N­,(Hmè«ñµÑ¸6DïS¹ ¢6Ú"G#ä›-¦~÷÷ ®‰FÈ_£®fr\2¦žûù:¤×¶ºmªÓ©³U9ƒäÞ3Ê 8J-Eb)#çÑ¿WÕjR[z±AfNýýrÙ2-÷üwYFXs'×ø÷ÏFYÞìY‡“zrY¦×ÚW]1¤tGŠºO¹VÍs‚º­AjO¡ÿýÙ™µ?åãÖùœO¡/7Q0!/roÅw#9OùüM/ÎéÚyöC/né’……?&¸Ï^e7‘ÊXÐ ·8NˆC¬ŽC‘„–Ee7‹ÊÆ…`qг/Ä×D²FEkûz¿«; T¼üZ˜”ô#” gm”H#Îy”1H%‘‘ ݰC)à~ê¦å‡hgm³iƒÊñyÑ‹Ýûs©ä©«‡´!3«÷©JSÛ„ï»s[uçe‡Ì-ý»:Y-.¥ø"C &ç†$ÅdÜçûf‘‹]C‘›fÖßÿ™žº­'»z_ÖÔô ²Ä{sØždúª_=½¦vŠZü¯^k5Oå\5—õ<´û”lP•ŽÒÐm±íNó Íê­‰nà3¼¨,ß@Ãqÿ0N^Š«w*"\7ì€YñÜñ¡ãÔñQˆˆ¢"iù-DÉmâ–ßB”{„í”âxTEqˆ‰è¨{dÿX;ªØyÖì£WW‘- ‹•+ç¿Yé)ÓÕƒ½S~í)’ÙéYê«]ëÇîÙßa*È3ñ{"ßeàÔ¤ñƒÆËHß½Úó¸v0ê ç™èŸž»_ߦü²‰_ ÷E×ì»Ý³‹ÀD:—.À3ñŸåÿO¥WWW/w2/24åÿ v3ªDqÜfûæÞ é´ö3¨Zhâ_¼:( ë'ÕpÕü‡z“»hÌÊ÷îEñƒ´ «}Oô ÃdOôô@ñ4HpìA„‰¢L¢“Α• \bÿ'ÅÚ'EɃmV-i³*P‰Ý£©Ú¬ ’…[9 .µ±¸ûÌcJuí±?ÚÄD)<Š61Q¿, iw¼¶PÆ*=nE[ǤDNí\[݃ (Õaý9ƒ (ÕaM;ƒ (Õ ÍºGŠo‘_u¨À"¿EY„U(ˆÈoH{oŸžˆüHOåK¯‚ˆüåw3Zm“\Dw°(Cºƒ ‰u‹2¤;h‘-EztëdêµÏè7 ê*òÝCºƒº¥é¤«7Ùð¦<b–‘* ;Zdò£õu$‹ZB»Rx‰•W|Z›®-c%{mëi×ÏòðK#°…kf1@å(%.ÄùYÊÏ ž ¾\ªZåRµd¨-i\•‡"&S®Rê€,ÞSª?ûØLïD5ŽÆåok)•{Ç`ãÿ2Á [öx\ݬñ¸Lïž #~V0–’˜î ¶s-“X¸¸V.-#œ!}š2I£VõN²L²ØXB¡réÊÖþ–ƒ¦¥Ho»wOÚ½ËDˇ=i÷.,¶¤Ý»LDÔ ?{sƒYåÞ¿^ÆÚÒ‘«RIšy¿ÚÒ‘«R‰]k¾ |¨1£dI,õ¯r¦•E†rÍFпÚ@½dá']N€¬H‰Êœ®5¬«ãqm Òoø«Æ1D€™º‚VÑ‚ÖÓxí>KÓ¤Ó:¹ÔçF¿Ðá5ŒÇþô~½ 2w‚Þ–0Ð?ÎS;Ï»gßRËzePoHEõýÚT˵m²À-ˆpHY¦eîô>Ëð,†½ƒ¥‘ã¶šq0\18ÐäÓ÷Éü)Kݺß(äaªê¶ä÷ܬ­)€ÛWJ&¾=ÀaQÀŽ ¹Ïj¹'¥©’1UTî*Y´oîI ­äß‚–ÒÝ·õÖ?m̰÷¸Y´¶¥Hæ¥{‘’dÉ£í+ȳ±Deã¯$±d(y:ËÈÕF-زqÉcÍ ZÄŽ%×2\ADZÄmÔ®¹«¶—±JÔFý­z¸ÖNñ±ä"T°×š‹®ÔWîJÑ»'R—€,=ŠzVI±šŸç·¡³”¨åÕ¶{[­žÇÔŸêæQŠ(Tyº«ïêôÚ!9¶d0-äË[ŽŽå+mz ta—j¸ŸF' ÝÛ 3»~n>Fk¯×Ç@¯™#&³*JäãÙMï†^S·ÔÀ[ª§óÝÎMÒÄû™›©è;‚dHû¨¾˜gÿ¼Î“+f$÷úHÉ8àéVï4¡Yå³M1Iä¹íä~ÓdfÅ„N`8uïûÛqZn6qdù·Å¶üšK·>ž;¤ðšX]«ù¶ìî³ð[C)̸”ÅÀªL™¯éËÖ€äk(,ãS¦1,ãcNÜd^bZÌ8›=À²2íGÝZƒaz™æ‘]æTÉ]f!H?Lû¸’U{âAQ¦‘F¬I'`K‹˜b®*ȶ°,WŠq"ÈeùÓåë  ÌG¥÷¶™r-Íy‘‡òµ'È,`/Þ-£››š_¦á/tÞL]©ïù|»fxƒ,BÔ=gPT¦e¬!‰ó”Ù!ÚãÄyJìþ±³‚S¥„ãò¼Zdo„æ™2c1ó0¤ðZfÑ“¾<žA –ÅŒèÔ¨³eã2Ö’=b uƒŒŒ:Ël5ÈȨ[è¯GÝ8­ô×£®W£n"ÈȨëé}FFœ;²Ì:Os—Óm-}2–`$c‚ŽOà ¤"JBÐñˆÞ RÄe‘Ш+(£Cž!?üPFß!™Ø'„2Ob^È ¡Äoìùa" Ï•yLq\í›0æsþEc2峦'N¶ežÆ‘“­AÒQÓgÒ5çÏ­›mäŸg&IC)naçÂ$•oY9¤4_æyÐUc!JóÉ‚ÍÆ{ó"JÝs€%¦³x¨{}‘j^„šxUÞ5ñ–yùÃϲ1„}ñ/´)n÷Y “Œ,2Ù#¯ #~Q-ÑVƒ× ™Çtsèµé&¬u"ùÊC>D›n®-’}&ÿÚqö}îN#d_Eâ”Ñ]ƒývŸë»wžÌ™{Œ<‡^‚Ÿ-|#‘j@m}¥OTF¯Ú‘"KZ»Ù–¥jjaÌGZñ[â_ þÃl¢ ‘ÆeЀ$]=RtœŒ3f1òƒ$‚3,"?ìEZ%H"2ÉB-Ùh/FMûÔÏD®ÉÄϤ…oe@™½F]ù#³·.ÉìÁY*¼™½¦¥× föî œ¤D‰2{ÿS¶~Ê‘Y9>V‚uÃx$Èpfˆ éÏìU*³76Éì}èû,þZH°  K(-$‚Pbiƒï¶ÔTI$ŸŒ ’…Ûfà»á¬'4å²øQçrž‚E¥ÿœ›JYð‚¨ ©'ÒÖ†dÖä~8rSÙWÃÒVëQȪz÷–pkê¾èvw@¥#½øÚ…"Ó@Fwu4ž²ø®Ô[颞H•EXº¨'ÒEe–.ê‰tQY„¥‹z"]d^颖HdæçH`é"ƒÌý ,]d"P±U‚/pM¥~ûFrÈ--<Ñ{ ´Bß÷‡ ÎÉü?ýìFýLŽº‡<æ_wHJ%¿Z+â¡NËDQ§Ø-½fêmßäQìì(™w Ñ«·ZCFÈf—W–ÇFr$2zŒ~K•1 _ÎÓ aq²Ê*$±ŠÈ¨ #C:OQº–_fÈ'a£é‘!íÂ4Bpé>zÛæoOǵ JpÛõY éÝy]¶ëã„Äb»>#K!©…‘¥ùu é[øuùþB wKóëò†_Ç‘¿N!-Œ,ƒg¥F–ÁÝRH #Ëà×)d`_S§3† ž™j/fÈÐâK)©éŠÂÑV[˜uäILÛp2dH燓!Ü'q¬y›Út¨fHbãì1¤áP­7Õ¼ l8T+äCµð­*gXëLavÔ°TІ¥¾›àÙ)ŠmRy‹•ã»H Œ¼Njxk“by)$½$‹©ß;Bº™¡½IË!=‹tÛ Ë!ýå þHÇ©ˆKüD]f2¹3wP«§”!={ÄbrJ’Ü­`»É)UHzÛ˜œR…tíMz3ÿÙ§®ÔßQ`oñà‚ø{ÈÐÞâ1N1îiY“ë£P±·BÒ{¡IηÑÈÈÒàÝóovDÔÏþ`ÙÀ÷âqW3™þØ‹3G!É7{7Ù¼ éX]Äw“Í«·.â»ÉæUÈ[ñÝdó*ä-7»ÑŽ@+7»>Ð.C+7»7Ù¼ X÷j˜É”Ø8ùB¥WçM†¤VIʽœb8o*äC§„·éZ…Q&³®ÍÞ³ÑFQH ³ÑFQÈÛºvo £(¤k“~`3žý—_ ÈàA%.ã "@ Oc]ýçk¥A³ú¯äN(¬7«ÿ yïilVÿÒµ [é'Š~:Ò³¸¯wÀ~ä:O=8ºMŒ!ÉS-R 0$}pœµ€#Cºï=­ÚìqëãVÀ±™&„¤Ö^¡¾#ÄÁ™½Zdö`—ARø.";ë6ÇÕˆä.ÈÞQSöÛ„8¢®Ô×QÔC’`¤«ÄÎñ”ò™‡Ÿõ¦·­ŠmJöŽ–$îg„ôq¼$W°¶üì«tnSÈà.WÙ‹\e‡ï3¼ï2` hÝàñŒîD6»OÖD¿†µÀ?âš<™^HOι÷N…$JSH»–Òd°ûtŸñÈ’jûÌL¾÷eNÛcç, \8¾sˆ—T¥{Õ¥å8V5BzkîT㬖æ“eåØA¼äbñ1n[(Ò¯U˺KÛëïÝ5ÄÇ8Rüz!,ÛOÊF_›†øØéÇ)ç§øõb'<ž‘‰”ÏÎmS¾¦”Î)‰¬[WɆ©ö)iðJéLeÇ™Ÿ¯]14ý–_Þ'Avœ’ÎÑ3ÛŒs<øÒeô„J¿<M†!™jüFµËè[{—NkÁ¢Ú¦Áï]F¹¤Û·¤{:× ;_îÕ7 çÚÄ¡S“Ì„wn€]F9ÃñôSáŸéždÃCC}Édû6Ü*$½Œ@¤ +²S+Y@§wÖwžýÒ Qâf2i:eë>MSŒ_,±V¡Ï…AÃÇj#{´! ŽIJ“ìV†Œ°o0·Í<iØâpm¡½ˆ åÇ[éÜù'¼á·”Ë£9ú²g®® ÞrkuöÌÕ•Á[nírAúVní'tר ^¹µñ¸—넯Z¹µk‰G)ÒÈL@–s/l!×ëId|Ñw4\cÙŒ/úïõUG~ÕæsQ‡(ÐÓ®STSWÝ{Á·z~ÑÊ/ÞhÇbƒfÅoôü¢ÿ‰ãª}=VMuj†-8Qšr*ú#Û.å+AÅ& ¿jW[}JŽíÿ0´Y>Ý^_Æ54ÜáLq^¬ãO'BßI ߉æ7‡/$aõ/DÏgŽ;Ž×Þ«÷úúNrøNဠ»™À òï„[Jˆ9´±ŒáÙ­¾Òü¨ËaGHïF³£u­ã_Ó/lô=;—|BÈÀœÓgæEXŽí½žý'2´r»ã_3²r»ÛË5Ñw‚ÉÝŸ¨ã˜“_O¨;Þ_Æ^'xòçƒ1ù%¾“\ÃùŒNzŸáw¯¾“ë4ýdlO½@íLôe¼@íTôü =¿“3BãÁ~!ø™Ý8³i½bhh~}z¥˜—nú\^Ad0ÜÏ8ªäƒKî|wdøéòbOmÅ+ÅÞÇK‚ß–ô×fn,öÊOß±’W˜ÞÜ€NÐÞ"wØN=òäÒƒcC>–@µ?Cºþhì=!$±;˜èwê=ÉÄÐ|Ãþ“¢©&20dð¬hZC2À žµætbÞ ¨^ŠÏœl¢i} =©Ò¥ž#þ“#Lƒ?C:OdgíU«6²3'ÎïIíHH·ûÎ3Å>‡â;(9ýE‹Î !-dçácK}ç‰ìü¶'… -þ>Z·›!‰5•»›j= I ïFîBZ ï†ZBR«¾¢Nþùî£òêh<‘÷¬©S¾ÿÃË Êª†[Ó½CÙI,mͺ]˜!C+½«6Û…ò”­Ç3º&)剌}Ù§[\Id`´»ýaDvgy\Õð¸ÝMïKÏó60“èH…C)ÐÕ·U  Ö£§+ûé˜*ËkKgË›³Ò3=;eˆ;¾çlÒLJ¡ K\lO!›h ›Kõ<äŠ[!޽KTˆ [!Nˆ=…¸À±$hŬäŸ&ÒÞ»öèùØ(x§ä]0$µ œh~®UìáJã+nÒ„Z‰Q7Ó3¤÷C‹{…_÷SÎåÞ`ä½ï˜©¸ËÁƒL‘p' ŸÜcµ15Ìnª é{Ñ»&}ÌNλá½ÅäG«Ä!wNU@Ÿ1dK’Ü‘ËzSgŽ!݇¾ÑPΞ¥¡œ_Ó *¤%Ùo4”+$µë·ég÷H[|‡¹OÉ~®çO~§±OåUžr®“m„ûÄ©—øt(‘27cy¿á°~§^YÄ! ©+Œ¤æAñ‚Ä¿nè ªµÈPe’ôMôœ×©—?—Ä›îUµø‰¢ûsÿ\túÜF†þç— ïg‡4zY6x¶Íˆ.õ ÒÖ§£õ?Òù¡ÄËbD îP³4¿ºzÑ5ù‰ˆÚ™`¼§F/7‘û(o8êcOä=Þ'˜=3¤Íp®–†s°€F¸GéÂ:jÍŠ‚'ž¤6daÈð±#ÒØb#»!â1õŸòØ1’Þ"÷~16ã(´nðÂÞRôQôÔÅÆÍá0’ØÙzj›q^¯§®jnÀ´+¤c1`]ÕÜ€iBHbïª>f„¤f×U©Ìh>Ù^Ô’»Îä¡^9ÀµVH¨ÑëìP²šöQ}qI æÒ™6ç¿ÞUû<+ÖDº6þv\,‰ôîùÛ,^Rüm…ÄýY¢rÄû³x'×¾#dpW1do2`.Idhã„—ûYú1µj CR«IÀnª¦0¤û)5[Ò{R€4æ¼óò‚©µÎy=ôÝ›†ñ i«˜°_7 ãÒnDRH0ñ»ÌÎãY)„·ùœæ'µ~:ÎËb,Ô3XЫk:Fzḛ̈ÊRº—YÚ4ú×I¹¢ ë'é¥u¬ô6e×tïUi2+¤û­ÉÌEÆÖ» Ò³h i»7†$«a÷¦ÄnÏ0ÂÙvü0cX0äJg¥ôQµECz! ¨Ð0¤ÿc?šà>ƒG]ˆCu ($¹Û7Ïý¾ÃÌë yîG Bºö~LØ;¬ªhçANs×'²²ë~h6ÝK¤Á¹Ýþ9; µ~vÕ8TíD!Åš,‘ ;¢äz'F¢Û~ÕÂök¯ƒ¼ QbdûU Û¯ì‚ôn“¿f¯ C:v&ÓŠ‘!É }M»Þl¸m±ëÍÖˆÛ&‘öîoHé:äÉHØÂfHÿYÛ°„/ŽGS£Ó!Ã磩ê4THbï|/ÝE²gv~7‰:È9ôu“…þë5›ö!É}/?gCÁÙ­§N[8ˆ½ê<ôBôëP[¢–ŒMέCR<ˆsëP[¢öìМ[‰¤wŠš"#|‡º6až\kš=_÷¾»o*Å—ãfkz”¼/#HèénÙVxd1BÒK’ÜaYHÀ>…üf—ê½÷qÑ/Ù`0sκJíÚÍúîJ„¤ªÖ÷†Þ2]3M¬6ÔÿZ—{a¨†¦ø”ø>½3röµfä i3ä–½;ì\4x0#ç\”ÞæsdÕ4ê$å˜,ÍoÖ«îËcÈè!ñmô5+$±³^!©å¬+˜kµ^-›³ÓP=‘ëØuqÏNÃ!o¿#i½Z#$½ð ¤ÝZÜVŒ¼f~r(JÅcÚEÚ ¤¶Äƒújº³“Ì»Ë`<]¢ÓFÿ º’¬psäö^«¼GHèÂ8™0gÍvʶ¹‹k|Mï6þ\ØZ;œwµYïÐD¸æ¼¥1œ¹\¢ ]²f~^³íûv+¦ôÀ¿n¦tL˩۩ ˆi¥¢æXtéøž.#ÿ:¡ÿSBçë@ÜWsy}Iâ-m9”_”Ÿ'ØB› CÝöøé%ïÏé”ZV‚RZòÒt@0àR{…Uˆùðû÷9úRŠYõ l^®÷CZ‚U×ÿ!IÇX×ðUyj˜NU¨³.ØArTµÇýU]†`Õžˆ´ÐGèxON1_vÔ³¬‚k¯çu¾ì‚$ t- ÁÄ& Á%е4„B‹ø¼ÑêèxÔÒê¨ÄçU;€DZ¶x³ÕQ"©¥]Åhut<ëÏ‘ï/$±4¶­Žyk%°£VG‰´´«˜M(iiW1[$ÒÒ®b¶:Jdpo!aÈ®2¤÷àugH0äsJD§UƒÏ¡e[òóØÅ#åB;ÍÒ8*bOàÑÕ"ZóØ–X#ä#vߦU¡ÅiÒî퓎÷CrAáý×Smƨ¸8¾sáÜpÿhAòŸ¸trÙ*J¼£9 ül,¸Ag°ZÎåÒoÇŽ >±×gî" ·O­ möHŸñ€d”OÚÏÙö€Ã¾ï>‹Op ð½gù÷Z’o¯G¢êó ùµ›¢[ >9kÆ|tt2C¦àe©.‹uÞ ™‚§–v³ß «¹LÚùÀùaÅßf@ž$ŒæwGWÖoLÐé"fõ•Ї>$fuñ¶\„·%\Ó·{?<ºh0ò …§’úÞyý¬ä»6FRÕÜÁ›&ÎÔwûþÄ¢~Ø $´lœ­¸•(Ž{“.E”H݉3ŸX—cOòzÃ×ô5¹_ g!¬†¹ß†_3øöË\>eiøe*dhr±Ï´êZ°È.oôªèfá•*1«¾Œë|(÷ã2ò"\üïï¿§3œ$öÜY3®ñÏKï'åÂ)fS§™p¿º@‰ÕQJlJmÞl`{À UœwGíyNÚ›Q{ž„VqÞµçIä}#jÏ“H÷v6Ç"n¤Q]ÿó4á°}Žs;{v”mø€1Ìûz?ù2¿Ò "pˆ‡™Ë¤âkºp ÊRy b‹÷cŸË³3§=—ìüQë…–<»O1:Nø%”ƒ8g‰L^ ”Ø••Þbø|Ü'ûŠZ¸®4_9¡ÉÄü#©Â"-2Ã;)p…t5YŸûÄ:/cVoÀò“Híkš)Z;ÛºŠ©¨ãË5}óÜg~È14ÉHd`"eE’!³um«!O±¹ÿø{O ³%lÛêê3"dt+ž2Î ùl'`|ï!}øŠM†ŽsÃå•1t$Òò½› ‰¤V)œ ¾ŽÐ{b<±+ÃZúv‰ν˜ô(vßÄÕ°JeÈðÑ7±{Œ$w¨¼nXàtb‡^¶†ç}.ó‡ë”6zÖ…h&³ï=SÈ®Z磇F^¤ÿ éÅÈ¿÷ø]ê¼@â½3ƒvÇ2mûzr|Í@'zŠBžgæ²+†|.ñ}†Àhž‘b—Ypõžç˯G·–®…aé #ÿºõt- OW€:š÷#8|ïNÖ¬úá2ö¹7˜Ü´ÿ+@é­o$?}èÓ„º§¤ì‘W«ušÚë xbóþŸÌ ©í©ÏënÈCý;;Èi ÐÀ0‹U'µr|Oûa¬£!4}Ü…ìÚhA£gCø‚û0²¦{&Óç&tL—Ç/Ý·˜×ÒÔ5#çIÀd«D¶ú±P0Ù*±d• °U"bQQ®ÏPyЍ½ê6¢$ÎÅòâ_h&†ä—æOõŽ"ïIs$ÖZHiiz˜yXP#¤Má}Ö|&‰to¶@C:5éÙë{Ç¿î[6pâTÈà9NŸš!G|ÍТ¿”:ic×;¤n7Q#ÿ² 0è“wä?«êþ' žUuY8 Ÿíþ4]Å ’á=ìà3›zêdA ‚˜FJ2C²O¹AHbœÿ²3%ØÖi»ôì?øšPLÄÞÀç|Û/UÜÄi‘®nÄ/DË4»æ°¶Ë§ÿ\®éé}Qý:›Lm¼c1!¤oöÌâñžù÷<Õ—_Lq©3jäúÿ,b_KŒ õ´SËòR¦iÊfè)2ÂY«ûâþù´Å¶ø>qaá ya¡ÇNƒ j)к¯Çg¨«ëUÏÝnû{¹jÇFv¼\•~K3èžôÛÞ]®êšg×´€nǼãiâxvÂ£ŠŸÈËùal«f>y‘ùLê—!铇¹±Œ’—ѵwžÁØ,ÉO²mëûa¯’| GÕR8jêòŽ&ÆSS‹œé]É_9ˆ¶ŽÇòVÆw é_Ÿ¿›½Lšæ¨ÒÌc©¤¬[v†öZ‰¤÷™ãqÜ¡@*‘®-?ÂÙ›¼žØòãQïýÁäsx›‘]DÕ¾ˆóúÑçsÉq¬5¥u,‡<Šýhr"qìÒõ‚ô§ŸÝbÈY)s×Quç¡Ô—eHÿ©“…¯âðëÁb¦¾ÏðÁB\FéËT ¤÷SJPÝ'"a)Á^H ªFmb’¿.R‚“T'@b’¿¾¥“zT’±Ä ÉÕ鋉mÜ|ä…sXt0iÒ éÏ,¯"­ïúy%2°ÊN—k†7ò„õñ›ä %2²uA–ÐDˆó£× Þ;!Oºéú(T¬ëT„¸5d]&ĵf÷{Ó0!=KëÃ8צa‚B‹ ‚Óó[ÐÎë%ÒNÀ‡|!Áƒñ²Ip&¦Ñ%HÂ+»†¼™"GÈw]ÈJ㺌Û\#äµOZ4s’ÄBDSf®†µièúml«ìn¦2[GéXínÄ$bšgÞrF@’Gš-;£«¯ƒÒ'+é̵Òj„¥«yÄ ¾ÝaÐo.‘·½ácÊ…Öá{§Ôf„Å4Í„q‰´au§BZ°¾ž=´u=ës ÑT¾[“ÏrRõ4‰$÷ýцɧBR{¦vú´š•aB}{;¢Fú ¨‘„>ˆÇ#j$¡Ám¡R4p½ÖÑÐ^½çúЇH¨Ñ¦ð‡'…TœëµÆ{ÓBôKC|òJ¡;…íÙÑéø“†—Œyq¦ø¾—s®ã%âZEVT™èeKv:MæDqFžQìŹÌô•ó¿ç²±èÊ›Nžñ1çÇå×ÒÅI”gJ°ÜÙ£OUs¹fÇ© ²lãÄÖ°y¯*<ò¯o’C½°ù¹[ÕyÆ;¹^ƒ…CL"ã­\ï8!¤e6™,BÍUù«§Öh¨ îë!!f6T÷õ££WÖ‰ënc„4­X!¯¹sN—ΩûÑX"Þ>– ¤{×>5e?°qBH›Ls6@ÑG"}\!‘ª?;úÄWú‘E¦™ŸwM™f‰´É4³·~ùõÈrî1ÔJHðúѶ³.pž;‰A ¾#6†,…1äÀ®m( ]2vcÏâ?£âPtš1…§WÎkƒ&L‰¤¨:tÖ|ê2[ú®S’ÆySGZ†5Cu¤€¢:’iK¹Oy³Ö#FÞ™MVYQolÌð¯kæU"Èü‰ö”Í»º©ðŒCÍSÊŽ¥˜>—gî´„ãŒk —yiP©ÎTX7Õ§ uîKNË8v눡ä»äôa3•œ$ô¬#±}.NäÄãbm³|ò|ÀP×€²0ì ÿ´Ê†<ÇPï¾:5óêÇ·øsŠ Nb$"hã·ú›¥Ÿ²&[ÒûBž3G²µéz„$ª7K\SÐ]Ïk~ÒæƒÔP>ΔòñRU û\v„”TÂóšç2ʯ9¾ÛcjÒCHñöòÓŽFJíW‘h’ .G®s›AèxXû5ËdX¿°ïŽ­S $]e ðDpNºR[ÔÅ{Ä׌¬¾µƒoï¬J—}“4„bA`U¤¨û±O@}‡Áwh«#ûgŸð5¯4µò¤©±]~‡°>,¡­r2×£ô( Æ—G@5ÿ\ǵȠ!$±:<€è,1Ýhïf„|rxè·f¼¯÷=5Ú"ßZ4òl«kYt»çyÓQÍõدë°Éô­ýn_‹G=J!yL¥¾&yÔZà‡O„´j-”: ì]€ú¤K~T€Q¢VÒᎠ56N¤AØÐÔLíÛP¨#Ívx8‘ÜáÅMÜyA´Ÿ´\²Ë5Ã+…Ea’‚2ágŒ¿ò¬X¦ã³´]šà‘ÙÙ*°4H¨ƒ|#ªBÝ)¨üò>‰Ùòƃoº1œÔ–Ó‚S[<úwn éÎÝæy¾Ü«g§ÁŒ—«úvÌ؉0WhxÇŸž0FB#;făujRc" ¿*"ÂH¨sç>a"Œ„’o"Œ€šD ½!YœÁó¤Ó}áY# ³ÙQ#‰õ]užÒ‚ˆ·¯ªßõªo0úîÞôWK¤gýÏéßoQ%í)‘Á=³hÞXüŒ‘'y^tŒ³àQì9 9ÆŸõÇ]¼\ÂÕÊî·Â#ÿ²è=j$ô­Yæõ¨I$±tË4Vb°Òoºe + »ø¢±ÓÜû†éÞ¶¸›ª•ÿ™'pNdŒ‹¢€Óˆfº›²=gðv+CâkR+{^gE ¦ûÕ´à`ÛýTÂùÊdºÿåÈBõl4ï÷\ï‹ÞF ?_±IrâÛOwÝÚ_®(Vºäœ¤ðª™²j›24Iéç˜Yš½M'=éC¤EiÐמf¡·„L÷ï~®þ„oTv‰](áiÆ-J|§¹wܹpÜê7iGŽIC“è‡4tC™ÒÐÿžBÂ¥.±¦dD†ƈ´¨DÏBáÙæ»–Õ”®oD/T¦Œù™ETaú¶Jö,ogŒôQ ÐÙÐVE²Úßg`“°Öm [¥SO‚·MëZôø×#«ØuVb¤<Øïϡ߼èÅnSP•UPG«ù*Z©U´É¶vÎ; µeÏÍJzäÜä[Ï3›ÐG>+™4bÒñoyz°’DØZæ³ %çV‚H1…H±5œ¨phk8bâ‘5ÏšÖpDâ¯Öp욦5‰<‹5¿¦i G"Ïb 'Œ» k8¢ ñ—œãÁ… k8¢ ñWk¸±GÖpDâ¯9Gö†PÎQâoÔõQÎQâÿÙþ\¤×ªÏ1WüºÿÄÊ0Ù¡&ËýK(×4F&Qh5Fî‘12‰B«1òŽŒ‘IZëU;2F&Qˆ8<ÀÊd·R‘÷Ír¼a<£‡Œ'ÎMZ®UõCK©vÍwÓÔ¼£õ‰1d*ûŒ¶‚4m¯¿#CÉù¬-çö0ìPP7ÍV#¤ÑcŸöa<Zö)jŒ4ûÄ*±Ñ”Ÿ±+ûfàP™JÎb”$‹U°çµl„ÔNkçŽÌbí³S9áQŠ,ü̦n/Ï.bWÚe\¼Má´‰Ö…MÉVΦ¯W%÷mÆ\µUå ¨nš/4+ÔN×$ü…Öi‘Óë]ƒ@Æg×TÈfÜ®¹#¤{#6Î1C7”j‚ý©ojhAsÓd0™é˰GzH†¾T\Ö9”‚èËhÊåË¡uÌïF»(K佨xœ$5Pw$ÒÓÂà†TÕ×KÜc¤o“¯AV"S³êÜåÅ5ç,n„ ­êªÐu(‘‘U]Ì/ÔÈ¿¬òª[‰/ª’òÿüÕæ<)Ï%Ì |§ÁL%ÿÆÁAÉ¿ÑyR‘)Gc èÓ»Ô•oúrŸú‡ 65ºnº‚ 6’DZTŽL–}ùv Äò¡¯GC´•¾* ¨¿€>õ, uúŠ~h®(~u^ûº0¨ã<êŽèê/uÈ×:ÖQê«2dw©'rèç&ø×ÞeýY–xé=tYs^H‘r es¦x!lΧ‚ð±#$½oô݇9.ñ5­,Š4ݨã?zQé6B‰D¬×BöOÙ{œ—Ë5é7’}ðÙ»œ—Ë5] c̰†¦Nðåõ1ÿêJ%ÎMÍÎ@ʨ~-³¸®0òbY/õäæw=Mù†¶„ü8–3iÙvká]j¹!ùˆÇó®´ÔNÇgÕ¥%5ò/;Õe¾¼$ÇÎu/ž¾pié›ìR^ ÔÎv¹<•,-ÝÒ]2ü¢ÏÎw¹ÌiwzKx‰ñäÓv§â°R)bÊî÷}†&T.º¤Ÿé2¥¥Ý©¨ ##aΩK¶¦x¤Ý©„Vàaú™«®½@or¯B™ä%÷e0“œ£ ÔNÎñ@ÜûÚ–I£QPÏæs¦Õí(uìïÞïvˆ1Ô»…6Õ<Aµ1[¨s5¬iqô]“a¨,4üsêÖÌöþ÷­ØüVðʧJLè¹÷²ï$­·©+<û_ßPö¡0è¼\¡ §Êµ¬ÔcqqÔ]³b(ÑÐB2ãØÄ\!/1”ÞBÛ"_¿ zÿISyì°e}ˆ‡C½[hÓÄûT¼­ý?±Sä°©íÑ%M‚¡Á-´áÐùµ86±Ø¯Ñûúƒèò‡£Ôj)޵¥žI†ñ/¥áS+áäAiôpˆá‰8–¹¦¿ÑÿÎÃôßjx|Z'êš®)ø B<ð3¦C ºû  ñÀ !©Õ6SÈ.¹°>Sé5ç²A;5u©¥¡YHÆ´hS·‹ÐïK›clÆQQb%’Þ óÞø¶ƒQrŸtŸÆ²Ô¿îYýNöy7üN¨ë[ýNúÃdçQCÞý»™ÛdçI$µJq@SuƒôrH¹á3½dè©>M>—kR[tÜ‚Ö5š×nƒcÐz£nxñ?¸¼Ùå×}k\‰ ìDèÿú…!#Kcõa– ddãÒT«âÒ¨‘ÝçvØ´ÓÙ7zœ ÚQW"‰]/H­ÿ*]gzSï±[ÕPÚ¦¹!?È|Ñ’eMª~/aªŸd,óaS4>jôÎ}Ùb3C‡!õŒ^PàsÉ¥©›¢é›±‚É£¨ÆÇ‘•XBò½4ZYE"½[”²˜êòÝ·h›ì Ðò$Ò¦X26õy¯X²ŽMRÂçáQ]Y¾.ß#ïy‡­Ës-”¸9÷%F’ïŽÍ¶lØ7BÇ&õŒÈý‹<×ÏCw`¤k%ÏÕ¤wCžkNòÜå× ÃþÖ…,ÚÌOVS\–Üq OJ,vž{G‰ã;—øà5ÑM"ïûˆxï±þ6=ï!W¶›¹2Ïÿ•+«Ò–+Û\™ç?çÊ&ý¹qÕ+ 6ë>Îûôè2ÀePî DècÏÊeFH‚œ”‹J9)ïíš½<—y àÜ8—†íœl‰'„t¡=DäDÀÎM»·Iƒž‰,+…<Ò½L1Ò“>éÏkrÓáµYó!MµÒÖRu[s+üìáYØGuM~Ÿë¾^îS &þá†<òš-[¾æyŽŒ”›¼$ÕÏMºª}ÆÃíéjù>c–¸\S½€†ßÆØÆëü”KT!Å–òF­ª+¨{ñßëÃoÝÞõé™S¤€¡Z6à_÷í“郟(°L¦ƒM¦!Cë9 ¥èé^ô¡i·¥{zy"yTÿû?T_×5áR|ŠÒY2²ävÛë N¤ j±ú;pÕè¦AEêÖ•]Ë› $Òìþ^8תAH¢´ü<)WÛ¥I¸ŸBÚ¹¥"ü:±Ü'ÿÅ}ª'òéÃ}ž )B‹jÞ¨uè©Ñ+|5_«¹­m9"ßµ©SI£IØ;}ïá(ÉkWú>Ÿ)xt•ÝU|iaªe ¤\ýàË<ŒyW±®£þcÜ+\‹^áxFHr?—*4—«2|.a¤kg À¤×ÝÏ"ãĤRþú\nMó†•10(D¤+ ßbEÇÿ^Ö½2F¤9“’GL…@²Xh›7Œ¤Jp©OÆ\8O±´ià|ýú¹.󯃧…Bdz£œ°ºOñuôùOD¾ÞQ!ëLuÁÅåa”‚;K_/Ž}_–[yAj]„Lž+ñD,Ä.c„tèJ5 ²'*Ë÷Ü”yö• Jq¢Žûs_ÍU×ÁÎh ïÛ»j}j±+Ûyú£Å⛀~›W‚\9ԬʦƒÌi³n˜W²h[„¼˜W– ÙÏK¹ $½Su¬…ª£¾OÏZ5lN­Æ!É7ïV ŒI¿O)µR`ÄH÷û”R+]Å!½›SJ/uñù¸¡›Eǹ¤×I/•‡ø{\àÛ}‹85_ï2Að­¯'9^5²ø¤AhµøÜ‘Å' B«–ÒŽYVAdïrÁ,+³õûdn8šÑðõ¬#¥é’á—®V°]â,ë Z5;åº$õoÆzæâiªõ—êÆÎ›3'O Ày;$hÖ õ´s†ðfÉ÷4—é‚Î/—ìË¥§XÊ]ß`äC½Úœ> ¤£ú®ÎçòòDgBè?T¿ÎUL§ š"$2¸Q`{¤ÀHCkÂòŒCŒû¤_\Ÿ*‡S_߀& ݇؆ç`!+axƒ|™h#CvzOÑÅ¡iè?EVGÜÀ~Vëázî§÷Õ·ðÆÖ¶RqÝñfûá! fðŸÍÌõʲñ± $µéµhmVFOÚi†V ž>LçJ9VþЄœ+%’ØÛòa¥µöxðQj1j.™=à+¥v™xkÊõPÈï«Tッ†&ƒ•!rl—Ç-}/+BR}šáɰó43†aZô¹†&Ù£ )ÝÎ Ò©âH{GÞû ÁáÔèE±ø 5iõAêA›ŠFžÅ©¼ø QÓœáâƒt×ú#o|ê‹5Ì,>Hø>í>Heµ"¤Å©6|hdÊF¨¹$ÕÎüÛ2Îy’ꛤßz„$ØÝ¨”û{×uz­‹ü1ö§3q‘oanR+\ÅÁ³&™æ F¡Õ…íZñ4À>²šhsërŸ· !-²S±ÁþÎÚÜÜT$Ý‹3Ä™ågí¥œºV(a#$µ®Þ“Ê-º¯º\p†u_¦¿çe/f+"Ûãz…¤ÏÈwȇRR~wM±uÖq:Âxú ÂRhî×Ð^â¾L&±3ŒgÌ0ª˜ÖÕ:þÿþ'²Ï’}›4$¸:þcž «ñwª{\€p_›®†wÞ nЇd]â8AH-‘“*é™2©ã¾X?ê‹“Hj$¸”‚·ߊCeÉ%ÒUΕ²;²’©Õz´Bž)»]þú©–pÿÀaë{„ôUô}¦+٘ʦ‰~G†‚-?E&¹âF7éR¶ë¨Rv-¬…¬µÍm·ÆËgÝ2úFŽÓºŒqÙ¥—‘i(?̈ð—}}cYRA/ÈÅ|N¾Ò:fGö^6¥û© D“[”‚îZ¬õ¾oÓôÆPj@KÙ:/Í–oÐ¥§ š]“ñ;Yصjû}šçC ­aq§ Ëî5M¦úôĆ…©Ì™~â‚ÅXŸC•É΂ûšÙ4i†*­04T)”óˆzvvñ#j¼^o {#®š(’éÖ-ùÖžU’]Ã3‰loªÖ"óº_ÛCч^yŠÛâÆxþ°OÙ)Šŧ=Ú¿X'›7Ï6‰!hçj,X„[âym²k`bsÖÒ^®sŒ¡²öõïß³ö%8sIVµEµ(\=ß–Øð9·—ë'Ù‹jêšárÕÀ€òÉÂõЋ¤~oÛ¢1TŠCÿ+ 7Ï{þ%åÑã·EÄÛÚþaWMÎÅ‚¯Ë1ïœç„W ñ¶¶?bjW•8·ŒI¼ÍsŸ\®J •2ìªYÑäE3ãU€ •OÅ>˜¬èÙ—uY„¨x[Û_¶²ñíôŒÍÖ"¯'SP÷”Sæ¿\W«O¯ýÐÇ þ ¨§[Ä3IÈcgå¦ÎùùCOº³e”;‰2,[cÓ}kÀöSAZœ¾¼íÒ.s>ùå±D™øž¢Ë³3Y}º¸šçíÝ_‹¿­Å±Ü8;Yv ›Öu’L9¾W÷¥ ¢¦{¾ö©4MßÔxj»¢”Åi” èTGÌæ@ÂÞž¯.{[/°ýÍx™C lž°¦Í÷¯„.(Ow‹Óc1ÄíXÍIŽ—b×åP~¯œ(¾­¢= öÑÎ3,׳IÚé±ûŠ~øBœæ¼¾…ÕôŸÉéØ+»Ý8×Ð!‘–ÊîX³êÁ–Hke—}«ø×]«³TŽÜ‡n·ž;‹”ê”íšÝn_R1ï=RSÚìvƒª„ÌA%G³müúBD6͘lý8!ä5‹®¢¯qUvZ"‘î€êÖ¨û}˜zøJWÒ¦êA•r{jØn¹#$œ^…òw)‰xíÑ$MR#¤¯´ RÇšv™†I)­Jd€r&êŒÿYš©ßñ¯‡h†”J},vp”‘HÄ)Uöï8ƽ8ð}^Œø¤„);ÀŽñ>] OÕExŸÞsu±†È×ñP Zt HM˜ôølIÃÏûˆ{`"³Ù $*kËûʹ¨êjÃפß%è’]­^“O1#¤k–•®t›÷,úÐsÄ7ÊÚÿ§[ÅÛ&Þë¼[/×ô¿‘ 7døF*šŽAB³>bÒuÉŽŸ(üFö Ù}#£ïös~ŸE®™cjä_ßÐE@Ûtº@Æ„ò?§¤e¡'GvE.}_!âq¹*E¬~`uWe¾î=†ºßPÑæ`™¢ žýÏ†Š’]uŽ‹i<ö˽úÆ)Ažé|ÄŸ9güª£]ž{wH¯í¸Øæâsy,Ì@‡¶†}žê꾡‚¬þ U ô¿ÿÓÐ’÷í6u¿àÇ’1òÉW(2É?鎥ءÿKA‰Ù±/©*ÓÜuþ²„R*ĸÇñ¾ÜÀ™8<é7òÐÌq×Oys\Ë3¡ç¸~òÿvmË’²Ìò•V+h÷åw¿'bþG°=ŸE[%æé7(-®Y1wxh„¢*+“gbu]˜ ™su¬’z,jwTè€R®(Ú˾¦½šœ9e¢#C ÄyÅfúiÛC_zì(‡~UÂ[g†?—ÐVB©>´>u=øð¾mñ½††*©­&ùäíðÆÐðÚJèî@‰I§ZÉwfÉ Žª¹³°Òoè:w"öž‹Ì¹×HË &ÇYU=V¹~>ÅŒgVÛJ„ç½J‡yʦι×ó×ú§ÚÅŽ÷*¡ÛÔ­¼]„/[JùÌÓ Ò~¹š*g¿8bdժˉ؆¦J×ЊO lèyJPÆêÚ™„ÄVˆ® ¥€Ã×6— †zÞÀºpž¦”"hUêQEÈòv (*ýÃf2únöbp+>ëÄbf0µŸ›¼š>Ψ'ñUÞÀÙ‚[ÐqêëÒY³ÈËÃx¶\MÈã–?ÃëÊÄÉñeM¹Ö*à%IÏ[ÿ“–µé÷šZy‹áïV9¥ é÷šâ#±V‘:¢È}­›!]¯©#MqxM11üâ5Åœ«{½¦ò–á1_)éý‚ßÒ…ˆoÿï‘(SBƒ ÛűËôá;ÉÉ:9ŒúúÅ3ò9÷Ú‰ˆ—ôÓßyDžJy£táŒy©tÑœJI®ùÉÒ]£…' ®”ÄLŲ„y„·n§¦Ÿ•ÄãoÁO&ø[€úü-ªù[€zü-¸â¬™û¤ ‰´ý-òÊßB²¸- …ôiÍYþ yáo!y…¶¿…B^hÍqÅ­ëg„ôi͉ªÅWùØæȘ“à¶ò/„¼¨Gu#i6õ¨ òVé_TóÅÝùxî‡'ÜçKû©áHåÿT{h02ðHŽO¦fHŒ§ ùƒàu÷ÅY$ü¹uv6*$|Ü9Ô[B÷Äô…_ ÝWP ½ '‡Ÿµ*†·Þß’I¡ßRè¯ï^Õ°2„ô·lSдëÇ ?Ó™ãQâ}tï<Ô™ã¹ÐùÛûÍ•hh ‰3ùX›x£¥(ódÛûÞ¬£/ìÊkµ£$;6dãŒëèÑ dëm'¬ëÐQ#ÆuÔ‘gÎv±Í¥iç ­È>/tÒ¦K>ãš™µù…|—Îù\ÜÊ5©÷f5³ô…5¼3ýFÅ,ÍÛvH8~vÙë«Oɧ™¦ßçÓžÏæ²~IðÕ_×óyhíùü²çž;Köµ;úÐPüÓ§C—,øúz^'Fݨš{îäOú¾ðó?ȷƤìÛ)‹u]ðuÎ=HAœ•RÙâ3°uwF¼VsÐéMÀË„R†I¹dÓÈÇWXQ2ÉÌ-€¯…o²Eœf„ /u;“y3ʼn¥Yê.‘b2[98b4KŸ>ünê÷²×ð‘‡eÛ}|xª¦ßÈ5ïG_.&E²Õ{…ŸýùM±<ÞÒ6f}0êÚs >æ~Ò’ÃE‚¯î³ÿ$)ø)$Z tSáG,âÙ„$—ÛXÅö ôÛÒZ ô[ožÍEÑ›gü D?¶Ë‡ã1ãëÀ5aFðVSÃHóB­f’ÁÑZ§BêòFâ2‘æŽ@&"V9iÿŸšŸGâaÁƒd»íz•‡A¸R!‰%:}¦qRÄ‚lúð!í¤K©ÛÚjVˆPnÇW7ÑŠ *žhOæ÷¾ ±Ä$/!Ëy*—¤Ú›©Áoé ¤¼<ÏÏòYÅ·´³ÙA¾4ƒâ}˜)«Íþ‡¿vÓÚ?úÍŸ Ï?g9¥Pýðk׈)R6úðé.›8 ƒæg$–9YÅJnÎ, ^ú;¤|Ø@†UCÉeoÛœ¤ij&~äïŽè²<ÏÌg¡Þ å }žEë·Í3¼f!3ñ…ÂÙŽD÷~ÖrÝûuÔÒë×Ñ ü:¾\8vçÙŸ>nâabj‰ÿŽR^šëªßµyiveY~ß³¨dljó#yý:˜õ1G7V òÀÊÍ ØMAXø¹AÂÏ„<ït„’ÊZu^Ÿ=Irµ}öˆ-Â|öʲ峧Á¥ž òÙSÈ jµ”s¶}ö’`±9u e¶ ¡w­¼Ò,U·»ê—Ç–Én4ô§Î¥di“_%+X‹^É nŒ_’’ϯ?¥f eŽø%+X–eƒ‘¬ ¶d…+DÁ¤‚Pl-ÉŠ+! >ïxÌØßì û¼×’[kRdt#ýb[H{œø©àn„„>}zGâ+²õŽ}úôŽ­'£wDèå‘L2só–^8Ë3(® í¼`y¤'Ê` „`2Ô俣`£š—Ö=ámìZúr¼t²\oŠûGœ²iɦšTgs>o=gø‰" UæÒ}âÔeÊÅ7Ô,À飿°fvïƒt´ËÍ;DXÔÖ¶¿)G,O%¢xÏÐT©/Pq¡yžD?w¦Ø–Í7±å´bÅɬ®fÔpB¢ ݰJ[š4ËX@ù- @Â/ò¯`ò¡#‘‰È/>tPT‹È/>tòƇÎüFä:]«ŸÚ>t _ûÙ>t yáCWISMˇN!_Wò<3ò¡Óoþçº?øX@á5Q¤ü¬œËN‘¯zßjÀSÈà[çJL»Sç )òé\IÛbÜ 3&Š|:WLVvvÖâ1Cã£m¶šV,ÊíÔÃBEŽQR¯JþÆW·¬*Áº«ÝÊf[sâÈÕ¹²Ýd–¦ã[HY-:î³mšºÍ[|ŸOvVjÕÆ£yÙ|Ô •óæ¼2[³3èØæ¶rØÐ”m’ ø=GÇöf>šÝA’KCCGxç¬%/IW›\c„;ƒI ˆ²Ì02øæÊ bñîó­EHe'óÙɰe{¯uÇ$¶¡‹Î¡Íù&»ƒv„¤—éžO³,Œ-iirYÆ3ù²eɂnjítÏ9f7 ÝVΙYÆbÄ"@IœMl›ƒ|é긜͕bz°²ÏØ{ÆoÉñx?=–&ê¥r¤s–üï ý‰A‹£‹(ÉDZéüô×çU ÇÞ,¯kÝ5‘½±$Pþ;ùn*‹tCÒÅ”#,¹’ÿÎõ>Õ«x.ö9±3`d 9t(‡%Î)DH2+È‹刽œ '?P›0Fnã’;cRë§·®>¯Ù1xüðJ‹ì"fÚó–oÙ{—m˜ Ä¡Ž¬Ê·x¬$qèO¨f$ž@âð^<ÁÐlâðñ†‘^ñn6ãðñç‰.ĪtFâ ß(ò˜äBäüü‘D $¹Î:ßÓ_()fHäKñêbJéFäÛ ®iÚu†³‚ñ¶w,Ö>i±¶›ó‡ñ¶×AÙyî¬>USn<}ÏI.·O±yÏ«ù:b´%Û[ÝÀË÷^˜¯#vO¡Y5x*þWø>ã˶Vñ:GÎðÕŸ—¢."f*­5$þ"šœ‰hYönšy†'þ’ƒ8[èφ…ÅXg“øKâŒNÙÖ²)AÈз*5b¿|ò/U[õ–ü yþܨKþ ŒùüñÉ¿ÈæpY}Õ[‚%ÀrÑHÎD Ü dàÑ–f6põàÆæª’4úÍ[r%ðæõ~Ô÷ïaƒ ñzmofIǩ̘^3ÒÛ—äùÝþQjQVózá-]Êþœ²*R i0Ò—áW‡uÞÈ•|w²}ÌŒÅyÆÞ1›c‡5Ï~- p\] Lì@§|¾<ŠÑü aÅhb‰à ŠÌ‹  ÊëÇ“Aá§Ô•É ?`C²QB1 ²z%¯Ç·Õk¥ElWòzxH6R1]2„t¬^)/ÆlÇ´„&ΗERD"$™½E Æ’~“WÄÕ?’¼€×âßýÑØJŒ"«±q#$¦ßé·ÄúþÓ×xÌç••†äð}ÀÈ–{Râj_ˆA÷m†&0ò/_ Üý”·"²Ò_1’±Å=޼²kyQ¸‡DÚâäE=â2‡a‹{Ëâ÷;m‹{KVå¿Cú&WÙw©2(w™FZí^.r‘ÂÖæ‰"¼k¤èƒHºðd_¤ $B†ßñ’˜Â¬Yø ¦¯è—û\uëô+þå>Y‚7÷¹fé¿Ï"«W|'F!míà+~Þfô­6Ø×ëŠ7 öwiá¢Ó Ôvo½:qZÂ&—‡¾UÇ6Ôro½<ô¥’ ;yuF`å0±ãû¤ßÔÃcoR°ÿ¦–Ï«{îàmS×­y"s>Ò%/µ†ˆÈjÖui2ôHƒ&f§–ÕèµÁƒ«‡÷c•3üEÅ_ŸøòFÅŸ·y£âÏñ}Þ¨ø;W¿Qñ¯ðÅ~&­â¯*þGÖÐRñWÈ—/iTüõ›ÿ¹â±î‹ä±&ðÛú!ÄÜl]Ï2ð(p—Ã'ÇÈÐ#Ù\ä½™ Ä'ÄœVÃÐÏý¶ $¨e¿k¯sÌQD–}ÒÍ!ÑäS*DŒ)"–.2¾W–ÈuÎ|õ§QàÖä/yõQ„BE‹/ᲄ˜åesæ<‘a”½a½ƒöíŽC7à1£K™Ý5ûl\Wñè#¾•Ù]ª#ëc¦# N—ï±áF†…—TÚ†lÕ»AHrY¥hqŠ…øæ;äŸÈ?åÖ6Åä £ËÜ´ IÌo{Øç‰×È|Po£ãé(4ÃiŸZ-t¸Öy"—adðÍÁhF¶! z8Ͱ몋B’kOY—ìZ„¤ßuI¦8-FF^y—Rç­hp+£/¥X„ ´œ¥|KÐb*nv¬»I#_Mê‹[Ö.T¨Õ>¨©jëÓ}‘›7FÚ—ÖI²’þ Dt¹~jLÖ±mƒ’BZ¢Uš‘Êæµª¾ÎBF†_\@—ß±ÙT26ÈR]Ï}Ï—ís)x˜â‘ÙÔ4øµì“OSBÝ\!_šþ^âg^ùZdÐ’¨ßü„–çk*“„§›ûB ÛQÎ&eÇ)¢Ðq|s-`«¡çQáïÉ¡TÉâ%É÷–á(hx];Ÿ¥a ~þ“ˆ!«f—³úÝåÜ*(õTϧµÖž„ÙкT.«lzOy挻Îã "3œs3%ððw¹äõ0ë´„H•íȹ­0Ò¿–t|FHïZ²Aû¨BzÖ’T®% BzÖ1Oç‰"oË_{]@îšle ԓݑݑÝf„ ìÊ Žƒ“fç VÜ BU’ö:ÙÜý)M¥€ÚM¡Ð,rƒ í"œå‡iÌ[óEVeðïïHÅX9+úô7ð½,ÃO9¹ÐZ 7½–Æ¥vKªO†ü@ݼçzGHŸìÿÖ2gÌÐ/½±íE›+Ä˧ôÖŽÇxÞâoÒ›†ØCD²úôƪ\ò÷J3ªhøð×ц#?0#¤Q¿Ì‹ú\›¦ª—‰åQ“ÒP[ Vy¦ij^òwôN¦B^pWeÜ®!Ò0¸÷¶ ¨Õæúå–¹~²h Ôjsý’q㬋#Ô–YœrúÒþSDn-B†Nù‹ÎItöa”^œÔ>eEbrM!½­ŠîN*!ű-üšø5›v ¶ ©k³';N†Ú¶Î)Øì)$è“Jû£óÙÅAeNÛ¦SZH±ÍTZ»î¬´:Oy¬.Úê§ “zÄñL“¤Åc>½ŒãgùÌ;¶ÞüFѽydbiÝ™w¼‡Ú¹%‡8+¼ÍY!ŒãÏœšã¬0OòƼƒá«Gè‹«”P<ønž=¾Ù¹ì & Ÿß5Ye¸Ð Ãj¹ãº5¯.Ððuwâ—'i}ŸVïÜUAœ¤„tk^•ª´ò­ÕÛî²Så•n,?Ò2Úò€ZŽ»RÐŒyp„˜j~ñá ¬Ü‡ªª«’~ÄW'ÖW¬²¦’ÛP´#‡s’ÕewÄõ¹Žë1Ëq„ÕÛê²;òL’‹{Æ‹¬ªûaÃ/juÙIEÓ 2´ï¶ë·suèM+C¥¤ï÷œÍ{µµ€´Vïþ§nÎïèóù¤Ð®MIèï c,YÀ.‡'Vt$úYÂÿŽ3VÃ:%ús®ŽÃo%Û‰½k€ŽF> iñʼnƒ9ƒ­ÆòP6¿f¥HRsº,e‹Äù55ñjHM¨N#?¡©æ¬)’!=„¦ºŸÅžñ·k¢¤)õSß×øÙ½„&ã9¦¯o-5ùk6…dVkd|ªWào³ÀAÆXOìtO8&û¾ù€ž¥vúä¤`«$“ÔAú$yŸOr±’ ~F}×oÙwÝrgL‹ av„ADô;h¬PúÄ2ÐwýYó„÷â¬2 $µû®uØ’5I›$µì޾ë7oeßu…¯[Dà–Õ>Š-#•êˆ)•0)¶œó–ÍøÙ/z¹%exžÊiÀcª^n§A»ÊyÆÌvhÙ ¨Ôy< gÛw›nÜ„MÔöNù똯V‡ù*Üêëë¬Ìš©çCQpôssVH’ÝÔü¢¯­“ߦŸ€ZýWýIk®þðsl‘@µ;!¿:D¼ØAØpÓ‹xš ÁGg#ÿŸ~Kç#µSÅצҕ§ˆÜqĸ•‰Œè½ÕžÉßÜØ²3œEhßÉý1£ÈA£çÜãUƒ‘Á7YVîm&2^&²â0Y!ƒï¥éhûtfiŠín$\yhõ”%|ñeu$ÚJè{ Æšø{&ËÝŒ‘äz{‹E æRücºm”ZŽªs·ëÜNëàÜçYB*4Rƒµ*Äþ¯_‹7T“”Z@ȧwi03äD¾ÉPè(6ìf?<Ô+°­Û’Ô !õêäAË1m4¯ØÍ:,›1M1’àLÏÉ­óS>GÈKqÑø BFø0¥2g]5ík²"ä…¸¨ì|¶ÅEòR\TöHW{ƒßçËgµg„+iÜ®!Œÿ?aב#9®D¯T)C¥–½ÿ ÌA)GyC9Ìé?=LJÔ¦€¹”aD<£»I¢³Å+²W²Û±Ì•|+’r ¥¹—b'6\¸‹È˜ëúcÕIüK×Pwôm¥‘¯k¨-XcMìqñ2“û$yV/a½¨6¯z©·žÍ÷ÍÔeÇ­ø‰fvÇÉÛ ×Ýw®sZµs„DF^™pÕØÑÉÛ-·m™p·öÎq"¯Î‰Iz+ ÏÝßѯ‰%Ó•È÷-f1ïd³¼ñrêKƒ´"èÿpCÀRØýu6ZP'¯åŒÚ“ùsÙw)·“ÌR>Ü“Ç1‘¢Î57g”:ŽRÑ"é6»OÞöpï±2yüP¤ ^ËV|:G"Ñý]§¿qïŸç»nÕ¿æûç·»®ÈðN]gÝuïŸgÍ\ïì=¾»—Ns/½~ÑÌ]pïÍv4sù ™Ó÷Òû绘ÒÅiÕ1ª’B¾¾”FµR-û¶zee鯾#Ó3ºþÔ÷ÒÛúrý÷ÇaôÓ“ÿ˜sã:Ï[lbö‡`:ò ÔµRÈèiÈøzïñ½r«fÊ-Ý {ß½½y€Íò´f 4f«ô÷³žõ½“‡õ<óö×O±­s\rFà’¿ï]rFà’¿ï]rNà’;ذucëÂc'Û©;,+øø![˜f膌ˆ L3°2Íè2ðNìÀ…µ±^C Y³ixc ÍLã’#¾ã¢$Õ=›Ÿ~6ÓÈÑåp.˜¾:Í$³±ÿþó¯"æaÎ|©§Ö¬‚@ ¶GGr8{·•ÙÒŒ±fI=,*zC"Ñw ;÷fêº3×Ûôðƒ”‘ywŸºUûµGhO í«Ì®~+¥Ø«ÚzÔÏfоïy ½íøTa–±ý¥þ¤÷|«ïä]£¬ôE ‹i i”1iâQäKûîñªˆ6¨ÓÄ]­É© Ýæ>àRÛÛÅFå™íÓUˆvªŒôX뉱Åê¶#©¿Õóô”ôÌ£X­I§-ÎF]‰ªô·Z^ÖЦ‡š+d´}ÒMTp²ÍÀ®<}1T$3OœE°ì8ÜTdQjoô²©Ìd«®„Ÿ#»òãõÑ,*dTFŽL X ½’%˜°ŽæyO\˸R_OZhCY(äû«W)kCŠêÏ1w e¢"2‰ÉDï@j™h^J&JW øh–摉=0âO·A+s¸÷"Þ»`È&Ûs€D:,•ï#ùÞ÷¢2âOÙci³vç "µL4玟I·Iïä«kÒÈD9I!ÇcɈ”–q<ÿ’½•…ö“ÌÓ´–‹}éLIËý}#ä3n<ÒWðmÆÀ_M–z¥7f i›1 #rÌØ-j›1 #òpl3ôJ8ÌäW{P𤧂¾Ç)‰œ¾×i‘* `耢ï‰6õ†ë¾2ð eѷЕ@•]x ‡h¹Oy®²{$2ôȇچɇJý#(Ð>Úºà¢wÝqL›ƒ¼£ïe†ÈRÒXÑ‚õ"Я|eK­,[Šœy—Bµ±B #²£óKè_a¶8«8ý\×Üœ™9÷RA& )ÚÅÙ¦'e‡§’T‹æIdäÏ™È1îpï±?½fÜ'³` "+eÇÍïØŠáSÁ½'þ욪Ú žÑÛ/¢Î, âÛ¥rKŸ=ºT†ÈÀ?âäKD¿PAõS ßÀZ>¶á ’[á!KæòM¾¶›QÈ#sK;½lx–¹d†Á…k!íO¤5Á[ž/ÚÖO¼,–’¦‹©ÐÃ˲$NÇCáë¡0§Ïû¨÷>õ­- FÛì¢?^aøÈÜ[4±W"Þ!J¸#‘ïn3º×é/BýrœzQm1ÎÞGuœp›¡)Þu+@Fw–i&m…ñ3U@·nPøðÄ1ùfB"Kîàš«ÃðéŽvÈs5Û4…oY¶pá)8M¡¾†aêm_ ºñZ§±ÈÀoAwd'9N€”E´h’W*›¯ËòYF€ŒîÅúkhÄ7b}×±ÅW›¥…m[láŠz[€¢àq@ ‘#s‘í ÓµÖ > Ë,c E·mê•·©3uåmz>'òß‹t]iÚ6=ß±lÈ2ÜÒšnSÒóÿNÀù°q$DFÞÖwF×U:~Ùô|Þú¶ü}›±Ý2ókÚ‚-O“Ü´D@´Í¿VN<ß&)³nómTI™Kqâ²è:³b±èù_–Ts>i²éùžÀ¹Ï~8TÑóíÐ/fÌšôµ³UÇ*\.þË++ެQPÛáìï?"ú˜ïŸ)3è¢I÷d ‘ž.Øþ'~zþgnûžiŠ#²ˆô0pnÊ ­îB6‘þü™*­Þ‹}…Hj”•lç¬Lû&?˪ׯz—H_j¶@ßÔù9÷ºçéK­ê›6Ÿ–Î9Î·Ž§gÝÑÛì‹fÙ÷z„{O2XÝ$[ž•Ûç(1¼JR™qþ+.½È;§­ûâpvÿÒ1ÒH¥wÛ•GOªBÏSÏÊó3·¶šÜ §ÆN™û9BŸ\8. ÖýÕܬÚù…6²u‘¾§ž°×Úe›ð©Zæÿ2µÅš¯Þ2÷ÃåWjÄç2õ'D&þ÷Ã1‘K¯¢/ÿoù€Ð«Ä‡hæY¶ý¿í!OÚ«‡ù·iâÜ¢×0™ÐCþÏØáË [\7…û¢á¥¡øçÆu“Ï×-¶Šn£mOຉ¬üèºÉÓ‡,×Mdåÿ@×M†´]7%2öEÆžÀuS"=$u6s²]7%Òãº)ü$ë¦D¾})´'pÝ”ÈÔRFW¥úÔ]Ežíú׌á|ˆwÕåç³îƵéõò.~L!¡¥•ú2º¸£KÆ CÃb3'Ñ;š/:SÅ/!'Ô—âW*qYŸýž¤ÖÁqEg#réê ›PisiéàJ©nk׳Íö­kàq&†uT ± ¦Ç™O„TúNŽ-¦L°«„¥£É"Sƒ”Æ~ô×쯃þ3Âã”]6vWÖ‚ÙCÝô…o[™‹'I¸ý˜åãx¶ÄâQÁŒJDÔß>vG>~œ TØ1w½ÏëƒøÛ¿l}™´Ð¢o¼½žÖi€õ§/JA¶U,αrƒ¦?'û„V¥PâåBßÎÍÞÔÊy³ôUB¡uÙpçi£qæEVò—OÚhÜ~‘Iþòñøìƃ¥Œñd3\ŸsRMAKïÌèõf¿8˜éõ ~q0sfòÁÁL_y<:˜á]·$Qð‹ƒ™³÷3gïfîýÞÁÌÜ!òÊ?8˜9ês0£p0SÐ[³e¬œ­†>g¬8˜)¨ÇÁŒ¹ Úf êq0ãPËÁLA=f j;˜)hÊ0,Ö„Å5Ó%D¦5ü.Ø$²È AÁ&Õ&uÓ6ºé†Â¯‚M"éÖÚ=ŸkˆÔ3Z3Á¤¯èÇ¾È @ÆßqQ}—Ñ5ɰ;ÛDßÈ­cfJ_Hq•þr¸re¸Ù‡ü„çþþFŽ9|#Óï;κ2²su御‡öÅê@_Ê—ÂX³ë”÷õ0Âëô €1…„fÞÀC}Ù£- 홇®vÝ’—ÐèÊí.ŠjhleHÊpø~%Y½Ò/žsZÈ@UAR+›‰ÉÖRP«¥VI ¥ Ýzv oc'\ÊÑ;;­“¬m3Bhú e§5~CÂf ˜¹Áwí¸ÁG*x™á»J§eÁµ1OJx¬Að&O/-!ªùr¿fš‹Ó¢×µ¾´A„‚FÆ$ºÔ/õl×J4¶¡âºÎÕU|ªŠ,Î MÈõ‡jÂY3U»Uñ=çu®jªìƒ~âù„÷k`Ú`¹øTqB1É–­Ó$; M”3óGÛœ]Z Þ@?^hÇ §}¨dÓ\tE1tó^ TR¯Ûl+»ñ¡¡Ú1èé@#Óã©äËe^ºN:ªÒ9Öøº¯ý^WkUÀ{ ²ƒÑ%V§UïÛV­ð‰ å+äF5×¹˜{çX¥ÚZ…Ì5zÌ=-Î!4UýÅ,—dª†gLãðX£mDÊÝ•ÑÏм­F/?_sïB*w º,Ms:Ÿ¡Ð‚6•âÔï]É^09Pq;¹®ÜùdE1€Ê‘<Ý*ÆÝÇ"U°úa zÁêö¬Fçb%‚Hï¬JßÚ˵¶%ž7g«‚ÈÈ@Lkæ¡©7ç ¤7ƒÇå25Ú“–š‡õˆÒ£¥îiZÉ@¸è“+‘´¤1_Íä{%˜bx¶Ù<5 QfÖ&1õ>J¾ûŒÂŽ"§qm× µ†h„KP‡Ç‰Ösy§-'SKš€Ik '«]Ö4éÑ¿2ò‚­E&`Ò§¥?i÷~Ã`ͲÅ:ÎGëÌxÚ#ôh½3™4/‰ ï—!Y _¬w*ÍÍDÐzç«’­Ì'õÉzg²ëSôh½3ÿ‰|ßðåé¥7U‚ßÉ´Q”íh‰’Ÿ{G„ëÊ:©3QxÒ·Ô/tQÙNnòãКtÛ–à¬Äƒö¢@ŽÚ^¤ûˆ%³@©´öYj{¡˜¬Þºl¸ê8'¹îu$6kûÏ¿b5'S[ö!µVv¢ÄbmKO^Å^²‹T—³w=T‘k¶ò<Ù¿éœmêu³/“ß;fûƒÉ©Ÿ8yåÅ:âïÂdNüð[q՛ŠÐ[+%‹Ç™¼ntl„OW=f0Ÿ7= öÄÛÞ°( ïÇí-¥vÍ7M"˜©ªÉôá %Ǫæ%2PU·ÓmC‘!˜,ð3býê®ÜzÝÛO"8/ÈÕ\ƒ…§ìùbª³$‚¾Ž—œ‹'~.ªa pïÈšH×®¡Ï#Ï;ˆ´çbàËfyu—¯¹®x’ÈòÍd>Ñá»6qïÌ;,‰¬ g†¬J…,–c"™³w9/øËÍ\‚ЈS:ÏnÀ„¾ ”»Lœ …ŽGTV|Å`EØ °‹Ï<æ>ÎO²ƒXjV+—CëÎT“ÌYk»ä¯§™ÞxãºÊp@AV™7XYÍG¯VOÆãOA‘ "Œ>ø9!¹só½|$ v¬þº®Æä°T6s±fmM¦ÞT¯Ô]Ö,¯×uW@V|ÿòzG6¼ØimõG›A*è @E.=)³ò09Å XŒýøÑ:c|8[ }Ðë¢ øÒ=ÖÈ´Ü4;¤Z÷z¬¿ ±¢”ò÷$6²ÓB« ŠtqX(6ËàÍ1™[ç´ûí«øîëO¸$ômš~Ч®¯ÉÒwð× L°P}víBšÜyÉ7õ?24M 7¯#ß·|‡[•Ÿ¬wÄЊ)S›nYvg«Uï”âUM¡å¹‹sg…vP*ƒ¶äè̼XB#ØJ”Ъ:ºRóè%”»ÿ÷WÌ …ÖcñØNí1ÕŠ<ö(¸e’¦×?lüîÁVð@7vHV8)2f"þpR¬[T–™È·ýrnÙ/£$¹c›IÞ‰ùø¿áçÏe“,M Á-›ÄE†^6ÉÂ8dÜ{äe“,kÞ6 0qØ$c“t‰nÙ$X·-3‘¿çµ8•Ìoz7›nOby¥¶—d“”+D>ðN¤áÀ„xæ˜e¾”©ÇpQ­{ZºŠ%j5óþ&5cÍ;±]%Э«ã^Ø®èÖU‚M6mW ôþöCª%W .z›Áñœ>HÛ^®g ?‰9³<Õ$2ôe ÀÙ ½ÃÛŒá8{!' ùËåHgu ÷Ó¬–­bõog!'‚Y™ è½7Œ,z?8¥O5ô~rJ³ý<Ð;}L¡0¾MÜå+X´wÇUÂé\V·$}=Éìëi¼"$“F”Âü*e,±N¯¢€Wôî?¹w¿¾—Òè>MSx÷w©ç•y®æ•óy­t}]ú²Ãz‘÷î³4^evØ wKKœFÏzßÓÙ{r—Göiu-œF`^éæ‘­³ƒL=¾8­Ì€Ç)_‹ÀV‚¿Â,[ ”Æ7¶ìfÛJ ;¸øËÊ϶•@¶©…3Â6Yzç.˶»,JoÝeñ ÜeQzç.˶i»Ë¢ôÎ]–¿˜,wY‰ô÷€»¬DÞ÷lwY‰L¼:À]V"o‰{Æ]V"Ó{‰þ̤É/$Ü8i[æ(…ë 6¥«›¹ÃÙÔ¶¦gÌ7TŽ©ŽùÝrm:€ôí²m.S½èFjš 3«‚dq?㬡ö÷Y ƒZ­Öëãs,F7”Út“¿ÿʺBín9Î î©ë™É’Wç>Çyd¢@bŠ!VõYWnxÉòm#…Cnû©ÍOP4Ž­ÜÖ£4wrj5•þS‰TXAÉ^Nô¥Œârñf`tv²Õý™Nxö/{Ü!sèé]ÓLU¡ö¸CL0ƒÎE±Œ4r§8|«.ç™8ÇêwPèÐmM¥›U*¨ bq[Ë\u2U{‘Ú¹MuMõaÅqÕ;}ž2ú¶ÊªÊT`ÝÑÛ¡b8ŧ¹œ""Ѫî¨{x]Eà¿ÿÄ Môü™ÒU^ô„З ËA퇥û8ÏTÀ‰“ìàÕ–ÄÉ)c¿„†â£ó—OqdÐŲÑr¹)Kx‚èN†ixTÉÏÏ“ÅbÉà¨óG”,²¬$øè:í±–ØN5üW­U¶ Áå‰[ú:H)„äHöm¬9’Qó¶ÄÊw‹Ú“µª¬O~‚—³ëÊ´÷ŽD¾.­‡a=õÞÃpºÌ#m·ø^Ê¥Ÿ/}=#ïª]96³/$@žtwº·¹“ŸøÖ¶܉í½¹™Ï˜È-‘á}̶9ÎØbñø‚®'ñ}е³MtŸs}ÁsOîc®— ßž¾;=ÆñZÏvRHä±/P)s}=ÔµB&·ÜÁvàÜÁ µ²åü³ŒKvU‹j¨J佨»V€¼û—2öW,LóÑéûó}‹À<Ö&Ë/%yÊÃf³CíV¼~g‡&É*1¾CzQ$¾7 iËÏB6ú#G:{×Y=Y^Ë@жk»n3E´J^¶–B8÷r‰;àvÛ®bÈÀ´|ø-Ï¿áEFZBTÍ ‘VÏûw ¤Œ…›«–DŠôè?‚ͯ­ìgrÔ—¢nIdl–e¥xså9Ö´¸ ‰ ²R '’kÞ‘6ÈÄB6•”d„Lg«ŸŽ—ÑRÈE …qáÙ«ªêÚ^¥TsþÕô¬i¯ŽLݰn¼òv½$­©Øª]ÑSÿH÷AZ+Òj[€ ¼¶G"H nÓ&áªÁ)¹¦O>õúõý œq¨"òS$‹EË® ã»p.úÛD¾p®•‡s9g”øÂ¹V©ÊûŒ1b°Œ*_ 4t ‰ëõ)fkè>CËZ„L¢rM[7×È4&˜,:yÊ Ö!$2‡zš…àò¾O•%idÞYA:99‹µŸ  ¹d§®±O@¬ýq¨…ÖTä’Gl‹÷PKg–M.çÜ sß<Áö ^Tåh‹m…ÀC³ìv3ËþX³lCàC¡–½wY<Ô’cdµøì$â ÀÆ·{ž4(4Ñb™¾B&quBÈ4ä äUÚL¨¢'П(¤_íóL~¼ðbOn»•™Fåá6 U#¯Çd‰¬+¹«ö¼#kÄ\³wû¶c]rˆ•¬LÁ¾­×¶û=B†#‰å\8ÍlFȰqpÇ@ ÞLÿAñéÞ¬hnµVR$`M’‹Ì=¦ÓÞ{1ÜWT¯-¦³EÈ$æ)ã¨I$ê§³ :ÃhýtþýÛ3ËþÍËnùœŸŽÑ'?ɯàí<”î«scˆÉÔ1 .&ñ´ò&ýtö/äiÏ.Öù¾¸o:†üÙÂtyDŽ]¬ìº¢CÈ$*Ó«P÷ÍÓ“Hb%:nñÙ¯¡Ô%®¬ÝÆ8¹E#Ýùf•hWÉ ›ÊQq¯!ôí£Ÿå«¯G„t´¬ÍT±Ùd¢sSt…õÑHksp—‹ZMÞúyàC‘ŽHcÏ>O¯¾ ¡ßQMüëm ­LüïÓØŽIŽrFe84NïÃwDæJÎ8~ysS†Ÿ—aèëïÇ{ž—T–Û·RS[ôBØt½ÀºÜ>‚~–Ï:¼ÛÆ?j‚xö¨/ùd…wÔôhT©Ä@ʨò…ïêr ë†Êï:-ÞdÁPæÏcæ…©2èú¤³*÷š›Éõ>-ã„ s¶–Áö¿ë¾ÖÒ]#cfÐl²’JŒ¸)mþPæ–@´z@€89ç#’â •¢fík`%9¯ßû‚‘iD€ø]F»pÑê!â 6¨é%º=•y‚m’hûº¥mL 8^A+gùJœçÔ‘¤²&,“¤Yd=Ðó×g†ëƒŽAJY§®±kuƒ¾{E>ÍÙïkýV*<„ÜŸç?¾¤èÀªÄ cäk|EíQÄ ïªS¾™§Z~"õêä6×ì…ž÷´~§ïƒq„¤G$›¦×sz2‘7L[ÚÏÎ_mË{ïìû˜c¶^ºj.§ºzhÄ£ÃЋÝ;;bé›Áô 4AÐfõÉ ´x6 •³Ò¾Û;¾Nê~¶›m‰ÅRíTªÌbáysë‚Úñ‡¢m…û?@\Ý‹fj–K„¾ÐXä …”Fé@J Í»Å~ú7䨪Ç\-Ð(úæe×ÍÀ›Í÷ëC¾Pû'ÞlÁ5®µ¶ÑÈÔ3К§ç´2Ó®ÓȽ€÷G­ Xµ¢ìå s™9>û¾ûý³)ÛÚubd•üìzÖÓȽÁ8îBëm©î¦uM÷ž£‡ ¥•NrÓ ÿJv¹¦.🭙Wï|ÎD¹*®v‡4¸‚ð@¼ÅÖX. ‚\Ï*Sr5Þû5ðŒÊ×뙳æàdÌy™Ð;"¹ÆÍ=ZdîA®ùY'ð%Ào,Álƒîz°-·Uc9~«x{G4–Ï:ñz¾¿v¿t¥±Ö©”AáÓÚ×ùôªÅ­Û`Æø1¾Ù½EÈpHÂÒ–ÝGà³çA*Ô½Ýè!I°ÖöcÍÜ÷ „N†ãÃL&öÒ>¹Án‡ªGíÚ­cÇ»!“c¼ÏöoÛ÷„™F³Åj“™5òzd«FóØÆ$û‰‹mõ Éâa-rT%Ðt9ªÊ³#GU’%g¡RpÞ„Æ;^äڂȱïø‘k "Çjd¶ÿ‡äXLcü&ÆÜÙ³~«§ÙC&‘Úzá¬oÈ™íψ. =è"¼ºº˜ËBºƒî ÌB÷ƒ•†[_öß‘Tá×¢pÙݘ¹Ê”~›b-Þ–3E¼r[‹ÙçI©ÆÌ$ÿ‰ûT5f»Dn§IÞ€€GΤè=s+AúVµ(Gœ±+ºè0>ÏçÝ—|tSgo>­ë}\¦;B&¸©£^‹¨?¬BÈ4êÎ刬PìS •»M%Péë“ v©ùB€Ò÷H P”Â#*RfT¤#BT¤­Q‘âcÆT¤å×Di†œŸŠOWæ¤r½EŠÏç¦øÄÈxAÔ5hœŸ ½Šiz•ýæ) súT½¹&pL7.)DiçÏžóþ[÷<ݸdÚY–Ô÷œ•òŠ ¦ñUsyç _gfè¾`þ:¹xpë b?ÐN¾úÕ=?G vjñÁý‰Fî#íòùqVÌÕäój|ŠäXW; Æ—»¨,Çì]ýö3}ݶwï˜9\ß邽2Ty?ïÞ pû´wTUC½0÷%¯4eJÊ%¦¯W· 0öã/åúQíÝæžÕR×n.¦ 5kDõ^ ŸŠA~ñ Ç·d|‘ -Z¯›–nù mƒ¡I:ÕsÃ=(ûîäuÕ(¿ËdŸ>=FÕ™¢ý$‡ÅÉ6|) Ýî³Ân"»8_6NåˆéÖ80ÈÞ5Û)|)§;@ErŽÞHN1ÕM³‡Lš}%Ú·+á òÚQL×¥ªñ¾Èƒ"dIg)\’9¹]¢¿vwu0÷~Kâ^踹½´¸ÂÎÜÃký¾l+z ˜,qCÇPå@G¡vÞÈ2¹dwt;tLºm1éŠæ½yŽcêü-?[‹NMnÑU‹ØÜE]]èFÏÒ|G·hdDióäv 4ôyK²0«UúóI²Ø‘“¥TR¤Ý Ð4­»F¦1š&_<ä5JÓ´Ùì™E©—ƒ‡ÌÃ…è‘—>; ³)'94tI=gu¶âE1|†¢@È[ă]®Á? ~ò?ñ)QØÓ_~™GÈ“)ÑLÈÔ‰a#S¢™j420%2oJÔÈ“)ѻΓ)Ñ»÷“)QàcžL‰ëˆñ)ÑnÑÌ“M‰l±( L‰Ì› 4 Cá”h iœv·¦DÌ?»·™„¹b…âŠác¦ñ-ÿ‚‘ PÂ0À*.ܶ–ù©‘™Ç½Û}:†Qg™XzL÷ðõ¢ÚiDHŸ¥·oýªuäܤ_kdê%ïÖMÓXóÚ;æ7l ÙºÖ¼@È,ċ޹wœ#$féí’i9uÎÜ-14’Måu*Ó_»QÒH«liñÙoñI¾µïèĘys qH†š>««ø¸q䤄 9ÑrŒÜ ·rdT¦ªz£$øcóyZ2uÓBi›dœ-o·ýÑHìãŠëeyöìä—IÞ=¥“©[…YçêÉ›=m à„ÓË/vPv{N/—X[C>Oh=@/ɉõ€üMí‚ɱIµ1AH½¤‘&ÕÆÕ!}ô’FBúT»†ôÑK éSÇ„!}ô’FBú†ôÑKñú‘gG!}è7±×Z Á> „ô)$ éÓȃV5”`HŸFÞšµ]«¦_y™S(û7VŒc‹‘å¿ú–F{Ì,ŸÝõ†Ž?Kzô`8¼0h|@/$ÆÑ“ÿõ/àèQ¨ ŒÏ›Öf[#³åÄ‚,'h’œlh íMÒ³wUS·g‡ü/¿Õܼث2ÿ÷$;kxªZl‹ ´HxZ‹„†½›r0ÈÜßòVú¿9±¢,Ë¡éR7ÓþÛ©GEÁÄC9W!dŠN4 ÏW7¿ ’Æ:c‰ÂÚï«z$= µÙ¤D¾êûwè›§èðŽߎ}V„L‘%ŠÖܵE;ƒ½ÞpC–ÕÃÄ1ÎË/³Z*tæ)Y[$ÿŠ¢ä™ƒ–cmö Óð~ÖD#mÓÏéôËÛ½GøžÕÕöäţ퓱õí;¯¾æ™„¿dUY6gšþ çØÂ›bû®ô‚”òεyX^ŠÓ{ÈÄR…*óÙͬ*Šš[rM±…ôírÃÏ«~FÈ«ó·®ê={lžŠbšj[`¤é±w¡iö\Ôïém×Þé[ÚÚCîO¦{=ywDŽ6ÔÛ½?—Õ;¦ËWemÝ–k úËFÞ`ûÚìåîr9]?<¤V‰øÛ¾yXÀ¶/û.;¤ØÓªZÈÜŸÉ1vHõº¶)ˆCÕíæÊ´›k¹íá«­WÄ¿zšÎô¸<{š…Õ\SÑ<ÄCs¯Ý¬{ÈïB ¦‡l $ÒLSÎö¶’}9ô¨ išiu1ä:Ó4®Yo§U8ÍM³£U…l12`WÅ´]•-÷¤`føwŸTCIŽ£* ­UÞ,kÐ%MÉI1tkÚ³ÓƒFè©§Š¡ÿ²ï`æ¥ô†ûèØlô 7ýõÉ21nŠ÷Ò •εkûÁC52µÈ=TaKSYË%ã!¯Î“ÆÐ,ÄroZ~·ôP´3ƒÜkö³—M;,#Bæ¶`ýÐÝ´†•œË„¨'„$¹ÏÞ ù³IöÕHjWø˜£J%BÈBºc~D3ãë4Š3 ×??…˜ª¢Å7ï¢Ê`Óìí´¾{ ë”m Èµi瑪®øô_Ž/Õ‹JØóºq}N3»{G½B«î½;Ë£Öm]ÙeAzÃQ .ÆNÝÖ4NSá5wÆ—ÚñE]ïÆi] uìèÇCûÝHè½{OQaèþ²6[ ç_³ ÊÙëùö 7Ui› “ÐúŦI¼ñ×ÿ³ç{RˆÞÖ–ÊÀgf³÷G¹XÖµam©oõuyß?04m³e“GåËk½{GMM¨A¡%wô—xMÝC¯¡­C+—¤ÍCjd¬ür9Ù!d —®:šå—M¾#×—ö:/¿èKì’]~Ñ—Øo)»œëK,›T#¯A‡_¡$æÜ ô@˜‹KÍj†šY¬¡)§mÜÐÌ¢ Me¤ šY¬¡©Jލ¡™Åš›U lhf±†¦j1 †fmhÊ牚Y¬¡)¯74³hCs˨”@|G1cáÄ4;56«u ¦P¾|`½ÖpdȲ¢ko¡` šÅ‚1cÐ,Œ!ÇOŒA³X0†:& Æ Y,ckê` 7ËP0†FFše0C#Áªƒ142Ú,sÁKVÁöŽâ¥^+V¶Ý¥gô¬¢¼íó¼hþ áÔ4Çìqm÷²/›åÛX><zÇ@Œ+:»ZËϘzª„g÷œNÅxX¦¿†ªsÒmêTŒ:IÓxÌÓ£_¹Òè2qµ‹ì†ªï·VÌS´b¹oáÖ{8Ú£}/céžRê±²+ãù.ÙÝ˶ÇgÏB2ëêeÖ™•ÃrMÛÚ´"šƒ Óƒdå+12¢ìhçÕêÞ42¢ìhå6ÖŽ`9¶<ÁfqLuˆíÛÌ¢mJUkàÜŽó@—©Ø”Ûl¸‰éý´åK¨Ë4ê£`ÅôžìÚè2ß§Üo·øì×ð|Äë/wß'9id¯òÙ»ç ­Qt”Õé5h~FÉ`cîû¼ÅWÊ€ÁW¼ÌdÏÌP0p„Lbf`´*Æ€™‡Ó=Qr‰ëžT‡uÛ§$9Ïáp#IâÇDn”¤‡9›ñÚ™‹\#D ]²¼}J²“jTÁàóÌ"D ¦‰@¶"B²HWŽ †5; ù:"PÆ ‡K²q3a¶ä"/\šŠ)>X©‚pI/2r¬,y·bdŽw¬ß­M‹¦ \ï¤äÙÕNêkg.‰C•õÄT¿Ä#sÞ£›¹…øZ£W UWÿAän˜ÜM– Hn(Óeo·ïÿMÅ5àßU dØÖK°bq÷s ½zH7Ï3Ø‘–^â;>eõo]'(½`N4´å_ÆzqõJ ƸvÁUí¢ðÎ~=æ…(ƒº¶ë–ÒŒ`4`¤w\w‹kyÕaÌæÃ÷«XÖª@È4b\Øý”¦'AEi³+z̾x™ `­LiõûPÍÖÕj: k»åTð?a×¶íªª)‰šÈã~?kŒ¹>Áxx‰ű¾þ€BCp¾WŒ"BÓÝUµs»kz¸ÝGÖh5åþ4 îÅ”îâg€¼ÿ’»€®y‹ÍäÏH˜Q²å¯ÿ|!_.2òÉPq\šMÓ@»Ô^ĵۥR\ëÜfùUbåƒMYC½Å)ñ5ª5œbd€Û+}_aç"·°"Œd6˜–K˜ ràFBÁUec” ÚÆ3P„QHv̧aE'›m)BÆvÞ¦Rºçs\‡¾Áÿž|çm:™·i¾a¤/37SÎZ“!ÑI6f^7p±WÈÔ_H°%÷RÃÑñ2a'Ó¾K°×”mµ<ˆ©ÌÌG¾cÚÃ@~GÕ`¸ç©Å¼ñ4¢g™‰*-kIœ·‘óµÉÙÿÙ2“2V”]e°k#ŽŽ»‚‰È+¤šÉ??j—9œlEl±®Î5½2òƒt15$’¢\º-Î7H¦[»6Á–Ð{¶pOYµÏçS2qßøšwÝ6‘íövÕþ6ëϳ£ËÄòa[<èªØÂè{ÉŒL=U1~‰÷ºÁ F@.Ë#]Ù¼§vÂ÷©êg¥dÑ=êg”®Vw 1rY^-«Áƒp,ÐÉX@Ï&r¹ü èµ–\.hÞÙ’”jw%—ëyË|¿Á¿ßNZæ¥7ò€‘·`#<ðk‰¡t|ÕC'Y…Q"†ÒáX H±Ež±QñäywÃ,…m#åy ±ùÍIŽ ÂÏê•q¥X—škdò-²©Ú ©§Bña¬=ïW|ͺrðœ§yìh7R„T-U?¶S¡¼fÁ çšV³­±èY–%aõŒÈvöˆý¥zǼ, .DŒy—Ï¥±çè^##×Æ×ºOÚñÎŒ§1í-—z”Ä³Ï ]t†‰X–\.!±íÚÖœà‰eÉ¥h†ÖÈÓ…/ο' ý$âmŠ¿Ÿ³ #¥ÎFlK.ÇšÊfÓ‰6™œÐìÚ‘ lFÈ›WæýSМå!!—T{Ô Öm4‡ê®BB gG*JœØ¹ÄŸ³!Ç HIåÊÊ Çÿ~GçHUî{\ÍÛ#ýÒñ{}v®kr.ß2Œ$ß ²Îf›õ‹zâìÚÓ€ÌúòæÍ0!³>…<1ëkð5OÌú&|ͳ>óß Ó‘˜œ'òt4H¤mÖ§žŽ)·`›õ)$Ñ™oϑݒ½é$Vz@>PŽü©>Ò (q>+? 9ò½>p„óKn›Ûš#¤éh(êò¥ûØ(^»™!pŽ©kzžÓ5‘Õ•œ‹êšýýJܯØúÞ¥|ï6åÈó4ÇÈ›÷‹kÄGá‹3k^U>Cö"·°‘N+­Ã P&·kÐ:¬Ý­Ã`?²Ož˜aË(‡kÞÂZK_®&R½E'u&¾Í#½ÄAù¹Í`çAnqÀÎC<;ª–+¤ÏÎCÌ»V¯;f_çGë½Ç;M­ó-GHÏšÜl˜þ«>;ÙCdUàòá«Ùª5?‘·¾ªÖdŒ$^; ”ù&·$¬”*‰ÂÖ¬ûΙU`T(¦Ëàß¿éVZj¼E¾Òäöð(º¾´ù!]ž}ƒQк‡8äö탌< ßÓ€™coD4Ú…²Y2â A´0/„8dœ73çÉINBl `mGn$èÎùßÈIä¿ÉfUüïqØÂ¾]îÔSj©¬ß>–,±ITJ¡JEklîë¶ó(b‘¨4‘G™àÍY?0Cä!‰ óx¤ºåË’ ‰êÛiIê;v5B"jNSkd‘¿ÞZ4’•—ö=™œ@di€þüQä”c—{{3V0JÑ9£$ŠÃTò=K «eðõß>ëJM”Tq¢ ðDwËZÍîÐni¿-²{!äMGéû©®IÅ5!Rî8W Ù [D¬4™h-º»šªj.¼y+Í6|Íä{.IcÒ•æÓ†Ÿè®YœødÿÒ¿f†‘àåã‰ú5Ÿé‚ÿ=ÕÈ8o*ý`ûmÅOrðæ$%‘¼›çõâ° Ô6K_åø¢Šèöïx¦  y× ÇЛ•´³ L<¾óP×…«8ðºW5ô–õ¬bFgB%öÜ3ódå}ûWôÀÄ(ëµ|i ÈóDXïÍž¥ÙÔu2$@ÈèÛ2ºE<ï¤Õ—:_;wÙg\ ó-?Á1Ÿå®8‰ùüâí²á'º[³´‚YZRqè6³ôñ¥ñ®ÿý}D¨^µ™ÚóټСèç ñÏçÚóùaÏ=w–ðå5vH–øÕçC—Íø™ôÜs?½N\•;P5÷ÜÉŸõ=PÅ5üƒMAº™YVWË2ãu̽ŸÊaAõ5³L,æËŒÇJY R…<öO¹iÌ#‘'%§xå”7íÐÁ,²Jÿ~¬„ËŽ¤s©µ)2 ·±™%’œ8Ef"¸‡í!·œ ²å \I|ùv‰Ñz¨8Hâ«§äwˆˆóÆÖ¦ ñ-˜ä­MAl7°šÿþÒμíVé}GqÑm@FŽÄ9Jh¦g×és[š†fw[2òz(M5k7í«GŒ{Õ·‡ÒØr H éÛ†¶ÒãWÞ(ÉÐ?ÑÃ{øl¶aå9Ügr~TgXbCôq¥:8Àm6 õ „!†ø´}2ã÷Jb»ÈîKëÃê7ÍĽQFéqvìÿ/b9wyÅ·'Èf*dvÝaÛÓµVè¦ZzjdŠ|í ro™`Ô¤Ïl7°??ǡÈÏ[(&YD_ u'b¾- Ê©3AsL¼6úˆ.6Šgêdú‰’Ëoêd!ÏÔÉð5OÔÉf|M¯ÊJÔÉHrAî½ßòȰ‚Ùôç¨Öåc@Þ‚åãö(3„ô–éQ>ÆH¿ ùQ>2†P¬,¤Åñ>ò¬œÙ8jµ"…LLƒ«NóµÛÖÐL × äÝ´úòǪ˜MÆDG!ßÅëV¯12µLt€ UnkÅž#~vb§Õ±n{ÎÅ×TÜïƒ Ui›¦hëá¹àaÒÜo»x>èâ¹sÕÛwõ|ÐÕsçªÑwù¼ÕåsŠ¡q¸~N • èÜÕà Ð[]@wîõ.çÁÚœDdŽl«—Éóþã@ÑS&ˆÄžÌÍPÅnºÏ¨ý-e;·Zü—$ñ‰†ßP›Vh…êƒ)&ÊÔñ6òÉÌh+5wĵ."óþµÎ³–ZWÈ»¯½ºí§¹ªfüì_{5ošÁ´W+dŠÖ¼Zé¾?”™bMbRs]Àme>=ò— 0`ëBÃT“ôJ¾Ë_J–D¦E[Æj@Þ¿Û¡}VÖéÌ[ºÄëeËN1Ñé!dêR·H—Ô¨ˆI^ŽYëXÉÿ*aô=fÍY¶ÖȦˆüpDc¯ýc朾ߟ#®)WˆÃ2a Oqª{¾:Š‘µ–Õz-ëßk>W_ÓX;ä‡U}óZªŒœW㌉Yõä:v4n|ØÌx¥?ä…w¨Xœó¥æYSÑÌì –ÞÑ:|lKòøÛ¯]C×!Sƒk®²4i–|ÉÙçšw÷ží½IîùþäùV ÎÈ_ õ0BØÿþS‹äøïÕê¼—µ”Û{X–÷jõ†Êµé¸ÕL–H«ŽaèþžÖ?ÇèDÌ¥z‹cíÚVxôÕê|è}Ô•:dcó§n14ù6Ìx·ÙRЦ™ñ-w¾f40Ì;ùÅh`ÂÈÛ·äA»KT=$Úï$d4 ZçÍbgôÏü¦¹Ýþ™Ï`c#ïþÖK›A—Ó¬¨!B›@¨KßÊ¢t²u,>:wü¸¢’]âèç!¯7¥Çõ«l¢O YÿÉò·ƒDe]úþÌmÎ_§°mÝâ^3ñmaøšVÙDŸß”M¬ªzxïk¸lÒtþÀÛ|\M®`”ê¹èô öøn­Ìxf‚Ç„Ñ.B.ïb¶¶mÇ„Y.‰},dì-W-ß GÈÄ6gÒ-Ãë9sÐç#È„ñå2N·~toa¯ÊÖwî3D‘Ä]xïQÀ‚DìÒ‚äã oþl—FƒgO¾ŽÝ¬r@HŸ*¤l÷°h–IJôMNÖ¢˜b‚Ö´Ó®–VÚG(Ç-‚ÅLÖ ºðš*)CŒ ¯uy›÷ÓµnåæÛ¼Ÿ¬u¹\ëZ„ ¬uR´Åy¢{ˆ¦¾5Æóع¶Co0㙞Ñòm0kHzbb+ ¦ßðìäÌ`zÛ($»$DÚ$ïBÒPëºl†²AˆÏØÏäâ[6@þÌ¢núíƒ_ !ùxÓ¼cS7]âÓD7«ž—Fa²nﲨ›.Õ°r‹jHÒ3m×ÌΛ§÷p-ó ©s„¼ùÅ;P£E³ôX~n/Ó†–>ÎèôÙä^’¦'tú½æÚ"äÍ#÷0‹l–ßBF~¤´ü„gš"9'1îåù¼)8c3ìÚiêeïL^¾öfâ°Íijíÿ”ZíAáˤø1PvòáGŽãÿ¡þ½y`Ë íð;Eå&/²Ü¢(‘‹ãw¤‘Û‡ý`, ¹ ØÆ2næÏWŇd׉-¤µgËZÙ«±ŽÖÏä*õýš‹XøÜ;×´ä*w¶F-ÿ}YÄAÖdáÉ唈`¨i$hÄ&Q»ÜƒOò›Ü¬Þ䔥ÈÌø¾Ø–ÙÆ÷„Äað^M„ùIB~Û¾‚‰@Œ!¤÷Ûl‘X!žÚ°6ŒCV¯‘<¿´æ·®…¼!"yºZóÍÔm·€sÀܽŽÒm¢á×i—?©>Ç‘Ëåì±h÷‹ž"d@*HìL½#ŒÂž @^O­§ÖÜçÕ‘¥¨¥àžØäf´õFž6?ÎÓ¨š5òäšK¡‘Ñù5užA#}$dI{2ò‚$9†§’äàé“䘥$£Û€IŽul5V#ã ¸áêü»W’c’ï'FÞ}§r)¬Cõ÷.‰Sû›ÌkO¿JÖÑ´ñ!•‹,#ŽЯ:el„œºˆië]½¨h¡[ÿ4"Õ,×ÒKV™Ž¡ø>“ÐiB|GpÍûI¯RÑto•1ÓȹA|G”âkF!j…Øßù8¥VPfžèDÒèhãdú‹#ä©¥Ù†MEäâ¸L9nXeYp=—:&^i-:¦@úÎÚª[h˜²¢›BÞ‚4GÝ<®‘ ëc[+ÌS.YÝ-BÆß¤ý> ÍQ -𣒏™kš£—h¨-Y52 ÈžJ/@ÆžýHG©E “©Eìƒ6©E#}¤– PjdäëÂlR‹FÆ>ò"·I-é%6©E#}¤– ÉJj¤—hÈmR‹Fz‰†Ü&µh$ ˆŒdÍ{œ!ú¤. 0ÃÕÈà—‘ÈÇoðïéo !OòÉæ½§¨OËÓ[¯{‹÷hϺôdMŒð¨FÞ½Nг%<ª‘°“âs@È“Ž 3ëÒß:&ð(vLà¿¿^}§íÁ–PòA›Z[‚\grß#º=Ÿ b–Û÷ª &Ì"-ÙV"$­µãä°µtÉ:„ŒÂ¦ó ²ßWR´?ïb–Ûí;»ÖÔ:»6UÛL2ò÷ÒÖZ™|že6%’Âo}ýLƒïã&Õ´ÜòÅÈäÄ®ÙRÞÈ{0ÇÃw¡¤®ù8É€Êc¥v¹jÍ}¦'‚·VöB Iø‰Ä9r3k˜E9óÇÔþâ#ע܊”§ƒXêöYåj\™T*òÛ“ç óþog+DùMŒÎr»d2>Ë^eVŒÅá앬NM°)[„G·:ÕÊêTé }²9bœ¬Ú­@ÞO«ûP»ÕÈ€ˆÝ$Ï_0£¿„€ôú4 Óöyr3òiX*jù|º"Ä:úƒ¢Fñ‰<9‡so”žq5šÁœ'£4$/bk«¢ äÄ-ΪKÌsmí&Ïç°âƧòbŸ‡³tlÅ8>oç"æønl†ÝW.ƒkzük%X$)ŒÊñiäÍ'°ÃlººFúÄ…rq@ìY?P„Œ‘ç§"EŽÍ(žäiœ›rv ©¦:kæf¤]=Oun€´ÐTgyí4¿rgº©vy¼Ö¬pqlZóå“/xFGijþUÏKÉt¿ÄfÁo+ºY¬èòXª´äKoBs¬Ð´V¹•¹mç•fe‰¡8ŠÕЪZiÙlšX¡is0¦¶Ú±]ÇCï~µ@«åB@±z@^êa}Oô#&95c•º s–íó‹V/8Y.RÿýÛ?,õVå5—¹+kŠ‘eû¬¿«¦üˆX%‡p?NÝcYYë…¥«ÛÚ¡âï´&t>á>É/š¸Þ°CCÆÐ4ÿÇÿØ--è(& ÌèÄÖ;ý9ÒZµ¢¹7ëÔι~"‹(i4Åkå2!V`“ªK®Pÿpo˜6(Š$·”½b È(P’iµ«våy ƒÃ;2¤¶€1¸ƒ<1‡¯.‰ƒÆà2µDµ1¸FžƒÃñ!‰1‡C!µŒÁ':1‡ƒ»!µŒÁ7Œ<1wgÆàÎ߃»ïóÄÜ…žƒ»÷zb îB=Æà6¨Ç|ÂÆà}XGeg,¾rËŠ5{ih‚šs2h¹iû¬¬²W {y’ –ÓxüiÅ䳄$A-‹yA~C÷jó1£òHØÔ UüäYùy®/Øó“ä«eQÉp̌Ϲ„rd’„ZwÚ´, d¨d¼©ö è㤕EœIM+yuyÛ½9¼ä™ïÔ^Káyó8ClÃ0þŸ°ëZv×¢¿d²yì÷ÛU3Ÿ › ’0`BÍ×_eiƒ„««ßÖÁDioi…n«k5Z UL+ÆÅ¬Jx:4ÓØô@† ©‘…_9:ªIׯ¶þŠ—pJp´Íp,Û×<£üâ &-Úù³m£i“ü"¶·Gq¬Üçó‡¥Ôrâ´!é!;!dÍ ©M¡¿ÐöoÈÐKÆ3Û‘©íLv!Î}¬°4ðø5Šzú~êk¿'z1V+@:äœ ½uxUÏ=½$–XSh_êKuõØ›¶âõ]2²FñZÍŸËgç¯î,Ôß“xá˲¬>z7¨KÒá”o¤ï§5'‹C“ pYtšÀ¯¡“Àÿy“7Æð˜>o¬×JNÇÔöD¬fUEÖewì'dâØ’#ƒ®Xý(Fã9Ь·…ÒÄ320šYm2c(2õdÆðцeÆ@¤#3†~›,3f(@FWŠOT2r ŠÌE Ë€´hÞ»‰¾wMuz†?åñIvô{R?Ÿ7>¶ˆU‹ú˜þÙ¸µÝ?)2ºÛ‚G‡é¥³øVj`ÕFu¡&37 a3‹-êÜ ¹CáWÈØsEÆ%Ÿ"ïvaÉ%½îf(™)'–ñ‘¡Ã{”>w„¬‘Þ–@]rpºe_1<¦éY^9ï<¾k‰è$kæmKçmÒ-êŠý„L©½U7CϳC<¯ 3WË̲XÌÖvf–æÏY,è[ô‘ÂkÏm"”Ï.týÔ©s 7.B‡ëhhà×yoÇ1Ãk BŸW¡ý)Y“¼s7Î\¾ŸÙ:ÛV¶™ß†ÞZ%ðóábÏI¾Ó´µÃG#Ï[U…Û/HPVcÅäY†mk› #g¸Pxkdx£“ã ï Cw7WxÃcFÞ@ÕVòÏЫðn¸Â[3[Ÿ!hÑ Ý0s_ЫáÏÈoðm{BQ¤×Š –'”B†ÎÀtÛJ!#ßýÔžP éò„bÊÆJ!žPô˜¶'”Bº<¡pg{B)¤ÃŠyYžP éb8âÎö„RÈÜ­n<¡ôø³Õ[xë_”.{û44ñ„ÙÒi…Ùnº&?¢uÑfT‚§…h"¢5KáyÇ» oý¡wm•àõ˜ScݧÌÁšT!D–¾ˆ"}l]Ž4¡N™ûB{΄:)dèn-kw…ô}ñÆÚ]!Ýñ5([,õSKiJÆüâV ]ThÙò-ËÎb¶ªMEtÉo®p5nH§3+s!ÔÑ- ©Yù„,[îna›Å3üõØéኹ‡+üuÛ>§Vdô˜„óe™zÝ^W]¶ä7ö9KK‹Àòé4ÅY鄌õr}œ¿xÃáAˆiÑõ1 WêvH_4û„Í×a«å*3w™VXZµ<ºY²déhºl°£5ÿ±ƒcØ[U1Í–BÚ[*¦âþbèKßæí ¶ «VKÀÅôn»¡éÒÖ|rÇ(â¶½±™s{K…ôÊÝŒ¶4e]¶ó:db,Ëjù³×„lhŸá1Ó+››ÍH€ÍmÇ`‚J„à6›;O|ln:†6wžx¼¥EQoŠyê §àHNA‘¾ÀL®v0á ºCbÁ–g7#˜K§±·ADæëxúDDßéBÏ\FÉɃŒÿ+ã¸iQß—¥©L\'/Õ S˜!—õ;÷@ÚqlYY|ï¤ízÃ)Îýz-Ú3S± µó êa•÷Á­•çQWayýªEëCÙ÷+ú̳)éóüäW­ÆOÒmU»­eÏÓg*ÖµýéŠÜ¦b¨~•®s½0!U‚U­FoÒ.3HǨH'ffˆ yîQø°Åb+)þí„ÝŽ@RH÷vÂÂý˜52ðTA´¡UP·©Ñ&x@Gž÷[-Û1‹¸Ù„§PdxâÑ×ÒŸpš'¼½æ£n2TÊØWQbáÿUìå4ïxSïRð°”°Ng_ñ¾¿Í¯GÞ…¯.ýëñ K–µÆ-HÈSÅÚG$_é)F‘‰‡ÉÎsÝ6¤j°à‘:‚åÅiéÃyª.$iáOÛ  #ÍÀä®É|Sð˜‡Å„Ñ(d¬ÃÑtŒ-fv¯Š µ¿²XZeÈ¢CõØMS5dªfC¶ÄÆ¿w¶uþi&2™;oñÿü‘,ní1‹W4½òi’UÄù4Ñ %û:„Qö@ûÃϺd~EÒ6éKÇÚ¡€wIMó ZqGkZƒÓÚuªÑ‡œR ¡e)¾ÎfÊ£|õ: ÔòSçM·œæ§ª(šÓ Xi±ì–ò:£ûtmUwÛ¡±ãXó­>õk«nƒPÛR]zÙOõÚîû6Ï/Mm÷u¹Y°|Û­Úªåt0j|×åËÖw«ùtYOÓ×±»Ê/k¥Ô>/¤‚Ðü ý2èvJº¿€²@±ôïù=·ðÂÀ’|ˆ^•™µ£šöJZ¨ zÝåUÊàú Ò·¿›£P½ð"Fvg[¶Š´ µ…ï ¤û(QÐÓ¹&ª-à[|Ô/< >­0µ4'ò%(—¿hï2ÀO0Ì´Y¾"‰6_\ ¾¦å<BíøKÈû‘õ¨?ýÑ7ðÕs­9Q)GÍJ&Ôn3>ÑÃrÖW%3Fõ²¼¦Ó`–n] ‚Âwi¦ú5k‰‚º#J޽pï@©%-f$†@k€Qß[PÑ5³/vxÓæ Õj-”UZ5;´Ç]8bE’ôÁJãªÛ'=ë êá[Á×%²ó*™n÷y÷ŧž¦~†ÑS%pÊ='E±‚½Öêt¹ (˜Ž„ö¿÷º™‡}DpxXP)Û]ë½·¡;=ØXÚ$ü‡Uˆñå8F²½ TAùÓ¢E(”k>Ží`Qªí•^ìTÅ‚D;T[Gª>Ø86éu#,ó§ íÝkÛ*x³âDC Ö@3ðôFÛ{!ïó¹¦Ê-£è¿OWÖŠøÄ™*‰3^ÊšÐѵ=+ZÛ?ÿª$Šš¯Ñ×´¤%;µãÜ@ÙQ™úA—Žt-<ä¡ô؈‹ÄøzþZ×-mz|³’À@kiYÐ~áPxñ´þå,£&}µ1#'h¤¶œtCAÇ‘±ý`øm%±€þµ ‚V2îè ‡âD° ÍlÈê˜Ê{†6IU*T/Oh6Ò^²„ ɬԈ²á‡¥5øwÙkrú “çÊ–Iö­›ÏÐ\C+Iàl޹mïêT ‰Êž5¾«mùºØ€šeÙ^5|°©`.ü'VþjÓs¥½ï>·ðuIÙÓÚh³ÄJ'6²•œŒO3w)(çmˆÏ°à¨®…ãkÊžÖFßÅÞ,5ÔÝûEÈé\éÓÚØRÒ¿å»’eN5Ò*²¯ö7œ·ÒTCÙÖ/sê7ê§fyW°ÎJ3eçÊÒ@ÄëR÷G]tâ8Ý×§ß©¼×ïk~çÅÌ ¢éŽŸ¶ýó |xeJ»íÿ¨>%µåá„h,Õ3óíèw-¼ Bk­Uˆ@”æz™–eíTn¨BF^_0ÍU“ÈX•í–Ž›ýúJ›– ¯ƒšày¦ðÚ±ºvËg-C‡O¥V¦ãµP;¤å¾Ãõæ:^•þú±5m³A¤K™N¯hc)À @Æ®¸Þiû®g€”Êôó3ÚŠ½ØZ€L½~p*MN!µê"Úµ’ÚÚ1­«ö‘ȧϳbÒì… Œn(°Þ1 ÂÈË^h sx0ÈBŸHÔ癜÷ªäwÜÏkÓì_Mè ŒŸÐ ùåÈc%©k?žæ%ž;Eî[½ë¾*´]Åm$;&¹"cuç9Q®¬fEÁÏ™8‘G¾2õe-ZË—av“ÉÜ¡v|Þˆ"™kD ‘!Ü5ÐO“þQ[*dþ‹Ù¤îRôøÅlš2ô3Åôß# Óå݆;àÝDw›dKÕ§c:¼Û¸±åÝ&‘™›§f{·Iä ³IWyÇl‚wé–Ù/)€ÏS/óNãXéÌ(ðp±à2n"C¸x+‘Ó^/]/§kö0b'ÛÂcZ˼…ìÎÛn™™´ùtžVNP%—£ÉP,íLoE©+€ì -݈ÌüÙØæ×¯\FÑ>qwÖ÷¶é/>ºî(6¼bÈmym{ Ny1ýÜp§åŹäÅ;Îz›¢³§%Efí1D0¥¤)³]¥î½dxJ9”¾ÍS½Ï DF7¾u-@Æþ÷óÐç™üx? oÞOó4“û÷ÓìxGÉíûÙïDúßÏÃ+ºy?WˆÌ@Ú—”µônÓƒXNJä(æm:ÞP|õÝ[€ Ý[0ˆþŸ!ÒŸöe}qé}Ú—Ù"Òû´/t:f ê +í ¡^;¨˜$ñŽ"Ëuí› Ýi_#9+æ´Dæ>ça66ŒÓ•ÓIÕª˜¢ì¦¶²|ï)òy›41a3wÝ;Òú‚dè÷C®2~Üø?r_E„”B X‡3­Â ƒ5þU0‘}þ Ç6è-%Ë¿J'Ü+O`F¦Û‡T"C§ƒv]û¤7uâÐën½/Ç„'ýuÄw‚–c²ž{ù„7´²å4A»\ŽÅæ,ð.âÄ#ãbaå^›:(N|2.<çä N¼¬q²ÌvdçÖŸê €:(N<2.Î…±\Ž%ʸT¿ œ“%2sÕAäÀ¥UʼnOÆÅ™8¯(üe²²àvJµ4§&–óY†úµ}:€„|­»XK€Ä'~¶Îù²•¶ùóQÌÐÀòÙbH‘ÇÁ‘˜Zi&c`ùlq/4–¬‘d›Ð"S¯T¹<àe^©òW÷¦–ÏÛ |•e!VÚŽcÝQÑOz«=Îüžê ª_x:R'Š~á_ï݈5Z"#ã1U—BX€<Ôm»ëú3¾Ê`UÖóþ%,¿Œd¢–Dß–~`x)WB‡P‘©à豕–ÏG:,!–?Ï33Vo¹"2½É±×õaÎóùÃ%Q¯ÝÆù—D=oÚF8N—D4¤ß%Ïð˜±Ç;˜y¿«+JþñäIpËO49Ax*.Ei¼ýGý=T„­B†×Ü,sCJu—’èn›ŸI®Z€ }:"‹6‘Ä7½þlR´(2¹ïõÍ>g’\’ã*í¬ :¾$õª×ìø’ÔSQ³¹t|&µÜÁó_’þèøô_’þèø&øëŽŠšY¦€Ž/IME}&Èõß/Ñ A’Æ%GJJ7MÙô6œe„ríÐûݽ!2òîèŒØÂ_-c™ºRÆ2]7¢Z÷IvÊÆ*¥qGÿÁ¸ßÙâ.ýöhBãGÇ%ZÕ͂ǔ9ÜŠGÉΓ~PÞá1Å. Û°æ ôµ`*½:!Íð˜¹+§’%­Ã¬˜¡–]Œµj…²^ôþ£msN lÕ éçž;æ£ZçiÓ É=f Ù­¯däu¦ c¯ÛèǼó]¬KSˆž Ç·6ÞOAjIÄÕC?Ó‚¥5fo±‹Ñ&Q2«qAí!µ~K"£«G1jFã%‘ñÉÌI:4í}óék€¶OÊ¿LÅ»ùðŠRwF'ã¶ëu†4ðÏ2ŒByh®Ž1–9)½˜Ù[Ë2ôä‚!ãÁ¤vBg¬—¥¨½éY’e/U'§ñÍyÒ ›+òg ²m“R¤©·;I¦ºVL3W4–I¦'¤+u”éxºm3Ïýy¹vÌ£¦Še¬1ê0@†$˱ÈÜwL‰<Ô—]Ó#à§W²àǧW²àǧçÍ,¸Ÿã̪QüX5ÒµwöcUS;YðcŽ[áµó9nÿûŸ\-T8ó§©Ì1ÃKý)y9¸£½yë¹#‹ÎêF¥èý¬–Euv*.«~Ù1ÅZîÖÓù£Hçý¤"Z…)‘±+5DèÌôû™Å7™æ¶÷v%w®ç–÷v%ÞlÖ˜§Yz³l›§Ùmîçal ÛkÀ‘¿c#Ÿ>_¦Óµ|‚,¿SãY¾A–{|ÒöÈÈ3.Yñ/ð†õHû|XÚ5¥ß’Ùû·C¦ã{Z+Q©L.8r>!ÃkwFGEÖéL€àätÀÕ̬üã»ô9Ušºú¼’êk¬+–šÎ-@Ú_‡ê éw„ñ6éUb—Óe}zhÝ^ðŒf|ÑZÉ‘ŽÞd1cò3¾™ y"›ëž·3µõÚÚÓo˜Ò"Nþ×W”Ýôqû›‘á™Ýô\ÇaÕ –Šý¬8ß)YðÌï”^–)YðÌïÌ\Ùj˜ºöüñÃ?@_‘­8¿¬×YéÒÜ`&]Z!C_bµE©ÏÛì ÉCŸ4†g[[Ò˜<¼ftj  ÔçÑ-Æ¢ÔçÑDÁä¹Sdì­‚f;Ï]!ë4†¾Ÿ3“Æè*=O|ÒÜöEYšÎä½i ë"éŠ!2r­r0iÌnª‹<±T¶{ãé?xž‰²˜ãÙëµÊ^_Ú½9!Ó«Pÿ)Ñ0ôí ™ÙvB¢^b¹ó{_˜Û<1Ö?ÀNˆñ)¸¼v§õ)º²F <¦”Æüc7œ-fׂôÇ)¡[psà©›à œÛ´h)‰õ!ß bô]Ì2užÞÆp›xª Ïn6qÀv;½±)ѹÓ ›­#:÷”‹zù7z–­ØP¿3yékÏo͘¼Ð\{î]Ücœ†Y—7áã}Ћ²Ba¶yŒE¡–/ÂÇã´¤\ŠÝH.Oß:¤-ÂÇã…Á˜¾œ^ï]õý¨‚M"-'@éiC{8ü™x†Ã_*E˜Øâ<*$R8+î"–WÙ0 *ÒæP™¹-.j¤C«òéSí!­› m1÷y#˜MÇÓ¾dh…©ò… mµLG Rú"ñ¸lZÈ.‘{—ðØŽ‡¾¢Ð„]KÇWÛ"|„Ž¥å K ¦/þdä ­6VJ¡%?ÙMd˜–±ZZ€ ¯¶G|p7¶GéQ£±¼…¿«)IR&UÛE Ksç­¥†ÿl$Ï^þ -yúu£'ª-“<ÝòÖf›Œ–·vøHxkã o¼µ§ o¼µOÈom<¤Ã[›ÆÀ[;|XÄ=è7K‡OÛ‰:´•ÔÀ‰šŽÆÀ‰:´‘ONÔS œ¨ÃGöÉZµ±¡¥¤v;QŸ‰3 ЙÃÇÓ;z@g–H×¼9°­ÚÁÍ`[Ÿm¸ØÛúá#÷¼ŸBWi¶õÃGî5€aƇVŸ„ÁãÖ¸‚Òýë¼IÑ£·¥Îv‹ÓÁ^ŸAp,¾³ ¸ #O\8­™:øë§ñSR–¢« å]vIÿGÒÌdØ.¦sìx캴Ätø<æÑœ§UÒŸ´Ä;ÑØ©åÊЭv,t`]±„Aä .ãôË; ~ù`ëw>øåƒ­ßùÿv%K®â@ð—Œd¶ã»OGÌ|›Á`ËŒ!Þ×$D© $º}Ê`3Hµefð›6¬!Áo:Ø;dèKtïçòr€((Od‡0Ñщ¶6&:° "Z ä3}Ó¿^/û|îu@´º}ñ®ÄÅT¿¢«¶E®y¾C2§WzSƒMc9µ;x¥/°%YÁ¶Œ˜;’gïÚûý ¿¢—™z¥·Ú+=§ÇŒp(bøRŠwØ}±ÕkŠL=³s™­ç3ô¬?¨g͈õ®g]“À’LæzÖÛ³6È“žµ½£…‹‡`µY&(È i×1›òä´cÕOÏœ¥•~í@̳u6ý¿ûõòËÖ á â8•­íSB¼*³‹ ñ¨f¶oò•Ü‘¢xC±Ô;í߬l×VÚëÕk &È »†'Å<ÀÐ ?þV55~ÛÌÕ¡_ ÅR¬ÀÍs׆եK¤ÀÍ®ñɬ¼Ÿç§%Hî+æ÷6‘¼ÆÇ9-9-ôÜ»cVaMöå÷®™wA²]~3¹ë_}×$÷·'`ý¼&ÞõS&IÚZš CK®WÚ‹2Gk 2ÚÍ‹®wôø ¯a(’²H·25Q½7Èä8YªŸ|=w#E¦®5¹•›ñ\/ô:w,Rëð×gó°ƒ~þìÆ×ô7þYG^þ™XìéSÿ¬ÙñÏØ5õòÏ”ªàü3ƒtðÏÚÿÌ Ïøgô:ýü³f㟤‡Ö"þ™A¦¾)?ËXbÈÎö8å×ÔcµCžDvÔ‡ÁnNÅk}Q ¶Cˆl]ñšM’Â¥Ñþ;Da¬Êa@Ò¾c¼¶C†¤€±*V+• ù«/ôì4²³,ÒN®7€dÇÉÁ /zQ€HsqÀTóù~>ßô˜žtY˜•0È«oGB»qÈýMãQi:@™[ù’,¡•ñQo?xd‘êDæ5 |)h˜·SùùÚ&gxˆÂ¶øWq\òqÎ[‚tË9öY÷í 5O£0y±E‚öÚÊÚy × sô¹ä]-¿^SS¿ ùÉÐý:qÛr©÷rïkQ,ô˜à³ŽyH]YÝ hŽþÅCªÔ¬ýz?§g^Ï }J©§ © lpïÇv}}ßÊ<­Œk¸£ôXŠ[…Ìš¹W".Ð «w³Ù®6eßõïŒ ¹G¤±ÎG,ºxù‘ÆQh»w<÷ív¢È3G!Šô; È<¢Àë(ô$ŽBº¼Uâ­ÂÐ|ºÇÜ}‹YÐÔ¹ÇÜ]䙹û@gæî-Až™»w:"^È'Ð~`µAÓñÇÑ(7;¤[‚zV»6|›ÈΔîÚ«5©ˆ¨Á1´÷þ’Gf‚ OòÈ…"ýyd?г»­ëÖHŽy"~‹(Òéƒ2³@ãQìhŸr?¾íÎñ¥öÆ"¯†¶a´^ Ù™þùQë'ðQÆç»B¼¶· ¿Õè1ÛàÏÚÂÚŽÙgŸâµ@¥»æ!A~%R$ðfP±¶ËÄûU¤‹ÒCÕ #Ÿ{dèe‘ö=½£ÈÉ Uåçç6SÌâ‹xMåÅ Hæ2øªXkyâ q ÁÅÚþS5mYÇ—£6 ¬ÞX !öÆq UMñÛ; ΧP;ˆ‚{ÃÕ²ìL¶cE ™!V´¬ˆ] RÍB¶rU†÷Ó²" Pm²íqŸç4Ù{ç¾ë”k—jµA<Ÿ4‘‡€Å¡¿-¦Z— <Áâè—½âº8öj´ÄrÖ ™_³i³œ5H~¢ÙÔäÕ¯Ù´YÎdx¢ÙD¯3rk6aËYƒŒ=šMÈrÖ ¯dóä‰ålOÏ~f9»‡G£eý.#µFØ#Ø.]!±]ºAz’Ø.Ý OìÒ¡9'¿Ø¥Ãj'¿˜‹ÃDœžš‹Ë ±#HvR·ÚîÝå½IëV‚ ™«— ~!ÔKH..G͵ÊB4Í òêê%tDQÍ C_- õ’Ë~ÐmW ƒˆ)¹üR·ºQdâê%tD'Í ÏêVôŽNëV;hptíSóùUõ}À»œžõNåœKþµ¹GB3 tO2UÙiÞ¤g¤D4Ó³û²ÓÖÚ¤#;}¬Ù©­È$/;–‡ÜjDCéÌNs•‚b•AšìTç &;²göÌÛ±§ÇL]C\-íZΔ»×Ùc2ÏÞ©Ä£xO°+$>¦‰ª½c¦ Køéˆ£ešäúË 5ƒv†]U=Ç,¶ˆ]¥=¯ÊªØb¦JÌÝ·´w„m3~þ]‡ó ƒã%Ö „Y7Ñ#R.6ÊÛ… ù®G`†Ÿ1û%Ñq¥‡ßè.÷ÃûL¾ê¯Ìöé1¹‹E«µ× ¨ç'±¿Û¥Y´'$1K³,Z±²hÑSŠ©O¦.ª9þö¾ KÞõCN×#ß¶½¾mK!r]ÒAC­}Þšl¾Aß!‰½Ì\­ç6O3Ab=·j«PÏó&,‚%ÉB&ˆ/&‰×¢HÅô‹€A’ž¨ŠaM3–úšË,Þ€H5eã ;ÐÎTx½aÚ™J¯7ìL¼aYê¯ÝÌÄ–¥WÁFСԡôxÛØ”³è xòÐ;x„B¬œòÓ+ê3¦×sûyÛ5F´£ý|¦F‰(ÒŒËL²*Ì"ï½Ta ¬É–ƒæ¶uÿ2–†ÄaÚŽ«¡ÍÇk~|¶è¦EŠdRØß(B&VI!åï j3é?nû:«ìi䯞†&C$,÷8"Äô©K-²)ä&Ê0ajg¶%ˆ›(KïX¯hè;Ÿœ¼óØM”¥ ™@8hF§%Ct-E!Ú€cV×5LJ`º–%;¬_DzL)Ò£.Õ7ra g÷óAó„a—NŸñÓг{ùŒS»;fŒûRæŽFqï† Ä™ué´ãˆ˜ù8Ø÷ºwNæcŸíž’KûÙñ_êéï“ŸÏØt ý•Ç„§%žürùe³§È“ Ïíuâ—Ë/ž;äÉ„ç– òËÅ3K¿~Èv–žŸ˜”¶d–žc“R¹0æÀZú4E™¶ÈÅ‘I©*DZäòʧ¸MÛ‹Ç‘Ié2h×Ïùý6‹OO‘غYï±*á]½Ì[a !9^åõ1§y!ÆswÌÐ.àz¥¯ÕÙ§©ä A¹Æ?f2WÌ/§¡2š+æîe¼¶Dî†_®®MvãßµáŽÂs#nÑ É|Ri}×ÂÙs N(j‘‹¼ÞGQö¦Ù¶9‘ßÚüEÌ5ž$·$y™cN æŒGž:%¿»Gž¤û9|GçÌÜ—È[‚dîÔ\7Æè1¹ŸÃ;S¤³1vW±r[˜ 7Ænõ݌ӨX¨-àwÇ%?À•Ó%ï¾|Ub$H÷@I¦‚äþät+×rËó¤œð.Y¾˜ñ¤ÈûÉýü¸Î 8ÊO  ޏ]i’S‰¡,ÀF[hÅ6"£¦Ä¿ã %á]°Í<š²,ÅwÞ!¯[Фâo«ÿ•Èš-E2È!å멉ÖEÓ_™øQd„š›Ÿ¦˜‡ï2ÎôŽboCô «wÀiËgßæ„$…['SW›óUçð&#'SškÖ’žO¸£ëÁÌ!ûÇóµ}GAè¾KÓÕÓ“ bZø±§yyØÓZ ±§yàKö5±§9rÓt¹ ‹r†'ÿ‹Ë0p¦xŸ¶xçÆ¾É¿¸ g³ È«_&Î~q‰G&N™8ûÖ%'{–žãAz.=׌éÛÉì¨gþQ‰™î,876‡QaÎü£3ÝØiº·œç;£¡ÈÐY€°/,gìÄV _XŽøbn_ØœÓï Ûvô˜WúAy tpí¾Y¾€úÇ,0"J©÷#dÅ‘…ŽÓ¸ $… ’yí˜`Ò ùQ¢YŸÙ1q9V°û6—• šÊ±-ËæR9ŽlyT¤šCŽð‘×Xˆ¢·wù”"VÑ¿og§:*Ô+\µx!VdÉYü)l£‘³ô$þTï¼}C|bPjà »&sþ‹H8rl¡³Wó(ï Æ8?QóPMc(tpìʪ–/&o{|U°ZÓ’Ôʲz7|gý¸@ÂÉw6.y¡+òyŸÆšÛ¸èÞems3dùr‹Ù¸±²z-³h¹ï×Í®ŠÖÆš#ëì‰<ûSvÇL6–÷N-axe;dêäµ)Á•lwGk;v¯=WÖYW»ÇN%•¾½Ëþ¨ S­×*ýTLU÷ê^»ŸiuþkFZ¶²]vŸ†á¹‡^QxeL–›BäùðÉïw Z.rŸÕFñû£F®ÊÄ»Zʦ]v¯iŒ¸uç¸éóaX€œ±AŸ²œüœÊü•íZ·záüHÎå‡Hp4Ãý½Œ÷mV›ó«o1QcÄ‹á/Îÿ[g´½®ž=B >ÇþfvVÆL-¯å[$r"V0ÍÊ yt¢ž7ecαL ™Ù½­ê˜5E^=Ëc¶ eç|!µ¬FΓ߼Ýà˜éoÞnyæí&òÌÛ"ÞníÎÛÍ C'’x»däÖ ÃzÅüz9«nòm"“#æ” óÊüÊNÙX¶›Ã¯üÜ¡¦Ùf8ö4ùÇʹ¬l,ù-5Íä\¯i ÚDcÃÔTY{§HF‹-f¶xÌÛa¸} ’c`3A(ÿ‹ù+_¼ ‰æÔ·ÞÜÍT¶3¹ÓµKFn6%zŽžRäñ#ßEU½D÷ ’9§ >Uõ}nüzÒëT«ÌÆqì‚¡ÝfuXßQ¿ÔB'ˆc í|^ËÐeí£õýw]AÏîž.xÖm3̉Œ¬•è¸7ûˆ.»ß[‚Œ Z®êê¦$µ4ý· EÆ>†€°©ßõŒÿ¸È¥±k ’1¶ú=·EW6iÅ£²¹iæ:oe {²å‚©“Ë€y*éÅ2õ]sÁé¤ÒªÞ©ÿ‹«_åÜ ~MÏÒI$ÃO5p“‡‡ÔÏ:(×02k«o‰kÙ‰v ã!ûÅ5¬§È×0xò!ûÅ5lwÌÈ5ÿ=×0ƒt°¶»†¤ƒµ%‘Ä5Ì ,fã½² H ä4P—©‘QÉ'%¿ÃŸUÅó‘ŽØ;НÜy6•ì²{É¿<¥h¯\Å`¹2܆—-…áwåÕvCËR–j?ìé1A²¬ç‚f,ï÷ïœíW„ׄwƒõâÈä‚ÊÌ/‡YmŽYF2\ÞJRºÇýù4õ£ÚRéNŠ£¹#ùv”ÓÓܺKlÆr ««ñ1ÏókÙ!m¢or5ö™u?!¬Q©\­óòä÷5ý¦z_ã­#È~£B›©{—©´xÕuI‘ì›Å ª¦>€ †AB¢T”Ú~õEª¿·áV¶™¬¿æ?†×§w™aÊîcN¼™º¤êžJª®Zè1ÍܪþTô«7zšêúÛNô ptú¥?O%t*“ QŒÊ0TïÛZú{z—2r PN¡ @³öKÑ€ŒkØ¢ Ùý“»£†x%/Œ¬«>ÙRPh´ƒ®¬»š~÷bÚm6ïi-¦÷Øïžkb»~ÕF˜”Ïuª«iÞAÓÕïJîÊkÕEýZÝôPª†O eú×ú+_Uuwí*//@LU5¶ô'`‚þ˜|Xîó~;(#Ðûª9µ”Ýý>ÞvÀЇ„Ê…B¯ª'qtО½§²jé'ÀB½›çÚ-ÏîSÝÆ…FºV $T>Ø4·6hŒ¡ÍÖñŸä€¨æ]·“•\ áô:~ šnŽ=ëûjžëmz/ß®¦+ž#KÐjx[]k}_žeÙ}Çn÷¸ž#øO½Ú¥ NänÚ/w6¿vGe^›V[{ÃBšX÷‚&ÖÑÅ›X+‚Jë£à„⪨Ž\FìòlÖ…}6Êïzû°#T¥½‹¾ý|>EÙR¤S R9¾Í`øÆÎò<Šô‡<Ù6hÃ-Îò4»cFÇ~ˆÒURLHGVdL¬xV2—D>Ÿï7¤w+ÒIToçvž%” S'‰/ÃÃÎ<ºÒÀZ%‘×ùÑa~"+ÑýjÇÈZž[ºŸ³æjuéxzä—ä«R…þa=b)À£èl6 xðèlèU¦86!À;jÀJn§«ge9?Þå-¢Ç;k·ÜLfjÑvÓÁQ””Q"Õ¹¦Mß÷PÜíwtO´Ëu}¯ºç¬ìzLž¬VòŽŸ){ó²»Î%m@y«Ç¶kíìLdÓïÏFãp-¤ªŠ|–uô˜‰7iëz©oäö%ì½§ƒ5ï ôq!ܳÄ@—%`– èFéé ÉñørJÑêíwŽÒ‹Yii‘†ÙH‘¦´H3O‘F­ó¤HÓôN;·¾MÖvÅh+è1?ŒÃoµîJÌmnWEDŽ[ßù­4XÎÍ»žÏ/Eš@[ÅO›ä˜Òs•™XoHL Ëë\Û†ìÚêþ¥HK­ÐsæìåwâMϾ굯‚gfTPiÄ6sùÝÝûJ­ÐÑciÊ99=¿9Äv¥ý!éˆ"„*}Ú…^g =ØeÞ]3¼æºêéu®öú}ŸÝA'…1ÃT‚äu¸í©ZvÛ㱿±9·=ƒtpÉ4¹íä‰ÛÞBÏ~â¶‘slz x xž;¹ÙöZ‘×=Ð|YÞ÷9³¯}¼¯ˆãëÖ”ö“‰X©Ò9Y_{%²ø¨*˜wæqLظHE"Çé3<è1Ýb¥Š6ÐÀxWœü¢4[gœžÕ¨O.'ݬÑÅ1CË5ÿ€6TÂN&╊ HhSë9b3qœçÝK€ëOa0î$3MïRB‡4ñó»-‡e ½SövÔ%AÕ¬yM®6%Åév÷{$3{™³v™¬c)+«ÆÔ?ºwWgï¶¡ÇLíhÛö~*»»FȘ铿xm@íÎm [‡³)ûv÷œæÉT¼Oøµ¥G­­äz2ƒ­xžXÉa+$ž„^úL¬8"i9HÚ“'‘Wp®Õ‚so8f|BZT­Y$ó5ôy&>£°qÉZÑ.Ïmj,I}¤£VÞzA>Ÿ¤;Ðý1'cÆÎÓËù1âÀ1ýÈQ·:Ê<=›©TtˆSFÚ¹Y ÙÇ{zß²ˆ5§„¾ßݽ^F¾tШÂKu©ï6›dDdñ ”;×1ÅÆXzWÁÕÙQö‘¶<ò3Wò»5uàˆ'vTFid6m¯Ô7@¿¬L àÂ1OŒ*¸4QpáÈ«Œ*¸(k¬àÂÓðD3I%ò°ˆbžØÞSmÄžj<üžjì©Æ‰±ÖÁS­±žjeèþVË÷6ä-½£>e=>u_;7y›¢£ÇLQ÷xM2²¬Eþ¤Ç4uyý-©ô¦¿¥ú“?äk²ƒÂÒœëÐEö£*á÷7AÏ8‚,MÖz  CoPîò”»w¯õ”Û Wµj¤¦r4tZÅu Jè/å`*«åm­â6hìÜrdö»ØnuŸ˜4½µWà.Fáÿ„]ɲ«¸²ý%$ckþ*¢î'€ida°EcçëŸ"• ˆ±÷l½Õd®èÜXEE!öw]ÒɽŠ6>RBpöw÷`Ò¨&þ®1Vn _1R|WäãÈ{ÎíÚ.û­‚v¹ìy/·¾Ÿ¦ÌÌAFÔuÅ9"Õé4dpž”X'{v¹†Ž­L`Â.Ñ)?¤îjIõ\YEC¯¬åÓŠŒÚXK¯m¾WKT^*ÚgÚ?;IN^´¼÷rÍò6#ž(×ñ‰áp±?Û¶éù½-»°3;ðäRváDj5ûº“õØú³sÄòšÇQQ,’^ÝOOª!ÈxïÝ9 w'ÃÂ.âÝ9ÿŽw'»ÜN2±w'»ÜN~Ø»“]0¿î(VCÃÛL¶Þ^öØÊá IvIöÞ®YÔ™Õp qì’ìÄM”&-àÞ÷N?ΩØîç'ýü¾Vd¸$Ú’°!†¶UÉ0†°ëeÓUÏA¶Óåî  ÀpÀÖ¿K¯²š¿\ÛÖy“¤w¡-–––YbŠîÝvÝøN 2FŸª\>iÕÿ2ø>¯×­ã¡c ý>?=8o8$´jìÙ]µ-ïRYõ½ç·¤êÌüØeJd]õgáÝ Ò¡Ê€|ëw‚\Ì ú"-~¾šà¨SïSE1Tè1ÝŠ`¦¡ì¾› ½^=ïÄegv Õº”±þ8­ÜÚýô0Ž#}PËŠà÷¿¹$ìVöÝwfϰyO„Òl?Ñjn¿k™¥ý0P(Gm­eA0C«Oñùn óŠàϲky-Õ -K™•O MŽ¥É8Šá(6µjç:µ:Áˆƒb½¤@ÃSeÁ&”yTiZ÷AFoaåelGsœ¹0/]yXô`[´À‰c×[ØiiúÀï)ù›ÐGä™Ð‡"O„>0Ï_krÃÌÊ 3‹]Cþºs^ò×e׿îÜJFþºìò×µ#.ö×uÈ8ë·îÄú‰î³®Ù™;ŠõŸæy2vìÌ©y :Eë¯Ù4kK‘á@°5"òåÖ¶BeÕ³¢Èèh=Ò™°†–7‹"â 4ï‚V‰ª:©à ‰"ê „e1if¡ ’ï¹¥V@#E-7ÈÛA›RN¹ê*Ø+:d$0ô0F%0H‚ z¨P°(>wÚ Š ;íÁ!ÃNûbsÌ3½£C®2H`@`pÈÇQЫl³¾ÖŸÉŽJe#\EJÑ!¦±d5dhO›QIÃÂOÚÓÖÛìÕd¸=-ýóäAA¼&N§ÌKN§þ÷~ ºµIâtÊ¢Ûɘl YþÞ“@þ‰e¦,ëüÙöÇ•KFêU_tSAõ讜G7F;d|T™Òƒù®ÁÅE'ÁVø)ü=‘Úf]o#µÅ昮£·¦!8`«˜Jý½?Ârg’fÃP ýê&çC×__ÝMÍû ¿÷£Ô2o¿‘¦`»ÂâkÀ©nñõNu,ŽNu³')rªsÈx9Õ9dJšò~Ú,ŽÑ‹6!ÇZ¤ €d§q÷¾aÁb”z·Ä ŒÅ©d›ç_‚t4—<±ð‰Ç>5; žó¾6A²¼ZEöÐVäîq4ÉgC³š!8æcSkY `fÒ–µ÷¸b;E]% —Ò"ŠNÿTÙdôQK$†5mG>êv“ìrE†}Ô[Øs³Ë¹úIºí0Ò¦Ÿºœ6g¿ÚZ¼‡¡}Ã;bWbÔᲞæur­Ô¯ý•š £}‚Ó¼ïx>»gGqÀ*C´ëá®WñŸëUÌ» Û«øLùçK~¥ZÌÉR³)Õi¥èu"ר¢X–,ïÑükÙÁn‚ùÊÄŸ9ñçéÆd;™ÍŒ‚ó®±ÿXZ×ÜÕ°wd.85 ;ÑÓc>‚&h~c¾2q´ÙFñ'ì@ ‰¸¡Â÷\Hn‚d>U> ˜aäÚv›—ªsßó÷[Å¡Œ4èæáÆ"f¯+‚<ŠÀS­ùHêÞ"Œ8Gy)Û û˜ÁÛvŒlbí¥pLµªlëaÊà˜Ô/.ÜRä#àS'³VÂò8ó©“¥l?ð©ÃîsŒ=N|ê°£c Éª-N@¼c<Ìr–O[.„2±Ò­©Ð$J’ñ(dÉ/:%ÉxŠ’´mA%ÉP`õÓ³Û %Ép`±Ï7×I¢$™±n£$EG¢$™±n£$ GI2/bÝXòÏäH%ɼˆu·Ñ$J’!+µä·>%¹>ùK 7†¢$Wè‰%?Œa8ØîÀ’¿+‡<±ä‡å7O-ùÑ⊣×>®ôFûÉ÷…Mó-sõküÛ§f†·s¬¤HhŽ=]o}÷|Ö 9uH?Ç¢ZŠ·™ºäÛ.ŽÖ´Ú™1 8På,\ج¥Ê:¿9Cöºv¡¾&dYËî»A&3g»”@7×y?",Øíöà·Û<±+\ ­ï!Ÿ<×­`YË÷»@n·‹ÑÊ•<Ù7Ë1•Ô*«´¿£d9íXÈ^Âj‘‡ƒo¬[›§s1ž¦½–›½â>Z¥‚ 9*§W®œ.Úæõë{¿9 ¾ÙPĺFõeÙÓ{OŽ(b­Ùï{Šó†»0n32%ÛñÂtÚIL¿NçÉÁxƒ è„”ôÑ_¯¡ˆ36Åøý¤†£²¿Ù¦..î)D™ƒŒ0ý墿Ì!5˜þr Ñ_là¡¿ÜöN£þ:gUœý¶q!„v;ˆEõ$ L¹Å'süLZ_Rn5y­ÕäE8»±ß¥Ó¡i‡õ­ïݤÌJ¨,Ÿ5<Ïá‹p–æy*³íj¹›gæRÜì¸Ê›rKëÈ”v0'Ü<áp‰w+ 7.–jh²ß F‘Û-l;B"aÙmþ-ÖÕßü~²X¿ÏÛÞaÝ#5Ó(| "»="•W7¦J‹¼¥È‘øÜ:¬­§ú›çm% 2> ømÓ²U¦ ’9K%Ü1«q(¦ƒãòþüÏ¥ˆ5(¥|©ÃÇåyYùŠüšÕDœ9drô”Ô4Žè)%ûbØ2ªn/Ýù½ÖsOI8ÞòT›ÍTÖRäa`²ÙL•#ÄÞ°¹¨ëíSÊš¡èuº§äüªÕ oÕ£rrñÒ“õy®o³kÇô9PdBÅÿÕú<-S§#Èûñ,‡ÙI &€ì$P“@–œØlâ_…yÝäa[¿„ßÏ`Ýäf\²QOýIâÀøi[mfüKâ«Õ™}J3?Ò&ÁU­’V½6IzL¶§åÉ9JgÔŠ“ïrÚfÈÉEG±7¶ÅÚë_ÝÔ™‡™+fÎ’°éž\ŒçàŽø©ŽÇûÛ²ävBM#ó{r ÄÀÁžÉßöœ-AÄÀ™c’8†ÃI œçI K‚¾ðJ’8†Âö±>Ž¡ðÃã}¬Ôy²ç,)ò(NIÇ’äo{NzG§{Î ôhfîž´ö‘Ä‘¶öíAIk…î $ik?A´ê}ðù¢`]‹ƒ ƒo  Ÿ<‚©*UyZXò8sïO'¿£¸_víŽzb7ˆÈ“Ÿ!)æ¶%)‰'?Ãay;q öäg÷kÐÁaY-B ƯaTFòN+ú9:Ü’Ù‰nP‡p†ÂÝÂ}kÿÎþ2'Lð”ø_樂"…áñœãÍŸÏ yqÈàœðÖŠ^gxNðô ;ÿËœ0Òc&Ç!_„Z|?¿qŒ'»ßþBp„ùðžœ%4Y7šÉmj"'áȶ ¥\ª××+6ÙýqR¿°ŠM #Þ'ÁaB Êæãi/®ã°¶z\jÅn¤ïei­áWä^òP­A¯ÓWWŸJ䎈éìñéqè¸.Vºªèá!%äᩘ(’‡«<ð;zœüÞ­ÜÃ6H`wô…ÔÝOäæ÷îöå}^Wy±ÎLá"”MÛ雦¿NDá¢Â3v¶S÷YF–â‘aî ¦Ÿè,XŠwXÓ†ºêãü>õœüâ¿%Oöúgޣ䅋„í»i*D3/†²9šÈ¹Ã"Ÿe1üZ‚Œ0R8‰›=æwzÕC#Ü’^‹-•½™;òA2ð"ZÃW›!¾ÒéDÏÎWêÉJ(YήT—Aýàá­Pÿù³Ü{ wT—¯oK™à ì²çSJY§`güHˆª6³$•y·ëBUZýjú<G]9M‚Ùã òØš d^2 „U˜—Œm, ,2/[„•öÉ‹•PbþòŒ`¾ÒðÏLá*ÜŒ0#s©6È(dœ¡“}ÝìØ’-,»å˜Í§ÿµyKl¥òX ìrvk™ÒŽŸvÆ(„Îy»àíÒy“}èÙ¿˜¹z‘¯fY¾ù¥w´Ø7è¥"R¬2ŸT|¿ÿ=üÚWŸm“çøårF…,…AFûº‘EÚºÑú‹ãÖ­û3~¹’î¶•Ê9’µ¨…ªO5ÁÙ£¿X«øcžTI‚¿°ƒ@iVf`,á˜Øì?j1j–`>Yƒ_x8¥Ec¯~¹õ'l0(œ}_±[C{5‰gç—P<»Eâxv~¹ŸXêàxv~ù[<ûÔäI<» gç4ÕCטcqÙ>-•[döðZ«éüH†Fbs×U:¿^ÂDÌzJ}'š_¯'fø2Ãç×(l”óL…§–òkˆqd~ïæŠûbƒ$–ìËÛTª-¦´ø¥¯Évû¸R²“¿¬&HÈ=L!ÍP¾ÌÚ>}WÁ!cŸ;tÀ.íû_24‡dˆj¶ê²‡I>µ·ªqH³ dÄŒõ8½>ŸbëòæW€+rx¦ÅÕÈ2 ¼#älÂqÆÖa2¦ò·¿ˆ4•$È‘æLyG"MŽ“³Ö‘ìšÊ,já«KB,;‚õæk&Èh]Í>k‹Á~?uÏqx5ð<ï›ø‰•®ú­»·Î­ÿ AF„V;¯¬ RÙâwQ¤wd3Ï=_F›·HµÒN$ò,]?2×J×ÏþÓk‚äÞäÀ½!{GU›é~s̲C(ª¥{Ö› IëgM™ ¨ˆr]æM%]C‘t 6/@‡¶1+'ú1Ä[ÿ»®i1x÷iýê;úä/ë¢!›ËþÕ’2}Êj| zÖ‰†»ü­ÝdÎ ó÷ôØU!7=kzÌmrY‰z¥Cò`w»ÚóFðœ Ê<(óöS‚LŽSËpmÑ!O:Ñ¥&ȳN4}J§hzK×¹õLºGrk]‚©Tº×='$ªÛ÷¬'³›YwÑ¥»­!+E§æmÞ——Gñ©%½‚|J±³rðå?­Äù: GR¤Ãp`¬ò(\2_ª‰ð( ÏÜP ’k2 Sõ5ÝÏì?RÏàQ8SPWØû“G³*äô‚z?I#³õ  zëüD Ô‡T~"ÒÄ!•Ÿˆ4qHå8cl+J„YŠÁ,ëÅ@+Ò­Þm3v)Vd´—¤¿»¾iûú%4Aâp¹ž=›ªO™ÃŒ#{¿gaĺOøÌ"kµ¹N¾G6]ž¦U¯6×yƒU5ô—‡¾2[^³ù¡gO¼¡çZÑÎ?ýôëЕsÈû)ú¾±žC›ë|€M&2ÔlÍÚ› ®Oþ‚u—.5¬ïTõ}©œÞ’óåòÐee«ôûõUO ôå,™UŸæ¹ª(4¦ÂÏu…õNŸêÝS(êƒ%¡&ošbxþ²ÍËwAÖ ©„´Â1/›/±¹-§ä5“Ýsq}²š \˜-]“nŽš ( ¢…ß°z‰ã­ŒdårYd­Ç<%HºšûövÔwe ³]Lë–®ç¶dF>GR´­Ô\¦£ªFQdêÊúdCŽDk[##¹ÁuÞ‚FFr12’óÄ äqتÅñ5A²£Î l?úWUðé%$"wecã¯÷— #¦ïÝ|!?`æ9d 5±|)ó™;êmyâ3­ò6‡d~Ì[;/Sÿz«Îüî[‚ä1ÝËÆp ~lNШóÎ@ìºïï÷)6Èd­_eà±7tã4–¹¯xÄ´n¹ql” á8Œ;BúÊLü8H.™(J\åXŠv8‡ÀïÇ«Î!0:²ë_æø’Ùõ/s 8H¸u<‡l®ódÙ\çɲ9ûɲ9æÉ³næÍÙæ;„“9„]Csˆ…’9„]CsÈì„çv Í!JævýÛ²yùgsÈæ©Í!f¿Dçæ-eŽM¤!G—³(l"-fiIQÀlLUÖÍ,&•¹Ù˜èŸ]KQØllÒ‡ÍÆÜ#F3a±˜õ؈›<¬]3sYdªVd´ï}Ù³wÒë98Šܨ4”YÕmý¤Èiç¬LBŠ ‡ŒC½i+v#¦Ü4ÅwJk?âz¥×‘©è €ÀO•^æô5ŒÍì~)‰LÎ9{{Ýš¸s~9é%bwb‡$×Y­|\õÊ_íg}òüzxÌÌó’"OïðäytP=Åœ*¨žòk&©‚jô‰>E’duŽô)ÇWM‘ádu¿cÁú” )϶äHŸ²{›"7+Å9;1¨µlKX "}Ê?z1T]­øºoó-!“ŠsNF0û† · VÓ=èhqj¸drÙu“ìôGæUþüdìk¢Ð›}vi[©¿w¤Âœ¨vþ˜g°Ñ, t×·%AF«Ý¢+]<œ«^öé;…g‘ùš&ÅTeâ•NA2dqW,±EÿYßVMK,î²Åùõ[•ÊŸï† Aÿš-1ª‹uœªÌfo~#5Qïû*ëj’i&rzö;zòn£ÒÖY›ŠáýÎ òáƒãJÇžÅë]5CIŸÒj2g[o« x|ùh~É’^èšRñÿ[L&–ݧý=…¯8qd;ûûÏNóöm––ŒÒ‹ª·6…‚É\:÷åg‹¢oÛš}•L7×:¿(=ÓþÖ<º±Óö#¿9}nE`ùÐ.$Ä<ÕTÉÏ÷+ úTíìâûkÅ æRó4z]uÛ‡µèKÿ,nßbÆZõ¿”¿Vþ(ô~4Ñk¡SOá‚Ôíð>šW£í(û¯$Jv(…œàÍßÐo¶7´‹ÆylîÍ÷ÔÔCC‘ЧAtƒ¾hª‚"´ˆÒlÖÆ– ]Vç–ìP˜cÂ@z‹Hnö"-p÷nN?¤Pš¼ù²×!%¶ø-e©ÔK– Lv>¬íˆ<²?f ˜¾%ÖvDÁO)F”yäûi`Z¼á¡yäÕd%={$d½£û¾è27ü‘{4¿±@ÑeIÛñîÑüÆEK8ÅîÑE°m·-qvH’×o—°ˆëP ¥ó?‘OVÜdXì 7”³[¹Âba~;%zLªö¿Ž$H"°ÄïÎoŒÜŽ9 ,£nÇó{GnÇ–mÂDZâvÌo“·‰Ý޹—fmýè¦vjÞžÀ˓˙C©yTð…$—-•²ôDx³ÔpG$íÿÍRþ5@‹g]§AF‡¹ï¼(|™{/B>ZæC†ôf‡dA9"ÈŠ9’ÍdÆÂ®G澯x¶fõ”¶k)Å¥ý»$8¤yèzút¢Ò¹[„/žBÅòäÔÖ¼(˜‹œ½ŽKKìÈwYÓ´+iˆä[áâú®l[V þR•êc¿Ÿ^ëÞOÐrD K)‡Õ_߀–xÖ~M9 d&[ÑQVtP>LjÓ;Ú‹Ž ¼+Ô43BBÁ 9Oö˜0!'½/3õ’O¼Ê9GÈØúTÚnrë<¯ÛÏÄ ˜UE}¿óÒ6sSAVB`Œ:}S÷.ÏÏέVj˜÷|üÚ;zbcyå¥î$y°‡&}âºÐ«© òÝ-|A<Œíi´¥2°)ÚâtGÄQç:|7LåÀè Þ^é,ŒM£­nxûnÆšOø:SW_åxïâ:ßE!–Püë™k Ój7زÉûr³sÉ9[À¦0´Ø›\õã`èÓrÏå2¢º_KÕl<={-Wjrgí:òöZRX/®²ë«Ó…2WªŠJ©ª¶p‚‚Ôõ!sµªäƒêéÜ¡á¥9mr.u­¤"¤í¥ÖÐØ#ð™SøŒÓì÷àÕ |¶› HÓÌo|ÙÈH ²† b¨Û)|óëÙó̩֯fÏ»c ÇÆ4΂Ûï®/!(r¨™—ß­d!2U»½7]º~Þ3F:A&F.ÕiÌÈ3K9—aŒý“¾‘,< ‘60ñFú 3¹œÍœNý|B¦þÊ02óOÐöôä~»ÛL ‹¼J¹L*åV'dp£æÈ¿©¹mø:U-ƒ5¾g°Š§KsæÓü0ÇPÜw¬×Å}È+3×´ë¿?ÈîŒ ýálóYzŽØ¾ã,õ„#´ß¯ßN¦™£äÊ+\æKì½Ï{1OsÑ•@%>¤Â­YêGrŽÌ-B¢pD/‹\&ôÅ^M™ø£* ‘)îñQI$©ùÒ-yŽ™¯×Þš ÅYv¯Ç &û[5ÃtÇÃÓC`ªf&×ôð§ò;GÄáf^™äÇc^ö¼UÉ52öñª¤ø‚A>}ú‰ÒTnÛ^f›'ßÓ£“c†÷: óÌòJçQ„ªíHÇÑEWa£—®í‡F^XJ($ãßö‹¡¿l’ òˆ½ ª´Ü(\'¹ÓshÝ'ŸüèHצêñ}½¨X¿ 2½3 vø%äáóÚàwÃÈòyÕʪ:ú÷Ô³ÔªÈóqkYlûQÈóyûë9t,ÇøïÊ®`:y'…6sœöéç®_æÁèôjdà16hÆ ¾Žg€Ó¹ÒæÉ1_üôxÌÈc Ǥû,ªuÂwD|?Èã(Qö´ÉA­!co ÿzê÷Öp<ùúTovBf®†¶ ­rþ°ïŒŸüÃ@ ’“稟v^ü@Ÿlìé`cƒ½”Wn ó÷ûe%‡‡zsT là¿MžndézV1yÑPê52üõ¬[¼ô¬£tŒ®„3©Єu…ÉÉLÑò€¤ †Ë"Ap¥Pè°ˆ! ÂuF&%¦02¸æñ¢ø6}vqŠr»3:#¤?¾ZŒŒ=őܶe&+›sÉ2¸â§î3ûHAT„ /‘û¶À«ÒÈȧ’çþzìgÇnã ^„ ®£,)ÑK@n¢V·„D‚Ä›+)K?èc&AêßnTfa½ìÇðØgŸ÷¾B¡“8LV0ÕçΛ<óÞL{“Fz¬1ó|j ýº×Œùôš¹oâo:" ƒ»¶Ëiã†ûF\[» íë¹CÂðÆÈÞU§!at·Ñ;šr±ùì“WM6R‰L€ ’xuÄ{±~ä´[2Àž&GŠN¹X˜çzEÈÐÇŸvr¥ðÇ0Œcéôåt…/.L}æ©ÊâëURŒ ²õPù6aeŠ^ {޲ñoüü÷Š#ä÷Š!dèñør”ÕˆÃz»ðørÔÚHÜyŸHm]ó<~VNm¶.CÈÀãl19‘HyÇÜ䘽3BФª²=ØØûZïâÆŒQkîÁ Tœ&19·a¦öÅH‘T‘ Ž›å=åŸaÝò uˆw$Ç<’9æòžì[õåÿ¨·Y*Ò[ÓíͼùÐQ§O™¯DÕŠDË ;l9ÿB꣡VµL «COƒçßöõŒÃšFª¤¿óÒuKýî /kÌSŸóå…Ÿÿ“ØMY—åVKG1ðûMh{dÈlÞʼóÀÐú7^2¯UWÆ»áœnõédT²Åe#g´Æ+x8ЮQ„:å#ç[úPž®Æ[§¼Êí-â6úóM´S)ƒ€NM/VÈÓ§„Ї(ý‹ÕËc|ÙÅWˆ¡ÖPÌ]¶4cÍêO—ÀªÌ‰ÍQ-Ðrfo¼f¯ítĶG±[@ÛHhâ@Åmµöœ³~ã燕ZñºR÷ЈéÒ¯k³§Q3(¾j=µÅ¨SS¼¶ö´= ïýèD”w6ìûÝ?øB«Ñú’Zí1]r&vþÓZ:Òe«”ŵÊü¡Â׆ ðñR$Ýã¹~EÎ ÚO·MÞ–ú¶´m¾ëÄ?;d,­Q«ôššw§ku8V•Y¤}ſ߷=ÕÐÄ‘å“'#2säù[Ü?4hjQ }ˆ"Öü.–ºšñÌ ³ãÇ£OQ*>vï¢Ãwôp$Vœ³‘²«Ëæ="ÅÍDc›wbòöøZ#øýù÷ü“¸9ßÙò-NÛÐù­ÿjz¡œ0Ë<,õToÓŽ¡‘í=i´.7íÇ}Üójùb¨z[›Z³JÃÑ>ï†ïônð|ÔÛÚTï‹™YZñáckºªJªä¨ûW±üÎx?ô¼Ä+a”:PÕC¨ ã8ôýš]åqTäq"ò† ž£”¤ Ð\ W—¿'©‹R‹äxCÈÐø,Y{ri§]Ì3tÌ“øD}¶V;—tá6gki æ´Ëvî>²ò†Ò­€,ÒÒz9í3íÛÅF ‰Sл{s ·žS5cddõ3ëVëNKåçB–d2¶¬òZWö˜lê‡"ïØÕ,Âüïy[e/¾£ÄÒ¿¥€¤:NáíÈ×±·ñBâøðþ#{ZšCpB$‘/ÊD‰ÇÔ­TÿÑÂ-òyNb™šö¹=Ý»n¥B¢EŠ“çˆ‘[°¹¢Eß®ëk°Ð$q†®¥‹ûAÿh«¯È˜L*ñÇ6qœN ÍØØÃx‡'ýCþB#¶Ð`yÒZŽ¿*µð4ýX–†$OÈõÃên»NuƱµÏ?GÈqp.¶CN ûú ÒùY¶®ö›låÙØÔæ ؤ‘À÷:ÎnÕ’3‰Z$œÐ²@léXžU˜¦¦Ý$.3¢†F&"+ƒˆÁí!Ó«Nd:me·•pÏ[6äƘ„碪ÈÞåV.–Ö¼+ÍÒìX.þ–ž]»BB$„KÏ«ˆ{ •!ÎqËIÚgkçi‚Ö4BŸ’€SzVz,ý¶€4Ú’”ó׺CTreãxl̹òbÝ„ ®ºkiKÛºk ‰=i±4B÷ºkÉØ rʳˆ ,XéBXANÚ—ý(þ6eBïv‡Þ^Bîš,ó|ÞEÈKÎÛÆ~éaÛ&éqш×oH^•Ÿ†,R»òª„øô0Žã++¯J«MHŸ»Ö¤Ïmùù˜¯YXþspÔ;*·ýSîlï12p³ÌVýe–9l…Ôѱ°„|Ô$ /xQs„ŒÜtô˜uùǧ5BÆ.GAÛÌKó¢}o¨Vı°6ÃÑ!ÏH‡÷Pkû"ñ”8}Éò7B¦²óY‰˜Ï™¹ÙÝñ!ÉŒiÛªñSá'ÿp¡ªËQA§í%°ú´¼ ] Qý'+¦²ÃÐÀ*-E+5êܳi pýEd >"a9½{-„c"ûNGöRè½{Ê¥“•ž&Éóç@T7eŠ]©\º~5kc\îžh Øwœía°phëÇšÓw×9µ³À×_Ø¿.­9ÍñŒ²µÃÈвäÁ0CDMÅkÁ^r²æT Éñ¢øwªèj»O~¬9î4áÐü4&qµXŽpYÚóŒ<Ï)¾÷ÄEj7q¬–e€ƒÛÄ2þ÷?ÕZÝè5œÓUzÄ™.Ì®-˜{ºÎPÖM¢ß"½9 –z³}›Ñ¹MäP •ÈRvÑÙõ!º±`ÞeH2òÈÚæ»Ýk\uuÞô÷J Þjò«DèE¶›?V‰²íjCÈÀc•ØŽÎ7ê‹Ùwe85ƒÄ'¹µòT†Sø(iÖ—8ŒÍ_µ&W\•dwm-®¸*Éž?6R°:ÊVKÛÊ•¾V®‰­\yÑÊ%w†‚:­\Žéç¯dª+¿K²Ð'¿ÛÎH~—d¡G~WF‚®ü.ÉîÄU]ù]’¹•Œ SE›)fÑ©¢ØïÀŒ˜dŽ:€,3ªží£¥(úÑJdk$‰Ë…äèÿ.U¾-è jdôKaý‡–óÞÃzŸ9f[WF-T3ÇlëÌr&÷§{O.Å.¾Õ$2ŽéaW‚Û„>}“è„=»h’aÌiÒOþhþQ…¾º98¨²n;±´] ôyÕRÔVmé´i¨ŸÒl»a³øÆåM¹Ù’Üò­œ.,ù ã R¥,¹ñŠ‘¥)‹L=¥)¦KS3F—Bœ­+åFn¹’x]».òÄž¡Óº½?Z¯6q¹Ö‘Í ÷å=ùD~ÖIé@6|x#äů«®]ôëç×ýzèùõéþzx£6ÞÓ–»äÝøÊ:¼iYH\6âe¯Œù@‡cxÙ+ÞÖ‰ëhiÜ'Áa!ç}¹äI.ž’v‚fS^fóÒÈÀ‰œŒþ¶,ËËFN =gnܧŸÒ†¾ÎÆ\gÍÊž|‚5I{1q(µa“FB,ö‚%t`ýÄÅ´3B†'yMs¤ã8®&W ÈØÑbî6„ôqK×~:z:êÅ„Úàyf~ÑÌdgÀ¬{ú»Ó(Ÿ».%χ‡!‰&:R†‘žëÌóv3G%ýRÒÔ\r(i‰ë¼ùÇuƒS¼Ú©|Íæ½?¿â#h9ï¡a\¹â d-õt 2ü‹>‡1#O*æ\¤Uðäâ AUgžHBì˜ñ­o›e¦$OrëŠkÓ’gâ‘fV¥hGš9y¦7¥hWš9y¦÷¥hj==³‡À!¼äù·>K˜Ÿ¿Žy5¬`ªÈgvíÄaNŠ|=Š|=B×Ã\ Q„¼(òµºÈ7aäe‘O¶u;«Mðôù¨.òƼ(òTùèò¢È'‘Õ²´¦4¢‘E>\©SäÓÈìÊõž!×û$¼©E®÷Iàu(Ù7äzŸ8L´s*Çë½FFáÝÖÙ7ƒð/ÅžžgtËrÚ™Ÿ±¿cDf­}G•îrEA=ú+úWÿ²=ÐIàô– Ci¦¥­ó‡F:rF’w³o´îË7ÃcFFa#‡Þ"u$.¥ðu^3æDÎÙ¶™xÖÕ±°#°žX.˜G`ý„¼XW–qŽÀºF†®2€‰.r*²Èi‚Y—ýwMŠT‰Ñzë%ÖSÒ.hUb¯v‡I#Cë dV)>nÍgb]#בW§1ãß§$}^JPxÔHâ‹[ ž&.cî"VìgÓ„^¿lyÔìøe'^—H†6÷†æBzäÈ]åÛ$ o™>Vù6 CÿÉŸwžRt×^ᔘ‡1wÑ^!™}=BþöŠ#dèãå%ÌÐߟ¶ýŸ°+[bUU¢¿”8âã~¿»êœO0‰‘ 1q¨óõÁ¼¯2Qšf ¢°ÞQ˜ŸÆ?mØBÆGqô~”´˜ïÈÎÔ;¶Õ©iæ¶^Õu‚à€ê:[¯‡êºiÕu–^×ui×uqq2{‹>¼÷䮬¤/ÌŸV®œßËA:V/h-Ö¬\ ^7÷‘L•D;WëX#däÏC*-·«<96âô¡(ã¿}ënpÍ£‚[UÙÝžìöAÈÈkZ7Ô[’<‰á‰ÃS™3YrÅÒ%9„ _©F&¡Ü&:¢Ü¦`­Z¶~i‡½UÖÀ0&f}÷8ôë2õ7KYÙƒ¬Bfžfé]4KM’BæÞ^égcS9b$ñ;[ˆV)Ìó‰II?h¨¿ßï½Õ=À<½„Ÿ¼Pw °;3Ùo2-LåuɧÄJ9ìF„ŒÍQ§ÞI}ûï#aÒò ×gxßY¤xŽ#¼Íô‚²S÷_Cf«ŒÌŒÓCÊ¡xµVOeݱö©¡É·ù>Ê7f –Ž I|VB|/3QˆÁRÈÂŽ¥Ü×#©à!ë' ™<·] E ©ìC÷†dz=ú+¼T| ¿l}¯12ò™y2a1Àn&½"»J~Øäõȶ¾fr´Ó”lñµä;…Lvš2©6ÌAf“Ìq{ c ì{…Ìþ¥Ñ?æFS µÀNfã3ru¦¯ƒŒÂÉë°"¥ñ?KXglM¥×£æ›ôà„§©üŽæë– #]_×\cQžCž&ǃ>Ë÷¥«a–&ž. K|fÜê[‰©ß!ÆÎ^PHL3­ÕÿDy é¡™nÂ4û{ µB’댡™*d8¥¼Ëô“§4 ×Ð~{£ß<µöˆ‚.z  یú,l¶õ-«êmæ¦-‡÷ûå7ªŸfuxÂ È -ËP)2·õGkCÊ!£°þaƒÿ™üÐ?8ÈýÔN—­ÕÀú‡ÜIà:ê ¾³¸¼úhí[ \~ýƒsG'úçš'úX9IòCÿà ÏôÎÍŸéÜ÷y¢p¡'ú÷¿žè\¨Gÿ 7À–þAC=úµõš‡õYf†Hƒ4ßYîæ$;m> ™ŸòššíÆžK¶¿T5RÚî½}k‹šI „¼²§wÍø|¾"dd¿ý) tÆgç\3>¾|i_ó1â…Lœ·¤˜èkûêÛ!ÑûT²aŽ|Üù–µAÈ,ìÏ0ë]xÉ‘jÆnÍ*[}¡h5-uûÎÕµu /ëÖ}Д-®Á*cWÈÀÛ´uhe´?´2ña}0)Žy‘œ„ŽÈüzÜ)ur§«M‘šc2F4Îáf?F2´:‹üä`^¯Ã5Éɽ‹;2ϳø±÷ƒ#(CmWŽ(ï´ÝŸÕW{Œ‘ËS‹ ž¤_·q¬×’bä~ÍÿàL]³y¾ú;F¢“Ýe‡r¹TS"ˆó#x*º,ñIœo¶E{S+æÇã¡a%Ô‹‚ïñаêÈåzB µõNĦà{éòº%K.ñyK¶aiªŒ ¨™sßð‚*ƒ\l=æ?²õ»yÎz^"«ÝçËÇG×4åÖ!äÞî[íô…ÇÚÑò[MÎ5óÞ«ûN.&þa܆ŠÝµîP;ð*£­»9×ÌÌq¦þŸýs&x½sï¹w™¯úÚ,ó I웽Ûõª²­7÷×!¶Wxºí[ä¶6'5|ÅúÉË*ƒ×ÁÂ{ŒÖÊ«©ìùT¿vø¢{•¡M¡÷v#_Ž×†WOì…¡‘:ÕßWç@CmîÒì¿ÈåÔVÿ!(NùŽÕòy!—,’ÀÏ ¹d!Ÿa–où¼#ªp|^ø5‘Ï ±D®Z»A>/ ™úÔÚ ù¼(¤Ïç…6ÈçE!½p ù¼($ñK£D²sÓ!dîÉ™_Ïu›à×ɯnS‡‘Co‡€ˆi¸—éÆhì]yœÊn™„ÉMff$Ò&7Bfá[ò¤ÛôÄHâ'LÉ#Zü”κMøŽN»Môê×—Ú‚+r)NÒmÁ¹xV5œ¯0š,9sð*Díû÷d Z|aà'@¬¸2ÿúó­‘©Ö/˜Ã­t+ÿúEW„Tö‘5Û®Ê4žÂAþ˸J‘(F;:1/kòJß ýs»3„ŒmÛöýÊãy¾G1Ò’‘UÊŒ]z‘¯å·Æ¿žê>g) Þ_» ‡5ã»q…ÌŒ ëC#]3-åð-û!í”jª³§ë×ó¹U_“˜¯Cζ{N› „›ýOdf[˜B÷§Äçö×#Õl+ÕLÕ>× …Ô6Î}¯UÀzµ„O»c¾0«mW¾„j©¡†FÚ/Vè®”µ³¬Í¶µCƒ¡ñÞßÿgïïËGÕÍÃòh×Ce:<Qÿî+â¾Úáý®™ðbÇÐGº×H3™Ýot”¡h4úïãc.šøf<Õ·ý¦#ãc<Šˆ û6åj¾»4¢£ƒôÄ£ð™yG2ˆŠ¶Íšñ²@·KŸƒ˜§”Ÿ;1 IÈ_•Ï ¶¿*‰ŠÀ—ï€la"‰Š¿*ŸomUb$bŽH\ÓöW%F"æT¢²j´+Ñø°‚Xîö ŸÄ×€ _Ò -A¿Bžú)Fžúa¯A¿üŸ– ŸÄÑA¿¹fôCÐsN‚Åv=GìP5wE–Ôhè ÅIÈ9T®³+tNÒŠázBlo-2GÞFÆÇÕ“ ³½zÆ ¢º›Õ“í„çÑA¦ÞÕ³—«'¾£,òZy‰Oz#µˆï™:„ŒB|jjË8,jïĹÄ ‘8?ù6×Òú6cç O)>,#BFá}…{/‚ŽVLˆÞL·Ë“a¤ ,€<õ§£FXC’褃4ÝL¤6IâPÌŸí˜!bË¹Ž±VÌIâ3–ð¼ÓO>IN„ ´œ6ø:’4c(Fœ+Är^þãžb3¹[BHD_WÕ²ð¾y! wdÑÿü6ˆtí‡Ç§ê&„ô;–Ò tDÈø8‡ð§„«z;² Uõ|Ôáª>!¡ªžŽ¸ªOȪ¾÷„œWõÃ!äIU}„„ü¨ê¤§ª˜SÕ'Uõ®{ã¶™{/Î}3k¨Wí¸.ïYŒäôz.íôÉI£nøÞaÕ>fÕ0ÓŠ}ôëQ‡Y‡¢^̯'¶øŠmK'’¦'õ’méDÒôÄÁÎ>“&–ÀÀcˆ"|&ášù™!ÊP›,Í]/ÈÎÖ¶ªšÖ\“pºa»M`„C,1€Ó·ä¿½5K+WJP^úâ¶­ìsïvÏõ–…,rÍIIZª *÷û‹©C²KØ—\|ïà2Oì ·h˜à.¬þ•Ö ˆ¸®†={™x¾Mµã†;2 ž ë’š¼w’…ÓLôO*éM°_‘]ÉÎWÃ¥›àŽÎÜZÅô k\^ WäëJìlcµw§ívƒpt’¥áõE“,;ÝËlfo˜å?¸0Ïgä·ÃüOòƒÛ=Sãqàv8H·CM‹Û¡n‡@ÚÜ…ÌBÅV”'üa³ß{VM€Ø6”ÌÔ`¹}ÆÏ«_®²~î™(é2Ò]uuÆ/¦›]äÊ(¾f2ƒáu2¾¦•òPbC)HX¿bdjOÅxÜ5gx‚Û7_¦rí/StÀ·­îºj0Û7_ …Äv¿¦”Øn£ó”HÈ`f pÚ˜Û"WÈÛã×ìÇrî·»©ër[äê.Ú-¦È/XFçœ Zæ$¿×®nCû Û‹ÞY»þcê_›‰îãÏ‚àŽØ^ôî¸I*fÍã àN²b©sMŸànR‚;|Í$\1mð”’ „¯ÚVp(ÉÓPĨ0}°ÂHIžúNPwçv>æ0æ 6ÃZŸ±+Û/& @ëš™oõP^ôåÀ!c+PYõ9x­ÊžÍ§„õ0ϰ•ƒ˜ÕÛ¤´­?O¨Uó̲ìùOÄV)×]þ}·g»é\…”ߟ˜ö>\½ç‰Üš¦.oί›¬Š=cSt"iµëX›ñi­ ˆÿC%ÿ‡w+BFÞHáràï N3‡ygf²xÓ °©ZɺAÈ807ðõpÄ¿ž„ U-Ƅ͂÷°Œ5±YðvƒmA,¼Ï¤•šs¤¼°D|¶¥U–RP1¾¼ì•î½Õýt-ßýŒy‘K7 wØÁÛžùÞóè^θuÆ \2r¬­è~(É«°i|>á;"x7£jê³€ô„Ó4¨Vi”óPÏ´BÈØ×?ÆFf|"Îøq|nÌÉgü˜íÅ—:bdx|À÷#Éa|b‚ùõô„‡€˜l$=Ë_`] cžd§Õ ŸY!¥õK ÈÚ®¬‘h¡¿bâF >kþV}¦zaæŽp”  :îæ§ý0–"nNœˆ€ïg>T%Òé[5|¦…Ó b¢ÿû»ŸwQõ½Ï•M#S¬‘„ï¶Ùm\ ö'$ #íÅiðˆQصÜÜ{qþ6MDŠ@gQküษ÷ ;d\H ÜË׆,’£ôýÒº­t7½ˆPæ e´7•åcžÌNÎx»ëtBÕ7ª¦v]×Ïæ ccl¤ Yªih‡izÃΣˆpÆÎcš>ë³AÈÔÄÝ å‡|Jë¿Ø m9ô3=14± r>ËÓVöó£bÎm¥ô¥ƒ‰·wó­žÓC3º·ƒ9”?Ø¡oœ«æ6”îJxå€6ÎØ·²É\ÁG8·có¬+<öÈëÿþþ£Æ«z®O¾\´Á€ž.pÚÎK“Zf¤oïÇ£Y¦†9“•LøW í‡:ªzñÝÕÖöåúq®…ýT y]Äg! "¢î*9iýØ(¤Hϼ1yÇØÅy¨Ê`6ÌEŒßdH6N ŒßdH6NPv–tH6®ÞøM†dã ™„žç0BÓ­(NŽ E?^?ÏârùáBLy ú”¬(P¦°%Gb+PF!ã]3:9¤´D2 ´ƒ¨BÆ>¯¼®ÿ~Ûv€_·=å5­ƒÏ²®k½)¬Œá§­$Ö;!ƒãZ é/ÞAx12±¶àp°Ô‰17SŒL-ï ðʛǦŸ¡5©>¯<^íЧ± PÈÜ'Êå;ç^œ#$±ÌÕRõîˇ¾ Y`Mí6ÏžõRÃ;:D᩸H1Ûôký©W„Oó<â»?@¯Y¿õå<ÂåoŒTßܿӺ«‘Óö*ƒù›O¯x§öåc¯ù&EvÌYtÉÈB^T!vbÖƒªö‡Oýìye“„¯éq`6I3¾æ©MR/m’ Ԉƶ¡Ù²,¬´ãùðzµ‹þÿm‡Ð-zàÐ Ì7™ÈM4<,š2ü6m¥*è˜S†‘j%C>FÃú¡Y”¡¯ÚÂU¨1æK3ì¤CÈÀU³8 B†ßNñb¥Ug'½kDø÷wdüÝß;êþÞ¿‘LjP„ƒq;p k”p‡Ù&cc÷¨æ–¨ä}˜·|FH­¹«%žÅ÷+Ó+у‘‘•ã„­'ý?Nÿänuï2Ûÿs’Œ%"k~Í8º´±JYümD¨uYøÞÕ¿ßõócÉJ¬!°ØÅÉ•BøhUâ2ÔÕó¥ž;‰©8½°5wuÔ3·«çìø·Â×gG5yücéUq·½dYr¢£î°ðœ"Qrÿ¥Çæ¼ÛÙrHytkñœ%sIZ­Á6ù:öƒæ9 yž%Ñ…êu4ϳ$:È@1Š.®æy–`û7 Ï”æ9CÈèLóœ½~s£yž%'ö?ƈiŠe ¶ÿqûThžÛ6‰ÎSH¢dÂÈ õ´ƒŠ«&%±¿cyìö†ÚY[+B’ñ™óŽ"乚€èrNz–Ä(+”‡üÞËW¹[ÿ2ÈäÀýløœWA-Ù(M{÷äºK 4²ä\­¶5jïÐß›!7ã› ¿Žw¿z“ ƒ¿1Ï7ç;Ê<é¢Ò=`’¥Wwbƒ2¢ÓÕ£BÕ¦jÌ(õÍ,(ùž¥rQVkÞ=…¶”ûÆGÞ=½{;ê…Uº³‚¥XIÁ9óûþn­VV–âýñI[ï%Ä6éU?ªHCÃJ›þF|‚¹”~Ût‚¥;²(ÍÒÄcQ*®Eiæt|íGÈ¢4KŸE© (9¥YêØ_"ã#qw×ø(KSG2>Êœ> \*H×øH#ÃÓÞ#d|¤‘‘—`°Û_óš`°N°†¤>‚Á" Û»az$8ÉЙv|Bá»G Ä ?1šâ¹FƧ–Äã0 à ‘ç>åPÕÈô»˜$H ¨˜”fžb’DºÅ¤ÇÍSLHTLzÜü_1òÀÈ®Tþ‘éjöüZfÈ["{8ßû_Ùù_é? ѺÙnævWœ"G3çñ/ Íð½_(3ÔUž”ο{øì»?®JD‚ÈgÖÏGæ×›wVÚÌg•ίYUë`¥Ín¾s‡é½äýº÷ IJìî+~¨‚Š~³À_PÁÑoxWoº â(ŒÒAAü©::¹™Ÿà:RŽ´àYv1C.x–%ßgb(¦åÚv¦‹.ËRßYF–4œ³Lv© È·M(ÎeßqˆÑ˜TžÞ݇ˆ/c¶yGAç¨Î3@–#ËâMËÏR#lÙ„h<s÷NÄ`°Ã&!2øqÇ“åu³ŽÅŒ‘“³sƳY—úï£Qjˆ‘¢¬–fÄwOÐ(™k¾»}wF)´Œƒåæ˜Üdäµ[T ìïI|!Ö/ü¤! J’+sŽÝ)5&©Ÿl–~î‚HÀÚ–Äïª4ë<ª§m °&;BÛXBš½×wÍ;ûu8v"g'Ì[¥ä³n9_q”, #·s¬ÖvÛÂò¾\ñsÆ â\Š4¹Ü6gR±O¿™À¹¼"U«dÉÆjgÓ6³!SS.J^„mâ~÷‡ñß*JqÅFµÖu1Ùüoòð,ÅjŒNƉϮI”ƒ-Á'KA¸²K@žœŒÅ5-ÁÑ™V‰Þ¹ 2½ùKÌcÕ;;Wz» +ˆ VïôvÑ.-Í\ò ]‹ò¥›OO/Ë— Ès“†¥ªºÒÞ=¼èûµ†I€ l ¯n*­QÓÔ[·ìE‡Žlºé/%Q!þz¸&:ïÝ›†ÿ-¬K©c¤'ãFšbé¶~ÂwO¼ÆN¯ß=õ;­äÃcì4vÓ™¨ˆ¾_B#;wãÌÇÝúÈÏ£šˆ``lø hvÒÇ×HG1ÒÇÎIL¼î%8:°(§Ë·äèØ»§~®ÆSŽÜýÂ5^¨ú™¶Û§Ýíy\¸ HŽŒg†Z™Å!ÁèîîÃ>”¯œ!dðÍæ¡ZrhÃÈð[rˆñi'$‡ìsfW-‰-¶„~”«Bƈýlüdžnó™ø¸D;äsš9Í”.Cˆj#H²¤™§™RN¡Ç†#·Kþ±iLÈû¥Õh –ay¦ïŽ‘àëë°¾|–Ó,¡—Ѳ9œf@ž2Z؈x*Žzö‘ÑBwÄ}y8‡m•Ž) 8Löm»Á yœv")­þ‘à7ø6‘Ïû@&6s{HxÄ™-"½è3ù{¼xPÛ[ï@žy<•÷lÛØ×Ù¥¼(m2È2V¥ ÿ6åo$ÚâI>P:Ââ¨gÿÈ#tel‡zäoö‡·z:¯Õp€‚[ìS®´²Óe^šn ö¢¡~ß¡®1)øª·P~DÙŠ|]OØsR½ß°Íj¨WÁ·­ëC# +›Â5u´/kºÏÍaš¦Fg]kC+ßf%¢Ï CN§»Öœâ?í>´_V U ¾Rq[™kžþVwŸæ…ÇUë-ÿûOŸgµ85?ýíÃŒ§•Ö[ÖPµF è«»¿V ¸B?² y5¬ç!= Õ\!­eÆZvþ.Í<¶<‡ý½8Á»NIó#VQOÝV0„ ]Ø5JÍi^ûmšx…rݤSâ×l×"Ñe@HÉûŸ¸{-f>é_/òjºYëR’/¡þFÿÉ& ù«·u—÷ýZŸ3=si`ŽKGž4Ê—æ¸4òÔ¥:. €|“‘õ2ôÝîa!Aa/¯äg$:o~øØö†Ì[->‘ö· [Øm+ìwd“Âÿþêă‘b,v¾Í†ÊãGvÕŠ‹Î'@¾ó¾ák>N™µè}ïðxf¾©f´ÍE÷„ß=Àî161*EhÖj‚•6¸FkŠÕ•ƒü CÐ…ÓæxîWBN›ã=¸_]¸©^ô]¸écŒ¼&Ô"« ð³ù„*_› 2ünA–HÙ‚,©ø ³UÝU–e³ 0ë·yñG­6ª]“œÒšŒ;BFŽ®cÓÊ­(Za B2v;tˆ¬öÚh dä×Ù^û¥‚*úÝé|ùüù1zË ÉEaŽ=yî ²ó3·*ƒoãIdh#UWÏdÓâ™ûf²4Jtgòµ9!éH I¦˜ü†%³Ÿìóø™?ðî'ü¯ø_nd<ÎÖd™½µPlDÈÀW™·EÊ{ýV™ßòª2¯zó‚;l®^q‡7Áž2p­62_ìø5Èû!º߆dd×GÑ”FÒ#º;W}Sadh…J²©»÷5ìq¡ÕFþóÏ(”škVüšó†ØPPçí'~û%7Ì;L\]èÞÿ?Îðî>é#qŽz·ôÝn–ŸÇñ<¹fèéšÜÆöÍÐÉ~Ò0»£dó†Ì©‡_ö€k ‘‰£KìŒçÒöDé¡å©ýùwü5kŽ\ðs>ðbÎÅÅ_ÓúÄ£„Î[UÊå×,§>ÇH>Ó\=¾’Êà ªsà| [ßÍûý?aW–ä ®l·dÄüùз—€™d°±™‰^ýÓ˜R‚DÕ÷ Ê€R©3ýÉ‹Y¥²Ãoü=K|ûØá\vOÞÃð©Jú{·ª¦œÅœª‰äÙÔïòôb¯AìFñSUç.‡Ø TÎ:\‰k›¡Ê‚¾O£O9œ«¥¡'ð¥{c–ë@ÑµŠ¼÷óè\ý)Ø2Âý)ŠqÆP_fµªK÷uUñÑv^NHbÔ[á<@•Q+‡i™þºßF#­Ä·<þ(¸5ð£ô¬„³KÀˆ\‚ˆÜ¦®ZL…7‰a6Ï=@êdVÊ`VÊ‘ñ)µ1+$q¦'Yf¥€t™•ÒÉ2+¤Ë¬”!Y) f¥¼f6f¥€t˜• ³(0+¤;‘É2+¤?‘©›02÷™k¨„£äÞ\´ŽAtQÀ fôD;xGÖ*öÏÿJ²‹0¤á»¶M‡/J=Ìèn-~Í2ž‘¡FÊDqM¶(²}z„Œ Æ««Jïé¦ù;- ‚¢q?K¹.¶¢Õvݾ›wd­b¼Ë' T¸þý»¾ÚymgüßSĶ–Óí=§b6ûÄ(½Û¬úÁ¢i‘WÃj’¥» ¢üF&tW=BÏIÁahÄ×.´]emÀnÕiEqtP;ÅN¥º¥hIî˜ûTøqdx¢mURÚÁfïî8šñ5^º¦жº£lêv©q„“,àDC^ów¼z„ 5LÔc/éPßÈê‹p rãéSkíVbcÄÕšã/ÿû8NÏþ‰r¯ôŸ¼÷î¨o^¿_3µ»(²cÀ“° 3 —l[¹ó5™Y€ =&߬&›0Òñ<òyR ïÈêNœïnωš{OÐúþd¯]~ïÕ^Ó~l=F†.õRS2½USM«yï©GMÕi5¾¦SM5H5Õ„5U§ÕTø¿;ÕTƒPS™ï=õ¨©:­¦ÂH‡šªÓj*ü;íQWS­ö›?ÛÖÕ0–°þÆ.W•î î(ÿCwÕa¤CwÕiÝU‡NÝU'uW;B:tWÖ]õéÐ] Zw5#¤CwÕiÝÕ„©'RŒ02yxöȼõú}>ZÜh 9Øì‘Ÿú\h -õyˆÏ!š{„ž¢Cåi>Y„èÌ«|ú|Ç«è‹jÀ× m^ÏK4¬«}mKÓ!d;Jn„)Çç^¬Ówû¾w„´ù7JÝ˵Ãü])þï‰#ÛˆVU5mÝ ì+>³ÿ±ýá¶ÂÉKb˜RÿÛþEêÞ¡øˆ„̯ÙF£È6:æ?O•qs5Ÿ²$E-⻚OY]Ar´9{ e¥-÷»ÄgvG;˜¡ß¹AZtË I|ÄLîiQ8ËÿrŒÇw³ LW ¡uäÆVw ez’ÞûÄš),±'z[ÖMEMa¶gÉ8-&0ÉÙÜÄ|îÓ·_{X8Ûüœ“^ɦqeÿxÚªõ¡Ohiµ÷">Ëj#H}ír!ⳬ6‚Ôgµ¡E|Új#@2:©ZPTÓcø-K±Â½[2º‹ë/+D&³ñ0^ýì’œ@Z*$6B*aiÛ!dhu/´fbžèÎ_ç€>2ÓaZAJü£nä¤-´ ÒÐT„ †vŠ‘ÍÈ—XIìž|šßYM¦].;œ¼ü¥Sõ¦#·¶4ï4-ó6ïŸ#ãë´øÓâ°Ÿ® ·™ÒrÒAn€ô¹Í-áÆHó\–â-H£ƒ‚êsü^Bú º_3ô(ó ‹|“:œ„uK¢=ú~¤ðŽ’»t!ËÀ.HïÈa#?†ß™yKÿÉÊãÈü&êÝäŽÒ¬;Y¹c€ô¸›Ü1@Þ䎅ÎR¼‰Æz¥ÛpÕ>UÓ>™íYfùló¦@%=]9’ǼwÕ§BHkþ¬„’ŒmQÆéÝMÓú.z…Ñžøä–ùS´óö„9${ ïè œ]VÊåw.O¿ þßÕ©šŠ®øÞ%2q ÙJ\¶ÓJ+‰„BäÉ Pù],ís<ýÎ !eÉ2×E½Í \UÈ ‘b›®š3´N×ÔÍz =Ž¥™~§ª(Û¢dÒïó×Lk;´¨r5ý_M œ§e_Öu=½z ò‚QŽæŠ÷i·i?ÿÖM9r<Ï<`¶˜—CcËh…jZä´·ßúû;AËÅî¥,uÙ Ò5ݳ)14u¯ cÑÒ5È‚›Æwœ0ÒÓ¸ëöª0ÒÓ¸ãhàdÞì5þòíÚ!#èwšµ÷÷˜¹óÃRkdx¥ChÂöñú|¦]W™ÓåBFÜ s^Ýäz…uð—Å—ú£Ç÷.ÿ÷2óD‘‡qâ§çøwº­i}T£a+h ¡œ8, |E¢c_nÇ1Þ'ñ{¨Àf:OnÏ>t,$G¦1Lv„¼c˜Lú»gæš™'^U„A}gkØçojá|ñª€$î€Ûí/Èó·?SŒ‘ö R¶t6p8‰­!ºn•x-Ðid€ºú’/»w?´»~JäAïUÏKÄšiïN2–iþt´_BZ'­Ú/›eöy®çÌ:‹ï«¢ýŒï!Ý-ðƒÏËæ)…<¥è¾4ó'‰Px»ñÅîúç³ÿoøŽˆ4t-íÞ¼²DÈÈÅâûuÕt@¤±¿`;ð5}",Ò^ôÙ±àÕŸ©§´ûcž2“Ü]y¤ 8lý¯o‹_GñSRE }&Ky·–íŒ{ü”Tø-øa¾î¹'Ý #áèèm‚ìÖã6–…F^"šF;…U¿ï0<ŸIüu}ÄOŒLÃÓY‡4 Î} HzÞõ·Ü:ŒÄDGøã$ø#w·þàÝzü;©ìÃrŒlÜ÷™yB¸Æb02‡¾~Ùš>ô¯è:èCë'ÿ°Ü¶õ°+kö±Ohà,š aÆožœòç´ O•,3‚‚T°ÅÊñ«šbí0ÒasÉ®ù´-Vˆ%=áH>‡Ôª¨éÁv>Å!cgšàÐõë0â;J®'”[œ Æâ„XÒ‰liìÅ'ÒçsÞ¶!3 ¹~±B}ÛðϯY†ï·Hžklý䓾[O·¤ÎtNŸ–¯-Ûpð•ùsØ´„•µÜ´d<ðM¡ßö o4¼+Y¾c¤Ã`•!ßÜ`Õ|¡rµ6¹‡ñÓ|·v@HâÍŠõtÍЦÒÉGÊ©te¹#FF6•®UöÃl2-§ÃÜ{t¡ÁÈÏŽËɹê1!¤Ã…†{n†zB¦Î—Tû%3BfWSa>7Ú¦Âä.n™ “0ö˜ óÒÚ6&wq;ÈT˜„‰Ñi’e&§ä“,X»MÜŽÇ$ëtM¯IÖ±?{„¼1É:]óÆ$ëÀ×LœFlº7>°Ä’G98}š1ŸÝ Qé6›¹)¿5B1v1$º±íß¿o Ö$ºµã°BBHø›B($„ØA.®Fœæ‡”7¯`3…7v¨ÑE7v¨yE^‹èŽ[ž}`‹b¯å?îë cLŒèC­b ¶iãÑàOñH#"_Y·õKÊmè8nâÅȸCf·J&·¤ ÓŒ‘12îh•ÍÅ2ôÅë…‘ Ðqùê¥j¶ƒŽ[ ¡+Ä}\å¢Èk ZF7 ˜nÌøL‘}„cJŸM:}ƹkÌ¥û>êÆî;›ç™z[»lïSPˆq$FváJ†?ŒŸ2‰|™Ò‚÷þË€D·-69ÁÞ1ÏMŸÌÙ1‰Ï–ŸW¶Ëò~ÃgKþC1Žü;bˬG1AÜ@%˜•ó<»s†Ä× ]秃8Kš02ºž ýÀ­€.®Râ÷Ÿ½éúuꬶ›2qlºçb¤ÕhЉ±ã¸dfÑíNÿ=»ž» òÜ…øŽro6;H¢HlŸ þO|GJLAÙÿ§E·Uiå?+ øàùWÌ Ûý ³M|ÉVßû ²¯éÚ êUFÔô*)zï÷ïXOÙÍ+ÙÞ¬{vóO¶™^æQÓ72 ¥-»þý6÷nª x{S¬°j-6îóŽï(Õ_q**vïn,ºzbsBfV¨r+Iì•ݰßQ~ÍTfÊj_zºwM¶©ü@Ú¦V8¾¡V°¿ Ð8¾q[à¦dææ“ËFš*o—áWïm§]´ˆ#iÈœáM­5Æ)r¸39¸¢;ícA2ÄN=ª[ýyíó ËalÑq“rÓÀ†Æè.“2¬IÙè.Ì–›ª I¤B$Fw¡§›FŸ ­¿¦%dé.Ê16ÑÃô§(ã S|Qygw…+­ …ç)ÜôO÷ 7 P+;éR^ðsj7m²_£Õ²T ×o Á²;Z;ïÔÃ5Ã;Z;ï¿wéñ¶©òÄK¿—>A†*O’è.ÁÊÝ#†~RG³ÒBdœž>;|Ëùˆ$ɾå|D,úýõôÔv>RH¾í|¤‘gã1ŽÖ½§^·ãNä-BS$¹;Ý·Ý”H’ý‘NÛÈ$¿=:€ÚMÒÇC¨­ö!éM ‚ˆV€e¥Ã`zóN?Ôú6ÓðÆO“›ZIBÒÐ3ê8M‡; A”F7º q´ÎrRk|⊥:öÅ(„I#]Ý6«Øîp_ê·F&¨¼à-.Ù c |_–V‹+M¼JûŠ+íM‹+µÆ§ûàéP4Ü„™tÜÍÓ!Ùí&v4³bš]|¦[•é¶ïý—š‚>ÍQT”kÒ‡—kí¼½{„$Žpƒ…uûì?êP4,[åBØõÍïëæ‰Ú- e¡Ü—ýÐÿ#IÏÙ¶•:‰gsÂ<÷ã:ã;JN ¢¬\ênÞ̉Wš£Aºz)׆þSßmCHé¬/»j­ÉŸE°˜)¾ÓÜRd‰;ª•w6,Æb¤l‚JþFŸä̯+¶7þ¡êlLŽzþy´ÒaÎìC:A¥±þ?ÿã5}Åï¾åõâÌf1³p+(ëË‚Q¬ˆl…gýÞ ‘ŸÚ¡’HvKí°¬´HvKí°¬´HvíŸ(H¾ÈW¯á«Tæ^ä_ppßa$qD’ŽŠ$%æ:ŠéA1-G:~¿_¤™%®eÂ:cš7H+&†‡Ì«Uñîuàúo©úv=]3´{’†ÌM fžÂ«Tv¥a½SPcùDAù}–äö é2ćc<žOó;?Yå( kwœ%VYýO ’ÒºT_ÓÓÎnÔx… )õI\ŠŸ»‘ÌIº£`7’ù#Iw즡§ &Øœ8ØW…\3x~3Rø‘üáSøýØ£œ¶å÷BÈÐß½{ϯ¶–/ÉmfcihšRÛ›],Ë+Úèosû¹Ôv‘$'Nm+Ú XLðÃÉÊU~ÅÅoÓ ~ä´¦VßQ3.Ÿçö¢»')-zX-n³› =®<úƒ õ<úƒ =ËÐÞU¥Éc_è77OnÛ È“Öq>bé5‰M…½žXzMbSaç#Ð7óRaɦæÙù ouÀïÌïJKn†=!¤Ï¦æGÁD—*¬Ë¦†MÐeÊóS€'ï\)c4.Q__;B›^®Š1ÏË«aš¾;þ¦lƼü¢Ò˜—N§ÿžšð RÛ,Ì|g^þï²w$ËÕ ['vóíø™ñ5ó+O‡w™FápŸü㚸 ü_¬Ä…ðñð$.¤•¸Znþ8qA ­Ä…ôì>xÑ2À5ÉM[yÍ‘Ohñ€];Ä~ÒÕ²Bº„ä´—BòN##?¡‡sôé é’JHN{„ ]ùàJH¾#dtMQçG3ï~˜@Æ0†÷!‰1Ü|H!­uÍ懗Ýðöð‘ ¦ò—“”Î ÝÌ5“V·p´dê=$èÄ!Áï=ótâ`ÜÒyHЉC‚_3t‹¬øÄ4adtåýó9‡7í2¶%*«õߥšt¹¦qHÇöÅ1t@ÈÔûÁ{™û8áàÇ øw:Ë&é\÷žû…ù¹¬ïÒÁ>KÌ>ƒ‡‡ÝË·vnJwbj+7% /W»û}¨)”Àø »±å¯.ÃÀ×]ä §Í}ƒðf1¶¹ï¡Í)‡^œæUwM»µð;£Ë\§šÚÇ~üvVŠìyñ{RZ«\ ƒÈuÐHuÿù˜õbZ‰ Îr­¦ø¿Ç¾‚ÞHøÃ þ« ßò® Ç× #™oŽ Ü~C‹Ñ®N4•‡‹ëØ3Ú0’8g>桼ƒÄãF-” –UKhg\• –UK¤7tÝVÚÌÅgþà'üoðѯÏ{XhóÆPÑãb»™Ÿ2•Ñe]ÚŽígð•=. ¥úb9^íÔ¶ZG­¡¡Nb³ˆÈáaEú§ZöïwîK ôßx`XæØËÓåݯEy`¨ÈúGvŒõÜX,¬®l·²ÁP.Ä«ÞѼèÔ®¯úÓWECS_¦ÕÑÁœg¥9œ7òòæ ‰#´Ø²B™€`Ú) '9s¿p¿r@H§œ™m¾Ú}Þð5CÏ™[Qtæ+‰þ3CÕFâ{9³™GI|Ü{Àême8ÃkP±sVðŸè.—ÜÁLd¬{×µõgAÈб:ˆˆÕ ÿ÷àµk߸<Ù/(2ÆTyÇËŠàƒgY ¤qàŠ>ë±=ÅA÷ÚÀ!ÁAÈOnH-®YõEÛu1b¤|ž;8UòQ_rá¥=Bšôʺi5‘läAfà?©°•~Š=·"Sq-pv26ÈFÛÕ󓬽ø}ð5į©f‹œ[Ž©uòÓ´â;>ŽúؾÓÔ7 ¾å¢gD¼Z.Åzàÿž[„ež†£šm?Í'¤í[^)שµÝ‹y¡@Š”[E,ï‡× $S •¾åÜzô©M ×a‹þõ{ž !JîËCUüêc.Ƨ¡‘«¼æâ9 â¹ÐúÑBHŠC+ôÃÉÕ‡”öäpõŸ=B?Ê[õâàÕ¿‡ñÿ »¶%Vq]ùK 6—<ž÷™ª5Ÿ@Á@ ö×ÛY26+Ï]\‚/²Ôê¦wçA|;Sd¼s«7¦Ò¦˜^MÍôv»Aù[~„\³]/~²üËyÎ,L€è»ßÂJIˆ³°R’Öþ¥$Æ‚JIb|H)É O”’v´Až(%9Ïy¢”ïÎþ¦”ä O”’`qbSJ‚ ™ýM)ɹæ™R’ó gJI.Ô£”4L QJÚ¡'JIÎwò)%)Cq¬”´C=JI Š•’v¨G)I5Ìb¥¤š†Tx¬Uc×3J†°ÔÆ"OdÓ¬Y&yÿæ(cžc5hJ † iðdëykú‰^“T𱚱 f#kAŒ‰:Oœ\¼"!þ.cñ™Åi.¯ ÈËYÿKÚ`,=!™`‘qÆŽõ¼íØ¢ÂÖ±©ÀŠ•±,PñÝú6óÑÞ=#‰­¾$vfÿãW·3|£[@}IÓùú’AFaBÀ9J†{’c(¥€ú hJA%²HJõxÓh6æ×¶§œZ÷ žó$mNÌ~˜í@ð›ýiÇ ƒI{î߈‡åÝG-ïí@ðK‡Û u ¸ë£X/(’ùÖµÈøHÜ/2^)‘ñ– co:úGÒѸ[ÀMGO$Í“³tô¥£yršŽîl:š'Hж©+ý£QÀˆ#CPm#^í •¸n–¯ƒLŽMò¯O©œu;™b1ôíäÁ¦nDzž'‚Ì|Éðµ]^(¾!oždxë$ÃÍ?ñfÃ{9ål6Ü@¯t¸@épˆ²Yl›b½ßGØ”QûÕÚÐ~S9®%AFDgdã]%çæ/¤_&÷§E²`8e'2¹r Å!#ޤ!pj§þ+(’Ùæ^m3ª·O>LCkß=£òžEUîÈwý›Vh¼1Hä\U™á¤¨0ù]ØÍ‹g¤V—]õ¿ôרŒý“Þ=E§5s®Ò­Dýs‚‡g(?¦Ÿó¹%ås¾åÀŸœ»ßŽb^]û¨´˜½ûâ9cô¾VZÍ‹¾ü•‹¶²ï¯ø•mßõÎüųRþrÀ+à—+ ¢u¤oeB¼ÝÁ\5¯ãør Þ|^ÁäŒã³y÷ÏÝÏ{‡&¾ùôQ2aûg¥¨]e÷Ã}\Vh6Ü¡™¾A|ìSÚ÷¬ >ö+{×®nÐb@ã²@‚ u49 'Ñ~†G_„Š/¢ªÐ §úÅ ’y'© ñ:¨Ð³øz4p5Ý2ŠTiÉŠ,ƪ׮a󢨼ÉŽ†Í­qvUDƒäûR¶Å9ÛRÖ~ÄúiĞĎ#_ÂÑ­³ ó&‚´F³*‰­—r×¹j>P"G=ZGmÕÚÁ7bAœ.íýì5y¸´'ti¯#È(|wHaÇñ™2ˆ@Ñu|Œ®7ûX%ú†ícYœìcÕ^ícYœìc59ÙDz8=‹qÙ(+˜¨"`+ ï‚,=Ždïê+O+-AFá47¬8ÉåÄr^5€ÃŠ—\Ï-çˆÆÑr^¾þâ‡äúþœ(±UÆÿ9öœòaû¼Ü aØ*Êo½¸u½ô3œ‘UƹíÂ=yþøMƒ}NFˆ*Õ»½ûcY§y*ì˜ÇVZçq[”å &ãìahË…Þ=¶ssgÇÊmîó˜ç l•±éx?áîë»éÝçD›2dhÚ±–¡µMÜ#«ŒþûǵÓ[ÖŒOk•ácŠTÜm˜‘ðc0ÜǼº¹!ÈÈ/(öÆ”ƒ$ÌêÛxÉÓB<”V;–b‡!ºç/Í^F‚ AÅÔ4Arßï¦Ìa¿fLÙÆeõØ9â+šj–ÿÓBü˜•Üz2ÇŸswÈÌ™¿žGÝZÝ—'œ€ÔƒM!‹N9CZ²GbµMÿ÷ß¿Xaê%{µ#9çDåòU ÎÝoØÄ<4‡×«ì%äì©K&&17LMß=!;1ŽÊëgó°wO¨ ˜j}š1_6zÛ&Hh%Cíi,IÏZÉP{óµ>Ùœ½r߃7Ê<û‘Y—¦n¼Ï÷½öŠZŸd[i×Ul»^’AF´ÕјÓÿD¾ä¿/A²P³Œûc)U|0'Ê­¨V/³µ"fÈyÄ»ÃÎ07Óë‰*· ×`ßL¯A%…åU–ó ¾jÑBªR†¶¤ Ø Z“F!où-seÀF¯éW»–{qìXƒô+) U#–‘"c|ü1¹ðþ'ªyÉ9ƒÄ–Hû,þ¬µt PféîZk³ÖJP(í‰"µêòÕÓZlâ[ŸÏû÷¾Wö(z:Õ±iè°”Ú»ö˜òsdcG]%T‡nKK“s!N[ÿAíiGY@yš³;¬mO;ª±«æ^[ÎKQû¤+%<æEQÀú™锿îkóx}¾Ö%ÒÈöGGÔ&5tÃðžgçšÌOŽÕŠäôšá¬”­¦éyVªvÁ¬ªû¥)ÉJrM‹óFY(×´‚‡ŽAz´åºôhË*Ÿ(Òd¥þ8Y©§ÊJuÎG f¥è<Ú¡'¬ûA³CÑucNÉ-~¾¯Å sÒo¨jó•}'™ß*òû(’…™ö/µy!Ê´.Ó"ÍÔ fZ—i‘fG©Ám­w™©Í Q¦…p™)ä…¼ ꦆÙè ^ÿKrCTÜË– ="/šaÓÅR$󳲇µ½;‰®RÏ$.¾ê¶í×Ê.M7Ǽ©,·©ôúñZ–»LHºqëv49)98ï«j^í2%Lýœªƒqí[›¾HQÓ‚;ê[ÑÍ”l¯¥ß 'nJô¶ ìí‹,»žy Û Å#×)Ùö,³,:uJ–‹}GA§dÛ·k<äjüXŠŒCZ t 3l¸â-îía ®9̨ɓeñ‡5yd„ d{ÈÔ~¿ßšUXvæ{­Ra°ÍÙöÅu܆ªJw"/æÖ 2ÄÖÒÉ¢$&}9ôV öEšÞbYz¢…·X–úDH·•abwp–eÞN=ß«AÈKv‰{À aJaæÂ6¸²,s‰0††Ôµmólû6Ä åêÿèp¥V¹(êw7ƒ)ŽAnÂFj$—s÷u­^ëüµ{Gf×d9‰±¡E{o›*¿;wÇl-cù-„!X­f9çj­Ý‹“¾Œ\æJ‘i(T¶6솺®h¼ÙÒØ²ì-q=•mܨØA2oLli ’,dÞÕ§£È8à #QXnˆíJR ]û^?¿ýK–íú¯â°*r¤þšæ;¼?7ì使Ñv͵Ï_åWÐk²½«eÓå0ÿü\äCáÜßè]*JÜ;‚Œ±ÛÊ^;n[åvb¯™‘Ù¡}YLí¸mש\¾Aⶬ¬ƒËؼě CV°bvnÚ·t¥ØWE~¹œ¦+_ãþ5 2BÕÛz ÓÃWFU$` ’…›£éÝÃéÊ—swº2×éJz÷“t¥ƒô¤+…“®4È“t¥óœNô[™Î£ºþM;Y…_¼ýnF¥JÛÇPdäÓ[k”gì\ü=“šµ¬_ë»%Èø©<Ãôš¡äžÚ=á9YPϪSzV_éW×™å9߈ŸÑ–Wyìdì驨A<Ú’Óø% Xªo$WÛe¬2ò —¨Þ´©!È€¬'v-⸖‚¨:,Âq'¬k¤GA8î„¥‚ òl„A¸Ó K“X„ÛNØPç&<çí/› EúŠõÊnëù5X¬R¬7HotGŠõÉ&¼z0íȰ~ÝB, ø5:'*Øy„]‹½4òÜÿðœìÄJþ+Œä+ 0šùSÂw¿2b&áòdZðáÖµèheW)‚Ö@ïN: ÁO1jFXi¯Œt@Ó•¶yN«óO³ômï¼Qæ]½•í» ò"³È÷DÿùË‘ÌÒ(2ËhýZw¨ŸŸ•«³¤ýJ>Å5Ó «Ö:à(qÛÝ+¡ÿm™ÓA˜7Ó8ä°o_9±4P:jº™¦~,ïú!>k^¤µ4P²›©€²IßÒAÆ`9®ÇˆÊýºµÎÛü1ÒçLp—gYWû5¿]ù¤ïžbóƒ-z,¿JÎ&XA¯œZ(ƒ#=î6¤¥Tä NHEµKt-ùoìçþAŸ“XP·•ß@/jÈú»•¹q¡QÐoåpU¶KÊê=q; NcþÖe" å>'õq)æuj׊‰ÈÌÞö#Ó x€øLŒ]X\~Mþ¢Fé #oO¢âò,ÌÑ4H¯nï²Ë—‘ i_ûÓPËåÂ\ÍöåÓ åJå&1R$ã­†¿f>E[Ó©/#¬Â޽[€Î£öyLçáȃìHWÇtƒd¡.p+˜Ï£Kþߨ¥4&yt=‹›òµƒ»G,Ây#¡`pܵºŸiÄ&? †AF~õYìti,¨> r^ɽBßZ·Ò¾?¥Ú ëN¬àÈYÌ!=iªÕnäÈYÌKµ[[Šä$khßÚ¹à9c’=²RQšüÒMÞdä·Xz#â¤A² Åx¡$7ØþH¬ŠÐ<>Ÿv¹C]«jeÆmiÃg)šïëMHzKE#¦Ù¬¬ú¹°£.¥mi§á,ëkVÅìÜÛv¯ª„ưò[`­ËQ×ê¿úÿÜ©Lßi|÷÷çÛA&¡“Šm¼àQv¢-Ší$xt ÷‰“vÎÎæ»<þÚs±ÁÚ•¶·£]†:µûà“JÐdG7ñÈi´ç8;;¥­2b´ÏŸú¾€¤ÃÙY)>WÂþyÏsÄ’žû[øê‚n:gAeyLÉÕÞÈì°Ç™<èШ ÉcdXMù.P!áìv®>eG2»*$J…²—#Ô~£Û1®ß3‘Ë«ýÚ˜Û²8qýºüÚú ñ²µeñë ×óËɧ(«ðòk8fÐzE°òè¤â¤õŠ(2 ª8ý„ó£2ƒµ~ÃFóœ•äÆF󜇔´E2š7È€Ì 6š7Hìûlhà ‘ßûY~N~yýì7Š™HÈn®÷eÉ[‚ Å`ŠL¯Éƒ«]yÈ\7,"gpÎÓðé\,j‡ëÖF”åÂ}9›0K ã< PôÕ#¢†qž…¨a¢%Ô0γ™VL ã¸/ÇC ûFÙ_¨a‚>ç 5l ×<¡†­ôš'Ô0A¯y#Q¥7 4Øq~ ç„”Dm'ÒêA<"ušèŸ EÒo¤‡DÊ} ;Ž­8Ï4 o_TP]“DTPŸÖ$”£¦ˆÑÌFYo{wË€ø³è\‹ÖìÑܹø| ºÎQ‡"¦år³Îw¿ïò]rÛeþQ:e­Oñ2>^íãcsÕÖdÇ/” ìŽ[=cBä·Ño9½–eédÎâ˜v×=ödC9 ¯aš~0;bT“<ä§õ×QdlÕv;εy¿×iþÂìˆãU}ÿ–uA„EUo‹D~îà[dæ³ÊjH9G 1Çz‚\j[صã„ÐÞU%gÓ'SòÑs1¡y”¾Ñ^z¯?Y2#'>ûÖòÿ–õaÿÏìP?Ük’kû\ËÅ~#ÛQÓ ,ƒé©F« â…¹et]J‚ë’h麔×%ÑÒu)¹„i›t]J.Á¹¹å Ž”\O±• ä!“(\?Tr-ÀAàI¨~Ä[Ȥ‡±”DúáKÕ—e€h-‰Në‡Í˹»·~¸èú¡ o®íÛZ_YË9*õ,ºI,KkHÒûRQ%BçØgÆõ² Bè·¹VZ,„ÎQ›‹yΧµ P±"¬`I|hØÚ¹fã" 6é­f,J Hâ<‰OöMUÍhèÝyÈÂÛŸñ$ ‹…´ÊÂ"«$=•±zÃ<ÉN$° Oþv~‡o”^–²Ï½î£,§!úM¯s‡Êè6}oóu¨‰Ám8è֡雎^“…ÎïòhØ$YøåЂÆÓ(|†U§rÑQ¤É­)cÓÂð/äs>䟙¯ÉŽTzu†]”„rGÜÍÆÔ»u;°çxÊÎìàs+nÁQÇ¿å1È ¤üTVdkŽÌiXT¿Ç·¥5ž&Á²&༙&^å×­ÁH)Âê&á¯üF“Íœ¤X^B󾋽‰¡”kÒü†µ.MÝç4†ì:%Ïœ­Ø‘ÙÉ ºéÑ :Í\^ƒ5Oÿ>Úb„tšCv÷¬]€ "·ütÍÄÔÈ­Ç]"¿òæcA±£/¾gò‘ç·üôãù}çwp â–Ÿ~4d¯åä´,ÄO÷²·Ô oÞ±ôy óöŽ4lc1 ½kS$Ä´Ö–Zh[j+wÅSGŽ yx)Fž­Üb&;eäÊÀz÷… ã#o° »¹Œ¼gÛX­-Ž˜ìήÝè]­!7Ób‘„·üô–])^ë AF!ç1´e×p=nÒ¦$pÍ( œ­N‘X9›gìÌ£ )gdHoçü—Üg§+@B‰gaåÏN)=þ=Ï’@‹¹6¨”™ÚHÑQâKŸ;ÄÏҀėÎý"‰/ž¥‰/-ºƒ$¾ ’²Är…(=K½ûÑVÀ®k<ËÎ+¡«ýF·Ó¬æ“éÁ¾9ŽÁŸÚƒ5vÌ#Û—©1¾›ç48×d>þÅ(úi>ƒ ¡á}Ócpƒãd«/ÎoÑßâä… ÏâdzM??HqŸm$pc'¹Ê±š;Ønü¤Ú"GÈçâóƒ¾Jk׾ѹ֮íá·S÷WU†žšÑh¶Ê8µŠ÷çóÜÅ›ù- ¶Ûnz0æ± ©Ë¨Gê2·ì¤.#“}£ì¼åeGÈÙ~ïuM¡±—«´÷ªAu7¹è:¯RwWÈŸíÐì˜fÔ…Q”fŒaÜI3*bJ3Æ—`ˆ»é Ïz;Iƒã4£Aò°+å^À¯—3b» ŠŒBé;|ÍSbž<ø/=±/zûWºF'‹Þ¢½† £0&é•…—²òµæ?XÊ®aSµE‡£{H#zóa:©Ã LjÞüç[Ó ‹N;ûÝ-½ù@눦`Œ-‰<ä «)_ã o©²çè»;¼QrJ³ÌÁœ<¾&J¤Ò¢Æ¦ßñõLyÛo ÒÚnoíæjcªõ:? 0_qLšK#ÿ·Võg­åQ‘"#ë¢XÈ·•'Êö› A¢rgi Ír]ùó=Ñkr»‰ìZ¿ŸvüµÏ:wž3&Haô–ä¡aª›… a»¹[x'·›¶(¾#A¦vv”æšêŠ{Ѽ(2³ªúÛäÐ!Á§*Öv¦È›¥aìŠÈú9ûЮöþb=*žÕö‘”Q@'¡{RèC+C¼ªÆ¢ø½Ÿôí¯¨Køaø~ú/}MŸÖ2è˜g•oõ˜¦;X_ìPÄ ÜUHDõ]¿M“ÎkŘlYîdËUT#èøîÐdc[b—ð¦Íû\.öR×`²™ͦ-§o½¶½óZÙ½›WN(yójÍ›»3øo;m…<À8T¯Êù¢ËÞ!_ìFårzvC5>>•3Q¶¦Õù¿íµÌ³æãº¾«…>kíPuÕM ]_µl>ý"¶·Â¢±ùz¹ï(ß júïœä÷øÈóé¹Äº^µ=(¨m÷í«šÄkq^kûZÿû³½Vµ­Aü÷YÁª½Ð²ÍÖCѻΙ×Ñÿv5Ë®ªLô•Ôá™ßSu¿G01Ñhb¶ÿÖ}úšnö9ƒ=Y¥šî^keGhߎî:çÃŽH(Wkéí;¿§²pV  êKÙµÌ*ÙÁRˆEèÇùñ•BwvûþÓ8Јè§Öô­x}¦i¤ÐØ´R¦ÿQ^õÑ–ÛB¿‚81 òÅVÚ½?bžÑˆ™Jf‹Wð|”*êû”Š©_(”MØw¦2ag×Ü+É¿vvÍýž¢*£kØANž4¥v $¤Þì"€äÎs¿†µÁ¢‹°oäÖXD%ueùÐÝ>âô8®Óãmõš“‰|Å.ik±UŒËÒdtf*ӿƦZà…F©IéÞ•¯“jÀaQì˘i5 8¹Gçùù—²wØz4ò‰ß‚Øe°ˆû*»¶éˆû»æDˆö}Ú'â^%$1=×︌éy›’pÚIÃrè|¶#ä~Y”tn4c^l%?Sùµ¿óT@Qs¬%§£Hϯ,2óø‹'z<¾]³¬I•æk¨õ|G{$‰è ¿u2c·#AF§yï3k˜5R:á#È<íJ‘ þŽT„²{xݧ¾ÕA Û·/¥3#ÄêxG³ØQ °ÕÀ±‡Ñ»ÝEbï÷.™è²C>Žƒx;]?Z‹ G~ŸgR“bq¬IõÀ*bÈ"æ¨TH5 xö$ ´I5 ‘ #ãî¸$ÎëS·‹QîÑÈØÃ¯·™c¿ÚÊÎð>´FFÿH}GÕÖ¶b5H›U;v½R‹Cý6»v½Y?1oBDejÎÉçéuaWçä½#ž”¬²É>+óDI ïJÜŶs9ùŠ­»8K¼nòr7=ì1<‰]sEÑÐ8K"'§g²Þ];¬ßv6¶Fžv>tb/\Ö;EH2 §‰€3ÂXHC…Dª, è ö£ÖîG,ñDÔoQ7éá®îõ@g{‡ì´Ç{c~Ý ºw°³Êr¥í°°Î cÜ£s£2€;ÀqîjÛMÁXê­þ75I¦±,4Cp2e‡T3væ±–PŒåK($–PŒt†cK(qcb ¥‘±×í½ÍüK¨š"–P2` å O,¡êq –P°„‚"˱„‚¸Žå!K(iÈ[˳„ªé[ºF>‹çb€e„ÿ¶àÀaЇ½ö4®¹=vŸ0‡)³%}>·vc÷gï» 2î_pÄ"V´vóâgÙûÊ4‡£}õ<¡¤TWKã/”'DlÆ•Òè™x•4JxIʯ¢Y†²Ü2'È}M–ÏÞ­ÛÜÌtä/ªµ9äE¥ã$½ýU;­þ»?“"%Ègê·Ïò¼QhD ¯=’Ðù³Ü+ t—Û÷9ùüËGDx …&ªìaö¡z|_çè7µ·•*rx‹oÓ7ýHßþ•c¨ZpåU×ÙZu¨Ìýç*¼Uté÷S@3¦fª ö.¿Ýðçýq¡ù ‰·+¿Ïõ"fö_À˜öQê:M=‰_ð­§»Uoë¿¿ º¿-9WåáÿI¿”HÛÝšWƒU4…3Xª(¡º¯çàvŸ¦¯sÕ„@•£¦T»­ÓBß–ªþùoo´ÔI49]šŸÏmr~‡.×Òøt–k9•b7ŸšâVC½åïbúöóêü€ 5sK瀪*(ŠŒŠ©œ%ý²ã ªƒë­G4µ² ÙRèõè_6ß›©­*kj¨xê֟þýy|ÆÂ™.ªøÏª)W•¡ßíün‡ax;ÐÄÔÁoÊ—A.ßbnžãÜÒu ÖE*ŠT»Ê|¯›e)ÊÑrS—Pµõÿ´õp÷ÅÇy,U]—”¼˜Œ4Eÿó}þ¸#™‚ñþÖº ܽç×·r p|³ò?½­qcU³ \°ÞÓ„æEû3—Þ@¯ã¸j4hPL‘úŒj<À¬ŽÏx€"ŸË Ž)²@«ï®Od©çVIV–¯TÅhóZ”ï~gv9H²™]]¦"n"R!ȈÄûûäñþÚnO~ÕÈø4âþˆˆÛnW’oþ•Y§îû9dÊN@Îçú¡cŸñ1‹Ý²‚]=» úµG‹¸Ëýé1®™Ëi) Ñ“®\n¿ÝlÑÈS’¥r󂦒ìê%Yʵw"¬Fú$[F1A‚<‘ly+É–{OŸèL²eÞÞ"î½oôš§’-7)Ù´Ô’-rã3’-s!B„›%/jdî£=¡è8‹<âCõ.÷e·XûO2õÎ[Ì’ØtáNÒ…{ûD±ßykzà3Yæ”" –Rò$à“º¾z›"͘«ZîQÔÙ¯e '­ µ·;H)§ÿSOO‚Œp$«»óÄ5ŸëÏËþN†bó¿(àÈñ.æ(ôñe Åæ&:–{¸úïùCïÎÎýŽ|­ ±ùýnúãÞôD®‹u$ÈÔzš>L×°ÜëEh0PdvDö".šÚùÕÒñÌ‘äíÓ0ŸYlóÅâŒü…„ê5nÅô™ßoúHº;oÏU•`Ñ5ü âXØÓ5±ÿªÖHmEYÏ庂¸Æ¨9ú½Äzóz }£×CÕá@B·MüùR(;…vÛ,SvŠû½ÐïÕÖ¯Çê «îÎûO•-ÁÓ¶ýN¯ûæüÖÌ7ùgL(Nþ©†n+ä´ a¨Þ2Ç1¼g;¥ƒ)FnÕÐÛ†èŒ&¿ù úF¼(Û¼œqïäWŸÉ›^“û?“Ç@é©I°X¡ªÍÎt0u48ÅYçöü8ÈÜJè!›¢¾ÎÈ_ü߉!ÏèÕùNTZS~'ó¼Rh„‰bð<†[Õ÷t èäG3ºhâ™Ñoñ‡êõ$x–q×ÕÓJgÔ•Û~S<ù·×Ou§ÃŠ[SK彬~Àë1®O ÍLQ”~ÓÝkºõÎ+È¡/r'x¨qŠa~ý`zlj‘ÄÛí¥´­ëѤN&hˆÇíNžLКå‹C¤hIi³~KŠ>1Œ¨«ñá ={éhgß~’óx£F.BŸ>XÉÈÝ<;¦O“ ø>?Ÿ[·@ëO~9!®›"ß&6a9|qÍ._Øì’åiÈZbkjyJŠÄG¼ÙÕ-9bǘ’å©{^ÔaÑ\uE÷lÁ7–Y£%X ×·oè5ù‘@ÜíâͲÎòôhv ¤àmìl«_žþfvIG)?Ë¿KA¢q}™ü{ž3õÖöÉ‚³<÷È‚ïU$ ÎòÜ# .g–gy¨–ƒeÁYž{¤ ´\,œØøåò‹Wò@‘ѱ½UÒ›±¯1'tèY±Òœ€96E¢¾Æ²• ùkä¹ñ5ÖÈ€¯ñF¯ð5v_cð5îéï øot”ò3[·ø›‘÷øË×ÁyI_cç—^#oïÑl_häï=’´qH¨pä]å.w\î¦nhƒæwµƒô+n=EÆgK“Ô=) —K#“S]ÈŸ¾l| I _¹@I/~q’ ÛÖuÙ~Å¿ŒsI¡UmÖŸçð½o.Ùíaê}ÛV–²ùɾ#Fz å÷ñÐÌåòõZÄq‰Þ=ÁÌí ˜ÛíÐM½;”íÏ ¯¾Z»úg2HÔ0±#ÅíÞÓbÕë«›XÈj‚ŒÎÔœ»÷ãÑ‚š3?ºqšóJô×4òTÍy úkyªæÜH5g4CR7íd©³{_` È,vª^ýftdø% R|­J¿ä¿¨Rš´(÷¡•r½%Bóë…´ª(u×¹«»Šèˆ½³7ôTºeAölt‹øê(2ò¸Án–!À¯X#C-¡µ.îÊõvä¯ñA㞨჋%¿Ó@Z.¾í<¹õØ:ñéà æüš|úÊú …~MÂ>}m;dì(ô)WÉš”_ÙmR²zUTb‚Ä«·Ñ÷ïÅ9º^j›ÒŠ­uíOU¾·® ùÀ;RÛÜ:µlœ8á^Ã^*Œ~¡ÈÈ$5mt/nlËüz=» ã£;¤¸¦t‡,6ŠLŒ6ÊÞúSk¥àåùþ©æŽ ÙñÐ'ÛÈÚfìÝÓãioØ5Ȫu€uþè‡TƒZY)UÑ›'Ažú”ãK¾£Ôõ pÜK{øYPøÀ*óëq !G¹ÅÔµyt èFÉM΄ß<ºzô±;$G ÀÃa¿’Úöî×Ð57«íʼnÒQo±ûÀÅa½E8&ð(v['!°¬†flÀo†GÔÓ™8ú}›{[:È_cÙŽÙÔíà Ù©6âOßÞ¡š­‘ÜS¢”ê„pÍä=;“jàûEÏ®¥ÈèÌ[«é?¯× htÚSs~ñ€0‡lñ„/.JC6[1@ü‰½‹T)U§Â´æµ=PDá*B¿r¢ªšµgˆC¢Ìi|î/S!ÅDz·ôš1ö[¯tL[¿—{;>‚Lð^ü4Çâº=Û‚ÞÆã$È´Áãɼ±b£ÌÍÛŒ¹Ÿ›Ñ?z«`ÎcP'” .;òÜï7SÈ"þ #Èä)ÖhŸ©s\ MÜ:ÙxÞ¯caÖUù, i“äsijq~Û§îêŽ £ÓÔb#S‹ð½3$¼å¦¥ÍeaÇÓRwhjQr‡OõÓQ$;KÖ{ºÎ\,±ñ'eø×-aøsäß³‹OÉã»N÷uÿý>íqrÒWD嬦Ç0._ûŽì)Réò™8¹Åìl«·ONUÑw¥E•þ•£ÍfßfJrVš %{>ë²|w(IÎì~tB5;BM‘±—j ™œù÷tÄ¿‡³{%öïá, jˆ[ÅRÎòPÃcmÕÆ9¿œ¹ ç¹þ;¼LÜ•aP¯u³=ëÞ ClüyØpK–;ñ°y¶ïæ'C6‹õ°ÑHð°)öäÌj6Ÿ­ÚnM?Ü2ñìÚ:s!ªžñüÓÜ˾‘tchäœÉàé»=DZhò4?ßÌŸZ¬#yžÕ¤³Q?zþUZ÷¹#šDœs&‘áí7륊­Øž¹]íàþ{Ñ/Eú4‰Š¾6dNŽèjË_KW“þgkólË}v[â<ñ –ôqŠd'ŽuKä29q¦qš(wGXyæsp”úA·u…5„g!e1ú½&x„àýH2ÆÞκüàü¬ Gé~ŸddeþLµeç¬Mi¿8¤¸­KÆêî{ÛÙ“)ÏuS›»ÛO)ÇÞ\3½Ð}³4O$ù–ö^Ã5 Í4¼Á³·ŸõÓÁ;J/‡Ü/’Œç#È38N?Ä=}’u„û@'¾¡û©§Z×…^3öùrú9´ |öÚ—}C³x~ýÅ1 ¾wÛ„éqÌr~ǬíÖdÀ1k£¿3à˜å O³ÄÒI³42ód‰žçÑ/3"ê<¹-"*>·M˜ç.\õ@‘ž™Œ…8nפŠ]}G»xÎ}Š]}G»xÎ=Š]2“Œ»xÎQì‚Ý0ç¿(vA”ó_»¤_± }GÀN8U´úVÜÛVºKÿK}+˜!™GnF!Ç®o ÕLK„ܵ›µûØ'Ê|r3}Y–"ö…SOž¡Ó‘éÇn—Íæ?sëxÖñ‚*à¶]SÓ’ÔÍÅ5ÅÑ÷ÕËdòÓËy~þ¥<k»*¦—k¨.ƒ”°ÒKȺK°î~ô¬2zµ«Ì^mêqpÑꮨRŸ^’PM iw¦æõnïT/<h¥É^8³[{Ô‰ ~§_R‚š¦#H'Ï Ïqb~Þ Ç’:.N~ik Cž\À㨇gû†ügŠ\HÖ¨ßñvk!k”b—½_Ѭ!Ý«›áÔÛ;¸¬ÿÛk=¯Ý`JVëb}5Ar“»Ø¿ÝÝ'¾qÚœG‚L}•[çJ/y`Çkrz½DO6$n•^¯¾ïH¹ÿÚïè8Ãö{ÿgkñ©J­¹—Æþ΀º«4µoAF>Ri4œÔvdU{K*M¯,àf‡ë†é©5…ö7% }é5õžÊ;¢Ð—^SÏÝõ{‡_Š 'Àå]¹š5ï¶« •^Ñúù¯¢G«V'™?iÆþV5W-ÅíÍY;Eºä»ÜDk’'V:ðÂIQÑÁwXÛ¥´×´à_—«'Žù[kâ:Œ òy0É?û®ÕsÍä¹|LJsM†, Ð݇¹)(äVKŽçž¬”ãÙ4u]d¬[×Ò4ŠCHäš’¾ ?ÍAö­™Ø&źä1&,r”F<ˆD+êá9ì2óT¢½#Ê‚»Lç"£#µGuÉZjOŠûXܺ6¡ö¤XÅû÷ÆÔž©x»ª¾ÍÏg[>°‚¡Ž—åêdVR» O3þŸ°k[’UU‚¿4ÝÚB?î÷=û|‚wÄûÝX_@ªT\1oØ¢BQ••9.y».É«¯&Z#@›ûN²¼!€E£4ŽŽFJ6ò-ÎÒéÐ%–sok2Œ|%c#Ç,³¢‹1Ò»5@ ×h`yƒþ\—xšPRxžCRmw-’j2s.:ÅPRxž#OkœzW„t9Ë‚æD8<ç¶;Žš‰ç?æëBQÏÍÙ“”“ak0òFŒAvCH1ÛxŸ'1†¾4Lôï3Ï[8löý Noêg"’b‹IŽ 8{©Ò®”lÉf)C3x°¶û{pö¤¯JɦÎÞ{€tóµLÑnsɺ^J¯ù¹e%åƒ8ïšHÕ§3ÄJâ{Øv—h$qU¯,ÛG#)òu8Dbº¾áCk®ÖÏßÌú¹gž‹nÃpBÈ·5J´¨Xå¶%çé†Çôn™¢bkªÕüNêfŠŠEqµñ’GOmˇò/ªª¬j¿FzNѽÒ>͋ʼQñæSšJåNô®Úñ™já䲿¸1kÿƒgiéÔn˜TI¾¶GÅA#½#Jß»uö㙉áâ›1Ò‡‘ª]Á`m—ø/WVSîÓfZùиÏ]!EEæMö_½-{e#ýûVhÈŠ'þÛÁŠß3ù€Oü·ƒ/ˆO€nþµ²â5ÒHj %,ô1§ä@zX©"I5)Y“1ójÒÊ´è÷S";q–bÕš!¤‘ªv–ò$¯‡)µÏÈ¿ó?,*ˆ(;D 5òc4üÔÕ™ú+¯ê¨DÈ"UÎJ^}™'6ã«“iýÆd;0Oó¹ÅcR£õ—Â3òÞã®Mͧ_ è:ìºåK…SK(*¯­T=wqó]³ŠEª%å“—3Z(UÀnì‹Z,”ú†Pe½!'ª¯»‚ žQÕØUÖä•3Å»ªñ³ùÖ$:צºÓX÷Iö§ Ð&jÿìì ý¤ú™ lèª?ÓW š.0Wâ·ðeMN£ZQ¾TóÉßÚM¬¯ó†u3†Q¾HGmrꎅS5ÁךӥZ”—Q¡XùñÛÿ•öŒ9]5ôk?à×êý²ætYzü€>Yó6ñx³”½Ï|°â¶êtª1ÄPuûýWqýö¬íÌç>l§íü¥âv$}°`—,ù ú]F*ÒÙ¡“˜Ychp׌5ˆªÉÌVí0NÍXÍÞŒe—^ßÙŒÅ÷f¬RÌîiNÝ”#)ícQ×öeõQÇóå lʘÄÿ\ÊGãTÊWUlEÈ·•LóT/?¬K†º^𘞕.ŠÝ‹´Ächà Ù•<-Œ´jÉáŸ'®žˆM§éF„¼·%,Å~²ôBBéëôW²¹^J|GÔ™$°Ç ßjTÝ& ÒóÌÿ8³ÓiPµøÝ¦ †ïée+ZÉá]ׯQÁ›h²Ðqêch²bf6fÛÒ4y{ÂØåÞf{S¢,dX$!KKjqÆšcËú!Ù ¸W„ôîÎ"»0\hïˆ8ýëmf¼öô$Ò~DîÅ0‹+³„ 9¶éñ’le—$M¾"¤lp³|î£!ýãÌÍ ·2Ÿ§¬ÃWÿ†¹ºN3‘›tÊ{§94sO#B4ŸR|  ̧áwœê*R@ÖÓLœûùq3•vÏ©ƒ‰L>¯gÏ)Ã/ÖH§ç¨B|@Œ—E Í÷ýgÇÀFV2Ž‘¸{~Ï¢)¤e‚Ëè¿ËÌõ¶{^#o­Ÿy_ôÖÓ‡|žzSvRfƒ7¦Û6Ý6kdß_L·™sZò x™RŒHÖTœ—¶¥lÒCg;¦O–H¤|pÛöåìÈp*xŽïS½¢8꼋&„ôœ"Ù•}C.Û1–RžÍšüù ¡”‹’r3pЧ1‰Spx0y¬ÝŽ÷®tÃ_p–KN(F~!ËõØ8·­+@Vò8vÅ];Bƒ¨+=7ëR•¦YÁ@?YçÍÞ1ÎÓP•é_;Ý%2îte¹üèžoÆ)ëç}›óI¡ZÆøM–úI›IÒ§x©®÷„ºwä¾™L— IÀÁq(ô^̺([Œ|»˜ÝcoÎ\À$àR…âxef7¤ž‹¯-bIÐCÈÏ5¶‘5d©â³á«·ÌîHªøœ÷|íyWñÁW§® +ÀL@7Ö)‘‘ê‰%ÙŒùqžô¹øBÚÌðLA‚Y“î? Çv<B‰µ(¸“×Úf„‚ŽR¤p°»Í…Bƒ‡µ*<èä!V%W‹·ƒ³ŒºÒ ¥Q:”©&ôëè|e: 2ñç÷Ç¡W!W¨WA@7Ãõ{‡zHJŸsM.Öå¢9r–ÑoÔ† ©Š¿^Ò¥[ÃÚøzXSDš—ì1Ö'Å&‰t =Žw/¬\ªò¢ÛŠ´2ëçdNþ1VX»=hšVåÆ+B‚xéÈ×%kº%afì‚4Ò·¹JPJ˜Ë¬K|õBe,&Çc†í(ûƒÕ"»yǾwb×ã¬-ï(Žb^a$5êMÚmÏuy,;Eòkóó ŒÂx›„ßÑëÇñ2mÑ)…Èñ† C_z”Gr±.Îu6bè˜p¥¦Þ7—ÕØ•x¢^È…éß*î*KθÞÛü !–OÛÄAúYCmdçÚ·oëå`GÖÐûªOа¥Ç¯Tüßs-;4§b+ÛÓ 4Úi;û¦,.ž‹#]tú_P¢±?`èó*7+¾~ûuá紱ȌEŸI—Ÿ>UøQr[¢¶­ÎWü´TUBå¨jåÙGMy7ž~€gÙH6³žŽ­ˆw&žF%&ßµ;víXé·5 ?AéÚ7a³¦)O·…¼©Ù¡‡ÒÎÕ”„ø·*+:]Ø…Os)²ŠE¨+ñPVt*Þk9j8÷}}ú­”Ñ?@6ô‡E=MøÁ*+:y ‚ž5-“4ZðƒUVtþüïHM*hSÕâ=;-¬Z=P<‚Lò9 eÄÚˆ}ê î ï2ð²/áÁP§Ýd ?šäÏ÷óÜd“ÒßÏcÐÂMÑäûyhŠ6–øêWC›v"°Q IKåòTL¿)[|É5­ÁtûB_gíbȪ_â bEÌ·'Óð˜î v³Ë*q±L±,ÂcºƒX[Ìü7Al_'$¹•¢” :ãêK¬ÿET`E²RäK²Ròˆe¥ˆm)»it€²RäK]¡©?`X!¾‡Ö~;>e Û¿þ5G<•P’ÂÈ"æ<Ïœm¯¡?ïqMmoy<>„²¶2ÛÒ•¤ ÏŒ°ÓQ8_faÊŠ‘£q£ÊèÆ‰B1òsÉ2zÃò}[^aE¶ÕÜ\´8¯ª@œjzøÀú¢íÕŸC}–S$Ž„ ÄÓ„Nôç91Õ'äSA/fˆY§úC¥O¹Úô’ÊÒ‡r¡ªõ—%/Är_iäÕÕ·©vP±ÌÍ’˜€S&Á´ÂPÛþu‘ÛeÖ’ºd6#e¡‘ß{ϾYB~šù—NBo²Òôu'ËÒ ÙJúóu‚äÁÊVj¤« ˆ­h¤çòÒ°„{úú‹—†!ÜS °~%¹,€p¯‘÷„{y¼5©nô+àaJ_Y™L}½oöCuÊãé&KXH@«ý«HjÒçµx ÂÂH¹Ñ,ÎÞÐJÚIR,9ž¾pRÇJU<Çe4iTôom‰Y1$ó€¯þ1ßœ´IØãf^ñšfÕÈ2@f*įŠ<^»ªÄ¿“˜35ßGUð¸•o>Bš˜54¾è¼JŠ~žó_ýk A‡(a‡é-)ÃHuüoýŸšzuj=U²ôøæ_&d•1SqÄLe²lcÆ0ô†ïÀv¾[ìíûήËudÛbú‡éëbt¯Vœ=Ô‹cÀ!äû®?³Éû^„*~™ž(©¹œ•­ÉeR Y®˜1VåmkVœ×ÝÂO,¢e™oÑiÌàNÕk•‹Ce¶¯Wà´F‹#³½jôœ8> dSÔ¦ }aÃhWISŽì]Ø}i–ðW€ï=ÎÓY³XE¾:È—äZRæGÈEf }Ù.­£§Æ«>©8L¾Y# 0#ÖÛ×nFÜfc‘šçªƒ‚øµØÀÆÓÕ¿wI–`ûz‡ÄÓþm9Ú¿^À!ñ¨•ªlÁÏiÙ6íiî_·¶\®áŒá›zÝ.â»>³¡RPß–`S³3„Å< Õù(EÎÿ47dÆÄžñºÍ¶ Cƒ»Í¶‡Z°Ù¾¬C¢€ÊޤìèHb}4ˆóÒpš,ê²Ê°‰g -p♕*ñÌò&ñ¼KÚ­6ñLï,€©3–§ôu#èlŰ€– ×;òňeÐ×÷I`+†!]æÀ©ŽÞ4<«ÅDò¸ÛV 8È×…ªypúpÊ[#OCAó’Éû Òƒ¬g#“×tmZšw5<ÿ÷wäÇîbG6CD÷Ûš[Qjž/NñC5MMeÞ%ØðüGû€ërÇÐ÷K³)M¼•Þ[™8‘>¼®Ñ}³qŒôÁ^Ÿk×i+Ë54]ü\õªYü¯ëÀð˜ªPÿ«˜þjÑécY‚jEHì~·Ÿ-ÄžJK½IoËÚF’I#¿.«Œ¥¶÷þ« {{¶ÊˆxmßdÏM ’¢Hܾ!’ѱ¢H\OùÐV'dàjÌnj;Ÿ¾{û–íÖÆC#oKå ’Ñ¡ïCFG!­Œ}ÿ%f¬G4òAFgÃW¿ÉŸ‰oÉèhäÇAì­+Mþ¦©r׫³”¦m×!ß®½c1¢ÆôMVZÙåoß:§€»üÞ }߱˾¨Y=ä÷IšGÜúŠ‘ïQc)ñD©÷ó`,-¦¨÷z0–€SÔmk¡SÍ,yOÄF9M•ƒÚ&ÿß?¿Ž¿âj2Y\=(<Ô¶Ù;iŽzþ“e:¢Ð¬âD(às2-¡ù6½à’‹UçŠ]„7SÊKª AÒX¤ý[‰žÃÈPÄ­Fú¶p—ëóìN(ûÕL°\·ê2µ3Ë—Åæ¥@¹þŠªY·}ÞÄ=“{±õ³g£ˆƒÇ²Þð,í;¿ÿ“½‡RQd/0võ\G¹ÍzÁU˜2;DРÈõˆCdjÖ€ÈõˆCôpÏ›?ijÈ/vêÊ Àä[l³÷Ù  ÙÍzûu|f\›0<æ@£ÍNWw›˜J…F~î2¬Ê À<#ÿçÙ €›LhJÇÙ;®ÍNÈ3€F›˜;²MéŸQm€Çt›˜~G ÒQ€FMÉ­U†!âQÿužVÏh’äý2¶‡nÿ}‰>lLÂB¼xvæ-©SÜ’€“×Î÷#Z7ˆ=¬)R ÷Ëï=Þã?EHÖ²ÏÂ!‘ùWU(²oz1¥S4…¹Ï§Ø:ö1 62¼®+¾£Àe«* Ñýf>·ÂÈŒRÈ4ÿ5ݦ,{v$}ÿê.e#ULéË]$Pæ|ä4}Ùe…}õ]Õ91æ$«s&…rjL<™wS7 w±¶ØdùJ>ò²«ÍnU f‘KΗ95 O°¬ÛÙ(®Ú0Vçd<¿#K΋òOÊ”lkì|<ÅÑemf~'ù G×ä@ç×}¸9î~èc8[Ìzò‡9«nÃYú>ó~Ž8½úØ0}@.Íy¦¯È¥Y#]~&Ì*Žk¤ï:xØŽ¼Tåúm]€ž‘ß?ЍTxå;oÛ€‘@ëÈ8?ÏaÇåÈéH%æ°Ù†-ç—1ý«§±,"6Ãbeèóï.‘’*§?Ìù:¶£9¢Ø¾3£Ž¡ô&¥¯ïÜ%͘!ä°Ÿ Ciš».IË!=§Ò¼ýŠƒCýnï†g#ß÷ ;©4o àxs§zÊ¢Að¤\%ý ͘äQé“ÙZN@0B1úd¤Š|[Ùr¡zöÂJuGÀ–Ý2 GÈ7R0ÒºDýG[e¿Ž/RV ͱ|w}i–pîò‘;?l”re"îòFë(YĆ4T¦§‰/£u¤”Vö1¥ü5B~ Rë ä&í"8BÞhÉ«—s•Î1B*݃CƒM‘å˜Ñ`ëXÁ×jª@û½ïŽ7Q•Äù½êÉ«7SR˜D­žù«$H:E(V¼$0hOR+l¬jyPá'(âÕ¤*Ï2V!‹Ã*n1ÔȲìÁ]¡b‘<.·dî3 õ­~Pž)a&)ß“ÌuוjÊçâ¶T¦ZÜÖ7MGøI½-Šý ˆˆš±l³Ó¨ÄBuTVý–}Tü´Ö‘‚Š£+ 2ÎhÎÐ/^õ÷º«}Þž¾­u¤ L1ª“US‡Ñ·P¸–²ª ã¸ž¡ÖhL-äª”ÚæírùÞA¾–õY¥Ë$ë³K´-Eˆ¡¾áiÇêKebI©‹¶ÎØp‚~¥;;ô¾²p)¸ ð54€ #¹éí§†udÑ–áy}«M›š4AÅä]Í'(5áN¬ýåoí£¦hB¼(Ž®ŠŒ íÊaÌã~¬7¼ýXhšj® øùÒ„5ÃPo¥‰>‚wÕ¶ãÖ2l±ŸWŒwIJœ‘¾rû0½éÔvÊÞEå Û‰ïÑìçÄw+ËÞ 6š;rù"ï3ÐCIð@0û?a×¶ì*®i…KÀûýLÕìO @Lâp‡š¯?¾ÊÁ¬÷.'cËR«+ äÙõœ`Jy¬Ç`ÜyaÌ,LO6 ˜¥°®½">’}{–C‡H+ïYà|`‘1¥+jêT[ߦV€Š±E&AU [dLVðòzXÔ›I "óÄFÛí¤¤_Õ£7Õsäu E¨Œx$`-Ÿ<Þ]zÑÉÅß]òKЙ˜ þAkiç«äô¬îÿpx›ù™3œº’p:frìL,_<(çy,hÊ[Ž\%p³ÏµÞ]º¹{ çìtæM7й°×ËóŸ_¼Ÿ5}$Kí;È•ôÛ¸{Ÿ‘aükNõPÝPÌ]«rÓûžõbAëÉ+f~·¯¸í<ÏÃj‰¼ÆmçyVKJ-±ß!i•ÃÕXÖ©-|u+O¿8ôŽ8¦‘\`r,‹M+£Ðì¨×åé‰Ä:¶ßʱ¥—:”4kÌH-ðçº<{A‘Ñ·4€$GÒyž Á‘°Èp…:"rÜ{pÔ,È;󯯣ƧŠr¶Ó”¬k]°S¡sW‰¢tÌØ7—ÖÆoY…ÃsWÌó$sèÏÚ„bõ2 å[9£Ì߯ƒn ¿~%È' ç¹^~ÎèQ£..êôRÿ³7y¡ÈÜ߬F¬ oÛñ¶ú˜5g¨Ô(o6V xëÚrxùß]ªÏÆÜEºZÔbÞ½¤K€gÓ܆†Î“½dî‰6Ê}칇ÆáCy£ïÉn¯ÒÇ.,L£_û¾=ÝäÀ#„ä"uÿôÌ#N„ü"e—à"}¾«Gñ)2>B¾ôr†ˆ{ÄÙEêäiëe楱°GZÎ:ÆZ&^ú {ÄÙÛ­Ñâ«ÖûPÜSm¼Gœ¿ë³öÞíƒßn»gÏ}´éUWöjæËàƒdA‚×ÜÐg¿ü„k\»?z²H=yÉB£ 칇Æá2Äš„ë\ûQÓãl!¡ ²P–ø¥t–¦qš9y%sÑ=º¾ñßH(KüúŸñÓø ‹ÈÚÓ,m}}õ•¼ÿŸ•þÏô;ÖyuMóZ{ë° aqPU¡²€<ÄEjÌ*ñ]7ï‘þÏ0aÑç½™',~ϼj³ñûC|6ó2€€¢>‹Ïf~’3/24óc㉀ i½ÿ§Ž,ÉlÛ†ò3L›ßv‘«ÉçÖÚƒ¢~È/ŽF#W«Ï ÞÑg~ÖcUôf ´m’zÆ×¢…w°´ÈÜ‹’×Vi¼é­Í å¬ù`]‰LþSµ~Æå>õi?ÏÿÌÌÂôŸ˜áf…4–¿ò¨¿+B«º¯)^¾¢e5™WÙÔÏ' ñhàVêÀÍ×ÎHÃ/øE8'ÃIžË0&m*Ôá­se_›²•{)AFGM…¼zu“o[bY°UPî!½o Î}ÃïÑš/Æ Â1FéSjÕÙªP£5b›ž"ü7„ò߸÷Ðè#oÆ?«zGù4µ‰y-¶y€ªòftbàî²N¢x¿æ– S·> •rÕíû|붇|£»ÿiÖüêž,Q:Èêå\sQUAZ­SÅ0Aoç±xv¾Í€å„ú`î`úâ/!y›_wóÉh½£¶Õ–¾^P×f´Ú¢Ú·Íé©Ú·ÕD½[‚DiüÊ$çU0xWU)A‘±ÏઓK¥e•'Ò2ð¹j2qߦIa?ôÿ¼÷õÊ›n"Èô¸ÙYî‹ÐáÁ~8Á {³ãfg£AD<á-ò(GP….ð2" 3šôü47ÚÛm|Îók!H¤0ãL_¦ò.Ϲ{ï® ‰:¦\fjçn®½#½E¢˜Í·ÇÊ_¯ª×‹"ÉÅ©¹Ö¼ØjЉ²H\‘/H}rS)¯½K[¯™}g(få­õhጳHH±ËY2»’úŸò™Š©k’A†BK°ë\Æ­›ÊrùnæŒä® ÖïV_`–ç¡ø¬p;èå ™À‹¹jˆ¬Ôæ´Ý¥­óˆW«;Q¬;¨¾XüOÅlwCˆS»ƒò±¹}ê”:uØJÛûÙ5EQJËàei²)ºQóÒ‹‹X$b…=¬£†ª†ðíÕ¿W‚$¦e†;××}1,óº¤ç »FœçÔTÅ«–lG)Ñ÷yš \žïÛ³›9A^DOR­l7e>]Ó'ÂáÀþç¦ÿç“ akTÁˆ‘•êÛ7—÷…v¥óÉ|7©.ƒ¨c¶[þhŸÝÌÿÝÀš)Ù‰ ?®ê¾½!naH¸à º0m@ѶÈ+ {È3äpK5Ê´ß&Ò(c?ד¤ Ö(c·®ºÀuûúÓDUjM–Ùèžµ/Å{)‚ƒ·©½A³CmöG5ï™Æ.q0Õg9iðìI@O»}"ešŸð…U>’ ‚ ð…u>r Èä;w8ÙÜáJÇLƒ‚d ‡Ez&ƒÐlE Ë$Fâ:‡TÝ­Êû6tï~›!C.Ô:ßcÅ|tÓÖ›EÝ7¼Q› ¤™XÔŠb%æýª]ÿŠs¬êMFÐ}ö–Þ;1ÏÓô– ‹ãƒÖ`¹´Ûm]]É™!oéoÏf¹DüécÉ#ì}!vÞ µÜªCÄD.6Zïïñî= t'×yyIw+$åMuë:Ê›²8˜7U,,”7eq0oÚ¬¯JÝ*8AÆ¡[…Ï›Zdp\é}G‹ó`Ã×­ë­ ÈèÈ—f%rd,faÿ"GÆbv7a92†T‰ ·€0K¨™”J6N"£ “´I²är*¸U°×%Ç·Ÿ§s÷ë9{Æ”“·ÓZÀ¾”ĽmíÞ#/J°Ûà–FèB«M¯ ½Ó$ɉ÷šÊNÀ¡”¤$º”_\å¼×jñhg¿3`óLS'iL˜<ºïb]ú‡ ÈØ»y8g-m³¹´à>ΰã_ÓèmÅA•ͦâ¿q‚ŒhÔæŒ.ßë[ô‚ cì—Èþõ{ÿD1õRlš#_–3òIöYƒ‹`ñ\y埅Bæ‰ðD÷¶›¢ìÛ#v,×ÀPOáA—’k`I¸ÃIÝ?<ã”%ìf,¤ Qÿßž«|“šbéÏI\Ý{ßw‹Œ‰à(ܤ›E*†:½ïœõ‘Ñ];/‚„óûÎI¤§f"Èøèìàúì€Ý&ÂÖ²BYËz$1¥ž¢xð­w~/ ùø}5ãÄKF¶‚ cÐÀçL¬šq2AAè£qȶ>[AÇLCwYß1ÆÒä„iU,MO|¨°Ÿ:K¯?u­‡üÔYz ø©K$ñSgÞ¡î(æýÔ™w¨ƒÿi͇eÌÀoÃ;m”€Ø„–gÓ0ÍB®ºG}qiÌ ð;ª±”étBÑé|!=–ázšHq}îSÜÿ:q~c×o®¯›%®fÉߤ‘GÜ~–ŒXÌÒ5:‘¹Å]§ìŸíuxæ¯É‘h±Í@Ë g€öú­ÐèØË–ç ¿~=qê˜ì]Q+Dóœé˜/,鯼GÜážÜú›êÕ£{òËíÉœ ödîöä• ãC§²yª> ®Ì®yPønËøÞªìÈMÎx«6Ê/Ê{«²ë‰À°êSDÏž¹`Q'gÈœ]Ù¹“3ôO3Ô)HœåáJœœÙ•ýâä 1Ø•Vž¦GsC±âÎMî;· 5êg9έÂÿÄnr‡¹Uˆ~±›ÜQnÕ—E³K¸]¥£ü½#‹ê©j·Áê© w¾õTÅUÁê©,‹ê©Zt©§²,þE=u£¿~¢žêç3þE=u7æ5¤1»%;Ë’“lqSxçL–¥'ýAEã•Xv (@Ȉ¶ÚêqÚ!Õ÷§HïeY€Ú®f¾¨yëg) QÛ›VQÛ›ÒÔ»þ¶9eÔ7>ßïb H°PÝ^†‰ vÅ¥ý½8ËO´ °)ËNЊÃ>Ÿÿœ¨ ¨«œ›¸GÆÞÎ¬àŒª4>xÓo…}zUÓÄžu©P!y¥i…äY‡2VíÒ³C^ OæV9ݲmú®ÙšWEQØ`ðOŸ:Tt5Çw¨8d`¿È{²_Ôy˜·ÛkV;Ì Hý¤Œ†Abë„úaÝ„ü ×wà ò@êÿÕh©ÿÕïäìÄ*s\š²¥c¦]Ú=Ÿ¦ITpÚF?'†}1nãE¡Ó–]R§ÜⱈŒ¶•Ó%UB'¹Ëÿÿ¤¸9™n‰¼„å ”'€S°pHs:èr·”ætÞ½D»ÎopÔ}ñê.ƒˆ~¡¿žø]·¶2pºG¼y½çš ST§°'x÷¶nžÞUIW$Žp·TËÏ|u¢ƒh0B߀¿©·‘uÐŒŠÌý;r7 ñ¾×ò­zúDì(Ί©ï»¹§3ÿã$Iô²sa¼%/ë›N¨S/Ñ£šž0ý´Ë{{lzÜ^ymEÕ»eÑêÁBÜ( 4ÈD7ø%šz.ýFÇL¾BuÓ‰w •Èp!OyLl®É˜à¬ÅpÔ'g¼ïm½­+!QJ{Ìb´ç–qá¥_Ìž¬ò u\ɯ¾ˇ·~>SB=2ó>§ûP.£_$ßÞ"æö-_Û¢®–Š µòù?ÿÚ²‚yõÅ45üVÙ¥^Êvo=Mè8ÜU¿ _‚̰îºþ— Ù¬í\¬o‚Ìü‰H£°D~±†nW·7•¶…â ŽÚïû^=lÚ¡k›¾¾÷¢$ÈèX\YýÖ”–…vZö«.ß ŽÖ¶yì%¶gÑ\i#*çåEa«u®Kõ…R$R¬ÝáµóðY>¯‘ ÓïÃKÉy‰ñ3û 'ß;\8Ÿux ß!3—rÑͦe³íºW½Ì»g7osù‹¶&y|oä&Hvt òµ\䕚ŽiõÌ¿*y…ÊaÁ‹g'fˆapùÁ0»SV`³+‰¼„Ì®zÍ®ò #L×¼Ù•CW °Ù•Cž˜]mybv7êøÐŽhJÍ®2lvÕ¯tÌ€vDÏ%’Žyhm"°µ‰DÀÖ&¸*g ¿˜Ž*_˜Ž™˜ŽZ=Ð32:ÔÕ™èZJÏtuä{‡ˆ-NQöŸ¿%°Ï­Ž›¿¥ÇéNÇÍÖÇt£l»M]'2ù^!µCsÈóÍ5E©³‰•wpÇp$üoUñMñMSðÇGÉúdöYšžÁ¦àô×s²êôKR¾ÄÍ š•"ىŧ3ÿsä3&°¶„^Øê¢€$°2:þŒ‘¶CÆGf­1€1³pÄ´›h gçA}ÑÐ1Í„1 c&!·a”ò‰ó@ÊG#qÊ'F‡é™†"ã°/1œœ±?“.~³Cçá¡/qKǼ~û»œÇH‘Y8iã8'fªßiŒÝÿd߾Ī­ôé}‰aæÂù&ä¸Ñë(ßÐìF¾=ŒM/wõxÒ×t‰CþzèÒ³S=t鎻toyréÞ!ƒþzèÒíý¡ö a¹;L/`ö“ŸL•ï•í« È#:™B¶|YJ~ÂE#{¿drØxÝ>· ¾¥$\ðª÷xƒM4‰Î¤Œ½7«DÆg$[ï£*‘ÉIJ #%2=Ñ.¤ÿ󺧬 ’ƒD–°–’,Lrˆ<à!’Cs/àûH²s’ƒ+ ;dhg'"ì¶Ing༅›9Qð®dJòjš‹NÆvPXIÐBk\Ô•![6SÓÖËVÞ‚<ðHJ@®憎 wŠ›îo3Ä ±Õ·ÏŠ IP"XlU?ÔýF= Bxò¿D²R“b°Bx•þœv ‚7–DÒ ÞQg =O~uO« .‘Ñɪ›ðªKã_¨5°êÒøj ¬º4þeÕÁ—Æ„ªDh™tͧI˜–Ù½'hÙsÈ-s»ù’kšœÒ2_M¥êЊvÚô,X.¼¥CFßi|xûgG9Ûûkh„ò’"c¶Ñé¥8d°ïàiþŸ*‡àD¼$2”C0Èaôï=?w›õ¥š4?u›]ø8 Ë¥[ŠL¼YWÜì#‘ìlŸ÷Í>…$Öå ¸=ä€üïý ‘€¶D^‚"(|BíŠ õÜþ0ùçÅ̳{ï×°s«½˜áBsEZFGËìŸ×˜Ð`¾„_»2 î´¼÷k3Ò;h%_“ ?29™þ&“#2,“3Bòæú®niQ¾’„ÿ˽߭Úó¨H Š Ô>ýIB2™„Ïë.a~zºÓc™™O–îö:n(U¢»¿ÚÄ`xDÂ3ÊΆ™ø*Rd¤½­^¢î•?x‰Â·Sú½^¢ då^¢°‡ óê%ÚS/Q‹<ð…}›ÿxaáìnLÀï »@±!?ýà »Ðc8ÃB»-?ýà yWŽ© rËö¥#{¹>æÖgoŸ%H ÿ¯’éº$ó^¾K3´îŠ¢ýIo0ý)G…@¨Ö®9_}4â¾Ðÿ™‘ñÏÚ–ydÂyïéµç!¯àË]k_¯eàôÚK™g&3ä®e9U–mÉåî9ô®™»6ÖŽܪˆžÃ;—³ƒ±cÑÉöM<-çÙ>ÜûMTè¾(〥›f(ãQ’­ï½Šƒª"éð–1+ŸñX’EzËÊ*Z]–DZ$yLMArk$ 7™UDíâµ< PTëXQÜ]JŽ(Hª(2$Ô£ÖҪɡå›|*ÛGrC'›*S÷ÔU&ᮈF‹®vôºv„þgJb+W½»¸¼ªvƒLöu–Ç¥ª?ge*@)éËÿ°n~ÇšW™ù³m$ì!‘™w€iu ¯úiþÔéÉŒWkX™WÝù]WiâµßD<@Ù·Õw p¢á˜_¿W3*Ï—×Ëå»h8F#¡ÆÕ¿»Ï|¹ôn_Ì‘F~¸ü›{d¶y ¥d£å~ïú±¹ÓÓÑâ°«g•Îî•8Ÿ‡e&ÈSÏÖ/§˜*Z¤WT+–¼£Èµj§5´”ož~òuw}ÝæË×-§§óû×?K’ƒóW¢Úœ­Úýú§·[[µS®–ïçù¾Æ¡JèÓUBóœµVN—®0^ħmšë²º¯MmåÞýãY?Q%Ö@Šð*e¥Â¡öûh‡axn †¨…eðåøŠÛølé³2D­õ±šdå{ábšª«)tÓR…Ósmöˆ· E߯Û{sY†¨õ[˜-´—×5N. 3Ð÷Úy¾(†‘‘å}Ÿ¹»¯ÅÑ€–±Hæ.™/ïjv×_Ë Öuq Žðuj„¯Þ Ùž0´°a¨8¨]RÂP±±ŠØÑ€.‡); E&aÊNO‘i˜²O¾p‘¥ì¨5B(;…‹´(cGÅ0c§p‘%ìH$%ì¨åº¯eT¨ÖV°TPcÞD׫áI¸v¿`¤nÊíÍ=M¿üYÇV¶’nzÎ/¨³¤ò¶áñ†"9ÌÖ`D_"ÓÃFÿű1Š,lÇ…MO,’ŒÂÙóŸÆ‚< ¤Ç< „oc‘oÇíO>£þ2u­m¼†ŒD”%¯‹îqí ’!:„u~TÈv¬ï AÆ6 Ò’õ|ÍÒ¿su},O¸öu W™ˆœí0ªE2ÄÒ©VÏ›ÛWß…ûmµûžŽš‰ý‹Œ¬­ΟîõºBÆ€ü‹Öí[¦ư¾þvŠaA‘™_æ®Ré'ýŸy(< Æ,Oä£ò§•¼­•ÔÚÞ h­‹eé•›/A2%0P$Ü¥µ"ÙX1öW÷àôì)ùÊÙö{ûú\‡ 2Û×2ĨyŽ:¿"ó  Z=€Yøj2«|sÝÁYîßM®mG\.££ì¾rUÎ2 Hœ,«Ä‰ª)Ù5f¥ä ‡÷º ŠKäãa-ìueÈn“ÛJœ= UúzEAB•¾2 ÓŸt¥o¢ÇŒCo•pÿ3Ûå©NæZUxá-.óc™kG©Âæ D6E†fê "YGQ78j‘,t?_°!ÊãaþJŒÉ|þoBY>l%::• ù?;+^m‘Ìg¶2ciE‰Œ‚f+B‹Úï{tŠ‚f+³6[±oqtŠdSd(°zöÄOWŽvÎÎŽ{¨ƒ;; ôP?ª‡:ÌUFØ¢bÛCº‡Ú¤¿‡:ê*={°‡:ÃR„,*6â¼-ÎkEÙ,2÷2¡û—̼7Ç,¼.q îËF΢­ä•×£d§nêõ°H/€›á´ŠÃ0MtŠ=ùƽ¯}÷l™Œ©/2 lA²€ýÙ(€/ l¬p/íuƒLV¸¼6È4èR†Ö<$›‘‘£eY¦ivOñŵ‚qs³µÕóû=S1Žç®±C˜K(¡ê·%‘ˆ%G4>ç¨%‘©ç¹¯”&qéûëexZ$&ÙÖ¨¹Ÿù|4A²ÉŸýÀwL®øN\àÎ!â€"8Ô]i,+ÄMXAôˆAÏ¥6ºO+v%e;R;`Ý@‰,:¶j«ÇEò(>tlU«éØZ¤GÇV5…Ž­EÆ~--ÅH…à?>…´óäçiçId°vžE² &]µPd8èzö$¬íO3fÁìüÅ%å(ŽÃ%å—”#äŸá))]I9ŠãÃ’rç°‡7Ôó@?"îî|L(M:5n,VfŸ 2óPîänü|~» 2ÇèëÉ$åÞõ} ²ð´—v~¸‚¶A–ž‚vK ÚöΟ‚“PѶÐ(PÒæ®¤m¡, ÷æDo%4!}[•ûXËÔ¥½Þï7xå‘%‰í]6VÖ³êÆOùZü;›|Šƒ1Æ÷=_)2ÜÝ®Ü-ÍÂÝíê>󫻢 u·×+jl¥¥}ÔuçîhFøGôŽßÏð ÇLü[“ü$¡cæA™éVÞ©×Ímb!q4=&<¾F·ðòƒML‰qô˜IÈjP~aÙaaMšÑÄeXX“Ì DÈ:Å#¬‰æ"7»åÖÐæP†*ÀŠÀg`ÕGÉéÐä!`C&+Z‘A>KýñwÿäÝ4¼FŠô›õ¼šA€&J¢€x´ª—Vý$àa“" ­%MåÂ; ‚dAæ×¡r6@Rò¸(ŸJ’yq¹-»|*I6lGT/•YÒëù~’*Ó¦>ãóy>·#<÷$AÒl›,©QYT’d×=„,©©t×… 3¬…±æ§ßË·ž_Ýkó?s¿ ú„ó©$ çSŠÚYú6å·N’zzL{U(ö꼸‚iâ$º<eC uPd…ã³/‘ÿu ÈÐäEÅ] ÜÌÚsùj®^>¥ö¥Ä;‚ |g°$C”äG“•pjrdͶ\P5.9²f÷Ý¥#k6!À¬Õ"lqiøÕc%ÚËØ»7©ÜÙ¬Øì¼s;]á#Ÿ¸zíŸ [¾ê.|i¡~“¸zퟕ?j8©ï–¯¹yoΞø‘r-×›c¦Ø¸Ò}ø^;·ê¡^ëåÀ‹;ÜùôtÌwù>²×ñqà˜Žœ½Ž_–À}=ÒÓ–©Ae €¯ni¯"œ0X\ý&=íÅ0_ÝMªäÊAø»‰ínÉd’Êw̬(¤òy3ÖdȾ„;¾@”²#‘Øjq•ò4,D)Ÿ¦2¼€c&Á7…ÝšO“`7CO|!6J“£‰ïÕ•SÔÁÓ‡¦V…emû¥¯¾å™"¤üzèô…÷äÖ(Af¾¹¹n¦eœéå>ƒ†^Fõ¯›ûŸ8¦Þé8Ó ¾rh¶ñŸ–ΆNãøþ\Ûæ±9fŒLoJ>Çêr¹¸•œ…ææÖŽ=wgÇûüß¿N¨_Þ;NÓæ˜þÞþÒ÷3ô˜á´Ïu­Wd8í»oÁ´ïÑmù~ÒÊ$s ÈfE(™[\޲"½µUqmë¦éÙM,°ÛTÚ'6)˜öõbÙ@YØ-ª›i¨©†+‘—™D/3=†é¼Ì,Òãe¦‘ÎËÌ"à•f ¯nMý}M;Á--÷8¸‚GQv èÀ« éêKdt¤¯.WÞL‘ÌﬤÓ>»Hð`éFBO+@bwŒ¨ˆ¼‰µe¥Ýi vàP¦t+`_*â0­XI]¹»T$?H]õIÄ=nf…œÏ¯©s4®"˜ø(q᤮"çT啺Z.n‰“ƒ*“é4¶Kmç«E¦¤Ï¹®5 ’Èõ9‘§•wpˆçÑÁ ¥iGntÆGçùôŽøƒGg¶â]ïþúªÝs/ŠQÚŸ¢%HÿW¦#®¢<ÜÁFg/O‡TåÇoq*Tù‡2º°êÖQy¢{ò†Ô<¸¯!àðQ•›³û©Ê•¢*ÃúÄ^ªòBÿgî.ÛP•чŸªÜÓ³—{éàþ²J»ÿ‹á÷½da¨ÅCm.ãË@~ˆÜÉÔDh,¢_{öçóÜM°êÊ$ä‹'5ä‹'‘iØCûâY¤ÏOuì/žEú›ØÏ"ýÞ¯‹ö~…kG>f:—›2àòZ^×k5$íªh³hÛnj«^P$U<Õ•¹’_ííó†ÝƘæ!¤\#ÊÏ¡£†•¨Ô Û±¶Í(´ÍRA~TºRÃKè6ErE­`´Ë ó€›mµ¸Þ~™9Rón}’\¦ÌJvË‚WòN{™ÁþY–¡V‚&Nö ”ÉH !úÉri§É~v£ƒ¤¼%ƒ¤ šÐARÕJ@ƒ¤ »‰‘ARý}Gƒ¤ šP•_u?±Ê/ ¸t­.Xå—Ø³&N²S|ìI1;%?xRôy3,y3ð‘ ƒž.f`nÜÁ£ÄŒyìtäE‚GxÙ) »î^8×]‰Ìî»2¦ì¬ë®Eú]w;¹ò¬ë®E†]wa4aß1Ÿëî­§Ç ºîVçÍ1®»rÝ$ªÂ‘šÀ²Öj÷4i¦¿Ò·_C¶ã¶f°lYË`$šEG"¢2¶q+9ŠÈp•Ù½õúœnbz?ŠÄã8fx¥“û¼¸·5¬º(ÚF,xpgn¿p?#ª}¾Ü‘ÿrƒôTònùÊLŠ»»äœþü”ŠGBBòS³Ìpíñ&tBBó ‡ÕZ‚4’qšÐÍëµ=1òº›æ¥$´8µ¬Éú‘»}«E¦†Ö+Ša’ø¯Õ›Ør÷FyE7.^¹žý¿ºNkŽÉ{þùðÏï-6t&…,6¡“Sié™Hù0â=ä‘ò¹ñ Ù^~EÁhØm¢ŒŽv¢? —gI@&¥»~‡– Ó½`´xÜ/³Œî2Û FKds™ß[Ÿ7È<$9Ô·›ÿYì£UtÑ+Áhzö2(NTsz—Œ´4Ö!Ëã:mNoüb´½ÉEQ1×q ö:-ãS(óMMuºéÀá¨a>¡L±¹{ EP©¢Ó‡Ë/ƒJ­0ÜÙC·r1?ÔÆgg§-ÔjÄË@ýy{M65fŒªž‰ÆEM4nŽã’ݺ¿çe¸\ä+?d‚ qzîRm¼¹ Ë™ž=Ýo¡J/A\Zpî0Èl¿…êù¿¾6ÈÜ;û¨”'9§ÿ³ð˜¶Ë;¯MÛí‹Ì¢€iûbMÛAúLÛåsצíé1mçÖ´½#ÈÄ&)NoIq?nüUÝàŠØÎÈØKyõéê >^ÈÏèÏï_«¹ñûnjA±uÿYÜ0:ηÔä™ó3úýçßj_×pËè¨ëÇjC«‰ kãøÀ`]+´29°#Ǫ',N÷Dn›¡|ža,ƒÅY+‘‹cà²82pEÓ÷ŽË°·ŠR «…—þ=xõ|µéI$ÅšH.n…ädÂþ¢Þ¢u.ºç÷§˜\¨‡I¡Éå¼9f^÷}ÃûÞ¯@t? ¯@¼?L²B¨_YM eÂâðØÐÜ/çqvϨ )fñ¡¯Ú©é1ã@ V9»-†C´ò‡ÖKXÛ(\•ý<г§˜û¼–>¯/o¦©… :.·>kö»ù^î½ Ó{zÌÜ26±U{mÆö嵩‹äòÒg’ßôs¿Ÿßç¹Õƒ,C¥EÇd‰Ûéôù^gø"$Çú|{‹“( œ»jé=æž"ã –(ýd‚ò´á¯.[)”º'È4 ¥×Mí—s«XÀµ>__}ïߪ"ÈÜ?¤Ø5­Ûë¾*†Ò`ÙÔ,ñ–WºNeIR³ãÛò¾ÿ¬ÍaaÍ'I(CY§áa0—%é‰H™µÀ6É. ‡ñjÙŠ×ÈVH±myÔà:ºFþɼ%åvQ%å cªåV½òý?nÍ»Y|[^Ó”˜ÅgI¹u ±Erùê{,=…T÷Td…T÷Xz ©î)$RÝcŽM½Ë¹Ô¨ʹÒpÎÕ5‹Ê Azs.}ç]”¢Â»w¾îRÊŽçû] –"Ý&¢<§Jß­Rž¦ör9w™`f¾=æ[\e® +$E™”w¡ÇÌl†¢µÉ W{ë 2Lí÷my\ʨšúå Š­oùz¼AÇÞ ç2ÊcYÍh¶ô.ùF…Ó›7ÐÈ/À¯ý¼¹OQPäiz†“ÆÇ"OnsHã#‘§³¦K)Ûjg±!Ü‹‰à ±Ø˜”ÅÆy òî4ÞKuã®ðXšóˆ3¤ ªÔðz ®þŒ(â®Ô°n8}õi^` ÀE|Må~@ƾe_uïWíÊ,iŠ^¿>äH©§ ? Õwè7ÇÌüÉWÉ ³ïMÌäa)b‰PÂØ±4†ùÌža7jÁÒ2ÑâcSBFC•*´ú«¡ +ò²Ó·í:Foš²ߥÈT_±{§ïÀçi¦±ÛùdwŽÿÁi“& 4`^` ßÿ¨×NzÌtÉ2£Ýö‚À­­”Mj>¹Ða”¡d ÆûÎ ¢§Ž C€D./kÚ"›/ˆ^ÖÊ/×xY{{eÞ"›ÏI%?”—uU •ftGÿ혶Ã×3¥ØÜO+yèŽÔËkÐ!­Mk¼½½šMëÐE³Óôßîrž7ýºäáË•ª¨é¿0!…/”ªx!õ&Æ·ß ßNu;öô0¥ÕSNŽÐkYÇ´»¯îˆSÓ@X¹G¯áнøŒCÿisý0ÊC/ô½†Yøö7ÐEDö¤¿«—êiœ†tÈ–qAHÿ¦+Qó¥6KAh¡‘ 'Ÿ—•ôw¥É·l(B¿] ª»=>Ïðþ‹ãƒùâÂÏ£ósb Ððó+ïc²æk¨Ç2ø6ÃÀÝA8d^œgx]ñžy>´EùÒ^øÓ¯ÔùÒiåK{áäK70m‡‘ƒ S£Zª‘¾+·9i/È3Œ¹8ð¯Î,æšâ+ oó|2Û‚Ì Ý2í Ž^ôzüŠ ùyVNÇÍbÆ¢æ{ÑûìeSó½Ès*N›¢;–ÜœçyÄ=;WâŽv!^ä?¯…CŒK65ÿ‡x=lüëÜˆ×‰Üæ+¥Zþ¨Žt˜XŠ.¡àKn÷|µõ_h;Œ!¤wcÃ%h – —÷K¸7IÕ…Úæ‘p_-¤Ù{6áþNXeú¿QôÂ*Š‘n‚cgžQôHp4Â*t «è¼ã_¿K¤m_×å{ Qì~?„ßS¨¢%h½ZùŒº…V]q>#;Ùõ©²¦I•`$½µ,æì˼)BB’hšŸ3×1óŶj”ì •&8¬îy+ P¶„äøyŽ´cã¶}— R‘¤ÿ…\!K`ë±Î¹YÌÄ/4ÖɬÖùta{“Á1­%–yð±nÉ¿çY) ¿cˆxF°ì‰û•àVÐño:7wÉ{r¾˜vȯÕHïWµ.û•Í^Û{(Ë‹"šr>.¿î_v¬²˜«$ß0òs³€Ïaócð±éWþH2èwÞM+*öÌRÿŸKÃPøY€PM#£{Wš[MØs¤oQ®¾áÅäAf§oh¤wç‡ßLbgfØØðš¡¯[à<R¨ѧ†ù(þ<¸Ò”ã^üyp¥™¿”^Žé[óQUÔ2oÊ“†±ïŽ‘XoJñÜ;é¢2±Ë¯«çþGñ¢èéVÀgØ,Iv„ÔŽ'’ Y©áfeü’*ÚÏø×£û|–cØL;&þXû‘[fÊkíÙI-µ“GþEUDVs×#¤w—[< ô /ŸÞ%+}óSB°‡2””áÅѳÝâj¾âÈ%ųvº[_Gô”äI-¤Fú÷+¾Ã’qzqüäá’ì T#/›Ë"ÞdÉHorßußbB3y½MYtþJ™Ák‹£<`ãi$¤DŠ4¨S†”·_þ¯`'ò‡SÑ“c×—ì ûäõF9)0Ÿ#Ï…jÂÇ$ÆåþL)¤s^×ÛÆŒÄ$ÈVi*%ÖrŽkØØ²æ8ü¸{A ó)UM4¸KO©j¢±8 é9êÀòƒ¼S½óu§xC[€õyýf¨ªy3ß•%ÈàÉ+@Îäi®r%’Ž{Ö.çWL^ª%£B’˜–¹/ªïéÎ ÝyLÝ‚œÆ½Ê¶ƒ!¤©m²ªÐ, ~̥ʨ¹ó†ÌýG-òefý7-û 2pgçšó Ÿ³s!a˜áŠ#;wÚÒ•+r:ð1ýûnán™˜;«âÞĤAH—‰ÉnLL4ÒmbÂü뾫Sj87ä;9a»â„oÝûå´û£‚¸%.â+>†é¬ëÈû!± æ‰p3™t-òö¶Ï ¥k‘·ïH×’uˆ•®EÞþCŠ¢®¥‘¾KLx@•NÞŸ S¶‚½mšÔíZ”pž¶_«dÎåÊÀœÒž%ËräimÌȇ©Æädnæ™b$±Ó 4=‡ÿ:ãgÚöéÃ|¤ +Q‡ɾç|®ÁÇ„~]"¦8Y] ¢[ÖÝøEHY/ñ¢VÄÖRØ­ç­Á'±Ä¢£«(ßš#²U5œëb‰7R¦ÀŠòf^ùºwn|ž±bz‰|ãJçEI»7{›,¾ó¯_u¦ÐŠÙêLr#³0Úe»%Al™Åé0¤÷lù9–|OOä­£Õ“Ç”0(l™Åû‚õÚy¯‡Å6¯ü¡¤&F@p-¾Çu­†³iEŒ€€Ÿèÿ4ÉNöx„1á‘@P8ñÞñ93ˆÈ™Œ¯¦ð1-q.I¥1au4#ÃÈA–zy¶dEÝ5ÈA42˜^Ëð‚ž×VÕÐ&C‹! ¡ô—ŠŒ²Ë]Š~o¡]§£Ò_v#KÖqÊÀÿà¼ó÷–fíÄkÿËmz¿ï¬ßúc•*Þê9¨ù5[é$lŸ„¼5nË£€€-b‰ À¦íLl®“#=„ðwD½ËÇÎIA€K²’¢l0Ôü6©ÚoY˜·Éw½w™`èðéÓ êVÞ•ú™Æ¤ßÒÚ«@Åš¦_þ]Mù+p–yMÖ*ñ†F6ïä4¤—'ŠÏìÅˤ[ßK?õ""32Cýù}¬Õ.ÜéÀ•F#c‹V ÛT7óPR|?•VMTl‰2CR· ¨_~^½wþüc¯Ã:%_£$=¡Þɽ£ýÙiÉé^mÛå1©@u­€SK á?QíU~T†úêsúc­¤ùØ´æ›È¹ÅÐII—1l•œìŽyÚæ îÀÇ1ŠKÁƒÒMŒ0ãbJg†Bº‰÷m|Òùr2’-@†ú ”êY ôì"‡ž*6ÂË!ɆY;z˜¯)r¨§ùŠü †¼Œ}Í—-9[(„¼n¶œÀ}âžg…ðú±©ç„¼ž(òü‘2ŒtQÏg>ò`¤›zÒtSϳÓM=ï/ÇÔÔs±i~¡žƒ'‘FÆ.UÒäûÁœ\l"éÝ[y‹…’¹¢÷ÓBijÍòü?’5($kâ=ßņ ,y4¥_¸Iˆ­ôþK)½µC -ؾÑ#ïß%d‰Oˆÿ–øæ.¹6¼FÚSfYâk$¹ûŽþñrîçÇù ò;‚å ŒøùŽø'¾#|ÌÛkÛbéßE„ï*"îg€ôð¢pPõÀBs^gÏ[ß"¤g°üYhRTiÛa$ÌÝòÎWÚ›¦iËq„º…—¹[T—š•µCCaN"níæ%È}—¢™·É<#Û÷o!ZP]´{=¥øÚC#Ž-@—–Dñj¤®åyêºEÖŒ ¤ø˜ñ‰Ôü ùmÖ#‘¶Ÿ§®%T`ü¯È‹äâ|ñš‚üG,éʜʠ+^^ÎÒºßQ9wówäN•+ß_=öærTñœö?Ûÿ”_…ZþÍSÅ Ü­ª0Ôw©ÛhcNà—Ÿ¥Ç|Ö¤Ìt\Hä°»V[QÔÛ?²e.ÛÐù°òÙaâŸBÆf6,Ta+ïç–uYÞã;/kËíÕªäå8òÿÒ¯ÙÊÔPÅZ–6xº¸áWŸ4;-Ž"ÃP¹@ÿ[l¥ŠÊZ¾ÍK7US?ç %¨ØR[ù[½—YùÅPÙ\çïýÿRåö/”Il˪Cù“âU[+š?ÛìI³´íüÝ04P~YÒ=LÞ-Q×ÛwKg Oh‘z×™±¡+X“A!®¡‘€Ê˪äçÄÁÛTL}O«¹ÂÐøl *“PéB³Û=U*$pÛš‰äxÃÃzêTõi|$pYýJ-ÏÌÒä¼&;äãâAÓ ÿÓŽÝÊ*{ôtd#¡;@Yê @Y#]ÁÄäZjäOm­]!¦/«Ïûz?<““«¶Ïb…Ö\HœáC "¡st™žVø ý…ŽŽíZ˼˜8T?µªÂùƒ‡™éFõ£:S‡êLm¸‚Xdgê͹¨~~³*á] Ãéª6Y•é9î§hDÂèñ~š@#béƒî¬çÓÖ“¶šæê®²,ËÐÁ1£×“» eæ‹‹Ü9ˆ,¡6Ç&zýÚšËQ„ÏL{›/ã8 ¤“˜ÈçnßÁýG#?¿‰‰k5ðuw 10y“ƒ8ÈD‘Ä‚ÚÊÿo½®£&D¶bÒàóŒîå† >ÏØÉ6ëI}ç_î3Xø:åIŠÎ85@튬e¢lº\(§f·&²öu†PhäI÷DR³7kpÍ:£‡±Í#vÆÈ­Ø#ÑÓòKÊTZ„ô~÷ûÑEj3C匬ýí3q2ò¤¦Ý Bz6eª®Ô²;Åö쀑ršÿGP»Äºœæ§!Y÷¡Oö!å,ÿäÃèÞ¾@NÍÊgÚ !¥oÇ¿‚\¥ÜýĵtÒmKñ¯÷ä~;!ŠD¡3ÖrG Q$ ÿ#!jÂȇ„¨ Ò‘îb'DiäÇÁì¢&ì—Dу˜|¨¶+Qü(&ç3CHï×¼M¤RØbr¿½­`âŒöÚ¥˜<ÅÇtPNŦJ‹é»ä^&ð– ёʨÎöÕÁßä¬jò>Ö¯”²¬É’8XmÇNáëˆßWjUž2Ô¶Ýp ÑÈÏï”ÐéÝ _Q`íçéØì¦MÒCød‰oåyÊMºïl¨±ñû!ðvjfC‘ŒW&ØâvÂbƒMGz¾KFpeLyuZŒÜ 5Ïȳ±—í‚i)*ð€!–àêJ[ŸxTê¶%¸:'NhÃ,­ Ê\ý‘ cß{°yXz†œírÙ„?-Û£ͨhW²!‡ÌƒÛ¡^Ò_{¤*_¥‚_瓌)YŒàÊXíÊe·h̰µKüëjñ÷ã‡N~ëGÆDˆ/BÂCJaBÊwºæ»qúÕÈÏ­s»Õ5ƒ:(&¨Šg9Œ¦ë!]'ÿHv jÅÄzHØ~'i¿KMø×ã»<[ûb0Ê›øÉß/If³/ûîÝ^^­™ÀDžÂeÁŽùwX>ÖÜìá]…3°æ$1Œtî_Ûçieµ«ªL•Ó̦ëR÷úiú–æIÑpÎm/^ÜôU³±¼AH…wÈÆÀ2ðõ{i” þË9!‰ÐUË×=FÓZ^»þË{ 3µòýqøµ¤íôà¿ü§ˆ=ËéÁù÷qLÛ‘ÂÐíÈ‘Â}tüÒÊ Á­ék9|ø¯‹¶ ¨òJé*:ʪìØÌyÈ/ÑZë †ƒÕ“ð_¡Ëk—ŸýRG‹:¨ö}ò˜º4„t8ÓŠîÃH›Ö¤ÛlšÒE8O³ƒ))]j÷AÊxµøM›!-òW¥É_–a›ÛL£·dÖÈóþz²ë¯ûޏåî¿bG x¨Î6°e|KÍs nQȲFÞa(dY#ߦtgÅÇôo‰‘C’oi‰~£“™UÔúï·£¨•ié–C’oârnúbã§eéŸü +õs#k’/Kø:ÞViõûÉ[r,`§‘ÞÉšûh*Hk¦Ã^¯õYZi$1dðªÔ c‘³60vùuöû \ëÖ7™qzÐÈϵ -¾þãõ þõàçeŠäÝ uRÔ}Óþ›Ü••BÈ« ŒÀm‰ Û•{^ò~æ%ÌžÁ#ßüdImC?tõØÒ7HYYñcóÒ”|FL[„T|•?CÏL]QYoÖ;o*–¿¤¢:?wñØ>¶Õ:¶;B†€T©ÅdG“ÉP!ddJ,ä$É<7Åt9f|"3à6Œ|y²eÈTÎ;¯ÊJÁç7´Vt&¶„ËbÜ0T=¥ý+”xáÐnmAívB­W4ÓÛÓž EÕ”ãú&`œ'^R9:,Bô4ô{yKL‚±Ô!(hŸçó4}/GIO*#TÝUJó„¥—£TohÑRWÓdO14´ˆ¤…T^ɸNVO}}FÖ––!Ô´¸ô3küúé=ió——j({ÒUJÓ³~¾ý/*~jšµ|$oÆ,ÁP˜qÎjL,Ñ{¾ «R˜m5ÔL9§†(Ý÷»}çË‹ååoµò™ëjØÓùòx¾5åÉ‚¬’ÃÔ\neyâ½:µü{uK¹Vøiy8ÊNŽÜ­š¤Ú“!_144¦ˆgïV*’÷¾k.ÐȈµ¶¾K–ð[2e#¨lyI(Ý’ [äe ¢Ù¨êNPfÚa¨©tÅW ß×nèó¶M—sgñ„nz¦Çtå«°a›¡J¬úYÀtë™/š×ËQ}“m–«Õzi÷ª=ª¡À/!1®j"ܬVV—”–k–CªÞ×£™&6ãN14„}P™I*GöŽÙ–uÉÙl8ª¾Ø†_s€¡ñ¹¼c¦jPÒlj§5íjB¯7äóÒa£aöó ¨^öJõòÓØò 8l4ZË6 ’|3Öeñ˜4@j'bø÷膽¶ºÙ·ë·ýý¦FF6œ©L‚ºo_}¶½êOƒ±K+ÕigI+ee›í=GÄuÌS=2åN‘~ý¦÷{+üïô¨y¤˜šâ•‡·Ø:æÉ‚œOCwÏüUýú¬Âc¦;R¾o…BŠ ^¬¹ºþIäTLõ¶h¼¡òÓ´ËðÂc>½>&-íÜ”s‘Cf+º#5ój_R6ªŒÏ2r”8TT K&‚£…Ù;ºû.–*‰ÏÄQt‘…rUƒ‰%rûªÁ2k➉£èBáÂU &Ö1ïØ£ Þ¸ºþI­˜%rìy‹H©p'n½^ÍÚCÏ&‰â@o’J…âöa§â Ra#­˜A<Á é™ÛÕŠl“ID¶ÉJùѱM& Ø&«œ¢c›L5ýÌ6Î:5ýh› »¢CM?·MöÆ Ú&ó¥$=ëæ6=4M#Î:{,æxÖ9º*¦“]lò#ìóѱ߅™nî†å¼í~BÆçÙ¶ =Ü{zá“Ã¥# þuÊ]Q³¦ŠâÛCq“Dƒ6è®2Ö·\ta…‰/ºë4å®3 äæ›r< dtTÎí•rnʹ$ŽÐÓÄ¢.¥dÀuƨ4ÂWÆ¡[ŸÉ¿ˆ@¬AÈüK/Þ»!ÉYçÖº¶ü7m#BR›)Q[Zu5/Å;½bd«î½‹€ˆQÀú‚/lì˜' (HŠÏ°µù­x–GÈÉÓˆ4Èç~’{©·H­ºuÖ~X¾_<ó7-'©¥-JÃNžEÈ2N¾Pc}”ŸÉ¸©c›ÕóÃ0©?#°?PÝ)ОôV 9iðã=²O#1¹°uíÓˆeП 9¦h$¦‡ã"@æöötœr,l_ÚÂB ‡™®¶1LkÌîÌnKžÛí!qŽSÿ90—~’îÙ8;»Ý&ÇÞK@Ì»W¹"$î}p™‚Í„¯óqF-ëµñ' Ó@($ƒ;ÞŒ6ŠÓ@(¤Äº¹ ?M(´m…¾_g0Ú^Þ˜PhX·Å.ú‡WØ–ôª\ÌA#3{ØâXoz]Q¼Qdxšäv!*.'ƒ™'7,»!±8ð®CÕ€‡–AÆnŠÛVšÑ¯AHçÀÝï¶jœ»ß´oNäŽÄèä¼Uå§+nøßÉ ò#‚Ë!ÓræâBòˆ.Jëk»ªéÇ×kAÈçþéÖTS‘’?YþÃ3ƒª 2bü|çIŒšm†Þ]Ù<¦¡m'> ïÞ>ù»«Î$ 3ŒÊß:ÿª¦š oÔxÿ‚¨C·JqŠ£ôo~­Ón·»C œÏU2TÍ–4‚‘q>~Pw†rïZ!Å™™R‹xb-WŸù“ã‡zO1T=«,Ðîã­¾»›!Ð{s=eŸ¹Z—6R}:ÐZs_§lþˆ°µ/ñ¨Ñ Ce EŒúY_ËXâˆî-ÍYoõ6½Û±ñG@ºÃ²mäÛÜÍüã;P-Ú"¡k#fÀ‡ê§õ¯ºÖBsĵòf¨à(QQ™$Þ§I(h1Ôxìˆ —ª5&ÅF%Þ—ß4¿04u¡FdR@‡O=åôqæsÓ#O]B¢ ×"×S—èO]èC!Ñžºþ÷O]Ù`ìzê$=s¯§®Ažxê $òÔ5Èô¢mÆŒÿjnòªm#/Ú†¡„ÄE]ÍXeJIÙêºÔuå½ÖuòD×Uµ Wëºà1^Y²Y8«Grô*Pjå&ôJ6“oÜ®:zà²ïÁA¯‚ûïÉ…SB¶5ÌÎRz¬™};’`pЫà Çc’€J¯Ó™HHô3[‘! Ÿ×€ ït|Z'Ï‹÷ÖÉóÓ:ÃcÆgësE:ø„Þ®îÈÑÁ'®~®‰5?Õ/ψ^ˆ¸)Æ?¬%G•áD©hb ÑEï_#Ú;VX9LâpÅæ=ˆ¡ñÁo銞 sÙ«ÚgÉÑo8Ϩ@îÅÓ08dT@¿›PzùŒ>­7f˜ñ?ÃӤɕހã»fQ GÌ=‚ÒÃA²ÇF€Ƕ«qô ê-Ò¹ÆëŽ5 Zôt}|óÛÈSÄ*œ™ß¾¿›]uÏ+óÛå€ šßæ WjAóÛÎGÒ `%8ódC„Z@r»îƒf=F^ˆ!¿»ºgªñàˆC’›ÿíp2i’ñß«vpÂê\ÅÚ³cžùñغçè äJA»ý5¬{ZEƒ ×=sèLL¢«º§tæòœfõÎÇPbõ\çÕÞÔëRC¯:±¶®žë›|7]×7’#Zºy?Ž‘ë¶bÊ„jÌâ“äBí,ãÙj3¨ ¹ƒÔŸÏ·æ ò Eª ‡ *oñ˜q(3˜ÙoGBObQ;5ô$¹Œ¨z’üQC‡ˆ:Iþ¨¡CD$µ¤âd·†ž$‡µdýáäömç3 ÖR$\çã‚ú*»ïí{ôÀªlªs–)%¡wo{“'Rãx T9&g¼t‹'OÔ]³?w9Ÿå8ö[·¼2>÷~h¥Kî~é™GšFŠt$½‡é$ÒQ¤#é=LS:s#ã°Îœ‡$õ¸­-vuCƒ¤aõ8ø¦w$É}Tóþ= «ÇÁÓL¤Ï‰x›áÔ“ÞâØ®Yhf©êçßÈñušZÀÿiUÍZiuÊç\£wó÷”.³nD$.XMûìÝG!1[Þ±¾¾p:L#äÞè8ÿNsö[W»‡¥QÀÏWöáJ?_ïß)h»¨Ò£QȪ×Znøß“Skêœ÷ÆLO Z‘`ãÓøª`Á¬!ºAž*¨ ˜ííNcôv¾¤ó…®$¯¹ø$¾†óL‘@ÓOø§q@‘@V«úµùÙYŠŠQ$àø:O ´.³}@i|¥H08Ý|iV$øJJ늯Ó(@qÜ=®ìÛO¿½4%¾°ÈÞT&›L¦×šÁ-уeT¹[…­ì-Þä!£3I¶5ÿü&{ˆNiw,ŽÚ|µÙ”:”- Æ@¥«^K/grQxu­@Iúƒžaä…¨ÝpÒ?¬@=dAo­@ ’ž“x- f>h›Ä†Ñ’ÒG–Ô+ZÐSÒÇÝ'ˬm‘Œ+yÞ}"uÒ›HÆ•8J‡•ÜÊ• ÷þtj™»i½Zvj>Ǿ"Ýóâ`ÎTybŸ%Gûñôí¶¾™m?sMXq—C«º¬¥' ¸‰`•ÕëæÌ<õÕü€i_uÏä2`²Nä™\K8Ù€é™xß#_˜ÉÞQrЗÀÂLv–õÿU+ÓÛwÑN¼¬ò¥mòB‰ãë¼ ˜ðu†%œlÀôL.$œx¿Ø€éé•9 Ïb«užÉÓa œe 9|žëŒ¡eJ<×CÎöö!=®3†>’º9»ý߇ìÛ–›÷ïIPÖÄfÞ]•ƒ3Y“ÙCFAY“Í^§=™¯:'RíUFñï#Ÿ kö|"Eâƒ^œc©«±p¦×/“ ·ªXK÷lz„Äüµ@¹T8ëØè©£Yq ƒrµô–øÚ3j M_ÛÉÞQb¯‰gäQÇ-³×[À1þ¢Ž[¬güÅdüE·XOC”7lr4D)ò€E¢l@zõ: ‰Ò ÏU8˜«Âaê²ë¶Mï·Ã,•ûafÈÞï÷^ç£÷C`g5ÕåžÁuÞ]UÔþ±žäbãä¼[Xó÷K‰1¾Â±œºªè'ƒ0Y‡æI÷}^ñ^t+Ÿt9iÖÚC&ð•ÑÙ5y,ÿY×YNšA¦®øî‡²µë' pƒ|œø¡´2V=¾÷'²y4þö}ÞU6âù<³®l´nˆìÐ{À;…q¨ îP_þE-û¶þmcÍç]$ôW§:–Â'Z–<[WŒD=ŒQwÙœµìEkz?•¤Õ† bB·¶&‡.{.-¯¼c|.-b= H‹pOZÄ /¤E¼¿ñþý\Zds¥E 2 ·tØ1“ë–fg>ù£]`k2P–˸µ­¡÷ôÒþ‰A‹ŒAF½QfIGôþwwu]N#\çóº#üèý é .ít/Ýþ\‚™n.ÁËÝ®— hM#Wö™ËóvUdîÁYR­Q…3ºhÚ¶ú¦)rµ=6 – Y]¯”ûïk,öÞvƒLΟ»l,€Éqôº¬|h«µùðì×Ivô°’¥1|¸£ä¯4ô9¹æû êú¯þû_(d?NlBH(a½”‹Be‚Àå=nv…¤Þm³|{¸÷Ç…‡·ø$€)‡Òé6ðmžWfWȱ•G¿Å*¨.‡ŽõRHG§VöhqœZOöVذ!¾]@÷¢ñ-$$/ƒ@GHžÆ÷€ø¡ØCf×ÀŽ:΢ØÀNZ»v4ŽvJ‘v¶vÔÒçŽ.&K‚þ÷pȼ1ÃAàä!ƒA mÐ1ÈôÔ2¦n‡¢†cl‚@. ÏÒ3.òŒá7A ïŸ'+}Ùê=¤`È š°C¾rI­p©q 0¦‘Ãh—èÌsg9]3Ï—Nñóü½°±ÅÿNñ&¦‹C ê:¢1AÅ »‰)äVLkÑÑ_R#­¿$µö³Š·ù*$yN‡ÊóšåŸÙN==°šMwkÅ«ôÑ"S¤I«·úJkl­­8¬+BÆŽ@¼‘Sz1MêvÔµŸý6R^§þûýØ%ê„ ÿ“ÙV˜~,æ~åUÿ=9S_TI¦­Å÷žžWÞÆ˜„ƒ«_7mÏä*¸Úœà*N.ƒ«ÁW–bx–7“î³ðïiX“vu=•hü¸Ð“\=IŠˆn§z’ B†ô$W«'iz’mîüÌq¢¤ävÑi× º!©¥Ù7±‰ì³DîW%ÉMl£û,YFŠ¡lÅ^–+ÆiêÖ/Œ#¤"Œªƒä6f]ÏʾRçu=×­büÖÝkj2Þ…­­'û²¬.‹dÃHì—Ë©’[ý,ÎÚÐqe:\ü¯‘>ß? ¯¹˜º®GÈäD‡™÷H‡™’+¢°«ÃL‰sˆV3_ä:ý,kÙœw{/;uY;REa)`ùÌÒú^) k9ê̦LlŸå´!$S+¤¢ã(dû›Ë !1=-ýÈd>¿-¿]ö’ž#Ûê÷ûæ™ ¤Úç2roÌÔAVµ&~·Ã»ëëï_çú­ÔÓ”I 1KY#ÞbøºžªªË07ŠwbÌ¥ý~ÅA Ïü iÓUÚ¶mÓå5†Þt¿ûoûÍ2ïJï‘ ÕyP9êXþæ‡J]OU ->á¼äyS¾ß3¾«»µ‚|{E¸š¶¬€[KOU•¼E]Gãb¡6Äjâ¶•4œŽDÅt¹˜€ÆUSµ•‰vnRM²êÕÍóؼ0ôáBÕŠÖÐ:¿Þ <ÁOL ?®êSwoø*›Õ;….Ÿ­Ç7†žÄ$Ú]tä”ù°#«ñÓ!äyàÇs½À~öŸm2µç¯öü‰ð€AƧ_Ê‹¾õä4ƒ‘_ ˜‚PÇÓÖ÷âl”'$=O[ß‹³Q^œW¾”4ŒñÆ¡,_°Jp£’Q€Òm{ «‡<×âÉf^ÍEgM¬•M˜Oz;í–E–óå½ìnÆ”Þu7Õ]ý~·ï!ÏÓw²ÉÀ>wzâ餞æG¶ ÃjõhV)ßL¹“7â•zÐâ6HÍÀü¯ÖÔJjü-ykgøÞVâ À<¦ñ—iFu²Ðeþö-{ƒgéy¬_÷m·ýæÁÖ5,sLE⎠ÝYž7ï~‡uþuŽu»Ö^ö)&XŸôî8zJË;“Ê Iއº®Ø2¶ñÕÎ’­€üÇëÇäà©ë;Œ¿s‘mëak¦n¢Ï­€Èƒª¬€xÈøx¤•‡_Y±wäðXPD2o‡®úõxLzv e²ªÑxÿžœ¦2¤ôPzщÌć†:#K­(øwr©Åm”EÉ¥VsV2¹Öвµ<×sùL×imñ˜Ôž(órWé_‡¦œ,(Å*ýX{¿Ûï€QP{ßž®¹…“eŸÒ+n¡bŸB"š†KƒfŸ¶t»`¶DEÓ€o»jßt|Û)}\–½6pù£ôyÁæu)hrÅ}u)hr ¸]È1] šÜ/Æt4¨Ë…;/ìO3¹.´¶XüY,ÀȳbAã .œvö)r^þ­Û°Í+ÛU#©ÃpÓÒÓ2¸–3ò³ ýœ3„ŒŽŽ¦¹çhjgNô2m[,6u™ß «¬@Ú§ÿ#ÏwíYß#d|T;ØœO‹—’ †°Xò#k1Ò¾GÐu&pÕëÛO•&sSÔ Dû#K׃eƒ¢pB±=˜Ê_•šÓ6"ƒ÷=¡^Ú¶Ü™ömµ´MùóçÜ”Y|á3ï:Ó€-œ˜*;KÉ•W§ãƒC]†›×,ÞkmbXu—þŸŽcMž!ÓD±–\ÓDš^È!ÓDƒŒlI7®³l´³/×€çOíðåúqúr}7û5Dl´”–®V‘“ãvû“:Ü©ªPòéϳ~¾¾£³¨r”/o{–L]9WÄMºrÿ*–{׌*3 X6Ú¹ø §Ã4ºâÏ‹5jŸft­¾Bþ*=‰ÁöP{ÖÃuÛ ‘»½-U8|,Ì!—žõ’Cnç3FûÒ¾+š~ª­alÏc ¢ÑŽÔ‡™afEÖÔ3Bbg`#Ӳޝ×0” BƧ®ÈoIÏ€X1Åxý×;=c,†­@È3™«Zw¢Â¨C^‚N6𣮛×0íûRšœÜ»aŠz³”†f‰÷Þ,¥Y’¹e¼nC“Z– âËØm#C…i³µC:×Úàíx^ë 9oÜó¦½]Ÿ(ŒçIÂ*B“íi F·k{Z›‘p<™w{ÚªÞíiVUP·žÌË?rgx—º@T‹.—%¢,GHbl -° "+.°é5e‰ìiµ —Â<­¥cQëÉ| ç›uî£;Ö߇>y&¢µ¡Z™%×êXGº#TFkëkت!£3yE1™R+®3h…ÈV™Lj… yê.yé èóÒ¹pÄC¢½¦‘€Ç5u Œ˜+ËísOœˆZ1ØÍ^'Æl?E$@úH²†­hHä8OÃIÜ1™©6nm^×%|N+×nÕièXMÖSyE‡âõÏêÿ{9ÿÖ|@Èÿ'ìJ’Õ•è–lÀ ߼nDý%`Z Œ}Ôê¿Ú”×ãt)•:ÍyÈtS»ÌÕçó*îW¬ãà:“3ŒêÂ5-7#z$·ƒ;’Æ'xþ.w¹§7Èc®ü|ß­ÙÑHîHâüï£TïÛy3Á:«(Æ–mßz‡ ‘&_ž¾YËÆq†‹Í»×Ï×ïq›;Œ´½w!¤PûûôóÙÆe‚oÓæ5Ži*ÄcØ[ód»È·‘$±þÕF>=ŒeÇë‘~²Šp¨™íuþÖáé0RÏ\¼¶)23&³!€°îpR_±— S^6¶ªLBD̳,hQw»"êGyïhô›znFª‘p¹u³½Ö5ò”TÓIÛò3òî LIW»|dÜ!ÿºØ>yr!AL âÕ·íºš’Êe)|ŽëŒÊÕåöߌ³B•¥Êmêûº™A\÷HöU\#ˆuÇ0¿ßüo‚q)Ái•/¹–KaSú^ë"CSY,J$-iÙ dä Å'\Êc¾ø¼E×!лÐÖ§ò˜iEùÿ…ïè|Öîc!I¶Äà‹„âÒÉívÁmpãÒÉíæM–¤(.\¦Ó º†ÙÑÈȌ޺G-g.þˆÒ ”>Äj¬´•ki”}cº¼°Z1 ¾S$Fo^ΖŸô³;¦õ÷.Á:šå+å¯ë8 ddwÃE§T¥H¢x»õì2R5¡\ÔŠBió²O~ç)’ëíXŽÜø{´Œf KnÓ*Ïçéд@5$7ÇSäßù—vîñ1D-ñ¯Ë©xLùx²®¯!‰±:})/ñÇO_îà§‘rUþ£3ft6F>–f¡_çóTŸ¹‚|r ‘7LÅRS¹e}Þ,éÒk­OŸbR•´.ç!7ÒNíò¦ý4iV_9´.B2ÑNþïUQ¬cÙo5B:af¥NÔãÏó»t_èDi¤óäÅ~˜€²æS6e™Ù7RIõ•}°þÍCB˜Ê3”ë÷iXiÿ&ù¥ge¤äF<µéY B†¾Î³%ó“[|éàÙÁºƒÜb¿½w5Tt ‰M:>wðLWŠ‘‹4_GWçŒÏ4 !>q¯àÞŸ>¯º6¯¬†Îq4kçiÔöëHü¾DÔM£&·Ä—F=á4jâ(ÑövÒÖW_¶ùS^­4à6DÜL䟿j¯\>NiF°fÔ𣈓‰¼cÔtÊ‹âßûýîCsd)iÖÎü.\gpíw )/ä\ä¿§Îþ¹»]8­'•\?¾’Ê·j,vÈÀí+žŠÂ¦ ’«”ÁMæ•cdàuDÝì1»t4ã”G•SȈ#›ÚÉ|Ä›œÖÎSòyêQé©gm ÈÝç©§²¯^™}—¼û†LxGQðª#HâôŸáïIaH^¼ù‹—  Ì4QY©t´é;mßõ>{äs¾žW†‘¯óu^㳓ãh#ÖÚc½áÚid|æI¥£ß§AȧéV 3ùm–ÏVn™¡ÚPóÑÌçM«ñ'÷Eˆ7¾ÔsÛÞuZ 5B¼©æwY~nŒpo`>hdh;fL1ï)«¶ÝÙO$9}“ò¿(ëíüÁÍuk5. Ôu÷ø¸Ú5ã<›>S½Mc'q¥ »«e½}òéÝ/¦P'ߟ¨bÑ£·â~SÚ´5Œó÷ÕŠr—M»XV4kæ*@7‹¢!4Ÿœ²fh|ÌÐɪ+=~ÖÓ’5à·Oœ,FÉ=P®r²lèÒêU‚±YŒ’Ë!t ¹Þadíç]J¼|ò”¿M–í£‘ñÅ ÅÌÁ¯+ŠW+Œô¯PX¡x…²wf/C‚£É”ꘉë¬×5ƒ§ä&îwšÄ.pjÏê:“†ÈßÏ/¾„¥ð"w6åÅò€Ï»À/°Kãã'¡çŽ\J†«” G‚È— 'ºFN2 "_2œôv°Ép$ˆ|•¤ Šx<|ò.áo+T +BžWJÞ…‘¾ç)ä]øìÑ)cpŒA¨¿ùô\„ž* È¥çbj«tWÖ'ÅΦÙöÿâ†ÎÞ;ñ0¥çbgƒù°-¥fÍMYñæƒRÁ0’¸þ0*5E¸3òq±¯ñÅçîŒô[ƒo¬F>fCªò¯Y‡‘‰Ïq©|Z´¥6ŒMqS3¾xg@Ð7ÐóšEZWAľï¸Pª) ž—Ù6Õ”O_ªi= TSôx´¸©¦Zlñ¿Xa†wÄ—À4)Ælß°“@¬øò ül³š³‡7Ï.Ê{˜k&̸:„ ü|I¨×Âû/|IÂû/|Éò‚/ cCx÷ð%y½†ø’yÁ—´Oéîqo2ìW{öàšýºÁ:2 ~a¿Âÿî$'ž³_wg¿`¿Úÿ(Øëÿl-€œ–H^Ô®Ó Ã_j#/jf@ÈèÌ]ŒJw1óYŒ[i׿ !lºXdÃËå !CdZWÆ:uYhOþqñ”Æ×â<%rµ*-0ÒÓ½¨ùÖúa¼ë^¸2Eh@È“¼NúÙV7¯“„ñ¥A¢u+&áÓǵg|æ\º¥òÜ㪖\û!Cé"Ÿ(FFŽA¥X"›§YÓjÃ×ù8úµÆ×˜"ä +ªÎ¾òYº"¤kÿµÎÂùô{ø˜‰?{º•a‚ú¯ªc'; 2s§NaoµZ«—kJƒòäßÀ΄XíãyO‚uø˜g¦µí^ã˜q#Ü}`i²Êëjcí@¢SóÅ÷ù»Ãâ!Ñí—)¨˜¢û/.SF[C¢û/.S0ÚD÷_ ÌÎ!±Á§©å°JI\¦–w«½£`§7u%ÿÞÇe\!„¸©aØT¹–©åëéM-¯3¨mjØé¸dõ”$ ½ãÒ: ®jâý¢Ê•ˆÍ¼ð–|nòüÉó÷x´=Ý(ºèéÒf¶ß{¡QÑ:ÈOÂA~°ÉÈ$rv'öÝ_Z-,{ácz½æ‡ywöS¯ùn“^ó Bg_Ýt˜²a˲n«ñ1ã3EWǾßï••B>O8Âö ÿú #“Só$±>Û,òáç£ c°/"þ$²z@1¥Ä›D&Í´˜RâM"31¥öÞ}IdJ÷fcJ‰“Dv¸#d™KÜ$²‘ í„‘Œýž~´NãÿNôz¯I0§‘.ð~"Ý^ïÒÖ˜bäi?{dl‡<ãï Ó¬­ûÀšë"5le© Ôb¤Ç¶*¶UpöÀ ZÖ¡È&À˜–kÿ.yÜ·4ë£: CXÇ=åú=j5|Úñ…TSàc†™)§E~u¬0&Õ©\cÿéPd8fÁ àÃ*×±EŠp}3«ðu2Áu¶]—6C;Cìjªv+¶õ…•WSõoÿ<Çu* q4U ÷Þuõ4à³G(î}â£S‰Ïþ@ЀäoJ6᳃ÄO~àg‡Šå9–3šaWKgažâë|žû¡ºÝÄI‹;õCƒnòx\ø¡ºÝäqd=«=pQ}¥láÏÞ ‰/Š?ø´{õƺŸ8iq6J‡ŒiZ¼× !Cx—òB»‡¶ /½ùŒ`¿M⨅Äl˜kn#ë»iÍ2»#÷°½(Œœj~™G$1_qšÞGÇ'X¾>]aña{Qÿ©·X'ï” žÂˆOH;‚öö›~©Ø·Äw¤Õ«Ôû©wä+*­wש<vôÂ.ÿ–kf§í‡íEIÓC×.ÏŸÒtwOwýÑÉ›¡vòÛ§ýçõÆ—z·Þâ)‹Ø}æfwÑ1 hÎèÔTU¾í.Àv ùCUËãžµŸâ3¦ûÛ"–ÐRêMж™Ûf†Ï»áòêÿçO`¦åøið¥=Ð`2g5]–Ô™˜ˆõ øûh/³ÖóåOÿ-ûÝm)Ï)q—Cu[ü¾ÆÅ64Tí/ÿSs½ìl‹½Á¦ŸÀ9Ø@u0õЬ¢ŸÀ§møBqÆO M/X®–”‚0×{ç ZÇý\˜‚¹Þ¤Ìõ,»âï’Ö*wÐñõqSL ꂇ»ç÷GåSI¥È§bÝÛ™bg„þŸêÞÕªf ->)>&ŒÐÖ«…Ï ÛÌg§ß±þƳCXûuÍòe©Fèˆ÷/L—WQã³?ý^Ìö›z^y17ßj·ÇóÊ‹™Wí°{<ñb¦ý³$KЉÇ?K"ÓéM+„<ñÏRÌ{Ú¿&„ ½ƒTkŸ|‚V!‡!b†šÝI¿<!Øî˜Äû}¾wÇŒ½Ÿç`ÿ÷Ær¡eU;z€,ù?´Ùù6±«}…;ÉàsÙ›ªÂ…‘ÔÉÞ¶ÚøÙÚÐywöófW/µK B&^G^›/ŽxýD"ÀøJž’¯#s¨{Û8ü­Cm¯x]Zºmœøv”·‘ÄCÕdРˆï§[T)=*¡‘ß}[T¼X£lÓÄxTt·:$#ŽØú\ ÿ¦~y*Û!/¤`0Ú¸á—'R°zî0òB ï’~‰¥`bKÚ•‚7üIÁÒ•‚~¹ø`]³±®´ïR䉸c›šGâèZÐ Òd?¼V.+²¨$1¹DZ‹J§l¶ò‘v²2~z¤`›tbN[ûä“‹øu±Øadpî…ÜÐu‚6Ž#Œ>µ/"ø#£³ ötã5Ã#ƒ#ŒÖM€Ó74ííFIl‹ïˆ°Qg‚/\ƒ$]#ãs+daD=`äóŒÑuÎ kL#“óŒ i¢cFÅçíÂìGhç¡ rÜø‹«Ç¶žªÚ6«Ö6ÖÀŒà$ošŒNC*/ºµYrûäíÆýiò&µ÷žø3:Á¼ßð1C¼/ïºékX`~On¾ù]æÒn–ð–ø¬ˆksïpÌ»WhÎk^€Â÷žsr m`í¾ëRU¦!âJ“÷5ÃGÖ =B¢mDó¿‹™kai¡µ˜`ß-œÿ( Qž3¿o<¿'¶ø‘ë#S±lÃÐ/Ë·Ø!‰§¹Væ¶JO£!6Kdt¨ÁÞoÏ¥ÉÈÞØÙžK‡$©_†²Cq’lV•è[¶x†¶úo›#d`-~…ŠXYü~Šjt¨ÍnòæªÖÔø™¯¬_«efJÞ•@Uhº4?æTev q’7ddfØi>ßWÙîäÌ0¬“Tqûu\PLUœ"ä)5nUTñ!}ÄAÇÈèÔèˆU#[|ö‡‡T¾,–¬8k®¿nîî·7«º f®Ä®¹~þbkü&¯Ææ³áë”ãüÑM/øR[®7ûþ3ø¬ µw;vP(7ƒnÌIž¾˜µzmó¢p¾â§/fÿGnÌIüÍßŬGh~³fïýùKÌÚy³¶C^Ĭíîý"f æ÷äé‰YQnÌšyòž˜µZ”•øB¯bÖvWª6v^q['¸Vï‚töØ «éëm¦µpâÛí‚iY×é`&ÄØMÝí ëD@>¥&¯¤R³CÈÀxÅïç·ô~æ«7ƒ wúõê]˜yìš>äØÍÞDlX¾&îØ8¼R@F^ͱô«t|»ô«p؆ñí±WUê ÁqýT¯¥ ’\¹ÎÔ– ßâÃb3Õí“^2ÕkèûÇ·çYõ5 }ŒzÉwõñ-ñ.%‹öâûíÃH”Sê¶Õëõ]º¼KVË»gñ‰jY|éeñm™ÙëÒÈÇyÁ¶ñ¯ƒÂ1ï‡À+ã%y t€ë ¼ÞQkµ ï(ŠÿÎ:µ)(ñ=ô´jÅÈ [µp‘¯U[“Ûª]-ïÎó{•­Ú3<_zˆV-|G÷È$%\gœ ©øþ¸—D~…cÿ“Ïêš?y@Æ÷‘Ú8§ò/¼=28ý:‘ªóê2t–±zé!–±eóM·!¡ý+Æn­=å¿¶ú– _§ÎÉÁSÒ«iªôµ;&1*@å/+ÿ͵àѶØ7ùÒW8eàSß“ƒ P•ߛօ›8nþ¶€Ò…éó›äÃ'|þ¸BíøhÏ~G ÷y²š¯¢ËÎ gJ5*ª‰{*†qùÂÈà„þ“~?°Üû)oªvwLสdª·ö¥ëôw>8º+ë~én»t/†‘Áiæ/Vé‹­o탫t·Âtc1ÒJJ¤C8Rع€ïulµ’çjÚtwö5­åuGû—Æ0.ÑqFhÙŒÝ þ÷Ó¶ªR‘ð79m ç-Ž^›&á¹á|W®pLâMxÖœ·!]ö»ñ.ešó†‘'ΩvN…™+ˆ=Ω9ì'Ω¼UΩ Bž9£‹<‡‡Ï‹¯Øå!ÇÁóè ª³Ë:¤eˆƒÄ£e3‚«eˆÄ}tð€´ žúU´EÑØÚ&¼]ùUð+€¹#¼4féQ­BêÎð1Ã£ó´ØæR÷2:¶ìøãÌÙPN#gzë¹nÇáÝߪE®Û±£ô»¿ÎøÈë›áÍ 0hûkäÓ³mºÖó€‘É™R²G'Ù/#o²ß ’ý:„ø:ßÖÌlçMýäo à)²RÛHö]ºv]jË ô~Αn¾>140&…Òpè­LŒ(mÛ4ýàÛW寀#ó®iú®Oóiwâ¢òÖ6Ý`äS±#“=ã-–ÓJ2ðñ)ׯŽLö`B'úôøì¢àÒ„n­a ‰44ŒíZ(B£ð¢µ),Û`‹Â s7A«€B,ò…Wµ2¼ÊÊ£ãÈ^ÕÉð*¶Gžb­ ¯bn;¢Rû)«ÅÜ}‡ ¬gbWTj>i°+>Á²W„$Ç@¬VbÍÕˆÏÛ8K¾8Ö”f~ßé qä­öû3SŠþwûYÄÚQ°}ŒxTgÈ FgXïŽZ¹A¦Ë¾Øg¯ÁŠáâè&yl>(ˆL0DdÇéÞªü¦~LÏãÈ1cø«&"šµ-_ICÉæÄCþ“‹ù.iQFó®k‰U\Ùþ’ âñ¾Ÿ©šùLÁ2ÁjýUl©±Äöó*²ºWÞœ=B>üe‰‚oý gç2$ô$dì‘ÅaÛ›^ÙÞ éµ½±G“ f«°½éñ1ãÅØÆì÷™_•KEš CÈÈØÖ8ƒLnØ0,­Ù4-l¿ðÍ'·“e°`Ë*saþ?ZÞOØ$%7´é”‹µÀyò¼·Á]™) lM &t|á@ÇÓu&P`{¶º00õüŸ_¾'X 9ñÿ™I]éøT>2ì[É—Møì™S «ZS [¾I¢I¼Ör³,XâëÌq£Óñ¥.?=Kî›l@:üổ‡ôòÓm4q#”<ò>»TO°„á‡ÉnG'Ò'뀕¦‘vÙ" H促}Žr¨›¶)Éó”Åß]}uŸ£-‡i4r-$!½íœjdnįH0żû~[†Ï®—->Ê=Z ôäÜ;ß@ujÅê5)i£Ì³©š_êÝ¿U‘&ú°´N¢Ë­Š³©±‘›¾ -’9òpÌaÑL.‡-Kâ­ ÿ¶íbï>¹ `ç_´’P+GÆkPÀ’%Y ‰& ¶²A³ ¤»¥ÒáHbû³‰]ÅŠžVN? ²•3ã³ÇvöâË‹Z-i÷Z6jŒº³$ÔÊé>àµÅótÌ4gÃ$³„\é2z«ËÈN‘]CȰ.c…™ÆÊêüº ÛnKò_ù_kx°ÂR¦0gwDhÞO°jÉR¯õBóñ´Í”4ÜHÿd^02ö1¥™ˆ±[ÔôºA\ìšÞCærOœ›¥÷óW%h¶ëþµ÷엲ŒëO×™¸ìÅVõÅ`Ù/™#-;±_ž8b7s¤egF÷"âJèé:‰—Ñý©ì¢3GZæ‰íÚ‰á³ûúÊìӻ˨q£õz­w€™»Fá)˜>Ó¿¤HÑvGÈ(”Rþ©à/!mS)å°CÒ¶“Kz[î 3x2ˆÎ5Bé yýÔ‡C°t„| Oqj<ŧïúZ¨•¶yú}üs²•í4 ’ÓÔ¦×þAÒëM¯]2¦A/¸¹—„vØ&¥YXòP[lSpcÚ= .) ¸‡i÷q»=NIÀ=Œ÷0|ö8ä÷߃“g–æcoüþ„ &¡>4g·«ó1媅?{†‘ÿñ ¢½Îì*7ØÅdŽʇ´¢˜,{ q®BNÒW–9… åÅ Ý0¤¯KÑWo¸#'cÍ8ÀXdÕÏï!£@ÆZ3¿à[²‰Žà®2¯÷º± #cdA[ã*ó}¿ VŸ%eW»ÊÐÖ¸ÊT¯çéŽRä*Ȧ{õ¾£Ì¬VÅÿ½†®å›?ê³Ä–0ü:s¸£ôRg¾:ï(½NØéF^éÌñ1/tæÆ÷R#“ÀhSôŠYv‘s{°üª3›¥éé6öŸÃ–íl–¦§ÛÈ—ÀÇ阑?O;Öe®àÂr,ùhÓã›Ï ö_LN‚|ße&üàcz’TQ¦€¤ô”0¨rIg0~fù•8¢ ½}ò9bxZœèŽIœ9&¹XX …™‹Ü/óá™-×’{0”í®_ŸFž¼Œ:È“¬ÊÅ«Iôã¡øº ù[†Q€kçm2ò–ª——›~“D[?®q,ÃHü³¶¥²È—QaFĶ4u~]ð%."IâË?TeÐãør$CÈGhùÍ #=sä]^ò¹]בäš|þ9!ƒäs› ›9ò®ï²nXꘓVÞeY¸.MÝ2¬¼ËKSŸmQF?ù[XÓ8œ^R|N-ïICùG²E䟮oD1Ò@½ÄfEž;Š*b$ νpè`¿ï(Ñ‚¬ ðcîmÙéisKÚ*+˾DÈ–áØ©ýËg—ö¹GKñu†ís-u“8a ÿjÒ—™ŽŸG1[¢É.ìs÷jiBĪH°ì€)ÙÁ|zž¹·Žb.2rUßÝ 8ù[ˆÍä/ð½ÇÇDÓ‡Îêæ·ó~7[oÓiˆÿÏôð:áÕ ÊCH¬3’ BöÅžÌD fÄmˆ‹/¤ÑñzŸµ«:¾ç|cdlÃjL÷8^cw,Ÿ¾BÈÄÙHÖÚÄu™§}/k ¼‘éŒdü£ÖmUÕ{iÀ:J#3'Ú# tù{‡­É Êu²+Ë§Ž‘ïŠßQî³èÜ[×¢3s¢n56ˆyò-_[n&°%sleã¾®Ô7_ïÕF«až0Ò Sã’ì•Çôy`Oš¡Û¶Õõ½uXǹÇHxGÙi"Ä:Lcq:»CÐj$݃ÇcžÛÏ1õ™šnßS¦½Ê¾àsú”åÑï™òmµ£Èk¢í«føìÄõ–S4õ¿È÷0| O;umYÓ¯µ®°¦¶-–mÃg×um±ißÈž]¿·ÓqzIwg¼Q*ƛ׫aÅ÷ÀP7+²3¹â]³¼ß|D5P‡ƒ½©ÈdþÇ^ò©!ݬòºSz“’oÍùUÏB>œlCE¬VÙ›Ïa…Ê@n¹yÛÿªüsE^ùؼëWŠ-•îhtÂmûŠ6 B¦ùÔ{Žò¹ó;<÷²YR à$R‘eÄ,Û±}eÏ'BÈ´” ùá+Œ¡YŸP*Ï›gÒ/uBÔA‹×¶”ˆ‘j=  f㛊±«Û’5 fÐPùêùÞ‹ŸŸÖ2’~^õgo†uÇW*_½‚6r3)+ÆÅwÛøhÕbèÃ@Kù‘JÄñ5²vkß§ ˆ-TÍté¸ }Ûã‡*Ý•dRJ–C»±&#g6ÐÔB©š¾»oñ)>ý^/ UY¡ÿè\Í8ÅLé³ø¾G å/‹?VÙýÒeÆ®iŠnß¶½<]k.¡&SUîúw1#ß]½ñ×3PY•/v]Û¢Ú×e[1ô. âÅ*— qàçþê^㺠%†Fªsººu«^Gõd ~±Â­QAE)EMKñåû°‰Ï«_¬"à#|üm± äÕ*óbaGTL•QrzM("†ž‡‰`ÍòøKhÈrLå6¾¿2rä'zã Í趃þ:ËãsôYÛè5 Ùšr°£tŒiuR¢Í™¿í{yøì ’Ÿ¨†âÀšþþ 3Ewã³±÷Íâé42 XÖóu6 ò$`Y/b …“l¼fÃPÑ—wT/[Ì/„|üFïR½ gO¯ ƒŽÓEæjÏO¦ÜƒPýCÄe–“‹‚°«úÏœPn\Né_ãøþ̶𒓠,N‹_àåá ¸*:鳓Ûí²è4Ãu’Ûí²èD¡ìCn·ë¢”æÈí³Åí–ï„ÊÝ ïçÕxkœ{~jñCHÄ*ëO¾ÚÚ_Æ$”ØXìó¾RÅÃtOnÑ_ª8zð ·G°ã¼—ól;Îä;ÎŒ‡í8“›S$ñÉ´¡‡NP<²#ÅÂNt¹]„Û‹†ÁaïÝ×ÚÐűBWŒ d|é‚Á€ ë Lœ(ã_ií²ëŽÏžø$ú©šÙË~ó%êÊyˆ#jþ‘ó¼û}¨ŒôËyVþëOHœ‡*9Oaï ¸(Dqç(kì½çaŠ; =&ޤÚtðµdUD¹í kv„|„"mßO8æýviËÀøâkOü츛"qÅ×¾øYà›$¾†¸ÔN…ÊòÃQÏ™âgÙ6|ñÙ±wœœa…6©øòe^þ9N¨Š¡–Bî÷“”¾mjJè†om–÷ä‚j›J{õÐ+>Ÿ£béÈ`km¥JתXûu¥ø˜W4ªo‰Ÿ]1‡BÆf†-Ôà-Æù£Øw¾¿>]­vÁÁÒä7_†No„L-…þ´n-4V42³[°º1ƸõÎÚ–ÁH{‡­FÊźøƒ¬_¾[w†¯Smmþ6ø­žúbØù¿¸øŒøÉß}Çc±½«WYv™¥5_0dì›T•y¥Ã(BzrRDÉ- B>ܾ£"Ënâ1L´nÒÍÐäåQpœiL €#Õ1rf_þE!dŠ‘5Èñ[àë̌ϱëÖ¬ýÈÆ7>;q‘zS)îˆU¯©DÈÜ$X’LJŸ|«ûzØñ“W¹ÔÍ7ÎÍSzºùûÝÚUº$[³¾êù¥Î=†ªÆ¼’©ù¸fUÿÞ,ÃÆ@¾‚4“¶Ä ¾§ GeK¼#däûòãÿ¤b†Á) ~y¢†·öËó%ZtÚ¦TÈß×!C›$Á…GÊä‘„>§àGîäÚ7¥³Ç̯|SŠ~¶ï>¿XVóå*paÈ=nvµQ0Èè^4 ÿ j¨¤$ zÛÐÙ’(èm#r—¡i6ŠÎ9Á8°Zᘋë½\¸÷èJ‚!òwaêŽ.%…~&‰.%Ó|F†$ïÃn>¢øTjmÕ®î|_ø˜É¯jvœ«‚-Ë{ÁwäÑÂÎ “ZX˜<£8¤…{Ÿ–V§ë$¿¡ºL†êvYÅ?åpMf¤L~u0ÞD¿‹zUj‘r‰µ^Ž!#œ`Óv:s!¿:6¦ulöy¦Q«Ó(FF¿ê´V§ÁXç&4+Í™Šc%„/ûγ]7¡+É¥$ñ1= £R’/qš±lVB²ª®2 êÈž§§DÌÇð…¤K×?û¾ÅÈÜœÑNË%Øç3S‡ï]Í^Zp¦¾yAŸà‹õ‚ÿ•0Ô;‚öˆäM¢,¼•E$oeAÉ—’ðìɵœØo$"‘Žé‘‰4PWND"§¥‡·Ç”­õkýÌpGyÈÊ–ÊÊÖŒµnB³rNiÍš¾šåÝS@º¹Ë’´¯<ø¼ëøNþŽ“Â?òŸ$:6ʺz™†…Õ0Ï<îAuñ"òXì¨üˆ.Ÿ’i1 däW€ïŽœœ´÷x!ønàä"{X)À†±Ÿµ#\Ì Ðóˆ3ê £n-é@7¸£!KHJß -Üó42úM³›×®ø _`Zhäþw#”á¯rZøPOñÙfýYGµÓoµï¢­‘‰7!oغn±ßRÌi;–†Mß3ó&ä ´«÷Óó}ºvØÅðþt`C©‘¹7!ïh… '<Ï4˜#(dÈòˆÕÞÿú8ÌŸº=ìSJ‚1Œ“ßž?›× i B½<ÛÙ¾£=yü ÃȇO Ù 5dq೫ëÜ5!Z÷c­§ö‹‘‰_µ)倌®äü©Â’Dá„™º…ŽSüo!½ÀÕóäó¦0˜Y2òuÂ{e3 ä#˜äÀ`AïÄÿþ&90‘äÀ2ñ̘$|G©7Éa‘IøìY(Éámg™äJ]`Òœl>3÷›"Ëÿ&ÜQ|aŠ, G=BF^ë>¡†ü—$1©qdP»6Ï$ùK§Ñv‡’¿u)F†M|G;2d—&¾N§1¹î4ÒuÇg?õå:Hª†½2HâIÆètvŠ`r¶ !A8èä/=cêv«Áý•Q¾²‰ q4¸~Ë[(–ºzYäW#˜Ë®_ Iƒ~5’amýjHzÏȯ†¤Ž¬áÏ9¼}îûFEG4i4£sBÙ²Éq¤¾,/6Âv7Ï™$®| ›míŠ~M3-Êr(1òX]8Æä7»Ï0ÁÇnÞ…sïqˆ >Q:îûbï=TØäkZ¾[æbGÈœ¾äidØäÏÎiŒ¬æ\CèsÛ^Â1“0›æûª·Êþiò˰Vrá)ä„Éjäß=U+¨´52¶f:X+º‚Ñ“V WZ!½ZqV+@œ4ÂßvÔ à³{¾ÞhV„ jú§ý–Ò€V€­CÈ ­ÀŠI‚¶5“¦ö A;Ñl’;¸£,íC×z‘Ù>p$íÃt¶Ìެö)û¡0ˤ$l]ˆQ öiΞbÍ`¥<$uÜr$¡¥j"ùkû67ø˜OìPìqs OeÍ%t‘,œåÕK$¬X±¬|ÐM)]ëý3#¤Û–ÒM%ûîGc §‘žšç…/‚åeá–ÈcY(ÃÈìUêR¿M>U’H…‘ž9±çÚßÖ…†Ø4Â@åVkY|]9¡FÃD²ø²r23F>BaÜ=hnHv"!¬%W„DÅßÎHâÖ½·)”$Kƒ)”;uSªH–þˆ&MÒ}‡d!’ýØäŸ|;ìó$ñí€ÕoFþâÛqB†};@äG<ÒÒSè<Ï<z€òiI–ÿ%ô`Ýò"ôf.›pèI %røB¹ªW©È„ÜÃ-”ŠL¬\Õ'Žw,Z‰+Bõ°e·ì‹É#Ì–Y–‘Gç§aˆóÿ¦«3#$0ÄÅÛtÖ‰C q>m¸NkxG®ÓšFÆÁ,/;Ö¹¹…B P)ë}Ù˜örù@µÐÍ-üÍòzovæB¹…¿Y^峡›[èËòqÜv‹š‹ÅÙ×¥Ÿ }•[K{XUÊ/DfŸ.%=]§’O©Ý®¦^LKñ­6J¸F¦¿ë%A¤™Õ Žy¿JÇuüÃH~ázÌN`Éô˜Cxad€ÃÇ0KÉô˜þ}ØÿÒ£hzŒÜvHzÌ|töÞm *¥Zö]½‹º3!â¤&þQP3ó¥†ã„ÄôÉ£—ô˜c©NעLjž>¾ÎA#ÿDƒ q®ÀèdÅ·£Ü-’“ _r·HN‚e+†r·H–Ñ3”»Erg©|öéÁå579—×D¤[^Ë/–ʸ¼–çaß\^Ëó¿”×f|Ì‹òÅÇôñË—×òüº¼Fw|Ì@yw¶x’çÈh[ZÂÒR3¿Ý.,-ai¹#$ˆêäB¹SÛ.Ú½è²ûÉÜ‘výïÿþs-J…7Õ`34ò›Ë‹ú×A iB×—àjŸ[ÁˆºVi¾‹‰îmË0R2‹'_ÊÇ©¬q¿;{û!•Èæ_‰jfÙpá“ÌwaãŒrñGÈJ£Ïùž‡=·í‰Ïžž6Ñò!ÉM4[],,Å&Ú¾#'7æ2]§’/¾c|©Ê— à®—»y• Ñ޹xΓqƒËon£ l äb ]‡£î&†.³VP™5×VGÓ#dìJN5÷á˜é64ïr@ÈÄ™> ±G$ÇlÏÓ¥FÁ¯¼j:µi‡jYÚ'Bªxs©v6~”/©›²¬K|ä—Î!ìfù§6Ëù->5.+¶ÒµqÍo zòÊâBém_´+?ó:#¤k[-Úú*!ñë\Ë!¡<>(ÂuS=ul¸ý–Õ™×7ô]4ðä3T®´,7!ú°º„Œ¼Œ4¶~§¶ÆÇ|˜í¡Ë ¢Ë³©Áf9w$}ÀH߸ºw{ïYÐvT5ëgŒL½IªYï(ûmÁ‹Ä3Ù‚’x Gô(,Vó¹»Z¹+Ô;Í›ƒâðäývQ[3Çå÷Û¯{™a’¯®~!ÿ®lGvT þR——ªâñ¾Ÿ#Í|ÞWª¼[óõ—Å$$6nµÔO!—'™‘¶§èYè—}À<‚[‰eþî1u£*ý+ÊÐÅ´k* y„'ãîò(›6Õ“yT™0„ô¤U…7o³!dtiq"™Gxö·_€|D›5Fé ¡(Y‰%‡á9®›U\g¾G÷‰-z(µ—Œ²¢ÝÍ:z[û’baÚD¯jh0ò ‡” Òþß“?;0Îäë*%’åûÄ Àz ¯E¹ZQŠex”® mü4aû{“¹I‰Ø]]$øñ¯”€%ÁãfuŒö꿬†‘7«¾\ÁÃZ®Â±íúEì¬+…cpý"¨ËU8”]6%ÆÍõÜüÁHÞöc0yéCÎdAfrÝ¥Ó+ëËĿɓÀ(=‘_ú…èȆÁè¾fxiÑâôÑ‘Æ!V.ëÔMζ&é ò\–R ÜâkXÚÙŒÒÛWÈào³Ïyd ÷In:ï( £ÅŠBU1švmÖáûÕY$tlSR­ ‹“)á‹nCÈÀ²8QmrâmÓ4ƒ Aßo#8« diHøãñûåÈ¡)Z°8!á:AK* z›Éç3ÑO5áû|jé2ªÌÄ5“„?ÓLuÊî@¾ÀhC2jÅÀ‹~gpí>ªë_¹VåÑVÆ7°²„VøI Ñ+/uЉO€víF‘ø#_)·o‘¯ÜÁrWCW¶-à ˆ"ó>ƒëlx([ßNÞjzN§½I—¹îa ì”i)h~ÜîËf³!dñ-f=²­Úð5CÏ1V¤Ÿá>ÛCŠm®Nì¦C _m¶ßm/×4¾= ý\D‘Y5vˆÄ6x¼f|:Ã×­hô¶›iÿò³¾7!äoÞüë^4šn]¡ó€mÍ d ï,”÷Ê þ‘Áã…=¯I „o¿=ïPŽ+0u¤Ïž·š@Ëä@úíykùôªžTò¥g²² — OÒ‚¾©¾³F’ÛêL•bÛ6bí¢ïòö–0—"oµkžtbGÈÐ$dL­m¢|k¬á½#ÛF,Žüóœæu×ÔÞ¦cÛˆë8ÓA‡Ø¶2Á¥"»ªîø)™iü#¶m㪋´’ЬMÛTØÜák¾Ï†R„›oL°ŽŒm£SñU¹ïžîÎé-Ô6ÏÑj»ÒÁùùÇãj}°YrÃØ?ü{_FüDŒ¨ ³J!´SÓ~û‘!dh…‡ú#G²¦nsØ¢Ç9±U–#c*¿KymV*âà†r _¦¨Öù¼äÂBBïßV'©ábQ2iGm€p5òòý+aÚ€ïO¢Ð£ÔƤRŸ}#B6å*D¢è76 CH?›\…HݳiÌ·+Š|Þ}<¸C»»èÄ(±•‹IÿÂ(ã¾qM¼f”l ¾ftÍk@_cË5Ñá’·ŠKßXÛ5ñÌ%ß*kŽN½wpÍ-ý A;¼:Äݨ$`†[ݨÆD"ÈcϺIèF5F^èF5u65£Ñ:‘G j[·#cÌâ?4³ø`.Œ|üã»i‰l·%£ 4“yÿú;ŒÛ°ŽÇVÒÿÄ{Wb;rm~Ú¡æž!¤m¢IJ ðÐö«-‡IlkˡРS3ÿ—´CÈÈJiàhÚNŸ´Xñ}‚‚d’ßÍ:gC–u¾ ù4,Õù§4·´cÙŒ/£†œš°Ý'XJÅ×|k-*)¬N§SF»a¢Zº”XÞ} YèZÆÔÓ&ef<ò?ºB!ŘåvŸ*ÿ°eË(ð?’#ÂŒ+VÑ®Úsx¦1o’\Zƈß_¾-ÿVI¦=?HÅõw«~`[24H~øP3t®hÎ’*_ÒyŸÇáü3±uƒŽ®ø¡\[ÏSNùV;,B:ïSéKóp¾hç/EÈ—…TÍb²ðÐŽlé0òm#5ÇMüPóEHb+›iÑæŠÛ”÷;ùóêà_^tâñ%ë1ôaKAüga×ÓN,ý`(Ôð’\Ê•—Ò8çÛƒ£‚Ó,§…°+ÕÄ[ˆ7€ÖI^9§ˆÀäÙÞ¯)B†¦=?òÚM›OóÜox¡æèõW)l¥ Úö‰ö¬*m¦aìspöɧOÝ'ó†¡î\7ª+Õ§¢u‘[üë‘®áñkÖj-ó“üRKõ¶Ø4ºü÷÷hN8,÷dÉçÞlx‘EùrT<`\{ÈàÜ5¶í’Ê?"d`Of¥4*”?JÁ¾Æ× o¥çoÈw¾æMà€øy¢5ו!¬„‘ùŒ6OÅ2Ú ñ µ«™Æ ™ek×ÂÀøÜl\@Ý…¦i 5<Û\ò¤7“ñm28Vc›(â~Õð0 Õºé³äŽx !£kÛÄdÚ21b‚ì••Lô$I"¤F¿ø‰ž(w¦³lsÒµ†-K+“™–±ý.©óìï 2ÓÄϧ…!3HríÅR} AIüϵáH3ú°×‡Ò_–Ê8)< ÏŸ õ¹¤p[±š ]õ¹ ¹‘ۦ¶<ýó¶ÙyÞÁw‹<½f¶Š räyWm‚çg·Q«©Sôe‹ÕFAžÑ}ã'…ãÜ3öë˜9c !QCú‘ÕOö¶ËsÐú!OÛ´µ™sä´Ì£Ö×"ÏØãĨ4å i–Xírn›Ï†ìO‰×5QèÙö§òÆþÔ¹æý)|Ÿ¯_ìOaÍ=_¿ØŸ:ÈûS8~<_ûSA1µíO¤ßþt€Ãùóå±?4KÛþTüý)d&¨ßþ´ñ>®^“ôo ÏØ6˜ÿû×b«“ç˜ÁÄî×û{êì[vH$Vžrƒ˜Ø›ö©Ø«iÛ =P¯”W—¢vr¿É>´l‡œÂ&öúñšû]P¿Z„ }52s)K*»Ü–õ2 ø™”yȹ¡`SßÐð:w™ ©)SÐUÂ^HÒ…ÒÔŒĬ¯‡£0&ˆÄ4Ùöq_6 Õ¼—{HÏzžÐ¤j¦ÝªÇI²¹’ŸZI1›%«òÎ%&Tp–ÒhÌ6E ¯5ÔZLº´‘L:3#O_0R·„‡—ðDñ#£hd\ð+v9MH ûœl~ýyRZ=Ûª´m鈗>ÊMÖ}g:àk†×’*Ò!xBÈÈÓö ¾´MGS¾¨67É8�QøaKãéM ‰eK¦…¼ü ÊRR¶û÷æ0I‘²$Udè•T[ìi%ÌužµkѬ•I­¿­ ïR|Źϧ_|¾Ÿï$)~pTDÀ禠µ#ä…L ?( ™–IÎÆb±1YšyŸŒ+ ÅD–k2nÚ«‰¼O±ía*į¹Tt£ËŒ =˜€æ¤hÌVcOÞÃÂÖd¡R¸¶¦½P8è¶Úö[Ï ÆyHÏn¡C×Mf[~‡(m´c¥R_š.2¸ h½5™y¢ðÔdOÄçS†¸ô§ >“íøŽ®ØOŠÙ-ÛS€oøŽnDËÒ´Ú€oøŽOÎІ+”Ï!Ûò~žD4#5·&éÌ=O£¤y»”ÎüÛá€i‚4¼]àØ6ßÌð¯G׼ݒ$xßXa)²zèŠ#WßçH‹f&|Ÿ¯³C£d kãý<9CGXïôˆ½_·c½ClkOwŸøir0OtUÔ(õ÷ˆNlÀH$M¤4@DKV³±~ÇÈ i¢YJ±N~Æ´ò$MĶiÝGóìï[”µ7ÏNîMP*3?mÉ §ˆÙ6ƒÅ/¶í-€#‹¶¿òÆÅŒ'AòfŽÁ†0‘Ò×$7Œi**÷PN²m#ÏÖù`ø\¶m¤0Ãdù-nöï^ì"GÈÐKî0ë^¥bãBq~ë² 6n‹¡'¿IMG±œ OùÍ¡l† b0 âu"[Ýg©Êu5 J cÑTÒ¤äÛ\v¾†´Þã\(©–jn5%ÿw;¾¦r.üWòv+U+XhOû¤™*|MrÕXÙihL'äFf€¿f"Ë4΢‘d!‘?C’i„X2l_{sfHìåk3g†ÜšûÅlœßÎ~âÅÈ›bF>þe†Tøš73â:ÿ2C<$>ö]¾…À¶yIâ“Ý!ZpH#Ãk_‘ÉøŠh$’ÖP]¢;¤*Z]IÒÈbD¸c<ñ5Ÿ>ÂÝ®Å-4òÂäÛÐ…Gêš]¬‘7$-þur–U–²‹F`Œ#ƒÛ>§•M0ž·D`aÂò"Ã#¿q&ÃÑ‘/ÃSv†G#¯+º,ÏõIJ#¯ë‚v†G#£kª¡ ^5ð뱟\LÅWvƒ'zÞÐQ ᘱ!dp!5*EAj”#_Þµ9ÚR£Xë½:S%hWGÇG¾]¸BË—6K•Óæ°–×HDö“ã.{“d‹!CÛ²]íŸB©à1õ÷IPNUUðÄ5™(£tcs¸¡i$î|UOÄD¿Ü7c#B†šL%®©èƒâšK?¤FF@»&ôJ5¡÷ŽvlÞ2$¢Zæ©;!']ôKŸHù¦ý§ÊR¶K"Ë"ÿšŒX$O)«,sk2VŒSO |Í·1¶/Õ!œRºøš2Ï©6 ìØWœ»h‰ŸèHÒÛb^™÷qœ—¥Æ}³B‘¦®ÕïYÉç]…Gôé‰ô·>ÒAߌ®ºI °/˼UudyºNóæÜkd rk”i:Wéܭ΄ŠT¾~éP´½Ù™ 8|©@á70´tZZçLA%Í”6iÅGà3ÑtÈñ<}¼ TŒU!MîúqšÚ­p Ä‚ I†RBÙ4±¦À7üXк”¾Ý:}&pB¨éâŽrCɶ~Ú¶¦qæUXÐZ.~ÊVLC :©*È™µ”Ÿ‚)~±áŸÉv"¥Œñ;MÇŠ-h­ˆ+*n4ÝðÛ ž6Tѵ8tb-{}\vh ðÛ®k9|œxCX&饺סLÒmwn€@t J´b`;¾±”óþÅ7þúÈq ê­þÖÙáF Phêk[ ©ñKù—wpÖvhéŠfX´B»Æ†ÃLUõQÖÌ„ê~¬02u=¡9qŒ+ªuk 1wv†ò×tøÌô©““‰ÒËW©ÑýSÓ×y¬—‡³ÆŸt ª{Amز®)—aŸ,Eþq^±¼ÂŠ\ß@ŸÕEæÌ¬èÇGp«k÷ƒñ°t  ›‘N÷O&çªN²ýH¥–CÑO‹sUu2ùûç_%pz¸=òSÉ2'ÎU#MWå•eú²^Æn)†‚6;†*0ÉÆËŽŒ"¿º›i_:WU-Ì2ý§g‡æS÷ÕT/€Ê(õ0,ËsU…¬›}œªrªL´¢ o­Ž*t³¶†› %×fæ–ùvðóøñ˜oK³ c¾Í‘6ŽèùµÌ·5Òo…`â~dÛkרYc[´@·FçÊÙ,+g›‰û‘m¯]“ $í¸8׌.t-R&t-´’FÆ—âfÃçóÙ«!¯›¶öa,‡#_—¹­ÙÊmqdèÏ—ÉÚkS#‘qyt%3“ƒ bKa௅l¦½¤KŸø>߯ŽUf#d^ï#–2|M_n’¸–YZ¾Ó6ËÐo]:FþǤüù¯çG7ßäǾ£ú@79¢yóh|Óõb€*:œâøI.`YÏtžÙʦ©¢Ãýê{b_T|Šeù–¬,>ø©äI{ýó¯ØD«CØcæotO68Jæ¾ÿñe‘«Í^|•˜ÐˆÊ-ï_1¥$PŠAÐnDz¿yÒ¾”h*È‚O¯ôø¨¤ÇaFßIPc§‘7*žðMÞwU¤ $8òÞ85ò‚—õúªYÇä`r6ë+T¶¶±u ƒ£,rÑRZQÚÂ79´Œ ] §ÞÒpâȇÇ,eWf)Ÿ²EÈK÷؆,M·!C¿.ÿîÕûÜË#ýzŸ Læðá1Ká{ž4K<|Üš¥´¦–>~ÓpÂHrîYúí328ÿ…·šm"ÄHo…]†¡«T*-¡»Óó+¡Ó±æÄ¡;ÝZ„ ½q¨É½‡Ö÷ó"•/Œ½JW»yïæ«¨d­ÁðSØ€l KÊ‘±O…n`ÂSÛzöçÇИ|~øÛ\U°ÏG?»©òU–#DCÑÃo>CÅ—Æ3 ¼†u9NFúYa$Q¢à–¶jçqô°ÂÒµšZüë±gŸßùÁx†¨âcq&ù Iª$êµEÈZDîó‡ÕÕÆñÍ+Œ¯¾ê [×Ûg…lGû= i¶LÔŒl‚D"{ ¬§‹ƒŒ|çÎ6w~=aL[ìÊòÄ ¢ïù4H-»Î}ï›{Ÿ/ÓBa9P×kÛš¬Ld¢Ë?RFÈÉ7,n ›Å‡À5ÏÜx0“TV«pŸ/žhßV«\ÚNòëµ|7#‹%"Ni¶joö]¦¾›‘_I¿¬&½ï…_v£7jžçïè UðwôÍ¥pšŒÞ® r¡Ütø7nÇ´ñ5 ²;íÞÒ¶h’ÄùuK AP&•Ë.¢j–á_úegÖ !_f½ùöò0kIü²3òC¸ÎÝáðùÅ$U; |8‘^†íü((Ú–ó#GÚrâW”w8JÇ¿QÞaÉÅ¿QÞkÞPÞaÁÇ¿QÞä å¶›ø7Ê»y¢-$+1RùNó•ê"Œí Í뀛5i28§PšZ¥P̯Gh”̳ϣJ¡˜':¹^jºÕ¼7éF[ƒ¿¤P–vÙëÏ'‡ jÄœd˜ҼKÖÚŒ<¸^zÈsæ‰â{òœIÜÅñ/ä9sŸñ/ä9ç×oÈsf~Æ¿ç òù yÎŒÒóòœƒ¼!Ï™'zzÈs²AÕç4ò†<I¶øiD €jvÐYæ¹*i®«^–¼mE¡,3æ‘•Pú_÷5ãù®,ÉA[nÉ€á³ÿûFô[˜A¶@ÌqWÿ4 #,QQ`&éL™ù¼D>'d !{WC Úú û»(?ž×HÁñ1ÃHaïç3ˆˆu‰,ãˆ9j»˜†gË–ÁŽÙ=žN™K«¨;ß*îÈR×Óéâ£+ €^X ¸.|yaÅ“Ç_(PèxdA=®ÍuWÈü¼Öšf£tÌ㬄I&h±ŒÖ *k÷oŠq°)Ê!\L£½ˆO5Uô"8füãxß—MÛ™2º­NS¯ ÛÿHb™†®@LC ²ãïw©\‡’}ík÷`ƒ¥¦Ž­S 6ß` vd JO/M‘Ãâºål­ŸsüȤHizYºÙ) Å¥¿AZÌE÷@ÌE ƒ4RUÜ#´ûÒ쬆ſ~; {ìã$‹'â9Ï=¦ÛT§Ûùüñד­ Ié8¶¦Výü¡RV-ê.Mò!Ñ×ALi‘T¼ûB&^ó„—cž qÈKÓÈØ›¯ø™\ÊØoÖǽö,cO]{ƒôÉØ+og§\ùL2öR—”môm¯(ùKÆŸÝ#cO±Œ½A†dìGgœû™„K  §“-1=;¸¨Ú§f7–ý8n¶íó¼£è¦„PD+Kµò¡AÆ>Á¢ëç7³WtG;<Šø\·Üóñû›ÝX¬ e³@éæù@¾mh7®Ç²µ¹ÔÓF‹‡ËŸ‹³O|æø˜÷pa¢°gŠF°„•>€tý·eY"ú© ½)ÈÌc)£Ï΋ùÕï->³Óµ#äúƒL|NtúªƒÕÆ:÷*ÒÐùµùÄÓ±nðÉðÓ1SÅ[ìÅå4½úÞ …ÜR˜ŒÿBž]‹u¬úöé ÕŽðŠ,>×Ð Ènþ‡28!cÜJx+mG[ížÌï©ÖO.[°oº¤uϪØÌ_¬Šâwî±dqX{»%Ý¢CÈ$´‚vø%sÆ£ä!Ì)_>oŽD‡1wlî×ò ×µø?îÓH±Î7öwǵ؈´‡ÝßâMjF„L|÷sü¢]&»mL6Ú^ÐhËîÁFS6úBHo£mS;¬ÉÙ=Ôh›÷®Ûöb°ìj´™kBH_£­;møìÁFÛdy±ËP|?/h¤°Öek)12¾ÐÅd¿£qw¿ŸeÏp³‰Kꊽög`œ‡H¾z3‘Ó1=ãÇb;6³nèh1ÐÓÙSÈéK:6ïv@ŵØ=çöb/6ŒÌ|åAú5ÓÓýÌ=F[dDÄØèv V ‘Ú¾æMŽnQÐBŠÉ1X NG7ÚÁ¶¥âsoWÓdŒnÑÕ»TL@Œˆ,yÙ'BF©ŽnqÀÇ~îÔë kräZ×bëR ÍÌÏHýÜý4qÛ;št)Ù6uU+Ø>Ný8CŽp ŽŽy ºô-¥›15HP'/µÙ”ÔPì—w;-í ù´&ÅzÔy1‹ ½dæèf¼ïKÈa#‡í+à;Šn÷«ªߌіA†¿b#¡h‰w [F€ÎÝQåU¬§¶¨V|̇÷ÛäêÛ2õM˜R~Þ1òŒÒ †¯=øzºŸ¹OÂEÄŸd7Rr']QbÛdéý "뻥#ø˜‰×Óä´2\ŒªžV†4°2(1k´2¤aƒôÓʆl9kÝŽCtûcD„Ÿi“hߺ QY»ZFtË‚¾3ÓØwŸÎ¾KY@*XvwB¹}îy€âóŠOäÌF]³×@0Š,Ív8ô§·}“]Û^Lò¨]Q]È$Ë8yÄÈØ­I'´![DQ|!’&?c39d5Oz‹HƒL¬³\CŽk—ê鬆÷`5{äø˜`5{Øñ1ƒ5j‘öMùüul“ÒË"´)(¾öÌ_Í–ÁÀ†gŒCø„‘ªêÑžªsüÐäJÃ\àáƒBfKªijÍ–òþWÓ”!d¸ijÌ– 2Ü45ÖDy¥— gü$3Fvc¤§=c¦ÁÆŒ*™Í°Ø]°ê6)ñCìÇœõ7fKpÌ?Ëpçÿ*sØcæHõÃUÎo’4 ×áo±Ò•Ô;,Ê'nžÛ+ p¹5È80}먨D.·Ë£¢Bœc&}Ãú„pÍáLù ± PŽïá-Abòq1÷ŒÞ%Çc÷?ÿ¨Ö4ºHÁûv·Ç|:ê̸‰2×ó¸°€ZÖÊÿUŠ¥JSì­5Å(më)¿jšQkºµ­&„Ô¥(å£óÒT5Æ3—â¼òZ@F ÷ý;×;B¦a>#,ôqvÍg´‹rœýÁg„P ÎBÐ׈øŒ2XŽ!Ý®¼€ Y‚À.¹²§lä$9CÈ=¥ì&t™Ø²¦v’eM)CÅmhå:üÎÎ:ÝÝ÷7oÄs8ÝUä8Ô²ÈVŒba(G|öôW-KnÛâ†A¯ÈqøUj*Pé™ ÈHñ]ÊÀ ‹½«øÖK;^„Ì +¹Té¦Z—¶¹Ý]Më.r~Åêm<Ótt³|h7½[üCµÒÍ¿ÿ;¼24'BñV80Y£ÉÑ#¹.éÙqÑ@âÊÑŸ‡g+è!è=H²ÿB¼šDW$û݉î’èšd?n™øbK6ËJ lžI8¶”„øÉFŒI¨ÓGu§ !_Ì&;}Nµ!‰§cÉ·ô; GÈǯ¸ì&8ày2î’³{Ç09*:ˆçowRY|‡jå¤{!dli¯ž‰Sîe½,3AºI*Pg'û™BrÇînZ‡G±ÅÓlÖ‚‘ä~v&UB<Úø}î_ïnCÈôb† Îþøc†Ê¾u@€£…:ÀH Ó€5FZY³(ù‘J³õ|׎K Ÿõ|ÇŽË /êù%>f¸žoì¸ òî¿K²ƒÛW’ýa¤cûüÚHgg ÓšˆÔD¤®g1’Oc{œ!hJrgúgܭƽ;ýÎGØô6ùÄV€Ï“f£’d?!Ÿ{ÞÁÔâÌ~ëÏâwv­¬?S„Ì=5®Qן;|öÃH­ßT¯ßÅ„jŒtÎ3ÍDìaçç`À²`k ®µõoÁöåDÁ®µõoÁV|02T°¥¸‡‘µ¶>iH*‡[*²ê$)„HUvó˜îñ/MSrÐÖ•Öð;srDGá_ C ÿº9 ÿ{ õˆ9ÝÛœËîëS\ûRÍ+0 £{.EJ/SçΧᛷÓn7î»Ç)†ã`|úF1õ¹®™\-”>uµ0H«…8¦ëjaI 6Pˆ×îRþ£KéÒ\¬þGô¸ý¡ÿËkÈëÕÿ€òÑãö‡þÇ y¡ÿKèãÐÿ¹—«ÿq ÓpŽ £C™òçˆöìQ G”ê#(GtŒƒqŽ(‘(GtŒƒqŽ(p”#:ÆÁ8`“H”#Zã`?”–¢Gân“n™+Z@þñHЕBêp‘t²¶ÙPŒÄÁ@£ßº—ßÉ…äYC¶¼A ÜÏû_AK‡WA EÈ‹ …âcÞ}¼`ªyÁpE€ß§D:~Ÿ™†[c"㟿'¤Ïï“3×ïÓ CJÖïÓ /ü>w|̇Ãmu2)2iúîxýÒõûò©£ËP-ø˜~ŸÿΠßçzÎòÂïótE~Ÿ„áÓG  ¤‚»ƒVíÃúbö)=±^¯B*!—nØÉö}³!ã_e¢šVíwœë‚!dbô†¬¬Tò¦u»Løìw ¹¼Ìðõ°ííú* »*?‘^o¡•}Õï¬öM,·,#z•R ;t‘ø"Ãßáá¿K¯ÒÈã ]>ââèºÙ'oéUÛÿþ9T"»DR5´GÈÜEgçÎßïk<Ýù›‡aDºM1Œàâ³ÃHĺßÇÒµÀ0“Òœé~FbþŸansç”Bä@’ÃL!Ç2öÌiOzN r_¹}LeóÄz¦· /YÙ<± #c_R‰š[ï°«~|PG8=UZê¶juãåCXûÚWØÒÈq’4ñº.±lEõá_8ûo¨¬ÞyíSÑ–„ï[Ai=f¨ª [×ÙqŠ%'u`y¸>~åhBêá°Àü3öŠþ˜ L¥×3Nç:}\VØXpš^VØ6ÛLÓð,ý6¶›­°¥éu…­ØBZÿÒZ>#.ŠDngãg6 ½e«S:fj”L£kg ÆŽÁ¯F*lo©°Úˆø›b¤~?7}L=É/ŽYŒÝ§(BÞƒÈ`äÃ8"äwZ?K…ÏžšÒòKùƪïx*Êòµm%CȧV+ëã•ÏßêÛÐujG„Ì©ërãžëo;må ™[±¶†hIüχ SÇÃg×[üÿ¨Ì=>ä3uS_â‹×u ©ÅûÒ%K­È´–Åç—u q~­Bvhõ5]ñH³õ†&¡6÷hç„Ò+±¡V| P‹´LÅ£>ù%[Îm”æ4Ýà ñð­ÀVGGX?£ –¦ìÜ›©Ä™¼þp½%íÙ<§g8Qe¢b‹2¬BÉóag¤_Þ˵µÈ{ÀÖN#'Ü9|9¿­ìÜ_ÎokûÇó0’ɤckg_óTU©·æ©ù¸Ð‘k=Œ®q,âèç¾ö°'9Ö­˜K Ÿû¾¬bÏg@ K±s1¬Èoò Ò{²´ŽqƒÇí3ʯ9x¶Ýù̯9xgd˜ƒÇìsϯ9xg$ªC¡è»f?= p] jKlÙUTŽÇ(ƒÒy·_GvU¥·+XvCV£î´_Gv¶Ò £ð¸Èò­×š­Yœö“òˆÔ–²(,ë&§ý8ÃǼ{åçd!ÒîñYìч)ykAgñ©(×äYФߤPÒçe—&…ß`Ïþ0)||̰Ý‹ãc†-è@ñþ@fVõdA×|—rwƒH¬ ?!Ê’ŸŽWÓ²˜ß´EÈø$bô/‹åŒ•’šU}³½l')KU³e&//:wm»@%ÎdžääE¦¾õ× &Hí÷ Ù;%”,Å‹<ô È È' lÀ3¸8è´ƒå@ê4ú3í§rÎ¥hZiŒ‘¹×–ã‹Ð9Îü*£º`e«Õ["áÚÓËýhïìçëJÓ½ˆeY0ŸÙ;7ʲ}”R±öQ‘ÃÁ;ÙGI¤c9<Ÿ,f_Cq3¿]ÉbŠ;ß{~;7HjcG§eåýbzöytÎxÚ|šõ(ÿ]?ƃ8óPvÝÚ döƒ•6¿à0ã˜6O.cZnÇ„òe>ʦÑr¨--&ú…瞟f ê$ßdnË/ù"$>&9ì£hñ^vŽ‘‰õjm^5—"õèÆ†QóÓlAeŠ›ŸmèÄ-Úì]rf ´ØþQ,þ,Ã>O]ÿÆHËÍÐ&îÇ×–l#øìOk|Øê²À»úÌ §|]*„Ì R©¥©”shº¯”…–d~·º›ªZe—BªiÜß»8þzLH0T—WS“ßmIi9í'häjoËßÙ’z¯÷¾ë¦ Ÿ?ŠOT½ö»ØçJf/ÿqýèEN‡±«¦®+‘Ò‡m*EÖ¿!¤£{hFGY·Òu_ê#ïøÕHùŠ.Õ#o¨œÏÑÐÔ¯“Éä&Þ¯ã8õ/„t›Ž7T¾x«|ñ`ø&w44¥ƒó:±½y,Á¿3wL˜jí+$ ÎhM?ÐàÏ…vó>xŸvù> wN/ª yàÓ·­Ö½ÇO)²Fòu{(Ô |®÷v-ö7†&ÆÉSOšª:ðÔÑID­°ÜçV¡]IÔ¿t±\&+ó.¢¡ne'èQ’Se¾ƒð3û]Ë’Ÿ šÇóÓߛϧh&|[£§ûò+É¡w]¿ëõÅšét_3ÿ\ÑV:¹Rž^ÌíE1B6ÿÈ+׺梪ی‹`Ü Ÿfá§Ä®äÙ•Äð›8»XvQ5–Í{¨3æ²ï´é>¶U“‡dß2¶N"·@Èļü²ÒG”V7ýîí^2>–yÔÁåþqöøæÈ+£*¼ÔüÜÚdµãÛï¾ìŽ80Èkâ[0³àÚÜÚ´<ã[(³ÙŸ¤*”ø˜~‘Ì, Šoë¢kxCvÚ ñíw¸ä°´HF·©cé5öVÖïP·oa³pd‘ „­c—ãç{Àì!v8~?b¯kGÅÑ)BÞÅ^9Û+>¶0}[ŽŸ§z&#a{EKúÃúáìéÕWl`*[žÛ‘¡kÝ4ñŽ?Ÿ~¶±SìðÜìø‘Î•¨ÌªxÁ òéɪŽçÎľ¯!OY•Ö˜ Rʇ•;BB§DÆ:Ĭ­(­ØŽ rv¸Dä_´_·Šoù@Ì|rðØw±+ ³KÚK3o!ãíEÄá™Ø.Qu:ߦÓÉû÷LùqÕ€c‡eççã™>¶Ü¹O)Ž:|¼8Šþà r@Æ—¼AK‰£°Ñ‚£ ïGg2 ¼óßχÖïq„É,HÏ‘m´üÚ»tÚ÷²ì%ƒA>|¤°cèm_tÈâw³ô;/±õ6îkKaù@BSí›zBŽ^½«Ñ>#‡ö¢l}N£Wv]ŠÒS]]ÎÕë ey¿·âÝéŠz¿Éá°(²¯N|ñ_„t*u£g¯>Ý{/»±üR„|8¶‘G$ð—}i»wD)²’z%G7k‹±ª®òéê¿VÖ䈘ÈQËÓ]ʬ՚ñ ¥£" +¾øŠrkTÔjï"‚å EÅñÙÑ•2â–€GÏ@qDÒ ÜâHe¿…õÆxl´{MpCóÐ1%±µØa;ŽòŸé<º]ǦùÂvèzÂ鼩µ)?lúO…ÐÒP¥CÙ€PÎÉídK‡ñÉNà·‡š;¶v]a¡w<á”L¹tcnZãÆÜZÊ{ìxÂi‰ Sh“v¥}Ù|NÈÔZ gv‹£ËéQg‹£`‡¢ù¸Øeîáù8NÑ|\Ç¡ù8Ž…+d 5èÎÇÈ»¯I³!Á§8N‚M†ŸbËô¶ñv`Åñ=´År&ë™Á=Â¥.Å,…¯ÃqPû¡¼È† Íá³p)´å’jk×û;?¾ó6ïϹ8¸ÿÑO³–«ÍlËNä/ÑlümV)’Ñ1ä耷_Q.ó¹EÄL‚–µÅ#ßЕ ¶íc–~9{Ð %hÆù;åäùh–AF6þ{?*þ;ŒKÛj-ºÏlFÚ€;ùïrYúZ˜‹î3p•kS¨¬ŽøÒ¿‘!£ºÑkì¦õgRvSYÂE>¥\žtÍ[ÃEZ.¢‘‰5\¤Áá"™ZÃEж¬³‰ÞOÍÿ{íí~SP0ièÝΪÇA$'Ô*% Gð¯l`ŠÜ…¥–Ui×¤Ó kÌ }Ö¹ Íc$<íñkI%㯇æ3Ñßd¥ ¡9/å:¾DÚøù«DUt¿mußg0}àð4…¤Ör2nèÙ‡4ÄDÏžeþ¾ñ³+ó·\Lôì¶—DetŠ~3ºЇF¹æ¬Žr@.<Ö‡yJÈ{ýï¨y8¨I~z%L‰Fàwé› ½Š…¹z$z9—hûp;ˆö#W ãžgLœÊ±ÿxÿülS–Íé.¯J˜j‚ØÉZÖžSpöÄë95‚+CámWÏ©‘xN1ÞF¤Ž×q HK.·’%xOÀ~ȉîø>ÊvªºX.¿Óâ9Õ_<§ osxNѳ»<§&ã9ÅPx›Õ:<§oÛ·‹ƒâ»¿ ³üäWóÚѰd"»õ´¶Äám²üHkËðæª-•" ×–F[i1® µ%ÒVþ8õdÏJm‚aäzx»”â´!ŸiD"¤’’“°šµÿÎëÜ$Ga5σ-‘ß¶øô°ž ï? m­\Q~/ ™Ož‚ò{Yèi+ò8;ÍïÕ 4j•ϨS 4+A2˪óð%ÃêFÝ;ÒêÛ½+"‹Œ³VGšEè:¥ÛSÞ+A2$:9äzªa!¦ï{üBKIÄ$¨ÓvZé3¬Yü1 Ç_†³pLðe&æÍªbŸÀ€¡ 5¥qË5ñ[yålãö]Å ®=¦Ë´ 6n‡qP¹CßB$ó˜¯Ã1Ýôâ•Ø´³ÐãJ–‰lÝà;ŠnžÞÑ»@ÅÎ"ÔCø«"ÝÕĵ³+¶\øÈ"‹"¹3ÜÓXt÷ä!Ë×ÜÓXt÷ç!›±.B–66sÖÁüNæõœBUe³\…$U†£±.¦û=ñœbs›töCÝ´P-ãÀ««õæ*+« ¾÷ˆÿØOâkŸÍª3 ü×nº‹Qàû:”©äùÖE¡Å¹áy³ŸÆª:ý–:5³V]c§EîЧì;Ô_Øt‰~ È͘Œ%,Š=c2–|°ÈMýßw= jŒEÞo3ËZó.%b¼"eøÔA§:JÝ_ÇžèÞR¤ÓðiXa‹Ü4íAô<¿Íøæ¡EîÑ.-A: Jóf„øî+‘»Ãb[\ „±øî”¸5‡‰TOV©f7‘A†N“øì Å[,²Éœc²icî“Íè¢Æ,cò¦„ßÉ킨±yƒ—(‹ J½væ¹–à³'hbëX:cëV[Çb_¸ öUdXêC]jäÙ·vY`¬‹c¯DØx0xµ j‹“*Q7MÛ™~~L©;•G/·ë&o‹/”þqê¡‹vìZzLþK¿k£yÉû ª $˹RlUcµ2ý #ËÙ;r9QQ$r91µr91ÐßÙ)ƒ\¯Ûï'&ß³äæöý¼æí ³aâ®”ÜÅØ!3$¡±‡êÀòÌN¥CuìD'ì¡:—cZæwE=Á¡:ÌÈ]\}r¸KÜm ¦Fr0$fP•!ÓL™|°æw$ÂKÇ—_Ƕ}%²'Hî²C«3eí. Xâx([wq¾ ÝÅosAÆ8Èô4³ožíX>O3{fâ¡P„-êC𵡉‡²ö!–9ï¼ÝlϤ˜.ÉÙ]`ÇpB­Å@pÔÐc¶»eÆý‘%á?Šóâ…¦]}r³ÑK<Úô#k^¼Ø›5¦ã$öfMˆ+Ò5qEÎ\ˆÕÜOd²¿N¥Þìûä"{+ùÜÏ„.úÔuCõÍòñÕ<_ÉŒ±IyÞO‰”Çl> AòÓÂÊ>‰é›m¹1|ÒÈà46Ù¯}§¥)¥hûê¾ÝJ!F$C…ìŠÏsûdt&rì¿ó`2Éß¹Õ…á&¦ÃõÿÁ)F»¼K¢X‹š"Ó‰;ó­ÅT>ç¼.W”šN\¥—ðÅ:bù.Ó@ïü 5íÊ#­±XŸ…·‡ïÓ­ý£ `jͤÊú¡{½+zŸšþ =Ö){nµèÌ<«¡C  å Ÿ@E¡îå‚]V· …†'4WħýúÈEߣ+„ðCÓ?¡‡Ã·‚ë+ô¶ÞcL-ÑÙ–J+D6\~kòëaöi³îÓçh|> Ç¹ÿ€¼#¯ì5ÏÏ’>-v;öÔG¬ž–%£¿•98ÓBŽffjN} U̶LýjáÁ,çS¿ZØdäj¤[- ú| ,ùBƒ6M<Ÿiz÷¶]>K™O‘(²ZC)÷eM«÷| ©»¼ï©Nç‰]}ST+ØL÷iäõMéͦJ9}SF•µÒ@AhÉÉñƈ¥±ïŠ»ä‰]Þ:ù>ÁFjš8ò«U3çW3œÓEò«÷§‰ò«Yš:Zj'çW3¤ú Ööýc·¶‡/GZkü8g1Ô%î¾?¨·ä1Û®,á.i$G s½åªÓw;zÌÀée ©€üö¯´“ž"=©€[KÜé; Å÷$eÉ{)+ÜOÛr^û)ËöIP¤Û;£3×μÞKsA:¼3òEL-={hs~’ŸÑ[À¨Èox³àïÁþ¯$Ìil«Ïç|?ù_¿M=ƒKä²´=4x5’K¼B—â9Má;ѳWtìÌž4×i÷Ü…2 QN¬ÞéÖ»½à¹¥‘ѱ—öGçĪï]åÄŠ÷Ö¬#A깿ªfW‘<¨ZüîŒzöäXüþÑ‹ß}LV®þŠÇG™b¦þùÖ•ýÚ./s—hr£&·ä+1o}nÞÏðªžÒßæ Z²=ÇoáÕ¿R¿ÐÈú|2“I¨‘ue‘í¾òð~F_´ªý¢7ó{)P‹¨t㺈j$Hîv77¿m©XÝÍ—† ™Mñ2•R¼ÀsOümœî‚t·q¾æ.%þ6T¢ioãl¸£‘¸s~bï:€¶P#Ýmœa¥W[ßäF¾É@{ãHô÷ïíMŽtæ¹S‡?‚\älœoô˜Çüþç¯neè6ÎT¾¦®ý~ó‡ñ¼`æºûì¨U|Å(SË2#¨fì9*"]½{¶9ÒA^¨6kW1öóGœHþKÏç#9äŽù;†h¥“¼é8×”ßCGI“äšò{èÊ5#É5å÷З8‡rM5Ò‘E©X 3òõ{üùúŸáŠtõäÒg¥gGY *uA}År.–+þñmÞdK"LŽ„óa„ïé‚þÛ·zsíc¥¨ò•ÏÌ3ŠPÂ9NùÊjíS‹×åw&vúMÑ”èïLmÆê qLäwlåz8PžÏ½lßòß gÇ•5]œì¢ú®ï7dºj$2;(t ýÎŽ«ä’óMxT<%›|?Õ;d€ w«}ë\¹ZN²R¯&‚4n5†â;Éÿ#»ÐÈètÿyÅwkÆÏ2¾gA &¾ y4Ìå-ÿ´ò+6ß&t<ìt\0®æ÷Ô£VJæsóš3Ÿ›)&WsæµÞ—óŒKŒ9Uܫڎïàw2îN˜QR#ó1îÝŽ7.oIƒÇNQórü”*0ªÛ²M‚ Ùo@ÚnG-¶a¬’C—²g»¡ÍÕ„´´œ½»} ‡çÔ65]ßA¥ÊÔ9Ô›;rnóa)›ê >Ûqö ]ˆ…3v©Ž»^PdâT7zöÔ!S«]8¦gîØ×q0w°ÈŸî,SޤFt'g.’žt÷ 2‹éüÁT‡³Z?Oˆ|Iç‡è¤‘Ír´5ï§©ÿh+lmÄÑfýôÌÚ²!H~"ó£8»výPÂê E©ýùïïÑ‹„c–OCéá(Jnj¨îÚcú5ý¼Éð;;y/Û±û¶€L~¤§ŽzØ>åˆî'êWÿw½ŸÓ:—°6D2«?G\#յ˚⹑YIäõÚç§È¡úe QÞÒ;/ß©|¦¿3:‘ôÎòì==&튳ªÈqYO‰{£ÙÜÏÔK1ÒBŽY&Ùþð¶x½Æ„œdyýˆ’TdC Sã¶¶DŠe™¶i$HîÈ ’‹Ý ŽÉœÈæ©\ ’{˜ê; ¤'H7aüuHu•@*‰™¬ÓW‚ 0òtðE1|»ç@NÂFRbÎ?aÄÑey]ûK½X³d%HnK+O¼n9é màÊǃ…$œ‡.!‰XgY4æ~†.!‰÷ A‘Ü¡;Pþ8+AâL¯a›¶ž]ûºœêäÇ~“ö·é«¶™«‘3²§TMïþzEV!ɳ}ÏÅzAÚ„$Ó!$õ&G«:DÿA¡pÞù›cÿö#×ÐôôwwßÝÔ€XâöÿºÍÍ4ŸÈØÿ*†yn&‚tÅ¿ÖU5 J2£©xª›ŽSñ8Oüû ¬äÜ-ôoˆ³"nÎú¢ÙS±¡·ç ”Úë‹‘"™µ¿•í®;çµÌãËÔ´ßV îéGת›åúl•g§HnñýŸE[/CþX 20}â HõØ´ã÷röjÀ£$Înл‚O€ýô±ç8<† 2¶&¨>1°xÀ¯Yì´û»™gtõ6¬µ_ß6MßeÛ‹Ó¸Wåj¸Ñ»±Û×£!ÈÀšO0ÔS³nšÎ¢úd!Wò ôwF率./v픜¹ä2ÐcÆ®ÞóÖ^ΞØô;Ê3®5#½®9vÏ`¤ÿî™0ßQàÝ=ëš“[<¾ò~÷ø‚9kÑN?®³W–K»Âj†Ä˜]j92Œ«y“»¿ÚGH®ãä7'jŠäÖŒ%Þ©`üÄ1f׌“ƒ.Ý$ûM.itr Ì AâH.ÑÈñ‚dNÏ´Á<Íäg5Tq¹:Z„y—R‡7¬“±7,ooØ=Ò yÃò{®^Iå* ö»‡T.©|$Hæ2N0»¦Üˆ]l®z³áép,v¡ê¶¡!ê6Ž£¼¨ºMŒDÝÆCþut”‘ØåÚQŽ2œ=ðX,¨ŽrK‘ÌZS«ÀúçÏ($æ+;5O¿ó«,ýë7¬ù°0å\OœÝµlèó|Í ÒUÙÉ•BOÏ  ;Ýiè»gÛ¾·Ú¼!!qá6*¼îPá=6ú;#4~VÚHuÊ[6læ] QTëàöß©öî¶·üìè1§PÓôÌÂð× šöáà˜nžÂ¨j`±ñ0öìt5m7šk^Žñ’ŸÑø6ßfLfÃku±‚‡±»f˜š¶é.g·Ö kV?ÖÊ<ÍØQ3 ÍQ3 ;½ ?æ+N|^Ð*˜m$HfqáÞ™,¨V SjŠ»Ï°êŸ§×ó£ ¤Îg]¬ ò#å[uD^u“÷=ôö°tI'Ör“¹ý´MU· =&GHmuÛUŸú±¼«“Ä¥‘©mvçäc…´6r•pJÁ42üEö'’ž=‚7do¦+¶ÝP Ù¸ŒÏ¢$ÈêÏ=HW ]#Šº¯3šL#S©êéè9‹"ëj9J~ÛçîN£²oݸ=?_zEÆ>×@ûÚPè‰T÷­•…#k|Ùjú”î f8ô¬úò·ýòŸÊMbO­My¿í«i«¦]/o‰±Ï=ì‡ ùH×~¥ôàåýGÞ“oûU¾CÕûrÔÈîÉ gd³iŽÂÄ~'ÅZNа ŠîÃtå›q„ø%"ìê›ñß ±ŸV9õÍ€/bÎ%bs,ኸ‡W¯|±zx¤×Rߘ'ð(ôÆð[ý.¤–ql b‡ ŠR=cù²=\|êÐÞv*DlÀÇäH“uyîGðêyôv‡Tf(`†Ç7¯ÊÌÌp¤Érl$w)þ /¿©ûMq§Öéô›‚M^£u’µåŸ‹^òý~l°Tˆ¹mÓG»‡ Ê= ®(ð¸‡eÊ=l%HGÁªœè °6º$›+×`èé’~Õ…X?ÅãÈ»…gôSÉ\é¯FEÎc/Å©È9 +Bº}k¬—·ÿ•ç&ZœØÊЃ’÷|®ïšÿ—°"¼¡eÅׄi¤%’¤X·i™òïØÃ´†­-[zöДõ'±\ù4Ë‘$äÙ`”gß^Íûú;ãß@”O;>—Öh¤¦µÿ?%XŠç*¾0~ƉYð[â‚ú5‡+J½qA}f¾âÔ´É¢ Üyœúã‚ U#Nº¤ž¨áxróóf9—Ø<öw¾+˶ƒáA´#ÏïhØè¸yÂ\‰ÇÃawÉA$F%ð'Ž4Yv¥?Ì2 ÷lÙËÇiŠõ$pæ«÷$_'¡3_}%ªgž„Î|õžä«s"áÁDj ÁD<‰D;Ei¤%‚hG¢"ôDÁ—Dÿˆ ‚¯8‰þAt9¦'‚èrLOTIô¢ 2µÛÖšVuÿ‹ro]ò*È|q©§b‘‡Ü`#Ë"ldrÝôî&“‹LÞ$³'rËzI@4eþê4˜ɬÕñ¬ã)'Wdˆ‹b*Ǹ¿3pM\„7$ ÄÅFÍÙƒ_aBýÔ]Øå€§¡Ëå@Iöð÷ž†niq9àièu·˜Í2>þáncÝ%`QtêÓÈSÛÖÔóܾÌzš¿[S‡€B!›ü±@Eâ4ðƒ„p8:*ÂÖÏ.'ÈÀñòÓ_b?b|f_ФMÿ?ÍøùT=AŠN‘ŸdÈù|^°•òЋò“|ŠÏÖfMEÉI¹È5¹Õ7½¾¯ÂkS“nõ¨4tî4FKn›Ie·Ñƒj)œÎl?ŒÊw)œ,Ô› ”a¶Æqów¨ËXS(·bXõͱxæ7pyÞÌ–Wê!Æ)Õ·C‘xÆ&…2áÁíæŒPhçæDÞÝ_ˆ"7ÀÆKp»û—ÁÕ%À¢BnNgzLevè¡yÜ\ch¿·Õ¬·ƒ]í£À7ÕÔæû .A(;òy¶ÿEço’Ùݺ±ãRp *@¦(GÖð;g£ˆŽ AâMDqÐtfQÌõcyŒ#ArÛfÒzl&õyŒô‡ÉCUjóÞ¬œ—²ìé1C-ƒ2#×6Ûº’3r‰Œ2È7 ˜'›`w•é)Ò=ËÍ‚"Dñå=µ"@‰-WBf&ÇÚ ¶™”زjJ^«­ÁìÓ\ÎYçCÅÝ`üf7$;½ÌrïMN5-ýÎYÎë42µˆIÅHĤ»»Ä¤ÍØÝ%&=¼^aõ¡‘ö“jdà›ô¯î<óˆM69â@}Á®R몆0¼w³¶…ùì'mö¦F´Í8·Ã3s?Ùol¬{0ý;Àò™kþñÖ Xàžˆ·^À™©kç·yçC™éÛ>« ’9Éaƒ¹ößn¾Ì1}Â샰șÔÓ‰SÀâŸ>Ï9s•£ E3oròÓã‚»´er†5ã’²‚IŠzãÕÎÔ4d  Þ¿û‹º‹sÿÊå=›³›1yïî»ÑçÙ7õ×d@ÆÃz½’§V^šôì¡ÎççÞüK¦³©Ç%M^Ô5àּ笺\»•|#k5YÛ\Ξœ{*T,â5M™ºOâýÿ»’eudùK6 ƒ—½¿7âõ'0 1ØÌDýÓXRaÄÙg0IHUªÊÌÈëVcï'ŒôÔÅ\%Ï(|Þœ¬ºJžQøS[GV¦›ÍºÂàÖok¶gøIp£ Á™ …F†ÞÈŠÙ»‡?1h¬ÉÿV°0òüïƒþßOÈ‹ÿ}Ì™úß[„ /Níø—weO¢xdOä™¶#{…Ä«à: Ù“($Hö$ÏM5á»õ–g U9ÍôWÛl…ñ]¶-Îx0Ò'OÏw$ˆÒÃø^žã4Ò/OŒ3B)†ªøî^yú\642¾?æÁFAaüW³þJ×ÿ»h凊O&^­Bqª\×#8¾6g­B§‰¯^¯!|ÛržÓ­/ã˜a˜³ÙÒ$5’¯Y»Níw`_8§#­›Ç…Î9ÇOK¿t?Ý]G€"ã“HçÛ›ùö6Â6ãjï;kmá:jÞ(òY®Š5$ÿÚVéÈ3ÎU¤VU‘`ܣஊ´Å0 dà›KioïÞîÓ1`¤‡´µfèˆrÂik)ÉgGHsœ+ýXÀ`±ˆÃFA¶•ÿ§¥›£æ‡k?}[ì\àFE/¯ 7“&ÜCÈKn¾o î!}‘?ß茌¼»áÞb$4K‘FeÎúYi½mùˆŸóåH'™³‹õèøˆæ¾flþny$+êÙÖ4RþqÿüW´á–‚“"Öä´OûŒUþžo¯DäaßÝ•V¸~\&„ üÂpf9»Ì¥ "DVQüC“TB€ÂþÓHâ×ý£ø^¿²âš®ìŸFÆŽk†šžbeÛnÝò!)NcäÙß]û5Ï7„|ÿ* ò»#%AóåFÔ[ݾnÔÂÔëçs‚*ÛèÿýWI É:'‡òÔ£ËöÓx7œ_¸jâm}rîmo‘w*âÇkw„ .„Æñ"rT#~BD\ý7u¬K+Õ¯,ÃE[nr­U®RN`E®µÊ‰ëÂÒO[Å^Dž>ÙyÕSÞÀN‚»žò”9ÏÜ8ÊKÇ!C¯C’Ý:Ixc^ìö©G$òŒ;ÿò¨å)"ÄÓò$ ñnËStâ{8-O´E-O¹Q÷B-O‘å{ü´Ë2Õ. _þ²qQ¶¡Š-‰¯vðœ±ß p–Ž&¤'‰§éH yümKmCÀ65º½SH‚²!Ãk[ÞQÌyx÷·Gk¨Š <¸‚”“¼=ZCƒPý”ák^h uBôCù鈴#§3ÉŸNgøšÄšÜ•¼o½¦k]ÚÒ%yû˜6Ù1KÁjŒŒ=ÑV!ŸtLÎòöÿ¢(gÃZòþeÚ Uþâ×ãw†ÃÄùÈ2`ÖEN{¼#ó7ò0?ÇÑE¯àlUÙ”&À˜Ÿ‚+·éý‡UxV¡y#×Zå‡U(ùr !=å Q^†0ìùŠ8²©˜Ú9ÿòsÆ„éRÕÀ±ÀëΊz†éMcS°½Èo«lÍåüœ2Xç_ä'­K“ƲÁZ©j$ñÙ[ó _ӓƲÏ1QüœÞ4ÖjaiäE2%ÒØv1"þæ=Y’ƒCž×ë¶áßšmE¯×}ÿMN_®5í?(‘ìÆ¥WXi…á_CÊÐÿQ_g[ Èijs©‚ ³s½îÒC©bÞ=~\ÐLT8|é±2Z¤ý‹ÿ•1ƒM¿l:úŽn,‰@ꥨ³ïz´½“[Áöß]iã¨>&:ñ½X73B†­×#S­×æÝ]ºÁ)²b²õV†8ô´^KÓUÇø>ŠÃÙz‘Ñ<™ÚG¡Gw¼¥„a] –Nð=1›T"Õ ‹ç–UðÇÅÑE¥-ÞP3¹F†>^ß`‹¶1ùQÆ<°†Ä¯?Jð°Çů[¯æ;—ŒfZlÏf˜!16j—Jp+}&Sh¥ ßÓ&_øz‡îjWJ‰jé2\åù Ç'ÉiΈfáJûf”ß)çù¡ùã'RmÅ92Õ˱0Mâ‘c|¤µJ‘Ûú õd[÷’À[ Ö [pÍðFÃG*ladpÕС¶Bú¶l ˜„žf+Qð‘ÍVf­M¢[j‚õ#Ž’Èï@]2Pd)>'ªÜ µ÷`¥Oœ&Tu£órN·GQ0û•œ¸iÚ‰£8©i7!¤úJ;Rö¶À¡ã˜»×Æ·»ŽAÄäøùœm—¥P8!dpáÀ¯™¯ë Å®$ö„âHÛ¦’äÆìà¿H‹‘V§€RâIì°s)Á: ²È(cÀœÀ´Ù€Ño;‰ðõfã ô‘(IN†W41ñ¸ŠUßòJ»i:Ö±Ím‚õÞ¹ˆÓ…0;Ä•‰ŸP8‰¨ö€ˆéý¸Õ3™A!;z?¼mª@a¯éÜH6ëQÁ½ƒŸ¿Ãœ,ŽÇº:ëÒ«Q©ßH|OUD ˆ+ßáM; jZ|GþØÿÛ[-iorcS™:6•ÑgÛªPµ"ŠfÀbÌàÝk©+lt[;Ñ ¸ÍvÜ‘GÊ¿J_‹ªX5ŸÚr±%¬÷9äsIæ»’D;4%œo½_Ž*§ÊÏ”–P¸âkxŸâçUNµwÈó­i=Vþ¿Où²­²²kQX·åi9´[6bdl[eÍ éd+"ÏiB&W­IRgɶÒ\¹¾8Eδµc”ø²X:á,öý¾£×;räñ¸1XF¦†ŽBÏ»’`cÏ$ˆK2‘™‡Ô´¨å¸·Ó_ÓOÃê Ç€@ãJÇqˆ@X „?'’“#Á¿W6íȵ‹ Ï¥ÂkèÃlçqH›NyE™?v!üacànï’•¶!#o~͈$ þs#!V`óÝà…kr¥©m+© Vâ8Ä\d±é„hâ:ÄüÊ´ _Î!£Ë,a‘bvpÍøæŒ‡ÔÄŽCÌ¥ø¥øšáÕzÃø¬SûǨnú›KÁº$÷¹”Íõƒä6—ê˜ýß÷žèzYšl´ÿÑÛ+ØŠïÙÁh†7'"2C‚ï>î:T[ _3´Z°Úbµé²oZL#ÿA2²gf: R:÷ÅòýI¬™¬KsA£¬Ø‡!äË©ÌTP™ùðDáÓâkÆ>B›(F&ׄ©j2¯‘o̓B¦ùòßigšnv|{¹#]ís>Ÿ ×‚ÚY ô27„$ Ÿwq‹#!I.[(bì`§ ÿ’”Ë0Ò#)'ÚÞg†~I9ç9 ÙföE4³W[ '-á_DRÈh× ïZÚø?ŒîœåÒ|•IùûפLDŒ!ñ¨ÍK²šCM . Kz¿dº"©º¨ŽrŸ0FõÐ4—±\›rá,Ün-Bª]AöWê2gs|¦å3Ð'BÂØCªb. “»Ž'šNv~¾‘Çl&ä~\¶=È)ƒÈ6úÃy»‡•Ñ¡Îüß®„"Jjº¤é÷ âs$zž+hUY›3Øa]v#m«‘¡ÓJߨžŽ\Ûâ NS9g\T ‚ò ñÛ¶íPdp3šBwÖeÇ'åbŒÚÃîÇQ€Üÿ¬Ó©8YuNIzºÕ¬³ÝÇ$Šþ -ÙïIþ -ÁéMôº%-Ѳ¤èå=×UâÇpÅw¾¢¼oþ#LJâסÆõõ QâQ›_éB‡a6Œ¼©_Þ•©#ÑÛ'S'Ö:G¦ŽDo?•ÉÔi$ø.ÊjÕR¬[uTP‘$ÄigùGËi(òƒgÿ‰+„ ûŸÖ©H[6|Áë^#ÕÝù»‹k6ÚU9¥k?æ°!§E~¥¢¤ê¸žŽ.í¦eGHHþFlîDm¤ê×ßýåÊ~(Çuä™ÕfyœÜyj-ãÎÚºšæ>­ðs&Ž*¾Î–¹/—<]+ü=ß0“Õ5¥OàWø¥õéË?¬5<‡6j¹©§iY×?è\ä3 5êþCQ}GñÛkwU:yF¯7ÝÀrÓ@C‘ ê‡ü¶S·§ó²Ÿž5²PÉH—MéBó¥ÛNP‚ rø—iåVÕOxLŸ/[f6Z.üÆ6ÁÔÛ@cˆóB·ƒò/ÀÊ|,ñ<}&*¾•óÁšæyÚ«ôí@…Ðf-¡Ã<Ì8ZšÙÿp M-ÄltþÌó>áÉ@§¼Õ@Yìý¼ïŒUx´‚À6JIŸVÝŠix‚†ÈoAϬµþTC•ã ¬Ír.Ú%4†}òÓkÚ”²W¿­åÕŸæ@ðr¡ÒkN@g¾?Ìç/ÛØ½¨T’l»mõø9]5ÃAi¥P«gë,ßÓk½]/½Gu|a©—ã{ZC‚ ^ù¿µïÍ·)–CŸàðÈÿmu‚Ì6åKúxú·CÇX©  [ݶYöiðw Cð]ȕ҄üXË0ðÍÿ¡%ªˆ/ÐèïÊßj‡C‰µh(´€°FÞòñ³œ /c—šAƒÓ2§Ç§®æïéµb£B™ÉüEL­cN{þþÐËj ÊþV-Ø•ŠM—yê³µ*O¾Nwñ苦²gzx(è¿NÓýÐTü:3Øèéx»Vµ®T§óøí³O—(p™åµ.©§õXõózÚ†ô OáJcèÁ3“Th­døµ¢È23+ÙòQ7ëÔ­ÕXñäC•¸‘Œ ]çâÐtKÚ×§Pt yXhf‡–s÷µ¥e •5Æ„\TY*ß±§™Ö3Ý M,”Vjf Çggü³¡o{Rlb5>³¾Ó´SûNo¥ ×C7I±Ó•*PщÃO¼Q9eõaßÈžVjªÚøºñ»ÏãbŸ3ð ç*zØz¹ñò¶63$·Ì&:ÙŒ‹D>ÝÒÒ”æô°XäáÓ òYÕŒgäŸnù¤Ÿ™6ž&‘ÿÌìôîÄfvzw‚˜bÖôDˆ9»¦'„x%Gè„6l0ŠìËþmYÛ‚ –>?X=žËú=–¹ý4'(„Úæµ›WÛ&¢¡á%”ÖÙ`«#ù »m˜ÕPbâ>OÔ6ßËÂ3Þq3ìX}ýBË~á!æºÊ­Æšë}Q¬eóá«ø~ú @e”#VáØ&6§O•çûºVSÏênÅP}¦º‹ÓÏ¢–G)´ØÛosðG?ý(Ï_¨p—^»µ^ñw sD”)²<ÐË(;ÊŽž sÒŒªóçfa%ß 6Ë'ÐPåcúßÿ¨5Z<5u¶1¾ú äÊiv})¨nšV“°ûö]eãéYÕš&;'Dµ@8©ßâ;Ôõ¼Ÿ É/”Ç üÓ¶?з7«·ÖqàÏê)ÊêcŸ° ‘-¶;ü#cœ0ÒVŸŠR››ÐÏQŸñÛÀª¡ÌA™ã*û†šUüô3B)šMUæ±±*¿åÇ‘Wö]zý„‘ÇøCû_“¸GÔf/å¹%mÖÓs¾¼¾jJ c… yŽÉ³ÊtÈÆÔœ>ÄäÊøSÛæÑc;fŠ6ÒUG¾•ãT!$Tsž ©É܉­tG(YÝ )Ø'OÔ¡ÿç˜Y78;ùµ’R§È<|ÜJVB9+&ØJJfböîö“Ê©^,¼åÀ Æooç<äWR-ŲË¡`Ÿm_ížOœè@ÅP2†ãK?t®ì5&â¿ÿç\SÔfÓcìê`ó+QÉ” *¥8ÓioÖÆ.d¯Sïp]i#«‘¦Ç0M§»GÀ„“Ön˜z–Ýéî`K jÝjãפõ4MPÁˆ!¿º¨´SÑ­Ïyöuÿ®5éA•iné‰Ô=¼§ê|KÐDC01AµÎê?¹8à ÿ»ð 3ÓÝØ#7Šoo®bˆÚEÚëÅÔºåKöË8¿_7‚DÄóþ>•ÌÂSÙÀ7*¿X­{ÆMÖïó3nEyÈäü…LAOÇáÔÖÃëyéñ}–Ž^É¿_ÈÇ™Y˜òpuê<ß¡g¤¨âýرîj‹xúkÌ;Ú"^+ì»s´E¼ VØwçh‹øt©ø¸Ò«³`Ûæ’Š*¢`ŧ3nE=  µIîh‹Pq|9µb X°äå߃߬Kªÿ¨+2½Á¯]âßÝ Q=M¤SI™ aiË ±Y§n?µ(s¿[_³ü ñ ò ËS¸¶Aù…®º†—_ë’«®a:ð/ û3ˆþŽ™‚2ùÚß!‹'–þóßU×ø>ßôâ~@¦Ø•ª^’ɰóû|î'è)²¿ÝXÓ1óàò)Ä$%Ó«:d3Â#A^=†z;ÿ‚IO^¦áž&õ>GI‘žž¦íPÇE?>!OᨀØ“n¶óÂûS¿¶ó ôÜ¡ ÈÎlw®•R†wIÇÌa/6ï“ÃѪÃy”†•kYÕ»$ä£Ë,¦vº˜›s5H|¸þ%/¸þy™‡ùÊ\Dt7rÿßНœ@]ó`pæxŸEœ ˆY½ÛñŒª\I(Úæê|Û¸ûúz™/©·¹T˶aÕªZ¿ß|û£9½O³€Û¶›þLR´Ë2-b™ RlÿÚÄ”yK’o[|½<²ôIâ ©Œ¸aÊWiJ3jHv¡"`°…ÉJÀ [Ò#` Òõù<žG‚LýÂ?ÊMЫ{ Ä{íûmO„»ÊBªh¡h/ôêyV^Ôfïª,*`0ñ‰ŽYzù)Êe -v¥ŒrGøÇGÀuˆ,ûAdÁEŒ…I‹†>6d¢«ÊúpõÌ'>>hr þuEP||!ž¹ãØ}‰'DŽŽÝßA Ò@YWyB¹ôôêaOˆgq÷„$3ì G$tìVþï—'„³.¡ÿMÀyî3êó«lzA†(ÚŽóEúœ‡ôŒCç!‹ô8©ò×°ˆÎâò—óÐ@ÌO¼v‡,2$Ù<¢óE†ÅÇåá-UþCW «x’§Çû¬‚Åi5‹Wì/VÌÍ,2 'âöÿ“¹ÒPÞDÜþ˜# EqRÙ;‰8öwú‘ˆ;\=’ˆ;\ÝŸˆ[u"n Hæß •ÖÀo)‰yÍ:¢2Ìu*ß%°<’’ÀžgÑÂ}:Ä ês6 "Æþ"G$µ‚qüšì@\Û„i €Ê8û É+’òµ–p8eŽ8ÓüIûwñ[]¶¨öòAfßÅ~a› ÑÁq¦oøZb ”¹âL>ÑùﳌˆÎo×v®^~ITº©0Yã<*‰WâÙlðÛìP5œó0,r!È,˜Z|à›¦%ŠaXdºzO‹LCɽڙïUÀñt‹^9öc,;ˆ X[Ķ‡éŒˆöÍÇu;C÷tÌ4@\S4Äý\¢•S·iÀm­½Ý ¹ÇN§°Ô@{_뇫‡¥¶Y,þó§$૽Í͇RB†Õæ”|µU¬¨|µ93Hö?_`Ò(Ù‚¶Tæy%&8>{'ûËÃÕ³½©KG¿ÖKi‹U¯í/!ÈüÛ¬E·#;f-Ì=ò6‚ð-åŸ]·lÊNn34‘§—‘§g' ë÷éP„™#çó•y¹¥X”´áV h¤È$à)^£\ ;E `Î+ȳSÔæ†¢ì5€_cfÔüæ¶›‹¬’fÌqËßM㦹!±L{óKþ<69`X²{8'Èt*›VQ0Mkûg©/÷uOÝ0âýcç³Í⩾6\®™™šë^†îŸWÅī֪ڭÑnÐ+˜І’Ó1R…(}yÏçþäĉC”sÛ…·&VäSûçONNÁ„¶Öˆ<ÞgØãd‰8æÊÔø"ÿ7^=Dþµò]2,-é ‹LCQ:Ê8Ydæ³q‘š%q +”X`É/ «†"V®ÄK~XXAFÂ"# œŽ™‡Xñk†dj„•©™‚ôÈÔ+S³'óYP¦FX™š^=ó«ˆ__‚¿vdAVkmbE‹×yÀ•6¡rh¦©@aUƒÒ|/ü—~¬!¡Í’kŽcþ(X‘á‚õ°.X‘ù·`ž*k#:zuæµÖ#RÙ,©¢Öz(•Í’*@ Òþ *öÞïÓ+’cÎ2 9A¦”¥?d/?œŽ”½œ—2 {9Îë´Ð«ç!«ÞÏû_—ž~X ìår–ž~X Àé,=} {P¹Ž}#Ò/ÿ8;솜>³|îd'æúj¤®#ucfaÉ£»+yÄÒ<˜§íÐìBÞ<­0yÚ‰ Ó°Œ¬ŠiÊÓZ¡YI¯šEy"‹ôæi#4+2,4 BBYFt„è}V>µepÖXÊbE1‡¨ÀáQáæ¬Éi¦AòmL<¥±s±2 Ä«‡( ƒ¦4 ˜Ez[àuÓ‹àtÌ ¥óØJƒnz‘=èBYd -’éÐo‘ÂíÁ?¯õ ™|‹ŒÒû¬ò<ÃØÀŽ@äy¾×$jXvú!¨'GžÇ/¨kÊó)vAEæÈóøýÔaGpäyü~êp‚v|µý~êr ȰŸú:Ò«C”®‰v/nšé9@O³EæDž‡›†Ÿ[ÿ|_FNï“A\ó>'¥…f–Yø×9ÌõBï³ô;¯¯/Þ¯ô>« ‘eÅ1Ó8‘×Ç}ÜGLZ{X“÷qO^Q±NF‚ôJÛ-Ï^¾ÞëDyòòtLlè¥t£e[’‚,ÈíÙ'úDeòÂï³ îëH¯nl±±•e}cå+ˆÇ‰ÌÑ7övøá„/ã~˜ Ê~©^âÕË ¦_¿òíA`—UOÚ‹u-Ö~ „v':æ¨Wíî]·=Q;<{ô¤e¨^åQPUé-8È姘Ê€j§ÌÑ·ð¨,¼%†DßâKea’¸Üä”Å®Ûfix~n×és…iœŸ%Åì\‚s43¾4a¯ÛRCÐàhfø4ak Í o¹EÂì@Í RnÑR<ºÜÒÓ1s¹înÜgGž†g±în„P O³Øö,:÷™Fg±¸ÆÌ<3n°ˆ‚ sÿ_§tìa¡ÏCnhƒu-†0=Ͼ”9Á½ëu‘ƒó>ó¨{ׂazžwmÚ]qQ–þ]N]‹Q¡]¿%Þ‹2 ökb!!wH‡`ñª‚ELéænÚè+­9 P>·ÈÄr‚K¹E¦!eÎÅ™GEXôõx¯w/ò2¦=X;Éô<¼~‹«=Èßu[ØûÈùHT­Y^’þÛÊ øW¸¹* æ°m}è¶?¤_›e©{‚ ¹ì*¦3 zða¢•Eþ÷ß¡xöâŸqmE&®Ëƒ jUaÿªA9~ææÿT‹âU¿OÑl7)‰«âzï8«£öU—û~YϰҢ ÈÞß·÷嫺²4™ã\ÁXC¶¬'È`2B§¬E†ãûaÌH²Ò1½*5#CXú#9 ×õ½Wíú|>#2ûú“ÝRèûq@Ú¢é¿ÿâìЮC|ž¡xÆ"úìëv“+µº*S3-|ŸÙ“ú¦†í8!n½lw.ŸE2Ú}kŽgS/>¯Ë‡ÞgáSÏúlÿüçø–ÊïyÄ·sWv%ô‰*ÿñŒ¿ärx"â³`©0B›¹;'$ uõö¡€%ë1'eGJr ¹8×Yä¡Ð¦ŸI!ù6êJiˆÍwàÀ먺xÙ|àjȘSÈ8ºß¼äåÙB´ÈX¸_kµ©ž oªjn^>‹è€¨²þ€é VÄ*æ´-ÒÛP¡ Xµ H¿—‘ÜpÕ:*$ßÞz¢]qçdN‹aKi/8Ñ<ðÍW_E±½3Qíˆ@‹¿Ha]G‹#A&Þ˜¥WM 0“\} â*£a{1¾È,è*S>6ßd<!uSœÂ®ó†c²£"‰òVáÂ.¶Ç÷]¥!÷¯Y¤‘sê™< çñ^å@‘s˜ä IÝ"8›¨¢-"³ˆ ÛNÌÇùÐô¹¼‡æQÁŽí6¾PeSU`Å7ÏŽ¥„½’ J±ªÀJÇLCíFØZÉNîA'»1:Ùø/1ìn½à›/úýÛ[z·íŒí[EÄãwU%s|Ke¬-JHÐqgEùå‹E[˜ ¾(ªx –Œ^ª¿… ö®¢ ´0)¿>ÒÂTTÑB0z“²òïÛålgÖ¿ä Æç>¦ËŽôe­êúMá’q )edGzTÏ·_Ï‘e¬%L9ÑÁš\¦A@…œ ‘›•‡6 |îlòY,V˜Ë$Åз¼(OmðïbCðX Ë4¯#Dßen­”ºÞ|¸t8ÿ.Væ±Öñïbe÷ïÂ¬ÌøwáûÌøwÁÿYæ?ü»cFü»8}¢ˆ×JŸ¨ Å èße‘aÿ.çå?ü»Vü•ó/­+â%ï´ —ñ6aŽícåÑÝY³‡ §mé»7¨Ã³’E3\H `å6al8*Ùá{Uvñ+?Tvñ)~¨ìâ?RüPÙÅ1Ë*»dDeŸ¨ü¡²‹÷é´[ÿ®]KµôNÛ·ß‘ï£!·X@ˆ¡Ÿ2äSî6¼#ãsÎîl㞡ӹÎë>:Ýs¥È„Ðé4AR>‡åy­?âCiˆN瑹Óén&k¶mðËuºÎ°Ú!;ètFÿpCòåzŸo‚dž}›‹÷>`Gª"¨n=†‡ôDÒN¢[&Wη lÿCªˆòÈÁÊPámKͱdiNW‘ü!®C¼åÌá _ñæ_Ü«2®»GUÒ,ÏňF©éR/c/ð_rè5VÍÒ„"о †ûßgE4Tt>È*d>±¼^xu'b²žâ¦õXyºÔõ¶(Rd«"ñÈi>r¾ÐûÌ7«Ü£ÆìÛ—¨'‚d{…àl¸RzÕÓ¸,ÃB‘.'¸ÛŸhúŽ­Iê4ú5øîö> —ZäÕõ«)2 jðÝŠDµ¾ÖÊZo'ãµmêÏm×k³È̯m'”¶]OyX„nÏsX$ éºÕÃ^i³È"(ëV×A–»þš®!i—šá½^—Çõ2Ñû¬¢nu{mo^ë¿mÁ€Î1iªÖ6¨êQî·™D¡'$AqÓù¼EWõýzAÃu‡& ¿¦Ûnt¸ú¹vbœ ½CÓ€PÚv˜Ûÿ§šíUóÆì ê([ß·ÍîqYZ Í}D¨Á¡à­ž¾œ*a§S'TØé ‡°åÙéÜé,’hª_÷6®ëÚM æYü}ΤPõ`ÈíZdr8Óä*ïMƒO”FÈ©ºG§'ÈÌ©åY3}šìƧÀ«g¤ÉQ·6Ø Êåv›Ñ›À"!jùÏÐĨ,2ÚØÇ&GnÚÍV¾NÞRhÓV{bÛö÷žˆEÜàÖzšKñÇ‚5<óÝqÖÒÒÊ'gÌ"\Ã[Ĺ¿¬é¯á5b‹kH_ oX?²?×8•ŠzuÀoTÆÝV|ŸåןÜi…¼mÅ›”žÛ÷Y‘VPDnSm kû©Ò©·u6®ú^tý³–A¦»4£ÓÕ7½¸ÖÍéf@u¯\GqúûÊ›|ÃöݧZuÔŒ™JÊÍ6‘MâÜÌ{ºp(h gçÑøÚ~ûüÉ'ÇmK룜aŸUÈíûS$œSœqㇿ¦¾†?äôwÃ96 ÷[d8Çv[G‚,Bþç¼ô‰ÊP6n%EV!Qläßß|(Ç6Jgz¸9¶£¯ÎC jÀÓ32ãu[³Ùc·`` -Ÿ×ž )Ý|*åp>/g‚ ÕâW̵X¤‡n1hºÅzÅ™Eé îÛ'ÇÂ4”wV§yª›µ–ÿžX„n±>{¨RXd”ò—¸ÇF|!tGâ÷YÄ %º9Yd‚Þj[×”vìÎN7Ñ¿‡š=ÝKOÍkûÆŸ©ô‘cÍŒWäØíXG)¸Žê^K0(^îªÔÏwdE×ïvÏvl³MÉcoÿ3Aâú­ÇÔƒNïq¹ÔxJp(Ä Í­6b×­­éÕ3W÷™ëï>ôÃY>–úA‘9z µÝî25bÙö™† ™ã>Ôî~5b^‹,H5Åx¡¼.—8ÏŠ,]$×'iùVÜíy~‚Ÿ7õ>m­q;Ç‹óRcÔP9Zú‹Ö±[ü‹?äu–çá#öƒü~:¿ÞÞ÷mö5}ÓFMœvP#;¢¶îûrá¼½Q¨>o«ýÿ5 ¯·–_ÖN1O£f»ÓÖV0úEêÄt=î5ŠLAF‘üÅD¦œ>Œiá> Ø—Z¸Od û0,2#]5¶KJœ×¦áNNžØÝ84I"}Ý$M~Å¡{•È"#qèJ¯î‰C·óCŒCÚ-·§Það9“4¤Œi¥@²*’ô»rßÙÞ#‡&i„–£¨§EfA*tÀI§¢Ô‘E†¨hÊ*žŽ™ f+>»ÛÉf}[Ìz«èCr½IŠ4ëØÿwpcQ†=#EÝXj ¦Xd˜ŠÕ9‹,CK =(Yyg1‘ó+’ MTeÎ9¿" ÑD×&:dX9¿"ÉÈù­ẗœ~£M”kš(ÊùYdXÎÏ I„&ú”ä,ÒsæVYræNXèÌ-1FÂgn3¦sæNXŒE²Tð>‹x'Ù⫤ŒI´ð<0‹$Ú£(,‰sS #v_ï;²:pX¬ÝšÊv\»~žð_r"œÿþO׈¸î.i¾×/ŠD_“‹Õ3ÑîyÍ|^pc„cD=ôÎi…®W•±H—<èND¹HO¿JW¹Hi̪ÜïñSßú3Ô™‹4!õpDªúØMœ¡rn‘ Ä"5‡uùeª_*ý§É=M]TOãÄøY†G½|ÒäA­E³nWH)>ãp—©k­ÿý£M²¯V0bäÃÐÌs#’yOÒ-h²Í4œ¤·Ÿ‰ A&„Òi;À×åÝ× ¾¥ŒÔ®õÙ§ãˆÈ$(ë&ñe¤ëëÛKNi÷’æâ"ÍI¦œ®!õÐoÿɹUµ†Ôüý†¨>eß¹U¾#E'f1$œSTÿ¢©œ+©ŽµSÍyIMô‘ _Ïû¥'H£ ïÆ÷sû¢E2’¯Eä¶'øˆéY¬®¾·ûƒ÷us%Èc†kÛšÿ³ãŸÇçþh'‚¬œ°ýîzÌ¥¯9}v{R I`y—íôÑBh¡¶»âSmÕwªDE¤¼7‡¯tJv[rS˜½YýùYûî0jrJÝÖ[øóЍ°“ïÊ ì¹‰2ä˜ÁÑu×"}¢ÇÜDU±ÝÐ);J‚ÌCÞÄØ¥e‘Ìï­¡D%½Ï€è4`¾#-å;(² ù\§1Ù0~æ×»˜lX§j£ ›„zt‘V_ݸ {#ï÷^î5Eö÷Õ%µ ˆnïþ<‚HŒE’}Î|w©ö¹N\ ™ý?aב+®¯Ôg9û?3GÀ{h<1§ÿ²%•@¼Eï20j!•ª²2uºÈ1–’OÕÒÎô!=}ã+8•"+Çi„]VI,<Ê‚&#D-Jbá©K6QýÞ¡ç¼pÿ§b†~ÚÐà ô›;†t­=äËIΜ'ÄÊî‰Jµ„jx¶ù8Ós^R„tŸjˆ4h8T®Çó¬5DÚqÒ­iòAûBK<­- ¨dŽ‘¨U%Åtx^UÉ©”>ÁîYÛ6ëÐ † ‰ÿ±!žj»®éòÞÚjÆ£0Ò·»EAÌýÁ-J•l"ÿ&'&‰ío¸Æadð⾕Ðc8F:–ñÔ$eÃ(üƒÇ£OÃ¥(œZôEu*Z›&:ÁøÆ,;W ·ÒvîÖ#Ÿ³e2‹@‹ úx&7mGBàn» ¨Ŧ0ˆ$šwmÚ—*ÄD1jBQÒ#—nßÈ0ŠQûundAP½Ï[MfÞxŒé[dj©"̉Á]ä‘n»EÅŸ‘F§G;Þ0ÎfíJœÊ ß=z”j¥ÅyÆw-3„Š®Éw?Kòœ#-æÂ5cÜV¯Fé7õx,¬uñçUBúT‰/Mšã¿ÿA¢kc}ž™jˆ_[ó4‰ó0vÿ q39Ö 1R|€õµSgÑ+-›V&@büí*gt5öuœëÔ÷ûž!¤£¹H=]ײNõÞBº6Ù­h›¥d.†Ce+«‰Šá@ìûØ^Þ(¯\à ®µ¼ÒtéÙÊ+JpN ý;%c¤}Õä -¬‰xH2 #]²˜aå cÝ/” †Ê(hk‡¹8¦MÍÏÀL5Wêîýákzè|ÄÞýWRß ­a V$°ÿþâ ø6ÉsI£Hu±Ö¤ô—p½‚¡W;mIi¼û#Ù÷JêrU©ÑXkRâÏ©E•yZ@ƒ»w7²¯:éÔ\ †%QÅnX´gwäjä#äk”ÿú¹5Î#ògêV€îCÃ-Žë qlk "øzÀîNŒ˜ƒ´žã—S9jˆã[SGÉiÁ´¹¸mëAЂ£ÏÇ”†0ù.‘ß›{a]ˆì2r]™c#uò{>ŽÕƒ´Íû_tÛèóFN%”û£kÒf-aíÖ©39ú`¹!Û: äÔÑZ¤‰H&éUé&é?^ó*é”/Š@OBƒäD^®WŸ3Ô ø9nÏö✺Éx£èQF™)ÈG‰Þ_qåÊAEŽüC›g˺%.¨SJèƒ7saI’èãÙhÞ¼|V³é¥Á—–Ña¥H«êÎRŒZÕ¶Õ ï<ž¥²Òý5£Oˆåšh)†‘(ù.K¯¾‚7ÒÄÌåTÐ"(¡o¤«-B:I¿øq¥;Ço‘¾€Ñ70òž9!­ýI‚úFͦƒù~ȨìšÍµ4éëH^H§È«ª ·'é»7òîíþKö!CIMï.Þˆ¿@8Èâ Fi@ò–c2FHv0§wŸê¢I<òà%ÓÀ’A·µ¡›\>à‹~¿ZûfUqŠm $ÿÖ€:º j!:&¶¤Î’^jI¨«²7¼bÀjYwûžb($zRÎ1âPäóõ“Ýêk¢Mü³'¯µgã˜e©1÷ Ú4ì #k7•ÆUCzœtÕ;ÙUñõ4hÃ;X ´[È2nBc$,Pq/Á¦;©ß$~VQŠáP¡RGÂÖvZÖuÅÏê|uhÅZ¥(´×Ó„:ZJ°d­¡ôX7Uã1uø¥˜¿é×_‰üy­æL¯£I0 giQá¤ëÊó‹­TêërX|ôãÐ,CY/ÆU¤‡%sGr4m2ÏÊjË¢ èVOÇ´îø/p"°{ÊE…>ÀœŽÍøÃK€4ÏôGΫG6¯RK®@-çŸ>@uŒÉPcèWùMåBð·-Å´^SGÀµ)(MT0CÁ—í¨pf­úm.<®§õäˆí2šæ,‘¼8 õm ^ã¥ÖØâ›|]¸5$zÝ‘>*;ÿûÉfd—Ý!È´ëÔ—ýÅRá·ö $FšìÎcw4_FJvçNä¢Ö.;Œè÷ûBäJÈI¶þï÷…~}‘óm HçÝk”™¯H©y0ÕY@°#2EjtKŠ…Ycaä‹©Î…ïî[œÊgEfŠ4‘Kd ãéý)2^ÒQ;?ïJ!§ëµ¤,Ü>‡7Òj6ÿûWo˜’Š,üDrv”Œ‹ / BºÍÁŒØAîïÛ+걬4+–“wN„ô!Cq9ÙÍ’½"³ß=¸Ë¯ô¿kcÇøš¡î…'NÂUF…{›?g¤ÅúB9a[M»ŽeG)~j!oÔ‘ ×ùÏ“RK–Éü3.*¤ þ¥#ÊÊä¼±°>«å0¯êhŽ1‚-BÕYåWua¨ûÔ@óc‚ÈÆû aAt§Æ}ùA‚éC}=>åb›ÒLDveðZ†¿6;A5¢jÕž Ð"£o€DB3&ôË"Ô¥¦ÛHš¬éZÍ—R5Ot±irÂe3ª´»¹ëÒGœ’R ÉJßA“U¤ÄZÄŒÊvMÔÜSy»û|}ujùjÍp„pÒû† „mñþA‚P­c!ú–I“ËÌø~&y¿«kâ&Ô¹êsÑ7B"(7+-64 –‡³mÁC ½g‰·qš@àA }þ-Ñ©\‚²¼ûx^ÕØ!dðüÍWk>gh.ðJXQL]wd©“›ÿ–íûµ”$®[ˆt¿1²#¹.Àÿî|^ ê\Òx"MÄ8iÑ áA¦ˆOçkù6y»Ë¦¾Mçûúm’ÓFZ¿ÍÒömÖÝlÜÝþm^2¸S«©x@«›Î×òm2—&*4†‘Ñ#uuÏ·òt‘ãXÍ;–ùJ3mòѼ㜓î褰`ä¼Ö5k•Ñ‹4Q“Ûc®VÅöˆ”¨ dµøN×O;ù7LÍ:G“bû¬üâö«'›M§vÇQ¢Šÿào“`×n¸ðs²œïÿh£AÆís{2$CÚ–°Ú8Ž&ð€91-·7r_¤<)׎vŽûëø6ÔÎJÈ”Õãr€}\äà&:ž®Îd±ÈWܦ« aM.˜ÄrEÏ~õþ«2É¥è˜huÎY«ä’¶ïç"/2~ á]ÅE–ä±Ä£$3@œ>#Piº¦3˜ GŽîáÀS5OwwUv$dDW„tg9Ãôë—ë—õ „A޲H$×tœ—á—,M‹‘šLÜw•N¦‘L¦!}Ý¡•§h’"M»&ù!d€ô×™î ›LM DdÔt¸ ~ò¢:{6eìEÈg.YšÒ$Ç׌ÕdÊÅÈÓ(¤;Çê‡ÇSüIæ¼ÛZ4ï´þ}žËçšË(ª´Ê‡Cµ¦½\,²\F›Œ«qUÕ×IŸµ]ÏÓ¹Lëf@=ZKÉqʺ҄ eÇÿ¤&Ó÷ëÚµÝA…QB—O9m]›µÏ*MÇ • Ül˯©Ž4M (ÿ¢˜Ô[.Rzm—ìç>Lþ³¾Xݑπ¤ÏÉiuOr<û?ú×Ç„«›¢hŠ#×_ÕùjЦa+îçØŽc‰¡ŽF-ØûS ì\’ÝéL1Ô5زÔq//®ì$q‰qUÏb\t-*Oá„x¦Dt‘Ϊ÷qé5±"{2_zõYÅvC‰„2_Î!K;û6«3ƒƒÙŒÏ"¸ºE]• b2÷c4±Ñ¨•þc»Íã Åý˜F bNÓ˜l8»*)®–uúûp£gû³Ýç¤ïÒ¬4 ‘FoäÞaki5’£å²ÉÿÈuþ$žo侊gœê\§IÖ<‰¿*ñ |Ï`YJÏû/–ºø<¯ r<œçëeÅH÷ÉJî:–²cÈÿâ5¹`e~XëÛ…j¨!$¬!,“–äVT´NÚ"¤f] Ó9²ÒþNØÃœ÷µ¼­çiuˆ¡Øªl6®éK#‹ú¥¶u¦´ì!ñ¿V‰?/m°kû/¶¬c fˆïàõ³;ÂHª¥:¡w$R#±MâXé=¯óÔ„²rJŒÄälnùunµŠç}½³Ê”F¸Ht¡FÞ{—F˜ ¤E¡^ºR½»]аev4êšþK_W’,³ú|#·.“cJޓ鼔DFä/É cw´ÇüûíÅÌ|o/bRäëºígôùk¹à¬ž«£Uu?0•T.˜„u§ªÓø·ê‹Êw-µ(ÆwsÁs[võŠß=T’B•´}K'2é&Év^žb´”rü¶dÅoëLnSÆìé~ä3ÂÏ),ÅþeÁwÍ?øºž)‰ ZŸ%ô«¢žtaÕŠºê޾5 Ž–ài®K|;Ÿ„º–êSÝ^'ý¯%ƒ‚¯ödr‡&‡æ„HS·ùë?½”Ü·d”ŽUÑ},Ë´$9 öME{Ÿ‡!]­›ºâí÷3Õ®Ðs4u›¿}š—ýÚ×]#JÝF"+º0÷YRɯM=Õ÷ÏI—±\LFþ&Gc8û¡"Yþ§kÄÒknGªÊè~¨i[þÃh %K´ö´‘¸NÆ6ÈlS¬Š¦äÁHÕ¶mª¶ÄÈ’æíõe_×väŸ2¯ã¶ÝÙ­Ó\,éIdJÃ~Léê¹;H¾!¤¯úèK𹩦¶ë{8ÌùŠhö›/´ß¼6¡8”<-AùXë9uûŠ!¯—Ð#ËÆñ@ÈXC6¼½©¦©†%;ÏüÇZ+šk× ¥øðë‰i¨ªöð_—ô]öðšÀƒ0èúÁK3iu_4Rsy?ÕbMÌ525Š&Ø”êrçyßÊr€TÌBiؤH ÙgXšÞ':óŸeÁnÌt5Žcž¹û,9ÊÄÖöL¬|벫¢§«ñóOå]¦ÚÂ7™qvÕÈì{¥5÷¹}ÀÜÌae yŸDF!Õ.ìªÐAµ /‰ùÎ òäÙE§Ú&ž½Èóg_ª±s'Ù3¸k+ \»sy ßàÖï}¦ª3ÔSɲìZu†ÚÚÝAã /D¾-]Š|Ç'ÍÐ…ùUhsŸž¶ÄIºõ®é´%NŒºÀéºbÔÈbƒÉ(úE”ÚF,èªZÞ,£ë@1Pñq Y>æÒÓÞÖ«Q°£çoþUU<1·È«Ê¶dþLé˜Ù¥5…${“÷”Ø äw=þÑUhÅT!<'^wÛA‹ÆgVZ^×–©qð*å•Zu¿¬­ÛòyªS"8B®7ٮǯ3/*ÞÒËFè«c¡¶‚ܪ{¸H(Ð+'Ç(zyD÷0ÈÀ ¦”†×L=ÁõêvmO1â¬}ÛYì)1ülªva˜´Ûv¶{J¿N®‰&z¥ŸÙ…†Ð(²‰ £ äðÛ!ÑḚ -™ £S›‚Žòøw‡×Œ¿ÇGÖ†2 Ž%  /COn™ÍÑtÐív) í4„4ò<ë ­‡¼_¨ßíÏ#!2 ~GÅ•!2 ~Gùâ`Îy529‰?ùþâ‹|£[ˆ?ù¤"ßè…âOÒ‘o¼ù6³C#ÃfÔ\æW[2gV…<½ŠÓN*kÍnI@Žï³´Ž±ÈG@N<»´ŽaybúNZǸg¬cX—wüædÀ’eôäÀÑí0IPgÇÂS ƒ& »íüÑÈ8h23!ëÑýbçQzi.äò8ŒÎ5(àÜÌ®ÅÝmUy*Jª1'yó5yìyg j]Ò»¢osé‹víÒ;;.íAŽÔŽÚMd…î°k”ÿºVÃÇqaB1`Èèì¤QPA'÷æï·°]©øBne¸ß/Ï÷eºß¿8TÖjPj2™êòxÅP“‰M&gšLLi2Ù1šLTk2™º"ºGWšL<dð×O4™F£ÉÔä‰&ÓšL‡gk2Ùê–F5™ö·!QÐHMVö¬ºÇýQRsÑ^3 ØíÒBdµêèþ²­:/Í6^B÷GmEe¼äžèd[1ɶšà¯ŸÄK‹Š— ýqxvbŸ}¦öן¡¾¸‚ª¾8‹L*0ƒ¶Ú{èž]dÐ|ÙzºgתHË‘aU¤ÙºÌSER*@ëhso)ûREòõ“ø…¿þ i±þpŸi°&`¹²™åÅx÷Ù²@52¨Š4ºèâž]ª"m»-»è= °³ÝÍNÖF}ŽÔ½ÑàùÀHùªW/FE·pÝ]غZjŠnž/¥¾Çl¬Š<{yx’ ba/¿Adâ#M§áDÊ‘ç#@>B§(Øf](º_uý‹Ê7DF.NolÎ'z¶v„Èø¬FN¥—Ý=­Ó2ÈôÔQ.7ÅZ|önÈÈS¬çW2Ù×ܶ¢8=ÐRJ-3tmúf SöÏmS7¿æÞÐi{Ãû|øHÕܺ¯x,ÖÛ-!N½Tªâ )Ë·´Mß´ÈÔÉ×Yß'ášÞ|újHM¸Ö§!\ /™Ã_W Å_“˜KùÐ¥¬Ú~#oþæté=Nžº×§´uË¢îZl‰*-θÎûm³u@Ç*\ùù/W·ÙsdüîÖ­h&€Œ ²P1ƒX@_íÀº~:\SV´ÿ÷W!U[1G¾D^î>¼Íú4Òè,¾^üVWaôòÄåŠ_·Êl(Ëbâ3ÞgjôErsXßVܶ<ø”)w¹¿Š”^·*VåÁw³m”Â÷É?ô?Z9CE ¦ƒ`º7ðÍß ´’êâ¢ÓŒÇ¹cýt€ÞT¼Q)$%õ ëað»™óÔ?Ì0íôd›?«“ŽE1:)«þk6ïü_¾äAOÄøú9Ð2va‹)¿XU¶yn)IÈó¬WÍsæØCš¨ÍþºŒ¾üg•‰•î;¶ºSyîö¢"79§$ºš ÃG>Ø&÷«6žÔØÃ @=q™´Ô>äh¢gI¼gZ’(LV¤Â´ÂîÜI½j¤Ø>ÿ[kŠ}5LJŸ§¼¢5Ê–0’_ƒÉ<ä¹ ‡Àt}ß³Þî4Æ™³|Äf|z”N'©ÅÌypGö•dt:’ÙH°ÉÉã@®“§ÁB‚ђҒ٘ɹÆóXù¯×Z±’öëæÒ¾äHæL£†-%¿4j¸˜)ù­QÃýúe£éÜa›ó—wFBF’MT÷ðˆ 2=;FR÷ÉãÕ Ï #ÿ©=^J6Œ‚F gY¤û¼Iµ»'ÊÂm ;ÆüuLÓ0%n¡«è_¬$ £ïv@&Û‰+{Yغ'œDrÈ‹¦^]=n¿DÀö>õ–dSÑ]ÐbÛ´Ï'©þüHÖÑþõ²åo¤úW~wÃpÚy`Õð¸þ€Ô–=~Õ{*y’ôgøëÉ7vûŒ«mæFIÕR ÕAÈzN^ói 2éTPáÑËØáÙÓoäÈ0.„ËDf ›Ò‡—{ÿyñ$:¥%ðìãÓ| R'² *e¼4{¥Z˜Qþ1лÉSôh2L1éà{:ÒG4t"¸Ý¶ÃUc*£»FÜ®ÆrØàUÔ>a¿*þìã{:@U1òÇWüª9nßËp¸Ýÿòó®ý°<¿%x1šcšžñ=Ö7:CŽz,EE‹ªÐf5¢Šï³¸î Òí`DìP•¥jt$„u¤°Í18î,J•×Hæ.÷Öeè¯!ó°µÑ)²àkòUlÉ÷ B—Ü¿df±|”Î}?¤3â“ ½j/-òy*òé˜xF™[(6ù^Œð×SÓŒšFÁzéÉ’lìF€ÌütAç <]˜ç¹´ð#v¬¹ƒ*6n‹¡ "5­õôHªÕà Vk_ä–d ~RY̦¼«“F´1Òì˜Î_«Ÿ>ö¡š5ȳbݶ­ÐÄÏ‚´<ÓŒ×y»“»'b@jÝp8ü‹®}s¸êÓåAD Ùóìf»b«çÃUS™  ™YvÛ0´Ÿ•o 3ÐÒj˜Ïy¾¿ùê_ÃAuG´UrfÚ¾·­k 4º™ CYïŠa5¿> ®^¶#Ø@ïN¦ÙŸ)< ÆQ=’3â¢vÿæy6n_éÇÎÚ¸F\sžqcdôÑ#"†©x°¸˜+Âv€ôD mcÁ‘{1Ã<äÃ'ª“Ú<ÿƒÍ™‰›}z¦h5+޲¡C ©›)FŸðÜjÞ雽2óçT£\|NåB$i—'Ö8黎N+„z³´ú­vxîšf]Wõ%DˆyW­˜|Ì;ä g—Ô±ûz­y¡¿ØÝ@›‹¨)„jjÉÀŸ@BùdÅtjE¶`"´Ö$ôKÌê:ïà{u³OÕªd©ìCÛÏÒä>VtÖ !Zy={+ôx„$DŽûr{ÿ3,žC¤ED†sÜiÞ2Ð !3B»¢¥aâ•<Ût÷™³™hÌc £ÑyQYØ÷ÎEÜØÍôž¼Úr‘Ï7ÖsJ>µÛx*>,/x͇/%¯®> äîðášOW'¬*u&ë„g@¦¢(¢Ã_Ͼ x…áùÐrxŸèû€MÛw:»ã|ÿGÈöªdÜhóUïÙJ  ¾J3ÅÀÙÆbe£yøç-ÄÍÙ²,Ìõ=ïá‚û(ºÁl÷§Ç.>° ©`vÓ¯©Bc)&aŽ®ƒQ0{29ãN‡ûŒÂ þá>£_îÓ žQà>M„»ÏÈKð¡ǦŠZöšñ•g+Ÿð6Å~^ª Ï|nBdv™·g°Ïä—y{ºøL~q™·)Á3¹v™weg”U:¬r²<Ÿ{fµá‘ãKÛ”Ðø¶]¿”Óù<éIšESçèº]žIàL›O9ž®¸ƒ÷™ûÑïéÜI<—yxt4‰£#+‹‚žá££ ½2Ø¥Ú¹nïçóªHØ:ƈFžqø´¡çű.ðiÓÈÈïáÖc‰°YØÔÙ2ò3ûꄳE˜êµ/ïRµ~~ô|W+Ø8’uµ4Ž×}Ú=D-Ë=3 ŠÍCéðm†¶Ý^ÙÞgv¢p¤FÝÜÑÏP–ðןÁ‘\ž(õ»ëÀHÞÈ,4’wוþô6ŸÃHîF>’)|"' rÊc· g_‰ðñTUoEÁ1"÷Ë×FOèð­çfŸ)½…ôÜÈôš<=7”Þ~Ñs³o4½ý¢çfW‘ôö‹ž›}öôö‹žÛù ²6F{›þÂÚ°^~fm¸7Ÿ^³6ÆÝ ¤wØ%+ܤ?`÷;6å¶;:NÕb[ÉïØÇÞEà£ßºÇ«‚7éÌò¡Ây8@ jµãém¼fìwë~—–¤ïr‚¦±ãhÆ´ÖåØ)ióz¶+h;¶ŽBq%B÷¶ËûmȧÓI3ßýSÐ¥ošr‡¿î|>­Ã0ޝ}^]?mêŠ??«²ªÿp;í 9 ‘ Zk}{×ÝîÛé9E>Ñ4ŽóÖšƒòôñ­¾«J‚ƒ¾Ñ—{¼Aެ#=[ìñwú8ûFêk¾H·u ÈÃ7’iÿFKÞõö@&}\|£…õVdø}l!1}\£‰ÀûÌ,wÀꇰ®›uvÜÔïoÓ»‡Nš¾ë‰ëON:¨eSëF£m]yæcc«ô Ú3ŒšH|h=uä½ÁkÆ^a؈Î)5ƒÉÝçÓã²5ç°ç频3­Z*Ü%M/ÂÓØ¦]©‹ÎTXww€f×Ño÷5¡BrQ˜]fØöf-rë<-ËnVõcžKÍ9kìªè)$œ(á`žì3€ŒÂ¼ »&gQ ,À¯ù)†mŽ’Å!ÞÄH%oÂÆkYàMÈ]Á›€×ŒC™Çìv_Í@1VÅqÌŸ™WfüQÞ~”ªË/ƈÝã<îÿÉø¢¥ǧ‹=îÿIϱ(žØk>.•‡_›Ýµ³ÇÏUkFÕ@x˜ºN½óÙ#J·מ=C*ërßtº(K/x‘¾.òyúg¼Èñ€Œü¹†ÈfE׿že_m ÒõòfÙ×!¹U˜Á}W»#åÌóZ?ãV¿Ýì@‡ÏâXÙ®! gÆ£ÔfŸ—ìDO¼óžJ€ˆÁr}L­"U¼—»=ˆAwP 3|µ™(æëü>×é¶„Ž´*nKiF† ãoä2ð!?Í£QœÖÈäô@¨. í ®;¹*‰:ª" ›§¢Èg`${šNE,W,X®öšñËu,× £siÐÀ‚¾Ý TkŸó¾_B£?H-ŽË¤.7æ òøydDî6^:Q3PHé@gâFÈ㨩kgGv…õÝD¾šÁ)~½>"Ÿág7n=yöòϾÀk^<ûë ¡gg«÷DÏ«gŸû#òy¦,ÄD !™^hÑcìûJ,ÖM›Pì·ej”¹ u ÷¦µ¥ZZ?©n ·Ù®S384SÝ@~@FA¾¡‹mœš©þÖ¦b7‰²¿Ñ9o·ÛÉ<ÒÑÛëyÖGóµMâÍã"CѶFƒLNîSOx÷yÝ'óð>ï¡ûT#Ä»Ïû{Üç=Ü”ÎdSúl®)âÈûbÒñD#ŽŒƒœP¥VDì5“kµ"Ó¾nÎcX6Z¨ïγ3¬¹·ôÍÉcÅ~gÀ'€Œ¼]Æl\mÆñSvû†íÚævTg]‡3ÈÄY{ÍÕ¶µÛ äÃ6º›ð“?Ñ›oßù»²ÈçW£»jŸMšÓPoÑ©ß'ÞyøKíûLA›½È¹”ûëXÁW±[R5mÉ‹ߨŸ–^XÍ2€ŒZêÙËêÕâ—}Klò¯ÛHÛ’w“¿ôÁ=G¢ƒ^c Ëò¼ËÇ}Û2 (ÌïŸê=dì¿ObßçòÞ‡ñ ®É_–—”*Û›|ëÈÇ·±Å®è‹Nù ¬Þ}݃Ãê=OÞêmaNC«áÈû…R“ ÕL@ž3l•«¼fÒêÄnµ¹ß¿•½,Oýõè43•„‘p¤»ÏøRý©{¹gOºF¢ùÑË7 òL×HtA¹|Ó ã€¢_i)È$¸Ë˜ý#,So7È‹ý}ï2¨~áÙè‡p¤§)¨¥›»(Ã)7wº×ö×=Mñ>E6!§»ts+Õxþ'-Lkm Jævèçm}Á‹* „?²=V.÷tåÄÂ=j:\Uy”Hçº$²þ.^æ.ÕP]û«ëq’¨Æ„±Â¾±4(Ɖ]xÝ~ oDFAʼ›y¾œÅ·h(ÿ×Ák&¡¾§É-{ÑÕÑœPcÿ'ìJ– U™å+µÚƒ½<ûóEü÷œiTZD…8Od([ü½ËЊªÊL‘Ò\;Ñ#2Ršc_ܶœÂd.3ë$Š*3÷bhüŸ m©VuMZd–1H'+«+FšE¥î(­|ðŠT€n&%24u¨î!2TTö4°*HW[!ãù>ç.âЙ^ŠC#áfhšx#šíj /íbÍ/,2‹ÉH ÔÃkÆÅ¡Qÿç#n厞èÚoùôHÛ´.Ïñ¢’‹7w……{)ž-ë:ÛŠo‘9°=ÔÆÊöͼep”ÞÀöp_“yAÞÎðš{àæ ö¢_ùâ»ÃKJBŸ%dC2p!\zb‡N’Ú§^JmÇäÌÿþ@„ûÑ{íëU®¸õH!4p^´IxÄÆZFCëtø¦aD»qÙÆu1ÏÓF¾È¯áß7m+5ÝNoºb©Iy€¾‚ot‡b9XÅ:Vìðò“ø¥§Ý°Ðj†5Ùíyþ:ç éMõa\SÏ1©wÁ9XÅÚWÕ´ÂÁJÃ.wÛ;ßm'çs5ýér×lÕ³Ö•ðm¥a—»³ÞT[„<ÀÁJï¾É¼Û‰HS%#ý¾íPÀ1Ùµö™ IxÏÉúôšCû1GþQ06.ŸµC¡°Ÿi±ùÈÀ¬ãø0Ò<ôk76ZK±,d#·úv1\mígä>N†å[O_¸ÝlC|Ñí†îCDG䡽Ø‹Õi aA‰„>£M>3¸l& '\UsÍfò‘YPh0ƯTª<5o>nP_'ÍÎ{‹QÈ©•È<©UE«€Sk‘§ÿ‡œZ‹Ìì>¡âB³£L*¾Ä‰ÞKä¤roÊnW…ÄKfGù£ÒÈ3Î^ Q9Ë]‹ LmÚ½±F³;z@Þ¡œ¦µ|ú"TÐ ¾Ð`­”¦¾&R-îH’b{Û’ÉeªkŽËòi(@†;ôN…‘;4í‡u«*€ÌC ¤Y#$õãZU@¾C©/§?ÃåItséî4<:Y_ÉÕ¾bý~Ð# kŒ@ÅPrø–’4âËLö{vË®•ç©ø²[¼R6$2ª¼ÎbP)@*‹Aìé|l-åé¾ç_Úô™þ*¹eè¶s/ésðã#ˆV˜lÔM/éókLJ¨èÑ ïþ8Ïéiåyû)eÙ…$îWjÎtÓî’WâdrfÛëb‘Ù©xCßm¢*{€¼^äíŽPæŽóz¸»«lî¹qdsãεÄ"O4êå‰@éŠ[ê«E¾ñ¶Òå|5J2Ø+G.‡ŸÝÜê5LUd䱞¬5Èô¬Ã<;„pHÑ,~~>¢ýœ éú9-2;óüÅ„*Ï_wÍ'`-„N¾3/”“/È4ªÈÝ!'{]ÐýµÏšùüÙÙÜxA8‚ȸ[ýè–å,¿t«—ׄÈ·zµÜ± U=DF5ÿ]¯ D¾#šÿ*¥hþ[dzÚƒGtžÏ{œQ„—À@"“¿¸¸´Âý/uäFég)åM§Un‘÷Óz’YûwÍ€QôÏÿ ÆöºÁ»ªÃ™‡&}pЊٸªpç=cò8ÆÑáîÞÃèÛ)¢ÿ"ˆ‹NÀ»?ü\RD6uûa•?ŽK ¯ùâûù¢(EAm_ŸEž*Q7…Êà5óS.‚R2¥‡'zÇë,nÅo¢yÄh,»kÞãLíáö¸û¥["…¥¿¸%ú½ãþˆ;^­ãÒ ?žqš§ŽsÞC­[­˜Bd\§ºïýþŠ(ùc«äOòBÉß…µ÷×E*M)ùxMï¶`*Úzõˆv%w‰’{þSÍ7guµ¿SÑ`WÍ¿ç ùRéä‹:ÓÕL|Å·i\xŸ½wS9šè 6iÐÉ ë[¶%îU„Í2 }Ø-µûâq¡#DÞí)Y'vÆRf9¼tgw¤ÑõPȺåm…!òyÖ! ÇÓÊ8e·Çíl’èä.+òÖ¡LoÆ:ȃôö¥Ãj‘)ìLviÄOE×÷eÑd¾£=‘€PóÅ_Æ*€ÌÂwdèªN+ߦ¯¯<Òhw×H7ç™”Ÿî†<º/î‘ý:s¹ÞuÒÉÃ!ï½ëE!(3@F\´ä7,ܱçñ¸JÇ“ ¶õˆ®Ÿze@Èßý‘q2ÄjA]òúñøáÛÎù~Ŷzd\èKy r_Ó|I À«Veâåãó$òW”kOI‹C¿Ü2AÚ4.ÂG€@@ëÏ?–‘i2(K÷<Þ±¦Ê~?z¶gLñÅ&¦ø©ÏïìÊ0!SüÀ äƒÜIjý>¯di)åÂí2ÏäÚÅ qkrÀ?u1À‡»ßcÞŽl‘³ÞKíw0 ø?Ÿ¿R·ˆÍZMþp÷WÌï ÿž(ÿíTòUUÑÃÿŒº8²ù˜‹Á„,Ïä—åéJ´š+îïŸF¸âê$§¸â~œÒW\(QqÚùXõ™Fc¢;ˆfˆ¼ŸÍÂJÆ×ÃÝ]‚ÝëŸã~ûi%~ìÓ˜þ9+(j…?y<ƒø÷‡6‹&yæ†w–>…èŸi¤ô©à¢è}yú™]óº…KC>³h‡âœQ}‡NéÿB_\ܶ=ݪü< ;-IeŠ+ÝJ©Ë4<¡>¿áaì]9ò9‚È»ß׿S¯ã½kb˜ÿÆ%©3Š,%§Î«‚ ˆ|šXÕø}°‰U Bá³»bIXN-D‹å‡‡2p¹^óï×s§™(ó—JôçžçóZ*‘ºÜÞ38%ü·¿M­D´q2%=Df‘ˆ^ú\ÕóëÂÛý{ýÊðºöïE®#äùb0e£ê”¦ô¹ò¢‚¯8½Š ˜ÀŠ®DT$œóûu¼W‡Nçós”ósöëw”)*W¤CŒ/äû¼¦‰ÓÿOÍ%´ë !Ö¬„ÓÎÅk^#àd.©óƒ×|N¹š!Íþʼn®)¶/ö§®'ä ˜ÌüÏ¥™«í뿸wÀ·ûßž&×U¯/áß®Xñ :§ûGí±†´ °Å² ,/OÒätÕ I‹ši&YxǺÍÅ€OwšqÞ¦<-‘ˆwÃ6.ùŒFLƒ‹Y^·KnÇìÏСBÀÙºwçòWÜëŒè3´›K¯¿xùoó•DŽÑ.þä¾÷Wzå"+#1×âòJ/}‚pãVïWv…iV"È4æþ#¯Üdv¢˜C”b™)¼æý—&Ÿ].KvqzÈSü0}¢g.ïþºÇ]yUçc0JëÎG_o í‡ÎhÅJìk·Î¿.º”/®o ¹ÚQ-ÇU¿ú™üQ-p(-1íçòÌw”[ÿgÌwTqøòuÁ³Dñý©¯8Ïë^o½†PõÅqNü³¿AtQštL§ßfõ«¶„ÈHv»4`Ã˵é€Ì¬Þ›©8˜Æ•qZDûé'€tú©º iša乸ÝV†V€|«¢U†`—uÅj O[Ô…Ó]ÂÈ¥MxÈשë“fÿ¸Õ&¿ý0Ú!£ÈeÓöy(¼nÎú¸œ‰‹ó8@w_G_CˆÉ|Ûw°Ïaæ™Ì÷·ƒÈ“Ì7Ú3ß¼Èì< ¢ŠÛÁò,ó=|úþ+:·ÇåY,ó­%Üpé¾£<‹e¾™É|»=.Ï.3ß½`ðšç™ï‘öð‰BeˆÚúyv¸íäöŽFé;³Ù|„ÏßÒ}qŸþàü‰è@6Ö9@fçOÑï~fè‘ãH|zÈ)ßù‹~U̟לHŸÏΟQN9Öœrÿu<œr¯\B@¬òé½Fªž$È®!‡ìú¶wûQÀ§×ZAª-Ö¬ óŠ&¦´62UÎßoígça(ˆÞ¹ ½`”óêä$Žþ?ºÌŠã¸`lc~GÈ󃬲jßÕ=ûóúùð"øÞó#ëˤ*Õ~´uâ2`÷ª÷®ïÞDÙÏ¥ãäyp*ÿ')æU¬í*føD®ë­jª=ÿJUW(!uÓ$̲h{¨¡*š¾ßÊÃ(å¶9L=ÑgŸŸdYúbúÀ'zÛ†/u’úìú\=F¨˜ü\ …®˜:M.¼¤ Üò­7…üâÍwRz)í×D=™&€Ì~Ýt:†iÿ÷-:éyèÞ`‘'î éÝ,ò½ÁM»÷í/î î3~ßâÓº|æ>wr]>ódØwrMûÂ"㢉£KZ½Ókïðx‡ÞXÅýžÊ3|åF) hh?IŠ’­´ë2=íœî«ueþ‰²€WðÇ$DöDS3~<ïÇå{ç¨kŠºÆn3~ß †&£þ缨€×Ì~µùÕ5É:¶~<ºßOã‡9qíïÇEãR Å‘=õ-×ïÊG¼<Â!`²Å0½ŸGÙ+w›µü‘+޼_â£Jþ¨‡ÈôäÙ•0š7¾—ÈÑD[—+C`|o‘éÉ(QeKз.öÎAg¿±qíÌÛ¬§•5.T}û…Þu·ë²iÍ‚Ž®tø†ýº·~ïñ+ ±ÑM €L…K_Ö÷¡cþX2v!àû ‚¿ti4äãœ.ÍBºôû :æéÒÞý ¬{RµÃE¹Ö#¼fA2‰„×|Ÿm‹©öì÷vÌÿ@Åt€&Uå~žXØØã¹¯6¡A¼µuhFÉ6Ïì[Ahv ýjh¡÷ú1váÓ¦úµ·BÔr8ªÉ3Î-w]\;ôe¡¥&¨Æê†ÏB EW|!4÷gÔÚ‘?k;ò´0º*ó}¡4õóGBåv gÿ-P¸ÜéÇ®ÞÄNÕÔµnjP³ÕWÁxƒ8[R_eWŽž­Ñm…ø@hö ]égTÐú½[;/­Zjˆ=¬Ç ¯…_Nß¾cþÏƹÆÄ: +åq N—Ôë›Fhµ u[¿‘ÃU_'ÐEFN ».¼!HšáZúqè¶ ’ºCßjýx†yúœ@3Ó;ür1D; E{, [öÍY×kÍç²eðÛÊÒ_hSš­"?Ðsá¬E gÙrjr»] gWÖJ¼œKȃÒTÖBˆ®Úìó'·ä‡e"„†×ª{jg`rƒ"WÊX×lC%¦eT¤:€ æ_k­ìU%\Äî]c‘wßÜ™ Z*÷XFhä#tZ1%½¡œ–ª¢n7ß‘»dᅥKÙ}œIóJ7ˆ|Y¤:à™YRóqBÝØXØŽÌ]£š+=¤ü`ÞM"wfjß­wÀR’¦œ¶C¤µàŠ? ›î7÷’ÒXߨ›¹n×ä–ýæ>­Í+`îò Éííït×øÌ2=éð>äv¤·í©š½ kâcAù`´%êv)¤5ýÛÆ\N% j aÖ„»‚/½5̲HSÓ£d¨F&FF[ÒCäý7,Ö6XâÃ0¼;è!p«ƒ\rÇÆHž~§²~%•¡Þ·-”1:@šÓ-?ØPÉ7¿°ŽRH–p}œbÖ¢' ßçÎR ?Œü 8ÁêZ;ÁöóܺaúÝ1/ ë¨d(¦¸›g.¨ºn.¿ 3·9î#¥ÚÐ|¾¸ í ®¥®hvõçYTɹ—ƒ¡c‰5‹bE×ñnî@2Uôϲc3«¾ù²­j…VÖÐIþµkñÌ‚×D®&I6r-•ÑN0™žÀ ¢Ü- ä(ÃgíÆº…O”ܼ¯Q‡4Oæ3 cÓaB¼}’Ää§yð)½"÷ÁÊOCä ÇXùiˆ<ḻü´Ÿx¯¨ˆ§º=qløä–Çä§åi0Ÿ–ÈwŒ™F´±EžÐŒ«§+$^é ?-‘¡ü´EžÈOKd(?m‘'ÒÆÊd!Ÿ¶È ùiÄòB~šÂÿy"?ØÊO[äû—(ÿg(*%É-"*-ŸŽ|r‹‰J˃} *m‘'¢Òò𡍴EžˆJ«‘D¥-22ò¨´E^ˆJÛüËŽ¼•¶éÉy!*}@†¥˰/å¹”¾{¢ä°*ƒS+š¦d¶ð¶v‹o[F[øMù*K%ÚÛv*¹álsY0€¼GZXïJ1;ò`²ÐšbH)£‡»?äžU‘HÛõð‰€D‹9Þª|Šr­`ðš¹o5V×4gKyTë:G:Ú‘áÖ©²DºÅF¬kQŒÞÝJ´¡ +<"w’~«Ð$ ÐÕ¦Cé®ôd+èá}¦çý#*Â#pH­D‹œO­ ¨Ø¶­XÈáÜ£zhÍì ½ÐCŠÁ‡2©œQŠ!2‹yïÙO“ÀQç?“î6ÉÝÐT¸å!‹;+wÍû¥‰rœ…$¹_›Xa¯™ELk u‚&Irÿ±¤41£#må¢6Ãkz1—}8U¼\ÌeÇK?ò)ÞÝ•PvWð‰^1»+ù2!2wGªºu~5åßy ߎ‚¯íæ‘Ö]ŸæªÝæþÏýÑ´éÚ]niúž}ŽÐ$bî[П÷™Æü¶(bð¡vU.àþCýRÌ\w²…º©g󾟽Ùü+µÐh0åï]…£Pj%[AÓšuT‚…m?P?üÏãQ­k¬ÕCGæoÉ0@¦¿T`MèéàWR]«³oó1¡e)# :@ä^½ùWK„šOYˆ™l•(fx÷G°’Y +Ýs,L§pòûDÁA1y“ôÀþWò ŽýŸ$qú¦6Iò‘hTMkþÐp:åÑF#U+ÆÁ;z_»ƒ»‡Ê?Š lReÈøýήXœ¤·ˆ;»Ê÷‡zIšDɸª)\“j’&Ñúžª.S€ÌN ¢”‘ÕÇ-izeUø–¹$Ðe:ig]¼‚Sâu™ÎI£›KéE{›ré¶{™F›÷Ñáš™õböz*»ˆ9Í"‹2âã¶ô~!T)sÄÄ$}@ÁWý½›lÓ0Õm±ºØ%=JZZú»ý0³/rÁšúÔþÞo/ ?\Õu)TZ¹Kÿ.ŠÈS,,ôî‹EÈä9å2(!S&õ£[´ NCËÙâW’Ü;“BÖ¹XUÛ7;\õu3r3®Ô?ÖQžÕV¦eÓZ~?J·ŽÆÙaÞ׃×Ìγ¼òè½úµù}ÜCÚ¾fCÆ­Åå·„×|B3Èv¨tã&÷¥"õŒæº Qwv+Tµv$ð‰^±8”r¿Û¼£ä‡bLõCg´ØðH™Ýþâ‹ìæSvûˑҭdÙíòH)œ$ôŽ<ñEÆjâ{_d‹|ÄŸnmÎn`-9>¹<|Âk¾â^Ë>{÷ZÆðÙ/Ž”ÞýâH¹thüHIO?RªÜ(„þ?a×±Ä*Ï,_Ɉd/¿ý=Uç0Iˆ`’Aõ?ýUb¤Áˆãu&Jzº=)¥t/lñõ>§ªlæÐ2qõN¶}–³+ð:‡ÒfÉÔ 0] iPŠ£eEÀt¡w¶,6Àu” D.ë3&À]Y?•Û&ˆƒWräjÿK…Ô!#4u©—ÜJþõ`7{«eô“s•ø–5ÅH3Éize†µÉÙgͪӵ_ò¹¹xIçu&9õy:r·Å›÷;¾Kº™ûçÏ_-{j®ý3|yeïgè,Ð3šøW¡ç®¹{²ê Ô{öh“Ax7#®! ïgö-å)}3ûF̓Úgô™ýÃgû@F~W>{í‰wö¯2‰ü@þò¹­@_F×Õ.N¿|nÝÒ“HV±mi¤üL¢húæU|Çš”¡åsÿ§¦sòHÊè‡!dìpÄÍsçCÓõ»ô»CÈä—#>Õ¬˜·­¤øßÓÃy6iÚ©ïüLWØfC««ÿG a5 ß3oNçùºp¦£m«œéàߟg:ET–ÄÅ!‰'õ÷‡ðuëÊ÷µ[·£Ce CT?N•ìÛTác†×Ç•/ ¢‡ß_Ri[Ac'ò{AÏJ8¦ÏáQ¼ußbÝ@%#ˆübЋ'è$¹œ“ [‹ŽB4™ “O3¶µ¬OÈÈ›ÔÙ!²¹GYJJsßsxFQä÷†Ë%éJ‡Qì÷†¦©]àMŽ~J°ÒŠëi?œãc†G´îè?HÊPÍß'dô«æ!$RóÕ¦_¤æD‰O̓ÎHÍ#8©6a·;WÍà ACF{ŒëRB•³œ÷ÐÀwõT°l‘CË>]÷fyÁšá"ÿªùÀß3Bš¹ñ?ÎüF?Y¶ô …8úN˜ô.y+YùmOç#~ ¿ÙTG 2ˆ8;Í0e;`òÐ Ó_¤QÌÅm1ù«k‰%ÉÄùvk+XdÝF0•]1q¦oýÅwɵ4´*èþ.×a=Aƒ£Ìhù=J]êОž'ÁÊææFÍ4köŸªNh-ÃG)û*†O1îø9Ñ/Hœ@öåS?Ÿ 1š—3_gM¿Ž§Ë2Õ}‘ÓUe¡7ZEò Ù:mšzJsÜbôy³¶m‡ zúŒ&ší6^ï5ñÏÊœVˆøq;ðaÅ}ƒØgN!g¨¥9¬¸ñ­9Å´Àl²Aºß“ñbRdþ1Û–?ÑeUÑåXΘ‚ŽÖÿNÚ#ýδdI®9…®2Pߨ¨B+DÖqäÙç™Öm…ùñ Ž<º­ëQÀÜ2ô0çï阑óŒŽF@>ó<@MÐ cß$ïô~ òB·Uº¼(ÝÖ!ÓËh]–›Àè$° [öÎ+œ¾”mOÿž X ‘8.Á™Þ‘L'¤gˆDŽÚ@Y2N‘ôµrÔo2ý´´¯8Mâ“—Ôåº\DƒÔLCHb‹¢…QN•äü¡nKû=Ï~ƒö3!Ó6‹ä\G ëb"ÞmƯÛ¡“Óį߬ÏeHG7ër.Û“¿CÝ,îUµÂN›øêvéP3•Ar£œ*y¼É‰ß¡N*§f œ …­¿fx¨Ñ²ß´˜D–:!dì],'"!·+C7C žÛ•a†ùñÀjL]¯  p8S×+DŽÆÔj^¬Æ”ge8ý{z©xƒ¦˜ƒ$ôf½Ã"«Öö] /ÞÏC¼Ÿåï-‰³^c³2lÇg½RÜW†±w2:³÷3ôd½f2ôv g½ÆþJXël› Ièd½Z´$kæìïÒËÃlÊf»s¹ªYH9uPßÑ”Á~ä¨fa%]É@U#pT³~UJjYŒdÙö¨ÖìR ‘ý6`³ªY—ªnYoï||k¼5ƒM•AzŒ·vÛ´yÛ¬åÔNö]Š}£ŸÒ´ÁÑü¯æ÷4 Íï ñê8Š µì0É ’Ôc!¥yš¶iì‰Ô¬ñ¨wñÎÞ GÈ“¯¬&¼²©Èv‘!d>Èe»¡,š÷Ûæ² nê©¥z˜—M'VØ ­•%Ôæ{ÏEÚi)§ŽrÔÉgR·Gí—>N»¶arÊÆ-–/Í[„D£?r;ÌtFÚN¥)WécŽrZððÔ5Èè·åjÚ£¶õ’>Þ¹îú%Ú½ý¬+dÒ©ÓÒ85gr\Ç3ýmΚ†/øÊ¤ã]©*«jïùžW{…¯ýå:$kR²Ø?ËGd ø˜ŒêÉÇÆˆ7Ís–Õ#†^zWÎÙ°³‘â«×Ù$îyvC+w Ùdúð{WÒRlK?Ðèº;ùi¿ ”¤ÁIH.à:¢Å.»ÓB’k©ùFµþ6?X›M]×Ú­ÛŠl)¤Õ#(v±åsB’Ë|ÖT¬‡M>%'ÿ•ƒ¿=¶sÉÄJ›|Jnl}刔á®ßðŸgÓ¥mG:ë'`ì]Kã ïF49‚X¿!›lPÁ&Ÿ&·ÖËßvÂHrÁ)ñÀZ0pb \Iªÿþj¤v”¡J¼´‚ 9Mí‡U(¤­”Ö@ÈðZnS¦î¹³ŽÆ 4çm΋u…ó|žÄÄÕü¦œ •-¢åÛÛwþ‰ Ô•¨ž™n˜Ä–÷Ü¥?â+µ¶œ’lüê[îù€‘ËÑsEÝןüã,9sÂEˆèš:ÿôÙöFH ¿Ëƒ%‚Õ•·Õ‡ï™ZÅPÁrC7ñ£ø<ŸŽð·nÝ˳jËÖ!_ÎD¨9Ïï·(¾ù¶ö¾óªµÈ¾t•ßRSMØ™ÐÚL«”[VÖã2÷†gD¬:FÄšmùä‚/JÚôŒ˜«å¹RšoÛ^UªÔ.éÁ{·?û ´äeŽ¡±3ÐUêÿ;ÒŽåU>lš¸PýêwëTÖûf«æéÓ)´]ÈV}÷_w¢Íb•°›èËgT½HvWf[„é :åaƒ²Žü+Âf˜ßá6ðRïÔ*­+æù !¦#Üö*«L-A…D5kì*þ:§2Sã’Õk ¥L±±ïY‘Zò|j'¥öÿŽy•¦ ûp˼L_v–ï´%Ÿ7>ã+ºm6Ä›¤®zÃ!ÏoJ. ÷…ŽÿÞÌ‚‹½~±å¦gpc¦¤ Òg„t§8Ô˜üôäÈá!Ý`¡GZP„yðÞ=‰? ‘ñ 5<Ã;ÞÁaØX1º+ÞÕÚYÏðÎw™&Ø™\1º?Z‰A¿#ëçÛÔË×îߎÝU«·Aûó¶Õ_Í™ŽÈÛ$šøÞ6ðŽ A¶Kï8‘8‚l—Þqü„$^G¸¾9+Èvòd_’òd³Wd›ZÒ’M»k>ç<­ýJùŠ1Bj×H™ñŠòB&~’¬"Ïô$ X¬œ‡â_üóy#ïçåÉr˜ŸîZk¨Zªõ'©”#ÏééŠÌZ{¥Õh»DÏž›Æ Z G}ù&6d#Ml¼|ªåìNl¼| éNl¸úe›Ž„+m\71iKZcÁ‹üXs+©³V–§÷ú1²:,[D$€¢ë׿T¼02rîRe¦U”Ôî‡s¸KáyšÊØÀÈRŠØ h¾ÂsÓÏ1oߜͥ³ß݃»»‡£tö»{0±{ìéÙ=˜»{¼¢“{e"Qé¹]õ oà.ý_.%ßšq›[; ñбUò>ÖÈbÊ?‹ÖÅ'/UÅ¿ÒYêG„öŸrFÈÈiM»"ݘwø˜±·Ý ¾èÁ OWh{\¥5&­ yÝØ;Ÿ:v_ÿfP f}'rµo ;§ÕD;%‘qnÆ šTVM¾ò5™OMmW]±³Á j5Ѭ¬.oObÅy×»=æë<7`ÌÛöCá­#lj]™ûÙQŠ ñ˜·#\B“µ6½ˆÐŽf’eÞcdè¼KÆÆX’¥ÚjuÑ É¹'Tš4“·Ã“OéÌb@Ù—¥¾ ¾¢ÄñÆ6:€tûÖ Úcé¯Ý4{óº/ùgÛòiŸfy¬K‹áPs0È—CG88Þš¿Ë(¾KÇ,¶Vƒ:úÍøYö½Ã'jf±µÛz¥…¤Ô¯ì_·'(«å²RrxµŒÕwN9l5ÔÌbÿ15,e ǶÅKuºªàª8$–[±Ø·Ü…ËÓ ò¸ ¬u5\"—–·éw«„1-ƒôºUnû éq«Ùϲã½Ü*Ðý'ðf”ÎÕý7ÈÝŠ^iôG7ƒ|ˆ§GÑ?xzCÈžÞ yÇÞ²ò¤ÿNÁ¥ôOð†Ä7¼ ‘QÐ}GÈ‹ûÉôÐ2ˆ©GcI÷›«CТ)6¿¡ŸG¥#U€®Ò¾ìÛþÅÇŒ=NN—ޏ‚Dÿ']#åê½­Öq`I|ý<ž--B†Þ~ô´ˆ#HtÕÏ“qBÆ¿n²Sµ¼‡Ú.¢é²—ãàF¬$Ï5_Øwäñ<‡W´6 6Žy;Û»ä…þ˜5¤Ñúïâ‹Æ€ºë©B¡Â8|óϼ*)l|L'QQEíë#Vq‘§ÛBð@Iš)ª’¤Xmêýs$½$À®…j8PêW4[– :è$p6Ï]Õ7ÊôKÊ“p´-ø˜‘·h á nØRsd:J-Ä ®\yÒMVâˆÜhnH!Y;‚N‚ðÎ+¨´NI<#Ó2A…îT'M!AtsE’Ál¯ÝYmNƒåƒ¼Ÿ0ýA‚ÄŸHK‘g¬"Žð¾ö¡×ƒå 3ôº÷àé+±ØaaliàÊ ¥…ž«Az]‰ÅóÜÒëJ\5;<Íç+ñ»þÔ-Bz\‰é`½ ÒëJÌœwéé)Ø*Ç…y¯aƒŒQqU·?–¡¨Å"™ác&ö.!W¶–;wþyçÍ âÕÿû…+›ˆ×Úv›¨ýŽžÎÄ™‘àŠQ“àuÃHpŨIà°Ä.Ù°’Ç=tyÃÆ€H€<îØ´WMƒÔ/Éñ–î\ºïÖ|Ûl_Ç7ü»Ã4ýß_íQm·–æ;_›©FHÜø2 e>Õä#B†¨¥›ÝKÿA´³ 2ryV×Beu±Zð¿ÇÎŽ çô›&Ÿ²…±òਤ£œS_àf³%ᇩ‹Ô×^ä_š3š!ŸyHŠ79[æ¶ï1òe‘Ž+q&ëqMïüÃQ6—ÔÍKϺl,†¿ÐÕ@¿'(qu‹õcê¤ÛÏšfÆPGìh&K—ÕÒ2‡chäê…™›šOôÍš­Ï04v¡‡gXEßc~†Ú*c¡»êÔõ¶¯¿RAú ] tŸ¢ÏW uÔN ÕM¦M/'§»¶ëO_jä(7›PBÛrjš CÁZ¹)ëïáàg[$†&ªj^M.µ~ò!ÃÖˆ<¨¹¬ElPï±Nw =r½P)Û½¬}×[5Tú²}R@>×fÉÖv©»Ÿ€yÞþOUÅ›]ªsªlÝßÕgÇKy¶PýjC¶vÍRço %´Ì,S³¼ß´”r¢ø\¥Èó&Y˜‡D©8ÙϼgcÐÓ= ‘…Êçªê*sÖ•c;^¬Ãø€Š°£1¹Ë,Öj‘Û/x/y~ !~ó*¦Ì«Þô ©›¸‘ÈÃ%a†Ku‚MIÅ--tmxÉò>lëØ dx=†6É148Ï»1´LŽ¡íI® 5™80¤9$¹—df-\Qê Œ•â’MZÉóNqib“}ò¶ê)«ÝG`,Óð®Ë')x _g•±F—¦Åò»ˆ»¿Û+zyí wegßHø¸)•Èц‘ÄÙþÌ'¢Œ9>/^)*CAP%¡«X.+ŠR+ó¥’uš®8Þ:g^RŸFØ'«ÛO#·Ä‡?qrÕ‡³§3êØI¤ Tð¿[ { BvCß”2Øn+TÍU½ŸkÞõçY?#d)3X®r¬®nAU’Øqø7£ùÊëyàø˜OWÝáèæÙ*q¨™¾\ º×óv>jèZ‚­_½×¯9†FWTޱ¤ófËýÿJÈNd±9•lMÏXuÌQWÃg°¯”H!0ì‹ÞL\gÜΑ0º%ïu¶:ì¨ œ'™ùÙaÑ ã;7`ñÙÛóŒo?ûi‡J™£2€gà˜™ƒjf˜xfàŒéµ¯Iz;ÇË#É¥ÝZ”egy·4»þ±ÄŠ?Õ•Z¼Ü‡¯iC´ÜÛ©ø_ääJg“·ªM Xç®”ò¦¸‰3ëÒÙ5äÃÕ²ÀRè.!çÞoOËŒbdx=ë.í»üï—ÖPƒ¶G‚+"žÉ6~Ø#aäÕd›Ô8“m !/ì‘èa„‘jÂìŽÛú'Μ?ž99rèw¡I®§|$k6Å(ôÓ¬äÓ´UÂ(ú™À;ú•ëô­"¬¢] µHŒ8p¾Nö~Æ' ©ÒäXbébYQO>fh³ñÒȪ/gyÇ2Â9¦ñ½Ì6ÖdÇd†AÆŽ·™[R9îÞÙ ~£–å ŸøÒóÏÒV>ÏÔº©™˜¸¢OFk^ìùèƒgDÕÞ—¬$=½?àcF>Ê;]ƒŒ]kŠƒL=¯ëºðé”SòK¦Vùœb}Ì"PÞ’ ¦Nû*š1^Í]¸c¯2£Ržº"µH­'VÍ v@†Î\˼S<¡åj2$uœ ¥fD~0 h½ò¬¶FI,²*õ.³Š<š2IGÈÐÕ Qž”Í:b3|[&^cÚò ÀæÛyÿÁH™ŸjÉuQS$ü³¥u¦–Ý·ÿ=jWzïZÖñ¹2úï¡ÒGnÞœko÷£á{è4’4ñïGâëØAÿ ñ\<$8(Î D€§ñ\Ë9¡çdFÈ Î‰’€ŸΉw<—œ“!}œ“ak)ƒ¼àœÐƒs²#¤—s"þ#ýœËNISç„iΉ­Ê¤VuózÔÛ® ÏV’Ü“ bš¾þõ†Wô|üã ýèùÛ¦¡‡ˆk(( “§_!sÿ®lçUY¾R‚M†Ëó[Úÿ#@˜MLh?ýñØv;˜OZŸ´.J ¶ÛÝÕU:šÃ5“¿Ê^v”ä²üFù;J©Ê$5*a¾{­w’ñ¢Vo=7ßâ÷j§©‚k¦ˆñ’ǬïÄ67ÐÚd¾l@]šŒÔ·m·¬¯ñ5‰“?/LO8gÛšKöù"$õ¸Ä5ƨ۪ÚK¨h<\>Lï2ºJ‰…ïSöùìo„¼yû‘qàwï·F@[„óed%·‰ý¨'„Ôßü¿ÿê¾*í@þ×òSÀcy@>Lu/纘TËõóý®»ÚÕ¤.¦ß÷­ì÷å ËâãvB—”«8>n¡Û y¿,¯µÇ=<$XK§Qlœëk­;„Ä‹:C«Ðÿ%â†!C–Q¸Ý§|?'Ø+ˆA¦š†(—ï²Òžßîû'/ üð»þ5=—ºs_R'Õ6ÈÈb×H‚¾f„`÷’;JâÛ-‡Ü^±4òÌ!£K£ˆîäÒS9‰-*ü—K#¾&‰ñ…]ýŽxvËÇŽÜyvË?–í²Î–í$9µlŸe;ñí–ÿUm^rJöÙ:å ŒüIÍyä_˜9Z˜“Ç“$–²d°$Éó,1 ¶¶!ä¯yïdbµ€ ‰\N4>¯™K4}Ò!/ B®çé½1@FÒ{¾…A÷w÷ËÂEHM늈~åkµ!äaZW6x¿¦×„$Ò3Þ8V!˜•鬮 ¯–±-–ñ›>lX7hH¡4¨Ãî{ i]qò’¾ŽKë³Û”|Ä0Õ!IYãŒG)b‘*ù°~{ˆ!›8¨@à@È9Û êM„œ¨²ÈÖHÁ¯á÷(9J Dø–Ò“o^éÀsÞNÞ¨r§A&1ÿš÷Ók:âu'‰»v%κ¤â{+­ëN8”BÅdä@ý “êÜû>ãÇ)±*6NRšg܉¯SN|öw§¿|_ÏáÕÃxÒ뙞CãÔ$½ž ÛÊxµCȸ°-ßñÝã¶n”èõ\ض„c4½ž Ûºƒ,uëGrµ ¸ªä#¦P!Fß="l+»¡&üFQa[1ã7<ô×ëá·Œt/M¢„ é^šD9Ò½ 4‰³Òî¡Éº;¾û!aBºyÂA`yÂA˜ðÝãºnÓä$íû|¿ƒå8Ùß=Ov@ÑÅ O:—ÜÄkæ¯uï·<|ÁsÞâªE CÝz;Lµ¨pÀÎV‰Ï÷wQ­NYîm÷¬j¡ÇI®Ö:©Níb‘ŸXÕp¸FŽ8\Äs¬Ã.9J>‡Ë c®±š6ŒŒr¸Æ®âIV…žGsÖÍ ÜIÒËO“BÅ¥>âsÞƒR_÷×­¶> $½žH|*f«}Î4‰;©"ÁV’’s‡µüˆ!îK»Êr—ßßEGÛ—v•H_ÚÕ ¤]Ò“v5Hw(…ý0ýË¡ö„ô/‡Òw(u«MzC;|’ŽövÆy qm± ›³åº¸ÏÕØTÝn%ˆç'wcÍÐQ‡}ÅÐÙ§¦CH½oÿ§¾ä¢6=Ók˜Š½R3Ùÿó¾ÉåÙf`^“ô›³ËÓk.Ï—1„tÍÙ¥i†‘~ËÒlëwGÈ›gð ¥ÇT?ÊÈ–ly#äÝkÊ—÷ÖN1u½­Û¼"äÃõÍHò‡N¶{ΦüŸó‰dNlÇZ³²®m>xä/¨¹­Uâ!C#þí]•aèÕ:L;wØeúîßêÛ0<¢Æ}F¶e”/ÓÛÕ|yÖÕ\œ…0”Ø’¬é”¬ÑWVŠík€$tê%z4™É„lbP»ºï³ìU+Íh6“UâŒ}ø'+–CoÄf)öè›IúŒçM±™x–˜Ø¬Z„=b³A’X†ÕKŒ¤Ï?ˆ£0™o—0ÃjÚðŒÁðtÈ »ôE]Ëê^ìû…Ðúv @•ˆ¹æÈ¦žák¯–U¶–õêø ¼â̪ˆY3Ê£ GÈô—"·¥Éã€×F†#j<½ÚKÐFÛg·®IN\dE’B7·,/&±Ó·t;IˆI*€wwzr÷Ž}]~÷3Rí¥]â6¹úâ¦TV©õ7¿4¬^ÇWޝI¹ªv:ËUâìè4ý[ dë߈ïu>T.ßNŒT e¤ŠŸóŽ·d˾ç)Ïàšéy:4ª‰o2‡Ôo$»aióÑýš÷¨¹9Ÿ3Éääã„ɵK&׌ÉIížóùGíø·g´Š¸!vr¿D«ˆ™°“ûŒ3—¿_þ0a4jÆ &ä~Ò&Ùȃ<ÇHÿ9kÕÙ<,îîW$h¬¤ç*­—ò~ç9›áû¼_̘Cħ9VlÁs¦|¢|¯Å"æ—yCÛœú’¿¯o¹ |žóµ—näãHô/áx!üFÏ#ŽÒ§sŽ…#pïÔAÞõ¥Xèõ׬¾³fõpÕ$bVßY³z†Q³úi'fõ¾ûY}gÍê1òÀ¬¾³fõybVëÍ=ùì¾Ãot`VÏ­Yý„fõ5«çxäÌê;kVodVÏ­YýŒ¡fõ5«ÇzdVß³úàýÌê¹1«gôÀ¬¾³fõôÀ¬ž‹9â›Õ[èK|Ô¦IXî7p»ÿÉ`Í6±ãUnh„ß"›ñ$¿ÅÍ=ã·ŒZÞ$@ßÁXRÏS;·ïwÆ’ÆZ/<>[Ô7Pµ^ø|6稘Ãêf¤r6 S;¨çèìäb¢vÅžÃ(y‡ÅßãÚ*µÒYiÏÞÊç®,¿ï!‰­¶+7 •Sn¼-FÒÈÑfþî~Îô÷¸Ò‹ã Ç•#õ ±Éò´¨ä~¶eBÞí¼sžKò´¬9˜Ù×nô»Óψ/tÄwúñ…î(_¨vúÇ _ˆ¡þqRÄÝÅ ÈE$ÏØ<¹4ôtóèq9a¥ú¢½äq‰õ}4Lõ}À9íq¦û>8BÝ÷ÑÙ¾ø¡áˆêûè2Þä65øîG}\õ}€´±AGÛ÷Á2Þ÷mùir{­®QÖ Ÿž¤±çmæ^jüu½=¡?|=¾µŸŽJ4–óÒUY÷™r„Lœ³£<#*å¾î;ŠŽ[gIƒ$(vÐw_ùȪw9ÕI=ÁÔÒ( ¬Ÿû±Ý+„L±l„ñ噤ҦR<Ï:+L/Ù-ÊŠ<ëx7=B&Qä¾àk’_¤ªôò¹qãIÐ9M!R§D®3ìžg]ˆwŸ‡y‹¿»yúÇ»ßyòîVÛÑ OÞý[ dìÝÙË{#zöî]"o"ŸÜZ÷8éÑPI{HZ?âl:Í¢„½øq?“X !~?ÚáÝÝÜ<'—¬½[iÿ —¸s…×ëtÐÚd N³ÏKtï¶]òy=á#rÉózÎ$‰%˜‹É!“ó8Ú³É3ÁœÃ0mÜB¼ôLB·_%ªÄ‰D¨>Ž·|&Á—lS¼½Iñöøši4 &yûÍÅŽéçåbŸþI%Œmd*6¥‡qÎK¨èÈ·ÊyûæÓTLζi WŸ/ ËÆ¿»>©˜œ­.öª”ƒø˜>ãC¯Q:ÄâÆþ¤¡X¹a™íI°5Ri»Ü:Å\ÞÀvÇ IŒ8ᑞ$Òc§Ë9h´ß³NÆÔcyÞHøîrèi(¶öó©²f¼çYg,rt`×vyÍxž5 Ï:g¦£²»/6e-Ìø'Å>‘/«ö®”l‹F|(yó˜¶&™™|_ÚFÞ¡¬¢OÈÊQòÝï¼ îþð5oµÚý2·Y;/.; ‘Oßh 1Âïºâlªñ(™ˆ†Ö­Š4‰@y  WÚVªž' ,ŸY5PH˜çE­”øñ3õl’ñ"~Ô+¬/¥.Wñþ"¯'†§«sEP_ž*µËO᳦T#ÅU³šåë «ÞÛþÙ¦¹ ˈík-H³…‹:úmz…øº°Â‰Ê׊Uü¬IâCu:ABñk…Pâ(9^7¬ø»ï@©+®浚y««©r\,M=hc”—Ù4‹û7Á¸&7œž4ê·uÏÆé?#¶ïDUq±Ÿ¶*¯ "6Ðø—¿¤Öº.ðdï©(øüO'vRÔö²ï{zÁ|%Ú™ïÿlöI¯éýZïF¨"goJ:²lMÌóéڱϼ`¨üµ6«j C|æeÉ?m¶c¨â‘oH¸Tœ—ϸ·Ã€¡4¦u¸ônaMQKÓ%K[Þ‰££€„œ.¡@îì[Ç׌—Í Å›8ãΠl6*]B/äóŒ;Ã$Ó-Ÿð¥Ü¢I*Óò9!dôpÍßîC½ÇÃ])Ôà8ϳ VlÔÏ|Wž4ºb=ïÃkø|€§ëwÊ4Ñ«.­î†!›¥(Þ©SÎÿýcT[•¶-ÛٸϒxB¨FHœïã´½ÇOY!¤‘LëIUšD¢ø6ßßa­ üœºõO~ ¥ÖkU×Ù8îÖeà µ`ªŒTóš¡{> %+güF‡z”LuØßˆ^.'GÕi0!d´Ó`„–dz¹œhGJ¥bêÓ3‡Ë±ÉfH,ÐKÕ²î”ÎãHÕ²žƦFé%Ê<–ÉM Åz9í^È\9Š^º»'ƒw§ƒÌàjwºvºmu×LµAOªµºw÷9}ëaXS¯‘óØzØüý/ëaŒ<³Æw?°æõ°A¦Ñb-43ÒËãÌzXüoƒ_ó·‘Ó&ý6íÈhŸ3ÒÈ©·RMØfÔoäD ÿUø·Ïy½žðÑ$}b™rÜ2åBjGÉoºT»l]š6gÝ­Ô³}þûûEHìݬ?.î´ß<[ºe@È›UÛ~UJçFr§ú¦¯E0œwyGžC*Á}öž×Ü}KıÀrÈìqlû”û2W¾æS"¥º“¶ ‘¯4}Š=[úÚòûìÈ_ެ'ݾ`·™+«;IQD™©³£ NášÆ.¾†$fÞȧ#iÄ~Clòîîé[—›H7ätþÛJÛÌõ$`ÊdK,Ê^gl°¿Åf\ŽÍ6#$dÏ%o_Ce3HÕt͈¯IŽÐq¯[·ØyZHrã”ÕGw{uûV×îüæHs4Å:I#ÿ®kfIÂ49êo×DYÉ:Þy¾#d°,ÖšJ5â¬}Òµn@e«çeÑæŽéC}³A¥pdÍ™UCÆ<ÇV_“ø¾‹f×–VÆ/örÏ™„¦Ç>rÈ !S»Ç½Œ;«ŒmX&Í÷!o`òô*MÉæ³½³që! G)ÁvP?HÎÒK ”¦`_Ûl•dƒ !I »6u$Ìüütu¶-;ÄRw@:B2`•äÍñ<,÷ò=ïïYüD¾æ=ŽdøšÄîåwoçàÝŸˆl‘k¶¿ÁZÌŽüåÊ-_ô ç —<édòDº£àw2m8›OèT4Q±„ƒŸžüB¹…âß±4+€©ÿf,øL K:5÷ó v"z;æ~Jhø™ÞãZC:£4Î#ÏT Æ*é»jÆôNPš†1ÒÂréwJo§×tºU”ÞE;M¬S íÕîîî'î~̓洂©kNý)ÈF˜ÙÅËUÀ!‘– 0JÈÉOžeÑÉÏ7Ž2«x£uÄçf”ޏAúÆQzÍ«L/ÊܼÖ×T[9~š^Ãk–:§?¾ÄX®[Ùf™D{¥€MJ‘yR`³´(-V¸;‰G¬»Üë`…Hə奨Bf|M-¦*OéY1EæBºŸd“jºów¯·¾ÿZãrš¦(], ߯:~~7M)fÝ„n¯+Œ–*劭~ôQš¢½.—wª^\“Ã6Õøš!Uv™ÅÏ5¼æ©BÈÔ•Òm‰DÜ}eù Íèyó«Ó­ Y?ÕÄÛ5'vƒÄiCóµùÀ‡Ò\©gÿ÷±S4£$ŽsÝ:Z±uƒ|º‚wmš¼ †æ¯·mµ#qïÚ$ù ±Ö°|ù®dÙU\ þÒ±A`/{ÿNÄíOÀÌÄ Šþú§‰’ #îÆ« BH¥ªÊÌvÊ0f½üó%õU]ltH …d0å mÕ tÊx‚¡*¤O\Þ§ëÀWýwj du<ÕÆ‹¥JR„´¯—;UmκrÙ!dàî¶Ê±^yÛ§beZ„Ô¥¥¦Ã1Y@'ïn™íÏJ8„ž¹øx]’/庅‡ä¦‹¹…‡–˜üu®aHm3$ï¿|ATýÜ|Ùx,òkæŠã—ÃP4Èk¢7.*DOÄ~ Îp¹¡Wç>X±W1¨u@">¸­‚NŸ0zxx‡G©àôïÄe·¨œ›X¹yQT 8.*DÐýmU'Y`ÜFÏ;«:qaˆp¾m»œXD2á,ïðM/³»öTùK˜lè*?(%åÜwÞÏ%›·t ¾.•Ä;÷y“-¯¤ÄÀ„‘×5bÍ)rÈ[F‘ä¥Ð‘sÍÈ+tÄd¥À;£èN舱Âð(ºµ£¶pÅ·ÎÖ ,ŒbŸ˜6HtÞÑënÖ%V>Œ^ž²=“ŠÒKeOjÑË“ÃáG®ù¾WjÞí×a[+ܽ£:öŽõP-3UÐ?y–¤ÓЉ'¥iM™2­Â w:‰p5GÈkŽD‰QãŸóÐMÛT‰LµÁ?Nã oS,ub3<#ƒ©êm.}ÒÏ"ZŸð¿Cã‘6-–ósé׺œ3»wÄ¿¬ÊšÂLŽŸ7¦ï2k ;Bü<íÚe•‘z6M;„ <õ©Š9ãxƳUãéŽRàO¦Æs<#/ƳÕãis˱Óu "!ˆ„,ªcq€"ËTw\•Êì¨Ò>ãkFßï¨Õ靖ñ}ÆÎx¹n/˜åZKm^=†L—Öü$m‘jøÞ㛪¨øÞ­4cèX–](È/Üæêc¼zï°Æä~ﰹИÜîm3bdpÉŸDnaìoMcÈ ´æfgÁ™]úÝ8k²Ë6D|vœ ¶á•àŒT9EÈ Á™ö$8ºæfˆ9°œgB‡mø-8S9‚3¡Ã6¼œAp&t؆߂3ÒìižòJp¦Á‚3¡57;±Ú“4Ì1ò?^i˜,Ï1ôᕆ}òú¼’†aHæ€~i˜±ÅÐÐW¬Ä`п•!‹ÿV„Jüò(B)í(·“-ö)¤²ðÂ;(AÄo¯+*UŠPö£ßtñ¡Bbüö’=’þ_÷»V¹5|Ý8쪾DŠ‘OO°,<8Ìy‰™RUY„X¶ƒñõ¼s¡ºCN¼”¦;†Ð!'^ø}&¶Â×ó ׸¢"Êaˆ(‡®œ"¾ÔÎOD9ÄH.‘s‘ÿßÒ_ˆHÿn‹ˆôwñï=ÅHyVFbЄâÐî®í-`ó¼3Œã8áÛQj¾r•®! ô䔑ø:!!ônVZZR|ÍÀ¥½FR`äC>ÍVèÐÞ¾Ši Ï2 GÉ÷w»Ÿ6Ye2­m»¡C{ûGiØÚ|GÈka˜f‡N‡ñ¡¢–ìÈËÿÌë½£ãCŠòàO×tC׈íÜ¥/åäl«ã;ºíÒŸGûÅE¾ã¾Ú GÛ{cÄFq:êߦ£¸M´œx'—Yi¦£ôEF­MzZÞ^­MÊÆd`MvÌȬfíÑ„ò;÷‡!dàýŠ9Ÿ2ô~Åu…¯IµÊ¿¿¸wìû´Õ׈íW"!žŸ×„§åh‘®—ùmªbJ¢¹8¨”ü„|Úâé!ó24I;°t¨v„ \»ºC¦€îå¼m#FêZ¼êO ËI Ç¥[*¾ $AHõ6%R¶ó!£o~„Üa?ž(¼kGM*:aäó{äÇ™©‘á½Ô.À'V0.ÎÆ%‡kÚÂÔ!‚dšÎÄ5§zHì5íªøßïáÖ¬F¾—½d´ÂÈÀ£­ë$ÔÉOìw#@ uâ2h.êv†øüÑ¥–¶ÛâJ¶ËU‹ëè|ů]¼4”él_ƬH ¦%?ï3{(3tqYð)ÖáHu¤+jÈÕ¹ [ZïBÚrp¦VñðY)¾91›¦!C[f-³§¹“Ùµ½Û’R—›TJ¦k‡M~¢ª¬î5ÇRŒý‚¯_–›f:Óµbé¶ÿ@§N]rÎ˾æû»0%s²K«9¼#} r‹¥L_¤²­<åø¢ÆnIŽh®Z´dR$iù”nÍé-i»¥ô@™Ì™˜-Ë(ÆþÃ×ü?–ö>~î”·¹ME’Çß•P…NÓÇ]3p’08#‘ÇÓó-±fÚÝ39ñ—>ºÒ¨fIÞæå> pâò‚ö# \ë\Z5óŒ‘ÏkqY)w2Á³ß”Û´, <;9;äXž¬È‘‡ÿK¹ˆìÀb<"”cRLf#Šùù4t¯GŒtÔ—Ýu™³]—N!þÏ(fù\&Ù†‘z§ùç×õ8HUx2]í 4IÓ„` 2¾n^éœ0üï¯k©Ë*“5„|_'Õ¥‡…¹tïÓ2r;Câ{<>#×Û’sî"Ýæ»8ÅSÓǵì»8EëÊù6ß7Å)Éf8]3„¤zžeÚL]É; h&ÏïF.ÍÄß±ò{ÒóçœÊuc¹üâ>û¾^ |ó*eQ² –WIž›¢¤F@¬—8"Ì)•ñMÞÍ ·GžÏ»öf±.Á yúI ÓN›v‚™ü ¾ü¸€Ñ*‹æ+¬KÏПá¿%SäóB¶²jl%yoë Õ­/pÍèÆpTµ¾ÌéiˆLsPòŒo]¡lC$yÆžw$9ºòA¬ìz¦AÙºêAÉàìñ¼.[×@=€Hèùö3o%ƒ2ÅÄ¡Û\Ç‹°~úI4:^´'´àñ—"Ä s–;·µsÔƒ žçoS{4êo³ÜöÖ•8£Ë¥¼4n’ày’: ñ¬ÙŠfËù÷œòéE~ ¥HsÎa.j^”yÍ# YWK9eY‚HT«R’EâšÕÒˆ ±CÈÐÍ>›¼À\e¥”%äIœH 0­v©4Ç‘En„Œ\ÉÎã|˜ŒyZ.~¢øÊR¼_µØ-eÂ)í78ñ¶±\Ç‹¹žI2ÿ+¹xYV"äÛ)a™•–5 [ê„Áj8åÿ)oRá’‹r^ÍMÃKü÷ºÜöŸ*\§ÕáMÄöiKì)>¾"K#ë’‰=g™Ë‚Ÿ®œ r§Iò|™»'¶±|û#_TªvDÕ±œT{™t͈¡—Í~2Ûb3MÄu;7u®s È}CQ«S@nW<ÛN‚ÛðÚYñ‚è›N¢óÚ¼ë:šïv–Æèœ¦bu-Ë(cõ&ì³Ç§sZ^êFÖÛ³¬céPTdK¿Þ‘é [@Üħ¬üo#ZÚΛ8ÓI¾‘Ë*“odä å“ ô0¶¹ìßñŸWÞçò¤–r5,ùòØ´ÏÉjç]ì´í^!wüìGÛ®î­Ö]³´âåVu ÿ`èÃi1NJm¿Ž%e<[1Ô*+¹å›°òrh‡6;½úÀZÊç¦ye"fܦºí0/{ºÔ+³R½ÇÓc¤R¤f>“*E‰ä]ahd»‘M6A>ÖRö}Wna´ô’VàùȎǶÍ0ôå@ÕìSÒKuÊñn1Ôñ¶)y•'¨ÖyÀ³ÿÇÑ6tmÚvmY/žO7‹gt1†´Íâ—3†Bÿ™DQZir .MòY‹Ó ®þW­s˜)¥ÝÜ5[‚¡¡Ý&4!Uš8ßx“° C¡áU,“µîà·d—Ânç{y µOÈc}2§3KžH*LEùe݃ì›?§Uåul?F Â°Ô>³»6 }[¨\”j‘€NRü¿X-&2¥'¡ü¶×² ÓÌ|¯J*Ì@K#¦A‡‰]AŸ‡fµ‘ÝP‰mßø ¸"Ë¥ù¶Ö„õåPáùª¥ÂvÉðè@“•õ,iñ2X}§¬0^vÒ¨ïºj=­Á‘“ÚÉõ2(vÕdÞKvš¯Aü L¶o +NõhaÎuÞñ…Ñ--N7 m"dü£äƒ”]—Ôó¼m^ÞBmñŸº5±KTM³ÏPe¬þ§ÅBs{æb±;ËŒçkø< © (Õw%U1ï ” TÅâÅŠÇRl1æIÍéöiXŠ¡á!i’KJ§’s)Ódë9-ðÔ‰‚þùcjòÍns²Ð²hzÎN}‡›bµ/yÞƒK!qDÁˆËHHcLÖÌùDùBã•—Wy™n#ŒRp2Í*æk]Féÿvc‡<¹ØW?ÝÞt #YSƒ¦Üé:&-þ÷ÐJïêw)¿¾¬.?¬œð5É…Kw5¡ÆIºNêÈ{[ÌÌdj Èñ„ßrº!Q º¸F\$$#.•½pŒ¸HèØIÈ™¬Ú6‘ZùŽY ÷éÚIüþk-´Œ3›`t•²£ã“ç™éè¨×f\‹bº0rÚ6u‹ºÉ®É¶ÍYžûÒ‰9 >/%þwâj‡Q]?‰µ´ÃOÙÀ'+ŽiÞ’qIU(ƒŒo³:ª eW<¯ð5M…âÈ¿êónÂË}ÞFüDo|6Õ§XñÍRüs8Õ2WRZŽOë0,¸ú°PŸ¨;ÝÛ½Ø CŸö ››Ó¾ìCm8oóCõ9òÏVCÅÖqËÚ,«9††°á( ‡|®véº’ŠØ÷ôXÄKô>Æ·” Kÿ$a|Û'ãdaC½oE<_Ù•ù,øçÈaèXÙ|møò›ÍÉhÍÀHø¾±ç]0#áÛß톫ÄëÕ]MÊz6pâ·Þ˜´õEÈKë]Zo4‡±A^›)jë!ýÞÎS…ïóÊzƒë Œ¼´Þ Úz#o¬7&Œôx;+ë †Xl 8|žÚféaŸµ”gk3es|_›º8!Ÿ^!ç‰n\µ•ç=|–F}U¹®¹­{¸4êCÕÐè²ÒþSÑv:b"³ÔÎ5â7µˆçW—ý«×F_‰•~‘舑{|ÎÍ9³Jöyç!Cw¶lÞJ \¤=¹eGí¸šy:—%Ûñ¹·Ò¤DædŸÒfÞ?»G<­Ò#óÜ÷ûáˆkαM”ÈÚ&¦UCÙ?ûûX@“ãÕŒ÷sßtÓ²à‘ÿñ¥×ŠÖZr—^SþR !Ÿ× (¬l˜½ftÓ€":íçݘ˥ÖNÐø®ÜÆF`‘¤¯Ü¶TÎÒß•Û$lGÈðš%*[èì5_·©Å ʉÃM¾n€†t%qE“µ·– ÅèÈËIšVÍ©E“U“¥ú’T< ÛÙ`5ëp{Á,Å JŽÃ­ ”t€LÄítj2°3Hâ³’§v¾M“¥˜Kk¶0ð2!ÑãF1WV©† ¾óÉsr§i“ÁaÏIt ’BáÓ ^z¢Jn2´Ì’èF°B©oÄMVÌ)e‚ Š§bÎOÀf%Ñ—wQ~ÕW¹ü–äp«Ÿ¨ÐYqDd}j‹§Ñ7‘À(:*E².=äªI^ŽKÝ€ñùLŸ‚mùD÷©ƲZ§ž%GH\8Ñ䢙má8º$¨ÕFŽX¾#â/ JME»2D7”ƒDQàÝRjK9 QŒ\÷¬N£øâøºî +H¢*F#õŪ.¦ÎÎ¥×Y1Â5ynZ@#¿Ò×$Öf·íèí-Ž0¥b G/—óû-)žKß\„|zÕm!>~øuÆÄ{o÷#ŸN{k­úDªaì*ºM=Œ¼eò^p]:?o¸Š®G‰ïÔ¤Š„qà_“÷©#:!¤wMæ¶Äìpi/8é‰å&Ë¥½Ô¤µí$=o“4i‰ÃQÅš´ô¤IKâðoíðDä/í°*ÆäÆ÷[ªÙûŒ¼Mls‰B™Õaž*'\Õó/ Ç´[ìǪÆdàK:­±ß}š"¯Gûݧ)òz$õzäyãõxB†—ŽÈ • ¯Ç“ƒ#rB%MñììÕ 'TbiŠ''TV 'TrESÔ»ŒlÞ<¬u~š¢öèš"yÝøT#š"ù Mqò qhŠžë˜ó¯çßv.†¾9/NPÚù™¨V[µm“.¥ð¬³rhÀxÞá¸Ï±± B¯) ‹,=Ú*òi§ŸVïñFþb?pÔ?ÑÿÎyÎþû[òdT ”Wâzéá4ÇH×…¼Þ7:áRΖÔw¥=²9±â˙󪮙æ®ò¹Xìf„ ½­n ¬`.QðKýƒ:êäý¸WÿÊqüù<_ oTt¤º™ýŽÞ'ÆT"ŒÛÏûœ>ÈÌW,g²X½Á3•¼ClŸªDlÊbnWhït½× w^µªœIYÿ±O„Ý+UD'Y>%UrÑ~·0¥tTµ ¾Ob‹ÿ¥™u˲2íˆÁïµ_IšÊ¥¬¶Ö&ö-å–`½×Û!ñLÆvhoØfÛ;­÷ÚIO°ši;tÏ7"w•Fa˜-ýÆó#J“Ë•¶6ߦ¸QŒt“€•N‰Y—M_6)B~:ºŸÑ*Ñh©¹Ä±2újÚ\ÙyãùºiÚ”ÝÏ #ýMÚ ¤¢Þv/>Ô Ín8³jëg[B{¿cE- ÅeÊjÞR§5Í:P4‡†&âSÂ׌.Û¹«Ê± 1Èøšˆ%›´wŒô6i»]—^ç¹3DR >¥>—(øò³.û¤ºh¢ KÚaCZ ³¾,2ðZ‚uÇŽýüø-Á:Îà¦ýüÜY‚V·*²FJK°#ý–`Pâ5È CyBYj뉹æLg ñºdb‚ÌòyG!æ ²[ùünÁ=ï)\ÓYçÿ§Öd£:(φ#ç%ƒñ QÉ<R´D.<›{ŠO©¥?ô5צÀÈàЭ:]3¯¶bGÈûXkŠQB·®î‰]ƒ$Ý KÜ×Zl²é=îÿ꓾޹¤#C’°!ãi‹—Ú‘¡mOÈ×QM€d®t¸8 á#-ZS^ ÙHñ5M;œY´G5·ÉÒõŽôá4-R6Ê‚®ë„ÿÿá°²c›“,¹¶ê4X©MVŽi³vÍ4±ötU—V,{U šjJÅ Ö§«k—™sŠÖ®c~¬ÈÖZS)ar†Æ‡’¥‚*¤„6ÃÒ%xNév8ÌW\‹6›éÞ3†¾/‹üêLÅa¾ˆFG1GDÿòLuB>/ÛÄõšbÜ2p_·‰Ù— ëœ !Ãëf73ýD7Í•lF`ùÄF˜ú;Q…,gÕ‹¿J^¨8F9F^(KJRßÜ®¹ñ©Ý©]ÓMf‘àš/œÁQÛ·i0-æy*sä’5žM½7¥b\7ö±sä…”4¿t ?_3üÞ™˜Þ™ ¯mä{gbzgª&üï®X·líP è|]Å·tº¦?¾LF|ÍËøÒìaB¾½§Y ÂE?ï S7ƒ¹”V”Áa5/ù‡A'úq„‘N-IkD¿÷4’Öˆ?÷- 'c—6çÉèñ¸§9×|ÜÓÆìÈ?·´1nwúÇÃÙM.R¯¡9Ò ì㢳y~TÙ@&f ‡™üÀŽ p²acRÖùIÌ:c™ØŠ¿Øœ(þ÷ÐjŠ«7šÅû¼ÑŒ"äÿ »’eWq%øKÇ Â^¾}ŸˆîOÀf`d÷ëŸÆ’JFÜ•7€‘JU•™¹%@*+[«?¿ÊýU3„$®ï"æåI?-­\G9ªõIíJ±®o©£ ŒÌÀÎ;qŠß*X=_´#-¶ Hääâûƒÿ«ÛT_äs§bν¶úc‘ù—©¦3’UpxógF²jçÓ®ýì+ì—â„L+©Só€qõØn»Ÿ(¨J—}f™X­À|t‘µ‡Ò»û5œu¦6ö|ïëÞ΃%äAûÉG:Á°ùëÒ劇ô1­µÎdC–I“–jÌ~·‹únÂÿ½ˆéáÒ’ãÿ~…SbÙ@*¢°×*¢yC--je¨Äg*æ§·.]!j´=-v¹¡Ó}‹}pûK˜ÙÖ«]+Fª»Ã ½dË;Óö4ÉÅΜþˆïIRS¦yT"AŒ$ߦž­Ž-| •Šø4UïûÐ1Ë>½æÎ>§ïsgíi­$V[²û».29úï|‘ÿák¦~“«¾á} wXoœÏ´RéNh¤Ý½Yl]’ø>wöŒÜ™­½î/ÛãoäÛ}}ôq”†j¸A@6W¯fè4=÷eã¶.i×ïXYDaݼ(ÅÏy‹;RÀz“$‡õõĤ[xW[dú…´âD<£44öH)Óû¼)B†c¤GóI>´=Bc¤v$1FŸûðb!#côé  d|ŒVØ9“ô|ŒfŠï~µùêœûØZ6í¶ìòqL¡N­š$Ù©àÑ9’d§‚G”º9Ÿ Aó¢A Q-xÄñsFè\ó )ZÁ#ŽQÁ£i\ð5˜Î³íÁsÞ"Æê’À㞟Г•;¼yrêÇç|ˆO ?Ö3‡ç,þ¢g>`dDàÌo®5È4Ra÷šA‰çíx þ-Æ=BÆÔ¿ßN™Ÿ8oÇ#õï×NÝœ÷b%»£‡:Ç8ìÏÚ­Ÿ×€PiççgªÊ^ÌÏÿ££VÔ¥W³Žâ»ͺYÉlUÁsF[Q˽ÇÏy;Ê1ö:Ç×¼¡¾#_Õ§„æÑ?öNH©Ÿ_ýEHÙú|Ú7q¾–;˜ˆÀÊvŸÁÌ µ ÿõ"åq®Êr'ˆjÓŸˆP tÇ*ëuðÝs$h–[k¹Î=þG¢0pë$ƒ„2 ‹o¤”ß~ˆCÒ€ŸóŠZ{MÕ~­ÏOµãÿ~;I\úimWŒ4ŠÍÚÔÖ›ŒßëûàÛÅæ?áDV.šø.b ½8Ó²ãhŠ­Ád3¬¶«Þ}ðÙ±áØºOcðªŒ7Ù¿þ»W½—ÝøyPc">ÑF™åÈgöE<ìgÚ0´8Ès‰}fòzHz‰å¹è¬H7ðÝ{®ª‡òÎO7ªçBJÎgƒ¤çBJ«÷œ ªèž;â¤c#¼à=yqÓQma‡óï¿8÷ÊñØÝ=ú…2$óKR‚ó}PRY6>ˆ}Þ­%°Û„™&6M%í]FÌó ûk˜“Ÿ!žé‘ð„DÕ'q«ãûýæÜÝïø5;˜é £Ig·>yݸj·±ƒý5Kè¹3È4â)D¹‹°Î;™’!™ò¨“ŽŽb›_¶~N|Ç΃ó¹ót%Ùåü|îr‘Ùåô|¾»'ÃݸÎõcýWg„ôe?­T£8KÏÜ;Kgo½?8Kƒë”A’ã³tóÚÁ£É ‹ØYší ~ÎOW˜ÉÙÅíɡӜêXå6KΜæ&×1M<ÊdбÂTÇŠËwx¨¸cE¿%s„Ì¢näîT‘¥çnäc€Œ»‘°Úø4Ì#7r¹d¸/2t¾eà£E²ì´£êÉܬˎª£Ô¾ù}vc”GÖ:åùš\díQ&m„EÓ¯=Wóà*ؾ¥&-6†¨.¾÷vÊ#ãµîÆdW5²ZÛ…P#ñ)“j7n Û‡ ?JÙ@2ù«œJµ-Dg™Þû$^Üô‹r»Rzgá%þG×ãúy9 “[—ˆ×ôs” ÍŠx/p‹2¡Yëv1•Ç^ŒL£»!H¯“ì@Ëf;$‡ˆº$»E‰ºÊ(´‡Ódvûê·}‘ýZ}¶îîÓÿ1ä>±i¿oÜŠI$öW JÈg؈ëóŸ—ÒRéX!$dW•ì§&÷½V±–m ?g~ÔõÆo9É/§vηœøtE¼ÇÑYå a­Ë“c•ƒî2žƒ!’'‘ôÇä !ªÌ“³ô<ߡȜ'g9è¶ï(þG±4ë;È äI$­{©7—’óô<áÿÏAOÁû<ÊA3ƒv…õM es¹z—ÕV¯šÌz@¾¤(B&V^Z÷ß«]®“DöTIHîKéû»Üg.—Eìð°ÚåNàß__^zåëÞ½^5¬ÊyêU²|¤ôÕy[ç¾O ú«»@®aî9³óî‚)@Fº d}ßÝ=‹UZµ?Öb«(·PùcMN`ƒøÜÂÀ‚Fœ¥öm„Ž™ü¤;pËä¾xrÂNQÎÀ€,NÙ)+Ÿ02ñý“k`d1¾ÑfFÈ4Òµ,«Ìð–®'Bþ}½»ìU#‘‹ÿþPÜ@Þ¢ÜÎ÷€!ä÷€ ƒæ`ä÷€ ÷¡—ÜŒÌ"<+ÙYnÇÝ÷R=èf{€,ñy€ÿûW#ûT ÷i~5°2LL—sIÝ\^S.ÉDÊärRµ/¥õÐŒYl÷è?0?ÉÙîQŠNH$Á|ÅÚÆ¿šAÄ]6$^?Ï÷ªìí3$‰Ç¿TŠ«À¬#i¤2'Ïú¨2G²HeÎ ]eŽd‘ÊœD¢ÊùëÈ¿­!n.å1Yßtgò•“0Y`ù½‹Øß}qÐÈY¶ÐÞó¡Zݬ EýšV—}$’ýsÀ×tâ뵕uÛ÷é¹=Øk)°¥JVS-±P¶÷$G 2?ìçY9Lø9ÉQ–¥¤Ó4Sޑŗƒrês9¹þ…âžóv’7ò…˜I7%“;[-Œ—“~qÉöïúfâQs>›Äì`%œ'<ŸN-~SÁ§j“às-g„/U}îé,ÿsYÙ´"dê#)µLQ&³ßýÀ‰.ÏQœÑÊ×€¹ß”i¥ šrëúrÀHâºÈZÕo¦V寧šÝJdáö8©H Ïgì;†Wïi­œ–'}m¯eÄoÉ8JFÙ$¤¾Íy~/ö8¤p1à?üÏš Òé¤þÔ¯ÓÈ[ü ´{˜²vÏ-O)œR{‚jH1éÛÁ|ŠVe­Ï¨­e¦r=äƒ<¶¦Ò\¬+ª³<й5/Sƒ¯y¬0ù¦>¤È"òaù¬ë¡rÏ™Ÿ1©ùîŸG¼øuÂÈ/~æ™zv+ù0ŠŸ3ó:a‰ò:{Íëö‰ò:ÙˆyÄãubÍ Ù+¢4+`.1æšXíäyjEqÊvÂÚ¤¸F8ÂÌp„!cè1@1GØØzoéá3ËÆwÏ<—ÒFïð*—³²ß*‹¼…Lÿ¶îßb=¿»tCB-ˆµˆs uIª+ƒ©`²ü5Õ3¾fæÄ¶ìùP\ó!vãç² d~ÈŸbÛƒÒ_“|s4$ç¥ïàOdqc’Ä ÉŸÂÈkDܸôb«ëÏ çº¯©‹/®?Xd­V"kj‡oVþ¢|´»ÇõÆ,Pël—•`B®—¯HDÉ5ªH¤ùÔ ˜×K(Ö V(m+–Ûðš™?Cëž,b¦Ýñ5ó€a§ö™¶éÅÕ-#Ì ‰§a:LUWõÜÓàšôuHÑ8]q§®–Ó†aä!µëcÚÛ¶ÈÛ÷Z§f²t_âøÍÿÄt¶œÀñ¨¿_MÈø8sMcÇéøêg¡7<Έc,:Μz>Î\Ï7¤Åµ•\OÜd»†kæwÔßÃv çufÑv "£íÔõ$^óH“ЇbW4ƒ3(Yß²HyÄxÜŽ)¹eay¤¶Vñ=“8$n¢2Áeìç%½ê]º4àÍSù1pƒë¥œ7?]jQûß8š$“4H)dD@J¥Uá}F •;…äsñ4”‰g•ú†t‹Èÿ‰»‹ýˆA²´ˆûJ) ñö9F&1IÁ­„1º\bep:Oû}2xq¹DÊàrŒd|é2=Þ7e|Æw?(ƒLœbd„â‘õÇhwwO<É´G½$‚IUX‹<<¡èsÇ{ÚØýÕ $VÖ‡ñÅuý½ß^™ùKsV¶wj}ï‹Kvà/Ý™Âe)cÀ!q3 Û¡Ühf¡¿tkŒb敾—(yà/Mþ™_¯ÊQ‘¼”-òbïôÞ|QÇ')¤Ž_øŽ’H_‰¢zêø…OÖ;Ðuf•%Ö—âd›J¾»¯£ˆÑTiæU÷pÍëYiFJÇ¥ô æ^x„±ð\ÌŸoÜsÞ¢çb…„sqq¹Å…®´Þ‚Ùq«×¾Ož3ù9¡F¨§½¦£–T¨éÑ#*TáS¡9.ålFص=*ÔDŽ”³ÁÈäH¤¦—"5n?J<ñÁ@¤fR"5lAÈìH¸×NÔöÍ'Ù‰˜ŒÒáëð¼¿wC¹wÀ\Jò£&eSŽ,ef¿£ä¬U@J^Ú„]‘Q·WµkS7F׳栉»ø3ùõsi÷eX^5¬6)Åî:Jÿ,ã(E‡ ¶ñH) ˜ ÏÚ÷½ÓÎíï)%T¯Úr¨æà‘ht±×t$4Å×tµµæ¯áü£ë¡£»vÅÈÛ±äÐ^QhŒ²o>JPÝÝ›øU½ËY“-yŠÝ™Ûc“Û7ñ³ŒfY ¶Jnñvé›\RŒŒÅÒ7ß=;e•y{Ú.<¢Í¬ôgr¨G´‘Îê´m}gNßDô©·2Év§G ²“û‹­{ó.M¾Î»¶ýWŠÜÊ]É"Ó3‘[Î*ù Áaokº·m#*Ò,¾wQÁÚæ+Û1JÉ_ŠÆîš'åJ4ؽùâ$ k'çÞ[ø†à9>y¤'Âeøä‘^¿ò1ŽÒKBˆ]¿ÓÑ`]’³È/²A µÊa4³\Za(Yòð…¡Šì†’H_ªð)HJ_Ó C… C©kzÂPEv9†*Çu@Ȩ0ÔÔ¿ð?:†êñsžCÈa(UBò„¡Šìr* U¯-FžC­<¤a¨!€žC1üJ„¡žZªÏz" 5†ê^áߊ CUe CÑÕ‘0Ô»™>¼e e¡·E€Bn¹È’ðÛ3Ò"ÒƒhH¾G–v¾jLe‡…g9øš©ï‘e¥üû¦è+”Gø8 ôüÚ 2?$Œí2nL/Òÿ›~‚TDj Òô?gDž¨¤ÐË òvÜ<©<¶á9Ó“æIå±Í29v¹î=—ë"ËÎ]®{È$dYTü]:È Oˆ²/×ðÄaU;ÿÌŸ•TC5þËv~|Íãv~YÏ“[¡ò“³’¢ÅÀ5I´ÉsVUÑÞRmòœÅ¡êÕ¸»Ñ&ÏY„­;ý¹9©ªh‘‘œØD]cGõ}’r·ÄÎi(ÿ™L‚žós©ÒH!Óo¹]ö©ÞñÝ3·ÓW®!®-+iãŒC 2w­ª8ÖÊkÊâ˜xLŒ$‘”i§Ë‚µNi²)çݽù/jº°ó° ò=ýM.z¸EóB½´M„öÚ"ÿ–N6™md=_`óÈ.þ÷n¯Ù/Ö_¼ˆ“]D¬."' æG‚2­Ê³1ÖIo™·E&Ï]¼5Ä#2„2šìkˆOd0јγÉÚÇGLÓÍæîr_¦ÓDNZ.O¼LqBoï !¡ÑÑÌd•=ëKÖ®o˜u¹/íñ‰]/[‰A0ïy2²Ö©êûj.ñ}~<$?!sp ‡}ó#éûíî2HžG“ rjilª"¼·øy,ìï^€ÐÖCmÚ­¼¦LÔ—CpÍ«Wy©õÎU‹¥nìövÁÏyó[jêÖ8Fös[U3FšhÌõËÏãÞm»»ãBîËtj·3Ý+Ó=ûwÙ¬yWu^,÷Æô¸>{Y@ft  iDâú^>ƒ½¸Ndeï¬úaù85üþzâ—z–Ô»j •W­x×µ/º@)Ï|×jÍ=ЯUu~•_¯õR¸úO[kÐ'ï>í}غàeéÁâÊ޹щ\Ÿó¸?ƒ¿u³ñh©G=S÷¥,Åb¾ãÙÿsÔ{Ƥv·K¹èÅEŽÒß]Î+™'ù ÆŸš€·R¥NWâºL–¨˜ºøo%Ž~F̽ˆ²ú¥å倡ÆY~Ô•ŽòäѶßÖ®\ƒ:wF µ=‰>Ä6&Vó%¸*¨Kj„Nͬ‘·œñ`´’:(ªÊø¡‹ — ÏzµPÝ»¢X; Ã}  †Höküùä{­«±Ü—©ŸñËJŒ˜÷z±anðUSðA»ÕCLmRâaF Õ>ÈÿÉ÷Jk¼S‘³i –Àô¸oª¤3ôQùißÔc’k‘ŸöM)c„ŒõMõNËÍ #b`@Ñ*òÃ%Q0Ãw]œK€¼g‘“(ÀÈôÐWY"ùõÌWÙ³D**Q4:xK·QEŽë29’±ëÅXz‡aßÍF Œþä¯ÒÊ™¤Žuut×|ÖÓ6®5BÏ:Ôh^xt*L–‘ÑÒ‚ެ$9ë¸qÌ%rfÑH‘‚!}“åâ¨rU5ÛÆ¢bâ-qü,¢ªX|™… ²FT¬wv¯÷;FBæQïPò‹—»ù{õêVÄ—âü5§õNçVÄiýóùI¼Š¡Š:*Ó öžæñ=Î]Ã2÷c Ýç#÷Ç·8_Q|MD!) fÈg[ƶަÉdg¢£±íïƒç¼"¤jôù,•€ñäÔŽdîrÓ9ôym¥ñߌ¯é"=•t³K7¶¡™ñŸ¿¸VsÃd›+ç­åâ,Š¡.’y˜÷$ c·Ü—º¬04uPGÈM„‰•qyôUð@eZI ¾¨rn.¡JP$㟳Þí\îÜ]-Ø5w¥:­ zÎË« ^«‰dþÈ÷ªyb2>úLý£Ü¶àªW+ñôxTN‘¿ù,–\úõ¬7<*ªùg’ŠS‹øh)1TG2´Ùj«õ¹éò~6|éZü*’ÑÔíÆ||]µ¾ërãbõÁÐäàX8—+&ºà7¤þæ¬öfé³»³eaá—šyÐÖLìò¹ŠOà>k»d¾ì^î»tЇ5%ä}sGöñj£Õ0ÕéV Í«a}>v) 4ƒL]WqCMbñ¹ïSûÙßBfþ™\E§Ê«Ÿ Äò$G§÷»jùWÊ÷÷çñ[3CH6Ö¦%˜–¬Ó†¯YX¤ìС™äß"Ô©·!¯P·+’'»w=oßFjÑ2YÍxصïsgõý½Õ=FêVúo>ÎìyÈ„œóq\阸³¡Úô`Ã''NR»ò3‚»Ÿ%xÄÆê”9Mðìe¿ãk¦ß­Êªùú1Ñàšn3Ѭ>“à;^9c$L×ÌþQ†Ùb“Äw'ßMÍ:¥ê´¨ 'xT;¤JðL M%äÑ9btj¤âåÿ »¶¥GUnûJ‰…Ëu¿WÕúÁ¨Q11AZýô&LvõwÑ£Ôx€ycŒø:é/;V*¾—3{ÙW™þ0nCy…ì¿à_VäwYŸWØå.2"±==f„L-{EiÚ©äñ3°axCÉ*w¸HjwxèEä)RÁeÞ=CÈÃ4úÿhãûC+¢½3vŸwŒÌ½\D\ªÊE†afY¸%@Ýô™ï÷ù.ž‘ùEŽG'v9`Òå`ÿ6û†/ù@Ê;ÿ­_™Fîü§¶w¾¸xl ãùÔÍü½NSõ®òæ {¸ó«¼ó°Ý‡ ôßQŒ8†pe1¢aà·¥‘z ;ßµšá<°YäB3þEÖZûX–ä—´ì]»ëˆélŸFÇr™>}»Þï_çUoŸÇ”xk$ÏgùðN½ºOþ¨/4M߬ո€°¬°º‹áy"[YtèÎòZœÉ!»¾‹¨°dí†_±ÒÛeĵ=…‰3]UE£¢Hâ†X–g[©µ$æ‘’I.Eµ‘äbQ¤Y?þs샋"‹˜0já?°.\ÛSíRÿ8¦•;.éÁãÇÌt·š¤ž^œ;IŒž V‚(·FÂÿ˜ïE<0.0×\Dû-"[•eè¢ùoE¹?ä¨F)éQí¦JíY”ºbæâÎ߇¦7Q›cQ “›GíY<Íå=®óŠáÙ^<áICS»Í¿];Qϑɴ.‰OOÈ\» ×Ó«]ÜOÃ1*HlfvÔÏP~%I4À²½V(»pl:)§tìu¦§u+ªQ8 <_îžU®¨†FF,žÅg <ÅÂáêHÄâôPM!·€ä øï ›Í×á²Ð~ü;¾,’üLÀ¿}0؉CßF‘â­û,ËóÛÁug3B5£ÐȰ]¸è7 Z„Ämj¤L0r B°z£j2OX¾ågÛºyDÈÔ!ãÃ$•$P³§wÌõü¨(övæŠ+—f„ñµ5í†gØEsŽ?’µ/Xi E5'ݳ="X¼ß=d¤'¦Äm„ÌBS–¬~~;H/'–¯’_½ÄçFw±.Ù§I¯gLÁÊ €-¯.´‚•"•2…ò½ž§Á•¬Ô¯3‹p wç{§Wô4]ãf&é”{IÔ¸yS;l7"dRƒ ‚þð–º#^T2¸ã8Œ¦sH3_·=âCžÏöÎg'2¸ïÁ©FÓ,ÂS<¤ ÇÖ:z;å…Ì6A£xÃFØ®4dAó#lWR#ãFØÜC¦¿Ó˜|¯¦;éš™zq“qÝVÁ/"ñ)G×AlCI4®Ûð”„åÿç!gnï<9³žhûÜé™mÄè0‡¬õgÈ6bá>2f1sÛW¡6•ûçÏÁhl £±/X iäÍë:Õ„SöÁlµ}uJ$å_U==jwÏ÷·oçoë! Tá6‚ bŸ™wŽÏN"¬©’Á/"—˜¬„2‹läî‰ ‹Ðb?í –…}~äI”(éN³xùøÞg³Öi¤ýŠ›Z ;ˆûùâk͇!ÓŒÁ 6¹„Í_Á°’[A;r‰ÏdIË!+hG.1ƒéq˜§÷ð³]âX”b!.ù7ÛC$#B&aÑ,%D‹‘iDY[ÑAr¹HiK½\Èü„ÉÊz[Œ"Žõ¢êgüϨ¶8ñadú;ïs”ƒJè%jd.Ä)Ê\gqÒ)*åüœýt~ª³†2ä-¯©þHSà˜õü®Î ±7¹`ÉC¯S2èO’ õDöM!Nv&n;™ÅJõ;äy3]l¯P¾î½ŸvµÁ, ÉÌx¿ïÀÌ × âÄèi#co0Ow3@\î#¶FRLkD®ÉÉä9z“SÐq”b~‰.È5;µ$¶æÅı˓{‡yCzè%îp?Y¹Ò.R+˜øÞgàlidˆ›Ûm‹x ^ðܯyÜ"Rœ›Ù/Î2ð"Ú~‘;Ûl&8æÇH¿Ú_Dfð¯0¤µ³'Ž ž' Ϥ(ü8íBf¡ŒM%UÓË Ã"£½aÃÃÜq¹zÿé¸Î¨_tâüܘ|‘«£½ñÿÃ,ómøÎƒ1©'–«H`™oÓ·bÍ!o½;Œïå,G^27•l⨃~û}Ùçn«„,<æºüâÆW³ +9BbŽ»êv)Ž{/Ö‘!Õ|ËŸTo´ÑfdcWoÏù3㻤û(pÙòKTDz¹s7`d”¾Í $ÉÏ"bF”ùˆh§$9[D\Ú©FÂÈâ!@q¼"Ó¶¿{e‹$õ?øC­¡WbããZÙ_”âñ’ZŽâ©¾¬¸ïoÙð‹²õR¦=Ëò„Ę$·ø&×Ií½ #“_‘¦EB:8{~*Ò5#F&¿%LK”tðÛ /°³[W…·.×g «˜Wj‹…BI¢›qåmÆ.¥Ñsê¨ÊybŸ!dRÿ4ÝTª±”ÆÀÆY»§¥4%tl²Mê']PІi®R'ôäëØùd|‚¨z!ZlÛ/L«ƒE9MþB«ƒmÆ:ýPnÅæá¨¶’4=èêÊѦi¥M›ë׬‘eFÖKeÆ ”52ÅÒIfüÉ" .©ÏIŒÕÓüìët7Ý& °†‹a½#djljv‹ ×^%ßžàšFRìÔ!‘Gçr_ûr]g»ÅZ¢ çpöam¹- Î4ò¾Õ32Îa¯yÍü12ŒDgø}÷~öÎŽ¿Ð–ZËýÕð !sC ·ý³Q¼Ÿ)Ø5 äAÚ<ß°™íËüÅw‰¸¶apR-Ú-IÃV` íÞo?:mþÂ$¹Ô³IZxŸÇãÔ8¬ÆOi_zgâ-Lßv+çyØí‡äÈ4ÿÑãÙz©m‡±ÿBýU##KØ>WÀˆÐÈ[xüas˜ó$d\eÅ—Ër‚%Ì1® WUíuÒóªªó*S¿~,5Éóæ6ßÍüF´šQQHmë6׎*`%#bœ!S4ÍÒ/èý>o=¿ã³gÓníi424ç<«¢U9cdš2nÊîÍ™÷‹ŽA Ù²nu§ÚËRt{ïJ»%d‡¥ö¯®¨f,y'å !ƒ,5VuÝ 3Î$»Æ+"£È¼fXn-–ø—ýÇð.wŒ HüËÙ¤¡-ï2,ˆÿr-Èk\¥X‡ŽŒ @÷}k+c±K²äwùÖBóâ6±ªbB¦Q‹–Î;;¨í”ÑÌb‹ø,·½…Àñ]²§¶!ƒ•Áá1‚E¡òw¨äÀÌ$–ÇhWuò]ÚE‚6cdÄ2Œ³æ°‰Ãc LlïV¹‰¸°c9O²Ò9²ÊŒJÓQf$Y~ú!\ËNê[G#“@=¦›¼³Çùý£Òx²Ïˆž)@ô¶gK!”7yÑ–Îäq9rž=Œ²¸ê h°9 X¶|ëÏw^ø„YXFUá˜×¨–LºÊVE‡Mç (V*ø—×ÈSÛa_”òÝN4p•Ú΄‘cJÙ‘s)Éívj„`)‰kžyßžÿmæeDÈäwÀP¦g­Hí]*Î’ÃÎ*ð‡ËJe#!S{ö‡Nw—êùzJÿ¨ !³P\'ã^Îø˜vR—Jå\¹L(Fà]hdMM{Øãn…íáüùßÁ9T.ø~ÛA„ øì$Ê$ÿ"®”Iì^AoÙÜùK\d´ƒƒ’¿ÔF&q‰SXì\Ê‹Y@ž²¼Yù4ùYþã*§E1ņ$vã‘¿w„ôrh}L.Ò‰æûEÈ4NņP5¿žzÓw0ƒJòë©7=÷‘QoúݶòkÄ%\ ^;¤m ¸„?ù!P ¯H~¹„koúŸ=êMßÕFžP±½ûIORó†äÉ_RÈ¡ó$*S']N«—={zêrÊì‡äPˆm‘§@:áPˆ‚.§ %¨‘Y°Að¡c ÛažÅ»ïÜ21¢ƒÇhþFó7ðÞ#Ù q‰5A qyg?ªÿý9ŠäÇ63OÍÜ–õŠ‘·ß•AÑ;¥öFæAÉ.9ÝhWK6 »Û›X²Q@Ü««Åk‚Icã¯v ’ä·8½¯TBqð4óhÕj›¤S2ayÙ¹á‡7¹ˆ4.™âì6\Ë£Ûáá ¹Áv˜ûÛ¡ÝŒg¹÷Ff¡³éŸ¬/½ë¼¡uIχ‹š×à%Hrg;üÙ8ÛqÏZ’ãí‹ITr¶“ÄÄ$J[QÎ϶ÃÏ^Á¸¦¹ó®ü›V¤¯Ý0¬%÷N ˆDÈɉ 9‰ˆDH¤+Ar‰8Žé4»ÏÃw{ OÛ<Ì|WšÖHvMâ½Cxãq*±ÌDY±(.ã:ï !Óð¨‚L“¼³gáA35eî½ëÅõ3h¦£BBÛöÞ˜¶í¾Lõ«âüñ6Èk@ÿˆT´¶ê=qÇØái$/?¸Kλ•&7Ïè> $§Ž—–‚Õ‰Ï>öÏ×6صÖõâBR°¼eõ´®½‡¼™ÑÎûÁW<ÃÊy~Ûºát°äÙ+sö®]ö²µòñÄu£RÈG£=Ag.§CP8Òº˜Ð+žÑÒß9D E1OÓu×%ÅY’âºë’â_A¹*ÈÀ1OZëRÉîðEqBŒKƒŒãE@o‡YŠâ„/o§ýíEŒÏG$’G ò‘<Øg—'#ÆjöX) )Ö0¸Ÿ4>tt›Ì»„¼†~{H¼ä ôÓCzŒ5\§uŠÉà2Nßi]ó‹â£ñZF|ÂÈpA»yîËbj’´1 âºÛº)jTÖ±H!äÓà£êcAÒGò“..ÇÜ6„ úD+(;âGr$k‹ŠÏ·1[€%¹¿.A#c,§Ç°s|öÛïÈÿŠ÷3ÿõt–º!·øIø:‹ˆ§ó<î3>f¸°9tãÊ|?id )ݧy…qgØŠXBòЬU_G³ªu´Ï`ù­n$ÞO¹ytÄÁ‰;ìÿ’Lj9ˆu±ó®ë·qìžû$5!/'ãDôŽh±~móºÕø:o&ö?ºË&ƒ—û»ÁÈ2¾#ب–¦§;ÂôÌbVXV*…Ðì´&ÁA+ˆ8£ñ¡šDç#ã5 ûuÐ,R“í³¡ãâûDÈPMB›fMø…¬°LMbBÈhM‚×Þu’ˆÙûV[#iôýäö.ÝâBÞrï¨aý¤ù‰x=w¼É ͽ)"ùƒ´;â6±ín¯ÓiC{ž‡íÀÜBZ³ß k”Ó¢›Òi(>äWàìä/ò+ö‘˜üp7H·õ§½Ÿôl¤·´öäg„ßN/ñ‰áÿ1êP$ ¥ÒË%jÔ1 ¶u „|£†ÚRnKI£XÁ4ŠÏ²þ©«,r(ª½¿K@^Cœuí¸È÷f2VÔ¢WÓ$Ž£óص÷ d:¨c_„ùÐJœma/QÓK#´©† ]—èåo-iy@lC/¹GÕ‰]6l›r}3hÅÒ‹k¯eâÏ#ú]š©Zßûˆ‰;°y(Úò7ÛÞm)–„TÙî¿R®yèönW.KÇZˆë4ò Ó)áYgPã•Ó²µs»²!o¿£Ùmís}-™Gs®½ƒ÷3ÇN°Æ[ ±e>½¸£,ÿkÈA Új]ž} Hâ![àÁ‹uþÎwûáˆE‰)äg™Dô,+|Ì4»'ÃH'b1~¤ËöYÚa¸Û7™àƺT£;梆é-þæ_gnVO4S|Ënô¤çÐÉžC‡ žÔÓc['¥ÞB¦òa¦Ç†çÒ5Õ Ÿ=3µ …<†”%r§ªBÈZ—Ìàó¾ÌlÜ6„̃֡hˆž^/'ñ’;DO¯'äHIÚ¶+Ãõz.]ñ³¥œg„,Ge]ÏÖî ®‘!Iî‘sñ…pïì4QËØÆ>÷ü”Jh‰õ2~©„â¨#BF©„”52‹Ñþêaä-œ)ê\gñSÿÔ%ún›ëaíJ³ÇÐA”jÑnŸûár_-Å™^Ï—ìÓ9wþŒpÉdÞ±!döÛs8ò޽çBÞLïNÕ¬´¼{-u!J§W—õŸS³êf)O:ì2 Z¤ò>ÕÞuÆòŽ©ììÓ¤Q Þ YðÒä‚$Ŭýóì/h³¿`žý…Fì/˜g¡‘!û‹Û_hä™ýÅ„göyf1 ä™ýFì/˜g¡‘Qû‹š3Œ<µ¿À7ôÔþÂ;ê‰ý…÷£Nì/ƧwÔ3û ïZÏì/<è™ý…=³¿ÀïTÈþâûxеqû ¥!sƒ $Ò$‰šŒ8÷K’¨¹—û%IÔÜ`B#‰y|'Ç„~­â;õö7ŸOÿi Ò©Ido¾¨¥ÿˆÿ ¤SG¨u^!^”aÚ>Ã÷ƒ©‡<^©a|¿êõ‹Ž—Rooò±.ßùÝ#¤µ=¯¥B¤|öyÞ-ߟi;ÂÙi¤$Å||Ì!UýH Û¶Þ>oü‹ˆÕ©ÓËŽTÝüTkµw%BRÓñRZmzÅò®qëˆïüÅ–Àe­\'”2"G.½ZÑÍG£Þe¹òÔ]ù~ÏCGŸ³QÅrÝëNz¢ušb¨ü§Žú[þŒ¡™ýôkÍ”·\ÍÛ;êͪ¡ò¾“Ð¥½×ß7†æ†H¢4/•зüô¹rïf.T½øj•ìlCß7P†Šˆc¨ ¥zT‡äQ÷r*üö_ ™D.©‡€øg*—×ku>ýÔ ¨o*"¯5aS  <ûO½áŸu¨´?Ú_å"6Pè5Ѓû Ç>Õ-9³z}÷>…†·Fú®žJm”Ò¬ü¢4>=*iV¸Ké5ªµÅW6Ü4à‚‚…aÍ’¦†…w>MOµ¡&뢩÷7fLN„íÔr›;ÇÀh“,¿ ™†Þmɹ½Ÿ¶aãªHÉcnâÓ¬_>æ-< ( `ÃIo§ VA‹¦·ø3Rås{—ò“f€ôΆè1=kкþH4=“³þHÔåãü‘ž0jKÓ"â$êºõ #Oü‘Œ<ñGÚf„,ÂBØ®?’F’ðD[µZ$ %¢b“2‘INž{)ÇkàiÒ˜šÐK© ÙbAJC£oÇ"™f=3ÁpvAêa:מÌ=«ÞãŠÉï¢Ës”;¿ÈƒVkȲû\¾Fþá~:Žy2ºƒÆZ÷îÊþÑ6ŒLLdiµã°oßú3Ã×á8æIWä²2Q‹j·óWµl™9ÄVõ&µùí÷o ‹Ã4ûó¯æéòÇ~ÿ6Ëë‹™‡Ÿ»+„玸^h E&Ž[í5ØÏç2Ÿ~§núü‘ÏèyD“XÀ>ïöÕµât¯«Ì¸ÕæÛtý(<®2c k]ž†]eDXgÕÇdØU”Udê¯Ð‹l†ÁŽßñ·|?w{ípì­”˜¡ZéyÙj4d+¸¢ì’lÅA°¯p(*~Ú ýâò¿Ð!ër)*^Úàé˜ÉoDMEDMÙD‹¼¸ª {3„ WƒläïxGü®Þ®\áO¼«·ít^8BH$³Uÿ" Tý©©úoyQõ‡7Äq„ðzGعã«þãá»L¡q¾êÄ"¶i†Ñ©„Y*Í­€HK ¸Ž¦×¤=‚dWj¬¸ñ,<Ž­qªábÛÚ+J¶^Õh-©«Í¦n ¬ÞéFܤ«ÚTý×¥"Ëæ¬óéWƒ4YÕ©i dȪö]úÉPŒ¶Êe¬váÒIN:N éjÅ㢸‹Õ¢5×çáGÉu™(\ŸŸ:Ó|BÔ™dvù‘ëópÖê–õWK¾p©¸)¢ ‘šµ°ÒE¨)‘î:_AÝ6Õ´`áªñòNë©Ï"œçn:ÞºôvûQ <滕ºy6Ãbgš†l–ëš@Eçö9õ !­Œ©Ö~Ô5òîÓ>`¤UˆWN òUê)iº7>!Sg´¾3ý«îMEªpúΨN§Ÿ¤J&‘F¦¤ÛòpA)GC,È8X+Uýjã%,Iȇ„p×_N ƒ‘€ÎôÍ»džH@Qü¬¿œA&'ë/gi˜ø<ÿÿ…ø¼3„ŒƒÇ$;óq}Ìa2S¹í3ºª*/88{~)mÕtƒïð; ŸN£Î;^¯íý]Ìsn¨ wþ6és[ÒqZèŽja#”¾g2"¤3oÜf§– âõ0TƒLµF»$)wP1ëÞœ}ëÿλ_LHÐÀw]Nó)L+šûžCJ#¤G·MiÁY¯BLºm‡œÏ5È8àÒ3ƒž@¦¹aI–ÝþÎ As9ÈBàÛ¼pE Š¨KᘗmÝ!d £ËóYÍo5ýFÛYë"‡Þ(+f0ÜlͲÑ~è02†Ñe™Ç©]»Ù¦¥žÞO{E8ú•ý ¬Ë07ïr>!í~TîYš[󩇵.Ê‘ôNôpå°\®ÍЧcyz¢ÄWÜ.˧ßaïˆr;hy|¡PIºyã™›½C:š³ÏÍ&6¤Ÿ]»6˱mpØ ¯~ß^ËwÃW¤Ý¬b¨Æ)Ö;3|E!ã…Uƒô ;J¾k&°yÄ–íïÝŒ{×â @5~‹²;R{jšr5~@ð1“Pø …0|\†¿P3Høë&Hmx?І¤¶.•ÄŠ­ë%ö™g¿3Ã…Åo”È~:Z•ý:2¤’ct^ëºì31ÈãàÃ\iµÈÊ EÈ Wèí ¬ŸI¾ÒuØð2ÉɆ&9ys—InLrÂÒÃ$Ÿ)b’¤‡I..“Ü îÈ·¦g… -Ý8$IôÓð0ÃTK õ_I!˺&‹ŽgÖË“ÇÜçi²È$ —'‘o™ÇéÑËSÇ”¶ÚBê’Ù¿Zy†Iö­ëvHQ’4˜š2ùmRø6]ϳ…þ6G„ô~›²Hí¤¦ÉýbŒ\~›°o&wGYïÔÂYe Ǿɿ´p ¶I¿ƒ^ê“Sƒ^JJÉ ³pSª‘M)ûudضX6ŒŸê{oI)Þ&2í«1í+ò¦Ë‚™ú¬#º7ñ’}?’Ø®=’íåû•³k#BÆNáæøˆ)£tìËyÀÇLÜ)ªÒ¶eÄFA‰Ðûx×ÛŽÏ~ÇÚLÙ Ý22(%¹3@õ©8•{K~º¢Ì‰ë ›ZÛ3Hw“ü‚M]ÊÜ_Q€M]n¹²¸ÐQ"õl#À¤¸ÐQÇ>#:J‹ü”ðÙSÿº¤Z8™ÞΣªö]Úä»ÙDê–òOOSlrÛë§5Ã8ßO.ï'è¤ßW»Cäï {îçwÞ!òw=÷s";ÇÈÐý”¼kŒ ê=õÏÿNÞÓJš’[½'ƒôé=-ÜÕ{2Hßè?ôžðï D€õ·$§ûYîüLÍ@˜@&áÎ&[8¥§I …£¬bdn:"d …£´¡02 ÍB§é_ ŠŠEPÞ²>yú äé 2lPä¼ó–`rn¯n®}‚@þ¥l4C$>.Fˆ•Ì® £Íà…A† £‰}Fٵʃ¡ÈdXå¡Ûð1}íÒDu‹vÌã2/–VˤyÈR|ÖV'd‚Ô¾÷Ô5ý>ÁþžæÛ_søÛÎp“ß-PÒ8ÿ÷§±MïÝÙþ3 9fù.OÇtZËÝ1Ä3²zd_qM-Bº+ØSu&4²Ÿg{íů®õ±¿×œ-ŸžâßùpËpÚØºÙ>S³“ý³ df‹Ô­4¦RåÂyjªuÝðÙs§ gÆ)okm‘:-,‹ù@vY¾Çw‘@Z8,f5—odƤ/mûg‡/é`1«H¤9¬UÄQiýåÏ÷éyÆVt©=z]=ûôoÆmBq@ÁnËÉöy_®Ýüa'¨#:ŠmÅŸ Cµ*ÁÿŒ*ÁA̧W¿µ'èÃ0|‹Y…¶riž÷áÛVš!èˬâógøÖ†jóÿŽ”ÿ±Êmïçáü4‹Y·}@£¿lËÏ÷½ŸÞþ›qS¯€w©Âç5|ÁG#Óä.ÁPÞ÷ô©Vü¶h³âF+5-% 1Ö¯W¹óó°Î…ÏN/¦â âVˆÀ§< ÷ÛYIìÈÕ¤‚›¦y#$ Ž*k÷C7{›¿dlŸ3B&VáPûÊ+»7¶ûZ2„L-•¡= ûk5¬xKŽw÷UÕ³ý6õL¤7§c>L"ãÁ—¡.m6íC…™AJ½×1¢/’ÏrÙZ‚AA׌&s9?ën…åÖl"tÔYÈë m±ïÊËšwøÎßtx¯­Juž,O²0F:|PýM[sbmáã=Û /½ðufÉ…X‰CÏÈÔK¡'†BOí]º_Xï–;[*†^ç3¾®ëØCn™]TIfI´béu“F‹ûN12±=Wu˜íë4™z|'´ù-‡Ø*{ µÁµO\D°Jmõ! ¹IPå&AèŽgæsh“Þc¤ÜðÙs¿ïá#Y0²ø%ZQM´²•ìoÑ*ЉÐ+KU â*ô®N»ûÒ’F¨NÇô¨VS ÂÈûéUÖ[§ø<¿óbõ,G2Üúkª²zí;aíÑF–üè¦ÜÊç!ú-“dùu >CÀ–åáY>ùŒl¨œWÚ3bi‚°6+ÎG÷K,vOÎÛ€Ê\ihì<º^±é-¿àKº^±0›-‹æÑ¥å3 ’Ç—VDŸ ®(Áª¾¢ÒYäÉÅÉ…iÄȰÕá ‹Hî¶|]ýùÁKý{?ƒ_ý¨/øìwXnj3AJÙÄh9ÑÓÙ^SD©m¿C9Üò§ü‹H ‹ˆåOy­Çm…·¡GæÛ3O}"çÚ M¼L`Ð&÷°A›ëøl¾2³\=­ã³Aj½t H7]ÅûZ^ÃPްÊÚÉf×Ïülɨ´g:íD/6øqÆHÛš– Ý Xźq2b$LkþþánÏ)ãŸÓ1u¥C¯K‡N©x‰‘øØ2³µL 4ðí·™]6ðvbž]бs»m;.²]ÃÍêA1v…´iW^ÅØÇe[…p-ÿ1ò0<‘n;~é­¸,üTbn-ü Òcá'‘Ž…ŸA^XøÁÓ,n±ðƒ•¡¸ùöÍã~’]„€pö(nâ‰"¤w౓6Tu¸c¿¬Û«2õU92ãye®$%o¡|Q ÚÖfï^ÎÐ_‘ãDº-í¢ùk5xš7_GqÿÛ üˆÖ»ü)×O]0”'çýÞºÇÉ^óš{ÇÎÚê»À÷cñÓêÄX")[¶¾ââq’æmÉ[ܶn¬8>¦£øúlMÂÛ Ë·ŸFÞý,HÇrY ¯8ì"—¢ #ƒvj3‹ü¢x"µNaõva^çÞ ƒD·Û•³È;ÝnWÖx{ <…èvûµÆSß»²Æ97—èöó½Ë…þ°ÆÛLIðÙï~Ã;ú–áB>B&ÒÒò°Æ#Ë—0Œ êÿ\¿A>n£V5…¸è]ªÚ!Êè_°9ÊÔ 2 M¯š 2 ”­åœ@&HA7hT3SÆÉå6nÄ méû?Õô¬‰‰Çoß­§¯ÊÑí~uíR[#cß·9.‹ü6™A>‚ßæ&¿Í;É_Ò-h2»21‘¢“píùE‘\62F@:<îÓpwOÖn‡voÝþbU`V†(Š7ç×€àM2ÆfºÕ/ ÀŽÇ “°ÀŠÏžzÅúÉ‹ƒX¿AÞmû÷Úç'Çg„¥ú|öìWS^FWSß ó_I}‰t$õ R6ÿOe=pöaÑøaøÎßÂâû;¾ø( ÷XÍb½ˆ\½@:ß±)1µÚh¼{³vཋ¬³ubÛï%|I‘Ã÷±íF¤A¦!¶ýn÷™ÈU×øGƒ´ÇÇ$vâ]]; ªi”YùçõÚ>«½K)Š*=–Úɬ¡{ój;3q‘/5O'‘ mi»!dê PÆôY±…ñ­EHKȧnH ¤HùÚ¹eùðZÚJ*ËÖ›èb]Ù ßíÓ¼{õ[• Îþ` )‡kÏ.VeYÙà˜9²[©Ÿu£af²ˆÍS$4€,PËEÕxtºrÝúç²!dlUƒÛÖôìw ,v?t,qt‘\j/ê©)¿ËX½02uZrlZsæ5g-DLÖgÓƒ-¦#²3ºÎ ·ïR8ß'E.©%dž‘C±;}"¢ßV°\6Hd“K4²Õ{mîg]êÝ‹Š"¤Ï‹K½{^• B&¦ÃÂ*XÂÅî¤w_‰\{>ýл猜G¯éŒÞýÒÒ¥45ÈÈ¡ØyŒ­vÃБ¥Øý¨Ðm®ù­@Æ=v<ï±.u ï±Ãi“¿ì± FzöØñ¼ÇºF#þ=#ƒ{lo÷X×hÄ·ÇÒójÅÈ«=Ÿ=¼ÇRØc]£¼ÇNí¼Š¤Ïî±±«7z¦LÖ.e2ŠÓ0ert)“Qœ^W€2YÚ ·‚`)“‘¥ †rN¸úûuιAtåìþû¿?NSNäróû]í3ÜûÇÕ€dæÃïÌ‚jStvÛ@‹â<¬Ç+­jÅyȪvVµ`#mIÈ¿`´;’C^Sìô§\Aµ¾Fû©(Ù†£;9ä5©1Q×FelÚv^×¼4g‘C^ûç?¥coÆYDn\Ñ„5ÈIJÓå°«ÉIÍÇÓùŽM3Ó¹1Ÿ_>æÝÕUyêI¼u¼k^†p!òÚ1lÖéñÁ¡Ÿ¾#7™™ÙZ­QeÙ÷K¿äÉðïÌ«ºÊþ¶â=|rÉ Ú–ºZá¢ìª÷fºMæÎß\Ñäîsub£ë8>}²lY뾃†¾Ðühl…œZXðÆnd’h‡¡‰!T5„N:Ϥ¬OÏ>:ÉÉ¿T<Öòõâ§Ëº›hHi|è y32´ V%ÑiTåàM¾ÖzÿÌ£ø¯ !]Óë—6,{òW¼¦í—"dâYøÎ)ƒa‘™úµYÅÂõ¸(H]”™Š£¦$AÛ™¢ÎGä’‘š’\oÝÎG”¤!5%ÂÙ.¢¶!dâîKÇ_x3}–uæ™ú•c¼£üã4¸^Чú¦u‹FÄ‹Ïñ]mo†¨›rÐOHS–\„N!rȱ¢%>{êD‚OØçGºíC‹‘÷à0|¿ã³?¼SëœZ·ï’ÐÆ¥Ïöˆ†Ø·eôÙ0|ö¢ —ô$"`N)>{qFŠÜk/±@.øìQh ¼ù0»<=ìJ¢ÇÀŸ0þal-Æ2@ƒcàÄ–8hâ©Åδ—µX¨É%Š3³bÑyþÖߎ"$–'   V׬^ÒO›]j\äÒA}ò|Æg?LAå^«í_JÀâ³ðÑæ5ŽˉœVËÙ#ƒÀòb9ËGž z±hrÚLNWT¸šp÷]’Úe'³Aæ")ŸQÊX~gq!Ÿ±ËXpCH:¬¸óR¶˜ ½ðf9ÈfïgzC ”ÈŸ`£5ûÀz—âü‘éþ­Ì¿ø éëµrÕk5Z•yÁ&‡“Ö¼Ã|”^ŒÍJ='èTDi ŽR¶)2d+.P‘$L<$ehX;MË‚ñ/]Y %]™@ž˜&'W¶¢œmYªù³à³§¶Çn&BåP$÷¾âÔfU˜0¬è‹b! !u>«"êWvÇ;/§ð1é†å;/M.ÅAåµÈ yÿó !ÿ92_µ+Kg‘vS„,ÜÉ“Œdä_ç¹§(þÑR…(½Öoã¬!éýrª¥ìÙ×s:„cd|Q=ƒß™]VϘ­ž¥Y¨SA¸4{A%! ›?o¥òsÚ2ÕÐußOÇ ¨íÊÕÁþΓæ«ví퟿;±Ñ›xñ~ ªíŽJ´¾Žûå4Si‡ß£{ôÿ„]Ù¤¸²ü¥ÂP ÷}Zšó .v³«¿þz·“ÂLO«¥‘B.c§33"nÕ ;r¨Zª.6ŠV}>™ ý¶ó«LÓÂ%;@ú.ŒÆãD(ÃVÄvôh¤ýÞ¿Â+Vi牢ð46ûD¡NáT$þÌ\zÆN.¢þì÷î»ËˆÝ°¨rMPX=aË× cïœPÔú똊™ÆT™#4ÝUóDfY·¯ ­b¢ÈÄêý½Î²ŒnV *rt¥é®{'ydYëÁw¹yHg¾[äjë¿ÎƒÕ£éœQ•Aø_®íºö@¾NH9díx° ß^C½Êí6"qÇcKÛÙ¡‘‡”ükù6û¦¢ÓÔÂ1S§ÊVÔ*½›óŒ_Á8ÌðÉ«\“TÚÈ4kñâÖ-ãéjꘪߟi¾õ˘—ª»µÿ5 ¸l}ÂuÞõãzº€8DöñvYG ºèÙGöÑÈË5”ø^yãúå{d RŠ~YäûNôKäœ(@^¸iQ!²’Õ–H9o“›–Ú±ºÓÈ$˜Áêm¦íy“Áb2ƒ5$º¢ÆÐ5_6ÛK=oùÄ‘ÛÒß5]ÆvÂKÖ¶kkdìú! HÉ1= "ŒÍz'ÜÖ•áv>ÿïÀæKD”dŽúæºgv¹ØWtöª,ýv ý’ÑŒÈea'dbH4"ƒ¡E•êú¨¾³íÍÓHO´¦*߆e<Ƙ÷¢1+øË—î¢_Œÿ¶'ú½â€è—è){ç+8ÑHa!VNû –P¬öN•é{'#%Èä²ûˆŸxùwdß{r×}ĨëWñ½Š¼[¥›}0:ióvŽ|þÎ:MÈ"3ié–ÙëtY™?ÿºþ þäÛš­”åÓ ¯Õ\Y-¾wû”Þ7¹mˆüܸzÅqØ «£˜]äØ|žè•ÞyùÏóý¸Û'ࡑ芪I|euŽŒÂ°p4uy}>ôëšHŠ£¶}otëyKk[¿¦ù^oæy¾“p\+wm_wäÓ‡€÷“ì›uÎSùºó~b¤Ýf€ y?12—‡];Oqäûþ×3÷<ß÷¿>ˆ¼8”Tb÷†‚ä+$·æ?¥ÜÕrk3Ds×A˜†äÖ¨‘[ƒcdž™'X¥7{1>°“‹Òg€‘$ªÜžã˜Aºþ°¢Ê+ÅÇ_ê©ÊØf+xéó?Mí÷žÞ(êK·vwïÛØ¦öžçûw?²Ž9ž2G~îsˆ{›Ÿœ0øsþq™†Ï|ÿ8ƒ¼–ug"¾0‘*ò^~W0a&»Cd`#|#XÁˆXÁv€L\_ ˜º;­Þ6º™^Côˆn¢tÁ”4Q%z G• Ž*vyä÷Þ›B£’%–üˆÃžÊÑÈÞ wÁ&ÓÈÄËpU*ö>Žž•|w:ýºŒÌJ--9îxúV»e»häË=¥¼T9PÑWr”­m‚ÐÈ÷¯ÿ¦äqìõDàSú~î7/­ëkÎöašŽ SÛg™‰fZöÔŒSVnS¯Óôrý1m_2i¶vm;7¼Ð( äx0³Ý?Š~U0G‚×±eÆFÍBãkP!¿?Ÿ. .n î•Æ÷n V@L#ѹ()ƒ¡r°7…A&wÓ™#îöŸ§&phBÏÔ (¨­Y»—ÿ¼µ«wt4L@sµÌˆˆæj2eó\$l˜8#çÉM矆 M\[ÖñXæv'€ŒöÑ_ÜO;@&äÌ‘ Ÿ!d½øë/°!«ÔQ×TÙÒ`“ÖÖÈ÷r9$²/òãs¥Nu¬ûѼl;ÈÔ#¥Špše›¹m¿^§Q9ü£úqkÍèù ,o 42™XE8"piªïF¾óyTtí«/¹€êÖÈ?ÿS­_b³[Æâè«•æ5„&T| :.Í:V Ÿ ú4 —™O û®ú~1|ûJåp¡›)3rtÁdYzþ)@èÛƒªÉÇß*^hÇ~ ªoA­åE#û´ò1iUÑNª(ý…òáò½mÏP©rh Z=oÁÝØ’mÈà'…\©(×QnsÌ%›3VlvÔ÷ecS£›šÅm¤o8‹´q£¾ýªÜŒr¡FÆÞ¶£‹JR‘sÂ,ƒÈÄGV‰‡©ó‚ˆ7øúT T£›¥º‰‘5È—ÕZËt¥]¦Ì›:;Ž ßž·jìi–i=ªoÙt@~<ÝL­L&´(Çm+)¼ÎÔ Å˜jò‹1É·µŸæÉ?§oF½¸ès[Óqg@ôø„shø[»¥§nŒJ9;ó™¶|ý!‰K§²R¬Ý˜—xuQYz–¶Ñiù­SWíÖÈäRs€ Q!ÝF;|‚ʆÇJ¸ÌïÛ<ç _u‚i·.Kù¾T'˜ùµ®§_ÿk%쀿ž^Ù5ìüÎkÛ»€¢GЮa§”ì³}GÑ#h× Æä›N ñ ·ÁÜ`þpEý ™A"€ôø'-m(˜Ú;:ù’çfmÌ7þóS·b ÐYL.7ÒËo^)[2ö‘z¿N'Šá¯{®”"ÌSl"!ï—ãäÓm¢†|^Ï%Þø6ÚBä èÿŠÒ´èÙŸ +ý oOþW\¦< ”üo¤c~¼,î9ÏafÓ¬‘©p³½™Ç4íÀƒø<Õ¾ÿýŸZ™õÉñ5‘õ{/4²5%­÷`N„Tv.ûl;Ù;.?NŽÖ|/í=2S¤nyO¢IljÝ==Að¦;Âe Cù˜ûîæ̯˯SÎeÙe¾’E¯Í?“„<ï»+~m½¶v6}`ÎI®µ2&:p½w<Ò³ÈÎzqZ•_ü2ãmjÙh: ÇbS.yf;Î÷jͶµs×™‚YŸ‰ÉÜ(•&Z ŒÚ:òXl¢C\§vå×¹ö,›àu>mçÿ:å,-ÞYÙ¯M /+#.ÙL²w™#«²ÝÊäËsËžu­\ƒöÌ*øëûuf•žu»†æ˜À_O½ïX×<!DXŽV²Ñ<ù‡Op-´ŠyÅ}ÁŸ?„z\CÃ×y|±ãy™NPäÑ©tSr'H¦kÙ“ B=K-<À/`&Ã*|4!Ô? ÕM©i¦t˜éTž.àéóL+)dÁgÔÌLóéùG/·- Õeñúó½™÷ضh}»|A®·›Ž¯¢3_Kðé¹~¼ÔB!büeáyæQÎi¢*yn ­U?%‡Rñ§…·¥ä¹5´Q^1mÄýŸo yëIU•†ÚñOvXà ›úûæ:#âqÕ.£Qã4ÐØu|9øT]Žñt‰OàU ÏbbÓ™Öå ê3yêañG ¬ ôå–å€#‰]Qöl‚¯½½ReBĪÒÓ‰µ˜A¨¢ÕýùGnϱH¨Ò·ð#D©càÉN#qzš.YIŒ©YžºÖ.¥­èºÀE½@hØ Ær¶o,yÁ&%Ö 9Öë[:´‚ÑÈ€(§¯‘‚€¥TÈ×µÈnêqAçÂô‡ Ÿù)£8£º.Æìj…ì±cv„t6†ô,åú›‰v ¹ªò1–÷lÈ c Ñ`œ¯ùtz;¥îxéj¾hF» _¿Hqpº@¾}6©Q}axêútïŸ0²…÷ž:di¿çe)æŸÆ4kú¿êBål–·4Ñ~\!4ú…Ê{º€z”©¼T«?a¶<à=2xû‘§"”k[:wZà ê©öæZ —C Ó8@¨çž+9ymË'K ¡/'}˜×jâЬª¼cúö89–í¾û>ïÍé¹:ªM®ê µµþ²¡ƒÐÔtÉ`[=•öƒ·¦ëÙÿC§Ó‡¢j²Ûÿ´=„2 ôaÍL6E!躟¡±mÔÙ™C{–¿'hr 9t8AU}ã´ÊGCéd\ Ô¥Ž¤#¼:Êà±ËYOO£¾¯ùp¢v_Û5-¾çñ2À‡ãËzÈ8T•¦VÑ¡ä®"„Àw€Dakf×Þç‰Ëq6‡±qªozé¹2Á1ƒæ(µå½kä7ŠÛwžvE…Ö(¢®Ð4ýnÓ» ùúµH2öߎù6–²ګë×ÇVã÷ôëÏ|¸R•Ù±ÄKÃ*W¥RÈô²§í—¢vûÎë¶§ß©ž"ôº7b% "ãk“%¿_ùñ“%¿_¡÷½É;!c¿?ÍrûÌO°uo—²_ÓˆÌí‘þðX´.î´â¦Í,§yq3—t.h®q#Ô¨w€Dž¬ºx—’¡Á·'VU¶îæœþûÇÅüÞ)äÛ¾Ä9@&¿¶¥¢-q§ËwÁ) Nÿªº›úñF´Ûvßwx¯+nay€­ÑŠ£{m—ÚÎý‡¶Ë0dXÛÅv0jdìeŒdö·ÚÉš¯k‰‰s™¼QÖÜÕx¬ÔæÁbAU`ê)›¨UÑÈ@'f¤¶%·8¾7Úðî(9UÿT‘3ÚÎC&°<&×å²b/©;<9†ô ®±0#…È8¼†Ø½#~Þ¯!.«ß›9;^ò,[Ͻ÷ü׋Íj£øuÇ-ÄN.ůpß‚¨ »Ìs|£ +¦¼;5ÄŸ°]íØ[gCœ8½ë£Ã»7fz«rÁ˜û6Óà;"‚»etѧ´–Ü­ QÈæƒØä±:OÝ›|ý,ú¹°krra2¯9„v;ûÚ,‰ï4KDqÀþzrÓ#zŠÜ=o´øà˜/‡ä6cÓ?Û£Ù¹hÍ­ HºÐKpw`ܤ§5&mmåiq¬å¯lÈØK×èöŸ|/ª!ËZÛ á*-SÍòZöqŸÚ¬´!pâ—ÄTÌ Mšæ®ßè¼ð:_FbCžþUÎnÆyÚŠÒ‚àÜr·ø)}ÏÆÌæ WûûRRmdefÝ×j( !ðy¦RÕ*‰,‡rhKxïÑRÃåÁwü@×nÐÈ4w|ËBçTë®[ñ·šV¡ÈNq®zÿù å«wÕu}?Ah|=8tíú BPŽUòq¸ëö}#S ¡Ï3TVn9”ÎÆKÏ@_–þ›—:,®•t›N ˜Ââ`'ªÔ¸¬¸,iµŸF•e¬Äk•J4r[‘Ø€‡õô\SZê 8økåW›38ûåÛúGdŠ„ô•ÊÂÕVÎ-_ú 42T7\Ê2s£t nƾ„®=7|B9J>wmÖžt"J`±S–)Tø"“1ÕhÇ|>î|­ø;°éÿgt'Êw»”{ôV#N f5«[zˆV,óœ|—2ç%…àÛ‘mô;” e!Ô²ËC7ímÈøº…w-¼æÑ;‚éu ïnšÏäž*]ذàù¼£JóåÜÐGG„[Ž ˆˆ-Ç}Ÿ¯Iصwôo̵ 6ØèyCé>¾‰ÚPÑ÷®$¹×¶Žy/4C̘¯ËYçË-˜;zE€æl„ËM+h‰´ŠÃ8Ÿ™çyçþ¥œÏ ]Ò€Ç.zÝЀÇ.òé^'óƒxìjäÇîý²Go-æèõ û ;4r²_¡Ê—†C¯WP®•ÒpD¤áøsúž‰ßÑ£gÈÎïˆ?{yÎgÒ_X†˜â×óWíÀ·þ ¯ÚX•Sö\Ã1c/«[N¥%Ì1b»ƒ¾Þ§ÆŽJß»ð=ø3; òi~­ÀÉ2¯XXeÛÃËëèGt~…¢»1xoײoëÒ³>kÛÓ˜¿5V¼¥£7k­ô¬F¦Î3µÒuÉef ™iéfÝÛ úG*—úuòXT°AO?¯ˆDIâkÊ+]Úõ E¶-7•¶zÎë½Ú¶ÓkR)lj騕¿QT|}: 41Š$°96ßwx¹ðåœ&8èÒ¯OÐ0@;ùÙAÓ»&{ÐŽÞ‹/ÔÚi ™Mìâ‘í4j¶,6$u>iWvUiÉ*ÈóIû5ŸÀÂÌ"ÑùÄ!üÇ(@¢Kç·¡Í%æyÇᲫfbf4òòð_ ?7·½ã“¸I=ˆÖ«²íj÷䓳ÐH¡R·"E²ÓáëžR0õ ’c:_FRÞÆïûÈZê&r~n2ͧrf|ç ²“ooË{žŸ›ç ("1FùÊ4PbBæ÷;à•{H7¹c¦ ¡s§œô‚„»Ì„ÚCà/ÍJ);zÃûЫ'@Ø@>y–øhXÈâQ€D7‘­óÆ.‹HçR›LùD§&¼4i,ÑᾺ–;ßKÊâU4©ÿ0':·6-èL°.ÒX|.¹˜ívBé!o ùÄwb‚¨Cýî c•ñ(Œ¶öñŠ%Ð$#Ž΀}’à>+‘­Ý¿> mô}ü2ÌŸèX€L® -Æ¢ž2÷Å}¬Ëy¡ŸÄB/:ùº¶Mâ8Ç-øýFK°vW”/7Õ®!U¬´òÞ9’Ð:«¿@¾=BfnÛ©È>ó‹ùäÇO…—ºß¯šèQu©Ÿô1ÍŽ]3ÛÞµðÉ?.»ã˜tŸ°·twäö5@‘Ïp\Ã"×,¤Ç|)Í™QìA©Ç$ûë¬ Áó¼ÍV¥“Œ¬[W6µÅˆô*„¥ÚÐ~FšÂ(Á χJÆlêP!CpQ÷;z ÇT¿ª]\3Þ¦Uô®ZÔù6­E_‰€©ËpAÛm8ÝÑÛ7ºWü‘Ëöu‡ÞÔjï^;Zeä»`Ú—8Ò€*YŠþi«d©¿€ªz¯ññ;޼+Ö§ÉMª…±¶1LGD¿³NÕfÜÝ‘¯RõÛ•ƒÝ5}žªOš,ššvêFÛ¾«~{XÄ™ ãR¬v™MU9—įgM7ÙLgêW›•¨h­EEi_ðÿk!òj´h7Ô¦®Ú|…ÜZ÷<]µùÏ_CgP´8§rÚ3€L òk+Ø¢m¬ùQÞ»>üüÕ ý!ñAû¢ÏáÏkç‹.‹ß÷‰®íù¢´{Rúº±[MéëÞn‘CFlv:Ý™‰`À¶­¥7r‚bkÅŸPšÞRl32H±ýò¤ØòøªÈ$DÓw²ñãqö„×â%²ÔOùÚtdôk=Wšô’Öz.~ÜŠM‹þÊ q­ $š{}>¦9Ϩ¦Ù¹æËþ5pìÙ[ibœŽ™„„)bšòúÜ¥N>pÌøÊ¾rïŠbËw{ïÁ¢k=Òº³È<˜(ÍÃ1Ãò`Í y!Æ)kNù¼´ö’‚™“E¾nmÍ„@¢¥^Øšµÿåq’ó}žŸ¶K¤w|k¯óôާÊ;~ÈKïx¢¼ã'€¼vZWÞñ “XnüHÃ3K³GsïÑㆃ<´ÍÃÆÑMqX$ÿmÎ4ö)D?ïhh؉OR+°µô`6{ÆbÒ|ÖO3@&—_Ãü¤âÆD!kD)ÇMss:£øFäß»=ËÅQ|6Ü®U®H{ÌV}bDó+E3S—`‹£Êý¨ÒY º ÛÑ›õ3úNêXvßôåÁÈ=,š¨æd¸Èýy9—ĸs„Œ‚R @ '^Í™D@ææ ·€ÀøÜÅ›»qö›!qîKLâì'G$_ÂDa[H&ÖÏÏ—òÊ06“Ä!Ïs‹›Ÿ[$¹¦äCn‘D׹Šr‹Ä£šþ]UÞª_§¡¼•þdÞ ö£ˆþäjuÌ +^1ƒ]¢ø¢~)æ<;„ŒBõ!/¶ “(¥c–WI"ÑãjÎÌC¦Áf{8B^öp|MÔpHz¶Ú0µÚ”vµ‰¼]ÆÄꬄÌ{5ØZ£A¢ÝP“d… }}>Õˆä×Eœ ·]ÌO˜u>ÝRGk2TÓ2×|dë¶a¤/tWê ¬œÉù¶-ß!IÀðÃ3^&áñÌxÙɌϔÅ6÷y•¹q‡¤!Ñue®µy@B¢ËÊ\6®Iœô©_Çb{$_âQ#5Ò*Šªž¸Ý_3ÖðæfBÈ$XÃüë` j¢™kx«›!Ñuen²54û惕¹}?\ô¢2מÉXƒÈp±|N™Ø –åbÂb(AZ4ª©U•Û†×Î÷ Ä"q:6IKñ}nu^BÏBcô-›Úãí6e @ ªé3okÖ[1£2؈Wã×ÈÊ4²7c?7åøÆ×$¿I!~H òפF^$…`¯ñI¬ØòCr<Ë&±JÅ)<#š„ǘsÓ$,+™%ÎnÇ£HOá×Ó‹š¨4w×¼õã+z»ŽÕ¡N@èí2¾Ú›’"žáÈi|åNsÎpä„>,3#-Ó{øÍ˪$Ї Uû¬[ɶn}ɆF*…:!z&&$@MmÁ"â@Jƒ¬®Y5ðìñ¥™…³T žAp¹tT¿³÷{äÎ§È Cå¸jíp¤Í,¶ÑÖ‡MB;ȨjNÐÒAè±îRš£dÃð]&¨·ŸîúÚ¿Œ¿R±µí7cÞý(À@mÔU4|MMØ—U4ÍM•ÈMœd›j¢ÄÑ]OêXÍÚ4Ó„IHÖ”aŸÐôªáI’jBž‰RKÍ O”šÐÓ‡’?R…"Ûø/…—i‰o¸âª3}ËZ› 4H¯1½j#ëR‹…vΚ7BÒ_Ã\yìÊ»1·-ì*|T ¤k ÒKP”ƒ´q.B]„|œ—HºnýÞRê;ù5Fwˆ±¾Ï²7~¢§3ò³Ë¬ë¾ü›3þõ öN3°4Ä÷ÀazЏTK|?£ûùNzðB£/K3¢.“«D×ÃEbò—.8zù„P¤ò­t@üc|ªÅ.Çaâ@¿€¼æÜæƒ{¢äJ9|w”L_;O;?3ôh°£éÞüóZÇzOHü¼Ö1>"ƒ:Æ"´ÄHzž¾QªÔö>Ï¡~úüHr κ ù7’ä~y”õÒ‹>uÔª‘ë”ÔÏ»²µ¡Õ¯û€~t-úÕV…$äª÷DªåÛÑLèerÓ9!‘$&7ùVuËs>‰O+°È`3Ò<åLÎ$«CH³Å¥Ýªúº?ˆOÉ4º*z.õr¡ŸDðÍ2òÝ#µ¢ÂÜs¯9|ï>%óMôêÍÆö~xc¤Þb•cmYé³W5沄‰GÉÔ ¨áωÀsÝD¨ÜøšÉ)‰Œ1Ù¿O”þtÓ€l"{uŨó>ðÜ€jsͦÁÅÜ É¯;8o†©ã«[m’ô"Y¬=ø×ãóYç«“äùub7ëž—êÄû HrH‹¨$‚$¿hz/ïâ¹9ètƒ˜Kº“H&†2³‚}äáéîJŠÞ z ”@¹vÛÒÔÐ Û–uø×=šLa„Ze¢G,7.ÙñðœŠÒ(æ‰ß}‹ƒ\ö}ã_÷è½àn*ì :Û‰] Z<*÷õ3Ž¶åÆ =šLYiæ¢Laä³8s„|"G±Æ¤AÛº§ß§¥Éøì,™kÙ¦è½z·¢ æë4X¼]†#ÔäøddYÊ‚Ê7tí7Ç·j“GÒ×>½\øáœŠ!LÒÇý:ÄpÑÝãþ—O÷ªîˆ2¡23z[ø,;,ËÛ.·è þZÙ d,óµ«qEÈÈ׉mTÉ­ÿ,uýyñFzB&©/[èjîµÐ¤ßlW™i¨Ù8ÖnBD—KÛ–7Ìû°~D„¹!dlË{[£4ƒ| MWÍN›†¥å !}õ×ÚlÈÓ°×cÞ–B>†ˆEö¯²¯·µð5ÍtÞþõ 2)3]‘ ÷`a{x¦{äw™Ô¥ƒYgVTÓB‰kÁ. s¶ïÞbÛ'g¼ýÛmXq ­‰n•”¯§¹<Ü@î!tkTä5Û9h зÕµÐÔë!lMz?ËÊ©{÷ßC‘ú«{Zú™ÉžýHýU'3ʾœÇîõšðTÕÍv Z•Ú«ºËs3Žùv¼jäAu}¶ÝÛ}~uf;-”¸´diäqfq´«ùg«ðËŠ¨UÓvn}Möm‡OSp<³”àŠn7T‰A3]&±¨d‡ùªW4×™A™~hæ¢~åÝ„ç€\ÑP#{^·ó>·5ãœã!ˆ 5R²Ì1¸ÏÚZ|ØüðXOÛïøª¬ZóÜ—ï­«§†’›ƒÖñ·çÕ©âÀï²P5Zb?·+‹Ògk¾Më ¯,DÖ¦¾­Òœpy&e²ÛŽÂ*Fký?ÜÀCBÕ”rÿQäÂúÛ›$^-4¨µŽn7±«EƶÃËz:¨’ï`ÓP&$6|ôæ )tåâ÷³bf~,z?ƒ.Z C#ýŸ¶ú²!k¿c~€’3ѳ&ö©qW%Áã³dñoî°éuoà£n¯ \ìAG]® \ŽøAGÝ^³Ç\ þAƒ‹\‹'ÀÅuS)ž©Ôçñ“Ëû°‹TbT™øíq‘JrÑO¹wÝð^,òñd;@슘ÆJvEÀ=‡#®GKïfþ3p8’È¡8=žXjCD|>¯bM‡céã`äK²Jýë.ÿŸ¸*6í;þõä¼{cØ;0Ñ0ÈǯÕ43VÓLo—VÓü ±¬oûu`üðyžys>½²-—¶ Fž£&™I÷2ÔéÛ&‚5F³•CÍ_ãwDH òmÊnCÕM±ñll„ƒvêYF:B&Ù@ =¯©õÈþQ%N7«>ËÎk¤–¥R56«^:L¼ùL«jdzvໄ$ýàû|þh0m áØæÍßüTºm‡qv)‚Ù%Þ̾N+BF¡¶²O9£ô´Å^5"b±$GHÜØ¥ö”ôÂÕM¤Hÿ<ç1côÌ#–}‹»e1½pKjd –Å”¢‚-ri­}åq’Æa—ÖÚW7È3w´•ý>¶¥Ž¤á|.Cîh$ý¡]»#)r#'éãòHê•ÎÒÇ_ÜÈa¡O=í°3E›Ù!/•.¿›ÊA)­÷äòÎéó—–UÛl]÷@›‰Ïzù-åÇw›³d+ëͶïëºÁ†ä»Íýùc5 Õ¶çl›û#‘§É.b§]yÙ:ßm—CNóà6gH߯55ˆ ÏmΠͳ äÎFäÜæì_º¿§^Œ¯Žžó„¤Å1T•ûæÞ¹Ô’!â¼%òâœÁž$¸Îw˜2ù¤ë¢L>iÀ·»±k2üz|¥Ö8/òŒƒÕØ ^ Ão[Aò,²Þà;,’çã¢%ÂwX$žÛÜy3ŠC¦Wä”A á-=Ï9ÕúYtâð?YenzÃ+X®ø[z?jæf•‚މõ³jÐÏêFè—¢·û¯&Ô²|}ƒô+(FÁinо®Yn+RIN‘s]ùgBH Þ*I©2Ôcùeleþõs“¨I™Dq„L`e0zŽR=¼h?,ã–2iN“K­Ÿµ2ªÅWÔíï!S/¡VŽß´ÔÒÁ Ø$”ÊU’Ls¼¦¬®§z¬ñ}ê4¡‚–¦"%bÕ¬ŸÄCå‡AºŸBçi'küc¡Î$JDT?Ê"‰O¬9Ü€ËzW¥äùtlòÑBéÁMIÌ)±Õ4ÛÚMv[°ÐØËû42A!ó>m)î€å‡HN ó»¬7Zûú@•zD”Ѱj·ROô¼ÁIÕG6$•AoäÚŽüôF/|ÆYÙ€5½yG~Õ,Wºv);*Å_?Á‹ŠCŸ¹"ùA!zÍHªÊù²+„ºfφÃ5É)É/k§:?©g#‡UyeOãÜ¿ójBH_¿×裊ûäe/Ιø ûÆlÊÞŸ‰ó¥CÈǯүüõª}W3~¢ô\É×Å¥·äBÉ×Å¥·äZi8 OÛ¹¯ÚÝ\z\ŠWíàLoŸ]±²)sYŠÐÞRz!Ç%uø» !£s±¥LŠ-Á\z^ˆ-íRliCÈ€c©’ ±Ot¿]ðTÓ”}¢û=$¿1h¯m RÔbtlcðU¸ 2úõŸm^#òŸ¥÷+L¿•”Þ/bœaßGïÙc±*м.‹è²bKe)òÔwßùQ¦eR~ýq¼Zà+¾?®“WýL^ìŠ÷G8y•©äFƧ±í‡yÉ+ƒ '¯ø:îN°»h©6†±jrøõôW9Y!•rò46¶nc¸?ˆkÚÓùøáe™•øšÄót0jнÔ`,¦ !©ï” 3–fÞÍ4Ùƒô œµ‘(ú¡½DÈÈ2AºÍ&ÊØ³N¼Oˆï4òá¼bKµoŠ“o±„fy©­EJ?!]‡ê?âÅ¿øË äÓU-kKOŸšlêŠÚz?Ø7;O#øìczþ…}¼wyâÔ*–EäÔJ£ß®hˣߦe>Ë`‘÷ŸþTÄñ‡7;Fâ>-Ø úoÞuk…$H‰ƒì?¢k‚#Uh»¦:õ>aiˆÈõûÜìq’FÙ‚eŠR,‰/R–wÏÙ` ¯¨ß[†s»M×Ïóë 4¢a:à ;yÝ}Ò³^=Ã÷ulh_Ñ¥16üzr„íÞûô6ø•' øbú?*Or›BFA"æî®™†(›Zos¶)>=+µµ!ôã(¹E¸ ]øëõWÙt‡öE‘cdÀ)‰Â›Ü.N½@Ì¢„\Ìdiu!‹'¿~4ðf¨¿Š诒ù÷zw=î‰û«´H‰¢1µƒ=JdŒ,1 Í.ϧ¦h|ŸÎF‡ªr¡q]-Ž~#Žpd;­eŠïÕÈœ B¦¿=…:Å—A²Ú Ÿ'=Kc¶|½ž%ûæ5;áßÿôU•‘y3ˆU)s;'ñmlëQ¨Lè…m=ú>ü®¡ãl&9›àN/í¥°üzrIós)”$Ç”ƒÑ6[†¹á|âëˆä\ÛØOFÒ+™zE‚…•‰¤Aì¨I°BšTÖ’^fçn&üŽb”à>;?õ—$VOi‚ ”QJoáÃé.(>P¯¿H5ËÆ·^ýúgWît^_¹ÍxÈjøkå âIýE?n耧4ÔÏɤ…î<‘áckSŒ”FW)ÆÌ¥ 2¨jájˆI‚½jn†Pr1î"Pç°ÇRòÓAíhç[Îë ô‚v.>Öadt®*ͯ5J\ÁÅoDú2@îÅmJd{Ÿ^{‘JSCv¯çyË6q®âyj¾.ÎвËÛ>Ñã~Ù¦×oFF¿Kuâóؘ©­Ÿ!-“>.Ü-Dø9’ }Ы½£õ¾#1‹µ˜ÑJ1òD+­ˆ.cö×Lù£Ì”á>ÚëʘoNë*~f²Ç˜Õ‰wí»-3 Œñ>Ûßøš^;¡œtFp,Æî ;Âã(rŠ5é;°r6H Ÿè¨R#‹·8ttoŒ4k²?u>FÄÓL,N©¹‹ÿ3QeÝX‚’Œj9B¦çD•¬é¼7#¥dÕ,f|Eö±ûJÿ6‹ô£‹?HwØ¿åØ¸_wß;DÔ¦Äùm–q/9FF¿ê™ªÔå©gÒGô*á/ß«„>Âå³û^%Ôç¼JjíUÒ!dÀ«¤“^%IÏNeã¶¥.ÒôŒµ&=¬!éýª!Ú£´Ð4 j“s¤úA}Uøƒ6¹¢´´³ÖRzÌkš ½.†~\^Ó£Xº3‚nÞd’ÃùݧX³¿Ê!fG±Ä¦Àr4¥CÎæ‰å\vg®Ô9Ïè/îUCωßeš‡!é‰{Õ Õ]Yæžýðß+ík†Bâ8Y¿OeøÉ |Mrâˆ%N<ó‡åPñp îG,ñëå0åÜ:bQ§àþÏúGÏO¸Ï¾ê÷R"dv)qs)½´•t^4}þ¥ ö£çíBíQåmy¿ÎÛl3<ïr¹%“@Îê]()2Ɇ°¾€PÑó·Ô†)*@✕"R½°>+>ÎF–>±œ…Z½@v/¶¯e; ‰×Úê#ô<½ó‘w/Ž‘Ôk™7í~¼ûˆSéþþtév®Rà•·X¾«|[üD‰oïÞh~~7VlÛ^F><µ2Y骕ÆñúL+d¢žÄí\†fæ<GŽy«³!U†þ¿”íJåM¿mbiX𛿙~¤tŸôB ± žµ€‡÷úMÕ¶µ”¸¦jÇØ”,Òcü§Eš+Ój*ŽÛøÞ3'}c;zÁrܱAžóÞ‹þ›²}>¯±'—K=qn}àt‡.±,TœQOœ[8]‚~òqÌŒ¤ÒVæÙcOœ{U­Ø¹a9ŠqKˆ ÷ãÖ¥×%•ŠÊ&¾n+BFÖeYݧ¦®M¼÷ùmï3ö8–R­ÀçTgE¿±j™,2úÕ5PÈb+¦õïš!däË(jNX±}§×÷Sv#B:]ƒ—õ¢ŸÜP|Dð‘ÔYŠTæ×‡ELåñÛÛ9oN× (îF±½¿M63~¢ÄÓ 0[ëªiZú}ÁOôð|L_¥XDúQÎ¥!S¯Å¨´¿>[ý,ƒÔA­t0éƒVfö­Ö ?‘iÈYÿ5ª×z2‰à“¯ìP¶D–ÖÍÇÈó\©Œë yÆ IÀ£1súØIƒFÜPÉ="äIµ§ŽHU1u©2âšSöæCÅܧ;u+Ûöi²¶j¿CÈÈÆVòŒÒÚà¾-Åwb#Bš^Ÿáw÷xŸ¶3ĪZ«‡Óº5È›—õÆ|ôÏÖª…ä 溶¦]1}…÷ÅñéÝüïþ¯¾è•c!;0¾”óá#]=mTÃ]!ŒÖeÞ>/+ln¡Éi©áW–ºå”ü¥Ô.¯þû¤¨ej-™þ¶gëB™b²å™…zD·O®i°€p@tûĸø-מŞ…_}…2 ÍTÓ‡·I~û¸;}³¢`˾•™„D‡(©!žÀű|‘)¹pß(ÖM¬´`æo‘’/¿ ˜\o¡’/Ií¶Ig !Ï{3¤ÛÍÝ1r¤ÜüŽ ’`¸RŠØ« |f†8—§‚[äé¡Éв!¸je?mñÙ[„LÑ€ ÍHŠ©ºékðé¼Òâ£0#j’$‘´½OíA’$Jíá’y*£$ ;¶7˜áI˜;UÖ¾0H¨$ôKª™äo ؆e†+p% ^óš=Àˆ' @0I¼¾©4¤îº¢îxýYàÝéÙhȽæbaßö5~Æ|èĹ °ÎûØð±.„ÔW矌«¤8…:Y °4™Sá³¥³o¾EŸ“²Òz}ú9öúÔ"Ksqwr%7[)ÙÑ2·Ýe¥fðWïΊ¡©9œ!yó­u~JÆÆï>Bq˜AÞý[mº#ÚåõùìŸòðœ†,ítûM`F:Þã^Ž_VaèÕ§Ñêz Ê^¯eÅP——•¼jOcŒVCóùV†¦6.¦ÉE:õxÛV,ï/†fPS¤ªÎ4ûÞü]¶î[2 Õ¾ŠäØFÐufëöz½«†ê¶¹ÿ\ý¦|Öž7³ð«ñ§º‚‰ÿŸÏc-•ÉêÃÜ î ,w™oÞ«²ò  ËcªË1^}²)võ_TÒµégíÆn©K5 ”'Ê¿Û}‘’\®xiáQo‘ÖÉÓ9Âg½#¤=K5Mc[¾¶I„x+g,EáVõÝ'R-¤±IŠ iIÍwÕªÁ2 ˆ˜y¬Í$½ž¼{k4E«~k »úÓ$(˶#.’¦±”‰Ç…BÒ4œÞàŠ‰ÆŒ–ºŠIu¿Nb]v^:“¤1nk©Ñ q<¿¼›¶³*6u¿)ÑŦ™Ä=¡$’Þã⊠”dIÆ ŠIv ;€R^²$»„n[Í“¾Û´É®gv£\žJ¡w÷2*Åö…Z#Œ.ƒWŠ-S;£1îR»m ÍÌ«@Z£/-ˆ!ìQx#/­…dÄ^SU½W´M\)öYù‚𿯤³P“WzgK;ã1³`ýî|–ºèTtÑ¿dü·‹þwÌô\TG|{Õ!žÈÆI¿ý>¨q"gýöÝ8͉Ù8ôÛË®$¿ßÞ óP¿ý2¬ø9oÁ~ûÇy?ã–Ù‘,É¢Šåž,q…õ§$Œ;0_âÃÌ’-m¯ùXn¬d¿\†ØMú«íy(·“ H#‰·' …3_´dê²l®ª}ñYX®À—M|‰(ÀÒeUÕ{_¶½ê’hƒé?ˆ°ÜGó§àŸIƒ!Aàû"ä)_˜=±JB’¿ˆUöŒÌ Îû#i42ãyžrÆ!2Ãd»QßCdÆ)gœGfŠ#3[6íÚ$¦ýÑ=×îåÆÄÒX–Q½32AÅë½#dâü ¥œ×(¡¹¦oZ6ÉÂmfHœŠ“r%EÎt¿o0Ÿ4|ÃNR÷‚‡„¢¶Tç—i~à cSƒ‘i@brœûÄ/Á?äåwÉG·ºÝ±—&Õ6 dºe6VÚs‰Ü£·ÌV€mCîá[q§r~Ë8‹šœäúÁ^BÑ z pÊéQA¢×¸² ”šœ6§«ç|);K^ɸ)O|Ú–°]‹'/‰™•x²°~µxò€iˆ[ÄiÀdb€dîùú"¿ ={º7Ê Øf Yœ$Ñ 2;å@)[¾1÷œ$Ì"ån—CÈÓ"Î^qº[†’H'køã€ÌB1±–¹µD#—~=¡ùQ^XrÄ ßOH'Ñ[%gW‘m¸aé-ÊÞ¶­næï‘=)c v½Çµj@5„xåòçå0K^üyùx=žÌ.lùFž” ¶|ÿúIùÀ`ÊÀZ˯òÁ–à1i@ðV|{øšy“Y“éÁ!Oóe¬ž/NòE\Ûp0.íTó!3_ŒNSÓ®ÍPðgï}MŸ/ñßC½p{œí‰<œ5ÑsVºypMôZ¶Žë( ‡_¿y=ôv–Úé1ïEÛã1ïçÊX“‰ÊSl](›¶ÕÅ‘ëÚ­Ócf(S iZmÏoåVü€Ä¬}ªÎAŒÙ,Ûcvk)CMZDû2oa Ì{…ÇÌ|¤oò­˜„  ¨IΑ›ð¡{<&õÚLlM¾+‹×R"d+DóyJƒZøNβÊi,uþáPlÙùޝä2n9=Š¥4Zýà5U›çό߈:±ŽÒœuÓ,ÙƒK $0È“}´Ê~¸¦­ÏÞGÞŽ;ÆÿåÆR]f¶?Ü,åÁ†´¦ïŸSíÞ(z‘RÏriݯç>uÇy:|$¿Ee‘]—ÿÄ“­¸wÛ#qor»„Ľ…ç‹{T‹{Ë_÷Ž 2 FöœŠúõAܰ‹‹˜ÝN}C_߯<´sTFóBÜÅOa°-Ü2m×Îq*hùžar˰‚—GÿR*!S8—nµÔúj[JpÚÌÈŽ4+CÈôŒü½,Ä!kkíDªKh¡7È€Œj%eTñ˜ô¼AÅgÁ#kP™È@ƒŠÏ—Gn4F„Á™·Bò`{¡˜#ƒ ¶Ü4(,êM¢mœ¼Â§[LŠYYþv…xÌÞ¿íš{çZÉýòS…nÒœ­ßoñ†ù¼Gd ZYv5`$"± ¨C»Iþ†`UJÓFÛ6²`òÚÈ Ò“ÏjÄ9ÿT,²­ä“@„ç‡1Û¶þ¶õ—!dný+ÝgÌF­¿ƒmýÅ¿žy$ &ËÈ…]±•­³cöo“𮚄ñ˜g¤³iÆcš"º? b`d½%#]É÷4–?ârƒXdôô™öôá9ɑϱiŒ¥:ï=:›ánºž…Éë2pÇIOÊý:EÕž@½Àøõ䞇꥜»'POü¾,P? H Þ Ó¼s·–"í[\eáÝ#}ˆk•^.Q®Õ ò†ôrAípúÖîleiŸ–Q‘^"û½Ñ{.ÑK”ÖÏó¹è%‰’¡9Ÿ‹^â>× |.z ù\’6ï¬cBF|®ñ¹v†g>׌}.zùñ¹<Þ²rs>½`Ÿë(eïªÈè%ýKÙ´#dˆ8Ì«"£®IBg*ݑ֩ú¨/¯÷Fª ; kqÔ3„LlíMaÊDÔ|òu;nGHýëÿýŸ­Î2c2þú|ñ¯;¾Q¥ a2Mm7¯ë<#$q§MÓèÀ·üîLZÔ=BR×ö4åÿß~}÷ó<¼ñ¯ç~†QWìŠ;®gT±ãw¿ýv0Id?~XÄ ï–¨\M’ùõ·T)¶h;ó:ÑËN‘­>ÅeÄöÇ/½ˆàd„ ž”Ä©Zø~Ÿþ…ª¥T)ŠÚ’”³—pwëz}ï jigGÕB½&S>ãç$aŽ‘¼mPXf²ºw*öÿz„ª…y;¥w“JA©¥—ï#…µ»ãz‰ ½¹þz«`¿Œ «`ƒÐu-ÖVµµ$z–vØG®Eà·ÙiŽ›O×"pRQîû|4Ì|.í5Ï“£×$DI«+µ¿î9Óˆ73Îó ×°:+¸¸{@íߦÖ}¬Ÿ—¡ÿºóóJ¤.¶Ý‡õìÑÞÞ¼’CeGo,9ÒØW‚âš2\¨ ,__±æçü3ƒ$¶T{H†ˆCx±3¤ñ'Qj&ï8ßGI.(õ·­Šaž?p†$—@”º]¥îò,J=Ë(õTõø9O<f<Ã|Þ1YÍot Ô˓֧œ§I œ×Š[Žržú¤ïˆr^îwŸržz⻋½ÎŒÑ«¬§hk ¡Iìœ/ŠÁYAIU\!ªji¤N¾;ùK,øÐI°oIÊ~ßE=Æ“Ó6˜”jËê›ËU•=?¯¾x/ !‘Í }åqòÚ{#¬¯¡ì©Ô±GÖ‘÷ FfˆÝ2½Ý»çGÍ«§õäš'{V￞ƒ‡m}Äíl˜['YI¾#¤¯b“œ˜÷Fjå dê·écQø‡\,øÉ Òìò#¡¥RœÒMÿU [e‘8ÈcÓ¡j%7Œí?gWTV€Œ+áì·+˜‹Ö”ÇéP¹ægs¿•?'9sÑw$Hs‘[ó…iNÿÆx«.?áT4õLj¹_¿…] ½z„Œì#pSó ŠýðØ@­8Í=Átµ–yÔ6ºzs˜‹ŒÊ®+ÄÅ}€bÖ>Ï0½]£<Ã-RdgxrFËíçna‰Þ®qžáâõ7Wr÷[X#É:àBt­p§ D“;êo ò$Ó¯˜æ÷¸Î\Ü·u•:B[½ð†~>ã‚‘¨‡›¥ÿ'ìJ’\å¹å–lÀ ¿ùAÆŒ!ÞêŸÚ#Œ¨ˆªY¦•N—™ñíbç³Ûâ}_¥#Ñiú|†Õ}J+y1‘¦ÏHr´~ýyAK§Š¯ˆ‘#׆ΰûé;3WÇñÉh ÙÔYqI³rAcg*ñú)†ñ9ÍJö`ûHÓ0Íjö 2 õºÚ}i˜fõö 2 öòŸç9ÍjièÂ;üëÏ£×WHÓ þ\l²î×ÏH²½ÙðמÙ-ؾž%UÓ… Ù Pº¶°øÒs‘ñ»Š¤#âQ5—Ò…ßÙÑ'ÕsÖ䟖»Q`Ÿ^gÉû6¦´«œgŒ¥ƒ+kÈ"Ûìc»ºq€ƒ“ÊäµÄVWUÕR|­wàóàÀ$dŸ¬É›©®»B&‡1hý.‰°zç‡ó|xµ ­\%= h>•ùŽ‘OÏG¢Õ ‘¤½ÚqYš!‰÷5J£_ÎòÅ<·¾vÐ*—²]fühÝÛii+Xç“ÜÖÈó–Í„‘VBöçã\òRè;^øz8Ó;´#Œ2è?Íwl|ùFBVÖÔøU¯¬|£/¾}0L‹ÊNMË‹·’E8ׇÕ²>"­+îÂ+üžÜ½Ù ûš®’tB9oGuÕñ¹Aë¾ô¹X w =ŸSË;5 A÷ýøößlm°¬ºÖh}µŸV¼ýÅx€Þ}h'ÖçV&kÛ,É“-†F ¿£gÔ|Q/§êÊ-Ç7+rÉwe…ÁDØN·>¡&†&Ö}"¯ì' ­vÞ¯_G}øF½² ¨ò*_ævnGÕÍßÿÓ–*|õ"š7ê[Ð/†´V˜~a5Tíö†êp– #0åŒÞ7:±åTV³0ò\ ^2\Ýž›=„;%a+G?1HÐ9ø™Ð×°oùÚBjé‘acÙ#ŸûÉ;2ì ëk£u+ÿógðÔÍpø†eÏìŽÍ½|Þ ÇAH–‰w¥©Ý1Ó+âê>»äΙ Áè¼~õ¹’¹ãn*KÑ@üÑÔ`Üvüëɉp•¥DÙ…“ˆ¶TØ2l©°¹;Ÿ„û¸±T ø˜ î¿Ê}§úîÛþf¹¥LÛ õʺ¬´œ©ˆ±gþs»?’–vÔñ›îˆÈuX­› AƧ#éƒI·OÓ AÚ±PZ9_Å Ó½Ÿò^Ÿóÿúó|x½k9 ’¦»v'0Hn÷3ÏZ¯ÍœùÂ-2B"{Hàz¬Š¼èw„Œ0¡^wMF‘¬oy½"¤“Êa´a¬«¾(ö}DH<*¨)ËZlz3 TGXþ¥œÉ/®·Ñ8¹ÅWÝ_ñ?Ä™Jö*â?ñˆÀ*ý¯k3Dü™ºN¼"Å>#dâG¤m­#ÒQDy ú¯ùøýÞµ¬e—oø˜jßþ³Ã¹šr&ùŸ'9‹r+9ð .æ B°¯›3Èì,[ÜV‘-¾ÜÓLÂò2RûóÉéDNvî;:—W3JXÒÚ&’É÷¸Öë|÷)˶­ BÆöÎ+Ï.ãÝÓq)o¸í™œ7VD]réÕV² fËÈ¥W['­)BžzµñÏ·¤àÕF.¼ÚFåÕ¶ãc^Hmp|E!¯6‘®-IΙr†c€l‘8rï %R|›{CÈÕ4§œ[‚w>½œ[ê :DnA[¡ilî+öhlˆœ6ršûŠñnè‘Ó MNswÞÛ Ql#n¤¤œ­î+öil˜rVmï|hçùQÎH‚ä3D•¡’û-èwNK.¥2íyz\¿R™¹”Ê\2TŠ—ãðëQÐërFÒ÷ä–Þô=97WR¬Ä ɶ{¢Hu³¤Hí°Ýmˆ\Vâ)B¼Ÿ%Ú’¥ÉýyÙ¬)0œgXÒSŽa ¬Þ÷°¤'EfUÄ'yjÁpãË.%з•- 3l«½Kÿ¾øk-ò v¡[o9—]|ص=’§3¯Ñö1|¡å0‰Gn¡W²¹ëK†GY¨Á;eÈ?oþÙð=} /-Sþ™øÔ-IŽR½u§ë:â_OíL†©ñöªÆ[³Q¬7#BêüX5¦í„“tŽa/¶7iÊûÒ¾*­zÝÂêr˜]Èb w_TÞd²,·õ-î*†F­xýè_#›_ÇÐØJ¯êéàވůeyã;e qþgB`3–Áj>Ouw8#€/ßRK?w`ݨL0TëѨp¤2Ï_B¿­öÃÐøF|Ë;³½¹ÛBS§£aK÷ʼ'_>ãáåÏ‚<¨tŸ’{Æ3èà+n×öoÞÔÙT¯ºïÍÖ®^io£pŸlê„¶kp]Œ³­³“(:´~- ]¤±û·Ý&Ø™<²é= „{€ø6`˜= ûŠ’=@20M,y¶éN¢äbšXÄD³;æãJHNìôî=/8­¸÷ˆÑy†ì‹Çˆ\ ëËF> ¯ïDÆY7‰² z÷^:«6eônÚ»ê9‰² z7•&š!“ó+êd­Ï"}s£S+wøvÃÆ…ØÌ~ÃkKò\bdr.†. {aµAP¡C±†p)#SêŸúÞ+sIr“{_/IîýÈp,Àž$ÑÅ7.%IüÃ]ðÌc<£,’$׿1.I~êžô‚oùF|k%lùÆGdùF|¶Ð ÃY¾g­tj›êåTÉóbünçlww)èf¾ä߉îRÐͼÁnæ$ º™ØÍÜ cð*.­˜™4†œçÂU’UFïùÇ÷=7ÈGÈ÷¼^‡!ŸŽ_"Ós-¥Vå}1‚«±A¯†¢Çôd å+Vûjz!dêÕP¬—™xBKÉ–7þõÌÖøŠÒ« eõ™E9’â!Ï bƒv ½Ÿ9´OÈ¡ÝB£‹ö[´[hlgø ÉY‰¬7lYój85ùÌ™ˆkó|Xñ­ÒQøó{ë;¿[èÓAÅ#5%V‰Wµß' %§.ñ­ïo¡é¹Kü<~_C¡®|È›UïµØå¿ôðTOñÇ%>G.ñzhS«~qÆaÝÞ”±/†Fç†òÌ3”·Ð8h(ÿ>¼Yº§x4”¡¼…‚÷|)óïB—f9\öžWOš×{7¼À{ÞBIØ¢blƒx^†'ð¸]×…ßF·@…n4BSÃ8fáAhJFzJhŠ"ä™Ð5µ¼!O„¦F#4QÄã~%4%+Ý3B>Ϊ~³šÂÈ¡)j„¦×š‚Ù5ƒ Mu/Ø¡w¯Êÿ+ì$#È# Ù— ¤o_J|Û°ÿýgdˆµØý,¢2±žÛÝÙ· sæ@š•>ñïX¼„Œ9¥ÙñG¹¡Ñï!ã_Kñ‘%y$“-Ùïöm, 2;±±Ü|Ì€˜/E°Ø’Œ"\¥ûëƒÆb¹ÓË"©Y&òðEŒà¹‹k׬µõñÛƒlEäí”ß»´yÏÅUÔž‡“H5ã HhC›!)€räE ¶ˆÔªAH˜bÑV%Æ(%oiÃ|EÏs±O_8>ëïìZÇe½×+X>À÷¼ZÁ¤F̈‘a)›¬KOOœç O¥4<édr& /‚G±ÚYƒ|@§°´£ù”MŒŠôÿðëÏSÑ›N‰Þà_׫Ϳƒ”Ômu5ÜçíRʆo‡û™]˜WÙ÷óÀå=*…P÷Î?£ “xܶn#£ó=N:ù@ôŒÃ¿®„ž`¥}&ŒgéP5Ÿç#,T=JÉ4Ø|N¡œ«[UgC7·åþÝBLM:-‡WZÏ6Ì·ßS«÷´çâ]"äéJKk¾ã·@Èø×àAeߌñ¡²H/£?E¾lõò™XþJÖÎcù“gö‡¥4¬ó—´.îWð~h]hFY| °&{´®3ë,YFÈøW¾IMìÎl‰x¶a¿‚Áb]è9þõ‡;òeÜKÙúÄÈ Œ{¾Û 0ƒ<á…+ë,^îPi$÷kÁ`×}$^tqTõX«Ï·sÇŒ.T=”àûŒQhJxw5Þ;®F;J÷›òjætŒ|ú™í-™™ÚöÍêÏ´¿Ò—ôë¨6l,ï«!Ýn¨gJUt1ìcÙ”°2<}«'eõ»Ô½—y{øŠžþlºÊS”æÍ<ÎMƒ‘ÄŸ8ï`öwŸ?C^ dêò_+…û)¦Où.›Ÿgv>u=7,? M¦¼)ut»Å–ù«›è³Ð{hB{tóÄMß5×TñƼÛÚvZ{ ƒÝ©“äºVFlP‹'‹Ç·R'䔪–êU+ØJ‚‰¹nÖCÄ,ÕVR×Ñ Z]É‹Ïù ¼âY]t•Äê~=½ªÅçw_rv¥˜1zsC$»RÌ8Œ )f,Üu€ÈEUTi|A5< öÞz£ñ…‘ѯ•¤º#ãß5”*bîîbzŸ‚öóÜ9cß:/e¬ªMLO§i—a…w)½*×­˜°:Wó»pWtGT9OTD ²¯C12 *b ‡ó…ù‚èû9ѪjË÷Ä„|†ø({wøuò;‹$¾Ì…y:W™¤ÔE[zÇærróRߦø„ù·\(t½Óèb‚Cdi®&›ÆA3±+ðÆÕy=‹3KÙ×[œ³n)©U’&Á¯¸Ëónqñbš\XrÉ©O¨›§håQ¨Ÿúl-§(¨æÅh]¿¥U£E>ÃÝ.ð`UN}óÃH$\›l®ów°s5Ê®¤Á怤\.73yÖaÇ.UúQU§Ò3,u2%/}‹wûËMâ[‡Éi Ȧ†±èéÖÖ°ye· M?i[ ñbv¿”évZO$»_Êts3e÷K™n¯vs´s“ÎÆ"’b¤£ÂˉWͤ\ÅõoÜõ2³{ÈLrÑf’9Feº»×á<ÓÓœ³ÜGoŽ5»‡¤L7…ùz’…%¨lT¹ÑŸ­…Ì_¨RÚyw> ˜¿|¤ŽÐæ…7ŽWqf~¸¬®ÓŸ%‰[kÔòÑF-®Zœ%^]À·_ù(û•w ëgæ´‰þSýѺ²–°¹£uS«ÃV`mA²JÄ}˜2 ¥Òª-ŽŸÏµ‰U D 2ùåÞ©éªW°wdNñÆN7™f ËÅ÷þ* •9ŃlLIíc=ð‚a$9ŒAé+z½—L‡ 2u,k°È¿Þˆ_ÿàkÏÐÞ¡¿b¹w¼;ïM~Wo½ÅÊÕûû‘ìæÅÊü°S»ŒÜµ«†½ ІÍdjÊÆPFE,®²™=f%J c`^`NIÇÅ)$¹ˆ¨åì¶[Á¼*$ºKâŠ6öæ B@²4¼ÃÊ2ä“zŽOs*l@]T™¥ÇJ±üâô4F]Åí‡+Ê•bqEóæ¾÷ Uе@ˆQ%ÝE$ÐÁ4¥cÉüV!'ÕG1W”Þ®û(3DéíV}T«¢­š¥·û©%Bââ+Û¤·è¢N-’ØãÒ›o&y·Ýù8ZºîKg¸¢8,2ÔòŽ-6ßNoñÁæÀ2Z(gÉÞùÎ2ª¡^CÔµ‹à»Í‹29³EÇœ`‹šÞ.øúʘÔ]ûãÚ˜¬=ÒÛãcRwž+cRît•SÇ–8S%õ”NÓÛϤ³­.{-bÈ‹ÓÛ¯`Uo%yæ·¤fa¤S 0Œd£&ÕÅz„Œ=ñ3Ë™¡¢}‘‰§,¦NSqt(ýNíòq®«”·á.…%d”mäG©ÇB8«B:û•Ôc!œT!÷ºá©ÇB8“¡ê:÷Œðœõ¡^ÉY¾à_w2î+*v”¤8bä3$mÅ» Ÿg¨ ¹—ÝÂ2ý•Ú;ÞttºªAf§Ü‚õUнKï·0·€çÒ({FÈètFmë䌚}š>[â8£ÖærF!dä±L&%û¦tœÇÈ邚žñÔVÃ>ÁÊp¿#æ¢'2Ôa‘¡ôý!2Ô1„¼²‘ªAžJÄa‘!ƒLBJ33d=é=¾Ê¤¤Ò EÈP&õqõƒ eR w_Ç=(Í|¬Ò >æÃ1c¤ìøž÷pEÉ¥™yîÝ¥äʶA¾¤#BÆžfok–Ë:­-ƒ™*ƒt\L¹~jä´öv9>ÏGО½g!Ÿv× tk­ ZÚΓüò&•¹ÅH§3 ™®CfYÐt}·‘¿½ó·3o¤Ò0ñ‡ˆø“Þáñ\v†Ü+ò¼*VÖ» ìîÏ+¢€,éÂC"ÃȾ0Kz y^:œ¦,à¥#C¼0e!/‘fïž—Nê¬{lg‹¹šÖ¥> “@‹µÛÜÒÝ.¤ (@93~õÇ<§ÀmsHtCªwÈ)p¡Œ‡cž„ª"N–¡*Ho§Î í¼‘@ݯßÿjr2ºh9P¶î°mGñA¥ÍSøüÐqaï!£Âç EƒŒÏ¹Y§»pžI0Ý]dºË;ŒŒBIlZv©óûMùòœonÜbw,VJbš5M£²Cp%ML+†2:Ïé§©É{÷4?A˜îðJ¡æb©>#FÈnZ+Y’ÝrPø4Ho̶1fæòý,öºŸ0òéo :þý,½8ÉϾ1„$þÈOgß_m#­ì„L=dÛ«i9òS.ß™ùÃAÚÙC Y±°†âcé5á(›­²zµ´[¾¤»{——^Cs:~—ùðû÷ȃjd' -+¾¬Ä7ÿ{оµP6²ñËçêùé¨Q ),Ìæo³7ãááéžfèÉ”™^};–_~€>ªö[óJ±¶Ó†¡$ M=Lª3î“´VY7+=1“ÌD©Oq8jæt+3f+…ê¾ kj|®ZºÇBÕpœ‚¾KZÖøfEžl—ןÉÚŽ9mi+.Ý-[ÛÌÍ>Ž{P3œ'N`¿¿/hbI„9G¶Îëô-øú°…[WêÐå=Mßîðý?¤“{‰Ê†mnŠfn1”x£Ö½žÝ§ÅR‹=O„2ªžÖ¦& ¤·î:毹ªØ?ØH=­M¥W•õïcùúš_ïÙñÍ›ÊÖ:ØrØüÓW}oEq-T5æÿ'ϵ®•x¯XÓ«mé)+†Fçjp»”¢ƒ{ÁÊ¥‡ˆÛÌIHbY²(k¾»Í‡àN®TgQ·UNq6»T¶@È84s9Bw8Ò`ïoÛdïr[¡§74™YëwJ&NŒS¡w²¡É’"äYÞ4Ë9㠪ǩÇÐ;ê£P¤H”Æ·‹úƒ¯H”zFƒG…’)¥žÑà¹"ÇÇLNýÑ´¿ýòâ‹É?åïq~ìåˇŠôŒTŽÒ8ºÈë}•£Ô3Æ;W9ê0òDåHß%§r”:c¼Öþ.Yûp?ã Ö¾ožÆñSËsØIã$ð~Rý~î‹ùžkgµèQ¦ç¿ÉTWF¨];ÎáY c0‡“zœÃŸK{EÁy>ÿb”Áy’?e°0ÝÙvëλûõô²þàÕ âô²þÐu3Fë^M#N/ëÕÆð1}imèÎøû»×»Ef§Ú½¹óåÞa¤??ÐY)}Zqöna÷pŒÇƒö†ÒTó´7Òäöc£ì¹5mKþ±¿žx•4à*h'S<¨ã%þÊà3r~s¨±;Ç7X?á˜Ãg/^Ã!,¾®>èKœg±ù@xuER¿æ³ÐªÎñí'm»Ì»ëÜ]ŠÐd¿š ­õÜaQ,s½·‰t†´·ØèÜV®³“DHÝêXñëÜWœ8½®“ŠßÇ¿îñ^¬%I·(ÁhWkM"Oÿ̸±¨P¤®jY8wýšÄs,ú§Ü`ªN[‚t|‘ÑEŽiæ…þ™ÕF­Šj^Hlïø˜Ù¯6áxÐ&L‘ÛÝ©6!EÈm©៭A›Ð ãàs‡®kš$¸c"ý[#.‰å;0„Œ¼D°R/¨2[`͆Ëw„Î]{‚ªÇ¦¨ “õea|]ðyŸ»3Ó5Èghïà®Îœ$^/à÷ Ù)D‰Wtoˆ8¨~Cv·&'®6xö†ìÅ¿nÒP´~xU½Æ‘»ô žÈ AdUäõˆd|ðbŸ^Ÿ}p·þyéÅî5}“ç¥û@9FÆBðëÁ*¢ è!`JÒ‹æ´|š°Å&Y ¤¦²Ù¿7î~:âàIÐðÿ„]ɲ£0ü¥g0û>1ó bcvˆþúÑZRaàÝ3X„JU•™"¶qÛ¡gIxÚþµCÀýbm¾Iô‹9œ ƒ¢_ÌáÜa&º7‡cÐthÏï¢ZkŠjpD‰ü¥ö÷ËõÕ"°Âeç¢àøË•ºU«KwI%¢ #¯ÍáÞ‡çLήeù­ÁHò]˜s)cRX î~U˜—yæA ‹q„¼.Ì{ßý¾0¿§äEÛ—I|â ø†Ió~ȇԊ&>ÉÏ‘EüÅ|šlÃ¥A¢mÛÊ6U|ìóþ £äÇ+k 0¥i“Šƒ±ýߣ×AœÐs\ãë¾oŒÄâ„p÷ù½÷Ã!CÏÞ²PÌr‰yÁ¡u8ñé€þx²yJû½‚ñLîžsèû÷ˆ¾•¯Ñ‰îšªœ¦y•6Âî*¦E¯6²e°mùD’Ú¥Ab2Ë·AF^ÀdsBéGœø>lÂo;7¦Ë•!•tÀ™ºoä$ þ«D ï.â~î8~ÎDÏä?š* Û˜ˆ¨« ¬| ’èÿ]ÿŶuCÄwÍÚB5r’¶Ûæ$—gw=;‘“48Y•EìòÇQ‚}CŽü9/Ï‘;Ùo`‘žcè‰R·‘WJHóîJuóD i\oSìå/ÎÁíàÇ_ÁÝÝ]ÎFÊ-¡—~¥F 8OÉ¥_©QrÍ¥_©VÚÝ&ëù•ž³ó!ÀðÜ=1;_²Þ}v¾Aް󡬇¿°óaÃ;v¾çylÑYLÏ;ß oØù‡w¿fç»nƒ8¼eçïoظãðŒ/ëyHÃìóP½Œ\õ2º¿#ºìe䪗‚8úʯ™˜~àË»pfgI_²oÆû7c¯oæXtö›Ÿ3zVtÈ‹¢3ó‹Îñ낯µÜ&—å‰ï˜QT2Oàݽn-Ü“1Êî¸×Éëç—…Ù¸«´KÅ#ý’¢aâõRb#Ãoæ"—'É¢Ÿ÷ !ŸNí¯0gø|“NEüøœfü˧|ûLÛDz ¹ùĽ~Kíœ ßý… uò#µWñ¨ë†à’©PD³/h_Noñ5ˆln·šðt¬2÷ǽ~°ˆ.RéÖ•‘²÷ð˽<{,­MPTV› oÇéÃÊ4p»¼érуÏçùxUÝî {|dë£~Öm¤Töæžõi#VY÷Ñm´lj‹*m€Zl¡Fm^¯$ÌœºûV þ\áQ}œÈÍ˦ɱðG}¼.j4âX¤[¾t98¬Ä·ÁT!‰:wkW¥¢kÞ. íó¥ÿ÷O÷s©¶·œÙ =—8ΰ(å½+þÐR)}ˆÇÜ·adp¬>ÔÚÏj;µÈðDßfMó4Ûó!¹ÐZ¯%ËPuŸªBÈðú`áþæ3çz£µß iSXCÙäur°Ð|~¶-úUV±(yEwΞBAòŠQ(pß(¾U(÷ßòJ+ÍcÛ%¯:ü9Ÿ(Õ:4±r€‘wÇ…3NÍ{pwÇŠÅR×L«ª‰"È¢áL¼êØ™Ï@¿Gr—HPu´!ƒ+¥ÿBÀœ<îëh`šxÌÍö;Û]•Äó¯³~ÓÌÄMéNÓ´‡Ìa´`JÓï0§½Ø‘Ç®Ã×ô3äôT¥¥nËuÌ ¢‘Ç «—Ou.§(¾fä1Õ eÂdëßöýpÍø’©>íùºdªïd‚L’´½¤r¢(ܺœ¸Œ±òÅ¥ÿyZ–*ݧ§Ùmþ™µØ·éÒ~:NjԚψòÌÍÐÀí6›¢âÚº^º…vÍ\4=††ç½’âI£e¡àŸN PŸÛ×umxFP¥<öïÚÃH™ìºíÖz}_Z.3vC²ÝTVJ Éó—B;,÷Éó—B;.’ËÎ1~(´'ÏcÛ”©˜)S-vyòÌeªA˜ÜD‰¾ì„ÙÎ{çŠOIt™¹íÜfâw­ø–U`æ›8†ì >Ò]qÔûL’䦧µw$äš2-¿æYd{FèjÀY5q$Ûïo¤³ÁB†Wf”Žx–«À…k3J„IÈã¶CfÆhÊÝa_V râ`èc×RÞº»G¹//GëÅååHðeö‡{‘^îU(žª-…Ò ão¤’þúFzfŠA)—Ñ­oxÓ| üCÞKUF]ÐZú}žšOßxB¼¥‹j»¢þð½+ñ5Î>N•¥•=/ª®YÅ“bèÃfÑTÞZ¯wu•®žpb\ó>ï»J쇫FßÐ"/ò­i¾ ñ9ËY²Ý4 ¿cÌZŸÙ¸L²g¼&—ine3凉ÉUš[²7PšÛg+•ݨDHöðçCD£§¹wfߌu3¶;œB}^¬uq0½‚ƒô{Ø× ¯»k–$¾³Ž±ˆf¦«±ÎX;îYfûÛ®{ç-+Œ… :Ì2ê?Í å7âœuÎ2ƒ†‘ü×ThõùŸf½u¦ !‰E¦êϳ,çž-5Åïî›I+…aU3­‹wŽÔèÜþ³1®õÒú”ßßÓoÊpm&ý{ÿ¸É'ÛéT 2J7)'‚ÁU?÷äZZ=ñY?wÖÁ±÷𣑶vkY‚¸‡†ÚÆë&'ÉÁ-Å¿‡âÕ¾{d7¾¸EÇÕ¤`€ªêYáªmúiÀH¯ë´*m7yº~Ä©rÂÈÄÖ)Li“\í½«–¯Æ «&ÆíK:×{å"'âÉ&ÿÓåZ \‰m›¢˜ õ›¸à ‰—J/\•ÜxwIâÝ2¸4ClmÐO³¡Köª¢®zýœmÕº>“Ž1ÿýG“ÒuªÈxµU¹Xs1ôy€äšÉ¯]È߉“}ß4ºJ‘ióÛÚý¢ñàæîÄyˆgŠxjÅ Twâ›"~[qJ‚ !¯¬8;—ü!ÎñÔzW,|ymÅé­Íñ½§·3ÄVœ¶â›(ƒ$—6<`£G|Ù„oÉ2¯ÇŠü$¿H–¹7J.Y€òüݯžq')ç}MßdŠӬʡå B®ß¤’âüRí^¬9Û^ (B†W­ t0òy!+Ço 'HÞá[´"‚ÇÏ/]cð=~~éëð5oºÆ`”?¿tÙ´°AÞtq|÷“®1n»ÆF„¼é›ðsÞ‰6àk¡(ä^£cfF‹JDáµEâ]µÈÒ¼šºœ#¤Ë»¶A —ûìUÑŒzvAµa–LíúY»Òž@Èã ­–—µ®±iž2IAœÒI)æ…®Ï˺Þ{-h³.;F[YZòÛ\ˆÃ4HoäË£žiåmyͪ+³ÉRÏ 2ñ˜gš÷%½éiJ)-’xẪªŠp]|ue׺á‘ÿ±:)ÔF‚Ú M×CÁbƒæjšÓš-í¼†ªçr­/LzL–*Ë©aÒGè²×•ùP]]MÃT-ÓŒ¡OgÜÁä?_WÒƒ©¨øTqüIuÞå?ÕUÍ³Š«VKßd5ÿóDw§ÕcáY¿N[ÉCîNñ1äÞC ÝJá/Ç_óæâ~ûð—cÈáš7dzá/Ç¿QrÅ¿òŽ!ðþÂŒ¼9†éÐBïÔ€áí¯5⥒'gn‰¸Vòœ’'ñD&¾´¥*BãŸ8KiÅÿ½‘½cžóõ•ÀÖÎÒ¡º\Šü½!¤·)ël†3ÄP-dx®“ã{¹‘ÇÚ uçX{®“3á9«Kú7ÀFÿ¸Ó7—d|BÈ‹í»Û-·;}ãéü­–\ès¶b G)w…gúœr£ßÄÍ1òDŸ“I§?©Ï¹!ä™>§Ü¾«á=áç<Ñçì´'¨Éçm{ÅO´ÈàFs‰Š*Ú$¸ÕP͘ ‚[ ÕÚõKäóŽïìpÍ'NMþW&Kp£=~y¬Ð‹§Ó—R‚e¬À›øRÿè´CeÔëfõÆÓIqXue«óÀø>oû½“â;èu‘Ï ÄóUµ=­µÑäÙ65fr€ýö\o†êÚƒwîyÓîPã9°ž±Ï—s¬gì3ñBŒ#ä9ÛT–sçkOß9C÷ùHõÆËÝ:gàu£«t˜á9ïÞ8I@îRCbù†X ¸VxãÊgv΀\øL¨=vàõÔ!¤§ðVšd´Ú·yMaç È·‡Ÿs¤òzÀoÃĘÊbݾWRg ¿Ñë»B,Ê ¾fré]1ÀÞo‡Gªq£Rs¥€|íðèÔM‡Ãí×eï n=îwß©ã.Ý~žŒ†•é’³®“Ñ£›Ëap—D‘.IyDq‡þ0¸O¢PHI†ö:¤F˜K²† é4qÌñÝ/’(L&Q0ò"‰’­^Þ8tådÐB¶*¿üSŠ•ÌΑ0D¥¢ï¢ÒŽ‘ÁuQé€ ÏU“ÅVCÝ»‡éŸ|îåÂ8ç)FFW"Am ‰„Ћ¿%“Rv_ên¬mßóqyWøš/÷Çë…žé»/}ᆭçòG Ϫ0ß–>ß÷}Á×$~-ÊdyÓ”à¯gGþ•]-”~ºO‡0ôútO‹oŒC¯OW‰òZ)¯5¶¨‡ûCäÑžÍÒ~qúÁïÿ¸¬é ùx¸êMQïxÕø\ຯţËèV«U/·"=lÌzžW‡H y­4tEwÛÛá}Wò­‘# %]ÖÏa\pyQVmÌÃÈ—ú½4~€z63p­•Ϻ•Å{=üSÁ¹Èö§_Òú5]Õºö^˜Ú{V×âø{|€ç±*'¶®æ@yÞL''µ¶¼ˆô`°Î:$L×h?ä¼wëÔµŸ7—´˜Î¡ß†®)=óOIÔ0¾q‘×tQn_©•²QÊu€Ë AÞÛþ)Lu K’!ÏÕW¤xîvä.Ÿ!ó²!ÏQ"r½uŸÜø®Q)lÇóùsÝÕÌÕ™ºAÈÀ;…a¼…Íâd9uëˆ!öŸÖÑc7åÍʨMå=w>ÙžyÞ9`©8ž3¼‰HÅ(¹èñùDÍ€~ß»TÝ™\”ûÄ¡ tæ|&ÝÄa†¼®ÿwUz†<Ö3¹åJ:òLn¹’ÎC„<“[®¤Ó¨!Î#ü[ä`yσUùInE:W¨}’ ‘ÞŒ›â&àkžs¼¨Ôz‚ôuäù¼üý§g²ÎäÌù¾Íƒ+Wù2éF*Hñ—|Ë xÜ© ãsHüu€NKœ?ñ—v–vу]kõwÊEb\Oº@—È+S€Så¿iÝ߭ǸøwïÝļ»?ïÎæ}£ç½»èÿ“(ºwzà ‰¢/6ݹ¶¹(ÖÖ||㥸3\0 ™wŒ^×\IÉRõÉÝü”¹— !ƒ³F—|É«í¹”ˆÜ5ºì|š02¸à1{ªþ$þ¹Éo«Q²o?nz•jƒÁõ{Gܯ! ×A²ýÇ$¼öGþy“pÙçAïßc1Dü! |£øà¾Q2Ý×(=¥›ó#‘G‰¡¦³\Äc)‡Ž$>òpÕ¤eùô,ú´º‰2ÞÛš¾…=4‰‘Ö*„äª2"¤ëV4Í+²Q3kÉVÁùº¨ä^½ ‰F›Ô±‹Ñ†b$¹*°ñpM³æ[RÝa4‰m/«úÂÜÃB©•°Z7Ÿ¦tÜg„ôܹ%›UkÿU¶–S6!dè2.…5¯Ÿršò©¶T^ƒ|z¢€h³Mý^ d„µ~£ž–ýTö;BÆÞ¹¿4‘øÄè§i ÈXkä #õ Îh7õÝŒŸSo̺O³4Kƒx£ö3åCHâMã{ ¦HÎÇu…̺ù×ÑZ0#ˆ7½7¾Mc—aèÃAM› c“ˆÅ?Í”ux}²µ‹‘н\W>•¨¡òþU-µº ®mh>6ôóÆßÞÐ,ävŸÛm©£{³ U[—ªZJ7Ù¨ª>*2 MW-S•S oäbàoNnŠ ¾<ñxùXî˜×ZîD/K£1%w¼€µ1q¼üƒÜñR¶ùÄ7m9Ä/— Ñ/6â¢ñw0$å5ðMÄ9ŽCÇ$ž•‹‘í‚~K9Jg—ºŸW†OMÃÞ5³±3 ÑoZ²Ra‘µéβ!‡¬J+.“4[„ ]LšË¦cm¤Î»±L!v"!jÔò*vgõ"Ã7Hd‘1øå/ZëûO¬ë¶fšð5c×`VXÎm9Ó­ó‰!äáp§¿û2”Ó˜¹â5ÞÚDki$KÆ?n%áA‡2+m0Øñtm׺Æ#ÿsQÓ¼.@ò¼4ºR$æÑÑC´R-{r%«:±×ÂFï±Ò1¥StÖ®éÂö´2¹ã…‹°q\)tåxžÖ¦cÏ0Ýwqö^³Ýeí§µ%®äzû–êÕ%Ÿv†‘ñqE6Âáç|ÝÔá9ãëŽ$\Ç%¯»Ž$¿ŽK^Gý};íØˆ¨Þ„$ToÕýéQ½ ñ+U¾CygÊÝÂDŽ.³¾ïøÞÔp´òÝšO|ÇYÞàkªïþwýŸžuFUÃÔfîç$^ÝQ' Œì­@ò6ÏŽÑUUiµ9Äèçç羪d3˜y]U²=sžfo¥ÿô2À5ÿOØ•$I®*Á+U*çeï»ÍúM Р û§ÿÌJImeµsC Aƒûå$z«=,‘ûW€©¬ªÖEˆ2;¹RñXá‘{cÊU 8•< ¯'õ\×C0€ÜÔCXó͘äR¬Ü#·Ö¦.½µÁ½±6Â#¿¬M…½µ«öì)@f;|„ObÙ°äõ@€Ogú{€ÜmiãésE y–ÓJ®? yªž ±rG-Éë ‰Ž…B¾Ot,XÔ±ðÈDÏÀî8]{: ­gßó½Ñ3ØH )ò¶«RÀµ`3…O¿‰r¯xá‘:ÊÔùJw<Ó±€_t¬cAã¯ù>dˆíSnÁûOÒ ¸)WuCõ_t9V`ÒË.˜*dvدb‚¢"ÌÒå°FÕ¶£G v¹nò¸€‘­ÿx•ÌöYÞÆ‘ùŽl¼q·¡‘§ߎ˜Ó _ì‘÷”ÿÑq’~>Œ±¾öÈ4Œð'p5𼏲Þr 6$Ñ÷ýÎ&Lú ¼ÂÌJC|f…ç¨ôȳÊ3ÍW؇§…£ ƒ±óvM%W2ù„Ä ¶FUóŽRžÐBz€Ì’¼£;µÛM2RR€L;Ô\^§ýH„Ôj"#@uvLœ[‰óµÄí ïGµÄÖ]Rz˜”ãšæŽãÚ︤S2W·½c®™}3Wë1 sõ×}™53ayûæ£îY¹¨Å›÷¼ñQ3÷{¬Ý×bÚg°äU}×¶“,ãúLv5ŸæY‘eè2ð<Ùù´á}]·| «GºÊè_ÞcqcR©œˆ¼øMí¼5Ý~-Xö³á”4ì&|T0Z·•€c¦­¶ØŠ5µÊcBÐ"Ÿ©`±%7ç#E¸.Ñ Ÿn.H»>MY¶A²ÏDóíÆìv·Oï:¶®t†H×j»'.4c—%);&ZK=@Ï;ªxôþÑQE¸€ÈÃŽ*-}ÒQõ,O:¿2;©ö$¨'Rv=9‘L…‰Èl?0|+äíлÁÊ»Igé¾å\Åö§ïÕª«é‚ýNEƒ­«¢T~¥ÉùŽy=$jðŠ„y‹eîUmsZd,g}máÓS! \¹dfÁÖõ"ß½WÔkV§'û£r¤aÊ·’ê+D¾4•kµ™Ï÷®÷MÕ÷ÈàÝd¯ÞÕpƒ§+Ûð8 _ÔHÂDË@&¡±+„OKÑû ¡GFU>³äm>³G8¯…„cîÜõ©²¬_8‡cîßõ 猿2 aõï}Dô]*Ü#7½l[Ï.¤»òõt7‡ÈC­JÖðíï3ædýEþ=¯_š€ÛŠÇ€¼ü£â1<ýzùGÅãfÌ•X-MlÝ5Ûä j«imúvKeçï…]¯ß±¨¦ö±(Jóà‰$=E»±¨9üFIO‘cNv}»ê7R÷.^ ˆ¼yd®#åÆ[¬álQŽÐi9D×p¡v\gé Ø ·ñ-B6ȧ?óP’ÐR^ÒJ¨“ _ÉîÀ¥ßU»ƒÀ/zï‘‚HX˜ùŸÃòDÌÍ—TjZ ¨>^×îz;‘_M8Èò~žç•q>ŽŠºd¯µÌx8º®ÏS&&Ú„ }21­D@ä•D$÷HØDh 5AÄJsǼ}_ÐtKªšÑ&Îç뜉‰÷ðé}‚ˆZ]·9D11‰@‚í‘ZfœŽ<3×W¢e–&b SïUäò}ÒΡéׂËr}o Smo’Ú0- [¸_!·³VyM ¶ÜíT˜A‡é@î6Bù1„o—Me®=éCž’W!¸w»€ã0ªmèæQuõˆÇÌí²17i3p¯+c!òqÔ ,É¿}‡Î@“Ÿ}‘á:s»l›Gý,¶$|ú{?¤Ì%þÄ÷ÌÎè Ô¡Ÿ~=-ï&28‹·+¨È‹Êͧ\šÏ"˜ {3• 5H]*d‘%×å³!|‘È…êkl¢ÎÆäR̺ ¯ûmÐHÈqÌ[§5e8än'R´ŽR™ônbR9»DJ± R@äû5‰¡Ù“û*äóÜYlWˆÿ6ßîB dAŒå]·Œ™A2/S[¾ UŠnF=@†Ó0¯¼”ÍÜ,êã)@ +¸eSð\í®î@ÞÓ«)ñã}«kÁ@>ÆmhWYãqèiŸþ „Vžm ù0ùÁ,—ÈWªµEèÊ™îÊqiÑ>ýíSðy¨v’B|–~ Î’ «þým Ï-‡BÏZŒ¦²Ï7?ÒŸ"”Ž£¹+F¡Y*êjëÀ 5ûĽNR€Ú½ôË28Ú¼SÎê8~P¡·”ìÑ×6˜±UŒpRm¸Äp\“¦4ã¥XÅfj뙋Y9CÊß¼ëÓ&E½l_ “ë(º®”Ë l³üª¦B¯ÑÉqÐwªrAL 儦©_tè®þŸMÁžW¤‹U†ò3@è%a†47TjE†øYYvØM5Åw}Ÿu:*Ã. Ÿ“NG匮!Âúø9!—š^7ŒyQ1ËÂåzôûiXd%=2ûrݰïæW×þš#©Š]mëµ£Óƒ×zôÈë¡\ «ïqn,÷nètÜ–ûiåÎòx܀ዙ'ºÍQÅ^ÃmŽªÙä¨÷䨂ӜôÂÝæ¨÷å¨à{æ¨xÌQ=îç9ª¾ƒÈ³Džå¨V€<ÎQõ3s/G¥+BWºÆ•ƒ^ö)kÚÓ® 'õ*iO»GFx¥!òº_Oe8ÂÓŸ§$^XÚƒnÃðË¿N:ÀM“H󔕲OÂ8SVÊIÍUG¬”j¦|z¼¨ZsÝæåÊà˜÷ý`—nÍ NÑóç8 ‰$g2ÌÒI÷¦²‹šÞ¯Ðç6 oZ©´›× ù)ZT$,ð5s³ê5cÖ‚ÚAd–»ÜŽó|̹ ó™voú§[&.º …cÞ€®®Ó>ê0í‹q¬ò~„Eðži¯ý¬¥WÈ&ÏYãêú=ò™ô¦Ý'ã¼ åÍ+|ÏWJTm%äZ1ÏÅP¨/È7¸‚™_S©îé9*73ÿsQI!ô’8uP~êÙÚãÏfÔ$:T»Ÿ~Z?U¾3‚uI³%ÎyR/ÐR4ñò¡!]R.ì¢K<*œã2xÄÏ+l¸ÓÔb¶úK½ë¸PÔp\±£ÆÑzkè°Šaœ6Ðg %¾¡§ VO B_^.7‰ãLÉs,i{&Ì^ÆÓ³ëT_sZ©®ëËÒoVÿÏtRÛozI,Ü96±®ÅKžo÷T"váû3[ñiö 6üc~-ã>Y°y»aÙ@aÉ–ùµ&Ô–’ösUBè}Zi(Ú@©WŠM‚¾,çrù8Âõš=¿¡UÙT:O¼…¾¨6}ØŒ:‹QÄ{»ƒ¦nqcU¸Õ¨óÚÓ~½Z·ø^'ÎÈ…—¯\¬9„^Ž KA7Ð,Ú% ¡M±."ß¼Àu:+(cè>Éæ­Ž‘µçíØ…¦IǵG‚N9ן:©Óoñ~Þ@  Yc™˜7cº‚ZS¸æ|NeÉæÁ—y&4€NÆPTKŽóçY.P_‚û¼Ÿ¹2”‹hVîGÉjG.wêã0»iÈÅYˆ&?Gt†ÖnøÄßèyNkK®ŸÏÓkŽˆ¾DÞÙw†Û0:â¹Îå'”Æ$òήùÎVœèƒ çKQħ'96תæc%¬ýÄÓ')&ÞCΈL®ãúk°½cù°®y›Û¸q¡Áb¡¹òáo­yåÒ7MÛ•]M— €|¤=Kô–#¨cËZl¯(|àçsjÉgd}ßÃ÷|{݇4*–¤Ù8äðÛ-îoýI–¹À@K2.ùJáã­òÃou0»Ã’åͨiØ2Í%„“óÇÚ<§'AÐDè¸b _Õ*?üYÿóe×z=•3Ro_Àleuì¨ÀÖæ6R=/ƒ6ŸuP;ýê¿êVÂAª~*5«V6ËÚåï!ú)úz€‹OçªW´…ŽN¤1@_ZUÏ€‘.Žç;@ߨúsPŒs¸ú4Ô,Ó|¨×j.榭Šuóú8wÐÚÀöŸâÓ •gµ%­–ˆó "o¾.}÷îiýù„$Í Êõ¡Êˆ|é_•˺àuLø½~¶‚»¶÷S­S\M¹ìº@Fo¾ô*)¥2S‚±a€c>RdcRYU߬õÒ‹Aä35}öצO(Ó7Âo‚»ú‹œ'Õ6uŽêNÀ§¿“Plmý2Ju¦r„O÷aSà%î*98ᗽĔ_eÅu]à$Êš9v›M»tÝ2m¢X‹¥†Ðë‘IñºÞ`¶Âµ>œ×¼?Ôå¾ÓR˜‹y¼™;hPGr‡©É4d×µÝLVZˆ‚M&@¢pYàÏW¸ ²ô`Åö´h9jjZŒ5†Ðäd­ì•V‚²TµŽð‡µÞüúÇȹýÚ#1ªSx®h~ÂiQy»^¯¨ÑvåzI-°emÕ˜#œoìÅõ€ZWs‚†€Æë²—1ÔaÍGºÌ#³olw'ˆº ‚Bìšø¤²“]Ýç!þÊ6Ê[¶Êx¾ÅH‡>Üe^ I°µΨœµU×dMq~¢Sj•~Q”1(½[ÃçLÈbæùLÄpårµÕLQoú3Å»u}2„Ã_§ Œr­:¯Ûw*Àx¾:ÄÞ¬#šÃÌß8ÏôÒø;Ñ=¶™rÂxâNÛ‰T¢ƒcQ¬¢5Ö¡%l'0÷Mu;j#“U—Öù|U‚i²™ ¯•`êç¯Täc7ÈÞóù s¨!I ?vƒÌäõ°¥=óu^ëå^ï¯fm÷E¼×D´2ûï3-cMDN’÷Ïa·i÷#¡÷}9­Új×y_ލ´ùDúeì WÈãà*`Rëí~{ãš¹ I 2MjÀT¿{ÉÙ€Y×MŽÞ†™ÔåyYB«N ásôVN©\å(%ëZˆÌ6H9Ztñ“›1¯ûÕe(ºyK” ‰»lt²ÊÑÜ„;Ô{:¶T+:t¬ŽO&D¨ÞÙpCä…'Dõ¡TÐÍ{>Ô:G2‡»Öû ”w·klâ{§¢V0ÆÊ’µ}Ù õ+ÓsµýµÊ6&EýaBŸšpB/þönª±,ÍJÛà¡Ãå¿þ’í@'‰×7ÃæBL /Kw),Wöé´èàf•Ü|:…cßbux1ŒèûºÉÑWÄv5ÓµÓ1ß¼ëc:a,Æb€Ð§÷v‘Q2ò 3Ö©ƒØõ¾nrô¾BD9Ešü[ð¦…P£×ǤRf]Ø,é;†ŽwØþAvë}Gà¹ÅR’XÀõ¾)U¹z…ìé:†LÔû~J蘳Ç?ŒYð½gºÀ˜=ÇS,£¶t® È÷sËÃìKç uŒ,,EßïôÀÙéÿÊ9óº[:Ç(IMþs[dKç8M ´ßÏ“~%]:'á˜ý®."YìBzÃTØ_Cdàï×ïIЩߧ™Ò"ÉÓ¾O3¥ ß"2¥”“hL’ÔͱL?\f_T{ù9>–5Ëî¢KÂäñÕ$”Ñíú€¼$Ô°gXus]!2;,åöª‘ ™¼§î­êð¾kgPúUwIÅë¿%’ r¿—T¼þ["¹‰eƒ—D¼~G"™ÊЫu‰âõ_¬ïtª*ÖöaÌûq•4D³ 3¯À“ö Q³4¢®çuO2Z›?†ÓÛ;ˆºV6Ÿ"³¤ÌÌé6Rµ-çR@l„©’>_Ch.++*Õ½¦È„æV[dÇ;×s_u@¾jFb“£ ÙÔµ¬8|Ïwð\œN«~: >ËÎ’sœ@³%ÔP‰ª¹)!ô’@Ií¡œ¡vvTaš'§°[N·9¯Ê®­ ôšÈ>c[É <)'{‚¿“cÓûkèQœÛ·¼ZÔa»}×»¯ñ*4¯“~V)¤¦‘š$“´u*µ‡-u1W)'™+ÇC¥.ô«r±úhEUÙmû]×4õ÷òû¤ýNÝ/d´áï/M ¹Y RW@îJ.—Ÿua*óB– 7× Æ]9îŒÒ}Ñ_›ð3ž Iøõ¹üŠJÅÖ•? ]aû¢Ú^)-Ã*MÄÖMná˦1'ã:³ òº¯¢•‚eN4´¿µHôùv}¢¡½¯^fþrÛö;/TWÎ |Èç’0©¤'Hc¹vPO$DªJ{UïùÉól‡¼z8¡í’ê8ïy8¡}Ä!=œ-òÐÑ„Aä-õÀ­!‘’öE±,>Ùt¹<¿Z|9¹ZcÇ 3 9eƒX¼WÓ™÷k ¡åÔV9YõIJDí©&=2i9 —ŒðVù«¤È;ü"§ñ1Ò¡^Š0æ h|Ø1-‰b£îŠÊoÉòKM˦iê»Oã‘ïã +Wþ² cè4(w(ÃÀ¹&6î2R ^Q·°æßÈ›çç3kÞ¯OMHJ|}ð%ûÙ*ˆ¹À¹²6XöIo—²ËÁ>RÖf,Â3D¦jÂ13“j™ÂŽË._ZÆnoê§ë6› o MuíÎ$5f•÷ËPä0ú÷Tµœ.9@>Òf »‹K†bç<Œ™}i¬cOeÎVÙ"Ÿ³tÈÌŸ\qLƒD¬£y…Ȇ¸§&„àÓoá4´ûÝ´aQÔã9ú–Y–4ýµ+Ùð#º êèHûí~kÓX±Bæ ‡|†*jgm« Ö,‹€_ôòHkmLÃøê/4K´Zu(Ú!‰9ß‹‚$¿{=œ(ÝM¼v.gÙvêüP7Ovèf$2,áLpÐèˆj÷ÒŠ å^’ ã ‰îreZƒõœ¶Ý¬~¬u€Ð(¼ü®dÙQ\ þÒµËÚ÷xý b”… bPô×?ÍÒÁˆŠ¨¨U^0bЙ2³qÐ…5¢iù">Y.¸õ×$'þyU„^£‘ó®1ŸúËüYv‹u ³ªF¦Üþ€q^±€Ð{̲2Ã5꼟¢wG ¶ umãQÐ 3Çðéÿ ¥}zyaòÔÕ´y!6 TæÆ*•k“ å³®!4•*—xÙÕWhJÓ ÖñË›µ[9¾á3€B©nìGŠ.¢[^âUÃÅB^‡ÛPÒŒüûóÙ‚ïÞä§@KÕa23ÛsîÊ~mà“…n¡ìØ4v@Þ‚ú=öÝn]#nTmÃìOµu2ÏêÇôAíàÐG­Õú¦ ¾0ÙÏQaaØVrÀËÊ.€›ôÔBǼ醩oW¸®:¬P¶´ç†OVfIÀj§pÊÏ€?Ã8ày†Ð|W¡Tƒ;B#ôS»;j‘Œ7Y¸¬,]Ræë¾ÕtAù¡IƒÙýä®JýΊ}|dG'AþI«qX%ÚldòÒ!t=ñ“o1‰®èzæ'¯º@fЇÚÔ2UGŽ‘ð ¾&ä”̇ºt ±Z:Dϵké2ù ]A#Ö(Öèx³oX?“àéIiØWV ­šù©‹¼C(—øž‘ÝÙ~´!©Ø°ŠÒ™ ü:ã{#¨^ÿºõK¿Mlmê¤ìnjí‘hbç= ^2É^¶2‹ˆOc 4ów9)îÞ¹ªÜ¤<•«I¹x=@z^ueøS&4|Úrž ¯¡¯®]vL½¥ÛVaø;oqO´dºüu5òUÀ³ßƒ+Œ›a´!Û¼uxH}“þSÕU¡äµmd% \ùãž&Ê•Ó_Ò=EÖV 놉°•Ü¡”Ú t›O†ùLn|¡Jt¯d°ýÇó)ˆ–î{’.THQˆõ­º£¨°¢øLlÈÌùbVé ¨.WžŸe? cWI͸À3¼§Eš³ëÑ×ʹìèQŽéí+zYäÁf8‰e"VÃ֯óÁ™ÇßÅÎ9¬ì›§‹õc%/—›‡/lݺ~È“QbÿUÎPR+~SZñ!»>Òç2„8N::%2 6šÖÕéÖ–®Í»ƒÇÌaI/ÓQˆÌc5@ÇK*Ë­~2Ÿ?Dú\_ª[rK¸‡Ç¼Æ5ß®3Íe±`ðw:fçói0%O®±• jƽÿŸ›Î|—iÁjqw¿ô‚RV¸”…Çéš ajM$8/‘Õý7m«ï·ûØf·‚¡·òeÇìþ!t Eª__Ôçw´÷û\¤åeeí/k?¹yíè$-õ¾õÑ@°¥÷ô_3yÂ8­? ovÈ„ôªjï¹6ù(‰Å¶ Ú.H$ú›íDžØ.ì¶ Ú.8äí…¶ Y¤®_†È³ 7­èžoˆŒë‡FÚRê-ç³gpZäÁˆ•òW¥Œ{u2‹<±¢J¬íIYÄ\3Þ(õIÉÂqxÌ««œé¯µÍeXf`ÎGÍ!o0øW‹øÑÿþŠ"ÃV—œ.wï~­ˆ|$¥«1Û­üOjŒ†ä5Ѓ4Ï·­ñÉTn]W<ïÎ9T&òS¶¤ë%=½$ŸÑ-dñWt¦-¢-þš icLE¸¡yjè}'øv‰Tm¼²¼eß¶^´^µã©Ú8Åv#¾¥Çãå;ç+‘ª Tl·ãñ½Ï÷¯)w!y4´l¬‡ÇÌ\䕟Wp‘—È3µ–ÈEÞ!Ñ·­­¼GQ¶¶þÚo [[]CP¶¶ Q4ÓikÊM¼íG!à13'E€MÙNêËžv2MƒÈ<å›CêpE÷“éõ± OÝ‰Ž”†ÊîíçÔmxùFÔ šÿj¤Uq“‹´2ŸH´«´tªÒ¢´5«©â™%ßÈäéÝŒeMÛ½Ó,þq'àï,¾å£_B^õžAi*¿ÆÅL‘J)êLÌ—o—o©gëuÒ`2ö^úÕ"ïÉÊ®§®Xä#!f«Â0v”ž$dØ&]n’GdØÐ' ºŠ­áìQØàß;0©ZÃäB¦[vøvèÉ ŽEÇ¿òr‹Ã†ßh*E" Á£Lç2sÛ‡vر¾²ÃV>y?/™GH7íÁ‡‰V¯=²ˆj†^½n ïX ‘†¬§Xué_7 ŸbVŠéÕF®ó×ødÙêâ ÿq.ÿ £²rgEæØðnT¡ÚÉ ^n‘²¼ª‚š´Þ»²}äóÈ´R½ð*›ò/ü-?Ñ㦘„JG¤eq Ç-ä>‘ šA5h*¶?{è;׺åfõ¸åÆ…{xÌ g4êåœdH¿äõ»íb ÒÄ·’Õzܬ"þÎöÁè°{m‹|D6ribÒ¾’?@¦œ®X|+`×¥q,!êºî¶1¬gUDäKl;¾­ x† oÅN#BýÈÖrÀ„Ìd93ˆnã3·ëÞg= °|Ä:•~€%VçØ°4Œ—ƒ`¹]Ó™¤ Y¢'ävÂÓ£êÈ@¢ÔSG˜ofÜÂ{ô„`ž¥ÛùøüËo±·3é45>~ç=‘íkæá,Bps»'79#Çæk ‘ÞȪ> &H—4/܉‚-ÓÓ?ó±ˆÁ‘ØÕØ@$’HŽ«¶Œ¯÷æƒêûÏÁ桟yBa3ú~I4£UšÑ÷ `‡šz¥P­˜ªt+G_dk .‘ï©¿›w”$ëôÆhÅ#³S+ ó813Ö¼Gݺ$R‹oR€D‡¨Ë<ãÐîº'¨ê  9Ÿm½qúŒWéïûl?phõð¾ +]ÞÅc<„VwX³t5óÞ£ûõDtTù—8«ÔK̶=PLÚˆošß¯iÅ$N{úòY_`Ûî“dœ¨“vÈÖƒÌW‘v¸+×6âå~µn„½û­ÈݳdG˜!c3€ŒU¡Ï7ßæqÃóý–Zy[ÿõ çŽÁ» è¥É#Lv+ÿH› ù#ÃWñ‘6A¢êÝ_Åo×ôà_¢Ž¹øÚ÷Ô¾UrÎŽ¾œØÃµüü¸=î‘íYënð“Ñ…4cü|d__›˜(É ³c‹°Qµx=2O×j›­í=‰Ð"“µÚžìYâ QÝÿqR_3ú ~=ORh˜xÙ~®~ÿÑvI­s%k/Äî f<ö›.ðz•vÐ0ûÒ¸üP^wMq)¿ÑšGÿµ¨•ïétý1¹dgù*tØ:UÚZø'JÑ-Q¬]JÊG·ªèç'iUûQ¼_C1áÒ“ Ì=ý¼Ë’û'ëô#}ùiô$‹4¾ÿ˜2“³k}vã\O»³1ÒÞ(¥./³IyuH£P§ïS¥&Ýûawí77NdäŒÌ³‡ŸÍ4ˆ2ª;K]Ƈ²œæÒÝP‹ôU`]jiŒ–ЧBÃß­üO$ÓP5³@êú5 ¾ÑŠƒõÈ’PßòB±ÃüWƒ]i‹ ¿Lè¼ÁÎvÈDƒD v‹ÌRAphO¡ŸƒªŒgi½¶» )yѯ¿fcðÇ|5l}/ @f û/Ì=ýägSlr­è©tN>!S©tËw‰dž2™ßƒìŠ4 žt2é +_œ±ày_2xÌ žñèÚ‹4 ^µhüFk‘EÒ—ïÎ~=ò%4,x ‘·7Pžø³_O“ó`͇"î°ápÆ":ŠÞ£sì›áè'ÙŠ'hÅ£ŸÛ™õYÔŠG?ç­xæ7x¾!™4!›ÒƒœÆvlòþ•Êv®*>Õ4%@PäýÆ®\2så›ÈqA®ùÍ1§¶$NaE,BkWÕ9Ýe¥|ÈÙ"ïÞ®Êyz©˜aYx³tðì@ÍèŒñ°¼öççYÊØ¦ƒ+ÿÕ:3ú.Äó½u}ï4QÌ"tjT®ãµÊ|î3û½+fKc•—ëm!]jþ†ÐÌíÜ¥V”ÐÒ§ã2Ë„¢­fÍ}¬^ÕVRâ5TUe4B ´ð«ª\,œ;ÄG>2òQuP茡×ßÚÞò?¼N5@¢c€‰ö¾|f‘YB [¶2O•¥Ö—P~j«»‘°úùžeì¾·¤‡ß[TŽsì«ÔÃ]]S»¼ü4€]]»¼ îò(jÒ„¼éÆ7ÍØ÷«—o +?b8ã”yÌ\(â»ü§§*oû<°q”û²_O8xUVFìSS–å¹0g¿†bÆÉë!nÄê䵬5NBEŒ/V§?OÊ焯¥OCãĈÕuVCF"eÚ7m5<{#MKZÈ0½’ßfÙf‘.ór•9 …¿ó ˆÙÂ¥º"Zá—Ó϶H/•W™ÜGIRó³«ðûÏn˜¶#^ª xUx‘##V*Ý>}Ì–]’EF¹{Éý{‚ÈC»o]hóš í¾M±I·„'oÝi‘Àî[·eM›YD~É. »oÕ&9ÁžýÀî{ :Љ@dÊÞNÙ"cÛg[—“¯c»õ|$|¢Ô™?;:™ùR·+GZdÒ\>Ãó™™+¨"'H”˜8›‰o? ˜“´Ÿfbs'Ÿ!fù¹ÿõ°¸#FõÔˆ1¢qFŒ¢ò$bôMv=iߪ{ä«"Ùí\ŒÖ—õ-2YaÑÊßΫ"ÑÊGÍ$xßɤL5žƒ?ûýDGV¨™hrÓYøQ\‹ÌRš{4DË€ÂíL¥“ööÑòÎŽS5?ü×;ÿI,oLñ¨ýÊç—ÝâÊúùñœý„³£”µl¥­eÃ[ÑMöMô’˜(¢›ì c+Ì'úðìùÑ׿£l`ýè= t-éYÇõ*‡Ç¼ÆÍc«ß•Òê9(&¦€˜AÕ@̈);û_3ä9ÈÍ£Ó@§ qá ¹‘¸øI\,tÁÃØ}j¸ÆœÆiéé¡3å~KÇ÷›,pU/×o5  ɯ›Z ¡·w—Ī¥k¹­zOóNœÌ)*’cËdšgyÇüV\Òe5b6‘â4dØ“ Pñ—5Å_BVLàÙ‹T J&Ï~…)U܆§¯8 Y _Ég"d­Ö0mi‘D8¤˜ˆþŠÐq R(b;0?$¤:c"Ž‚íŽ™Ç›þäª&QOX#àï,"ùeÕAVÇ”O³¼™ã‘GãJüŒU8Üwô=“ªï‘zë>«w¿3^yw튿…)F‹|ìù¯OÍ•!cã·›".¶üã[ìšåçlz9QTdPzºn¬ÇáóVªAÓ #ß Ã½UlªÚžûbWµäUÓM õ¨ïØ Rn¿}ð{¯œn«Jp5ræ[“´!UÇ´C2™›ÖV>Ñy‹‘Ä#«©ˆŒmH=rÆåÈgöÈh#šé@uöþ3¹Ù/·ò?±½››lg¸šù$½'8¥>±'„{¹gç ³\{¶;jä÷ÞºÇõ:¾±û­yµåCÒbÆ·÷<ÌZD^tþ·âqz^ÂçÄjÉÿZ7iÝxGWŸ±–ü¯ûæàU;tÝ=Ñwµn¹jB úˆ¥¢L©‘õ¸ìås³{þ¬ ©ZõV •yØP­ð¨Î†ô×ìÎjsVÞQ¯±Çô ŸÕ؆´5zúê²È6õ•a("ÒÀŽ3ïŸrZÁïñ¡A¾¶v6wò³;Ì%Y|M¾ˆlH·Mx WK†Fª¨Ñ ø «wøñ%äu]å7¥ª†ÝQoǼv%–nlžjE©!Џ4Z°èW;¶e½½Õôߟ뙵òÌj×]ѯ³ÖãÚÜx+ÛðÜËé;^&Õ¼Ìæ½Á³ç‡¼Ì’ª‰=ˆ,y™ŒN½ØýOf›Ç_›ðn½ŸÌ¶È[<™Ýy³ÚÏò~‡È$’ J¹›lŠC) òq03i e´“ *{ñ¶±ÉŸíQqÛ69o½™(yI¾¾{€ürÌÓnÉ´o? ót­¤5œ;ùŽRâ«?dÒé-¿!v¼®ßž¬„È#6ŽU’æŠ[DCÑg·¹½Uÿ|¡¸E[>´Vk°àÂó -ÒrÄ´µV—îôMjø^»½I¶Ãd<@µŽØ(ü–+´/âÑhTÜOЏ±h´E¢”5}†ÿüÏ Y²%bëÆ"áp„k\È4£ª¶ e›U±Ù³Ð-2I€gO“ØOñØßx;7p\ ÌD¸ñr Pä@xÌþ•Q¶"î®è‘˜÷–›ƒ ¯?‡Â€†æÊÍÕ="×Ë ÍUW• `™}YìÆR"zsT€1$ÆM.@îDµì1™˜y³,™*¸F¤PtÍÆl2Œ;_³D†AM†Úé×,‘aÌ:ÈÊ~×]œëó†Ùæ >½f YÂÿv]K¬âÊö—l„ý8ﳫöý2ˆ¥š¯¿Š-5ŽŸWa¢B÷ ­µ%ÄȳÆ¢w1þ÷³ƬvÝá<¯%©``h§oÝÌ•“ ÙÙ‡A™ÃlŒ„å>I³4IÓÝyGÁ;j¥È!Ï…åb%âµàÞ/Ô¬3ÿ.'¤)÷2qÄ¥·ß:øAö ˜”ï÷¡œVšŠ–ÔRÆ»“ü"{‹ÄÇ =û-û.MÙ$³²(>æëÙ $ÃHÝÚÒ­ƒÂFÜ· mùÜâÎZͶfœ€‚wtã!"n“«¦¼ï(xtå®Éð¾Ë±‹=Lð¾4O”ÇÌ+p•2ÈàR7ᨂ7Rù9–3"l,¢Çú©î-3B8sN«KT¬èyK°rqRAÜ\»o8ø¡±&+^bæêa–qÒîÿþ«½­u³o³Z,Ê¡‡ÔßfeLø¾ÕS=.©©û»NÑ>v’°Ö´K « O_쪑⡩YîÿÙv®u‡Š¼N§/þ!“6cÇûmó|ÝXïÆ1sµ±èua)ßy7“{Fw.r¥TÕ7üªKd#HìFh›øÊÙß6TåÍGžrö¬ S¨5FÑAÛR˜&­*uSgD~¸ÍÿéJ·%R,—!²[ë ä8/@û>ž1ò}Ù«9FFŽ´T˜6éºl[ÙÄ Å×þ9o—q¿]¹%õA/2+½Hu¸"› ¨ú;Æw˜ïõ¸‹­lú¢š<$›Ô"³IÊ2a!âɆÿþù{deˆ=|Û äeªÇÆÿ‘ c6>——ɆÏúÎ0GßÿÑwn𿇗&ŽåîI‘O,ßü‚°'E>±|+L^žú‰å›_öóÔmAX[9¨‚0¯§!u)þv¸ÑR™¾É¤°,µ/O]PåÖ·Fí#åF!OL TAxš³Ãy^„çØ1Ð>c)Þß Iù½}šŸç·´‡pÿþ¼õéó¼óïN'°å3Èðl°[b±7a¨ýxÞ-‡)¯Å <Ï÷ùpSöMÜcdtb9±©4÷™aäçÂé[l9Œ¼D¤å;ÜùÇåžnÓó”AÛ<ß3âsã*%™nqõ îâ„©³Û ÁØJ¯ËöUïͲÀÒîóãelºÄ2B[,ÆSwŸÈ_lcÝ„èÉêOYK#´€>wFrÊÔuAÈÀ+Û[ç³¥ÊY²åÌØÂvÇ9•Žº}ÙŒÀÿD¿ÌˆÒ†—Ǭ¤îÚ?¨ ££¾M#"Ÿ¦OB®(Q˜Qd¬:ñ°*\Ÿª…!³‘Mš@ùâó=*Ÿd3Ù¬®Ö2Y¹í|†w…nù+HÕqH¥ ¾$ÿG1½U™ ‹ÍÄ üÈg²žë„CÅMXç– ~ä³)Öê&Œ@2:¯µ÷ÓIË|AôIùîÞµ#Bz–,Ö´¾Z¦-”ÂTñDù%%%ä¾ßð7ÉJÕ´¥ùÀÄÊ~ÁHrŠäñüƒ ,ýÅñ8™![Ò _Ö¢7Í­µ®ÅJ qï©ùørù­øø (S»Nq‚žlÙÆÛ‹G°eÉ0AáÚtÞW¼&IW75B~}Ö§NM¬IÈÏÅŠïüC“cÿꕺîK¿çj\ }zÒU½›R^UK–Ùá¨èS*àSªË¤ƒ.å÷õó)ð)Íø’„<|JúÅ“Ÿ-ܧt¨`hª~™·½ÌïÓ1E›Z•é ££CñŒ\¡ü]²'Tð‡›º‘À/zCÚ •}:=B†¿ÕZçAç óu¶§Xb1Ã;b‹>ð,͇CEDìb„<‹i¡ŠD ðïõî#ËÅê{Zðyž 2Fí€<3ÿR¬×©q]‚ïçÞíÏ»õß›Ô]±§€õ?y<.ToÒâÇW½‘ÇóBõ& h}Õyl(³Ì®BÉ#@ô©ÒÊ ë…ÉÒ ‘^xaN²v…—§*^ðy¾/úHâ%a !£Ó>Ò«©: ?W}$ñ‚`ä÷ÊF„B¯Üä23îÛˆO-~b#½N“»öðšÇ+Kÿ“»¢×m"Ñ>â)»Ov4_&Šäœ2´ð6ç=B^$‰³fùºRüU ø#NÙ}¦ø›xu¸öè*gÈ¥Wä%­+æ‡ÿ^&ŸR÷4߆ªìÃË‹ŸÄcOݕئ¾šáÝ0ÒeÅ*äñ½±c÷ ¦ÄÓ,ŸL9ʈ—cû[0õ#ˆ—N+¹Á±bA©0À%VÞRõj‘BJU¦Ff{Ìø\pë–j(±Ñ(ãö¸i¦‘w%BÜ37‹†žâÑïúrC«@ÏŠö]+ä ÀÔàÝÎ[™ö}Úãó|{ÈÚNðãÂÒv¹%‹%up^·ãÞÏ6Ï ëè/Ó¼ÕýglBH/UNQÒoæ­e{Mã ßùTµ•â¬4ž(Ïö„b(ÀÓ òßÒ¸¥CšÕøÿŸ¨®­‰ÙÒ?…ó.MG%~Ò³Ñûc²ïÍ^àçd(X†,UÛíù¼ˆìpûË0õ´ö¥ ¨OÁª+3äU{Ÿ–g¡‘#›)E:NäÇ|8׃Örö–_þ’'3ÛY²`èèÁÊèR؈Ïd–½9¼ýª>" H¦+,œ‹O/-X’ ÊÅåß?ò¨òVUÖ-æÉžÌ)~«%kÿ÷ÃVÔüä¢èÛNÜ-÷ICb£…©X=°1çñN{|³$KC•k­šÄéoÕš²ß,IÁÒ¼*MÐV¬uÅV¨´Š> Õ,ù´ÔWçŽÕØVåáh –mÌCB´ú n‰]ä&ŸZ««`†GÃ{Xk•šÝÕwS9x¤Hf«028'É{­]>µØÝýÕWd]tÖ:™*xPï“ü.£é:Ùt†cF×r»ÎÜÈ]&}©¸’ æGßßà,®äˆ¼Ž+™zŒ¼Œ+q9Úž»žû.òÄÏ}>ªÀ¶5 YE~ý |˜¸$˜¯¯´3Êa@icc1ñÑv°ÿî;!(ЉJ¶È–NäUDÏ2A€ñþUä·ÈoýÚvÉ€‘¡E&•(þ½–¾Ïz„Ô)g:™Êœ§X=Í}6t°Öò2šMìO^À¿uWŒøŠ"]RPVEÔjÝ×<‘›*h-RÕV9›Ë ~%믩:ªÚ(z÷uÁÕ–^Æ•x>î$ W>îòãô|ÜI@.|Ü¥Þ÷q'Ásòq'ù>î>æ{…¯è„43¥ù¸äµ;Ø’äi†÷; ò{•áL¥Iâ5¡vÀÐn#‹ÊzPà…ó¾s˶×Èm±î^$xáFržÏõQìÐãi#B?Pmåè=,þÃÞ?x üj©¥„H{9ˆù»GH ð'vS+Wz+ŸyÒáó|_XñroFð³fÿU´Ì‰Öm»òÌMÝ^à©\9yµ=B!®šºW5©¼÷½»â” æ6»sLÊÛa¥z±Ø†è.F09Øo3>O É= †ZL¹i£c^Ÿ©›¯ÍÖ5óÜwøß#?ŠM‰ÅΟÆb¶F~ìÂU!UIR"›qíb|í_[7׫qýï]×0Öoø˜6¯O9ÿ/Þ­hÅbÇ—ôDvÍ•±ØbË0{aWBÁ‰Ã–‚ªäâ¤ïÝ{÷¹ñOŠû¤gBlº¨g¤,æbpãÍç ÕQWSM-uÖÊù:I+™èÖU9wÈï‚YÒ¥`æ’Y{kžïP’%äq×û‹]I–Çu÷MÍððïäyLÕ‹ HáS‘ßlT<ÚAÏ™c\_n n«œá›4±wò›ZÁÈÔìåž, BúúñPuÅ<Ô]Žu l’§K¶Ò!Ísgºš¢?¥%«ë1ØØyÙ¨2ËÓ]‘@Æ5MHï;έZJs§[Úá@C¬üSÕ›Lg¥(S„üØ*ZªÃ<å¿ËAOþb„üúºµ£’Z™qÜÊÒ¶ ì—ß1S…‚Ĭ­jkÆfl[†¡O MS Íò¦äs ö­(¨Œ«OJc06nýLëq¬ %§Ï¾OËÁ7OpÑ»~6«ËçBç¾vrí£=yÝRúZh?ñõ‡ÆÚõ=PN ¹Ž/«ÄŒ,.‹"ä ÍZzxú4kB¢+šu5#š5!ÑÍZ®}š5!ò´žHŠˆ¿ekïö’äó«Ç/Œ‘43éÝ—ü¹qdMîü÷úÎK[mÊg„¼ \…ý”yzLªéc^ö6©†„ϳûi|¸ô °#NÜøH?XKª#ap_E„¸W’ë÷Ð •{—Â#ÍÚêi³ì»¬7éu7JÓ$¥ ¥}󓸠v¹í3Î's67\Bßgõו2¨‡‡!ŽtW[^̺ré¡õho·nQ7õ½‹U ]À³Ë £ :¸—3fŸK:¸ëj…^‡øÔÃ]Ñ ¹û¢D25ÇC× ¼±S—s¼ÛŇïk9òY‚ jxC³–Ñ7®«Þ¶]e\"FgÿmoÚ‘o¼œ½ûyÒvÕ+!Ùvígɤ™ÿ#…”|­†Ö>æûW¯8`”Öð½‡þÊÖ÷n’ÏHµ]ñ}Î[¹tàý„‘ß ï¦ÙÛÍ…‘Ç×Bô;ªÃÊ«Ãß?Ÿ—=+1çê¡|ÝÔÈd;Ÿ2…â'Iø=Ãô¹¤?H»¤L8Z…¼—f&{z¼¡¯ç]áä<ƒÉ+¸$vý·¹$v;¿¹$>"/‰'¤ NŒ~–²Æý+ oŸnlãwÄÕ¯é.Óá¨Á/ÇF&bÌ…³ß³Pâ|ÂU!V?û¦¯·‰Þ§|Jm>l›líÐ;í‘…¾,Û"Ér3{WiÜUóâfo}ÃÈÖwëulÚrYFh¨Wk"M׫61ìôØ|NàJe°ôÛm¡_ÛÖŠÕÊI5!¹˜!-' Õ°ÿþQ/‹Ý,ÎbÚë½î0ôбÎâ-ƒ1ß›GÎú*Ö­ïÇ]˜ :õ¾qT3°³A²P_¥bé<ùM½=ôóáýßføýüwx[÷pgò~]r«ºƒõõûõæeXÏ[Å”ÖÁËH¨=ô”&êFÈ·ï4öÇz'K‰Xàq™ÅWäéê™ò9VUøR‘«x`K…å°+¶baÙŠi¿7mƒ7±åP·~.ïÒ‚bËÉûs[>NÒ÷eµÁpI~ÃÑÄû9®k»ÁHþ¾ã¬©`{Œ4sÓ=‹é^M'–qµ¡í;ïIùTŸ Þ¥•ÆË²ÄàÌJ"ì «%@•6ZKÙtžÒÛWéæ“Ÿ£|œ€õy¡-ÿý1u$­rˆóu>æË¶Ü]Äxß쬉y›ãó|_DtyAQ$z-7JMÎX7®œU‹í¢û¹³¦vj=ò»¬ `›/wV¥å¡oF:ón€½…'9ü#ž{ Ñ6tÜx#FqXe¹4Yå_«úij®Ÿd:oìükID.½'{™3 ¶a$ o­Zê®(<>÷Z™-Uâ9V}?Ð)Šn"º”ƾ÷è.¢Kƹ6€|ßw›«#¯»Ín´qa§Ýf¯ê½ܲm/‘i <Íèfï«V×3B^êPÄ#ÂÈó53’[Ouw&·t.…uŠ}jn5+“Ø&3¶Lî¹{u)cígã´x¼ŠÍš{?a´Q~a‘Ì10]W^îŒOð†x³ç߃æ±J’ÔÕ9=Õ¡p,?Zì}JÞ'<µ;Ùïã‡s]šˆÃŒ{êÖßçÑ}Ìp7¦M6ƪߛ.v,÷ðÜ¿ÁÅPê’ÄÈ7¸³ª½õÕ7¸³¢Üíh¾[‰vITí’`¼ùÞì£å.É­=}â©=øî“ox]“TÆ,ðm~_7{sšsÇÊÿ¾~{žF-ÄP`=ù^ÖOÖ“ïU`½xš(°Þ ‰U2Æ0÷Š4»ñÓ¾UZpËÙéggÌgŒ »§2i„ Ö|¤鹿[·ÅZæcdøË:”Z:uI‘FW¤Éî¹ù:Ú½äcr8¦aÉýA´x^´m5 øŠ"OïCÛ‰rƒ\ç±OsvžÛ‘áûù1l†hf±?My…‘þÓ¬t¯D<Ílj†²IÒO¶©t/QìÆ1mf¨G!ÝieâSÁ/ ød¤m¸ë¼yÁ'•pq=¶‡ú±?…Sq3Á:t±g®ÿK ;ÄЋˆ=™¹x 9áã&¼›ûF¡ŸhŠÍs¦~ëòº÷áã®j'–ôÐ WÉ!ªj·òépÌ Û75sÁµßéÉX=Áš!Dz2H'0j}.žÒÈÃJ ×éCòý¬2Yq°ÚáÐO Õì]³”Q^]Ñ'>&Á­¶ Ú²)±Eèðñ>U‚×’¬Þus¹š!ÒTáô<1kËdlŠÐ¥JÔê»4êò}+ë! 挻ÖqʦÄZ‡¿˜JÍVëg$646"||®¢Pr`øøÞ&º/.<$[k\Þ›ìk¿ V3Cù:gåÜ$vñúŠ.&ï’]üWÛ(öHÍj{ŽáÓwFÑqäZ“1Y‡¤K‘ª‹²Ú »½[è–f¶óe^—JµÄKU3ÒÚdø<]—*W…U‹,&¸r˜»öçQ§¥ª’½›±fg‹åFd„ÁJвäý2PÖàc~ýveª7q?‹moƒ_ßT»4|®,f£ØÉr|ç¨rwÊã’/ýŽêg╆¯3#d¥¦²Ï*Š.61·mT±ë›¦b"¸A†( Þ8JlSAçÅštä ‰_´äqQÅz>Uy-€mRèÚéR³¤Kå ï;)ºì¥Q„ ÎÈEÿOØu%ÁŠ+Ë-uƒhóyþïDÌ[^H Œ QœÕ?y©è†ùÏáD™¬L¥é0ça# ©‚+ͬˆüæe$’—Œí"QD&´3¦@EƒiÜc …³ ¡à‹ñzw)–J°ÈôLË£ô¢QèþºÒò˜ƒv'ŠFØ~];õÄ?°ýÒÈÈg‰  „-vp,†½òýEÎ4¿Oå«ÓIðlÉÓ(¹cÍ8™$­ü)ùd%÷¯†´K ¯hÞnÛzúD…m¸þ¬Û ÞÀ:SŸ]Qÿv€D¿RY¶Õ2?u©, ƒi_©,‘[xA\*‹Â`Úo¯ßäFIrUPØ™‚6s^¥Љ¶˜«Í‡# ‚âV:\6ó'ªAµôþ7Ÿ|)Ýtv †·sSÔ›—“ìÛ‹Äx·Å§-JˆŒHã´áN ED|çúË«ú©‚È,6Ú6Ã'„Ë·CF"µ@Ç?ºß8ù³|­åUQ§un‘úß!ûÿ¦w¬B±zÀ-‘È—B®ç/î>4&Üì#D¾5R—Øì[W,b)a½»ó·3îÃþƒO§þ}!´g3DÆ}Q´ái­úýï0yLhíÀ­RµÒ ãcZË”WkY.…›ëFÑt–U «Ì!UÿvY;±-‰"Çû!meßñ}øxö,LK`+m‹y‹fñK(šÎ2¤"ó{o»m›ç’Ðf‡×þ$v’*o)!…Ïç¢é,;õ¤Ši¹—œÂ³¿Ý,¨Zgk¦1¹XÛrj·%1‡Õyuú–*üF§©âz<¥Ú\&‚ÊT%ç¼£:²v”&lì®ÙÜòçEoé=õCý†R%Ps=6¤pÜTÕ¶&ÿS®(0©e T–¾Oã Ù/P™ÍÏ»ç äu`ØW6TïsC7OâE×á¼rÆàl›Ú†÷[C2 ×zùåÉ[Å(@¦±¸—›6leRµùY.‹D@Q¯±,E2˾Ð7ÌÿTò©Y-¸-I1ðŠÅ^)ZBHPÛ±Èç©Yˆùú5ÏŸãYŽE¾ð¤©{±n¾Ö•Þ.ªË1O ¥_rÚ~REÆ#3•áºCÞA+ô²T=Rõ²œVJï?ªŒ †¶¹ecÛdz&ѽ{k4tîÑ«+ÁŽ¥ `~iIã ÈùÜWî~F³qzö^S÷¥G¹“Œ×$B±Gï¿ÒÜ÷ÜP4÷C(Z»Kd4ãêv{-ÿ<‹ÜqNQ<÷GóH­ŒäÊUêE½ñ ŠgãŽs«hv8ûóÄ«“n×þŠ˜Jö§¼òIþÀYÞºÈÊë0± ¯ˆ|8{ìòFJ5²0z¿GŽOØê˜ð ïíò9Õ4fÿgÆqMô #ævo+Ñ MÏ<`?¡œ+¯Ÿ&°ÁfÒA³ãü¿NÀÖuaíèï*ºîŽÖ>íO¬‰V®&ZQ!¥©i<}¤ß=›|N >”æ>ÒH}ò©>Ðs­ûh Ûq¡´ôcDß…ÂÌó¿PšýPomm§¨þÐýãŸÓã¼Îª4ü4NÒfÀDdº;*7Ü3=åy‘r;IÿTY òBm„@ä…ÚHØoŸ'ŠÞZN& >¥¼p’ÖŒ€RFó~¿³WvCéû’€CJ™¾/_ÇD§³CÐíÊàB°#š<Ø™žu2Ú܇OÊDQ'´®÷Eu¢HLˆy¤L©ØÐ¯™RJóË”r\ü3Š&ýT}cù3ÞKFJ€ôÿ ‚\ítÚÉÞûÞBäc­KH¥ûƒ¬¼À2º&$:7óoÝÅTä¢4ý´:Ч"è3Î![‰¦"è3ªayxÌß–2¹Ü”üì S‘_Óÿ L"”]LêÇ“e ¶´¼T2™ápí/áX[n>³@/Ïi[ödÅ­i(QR"·†žÆže`‘'{²šP ÈØà"fm³kEÞØµÝXÛyÅÚfyÊÚî=kÛ"°¶ûkÛ"/XÛ3\ç#žÁvz^Jñ}ô3Ø(š ô®ÆÙgÅ3ØEJ¶,å£e¹Ï ¯ùˆbe«ÌÑYÍ Vîœÿ—ÉÒÊÐUxAò~eƒÿâ²;ì¼iAšÎ*@Q’w>ó‹í–ÒßJv»3‘­E¤ìCdDN¬ìž¬Ö9®(J€Ì R­Ó »C$ '6–Æ(×Iª~gÆHsv½Î‰LM ¯X¦±³qyÕÏòÒ)@¾Ò¼óÞ“+¾—yèOfQ?ÍA̓¯ö‰—¬?ã,ê§ý1ÍË8œ÷¢k”¤5ƒÐcZaoTµ£OU²¨Ÿöçïpý¹ºþüðìM?Íph++Ï¡ŽJEWM‡dà«×µ}¦i­—õ£ •5Wû’·­ía­Ï­í®SíW9ØúŠ NW[æjb©k~Xëja«y"w©mGMnZ[_x%ÜTM2xr´lôQ*«¼9Q5Êó±†Ð ^UÎe¯¤9ëò­‡kMÒ­m=CÝRé„ï`‚´±ŸUµw5ÝáB3˜³éïªYä¦|ƒ_KòpÅ<³V3Î'ת„l7ë ¡þ²òuëk}¨»,µOrʨ¯'YhÔ«6é­6`íé>mBÓ[ µÅuYÕ'?¬5½ÇŽY¬†î8?¼Yiè’UcºÊrt”1ÂáÁ¦iPJU®ÚÎ,V1¯køÒ¨ô]– ¼®øá²¬žu8r_ìP0Vå„>Ôò¾;#™×ÌãZÂG>½ŸÖ¾ÕíŽr¦ó(‡ý儸L!ÄìY îxµÎ‡›õö­Ðº²•yÚ^òí°g!ý´vú¨q¹VIyÅ0¸Vt­uÍ›¥ Å6|Øá¨~'4Š)ï¨@¥š YQ!èo\´Y¨|¸§ZdäË-y°\hµvÈ4&Êd\ Ðh÷w¦¾C€D¿Ãx™V‡³gñØ–!ЩðX⇞ýqð=ó {Æ*äVa+>ã ×i ïÞÒâÔ\ÿ)j Ïþþ%À£ÊÒóaV5ÔJp_ãþ¡å±ì íw_²ˆÇýUˆ¨ÿj`Ž bÅ>/@¦ß¢–˜÷óÚÎUXgv!ÙŸã=Ðâ²Çy¡Ç4}Ó˜/C¯]i†gô<f{ÕËŸOøê.„¹gwÎ;D&á¹û‚“™4û`4Äož»aQC ÚájHäd3itÄ(°ëÅfïobZc)Ày¾/»'¦eï¯Ò«¥†ñfæå\;ñôˆh›êW¦%Ÿ:ëÚ³™l@&AäÝTäÿÈDK&%@¦‘D©•ª\û· KÏŽ"Žˆ»VZ`ÚDü˜G4$úO7ôÙ ÙsáÄ-ò~ë%B¸šö{øã8cäèù½ü- ºçŽžQ/ZúðX1‹ÏÇ'&;,×h=³×WÓÜÎs3$¥+…ßîtn¼Åz$×’Ä‹/ÿá_²\xiÑ#ùjßXo%²Õ4ú€ÂuÚ2KŸ\(j>6#H/qQÔNâB“FI½{z)pÖý׺¸h2¦Úçi>1Q‚_7޾¦ô¬”,@¦±È„yîë„{þY8oEF†f éúbÊ•ÚÕ´dÙ1yIÍv!<ß|ñí¢†Ô?¦Å¦c}¦¦Gð»q=‹ôažÉ\Õ"÷®œ|–®26²A.qÞr^„g„"Ù ý.Ùò¬|š‚ä{NÃŲæ36A¦¼¡ªÕÓ÷„Þ#¨)«{ß•l•7 B“¹f”ú) U«Ü¸&ÿñV2¥W͉¶[øDï(žS5ÛØTöõ$?¦Þþ{¹hÖ†[ ŸéJóbk x„n´zK£üÚ*2;\ÖÓ‰…æFá\í:ÓÂÈ™,ôuèŽèε| ?ûGÀ‡e¨]N_±íØØN>‚4¹M8Æò™ŒÃ€7ø`püc‡P›&w•W9ß[ÖÀµ&†ÿ×t® {VB1¥{³ ô¢œïK°3³¦ìçà…Œ_är/ ½nJڇΑ_õ/ihâ ´Ðãq!‡(äÎÖù¼å#t ­¹Ç q‹õN­[.ãq/l„OÐðɽÀŒÞ'貎i‹‹j¸²±#‹xÕ¼´sxM¾dÇZg»Ùϸ•ߪ?æë0z¡n¨‰5Vy‡h. 2’¨­|÷´äë0|ú‘dê:x†´mâ,QOòÙ² Q„ìÜLÈ\| î#” =R޹ÉLgò‘ã#ˆýÝÝß¾Õ& J/ÿ|@š1-ÂSÛýLå‹2l.)¼¢×o¤À‚Ñ@¾c$vggjœ‚Ácþö¯’¯XBEýOü©GBˆª—±Ž»¤Ø‚û‡j<®DšÊ¿&lWÝ  Ázå·dÍZ9G^‰$}U:Õcô¼°$b€¬Š{Uæ¥?æ×$¢=æŠUÞÌCmåy?êw[Æ‚:¦¢"ûjÁóþÃýÅüäÇÙLHtè(dÑÒ¶óÏž¤!½)ä &§i‘ßÝ„œ“m‡gB=-Í(†v¤ËÒÀ³í«Òv*é§¶ÙRÀc¾cŸöûD ¥£S¢wwþJÿ:X'±ÊgñÙÚLüÑz^nä~˜U7Žö;À©ù«§¬YáRïi€š}Du)drGYþ9@½”XÁN`…ï{}€FâFzXßÿ‘”"4øŸQô£ç*S×~"CË oCfûŒª W²R¹’ õæ¸æÏ¬GßÉÐSJ‹í°ÖXm±5[©|¹ç¾¡å×jâ³3*Ê<ƒÐãO\bkQ‹‘Q¯ ï ImÌ#Xó^È\°háZ“@õf.×Úþ¡‡; o P™ÏJ>‚|nÈ¨æŸ 43PíÓj +ò¨ëLŠO~¸¬Ÿ3 º{žÏ€ìpèî™\ÝÍ¡…þL€î•§xXDبҳá@½NºžèzØ77žèz!.z¢‹áÀY™þú'š¬]s˜õ/BÆY2~šs‘ɷᚘUYéo¡%¥Hà1ÑYýi‰îÒãRz, £HâçPêTý‰„úÓ3&˜øqGl¹ò{ ¿ÇçÑ6Ñ’I•%2‡ó³W‘pÏ÷@ìÈ‚ zÆ‚ÒÿXÞ¾žƒ˜•èï=ùîùº¨i)±Ëp?ߢœ#ꎱµ½®Ö´•©¤â³¶œ?áοφ´a½?ûëv·ç §¢Xdç`2¨d1ÕKé·úÖÊ”i¦Âw“. ëù,º®3 r‹±É rb_ òÔd0C¡§†õòÂ7ì„!Ûÿ2¬´¦Hdç ¢Žµˆz¨z›¯jÍ<ËD Ð^÷Sq[lRÑ+¦g7üíß±Áydíaõ—m Ï=ýþ·ÇT2¸W”F•¿?ú;2Á†úŽè@…¯½Ò¨ò§g©l˜‰9­Ë~ÁDf FŽ)xí;=¯@ºtgvhy\dèÆsŸ-¾"C]®,½E!?;©fxE¯xâÌÕq© ãÒŽùö&^XJÕç|¥ð~Z…¿¶Œì/¾–¹<@OÄÇ´í­_)ºץѻœ]JŠq]ô:£ìX)¹ðïz=UBWÂx®ö’qÿßâ-_o}®¤¼½í­E{ k¥«Œ0ö}óïçùø¿‘ä÷oýër¯ fèõ:ÇÛæÆÙgÈ i>_Í|½¯¥ùhxïÞÿ%ÍG2=#ÞET˜÷í(6b©0 ¹ð²ñçØÚŒ0=*³…ýæ}¾‡ÉA@â<ÈÑ|I†·î\ tç$ô·"Ãúo2:Qÿ £dí)eê÷çp—Âf…AÜ×aètaøžÐþT¼¦LëÂ:Ñ•À‹b«7ºØQ"Õy&°Ã¿ŽyÈÀ´ç¸u-ßÂü;ŒËæøDý}EûSh‰Ä7ÇÙÍ~]ËÐ/¼öaWµF§ô¯ˆl $Yþ= Kôû˜;“1K²ücÞ:̾ž?ÃVäo1L±£¼ßƒÜÊpþÌíµg·Û7¥ J™&Љžd‰bž€Õ“œŽy¤”šÚÎò®Z€DÔåÉgU7Uð˜Aï.â20Ü«l•ä";ìëŠ?ùô”ªªò$¦ê½…w)f)yŽN]Oòçî¼E¾ý`žFª+2ȵrq¥»ó·¬z>¯ó^fs‡ƒÞï@]Ç J½`#iàÕß“0ËT™œ_.`Ëœ0±Bh øL:©¨öbbe¾±ÃZÑ7õIC;ù+?¬5ûfih¤|à oæ‘®uu¸¬'¤èXš¡ò;}y=gEѱœ¶]1Ò»ê°o|¬o–}Wv^rÌœi {ûo1™Æ´¡ñ£¬Eïx’zwåQMü±4Ía(—šÔB5BŠ Ú5!ÔÌÌÿµE×ÎürÚçCIá{m)eæÍ²ÊQÛ²Õï†ÆCï ×í+Ó’e<–³.|wÐdÕÇÔׯYuÂÙNYd×(Mªºò­•¯êR.‰â×Ú±T‡–ð‚6ð˜@ê‹×H6îá¸ù˜u*䨍)@>ã©?³EWÊ›0/`‘¯©I5² j8 ßi¼ pW³®, º Þù[D<´ô0ÅO[Ž· BÏj©Åî}’49«z²½>@ÓÀ&¬í/J=QÎ?³+)8( ªí‡jYk^¶"l*wøùw6÷ž4ŸýSÃ'e?ÿÕQ[ëº]í+.å—ZôúŒ ZÆFNò‡vöówúòb³žÊ†en¿È?/öŸrjãÌ€5}v*É¥"y\ö´/Ãg˜¹ø¼)»e§™ –™ åaûÏ®2ïQˆLcÆ6­®8-±‘ÝÎG°TuÙg¿Îç·@¥3d©éNpÁ2‰œ1,7Ž)cб¬1ÈôÔ*ÊgÌÙíu2¸¢F´¶G¾OÚB½êD·ü3P€L€™á÷8¯ÛÂËø[ä¶zš4j Y$ –Šó͵«¢ÃbÈ,ðRÍ2Õý3á2Üòá^z]£ª±µn¡¼› xí¿Z Ü´ë|}镬ȷCÚª.tÓÈ÷½‚ë¼ÿl4ÔºÑ@áÅ›‘ø?Jd n*ãIÈðÌ…’ú‚+½Û×þûÚë¤@bez¿ì‡¨ç´›†¤S9`|&Û4ÜÀ±ƒ¢S'9ïx—Ýoúëqª‘ÝïçRf{ðÇLŽ.Å–ú¥[K#Xééõæäï² cäfNµ/2àa^ý1»gß“-P.#—òÉî 5›—y•HSzã™üšíÊu $\ûã¨(i9%B0à1ŸzÌ+ÉØc>;õ˜×Û˜Ø}9‹zÂ7r…±ðMv_Ñ\#JG–Ü.¼;¥Ão· $1jW+í ¡\­–…öävZÔQóãÁ³%Kî—žZ¡¤”Å~ðß%¥gŸ ÓJª*¡»;Ÿ\i÷Ѝ´%WÚ½džc‘'¥Â¿Ž‰ñ¥²³Æê¿}š<<£4Rõv¾Ëzºª™×nn½RÙößXíU(µ×E@dúûëØÇèëR>ß_‡RWðEG‹LN›…xðÏ(û2UxF³2Õ`ËT “owO#·$?—²$_n©Nk&@+K^'‚\ªù reÇéHk&@+‹§5u¶.­« eäP‹Ú?£7$ëÔÒ~q3/éÔÍ™œ•Ó˜/¼eéíÊmO½ó ÏÜö"Ï7‹¼Šµމ‰§’³4;™JVÈ2šJÎÒìd*™é©ä¥? ÓïäC¼~dòÑ0€ o~=õÏC~mÑ,9Ax$¬0RܯòÒ¡€^̬²U dŽÍ<ítîô>ÏpÌäÜ¡™9qΙ^¥8—∟É}‚Å¥8âgrsƒ§FŸ `¡>6%q×”‡œŸMIÌ7%ŧÄYÑPÏ˶ z@FŸmAë¡-È ã«¶ Ñµdr©6Íýú|ÝèÛ +È;w Ö2€íŠWâ'¤) î£S4ïl5Añ8Ô¥!y…Dekù€ãè èé^U95c5äŽ,Ï Ÿžo§´<6ËVluæ 2 ˜yÊÚ|£­ß˜0/ 2Ô5ÍÌO]3÷ ®ÈÄàJNõœÓÜõe¹ Ãsêtò?É–PšÚÎ £y«É}ÍȰÏXG¤J­ûõï+mfÙ´r§ŠGëägƒç­ŠõîS–tG›GÏO+ÝêîŠû•ä–-;Ž¢Ò^•´±k>Šo¬ ±õz¶±gŠ8)^Qwœ{£ä—;Ι\Üqƒ½ãà˜Ï‹òyÇ-y¢!¦™ öÎÝïQzÜG•)yßg;Ë@>ŠÇŠs’̈ì$ÃyžvæªÀŽ;­è3nâkí¤cÆ^ ÉJ$M¸žDøäÞýõ‘°2©˜½Çù†‘³žŠ?:¶n’KåXÐZ˜×ÎV y*þ¨øªQí[—~>W[gùôމòˆÓ»ëVá QˆŒ}S’é„ë³lú…–m‰‹¬« “ªÔ®ó©á»§€1LS.júÉiä $Œl˜a:¸Î[ƒ|HµrJk8KaÄÚæ5fq½Ö”äÕá#]õ²I"ÛeÜ«}„OD¬ÅKÙ$PQˆ«S˜öúôaèÚP½l.iÞeóùØra¼ÅÞ¨ñVå.º…Ê·zE™|¯ÅŠq7uj:u%´0µKÂGC˾öÙ¡©%5W“¥`c{FÖè/K})–J£ÛÏ‹£…2J£¾CîKc‰V0ªj¬áêÿ ¡­i ZkÆêl_KWÿþýŸØÑµÉ·s1Me–·ý ¡çG¤–©rËåý‹LÕy#S5@äL•KDØŸÊí–…Ž«Ë>_7çÔÅ_‡¸±b yÝ.¾ÏPUí5*±¸M…0\· Ÿ×á [fQ@h`¯pB B*×idqˆ¬-Ãèhb 2±Ç®f±U‘p²õ2æL80 þÓ­Ö,ñ);tóå¤E]åš@VhÛ)•A¾--”f‘[_Ø[+¼•"õ¢Ú‚rË}Ñ yÛ"Dƒ~ŸpLKÙ‡mŸGç·$9 áEöð]Åý;=n(ø„Ò:7$d8¶Æ4-k w‰Çà›!²æ(ÛŠup¤CqØMo/ÜÊRéA>®ž³žœ›F¤b›±¤bó;)¾"ɸ­ç+7ȳ:rDZe4 ŸG*Qe–Lż;‰Ëø®ï¾‘A^?æäš&Ás³”ÞŸ7ÞÓûóƇâôž/ £SÒÑY|×¢sßèuAÉ¥…”겎A׿:ÃJ«Ù´™7±W€|^I.7Á» •¦2j8 ¯»ªAûÜW©3®’h«"]‰|#O:ê8|:ºµ-Ckß(õ ]¡¬Œa†Ä;÷ù æNîüVmuÙçùB.«ûªâå|˜ù¯@“Ä‘è˜Ïïá„F÷âébå¨Üœù‡Œ†6•…Îu›óYâÀ€‘7½Ìèiûm ãØ–¨ï£F'4Óó\¯Â_„ÆV,•¦!§º¹ØWYñ¡É¥½KÆ×YÚ(~s{Õ&_מ˜¢Àwc^jÜÍ;W 'W1Duè”ABÓSô=‡ƒ¾gœ<Ó÷Äy¢ï)s¬œ¾§A>O=±Uª9;?0‰n ¥éç3 ¸/ÃØo†E·Ø–ÇÉ ãjk¨Fx‹óÑr‚Åaëó'¡i6ÿœW™?LYƹ$sTŽ\Xͤë\~4ùÑÅ’+D™ü 9 2¾æßwf[rGÝ"ž“:ƒÀ7^ŸSá8õÆ8¹¡nA|&þRLÞ·ºo¾µ+N¿îuß|t,ýº×}s qЫtµJË…'µºúªoœ!tÕ:áeãÜ59#][Aä#¨.“§¸¼läqß4Ý–de6ÚÜ/Ö<2«–‡]µ:[c„f"ùúP°«VpÉ$ˆ.K1'2ò C¾ãÿ4ËÆX%nœ SßîoI^xßNœÈÓ _W¹áÅ•^Çéã¦Ý?¤@Šƒ†Â ¤šgƒkA‹ÓÇ%[º:içþ¤O(!âΛÞå!)6w2¤wyˆ&`GÓë<ÄÜíùàóéu‚©<‡cÆŸÌûâ´Y*™F†c^å!fêÍÐæ!`öKÊyùïžÜ·µyã2h=š|7M€y÷чü%AR(üµ*á/Nüõäª1aö yÝÖÖ~ýDÎK|£JݾbF#ßçvˆ´ü.Noh¿T݆ûõ×u]Vø¢²ô}ã&…ÍMqÐÎxÖÜÄ}å„ogü$KÒÙ/‡ü¥®È¯º×DíC-c¶­+êÅòºV•®×Ð ù‹ôt¾DÊOí£g.Žƒö»Ÿÿ´4œŽ 6‹xqñŸ‹\¿ž×ŒÕHvrú7Šn,À±œ}Éý+‚vH¡Ãgbæ…]Uq±¢@>/ÜÎp-½â+GZqš®}9~%wœæ’›äÅ­­Øä@I²leÏVÒÜý:,δ6˜BîÚX=_ƒôaV™TRn’8iWNªq¦yÚfB)ž;Á^×™¿E‘â9»îõ:ÓŠmì>â‹ó}£Æ.[¢ÈÇEQ®XK.„ªœŸ}`âCåü œÈ«`àßßGU†Cˆo†Èè:Äçl†w`†øœMûþšSµ„Q`’9±ª‡–äM0ððë7ÁÀÎÒM0fþ&xmkWÃ`þ+héƒù/.YzÂü×ûq•ÿ,Ƚ×ûæ¿Þ_ò_|È [TÕVÀ¯—Úg³1„ õPf‡e)¾“³våt¾’?¿uc° ˆÑoKáC|Aëá™bNÓnÌèÅwÏ„ …gŠ9>$6ž*æ4ðׯsÄÜ»ïwô‹b޳ßÑ/Š9Žy¥˜3ãÖYaïèÅ‘7Š9‡w¿SÌ9 z§˜sõD1G¡@1ÇB¯s¼…óŽîs8?L•^+$›5ÄW3¾/%KgÜ‹³§užJÐú¹«®¦¬6:z ä¬kˆ|@jS®Už»ê‘wrGl!+(@º]/UßôzÆ]K„Z7éOqeƒëµ'lp†3¿ö’ IÝaA™ØLÜÑÐ7_I=§ªÅ _à˜ç68i†Ý×Ô½½ µÖu3«×Z?[i?‰ÏÔêÆï×u|Q“ »ú¾´2 ™0È‹døuGmš|}Á¾7¥3¯Êx;÷ƒpú{‹üþØÔå0ÂÂB2¥dÏœäëPe-;µÄçÒ ##™m×H¾ E€œH°X!˜ŒµkfMÂ9M°Y7–`“lÓX~=ö)*¥Û¢=þ¶ÝÛÖÖE$a‡ÜFb³Öê6óÌ(c "Ý4ҬõZuRO˜Û+9ñrоIQj¿“nâpª]d7ñrŸ /ª¾hvc>n’DÒ°Q.ƒ<Ä,{ʶ¢woÉGkÃK–-™ð*€ `M“ï|+9D>/~}¿‘P‘Ðð¡ äTLsñ%’Oö;šo¹.=Á;É÷ EzMm¨4é†ÒÜ åäë9*d !wœ¦£kW6í’;n'pæ¿yQUÚeBÐ%î…Pƒ–v“Q7¾°r+ጚä‹äÇQ´7ºó‡àoh9|ú§‹êfo¹J;ÞÔ;q51@W±æO qp×ÖúiWÒwõž9²\ M<ÔòêvtjÏ º¡Kùu–^uª ¡¯ºM÷“ÅV0šUËa^ߟвhË=ŽÐÇ×EQqñJÊ©eù •jíù>f~=}?@J7КwFøÐ»}ÿt´á^6¶~\ó1øëàf°51ž¶yv¦Þ÷Ÿ£\¨¯1-ù¼A¤éòV¥†×d^œïÛ„¦A*“àG¶69 Ù HöµÇ%œyÕåýó£ê”M6·Ö¹žk4r½R6‘0î{>oÅXçCä¥kãdÇ òRŒµq ƒŒÎÒ&xZ×®çnÌè:9ßÈÀ…HP¾a¥K1h4N|;¶9­xè°Ž»X} Yî”s§øè¥tÀ€qæÌÁï2´ºB±îLæ€|œz¨&Ö ŸŸ…bÌ“®ðûØß‹ÿd3ŽâÞÐa~:ìRnžäE’– »«{5ÈÓ$­¸–eà¾{zÅÒA¹ÿîa3øÝf¢ ž*f£Îí°|ãOØ\?cÒÐ9›àû,ax¼Êf¦S×äó"Q)U‡ì7z|ý’œ·q´äñýKrÞ¦¡’C3øgrÞf“Ç÷mr/ó:9ïÂüyòÝÅÇdarÞ o’ó D¦0 õ_p1¡b/­-ø8K8äˆ÷Œ¤QÞù÷£Ó¹j}ªÖ¿~ðÏ6­ÿ[ÿöÏ$hZÿ‘íZ®ùN¶´ã¸:[àáoŸŸÇ6=²—~> MZö b.Mš<î8 ¥Ÿæöæãydß4¡$¹ß²ñÊý:,‘7§ ŸÎ¼­³ymòxÿumë9æu1Â1CM‹ÊÝœÙ4ï§="à§é@V¥Sš}³¹ŸÏèÀ¹¢¢hµâ°Ykè‘IPMj|¿Aµ §ŽdJ“k2|i[ WÚõ7$¾aßžŠFyF 5Lâh+€|\:ÏÃì÷{rhU<Ë™þ³ìO†ôžg™¹pß#ý…g™Aä Ï2¶<Ëð9ã«fpa€BdrÑ .y–@Þð,øî'<ËØò,Ã__Ioxöääñº¶d‚šû1ƒ[æß&À®Cnx)ûewaÉgØîÊ ëjmxÀ›f¯ö ¡™!Šç¬kLÈ’äó Ul•˪e_F€ŒRŵÆÞÝZ (ç«AFIå( 2±¼ÌyžœoëZð–Á7Jí>Ê û¼V¶—õMYÃ7z]½Q¶î‚{óðëåÚƒ_ÿþ˜Ï`Lá£,Öé Žc¶Í:q¿–<™sXBÕwŸ¦Ìž Yÿu ÆËRí òqŽdÝsˆ|^!÷ý0f{U”$‹mq=¸ÊóéËr?‘ƒ@yòÝ›FÎ|Óú¯ùô÷ûÏ_Ðûƒ©Èd…§“gô1K½ßÅš¿æ£ÏYÒ¯.ÆÜeËþÏs$£ =º@JmR8æawh¤Üã02€t³”kÏXÍÒ6!áõÔðÒ«¯)ö¦ûšñÅúcŠÎ||3K,oä¾{ÆôÏYˆçÜÀs&–¥&UбXlöñ:sïîo.“~2¥+’gk·v‚ȇm¶TY€ÖhA1Ò±ÜÝ©‚GJ¨F4‡cIzåC›"áC£±BÞ^ò¤ LÃú®ƒ+GIžw7Â,=gåª8Ô‹äó3‰¼ê$²£‰0È(¬ 0ö§¸µiåõº Ò«Úɸ¡ò&JÒÍ{]ì >§ZŸL&g —œm®FñZð9uJCE­,I›äü—ÆÑÝäë¬Ð@ôË0/ùvª1a ;Ÿ…ÉàiŬóÚ~çF>ß ´Œ-0“˜׿œD!yòBê®u‰œyIÇ ÙÚ1ç­Ä.£…äÉ–Ywn#¼÷mïr™QHž¬X* •H¶µxÈŠ3êØ¹ë«fLî +s¯—]Áæç]où€’’'#G1-ßOåîò¸QHž¬ð•ÎQ.ZǹÅp–ÞGi£@†ûÂ7úþ‚ò↸$ÃŒ0üyßÊ¥ËÔ<‘­#”XòdIò+› t™¢Ôá뵇O¯“ÿ~îmØæm^œ)„–]ãF Z—Ë Ý6õaÔØwçª_f^)"ÓÚ7‡g½Ò›¥l÷“õ <€@¶.¦™ymXƒ<'!cJ±ÈÍêžjŽc‰ä{;픸²×$zUi‘Å,ˈý— Žÿýüø\.ç}¾­y‘AK]Ùò®~ž—Œ»“,Š`ä,Ó á©gjÙqîbQ d%´¦‡a”OY½í @>½/[šy Xªª¼ÈèŒ ›LªgwÞGèîö%!2§CX]Þȱ‚ʸá9Äí)þ-ð9S»šõºÓz‚3Û3€|}zˆZËò"w‡D¾`ÍQ ©7Úò­Ìǽ> +(¨ ‘Ϋˆëg²Ð U+q/k$¾S4؇â;Eƒiörß)ŒÜç>¢øÓ›U…eÒ›%¼+93H¦êR{ÏÂ”Ž„¤.íú§ÛõŒŠÍsîè~ z³ê•E6SÝ>gèÍ- YÚ•ïèøîï ÖcòçÃRgCVr‹ë)JãuDRaWöš„”7L–ÄfïG2®«‹VG°±%}œi?õ´õ»3DKú×%·þuÜ@$ȸj2 I> 5vyé(ù  ׺$šT|À¾  ×¹¤†n5¨#7È—cK6碬bîÛ%[ʲȷGÊ]¬Îo†¶j¡¸àÌyAXM.«ÒDë܇p TÛÌÒn”UÔúgÉjÚ#Tg\ÿ§ùuM²më"V =<ÀÓW®4:h,¯ðR2‰ Ã¨‘3Þ*Cj…P¢uå ¡qXŽ¢Jbôò ǵ—кµ¢ƒÛ0ì¬>)QÇó§ëÞîæ{=®È~?;—̱¶Ìy‘þ×óŽè®™l«¹Fž´Ì *~Hà "ã‹çšXöîi_ìÞ(ºÐÄ’\ùÕäòóŽM'h=Õ”xÞ»_Ò¾NTѾÚ7Šï¤DöÕlæWT¥´ºfOp¥Lmùµ·ÞëuÜ QPØ«[û¦£!8f|‰œ?pÌä¼”^´'¸5Jo)Ã]Ã^úò«ûTv«1ªõ¼ÏSÇŒ¯U4ܺÃfE@%‹ù$ín>³Kä.,@F¿UÅò[Èdžu<Žœ$“È “°_¾;÷¾7M!é++8l}•d{r1ÂôFL@ÖUÛèWú¸¤´ß§â Î èT`¼hp³y†4º$Ô:…®Ù;õHR~Û/÷¯zˆ iJT…0+&6Íæøö¨O¼&<¥…(ÃSúÄšèÚ™kd|^-'þÇÚ¹é낌”ªÏft}ê“ߺ:v¸ºº4½_#KÚ¦è’þƒúÛŽ“¦Ù  ÿ°Þ]ê×ÿù5ï¤ jÞÓüN-{ùdtKm^a—ÕD·ÔæÓ•NÑ-µ99p0fr‘»øÎ|z Òîù?ÿþQûÓd̰‹6Ëá8.ÌŽß3ÆaÊ È2‚]wôý6=õ퟽THÆ8ˆŒ˜j¦ÕU}tX†ÊF ‹& BèÂHÇH$êjíòÐù«ýI'Üw¶ª½~Yèá.ž…Pм\PÈîÏ:tÏîæu( [¦ø™¬ëÚ¸¼»º6_S;\h¹¯Ã /èø9‹hj²aܲáeàœWõbš%*Z#±’ÞF‡_‘=.5ß{I dßýŽBÙ/.{Þpõ ÍwëeήûÉY ËBM›Ew9+÷™ÒÕ ©ˆ8–ZêmYNSi‘ñOµš:艨ŸçVÝK¾ôØG«é³6"…¢FÎ;]%Ù‡µ*2ñöRcz1ȶ .øœ^ƒæ[¿Ñ8õØV[ŸÓ’v{-}ËÑ’j/ŒöUêi@ ¸ª‘%ùüå—¥âSå"3Wï«uŠqÕ°ó[níRúrÿ¿SÄðTÃñÀÇ$¬­àsš*^þòÊ™*d>¦Ž+ªÄK]Þ»i4¯Ü4q‹‰?É¡‘G{©}dqà€‚Ê,ùaøÖG7ÑîÎÛ*â,9¹dõ˜·šuÈøBÉaÚg[‚çIPŸJucf÷„¥O¥º?6,ëñzœJu×Á˜ñ™¼ñ¼û²Ö©Ïë*5í=wÑlkOv}Üñ³abÎí¼ƒCuóóÆn’Pt­•לø<©Y™ú £+¶ǃžzbÕÁƒgqàÔÖ9ÍnŒ–I–¶õyòlæÀeíº9óÇeƒA]׬Üì1âKPÿ£Ùu‘ý»xMcúüñã ©bq%µíáÊÐòGêkU¢V´J‘b¬Š"_^É­ÖÈâW×§¥Ì•Üæ¼–ú6²·¸,ç¹Ýá˜È¡"e£ÚÙÖ£Y[[Ç'ÀൌsÊø·@Ûž¾G ùŸ +ݯ¡ÓºÃ©:ÍQkýVÍ|ÝI7í „Fž$‹îÙà¶jÑ2VÁÒÇ^XR—1óu:DX²†ïÿô*$ìy_ ÍØ:…z}9.Q!n¤ÜÉ÷ö9hýùBhêAíò¿YóiÇ.ª^ÿ+cb*$ßÑVŒ«á"7ÐÌ5ªz Ü.-ßÑ% – ÷¡¸“2 ïsϯ½îþ‡‰ô2,)©]:î%3~‘JÈ2¡8Þq»í†K dneÇ ý’Žï”®(8Qìóžª/€ù~>Ó W+J@XR&ê¢.ØÜÒàc‰Tªá_?ÀË¡wèßdƒÐô·'„[p¢'Ä `¤ùµ]¶K]Î"#ÓE íq¹„Ö´ Ë £ZI.cç?¾¼Y{÷œ1ÈlóíW+;/˜¶Õáªyòøç¶6éø9¶•Ú%MîH_‹ÝÒ»¤yrë7lVª-Í_gÒbÊd=ħ2ÜÉz4ò‚òK ÍyMÖSaøë—òZNb*uD$)]øåÔ9q¯4O/hlù"ilmDÖQl4¶£ÓÜ­.ÂíÔêÛõ=Ôü¶·œí_Æ \VžÝÇ ,iHšg÷q‘ͳÛ8Ádi52ù5a°4aXšÿ…FÌ{£êÚÛzDA‘ÚÎ}ib·È# 5y‚[g×Ö±/¦~1_‡FF–vU¼»¬xÊò&ì ‘Ž¹»©´œ wY«ÚÄ5ä Å…/½¾í–Þ4i¤gDÔX}õÄÊöûµ³¤‘žÑèc³zï·™lF"¿ÿº˜QÖPö%¤‡cf¾ðž^#† :4øõܓЧ²¼@êb¹‹qÀ™PÁüÄš¢=Ýà O Öö–Б;–;~—sFDÓé 7w«¹»BhìQ‡ëêoÚé´óƒ§…ÐÄ•˜¾•¼˜HZô?Ii ¡//µˆ¥!2{Œ}wb¢Yšž¶òŠc»i}Þ´òJŽÚ ÏSKX¤C¨3ºÐ±±IŸ[ùRÙA ¬,M¶­=’kæÄã8zì~=¹·“§Ë„¯‹fY•(ž´ÈÓf+ØAò¤Ùelß{¤ë!Òc_}ë ßR5ÜÐáöë ¯ß¶!íÌpÝMiEÒ+Uš%Gz-u ¤È#Ž8Qš’êç™]2LÅÌR~Ò@3ë8U?3ÿø­9â^`ßo~þ²ÜË££@¡£pŠ›èžŽâà7-D^ÓQX&/ôHÚƒÕ:ñ}Wc1vžÐu:wânv+Ë:½ ¢Ük"o!N ±Óês"éDö$a8fr®Ä†ºEfA#±XM•Ú¶ïö+ûFy€äã©ÒI¶°™nlfé¢M«;÷ÙðÙšbßV€Œwwc¶=GîŒ D&¦IÀJŠVÉõý}s+ _N÷@{îÞk(àmE…°²z€¼ ÿô®ÓI#ã“O ï 7"?öSz>¯#è"Þl­k :Üd|ð ”‘ŠÏªAF¡PBk;ˆø=÷m¿ fI鎈kvâH0f|ÑÝçu›£g|÷F¢­Ò¾{r׫)Êpw€á#™ÄwÕ“÷ÐÌpÌø·|ÏC±´xµÎ\M¥>Ù¼Z?:v¤&BgU·#©7ںL½B[>mdü”†³^#‘)âWWƒMËX{Œåß(óÊ}ueôø.–nj-QŠFæ§^_3KmÏä8¾Q’¦*Èè”õÞñN¼;âä/wÇ‘ºAÂßvëþºùuŸ•Åé_X™Ý¯§Q&A%:M®4ù ß¿áòÅóöct9&ŒýÎŒ}c‘¯fSׯñàWÜw>Üsþ*uÙ 5hãFÉã.Cíµq#¿ï÷¬ÛEo€æ¼¡–ë´šZ_/£É½"_sþ´áÃç|]7|&räõýž·qð9OÚ¸ù6näú~ÏÛ¸-ñ&J7mÜuÌò(ñMÀ^æíç‘Üø‘·ým½ò»^ƒEž‡cÈÑȳ^ûU4™8Âv<éµAÃYä²@¾üŽ0¡îšIž‹Dä"ÃçDçSÌ®êT#¯…˜ÜÑ<½NÁPþ Èè>äIéŒÝgœDWAX%a%°42> ­ŸALD&NTÆ!¤9 ‘¯óÐ*¡´ ™ž­fUì3éøî6[Z6îó Ý Fá»gçr Ç\¹c1‰n‚°µ'«efþq” .(‘\·AˆErÏ(Inõ×y‚ÈÓZ¤I$Ä­âJ^Qu[ä.ì+¢$½$&%² Âz ºÖ棢 ½‘gÿž•IÚª%”ÜR{xUKÓÿ|æg‹Ì¯>¤Y|Nz"æ^sîÎ7iá݇@ÄÜo¤møcŽ+s÷¶/blú¹`3íÇ鉘æÓA0["寳MÏ ¹ ‘é…F›ï!ý´=œÏäݱ/Hoàˆh_ãVQk«†ÒàÜçS•PÓÊ—s‡’dtY×f iÑ+¾³¼BZ¿uµšV-Ùé}¶Á¿EiWiÙN A‰ð7p˜ûõär×Í A f¦“*E™^W)~ûéíÎ×NtV¥ÈÖ­»ËÎ…ZÏ×^œ¯ëB¢ô|)@^Bì¢"O “w aŽ^ÙmC—ñyeׄÉRsÙ^ ¯;f©¹lÆôÚ‰lè[:±ü´aßï{{›¸¿ß$¤Ke´ÀÏAŽ®¤–K#O›oø­IKjÔZ5ÒWÚÀf]gnŠÌé{‡Ú‹]z< ‚îsÈ dÅŠ’µo*Ê; Ò×:Tt`†h•T“h•é2‚º5XSñû·¨á˜±Q ’z.=Z—/)·7@&¿©þëÍÄJjÈ×5RÅþ¨Ì>çÐLígm2=+‘¢2·o¿£ôæÖV¹ý ¯ïB’ŽŸçá…Çi÷|z'õ Z<í­&iñœ!ò¦Å³‡¿žœ™•—Â.Ê’úgÐïÙ ÆúÂ~ïNûLÓŠUÎóH_à\ò«¼gLç ÛÛ0Moš®„wh³ë)ºKdˆÈ«j…ãè'ˆ¼ÒŠ¥|GÁ_OÎKõ±–|P#_>wŽ2פÀ&7 dê³×tæëØ>ÛÄ-F€D@jOŸ|–>íg:Œ¾…Ff޹I¹›æ¿þmË~Ûà|æ©é>ñ07„l=q'ƒÏI£ "HÜÊA{Ò³¶ éé‹®é~;ö))+™5A‘ÏI£ Ý[¼0¾¹FàD=cÿ¼S…£Ü‰o)ýÓ'o  €vŠXŽCIõýPïUš„¢yÚ¿ÕûkCúÈã¤QÐV”ø¶êö}§{0YÈ×LQ;…¿ØÐ¾çíK Ô©ÉIUýéÑœNVîCUS€V+{ø¬ÑÃvòªÇm-·-üP¼R¶Z¶Iñ/eî÷Žíd­!ÔɉUBÙG/lÇu+‚QcÀß%Í{þ¬MÅè£:y„J©Æˆ àXôe¼á§½ ¡Iv ›†­í¾Ý¡©ƒÊQE™÷>MíÖ’®Vä¤km«šxÖ–- 9 4³FŒÿZuÙV¸^+wêNo¬¸~ø·5ÒO;Ñbs=‰S­÷+_Á4Öbø±Ç÷Të ,í·º8qä«`«#p©š¡,«ï·K{½´o£Tm·7;¸°±Ç÷ÔtV;"- %¸úõÛúÀ¬æ_,u)M Maý†ô®ÙT¾K0Yȃb¬XŒXÃá ×#„f–Ã_Ó‚ÄNè€ó+µ?(ž T®Ö.˃kUï Ä<ëa† >kòð…å ÑÀÄžv?îäéN©†µ±­‡v;X½Bhä ïVs3±nüîK=£ÆÆä—,Rªó¸èzŠ‹ÏÜX‰–¦ç\¤:¸…J#Aa –o®RƒŠs`X—7áÁ¨©©ÖTзdÜ+VúÝ«à‹MW­){ë¸={´åÑ×ýÌ@48)Ù@„‚|ÂKà ë—(÷O-ê–Ë}%Ë{£í@Òr#—µ‰Ö ¬›ÚrÞ øîù ±ÇG{pæg"šß]ˆhöðAŸÏ+¨SÖ6Ðÿve»’£Jð—N•kÁóÞGêû Þ1xoh¾þ²Cºìu·Ô!ÊÆl™DFÜO„=z+ìA!49QëèZG{ÿv"Á!~¹Ëý¦>@Ÿ±··ÑÀ¨†rÊ»Zsô“–¢0׌*åâÐfá­`«Ret‡ìÚ’™ÄHl¥mpyÛ†/•@[í,ŽuÀûy¬G@°HóF¿ÆVÅ\Ëq'c´µw–ÕilU¶ÿ[­Å{^çØeu,òí¡Iy‡ulKçei‘ÞV%wçêê&¸Zøë¹§ ÷ÚÙzh×6Œ7°çâ´^k*pßÊ6‡Ðt`Ñ1Õ\g3™–°:&QT%ДܰMl®¸Q‚•=„&?§%Ù¥±.c†‡bЇÏ'.QÔ EA³aw¢*)¨«ÕÙUÈÂÕ›ŸÑ¡F«Ä6¶¦P"©À +{€ŒÉô&û¦”éÉxÛ× Ê^|ÿÊWQ[·Q€´É ¹‹iÅ5ûj×>ó†AäóìΉ«ÒLý(}é{¶ g09L€¼ÏØ«xöÐg(·ø‘§+ù®ä•ccv¬Ì²!÷ •zC¤rÌè>‘÷°’7•KO|„wáFQ©·Cú‚BöäÃKÇ{¿ùœl œˆÔ=¿›‹ëÚ'tr4‰!2ÚqšÚí8y.R¯8Œ~Þ`Ôi5+SÜU`Öl$ï×SnYCöèœó>”W95~%O&ÃÎÑ­Ȫ-’‘šŠþúµ{o&8@ž¹÷rưâ+Àç|ŸÝ[Ï\ù(;MX¼üˆåzWí5­éçt3œaÊÈÄïJ…Û•”‰–ü+j?"2æ¿Ö˜«m¬1×,›k€¼G®¸VíIžDå1cXú “ØË$ÅtÜYW€Œ¤%\‘£¬Å4ë9È YYº"%>¢®ÃÃÙ)ÄÿêØÓùiÊ7êe¤6t+@¾=Á³´š&¦Œaš0‰.Š=äòàOƒ·Ÿ/µÎµªø¥yéK+f‘ɧ?‘Õ`•€¿þø¤´¨Ò!Ǽ,n?€%~–ÀJ _W²*k 'N>Ú—VBýjsû¹ð¥”/­Üâ(üõôŠª\t~MŽ*ìmExm”›ÆVlÍ0RÓJBŠÔœ)f€L. Yx£Û÷HÍûZ¤YiMP›k³uX×™’¸Ežx(áBip†)@^DjxŽV†Ûí«‡Ç7J/×ùƒÜ"ZñÑ!EnpÔû¡Û±TÏ­ÉʃšpŠ9l39]“gµ&3ˆ|œîÚjMöDi‹|žj¶)ìJüwÿ⦠WÚÝgQ,ò~Inõ¹;t{=ŽMHi”‘—Ê_i ÛóS×ÁÞ)‘,›wïGl‘÷S$f„‘ÉaÌ;­ˆyÞ÷  ½5‘Á8—‘"ÈçEA¸R¡óýùúªê Â-ò9ŒµFgjÅ‹ÜÛçaƒÈä„££È­e”E¹]ËØ(å@G‘®Ã t‰r#·HÆæ9×S^¦8›2ž-ü¯£Ërt寢6SpVÌt¯õˆç%§½?ÛÜÒƒ?„¡ºéy44+óúÑ™\œ¬f²ã çW¹ÓÚ\®I{ Ïà&ߨ£€ò4ß Ù¡ð9íÞáK^]áºìzßÝj0¸3ƒÙ 3¹oÌ!çpK/lj™ÏXt»¥×žæšìçæý犬JÇÕòR{ƒxGt¿]  àÝïßd‘£‚„N v_p€î÷k‡U¸v„HXáSûP%c D^h’%È"[ä…ö¡âÇû5äž|¹}ÐÅU¾ÍÇu®^~÷ æˆbY‡¿¿ÖWIKÃPÆèÆöm¾ÀÎUøÝpÁeÙ rxúç|_KÅÉ_¥Hèþ¾.ŒPÅÆátG—%h:F ~Ý¿Weº¸Ê#Ó‹6Uù´*kóg† CðY¼­î:¿&'?_‹·yøõäçkñöJD&êAb÷„n”ÜŽwI•Ë‘A sWºSzrÿ"½—Å=Ÿ$ß)ÿaÌ'QÁÁ‰üœÈ /ز0B‚ïü‰ÚM¾q/׎BÙ¼–kw²J„½©GŽ¢²ù_p{kCyh3¹PЩgâ×äàüþ¡‹³²šð9|Í·ñ‘”•@SÓ# äë¼LP•ŒùU1òs?+Œ2žÅ†+lËqòi)Æ¢ïßK(b¯p‹Lb¯p“ƒ.µrgžØa‘·Çå¥ëO\d=æ³w:µÈgÄÖ²$´ŽDЬêa›¯Hª­iíÞ1’I"Ë ßW¥ÁUÜ";ùkò¥ÆAT-K{ÓLÎwÁ"ÓóRX³ %_K=Xt¶ù”6ˆxÒz?ò_ó›¯(ÄyµµAW %ß´x "(r“WVá…Fêv¼(0ž}›QæD™Z«Ü»>y+äR‰>ë2Pjä72÷¼‹Òô–[)2‰åï+›}ƃŒ» ýqqï“ã5¬`)ˆôsgÝ–»êK¹2Âç|Ý» ꊇ1ÖþýëÌÏõsŠ¥Ú¦é𜑞»”—o4ÎÛHÃXò§µ?ÿª\eáÈ”ÓÎy#rêîŽ]ÏGœf­Ž¨‰Òý0*;×häeo¹¿Ø$ʽêaØê °e=VLöºâGŽ™D]MUÝL³#gøë‘åZm\Q´¼pÑlħ °(Äp¾²·±Øò¾M R43“˜_"M µÜ䎩"?|ÕP^Ôþ¨yÙ›Ô4¦$eeLNz¼®‹¨•àNÔŸ¯/s î|\Ç4™ªÆ ÑäV娥ÄÂ˽oK‚l¾MtíRóCg™hSl‹ºvȸ„Ä2V´Oùž×>÷@‡û.8êª5,:èxç3‘¾ÔÜ"Ÿ§£Ž©LdXšQTüùÉ©ë­a¢|w:Nð9ߎo¨³2z“<Ïg²d¾;ŠÆ§ôSùo.BVÆ Ó‹ì¦üöþäb{þ'Ö¨­¿Q%¦‚2ññHÁGRó½Ò ˜É#6¿}?R@º3WxæÀ,”:×–@‘z¹ÑW»<‰Øæ# ϱ¹¤`;Ã<Ï£W G—_u¬Ü†»÷|ª/@o°áõš“Ù×î£çÏeqÝ”1*¨£P¢çχNŸIId¯>¨Ê‘¦ˆ©¼ºƒà|Úø˜X”´¶Zm3.%?üúóS¾”Ì¢‘U†a›¯sQÒ\ÝÛÃw·ºrÖô܉Y[ñA‘ãva÷Nù!óœ/yÛdê†rnR(ª^G þLØÛq¸žÿ¹pWaƒ—Œ@‘øÉA¨oîØÒ°Õ¦çý wd…žÿ!á¿øµöùMÂ_†ˆ^¬Åò#‡:ÑabåèýZÑóºNT堉繢ÈKùDÆrÁž]žÏka&¿¥ç;¢çëx£€mvUIÌr!óïþ¾ðÔÆyû_$?râ©«$fw€L>jˆ¨ñ½„®j¨¨Ù0°ál«" ²‡û¶ ?r^Ò+(È\I¯€<‘^‘Aï²7ƒ—^±ÈSGJ²èûK÷Ý_·/N¹êŽÙïð¯¯Ên"óêfèu;VýÚ"‰n«.’€¿~r©%Ôý%lóyV$QÉTN9À"_gEsÖ2…^ò÷—'pdÄöº…… ðÚU•‚Ö•ƒ¿ž^õñíØŸÀäÁ¥1ôut°˜wÐÛ¥VÞéþÅGK±Û9D^HéÄLlôJUó:ZSr™‘Q®M®êÅ¢&–éjeo¸\Xê ïiDfrjXÖdâ6Y=îÌ&+‘CÙ¬þ¼‹šh1“E1¬’qÌ2Àx…Ìá9Òó%^°Å«\¨Fbœ Š‡a›oWKòŸHô‰4ÙždjæÜ¯ŸsæÝå^3‡ž7ç° ´ñÝTôM·Án²lCÍvTᬠѕÀë¬{DlCÕ gåÚ1ø™nIµF—å¾NåÔdNPÜA±ü¡y-¥†Fò¥oÏjãm^Î>ë,‡É ¡¯O¨~ÖyÍvøQmŵ…šÎR­örôù³½…¢O¨jµÍ: i(b+m·~­¾][د¶âÚB=O4´`åa‚Šk›A•‘-øžu„FÐ¥SZô¼Ý38\BŵY {½¦øZwO;´ýj;«ÙÇ¡„_ËU\ÇPÕYôú‚g|£Ç‡³¦à,?tVÄ!¯¬âƒz€º'±@(ú„ªÈO Þ1KC[÷Zõ46] W ŸO¨nõ3y-T~‚l,—¬„s;‰.ÎPc ×r„=$Q4h³Z²U"Aå žô(V*—kÃÖ.LTp&«nœh|“çTtœ[É+*$7¤1ýŸÖ‘Aè;ÜÓë‘eX9ÉrŽáÈ2×*õ›y[yB³aœ¶@ú°Ðô:vÏù/ÌQV-ÄïÍ6yuj½ º_åA²X–>ëã~ Ýag=L-–Î)Á“1ʦn…‹¦®¸þ³kûlCÓ¯E§®š­ž;%¼ÞëyRðŒMf£œ©±-¯/§?U§éï._ï ^2-¨U~ÇwêÑIñ4Li:VÊÞ‡ÅOÇÛ„™¨òx IÌ<1ùÍE­„äãì6[!¢³uŽ¡­³!™¯˜³È³l„ª(r‡oô¾#¡ ½Ò£6M]YÍ—¾pVµîk¾áeBQXÚµ‹üµ8"£ÞüÃ"ÓSW¢–ÌC- ÒÖ¬ýÑaiesp*M*Çòá•lÍÚï_Uõk³ ë°²l¤ëz?8L¢Ú·Ãg²5kP‹«àÍÞ”¢ú8Q F=àзç9›H¨xÓ?ëó’¡4ì„v<ŒÒç7^\ñ:Þ¯on`XD³éu]¡œaåí_é}ÉzÒL*ºô}¸©K·{*ÝÃ.0ýÞ»gejÔ]ü.wÏðœ—ušÈOm&_$Q}/¥ÿ!‰êC¨wú’¨aI¯9WB}w¿:E(Ÿ–Í"Â= ŠøÇ¬ªq.p¿Žn_²ªLÉüïye/#vºt.0¦¡n]9XÓˆúFWÎLWúG&tûj/!Âúê\ X:ð9Ï (6vèϳJjUøÙÖ­ÿîèš·ëzs‘—=ŸE¿~ÿìy³Šªžç<÷ëºô¼Éªž'ƒìy §=¯s{™Ï¦£û—ž'£ÙJtÿÚó;¼;ºrz ~Ý™~®!ƒÚïBUH$‘¯!úÎw.Oà@F¼÷ÆòÞc Ùf:WivlÓÜ—ëž/ª è²ïEà¢ÇWÛ„=œ…Ðór¥Õ¶ Cèù祽±Ú󵜑¢ d|-šñÅXɯ ÆÑŒ/õüë‚ñµÆW4ã";Ü­2ôè«?deèÑá¾¼pZ´B½m»°Ö¡ eL1®Xþ9H(¹hzIÝ—“=ëœÿÜg¯²|k¢ÙÀUlîmÃd›Ù@pÏ[€|†K[{¼Ò¢tœô£“d³È×§ÒÝDå™%«›iHï*båóL*cäx, ÈÙájí8Í¹šš¬›óRq2µëLŒ6ѵ¡/ÆöüO µÔ´‚5ŸGŸ°Ð›IüTæˆ<0‰.«|FÕBïQ° ™q¸Õ~Ÿ}ÇØ¡‰Wnsˆòˆf ’C«ïÖg¤ãÔÀ—ÇjҊɧó-ôé ÆÌ¶šÍy_t°WužÖúìÚ¤íºª#œó°OÁù!k3èv©'.)©T€Œ„n+s—‚'šÑ‘Óaäé%örÅ–ÐUôbådÌk¾GsUPjºiY—fÞ‘ï€ÄÎÀv‘CKv¨gü¡PðòG±ãjS¥*'i‡Û®X³B¤¾òú5¥ÄÎ/0[0çûFừÁ¿ý±Ë™ù9^—¶\ˆÏ& àÆlCU%2¡˜… Bî"¾4<… MÔÑ_^‹Š¯Sé Î@ÌÉ& Ì#Õp0ÆÉþÝï×Ç¡eç9@^'ÿÉhéöª*­²è:Ñ|®ÛÅÑ–S(¬’{9w±ðRN¸ÑsjÒXXå×¶©¨nsmœÿºE&îºOµi–;Õfßöm–¤õoøkGÖýTìùtéõë–Í$=›«Þß ¦ ~·nFúBD³ç=dÒHXÅÎ#+jC›mÕ"F€Da[®jK…žË~²¹‡ïžFÂî>h.3yÌË øœ.AòWÛ¸}±š•¥äp€Þâ-ÜÞŠÎòèVï{v€•»]ó<í¶$[ÝJ&Oí„&Aþ5‚åŠ)3…U~½U¦ÚéºÈãu¾PÕëýÿÔkÕîJ|('‘-UMà7µW‡lR¯<®½6J¿Ÿ±çuIŸ_½ºAäYµ,[°Œ†äyì¹Béë‹å—bTù»€HÃíœÛ¦=úÊm jyi-E )ú†SnоG Þ8Å"ŸWq¥|Ð _×<Û|_FFhоf#JŠ@…ÎgÏÇViú=ƒ¸WiÅV¿²? ›gžW\Ÿ!I~ ¦Ò2úŸr·)f[¥?°¨¢0W°ú.`j†­È]©Dú7o£êÙZjb+2s€<´i¹®”Ø2嶨B†ÔõV» Ì"A¡†¶Äs5ŽÍFFøœÏxÆ™ƒË„ûE½RÃò¤í®úéö|-1@¾ÃÒìÄž;[5õл­Î"AÔZíÓLå‘–¡È4 qeTÌï_xu@Ú8èýJîÔȲIFõth ô‰ˆ7­«T…ü#!ôí8UG³ÖÔo šD5Bfg­¶Å8Ûq”<TKwÈOÚò“Žð“¾Ê¿‡Å–UÈÅŽ(³ˆ‡HÀ„¬2˜ÉÞà…6º’¡À2ÈŤ>¼r¾=öô¦ ›”A½”šºã[®ušôQ«kûRŒ]=ÁÑo¸j»ÖðvšóòO]ËPä0Qn>ĨìIO>k×oj+¯¥ù*gPJf ?¬æ«X(¶Ä¬þ7È οûã*çßáÃÞŸÚÚ»Ž¶!„ðÄËð>Õ©XùjÕûqdÝCe|Ö•õò²†+5VE 6‹E™a%l0É­ù*&vw»­XåV²Q^ÀO ù*2vSL{\W浺OÝ>.„ê¯õ«Æ@]9…9ú¡ä-\4_eÛþ§cG­ÐÑÈu²“‡«ù*ÛþÏÿŒ:¥ Š2:Ëõ¿šá: ø*Û›Ž°3¶®I·nµÆô nd“"+E;È©¡/ý?aW’Ä*®¯d3šeïÿ‹è>Æ!&‹Á(úô_cI…áe† BC™*ƒ¥ìN:•[½Î´ÂŸ@Ö«hhmÿí{*ëmxïÇy}(èŽÒî+]KòZšÃA$ëUΠì%ö~­ÄwŠÍIønÙЮ+¤R,ôn¡µ²(äÒž{>×¼Y¼e½ÊWºQ2´+'@†L¿Ã&iÅÇÃÄgLÍÞñ7dî ÉôLs‰‚õSÜ¢ æÑœÿò; ñ;·øRiân &WúH²'FÈ ÷ Z„Â1#°‘`RŠÏ;³È A^ƒ†ªûâö1hhJ)nÿƒ†Ž±âvƒvÌ…ÏÓ‡¸–¨âZZ{g©äW\K’#Ã\Kü€ô¹–š—UÏ鸖 Ç©w¢ß%ÕÃÏ™†z=(á»_I Ëj*7K?¬â5ˆT.Û—M­ýî÷ÛS¹©»"t.%=·HgwÚ »1~–qŸ·êeÕ^ Çf[b¤‰ y½+aIÓrf !u†æVàÖg.‡z×aÜRÍç¿©Vb£"ŒÎíÞb$Öڒǘâ=ìå–§¯ðÙ¸tˆEÙ=Ú:Ÿ'¾ÀEæ±q©ŽZW’)þÖ– O»û"d¨N¨ÜÝÞ¼‡˜5¨ØÅSËÏ¥¸{¯“J•:dÖàPIoI€ýÜ¥-îÉofNI¡¨ì>¥Ý/î˜MFu46¦6®Û'V»çLƒ'-®(îÞ¸ w³”]1Õ¸Š{vÁÃ%Û#ÎFÖ£ðf„ p’*FÔ!c¤¾ØªP¾°A8)g¸ŸrDHO~¸«f&öÛ^xLÄ¢½ŸËwqë3;6ÜBè—Ôû>ì¬EÈY€ÀCàk-‘Çü²ÿÑBD š‹õßÎóþýfá[i¹, Þó"z`5KU¦ÊÅç­m÷²o𘱻;^6Ùíß’­¥e0ÈÄ«'PY?¼ß¼&#Bzì—Ÿ2óx|ÚÆ4ñî½X#ŸÏ !sÇãc™Æî+ìyÞ×3B>€¬BÅÜ7ÐÆ¾õ§~µ! —8T+^ÌèºCC›eÁó‰n}™Ý’z›³¸(ï¥òhš2,È ÅE|;4sevÁ™‰ogb ³ûꌌÏev…'³Íøß“S™Ýï{w2»é7_+=Ô ß¹jÏ™y= i¼2€aÄÈ"äùqâDâG˜òEIB:¨ˆ¯H…I ”~EŒù2 ¬%²p[R$X@Ì ¤ªm\”$,HUy錑X˜K… ¥0 &i¸pR… !šd—Ê›Ž(ºHBDÑ2ˆÿŸ§#ãs·GZ,`0%ùOý´ÁÑÊ·C|B$d‡ŒÊ™’äè–qòâîX¿ÀPNr|Ö&¯*Ý Þ<ßÇc¦!ú rçø9³s÷L|# ‡4Èó†9Å ny‚ikŸªä^»=œð÷òf€,` Šþ@,Ñ ?'´—)±©·n>®(5ÅÍ ÷wæ•ÿ&«º§;wŠËdUé¢ñYqˆ3×fî…ƒóîúÚ;ñ‹Cœ¹!º¸sì”F/gB&g÷»”¸'ÈiØ[‡ßB3¤û |ÜÀkËïòée¹»Xk~‹9Èò ¢)òèJhEÔ·Ï£ã˜îßKR.@öPäñEIÄT»2ù"?”˜èŠFé]rÎßRø #cH‘*õS­mÉÅž^ùžm­h­xK?ŠKio€þ²È“À™eÕYNùe|LFPG„<ØQ©q—WÊÓ`œ¹ãR2È}Í çé^šÀW•‹;Š7÷ïyˆB—QE9àÖÒãB¼ñÝ•ìä+2SR‚Ô^‘?®ÉL;‚ÿ=Lfú„½™?®ÉL[ŽŸ3LfÚ±˜?<)3ŸÆ@Fi$ÁŽÇ|„hOeJ!d¦|þ:$\’™Î®›ÞBCÂN1D‘‡ÛHd†aÛÁÍ‹ð>–äh Þ^<|ѵ?k‚°Æ”OÌûÄaw¨C~ãÇù|D×ñc _Þ£ºÄg„ŠcdF‘bÈì´XK{3ºY*~óØÉKq⸙/PD\5œ[ÎÇ>gøß/|kn$qe39"Äø+x¡¿µU«ZѤM-¼YÐâ)+øš»ÉÃh¡kIi$¾'~NíMÿóï?滤À‘ÚMPq6U/¥«HM?Ÿÿ{ü†¶WX ýð©éâbŒŽ•@|NYc­ŽUB [ IÇ‹¡wŸnîmèæúò5-îö(°âƒZ#&ÄÚ‹uÒï$R|ÐCë2¼¾Óò…H†c%p%Þº½n\…ïÓñqEÈÄ!-Å {²=Ÿ6„<­K ª.ö‡Ït`‰]PìÞÑjlá6.."‚ˆò«p=ü§”_Žþ¨(¢«(£4Z‡}m¨¿l" û’ÜÒEÅŠä’ÜRlÐ!ãó¨-)gWì7\«­œMÝø2pZí£{£ìX«ÔŸ$é–¸f¾Ï ÚÔŠìX’ ¾œlåWìŽP’\vb?’—¼e!ŠSàBÎRëÕÖŒµbu‰ÇL½–RËA¾pÒˆûðƒ‘YPD‚»wÏ/êQ¤844RW¦>m`Q<.h9RrVÒV5Èìv»¡Zäwù¦yiW:aS‹¼6%3BÆç¢Ã☷ô†]H:©J xÎ8Ð6µØš€Äur‡ÜgÉø¶XdzXÉ’€F±Ê°WM§ç>ué4€t[:ÑÌåü´4wŸ ™@Ò'5ëÓ"ýh} qè‘î|xcḑöÿ{všø|ÉÄ'£é 5Õ¦ãšÊØ ­_þ÷ÄøTcn£‚ÙLgºã1‹#²%RóJV,ø9ï¡Lâkë8žú»—I¬!¾uÝ*.šCƒ™D2“4ÈÛËàBvŒ()4í:6úÑ|\Ê C´Ã"/¢ #ãÓÈ„/î#ÅEdÂ÷±Hì)§Bìºyž©ÝK÷ÛU ñöüýŽYJr åÈ(kT¬Æô›1UѾáR’Ä}üÙLÍŒ‡7Ò^ç.H%Ì;„ŒCñê¾Ñ=ÄZ”Gãb-‰ém úÕƒN‡{| ×pòO%#ŽpÙ"¾_:±Èr ªéÙaÌsr )ÇbeÎ2 µÁ ûf}Ñr†1SôRÿ‰³^lû7ò¬FR#¿î®äŸdî~_2Áíúþ~“”Ó™]ˆÖ0æÝ²÷ü‚TT’XÁÉxѦ¤è Üs÷⊘A °EFç ‰²iÞ=º]D §šÛ6X‹<¯AÓõ€¼_F™¶Ža¤ã»ªÅ8%~=›Š}wŒŒC¹”Ñ­ÏèÊRße§FFâ×rwû(Нf^R€vyJï®(b¸#¿ Sr²õšw™ üµ‰\I"xÞ²!Ó;±–ºEéÝåဘÞ]Å£$sö‡UÇYzü†VP¥E¶È"L* û=J.IEÉ"£“h™{%%c¦¡h˜T5ýVßfDÈ“h˜ŠXV­„<_ŸŠÂÉÍRz}#8C$r¶Ý.íEY«ÎÏmܶe ÅÈ“h«¨Š†‘!CѰ¥ó¾Qzq#T_æîâ(u_óP=½ËêéͽхŒQ6Fžå9É,ïwÒF'm©š…w„ øÆtåÇ1ã_ºüOSIÏøã^ûÎÏTRlŽX/Ú"Oå²##BÆ¿dÜòß÷™~8EÈ$ o?WŒâ1ÓþûYñß»ûȵïó|ôö{qIÄ&ìOŒŒ\}fCjÛ)òš÷™T3BÆÖ *UäȈ mí`>ãÛ…­(L÷F^¿—ͤ˜h-™ºiš9Ø`~×ßà¡i¯ïÕÐC&q CˆÉ&B9ì£8f|vlýÆÉ…„ –ÜïqzE# oí!#דּýbe’näÄÚ6qöSél„ ;UÉæÍR~‘e¬k—!£Óš7ÒîüåžÓÁÄut?ÿþø¯òâß)FÆg23£ŠÄÍa_FGâF„ ËÌXJA‹Œ½~ÓV,,ʱݗrµß(¹{È,)/™…:²‰ dd;oԘ撛¥ºz »#¹¡}od¿’ºð¿'‡{Ó"çQxH™¢È¿z#y~¬ a%'·c|í`©‚™Ü/ëX,‰õãþÊ“÷!Äx|ÝnÞë÷#Nä¹#d¸±%xÌ@å‹ÔúøØYò:oÎ+_`-¥·‹ú áºïž^ˆÞ–Ȫô;Z~šˆo­¥ÑAÓûC\T7.𖉳ÿ{ò+U% š:'Ue‘>A¤‹–ó,6Fžex…'ÅXU I£€•ì)þ4ìÕáç Ú´%¡øß‹ã7juä½ì·'m$ ìáøNl$ß!#Ûxñ¬¬(ŒaY ¶ïÜ"〼<`Ì­yÛ“§*B'ú^‡ÆLº÷ˆåB¦Œ×Ûk°H/‹ƒ*¨”»[éà¾;¦Ûª´¡*×üþ)›®{–vù}ö95C¿|Îaµù,Ξ³ç¤ƒ}÷ì 7¡†Î%×#ðc­i’78—¼¿UÇ~ù8:Ï0>³Æì_ÀØåÁuw)ŽYeáZYc¸¸xryTN‡l¨:á´ñûþhÊ¢ÓðòT”ïº N#“óø²+*<uï02ìE:/KCQw%AD[ˆ¥gÙ¥ÑNfŒ Örw#xuòñ'Yå'ÅŸ„LÎüÍ¥·q ¶·W'*Aä}Í, AD­ø~ÎÑ<²#ÏÅŸÞŒ.ÇwpxÒhù_Òh #£©£Íö+¯q4›QÍÎÁŽÿãÉð¸ (GÑl',úë3a%»KV\YkÂR‡7Êo×õîâüv·aàAç÷«¸¬ÑÆÈ(m‘}[vwüÔS#žžÒ³X|Ð_NqÁ<&ÄieÝ eß±AU„L~#ºª–ÑÏ‚‘©C¾gªêji]žÓÉé\¬´üGÕhãV]ašlµßÕ˜r¿ +l†Á²ËHϨÂyqÚtÍж~NàÚ.k×T]ke³tKù,K„¨ò%-je[µÍú®¨Øƒ©»Áþ¨~A³;úy(ëq©Ýw/P\#{J{w*Ú¼wc™&Öµ^ÖrY2öë+‰©l]ë}_ö•"d‚š´ HÇ÷®§#þ÷4„ì:Š‘ºeë_»;ÔŽ[Ærzs~@ë“ÓðÒŠ1×±a³•˜ºî»Q5Ú¼ï^ÿ'ìJ’XÅ•à•Ì`/ÿ¾_D÷2b°À€¢Oÿ5–T€è}šÉšjÈL6Ã9ýùr]½{äO!üåUÊ¿ÚXÅ0ót`Ÿeu[’׉y]–uÚAã*0Ж7°KTïBYt™Ú\B(óBŸÿçËúHBNµrb'²ï˜¹ký[÷åÁÀ‹@Fa/2—³·HœÙ5ͶªVº­›EúÝìö ç !!Ãç´=Ê8[×òÙUêÍFMGÆ3Bž÷J èˆ<ÛZW/‡9/xÎ8ÃoêÑvüT‹<ÏSÉOmñ½ŽVEòˆîi>"ß }ºó‚¾ÈïÍGAŸÊyA_äYÁèz‚­®‹`ŠWçìñÍX¶+ÚxŒ¹0´CM2±ÕØe"¿ßß>çG3­¥ÓEÛ:äÁä¤6w—…¶†3À ãsSŽ–.þ£è²†`짬!(B†¬!¼Ú~…{KÂÚY äc¯á» R¸ûó2H¬Q’EÆ»ÕÆò}sb5(ò |jzd8ïû¾&÷¿g»~Àª–óÈÆ!O¢©L>ªZÈ8} F¦gløAÚ­öî{^ôpÉ8­E®þ4K7ޝ™œžÊ¼®Xšf„L*¥9L+±aWß.57à!EqtÁÚQ½ùö+Å×òïòåªS«2Ó¡TtôYy'’ï¾¾Q¡;r>àªUèÖäŸJõJsɹÜòôÅÖ÷ÛXÐ}×nŸ<ïvË™çVu¥JYbWïm S½»jv^)`9ÈW htUò#®„%—-„%ƒây”\¶ÊÅ#C-„bîÏB¦§† rY`I’ðAÔ&2!dle “X‹ÄäCÕ,% ©1¼²yKB¾Ý·èsãm‘±'Xo|¥¤BQl7;åQ¦³\³Ìõ0¸/ŸžÛ™vÔš~é·ÀÏy÷óÕ¶Gz:”Å‚‘?‰a²¦bЋE‚ø9Ÿ¸ÝÏ,&[‘w¬§éË|±¥¥3te „iùòLƒŒP¥¸fQPÞ ie¾M×™”——йÍg`1[hdgh B™b„Íúí¦ÝÿiêìZ÷ÔÔpé»éÄ!ÏØ 49“èiFe kÔ¾…²i4G·¥m]SÒ»‘wß°µ º¦Øq´;drêTËšvÛ¾{êšk=JÈü^šy£¾û=$%”[á4‹|¤„${ ßýéÔ4í¢Oæœ×íLó!Ï,›&uÐa~÷WH²›ºC³GN9 d6â1S„Œ÷ä>•:ì~ÓÔ@h‘<BF ¤<Äxj -åÑX¶?¶™MóßejÖ™sŒLŽ¢Äƒ%fpôi,{a"„ÝfŸíÂi, <½!¬JŽÁ’­8vŒˆ9 ¡…o‰£¯ÙX«'“REé&¼¥€°J›Nù¯ï×nl2ñJòòR8¯¾bíF„L=äÇ6îòO¾ü8Å×¼#¤úH¹ˆ ú;à7z‹÷’@Dy¾®øž~A¾1вÿ>/)EÈì)O£tEÈ×±È/‘DÚºâk×¹³>BЈÒÛµ9´; ;¶Ï¹9´ËŽ¤Þ¹Ç@l¥ÑÄ@ #/b  iˆØ>J£U­Ö^&^tÁá™')¦ñ…¬ô‚8 M.ºB¥WÄ)ÖPUÌFÛ]ý¦–KH‹L<›Ik]IeFŽqX”Ó°m§}Y ÝÿÑÛ‡åRÅr±G¶ÏÎR×½ûãZ“ØSQú8hßãÅÎýïÏËÅŽ»ÅÎw:]ìÜ¿ùD¬9ßy­]Þ¿¸k^U“d‡G‹‘ñ)/½«*Ú»¯ôºâ¥ûqjv„¤û˜ûòƒêZd&Û4®þàD'v­2wº»¦çÈ£jnò_s¶®Ne òü€þÞtÆÚ(iR.¢Ÿ|€˜Æùí-`¥J‹³€HWõ:"=S[LÂZ!¨ÞÝÓ«N}¯ÞÝ;-÷ì!ïW*ï¾Ò}ß²XrYdеlɱËÖ­@{Å ÓÓù¾©ùï¾÷ÿª€¡!ïÞBûAÆ^ýÁz`ك݆!H²yÏùØ×íMˆtIû–t*áîÏ+un!ª™2²ák†ôêÈær3Žkt¬¹IW/kEZ—; rTÀk·Ò>üêñá@?ƒ†©Ež¢KVÒìV°Gä'·šŸlßý_0%?öŽG|qfüdН™œ:ÁˆUqu«â#¹r‚áƒÛß}®‘ájÍ6ö° þ£ÇÞ- Í^ƒžKä;—œÎ¥<®Ñùì€Ës.9œXðìð¹FÕ0•¹„ç¼Ð3GZ}‘ïŸq¦\@àÌð¸æä·÷¿»Ùñ—l¼ª?f¶bÐר²ZdèÂlpM¬LT˜„l÷k–²ä rw>“DŸ—jÓ:“ªî¾õ\!dT7~Ã|^°d™Òñ¡yÆî#b÷EÏ »O5Ã:v_ô ±û;ÅãðDÏ8¬ƒØ}‘Ç$ñSq*Ñ‘óÒé;DÏse¢JŵªÙ!ã}*î£Rqm{¸¦î©ÿG¶£Êzt­*~bÈóŒ×N]g6ÊYóH‡µ´= ÏôÂBê>ÂŽVû—M»ÄÛµŸ—}O̵÷FÏÿð×pkÈóyá´(æ&0Ü"Ípæ?4åùêð'®BßjÂÈØõ•èL”âQÏ-ûUß!“À9yW!‹L^A ¼‚,ò~æÔù^Ai¸Ù¦¦a®Éë®#㈑Oïäc×ç3$n¼>ý#kRú8-¬uÞ‹‹weøŸUËØwñæQvÃ-ÃÙè6äoÞ¶P»ÎnAÅŸI)þÀ—¹zÎß’){Å5r“jûŽ£`Ͳr2ãk>ú¾bƒ‘œEJd5a®«%;ô¦™~"uZ“yj;7ýv~ÔODl?цá~"àƒE¾+À™p§¢,¹ª]{Ü)ƒŒCÎŽ;eÜ)†‘i`µÉ½K–†•Ü7OÉ] /£r6»hvï°òîÞÿþ¸ŒÚ¬!Ùó’Éܺ¤jvÅñ’zXn$?ê½’SêVÅìBÍ0—{1œ“³W ÜÔ©=Žy_þ(7 jó²[žŽ<.7uzsë¼Ó‘?f¾o6t°k¿n—ÙƒÍë^·°·‡êÓ/ÿŠ.:;|èu<‡ø]-Cóè•\vµ î¤úJB]-ÒâAœW`ïx%×]-9œÁ^I˜u¬5bàîé¥ãÒêz”^÷KÕsÿˇ8ù-V=·Èä¼Yö†Afo§e~С˜ âõ ëeLJ/®™]g9>°sûšÍ,vóèõºxw_À ¯c×x¬‹ÑñþŽíj×¥øvtß$†$mrÖÒfc 2Sõ;â[H´5ª öËÇžš¸î1ŒŸk6—¬²jqñ-ÆŠ?*›ý1ŠÚXê–7B:¯«Ò£%Õ†¶X—K„L¬ c¡SùÖoº SŽïžîô\T9² TZR„ÜÓbÔÝŘó£oòqÔR»¡ïD/n:¾½E†”[¹Sëˆoéµ¢ì›Pô[(q[6àwÏμ|¶Ÿçåóˆ£[ÐËg7>£[ÐËg7>£›765ô‘^ª£?ê"I©¹©#hU4•^ªò¢ywù%{Mí¥:Õe—«j;>Yþ+G7>#¯3Î U³Ÿv=­ÛyÅïžgÜJðé¶åô6_^Ú£¶t 3~NÓö¢ èA×±ñƒÚ¶— §á;¾+Þc(h{hÿ®r MüÕÁ>À”´jüþQz¾<4\,øÏ×qûõAÆh«uHè# Œ*¬v’xÔ¹/Ùú"}ÈRçðVñÉ‚«(DYû tFÈ8”às’Ÿq”\Òëœäg%ÿa¾Óné§Ô ÍJLdD³Š=}Gž2 *rnâ¥{þ>H½ ä4²œ $ ÎášÝ}÷CÈsL!§ÏY¸"š•úò–8†hVù8êF!MÝ/Ê3~H;2E ¤-$ºB=@]HG÷¨¡6ÒÇzúý2>Z䞦2¦ Ie§È/§éYhÕöÈXô¿†NS> ¤¿Í7 ­×Qqa8†Fž|צ•Om¶úå}÷0ã›ã»cv¶)Ðõ7‰#Nƒav6i6„=ó¡¶!ßå͈'Ìï÷8Õ-oÒw¶·2 ”°®!n÷ Ÿ—ÀDöý(þúò÷~ó¯ZIú³þ·ƒ¦ªõ5ÔXq|(züù#¨'êA#™Â}ÎÅ9t?ö'T^ñQÖ~v •Éþ‘.ð¤2u ²®tØŠÇT”µ²)¹tæ½×¥tF 4ÃØYCœ wPh‚‰}×ß™Øæ×<·éõ8‰5Lÿ©[–â•$:\Í5ei–€l Aš´àÿTé˘`ŽÓö”™Z¤2‰5ÂÕ´*» dÈ òŽˆîš|®lÐ ÒRk¥î“Øj!ÕȧŽÿ…¨Ú ×M 2ÓHÉ%ÒlœºÝ5_º„¬ß½çœóùçþ£È3ïSGÌÒRnÄËýÄÊô<Ý'¥R]B#‰¯ äüH1IBEùBÆJl$bñó·”Ù+@ 2;)Jvx+‚ù!_§EOIÏf ß“[õ¹‚r]ÑLyáŸ{ê‹=hAj­ó¶”•ô­fÝîª ö Uûl"¼¥tÛ}|#ö §•5.¯:Îêv¦…¦¾Ï ýT|ú‰Eg7L¢»7Îç¦X§©ÆPè‹-u©œNÛ’oMÞ½wðtÙpÍWU&ÎK3Ôn÷6Ðì ú& ]ûvwÕ—-˜¶Ëwþþ­\Z|Õø†R’®Kº¼Ëçbs)t’]¦Tƒ“\uEÐ’QœÞ04EtÛÄû>ëºRqlý`hrpv.±OÏ:pÉÝ }Ç ¿JŒ^ÏÔJ|¶bí)Bz©4-ü+wû:¯¿UEz„LI·a' cw$²cXÀe»|ËœcäãD>fÀò1ù¼Á×Ì.äc0ò–ÙðW².X?æƒôcþOØ•$ËŠ+Ë-e"Úá›ÿkVµZÑ%}V«ÿjC qgpÌÜ”4B Ex¸k¨!ceº Æbñôh?ó±a¨÷«53\´f4”üŠÍ´± õïÄf>HlFC1A£†³[ÕŠËm…¿º4ÃE—FC#KøNÍh¶ªñe­Az“÷,a£¡Éƒ„ ¾ïå–°iñ‹ß´¨ðq;v ç_5o6í–î êݨÝ4XíFCoŸCƒÕn4Ô·]¤D[TÚñó™¿øayÁo6“­jéºPÆÑP™øüO@ÅòG¹šâÙ¶{¦[ö54º9‹ó¼ÎÁÞ-Œ>ŸÅAèʳÚ.oÏâ'TmƒÐ}¯×u0gq»íò†V<˜óSð ÅËiŵyýñM„¨´/ÊsaÏ ÆL~E+%Õ7,G×Á©(|=´µñ6kX'Ã)IÕHzªFRøüCÏÑH*)À¦MÐ ½ÇFRcê=™¬Í¼„{dHœäkÑ‚öYé?µ ñ1„ôî©ßÂöÆ|¢Crö¼Í0|²¼ç‚ Bz£›®FB³)…†‘ÛH”Û[Ï3vùH WuðLë¡”ï)5xè‹æLO ÅH«õ­xÿ(å ©:²›¹™V„ô~mHZaC²æpÚ-j@r¨D]ŽÝ¿3,iÓ±JMõ"|*×öù)z9Œ˜ùºÄ­á\½² ² ¬.̘ï[.‘/Fxó¨a½Èsȧ n»‚Ì«gYhýù¿‘aôÔ.çgâ¤Õ¤Èkò4,îhúžÝ§> ƒnš÷…½]®ÔfêeJÑY‰\mÁÂü‘7ÍÃSòŸP,SZ…ôîšBvrÝ¿PaŠZxka(¹ ¤çRÊ¿…r/†òïEá#å¿¶îý¡¹¿¶µ˜<Ë ÏëóÄsóŽb÷Zljç&a9 ÁH£Ê`ØÆýÔrÞžmetü‘«lü¤eÕtY¥Ÿ¼Õü÷¿ÿþQTP‘×aaÛjó·ìæ?$dÉÇÛsš?-B*' ©mU*;¶´Üö²„•Ájþ“¼(}jgçû£KϾÄH‡ä%·áƒ³hüv6–G7Ö&ƒ{ÊÓ "‡eëR‚†g5êÙ”ÁH”ó”dì\‰‡òœ ÙHñ‰â(»¥ërÈ^%Ês Ï6ÉYRºw,Z[24òc¥Bnë”Ò¥: |‘Aê$Ó¶²÷C×½Æ÷Û’f2É´­Ÿš…€×1!ÏÉß‘Ìò÷[›†â3áëÔyNž)UEb[¿E–MǼaèÛ@µ¶-ƒ¦ã:fþ}“çÌ4k«á3…ŽÃY~0Ôäƒ@¿²¦’}ÿŸ)ÅP_çyA#^Õ–Ÿ[Ãàú2¡ v‘iÁ^.€A—e -~§2Ϲÿ+&t)âç=óaæËmE–í©ÌÉ4CAy5"& Á÷´ý¹T@ißm{~y®‰ü¢Ø÷\I,¯ížt­ø‰žý/*ÓWÃÌ® o¶ËðÞN_ñò`Â."ö!=Ã)àkT­ N–cé Ê—øi ‡ø! ~¬;PÕ´7kTøP5Bhé9e¬•üj$ .“¯ºíÆ–}Èp>Xs-©°ddâdsáÃXÒ»I¸5*áÈØ•p[T­EH‹0+_¿pÁìi¶gË‚ä>5×ñÔÜ€¾u(k}·|.SŒ î“x=Oâá_“xƒHâMÄSÈÈ­Bm>“äº(ŽWyëŠ×qª€¹Î÷ƒÿ HŒÂ1Ýùe,©ÓÃö†!‰«Qvõ‚ºóï¨ôúÀHÞï¿PéÏ!¨ôõ7Túym•^!¨ô—ëtSéf¨¡C1…w¸Ò{PLáª63FÅÓ’òxUoõ@óy?0Ò¥¶5›.Dò&O:R§±B!oÿ^–ºStX¿û<6zS¶ìpé7û—VéXmÏw¥·o3é,½¹‰Õö|[z[r<æCémÁÈà¾Ñ¤æº›0C¢‡†ó:= ¸%ïø!áÆß‘AºjÛSèUëçé=Б‚,ñÞŸ?¥STP⹨ ‚`QA‰ç¤‚Î-¢‚*$qhŸ[¥L…ôo׺P„1ÉóZwB˜áY ö›P°¿âùX 4yà´Ö]Úa¤w£Ôȇ2’8~O3¸4¡éPpË˦Ÿ§´9Ò2¶×¶²§4 â•JuG@r ¦óöþŽÎnEÈà&ÙÈ}¦-÷>â…G?Û½xá_Üû`GðÂÃ]DVÅn¸ÎG…ã³kº!=GYü¨‹î@H§w i0"Þa¦T·º]f¶x7¥F&7ÚiŠÜR§Y7BÌàÙ¤{éH-wÉ$×Õô<+$±tL•Cm9°]–y½"¤(hÊØå“–C6›ù‰­U„:”4ÊY‡#kÖ¾2´‘ú¨2m“OFFÚ„…ïÚºãz`[ç<}„”ÉpÎiÍU.œÅ!Û||Ö|.2qj£‚»9A ¢7Ú¨à¬B,Ÿ¿{­Y˜óäý¬5 Än%½Õš…™lµ’ÞhÍÖí»¡ÕJz«5 Zž„¼µfÙ v ¤SkÖŠ.ˆ÷T"´´f ñžõXh ß&!O;¬E¾"Ä©)8ÐF@ÈQŠsFfóÞ§ÇŠ|| Ý>¾½ðñ]ÒéãÛ™ô ÝI!Ù°¥WÅŸvF»•Óö !¿íŒ´Ôž!´Œg±ÛH,ãä½j÷ò¤Bg±´Q ‰/ ”§¢…C–­E4~… \%5`dˆ,Ÿ¨L^ß4íÁ+F!#«X£Uüë™5g³“ØeIÆ–%NÀ:ð˜É}ä_Ûgm’<¦"ûcÆHOëÛepÖf÷>}¦ê «ã+µlNŸ]ޱ-ØB¿#¤‡5bD¸Ä¢Ùq¬öJ§ü÷¯Í™‚g“±¹< $ÖxS¢TÒˆ!v;ãFÌûûo;#Öˆ™á)™vÆ›ý]Ç+r|úUb®MdÚïšêfc“I|ru¹6DSnbâäw&A<òñ·W­Yâ»Û¬E  I¥ª–”ªa˜×ì[œéVÇ—§sGjxýiMa7ôãçÖØþ‚ôPV;éæÝÒ7ð½ûñEñÒD›žéß6Ѧ­4¢³‰ö{ZgX¶$+u|ÚwÓ yßhšhI,ªÌ³}ìÊfÅcÆ¿:úü\Ìuôk›ÅÁjdW%0-ë¡í¶uø×ÃߌP-2BµÉ „¦qxÿW’ß”0ëñÝÖÜx*d¬û;ó‚GÀ•ðÄèKš­ë‰¯3q’©6ˆZÂðL…*§á¯‹¬Úç®àð¯à!2Àæ½?¸JÖ‚Î÷?PmÙÂhÎh¡»|sG‰“ %è7à9@"WT-hÛåiê#‘Ó‘cæ )+RÞÎÉì[â4‰Þ8oVèܧæUkÿÕb*$ÂgsKw’¸û.…–Iý¶¨PAcä•Óu:;ÈXF k©g2ÛŠ=Ûl@Hßâ@Ž‹¶ì6•©È¢°Þ´À×=d,#Ï¡z©šå? ¾÷6Ñ/sÚ¼~0çýÈ¢°JW4…ºªMÙéârÎæï4]ðu¾ÝÍßf*G…Uže5…•½ùŽÒt‚X(²)¬w¶WÖÄûK²zÍHDÜfÔ, 46à$ò‘°ÐR ã÷È¿c6}!UX–ÇB"yUìŸ6ïÛ´ÒÓ:’™:*ð$;Îä[Ázd–úÿ ÉÑ¢”ª°ÓÒ¦=ièR’%¥P!N~Y|ØžŒÇ 4Fø>{dMÕôÐË® ç—q¾Ÿð\ØÖÏV×kIw„ŒŒ(­è,¢´Ÿfª›ÏI2¶â+u;§°h¨†TdiD(¤LGYNé'ñ)î´ÚdÕ§:ësiÒú~¨Îb£öýÆÖQ`zF¶F„üQ½/ì¦Ê´h¾ÛŒÔ”D2]ûhйŸútÉ?†ÚbMM%g6)[ö†Ëµ_Ò‘köT—±Z×êòB›¸/é³ Ê%|÷á2M­nZK–?ƒæãº,—7 4"´í :¶ãòs‰åK)3 †ª[ñs•’æ_ðÀ?i.]–n]—bèÛ†6‚qÊ¡M:°`C­†„¢V¥ÇÒQ¶ø•— °:„ü#å3«_Žq.OÀ3tÊ¢’¿5 ³ÙyäPCŒF„*‘©V6jQ¬GSŒ5††—úÞ«%š=Ý/£F¿ÒƶlÔªíûCc›ë/ÖI^ÿ›²<=>— 0œJÁèl„¤ÑÂö¾²Ûð+ /uRý¶C§6y¡¤¢–T{v[m³v(è*¨Ì¼ý'¾ØBI) `›rÂK !F'DÈ?Q>_{Z{6^ ¾Ž83]æà‹ËÆfö§ÆO€÷6ìqš½*|°n¥ó<›™ºw®¬`ÈPv¯ó%õ'üDLh=}µÐ´ò>ì:Óz=ͯ'nK¿^$Êô˜ñë9ùfŽ/ñËmuÏ <¦Ð¿Ý÷Î{ÜAÄ›ÄÞã½&{¿Å(}¾Ž|¡™ž#¦V6™ˆã ,‰Ì5ÍÚŽvÏ«îê£*‰ÎM¡ ï“ÄÁ¯Q_¥ 2휵åìNÖ?B:žÊ½—ß ÍŽ®qàد…ÖÞ%$3…åy‡Þ­™÷1ŽË I­8rê£ B%‡{ú(\fœMä!ú(óiî(v¶µ'×—4óó©|À2`ã·-<1ábå8^?@HØ·ÉkJ϶Y0Ò7ÈJòÁªmæËuFiLwa‰^Òºh ”ˆ+#º°Ô*ÞçI‡ÎúŽ ÕwcðNÖœWÀñ˜ño7†êO=‹Ú=ΣìÏÍ”´¬ceyÍ<ÏÄ©ì@Gq¶WwäÛ}w"±Â‡¬d{)xÃc‹žM ªTkèwNuk‡BÞ/Îtí T«¾1-µZéZ|éztüëÁ¯¾À ôxé!Ã_Õ¥Ì ‘ˆBªbÔõërïJ϶e3¾W#·Õv21gûRéTž\ñ¸kú Æ|ßi_6 }YhíMÿ…“t²¸'Æ¿5ûƒ´¸ÿú% Ê ÈDó”Žó¦w$…ôM¯3œrëdï(Ï­DÈÄ!¥t.eší’_ ^óT ˆvBF™«ï½á5³îSIñuƺi!âÔ¹L%›x§¦Å(dbñ(äÙOš¦h¿ÑOuË´ [’ér~ú?z¹Ç2.jqRå‘:gù›7ï9èC-ÿæÎ Î þËO㤠µ6ߜɧýþz:Ÿ­¹'ÿ!‰][}©þ+xHÝ·1Òûín/½Ã¾mÛ+ÈzG’äùs6¿~íGfªiv¦YJƾÕÈê ‚.¸em»eX„$fGâ! ÿâ·oÓWû’_°ÞpÑSyö(Ö¦ kÛ¥ø×»=*›elÓz›ªî‰>JYzç}”c¾šõÆçJò’æ$ÿ¥2& #²·¬Wòx-¡À¤‰% öÃmý~iÆbŒTÙ<žFÈ5'©Ï¾ý8°Eçò’Þz ÍŒŸ`ž~XÐP׆*&Ç?ÒæHä¿Ã7º­l' %¨M«’M”Sy®œø5Ô7BÚêR³fÞÏ6sBØ‚)ÉÙâ¦ûoÿ‰¹ÆÕ|„t=ÏãÄH‚Ž‰ÒæVûÿ'ìJ–Õ•à/{Ùû×ÝŸÀ,Ädâ~ýÓXRa ÏÙf`BR ™)&BFß”l¤îk¾Oâ:zý0qa"¾f|&îûáÙ“š³ ¥ÒÕ€Ïó(1_<¥A¾®B×Á=È-ãÑ E«`áÌÃÚ"dˆºÚºŸï[íÍøFhU¶ç¸'Jn‘ƒ‡¼4”²ðD7_1OS]üÜH¶1±HÛÕ ƒkÑ^XC|ÇKeôZTº¹P–â–*Âȱþ€©Õí¥Kû,«q !µ¶ó/-C %£L¾õª…Á±þÔ ®¸»&XKÈîH‘cýtZµã  ©Y+Š/Ts‰×öˆŒ/dsEØë~=¼yG’eAï̉åÕ”(ê˜ÂWì¹hÊÔ„Bª½Cº§òi¬È3cÚŠQg+¬´¹N³É@úÈ#ÏEóÏÁ¨m’1ÞÛŒq¹´Ì7æ[¼\DT£=±zlº£‹æØÒQ¦C2¸`¥J¶'Œüµ4LKw¯—" ^wLBJÛ÷^ ¾HS3Ç$ŒÂ»ïHÚÍÀ}†»´¥Xiaï7Â4~/Eÿ襠B^ôg¨B\3¼UsX&> dpÁpæÌ»fômf%ÛÄE7à E¾IÜAˆ­nçq!¶(¼c/ˆ –2|Íðì‹›´ !<ÑMÿ4„•6Œo\sÙgwA·Ï¿:a#3(/Ài-Lþ‘:ƒ}3|Þ§Îܾùe<÷•:k2´½Ì„Nµ8R¦¶—9 __-˜:ªÝ§]j7rl¥_Ò³Ê7öÚ†nÓ_3<¬Šj­osdÙZ!d„D¥­ú@ÉçlXG„Ô©Ýßzäá>»’×ýR"¤Ùd@%ß‘:Ê4W:m°F?G 0ãp+æ|)bTj»ò#dQ§ÞQ­óÅrÎc^R|ÍðÛ¾Gýpñ¦ìxF_Ò‡úX)þjž? |›¾Ü·•¡õ6Bü«ƒ•gUëNˆ¥e4+-Í™‰3-û¤Vº(n‘nƒŒOE¥%›ÎÒ£‡ÓO9ö ŠÁªšî3¸éäò> dp’DÐ¥$îÆ3@¬iÝ_)æ}Ùë©Ýñ5Á§:/¥¶Èε)ƒo3òúÆþþ6µ ¹[ÖPüD±Æ×ª…F²k`çŠ/ÁˆÕ[g'Kj*àßäR@g!‡•qwéÍ(ðJI8ˆ.Ê}Z½¹|•’ìv¨i”îùÒ‡GîÛ(¹o°*Gá5÷×3;ÐÈ1ï¾…4UäáîôZ0YírÐS!sB`ëkÍ  Õ<£év9í­”›þ qR¦>oaµó8z¿T{E^Û‹«æ_S‹®[ÙI͸ ÚÎKÊJ„Ôö•JôQEgJ§/7±„Z·$ƒtìHhÿ°´é6º¸/þKÍ”¼dÃy[uoˆ8#lV¢V&cVVy¿7Ë€®ÁJ²ŒMÛX÷.RšoùüÓðÝå§ÝsŠï“¸ŽëÊoåÂסqs9Fh™¤¾©…þà Æêyh1REÆÿ¬˜Iò´ù¯y‹O¿ ÚòùÜöïÞf/¢£‹|aø³ïvj³•¦ã!©u²^?[:6ž"Ûשj3ÈÈß=¨1¨CP}ø§FHâIMÖÖЪž§²{÷+BÆþɮ٬lÞ !gÓVPS(‚°oKüDOo]¬KcgS.â3-Ýjç¥"·¿ø×ǽ-ÞÅ€GþÇëhª´œ„øùlÈŠe¤úp1ReºÈùØ÷Ý64n½ñS‘ÿÓa´>¶°6»½¯‡Ã „T§y$TžIú©n,ÜþèðX/$Z~Šw_UêåªÒGÄiYúÔ¿”Ó2°@0í7Û–âÉ÷H.lm<í¢(zÞ0ƒSi¼ ¿ÿºË¡HÅ{Mòs­r$5«\ìG°¢†l±°B·i#EÀ {E‚W®ª-¯KBpå" Ñh•GPéínZ:6ï,ÇÈÐ[ïÍW"µL61ºÙŽÑyC—og‘ðÞv‡÷é›Sþ‚‘&-Ý4PX›=sÊ3ãØÁ:êÌ)¿öOq –š@-BFç_³*"äwØç=k¬3Ž»·Ï“øvŸßÜ>O.ã4ÎäîÔÀü¼3¼Ú•¢Æ†§§FUzr™;’ ޤ: j†æ›Ònc¬d$9h¸BÍ  5pj$nmÆ'<ÍN3 ÿzü}¡4«FùH™\œðæ n Rgåz¯fRm²ÀtX݉™$¨éÛo¾ÊeóÕ»…_^–òä)œzãù¼Ôë’Z;©;…ûìÔCCW×wŒº¸Âc§ª“½Wø’È=u3ù‰ò︡‹ ­ËñyìTü6å³okÜÛ|Z¿¬#©Ü?ëfnl䨩g¥¬)ßݪø¼iý*xNϮ٩¶Û²©TÅÅä$ug¤T¸˜Éâ³CÈ=»ÖÅ‘é@¿<Ç_n‰¥†Î” ëœÃÉ‘]φ*¼h‚$Ý`;ôˆ‡ßHé|ä7R“ª<Ëwr'Ò!ËS°€&?—’YJæÈ¥Õ}:¡M-[)ªyšœUäè„ß’Y)UC…áEÙG>‘ŸIpûD»û6“àºW^‹•Á5CLV÷I5W§yÓ´€‚prH«ƒïw7ô5Ë¥Î$ºt%«7¶w¼Ç×t]Z2äמçŒ5£ý2!d„B?ëû-Í{Ù’86‡ºd­R¡u¶æÃ¶"dìuøæ‹f)Ì;·ë¼ï…‡¾ùŽøT·p\ó™wÛ/#:MÁåmŸv@z…¬ÿþzBCÊåm›A1Jb4?u1\N§¥i¶tr_R¶:˜”#Ï–ZìÚ}»ßŠ}ÆfÏDìÙákñ ÕwVZqìe_ªÅ™“Ø¿P¥9CŽáË2q`,K„<ˆ_¨>¥<-Ûv£ô´*êò‰ómŸO»ð?ÑË/Ò Êk›ÒåÍ<ò?gfÛ“2Û†œmrÈŒ”²>Të“r7oÓ!$¹ðã­kàôxaò„—•¶X!%Óöªb@zÝ5³ù‘Çö²‚m†€?NËÆÄ‰F‰ 1E…Ô…7)í¶±ÚŠ<×ïCãY»·ãTÀ)ü›Ãå±Ò¸ôµëç‡ëи뒑‡ë¤qWU 2üf{1•€ç® çß7î¾!7ñŠQg¿N«d¤l ؼüÑ+FœQq¥ú€³·%oÇaÚ7„L¾¹fªÅ7å.eûнÄáI‹¯K¾bOÖîÜÍù°îó€GþçRa+…ÓíëŠ ¯Ð]tg‡Ìè¢×ó2)Å4é¯[ƒ»Ùm‡ˆÀöGªtWªœÒз«ü½~ ¹”ü|Y•šBšì{“÷b»ÕÉÏÏÁܯÔbXÚDk›?´CHF¥‡^"?M¾n½M À¦‚?Ë5If-ÛÝn3Ä#°Ésµ UL0OyWU]¯C§Kn—¤›$>… y= *ì&;žÄ7¸“ál©DtT"VLºwµÛ âQȰ+T§lØÅgŒ¯¹.ƒÒô"³v­Z^¦)F—Õ·¡üG‡ò›Œ$…ÌЃÔkW]õ[Z4;ï2ñ‰D•)ËÖ">Ê>GÈçizµ©ª½´Ç5âQÈl»2¿ÞŽ9_v›Â!…Ì” J}`RÐ=-—¦ÀЇ5IpåmÚ-;ÅPhÚVlL5ëY;޼,ú®ÄÐШt±@ìïõ§MÓ~*c‰öG9ë.9i‰V®t¡Ç{%WºeŽbJ.í uüŸäÇO„;þƒÿr ï‹ ±³ŠüêU6ƒrq¢ÃÚ2„ô¾åÚðƒ–z—å´Á}#¾ôãµ>Túš3-7: _3rµfÍ"!Í&>»,ƒmÞ urHÚJë¾J»™öÓ»¬„Œ€‘œQµþèe9çpŸ'ý»¦~M·iæ¼EHߤT՚ŚS-éÄ& 2¼êÛv’Ÿä‡\2Ž´Œ¨¥øVFÔiü’ŸøN¯Î3%—îvÖP”c$Ì¥\*Èë•yÛE„¶¥VGŸxîvö°n®3§ËùÝÀz{+õÊ´ÉÇË:‘¬Ù$¡EÈ‹Þzßj›\3¸h›*™;—.ÉĊǪv5`òÀ²-ºø£:º+ËášáµÇÒ—k:`$.™X§0 2¼ríp Ø]êÓƒ§ A¬°}úå€ .Uç÷!dxª:O•꫼QòÝ™´C‘ÏB¶…%ï`­új*Õþ$VÅ‘òJ ¾õ“$wЖ¥©³w"ÔWo#½Š¼ì)S÷9ÒtQm™|RÓTi?Ì‹»Ï9l¸û,ÆOQ‰àÃÝgây*ª>[oľݶÅ׊ç`ä½ÕæøìiGswfsL3ßII÷¥òÏÚpš!dpŽÜ²ÄÈЧÀêÆ7©5¤YÛ4Æ/…¥Y?÷I¬z«?òâp‘1÷m??´ÒìÚ…ˆ#?»80„ ¼îŽZEU.E6Aß—A†§ïˆ² J霔ÊÒÈRÈ·™²ø·©}±þnæmêS½|›kµÖŸü"F~É29Ï,•ÿùÄ .í¡š’,aÕ…Ið8¸ÛÉÓªI3Ñ9ÜÎ<® ž)O]' į̂Gq¬n„ ¾y­ƒâµŠÅ_óÒŒÚ;j1;—‘‘¥f‡ ¯Ý™>Ã:·#CÈKw¦ ú” ò|?â"4öž‹’jõ<Ýû´·ù.âxv쨪Y`i_uò“GHɶYæoŸºkûaBÈÐ/öêt­4¸fÝÖÍ !#WͪŒÊ,Í{ºŠ?Ž‘ú¤ª¤Ü §tm&΀/„Ô,e•Œ+J5ã©D¾©(?™\‰à8™;Ä÷"8ÜÍ¥øZ°fókˆïxæ½â2ÄñOE[ðÇH 4“2‚6bRâx3ˆx·HìʕɄe­eì÷,Û2–méä+ĺԘT ßÇv[ƒD&äÊPG—qÅÉjò\¨ùE“àõ¿è½EÈà4#„²7$¼u1õ²7Äcl^ˆìÁ5·"{̨ÃÇu–Ie®&@·Y¦Í»ÏÆ&bÀ’0¼ðm3m_À$އù½.i/¸ !A®8Wiz• ±Lžï¾wŸ±ù­T‰s@Èà¬&_—#=ÁHxéÔ­ûA*ˆD?÷êЇL¢+§nÝ ìœºIô/§nX½£ŸË¯)²Ú÷ý«È ßQô¸eÕº"+ñ¹ˆ¿T1£¶ÃåRÖÛ§5ß·MçX”ò¯Ê]ˆqoç#ƒ+—Hï½GáMË›øŽÜ™!Šîæ§ç¾H"r3J|ß8¬ÉžÇÚiž|qï=¹Yå×áî3ùŽ ¡Ù0•͆pŸÏƒ‚—»(ÅIñS渞v˵Zè§Yض¹wt#þ‰JÑÄó“ÕÏ“«éö-]jØ;o2ä¾ÉñýdйN¶÷²–.Ã&?—š[»¼„L¾ßÖ­â÷ †ë\ÌùÎ:€dèéÔ…^ç)›wX““Çf>DR)å{ šÄI.wwþL·ž?u³. îšßåL¶s) /ªb.IÝ´Îýzt½zï{:ASñÚºµQIa$ÐE`´ïï!Þ<•hë0µ ¤xµˆãüviƒ´lfyÍ÷Þ´‰D–š-ï—²™ï2óM˜fšÙñ¶ˆoTrŠ„•Á3*Q9ÀÜfÝ»ao+&öz|Íä9Õ[ºãg~#eÔsrͶ^±#/–ŬÍðÈÿØò¶×Ú, mÕ¼üóÐ QÔ”Ú¶þ×ãÖ ®¡e¡¡_ÔÙ=>ñtËV^ã1Õ]³2DÓú÷†z!1¥ÄñªwÛwrcö%MÉ\è—Ü´µ¨¢äŸóõáA%ݱÍïî…0Ít÷Š0ðì~'®ë·Ó>©øø6hVñ;qMwš6Ê쇴߆a*ì³?XðK9ÿÈ×)‘›+5AüþÚÿé.:=dJb8â!dè#µÁDÖyî ÇO×r,ЈŸ¯æžc$ÙoWÛû¤cãJ¢O×¢¾æ²0HyMÊz¾f™œ—rúvÝ¿þü~vÞ oÆŠ>ûg€—ñ²°¢BKû®6»'fø¹QZè°°ºv«Î3ðšjü'’¿NÅj–}#å5)+ùŠ‘~¹ÍS:¾ô]?§°>¯¡Èït”#/Þæ´À\ ¿ç¼£ažÊ²CÈàâmJ†!C?1¢ë3’ ý^ö¾/2ú¾O:•C÷]ܧDNè>£ ³4見~Dï(BïÈ=‘Dâ'ŠÐ;rÈ}(ÏçïHìÝ9èèd|úqæR»Or]²WGkž×’šL­7Œ¼èû?;‡`Öuu©eÇ×Ã&Ï$ }íjò|^‹²©^XH=_7OÄ©—æzݺò®$…ÈëÖ•÷MÈ+WÞ‘‚T%yyºöÿsî¬J"¦i„}óõsÑÚ)Q:®©‹’¿u²ÅØ“N2³œ§V»Ú Odd%/ç]óþpÍçiéÿ »’$Vu$x%Œ0Ë¿ïÑ}ƒ X¶˜ãŸ¾5–T€x^f0ÈB*Uee~¹8¬ø9³àÎ%Ä~Ú2[Î:øâ²û•¹¶'n˜dÑe`ïÑ“²ø*°÷éIYØ*½¦‰¹ÃBö¸K‘h8,d+1ŠÍé dXŒbà£p¡uæ­6ÿjÿ5}œ|u=_šjÙ½QPŒ‚‚Û‡A¦Gûõ½„™A>Ïe+¨§îmafóé »wº¼ž:l’%ìU+¢äº›éHr°•‚jJ[vsçIßläh@Õ ³›Ld_Ã3]ƒÛF§¥ì¾õˆ3«*¶5EÝæøî¾nŸæ_kñqÂÕOjáâ|î*4Q]±dÄÊ ™¸bÙøXŽ9¼QR´áUõaÌûžWv|¤nÒ?/45EðíêYØiW™¸I–]U¤ÿ”¹&¹ÝÂ9}YéÌ;@ÞCâ ¼Uâ v±#·{@އ.ã2Ü~>e `rKÂÒ"Têa !£Puj) r#afmïo]ä–þ…YÛ®W£kY†»ïª§•µ£iå1_ú;cdtâ°\tÚayEÈø4k9´í[|͇ëÏnÌ»ÿÚªjÊïϵy²Ö‰-aìØ¹Hƒ<_ë8•*àøî©¿ÒRªP)‰LÛ/ü›Ù×[—ÈývÁÁ•ë’åb’{XµZ6¡9f¹_ªVK«!£p͉2º\?{h±"÷‹Š¬ldæîšñUð픑û¥AÙÄÝZç{8hI-)ÿžšß\|ÇÑÖÛÈïïšç§Â þ#þÙnœ12òZøÝÏâÄ÷Þ·éñ~Sh¥ô#fÊ0º3Ù©_ZæâTnóTÔ3e™ø1ÃËäìñ«¶ßݱ`K{8äËœóo3SŒLm—‘j6Ñ‘@W5Ÿ_µ ø9Ÿž ÕÆºÙóü l3ƒÌ@õTi¨Ê1—Íûk·îFþæ‹oÉqYêo ýÝeW Ù¸µ$r¿â†ù¬Vá)3ÛMIEƒ~Z@—>¤ öX6[µÖé˜ÒÒ¨\ÿKkñ^Y7»/éé¥|£ry÷õ]R7¢O/öÇôXiGáylV±Hãkg«­]Ó¯£ÍÂß͈)Bêl¹D~øÜãwîÔØddW‹y×ló€ïž9uXtwÆ_C‹Gþ† îö3ïgüòw_wÕHÕüºa\úWýÝ04:ñ3놼ûr(ýX¨×³§—ÕX)ŽI|üîžÕë5+‰€ºf+~j¡Naı7Eô_W-v@Tj˨«sÞ´ÍkÞ½Vê8Œµé’Ð5 ØÕZèÓ5%™ýF V74Ó¶{Ö ÛD+uyûˆˆÏÖŠìì¿y½Ï¶°Q°lÀÅÿVdÚÕ¸Vv¤ýð«ñ¸F‘%›æÚõã­ËbÏëºCcà¥V²çm€wŸ>ß]õaCB@Qí*×V¿¯Tù°ÐìèÙ`\l£EýBžD6™u‚pØ·{9ô¨/²!Î~VÑ® ézÔ§aûMóïÍ2r›ÉË´mößWÿ’¦MBêaú³§¸l saQtRC¥€#( š£H«†hÛ$h¸b¬\HÅ×V P!;26µ$ÙÀ=çã¢þ¢Œ7:„ „ˆ`´(Á­4Þx~òA̘ø†+jÙ÷‘}Ûöt@Hà]ÛErœ¦×8¬’Aºœ\w4m{œ^ë:®FꦆEw—*µ鑽v}Ûuø9“²›ƒ$¾u¡âŒmþ­·m‡LwA•šm’rZ_üîOK¬Ê¥œòòðÅEN§ê€œ²Á#¯§u¿ì‹Z(ãïyiñ0é­ä:Ï˰ƒ†âñÍ‹s}ÿî,ÄJ/ÄgƒV›Av¯OùýB’xlð#í÷{ÿø!ãpж¼(dÒÍŒà‚û”Â&݃\òBpÁ}\iÉ­îò_óLpa—â6ÈÁ…—\òBpaÅw?\hà¾{v‘ ÇH£ÔºWš?ôEmzŠ„Ió\saµoAU!¶ú¾œ)ÑÊiôK¹%À‘ø¾_C …uë²tNÀšÄ÷]ª³Q&Ùòšm=tô)šøî m¬e¹#Ak¨"d ŽS'2N“æña–S_Á5]-S5†U ³82ÊÅ7j«ò$Žƒí ººàþ£KÚÐÆ¼7zà=^…Îr†¼ÖacMçvšø Éí5G©ÖÏ«ÄõÚͳ»ûuâºíÝx^$®û¥Æš!äiâzÍ›¢ò!“SbYÉØ‰kƒ &®Ð55ÈéÄó¢é·‘8Å6zõ–w«|ÙÌï®ùÜÍ%iiatMy^ð$4|ã&c¨¡£U)s(60 #¤¯EùÒP‰üúÇÿø‰j„…åMÈ2]˜8V3„L,Ë!×<õFù¦”0R×ÿщ‚—Qƒì—fë :"$ìñº*ßèÖÖ¦.Ë_‰Ÿó骵z„ˆ€WÖoUã™!GkÿüiËWû«¿Áù£RÝW2û郑±=~%êr_àONœ µ§„¾æÌó!}mÏZ‡ê[óš~lsñ·gEuÖÈä­ Ûe#“—CVTg…[k'®©ã@»Ô…Øàáæ(ö«ø2C¢õnŽ’Î+´'Ôª±7w•ü#Ü=d«XbÝ–<×t[j[ 2 F·*>’Ë”lï‚›GrmÀë’S«–'¥ωÛspÖ¨í’x,šõSÒ”qeVúMû=.—™ ³Ã ¦5…xÇßb ¼ù™áF™^W ¤2Ãÿî2Fû¦.?bQþýĺŒßÆDAcÏi³B?ñElSGcO>bõê6”,Ò„Ê£b”¾#ì2¾ÝÈ rs†‘×XkŒÌUûÜÔ~à|赜!‡ÃÈG˜àßfý…à¾bd…á5‹xf'¾Ù£j¸Rfîšñ¥Ù#Áj“ÄÁvYlöh±Óÿ7®(ê“7Åç•[äã±è¬ ŒC†Ïöûb û0„ j.ô÷[_Î29ì ÚÀ›ÔŽ€ÃLB‚6° 2(Ä7;9fO$uaDÈsûipJÝÝÓKƒSêv¯ñæ`!®ËŽ0žÏk q—åÙ5Þø:nMN®$udÁÞýÐNƒT9uk2j§9š|Ö/8ž‘û¥É§“„ ä,¤ÒÜ=ú ivCÏ÷áœ4Òbd42|­d‰A†I#]ŽŸ3PHõI#yA ‰\ì­t% «¹­¿iê?pâ#ñ•á6uí²„Äˆ‹,sÅ:þl )'*vD@>öÍ¥FZÉaŒlÌG„Ýk6óH8jŠˆ½c)—†!$žÉª<¢Ü1ʲ-G„Œƒ|G·ËçõL£A&¾Vi*§Ò#¢únBÆGŠÕ¹Vú4D‘S£$-½Z„<%]ÈíHž'Ì]ˆzãIþ’U…µ6½0zGmïä¢#L¬Þâßt3$LJ]”ið;Âö¾qiçfÏÛÅéPžd!R~Þ¯Ê=Rc@ÈSc>e‰]Qäa«²±2V]QŒïyŽH&‘Ÿ2öꡦ5G­7üÅ'|wDª2øqþÍBz¤ª—!äªç¬ª¾Ç×$G$³È!S§›X S¤QGƒ|:›b„É¡ïË­'¾fÅÏ™‘“EîFþvV?|íDå-Ô;Û ¨|{1Rùô£¡LCû=4†b›ÉT‹Õ¾øMe¹çƒ…>ŽÐÉBwÏjöù?à C'Œã(92ÅÕ==/âUu[}ZÞ\-z;.šË×ÝUÕŽó鲤heòÚ­(øZ|üZщºT÷aÃ\d×B——¶}ɃMWn%Üÿ±ëþWÉ;ª?¾v}÷FFþH;ÚIá­f 8<}k±u4ð8%OߢïP›SÇÔ¢• d‹ rDª R,:x×Äv<|ÊŽ…œcdz^¤òˆ> ä3d£H+÷é'±QtwOÂôª6p%rä+¯Ým§¹+=Í]ò|†µ1æ.y>š»2Õåkî’g(d×MW^wÁóBCNæê½4 öK…0;žÙEñCk µ…m/ ÁšíèTÅËÐjúV,c]þRA%­.òöbtÈŽ©™F­ÏmÑ´ãoëVŒŒÊ#w‰à,Úû¸×à7_·uÚl™À·©ÜP[D¼ÑÚ2pT6Hâ¾8‹le˜W-~ÎÔÙ¿Õ&­ßc×4ùoÄȧõw7_‡˜òrwLë,ڰ߸‹®³ø"Èâ›·Øg¿øNÀ—%ñpwONÚîMBðÇ«ïÛ!ÉÅsæ>?#—X›KÁgäš§ãÖÏ,½nEu‰¡,½nEÝ#ƒ­¨ß!»ÀÍì2å/àÔd) ²ŽM«î{OÿÒŠ Gô,½nE…fzƒôèö Hy1ˆh7ž™o“ –±¬lÇúkCQßÃ’w:;"VoñJîß¼p&A²éíöY»Ë¤·Ûµ)¤¥Ò]¿™êe2Ö¶«Ø4?¥UeNo×JGóL½þ¨3íÀìÌÒÛãZ;æ|z{\kÂw”^8ˆ¯ØÓ¿OoIð$Ý š€ÓÛ…I:T¥·ôªÙÓ©Jo¾ÙßQŸÌÒ[v©OæŠ  =-…PVYÃgjfÓ»é? PbyµUÓŠHÈ&Ò;6ëÕ©.=çÅ™jüæ¯!½âœuZTŽK—ÛË =sY9F9T [ñ±Œyƒ `‰¯Ã® ©×Ët<Ê7‡‚Jz¿Ë$êä®M?8½¤w¬.銲­)Ê¿y÷zZFˆ¥•'¯aú´0žT<.uOµŠ“ù«X‡îÏ™J˜­.ar[ÂL=~sMãr#®93tÍ«ùéG•éýy‘jRF‡ðe¡øSnðŒAz7nA‰VÄŸ,·)¹4º=VTìL£[8e,ãOèÊK£ÛE±Sª2Ã݃}› %¥RŸÒ¾ëÛ\QR*°þ6µ*óðÙ÷û†QŠ/v„Ü+ç¤A¢ºv/™WŽ‘Q y&I«ðF“G ;—R¶XgÓÔ#ªK¸+Ñ‘½‡múä-Bžhpþj>Íø…Ë#ªŸ+€Â æq¥±([¤šFé_@7ŒŒ”ÙÍÉB¤>ÿú r­F#ÏËá’âÙ»¹”]•ÃóúÞS_9ÛÆ!oóoŽßŽ-¥é!K¯IÀò¼iÇóHØ…7R)FfHc,æ$•žµ@”l:*"@[NãèB¾Bžúld•ÆñµŽ[mâǵo12 èPæÎß&õˆ°'ÑÅ›z×ô:<ÿýŸçQЪ*‰‚ð5O< tù!‡ô¿A>œS“ äûù´¯uûY$Ùù]ØO¥\(Î\°zh¸RÞ¦-y]Uï!ã€ãöâ·SDÕãi&ˆLÛåâKB&¡3¬óæNcÏåÄ›ûÞÜiìéGœ8nà¸mO”³Ò½µÍ›q,x‡ÙÑq›í·íÈßB–Û9Xn[è݃RÝå( Ÿ’M?KµÐȳŽë­O%ilãî¯NÞýÎÉÛBG'ï_ÙWâèÃ<üw'Ü."2;æÅ\œ¼8y[hzáägßÝ$TgÕ³JŒmÖì,4 ›~SüD·£é7Û™~[è=húÍjü¬ªËL¿å¤n¤Î íÄ2 [£Æ' ¼*ºw ¼©¯GxeÝSà5ÈèüÜïlR^~V°¡ãLãgXÕÙY§qvML…ìHú¸!/“Üx™¨=¼ŸÄC,vEyÜm[#ÕGµm"v£MÁÒ Þù2›9kf(§žv¼ÔÍ¡ÃYçQ[ñ5!„<‡˜èqG…ìÚ^¦q–ªä9œwÔ5­¨W¢åÈ~ø9SXõK“4òš¿œoy×aäÓ••pN#ÏjœÄáfÄÏ™ít³@;4Uµ{N³ž9V™*4]Ól`àc¡îtáò¡L,e«øþN·TÄ:¦Ñ3*¾F—49Kä}»{ÇAS«$UMëo^¯Å·Ç©ëšÖ’”Ú%åýn¾´Ò@‰—´×e8ù¥,ûÁJ-´ªøjGé×ÏÔÝòÞ=ëÓyÊâšv]”Íi½8µõ;(tMçºkWÍÔmÌsñ©nxößBæÛ¶›þ‘•Ë_Ϋ¹œ_S7µk¡ÚóóZ%åë7R\¡©*¦î]¦sÅù¨Õ³Ê½Ys÷;(pDô–¢Åƒ?}׉ýz5$‘?&"ÇõU‰(eäÝ€ÿØøv²¥üªš¡ÆWÕîóŸT!êÌ'ãÅ0æâa>ªv±«‹×¢/Ó{GeCãËn Œý󶈕 Ee¹,ªü¦ {ÚÓ6ºV|d͸ $¦kr¾ºe[k„„fãBUuãzU}‡ Òw74$®©£¼o¨AÛô´k¥øR­§nŸ:øž6¯Úøž6Œ} ÷QùUÐÝZ%ÕÒû_3>êÍLŒÓ°äp†{¸*èþ“Än ƒ¼Pc£ø9ψµƒT(êöïnˆµ«©Šh]¬öÕoùØòÐêÊTQÄ[± ®"Å~&Bš=zýŸqßT”{¾Íóêò+Ñ&ÿåû­›.ëa\ðݿŽil‹»¸÷Âñ_ÓÆÞ}[ûnªø„Xý¦¦9wï~âùÔy‹ Ô¶®|»šÕø93Ýäò_}~ÕU™§äȘڑ¿m¹b—.kÙbèýÄQtìùÔðÊ­Nä"Ë@婯Wœ£(¥õLE YZ¯ÁHú¡(ï’¼KÄ‘gÃȳÊo¼jA<}\d½UFj,(§É´+œ½{rA´“™ f¥®h'!+3¾ØlêšN¾Ølš\5ÀQ¯Q/M.|1t ®ùh%N´ªzÆ€öžº–”#X¬ -TL 2:á=ˆÓ˜ì5|™çÛ¢ê ηá·~C,!—İ|Ü]3>ÒK%;©•1ù@ôRG÷ ¡VB ¼¬7¼ŒŠUQ|Ëb¢IN‰a"Ò/8ìH‰—ÐÎò–$.[xÅ® Añ»sh§—ÙäÝ53oçÔQ†¸;·#!—xù©PŸkË™ú•~åâ@¶»¨^””KaU%f6s±8õ{¨³{•µ±såCÕæEmí\-4>!ÍJb/]HšÏ^wüê. 1=Úµ)^[³ahrრ#|0ÙÎ3MÒ€æ\¶SÛ7“ûBÓ€&Ûù`ä•f‡W>˜øšLîù`dzæL·~•3¼n4W5ø—Ívƒz†Ͳ2µ²!©«¿#ã3i‡QF¢ÔÍ|GÒßÅ÷²5D»k&!iÞ¹•Ä©0îãðW¾}7P3HÍÿ¦ˆ›´ £lH[Ýãk>õÚøÇ¬Š=©”Å4ÅÈìl¥Ú Ù>º|ë~|±>,mWs1õÑŒën£Ãu¹’¬-!Â"·€W©–ßà.§Lî»Ú¡Õÿ¦Õ€ÕÞoDS#ÿ®dYVþR͘eïûF¼÷ Ì3Cã~}{”-Ð'Î2ƒclYRf*%B5ò[²ÄŽ Òd´Õ{Wb€¿tƒ|ì5²Q¾AÈ7Ö|Õ1kWZ%…]º!DÕÇIv«|F&OÈz.-ɼoå2ôªÞÒnê#¶©¼n’Bv8bèrÉVÔ£îkqäîêºÃ·ª÷DušW7 N-›E@4ÖCÕ'òßTò§ÖÍÂ};';ëËzÅз“'ECa§â£fÒ‰>ï³h0PÎŽîP9ÛQ®#ä}¦Ï©F8ÏÃ"Žè ¾‘(Xñ¬NŠ8ƒTÃVA[wä×þüÕÊ~:=ß2ÚWÅè24ޏö«aŒ|µ¢Kï3ßW+úüTdÍ[¢|G*×ÑÇëlíjõHSÃÄE8Ñ~ü3ÈŒr6 çADØùôû~àšíÊÓ®]ò…©¢ºÊÛwâ>Ó%EÈ÷AnF„ë¾Êuä­äì)‘’?ðŽ|ß7D;n4íÈÄ‘ïû†hǦ·òÂ÷ N§¾oÒ+É÷}‹"ÏÆ"|¢Þ÷ŽŒ¢ûÅí,ÿB4Ý/žˆ²¦eøšÏÃÜŒ$=OFî‰Tõ¿þ¶V*C@µÛ ¸¾øî¬²{y†Aýó×Ú$"jgOxÆT„ÖùË¿Ëh ùc#½+I]ä,)z¶ ªAj©À¿þ H"×m(àÔ=›/1‹ˆ•ƒškäÈh?ëRBÅZã½÷g 9ñª¦d­;MG?y¾BK•(-—yH¡ë(ÂRbë®õ¶4MSÛl ƒÃÑÖ(ìò”¾ãk:±¥Ìbt]:©*R™"Âý^©,Þ¥ˆQ•‰ÀmÇHÈGªs¢Þ»¥=\߸ÓGtN 7Zàð6?—Zàl€¢È¢°’ÔP®¿kßÌ £ƒ^"½%4â€Z–3Ú¿ÿxôº|™ùÞì9dï¢ *³8÷ÎÞ‘“ÞVÙ%ƒz[£øB\MúfÂúùk£&™ÌŠÊÜÅ ¾{ê$÷si¢I&›`Ö‘+gU±ËBGuDWjñRîóyA«"8hGäy¡¯Œöì\"¯kçt׋IÞ§½­½òÞuOô¹ðŠåb‡ ùœW¿•e»ftÕu$¢XC~ퟂ'‚9ïÛ?…‚.²ã„M|»’®÷ KÀH 4õ%®y¿è6kØø‘glôÓa9v¼wŒøqÕq•ìÔÝçµ8w‘•ã®{¬»?ÇÒÂÄ`ߪûp6Y_ì(~aäÂ:–Êžæ,íRÞ"¤Ëó••]liR4M2éKå)³Ú;Ä*FGHO*¯ è‰gk†o/úµN#‹8©ìƒëãð,lœ\«¦:XÊ åY Òdr«*Xmœ’Cª6.YËJ3©}ˆ±‡¤Æ;e¡û>g;Ôñ< $µ,nñóÕÜ/M…þŽ:MT[%Sµ/4xKwR(ß¼>ö&k&±ÁUŸ®=Ê–gé’wÕÖlã‚¡/§ÄQX¡Ä*IÊîМ{ç)´ý«¢Ã¢IZíÕÜÀÇ;QV…y©kÕˆ{­ð 0DQÝr¤rœºåhjÛNJ~%eyÖW”ŒÑè—PZ2oòˆFúÙå6¯ì,ø÷›$upÍè˜zÊú ¨§‘G4:¢ž:¯ØÈì(é§|ö:åóÜÁRæoa²d ·(; i6c‘qà~k꣦´!Fß' "Éû,£nÛ'9ç ·Dr»i1M$V"0|ªÆÍ6eä5¹–Z}§»~ä_|Í—ghl\e§jÓyþæB¾Ê%ãX¥¬´ƒüØ®™nÒí°r†Ð*ÏmRÎ #׿Sk)ñë‰Xšæ?q¦ºPQId¾ä[>${«ˆ±½ëhÓ³ ÈíÈß¼&K±3©ÝvÅ.ÒT6²Ð3BV"Ω0¢÷“öfi_ßÉíþšÕÝ›\6«;=br{œk_Jí D‘Ûó‚bƧZ Éí…[ Msµò{ÈÛyç¶TBno„TGd…Ì÷|Ù×zaÉí}`Ì¢­QÆ%øº§éˆNJSR÷£u#M“Õ 0 æÈ6‡ ôŒˆ£(Ø.½3ë"! 0SsÞ8‡ˆ8DüG—ttú*åÓ!Ofˆ¤ÓÎpÍ+Wß–x$Ä#[G1È [† #Om¸›É÷'jÇÐQ˜¦=Hqmw„|8Ð’%ûŒŸ3ñuàû<·e€Fvƒ<µe 4øõ[Þ,ܽ÷ç[¬ßŸ(+‰}]mr^¶‡üOUA®K]^úfn!¹ð&'YZRŒveÒÁ#aG3Õu¨t²–TðnÝòáÿºí“YÓmî3±{ $ø”™n>ý!‰ƒ<ÿX$AÖ6^¿Ð.Ö,mäÃßbK³ÅÖ£˜Ë5,vwLP“„Vì}šänäÉï5FUÆæ¤†@ÄsIû¯éУÔö]]4/ð}~~åù%Ó)•òü3BB¿¿’¸Ó[—¸fÞ¥Eðë;þé%¬ è ù⻤™Œ±>JËŒqÙËš#ù›ïÓ$—ÓlI›%xI~ºVÜ2cÍÒ…• Ñ;L’TNXçûÊælÏ‚‡º;ž™qTûÄmâkíÀÈIMTZ™‰ÊDÀ¾ÐØã&Tš‘ï|ÜgñQ³ÿæç蓸‚-=4—ß%M÷½Úš»€ö[ÉÊ1€>|¨–Ð!k²ßëãéuf›ÄƒÞÄ›/ /ÏüÍ<]öªœKÌÇÛ÷‰3Ò‘l^Ä…~pë­^T¦ªeÓ܃eµ™µý^¦å\a(qeq3¤L±Fæy?àOë»2·J8,ùvs70 }Þ~½/å}1¦4X¬T}kÿcÊþ¦ÊÒÔ;cã²b¨|[»bgˆÏPë–6K_ýX'CåÛÚwÔsÒ÷|'^†¾N$=ÅorÏN’HUpHÍ“{Œ•óEü®Ë¥|K¦ms¥Mò¸aåü$ ªýéÿ¨øÝXù–‰¦%œOÀ”ÞK(¨KQ+Nm¾àˆÖ¯E­d¬½Ì»M§’Çý¢Ø ·sˆÎ+‘dáùDÏ®ã#S¨Þ>NP¯PvÂÔ+å¦2óz´ òë?çQ¥•)œ/ï«ØPÌÖ~AÈ“rTâÙ“Ç…¸>¯?Î51wIņvò —Tl©@€ßȴ׊µ pJœ±YêæÂÄÅqJD ñœ½ñ¼ÒàÅãŸû‰Pž8ê yÞ®$v< ò¼_çL\Æù¸zG"Ü„Qz>/‹ 3Éóu%"âéÕ’çû¢¼§Þ;Üççš‚ïÖ%ŸÚ~ TLÝ·éQÛ€]ëyžù Ëlh$ÏèÚ2Û­uÏè¼¼'OŽîœñ¼h] ñ•܈'ãA^·”1j‡Lòº¹ûdä¶²ÙŠ®ÂÈÇ™ýú>亙TeaV°4Ýózj1ò…óìÆEò›$ë7¸¦Oƒ²-ÂR¦kž\æÉ‘pŒÚ©7žŽ„û#ôbÔ‡íœ ½õá!!‡ªZÁ´"=Qu‡¼p‘Þ&©â¢Lÿí3ä¯}ªšÎJ«`@·ó- F>ÎK°0“}÷"´©¢2)ìGeÈøÑ+Ø·Hûæüë§áÃìŲA›¬o2„ä ƒKÁÁ‡x$ϱ‹‚c×N„|ØfÁœï$•²ÿ®)$žÞî;²;BImå•}ǹǿî LZ6MšsÈù}n¿+mi様é§ÉOØÌZèê´˜ueRŽEa…; òy  ÀªF*(XÚ†A¾|2†9ž±¬ùŽYÂ1òý+µ°ŠPI-ôùÁ»¶Ö£ÙªfKŠ_3:Ùµ—¤eIÎÓ2ÍŸ›WŸVÚª%]S²7õ´¯xäoÞaÆä'”ÚóÊÖ>xI÷ážL ÷$øNm‰¤¿F¼A„`•”.èñ­Ú&’_‘ŸXúr\ùXºÏ*Ý%¿  ïCBjìcu÷ŠÏ…’fWSjëxŸ[ËI <¨%°r‘ØéD%¿ê}Í—ZªG´*÷ì3a…gÿíWç¡W:ÙžÊýH¹§¦Õ¶o¿­ÇãW‘¡—Š µóðc=ž'Ê=]7}ƒx*÷ˆÓ|Õ—ø<Þ‡Ê=œ±½d†~Nþ.õköå…Zh‘ö-¼d@ZØB׸Î|äY’Á7ð ¥I{¬TÖ£—ö I°³å5ù’ð#ŸÞ2™kNêù÷˜}ù —47Q÷ìÏÀÁ{RÚëÍù9î¥O–æ»àûŒ…ÒyiÓ®Ø<—ø×‰ŸKÖ žkú­Ò¡Ÿƒgý6 ]÷‘‰ãŽüÍ!Ö¡V½Ž¼ëß<§ê§±J[`í&É%pSÿ*â„â9+¾U«ˆs ž“lôå5€—Ð.fɾÁ ø½÷…U#«†&ãœÐÏ¹È Ç/U/TGÊ-®'ÔB/4V¾ÁcÅž­R¥Ã 1¹§¶dÙ¿-£ðu ÇÂÙŒ'õ—À9–¥ÁõxxÐR¿‚5iù¼oi\õ‰ µReÊ‹¶YÄÉ€Y¨”Èž’©l†$aÁcé…JYµ–Vë)/Ö©I·$¸×ÏiNÍE“%ñ0§æJŽ>%Éö:µÒ»¡zÈÚœšÛ€] í_µSf¦<8-â$¾gJ Ÿ7*fEfbî‰.²Ü ¾käó \]Á¡máɪÊÒ©Ïoÿê¾3ªQ(¯¿4ÙÙŠ:îTg­¬ µñ¥–™²ÎݧëBù«Ê­¬¿ûζ¾¶.¤ù>É$Óîfé…k1•ËQ~È…¨;ß¼s¦#ºˆº7#u¹*ç»v êÞHQ÷!±¨»ÕAL™S89#ß5Ý_a X>$E’»ÕÄó]CÅ&í (VŒŒ~E”¨û4ç ß癨ûœÐàÙã“åäå(=: îQ²À~rôÂ]™=¤Ú¥ 3üzàý…ó‰‰ßG=®çt¹Ïûëp.Ñ#Ïç’wŸÏ˹D§àš¯_/7åá'[–„|Û ›ÛnÆJö® –dOH Ô}*ƒ¢ d ò|.uÁ}’CÓ·rjèÛ5ÈØÉ!/5^Õ°~F¯ šˆªÀ¯¿QÆD‹$*Ú=ç²cÚ~m}O-¿ñ¢†Ó£çföG·l˜/®g²‹pKƒk>Q[ísú+®X>ÏÐ5}P&WæLŠˆÅK£e B¾¿¸)ñämH]í\…?ë",¯íõ§M  OÁÔè:k{Æ›–µCHè£Ó4e-OÆû²ÞGwŸµÀ8¤|oòfèÁûÖ µè¤¡>WpÍfÜë_ómE•2h«i¥â²Ln&»õÓ>{ Ͼ¯¬N£<]–YÒ¿|ö¹éZœ£‰<ãûÖ½Xf„|Z*¥¥Ø×#_V³&S5 óD´TÞ!ù¶$Ô4³ýë²Ð>Û&ŽïócÇS ÆÈI_ôùP¶mñ5ñzÿšþ^u¶VÈ|áFº®v›úS^[•ç[…O,÷)#»qj»"k»aBÈ—#'¦X!·¹žr„ôVµÞ ÅWœH´nGH×Ñ"MUvvl¦*Ûf â9ͺTØXv•[“É ‰'ãgÏ–•Îx”bI9.ã½£$ÈÉvCý’F6'ƒl1^0ôîg}©ZÄÓ³ï8ÔÁÓ;ñd¥!aËäûwr(´[ ž\Àyé›'¼í\e•ø9 ÿÚ0FÕÂi@ß6[ãFUBS^}çúñ—©Þ¤N×¼Í 60âå€T¯kn”äNË·<Ë«꣕*$d…m½™“IlßIpUèet5¹Þ‹'u;ûOzeyÂrQ†žTnõqí&ár%>sU÷jMFª˜l[ UC°|fճťJµ5"$êe¤ªˆ£¤«ÅÉÂ[ÏÉ-¸æ>«kò !žjg¾mýFáÙ?Èòû€/ Šwøƒ´!(ëF) »"ä‰éVíÇ×|iEU;œÍ=!^ùìÀÁ¯ÙáäÜá~XúJKε¯;S…xU¡Óþ“$-Ùâ‰ø’µÛ¸ãl|m—ë< H|ÇÝ®bÉ×Jvtà%èXÛ_?rr³¡SSÒ1‡¼Û“›FöÉ«‰ÿ«jhÄé3¸æëÙ[dï3½îØÅÄwH³Lu]ê’LõM,8ðë¯ó¦ui{½ÃLŽ_çî…‰:‚ÀÈ¿OË r“ ñ;ðE K‡Œççÿ”)Fz¥Ã tÜRÖL%*Oq<,×¼(BHE×z! –_¡“O›D¦ð=ƒ4•Ž˜åh“¿- ’+Ž^$Æår¤†¹J5LHöÄäR Ó£pÅ.Þµ`©[/$WA*SpŒÔIU:ÌLª]K–:× ƒ|j\:²BH\”«’Y¹Ø>¤”FÆ>qQ¿M2‹·Yª.…gZúÉ«M|Jžë»¶ s>ÈsNHŒe•T©Xñ,òGË̪QÆ8Û¿9F¢f<ê*èP¬!½Ž]Kå¡â >#h¨0Èס ("<Å·ç•›™Gx2HÏ%¬2”8ùަ*…vÍøö«æ“Š¿ÇÈ@…ǪÙOËVÚøöËç×dÝ&{XÊAÿÈ _ÍÎ8vRñ!Ué>SŒ|ÿz)}úÚi¤O¦Fˆñ6IÄAßgdã5U´5µP.Î*I É‚kß.¾½/Z+¥;ÜÜ ¤÷TÅúÛlÄ·9% F>¾÷F~ïýîÞÑ;8ÖèÝPŵߜfI“[$&ê‘× »ìšÒÍÏO ‹WVšb(–9qH›™{ïŸs¯¿D|!Ðߢ‹ý¨amïž(:UnÄúÙwnäÉEÄ"mæCȳõsß<¾æáú)ßQ’¸™LÎ[uD ßfü»Ëh†ŒŽ§Þ´ñÄ÷%ÊÂ72lèÞ}òa^Týߌ¼XŽ¥kˌϓȟÏn ¹ßušêR+fö{³§öˆû¾|žTÅöa*`M¾?Î"U1“)ÿaW¶4«Ê,_éûºÛË}ÿïˆ}gÁ q ÖÓf([]k¸Ë°ªŠÊLæÚ¢ 2>©nÉÃ/­ºåW†fw¥ºå4²_¸*jª™*·,[×hó£­`­õò¥”¬h2ñQº%F¬SÇs²äÈôFó«Þ\—4;I¶²¿:•o·áfDUïku0Böé4Jg.Q˜¯H<nÄZ‡øD™wÖ1Œ½É<Ψ\{8ò?W¨‡šÊ‹úäæ ]ZÊ– Ûû ýKÒ²1­‘irâ4¹¢Ñ Õë"ëT$Ö‹iîÐNrmhãƒÀ¶±Û2‘æXCþú¸Œˆdò½æ´lZV¢‰¤÷Ê©l$ÆyYriÕ;ä+¨ß9žíF^óíHU7íâÕ︃×üxdUÙY²¶“p”²‹Ì ‹Ìkò™—y5õŽ?ºXë—‹a {Za¡w)©<æžéý@¶PÒÔnì?_ìZèŒèï4{tBÝ]™5‹~uº˜#Ùdeê"SY¹SÍn=S%¥d?ÑsöC];yý~-£:U¡3Eñøø.Š &y©ýÄK8cŒ#KÃÊ¢s­¥1m†bµÅ"El» vim®Ù’Ø%ò€ ƒÖ™ÒÔØV¶”÷’dêvEU Ô3´ïØ´È×§†\ÇܯÇgi#u!b‡N¬[ãF z»æÊ³@~I=)«•ð‚CdP ¬Ía?ªîc׎û+É>TUh\bܰq„ÈÄi>ò£äªö[³ìe‘©ßçã|<’â^Ý ywš?ÿjZ¯Þè¥0\1{Aò Ô˵–™p^ eåÆ3=eüuS™*lµ‰I]¹Œ? ²ŸÿTˈÉé4 ý1vtÈD.æ‰r‘ö•ó‘Iøìvý>0î†j(Œ’½fƒKRv=¼æ+Dv†Övˆ…¶¬fˆ|y§9€Ùd%¦Ùzxä'l©ÖY »m¼€£¤·y 4.ù†ÖzÌáÈ›,1íêÊ,Ë"°–yJÃO/I«ºÊ*p¡T©å®0"ztÇf½“£ä„úéôÀ>Œ‡ìÄ>„ÒÐ"Zw̶,`ª9ײ„òèA°+‰eÿÏt$4z¤¤¥±x6ׯ“yþŸ¤§þ²ƒ¹d/~Šf7©’ä‹"ϼF­Ô(¶È‡&UÉhôibÝô‚¬D¼QÉ«ÃyÑ "'êÎëŒäE/È:¡‰aoÊnÉ­¹¥ëUÊâ§žyV0.yÓ³R¯íyÓ³ÂXWÄñiûhL¥Ÿ¶®aåá5Ó›B—Ø]€'Ïêy› Eâä^=6;vòy§ž'’i¯y§ž×²à½'÷êyTªç1øë/V#=Jª=8Ï^‘+1ÆÉY=ÏäºO‹»Ò²AÞ©çµ^XÕ ³‹Ž´Š%wÍôž½-5zýʧgu#ç«¢-óïýõ Ó4íá\zÝ_“J¹?ž!¨ì˜ ¾¸ÏsÇLð}þ¢Ëæg] <õ¿ÿ U¢ÈŒ>L–哬SÕWäíÛç“A,7 ¿_1‡t¨\È3D4ºÝ#¹Ó“Ò)/]â•üþEZÇÍä$º ¿[2|ßÜ.“Äü~±ÍQÿëájsѽêÄØ³ÍyÕ½Šü³'_%[Ýf/ùUßzJR÷iIÛ[ͯÒÁÀ2®‡ã§fñ  ¬*œØ5gûÃûLÃÂv­Í) ã´áÞçë»#VÜç‘ïͼ"€|_¦3ÊòØ|hfaÅ_µ¬G9;ų--'Á§Œ“*ÅPá…XÇq2òOTëöf™²aî ™2¾*ÀU€w;WòÔ¹+fS€ÈÎë¹?ª¼«KxÎëåÛˆ9üõä²"¦­ Ü¯ßYAI4B¼T–Ü[AÚ ä¥Ô¡­ €¼³‚"aˆ¼·‚Z(¼Ï{+(Ìà5o­ èâöÍäÞ JÚ4ˆÅ"oz=)mfæF)»¢_¤ýbK¡AáÿþX¤Z¥Ü˜øß¶îµ51‘åí*€ŒÃ¾L]‘ß&Ù±K ;8;Ãæ<–­ÀUæý¿w†Ç‘–@¾¬km¡‹ÕÒŽ¸ã+gô(F€Tï迵@–©CuŒ"A¦ùHµ.ÑqhY· ¤êzúó) ¨µN|G"“e3ƒ£äܾ{Ü‹OoµõUoqÅÝôT)KsÎ;“¥?*äO Ò´îªÓ[5E’Êb`[$P9/õ0õ-ÂÇŠÜ&—šH®¿b%ÎE©`“ /Òð¾”m“&ø3±*ä;;]3…g4æ„}<Ž£ 𚯠¾g’rù&x_ˆ|ûZCeD™zñ:›úðË¢F~lkœO-Ç— ‘Î}ð™y×½ªR--R’Oõ¾Y{%;ò?AÑNsޤòªXåɰ¹Ùt&çY#ÁR,b}»ô;ȰáL3#å066GÓdì«úf›‘Hù½×´È$hM³lü¦áê¼Ïô*þ]€!j–>(¹CTƒ¼4U[¶µœ\|–¦O"°#yS°Ä«gä}SKïý‰9/îÕgðÀ’Tœµkžl9rMlYhIúŸ2ð´6Õ’§0.~G -Iu†¬GI«ÍfDÄá¯kvÌ?Ê¿ÓH‹¯ORº _w-5­coeÞ’ÔÒçÌ[Š¡mÙîš„2oIjÙ1Æ(L쇤¼xŸY¨/`[ñV®{ë÷™kuÜÎ(¤Œ®u2K”q¤ÒëFÎBÍ‚ »à©s±júhŒ‚L.P"¸Ð5[[§šJçF.e%î³®×Ï¥•¸ËlÆÀb( õ.¬Ä½†Nê |kèðŽºc´@_àÒJxÍô.ÛéÌ·:Þà(óúWœø¬ëÛ1Qéô~çm©p1`@˜þGe3¥%iŽœ›Aö jQþÑ5wMûÛ¶Vèòþõ¡—ÇÜ|¢Ïè¬L¶Òï\Í‹ÓèËä¯snª–ºF©‹¯æ“G¦Àô[×á›cé¶›‹ý_~·ÌJãÀd®ß!köb·P¯$˜½^•¹Žxä·BŠÍõ¹¤ãæš„^Ÿ'†ØýL>ÉÓ¶%qeeW.”ºÒûël«œÔ.3#kvw€öÊÎ1ƒãŸ¶+ŠÅj'e¯ è¥çV°KŒR·òbl‡ ïPæÊºnªkâv.o!èE4õKbH †1 ‘¯Ë)U]skÝûç/ Rî{,áÊ0š•Ájýdïp ùO!–Š@R^‰µ #€ìì5éVá©Hw¸®¹cF3ïC7¸oâç”Õ5=["­s*ºYhâçV0—KQdäã¥÷¯g0ÉÕÛíGZ¹NÈ÷÷Z7šµŽÂ_ÿxkôÊÔ_[Ö£u¢ÝG)»\Q‡Åª¯ X<æÅ+QÚQ ¿@èïí ºôð™4‹ç_mÜSê"èLÚ¥èÅòp@h|±Úb½Úºš¶&ÖaTKË·FܽßèÔœ®š~¯Ì2T+ó骯ëB™^¸©} Œ™0–ÇH7â¼ã[i"IRaÁK½ìœUÏD0©ªÒmKïäëܼ3ME#^I5û1=WVr‡óïS>.ðšIxH¡T!×Wòþ:&¨Œ† i¦µƒy’œÎ:}X.öoJç ßi¸6ò /§D~‚Ò„i'.v$’y€Ì|Át"áoɾ¸‚#ÿã0k»6/+mhƒ&¡—=ýbï–=ýnê‡Ní¼­]±ìI‡ÈèÛy[ YrÒb€¼vGDr #™|·Ò!0d)d!­X+]%ñ‰”"ã¯ýû|ݳZ&_ïÛÎ]*Âu>rWVßwîŽGM6gM’½ß÷N†Tõé¸k~¾Êÿ.A‰ì=&ÈcðDÙ_8®32 Ì„N,8€#‘½³ï⮟K¼ö½³¹õz.¹°- ·^Ï%—¢zrë7Ë Î%On½tGÄ[Enƒº8à…V³ÏïcšÆÀˆAÆwÛA¹ã=$ØwH}¢»·©:à‰ãÂä}ÇvðDÁ÷EO?îÜœÿÄ=ýÊ2éÈ»"†H¹1¼&,b¨5T[i`Gù7HPÄÐÇS²ˆ!BAî¶ÙOtH}3 Ä·¼äëºÜQOÜÉ>äMƒ‹„Aäµ,ƒl÷ó³gß67XÛÜO¦?'éöcܹIdŸäd£wjñå.¡ûܹ²÷´,{Ī“ˆ/|«ŠçÞ^ÆÌõ½¨²™ÔˆH‘ûnnGÿfOkå‡4ʦêÿÔ^éüH®I;“ÿ,ò\nQJ_ªi Ýs"ík2²:…λTâ·Í¨÷v˜b­â ¤äÞŠ/drùëc^ÔFÞ?€©úG›\ê_¯Ûm·¶ÆÝýúrV©EÆ7ëdk2‹ü}v³îÌ&Ñs¼fß»EF7&“þ0Ç"oX{j“s£tïb®bÿ£]òzUV.ææûÈäI³B n¹k>YfÈŒc€¼ñ’& Ö B _OÚà=¶|Ñ1øõ(‰Éâ®V9¡ˆB¤-€EfAïý·jÈ$®¾ä•A\!ãJñHðš^GsC”™Û!vmÂýœÏ€ÿ–&0É)¿U×óŽ÷™ú÷Þ˜T¶ªLE¾rˆ|…^Y&ªU¦¶9¥ ß)#;ÛtÕRÄD,ÄÒùoÉ ÌÄ¿ë@¥)ÀéšÙ•-•6=Œ8ò?®‡®tjx-âJM^T¯Ê߇ h"ýê;Š*×ÛAq‰Q^w„ÆßrgÒö®”t‚Ó½:a]YB1zÿx9š¼â ‡Ðô"Ê £Š2ÜÛÿýy°‘iç‘Ñu¼,Rs¾Ø;õŒÑ¯¨M,ŽT|w oMXÜQ‰@>Ú-†ß]À•ò¨rëÃZòcu ÓÝèÿ®*ì×h‹ª¾•¢äÔ¤e¨U4”—¶íÌ"½õraB1¥VK+TÎ @&!“D7¬”Ç ×ˆÎRò­ÿkäÇR°E¾¾•‚Ò+[äûF)8ÇÛŸýslsÜ/™}k K‡¼@SؼwÈ“8Ær°j <²ÓÐy¥žÉ][Û †›ÓU£o©â~RÅ_yÙ•MNöÝí €¶h ê´ŸµT"éÆé@„¦—²Æ«’5>]Õ9 #G-–áýÌšr?ÝëûBÖÓPÖØA¢˜íë’í=U7‰|©>M~o”kõõ®qÙŒE!–~8û/„Êñ …Ê9œVWú¿âã*‘0|‚F7©Z,«C@Ó‡¿Y©-SXäµhN+»°»æëV¦‘r0¶G ß÷RMT|þ‹ÛÈï…c¨øC¬KEÆß‚A­ r÷ùè9/ƒ€¼ Œ¨kªÈ쉣ƒFÛòþ‰~žy?Ü-ÐÑïÃ5e ¹ØûŒ¢¦à`G ã§mL²ŽÜ}&÷)8î–3Obûv]ï•뺻Ï×¹“´Ö"Š´šï¶ËÛ"#û6eQT7OË(Nv’ÃkÆwNî‹ßð¢×½dWÅ÷ëï{)‡cñRùyrÀµ“r°Èk)@9v”Eƶܧ7Qµ‹v‰„¶îmf§¶Kµ6ÈÉ¥l×Y£W‹Œ|øX¡¨²®¶2_=2v UUÛ_GtÍ™ÕþµÈŧH¤öpèP…0ñáKäâ?ÿw˜"s£ûmé4íµQ¤´ÈP±6Ç_#ÝöŽn9@¾/{ciŽä_€ü8’¥ ˆ{º‰L¹ îÙ=/íâ×WñëmÑ5’ d‘ñé>5m”Ž('.ÆÝ1Äʼnb`@êÓùÿ3¤FÃÈ6÷Žâß A·/‹2­eÍ\/]¾÷j#ĺyYdüýëóœ£j)¸Ï“Îä¶­QÅš™Ž}#·-GC^o-DÆ!OÅ$¥$gM¥öê3»g§SKk΂gÚ‚Ï3¤ï{F9D¾îKc’«©EÛÄÚÓ}¾áÁJ«¹/b΋woƒ¬øBêΔHŽªšFb噜]ÜãJm‡Ø¥+1 “7iÜ(’PËÐÐнq»àï}Ç,‹O©ãŽòëôׄZfDõ7åˆóF:+Xdv*ûH™¥g|”{KêŽÕ8fÖµ¥è7;©Kž3€Œic|.¢ &ßÚÊ•hâ/ï-GÑo¦¢Ûx¯™:dij$úš¸ÚŠ _>Qµö}!²d©[Oò úÚ´’t.Òé©ÀÞ§ê‘”DC}´¢½þðZÊÕÁþzòó½ŠÔZEž-4£‹è“[¤˜’dì ¦·GÆAe5okU¤‰þÓù„–•ùÏñé>ÓÛ˜š»U$àC~‰Œ(–£‹“‡ƒqÍròÎÕT2Q2~v‰õŸ€)ûڔמÊû8_Š©'­aå dP’=”dMijˆÛLAÝ´dätÁ«Òè‚·­ˆ+×­ëF€Œ½Ú·•ÉüJG: @º¦á›É¯ÖÝ‚2 dñL]nkWTµdß8@z oUÔ3¤$x?ØTä;ì1·¤R)k'¬È_ëlp#åf”™9ö‰\éuièh×¥(úv†#ÿ@Mr. íRÁ‹úî?EèQÍo+átZäû‡Ð(ÐÅnÜ@UxÙ›A¨s"È](7’©,޲ƒÐÄ7³V–ÐK8c:§ •Þh’âªVû¹adg#œQ¦gÙ¸r‰|’=Ÿeû”*9÷€b ¯m/Ðû'ýùK±ÅÕã=)óªØÂÉùš¡*wi©% žHïC‡ô÷¶ûŽVG™+Mx¶áU÷,M@d|} EóáH=öo`?—ÒøYáÝo O¤3DÛ1xöôIêco[·}QÉ€ÔÇL}YÆSÉ®¤>¦ÖžO[dTN剉>‡@xY& ‘Îcídd#ÝØ1@¾¬¾ŽJ{µaê"AZ ‘ОF]SÙÓ4ípºÏ³ û $ ڟѦ)°:‚W°£ôz¾MФ´È~fXÉíë[:eÑ-„àïðzÕù.ùÀ5mo¯0}“·$¯6‹|¢b`j}ê$©GV윞EBïM2«‹F·Šš)ïŠ ÒÞ÷¡÷&‰š2¼7}톂g“§;UÚíZuªè˜tªÞ¸÷&‘^ó¹¤KZâßùö†Q/Ù8fË\"dä7¿LÄ4¯U&ÂËŸ=Fm2= »øv‰×%34}qíC›Qº`¤ß{Óti©x?–C½rKn\®&qæ}/FV`hèCKX¡Ížåc‡¡OÖI/'yO§*åe3aèÓùÞ˜1ñ[ùDÓO7çê¾ Ê ¦Ñ?`¦ÃÊÇCõ€ì£\©_KÉØ5}J[ <¨¹Yúév14>· *êê‡ïê,ÄëÛt*lnã3ïtö[›¥R·â;ŸŽû†¡ œ¬‹Ó”ퟑR÷¡fnÅùVÖ\„ìîw:†õ‘­343ÿÔÐ{z_»Œ œIF03º(%ÜÛH£«±˜Eª”‰ýqGÈ“±‘UеÛÊ¢ï±õQc1mCü;_çÞ‹ ˆ <µé+YÎ+9B¯(úvü”ÄL†öø˜ñ·ã§"ˆÄb_295™É:ñŒCÇÜùŸs":Ý;œ>83s䙜â°ÐøÂÌEY´¬`Ñb‘á•ñ ³Æ+y>\Ç$»½…«On£Äqõ™èçÖ>©e0Â]Ó&ä0Xë‚ë(¼Vˆxö½MÓ£Ç5ÛÕWEÈçÍI•4s¢×è”ÁãŒÞ7²žN™E^9d²Áõ{#¯Êz¦ÙäÞ¹(¾sÈ”á!/ „×*)tu<ÀS•—L{€gŠQb5aäûJO‚»BBß,6—¤FñJ•*ø˜‰?†Wš1¼ŽäãÂ!¼”XdNÖvèÄ Úídè ×ÉÉ•J{\oã²Á^ëU= zþˆ$„òáƒOŸò§ƒ¬zîÄÕtîƒ%l›Å8$ñÏØfÁïŒîl³œÚŠE>ð€®êŽ*µ‘ÖÙ šO¨rž´2 —òÐí²Cï+öìiÌumv†}Ȳm«lÇÕ§I¡/¼8f.V^µl‰§ Tx+~''C*rE„|øOÓ¼KžsÙÂHgÞxhͺV2ªòu¥É( Ÿù¸Õddnÿt„*èèN»8æúù æâ'ºKêÚU("KWl¯˜¬‰ŸßwÉ"9¡^g!~z^š¿fPPµJXóa$Eȧ§ZX†wýIÓ¾i„|Á¾¤â £6ÈĹØmb—.üýû¯Ùm´¼Ò i=[‹‘‘4]”ïæûñš®ÚJdÛœ™|w@Ú.oD6™ÁN{tÜ?ÿSƒ•Öâg]?ÒJßP#=lö­+mÀ¹ 3¾OAxæP3(‡0|Fש— yÙX5~¶ŠÄ—B(ã–/BòáùüV™ß ±ÑO“û×e»öƒß] 3í/¶#¤ßüªµ‚ØF¦)£s÷>>6Û!ï4u"dx‘÷S°¡¶ÈÇ7_§•|ÊVZ<–Øq°h§ËXyû,±¿-¯ÈÔõ[Úå|ÆîCcäsrãôT³¥lVcäó\ ¹æÞ˜X|ÿ¡©l8É퇦ÝwØB“Ë:ôŒü-òáž™¡ùQ;#ïm½'ùûq%ḂBÍ8¹õcþ1-Â\¹ ¤2ïÍ>TX̳Bù_XKÞev!¨Ï<ûG'òføk9cŸu@HOLvèœÓ¹d #Ÿ>²²H2Îc›­Ï<3.)ÚñçC×^N&C¸è1Ï~ÿ¨Y[Y3oœÈMÙXVmC2ò„zKC2 "ï˜Èñìñ·¸@–dÚÚߥÄö²ÜöØÜ®Íºº±&Ÿy¦4}c‚Œí²¦!„\Èu‰5âÔä}ê^¥ÞNý~À}ºÙÃôªo2¼ØAgoMb¼šìÉ]ùCœäŸE†gã³»ï·)ÉåøìàûmZdxŠT6[v?Gþ ldqâl(ìÞ\:êîËl€2¸)‹”k?òÁOp[¯<>æ•0Œ'jš.¼ó~g€8œ2IÒ] Y@©÷¶9üΗ7®ä•0ñ±¡ø˜ï«‡ïŒAžt_T ƒÖÐS1ÈK)=ÂgºÌb•x7+7–ü„‡^FÀzX©…[« b‘ÒZÓ$6½!/Æ|Õà\û㦯 ÓýÎ~ô(±e;ÉõÌ¥žôb‘¯Ë·x–2ÅœÂÓüên ó¤„PÚ&Ù‡mß2¼,è÷5>æã‚~ 5ƒù8ì6N÷A*4¯@z ‚çítÅP¾äøvçÓÕˆow2Y}î xÝM–,Ô ËZdx®÷!'Kæ!gZ­ˆj·Õ=Í÷ éE|bkw?ßÈÙØTÄÓ”•Þ]û¥ÕŽxF2þo1òô~ŠÛÉë€&ñ™ó^­vñyÝ6Øçƒ!U‹@Ýù|“­{JF†ç B–ÎûÉÑ™Ó ƒ¤ù<ÚžÚvn¿óu…Ü fo'õxð+¦„"dd³£x­Ž¹Š½“–|öØó ƒŽ¸„P>ˆ‚Пøf¹3˵p#N-Á‰Û¼¶èÞEH[QX!¾OÜÿ~%ÇÔ|ßùÞ|ø¼å°æ=Ÿ8ì_Ú)ÿÒÜÅ ax«ü5ÃLO^7=¨Èb·æÃç´ßð Â×ÝŒ””Þ‚+z³ ß2€W ìóa„pS¥5®š‚ iÇ‘¸·Ã'PYåxKÇëx9 dè“l+ƒIQHnkÜû ¼¤ósòõ‘5é²7ˆ¼Ç†7Ÿ Þ‹–ñ` ÜR—uR)—¥¸!ç|<&ǤìÕ_zÉB ÒµÞã;Qê½”óq7‡.‚¶ÚóqÕd­ïä"×Ò ƒïäb‘'ƒ_Zœ\,òÆÉRcçÃuÎ&lðxÝh‹íÎ…Ê÷%3ª•܇Öv‡ÄP9zQ)fT‹×N>_½ý¯FªPv‡˜¿Èc‡D÷»ˆˆ6Jòq!H#YµùZ/øw¾.æÄr†´Ëç ´K|:qÚõ /Ò.Ù‡Gi×3¼H»TQÂO»žáå ‘\«Ö¥ Ž¡ò]0”;4=ß±ëWïôµ¤™÷u+‰{F¯;_HVë%ð*ç¾óÉ~a§y¤õq&–=ìu>ñ@Nó¶šß6o3B>}†ŸuRY§j&ƒñq±Hg| Lžñb+²ŒOé_C¨œ)™‹îƒ!¤ž Ü:RÍlµš9;mìÜv$—rÌ6ö)ñÙð5éŒv+›2"^áL¾ó?'Ð…¤=§õ•Oéï&Ë6Cƒ¡¡g°eniÏ»‰´%øy!]<ªôQ”ˆ·“º÷3ròB"QQ9·&.ò‰°m™³9ÃЗƒV†\Û‘•T㸴#†¾Zß®¦(H‘–Y9 ‘nÿ*¨áö (ßû©ÅÏJPn”’ž9?vK·žo󞦚8hiøYb{à+Ÿç C¥x‰†¹]€U%âÖ%¥ ¾YR¼ µ\´Y‹l¨J ¿¡ûLD,J³ýpÔ‡„Ê›å\‡¶O1”)~ÿÂ'@­>|“R^çbiÛ©h }9hmFƒËu=«ªýð[ß-MɾÙúš7âmÙðÓ # …¾x“Jß6.’àÃ}=¨æø6™ºuÊÅ*ÀÐćê;°×kщ]›âðøñ¡zh(#lZY—R¼^êi‰­òrIMãÔùˆÝ?G ªû%âßÖ|š¼o*¸ ôÊ®Ýyã h|ë[×Pº÷<þμq½Hûß{ãyí[íùºtûu%ÇgrïöëÊnÏäÞí÷ˆ¼¼"7 d—W´î->æë’kÛA ùºqÅ wö×Ϥâøá.>yýÜDÅR<^RNöMÂásºWpCÂiÅuíyA‘¬ F>Ï•”]\Qx›I»] müàÞI»Éò5Üù[Šš$òyëší•t^w"‘¥Èt Lôz})J”¦!âH‘lpE.ŠÛu´iÈ–²­ÄSYGµÈÈ‹65Ìè-ú‘Æù¥ÊM}ªk/òžÔåR»U]“%=Ï{îñݵ“ÚÓ^ñeƒXÉ”ƒZWðŠïÄ5+ø‚' b9EËK§eW bù3ñ1¯Ä|ÁÇÎkºI¡‹Œ¯º™·Ug§¼*GÂ)B†Î• #‡üpÌxÂÁ°çâ5*W™ôJŠ¥m§tfÍÊv^à+ã1””¢Ynd~$!Vºº»†‘ÇPÒl+|ÁåTÓÈVø¾±oµÓ«µ>‡éIÿa!}IT9Чëcåþ!b"äÃûvX™U5ÐGXV!¤ÿ•1%=Ð×± ÿN’ײµŠB(Ò¤n.Ú5GHO_ÉX"+IÔºÎ8ß5õtíE¶Àª´l:Ž`k#+=Ð7m[ •´·×àPÍÜÂPÐå1ÛÔé”Ù;¯­q÷_]Ž×æŠøŒ54uÛ·¦ÿû×31ûÌdYâ‚ßæN=¤ÂlÊÝJÚ¹[ÊÇÎkUF*+æ&çSO_X«ªkðÉ™ê~@È—Wê5ZÙr"ú“ÕÁÈ÷©'ÚŸÆe¨“F”QI-z¢ŒAt"¤DUê‰2äãÊçaqÉLôƒ§Áú÷R²ºdyH/ôÇO³—Os˜-o8ð­ó” ´¹Ó%’•²µ, hð­óðsoås¯‰»öi 뀩ÖËNdÝäSá³{BeÒKU¿Æí8÷¤§éYçé)7êJ-]6Â>d]2òæ#kã\A«¾,y[˜g÷÷Ï/ò­&¼Ú—á³'(h¨¢xÝ–3%i<”¦™æCÊKù¼Nï14ðäÏë\·w{-°9†¢X¤4—¿‰eÏ»?&Sž“wJõˆÕö°²-ïò¼áêÊsš·*®«ûôâKW-Ëᨯ jž 2à„§ŽŠ^¬¢&[tŒÎ“4EÀQQ–úd— ýÓ±ÑãÚq –JØ<ª£m]hnµ¸¢e¤Ã$ϽMiév*¥®Ëu_ƶQß?M©ì R' ^{}@†6­3Ø´Zäy“Cº¸p9Šn] j‚GѵP1¯ÅžÉy_Ls*^Éèe¢äØÜ*ôLá@´Ês˜Ä:Ðý°ÒžIã„|؉F•"µqXö†¹]Ô}N4“˜zEÈ—K¤ [¾Yˆ"8@,‚ï‚­‰›¯·X¤ÅM¿S§ˆ¿êËå;_©&—V!c2þšQ•Ù²ˆÕ129s®£Ê| ñÏA.jºÇ?.I²¹UJ—$8fð-ë[ÒÙ2Ïc IE|£EDj¾y=Õç&Ûâk^É€HÐG÷;nÛú•VA)¤ñ¾ß×·ÿøÖÁ3òý¾P“¸5|"Hç<žÑ ŸÊ ‰ï˸{ß2ïëéH|‡†nk™GøìïkæÑ€¯=rrv…µy¨§nJ øu˜’”BÚ€g¨Ä+úFAüUä*­ljÃÓlp³ø>ßÍ<#3 *ž‘HT·>_'ÑQS+éD§Ÿýõ-†*“4:déº ä‰¡ZùÊ=%ÝÔã³G~°‘CšRÞ øŠbÄÁPÂwjÞ—, Jišê¨&ÍÏÇÌ«Ž±vÞðÿ¹¬ì‚–BàÛ·Uv½þ}_Ùu5¡ø}[Ùå® ¿¯§Wð'6ŽÐ+ç+cdR‚j‚:SìÕ1÷>kÅ&R{WtY_ÔH ½O Dæ†òìûÜNð™‰cW•9ðä'.f®CÇîåÔnËY$ßjG+‰c¯*ó¥œ/^zÉÝ™e!TP|Zà‰eaCEê`]wxFžvgÜÙt*178&¶®Ó$=¹Có‰ä[aCpìçÒ$@Ží–R„ ­>6-kvöÐ ’Rzw†F*í”J—;BêÆï¯gÿ³î+oÆ±àø˜º†ñ×G~2Rtts$Œר°‰­¤¸»ôR×E$r^³¶èòå™<×Vát^Úa`ùŠz,@ª9kGñ·6ü#â=›2BõE½’۾ؑÐ2„ŒÏô&úzifbu` 2ùV¤!e¾wË´à»d6úÃXÅÅÿäNLÿO‹SM§¦Ì% !Ÿ¦µe.ßaÏ=x}L‘÷¶SúAÈÐÊÇ+&®:¨bâYç–²ßÊ‘›]a„>Ëš¯UJà{˜ÄØwHK“«"ðÚ¯;©È×·7×ÔÕ¬_Úñ€|{’ô&ëR<àÂß¼"›ÜÀoKòk×±l 9•@‘íÀáuÛ þ‹ïCx2éÝ‚­E`c‰4·Â¹äµ#sW”YÈVN«¤ýF©k :BYfúKt¤Ä`ªq¦[æ®ýÈ>w±¿rH…6AøósÓ! h „?7©Èø$ô¦*^ÓÜI¹BX.Rý"¦1"UMÈšZfC»ó~ÄH¤(¬U;Å1™da¸³;I’]7§JS£m;>wùtóðUY˜-¬Ö6Œ¥E~gv “ÂC;Œb¤®«mÛwë f~¤,?Y‰ÈB¼R;Fú¾§•n|ˆXµjÊO÷Ág÷Ít7X¼2*®mFÈ÷)r,è4MBFžš°q˜ÎËžtëí‡Ó Á Õ­ü×¼¢m; ™ ‘W§·¬po‘~&gQŒÔú*Ðù'GÈÐ;{­%s$/°JçÙÝÏ'–7B4r%wkGW• =~«Vœ®+;ß_T#-—aGÈÐ N« !õÜ?íRÍGäéØlÝ.̽›wbZcÃØŽ‘Wìo¯þD·í`7 úüÖ“v°ñ1¯ÛÁÖ+ýÿ„] ޤ8üRÔù‡iö Üæ2`sXûúõ™vR@k¤‘FŠ¡À;™á~G0î¬:ÉÕaíá‰Þß<\Ýx'ßyQ¥‚ú·ùÞµOW†­¡2LM2fÉÄ2F­:]+éÓŒó#ï¡|;1ŒrÞÚµb…E>B°úÞe¬XM©œt)ÃÈ é´²>Ç$SzÓIò¬ƒFÇ]:JÆÚßÀóJÛ2¡àúÝ^—š‘zí¢+×C2M àÑí}AóÔòå0I®Bzµ‘Àà‡´Y§´gÔ¶ECy£´öò@½±ZŒD²[š2¡Ë´lwÍ“þ=ùDPvˆ‚íÀ‹¼[—*Ž¢s¹mŠÀ‘3ŠâëP„øQŠ¿õÝá”Êc90z¢hGÒÏœâ‚6qeCéRï‘§â~÷ÞhFl²¡“âΦ‚κÏþº˜!Jægä¡ׯQ"ïò„†¯co3¯ë™$°,G¡Ð‡±Â&¥)a5)a ºt¢€l³'Äœ=ä²Ü¶›Èü{å5KwˆnäOÕA’"$°ØÔáÔË@,K@L BNŠœ»˜íi¡¬îàÛŒܨ2mW1ÁÊ}v½ eYX¡ë*¥s½ QôA4d›¤7ùµ­)»ÕRØšKÏ$Ï;FÁ€=ŠÎç’’“  (>;ðj5ÙÄç£øvUŒMˆéãÛUǬHü\Šoس ‡ßrO‚,¾í”¦½U;U•„„1„„ŽYoh¡µl•þõçIH/&±C¾Ž ÈÇ)ƒ,¹EšŽÙ¿;C‹Rž€Cg‘Ÿ“6ám¢8Ú;§Ú¨üŠ™R¥cÂ!ãseÕ‚²Eä@•h I‘wy•ß»Ú`ÛyAÈ0jµW%’5Y·GšèÆ¥Ø^;ÚT¼‚¨E>ßi—m&Ÿjˆã j ÑVžÊ­“󥯣ä@uâFÍOÚ[–42Åp„_ÿnÿNëʹm”÷ïÓå@Ýäa‚Þ/ÝäY0Eîç] *Iï3\ñãÄóD‘švn(0r I̤d£ lœ™ -צU¼Ûë„"däh–&þ®õ²8‰…/´^2‘ÄFê“Òª§p>ŒŸˆná{®Ÿ{‡ø>=%²p­Dê¼-è2ç !ƒÓ©¥NÉk®ÉZ7I‹¯ §S‰$Ä.aë Ãï¦ÆÈ·GºH]Þ'$¸oòsÐ!Ó°±è,ðxš¸Ö„À¶¶®†I†L}ædNôæ1½usHùy²mÝ ŸëÛÈeY«°qÇïÓÙ¤»*8uÆo4›”!«Q­™WåýÉÏ»½]±ÛŽ 'ɼuÇÈ( ÃÂéC$MäŽâ}VÙ™¾«ù±rêÃÿÀòÑä¸ÔxSç‰e¬)aãö–ÛŸþ'õÃó”3ÿu~ömêAð/”®‘CÞwÙ+L¡Ï§‰Q(pH¼ÉºžD´ÈEt"ޝg‘ oJ‹y“€°½Eú¬Ú»4A@'RÆ×Ôm‘!«:òÚñœÒ¦õYåûí4÷.÷WÕwÈ 2”ÑJ¢ù-¾° Ø#K’\NÑîsç‹£z½éT^¢î—¹DÈðš¨sS,ðÅßq¦:…ícæI¥Ž= Fb·“¥ç=oKÞ”-Bb·bjC½ŠíØ0 dèvSÛŒï7¾nÛîš/d cZZVÖiÚ B¬LêÙéZm3ÏOˆ4Á€ù¼ZYï”ÝÈÿ¸èJ ÕæF§¤M_.zóЪ0=:ò™:9fò_ù$Fn¯ªÜnÚdH†CãÝÒhÔpªNôÏ04ˆ —V/çe‘“ Ê>÷}Rîì“UÚ¯½àïêrŠvЙŠ|žEŽ‘hBÁãWi“­þ•~Û'¹1•ȲS$‹|`S$ jS$9õÚ!Ÿg¦HY§Éû·}’7Eb owÈwètTù+ZSšªÃBöI¶–Cä(±5«šfÀ#ÿ¬9N÷A¾¤ŠÑ1Ÿ14(“–û®¡´ÈýÔGzèjâ Ý(ÝúÝ«Aù7/ »1•ù¼Ð"a †Þ‘(Œ 1I»Ì4e+¼¨Ç† žPòðEhYÂÑ"ÒPM=Þæ(ßÚqk¶œP„ô¤èžyJø¶4;äý¸V;Â+ýR(¾ë’»ƒ(ÈØ§åÄo݈B 8úÚÂt•_Þ„‘a­¢tÍÅXɤlÒ"EU[=vÑukJ)ä—‘@†>NëvyÓó6m±nùD´(£OÇÉRÉOdÁÈ—÷ÂÒ…S-aÿzØGgW£Ç^%?Ñç ùhjPóQxîš2h>ŠBbüaóD˜ˆÔ|$ð5/š c~ÿÒ|±àÝ·’í;Ù<ÏYÑØýÜh›GÅïߟ+³9ëá8PèÍnÁ¿~nv“øg÷©™# BþõçwúÌÈo_ͺ.Ìnä9ü!-òTÇy¾æçDpj€0=~Psœ×Í”Ë׬t3!z\Ô½´n&Ä—Û¹’²Õö ¬G„xßJ‹ðŽñµÒ"ñ¿ŸöŠsV¶‹ïyÜ/e­–ÎÑH,òL‹³e>¾|ܯý|âòq?õ_HT´?ÿ<îHŠË®i¦<ûãJ;á ‹=žUL‘xqºÈøÝ Øî‰Šw¹K¸@F/z¾i‡œXh¸—ŽT,ÀÞÒ©5¢‘yl|¶çµg/…B‹ÚIÝݧç¿H*tøâ_·¯,JE gC8 }E»,Šñ ÃÙN5iPƶÈÈû½¸y'‘$mŸ }ù¾Ä ¿ÂèUx0[ä=O×|Ïzù÷{BȪt›f†ªjV Ï¬JܯBx7Í•<›Ã³ß/´¾•;쇯DžÏOè7½‚²¬ýÊÛ>äQy£°Ïù:u¾ð_\hJy¤4>Blõ¾]ÄD ï2º@Êcœo®x_øzi )Íû•¼ÛJüÛ ø—ònã\ó(4Qü–w¼sš(~‰Mµb7¢è“†¾«¼“_GÃä{ÚÒœMÿI.“5›X“LS–@´ç_î$¤ÅëHÞâû<—Ú?ûç{7¤v7ôÏþ¸v¾à-Fž;_Ý5ƒ~iã ið:›'îN¡3á?FºÀöâ®k3%´ë„  ç«ÅI"W¥ úý²¢ùŠ¡n]‡‰v¤+20Ï,¬Ï¥ºæÚÔ §c‘ìüfœxßl]­ï Züë¤uDzŒ§Þ–°#¼}´øG7¸ ªà¬gy9— Ñ¢U+QosVÕËÅð³œÔ•¾¦¡$ \ž=S¿ŸX‹"ˉ©ɇOè¶–Ò€ï .jœæ ¨ÔMR¨³†}9u©uSOk#ƒ‘Ýk2ZJ`"Ñ7 †¿éZ‰ cM0ÔY”Â…nxÔɸŽ%[KËzÆÐÇi•@wwH@=¬¢úx]WQƒïîµßAÌ­iZÉP=_œþ®EÞý;µŸ²DÊeY,Ô¯> »¯·–1æë­ï׉ؗ¯‚}áýKF bà÷ç2#å­¼£÷ç¼9P›á¾ðù¹–nóq`@@=Ò9Èü}~»Mb¿×|Î]Bh¢{FÜ(}΄Á•_˜R+„ˆñsG÷¡#Ò†aÑÞ—ïÈSSpŽŒ0‚¯yÁƒ¿÷¥3:pŸÏÓQRûóç©Ïswž )ßÕÔŒ~”^W”o4È…Ž”ï¤õÏþB»’QYÓÍlY×w ñÝ:Ÿ×N£øh)ÈY~^¸A.sÒØrU ¾àõ *$G„óZàk¾À 2¦3—ËG›ø\Ë'pUû¢¦ –íGésÐt§¨é"óÍÀŸ@BüËhÓXôô}mÑ'ü}£ÍÛt¯›ÑJîtmŸ6Ÿ™ù©¯!ïÇVX¡2läÉ¢_)>ª4y ¨|>©]¥Éë_çç‚C/ß/–œÇê~·_Ôý×?Œ6Õýv×¼P÷sÓ.Œ6Õý\É)Œ6±ºá ©ûÅÞhó¨MJîž \3ºnºƒBR;¿B[%SCáÙw$L¹~™¸i"“ÿ³*™pŸY_ußç#è²È\ÆKýXMEÈç7²ë|/ª¥ÅÈW`fK•íG“Mù†ý(a¶£®«m =GÈÏ7Rýzû »o*wJ`$©2FR|£¾û&”j›¦K¦>ÅÐÇv:{%ª–ÜÕ4>’(jå*FŠßÓ펡&#ÇÛ†‰óAsÐÇ·œ‘ji’Ì)Û2¨Ót2 «ÖQ°Ý4}…ÒG¦k]Îúv™ëÆñ˜ô T–ÛSzGÛ$cÁ‚o¡Ÿo踱#hôãì•#±|a±Ì‰¼‘ôdÕUò†~\ï»'PÝÃ_tà„ÓC\é(¨†:„ŒÒClIäéy‹ñAKÕÔ –ªøöÃ×ü´+O¦âl:×3ãF¶{eÉë^<—Ñ ¼ÎûyÁ$Ñ­ððK}°e›0Do½.mdž‰b€˜,0›U§J³†ê“À¸ˆ²'~ÿŽ/8JÉlBTù$( 6Ä£Ñ3ˆ\Õ)²ˆZqºŒœQàZäýpŸ››´ù8r&QýWª· !ŸâÍs³äÔ£Œ2»™ú=)´Ïud*+‹±æ´N5£”–|?ŠEåƒ)Búh8·9ŸzÚҺ̆N!gW·ùºÐMÈh¤ª„HB><ÒK¹×Ð~ÅÈg€tT®RÁŠbØò…[a4 ƒ-¤cÉÂð(¡h¸‚_—GE–cäÅòÜjy  r‚P\ôÊzR¹T×ÇÑ—óŠQ@P¢¾e³Af8ŽÏ[%eð–„×¼_3›¶cFžºqùÞxWPWBT.}_ \~pÍç—ž…!˜+®çÃP–…”6«¿ËûTí[‰¯#^‘ž$ùVËÓç@ù€^²*Ó\%“ÿɨüáhH 6ÈÚ¬ÏYÑa£»'zz¤sÿìTÿc™µ°;…¤`‹¬õÏ+$gm1ò 3ž5ç€l‘uå©<³Ðm7ò?!Ôhd(è&/êü<ãìNlšáNä>ZmkÛT†=^¹†Õi$£æ’f C¡É+—Ú|ëG¾õ™³wpÐÀz¦0h:@˵s6µúÜgíN¶0RlkW†BŸBæÄ›Ô`)¥ý¼»*H_§¹Ó9•÷JäÁ>ç»{}û•¯²`a¢e,cžT:WcÝW-׺.H·ˆ­s|Uë“*K“aô—Òn ëh–mømŸTmÒYÙ>·š)ÑÉ®jøî›Š¾åy”úI(Ïǯy]Wäyâøu"Ï#‘HžÇ"Ï€‘ÇWfž‚z)8¾2ólfâËñ•™g£š$6„¼Ÿ4 Ü?¿4 ÔXéø Aö€•~xЖÝÏÉAƒìž•~|ИZ|Íç±Ó@ÈJV:VÐ’År@°Ò!€/‰³±’A$¤óîÑYVŽ•žùš“¦DH_W×45?Ç‘‘±$bàûdºî¯ÔÛÃÿ„]Û®£ºü¥0IxÜï{Ig>`ÌÝ\µ¿þøÚv`¤‘–F*™`ÀînwUÃgùÌ:¬uª8Š8ñÃ2WBFß”¶âãŸV8ºÓȧÇ<4Ñ»tXûÔ-Ðù:땆l¬-6„|{¥ô¶†–1é4w-ÇwûH Èaî–ÿN—¼X·/ªÝ¾úO³ ³ÎÚ²Ÿ3–ðÃó ¬«¤9Å‘§Mœ-U»¸¸Ä@]ï·jÕ}YUÉ¢¾«¹:‰v/!¢ú›E˜æò)·}ò%¢*.^XMñMFg§ð’æSS7ýJrô’S©Ä¾§î<ñVn|©U ×&¥ÊB6Òò‹vÌz“ééý¦ýB¶pÍuwÌ8’ÌzÂIÄ~¨k÷”\\äwTZTqˆÁ½%..ú5iT>»±ê ÿΗ¬L÷…H°é°xÌ·E*IG5¦¼z:æôS#dì#u¤'‘RñÓá™ÿñ/­)=O²}iF<¨KùïÖ^ßÒµæCƒóÄAuŽÂä¿në®5èÒ†>“÷Äh¹[ %×M’µ¡iHb´{{ìÙð%ÙöêÑþ””3¯:4畘øÚU)=óæõŠÞ´Ê¯T–Ý»58 £Ôú¢‚7]°¨eï$+(Fž²ÇD¯ÃÕoººUð;X\³8’DÄ9ðyFáM‘²—Š6!ƒ+n²× ‘¸^è±DÏÅõè†á;؉ë…ÁÝüH ®íÄ,òRX°S¦žÀyÍó™ñªHƒ¡ =ïäE Khô¼˜“bš°ÔG×ýs’Áí•¢÷Q°Ït¬ªv¯|ö!¤°l´×Ëf«“ê“!dè÷jÍ ©„°ó¹IR„$ÎöÕrüçt˜³^äzBFßýs" Kxáøã!2o–ߦ= Y"¢ÐÉ-õȼùËÚeê(Ô‰<óf+ˆfD*Åtne9,BÆ'ïÒ¨Þ%Wúp\ÚïU1 ˆ[¿Í›oƒ~ÙÐãÒž)§±Z‰ž{å4wæsiš ÖLdð•'imki¿>¦kÖaäE9Eòúàëx†Êbe@ ÙðInŠN>C6|ÞhÁ©¢<£§ßšõk¾bã(ã›Í!Ÿ7Š`’Oóùº,:u[Q/ âåçë¦ÕM¬´.´{¾/Y"ñ/ø9Íó}Çâ 5hH…Î÷dMöõ Bßõõß´÷¨:¯”rŠb{uêëÈ(­ •H꤬ÇÊ훟ód¿âj瑪󤼰šû²ÑO„‹‡«»œF%½Ô8RìÒIªCHמdÏN¨Êix2´øw>‘Ó™Ò?Ü÷\ä4œ3<æËç¥h–½ô+Lç¤Ýñ˜o¯ÔYèìG:E–5Ÿ³£.mj*òõÔ´´'™™ÿ¨RêP‹ò¸g}9ÏìðgZ›ÔêØ×€Í†±Ü5]µŒ–Èl¡áE·ò´º½Ó@Éy0"?e7©ë`„ÉSHû_›Ž] Á)Óëº×O,N9:|…w„ÖÑ«s¿ÈºµZÂáêÑ_*âP}Ý-9¾ïTøzýÅw 2?${ìñdÃg\^ï›ÐR]#ä…Ù ©ûñ °óB!ÔyBœG·4z¤Îà4z¿3F¶)šº%û¦_ªr/?3ºì„]`i|ÿÜtÂ*²$CHÏPÉ–Ï>É9sKãûòão$àïCŸ8ïdë\'³^ïײaì³cd€Ãxucßï;ô:½Ïpá¼÷îvÙJÝ,…¨—ÿéfÉá= ™-\6Ý.Óܽ]wí)r? /g¾Þ³!/gþ ù´_œ²º(µTã8I­ô¦µHLÑýFZáð}Có—lEܽoS:ºŠØûy">Yii¢ªÚ–¾wŸÖ*ñê¼FŠOòÔ…B>­Ï“”ÔZ=+8ÔZÞ¯£þ \ uR—ŠÝ[Äm ©¤j¤V¨Qäð¾ºG°2©²7•”RŽïèy®ä/Mža]ò2OÌzvoµñ’9uB¬8F¥LѲZ¾$nsÉܯc€²·Hð˜äÛ«R ºˆ ctß‘[ç¡Ì¤£+™tÉì‡!$¤û‰ò‡5cŽ£:žò<\¥b@·kÇ?wýXb]‚è"¾‹.zª\œx{òQá%QQ9MŒÞ‘FLGyõ™øÎÖa†"x|è;NóJûXÍÝXŠ->µvå¡ï+©Îm³h˱d~÷ú(äPºˆ%öÊ'r¥Í-åy^òdÚã߉lSt¿ mR!¤/º“ë)›P×[’â«¿<£7ª •2áîV^Cø;ÍMýÖ©,IÉz,y¶–lÀWJf„½Uwö:Òi:UõéliÄôù’Èç¥òØÓÜ<îH\ìH""€Q#”Æ+:©É?X[}’[†•çÔy$ž ¤$žN\fÎ$Œ_¶îÌÚºÃÜ¿¯mÝ'iëumŸøeë>I[÷ !¯lݧjLñÕ¯mݽ¯ó}gë.Â(ô8»Ès[w6á;:·uŸ¤­;DÊñûÒÖ]lqbÑ9ÌÈ6¤™¾uñÖgû0Wró´Èø»lgN)Ê)ï]Š¢¥={È¡I†!½].×[‚ê\a5+à1Ž‘Q’6êT‘²,Ûe;ƒ.¸÷¦Ëýš¨¡MxšR: $’Ù¢Z4ºš¾®gkñg~ÙN×!å3jÛbK–!ßЮÑÔÇ9.K׋¨½CHÝ ,•¤®|?÷nA˜Óøµ3ÿãºË¬tîÈ—‘¯UU›& âye*1„#«Ä¶ÍÖeOò!A6!µbTÜÒ’±µ°¡ˆA†ö–ÒÜ Ê›ûuƒÎƒ$V_!UíbªmCÌR™­“Ý> 2rHj´µw‘lg«»yƒ|Z¤”£ÕJMSåeÖöã4ÈLhNsmVÙ´ù¼õ´áßù¶H«ª¼i›®\Ë;¤VBc6b_(SqSxætwÉ?j„EæFüزŠ¡¥Æ¾cÆd.eÈŠ¡ê1ýþBYH>§d¦t»¹ÁPõœÖ?T{‹ñŒLæ}] f— %г’›´³J·¶]š’×%†FšëPLüX^,­Øz€–a¡OÕ­8TµXUëZ-Ë¡gÌB_Wg?Îh…ü<.j—¬î6EÓ­òb»k3¤ÝäçÎ~Љ­É&@Ä£þª:£ç¶7NµrWxOC¤W˜‡žHÔvÖÔMÏ2pÔJðú™WQmà·L~|¤N»ƒH»Yßê(ù9Ò áwÊlnت##?í¶$Ì:a“ó| žÿª½÷î}›ë*$AÕØÌZΩ{ç¬mÜ7êi)ý{üý¼åFÆã,Mù6÷IüîˆS¿øwF–¿áˆñó4ÉdzÜñ˜¨oD_}ßÛel ä'BN¦©ë¡[½{ËÒiº‡½éè§ìi»ÔéŸfåÔ(aÈ=Oð˜ä¢p(ÞùƼrjeÆÂ®›2¸:ç^÷u\”uI⥉äçu(ž¡4qÞÇzBÈðʵ’¶î+v¡ vƒ4j…2°Ô2ñÍNú¾uËœÎB†~³½nÏÈ¥^îÖ¥·7ó>9|WÝt|so]üE×µ}¥ÒÞgùŽ‘Á¥®!¤täqÃC¡5ñ|MÌ.º5"èm’JÁ³K­Ÿ³‹<‚ f—òÙæ_Èf—¤}úÌ.ò.˜]jLÙe7Ì®#o˜]{7Ì.XÁ³kŸ2ŽÇ¼Ù_‹!dð},܈,µéº½$9¼ e©ƒ,™)ÉbìØ!dp‘ÿ$;ß9B†§BFc2Ö@E!ÎRöLÜowªä¡ DW'äÒo|_K:Àæñx^.Ê\.ÊÔRŸm|Xj¹Xjiž`dx%îüûˆÏ!– ¬z““³´ïÒµºYò²Y+ LõÕÓšU>0„  ÕUñÌuÓŸLû×ô0¦n`ýÇÙyÉ1?=ûˆˆé;¾F¸lêÊ"Ëò ##ˆ$4°:›¦ó>¤øpR`­ >›X–³´9 ¿-µ0m©".ÄZß!$ò´ýq“ÈƒÙæ¨ja’bž5Oª2:ä¨9¥{^ ùôLœMûìà 7µ®¦kKV”œã õYaDûÄ£dÝ:ñÃõ=†Afåý$m¢NE¢z5Dl ëH·Ö‡ßê¹—«.ÊRµ»®Å^tÓW0+­âÔV¥ŒÚïÞÓ£Ú¢x¥ê•‡‡úxydÁR×Û>Û.ÙzãÄ1ô}¢uVó¼–å¹ Cc_PÕš^óN:¢äø¶‚ªKƒÚg,;B½ÃñÜ|û:$b =@WÒø”–˜¿•/v~€†”–ÖŠj×ß ߋ̿–aM3DVàÝWZ¦~ 5ÛBŸ9HE¯j&^¤d–ªµþgÁT¿w—Nù”‰e™XèÛ)G~¨=uÚyލòÐD i™3PZÖb;£E^“p¨TþÝÝ×ñ<¶ï£ÝºÝÜï†Ô•îÉ뺛u”ÝmnÌ÷ñLZôÁ˜ñ C"á+Ž~nÍ7&÷~FË.¥ãì*yQp¡ãÌŒŽ3¼ÉQp IaUý4YÁkÚNxÌgÓ5Æa ‰‚k2›Òqvw ‹¾/ËCW—£ͧÑ}ÏQ2öù<[$ñ òÿj;=Ói#4¯¬&ñí O,¶$‰üC(]ÅËÉմaé¬uÓÒìÚ‹_ÁV o,)F^[º]&ò$ÞU_ÊÇ|‹X¾*÷®pïÏ#sؤ‡»¬Í­\d¨yN­2wyGtOƒyF^ÑGiM!ï@d6ÿWÖIb;r3ìŸA]FµûÞãÛÎ¥Ñ[mâËÎ¥Dv.m3öl)ï¶øÚæ™w®‰ãygI$Öåv™çϽt¯äµt¯ä¥‚ˆ­ðïÔ=þªß95î0RØ®R1ÃóëPOSk’ÒµXK„D’#z“È•ub“EÈ‹“óήaà„¯N|¤¬DÞ‘m±HƒŒ¦DH| ùÄÇ” Yi³—S>ÿrL }Äy}Lérí§L©cZZ™.Ñj¨òvßòâ˜r“”xÌØ« hUb9æ6}²þƒÇÔÇ”g/SÁÝËäm‡_ÈT¾v…E’¤}íVilcº”OõçAáó ÔJŒy6fÊܘϓÏÃ!§ò€ /òž0’œŽ3‘‰—‰#dtì²Cȧ ôoçSlIIüëëÞ)Ì|—v¤‘Ï××½{HñÏ-7¯“¥Á"EDÛ•yX”%¼Z¦ÕÝûëdiÐH¹4ô]¿!äóüꥸº[˜ÞwŽr~9Æã*éh 4íŒk×'Fz~ pGšÓ/‹­çbõ±ÈÇ÷œß ó nIŽJFwçiB„ÉxxÞ§¤ PS ¯àN{€;×$ò /}Kµö$]¯ðÚ U$\+I¼îܹ·zYܽ߻s³æ€ôCÕò£ tÌÄ×éúä^—îÜÄWdé*,Ðà¹GˆaìÎQ”UB¹¸~¾W„%_?úlFÉæ®Û02´ÈÌH×Pc€$P*}EèÈ[d=¥9uıÌxL§š¤ºˆe ¢l ª½œð˜ÏÃ3’3Ÿ–¬,÷‚0|ŠCÔÕÙ”uW !ßY‚ÃÌäßÑ#ãïd¦“ž˜iÒ@ðmfþÇÓ´Ëu ÷gkÇbKûæ}øê°:1W =:|O`¤2b+´f5—i½V††PÀa æÁ,e—Ì|øÞòÇÐKÄÃß§$–aÇPùI•¬ÒØ»mÍöýðôõ‘÷ª¢K(mEæ7•[r€êˆ ÂeÈZñ¶.U2â7å ërÅÕ­Ä3k·RÊâ‡õˆ¡øù˜ÖxñN³-I’CÂÿ´´šiþdmS‹¾=@^wz^©8+ßó½ïj‘þbhð-„&ã—¬[ë ÏïÈQ‹´î[ÛfÎŽ—ø¿ß" b=‡\íõºÎ>©ê^‚I}#&çQÖ® {ÝÉÚÕ-Ý óvœäõnäR^>q-Ž“ü]ó Ÿ«y¼nØàb_t•à÷ã¾Úäî¸âùdò˜†ÃÖèó]¿ªb“<#ÂÈ‹™—¹€ea‘÷LÒ+#ïèÍûµòy}î4ªtºCÈ‹ú„’þ€1_·Ú° 12ðY;ºŽ2gãRQñØèý>Šÿ™°àS˪5ÛÝ,½'²’QY¼~ž!òø™ºŠ£OÅú°ÑeØhu“ø[Ž®:˜«×f½=±_+”Q™öOÎņ7 ä ÕiüËw‰nxÌ×¥à%øµ‘w|/xéB·w|/xé½Kñ­àåèN¨Þñ±‰Ûk£ö$‰ã‘þû¿ßÿtV§¯>öÍÓ 0Èàû‹S&壈ñìÊ?î¾8É1` )êêj·e•¹ªìHì¸*¼¶]€3O¦i›èŽ‘n/"¸oÈ+·±wøíyf¥“–î#ò¯$Ï2Âtòýœ³$¯Ó¤F òy¶2l\ ã@øpiá)fBȬäùɲü€ï(þN’+CG)/S@FÇó[}qyî”§lï,§ÄÏcåÒ4ÅK—¥®hv8ω_‡Z¬“Vo†fí@ZįCÈž«¸Q»LuÉÞTB†Îºª°®S»lˆ3$€F“­É›^“È“5YŸ¨Ì3ìñ±G‰ª óa˜Ï¤Dk²L‘~AÜgRB?«aR–"ég°‚ùLJ«kP ™¡³Ãït C¦Ÿ”³›´ÙáÌŠ¼’8Æ ƒäÿ(ä2v ÿ?aW¶<§ËD_i6Ô¹Ìý—ªäpCÁ¬<ýÇíoœ%©ÜœÂšî>çîí·_ï7@³ *^§ÕÊèXcxu{`8y¢r,7Ù©·t¿ÿÜgQJí3^ÿþpA¸j94†eÍÒÍ$9>A?J5• ¼œƒ¾œ —)èM~îJ,–£l!Åá²ÉJ*~ê²,^±ÜA“˜÷iî¶aØßœ¨‰¬•¨ ‹¯B±ã¨ªßûQ…Üí]l‹íÔûˆÚ7uayyóy¡©10tI´QÛ0CäŲtú™CF;˜øm÷:ýÝ÷j¯c9õ¿3"þý³cö`+÷º{ít{žxÑ•íH l¯YWù.zÿlÕ³©¬›BÑp9­s¯OLU•Ÿšž$ºP¸ÂÜ7†¢Ûë+å²óbÙèöwdä•M³ûa:6GèœöiM€'w,?¨£‡ÈGÔ9Q›ÞxÝ9!XÎ8@>#!dy뵕"Û¦q=ô"Jb{ø•¼Y»Ë;ƒcöxU[GGå7!¸ðý™|Ph´ D!€4ï¿Lµ›ØæáCù­Ì ³ i‡‘ø³—E¾¯Î4¡'E®?*+Óºb_YA7(:ª—¨ÄµÈÇE½„I$Èghs¯­l€2FQ¸Ži¢¶?ÿþZ‡ac„ÕˆqÙÃ3J#7ึAU<«ò@&FÿBXý ;æ<޹¯“Ydꪉº¸ÐZ¡¾E®6m¾:döArÒÄbòÔ›×"¬KÐ× ªÒ“ ¿åaÖçÐ->Qé=™˜Ø¶ä.F¶b†c¾bUi'û®t«ò#¬ŸáDõgÿ …•UàÖ2€L¢ eƒKä°L6€Lc¤säŸ(›€´ò¥Æ¦ÜÐöÕÌ5Î=ÇùŽ µ9ù5ó°UùÈÛüþAP´ò<׈b @^{Hv ÈKÉžž¯Ï_\¬Ñ‡î·Sc=qòôKÓU¬ó¦E(ö 6NʵG÷¨µËHÅàÊ:è~î{#Ä{&w5a{ÅÒj‹ý6ç9“½•½ […E¾B·¥÷ø•HÒ²Þ,2:'ÕnÌ¥“?tç~çºß¿(G©™~ÌÇwbŸäDÝ4ú6Í'dèÝnx^w5ͺ«Éù‚žœöâšf¬þX‡Ð{\­K³üïhòB4W;‚ú{O.$få‰_IÌzµtO¿õÎbî%fÑ==Ùo…ÞÄô&¢{öu–Ù¢û—.1¹¹ué‘üp¾2~æÊùŠPá3ÐðÎ%B•¦ùŒ,CLÖÊ£©<ã>Ì|zòËõÈU#+¿Ç=Ò%B9ó ¡Xy~/~œõô*ÒZZÔ1Òq\xõ×R™d$8SÅͤ<§^=ù„œ‰F € ÒÒU^JÑ !˜X@f‘ï–¥ÖK$!c±3ø;‡´´eé¶d=© NégþCµ‹\[ñž©ãùsHmz@Cw¦È©úÎÊWZvt'ÞÅŠJœèÈ„ ¯EzK^êJ_ëÒÈtÙ1œÔÀ!Uo©y£ºAî7ÅÞT%„&QÚÁ$ôkJä©»ê 4ý]5´ìW’nº©ÁÛ»ú4Yï Blÿ²þ­CÙ;±'÷öÇKo¿¾.–oª×µpÐ{ÐϪ§¥9ͤ›Óo R%µet”ÖâX[,HAàZ¨Ú>yµ¶ë—Ó—jÒxõ#¿@[½îx.†}8N¿ ‰3'å¥jÉ«£‡Ð$ÿœ0×Dú­ò¾;MV¥S¬ÿY‡»i«[~œ ™7@¯íÑnýÖʵ·¥'è;Ü2YövÀ³êÌ/'}ޢ̋ ³Ë­”¡– 5ü`ŸqùÓúªwxíIJ5œ×çã't-»Ð'€º°Ê%ˆðÁ>_§,‘Òü:ªuß÷ú ¹§ºÒ© Òvry+v¹Ož ‰o-H,•ßÝæ²ƒïÀ3ý pË?A³j¬„º6kÚÞNÊL5Š›É19í·“›:¼­ÓÆùN|Z¯{ 5bf[·aÆjïç §f†M©E?!KÃø ?Ã×3†Z_ž–yÔÂ.D¯WUR±ªKè ù±TLl„×ü¼ÊUóâÙÉšü„®wŸ ii³+qÛuxft| _Y mtΨÃò‹ár‡;Aß?¡ëª TœFE7§Ó†­êQ30t#\àÑwkªìèñ¡·ÛòiÉÈæÚ·“¡˜1xŽ—f²0/R†c𓇄û,Ü㋺,ž›Á×$Ñóvq’ÔI ½q‹´—÷WõʺÎçž÷ÿhfó±÷ó~Ñ̦ˆq3›E¢O‘?WÌœèÞ¯˜9[3gWÔÎßf0<@æÏqÏÇ•sòŒZÿ*`m¯~ˆv=øÞûlaÄS…LÑN1E—2zî?Z EB×9÷¦ð‘xóþ²[©éªW‹4‘s 'Sµ†„7}ÓRÞYþ¹'°ëç¬ð#|ØyóþÓr ®0×,ßùH6ˆ|^çCü öL¿œôµÛ°ÿÙ—ŒDƒ¹¯^¢ˆ§ú³j½ÈÓQîÆŒxªF¥ÙµÑ©Î—­êÜ(bŠ:9Ï꜕äÝ ùpuc­¡˜ÁrŽö™“ˆ)ªãŠÒóÖäqó˜½q LQjüŠòóÇw¯Stÿ¥UÂLÍ’Z—Æ…êÕ+r"P³¤¬l¬²ŒJêyõßÑ+îªÐúWö¼Q ²É¿¸ù5©²2)5f]¯!Ùsz¤=oÊ1˪+G€|?í0¾åDb.b>9f×­t Õ–Øžó„짆÷‡€WO²ñcv^)@f¾&US]‹>:¹9 @¾ƒáheÿV¼c·§·ú Ù×6‰ g@N+BŸQLd]±' ¶]9íú gø’8CÑøØZ8éãÛ³žz]Ư ~$@뺶É!ù[ëµèMcçYÕ¿5_Ëú4Y0©Õ_ž¬²éªÓm½?ºR`"C£þÖçÍ…F…­Sé#ÉZ´ýPÌê÷ =-±3À7Ú1ø¹] ¦ëžFÿ'ßm$:¯\’;é×™OK?Ìs*Ö.Œùói‘LN/§JG†ä#BÚY’H9—,Ì|P"øœý =¢Éã2û7ku- ‘è³xOá%WÜ5æ,Çô{\òü*UO½…J^?¬z(/Ùh5xK” ÈߟJµéã0ÃÑ:χ\‘Wá5 ,DÄæ 䘕cSô]Sîù†ù"Ÿ:\À«›8Ì¥ÜyQ*p9œÒæ– •Q}¹Àyº?âÖhsXQ7EäQ”ž ÏX Üdiu‚ /…ë @ä[÷jªi—K}Xœ’ˆHëã“¶É'ÒÏÍ$ 4 axi»í;¾ô¤¯~š¬4Ö¯œ¿çë:+“ˆHkòF &֖Çuƒ¼‘9\«¼QÙv]ßþ[”7r6}ê¶Šm&ð¶±fœù•Gö¢nñéÁ>âf+."oKàc›|Ôl¡q6ÊdÃTç ɲ8yÙ(Uœ´Ð³ý…Ù¨Úæ¸Še)BŽËBUa5ª¹`ü4j ÌuCE7(gëº`§ˆ³QÉÇu.1Åé¼a†ÇfCÖâc"pº\LÈL®Azÿ‹‘Okm5ú¹“S¹˜m©| ŸÏ8cü^U.¦XŠ‹±Ð—wÓ•\Ÿ‹‘kV߬' %FÍJ?XLt|Opµ^|!d™6ZBhuîÆ)QÞ÷;\l~Ã[ãš§µLÁÓiy3ù?꽆ǞCßÀÛzÝBØgž+Q-øÝ8Î2PP¯ùõ¥Ês›ŒçÄêz?bA/ߢÅcÍ7”$'Of§„Y åXòÛ2ôŒëÖvëWn$÷Þ§(Ò8S¶PÈ~39!½D„*ªYzT×ÌýBë2q•:-;a{Û»¾ª|ú&c%CîqOˈ»ž|ߟAfäÐgÚª¾hMÒ/'-L2äã+OW¼å¹„d`*T•µ™PBÝÀóy¥§ü`V?³ú Q¬×dz~Tþ¨„EáÕãڡꄞÃÔÈ!Gyx„Èôƒ¬4¦öðwÆo÷ÉX’±=°š-ò}âs¨XfÖ†>¡R—dÀYÅö¡vNËvÚ„Ý?»ì6UÊxMžÑ)ãùÎåä³2žá—*e<ßü—2^‘_”ñBäõþæéɃ2žE^yz.s¨U$•ñˆ~FËÑÃ{¿RÆ;f1À1ßWß‘Œ¹Ý̧·/ßÑ¡T @>®Þä9Äûé-ª¦zõW9ŸJ£Ø‡0Ÿé-âiǵ\ÅÎ)T-×ÿÎû9÷fg~#›œÏ>ÔÛÓ{°µ ®ÝaP5yÓû>‹4Ò»ó=øš)}ÐrÂå^¹¦© ×äÖùÚz0*äH÷œ¤YmäZ‡½æ›aÈ÷^…ErMJîħÑúÉ5ýù­ýç횬R¤í8®þäšFlö?1R±Ù;¶W¾ƒ }–Æ/Q³åÔ¹áÓ\Ž­ÌÓçµñÆ8p•Q$õAkz=fŸ©Jã̼â“Û2z«DZeD¶ø!‹úå…pL–NuDY¥X,JýÎÒ…nªŠ\×9óåž ¥³5JÆ­¶'W¥˜Â£wéu­Ë ±Â;>¡4’¦ì1ù†@öØ Ë :(d¥É°ÇÂsOþƒ=vB~a5ðêØcŠõØcirÁ“HÈK“ ö˜BöXš\°ÇæáÄ3È÷Ïl 5ÙšÞ¯ŠizVF¨~uS4<8æ3ÈÇe7_V°ô•x*—¿OS º2@ƒÊÕAAÚ"Ñç Ð0ì¡”ú˜ácˆ†¾ª4büú­ rbÅÖø«Gû»õª,_³Á-•SEô×´ÆlhÁå! òž¦ëº¼ UcÝÒä´L)¸²oˆÜãè¶Ý z–þývì«f5 ù¾ç;@FVžFJJíqe¿pNs—UŠt—,óØV ó¸æ| Oó Tý Kب=+–0¥a—‰u~jÏ’Ö?£HwéÌr“ÛAÌrËî—¦¾/÷Åë…¢ìñCl¯±zœáéÀ¸Èà´¢š}M{~QÍJ ³äù:f¦…¹=–~í îËÂÎ¥ žŒˆ‰ëDž÷Û։ܚl,2µˆ«Ùžo›Ó3²È$2è´ËçÀÊnÆsÅà˜©ÁêÊ ®5]·ášôÞQ›fÛòcf¤ïzÏ#Ï|Çëu7íMylÒa©á˜÷¨#ÙùkË-sd}ÊYè’ß±Œk•ûÒQí\ÊM®k6xýûãR†&ä¾²¯242óA`öÕ(’^  e_Mv¸RÒÈk“К½®›CÉÈ×'ÓCTÝOlÍÐ…“©êpDö ]8™*_-@dÏbEFa \D›ª—ôô å*ëB¨ËVõ°ìðêè’¿‡ùDÀþ@KGØ«¢ckéyŠ$‚ Rïr¹±¶[g€Ìb½#ÇS ÌÞ§–“Êì²z>÷¢+ÊÎüÍ×K+ÝǨŒç¦U¾LãÀᄚ7T{ ºþyO˜ Å…* ôqU¬îÖÚM¡dÉáDÝŸ'¨Jôo]KD]Ôp¦Œ ÂÿæÆOT”pì; ÍV™—’ƒêä„/J¸Ë[ÆB­\WË9æS‘3OD˼Ðþ?ý[ U¯ãbkÉ.öÓmej*J^e®æËût[ïK²xhyß¾4‰(ID¿‹¾o Är5ÔÎè÷‘÷ýÚ‚­…Ü òÒ‚7§1/Ìï­ÇT߯Åí`~‡Þׯ@ôÐM"~–žßšDpªBïçW ÿOØÕ-=ª*ÑWJ4Ñäò<ÀTÍ~üETTŒJí§? ÐÐF³o¦¾©Z…Jšî^kÅA=¬²R4:É©KÁù@T!jLw³l¦²ƒÕ;Fâ:˜¤Ž\`ä%ˆxưAbÐÞ˜¼€¦\B›A^€Ôã·x>ßçm$L/¿¯¥’ÄnÇ Ÿ÷ãiX°]|Vpî¯Z›…ÎòÆës™E‹Œ®î“ƒ=Íóü¶ gþ>“K ¦5¿ƒw>½¶`320æ 5¯ORÓ‰JtcíÜêü~_#çIªÉš2:Gªi¢AÈ@jP}Å•ðP_Ñ̦¾CÈÇRj$]ð}B+¦“Y46yl–ì 4Þù³/¶ö•"jçÏN(Bþxv*òdz®þãÙ‹!¯Ÿ¹˜Ù"ÏÒŒ§‚n In¿â´Œ„ÓJn÷ï'Ñ>ŸÂ!£_Â%…æ ‹Œ !iæÓ8·ª§é g%“„boÿ"çINR­aBúÞÝ\éÇäE?´i{ÌZGíáwÒK0b“@ìMwŸ“ܵ^h×ÚÏT ‡û|†Hj %zÌ…q†I`E[V0fE6âûLÏ õ„6É£iäÃMK3$=4ã-§‡'2-*öt“Ï©–c_UÐz¢tLlmëÝ’—*ÂË!µž„¢t')Á|’P”î»KMT‹‘× \ô€<±ÍbÆ6 jÉíùÆL7pñ!Ÿ¾5¤²dܽE|’¤Y Ú„q¹3×"¤$3¹Š4rwNEȠЬ©Fgc—º…–4‹|øòqee·>£T§Ác>CÒ°%ÒÕ¹nÛkFúB3œ‘÷g¯Õ¬bdú]–ÕcÖÜk{Zä묄:–T¬P¶È÷w9IþŠ•BtáfþvZCUk­¯¡&·ôG UEõà–ÜÒk…`)§–úWùõå ®rK_r:~ò¼Gº1ÊÐêCž$BFþ§}Ed«ânÖÍþã|#oÈ|imÆœ®«X]˜„ÚhߎÎÂ'›’Pí4ÙäBÿ$ÐF;O6¹z|âµÑNÕŠ|²)ñÚhGÜU› ý6ó)šêŒ+ñ÷#•*]ѱHm ™¯[OBu2÷ÒÛ ¯:ù‰LJŒôT&ëûìé(YÓJ„ŒCŸ'[ïœùV¯2sN´iüPw¦Gyp>}اÿે~¨® é#ä(s›ñ+ëëßÝn±TgIfѵ¨¤êÔ*3V žg‘°0‘r/#ê¥v’Y>U ,Ê÷'Jx`+5ù‹ÀÈ m÷ÈÐ PÙXg\ýCÈ€YV»tŸ®º­Ú{Äø-2EÔɽXP²b«DÆjüìЮŸÈöÆwM–‘ª?Üç;è$¯œNR?i#‰‘IÊ.(dù jæ·m<@ïJu޽u¿®ysü=Á$…h:¦¡ÿ÷4›2Ro‡QMGÀ®’°SàMˆ!eG‚¯.èí<´XäjSâš[ô,ⵉ›ÔK8uU úÐzÚŽÑk&ðOuOC‘êä‘¥ØVQã·ïþBÐ=ߦn cóÊùá^ßN×u¯0ìK.#SÅBž¬Èðëþ„Æ—jÔÏIJUâ{‚oÊU4§q"ý&*ؘï î°ÑÁ“Ñïå<«5ÅùnZ$ò[5É)ÖVŒð‰6BÆA³¤³ãdËjÿòöND,¶YÝK†OPî?êLn ¾z⃒ºrAÉ8Ms5°äž"m˜´ï´ IÚ­nHïûcâèôêì2OBÆY›WJ!'µL´•ÿúÒ d7ÚÖhL+c¯‚OP"…ûÔgÙ)ç­™¸nƽ`•7H­bgŒé,£»ÏèöÃç,o‹Åå{,òÂçLg;x¢èöãlÑr/(l‘sÃê½5_ýùío')CþvItío§®?q?ŸQtí„G5 ÏeC“è—`«¶hß=züÊqNÞ^Á"£ðŒ^[si]©cþ=‘P¯=)™uÑÎ ÐÉ“èxþ«­Òž~ëXÕ•{©q§²FEG>µ²ÈGØja–°½N¸y‰E¢Ó|íHÏkÓôÃH|š$û¬i2u-už¤Ê I5;\ýuF|%}PŸ1Ò%{ù«¶\4±ÍÓó™\KkmíTÜL¥¿¥H¡D—¦ÍBKkmÒq'~–ÖI”ó-µkI¢×5iM‹Ýïçûúë@ÒÃI|;Š>«¥{§¥ÌM6°muíøI|?6Zbº¦}’©Ïá;‰£_$UéEÍ’ø—Q¹œ¸hÜA1~|Ëm»†I‡6ƒµ.¾6*ß«4 –x9¤3Û,çÃÈè|>µø/¼óqò]íoô‘AÍRY¼…à&þ²u³‡º½/@ëßr„Œ‚æzûuCÙ•:³¿f`ë†2XhYs¿Ç' Ñ^NNV“k'LâŸrršÊË2ºrèlýJrr‡–Ïçb·kéaœ‹}üáÈŸÉã~E==P/rtJAôž£I(rtœyRò¹„€éq8xò#zÒ1ÖAîð-:¬ã‰9x¦¹ pø|Ä_ÆÔѧm78$?|ÖV·R#n±ÿîrkµñ!¾ú3·²ÛZ ¦’Г`‘‡6¨ý3RÍ2M#d‚1jº$ÐJ©ÖùLÅŠk> äËû‰‘ÞÝóвk‹ivÒÃi<÷¬,©CòiYVȬۙ¿¡Þ&Ó6IÁéÒüH÷Ka1®£ÉãñE§qNÐj]T›ƒ;½jÌÝ‘’®17y<o:8L=ž¿‰7>áóxþ$Þú€¼&Þ ä5ñf:Üç5ñ(¥ù:]‰T'dØÉ³¸S°/J8¿ÖÔe]¹¿Ïô»IÑ÷e¬‡ˆé‘^DÊ ;ü#E ÉcÇÐ6<æã ½Eù 5À@š[«8þ‹ö„à;6&GµhhÅ2ºJœòÕÿF_¦a†Å§®¾Œa TÝž·C{ha‡KÎ>mÝù·î‰OÆÂ¦1‚X30»±È8´¢®R’O½·Ú±ÈG žY›¤ÄNû‘[ ´ç Y>’܉9é¨aþpŸìzÞ‚Þ"ƒ¤€?|Yð}"1+ÓË9¶‚ C×µù‚=6s #›:jˆŸ7d/ÊûoÃ'߈8Ìü 4rJ­5iˆÈò>$ ½»Ó©!î52Á–¦X@ ÐA#÷:Y¥ÍýSZÚ–xG$]E§/ͨݠ¢åMÇQÈßÌ(hò¼iõA›…>ÏÏs”x ÓäyÿÕ@½•eòŒ.¬VmgH¼&ÏÇË*\6ùh~Ÿ[¨¤>ãý:TÛ+0„Œ¿©›*ºT‘õšCýyuSSõV©è’WÏÇÑrJ»óã ÑP –r²Š®ÔןÏ_hæƒ(ø,¾kü·œþŠïHøŽ¤W”žÝ¯<8s?SÜææ#‹ŠÔå”w |¾‡†øÑ¿!ïf¼•6ãuc&Ç•¶÷²û5C¯rr;Ô†oñ™µ´;ŒÃJ’Õ6[TÊÄJ`–¿âݺ_sé‹tÉíHíÀµa0“´ÈäüœDe ÝÛ™zñ:§kß©‰Ï8'ÄàØ°l†eI ª\vYʼ­¹“M°ÈøÚÚ bð$”N=±6óiÃÄ‹[±©’ÚD¨èg1 PíNÎ;<Œ¸.#AÇL(Àâ´÷­m)W-È•2kgÞT¨GÏ`¯IAÔ?N"[ÿD{ŸÁXL~–°ËÞ=àhBÞµôƒÇ ó7•ë/Y—N*Iäoþ„y&])©¨?+$½ASêÍÙK›0ëj÷8AÇ¡EzAÔ½5U‡-].—: `–b”9Û(Œáä&dKjNJŽ'ªÂÎÒR‰^¢¤ô“£é¡åÈ«3ÍÊV© –ó*(Î*Äê7<æó”ôEÔI:#xÌä”Ê532O_%qп¼ç!Ç–Õ‚d4ÃW…²TõžcûlcÇÚvƒÃOâOT»bél ÝÃȆ–ã«{ɼÐERŠ‘ùvø‘î¾äë2wt.hÝ®=Ã׿Ga5Í@Õ××ôÕÚ°Ã „6¥–÷kè‡tdÎ6^ }\êÛùp T :Ó·ó[Mòø­oB-y©o'ý6›<.½ÝZ}þñCò¼æÃ¿#˜ýäR'›KÝ_ã7¥šyZÏÈ'GûÞ,®’*¶e­ˆ¿úû—ZáTK¿Ñ½ÿC­j§>ðÿÞÃÝÿ[À,2½]ù³ÝÿÛ§à^ùYéeñÁHÀ+ÿöêVKÄpÓD¶ÿþsàAÖ¡„F ô¤ø±Ï»N°nb¨œ×S’Þ/’¡ºgÌÅÀ3„ľ{]T³†'>øä²g u¢}“·þÊ*´œ|ŸE¡úíþuÚîž‚óÖ-!‘75 ûbcdù´@ÈPÃǘkhý–|˜çJà«?‚ÍÓTIÔ[R4s•­Ž ôÀ3mOÌ|¤úså3B&¾zìœÂ;Þ×lm‡™"QžÆè÷œóÍø>½|ý8ôrWò¼^ç_ýíÔÙu+¸¡‹°rš k@ÎÛÍü-ðV±ôQÖ×óÔæ¼€ô”?-veŽ4K=U³Â QÀ*Ma¶ç¤ß8= pújî!vøû§¥fuî+ûvÝȺº™Ò¥kæ—“‹èúû\(_˜ Èa ©ú(ƒÕMKßõ^ú ¨úÿC=Ÿz–Ô³‹Æ Lmoê¾2í™Óq‘}_"dô=&eÁИ –.JûD¥îÞEO”\?‘ì¦Üù=Uÿ\v´ƒm.ý±)èöLú éê§²Ž°Í¥ÿ%ëQF@î>T1çŽ~j¹ÀÆ}$Mïåc½4|Ø´ªUY‘ùºaß.ÆV[•몯'øä_7|õ:––‚È® [‹´ÕÖÿñJh:­Õ*Ãȇ·˜°«:ïgÙ˜M`üh‘Ï@dÜÞ§3“õç¤× [@ïã4~txw¸zz~öb«h/Ñ"_¡!mm»2ÊÊABtõòy©“SÚZû¾®W—úwï8Ííg¬©žÓ:Q‚/o±“sššÜ _ÿ]z†ø˜Í3Ö¿K³tÒ:3p«Ñ¯‚k5½âëTÑêP„x=®šKú®J tž$¤-Ÿ©Ãv~ÁÑ*7F¯ÉªØŠzm}ÙïõÄ¥Dð"Ö¯¯ÛºSCš+úèö†€Yúp= ¯þÝ›·sóæéMíIët¯ô!V'à´ðºjÁឥ)˜Ï¢¤šhÄzk,Ô®è‡Å¡tëtù”•XØ»_ïc*Ú†W:­Vå ÊT!Íõé5×D?ñQa¨@ȇW¨ zßÉnͪ¶"!Ÿ€,ƒUÝŒKQÌŒU|CÈÄi¨1m¹ S»qËXiŒ€æjuy©¿¤3ió--¾úË#©kÝž§zÖ¬ÂÈ·ëöÕOäõå§Î—jlðÌßBQÓ×Édjó‹Cï>Ä)ÍÃS¦¶Ž%'sƒŸéú×ÑÒNS­ãúŒ~z ¹·Á½?¶ŸŠ¶b™“¾LBš«ZÈvI‰½‘R­w« *Æ!‡xB@R8ZM1Ë!ÆÑÑ¡“:jÒ3VŸ·lôS8JpòÏ öüzíÊ™í$‹6úwЀõ¿¿FQÍ(5¨·nëYfiÒ]ºS¹0cìI¿ k]àûÿDR.ö>¦®y«2iÒÊEûÅd&†²-süDé‘ °Ÿ=Ç^ò’ï {BHfx2ìÙ*ú‘þÜ} ÃbvB=10yÿWÛ ¬Ìïøº¥ ùŠ'ïÇO_ñ “P2¿tå?ZWR§ïçO]yî3 ž’yT?ãTWZ&ñ˜¦_íÝšg”xA[äã’âS}ïäz–pùå~7`9u¾¡& y&ï×…:ŸNs¶¢ô»çûu,ÏZ½a®b¡¡. ÿ†¼¾ÔùL[‚ævl9åy©Î°@Þ¯ku¾IÛ²ÍxÌ u>9L­—^gê|êFÕ.»I:ÑòJO½P~æ_ˆ\|ðu$3x$!ö‹À8h%GÈè"ƒø´§ÉÔ(´±ån-Œ9‚mzÃ*C_qËèf>½E?š{v]yæ—úâî"2ºPø$¾™/½]e»V-!«<"O2‡|!#%4ÅZäIæ°È v8(Yäù]mÐda‘Oˆ]d­¾£b %)\h‘¦¹5†îo²ZBcžßu/ö(EÑâû¼&¿ÃÊ`‘ï3 ¡ TÊùD ­½½ÅtÁgã'òJr„ŒBjžÕ0¬7"ª–ÞQº0´)êN}dÝ0VÍ¿1±:ÍIOÅLüûé›kŒ•íHP3?¨‡”=~¢ÄEbd׊6Eé Yà«§™ƒwŠEZ-;³2˜fSíÒ¹Õõ¸4ùʘ´túc‚ _¤Jš§‰BÕR^©Ó¤?w¯º1Ëš‰jö_\‚J¸»OæYñYŸJYÃ¥ÇVÛºP´º ‰oÈ¡Ò uéÉ Ù„‘ž¨nÌ~õ¯¹‘EÏ—3B>×uk¥>N3u~¼úÓ§Ü·‹‡l­ÚâýÊ0*\/„)”l‚}ùFȼÉs“oÐÈå3ç+i¢úôšn%}ú(ël•K‹|Ÿíŵvg…ÆÐôöºpgeÆ5XŽ{±/N2Æ;2õxÌ8düT¶ žUUKûyCÈÇe[êæ¿âvœØ—ƒ,úzæm'ÒrYlÓìG3‘›Û ™~ûÍ:‡l)¾Ï×Ë“¶ÁnøúžyK±ÏpŸïËÔ™ñmö¿ûûúÄMuíÇ&Òûí¢ñííl¢kyGŒálW;Üb¢[™+³§ö,qGÁ×(½G¿Ý­¡Í7 x«çíÈ.]l‘×îÖ~/¾‡¢F¼Ýìoi5Ô?Ñ#Hí† ªÏãÛå¢ ~bƒùŒzUmv®—¤œ7°ËÄ÷+ÁRZ=ç>^Š£/ígÕ „“ !£s•Aͱ„å6þ±Œ±*PLCžÝÞó—ÕF@D-$½Þéf˜Ó/ž¹¸FJ2óu[2ú¶N¤³h„üôþSN®Õ©ZC}¨§?ø•: [büúÑYŽ6äø ÂêåK:!Ç%'>‰¿GüÖ½…[wü­ÂnÝÞP×"ß"… [μ€ˆE>Oe9šUäM‹‘É…ÔÆHzŽŸ(ýLBèÿ„]Y’«¸ÜR¹ ö:â¾%0 aÄ Š^ýÓx¤#÷£ê+ƒÑHgÊÌÉŒÏ÷U:¥‡Ž÷þ>]n‰L¼àÞ¿9†žµ‚R§¶gw[7§ ¬™D¿—‡‹ÔÆvIRô{]\ÛÂlÙ$zâ"¨'3ÑK™ —(DÑ…ÌÓ2k€üý–o J¾!ãðmz&Ò'¢ C×H3]ý×µ—*˜G½Hæ<ii©Q¨Ò¦R´[qQpb[C‰gxü5+?Óœôî)¹$)œ€gÇ^d ÷–Dñ™)·Dó$Å ¬ö˜f&0†âìíPóÊÝûëZ$KÄa0F“ksb0Iƒ^Ø?¢ôBçAnÈJçîè}Ô3½2lî˜ïöšX>s‡Ïo…ZΧÏ^Ð¥Æg?g¯eM^»4%z_sŽš:Óƒ<ç‘öÇÏ “o¥¦”¤¤ªAÆ?ÒžÕO`J?a¬ììOâsÒÔ ¦ã0e¿*‚–¶²S-‰ÏIûÖOXÄ?Œ4 õÊ`\Û¼{ߦÇI“ ¢ÓOÈeÇ}Âש‹ôêë¨ £€u¼þ|È@1Ò®þÁÈáÓgKŸRê‹Åèç)Åbº€ºdâxVêŽr¸#%+sЫØGCòd’‹Ø sóyºÃjSj¸Îß»­`F(ñL©OÙñ®$ã›RÿóGó—T¿^i…2:vóYÚ"Ð$Iå2óƒÒÒÝ{t‘¢©æ6) ïYËN@ß1ñY§­õ Jñ뺵.†Ü¿îÌtEtåÉ]»^ºšÁ;JoôRħçÊßξJ4{äû¢d(ÇÏÅÏÞ5ú|FÖWÒIÅê ­ ÇÈúj f*5ÏïÔ‡êԇ÷ùz܉ Š$ âétRT–áłϋÙIñž`õ~yÒØ~ÌÒÆ°‚õóõ{M&IÂÌݽÿ^دéañuvù¼@`® „øK_œâ«ƒ$Þcûœ©Šzí‘×óNU”“Žàc>¿[‚òìÇLGh&8¶Ï©Zgž=¾Rëä.ñØ>ªT\•†íOÈÐ "¼€ué]ší¬b ?&÷ ‰Ž™eŽqÞò]ì‡xÄ”QÜ \<©Ÿ=:T•Ú1¼Íø/jǾâke¼Î¿^wšKâuBÑîõº,ÅÉÌ”ygOîÖ%‘o»§ä Õ ÒCŒ7 [hQì6ß|¥_¦j˜r1`ä/Êa[SüÞ¦}˜ƒc>Ob‘¿gYÇ!fð¨6ÐÐèGlÃÕ>¬î·ôFÃA™ª“ÛcJº$DkÕFZäİðœö¬Ý>{äÑw ’vå1dŸ&¸Î}Gê½W¥Ødêdgg_y>|áÖÏäç~ø"D^_¸¬Gô9¾o¿CÈ|…+-k(Ò²U,Ÿð½;¢O` 96[¶5ŒäËÛLÎ%ÞÑ"r37VüÜ_ôÁuêá ¹ª5±ÑÃ5¡‹ûÍ'?ápÛ‹qY7yœP‚ü!ÜÅò$¿wC¸Í>@ùÙ'Ö3#ñÈCr`6+íÀ,“NÝSA ŽÑõÀlq dŒm¸T»žO´éÛ¶Ÿòu2…š5Ò;¦PGr”­FÑ6k]tâ'ƒið<µ[š|žçù KõSÒ¹¡|JõxŒåü­ Ðäw$¾ºÖ%#ù´ñ’¬3¨XÄŸ%_¤>;ðrÓØ—}²Ñi:ŒŒý©jAŠCÅê¹gÔ=%»îRÿþÊiR±g¤K\;,Ë‚ïÈóƒ1t qïýÖ®MM „L]XÕ†,Ø-9͸kÛ&Q+Z$³HŠ¿hìŔгenvàcƒºjUäÓ\÷YœxéY ÚzSyP±D»{Üï!™EÎùºR‚˜@ "Iî• œ­n’øuÚËV×"H^w–­“³lM,öªÇˆtvbǼtœ=Tá³ðd©xSÏÇÈ_`2+¨ºw™™Î“«±xæ™RÖD ž¶Ú˜‘L²#Ù„Œ;Q%ÄŠ¨ÖËâÞ;Œü(&–ÔÁ3ù&ég˧„Ì“V£`ˆÐOUí};ZäûôÉ·ZÍr:&NÅ6úìbg²ÀKz•IQi1*3)û<¯I6ŒHõ­¥+SôYiÿ»]&ý½õ:D¤ž-!òdÔ«·>– ˆÅ'¾dùÏ2òoáy’x,KŽi(Û!ã³T|.Bäil£5i¡–žÞ5¢iëe=éó´yØÂ³«¢ï h”JŒßàBæšÖ Œ*¤Q¨ Uà 5tCŽ~Cȧkô™üÄ [ñ¾£ÔV…ƾ1wY¤7Ž—FÞøŒeµ0–5Á~”ºaUK²š ™{:2ŒLÎŒ—ED}ÌÞ;Š\óðß?V7¡Õ&´=ÆßÑÛVÌ|?‘¾ò~€,2QÅLÇŸ†°Å»^j äï7¹j*dË:cQ§q02é:Móá»q&éµÞ©ªœ¸.†s0ü^ËÄ꽸&|Š6Ut¡óM{wíúGi0°©äªr؈øs£iD,¢øËyfñ«+1"äÓîÊDs®²|o@—Õ #§IeJ9V"dâe‹±§j¨7X­—õÃÇ|}[¦Ò‰7â½Ê!j šgò˜4'óL!¦õpÿ©o³ º»,r®®;xUMG€“KÈqv³‚19CÞ9òŸA>/4“3',‘¤ï B†@ ÀóN'žOÈ`Òo­û1F¢ŽCe\€:±}”%ÄKïŸ/B†g¶Ñ‰dAÈKBmÒäýsMÈ%±é»¯/bÚáë  1mýiÎð1O R{b ó}=tãîèqæ+«q§Œ:‹—Äwù;±xYÜàÉû÷z`sZ›©„_È;ìEÊú§V“\3ú»ÞDàJ'¥ùME‚e+ÏgîÞf„vm©ýa!¥9ôLÁF ŸVóÓÂk†}“eó(j@FK;H«’±½´Èø[·«5O©¡"7„¬Ü£Uô";²Á·éѪÂxéè–a¥îä£êR²=¾vŸÔ¬Þžþv¨ðuì…s3È×¥y»{;Á×°•ThwëüÛSçûZrÆ8žñŒôm»Yd^Z¤¼ÎšMÓŽ¯3g6åÒk¯³‘âë|AMÔÊ#›bâ9>{‚ô°ò˜F¨D½}£#ߤ=e;Y~åLѼÄïwÃF’–š­cÇðubM(µÐJè²­«H¤1ôáÏèûmÞ>lö*xŸ¿ÞvlœrÅQ·vj7÷$Ù—ØÌ¼ì«u¦sÍð“zDßËëÌy¿ˆ¤n+ Kïv~®––gpMIæ¡¥Q1F9oÍ.–e·y¦XÖO‹zÈe¬«ª#?X‹}#ŃKÚÑ´ø:=‘±ÚLTËë<v´ B‚`D® ÿê§7LëPy…Ïžø¢ÑÚ>^ú€ŒSåÊfŽyhÂUct/ª<[Ý'âØ2T×!›’{Ä;-²ÉêÓØ'ÿƒô¥Í.ϳqIpPÃ×~Êö}n[/RšºÀ÷ô¸ Fd“£û&ïkíG†"ëÔ'4†‘õ "ë!ÏÕAEd}ÀŠ›:×Ì|i1b³ŸôηõNSŸ$yª­WÂÙŸÁD‰ÕÁ£^êyLžëàÙO)ýy†'çtˆÔíRÏcòBÝŽ"d|©n7dùú–¬cd]úƒÕÊ¿ë>fz#X7#äûR¯n®1ÒZei¦‹N”µ©g6‘z¬S+Õ®oIr8Ž)ËÒ9:AVúUl=dÛ<‰t–!äïÉלmxõ3EÈçùF/"Qà§?¯6¼é§y1\*\Bág—\ ÚIaV*)B^µ¹Jp‘Í+ÇM•ãÒÀ¿0ÐÕó,9ÒÇÏ ;!ó¬ÒÇãVoÁ¡ô?cs«0˜LU¹ð¥\-òùTa°@f\f?BzÚ'MÈ–6EÑù¼69·å¸ôÝšœÓ~uŽ5uarN1òy2¢#%†½Ôwû;Ñ! !OÆE¤ŒÆÓÇÕø±@¢ñãôq5~,¾M4~œzf¡öáGkÂÙ“‹aHµ€vÓvÀ1ÓË‚í¡ù !¿)ª.¾£ò˜òÆø‰`äµñ´Y 2>:’÷y nY†­lƒFÊźXC|†Ó™Ú+ƒc‹ÕmŽù‹ø_bus€¼–›àmÞÚNÉ@ä€cFˆÕç›IeÓçÃ`l2ýÒi^–Ç´Ð"ߤÇl³ŒÆ±›«nq–1)2“ FELKwGñ•‚é$…ÂKú{“$jË-@&±Üb3Bž©\Xç}6Ò·Èï´U= ߘóê¶2eÌ@(Búmkņ7Å•‚á³A>=~¿©,Ó\69³É*D$DÿZó’Áh΋œ›"FêÙ9Ù±¾ªÍ¾Oݸ!¤núˆP]7’m["’´O¡êóñ=ÐbmKÉf“Ùô‰ÕFë°äêIí £a F>O‘<›¿Bª’¾Bæ3£Û!ÿ+î²,—åP„|}Q‰te+óÁ­`‰lÆu.+É#c[õœ#¤É|þh=Z5ØÀ>e{¥˜ñ1ß¾÷­ÖKÇ<–²J|Lç–ª#eS´_ËÞ.aÏßpKð‘ë:HWïPÑs.µf›˜\–4my“çP±Ò\¦Ž©{$+;ÊŒpŒDŒ”Ú¤ñ"$á…àÆ'—.¬·“õø:cÔ³7•ú%§Çg«s„|yÛaeóè~t·Ü<Ÿ¨R_TöãÜÆ²Üh±÷3B¦>R »M«xýó¾×ù¶[feÐâÈHðä}ïmgJFÒOÍ,ÒÎCH.N‘ËÖ43íò:8ꯧ=bÔ½D4ð9JBªC] ¥Öaƒt»(•xî\¦©•ÞéäÐ¥)ð+}Ä—!£ÛæŸ×!#!ãìBÆçmÈHf˜Ù5ÈçŶÄß[ú Ù&Mm+¼¹øE­ý Ïôp ¼\¶£ÓâV‡ºûµArZw Œšz<´ïº-e;VdtîOFxç=Ogf‹¥&Yöuí‚gX9ýª±2ý[uAÈ“+ j¬yWc¥yWcÅǼ«±âcÞÕXg„¼«±bäI•5Vƒ<©±Ò ÆjŸüI•5V ½«±ïó¤ÆJƒ«…ÞÕXñ3½­±ÂQß«±y]c= ¯y¾ÿVcÅǼ«±R„¼«±âcÞÕXñužÔXiPcMòªÆŠ¯ó¦ÆzTøÉŸÔXiPcµÐ»+¾ÒÇ…(‚ ïa¼Ù]5ƒTé%¯]—Œ.RÌþH¢`ÖTþH¬óY[’ŒW3B‚4lbBÆ3ñíÇÍ AüÞ¨º¨‚g¶f°6G¯Ÿø¯aéÊë§¹û©Zñu:‡6¹6·Úµ³,ב˜¥A¾<ñ{-h#y Íç¼ÆÇLR}ö Y{ï(õ?3'&>‚6sw ä#[íå&$íí“ÿñ¡Fþ^´¦EôáuSµ0–J+;ƚњX¨7øWjM{"3Ð}=ŠrÀPgón‡±Ûq›šwl~%ž>Tmˆìò•ælÉûà¶<¨R×YÕµvÇQnC_h4¶1¯j-RÕ†&0®T®åQ?"¿jŠ¢z õ¬YÊFç8âfFòr(1ÔÌý±Zýò‹bY;Súaø¶~z»d\"†ž—1³Œ;ÑÄô’×,g‡ênƒ –4ú æ9Eìhœ…ÉBéq¸c>Ãλ6Mç}™é÷4Š.™\M×ÕSQitÊPOzVQ|Lp©ó"‘¸ñŒ»|(ŠQñÇ8ê>Ô.÷Ç#¯\VÏK=²CJ¨F²‚gÏ¿óÌ5#>{|^Pâ|®_êóšO§8 Ž’¿Lq@†%™â€,ÇóÅÄSâ­£)ŽÔùbÚ©WoBä£4ø-9Ïܩٻ¡pïýyyeefÆÆ®›Ž5“ú\iÍþ6›¸ÌZʽ.Ý/Ä 6dÑ ÒOnZš–ã³G^¿Š˜©×eZÅufCHÏa»%D¬#¬Þs|†¬"=ã&½ÑÚÔ>fb¡óʾM’Ub?r² ¤ž\:”á‰1÷XÛÎë\Zf‡A¾¯”.œC^]R=‹%¿¸mlêåî¡iè Š¼ô(s^zé·'¨9&ËåðÎä2¡oOP<½®œià ê\÷F&VèbíKêñ¯Ïfr8L&§ñO¨tá1ß;o&'.…ñLNêy‚ÚŒMi;J.>v`@§SÛ¸ˆ”zŒ·”ü—©Í¦!/„WE^ EÔø'?õïS7wÄ=Íقω€)¢šþ4'dö ÒÅNUmEèIOÚ9{|/䥧"å¥7̳{ïäÆjVZÅ'Êó|ÍzŽ‘©×xÁHñÛïæ%xJo´i v±Ÿ¾ ®ÓÄNŠvUL6ñbhÖ•/éáϤ7•¨¥bc€ÆEìÇNÿÁÓ3KX»MÃÐç9s•/»k@Æì”öÕq½À8Uæ"Új“,kUM è:¥ñ÷&¯fÄCeÃ<¸p ö‰J¶™®}›ú•³.³µiü †Í퀰ԆÛÅÎ\•] ÚO dcÒ8º–öÉTG®3¾på$GÓ?!CLbC†4(¾ñiËH6{×™\ ÌóÐm UšÆ7ýI âÁu¦w$ƒŠƒÚ]§ÁÂ\C¹0ç «©-jÄï¯ Y»ÇâÓùΊ¿~Á×Ê]4"bíÆ#Ÿ§ ¤™T uÈëó*–”ü}Nu/2õ”„Œ½!YSöšêiÌ÷fØ:„èÜêb´d)óÀª•#dâzª&’eÄ#¯Ë1¯2õº¯6Hbo›ýc4¾xI.ÅKF·}½qY¹ »âmã´òC¡ˆ¬ÎoŠTùPdåÈñ5EäŒ,µ‰ÁóŽ×›¸ }ú^"švY›²ÉÅ»ß @ÊX٥Ʌ|m²²£d·  ¨¼¯TÍ^ölÄЗãnØþOÝu>¯¿*®ý‡B7²HGóf ~S&] …z%”¥R§æÛõ˜JÓ^ÙýÚøÉÿø=h=èmÚàæMjiâLC¡Ë¶NeŸýãÔ÷²ÊøØ‹ÄBŸÈ¤R}Ÿò®ò¥_;|WèÄ{’”å,½'g ¿}"eýZùDÐ×¥O¤KC Ô5n+£ÎCDvÙ÷|®ÜoÿŽM%=ú@Èßk*s†ù¼¤»Yé$ºñÙ¡ËÅ’ø. á†{¤—aÉ"qxf¤×û?aW¶ì(®É6<ÎûtÄO1›dˆ5æë¯Ö’J¦ãç×I3†²/‡œåÈWý­™Í…au«·C©Ì —…ÿ:¤áòQzcÛ"d(hèF©/täÖ¯`ÿþÛúÍË(Öw3²iFÈG8öl?ÏQšcdÄ6µS-#À Œ4=*_4•vù77Û´ÑmÍB¾Bw$Ûf2cGùÒú(©7T=+Òm‹5'´2óté˜`®×^þnü;í:M­+SâLð)e‘-š‡hÜk{ìMHF5y¼Ô«Ïj_Ù ½W¾ £^Ö-£Z“•ztz=°›­öxNÓkdK€”VWþ—>½Æ 0Å^}@Þν¨}öÞÎ-lAõ<=Tì°¶~O÷íåÌ$÷60PjICóà¿ÿ„ŠÅc9ÔeýùÂý 6…õ¡£šÉ©V™zÊ<„#ä xT…cGÉ„ ³ŒÞW„¼‡<*sE%ã8Ö01g‘›±¢l)Ù· #OùQ‰N—ÄÜ4+™ »•&(¯Ôª–ò”¯DÞ,è§§ bIH¤ÕÕ“Ï}.çªhs„Lwu[EG…` ìÐVË[µg¯º|˜}€™&8¯´Lsún#ÅÜ|0ô@ëÒAF¾³òI\v«€Ôu2j¿ÑQï¿n»tª‰2á'jóÊÿé´¶Àßá³LóÿÖäH¸ò)`ú<ÑWêG^Òg¤UNVêž!¼'¯_Ž€ë®Btoÿ…¾N&+eðó¾¯M¥-ÃákJ‘æ¨ùšjøš6S œñ׿ÿƒúY½jršLÎ4~ógH×Ò3y XËs5lÉi™¢f³S„¯íÍÄÛ¯Ò–~çN+qó&?_PL¦?B¦þÎ2p–qmʼnS­K“iPˆ¯Ô^3å¤áPÝ¥Ô‘åC·½b>Ml|E™’¨Œ\ ÒÙ•ù’ŒÇf|ç/‡bJ>÷Ï.çbJ¾Ü™]N¤D‡ZøOvV–-•+°@ÈÃ(\†÷ !ï(bÖWo"æoUùìú#ŸkJi*^ßVÚpü;û†0bæ*bÆÇ|EÌ›ïEe×_ñIºíUu Ÿ=ݘó% ±d×gÚP\:Ín§âÒƒ/#†ò&VÅ‘C”‹WÕ3”7Ñሣj±²õ¹v?–ËV­>t½ õªßºÚRYûñÈägÎËYl¨Ö?óð@ŠÄÍy9—¹a|/â!ýæ;¯r}vþi£³?‰0sLÅÇ£cGüûH‘XZ·¥N1§áÓùïÈoÞ4ͽgµà«LÒ9B¾Ü”Ü]RH¹€ >fêäõè‚©³—õL|EYÈ„sÒ‚B†l¤ðÙÍæUqÕ­—[òëwæ7ï}œàûxžôj)›Å€‘·CS_I NþQ^•ÈŒªl¾ ³¦DÉ ±¶÷*XE)oBˆ‚òc¶ ™Ñ-ùêƒÛ,”’úñ“‹_³S1ûÌ+Ò,â}±½ ´-² ö®“)ª¦|ÔµÌx+6òw^"ä-¬á™ Q5¡úw5»û™].ˆ'ÔðV&×ï lX,òqh®RD¿3ù-¡}{UB+@3Ä"Ÿ¡ Qß5-º!ú¯#Ù+àß™¶,U„Ìüv\‰J<ÕëÒ»ÐÚÝùËo¥Íx»0(÷8èõÈýsûø;z=²«ù*³coW“]n1Ó]ýHXhWc‘Gú EÞé’ ‹–y1Œ»Ú·Û2s8æãÌRHß)BÞŽG¢8\Qr:ÅÆU äÉHÃÈûÁîèd— åÁrvy:Åo0•EŠ ‘£hPéÊ~½†£J—Û“²ÀkàýTTñdáìq¨²*]urQñïRQZÄ^?ÕC;ÒÒ¿Ÿr’%ç«.Ÿú¦ˆÇòf$ Ô>Óy ›#d²—$i+)ÿ†\éDÙBøç~½Ä‚žÞæmXÔ𳻟×3ûŠ–s°šÈ®§þ†ÛF·#Ã-î×ÚëýÀúÈ8É~k|]wÜÄôÙõqf1¢DWÝ;MNó„ ÆE³À™÷×bdì6z˼rįňù69BÞ{®P<ËB=ˆ½žëï¼÷ÛÕù~ÐI¥2á»o[#¤)"àî¬:Þ$¡ùpwI!´¢èËqÑ£,T£øë°Œ,}¿>ß!½«¦Ú¶´j5SÑ»Úrv=µÔfj]‚ß™­KÅæW›kvbâµ zÙírl§M¼à­»]ÿÃ2Ð#³ÛñwTDžö£Û¯6Vùˆw.G ¯™ŠÀ''b›yåˆÈ”B¹òt-×!‹‘Om¦é¹â¼á.=ãË)’.-åBrGŠZi™†RÔY¨ñ¯>5Å]ݙΧÙßÏ42VÔ…×o–@„¼¡~³Î·u¿Yf’³@Hœ%†„¦÷±ÎKI:Ša6U€¾ÆGÍ¬Ôø˜Iˆ¬’t¼kíØ"Ÿ@rùh~²Š+ÙÜvLØ o~LÕJûhqݾ$>fúkK&‘%™êŠ7™¹–‚éLëwAçfž¡¥àîüF­H¾"ÃäMCˆˆz½çù].ÔâpD(ý”¦üÛ~·¸|& Ô0ö¬‚ˆìî—3« ¥'ò\Å€Bo‘`ÆêMý&3ác–{8h°c~ÔPü;ŸÁ€‰U÷Ö×^Ñ:ú¯_¹:fŽ¥‘E¦G–F‹Uï— 3ºciECwç/ñL—nžó•®ï ×“™®Um !wÕ¨åιµ¿M^^d—ù¾hÙý„ùˆ|Ѳû‰O禄¸!l¸ßÏÜd²9Òý;Y«áËa ½ãâ‘N®¬OKh¹TGÈ›+ èr˜)*o›­\ýKÿJB¦ e5ó”·MñõÆý½mLÇÐOÕBÅŒ§÷<€ån¢_xçÃïPc–SXÞŸ§%õe¨± çšœ³£6ªwWõ¿~œ2k§C"³¾B|1ò¶ï#;l ¸Ù==¦# $ñ {Ž·Î Ÿ=9Þ:aù¦²ÿ¨¾ÇÛM{ö2ßíÊ ÄY³`*{“Î~²ÉÂÖLeïo²°|‡SÙû›ltЃ’Ì »ìîmŠæ|Ãb\¯½†ý;r?(ÞPë5!aŽòm•ôÖÙÊÈf‡-òî‘•_ŸÆ¡¯Þl„·þቮ+Y‚˲ˆ!Bb7ƒTn,¹\p(B>‹LÜz"GÇŒ:^f]”:ctíGŸŠUÑ1³C÷dPªwwþ²ÏÓSM}œ[uú:O0äük¢V稧eäÄDM;F˜¨2­€¸á‘DÙNx‡jᦅXäq*¼#£ ¨uæ}WÈ‘²GvÌ‹T_&p¬³är&‡L¨Ï¸“ëQ§1ý`¨¬&XRÄØ¾š÷S†‘÷ÀhÙõƒ k<>û>j«ƒb–ļml:«òs‡¼Ÿ™Î ‡Y0m¹k:ËkŒÜ'ˆÓYƒ‘Õ‚c>þ£;ä¯×Éó'¦ÄW¼ùSÌebó'$”ÂR›„æ:¡¥“|àŠ+âkÚIrb¢žÔ´“çu 7Ö)>›J^QÈT:‚µ²¦¨Æå+òæyj]²â~”•}½ŒäujK¬Ö1„ ¤µ?nŸ)õÉañï<²Nò3fù²qd†´Ÿ#?LSZ p½ˆÈÿmòéËfE Š#dR£Q !_È3Çhq©c Þö3B¦N÷‚Àò­(}ÇÁeÚ"3çĨF‹H!µÚ,øÎ_B¨±’UÐvø¼»zýÕÄQÄŽ® –¦g0΢ÂÿÄ e\»Ê¦‡rÃóðªxdç¦k6MBTû”žI¬~púåï-`BÍžäÒ©‚n[+ªpžIœôÚ4e.E»TÕ<àcÝÍT¯±r N]uB®÷þµOeÜÈ`|í:Q{ä±³ÒIù)¼Ì¯ccO5°ì×ågz>°<øc½Û]º¸¿öì”.^ÏþóÌþƒ.˲ŸÞû}îßIpÿÜÙ<[¶«œõ– ìª ®(0šÖt"àRÉkÕ2‚ºvæ¦wúC¤:ñÙò¿º7–[>š¦Èù¾îi¾n'ÏhS¥+¸¢ûI«&ÜGÀ¯Ç‰bwh ½’ócúçþzÆ}A'4Ìd²¿Èüމ'^tÜ`¨Å[=Õ˺@´úzE&]ê™ùN^Ò‰Ï#ƒ^NY9n|å¼Àî­_w™"ÌgSÁÍÎ|§²Úƒ³gÑÜdUš‰ÄL>”ø` ÅV{ñj#Àt×"C¹‚ªED~lC7Ž2fDÈû¯°–ê·…ÂZYz=å¬0L‘¥·óPÄ¿uÁ0Eüʼn }qéý?VZˆ€‘ý©]i #RÞÏ–zö¢E}ÉÚ…œô~°Òr·Ò „Lö½;´~ œ=bƒÊÀׄ꺜ßtìüٓòr¯ÚÁ>‹N“¨À¦®ÝíÚ÷{¤þw&ÝñO™^t$B>Âb˜“hªnúˆèìÉ7k«”Y=|GÁ(Ço1ì-?ÐèÚ_®Tmrk²Ý‚oÑ1Ó@U,éû-¦wÓ dæªC÷2M_ªù'P]L³Ó°Í×d¢ÑPJoTRzžÚ¯î9Á|aç íWÿ˜Y‚ÂÚ^É•akhxyûUW…Õnx A@ óö«{þ.êCZ2Ù•ã”H T;ä5ôi ãÂ3Ö gùŸG†-´8`m5¨äG?ŒÐäÍn?¬3%?¤qí„ÜÆòÄ‹E{‡@–=NÇ¡´qæÙüúìz—3¹O-är×Á(^–=wâJ»Ë·3ç4GÈÛŽ§ÑÊú•®ß óØÕÛ§©˜ÅãÚÒùØ-K(ï%³d¯(ùVÚVŒ­hÇâ ÷3ÝAj füNFò6«åÖ313ùs¿yøV+«É 2WýåÐ5ñ/h¢Õæwòví!¶ ]­yKO•M1m3B>Qã¸4–™UNòyjñ1_^¥¬²ÚxÓØn„™ú¹7G¡~g®°BfÁRkƉ5’–õçÍñ¿øá ݿԮÅ8 ­ÏÍ×D=¡¡•¹& ýŒFG½yñ­ÂðF›yi ¥å§Ø0ËÛ˜ÙÂbÒ Û‚¡@Ô&Ÿ¶-H™ûÜB“p¸ÑÌSËï3_6¹…á§oU!œ×ž¾®/Ù¦÷2–ytY¯_èD¾5]Þ¼Š i5•KUºœ–wU円fjÁ­ôQåÞ´äUôö_ Ìé@ê²DKåRcèÕAßZ6¨6¿U9K%~·›#qâG@û†Ìøe½é§õÏßúp_ÛϷɾ¬Û#ÞÈÓ.Q”èƒú-oùçFîB³€¶² O~˲3Ó&²ºJNz †?~”[û½C4(iJiyР¤ªA¹"äã  ·{»5Kd¬µ ³Ú«¼îulê/‘·¨¡L!7]¹¶Dá· ]³ÜÈúϰ8Ò£DÞÅ€jR¯É!&ÚkÆ”ÈÇY”9@MÔ!}ªç­ÔÅ9©_©õ&—ÈäGÒ‰¼ÝX-t¥é)ëÅÇ& ý _„hBÞ½Ée] %Jª¬@ý3òÉSL®mzÑ~Ê•Ž5CÈä0¡wÍ/‰|—=6yOƒ·î\TKÔ5\û©¨“6‡ÜÕRV ¨–CîˆjId(ªå°Æ\˜ÙóAéJ]Ý;dDÍTÈ ¬éê !ƒ>€&«¥qœËu”¯5CÈ{Ø0'—ÛèÚ©ŸZ"ä#@ÖffS"ߢÇ7F&!Òìbê˜ë¨þò‰‘Vð¿[Ç÷Rbä !Ýï”)-g>{"›Ò"óqÌ»#oë6PÖ¦ãyÇýw”E„KE 0±ߪ®[yA¯á×iv0õu–Š AÃÙz•I¨LÂrþÆ—x3¨í!òì9[#èCÕÒ(¡9Ï9Ïs ¨±…ío(e'^öÕF04H {·äÍ’‘^QŒ-†Þ %x3¾U¡òa-ªNóOaõkëF Ö}÷)†f´Ö>:ÌÓ¼æ9¾¯j»_T#êŸìál%âËóQDЫ‚*§Ý9н &72‘j}c葵›\-ßîã¿âÖ^®e°ŒJaO¾Œ´pU×Klëì ۨܛ¸ÀHdíViåG%Á>öƒêz"Á>ÒqhCÈ$@‚ÚmUÊh³…e÷0£ÕRþvKù ¯h¥\Ôø˜/ßùvHþ.)‘¯ÅW”îɺw|É ‰ÎÈ”•“ŸYU‘~ñ¿8 0­¹¨¡jÂWf·ã=¤cÖ–ë±Hèõœµå°yÌÚŠ‘‡¬­a9BE÷AÑõ¸#a5àì÷óÙ+'ãá3Ód£Á=¸Ts3†ÚÿÎ$êHT¥Vx2¨¬p|‡D߇TâŒÉ”ðóñïH‚HoŠÕ6ñ«KvxSJ0œ!ä>7cP#H#>æsŸq±…÷šxnÆãÊd™î1.Týgså<‡4øª³õfÞ|·Ufíâúù8{E¹•Z©e#šÙU‘òov*³¦±â´ÆHÄm+Ü*’s6o%<ÍÐYùv ³ÒA+ݪOGòtì¥<æ»ïX Ëõ«Ô×f¤ªëi]k1âc>B£×ÿ¬:eèïÒëÀâÅLËÐ Âûpæ.žkKå"Ï=;r‘Ïù0*fŠû³2v‘Ÿ+íOÎàÛ¼ùÝì‹&¬ä×Qudè7†y7Ruç?@ÉÙô?øŽn¾ê¸Cí–âc&~†±ÐÑ›Avʬ#Ÿæ~ª*™ºŸ•že“{ç“t‰ÝpµmeœkùFÖŠÂÓ¼á´.‡^e_·M_­¼æ‰÷m½«Êð´}FX烉¿¿t–îjUœŠzé8BÞÅôÒMeXõÒ ÝøvÇ–‹ ¸¡ÎN·o7Q„|„sLÝKçó,ðÙKV7ˆ¡Tfhù-`‡¿Ý‘Cž¥¡©ú$›[&mñÙ-Ùú%{è;?R·dÅgO÷<×)aýÔ|Ì 6cÍ_1go[¹)Ð#­CÞÞrÓmø’®GÉ÷óÍú8íkV=¬µ·#KRÇŒæpú'ZÃû’¼dFý0ò® Özn”Hº¾ý[¬ ˆmÍ-ÛÚψWèØÖܲ­!j¸=ý×ùc…£ÙÖø˜Ï}æ©f[¯ù:n™AòÎþFLËPC)Åû‰ïEL}íú6y1uÀtqHŸÉ#&Yª?2ªÿâ_-³/n™9d`v»Ž²drBðÙwôšf5#V mô;Ó“F>{`ÿä¼;Õ~È˯ßc£yÜ·vZÐŒ‡õÿ„]IÒ£¼¼Ò‡§eï»#úÄRôéŸÆ’ ÿ>RM™Ù-™Ò€Jò¶› ©í5S¹;Í(eÙ×l€^ 3„ ¤ «Eª¯9¶+iÒ›©ÉŒÊÜç”gd©¾Ïg@;³åk!Ú±ÝúyÄ×|…Ñ¢)Œ©IÞn-3‚ŸèíK)NFM®sí×çÞÈ,+œbÒÜ7¼FŒ´]£Î([g)<·VâÏíÐÈì §œçØîÆI•†<eß¹¬;$zZJ‘å)5Y¾4$Ü}Þwä£ ¦|x¾N[ŸC¤ìI™›Ü”U"_›L^ „ÉOcžñ5±5›U¼ÈW¹IŒpôM«jO#c• m5 ɘV>~ƒ÷S•àÍ…8*ºÜl|=ÌSW]T—œcä}Gƒ¶ó”¤/”9ãd£5ÙKkZ§[P†PLíÚ/µi¿ÌëT»'Š#$ªk´é´.C:ˆ luUéd¥™LvM™ƒ­I¡„Çð5ï>®¬ +ÏÖšÏMf‡ìRÜå(f8€ukBZº  Æ©ÑPûg[µeÁ(äR@]5…Hã>ªþÍ¢!]·Ü¿Ïè<^R>ìŸ!וu_%ª2_ßiö˜ÍFç(¢L’iJf„ %P3«J–™ç¤‚RXHÝW!•N/÷÷yGŽ_Þ ¡oútì8é02ÈQœErß0Q·¤HòÚ¹*$ÝxÓæßç ç| ¹®Y¶¦|ë0ò" ½xjåæ(¿Í¿Ï;¹:ZIÓÀžß±ãWj¦¢åû\+e0Øó ?¼wüJ¥©|¥m+O±¤IŠÝUo^ÎTÀ5¤å2M±6{õ¶ð¶ß\ÖÙBMSÞ쮃xáʰ2ÍK>—éî^ϪÊ VT|5k®„<BÞŽL¼ä " uíøq*P1Ë\¶ÊýÚ;Ó]S.ÊDm=BÞÑn¯+gBd“{8ìöñó|·§½Dúgî¦~å­éÚÕReB"·#ï½UÕ­Ø´–ÓÌ ?‘Míþ¡*(žçj s½ õI'¡óõÚØD©¸%MfiÅÅ,—HÕÍøuÅFP’pÍ÷Hnøû|_´»;‰¼Ô‹ª§à‰>'kɘ¾ÊZߢµD•Õ¸ZK ! ¬ÕZâ<ûãçTÆMfKdtÑÀ—_‡¯‡…<×oÕ·¹÷çÂãT­jVw?‘·½…måÉ3ºA/ñqßÏÁ™>šbdV")È:÷KQpI‘Èøšãësóiúí)2M}ƒ‘÷…dA&ÿoÆ– ª";ÃãqÎÐL}¨rLÓ#Ýãªò¿þü^ŸB冓%òuªN§8¾`XègJµ$èM! å_Äîh(M2{òÎ+ÔtÑϵ,Å5ËW¨ï_.tR&ÅØ#äÝ×ÍtÍRëæo%ÝHû<ò ÝÍÒΔ‘¶ÁÈÇrZ¡Ê´ó ÕÏ^ÙŠ~B—féñ³¿ Ÿ`ÄŒõÔ­(•±e¯˜¨ƒÓMNT}ßçVr–×:¹ƒ V¹LZüæmWRý|aG"úNµdSNðE#à‘,³þ¼r_¤¼&d™1ô†ÇêT½#—ŸWLüPÑýøKSSÁøÀózæ¹Zá yF§»-oø0å FÞ_,˜¸.SÚ´­ÿõh?]f®j™Ò~› ï}Fgó´”(á Ÿû=£“á"-B5ÌQ'.RÄiX%Ïûù>¢xZ>£{Æç²E£’-‚êÀ3Q¼Ñbň Cö|Ç#æÙ4W0¤÷|"¢­ïS¨¾ €Ý!ô ôR=Á.+·2òvȬ'™\$íŒw,má°Z*’— ƒêÀóµ¯Z¾šƒ(=ß!GÕÀzì6>ç!ŸÁJÎ Çë—['š!_²„n£ŒÁi=àû|ûnca­*õðÛ|ýýùBªèƧÄTFDÓåbØ6üæÄ!ÏN8_,9[ó?’Í+Lެ.Yh‰¡2”*%†Þš×³€mÔBïØÈ×Ìú­LY‰Ÿß ýûë¼gl#‘eµŠÝc=Žzâ¨ìîõyh Å*ÑñÔ•9Ÿ‡Ç)EÊlvÓ]O<-—hƒ±7cFzâ·§oitS:]U:R¿é`kl]h4YU"W~zaHõ‰ê0œ¬óÀKh}=?X˜Ò ̨Tu[I9°r÷ëÏ kIXÕ\mk6¶!äËæƒ®Ù¼¬í@´¥_?û ÀÎꩆxÙŒÎyÇ!SòÌ* *¸„¼‡¶à¶¸>“®,Xeø—UR̶խÔÊJ2–‚ó²AHý–¸¾O;+¤…Ù[y—0Ôöò£JÎäÌ™§ÏÉ´M|k2qt’2Qr{aà Ì?÷DN¹-³dµDN‰¼IÃLˆ©&‘÷K¦óƒRÞÒsOq™úQlà6%‘1šd ˆ+lœÒ†6^ñi¢¦%W|Ûí‚h<›´ûb°.sêЩ¤CÓRèᾞ;É'Ýß³$i’É­¯½’ i+è“nbÍ¡àR’½æ YÉ´ê„“ÙwÈû)RŒfnÖ§EsÚú7ÿ:¡`éf%÷ù>—*VÔ&?\âÉË'V…z"ò2¶ÀÐþþ¹_³oö¾£½ V@sÞRF¹ûâÞaØt4Þ;ØÎµ-µ-\¹3èâHAIdü-Ço 3Õ”ó¹¶!oAIÒ.‘^ýGÉêžïø\Ž_ÍŽû2Æûq^Q~Ž>¸ôÌT½3-T½'+Â|¥µ+E{fê!QM~Å !’µûŠ·;ýû|í X¼~ ÞÒûÜÞ çÅ\Àiø~_Ú4>™~_ˆƒQ@~N UÊýèU@¹Äf20&Õ#äí»í¶ôÝ$:kÞS.e$d¦œ­mÑ’±âYƒ¯yÐLS®¨ÃÒ»û||‹õª&–TŒ¤~‚ÑYÕf‡‚½jŽ¥åZ§pÍhGç+­*»!É4ÂûüD{É*[‰V#¾Xê_3Üë ßS‡¶C™‰‚"d¬«]/?ájë‹!ÅHOEr½ü×Õ$ôTáû4g±^ŸN •j-Ô6âº7¹}Õʈ…±¾,ÒtLñ5ß²Sß2y;Q¥»ª!‡<é­ˆ¿Ïj¦¹5¹+ªÊ!ç=ì!É<‘3[-‹meÕŠ·€\oÊl5ÉR–M²Jl &‘òC­FÚ!d|^¶„VAhœuÄøò¥»O|Íøòûç'¾d|M¾Ôô µq¡ÔEˆ.<Ñ÷;áŸtÂß#äíXòOPÂZGíGåå~\up‡¤ÜC¤ÿu¿{µó-%¾°ýñ»÷1’ã_ÃýÓ6©™ï‹´‚D: cÓ0‰lr’ þ×}û|)$%-Ë„¼ìɬ×_ÿzìwZ?p'yŸ»_ ÝÈõYAœ°Ög/öȳõ¹ÏÊû|®Ö§Ì8a€òó9—"U3ذ–¢ŸÿÄ„6Eô]$BÚ"ÏV²ð äȳA“ÝjuMtY–´uÏý\•®”颿Ï`È ük5 ât/òîÛ­9”®+q†_‹Œ¿…󕚥J!MÆ÷ËíÉÖì‡Ò¡r2&iN-WeŠŠ•G«Až=¾æëHŒ_žalÛ?û©•âS‹üàÚ….HUt–‘2¯s‡Œ/úô´"I3øµŸ˜ÓŒòglƒïÝ"ïgiÆjò^fûe–îqÈrtb/J/qªèùØŠ–£2oé„OtÆ9>$§u:rŒ|!ædiõÓåÆnFHC{0ì±Üž†ý2q™èOB~ãyÕÄIôó¸ÌÖÞ?û㤙cF= 7úyþ‡Àh‡‘_£Zþ@ ŒÒ!/FEƒ±“hó5°ÜðÆ@,òŒÄBAÅÏ!/F'üD¯3º‹hfüDÇ£\(®4¾æ™À¨LO9¾O'0z¤Ô[Áÿ.Ê12{¯üúú¥^¿1½ÎÕ”C¥^‡ŒQ°¨PÍfhüäUR¿&¯¥\ß#ä©¿V_ù-ìsÙµ÷¯è'-ý>‹Z˜”‘Ë,#`8ºBvåØòŒÀ†~l¹@Èf(8ä¼õ¯·4í+Š·Sõ;Ÿ„Ün×êw>¾Ý.Õ5{~ý~RÖW§­ š Qȳûë4^Mÿœ74íó #ƒ&¢*pêIFV«öõVÀ¯?®´âÔÜûnÏ˹;áOÛÛódînqÑ \ótRKÇxÚxÑíRF’pLŠnï‹9%"ï¯ù¾òÁVÃò̃hòG3ë×o“ÌWÖ±™’vé³ Ì‚M3›ÐÒ&cÍúš $bÁVÙlkEøânaÁE}©û:”Ÿz:d~…sÍ_s|+¹-‘²"Á÷ùØyVh•¾ªÊHßmù ¥C)D%æ<(B¾0WK×Ì«’WZgŒ„³ÉÅê×·­Ÿ3üDŸoïó*mHOzhø¹7ÿã¡°5¨ši£ºăVÛ©‹™ôÙFöW½…R¼f¦LCyEšôî,´R]’ÔÿÓÈg–²u÷?E1p©tV+غ&ÝÝ+$´6›¸„®+‘¶ƒL‚¨ê™ºt¶î芧”¿YU!ä-0L1™ˆBV2™ BØO•#sË›UIS d¼«|X伦4oòT÷A Jº}?e+B>²DjQVuѵ‹`‡7êí'å©Iîz s—ó~‘;$B¾ÒThd`Âê™Ì!?!‰ÎV}h•ñ– ¿%£ÊªLÑtÓÓàS¿vKÞCTx¾J^†V®5VßÜktöf)S¦y¼#¤™tVH&#¸ !ãÐm·„‚[•œu÷è¼}o|£y;/ój SsB£ÊßÖÞÏÌŠ ¢DÝenGö“4ÒXWd›:jå‰CòîÍfæ”ÊîïóÚGU‰Æ×>îïÓÚWŽl>ÛÙt*W7ÛÕk"@±'ÚóMXš9ÒµL‹#oß3ŸjŽtV›c‰÷ï™Oªg>û î3ö[ýß¿þ÷5ž¹ø×^¾µ²ƒkó2aÇ×´[½ÎÖr›­µdÊ“„»†³Eê­þŠ‘–Æ'wÕr¦·Å°Õsãì’»9ù&ÇU ~öÏKÇ3l£8ºtð,(Ž.Œ\åê#fd~ùm®dyÿòÂËmÙ>mx:ÁDtp±¦“åŠké~måóÏuÜ}ïò-Éï½ñ-µÿ#ö%P_1œq|-:ïÛ ×N‘Ê»­GÈs Ÿû];E"xöÇn»´.ຽPM¹àù8×Úh0òBAêhñãZA#kð}†m:—ÿ(5u>€yØ,šeŽØûì+~^xq„’­Qüº”l­‚÷ùBç¶m¥êg§¤/בÁ}¾Qöe­¨5k·&t„µq`6ðç7¬ÚnÈg¢y‡<ÍÞgm7¶ öù8È­1—™1ƒ„@æ¿×£ßv”OËý›Q>Òc¤a$r§=^ÛgWd\¨qǾ2øëß1©HD"Wl…šlì+ƒÊ†Û Õ55R,ÁÈ—WÍí¸¶N– ñ›ÿ ¼“íkÊeö5²±u ¤XÕUkgÈ<,ã 0ô&Ú –¼jW‹rÀS ò™ç†Þ[É«féÌg¾[%ñÉQ·b ‡þ^Ôiþþ²]&ƒÌºR®h”ÇŸÀ¹Æ jû"£æ,¬òuf)šÝ¯¿O»µ~„&þì£"¬ 3Á޶ó¾Ý{oÍ0¸=έ+3´æžýq»rþ"ž=.µ;óÊŸOˆ¿ûí+f¼vŠËN‡<Ž`tE¢ÇyÔk¬äG8Dýûd•„&£Ëޝï‘N½ïª!«Š•MIòvà?•òeðþSy¿¤Ü)­S› ¶Í°–W×ßÜJ í7‡‘S¾eð½/†üõ <Ñçdˆ¥·C,ðu<>çÿQè"÷Žž?{v¢óðrùð½!¶çÔßhçZ½öçU& Fæ Æ LHý Í=צZ—-µ?ï{;ËH–ûÒ–l“ÿ:ÃпƘÃ$j„›¯c$©(0 µUIÛü–Èl̲¥/2•S 9G†ýád ͯ›ÿH •˜àø Cÿi¼‹ó$²v÷ù ‘ÆjD!ÛnjXƒoר3†•5¤ˆz4„„ab$WrZJ6Õy¾{ó?`o™¹ÙýŒÓŒÊcÎÍÄGÏpQÒÙö ¡,hÓ?}ëúäR÷!IdUh-?‡ ĵ~kƒû/ŒU}ªv&„¼¡:«Ö5гhTfa®&êI±aõT§€]ÅiÛõ+BÞPMÔØž©¡µ¹æ5FÞ¿-3µx§.Ñ8¤Oþj0§¦§'áÔ?ÀòvXÈQê ‰_vï *¶¾èòX6ÊXÖãkÞÝ”À$]–ÀĈ¦¥jh¤”“H&W‰ÿ>_&Â6)õÖÕ.OÓ³&%…NÏKû)›0ÉM6¥¬܇ôŠöYõKhדŽ÷ý aÐ Ë1¥¹k–ÕuCJ™Ý@²ø Äeÿ膉ãMÔò¢ëþOØuåÊ­+Á-áD}úÿ°—@%JT¤2îêc“­0†qüUF‰ìTUFÛŒ#)KšÉhuÝ!èì¦ð0W=㼆$ìkýïœeÄÎË °}ßÑ‹NXÌ'fekòÃyï’i,©»$¯}¨á.=\™Ò~Þš&CHr¿G^ÏÄûÅûýu&^øVòΨuϯX}Hýͨ•¢bðûÛ”¿  $ùþ6åŸOpó,òªÜ5~~ýÅIÌL–íæ’éZác>¯EaÐèóócQh¥††²§Æ¢ðmzCÙ cÑò‹±èîì_ŒEa]úüüÃXtwí_ŒEwÈcQÅÖŒEò‹±(|?‰Œœä63§Óâ«‚;ß]\4û,BžªÉ”OT~ãüëîVfôg¿_¦•.ä 9Jè»{ IñÜÓ¤nž8{¢l¥½ [„„EYS…ì+"ïç’´®è‰ÝtAÃ|ªèÊóff#BP;‡ Hµ04s“¬ø˜wTÁƒc²\øŽÒç‰ ’ÒÌN¶ÕÃ,Ÿ~>Aý0ðȵ•[’QÈvx‰ù ‡¬u›ü0•™Òî˜o„t:­ªœTB~0Ò‘Gé”UNéòö üþgå¬@‚ ,r莹>õ(]ê!S I´…Þ@°pGÍJ™É4©ÝAI8¬iÄ.‹afÕ8Œ•K}>{¹s3‰*ËÖ¥âåŠd‡T¯}>Ík—§ GÈP ÏŽ®ù¦ä¥ÚÝ1Ø™ËîÐ’M[Œ‘Ï0ísÕ2¨í³6Ág9ùzô@×>K×®EÈ·Ô]“NT2AʪtÅÇü¸ñè8Õד«‘¾iZÚŒ÷%BFNÇB"•fe¨&|EèÑ«š!Ó~î·b†i5 ½9Î 5þe:Ûø8ÄWz‚oÇ!øç}‚j) ÁÂúŸÿÙ¯Þ„8Sºetcþ1}P:gsY“/s9—ýˆ$|L¹{ñW¹4&þ 艀TPƒl«Ÿýzp˜Ï^»œúj\h¥¬7ïÜ*5O£rÚâ|ûD(õ2&w:tæšó‚'IÎÈ»m[-Y¿LyN¬7Ž?îwF?{a’ÜLàÉ1íiºd.Anûè¶F°BHHi(¤4\&*¹L Ȉn(°6û‚¾KG>úÐ! —ÿ1•k±7¯óVvÝ´;¦ùÿ„È)¡Y-oló¹ü ªÌyUû9ô2öÊwf÷äI5Ï0Á“ñ¢êò‹R™Àg?£X©Ì"Ï«†2Ìú_8)—v:6ø6z·Mãm¥|«†bÈ?Å4[ƒûªTߢçµJuªTߢçW•êÑÓ¿"ˆæ›ÇlÑëºbŠc¶è@¼mD†´oÑûZ± µoÑ˨­ÓHÌëG–Â.л±Šb½SQ¼Eïh#B,½ÿ¥ˆ‘¯£:!ß©Zäû(NÈwâ„ù9jò6¡EF_¤ 1ÒY¼cõ•õ+TB»ë³1óÒrx€Ú›l5®Øên}`ˤ9ΦħóU >¤hŸ¥YEëilzWМ"?»Ìé·´JWŠ;ämçè¹·¡á˜ä6Ž­O~- K/q¥r:wu³º±‹¼_ŒìÈåÆ}räÚïV Or¤$ä8£–“&aoZFNîIËI~ÉãŠÄaÈ] þÍyÍòóº[¤ZlîÒ‹-&®éS·T†•ƒðÏ«ñxYÆÚÉ2b$žu¹sÕˆÓåw • ò³·#·ÈfÒÛ- »O÷Ô#e‰æ«U¹®EV3¾9½âéž)Ÿefç¡åsg2ñÝÒlð+ֈضmY ã'·ƒŽœÝ8Õàˆyã6rÃ#z±.ʇҵ‘âêÔáÈíçR¯i@Öƒä¤ñ¿ ÒvÅ –§¬…³_[$®ÊƒÁÄÓ=¡ºÒREpv˜«©®måï’¯ìþFšEs;‹¹“{,üN_صµ"MŠ4$4hü¥;kÙ.¿¸²\»e„ûùÍK& Y5"d0³ÂìÙSùÜÞù¯#¤â6k^5Šå»µiéõ6ÜHÁº¡Z’Ý1ŸP-ÎÒÔj]U49mà~>ñà´ì0Õ#‰ì²¹™V„ {)¥„—ñÂ2´I¾p„¼ïô åk,¶%K&‡Ü+¤†mZöÅ:×òe1BB¿ËW yÕóakFÿÜߨ—X9öóV5Êà!‰ Õ;—­©«Š]‹!ïçø‚@Q";Z*²ðTÃ'PW&·h§Ã õïjª€–JnX]ó`SŒ lÐR°£]Ç1óˆÏþ8Õ4P3—ö£[°/޶3Ʀ-ò³èd¬ˆ‘'ž­Ö4ðÄz‹<µðBfrÕŠ¯(:Pz8°‡DÃ#ÝúŠ> ì!éú… ý­~ T I`yB8K ¿¿“Ÿ]1.uZjJ¿ETtÄȧ§b;k5­ 3øáBÅÎ#‰móZ+‰C5]^YNö[ÂÇiZávÖj¹üa(Ö"£` qœ«iHePÝQ@ýÃUÕþ]´˜{yáYã„¹í®˜£Ðå<ÙhÓ yidŽÄ&ï׸.°*’@Ÿíyç˜D1¦óÊ騄|º!:­®Yšû™'‰(@ÓÕ"_XÀ|G)•ß¼HV„|û~—cñJf>õÆ» !?žXŸ•†•Ê©kÇqÅ×njaÿý ´„å1—fK‹‘ÎÒ9IšI‘yªº5.ñ5µ°¿ÿ³_§!Ì—¢N;ó%ÁFcoþ¶ YÕU ùAB·Ñß0ÃVj£ôbÌQϤØsReòþE`³GKhà6ªg-Ýj'g³m]Úm)BžK\Råïà—‘Ç¥$Î8(ÉÐm@H_,NŒaC¡Öñ$ñé‰î’N‘ôë$‘™Üä ÿÑ=Q?#ÖvœÆ¡…Ë·¤à óî¸f¦.`É{iÝO‹_š^‡Ù0S®Tªèbe-lž|Dnt8 ±w–©¯)g¦\&Ç B>Òè^¨cÊHãc> Œ T”Æ-hÜï̹ӽHólNãfØ JÕûá1ÅËà—z_ªþ³þѵÚ\OضuZ21&>f¤3f]ÔÄÅaéêTà;ÿãM¾\¸ø&ã’ "ËÐÔÚÓ¸¼k“k£ïÅd ºGlc&‚ŒAC¤E?9æÃµ§Ð¾<}Ù'ø˜Ï@Ç È´˜®ñR0|LÓOÐ$èÌVTù¹í•cB¾¯‘+>û'|éux¥¢~šhð>GÃdÃÄTó­\¾Ê+B’S¤#jÇ !½š›éMÎ9e ·a¤)ë*=ß4qç(߸n >N_PǯŸÒm-bÞb¤Us[­=¦èº8_B¾1¹4 ’uî'î»èÄ„®º¾w$rßç±ÆÊ\ç±lËzP‘&žU¬{ñê˜vt²*Z–ÉçY!äÝY&¹›~éÚÌÝÂj|ö‡³ÔV|…!mRÁdd)ĆFîã¿¿&¾ÑÔV‰ìèœe‚/glGM«O·dÙÂKÖNøŠŒ]Ý/-ÅÌ>#W¤^¤¼‡ªÄývE+'s(T“ûm—w9I[åd¾#°ÄIhKúÛ,v ÔØY^± #IÀÙ´S:jÞl˜7‘À–ô·j2g¦5dm³”·E˜¬0§w3lê øìO@fn²BSYð­ù:·éòª÷KS¿Ò˜ú18&Îác«|¦6xù~0/rBî+û¿nZ×ÔÛÿD6æ×n]bù0f3|›!UøÌ(ì'ÈŽ*¬‰úÁ·U"#êÔÇ !U›úõi:ód©+„|Ÿ˜úMÆÔ/åù¹”l¢FF®Ãl§_tιÈwN Iã;bÿ×`òvøâÏìÿ&mÿ·Ä9>hÿ—=ùò4Ÿû¾n0ôîŠê4ÍKóÞËd2mGJëÝQ¡S ²2+R*ÚÒâÛó2Æ©BI^Œ5 Û)äþÄïž®€kqŒ±™Òq]ŽaµÅjÉñ±[FÈ+£[KN2;²îוе@ÈG kæt!ǢɛeB>¯FêƒÜïh_‹u!‘PeÓk£þš”ÛéÔÆÃ7ô@Q0 2mžCÎ*ËØ­a­ú•¯)‚÷7žû‚&Þ4ÆÅ¸Î|‡<¯,#ú5¹_û¬ÈØŽÜ£ï$`á¡äG'*&°ÖD¶T@RRº5×ÎÊW–é ÔXU`€aK¶0’ArÍ‘‰›ÁŽRº]O[ˉDnHÃØBPº-iÕÒ[‹yÊòxé j (ݦZm¹KšES³6s$/òøÙ›‘¥F¡UvCSék¦ÀwDçç iMÒÛj.7Ø»=¥ÛN¿ç¹éM]!s¯hâÄSºõŠCMŸ@=£™Ub”/ˆïüOè!dñº¢LyƵø‡ú‘"ši{L;ŒÕHc'Lá $„ê»_¶Û tFøb(ؘÒÜc%OWEžÅÕAƒuL›ä¡§tî•=+”,ôâ«WU4xK·/>%y5ûN^`IüŸîº%…©ƒk•—uYaÅE¾¶Öf«±\nwl†ÌâÒ·~*¯I¯€LR;¶ò¼@ÞHCÆ= Žb«35øIÃêÿÎgȆuGeÙôL0ޝ#R3\7r‚$4ðuR#Fž‘É7$©ÿîîy%“©izéÚµ FFG¤:{uD:y¥_]gÔ(x²d(âCoØùÅVD9¯©hb Ý1ÍtkV^ëæ”ïŽz™©pË£¼Úúß©ÛCÍDÂXñ1£k‚¡OÔ×òœ­²A¤ñ vG}9&l“œ2iYÙÒÛÌAß0Ô•ØZHÎSÉ™ƒÂäcb›rl+™«úIŽÐ~ΠÏ¿éÌE©FMT^ÞîC¹û+­é¯tPþx<.ú+ÜôW|? °0Æ<"”"O»aä=ìh¦Ê¯Õfïà‡>¿‘ý¶¶háw^G&«\"ëJ`$¹²oöbä«\AhßLï/"À‚ìä ô˜ÎX¿­gšÁ1#dE¨~õNª)ûí6Å-B’ЊÐ{ñŠömÂ+¿òýéå¯NÒgO×~ìˆf)B>B¤ KÒ5EÓ×F>!†qJu2ÖšÓ™É_Ý!ä+ÈM #&ÖýŒï`…dfáIצ/h]OB~‚i·˜Ô›<õ’Lø.EAY¶4â¬2¯âªÊóßù?î«G™Vhó¤]!„²r*2‚,§nû8Ž9wG%”åÊdø|€BgOÿ}OÕõËÐLæâú@m#ýHåMm²y¨GŠ¡O`ëhPYXi‡¬)wo”]÷”VFì¤zNÅÜÉÕ|÷šîÖ=Ó«MYÓ§ Ûõƒ‡ŽÍ²I(ÿx ‘¹Òôéå‘TÉåá'6`ÕRà™ñ¯S†Jà !IØý.¬æÐmCßê÷¼]KšhAj¨˜4ô´›ÌsBi7rb#[_I»‘†¾G"i7‹<‘vÓÈ@ÚÍ"O¤Ý””K(íf‘Ï3+z¦¬è­DžK²¾6ÛöS9ˆ¿s<33kî{~>/fÖ¸›Yk’ f‘5ƒÏçuì8T ž!KMÈ‚¶üoY‹’„|!|¡jh3ØÃž¯ëYä5GžïxÍùk¿6±Vòµ­ßo‰õžÚžW5IN%õå^RŸ„tùƒ¤þ²p_%|~ùU¦õn¤“¼~¾x!êöš;ûëvyE¶½V!$Áò÷¦ÛŠ®“‘{F!]þ¤qÄ}†‰èò¦Wœ™ÝnH‹i“|‹äªÅ$¯ªBÈûU‹i™ÐåõL¥©jö,ͨŒÞZŒ|^Õú_ëéòÞ?ÄðÄļ”bŽò}Ô±”±ˆ©ú‡Ÿ€AjGÍk1ÓºH„¿v5Ï>ɳ1B’sä&‘FÞw¿Ó¸¹Êh0®óÍ"çW$ãûflòyÆFÎiÓŽ³F;¡üÔ »È7¤›R¹&ò|DHrÎ[žeÞ»Ì+ t¡³÷}L³eèýý|a±l@ʵNFŒ ‰gàïóÓ&Îgÿο‚ØxædšÊÀeìRí¯Ý$…»v!¿¶\¦öþÚ}«öð†Ôu=ŠÝÙ_¡—¬%8t• F¾Ï¾÷Á|ïp—‚Y°ãêÝÉÕäûš€ Ð<ÌÓÌ·Î##¬Ñ€dÎtx9Òå$ïo T¡.' Å$~Y‰t³€* dV3ÿ¿vS[ya”ÿäV·K ®ö$4¹6ÆÄ¬Ðw¾­ÚD4kÑ`$Ò¢5]­¼­ ´ ß/¬º;-ÚžËt3騆ù º•¹‘ŠVºœmœ$ª¾ýÖ¥šäv 3CþUE«¸ÂÇ„ÔØ¶#´ ‚jGx;B‹ümgu‰=°%ï÷7j‰üàü3ú (×\Òožn.­ðÖEߑӈ‘ä¤ÔOÙÐ.p1‰“–“È!— ê¿Í ÔtŠœñÙ_¾½c†YYÉ›dER$B¾È¶Ýõ¡ÞQÐ\Rýt¥ ©¿%^²)O*ùvcèãm5” Ïsª”Øв#âP:h¸åc=Ã{¬ÿBü@™ÉÊgÐÀ@Öçv`¥2;èÄø(Ãjþ`»gwH5ð²¥KÒñŸý¬N 1®,z9>æ%ç°¨+|Ì×%;±ð½ƒuÌVU¿òÖ—á?~œØm)£@Nåú³ûæ-ýó7h®È”»bŒ‚Æ®»ó?.ÑÓh…éh+г7!Ÿ çþïoHqætWOq¶È+–šL½*|Ì;ÒQaº«›Ð¬­­H@Xÿ»#COKdh‹<¥[[@¸øûW[À`Öߋހ·½)ðÊ@‘ˉÑœëm﹜„¢#gäò²ÉÏã;¹\@ øy|'—wéñ\^ú§ SI.È%)Y\À$žGq×nKä¶¢©Ö!wõ0=C"ÔlF—MBÞƒÐÖåÇã:u]—ÂâÅQNÅfFS'Ÿ×׊ÔìCÆPÉIzO2ÄQ’Þ°z‰ˆ½¤÷¨$½JW„$'’ÞÃL &ï>o”LJ\)*Š­½Aòù Nºé(™µãe¨wÈ3ìÙŒ(’Ï¿¼®¡^ŠI8Ý$ÛˬHæjÃÈ'pùT)2wW$ô\>B¾Bµ—Üló•(ä¯n¡6ðÙ×]¾íS±ÔѵQ¡åˆ„${B‚B,Éè3Ôèçȳ‰Êªjê~Ð?ºÀÕrûÅ(`]Šn}L#¿[ù-6"{Ž13ÒÓªú.Ó }ô…·¼©TØ<¢Ç—ß©æ5=ò‰ªïjrÉðÙ¶µœ¶ai`õÜåñŽPë!/½.+Ъ‡;z†^ôþfôVz4 œ˜ˆmbÀǼ6 ~çå7ÅiWâ¹ú°w!yeTd3wÊ™Ä3ðµ~£Ý;L’¦dÅHT¢hÇJ yõ [{ø6£èÚ„ñ«ï??_¬ZT§›ò¶c<ªUÑŠIäë¤ö‡$»ê»­KžmÕƒ~ãýçDnÄN™°ŽÎbÛf„¼‡$ÃjR$Æ“!_òñ®mÙQ•ë¾ÒŠ˜¬ärßÿ]µÿG žžE…ê§ÿ@`Â4ê^}Ó£0 Â<Žöô­¬VÓꊑœSÅ2d}Ưï©DÈÇ.¼å¯g“@^W‰¿¸¨ú8!Î^С@È'æš"¦¢ÞüwÈH@Í; &{\fëØ6xå"j©Ê²ÿš¥—UÝäC¸Ç7+êãe®ú‰z­/M"hXü¡«[UŽ >†À®Ô,ôœÔT”»ahÓdmSYzZmß+Éf 4Äœ„Àg(ÇeZµ«Øbè#Öµ/ 0\úe×Î ɲp!¬išUõÐXÜÓÆ.7Î~Õp¡1õ‡46’¡cõ^yw•÷üבí[·n”mÙ. ÞÉÍ÷;XB‘ÊÚ¯½þ1œÅÁ–Í5Úqä=\¢J"hÉ [A@›ª«¤è148‹æ½ÚƒWUœ¾Ëe›p£ðFÚ㈔Bê¯%ƒ@Žn²­+¥ïÞn×Û;{먶mËîíÏ>‡L!•!bª7O<& yä «\,¬ŸŠQ"dŠÔ+{˜ûžçuþiñÓ!۾媶ÏJûKŸF²¥ä}/ÿ´ñÕ™ðƒÞSµÊFFç~éù…e±ŒkV»CF§¤Þñ[øcæ9ç•è&"$¢>/]kD'EQ®ìƒäƒî]Oªà-B¦Çù"5ÖДOEÍ·él˜QÇð¼N b"iÁÌ%·ŸÓÌ’6ñ#Î4r»`p5%•PÑJnÉe‘Ih¢ õ ¦f¢çJǹ‘S-³0!‚ÈWl“•íx茢ÖT(8pùJ Ö0›YlÔ°Cbò•# Ç'|å;¡9²ZÑÿÎû™²ŠyyB˜¡zÅ%Fî 3ª-&Œ/ÅÈC ãüöÒ-=×°C%m$&‰ùw¯ÌM«P6Cn{EsËZÂO}Òõ}·Cž$LJAÛ„D—¬oklFVIÆüýJâ{Òäy4d–;äqyîVF<Á*=¯ËˆyØ!OD§þåÖæáé¯+·¶Ì£•»ôú ™€¸‹ìHM‚–Ù\ ËòV¬÷×\DÂáWÞFwù:0õ)29U¢dà†%É…žU<œ6 Ù™aeå›?‹¥¨$ÑH̯`ÛÕLCŒ/ãÔ.µ™Äôô•‹pjY8:I̯€Ï¥©asÅL!1¿‚ÝKÎdÚðä”ÃÝ•|“ãã§äãòéj÷ë¬>=¬RT´³UÐZÅ1s~.êSÑ¢÷î""ø³)ˆ»VCþ¡á`¬&8ðaöp¿fÕ:~ÞB’ˆ«Ã÷-”‹i¸^º!ÓPÀÆìÆBâ1ï¡|×Sú:šJ&z<æ#"L.m8XG¬šªbQùµFû²ý;ëªa=#\¯9lµÆ©ág‡RF‡|ÁW íë’Öt7wO§Žå™x¥ ®÷i“çyAȸe!àñ¯«,D¡X'òˆÅ(3,F,\Hd_9¸‰$úhô‰*z÷·«+D£ P¾†NB~ö‘¤¸‡ÛtIÂÓoWÝúò‚-÷Ä  ÂÒÇ=ñHµó¨!P;/€ŠÇ$‡‚hVU"ä±…¢”ƒ(6!—’dæÀíÔ²Ìw˜Nµºf,¬6˜à\2ÜDckXv12ÔXsëŸ:É:8üQ§{8n¬GAóFòÖ®rÿ’ä.]Ì)²hš™#d#í…dzP²APo„$±¸¦»äå¦DÖ÷Orß7.;dëP.F%!︳Ä‘C±Ë0ò×ûõdT{ç4[ò7Ž ~¼0³Ð^´ìk„Œºô*W:2”óXeëúéò)l„¸`Qq>~f¼ò?!Ü—»€°™üÔÐJ .ÙÜ1] Ú—©[ú)ðÚûÞ.0I+‘i,†ˆ d®þÍ4¶|*}2‚;å i¶øÐä,‡¦’5U-††n•ÜóäkCÞ¯•“áÜl± ]·Õ[2ðTô¤ÎáÀ2ºöÅDwïÊv«üÙèg,áê¶ù»BÔuµ[¬f‚`¬ÕiFŽ€íÒ3¥oH×µk9O¼lžVrÛ‰.XÍœÊ(,®†û»¯Ø³‰E!Æq·Yâ3‹Žë³¹!Ÿ¶cy_ì^†s‹ R:¯&2‰?À-†gYÄr_Íé˜7ËØ¯x&ï6œ_dR#…Åzìd¥2'©=¡`á“ÇîŠð»µÓ§™»ž"Ì2 |Ô†Âm]_t™²·ÒQ1¡¨öAàÇ!ïžÚ†’¬â9;9µ¤C>¼œuL[íXón´ógô{؆#뱄  Gm8ú–‚°t Pø®mGc·òZeQ£>!ç*‹¢„ Ù‘,ÚØã|ûÕÐj³}õë¹#;p4{–Ú†ªáétO]•®³a´xÓIÍ™ gƒlöȈ¡pÂxúéúŒ.…W(pÈôÙe¼Ú‡DV.ó—3}sñYZ„ÄV®CŽ´–bh „üEHÛ!Z¢ôŒåùŒ|«è*ë뺀p[zC©#‹´çˆQ¨:†gDï’.Ào¦4÷"φÞ@zx“¦peì9ŸÖu04 ¥ssÚ»¢•\Š âJÔó;ê¯Nˆ¾~O·4*Èûlt„¦à£\×Z”;¨û–ÿlµ{6|=k“gªißâ}âRG6SØÌ!§JûWU®µƒn¹UžTJ;Õ"*ȳ9è3ê0òüÙÓ¼4=‡Ú q(l¬9¹eªbŸ¼¢ÃĤ¬j„ÄO·:ZÛ¦EHòe˜ß&Ë@3€¤»’j[hfØ…Ö…Ê^T;dÅù?ÎÉ꘬„öÇÞy&äAEN¦éEBÑ òúõïD}µ›«ô8•ææx¦X’þ^JÇu$}žΆ„i„°pú:ï9E5 äþsYÓ BøåþsYÓ0B²Cž×4¨‰9­lÙ»)UfEÞ˜·7ÜV¥íò&cY ž Ä!Qé·µßÍeÇÕ‚ÛI¢àÊ–› ®]×ÝÓÓÀc蟬‘ÑIí„Hèá™ǹ–u£0N^Éî‹«ŒÇLMcr-1ÒqœoAiï³¾•þƒw{r'ÿ8ªV{ÑßZök»Ý“ÀagO\ס9Lté× º)òq(¾6Ry¢wòÕõéMÖèµí!³I^[{¼òEâY”-H~{zâ¯[Vì‘¿wû~ùëbÈý¾¯ü(*ÇV‹¾Êó°çï¨!ÇDf(2=‰Œz‘ò~–`Àâì§Aþ‘‡UºŸ°bÛ `qvÈà ?3 ÑÄOß‚ü†Øcãb÷z±¢h‡áío¤XBÜçÜmpR#E¹ ÏúKBOôR–Ú ÁHr†\×ݘé!·&U†…sBÈû ²ÓÈ!mê¿~î®^» ”¾½·‰¢ûßɼ´SUqí0¼ÏÝNH¹šzfä)' ÆOOO ‹÷¨Ò “¾µú®—ù8[y¾rXùç÷{OÏÄVþu°C˜¯Ê(ßkçÇŒº¼• qòˆDµŒ °½£ ö§X!ŽøøâU(,SªaOc,t:;d‚ߦ¯<®ôEoó‘ìÏ0#ý;{„ܽ£-@¶­‡Ü½#‹4ï¨þ‡|«I0U—y«;&ƒ%ðˆêÈÿúªAËn9-mÑ& yÜ/Øë( ¬…$ê_>°.æ kK¢þåõÿM$ÁØÔæJØJqT äñ¸Ðµ5Qa ȳzMnmho"±Ú÷FøTYžm}ËdF%¡ƒäÎ#b”ÿ¸(f|ù*Ü28máÒU6vnjz¥¬áîˆ;ˆ½&ãf‡˜äG{)(ˆ»®d_—Ÿ :ºNpƒ‚øAmºIBÂèñºB]$Fbq\-ÊêA­ýñø¸×ø€]‘70÷_Ìä»gWlë2[l+§uü(íÞ ÔK"­qŒœÇœ6IB&¡i¦*|ÛJƹTm‰‘ 1¿ã*å­12TWÁ¯§¶ú'Îñï¼uj¯?°5ÿͪØòqäwè/Ž© ö|¤ž~ ì´²ðÞdY9õS…U›<²+¿»Ä«E #ƒ¤œƒõ)oìÆá´õor¢[IF’o¦NíI)*S'ùMweyé¥ñ¤é`y?óLŸ³Šê‰CËéQ•à$Wðeâ–Ó#å1æþ‹î·^+¿kZx…èÃþ|"äÖÂkëßL o¯ÿ#29Qv$2hY˜P´-nÒ§bÝ™^R„L5 hõî¦ò~Xd»ü¹ôûº¼;VàV#ÏŸë»#œÞ‘2÷áÝ1‚‡òüÙq øÒm;¤65ò¼zÐt ZÂ×µýáÔ<ßRózCùUzbu8[£h=Ó¬æå,Æ$êR³BÒÖ•1;ÙŠ#$9Iâ‹na™§Þ–±íËË´ ë[áßy÷Ig Ñ@ý0€Ú‰CÚN˜?žZËÎ]•MÃzŽgôyúÙ7­þŽñÓŸ§jôÑ;"×jôá+~’k5úÐið$—jô_cžªÑ/²ÆÈûY¡Zƒ$ÏôŠªÊp&Çbß_sWë¨8FžÌ,”÷Äbß_sç}Ð,"Oœù¤™OúrãA3¥wBÆ]U…Ó­¯óž4”¸DbßÑN¶Þ.W;ä¾ÐÂõ”Æ)¯ñïŒI||‰ïIšÿÎ×w,È”n± X¥Çé-³uè1H|<÷Ò1ŸMÁÏXuö÷jÈú=OXÍ}TG»îwÏâ’ûl“Ó U Ï牜n·Ééæ ØŠÏ«»ƒÕ¨—“¨ïÎçð+«ç5ã!¢ý<¿;:}w”Xk¡ïÎKôÚ •yG²6½xÌÇñ*cÍžÑïY©Xb•Ïßå¶ç·À» \èû<”×.mæ¢Q¿ñ. R ̘ۘ[Šd« h†FõI¢>œÒ×´ŸªŸ†¹@È4*P,}Ù¡¢íôÞ?ý'KW;M»r^W‘{šYSåa*w»yÛæõ³Ó•Ê §Ö¤ÇlZVB>Òf' ²hÊzEÈWЇ(¬#eV)WúgŽ ^ùÍ xÃüÐ2Vbè-NIƒº'åÅ2ìÖé¶KO¸ìµ\W¶R†¡äÔ²TzÝξùqœyü͇NÊ£ožöV¼òFÇÎå¨çrg]|hU·€gþ-MI%ë&„LŽÆì°ÅöJ/r Èb{¥—›½rŽC’` •®LŸËµìYöèý´ÀšwÐû#¯û9ï¦â>üëq}Ë[$±>¼eC\õõ¸¼eY´J;4Ðæk6m>6íÆt‘â¢HñP-tÑ.m8Å{&¬ÒúÝ[ ªg?â§Ÿß²íîwž¨øiã¸òu΀žþû h` D´¸È[{=ˆ¼vú _Lmáé‘ßõ×Ü^™;p‚Ïê“Ãy÷º(YØ2‚n'§;½é}ÉBï™|Wrjoª¢ü=Ô#o_bjî´S\1Q³C& °™œû:ôë;dÄ é;”–±1”YÃc¦ê·æFX¨ß:äý,sدӟ‹"oE™K=ý!¨LÇÞI[ññ¢k½™a•ˆ°6d!ý±÷ªi¿â¿'û£™\»Ñúé’`Ñz[RS­õZ@æ2ýIw¾å&óaM=Tü=u5ó"ƒ¯‡9Ë2vHºã1,œá0gŠ©µGHP±0v˜ÙÅÕf‡1Úˉ!ä3VQð,Ÿìû^#B¾¾õ 2ëVí%â•ÿAD›6(º‘.ãBw/évä›ëçÑe˜ýý”×`2EJàѤ¡'ñû޵´jBFä^Ué­å÷›Ë05¤q¯ß¿þé¥Í¿ù¨muŒL"¤»¹‘Éš‚Šuzýv6°á,¹€S9 ½~_‘«Ñðn¨ÝÓÏb2ãê_éÏï—ÕàhÿFmÎYÛÁÓŸ Õ¦è«ÆÈäDm»ÓîFÌ´iiÿ:Öë©w!Ó#ÊÃÚPÞûë¼1Mmñ(Œ<Ô7O74Gy¦Þu<œ ‹ýŸÝÝE‹N#hzÛù€œ§–6œ7¾„4½a¦Í̵ÖþŸG‘SoÙ¥·Ÿ/]@_j¨F¹ 9cdêmej+¤¶ý©dÝÔuç=®Up+/8íKü5‰¸Q¬¾¦Sïãà+òכ߮ÇsûŠÕ›*^‡|úCÄÔ“Ø2K=fSç£B¾|㤉“3ìÆeY9ž»íý×àeá‰"F½;Øò¡xJ· Fçð–nWŒÎLÛ¹!/};‘C^0:3<æ9£3XêyÀèll¦˜ÑÙ! 2ftvÈFgSæ3:;ä£3œvQ3è÷ÓcFç4jýFÆŒÎyÀèl~gÌèìéñŒbFg‡¼`tïˆ\1:«‰—5B^0:«!/Ãz¦ÿÁè¼C^0:‡=Ÿþ£s˜{zÅè¬D4÷ô?F^0:ï~磳ÝóÑ9ZQmmî¬êAûœï•©vH°\auéêÏk*£.²"drÚ¼ìÚÛïEÖš² ÔÓÓÛó¤—‰ËPš<GÈÐ{cSÑ&/7-Õ[pQÂ;zí2Ì…Ó7ÐZQ®rý`dÔ~mEeM›¸Rm5*‰‘$d±rPOïØªß¼§MãÓ¿Y²ü”Ê‘Ièiñ­~¹|]F¸»’T»·!ݘi"B¦X©ÖgY—Yû>!ïß¼^Ú—Yò9ðø¥ÉEãû&¯ öEç‘ìwäZ'™àRê c&»äÒ}&8óNÁÉœŠ[ýaô§v‡Œ)¬œŠAÊzí>às&É™jˆ´ Vm‚Ûî ý±“¬GÙ®ðôôKM¥p ÷lœ´ï!8BF"ë®;†)5æªÎg†Ç¿•wòú]s?x#$9Õð¡»1ÓS Ÿ9¬Ò-º;ltÏꊚ®Z:®Òç|RW#ÚÚRO]GkùáÅHrU‘èv·:^èì8Öz—k/Ï6@GAÚ¥QäGõPçí¾#¤6ÔÛ~µ.·ªrtMVoã”r|ÍØo±jštæ²´Ïð5|…W„T–vó¨m—jïÑõeá÷Ðÿ ñA¨çx÷Å~+ÑÏ_îž5y}w`gdpºöÊZо'ß¹ÍEŠ-šIAÈi£Ç¥üŽÜx'`²¤ÎTÿ¨ÌI‹Ó{3ZCÝXJŠ‹Rð¢£çE…WiÎÍ;H†Oö„‡˜x5‚(¸æ!Rq<¿/ô}“ ¾q˜“A6¥l…'Þ°P˜‘{o—¬yœÖ“0OÒ):„¼ó\ç>"^é–±Ò¼¹ªgU[T°?D ÄL„º=U+gi±r„|^ù¯xÓyÑi}D&´JèĬ6Xè3U!„žæ‚ ±JϦ¹ÜóŒ¯Bn¦¹:„ pUyÏTtªövKíÎðºòÈQ®¸žGNèsEMb¥(‹Já¡ccÁ°Ç=SyÜû:®è©ïÎæziŽ+ê&= ­ ‚ë­,áûôx:YKM?IJï²j/æÐãuþgBqS·-ÆyaI…‘Á¥ëÌk‡¯à2Èì$xø ¯ÃQ);ìBǹ™:“óïðÞ}¦êõªéfÙ狘1Jø;_hÿü¨Ù<d6#ÿx'Âë…÷T~ñÚ©¥‘¢•ºÂ¾õå¯VyÔ3(Ù¶ç”·¼]òé…Fß~XyWH¡¿!Oº˜ô£º˜$éžæ¯ª/+‰5²ÜÕŒ7cÙ!äÓN‹›Ž£Zq"NfvèO¾rzGáû8Ý|ðwÞ¡Œã*þçZ†Íc–5—¬yÌÊ3׿Ý;oÖ‘ø;+Uøöû4_âöEë:Ͷ¦÷wVYÖvÝèþÎàN o÷ïÜLÈ• çû;¼¼f•Èj=¤u¾³Ýkχ}í€k¾£+®ýÄwŵÇȧMÁRP–·MºrÉha‘/ÄŸJ?%•bÓ4ÉúÐqÜT –B²&™9i[æ 8nÊGÁbûHZV7Š¡C–¹AöK+þÛ¡/ûöŸUÿ#×/SVW©´cCÈÈÓj5gNDZÝË¥éüArÛãqˆkÅ/âéXe »ì«xó¬«VŒŒ}udMJJž”ý8oé)°‚5R%ÇÓÒ~‡F¢úû¢ðζº.åìþõ.3[“’gî’uSbh`K9°òÜÅyüYK^á7ªS°uN_è½iïù²¶"¾Ã/êü5­K N:©KÀæÊ 6]ó2’:Ûšîûáã3 ¬ˆëÖ0qz®C^žëÛù'Û hçCÂÊn‡¦…Æ>T¿WÍ?^¯‡¯ÿÇŽŠ‰í¹VåN±=³9Mx9â‡õ||;ªÈ¦ÖžìÇïJ+°Úq[yÍR@Å3•Uü\«Õñ*¬â—lãOxU=C4«%`ǽä{g‡?€œ1e6Ä” }>ªžñ‘G®îVëÚ­P"¼öB”iXoUüs£'gÜ!vŒqëÂ;>Ja4ûR‡õç÷mJörj[„|z(ó¡¨naÒïÆÞtÕ?†•¨gN'º}jñ,‰æG ;ÇÊiÚ‘Ä›Ø2_‰@Òr*Ç #UQþ).©ça¤~\½ÏâAmÖBÚ UQþ÷_«©¬®IÅÁ3MKŸ’.Êÿk¼t´)oó-Mh;"¤rûÝTñ«°S´Kµ âïÆ§î~…’èè‚G¾xJtl I}CJ”…Gg¬^’eª*‡‘¾¦«PæZXSš|h5A <àŸÚÁŒJÜUåcrv<ªåAåñèRÀ˜ ãQej„clÊ»_3t zíQ#iSR¦c¶ákŸž[:“Ȫ³YcO \uádOUëéÖÍ Â†!$òCпhOAœOÝ‚‘°ã:qˆŽÕe¶g+Ç¿(öG4­â²8Ç2ÆV|MC=·)mÇ]×I"þ ÇЇ-d}ÓQ¦Êy+RêN<ôyá0vL†ÄÇù„ÂD[Õ4îyÉhtÄ/;;¿c9±V³´qÈ÷qæ&?«¤¦)˜äA3RMS’ñ±,¡q¿]ì¬Ö¼µ÷ë-ÛX[$B†nÍ[W®Š‹´›?s‚þ|Wi*ɼ*™È¬Ý‡ç¼uð43$ò‘ äÈMiJYpÍVÙ÷jÜ6N;Bž¶*moNeòsw~È·i£-òóø ûäó8Ár`êWB/8­•Ûs~ëñð5ƒoV»ô;öYí䟚+c¤¾3&íÍ1’øë4¥Z¶ˆ”ß=ú&ʪ!áˆòÄ÷=hp–Òhkw×<Öðœ)Ö&M±v;¤§Ò*_‘Ö­)yV°ö³!dpeŠåê.^æ‹Ð43H‚µŒJ]e¥³´H¬>%grôÙ94|æe¨;„|ž gÜ¿þ´ž™œoú|Ì÷X¦Äg™"äÜçÍ RÇ×vZ+&7;D~ðÔn«º üä²Q¬4Qº#/̦Ԋƒ»G×°Îé὎,z£•õ!å²]íy>™¬Rs¡ÚG„|ž·@¥Î …»Ç×§ä`xOéÚh«Sê>€|üܹÔ$;¨3xðÝ™¤”Y&ÄçþÁ¾;üŽ!þ'/ð[ÝG^àQI<^à?ÿýïPáNÅNÇ12º¨p‹½ÖêÇ <èȰv@†gë½–ë˜ÿä^‚mˆ5@|³>«/™·“H|úÁ"±*^’[Å‘ö²H2nù´óðŠ«¢v°‘Ë2šl¿!dà™'kÔ)¬wßTP§]0A=îå*¥2p»· TdŶºÈ2X›Ž£¤ödí³£Ž8±0˜*H#¤Qóò¥oÙ¸Êo!£‹®Ž7HKžf­¢á²¶(wÍ¿eRîý-“‚]ñy›IU"“by’I‰ƒ2)ƒ<ɤ¤¯ŸIäI&%¶”Idtn¤‰Ÿg|Ùë–Ž<®¾F‚Ÿ›>¿Úì݃ÛAœt°/ùêY‹¡^Z Á/rü—“ˆ´‚u<禙roxžÌ} é$Àyâª$- XGA€×QnýÌç*KšríaþYük³3ÝqÍ·¹Yæ!Oå2¦í–tOG„$Ëè2ÁQõÖW,¤nŠ]¹Ö&kºub=EÈKm2æ¾%ç–w¦Ö)Ëkðä£÷Á>wÅzD÷]2àÔàu£ø‹;®>«“Ñ^] ºæ{ÉÒSz.r{Ê”"—AI—ïƒ+HYhv9¾=eõØP„ô³òº,ÒÆ’$ÍÂ0ÒWC´9¬ŠiGÐØ6ÈèÑÚ¬Ìî=R^o5F™©Ø?mm„¸¤¾ÃA. ^L#ì6½ÀÖýu^ü"±Í')Ä!ž¯‘4¼O€Ñ#bµ’oåñšÁ¹=»ì!Cduík¤#U÷…„ä`}VºÒTRV+¡«=ã¯ù#‘ÇšÓ]v”~àD£‹'žÒDYµ@,Œ.ÔÅzg[?æ_3t³W¨I•©ÈßË•6Hrl"ª\¦[ÓÊí`aäÈ zm–™U*M»nu•½Ðiç}ÍÜI•&Ð0È·?¥•ÛÙÀ‰ò~s¿èu™îê4„wäEÔHº¤-&Є&¡_S=jŒ´Ìi½‘0FÆãŽ¹ÙŒKÛ´Ó'¬7àÿ­BSÑÕ­ß©éxͽ½ìnÄ^9ÃyD‚›é<éX o“\Îbˆo^jÄÂê áMMퟄÜeúIìZ‚Fì%[¹4ñü¾·m[tÜ=O¬"¦ú¶zâoªö~ê+È É·‰½e+çKÕóaÄÈðô!£EB^1Z¬8B‚Ãn ,Y³¹yêÞÑÍŒ$¦Ã_3óÄ2hlÿŽ*áštÈWØëŽcûfÂØ¹x»À:òÇöUß´04²™- 㜷BºJ)pºŒKïÌ̉7¶F¨ZAbê6Ìíáï|Ùñjmº ïÞ6"œç Fžë WÒ½„ÃݯOmYuwú÷ÄŸY6Þhú¥Œ«ZØCü™eÛÖ­+—q´ŽgÄŸYVùf™ëÉ/9Ý\ÒÍU #¯®økTJµæÀ”-r§o8B’+›Xr]ØÄÖ0âßþróqÊÞSÅ É^Љ%øï|Ÿkì%Rá#ãKϘ&þ¼ö ¥¦ñ®ù¼ž‡íýyXâf«OçaÝd7ñ=ˆŽ©!™ƒ»ßT9*9‘ ;C\W³¥UßRx§¢›îG䕊níÕ—¢ðNE—~]3Ιªj™Ð±`«ÈÐð5ãK•$೓è}¯’tDêˆÚffÚQÄÓÓgÉ*„ôf¨@O‰Ò±šÅ²Ã× OxFqkyM[Kâ»IÏqs•“ïYu¬ýïÎÍ×ãVûqù¦ïkôíÃ8èž’×ãRû¿š×”ƒö?ñ}Nµÿ-Q›8_£‹ˆzÄ×¼Òþ5Ã×|b°ÊÖ¬Æ ¾¥[¤^†ó!O\€$Ÿ@Jަ𔂛(Ý'Ï­èÏökŒ©kkL]´‹uM$/\·aH­‹€"V\Öt*û!Ÿ~Î¥R–îbWÏ~BÈਣ¥®™ì}³—B†žr´1ÐnøÔÒ­I`¿|}*Eé6ÊŠ]>NkS;þ;£s®O•p Ì’WtCA!ƒUüŠv³á=Hõ¡í#òΆ¹'}9>’ä§cïË•ÔÕ!!öþÈÍ[!"?XSÚLyQ_’‹^ï›Þn‘T0äF<–ÀYoWœ !Ô±5þ´ŸÃr¨Ï<ôx¯íïs‘ÿË#­žÔ+`÷äeowwƒÄ½]M„•½]eøîW½Ý-–€AÆWçûžAäï1$°nµœÂ”ºÕvtxÞS‡~ÜHç™w®÷~ÜSºs;­LÞXñõ“ÙŒ/cbÍÑ_Éûqˆ¨A«½`í*µÚB†z²SÖ‚Jó…tUÙsÆRXs"jxäý¼cÛÈ^9üöÉWH¾K®vÚl[†,ç~Ñ¡Ï%¾Ý@jÆ,§ýgëB>O¼ûÆLœ® Qú;¼pùSõyþ¡pv¼CôÍKï>½ƒ‰/™÷ÝÞøšÄßëtp30žô¼†„AFžÊ²q™YdÖ‹4Ò=yOùÊÊ3+óŒá»¿~€u%~»08ðÝc›õ¤™ÍzFN—:[øŽŸ§ñNAÖ"yglO˜{ñžûï¦g 4õ¡éÒºK®:@Ÿßä˜yÔä¯þÒ–ƒV²¨[Á†ó¾¶å$3î]3º.É™w7fö~ý¥ÁÀû}‘DS]úv£gtfõ숀y]ú“A^G/lxÇG"`eåè0ˆ5ßÙ° Çã@H2÷ B;ϰè$b»+pÅ?G3FcÃ.®Ù¶œu°Çþ lÉÉ»«„BI°o _LâÇÍXÔ>rÇO4„é[í%£”†4Ò³?ÝÄfŸ:A<WÆŒçŒyãpq€Œ=½ƒ†›ƒ¦CÈðÔ”/©7šÁæ—ÆTÉÃW‡IN!ø/ a#]ò3_%qt2Lb~ÆJ‰4EÈç•MëÖ¸§a“•£M+= CÏlYe)òcbK[å`bLâÚ±‘»_ò412‰±,BŠ%ÏÈÀOáK#»šïÚvÊùf0ÿX+]½Õ'z¹!¤+Wæ¶*•XÚ¥M7†o4RÂ5Ë©‘øRx2Uf¤Aª¸Í¤Ä~ÀöÇ–Y ²›8…±RoèÚNÑ—vH˜Ió”#_YÛF/¶ŒõùÆH+c›Ì9³¢šCÓAŸ2JvuLd[,;ìÕÂñcÒ¯þ÷WÓÕôçLÅ©ÍÚªÍïS'òÿþc¬àͨð”·Ã`“îèçÌ^ÞJLÅ:m=B>Ï‘[ÁÁÈ ƒ+亮ž‰FJâ³Ó2Hrì²CÈÛË«p@1¦Õ]óqóÛ·‚®þNoößÿÌó,áyN«M£±¥wû\éÅKE@‘M:ˉè'øzžè–”±éƒ‡çYÙ²L!~Q!þí2Cֿ¹¹{z¤Ô8䬀SÉ £«»Öîž›©ëÇc³Ï(úh5ºúß3œI倎dØP¨›ÚOÄÎÍò3mñˆ:OqL¶Ãz:fÐÅF¸B‹êËP Ýx‘ôÐä=2‰w˜s¥3¢Ë°b-•ý>– i*¬åÿýÕƒ‡Ø êHg "u ú÷×ÚCÈR¹4’°«ä;¨ÕÚø g4-µF˜(v0ÄE¹±äÜ%™Ü_QØÜǬí{DÅÖ3æÈf(ŠNÖ¥~ᕵ'f-#î~ÆŸeXUhI¹ö{ÎýÓ<]ú§ÙSÇI×d`œ¨š¼z“Óƒw5HßHÒs;rgè§>à¯?´¢œ1'Fz'ëó¢  uëáí ‡ÉdYÆr¯=õRu­›ë@:L”ÍŠR7÷‹(º&!p`±ˆ‚Aï‹„ä‹E±ƒ‹Eä=¾6OÉâ¯Ý6O‰"Í)ªÒj Cí4ÐÇø†'°­â‘râWH (£ºÂ¦÷¶Äƒ{€Œ/i*“_Kw9J¼Ö2Š‚ÝQNQ¢è}-‡Œ(QteD©Ÿ‘7¢DÑ¿Œ('ˆtbž>'œ—cu©(0ޱHMHñðë|ÈÈ +ƒ$K—Ña_±%´HŠŽ®C®’¢SvdÅ™„HS È:W ÏóéM4¬ÁãÊĵ3¾ZuRŒcþ:bc®½9*Êà1S/vU™Ê‘<¦™œÑ‰A¾ Rzt’ù¼d@¾C¤%mvÙ°÷‡-ÈØ;ÿ ýù¢ä¬œ Ô'ÕÅZ´NÜú!ók9Ìíÿh3Ã&R7¿bÍpzô±UÑ«D>'y§h)šB[¶Ô¯ˆ½©tÊ{—Èè3„š¶—€VcæÄ/-…ÜMëA5‰à’Ln+1Ðô *2°Óe½,¯;seY?âs»@èû º÷ž€–q‚N¨²'/÷²Ó DmC I+ÚFÕ-âîߩǙ*oÆie(*B¬Åíá𔋈´\†Œˆö}ç_vÓ‚ »*ZbPGD½ˆˆÊ¶v­aOˆ"Ù.Gé¾Máð”j —š‘ÐT²ñƒI岕89‘[$yÔät-êÞEnÞìæËØ…êú¹»Œ'CâD1gDÍî<ÑÉÁ4Åeô2°q\[QJqšTœ“÷Ù‘7-XÓ yíƒÕøS 1¨¯k¦Ôº¬ÙF§Ýó좶Š}¶ùìZžèd £jtÚ?Y6Sçý†‚Y8£FæRtŠs^âvȋكPUÅ見 £KÐæŽ™ü\·Qµ~“=frÕÀ¶%$WÈH¢m “:;W3”ÄwœTÖ;fJâpÐ*þЬ8¶v‚ÈøSEˆÊèr¿Ïj5ú3wLl<¨¿KñYˆ8gpÂÆrxEè‹o¨T¶Ûñh'™ 2½àPÎ|÷ç™\<‰n%'Ïû)šÜßùçiž¡6ÌH9u<±¶r mò3fçyz ™\ÎÛTþi>Á<ƒÖ)Õ»M7âœQžè_.›îÚÓ¸lú•œ^¹lvÐe%égéÐê7q»}û³o3$HS“×¹¼k”–µŸ1™]bL£}¦”Ëî§OQòþ,Á«€I6½2ÎS ¦Ñ¬ò¢õïq½o Ù2‚¥Íìi^‹‹Ã½ÝL¸×i5.q#ÈH;€L®T0zÇwDÏÇþm_æ{ÞÐe`ALÍÁ;OMÍ"oT»åyžÉíyŠý»ÈèRÿ®roñó’"Ö"igþ×Ñ­xïWÝ3ý`Àkq\é0wÇØÙöX0ö9–“Ûž¯kå¥TïvÅçûV¹À«7£Ð™âN³ì´º™R„ Gr^Z­¥ªÞŠ0K¬Fa—U"ïs Ú'åA*Þ¹ikà1C•@¯qÛ/cOÇ ÓiwZÚÏ#e#È×çôþD;² S7gù øZ»)3Ë·Ö¯º÷EKŠ6[1ÙüÐ7«ÆM´²ioÑÏ[E}ýáRÚʵˆ¨'ìwôÛâ˜âˆf‚ýÀ=¦“/m£wPê’ÜnUÁÁʇ•È}Ñ=Íp.HMÅë-„?ã¦)@¢ç¯Ž¨±ÖR”M=?SÕýÔîBò˜å@K\ìð˜ øÂj¼ˆükñÈ ˆÔkIœÕ£xãžmN óKÐÃB|a§¹Ù|vÌ/}ó°èÅ¥wª ÓAý¾”{ÝõcÝDK×,ƒ'Ê„Ó>†Œ[k5."¾›K¿ó £o´™?!lñq6l]§É©áWÛv#™D¨V8KJtž *-9Oì ¬glp1íi‚(7Þk¤)ç Ë03@ưp£½‡Å–ÄæzÈ2 T®Œ¯íVTyNÅý„È` ±Öž2?š—y/r(ty7ZuËJ0ß¹ Ó°AUÛyÅ¡¶Ö•¢Òg Òÿ³^3<×MÕd Ò_¡ì OÇ<ç¾ ’>O*ýî!‰e ÙZ}xWC ”÷icxoGxM(b7£V*åyœ$«…Æ>“T/²º§ÛÊÖz®*Mü"µNmDwB›Ó¹>*1%KBëéXN'€üp§µEiY%–T¾[ƺ…¦JŒ¢úV—9_†z?A_~¾¶b…â0­7;°j¡o¿C‰ÄSAËd7qa5\Óª¼«+]uU™!ñm:ÄÒ)V ¡[ê’>ÙÚþfÝrñe 4²P“¡ËåÒLÓ^,Ü…/ª'LÍ ˆŸoEæ;˜Õðh•~ÉxÍÔŠBÞħ¤Æn…Ðg pm4ØËm¯u>ÓÓ¹"µœÓ¦¶ˆJr~‚¦Þÿ­Ò¡ÍÚ%^j~z¯£—òÓ²1¸R'P/Y»ÏýÀN÷õ}©NæI)éB¬ŒËÜh J?äµ.Sˆø±ªvÆ]Ù<}]-L“ˆ¸ü—çu­’)ÍwÌû:VÛO]Îé;í)ôú¹52å>Î}ý\«iI%D?_ðÝS´%=³,ýßz:;JLèóÍI¦tõŒWt¯é£ìW|¯é)1¯4ANª³â¸~Ñ+¾õU º5¯´ ƒ‰~Iˆ§ÒMÃ"ƒ X¶ MÎ8ÞÌUæÖR0˦TRýì??–ƒÍ­uKC/h(PèV©=æ6fvr³l©é)ÉûÙ O¨@ìIÅJxž(h‚Ç©°ÍòòpEûp–M©µiI±–d;w)+x—^AVMˆ‰Çñ6²q².(˜eó6ªò…[—SF{‡³lš:í(º¿_Bèûsb}R>+f‘³€˜˜)÷¼Ø³â|zw¶æ*.-Dz{\»hÓ@“Tv¿³¶É–Ü÷j ôùµæ7vÇÞºÏÃëy[ó ßúç½™…Ï­_O@Ü‚~\íÝ0z¡»ªÆ´øúÜ R>>µÜ. ü£¾ j7ƒZ®úG}ÔòŠ(ôú:¨åò!ïõÍZ|¹°»Ÿ¯‹ª›Ø•aÕíõ¾©jÈ^„«+¼Ïº=òk¥çÀE’ɫ־Mïlj­Œ–ä#b|ž×Æét¡wÐJæÿ¤¦Nñ™mMÙ #H¶EVõ{^¹äí©}r´Ç¬ä©&YõŽ÷öÔ>­öìu²ƒÕŒº}ìPû>¥Å´ûõ讑í{.õÔ;÷|©…È;÷|U÷^y裚«~‘Øš)^Ü~ûNγ˜`£¡×ˆ|òwÎMÍç\Dºù¼ ÏËÝžV´sïûûy¯ðã»ot¯ðãë²ot¯ðã¿òÁ á7…‘a0€Lk3g¥ØCæÍ=£|»ssž)̪j2üvO9+™íÑUÙÃABGʑǔ¤œZ$NC ‰·+·Ô)yLB7ç%aÏOäÑK »fr„¨7t«³„­c¼Òãp1Æ;Pãùó×)¨©·1Û§h¯Oä4Û4¥î[èc¯ZÁÓÿ9slÔ'¡¯–B,.}€Z‰NC—9[¤[¼¦Gô]~a:hã8!~ŠsÏSdKJÙ¥ ÄÁë÷®±æ§8]£›‘é”Ýï® õ~_ÎŒsiw2Ù_O 7[Þ Ïdfõ8Úy™ôç´Ü?ŒQˆÝÀÓŸŸãºt’¶|ƶÀ_O|9­²Æ’Éý!³sê§É¾Z¨LÎÒ/õÓd"Sþ5"ü2®DH†ƒž~]óL~•,L©«:"ã9ÜnFxí×l¶*©î§IŽ˜søëï+™߸HCã †9nùXåóx8dt–£4Íy±˜[´p€­-StÖmËg2õùÁ¼Õ…̺ž¦zÈ仸“ˆëݯÇ'Æ”b«¹â5[üÓŒodœUc "ão©ÛV‘úí´b~ÿ¸Ùe{чdîd xb“DÉÛ1¯üýL.­¿{`º‘þÜZ­­ôŸqm%°òœòÆI¦á4Ùß?N¦Lµõ•¼ £i~] 'Z{ ƒŒa«RÓ‹äû[ÓÅ= 2ùÞH'’ªyÕW8ä+h¤)óóÒä>Ê4ØpÀÄúÏ|ÀDBå#ý íF発ì}YBáÓ”Íܽq³ˆtmLƒEÊhÑ7"#Ïæ•×.¼öl"؆S0#¦ŒÍž¼.[¶a_Q€Œ\ù¼Pï0–È1“ôyÈ8¿+=D¨$ÖqYž ‚Ú¨²àVlÕÊÖžuùt¥Î\l µc§ßi?/ð˜êÏe~š[Ï;‘u´E=U é—}¾÷ˆ‰}ޥ׷ݻˎZ,:ˆ|»*£œQÅû^$Æ,+Ö‚À;ÿóUpd:Äר½Ä‹ZûŒXí3:Mn»yħg]b:Ã=­·‘í cåOcÂŽdtm7èSd>a—A>N:e3d¹òT¹ønï5HÿàÅõ¨T®g™"íÌÆ‹© ç%R•­eæµ”ù,òȼÈÔ˜ëÊ ÙN‡ØoxÑ×3@¾\yWG â°Õ”MEÝç§kbÜÖrp•»ôñ¼bôÎ(éãª*¡zîÁ£AÆÖ¯5ÔOìñAójtw}ŒL[M©FYlÈÈk—[Jºrh+ÚÌ}<éyÕa=.V]±gmCz€„Ç$¦;ßÙÜÔð˜á&BL(¾v8?Ä?dÆó”ì…@VÙÏð˜O_;“{²á•á|`¼†ç‰}OCtk‘ó£ì+€L/ư+ºqxÌø÷9$9)!òøÝuû‘ÍËNÞï ¡«õ_Sæ!¦Ì3ðyXªôB‰­õCÁê3TÏJ©yi¹Î,ÛøÖ ýéÑÇv»Pbõº²l;Wí°ÐäË+2Q9ç;úoÍëš`•IËÙ>^ç¬iŠ4lß±[&ïÓÔ€ÛCO ‘¨@däØã¥¢sªy;$9¡:2Eæ×·mc‹ØÓz€LdGG"U°ªò”¥ÝÖªêð\¤–ÑÖ£(&å_ůouç¿JÑÏY,×\|É«’S‘ô;äã‰uC»¬zñçbŒ`‚Õ§ü9æœw´Ë2v6C.SØÆ|ëöº³Æ4˜`U¦×Þ"^ü:Ép¹@ä3Ðù1HùëdÃ#¯…wÈ—|ÃÝâGL°Bù‰”B°'äë‚j-7fwžÑM‹j`›#¨¦Qtm&ÙœÎv$âK ZĶn‹®ò”I[=:º\%·ômO;M£ç­V˜ˆÝ– ó*A‹ŒÎå}Q(ÅÿQX^hG ò‚Ȳ¡ý|E÷Rü­ýK£,bºØR#®»£{F¯kЍøtOŽœ›6X_ȹ’‘q8Í„­ñÇ2Sš»]1zŸˆK¡­§Êe^Ñ•¥¯ˆ–Eâ³ ‘ñ%©Ð¯ºøT“q¤*6źm×ÑÞùøSNY;Ëø_~Ž #{EŠèmÆî¶/â &€Œh’î«BÓ‘ásœdZÖ–˜|Sº“‹ûxƾÔd5ÔuÑT!1^\ÜGçeœŸrY†z±lƒ|Ú¼XP•ÊQ.–Þ8÷¬†W„>_¦þãeŠ/^&úñ2Å/Sûñ2žÜ–Þú±ô¼\zôcéÅ^ͬ¼õc幘«…G2½Yw=@¾ì§FÝ%SÂÁ¼å…LƒJ½‘#l@HÙàºÈý²O®dÈZ#ËØRqÚîó'À?ÓðYõœ’ø Ñ…P€LÂÑ@}Ì2+ÉÊŠ~‚ȧ+À+59ù4%k¿`´Ì6€T÷ó?Uè²R~b{aƒØá¥.ç×]D,‹mŒe•[!Oð©9mÌCd@FA®‚í0.Çtζ¹Èøû&:sN² “ ¬V¯0nÚJ„BÒé³ÈgÀ©2^ëkÛ ÅÌ…–ñÓ¯º_Ë çËÖ(f©VÝþŸ”FT:zâ×å0•È(ŠbHµ…ó?æ=RïæQfÝÎÙÎáy¾ÝÎ ¿ÆêDsÔ7$ïkˆ”[¸É Gl"lkË ÷¼$¹…¨ºŸ*£œ¶cêD‚¯Iná* ¬zc¬ÉÜm«] ~ú-\Cq¥Ù5¬ÝØX.ór:ªÎjÄMÕå y¶s¿ÛZàÓƒzè½Q¬çªÒÛƒ€ò¹ëŠ9Ï1„"OF1cb2ÊF2ê–”§Xè­DFörù•ãºQÚÓ™dtZ(ò˜z¡ }ñÕãgEÁ2¹|üŒC¤ºx¹á–Ž˜Ïg~´”÷~˳óȻ̪OS/SÊÅeÜÍw§nÙ~lì&Îçi*GV¸|ÖÍ#»Å'Khâ÷ÅâkZùê-ù¾XPbƒbðŠ‚eŠ ½áÓÖvrÂê—i¥hÊj•ˆÅ/•¢¼z³Lõ*!]%m V –©„ÖêLåúû?aW¶,+ª©K©Ç~ïÑý Ž (8÷ë/ Ó²ÔÞû5ƒRT` ™YÌóRŒæº¿¦ÿÊC 6J:õ4/ÅPt…ðüœ±åbÒ%uóŸ\Œ”Û€o`HÞÉe룂r¨Æ¦ª…wrUEÛfäùºÈðN¸¨öýýU1Ú“^c!Ø4­¶E= M*÷wï¶„ “¯”…&•ê×id+¯ä“DK]UÝØ|M-zÞ5E°ÑÏgô¼kŠ˜=g?‰žwMœ¸fNƒŒ.‰e®=5‰^×TN@,3È Õ2}»h1zÿ6ÜVF´¸$Ñ}‹ ýuFÐ iWt‘CS“Ê*Z7fû+•WÑ+d±‰5MåÒ-XgrJÍ^ÑÝùMÓ·íBr€|;æRYyîªÚúiº†÷$¤ïGá]/@)wQÖ5®q% iÁ. 0ýŒ£òªqÇÁèÒ0Åö¹H9º6L™€a_Ún«nM_Æ•³ L<ÕXwÔn ¸{u`f³ËËyª±ïŸßÍ)QÄÜÉåR<ÕØ)õYcVU²HÛ­È@€[[Z”3Ms¬EpµÉ «((¶rWV¯ÀV»ÞO£#“Û69!bƒ|_)mÌ$º1ÏÝBóÜäó¸ÿâÆòõ«ö/jÿÉçy¡ö¯3ÌÚâ Äçjÿ>‡öy^ÕåÕ[§,2Ýu¾nmzZêrSŸ×9uô-mÉ )Y¹´ånj(Ÿ{•²Aîø@^Ýò´uU×ÔÉvv‹Êosy¸æ · ½¡ÏžH2ÎMÓÉ ¹I¦ÌbvËÞX™êÀ_O ;rî³± ™")6<¤biäÖ Çtæ&©–UÐw-x= Ë ò{fÈÛ³5â8ó0á¥M:áµÉÝZ  ÝÃäwÛäýSjj.ç>ã)¼'Û®ÅÐ,#¼–O¨RëSi¡oOÚ[° hlúaÇ+‚…V4—›RZÌ|ÂSu5L=èu«Þ*y÷+kV¯¬P6'í—|`› ´li™\È]òñµ¶ƒ¥M>è^ÚÏ7B}¾÷Ò~Â5–}n80K1¯Ä=þøžã0’ÐÍÔæœˆ=†ŽB5½ZäIª7D:wXƒt­‡:÷ _“B¾"C•v®òÃÅqÏÝ?¼:­ù¼`¾ø—Çl2óE¾¢».‚øÙ—¹ê"ØY]¶ñÌ‘ 2 õnÙ=óÊ1+÷ÞÅ/XM.TÚ^—‹mÄk޹kV‹_‡b•ŒR«Ýùi¦¬§ëš¤+V底S{±´a˜÷‡ëD²Þi·-+(£Ì±z ò>«Úh°‘°º„o¿çÊšÚ·z­Ä eÂ%» Ô‡vùθW×:”rņB½5GnŽJîŠ0  „¾×¶ž×–Ês.eíqÔÈ'í¾+?«¥WñÕaÔ‡V–'É—¥ŸD5Fƒ4ee¡E×g¿Ð$d ›œw^¶x[Û>‚ òO–(^Ídc*#¡_[H÷ƒ±>ÌÈ 8KÅ¡ïGÐò´'–”ˆDÕ3Æ×Ãbõ x½xÙ o±âqLè+©Ú&Œ¦C- {–ÚÞÖ.ö­„;k*&8ï K YWÈÝ}ËœÁeèý±yÕtï i/pìÛ¥`•ŽÚôm×M2ÊÍáðNΞ”›¤_ÝÞ'fGÆB™CúFËøÚ—ž*nŠp«øsy<×’ÆÌí¾ñçúxt^’Ký”]çÅ[%^?å‚ãÒŠqr힪‚1ÑM˜[ÑÖyc&1:J˜ûrôÊÑñ]9š†åèø¾½ùrt  â¤ë­3ü¸©hÏ^g âáõúƒ°Ÿa¨RY9þ¬YY¶a=,Q 5'5˜>Ài+ÅBKÚí šåÔßTHßÿK{`ãgB»t.ÓѵÓ|ìOÛN£djóž D¾ifÛ'ߊ²À@F@àR¯"r̪CÑÁ1 6©¢NIqxÏ÷å·òÊ ÞQyäS¹Á_O|Ú±0½¨Ã<©0µ²®¤‰¼Q¶1æÑŒ=Þ³[À¿Þ]a3Ì×ý‘3ßÔ]‰WøëûKbÿ++ð^6i;;" }z¦“¶¼‘hE Ï&‘¹0åû^’3ƒ/ßøl¸1aãÿ¯ r {¤ MîÜê jT³vëɯ^ià—:ʵ‘¸ñûþ1¨1Ô12ÝáäÆˆxºÃÉ7ºÕ=/èlŸƒ­\«Ï–î:?·¶r^ß3 Õ NøKÞ. ùÆ÷ü%ÏJúQ/8ð—‚;НÛ„jp;]¨Iðk;“_T5  ­W¶©ScO¾ (V§Z ~_š”DÒèsèßä`/\TÆä 3uòÔð@“@ç›ÊÒZ „´“êºÈØÕO\+‡!‘‹ ^gÌ ô^£Ì †1'‡{ß›‹Õw¬ï\«€±’Èç%BM‚³2¬ÏŠ|ѽ¢®/Æ’ÿ Ùh„âgd´Å«ï(Àz¤’¥t[ ˆ ±Fî#!}9€ ÈöüOø6÷}ߺHÁ;Ÿh\êʹwØÛq4ÖY&y`nœÂ;zܬ`Àž…f°ûWlî]~X0ÞÚ{G¡,,ØŽ (Ø¢n ¶*gl ›ÿÙ…w‰M];+œN.z| nf±oÇŠ¾£ °ÝÈòu¦»£3Ìéîä;hJªL«Ñ2—U¶öVàÁ ]ÁV÷Œ†VMfÌÊyÈOÀÄ+¬–f¡–AÆ^ËG!w-ÌB-ƒL®zøFàu:Wç´Ð/Ý”„éÈåç'òfwwí™–¦Xž2v˜ùG¸ÇîÉ«F`>ñ4³-³ ¶cÝ'¡¯§´™ }y%DcU³b›äŽ8[±/ }ŸôjË€›¼ï.„Öƒ ^¼[û˜’ÿØj(È‹Í3ÜjÐ.ö€ñ>,X¤“CÂ`E˵蠿•K8É9€ÓR§š´(ºb¼Ã1CZ+6Â˦‹‘oéë[:3£ Êø¼@úòVV3õ–B)#+DÆ¿š¬šùŽ ô‚•]k Â¶°›7©|ýà]t*¤©Ü•[€üž³ý[Êo)œùÇYûjýÀ[ §þù¼`ñ+¹šÃótÅ彟neL¹áU|‚Ð÷ESƒ|÷æ4rÝÿ™åÇËQ[JiÖÁé7 ¿:|¤Óá¶â“þ‡¡Ø„GÝB MBuÐãèÞ%ÃÆ>Õ'òUxËú/6©SùI¹kýÞqºçÑiVä ²ª]´e‡c¾¡¶°yý*ÎË®cF§"#Y£(Žù¹™¨8üzì«•…²µügyÖ))@&!ý;úó°tƒ¿Ž~…K”Xek*à˜ß+á’fô;ó7†8ö̦©O£@ä$áV wxC¡"ˆ’öTl]½–±N^t-&+=…E¿þ÷oÀïl›T¹ŸÁ2P“RbâºQcZêzK{F¿Š 51ÚKxé˜Î@z×Su™»D­EF OxÒ­æI/®cŠ Z–¢ÌK[VÒŠ j»7:w*A”§%¥kv˜%~ Ÿ¢¡ ·mšvðŽ¾¾üdäœå‡D¹”c gþqÙ<<ø×A®,äœtþÁßx•¨mÙÅK(Pùó÷¿¡±šI”½¿ùÌq'ìfXDÕ×4‹‹t –›õFÆ`£2˜éØAjÝÓS [>ùHÕ #O±ÌKbØVʇ{muÖ Írû—Yn+m¯&RÂi0Ÿ— Ãc£Õ‰mL‹žñeíM«O#D^úuøL+ ô3ÎgÞrè?f~lòdæ•=œyt?ó.Ca'3¯Ç3îgžP8fìéäöŽŠ­)ðÖ¤þ޾âùéÖÚ@ÀAU€r7Ÿ-£)£,õÏÈïHçÈØ'VéDé—Éé\@~NLÕ›SdlŸ{ž[‚¼üuÂò•¸ë ¤Αî:_ Ö£ëO;å‰4_©kB6È÷%Òo¯Çí½S‘ €¼¼÷d °‚qik0˜©ŒûõçÅZ§Û€é¸¸ìéä°#aëIéN À~]Ÿn\NPoi[lð×£³öÚ‰­9IÝ6ãÅ+ÎÏ΂yñŠŸ³QgW+B^¼â¤ZCÄäÚ×뺊¬Dá\×z½¯5ÛSzÁFqPQƒy‡×Y£øÎΗ'ð¬êýÓü\ b(—-æºÐ+¾øu¡d=ƒzz%×­ï£n}wc¢›€¬ÉµÏ±î÷¾r×^KÓ^ˆ¼0ÂÏ,mz–2 /+®˜:É”¦V‡°Îõm Ð Z×°í!lV’ž ÷«b`ýl,¬ ã²-¢îûYÀ_7~2!RnZº–nÍ Ï,n‰ÿõçµÅmZsR¸u>zø³—Œ¤§“µs›»ï(zøó¿}‡5&õÙ´E¾P€ŒŽÆâ:ϨBµ²°G«÷ëÂ#Q¿ó‚ˆqÈWÐ}l='7"·8ù-q€|-Èu÷€² wÝ(P8­¤~>ßGMfuüÕ§‹&“AOãßèèÔgÍr/¦t¹ûÞ°³²Ï½Qñ¥Â?÷è¨"æ‰!ð‹{ßÕBAQôޝ»î4Ì}›ïäR÷´]µ½tØ„œLIPâÄ*QèÈj4®KÓ=Sž§®“ެPãZgáUÔý4k<ª*‘?©¾PA‡³¤;ºÜ,}ïzó5l]wñ7Šdä×Ïè®K¬¢‹3¾GÑóÎóB]§¥èu]ͺî(zßô& ååh¿ŽÒxìð`¡˜Š¢£7¦'mÅDœN5¿†.ND Eñ‹ëY'o§§ýò°$p’4ȜΞ¤ª6ië(‚'ÿ,·5*AeÅ[§¢äÒ¤ÑDZÿ† » ™zJ @ž842ãÐèN!YO‡å¸Ü¥Gåi­Ãœúˆ/ºêõTNÊËÑ­óÑ÷§Šik¨`® Ïãîl0WÐçÎˑߋ>ÿ%tì¾÷Ï »Hêó_BÇîø¹:&¡cƒŒÂþ<²3"Æ™dJÐÈ]眓µžŽQvä„6¤·&Wù Ä”ÔÁ[›à‘¥aSnÅè ò}Ñ3­VwGÑm‡±üŠ)@z&Ð¯SÅq'–ÏçH4»6£k³ŽKy@BÆRe%g _Š"ß§ÊÿJws»á'¬<ý(ÿÏMë²_yR'¥ªŒ%Rlb˜K;5ÈØ'ƒ,PÆ;œg20åi„¤ êª¨Ú6­zè´ÚÊFž¹* ý`SŸü:êЩ}]P(~lJ·~~’ƒl56$âR/º /.†ý… ·TS·b\8¦q}TÙleÕ î'ºæþ¹'W;¬n|óòzèƒnzú•´‚]®`:æòçÏ÷ÇÉܬ!ò ˜çT¸5$~iû•sÉyÎ\Š×bBÞ‘/gÄ¡¨ã?š˜¬ãçzæ½Æ*‰]CâÐqýoGa®w$O} 0êv'… 0ömßV3…c¾½¨caLÚ4’,c ‘‘u,¬ƒBVãàV›€QwŠ–"ƒFCÖÄþú°ŒËÉr‘H ÈéKå™ «‹BF@–r+–ÈÖz9"À¨ÛÜTGm³<+¶YÓ}^BYWCè Bõ£×Ð5#„Ý‘ÊLRërq’5MµVB£Sh¥¡pRŸAë[µÓÂI› ™j@Ë+¡3?‡&¥¹¿Ñ͸ GVE€¦©Ÿk›•ÕJ«æx­ß_èÌO¡¯‡oæ´íoå6M˜vÝ:ChàZ¡¿b£M_)9õ”š\Ií•ÜBó˜e „¾ÿÓtÒ¦ò0*‘p^hý4eǶgkãôl`Ô9¨î8`)æœ5ÇQã_èœC½šXnÙ3/Rù´Šr€Poš›F¬zØÒ%Û†¥/ 4ä?šïU¾„2®Ü¶Bßkè\BèÓS%­ž³|Zªyj\àÊòÔ kþ(l3rù¡o }¦Ó^ƒ< ¬«Œ×%5”VJZýØî­ÊµsÊD£Î0‹¨FM»B‰ôAhòfˆÑ¾RžNOëí*ú~J%Œ¸¬Ëz˜×¯3VÍMjV½Ú3,?Ì@´;Ú¨ CØûë’^Ôs¢ÈkôF€Œ[×)3À~0‘#weyiæµÍZÅ©o*¸GokšÙPKÕ¾;¶ÉHÞVyµ0²3‚ê¶•!Ü$Èp^#/íUVÕ®{¸)m§±âüp­»¶×¦u°Ì#ئ’<å+Ü`¢Ä‹ÀªMM%(ÅNwÞBÑeJsô×ú¾5{o|Q&ŽîëÊ>ŒŠ£{m+×¼ˆnH•› É}é*þ(ˆ•á´Êá0Í6Ÿ*Œ¯[Qµº”/ðÅɽº”Šãä^]ÊLãäV]êgÌè"xW j7Kè’p2i‰G~/e'vÊÇyžÞ!"ü,%‡Î{¥°¤_;u˜/q!¬Ô)J o äáÛµt£ÀrÜ$XäQE­h#Ç^~Sïc_˜61Ð}a–L’×és×­“º/Ìêñ¢€¬x’`i:îVÈäu©\¤Õºü×ÒuŠXË hÉœ.Mºº'A±*‡Ù²]:‹LÆ@¾~‚!·ƒHS¹â¸ð$ ÄFü¾=(õmº–­+/&Ññ­ J-ÊØ•™’K Ø$Ò â^çQªÚK•ú' ìA*/ÉeTª:†€|ýRy¬©`Ô¥¡Â$èÊ X(rŒkÃ=ö‚®Üí·~õ‰Ê€°w è6Š ;‘±mVV »ûf'gIéÓáÅ–„’›2“|œA*ù^¬´l·ñõ©­ä všÔý’|í±¡<þ{ÿ^¬KB]çèí†z\J…(Ôù`u ô# £í8þOØ•$IÊ3Ë+U&9 å¿mÖW3Ä$ì;ýÓ,´uY¯ÜHF)w]6Ñv¾t>E›ÚP Uqžà1Ǿ)“Bþþu§7Øgù<ûÔ,}€r™~š¦T-Ju&ð×ßQº2Ti^ó,S®ô ?WƳ×w²ÈotL3h£Ò|²Éˆ<÷Èç? þ>ÍO“›’;n¦ÐfJ_wVª¸¾ŒŸ¾¯IAš¤îWï4–-­@ª*îy(~FC€®æG÷U9"|ï‘5­øc<ûÌZ'©Ø`Þk ¬iµÇ„Þµõª8õ¸dóâKFi K1ÙRx M4XJ¯F‡câðï3oÂ7;¢1oÎêVÅvÚ—ÆG€(*eC›c5`S”ÞÛ‡H5Ä:•’ñN‘)úG)ÛKÓ¡Ÿ›Rv£KÙ ŸŽÈ‘«ØÆT¨hÃê²Ýú‰~~ËÈù™[R­eád Pì:jš2V£X‘dT»WD#<ïÌŸçoõÝÚQìcN–9äÉx•ŽX”esô!ôóú¥Dj| )d¨VÏ@&‘ÔŸm ,”7L#¯H®Âžg3³aæuÊ\ù¾Œ?}\‡~Þ÷ñ§ÏaQ<ÜõŸ%]èb“¢Räòý  -•B7ß­†½‹?Ã]zGñçŠ&óâI4þ×?Ñ…Úµs•Mø+ qÈÿû_4²Ö«L'z?:€~bõÝ?–¿®n¨rýl²½Ÿá1“ ¥ì|©Öº] “Á7vÈL¹+«FC÷Þ÷©Ï²>Û;€ŒªEc$Ùš¹šÅ&à “¸bëas[Ol&µÈ×Y夭Z±9ÈH¯²ÓNÞÌ:§|…çé5Ö¼9ªš]k:-í _ØuF‘튧|È44 KwEM¯s¹qö 8o˜x•â’€Œ¾£Ú í{?ö;¯˜ ížÉQ»ªr»\#wÃjf ÃZW8'¨O3•>@& .è¹gýµå5k¢ÚÔ™’Ôcù„I´y“ÙÜì½È{‡|ßsÈûðŒ¢ PüOG¥³_ÇÍ8zîЬ'ÿj¹+‰(F[—l!™Dª­‰Z$r¥ëHüõ×U$0àðëß µcþN&Wj@ÏôÒAsž=Åæš¦"úÊŒPNÅDûpç£èB¯´µ5gQ|ÚZ.¡=D&§e+®ÊVáŠà<®é¢d±ª)œžäûœq-rìÎ,òsɸö-‹´åç+®c~‘™`xžéEyMq³!¦‡€)ŠâùŽM?ÍÒ4ÙUÙ_÷gîi†iˆSe7áõYPrm"#‘ûì-\Q<ð«ÑÆùT†c¾ ‰•¤ÞE»ìÓÖû;¹»ŒÎÎ…WôCÉû²½Ë‹%Ÿ°¸9DÞ%|Ê™|ïìk%šú;Ÿ^¬!ÍÜñ¥Þ Ÿô˜öð¹ë6Ÿ»ö×îaÜXGiªÇ´õþ½ž·zL$|ï¯ç›íboËWôKè•üV345&¥ØË¯fh‘ç…¦ ‘ɉK¼|çåCÂNY½^¿¾ŽÆÍˆ1–1æË,{ÿ)ÿ|™å`!g‰¬!ò¾MýØåÏE>{F«E¾R R) Mt`ƒÈÏù¯×ò×}¦ <Òª)µ|Bi–;dT®ücî§•—ÈEž„c¶¡0pzÌŒ„c~ÝÏ9×drdaù:”ýÍœ”\jkîç÷Wì!YbïWÔ6ýóŸ½öÚ_»üu?C¤ª†–Í[çM³U[ ‡kwÏhS/^‡wÉ]{-ŸÑ ýð.©LƼKd#@Þ%…4ïRÅ*Ÿ«ó¬¦pžèä¹;d¦®ÈÒ$ÐûçfÚQYùõóý¸Ym” –ÏÞ‘•üÞu9ÝΨºw9úü=²²Êwî]Rȉ-#Èçé|ÇXpÖù•öýºïѽîìÔq ¡÷]as(÷é¿ß×súªVň?ÿKõOFé[Çü}oUÿâ+úÞhæ ÷jz(ðçO4ò´¯?fzGßjw?©„"G“õ¨b¾þŒsyMdÂN E\wãq›7ö+ž™†l_€|Ue»31mAùÎ"ÐB²E]ÆÛqm× _WsÐQ\÷ù¹ÖÌU­CO¨@ï·oêLjrßôÏýsY³šŒÕ£¿ŸŸˆÂÜt >r#@Ÿ›I:0>ÉÍÄߎƒú¼nuá;Æ!òyVÙSŸ½BŸ÷µ&¦xõ43Ñö„«Ýßø;ÿ¹Öî_Õ÷æ3èà…p¦³OäË4dròmr¦¾Í•ù7ä{*×=ß\FŸh‡•û‘>¦ ­8Yû¥ ëü'=q¡Ð!u›T9Èç)Rv:"á»dæßr–Éö/`{gòMù|š¬ÚÂEeÿÓŠ®??袢KlE7ÜyôŠ®T#wO"jL£­\ËZL>ãû­HÕÛ¡³X5/³MgôýoréÌÌI¿“,ãÜY• ïã@nTrnz [¬cÙZAä3ž;3þÓŒÒjéºQ@$s3Ód Yí¥ð_ñ÷äÜŒS–%åc?”¾ºõ}t Kãª¬Ž™U½*hä'ܥ tÂÃÐ>CùFĤ¿®f˜6A»’À+J]©î§%üt-%yTåøa£?ºÝã´P Åbßûápí¦5óGn\GOdm‹Õó4Ôxríå§UIò¶•Ë-Wÿ8M‘”°ïꇪÐ÷y09p .ùö•2›ªüÖø¢',ÜÉ ô}“ƒ¬,û!+& #{;:drŸr†Tîûº)5Ì„xŠ t±4×½uͦÇd+ýàÂň±©µT+ÁzOI$å5E±Áƒ-û—¦`¨b JñÎ2úKo/±+E‡Í/õ±Áƒ=wRæµLÅ oˆ4r¨ I…ïr~#¿EUèPºŒÖFo—ÿhôŠ~¢Â‘i÷˜èŸ«QSåÁ2í3;;åÙ¶’}HtÍI Çüþƒ“Îó{ÁISÂJ1' E XØÀꚢè'æ2è›Þ£´O1Èç1*hÑ]Ðs*ÒŸ_%ü¯>üNwŒ&ÚŽÓÇÁѸ´Â¥2“òaswEé‘%bkB Ý›EÞ*€|º©Å•µîÃTF•{¸©ÿÞµø2¶vsÊèŠO¢çcYä˹úæUiŒÙÚ±Åý:lµã‹Z¤7žÁÖwF“SÎåÿiŒgþyWmÜÙ²=›†’–3¼¢ïé&[¨MÖ¿u±¹… þk#˧6Ùf›,DÞÏøì—eÅ!À‰Oú¾0%> ò*ÀPÑ:ÈälGS~ýs þëÒÍj¢Šf #ÛK>–W´Ud+÷39ªšˆ\i)D¾â½×̲¹h% ß§òSbËwL!ò72êÚ´à÷ãn=\û7ªòãÕrMœx(Õ¦Ÿ‹rºL|¸jfˆD d›#¢,7*6ÿ.}¯¦”ˆœðeê¦ÆjU´kÈ<Õ¼‡éÌV¤q6-´Ù gA‹b[ÓkÊÊ6ÅöY×I¡4½L· àH£ÝIìÛ ýܘÙT‘Ô LÝßâW@z ýfêZé-ÅA¥·P°LˆwC­»,wÃ-ç~ýDÏkÁq „PrS¢×‚0yc„  |1 ½oâ%µâø}N!µ½"åi²ö+ý¯œ­‰*kcÿˆ»bà>¡ˆY f^¹2ãºZÎv˦ "“hÖ¼Èú×I6ᑤw¿Ô»¶‰ÁÖ¦éf<ô @¾}j\VÖ¢†Wr©à}‚£½\éºÈ¼â-@~CA&B–“Ê)¢Ø6à“mÔøKQ¶mÆ ‘‘hï’Ä•¦pÔ6\AËe„wþ' SV6;íºvdt˜|†9 ƒÈÊ’&%²›EFýbˆ­YÛÑ¥“+ø¦:$™¸S¨7á±(ò‰Ÿo£4R!Ke#Õ¶àŠr&FOòCAÝR!™ª²ÂMÉÖNô©·í?–hfÜê¼4BˆšÂk׋²ŒüÒºùàq«hôÓ‘©#u¯²~œD`2ʼөX$ò³©:U7tž™Ì#êÓ äÉsfàÔ(j5Z¾¿ä}ßÔC ¡U2‡Fú¶§qíëù}j¨zLeÙXwRAû.˲°ŽD‚Û†ý¡SD³f“á€ÏÎcªrШ°HùpÇdd<\X õBd#˃@1Š=#ì|¸ûu‰Ä"ZœB'’UÀ¸.û¼ÍyHéœW¾'Å´ÖÙL„ý”ÑÏϱÚQ–F `Ö²ÚÄÖ€|†>geˆ"í2ÉŒ»æ.QpÈä<9–[ Ÿý1“¯}ØBrZt–­à•«¥Xçë$2ùpËsÙr2X‚§C¾€j‘Óã‘i_Evxžï«°“žçç<‰WõáÚ¿.¥°Š#ºg>q1ðÕn‰ —Mâ¥W^àŽ•d-ò´E­ñ‹ ©ÖÞÍ2ñ)-‹JõáIF' ýucÕTú¬¡•×ôrÈw¦vÔZF £zKòã¾8ÅW5KŽIá[ãÔ|%29lž.‰oæ¼Æó Ï ßz!.2‰]ÉkëÎYdÊ/<£ËŠgר´¯ÇU6Wá¹' r¦º•=O™Ææ9[ ò$J3A¡†lô|U‹ò1ž¬ß(Ï9ÛꜮ]—„&È–9È(ogÞ ËtHtÁÙ½Ó«D¾ŽãVƒŠ *§t(‘ï[äÔ3ˆ|^©¥~ýsÓÅRáŸæ+SÅ=É!ŸWìcêØÇ™ÞÔéUi‚ù_G7çªGÁÜsüæò˜=^^»Ü“&gl-‘›>’6?ôÈçÅú©‚zA‹•Ly²~½~’ÎßùGTlZÂL~A•ÖÈ×yoJ¦SÍ Ïó}êz9E®—yçz9×K‡¼t½NÉØ!“óÎ-WNÙþ˜wâƒÄSì¤ÈÿZ"ßÿð¿æù¼Lû\7X"?wrÜ—Í$ò{3ì»co#‘)\i½°S§…V'ì$‘–´sY.ù®¶íaØòÅ!­QÍ,D_OÙæ àeYd[o› Z€|ýÖ)’ Ã$f6Ôð×öQ PÚC[M‡ð4T¼,‹:£Œù8äà˜uéâÚem;¶MÛ@2 )šó,^ælÎ:øë(ÄŠAfç‚M>ÜùŸj§Ñå ešÒÔ3„>b¨‹Uû±á5=ž‘?§•–ÙdQÏ«h Ñj^ºtrÞù0”´ÀúŠ 6V²?uÅÄoÕã ä”ìQåQ­¢k ô à\å®d¥Ÿ<ô"kX+V·R~Ü÷4õtTãX`dªäb_Õýá¾"·Bi®£ITiÙ×C>Úä׿ý?g"Ms‰4yè#@ÍbÓòšËt[X¡Ï9¥l\"9%M"$ËþïØ¾o;þYVÓë¿X>¿“Ë)=¾£ºiý)5ïŽÌeŽ'ðñ†c¹ü®ŒßÖ†ÛTÁûj4½„Šr3çþ²³aaÖ]ÝCM¸ó÷¯ƒÚ › Mq/ Ó¦nª¹ê÷Š2ŸXhú[¦ŠLrƒåsõUƒ2·mÝ6Ÿ–½ï¦ú°b¿~H;ŽwÄz rÔy©g@Ýl·C&§Zñd¹D¾n'ËgG wÈëÐ+„ÇÏëÐKwé]·Á!/¼¤µ ‘?Ï_ÖV¡Aéå`¾åÍîߣL¾Õ3àŠŒ¶æ…hÒÖL!=Wžðxâ »J3óÒ•ÿX_ ¶ôlHhœbH¬çdjE ‘çÛX+„ù7ùZ[HÈ•†¤,9#ů>ìL®=Ù|PÅ"wÌävГW®6ï×´ îSƒÈð! ~ÙÐkÞsÚùo3yþ;«M·ã̸áé{ŪofË©»:ϵÄ3@&1Ò–F›iç D¾B¤®J[²hð"ö"\Ñó0]í\ÌTÁd“áñ‘‘‚£©XèÑ+,¿L òë”$ÔjÓº‘;E“z“ dûß_[¢¬‰7–a¯|E@¢ \•ç†(F‡%ÚKäï,—×N0>  šìkù’ÌÃ`ìÌq.öšÍ~ìÌ!ƒ¦ò:7ÓêlmkÁFÜä;(ÚÉUåšÙÖ´Â’À¹vÝiÑ)L··}½->0M’ˆ<¥£]KÞ—W„ë<ïŠ S׭ŶբŸ+g¹uW‰¼‹×U’ï3ž qÊpþÎÿÄÉT=¤ynŸ%/ Ö”çÎ5FY8T¤jˆ •ñÜŽ ©KjëA´åI|IæÁ«KªJ}Õ y§¤Ün±J( ™&6Ž~ K®ä)v½ØùÙj‰|ßËd…MîÚgDO*MŽ%+‘ßK–,3,YÏ«ðb5‹äŠqÍŽ5‹$ÝH¸†3¹kμq¹[‚œ#úyÅî`Ìkg§9-q1øó|AIìëÈ Ip7— “39/‚å7ß`ˆ4Ó͇ 5Žyž žçûH j-)hëü¶ýzœv–G­H' Ï©)Ú‰ÆWaþŸ°ëXzœÕ‚¯ôI¶–³ÿ§jæP(Q÷é/ަÊË.YÆÔÝ_¹Wêí!C…4aT™Á-³ã¬l£d‰®»B¾î¸¯Èü9«½ùyIv¬£®&CàJÈ’ä51éŦ ¨ët%奕ñëËŽ‹O2QOr¬ù~qN1»C†Rä4½› ×lÇ ów¬v͘VoäpÍÄÅèÔ®}!'±j•¬ðJ¸¦Ã!ÿýµj®{¡Ö“ R_§Q'*¯Ž·;^ª s?Ñj ,Y­&æ$®RâtÛìØD:®ÿ¬ñª9?Ǿî0ŸZвx;Á¾ Ík©×/F[-±ÝXÞK« ª€¼¼ã,©Ãýó'ò޸שÓ;®RñIDÎȉ$ñ(þ!"Ð"ÿ惣}týÿžø¡„ÀΑÕ'FÂÚ×/Œ*c]~{2vë™m¸&¨zeL8‹ÛyÚÜ<7=ô ‘‰ƒFãæHŒ›ÀFc_³¸Á“ÁÌÛ3m­Ê$xÍ0éé`bÊFµð¢ê@ÿdÜX“sÚ¬ZÉ>¼eŠ˜JkŸlj™ Çc%fxŸwŸxxV»>—ŽƒÑueð>Q®vJ8ZÀ\ sèþqì6Ì…›õÔNZi›ÂûŒæáºgE÷àò(%üñNÈû”š=§9ˆùrºjìÞ<½¥ÁÕ¡]š˜§œõ-¥”¥ä!ã-R*h“: Ù&FJþŠêp¦.0rmb¼„oOBëa¬ ß.Uç]\ÒGböñÇ6í¬–Ú†æ–·GÜJÄìÃ(×öšë„¦¥éc«¸8)P…ò•Ôº4?Uùùõä˜ !ÓíçEÁÏÖ…¥TQeÅDÈgnÙgTtÆÍ-±#|}Ñ0™|{öYwîÑíÌ28Ϻ ùç öðÝrhÒú2Á²ÓÄfN°«g8`÷Èâ=™&C{ïvy‘´rá ©ªjÜQhCÞ®/MPâ2¬^‰Û6TùbÕd­Ý9›%ßòœ†¸#TlÚØiž€¼¦DB§‰]QV®sØq·kTÂôH¯„YïÃ:×-@º!’?n•ÌËK õ,ó¶äýƒV*K^s©þ[­Ô¬ÞŠ:±ÄÒîÂÊßþ‘"…`àù1¡0¢=2è[*äãdµìƒU-ÅSîb8!f¦ k™hè2ų.ÒÙ>è£ ßÚL\êä"‹Wáµß­ðBøö/3ºÒÌè2€Ì?rHHcZþoÃ2°M¨Ñ("μóûè~¢š–M'*ÙÄ eÙdè+Ù9UÓ:fÄØ„€B¤ž¹îCãäî¨Ü«vì·dÚ§Ð ]•X\âLEêÙþGïÍÖ»ÐMN¨šÑpä-A:-Ê‘ÏG;¬¨¿ýþQ‡3YÏüÅÀŽKˆÐ(BCíû~9W­“÷©¡«U<°ûø­^¨Ÿ´ÇÕ¾ò:œ`÷ëKÝʾßÍÜïQ¶!`»_Ïsþ¸u6Ó¸]–f ã&÷+Íq š;ë(g1°¼_Af4ÆÛ 1.Yà·ßâ{íj‹jÇÓÁ¦"“0Ì1M‰zÞÊ…®(„Lùø4Z§bzxÍç[iÍà\O;÷û2¢ôb.wÿRåI]Üòö7‘ù§?¾'¡|¿Ÿìý†YY²’{CLl·|e^…œ«U “Þ Í—åF:€¼¾ÛZhCûð2ŽFï›îe¨ÙE£‚ÐǶ߾VMõBäy÷“ñ÷0MêS­ðÛqâÚ·{û^jq—ØÝï1R×Eú°JTe¼©ŸV鑈º•.}ЛSî[Ç»ø(Ç׌/~[ú“B¬_ªø%¯™€ÔP‹E¿ýšòÕéM-JžÏÈš6 “IâI24„UzœóÔÊô$hPx Ô‰MVQ|VÏiZ<‚ 27&`2|u•¡©Û”T,^tíì§á¸Il‘žxAðU,â`!¨M!¸ÐªÚ¦”íy|>m&g=®ÙPAä%¡¨¹¿Ö§s%8È8:Q7Ac±o¦£jÈ"ˆw[Ù1sÍmexoç oïCµH±bøÈÁÿ^…9b§IµWbÆû¸|¨Ñ늡®Ñ‡ÒãòR1ŒHDà5/¯ÈÙÕýO×¼úÙyW¿p÷ÉZ­tù¶»C­ùQî €¼ÙVÆÖž¥Pã,Ä‘÷ÏÈÐà}„FÊ{—øFx\¿ë¼ÄDîq}S‰3©Ô8hâ¥!¨M¨‰&Ý­ÃÊS´,ÇBDæÑ'U+ÏšÄXl]w ->!ÅY)À×ô\ö6nœ@^cH훇+ëdÉDÙÃktÜÚM2xŸ·˜FVn ‹o£®ÔM÷ÓîÀf®¨al/O«ôˆ“æ-é|¥x]Ù6wð=£ë­Ól׊*Üf.áÊÿ|QVxxD`(pQV™BÈ<ǧͯtfŒc3!28 W!Ÿ£þ D^£kÏ8R—™YÄ<2ÎI©\îãDSÂà|5ÝUÏ\²™È¡´}«5Må†`Þ ‡ÒS¥þã+ÿBêGR©œ… ÔAÅ¿f,›Tê'14Véÿû[…®±>n¤œh¨E%*¿ý‹[„ñ“J>€¼Æ€*X¿¼jUÂé«çé¨u¹Že7®„Å-÷â˜ÔX‹N=uS6¨¯íG*LòÛª¡rGßnˆÓ:vöpðÕьѴŠ6Z‡ éq¢ÿT¦ÔšpmYÊRÅ«yK­D-EMb¯).‡ ¡ÚȪpMðƒ=¼ÏGTm÷]Y‹–ãzÖdð5ÎGªËjäX!~H¸ò?ž…’f*d3…³!µ¤Ñ¥†:ô.çM¶ƒJF€´‘Ý¡·qåR9ìs­ ‘Îüë—8$VØŸnó¢¶…ÈÎEl®?"§èT€ÕiÁDÏ#oŸœ¦G6ç3ûbt8E’¯GžzX& 3‡Ã©ÉŽåü¹I"sØî‘9äÀ8U+4|=j€¼¤Hw0Uêû÷u ¯1 óó›¤â¼¢³à@°ÛeÞðk-qwa<è_LœÞx)aÔÞÕñß< ¾4ÞÁÙ y¿”ùHu¥œˆó‚ør ýØä3ŒÄêHÙEµÃB…ˆ‡È3:8[^è%µéW”€Ð,µÅoÊñ¾°ªãðû-3ÒÎc6~Ìô(ɺ¨ ­…ÐËûn`áË>Z«© ƒBæ_V)Q,UHhÚd¢¦¸ÉÕªËÓ% ß´¦:;ï…)ZkÖ„_T¼ ÝiChË~õ%õ,õ½°œTgó£Î‹ ×5@^` Ø6 0¥h®‰ÈÄ"Üô-Uár%@i“À*«D/;a¨È[òžÃÞ`Å;U5ä¸çtšÍ°a• ËÁà}>R¤¾ 6Ò9Ë4ŽñßLò¾¿¿lÇÎ{-Rå¥ +ÿ¡­!-œ`Fûùµê‘[¨Õíd›‚6ëØ@h¡ÄymLÅêllÈéªÁGÅ ¸Ø¡ßp©ÞL„^ã|A븊–«}¬|ÚC µÊõ©8\Õ,qÞkìs¯}–´<õ(Néý$ý¡+‚­Ê|›ˆB©5޵ÊPWÝX¹·ýé^ŸQáÕsª´iV%ª­ÞàÓÿsR±–v["ü ,§êÿóŽ6MWÐUå€ð^ótÂ=¬=ꛕ–ë7U~ Œ¢¦õŒ"u I& þ[ùõ £håíÒ¬³l!´Â]—á _Ñ!0;Ðpª¼ƒ”•¶Ð÷ºVû^U;„ÞhçæùP3·¥#ü òG€¶N¬“\C]õt¯–S¥ûV&Qÿ,ÄGª —K`A®QˆuÿOAUr ÿØK拨Õnݶ­§°M?BÍ¿õ÷?wv]‘z—« ¢„¶æT9žRíu]vB6ý±;]ï½SÂ6Ð}çzÜÙ—ï=´ø¨‡˜äYvû®‡&T³Äý'j€c뀳‚–8\óþ:Û†þùéý“¨šÿω)ÙÍÂi¿ §ðíÏW#B7/§bÃãƒd´Ð mwé •kHräª1§ÛLÇ‘‡]ÉTêËÿh>cÉÍõ°JA_ÖqÈüD€ÑûdÈA{ê¹² ©26ÏÒÈN Reì*iY\²lËÅ;á8¬•iÃôx–òãÐn ©ÒA–ŸLêë¦ÃÎԲߧ}¾.ž¥¤/gî”ü—~8–É óèZâÌj´ß¼,l@ /ÑÏM…è")jÛVì ¯ñ}N,Y;v¡Y|ŠLEŒLóËG÷ŠqmÝ3óÈëg%j)‘àñš×/„7­>žä”ö¢ž ÕgÂ>Ê‹¯ê bðš—J1Gˆ‹ó⣮¸¸cçû,RqT?F̉:›ùêc®Ä¥ÈK̹!Ÿ–HÖ.1Ëo`xÆú¬™ˆÓ\“†*Y–§sÑFÐ1¾ ©¸®¿, ó§"ļìì=TûÁ¶qV骊zâ~‡ZÐÖ–Át9(G=CCüv¨¸„ª¶õ:ÃŒR“ä'±Ä…ôñ>Ÿ<¼,’#¼æ[±ÄI½<bðš·OHIxÍ{ì]“7ó‹Š1š}©=‹ÞCïi«1wI…ö_†¾ˆíY§²Û®[¦=<ó'ºÝÉýGÒ&äÖ—ì4EŒ]£¶æ °÷×óÈË«ÍñÖŠaǸöU\‡tŠhú-ƒÃ>“`{ t/Ù~ÎYÕSOÚKþÍÎ>úï(äåœ9QG)E¿ Y†ü2á=¹9¯YÍf¬U¸ã/ºB¹´!1IÑ"¯p‘]Нnž¿ý(¿ýöªïÆ›§G^^Ý}{T4 U"=Fª¢ 4"€|D•1°hHÏéöMXävÃ|Ín\*¿òA!#ºVkK ±¼@÷¦Ë<'ÙN²®ëðýÙ™+ÓX­BBÚíh 6€Ìc«ÔÏp¨¯GµP9½È ô†õ§Õà»þy=Ù¿Û ]Û®Í1ÁûL›ªnʧÆZöåðºŸy‹Ê;^ N.C/ZA{xŸ÷_øí¡p5 hŸò‘L89bu×´´}M @>Óú ·j_WµUD½Â•ÿ‰Z4.î(–×Ä!ÊÈšrÖV×[µ×C¡y µ·º‘uUïä®åzôfs¯ÍŽE M½ t¨ðÃþéOMÆÝ,õ:­Õ„qµ·½RmÝëk%Õ¾í jÓy£ïêêDÓØ5²© ôâ‹9:W³#Ú A½úïÊÓ°•/+ƒÝüÃ6÷=­Új<ý¬"…Z C¿Î >öÐcõÐ["“k}Ö;¹¡FVSÓÁmßQY×y‡P‡÷uþJ±µçíï»~º«ŸVàùê,KŒøÇP…JAdüš¸°4y %ä.Û–Æ÷ÙG%ÂŒB[ÈÙ®×/®Z¨côoýÄ0Tˆ:#tNhÓLLìá'Ý>÷X9ç$Ö’"“Öú‚Ž}#jLwÎÛðPßO_¨¨ZÓiŒñAÂým¦=R3먮h0€ÌýüGUùª“B’v™HD>áÊW>ÇX—…ŒÕNBlt}~ÎW¹ 9ˆŸ/ÍŠ7žÓÎ+W­Q5¢ÝGäū紛rlcå0œ9œ×5}±í’ ¤yIò×A“²[»]ÐyH¯Ú£wdtìu˜Ï²HFùõ—é캓B;xÍ›çí—ažFEó>ª•§,O¬{Ï…ÐZ%D>|}*"i)1ÚÔ>‚÷ù|Õ­Ìœ­$—Û7´÷rœÔQÐßÎÊn¼†¢~=–B³ô¯·ó7ZsºÔµ¸¢Yþ§J’‚Zb¹ÿ2~ìtöÛÖzŠ ÌG¹ªƒÎVV\¿øU®ÅC³µ¸¾m²wn ƒÆB@Q|àӚ៊Õ¶¬¸}àÓZ¡"B &!±¿ãÓr ‘Ä~òÿ°~‹5 ú×ñÛ l›Ê l ×óqoð«´êí…­©,5¼üå4Û:«õ´·¬o‚ȸéÂhwoG»û~{²éìð~3š™˜£ëÖµÛòƒö‹ ßâªí‘kG¦ñ$Q³É ï>z6ÆðVbŒM“江t’Í©ñsNW¦ŽÒ msñé™òz_·õtM³éLwËÕ`죬BÌKŸÑ?^ŠÍNeŽb¨‚jiD÷_ÿó5-Ó_c¥®ZxM×_²rO6ÄåcMز!Úä5v¢ÌŸd&w‡æX'ê‡l²xU±J-B†¨1õ5Dÿ¶ñD,hi²™Túkgʤç÷p9á­pûÛø4gJâ|Xv˾šÉô±ËqƒQ²¹éœl²Ã¨ íú„Ân-Ë*÷‹ôpõ1²XýJ)ì¿~'Þ ¤bï¼+@Âáj³çÌp5–Û¯ÖN×yJ·Ê|¹AGSÑâ«Ë$òrv[©›º&V; ï±.Þ: ¾O†ñ*¾·øöúê*æUS!¦oyúEÏÀШMŸG"†NHWðmMÛ¤ÖT¼‰“bÜ.`ìKÓ)'`¥"‘J{Ǥ=•7°mÎZ¸íL"J(@^Þj Ä£’¦C^ßʈÿŸ°+YvF‚¿ô,lcû>/bæ0db3 è¯•–’ ƒ»£#ú’Y¥Ú2s#ñS¬ @dÄE½Ö¢äN´M€=czHzÌ)ª[nZ½† äééz9Þ»à køõHw’îÛƒÐû¶PÞ^¯_’?½oõD‡û6ã~×ë¡0ºuÄvvÄß§zŽƒ~•_“j1‰øût¨^?!>À<òJhÒmE‡Ìö¡¯³ð •§ëýxw.rÄHäzß´¢ü(n±Žj#AÉ®ÊÁfØ6Je©VPPÅ!èSz:–¥2M,:Ä\ûUÖ uu Ìô½c‚æ¦$Èùx# ÇL¾‰Â+ãÒ§ô|86 ÒvjÂ繂îŒ`Kâ ô²5g#Ø´q“^7ƒ¤›ôzÔ¸²tܸ!þ¡ŸO³ h gïÞy†LÓooc0€wéöeLFêÃ1#¦mˆL°g«¢ÇŒ69o†;W¬ÙøED;ötóÊySêÔ‡«×@ýb@3úÒF_‚£žŒC^½¿®[çÍÞ¡×ùA¿"5A¦¤{`ê‡úÂç~È·çé4þþÏ QÀ1íE(‰¥·àý·'Á†(ÒûwíZ$Ñœn?ßÍ ÁíôÝHmBN7öQŠÛ!¯ö‰Hªvš!™X̪*›¬™s‚ ’€Iû®tÎȪÃs–ï±b™–înTí4n]¼LëÛ6·dcmõ% ÕhýÚLyõÒvW×qÖK‚´íB3gJpžÙsz½ òFŠg¶€³>þ,,‰Å$]kíYò‘)•×KF‘hpe Ì}Ã^5oŒCn‘ ‡Sà7âë¼ÉÕ»ÍÖ•S¤#ú›æšSÄz?dñèçb® ò²ëM©T†åyÙÄ`~tôŽd—¿p»ÅÑ…ý:ì? ²ÕøÂ3ñN·Ý2°qrJ)ÀK‚dŸ±¢m€»Ó-%)ЉÖì¾=ñ¶šêè.¥‡ŠCƒu©¦Èd“òY½#©3ýjö1Ãí‹1φ(PÞ°:wôš}íæþó)ëôšeÐk>EÔBŠ4òGq¹Óý‡´*Ì€¹óÃ8è;?ÌOŠU\UPq=E»{ʬùyÀÌ•ßO÷û?”ß1¼‹µ¿¿ÿfæ@ªeÖK³gí±È»•21„abÔʧˆìŸŒZ¿Í³/ŒÚÕ†bxLvœPé¨MàÂ~ޏá’Þ!¤ØOr¬¨væXf±;å‡Ò¾Ÿ.;dÏ}XµB½2ËvXëÀÄ`‘å_§¨cßϹlt¬#žõHVÖåú-œªŒÒÁH3+A&Ǻ>ddów_·‚×ÉöJlT·Â!u+¢§y=ЭàÝ ‡<Ö­FzL41Óm¦|#^ªz ïù‰ÇgÔ“d§ô=É" 7ÌÀ÷ðlÄ8v+Þ¥°ÚlÕ|D¦WEvHö+ë”;Óÿ¥è1“ý¹:,òYEΆ—-Ö©q†st,ð'1=Öa]¹þ2‡²Æ¯8ð'§ÈPuhÍýlè±ñÀX¬yd gø†(óg¤Ç´a:*Žš)'Ôݲ=æ%H—yº! ;ýŽl×xP¤t¼D¡tʹ¬‹G†bhôqü×hêqÉbBzáØGÍsy7PdräôrÆa¡Äž:¢Êª÷“æ,æ:þÝwô·V«zE寒v‚mf€§4ç]ñæG¿ÞÊiZß]×5¸s±dÓß.ªÂ9ñÎýS©÷ŒWtÞ”íü1ûzÔP‰œ"3-²òȬ»'—™­WL´ž›®ÖÉÌDç(^r¤ Qg«ê‡vsÌ ÆKi×yÂ÷Kô4ÏQ‹Â]‘É&tè7¿Ú¹Ž™bdåô`Ê4½2UoŽyûä`áuà`ã]¢åZ;9çÙóVg)kŽ«wÌ2…¶G^x5àG­7gþúõhÜË´;¾÷ô{Û˵Œ¥Gmã—i£"c鱦 i3·»¬\Ÿm„Ûy–,¬uÏt/Í»Ä}»+oyÎóNY=E…™þ ýʼn‰ ±1öÀ=˜çJ…È?æyÂýF“-Ó÷úŸ\/$’ /øY­ÀŠSc|×+=æ÷£Âû/ëxò‘åœÓkOãÉÉÂMíVb¬žÏu%È"Í1MѰyå]?Ï¯Š ÑSn€­y=YÙ®›;ÿ††=[FÖË"–¢­è%N|ØÇЈ ejµEŸ@¯ªõò/Š«CfU ¾iùcxèU”>ûJíºÌæÕuÃÀŸ›ØeäJàÙfõz [ð%à¡Îù\¼å»^ ÅRpfvZ¤~E®ß›Í}µú'ηн¨¹ÑNÃΨ‡Þ=çR?‚—¥•Á^«Ãúè{žÒ±üHe}[ô^/Fú²°hÒ´ä6Α º¨ú·ÊÝÖK^KˆFù樱›^Šq=óÑ j@t×õÈ=òô‘XU!®VàÖH?>Ë×8RÉ0t}Ìr'‚Lö‘ë¨Áô×ÏÈ K—hÅ!¡Ê5‚TÎJ׃cæò¬Y²“UΡlZK±øæK’$÷ÙRùX$"Ïß•þu=E.‡°á>¼—¶Amß{{¹~žçT.ÓÚ$;º¢qÉ)29B.Ëæ˜ç"¨ ÑH—¤ÔHIöýþu×^áµO îx1×X&v3±øš»|)½Š ‹|Ûl;©ð&×ux“ÓkOS?£Ž 7ï'¸ö]ÒoÈH›÷öý,e¹äõxÇ9bOÔ'úA>ÆïÒýHq­ûU4¼`ÓÙpJrß)zOºÎõ™l”³!Ÿ~ålå[ìüs œýrv†‘cÌ þ8O½Ú<7Èäà<ó¸Až÷µ«åcé=O«Sú×"í&Èfé Œ¯#^°áQ™¬ríæqíÖºÎ_Ýî" vþ—ÛÆgvh³-2ÃÄGdrX“¡¶=†ó¤#+À÷ôÑSûšõ׉orÄuûèçGBv¾W¬‰#¡C:HhpÈd_mƊµ_·ã:NŽLôJʦmZÿŸÓ­Ž®«ð©mŸÓ0`DvN·j3V¶ *Ch¿¶A&T_Ðv2§*k&”™vÈ3EÚÈ­ÖÈL” /quÄjê|¥ËWì`ÞÉw–Å,ª¥÷™z’)LüÙnÒ,gÙ‰r]j‚¼a#±,œÀoš9+sÔAsÈ=²^§Þ<{)Š<¡  –;™6ëË©”áeJCÏÓ©Þ\¨Ó»i1WtPm F?vÙ·\åXB;ß>…BK»Ñˆ,[§°€Ÿo[qÜ€Ô‡­·Èdw^ÈpY8^Óýp~U/"uƒrªìòsì°Å`œ‘sÈ#‡u½–`1ø“ ¨/x0ñ_§ËÆ©ê U9;ãÁu šOø!_¨[“YÄ û)Gð0a¢|hÙiæW‡1´ž.GÆ»:U­–\f˜ú±ì„ꥈ®ýòMüM¸Ø^piúýûk§gÝh¦Éj¾àÇçYû°ö’~+®ë‚™ÂåvlBšö–c/ÇS”vÆÆÈ9‘†ô0©EBúëgðB.rÑ!¦ W¶#¥â©_¦¬ô ã5ùòëò!Ãx {Hh‚Lö‘“FV¹“Pè'ž“àÿš%|¬IBqMŽ‚Uýëï×C„ó<“`ÕÞ%$Ájà>DwÞ_Ñ¢¯(ÜùóεûgDÂÚà‡¸ VíµGÁjðCÜ«æÚ£`5ø!îœçÎÓ')×Ë뮨Ã]s?9/}ŠtM¿¾ŸŽ™îÜÏ€œª 29@Â5QäyÚÙB#M|®)I|6È8ñ¹†àS´6¾³A]oŸ;‚cÙiOLGcÛz’v†3|q÷íü‰)眽UK÷'±_vÄ@Sq‚dt‡ãNß{m¶ñC4ìFÇÔ­+Uô½gL²ˆ£ñkuG z×\V…ì±Ìù!ñV ZúWÖÎÝR5ô×Ñ»%+JÏׄ‘T®×oEODÌ ”ŽÎ†®Ÿ‹é•ä5Hÿ›æ™$Ô_Û«’ozEi˜B÷¤ÏµšE!‘}ÀÒ©ÔÛ5½…låÚ ð ¬çùë›ó(æ®–3–öÓ0íùÍlC'3-µÍ¯Ÿ=ÒH¸f…ärVïy%ÈK@O#­ŸQ¦óØõ…áZ¦=ÿüµÃ\VdŽYÊ&[)2 Œ^o¨wi]†§ ×~‹¹¿Ö~½z®OÜ7Ó@ÆCÊ¢d[}Õª§Çôd<3Ú^úŸïûgÙ〞‡žh›ßBõQó ué¡,PŠýí»±É˺xxh”T¸/$¢›_¯–Þ©SL?®<¸Ô‘ÃPÌ/ %ž4 ^ôÒÿØémÖ«×xè5†¾Ì{ª¡y7åz§Ð4‚¾ìN7²š¦Ç樷h’œ‹Ìü׫ªÇ2—›ËºGPÇ•nd–ËU£ôØOa~úO_ß×zžŠœ>-vŠíÎí0Ž>×,ŸrýRhPÊ}¦OàK%óÍç—DÅ W½®+ŸÆ¶•›8Ç*Že*§^VY/é§Ê‚QŽ-5²kE.‘^졤xn2æqnºVi Mw"REŒsCmkýóÎX䲺Ë;ãጢ•>‚ýûÝ„|-½| ü£ãù{® H¶‹TÙ¼ÑÒšC®ÿµ…,3È,ßOµrˆbòü™¯Y ˆY…_¿ÒŒ©€·¿2¿>4:&­»š ÷ó5b³‚s_#ðPXl^ºËCáFŸ¾ÔŒ¯YUzGÃ;â 7ôZØÞ·­2¼w÷ÃÈd5,øÞ>¼’0 °ÞêºÐ'@‘BÃÓÑÅa(¾.û^Pdò9£‘0ƒrDyÞéMÙ[Ÿ çy9óÑÉ*EoXüè™êT=Ñc¦X$)ʧõ5:QïŒófß_ï9^™¶Î “ZRä}[=ê{Ï üŽnÇ"Ø@¨9CÝN1¡ûŠõ~ÿ|/!¯¼±ãQA˜ù1Ì-ŠLLÆä«ÞSf´­¼* ‹1·È 彤?‹1?Jqþ¤È$6±´Ä˜ÜY'¡Až÷ Ê«ð±˜sgõúÌí4V\ƒ˜T…ÕŒˆs·í^Åü¸Ýk÷1›Xî^ûL‘_® ƒ?nÿÚû‚ ¯}Ä&ñíL¼ Ý ˜ÍYdÌðe·oàkýœÃûù]\4>Ý>ÀíÜ”ùâJ1 ýõóþ˜$‡ª ýõË‘Ï⼘ÇG­ij Àné78ªã¯ßŽ‘ .ꇷXzÍšAÙÉ<€%ç8òp?âÔ;£º÷¸ûiKâvܘóá¹êXp¥Èƒ=.ƒå“"“ýár—îì@Š ó¼V¸ÎÇÔ+oZëjúÁçStE‡Cîæ~F™òý{¥1ˆ!³ûå‹-©4Þ/Û ³“Ô" Èî×cî?‘d÷†/Æu“¡ý´!Êd.ÿ]/‰9î°w::”9£Ã+W󜅑ðˆ,ÆÂfµ†S߃' AF\Ë¢´Ç4*²E‘EœÍ‘}œf`­DZ¥ÈË]CºÆŒ±M ‹la˜´îß-ÆK÷HW鞈`½mêugúë·ƒ74ð˜÷/|XБðïgòó³ÛP3™z–Áâ¤<2|›¿ÿ‰Û£ªùX6ÒçþÉ ÊÊ72ûrž}u=ùaC¯Ü½ÖɆ^yY¯¹7Êú€AÖûy<ÊŠ„‡ÜeÍ(+Ž¡9d±3?[›æQ–¾I—ülשä'r¯÷t·¨÷”ì™Ô¹;º’ÞSˆ2ŸHÒ{rÈäXàSá¿üCàs˜ò‹Àg@^ÿ!ð~=Z—¬\kYºj°(Ô(‰o]ú…8DÕË$" ü!¹ÌP©¾-K”©J~î_ucêJN?ÿP™(2~¬J×WH55"O±]C`¨°T…ôqr›éáüŸ­ˆ.¥X²¢®rß8cÒ¡ FA ‘âLaUŠòÙV‰B¤:/ænçÒem× rß8CÂ@ßH™RÑP“õÔj„-ÖJ9$1”+M™U/ @¡[üŽàñˆ¯\v¦š9ZAݶ›áqBÙ Ó jY–¬—¨{› ¾ðu¨ó¶å4+|žTP’CÌŠVŸèÉ>åù›an›V/%øóI¤ÕñZQÚª$“‹÷Ø$&Õl©š!Ǩ69Eµ“æ„xÅšÉéXsBZ͉‘ Ydbàm.àã*¬$ÈÉ~OË·êS¾kŠ<›b†ç™˜鵡)Šº•xÌÛ IØ‘… È] ¤•Ð’Șk«$ôÕ·µ7UNN÷C ¤‘Ð’Șk—6€Æi+ñfýöCU@XÕ2 &å9V°ƒ$ûDÂPøÎ1Ii ðÀG\‹ò“É ‹ª,FŸ,wS ÊtzóxL*Ðl½æM¼æe¡ <Ï)ƒ’;_HˆèEÿ’X‡*ýó„%ßs)$h%ì[ìZbøÖ±Ë1×tïÃ1¯4¾°f½ðŒøS§žQz€|Ϭ«rD°+}Ux]Ñ\ˆUéEŒ “ ¼ëôOE‘Õ¢o$héóÔ;ñ(VAߣ353'å êúÕá]J‰ÉFØ»Œ®×ÃŒßflNEê[zß®u RÔ#A2/úàv9[èôÖ¶¹SÐÑô UN¹WMU+ayù¢ˆ¿~ÿ‡v ƪìþ‚ó2ID®0B󛕨c†’èI­ ¿6“sÆìS–"E2ßOËŸ¨d 3¤ér‚DÚª-E™/ø˜y!‡Œ¨OßN{/™êÀä€ /¡ú[–…‘ƒŠq¡ú’ ¯DyË‘TSVåíÓ»8dŠÈÂ(ùBÍlÖ×5NÜ\8dhO=¼Ð9—CÕr¬è¯‡î¸JCÙu¡¼x·¿ó?”{Þr’‹˜û7…ƹ‡Ó z!_ÝóÐÐzºuŽZu(zK=µÃ°¢ î< %âê QÊ]8Ú!oŠiÉë–>RGíøëК¸E"‹Êú~¥Ý)›RUú]êµ(tcða+Œÿ'ìÊ–ÝÔµà/myz<ï7UÉ'ˆQˆ¢òõWã’6NåµÃ6 ¤5u÷T5ºª_a( ™sì-xÓli¸ê ü52´êª~¿î<¬Gípr'V¨íÚ¢J7á™z‰æ\çµ_¦”3Êjü¥8j‡Õ· ƒ¶`­ÄØ€N±‡ƒâZCs–W³l*¼²œÁ‡:Ðf­&ÄÞ«¡kÚÞûÑx¨Ñ”Sg =`y*º&÷¦Ez=`mÂÆ§]ýVV‡'ðð)…x˜/*,È$cð[ã*…ÕŸ³_«®Rˆ’®F^#ËÈÖ$Ée‘9 ïêz´*w–ŒšFÛ m¹rr=ô”œpªEŽmW7™Ä¢H&Ñ6&á@.’\:¸fŠÚ,¿¼™œ› !Ã0onÌŒÜÌ^–Bö)þëa˜×X[;ÃlõJ‡uÊòL{¬ÍÀ°.s¶åDÈgäÙㆎ•3õ‹ž%AÈ—W‘tMéiŠfÇ WN¢ùø¢¿‘ µj1O5†^ä‹Y{†Î©NžÃ[º\c;ǽ4mµñŒ7%†‚0Oèã·Ã¸($ð3½³Ôaë I’¯©éH’ ð9V™öiÏÀ0AÞ„‡RšVX£aŸ&ØÓ×ܾ»¦Ê™¦ y AǾ^4;_¦"Í}vx¥7,—;:~‹yW§à”õ TÁÔW~jVv¬úbÙ2AþëF¿h©¨úêÙæ½Â’Döë੾ª¯:ïú!ogJS(äÅn‹HüZ‹¢ÊHü:‰Ü±øµSBèGÈ/â×=F’ςŦ™ ÈÇùZ2ŽBa-=ÏSðI]4” ¬‘bY·N±­ëÊ~> ¯a#±D^ÓÑÒvÓÀ2¢‚.wÚB+æ‚âäuª¡‡Çã8!?_ÚÃFIÆ_3â̼ùG¢!È„\¿$mz'… 8ör:4–\ûͯyBpºœg¾Œ(Ӻ̆¾MrCº@°€¦QÎ"Ýyý4ÖÙ aå$r}:hL½îÊï #?hh%„XXÙ!líQÚç9Ž=oz¿ƒ’ÇQiµè|qæÃpO<}“À„ùÄJÝeØê#Ï©OR欃+v’B:Kê")ó„¼Î ¨™š '©ß )Ǭ¦œØó—ãx ƒj7”;hø$·CØ’yd¶aää“CEJÝ!maÀ%‰‚âbk ~ÆPÒˆ‚\aÔq{ta´¥98b&Á!èC¡b¢Aè?¹%ßd²µ‚>GÈkˆAQ¡J›m] äFP9ÇŠ_Û3®/ùÒƒB`rúÎwÙ*ÉH^®Û„¯™œ6hÃú¼ý£AZP·ÛQ·ª°ß‘:šFEÂG·ûWÌ.“¿$Y+Ýi¤Êl6ýÛƒNÝ—Þûó0|V2«Zв¼˜‡Ty=);Í)§!“e'…lß‘äT{¤eß@ªÚ¤Z£PvŠoH®ãùø¨g’=“!ŸÇRVÍt)KÛ;‰Œo>©”äëV]0¾9T½x³6Zh‰ —3EÖ¯zVŌģ’Û “Áιoš¾i—|÷iZlSs˜%nx“«h1CÈh¦`Î!¨iÖUE#]‡I`8ò©bëÜgY+’DþDÎ ¨o²­YÖµHÒÎÞýEVÖ¢çÕVMùŠàA™EX½áy§2ÏIzî™C>bƒ w÷T•bív„|"ƒ fEYi!3ÚC•䵟í·î:g^~êUÄ4ªßgP ƾèÚ?ʃ±›Ïoøê여Σ~‡Ó+òèñ°uÔpߨ¸¶Aȳ˜î ˜ž÷“{Ò¬ޝI|Û9Î|¨.†¶ó=98Pz2_.Ud·Íík¹¸Ví#ChPú×!›Òã*› ŽÈ¦Æ{Âû}D-Ñl Eé@ÿzË»¨Ê»((x&þíÇÒQš‰©_Ýs|GºHÑ/¹“(ÐíùEv‘;ù‡î!l"÷Hé鯉ZÜ¿Ì뾪°VÀ“?cxà.ÊgîX«.pëÛy¥u“­á=VA@êĸæ¸Z&÷ÇÛ˜Im6-=ÎdUõ™„ÏØVPM•*´•+BÚ\î·Az‡bmŽºn};!¤)žýµЕwc}Ÿn[º!äýÝžH-"dO”ÜŸ'öDƶ"²'JîOäH¯›eΓ‹ .¥×ûëð<¡E+vºp•QH„´kÉ Î¸^«„Oû>w‡k&Ѧìí©³Y6[_!Iì˵Sy:2¦”¹ Í]:G`¢j ¥øøyÛ\›2“*÷ˆv›ÇO´3…/?6µÅ.¶îý¤ƒbïJËjûyÃ#u–É…TqÃà£ÀÇmº´¼M›VÏ©áþˆ}\Ƕo[è!,^ÒÑÓ/’Sú…+›8rïA`ueæÊ$4w"ƒ k-RxOví†&›¼ðk>¦5˜kzS‚eX—J¥>tGÈk(0æP‡—U:Óu®”pÏVkk»YêjB’P·»ª^Šu,g9gBçj]ˆ´C£>>æb»ÇQôRÓr¶ß;Ó:æ¡°n‘ Ð]Ø9c•%t­àýi‚µ@þ¤Ì̾©ßYìÚÂv˲ !MÐ ™²¾3gtdÚ·~.ñ“ÿñ¶Ù¾ Ëj„µ9­úß’Ž,Ô©«àªÍU,Ä€¢ã¡×Ê4õKeÐë>-´iðMé⪅ê>©íV”lîÖ®*!wPA™ÝHªvا©®;è-@+çÈÞ´k3æh:z÷nà6MÓWûu\—¬Ê?ÀzŒÿVТ¨m.¯I×¥sêá=ôéç} ”™ƒI4ŒrX¨ÁuÊš¬³Ê–ì •{UCÕW!¯ïËoy[~á`‹jy[Tá`ú´¨š,ÃÈÛçEU©E•– RòºÒe?Rµëì-—=^&Ä! ßMÓÑYmS!Ÿ`ïµœ§)g*¼ŸòH®š4×NÝYÕãß-~¼LY-ÓÇûâWôò ‹ßÏ…×Í´¶þ¦ðkŠ?,Ó>û›ùX§ÏÓðM“ÏúPúˆ8]ïeŸrb ØèçÖía:æùs"´k7/¤‘’çå‹4Ò¦gØz"¶Ò»H¾¾#H˜ž×#K-⢠z®™œÊkö w”œß»Êæ ¾’˜Ûcì†ìî‹ÌkŠ$ÈSÊð“™%‘«`PÅDŒCÙ.„çù8ÏÚH"ÜÑ·¯ƒ²¨„ûTýúûÇN[{w•}fÁyË!¯¾£•ŽêÚ¡]òŒ¦x~[NWåz™t<*Ÿ>_'‚áÜt¼§pG1·Ç2`²ö™‹±'Ñ«“ƒ­fÑÛ;Ò ïè\¾˜ïZ¿ ‚Ì×·Ù[ÍRƒDäõÍ R³ªüš'??gE{­ß¤¿Ð!¯§<Xuäçr4Á©*W:®Û®§µÈ>;¬p´F®l¡Ÿ7¿ÛŸ+šâí,ÔñNÛŒ#$Òv`ÎŽ[ªc{i=•ü¼Ï˜Ôn2>WÉw#d†·°æ=§KÿõlÉ UDÞ˜0~T]“6ê£ß1ò¹K:q7Þ =_ƱKò ÃÆxËÌ÷ E«ÎØaÅOéÛqW¶Êªþºl&¹¬øÉÿ©†²°¥uÑuKûrÄÔ Æé'Z¥Úé§]Pu*.ø—^>Z'ª<}PÛ2\59ÓÑ Ò=<Òä«é/‡NùÁF˜FÒÅN¸hI—¶½R!ù¹!ê]š»*³–”˜x¶´~ºD¤ÿÌ,Nî$ÛÆ™ÓV=&)2 £™ L(¢ܲAHØTmX¨nB-'‘!ä-êU¹:A.S¯”ùþ—CÞQWËÖ Ê]=öšö)B>ÐbõÁi¾Î¾£g¬RbirF¥¤ìçÃ_}”>ø0ô%~ža`ó gR q„^b(30Õgýáï_ ·¢5B,†é2/]ÔQ‹¡I ­ —SCÕsÙŽ¡$@½LK.Û9fHª=4CË­¾6Syª:Àd_s ½Ùá¶îÿÚB~Û%B~Øû·ýñþý‘gùmäùmÄÈûcÿ¶?Þÿµ?â§t¾?ò°?Þÿ¹?6úaäoûã=Z¦X—WÌjol@——ü<mEo„¤Ò.UÐÁƒzâ€Ì{Ö+[µFÄÒ#dDd0†ÆVÒC6;ï|Mh@Rs÷9,§a׋ºÔòODˆ×4Š>•i;A¿;ïûBÛ†ïÛp@Þ?QçÚ. ¡Æë<¥T)ºçNòóúž®Àd¹`MwM<õò“s»°Š~¸\Ž3FöŠ9÷Õ òú^ë.ƒ!tú;ŠHpnbÌ%`ºËÐÍéÎ0Òu¬ÌyãJ^*•Õ¶§CÈõ#Ì“×Ô¡…/Ý‚¯I>¦j†l [Óåƒü¤Óu”‚åÙ…`¡5CGÒgX˲Œ‰ xIäe¤ÎŒ¥°µñÖÚ¬õâZrÁ§2BÊ©œŽÈÈ:¾p3šº§Ãè'Î ò‹úm]7ÜÛlÕ¿y[„¼Åýïp©rš!+7ü×ïÑTŠ+w)d!³¥Ï„|Ä¢öŽòyªS¾æ²FÈgN6ÓæzBt(¦^íµtBÈW\’µÏHowË$¨/‹ù'ÿ žzÉD§>cA—CÁ(ÍÜıúû¬úU( Kç ^méžíü€pÒý5,ŠŒYEO•ƒIΫ¢c Z»ìŸ,›­Ê%Bâeo;LjÙï{±„9:霷«ÍJ- ÌS[pI;D]›¹=f´ù1ûí™þ”zø”¾¨PÍ­ƒMìòú"C^6«œ0òõÖÈÛr÷à $b5~Ì!W¼þ !f+Å,{dW‰7hÆ‘ëå`°T¸MliºµjÒâ–ȰÊ3ј;d“‹q7„tü27Jk¾;mü6m=ƒñ™]”–Ôw´DÙïõËØ+3"èyýp(L=>ÞM°ü¡ ‘ñ¡pý¦’¢ÿ:$6W‚TgŒ®¤¥[/ù^нJyCj=ÆÀ\ißÖz­GWÿSëkÙ]6­±@‡L0RC-R$!I¬lá9ªœ%e3þ·Óš 辈Ñù±&½£û÷šà4cäiMp%‡$ïšÙšókÔqàw>ÞØÁ_‘×w¤µŒzC"v°­ð²Y½Õlfá½G|R§TgJ}º"™ò)Ã÷þ@*S1÷Sk›íEø:žçÚf,Ö6#×F¤QÚ?íá½¾§ý@ ×/›³ñÈäçÔxx¶–ðù¹”`†YáÞ“Ë·ºX±CUŽ F•fîWޏˆQ-¤x¯$fTýúsàs5R½Œ„ªqšÁþ)ÖN=U¤˜Qe•UÊSÈi¬Ò¦„ ZĨú…4Eöa^·M-(ŒÆq ¿sßÙ4e}žg¨vÁ˜«ÆÒj§û~¸æÁÞQš¦&›ÅáÞŸirIíT•U}u¸¦³Gø)Ù¬zÖ„WÑÛŒUG¹ ¹Ž ‡è?Á.¬Z~Ä&çZ~dªÒžÂ%.CÛøÆVp9!÷(”á-²â“Xó#c· ]lª´ŒúJÓ½‡¼+Á²riáêðº¥D«T6 #o(‘6fÆÑ¬æmƒ‘w,â¨æ-¥-xŸ9äÃúLþçÆc²l[õô1ò_H¯ds“®­„çy; DXÖÒ¥š@ªŽ$±Î/+œåþú´Õu'J‰È›Ú/Б³bÚ'|Mâ‡^©º¢“|ÜÕšã{Æñïü|téÖ(´5Hr?•x•šÈŠ$y|MPÙiwtndÐãjhÄgúÄÃ`¹—ì&‘¯Ðg|ðäçû´°©¹|Ÿ– Û" ¢vÿ¹<Ö;Þ© V -„þ$ ñ\Ÿ'¶¨”Ÿ#$ 2à…›ªsYˆŒVíË€GÔýF-ø-£ûˆWÄ 4[XÁ󪞗‚ZÉ€ÿÚÂÌþuÉÛ.m’ÄHKÕלׅ­øš7¨mC‰M»Gò¢J¦CÞ½\¹[óvâ¶ÕìÕ#‘J%ðtÇÈ'›«kú¦ ­‡tó†/,W®ÿårK»Ý„Ÿü‚š|B?¦©ÕÿÁÐK6÷œúª•T± ÇÐ+‚šýHy>ÕôMb?-'± ®*×l!=”ZQåˆR‹è¦i—#ômÝÛŸFÝó¤5ìcäŠ+Á:°v¥»Eý¾ÉüpÕGäßiêlê]-l궇çúŒp+§ÄÞ*ñoüZ/¯p68B¾N;Ú%^ý?hŒœy:Š /a&ÃC£Q‹²ð?`Êå6PÀ5Œ7…-2ëÛêºunÅP»—ÿÒ)Xáz6Z†QφD2à&_‚ã‰7u•ïùVáÏßË€[i0›€jhݪ%aèýt*fI¾eôL2(yrné­§g€€ç×SÆJÇÏpôn†“ˆNùiÊ'tè ¹Ÿ“Nµ(Îò8Æ{ÏF^OÒ‰-™Ä„F³øõ×gJY-S'u[ûÙBB0oG“Ûé&éʺ½eB†Ž |{š²•W¢‡:yá Ì1˜ñyöª€~6yᎉ–¿´³’ÎBÌÙŒ¯yó…Á4s ´^Ò‘¦2»!ï@¯²ƒô:WMé˜Ö*¯Îò)z:-)­,4…£Gȧ×Ie±™…jöFˆ!_A1„U…“WiÕ§‘‰?O»ûèÑvö‚ªÈ$JId²«ÇÞí4”9¢Ä®ëhÍœaèõª®*Š•¦Û†¡ Ò«,+§WYªˆX … hê&{U Á*Qî]¿õ vºRë‹§}»U]ºbèÆUµºŽ•Ö\—bK«Tà×!è´Ð¾µúªEWrN›&ÅÐ'´—Jÿ¦âç<‡z/ &»›üÏX÷zód*x*&Q·xõÿøATÈÕvQÏ©Xj1§%^,W˜Í*?XÞ™¾A‘¾©X޲°d8õIÏ꜔^œÜÞ†ù‹ÚLM›"ÞÛYÌ9N³¶®†¹aÉú4÷ÃAE¯>ë*ÏHG§¾ËÒi3ËÞ"ÚÜÿþ8N”+iÉ´j‡FÈ{Œ´ªFò:%F>>õc¸Ú÷¦±ÃýùE3/“ìDæ%KòuÊ<Þa“ŠX×ïµ=²#·Ë—‚¯ƒT–CžÔx4dçñ ¤t¡ª/ÛÊ£ˆÉíô¬{ìÞŽíÖÏF^1Ó Ÿ5¼§{[cdòI~¶[åœñ#ÉYžÕ3ȳn¸àÖ¼f]ˆU앯¿ZG ¤R'O]Ø!ÍÒÓ¦þíï+9ßx§:ât¿!g¿hjI2u%ìÉá‘HâLÙ9aÛU ßmð/zBΔˆö¯búL+“q#ø†j®“ ޔϩ–”Òjj·5ÆPïJ%˜Ÿ‡‡GBN±ÌÙ$cV3¨ ¨ÜûýG™Ê“ÆK×oñçO 펄3Í 꺫ÞUÛ¼dUž[1R$"F;6ÅM;àk¾Œ.›6‡‘óka kFúvíp¶üìl3¨ê…_j¹Rš«oœÉPé9ŒÀB3¥£åf÷ûÐÃÒx’}ììNæLˆŸL²óMbgBüt’½6â¾ÿž}V“ìøšþÕYg…—ýп?ëlÔ™Ñ>=ë¤«Ž™'ÌÀÂH ?’K{M›,+ó"3@B¥› 0O­‘*QMíRU4—¢áÏ<¥_óäÍLª Øý> ï,% …Yrô®ãè`„ï{š8Zúá•NOîØ\² Zlá ¡œíÌΧûïǭ̼µRñßOTy•ùn ¹Ô]Øo˜ï-JÒ(s=O«cØÞ¸{R üñG4 7„<±câß“ÞþÖ" ¸ökÿéÖ¿ÜCøïFbüþû&¾“dzûéáaõ^Ø÷™•M«êbÏái:c•_]¡ÈfIÿv¬ò4rév‹ü\F.‚–³€ð²Fzg¦ÓX³nøžÑAÏÈ4žøÞdûQïQSD—I9íŠ:æ¶WŠ®L±Þjy敌£hBHÿܲ€ÚîÉïèÛ–V †ºÐD3×üàN‹"ôŠóx m5”[ ñÝçqÝþZk6 ¶C}Ž*)µ*YZ) ½kUái>Â/úx7ªdSÍlûûã]®¡ÁÒ± öÝ<·ÈƒxùãË’#-'xFh¨†b§¥Îiø ÿqÚk†ÿ8 í÷¼R6äI > ?ᵺ¿K£¥»|N¬˜+¥6À—QÝY^åi•*ÉÚß~GC%Yw¬NrÓ/å;-©ÇijJt´Ì•œ¨VVÙPûœ8)&*ªrzÿÜãxalÉwFंèq¨œ†0ÂÒºŽ;„ô¯O{ÍçÝNëƒmî8å(Æ)-ã:z]îɛؓí»iÇÕ¾Wˆ|F@™‹ü}âè¬ùѵ¾0¤mU& ñ ›Ê,MôaÖ–¦UËóƒÄ¦Uº»(‚ÿQ˜‹V]ôFy§ ¢)6/­â¼jóiÒvASèÁŠOè`¬ì5Òùôz°•¸] Èã#K^²s;ªØíü¢q‡¯Z$Xùñ4Ñœë!z;]Ðÿþ¤P»R]ÐÝ/DoÛÝÜœ{³@K=­9’ȹjCˆ“k¬X[%øÎ?ʇP$P ¹Fpr1P{æÀº˜÷2‹¥Ä÷þ‰dC Y8lê­¬ùn›Ïú²úmZê»æ1O×´‰ †úV•œcU92e5’¦:,(×^·P§ÒRLñÚV´ÇÏT ˜ÿ¨0T+ȧqÞÔUÛ~ÖûÚšršèsÐIÊ45‰çÓs]6%ìyQt1iAå¤Eæ¼÷ª3J=@ù>ñ¸¾¡k²A´EG!4i±µÐ­"¬òÓü©Ê´/!÷Š"l#t˜ÉØle*rZF_34IíLF9´,9åR(9”¦'mÙS[=ŒlËOoP9½‘ô‡kFWF§<²Öo^ðxÜBæ<®£!áŸd4|ŠÏ:i»qhðp Yzh¥ë¡];Té]h‹ì‡ç)lßòÚÆ'6ë3pÆTþ§j¹’é$ÑÒ¿6P"ðé¯(7J î¼o @ðþa dâ¦ÀkûÊÛ®ƒFz`§ ¾­BT¦BÒͽŒ20£H+x|¾âemëÁóCV'ý¶"äµ>Önïçç^k³÷ÓÎKa‹DÂÏ…qŸ‰}î®ù‰:çÕ²ã‘`[±žß~ƒt²ó_? YiÂ{[mýjŸÁ#ºÈ½t}¦ ‚köÏÇ]¼›æi:óRÇz}Ý ã,XKOï:Æõz¨®Ø×¬˜È&)\óuT˵ŸàÄï}×'&KÓHïÜHRf~ùºŒC¡Ö<ý;…mÇà6°SPß5!·ˆ\‚çá=âñ•V®.ø}ê{°žn§äÛH§‡L%x~îtàDžŸ«j\+tØ6!äyŽKµv@F·ä‘fdéšNäšBP—‰ :ÿ¼£@k©E¤øù>/uÚTBzײ«K‡/C‹ÐÜ_yM!:äm‰¾ƒ$ÚE¤®›†ßP#úª‘'­|u"V¼hÝ7ïÒÈV!¹ã ´jä‰@+DH U#OZ…Ê+ÐjîüãâÁï”ïy̓¢²|Dòüå”Êp$¸Ó=·O^Œ#¸}ÞëÉâ©>"]wÊ¢Ððû"ê–K†/çéP@¾Óreˆx¯ãô™!#2“2…)o T*­å›5™¦u¯;þžáùk,UÌ&⸰}…kCƺ¶›ƒ ÛÁx€X#‡À ®•_ˆA‡íÛ ï Ëv[týÚÎfLì&r9·B3&÷¹*Ø’1z[° \1 «ÈÝÎ7údMí5íÆô#è@(æi²23ˆ;·"çéd$^9+mÙÔÍ€|‘…ÞèyÄO÷fÁHh$I÷T=ôX‘…æ#„AhåÜæÕhj2Æ<¶DHÏ!bà‘ˆ  ×ëË‘•€#+ÛsÚÔé¹N@úk’v üί€ô¿ƒ•`º l”]J E:pÆ,Ö_êšj¢eä+XÉvÌbýõWv%µXåPÅKÙ¯c × °V¡4×Ì›¶)Š~2%ÓÀ%hµ@9¿*n{ÌC†©ØŒeC F-Ð賎}¼ð·£0\↌ /&ÕZV;Ëúuí2p5ÕoOÊeØçtJñ§‡.²”£0I½%.Ö)AÈ·ÃûRbqÕÊ×J<ôE?ÝjʃK|Ó¤Z*6å„QJ}ªÅ/þßÛ|z¼óG¬A/åe\ö.×ÙlµŽkÍ_½DÔë1×lOÅÞÀÒû~ðKµÄeÏó® !_®FªºMsņ’–#-Òª© ÖŸ¢ò‘xà[ÊZn8çv®rhÒ¶UÆwÛO””^â²s\oCµÏݸ•ù¾4æ´›3c"„òÕF¯¬[hÖ ±=ä^Ÿ3AAÕÏ`l+»iCHï¹Ç5GR„|9~ÚOLSŽÃ—“!mªÂXȱÚdUÉ& Ñj¤Š˜þlšST*I{Â_Í-ÅŸ®¸yþ*@awD"n^elVIN‡!ÇwéO3WÙ´CN'è‰jdä²øT¬*B–º¥Àâ3wþ"µ/î´mÇ®«áãÝ–¬(5ˆ“S@Éi³É¾cW$‹fP@X†di×ZÜ;ôåç-´!±ã='ͱ˜ÇäÇÜ•6|ÜæÕI (m]Ý@¾ "u|H¦/‹}2B&iÓCåw'õ ÷±ã'„ʈ‰/eTt¬ul1‚/«¦£-ÃÈ[ ÈQ‚çUûô`‹‡q>ÕtRvûÞ|ƒÀ;ÛæŸ¾óuÇ#1Ó̤aÍÞTšûšŒé8"äËmGëøW¨c”]eÀQÔ4u¾wu’PžM ø{ºÅ|¢Føû>w|éÍøš¡uÂ1EHѸ¥Ã’®Øq¾¿¿~£ÚX†öš"äÇ õÜùWÍâ!'Ûþž‘Cè×_u’Ò’ò…òH\€u­ÙDƒFÖldDÖlAà_X³ ÍIך-ø¶©ÒRu<ƒo¸ÍŽM•žƒ×á•:N …lÛ¥VË)2ãªÚÕÙ>ôé›B‡kS¥Œ µNî?_‡ªCH5› uÍž&u6¤B¾,9Ëh¿ek7´ÍGŒôMá=qÊÔë Ò3†?=pûwz†‡Ó}>ƾ¦>;~ô]H/Ì<ömí] ÒÌwµ¢[Yîé4ÏZV§ JßF°*ž&ÆŒœ¿FÊ€éh2g&`ê¶/dî;|M0m¿µ8‰Òï&FcÆÓSüEŸÏ³Rñ6 Y1{Õ÷Mñ› Âöˆç{-?g¬qbà˜‰9Îm×LÌ¡VÈ’!ßlLZý¯ÜEÌÙ¥5ƒm±Ö1[ÿü(FUHÛFQ“¤HƒŒ®ÏmÁ²§\ø¸Ð2§BËœGìP=q¯L…Kö2ø¦<“u[w¸æó®Óv)FžXØuÚÂÎKíµÚ(zäd­©Xw5Búßú¾d‘¾oàR{U3¡ÌåýägBɃÀÄ"_$6ÙÕl±÷óõ¥…d|[=õ$‡Uç5ý÷óc"Puzô|%gþtÿ,y Hb¨‰X£&CŒËT‚Æ÷έ෉àk†§M9aReß#kÔt¦ÍweûéþMÍN’,|Õ˜ô螨“!kái†¨Âe|©•ž7Ý«¥íÒû¦Ì£›r»–Þ‡Å!±ñ]™ÚÅ1UÂúJTM¢5ÅÈ×™jR÷…á ¬©’LNUÛAÒÄë}®36ÙU÷FÍ­¥«–Nkªt²+öõ²C†b;Ä$71‹ðNßÒ±°+ùsY£e kÄÈ×UÚz,Yl"n|!Ìlé0›Xà}£h ûS¨Ù9dÙÜÎ$§BÙŸÆdleómw›åG¨©iB@¦[æÄH(j¤kª½(8r©—¡†&çûym*•¿á~ºhqnç™c´¼b^ ‰8è_Æe\J‰è—Ø8èýB. ©†}rÛ ëz»Œ_*QŠiÓ6¤RµFÚaŸLÏN)$?j z¿Š™Vò ÓFÛ±šâ!C[ÌLñdÚæ>kâ ú²%Ù*„&»¬Ú’¤É+„ü gÝjcû”®MEæŸã 'N®½ÛÖµXñ¸,u-LHD‹B8"¨ÉgïzþŸ=xûYßR>Fb Û {cå mD/5)÷’vüiné;Å]è`¢®ZLe‹‘+"¨…þ,ãzF‡ã|õƒÄ x ÊòµŸ¡oû.|ØÅ5…¿úÞ!äël2cdk\×K#õ±mÌBÕË™m}Ü”‡ï©9Ù¾+ôäwží1)j`ƒjdx.&6¦¾çu ‹J£ØìÞïKþµ`³Í"[m©;ÑûÞî4-@*p9ò*hÐ*?"ØÓ=·/Òƒ³´€­ösU˜‰äçØâÉçº ÈÄ]²G×·¡Œµ9ˆ¥ \Ó»i3r4±×|] ª5BE¿œáØþøGYD#T6ñeÌeHx?¾í(jÍí"u±‚ˆ€FBY@(p¢Êô7F¡iYꇩx¾Íò„BŒì¤ÓÉ@3ä|Íoã’fAH¤þ«T`YJ7Jã‘1„t< ãIäÖÍm· ¤ìdüý¥¤&TWŽ#«­ÂÈàz:ûŸ›Bœ°ö°…âÏçbW꿽P„;¸…fš‘iæ”'¼Bz¨P¬ú&+û‰æB¾Ž§jùqÈ7{×¢ÇÑÞB§œÙÆé˜‘ž£G Ka9ßB†…§¼B¾¬A¦ÉC9Æ|[ ±Ìw²ˆ'ÅØìDÂGìfÍ_ì^'»,&9Ó#2ÅPÇŸ&ÓÜ0Zó§á2~¦ÏðDê®VRwÛa™¾Uˆ¥[YJ95ægX»Í„¡Ÿý:/ÅT“épÕÈ*ÍéAŠªi²†Žü…îðêܰ7áf½ÿÅÞÄHï¼ ‡Cy7¤,]Bá‹ÞI¹*î¡3Ä"R5åϪĸèÎLO:|>;¬Ue©xš¶ ‡ðé8rIȸìË´ÀÐ…F¾°’¹ˆÝÄ´bW¯ ÃHF¼ä\£ütŽœ×>‡;ÿ|\¦Óâ™ “>ï°¦fé]2K*Øòo†m„,€-â„ΰ îaR9ò±C'|zƒ1ÊûÓ2KÂç÷^QÞø éD—Ê ýËír£{ÃZøôà«ó£¹u9u{5,!À(øLŠ̓žùZïäжùòN®WÊà•{†ßnv<œÐA Ÿï;¦º¯ÒC’GÆÂ)ãÁè;Îós)À"ŠŒ ì…Ï+¡r]7“ІÞãBÈ\tiöXhäÓ9êÂ}g9R¡ãü¢’?3Nø©TLÅ>·é„bŒØ˜B.“À =ï£h¦4z¯›!zæqBÏ¿ér‹1UûÛy¢ <øJ#Ÿ¶o;\3@|ÙáW’žü÷ðß7 #Bz¨£"ƒ~,W ÉÙŒ‘/gô´4>˰” +†ŽK‹–K,T¹\°”¦,kŒÄþÁÄøÇ{¹Ø I¶DN5Šß4§{IפE4òmKr™\t"QÛ⽨AIX#£+±}Š»4'ܦüøì2²²*¹–@™—jáAÆØâO×Á‹ÖYS‡ÜPNå¶nt8<¤çQ×ì¸ë7H) ÔûªÄØ[4|gܺ‘'Vªfijϥƒ¸§ +¦½'°‡zÖ~RBm¦*‚¬f@è2ÐÀèÉ*‘ØRÚ$ Ù’¾<Ü+1êv3ëyœg—~xç5Ûñ­™ßÉ-.52tÌoþû« Pr@ SÆ:Š‘Ú[ѯ ½øØZïV12tÌoN+Çò ïs_9?ˆÐ :ÙF™U– ½èXÝ·94D¾Î4oK5GNö¤èáùŸ°kÛq•g–¯4 ’Ëuÿ/éÛÀÙ0˜³æé·m7–4ÒÜ” lw·»ª‚´…¨ß©ž‹ä‰sZ;¤Ëj%¡"‘¸ Û¤:ðVŽ®W? wŠBÒÚŽRðüVæ2Ê«c/bì!»·¤,Bl/ Â{R4ùFÁŠ2þÂw 9“…»Ès 1§£EeXלmcÖ¸kFÖe­¶.Ëà ¢;Ü.¸d*öj{2!¤Ï­õ¾Àš¦.y•CêqI&g£29KwY&K"Mtµmçû¾U`"Ñeƒ‡ÔÛZ Èß ´*ѬYZ˜ÅA|âh£C‘*4ã›b£œÚ5ÈÖ¯5ûrBÈÐ?OG›½JKšàßyݪ÷7¢ˆõÓÕRPù¦¢F×9°T´ô).¼£ÏåìØôì°OÕ”ªR“ܤ~Ù$~@…‘hä £ÃÑÐQ|J0ßßCÛV¼"Œ`dxѲ-‡‰"äËÉÛ*+™¤@¬S„6ÈÈVYõI»ŒD¶–Hi_ÓeÈâmêsTñ6'Ùe‘àg×e]e5rØJ‘mçÃ×üœŸ6«Ó{ûÕ…›äG6$0¸ûór7T>ä.ôè)6`5m„$o¶rg¥ðø……iÓ’ ¡Rq!=â±á꯮Úù˜"dðM!»6¢Eˆ¢qH…( ­Ðà>#©5Àß; }Í)•HçúäMQDã¾Ïùédº­VZ’d㘌 ¬B“îCÑëß—…€±Az HŠjÍ,Ç¥£ùºÒÊ+XCBoýTc²†–máæ¦òW‹.i;—ŒÒ©oÖ_êr2`Õ£4ðVÄ@cÕáßù¹Rè™Ü®F¾É™–ÑËâL’¼׊㋚ÐVì3Ê"Äè'eS­Ðìi¡OÒRÁ•9¤ë'1í¡2Ƈ"³i—'Ò+¢_« B;çüñ¿¿¿êÕ纂37„UÅ´#Bß&kT™¬ ¼ƒk¾}¶Uiºg«ršæŽbäÓã^TzK’Ò"çd€X¥Aî´l¼gwýÕ¶ëO·É®¿%IêÃ5/6¯†­ ÇÈè\lW²ü d ß®ÏöÀÜÄ”olsáçŽAµ;§ÛÈga±N‘XKôú¹I|±–èõóMÕ<B‹bm6¨ ½×ìFÎù¸Ah‡L ¬|›J’”›fÒ&‘Ï úÕù¹Î¥…VÖ‘ê€D*V–ï¼JÝRïsƒþh—Ê,É"—eŒ ='¹ÃËÙ9ˆÙÄj|÷°Itu@R§!á5_ZÚR•fw¤¤a""uñè˳ú:o<µSÑ+øGã)ÔÜ^Á?OÝ탋ÆSÙtà7žäMãéáw^7žº=çu£Ü"‹.ÞÚÞ]ˆ›á£(#|ÄÈ+FÑîíö¯Ðu¯[ÙáÒ4G ÃØ4p\†ÌL6˜I’쓛ѯÙá¾q©È7312¹Ú.:må:m0õ#Tt1~y¬*—hÅ x|E¸"F¿ô#Ì7Jiï(ÆAn^Î[Ár±/2–4yͽAßíù¶TÒ¬Òô——(ÿ&}V%¶ÛTÜÒ söÝ^ÆÖŒ2¢/ÛÔ^&öˆ#µHïÿ©¹Y™¦ÛTM£ ŽsvÖ]ÖWĽ÷÷ÕùiˆßŠØiXŒ]6Ã5£ŸK9ôªiJüÉ(z\û\K­$ }ä—о¢’d™¿Èç‡Ιnu‘wg}f¡QäŸYøå„Ý6…Ã݃뚎 õݱ©dÙl"ŸM¥R­¤NµÄ¨“¾„»G÷H ó(:9G.kÃÐRvÇðŽÞÊÔZ(cäóÛ™cdˆ_¢7jýtvÇÔÚS„ ¿íŽ©µ;Æw}ÛSkwŒ‘‘;…) +qžæaÛìÑ¡‰YžhçîA,ó#gƒ<“ëWŠgøv‘g¾à›nÈÅŽ ÝÎZ8)‹Ïe±kÍòL6à Eóé„/M[wJè1Ÿ@`±6'¤£X?S(ÆÏ‹¹)b¼fêya ynU ²›¬ òœI&;2Ü숿„ ËZKØMò¼¹i ŠÃC³ž•©šÅ ÖŠÁïlÑ%~I¬£ o–nk’ÔzÙFÆŠ Z;¦¼«²u±‚€‘G€Y•ú“ÞT±m¹]@H¯ËÅT(ÄÝ;‘Um[Ò(Èi}Õ$mß$õV dtjBæjÏa]Š£›gi=gå\£ø[Ü^»ɆJ™‡¤vv ;‰ïÒ)wÍzñç¥SˆÁãÏiéT®6ºtê~çç¥SÈ’ãÏ?J§ÿÎóÒ©x¯tnJ§ûÄ›ÃK§²‰ðm'^ òªt*ÐFjÅ1áS}ìiš^gñN-ã-zÿ|[@{ìJSšfù¼BNÕ\ YJF†gÒS›ŽëF„|] ™¾ÂÞØ£<ñ}2fµÑ"Ïtã쉚Æ=‘+Ë^V=žŒ§x"¸fpè*¬@ׯY˵BÈÃxÚß¹Šßéî|'ßY‰ß9ệhnª²0©ò`ù²HÉÄÕHyt<6%+7„Œ®~g9ºßžŒ§E¦ò‰l6á“©þûŸ%‹SRÂ(E_×to“‰@vG¦:CŠ»»wŒ§ENYaäa±C):)Gcˆ³§ ßy§-m­6øÑMä?‰y”Â5±L©zvÓ½Û Ý¼g# ßתÝâÑ·Õ}!_2¥ž8§Í ãkM™8­¶}¯`Cr\ò$CÈoר=i{<ò?ªY-Ú%äõÍs Û‰˜2o+<ö§5W•Uƒ-ZhàNá+Э\ºÔ#tíÉ\ÐÆh¡‘ ›¬kŸŠd^—z=\5vêpÖ–%ߊa›9@ßzÒ¼3XbÁßÒ‰u†~4ô¯Š ôWE›¤ÙçndøhŠä& ¶"¡íÞ5)~¬çÇÓÜ$®ZÏky˜S°˜š Ä\µ)ê‘àߪO“ôºkûÅ7ØUt{[ Ï'5oˆͱO-9 Å‚RÓbeùô‘,)ã–À!aìQKN¦?“ºDÈ«é?$¾ûÕôŸÅôÏ2ºšÔ­›ªŸËéÏõôÇw‡éŸÁ»—K_ß²œâg¿œþIbyRväo¦??@×sÚf[(Xâ9=–Ý{ÙÃsÕVýƹ=ÔÉ7:§Y_À”zx®Ú~ëOU¶yЇÊNÿ³•b<üÖè°R¨é¯V æ±ÐØcàºç˜‹°tê*µP˜þxJ¤[óôãCÝœæC2<vú•jô}\,*ƒXTð×b§¿Y),Y¯Ùón³¦…¢éOJ;ýËÍ›þ‚¹a–¡Úâþ« } E.ÙK¢c¤e¤Ë\-З?pJb2}Íe:Xþ®~.¿•JÃâ™òvìËnDHÏ‚Ü~«ù–O[ßå)F¾|œQ݆)£uÁðÝ#WëÎiJñ/÷Qj f»þc×Gfy¶#é !ßHÕÜ}#ëZ×þܸ'/ÚŽ iYRŒx<?ÞÁ‰í®œwF¦6™ð#=€³¥î_Úû7"Z' E^_úT<~»o®çÁBݾ°Ö†s‘Ãêñís8Rn†l¡sƒÀô’È*zv¨Ts\Äj»/Pàxœ³µ6•A²µÚjŠÐ¢–­©Øë’lʵ°¢Ë¸ˆ~š` }Fó!%O*ßf9/c[NÒÜý¯Ñw6B¦[7äÍT"dà÷Ò—&z¨šTÌdw÷›¹)…7¡Å*~¾¯Ë+’­­ñósýŽð{~nJ6’ Kù¸(檒M±Cy:¾ãvI£5÷D¾íÓ—?ªï°ÏËÉi%ÆAp_rûQ^· #­ÄØãv©¹™ªf,¹ÓŽo íØwÿÑÊ?•.OËA ùôÚõÊ´ëíkµÞ³G׸¥+D˜¿3¾-ÀMÞ(Å7~‰ýìd~ãàKwÈiÅ´E±v<ÑûV+Æžãà}ñ6 Ï•cµôWÝÝ{ñyLEgù±ÇZ2¢ fMÞ«bØL½8üÁ¾ò^Y- x—÷pMÿ›÷WoªWo+mè­ó¿ÿ¡¼Z\“åÝ᚟­èS\³áÉÞÀx†O鯕ü×!8›yÞ÷!_(W1¥ yÍ…2Œô \XÏJ²ÐÿÎøt?_’\òí¬?TÊeg.º½ÀÚÓyRΊÁjCÅáóB^iy…Òëðe. $¯zÒ-øšÁÙ<«?ÁµÇò¾'"ƒñ ñ1jÎ7Ú¨]W²ô€|º–µÂÐ×Åæ¾÷%ý†x{¼àb!ýXÀÊàõh.§áŽÈõ“æM^w !_®IT|!ê}î"ð‡÷Ž^Çyä‹ÈQŠÏ«èbƒf—8Œnv.3p÷}Æ7Ç'rç‚ý(¼´00û¬!áûúÀ’+[¸æ­Á†½Ã7«ÑޝUaE=²un ¼w߬F&“…ÅÃ<îC6CƒlüòMÍ‚-hõ¾×ãà_–E^)O$þ2Hú<³£nWZ»5 ðë òu¦œ6.3£ã w÷¸‡ÿxÇQâ¡»aŸ’dFHOsÔj¬"êaû’_Ï+W^­ M¢ñ+øZ“!úÝ—etq²×’® S˜+7¸4þÌ*#!Ö¥‰ò¹pã´Q ÃUÓ9‚­FÈ­´Æ<‚¯”wiÝ äËÆ ~$ÐÊH ÝñïÔj –¹b®)[?‰Û^ÎDË´Î;dßvÉ4aäûb䉳G=³9ã´%šnE^(f/h2ž·Hß²ÄIGÉ÷^+é¨Þ»gD‚¥£æQIG‚‘ÏsUʲö€ .T Ón< CËṳ́̊ú|a9­XRù:—£jÒµ?PoÆ¢aŽ¢h/‡8EsÉh£™” @ÈÈ~!™ë švE1ÍÖŸUxF©I`â/•H]3nYŸº÷~-'u/§ã5ƒïª‘4aKèÐè}ù-%‚{Gô¾žïZK¾¥Ï¥¡¥•#0J®uþÄÐ’û™iüs™IQ|÷øqШ,Lä?Ó¼¨Åb›ÙQòâUMµÒ¬õÜ/¼ØPaäÇóµÞaiÛÔyW"dà#kóìÝ›yÈ{„ ]s4á5Rh)+a ‰=jªÞ‹+Ó—íd_eßBFGýXyîÄ’™óÁR öM¥d¯†'¶b]°tƒ|{íP±"h}¿vâkBÈÏ ‚ŒˆÇÁEíW$šˆÇÁ?ˆ™:Ôóʉ«‡øN JWÁæÅ´nÛ©ÞÙlW` Ž¦r+—&‘ó.ö†OŒ¬‰EΠM{µ*ª¬\ l‰ ºï“"` O0Ž“×x±Â:ï þˆ‘÷ %)±[Ë ##8î2"Y¯áÅ/tàdºj­":÷Üe±“ û{ÜØÐ¯ë†ïþù6]’¹v_&Éášö¼YmƦj&»/`˜¢ Dnêcñ”CÍÒ )2¸ê¥%ÒOv[¤[”e:!žH9kË¢Ù6IáÃÈ ƒ’0î»kÀ §|»â,åã®°®}~qjêó°S$«¤JÝ”ó»ì±S¤H¢öfîøÄ^„X6ªˆDúb&é[-˜“òêû¦ñûà: |P±Éå4ËÆžèàϤËÙ2¼Eð[UÃÈ' Û3óeoyFvŒ ®Ü ±º˜ZA7ãM¥Kä)+¶­ìò…úàT‰G¹KgÍ ©é;¸9R…I-Þò¼ô¼K÷!n<–ß_cnbºYGJ×a ðŽ^74íȼo)ºtj”²úÜcÏ0åtä9z½óN OwÈ2.G>­òyi@SÃçûÀÄ=rvAË#~ß2qYÕ@bìõΟ™Úì»û–n™¸´réÙûíùÒªÃõJQ†%c˜l@~°^‘ѽ–ˆ­ t«ù½ó†wUƒ_öÞì-}Ãà 4ÚÍÔˆ(pÏñ5¶Î•€Žšq aMU@Zî¦XCw-À,o¾¶³k•úxâVYaÄ|íDÀT"¤Qfùϲ©¿!!yÛ Ë„ñe'ïÁâçqS°“¼°†|î„üäq ì>Ãg]XÜ'@²<’"qP¬ü$«À ƒ.ƒ2Ã()B:ÃÂ6? í¸KæÊpŸðª– OPÑÍž3Èð[xNq‹ ÂsùB‡‘êšùHªŒ¥=t^}BOxù¹§Ú`cÂÈøR»ÌË ò}š ‰ýmtÅ üœòE¸ÌËáÞ3,¹ð^‡»G·ÞëÞ±ÐÇc>iÎYiÙit™çÄu[â+ÒˆµÓ MÆŸøLSY#÷¤HŠ^Qµ4ŠUbÛàì ƒÔ‘ÿgìÊ–Õ•å/Ù`lxÜïgGôùf!Œ1Æùú«±¤Â@ߎXÑ/˜ASUeeêD˜¹Oñqã«cp'ÎùÒ"uD®ýtD¾ýV; J$mÊ}ïRf¶?:m¤D¿E³âdÇ2Ö"'ÿ(•c¾#V…’V„â÷™ø¶\z]’kHÎË”7øÍ?®Z´ÄÞ/4Æ93é6 å,-jFYŠ‘‡”1м-]x¿ÕGHðŸÑe65¥ÙA5µ;¾æë¼A¬– by b•u#ë:µë´"äû²AÌ›rÇ|¡äùFCŠŸ=ÁÏ^XÙ¤§‡'rìi›Œ›ÎjÙt6!äËsn#Zdœh6®ã¶~Òˆ ü±ŽÕj s.ŸÂ9«X ¹¨®¯v°¥Q[ Vò£JÊÛjãC³ >®¥ž¨Xì7Ëœ8¢¹zuüïÑÄu7Œô„h*­A¤$ÜÛ~žíÁ.~„HXËŒØ{;Ì×#äëÊe¿Ó £s—5¶9—5ƒ|_¸¬'­cŸ+—5vDÆ>¿W K•Œ4‹cn‘¯Ï<%׌î$€Êø)ñ#:iiˆá¸qÎ)¼¥÷O¦V7ˆIv iëzƒoôÁ"'%@Åñ7ïÓÍÏÏu3—ÔÎÜíÖßF( wÈÄëÜž2.†p7~ÞåöR±%rŒ4r=¾½óÒ’eî§Ù®612b°rƒfn®Ù:Ž0;<0f0Iëàeè`­‹Ÿ?ÖÁ¦Z ‹¡(f+©{`.1YÕ]Œ»a˜(BF–/©]ó}öz!ûh9±G¶–Ñ:ØH¶w{¸Ïϯ¹´D~»±ð³ÇVÊ Õù–ÊqêSJ#db R¹Ìkä8×ÓØ”%¾¦3Úu‘Ç(›k7NÜG á”<_”ö|‘Î-Ú^ì9[س?oŽûλÃ5C/Š%Fnâ[»²¦Lòåê Sò‰÷e­R˜ÆŽR{FakÈÇÄŽR{AaÚ[„ ý!ó–òoZŠˆ†Ò;Ñ«¡Â ‡|2¾AiFŸë×ø°s>¬¼wÒÓ×óíIeçj–§SÓ äË®ªÎUõDe±ì2yAð¯G¿F¦D~ȼ)¦!ßÈÈTGrŒˆ½8Oó!?§«K1¯Pꊟ·½ŽÄ½âgtáOcŠŒc×|ß¡°ûž"gEÆâ€¼,2.ü€|]8Ùdk@F¿N6ù]]ËA¾ýxÂhXM »²gð–>¿AÝ6+ËÐ^<??¿à‰â ƒ¼Ž'(Á¿þ:?Ñ×»8Ñ·©Ðÿn&TëùNúiÛrüëÆXÁë-RàŽÈ¿Ú46ùLJ: %¾OOüûO8­ZƒÔ ¨œqzÌë#õØv4 üæŽÕ³3þ5“Á6)#œžÉ½MŠ·„%7LD%Ôd¯¨kªTm¿²2úMÀJWñ­j!ežï¼'w¡g\ºmà?^áÆ±O|wÊÛb*F„Ä2­°Neµ’!ýÃMc)kù^Ò!_¿^&R„1•^&pŸÌ×Ì­4…øšß¡¥_÷–¼túÝ©W›­+ÚŒ?&|†ôO~Il â´”•<{ü#¤ë‘ ¹—³{óñ¥ë§Œ'¾»[m’»xB®K !ƒ‹Bs6hqx£èBüzø8Ûµ”bPÅ^ÿÀƒÊõáÄ~ÿû&­û¶+XxË ’‚|Bç¾#TòNà×/…-¹â^€@‚AžvI)Ävw×ôÖ¥“'ªÊ ž(º"‰ÃèÈ *ìÕLŒ`;ÅáuY*%R’Ä}÷÷õn¨¸V°~úî,ÎáXí2’Ã>4<Ѭ¦2ãRÜÊllX3`dp(ÍhÎwOZi5„ž‹¡ Huÿš­}]cäË—W4aìD8ϪÌJydä{íh𙿴g=ýâû|;±"£^'¸¸YB~¬hší&{Ñ SÏ[ޝ{Lî†÷ ^D›);üz‚Ê=úÙeÃN×-¤vTÿ#>W›¡òúIÛ¼6Šþùü å˜æ ºP.LnÏA^>ùÈœÉÂéæõü‹ü(}^ŸþŽE)všÜ ÇÄ^––ãÔ“Ž]Á± I—´ê]A2vÎ#= ÿ87Î#px…'Î#ŽaèÞ òuÅ0ì¾dtÅ0,—òe»uFFjt-sïósÉE߃Œ¯}Oà´¨‘É%kÑÍ›\Û™|ñ#=Ÿ—~&nO2ÐàÚÏ¢9 ¯ýLÆÃU_ ^QØæÙ–±õ#x&Ä~£‰¤jóVê¯c‘~iI—!=-5cT(>ÔÚÊ–l+{&øúÕÇPžâ_èfjf¤­œM_ì5š{1=FůSº bá«òíñiôñ_&Wç™óº‡a6߀N,;%lu¯èÐp`류ñ¯ ·D›úÂÖ—Šwk]/ny€ƒµ± ¨Mƒ’Z,ám>âûŒÎbÄ…ªyüº13Lwyt€÷ù¹­³æ^ñ}ÕEç¯ø÷ÐÖ¨t>é]a„$×ú£ìö…ƒ5rhAeR)ÊÓ(‹/ZÔ!i”ÅÑã/ePL‰Wí#RšÙ3‡Œ£ç³sß.кGÏ»6‚QášÁ•J˜äU§Gá…J˜ P7WŽ£ðB%LµL±öˆ /ïÓm_¾Gƒ'i¢7²¶ã ÷9d…á‰w>îÒ» !=OØÂø’Ê…™’q‡í+Šºâ#‹Bql›¸Xmòå\WŠª2þ0lã¼+7»†x&¶ñÑ”œÚò}j!-âMÖÿþG~R³Ôãn%·–!äéXbDµ/ÛÿÜ¿Ï}…kÆ÷ï³ëZ„¼~ŸcJòü}ŽÓD½÷cù’L+gÑÑ݉>Å׎âÙÓÝ[Á£ &Ç¢èd0ißÒ¥£¢› ½Þ÷ãN5~·þì_+ƒïhàܨ”‘£8®Ò©…µÎµ@=Á´rr>´9nVü~ÝùÈ{®(ñ;º¼OÕîàV°wt¢ú«æ»X»&ÚV°úí#ÿS©ÀBÓJVôU>/\ó¤•J€AŽ¥ñÛ‰˜3m12pÚ8¥<\HjÁ¶ giü TG’sSÖ‘zŠ/o‡5©1’‹–W`ëf‘¬-2íyßB¾½œºi žÛ¥ëE8»öÛeµ$›Mœµé¶éñš†¦ý¯AjwŒ´J‡•îø‰«¯®žHó¤9]šeq)¡·Ç’Q !Š*"þËò¦‘®A蕬C:ínÎÅØ ¬+í›EÄ!´¬çf*-òÇÏÁ¤‹gRˆÌä‚Ù·—ÚTÐ]h`éŵTr‚"dèVËÎ\ŠyöNé9Ò¸©O߉WÛdÅà 2ÒR&Je ”õwñote󷣟lªÌ[˜´¡@–íÞp7=úM;ÿiVž4ªî§XOŸ»ñ¤Ô«å|×¾=ã¾9Õöøó@BŠ¡k9Róx\7¨$}Çõ»´zºdβÜ ò…šÌòLæªæP6÷›|ÀÃD³¯WºŽiÙa$ÐŽ´Á­)R:£®Òé;iükNßFìf\&Î[Ø»>Ï£â²5a’­²mÁeÛ|£Úæ!šò[ŒTûtm£B†”Ð4³uVßIãß?Ú³HÍÎbKÇVD EÈà 9MVÞ/þ„˜Ù«HOº)å;òlï!ÍõñÕ¦O\ƒÜ©áóú=ªIž×Ä!IÇ÷ñ8™ï_o„¼ïç;û2„¼˜ïCµ,pþý¼ïæû´‚“AžÏ÷W¹›ïŸ÷Å|—~Mh¾Þó] ñ|ÿ¼¯æ;×óv¹ÚXÊvpˆ3òηØÈãó¹'=¹Xêß“ž\Âö_ iZ\3¹óV"ޝÇ;I t„8~^rªµñ6”¼þ‘_þ³2Þn2¸â?óÎk®äÀUfÖ$ÿú늫ìZc¿ä,†våà8Ä · z8O½ˆ<\{Uìu…h-Cký·¯Æ"¹ø…_$²Ñj~)¦ÑÂÒ¹r*—̈­ŠK÷ ÿº3 ³X§vçYrߌu!Ÿ<×¼\—HFiÚ´ùöʽ‘ˆ-fÈd >¯òãucð²²ZÛŠ®;6{¡ãަ‡ï¾%dí_rMj®¸ž&FéŠßüÃÓq1ý”’œmÃÒêVz`Ì2’Ü·m>@½¥¾0ÌMq«»8ŒK¡¡Í›eÚ>Ó<•ÌV¯‡«ºÊ¹b¼5ŠýíÛ¾§U†¡âK­ÿ‘«SYØbÁÄK)D–¯‡±÷F‡ŒÚ2vqÈS³8¾©¡žÎøÌv¤Ñz~”åíZ·p§Ÿ£òŸ Q é7Òñ¶ù8¾UØbÄ- 2ø­*@ø“<þ¦?gŸý²5EëϹv‚øº5E6†K¸fp¦-`ðûæ•”V«¤Àý²*£øHw« ¶:ßüÓ©ÄÝèV@ ”Ü¥zäÁ O¯1æTIàKlKû&Í€á-y–È`T’ y³8Ú—gTñ«v9ÕŒB¶ÞUœ¤"Wæ®9D{¨%Ÿ›Ô„¤iÁ˜Oâk[ÆtO¹K&ÉừªúîµXÈ–Ö}÷ä²Ö+5®œÊiòx £So’Éêqª¢&ŽýïÓÈU:O´õPƒÔª|C q \ºj«-£È CGK¬ŒØÈšf«çbòu©`í‚É#¸U0ú¦ #ƒ »ÃYœÀ[„¼V0šŠ' F4à Fy ƒJ.¶’Y2¦”ÑÑ–H¿Gà€Ü%’_„ .Œ&'—OüÓ_ïàš¯¿üúÒ!äõ¯÷EÈð˜~'Z½©èaÌ'ë½Cj ¸õ3yDWòh;ïÀ3Èð,¥/™y¤ô“‡Ÿ°ýIéWscþ”r°µ%Ó°ˆ3oà>?ùëÒÊ_·déó|¦BHB‘$;íKH·ŒéS†­æ8´ˆXšÌ B¾œ)´Å±|¦Jì°_ŽWlÜi°%®ïàBƒm£xv]ƦA¬ŠK™1î¾{rÒI¡£s:š3š#äõ~B‰³ùMíJXH]%È¡À3g1óäïbæBžˆ™³ƒ˜yòw1sŒ¼3gy'fNòFÌÜöX%3Ç×¼3Ç÷y%fΘyr+fÎ}1óäÿ!fŽ¿Ò­˜ùáîÄÌÐ;1óýމ™ãwõ|ÿzëü)mwxòÄ•:¦ë ,­³¾MBžlŠLyóŽo^‹õY1óÄïæø¡òuÜ›’gx_}üDò<©8*0¤Ç<¯h¶J]ÃÓcH¼6ßÅAÉ_¯+ÛášÑA„ùXÍJ'„<'¾Q%!Ïþ¾–bëA–*¹‘R—ξ-qoé)@¹]žh;Ž$g©ø?¾ìv6UiÛf]·N8ˆ²Q nºîm'† B‚€•>êLp37+§n‚|5Ô $a)ûn;¨$^Oß.dW”êŽYë©g´Á×ñX¯ã†òae=ô:%^Oóä‡: –á·û iFÌ'Ûëtéò‰#drþÖb¼ô;9ÇH½i'ãÂ+©ôÚ}K }¢–Iõûå^¦D ú¿§§>…kÅ{yQõ§éÌVÖZ:…†à… Q?-%m£/†C5½ä1éÕ2&/KÅ™­]Ût=P³‚~Ÿ•žï-%Ô 2ô&…$£8[q5È—5øîì†W”eÙDçÔ2' 2òÖàüçR™!ßçšObÌÜ€A~0yX…+Ã2¤Íž[—º$|äõ,’JšqAÖ#ß}LÏâYÒŒÅV`dˆÂi55çzXê½`—}¥1Nk“6IHnÅz‡‘ À¤7§^ç‡mçyž÷ì.RHÕè&‘‹Ø<Ú|t‘EøÄ¡ž¢ÏW)ú±«Ž*Ù:Eÿ圕B&^]Ťº†¯ú‡¥éñ³›È”´J¢©g5åÅV–úôê%Š]/ßýR÷ýÆ8¾Ó§'°Wš2È2– ŸÄBr€†'ú?“Öÿ¡‡{}y…yÃ_x9L¼f ÇÐèwGV1HF¾íú†œSV›†áÍDz—ÀRb ž[aĬ†|'B±×FtìA‰f% èšqÒf‡«&-K[Ýßõ»ÔÁãOÛ¹ýG•~ ³5‰«ÎEÚ–~,mçf¡º¥^BGÙV?A â–š¥3ŠãUC%ºïݾîÕ‘ðÄciƒ|¬ª2†‡kyPy§âO —/kÙ´â1¼­Æ¤>D¨ŽÇmk¾C¦ÝB¡ƒj›–Ÿk¿å¾¦Í6c¨ëFÑZ˜µÜ#¤@[™—øk Ĭò ¨ºMÅn¶á7>´~Í¿Z¿¦Ô4ŽÔl#‡…%ÔÍê¤k†X*BÎ6üBã†$Çkiiº´b[ùâ{ C`Ȥ³¯²ÏƒÄíÑú²gý´Pl{9 Ó‘r24nÐÐÈ j}<*ÒbdL„‡{}{aQCeã>±9Ý› C?.,¨ŒÛ3š¥5É; ¯Jû_oÉŽq]jyÙI|C&$Ä®hÁ+öømñ5C—ÞýHºŽ 6Õ½¿-B¾ÎÆ*gb¬¦-F^n¿Ò!ßçÝz’z³á'úœôà‰“¤ßƒ—„á59õà%aˆ…Su¼Vï³­ú¼‚Ø uþæçÞyþ%?ÖØIÝxøÐyõ$ƒô=|,ñEDÃ{=}­tizõâÿh‘S9ET±í’¥2"䡺j„Sśϖ#ÃËdÕØÂ×üÜh*Uø!6ÎOçË›´dÓ 9ê0Æ=ö€œy—~)…–Äë?tR›šðÄÆ¾ßwH¿ùý‡g3Î¥‹Âäxàu¡°˜GbãÅHHj¾¿Ê{KV_]P&!ÓŒ|]ÌŽÝi+dtY+w»þëqÛ@ñu ä³ôǦµé}_÷j^¬¯Zâ÷ÿY‚ºÞH%A¥œ”\k‹Áºì;:¨•—àÁÓ+¼ð”Õå%8!䥗à6r†áÍ|äë/óNy]sóÝkìR EÉå0iBÞïl\3ºP òE,_G÷5ßǺ¶¡lJ]‰Žg.­òò\òþøÀRcŠ Û¶a$’†”RJË,æ Òט‚¶²½h—½m12ò5Þ»vi çÖ ßH‰À&ɶu%kJògïPk|®êÅÈ¿èÇ9j'ûÈ2ð”¬NÇ&c{JúUK¸OÒONqÜ _³Xe½-2¾e>|[÷Ýã[ç=¯äÂUC<ŠrÕ€ûŒ®™rÕ€±=nš°¤*ÌŽèào`ùþÊ u” -¸¦/Äåû|’ÿ#ìJ’Õ™í–llŒÞù«ˆ{—¦¢±A4ŠõO©&¥Ä†Šú¢F'Èj²=çÕ)w˜-¸–|»–&Єجi à²jˆ;Yž³ ïçÖ…ÿ¼*ÑOå½[ÿÒ8>WÞó`´™ü¨³zc>Î묂1$ɳãfd,˜¥äŒ›ôÒ)2:àQ,„À[;Nöêâ6ñëmâfé‹GQJdL°Èø7¢œ^{äã¨hBÚ4~Þ›P'Ðq §-`ÿ˜†TÔ·¶¿ßcJ{­sЕI‚Ž"_§~‡$IXK«meâíOï8ý:m¨mFǼ;îPMSg”? yÐ;5£{z¨‰ÝðFÞÀ2"@BáΥǾ ¹v «ù0ˆq(ê‰ £o.Ve]d«¶’"wÞ—¼ËŒ OŸšHêâÒL°6¹'²yئíÏ@iÓ÷Qán®\vy''N‘ô9µs®$WÎÔ§›Wôz$[ÿƒ!X€Æ;e꬛îØ-|ÃÍê®4Öf¼++Gútpä·Í3ÁÂ{ã0Ë‚£'õ¸”]ߤœ“'åLÃ>=BÊÉw¤œéƒjäȈ¯nNõo’yÛç#ÕkØ@$o\2pÏ ›/S‹^¹g}÷Fä}ç‡ÈéõYÞ AÒ1µ_®ÇTnä›ä- yUn̺}-ÍnÌ{°D˜#¢ÍúN~ú©"Ș mT!—¬G'öq?:˜´A?x'ö¤G¦yêÒGü-GeE·7#ºÈã|ÄHD·ÓÇ™\X*š>¢Ôá¯C`óÓ×!ŽyR BþêzœÑŽ@ÿ†fzÐQ÷ÏöÇò(j§«ÅirR\irÙõ83½ã™êTÄ >賬˜¶³jÖÙYWÓ1o>ûiÕiÔìlk6ÎÙg!ÈûOšæ¦ªd‰¿frÙ354¦Ó˜C3LöùÈž !9ËmmÝÆ´!ÈÄW°™ ­•²éÓ ë¿ú3C6|×òSMA©‹„å:¤ãìcß×¼˜°3ù¥ŸÄ3`:rb.iÐ(÷«±›ÐC å aª4]z {-ë|T^,~Rô7–'·˜’Û)ËSë7grèqj«vò7gr?hÈîLC¶ù¶²_Úf£À†ì4‰O¶G–q†iƒäq¢r?§aá|@|­<L'É.­XÛ~ˆ¡}½Õ i’쌀¨1ß>k¾ùY Û—“·iöÝ6.·SAÉ®}9wŒ‹Ÿalê×»ÆÛ8 h¶ÿLÛ³3Ÿ ùëÅ)òñÍ73k¾™ ˜øÓþV"BÖR -ýö炦:ìðKNBÀJ÷1‰$=—¼Á–ºôy9“¼ayÙ-2úE%¢ÖP‰¸Yz^w¼Qžqñ3*»6Cß4lU£’7³¬Û­žwHÊæg“ÙK¯6ª¿äž´2=L{4íHÙ3Ä>]¾§e]ÕPdŒ…SøžR‚ÂÖ0 þ •ꈌN |*O[dB s­:¶Ã$vßþ<`†¬Ûz÷ž©£?˜!90C®>•ngþJ–7aǶ$Ýw@‚fe Ôó?u¶Lã†mM©WoÚ?~Ê”S¾J´ža#Ì.€ ¥rûü4Ý©ª»í†oùk(1`ø¼ïocëH‚dCÓ¾:?f¼cò.‘b•eÊ®õA³§·˜ü·k—Bd ýRcXàï*b*¬aÅÖöUVä}Ç<­¹uG¶ s>g [˜‡ÃA_·êÀCçô¥Qt¥IëÝØçã;Xj;ö• øf¾.ã™ì$²‹ª¶ˆB™ÊŸ†UŸÔÙ×.Re¬Z±®­rj(2¨õpeÇ*dóqôéwßÖT:­#‘iec F=Ne½BJ—ljǵ≠Ž@ÞÜ`~+c0co‰êw™`¢O9hL—-A ø3œ"ŸŽjÞª7Õ†¾Ç1¨û 8•¿*yÕY㫞Ïã“î^öûèLQ—Lú/JOšéd6 7Kš^Nšé€›wGz"^*µíïÞ3½îw\m~#u2ŒK-sôC•©ib¨_:þZðÚN¿Yö«e,§K6fy;n(õD”«~UÿáZ ›þ¾^y»ø™÷­|¿Ä`Õ¦Çß= †¡Bá8­±r"lú³ºŽ{BùÐ\÷.y·kУ߮›=q>“s®ŸJOº5£‹ésç—»þa-å—¯V¥é>µÝ”ZØ ä‚5©'ÈÈ È¿^ŽçVfÅ+iVÈír Zù¾‘S½Y"oDþ*¡~ŒIÚÄ,‡º2è·|e†º‘÷£&_xäõ$ÕÂÂÇŒŽ×H%Û,"#O±ZÛ=¨já¯m˜I›élå£)™R>ßgìAFA‹·moéV(¬_&‚¼uÁ:Rk¨`ç×XftÌû·YiâN± ÷³ÚXµ DƤ*97d]µnšfÛ{ä5~ûcÇëUX•”b«—¡—{9dòÅfw¦¢n«¹AúÆ7Ëi¦Ì5>,ÊTœý¯™ìjú [Ó­Ro¹°q"HSÓ·þgZÏj÷ž²*;F‘1á5À/ÚŠ‚ÍA>¦2Kõ>O¢¯³Y~è{&©Ã•Ÿ÷ÔÕRγ ÈgÐjjŽyhʲÞ%G™¼6Wð±Vv]•Ó§ûš>M– CåTÕ6¬F’ÔCÃó†9UP¹Öb³•W‘æKzÂ@(zjé«^oÞ=-À0mM¯zm§7}[Óg ÊJc²ÁTÍÍ…ÆŽûÕÚéÄg`Ÿ"«)ôqàÇ®c Ïs86᫦g)˜RÈëåˆÆ¦346mã×ò¸«ºR—G¦|Ïeá}Þt–ð¦ H/çh­;¦Uìß².Û– ïÁ:±EgêéoÎßïª"HJ¿aÔݸ8ª)'ȇ;òò—í.iºü“å[þéK‚L¼(«+øšóì“7<3üˆ|þ"æ‘Ð*• úíi@Ì£‰S51O=¼1ŸùK(âdÂê\( tÐë5P\²MZå’åëJ¡Ñ7tR@aúô¢ÐÛoŸjkm†‡ú–Ǫ 剢‚¶¡Ý»ÆÊ§8ˇn­û|¡Ð‡ƒ¾4ùЦþÌåú®ó×nTSœ÷.GV}½‚•…x×UKÿëÓqpg†ûn2¨‘êŠÂˆ¿{¨6ð·LÍ¡­T¿h.FÑttõ_4«ˆµ|YÔS.æf›òj Ð+@õgÕ6QÕ %¼µ:(ÔÞ<¦(lA1cÕ²‰·­zh´+ÁlPÿ­Û!£°g¬F•¦vl ‘·oÏBsí{´Ü“€¼íx ƒÍ¯®U±ö-AFÉAaärÀ”Ó1oÞz-1NôÖ“A’.Ó=l:­hl¡"ãŸ>(ÈÚx">(Í™üöA¥²Š[Š|~û P&&YÆvßžþòAÙȘ“Mñ39Tl ~¤ûéMÂýMr Éfu½e ·¼få®ãΧ4gyQab9Êujü4=¨^ÎËéÎ/¹ÀÞ«q‡&ĵ¤ÝîŸ ?fòÕ°åH릭Ε+ˆßþ<©ªo`|%Ȉ´"Ù¶W™eಠy#7f]6¶Í3C#*h¿Ãæ?Û°5Ô|áù2d|d»¼< ÓoÄet›È}{ØgD»í}Xß|êmÀùŒ.ßéÄ`Ã3›]ä^ßÐm9]cÜ– òèúEIVÚ S«ö|QlAÞ|`°®M‹,‡ýÞª¥/òîh?m³Ûœ ŸLŸÔ‚)ºž…’”ÖRä>”¤« ”” YK?CIãȤòí蘩«ØÉ1™)ç©èûн‘™‡âv#.GÉœmßdtÔ"éD€¼ý%@4Rd²F0Ëý"¥Ü^/ÿíd÷åÞU÷ͺÊ"lRT»C|^²!Èßëó :ËÑcO™WºPg«ÌpÕ=HV]Y¹U'^᪠ª¦É5£×<\3ôé‡ë3ó—Gô8_Ÿ†¢Çi¨s öûã4Ô™Ù>"×§ u"2=÷ù’ü%܇'m çDÃ}# ÷!òvT’àÀù<(I0zkï÷{zZ¡ç•IR^wK­~£J¹•nÌ ™’*œp£pâïßL¹Wü‚¼Î»eèÝNˆô¥.qß ð=£Saî=Å[tÌ„­ÿäí„~´¬0þzœC·}}žÄG /?à/Ÿmóà6–Ó§ÿTKíÆ {/lž±j‡u}ó¡ë0’u¿¦t0Þï¹ûõ'IŠîaÓäzÂyÐýð"5s2Ý2øƒÉà7xo{•¦½¢ÎŒKÉ8AÞŽ”‡ïØ{Èý~)?ñzœè{þ®`A mûí„’’¸Bî÷³Ô d8pÌøTî`™0|{R@lª3žJwËÝßü”µÕ`WGXþÞV‚Œ¾¥r bçݶý°ŸãÿŒŽ—ÕS±nþ=¹_ÛùQÙòÞLrf;d|¨ê}”{r~*ÛN@>÷Êd¥Sç*Çn9\uér~—ݤ tüÙ["ÊA‘èÞÓï@‡í7Òe”#î£ør^Fé¿=ÊÁ (}*wc¡îìiÅsØ'¡OeÓü6àǧh)2B:Ø›–J-ä:Þóê­"(¤;?PPÑ éüìÊ8ÚÚê(Ÿ>—ÔÅÅVã{ÞöIÂFè¨MŸ©}òn1ßH%¸éÆ3ŒqµVŸzµy è½*ëð²UÖÓÊæAÞƒù, ”õ&ßè!Å·Ñ’=µ¯_¯bl(Ò÷ໆ ÝW ¹â.Ž­5ƒt4þ¢ÂðZh­!—¤ Ù1^q¾C¦Ž’ 9»`LùêeG:óo¬Ú´œ^ŒKõ‚B¯a,Úh´ªQë¼jA%5¶KԲÖåd§)ÔÿN…<`ÓÂê-g_©€ZîÄó4rÚäVÎiÿÏxØÂì—ÃT÷è)ݼ¾?ü‹*džõÛH²6§²>GúæSñ­Åèv|÷çÝï>eœ§ø´“ÈU‘"2 ¥mâ.eb1w'‚J¿yƒG|Ïä€7Xào0"OxƒñþˆrŽ„Q¦É0`ãžG)ûFGá-§‡öäI oÙ8ý–E«±w/|z(~Dj‚‡j‚ [ Èë·ØƒŸl°í6¼eÑS·SæÃ:ä=>-.’–­‘Ñï^3ßÈÇó9tÏáÓwþ¬#$š¬sðEϲ6X«}/ŠñÝdP¾ÔÌQ"僚Íj"È!Ó×ô³PûC^ѧߊ|›"소­ÈwcÆÒpþ³nP‡B¾‚ŽùÀSñåÎzõžre™„¬û†"Q=½¬Å\nŒ …Z—å9ç}ŸÉ¾#È4ìÕ5Ù1žËB¹i=æQϨϞô6ßÞ|ÞÛ\l3…š} {®2¬(jÔR¶ƒš®~÷{F?鈡rÆÒ4=mܤärÞ$îC»¾«ãw“8C§"ìêÐ1èø‚§>[-7†fS²+‰ÖÕº]A–:Á§™äO¡k®. ¬ä´)ÍùS/rPæ];ù÷¼êEBÓ(óG(Ñà!Ž_§^õ]ûTNØØ ã¥Í‹vê–ˇ $•ÜwôÎ¥ešÕŽßPOŸ o?œI‘µàL¢±žÜ\ÄiÉ€ CÉN“CWì×ú:V+4ŸZ ®†º>–1Æ!›~ÈAä #Ø‘Û@‘‰Øøä£½žieƒÊ\nÔb~>þ¹?z-9šl)€ái‡Œ½~tÉl‰ËÐ\¹sxy%qÀïõƒËв+òñCÓ\ˆ\ùÑÓ„NÚ·Op)—;ÔàùIâÍô/d Œ"Œ„ ‘·_-ÿiþ|ª4m“¾Ü ö<Ôˆš2h¼aXTn{JÓR=lRm¹ÆÝ±éå›"Þ ¡¯÷Ýæøžé…|›ß­[Ÿé1w©1¿q…¤'êŸLf“7Óè<Äæo„ôŒýz”‚aš5½ÿ…9+Óc²…!Ó%rˆ|†íô¯ÉGŠŒÂ:RS瘟Ô‘ˆLöý,¶¿shëæ]I_O㫬M@*wgÝ—qÅ„3ïWÝöç?#X®WòðY¦zm%LÓ€š`ûc©ôé­9V· Ãaiº×ì¶•œšc•½—v%Ȱ£ÚÔ½1& »ÙD7’P0ëSlËJútÏ® Ʋ*›-Ï»²!È8(W¨™.˜Y1–Ã:}è˜_'7zÐv毗˧™Ð?0©y=`R×úm îlÅëåT7d‹Èè¼=×ËaÊÎ¥ ¸y j¼©Òñ ñs)Š+7ù¥òì"B×Ëý/É>·‹¯A=ö.(±KÌ]I=ö?aÁ0|ðu•8KßììÌêH¡Ì•¾o Ò—Aýš½fÖ×yÏf‚¼}ëáyh–OýFŸ~?@ Þ‹‰ c‚´Šž Ù¹.A>ý"?™„µÓ¦¡»ËûZ´–._Ãzl‚œÅÇ A¦a¸Ö<~Þ>-oÛ­¥_ä”ÞtîÖþHóò‘hß ú«Ú…* ¬ÎÕ£ϿF¿ jy*ïœÑºâ9’—FV§iÊ~V6β6%…ÞwP(3Ÿ»Eíù¦.(£®/ü”¢ÚÉm÷YafÔz½Ÿv†I+òí¡É7t©¦¾ÍÆnÙ}ÖÓE¥ ’ÍІ‚$F/Õ«ï^ ý†–Û$—n©ú†cõ& 7dİrÆ•×ÏvЫëþ‡Œ’-væe=´ÊMÝí)Så ™•´ÐlÔ¦ÎEžor½}Cµù8ÏÅêYYJ' 1wcßÕy>îÞ5díÔå 5+>Åg¨k±Û«Ñã õ±[ÛŠm7jòKã“}©}þ¥/Õ¯ìçašQ•& 4¨Yj!ÃP9dDÂûšÚ”9©¬MñD õX(ý—èÆ¹–®Òë M°ƒ` ëõzFêå;H;Í í$z)ðéc;êþF\v×äi§©Ûžˆ…½>,|xÏп…©»þî׊fÙˆï™ôwCÁ’Õe2d²ƒ˜]]ÙøéZN·ºàZ'XJ?óiÍøjY¯r7fL tˆ[믓äùÓÒÛ€FÄÏ|tÙ…¸]¦Ž–OÅF q_£ !s£‰yOÁ È+QfTŠGÞ*·N2Š$qNf%½¶€‚‘·ßå ¼í0–r΢‚ºË˜"£_¶+WP9á}|þQ³äôw%ÌBº~>o%ÖŒ®j‹%Ö× àSw\b‰õgœ¦×kËðüŒî´ëÐÚ"íÊú-ø<$ÆÐÀ„`•ÙG[Öí{7¦)_øŸ!ò0?R÷fýüÊæ¾çïµ–‚]ÅkiÐk‰aïÛ5(Lu}&z vª^x%…©pwÂJªìJf™ºŽZøß…©@’¦‰'xžM&é®AÉ¥WŒ1œÓ œhéù’Køô³Êñ$pÅnÛoÃ(Ù±© bSøžûÒ Wb¢î¸NYš’R~èYšEöiÅôÿ„]ɲ£8ü¥gŒ1>ö}:¢çdv‰UlŠþúÑZRaðÞ;e€-¥ªÌ,îßRzÝ®´V«m×|}·&ñO„:]œX“4äµ5ÉìJ®7ÔéâÄš¤„otº8µ&©Èkk1ƒïtqjM"ÄášWÖ$ŸÏ~iMÒW‡k¾.©ZPvtoþçL<Ì‘‰¢kÔhã—«Pê(´mçFô#\4 R¢iÛTIä8ÛL2rÌ&íÜ£‡²|•;kç,ÃH¤è€3J×–ñ§ùm”ù{—0Dîæc WæcªKBFg²íÝȶ)BžŠ±w#ÆÆH»,š¥Ödhä’X´[QÀDº{.̉QÛ#“ ‘T’‰ê§+±Æ_Ó3}•*”ÚëPÕëJ”¼êa¹Çg^Df¹Q¼iëßB¦/î÷<Ñ ß³B&ýžåæô{ä—~ÏFÞO9¤B3Ñáw>åIÛ-UùŒ³ž4pH¸ªÝº€á7]Þ“¶ÇÈÈ«q+«ý‹Ý:’u…óž~$>ÀtNü¦ãÝQâÃjGr]m« @>Âö*¦[ê2w¬÷ï#“Ð’Ñ|#eÉ8¿ÒÕù ÙB:E ’>#xCB¦^·ë¦eÎ ºÉ-ßýåyEšb]™÷)W0¾Þü:óég’ÿ¦õ›CŠâî«ÝúˆäØõ:l—º"… ={Ø…‹fƒ7HÞWÃŽÑ÷Ž.7–cl|áhuÛF‘Aaå°‡±[¬ò¦Vn±0–={Ø$™UH_ÚkN“¼.,õñíRƒÐ#^ì-Žþ‡;adtÑL†Ô®¨t ÝàÏZ~7øÏF^õœÕþwÞ¿È(õ ã/¾Ü¾= £‹ …ìæqü8ò# çè;õ;—ËÜ=9ðË ª"ˆr§!£°Üìt‹…¨J>ÀP8Á:¤ Ý#C*wÎ2†PÄ\Ô-ûÆ''ZêÚ-åìSBÇ{Ø#¸Ö^Êm+@'r‹ƒ„°JJÀΩ¼”iÖuœÛé>/Œ¤[]³§å¾íy÷¶…ÖFfyܯEŽqˆÔ) EQùðÝ„KW‚™—¢˜É²Ï™øÁZoe®Yä«’@ ä÷V÷Ÿ”õí:ŠŸ(E¾ f]T¾ rU†¨!Â6qY:õGÁTO |M—6Póš´XšÜ™$8h¸ LuߊB;Œ4O/! ]Šþ½mþ©·Àª×™‰hhW­Õáª1êø¤¿”ú­M늡¾“kw£~+ëá픆šPóþÍV¿÷#ôéŠ!ê[9çi!¬{ vxøHÃ÷ƒ˜ý Án *g'r=Ó}wýO2=DdÐ)eda½ƒÎ NãkÖqÅI—Ó©; ÃfƆW§{¿°­oœÂÂ"ã“’òlKÊðF_g%eµßnŠ@.ô‰´-Æ aÌÚ*{³~èòþ‰\³‚fë7Šq8é\ß›jæ„#ŸÈÞ!B~€‰rÿ1eÚ Wy¶(Ëå0JbW/!ÖO]u«f’ƒošƒí&å¥-T§¹ S 9hò í-´;@Ÿ†Úˆ‰kr§Õ(ð÷¿=VKCª5jÍûalÜÎJ"L² 0†Šr¾ÑÃ!#ùÁô0ûÈÒuýV ywë†-2(É6eîÇ2†2XËú.WURŒ|8³‹¬ƒœˆÒÉÏu¨Vg“$׆ÕJîÊ€M|K.å®mSÉñW‘swÓª†õf3L¨$ºæ2WB>û„‘ñ•0vëÈljaWFÐ ã,2 «¾6 –»™ºŒ»q—Ü¿ðyQ¤ˆQôBZäv!UF;b* ‚C‰É₩ÿ±±ù™•ùD 2½[’üÒ1Ânp*ŸV“Àó½ŸVH¡‘3ÖžðÖPgpÊÚƒ)—¼®-÷‰îHáîþüù“ՌE÷>Ÿ·/~À¡hæöüfÕP‡ ÇçýÃþÁZ‰Lt튭öw¿Ž0• bö¼¹gü¥¡å°ˆ ØFž¿ÿÁ³ØM@¸æ—ÖXÊ»·ö×¼bkÕ¶Ÿ0êo¶ Bޤ‰øÐåÚ“ü6×´Ñ Òlûiy¿-ÏÂ6Sâ<#'la`$É•ù˼Œ+%$¯Ÿ¸V¦ûð™zÑ(d0B{Xëžé¡ÝA°ïC¬çÁgWµÛÕó]ñ çf%GHOÈRÇ}wÅ1ßÕ i’çëÐB¶°‰sÊèœ/S.:„ôt¬ÜÚç6ŠâTÊC-¬!Ï0È91(O”¤¨œ›ÜX!ÿfü;ŸfM6vD†ÓJÙHë¦Û·7B¦Wf“˜ðï|]®ÉÕ©ƒœ3µ(ãW;Ž×ª…ìœéÏwA_EÒ£ˆÆJ•iôb¬°-Ã._ý0;üæÛ2œ°ÃUƒRˆP[†£áKG]Y…¼_2ÎÃ&²€Œ.yþ…¦ñwž‡?y§ñ—õ[L\ÀΙâz¿gE,óPÏŠ- ï3AÍjˆûòò}ÊqWLìÛiriû¡Ó®Á›«háŸiLK3¶¶þîÏK5ÃUUȉñ•bäIcZe¥Óœ󊈓|üîÁ¨{ù¡Üt¢>I¿t}2º;!¯¯ içTÈ’šb,ø0ÏrŒ¸‘ºÞ¥–9«ÔÊjU†V3ìœvâ·)’Útg+gpUŒ¤åy¿Ìâø·øã ĺ;õâWtU ¦¦@ìgtQ 6­r‚ñ+,d˾ËVdùô¬ì+Ú_óáPº¬ex‡5_‹wÏaƽ>åÐæ¢*º©iÖÓ !¯ ¯­À×¼_3)a}Å_™”Í0ò„I9Í=fR¾âO; £‘Se_îeÛ·ÀÇÿL¶=O0‹__$ÖAó…LŽ×,Í™OÑþ(•ËÆ‡Z”R(¤X„Œ°ù„I É­pž*ˆ©_Ï||wˆèÃÞ§w „¼¾;ïyaV“€ù÷º4t3Ú ˜›ÑÏ‘k‹îNëÊñ#£ÐÇÿ É߀ŒŽ RU‚Òõy'Æ}òhŽ¢ZØZ/ J9Ÿ]$…îü­~ÕºÿNÓÎåey\u+#OTùÝmi…‹”£P büÜ ÓÙp\d ˜Õdë2B =Û²z©—²£4‹¼t¶D:‰‚®!½¡w.?~ŸE_³2{o|ÍÇ™º»R–<¿¥Ç¥î®Ö-–9EÈs} ©É g©è'ùb”0´=iËØÚŠÉúëV»¢fþ-]µÚÕ t×¹ö_óªÕ®iÊK™ày÷ÉÝÜZ©«V»|¢c‘'­vÇ]íÅ*?ÑOØj׬ŸfïP™†zÀ }Kø–Óbn©§.wÈôô}6¶QúÒÊþ~dSj"<šÊ8¤æyAJPÑE_ó¢ 6adæªz?ÒãSžúª!#ºý\t]Òî*eÈÛ7˨iö#ùv»îè£t¶p.n=¶36\[§™èvÿX“A=;ÍÙ ìö9sÿFYPURèšzsÈøB-¯Ü»Èß"£3Þá:•Ê‘!¤IÿÛ^_–gœÉø“`?f‘q°kÛn[ò\Nß[»5 B>®²VŒÔp÷s㱨œøSD·ä[›Ê¹ƒœDtK®Ïš*ó(P |˜ÂÒûè"º¥_¢‹l£`ÝRÔÿ†XÇVCZW>Á˜Ô®wšÉ4L|­›™ç°ÚjOÂ(¢€…ÿÑa®åSF]¬–Ó „!Oô @°Èø¼k]¨@°È/ „2ñÄTˆçW2ÎbaüÎRfª¼¦•< d(ßãRb¤ï+“+-Ó²š°j¯&Œ¼‡H7‹;"Ï2$c»Ó1uQû;åQ¦Ÿ)B>Ž´XíS°³vÏ(¾frE ¥,ÿóyI …“~ÝŽQdgrY•t °…†×º­%F^»nsØ>C™Î?d¨Æ+Œ KÛŽ _±áf]!KQ08L2p~Ö )‰|ÝÂ`02S×íœâß–3Jwè%2fìŠï~庋êðì×®ÛâðD_\·Á ÛA¯­ üQúŽ;…¨1bܬÛ^È@‡ä=¼ûèÓÙ×Ns^,{Ûf!׿BòëD}N·=ã‡kz×?ùðº/“MU6óÙ?}ôál‡2téÔïòäv•Ml×R d k#®P Æl̤;ôŽ>Û¾…÷[ŒB=ÑQ¹þËÇWýjŽúDŸîùÁ× ûX$”32Ò¥¹~$­ `Æß?:pØ™¤yó¢èý›O>Ê•:4ý[µÿlß2¤P"‘ØŒp‹Œ$´%–Ñe™w°€ßT–ÔyÃz“O´Óœ¼-2ñDB‡ìß%%r+¥øw>ý¡Æ©oú÷̪J02urPߤœBb¦tøî¯‹WsŸ’ºŸÐ%×F×7WÈô[#py@1òº¸OwÜÓë^D±yüH~})áÉQï8÷×·Ty ¬ˆ¼NæX¤ŸSl)¢øvÕejgãN)¸hDñ 7Lƒ#¿òÛ˜÷ŽçMЧI7Š„:+<2wWÉ–~È ÅÿG1†ï£ó„dä(Ž¿ÓO|ª<þêh<1?æãkX¹u‘`G@º”\UÉ@•Œå¤¤ (‰²ŒeÛ£@×ñ×ÌM7–tËp¼¥Kë7]P衟ÕqЧr‘k© ÿ;ýH>´jdD(å½ö—ŸG¸§"%k930-â×õ<º£‰{¢Ç•ªJ¡0Qúx 9Í«CMU‹• TîA0>·K€IªCZ&pš—d{DígyöGÔGtMtîçû÷ôfíg|Þ¬uz³Gȃ<Þ”’¿ûãÚ¢NS àk.ÞX•G*¯ð;ôáowè6HV|ð_3A« é-’’v.BÞÏ”~=™k"F„4)S£PÅîDjù;!5ð…)©¶”‹òÒw\ÓT fN³-ÍéÀz©È€W®¿‘æóh);®ýPU9CÈ Ôè"@u÷!+ùH2›ËÌÙ·tYXV^ äÃyç›8Ý‘'cÑ3B&î}ÚˆÞ&ÄH³¼é†Ïp¾ãgyM2ŽyAñ¥ÞÞwX[ÆöjÂOô:µ -e˜¾± ¿ùo]_ë±T5E—çl›Ùáö†vô¯z&è… ÷#ÑÊgÀ÷¿]:HŠÂÐô›{Íëò¼r¯ëÍ µñ‰’ŸïÜ^`DÉí;·w9 £+Æ.†%·¯­lX@^e¡ËÍ/õÉ-¨S@—WãÒͼ ®áÃqQ:ÃZ.¡ó!S!®ŸÛ:Õñ´œçRtÎ!:òlå¯Yë¯ 9ðäƒaêTY5Gª¬(‰/TYJzª²¢ä‹hvÒwwc9y|0ü†˜$ß Þ$ ª°ë–“Ú9E5ÿËä …ñ™$Gæ»=F»£gŸTs&Š«9Éó{5ܬ,2ºò½¢>dJRd Fu ·ã¦™‡mä‡h`ã ¯YÀŸ¼õh7ã *DÇ«ªxÉëàyí\N”7Þ&Wzkï%_ÒbD'jÆÕÕÀÙ–Á˜¼àÛ©©D³c#*èîŽðäÞéòÉ_å#ÑU+0ïÿ>ïZœ¹¸ÊXnï*÷ìÏÃÜôé šj½Ý(BËÊô‘TÙò)¯ÛnªÒûѹqcËÅ(–.Ï2Õ…m‹´NíØ0–žÑ!qåšuk- +òß=9 j‘Üé -òé}p¯¹eã’eY ÙZƒLQ#IÃãÊD-¶ÞW® ò†7v±™9Y¦itMoÜ›ÿqѿγXý ßù¾íÝá#Ý>“7: [' yc¡Q¨T‡äjÞN Xèy?Uª«šÏ{6µ%FF!Ò,Ëù>ÎYß. #ïŸ ðq• ªºi‘1¢ XaŠŒ‹•Šç™c :æwÊ»çM;n™ RbcÔïò‰Æ©ÎñÝŸ™AÁ±•wï«Blø‰RŸTwY‘|oÆu&„-Oßï(T¿k© iéèÆgÐïÈò™\M¥åù¸/„ㇿÝÂB1g #K>`ht”Êkh+Ï~Åñª÷P~PÁf²ò Cm¡ÄäW]òŒ“*›:Ž_êí#jUS/¯Ú©¨èaìAØš™¤±^sg²5š::èÓUéÎÓï7Ý—Ö_5FÝ<­¸×Lý7­™?y?cdÏnʳ)(gþäí%"ŽŒ\厌œõýf˜QÐâá“0^=Í£g|AFÖĉC‡¹ÉNBs7^ÜèÞü%„ZΆzõ”–þ¡×kȨœ¹RÑýÜDW½Ü·Òé0ëm–›Å¿|[‡bÑä¢D“ý°E£$ ½æýt›‰ÞoBÞAjûÖЀªa]WýÖG¨‡òÒV²¼0ÔðŒ_Wåd›dº~Ño}PŽ|'*jŠŽÔŒÕ¼ú­ ›…m50ñßéyW’¨®$8¿Ïcžuh7äÅÜÞ÷ØóÁ=“Ô«y&(Ä?ÐG꽺{=ÜBÝOäàÐõýô)€^fÐ98ŒþÙŸ¨ãõåà#ÓS‡mÄÈûiº_@߯Ãt½€êtÿ‘¾~… ïÂ/Lï׉ç6k¹¹; ßçwß&¹|!Âgå|/‹ªÄН™œæëA7: ôIGYx¾m‘gÇòAÙ"“Ó6tÉåú«Ï*·þš7Á?Œke¶*Ó"wÓ0’“˹o¿bÑzJYrI~8°y)Aš§ï¤ÈÈg Ò“3†Þ€¡«+ºb[ãeÍI¿£UHáΕ˜üà?Ã0–øù¯i”½¢2mH1‹©–û 5› £_Ô_rÝÈ=ãÎØÊ]âX‚òwÔÐ/]$SùÍÙ8Öð"·äÒ¤´¨àNwµ˜ÒsÕ ÛI?3Û –ëÉå…j\Õ+¯U5‰ºyÈ•?c/Ù†¯ÄD¹ÈrÖæ‹½ùÀ…‹|C!_¾vøÙŸ!’êfÆ8˯jZ×¢EÈ—+°ÙË7=ûÛ }»Øè〵j뱬1ÒÖ¸ÆÏ´Zé@å—7­Û'‚zf™ñÞ’/`îdY˜­Y…©¦6Ƹ±c¯­Šjd=ˆ¡á0mL•-¿Ð‚ B¢7uõñîVÿ.Çž¨òŸ¶2üú)y+gû^tD¥&¡Õ©Ô^´!oß“)w“©›&®Ø3æ4èÉ&AðO4Er5E6~м^¢X¾Ú²•$¶"ƒ)òzA±|~ŠänŠlòþ=EyWÈ­ìš,òYì¹ê|Ôzy¨Öfçpld‘ÏiÝ¿Õ!5íëÁ¹ý[äÁ´ËÜ´Û!äûl.å-«ñ›¿|Ï¥ÌÍ¥ø‘ü´«™’†Ÿ!zZ+sDüF¦]f§Ý?ÔÑ´ËÝ´‹ßþi—WÑUÑ´k†¾„ÊBk›ÅA΄۸TPˆ1( ‘#¹^Q­9ârÍ<±  :%aBÔ±²f¬‹É ±2ëÛéONÊÜæ˜Ñçr~CÈ;Vœª)²ËIÙfëÇÿ£®ÈMî›ëóõ<‡êÓ÷~gr٠þš‘ÿ›h×¼ÿ…hµÞõþ7¢Õ„¿ˆVøš?ˆV¼DÈ¢ˆVy@´bÑÊ"ˆV<"ZYä/¢Õ†D+­Ü›ÿE´ŠþID+­ô°xጓ’+&²èAb:ebû›qŸà§>OyºLÇmpÍ:áqëñmE¹gðJßÇlNEA2dðS³2ÉkÒYG— $^™l`,-êž‹}GÈÀÖ»6•J&¶Jòþ­² ‚oÓJ ;›ø1½]ÎÌÙšÚŽ¨ó£­­ü„Æb!R {9Õ¨F®_•ÁXìÀØKÅ(8®r»D„›Ò•„¢è{*@|˜Ü®ß¬V#š”Èq×;9zHˆ½¥¶!3Ù˜(‚U„õŠV×ì+ÆÊ_3EÚC#”wÏ•^wÿ?*Ý´,:2å‚À–1;dc´(bPžM$ÃÈgø¯Ü!õÈ?ÎD& %Äÿ#]bê±$š)Û;„|ûjÔö¼šq¤Å–g¾ûæ/®U }ež¬‚*¨q-ÔÖÌýµ.zlû.o‰(ñ½z¥·>ÙÔ’:Î{Þ5”D·[D%Éí±U±)뢹ƒþG vþG –ŠÒ̃¢}ðjðϳˆ E#·ÿ'ß°Šñ[È"ú£Ê,ç§×ïBÌ99BÞ±êÒ4û©¬IT“!è¨Á0n*¹a›2eù ezæàˆµ‚‘b™züDA n­×YÝÈ?›¢»¿C¤¼¦|ùùaŸ«ðû´ÛmŒz\BS¬Éz ¡TQÕý3Î9‹îõZ5Å:Ñê&šË•›Ì[N04 ¡Éq“Іð-ß140ÒQE®‚[7eŸ dþzÂx} «òömÜxƒÿûÁ.¦m"‹¯äöøiñÅ‚¡ÿ8i”)a:Ë(~’Ûóg0C ¼äöúÌ@[ê¯ù .]©a¼´ûöS8äûG{vT|÷>“ËOš¶æKP’šõLZ-›ø0 ×¼¡Ã Í9±ì=ùgÝh„ôJ,}r§Ã¦IŽf¦½I¨ûŒZ©*œ ‚pº$ÐSÚ˜ÅZ¯šÌ'¹·fysÇ–¬‘м·ÐSñùlß_‡²&ò_‡Ïg;bæÈñ µK‚Y_v›¾áœüЯ˜æð†g†XÔ„%ÉãWæHÁØ#I±ù5’œCr÷%±‚ÄÄtiƒòjúˆœ3„ôîü¹ 3Ä995晄¦v¶E-ªvu ™†>þ&jBÖ«ò%´ŒgyGŽÿºŸAÅ^s&K‚!C‰e<ç‹mÙ³©úìøÙ½Ä?7"wýìrUÞJÿß í%þ5GQ6õ6,[ƒoÏȲçŸê‰ºzÍ©K,roþÄëØÝ§|$Z¯|ñííR÷ŸYiÌVl m[’ Ž¡ðX"ª*ˆ”Ô¼ï vÉÕ˜sKv.g1A­s>]Ô¬nð‡wл³!Qº1«á¦Bùsîttи‹ìεe'¨§ó'qæžšœÛowY‘N;B†6x¥Ú¨&+Н™Ûo›¤'G©ª2G¨qƒÌ=uR®,mšÚåjÕŒA„}dîÅê%R/{¹ Œ|ºW^ÄãR³µù:™EÇ Žk“äý—YÔÏÌï¿Ì¢~¶?còÈ-r4‹{ůՓµXŸ'^|°zŽòæðÝ¥—(¤¶åµê#ò6°"‡J⃄•Q@!žâðôøì"aUJo'êynÕópÎ~ }ªÚî½×Š­¤„~gz;QÏ›c»±ƒfJz;QÏs«ž‡Ó˜4Øü«ˆÔênwYehWE„|œ‡QÛ"Ÿ˜/ÚhQÎ>i)ï!_a¯·Ò[@åúX¯r¶Ç×|‡$gؼw {†‘¦é£†©\oŒûº®dàÝf«N-Íd¿ô—”|&ǰAÞà÷êèå F–ûûN¶ ¾¹0oðHmÞÐ !o[‡ÙW)·"çæÎ?ü#b »ó¹ÚHØLüïÄþfUl,«·ùý®ôɇªÊ4äÕ53.²_3uN)jû©7JÍ®“UYówLÊHtÙ—†"äãÔr„…Iú<+û9BÞÎlç*G `?ÖòHXȰ°0IŸçìxdÕ¤Q0AáTVKÎæ¶^|û4кÿû?´nª6´^ËÍ—ÿæÞØüQoçL2!)ºiÝüù®à¦N+ eXHÕÖ+ĵXdzº›ô;€ûå÷n²ƒ1ïÃæ"#4#uPˆ‘©Ë½2¶Ú–u>·…\8BÞ]î1±2ÉÇfYôq¿àX„èô‘öðtþºd*´—§ÚË NGÕ“ÆÈÛ‰øsœüÊy÷`JÛbÎy'‹ ‡LaŸs“ã“ö3­f"F„ŒX¨º’O4š8¾äž".¹Þñ›½¬˜6ŽKÃÒ{œ¼¶šMÃ25™Z oÚ7FÈý´ÛA‘=CÈC§cŽSÉ÷e}®‹¸æó<BïÎý‰ã«ÂQj^…]„û1ÁM÷x§|UÿApS¤ºaä ! Ýýq9¿û¦È}pwMuDî“o~ÃÈä˜Z¨_§{KsC^åÕ!(œâ²pËá Î"“‘igå Ot‹rz­¢“Jäg§Š©‹^ʆS«·$ÿŸSßW(ËÌé¸&÷õUþéœUbâc¤” é_ùiÚíÜÒ/=ùdõˆ‘÷c Ù½é|òH~R_ð²±ÈÛ™ï ¯ä‘ž*–8ÕÑ?ð;ï'õ’IÆÞö›<¿UPž—Ê­ÝÉ—cù´<#Ô`×—g™Ùžv¼od‰KÊ !oÈNZ§’~¦Zë¯Ý¡·i¤u¶.uÙ"CŽQcü•%²”H>ák¢Dv³““K}Z.ð5(»Ý)-jµyþñBMx¹ßoÌ–³Ø:%‰È¾û+èÊXèŽu›­+tz/Ô„Ws²Y;TÓ®{‘Qüæ/g<ê<è’Çû·¯¶?¢Cúu<5l&õÖ=Òóò3õÖ¡%ÏË©AÎHu>®»ûóœOË…Re}E'õ6WÉ3ù™Œµø¦e 8ŽZ¦r-l?¼„"ì4Ìdïpÿ!=ᅳt žèŽ&;ˬ¢æÈ³eë Ì0ëë_] Øf üääïØ|+òù8uI79°?Ÿ?òØvâóí’çëg {Þæ€|GJΧ¼kûEŽúš<(më+}>;¾fâ](œK:oÛ­©ŠbÄH;Ñ[–®m¸H-U#BZa—”´®Þr ¯rgÎò¶Lg¡´Š•eÐ@Å¡Æëœ”¥ØË!oa¤¨#.P"ÖV¾.„ ¥á»'‚‹ô™¢Ôº;YŽú6r/lÍi•öyrÞ„DÇÒÙY~"/ñï|úsᲩí‘S_Uœ ž#ä+8A68YØ‘:›Vá’@,RN‹«"þtDšmj‡>—eF^/§F:~bŠu¹èœ Sî­€¼ QÔdç{ †VÛ;+#}{–£â¸÷ºµ2:°)«ÔQ¨ù!ƒI¹.ÝI¾ÍQ.!B&Q·”B·ôSbdÀÑóúŸ´ÖziEÞ>Ÿ£Å 5˜¦ ªï—W mz5¶%µÚŸuY'KuŒ|;Œi%¸{úã„F‹F6„ BX*K颴§M-V˜^M¬tœÏ}oöõ“q¨ì^÷øT‚»kÜ uåëŽ"ÞÂèìZGgoøî)²I±až„ 9å8mjòÂ}#ãÌOú¦ ÃÞÔÙ¤*DÓt.;ŒLbYµxY¨˜^H£XU¥¥WÈ»¯ó û‰vBÓwojw÷y*+Œ|!»¡XxõïëLÅ¿n£·ôŠnÁ8Üú¯ø `i®n™‡[÷æ/'f¸ljc(ô´3Ó4õâP³±ÚG ½}ç*Ÿ–Ð8×A“có•Ð9×AÓ#Rׄ¬sô|Oãe3aÄ^´§Ñ§ìlyÃý3“LƒûÎÒ"ì(¤áÓi¤è;àÏ¿^ßÝŽ4·b_ZŒôãY«Ç©;ßdÁŠ‘©§‘Ö.J@"ûr{ὂòkŒXk›|Z™¥¯¿j«O%ŸÏ>³B†\- ]ÊÉ©’«¾ûËX‡¹PbÛÇ8Q&N°x¿Ïo© i‚Â:ÔoǪlÕ¼Ú`Æ{_9dª0)7˜Þ·¿8dB×ð};í‹`‡Ìäq@Û¶I´Cu:nu(Ÿ !o‡îÊF‡‚‘É·…; ¾{ú­C†½ê|mð5ïßêæÔ% !ßêîÔ%ùQz¹œ®Èº5'éåܲ!§§ôGh£úgJ Üýöù©‰5Há¤r M\tK¿‹½CþÌGíïjû,þöUãœޝéÃOuÕJ]ÕÚ’fÅÈô8˜f ‡i°ø"œ1¶È*­o[9å­Üúbä#M¼#i+îã-ò¤w˜µ+wcÉ"ßAè-pZÆT^¾¦—Ѷû­`Êvß-ózÇ­Úwþ¿t?úÓ|¶îÿWo­ y»­k+/¼!¤•ˆéSa+|âÆLNîS/ß>bŽìh-2=m‹C/½<ÑÉhèZ­|ÀY0E±LjKev6£ÈÖ©·ÐøÓº¶SÉÄgôßñëÔµš©þ !B¦N¨£*k³ÔHä¸+‡kŒ¼Ÿnð–Þ‘¯ÝЪÑ4²–e†?¢ Ç !DŽ!¢ å FÑ…y?äêLr^†üŠ4Ð~ñj¶5'pâ˜úQýæ3CîWAÓý(WOhœ¦Øï¿@©"_fÕ e sM±ßÿ~ƒQÔ°v_ë½_¦ôzýbfº6ãPóu«›¿¯·¯àncïe‚»sáÜÀ,2ähÙJp”ÿª]ëvCÈ$Fª¶”AÖ!SŸ‰aôêî²l)+Âg„¼{$-͉Î8uã´Í%òð”h£Ë†1/?ŒMu‹ïþôÈFdÕˆ–—5ó#_'+üȨö•–Vä©f0#òÜ3!éo‘'4Ó ØSŸwº$-ª0ò£*Þ—HÕà%µ6Ô7¥ÿÁÚu$-¢»ßÏ„£K!ÇrPž­Ÿ?ûÓq&|`;Ÿ‹½îI>ãßù2, gÞ’¼f·fåÎò}¸—UG*æ¥ëï# ¼úôz?¯ƒP.DêÕƒÿüO2e¶•#d)f²Õôúü¨Î@Fz{– N{ OôBWÓlôŽ¿z>ìm·? M•M»`Œ%ÔYûžoªk š‚ŒO¢Á×¼ãmã(hB¶7Œ< +>ª¿û_¬µøÞ½&pýŸ*YäVR‡g7L–ôÕTs‘'áÀrÉöóüíú#&´TOo·¿dIArKГÀA‰Òß‹yæCÆÂf×WÄêBì`•*_%ªÜym%é'„Äã&!ªeYÆÍYV[d!õº)«›EÖL=Bý0î¢YJÃTÉ]'þØòfvÓ'7ˆ ɳv^:„¹²¶ô«-o`ã9ŸÖ!_ޱ‘cƒvÝBªù=ÌzÄ˱­—néñ³ÛÆw:¨ëßrܲagŽ¡¶þýW‘\­« ¶‘‘,øþ×CŠ˜.•wÿ¦û×p2ˇÊ[æmÑdéퟷ6Ô,tbϘØx†‘ÁäPA‹qùÔætBHD¿7Ç­rCC¸œžzx¤3ú&3N\¿æ367ÖOs¤³ Ÿ2ºfòMôäÚ³kÿ®dINž[¾’›‚–Þ_Gø{@Œ ÂOÿk–]Õ×+/2(„t¦Ì¤·2nÓ6òº#™+Èõ¼ÁB‡"Ëe–öQê‹|†À¥?RUÖvÃÌû–¨ykFyC™&¡ðÖ§†r±tËÂïœæv‘kî\s¸æíë»Ó…ÝÄ4òDj:Ô OB‚]O'Îmdðš·[}:ŽoÅ%9Å4¤3DÖ¤EaZ¦ÌinŽ[ÊÜXÏ"kÉ™b`y»]‚ê6Z*‘y®{D òö.Pg´>T,À—·Û7²•3‰bÑã˜>d•J2müÞ 5t]¯yOÏ3&h!o«¶ȼwOœ±ÞCš~ndM2ëÝ{KõÒ¯²ià}¾òyK3;m”R^3§”Ûf«Ýì‘Ì‹J¯ú•Aãï#ª3¿Ÿd“ Ôóz%ê¹ÞžšË ÜMÂ-|Î4Nòãreâ´3¿ v}zê4Î1huÑÑpóÓ€¶ùzuxf‡§M§Òݲ`¡pÜ9¤·»o+|«_ÏLÇ‘?ºaLÇ ¿>¬×ådtB;S¿­ ¾¬þ¨ùLÞí-ôõ§Òïú ® sR¹õ¼ZdPK¡ZŸ²®W½½±í\ûaÛ¦8æ]ÞÊÔf m9Ö»n™d¸2Á¸Õp'ó2®Û¾Æ]* ^š<È$ ö[5gξm¨qG¹¿#L[eÖ^GÎ:tUY¼EžˆÓHV/sƒÏ¿ÿy‘©pÚkœŒ'Ifðù×J£4þ>™LZG ‡3ƒÏ€¤$ Y^‘÷|‡sC‚õ>Ï }²èDÐÍóÔ‹dh;Åd#à5ŸÎçæ÷ótô4Œ îIJ×’Áçñ×Î7Ÿ´n„>Æ:øä½W•×A{ªäÜ–õ•cSjëê§Íüš¯‘Ö×=X'ж-Dͯ){)Dµ¸«HÈó”'@–Qè·Ôë¥éCÔh½ÄCÃ_dG“·ãdÒl÷rPðšö%©N^ÚQ»õSÒù*æÁûÌ#_©c (V4[_¸Sèf–å¯o„L7¼aÚ%œ¶Ýtdœ}´ÒAž²k v&:É èn¾Ô -mêiQõϹ׵:Úží‹ûeF'rDG›Y™wd,¼»q‚¿î¢á?¿³Ìj'c[+Nvˆ|€6º-òNñi[¢g“Gº#ù!ð×\ÎS?"2@¾’´–™™2G"ÙH&Zsøëßw»ÎuþXƒR™1q+zª žfpCŽÑH¯LLÜLÃÍÕ Åtb¹…*obâþ6™5½óLqÔéK°²+KÈì¸L^…†ø˜~TO1“— ‹Ü%Àݦ™›á½lbE¡ü¤1}ˆ)I,—åG}3¹²JÓ‹+´un¶nÝ꣋5ÑÜ{ªªŠ|sÿ>'zYÅÎ[îþkyd{[ÏU6Qž±ÌØ‹—á‰Æ’”ÖxÈ–¯ ÏÑ>%[»ÅÝÐ/(†"{ìT!%ù™Öß®mÛѼ¥Mo_´Fr‚¿^¾ Xð)›Ôu,Óøöûþdì¹^ܳqnÆAdª æî¿`Ä"Q)«,U#LYUóô6“ûoÔNu‹qÀÝ÷~M×,>h§21°ž{|GUqyòسA-ÏQq»©`WÇpQG0 ƒZLñÉçœD;ºæ}±W“!²øheÙ=òöÑÊne=@–¹? Vuê¯æy>ñ Õw';ƒl¦ƒï A1ÃËiEûº#O¬«Dƒ(s7e3×eV›”"Wßf¯í}ºüWÒjb’’‘¶ÒiwM3ƒ¥èõš·ïSæúS›už²Ä¥úÌùš,Q&ªÇ,6K”HPî¢æãíK}Õ7kŸø‹(©ÈQ€,Ò«Ñh$%’@ä-955½ym;;H<ª¬+îž< š{ú|=¦å\Òî!þÚÙqßçÇí6 såU=òªÁv·qÇŒ‘Bf¼ —û´%IFž´›Cϳz]WH|J%Ç*· ‹|rÝ úšgߨ)Èó—wH@É‹‚fr}I%ÞûE+Ù³•Í| kéÌÆ½ÈÛ»ò¡™q?1‚×,¯é¶ ¿™ý–Â_”[ãx::¤ÆtèúÊC_7sé§…Œ°/•Sð1+ï°×Üèû¡ãóIq ˜î×^7öR‹:P>æc¢1ü½g:ÿ _BÇÞò@±ûtÏzݾÚä™Úr =idP"õÈ{®´Ál¥c’:X3r¹ð/zdÌ÷ÉIÄñŽêãHV&, 6Dr&%@¾€¦KfL$`d9âÛ¼D]½Þ­ºåh$‰{ÈývUŸ²÷i¦!˜©"3¼æ 8LÚóÈÄ 'áh‚×,³UÇB@ot· ê@Vo†#i«·z‡#=òâ%{rÙºÕæäZÉå×—®¸g¿ˆIX:½_ ¢MX!;Y„>$û 𺵄!dGá¯û>U(Z=ÞLÖœ3# B¿´ñ3óNë¢åF× BãAã¬áì°j׳Ñýå.ºÛ–‹‹×þö%Öî·oºÛÞˆÓˆiS®T}¹j•î|¦°öËxNŠûÃûÂ]çýÄtrdñ!£é'°î%à m!œ1…„ŒÓR÷ örJ@˜2Ÿz‚–8r¯.;³­œ¹†jG{Åù·Ã•u+óÑ“Ö+埴„V– ­Ï4ÜørI×4èÔQt=Á/övwпö3t½iš·A’æ¸<Ç ÛŒaVÞf2ߘééxÖ™—ù¼N·ÚÁ›½ÝÖ…çùüõ1Ú6õæ,oþ8c™é•¹Ê‚`ÃABŸù4ÚK•Ïâ{µ(yhú¾áY¤n©ûŒì5wº6"~GÉ©<2 ™´©Ìõ–;d òö`g`$Á¢î¤GV¡uS»Ö=mö–)^¯ð×íÁøÏæ„ØŸ¡l³ÞèEò‘üK¯eé¸ÑgÚ—ž·ïÚLÌUaçìlc#.sTw,¯Ì¤Î5^âÛ,A禶T,?š¥s¼Äµô,ßÎTÛ¡t"ž:L™ÊÂÛSd—IeáM—EïÉQ3®|Þ?2ŒŒbö-/ËçÕ¢1¨sö¼'‚g¬ÜQÝëñb/ÔpÙ ‰Aäí»¯å"!”ýEOZåÂt­²žÄóñQelrªûñןíôY ír^8´3*é`Ð.ó ‡ƒvzÕÁA»äþnŽÂH3äw¯pÏ¢¶¦¨Æ†8üí9ר/lÔ©jâó|}][ôQotqz£Y|X z£=@BŸtדû¨_CAÞ’bß½ëBkžFm^E¦µj×¼ÿõsûqˆõ‚L¼ŒxŸ& Z›iŠÕŠWxÙ¸lÐE…×|¼ãaé57 yyJÏ ªTïðš¯Ï ªÞ'h>ƒ^¦VÃëöÖ ×lLbYÛ¾[BÑ÷U¾ ì:ï†Û§íæõsùgTéOJåõÇ‘C¸¦ÏâúŒªeÆÿ÷;¸Á¸:íêRCæ•·n|»Ò~¸#I(±Ìùã)Mk·’^×¢Ž×ÀÖH£>­±ÉóúD’ìýÆq¯$Éiuí {=´‡µÕW¬³ÏãM>"rÓÈaÒÈ 39êÅž7bžÎèäV¾nŠ?UÇJ#á5SýÁ–”¨kæë]ô=¼¦ ¡Ñ7O&>p½=L"ߘ»˜9is̤k>¯³.8Hj(mÛ8ôz~8fŒì»j à o‰¹Oýóìy]KÕ­±èøz7ñ‹@üЦÞg•V2&!¼@6C‹Õ„Wjpý¶ÅQâûk¸ÅˆÍ«Rðš8)ŠIë\¥z¶*!EÉdôÆ_üª³5"õës¡¿ _±±Ù¶Þ~ê”dedoQ¼Ï”Ï2„['#Oñã%–ý^¯ïä/MJ{´p)1/8ßšf¶ÜKûní‚—G–©–†=%¦#l›j¼Ïœ4å–’Þè÷áh„¢ Á”vH'ЩT­·G€Ì¨iL7ÜtÞáßþ¼V‘h¬"Ñ s3ÐÎ?&‚&É—>ù¼àå¯i ü8xÿ¤`üeK®Ö4UÿMÂJðvß!´È¡ÎÉmmÐJ‰ƒÐ[šo#^¶mÐ2‹­BËÐ…u7`3?¹0Ú·ý†!¹F“¹æ˜š´‹¾RyRý Þ)Ö“cf›@GT¦ ÐGöåùjKKuòÑnƒoàË3ÚSÙ Þ.í¼>H{¹WJÐ]¼î¾gÙŒ´põÿÊK~¾_n ÃÜï·ýº|û®ƒƒ 7~‚¯ ("”øt¥[¶e\äÆÇBoQr‡Ù½¯R"¸<X·º58 a›Ž£®á§ZTyÉÏ…ÃÚ4‡¼¬l_žtÐ.6¦:Rë ¾­âñ½:¨ÿ¬N ÅÄôÈI`üž÷¬Eãå^_!UG8B·µÖ»åŽà÷êË“¡:HýŸ…{b%u3õ&¹´×fi(áýå^]yÒr'±¥5Øñûºžw®c9½…½ÅkjŽr;ñy¹yºB¢ÎÚ[çØköÐ*Ôq¬çÏÓŒÑÔÔ.m_žtõæØ„ u3™.7ðˆPL<p4Ž QõåžúŽ«î3ñã8êe õPwýùgú|£FÐ+[Y(|W™$Ë{d;äe Ì¾ù²5BŒT}Z±ÖÕú©bŒ$K‘Eú°=ƒÓ @ém/Ç·êmHóª\¼åO’y±%­‘ôŒ m@–—È'ÌzêŸî}ª¯¼ê›,H˜[Ö1R/ëå ÂVYËSgÞè¥ÝOõ ‘¹Ü"fÜFcåð×Ë,î ,>>Ïͱ-î‘UwËÕµQXÎy»¯/Té–C/òñÞn‡»ˆ¼ÿdnÎYvÍ;|J5õùç-"_ÀT™øÐkN³7!ì È‚üqÍs/Ýix¦‡º }žõÇ–ÅIY‡˜i•ªr[ù«J²PBò)"¿.rø­·€0úÔ'Y–uÈ·*Ézk&œ†|°ná­±ñ¡-.06…·Êܽ<„g™‚…4 xŸ°`Á‚½ÖJë:DGÕnáÒÉu[®¾ŠD&{ž$QªL¾$´X¼ŒÎ×ÛœküÛoZ,Þú£å ßš™Ùr+Uî@îMB&®¸Þ;‘Å{Ó²êãóüIÆBŸµQR¸Ê½Ê»üÚŸ2®É±R}õuÓ8±›²mœô]FðÈOVm ]Õ ïW²`%߯ÌUëavÅÕG‘{¬Òš'-‹ì¸æÏ,­dûŠìJkZÉw ŠXã·˜±P)Å1Ãk>ß7ÌÖLœ­úzü$"· –Þæeе¶F\f¬Fçàú;ªI¼æÕN$ 0ÉM/*EÒ5_P8Æ™{Ù–U/ÑÖ¶ç·<õòíª†µ¡©^}ecõÊŽsùüzZÖ~ï[vÂ_¯ “¸12Jc»¸0€¼‡8™õa·ÅþœNÄ9Ÿ@>Þ›§2^hèVß ÀƒäµÎ[±Ž¯·ÝWÅ;K9Ϭ^§yŽ’(0ÿVˆ]Kk{òv SoU‘¶àôÎÅ Š{]. bÏ£¶õ-+6s6ò8f[oä¾]!ub@FrŒÕ÷·‰p«0”ŸÝÀ(Ã-¥IR¼Õ§Ž²¼pÚÃi+v*¸…&€dökïðÔq"õ+òLÕf®y4Ñþ¢Ê¤F2 K›„ï›~—c€¬Ri;eS}M¦¯)ih˜U™Ôˆ/„-ibE²vðo¤Ù â³õu\W½)© Þç3$_qÊ–mç‰DC9¿žs²¼ôîvý˜šÈ>¯r© ·nÓ‘¿â²VhdIÛΞ“’ΖšŽr ¡Eâz­D¡AoÊ”_ ·˜úÐ`g?Xg‰? ¹& ó´EIwRŸË¶ð¢ú¦<漸Ì˯õËï9@Ÿ^i_‹ oñÏÇ!GÛ–u“âjÈ2!©×YÔÈ•ëuRCd•iø‹¶¡[¤Ò'©È{È‘›˜ønÆR4QÜ#¯êDn¬.û6ŽŒª}ÙÒ.¨?Êóîí¯Ÿ-CŠrNá5í‚:þ3«ÄŽñ™öŸiC/OþW|õmXϽBýÒLdVúÓî&¬!ÑjVIZPUZPaíyÞÿB–Q9Ã[… Ê阛uêÀ)„–j·¢É"–ý¬gz¹·<.£/%¢­IUÜ?$”Ó5¡,ÿ_’*ò§Ô“ä©§€È7©çtM=‹Ç‡Ôó„]É’«:ü¥*&ÛË»ïÑïÄŒ1#ÅûúÖx¤ƒ»¢–2 gÌdW×3zü?ד!äã6cëMÑsWšš`íÖÈ'dÅ ªâi@tcôÇkÇߨÔGÖø0Ó€èÆ‘Ò»ªÌ•7§È]I`Ý@w–cº_vºàÒD7uå´NFê·4SixS4þAµƸ֎¯\tg;2p,â¬×!¯úÖ˜“¨…[Ù/ñ/îú7t+ ¢4U3À‰/½LŽCe.†¦ÈO4þ}K8¸Òl+éç#!—sÍ7XJOHÇYd ʘݱÔËœŸÍäš•-2óUή"¹=å16±Ê[ä8 GöBûœçu9»>.‹|zd ƨDBøÊ _éT8ä˜=•N@ŸÓÖCsCÌnœ™9æeKØBàªcô¨SAÊYà7jl›!É{Qò 0%´ÕÞíôÀ¨|_†&¨zس•o­Õ¥ƒš¤œ²»i. mfpj-4ó͸®ÌnXÒõżçÈV¶a¥%-üf޽OíH:ø±‘Rð¦a !cÏ·¡ý Ý„MÎáBš8ÒòI6H¤t0Næ.,2õ¥Q®±¤][ÆòóÌO„üOhC«4Ž‘5nb>úb‡AnÔÓ ²Æó²¨ºôÑÙ0n…H³ ²¨ÒLCkEQYý›™‹æ,;3N°Œa×ÒÂq|©Ú£kK„L=ÒÅ»*ª ½¢ø9³ à©3qsé-*¯¶Z12 žvâ%>±íòœOh±Í—ÂNÇaê'`°·È—‹Œ8å›ïy'-½¿ùŸ“.€€e—Þ«.)ݨ‰³È覊Ji5”¼íà‚ææ¶Q¼ÂôœåEâ/¿®`áÆÏ{¤ê˜Æ¯‹årQÞÙºô›ú:Y– ØCÓäçí¦5 TõASÆ–ÒmNÏù íV‰4ÚPò.Ç]¬ wµS}ŠË]¼H»éØF„ôzBjY &&¤S 5ÅirQÚ ˆwÂÇÍLɵb´q,Š!zl¦nGÈÑ•é%¢äË&騀«œ\+FëÖ…rTZ³ß\7n Úï&QU)—^‹|•IÏ©£@K“à°»ÔîQ±0_»—&1JV —=Èc~Z8„3’+M®¦n4"­ UXëÉի무 ôê¶³oš!£PÎ|÷y%ŠšµšZ„ŒC‘·Îä_WÒŠ¿AÈ hs}˜Ä¾öl<„LßóïƒÉ¿w.ÿn‘Ù{’tWIÒ¾g9EÈGw´é´žÏ• []cä3@v¦wµ?Õ#ô9¤j’dë´û£{írå)åÑ!Ñ$ ™>Ì5zJÔÛbHSw>ôeµ÷Ê&Ó$»ÐX¸KÁ«c9Y溞w·qg™¤ßµòuu¯i(<ÔÛ­:ä÷šýæôΗ´¬pœ¶¦q8Û!¾îéK<Å«±YH+‹ Sä¥ßá±Î‚|AÛ$º­CÈä 7Ìýù•Žùƒ>y~‹î ê³dÉëžX¸UâÖpu¥Êe͆Tš ÒCw_3$%1†}cØ Qsqn nzR’‹$°rý´$0üzt ¯\ ™|Ýì}_[a<ÑÖPšKƒ‘#$ª·2bt*ºßU7â1}±ªLUB;]¥\ #=Ç)Òchæ­)áÍ´ orÝ–ƒã1³rì,ZÒã=œ$—^KæšYذ¯¬+!MÞ¾f_³•Ǽÿu€ê*TÂÚœ›€lž_dgôu(×Yä“:7íjÄ]ÆåëQ”¼EHl4˜²¨B"”¬Ë‚ñÅÐ;n¬ä&Ùø‚7§ò:.tíx‡‘éçЄ–~w;.~7öoi)'J.­†ZìàÎô%†ƒ·´•˜ Y×{ aÖôÒ®\V¶m‡bÛÊ¢<„ ÄdJë¢J;½ÝúcŸð¯'¡ht§+ª•hô´Mò?é¥]T¡f¹øYs¿æ÷¼;·ÓIvðÏÒ ]ÙëGuú×Uä®­1òi#î-µV8 ÈÅu©oWVÈÂD14-È6ó2//¿î-ú7^%i ù`>ò*ÁÕðÁ|äUBç4}Þ¨Ù+Þš©?– >ÒëVÛnUÚv­óuב¢H/Ff‘ñ=ó¤†F–Ú |ø€å³¶Ä‚‘Q¨‚gzTAu_îþøÎ~¿hK,ÔkKXäm‰Ë¯§eƒ$€*?–ø‘`dv¯Bqóq¯BqA~Ñ–hñŒ^A”Õ¨_Ú¾œ'zB”-‹®Çwc kåå¾ägÁ0Ò'ÐKÍ ¯¦c.E»;ö©4dOùëxV¬ÞOÙ¯µ?èCö‹l’LëT‚ ²§òW¬Vsï阯+¤qöûœ—Ð.æe¼Œ™¾—ÁHdMf¯ÿ‘ì)sŒÞÅËJn<Ö J!…­©U,ÿE×Ñ_Æ|†¨Í’É´(Γ:¿'»¤2 Ç:¬üä¼Î2 ¹à%²ÏÏžC9»¦2K ”o¾èX7M!}[„~ÎZ+]Ãù ~d–| çV3’cžý4uÇ‚ ªçää×c‘€íÁy]ryp2 —ç|H±U—`OÇR ä+DÚ’W‰Üjrìø-9^ Ç ¡è)äø=z ÂŽ@BDzEÃ04ò¤€VFTMÏs2×ø•š8¬¾¾L´Áô¼¬{Çë fáÿÕqP»í†u<ä¯HdéµvÃtË›n9ûsÊ!¸Ò¬üûäœå“ò™ôýD íèiV\M„Õ¦¢YÛ)oĂƾRÖ²ô}:Syˆ‰3 ‚,¨Ñ3HGµÌ¬wR­™õJ­ ­7ãT‹ÊÏýñEB–,¾m?ÍBâH¤†0ªëk]k8ÆnÕ¨RCh‰?D1ó®¡,jMT»ë8n7²M¹_÷Ô7 "ðfŸ¿¦qË-¡ª)E“óžÀsF—zls0Z9ÉŠŽ #£w±r: Š•§ÏøÝü:ë{u%qHæ<¯±³ V Ê÷N@Ö3FqXßèΆ®§ÅÂâ™Ü‹Ó¡Sì£ê;“<7城Flø×³Ûøfð’/‚y*{ ké™bb ‹lm\¦sé\€gvu,M‰´ÙT³ŠºžY@ñ7¤ÀX˜üðÛfðóq±E„éóùU€p ‹ŒîÈw7 ðKŸ¯/~´?Ö#£ÏîùJWïž¿‚"˜w§»9¶ 2rÔº¿…~|–¯NY )Þ~+áÉ!£›_çGAÆ÷Zhà$¾¢/ZhµÒBÃÈ/ZhŽâ1 ÉtðªÁh!Ê‚P ðú@¼bû˜šž­Ý1¾vä­ºrc4h=œà ¿btq[)ãòS*§Dð¯'¨Áíâ^5™ÞÉuÑÿv8“ýú|…U&ÄgN†’W¥üîÔQÿ¦g MÅ++&ÿüŒ| úòÐ*9æüÏz„NÈ™`k’M¯äGÓl”ûÝ^—` ÇýV¯ì*SîÊŽYº²Ã±adôAV;o´¬6ô³¼² kAÐõª®™¼÷pÍLn©bš!ùÊ<Ù凋÷ìô=\¯, ¦ÆÆªêá¢×¹]i¦ÐØô³ô-®×;EÜ®ºÞɾoTxß#ävø£‰0m§=±˜{r&ü1¥lVhG]ë0C!ÝëùÀi2K/ï$nBÈ™ð×0 ´NN²ËéX·!BÑH¹ãØÔËÛq@HOWY:*.‰ÜxË6àx΄ÿpãš6{:æ²,žÑ#,¹3n_É—™…bÇ×{ŸˆëñMÍ8ug?ïz+¦ÖRåÛäG{@â^‰Ð âm“+2i„ m°Òí£†Qµ¸CFo¿kžòþ8\rö}15…?ò9¥!B{„ û›Ò­ù‚É5ïòÖù‘h‰È›xmýÜ£kÎ)ˆt(u­~=¾ÑæT7Òã%-Ì(¹)œm•E“‡2GÈ(ÓpUy‚ì=΋Œ=iÐÕ»¨+É£äJooWDýÁV·>-2½Ë…#ƒ÷™~Ï…C*'ûùBÚ¥d7ZÈK‚Q^Ô»xŸJN3z\éülé> BV |&ÙÏãf}*ÊáIRÁ˜Ï+yykʵÛv)yA7¿ž÷Iu0Å•EÆ7Žd…Çìç»]ç;-2º¥6ó3ú½Rû«KÛ*F­eÝÎö΂~ÕÏÔf F~¡6ø×“;AOmf‘wYÞ@L# z`Eí"†ªn“V^“5û½©K; îÎëž3ºöS7ë1ä´Øg6!d„­éÿ•HA•È"c¨–( XœKcI©ç‡Œ/ᵪvú©oÖõ !ËÊŽJÞÒì׬º‰KdFÿæCk-L$+=¦žÎfÈÉy­’V•¶»SÉt«“„3„LÂL|ÓºL<;$¼²ß÷šÕNóí½âkç“ÈÈÉù?ÿþ½æìÙ¢ Y 9ï³û­}KüTJÌù £Ï¦(OýzSòrÅïó4ð6A£~=Ÿ›qóåÍÿxh©øy.ë¹­ñäƒwÙ¸Êb9jq,—7ú¡˜¡É‘LëPÔéñ‹úQ#‹ï7:]7^FMp|ш;«øâR9é^MC?ºÕ}Ò¾Z'ÆèYchBM“§„ÓVÐúò²¡Õ¦3ÍjÔM…«ó˨Ï@/¤è”^xÓ¯5Ä«ô@m\`¤æPÑã0Œ7¦Ö³´ÎŠz¯ý±UÅe£ü†•†TUN[ÑÖøD¸j…SA—°L°âò!ßFX7²Ž#ÃË%‚ülarjzZÛÌ23¼°£RãÐ?°i¤~YüÕå=Çz Ó´pP%Àxó)l¾ÔPh‘ëŸÃæíŠ7„ž:.Ç2þˆTöÖßeA%R[5õ‘ú¬’×ã´N=¼¨Ç¥çZÃoÍ÷E^" œ=ì‹£ì§ëBÍc5´ÝØPq´™ø^Õßíµ?1o™BͼfíÓuHúÎe”åiìªå¬45Z“WHX»âç||@*ZC‰ûí÷áI\žéÖoù¶ÕçÉá~|Þ«×Á¶­é}ÀJTr¹DrVî¥ þÚ˜wTbEÈ‹×`ª/GŒŒ?Æx¥wÃ7ë½÷}‰ñîtðg‰ÏªÎeÛƒ¯5"³´Ük„̂ة‹²æÛ¦J7„|85ÉP¡RÔÃ@ê ÏèX;®~W´{{òÖgØ/ÿ×™1YMwvÀáýÜĦ´µSÞ~P‘‰8QqºŒ™`ñÃÆ-kåjC3ß­TÔ¦,AzaCU£ëÚ΢è–ùSšêkò¦*WÚ™Þ {ð?Ø™mëŸó6ñÇTa×*ü˜u2® m×}_W¨ Í¢ôÂi¾%iqo)ÅVnéèn+*ĸ6e‹‘.ª#œ=êu<›æpuYØ2ýª7mGhÛL«<áô޾Wg2ïEÙǯ©½Eù5{o‘F/dúòdò~¥oĽk-keÑó¦XK~wT¬e‘ÑûiCíi3ÂJ~Ýd¨=üs¾P[»ßïTí÷ž@Ùa4¸º¤¼‘^”÷¦tŠ ÆŒ¾DÛÖI!!±Nx:áÉrÿ’e ·Îâß›}¤¾û¢X˜ÜJŽ£Ï©H–›¸çp¿Çñ=”ÜÅ+÷¿ß™XÊBÀ z÷þcúßkG(/ÈΤÿMÒ‘JëŠXÚ9•#+»FQ™n;ƒIûA&3,‘¤ª¬ù w¦ G!çaÛ02 ¥³”ͬ¥谬˂‘!ƒJk$ãØÒœ¼/º¥CÈÇ»¬Ÿiò›ÂŒÒÛ|–Šwù®ÉÌ·Ä}h¼W‘¿>7l'*S#–zK³ %ÎYVFZ!'Í)s6XüúT bd{‰ Òº`…uð~L!/$ãÍ’·ž Kw¨æNè" Y ƒl:FÒ™t¢€(A‚;%äAf¹ðÏ##‡Ô¬€úFØ'2QQ‘#cÔ}ahD›ùhÄ4»²,h5sH½¤WÛ’båD„LqªÞG\¬EáYy3ßjöY ~-òáy¥*«j½[íïjCÈç­À×)ð˜¯K—ˆZ÷å6½£h[#íŽSŒê#Vi1ì¡ÖðÑulj{ÆÃ²7C:¿ÉçxÆìȼ{îªí1È QgÝÈq•NGU½§L–‡òñQÿqcíªŽÉãq>kE|uÉÉ.¦5_xW á›'‡îríÍ÷D–uy6ÃŽ8¯º à÷¦~fC;ñŽ „¼ÅÒYÎnˆ©¯Xë®bd`Ødža³ðe AÈóÙ‹pr?âÉcÌ\×[Îâ÷ˆÌùûç¯O7ënïÆ¹[‡72çç'S×Ir6IÃý$¿£ä‚æ³Må‹9ž7®R}¤šTtçlϪêÉõ´¦£"¡±y³$¦Úú ›ÂdcË !€Û”Ä”ÂÃTÁ؉Ž4MÓê줂IÓ}‹u2ôB"Zv2}‹}" ´ºwú„¦ÑîPU‰huV‹Ë[)J­Úäݯä$ÖMþÇŠÀ¹y£}×Ì`øŽ)¶å Õ ¬]W}?a$š`N|ÜšM¼:vÙtuÒŸ4³l•6­- l­£ãŽÚÁ˜ÜCU%‰&üŽ;êT¨Ôò2‰DlÀÊCE«ê„oK$ß$‰3ÊI’žHé‰I-Iþçó¼Nd‘$B~¦Í"¼wò…0h…e˜Î!|"˜ªŠ%sRÞíó)pDzSR]'(T©Vó[Z“7ÏÕiO./žžª~½ íÒ!ä=ƒ=§”Zh©ò¶C>Bµ×¨ø»¬»‰—™ø(Pw¶˜ë«mTHÑþgP(*P+ŠmÜZ˜ #¡R£•µ©QÑï]%©{Öñ !Ÿ¨šf–µâ.VØ?‘eî¯[uFQC—™V’AÈÏ=jjÍ€¼‘̪D3@H_$³˜úDª;íOëŠ'‹ºÎ$9‘ 0beCÅ R'䋱0eStG$ZuñÉ5«à»Sq”b#\ëTçªzë׊Bo‰¤ÈýŽæpj[iÌN’Fj"±¬z=È 6!Ï3Xcþ™Á&ä\.A;-DÏ3ý9}›f· ¹ñ)·G;Rh­ØÓË[‡¸r25¯ö2LʦǙ°Òkë·¹V|¥¥®MÒ·™°ØcB‡82˜uH±¬+^m‘wŽ- æº*®zÆpCÈÏ]çQ—: * fÁßËJkkÂg½Šz6‘Á,d)N`o:´ÿÏÔ?yÍ’s~-þ®+í%F>a¯s5Ü3Yß>  oïª÷æ͵öŽXWÈNctñÝôí^gSYtÌ€‚^³tyÙ÷ FÞCí;îKÕR.DUâÿùx÷5ïNá{ (—E;v¿ž– ›¦EȈ´oªŒl_«ÈÀ×Lc©4›w4y¦þŸOìëæh±µV4÷dWÿä­ÿ—£Â¸°R%gYMçãKº|¦K-«]à'z‰ /ÉD{j©§¤G½Å¦^/³DÚÐ)ÇjÃÐ{Tb,­èŒúæGκ½;üGë.~Ó¼ÖLÈìp[É ñQ |Á=61¥¯Ž)}IŠ›ù™óæ4l¯Ç!ÜÿÁ¾DIY7o[Œhò«¹Ø×¯t5N%Ý&„¼"ÖˆPèhÐ%Rä•Pè n›~ÈRK¾­œ§‘©‘C2«ÿѨsa\ׂ#dú‘¤XÇ$E‡|žë@RôOÔ€óÒO ›g>®ÛŠo>¨Û=O¯½¦)Ë:[³ ÿþå…»*£¨Šj¡}øžxASÝ614©v<9QÚVÉ=p÷m§º~3¥\…˜?þ Œ÷é2§¥‚ñÁ$Þ!íè­1leÛqR4k½GCåirbXÄ&i ‹ lœ†Äæƒ R¿náM‘s³F~’¦g{•©ØšAHô…þ¸©<µ ãçý1j®2ˆït`~ +¢?~¤q0ÄŸ‘ø'…!…çO”ü9¦*.aøš÷HË•·wùölyeù³Å•çüªdiÈô’FÈ!ÀšB6Z–!É)Ýü²Ò ‚ýþë4œL©‹Êþ¥Îz|Íç;Ý„McžµõØøÉÿÄ’î®a:iqÎ=Ì 8èiÁ‡Máî/_ >jM „DfQÞàyØ—e )XL(5ǽXÔ¦¼¼êA49Aná¿é”¶²‰sÙoy‹¸í µTrý>v ÿ ¤ û?W>´"·ð¿Îñ t$ú‹ï³Ã5Ú‡áBn† Y×á;"^Ü!»¦¥Ó„‘é™ìå"1Éóö©|g‹]àYpÍû{›ª²¤ßWÛV2ìaÏû—Ɔ.e@ˆû||% kxïÉw¢‘Ï39hpTÖ_Èš®ñQÀøé“ a8D5¯w¨æÉ3ý6šC·@õy¾)Ö×ɯ/Î Ðg›'¯û²Ë|<â×Ï”9•ˆ@ˆë·¸c¦ÈYÃ)ç]7y; ÒJÉë'¿l|ÛêŒ#dd/äu¾J1‹JLã*26s¢;s^f*eè׌¬Ê}ˆ»,š0îe`<–{në7ºˆW+›!A“Ë´¡ô¥=väÒ#$ 3–¡s[N[Æ× !Ó“4YåàŽ®Ÿ´‚iyŽ;¼£Û÷–'lµÇ¡Žv;[±¥Er„D¶R¦`­V_ä2 ^¡Æ!QbeeYgñÚ31f͈“†kµ%À!-wáý6s»)¾†E-»ZÞ,Ê!Éç֬ЭY|Í4 îÌ$ž¾#9Ïbé_øŽža¬Óõ¯Y)cKï™þÉÿøà6ƒÎ“I˜Øxôa³³·TU¶;:è¹øl„ÉJòs×eu‡¬Ü´öȰ d¬kK=S–ùº]‰ýWßYé]8FBÕÃꈚ)³n)k.÷bAÈ{Þ›Ž/{½4=lvù¯mRsÍYåT­·õ&±ÿê_$—ou+[áÅíHä¿ê³_fRÊ¥f<ŸÖ-,¦ªhIq3ƒiE —ºâb5‡LƒQ8s46©/¿[ex›!UÑ3;YðiWhµÉað“ÿ‰Ç{ìn×KÚËNÒfÆÐ Ê’Íf[îåÞ­BVø÷àÑòÌÝ·¤ÉÐuÃ0ÂW—O…—ÕÒ£Ç\v[X$äMTÜF-óÔÃ$ÀòŽüŠ’(§]=WÈhrP¨Ÿh­ÎÙèI߇,l&_ʼò€t»‹Ù‚l?Òe«V¶Mùx—8ÖbȱÄ1ù‰HâxàÆí$ŽI é$ŽupÇÇù‘"Ì5Ej$¦óšÜ§*@,„w"h£’ËÏwÒ3PoÉårJzfÅ–@z&—Ë7Ò3!¶#‘©¬¡ŸêUgjÖ½ǟײ'—£$€õÐ5*/¼h9B^=yÂI[ÛÖÂD÷zÈüæjÝÛtêmʱÍEAò &~EnˆV'ÍÕÊ˾¦“¶¶¢VxràÓBy‰÷°BÌè—‘ÇoËmî¸w»wÈÇIÎË6(p“Ëýü½ë·)|ÎK.÷£ŸT°`•ÚL8‡kÇÙ‚Ep¹×Õ"™Êþšm7©eŒW•O†÷þøh&Ì^ÎL˜s†'f›¾(þŸgfÂÕ4 B&Gäd ÁO­D-0wô¥U£×<Ȇ‘Ë;ÅÄ»qlL]päð?Ÿ'CUÒ Uí¥Ï£Éõç|¨Ê|qpx!ª–#u¹ƒ;Ëø6·¾~BbÔcÙZð!´¾Hl‚j‘.÷PÈ]¥! &¨ŸE8 ‹vÈIõž ŸqÈÇÉšÊ|`Õ]¯¸¾ê—ÒK™ØÊO ×Û—zTn€ü6¬3Iõ…J„¼ž¹@Š€ d©7‰D¾i‘/¯ÄLnïj£n {ßvÖ‰ ÎÍÛåM~yO:>Ȳ÷5pr»D8uX‹F4`üKn)²<¹9+ꎵ GÈÛY•C•Ün‡ó½¶^Û/=ŠŸe4ÚÉíÍÑǵÍè.Ïs?Cn÷êóãÀh—Z=¤_óvrʬ#hÞ“@–R{Hl3Œ*áU1õáš3x:H½—½J:=òq¬ÙUÎ}TÔ–_)B^#‡Á²òF$c5ÏókEÈ[äfT3U¶UÞµDÈ»×:Í+?¸´KK;µ£à_|Þm( càä–|§á-Ab!z·q=¡Âéiu|r¤ji_KÛŸÛöiÏ_ 5\™KøÍp‰ !o=Ñ4iZ¿Vh0òŽ|¹Œ¶ÔA(Ü!(ª´ÑšŽ*3:C•ç–¢;rª†€1ªH­c^´Ì!¯±L‹}ïÚˆ/_è^v‰]joÙ§ ÈeniDÀÒk>w^úns $‡´w¤‚›¬ôªû<­Zò9¾£Ä ¥çSªk.û«Ù{„D" •ï vyÇv±"d*›¦¾V? Ú¨`¢J‹|"éA·3¬Ý”wÕpxò?qf^¹¹³µ–»¬úC/~t!ȆŤmK ½¢¶yRlÒÉù8JüH/7¤]z“÷Irè¶ä°÷k‰¶ÛÊšW“ d}÷ŸwkK¨™æ-èZ“ûÏALÒ•éõj¦y7 ~dÆ!ÑâU'Fǵz•!Ñâ¯9Ó¬›æ¢AÈr&¶1¨¾¦èǹEÈ{²¹Z5åý4zå‡$1òU{d#¦±g$0GtUi$‡3éúC€´¡òD«ImdprߣþåR™ìTîm:Aùáºî¿æ¬)ý*UÙÔ(rÈ)ô Šê…ëg¼8䜱eÎ1Ôœ´Û¿ZjÖ…Œ/I'εó/~O—ûÙ6¾…Àé~ùžÐ¹ ¹_Ф¯á¼ê²åOw’¯ðO¯§óК?=ϛć¶ùá9]9”»kIr¿Û$~†µ+›È멇èð9äíLws¦0¹ã‹¼qžfÜû%Ñ#r¿¿ÍuÅÊ‚E³aäíóÜ6| ïèŽ}šôÂ7×,F¶å[Öe!‘‘1sÒ¢~­cþ:üO§þhZ¨5sHu€ô´•I¢” 4†luŽé‰®¡Šž&ü<ŸïÍN™éyh•¦ú ?âºý±Gmå[DRÝM3Ô!¯Q»Ñ[‰bëè z3y;÷"„ãæ?½Ç|æE¨žò"$ÿéEGØz_¼ÚÿæE¸mê´mòþQ§\Ï›‚‰Ø{˜÷£™'Ë0¯Þ܆Ä\·Oê¹ $ž‡Ìh¼™ Ñ†ÖÅ®}éùãrl‹º¡…¾ÙUX¸æ¾ÉM‚à_óžu$zÞ³2ãy‹‘Ì öô|n[ørÈûçRÏ@7`ÈØµðM›ëf³DÈë§gtŠ 8ˆ—†'Så¦%¡Ðô¸ŸÎZŸžBžÛˆ±ð?ï¨\Œ•˜ Ö¯Ï/<"¯†bË#9µ;³³Ëá×O b£]†õùÀ³Ë^Aç¥õ¥t¦¬V³G¦H}Ü>ÏÚ­m>H„¼žkAù;‰ Ü>+0£~ÿþÚB“ W™æ®i<FêÚ‡ÀlÌ6-Ëã‘ѹ©®éLÌtCšOÚ‹{ðþ›LáÜC2euÐ3÷ÉOÌM² ÑT×̇~ÛòI17éß¿0h«KåƒîS^!äíüÞ³Ú#ÉG¬—ÕÁÒŒ@øŸá+Ö]ÑÌäH•QgQ;Ø.By3‰’îͦç®)9rjÈðŽž‡Ò.ØEnÚrb#¯ïv‘%†¾˜6(„ÆþP¦ê‰/}=ªmž¿ ÐùCacÉFêÊÌoü¡üˆ³; ÊÊ}ÌÈäD™€mÀo$‘í’.wXE"£D¥qÍâù#ß )žæëÒ@:E¢q7§Hd †úšK;ä#¾æ )³šºŒÖFªvya䩨š8Ĩ¨VeÏñ¯? ž·æufP¦o^² Ðz 4¾hZ$•5¬×Q”tÅH8â±€çF§JÐä‚õfôPËË–›ñ~ÏèpÈg\`¬#Uõ…žüÏG­SÙMr¬ðÏ_.hÿ6•Øy¢S®ÃU£É'­uª_“ZöÓ¦çLа×ç^o¦‘RN³ÚôàÉ¢–æƒ×ª¤ÛTI¾®úø¨ ª¤8\5‰ /#¶©þÀKßÿÛm(yèNžíNÎ*p©ç½?@Ób«œ$ˆ­zèó£Øªú³»”ø¿Z½-ò¥ç…\}é.°qöÐK`€W®Û«8§*EõÐhÜ5‘™6‡ëvZ²Co¾4¨ ~vÌa7úóUˆJ"f¢žF1»©k­èÜbda]‡lÞ ®½½¡-µÚL«Q@<™™mfpÞˆZEƒ«CvèÈÌì¶ŒåG'8]TDŒiÌÌ"ÆßË軩èšWÛæË÷Á‰íxcƒ÷ÕÁ g—0ÆIHr: ® 0òzæBÜ !'\6uGT#ÛâÖbߵݫȾ SBÒ/‘Œ;Ô'ÈÑË¡tµ>=I¾Š*1?ÎŽ¢¸'϶vQiµ4ÙòU 0Nå˜ PwH[ìúÕÍ"VÙ4u/úv§©Ã¿~ÿXm¢»Æöo3ý:Œ-ðv rÞúcÊáv¢N}ͪ£vøŸW<%gôlD&ÕÕ‡FCÓhlÄ©ËY ½Iµ™W+”ØÓÛ¹«âA“ˆúã)íW\Ê¢«òy‚ïèHýÑgŽSw^úb–I d¬ºPÛêH?4m©²Oh/ÄÔŸƒý¸‰]´0ýS~«ýå9¡Ó,AýŸÄÔ‡d€ìg¹,ø×$˜mÛ Úx¸kŽ‘$()ß͹ #¾÷4Ö‘pûÒB÷µØëý[§q9Z]Tm'¼,!ŸŽ©?¼Ù)Rã'LCé2¢þ|ŒÉ¦]¤qcUÐ]ªr)9¡ HG¨1ò]@ºÀ«ìBžÒFÐêwÈû'ƒfCÑÉvüë0l –©ëûvДœÐ¤£ p|ÍtéèF¦¡SÕN©ÌL¨3÷Åõ{sÊ™U‹êçrkm× xc +æ<3È~ÓôÈ -ìë!¹q~íÐzLS¤Ôm_»iæƒÚrÚnÇÿóNcVZ›–UcS¤ihéáÌŒq.½ö‰Õ†‘$²Uuµ a×êxÏ »HCKÏöÉJkz¦kÁ"ßòIà§ôD3¬vònÚç:ï«ý…ŸüO,g‡m9ÝëEô*»ÂÐKsó*}r|ÉéôÂÿôé¾ÕÌ*ZÊ¡VÁ0ÍèáÕ߀gµÏu%ž©-7•\1ôԜ fž°\G–çŒþÀ»a¾¬o¦Š‡Ôg·õŒt›cº†AŽrî)B~Ž2í oêùóÅ=‡iådÿ-??Œ¤TNËT]2—Üw€ž×ïcma{Þ¾:-ò Åä›÷v*Ú©Róö”¸`ú)ùºÏ39Þ‘sËR÷¾«¥_m9B¢Š†g ¬ÙÌý·Œ(5±â«º÷zçYÙûfnD©Ñï=³“Ö¹—3DÏsOF¾3è‹$"ßxMßêù¸—0L™Fä³3‡³®_öªe ˆ“ò:ÀÌsT}Ðbå‡kÚº¹~Gz†×DX _úi *Üy÷=;FPûkz–!qEì%£43 X!™Ä”H7 ô®l‰Q\Yþ’ ؆Çy¿1çØe±*æë¯Ö’ #wGwÌ"f$¦æ%6x±3Õã€ÉEïd9³½_'†‘„TÕFé;¼Ö©jòyñ<ÅbS‰¿-ùršIJ¿WÖ’º¶Ü×4*Ò[rRW²ú’œÚ ò¹yŸý«O|õ©Ò:ó©\ó_ª¯K9œÞÍù¹a*ФõÍÅßrÅ¿~­=–³|ºôöøá0¾9TñR¯O·eF­éíh-J]~kA^´ÈÓD¿µÀ ãþžpﯟþžøj¥_~jçÓ/÷¥ÁS%}úÕ-ùãôë4浟Q‚bðä³ï]¦1• ±Ñ »­L¤^[¨ýé=F¬K3_?6fK½¶Šÿ4ñ±5µã†­K»Œ6®NKÚ•š}>-8½cÕ}MØj¬WìXÂiwz÷U÷±f’ä—ùdô‹D+ï(BFA,h¼Iï1Ê}¾°¬6wìi‹4¨ˆÔ :!ãà %œ¥^ ìæQ&=âÜótߦ­‡‰•¡•úÓ¹Ô; Fz¾ :må 6ælâô@È•Ë Nª¸úÓ h:êÆª©kl0{œÌ÷Sc÷Z Ò»—sŸ¾¸ey?àŽž¿”XÇNÈèZõÍTSÏ#ÉCí¦ÄdŸ!më±H‘ VÚÒð`$²éö¶:2ò÷#½€IçJƒÕ!µ•ôrRѯ~óÇZI\gØ` U;,!£K¤XBZÝN=Ÿ ©á§Î`´CÓ*Ë02 G€ðG‹!ºˆB Ø;pý%t«bŠÕ˜~ý%t{\t ¸ ëÊîáýú=ìÔ“ó¼§žÔk긪­~@Í8õ<}N3„U?å;D~ûzïjM>Ä{?2ºDŠËôæR#ç#åÉfå3˜Ä1ŒL¾çU#KikW©£µÿ†è¬¿8JÆå8J<¦®ÉüϪC[¤À‘/ÿ‹Óô‰¬é4Õø)¥ÚýG;8h¢3Ñ_M]ƒAj=aÕøÞXõz‡tZ² ?ù[`¹aþMÂ=:xKð:oν­3G±Á…þ°-‘Öq.^˜ ”„u٤φ7éS„tFý$þSŠÈa@H(íæJÅZ«õð¢dÍVb$"'Ö†ÒÕÒ¹­*Øà£éÈ1MÙ®EÞ|<æ Ùk®îõ§Åwô 5³žb$XSç–ë)½+þ)[„L!¸©¥KªO}HÁм-f„Ì|·ªV˾Þ~è;ë¯`ŸüíB/µÌ•Ø åXèÝ“²3ÂàZvuÛq”ú2eX[õ#‹ÀôüêcgÕê¸Ø6‡²Hy£s‚Ozƹ«-§~ã“:U°N¬œÎS75Db~;ÓÙG¬_ç|ÄÒ«v&‹‰Ð¶…xÀkg:þ¨¼!Ði›Û}þ®AÆ—â%"9ï6ÛÏŸÆQ¸Æ•“|q?þå¶6Ö´‡Óø‡ÛZÎÄ:>2 +ŒJ.ÎlÛ¿S¯MèªåŒCûMê· ýÑÚõ h×·Ôµ”§ñóÄ?kÍÉ!=éÛ½­„Œ,×VWËutWµ=«{ÖjWM5 aûÞí°w{-=×]Þ{ær±0C]g?k†î5M~Ô6‰\6ü,-ëCE*µ·]a‘§•ª6ÝüÃ$‚¿¥ßxòØÕ½„ÎÞ•Ê–Uñš„Œ.: åyÓZæn†¼p÷ZeD¤e§Ä[|rï™: ú}óù:  ™‚n¾£'îEÔ¿^Ï¥¸û#_ß]‹õw u]‹™zÄ]C釪-º}˜12ó, „ÐQJ™‹.Ì“¿y-2 ’ºˆt3Ÿ(~ ÷kï;µ6¸{J'9’·.öMw’ã÷ ü«ÇŒ·Aÿ¦å(’2ú–&£)¥É ÛöxøXšlXòNJ“Áªüºy¬Ù¯Ú³sX•_· |‡ø:™ëRI_÷qºØæ€'’¾¢Ÿqz?Ãæ1†Mvh+ÐÝD)©;wG1ö¼u"‹‘€_OB";?ø(þ#£ sø%d|%71h¹‰!“ËÂ"f•‰EȈÙܹʢãUÛŽ{}È+3¹£ Ãc&×݈Dr%ðu^ ûÈÈÖ}Gé±ùÕ ÑÌ{Î>„¿K¿î÷§ÿñ¼C·n«§¡œNÈÈòpÝy¬TˆmE •0Y 籦ë``+Y _2 ñ/¼ SúßOÑR¨x’þZا6ëçÖ±oŠ„Êh|¤¾PÿÿùŽ d™¶‚Òxa¾P?¸ «Q1æX–.ABýÿØ1ßzL>÷}‡Ç4n<¤“4Ÿ "&O¨_YP+ J-p2ç=!à­•zBý Vi~}Ÿ%놯ïÓuÉ$’§ëV@9uBýß<ií{À—…Îc• óÎc}ù{Å̲¼0qç¤/·½²g}Yü%/n02ȼÎ*–¤'˜^«H@q¥?û±|H^å[Öm4r}—ûñ©V„L\gˆÍQÖcšÊ®ã|¯ÃJ. º–õMÓCí$‹ƒ=›Š-ëb†, ÌyåUæY¤Ùã·E7æãì×ÕØŠˆ¬åoà ”zRõvÖYñÏAÄ+yõWÇ«Uõ-Íc’×)FÌIÁ+X?³ç™¡ƒÎ¯<Öä7×ø\Š{G>—i–|.åŠèû\¦™×)üç§\!¾ö©.æ vm_þ^GkfUÑZß÷ Xždäö÷Ær¸ÆuÛ göañU\GYÓ0f½] 2¹ê Á•ïìvû[å›"䥲 ®|gÿ7Pùžò¢ò=œ*ßâÿ^U¾mt‘Ýn¨ò­ž§îɯK<ö÷¿î|Ú9_uŠ*6šÙ±*2ÇÿUUÓjf+ï|g סšY¡èkÊŒ»é ´çy’³¦ú».YŽOwBÆÎ}­6d]ºrZyNámÆ8ä`FFV!‡M†¾yQä¬b!c÷ëLÇ`Ý^¬F&aäŒý’ì.˜{ïIH²{åmw´ïòJ²»“’ÝœsŠAÉî¡=!“ï¾S9ëÚwGW×Ö_õ.#×%*µ¤,òdõQÛº‘ÔÞÅîžüó$•iû–D ÆÛb€ŠHv{¢ÜðKÏ?çŸôüU•Zéùä@È™æØÕ¦,öò !ƒ<僻ùù œ«SÍS&nexýä–òù€;JrK Hfž¨»ìšÊ•/‡fˆÏÇÖ8Îf渺'v§¤òøìÎÌɪ_±;EÙÍäl2îÖì7gj,ælB6aÏ`äJvÿ™ç¸¥™Çþ~›bñƼ‡ówÙí ÑEvs4Œ’ ãßsÉ3þ:7–9‹kY€c˜ùÂæÿþ±ÂŠDi2ô”Zb¤Þ µT{>QC·×Ó¾"d|}.>Lï:?£5ç ž9^íµƒ8;!Þ²¾3äþB÷^ÔÊ^‰¥SrŒŒB$pO¿4‚tÈ 5‚Šqi˜!_g8ÚoN© •CÂÙ=ûöïÐ5òåónêVEÇuz£*3 G7·¶¢œE·ºXM×C¶›E÷K "UÝ:æy,l-(‹~˜Hn)„¼Ð—[ ¬/—ù‚áòd¦Ty‡TÛ·ü—ö„DúrzGSIdÐm»{6j&ìçuëG 6j™c¡ú+˜ìflóI {´3B¢Þ+¨9m·¬Ï`Å—QºÞ I¾€ÿnöM¯Ä=.nïˆþÒãâöŽèñSˆ{Q=ƒŠO‡dI@ŸGv"bbNÁÒÕÀ÷1ÈèL𔕍Žvmå¢ßè…¸º²ÓZëðI 7éqHäõO`·f™LŠu ä#À>è?ð˜!NÁ /Á Ïœq¡²%¢ró’S@”}ú¯3 gRð½ûÄÖËLÊ}é_2)Xç=b+ΤäþîgR™OlÕÝðšâ&×ÞÍqgQ†OË寫þ7™wˆ‰TC¤ê„â¯<•Æ…,û:¶#\,K²#ÜÞQì­u*ÐÚ ’®J×¶o7Ë4È«Èÿ#"."ÿ!‘ÿ°k‡‘‘ÿª#ÿb†Ø¯D©½¸Ñ3¹ɧ)…9»“¤“¤EÈW`’¬b’Œ~õk…ÇÌœ¿Œ-WV]ép¼ ¾wýêÿùï<óD´JN7Òy EPqOÓ¼¸bmæéù¯ÌL±øa–d!öœ6Íá°/$·ß¦9Û”‘!‘þ ÓÐAË|‘þ+ÓœÃÈ ÖÏ`Y pwtÊé³&\$S`¢‘%w¤“i¬=å®ôVÖž¼d°ö\geí Š™ÏŽÿª—¶t¨NÈ8P/-ïÛ “ksÍ¡ØGޝSG#ÿýÏ;»”È~kXH’èd`]µZǧ>f¾·d‚œÂgñŸN·¥ÖD>Bú 5±Æ[ãZ’:ÇÈ8ȸwó3Iþræë§©®9›6SØÚ-'Ë̼2§©~}:ó9ð˜q(Â\í(yþÈæPí(ñ9*Êt°9áíg´fIYòBgÖªsýmŒÆoïÏŽ—ßû!­Ù@¯;KÒ/Eƈ)¶´Ù&0Ì|λùu­%9?”{QhââÿëFAÈy·@„£™f^„ó¸ÿèq‘lˆBÑÙ`QÊnª:OýY†v\œœ¶¦*2³XB„„œBÇÕº¦ÍØ1ï;Äl8p~gØn&µÊß_j•Ã=~u0H pŠQHsÅu¿ež¹ê?“ÕZ8Aã#³ÌãS댻4†Ç"hØöüíª‹_Ÿw0rÒˆ”{@È8 Ûäµ§f>Gûê$…C=ÿħ. #µKz*µe©BºZ\%ynòÞåZ7í_ñç§jU$­Y½›¼…–×ÌW ¿:Ç©Oשφä×Q[u–~ªs.þ¹¯jÚÆ˜ÙÆÕrG õÈ:Œ|…Ά'ø:ÓÐÙXé12sYg­}¢díH<2YÛ/ûäoùÒÆÉ X(œà)–¶"6ô¬k³°Ë~pÙ‰ìÛ.Áì¤Ô^oõÓ¥+g«o•ù\vÍúiµB#çïê#Vo«•ž9.ûIY¼ÊiâÒ !cÿ×ßZ}^\âpH·"‹Œ~´Z‹(Ì»÷ËÎye‹GYN]¯EöL~ôZˆeÉÕ¿ŸIX]KdÒŽ•=ÃL©rŒ¼†•éù£Ñ[j̺“§•~>aft«‹Á0?_ý5©@¨ëÂÊ|6ùUÖÛÃ7÷|á¬W+ˆ¾u¬Z|…=á™bpPjWñï°¯CÈ#߯ðÑi&BÆ>’¶lÎȾäû€.ëÕ¬^µÞð…7}½-ù°ÉGn¥ÌulŸ8B>OHýëâ:ß|~#äËGS-ÎsÞ¶nïzâÔG=O5¦zž¼Þ¦!3„|Û;š·žÔ%~ò7J ¹”-Œ—ý?¦;0VÍ[²f{Å\0üœLÖûßCÛ|Û4¥`Uy‚ÆjÜø2¬ù ‘íÓµ™;2(<Úo /f¡O1]Õ8•‚«È,*ÇD0ЧÕ¡µJ”ˆØìOÐ×ÉÆO}÷“´ñ›ÊÓ¤¾K™ó\º°4ó«¬JNR]€ø¨×Cµ¶·2T(Õ:.½3K¾­œ1Í•ÍÛDÅg*V–z>2B÷¯‚Á©é>mÎÀé<{frdF m¦õ4m!äѦä{IIò–Š€‘o’ë %Îò…@ äLlÑ\{s‘Ø [ž÷pPôÌžSSX¡›Â–!“+-'*ÖuiaÌGPˉ"µ¯ìõj9Q¤öe!µ/VPˆð_ž²:ΈÈĬ›ÿŸ°+Y’U–¿T©œ¤åÛŸ6ëó hDhFv¿þ3A¥²kíEj"‚pwwG¯/ÎERzÈ¿£×u<,™^¾–rƒ>¸GîŽÇž½ßXUÞÕÛzY¿ìŠÝ##î±CJëЖÔUæ<7(ð›PqÙJJz6J©g¹)EËÚÚ¦rHÃä!ØŽPIJ—® ñø1ö B>ƒŽ :HÖà8æÇ‘éuiåÙŽ)G‹®(:áï=Ãʆ¿‘+B&¿‘3$K¡ ­‡8,÷®kæ!}R³Íë“Ïœ-¹ãíäó£‰:êëÏR¼w˜Ê±œqºrÌÝr­>UŽý{Ý>UŽûyY9x„ôÝú•c?켄ILª !ŸŸkÌ]îÙÔù Ô‘¬4í:1NŸ(Këü½Bº²±8‚{¿ãžy`P•72ð ê“~êÙ1]œgsˆÜeô×Êqn¬ÖÀ²±mØB>\íÖtŸÙîrï ‘¥XiW-óµ>snça„ v@Èñ MxEÛ>:·*¦ SUO’ Ûcð;BúˆTòSÇ’HH©×vDÈ'®_êþnY¿dŒá1_C%‹8aÚ'­Ö†Ê H‡Þ"_ÿ,íº”~QÅ]gÑ=%ÌiPj*SY–Q@8®6£O³ï•cŸÕFñ÷W0_ÍÈn—Ü_I#òÜ_ƒL.üE%óØ~KYW£k×£Ç8¤ªîe÷_lËèÅ•e²_ú½Nâ •½o??WÊÞt塲·E~Qö6‘Eê•I©òÚèÆ¸WZ÷'@^å寓’šŠE~ÈËÏåjV;‹ ˜¥ázÉš/¬ñ¯`§Ï'Wî• ùü}Þ,ùT. !_X¿KÏ$~²šÌ¹3 ´ ÷بFOS.öÍ"ïò_Ç{¡ ɧjn‘‘j´Yé—vÞÛ½EÈ«SO¯º ÈÐËË*)©ÞÐ3oë½¥»#_È#'Ýs qwÉñ2žy)Ãvl+¬€|aÍO)7û!“ËJêßæ;Š+Ëj¥‚îû²OnÌ4b_ÀEVf‡—G_ËØ#dâˆM¥éé°k.ëÓQ ä=Œ[%þ.c+1ñiÅ¿~‘C÷\:Yd¤êâú¶GÕ·MFÊ2ùÝ·=ʾm"¸ŸÅÙ•‹rv~‹|¸c€Ê˜*Á­÷fû°äí'î]¨tuUî±uS¶ã‰]¿‰²ÂlÕu¶ÍTŽüèòþñŒ.TÍä »¼—V•w㩤¨CFyCö¼…]Ž•#?tNÈ7MB¸¹yK¤Qc“•]Ùàë1€¼ÿŽ”=òtõ‹L¬[¦âÛSy´¤®Fà1ïöøCíºDîR[{DÈÇo专YúzŽùt™±ê Uçâ™Öª_(¾ÎÀ¯1N½ðÍoy>´GHJ¢]ÌäšL‡y¦é6„ônµÎzƒì¤¤K‹ü¤Â§ã5étÎjÿ”ßÞz¥Ÿç²7ŒwC‡÷ЗM³•|Cwž»G·'оeA]™ÚÊïEúq¬!ÃSñVOxJÌäÕɯ_Ú7uÚ7lYWŒLì; zAôêmk€ŒØV¥c[©ÕÛ©/ZdÈ'iõ¡<ë`[ÌÅè¿ùPá"ôøPè„[%:@f¿<>t*ëĬ[·Î‡¼,5f£y"°#ÌWJ5 ƒL¢Õ¦2¾l­ÔË«¢w»vȶÒÇC•>Å•ê‹DròV„ BM‡]ávdiïDÈ»å‡u•jL±ðz ƒ‹X’âô’Úv°¥<,ÑSÇ!2”,ºN,W¥“ôn'· ÇŲƒ,vu¿ž ÝËÀåòÐå ÷+ÿ2‰ô.o™Xl¥t`LZϾªŽÁä=€||Ñ×X–ÓV/,2ù܇ҳ`7Lžÿ±.ùe7tßgò¼Ø ¥*Ú “g¬´UZŽìq]o\€|EŽ0ßU˜ o¨çÇÚ¹8$¹æLB@-ºxÌûçþ|§u[¢9—r·ú <œí1÷ÚOÓ:­ÑóÜÓKÌ5r«kÖš×u4ªsO'N€m¢)¶zo¢QSßPh„‚d79Ï¡g;†fnÝQ\XÝW©Ï·ªÅ_ÿ‡ÖæìGÒòæ°ÆØTX«ÊêõÌí*eN¢Q]+«¦vHèÜó²àð]÷êu$Tû€òH>«.ó+ІêäW~Øê8K]«l4ïÄ0âÏ%yzh]:ÛÚÂÅŠ6z[‰§ÈÁ°­9–ž†¡ËYÉû³va ¯Õïãal ”•*ãótYùJN„L®r§Õû¹ÿ|б©Ò…–þ5¶_·ïÚÈÔ}Ö÷k5]éhæ”™\TrFˆÆÙâü9,2¹Ò«çÁ˜w¬éê•Z{.fQXg@@>"c»öJ¤T¹q‘Þý·¥N•YÞ°Fš½t‰ŒYô„RÈAÌGÈ õW²²ýÄ×ùô\ýZRùàÅoùÐLç5Ó/®óµÏ÷&ŸFÝÑÛ/'ª|)×^ØLX×MÑSJ—dýÚÛ~[ÃL}„t꯸w éÆzÿnÖs­MÃÞÆäáÛHŽzsaUÆRƒì3hNïþæeìr»ðmlè»®Ë÷hTÜÞ£Ý*Q‰iìV†ß¨iïÑÐZÅé__¨0P—*?;ÕÞ#»fÊj[à #†¾®Zj™¤îOÔú[”6˜Ø¤»%Ë`7ÔÐJÄ´âh½¬‚ݳ†(rGÈÄölÉ1-‘4/I3,ýŠw,Dª¥œá•Òf)Ü-ÅD|£{¬íér ¤#ŽÈr’ ød‘HR æzBÈ ˆYËsºn{3‰Õ/:ÁƒN+-cV:Íe…OdŽ¢6²¥Yȸv5#ä+<þÓ4 K~k{"¤ë–“V†j…=·„À!St@¬>羫æ¾éö™ùÂheèJ´&ëzDOþçÂ#šr«`ПhÆ]ì‹ÛÃ<Ÿî³þ­ðk^y5…#©úE"äÃö£ÈìVO$ÖG·í{•#ä3àDëuDž…°æ€·¿#äËy ©æ7Y˜Ë¢­å\W„|ë­À`ØÓŒP¶®û 2õÝ0ªö¢Î Hudl„Ô¾j§Zïk«ò¾Ói†ëÆ×©?+΢¨?^Çé^Òíªì¦äªšÑ¥Ì!íÐö=ëvÊS¢ÞWh‡*v++ËÖZËvN+„L>Iþ1ºHÉ?÷:ï_Zø—e¥n}qHIÔñÖ$×EIGÙà’“»ä:$¿}*éX‚E&—TÆÊ•CòÛ'*£0ò’Ê(*‚‘÷ÏÔ»…0á¶ÄÇ·8ØÀƒ'Ÿ}‘‡–¡›K›ž‘$ë"[Ñäù²äö:Ÿ·ßÄ?Û[×¢²ò‰äŒ©ÿ‹e8É€‘wÿ”L-M¶Eäìì÷"GÈGø<­n=;ή_\r˜Èxû eQ=‹rnŠ£Zòe÷„@b–©è¾o"£[êd²¤_¶ r¼ËkŒLéVïœðÕõ'LwæMdLOrešq¶Æ„«ÀOIÓ¥þ•7¯;T-O°uiaþaèÍ.M¤vv"05ÙWr`hrå0å»z­\ϥÔ?ßy&×§`¡) ïHŸkÏÍõ¾»‰ü|ü—ö\‡_´çüGò¸ÒžË‘öœE~Ñžs;÷óq¥=Ç‘öœE¾×'µç¤ó,OJ-òOºV·S¤##ì îDàùúÐãct´»}ž¶$ô5Õ‹íFK¯xá*oO„žÿÕOº'%—Žã‚øwôºÒ…ä;i¦fé0òùYF1»„ä…Õ…%CÉ•{Gi„”5y…œ`{ŸvÑ0„L°)hëLAé8—é3ÊÊj¶ÂâФ©ü·„­>óÂ&UôPI•Ÿ¡Õç¿ú:u[JbÓ¾UùrÝ®#[ÀÔ̆SüëoÛ¡©Jt*¨|–F¸¢l2 ‘ú:Yå9o<¦ O­wÓªÕf\ׄ7~Æ…VŸ&´¤f‡yDD5âA‘Õ§jBkZùÃ,î|þZ}Ú©T[~h½vb.ÀTÆÿUkc¥£àâ )`tKBcðée×m…’Øá÷ÏW,©–Û¥Õ’Ë'_·˜fN5[¦}%õë;ŽåveÊ„‘÷OÇ¿,tØdriäxj#G{ï‘’|£6n’ç0I12¹°k#RQ!?Û©è­¦CHWn×­´:nZľÃÖd'S@dý?ÕãTšf‰<ÆÆ!–Xel ¾Ó–ƒ›,XÕ&©‘–Pe>æ}‡ßša«!KIÕG^$5Oì+R‰vÇ/+Í£R*3¦€AÅì"‚—/#ýï3¦©  yÀ–xÌ 9¶µ!Ƙ»ƒŽKïhH¼®êuÙ(É5‰×•»^Ïë&I€ñi¯'{K#NÎÆ1Gÿ6ãmAëj‹×­%Âû¿p¢7#èk˜O1»ƒÍn@Ì qÏJ–7+ó_]Ñ*«JcNc^Ï !á{7=xÃï°0BšæKŸxÂ÷y¥8h3âë|!ó½ÖØv‘½]† ÿú;Dj¾†DÒj^VÙPê,Þ÷ï ¥> Éy¼Üù8;äãW–ª›âí‘ûîßQ³Í¯²y4æý²jî¼ÐæêƒC;é]üÆ i–§×»q+!ðz„|]â ÓÍy«,¯s8›s¬]éíwYã$Ša­jÆCÏNBȆ‘ÙumˆžüOTÛ‡¹ljû£;§ûÃ…Ø }aÛÆ¹5Hè+¡Ê$ºµ1´S-ºVø¥bB ¼)óþ[^l¯ùp4Íîæ±§ùÆF8´™8ÄCnv¾Ÿ¾‰\ g º¾£#ü×ìª#ï×½D5ŠÒpv¾™^"™nßôN¿Ét¯[0„ éO–ž·²SªÎä!ï¿#1mM…;¡}c¾¾5 ÖU±¦žç#“`~ØoýÉÛ©CHGõ,r»Ïnã°TóêSº€ž üÂÊ$u/]t÷ÎPu(ð {b-|yà¡=džÅŽ‚E¦qüoc¶±ëØšÏÂú§?±Ñ•·ÄZ]ýafúË [‹±nšV2ÑP»ãJ5Jcg¶—ʧAi=bë—´éŽÞÕ8ÓOèŠÂVvØÃ‚ôvm8Oä Œ+¢¤ÉWúÓîw9d‡%ÊåŽÔûRz]‡–ÚðASRzÿPÛ– “¬C‹ü(ü½ÿ—ÄVç_l µÄÖ‰Ée.<¥/â8ÚpÓù¾j ](÷Èô«Ü[ü¥×¥»PxÙwJ•ÏOÓ/ ¡Æí'4ûÝ’@…¿÷ Ï#ÃÁÑgCÇ^º1oѹlEkÓ 2À½ÔÍŽìö…ÚMÄèc«ìúK>å÷ÉÜšœ%¸ÌVX¹æ^ò Ç‘¸è&¤çá‚ÜR–,,Èôà›·‹ NR"sªnÄÐÄY@ÖÎîvÙ’ŸÕ0cè5S¶¦C²‡­q¬£kõt Ò5Ý)+G¬õ¨ƒ>ñº£¶Ñ^” ¯Ï5ºÖW(e¢qîÛF î^jzÙÅ—å ÷Ñô÷´¯Ý´ï<¥ñ’^•5om4Ðà.€[üë¦/ý†Ž¯iÑ 2Êà 6Xä3Dj),‰<¦5F¾B’»&îK$k+aõ òý[àŠõe+•29¾£Ô¯ãú܈~˜+V»ª‡Af¾­ÍVíe’^ðŠð?ùŸKµrbß~²ïjåÔß|öIÝK»ÎÂ>U½…ìÜ_©jq¬îð°s?(ïÁŸûõÛWå=²ÆÈ+å½r]m3A^ûÏ·îcºÝ¾úÏ ¿Šßn_üç/bäëB>üÎÝQ‚6J“jîe1õn¯ œ•1„RŠSÈùäkñÿ„]I’„¸²¼R!r¨\öþ—Ù»³‰‰Éúô_cHABvY-ݘ¤<Üe@¬µëu†µ¶ØÈÛµ xÙÑq™0òZÙÁ; ydúů~£ûÎ ªÿyÂZµÜÒº oÈý‚3ı_¥Gžq†ò«ôÈ/~•äѧ'KJו¯¼! Jó€pÏ/M=×î;öè{{ï»Q1¬+Ï3$ Îµ[eé¶Œ”QõyP&’œ_g\êK’×÷æ= /}K´©’ƒ"Š›27ùc’ä€lÞ¾©ÊÙe^1„$Ÿw–/ä$/Äaqam‰â&»y¨¸©ã]7 yÿŒ°J±ÈbåbÀwt7q7ác>cšƒW V§ú4a‡'IÄ.rmdÓqæroúj<ÍÁ!_¨ˆåüç³Y”µðsÿä>ƒ±YcEŒ‘$žWùÇMFÛ)1J›¼^ü̯‡’‹ÀM9M}Äî*IVá€rÛ ºvÐÛgŒ§^§i/šœŽz¿Œñ¶îðî=>c¼qʦeÝÞÓá¶žqŒ×‚®º€}è6Q.à×C ;|§çVË…ˆí}}†ƒÜ‡ƒø]!6ʵuLû¦Ò÷®r›B„ø×" ”U,ç@GÙm66l­‹”hã¸.¥ se‘‹nÀШXãß·zX›Ìóíp­·Ú´¶¿4emÍ Y7zåÎ:Ê•Q”ë æ×Út}Á®šzb&ä(»¥n1TýZê N?ÂÁÖ2kWÁ‡î°ªü^tþ'F!Î%亷ˆêí ùnjøI¤ÖOµ%éëH¢.‚ëše|wcÙ#dô»›EÑDpt•+—CÈô ¹Š#o±?…ÕgÕ¡õ(Ú:CÈ{<åÞ}^Y¶·ùˆ#Mgí«Iº«¬èŽÏsä ~J‘^c #¼Í×ií1òååÜÙz笸úóã¶þÉÿœB[…dÀÐØ¼²áŽž»jÈx…¡‘X<Òz/X]¨/CÓ8Ðv²-2k†AHhÇ¥`»€ýšðlnMŽ¡wµa¦1ÃÕ·”µ}/Cœ›‚í‚…–…‡J™Mó{àP&rÐ牾c!´ïBUôxîÕi1ÚÄ¥Ù²½î@‘%‰ç^í A}[ªQ+iµ!Ï|šjj8÷¾ yƒád§6§õƹPIžÀÈ{¤Õäœ,ø2Õr(„ãÑÜë?6uñJ,[Ên ûR4÷ú]!pÉô-’hî5´7.lÕ›uë–ãë|AèR™Å¤1žeƒŠúKä¡ùþX×°Iè~¹œ2Œ¼ò€dtGI¤ëùé·T+’ùZõ CþIì¶yâ·!7Øë"·ÍϪŸl„ú`ì¶yRõ£@¨H‚Ûæ©7FqD>"í+ïq5ñ¥¯8gLOSíͲ,“ “Dn›ÿk[îêåì-¡î¹mÎNÅáì·‹³ëŸýögÏóv±ÓzJ$5·ûP Bw»a˜ô|ì.ö°2<°kmU–^myØÔÊH¡_ {ElP¯Þ—E7/<òÓË\kÕŠÇ˰‚ý^òªp9“’Ûë¤mbæÜ'uóœq¯£–ÄšÁgŰxô5Ý¡’xOQFã:°*jëûšçPEF~q½U"éMxJÑ,éÇŒæ¢Õ†¡‚fIÏ&/Ù ôp‡L‘&µ“À(÷q+æ7õÈOBEã´–½s‘!$ fÍ¥[Á´žÖ\±*Ü{úA”uZbêìÙ8¾FÞüÎ\È £¼{¤KfE¤-ß4î)Rü #þ‹z—±·>æ3"¤9 èœ/ï¡`¬´÷@¨øó»wl¥Xæ¡Úñ1_ïg&wȨî·ï¥  ='÷û÷ÒÄI.VõuÀjMÇž¬6òÍÓ\Ó~qL}ù¼©kôH]XCÂ|ê™3¥ÊRÃòûÙ-k€D¤™ p¯‹Ñ nBçàÚ“gfp2ªØósH08Ì*dr¡qȌơJº7„<Ñ8´œ½Ô"äçn!D5ñ,¿q4H6«d¥õ3{´3¯f OïŃʹ‡!T&$¢VjfHåZÄ3ÍÊ·X·pG$¢VþY^Š%±/YÝ5ëNñ1oz`* Oþ[9Žiû5†:Ó±´C$/†ïÂó¼qÑ0*<ÏÚ¹ 1ÞùÔ²sCáŽÂ×ñ·ýãü¦A͵•DvÃÈ•S=Zê¯Ù7Û÷¾µñ¯ù<­v´Ö¥: Ö™D£gß{4Èäñ{A8·„Þ0•<¾w¡D(0ƶ„ øëµå´aæïèùsôÈ® %Í(¿2õëÃ1Ÿ?ß"l ‘ÀÇPW }Êm膨´û¨ýcm ­Þ0Ó㢠§'9*±U–½Á:uЦ,¡7ÿ$Çá—žë•a+(ÖÖ3ÄÉ'+ÃTÃò~Ò°QÉ¡ºý°s=I”áÎJ•íÃÔmøŽžàXÕ%5m(õzn;Âwd‘®üþç~w“œªõSo ‡c¾¬î¬u6²:K¤‡±g'?ÓÕ[Ï+$­Ú­@HrõwSøÝo_}kxøŠŸ÷ËZ ×ßQày<—µ@n©Ôy¢;[}\ ñçóùEá*£jUìò|”P!9®“çï‰Ûœ­riòmý>_×»ö ááwÿýùFùžº Ú.¿?ä[=BZ³C“ØÍë)p%ñÈsB¯89&6uT õ†lùº7!o¨?í¢ß†³yyû±¦ ì87D©JmZ†Ø ìM W_4~ëj7„ ÄãÒ·çÊ­oË. |¹_òE£‘æâ «Í/ùìy×ö˜KSp.9>æ# Õëaè•Ðr¿’5ø˜A£±p²Ýô͵ÖϺ |GÑp}io{w›ú„åBòº•›©z/mÅ×Fæø˜A£1Ó«¢M#—w3ʦ\ñ-%I¤<ÒXŽÍ[T£6šР¨QûöüÒ/m=äµÌ14=ïæh×ÊpÿéE4ÀL4І;¬Òk½‹tÆËL4@©DHâißÎÇT"¹f^„µþ÷vY·ÃËáû¼—Þ¨;Œ¼–Þ¹ÇïýZÒ‚ÆŠÜIäf¦Çû #Æô)L²­ySpÌçõ nô!^ŒÝÌN"61¿=¯Æ [ɲ$’hË (V0œ©ã.ƒHèõƒcå¼rnQz8sÓ3!!Sä»MÁ%l]CkaÓií) ¨ì&¯ÃÊøÁkƒ¸!Ö:çµäR„mÖÒ+ý.¿É+E~ïÞ¹Æ^'ŸuùÆ#o¨*‘ƒ7û>¨ß¼ÌÆ # Ö77#AôÀ“0.eT¾mãÜp‘´Âù¾ÖÂë9nĆçF|+{è!¾¢¡u‡ÕŽJú® ½Ë!q]Õö§Ê®mûel |ögX—õ ™Ó&ÔëQls‹¿‘C„R)¥Ð"¿ o¼"E\‡´’Ù‰½FüäBSÖ9µ¶s·5Úœ{ǧO` J;TX÷íP±Juƒ%†’`²S» ЪÛʽ;5…Z‹uš1_*t„‹¡·jži[òléŠæ]¾1<Í"Êñ–g¢U[}¡ðW?¿í¼”R!×¹ïÐ'Ö÷6o€JiŠRŒ«ÀÐßó¦Ôy<²ÏªÞ‚!ƒõqáÕU˜ÕVy3…åñušõ²iÆÜJ®ó8!$˜þé„ÖÖbU:]‹Zf> !ÑT¡×A ­5Iæ«ÈšÆ§@$Ï™Fšf̸cNS#¶æxÌ4\±Ü*UN“oE8fò%U£™„igÏ žPÝUòßydúÕd^‘—TwÛ7‰g?š^bcí´!äUÓ‹3;fO©î¬aH˜<ŽuM\Å¡Mç‹Ë$6‰CMš}ƒ”¶Zòsÿ¢£Í]}€G~N©lO^mñ›JÖr8fleb5¡¼)O›±¢XÃÙ‘™±¬j¼eËçYn ÆI&̰¼·%Ù>3F¦±A´ýä*^u1B£—Ćn¾ÜC- ¦]©~UŒ¼‡)bÃ{ÓFÓ»¯dSìùT%[jjŒÙMÕO /òYw6•)_>VßÑ/ìžöõ¤æì´ØÄÆ;„|ù2_(ª§´¯m(.“h¶ÅÖ#í5Y2[TDùáGJлì&÷ õJ©^`蹆ê׬ÉÏëÄ ÖDFüQa’äç›§±žÂñ§å>§pª š@âé–êLÏùÔÁÙÉeuF[õnÀk"‘÷ܧ?`¯>d¿}$ýÖÿ˜B—ˆ|Η8ñ‘ÝúåvÜûíËuN»„Ê>I®>yW…‡jIß«ð4œ=ò5ûß_Üë͵8ŽJ”áÞŸ¸×[ÕNÉ«¬ï~@M( G’S[RÛ õœ$B~‘}„¥>ùÿ¨­°¦`0ÎèVI"cEëoWyÒ$r†éõÙ[Lòóg÷Y€C^Ÿ&2=o´-<%’|ÝxøÝ ¹¨­3S[ò”„¤µu#ÍÓU ~NHz #—µ¯­o¢«Ç¾8‚G÷?&éŽy»¨˜w{Öaäýj&Y·5ò²¶¾3‰‘ÇÚº¶PáꮋÌBžÖÖ5›oç‡|]Õ‚xõò¥ÓŒzÒ„|0HiÕxu.DAKì•ö™¤L"„v1¹ü4I-)"—ƒl£ŒçêUÊÆ±FÈrýkm¦¢0¡Gñòóøüe W0Çwô¸N|×ù¼zç§)üFÏ3UsGÔ]"oȹ(†.‘¤ÊQ(F¦±ÄUøŽ¤l§\ äíÂMÏqò¼Ÿ¤[¨™ÄǼxçé0m‡;ºì'e!ü&Ïoï¼ú:6|/ð‰«¼N‰Ú¹TX›AO…ÙòÞ"Rùnе‘lCH—r¹ŸÒöe­Pݘ½9BžÔî´„è¾ùgö$ycùL{ïkb$âÕÿÏp7½[ ÕAº`y*f„–Â[xõg¬/]A¸;d£ µi2ëü¶¼Ù;BšF<Üó£B÷ü::yä ExR@Ê ŽCõ~JfºnÝ$t” ¥÷Ká*ÂK¨B“ôql|¢2†¹Ë ø5cC¡?“˜7Ö|Z—ld~#øŠ×ÿL§¤µ‰¶=ndÓø¦‰ … cÃ˽ż¼¢3$b¶Gü0=ÅØd£˜¶­a‰¤£jï³5ÝÚ¿{„LãßÈyÀPÑì,¯Fø^¨/›ÞTí2Å47R‚Üwþl¡ÃŠ‚Êe\´7™ÿâbò‰x© îB’Ó©Ð\O…úª)¹ý|øU^˃‰x¥YÈÇYÏ\Ïznø˜÷Ð)ðC¬[W¶V½ï‘ÀB>•9Þ #ÁO9ób/úì]±í}Ñ äoà—NÚŒõ4Ÿò¬ÉñSz¾14ÖÛÅR½ù[l~ò?W“ž2족:½“€¶r—3ô^<”\oN0öâ¡i­]{T¸i5uø’ô^«™¦ËZ‚N³ù<4ÁºÖ6¥ðÈNô=EÈH×:jÎ6[ÇÃö‘«iÝÎ4’7k‘·é© ©v%>°!ï±8Œ ÕgYv›ìäá˜Ôr5•‰7Ï„Úç¹,2nÎZ^Fr^¬¼[‚›³…(  Ù­ä ÞÜœêWêjî'Lý“ÿ‰7FÛ\o Tפ04ÑP­î¦ÍÖìœëûµ¯Ø*P[—zî>ÓS«°3ÄÌvç\J‰ZIXQÀ¾t#ÇÙ,u~‡Ty´ºý !Óˈ•ïøì·€ÔkžíÑ©|fr…˜Ù~]N‡c>®õ `· Ìö =(ˆo'Uç)½áZËÁ¢*ª‹Ð²|‹À¯&×ÜraY+eÜîמ™ˆ]CnÿÅ®]ñö8ú²iù¼¤eAZÛ^ Òvø˜'‚´ì Hë'‚´ì HëßiB>|ÅÚsÕ¶ï·kªëoÝž­‰Ã'é×üýk ±6v˜¥¶5žÀiŽDYŸÈ]=yš!$‰ÛÔ²‘Me¢Û!¹G]ñÓ³dòg÷ldrOþãìÞ^‘ÜK½Ù?Í**–f“Ãu»{ÌžýsÖ5wÙ–±ärEHïžn÷V'—²‚¸)põϲóh¢ÄQžÔ:Ã1–Íeç»âä~;TjWªŸŠJmñÍ\íIâ<ÞNïé"ôÖ”Ðm%‘CTø:¬¨`ÃX6–ž;@î74çe5\L PÓ™o;ˆ6‘;}7×IÝÙ'¹Ò.ëòî¹¶4•³ZêDqÓ=ôÏ]mÀ)˜ÊD#…:ŒüÅHÓò*&•#æj—GÈ—×>,Jû4º4k¶æöü“·“‹ÚˆQ÷ÄÍÊ4vËØtuå-<emUÝd …¶¹à ¦î¡X¡£…òU5OÓŠ¡)ˆÞ;—Vª. ë> âð–Üb¡!kù¬ K—¯õûpq“ÊÓ²w5³|_Ó +tØá=S™§ZVó¸×úôP8Ú™¼L{"¶3†þú®cš’S5©UT4‡×Ï)txMI=¨k‹u- ü°H,Ñß:9—¬ZêAm;øZ­B‡©g؈‘²˜tåvÜñs ™Í+uéco´älÁPìÖdH'…­Þ*ÖÇÐÖ”¤öÔÊ7‰?r?Deêê:+Ç²î  å !Ü(}¸ñý¢.!ts£1G!÷ÃOƒX6ÖeÄÃ%ºûXø”ë!,BÃ%nñ³n \Ï‚ ÈG¢á’¿ÿýk(A®ô3ˆYòàõè'##F´MŒÀ1/Ä/:«pkƒrÿp¯„yÑm­ „¹_ÛÕ:¯*Žö: Q4wåNuï}» +Ý?ÇVõ­2®îˆ¯ÛŠ$VÖ«=+¢û /‡ËÄ£~•x|õD¡]h<¾ÑËöI„VÄãsÓ«aÓ«—J@ àq;z‘º¡L­Î« ´+òÊèqç{¸ÎûW釅…çy?}ëìeÛÆÃS _‡]  ¿åJÆDWÊrBH\Ð1)‹.èȪ^i‹idì5 %Ë5Á‹õy»2PÔÎ ‰Ë^Á ”¿uœ«.#É¥Õbu8fê S™e*êç)3]D )ËãùM…5¡‘ü¬£’&çù Jšäq­¤ÙM ú˜äq­¤©ei²CÈôS¡’Ïå¾M9ƒæJð¿:ñ|£» ŒÇëÒÍ@ ‰Hòü.ÉÂSBã2ñ«Øuk _\,¨ú:¢c~‘P1k$LÈÙè04¬R¦@Þ'±_‘-ŒzM}9«Wo›`›ýŠ\‘ÀYBîí¾ŒCjõü]ÈÛ {Á2Ïù5µ/äå9ÛÚ> ïö¢,j¾o(²Ç><é|…œØÿv%IòJðJþ,lò÷ÝýŽ F!fÄÿéŸÆ’ ÷» 0 P Y™e’qwïóýRôñ¢4ŠŠªM¨ }Q8ðáyO¾ÙáݧîÞ‡çýÉŽ{Ròá ÷b=<ªª÷îÝ|}Ý‹7/üx½.öM®÷Í£ðk)þ¢€¥% {„±Ö€7ž$ʪvßYÏ=¹¦P3!sh»zž@Ó«2×.öYyeYdŒ‹×ʧÊÄå[¤Ì ™1¹Ç?;—Zurçj`犾 ߇#M÷8”0ýHw†ÿ¼qˆîÌOtç{вÝy9Ñ-’|!1ã³GWÔä¨Éùxç·'¾±E>ßپů%÷l_‹üFËm2¾ ©©]¸¢èÄ&¬`Xç8òŒ®°#ÄÑ¡¶kÕôsÝ– ­qãÍfc›—í;lü@"+Z¸E_ÑØÌœ—b‡•?ÞýóìÙ·† ™(r„|13¥)í4Âë‘»8$Æ’¦Qç öÞKÔßã×I`¦°ŒºQF€sy€lŽEÞ?9 ©1ŒÒ·âøREonxyPÄòŽ=ïß=Viz‹~>ùc&oåCWöØÊ~­ý799ùrdNÊMûpÒiÊ9BÞ‘Œ„iú²–µM:ÃÓLÎm­ÂùÒ©2çA ÈÎ’Û)®Cуµ5>æ#t±QV!Ò£ùÄc»f×–™l*J†‘/<¶k«™ãØâ»£âº‘‘(;Ê›¦\ð]J.ʱTøw3¹…C ÀF‘ç³v¬äk<áÛôó”œ*ãxÑîc+Ï?ÐCïˆe¢ë>m)ÓÈt›çÓ£'a¨f6«dÆ ã–j‹.\ÅM…–û*K—Ó2ùùX¦kÕ—¾pn¡OTŸ1C 4—Ÿ½lmN—õB¶„Z”³¥-é>—§ËŠQÍÃÚXÈ( GSbh57_.÷›mÛTŽâÕ»0—’¯)°4“ŸSúUæðìeêÙ@>œú¤…Së÷äZHS‘_´üË÷/-$à%ÿÐBšüsú‡Òù¼ž„÷WDPø`T‘úìü™÷Ôt¨å^ÎõQ–i³îy¿Ôý½Ç{òøbç&ƒV66T.evkâœoãÈ]C7ÑMâÜÖPÇiîÆn®¡³•`.–ŸŒeó:ïò]†€=B1N7ú¡V]*¸è(˜·Üƒ!Ž™½Ÿòì2 xSÉ5i¬J¥¸#äÝO*åei¹C|J«É÷lŸz*æ5žzkZ›iɇ#ͪûóÛƒú©’Ôªdô„ËÑo¡IrÍ"Fƒäv»è)j^tÀµ&·Ÿï¦b0 OBÃ*û½s7TÙ}§ |A‚›"ÎDœ{:÷mƒ0KhzK¦=O¹b»k'h´Ä”ãí{$&º ìpì2r#oVë!ò`;GHâV)$U¼¡ý84=o2ºB*£M„|„*Tîì3Jäbä3EA«K)ÁòŽ2ºàí3eˆÒÏ»Óä$¡·®î …*9Ô]wÌ EnÏKüã »·E'· `üK+¯ÙöŠ|/V¹uN7•Ü^×§. Éh°VÈë«òZ'Ž!í3ÒW{—Žye>·¸â¹Åçï’ ñòe£ÇÐÒŽ™¼) =iyçÕDÈáX¯ä–àµd†PT<²Ê[5 Öå ^étA?÷rR~”øìQ€d®¯VŠ~ãÔ)ÙYä#è)–Æ1¨UÌ lžÖ!Ÿ§”N¿qe5 ¼œðÙC5}h–ÑQf‹ÓbµÈ8ä8‹8VQ*㋽Ûõêt.¯úèß²ÊuõÜ¿¡¶ž%UÓli/0Ôp-~§ ÓÒäÍ$sÔnï7 ½Ÿ¬…”¥Y×2lû€¡Ä‰P爩Ze)g”Õ†FAO©´zÚGU y¿x¡/Ïìþ%wÙ¼’ÙUÅ1ô8.j‹j}Ô¡kÚž3 Õaãoµ+Zã=ÕÔ’ûb×ä=ÅÐøÝì^¾tò¿²¢8ÝÄÏ„»0&Ž!Fà’Ð ç·ÿ6¦©™b8Aq¸á`ëéE3z{°ž¶HMÅÒ ª5íÖa«ZŒŒ‚'eå̹’6`ÊÊ!NôŸÐ¥§Ó ¬ á™þxíRsó ³³VwtãuÕ/øŠ^çûÌ`]éƒPoÚ T{ÒÌyÿdk¼#î/9û漩¹LðŒÈ?Ô\üÙÉ?Ô\NǼVsaŽ¿c‘Ñõ(#ìvÏÇV&uª]$ðÍùØȨ̂!ïÎÂ]•K›Œšú‰U꾤?xR›½ë•,oûxlÃÌáìxV*`úì͸sÞ²!aÍû=l){לäÂTYiÓ2¾*ï³Í ‘K?ãÁÔ€A.3ºôaZ´en)üÞ¸Ìü§î3ˆÛú¼ÙØêš5äþsÝLœŽÃ»áûIß«pVÉ|:xV­5\{8­¤‹N†ÌlfQø´#GHÐþP±5³Þ€JÛ–ÁØ6 ¦•þ³¥$Ã{î›v«Ž6=ð1£ Eh÷ïIôU™ec†‘?^^Y Í"ºuíV6µG'מÜê˼°%£ÙŽ¡êº™K•o1[X>í€$ŒrLD"©”²ÁÉ"’¬ZH3tÚaK¡è`‘ŒŠ*ã½p7dU¹M~Ú^f{6»ÂµE¾Þu‰ÆfÎê~ا!ã“e®¶ fK5‹ó1¯5¤\x-•Xnó}[äøÎßÙ¢uì­Çl˺nÁÐ+µb%äö™û㻂'÷«éÕi|ì$Ö©äsæWhКþ2_Y¦t冾v÷­i(W ­yŽÞ£¬Ðæ"*¾íŽ*ò5‡zbjú·³–!F:M)üÏø\ÃQä>£r5支%F"žhm¦T©±mGŽ‘h‚Àô²< QÃ=Æa»;›º¡è„|ø²¨Þ¶Í1Ó²[x%òé[UÎOL®P: mî¿L1Š™M¦fÛ Û®èøŠbð üåhx¶S†™¸š Ì(÷ãèÀ{ÇÝù«±ñ|=ÎЫ±qÊÀnÞAïW’Pr¿š¼wWLȬº+l9\aŠÛ‡¬6<66Œn=BÞGm;i {;´¦ð*‘÷Ãzç,tl,2:uÿ˜5k è·[äã:©t¼*B¾©dL“ïå’`\ë÷oŒ˜ÿ¹ :m™3z „\ÈæšòÝzÀ6K¢ë±2¥Wæ >$ú&%ƒ±žÑuIÐv>á˜ïê¦C+?Œ¨CKȵhׂ°ð*\”ÓŸp]BR›R:ˆÊ8'+…Ô;Þ¾²¾áÎ9‚„cPT—Ò•›$R†ô`@U•’t˜£õLŠ©>ÿKýmt‹MŒ'Úu˜j×]pÐ×'/ûºÊ|«N÷5ÆLz³PU¥¤®x†¡Ég·7Áwç4f†-@b Žþêý\L°ÝRÓWeE‡‘—ÒÅCs4I.¤‹‹¹…9ú̆‚½!"ÿ`CÁ¾‘°¡æ!¿°¡v|ö‹„úXF$о 5ÊÉ_ûã{Réw‘èƒÞPm‡½û¬Ùª&uÈ×ÙH,”ÀÛ ŽQüYí€L®…-öPØ‚äïwúÇíÛ¿˜öŸý›°>æµ°EßcdrÅ*ô"Çäñ󥡨$0 zw~©dI%é&Y:æNÌ%ˆp“ÇI5ÌÎü2ÓXÚä­yƃ¬)…(!ÞãC«,4á%èMWÎ=¶‘¶ íü3z¼éÊYáåñÇƒÄæqâ®ÊÌ—Cg\ $9›üÕÎäÄ4-2 Æ›ªÚY?·-Í'Ø?žet2ÑÂ@2À¤O>ÿ¢ÁG™ÎOEÕƒ™5yÉç/+Ñb )ù>Ð¥: ¦€¦Þ÷bŸ­šFwéu2pp oùnvƒr¡ÜòîöNLS”›Ú“„LEs?õõ\d‡ËûƒIà4Ú¯Í!?´Íf„ö£·"‘¹ŠP«¹ÃHZ»” ξ™cÖYd"™åŒé³gó$0f웩¹Õ|”Ir­i¢ø˜a„§¿³•ŽðøÜdþíˆÏřܾrêôÛVäþs‡òÒ°šj3+h]T§£ÞCê©QVj*J€ %ï<'¹§œ¦ÓÞ`häòôn¿ªò6[>e§ÿú@å!ÓQÐuËùé¨^ðê.Å’Oý,c‡ôeÊÌ¿ óþÏ`|;(L×ÑŒu­å;] 7ƒè Éy¸Lï7u7l£ÀGõ[J?€9÷e>‰:/NÐ Q¥æÙÃÓJ¾Ž¯ý„‘Ÿ vùb2ÔׇßmŸ?WS êö~*<ï×HÜJäŒwçýKMn©bѺm‡iòÄQ«¡GXɧ%M»Z‘eÀªuÚ§ R“'y·ÉªL,Ú²v«€ßHžäÃ7ð' ÆJI>r™|O€‹h‘QШv;£˜VEôòÜ“ ­ï¡¯}dÝÔVE¾»Ì6˜-²~ÂÌYZÉ„~¦í8 äÝ›c«S¿w­üþ ô,’¸ˆˆ:š°b’W)S*iØþê.•ηR"y¡ªã)B>>™9V-ìMádÓGVí yŪU:ªI.¦ºŽùð×þ<‹Y‘ç‰Íù8ð-…§ùz£›¨*¿6gcSºe=F"mæ”v+yçgîjÏ3Ëö‡U±µÉæ.-BÞCz„±>Ѓ¹Þé€$, ›¾¢qÈ}l„½á‰ËÇiîÖ¼*^‹Lî8+B>P-É]Ѥ$ Ö!ŸP%‘T^ûä¬j-òåÇâß^1ÉåÅ FÆérQ9bÊÞ,ùQ”™„öÌP’–‰÷ÑBk韙º¹¥\¨Óg3]‡ C“]7¸Ùg¨¤=ƒÝÖ²3˜úVe¯±]ŽÂÍ|;¨1«Òë>‡~ÚŒm!6¡ŸÝªŒC@“ |ÛŸ÷[Mè„ôAŒuP¢x])ƒMòÁ‡Ê`äu{sv¦ìèA‹¼~¾ÒïÃTxäýË+;%oNH¨”21ß †À>—R x|¤Jpvš;xé_~[°\M×3j„×µÈèSš™Á\¸Ÿ_ŠT¹ì@äõøòÜUJ…î×ã¢$n4W{w ¯ç7 ÛÀùŒ¼ž_|ÞCÞ/y½®õÔ˜/³¿â·D¹r‰2k愎I0\uæì1ª8{°æ_ɧ®‰zM6ß¾¨Ïtsîí$þù¢>#SjÏ8ø6\¥Ìaì’Ä÷ P¦S6ÁµÇä»è EÁø_îtðÆÅÍö×|¥£8–¦€³?P²èE³—e:.¥@ÈÀ³Óñ›–†Qùå: 9¤c vty$ Á€‘ -AÌ_þÏb¤=„–Á€ÑßÍ0¶ŒŠ“RKiÚ=ƒÄ Ÿg¤^QH¹/ác¾Þ­Jö(©odºšQ¹^»ÏÊï7 Ÿol^ƒÔßäyÍý 9Û(T•+d2hš [â ð€{¯mÝðlv‹49݃”Zðx—ö=>æã²ýçßâ` Ë´lò‚Ù…D–ÇrÀ ØuòmJ²,&„ôª¼9°Í»Cˆ<Ë· !ƒ1ÁÜ–¢ó}g¢Y—Ÿ=Bm5]ÍЬ1p`…Ä1b…d À-s¿oåžb$tÒÓ˜·òìÃF`Å82A“åÎÐJ ¬ÄÈònXó*ñÏÒ£m0:é™õ¥êkÀƒO®sIÕñáErûªûßS q'Wª½êOr¢$9I¬É­X—¢™Òeâ›hŒ¼0‹b¬Ùh Ì|4‘ö„\KQSímï|}H@Ý ?ˆòfKØ#‰R‚ÆK4iÊ×Ô+ãk«8ªpÌš5N£PUC_,®ÜŒ‚8Ö±Q‡Y*™÷¥[¿ y÷ZB:TU¤¾J™Ã±­[’ªCv¦‰µ¨¶¼ëG„Œï„|HõÖ]ÖU#ðOaW“‡Ôxr«}}ˆz”c‹'¹)½u ¶‹¦oö ßù›ÓÒõ0ÓÌ«•GX*(¾x$7ÅLê'·xVíûÌðµrSu,âÊ2uË÷z¤ ¾(Ka·9óU¹a§âô"4x¨Óéœæ‹˜«¾Ä·ÿHÔia*ì•g<%¿a( ©Ú˜Qµ äqéœBžÝNb€\¦œ¶½Ì)w„ Z;Uû<çûÑ•¨q»Ú©Ì~ʆ´ÁÈO%°ÐÑüŸrçž9ÇÿóáM P”×¾ÐÆ5«,Ò3 Ó¢64ÿ¶Ÿª¦êÓ¬tÈôŠEv1riMGÈ{°†HZA\o‘Ä“\»]99òÇñ1£PçÍ6ö‘ÊÇIS|ÌGPpQR|z‘nǾe¼ò~–û±`½žÏÚÉ 1D·û9›¬LÑX#[Þ Ž$˜Åqj\MUî˲ŒC~ÒâsS;tGˈnä½,U;êPµ5}¹!$ ¥a¹‡‹©2º@ S;Ñ ¢F:ÛZî7…8òé C®)£àzÛÚæiš¾OJh{)³€¼DÈ8x =i¬”Ø&± ›ã?Zd¾ðV˜—¶]•nƒ+m»; +¬f¶-­Å>@…ÕAàŠ Ã‘uø˜Ï*WÓ!€û]› 鬦¬&òã:ž ĬÂW/d 52(ü1ú8¦ã>îGuÃàxšQhm´i ^ιòcq:Q`mäÆ! ¯o-©ÜCÔ‹Œf¸’L×ë“ç<­öÊ8…²Õæ*×'dN•íùÇ™QAË®¾‹ÿÏg(pí4BÙPö[•áÿù‚(Ü񵐠 ,2vêfn|Y÷Ò:*º<ÃgO`dÅLÂ+½¶R ƒjTácšÄ×{½×ƾ9ï)ùù§_J¡ÔûhäÜ/#EÈ w -‰ K$þâŽ1É´všŸø4oë¶Ä±™2€gPôó6ëfNõ+WemA*/úIÞéõ è\—Î#0+Ó"÷›*=Æ #±¤Ÿ–éÈB"û¹AÈ&<R€"<7;ĵ?Éi1å•{œó^íG^ùz¯Õk¯;þŸñ{¢¦…ÐXÊrŒL‚.û?aW’Ä(ŽE¯”ÆàaYû®ˆê#ˆ$E¾5~écãŽÈÌÕK Bhøzƒ% Í=;•aš¹½ã¥ÿëÚ;#MŸDu‚Þb¨‹Ñë9›Š¾>C“蔨ñKp²Û8±Ó«wJÿس'wAȦºó¹—¤x³ü*ʘú3ÝI&W@1xàbdã1Ãøœ]ÆXˆÖº@Ò#B&á\Üwg}Í¢!eøõr›Š­ž÷’qíBÆ„”ÚóAØØ³mƒvJnÑ<û7bŽ4j=ÐÍ9F>¼(7¯ü.½ÇŠÔAcáàd9 wËDÇYz¡šC¾"¤ZwºÈJÀ‘Ö!ÁǦí25wÕP’ô-ÿ'’9ûu°šç2TUŽ¡·/Þ½ë"Ëqžj|§·ÈÊ›ÒJÙ®í~0}ÇjFdfö5u¹KŠÉ•WGÈsK“(½ç_w0o'‘…+g LµÉ‡DíFq©9… äÎ¥‘žçP“S Àô3Mp‚}n—¬v­t¾,LaÉÉ[¢ÐÙ™f$›¶e˜Ù ûÙHýˆ£itèU¯ª2^5“ÂTöë\N &k9¸e ý¼j…;ô$;•œ*·\_ ÙÊÉ?Ñ#4vS d]–Ù;±;äÓWg´öÎÙ± zðc?Æ!_(Ô×ûèLÓ>ÊZ"äûqä˜zYÝ9 ÁO­/Ñì`XàÅÉo謻UsçÚ´%ÌÉ‘òÏžâÛMs†¬v‰}ÕÁ"'ÊI³ª`o‰5×d•jÇ9BÞcþÚ)ÿ汯*Õ™gýÚug¢jÛ·Ó>,“ç/3MM)ƒ_ý<ë>z×Ä&•ç³n:†öÄÑ&aÉö%¡OÄ•®Xúö5ϵ4÷o¥ -02ùjÌú½š÷!ïa/]·Î&rèfqÔ½§Î§QþXØ [äR Þˆ#[«õæ¶œ8=`°½ß¯ëÓæÚ°d;Žc¿ÞÍÅ!SÔÏcœ/»ahçVìs7"¤ÙªüíŒ:ì³Ë²÷Zž;àfJúû8!µû8î8¤™’Ô oîÓeç¨!e›0òf-¢OÚÉØö;/<Î!߯ÍÝœOÖ•ó9{µýÙqËCOiä®ú- 5¯êSÊñ#¹8ý–³™UWÝÛjǶ™ M_[µ™wá}êHíÆÂf…©6í2A¹^MÖ*›>ß,pî¯Ïbp¤#åa|¡ó/kçÌ Ôî—3¾O·ù7ŠBÒú#A7ÝÑ¿èrIÛ/aÀ{ÿoX˜”âØ¿/Þ°­˜„¼ðCVX°Kƒâ/¨‚ÍöÇø6SN'ß“Óë1D 7´>|†Bš^×¥,a&ùô׉ó"CØyz–µ0Äêe=*Røõð{*Œ­óµ‚/:zHú5BRo§²ñö FÚqéï¿"×}õ޶^‹—„¼#ŠáQ–Ç"–¼ ¶GKýçoW“3lÛCòž¯#ÔäÒ7Ò¶˜šœ3Ç”½Ü Ûk§ Ëñ×Ö¾÷ô´-îšÎhHVõ ›4Gtí0Vëei·-´ük[JpèyÕ :)‡|"rS0×±oÇN·²EÈ—§iF„}v©&-©=¦ü5ã.Ýòij‡ít´c»Œ!“ïÜ £;óï(ŽÕúÏ_>VË.-is¨ÉË?;RÒ™1ÙWS‹ïÃ’FXŽRæij½dy]0se ªë%üºBõ6ª%‹5Ö ¤v¤ØŠ¬ûÖõøšY˜*§œ-jÞš<òá•2!ÖW3‚ÕÞƒüìÏ ©ÑÖn®•F+#1òåu2¤ðs‡¾&Q×<Ý癕¹Ñ[rʺ­ÁH[ê‚—ä&x"ÔB<‡4DŒÙÀëä:„#dÓDMÏëqƒº b´”8()ºæÅT…½#† ~ñM=”#HéÜLËÜåF>â¦okßôõ7ý½$Ü «Æ_^R¸OÌ&¤ìŽ^î"…ºÏÿº}Iÿèù°ðͤFG"ÔÞ *M‘ÖÓXUL¯T“XÝD!mØ,­µfim¸fXþó¥#TîP\læ<¼øˆúï_ÖS¢ñîu±Œ7g”µl­W€škzŒLb¯†Ê9Els¹,ëF2ŠØô­¤FвçuØÊfSĦo’L|%þõ,”wâÎt»mœzÎßí´Ò´5“—¶4˜êFíºò >¯FãÌäüë/oGÀ(N!k2ïæ™,œ”˜µjéÛÆAgÛ8²GÔ™NËZí CúÓEo—«–hG‘=*ÛÐó¤Ùëÿ(ÛÇüúªl׫l‡#ˆH•ú]Ù.ñ¯ÿP¶Ãú&R¥~(ÛÕãe{T©_”íR'|ù%¾Þ)ÛA.UêWe» |„“*ÕŠB­û@[ìo&@¾­—O>þࡾòÆQ–°/f˜ãø¤ wC˜þ@—JÇË@±åq‹x‡˜ÚO´oØ¡=ÂIÁ¿¦ÄWxÛuÁ–ijC+=’ß&Ð`íœ>î¿L ÕJH`dòýD^§w„_ÿ$×» ñÌ];38øzdŸ+!{òb8M}é‘áÕjY9Õôз¤à<‡ä#C6áŠN ½%°3D…åO*:ÛFŠ‘YtBäF¦­ «ú≑OÒ:5¤õ¡òþùDƽæ‰Ô5©˜ú}À­ôd¥¹¡vo<¨Ž7#¾æÛ{Âhã?[°¦Vs¼ÁPÜ·üð©«¼©÷Ú’rà;¨<ÔVZ4½¾ô£­zŸußì`sê¡É·Êv£+Û )IŸš’`F•†`¶ ªóÐä©yìöØ9pÏT,-L³±(ÑLt&Ê«6*®nßÕÊá@È«¬ä¯þý+ë@íÓNÈ«¬ƒ’†Êãý#뀴ƒ•Øãý+ë@ßçY’³E`äãBV­6çÐòq4š©Ù–vmåÕQLø­W¤ŠÃç)j3ç)Þ!Þ!“`pÕ¸-â*ÆaíÛ¡ñ'~Ïäƒ`ÅDúl®/Ú>ùç™®ã& r\–#]§våEaFèŸÏÓK ®¾¨ï“qÊ'ŒŒã—ZË_ÖWÚL¼ÂÈöêÖCÓÆÛä ø>Ã0b—ÕÑjÌü8 vË!_¥@­ŸÃ¿þ¾*ʾâg;~Ôõ´x‚~5¿;ø¤³+|_~Þ¯£- œe=ï(EÀfB˜vZ„q—°\Ž¢î I!íF^#˹­æ!ÃV:WšŽnCS‹a«)BÞ#Á‚/ZjΊ, ,£îl¿+ÝéµÎs^ÊrÞ2 …PÏn™‡Aý³u0y>±#«aÅÖn¬¥ê¡6Š‘ÏØåÕ²bK¾õùQpÎüÄŽ¬ÖÖh™øÖ,ŸrŒ|Ÿ@õ÷!Ô铌 ¦ìºòM6œ[‡¡ç,m=)òjÖ¬õJ`hDöl%u«]®þ_…?²u+\íÖi!õTƒÏ«‡¦Ô)KtiØÔÎ#††¯9÷Ц™­mÓçtè¡O±ÉµBÌ ¿ÔJãã6múDlÓ£çâØsNúÓ¸½â &{R´ñr›Æ]î3†¾='<·5]ˆW7 Æ‰zkqïÿ¨ó†<¡þnK5°‰·k í ¦SK˜­¢Ó¤¾ u´£Eñt F¶¾oê7Vr‡HëÒ€iÆ3¥YÆCSäþo‹d\ìS+É"¨sŠWíZˆ½g§xx¨±ö3ë:’S‘Ÿ O5‡;ÊjPYx¨‹w2T'^Ñ7°Ð¼iOíú>1¹mR÷RïM?á«ÞcZLS‚û?e+ ½¡M‘-ã6aóâÔÆjóÂ,#ŸÙš !ÆÈû·ðiª}»0§à”¡Ü×5ïY- ›yƒ^uNªÝ©ªZCòü)CéóùiØçŒÆdÙ3Ó÷è×—}ÐŽê3à‚À}¾Î«KÛ3yY´&d…hz«FÛùY_6ã\‚‡CÞ?uÉÌé’;xóïÏM–->™M–¬ó !("kr¸£•v„NûÚµyµÎV„f¶c娮 B¦ŸªèÁ©¢)¾Ï mÜ\ä¤Ú¸õÇJ*„|€1–Ù6v~Û(+Úãk>?•ÖƒSZKŒ|a¤9´ÒϾ—‚Œùþ¦Éî´&[BuôùŽKÃÚùŸ/Ê£÷™Òz»J9"ápí± MÐðíMC™½pßM§W÷!¢¶—¶ª&ñ—ªû1 ErF¥¡K®†s Í>µæÌiÍééªËH¦%,åÞÑ|öºD«Îdò=jiªò3J2ùÝÙ©ÿÙùì[,‘§HœTÕ”8ܚ¤J:¯þžþüâ ¯C(¿°MjÄk^5¯y% #“¯Ü^A+:Âhöº¡²¦áª?…ÏKpÈôÚ±Úéu l«s ¶TÄ`§¯äG v¿G$‰Wò%¥ÃŒ¥Rç+«ùÉ}¯û/sÉ…‡ÒÖ+½>ܵ3 ³ëc$fN_ŸÆØ<?"Wãã}ç;N^¯Í…O$=ýð‰1æPþ>ß—6g\gúq±§!ôÔ[’;˧VÈò)}ß¾X>™Í»€¼+Ð*ŸMdúÃ~Qg…gO$´m„ßd'9g<õ 9Â|”ÅrÎùhWóe‰ÔÁöHFSÇ(/„äó3‚ wiÄY$üt:wW±X·Y¢Ÿ¼%Aå~7hRðÙÊ‚ðó»ÅÃÞæ™Ö‘ÊKÛèÐ5ÅÚ‘eGÈÇ'’­Ò Û!#·¢Û©öàÃ~„|2œwU\¹¹. ä;šãÜq˜z¢Q3îý’Ù·üf"Ýì'×5¹ÈóãtÑÛíÊÆ&§4ghp÷°ê\]§œ+96óÜ ½GPg2¯Ý67]]mš‚˨gÖa‡&ß ÍÀ5Ï«iUûº®­Zbè#‚¶N4• ËôùÅåa.gÖ4¬>õè×'TÛs}ÏjÜ©œE¬…Z?Žv%æºÿÄÜûÿ\XnE¾:ÙŸxA¤I%yãDvzQ@ø!á“zŸÝ¡5]Ú ºGO ¿ …tâÓõæ0Jn¼ý¹RhN` oÎ×´¶)f9Ö·T ÿ¡ÜnçÅ 9d5ÏÂ')üÙiv»a&ªêR••¶¥ºG¾OpŸ (¸pusÍekÔðè÷@Y¤<6îÀ•áG™å­ZÔ¦ú,(¿8Ù’#xÞfq¤ R‡‹½Ež§Ý°i w²ÕËÖÉví2xËTµSÊní:oí¾ñ!AGž«~oÄ•zûÕÖ­¾L›E‘‚¦öëåÙ† Úó²ö²ƒ,Ò('ÐFØò…ìB'0»e'±¨UX™3s…*+=òñEn»ãBOŽÕÌÎ×r:ÌÛdÁ7;©™‰¡—6&*¼¡ãÖ”ÞÑó\œsj{)—v/о`‰Š^þ>õå±Þ³³[œÔ`¶ž­/P5j‘£šŠ"d%£j³ÍÔè8¡Z)øh¹Ò¨= եђ²¦÷VYéîÇM¯s.IŒ°œ©YdYògÉ4Ž˜6ö“¨w¥á,Á¦…–éºãP¢=}h‘°hµ{ÌØ Ç!kŸŽã Ô,Ì$f*4Œ,:òƃ:dèÉN³ RTÖÞKÊ!³Àn]0èÚË¡ïv±à_xaJYEÂ^Ò¦€%Iâs"¬.E3·–µÄk ŸÅå/ƒT÷é"òàý<5+ „|{UЉ3´Â>É:²îa\J>R|ü‹oõÝ9 vANûÏ®ëÜó«6ˆ|"÷çÈiÃ#™ñ³UDæ¥Þ½ISrZå8¨y+k]ö@ÈÔ wÐaÕ3Œ¯]>5ð!œÖIrGrìÄH%z^×ùˆŽdüy@QÍM9íÄ‘žÔ¼øÊŠÃÕ°8²ÑéQB&!a¸ñåÆj¬ô=<{rRº•^¹T¤:Y d Z°ÚqòÔÂeš‰6GHsnrü*çªéÕʞѩá5B>BË;¶WwLdS{Oêɵ ´òxàD]YÏñùÝ”=7ÓcN¿”dTkv|MÛAÿ±t/ÛžûÞJµÄÝnO«Û2PÛ?Õus.+Ò6bÊ1ôKtõ~»ÐN÷ e!u.ºžÌŸE¦¸&Ǽ‹.FÆi¼•“© }S¯°óF}]ÊNsÍR1Ñ—[‰‰§j[[¶Ú7«yhúm9òÅúÎ|¢5„´R{s[5’®um康_°&Ùת˜†¨¿rAÈÈLߨïáçczý#ÊæôÁö\k¦\Šö©A#»ÿ÷?Æ¿Í阩fmâ‹÷OÍ0ŒMP²äù#&PÓâ`ayR©FÞiª+šÓ®ùþåö‰DÞi>"¤à“ã„‘÷O—5ê\ÖNÈoÞij—F)§¡=CÅåpÕ_qzºJ$rÈÇw÷䨕8‹Ô´'“žN›ôh>GÞ®Lz¸6éiCËßo&=Ìšô”^œÝogÖ‹Áb}q¬])ýñv¿!U:ްѦ ¾fö=¦Ñ6B>¾U\ø¡2 ž=ù¤›!”Ùès:dò•KcN×D}ÞôÚª’å4÷#h,ü<SÉB4†C~Ý ©š–è×Ó ú3ÕqršþÌ2¦?]CSDvHD®jOE ?;ä%ý™Ðßç5ý™Œ¼¢?OKãü=½¦?šþ|`äý¹•ìÀÏþþΚT£°&³{vIQ×vh ³HôŠÛ“šöTƒÝÉg{:;4`8:äýÂá` u™Æ!\ö{(äÖ©éÃó³;¶m Iî:ˆŠ5¼’!“¯fÄJÈî¯s+y'î¾=#¬˜Nñ¥( Amº–32Ú+¡POÃi›yÿŒg`º"¸ðÝtÈB£ÌøÙÂøYrhù8èÔˆs½ÐÅŒŸ»h[ŒL|µ>´§ÁèpBÞAð 9Ù:²HäcB¦žQT¾$¸Ì¬<#U…NÔÖ}i(HÕçûtz¢ÇÕ³K{déí׳êÙ„¼|v6œ×ÏÎOÈoϾQµ“‹Ÿývñì«vüD«àN;³4ùQ×ͨ³8ÓŸ“¸ž¼×t¯dƒ‘ÉEm»_†#£àNõ½»“ó<e· ÇÞuMãí7B†b¤åv©w¤­‰œùâÿ»Ž$×qm¹¥*I„¤aÏÿ¸o  @ÐtÑ«ÿ°8¥®šf¢ŽËL>½¤œâ×q»~šh–zõÖË7|›·kb”v˜dßš©Úa¥½}ë~P½ŽÀþ~ûÒý°Ö„±|3îäû))Ù|!wö¦ Xþe·;êø¹YYO±—y®×»!/a:Þ¸¸ŸÚxÓ7Ãy}§„[£è„žÝg~Üõ„÷ÉÀ÷mhå²½lù= UØè‘œ‘ŸÏâQ;{m’ÔÓwâ9-:‰‘—ȇ/¼!ɘ¯£>f\”¦Þ½(¿àCêÖj–zÏ#qüû¯cZø…Þp•¢°(“ËQÅó–‘ë‰f²ñôåË>$rûŒÔù»8"/ȹЖNŒsa>­`ä•‘ƒíOØbоÏFˆŠV䆔œ"óZ*9[§x—bzf%ú]˜ne‘ Fã¢LnßÉM1AJXŠÆ\ÓV©]?TM,—j€R!­Ÿz<°AӌEULàÉã»EU Y"Uí*„|ž#^Êx^MÿN7ÓåAw|Z½2K ýý¬fÞžçå]Ðc²‚ÓãkÏìøè}o¦7Ci“4Â0Í“¼#kçĨ‘ó4–9B&Õg°¨fÚôbŸK„¼âq+× Å*e¼r<ò‘¾`¨‘ݼ¯ý²×™¥ƒY9±‰JÕÏÁUÇ# Bº)Å 9õÈϞpgí=ÒפwŽ6×[Ø‹"ä#é‚—® ¾äå¾èï:Ï( ô÷Ï_/‚æÈ^´û|Ž]² OG·Ož–:º± þ$G.|2¸h,h’má³Íf,hÀ¼/{Þß´·­¢…FŠJ6¼ƒ Û3Qk>1«Ùc¥úyÿàãkT:Œ4¥ÄgÏ>1Ý8¯ýãÍ4e„í1¨O,ùÎX^M·…È›<#yéÔ óö‘”Üù燊¥µ8L˜äçç蜾¤©oç¹ïÆ: ?¸ÞÚ ð]oIâ æÕÄyåMûmÛZЊ&q¢ÿÍÞ½A8ùùʶáÒSòs;X"ÀB^Ö­im%?8Izãåì;F^ƒžM‹Y- 3 l=BÞÎ<»aðàß ìÒ(#iD€©,óîöñµ!†Ÿ1ÑMž»yAb›Î“mÛ•þ8º®GHÆt]N8û6æ{·É}Øž=§øìô°‡Z\×þ€ŒÂ˜y黇m_ÔtžËN ä=JÅËœNdšløŠ¢ ¯´ê¬mv®ò™ŒbÚ·“†D#d“ ü;£þà ”ŽÌé×µ,š C±sžýª³U|M¿äYé<3g¥!TŽzMB¦•ÆÜ‹šzl€ð‹7k1凣f¨à"5tY q8ªÓÀ39]×ʹЩç úôc݉uÇ‹‹|‡²T€>B]Šæ¾jkÆoÄF—²Ü1ô™|Q^É_G†u7¬ãÖà·ÿ'-ǺÌxLNª.Jü.¿)#Ðí̦ûC§5çðbï%¥%w“[q¸­÷/†ozßüÒd9:L3›–øZ=1ãJÇNŽ.vÖ3±îñI=Qç+ rµÍC?´¡WB"¡Àɶ•ßqÌæ°ö+°£HB(0ß¾szöF4®j—j ÈßÓõ¹ë3±È/žhrÃq°>ï# :FyMy0•ÚÕ°¶ýï‘·ð:½BP`c¯¶5 l{döA^NöÀj'¿—ï*_Е& ÁJ[ú{¤ƒs}ý;\QJRøã¬uÜX»ÞëóŽñ^!ä‰iº/tÔ7S§umƒW´îÙõla=rªÕ†·Øõ !noìzV^6ø˜YÒ,ƒ@½Yžd»c$Iû­nnÁùW Çg¿§J¡;Y3½?0)ò„ôýl^íC!šŸý—‘8¯Ò3#ÖîüO’11g!.šÜh•ç;>½[ÉC÷ÞT) ÔȳԵÄOé÷rÎ!JU¸IêM‡j:$áò¦3ÍîÐWYÆ×Ò­Õ2Á/%Y”ÙÊš–½šãÍ¿Ô×r–m…(â+𧔥Nìtˆ«òzVsê·ª1âTùÅJÍ,'ØÄˆÚ:ÈDDmòûü2fÀ©Œãåç[¿"qY$‰GÖ‘X¬ƒ"ºí c-'x=xMuý2)SñêòIØ î|ßM¥þDCW‡Äøÿû÷Ÿ IĬ•ZKuV68$ŽÀkd0þõ–æ¶:üÎ, ò¹–«%DŠ…¯½ƒgtIdÛ‚‘À—tZØde’Œ‹›¾_úÖuK+ò­d\ü_[E˃ê¾29Ø¢ƒ2„¼~®_B”q¹ýGýr“y‰23AàYÔm«ôf7Â%_Ü¿é—&§rUy ZÌÔqlkxßšVå¹@È“´ÎØ4 nM¢N$öIƔႫіÐÀjæsÅ$äqx „øÊ ÿÓ²Ûñ¼Ü'gx^†,ÜI„¼~è:N ¨Òäò8ÓFµ¶ÃT(>‘\žhCtb<žm$Tµï•BÈK츖píÓØJ9ħùÄ2H…ùÜ9è|hÞ9CȤ&œ&&½*Ž|j ѱ \ý.«T͆'AÈÚejdŸÃè¬GÞ¡Ó^–>ý4W4ÕUL?/‘ o=3å—O¨¥~œå"j„|ž;MìS²]¿¯ŠqÊ€\?u´¦u´È™ÿŽ]uP:ZäzùÐѲý´¤£E®Ú1ßÿÙ>US ¿3®KÛÿþuoˆë?ëŒ)Ê’ëQ̼]ò­ÌNî|2ÚKCܿɆÀ•¯y‰¡]™»tž«Rnm‡!¯q\Ük´ÛºuSÏû> äíXn2ǤtÖkHQ#×ÛAå7¼Kõ@i]É}Çgü¼]Šªœ˜’,h¯“8Ú”°¼ÏE_‹u=\û9ùk—´¦éð;Ÿçc„øýÌŽzÕÞç ò®Ù¡D€üŒþxyLÛÕ™¤œºw !/ Xèõ˾ÉÅVrÉäLãÉ•  Ú§ÛhmXø^,ÅÏè~p®&Iaú;t’z$ýIi^yÖìÍ\#ä1©9S¿¨å„7ðp„Esí­‡œÓ¾EÈ, ê¿€ƒÉé>-:™›ð1I$,–µß7Ù°tâ% ÜIÑEŒ[¥šn^sÑx$yÚ\’>6Ðzá•:Øšy0¼ª_Ó²tUÛ ßùŸenŒ°~uK‹Ø>ú›B¹ågoúúgý¢l‡çy‰PÎÂQ—Q‡b«0ôŠ –gŽJÇñí¨·HBÕ‡´ß²jù\–“9†fïó v²‰n@4#?)cèë nŠMÕ«\8¬cx°ß¹C›'5Ë…½VöÊ1ò’&_^lCQ¶ìå¦02R6¶·}÷ôý¥N˜DH0N´‚Žû¬ƒ«J® R¿ëèªÿüû?oÛhŽùÒo± «\’|êNGÏ’úI!ñH+`›X>“Ûï ýÁ‚‹¼)–0A@n¿o>q8“7²…â@­Þ®=m 2M¿‚ƒ‰£õïó ÜvæñÙ³O„Mr,äm`>¹öÞÌõ_¿ áÄ,éûÀü‹/°ÏÞÞýØ](dŠl«!jÀ3:Nyøž–q'V¯ª ñi’ƒp¦UZ0"³ê¥Zq¢G&CEd+£šI+Œ¼¦_GÍý¬{©m“=B&~ì®ÖbO”Uë°6Bfh_p…U.L 1K„$HMß…*6 ¢âøwÞñjoɨ±—ÜŠ!qîÏ'²ú˜;[·U?^„|F¤Õ–a–Æš†5d·ùc¡î!Í2²FÁˆK€ºÊŸ¿^6ÔÅSßÒYÈzÍ\ïDc-+UcYaè5­ïzukkj´h1ËëÚ¥¹íÚR¯xÀêvÆÄsYgñ´ñÓ·Åð !á™Ú½¾«~ýÄ‚¡wµ³¹ªfѼÊÃÍz a »˜!Þ]ýñ¨O¤‡b VZJ2h+’Û‘HÆ|ٚ˚Më eÂ=Ö’3_ñ)õwjÆëš¯¦õìbש1öØ¢Ú1òöIp*¡„v{|ž¨Ô븂æ+¹á'#lÅ|,>êô3’èHJð¸Ì¹ÿZOÄ¥Ù{(…'Nr~ª° ™ßtö7LB~…°Ù~üã«_æ!oÉÌ­M—ŠŠm[…™%ß^ÉüÙé&e¥zŒüR7?!–œWg ·É~>TgÌÔªÎd?q^îÛ$ö¾Þ¼–¹;4‰³ßÓ¬ÒV9)¥}\"²¸ƒžÌ²ŠNA)KÈiégöA.›`r›ì‚/Æ Rm¢ TX’zÎXc$íäìú̓ª#ò£5†Rñw^¿XclzÏèúÍcßa"dׯÖùñwBÉÞÈ©yL«?ÏÕñ]JZé&ËKï9Ñöûþ2>~ B&Þ·¥˜1rêyÏšó(=ÔÓ¬‹Š6»¾¤x—’VºóõÓz‹\(ÓÏ¢±,m¥ÿ“¶¨_F 3_)üÎCV òr+V3’3bäå€4mGUl¹yMɽ%w´–R¯ Kw8ûí€4÷3ß52:qzd†jA [5j•b$Ȥrï8ÓÃ%vV[Ç|ðó>MlÞã3J]{þ:Ó{Pg[¿ÇÄ*KZéV  ô ˜bëÆ‚ue¸ó?çPÎF.ÐøÞÙº­]é·±šf¦5†¢t¥ò—¯sËZ§  C¯ØóÎÅ$#c´Z¡~™%­ôhÕÜÑ&ô ¥S íð[3Üž6¿Õ¶§«^'$J4»g½tKݱaç-†Þßå‡õçä‡IFŽjQ^}«íuüÖëõÞ”ƒkáúovŸ[‡xQwÌ]°¦©~“ö«”m×DÊ 6q5—M3!×#]Ïâ#qožÓÕ&ÔŽ‘Ùé$5Ýi“ì!¯|ˆNÄu4±B:í”ÅUçù2è©%Ä·ã¤À²H|;ë&.m„`ZèË.:ÎÝUðmPSðÑ&ä÷˰ß×N.§" 5 ìy!B“¿óó:2þ‘Š5y‰9 +CÎÂù`ì+{„LßÒ[Y+ãÐ,Æ~BÈÛ™›ÜîÜäðÙ³ónÑ`t€à~~ë¥C€„Ü>O»ë}VÆîɾø>눔 I*“ÁÁѾŸ6Ê0{ð4ï¢ ;,Ĥ=òò^=î,I9λBÈë{<âL½L&†·È˜)\%ËÆ#|#ì6äŽaâ»dÏ.æyÃÇ$ï‘˸IÓôÈ{HcÒÌÚó†ƒõ™G>Þu8Ý3ÚÀé‘DæÙq¬‘K<ÖHžÆ­7w:ÖHN;=­~3L”ØyL-Åw¥°Þ•S¿cäG±£‹Ž×ó·N?¤ø&ßÁ…]—læiœÖû™70v?Ö»œ¹’‘£ÑKØ"Š ñH†fVøÙVe{C¯è'^…t:54ó•1§ ØëÕ¦ZJH#÷Ë[Ö†×m;ë¨~ ‰ÿ=µ)þë‘v®kßN{ „S-×óµ{¼aÎ}ÙäýмÝÐŽMæìÐŽÎU$BÞ¢™[xžÕBuîE|vˆÚÜÐŽTÖð\õ#>;‰ýÿ3sÌQ¯!´ÕûžŠ9¸¯ØyïM]wËÈVü;gÞªÌy«bä3ñŸò\hsL6pÕ¶{26ãùÕ®ÿf§Ð‘ˆÂý#=³Š¸…~dжy7Õø>ý^P|e‹N&]˜›¹W-†^aÄÇu’™iš°jåfCo@2D ›M NźÔtÁ·ÿ÷L )§“^s`;@ 4__¥BkE·õöCAr=…' Õqëw‡›õ8SXêŒÁ¬hG}ÆòUà5ëÎô’ÕgèðÛÿã¦ÍàÞäµ/ÍÀ}?­‡×f}C[ôP9 YÝ?ÚVê£1±„Ÿš}5±Ô»(<rÌr.}®««—ü¢ÅÈ ¦e¸¹©zÞ‡bÄyr¿ŸÉ®‡Ú˜`=t.îé|‚EËP›íhU­ êC‰ýV õá7¨Ÿ§öG–GT²çªlç푉é¢cbY‰¼VG×ôbîÏ)zcØØK‚ì IL]lÔ )WB *Î#=°Fô«…,.—VtQø˜W4Hï CvJÍ”ì†`Õò*ôëiCá½ç¯õÕô9>{†&¬0ã¤úUtbí&„$iuÊÅ9É×rŸ¡~þøAvóQÃörœ‚XI mœ„'î˜Å¬§{ 9}jhcU…ŒÇ3YÍz=_òW½ÒÏ',ú~VùÚ­=Bzj€¾ŸU°~ZtH¿ã³géÓtϽåyž÷k¬x%†6À¼ô&Q²Þ楨„¼DF#ÜO¬ëõ¹ƒìÿqI"¿A¨Í¾!ŸÚ©›0òvIc™ &«$å¿1ì…^Ð䆗óz05‰H×´êòj†ÝéV†Çí­êãÆƒ‹­Pú>´°‡>no 7Û¨ú­n¡ùû¸añ"HÝ—²`œKXC7D °g¯r]f¾`dݹ`<8—T”l„$ ˆ#ÇKµ«5Ñ#ï0aUØd¾vgc[S|í`‰HC:k˜¬L?ö¾Êò‰ºŸuè~Ò±Ñ;~@fo}çÚúêØžUúán9B&•ø²öþÏrajmôÒƒ×ľ3t4HÔS]ãcÞ"©ÎzglÅç~3æÛ™%_±·Õ¿“V£C‡äDQ#§,—:¾Ç×~?ÓÞàL‰5o0òÖO#×þ†VTïZk£ðµ?CŽl龕óøÜgÙôݲà;ÿ“B¹v™tˆÃrUßÌýM;@ÿOØu$;Ž+Á+ɃZÎ~&bþ@ ‚Þѧÿ°%j–‘Í'‚$P.3í[?erR;ŽJ×0ô¶Ö3—Ù«f{Ÿ…­)ª· ×Ë·ÛÈ:°u¦{ÝỺ>P8V;eJ­Õ1M†>qÉÓ­I÷2ìáuåÏŸ°5Ûߺì<§9†BêÂ1K2¡*~Ì{üü}äæŒ3ì ÓJÅ\…íñùaFQØÇºÒví÷=Mñ¨+©S]·Ð,Û—jÇÐklqaëxºâ˜¥ûÎñºÞnÕ¢Á&v×±^æe.ñouÖ¥º«÷Vµ´;üÖ‡?JhÐuJUL¸Qü´œu©·­Üm¼L_µµ.µºÞ&iÕM»–µUÙðæð[‰Ÿ'¡…Wžïeš[Ã)þ n :ªMFK0]VYÈÃx[‰eè[óVɘ¦¾ãèH¹±«¦Úi¾Wiz€^#ù÷ÊöË’Ò-/ûÃx•âk[†iöš²¶g@…É#›åjè,6š«-1K1ôñÉ×í½F*|±¿4R…ÖHåy®‘ÚK|ÍûWw'£‘Úãk_ÎÂýšéŠr*)íà¡’ó/×\Ëòvpz¶ŸúLTüœ!ä÷ò £lE½$ù1(3Møº¯îxs£î¨ðƯSw<ôh©"Ð~½c_­o%0xF_Ýñôî£KÉ4Ý3Xùƒ0E ‰u™Ú±á”«"aŠ¿Í_÷Í»uQÇþRͼ#Eæ…¥»TN…|\×6ƒ€÷ý,m›´ŠZ°xy¹‰O¤¤s”à½Chø¯ø×êÜY3˜5—‚¥<¬çý3„E*Ïðu¼ÏTž{¯òÌò‹Ê3÷*Ï3BÞÏT‰Y/ñ5'_œVynòLå¹aTà¿~®òÆ7ß?Tž­ò åé÷O•g•·öøw¾¸²³¸¬íUf¯Bøð~>ïgÄÖ¼XEÛBzù~\Ò¼îªBò]¨x#ïÈ-޼ɹØTp4‹ÿõ¨˜9#MäèôïòñÞm±_7„†fUlޝ˜!o¬ )²]fÀÄ{CùIÑcú Zï×OBTš"A—ÁÇ=Éjê-^áÞ;9‰’* »wì´ø—u\°àRv]'çÂK‘ËåG“‰ë&GÈM&O“vÈûië†òˆµ•LjÑ:ÂyÔ]È!ldÈ!$ö%üFä`^BÍ!±2‚k†õ¢*8õDyÿ¢Œ0ai2r‰öÏ¿ì3rÁ;kÔëÉ oíC.s)%“S7/ —™¤ÑÙD«ßYŽ3Ü;.ùy “„Om+Á\^§Öê­W‰†7@"±×á_¹•7™Ë¼Qµ‹)È!#ª=aÍ5ǼÑêŽù8s„la#ÅýEgY;À6=BÞÎ £øîä’üW„Ö&‰ äÐpNo‡sVŸØ“ˆÅi¸¤¡ ®B‹û›ìU¹Ãh¯CÞÏ]àwÆrÇÒqq˜Bþpqð',¹b‹ÈjnÊ%¬æÈo«99/MƒçVsag¸ÞP¹ÓŽ [ë>ݵë£õ¼cífÄ!oç €I"÷µª{úy?U«v> ,np¬±ß‘d}[{çI,äú8Æ3¶…*ööƒyóåýÜmä­©¼c¹máÞŸ'RošøK½‘È”î‹ÔË8ÇÈS7-ÞŒ'nbØ™¨òTÀm>"__ÄëüÁ½¿~Š×ev†È<‹×õV¼N†7äuvﯛg„<¿wÉñïüvïÜÜ;”eòupC±^Û”öÁ©–\ɧÚl_ ýL®§jÔ3vï ×äÓО†¬ÞšJå»pïGg'®¿Í‰7,/R„¼a×ÛÚÙÔç>gÓ‚wO¢Î@òÊ´ùÀÂs½îÔvÃìêÜâéÞîuϯÊûC¬¼On—ŸÊûKØ?c“¿OºÅÂ:ŸËÛõ ÿ~Dúè—Üp;ßPÑí¶+Ö†µ~”šÜnÂ}AMÆ@ŽDDw@ú–ÉÐtÓTcdìTÄJ§.ÁiÙðÞ¥ˆènãyǶ6^ÆC:ð_ó‰––b¤"°VóI‡!cº³eÁ±™3> sÿz˜Ì=hœ×±4ãø¯'a´„û¦yUÁ|‘*x½²r½ÇYˆå€t­÷?ÖÈÙ6žÕͯMJY{€ÚA8«¼ä†mT–íÚ ßÓõæ¡™­àš™Þ¾ËÕ©£ƒÞ}Îé šCa¡ ;@ß­Ä&*dxI¿¤û•O÷c¹=þƒÁŸrÄôÿÊ`{? p GÆpŸŠ¿:l ÓóTËÖL£ÉîèuÜðœ¥zB…(ç¶ÆÈîícnÅskäö:gå›ÂJ?íÞT¨<…—$Ásß:³½µÓª]9 ïÈ;â\ÿk%þœº¹ÔIôˆIàï§¹ùFË¡šÂï<Úä.°Ý2¾òª…;¹_…ÀʽK¼É†©Ï#ìØÅØÔ÷Û)oùž 8fï—S !¸l$÷ ’ÓÉ€2ò©®2uK B†îRQ–nî{Ê)O³ŒcäË‹äè ÏuÁ¦v<ÂÀ{èz gg`Ù—ê“oz¹@±Ø!“3»09Fî׃tž?§¬¥ÅÒçaå)oî9Ú% Õ%7p  ÙŒû<a•"ý_1ãhº(’ftcö~C¡î*Xý“"× UQúò³CšPè_(d¾P?qõ³:_F„4Ű?™9jÇSaË´OÍ&„$_‹"LÒ¨Ø)x=o5¢U³)ÜûãLOf™U0ôdH¤3 þ±¢š^£FËŸLÑÊ?> n*g‰²,å¾{v2¹?O'gfdŠçÝ3£·›~žÃ›üúe*ª'àšäÄ’Oí ”F`rOΑ*KPÈ!£¹"ws;uÛr¶‹Ã5ï¡ÌS9§RØÖb£(s¨…-\A9ª®Ê¹çþ>SÊ×C 2:;7ù¨­^6Ø?‘ÈÈÌÌVNZ]s\I0>pj®çvì|‘žÛYugAHHÑlÙÌÊ»é±Î´ê{„Œ U½A.c]§b†Æ;M“È ÌMøØHH—¸²t¯€½Nb³²ÕÓ’¥M÷7ÙNÙî=ì6aÒÞM¹L˘ï£:äí³åÒ›–‹,à”9å;›– kØŒ‘·³ó=hÕ“s;­™ÚI¹!oÞø55ÃUv¦tèš¹£aå#†ÏÐNkúcäYd÷‰< ì´ó+FÚ¶ƒ™q#u.†zh«Q,ù<+T÷0?Oí—]q3B f¤“oeØö+4=ü^·÷YxCæÞe…‹CZžÓ:íCqX½Ôpí&3®Þ¨-/òš]•+Þ´Y¾VYSÊ!Ÿ¡|â ƒtkHÖ”B¾‚µPéýâ›´‘ó6úv´C’PBP?ÓqÔShмn2Ájñ6Ë9ÇjÇëùö£ ÔxÍ™×8ò¦¨¶lÁ+¤4÷8q1Ò±®0ô  ÚëÛvo<¿ÄCm¨óxKQ¡EÊ÷šŠCm\kxMN2Bë Š9Ýç?QËõþŸ$÷3)¼˜Ô«7ÍÕá¶žŸíSSä‘ M03µe§,ú|(³qëá¢o¼ßÆÖÊèÏ´]±TtÆH…ºIr–·Z†#ìáïC)´òöò+SïÞ>ˆ!ÁpÙJ©òøŒµ !cQÇœ¹X½âÛ^Ò#ä ö‡Ü7U¨¨‡9ÃHÆgÑN’©  ˜¥:dò=ûPùT8¿bk¼/†w3Þdg ½´}š6© àš·/zhv6~ç»d…×"Ï@žZZв;zÞNü¬§ÖÜBùêyC¹$*ÿ#çòü´'¶< ÍFa¢ªüõ1Ú6oæb`u&æ CÉ6âæú‰)Ç6.§u©–P„ޏ¹FíÊÌÛby?›.@~Îõ9zÍ¢Þ¹]ë[ äÍŸ ™›?Tï|Ãúª©Ÿô&Gû…ábT"᯿N´ËŒa(¡Mñ$?TTÐZçñÀÕ²¶`°NžGx«eÄ‚€íŒÑ©¤‡ Œaý²Z7N¥g‚²N“óÚì¸*3o@ÿÐ!ŸŠŽº¸›ï2w-òO;®3Fô öº#ç¦Çml¹„øó}2=.ûz’é}›ïéñÂÉ«(´éaB•Df~zܪj°Y–eÚô ¾æÅ–¦y«ˆiWÍ~zœDfÇéqNwµç„w>ì`Ÿœ…Es<òu9å,Ì–³° ä‰!#*G,Î Cms4®bÆ.[|äðúàUÙQBÆÕf²¦rôú]$bqFä“Kê~‚úo BÞbM\GžN^Ž´ó|%XœûÿöÿÙóçõTÇ8©”¿BHý4…¯ÉØøŠ÷¼Y'õ¬Z„ÔOSXñ^}Â[dß.…Ê+0òeQ,¤î½Wˆqi‡$ñ*¹ªHZm³Z¥îè²9=á_;•¾×]Yx?#W@¿JÎŒR­R;Ñ.¬ü#¬ÒßÿúUÒ'¬Z¥nUûÝŽx•*X¥RŸ´iWÉ™QÚàR­Ò°t“\ñE«dçBõ* r*ãUŠgÂÿ²»¢ ˜ô®¨V”›ü<•«³Ø´:kP?#AÏ#˜¥ªkÊûl‡¼GÚï CïCC§ #§œÜ°{¿þcø%œ°ˆiûÅ©×L°® ð»²a3Xù÷¡ÖQ¹1[ÞðA²5Ï;„„ÓP7„+'m-›Iæìó¯ ®æd‘¼”Þ’ºMBËëõ>ᕌí¶a¯ò!ŸÔnŸÕ×ÔÃv2¼É°º ÛÊ ªô2‡¢)2|Gä̼›‡‚ñllSÙvtÑJŠøõ$ד:i\Ç!òáŒh$Ð!OF+•}@N4~%- ?%¸9öý¶µ@ÈW´:1yÓ.K*;‘G¿ÎÑKE¿ãØ6™|q»È­xp»pÈ÷W³ un/0ÂæWþ¨v^^åïY±ñ©ŸZ|óXMÄ2óZ1¶¼iÅOÉ5ǰÙE«vP>4ýáÜ#v‡ Û’ •ËÍs‰¡Núâ'¼a*wbSX&É4!,œÙ[èVõÑXƒ¾ðHeòš‰lkW%1¡6ãâ-mé’Š¾ÄÏʱ@ ­²bh3gƒl·x©>`®y½ï{3w]ßþKÔÇeµ›Þj½àÜò~¥SXc"_„HK"ª·“3©á2+Ò4݇´GÈ{H‘ý·….*Q-r„°,s{®väÜšºëÛ!ŸðþeîQ‰o]—ê•Ú:„|¹ 9LŒšÌ·C!iBó.ÂÁHNWi2ò0a×!ç‹@Ø÷ ë#j÷©KÛ¢Iã4ÓÈû×4›Væáù}šM?÷èÞß'mv'JæÉå8‰â¶|µž{³2 ±¬…ѧXÛŒOçÞdDóµÌG´5BWˆÐ‘˜æëøl³"S©Â­R5@ŒkŽomûeÃ0H/ÞL"š¯Gº $…T;C³á¿ŽÒY·/-jA·i£!ÉIx+ç 3É ÂØhsœkØ’ãž\¸Ù-«Mdn`K>J¯±ð¥£ f"ò.1P{1ˆÈ»Ÿ#Ú—œ@Þý"Wƒ©Ðˆ¼‹‹R­+J…k ]Ž a"÷%ƒó(yWLFêVþÈ_òÁµJÖYòJbIržX4*±˜ ±ˆ €-µyÏœ^r:ÙÒ!Ï ë@†vÈ„uøÞ“äØüA÷ÞG_ñ™¤cƒú:æ0u÷¾œÛŒÝ*ADÞ×_¶B€™y_Ùè¸#ï0»/-êƒ/²Õ#c#ío-…pGÅ]Vº|•€õe gÜûñ±Jqé®§P„~?O%"tɶ§ #o¡ çÛYÓÏNÄÖL…ô;ÿóIIºkŽ›ÌÇeïº!I’¬œa.hÎÛeö†NHð¦8aƾFµöÃ.Ê!Mš(L#÷B-zVHïìWþ…Ô…Õ“7Öò¥Ì¼n•‡^c¨…^ש¨Ä¾¤xí¯ßˆš,ª{„‡^U›ôq ÈÛ9EùY%1á糓F„vÉåqú) =¹aXryþÒÉÓŸçŒß湸™çZ%üÎ×Ù¤'SÁ¢¨ø â±}Œ¥1[ë‹jêòöµÎ§“ÐòOb‹ÅÃdM¯¶‘­/óAWi¦ÏE¼žÇ:_áh'}S.KMaÞ0¹\rk¸`ædÝv‡7yÿ´êµ½¬ :iÉ5Vvþcí5mwn˜×Aå(ðŒ®çý-hÈ$Éõú©ÐÏ,m¯G*PÉõvÚsãH1¹þpГ50‘š\ÈZÓÌEÚ²ÀXЮm wôDÊÎÁ™­oFÝ%Å$¢ÝÁÜûk:‡J>Ž×<£|«; ëŽ$õMta”ñi+)mò†ÒXÛg^Æ*íÕv*òþÉ{õoŒ|Äå5;©¤•†,m|o09*bdQ YÆÈW.:¡—UŒËÜd%ß’‘Ñ6ÉTÛíý²ùÔ8‰zÚ½Yd­.º3¶"ä&ªrïÄ»jÙ˜ù®W*þ8ÕÖnb«†’sŽ—)X€jFAm^Q-‡r}Æ$"TD²‘ä¡mÍÒ~kñO½BOG˱¸Ú~Ûn4­æíðxþÊ™R4UÛv^JÐCŸŸP&TíÖzå}ÅÒ1ÖU«Ì˜D©ÄPr„ÖÌBû¥L1ôX3¶Â)"]÷©Ç/€SÄÑû޲6—Uíe_ |ÕÛ%rÅpÖ^V¼è°áu½]c¯ ût([!rü^YEœ¿œ¤›î¯yQíåÒP_IñPÐAÓÒ1¶ê§¼Ú5«ÇÐÇÉ«Â6ŠûǨE,í&ƒ" ÿçCUñŒiæNID FfEõ A»¼æyÿcsDà’@9ŠÀõšªÓæíŽxÄÞŽ÷’ :/Û„àúN¡»Â'ɳj«3¸£ç'ëÌ:¥iQ{¹Ö#FßO·õ¬T9Ÿ¨ÔFpàF†œ¬ÅPY8ÓÔv¯d›2$Rèš0³-3ŽÏSk œI"êÏWkŠ\6yóÍyBè”A¤u¹ÕS×$X,<±p1Wj¡Bx#G¾Ÿkj*Ë©ÌáÞ”°Xb‡eÔ ¦¨°ñ%¨¥ièY٬ـãêq®j^¹JÙÒ~Ñ4>„ŒŽ'Ó&Õ´"í3ºŠ…!äRšÑõml >W"ÿóåë]©Q…eîŽÔϬ[Œ$áνòêwÒ…PCsÈ$ßþdE—j\÷!ßù¯ ¶«ÔŒ*ló¯üål K0ȬnïOÍV-jÏéòöe?ÃÓøÉ-š7°ÈÊ&1Þ—ÿ'ìÊ–]Å‘à/Ãc¿Ï˜þ± !¶¸_?ZK*lŸéèî§ :Õ’•Éæié0òñAIráê W1ö‚Ïðñ^r†_3ëp d‰?95E­tz.*$ö¿Í|Û£ï©dTV N™%?Þ~ âO=ßyðNÉ,{à$sÌzV„Èj;0òЧö°§fåÙ"E¯þ š~µ›'¥:Ù¾ó !S(gè¹r{zõ‚ )·ùz×ÖìP¸v–Ü~×ÞwyúR¸CÞ¿M3…ÒmÍ|}ÜŸ2$ù}žpÈEN¬‘~©)¢qqœgEz„LÞ¹z'«t~c&IÂþô;ÙîyÆ[&‹°ç“ä·ý9¨ Нž~ËÒÕÖƒgüš¥S(Jf±cìŸØibëé¶N²ëùüPàöSW‚…©«,žºú×TgÜ̬þÜ#mØŸáðøó7öÎXÕ Év<.È_˜±áû•+fÒI„ü… Çaò+3V cà«eÆÒp %3Öë?Ûgoç­˜¤„jBòÆío,ÃGEÕ*Ãì刑w4`#[£ýÞóM"d?{í[‰ÛZ4T»’ˆÛÿ¯™”qH±oDLíþFë¾!î5âý¼Ñõå‚i<-â¼’ú™­ãXB^—äAôËÅêš žýÜŸJrH“üýcf'|§àtß•-–™¿7`´·)9B&{ü|¬rºICýmòoq4ïfÜ"÷§ó<²„¯M˜#û(òׇ¯âã[UÁãéïìñø¥n«ç¡FðÀA­uÓ23ȼê#³'mdWK×Àvù|Ï8T|W¡‘ÎŒÉèZÆÊ†žt£@Èä“ä?Ê”=þÍxºÖÊÕ\Õ3oÁ2{DB#iÕ=;"‹PA‹=.?y°m"{¼~õ`Ý€Ö”Å3_o¬¢_¨7…™/Oïh+Oï(yäÁš…™¯O¬g˜àËÂÌ×§*§X¢'ÊÇ;È­ Ú·'“Z üû\ƒ!‚À^Šgd>}ç+ˆ£™Oßùí¸ ¿Rpèï{On¢¿Ñó~™xò²ºr:ï aðìIT·ý'âÝé™S´ _‘E.×4ò´i$<ÑãËonÍVu'Èìùøe^ÀÈú½ô|~¡õxR¼qaFæ½GuÙKéç#WÙ–uOÓ¸(½u^ šL6×›OfžÙÒÉð¨‰ªØ’íØ™ëùóéäó µõxFÆD¶—§ÃO¡e¢¶ ÿæϳ[¿Juiõý„îË3¬LTi#+¶ÀžOì1ÍfõŸGÚ Â&œ«$êm¯ÏàÍÒûÿñwyÿîïoGz|(ìÕ]9R_}¨ÄåêïN F>CQ õnJjåIA€væÁצò"@:A¡£š”C¾¾»K@˜ÞQ²Mœy¹‘äëPñ_=w— rAî~åÞ„´àBl/á¡Xn˜º¦H_¹YeSb[Wm@íñP7|c¶½ßxýÖ÷¤/.å¼B‘Ïjuxœ iìz‘](»ŽÐÐO#x‰´U}q‡Æ+Üd±s r©ÊB½0E%„¼Çš=Πj"Dý/úë§WyÍÆ~Õ¿5Ÿz Ÿ9ä#êº2,ï÷’ „ŒB>Ã>©ÍüúÉeÓŒ]I2¼I¤;{uzNC7â«¿@ ÇîgÓ}jÕ’¡ß¦Q—ÐVœô­ä¤™„hñ}æï~)Öí­B]†æÃ¬7š[yí·6·¢å&Å+¿Œ‹Ú1ñQ"d‚žÈ&½ÇBÊ%êàÇNŒ6ó³M·®šÔ±ó øJéµÖR9‡¢a‘#'L)9äý2«m«›=Û{9•™DýÙÆk·Tš»ÛyÍ ‡|Ä/¨Íø7º¶°½À¿ùÑÌÚûo”èBý¾K„LãñG;ìÈ Õ §!_Æ(A={­ósõ‘a—ûÒì™yK…Ê8!꥗*ÀÈQ©,Í"O¼þ©óì…úB„g5!7ùÓµÎ×…ì*bTq8BÞÒ$çz £ßTÏ ÈT´Ÿ¯ûê»ÜX³7Ë‚‘ Ò|ï„d;+×)r—ÿ×ÅË%9«,šô]"$¬¼©*Û±ªªb)§rGÈ—÷Ðç¯801Š¢€þm 5!ã;dèå6lëT(2 Ä˱[æ_ÿ±7Bð¢ª8Ÿ8<{ä–iŸˆ6°ò[+Îño&‘еBðLë"óâ„o]ä– "¤Ôj º÷ÍÔÂÕc÷0Ç1Ÿ0Þ·í4s †f/좬E±WýèW>š t’²n Y[Ô^ª0!ãg¯­:•k··¤Xg„LÞ‘¢DÑ~$ùˆÜYœÈGr4*éßòùŽTò©¶ÝT™FÖ(ÖVs'VNùŠíNl/å8f•,´%Ä0Aèv]ÕºSfR *ÕN:!s@ê Ô¶÷¥’h#o?`¡â2ÚÉn­·êláCM¾Éä2Aލï¯}ê»fè+2³¸ˆ±Zñ|g³×ES³\–ØcÃ`ž½_{9Yd¯ß4+ÕÇŽB|ñºø‹×mgÔÄ47rX¸ì§!¿hVÒ³‡1¦,Œ[‡Ô=ѲÌ}Ég¨I½^×zG¨rÝ΀“ó•ýR7<újƒoí+û¥nHµül_ÆÂµ¥ÂÊg¿Õ ÅB%¾úÓ×;̲U(Ð\Ã(8±û£oÛøâh·rßÈü¢Á¬Œ:CUÛ€Iÿæ6Šªa0Ë 5iÝNM®=9h3nGÈÔÌô»ÉiR=Ý ä‚×Uô¸uôvõ]líîŽ3 –~\`à›6 "í¯XÙÇS5GoY h¬8dÇAnŒiZ†ƒÈõÀ¿™dÝÚe–Mç…HÙ­|4¯Z¹÷}•Ë$I)†Ë)ªÕÛ¡M]«¹”|iðõo÷˜aYû«$²” ŒêÙ“¨=bXÕÑÉã`첦·`'ZK8³¨„ëÊË <#hW›þœ‚êŸdÇeÒj=Þé‡z»×tè ²§*©¡ízÎh%ÅU»­+ÅPÈ £± yãÀ% ÞnºXO#”³ùS¥–@E×—Å‘ªþ£Ùn¯ªÃ–œ|#=^¬{äQl Pm7/‚4¢!ìÄP¤)׸1-•©ªÏä6ñãël߀Í[v e§ìMö;Ò¡íO:´YìÓŠòjnòjF|õLJ´ÚèРC›E>­Çÿ‹Ôe‡žûtA†ÎN u'+ •ƒÁÕoï¶]n8°o­ÛÊòþe=Wµž!¯!‰ì2zjÿ&ôR]†Iþw­9^·ùŒ†k¯§WÓÖžp6Fc™^ßÕóÂŹm …NY¡_)©–½`#_A¬µ! Z¥INBl#Ff_•ŸC·= R~ÖoGÈû_ õ]òÌ¢<6Ì·Ö™=Ó’Ò}ç;äUðB'¶ã<öÓ$_A˰q–éäšÓ°:γ-ÉÆV„Œ<5hk‰àkm¯¿Ñ™Dó'NxNKus±Ö-B>ɱíM‹¡[Žù\É!Ÿ~¤D+9Ït•ÚnÝÞl3BFUcç7Ù CgTÙŽ¶Þ¤¢ =So5 ¥ŸUN»s¼JYœÓ¹‰&9JÉxsÀ}&ïþæ¦ê@›µU[X¾õ+§;=ÏK;í{ÙbdÆð -í„~J¾öÝŒXéÑ"·r«§}ÝÏ!qÞÔ畨z¿`‡ŒüÍý8Ǽœe)UÜ däoîÂdu¾ÏŒGÓ`dÔ*^(dÅÚ£œzŒÌcý+§jÎ ‘û¼-+^ùŸˆ|æfÔ!£Þ=V‹CoÀX÷H'FuÉ¢ØñÓ»i®¿FÌÚÕ0V.EÃ14ñ£Dx–ףЭ 6ÉCPêÔœ s+ÄÖ¨½·cèó²KµÁ²¯j—–ý‚¡);õß¼ÍÍ(ªz¡€ê¡¯¨ØiZºr®ÇaÕ–úY¨Yh9EÐÇ›‚íkU=iû©9&¸þó­”e‡Ïc9i7 /žGãåÿl[ËöÊ ÙXòð‰x^Æb[g³ËíñÍ— !ÑÅ’ %f#[[´ ßç3pÖ½R;ä°+2MܧLSçm«1òSˆíonë(Ʋ¯/ÏžÅTg;ˤ©ÎóÖo'GHT±4ÚUŠŽI>o¯üHÌæTó}—s¬I…¡7 Ú˜àÅhȘàå,v¼¢®•þçï¿.zÑÅMôÂúC]±÷pÌæWçíìGJWüü¶”¥å÷4Ôi²*輎åeùoÏØ‹Ï½ýR}]öT5†ê?ÕŸÿj±ŠÊM„Ï[½,„@ á¡úoõg×jEåPmÆmÛÃ{úŒ†}älþ™ëS²™^Ö5÷{Ú”|mAaÔœ}Áà•ŽÚþ®èjÃÜ)u¶È2r[«]ÂÆu9CÔ@ŸÊÒ7·µÚÕÜJºT*(ò“SlCÆZ täùŒ7•W›­Eîóõâ6I¹€>Mþ“}«àhÌ=ÿÉs?hXÏüë3 á¯~ûÞGOyzªh~ûœ°™n¾Î“Af7>‹U´‘X…C†ö–Ý!æPR¹š€0˜ßð¬,|{kå‚ =e÷èK Ø=cL@›Ø!“¯žžÃW|C ho9ä©ô¹««§%³ÄWOc›7gÕSîs[„bÉ„˜–.p‡Ô>Z¦öGH7òg-CK]ÚrùÑÕZWwŒeBÌ}¶µ‡ÐJ Ó÷y¿ÉŒ—¨/|ä‘LÈã%­bÉ2ùf¼$®ÈÇã%mÉŒ‘Ï/ÆK[;÷ø>Sð°È¶sHÙ^žýõÕÝÊ—9r}½¸{Û ò«j¬­<)¹üæaÃ{@&HÊ´jÛ(Ro»Šey÷ëI|%I7`ö^…'þÍåKaÔm!º'ßEçµÿ;Ýó;&cëˆF 属±`1´ÆZÇõ;c¾„—ߟ¿S8@È>¿§¿Oøšß_¿O)>"<\­G|õAM£ªÝÀ¾¾×…,*$ÀÐ4„‚F*Aý·‰zà;—^Ö[Tt4ûÙÐ i»Mãh<4‹gW¬ˆÓÖ¦wo0Ô*Jêh°¨½7'[È2¼§lb“¥ªq3pL.l bÄ+p¿ÅånKêUöZ.{ßà½je‰œ‡žúÕm|¹·ESbhê¨k7¹´vdà‡ñÂЂÚI4 å èþ{hLð¬m_Ý«hö¶ŸðŸàØÂ–Fe´¶sYvà*{è+‹õ°’çÐNËÒ\ Y¨ãSÇ‹ÕY©°°™.‹•ÇÂL•£gËFµdx$?Ú¸MÈQu¤eÅåcu ÕÔÚ27;>7s·íœã&¹À§U¥2ÛÐÃI¾–3… ¤<ùÖ6çq_(¹}WbDZy¬Øá“F{ø-LS2A;GŠn–Á…›Z\Ò#ƒrƒEêM­Ò•¯ƒ)|)vX΋·È˜Û…ðƒu˜&QÃÐ6ä½®èœôDŠ ¶ÖXÓ Z«%º"SÄÙmW°J[Zæ»Ðyòø?>?j'Ï«¡U‰ÑG_{Öó ¥´$v½3S9•-ùYq>C™<£âË'÷ž#Aw‡Ô–f$áZý€#%y"¶6BNd«eW"d rhæ¯î”Óv¦NŸ?Ñ볤¿9îK¿í¥^=‰÷ü 3›ÿGØ•,¹ŠkÁ_ªÂ`›eï»#ú}³@€Ä ¸_ÿ4Kƒ»¢–ØÈ !O¦–4R9ûR€L>Ÿ5A£ŠÓ"arÊkìñy+1f½ÿô÷iƪiLh¨ôW¦ªZ}©•8vŒ Qnrƒ Ï€ŒUì‰Òq•>Z7€L™‚µ @Æí¼%òw‡ß3ƒ­š(®Ô21þ#÷ø¦ Ó‘ºÄêÐñ{¡ò Kyú{” VðÏ#7i7UêJÒâXgC;d5 L£ÁjË®ñÇÊå“L—a ž§'ÉtÏû¨í¸IHÆ|Qƒ°†pêÕ\-òqÉÚ+zDÛ,2õ­°ÆÄ•áa¸ ë·Â›ß1D,²ò)Väç|.ÈÔú`¡T‘f€e¦u‰[SîT3>ÅŠ•EÀÉ¥Šn¦!iŒ”E.Ì> eìûÔ†óô qq  Se…Å'éëK9¾¹›? OÎφë¤ß£j(NëpïïS‘ÈžT1«dGô»¿ï4®™Ö¸ŽžÏ÷§ªŠÊaGYÜMtZd¬ªb9nM½)îkë›éûSPѤÖL £’ÇÒ z÷þó—&i;1Œ–}©ŠjÈëÝ[)ß,áwÏïí äÂÿ=OïI‹BYÌ„ßøôB‹™CYÌ„çh˜¦.²OrÇê–Œå;3š¨ô“ýÞê…èç3ìŠÙï½…|鸟6ɳ/jØÚõ.Üû$Öú}·óe¬aíØ—.±ÎRXRi:ë¤VT4˰“ ½Ë½‘5Yj0ßÇ¥ÈGàŠv¶÷©Ê4}¹5>Ï :Qi Ö½XWQS€L"Ó« ¥®É±<µá5±ó›õ­‘HÊ…à S?[×øB‰(Ž£Pø¼Ö×¢•ÈŽb˜'€|±õR«eNå9ƒ3YZ×*ï:~Í šÔ:÷Teö]n¥d?J¸JÆíª™n½d Öø Å:À•ÿ¹p:A 8äÙóÆéD÷#§“<{Þ8¨t"v:±Hà$ô¶N[×Mußyö:‘ìÙ¡„ž; =ç‘™²wçs숡;öÁMZä#–o¶â[ײ½+) &éˆ~ #9Å¡Èì^ç9<ô¯à«ôÏ¿€Â´ÕóuŸþº—ná5ß®7…\È󨇹È<–X6s+ÍÐ ŒToáÊÿMÃÆúÚ¬8:ì>4ˆ!·V‡N­(?”¿*\{Cv2™¼nTªø­u§ÔÀ)„>¢áÎÔh±öR$ƒwe¤«ƒ‘†aä}7aÞ»W®VéGÕ:Æahƃt¼:ÝÖ3@A+2Åx¨RÆ ª«ÃZ¶.8c¤gã¡ïkc¹{UŸ(ýThj1Õ:¸rV–èÑY=n²‰q˜ÖªÈ$Vy°„†·µÁÏ#7mUÈ5,÷éÅ<á ‹æö\KĪáBTû„ 2sHK6QÉQï}=L"ŸÑäœÞ؆6*ú ~ÏWÔþµšWk¹ S4‹d‘AB·Vî»ùt¶­2Æâ™ƒOïœ:k=µã½çÀ¡Ä‚:^ß7‘±&‚Ó˜àu‰I»ûxýùsjJ˜·T!—®ÝæÏŸ Å–ÞÒgˆè'l‘t °DÂ1Œd¤Øbà EŠa=Ùf´äËo¤•#.RBˆ\€¦†ßóÔÒ³*¾=ÅÅîôè,28|†êÙŒËv#!º}FF;ÿêNGc™ t©É€È\À5Ô¿z\ÏÚ­(úŽÀûÈúBõ)ö÷àÂ%°wKé^ºçïwÆP;©ëàɶʃ+So‡|€dɈõïÌŽ ¥ ÈÄðþߨÆZÈb¡äË9Y?9äúf´e¬ Èô,3aUõçN& ó–dÄôAMg¯YȤ»å^óq3:´°ÙwªŸÙWÿÈ%°@ŸÏnmcv*rT õÉR$U»µÖ?’"xÍ{ÿȺER5šÃâEtW6 åk¸&d¢äÀzÅIª} »üѦç•+›r¶L“¼¦12Q"*r³štxŠf²¹–O9S™ÍóЊäZ.Xcxàá{¾£R—J)5­X—†"C¾úUÊ¡ª»¡ jžL.v„çç_¬ƒL–ü½G²ª¸lXÆâH±káû‘pÉYYÁùÄëò×Éš¥±§¢«èª5žéóŠ??ŒéY߈L¯¥2;ù»Ÿ>=»‘Ê,7rB>ÝXŠ}C °”û$à½1£ÃøXî§²‹jåùö¼˜Ú Éx¡ö²ñ¿»Aæ—{(õºÿy9K.jt&Hæ‘pÅIäYµ „üáý§§7å]ÝØx`å¼Ò›Vn*Ø›6å±£0yV­†ðì9k¯ô¦U0«B°š¯‚×¼œY±ÉgùbÓ+ýH{½Ûm¼bˈ/G²Ÿ^¤J,3¬Rvc†¤Ä¨e­ä±—^í'ÖØëTXײ«y(ÅÙaögGä|lÅøºÞ–f„ŒÂë•Cdl?† kLïKÊ&دçë‹°9ߣá±Hl°êxFªh»„ 0íPÈÀw6EÛm8!p9ÄŠ°f+9@>ÎÁ*2A Þê°òoèö];.˜.+=ÙŘù*®„ òé„ã$Ò†µ¸oš¡òtGÁ©W}ÍÆ CÕ2ùœæÞÅ6±Có‰Ý¶Ž#Pxêò¯œµˆW \pÖÔ˜&DÞrÖ ¼@dvÃðR^ãî{Æ2— /¿F2× /¾„«˜!fx„SkP3§"cÂ<–,¸2&<<Ûúý{*ŠEÃzžãÝs“ßpÏæg:ê®ãxƒÈhÿt'Ws0A;6ûVAìÐü?%ë„â×eÃR-a=#QbÛô¦í¤n¨ìòvØ™ûêü}ßôÔ™|>ó:=óïçwFgîýùý™-áhÿò™?#ïŸùC@düÌÛ«ÌJ*mŮϗ~Û¾*õ~}ðÇg'ïhá©{Vµëæ‰Y=y S "ee–4ìC™y$/w»ˆo@>/}Á»ƒ_p‹|Åfr­ñõa¨“OÖTÂO£—ö0T™”¨ p@¾/Ü”­)†ü§»gÌEþfL²²óò™ï™XGŸ›¾#»ÝT1ƒþÚeåqÝ;â¶™¼Þlt·`™nú6ÿÈÉÿîÑ€ÿ•7˜ Y2ì!‘mŠy‹ûcÝê~ÈäÂñ 3àø•ƒÿØñk‘!ò2,ÞXÇ"ÓO-ùÌã‚ãpjçp<¶pvyЦ,¶q«šaªrì°|’|y/|¸S›ýs8f‚ 9(üt_‰-!B¾ª’?N2¦ÆwªGsKF,w»‚dì&e©j5g¢W&uðÓ_®}« Í ÊÖµ˜po@k‘館ür2ÓNý-÷ã±WÒ ‚#Ï~Ìálfáe±ðVÈ]v¦~63–VÐR·Žª²NÅ„å ID”±<É• ¢b¬ «”}”+ãP„)ÈAü*‘Ù}Èà÷ >sºnŠ¥*¼ØV¿çë6Vˆ|߉A×$¼›ÑlæUT¹œîý7W5íPmK#S Xy4›y%HÌ—Ó:ýzK<£„`¶‘¢ØÞ…/šÍ´y\ &“)ˆù凉‚ÑïÕ›¨ÖïE^¯0ÏODfU0J6¹6b,F€LâB`c\9¢˜Èý^ó¶[+w«úƒk³ËÃ"Ã*y…mt0ÖÉ`@™E¥#Ç%FŒ(Ó3dB¡äççç~=ê wÈßS æø~tÞfŒ¼µC&'VÒ…XÑR"“¯Š–¾°êÉç+¢4Ep7¸çN"Oª ^/]†C¤—îÉ•^:­–ñ@#D>®õÒpÐKwÈôB±/±b¹CfŸziƒ“!çù¼’FZ~Ï×ç‹lM¯ùŽ- ïK•!繟·Þ!Óÿp„§þÞ³sñ»±Â‚\>¡—Üßûó‹Ç ‘?Xønu?™ÔbNÈ!IWŠ&l_<òuÏ›•'q©¹D¾?C!ÜÅÊU™Ÿµv×Ñ–y”º†ÈÈUÉì j(°›Še'¤Ù@âŽ/“ ýG(@zþ,‘iwÆ™…­±oœBÊpÀ%^ùüM¤p41ùùý¹MÄ È䣉Ž&:ä·ÑD _Fýòûs3šˆáh¢C>/ ÕJ("¬Òïï©•Ñ„qÇCžÉÎAN"“OÛYÛm;BkA9@žF|B¾Döã( zskèÊåë^NØ¿q¿ ð勤«1«89Ø‘Yˆœ¯‘L%׊¨¹~€|Â)wML'†@¾ÀˆbÛF»âÀðšïÈ&Õé•™,‘ïÒ‘ùMj.÷zZùŸ›Ü\½H'èïMr.‘âM.»X‡¦¨ù%½-Óó‹÷ÒuÈ$¦ãšƒ[™tÒ[é{‰L?Ã›Ö 4‚zê¬C&·ý%,Tv!¢©‰Re‡ÛY8£y‰|ž²^5)¥i.—sG4üL‘‰œnw–´ŒË‰e±Š ‘t–Mø%riµJ@¦ñ<›™èRólýˆ&+-îêa>¬>Eo<*3IÞŽý¿ç 5? S‰\$rÈW¼J¦m¬ViœÅ:ÏùºZ%}È U]ìÈ$Ü»<Ã¥U¾µÛ…ôËŽ1 S_}7a˜9Ž÷}ÈlñÄ8á±Dhæš01~IÅÂBÑÄø•Qjqø{óÕgSS,H8’’VLkç¼¥u†d„7CäãÖRÕ™B;dê¸lVÛ¥.•3JuÈìjˆ†Æ šD>îÖÕõ¨F¢Ü¦¦/jÅr8’­CÞHåÉü8ìŠIö%åAz^"ŸpØG¥‡&;?”jl! ÿ=_@"QUzcÆ¢ƒêé8@Zªü_†n§‘éQÑ  ƒÑ´×Êh¡O..ÆóÕÿšþ¡©®lä+ 4ö4d`™˜SºÔ›CÝœ¿•1„™™–ÿs=®ª“âÏ£$b º®ŽèÀ¶¶ùHsÌ0‰ìYÁ €L?ÉêŠj‡ßøÙ§f’ÇÆ4‘Â'h±¸²õñ¶x2bUuèH@Zv$²¡é&ŽW—ªßÝHK©ª¡Üè¦Ó5ÍnóǤr&P©ÜZ+…ß3»aU¨çÓ_ó÷“ákÈQèPZu¬tçæ#ù¢~X¥Ç‡“¥¦ÉõìÊIøýó‘ÞT Õzò‰8½‡L‚H¡ÙB´½ù²´¸š òqojz¸·ã‘}×Sp{‰|þ‡žÂBÒ+Y¥4½+ÎsW’6¬Ò æ¨.–ÑÑP#ò…G‹ÿô÷gš "eÞGDÓû=ù’èñ%W_#2¬.öòt͇‹C´àº!呺#5#] @(YZ;ëZùV@f€/Ð+Ⱦèùθ“͵Y%ƒǑ׋1sÈØÃÀöR”5± Û–$à•÷úñT‰Ï¡½Mÿ[J=ª¥;Ì}ô€Óÿ1RZi9DFÓÿ­Û—ø¢ 3« Þ{˜þ×É)2{²ÌKa{ù¾D*¯4n›I9w"FBK±.på|“¢êlåH.SßQ¶§)ÂVΆs c_Òv^„úàªt/’LRäfÚ•ûÿ÷ñêm\‹øØN„òCh”ˆƒaÐÒÌEUùÐòOÿk–PçU½d„ÕʌʳéÏ9£±É¬|›öy¯zÿUSHÚ-k3wÞõòEåŒsçßç`üÛú±Ae¯‰7Ÿ §?çˆÑŽ~`Òw2èÊ ³(þ÷¥ ™Ê‘¢ðjúL3Mö¡.ŠI¥l8+¯ùŠ:?Æ]Sh VíØgIi íºñ±ÎŽ5ë‚K6ÃOϯ#Û‘RVé÷{$†|™+ý½±Vš8ÑȹDBvmÙ¸õB çSê£åôq²DP >3¸'c2ÊfÖ¤h°ô/W†Õæ·-rÏA ãÌËVß1ák!áJ¦a\4ÒyU;„bLTû¾‡_3˜3;a#^;¬cÓŒú|?Œ‹ºaj«MA…*x>¬™ºá ²u¹Ùlb?ŽdvS¨ÇQ¡>¶—¿,Ôût4Xzæ·Òešᣑ“½š<6Éñ@—ì“Ç7ÓØ€|Þf¡"”¾o!5W:d4i~ÕVÇ!¯¼²•CÞòž ,à5ï”­–#lÓüFÙÊDb^[*ù‰F;¯´ý÷ŒG;õ¾zìTmž¸ð×LNâô†Ï®Y 7xô«”%ŸÍ)u.ˆÀ¬3{€8Ø¿`2u}øžé]ÂRîŠ~_І+/Ôí ^óá­ÖRFÅl¼ Z›Ÿä•Ú Œ;ܡӧgŸV-*㎬Z$2»±j‘ÈØªÅ!/¬ZdN[µ8䫯yaÕ‚”CV°jqÈì®»„ÆÇ½e½©Á†,þsº±uCµ46u‘Èש‹DƦ.yaê"W)6uqÈ/¦.‚ä…©‹Z¥ÈÔÅ!³;57*ñ ÚÛ.²ÂpÈ;.¿`2¿i ª¬32!I~ž?_÷:„|ûòùCß‹¯†=¿I ˆ‚ùHàù{Çñ¤z¯ MŸç/l¦¡ƒSáOÃ0t%5°pä÷ÏgòÉAŽ» !ŸzÞ[ œº ÑäÐ…DÑʧ_%z¢<ú™~“èÙTK =‹­¬uIHŸÚõ©Œ*)@¦îÔê·Ê¼›àuõ5Ãgq¥/df¯ù¼“ýAç;z]Ëþ FÏÈw\‹³úñœÓ$³9ƒEN¡nfxyì`»g¾;d7â-¥„³Eµá}#>²w·¼û¾³cb+†UìþÞCdåÈUª·±›ß½cƒo϶3fh*›Õ£ÿ5_gy"o›¦È[# 2ù<‹uCvÅCxê uµ– ŠL„•¾¼&iHŠĢ=Â÷ Ý=³¥-+g‹€ŸžÆcÏg_»³ ~zG•‘¬ ]„i¤Ï¹¥.š[’Èôl‚æWóÕƒhvçj~%Ú½_Ùç>ïÔo•RmèE¿îI2Ìd€L®b¥“{ ߉ŽÌqÏ×ìnEãO®×‘C¼9òöäZÂÛ&r®O®3Ä9su ³ÁŸïÑüÊÅ\]7ò2RWFëê ójwOÝûçvÞ Åõó‘ÀÆ!š®`ûbÊý¥ Ñ˜ÌøœòéÈÑ­'drù“¢“ášðoÜ;9‚U­°=ÕD:_~'_BG»#½cú‡¹¦­çóz¬pÕùõŒçBþ¸1wsrÉ H~ÑŽdÄh {N¹©Ð†Û¸dDû©[O’aœl3ï2´Âa͘;#òíŸw€¼›áP]V·ZÛòÙÄ;ý6áŠVðšÙí³´øŠÄûSßJ_¢ƒË߈®þ|2“ŒeÓp!ÔîM2¹Øë¡`¯{¿¾J‡qîÏ£ÈÎño'6e§=ë†ìáÞßç•7 7_…Ä—jìÊK’… :²st¶“V…Ÿ,bU8;âÉŒ¿Oä=¥Tø³8šÌ8þ1Ù„«è.Ë"¯+ òq¾û{Ïÿë|÷}±’âtmÍÌ÷sõUåwuŸLÿqvÔª“ÂøØíVºx)O.ZÇU#‡~†HO6Ó*ü½‰ÒÔÛ¸Q€|}âÿveË’²L𕎶½]Îýw"æpET\p‹yúŸµ lí?bÎ\eàÒEUV¦=j$'Ý<ã1¯ƒ¯´M«5¡Mƺ‚ ¤õzù«¿8«ÑÂÅÀe‘Wùps)‘Ú7mÝíÜ!äÔíµá§&“÷”ÔÝâDtòåûœH‰Ò.õÎg·~½&ÉëS$È®ØJ_mÆœw¹q„¼}"Õ˜'È#kêÆœÓ­DÈû'ÒŒù|@oDæ´®fAXßuÐkòçßwŸöêÃX¬ #_ŸHuõ¤q-ú÷ y3&ëÖòpuSÃÂP5è4ò¨â.¨õš‰CãO¨õŠz~]F{$s/ˆ C“kè„RSÃú=v±ð¡_ïÊ(XŸC·Ã4}~žäiRž9ÞëëʾH¹:hr`ÔWµÑ‘‹cËäQ¡oò4)DŒÀCÈÛ ³:;0«ƒ¢3fõä™ÕA Ñ9³ºÁÈoÌê !¯§Yý¾eVO>hD-DÇvŸJµûÀïÐ,Osü|z  ÷å̪/§AÈ‹¶¦Úrð˜É¹ikZØ¿Ÿ_L³Æ}£`|?1µŒyfšœMYÏþú"‡ ,¦! ñ.²' ð²¯Fõ@Ô䄲ûcÚû}4dÒ‘ ‘çi蘷!½^·bôÖÖOÎŽiÈ[„¼¹åQ—Æt!iÜÒº\êÝ ÁÇÑ&¦š­­­›¶©j*yP‰8¥£‹°r …>®¿Þ8Ê(j²}\¬›C~dk£?IظS‡Œ¿™•Ý䂜(ìß1½!u¡é½ò- ÎØæH‰QпãôQ­©›*eò¸÷™ÊÁy s•2ÎxK)µ‡Ú•|šü[:)g˜ÐEûˆ(Ë îóqb[UGwÎSÎ]1%úùv”&ã%¼(è7ùE‚CíÔ-{Å›D¾ÅÓÒ˜^.|dbe©£ÊDÑÏUñTL»*žºÝ#BÝŽÓËLyÌ­™¤C†¡`8&‘_\ƒÉYA¶ »üøê÷Ód‹b o £/f~ÚxϽÏ(þ¶.„ÖQtC0ânºÔ8Rym'Q#‘Ø@È–ƒMB,ŸÄ ä(0ŠûEÒD¹ ËÖü€¼¹cš—"S¤bº¯E6;d@¢;•¤‚¯#ºÿI*G5´È“’½êr $©òvz˜%;™œÂ³DýÏõo¤“ú7â0“£ÇýCõi’ ¹E˜4«œL_L½Wé8/9ÌùN¶„‰¥SçßüIÂÖÈe)))ƒ}3 HÝ*•ï3sTØ‚o}K¬‹†C"Õhëk.Ã꺜`‡µÈ[hWf“-UEª)%drAPšpŸAX7RgN›Upùr²Á˜ñ‡t–‰C ž÷e6Oþê@¸’[ —#C7ûÊœQ‡±í 1en׎âÛÁ:Ô0v+¥)ØÏò¼Àð˜ nK1Ʀ/÷‚ÁÞßÚ‡z"dÚw3«B>‚Fj«©>42Pãû|º#ªžÉ.}$·„®çøê/·HAó…쫜£‡g_..Ë~ÓN š¨ƒ†DKëŸc’‘ò•¹)N>:5A(P/è±—9pVÄj¯R¾»c·ET?W¢QŽ8[µm~Ž$±Ý@RP^$òîÄ‹U™ÂÜöm˜ç6ó¿J‰)3žŸ"åæKi¾Îí¯¡Ó“’WÛFaà1“+ޱ/ùø*Ø12ŸOT¦ÐÏnã‹Mµ®~†¾ŽÒÉ…KÄŽÓ6e¿Ï÷!r¦sÓ-U“fþ‹| \Çs¯Ö¦¢!ƒ¶-S–”[lÓÔåXå9¾º9K)!!EÊ3ŽÊZfåäpuï1¢Îæ¥qIHå‘7â:I¯*-W n?_šH”¯Ž;F·èÿøêø1ƒ¦¯Û«Ï(Å>¬P®¢Ð-ç¿_› 5‰íe¯«‚å5B‚†Ö®5ʹLÍÓ\8Ò“EÞB…_§,>VT±HHš…]6ßä™18KYäÝ)¨û¤pŸU)Ö_Ý›”¥M‰•©WIyi‘e–ÇV $Z¤^A·¿¿n­5Wgù¾—%~ŸïiV0…\ê|Ýð˜FýDâ@—Àúm7Å«@(lŠnÉ5›ˆŽªÙ.?Ö+Ó1§»‡ÆøfÑí’¡Ä•Âä4Æ$òú@a:>¼¦ö`î’<ïe¨ KííÒ÷z"êBÈ8ð©+©U^$£êãnÝ}†ìë3dãÑQȾÖo©´Áÿ,ÚqJƒÔ³¯}•ļNÊŪ?aÌ袞¢‚ê°ž%ñåæÑ zŠEÆ_‚+¸Oœ1>š¶”-¹Ì‡ UV,p@ Ìeε$ýÕ¯´$Ö’tÈ/Z’ FÞ®ç’KpEÉãÿÌ%í’þImv9&áòåwðDϽäÒús/C?ç)¦|òÞÏyáè¬SLxÌ+Že_ù/.y^ÖûL·µÿÝ_×îõ[•‚{½D¾?:§l*ªßd„å;yŽŽ=¨I ÁïþþLÀê*É(8Ýæ™Î!qOPm̤xÅ–Zƒ*‡ÄüÒÒt¯³Ngîˆtÿ9• Ña– ™r€O¤BFÿy{—„\m)¤Y¼½‹ïƒÓŠÏ#ÊÆq•£{|¢teüˆÜö ÖЊô«tm®¡dí7âúw,*Dºò¢—0Å~é÷yœ9BÞ.VýjsŽHZÿO»ŒnÙ"_@69—Q‡¼_ú¦®®~j‘ðØU8C:ÖäÃ0®ùDÝXšq¦\>ßx‘/_J(lÃ2u¶n‚á'z_û¦Öø-…§–÷®.?Wb£]Ž¡Q Yaë†l«¦4ãá÷¼ô8¥ÍŠo5ð8+Lùöå_•º*»ƒú|XàqÚŽsµç¿~ïqªF5ô^5jÙˆ”ãßôÒã´áb;¼,°£Q¡µnöWÊqlY± ú íPmÇ‹«m½µCèÛ¹+٠í8á}?ùC•ý?×v¨-~¯ÞãT©ÜÊŽ XYCå÷‡+ð8-\Û¤²íûµY7 5¦ˆ¿ÈdUƒ|&{bhÐ'ìLžñì~ ÐH`ŽC;M}Ou?”æM²Mý;2PÚæ!ã Ýɉ7Ó}Y'á$0ò‚¦…Ë8©«u ­µQH­w‹ye—ý•­ÅÂj„¼#âŸ!VUÃ’öBø…KG«Ú“É/m'X02Ö?Æ,S o1 XÑÙl_æ´„&;‹ vå b㺱¯ÈsÞ½œªkÇsÍ€yÕ ù:á«?­úš415oGRw_ýéNª¦L¤E|ÇEÎ|l%h²û÷«[ÔKhQ_ײϲ !ß'-*#R®“Èç5QMSÁ;º¿.åb˜!|òý ¹ùä0ƒ©¡µ¡†r„¼PC•vÜ.² _=ùDrG"ÅÈû'‰´u$Ò !oIIÀ;äãÊv€wÊv`SwõÇ•í@ˈ›ð¡cЀð«ùlH;-û"–ªT¾á ü¯Dúy³¦‡1“O9e0¯}sþdÂZIÙ,TÀ³«•¨Ã*„Oa«Â©GcÞ¾¶?l¾Rã[Ž¿‘ü<ỖÀàЪðÑÄÔ(´9mˆƒ, áŸ7ÄQ<æó†‘æ7RA;lõ*·/´Ø™CÄ”t”gô@*Êæ”À÷Ðõ]ÇŽ¹íSÉJêÇ ¤‡4gD÷ôê– ¹É ÓëÒ#ÔÇŠÀ; Fôx]Cè¨T:ÅèßçëãRØzëNfåɸ!äÉ1Dµ?lûžÂÎPÑq ì(ØÖËu¾òþ)\§J¸nù8´Àª%YÈÏX¤ B>«9Û‚ U´Ò}šáêÉÁ¥ÒêÚµñ»NY1ω”ÚÁïšUbU‰·€éYض¹~Êónq¸zrÞV;ª¶ZøîßÚjéRì‰K%:'ÁSùA¥;‡jï;cpkÖ6™„yŽÊ•‰ZBäÅWÿÒV{@Ì}6TQX&Wä\ðÙ%߃YQåÚD”¹ŒíB2>•Àì§/LdªüØwÿ½/é…ÊT‰ò}]nUjÐp6®£ cžçî3þ‰.[Š™Vótk]üy …)Èg—kX—9iÃ8T¾wsÞ'[9ç«¶v2„qÈœýc¬§Ì¤WÚóy%x× $Z—l#Q:T½P><yCùrͽʆóˆ±CÈķ9îò¦âC¹,„!$hä§™]æupåD¸=Î"HOImãÃ> ¥Ö¾!ä±LzM´Ó&WE—Õ¶HÃFø§¹V´ƒ¥d”ÿ˜5/wÈ·=Õ)eãƒCvÆ‚V3÷æÁl›Èg·ú½”.­| ¿&ãe :lP&ƒlk¨Ë9h êP¹µƒ©9•ýÖ,.°tÐ@HŠbfÍö4Ý*1/-†%©¿zT»4r*²† 9«0TKo›iR7#ã;/dÐTá·jЧ•ñÃcÝ¿WÆwÿáÝ‹xQ;zùÆØôòøçàs˜k’ñþj Nœ{ŒD<µÔùÜê©vsÞM­ë¶³È#M›B¶]‘¡`{e«„ròqÞLbBÈ$ô¿2Ú\ùVTcbMòîkjŽ?̯ä'U „|xÁ¢ V£›ù–RE>/h±;ƒƒ_PÖ-Öy¾)Z,i{Ž×´Ø „¼VRHÕsš´)W†‰;&iÍ[£1Rc%?å_ývƒºûä¤ìGP¡´Èêܤ.q·vé’ág^‚#ƒôfüóþb¢¡üîÜ?Žp ú Ù¢tKܘüA³E®·#¯4[rÚÑy;×W‘q}íç™\è«(m™ !ïçú*û”‘ Ôè•–ã(¾ Á™Ö Üà>q]^¥7©-¢ñ†*>!Œ™\ åá§ßù0ÀüŒ”ŽS«5fžF‰ŽKŽÇô*^…¢Óé-dTšî;07‮ÿïéú/,•°]«½ü›èúšBê$õåLžÖ©¯Z†7(gÀLæJAlÍRõÇGaƒ`Ŷ úÄã(ìwì#)JX¿“¢ƒ1þ«šthèȪÃ4o§!ã+äP7xLŸì"cËU¶Üž2ùLV;õæ#äý“y1æÃ§lÉÉÝç<…@HPq™+å<6Ôé<3<æ !mWµD¶ÊD!FDå´y'JD&F‘^÷5¤äv'²â ZÍœMX¾-T4 øN£8ìC… ï‡tb)†Þ® ¢äøMF„‚fo*ã±6ßV ½_Awz¼×Ç…dõ*qô>²§­LÕ¼ ÙÚ7™ëeŠƒÝ_ªÙŒZF¹“ÇŸ”dcޱ¯U–d±lKÙOòð»"äÍEŽ©IÉ©_ª•ÇŸ¬Η%ö @†0Û¼\Ã*Ò´ÝŽïóîDEu„g;¦Ë’ËŸ´+òábAÍ©«vÎI[¥=sù ‹|úP°ÐÅeÈÞ¬s5ÍM¯C/“±Îd\3ˆÙƒNg¶hz°Û&ßš5]aSŒãc²U–§ù¹oÖ¦ï2F]ŽFy ©6ÖŽÇÀÒÀ¨듚>‡Èãˆ2hÛ2Ú¥ÝfU†,“ÒŽÁW¿{$h!ÎûPmk8B‚Œ¯uðÁû~žfmY ãN Ç ÚÀôÒdÝ•ò}¨;^ yGÉ Þ ûBÛºä_òëwʘ¶ïHwå1«ºâ°§D×üœ$´ ï†EÎ-ò~4šÔ™`ÚNäw-òñ¹,Ë'’çÔz™,ò á20ñ—RUå„´œ}›‹µËÀšg¾Ï ñè–û¼i¡Â[”!QŽÓf2Òn®ši"ðìÏcßfU¹u¾UÞ®¤AÈøS¼O~Û´¨ÇÞrà gÛ ­PôÏ­)ýïþD:©wû#E1 ù1á1ï˜!¨ó=YKçj_ü y–Š­RQS?f{Å+ÖÍ:Ž_8`ÕVn†Ç6’\ì"ŸòècGõÊ`ŒsV6N2¤Ý©ëâ*ú-èâŠã0[oÈÓ…­-³ÜŒ»Ü2Ÿâ°Gç÷Í÷èãqÚùDc1 ¤·ÜPH³Ôndé7Zµ9BÞPIJ‡Nžºåÿ™xÁJ'F“˃$«f²îy÷.eÎnDÞçÜ©+ñ}>`—Q$RC‰ÞêQnpò×GHŸ—ÊLζ’0²õÛÊ]ï¢E†¼LÓ8©|W>ÉÝcCÈwëªM±->‰4u‹îÍÿ¸ !-\Ú¶èhÇË”M=†FjGúc(Äöé™üâIßWûqÐ6¯ÒôcÒzÛ—¥ë,0²ë¤p"Ê|Þ™r[aðüQ 2¸2¾V0'‰oñ—:»<ùùuävûÚª"ÄÏ”\åxUÿàãÛý"˪´.òJ08&ÞG+k»wÊgoä~˜q`9â2ö†#ëÈ¢–ÛãP™…ì!#roèºïZCeú±®c3,ö$þÁÒ‰\ž?W‰o¯C]£²LÞ¤läÅqXhòëm[ÉÆövï&„ŒÏy‘Dñ"Ý›þš7ofÈBg;là'—U?ïðo)l'ú»é«W6hbKG ^2þ´ÙÑ]BZ6RȈmBÈø)£µéˆ¼]Üç¾rIœÜ®+ Jn*žq’\è(()ʲYFÇ;‹“ûwÐõ‰“C"VËú¨¥©å¤R­ÿYåÿm€aöQ­=ì²a“Яu¤¤ö(Oø:M0—’ŠéÕîeæ<sÑ4=Ô…-ÒÌyÓ [QËêéòrcbÇÈ;$8 ±É¹Lhß.þ>ŸŸÌD+W}ÓÎе‡-Jæ(_X«AG¹0´3AÈ[ÐÌT}à–æ9ç=X^ÄMòOÑ;·ÞA¨ Kõ?®lÙU\Yþ’°ÁûýtľŸÀ, “EýÕXRapG¬Ç ,Õ•)¼d{äG”¶?µy¼¦™Ê÷®´%yNýÛ„‚ñ7RH$°z,2¹ÒäðjRQœþâ™ÒÅ8ãô(,ŠÎ|ß-þ9¼(¿ù™#dZ ÐÚZ drÏèqû!ú«¬¥ {ÜwwùŠGY¾º1ESmKBç VþA¾†]AŽñ医˜éqeªÙŽÁðbôˆëþÞCÝ”èñ¸^OÅ%£ Fžr6̾äWéy૨=µçA2Pwß§gµtظŠMF##£³²%Cò–Ñ#½ØÅìŽèqÍ åŠ-îßûóva’¦D”•IšcMD![Ü´¼JSºS£~bª3§2=£ß¦Ÿ þ;A“GƒE{CÈèDÃlÎÖ¶Þ€Ch‘䪡Áýiø uhBu™µ¥ëgX*(-?¿ã%_Ô>±R‘©Ûßæ.~roó™\Ï(ÈÛôÓ ÑóÇ܃\|o“œåsí%¿ž¯_'ìä¹êQ òm&ô ×»_æQ9|¾‰¥=5Ã×72‡³&ƒ“+ š9n„Íæ]jjt\ç7B^yhçLQ¢$:²¹Þ•S¥yÜàÛ§!ÇécÉgGúXQ_Û> ƒÍ(y\Æ!ˬâÍç—A1<+Ú²ƒ³89¶oìð¢ Vˆ—’ NVCÀFÎVýŽè”ϳrLEÈøü”Q:± ¾ÏÇ?mþ>“ß'—ßm™mÇ64ñR¹‹MÔŸ¾„ûL¿…™(ÜR®Œe3­2ºäÍ‚4B”¼~†Ôs£ô† µ’–5všÔ@½\(‡¼s©S¡™·y)02ˆ—LåHå±k6óY8C‹$A.Ck;߯vÆdòã2”4úqj+¾Ä )ùóF8BQjÍu4£)* R´êw5¶ùüñpMÂþó”Ct½r`eSl!OÌÕ vhÞD©1ÏSL³ÒÇ)ÏS×4Ï"ôù“çI}›>0-©h)ì oö<Ó‡6ý!‰¡yò°Ï§éï}ÉçïéëRºCíóƒ ìëvÍUuÐkŒ^ç±¢Í e02¹Óë§¶âÒÁÜCrG¿Dý—ATPåx‘¦|jDÞñ{£;úÔj-C,›s˜ˆB¦%B~¦2ëd¤šíùóÈQoX[0¶‹¾ÆHâ a\ÿ’µ[ݲ &c¢iiò£F«|¨û”q÷ÌàìxÅÈ Ât2lסm?2fšòy®ºÔÂ×j_dû¿H·Op04Sîö¥×óÇ'ó>çzý:Bq—èõ=¹Z×¾Åý:Îq 5#Ð"乕qZG^Kõ`&¬E3áèš?9S¹3ŽÜBò˗ɹ ¯y?°7C“ó…¶™Û½‰W3Ýþ¸ê³¡G)CòMnd;B’ó!äd’[ô;ÓŸ\“ÃLŸùLß"£Ë\›Î !ͧ+ÚµååM/÷üeqÒäö£V‰r*¤~í!û0U3\óÚHMÕ[ÐúµÈ(쟹hmëJ©G©Ä©NéV!÷1§¥JÕÎ÷ºt/AÑê{¶#$AÕWcƨ8®9Ï»!õ6 4¿ŽŠçÛ&ð}>BÃ"+Ð åÛ¸97Píþþýkm4Ì5…¼¨ |Ÿ‰{›–9©w¡Ü…ò_3=×–ù;h”’ÛwõÕêïËv—Âñ{IHÊûŸËy›žÜ‡o9̬‘”g²‰Æ¸xÈó}oÅÞ !ýd!ˆŽ||7ÅäAòpM@}Š=Û1òé˜ÀôÏÔ)Ãó¢`™\if3˜N¶HÛ¹4+_[ ±®e"Ú!O:—Ýaâ™Ü^¿ ß ²²Èè[ÈJÛ}¨r÷ßï±­î¡3Ó‘v‹Œ“]‡ÜïG¤ñ¥ãÔUÅVN„”Àcn¸°%[ÝyDî8‹ôê*ݰʬåŠ0»”• ,óç±»·@ÈVl¡æšŸfz§*I<%Ðæ2¥e½¬2dè—~ß2„L<£B'Î&”W(w<"‹L­8ÓG‡™+lÆ–ág…Z%¦¾¤Î>ì™3Ýu+ H*³ôŠò·o-¯ñE^w]Õ†K3öÙ{Y¶}Î1T òù¿\3?Ôo^d½?Ï–7JtWî¯öQ7»-Ù‡5u;®‡r®Î™¯eúiá3‰É\ãÚ¬ò4yÖ¬!±’Úò••ÍKQ,Û†¯IBäÛŽROt–7êW*Âèªq¤~*Ê!†#ò][)p±69kÈ'|zªîj6\¹37¬‡‹L\¡%3ïI'Í\ÖÏ{CÈÔɯh! ^ѪÚ8Å’€z”ZÆîÈijQÿ¨…–ž1L¦I Þ»¡Rr?U4¾VÓ¤äBœä¬ƒà.÷¼ä;–$øòœ›ýòüEžsÂo$Ï£~7ìÊáÊääžãƒñÕ8Ýàè¾ãp@·«QÅÛz÷!‰¤VŸ²9jÚ¢åœNûCÉñÒä}.K;­ ¾O3ÁˆI2UÝ-F>/\HUÞ‡Ÿ(qáªq“rQz¦;„W÷$pmWò´uIuË^F"»PÑ2¾æËJÿ¸ÑÛÆ AR¡ìÏðÊß.¤%é<ù×™èçµñÅV›È»l³·¿Ñ×q¢6ÑrÇËwÖuï©EÈðuª96ŶV4ÛLYr+*î:®UVö3B†<ªÚMéöò“΀~n‘ fhņՙ¸ä¢Ÿñ}†Òh>»DŽ#þïHÍ4g>ËØ°]þ¨ñ*¥R_±‘Ⱦe/CÈWÐc5£¢T®çÂd¼ê#‡W@þŸ=>µÞÚ(ëïe“¡>S)ܰOÇ×÷¼eµbh<Ø®‹|ü:?ò•bhà ¢1·úMÑ|zŠ¡q¨ðØ8…Çœe9púôá¶f¹Vv2ë³”kÓÅ»ÇÐg0}ИpPþžÞ}½-^Ö{2líÔ¦ú.ï²:Ü@ºÏ™§–Ù¨3Ô%iÝȔ݀4|btCç~Ïlü™}Í$Èkû(ø€4|j_sD>/¥zü¾Ý¿š/¶-O&º7 l&Á×줚j†…Ë–Žë„‘Qظ·*õôYdì ÉZ@ð5’lÛå‘85;(§“Næp2ÉÍ$“«%‚äíõ@cvgùsÖÙ/|£_òöµ9çʘ¥)KHmByû5ùÇR–Y÷1QWØ'¼½ RÌU=¬ü?\†m=B>ø•Ëw®s™¤ïœñyÁÿ=99à y†ñ <âåí¿N¦>£µ\$Œ|yºL*Mœ!Š¶ÍŠOAñÊß‚š ÌˈùÃ×>>z:4ÎQB~Gµ®$¡fý_‹tÕÃVi 3BÌô¤všq>Anã¹ÀòK–H=$ ~,ûÇ"QÐwê&dž{º³ŽÁ–ZR^çBWR$ò=gs†úgüï½ã[Æ*+Ÿæ¥GÈǵ7 ‡û|þ‡7Šÿ”Ÿ×¹â,Ÿ+"Ží±° ìeIÀ±µÁ5ÔCeŽÞvÀ'!ÇÖôçJ;£.ÜZõøñ5Oûs2³P}…!gìŠoYÕì;‡ƒ3¾ùúQPhtò¡æ.8Ëšzåxî‘·ä ßm̺6óíŠø0Í­NܩܻÊëñý É¡b;ãxÞ·Njq¹®Åù‚ùÃwž°œ”DV­xÏ[ɹðÓ°´þ”{@çéT–xâ.yü§ ‘1’yÇȳ©ë¸€/ù-FƒÓ}ZX‘÷d`'çªð2¨Ú…ƒ6AV†8a’ÎI¦œï…õð‹óV'\ÙÔ‚·y\›î ù¢sÈä7²4:Ô¨_ºßÉõkq:^äñC>N{…ÁÙõü%NK³Ù'ñÏïʪ)ig>óÅ%sÏè’p¨öχ$(8K}ºúˆ¡XûaËjZXùg|!x«Í&/xK‚1õ‰ø’Œ|¢Fð¥+á>Ÿ˜Þ\¸AQõiæœgð%"è'¨©”‰‡w‚"ºQ‡Òç‘:^«Bí#øš?<£àà|þ‡g”¯“?“Ë¢ÝbäLá¿ÿžRò† àEü8ÃI鈊ٟÏ×…•2dC E$¹NØÆªC±6χ"ÿÀ’ÜŽ6°NGêC§~að‰OOݰ)Épª’ÄÀF#'l2½LéÑJcI©~ÅÝ6lCaP8vawÚÚÙñôû²ŒŸ!#G+‚‡’tõÀÅ»BÈ@XÄ6RTÏG˜ÍPHîÇS¦q‚¢2åõ_Hr?%l›è°Á(Ç…RøÀ.!_Jc2¯(”¢n3ø'äH0¦.¬lËêì‘ÄÐ;1¹‘N çóÈ2ö-<Ý¡ZXòSS=c$ˆ€dzÜ\=|í2´(ðEâÇ\ˆ§z¶“Ï¥ŒÝ·1¢QvA]-7<üßÓ€×cc‰ìX»í9F¾¡éË.tWÅÿßã£ô¨f“X>(½J„ŒÎÏuÆù/äÆÁì¦#U¹Ll.àÜ †hþýšÀÒ"“ ô üòü¨í¨Ñ¼Ë”ïÍJ„$—– @€'Iò•JAf¼pö xöô+36IBÇ[±ô-˜N“$E6¬:E1‰\Kùœí$HIú•t5µKºßß¾&Nºü5©¸¶È‡+“°‰Èûg'OùD¹>NˆÎ I8…¢]0@ttPäÃ"Sxøïéý =ÙØ]Q+öåÊ!‰£æ2—0Õ=:‹ºÎkÞbd|iâà¿ù4”…™øA˜‰¤ÿ)ÌÄòD˜‰„™HúŸÂL3Bž3ñƒ0“Eþf:\óðØ\«m’w*ÓbêN®4þ'˽Zméãz„IôÚ‰TퟳÏ~ Qc%Ïž¢šmãPsÂòªY xïgÒ¦ÖÔ­üÃ/.},EJIa73£¡„Ò÷ îm›±{žuP»Ó×ÑàÅÙ.Ëó½Ù&_ K_¨¦k[ëæ>ó¼ÄŸé ¼Ø'ÒåüfaÙâ4RO|òZ}Ôî6Í6v3F¦¡-›õØl˦“™!êSO|:£ö­Ë` 7xÕ`N8>O^÷ËaŽÆç-2:—¯ê™÷&¯èǘ•Lµ}#:Ý:5óuâ@öÿÜp Î÷`tëÔpÌç›ìÿ¹á˜ÀȆcé{Ùÿï|“êzWõ?Jô#1™FVp†"ùgüÚÑ¿÷ç‰_«ŽTåV§Ü(k@žÄ!æ4ÔöqM¼—pÌ œ]í—œóœSŒ$ß/Ü ¼€–¦EÆc,óÚCAùæ†ßC%VXä ŸZÉ¢euW5øš‰¯r8ao傺äíÐák¦€¬œ:è:U2Ù_> ¾æëjìb¡þ«Kó%äÔѬìfïè ÷o ù>ëVnbô=å_X§;€þR ™Äâ‰È¯ ÇûÇ-&=œèÜË›¨ úz]“°…¢Àûgz]Ï\k¶‚{õqà&ð¥84öQ¸D2¾Ý)í;èÅ~îLqH™N`$¹*J¬ÂÍ’Ä·èWQbò‹}—­4S#([Å7òËIAó®yä…9Ç3nϬg(±lÈöc®»ò=±’ω1 $Æl‘áq ~kMÞïmÏá]‡"T­õO”\«ª %xövRãT/u!žýõ¥eé¶&‚Êõw÷y¿Ø e툋|oJ½Eb°StÙ»½}»~Ešƒf×Ì2}X?Uã"ÜÖd‘ñ qÖ”zÊð5gtDùÔòóœò‰¿ySQ¡÷<ûg?Jª—0ÓŽl?ŽYߊye5>|jÚ…Ëý!a•Ô5 ± Úg±æ è9Æá`ŒæJ—–E¥þ{=6 臃1jŒÄØõhÝ*c?Îø>‡¢®NÐrÚªNþïO6¸£S!Y5Œ‡ûôÒ…µ}U|6–ttN±Œ9›&òìr{ÈœLÔ6®±/j¿ã{|É1œÛ¶Õyá'¥Â0†‘V(ý†é=D‡aò dÈ ûkÝÁtp¥Â0U¾Áȳ~ E|«Û©Ê2†$hÂ[êÇg^ßï=ëò!_!€ªg/–¬| ¿òÔêBúw-WiÂÿh:é3Îm«ôÜWQ"dâ ›šI¤F¬SQ!dú­U­\O?m–}ð7 ¿º¸GíDm7U]éá¿ÛvýÉKby ?ãçÏ—$W~GÈèL|pWâƒSÏÒ•š,Ú|v&®‚ÏΓ÷´Lxhé´·™¼(¾æã¬ç!Ó‰Æ÷<â{r^€¼1ü÷ô;6Ưã:ÒN̹;bï/,„\––¥‘¢ªá€¿c£ç 2^…\Tâµ#$ •ü ×Í(ùgÁv=ÿcŒž©»OV.¼æù@–ÐM€Ü– !Ÿ!Ò¿%Ržr Ã×LÂøÛºl,S&#Ö©ÅÈô 9A\c9ÿÀk¾¥Œßf¼JæS>ƒn|Ÿ1ôþ=_G—9S‡ÿo"`¥¨ír´V‹<áõ‡¯)J±§‚-Û‰a^w&× Xk5°B.;×F‹Œ¾G8dà]ÊL Ü%ãpØp¨8lg®â(:ØúXš¡R2j¶m(6@úóêƒnEµ·rwtÅŽØpX¡[¯@ºÎóÞ6øš—ìÏ3“AwóáqÿVzå%\óq¥ôÚ½åvë•^ã@Sü ôº`¥×8˜#ø¦ „J¯q )þÇòƒ¨ŒÈ2Á¶-ƒU‰´V›²±ˆX„hû#£R5H–n§]+ü³?#1ö>Qãÿ »’eGq-øK×a{Yû×õ Œ1‹IQ_ÿ4é`ãQÝ« Ì!)3ÓŒw¾f<%{* ½(³T K#$Á¾‰µÞp&*#Þâ_O°¶´Q^/'Æ8°¾-òuèœF$Í^/ù„‰YËõ0ÌÆ‘¥ärùB¾žº“2µ¼QiÒé×-%æ°KÄØŽu {Z,§—t{‡« GOÈh,¦d2ÍT‡² .åJK|«7h`¦zÇÓae£Lz¡pÖiÿ@ý¢º)])åK>b(y‡®SÚQÊ–áôg%×ýúôg=€Þçäß›nÞÒ‰ñ¹é0ôybèËÇeúПsÐWÈï4vbC{¨nbÙ¹8+d¼˜ñŸÊ Ϊ,™¯ 4ÏãñrB¹ad’ ñ|áíÖMŽ1[ÐêGª€·%c÷ÇÉþÊ!u©oÏÎH°¿²…5Uoô3˜_ýX¹ÄîÎ )£œ¶jYÊòéca—¯ m–µ™ÜËàšÏo~˜¢{¡8äÛ¼»\–¼ƒÃþþ TÄþM?ÁùÔæÃêO»×eC‰Ë¡õG?_Ø)Š™ãjHqtûÖ¬Ô"ãèmd¹2檬eY*“È@FÀ4fÕ§¤µ.d˜!ß¼Í( r yÍÊnÕ×жóŒ‘ÑçVɬ<´ÝÛô|›7²¦=éá>ÉÅI¯Èš‡"kbä¥ûn íÖ8JÞJûF7EÔ é¦Ä!ãåñ9§nP¾Ù²FÀãèÓ0—Uz“™êD³Õ!_—&aܘ„¹ûD\?ªnøŠJîÀµ â`ôÿls(#·ÃˆÅ~ôÿ¬¿^·H=Žï¿Ô{ .G—õŽë=qôµÞÃ}½'@¿¨÷`ä·zÏ_ê=P¹ôèŸüZÅ*àqü¦¬5ctZU‹lÏáü ‡‹O‰"—‰â$z÷ÅÉÅ ›\Kh-Ž´T‚S4§Ý)ÖÄ~Øs«" ÚÂ\¬}z äýsl½°|„5?/¾w5>‰¾÷ø«~ÛÌ}å’ü|h¿èÊ<Œ§FÆ$. 7ô™¦ŠV’È>i¿!äÎékLÇQ¬ó: $$ŸÆòMkÉO£ÍçâKÐ]Ô·iVn+t´ZºÍ5j,’øe¥Ë[í%Eáœå›E&ÞcÅiWL]'ÿ·5#þõGÍ-¥MË‹išw„ 5!ÔŸ®èæãF3]ŽùÂQz€q.¾K‹ÝQ®ÿ8ê­úŒʘªÐ¨×U6_Ød̼p:4øÙßî—bÃ]‹©wúðŠRò¯JérÔ}¡^š-£¶?:ÉS›¶pø” ]daçrk˜Òv>­½Y›9±üØ3^·ÃP’ÏÕT}ôûïäKp*}úiÓ²4e ZµK6œîõ@m0.ßV7´Ã²ãçzÿb«"Xš¤i£lZòò˜0ôæ¸vjãÑ·ZOCºŒ#ügÝï¡°•i[HèÖ¶´êNÐ(¬å])¥ŠÁkùUŸî5"lj˜ïjªn÷v?]•̼Âfx2ÖT4†&W2¬l?brÿxäÖpäúÕr-„ª ¦ h‘Wxu°M’øt"ñšµ¨˜„ô–ÓÊÅ”w逑WAîÊ6†‘‘··²ä5a?ÊËt dPŸ¬l©dÈ–eQbD-B’ËV¥/,ø ûûÅ eÊ Oéñ¡Ui=ÜŒ!Ïï2ë0?“O[ìèR;4ÇÉÏ»å -ÍtoÇ‚ÇäÌ~)m7}j‹IÆ×ÔÍFXdä§GHÏ1,ò À×´ÿÙIÛªÌYA}”ø fwŒ[¾D•® “w‚= &YíTt–[_„؉'Øþ=Œˆ„m¾MÃW^,3B>?5cäw$ª _ž‡ðá;R$h(¿$·ë¶·FÂwb,¼±ž|Ó(9O0;A5"wò:uÉŸ]¿-´8š¾R°³‹r–˜×êJ𠻝<÷º[Ý(çT³‹G½ûÎáëHÈIBÑÍÕ­KQ²=‡‹Œ}³Z{uŸt ¼ÀHÈ¡Tf¶lhÙÀš¶Üñ¯˜ÙÒºJuÆý ÏÉNC务Fœ$×rzg€"y\ˆha /¢'Ïo‚쩟À‹CÐr…Ùšås©UhÀðA‚6 ‘û°ìVÀnƒ Â9¦çlæÒMõÅ¡ƒš^ ÍÔŠîN÷jú¾ÿ\ßWÇCòŽ}©h†¡ \ÌUöéT-Õ0œV¿J–7P™F¥ü¤Ay׬¾ê=èëU•s9 Ù:æ ”ÅR‹6s >qàè‚Åb'šnŠL'¸ŸaÿäþÇviÀëyí1kȦpÍ×/å·ï‘ŸŸïnŠp:ŸÛw?HlÈÏ•G"³‰®4C~®<ë‘èïóDA%¡ûŠ. å¦I«5CÇ1Ûêñ¹K >òìà{ ‹4Ñ‹…së¢Þ{3mÍÖ dP J³ðÍ)ÆÀA”ÓîŸÎ;¶Ô-BÞ?w©:ï ÈN‚i÷?šêZÚþø$³ó\ÌŽ`jЉÛKžæ=­wŽoƒ–•¥­p>´«È02ò²ð¥%m¯¶³á_‘WâlÙÐʳ©m’øó®°šßR5>Âñ¯‡šßYòò‚s½ç Cj‘ 4tOÕ áÝ| äÓ!í¤Qí&ÆC0„|˜Ù8›Úöô<Í9b%÷jjµû·©Ù|ðj:º”Q@Ar“¨–ÓU‘q.ŠJáªç‘W³Ö~ÃzÎò~©<‘úGúü®9Q7t_Áe÷ÓÄ·““QL¦•ME²§J¬¶åÛíÝÐÛ‰ÍÓ6Û‡|@ÈE–jÐ7tFƾ¶î˜©JC°=†|ZÒªÎý³=v8]q{ˆ7ŠùP_»äöÍ„yžy¹ÀSŠ.ÆœÁšö ·øƒ58hnñ/k%FF®EžBD¦Þ2÷ï›arH‚‡RŒ5¨úŽxA{¾–)GÈ@-¶e¹y³’npÌÝJÖüV¿UbÙó îI@J𛈽O¶ÕEÅF„ uYj»˜–b`yÆyî¡b“Q1…”n¬×lævFÈ{P™ª›°¤ÏÚÊ¥óÄOð[…Ϻ4î']'æ6?ªe@ÈøJ«`­r{\&Ô}&·¯¶çÂk¹Yäý]YJ©®¥‚NYŠ„ÆÍ€SeÕ¦‰f-ƒ#>øvŠ#µ¡Ž,*Æý}ßï,çŽy[Tr¿_—›ÔÚ$ä~ÿØûq*P^~—cÜœD²Ùë8S€þÉßÏÒŠ)‡ÜGR•hÊÁÿѧŒÕ÷,å}NrÅÃî}OÚc…;;(OyÌŠ!±@³þõnP“Ô5ô½,’þv…©|ly`º÷CË£>˜ò÷ï-°"ä~!rcDƒ:¿’É7;"µšýß}oÜ ÿ<ã‹Yغ–»7—±ªÛ½ –® £ -H“Aá$—"7[ÑV@þNuÏf_2Nr_¢û>·Óæ\ÐªØÆÄ^©b3áè„<A:â.ù¢Š]«yP¿B’k=ȱ•gB gñõ4ª5Øe‘ä¤.ªZ[ÎVFåAæžg¶B]+C‡\fxž^û$k%wøbå;…•œD†t¨j5liÅè¤<‹ âê|¥º!^ÒLÀ¸Iâ÷|ÓŒÍXZ‰ ¥m¨/™9Ë¥{™»VòM=QiHðë !"Ý<»×!ÏOD_ÀI K}"7šÞÃZJ^'G g="[dΛ¼¸;¦–µ-8áZdü‰.3®là~…ꉘÚ]µ= ¨Ý™|à`/\4Û"Ðk—Î÷äuÖ'v¬fQŠ1`5[äë“X”ü<”X”ûÛO:ßj Ù„•5—÷Ú¶b°ÇÙ³´Ö]1+Êc8çÙŽ‘‘?‹ÝœúÜ6ó®Âµ!c¨{+z¶îÉ òÉW?úkÞÞD ,ù[f‘l­;1"äÝëé:bšàÇ$³³ò¸`f÷L{tKͪS9ìN¡ÛÌì­§K¢®ÙÒ-mñ}@FÅܧ\òó ™…MWNÔ5MÕ=87þ„5úÄNçe•YÏ@KgÇ“Èôm¿¬¥•úé×_Y¯Ùg•ŸCzäÓêôžÝ“ÿñ‹Þ4³âÙåC]¤z 5Á5M]u;X×å†Þ½0¡ÚoÌ@_Œ29_¼<ŒÒxcì§·}Osˆ‰ì?û¢Ì¼¡ùºìÍ ŸÈ# ‘ý§cõÂeËÈA~É󨻩M\GÖ³èÃ{i哨OW}8Uß x‚OeK[Vâ·jHdlª±úÔŒþ®mÒå}yhehdòš©Yúóú3$2‚¨™`Éãsžp sÐÛo½¨v LW×½X·zm6vPÈ,ü|ùg^Û?0Y™`Ã`ÕZ—i9»}(ÖÎ]½ÿ©neZw äýƒvŇfwÇ!ø$ÀFK·þ»:ËÖn)2~w–PõãÁ7å#·“_D+Ô`‹ï£=Hµ"¿%v9ÊÇ9 ä!E 3Ö{d‚;¥ë6ª)¥,›AOš„SãŒoéèê_Êm䉬Íɨ•(TQ‚©q[‘³k‰µù˜…脌ñZÒáIÍ÷¦EHòΩ`« ,?À‡Œ<=TýäÝß®Øè\žþv6sÒ$´YWùIe{Vá_ú:pÕ8Õíª¨6eŠ/p-0´ÉFK Q.s¥zÇOþ'`X6–¶8ÏÅÐn0Ëæ 7 µÂj]Ò´;½Ïûûœ³Ò4ä?(#¡}Ý|qMájÚ2‰[á÷_oH£õ³åõ6R¿0„4ÁðßÿÁà­ÝÊiÈW†YzW1·)ÓT¾¦œ2>M^™„å ‹Üôñ¯“Ë.Ð?È󫎇òŽu×|ÞÎc-¦(¦7!ó_÷Bƒ™yS”¯¾t„Àzà% B3óÚTD®eó’fÕë•#B^XÎ2Q†Dà‰ §Åh<ÁòŒ?i<©ínWQ{•B±ëyÞB]±å%Ëe¶ãkFaiÝ9»Ñ…§Þ¸À"ãw=¦•—©Òc:Ýg ON\;Òeœ G}±ÈÄùß)ék;ÖÂ7ÁxU­ø× Kk£ˆLÊû°&û3,¶Þ ”0P" à£Ò‰ê“\zE\¹tÃþEÀ^¾våý‘òäÊLBÇç}YÓ¸oòþ¾–†%BnËpÄ?Ÿk©\Š£.¸LqòŽŒN×¶ö[ºfäŧuˆ§2°Uˆ™®bâ+„:pÖ²^œ‘äÝv¦kµí ;02q«Ú™Þ$J³ˆ­3BOߪPÈ ¨Â*)hTL‹|ú½NeÞÔ «ˆùXÚ#_ 7éÕXÙPfÓ^2Œ´¡¸ó1§ÒRó‘àìFRÇG!¤ ýëkCšÙ#ýÿŸ°ëHbÜV¢W’HŠ”–Þÿ©²À#˜Ê§ÿˆ 4ƒìqÍê ňÐý¼§ÕW¼ÿù3M’W F¢€ôÊX&6MmÉB†gË$Ùøn¨Š_žôåoÎSYg‚}.ù²ÀÔ“¾HYst3±Zå½òrÒ±•S}ÄÒ¤\}ӱ̲ ê8Nú²þ³©z“)¥HžŽ˜æ˜€²¼É²f.žå°ì}…¯ýãÔ¥òM2ãÒ8,ŒÃnêƒsúd¿S·ö]lÖ¶¾±¶A/?‹áìùÙŽx]7i¹Vµôú¼Q÷%³¥!ÙX Ó&æ§!=,)ÍK/ÎSÌ#ï@Â&»é:Õi›6 ª¼ éŠYÒB…×I)€YR3íIÞDÛ#d€8(¦?×HSå’æ^!7–6é0T]RÕ9“i›æ~Æâ"øTõ’lƒt]ƒ |(ãÓ¼¤ƒx™›Žù<§\i¹MŸöUæìÖãÇó˜re“³šŠO‰Œž·(”×i¿v©ehdtv –çYiÇBB7Õ’ºŸûÖ|·¼ÁÇŒHIӗȦÉñy&g__¹í‘¾¾þõ÷ƒ‚ó¿‰Áy§\Vvp̟ݬ}‚Tåø".—/ÚTÙUÀ’=¹‹ãŒx)g#—éBêmâÓÏ]+¶åbÌáy™]õMºA7Ë #c¤ÂÎêç Fr×PfWe´åBÆ·ÒkèäÅ×½óÌ¥\Q|è£We «¦†¶î˜1â±ìSèÄž0æ"Á^ŽÞø×£ß#/ª#v˜Kë~ñ†Ày&¿ .={q`ÝHtqÇ·jåvœ·ìI:¡T¦ØSG\%öŽ &}uÄrÊy\Ó–…Þ|ïó½ý.™E¨(kF¦ÊZâ- ¡zEÈà6U™ñQupLU^ÈûTeèÓä}ªr£÷3¼_×Ig,X×ÅÏC~V›´S ãç{êH? µoݲ‰ýI3M©ÕªŠ‹`8Ä]Zúoý¹…&h×ÝUèš|j²åÛÀµ{_Ü?ÿ3Š õÜóo:º4Bêä,P\èÙp\Åšüãc/ wÙ¥?“Ø›BˆOì´âE–Ý,B {'abldù:ä«¶¹ð|†kO~H%åÞýúû4&W–]Q’4-(Ó­C6£C\Fáží£{C>g¶´úõ²hÓ½rþL±—pfWH»¸öàqÿ±)»Œ¼µØ(¼ŸÏÔùs2e˜¸KÁá{Ï­~Fî¹ö-ÎYÇU¥Ú+ùåwÆläYzj¼šT{¹Q†Á]>x»ž88ô<äšÒ ïâOSÂâ+ÔXWÚ\øjÞ ß³mBÈà>ÍÐýz|äâŒÂ1ëÒã39?6±¦œÇæb_Kp™Q£·o 2 Åêwk‘Á¦.ƾ%< kµãâ÷KÈ5Ž}KøË4CŠÏóGšá†ùÆj(½ž—j(Y{GÈ—{hx«2djÝG c]Ü»m¥Ê; ®ý˜þaÏ“µß/¯÷n€óüÜ »úØÜØfå1‡±\aœp¬CÊc^ £»u2Ïa|.×Þ¹å9>f|»¢N|EÉæ¡¶tìi3.5Û¸•€®ÊÕż±§Á"Ÿ‡¨ŠŠ‚—Rŧ&·yÖ±§£0ùàÆˆ®†œLSÕU:6jIµ×Ф¤Ï¦†LyáÜð¤çƒDÆ êD¥³à8MÛvøu§d¨Œ¹ò(my/æn„L¬ýMVÒRw šŠ‡ÐTY†Š×ò?P©Õšœa—ýK¤oĆ=~þQN Ö b'™ÌVËñW¶íiŸéMy:­ÍJw }zþPÆE«ªú²Í¶>?5¸6E“–l°í ƒ_Õ|ér>!dàIû*ÝßžùÐfž´//&C ¬%cìýâÔ|7„Èx_Ø …Á ê>-ùRJ=l·0FY²eºd'­ÎÄzhciR±Æ\ JGwEÑÍ6¶Ó.Enë¾~-öŠ6!ƒkʲØoºMJøBQæ§äAï×cT®TÅ=+Ãkè([á™x$€ÿQû]-¿¤r_¼»åM˜Üž§¢Eu5¾ô¬§Zð܉7̨E^l¦€Òá“óâ臃˜t’¢Ra™¨!è–÷bÏiïRÜ!ç]öëS¸óQ€ä©K{”Õ{–¥ã ïgt(S£Ü‹fíçÿzt{ѬÙ鉓•@A.Õù^1¾u\û}6%S9Kð4=‰‚iÍÐRsŠǦ)w×þ:N f`HÚmã6Ü,ö¨ÿfR ö˜)Ã7ïð1C›€œèQZ@Å·å‹I'»·îžú?É7™ï¹ üŠuoD.þ‡jY` ñÝí1<Ÿtá¨AÈàL_ˆ”¨N #‰»½ØÎ¨–¹¢.Û™}ôÎóíF0Lgé²õ«wío7!ZÉœZ€KZy¿:‡ƒ¼»WpCî½õuVÛL½?$4¾IgüzÞŽŸÝ†æ£Wð3 wsóÑ [„¢1‘GãWø›<šî¸F†¢¼¤Œsjû¦yO­lÇ £+Á3ix¿—°|E?ZHâÎCH·A÷ÆÞ~ý¿Œ½a´ùmì]²…ácþ0ö†Yæå1ü­_ ÝkÙ÷¶ÁÇ|ݾŸ£{CpšJAiñÁØÛ”ì¨jó!Yì‹.fÎ4Ú ƒ Á^£Dþ;ŒuÈÜì)äÈ7÷ŒÏøÌ<–…>óØ “3óX ‰}æ±A¾oZÆ©ÿ½ÿ@н6$ÞÅoŒgM41I[Þ0XÛ¼Ÿ›§Â¶ËÉ–ò±I;Œ ÎMp¹ë)Ö ¡ òWÁ1oÏμGž¹¹ãÞ8xÊÜÒf#î½ïjVbMK¤ƒ'¼Éï_5«¼oÈy·ã«V7z¿Ã›&¸¥»}œï~•G[xš¯ S_»X| «˜¼`/óŽÑ·©Ëéª"¦.ñÜ 4¬ßÉ̃µZæ­Ñ«ÊÅçn+e0 B†g™G§e@+5Hd§BÕ];ý|h·Ô]{r°S1~e²Rš1±´«2„Œ‘ÝÁغ5ß’áóLÎÒ‘e)Š%ßVk do©cƯTp¯ëáªÙgÉf);Ð0Äž«ûñŠR6ŠÿæÒ"£{$—Ÿó< dà·YËJS…ÅüÁÝS„ o-|w´´O„s¿]³Ï´gûŽ|k6Ý«5rÞÅÉt`dM-rά¯ºA†N([š\Fy—ú>M¡iþñòÉqÑ´F¾ìzÀ\‘9OÖ®ÇÈØÑüäÓd½æyD'÷h=8J…ŒØÝrÞ dpíLføø&×Ó>@-Ÿ“šÙ™¥õ8Œ-B†7ÈvPƒŒÎŽA߬ £i²[1ƒ|]x ñA#9BÆgo¡Y{ õ ¾¢Ä)Íl¬ö¼ û—7}Íò h®û_ÒG­¨{&^æ!?6ÕWVøõúíËJ"ÞQq¢øÎ?À\H‰µM+Éx–Aê„…>ÏЮ%c?BM7×߇Ïß±ýÊ*>Õgxö,*†bèžµ…FöFb~¯)g‡xÝÒ† ô–<â{Ú 7soiü‹6$)BúM¸J;C˯ó'“ÇäTìBÁõ-yÜǵi™¸»¢Ïïf6èy’ÇçÛxœvø–¯Ò$t3û‹Sª“çóWòuê’¯?MâœP‘:Í@ò<9’¯7ŒŒ<%¦üDFF³±ÀÈ×mî)1'ÄS³ ç+£à»fÉu{~ór· òí#©Ukt}ÞTäç&¡;s ÝöÎ?<º1Lì ˜°Ð'‚k†tÙ–¶oÏ38³($³÷´làTï;Ê©ôÏ ð){38S-/³¸¯[i­SOƒ‘AŽé±(l*Žü@¦¹Ç !Ã3²³H†‘Ï[ªÌF`›±¼¯s„|‘Fîd|ÍWëÖ¬tw)Ä’ò&|Ûz·1&”Éʘu_û猜-’ã;ÿpŽýVâ:KÞNÕ°Ÿèóyå/³¡Íä î5‰š KÖ»$ªÄ ©‚5«ó}™³ê ËO(¤MyiC××EìHážüË…ËKªr³]¿]¹uiQ¥©æšÿè¨èìhÆ'2UB¾n ­¨“l$H|tQI¦îÚ“ûLµqܧÍ=Ï÷­ügÛ•àŸ[^ß¶)Y¢}ë]ªQR\*‹p|m1Ò/)Ę:‰u†,tºÐ¦Òxt‰ÅPÞtµ vƒŒPg³¤&Þ©áõh…Õùrü™ÒL‰”§£lŒ4ø?cD,ŠÏóÈÒJPÔ1åÖ#d쑇ŒÒrß§~ÍðuÒŠ[òúÖ­,c}çÃøŠ¥½‡‘V< ±EV¦<ªˆ¢m1ºõ|'v¬s‚ E{u¿®ª(¼Y,í5 ß÷ Hæ;ˆ'áÏ=š“7„¼ÊbRÞµ%ö$z ¼¬Ts—4ñ4ݧ)ƒe'Ø0©E¶Lr^ªƒÊ) +ki¿¼ÿð‹‘î{/µ'•3GCë––_„Œ¬îK²õtµgX–B|]…ù²ž5©¶J•ÓöÎ*Võ¦Ÿ½FJãU.E“•‡_<×-jIöt—ÉÃAÈ—ï{¥‰ÑÒ!«hÚ¶Í2vO“˜u²Dnå·.V„L ¬-5Ø&“g®ÅÚ‚@I"~8å¿IÖ#ÃP”ã &$ëal×@%•é sIýÜ!1 ‰Ÿ¿îü2Žûÿ »’eWq%øKÇÆ6bÙû¾¯?Y @Œq¿þi,©0øDx™f’jÈÊ„;ÝQŽwIÔNa0~…8U’Pï’ë£U¢šÀ}"F;ÀãH'±ã$ïÓ–æFZ:©Ê¹\á†+µã­>3r«wÔ™yêi¯ÜHùK¬Û¡¡ø«þª¹Ðmä©g©‰“a7|]»KQS¦dò‹ÿ-3þùÅÿJïñÏ—ž‹Ö¿‡cÞN¼ÓÍ÷Þ0Ö¦ƒÓ3‘úþ™ äñ 8=uL£‡2åyÒeV=,Õ¾ñ1v‰í6Êl¢Yæ7+B>±Ï¹q£ß—9}w‡ÿùº,æïNû?ÇZ¶ÿ¬ãŠzAÕ·)?ÍV†`¬åd¤|‹Ã1/GʃÂ{]Œ”Ûý ±Mƒ%g…wˆ.â"À|KÓB®!Œcd(\mdúeTÙOý8.ŽÄl‘äj¥Ý©ÿŸ[Ãu¦ÔÀð°Và²^ Gw©¶ØGV@ì¼BŠ?kµn7Püãøù!`ád)Ò&¤øÇÈ!áÃ׫ZwØ;âçIDmî’Š¨‡Áq¯Ã@&”U½®Ù}1Ýê|”‰•îÕÎ ²Š_ßG}M5ŽS×é›jƲÆZâøÓ7©´ŠÌµL Ë7èƒñ³•6h—w©ø"GH/Ö®5‘õ3ZÚz˜ê¯`äÈù,žÓ:¡^§)ÆoÎÇíüÓümÜv®8¹Ì‹u…ÜÇ´äç´B®™*ºBÿ“|Ó£ûDa]"—ò¿ÿ„ƒOÓ;ey¾B '¿Quo¬gʲyîBÞ?3ÖHeûœéœ }LåDÊ‹¾’8XCHÐ7N¹µsH–)J›¶cðŒäR^žò¯(§:‡† ¹!t\u§|(¡rB‚>øfÞ:ÛÝ[šË ½Áw‰|Öçåµïë{_Qrá7¸t¾¶F‚>ø‰áàžú‚2 úàf¥Àä*×¾)–å ŒÅ4P÷X—ºÎsž»m.œ}²äóy¶ÛPs¥é„‘aù—ÚNÛ6äòü9|tÞóA‡ô¦œ®7Ù¥Vî•i»#äóµP”.æ×ÙŠÏþt¶$™¡Ùª×¤m¹™ˆŸýõi5ÂÓ´œš®j„ŒŽÎÛ”Š½˜û:Ë€Hf`V¦RxÓò˜YºÕ¼ß*|ö$”²S¦òÚ›'G|ç`Æ”èÕÒÑ¢©r·qЛƒQ)ÍóLS™Ìñæpïõ£·Kå&­wù4í¦ŠWͪˠ›~N¥Ù•äB4oá¼$ôñYA¡23Oà ‰Ž­pàNË[ß°b1¤¢Üþ9OéÐd"X!¢#Ó“ÚÞä$a¦Ô–Ääq¨r™&–,¢ã¶Qˆëƒq6«õ§ßíˆ3Ér‡})0½øŸÍç /’¿ÛýÝv[ƒ6¸U8à#kò:~vnxšÅ¶VÂ?ûøP+k^Ò]þ…aoà!ÔóQÈRï6J6fÜSŸUx+ ëà®ßõÖÓÖåY‘"dt©ªJýò”œ õÛ7ÕØ’ƒKŸyFªŸHoÅÉí R«Ç0‹°ZR1*îBÂèS =;¥‚åkëFMã$ìÿ±1ŽÍ¤Uòå³Þäþ ±öùpœ ºj'oºù³?.œ¼?·’BÈ'oíùNÔÂq*4<«œ¼eŽö†<§Â"ƒ–Ù}Í2¹ÒšV+]ºBtưÎv¦u¶)|ïI/ÿ1 Fy⊨?Öy\cm“—7ÅÖ§3x—ÆI å”™u›S+3Oêç¯/Êáòi‚ØHœœx‚šé å.8’Æ ùˆÚ¨“ÉU “Ôò‘LÖ$™¬ø –Ÿ´¬L–Ø™¬8I~ñv¹ùù¹æ_l!ÿ‚ü|.勼a¤:ûŸ¿þ.’TûŒcV;dðk9X+}`*ƒ¬Öm³$` ¯ÿýÏÖ+]§Wo'©=pÀÿ'ÏîÂ&=¤ @æ…xøÅÿtUmr`vk?£…)ƒê¼ÉÁ‘”„<\Ë+§¥ã•+Zû„‘÷3Y'Ñl=-ÝúI~âkB¢«çy¿VfpEä«‚ô¸4 !¿(H»÷Ó"£Ïš%Ó5K¹Óp„¼TÞsÖ äó\ˆ²RýC¸¢ä#›„|NÙ×·þ%_ýc#¶!dä¤ 9ÊTÊ9ªbÓ¾s„|œw/ǽ|ö'®±’ÇÛ.åºÙÀ–le'æJ×o±Ï]º!¤Y5«B­ÉFˆ²-&–Cߨ"£`’£´ªgMeþîÞd~ÇбmÇÞä@1Þ{ÁRã†*O.ß:ŒÄ[˜¶iD¹dBFá@–yšZÝ-…Ë“,2t…·ã¨Z1ž§ûyî³Ø°|£®þm‘/¨–šV¡UËr rn‹Œ?E{x#ú=í!!X[j9.rJÞmá+¾EßjÀ£±;âi¨Pû÷Œ’Їˆ4T¼óƒç¹½~ó¼`yæyÁ°çAÚò§ž!OÈËÜêû £J˜n¹±n]A¡nn’™Õ{BÈG0I`É× eK»ËÀòö$­Gõ¸,2Kß‹ Xÿ•µ¤Ó²L¸`dìKÕ§ný˜”VrÁWD †QºR¹¼öe™sàòXdrÑ% bôÈ­`²-¿R{T3’ X ¿ûÕfVÎÓSšúÕ&9vn©«@­ò@õo]òañè¤N6%Ò5v!g"][?çc™bäìî¬í±‘imײ<œ=èÜÚ™NÊ›ukÒ¡-ñÅŽÓáZ©“Íñq]H~Öî…“ ª·t›¼ç Ü@”O¯óJî˜Nùñ˜QàÎfgæŠmŠÎ®ÊDBVï—õع¢ˆ’ûíè÷QÖ™ö¢r¿D#õ`¡–q[Ú¾Â_Ñ-¼5µØÙÔÃ<Ó°üŒƒ‰ @%²J‡µ‡Õæî«†6ðPóɪn×-V†{à‚¤&þT6U¶K•ùB’ ªmTNè0¶e¾ª£CbT«,K¡Vm‘à㦼áÌþÞöKY3¾ Búñ‘¢tL·e¯—vL‹„i$sLjŽ9×YÖQŠÏ`8ÝÈ ¿—œ±nëš5EÈLáÎENelÇS|E±¢Tr¶q«¤Þó´’ëäù˽Üûµá>fr. Me´`ÀûƽS¹†rˆ܄¼oË 3ãrŠAÆïmDÞ÷ƒl°ozÞ÷¹·pŽÈýqœc8›!ÜŸ_ù€ ðIà£ñWçy îc/7C¿2¼¾¸tõÍxäwE> E^Î)n~ï¸Ç—w‰j·&ˆ—îäÊ;¼ÛY(*Eîɱ£êªº·/׺”/þ]:fÚ±^ P4M5·-x²ÀKâè2Þ ù)rO.å§ê|èú²ùD¾$º¸&™UݼÕB¾p‹“Ó¾o‹ÃÙã3¡ªÚU᳓“ˆº}7¡¨”E&À|É]%J¯É{׋ßùŸ‹I±€“°ƒÞ.Z$)¥ Ÿßz‡#åp=ê(‡“èûþ–îFí»"˲Á50IHºÿWÚ„×"'HxCÛ‹N¾Ì›k<âm/ôÿÄÖ¢øºÔ¿tf”Ó.z7nN¢ë±xÑ4TÀX<‰_Ë~,žxzþ§Žœj6ú¥) S#¹U¾÷”Áý|íÌ\=f¢]Í: èõAq³uÃ÷´| „Œ®H:H:$ú…¤3—³¤{ ›BD¾Í’*Ú;FÞχ–hêÇIè}ðÙŠôI@¥ÇÊÌòÎ M„*=. Õ¨Ör@¥×ª6¥›R4†MbéßO7 dšX4ç븄JKžU„«áä![UCLÓ-,™ÆñUäðm>"Ôš±ãMµÕNl86„4‚6ÿéÔ¸¶ÍÛLž]ÕBZ•Å?YC¥œu_S×@³Èçy»g”G…åîq°œÃZ”»Z üþê¯CÞOš«á*Æê²saX@{7ÚòNÛS!U›µØÒlñšv”›¯®Uî{9—;BF—f>¤ÄßÍþºòÚì”Ã-òÚìχôéÂéqj¨ßbÛÇ&õÇ$'m)®êÆå ]kòH¾7.ÿÎ'_—µðïÒU‰ž[#9øŠŸ¿ÉA€ñüù2´ƒE^QVeh×þ¼ÂÚ£î.ÜùçýzhI©åsØ;?˜ž¶ëR—²j­á~ Îж2­XE*¡Õamà§ I%¦Ì¢ž‘"ª”íèÿg„l×ÌWlÎÞÎõÊDÏî‡À¼®©ÃÊ{_ {>.`õ4—Š¥Ïç/0ì†Ï_ü}|bþ|„î‚öÄÄÃöÄóõEöFôA{"p¥0ó½«ï¨Î„/…=ãéÞÍzŒtbS?w)>z8Cp±ì2á^&|ÌÍv:)*¹×l·È‡+žd…ü‚u–²sš­YÃs|Ìg¨înÔÈäÃYYÇV'Fh‘¯pU4-x‰¤k¹Ï3>f|éu<#rq—ä}—«÷FaU<ø>¨k·´'yí³\ýýLÐX›ÞL«+—ë¬üŒö!#ÏRÉkë¦&DÍæL”ùðŽ0îÚ%R~ cš „´ŠFÈÇ!e$0´s‹¯èu1X¶W#ÄK¯ŸonÁ`y}# +%z(ž„g ´¡Ià%wI³^”뛆|#ä©—Ä6î£ðMÆWt¥«LRGÔ#Ûœì 98DÜF |ùOÝFà­{=/Týõš,SchŸ½^—;Ô#¯ë4íøæ[]Ÿ &ôÖ&”çœåI®ý§´{ äG¯äÓKœ(«Á™ÄߣßaçÿÒ>óÑoüs TÔVNÞyº®b…UyÛ»ZoÆ=Íø7½.ò:ð ¿'?ûtbÌGªq„Ú=yîb0eÿZ±j÷ÈÇ÷uɯ6ñóûºä›¡÷¸_™õ3g£Ìö 7PHR3¬`Fö1W=[.–!øÛ4m}&¿Í̯uñóÛºÔÊ… ŸýޤCFÛÈ]dnçÞ!_Ç!;†¥äTÇF>V÷Sd_6Ã0¬Ž‹•µëRvó+XáV°b+‡¥n|ίÿè*‡[×qÝ(3èÉ—ÂbÜÀò±M±Éý ïgLòqLZ¹cV[xLOØT9¨påt>,¢©×}drIÏšžß»w) ?ŸBùk÷ôç3O™BCþNn‡œ+ô`c³oy²3[‘˜óRQüö#£PçÇ9,òe0.FH`WjZÛ¦Óf| ö¨V$$5ã:h'äþ­nø.äêžå›@&$úcEÒ#”É—qpÓæƒc>?ž¦-ʧ)ön¢p—^§ÀŸR=,{#sHÿ4ýú^¨{rf×Vå5P²Èórº¢0Á+!‘2wöÙòZÔ«"9Š%¸†‹Ò‹šF^Ô!ùR7š@§"]'¾•!#? dô×´|© ~ƒÚñC f”³²Ý:¥3ßDã¯Ýi@,ÁŒ‡f{›µ»`øŠ¦Ž~ÿû×hY)nEלßÌ9UY¤*o¦ômƒt aí´Òòp?U¡xÛlAÛ2ùÈç½`¾K¡ÊP Õ7=õAI3)fvƨ('(‘q+õm²eŽm]NGŒŒ¼F_Q¹Äx›¦l\&|öÇ©À“öLò¼¯æŸ<ɸ’bäë\à‰öû¼=’x*û‰ÀÓrvI.žT%®AÈ‹þ™ Y@¯€$®ÂiHªMsWêÄ…ÉÁö@/µFÝ·.#69B޽’cHëâ¯LCHß±v$"¹„E±÷r‘DÈGàC_9#zϯ#Ø([d°(—VYNóÖ0^õB†ê©v„A~Æù”sÏ"J‚Ikª*?kªZõ $A-’„‹HíÎþÞÄ4:à ‹L|™Ã0j•|ì¬[;¯ÝNšükW)ãl‚h1 &MœÕ‹- 0149ŸC›$÷ž†ÊÖS>ï TŽHT9KC–5³;™xBz.bá$µõœM‘oPNO|9è /ì}š§¾ë›1uŠDi5´Q—ô.¶þÝ·ò¬ùE ÍQ¡ÀQ),¶¡5âœkŽÊ:% ¹Ü퉚±ö€Œ.ÚY×0É*7/;ÉJQlœ§e‰O¬¦Õ„h¶ö‡+z›šµ(sj"$y~5Ol¹?æóÓ€U³©µ‰sÀ¦&¡;„ü£Æh[÷.·½^ó1…Òbãf“NgôµË[}Š$äbeR›¬"=ÁúêŽ[¦™‡/ÆNe]ø˜‘chª‚aÏ-»¢hWB><ŸÙ9Ñï;m[Õ{#$.[;ž‰¯l-Wh&äøŒE¹yøÆi’|é×+V­Û=’ŸŸïvº°Ç&??H‰*`J¸)s8æí¦ÄÈò SÂqi,2ºÔÚÉ"MƒàÑGwÆg2²d5¤±IÀ9÷üO)k‹á]  ¬¬ÐÌÍŒ º.Û4"dä‘uiô8‹­+äkºb‰W=,ÌìxÊ‹1eM…O„´óJÙJäŠ/Ø9½©Ö¸³¼^Þ œ=:”/Lh¥Ž™5lœË!¤·3Ó–ˆ:b•õ,GŒŒ‚Ù kÈȵ!c›ù;}qš&Žü(ë*χóùY’{ÜN…/%?~N ¶kÆÞ}samòó¸nÅŽZeŽù¼Vc’WÖ@B‘ }n•PÔN"¯¥iY·ïÞÏ—YBÙÒ´¨'Þ1„¼‡:î&j³¡î'.ÑQûY¸ß¶4wBÅHW…Õ’±Wç)GHÐÞÈr§ËØæû²òtr“E¾<+,HgTf +­EÆhÂÅ®É-ßò|5B’ÀZÄÁð,•œt¾"dâÒí´PIŠþŽÒ1êùÌîÎÿ™ÏÛüQ™ù,2Ø;|›ÌØ%§WnnŸm L:(Œ]¦…eºÉ¼Îš­Y\­ØA#€*9(“LîY¶ÕÓ¼´ Æg©Ó¾“Gä*:É· CŸ:¥ÒÏÔŠÎÈ”jçe±W5¾«·×¥·+Œ)&?ߺ§»êžÂ‹’|ªQ' ¨¨I0ðpÚIa¹¿ý 4í£?ã$xÀµH:Éxmž©ó ³ÈÇgH"k¶°ÌÕ"-òù i®ÆÈ¡™ !Š¿_‹¢Ý«1#X n‡ikUz«‹Wö™˜ØÖjGé.ÆLîàGÈ@üDÅfûdDk“Û•,’¼ö¦ÙöÜŸ=NǬœ©ªÿò¦ñÛç æbßú¦KøDnë ¸ 2À¿Ü"±ë³é(P¾§SUÁr{^ZÈ`•«Á:‡|ýÆÀ€³ÇH FWõê$ÃuJó+’€Îî*õV2·®Ó\®Ž°ÙÜgY[©·Èmyîk»IH|GyÞ©ô£ÉàäoL‘o™¦ÈFc¥ö1CÕŒe _\Hþ6jâ´QQ¼w§`Ÿ„Ê׈LϵÐSKy1ñÊ×§4\/"”Üo—ªßµQývOó~í‰8âÍ;¤Jÿ÷×9wZÁ´‰-0à”Ü£ïÝ}¿Íß—òwÚ†‰Éýñeœ2¥tÑ’@üù¬Ù@-2A’ÎÿrX£š Èü¸ER{17kˆ›e‘W5SÕá†+ DkÍø´¾I®×(<£U–Í…•åì÷œƒ`r?84+Ê€žâï¸Ò-d‚ÇÕ°{â{åþO‚/N bÙ‘ ÖåÕäCÊk„Œ®ÒÎÝï†a÷Ÿ¿vŒÁøk &cðº\7„ ÌwÔ:«È‹óÔåJŸ{ÂW壬¨m½¸ØÚšõ|:œ=†ñi3 ¯0¸Hkù¯×N€C–9Ñï™uíÆk'„Làì%X>ѽhxÏœ~}]÷ì1ý:‰Ž_±7œjªF%»»}ÈÛñ|UâË9Ò’!äÉ:èEyßßíÿ »²eWAmûK+1ûýœª}?@±CT¨óõ—¦IÖÎó(¢H3Û1ºªC`Â#óòkêîw=æŽöziF€¼åg#,˜Ø´£AŸÞ™¾¦ë,³ž’ óQ÷5|£ROõIØÑÏxÈgŽtHŠ7¹N+P|eÊñÄ+Ì)í¬%– ËT…Ðzº=&Ò&«á|ú¨úcᤳÁé1‰q§šêuCõ·vUö} ¬ ÁÈÍz×qðèZÉZI _ÿRdN@Ìà®ï¥8[€Þr¨»8C5«ëH~ w@ùn£MT ½›ê:„4gÒ4AcËïÆJQä{ Ðg”¨Ê&‹ÎÓÑéY_!âãº÷mDÌ{ˆãh­1×Èb™J8ÒïtLðY¯@Ý„zÞM¤fе% ¡—Hhé 7“IøAz4ÓÓžº&þêšÃ;C´KÖc"'hñN*¹×ý¦7‰·SV…‰ºËœD )8ê8>¥¨ÖC¦×óްÍ8Ã1o›ý¹âœË* ¡°Èè„÷“åØz©¾ŽtÑ®}ßýq®AòV³R|áŽ5HeñABÁEÅ$IÛ£¾ÈHüi:Üݨ“”lŽÈçCrœSô”€úýEOô«Š×?(z¨Èâ[èx¥é„.gcfwøþxR—|kբϸêr:yO_€=ÉÜ®:=¡M×Häß´>ç«1¤[·ØÚé‘E´Jâmoû–$Ëñ–lahÝ; ¢uŒyÁF+ÖŸ“`q+@>2]¯|ÍʺhkÜ~2õç\gßôËõ‡ÜᘯLH /¤µ÷RÃ7*s$õ©ÔÝ´ç¡î.ÌüÏ»óÛŸßÛåÎo‘¿9¿ùÅý”³j×ø ß]jy󢉛5*$ƒÐn9묡˜÷,oȹ%â ìÕ#%1}bÝw™GÚ+N*c²Y£‚å{ŠNÐ&´ýBTrnY‰³6¶ž)}Û5¼S7ä=æ=ñZÈÜ6>ç#fÆ­¸‹ãšã½†ïþ¼ŽÄçgõä7”;`=—©ë«g´ïÈ2:•m”Þ†Wò4óÑ€A!¾o ¤–j¬g½|àRºY{•´Oê GÆaå µý$Û´11@h4`Û!zíõÔ¨¦èoqzÖÛGªN£9¡ü¤—ûg®Ní/öìô¬Dâ…=Ñ[¯ôÁ¬í=2BèÓ1±æBœàެVÑê4ê ØÏÄËA*„Iˆ|˼§Ås :ëAß"D»Ö €Ì:@Z/5Øà‘ª"鄺½mg$Úû}ÙÔØä-ï '”6Iµ_?ÔyÿZ·§—OTV†·°ötx¤[¶m7RŽùŒl„á¢ï64(U $Ú=òº‰˵i¼Ûa®x:so9°%^J~RúÚ$ãpæ>å{+¤–öÞojµ\ôcÌÜß<Äõù¸Æ1Ÿç`Pã±ÃµÌÔ)ìΫݱk¡ã¸]º8f2 ¤åˆj}^QŸÈ¥-R~Õ/!Òj„ewÿùåÄ7aîè ¤–šÏ…ɱ‘«L2gsLÏ0ÇîoÝü$h$¯’©uœã˜Å—@‰ 'mõŠb¸ó~2™“êƒö€eÍz*²øÚ¸™dYS‹ b6a-ïlo—©^¢ÃpÏ[Óþü_Þp¦Vm»D3'Ó±ˆ gÔ3½ñnTmYÀ¯éˆúk[,a.ïs9|T4´c!úaCyÍÚM…“9˜hÓLÓ<­pL×0ñ÷;Ãmñã„ï§Š¦™O*/oH¥‘±µ×#¿rY ±Ð»ÌU4Þ¹‰DÆrcå¶WènúDÖ¥5ÿü—U<ìRKÍ{h’SÅÎÏ™©Ï*]×€¢ÿýmgþõ‹n©#ˆ·×½üÀ;åÞ]Yêì¸>ß5<<ÞÄz†s;#Óðø+Í,µÞO7š(í¢ïå ÓÝé¬àÙÈÖLùéê^íÕÎ¥¤áñvs+Dqvs?~@~þ¤ '÷ Ë›Zì>"Þ2H‚WÖõùÝb®÷8fαç›Ô©×ÛÐ~š”ñ y@þ}OqâÒo”nà ö(~iþ=¼åãµÌý¤ëÒÆõ™µ¿üq\­OÓ ½<á"¯9§pk‚¶fŠ{óqϸòÿ›!'¡ÚÇ3€¼¾ûœÍ®ŸC[7¡9Ì#ï9 µ9ÒmÛtLÚÈG"ñµÙdã&îûB&‚gøïÏ %¦OOÏͰu»áÿOŽï#ꬻâÜ&îmˆÖÇ,¿ð_ò•Š8Ÿ !—‘ðž¨IDΘòqRmlmÓ*k®ÃaD¥â>zÁ¤ES{ TßúÝ8?@^¿h ™6²øîå?ÚÈÒ»—ß¹Ölê1Ú6ÏSr:ºòÃDëº(†pž—/ilà V×Å{óyù’üû2fÎÛçã§ÆbµH[Ï àµ÷ö®¾Iϧ¨7ˆŒ§we¨«í˜Ü©`,²¶x¤ãóg²ã²²iìUû>õ:äórŽåÛùúʈ̃âE™ë‚|T÷‰A©çïiì¤îS>ÿ¥îs³ø¬mÏ3mû2k¥²lÐY2UÉm1õøùÖJRzb›C¤š©çã‹Z’i#C‹¾G€LõwM`máu«-–£o@Æ4äbÆæŽë”·¡^0@ÞÒmè¯bSã^Uã¾5@Þ#ŸSí%b g6;ª}ZMùÈÔS|•EÏšAÛ-ƒc&cÜzvmKìŽÉ¸Â7z}PiUœ‘qGˆ,ã™Èvi£öô+ÁéIØm1Ž3¬ô©¨ú™Õ˜–È#U™–3„-3š±ìx³J4Ðý4ê5Å[ŸÞ1ÊáDáäø<Ÿ°èÕ#–LK{g¬ÖÛ~Èk.Œ‡}ÎÈÐfSÙQ€n.àѬ{· }‡LyÆU(²s³,¡ÈÞ#ï‚8\­úîÜQ S\À›æô³L×ñ’f®jÂù~š¥W†¤ÙÔµ]eV†ÔÝÅØˆ£•t‡3ÿe ¬ ¨‹u‘^;Çõ~‚^2¨§<›FRuŸ‚{€^SãΗ7!%{1>è¥ñk:ìˆú¹Ç1,÷|¾åÀ:g  Ul5J;ê7©­tq Òf¬}§NÏšµÀÇê>Ö!6ø»RUzû«»ý‘QHÆ,|:ŸVÁ@çx(ñÐÀ#R¾`=AZ!¦PW_äi…¼®çêÇrî"§ÆÑÌ{ê j=C؉ˆœz2Á1ŸÍ$qÛm¡Ãšq&•¯¬žÀq½ø¯­ËѯÔÃ/Söûú6ýF[=ׂÃ1}8Þ‘;y}­¡Ú‡yêU§)¥–ÂÅÅN—~ BoûB]«±{´^ ËP1MlkÛÓ¨ŒžºŠE=íS†:Ó2 ¥k1cex6÷؃V¦æØ?¦U/©.æeNR…8ÖëöUßÖÔÇd%µ/è×:Ó€Z…ûxkKjÖ¹2Ýn!m/ÚÎüϧàX·®( £•ŒÙöp=;î66±$6L)‘u¼†—ÀÒÜ£gyˆòyÖNŠýwÊõßEä+£N‚š¨{£/Å&ÍÓë&*&¤5R¾EE¡bBú÷ò-»5 ÒP‚HÔ,PF³Žyû®Y á˜÷\7ʇ ´e7™ m7fñóórU,9o׆ô+çxÈËY?»n_}2aSá "2ËÖ8jóîs§·õÚIY|)»6ª@ñ9߉Xݪ7ÙY)‡åØò_>"¬‘·ï4†sÆã_I)OÏyº,G+)ë^; OåÐ`w¼¨CúI¢ ,÷Kω`3;Yde#.5LMõÀ¶5/0 È[ìá­}=‚=™´YÝùL@Þ³b/¡©ó…ã‘ ùÈ‘®Ä£mÚ±“ª™à¿?AV‰¤¨®áÅ˱Ëá@wz² ÝŒi¾¦FŽ‚/-†3ïz$ÿçIöíq£ÿžãj{¡—\ÅÒÅ®}oÊZ`!!4õHšz1»?µ¦ëåŠ ´øZ·2°øþ¯ÍwÚbÜ#€F>ONë&ÀÐËZÞ°´?ŸßëA¨B+Oÿ~æ ØçÆïøHÇ!þû‰kÞ7;õmµhK=ØlÅÏåç¤N¼ÕÔ³JôÚS[V€Œghårã”:½æAA4 ‹ KdC#$†FúpÌÛ/ÔQñ9/ßIúò®l¼þ£+[1€¼¦JE»—,—Ú7ÅyŸ³x®uµ—ᤪŽcòšû’>‹Nõ«Nÿ^@µŒ:´oO&2Ð.Ë.ò–—´¹(ÆŽµÏnásÞ3ï˜Àò¯ïn|dÝøN€ƒšàÑŽ¶Á÷oä3»;ÝǤK=,D/=Þä+ëÈð²ëFëTë ß½LMæ£{v"äʘ€3ïÛÜq·—;ªLÊýô‘²[)ØT SRr´šKÔøð]ƒšŽÊi—ðƒ^  b¥{4 Q­+†ï¹Eb$'¼ØYKí{Íj†ŸÔÕ^šfëÚ0º ë0t†d¶:½V½<''DãdA‰zÈp‹ÏtyÌ'¤çSt>&9ÓQß8[Úx·Ôð¿¿Y‚^ÛaL¿Ðîô {lì4D†c$\#gAw‚ý¡CæºÛU ‘§-J%À²!Iãᘠ‚}Œö"oß»Ó}þÞýدòC÷£eROÝùA¶×dY9¥Fž?C]üRKr¬-šãÌ—§bw[­_iصgUU5«2O¹˜'³¤K Å;r³HvFÞ’‰ýÕ"5[ ÷ÈÆ"w€LÁ‘Ö×øh7µ¶ M§O"cÚ­êBt½Ã+®& ¯ÈW×4Þh5!΃pµI€,AR ‹¤®œùŸOÐÑ@×3ô’ž7@›D‡¹êÕ¡Y·”}#óAõ%_áz3„I‚»%Žòh”"S(Ö"ÔOÚ ù¿ »5Jòû¢·¨L§nާã?¶|¨µ\z¶˜Ü‡VáÐ1¡@Î%놺]H3(X¤Whk$äV·»àó±p€<å5 rPCªCÌ=@tÍ7Ä™¬ŽzÈ[6§¾L`hǶÒS* @Þß‘›Aâ7d¬²ª»ÑM^ÆÍB° Ÿ™¨ºGîq½LÈ‘¯Ò†SÔˆ£îeöé}ùü6ìÑfóTÙÿ‰E^VÓÜ܆nëæZuBí2•ÿMmºz¡¢V{€3B¯f•˜Åß„gíØŒvmºö~&³L´õÚïÆ‘õ5|³LÔ³„†ê±×3,S×ÚV­»R]}ÔðK™e¡Ä…ò0ã Ò OÏú„PƒµP=v]AèËBÿ:7Üù.Ça.rœ?A¡­ß~zçý{Ž^Á|MÑ£þûóœvw H&í΀|¥¬{,½V‡>ëúõY~’&6aš•§ç,O¢¦™ ÕN“ÖR²œO4¥«¥)]h3W{³ÝÞ!ˆ» .Œ‡ÁCä)W{ûˆ¤ÁÂ/®¸‡,'í©vCŽ>þ{ñiX-ÏÈŒ˜8°ï›¦Êš<€LäVÐÕyLt£¤>âîH=ñ–=Ú­%×ìÐ׌ #ÎgñF³gœEâÙ”zC£·óÍå ‚iSL"Ò¦7ºƒ¤¦)uw¬^íÊð>M ¯ÈÖz´cÁ‚ÖG@ïçÒdÏ¥Ž¤7ÊÏ%WpàN>Ùs‰¦YÊÎ%›t¯=»Š+Po‘„È"—‚Ä>L£dNÛ1>çó¬'`S•^е[Çôîé\rd¡Ý gB[¬ˆ ˆ,¾s«Ç»#ëòÿÌ­®&€üÀ­nÔ`2nõ€üP&mºüi*“ÖÈò×$Ãì¥ÛÏolJú~g ¹ßOc_šUvº]~i{´jZ ¡Þ”Lcf-6lÐMÿ·™úØT‹k)k5¢Ðõ*MÔE{€)Ì}KvcLo|[¸Ñ¯3?¶d¬*LúufÉùPѺev]Øq6|¥P{‚…"°}¬8ÈÛ%%s´¨ʼny·^?dä\Ýqñ»¿ vJÝeCé„›2Ð¥—Zaܶ=*‡›”tA ïÄ7°¹ae¤D>e¸Moh]Íig'dþ®–©Ï©¼óxÖEû3;Ø3Y;Ðè%ÍàË"D<½¿ßÎdPqħ',o^oØÒÓªõ¡£ÌÁb9)1–uÓøBß_ÎÈx‚Y¤tÎçšðò¯“²eíìº $$éù vl­tFÕA{Ä39ON]‹bkó%]sÓøyl8=iæèw?‚X½BfïnÞh#ÉÓßäp¨Ê–tZ×p2ä'Íœ0Kv> í 2ij3á½–Ô,©O93ˆÌ‚íÎvÍÔràD¢3€|¾Ïç,…¾¸bú-ϧC,ÐÔ+¹£¼ k)ò ¦ «©½nL7©·iæøÝo-ÞÖ‡íÆøF÷ÄZûýŸ-±1¤ ÇÄö ÅØE~?ë+:›ö`}}pe¬‡oužK/ÿi<})¹ìg€¼¥½Ö•ßÕˆ 4Š õ×üû[þ2’ ¶Vî`L ˆ‡]œ?bp÷¿¿¦"»³Ö/ÇËÞ-åÿg~Å)yˆLdœÇç´:‰˜w15Áò?ѤÄBó“cøšÅñÓ¯wíS´O¦!®Rw,uã¶+í»:òçzd «k†kSÕ-ÍxT¢Ü!òõ~=k§=ß YøôÇu†.Ä.ž0üŸî£qÆ{S. @Þ®syaÕ½5×;‰,ÝÀ«N4· ïúŠZ9Pk\~Õ%ðŸ8ÃFÎÏØÿAa›s ‘ÒFxg×¹aiðDÛ˜¥íí’8ƒVQ#L®!v‘´·ÿŒÀêôžÅ"š`±<Ï’ >XËfÛ&Ùë"i„׳2Ø!벌‚ms |iUøI=ðF¶ÇLt Y›Á5aè(žÕ™v2z$íXÉ%/ @Þ}»BeŠSRYB!×üL³½Þuðæ—ï>†5ÿ|&ž¿|ÜÆ½#ë2ÏTõËÎRfi銞œOðFI$€¼_®žÃ1¾UΧÐþ&Dæ—ki>ù¼”2ˆËó¿ûÛÍlÅçÙ7ŸÈÞï e¨1ÿâ íhÌ(?#oIç6ç-…Ñbä cBàÞcó6+} ¥Z  ?õL]ùŠO‡}d–ÊÃFò·®Ûf©8“Êaìl+JZÞ`ˆ|\j!Æx]¥ÎQ£Í·@(äí§¨ÑJ†`ƒ·‹¨+OQ£"m«øÏÆ‚lœVÍçrð6ÄÁRMQ§Åí¾»B*osY òönÏ3c¥/UüŸÑO‘:š­‘„VpÌÇ'{ž){ŸMq¿bgº™‡ò·)ejF<„&ejiÃ>(ScP<Ä#oO×Òhá>ÏΉ=4ލÛÞûïEqÖn­ä×ÂÀ˲Õ@ÞÞu_5ߤ%uÒßú+J똽É9ßYbVi«ñLm8F6DçWŠ{óuæˆÇ½©ˆîÍ«€|€(‡™Ï¡ªW\ÑXxW¼€Ìˆ)}³ž>-Ë£cÈgÌoº„ƒ‘¬9„Z£-@ Á¯UdÖȺ¦MÝù‘³&hÖuù%LÇpšÏ3¡ Þ* gþ DlA•:¸åŒæCh–РÚvðɉPQAè-I°:ãŠhšŸ½Gr‡Ð»ï­®´£=êÕÕ¥ìJQžþëòÈü²Erö¸m¸NÞ ¼@hþ®¢YfE½ŽK1ч\ð뚨M™é‚O‘ö¿e9õÉbůìµ e¯Ç;ôŸ5±M¤Úý×íMlÄi2æ ÐtXCGbC;ÞvMx£ûÄw?¢ß÷º'ÖH`Ÿ×~tU"u€ã°C_©0‰ÉT¶1/ ‘&‰ÂJ 2œê[ãQ/X¶oXÀÍU¿Fm½v‡c>¼­^ŵª”ç'pȘ¿Ra:ÚÛÿIP;q>µù ñ¨pŽi¥},·jÈâÂÒÔ¹áéIfê¿ßV9ÜÙÿ‚k^Ð`¿ÎÔs‘ÿ»F%¡÷'IÒ ëÊm{{ww R.š”tÈ„*ÝìN5¦¡„”ñFÛÒ±»¸n·l¤Ý[!à˜ ¤TH8f~BêÝ!¸Î­W¡ììÙ<,¡¹:à RýÏ"ÚÓ ‹XxåëÓ†º®K¡|Ä M…Ž´Øã~ÇlæLÊà!¾<›‡GúÖ V¡uj+²8ó_ÚT¶ëªë©¨:—±,!4óÕL&Ea¦I=_YÓDà?µåT¦îH=Þ±N „¼,å zPW¾Û³ñuñiö]ú‡0pr¿.ÃÀë©T"o‚»Twd+Ã0ð9¸Ëð ùxîêB€V8ÁYI„‡}Wn­ŠÞ¸OËÒÆ#üTk*Z ¥C;c2ö,¤*½¿]Í;è¬ÂjX÷4¡aÉ.H·²mÛ2¦)Ü1¦æžK2wCH:E•^'½Õ¸„tÞä&M!-Ò²Q©o¤»{q'j€,‚KW{¥nQz[ñDIúÊu ëŒÄ[0Ec_¹qAìb‹‰t“Á´OúÊßø&…F†ú½,ØÒIŽÈBCš÷AuOóݹVŽ!˜…Ð]ÒÝl¯¯Æ‘¹kÞƒ¶ÝãªKô_½ b‹ÝtQ°^† iÚÝlÔRµ3Ý9Þƒ¥bD¢ÿê®/§>»òzP«d 5Á ú“ÔA0Z¿óŸ¥bâú;ÿ‡ÔA_%]ߥ:8æ#Q6MútÔ‹ÏÁ­‰½Àêý1+Ù…B»¶¤Õ~,ya iŠúàL?˜BœSÇ,~âóÓbIák¾®ER±$¼}ŠZ(ª …ßß?ÉN òö^¤£‹ÈÒrž,v„¾#A9Oöõõr¿>ò‡rÿÝò‡r¿>2—äëºINSë¹u2: .ÒdK®zÖJ‰$@ÞÞwÇ\ÉÓÆ7:·VN±G¹tÕÄY}Œ “:e[…K^¯d/¥yç$!FtLzNŒýYžw»Ÿïq5a¿ã²DWÕp¬††õtDʪ" Ÿïû}5û„¢<‡,¢n¥¹fÌúD”šÎ _ŸÝ)¤Ý©€¼ÿ,Ú±y)ÚE|÷{".bŒeßH¤ùm2;µ…|\U— ÷ ì+¿@ª7š6Ïq%ç§€vm»ÊÕt4[ Ǽ§<⾨Y¨íÞÌ}@>t§:Ï é‘·Ë„ppO³Sßè[BøŒü!!g©øGB8~Íâç„°ç;÷Èë„p8“³¯$`|ºß â$–´d§þÖ3¡×ÐųîûÜýÞ˜2Ý?(›JIò¢ŒK»æŒdR¦íSIzƒŽ¸\7W*’eïAèÎK‰‘u<ŽyÈÛgä6×3‡È{ÚÈ¥–½:üÌgoÿí¢Q+—b¯|?¿C&g!ù×È•UK„/;rÈ`¥»ÓFïb}Ú,‹ô¶¢C>.2Óý|&}¸>0`½}®,j9 È xäu`€Ç§ßéUãš;E»æX”è„ Å¥¹Žô45RÊë˜e˜Ïû‘›gì)KZò#"ÏåQ ¬~tÍ‘·‹°z#†°’c{e°½½v¸²½'1ÄùÌMkømZòІ¥ 7lÒ^X·äîž!Û#Ó ¾cNU6ØŠ¨räzŒ6˜iÒw‰x¬lÚí¨ö}çRl…týKiS®ù:6Xݯe÷´äÊg­¶¶ +@>¼UYÚZv}ÎoõvìRnðéù‡6—¶¹di{å¹Í…¤m.Y"¨zns‘ ÍÅ!Ó†˜Î§£wõAQ}Tù©xì‚7Êô•Ä!?4ÄSCŒC~hˆ!§†‡,’ÛÐ1 èª4ÞÏkßoœcVhKð F¨;.é…ÂÔ!X.5õGˆ3d·”ÌÝæLÖº3G›Üq©DìŸh{ÛÂR %K¡þü ï9!ÜG·˜´ÿmÒщ’2Ž+ä ¶ãTKæ lìkr¬"Œy?!=ËßÀrù&0@Þ>"ÇqQ†Õwˆ´O×c¾=ýñ©Æ\QE2ÑfÂŽ.HÇ‚Ôi»úr]‡Lˆu^ !ÖmȤɂ ²ø€\4#ôﯔcÅÆC4ƒÜŽ«Pjçß±˜Èj;Ú2.*÷:ìâÐf‚Pα\Pw‚†¥ªòžjžjB—ÍzK¡&yl&Ÿ.xôý’¹·,çZoW ]–7è#äç´4–›þ1†öŽCh¡¸ñÐQÙ•ïÐÐ+}š¬jo|îÉC‹OP5YÕR'h¤«ÒÀ-Tµ¥É¾Ö#„6‡²î]JK¹rgm;Á•jÅ%=ÔVÝբúÏé´¬,±®ô«Å&3Y³³‰r‚žÍ,›ë'ühÔþ÷Ppq¼ØóZKŒæDùØfH[§o:´Ê‹5ººv×’6™zŒ RíCpS¯•u‡§G|¥'È¥&U”•0…„ñ0-€ùÿçª6¢ºÄPO2ɺ¶Ø‚·yÃ% ®Ú­€trµoÁݰD‹þŸ ïD“ºþ¿Þ#(Å9ôHs“Ý^ô¦úµzS…|«q5]ê ßK^Ewåþf©´r>¦âñØŽc(ÅiÅw²PRR\ò`ݓڳsp¤UÌ ²{l=ÿûǾ{gô¹ò»eE8ƒcÚYÒ¡‹l{”¾þÊ!Ÿ*Ì\¬»2Ñiе¦Ù=»¨$TF­$ cÞ.+ GSIØ-™ö6:¦e4«×iæ°ãVXi.f]IòéÜ|½¥:Å* njÚæ8çGõ¨œªº96 ·ObêdØøÑyO–g ÛD…˜˜È4¼Û›’–|êÅ^Ê]dÂwQ»®ç™ 5­—lôÈgŠÄ‰&6Ÿ^¤†NçYVچμONµÑnôd]ù¨Ö¹Ã^¹ÿ[MËæ<ó_¾À±Õ;KíÌa<¿RæÒ ÒA­I†Z´í}0´Ô¡òo2Q\­ß¨ô$j]@i•Ém»êÀª¾G‚µðý³ÇÅÇGáã¿ëÿxBšú˜û‘aoÜŸo%`^•b>¶nè[·K¡Ö]Ïîi1£µ&Zê7ñ½?a±míËß43ä¶ qcæç4 lޱ”{,füÞ¨wM~¤£S<ž‰(ü_3õž‡jA{yÒÒ¹¸HŽÓÉÖÕUð©ïÏ+¥ ¡ƒh$y÷~#ÇT¬tt)¸î½öȰÆÏª¦Å5ú:Ñ ­Ru{Q÷³2˜ö”11ÌìpÌÇ…¬'] 2 ˆ—Ø®s‚äN˜Xà˜O;Ÿ¶IÚžáœtCÕÒ£©²ø(ÿÉu¯ðgéõYýÓHAä÷»ø'SžAÕZupæ¿>“w2*ºx{~ƒ~#Læè;.Ô¶´gÓTµù°Ëqðú`õêë3 ·l˜êÎÍs*q;ô> ÊÛêPGª9.ê½­EöW:‹Ñ¼Ñ¶bÖî¾\){Ü.õtmòêýbŠ}‹ïAISO6Òã’eB˜t ÷UÖÙãq±=˜ßaÌüÛƒAäÛ#ÎR~½=Œp^H«ÄÞ½ÏÛƒ‘ ?mæ¶óÓö`z{ˆ¸=bïÞ§íA»dÕå?o/±ç‘¶‡Ú”¦Ûã‘'Îêß!?D?<,šGÆ2—÷:©.†p#>Š/»¿= ëö¾ Xä-´Ëª1{‡Wcn#¯B$é‘”˜ïÆ÷ªmmU·|׎[/2”˜k¤¥oÐHµXçp.>Š“V%vDÚpËX·ðéÏ$îâ¶ÜÀ¶±aE»mœšbEèô?_ñ>ôEÞ†q-«„c~'7'¶Ó4ˆÍP. 8Ÿîs˺¶¦X·.lZPŇÓGÊmk£$#[&ÚBõµ=Z»ë´.Û²8Qà<·âÊX¤$¤…ï!S ÓÚIEÆï®N O…@ëú2¤Ö#§¹Ê€fˆŠXo^êü_‹G¹±›ÕòÃk`õPh¹ö®šSö[Ï×B¿SNo[x«3•la^ò8¬þ¯Ñh]æD½–š‚Ž±ÓF±QÏ?F(Ë­U®®æƒmˆž ‰ŠwÛØÀø,8jy«Ö+„Þ?åòIrù×eÖ_!¥8#o‘¸Æ.©‹ŒÉmoQD~_2p†;8¡I£ëÿ~Ùê®ÆYo†Õ[pÌû•²jbm$®§V}…\Ô-ꙺ²Êúèuâv§MÇ iÎÌ=ºU·óìʲ¤ÑÕ¸WVê[/-‡Èü½ý_ÛyBŒ‡oÿÏ’FWØþOLû?ë'ø? O¶ùÖþßLðé¯(§Õµ^mpืNâSÝ^å²àÞ;uÚº“Þ<}ÔJ‹jF2© 7õú‰™UB9 ðæ~Ç©ã®ñÉïceÝ}‡`–ÊXlE¾D5Kºw/¶é(¾°] Œ)D^ ¶žÇ<‡ÖÖ à£U¾VøŸg6ž® 5ù›à2æ7¢àõ[Zé´nôŸ· áxÂpüüµgZˆfÒºúÝ[ëS«c!ˆdOÈœ£‹ ,Çæ¡œ²ËÃ'‚ž§X«®q²ß]Î!¼î=@NB?fÝ«ÛQWày޵ֻ–}Q®šW€|¤¸öšctÆãŠÄ„2O)Å'ˆ1c¶W˜Aä3EZžÃnÙpI÷ÉwÚ:dÂéY²Õª+YÙÁyæ§¼RäºaÇAä ‘X7H÷f¢æ™4·N7P¹ý›‚Ž rÛíâš^ôèéV¾ï}+rÛPMvT-|Dò–Dr¢‚˜„ˆ9êô­ñIO6¿Þe`FéM™‰ÚU*h›§'qû—–)kœë!5î­GËØV²òŽ„ )ÞöÅ3E ® UKQÃô|èÞþËØ 'wÖ«J-xHñn÷cjXs@ P¼ÿX™?)cZ2=òS!eÍÄ©®äœË5ÃOº{Bî§SŽªŠ „ž º"/k$ÇÂ!Ó`¾ÍHq.™J=ºIfÝ!C¯3+;Ì»jÈfIhãë¬mãU†¿ÅÚC1 äþ£i¡F¾^•£{²Ðv……1 äÚ¾kíhãb{½Þ3,8Oÿá:ÏØåô˜1¦*‰<¢Þà‡Œ–˜ðl„g87ö‘ðŠ©†þy=eséiïÂÚçíÜ”Y ‰øaO‰ýæýˆ*$Èö›¨|›ÏÇ—0 fyÛ„UÄŠüVe=¤r+ÒÉÏ:'×£'d1$bEª Åú‰ ¢TA 8y†U;\‹ëu-¾¸€ÁøW'}¥sšù$ZÚc¤—W)§ o–÷›þ{™ºÔPY‰ŒeÞÝôîS0ßSËP“¼›Ni2ƒ½+Øø[¾LbÆÈ+ê¤ „ ’ Œ4ò5ó¨aM ¯a¥# å>d2ÃZ0¿®‘œF×þ8ã}É%Ž™ü´‚©Ä«CÈSH0´“§?ñ@È ò³IžþÈ™}HøÝ~ò@æÉ &ß툀íò”RÆH}çÿêRCi}OåJ[mc{¼\³$ÿ”À²u;[Šr ¬$÷b-ÄÔ¸ê¿x7ûìSãÐGV¿óÎô§ÚëQ†,žŸ0-Ý1Í:¯ŽIYxÌI( ™’_G;¬ÛÚÀµß#i>%ÁjæÂËnë^‹s”HBV¤õcÓÛ«FÖ£\ñ(BžÅÊ€Cê·oS®Ìy;ù6ÑBE=pHýöm¬ÅÈÇÉWqçódèñ Ì#‘QB8 ÈŽŽ@ÛÉ3B½Ð¢^½õ€¢(}‡"ÿ0fÂbn>ÉŸgæó³«xZa×"ó¯Û e/ROþDÊA"9B²µ%¿±wßbÛýÓ Fþùã::¡kÖbnÙ{uÈç§±½õ"×3`/¾!dVõ]‘ãü˜*ÞmBfŸÕ3™Ðu2£;ü¶˜Ÿ/ãj¦< Ò¾‹ëÕeK¶m‡zuš$ÄÑåÓ¬äÝd+F¦ahË`¬…O?ÌÕ]ÌeäÖ¯‹»KIö9·oµw¹”ÑÙiœ¦È÷ó—éûPk§úÚ6O¨K“+šÔߦ!»Î2®gø³¤ˆnª—ñʬ£Õ¦„æ›–`d m÷¥W5OÝF@³ÈpÆÞX°µkY3Õe†õ.¹}Tw– 'ÒFÞ¼Oecý˜–©&ŒM,º¢'eϳÝd€=ðz=òáƒp[=’ïg!wÚj,„|ázãÔ;‹Ž5ãè ±™‡ªƒ¦&‘Å8ŠÅ©º; 2»ƒèÿÔ4cô¾ëI Õù™zÿAœDÈ7Ê#çBDfü0[‘&ϼ†äK#ÏÅI€Y’Ú¯â$@sNC íq± ޡޠ©ªóT-Ôm‡o.ÿ±€$vÌ —ÜiÁƒc¦— ©p¹Òô«­£Ž _a“Gt׸û1¾‡Å)ާi‚_?Cû#³óÐÞ1+,òêKbîCV“Î2WxOø˜·ÙrTbYøŠÎ{/½K¿,òqžXDÈç—Ä¢­È&™Ÿ6TÚi¿Î¿¬•¡©È­]Gº¹ÃÿCïJœú…-¢jðeé%ºÓ4ýa£ko¤“¦ÙŠÍ áU@‹Œ”%“7:NCãÁ_¶’aÛ×eW¶£x÷4ä‹g¢†¶g‚Ê$Y'™‚Y\å¼°û}$]7Xì¥Q ¨mëž[Ùð~ÝZ„¼z$µü SK z„¼9éRÒ8a¾)GòÞò ¤Ä‹‰qoÞ ©ñµ?B}’—–å†<³iØýâƒå¿ÁtÑÈRR¹w£ ¯"ãA+}M-ý©¶ŽñZj Ý蔥ß.€5Ÿ"å£;gêF™ ÷oŸÕEJÓs3Wô~W³n21Í>4O¬w/“Rys¾)Bf˜ŸeJú¹r-Ü4» Ê]Èäê$’€doš]þCY»!ß±}S³•®2”Êt7É¥t+«WyïÇeDȇc"+Á£¹·²•¬Ù7|íO7Rd,Œô©* £¦¤-¾¢YÅ3èQ0ÚÐäqwþ‚µ(YÞdlæ†óšÖDµ{C{6Ë$]à«w Žòt˜ºx9P°O—BMû‚Ážž¿åcg>MÏÔ"Ã#Ær¯­ Ïü^óë÷o-Ðç&¿ÆUÉËúM?‰aþðÿ~ƪQ>Íν[[ «|Š˜¦ßÄß\c!Ín?7| žÝNˆn©÷/É=VxÕ>Äê£Sâ¶ó°Ã§ôø”$jL;‹²v^ƒOéù“ˆXë#ÓsmxØè²°å¦´œ‡Ò1.#«¤9|áUäÓ€÷WG8àöÙMß“fÀçy?ã]õÁÏÔ~îZ¿8œÊF™ÙU_í¸^P95¥Ûƒx àôŠÝÌs×K“~îxþ¤×œ|&VxñÌ4àœÅN>2PWN>™¡ÈÈðê»4ÊOó-—|‡Ì°¨šÊüŒsìTÑ÷´ÔÎ96½f‘_‡kJ«‚=«é:3„Ì>ßùµ9æ­ôÚiàªçõÑíy*êhļ}­ɇN€¦^¯Ñý¬lYIMÎÝ:Îî; ¹q»©ÊX!V‰ìäõBž5<ÕÛÔ!äiÃS"9Bž5<‰oá4àÆEn´Ì¸ÑÂúyýâMHèQòñ“„Îè%tÒ€H+£O2?jøŽ®Ïset£bŽ‘¡C£ÓPFêï ¿†9šÞet£F‰-‡òö¨G„LÏ=ܼvÒS ºiÖ"úþð9E@OÑûÊ™,T» ÙÊw!±/¨›+»©P_ é)±[y1ï’"zŠþâlC^fIu§&Ÿv„¼Ÿ»…üïS ²êdòeÃJ'‘–—œ¹šå-yèÛ“ã즓#ªnò ºy»þ_usBÈ/ÕMW7o×øÙ _æ&|yÆÏP ºn§Ð”NC6b]p™„Àx…E¦ßÝS»fƒv«EfŸ¼j™Êí¼k|zxÃŽCÖSåeßùþ˜ ·~ÞžcØíyÔ „ôï;ºpëè‰äí‰aÆI½ÉªM4 ˜Íyuò€æ˜î!¤ç ו%r×.7ÎK†×PÔ ¡Ë¥y•[øì¯(í”ý :K-¡¾ˆJÔl“1ŽC^ÿ\ÿ~;Ÿ›8Ô¼¡î÷Oõx3ÔOǵØìߺØb×Qˆ–òX—¢éa©IÿêØ"Ŷ1Ð ¶O’Е²)KOé¹|7IÕ„Ô5®¿¿ÿ5zvÆXƒ·Å<Ñ©)òöeš¬Ó¶¨`wŸÞŸ1Q ¶Zeùeî̈k™}N“µ‘-ªE^£V’%^°m\`vàžŸTU]œy-š{Ž&VÔ1ÍW¬”`ׂ®~߃¹HÝ ªlÓIý{3Rá׺ÀôRÍíBI¦_krŒo €Zä-šo ADíÛP”¸çÁdâ/S±ÓdEËêaì0ò(LHÏØXµ *l‘OHÐê²²”A¡ê€í!\ôˆ- QÑS¨X×¶¬ =’c¬”šÑ\PT£ƒÈô÷@Ȱ¾§;Ç:­xK«~FÈ+¢Žé†ðqˆQF™>xàú^Q;§+‰l·aß|Ì»·µM4¹Ç­rÛÖ>ÏGhçHfB^蜼E>²¨í‹¬’Õ=Ýwüïù§ár Ò.¯#wS«=ö~\ xCxž«(†Ü7+I½òðŒ²i¤v™eSºé¯óJÒ<ÌZæÍT2Ú!d†‘úÿË-yQÀìÕ¯óEe Àj/®d‚(×]†¡Òuö˜„nŠžƒÿýîÛ¼5u³–#‘+Ý^ác>†pk)×-é”0¾ö§GRKâÑ›ó35>ÍC까oxõñyºù#=(Õ8áε*Šq†za#H•Ï0ňÏ4I¿ô®Ý»>êCa+ËTNÇZ&loè(”ò“ÇÇt+¸º¤ùå”ß9§­!¿V¥ˆÜãvßžË/ñx çOû4ÿ8ÍcµÿÊæÈÊ)æhÆQ ù•,Útàg‘™›ëQ·³±îH­L•Z¶äa­é_coŠ±Ã´ÎÛþDydíÞy}LZÐåÏ“Ø%JëÊ8:(­̰§­n:õIêf Xëf™}è™"Œ„»dÅZ{"dæ\­¨¯™~šÖqó«MŽ[çº6b¦zŠ‘,µ’žrÈÛG¶bTìÕ5—‘eƒ‘¡Äˆ}îÇQeWL0›‡â깫¯ÝØ“¶u!ooß!äÕWä*+õßÎ9ëß!oQ–Æ4C^‘ —¹|›aõ΃QS3Ñd³ÔeûIˆfªòáøÇVœ@G•#%˲AC'÷£¦,„~“×¥›§æ¯(ÉR€›R¹.;YÊß%“­˜ %Ë ïýLšyà¤jyÀ–p²)/+•©lJ=ÏÔkð¸Džj+£»~<04#WsùòWõ(ï"><Ô˜%‡2RL=±BºK”|¥-×ü€à5AØ¢Fø[½+À_÷Ü‚¾êÎë÷ B“¸¯iÔÛ¼/ey0¡„^e¨ô.ͶŲèÓnœà‹zAI)ìRÛš¹š§íô¦0 ÆÖ8µm¦i¼¯—¨|XöD¿–èã|<Õzûà1£d:rî ºôÈoL NÉ yy¯a*M‘OHkŒ%)U̬QƸ=ó¶F㢠ºäÓÜÇ^TÅ&:û>ŽT˜G9ãö¿¿þpv5-U®tb²È\S;ì?’Œô|ëÒ<úßF ²ªü(y¿l­Ð?ô˜'€4Oþ·=r+»J-²YÆ~$üùkêË„æˆ6†Ö úH$õ|‘óŠr"é￾úáÅ_¤ŽJbeDÒwHÅc–‘I]³´%nHE®cÃÌKÖú~ûí¼ Èë?¾½ÙòË··+@¢,í¢JHµÎuÈèrû2TkÚÔ,ÞÏ×vqç£:¯º9†™—Çç9z½A”×|ž‹è^ó]#+,åÔùÆ&B¿ÎÕQÒ{ÍbŽé‰Êihˆ?Æõ¡Ç昵¨œI¼g͈™ÄSМA'*§#ru§£ÅÇQG_%t¢rV7:$Í1Š®Ñy åTN×(ö­ZkXsLòôß3b®/ ÷CÝVUµÏAÝ%*§Wœ yè²È˺žR(Q9ýlNh)ëÀd9ªCˆLÃAµç±š6K¹Uý( ¡I{¤Ç*ÊjÖ‘Y ¡™…€gÎúH/å&ú¥¡8§rK¬hÜl˜;#„1Ǩý؃uKf:mNëš ^ÔzwG9õ§«ÞÂæhç¸\].¥,ëíüîi:ɧ#fM-LnK·@è#–ìò³%‹®¬j}0J¸P“Yq€šõGj ÝãÙàWÿ¯ æS…ÑM}³ÆQ²mVõú?jï€NŒÓþ-Īsï^éal%­¦.ëK¤»Ûºš{'ãPp ÿÖ%òÝ+_$%½J.0ë*øšÐ`7ãÍÿŲs%YWZŸßÿ›:ê11þR][¿m» p½^îúÇ^ÕÑÃ{Æ8W¥ù¹úø@¿åG,|#ôóU?OD ôBÎI ” é0C_Ì÷¬d ›òò¦n@¬0 Ô$Â`…ß* j:^(7¤}g)“ýÃ:fy.ú4Yá aʨ!ç‘'ØtBoHLÖfsõy}7Ev”|JSdÝ>X@[-Æ2)=£œø Ä@&&fU‹2-»˜?±4vÏ%ùQ³¨X‰Ðã…Öê‡-õõ&¼51ÓDÏSÛvNªTñifDrË8O•ˆô;O²dçIkzE&È•‰­á|ç÷PNNSd$ØJËaìÓý¼@ÎKªþV¥•2Å!å³Á/³©ßxI²x§7¼´Jî‘Áä‘×ÜÓ9NV(¢ƒ­)$z‘y#NƒSl ý÷@^rmGOx—Šà}êÖøíHVC#ÖÍëæJÏ(§œûý3Ìu4¼¢¬!Š·yI½uK9Çpý¿@á÷$e^«a„ÈË;¤Îüë~8]½5„)™~íÒªƒŒÀ¦Ü¼ºÈë[=½;KÚ@ä-%Õ^Õ‘Xâ³™–†ß~ÿ¬üËÅý»`?!/oøh¤á­H|4Td¤ÚÃû¶º÷}4v4´Š…ŒÆœSÝ7ÐRJYfßþ-Æœ!¢wÞ¦~ñ<1nôÏt“ï¬&¬éU`y$(ü¹v”û¢j ã×O‘Uò‘@×_ߦFõ+#œDo Åf1™‰ñò6Ér\K×l¯{7+Ó¼™G¾Ñ¿ç^ÿ~›Å*z²¸Ñ‹£Æ[SÐëy¯sK‰8y?¾¶ D^>)ú“(hã‘(󑀊þUúG‰ú÷ÿ½6”%“îêz©á5¯og¿9%ºýëì7 §£dœøœ¸NèŠà @Ûxs!¥Ä°‹äZ‰2;D8«<…Yå /¯|cTµm"[!W01ë<4\Gf#½cºóPkÙÍCß­kR¦õy{±ïóZÖjO§ÿ /Á´'ÄuV8ŽW˜“Ø‚Î(ü†¡l˜~„‹mú?5óTdÜg½÷³Y!CÓc>w1ëºÂîÉyb6ë¯]ïúk빿v½›˜ÝNÏèþ¯þüöoý5ˆ|×_£§þÚõþÁ^Ò ¾r¥0Ðõ£ôTÂ7¤ë¸’Ÿß­ÑSÞq}~³F×idZKÏ·Öè$Èâ61C¹f{ò_§nçVúyVœÄÓðšöä7&êÓÊ‚‰ºGÞÞ›¨OÆD~û{ktbòm ÿûkt’Y£{ä;kt­ÑÃÿõ:vo(C¹7ºý:Íæ`Ô!Ë8n|íÃ×ßN’Ðú6ªÑ+žæ Ï™ËÚ7A!Ó\!e’N!¨k‚B¦¹BÊ% ^ô‰fÜP&IðNA¥’Äíç›í‚~™¼æý-µÌð~S¯æv*¤¤kTØ&]áÁùû"ù?«ÑƒÅ‹\>Àu`¼\<™Wz´ú€Ÿe‚’À¾-ã1s’ÈS>lR¾ã€×Ì$Âø±Ž¦çrêSÊwC`ÊÌŸG&EÙšf«}€ÿýž#‰ Yø ·[±ï ÈÇ[Íjl\ˆNÿýùšFRØá!¥‘·œVz¤ñc#ñ°®TìÇ~‚fmJ7­‹ûaÐ;JµGRm€^2‰¾óQ ^Ö[¹ÄvÍí4U6vÀЮ8o&Y–áq®¶ò‹÷ͪÃôº>(¼ý~®ÖÚoµÁ"MŽ:·¤n´T°´âQ³—•˜òôbœ¢+V5Å5@¢7¦s9ÓµYZ E ñ—ÑøÌ¨’ 5αx”9Ú€5’m¦eSl$©(“9þ±v'uí¨'®)­“ë?TÐãA{»}(ƒN¾ »·ûÇ`Ý—A@^^ '†Š†+ Ñí¨)‰pbº©r–‘¬ˆNân<Å:¥/HtÒKwDzr¬z#— Ãå{)UºÑjãyÍzz$*sõ³ÞJb¸|{~¼ŸÓa;ÞáiÞ¿¢Ìü¯ÈÏ„¨¨Ù‡rgáæ©%iÚuL%`àï “ÞÙUÅk^NØñr4²ª$k†H Óú)¦oTÓÄÐ!wí´÷c7ñaD'F¢Ê\;'ÿYìlìt,âsÏ\;OáˆÔሎÿˆ¼½ GZ3=u0ˆ¼ÇqͶ3r†CNø¡H9ÅbGríÔÏè·F¶O) -›¼æó‹|x‹ï™ÒÙŸß^€Æ2¼ÔdÔ+Ò[|Ýë|1Î ø–Ñz 寑vX3¬d"zÕuÛ òòê~ÛÒÓ¹+Ó¿D‚p$› —LÆ÷ýñóu@Y&¶ÁãòÉ„”yɆ°’*,›3Î¥ñµŽ©M-rÈË«¸ÃÄ@ú2Óïÿ‚K­Õb.~4^³x'¡è¼Ýéw^ÃNkÍÔl hHþM¥ÃjxÍÛ«[“«HÜ&ôxÕf ~=ÓaüzDy°ãÿŽê`uŠ3u"óãæD`5eãæ)ÝxUMÝo,% %dXÃÖ„t æ&E ]U¿–‡þ@^òAUìg,,ꊦßyâÖŽ&jUõž¬ÿOÌÑ7`‘V¶¡«¿¯¼Û6 ×ø¾G%è•–>HY&p\°™¬+ÊèÝF¬}$£Çyÿ´ãÞæÉKÕQyL±Íùx|PuV­‰ÆŒ2úú{9ûXà{þz"w<Åc™Vw4dÜÏŸ3ÒKÑid½Ï:ay‰m9{;­'xßQZ•uPéA‰nKWVÒÝíóFÒ½Æb˜²È2$wúIqZ²aTðÛ¯©,B‚¿Œ>³éÌÊÀæD‰nÇ:ìxno°kS–¸ši\!ÏÄ‚ "n6”öl_™XY“.­c¿éÛÉ£OzÂò·‰?Û@]§NñiȬ1†}‚3Îu9$ʦ#펽&'³H³o™ ©—ÀðsMξ‚FIGôüntAë¸fD÷³ÑEiŒ.¢¹'z" dšù1èw†2¢ûÉïŒA¿3”›Z¡Æ.ÈÆS ‘t™YHw Ôî–%VEžhä@g´ËŽÃßyý茦‚3šGÞ>:£õ3ÈûGg´v†ßþ€Îh6¢–Ç•ªxÍçg4ÑÂÿõ&I0Mk¡¢8j€þ¼Ë”q?bÍC/‘UÕ†ù½œZ&ÌJ€žNR‡6ãÄ›£ÈD4¡€KNõÕ£´Ìåº[ÌíÔÌ]m„Eê¦¡àŠ 7£d8Í<ó.ÅyQb+ÕÞ¨3}0ÂÙÆ¨µ„2šûsU¦cFs‡|6bùlœ'ätÍOÃà”d×||Q²Z6ñ}6†+1\*t<_,üX®>¼HiÆrý^än­N÷3„a’ £CèR9…×êã„~Û*Ë…I!B¨ì‘ù+Û@­÷uèÓ5 ·§ 2ÇË*ÔR%ƒÈO-Ý(DÆÞö±l€±˜ò…Þ•[Eò`5”Câ§6¥ÆÓ·__̆Ã%CZü‚†Uë];­þ®¦£™sä°+_9nxªéï'zµÄ >À \µtˆÿ¨ø8ŽMOÏýúçÎ'€üòÜÃWä,ʳ„Þ™ŽXb*2cÍ÷e+ÿûý“{¸¥ÂKrÄk>¾‘æKª€¼|¢Â+u@$:Ú÷ˆÃÊâ×óÅ¡CÃÊâ33sJ3³È™™púDùôIñóëC‚6yM½øßs%ÔÔ£.íŠwþç烦õšz§k¢O*ÃR†´«ø šÚÎ{Ù’ˆÞæÌd`3yd`´ØŸ†M?¨šMñíø¹œ¦KOÊŇ×,>*o!‰öÈ+ =ù„bÙȪÓC·Üä#tŽºŽcTG=òxL¶DÞ›§¹)ñÍŒðšL Ù“¸^{7×u ÏdáPûþºIúh½ª=^ÐΙҙõ¹éÓávy s?îÜ4›ˆAòÕÐ|%×ã4*¾,=Vmˆ<2oxÖ®kxõƒÔq-È8GU…Á¦]»`M?÷È[nì4 MRcYÅ9ø·Ç¦9‹u>#yÍ€Ìl6ì$“yÙ«i‰w)‹—þ:¤Ÿ†ÔÈ…·{|‹3¦kÐäuR£ŠË†£®€D¯B&\NF ¿ðÛ 8 Ꟛî£>ºâJ¾ôÅÂ32WT¿Vé¿ß r–ÀnŸç”·Èì„ Ò›çéÎðÆ2©KÇÒ¢Fn ÕÙ¬Èk(Vu,IEJIcá¨ÈÙ³ÙùéUëscgq¶µÈسA!ѵÏ&I1²­C„ ”£‰Í”(D>Ckƪ.zÁ¥TÛr)áÿ•C}­¡ƒNÒÄ¡Ñ;ÏNÔ„«NÛÒ !ô’CwÔ@×µÇG¡6áÿÈ,®Ò£·ù¹¥²_!´øü2 ÷ï/Ó> º.ÁQö ’•}zøg'/lÉn°ye: „ÈLÞ-tÛ”â#ÙçZAdÎv‹cWxÖa†JËù‘uDÿdråj+vRÇkfB…s tƒ¬ÙÈ©ÈK)¯] ØÿȲ–f$ ’†uìÇj¤ªë$kà‘E.ʽ‘ÕÔI_åܧ5vrl ÃvrxÔaŠË·0WRÅ;¹ÀþLÛ¶AÆ“s…Å.V‘8–Ƕ7W"¹N$É<ò½È­~éE䬗⋰W‡J×¼¾ñ‹Új’éw~ÔV«F§­Æ2eõCÝáCeÆæ ^½Š†Ñ w”É)ˆ†ydñFLµj6B`@^ßÊ/èûÞE•¥âr?õ»üX‹ésêiâ1E»Ü³SÜùáI³…–T1€DŸ4žò;Ÿ+v½T$ñw>NÓLv˜ÊUtb,ö9>÷çi Ýž^Î7Pa.dZóÏŒ ©v}Z*9&€Ì}™½0©<9Dœ<*ô;öv®.Ek„Üq˜•(2~éoГld©£›½‰ÿ=ñKßrkùGß[ Ù^Ëf1ÏkD^^”ÚÜ]ZÅV„”Df<ض<Eiô)£¦œG¢|pÔñ;‰ì+‚Š^3’OýÃuèªN”yM;Xðe#r XNQ Ò#3§`O`|K¹Foy¼ç¶î.) ÄB•þ£GêMÅÉ#Yö:ÝžIIvÒ–¸¼½KYUF'Þù_I¤Ð†&jš‡z§´ÄâÍd'Ã$î*,ª½ U˽dPûíX?Ð ª¯{zô(³teus*- ýÓ!4‹ËyϪváa¦¾@èÄEód0³‰ÎúHj—Ì6¾õ²óúAuëºõ;@fåòÖ«ÎëÍAuõ>¦…²[ýÚEïYS¶+ç*zÏzdŠ›Æ-õ¾àêˆ,À"³?µ6ƒñ˜÷n4Ë3^㟿n01é :Cúö´® ÏufˆÐm2JNÞ«&¶§ÑóštœßòòªDeÍØ3%ªÝNl›T?⦂ñwÞ¿¨e³.©eèñ…¥J‹CWEn©zò1´TYƵô„MP¦™F¥#С^:€¼¼Æëfg:Æmk€D±Þµ^‚Ì·²ÆX—IÌÂØÊr-7£ë…Ça€ÌZYöYŸí]ô ïjÈ[2pð¬c2):O#ã!Ÿ˜…'¾ åJߦµÝ*€|À‰~ûÒsqP}Ô†¡¢xñ¯öÕj+ß1%ƒÇ"ã ¦é{›U¬Âý§‹Œ/hsÔ62Ì4²lÉë›_0"]Ne|D^ó;ïêT)S^ä¡)[$¾`0Äp”$}—ð~°ºç=@³;$ʦl汉ûbñ; ‘%`(å¾)ˆÌVrÛ»ç91Ö3ºD¾K‘1 ³±Ý>25·Ad‘ž®ƒj~gEY·Ÿ~ç5GºÍ ßtÓ!(¼æ dòĉ¬êF½ÓJ€¼'¦&NÈi6O ^ó‘ÂúzGÃÇé¿‘Ùü»QW²ÏÈÐY…ˆþKáÎ;'’?nâÌ‹8蓃î£èµûÍñÛ·zݽ_hµ1¹í¹ý ®£S¥8Xç¹À® T§ƒ1›ä彘—lkâ×£“åztÞ"wè³ÝÔ-’#f½Eñ•Îû?®mÉqT þÒ´-l÷ã¼ïFÌùݺƒ$ˆýúõ d¹§£3$ !(ª*3;5âk^tÍ2×5SYö#w¨[Œ¼ ó²¾”)×#IÏY:›é,äÁKXp–i?{#'ŸÒãƒûœØùü¨€4T HYBmô kOG›zeèhÒÐÙóc nz¤zè‘ʲ´8wA“= ˜”’ Qǰ[À%ð2òë´4»€‹ d겄\èû€ƒñWÉËâ0Ž^ =í†2šzxÖ™wé6D†•~©72ŸbÐg:|w6¯Îñ+ÓáÍ2l¡O>#¿ÎÑz`ˆy­CÇpF¾~(aRÅAM+C$H2yž¬àRÊa9ÂvLnŸ;†ç´c8#÷:†û¤c8#÷Qµj‚Dœ> š4ç„÷x殬ƒž¹¦<Ž~¢’´;íÔ¼R¦b±“İöât®Vè-öÈÃjV½À¿ó§Ža|ÍÏÃlÂÈïH2k›@2[ŒKkgY’¡s¼Q!vÙXŠA ™ *ôZ“C;ë ²Êë%(te©ã±wvÝ{ɶzÕ‡%|÷,õBwUQ½#ð¥Ù÷|BHy;'Òz±lùÝTÉÛdîmÂÆM²8òáàÓY½ÚB´G¾> ¥Ä¹ô7¡”ò¡”8—þ&”ë'ù‹P •!ÉG·ç¸s‘ÑÿÔ#%j™è[ç“Ê%§qµyþØ5;%wOÍj.Žr4®É± VZ—Eà¼eb)U‡·; ïèñ—AÁ×ñHBzÄ!1ýµú¸[åøšw´w¸Aïý>ñÀ!ñÈ ?‘ckš'*â.óøqGô–€ïþ€L3)rÕȧÞÑãës¿²1pŒ,2¯sÕ+‡Q:I…Y »JFþžD8fpÌð1)_ïG–”Q%âžû¿­Ì@XCÙçþoCÅ[á°Ÿ0ÁlúÚž㋾;ð|²ws`ê,3•!å˜$cˆi†Ubèjz {Ny3€.½G~90>Z0žÏ2ÌÊ tõ‚‘·rÅéšv<¥Û‹mŠÉ\³šYeôzòRf€™J­‰ðµõP¼ûë/ÖC°2<^±:!ï×_ÇÀ'ÐWÌß?|¹Þfà°Ÿš›3‚Aú8¤mx#b)áwùÈÊÆŠ¶‰í0Ö*POHø]&—7ƒ­Fµ­=_óþ.ÂaX>V„#|Gϯ+9Iël[åW¥?`ÓT»Ljk…ô﬇D‡”Küw\—«ÿ½ëÀ†®³h`GHMb/ì˺fHÂq²Læ"4Êxû2 «wb’ùÇrDËPîܘçð½?q׬ý6Í2lz”†b ÊËÙ“\h`Ú“” Vžºá™äþ)¥[±&FÓÙ“\h`ºkŽ}+&T(=2K•-mއVr˜d9s‹ä 9rYò¢™j`úDÜPäFþ“MøîO„´MÆtWö§ÓïLä±Ê€Eö+ÎÈïÙQ, &“YGNòØj]EÉÊØö$gyìºóÉïfœÌ1¡Åãô•¸|û¼± YytA„3@cƒXéëXá”ËÞž Yb曨U¶ª¬ù‚¡$1ó­ƒ8º¡I”åvš{“´§ëß4Òž|­1ôv¯×é`æc•Ûˆ¡¯4H{kÅO?à;ª€V¾Uª:vYõÀ#àå±O* z¥Ö'«jÀЯ„yRw®»}Ê«Mepÿ ÐÛ ê[«šMU¡0ôU¥ÊWJÌ0 Åv8[xhvRm­ñ°þªŽ¶ÁË$¾gÞgi+!zÖ3< oò)JÛQgjUÅfv=Öú„;„^0t+übæ?ò]]µ¨EGæ=À÷I¯SÿZ¯×)æ¯@¿´b4][æ«âIâǺY¨´Pw\íÏùÞòxè-¨€‹Î¾„^õJ_µx±¼_2¯zdô‘=غÄœº ¤2ËqÔóyÑ$8Eko¤·ò…Š&¶Bnßë°êYÅtȘw’vŸªÚ D¤tô¬â™1r¯ŒmçÚdzhÿû^£6ù1 g±Äª÷·eþ‡‰B9Óa¡)gäׇFÞZË.€+ž¥¸¸‘WúFÞ!ï©¥?‡¶úÕ¯l9]3{où]BË/¾æ3Мmé¡bÁ+IÈÿï?רDƒ˜Ðc -€ˆ?)}qÇ*0ÛRïSaOyÝ/¸÷îìÐÊ^oþ #oïÈ) B&•|·IÚ¾!ÉŒcdÚV·AK|l™¶!¡’o¥=m(cÛ¢_vŒty’?¶#Ævêß™ëù9¢ÍW’¡ºDrüì¯K¹;#ðÏŒ)'Ó¼Í:ôvé‘—‘wÐeó:ÅQ¦ãùç;—==h‰©¯Ïœ·N&{*cWÜ×»Ù8u1—’TG9Á\zàÌä›äØ_Ø•ÏÞÝî"Æ‘¢W[-ª¯ç_„Ü(Fþ äìëÓ KG°HÈÍ#I2—¼iªi^ç3[!3ùz}Ô›°~s`“½¾’9Ô± œ†^ßet+K'EùtÈï%œL'@UºOõ™±ãjs‰·”Uî"S‰F¼¤GÈûu_›Ñ:„u)òùçû­uÄGÆxE)Ýîr&Œv>ÌÏ&fX¡ K<@ Ù/¶Î[ZK§úFþõ^…ñõÙ’÷úd´`ä-m·du§ 1Õ5¬Þ‰·&–ĶõIJdÐÓ÷ýzw·la‡i\C~ ÛÙÜK\—RÎ7å}Å%TLȯ«Î\ÐXY 50 ßßj¯ÒE×µ<ð¥IB9ó>¹î`­kTJ^”DÊÙu-<ù•~q¦>[yeºmšÆiÈÁdü /9Èl»÷~LrBÈ&«¸ƒ­XY¹äS‹ÀXvud+o)UkD¾'|÷,Ì:Kkq4!Nú[ ™Øs™£Q3ÐKɦ‰ |MlÏe¨Q=`ó$âÛÌåuéL€ç­þÕ#_=.‚À¤žŸƒœ8ðïüF«bèïWª—zi È“bVÅaÒ§™>W¡@ ß)¤ýÇ02å´7ÎEËDþ%7ii„ÌPK›kX“, ¤ü¡Io…Qzü¥Ir„ü¡IïtÍ;ìeX—Œ“ŽdÕÞÂï|â]Ƨ¥D2*)Ý0ò†´õî<+eËÚ äΆeèá5לd5=Bf)ÒårÜݨQzdTšsû¦Mdè—¾ö»:ò Z^ÌÊœâ÷JÉœáß™4VY“êøÛ¸/ ~vç”wíÎÉîÒÍ´ äwàUäЙkƒ>uJüD.“ `2Öë#b![ Éø8Úê«VxD¿nŸ^¨¢ÕCîèÅ ÕÉ8^èÕ—ePÅ6ƒ/»~+8BÞ?¿Ðõ@È,}¡­O7M†YR Ÿ^}ÞƒÑ#xõbFÈó«·Eûêuà‚¯´§Î ýªO=›ØwŸý;$ñ%ñn{GþׇùTI õ¯þ<¡Æ.öèís59®áß©&3·k8l„}65J½$‡“IRߘ:Ô0uÂïüÂl€¸/è‡7)©|¬òv-»W¯_iÁ‡¹AÈT¢ò¬úÒ.ûž—y¿ÌqIÅ«10!HJ²uýZMˆW«<z½’¤ÞÐ^ïCG¶¬ö¯„dëv%7ï\Ë+ã"/ð5Ÿ)Ù²ógе¥ûÚ—ø‰^Á¬ÐI>»%g5Rn‹$)Éö_Õû:¾XvÅZEá%Õdé˜iØ»{µÏ|BHÄâki ü­j¡qI¶—Þv=Ød<ë;å\_ c97ú H‚³‹îµÛ‘?ÚyŸYÝ!$´dÁ<Üøw·òЧIŽ÷àeȆîîë‘ÛÂÚ¸#d4xò®~zðGºô’ËøìÑfç…%eº2I×±ŸaÎ?.ÔšìLÖQ-em ‘ØWÚOøÇIx¸jÐ[]öuBÈÏç}¦0òò{¾ËÅ+çp9ó¾¸ÔºÇš~xGEÃRRú >¬e¹-Å>êÆQñz…Qú¼‚)³‚?Œ$¬Ä“5ŠÉÖR ýäöë“ì‚ÍÁ è$·_²µ6¯[ Â÷È{j¢â5 ¥‡›3"B^dkÍ6—+Ý#I®LTh­xŸý–t¤„¼™W»Ö®Z¡ˆÜ¾ÎþƒÔ=»>)4|6zŒyK €A¥kÒño9J¹áLuáÄBí™bWofŠïžM“ìÝWYÈ.dAIêù¿üIÖµyë'b4Ÿ02jmWA«ÔJáŒ#ƒ9‹­ãNªÜF G±_ó•úNzs'nœ³Å:NÉíö^ñ^SoÔ(ó< ß…N:¯QkÌn+=S2;ë`¶ 'ÛÎsß„ü‰îœ¾gÉv3ºnôuÝô÷„¯y?É.X^í&™!d†¾M_ÇY÷Up5nùÆF¥4¨±«¼Üs5"dÊÌkÝε 5³¶/¦ !ïÀÀ¶ó³óö_%ËËe@È aÒ™>“zŒÿVL«ˆÁd·Wí\²¹Çw õl÷.óuÑ{¡ªBBÇiÙ„n±}Üu\S©¦FÈW”ÙnU¾«L©¯,Kv ä÷…,Èb5&§¾¸ÇI•/Ä!: 4Ò)u‘·÷ܦ•Òñ’ÂÈ{X½Ã!»V£[Ž‘Yªðî>µfƒ FÂî ՄΦAõAÊT3ÊÓ݉ž@ç¬sõÝ»-ïF.ò Á”ŽãØl2~qÏ7{ê‰*C;7=؃ÛgV-¯Á‘Š%7åózAȸÖÙÌRæ}mÙD÷!³´Áor2ß¹•ƒ1§G"{%ßu©q(±àk>Ò¨Ò3ïË5—BÈ?QÒ‘Pùùi{Ê-?B¾¢§íˆ0kr±l}ÎÇ?;0G×ÜÝD€úžFþWZã7{Gkkü½<¦V`èWü:C÷Š©àqvÄ\Ëí‰uð­À¥UOÔÐcâMs4zO¾ùÆuˆÍÒ·¢(¦ Ûzé=zzú­@£+ê :QFi±`pðôÐGtútÓ¹ÕËh§ãoÙÀQÁC­'ço×åY ¬ßYÎ!ñ[5Ý#Þé³i<§Hª}¯FU ÝC¿?ZÅ …Ü^'BlåO¬–ÅÞ¯UÍò«8…‘÷dVµŽïhŽÒm±Æ<ãíõ³UÜßÿëD'3N?S ÁŒ—r@~ŸwÐн$(+! 0ëmdï牾{[éeÉ–#$2V çÞIŸ{g?#)³þ„4'd) Û•:7#á7Ãga”Rçæ3R°°:'Îͧä3’R¯á¼P Þ¿N2iAIz`UÞzî2‘Ik}'ÄPV[[N Å×LãŒÎå—õ¹SòVŠ í‘Yè®HÒ(ú'ªã˜âï¼}P½°u);’*œr“ù!ïÌm•€z<¹Òƒ7•§TžÜ3ìxS‡j§iCÔ_Թɜ´,‚@~¢Bÿ'[©;ôÓ™R¦ óóžžQÓzçÔ³¦í×™Ni¿¸?ÿºg§nqžh.KŽ7$ZÁšGÿã‘Mòô;Ÿ¸}‹hJíöñ¥wRjSj(x8Kߟ?Ôz=26ª¡Q2‹CÛ#äÇQÊgXÁîÏŸG)®Ÿ÷çÏ£$â×ñüy”’¹ôB›ÁGÅöpËyŽÆ”$%«»š_ít'L½³§½ ¦Ú$%«»ª°õt] bRBôùÚˆ(ØJ²_ø¨–~OUhÃ$¶/œ£¨Y¢œ g}Ã$meÑM›ñžÈÛI±æ@½ªƒ×0?S“ÓwÕ uí‚? Iذø™îy½ÎÇw„ÌCƦóIÌÉn˜²aÝü¬]—’ŽÛVÕ°rÆÈû•ác+{µ¬#ÜœëÜ6`‘óV®uŽ‘ÑP¯òý±N®UÔ dRCÒÿ~{þ¤Ë²iä²×]ƒ¾"nÏü•;Ÿ;ù[ª !£;Jíz΂ü--gƒ¤†¤.Yß:™w=?Í'²ÃiádHZ“­’ùjlOv¸ûóÄÍÃH!‰éwTfK;5ý³BÙëgfKü6³Ô)â]œb:’ý kü  ƒD›Ñ‹:·F®!Ÿ½n¤ì׬K ùú‹¶ä¹sõJ[iÅ×¼æ!#m%Ì>ôH­ ôaȆ½¼fdIr;EVUTó%7ªùüORÞ,XÖšY¿”rë‡>fšRÞ,6þUQ¨µZñ5ï©- ëx)¯§cÞ &ðf1rÓÈþ(@¾„$¼Ù?–Ñdšj¬„áLÇvf ֺțu]_>¥¯ïNóŠã™ˆºhÞ°ôõ.³®ûˆŸýÒ÷ƒKûuÀ;Ê~’Y¡=ð'IdÞúØœLìc#)#ôc„ú]{èôâ¹J¨œi²½ó¾X™8xÑòljrÕ.;°éÉ/AŒ†Çi.Õ~'f=ùVUçŠæ¡¶ ÙÊ‚Ø'bÕ*‡#¯Æ!©ž‡$pgʱ;«¨ÂwO¤[šÚ‹2êèO²^(B¦R#]g+“šTÞ÷ý”#ä32 ̲[c¥Ý3d1€êZÕíéܮɳ\L¿á¿Í°~†öóÆk5±m_êuly‰+/ªÊ§+Ù/Æþ,®6¯+MB+ÛYPÑŽò„¼%ê[¾|ºIÓUÝù§æ¡nM¦aη6ý#ä-QÊò£¤§ñ¨OêCäû£é¶ñŠhD€)ö=#ÔžÕbàfzŠ1ò¯[_F[ªà¢ß„ ûç­áùÚÃÞïõ2•УO§Íÿì(ÝÏó”­8ŽÀ%‰Óæ^Izk]¾nú8ƒÈãã:ïû•aœÏqÁïqêõ7lüa”î¸ÚW„b¼þŠÆ±M™:‚¶.y1Yƒl6Îøš÷Äš±q=»ÃZåSaât„Ì¢³A ^7¹¡GL°zGË·]Û×/áîØh¾ðFó&2ÓÆ¨‹†UñAÎìˆÖ™±êß©c>Åkb£yW{pùêYÒ±Q#üÎÇ[>Ägîø:\È#o¡ïß}›i z¡(œßS6¬toÓ-Ÿ†m·èÙÂÈÛ%ߣšÞCM4aÃÆÝ…‚c’ ¾¦ëÐú×Eª®?LËòõÐ3_“\3CÌÃîþˆùwÓŽêû7ÚæìÅ×›±s—ÝÄÓJ-ñÙ_øÜá2õŽ˜¥Çt¡°Ç¥¼Ùß._\{d>,M^µ™%}ÿM Ä4=ù+èx¼N}æØÑÚ,\ÎD;‹¦GÈGRlB…flå¡‘ B>— u^LõTNBùJžÁXÉa. Åãù‘vïpÙIê+Èr‡‘Oy‰&k Dù!DÉú¯T‰³sÙòm¡ƒäÇ<ãqмD'ëäíÚž+ÅÐ{d‡4^+v+å3Ë›ÓÈ’b–o&ýF§© …z§ûî¬[²àJêU² o^—1ZnMTûŸŸÝÒ¨‰ÀcŽ+r¡m$V¡»z¥=ê®&Ï/Ü—Y—¾WÆè>‘ˆÄžgÝζ7¿|“ûëí»ƒ¥KïuSÑîM¡ºÓ5¶OåÈ)ÝÞpÉdC÷!¶Oíû\M§Î!&Ùồ´ÿ†‚ä"ž’¢ƒ¥/4uÐÍ·Iràn‘è`$öá‰ò­èx‹‘ÄÁÒVÝ¡Óì5:¼”t1J,ÿýã4nÜ®·ìV’gÔí‘b/0ª#ÁA-òôH_Ö4˜@ôþÁ‚M HÂC?™@tÃÀT4 )ÝÎ‡Š’„Ø–e õ”gvô'i*ƱÒû§yêds½O¦‹±ŽÝÝ)=Ê<Úš#+ò}•P‘fožÖA’õ ‚I’5§ý?aW’$+®¯T•I.{ßϬÿÄ$ “°>ý×Rmµu£RLîn«2cÝSÅó ÿÎ ñŸÙª¶®¾7$ÏÚ%¼Ëaû_›ÓØQÛZHµåN0gûzD–ï*^qQ#Yå²óLbéHÓõc¥héÚ­=¾w+ygÄ• O™VP™«€`ì¹7%! &‰ +þ¥nˆñ“\©á1=¿‘+ ¶·yE®ó %ðXÀ‘+íšêqµß6 #¯È•{]ÏH4)&W¶b? £@ƒV6º£VIžˆ€Gÿ¸Õ+ÄÖ7UF„¼Å&p•7+ó¹oèŽ÷3i}tà%y]úèôÖG#¯|t´„"GÈ«tALÑñ•^ù¾Œ9ŸMøÂ˜“!ä™1'ÃÆœÏ@¾2æœòqæ%ƒ9ò‹1' ¿Þ¡Qpf "?Ïôç» ðâéym .yiòéÏwàî€|úvô¦±m Ýó<’©ÕÿvC¶ZÆDåÝÐhM϶z›Ê3‘­$”Lí…ƒœBƒzçwMõ‚¢TzûFbÒÎr€Ä4"Sœ°4"•Ò 5)¡åu}‰Ñ†-T’¡lÇpÍèðrH;²¢‘ÍÒŽe‹woÔ—ùî©1˜I± ä÷¸c'›¾ç­`^Û!Ÿ—>d= ö¤‡-(á˜4‘òZÇir®j,ЙŸé5O‡«QK6=ì6º|eSª^9ePI¾Y9uSËjkV…ƒ!6:=£7†Î÷ϳyÔ(x_ËikJûA••¤æ¨²Ï@AýD «‘·Oª¬þ:rºí°'¿oGÓO8Òkšç°FfŸíÓ¼¥\»òy¾Ï Ñ 8e"ìqÄ·® IVþñÅwPËä»KmI'“ËòÆÉ\?Úì6 UŒå‘Ñ›¬S4#£giBý‘ð~GжLÐyîó¬ y‡Ñ_j¶œ‚KYák>Ò©j5<'ËVålcùôȺ´»ìšKê«2 Å]o¡£þ»ZÌa€ÑÄ·/»¹#Zù‘þ~—êÞè4!dz%ÑÆÃ>¹HžJ´ñð~Æ”4³J>¬­Æ5ãœ-ðÜSLí,¼‘Ëš×ë@i Íœˆ~{Z4]›œ"ýp# `ºêV{òÒ”!ŸåU…4åUÂò‰¾b $ú–G_qØ—¼Ô¡+BÏ|ÎzI{7l…k[4* ì±4ùùA´ÖÌÑZkC¢ay5Iä‹éMs÷µÏÉy“yÝšefO1/ûZ{al‡|ÄH“Èä¸÷¤ÄÈ'RD7CdFçœõ½oÑ8db›ÊyïËÞŒg=F¾baU{ïc«Îv.Äáš)’`5w¤‘Eß½DÈw|j[&‡FöuAÖ¯üOáöÐÛUuYeSð@O«Ë*A¬muyfyCÿÞû%Ën\²®ÍÀNî|–’Ÿ£–Ýa~Ô !oçSõ¼Õ-GÈû•B²€úMòó¡^^z·ævhQÌ!oÁ_‹º1_Öæíœ«] #ï§«.Ïs#² !ž§@|«×vÎEèœ'›ûCKY‰¯y¡\BÎøšG…duKN!Ù$°¹Ï’ëIŒ|_±Èî(²Al£±‹Úm”üàãØ¤Æ¶jØ©ˆšv„îh«¹t›£ãy Šªð É*R­Öèw&hjÕŬ~føŽð ¼¶Í¬¹“SžÏÞÔÎ!­Ý¦Dðï§žsÜÕ†#2‰µÝV¯e¶7“wÔvÈWT5´%x}x”s¹×#^¥ô\Ÿy-è ;dd‚P»ñu×*²åK¿â•ÿF³±Éп”וº"™Ùá!ýF~÷eÒ󚊖¯™ŸC÷вV³%)®%pÄšZ}FÕ¦‹!_QÿÚõ“>Úòjœ2ªÀ®¹p¶¼Þ0òuºƒ™ÏH×âÿîzdVeÓY»²•̆ßüo<çô‡uÉ”5凫FY7µ.tM'û…fíæ[*zG‘ÙqWÊÉ2Ew¸ê9(Ù¼¦ÙgBÆuÜ1ôi4þvLT;8¡2ä<(}x(´j‚U!o´¤“Š6ÐìÏ…Ÿã5aÛÚ@ñÐCSTˆ·m_®qÉ化e_ükôÞ o§ÓtLB: µÚ&kÈ<ñJ˧´m›õèïÁWQ­A1#Ÿ(¸:zèíBæ0²âK~o×Âc 4Óä÷~ðÛ­ ?TGy ò`žÐ#ó„$¦kŸ™'ŒjEtí£ÑÁŒŒ’ØkøÓè`FID×¾0:ÀÈç…Ñ F™\ P…õL¾†h9sÈÃbÿâc+U ã¡Éïë‹ ÈÜ–{XùO ÛÒÙ€´êEØL_»Yê7t8ÌÛ2u‡¼ rÕéŒçóÊ0¤ËU‡¼²™õ¼/B^¹Æqò2ÈU;9F¾qkÜ ŽkŽ-§’†@ÿDîº(v‡ôKjµŒKtཿJî-lN—¤v+AÊBtò,n¦r\¼¸f“ÚOúiìøßçý´Z²R–ÛÏ ±Ûº/ªÿΖî="µŸÉšB¿C¾®:o,áéÅðt-A*5¹}±nÐcÖ;|q7lÑ“sV“Ôv½JDZЃI>)àvšR×·~E1 dL˜vŒÐe^:´„Y·ûAÎÜ”¨AR¦b· #uÕLÊY•ì6k÷Š#ä3ÄÔ3RºQVL™D&²NCcÉË.ËòúÛǨ±“ U{ÈÖ´D4™ÆT`¯¯#: IííšØvgpjâjgW½; ¼ò¶‰­3;SÖsdåÜWø–\Ê⪷yN\k¶E+W µœ–=§Åĸ;ãD…Ž}pSxi%¾’qÞ—¶„›ÂÊgAU«ÈPeãRÍyRíTòÝRI¾æý³,ZÏ 6Nò !avÃËéßYŽ$lw«Þ«ÑØ@¦6±¶“ ‘V=BêƒF#U"†¯ùŠ`l%I—Z‡Š„Ãëvм×ù’sj¯ùÀ‡/Ý’Óî{³ì¼%^' ‰¹ò…ÛpåçV¥ÕÜÑëLùÀ~Èõbh:y;S’›ä´‘)lM¯hvÜV¼lÆRê§%Û ÙÀ,‘zž’”å2·ÑV1Ëͤµ/r²\Uú_×pG‘v‹U§s- ežû‰OÝÎ2ø¾-_H¶0.È*#®vAÉ¡ßñvœæ©!!¼±LTóm£JlXž&÷Ã1g‚ƒ”µŠÔ;PÅNbní?àj¨ŸÑ²³\wÕf„¼GõÛòÞu¤3¾æÃïA7½V‡á>HðTLbn­ãÚÅ ÁÃÅۘݪà²tD¿}…Ún¨‰FìÖ¿Bpe ´>ƒ„Pù~ÿ` ƒR¬vklrÇóÓH)¶Þ6¾ Œ´«ô?Ë"sUÞyš‘o]ăÕsóÆ%ÒNu©S&dÜ}Í%âÁZ$uèÚÍr*äy Úº4f¹ßꈗ’CÕ#æÁþã9-ö¿«C]²œòá[èúš~BQ RŒ|EÈç§z·Êã™øwž(‚k7!…Üþ¯OßK¾ìT½ ÀL"Æì©ÓWøŠcÖΦ:‹Y뢴"‡ß™‘NBO!ËF¨˜~CÈØYÅDF‚ª;Ê+xëÞ•ñÊ{@´%òœÑ!#½ êB&ÒLÂ$erõ6*¯pÙë"¯1òql2Úýã`§ÊûBˆöÈh÷ÏAÙÈ A!8‰Œv £ÆjÊšÐnh†•Óý>½^Õw4h_mxçØ‘,Ò'f½ÐjMpvD,\ìËÊU"Yi_V‰÷/ªÃðßïßR$m5 ÈÇ×AB•Ibä¥KÃ<Çøº. 5k×¼$ $¸×žº4¨ØrFÈä´j̇¸jŒÜk?›Ã‚À s€OšÃkÇ0%\HOóv*ì ˆüÙÈ] hMÇà“ö,!Ê$æŸùƒw™C&Ðs-ªñ7.˱®3H$÷1Š²Ç£(Éãu¢Xiî}&ÚÖ“Gú©XiÕæ¶]mòUMf„ Š•ÐB¯‡½Ú÷uìBÂzšñ+Ó)2ãW„Ží†˜åh§Ö¼T‹¤x‰Ï˜yî£ ªå*Ç #¬–döä©$ŒMìpï¯PÜ«¼jãÖ×tàåº#dêÙnἉ2™UÅèý»ò´¯²–U㾸˜+ÈL ™ºÃ2ýb6S l¦Q,žãé¡7/ꪂÕÒ*-Óº³©ªFü@/|vbî9,ÿ픜ÇÔQÑ•€¸±ºí·äã0A–¡Þ¡ðüA*‹Gä̧ä |w>-?ü÷ÇRv !ŸŸ¹œŠU.Wï‡ÿê…†#eâ°Ž a*?†;:ªêDÒroT,Ò2îY2IÄS·'M£ÕöLva*£hüØLxê‡ Mí¨9oñ5ŸZ1ªó«uÀ¿óù™¡-¤kÈœ…NÅ3öÙùÛîŒ6?Ì»z¡õ ñbÄ}×VTf¨ÌÚÉï”k2Ø?¸ïÔ™Këw™…€ÞWÌ}7ÊOú‹¯l»ð®­— !o>n0ñ&\'6®y‘xpÚÝ‘:Ž+=@€v=uvj"õ)«g¿8„ªçÞ‚6Xóª‘z×÷ÓÐùaì$â@ŸÅßQã!â@ŸÄß»8"ïWñ÷:Iù¸ˆ¿‹™~ç3f`Ûñ/1óbëÝk±$ YÜA}ÌmT€ïFóªM#Ç$ûv¢×A=|1¯óe;j>"ÄßÈØ%ll××êgv GjWRÁï(ôöšAúË)H;BÇZ4‚Ï ^µóݰ£¡ê+V‡aß{Ä«6™x:t|èYÎ;øŽ¯úÄ-ËLmøï=ùÒÍ®ùtC§_ó~9(à„MÒ«ù@q˜L.¿b†}ô’ˆ± ¾Þ®ÎÂÕª‹þ{`¬8†ûÎp³íõ{ÄͶ×ï“ÙC~øz\£T°¯ë$ ‡©sfÞ²t>Ô*蝹úð½üsu&Y{¶.Ϧ)‡È*¢¤9N[.mVJä<µÞ䈒3rîš%—S5ÃiøJ®y t^{à&¯×‰ «Ñ·dÞ=Éë³½íÙ±;“×ëŒêTšbv§C>K¾±|úžf|β !ŸQ…Ë)H› kËbDÈ$¬Ré,F—¶o¥ÌAïÁ!_‘V¥KgI:•$ôõŠW<Ð<ð@òŒª^9Ú­]WɵÐj4Q¸ë»þçT¼y0Y;)g^ 7 5ýKÒ-2Ûæ ?Ðßû •`"ª‡>N‰¨4&¢zèóH 3Q“J±×š~%,ô<ìß#œ)D8¯÷çûÜØD2ÒEï^Dô³ ÔªêŒÉ¢ï{Ž·ÏgÊ…`æ™Ny÷­ÎܰþM|WªüœI–1„<.¨õpT?t)Æ !ah?Ë}Sv™×q- ò’ô$›3—%ß)ÛdˆWÓ-z'ÕÔq²V¯BÞ‘¶GÎ,Û6o7“D®©^KÀ:qUË9S² ä3 ôØÒÏ(›WB:¯À”Ä®©ÿ˜{¯íUw´V}¥B"„|]O}ÎÖ®qÎÅÀFiЭ±Ÿ²î\wM®öÈ£ÓhBÐ;_äš3¶ÍÛ¾á{·•ùÇÏœ™‹2ÝÏûéð~!—­|—½èºrÉÚjÄÿß~ËòöU—U[)Íw ½»ÂÅ.ZuM a´$ýP rý1ÖæL6¨Ü8$ÊUìG¯ò´…m™BzCUÛ dÆ©vÙøšŸÕ%¢‘ Í ÑXzC®±VÑ]sXrI$¾£äS‰HýNõ:ç9œôiäøò·íÒ8·«ùäI‡4o‰´õ3§Y¤×’íÙÐâßùF½—¨£2Éð}âq?„Tí2#äíjXF†¼yÖêËWmNFAù6‰)¦‡. Ç]š˜bz–ûõ¥Ée—†ã.MšüG—&|uÉti ¯H“ï]Yãk^vifz¸£Ò€²'H=´õ@À¿'I_gÊ-f™&Ñ*d‹±æpéä r¡r€\÷ÈMЩri«¶Ía®$=Ì·ç%ìËbVÛò‘}š\y*pgoè4çTÎi¼WN_¨Î…z‘ç¡¥ùÀHs÷ ™«¡ÂÈØ+¢q9U5f4ϯƒä `´%㜈º\„Ø2èwhž¸ÉÇ–´oÁ9É!S?È–ù‚mS=ÙY-›!ßqØä\£H¹Vk'ü;" ?g¾QUc1SËs Ÿ’•ßÒ2H™$ƒ`,¦Kÿck¶–¨®Ë\Ê1 ê_™}AÍ»<óA%€Eû¦´ž*®»I½ö}H5Ó¹oÐu¤m³‡sö(LÌlîh¬VJ'™ÁLO$lÍÁÑ’¬™oÆ×|Ek_Õ¶©BÖzš²™my¸&‘ qÖ…Î’Nù‘˜Áéó%U*]nå£çY:„ªšŠfÊx›cèïù)KÛµ…ü/vŠ>9i†0y9E›,ÙÔ-Õ’Ë´IØ›‚S´Úlÿh —}²•TLÐñ5¾O¢çèÜ:팫 °ƒ>ÉÁS:RªÒã¸,(U%ïÛaâ˜*fªì©òÆBi"Œ}×Ê¢àÈ3U˜cª@¯ r`ÆL•Ú3U&„|ÄZr~T~%+ÕÂù<á´¬ žÏÓò¾£ŽŠž§²#ÓzÔS-P„|}²_жiz2‚šC¦Ÿã⺾‹ÆÅß÷(Â@œ’ÖqJf¼ò?QA²rvó­ oHD¾yßq‡ÎqJ4ɖΤËû0@úc™Ž±]ZO3ÿ¿´ ›; …3ÄÌë˜ïŽ©b«Õ ã5µLLaŽ(² gÃí¹nŸÐäÈ)Ñc/¹ùÃÐ×'QDA»¡ÕQ;†¦g3ó½™?\5âýUµÕ›ÔÖ 3Qÿ¡Ço¿åýýO¯@íŒ'Y¹mZ&z;|(¿ÏÙM‹ñvß6= öq!§¡•šUôZ‡x^ën ¡ŽGè„D¢ÇY5•[ bŸàšÉ¥Ú»žÜázz‘\Áq ‹ë),ó™ïÚ)¼[†˜Ä¾gB®y»ónןU¬ž=PÞ7¡ÂOHŠiÝy5Ó#ŸjÚ{U‡'½&þX5m†A]×v꜂gϸ»îû›ˆ‹˜ÁÑ1ycÇQÝ h|7`Z>û]âõóAmpÅ´B®cÑî`Íúúù=ä !¯Óêù¬÷)¯ˆÝî©L¶Š©l^8$À;¯5 Ç…¯+þïñìŠû<Æv"ÃPt>gpÈÓ\Qk÷3à1:drÑQìWXO‡|]tÉ“3™b }Ši‰Žúÿ„]É’ë¨ý¥òˆ¼ìý»ÕŸ€FšˆûõR–ݫڜPÙ²™É†y÷šXôsý¸ÛRà ‰™ê¹ËlпѮ°Z¡=òÈÂ*Ý0ºpÕΓaÃu?' 5±ÖVM[µ¥ê)µ©4@fQ•çz²T¸j¨ôÚ0ty¼‡Å¹b‘¨¢v›Ègì°à…ˆr&Lij-aÛ¾<FÎL¢Ü{Õ0a¹AäID».DH>÷ó 7°‚ù‚IŸä†ð=‡¼Ÿ¬TZÒ?Äçó=ÊÓQGrA›Oae¸<z¨¥Šy"zá·ášè‹ÆRS›â7:A”ezR—FV°Ë PÚÌA¶]í´É>ÝåêÆM(UÌž";¿&'¡É0$}ed]FQùƒ?”hAÏD2\úf]oñ»i àD:ø«·¥ÑÓØ(†–Í÷I’èšÐfþqMqM—v"%#¼æ©»éŠ'¹— ^óžþÔÄ‹ŽÔF̃=‚CBÿ[3”4î¦|îD>?®ÉÕîÒ㓵”u -º>¿…z«Æc‡È¡Þ”…*(‰Ä}õvÚúÔDâž„zÈ®(F➆zGäós#£ÏΙ0 ]t>].™°lÂu»OãÏNîñkåœÐBýôùz#$;²(ÕïÞ`JòzV×-m»ï$ì›iئ™{êH™ëçpͤé2J"[+â:5ßò‘†çÖîs<Å0Aä3ެõoiÜM‡VéÃÜb€Dq¼\ÙG^=Éjãjt@f~sîFfUäy»òyÛòuò$3#> £t;üD™ŠEm”ˆ!áóI¬ø$P"†üg×ÕE¶Xm#ªôÈdUüû›E–YýkA‚*JãCÿ~[ͺªÄ™Ô!vÌ W°B=#¥ôQÈ(‰}§2ÖšÊ8äã¼k4•qȧ¬â@£l¢”T,ÞÏïž)sܹR)æ_·o:‰ãÌFÕ™¶á׌ëü®Õ z“±ßžp¬¥Bßq»ú™5I3ÏüDº¶aù®y4êH#9úp€Œn÷ê"Ðw{6ò°~Þ‡Hã¥ìŒŽ5û^ó§»µ ð¤UÑn ý0M'%5Ë™ F·ç‰ÿ­^ðtxqC@R¡<íﮣ*¨Z÷ðÔeÇp7:Ñ‹Î΂Hçþ?ûvØñAW¶¶ \C5Ò¹l(¤ªÙ‡øÅÞ0 -­I#§.Ĥ8ä#%ö;xÝAÓŽÏœCdfëíÀ›M°¢å-@¢Â“¸ÃÞ^_…'2ˆ÷P*±±æÝŒÒV6«Î'ÈÑÞbo H™`TTØGW9dú76ñEž)Îçøk¢„ÞàM‚íZ²uié¼ä#õÊ!%9ËuÁmøœÏO¨EÄÿž};nÙùZCäõ“„jž×Lê:?·Q÷S5¦]m¢ƒ`5ÊΩ“Ïðš4–ÓKtÜãØ/¬ùüt0Ó—^ùI©9Œô´¯]â~ ûQ"XõN·b¹•2Q"X=…­r†ßݹCŸœáàpŠ€`Õ¥d8ËÍÊó9¾ÇocÒøÊ7bæèþ:„)V¯ìÄH˺Ï@Æcó¢v3Hí«gżæý<8Öïú{ÿøW†õ>.Q"l=•i!?z\ÎdÚæ¿síÇÂ}Ñã èqØó¹¬¨b/‡nH(Óv;)dÝUýa¦k [Â5Å:ð ï)ÒOYÔçÔ…Ÿó˜£bzÄÀ`”È@ÏŽ|+S !>w¿ŒÒã(¦©M"kk§Vë°$Zš BõÚM±Åß}0¨D¹“r&%D^']z‡Ÿ«uQõÀáš·pÖd’ïL»½HÉ›EN ¾ñûaÎh/å4ä#!¶W–ÙݱiÑù a y h6âc÷åê¢ ð¿£X«Vn-÷~*›¾ s÷G³D>qæ?:ùíù²5‹>g+]ŴСʧ­¢éÖZë`§ªª¼ig¹0”H”­§îåcÿ&)Äçêã0@HSˆOÕÇ„ä™ú˜@õ1JRˆOÕÇ<.v¯ïêc¶¤Gl¦¼Ó6ñNÛ•ë`ý‰ž?_ÏHÞç¸Sa§±[‚ª­B0z^@¨™åI8+Õq)d…!òæýË’í¸ïäÞ®Mx=ž×|#1¬‹GœÏÛ¾‘Q8yýP2Ír­ò˜Aà !ÕÊQ] y=õß¡ªB!ô¼2¾RÈœöË ¡çý;C¥ ÇRÏØPœB\Bð¿f¨ÄfÿyÿÎP ^ô™}ôÆŠ‡#‰ªþîôíw¾90Ú¥®xjÉ4„þyX”uk‘Tý´aCz"P _E{ÌÇ.TÇ^ Àõã û$kͦÚfg€¼Ÿzå¨=q !q艀sùQCS2 ‘ÏTÁäÛ™B=L]Õ@$Š1‚>ÿY]³9 †ž™Åm¦"NOÍ+Õ¾‹åð^Ÿ¸Å"Ž˜žé¢üF.îæ-v¼Ï¨1ŒUûº4£Zí dé‹eÕ ’†Ñ=‡²ìXV;ñÔÄ»ªÒvtð~¾ÒQŸ¨¼Š³æðÎ[â÷®}+74T2_ëvÚà ½|Êëåul³Ïæ\0¯%PÈŠSï1dŽ>΀—ºàÿûëÀë­|;7ñ¹Ÿ¦¹ “ž×õ`KìÙd®æ}žYØ‘^oö´MãÎ=ާÑibî¿ÜÞÈR¡:ð{¾’9èïg/bÉ×”sI‚YJ…PƬÝg*ë³[£„ ×|@6d0"Y„ê8›~? ?C&¼Ÿ4Ý61~"­† µÀ+áÏÁÏ)f9Óh^è-É»ö_žÈfV<2{³AqqI¬ÑÜk7ä5e†YÊ=¼©UŠAä-ò;}B6 ßóœ„zñV/è²h¤d¢*€LÙùÄÇþBë¹Ä@>®±Äórb„…Fú•åÄΦÃ]WŒ›ƒžW"ÿk㟬ä¼Ä¥fßìD¾Ò ;V½\žÏjGâðÎÿÄ’©²¢k2­²jò‘²BC‡˜×Žè×.«ŽaèJxŸ¬ˆº£ÿæf ¥×‘Nírš ½E×»2j ¢™k¾î‡«C´®q»ÏM¤;è#„֬픘lê"jH^iLÁï²) ÈÈ¢+ Ç)çÅÀ9Æ’€¼¥ÏIkk£M0gæy–Y"nS…‹®Ï93VfaŒ‘ý$¶>N謦U=²«A$0´24!¢­‚ZÆ«>ü÷ËQÉÐx³|…]§Ê÷¨Y"˜;7õ•`–æÎ @cW‘ý\þÃTÎù8Zá„5ž+“ý\Oô&¡A‡Þ.á»ß’UÔúøÚ7¯›W¹ŠžÇßè“áÚpàjg‰nêW›ä W›¸Úù« ‘'\íáÀÕvÈ/\í"Ÿ±K ñxLí‹ê˜G&;ˆhÛ~n-èÒtÍêwä, dýk%k¶—Z™ç’—‡kÞR£›+Õ¸b[^Í@ÞϑÖ/ŒäÃÏÝ8R÷ˆÖT'idI «ÙB„ÈBp9o9àçLÓÜt€²QŒœ¯=üïà‹8.ìÎ(©Ú6Íq]>XaÌ&Ìœø9gž“šï ~Î'4Óm ·d <¯ÇøÐçXåy¤t+Îáä'µa™TÕ†ãý|ÞO“‚Jõýœg€üàCÒ±n` o Ct‚á÷Î5§‡Ïù8ŸöèõÎOº²ëÏ7c mR ‘×»ºðg–hæÞ8Zz½ $‡ †Bš[í¸OKõ>sϤËRuÝ?¶¾©\µÚi³ç`xìר=-?=£ªCŸ€ì·D?äôªŸ” ŸƒñR–¦7ZˆHcýÚèE ×4Ëp*ÔHÖiªÒ2gÿýc9EÖ W}y¾ äpÍ8¿ÒÇ$¦?—²Çy¾Ç·ãz?<óγ]?ó… E! òúþ:û†P/^SŠUnÙÃV"*µ!Ï"TÀׄ³ ¿Ñl¾?\ó‘d\¶–÷µˆ2y –Ê®£v_?ñfÞ±Öt¯›|ÈkAÕºðµÌí9eðš‰Q¨“šëЉAÔM8sË®c„Jk{¤¥¨ò!߯|ÈG4Es…ºfÛn;Ö Ÿ~Ò¤ó=mó"°ãHë Qj Özs×µ• 9 Uu‰èLŸì.«î'&‹œ¦€|Íøìâ¾û>䙯֭³³£;@&A]a6 &œïùÔWyß½Ù¦D¨jyŒßÝïÖé¬*ÊÖVs.–VÌy ?çS#Í]jü¬g¨ %Zx» ‡Dé{d{c©Upb¬Ãú™„<Ú·Ø×7ú-ndÎ㳄bgCßtË5ä±¶»"˜¨k¬ÈÍ¿'’pµ@Æ÷ýàWQyµcn´ÞšÐI&úKc˜X™#/ƒÄ-mÄÌj€¼8 –3Ü÷õ²cÇ”ÏReaˆø1F€ù„5 š2žHÁc`Ç뼓¦+ò–òQÝ/¦VlR ï)ÕŽ¹®ü…ØCquûÖ¼¹­[C:SµÍ‚7 QÓYøÙ™úF Ãs_Ão„|v¼9éuó ¢:«-èƒòÄHGŸ±c1ÏáÝLµ’§\€°sݾqjÍ€È/\€Pß®'Ê;Ø6Š÷ŽY¢VôµªæU VMÔ“%Á‘ÿ¸YCc+@Ù¬zצyKUkN•Þsº“hGíw?ßÄ®ÝÖL`¾Sõ†T ' È•àN°"¼G·” üÇÚø«®ð(b|–¨*ÿÚÝÐ1êÅRa±V〧£í4õo´0¦ËJxM[ýþq¦’.þµ/k*E?ç#¾›µ§k˜¡\ârð«0N¿6-Õ¼m£ L®üì¦Ñ†–|Ý2Ì+±Ž×4¯ñ0ÕêCK€¼Ž’©üÕKÔ0Jó~ÎG:ƒ®¬§ˆÔî¬8«M ÍL—µ:D΢1e%@†Ý×.¹Jõºl! ëMsãÕ…»rZ¨= _§çXœKFÂäèöütB#fí×VþŸ°+YrPÇ–¿Te-{ß7â¾O`”°˜ÌýõOã‘*ª–`&éL™ 5И{z¨¾Žô¼ãemI.Xþl›À "ØŠÞVÕ†,ºÆ4ÔYYò!­Ê”·UÙ*ái¶â—jf-Pñ1ïG»¡µ@…û³už òG̃;ƒ;3 :ì³Ü!a*ÐÖj-¿M6Be>ðEÌÂîdxFÌ;°’ÙÔ‹kwuíG‚ÕG@RﳓÔKkíPRoeá¹?‘­*’¿«E/zˆic~ÛŽ G×E–k†\×î§Ì¶¬}qXct¬?ŸO³ ä9“ø {\òúƒI ù{²·ŒÇSc _\’^O!L;dlë¢5#º˜WÄ´ ùcª£–y;œê +Si Åì&aõXX< ›>wz*•“7ÙÍ;ˆüŸ¿ß¶-^·XmsÕØ „¼Yikß¹4óLª î]x©òtGLñZ†:W/Náýµ?1{^¯unœgÙÞ¥BÃWS@ÕþŸÏÔêÕ‰ê!n–Ifrá’+B>b‘øÆd(­|/r’£Ä¿3ÔCJ;^ªÞÏe¤+[dç3²Cq5+uE*˜–÷„/±ävcØžW-Û b!£½¸ª½fÃRó…5 Ü¥åÚ…c\èÚ¯z¥F¾åy‹,k¿¿sÉQAdõLNöb­ç§ö.ÙÄ3‰˜§±Î“ž?Ð}œÌGþˆ@óéK1GßÙÄ&¢ŽK0»Sq<™fŽ©ë,!£Lß#“ö¨=®eñü3ê# ›V6ɵXX!ðÙ“cæi¶Žj} óÔ ¿š¹×ÉÙˆ‘7œéS³†¨ÍcèqÉ7R»lï‘·H›Ç롪5¤ˆ,Uj?¡Â؇Ñb•ö]üŸÕû¡.+ç… Ùõ3Eò¶Ár¿·iúô`¹–>÷º/µ›ƒ5QúŒËÓ'9P(t–-<[+0gKŸäÈršžÏæaÚ(B>¾ÍÙ ²Ò˜éâæ`m®=³Ï¬¥PO~¬‘[%EµsÉ&+rñ™[„|!uv“Ã~´:{!ÇE ä™åZÓ#,×¤Ê éÜÎo|íÎr 9ži(ÏC‹oèïï·ã™Ô ƬÿÌ9†ÞŽ‡Ï¹z ðÚ¿ÎYW!+áü¯KAV•ÆBÀS‚Ž$ýø_·kI¿aÅÈ I?ø@^·?$ý`a|Ý®%ýO:vÈsI¿ýï|ú;ïEŒ yx¿Õz ¿3–‡üÈ™qå©“êåqOÕ¯²*ÔODIÍ×+£Š­²žñ­ÆÈGØ’¼|)›Jõâ›×= f}9wÄçéëq1~Q‹6zC’‹ñ =Ó²Žy;x—ô¸&ò‰Ê€Æ½Âêbmß /<ÞjƘ*ëo¹f\ŠmÀÈ;’vsÞ³TÈF­M!GoH_mÓÈ™œ‰%Ñ»ôÚµ#õBof³&Ö çáa×’hT@sOõ®ä‘é·”càžŽs -ãWºcfûPY:F©[J_Ñæµçò Íåð17ò¿‘´…ú ç\âc&¡Ìâ·¹ÏÔ4]]ƒ{\úúËAÖº@ŠÙjÚ”v"yû&&Åì)•Ù‡²RãȻΔS7ÈÅ´t¢j ‰¼ë°;q_gŸm£aÜ*&Å8ÉŸÚIé ­¨ª‰S„|exÃÓ›ì6ª*rŽgÔºªrÜ: ð|øÌP¢‰6‘Ö}cäÍø‡µ½ÒT© °l²ªÙª0¤‘>p¸XôŠW›À/&ED›ÿºUÑlÇZ\·ùžµkŸ©½£_–lzÒŽþkŸ¦-SЬjE™AY }œd¼T¤œir(ë¡éH*TVÿ3Ü¥ç—쌻K¹žá„ß‘wåšû Z¯u²˜Y!2H‰3Â5ej©©/‘˜FÞuÞ«ÓÚÏh¿ÊO¶2O@L#ï:Ó,}CÕoF—.k„|ÆIŸ íØ´Ð±Ìx]!ä+|GN!Ü®´´o»!S(Së’ˆ~Ôþ&7ª>f„$±Ó›M·õ(d7NàôæïüOÄëÓFZÔð»LOç´ŠÅl¨M)ÔV¼RÞåò"Ô_|åF…i=ÖSh‹Et(ë W0Û…WÙ™PyWŰ@‡2¡eer9 t\éþ˜xðÛôõhÒ{¦%´Åbÿ6³Ã«%¬²;ü0S9 Õ/(9®=â¯üž¼,t/4öæ ƒ‹¶«$Çdï´M«Ú•ŸÇQŠÏ£1%Ç´+ÿ.÷Ìä’3>û#Šj½€¾v4‘Hþ8däRºi]u‹2>͈‘ÏèÎ7æ›Sw^-K’9‹-¹Í¿!#ÏÇž& žž™›X[Ž’Í»uÃw‰D;§·¦2ÃùB,øìapQ‹Pg‹=÷Í… j‹ÿþã5@Ì}š¹ÊâëiwÔÛ‰¢÷6öÔ“ûUVàüçÆPÒ(‡AÞye ejÀᘠV.ˆt¶2õ˜ä5 òü^ÂÝ$‘Ê<ò­}cäíYMíʺ!LÈ“xFÆTÊH¤~ BÅÁ>æÏÒ³31VSY¯DÈä{Ràx26°:T ¯è_ €F^(B:³±vÖLZôG€5S±±<ãÀ[3É5¶fJÉ^°¬ ck¦”ü¡Ørü;_GÖLZrHd#F^(î®ý\0ô(È_ €aH¤ØÜQ³Oížü™ÞͬRÞð6‘“ùM%}ñŒ< l¤oÃ'µÓÃ'òó{ƸÖiüÆ '?gi¼IÎçÐ=uȃ4Þ$ü™ p'„¼³¸u?2ÞûPÌ!Òø^+ŸGi¼C&|ï1›ÙfpòÔ¿@%jÒ#/V;Ë$€c>®|j¶¶8FßõMµÖ„ú&ùy^!G…\òvÎWã€|ðÕ䎯F~^ðÕ8FÞÏØûgpEéî.Åì}>ˆl•yûf8öþV‡ƒÄü›HW0/û®å8¾ù5ùÝ4Ôu%ÕW§Þ'—b'#;ƒË_mR¯ÑX¬ð;PŸ ð*F*|ȺNlëòëÈgáM¾ôøì¨ÂhG ®[¼mÛ|6„LNØÞ[ S$ðl¾iBÙÎ!oG–ŠÐM4X~ñTGèîkKê©`©è‘%u Ïhž§zÌß™ÛÇ®¿£m5/:Œ ÆÝ•WXPgŸçOß™œi˜ÎÐ9&—Ì!µ‚@ù†ÄÌ¡CW,Ÿð“½ßa¹wÅâ ÓùYéUÊu?cÚ˜.%ˆ9d;N¿U!·L'ÓyÛ+#™‰@£¡$BÞ¿5”,Rˆóq¤¡$µ†Ò&029.+Çå²÷Q2ós6X.Y9Ë¿óµûŠ©³ ×]ŠO)‡ð¿öSž§(èÊç! wþ…æçòÊ “ÿæ†æ’ |ÌG¼&;v×¶ª]“Òð†¤'¦Òh˜f+솿)ÒÜñ)µk 6ôµÚ=r${–?sEmVV#A]‚Ü~®×yà’’Û/YsI뎆•áös>GÅÐr;°y6‰—ŠCÔåPáà qBîÌGa$âo`§BõÅ-cFÃ3 üã„{ÌûiŽr{\å(à r{ |¢°–Ìu´áùRú !»#ýcž»+œiùÁ­¨z¯BnÉθJlsÖó¦æÞ.žD¼ïa÷##~ÈËyùÀþ&¦V«wQl „F"^Ä,ÓÚ  böž'„|î:²ú~êß¹å\â+þŸŽlSÏfå*j O&Aw- ]ØÍÅÉí(^²H/EÑoÄ 8Ô Ño<Çÿ­7Äèa9ä©ÞPÞÒ]#ÇŠ¼ Ç åoSV ²–j¹©Ç(V Ü€(Ô ˜æÔeùRøö Ù»O;ã8´*ÑŸá눹¦LïW°Ï”õb¢#¬`17À·¦¬²Â8gMÝ|jE÷ßËnôöÍØuÈMGÙwIóûyœ4IpúŠ“Õ¶Í£»t¿FÔÒªZK„ggc ZwkÛáÇú ³lzÀÎà”kË 1ó¬ÅoÿOè¿ÔV猵㶽é]iýõ™…+Øë§UäYÍ8Ì’È%Ê–ö«ÂÍS5®]›yPrß»z?è¦ËÔš?aå ÓB†™Ú3ê'dt̳òñ­gµVPâ#Ÿ]uÙ7¤k,x~yì5)TC?CYg¡~;:¡Æ‚tøN{Ÿ;ß.P°!Óí‚ !#Ý:£Ê¥ÞiBMë4å¥FŽN¸±`æï'•¯H„|~ö¥+ìwøŠbm*7mùÉZíA.½/°CÚù'SÛ6#¾Ú3±¬>ÏÇÿN+yáEûZùnJž• œ}§åc®È"3õ`³’ŽyÃH˼ÍÞï© Aߦ«uÕTEÍ}ƒ¯ä¦‹IÍZª ÇdI¼–9^åZÑu‘˲"ä3ZIcP³di¾ÕM/@Z¢“©…n½XPìpÈt‡TÐrUéŠzå9FXqŠŠºi6uv ^¿ÊßùŸH²Ã~pöô¹zøø ¿¿‘·9<%õFqÙ¼wP(3æ¥Ëû=-r®ýŒ…‡Þ%\6n*V§‰ §9Å÷Ô­äˆJÓZ* ôóÈãŠ, ´”ÈãþUIJÓ¶Ý4…^&yœ·©Ö±s‹m*í¹-$ÉÉ4žZÑöæ(ZZQ¢âï>ú×E;­ÖF<€L/RU•7„ÂmD¥9vd,\AâPaÂD¾7O˜ä'ô_Úÿ°Œ%¿­DãÏàŸQr»"tDT’ÜwÁ#uÜxÓTÉ6 }‚Çúó²ŸGA— ŠÖÉ_'Ï+ù˸|˜¼vôð½<£$ýC‚ „¼ƒØ0òB6ä$ýCbwÌä´= †V$!WíIÚ“$!×íÉ"œ\¶'GhO’„œ¶'GÔž$ 9mOލ=éíI‰çi{r„ö¤Cžµ'›î®ý¢=)ñµ_µ'a¹IÈΠ ?%©»T¨€uðX­ eEÝ*²~:Ù• ó´µÇ×N\íñbÙüô®C>.O€ü“ð´"äáIîOäoÂÓ„W„'ü;¯Oøw^ž0òœð´zÂù›ð„I|IT½K®$:°—DŸ Ép#šorrÑêÖÒÍ_Ä4&$GÁwr$¢ÈQH„¼’£y GÁwräù<‘£à;9 ò|î¬å½ðf£ëií›üú’£ðvõU&‹eÚ!o>jØÉQÈ­‡vZä-w©±²Õ[önš¹ÃÇ|D$_@TûpÝg3´ƒ·Ðò¯>fíÅZ´y_/û¶ÅÈg„´Z¿šx"Ê^µFÈPðpF׆(Ü.ŒæaeˆÈÜŽšï¯}TŸé0,!o¸fë—ºVHîË iϽ0L0„C^¸4ó$fý:O‚¼öÍûŠz‹Å® 2hó¿~QTk+µ‰­ª¾¥D†Id„c¥Ë*÷Ö±:{k&‹Ÿå#¯‹²µ+º†)cš5¾ÔôºŒ½Áì°{H»^wl7a Üîw 1ô›§1‘ˆwâÃVDŠç* ÙÞ`®C"Þ‰›ÞevŽQŪu7N5ÇgO„Làáë±—Kiì[׳wKåR@!2­qf06•ÒC”wbåBÆÚ“øç÷ÜÔu^Cã-˜ÖXVÛnsSm™úädô;ƒ5²EšbœF~æY!A°„¼)GöKºµ ä ®è¹°‚Ozý,FQU >OëÅÖ+“C[sË ŒÉ+–äU{q^9î…Ú m”ämHÄzùÎfŒq8\Ñë@îÕ¼KVòdêIÄPùÏÿ|!ÒìðFò”Ñò‰Ï{IE6lÍCƒð…l‘ôc¦²³a‡|`U2ª“lðÙ“XŒÍç‘}6 ÁJÀ!Ÿ@µ·Ó4›·ºê¹ÀÇ|űMåbªÒý äéi$Íj/H]6Ï EH4å ,ۦγú½îî<”„2/i£¡´XÕwÜaèïÀsÛtÝ0€­©‡žhd~ägœZ ¢£VëK}Ì\=ö…©g!1ôq¨§©UGAHÕC“cAM6ÙQtŠjf=ø–"Sí¡V¨HqKß2à Uh-Ùî¨iÔÙré0¾YÏXnA›ˆ+§"6ôCS‡ÉªÈ œs,abâ+­x5Áfâ%m,ïI-¹“”(¤’ôç„ÙÌÏÔî Ìf’þž#‡‹=ò-4zƒ‰¥ô7J+öÌfN‡ô÷lÙ uƒd:¢giåíRæŠ||ìUìЇcÞwê!í¦ÝVð ’Äôq¤âà}zÕ‘ÁÙ“½‡V“o´Û÷ˆq_Áæ^¦²ŸOŸc$T·½’CöŸ¬ÇgªÛ~SÖM.ÆÚ48dr‚ìøùN9E\ï3 §(u³úF.ÎÑó/¥"®c¯HÁÿÒÊ"kG ¿ƒÞ§Ž<Ûþ4ã?ŸÏÏýk,Cä³W¯qù!bÖ…Ì•cüÝ/—˯¢kC[·yä ¤æ¼»S‹ÐÔR8f––¿ì[ZÑRGYµï†ÑÈ+H†oÏnÌ<ï‹|r¬ LË_^ìd"¢“´ß™¥Å"]“MƒÝ!-kBÍÖJpK}˜†øžµ;ä#¶BiX埻ä½ßé4òvª_8ö¬'¾ª¤‘ÙîÞí¹ÊܻҫDä-ñBrº:ÂYØŠ<3Ñ#³c]U$”<ò~ctch4ÐÈûÏFåûÂ=òwÏ-çµížm#+|À"ˆÝ‘IØ‘¹ãñÈ[â”\ZJ¨Ùé†zž…È„-S;Ç£!-%]%È;ô?¶^3­‹B:ÿLÜž»²eO÷4yn´¿‚o‘GÚ>¤-Ù*—kd•¯Íè„ <2ô!!sC[€Ã ©dµ’ÎÒûÀBeÔŽb¾ æ‘‰GqY ¾J“—›ºÎ|” Ø×išÔŒ0$éî!ÅŽkÓ¯µíÉ”`Áøœ;Eò5I)_£´{&C&]«h€žºy+¯a¨¡Ï$uîÕM·(CGÌ…y¡ÃW÷JÜ4þ—äHf<#";Á8@t¦7m’“NI€Ì޵”·³wó}ÒÁaS„F~² Ae]•õû¸F¥|²YH*åBˆ¿÷+\Cs»}ØîÓ¦¥¨XG€´ëˆÓ€µQ£>ŽŠ¡ƒH{ï›ûƒ‘€Ý”]ù$T‡ QäýŒ….—ðŒ®·_,ôb; ·#n¹á¿3µÂ1î¬ÉømÍ#!Ë2.dÈ:#:dgùˆ¹ /eR¨%F>碑°ÁÆø8ŸQŽJý’а#^³½—‡KÜë{Ǭ¨{9d<ˆu¥éVZŒ*ç…­Ì3rΨã²XJ Ÿ…õAµÒï(íés½‡“ìˆìIî"fLzú|ÑwëÔc:¿óôdÓ°qé[ø;?‰g­_YnäìÄ4Á™¿$Áˆ;è iP%$œzçYµkì2çn!x˜ûDæçÏ¿·§vù$…þ75ùøÔç?RAä-:·âO·EìB÷ú`ÙùÕþð¯>Lùãê+ÈÃÕ(²käkÇÇH\†ôR7!rHYGMX,D8×½WÔvU¬’Ã4,™6a‘ݘ÷£HLéHLøÖ?ü|—–*â¢Pƪu¤y;òËb²7~Y ÕÒ­Óz‹Ù } # Z{Á$¼£We¬ê’X .} Y‰ ñ¹GUÈ¿[_2v›‚qÖÒ{2UpÌO<§˜ܶ{l8Ö„õûvòcV¡ÙìÆÖ™´£_n׌…5òv*ô8Z¡G·#…žrä42û騄5r§}Êj­/«q€¼}˨/–Adö],£®X¢ÐÛì ±F} Žùø®€Q_Ãù-TÑÝ|~¾‹OÜŸ$œùKJ)³Y)Š Up>¹”lêUŬù´Zõ«Dº²È@Ö7T2™VÖ¶Œd”4¨°ãº:°>H¯~OmÎ$š!<‹Y…3!›B“8º™Ä ñàw{hÙm½ª’ú·´‹_Rº§Si󂯍m—9‘ *m.`3Çø±ÄÍ8Uqê__*m¶Tcã<‘"e#¢F=ÈÇ7ýe®W¹­ùô4T_t–XégDò¶V¢'-Eƒ òíû·rš{C8©W½Üa€ü x)FÎá½ûª³å^…úOYú§tzM?O߈U‡k+"ðú×pB6k¨ËÉ©|(ÐJVxS×Ì[:ÛÎ2+ǯ?i5Ö„Þ½æˆåÀ`[Vš›b,Û B‰ ÿ毰••DÙãœp}&IAËZ7œ¹¦ ë}ùsj^ùCzÛ´®G¾ìnë¸6¸FBzEÆzåá¶ö 丩G ‘Šê'¢2JV…Ó0ÂEÍ×< ?¹î¸ãú©’‚ ¢Ok#@ZmƒÝïäúwê³w Ù‘HŸÓ ðcf—_ÄãCìgvýÑ/ôºb—ìv"~×rcU"ã¹;eñºSªÝF,o^¡e) åòÖ Âä›d‹=òžGÈAo|²˜ òáãàÜhØ8ùå™HÆbþ.‹' ¿›À¬—ФlùÄŠ±Èײ§a¯Íâ è°ò·†S?pøÚZm\I,X£w;ŸÙ;g•Ø‘3M%`a9gaæŸ'ÕÄÖfúDˆr"/ùX'æ³Ìô}çÖÃÌ'Îÿ¸èÖex:® Ñm¶üó÷OšEæ•uúè¯rËáüŸ²-•¶®c¶Í‘u‡Ì¾ULK¥`I„wß¹Vîµ39d(´ÈÿΔC 2æ›ñsQyB}Ò³´†¯ø~5ŽÚE¢á ùMû"2æ—#íëØM&AÞwž¤Ø úð2!Åjì[¨Çe oIߌealRÞlž¦8=._Ï~¿ÊG\ç™>MÛâaž&ïõ¾]Ô¹ó¢ÝZ<¸>òÓðêwÀoß5üö¾)Öˆ~\vn寗6m¯ã¨ðR‡5ùqn…KÝ™«7˜õå0䎱n£&1¨bæs a½¶ÜŸmæUÍÛä'¡’UÎsG¶>©)ÄáÌ_›– »Íë/‰¼€ÐdOÀnOÐs?à®ÐDZ,™R½ÅS§ôš(°yOV ­õkRw+„ÞwP;j½p´ö„> "«ËÏ­hÛq÷î¥ìe¨l§¶Û½(6üûç{ªÖ‘ ª&…&u¼‘¿¶´ãJéz‹è_þë¹}ØÆ`åþ#M¬¾Œ9 ”}¾)ÒÎ<$ØÆå¿¾ýѵ !Aj±†dÊ#‘e2ÖTvS6I{4Td 4œ­Ù®u¦Þò.&¼,çrì‡&<þ;l©ÜBkw5uú3%a«}ÄÔƒát¡ $©ç¾XˆeÂGL=üÙqºxWš°"CË!·^jˆ®™æ+—ÎhǹiÔ<…óÚãñ½@5ÎZc.wÈÛn ³\×MÔ¤f™i³èÜ6¦<§acz<@‰ÔÒëI‹©Ž$F€|Äô¥× ¡Lê[4Âßù<Úè•bkMXó %Ó ½¾ò DÎóã™<ͯâjâ €<+“hçŽI’¼"ˆ«iäë?’¼ñê¯+yºYÉ#o%ï‘?’¼»1C’·ÈC±†¨e¨‹ï'¯BNV8I ÑÅï=nÊ® ám"sI1FƒT™öb gÿGRø;0nKŠžÏˉ=ÆXpó˜²O¸‘P*ÔYs}¨ô‡é”ù•%|lÂj“° #Âû½¹3kQ°°ÖíØ‰[0f«¸’`Jû˜~ÂC}î[5SŒ’ª©F€¼Z’™jûJ!ò$h¬õ9<ÍÔ’ìXŒ6Œùü2$ÞØº’¼ïÿÜŸ¯3ó\g,Ñç î!+߇¬;«²ò}Èš˜XE{Э€^P¡LÝ#_—yîÖgB,ŒÚQÃC)3á‰Ù¯Ãz±Ñåï‘Úpð|ÅP6OÐÜZ§…µî•ˆ¼î™otPý²†òýë…}KÄV¡ÜZ"–1Q_—ä ÿ'‘ä™Ù\ ¼ÂÌ'|¶·"™×7‚\¼Ñ˜GÂú ˆÉœ&€ÌR‘¡:ä9y…çxG·sË<„ Èà;£[*é$ª°Ã¦ÎP–áì’æF¨/bƒÄjo‰ËFÊÖ¡ù€Hçÿ¢¯_¡p˜Mœ¡ ûŒ­W†q+˜cMŒp¼ ­‚³ô†2?v‡èl š òs*hÝ„!áþq­ ®¹GI*ÁÂÁ3áÝçáãòlÏ(GÜ*Hhx=¿8'«(:²ŠF¾ŽÌ ­^ßjóýÃ÷G†güIè7{¥þ0Ç`•x¿DªÌá,­¼ÂTOÔæu!³”Re\eÒNgÚ(ý½¿É*«¼^CûWêæãŒöê&ÁX÷ú¤ÀòvŒÕæo(‰šÞr©æjªÑ,á˜÷拉‰X”\¼ ˆG>ŽäŸ«YöcšpÞI*ò/fYýÅÀTÛäðê©HӲ϶H8æ;u›rcæÝ„Ù8†#êÚ[]”íÛTz×ËCHˆ%žGÐÎÒ¬Ÿã‚F‘Y"¬å¾£Ê¨À)V‡59z¥HsF@U5IO(‰ç‘“3ll\·ÉJ\/á­{œ§¹˜”}_× ’W6ºÐÈ¢—JÕpÌ,iì±Jɦ¹EÂ=—@ÞEöùHR(®¦åkÁ ®ÏÙØjšFb>*Žáï|Edí28-G:-T¯ò"mƒ»AcË)IÉ"I@j å…39„޲ q±KHJÚà0*¯W»çyK¡¶!ACsUÐ<Ï!4;„ÖÊ÷Ð$/U5›ZÑÇS¬ç^ 4MLmP´c¡–š#„> ÓÍ÷дµ*¤¦}ö芡„ÐwZ±º›:B¼M?@èç;5ŒS¥>‹ ¾ý—¨‚æÒëæ 9çd‚£Þbrª¬\ÆI¿ÕDÍy)áo½Ýb×-v¯à0v´åÈvŸ_ö G}‹Ã/àf)eF(ÄôÿÙâïÔ΃¤ Bú°Ð? ´"m³2< Ýo}zšÁ¼m}pzœ;RÈ~Ö·—ZN[å²c|àåÐôúh ¡ï#¦Úºš²E8Ò¿ÓÎ×?6p¯] Ù°±˜d0ÛÛâTgi?µ¢‡cf 9eÕ›ë B•ŽyOúÍkßÓ¹J´ ¸h¥¶s¦0zéå:Æãw´RÛu¾š0’Içëû\ÜmLÅÝ4ò·¸›Œ^ ÷Îy3»Ò»©àzCWÎû—¿Œà r¿|._¾é޵Â0­§j 3ÿ¹‚ÓÒtrx¡znY·÷nR Ÿ¥„'wèÞ-B’âËvÌ5·™p¼àd(«ð;3Èâ­¼1Þºv:Ú X2Ôÿr—h4=1¢†&2åd»À]FE^<_òžöò:V™~F\Çím ØÕ¥JÚ³…„Ω„ý޵V…C6b«Š€|¥l-ŸÊ),åŽ7)ûͲ°³GÓ¾($¼úç[‡ÜøY­F‡<Œyanê3b,eõÁ> _H/æÈ{)9 aîç±Ó¤Å.õ g~]s#Gi¯bmµ=ôÁ2'úÓ ßûçùÓèo-Dºê£³öÇo#Ë[C¨—:‰ý/:SlõTÅ*B¿Þ絓?ñoˆ~çÚ¢¦É—ý³…¹µM‰¶=éôÓTq–^;׃*˜¿Ê^¯´±÷óµ¸ÝxCªžñ2&û>ï};Hƒlºn…È,¾ÉÆ[sõcz—cjl9@‚" HÚ÷c¼£÷î€Q¹žJ œ¡"¬Š‰“ØAÀT¨á½¿NÊæÄ‘ï“2€IFCä°]]÷†0@EH9}v|èÒ?£™é†qÀ)ïͦÜáʰ…Ê¥.s )[ˆøï]´úê(®!Ÿ=7ÔÿN2O˜×K>äà wÙ™·-ks)­óyÖµ3†®ëåK©"ˆBQDh…Òȶ³™$÷;‚ò<¼!×Ëm¿s9&Ÿž%„å(üW|M]̶¤yTÑ_-ë.‡È(h’èEsý½£Ðëp.fǼ/´ª‘çD›Im(W\#Gí@.±îÖÈo;Û:4Jª‰ fþ;lïݤƒõvÌÈ[l4rŸ6`Ÿ¥ê×Ò‰-ydšPpo²—‡2Gc«ÒÖõÓd¤A|ð©1‡|ÄÔƒ%Do+ÒÏr®áÕŸ‰Ä—3§…±¦ëÐ$à‚[v;g®§qqÆÌù>ñÁ1ŽáŽ^_1­ÍF ÉõkU¢xGoØë|[ÌžeZ¸ãûùÙ;)¸Þ˜»w¦…"o§=m^>ê~=`^ž6/Úë‘ç=mû1{Úˆ,dè?»^/ÀÆY/[$Ëe7Ïíâ‘×½Ôh]ÏZeÙ¶ o©ãƒu1n‹ë¥Öû4yd–Z¡çÊ‘Ëy@í@ò~ ’oú(’Â1‡Ò|›•Kp›3ïUè;tÈgÔÒ0·¾uV­y.TÞc8æ+î^ôDG€¤‹®-=2Ê%{Õw;ŸFË.‹\j€¼}sÛ'Ô¶ŠžÛî‘YàL·Š¦ëÚtpÌûNÅìÓŒê:Çá{¿&޹5Ñ 3K8$ÑòETHí¨lÝD–¥.vÈ׉c£>ùTÎ52Ù&„• S×¼Ÿ#S×#@Þb»MŽDû%¤2KÝȦ ²içP} )áÕï~ÏËÒu|–rÄ·Óâ#Àìr’Óë'ȃ]³3…<ým"ý(½BžFÞΑBPºGjéáMKÏg®Ùm?ó®ýH/öÁE¾£,–º¿U÷ôD¦ºC>ím~%ú|¤œÃ˜èÿBª™䡸/ÕKHrŽËÉHØ7³Çoo2%@ÞNW°øuD¶Àbv G¬Ö/»~é†bm2Õajˆõæ•“,ø"þ™íÃV©yË×uK‰Ø2dÚze·bÂ%PŽª2•¾Þz‚ÍÂÐY¿ÈBä=Qª[’o°ÏrÈGY™ÅF¯‹mÛUúæ±*2‰T±»ºÏ+ ¯@·Ûˆy›|èºêWT‡"ùþÎ';Cl @&§òºö9+“O.½QŠG¦ÌQÒøïHc‹² wôor’ÑÕÿóFÐ Áºò´»e2‹áþ´ÛM‹±âaËິÏè2ö£,1¢ø×+9™ÆËvZ€|ÆvCGÀ6+í œ ‡Ldé±k¬ÑÏG,9¯Ã¾™}NN»‚Z›–°sO®¿6Zkëf.IáUK5òzÀ<Á!R¥1¸_¿ýµ+—13õ^ÖAä!ï…¦ ¹w´ßäLN X,ÔªrÌ ß®åp¹t}\t ‚òv¨Ýh#ÿ~á¿–Wí½‡Y+]˜Ï}ñ~;Ãê!Û±Ò;£á„²cžläíÈ×òJÒ\ùþŸ°+Y–›e–¯tZ=žå·ÿa?@M …Ÿþ2”N·¯ŽpDº%!EUe&þÍÜa/H”mJèn×|«2?í}8«„:¬§BÞaýÌO|+åf$ðÕ(fð­êæ,%µu„ËÉ© ö°æêt#Jªìmf­ÀHy«^ˆâÕÞéçöøÀ0läJlÏÑZ0[‚ß|ýË1üÐgdî\Û¬e£æ Ï~Ö€$·Ü`!®Š‡4ç]¨ñä=)%y#8f•!VUS3Gòñ–£/[.¥ù„¶H—·qÙ->ô“˜ª _ý•øNª«]kÛejŒüÎÅj}kwyT¬„ÜZù¯÷Çrpýåxüwl~õ˜l“1~¦ |»Ô[ÄF")ŸH ›B€^ÓZZ›â«™ø Cí‹Ò¿ÂqÊóßÇQš ^îì½CVíD{ì0Õ+UÂWÏõ’\#Ä«fã6çZÁ*šÑN¼YŠ]™ÝwçØ‰Êr¹ç­oïbKÈåd’·¾·1fd3¤¿½M¨ûóvp–bõŒÎñWǽÛ5šy'Žm‚¸%£süõ»|Û=­õÎ"#ÁË`…a[µ&3 f¬à‰Ø®$Ä6ƒ±ÖãÄ{Ø»ïS¾ EãѶºJ«6‰×¼™/Ú-ÛǽQzbÕí&¦ùzðJ2½Ð>› Λ8¬$2eo2¢|õn«ë+Òˆ½\F¢8Æ5gSå10ò's»*4t¸:ŽÍiA d2@ô*ânÿjfvYµ#$Ô†Ê`^íXŽmµWBàß¼åÔ‹6ÔÞK2@TŸ’úAèèZZ%„.«øŽ2K®xuÿ›¶ÝD‚éê¹%êj0ÔvZ6*žSعÛÇl¯Â[uj%²À¸ŸK¬]ÍÈÃe$Lgņ˜å-Šo—ÌÀ*Œ"¤›B^×½¤~6ÛW9”PsyÜ3ß„´ÍVÓQFÕ±€L,ŽäöÙ¡6‘ƒ¦Õ„÷„da—¯‡afz§×}ÜÑ™×–Ö}ËxO¶žM£ñ³?ß {‹ä v™Gl6ÝmÖîO,ôµ]©ËAR]E¢€üþéK{ŒÝd¶#1Áx¦u>j${ÈÚlqb1a½FÈ=»×ð6Á:3±:Ôm3£­3rÛØ^1^"ä Úí Í… ºn–¹3O„9í†d‡õ"7Ë'ì\‰n®ž¼Û±1s›û„ŧû¤ ª3`´µ[Þ?MEÃú©ø<ôk© f£-ÿD¶^î¿#5nëÜWJTyÏ;:º`hsUî#ìÚ-*ô¨Ð¨á]“èÆaFÈÔ5ZÅÕ{Ö›ªÆ}T !¯é½GIÀ^µLMf†T™Á:lmdêRhü›YFÈ*ž¹¶æ’ONIØKcgò¯?!›o{¨Æ¦#3W;þMh­ã!©ãÍ Ìq‚Šäãäk_{ éÖÍ-ðÞ¿Os=ûÂwÈ`d”°¿Ø #ß”TV±Ç/ ³9ßú¦m3—Úm«ra™ëÖ·¡³~´Y4ŒgnGö7ìq!^ª‡Þ|G°æ4³?^¹Ðçy¤°j®ãY¦D3ó÷IÛ&ì†CkÖïq‡3 »x/ú`V3ëÔ"ðob–Yd4lÖ#÷„|¼dQNiq„•äû=H¨ªõúúgUk9#‹w½‘ÖÖ>ë¢<¹J"¤Yô R!d²&v¢$>ËJ7ó¿Ttö¸¼Š·Œ¶–ÚlÉÁ2y06Q7ÓŠËVÌÊ»"$ŸrñØÖ®ÇÊÛà«ßNÊè¾ÓÀêÎA¯âLئž lîsâTLQ„6 ù9È­¶­7ñà^í!ŸÉh:fn×iXmv®ùJzÔ³æ:9 rªÙ •ÜW’øû7ZM¹gg[;î„õ§‘ÿJ~ÇQô®îU© fÐË'ÎL<‰LÐà]Çe’O¹d‚ï87D{.IÐàGe^{WEÑ>©[XwŸ«¬ΓÔ%£Õ›‹{£°'ÛªÎBÍ—Wf5ýëW&ób½WèÄR7_¢ÕgÌ9æï³%% êõÀî'`j¹.²Ÿ§Ëë¸Ae;C×…ÌbQ “uyå¶Ð¡ç18ö ³g;¸Ï´~ë_ÞÃ)1zòá~å¾3ÿ…r&íB9“.ÙÛ|fï觨Ë?ø¯­$-o¡þó:­vðÅóîàe)%tÖ¿cµ†.$AM„ª¶—ï¯S4ÄÀc¬âz­èçר}f¯fÈz[ü:ðoÞbµŸTpŸb§‚ˆaä=«W„ÊÛ(ªeÚØµñï“&äÉ»‹·Íxº‘Çã+¾Î·ÌhEdñ“)ËûÖön¨W ömê«rE2s´#rÀÈk.ï㫎–ÏQ®dK£TdÖ¿ÿxß²6ú–‰n.1òþ&¨L`{´öíœûöíðm2M)@Þçò}ýà 4s²Õ¶5“#äõ£öèöoí__qæþøÛ=Q:2¬¤•yEãé7¯¤ö$vø%ãÔ¾—Úƒ,ãÔ¾—ÚƒóGâÔ¾ñSÉ¥öòö6ˆ{‘Ø·ï–{!²HòS®~î;2¥;VAƾÝå¥1o3m— ò=ß餂‘ãF ’ê#ïàÿW¹³—Í%LdZš>­ŠßÙIÅï¡jt©–•ÁJ›qÝnXÆ^lNKr™fH)#7.Þa7®Ëwn[ð_ÐxwùK©´Ü­ùIDbîoÐNðykRKFÒjó:±®iì´]VsNÏúп_§î³&êâ-ui¥Óºô:‹1Ò60eBË%uæÜ_èÍ :d¬ªqÅÈxQ×±½¥ÍYõª#™¹“6¡#@V’ﬗ!_?=ðÌ×Ñ-²ÓPmNÜßwüW©Àuæò}bøUqíÇ¡«¹Übý§øú:õFïÞud7Ùº'BBÿ¬½ºïCéG»:Œ ™òš÷w‡Žµ¬ìê±FÈôŽš:ø[‡c³ÇiEÈû䪎J²y¿ùÈt#BW,·Ìøc>¢TT‘sCO™wϵ¢|ku4#ßz«fe ÀÏ.¾Š'¶­ê4üæõÔ›ÙtžÝ¸òšóiT·“£_Œ¾Íº4›hV=B¢ˆÏ"˜nUµì!óH¶"±3™•Ùbt÷<»ÜºÕûÜïjÙ„LJ1 Ö¤¹ªÉ^Ñ#ŸYž/4‰)ÞÛ $ìò•¥ùZï¸CÍÉCË¢ñ}§b uT¡›c;Ô+„qä¿ÞÙÌb‚LñuÿÿÄg0ò A†ŸÄgŠÌœóƒøŒBÈ7â3ãI|¦øºÿ?â3±Ü\|a,'³¨ÜÖT‚¦Tñõøð!ÙæÌÃ~H!ýëLbG‚ ­Ì"–^ç©õËuNû–õ…oœ§B©ÙÕ ßÝFn_F‚|AÄ(œêÙÆJ×j„¼¡ƒ‡KtX¥écÙ¥ÂÈû;áÑÒ²@SµøzýÃt¤=’5f@ïäJÔ´,*›ußxi°•О7Hmbÿ¨õ\dí`öÉü¬Ÿ©\–ÁQª@íœôm•÷jÓ‘ârùÜÜØ–à~³8Ë€Ô,šq¹F_˜K—âƒÁ× ¾Ò?4©}/È:mæ°[ŽQ­¸'¹ØP«m±öã¾ÏûO3ù^ŒM”Å‹K·0 ƒi˜Â÷ùLÉêh¨^+³»—#Ø$ÉqKØ*S“†$p@~0 SÇq¥Øœw›-TöT”ñ,¡—Oc”‰"´€e„Æ6µMš½¦Ôœ1ôš7û^s=W»¢§{½Íi.6ãWzÉ›LB¹ï3õ¨^N÷ú€EðËk´:FvÌ ÜÀõƒÓìáAo«¸Üκ!ñXã2¦A‹¤¸Ü?»à‘É12z+7¤NŽ}&ÖJöäËýÜ™šºá9eu½àß¼½é‹í»i:d[ „¼¿w¬[ÇU‰!0MKÖù¢«äD|Ti<ïÿò¶³*ø>?yÛQ©O£”¹6ÓÖw0ŒG%©ÖªÅ#ÿõ¾ÍyYòË?~î°`îTm9"dñ9F$GȈÚfÝKWžESê ta­¸J dÍ)òÿsE¿:ö¦NzjŽaÕù¹Á\¶ðâ¿Oòu°šµ;ضS­Ê‹âӲѾ[B?µÍv¼³£¾"£ÈG±±Î} æÓhªDºúå)Sn•Î9B¾I™Úd‹žX ä5÷õóEìѺ¼rE¢¡IQ?õ„ÃNk»ðÍkÒYDk3ŸÀ .»æƒë{n œ¼ò'Ô˼µzW[Ý"äíí\BE’¢ø±„e³./’ä£%k\¥à}”¯ç«ß?#OW¿Ÿ’-®ûÎÇ*³{¶f‚Âof’BÝÛ¬ü&—†ë©'±ôY!ʧu!5¥Ò'«ÿF•`OGef«-É yûhTþâ3íÞšLÉåH3ù‰“ÀMŒëÍ¢,&š®þBÒq¤rÖhÖDõ–ÌËb¢Ý¿±½§‹Ñ"ÑîOz×í¡Gr°eˆ }nÒ÷Nà€¯8ßÍÀÄàe\mlÚ03.™¯ +ƒ“`§ß¼¾¬©Ø@ïºø‡IŸ#¹œ‘Å{ÿ4çs;¿Ÿ'•#Is9ýÝùƒ´!‹÷§ŠvÙÛ˜6,®×{‡YéSÒ²¸Þ>|ïÎôg_Üõ“´Ì8ô=owFéöÙñÄvSÈ‚Èô¿B²…zG&mN4œeO†zþŒÓjNZ#dñ†>¸™Åså¿ùDe,ºÜ& *Å8¤(øúüÑ„wl“Ô#BfVòu šÇ>Ú³B%ò– +²@Ði77.i†àoWŠ÷É«E6šÈéì.yÅ‚=½}¢Z™[ÅÈÜü›ÆR|(ûR dF(÷æ¶©Ç,&º™¸¾P»+ËûQŒ¬dñÕï™ì( ‹à)U›æ¦FyÇ“("[jµ¬Yœynä ±ŠùpŽÏ)òÑ醂UöÂæXr*2B9œ)YÎ&øÍÛWömæ.-i¶jà-µNÿ¶»vîÆc×i¶Ö‹DÈÛûÖIñÁ}^>Ê÷Ú,–VïD=—Eh­t=B"©‰@®úrÔË‹.c•>Lö [3C$Q!aÖEw'Ûд­lRulñÈL*²f^¹ÝÝlPC¥V„¼e¢’~"wR´3mE!ï™Âu0J“b(Õ¾£[&aûäfí_ËÁ*µCãU@>sâ‹×›ÙfÖNƒÄ¿éõ¿þ dW{0‚Òéz„üÎ3[¯tÑfâq.(¾zÖÑÄÞÝF®RLÓtºüå’5q†æH+F²ìJŶÔEÍ\¾;²ÙÈÁéÄÊÓ  f® Þ‘†Ob:Ô«†ûähÅØÖøå_R*¸ÙònäÄè«N¿ ¹à¦ŠÜŠJuXGÕG#4S o›@Ȭg=w§xe|‘ÖIwK߬M30u‚~gTм­ÄVo„íÓ„gÿ@ÝFo_è7Ñ×|e/@¡•´au *U½^%)KVbh‘7¯ûTç¾²&¬,ñ(®JÓ­ Éàë¿ yiš[[Z޹-mPƒ\«ÆD¹Ý1k„¼fm#̧²œð+S|}Ëœ(P–Ù•»eu¾úýÃ)Õ)¾Åí§ÿ|ôiÍûÁ}> œT þ%H¿ªjï0²€¢«w€"¤Û4@ål–|A:ȢݲæÔÿ~{aÓÖû¥sMÖzÅ÷ùÈÚmÀ–|—µ?Ö!Ÿ¹‹Q‰ð¦2­‘ÌÕÄ9&4ñê²Öû”²#·ÔœêœRB,‹Ãl×ø‰‚gÅ¿3R¿µ[²Åܾ;¼å5ßa¨÷%›Lo‚·`ádNKæá!¯Yøä¥ËmOÂÒk±¥eç‰+@òݸœù¾q8øßž'ÝôèOj‚ +¢Ç{ŽÌÇ3p•¸˜·ÿ#ìʶdU•à/uiUuõã}¿{­}>@PPq¯¿Ì–Õ÷=–"$™‘zql¼ûwÌváÖ½p7„ɶÀk¾bòÔÙ&›¤cë SCäO¦¯éûóØ4³qB]Løø‘ÿ‚¬\KÿZM»Šâ½ešMž“-½”¼ 8N·(nkžP7̪æ,I3«ß7ÈR$á÷|Ñ{MiÖ\òä?ŽT†=©Lí;sZ³f¾¿þês}†Ž‚"mÆ#?ÑQfýt<òþIvBÊxþ}œ-³Ã6n”­ôb·Çiÿx“™lƒðƒ¥ÍD÷Ã"³>KY˜cú’Nµ¹}ðµÏW¼û탽¯4¾QÜ»"»G_³oUµ·sÈb=ÊûlÛ¼¬Û²Èï|û‘lFS1 3ÁâT\LºXxÇ› ï×eNæèPY<Þ­½©§GDÿ2–æO^«Ö÷'È&^é£ÈD!¨‰ÿîúš>¥ï"Ëwä r¯³]6‰s\8“rjœŸïÍÙ¹˜»ëi‡ã×|]’ôœ²W‡—¡Ù²Èëî®cêÃjYTÁ*gÒéü.©4Mo‘–ðxÎÔ¸uÙí™nó.6dæ"Z±éÜê@¬Zjx÷gn÷ãF*{Ę>¯6™µsù™Ïk=Ð¥Bù” /¡Ý­Õ.»mÈŸ+3 ¤ã‘¡0ò_ùQĹ8Q9ë×É-zKŽÍäm®ÊÔÒµðI}Ã¥×Tk½ÌZ£‚ƒŸ.혺Å^ i>ª=f<Ô6*ýç¯ì¸Î \O[S$ì¡ÜyÓåÙt,¢Ú5Äן+s»/p¦6=¯@žB/±ÏP/›X1ÉdT`ð`®‰z¤/ ÷˜°›²›MYÿ\qM2*§­Vè­–QÔùÌÈ3¾B¾hÂRï´ ½ì´¾¦¹{çÛ ˜ŽðRêñ“Y«;jnK5w5·x~ý.üÜÇìG.Ír~FVøYdqeº2rR)'üüÍ…PŽ< Ï“¨pã fWšç³:®N™4ËÉ›UŠYfÞ¬E&£½YM]IΘǘ5“QÞ¬Â{³ÆjQ&£½Y…÷f]à5¯¼Yõù‡oVxÍÞ¬ü8Ýýy•#R:ÚŽÈÜÉD\Þ,žŒQF¤ÑÏÓÙ/(.z¢àªo'G`sM<¦‰Ó¦™ÊØ ö¾ŠúTÓ5{ÛrˆÌ^Qâ{…%@Þ×#x šTïŽ9@¿6ÊäH‰¸&!älá'äwBº¯NÌU¬‹‚we∮Àœ¾¸zI_ò'§SÚ"ºy½|N…#ÿõ‰%I¶ñ€Ð[nãø±úþzÊ+IšÏÜÐ¥ò\ŽÆ iSÄ–ɯÎöV¸/º.jUÁ/@ïyÚÏm¡úA‡z„5â7WÊ0Ï:PUÓB©ç¿ÿ ݦÖòv>6Ò­#üÎмè¤>û¯}ßÓ 6 ¯‹nÚ´KÖ­Sdê8×Ý:i){þÞ­“YÏ'(=ûÔƒ¥¡±^%Ф¤'´²­¼®ý¹:zÔCd,=»¢¿ ó8EG}Dnj♱¸á‘~Cëö=¬žé¤l–—îZ8G42†PäÄdJ6Y{$µ$uM‘€×|æ$Þ§EöÃÖ,SL>“°ë¥ ÈmnKÔnùÊ’)þ®§¿ìû 6ä‘?y_¦k 5Èa›Èé9“§=3Ø_¯‘ «Qµî„æªÖö BíUÉxHÇþõ ÔóÑ4™}´…Ð z„±×s™¥íáõaŽšb­¡GÄÆóõ‰aÃ9%íç v2Úã¢MøZø¹[#òçsYBïá<%“¾¿~QêÆF©;̧ïÛ/jŠÜ(u €ô ®öx㋵ý²›æt÷âƒÕ´pVÓsÜÂ3£kw ãT\¨…ó°5&m{õ­ÓF+oC:h&i{ˆÚIµ sÆá#Ú†µæ1OÚ6x:—Þ—feÝý¶ülL]‡ÞÔ¢aèÅ Y$úNìÕåÒpDP\¾ß: }ÿ€QêËu׋ïçgÒƒ)'RkÖµ´òÚ˜ôYò¤Ï÷ëMÓ†dJ+G,bØšú‘OÞ"†ÊpÙÇŠÄëë4—ZOfnðd2ì$¨ý¯÷®ŸGã:¸žÔ?r;× «M¶Áè"™,[—8oð€PµÇ.5ÌJ°Ž×G©ñÇìfÔ­ |„¿¸jƒÎmƒ†¶+ŠáÝŸ‰1ÀBOy“Iª@~¿Ó‰WæèÄñïÈú¦/¨`”5'dqeï¨`15–õMÿµ)§ðËRŽÔ[MœÉmËÍNƒNÇëþÁ=Áè„#Å£{B‘]_}£Dì˺gÃ7Â^gU1Ö¡v²_Ӈ윭µ´Èò ©âhš0@Þqªnƒà2±}ˆî±ð„E»ÖñZŸú"‹¼Ñ:*òÑIl"å"õÙþý¯2+mè¯Ö?úa¡7¼2þÚÌ1µ% ¦ÌÊ*þï¯HÛ˜À»¿bQ ö5¬‹ÿQê…v Yl“}&áBÉs àÏ×/ºÊØø=…7úù‘@LÍä^Àï îc™âá3ïF>u-®i%Þ½üØÞâ‘ ‹ÜýÐ}`ŠÄ©¬w÷œ²G‡IÙ§ç̎耀¸ÎMÓ3ýÈŠÔ‘ûž6í© \n]1ÓͺUN:PÔ“5ÄÊ?g¥âóÁú”¨Wœ¢Ê¼{öʽ+Å`¹#í¥{W,e]©îL}±dÑÿz3¤‘‡Ähß•jªtT2£“׺ŸsI©¾Ò\ìÆKd™æ|¼„dƒl¶HYË{MÕ?Ps±EÎD>ò¾P·&Û¾P¶ïbȼšÖø,f=Gâ¿™õšúçô´ŠWú6(ý›?T›4Í5êë ‹w “‰CGŽ1h˜¹'¬k퉪ㄋ­K+mæ ›¾ H#õl–™Ɖky4¥é¶AÇ4ÕùÌÓ»^)N¯Éë@¤2¶áÔaÛ4 —‰(|ô@¾Rj&ÄK&5³Œí´tù“Î|AZL?ç¤DCbñÉüWfÇ‚o¼Îã>Ê ¾ü-i®7®úå’8{=ãá€Ð"³€ Û‡¾*ÙŠY$-3—ô–ø*:1: íiLS§ª½/—M -\ =—ÄqçSÿVzæ·+æ¸NÐg' €Êy 59¦Ók}g{]ëu«ô‘Bô:‚sêö ›Š"¬Ÿw†¶&ÿ Êz'Bf†$óˬ+Ú:‚8³îŒË*Û#ª`—yW´§7ÆÞñŽàEo8yûÝ­<êy”_Åïnå(è%”_ůnå³:]³ÌÛ¼«º<Jp™£|á›õYZ`I6ˆ|@?<³D ë‡'¢êe™õ:_"‘Å•sž@#N-;YÝy5BˆÞìãsžürš ñÔ Û_4Í ¡î¼= ÝùnbmX#ʯ;P첊Ÿ^¢d +íºä=Qwp|[Önž@>òø2”¿ã[×t5@>?8µë9B%@~gN0¤m#UVð6½ûã²øæ{ʶ6–kʼÝ×~;Ë=S«ñ¨²¸$&˜~º#ìLeÖî{•;<ÐïžíôÊœ+¯>Çýó‡TEhq„1›¹dÆÿ± 凌 šH ï~ö´^A auWo@>²Uܳ%{#†¼ˆ-xÂy¤s”ÿ¯Í^ù¢A»w3I-Â#¿#Å&re©ZôOµDßh|Aå»ÎæÕOkÅ"2kòê,Ž,gŠZ: ‰ÿÑí]åÈmLf†ÌÕ2įyƒZ¾œèÎJÆGV"ˆ,ÑKˆwOëg,ýÙ‘×+C£Ö~[÷€,>SWô\Z¢^Wy+?H¦ß(´nxdqU 5o4Æ\¤G–€Rh×äV4#®;yÄw¿ŸNž6n#¦@Ú­LÞóåí3Mæ Ù4¸Ñ,nÄ)Keæ ü'´­¸ñ\ØÖmM<Ÿ{$TôJiµa½ÇV||\¸Ã:•ÞR4CtÛéqÚôéoê—5\Úÿ½õº÷iëá5Eñ/¾=ßýEH …ÌŠª ^Þž utJ3é›eë&ÔmH¨»G}ÿ¬›išw€|d­Z>ÂÆï é3 O ^j5Öq#lTbáù}Ñ“kÜœæyë@¾2$Ȇ ®í€üÉ2Ž`²ÕÜ[E[8ò_ÑâÏöc»{ÂØ,ëmƒÐ[õ$~6ª«fj„Z@c»ÑP£`)…„•Õ4<Í‚tÛ¶"}þà ŽÔ-OxÁê•#kÙRÁOê#ÑìJb©ôv¨PЧg}K¥XH×Wít8`zïÌ13Ð2ЬF:uœ§·Wn…Hï´‚ýô¬NÉÇ\ÕN?Û u 9¡Mp°Š¯LÜûnR¤ô±)œþÅíÝO—Ò†6²ÞÓ*ñýæ§ëÔ$lmÄŒ@YôÜhôŸb„ÓzxÍÌ¡·ç^sUëïW‰W¦Jõ×7Èú¦Û£,Ïš˜½%!>&ù8£¦Y¦êñ»lå¨-¼û=ÍêB†:µ-úÜ&6€t7Ó²fû¢‰³=›™¨bÓ˜G>/ÇA52’8<òûÝAÐTV¬{wDB2”ÓwzŠz_êè5Xïµ Ÿ£áÃFxUÇï^|]ÌzaºVã…¹ë Wd–nþî¼Ã3ixMGu ÍXöš†„8ïI.¤LÎå»qO1£ä›ÛtÜx(³öù|Ws4®ØÈ¤?¤ϚÂ/u{eÜë‹âwÝÞ™CägÝ^÷zÐÀ}Öí¥F·"?ëöÎ'äGÝ^IùŒÙFSq‹£DRu|ó3ób·y´:´9¬RßxbküãŠLÕÇ¢ÄÓTÑ *)¶ ½N¡û‹Ý5G¼?N@:åÅÝ*]áÎëZ a–ƒ+@>BÅt‚¹&Ñ׌«MQ~|÷™ñ޵<¾ÑýÔ¸ž³â{”q€Ìý5[§Ÿ:ËmÖ;]@–a”às.tˆÎåy¿O²äãyÏÞý<žƒ¾fŒÜŠ; ‚Õmho1ZhAˆoôxÓ#Ô©ë‘RJ€, Òܾ‰ˆDE,‘·^·LÎ.€€ÈûU‹*³-ªé2Ò–>¥:Ê ”1²®•Èçe‹*3-ªÞýûÃÎÕg;Wñ<­´.%kõÕªq'x»qqáÉíE5ÐZ%ãy!kñ÷îÈ4èÃPTEˆ,sÑŸÀ…Y‰Ð×$ðî÷ëL+7™Öµ¯³ÜRÊõq¾6S[ds#kššu¢3D澿ޓÃPÛf\÷lÈûuþ’×3Uy|\ç$G““äùLÿfã£+}Íz§õØ7ùý^Çê^ÿF7 _Q´  »¦2;‰zM;W"qÿýóï?ÉOwæ­>{OHA¤‹®}ÚÞq¸Ío|ô[ß'¨“[2§Ï¸o Ôîla4íÆ¯ÔÐùÞ‰¢q³ŠÐ·°Á§õtRãX¥‰W~‘ž)§‘ ^–Eeùõ‹iý¢’i}Y~MrÓzÜè¼äýd¾k¥må+–Ý {{.½½G>¯ìígºõC´·÷ÈïŠTþèKº~Þh½«V€|e6‡­ãÄ›ÃN’MÂçüI]UÔ|"}ÍuZ¢˜‡aä¿Â­lÞÖr T? ËØÇür’¶¸R>7Ÿ"‹ÊçÇL•Èòƒòù|( ‘÷äŒEZÔØ$§ç||xNà 4Ö¸RhGgä'…v„Ä ‘¿ˆÅH(ë8±äN"Be.Öq)"Ä!²Ìó¡îŸ30ûÈDp„(Ëû '”˜D0ÊL¬ã=oKÅÒ¥‘‡î.I¸à0žñuÍÓ(=`µ Åže™;ÞcL_ž\C7›Ò¦Žx–ÎÅ:¬w„yNòwbšb\[>ß8¡Fº¶¬ÚS†·LÙ™ÿä=¤ú|ȦU^óq%~"€0Q™¤BÞ‘@˜¨,aÍ9“„’è8?PؽÊ×»‰E¶²Qtá(¸•%¬9×Î2Åî^Ͷ*½É €ŒùP3aï±s<BdlgCNe× éAª‰½ÈG xQC3ëên‹šóùÌZu ƒ×yÌOäíýW^çMZw^'w™àuÞ{¯ó^óþɽZ9¼f<}Ö­´7q8¥z. qöe;“g&û½Þf9ÎL\6o»:6?âé3ˆ<^·’ªª+J§¿Ç rðšá±v>ö¥‹wÜ~Êß2Ö˜W1ÎÈšömˆñË¡^Xaž‰Ñ$È"c÷8U ÃîÙä¾Ð=<îÀ.ÕÆu$ªO ¬žã(e~N­Bo6ªVéÆÓä<oß ·y—S;ÍY&N£“&ÒñzÓŠQ©mQø#¯¦ª|«­áк®Åžj/Œ¥éT~†ndØÞ昹|œo°¯çôK‹Ö‘ˆà¾ë‘™àMë䈻©§h`’÷a„Mû®“6½Úw¥à5“ÿ MÀnÎ*=ÙÛ~ȸÛ97F{ª·™PÁˆŒ»]eòRîåk}@ õ+@fÕÔXx•Ú—5§‘ÿÊêž¾@L§¹'’ˆÐ& ~ãÓÞ§jê;ÔXë²X\xdÕÔÌCÞ¬·­‰¶k¾œà•›ÛºÒsÓvm-+´¾ô's v®ë]¯—ž©vàìwÕTk”mb[¤¥HÚTP·Póµ” £Bд™ðÚ7ø„]Ù’¤,}¥îÒÚ.çþŸˆùÁQqA…è§ÿYR«ª£çòŒå Ir ½¨q©®B¬K<”ß¼dZ»\˜ŽgtÈóüø¥¦qüµm|-u6dƒ¨þT/Q¶±·KiÖÊV½„ø\n¨úYÖfƒ'çzGY;ŽSP2ºw`ð‘{‘óh{.&¨¶¯!ÑM'••W«ÏšT,“#ͪ௳·]Y’aß÷&Ì&Ai¢†4UÙÏJýU­1§1òy͹‹¯é\ DaBFbûºôbû†ÆI—ÉõñAlOdwD‚A’f®¹íŸGdXµFFGÍToí³„¼„ ÇÂñOgΖ}›3‰Ç^뛾ÎeÏ–œ“[lši˜Vî<5sž—Ì+#òrÞ«Ôjgõ_ LÄ!“w;º!Ÿ/¹}#fU>š=£|TU1ór0Ÿ-kgØ-ªt*M"ƒ ¿kdùh´«i½e :J‘ÁþumÞ½©>ºÈ`Ò­ r^6Ò.[ Ïý–¬Z'ÓÌZÏUŽù"óªúM•Ϊ[´§úã9®ÞØÕ@öë‚Á„S{â{)ÄLY?ÔpÌôÈ im„ëèLT± 5vdcµ Ç8ΛD¶¯5}P»Þn¿hú r¾Ýßê\p‚ci¢-ѧ¨}œN/þƒÝbuS ±ve:‘*3éWˤ-Zg‰ë‹‡®†zõËe˜[÷ûIËk]X7RµpÜ ¯p¿‡X”,¬gÅYïßÀýø˜7³€kBr~Ì›QEEÈ·y3sw@¾Î›Ñ9Õ%ÔM÷ç!j©6 Í'h³$Ð@ïσQOmõ(j|j;¡émøŠn¡rqÁ˜šï"Ä.òfAÈ{„Ôl ’k$ÇÈNjΓÎÅÉfRâksqÔŠÙæât>&bÖ:Z'››‚ÎªÒØ0ôûM2‹øÏ÷gµtŠÆgz¸ù.jÉŽÏÎ@mm³j.—f:œ@ê=ÌÀ£í‡,[éP€€å4^Ž‚ê—,£Û·(¨÷gµäÜg-¥]}x´ÛÂfäã q¸Ï„ëo [#! ÞN¸æÃ3ÛBêÃë—=ÐÏ} þ3¸.jK u×ìRâc¦¯Ûž:äPcó­´_ž ZªpE—söIã²OælQëøõäpÌÆ“,)»Ò2’(¤üXhQUh‘Ph=ÒOÆ&j,íÿØèà´´ub\ûí“Øµéâ˜pÀn}ÂÁTµÐVzÜâ¡ÚÍLRVr/ŠˆÇ‰zìÈAfûª¬Àf!yÄÔc×±dmıˎã_O£m!hŒ«¢Pk?‡?ç $'ðRoH#fï<>˜…“ä貤Є›qAÈ$òs ÕRÌ‹(–qg™FwÉ5*Ôyjp¬a“ï}0 ëÜ*¬ÈܲfÜÇÄy޽võÆïõÞ¥FMÕìRէ׉3ö;k-Adê) ‘ƒtéñ@RÙÂ{ÏQ-eKÙãûéc»^(%Ã*èñü¬” JŸØ»á…RRŠÃ1a÷(WWd-É"ë:¯»04}H«Ìó)WS=F^Ξdý\–l_:oßDùðaŸÃd½ªy©Øð1ŸÂúþØ o^Ôz~ŸI†y}á^¦FP}q°ö~F m<Ø‘ÎòØá׿?Vdê¦ÂîîÉ‘ÁtðÍÀÄsjHÒyôfòÒ„g|iˆ&MPîzÜm§r^ê!ÇL {°öü[6—‚ª%Y¸ö° ²6©uá'êIDø—>vy°ç©»iãªó¤ 8%ÁåÁµ;åQ+32°®[€CôŒ’{u­Ö:=ܨ1žÌjÅF[„L_ÖËzM+»t}»úÕ<šhõ{HSGñb(w=yÞ?!£Üõ¹<sשÎ]gù&wêÜuüëorשÎ]ÇÈ7¹ëTç® „¼½E gp£8«<´n,h7"G«˜ó}è VŠ“'"¦qR÷_Ç}p)mæšõdP_Zc]²ðäœ5=CÈTzT¬-;½Õ[fÂë€Ò8©Ûh7ÜÞsKÉÛIÝ~‰– ¨ýÍè­ÏSʑ텄@Ü4JêVŸÑ¿ÌˆYM¹6puE9÷±Áis$¾¦ôŽKCOE;¢CÆ"¬Ê4±ˆn¶ 5}ÔùŒú¡Ä0;õH+é²ì# ¿¬ïک̤΋îòr؃´Ó¶Þƒ„µ—C&ÀŸ*+3¥^>U],9cF;µ/{m <£ä¨Ë¶®*z‚o;U ¸"\,Î œ§ÌsðùJ¿Ò~:Þh@@^yÇÒ_¯ß>—þ¤£ù¡ôŸB~(ý >fúöiáiÞ?ëª:"2ãr,Ú‰®äÓ:홼UK‘Ã1ÓW™óB«è¡3‘FŠx°W7³Ì\Ì‚/;ŒÞi¤õöçYùÄû޲‚kZïœ,"teÒïxy/<¨]x@tUúxþ˜¯Ã:é’ZªÞ^<Ü?†—T{çuD÷¢ò=œçÙ .æ[„€öô;}Ó=2NpTݧÂ##³øëL% Zš{Nk«˜ ’FWkÚa@[±cäç¢X=þ^ws•Á׫˜mžT­½ŸéÊVÎB¦!í¤vñ1ê­TödÀǼž•ûzÉ—qÚ ¸Ÿ‡åY¡e¼úëX󡡪 ©)BƼ¹ÆÍ›bêt2 ÃÇ„xŠ0γ­©UmÇCÈô0z«¨ÔâpÜÕ:ÿúõµóãÌ»ÍkLÒHmj¹ö•Ë™)E5©ÏX†7ä…[­–WmPCyôÎ?± zéw5T¥¸æÅÊ‘4Òf‚·CíY‹è˜±6Ó/Mm¹$ÉJd/ 8æwôuæñѾ:so†öÛü3j5ç:[ö ÞºH©r{‹Ì²g]7õ}ì+B^b?`;¿¯<£jðïüå¼C梵øœ©±ZwÏHQ º.¹¸¤©ª X™¦±¶Æ^{Mœë‹Ö}írÇÇLÏz]ÓeZÈûÁùѳNWÈÙÑ-<÷;r§qg³/›Mo ì= ắ;V(‡ \£¸4Kè¶[IWŒr+=òy˜¹| ‘ÞJÊH¾û݉4ytý‡V>ø€¥é×/BpEé÷/Bð§ß¿8ù]v‡LÞtÌ4'Žù! 6S¯‡„19MÞt$t,|ì;‘¦éÑñÓq´tPÕ¦æN¨P £u;õQfKÕ15ÜÀ¯ßHŸu@¶©SSœô ½4düßÇØ0a°"oÅ*7 ‘¦‡üsLÃN3ÇÜÔ`‡``WЭcZ×b ó{Èøçç­çm&ƒ(¹(GR`ä-ök\ÈÉÄ :÷¾öÈÓφºE¾t™ô!'iȹId/…XþuÓ»øû×ΰ®k´rUõOÕ²à;ÿ—Zà`-TÕ+º„‹?ïÌX2½3C륃B$2žwÏLîX8Ñ2R´™5öóØ–m:ìâü>»‡ãs+w©¾N½H-ô¬4Ò½v 9”Í á<¯_G:¼Ë£}[¨™³öâöôz4†_/ú¬)ræ›éiL±±™:eÓÌU›Q„L¢-f»*×ÈzÎêYr„L#2~kƒ™ÎƒÈÚÁ· òZùµ£ûM5YÕüºøÍh‡¼Eš£j«Ëu ËžëwÐBÿµæbö˜›,ç–1&1òÀÉm yVož©µþõ§§dfv˜×w¾Q%­Zl{¢·¿ó_¯UR«0àâ/¿¨0`T¾^~Qad‚FúSÎpŸÒ8ðEÎÂÆÈKˆ9,À7xi»EL!óÊÒl .æôzÔ³ÙÚJw”‡i`“ þzt)w cÝã!MYö#BFŠ\Û=h´N¬äÕ^%B¦8™®¶tô‘‹ö1òz¾ó66’Î0Ç^o¨ľÖe°Ÿ^ïzQªþ%T äå}Œ:̇ïY»L•þjÙ µjÄÚ=zXíÔMÂy>QôÀ‡³½Tô@µxû:̇zyè}˜¶~ŸùæØ)™<#Aál‘fÃÚs²!“WH}ÌŒÚr—/i:ʲ¦ãÈ1òŠ­sF‘cÍkŠ‘ogïœ:Lr&ŒÖ?v’³¼)¹ ¥^¯žÆL`›·^[µˆ”“Ìm©†I„„~!Ñ™cæØÛåÙQÛÎðf9ÑÜn„Œ­,ìn Ž-¬ú<f|E·wÏ}–ÐQ¾%Ÿû ùá¹Ï#B~xîä‹ç®Ÿ&ãçž¼yîú ¡<~î§.‹%ÇX'ÚIN“?cÆ2zîZiI3Jg‚±“œ£°näêί2GÈäü†2É&ßàí„ßMÒÈ›ø IѵkfuíÞq®Ñ¼^‡¿Â´1«ÿþØgT;Ö.aM5Ÿt3«_†ÆÃžÃíþ)4^­<`•p» —m4ÚÜ Ÿñ1ß…ÆË"ÌQÒØ‹¼'Wtôh(¬ñ‚ªÓµòé³Þ—€·çå 7ÌþêÒ¬+ì¢Üžx–©|2]e3懮À {ãƒ@”»úåvÈ*†oÒ6UÕµóœŠla#EH[þüçøºöëÈx–©BŸç-¶®±_œ¶®¡sÝîBF^Yeí=ª™XÖ6ÛüyFì÷ÜV9o°çpÿz»HЫØ%¬bïßW±<ÌÚ÷c¤(„rµ]–åAMÞ“³W±w–¢¤Wsü€—h¸5œv¢ê–î¹ØBÆ)NnïNMß[ÙåtDîÉ)ÅÉ&êÜŸ²ÏÔN#ž¼ó­tÄ9Uß–;BÂn¹‰Änlé¿êé¾÷ˆ'/þ¸]Së6RVóÔŒu‹ïÒãÍ]ÚæYÂ]JÑ,“•ÀŽ™¶I=O^Ã]º¾ÓïnB^Þ(hÔ,ßÑýzòµWD‚¦ÁÈô¼¬Îséš³2r[7ä³#Ç„Nó ïÒíì4táBàó¼ú]SËP·³aÆ(£Mø6£A×`ºR4o}¯Óò„ªn0ò±[­ ™í·±ç~¬{`^Rp0™êR»¢dR"dVⵟ¼ô†5ï2"ôF‘íC³÷UN2ÚFMÈaê{‡Šúñ…¾÷ “VH53ÒmÁçy Î5A÷ºVŒËÆÎ9ä=fÚ. ñÉÚ7ÖcäãètbìKx3.#|GÀK:š‡ eÇ*97øÎ½2Û‡¾04n¯YËPí¤Ɯ}ðÖxiLx‡Q„¸lVÆÙä“Ò(ÿÐIß½à– |)8k2rd±^7U\噆`{c¾¥YDÚAž‘¼­òv°\dƒk·]­¡½7zòÒzG*$ŸuyøÞk0SÇRŒÞbÅ!Ϭ¶®g-éUá …ÜlóÚ3;É*ICÕ;:â;ÿjL¿{rª¦= 0RÖŠŠ8[©o[½9äÍ=ôâÅÙz¨wZ—Uý©BðøèŸÙ—{Jq+ûrEĪpP«N7èëÞ´5Ÿú½àè  ªkýLíM­kU uyWÎõ† †[«¡kžïûzòx÷RµBìí¦ ×ñp_ û.ÍcÕ²o¡†ê­ôp_Ÿ^¯K<» deɲ¶©w|YÆK µ±›˜:Ô†BüM…e¾Ž¿É) Ë|ïé#*¿j´!R›à(æ£@à’p‹3lB;¥%4ï‡4øs¼¢Ÿ˜·ßâ;„ü¯HòS¼¢@È×ñŠK¯èŸâB~ˆW„…âãö&^‘âòÑœu)Úiª³h«Ó¶¬³\y›µ|ÝÈÒÙ¶-Õ›ç¼kÂuǺ>ژݤ!ESxn¾ûÚ•BNbYBwäq/¼Ï…–WyÝL@â{Daà¾{èõ·yU噜Z ÅVÑv$å}Ã:!ÂÛ|`·¥ä“;ºljÕA›ô f¹fF'Ù¨AG}øC_«>Ä-Eò©W7ØE~<Þöìݳ'ác~~êÙk EÈ˹sLsu5“,¡sü<ö3|ï–æùÜĹH™ƒ{·4ç¤Ï³išÒÌ¢ÿíFZº€uŸ¦y¢Àj Êᬠ2ã´âm;Àkòü:18]ꕺ¢E÷Dý«e¥âN'UŸ²étR„¼œ»’ 9/èÚ#á¿ÿýóW¤§:uEÃJFèt>¿ÏWÔ¸+êù>´3>Ïë»É†õáGl¡gzβÍ1›3· x’Þ¨ZQ›.EÈËÛL¸#ò¥7ælÔSÐ}Ƽ¢¯$ÑþB·f”(›>ýf1â)û¸Ë!VæüŸÕÒ¹Œ }O[ÙUp—gN»=¨Kœbéʪ ïçãƒcð̪ Ö ÏØó9mè4ò"8m¤qþêKŽ/ì÷>áøFoÈo_Ìë×/_8æõëcO”t …»͉÷˱¹­4PNäì‘§\/T]¶,¥ZzdrtOµ!5ƸÕÁò'"¸Mã Ù±¢CȃhIŒfœßÔ°f>&¬ÔsL¦“ÃÕ?>qÏ,wÈk¬¸÷+PíKÈç¬DÈÁj»Ÿ¶u§Š{üë÷¨çH¶*dæ•Nùx—p.¡3çO0‘7$ãu•­ª™DŽï’[ÙÑžÂÊu÷’g-†~ûl(ýŽØ]y5Ë©ÑôpÔÐ@Õ”Ó¾í×9›û-§ð’¤ÿ'ì:’‡‘à—Z†lé8÷íˆÙ'ЂIЀ1¯_ØB%õö¡O-P.3ߎõëx¤ÐkmÑãN1jÔŸ®Û’Êc`ËÎɳ™ýRo»ŽïäHwá¹Ñ‘-‡#£¿ž $«C,ÈvÖA,˜ Ì€lC,Èr ‚ Q)«òÁ“NAŒ¶§Ç| kæ“tÆ(dÞ/ù¤ñ¥ ‡Iúc=èÿÂPæCÑaªZL…^ÞÅ¢jǪ«2 ½"¨çícè:Ñ‹ºÜ"4©V©¿çz;Ú†Bï0åFl}0kÄQ³átYIüœƒÀrÅ«¡[ µÞ=ìÝaÎÔ0•™àûžu}I¡ß¸<êB§>ŸV™-u3Qè#Ô†‹fÓë·¾\ò†B6ke”‚‡†ñƒCÆv}"°¿Ö¡×µ·¸¾pž­å”dBUÌ1(uÌXƒ‡Erû¢N”%¸pvJý±…ÆAr»Ð©µf:¥Þ u|Û3‚¼R¤Ÿ2È!+)ò†¼¹K×/µ3ÕÑl#AÞ Ò)äv4+=OÐNq3ˆäŠ8A¦Ÿ®hÈúp?7ðý×W4é+ª òöùŠZNw¤Eƒ®Hè”m§È$0€èÓ´HIé+Ç@8Ž‚¹“½ãôü„tÂpOªö H¢ì2ú v'‹Ê¶`•šxÌû«u +†Ë™íÝXÄ7;¥ú™¤àg5±N°Ó1éÌ\|Ìf©Ÿ=&ø2;Æ´i ^2uH‚ô$ûŒ¼‡ÛTg«äúL诧»½Ñš¬Ú†úÈaçºA‘`ÿëdX+÷†4KÛ.ëRÂŽpƒ"Á6.‰ë0'Ժ玘yš•(ǺXØ;néK ¯òí¿ÍXo5E"7£¸mUVæ~¨äRœŽ‰t$\"ËÌdá¸ö=8³%Èo-ö\tѵªøB™Ä=Î%²™ÃÊ™$HäV¢µ©[²qJAù|„ý̱Π•  #á‘×ÝPl™Ú[³‰âÇ\-ÜóaùÖn[¬ÈÞ?îï)á, ùª,þ†üpÔàÄcLÔßzZa/¼v½†Mkµì;Ú¾?G &¾˜7N0—nŒà[§á1ÕBI S‰›Þþy®zaЛg.è14!ìË’f¬“Æ\“ ñ,qcEf4r‘í’ñ®$HðxÈêÒOñR.ËØ­¡«ä‘‘Næž»ñ.·‰ñb;‚|~œûVQr{œ\ÜN3ºÓ I´…\Æ©Ÿú<å¢k$AÞW¾ ™±8dUïU(ÞÞž¿Ï'ÃPFòâ6w>Ï0-é‘¿œ'Dô÷˜Oü³c…ãÜÙóÌ[TeЬåý篵’òþ½ Õz‡»YË6²«s3B©:¥È:‚ŒeÆÊÚ([ݯ¥ßgìÿ¹â~œwÓµÎpó¼wy%"œnU6¿Ýt³ ïüývÖ@ - #±²/:wì(d)”ÎD®íë-;Ø¢g$‰¾t'uf³Ê[uæð½ßOÓÑ>75U–JMc3s æL ÿÅM½Ó‰œ™Kï—9ûToíÔ ‚ÄŠA¾dfòsYNÁ«%Á¾téc¬†"å“/ëç9¯é<çY¹9A¢ê®W4W¿÷s±ëôŒ$xFnÛ¶oò´UBìÐ+¾t®Gè‘–7Á†j¡Wô »GQØTdûX홤H·Òÿ‹Ó8N¨*7­Çš^’Wg& mõž´Ó§t¹âÃÀ ú,cE7ÓË÷êÌÿ\j˯z´M/k¸Ã°*/g2ny˜ÝI/Ýñ³Ã¹š7JÌ:EÖ½«—ôD\1ÐV™y‡º÷ô%Mƒ 6!Fîgå_æ?ÑüXK5Ðc¾3·XUgäâB†WîçiBV>WŒ"1¡® Ac!Ç)(#Âþ[ÊŠËÓ÷ùÚ«an ¶úëUÊH°ÑÝ»âÀŸýãe¶-$³Lt[«Ú‚ oŸé!`¾?ÎaÜ%&D7¯ñ=_þµÏQåh¸™|$Èk«ýšRê ½’ÑcÆâjé¸qWìÐ['È;>f˜hÖ‹ørÌœ™Dfÿ«DøO’ËG „C9.¹Ò¤»2£×­µçZ–yЫxxšÉíL±vL³Þ›Íf¬&‚¼FÚv˜ÖS]“颇€“ÆM{¼ •M# ™Fl’„–âÈ»~73¾L=ôr1i< í"¾uíÆ›i%AB;Ïö3Ýy.U–çl ÄL0qÅ1Ṏ470óÈIÚú+Úºw‹”ÇAßéô¶Z‡‹Ñ¨#ÈGHýl7£vcôCÃŽ¬Û‚|Æñp;ÌìGÆbÔŠÞù/ÌŠpkø´dBîù±Ôz ZøY ¶²™NZ5U9…^A6?z¸-Ù&÷¡˜éõË=;7]Ç}KCŸ“[î]]*¸¬}Õóeé ›Opß5¨x»Ä¿éõ:!:(ÊaÉ€¿`£mWf©CQ5·y}•âN6*†×ˆ´ÿï?>Ä´5K¡ŸhVÄgš~âN6ê|Ì(…jJëNfSNË»ØÈ‹BaˆÃ ÛêßæµŽ¥*¸¢2oTãÄãÍ{²ÉežÄF.Àýq+Ic»ÓÆÐø0>ÖAºö‡mŽ[dmBá,ÓH !{BÇ‘^ŠUD"£¯w¥ Þp‚¼~,e€ B¾ôyþ êí6dß¶£bû0äIýÔš;ͳì2h+`Á‚ŸÿRc*Öl=!£ÉˆA ™1ãßç™~Ññ®2$6VÀœuâ„üD«w¼õÈ$„XÎÚÞÏÖ¬c;øù&Q.ጲ£È+Q=±PÛ¨¢Øì³Q.a?<ÅÝ­ÌMÖ4Ýr¶‚\‚ïÇa a3c2V3ŠL0²uÍú‚íýÊ0"º×Ã<—ãˆ&ù<}Z•³mRk!iß#éÄ ónk¶,ßeN@œÐŸ¦_Ã÷’õÙ4Öýu³2hãmRòaæubr§Ð‹…ê/¾r;ˆù? “>âô”.×7œÆ™*“'风ˆDÊäIzýE™¼®wàÜ&Ø7îE™¼ž£2y‚Ô"^•Éë9*“'éõerYõÀeMRZaŽd£WrŽŸçíE§Î/8:2z¹°4aµB0ùpÌ7êsFOO²‰wÍZ® Õèé e‡×ÃY‚ ^šüBZYøÒIš~ö" ÀIzN¼}»Ýhº¾œ@>^‘Þ¤D#‡mkw‚D}áhg²Œ¼ìcéã\3¯Ü²<½šX·Å…y]ÿ`}׵˪Ik|š‘õú×(†hÖÜéÕì˜bÏ16!AŒ*pnÕ0ôª„Ztú ÂQèc‹¬ÚùÂc¯9E6!?¸!:Õ¯e}Ìôy ZjðJì}ÇZVa¤K<¥>j_ VaxÀÉ$Ì'H…áøûãkÑî¹O|kTߺ“{Uá]¨ÜÂ`¤˜à}®üZ_uå±wzñé^ú„ª­Ž¶«ï;AÞð ¢{?{®²š×s“$|qÞÜ%ݬXë-_2!…6ýéy™‰f¬·Š Sèþ¸)AÓw˳iÉm( òû^>­…ÞækE‹¶«¢¾Ÿk›ûn‚ŒÞÌ…o˜_ïó¢í2úë~êödžÕ6^kLX1^ ½õ.[·ÖuºxtùØ„z {’íBØÚÌrˆ©ežŸ ·7—Agù<Ç»ùXpa¦àC‡ï IÑ3Uv’¹˜†# VKy#~*¾*iDEú¬È òŽtá«ðÕéw¹ë+NÏ3‰5¼Pt˜6UNòØ+zžé[/SSÜÏ ¾þ}‰‰b2l§ª_õ~›wyM‘<ïXGè'µ•ù zöuI…9æ±°‚žgÐýqÛ—‹œŠ¦Ùw±Ã‚åGþãèÎíˆû¨9ú<'H~äǵ|ƒÑ=Ìöã„|cà«7:kà c#D~ä_xœ^*Dò-–:Ob¶ԢãкŠï}‚ò$*n–5FÜ,.c ü±Ð¾)·rAc¡Ø|ñ4ÚÃ2–¶ ¹Œ·c¡ÀvM\ÆÛ±Ð3òóXè¡(2ùlõ a Áxoõ+ò£ÕoV¿ 2‰|[ “«$šD¾·úå‚3yµ i¬UH£ —ýþlZ=»‘XxFÏSk:´KÊchË.S4a!O/©¼ä9+öfhç £/ª2êW5g{yäX›F#P“oeJ°„ßfÝöe¼ÕòBÄzäãë…™Z;µàC1¡ïðx£{7¾ ØãÓøj³:¾úø?ã«` œ<./׆‘®“óòNÄ/5øÖ&t¼+¸cMñËqí×%¥æ¡ÙǾÄ/÷AS6õÝýP¼ãðß­ ö²×+c@žÆKV9½¶FêÃÉyÏèv0qƒ„6QP¢–3 !κm^…—•÷;Hö&„hÑæðdÑ qlù‘PO(rê“Ì YÍûB70X{kTE%I=ò—»Up̘w—ŠxíT,™Òód«"µ±Æ°qm2ƒœæj—y=«˜wÉhlœˆ5~Ö*àÙXg1¥8±Æ]È5 ¾JÁ(ßãÜQ ;€_TŒcÚðwÞ«±]ácßÏy“T]mëÐÓÄ÷ŽmyÇÔDw?5r›xÛô<Øã‚°aê4zãÈN¿žFdí­fU¡ô‹ÔL_‚\Ï:ói¶ßë"’k]w6PŠ|b¸'wJ/¶U¤S`×Å3c\™Vf¶ìŠÛ£¾Ý­¡b›Ú%ðÐôŠ¡NÓÚ@×µeGM¡®nù׎T^È}Éæ±âÆ<ô5µÍVÇtæ-pgÜêBÕV·Ölò:X«—¨t•2›ãÏ6ywLãa$¹òÍ”³póÐàÝ•`7GŠ4³xú‰6:3Ùdk(æÙ;eü¦‚¥ñy9{ŒùöƒR­âE ΋ b—¿©àè¥ X7Ø÷ñÏ>÷æ]§÷åž"1¯ß·©Dζ%W,$˜ î7½Î–Ð9ü,T stˆ -d?‘,rÉû9e¤9D"¼ù@ ^1:D|í¿%É»uoï‘¶{Øú^ÿOŠB³Zk‚L-éè…YjÞ8A~“¶sÍY³ê»¯èþÊ{q ·R™\¡…F;bÁ‡»ä's—ê)&Agõ7å`ÔrX¢?e¼K Ü¥Mߥ• Ý]úÁ: ú.Urh³ Sè‘è.í w—:5 |—îD—ß¶\C•Q±)áMN>XÛpõ‡Iäõ¤§Èl\gª[G'Éë³%M—_‚"‰°+¬ë_º£X=ÏÛöúªØØXÐÀóÈôDȵµÝlìE~#&¸î2LðZî,A"òlÅ ¾Ê¤N@ ¸{&oȳuëØú¬àÍ:Ñ;ÿ…gª)¬J#+=èå½,kЙ§ƒ5Œ.<ÑÌ£6~ì‘ó"“Ûéˆ[ã[£¹Êò|êáÒ7kæj]Æ9MÄu9=)ŽZšŒònzó'$0Er¨ÚVG«C!&Ó_§æ¥e䇊 ŒgJ*89ö¶&7RQd+mNÄÆ\ÑÖÂè+ä7hÖånór¾Á¢[+>ä#ÞúPjßwøž®èùÎÿP˜"…„ê2Ö³81ZŒ¶ÜZîÉóñ»¡yœÝÆ*ÄÍrÓg[Lý¢u³ì½›%t~¢u³Ô«M¹"7K|ãf)¶¬æÈÍÒ#ï´m×[‡6®™"•Š¿Ö1/ÜyµLUÇ:$»ÒÏ*K3ëÈâ†9£¾×a–ðë¨tfwš<“íZ“yvó–ŠíÄdÆÖ¾ zæé×ë$§÷ÚtÈ ¶V A‚JEQøZ‹YïJ–ïs¿äý-RuBd[OItê®|„av.Yæ¢&È«ÖÎsI6úÉyÍ ëº-Ñ(JÌÆû;$³iT©#+5Œ¬ì&™TA>cÌÜ{¥˜~›ýõ(p…e eY[µÁÏßO"‘f¸Ç\½ù€èÇ«2MغӯsÓŒ‘z›m£iŠÍsõ_Ž:«”ƒÞdúæ H"`Ãê `ÃÅ6)"³ÿc•^tÓ"—ªYòÆ"0 ¤h¥ïüúãe²Å]ÑV÷úŠq¦ÈSãÞVFLâ‡ÌÇÓ߉ç&¥Ǽ|}L)—RH‚"UV„QxÑ©©>‡û‰)êÜŠ[è·z+uòS†ši)êÈ6ΆlfôkYŽP3Mñü,B½8jøõÛ'j¹˜ˆP§ˆNNE¨7–é§îŽ… ߈P‹ B-òÝ϶‰P{äGêÌZ<2};^¯Œ0¼ó˜öîn× 1Ô0Õ-Ûšìé%9{CykW-–*óTã3T;›îÏfÚɤ‘öþVŠé)¦ô’~ËžW62E´w£äˆ7^š_è}ÝùïöÊæýÜU„H/T‚Ëé¼8I˜¡¯ömcðëÏÓ M¼Ñ4ñÖLJ‚DaP×eÕ1`$Þx䆿Nr`<ç\R$R Áb/t25BP$¥›… gÎy5äA¦Ø¿Ë…éæŠØ!ÙD¯ýS,™mJ—SŸmÿ#ìÚ¶$Eà/u—UÚý8ï3çì~^ÅûÙ¯_® iiOŸyŒ±2“Ȉum¾æW\³õ(ÁëJ2õø>¿1Òê»æL’…÷ žùðB.<Zp5¢¶/—ô3*ÈQ[DPO~Y‰ì=ÕC¾µÁ)fQCÊ-‡|=Ôg´ËÆëH¡×?S‘ä[ï\X½6+ÑÌ\Xï‚äÁö˘TÎV\ŸuÒüè}Ý4$L*mΈ«C5.ê[pÍODÉK+²j–š­Ê!´ŒLŽ/Fñ5“¸nê×µ#q2ÖøšÏ+»ÄÝÚ%ò‚Læ$1'yhILû½ ˆÔ½Dp¦‘"ÑGXq&²ÍÎêrƒ=)¶¶EËÒ§>´à¡ßBÛÿeê3Q6!äã* œ'Ó’¿ž!ea‡©ˆ­â!á|¬rô†Ž«°zâŒL™D®Œ Ë°‡X%¼ÊAJÀ†À•/b(›ÉìU‡Œò}jª-úÜ~fleí2(¬BIŠîë4ì;ùÏ3È8ˆy=5™¬,ûmcù¾!äã 9ö[®Âÿ!¬k¦~ï׉âÒ %°ýqBå–ƒr”Týú¶Ãûl†¯~]%^§;M>N2giؓτXåNçÒä>”¨×É ?¥qÛ¿³Þ´±ˆm–;HS,òéZ u„aZ 9aäÃKÆh1[hQQ‹ê}o9B&À(½³mîÙ¯is¿ PÃ"ÀØvÈ—ïÌœ]’-M¿/§9ÐôÓ¨¡ü“äp¢¾3™X±•'ä]IUÆ­ç—ÝSù¼éžR[+êžrȺ§N×L"#>tΫpÍêE$àFgLÞ¦¾b~UŒºÿ¸«v’ô#›Ž ‡—†îßí_ÈÔ>(¦œ/åÁ ÙÃ}¦ïÖïfe0ÖïbÞ þ|žW†Ú[ci߀A†¯#î¿5¥Æª²[°¹ •Fý·z'>TÕ¦djÛR»6¾æµà¶6›…#‚4ê¿}3†µÜIøõï Ù>ýŒJ®/P¤¯³1låîÓ!Ã;{[ÿûfÉä2gË«Í+ê³òÜI[zßµ!=ÿú󒓨éÒл•Æ~Ù¦E¡òVÌ3­Ô+7ÂwôºÍ$ÙTÜûŸµ²÷Ùɲbl*`jwÓ^º®9MUÑA<÷WôYs*W·ÒSõЄ¬'ꪽà¢J=¢¾Ê .êA(Ä´¯zëN\TRŒLîLó$™aDéO\T±–P9z¥7\T湨;B^pQ…ç¢2„¼à¢2ÏEÅ×|¡ ÚVkvThÇJCWç;R½q )ÒF¿^ÖÇ’5´‘é¡‚_øõ¯SÐè«è‚ˆ62Uâù¨ÿø˜µ=r+:o2|G_ÈÈ4 ŽÅ¾4¼äášwG‚®‡Ä7Ó×Ý‘`g¨¯½îŽ™=”#ŸïíCeÝ’«=οóQW§ t=¥tàM>„ ll.íÚÆ\$ §i‚À~™K;Sqs,¦÷#µ%Ô¬02–ºå$ê¬Gå2“Êk¼!pÛ;CÕ¨µÙY]zŽtxè¤ã‡¶)Ær˜2Aî8¶ZÊJÔÕ¾fœùît­eʆútÍW,›ïªs›7[SCÝ?jØsvlNßCˆèó!³È\Àe‘ýT’fR4FZy¬?¿á0Ö"ICzX?-òìÉ&šiÛÔÇAðÌ„æWð+T‹sÁëŠú Ž`¥ÏQTUÒ\ÅL'è#jÍáïA!{œ¼~À£>Çõ™\xÔçØ£Þ!Ÿï>Gšé§‚6ð9rÈ×…+`Ý\÷­Ä÷™¾;"1í$²CÈìÂ%>Ç.ñiԌ͒q3Q³´QÑq„¼r‰Ï±K|5cÝsìèž/è“w’ž¥¶W¯ó†³dÆŽf)¹™%3Ÿh–ôª%HÌÒYýÓºò– ›f:ài ‹øDk|Øp*ë£âù°AËÿj1j»sën¹Cª#“˜gèì<çQ4[±Ã&›¥ dã#£.ÈÕ¸â¶-'Qä\ kz0¦>AÈ[¶WÙ@h¹_±½¢Ð.ûú™íB»ØåøŠíB»ìMò©µ/½àŒÕõ$nÛúçÔ%Ê×q§px{ã´‹–¥Ø¦Â·¦Y‚¢´+·i—ÄÈçuÚÕ dø×_¡ ã÷̓Mã&†pÚËÞYiZÏxviÔŒõËómáȦ !PÿÂÌsË53÷©Ó„ƒC K§6ÜØ@H JY@£dЧâèB«¥­ˆûWòYAŠ©…ôðëyòXnKVÝÑë^BK÷ÅÌ@þ@Æœïœÿ£‚„÷+û ç?ÌRvŽN§pùõõ—ÆS(òÄ>o.Gäâ~}ÿàâ µ‹ƒ@ÈÈßÊèžÚùœÔp€›žüm nI2Õ“º$GÈ2gt׬1Õ3mG½o«¢ù)ç÷'nä-@z&óÞòJ7ßXæÌj…X¤úØF¶@bõPx·2O!ý®VùU d)ó‚¸áÝÑóÿº- l&™r’úšRóÒ„|yÆ(s/}ÍF]³Ã÷™^]2Þ2hK£^#ñ÷Ù q (‡ !qÚeuðä¼JÖ7tÁ×Lb·‰pŸí·#Ÿ×óÙLñ|&ÑØÏóÙ«k z=®zgêƒÂ¾ùýÄÅç·òލ‹á2“ +XÌd¿Ì¤`M~c²GyGgò{öCÞ±ê¼cBÈÇ}ùv™Àæ¾:\Þ£Ãåïï[å}*¹^#3ûøøAyŸ²…tBÞ(ïSÖ“#/•÷©ÝNWŒ¼TÞWÈU!9B^*ï»1„LïFÔ’®ùùƒò¾Q…‘›•ê>B&÷#ê7„¼TÞ§bW»×ÄòRyß!g„LoZi-8Ügä1z'KcOЛŒOÕ^\S@âoó­Iôƒ³˜$}Õ$zøw> $éí¿_V§Þ'‡TŠ•«ÿ€ÏÛÖdè!È>p<n¶f4Ì^ÞÚÇ·pÍìt4sj§a–°dÂÛ3Úüú>zSSi`–¾ßÜH+§|ÒÔÓ\‘mFÈǽîÊ>!dÜ äâÁ‹ˆ„nòy¯‘Òâk¾î5R†é$nÓ$®CÞª©ly‘_qM v¯uY¯Dv=B~G+ލ ¤,›™î4óïe#m.{ •Š+ôó´Ôj¤åÿÒa§%•G‰Û 6<¤Ï{]Xܺ’EÌëk³5z—}&7fk›­1„¼0[cÞlmGÈÄ‹«-ABi/‹¸Ïަɦår-Ÿ: þóyf²WµãI”û@h vȨÄcEÿcUDäxLpŸaiÀ qÓ?®¾zX”#1à}מ!>Ìüà'HŽ-ª>9•"ÉÊóý³ÏôöiJlQ‡|¼[D«àfŸöm‡Mî3ÃϽ²ýE¦­Œç”¾h•}ž-Ì=§Á&Hˆ–eŸ?õ%¨õóðܵìñc«Y˜€¼çØ© r8µÍwž„­E3«¼ö­¹YlÏõ €máfgÅ2ÂÌÇö\éì ò`=,"µ(:>µþŽdYvL€¹böxÞk6ëoŠAYd¥u­Õ=ï¿¥»‘í•Áö*‹l¯LáFë§R».©•fè ÷ oȾÿù'Ò‰³êFç)GÈXŠ«ò‹ò Ô.Û{>qÙ^áïÙïý0óQ«%ýr4t¢—*‘„³í,ðJÕ÷n”VÕ›°ß{sºfrgD3B+e–`þÁÙ^¦™|I" ¼Ò+3–RåûøšÉKÖ¥ä#âV¾y±´xòåw+ÌÙ8aNV›/•f±•–}—œ‰Ñdù²À»[iýçFD݈Fv,Å2#äý|NtGÈç»-:3¶èš‰Š¯Û™/i>´+rcÎõ«^®¢@ÈìÆj•À÷ùý|•·ñV¿N µ‚ |Ÿß·&<Óé>m(pùàÃò|†^‡Ë'íËjkÊv;nܧ¤·$õ9…W4Šéýã<²¬ÏˆX7Ò‚K–<~eÒrC!“‡®nåášop«-QMS¸Ï$¨vë‡bIT’ }"dÙ,I.h"v;VÑZ'åÈX?õ·% 7Ö Z%)źžKB iYY–”œ…çK'ø3ò©âBxB>#c„ʶ‡ª-~bë!¦=²~ÿã)ö4”ˆf—ª Q`½F¡­«63›UËò<é=°š{šÏ¢é02 ššägk7­Ô½ÓdFÈ'´±Z—›{Ìí8®^"‹(°ôÌ»3N½Ñ b+hÉÈ"¬í_Kò³}m¢ŸÕˆò™`dæÃRzÑwloGÒMùuWÖ<¾*+º >ÕøšßÂxŠªíf)ħÜ–Z"¨Sr„|øœ3ò«l»co×°%!ª® Vm­Å U‚*B[ÿœÎb«œçk3³¾\sÒœ«ç¡^“±ã>ŸAîK¿ Ò*@è3$y8KÈ‚ûRpȲgœ²™÷¾ÈK‚I¨šy5Ü…÷kÃsà4d1±Õ6«¹>$]§n6žÃ¹/ýB.QZ¨ZnBž®ɵ5Îq–“i‚Fç,"Ë:7+“š`u›ÔSàétÔ5kß”¬>u!Ôs‚7äù@TžàÄNþGYD–ÅþGìä”Å>M×þGB^ø±“ÿ‘C^ø‰“ÿ‘C^ø‰“ÿ‘Cþä„ý'ÿ#ŒüÉÿˆ!äOþGyå$NþGzá$NþGú“ÿÇÐ ÿ#qò?òÐ ÿ#qò?òÐ ÿ#vò?òÐô2§²®10YÏ»xÝð1' ÙóÜq\¹’˜ác΢„x=2ô²|·Â}$å>ËBe5 Æ”žÊÕ&pÑÝH{ÞŠE½R!!¾ÔKsë¤OòŠ€>f»/Yžxm| Œí™eÆ~¶ƒ¬œYº¦ÊåY^ÓôÔ¿b•ü kžÕwâÅݲÈ}Éjn–Ž/qìÓVîMÞ· •%k¨ c’êuxì_¡pè…TY¿XÊ!¿Ã'Zš©ÑÈ]:÷Ä3ÿñNF5Ÿ<èÅeÏŸËçø>ï’?á^¦ðŠ|ÿø2-û,2jº·Öû×ÇO…„ƒ‡—þõyf‘™V‚V§ò`ÓI u_+Ä€¿föJ.®iÔºµ¬›–Õ€k>qÍ6TwåÁŠfm¡8Œm±Ù%UÚ-f©Æ!ƒ‰‚\{‚fèаƒEl,Áxgd Â|=.×Äáܤ¶ž-бÀÈWÝ„3D­&y¨Õ îó,'jt+6#äãÖœS|͈¡DkOÿ.·Aå +CHSqêüF„âØ»qÉýùiðè4Qk2i\c ±”ì«´gû\¦ ·Îù¸—>¡ðëß‘> Ïèû/Ò'ðÜ# ôµôÉ yé/"¡= déw$"´gi¬‘øŠ‘Ô#Uö²YL¶J`Ô>M:õG]ç|ÅÈÇœù´Á†œÆê?gîÍ4T°Én­—ÀhÖ!Ÿ·» ðu³ôëç]¦‡/.ö, ÄûÖ¸\¬‹ ®Â,aIS,7û¶.–k?ò}FHLÑ7#Zë©W[·bd‚]Xì‰Ûƶƒv-Fž¬ô¸ DŽª)–±m îë Ûs‚‘iÌ kƒÎ¸†È= -fãÒoÈ>vL7ö „üž ìqå:Ê‚ \àk~G)'6¤¶°¶¯·–s<ó(å7Ñ éÈœï¢>Aqkkršv~Ô!fÉηáfâLS<1òqyHCÝ)T…2̃ÈA®Z­ôóκ޲²Ol´`óI˔閩ØZŒ| R,µ+ý:ïëЇ_ÿDò¹=¶ò8RnãrBuáªv÷)GÊ$'m{\´5#r­ÉZ¤¤$K %ãØ Ã*¸ö\Æëy^ºÃK6g‘†­”N§O;§ë ýŒ\ËÖøÊ}èŒýÛm$bÏÃM]¦Ùv<"§÷+>ÓЧsb[Ko²Ç©«ÑO¨úùªddáB>b-‚Ê9ï6ù¶¬+lIùÜÑ„Üæ¥‘ãÀ+ïv–etÈÌ ˜=°ƒ©Ö·¶(Õ-½Ü!¸Ê’ŸËB$<øä¦,$H3ó¸,»v„¢”9Ssµ ñYJLÀŽ~]“+t‘bCÈ„ EieWÔWßù¦æ~EÈäD Ô9’ …ú<(œœgXIFË·ZÊÄ8T¤ËÇ΄‘ȯá€ÊÜç²M}· d‚)¦f/8m6Ù7B>ñöa;û²“݈ï>¹¢ð„ÌV½q²–ð~F"·ÖºÜ`¶¬[HÝ.5Q†zÁìiR³0µs×yŽ_q/Xk†ÔónÚÔ˜×ù=MGA¡æ/~š‘È-0MY¨Ÿ^Eé1¹Ø1Lm±Å² <¦O×|ê… ¬ÍyÏwqzôIPŒ£V#²íê±kò6ïh0¦†W¯†WoßhÝ ¯˜¹àò V7uIàl6¦ôÿ²­1µ' iF?Ë3äÄâƒ1Û±¸Ž¤‰Š¬>›µj§F”Ž«dˆ g‘‹)ÃëRŸûu®ÿüëϸ_Ò"5·¥Vá-º²¯7–·öY³K02„CNòS¿&jD”(#'–‹Y _ÙIµí @„Î"¢¾}ï*ëî¨)Ótf]±”ùˆ$Tk[’ ™ØP bCH‘m㶉§ F&^À¡ÊWØæÿƒÂ­ó–5ßd¹"ä+¢?ÕN[ƒÈI,´óõ™Æ±˜•e-ÉZÎC“ûžV‡ÌÒ¬x éU¢n2>ÒqŒ¿’”K3l,ÇÈïhWª/ÄÑ4ùt Á3ÿš5Ýyk[ׄӰïxH®¯Ó¥5V¡GAu óÖhúðΞiü™ŽG?. >yMâãQwŽÌGÆhµ…÷éñFó¥V>÷Øé‘oExŸ’·Nr÷Õ*—f…€ÃÔPͦ8’d_ø€Ò•ô&Ò’ª]ª­†'š¾©8Ùg¿LÚc°¯þ'캖nU¹å+}ߌzyî÷ªZç0`F…ÚOÿ‡ gØ÷]D`„î†Ã`êÛòoÐ×ð¢ÿ‚TÝÐŽ¤FÈkD.ìæ“4¯W¡oöHlEÿøÃu@VRõ¤«J„¼§RaŽªI–m_WB>ŽƒðQ°¨Ìx6‚,ùDÙå£`Ñ´dÀÈ,9 Öupx¡riÖ¶™§ _ô´ :oÓ†Ÿ3ZýVïDÝ`͉Yó0ô¬}Ùº`mêÊŠ@ ©ø%z©Ø•zhœGjÑø­~:¹ëeôÜgʹYÍN*qªò*ËfdQ("ÆŽ`(Ä¡ZÆü` &hZO¯õL aÝ3WÝ*"Žôi€BÊò´³ÃIŠÚq=?+.Dù¦W[ˆ**=âÁºül‘ÊG¬ß›ÕDzÝ0ôAN“ƒ ÖzÁúænºÐ~S¢ØæC¯)Ô÷¨Nª#ŠŽDâ™u¹ÒÐã ÃHN?õýU#a›%—r?еÙó¬òJïÕ²µŸK6 $Ò[FÑr`|›7HOnLÑõ;”ìØÐ35ÎýB2M–ÔÑc‰ò†Ví±—f'z\tcbr&ºœõ³:?“G[OžËYÙb $ïSê•KO:zœOuk%æv`™´›Ôa×e²3›•ä[‹·-Amú\ÑÊ<-BÞßZ?ãòNjòóB¹[l¿ ‘6›‹ðü¦£çJÕ é´ÄçUa‘[…E¸æå‹Â"Óò(Ú$t®§ì8—òë×$.?’¸ ©è}q R‰ùýóŽ«Ù’ì¸ùãSRÜ©|'éóüùéÓç B¦s)œ7f1÷J”¼‚k¦tÿáüè›HOç앞©ñ˜ûsɾ۴_”à&¤¢¨Ï“iš°zZçL:5]Ví7®9CÓé£ u?Ä“& -ùÖžŽmìÍyB±ÅtOogÅ™f5¾æ=ÝŃàÄÆH'xþe?gÙƒ¨¨jÎãd”»ŠYB~úëéGÁ‹Ôœñk"·:öÄg ù)Ò"í)ÓÎÏUˆ‘ÃA3KÈOQ#Ög­Š[õ,ñs"~2+•;µìÿ›eì@´H"ÊVTB^NÈÖ·Á)ºU|CÈkB" žjæVN÷~Ã×¼. °&ˉ¨e%e‹÷$äÜ—ãJ"2K(M Ñ•¹¤(šøÇäóˆ™\Àd?¨4 þ²C9" ³“È‹Í{õ]/¾ì#BB„Q40žS=-f‘ˆ½Ñqä½rŒeø:An'øVU•Þ—®c Ê1t¦ðEU—¼Áïä# –”„ÏsžzEPwU-·¥Ø›Ó³Þ Ä©cˆ3˜Ïù% ½GhT¹[fî]w‹mÿ}'©½ $‡©æ¡#?½@¶?KØgo$°,…>êí¤PùB‡»ÞÄ\Õ B^>ŠeécH:@½K7õ=˜«Ü6Z˜s¾ûí½¬–¶²Zyÿ(pŠ YÊSs÷4ZtØ ¾$ä¸ûロ‚•°Nm²Ä$ã¯o$o¼DðVnu9Šaò³YQøî·7TkÀKˆ Èû{±A»…rx÷çw¡o8d?_=ެN‚—·×4Á]zÍüË5ÎÊ~ò^6;w/‡qŒ5»ì÷ç¬*º5ÍX¶b cL8g_H]³}£c.ýb!P;C"ã²¯èØŒ0“¯çãÝÉô;Ú²Ô|âMÇw·h@Þ?t|sßñ-`Ö¥æ±ãÛW˜J×ñ BÊÙo* x¦©IiŽ‚€|¼hUÑÐÏkÉgs¼ÑŰ‘‰žy¥ð5¯ø0ÔxvdÁç"yw'†G;©í™øôX“/÷ÉÐP†3ñj« !/‘»ù%.19L£’#d0¾Nû¦ìë(J!¤ È[Â4J+u²*¾ÈÇç‘wßh‚‘þÇ7ª'„üò¢:\vy~ÿFàÈ·óÈ3yØa/ÙÛ‘g0òðo^²·#Ï`äál“XT`Ûmð“Ñœ^N×¼EÏ=§çà…sÌsm^½ŠÈ¹óYdp4ÈŠ˜2áÖøÇ´Éãz¥Ã,"³>KÍ,ú+L a !o)2öõiÖ- 9fHŽ<÷lǃ¯•UÊÒÌ«IŽù8~±±Ï©+VòZ®ùŒ)F§^ìÜÈÐV&ª)2CÈ6~£µ­ …Ÿ3KC7'}}YJ¸ôZÔÉoYÑã¹ö%Z¸gפ«ðl—eÁÏR+?^œ9Œ¼œ6Í“ózýz² ¨›]o¸[¯ôêpÈXl¬6×ûg,KJÝ ê¹&«MÐŒz8ón«ßBÈëdz>Þ(1_c-·;c-]rüœi'XÝD ¨Z[-ãjs}|¥yFWv}¢5ùÌÏ;èòÙ5ûÊÏë·¨a’]³ïü¼b„D®ÿ-?o>f]²2¼3[Iîž7[!#ßhu^ ˆs ÷õ¹b‰Oìvl¥å>FÚ@@ÞŽ"~Ôc4HÖÑ’Aášöõô…†-iÈÇG«Å0òùÑêtäò ÏÚ#¯¥aÎKÓ&¤Œ+mÊ<û×÷øž­ÍЪE¨!jÇ!ðNG12]Æ‘¿<ÙKo”ëââfå±sÝ~ñ7rþéÞ÷™•¢JˆøR>™_çÃY±R›.I)„„ä{ôÑöQ¹*T½à»''êUnW¡;º—ŒT™®ÞÌÏùJµÌl…ÄÏùüð5ûT2ûô55×ø9óD*˜/¸lŒ¤Ó¼¼˜\ú•vjÈ*9g‰ˆ&ÖdRo}£èñœ—S! $¼m]+9#äí½¡˜]½!.NXw>iXƒ,voÍD´~Èn·Sž!2b±,ƒXuï~]¼êÚd¦s¹ ›DÈt&ƒv ,oøxÎû9Žó¥Qf`3ÛK`lä-ùßö¿…K±öíXç•»¦µræ|ÛÔ®z^ÒÍ:õ×dÄÔÿƵÖÄw¾Ï×1½´|MÌZ.ŽTõ²™“Ú¬ÚxRMl/þ ÅŒ x,«zXH¹yAÿ»»¤ýßm·œo8Ö6wg±) WT©FR„<®Y…”€m  t,KÑ ä5±oli°!…XÄ›ú²Ä 㟠îÞL-V²oy‡NÖ2ðV9ÏÒÌQ=!äYι’xµ$Œbf™è 5¡¹hZÉF©hüFY¢˜äëú\™1*Ç!óØ_£óF]W³ríT…GþC›˜S®zÒ®»^æC¡ÁÇÄú>{1ÕiÞ,øIS•ƇÆßf®Ç6ÊEè5Iêû(¡íW2ïJ ˆö9Vù_¤ë¶yÇFœ .cùÏß`“ì_k2ŸW•´Ä_ߦ¿¡o¨ñUªÈ´ÍRA˜ Ï#ÿ^µþ²ãb©‘sŽ¿€mIØmÃ÷ÿW@"5qB×óïK Í¡).í@ÈÀØ0œžõò“†‰¶R²Ù,(sËI~6 )1G `<=²[þU UN±W3K\_^ÄPM”º€lvQ ^ɶÃ)õJÎR2ßyW6A ç™Ïn#Çyí¯WLäu™ÝoŸ¥Ú¸“j‹KTJæ; ° /À6 ä‘·C VrµlYBæ{‘UNV _óö*«Æ­¬?dÕ²„ÌdÑ!X)Õ¸Q-ñÝo)¤¨ÒÝœOœrRéÎR/——T=Jÿߟ_ÓÿâHNn*Ÿœyàšê–;Ëó’Ð÷ü‹f–u€ üñó_%¯øœ‰÷H¨n< É*L ÃòÃÙA’{q`3âPhÐ’œ#˜xÚõ2ÌÖ^â=®ßz!ÈA´ ÈKtŠ³Â >Z1C´ìËH7Œ¼¾'\®Ó:ÀœÜN’ ƒÕöª@B2{ÜO¬`kl6F[tc]Ë2•X1+˜•k«ç!  \)§,ÖÑ¡^W„L_ªèK¹õŒñÝkÕ´ÑÓYl­nK„|­WNjÝ^¼Ôº„•ö‘Ç^zuÛ«w|ïÕéÙ€—wkŸ‰]ëàšçn.œKÏ*a-©òòA§å=¤ø³D[æ;Ø Í8RSâõI®c¸`¾‘9²v`yˆ×NmÜÎO6ëY.rÆ×¼ÆQ¬?дëfÏSÏfá|W¸ *¨âCtXÍR£ Ç/qóÓ† KMVwÔÚ_8Ò!uÿ» (+kX…?²çïI¶¿e´©a¤çÓ #)ù+2<Ü9·Ÿq7ûB¦í™î|IíÝ®†1 “g)ùË#[ÖxÑ랊‘–ˈDÓ ´BLæ¼<î”l5B"õ-d³ë}%øšY‚ Çpƒì ZT#CHT -eG‹aNoúhÿx>›o ­›ŠBiVah"[…VoûN¢X&½bhê·8#fÚ¯R®sÝ`(ôÖX!\—ò¾±å47=†&¾/u ª™o¾”äóiBݺm½§Mö]5í ™‡ú-WNº¢o)0ôCúCðgæÓ¼‰qe§qÍÞ³)ÕÈ@Ë<{^¾H^’Y€a]†Hu¸…Z[Ô£k#¥µùí»»ˆ4 ©4X‚—7[- [-¾æõãV{,¹‰ÿÉ ÒvÁèe@Èû'焜²çí?˜ëÇ»¿ñC›­B¶“Ù‰„2vÚìÃ.’À=ÏGVæùwf:iÒЭyA½Þ¯Àô”&¶“™DÕæ›»ttWXZ§p´NHHî ’ÌZ­škVÅŽ‘÷$T ½-ÎçÊ<¨Äo”ÌúØÐ[7 ®!Ÿñ|ž¢ê@·m×i¨¨”äðž‡u­ÓªªÐÎÇÛŽ·¥5+DÈ„¶Ùð\ï{3 »>üÏQ¤sÜ"[¨Z¶ŽsËñˆÐì“›$«ê%q“Ì^Õ{7IØ^Õ{7IðÍ^ÕuáÑœJâs¦l)$ÃÆ£  ?ɰñ ö ä¶!ʰ)„L\Â+onÌ,!œ7Óo”ÅëÐÐÅJkò¥’²JùÄí¾hÅu£9D³©UŠ_ÂÂþmÛK†¢Ö}¥V)¾XC]IÜG ÖÌÞý†ã*&×e5s™kX•³—È“Åb7Õ´˜t/òò)&]cäïô­ß•… )W„¼½E*‹1ò~,ßuèH6ñ‡æM ,œ€|$©Î&’Ì íÌS–%B>? ø0ÈMdX7÷hÏã®=ï°¢ÈRVûŠ.à9³ÿÈ¡À˜¿Ë7 ±Ò<‹áX¾³üì­ƒLå¾Ér›ò‚Ýx]^fh+½™ãp|÷”à‘¾¶á’·“š·èùžæ/ÿQötùtz¬À/‹ýåÙaþb^è¯çè¹À2Ç÷Yßýö¹ù þâü÷? !öKlbÞ+@Ù5¿ü‡44tåg'M{¶°óΜì9߇óe~=E Mèr®h%©*ŠF $NG»cX-[!dÒÔ”µ¸H© *GíÊÍÇ0Ì£_¨ ú¡Öñ“ llàž_QiØ ÎØÛ×Òì于øšOçÕ­n4B>¡DXÖ^•ßüïÛÆû]ÌBfI“míã93ž&P’}3"¤ß8ÿø¼­Óåo×NwÃ>RÈËäפÛA˜ƒÖ5ŠYðÐût´úãížÂŸd=E1Žøþß3/¨šf6õíÀOັm⸂Bˆ™„q^,CooTD{¬"š}t¿‚aõñ‹Üß3]d³±Ü¤YÆ#ò“-D¨­ë¢L–¸ßüŸ Úµ>Z³½ØdTп?Ð6ëº#Õ¸ë7²´PoÏHÁ#[¯Í³š]¾ê„<„êxÍm®u]H †üq?B¥ëï.ÔÞŠ­BÈDÉÆ‹ïÙmVÑvéË_3ƒÞ* p'ÿ]*¨.äÓÖ‹ªñÅ ¦yÛÐq(%ºóP(÷—Œª½¤éËg "Økº¥lí*ÁGNñWú½%wë@ãMK8Ó’Ó¶‹ÐçwV0ƒ sž¡óˆCº†©ÁrZÌÎyŽU= _)1™M±ƒœOž£2iYÖKÕ }[qRÑðöùnÏ,Üh™-t‹ŠyÂÓ‰}äúêIf½¯ò™†6'éœlNRtrûy©9vðH«€—×VµYrÛª:þyÊ©yçµ01x÷Ë©©jâ¦{b<¡J¼œXm ,§òÉ•N—yýذ õùÏí›'D£¡¦“ÿÜÏ6•цçM¿õ!/I£1…,«0/Ô¶!¯¯3™G~;ŒüãÔ–kÓr®‚Ís¹K¾Ã5Ÿ'…¶Ö´yH|ÍSÛc囦yé'>Q#ÿÉN )5 )›‰&‡ñ˜KÞç«X©1§¶Ií ­ñ5ûÇJƒ…¬ñ5ïñß$Ž.àsÑà ¸¥Ü!äã¥äb­H˜šákæç3c HÕæÀ:UÜò¬Ò–¬Ì³©f…×#¿ ®]ÈÂx+8BbT !úhËë!7ç}þ]—,I…íL ‰·íodÖ ´ùóÔÑçÝ(Iø‹¿ùy”¤ùi”fÞÂ÷ûû}”€vG)ù‹?Œ’‹¨L€ ßý÷r¦J„#«cU‹©…Y÷{}¡Jx[EK€X»NÔB¦µQæ—3“k),9!“ÕZÈúæú^ìRB£q@ÞÒÕÆ'£+7Ïd*2©é$”³Ë™  #Ã(ýõ£ä[ÿB澇º[@úÕ­ î°n×¥ˆÒ„QI% ³w‰Ðet‰Px£Û‡ú 7_Ý¥"„¼¼AÎ>½9àk^8©¦^ÀǾ»Ù{ Ïy?‘*êÀØerÝl«˜R™$ÌkלÍ5k&òš´ª…ê¤™SGJòv²F©:Öž‹}Þ„¼ã&VŸ¬v¡¬>æçãÃ^lùì4Ý‹/ÑdÔu[T§D; „ôç{¨."ífµþ7“Òt@ÈÛ›ý}qû;ƒUñ÷þâtׄ5æwÇ×||fè+¸æ—:»cèsŒD§ PÔ‘K¥Ön[÷ˆÄªQýÂJxšŸƒ-0òùëâZÌËÌaI7!/iö(2µ+óŒ¥Ø0òš6±96nöÂMæ—ŸÏ-ÞóJõ»vâbu´c3¯H4P¾ƒÍo@^p†/¶ÐJ=ŒpK‰D8èóÝPøÈS¿+GlBÛø*Ûv´UT@Þ¾çµ9Ïǯy¹=Ï› ]"äåK“ Üýdinís]Nh5qi1бäW{ÍÊЋÎiv3pCÈ$걦÷>'4M…°6à j(ØÏƒ¨h7·Cd_ç ñåüw,Ê,µú¸fv¦«b¡QÈçñåÍD¬ïè‚I®:¶»†èÒŠíGd~Z—âÎåý<·‰öÍ&´‘rb€Ž8ËEc)g,Fþ?®,IR\ ^©2!>ûm6s± Ä&{§ZC 2©±¶þó’EŠÅý™FºôÔvQUüY°q>û#Ò[pãÔ“X§æ ÇÈ`dZ•àÏ$Ö¢ë ‚¯ó!wö^Lâ8–2ª3ù¼Cý¢µË í„Ì|ç@¼Ä:Rìê3¬çž<Ÿ"#'>”RF>£ý{"d(H™{跆Ʃ"”%?§ ‘ÄT¶ÉTrÃåêÜKXl|ê™Ø/v‘%·‹R(ëõ2‡Rh–ÜN®6ú>9ä¸ fijä$ a:­Î6°ü(`aŒŒÁŽ,Y¨v›lß1¹¨ÇÆ`§Ô˜(5Nî¿§Æ`C˜%¿5sÌÖ)2¹t³¯ EJ’Ëž¬JDèÉfIzÔ–¼gä=Gt*òL…ÊE³‡ 0r±²’‡5˜t²‚5óN9B¦1 ÇÒ`tï¸ÉU®gœ·Gì1 – .&SGØH_ÒHɽŒÀs/Þ«ÜÔJ"s !ä=f:·Î:ŽlÝÒˆŒ?s7Xkæü–E-ážå¿+¨[Žyß²è©bŽ ˆQ•zˆi¥­Zó„|FÕb]ƒV×y”•ú¤{±ãë|}oŸÖã ýè,ya²PU5ŽG%ÝÚyáο‘&„™Ñ¡>À£ 00Ü­ÝD 3k”œòî|Ôtr:îG.tÛ:’ìRúé13K¯-B‰J$8³ôL©ªl?E­úÜ(„ôé)ÝÖ_‡C®í¤~P‘w¤n“SÝÄSoè ×y?é‹è0Ýé£ÏLÝÔ’#äÝ+ÓzO²ÍÎCŠ¢8BÀ–^­ ÖÑ=úÞ£9ìסUCb¿Ž,šSùT;hgVB`™âo³°er#GJuŸµ€7$}~iG[¥¬Î”·³È Ç˦Ö^ãà] ²©Yúºt³gD+Ûxa™ ùÉÄBs*G^ËðŒ2äf7„SŠ˜É±ìtÇÈG$©¢­Õ¶ŒbðÙZ8*3Å5uGßæø·¿@ó¼p «¦Lͧn?]çûóÛ4û¦kýÙñÒQ±ê|P8f ê;ò¿—C¤´ìÔ¡ù¸]“ê ; DýoJ9ó Mæ,rÝù´C.øÞõpÌ)í;N‘šiSÛQ(ÙÅDý?&™rSq«ö‚Èë¾â˜¨ÿ¯y—üüܾ‘ylJˆÖQÿ£¿£ºð¢[=«NÊš d+=8pAóE4‹9eQÿ{z_Gìºc±µ›yÚ誢 •{Ê@ùÞøÆ”ë‹©¿ØÇ£+j„¼‡ÄÜ1Zty­ªæjh}²ÿxŸe’]ÉŽ.½P7¾.BÞO“ÊÔ: ÅÆÛ!£>£çª³åB $h ­!a]²Î3:§YDÔ? ?«=sá`Už=NtÜÆ•Õ÷.eNÓ1ß=Ì ?©¬ö÷¡fgOLz:§$”Ó#//™Ç,ÏÈä*ñPW‹‘Ö%ƈê:M:µÖíX6`˜í/ÃTد~;¶ë. ÿ~ö¼j«f‚hØn&o˜ÛQVð.=SL™.½|›n±yžùˆç[ç¶DŽ|9?ùíÏÐâô"{벑nìä±s…%W˜^§&‚Oø˜iÜŸ²õ–²kÛa›š3bUÎrJ#m@ ä3¤*eí<›…¬Å4C2M¾Q:Ýë4{£„í[Kf|oàÇå•£V¬l8L>‡ÏžAð`Æ~ÌFφ~ìÆbøÎÿ|•îꦔ5\èó=46 7Íã-Ÿy¸Ð×/ i­‹ÀZöF6™FÝE¢ÇÌx?@IBƹQ{›©d•ÀÈû·QL©2ÛY<úbF‰|3ÞèÑM@”´üÃ:në[=z€Yd©óÇŒ‚bO8ýßveÝ"âù¸ªΠ_çÏ‹]Y½ò#­æƒñ|2»²YÇõ®Ì›Óu¾/¼/©æ«xdúIY°¤UÈi[ÀÌ({=ÎÅz§·Ö_ô¿!Që…"a/6Ù,ŒK|ÌäJÉA„Æd4¥à'\4ÆÄÔ|‚èáuÝ ²ª5°Ö¾.ýIsÝð ŒYD•÷bӮܲèÍÆz³È‚ÄåçŽdË:õ”ȪUÞõ›Ê¬vë\Μ µÈˆ*ÿm º†ê,69TÓx :{ßC ªè)q:ö „“Ex<ÓÏeÉ¢1Ôì}¿˜¢ég »qg×{ÇÜä#lÛŸ£Z–ÙàÕa+±aäý—L îÒó?2¥ò—L©ÃÈëL©›1ò—L)|GØ4Z…¶F{¦"ˆçK£'a`½ý!UD4àý:Ñ’43Ô‹ßÑœ•n]Wžò¥Õ\¥úÔŸØ&Áº::w½þ˜ˆ6u„JÓûu©âKâ.ô¼ÂàC¨ñ¸¤ÚCV%‰pÙi?ªk«}ÚkÛÜqódT@\îçz Ýà{Ï~}P{ÈÚ@YEÖssL¬2ñj„¶: )åÈ÷"h fÑ‚K)¼›KW©!ƒ Ÿ)x#n–” ²ùä#»aûsÝ.w 3²“ÛA=¹6‹ þüµT?Yª^cíË„‘I\צŽ01Ócç[I2ˆ\õÊÔPö,±²x˜: ž0!G¨ú7$|øî ßQvrÁ¶MYêtöªv–BÞ¿{FÏ,xF;drí-ñÙS4Hb |*¦ÑÁú™=°n¡ý:ì]*Ų‡,‹V0çÐiÏ^.D°b/OÈä;½ î¶9ÜÏçïuØ3òþI4ÔIפ%ãáì¦,žh¨‘ó²„gôÂêͰÒRC¤3ÃÈ’ØÂûk=@º/;TIJ÷‡o2=À¹PÉ1FÞ¿I´ãÝ»Lö>"AãZ`k‡Lã„Ójå@õ2Œ||jk‚”ÖÙƒ¨2¶Ç8õ]zÓw w)Ž­=†÷^7½0Oʲ³#°§k¨<ŽˆŽyÊÇϧ•…£Vl‚nì ‡{îy¿¨ª«ÿ„L.{9Ä­ ùÑos!˺´¤]ÖÙñòþIªvÈa–rBƳÄÎìD!s¾ä‹# yd ÔnêØ8yªŠG¦Q=Î¥ú='ZK(?3®ÜÙI#Úójáùî¥j<ò²´Ž®»ÎVÒ¿ud;¬›€­\UͲV EÈwð²÷‚‘kÉV ½!5nëU^ÉŽ«ÛåúS½• Y·êk’}òÉRª[O+á¥ä BÞ²µ›‚B¶Ã 1ò–Ò‚ÏžÆú Ö“F³”–î=F>®¹G´CÈghã NÏ|⣠ø˜¯H¼Á±è6±m¼!ÞœÔ#¯XJ ¡=GÈk–’•áÎ_³”¼ä@a)É4ÖšŽUÓ9›ÃÍO/„Ÿ¤Ô½^°¡RÈÇ5R\!9BÂ>KÀÙŽw›P;½·FUÈg´2ÿEôMµ+éÑ–ýóï?ÿö!h:Q?¨ë‘ÉÕ{ÛHxI^Qž¢n¨c7²fŒÝûÔ{䥵Uå­­<ò¢~Beçɸ ùþpˆ°Ãë2 yÞ±°:ŵ»+ÕnWj›q-ExðYtÿz1Í-²QI·ðȺ×Öm„Z·­…9/™~¿ór¢]¸Kg{§ÚwÄu¦Ð,bðg¿ýœ;Áª§zÁÍWñ‚SÚ©k­¦kd8B&±f «X½¢B¦'s)óuÈYe*áë¸ýDŽ0^ãÑô4²Š²ÞØ€Ï Q¦ÍIòõYÔî¹-joø:m¡ÜF¶.—TÛ—ã(ñ1³ÈãÆ) ªû>Ë¢Ég|?½ä‡&‚Võ?Ao‘Ý«|PG•cw°Óoº)ýª’Éš¤ì M<Ÿ‹ø‰u“òœ­]O Õêøëæû\i™Ïl›æ½9AßV'>Rw z»\ÇòPÈ!à2‹–°zof|L©2y!mÛ¬j)GÈôÉ7¢õÁ1Ò™£¿ÇÒž½ÉȪ~–ø:Ÿßדá‘ÞÏæˆžŠ½PÎU>½ÀcJÐì±ýíf³ÓlŒE¶\gúQAªi»ab«ÚðÕ§']îÊ–h¿µ•®t™|5G$„ÇOóqeѧm&DƒÑ(‹½óUéî|Û÷£Ö!ÅÇL.jõzŸ…;í_&óõ´;µÉÎãH%ƒûùú"4a³dæ§ïÿ2óãù›™>æ3?†Íü<ò‹™Ãf~ù@6u¶‘§ÛÍË1®pÌìÃÌ6ÞÌûrB»údæÇåT™ »ÔÚº¥$ƒÚÆ [¹eçªiä_SOd›ð1~Ћ€¥œBŸú#Ÿ²±nõÎu夎Z#ä+È;úz W+ƒÚnjøŠ£Q¿28¡R…”D³bò~5 ½>æÇ(uKý(uÁ2½&²ÃÈÇ… Ëít‘#®ÄÆÚĶ*fhª‰@Ü ÒèqMÝFS=ÛÁæS!“K9BSs8ˆ@ÈûUÍAì°zOœïµÐrù{zŠ1Ýç¦SÙgîŸûýqÜ»}<#OÖ¡ÎÚV6;iÖ !“K$_%B¦ÞñPõ­× ©œØB F>"Áeo÷8 ´aÍ踞 ùDì«ÈSÌôæ„ ÷óõ›OÙÐó2òÿrÚØú­+;Ò#ãñÂÊÎSLE/§¦+!¡‹~Ôeº5Ädý©&^L#]Ðb¤WlžJúw&Ø yJ<ðcÆ u®^GGçz†UñKxýÏ ;ÙíÐh¹ê‘MŒ¼uf™<®?{rÿ©¼¸‰îæHÜA œÜ.$Œõ^\ËJÀ›ü9IâØÕ ¹³ºš!“+ªŠ¤ðŒ’_½#ç®…½8INCY'ž«ãQÈô·úª<(Ä6aîâ[ïcÑ1ÏߦS k!¶Çáwíäù!d÷ÙUÝÞ¡*M>™ S5]†f)v¶ïÆt+ÿk¥˜b­·3ý”ôYs'é3 äÌÉý´»©]Žn®$B>A7ÞÛ@µe)+R¬Ì1Ï<òõ©Ó£ç."|#ÒÚ±î8ëK²5ÇR#d†&4LùèÕJV–× ßù hUÖ'¹mk1÷Cß4áq>ƒik€êj -kºÓQïŸÅz®uÛ(…jOl K–”ª^»]0Îò»-mÅ0™aÇÚéAh%À2çyß!dú-’kuTSƒ‘ÑP–WoS×ɦIîaqx}h¿:’qÁš}©ö ^’!¸2.‚Z…¢ý’çE—#ä=.±Z¶i?ns3vtª2 %©Ú+Ï=iŠn¨6„ ê•'†Ns¯^}²-ø˜@o¨*›ÎhãZÔ9¯2èÑXs—TÚ¥9¹ùŠ’Þ¦5ŸrUV³Öb‡@= ƈg¤Šª—dæÉå–FæFÕDîøÎÿ¯K÷Tß<ú¼.Fç+Ð[¤¹å‚е×eCÆ8>¿MÏÕ»ì5Šô:FæI-d¤çÉ;RÇr“áêøÖW²V†¦ß¸-T›„½.É®}«ô*>C):ÅÝ}Þ±Ž yŸò†˜ðvßîuœµ!“N¯§&õp7ŒpÌI"˜šãZtä8*mºvè¦ø0GÇ(F&ßg õ{5Îô·iÄ™g$Ž›Üò Ên§ìÉiŠºyN@[ßù#W;Hu*äiª¢¬Aɶšå.*è)¥gQˆ Ž+FYЊÀo^¨/Bªt²Ïè‰û\t(í§¿²É´I ƒÿ°µý(¼=ºàz€LeÈyöÎ]/ä$ Røßþ8™TÖõÚ"åB$¼ŸÑÜÅ,Cç*®nÔïyƺ%\#9 !SÄÖ©Þ/SÁò9âãç$ n,O4k#Ôº,DùŒ…¨•-Ì·&¹àø½|·¥"“ú:»±Àg#6;0ɾLˆ!³höÙ‰B¬|"MÇëŸýœQòº²é•SÚuœì'è &kK/òÁ[ÍDi‰ýíþ…cÌ• wùv:j-øÆó±¡åTN\¨#ã'j}l|éÔ–°ÆŸ ïÍ1GíJ£îF†vž3‹£l ^ìå‚ÉÅ¢’ pv¬ðrÒ…6n*™EvÞÿ€À"µ¤ApˆÄYDü4Ç$»ÙÙΛúÞtÓŽ*Sd4ô…·ºyáx«‹´¾›Â›>ýu¢Žšç*š'8fr1Z¬ xßQ(]Fž+¸éÉlÓ³gñ¦'5æÊB¦WMÏù˜ñu>> ÑԢᘟåúÖ„×*ÀRaÓ\ þ]z>¾”¬&]Ƕ©‚òòóñ¿}æyùÛe(3†i–‹ßKx<ÍbˆUf Ã ô}Å ÁóùñÛý¨ÂδÀÌP düÅUžø7¬ü(BÀú|þ‡#|qÏ×…¡!s†† ß'MºÆ‘vÊcËš"Ðó}ahÈœ¡!ä³Ï÷…¡!ëøL´¡á‚ñá­4šœ¹Ë’Cƒìy¦`EÖ‡j›ÕFpùÅÐ9CÃ#_hç4y¿Ù9‹]ð!mþeJÁžøç6NÑâßž…7¹Ñ|S+´‘!B°çX&NÑXQ µîBÝ0 c<ãò:f]9™}Óµ:ZøÞÃZwX¢Zãï’úåFÈÁ!_?'1”ÂÔ¾¹í¤ Apð°ñ _W ¶b(K(‹½~Ðü˜£Öƒ"w9RÇÃAaÞ¬u†ZÎ~ûJ­§­§ÖŸ‰—¥0ãßæiÎW©’xäýC÷ªv–ÖÝÈåÖþ¹ÇGò.”«DE $ꂴͬiðãö¸hàÈÔ[À—Ôø­\Â^ç¶’Öj‡H^³Þx<ÇvN&JÅ!ÝÇ=óy^iýØ‹¦.t …õóõD©W°†×ÔÆæªØÄ TvúB ¬¨ß=Öá˜o¤bìѵé¹J*Bü­6YWö—…¬æ]½Î!ͪø¿?vÔ–g=¥½u²™^þ¢"ÜÏì×f«VáqÈ÷Ïù~ž¢ X—Þ·“"&J¡¸ Ý|Ï Ð;ù¢8æò¬ ¤@Èoã9´,EäñÈ«ñœÿveIªÚrJ¥»ÿ<8ç ;ìPQãŽþÑ.Xn­ªï k««ËÌ}ëýß~§çÔPÂxß®é9FƒÎâ÷í Ei¨ |¯ÂZLù²bØ yäiûCeZ uBH,YnNm#D¾ïE Hì€<²G~¢é ððlx¥#‡'ÿOØ©.]Ùu¯=;@f¹NQ—±jÎÿ?‰>?•,FYðiZ9~¡É-.øø©lÙõ[>4è=VO·cX‚“nã2k†>⤶vĺ6¼ÐøýÜ#»OuC}tèÆ)Ôå>÷?ì>ÇúðÞCFÁ]MAȯAÎôyþ!¿Ô˜òx*¿UÞ`Kt_ÓVS‘üšGžÈ¯©›‰å×<òq%;Á¹äó[KQ“6ÂSz‚ô–«W±•T}3sX|‡³i—qiiµæFFÕ—ü›ìŸNêpšò†Ä]â@§¥eBÞCíÁMüªCd-Ö|bPáþ|nòn„B‹¯‘™,íÒ"äó[R‹ÐªtÍËB>’Ÿ+·ºb“c1íÒù$?É™¯„zõÌúJŒþ`J~’¯vªmÓH•Ò÷¾fô”Jû)idƺ¥÷ÏÓ!äIá»d£º÷a( †¯ù€Hî='› ´¿‘:ä]và×HM2ÙtÒ‹^xä ‘wõ+oÕ)Pùö´¦Ô5™øï)V ‚®Ž¦ù¶íîu¥<&¡,ÚÓ|Y®{ŸyCÙ¿¯¦ä|*Äá¿ßO'¡HÃdçÇ“˜ÄiŸ¼;o Í×LÝ"¤­ë\©×ûQNjõ"uù:‹Ã9" $?·+Ò@Íi ‰øŽ'¤}ÝÈÛ‰ëý&Æ‚ÒÁ{¿e¥ül×Rw=_aüÐ!ÓÙ²âkUmy‹DêJà&êD™Ô !ƒ'‘Méôž<ŠFlëÚàÿþøî1ß)‚ÿ~Õ)b¾SÄòš˜¿tŠX×"¶s„|DÒ_îàTOi—¬‚|6ùùcع¿ó÷agÙ¡]xƒHõ½5jÃóŒç-*¡uòóþrŽmLî«¢+õ1±²í<òs¨¯ƒ>WIÿÒ@•7ù9žG©}Í4R2„¼·Â‰èékrÙMŽwD¤3µÆ6'*UJ>!äã¹dV†÷ŽxuÀleÚ¡îèÀ «ã¯¨6äÎŽ–“WÜûÖzäûÒÆ1¼wDaÄŽ3S,q¯É÷°ÏÂÙ…Ä=Ü{‚Ý’bãRHØ“cÊ—ót«­‹ç\wŒí¢o2 É—wÕ'b͵øBÞ®Ì'˜nqH »¹Ž–îÿlYS5íÄàÞŽ¬… Þ·Iû¼ö>AN¾¦ðšßJá×|r¿\óv%‡·í´‡•¼é•¼ÃJNb¹¦ï•¬Öç„÷ïõ¹ØõÙÃúLÂN‹×çâ×gO¤÷5R™‘'Þ½õÞˆ>ø÷…÷Fo¼7È AC`Džse3¤Ðé㸅>¿izR­ÅéDŠ[™Z·Ç6*´Â7»4 ©ÿûÍ5UâQ‰Š#äój%ƒïˆB>õáuøŽSãVI˼äÛB¹äÐGœD«²X¹b½=Œ‡:|/<Ùo¦!,I‡Ë´n(GœÄCj*IÅèº×øš÷°æý§l;RP>C*•z=dkÙôy½ò]”=B¦±ÚxíZØ#QïHTøš7¤!nÊk*5t¥Lr„ŒŒ6}ïAý÷œu*™Êò©®9mŠ%/Û,ËHÒ0úõ¯Ûǫػ<ì Ñè×ÿ<¡Eßü¸ÙS^Mùö½Vbåæ¨Ö˜hÇ‹žà;úXf±fÛ³¸!e¥väð”>ˆ "ËDæY;0„ŒÌ 'ª¤u ‘!OÇ\yWU{Y÷y?7ó£loû !ã‚oÖ¥¾m‰‘gVÁÚ~'^Çø‘ܬ0¬•tS0N8F¦ž?h‡1ô‘…Èa`Æ!oç–è{¿%¿Yô‰*¤úµzfѧâØbÖêÙü'×í¯xˆn Àï°ÏÇdg¦×^7R!o—çûtxJ÷ë§4à§tÿõ)ÍÑSºž’¦ÓSï ³U3ƒ"Îì¹Õz¸÷çïHƒI"Îì©){=oy»ÐØ…ÿýõÕ=µßû¾«!¯ú€|G•€ÅD‡=%™2=?¹Œ+üÎÏ/1˜i$0„L/Ë÷›Œ¶Lž¯pvÜbg–{ÿ£“-ËÐ#dêc"­ £-³ä#FÞ@[¦0×Ôœ“¾ª|E)‡¼#uwK]Ôêî-iÅ€@nÕ‹õ~k»r¦9¤»÷ˆqô¥ZOcÙcä+x– øÖÖù¦v‡ !ßßÊ¢êÞ÷µQŸ2¾æç¢@/»ðŽîãè¤B¿“RßcÆ‘a#Ö•ßéËuà…”øÿ'éu5ßÏž%Åñ”­L žSO8ÈQåýžd²(4ãs®âµ’öy¿®¼×ù8‘m7¿sªÃrJ³»¥»¦ùóÔÁf,Ïååk¸£Ûu÷N}uóîýþ]÷ÇÖ8ðßGÉük ªV¼£'::M;ÜÉbK­œ:ˆâèüYj¨DÁa¹?³ú¡Ï7´(ȨÖP™R˜:ºiÕö!iŒ…u3~ËyßS„Œg!p\´kë–Ñ !_x:Ñ9¼ÎÛºA+Þ!A;‘¸¹a°µÍ0á-ú<òã½BSëÐÂtK¿pVïQ­ÁŒ’™3Á,PAs&XqØý>ϳ¬úèð/M®Š°ƒ`3~øŽøcª›ªa«‚KQLt<ü€;4¸ý¦¡da]¾,j*bÛ?†«î]IŸ÷«ÌëCŸ—:Åu¸­×ï:‚3„Œ•,ãÛÎU ÎfØñߘÀæ'=Y£>ÑIì5B"›7êʲ]yªüÕÛa:øŸKå/…œÂØ]‚¿èˆ ÜêÉ¥«žèSEø˜#‚%¶R×Ê5‘•ºB¦è<–‘!Ïuá {ÜþÐy„ÍñqûCçê\Û:°‰?n¿ Vh}4¨ˆ=î×.šDôûžqkŽx¶lÓw ´Œãâ÷Oä¿÷푸 6#dŠyÿvެgd+I7!$Ò¨]öÅT†.ÔÚCÈûY’!ñ(“Í”d½H•ÎYÂ!ŸEH É3¾È!_ÈÌÀi°¼ŸVŽo?í–U)µ­$U*œù‰U]+©ŒÊVvøÞ ê¿n)Û~Ÿ‚²NŠ?P§¸}t]Qj\d†¡iœ¢›^Çmº"½Ðš¡³H/s¢þ`Z?yÞðÑi¾ÑÍ©å(hV{y¸äy;´4(´^¸¾êñšwà~#M[®ø<×uø@îHŒRsnÄyžhµŠyù8ã;NCÍ‹®ƒú<^ÓËrÌS¥6±qiB±ÿ³Ò6©+‹¥m‡<Iˆ…ëX÷vj['Þ$Èœ8ä=2}©ì²—̈±dPd|þeúQøóuœà«|óƒÍdÅÞ!äíÚ°ç ¿íafüßc7¿ªv&dDè7ßò[×É"[! ¾ª|x[6¢îžJít´·%B¦1’²¡y»xä oàšRm“úïBí¶5LµvëaÕ‰¹Ç«Úýç¥SÌšßTdµ4£Ï"~)^uêšxÕ½Ò?V„ ¯ôjÕ©èFm õŽ‘÷ˉ`¢&¯Ûïh;|ÅÕfž·Ù²N§ñašéu?ÚZ”>°4hôpMkÐb‹M.OÑFqrîB.ýzÊ‘F•°q¶½úŽàÉ?/ø½ö h‡lÌn¦0 râ²ÝÇ !í$‚©b”–÷¢CWNzÖgy‡T¯H³C1ôõ¼àCö»áCÖ=þç‚Ë6™‚ßùº¾BrðÉ ‡ VîÙ$SkÇò’•^ŸKŽ%åÛ°—И|ÿÒfÖ‹¦¿Ìá­È£ ÈãäÍá2A¼bÄUžX6IÏKÞ ¶@+Ó‘¥eí4@ÁÁ!o—u.¸LÞÇ ×¹  >$±õI»üïlµx⃺Jò¾.ÁëF…‹”ä}ÿ½QQÃ4Óû÷|PÏì!ú)Õ¼à 1y²ƒ™Tï?4§à|x§-7ÐÊqÈ_4§Âö‰ZYšŸŸ;«6ý‰®-·ŽCÔ“¯­wh±Éz¢Óón›:çvcÖ¼Vø+›ÒßQDÚû’ýUËS„1˜´wØm6=âòÉ'ým B°Š'ŸCzXº MÛúòÐN®ˆ`çeÓ­ ‡ŠSUtABé&ìÂ×a&ó$“d˜i_Ç`ŸïÓfôà¿1ßãYLŒâœÅ`wD «bÐãkÞ®ÄÐYhL~þhaNáÞ¿7&£·ù@ þïSÚx1kê_»‡P§Nµ-Ã4´á)½°elQ¹ÿ¾«›×^i°ƒEöoX]E;xÇê*Éç÷os.ý® kµ¨gM‹yKÿük‹ºVÞ½/Ò¶¥ßÓ˜ä à KWq¶òÜŸïéOüÅùµäô¶2F2áŸ|úƒÙÌ$w“jÕµl#²,;„ŒËkÎþM=„¦ÖÑÇÞùˆ ¶¤¬…:ÅÜ%þïϘ·CluéOØ4f89Áz[ŒÒätM¤Gȱ»Ìh…‰¬š©›BÞ¢b”+ö*{Ÿ³À$H#†Óù8f w”"˜`6i†gZ øÑbV²W+²ÌŒBÑ,ý¹!M‚IÕ¤”]µma…ÜB&¥Û#ÆÊÚ {)·’®@Èx4­²Üôe”æZ Ï#<›Â“´ÛHÏ+†‘i„ô›&‘sÐøH#ži9^½€IZñU…-;BÞÛÞ ¾7 ïTÞC‡ÿw8‹3+ªã \9º !ŸÑúl,'FíŸåœuíH2VÑjlɮ؋v YæIìù"©¥SFn™6öŠ#äÇ—”‰÷Ò÷®gUT‹Ÿ|¤bl*qz¾ « ^åŒöš„Bµ7ék ih¯Å|14É­?·‚v[ÕWÿTÛ™³=4çÜ02MתÜz}û2wŒÿZkŒÕ ¥•F4'=ãjB ËTÈeÙë®@È4¢)ßN-¹!dìé`Ç' ’³†v%BF²Ø¾Ô!ëe—•dƒ0® ºóRªƒž-!Ÿ‘³°§Ý*d5w¤ïòŽÄÒŠ¼[AòuY&|GzAýg{>…»æÞ÷Ûš«|fGÈ_øj9¾Ñ¹3¦Â¦¦ÇOþVi©FÌ«ïT¦ÀÙÎ;“3«xœþü2f0J“éÏëXˆ-ÃÔt ¤1!-jµ×¦7Øö-ç!o—íóúpÍû…I°Ãï|DÒ…¥ÛJ9å¼nkäû ÒU:*µZ¥’û^Ó…–Âd(vTÓºÂ<›CÆ~"®nÙòrl)éB‡¼ƒ@°Óýª·ã*EžòqI7ÚüÎÏÁ¯¹pr^zn™·œ°!ÓïÁ‰^÷ævQˆ !/ˆI|ÍÊ #/ÉxÙÞQLÆ;£0í=B>a-•~{ÒSÓÓš}‘ñlàFU•ña„ðþÂù¾tôÍ4"ã™NoY¸Nï¾÷Ã>£ïœ§Iò«ìí^Ãïü®d»uU‰þR"Yv2¼ó›µÎùõ$Ô ÖûúG[P²;ÉhG½¡(v“ çP¾°ix,1_8 ³×ùÂz¹ÒÄëÄ»sfŸ |„^ülç ÇÌ‘tÍ© ‰ýæWÕ¯›˯ì35žµN?…(½à7D-ÔZrë‚Pup·k“¯ƒ½Öj™´³T8÷çbj¬ •ÂÈüeZ±ipöâ’<î øÎ@o›øäïÏÁµ^¶§‘Ë8 !câ<èÆùØ·úlÂÆK– ½|¯Û Ú™ÒƒâHùŠ·wRÿ‰\®³xG$T°ìΡ—}J6³Ø]ç²ÓZ/?ñ1JçßJÚè6¸£Ç5ïfij£“LÿœýëºPs¯Ý¨9 õKÂ|”*­é|m¦YŠùì0 çlá`¬ö˜.ðf|öÛ[¤œ;„,R¤“¦ïb©…¨ç#ï íÍ8檞y%òñ 9Íüù•:æÁŽ»Ÿ7É;ŒüNŒþü²fÔk¿®“|ÃÈè€SÛ-/ùVëJC?/P—V­O^Kyfj>f ­iÍy]chR‰zwbÓ,yLJ£ÄÐLÔ„Ð0ýPÎÚV kÑÚGš 8z#¨>0ôc„ÚÁyÝQ*LÞQwr ‹°Æå hø¶•ÇDj°PЯ$rÈÙž zÄ9ö£«·Ëˆ&a}M˜juÙ®ßX…¿þç5þï_ç5î”°¤T5M–ˆíÞF#¨!e›šP"dtäðA[f²-gJ#{ KÂ_.Y’©)NõV–g¹Æƒ“(-D=ÇÈ"EºÚ [µv_ç= Íu®Õ×Ù²²t²4üИþìD/-¶S XÕFÝ}@ºŠyž”HF„ü~»´*ãPúFÝ¢õ…Òdº¾ðÐÏJkl`í~¢êOÆêa04‹É¨MÈ^ÙôZ ? ³.KáÕžèMÉ<®X–} W3ÖÜö)á#É>P„Tå2iÍÊZ S£ÇŒ¼=óäÜF±ÚDÈ"‚‘¶þ9¯¬æ`]â‘÷„j`‘íЕxÏñ½? ~©‚TüàëAO:c ü‚jlÑG9í}ÅΠgòHÇÜ7?¶ñŸ½®òÌÊ’'ÓÿÓh átÙ8e‚—øæÝh*Bˆ»Òãàs¿4 †f—} 6Dö & P÷ µûLö*®ìR…¯¥Ä[˜Y×íg%´Ó²ÏgÓo[X£q‚ Æ#óÄèÄ•¤fv¦Àz ˲_6“¯TzYþ‹f™¨¸“ÅäÍ'Ö'EÊî,{Ï¥HÙ!Õð+e7áù‹²šŽ©jØÖí©^[áTÎQë†Ãm²?Núµ3\c/’âWAõ;h€¥˜¥yš–Ij9§–Z–Š'¬­²nÞ«k`‹Q½ZlBfÏù@Æer­¶‘bdž„øÍùqkJ7z9û-|p[nå†Þ$Ë‘Gˆ7=ÝX·ã³›qDz•ëàõ\œŽâ$`”E=¬”Zå2yÅÊwÕPÉ2ñ &þ½¡/c;Aš%JOÓw¹´~²ázôY`\Nu‘?©ÓÞΦ£g‡6þyAv½ë'¸lVVAû<Ñ0þíNc²ÐN¾^Ž™c‹·23ÇÂB‡$ÇÍûĶfzZÏ*+°Rj°~±Áœ"Kõ†WM=ß¶©•=BfÏšzgVKXÙ%zÃ?îɧ±†â˜:|ö6«íÀ¬v›á·™Çöù¿] „k$5ºjÓÕ ´´íó¿Òn*¶ÎÈ‚–ëÊË’B&‡ö¹®¥ÓàyóÕ5íZŸøÞ¿^÷º9éàå8_-n°X¶ï)JX)§©£(mÖŒÉ6mŽùø%mV­*9û».¸žû>õ™—Ö€ùUÞÚ]RsöªÒ%“^ dv5s–•„5à¶‘¡ðGÿÞ½Úq׫›™Ž!zç AóÕ5»^…`d‘ô‘§j§ln[Vò_çý59Ôxt]ÄHºó~ë[Éj&ô¯!¿~çá:¿ßc͘<Ô¤ ¬äìvÙ&…¿RÇp+)1¡íCGg}ñ1ÓnFëz§CLÛIT«Qéù,Ž[KÓ¶äç%)°÷²™í¿ä(K|a´g¶—âÙ³§ôsOýÓµrGD µMÆcÚzÍè~ÒЮì–_)Ÿn:2”Ϻ:{ÈÿËn·'³N·³´“fÔƒÝ õw" tHµí"Âp>7PÞd1%ñB±9¶£ÔeCo‰­Ò«` ]‚Ûý]øˆ‰ê(apÌÄïÂúԚȾRFvûº„ùŽÕpº—iJ¢ 4 ï]¿Ï]R Ç,>.Ôi7(Z›Ô}ã„ᎊÏ7á#¤Rþ–€îê‘YŠ æ}ŠŒÛFâÙ±ÄõéŽNxJ‰6ëelVìù“®Üuœ ýŒŠ®ƒµGq»>OÒº¡AÏI“¬,ÆÏy+| í°ŠõeGïâv5ÍoR¿å V¶ù*þc-‰ õÀÈâ%ÒPl®g¿'5ƒ×è³¹Õl À½Ú¸ÕôÎ"Vn«H2{‰$ÒXZò~‘âv>HS)²“S.Ð(Ï#­×èôtšNЪgÅEãèxæÝ“Õ-N„ÌSËþÁ•éçØõg_×yCJ&ûÞMD$Œž9¦œ÷”y¡ôÙËqGHØŸÃúÞÉ&û*ØÖ{ä#pRT}Gz=Ÿ°ûã_ns.UoÊèa©jYü>qÃßXö·64˼#£©0ôyŒLü»‹°³#<×^ÉzÐëf^2¹B¹ìw…ÓÌv˜=TÙKRbdŽXÁ¶u«¹5d¾¯®xÛVQŒ(>èË”™!+zÿŽôu²r„Ršeø$]<ûuRàþ.—H/b§4—(K%lOv0’®ã†‘(Íà ‹Ä¶Ž¤ nÜÙ3‘êàaÝyeW Kxž(1 ƒõŒÔ³Ì„ÕY*LCHýSŸ$%=´yRaÚÿŽˆ£4S¯—|3)ýývXÙT3^uuÅKwórU¸jÙ=G~®NñälA¶Yè©"×|Ä+—ü³DñôŠK¹*@ïÅ.¥aÛv‚Ÿ0‹ùˆoÂág|É2¬½3†-Yôþì¡h¸?®›yMØÈì©ÙÈœ9Bf¯Ï®Ëàúf‰’èÇ7/Û&}Æbñž¦‡"c“J&|ª$ò|-â< Œ#—žÒãã—rmÓå¼£Dt-×6[®…Ô‘ìñù{¹‘Yšiç”/F…ëòüÎ^|K©æè²1|4ƒ¢ "‰æèYd=,àÞó÷K>]ЮqÚNõAϦ9«‹,jybnïs9.ý÷ßKïýŽa¥mù§Äôµr MÈ.õMf›°4ýú€;rû§~OpàsyLc݇|tZ§ÿõvz6Ü×n5b–ª½^HÔ£)^–*³Ð|4^ç£Tou8š¾®NÏvÝa‘-E»«Ð,Ufý¸ø97ÒšL9=´°Ùõõܬ Þ:RÒzÙãuÆE—üã”ħ·t˜ZÈ^óÈ0cíf•ÊŒ\!‹×ùˆV»÷^¼UZ;WÐ-f‰ÚËÐPJPýPVÖ'If„D™õs¡¡ð©)ÕÊ0Òóï4JaƒT%[1+ œ…‚†¹Ó£<¥¢^a²#íT$}=¹Ú¿Ý0‚×*êK¢šYJ…e¤˜õHÒ!³È÷Ú|g ·«z®†iû€¸µ”i²èe‡ˆÏ3î®û¼sÏT²ìú创R‰æÈQî‚&δxj#f öC—:¤" °’<7k!ýÈY)ŸR¢N²Ú¨Àa4oSÍÛÞ©©“Òý*¦rÇmâ$R,T€a>*Ù6Œ`iê‘·@P«±¦u9{òF]æ;IYùߟPUúcNƒI‚BÈè^‡c6Tkߦ‚}Þ.ô'› Þf¢¢úù÷zŒQU‘šù4˜ä:Çá =>;Ü;~J½FŽøìþÞí{÷×iÎ.ôÙ¡føÎн»C§}62ª~Bû Q{ÁÆaï š„êØ[8Iœšý–Z·áb*êšÑ– |IÔ^Agç=FgWO|¯N„¼aä@r FMãž’³7Ñw¤§Äø%'I´^ éhØ‹þæxµ‚ѳG>’•iG\÷@j¢¦KHéòÈ/˜ãÚàǧçµb¯áÝ.®á×Á™ o!m=û¾]}åýZfœ[>s 3 ˆû›ÐøœñJ¢ïâ{ݪë5S¥Ó"­ ¦«ô*®!e¿…*èûñ”¥ÝùM©vÐó­‚mËoìqaÛpvùnÓ¬Õ·«­™#L/Dß"—½8ÏxG_ÏD[ƒ)cÉFÅKT¥9Ãßà@3pRm\OŃoEå­™­*’Hè0çQ™õLhp6Ӏ̞ó¬\t;ÈRò#gó¨úó¯üÇŠZ¯ÝãJ•‘–'Ú(ýä½yù츖¶UPø˜ùëšAÌ1S9ЧW5ú!5OO¯­ ³øÍxe¥àùÎXE<Š^žS×’Æm¡<Ê^!ÍCÈ å×9·1”]wöñŽ’ü[´ÕDÃVÓ†·›RG©‘†¿‰ª‚i¢1ií[¡hí;òÛa!e3À‚ÛÙu(T#ŸzZsº1„D‰(~«¾ê®RËDŽߦ³ðjuím\?Ña"0såQJ(VVk)l?uEÀÒû ,àÛÖ;}ñq課›$>f”…pKÞª¥šÂ~‡GÞß ö6Q"äãÝ“'*¬<òëÍ“«dé·M'?8’ѡߌ0øÉ¼Û˜‘$¾¤wvWÔ[Gô$̼²ŽæÙ2-FÛ1îI9‡É#IYyÓ¨ ƒH–šÚ¼l¿bdöKS•"dþK‹Ž™´È_7¾12û¥M2Oµ’®Yë•ðS¶PR§™$~‘`‰ü΀3H±È³K’MÛ°’qSºþmC3(ÏŸ,!:`g-!¶ŠÂÐ\üˆêÜZ\K)g)z„ÌçŠ6rèû¹>Y‡‰m¶cs›ž‰uÕFƒ5€G‘'Ûzƒ¤6#={gþ½/[ˆÓÒ÷ÞK¡Ö!Ž9êúïÛØá§ô•L]­u,!c­öA׿#AK¹c{9.G7lªÅOþ#qpÝ-CƒÔcÙÑ,ègBx÷vc³Rœu‡ïqã¢uh–f×ï©®/¯>h×:¥Ï0ê×_Ÿº»@oŸNësè‚`mFü™8ÛìþçÝÀ­&ˆ’•ý-/G½ã>½ó-_Žm3ã †>bk×ÒPÍ2Mõ•zíu`è˜Àµî¼,çU”’`èwbzàuvãX®ŒòYâçš}©ÂZE™¤Š ßò„Ùl[‚•"M±£—´ëÜmÛÀ2‡†yãEÕ>U¢¡ óÆò´µ^›}*A0²x­OX• ÈâÒú OPÒê8BFUÈ[Õ¨§i›!€!OXÈ?¶q"šw1Ol›b+#¿ÿ¶¡¿=‰™¿Ù€X×+òöfÂ8fb$4N«&x}4ræ£_ ÖÈãÒûǦžX¤µ\3HÑ_Žùx޾à.úB)xž¿mjt]RâæOû Xþzäã’}`f—}@ƒ6Ã#¿Òš­·PSܰ“•'GÈïWÖ…ýl­ Ꮂ y²oýŠE½ÐØ!cœ² „··>’¦á|†„Ì_0°Kgrß|‘½cu—Ê'r„,RKÕ¡–ªJÖà¿“)‘Ì®¼½›‰¸7êhhð‰øïDKU¶¢y‘¿ø’-ZSm² ”Ýfb˜Sqº¹; µí=vÇ^%_Ç\N,Þ$_·7Œ|k#Í ø"¿¾‰  nNÖåm@foƒ d)<À©Hs>ô¡UuÏÞ‹Ü`&¥=C¦rÏÎmdW”ÔHÂ7!ð5ïˆÀd¢Æu!l¡ L:ä#nËÛQ”nT}žÃ÷þŒFb[›w®“ìŽyG|ï¯H¡rUæE¨õÉÈ‚¯éÎd#ûU;ÝÄòèÛ’®ëoþïzîoÙK¹ ¸§û7ݼPäZ`$r›oÝ8]OY­‚û!‘î—“ ZúƒÇè9ôÉÙ’ Uì ï´#b;Q€²î÷|¯÷ÿú=Bº^ªBy½×FÆ&–¡øµS9³¹(?BêO¬sàšÅT¬²ÂÈd‰…×”Qk¤¥ó\‘?ùŸXõÙ{Ñœ”U³÷ÈÄÒR¨|D žÓH9iÇC#g…Æ¥Ó¸MûQ4dÃP“ÖPÛT,¹¤Ç8ÃŽ¡©—VÑVqö膀œë…œ”ySÇÿ¬]„Wæ#¬Ûd>àgåªñöqA‰Ú+D¥^ÌP8èIÖØè¾‘®Õ[ðš²ÕøþÕoÓé$Í×öô^q“Ái‘yH¨¸Õÿ—¸[sÞªÔr"\­~|Õ[4šì³emW¡âLp¢Nî/ýµf˜'± $¸ÚÜÒŒçj&î¸ÔÐ-½?Þ}à@ F%–}øõçg·qL\šÀêvÈ[lUb3ÆMŸ¼P¡.\óõ>îìÈ~ƒ(6RŠ!oà‹ZC ¹Í8¯µ7šrHs2ÿ÷ÇHÙµ6ÊSÉÁކ™'êÚ©M¬M©ŽÐz‡JkL${s¢Ã4AnYRy¥d§«5•óh4äñѬUIí,©ÄJWyìøš)Ž}f«)˜…$lª·:»cE¿×FФeeùDcóɽ¦ÎØøðöëéGå’P—Œo˜r6hÊY#C|ýx3ÝqÊO*~ÑyH¾ûýáñFÈlm:¨/IïÞ;6‰l®¬EI/¬*ÆÀÕ„ŒøôÔ©«2>ò±! ôïé»ÑÔ ¦ä FS™]MÙjþõûG£©PÑx€Íu†d†¨§Œ !¾~`ºÈ¹ó†L>ô`Ô×.02ýЃéèùÊ#Ddÿ!›f™JÂhÖÒýÍïÆ4µŽõVÉðëT›sŠ_欶Ⱦ†_~­ó•ëÇë/c¯a%¿þ2özB&ïn£v=‚Ûhˆdïn£¼&Ám4AÆ]ó3ªNÏßïó3%<Ï`Üu¡ô¦.¦wbÒוR‘„,ä™|W* Ñ}LúòYõžÖêã yÕ3ýbüNÄ%#Ò×™~à ý&Ü{v¦ìºÜw£Qû]ø:žÙw¢Nkþ‰3›¢ðê\ÝPµUNC|ñ<Ñk+¿’­ÖÅ|@^õ| ÖR¬ɤÃ|äùai÷kxJϹ7¦" t® ‰iW†2Q;‚A×è²'a³ß“_?ÜšëÖ¼Á×™-ÕÇa×’ªB&ïöfºO6ÏyèξNJE…·*éXIÚ|Ð׉‰OÖ¥Ûí ]Q®´BdˆO‡4NYG}êôXrŒL?̨£F*#’ÒÅL€CòÙ—:¡UgŸKÚH"ò­÷¸yxSCšÊf‚îldõä‚ZÓi%-õ5”^')yE6-vº¬rù´#)&ÐnOùÇ#½‚šGÝ«e2 d÷ gN)޼Vµ-2=­Oo'#Y%ä>·ám¦ßéôaÎà•½×âÝ&tV©æ½‚…w›×ý£i™´Jçð”5æg¤1ŸÄ¤$%0Õb•‚‚~òzâÙšªöƱúÛT]HìB ã%»˜ô [ú%‘ÕÓ¥ý¸O8dr!u¡Mõ–èìx½ÎUœª8-Yæ¾wU±ôÝ>*®9Ì*TäIH”®º®+ ù^æD ddÄë'ÛÊcòâè×!¯éf²ÖkK2ò]q¼fýë{N÷ÕO¦‘}”í4>9IWuKV„|„~ïV´uµã1 |GÏ8ãö'Y*©N†¦:qügMí‘íBVõnñ“ÿ‰nKPYt9û0œ ¿QÂíj*Ÿ:•‰C»Ûã¢äšDÔ¬#¬1Öñ­ mÉ5·¢²£‡F,ljun~-¦4‹m±\ï“o3›6ÐõLâö?húˆ¦VÑÐN×óßÍý i£Î;5 C™þü¾; Ø®VQu㸎+ü¡á\peœÊw‹º‰©ôÆ×‘òÍTº·/§©šu¨@ÈxúÒQd)»‚2^×™'oø$»­SÝB„Ì`òÐ$ѦӋ騇#<%awHk€¡GZW±³ã ùÀÆP¦†0‘–îtßñ=ýù•›£Ódm/© à ŠV:¥°^îMEšUý@^á'ÿãùy:r°¢‘¢"èµ>†þú^™þF»][«Å,c÷ÓÄz P/\_3Y’n`§?U¯üµý­iÔ/ušY¬,Ù¶cŽßÖ-‹ KZº~š¦2NÐ{è—º§Õs5õRÅ…xÞj®j–‹JûMóá{³oë_ µsÒ ]ºNý ͆¾>šbË^lòIbkUÛ©¤+‡‹¦Ÿ$¶ô<·v¥éOúÉ®t6v¥åéš LÄl‚qÚö-œ“Ù)w1Êô†ŒVð·k‘#d4±iÇá¨AV“JH(B&Wó·kß#ñÑnù½]MÕ†|(üÞ.*:R@¿6üÞ®¦j%Ð~ÓÈïíbV¶èéï|^‚« užçý¤ Á­$>„k†úJµiµ4"Éb*œ¦õi*\+ä”Ýꞥyò뢂¨…Ëp>cÓ ¦Íº–òQ}®y õ¹ÊÉ‹Åóœ/d@H¨ýkßGÚ;UKY6™B•ÈGê*{±U݇2û0—Us±`äYr›Î•ža:±Á ‰œ´®äÅ ×¥¿o}úÚYfpšïMušô÷³Êê¬õm…¯ý¤Rú¦AÌ‘ÄAQJ¯ê ôéÓßì›è$`óþfßDoÔ—Ù`dòaVVpÈ‡ÒØ¡Ê¬ÛŸJ Ó^->~éŸïªµ‹(`ÍÿF] +m_á§jÓˆ(Y›ê‹±<>|v›þ¾9ç!eá%zïQžá×oßT€é ¹ŸfHoQŒôö`_GDýïp½–VÉeÅˉú¾¦C¦ÞFÙòðl_[×3_?vÈìóÛôòbéÉWãímîð<#ò)¶¥vïh†wq%϶ԃ¶¥Æô–|¨t¶0”ð<¿Ê]JZÁ©±*/ä.µÅ9¾fòAîòàÑß™"^€aRû6û’Ž5 ï=ûBŠW_( §±¯ÆiÊJWÄøó¤«ò­W¦5À·/}5LȘ;46`uWåøšÉ»S± Ó~W™ÆbG~ÞE%B}Ό̀¿`—<5×uÀûÒ-&†ÛS¦q}² S&¸e„¹kó<5íWŽ‹„Ðö†µûc4W£‚k¾þR£ ïè…&u ã·â+¸rË7_iN“³œ‹NÂ\¿hYö¹†¿3ùy“u¹Ý¢6›½žá4<ñD·¢Aöt/öÖgÌõúË–}Ö´«ú¦ ޝ™ù¯8‡‰½Ž‰²Ô–7!ä=6ojï§¢®9C –|¨i„à!®Knïž–N+!C`O¤Iò©>a:„çIBžE廩m×1¹§k&—lo#;'Wļ»ðݪ4Á“7. Èû;³É T¬¤L¨b¦Éã¬$N]¢N.qÌäà‰äNü¹é›v&¢?2 ã;x¾æy¾’^bd {Hå”uí¼õàÖŒYÔ¯ý\À23¾ÉVÝóã Q ‚Š™`OŽ8e0oB«r&c±ª@~ýõÆ1q³3Q›ÍJ:Œ'4k.ç­íZYî^ñ<˜bf6¾°ïÈZÆéÊÇŠ‘ipWóg±6‚+ø¡Ž„Ì>YðI¾÷Ȱî‚ogqÖ]Xð0—sÈç»c[§âš¢ Í‘¯OȆ ø×Ý,˜o)ÚøWåû[9O5ÅГ¸…†n¢’U½ªÁа˜áAiÓ¶I%ò,ÇÐ w9 í73þÖˆBï+³Õ1×´Ì›}ÅÐ0µW™>)5«(µ‘0 ½0˜Óöv*Y†ôUÛÝ2Šƒ.ÓÆ^S¿OPVQW5ß²¹-ÒŒœVú ÐÚqUÌ*T–ºŽj= =åÁ©½ÇZ­*h=}(˜ažÖ¤[Å$ÏЛ/ãyå tÓ@4yhðº%Ñ\Ž…çuëÔwÑSÌ€ôÒïµËS =ØyjÌ€DÈU#‡7d!hʦs_u4JŒL½·óð²SAlU÷Œ™…9²IÞB‘þ~å…7[¸÷ÛÉI™³Xƒ‹˜G8E#®äµœ'œ$iúAÎSg´±œ§C~œàã1›¶©]…‘™³vý4;å^Ðh››ÍßSš¡yÁ“¸:ö †yÐ\r:›pG÷³žc[”\-}²ˆpGS¿¶rýo‡\Ä7Ä˰³}êT&RF'V-‰'Në¿þü>÷.Œ¼}ž'€ˆ,vÀ¹œ'+äõ—y‚ðu¼>̨(Í8d{Ð8­¦SÏuà^x)Yª¶gÙ@oµ'‹ÙCÈoË€üý‹Ä2œ¢1÷I,³“ÄrqO?H,s„¼XNËiÄ=µ{•úÕqA®¶<@b‡w+ fsEòœÎð6#N§gUšS»QÒcÉ· !“À|­½ï)ßT´ìþõ4FZŸµ¦´˜—Ñ‹³¦Óé'Ì|TGy}'à¤ËBwÍu¢œŽÚm†%ÏkÏ‘uÈVñ-Ø™µrªr„|„®í3;Ø’÷E× d¬jâfy»®êØÚyIä ÅÈÛ¥GhM9agÊ¢Üæ°Ã%Ö ¥GÁ@7Á!íÄ‹ö¸³ÈºõHÐõpÈì}¯ÕÙó dgÁÙÓ½‡šuì¼d¢¡øÞ™¾÷!?޻ŀŸï&ÇÒÀ’½¾w˜!Oc–ìÕ½‡J_vÿ"Ϫ[á‹|­ Í¡îqõ®|–/‚.Ü“E?cäí“+1!|FÈäz‚¨‘ Ì@¦÷Ÿïú0…˜Æl¹ÿŬ>ƹ–¶àUÞãÙìxútõÓ§BÞÞ§Ouµ«ÞÂôi›ú@ è¦â7:21KÌl³s¿®ûÒquÆP^Â{˜mÿýë»V~ôŒ‹a?2 ù|é7‘f!Rmö°/Ʀ>ÿxñb7W¹5r^Ú!c¦`m(íÁë¾Û2‰&™ý<-ï[™óö{ŠDÀsˆÂt—h[úPk»gh~ÞUx­°£ZB@ÅBÔ[Å¿þŒ§ËZ3¶UõM_”q|ÍWäHLýúäŒw¥€IшH×ïTÈ~ÛÄŽ·è<ªìî­ž’T‘ú1XÄ‚Q¯ÝYb˜œ“jŠâÏG$¬;%àÎHµ³™ a±`üóô[òè¦5‡ >fÁüÁ'WÕHYä^¥3}œúÇVHϾN³Š©Yèù=ž'DKöUçѸ­s±w±<žHËeræÛÔÃVÂämd:u¡ÁÐ÷¡*L§.5¢\ÿ9<ÿŸ‘J7ªûúïœVV0yúõ{$)ÕxX3 _ß9œ†ÏŸÜ–Ùr[ùû9x䀷뚄 ì€ùåI\aª½aLE )ý¬{qpÛŸ£ž¤öÏ\†üèyûÖó‹{üÏ8®ûãªk6®kÄÁF ½Ÿgò½r„gú½tÀ³u®ªAàa›>S:édË dy®¹ó™}Ž“µƒH5²SòÛûQÑ/;ÖRBïç™}ïõ†á)­%ÿwM=&ªÓß™]ÆÞ˨coüë5f°ŠLŸ÷÷>·‹*KRŽ}8;ž“€ßÁ {tÙ·#£n«Ñ{5¡w™3^ïë?ßtí£NÉi½3ìuÏ ÝÆ×¸l«¾FÈ,&ÍS§Ê>6†ò3Û²;ŽUð-ä8†1¾ˆÎ敼¨B.ÍÌœ „¼E‚"Ôñ…Ü(ÛÁû3}aa;mîmWˆ.*wt§pÌEÔ³ ÿgÉÝ%íDÚ‘?Ö¹=#ï$ ¯äBÂDz#—uxžIí­Õ­%fC þJP¨œ[‘«Öˆfo+¡Wú.º­~g»lºvAÈv¤sÒË’Ë¶ÐØÏé_GµC2²€·¢C¦‘¤µ ½õ˜:]¾tæQËÿ Zúà®Ú¾ÞAØ!ï±H¢™CÖ|²äÇ\s„||zG8ΦW¹ðŽD¾ŽWöí©ýv†W†ß‘¼2k^óKæ•ù-ìu?Ëk5ÞÛ»¡KQs/ÿžF´;püò®ÕÍ2v{Û d$}P;ú¿ñös#¡'‚^8W•MPž‡&gäe?TÄjl¶iªÒŽÇy ¼-1AÄ>4§k¦ñ½·ŽºÛŒßs€_Ï“'‡—ûT«îà…æw{äëiÝz4²¢ÅÈÛ{C’¹†dx›gÇDH=ÔŽÄè8Wøšé§Ö%9ŒÌ¢t†ºk®ó4ÇBð¯ß?ù_¸C>>Ë3òùÉÿR†!­× Iˆ©ŸÚ¹4M%[ê)YLcÔ­`ßëÝ‘l`¤)‹iŒiþNøWMÙŽW­ôäúód O‘ýüœ×RÝÚ}^Åèù±ÇŽ\énhãþH¾Ì•HÌ"£yG…''vƒÅÿveÉŽâZpK÷bãá³ð"z b’X€Äµú§ñHcWE÷_¾ÆΔ™«˜Â°NžÐíX…Ÿ?·®-d{‘RL –¥±¾;ä°#Q}Í¥¦¶WèMÏ2)²Øñ1§ãFšB5“BÈ<íŸùI3}‹²#FÞ€!a¾zkëé¢eCÅeèOxä=YK^;f*™\i)~æã¤ÌÑME»Lr]òùQU|0òßwÅ¢Ú)Íú×ìIÁÃo”ÕFš¦õÝúšs©?|EÈX ÍúVŸñ²QB—éÇEÇN²ú‘DÈk‚ôú>ÓJ¶®]ƒŸ™LUW^ s\¤j¶NŒŒ“2÷Y–•’[(ˆx$ôM‹²ööÚ³Ú§a¨º ¿¥GDZ¾‹Eêd»·PƒôÈgD&Ÿ>ÑmЉ ~ó?h¤›¹1»¯+ézüÐßßÔÍUkûnœ•~ýlÄÐ,ä E„IªMþ¦Àó6@/q‚yóèÙ¨I!B‚  ¹PAcÛˆ>rʲÃ?Ô/˜0–ç†IÓî] Oýý¢GÉD]Ï¥<áAžhÉ•%(Få Òé@±&xïTë`”&9BÏÖ÷,© ×±·¾âÙ™gCìÒÒœþ³¡3…´3»: •ç=/%Ÿ9]Às)Ï®¸ ê¦:l·ÏLu 0‘gWüÝm×Çé{’j–ëgcd"}œÒðÄÇ)O˜ˆF%-hq:7 }Û€Š_žåê»}fò¼,$ôÆ<2C]I†³¶Ð ]‹‘—3VÖ† ±óìö‘¿µ!Cì<ûfˆÍ!¶DȆØÜboùÁ›ClŒü`ˆÍCl¼}Ô€¢ažÝÿ¡Ÿ·göø Ÿ¯ãÿ.ÕÏÏ#òT?¿cT ä‰~>wúùÀÈ/úùp#gèçwy;N1§Áªt8ÈçQY±Çz`ãå—ŸÏì±ÉêîEM‹up¿_x%ƒÞÚ8w/º6CŸ‰ó‚³ßH_m½ !óT]£ Ìx2“¹Wø™§ñ3u Pȶڻ–¡¼Cý9SéƖμÊy n 9b…Æ·ùÎ_ðØÉÔ{ó{žgÈ£Òß2î6ùúz5€¼à9~ÛDZQéãìl_B&z6U¢ôóFÖUF†ÏYÇg'0G•' ×ñ±#÷Ìú«uW…ÂÏÌßÉEP$äõcsÝ8ë51 Ê¿öôõ”Zòüs5Ìç2a…\Ólåªu÷æ¾+#”B&“ʫߩkšk0W°–8mÆqS™Î{U uIJCÄ’¸¦Eç•°êú·qÕEß—“Ø[î±"®i§±·ÚA)Ï£ïËß?®ïâºÝÄu܉¿V@Yš¥Òm¥02;=? “[µSh™ç©»J³»˜O ì÷ènvÚÕ/J!äådo½7'½7ñ§'ðàÕ×o£NQÊ&¨uæn•)üûøsËuèJÈn¿˜1U~¨hÎ Rí[¼.gÑÔþd`}¿èXCB5毦Àd•o]\@¤ëÁOÒ#ó8eè>Ù4|èÈ«FÈ[ ]ÚAe30ÐÎ!´ÀÎ#ïà(^…qDÑvëÜɹkòÙ™ÏL²é(ˆLÞ|vðipQ¥Yu:3]8ƒì,õk;zΓ™²ØoJxen^–Z³l£ƒ¯ôOTÃàKžòÊêDdÞwëK ¯,p? 9¾ººG(¼Â[Jïådï9Bæö»PqG®ÚÙ~üˆüYÅýžpÕÎ"«d¿G®Úy×#æG©Ü©îc\ŸÿÒ}Œ'à yàˆc´9•J¦/V›×j€o4rVO/ˆ*Ϥ÷3y7g²DÈË»çã΄>j¢çcŽ<“ÒqU]ÌÃÐ÷ñdHÇ@­f½¯>ï:ô_Å*ã›~u«–àŒ’ß°ú„©ý:·8[ûå±3u?Vcjj¿jëd½ÓðwÞ³¸öÎç‹\AwîÌïÙwM ˜Î϶˜ýFuã§Dæ±&/ý’ žO¸UA*¬%ïʽƒ „ûsªÒÛß±RL::"Ïj¿ã";³;àÓ?:ŸsfüpboýŽU©’¿ÓVc¢JFžòvÞ¿ûKv™¥œOê³ôYküc7„üè9ÏLj¼¿¹¾Óàúnà0ì‘§^„É C½mÆÁ++ü"½þØ»ÃÏ~°¦Ð·& 4ç ¿èFyÃò]]¬Ûé {ØÅ)oxPæÏÜw½×÷v…ß=áí„ù‡ðL±éX`…h-ñÎ ;®ñõùºÕ7É;.aø˜îvQ‡û}Íó>´ñÓ¿£XIx;àÍ‚sÏ´®[D^>Ö*7Öé­ 2©wNÞ£Na× ?óòyŽ((vçë÷9"»ã¹Óo3?Ó‹#äåÓÌÏTŒtô_§¿ï*L^ÿÌñš.0]è!ù«T¹ýƒ„3ù‰usƒd0³]`¹ê€#“Î­Ý •©è6Ó\t¼†ÞYaD†Œè$ /]ƒš$ݨd ’?•({Å:íµ^ÿ‘å‚‘—Ä/ØkúéU×K.¨%ħ¼”Œ6g»W\…¹¬„¼ô©³×¤ãBw>¶!¡jäÜ=mhÝ= xç)y#tWYë½E›jËÚ#¯È¹ÇæGó°P5löÑ39Á°B^¹Í“œâ]ü̽¬]o·eËÔ×ûJÚàòè‘Àè3἞ë¹1šZ˜V}F {dvÔLšÕ‚‹¥ÂÈgtîi˜ÿxõb›ÜŒ¼?§fÛ2›Núb!Ø¥èo’ë{Õ?>ó†í~€f T‹5$3)xuøA/ ˆºág3k&„¤k‡¡©¼–×2{gþë ¿€¨æXž¹Õ«Þõá¤\ÓÛ»š{ãÕ܉j€Ï¿Fê_^#Bž¨ÒrP F•V"dBB‹®´ëRu°ž‡zKí©®8™ãét¤>ïo}ËsÕNíK $òß ™×ÆUGÚx><ÐÔṂ߽þŸ@ÿ| ‰¯Â»Qè”ko÷ÂL'Áßù<’¦Z?w¯˜¢Jˆ#3¤àcÿξlJ©€-%ù8·¯-ÆTÏVž×B^S#ÇzË~¤SÇÙŽy43l|”ïúÄ–û-!ϸ*“;ñLEhïʽÒ÷X@âYeâŠßfƒŒ»=éY‰IÌÖxÓ£nÀ{Þ‡»û–:6ýÏfña’§lu\½®AOÄ#¯žêÜEìœaW°ŽõÓŒŸ Z—LJÌj1G3é™:æ¦ëÝ®R‰pâÝ~²7jnM] LõU%%B^’UçD ܪ#;Uy…{ÖFËf¿?оë…"™ŸÔÞWV«7·è墻"L5÷üµ‰M4!»E(—ÍabV#û¡Êþî³zþ‹ì*ÎÒÜ ”Y!ÌçÑ¢6ÖÃbZñ§»3ÜŠÓÔ ó2iÒÞ†sñ–rþlÿy¶±ÝÆZ– ]üò©°öŸPQw-)µÅRàí'e²š¯T‡ÈÅü£¢"øÓ¯i›Ó—EÌ?«Oø™BŽ?n:R­`»ç‘7d¦g7üØI^¬¦ÍŒwHü\+Ú¼¥z§¤6¤J„|  Ï`‘Çù-ò<Ò§ m@à.ZcÀ»©Nv ~ó?q¦#x/iè¶²®ß?Ò/‡ii»=U!‹Nah–®{ꔨuæÙ­:Ǫ“Mþïڧj輪è0ôzpésl,UíKÓáeâ.Z?, ýºŠ,`Ó ·@vsæ$³Ä«º CïIPà-ýôÒ&¦]Ðþ€G?xý*Ò›Ú¥Ðg"'X¥dZ»išÈŠWÿO’-zó?±ìúâ­—/Àì÷ eë ÙõF É-!d(R˜+|W¯ibF¦‘~ÆX¯@!Ô¢ª!/ÈÎÑñ ;Yµµc‹é 碟8ÅIapÁíè@æèÐw;º…ÝÓCÈ, ²]OÇ ã®¼[»ÐF½ý䪀Sxs»OïÚ„„Öl ,á^T=-H9× ô­L²úUw¡Ï¾ !oÉûô2ÐúÓ®÷²BÈ{2ÆÐËþÕS2KŽ©é¥w(Óo~¬–} ƒ ù„Æ[¨#™Å<ë,ˆO3~ó©é¥/÷Ùu¯$o$†þ¦ë¾uOç¶Þ¿gâP^©™Uœ ñèËvOî ãlb›e‰«$ÿà+WÿŒïŒs„<3HÓéÈ C­2)ôQ²±©fsú•p˜Ü&éµË ’µÊ¤N™P CÓÕÐì:“³ „LǬº LÄ,v‰Ÿy:´v5áYUmÅ÷Vv™Ç±‘À§®ô&®¦Tø™éçÍ1l;( ä=å¼Ã^*ºn)âþ¼£;„ú¾KDÆjÞñ§?c¯öƒ0ú}šÖ|è¥r1¦Žg*Á¥uym†ÿ¡,[M$~þãh´Ë\Œ¯O’F:oØ2– ­qÁÊNÇDÈKbåË^ն褥˜@ÈkBñ†(²[+Bæï²döñh©à‘·ܯŸðw¿²àÞÈ^Ëá÷ì&}LÀ]÷¦µP;Ö»EÈ!¿ÈÑM !¿ÈÑÅ¿óù9:¶!džX㹩yóúöš Iyû=’£joq¬÷œ^”‡ÑÌÛïïÙ†ô¦â:Äç°;Sʨ·OõA®~&_õµ,2êv”!µ·×"_‚Ð!¯¡HT¸ƒýô©â´&rDH—´˜[©¬‚hµ0!)‘Á`Ù#ãð„uF°Ï5˜7%Çßè~j^c¤"Y|ŸÙç&º²åÂ02;k¢‹Ãu¼|”£c5 ±`¶AºQWCPß›Šƒ·Hm=®KR»”ÚúŸ'‚ú±iVñU‡W!j:Xøô™ªƒ¨)±ð;“ d0\~‹DÐH¡`o”Þô}ÍëßÞÒý‹e’¥ÜÀw VYB DŒÌÞtÕ‚¾B@@÷öû<šCÑŽõ'º™!I_œ[* ë‘—ÏEv¦òú.]¡3ÚmšxwÌþR‘¹¾¢¥â³@È”Õ0÷BK6™-ÇÂÍ™ÐáìÞ4M OzÑß}ÝeÐ(º%t¸ÐgAV¼Vb ì‚¨k)!ÍšiWup*¦v{ˆ6;™a &Ý»=LHë! ¨Vy2”À! šUy=¤¼ÜvøÝ~¥« ùa/'3p¸Y„ÆŽÝÅþ7 ™žÉþ¤5ªKë:”jEÈ”~Ì™\#e±•ƒÄÈ+²ró­qF•â‚r„ÌSƒ6OeW5-d§à–ÉòC¼Ö´ž RÖ›¢k,z=òžDa0êJ‡jy½`Çe‰¡­YŸ>?µŸO„^É?óE:kŸÌ3¥s”ªèË¿ùŸD‰^=™†b„ÀÐß„žã묢+Ʋ&¯ºÆÐ,rT¼X¤õ¼ëÔ Š¡—DXÒ0˜áКŠVIÂúw¢…Ô¸]p¥tByø[¡é^†\Ë–}Öê½E…K’·äÞ‘ð ¢{è=î{ïB¥¡ YWÕî†>Ô¦ ªFE÷CŸÁ4Bõ¯ÕËJ¨~jö“ô¾]„íí>±¤¿× Z7ÖÿÍþ®ÓkÒÏT²Á«%Ë‚_/±Ud[ù SóH¿4z Ð"¤um¥Ã¸½é›¯ìúedÑ9É«yá79ºÌ_¯g.ýÔ½¤¦Ï‚¡ì˜ÉF§®ÄwÚ“­£%þµœ86i¹´åÖ¬‡7ð@P»a,TÊ¢8@Ÿ‰Kºàsµ}¥t‡èç³ T½³Û—úiW0»vËþ¥šôÇ· þ½®Ô-23ÏÉÿ-{J:nÚÉöè°–MÐn¿]޹¿žMC‡nØŒLËDî·gYte±!/j‚:Éír˜¥6n¦¶—¥Þ&eàÜ.'j9[¤<  ¸p¤˜d]•sÔè=2Qyoj—r®·µ]Œ|à¢Âÿ »’-Gu,øK™Ø{ùö]çÔû1H @€Ätúë[ã•.Ngצ6‘ÂÆ Ý!n„Wä©v2€ÖL~»(Ý4ž¼f¾Ñ9W+™a ZÖz¡Ç†°£ß¾Q¯Å„4¦CNÕ| ä=Ù¤ƒžq¯”*É)ÆíûÈTb3ÿ8gk¦|-»Q"döÉÕZžñê·ßüF“În~»ÿæ7štv=òCg7õõHäßê×Ôáå |*òÛãÊàïœMËÝéÔSšØ Š¥ÙÒ+¼æ-ò9‚Ô¢~ ÛÕO<òžN#‡)_bRºà«?°[´ZN9¿ ód*•yÛEXÉDr?cÀã;¦>8¨¦>8£·HZê'!3Œìšte튷D° ²ˆÄЩcið–ÿPÆs%…qm÷¦†–Ì-ÇýoÃËnÑ¥âÑ Ø#ÃÏÍcÔÇ 7ïBIiç}*ºI?H‡ÂWÆ’8óƒ:*«ÎY‡´ÆŸÝõ£\øÐéÄvÛÖâïîÂBÛdªtŒ©! ¾ü7Ò¥ ;ý¬³!áìJ'Á¡qá[¥PD?¢™EYÆ $­ïè<‰•Í'BÞÞ'—›ˆÙ˜ª!ÏäÚTl*ÆÛS ÖÁ®|-õ}P’Jý€ÎÀ(Îo©³ô[g™GæÏed×±![gêM)­X£œ‡Ñ•Ò“løkgL–n¢û!02Oxk~–ð<»‘W}¬'<2|»˜Ár ÇSgSG×|ÂL”OÑmÇ.«÷4 œÔŠ+ôvô ¢ÃÈk‘Æ ™ÔõD¥‚ UêJiżëŸþ™ºòØé¹LáýHfÖƒ÷¹¯ÑL­u¸²² Ïï£f&¸4{dŽJ~6CÜä¶SºKHø˜TyKPs,‘abS¢Ç ýžÁIÐÆÊ«éî‘!_ɤšz4“j5Wr Üpç¿Ôý Š´Œ„^ q¦® &#óÕ˜èõHˆA^ÈÐW§†i£ŠÒ‰ã›‹nNÌFÁr`r(<„å1÷*Òé¨iX[ }¼órZÒ’¾ß=04õðüˆ™è\JåGB ?.—¡Ÿç9U•”øWýŽÖ]´ T†…qô{_aè+z]‹q[Wý8LC]ÑÍÛÇšŠ}§1Ò'ß,Wt³ö±¶Sks›fY˜)9á;`ŠnzQ½õ5@VŸd7­“Îí.«ÞBÉÉô6U +Ù66]îkv( 5¯²ë»uå ÂL}\ [Ö}­¡%œšƒhZmEïí`’Þ~ªFƒò‹1¬@av4hlT)/È샨—Wä' ¯­Ž!éãþ›…—~ ¡Ëö¸#! “Ø†áÆ–¨]Nq›~ ÙûP»áÛs÷Cÿ¦!³O}Ã:vy‹Ÿ>§)ÿ äçáÛ’åGñC¹ÏIºÈ£×oé oÔó³<ÐiääŸåZË¢pÃ[óXˆéoòjtÆ<µº•c[“aÙÇ¢(Ø‚å©pƒëV#Žjc€üþ€©2‹¿{ë»lm[ë¼±*'‰n,ÿóŽ21óÀKÊŒL$°cáEßOÅU¾Íé„l2Ö¬IÝ®}%ŒÌÒ®iõà(Ÿà=ºJ'4a'ç‹™¶ç5ÙÒî£ÿþÇŽ®³/²,:9 ¾úëSÏ´=ÓDdáCÏ”#ä‡a{J£lYž_dõ*æß¸A¬µàäò<vò²žADæžÉNà5cHjD©ìf[Ã\›³oýMÏXÕOÝ>î5 x~¿”¸ çÄìµ+¯yÉD¤€ç÷k‰›ºVŒ)›³þ8â7º¿0ù»4ÊŽÅüŽâÚy5ú±R®¦ƒ"dÇ Êæ-Y*&-yâÒcõÆóX†¹mw©Ãk>“¹ oχiã»ôB `÷‘ádªÀVöwþ M¹/O†…‰]° 4eBúÑ\ŸÈÄ(4KÚP¾g¨Wå¾KÎ0ôç’Ü^ËtøÊú¾íÇ}ÁÐûǹE˜£ÏSå k1º–ƒ0Œ‚ÄÛŸc¤þ\¥Bž5×YF|EÒ)~_¥ñ:·[SémyÆkz À_ë×èû¥¾ºœê:{AâÂQ6ÙÄbå>OÔV†€§Î-GÙ ãyW/.ÇBp”?y³œ»Œ„Õ¼xóAl½’ɉjæ>çͧÛ(ß=Î=Ù&.AµØ#³w1;qSÍ«ÀȧeÞ ‹¯rT(JÝøL§Ò$ö­¸ ï:íBñXF‚Žhž¨v„i#‡lT}´’žÐ|Ì_oD Нrc•UÜð^?YõØçsVÇQ)…‘w¤ÅaCÖEnæ³êT!qò¡ñdv£wzìúÝ«2*¾TÐÍøT^³%i3Éî(°BLçáÄ«y4IòOˆFD_M‹èNî ¸›âq—ßÄ2p¹+ ¥.à}¹éËå‰ ¸£iPêT õ»IDyTPN\À¯'”QI¯7ÑãÏ™Îdù4Ôš]çð9¯Ž¡S7Og=«¦eóÄ/Ü+ù{Šß*×m˜x|7¿ð¨.A8<9çÍXâÏ™§¾Ñ®e¾;›1²HµM¬ dWσΓ¶ŽãÏùŒõÆèù‚5‘#þœ/Œt¾Ñ%_ˆVÄwþ+”ãCnÅŒ¸ÞêõýƪŠ^1zÝÈ2JŠ¡YÂñæ[¿ÕS9‰Qaè퓦yÍ€BVd¿jš'ÕI¤ªóƒ¦y¤%ª:?jš'ÏS†È{o4Ô3"o¿ÓPÇønŸi¨­¥¡â5o阛;e]2;o°3XÑ'³æü°É¬Ž02K>gÝ‚âÕ¶Sw‡4™}#~o#oñš÷OÄoÂáDLüÒÍ‘›wzÄUµèíNîÔ‡üN@Ön„ÌRÚ0K_–|«· ò•ÂÚªe$)3!úë³3X¤:z|££±“ý²<úëäo:wn¦"Œ‘„@H³;N)Ò}ë7Iç¨e?M;¾ºÙŽ?ÞÛ|^Æ’—ùü (trðŠÏ£š’c#Q;Ïlè²-;©LøQM颞f´rRÛ¼ø¤`«‘HÁ6/þŸ‚m|æÿŸ‚m|BŠäÝLÕt:wpý+Å·ãyÕ<¥ «¸œÛpv !³ôLj‚¶5Y‰…‘èÖØ]®&Ô #™Òó2#ä=µ%n ë<Õ2KÄÚ"®þ—¦Îù·RK¨ itºz ºz*Îß/Ä7p€ÉšpŠWÒ)üÖ .蔪¯yÇB×ñ7Â*yã^è}Ošôšjš.k&êüµ·Æ{Ùô­~—$B©³NThRJ((8/ôv\Õydã<¿~ë¼.JÁÙ‘(^ýä¬ÞÆŒâùõIwÞyƒ-Ð[z~ÿî¨Ëž•Lg1­y£B–9Žv!OûwEõs¹ ³¾h±7ŸxÚ›§Îÿî&=?ê½­éÚwlâ³$J'TýN0t*K«žàËÆ¹eà ¥³Do+øÕ¸žÉPëHŽÒãç-Q¼²¿‘WÿYKÑ”óÖl!ÅU׫ϭ;¡Ì5¼~ÒQ5J$!³wU½3¨½U¥ÂkÞ>±Åúäù¼*EÆ\Nszj'ªO?©:’Hzæ×¼«c¡W¶Oû$!þNµœüÜ"‡Q(úm ×îåpÈnVª»!‘¯¤+VЏŽñø.òŽøZž-60qPÔfóÄÓþí¿UÔGVF9®ÙƾöZÀ…»É”8áê¯wÞ˜<›; ›çë£Jæ`U2/kÆNvÃÿÍð'¹,¡©–èCýóç?ɉ ÌDx«Ã¼põD*èP‡(hYcº¥2KµE\™i«šMŸ°|&éåþ{—Ê­fxÍ{Ôk 3Â.ò 4.ï²H²Oe špù »­ÓÔaÙ” ŒîüWØK02˜lZþJ߉‚[øuP1µ—U³Ï4 f$rkïÅ]J“ùÃ6Ì4µàk¯¤mƒþÜë~)5EÃi s  ˆ¨ýIBÛÖKòTQÛ%ЍAGÇ!Ü*rÄ/ÿ@sÑØH¡O ]¯¤íæ9èºMkÅ ¡_yÒ}Kzë‘ý0ñµÿ)ém9̦‚[ÿ&’·Î$V¶ñUzbÉ[Kɱ¾ö&Tb„4)•Ѻ×uòcÈë°æë3yÝ™]H„Ì~‘lôw©H¤¤>1r„Ì~bìòöÉ «™ü"‘§²Ehî34w³™¸z†Ò¤”T¨.†Qad–"™'p«¥¢aBBXïJBî=>Ù^r¹ú=ÉfMG5k6íÖµ5B>"2l8 ¯™¤kÄL¶;f{9¬Õé±QøSŽâ+{£eûÍöÙ1 uùœÏw¨U8¨#_Át‹8‘Twçû£“m襩쓫³ -©f#‚Ú\Å×íâÂã¿»U0ãÛ<!³ŸD=iE=ðšPÙvkZ.«^s?çsíòž"?Ö õï0Ì+B>Òú¿S²µý)¶ÃxneŸ~’éOÂ%BþäQ%ÉÆûª l½"Ê>ýä"¡²‘û/|Nã7Áá»_‡Y¡+ëγ•:Ê Èüª†ç›¨V OJ%Bf‘»»¶Õq¨ÜwÑ#äí¢2g#,£276+\½¸¶¯=’÷=?¶ó •íâ«xSo ‚OŠ“AÕ£DÈFººv¯‘:Kò´¦@œßDuå"Ф„®ù¼pÞ’îì2¢VŽ®#™©:„ÀÈ"ÑzòõE3û£Öa\B>&à´R6ù¼PŸXðP^[ÃþvñuQA´Bî#ì`‡¨„Ì.£ÉN‚B's‡¢xÍTv­v›geþ¼\ýy§ŸRZ!Jµ¤ÅWOÜ–mÌà\¡Gª/N02OEgª§ìY OÑÈý¼~£'ö¨r®g¿‘³Ü{„|ak÷ÔqÅ׺'$• ñ’7Á¾—¼?g¸óß_(ŸsH§X¨ôª xÍT±ÐÚ©: !N‡'ù;é÷ýýãëß®j8ó­=Ë^x$ìŠfñÊžeyÀ¯™È™ü¬u:×E*é³›®~3³I”ôä U&ÊÊ´ºµ:·]U6™A½¶f^sÕô\úe®ÄŠ·ŸªÚzûæÑW¨Hä7~rllaj¶Hä7.¢ÞI!Þ¥Ôõ •±™«áœ™Nè™ HÆfu26s‹‘Ù»Œp26Ë)Uø\¥ÜtœD½ ‚Ž !޽¥VoVï_JgÉ"õaÿûOD².ºÛj[|õf^ÙWµ·–õ|P!A¸Š4ÖéÑ «‰ ë!ò »MÓx-Óyšf_ªßOàdÛ…ããÝÌš^5¾ó.“´…å kÇûNJÒWpl{èw"êQ{¯ÎvêÛ) ¿¿qGÁtS|zºH¹ôQ1½HER¼1ÈT|°VGµ³$Ò'éê†õ1«J @µ,²´þž>w=Õ^q o‰cü?1é³3(:h¶âÊÄ1:².V5W¯»áÜ2Gž–Lf¿Ñ¶èÿ²ˆS¸¿ê« Öœ;F>S6w&èg„lŠŒ—»ôºv,«… zÓ= 9Æ»qm cJõ|¬@å*c¼÷u•ØYÚCOÖzÂÐ,±÷q³–ªS²]W½¥ºå=ûD¯ˆŽñ>·õ7ë9V-£¼.Œ.·±ý˜$$¾Y† Ÿ@ŽlÕH¨Ø(ìY†â6¯;á®Þö\lãŠOŒôtSìd7"dB“Ãæê¢jIÐ wþ ìÐÃj‹æ:p=* µ=%iÔ>z1nzœ³˜1f0jGH0sojoFV‡6@ojw UêˆsÞ§ &Ví µE”0Z ê§—éAÛ­ŠŠžšÇ!@¾ã‡Nç Áþ-@¢$´r;5t:›iu>ÑÔ€—8޾Z:[ïÕÂœÑÆÿXí(©þbB¢£ÌEzK¿,{EÚ¸ñã‚Be'4mh¤Ú¥$ ©êT° °-ëR\§ÔñÛÇðñ¿v¬|“tQ†½.I¼zb~ì¶soÒl¶ý'ã×¼ý`°`Y‰"*Y½#‘¬D‘(Yý`°DY‰"*Yý`ÿ¶ðhÿVd92)±ln¤ËqT`îU¤22ˆ@llSõ£TÅÿ™ÙˆÜŸ§ñm]02û¬ï'ØÂBÆ&&Ç÷yšzUke/¼åÚ_³óâõÔ¡Ax™o_oó/!,bS5µ@-RÁ™¿þÀõöû¤ª ä/ŠÛÕ”ÝDEÉÄ)h!(Á¦rG£ÚÕ(a©àŒŸq;©~;FýÊñ ®ŽÍ½*'äÊì”àÈNý $Bþbi OÝgÑámSásÞ."n–Ît!¨ÒÖ<Ú×9ˆÆ7ˆy_–ª®‡`$SÜîoòA@6`FQóÀkÞâ¼õŽC9¯úXVð¾ßîȦ¢r5 kh×nÆ kìò‘þš®ì²1¡Ð#¤·{bFõÇ×n[OpÓRY„Ú­A¶>v}&ðÎg¤6¹Óø£”e{”ßó… s­3Áí'z6<Þ¥Çoïûÿ»’$Ym(x¥îš –Þ»#ì#0JH ˆø§·Æ'=Šj‡Ã»ü4PHzSfVœAZ›ÈÈx_nú‹kW²ÃNedÎl¼÷…ÂÎp=–/x鯎éü‚A˜‘ ©ǬXê¢ä] eÁ+°!¶×÷kLµ+–ðá/*á[¹zuðy3§Bdãl+{‘¤ªŒýBÞ#}30¤jºÊyãàkvÐ\ z³k× Š-„Ì™™ä ciK9×üׇLÖfR@´ã=µ7Å4åuÂdßçí úFSLaL1e(ÉnߨôP6nzØ5ô„&z–`íMûË"v(·Ý.‡sâ"ûNÎrßË]® „äÒPììÎ@ç½mËVpŒ¼%½Úú‘`V´œõpjߎ‹cnZ®‰(ZÅg¿~°Î:4¦¿Qvä}uè3~“ûì†Ud iÓ©JµQËX‰DÈÏ *†ºØÈØGMº£¹óޑ״9ã}=7ìö8îÞvRÌ•ìù°®Ý†iIT£uüU÷»äyýXn[wŒ¼},·½â©Dnl¦õ]GÉ›Žª©˜ñ5©M2 ã‘ÃÐï5”˜o‰ÕúY zÈ™ŸXÝLÆõ`\ó½­âFïDI!»Œ_H†-ŽÊ çñS¡úNØTôÄ"ݘ1Ö¥”sA7ŒL­ë}ÿ‡Ùù¢çø¯ÃiXÔžÂÖ‰n×ùÔ´N=B>`x¸Îlg •‰*ð³gGûklú „å‘Ðu=OoÇ”Îä_ù<ï£rÎË?;b6¶K멞ÄLDË14æ¼ø…í7ëU¤s”v§22ÊÊF×Î3úÖ´£yI ^ýÐü"T%6‘’‘ùñÅ ;`äYÉ  q{~(ïëYf÷_wzºÃuv?( 7áî»™Á©äË{óK̬ã;6_ö¤'ƒ4ÃwãÒÂJJ%_N¥¨ Ÿˆ%gƒœú`€ŸªÏX3öÚÉÙýþY]»[ËBÄ'zü¶KÏÁ5³_÷ïâˆü´ëLRb¤£‰xJ ÉÚH˜ìÉî9*òº‚¬=å,™f§ žè‰”°ãÞàÈ4t€|"2ïu¸ö÷¿¥‘1r7B™ 2¹{ZŒ>™¢aþ*{|}˜nþ©‡8èó3°Xõã®sUn„²ùíêhül ­zú"´d…,²ÏA6¶¥^6Vn†Ëµ ä%¶K¼ ®iµïkÉwºäõ 0EZï ùÒï²Ò/U!d$@˜ÕѹÕÑ]³:”ÙœòÒÃLs¶ÇjYÂÈgvä”;Ψ-[ïŒÍbléìÀ)¯¼î¾k7.U"dl ‡²iMJ±—¤yOc+x~‰r+ ¢œrß”wI‚^Åk=è(}†})rÊO×;‡áú,%JŸ¸Ã*NˆÒçîÐ&K‰ÒÈÀ]V ¸g²÷2\¶áÛ.ÕòŠ£ ÃÎP6þl Ü÷HÎRó?fš­®=ýYŸ‡»Òj|¢ì(|çìHtºÒiÞW¨E=Žö‘AÚ‹Î ÕOOY‹—cø:…±¢HÞ”É#ëÎÖNŒ¥²œÅÈKè<òC^3”K¥e‘ÔüNx*¨ˆ¾sY¤ëžP£¤`GägjTlS%tÝ3j”Ü(¾æíý„eæ„Ý%²ìûwopXÍ"¦·&M°Ö—•+Ä ó »ßwúNGpÌÒdPT÷³ž:ן 뇽’<²Qó.È>AÝ(%þ?.™þB‚X–="Ÿ!º0C#dc[°;Ï"%Nÿ˜9µ Ÿq6´ÑÛÍŠ‘×RÖ²¥ñwÏ~Ò.h$¶fYv ¥%õlJ_ÍëVG–ëQ3ùe›·¥BÈ òpSZzWPíÖÎ B^Ïœ¢ªmöd–Ü bã¥wyµAv˜å‡¶;ãl YU˦y„|¤RÁÔM·èÝ[ÿD{³"d– ž‘ Ÿ(ö¶ëÈËl.3×{ä´!äåS´¦O!¯¢µwäíS´&ÅÈ{ÒÄó”U®ë°Ê)¬âüëmÇU •~ÙJ¬Ïò/¤üt„îÌ5…*Ä™"_B¼!sÔrq2|æÝÈŽ‘Ïé• ²¤åx@zÿz/#à‰ü¼ ÝK ²aèwõÖhÚ,“Ë îÇŒ+Y¬]2¨åù!ë4UäÄÔŒ¼m4FõÓºotà0þ•稛QT´ ¶ìõ6òB® !oç1›Nާ¸“p]Â9ô6ý8K EÈ,[s¥–^4™­(Bì¦í5ë¾W|ÞàD~>"½õ•TõD‰éU¬m»(@?I­ N(µXŨÏ|QwÒy¡VOêîû¦Q­ãw÷ˆôVåôgý$<Õß1³g-†^ÃèQ]…x]EmˆD0Uâ¡·êÒ6kóÒóá±` ©m\Í]7¡ÏI }œ‘í„jy/aBñ™ýB¶3ú)°å%¤@”o©Ói¾·EÝòTÉDÇç/"¨ï3?!±Ù·ïK±Pšy¾+Ï-Þ‹b®^Ô‡YyB tª •Hj¥$z½X2™áõ.¤©ØÞ%œüë «t›ÙXKùZg¶ê}™†”Ò#oHiÄ)Î[ʼnM!P¼§N¾u®%5ØÄ=òKð­7Vé«}}•íXÈ™q;Áºž³¹ÂO”'ÅPâÂëZu¥*¸Øyäó³ îÏþýë,þ"wxvÜw¤Äqoôï® YÊSBäÉÔþÛ5¯‰@±—â´z,Õ#=yJˆ<€u”#N N¼…Jï<±­7ŦÒ6î[û-õÃ0C¼ÏÛ»¹§OÑ…JSôü Ë8Rt½ÕŒ·O)º<"ïRt)aÀÀ#!)kkIhe]Çn\rx¢,uh}m¦î–¶ä¡4“½%ŠG%JxóÿQ¢ä Bž(Q²ƒež0ý>(Qr„J*òò~|®Ñ-çeAÈë rpÈ#o‰z¼g(õœ#s(‚çѼÛ+ƒ á«éKsz+„|¼#÷VeYNrù_Ž´Ô[ÁÓaèêqªGüì©¡Qê8Ù^»Ø*†Ÿè•!Hh,VloKmWXrë ­)‰„Õ‘òâëý5 bE¾<á›ýüíôCZÏ@>0P”'öÙ§ë]2|Í%9)Œ¼}\ïìpŸ^µÆ¦I ñ¼#³ÞÉt¸Ï;ƒ ‡kfŸíÈãû¼üÖfæ»%¹üûz¨8´¾`OÃ]ÊÀ©Î¿o½5;Œª‘&ñÓ™oßçíPÚÕåµVÈzòšª~yÏ¡Š„©RâkÞRón;³`Êg†åHá<úÆ­A«¾ê[³X§¢†¶ù~dvÁ‘é×IFÇÏž%A¿6uÓ ãÖ-™£»^E_,å,Z…Ïwù }Ÿã^Í0P”ß±úÓ13|ßo>,wºH-2"q›¤¬BInçt¯²l9B^Žª»öš;ÙŠ~WyM†ºýðä‹êeÙX¹ ä-Ðò1˜‚2I@fÉîmFø?þ=µÅkad„s3åC:!zÿ–hѬC«’u”Å!:óÕ¹rƒmt¢@^õ"ò–6ãÝa¼ïÃ4ˆiçð-å‡ñ‚0º)8—¬i§‰ db“bú)6bZ¦qQ3 !Á޼h@oMM:½8á-¥>p¦ØÑøñÆûìýßR¢geÔÊ+pš‘æmI¯òúa g§0NŸ#žÈœÍ@f»MŸ:»fÉS®ÓßVOÕ—Wõ5)Ÿ— ž(!†X:k5ecªs5ǘ!%†üü¤ƒz·Ù6¶Q¸ÏÛÛÀ0¡`Ú®7œ#/ØÇÓ.9>‘P3|jZ…ÕÑ.E3P²­‡hžžPÇoI­Çøæh„¯ôzŸWIFE§& ³ƒòjëº9f$²&Š—TZß[/®]×Τ nGäq0mÂiÊ ã•=òq:H¬?% o‡¡+÷…tŽÆæ±…':£bYF5åxg¸bïC]ø”oÐýâE@f‡Á޶ƒ„ͯn‡ÈêŠÇ ìð«ÄÍ’Nkýªá>óÃ^Fý¬ßçhèmy £*ÞïÓìÉÆï“oàÆë‘×JŒ1öN¨–¦[6>NîÅ ×A­@ÈOJŒ”ÕP5º¦š·%Îr¯E2ªú oþö…D§¬·›îÕYéV«:h|䉃é_NèÍë<»köЙóHP[¨¼Ž®»&¥†{ ¸k‘]øë´V´ÆyиO¡ïS`äãÓ³O4èç)áâô‰‚®½G^><Ñ®Ÿˆ ä5}¢xŸ|U+DÔ·ïߟ}¯+„v>þ*}Í _Ó Þ£¨RGVuÁhåä‘BrpßÞw•ùíú‰•yBâ8ñ馛ZB^ÏOJ9Œä·ÿQ}Šë(õyý15À#t/šMÿøæãnóçoí\(TÙ•cpûÈ#•`û1Úmˆ*{ÓÌQíF9B^‚ž‘½OW¢’êÿŠ#¯© S }iÚ-ônó8ø~¤²š²»Ðožýù)w¥‘3BžüF¢ëûÑx©s„¼žSœfF{¨ƒ¥þ©^éÀùÝ×R“ÖæýÑå¼ë©8× b剪µ¿nBÏǸÌÇ‹<ñO=à“r0ü§MízŒÏ\¶Í¦òtì!E@2„¼8rî—A»(Èüæ’)¿ëɉ#ì®jl˜òûõ Ú]{ƒ6[g ¬öŽ«Ä&Óo¼#igVéŒÝû¯Îv»lz› ®9y4Ñsc°‡0i$àÉñš×è—ÜúIí}׋¯$ÛÈÇ{Ö ìºíTrFÈKR ®Ê¡ŸHoÊ‹„SûŽ}äMfÚ0&¾/eæòûaRÄú—Xú¶b«ôZyI]fÃT Ô¹¶÷”<¡/7zÎø®xÏ8ô;z@D:ÿƒb°höñ'´ö‹±Õ»F^?iNéÌ Öæó÷j!höå =àt€/î´ =àt€ïˆ¼~à‹ÕÂGŒNª…=™`=¾°†î±¦ ƒÅy$'¼íмfÿ„k^>#uä›ìŸÈ/U¿w¢§ .󄜔«Ý×ijÓá/CÈË|1 #£¿LÓz?ïžê¼eÿú-Œ³§×û«QÍDð5ïOû»K6Mû¹öãŠú†õô}ݲ P=x$§¶ò.DŽD,vJ¦j_j„¼|é¦P|Üßh}NÖÄ ”Ër 3}<~¯±ÄºMB8s†Ûc~ôHI>ÿ`DzUÑ«)-8 =ÅKŠOJÇKEŸ¦CD­÷m¼/eŸboS[CûRt_:ÕQU;Ô³Û±r0Þ…žiB98=eÀ$7O(ç«ú2Yö®ÿØ…ŒíId•¥²'ÇÈJo 0’'CÿÞqÝOm±X¦B„`ê/óÇ#½þº(èX¬¥@ÈKR-ôR&CQòLž=Q§t*®fmVûJô  Œy2Κ¼6º0_Ýk˜† ßç=­/uvÁ›A·iU¬P Ô`¯Éëöù´ŠÇïó™e`ç©‚.-[ KüeþxrlD¶ËÈ(FšÎYeú\ÓZèL» 3~Ÿ~ÜÊ)fûìLPZr¦/\aèw¨o™ÔI²ºWL±ØAòÐ ‚Ú¢×9<]W½hÂãXJ_Uõêz ½Vzû­u¾$7. ü¾¡g]Ô$(ŠýM›`ΠÔZɼÇR¦HÍ‚ûo€f©X¼wç(¤QY+¿Õw~Õñ˾ Ï9šOæ_¿åüi>™$ÞóI”óGß CŸ@_Wóƒº+ÿ[ŸÉBgú‡¿~ywãt]É¥WƤ£ÆÈË{ô \ôÐC]&ÇyšÉ´9ÿÜLŒÍìð×#Y³ñ#B–ôLJ5øš÷@&.A­Ää~læí _óqpîqž^õ.»Ö^Jæx§!2 4Ä<’9NÉ… Ãæ‘ÌqðøaY6T-ø¯ß>Âö"yþ['%„åÑaÈREÝIO‚ÏM[I¨^%‘Ýb$YãotOòsÓ™k<åŘ&ey=›†\æÔz …÷iH)%7/"S‚öòjŠ1¦â³g¸~Е/âlAž¿Q²°Z¼Tyù¤ìÎÅK äÇÞƒ1½CÈÛ¹²ûÈ+ ™gŽÉpÖHÛõ±Œ‘öÌEæÒИ

²#;iÄŽ—8†Žoã»,ÛÚ× ¿&–öÐX$äϯϤüEŸŠÃŒ‘§¤üQ‹øæŸ_HL'ª\‹ra„ÌQ=ß*ྈñ"ÓZ¶{$Hòç÷1[h”¨qm:¨s¥NHÖð¢öš’ršŒ˜mMœ‚5†Ö¦õ@ÉºÕ BÞ@« ÊÙFÝ\°±n „¼Ç.Eèöéx½æ]㛿àêU$ÔºžSÌžï{]ë‰ÔkQs½ŽÃ·ô¼;ˆnTؾ%>êk/ÿv%É’«HðJïå¬åßw™uA#4‚쟾B™Ê²ªE-¼¤H„»#ä%©¶Ï¾¶^pýk02™ÍˆÌ!Ë GçÓJkÎðBÞƒ{bY’ÐÏ?äzG’%|qÙíÃŽn³œ¡:Ý¿¹ýå:Ÿ—yæöGÕ¼cdüŽÌ.ãbÁfégZÔ#ÜýƒŒ‘?9¦º ‚G¯•!‡ˆÙžáÑI‡XyM놎z«Gž-t˜|÷Û‘jãæõë 'ÇïT†:¸¾Õ«~GtȄ͚oÓ×PšewÂv¯”ÊàåO 0Þ·êÚÙÛùeMüÁjÑC–;é?ø•æ2º¾²×9)Ÿæ»8"/NdçC¯F†¢"0;(gI¼u•rT{“¢Ž†e”CçböƒeE¢vðpÐÎÓœÚÁ{ÔÎ’þx{’zÈÝPµy×Õñî¿G¾ MUˆñÐæl3Ì|„¼¼wÚ1N –ðÅydJ‘/#¢´Öu·Óþ¹épÍ{t}k¼;„QéŸe[Õùˆ‘@ÎÛôwÄ»NM€¼ ~ó¹¬[Ç |¤‘•‘%ýñIƒí¦ƒ«¼R%B^cŽjޱ¼üߪöjRYì?ð7Œ, è&Ï¢aЩ -2=²Ä0ÈzÃÙsV;JÖµRt€¼"«†„ÈjÍW’çñMÆuØÂ nZF餓)Åù€W´{{ÂRU_óçX–vl®ib°…/ŒõyæmHÏóï„Ä×|„Š­är=Oó@»²áª®Òåüر§ÔcÄ(•x”\צëÀð3u¥?áfæ¡—È#³ØËÞP'ÌòRçñåh[aäp±Ç•ÀwëX.z;/öèø3j=e)ÝÁäj`å/j4+“‚aºŸèS!LKóœ3„ÄlwûÁ›‡§£œ%Fž¶uÐy‡Wä–EײjÃJÓ²Ú‹ay9µ6í•@Èëƒxöçß n$B~3¸Ùò›Á ¾û7ƒ|÷o7 !¿Ü`ä7ƒü;?ܰƒÁGfކe¬1Àð¹Õ@;ˆžèuhv«½Çú"ô£ëg;B&jŽ•oÓÖ ç6ÍK¾®yý\„nUS·ÏEhÂT¦˜ž…Æ´Æß}3Üd°DÉ"Ù’™®I&t6Eaä³Ä?/µ—¸b]— Îòò™æ2+9‡ãè,!F€­CêóR†¦Ñ,!FC]·Ôê ‰èõ‹—yI·X_´Ó1ˆœ—‚†„qPéž±Jw–>«tÃWü{ù®Ò euLÉæißb©×ÄFf ‰Á-ôeP ‘CÅi¾†ÒIö{{k'wÌGÓD¶³‹³„Äe8×|mÊpRŽq”îïe8GÇ1e8Ã/’yù¬h¨É9GȤ¹€xʱÙæF¿õ€|`’ KRÙµ• Šî™¸w„Ã*û•Ì¥„°26òtm œý>ÿBRŒ£ôú I¾â¿X É9Žçë;IÚO²h-ôú›{ý³ßìhÕäG~áõԾ¥mïÿ±ÐÚ™ÔRÚ¬»¤¢+Øå÷“Õ³³›¥æ#CÈ䨳v!UœØuü—ckƒ/ˆè,›ÊEÿ !/Á@ÛDNTŘy™  š¥f GRH?´úæð;¯îNáîQó'Kšîm[‡“š2ï±^kl[1¾æÛÉÔ=] 5Ís@ÞPS‰+-ÍÅDÊ|²Ëí¨;&ƒ’5SÞOB¢»©² }÷÷C ’øyÓö2ŠÂ·yyS=wˆöîÝœ÷ñ‰zÉÑ‚¦kù˜&œ‰ÇÂÁ‚FÒÈH8¦‘ [Ðx$j˜uEeÌGKÑ8ïODÏuÛ<ûšOúcjâ5\_Úsûû¢ärÐËØ€±Õ®¶¥|K²Ñk]¢à”%4|Z»»+"y_UŽ÷ÄŒ=„þfý$;¨Ègi#ÿ§i0ò,AšgB¾%H¶Ìa$‰¯›òjÏçzÞÇQÍ4áxäý$•©Ô%‰XÞR©Á¤R !?'HÔ®¡y’ ÑfÞãù)AR¥Þà’é’Xž%']ÞÝž–C¾Áí³ƒå¯ÝbmO`µQ>­­@È´£¦ âÛÉ—j(ð5¯ØKÊ÷`|íKÈ8/Ù±zá‘Õd~ñΦ!ï)ûÚCÎ.Ï—akò‘¾ÊÖ¾t¦Ï7žoB>ÑÉ!ÓHy„ž«ìŠýÖÒî,sÐ¥×äð;SVÈ?>Tõ‹‘Ô› BŸ]ßøàÁd[ìÝ.Ú‘#ä,’¬ œÊžkÓ Áòöáµ¹UµæøwÞ?½vJ¿vz­òñ‘m7øëå­Fî5%8Ù =¤q¼lTÞ`äã|âó!Ÿç%?Ilj/õï„:ÇõžLÒqâGý;FúâÞAËD -“ìúø‹¶„‹×Ç©–‰@Z&ùE˪ù×Ç_´L$Fžk™@ß“G~Q,8<Ñ3t~¹3/SΤÐ Uãåp«½o+Z©Š!dÊlóï¹õ]|™ž8‰.à Ö"ë¹–m÷™ç›·ap*]IÉD±á»ß± bKRš­#£è¥)šÙàZt=“:(”d‰EëçðtvÑ)dÇÊ.Ž|,ÙÁx:Ö”Ï-3‡·‹o»®@{bmv$µNí€4Jnßõ(éo‰ „¼~`˾&cI!á½Æ°öÏŸã)2Ä¢Äõ(Ó¨^n$"¦kvd0Ù¢aPU‡pŠSø)²|ʜ닖 !¯ ß‘œ´²¾;—¥@ÈÄÄ© ¥Ù}ͽĿóž"Å™#10Èö!æBýi“Ý~Oü£×²V+ãm¼æåÄ?º;øGg·Ë‰4;øGg·´÷?Ë«óÅ(£ÑðÞÏÄòÈÁÕÁŠÍ–H! éKØrv q5ÈQ¬r1‰¾»þMÉÎóÑuª dè?Èno»Ôyè^ï1d…5äv4‚Ók·­‰˜îV4 Ã×¼"‘@›LuENŠ žGÞ¢ï¨+ÿZƘ¾fUlyO Ú¾3ɰ¢Í•øî‰&jà¼vÅÚœ5“G>á<2/Ûe‘:C­òøÆúƉmë›¶4œ „LR¹`.7¨mk†aSxœÎ:û‰Oê$ôFë3SËòœÖâoÙ ŸÍà^°èíulËMö]$|w²„PyÔx½ ¿o"!4ˆ„ôrl@'»_NšD”ád±I$»_Ï‘s.ÙùÁãÁ´ü”dƒ¶üàñ0h #ùí{7øx2¤à )!?‚\ƒë>×qÕ>Ì+|©çÐ'@ st?x'ÔV›ÐúÄÌj–BB]5!*bu]æÕuá?Ò¬­hÓmÖç+Ú÷×9rãÛxDÂIF¾¨æœ¯éÉ\yMIiHÅBÖà=ã‘· eÇÓ‡\•µˆÁâý•H{¥õt#5Okj„|¤Zê­ä” ‡qƒ†Ž„¨ª{nµ1Õ½‘/*4f‰7Òf$ÝÌñ®-tè¥#›éÜCÈ„jíæÒ &èhqZÅ‚·äDкØ.zbì k‚wD#pe]ýv¶ Ó#B>‚ä‹)…¹B‡þH—uÙš#Ÿ‰ä‹oÃ캵'#ápÏ¢H~"ÓJ½º+ŸòÝf#döÑ'Q/µzã oÈãSÑÌÕèó¹ëf Úd_„ŒgÛÕ>KV®ýù™Ò˜·¬¯ Èóø=œq‚êÄE͇·»ßÎ:?/Tÿ׉Aù“KžK#ާ¡Ë—Îe:?v„¼¢' y5ê' +Ããzréi’+„€)ñÓû$ò#o9›æ#¯GZç&iÖN dê^ÐøÐ_VãÍf ñÜ¢(gÒ »8<Ñ#6-ï}÷¢é—µ•ùLZe#rÍ €ç+ùâœ]s˪¹ß¸~$ŒÌÒB± @M¡¸(„Pp†ôˆ GÛM“Ü~6'û[/Ú CƒPsîqôØO¬X¹\w…¡—“Oiæ ¸˜=°jVª\:Ó…®;T,S6ë?ÿu–fÆ?Yd³ZËÜ—`õ¥MÁËM—ƒMŽSÿhšM”Фò8´ÁàÓ¦ÙF8Ž}Ûƒ¼_´~IêB1|ÍÔ;Á‹tÓ5¯ä>î㈷¤¥#èoèMSïsœá»ßcÎéãßvÒ{X#r@>•ÑÚÔm]¢€pññŒ‹­EÒš¸÷Þü‹4…ÀOôŠÆi õÓ9uÕ0 ŽåOôŠºÖ|s÷Yÿ‘Œ ãaä"”:n´^ëÛy—ÅÎñýziP0VĵécÂ÷7¯¨L«S¹þš¶E¯ö„ùM¬ßÃfÃ:ÖÍuɛø} ÅϘ¨š=N¥JfLTͯ㉰wž¸\r#jò¤H¤¶³…/Û‘¶›WUnÛ'?v…1¥–³,}Mv!Š!¯ØÜŽ“Ò»ÝÈe· ä-|vEðÔZ­j“ûŠïž¬£•'»[ãŒuTAb6{þœ¹ª Ù«‘|kó±CH—üÇB‰?7Ïe7÷ ’%„ïý_@Ú7'êIpÌΞ)Õ$¥Õi¤Y7èCxþ~¢Õ9gC©§³_%BžÐêòB¬;¾æSØ©õ]šÈÈEì {þžÓêÑÅw¿ÇåÖ82Ø’éÒ­z1iI…±Yº—Þµ‰ŒÐEöL$fÿ¤Ò­zŽÚÁÐ/ñï|¥‘µ7»Õ1x?×ñÐÉ!3ˆ—Ë`õ»ÈBGb}y’ùè¿SгÊ\ëuCß]Y/%“…„8ÃC/_^=þ&_Üõ—·~š'ïµ M¶26"ä )5>”¼ËÅÄ¥Ç#§ÌàHQíý¸‹q,Ýìyy÷®°­%Æ»B”‘0ç‘Ø»Â®÷Ù쥎 „¼'ŽæÖÆ5¤å¾5”8Ÿ ùò#áy:”ìó‚«1PC<ò‰û„¬°¬k®h3¶ùŠE±àò cæjTtŒoóåàÒD¼ðã$zR )øaä‚qŸ9÷Õú¥k'ÂÚÀÆ Ðß´g£ñóYçS­hW½¾eŸ¾¹XÖR–é|^ÅC:™â¡ I¶q@Èd>kæ³J½1–øšé|‚H>Úùy˜O;Nv>wQŽùˆc_»BýÞÑ^æó(BÆžáºr¬[sн”[^ßUŒ_} ^$úáú·rGf‰‡y l«VŽíø‰Ì|º=Ù·írϯP²C»ö3‰[?=èå¢öç픦JM³Nl2x¤UêÊç ƒÊ÷¡.»¸Š?.”$P³9¹œc1zK‚çXp¡ÌÅNx\gÑ[Rç`†tÜøÖP’š>é>áK}÷&ăÃ\íLoh#¾{$’4•'`²¼clÏAŒÃ#_œáÙŸs”y"ÆajX8¦Î–®¹Ämô¦>Ñ÷F x¼P¢ô†›G¢G]jŽØ· Šë 'ÿ_Û=Z:Ó[«ÈÛðĉÿ¢I¦ÿFú,õ—û°u©Àd~üüü¼ëzøcvÆ’Vù€¼œmHŒ|Í„—ÞøÊÀ›±Y'榀<ݺ@¿6 O·®ygùÀÆî6Xlh>·ÓR7ù¦Í_»Ò¾F®û¸¯þ3ÈKê“ã‚ڙ̹˜ÑN™zzS3ïj","™v4Ùú"1Ô×M Á|e= ï‰ÚQSûÐʸAtªä[oµW³È² Zòy‰!K…;œºÕšòŠÉhYôâÝ0ï×c+D Á͸”"ßw„¼%f«:ïÚŒê|i´Óòš6MDžQ¿w-<û÷ÕF¯;ëàÒ£T5¯t•<ûýX2m™Æ6ê¿Ú29® ܯ:EâÍÛ4QûÙ4=ZtCÓ„F>Þ ¡®pGKÅKUµ Üý‰P÷¹Ûã$%†.ïh‰—D$HÖ¹Žu’!$tÙÒ‘«•-Ý6(Øä-Ñà°ÉŒÑ-(§Ý¼ yÇý“®p•3®h5ó¿~­Aº¢AæC¥âòB‰Ga¿w×¹ªç“®K¼û ¢Ö•O¥¦Õè¾,A; !ñprbÛjrÊÆ"„VyOÍ >(•ëÔ‹ٌ㶠Œ„(¨]$s@±É1?Üý’m{è®I‹¦–ÿveÉŽêJpK<ö:¢ßÄ($F1)îêŸÆ’ Ÿÿ °AH5eæ‚ ­÷ùÊ¥g-­yÇJ‰PxÏu™¸qv*šª Bpçi£çä×vÖÃ\-B>}´fž’Ó\ê!ˆ?ÓŸ`î\¹œ³ÊÔ6b[Åñ“ºñÞ¯m›¦Þû*ë14ñ=ÃŽ¶þaã¤Rý½YJ MýNÀ1PK¿wzðS“ÃHéÔž&ÑÑ‘ö²š2í#¼ {¡¾œ¯øš`¸ÅÌÕÖЬ\3à;ª…&[HRÒwùT¯@²3uz4°ìÓË›ÕCc¸é=ÏÙ ‡ã86£ûw¨-z`6œˆÿì£ò®ð<¯ÈÄà@öQ'Ò™ž}¤Ê)0ò À wK½£’µ¨–Ò„ôv° /uÉ É«‘8³DL#•G—ÔÈiØêS,ÀgìIÍÝÛl$êyŽ9CÈkèay*õ¸Ð®cb- BÞbÉ6ÛÃê¶ŠðqáˆOCò¯7§r:[dX½N+B>>“>T(ÒJxJ÷ãð‘VE5#E“ŠÓgþQØê=©ì0‰M×Ug„<(<ÔWxØ%§ùQæUìšébúübz?ÉÙKÜz$×’ìIùÈ-· þûëÐ?Õͩ„¨Ìo“òºò=Sc+<“"…N›¤õÖW¥žoVx†µæöŒñ|…»§ï·›Á º´C|‰ 1þ¾I¿÷!M¸¨1`Ë E×¹ó¢“ yýkó4®"þçÁ<9ó4†_ÌÓ8¾æåT†˜ÀÎ?Ê’!dÜ,roV“÷Ó¤CeŠ—èë Nd^D®ò}8â/ïàV[ƒÎmW•YW­™¢ðÛ½÷uáõV;B^NS ÂïËó,õ˜ôy¥—£Î’ü×Á\óõ]ò‚@="¸ý1ϳðÖ¹Šª% ïýkÿ3Ôp»®õNTøO`_ waØü÷‚Œ%7¯Iå‘—˜i¾ Q®u>ýàßÑ59îunÜmÌÛ,c™ \2ÅïÝÒë¤zï[ží‰ÊA•/1©[¯-›òì^=ѪUÆ)2ë3²˜s{ˆ´ÌÛ‘ó­]W„ „¬ÂOµ+$e*5)B>â‰~{ÆÑJ% ›·ùŒBÝ ãÂKõ<³­¯2š‘ ¬Z²^dÕñÉÿx™7 kèѤÏò™WhÆÉ•!}èg¿NR=ß ×Ã$UîIÉÖlZ›C/0·\9ÒIÓ¯u_÷ÃØ-zEó£• •E=WûŒ—Irûl]Òײdð[óYF3ÙòÉòÊ›Yy¤64]^=-áµËd&Ã~=×cëFß9öÈ3MÅj޾¦ * }(òú[1#¿B^Ndô¹\¡Ør½D¨+£Ò£‘·‚² !O÷¥ïžz¤Y#»ž†-³3«å¤‚Ú~àYxG·7ó:/áêʰpÍû/eXH'¯w¤ðæÞ¦Ž1öLå}jË…ÿþ8HK{ûÉÊIn¢ +äuʱ)8åHà=êa$…}ìuØÃ«ÚFÖÆ.R¨»ûkÞ~ÎûÁdšv ±ú-9•Ñ»–чߘsf>)*à0-¢*)$ž·ô›Þ¬ùÈ Ðr@ƒ%²Ú”û¶ƒÓ32ôÈÚó…Ì«–ÔB¦A´£ð»Ø,+ôNŠ_:³1›é_š˜„²ÌíØgÍ]ïVß½¤kC „¼ÅY;}Ⲥòðîñì‹-^iÁ}¡’ø6oQŸÕ÷9–½«÷¡Ÿ9þOÿvêa†ÄòEó ò!¹BVÙRuÙáÉÿœ;óBÈQqp9VÓ¢‚p AÛ튚á¸þ^uëTøM$"-Bý½©² ÃÚ Õß«ÚöÛŠ½X Z„êrl„J½m°«/il[|÷¨þ^9…‹e^[¸@ïáv;©¿Oõ¸.*øî¨þî4æµëjA×|¼WêeÞ–ÝÕßo·÷ú»Ó§ï–¾ïÙ2#äë$´¦P ½ÝÑ'—ç^ÎR}*—%”ò6‘̽ÌÚŒªS2ìvFÎ’Ö})§>Uè÷¼ßx'òò.»©Ç%èÖo~Üž'²›zbÊäÚaägÙMÊ{>ÃÁy ‹¢ñ÷RÅÿ’„¼z©÷Á+pÙC•7"¼Í&ÄYý‚Z×¶]9gù %!³)š‚Ü¢’Š‚‰ã5¡$dËŸlmÖ"Ú¢ÑÅCI(׬M¾Íêò8Y’pÊägNVè=D^™öyšSÛÍ+ÐíùÁ­’zý.ÂõäGF—V9ÂKObJÙAèo´í¹T‡$-&-þýwâgÚUZòÉ'÷cæ™fâÓX ÚÕ!£ÿnÇL‚JX>“¼GÈË)r‚’ÐýŠ<ÔÞ2yû„ jÅw¿Ÿ"'†ïþ8EJ†ïþŒÞ;øoRRÏýVbäëÙà»»ÁŸÐÿ%›ÒüOËTVÞ]œ5c9.Ý,ðýdnT¬ê¾k€bå ¬b•÷Z±!ÓÏŠS®yù¬8õášÀÈÒ7 MeKÕY\•;BšFÚß¿†»å}|×–víD‹'’h{¿x#r…¼£¦þ*¬'P“Šh˜Æd=Ï×¼|B~¼æ‡ÿNÛFÿ÷½ÿw»94#]x>”!ïÑ'5ûa£?÷ÇÖêµÂ¥œÔN[tÐ8é¢`ìNÖJC–r?ÔÌVy1£M0ЃñIJÔëÜy¨®ÞŸÈ6Äx º! ]‡U;)¾û5L×U\µOd”~\#²sý`1‘ª«w,º„ 1¨6ÄØ26rxÏù>¨K†wôúná­H<ò³u5³½y?WÖ†#æ+~TÖ†°!6¨}WÖ–ù clPëP¼m7•{F¡ú8ôÆrXK¬ S×u GÈô¨`Û€ÅêÈø5(Ø6`ñÑãk^?ñý§NöÝ_1b!þqEæàf#Í„h‹!ïkÌU„$§ËÖפ(ëÒZ"¹6î ’Bn±M™ ì›'6×{]ÈZ"ä+„ ^C@½#õ†òbÅw·Í_¿)ÛIC½}—ÕåÕˆøŸùŒs«Ålf'Õ.&¤ô2_S‘eE÷mc;´c‡Z×g¶Õ°bo»akgH:W4(#;…Ôú‚y ö¥g§çíRÏ«€æØ«Xå¹Ûi5M%ð|*Z„¼mªÊÉ`kdËvÑI„¼–ÜV,#Ùˆ b•y×ójÙW EÈgŒ´ESÜ© ý Í_7H9¯01ñ¸è§P‰¥¹¬÷]E 5†b»ÓªXUnX1Ρ=öˆ" ÓM*|v®€^&þ©É%Éwí¤Iˆ]‡ÄpÕÛ›ç°÷§y5 …ýÇíMN? žM0¯ò¸ÈéOb¢û¼É _óúI$‰Åî\ y?•Sb±;—G¦ïÅU-h™8(äãÈC ^8rȘï /¸ôTÈgÔJ3eÝP–AÅôü‡çùJêÂ~é¥ZJ ±ÕlÆ×Œ¦¤tˆaMFõ%M!C}<ÏdŸtáN‚\¹B¾Žm/ŸñkË>çįæ˜âõﯫLØðªhwž±V äA3ÛºÇI¦žûÀ2„¼øš“B±~õšF?Œ¼zñ!’ƒÎ—Zæ`†Rä3LV›XÝ&¨&l™äªÖHŸ#¤ WÕÆœn,Q}HeAvõàîøð4´F?SDÈ\NV?ƒ%ÖÞîw²î™¤BFn‘µŸÑZÔâìYщ§ô+«i©¶û}™I‹‘xBíõ fÊæA¥¨¾"õŒ[Òÿœ¦%uš–#ek>"d*R¥P{=]j¹B>hxf¦ÇÈéÛnŽÔBÔœBŽø¼ Ry4 <ÈjEWøõ‰{Ÿ&×!CU¦€Íܵ¢ 1aï}fxŒf†#ž^Ž“ÀÏc~3)&…BÞ~™! Ïó~*\ǬpßiŸCñß§S”|¯fgÒóy JVeiK»º\¼0:Ì™~áqÀ}熔¿p¬'퀚ö¦]9éáìx%G½YGÔ±Ð%'0LõzŸGµß{¯vź•mW!dÑç|Ûw[¿ç²øWzJ03̽¾L„*¨oóu=«”Ô «ˆAæ´$ðßogƒd³P‰mÃï¼Iª.T·þ¬TB“"öµ{ˆÛuEªÞÇuo¦7³ÂNEš‰PÊ9É`§}ŪѶEbÏ8S5TÁÅHW5Äãa¹î r‘ŠýDß²›ÚP`PyR§n-G ëóõF€Œžü’Ë’`ä%v3u%„];¾ò êµwÉ]“ºI.^/¬ÕV„LƒD¨–í×±/C?´öE,'ØUާ¶~£0ÒózzñSâõTú&ZòsæÇl)ÇÔ;¤*dr&:¤+¦º`Ê=2=GN’UÒ#?ùÙwm;Èm? /§‹'<+dÔ³ã‹N5ºW7Ÿ¶ NØäçŠwóÜmj.u™‡Žéyõ]òöKõ „üT}§ÅTˆP}ObͧêûäkÕy^}‡A‡üTÀ˜¬KhÏ3(¢Kĸ„2ÑØªž?·ƒy*Aâ¬Ýáš±¢a¦ˆe¬wš3†q¬XzÑ>¹mT½¦!/§Œ0œü<®À>fÐ#=RmM›GÆ„ñ;ÒcWE/¼Íˆò¨¶Ì’³i¶S ™äf²Z äÔ¤ Î12M­Žþd%ü÷ˆñåÍHIpÂöÈ3ÆÇ°Iƒ%Iä…âÛëæ9*F6á¥a=ò ¯Üäµ™*—,<<¥ÑS[í©X[öK’ zòA~²÷Æ£pÍë©ñhoGw„üb< ë3¹¢–½¶Z‡·yÇJa¶½BjAT ÒÀ’Üß÷%»ê´º¤”ákÞ¢ñ7²«×§9>BÞÏb°†O’äqÚHqí@>k¹„üÖrÁ×üÖrÁ×üÖr™òKË¥oò[Ë~çë·–‹@Èo-|Ío-|Ío-—!¿µ\BÞ1ÝÃvYGB¨h7¿æÓŸ#¸ô9BÍ{Ú5Ó†T:uµF™ QqؽӟƒBgí4ÓÔ¦Dö}îýpos‚þþ‘'³3g Ñà¨s®ÓÝ`Ò÷$—!ïAÈêP-Q•‘k^B>NÆ¿`Ù+dr”£rÌ)­wÃĺ4pÍôtœ^ç°;Ì $‹l¦: jÕ;À—žîós¯¾wA(GÈô}Ñ–¯´ž`ø<‰É&ÿý±¶ÑVâj\G&Õ¯…·y;¬Ú¹-ô<¼l&‰‘i<¡S–ДëÇ¢µ3£­iµ»»Ü(ˆš{ä5´† Çý\s¶°z~nÑ=þkESWÔ ©+! JïxLÝÔ­)±íÓŒ6ºÐ\Å¢p-¬~%«7XuÈ«_Kú¹á½YŒÕ Nk ùøôÅyjŠvFÈÆËÊå†ËX’®]ùo3b :bˆá*f²Ï349ÿç v-1C˜!‰­ÿX/Wƒœ—¦ÙwVÈë]p§rn lšY1Ãåë@E·o–„ A¾y¶h¹´´¥¤¬—†5™òŽÊ +´´ E=3_1K.rX²Ej]ï"KŠí˜Í›~›ršUL'ì%°níªó“RŒ*éÆ_ó÷1J·'·5ËUÂW#äýÝxTåeRû_B$p òÆa$÷]-@^®$Û6„|¾Œê˜¶ÒZ§3B¾>kH}wrÅ®}ˆÉ«"Uý ¹\ßD弇—ΞÁÃK!–¯Uá¹ê>ræòÈôŒ¬æ­’Ë!‹<8sÉ#òzFÖ›BÖ­¹º78^uÍÒ“ê ±+™i×%9ªW´®ei¤Z» ªócÆÈXX $Øê^eû d»—7Ù¬]Ï×iy‹eVÁsªÎò<›1ò‹mº/®_ëyî‡ßý$‹­7Û¼g¤›ò!k7f³Ì–ªEÈW¨fû†¹ìUP½‰zäøÉÿœ% t¯óñ5I˜£%òø–$y‡)6EsI‚K8U’ &Ö„Ïøñ5I!E ¦h†ºH6ŠA±)ÚŸ¨ø[¼˜ˆ„þyD<ÝzZ¦6Ï8B¦'­»yž)F¢§ÑêhTvBXÏ(„k—ס b´•µn–ÚjÙCÈG¼ƒÙÑZìÖ±îñSzF:£®É§‘õ gHf®w4\ª‘Ž©¨„¬.ñ“ÿ9íÝQ}ÆÂ|ì¯g Wñ/üÐçIìog †°-^Ÿ'±¿ž)hUìÛwd¸…c¦bTå<òŠÜD=eJ}H­áw«mvH-í¶§Óž³),»`5ðO÷F,RŸ=! 9Ó!× ºM;o ºvû9ÄÔ¹ÒeYØ®R9„Lcò%u±jWÌ[F<¥Ò!/Ø9ÃvÏH]ù ‹þrý£F •dak¸%gqeÛ¨¸r ÷ÜÒߦÉý²»]ΧÉ×^ÐŽ„ü6MÎòÛ4ùŽß¦É9B~›&Çwÿ6MŽïþmšßýÛ49F~›&Çwÿ:MŽÿÒ§iòþ0Mî¡imb°áÜîß7±PB¸ÝÙÄ €q»ÿ²‰Q|MdÌÛ¸F_£î}†-ôà3—Ûã£6JÑêæ"™"?'7ý¼U¬&ObNnX‚.·A¨4[‰êyâ|%W§NÄfÉ÷¼ÄÈØ¬Ý!WÓÖÛ¼Aês ±²n"å™÷²ÒÉqßU%ò’?•9çj=’F—!ÏÕ9O[üggÄmü=ÉaÖù ÉqYûä˜ï*ëæÊ#Ÿ‡íΗ͆µ¦yg5öK לtt ‘zLIJ†·n…´¼Ûš¯#¯a®×“‘h¥Ò]¾M¾ûíÅH‹ŠD£$¢l}¦ÁS¶¬È+hŸ°Œ×Ùbä3÷&òZi÷(qÒÔûq¬ÙP¾ÿ„ëá86ÈÝOü;äõ=“4qa@ÿKîÉë ™$7í¦޹Èåç‡Ô6‘€ šÄ.wâÑžïoVM"r×1h™ Zbïº#7@·Á'¯y9åP†¯y=EjjÇ&ÙC#ÆÞT¦d³vpÍëW•)Úª»Ç¬ýƒ\œ•õúä ù‹£gôÞuôùÁѳ·ŽžaP"æÃ|lÃ>±\p‹` ·‚?²\¢V0ÝB^Þu: 3dVòëdP¢?ŽT¦Çy©xü|ÿÞ’DüOßû4ÀÎðHN¾÷É~Å@!Nãð½;ä|¸ûÕòØajóä÷¬©^@ö8ŽãYó6ãHö®#Gv\ ^©Kå—o?˜9å(‘e(CüÓÚ$Sehô* W™."ØT®3¼É©ŒLZÅ329Íïç7Úìf¥µ*áé~9›aΰÎÓ¿~{q¿f\ï_dük¦¥ÍwÂÆÜûý8†W°Ý®`pÌã u=}Ì‚‹YÈ#³wkÝîÖ:¾Tüï^aË)êmÜŠÝ#䯔«"CÈë»wÞ­Š;FÞ`ø·€F´$zo/WXïO<ÖZ@{YÇýb/ûxqßükµ7Â1G#Ç/ºà<ç0ÒKÂoâdÞµ+£y [î)$ÕÈŽ!¤wðMÛàæìRŸ*›‰K‹Õ YŠŽ¨9Ù[¾ÀSJÆím>\§Ž½MØPA½ò×ï&cu{²Èu­ñ1Ïá)á;šÛNö ÷ŽŸç&J•¸8noµâðóìõ1gŒ¼¥NíNÅÔƒD¹¬ OÈÛ;ª ŠIQì±¶˜ŒÛc§v‡œÈD'ôàí%ìdê9B&9‚¡xÔNÖ›`ZXÇq{çf"@±Hi–%|ö[¥žŒÒ ëB‡­#¨ydéXmf_ÊY Õ½Gâ˜÷¯­šùº•Ϊj#ÇÏÓ9æyqßP]å@øáÉ;®Úþשâ»^ÇAkÝŽ¾¥Ó—s߬Gh¶%dƒƒhoaD{ÇOÔA‹öš}[1Ø·ÕMÅÙé  F`—;¸½%äåÃ(9;Œ’ŸR²ÁûQrçRÑq‡O]wÞIEWdd:ü@žy›ì@—ÿ¦®;oD¥Á»9 /ŸD¥7q@^ƒoØQTš70(œ¸î8Ba`S–r¦¬è–-´··cE½r¢+S15:Õ¯ÚP¸J©H Ö8Ïs÷ø†<~ÑgìB~Ñ|\à˜OÔæt,o—›št®Yƒ€þ)¡:¼:Mud:Ÿž§oŽCÍ.`ˆ*qžyë8üe|ï8dc–#/¯ß‘°´„™ÄcfˆÒM¬:¤19™Œ¼›ÂMí=ÓhÍsÈwŸËÊwy󀉿3TnߟCûjQ/•ÛÜ@–øÞ˜¼Çýšþì„R& ×O(N׬R„AN•‘'Öjp+¨«4®Ûšm Eåçí¨Z[…©JT•Ý<±²óüq”ÓUÒ]¿ !QÕ!G>>LÍ> äù­ºN Ÿ×ºÌ›\"ä5!þù˜Z¯!„2ýZã;º½÷-FÄ€HÉxEbb@BÉxC ˜6r9¥”Œ¿açô û޳™ÀðÜó¥näïÝŒ…é©ì[„Ìн۞ ½÷¾£¢DÈó+r1ȶ¢ñ Á–8îÆìŒiBNU>#ä5Ôvã Ñ‚QD`ys+­¥2z𵕠n*½:"äÜ­%­­ªc’’S‰Ïþxƒ,5rË) ¶>цû¯Uón¬Fx»’reR8ø:½ð7†öÍÊø,`3öPçoÖŲñd|Fh-ùÔm C³wž“ZW$Â¥—åÄ–J¿Se?%¬#¯1§S×,Ìò ýÊ:d–0gÛ¶ƒ5ÆÆ²½[@fÑ›ú¢²PŒë˜­PBº„û+©á9î¦\JмYt ÈPTžÔ^÷Mæi²Ÿ4w…6ðufã nYâô¿?““LFF4þ³Ÿd£1òÓ&±Y+Þ:6{E²ÔèÈ% Ê®3ÑY²¡H ŒQ¿Ëf@ !^„éû0Ln¯`¤$K¼|vç0,LùH×¶a ŸÝÍÿk£ÖÅ7BÍÍÆxÞ¼¾™XÜÄê Ïóü©&Vg„ü8±Ú”ñ쉘àûB‹ ÈËo…ޱ‰Tù‘'ýÒ눉.j„;º¢a ók:—³q7»äûŒÙ;áoÃí@P;KøE¯ÂßÚÈÇ\!¼É"¿èÝ1›ýˆÌ^ÇF7®œºìàÐcuêìC2È¥W=i2™`«ýHIg¬í"X‰çWöpì»5>ϸ}üõŒ÷Á+%öM_'ÛÒ¾¸bC„GÔR©Võ9B‚%¬šÚ³Áõ­“]„žy–8ôüùÇmÇ®¹nŠ7DÇÀ9¼KOlô꧇™H|òOìJåÅa/3ñ#ÏGÏ6ó&Ó} e9Ïe[A?_¯Ÿ:¶j×_ç½É¶ÛeÒ™…/bÅnj֠65¶°U`uköÈûÛ4vjx“‹ùxŸÆªabûŽO5¶¼kD¬¶md ½ýðä>’ ”~¾“a’)KŒ0î@RôÈ/$ÅY"ä’¢ÀǼ¾j—{;–›~¦E@ž65ÖåÀv=&½«>d§Ùé üí¦6­útÓK¾mðÁŸN­âÚkÛc²D²ÓkM; s&ÛIßB"gšgB’ ^úSv!¨\Ög‰¹ËÜǧôÒŠHÉÖÏ!³×P@øP ¾!—¯¡@¾ÎRRÝ»PÄQ²öAŽ ÙMÓéìSç“ð”° ï˜[ò´Ì'n;#äm%¶>øλÞ,apÌû/KX¼÷ûoKØŽï—0‰–°ÓýÃÆŽKØéþÛ†‘o–0v\ÂN÷ß–0|_–0‰ïýÃÆÓ%Ì?ùŸCŽlÚ8¼"ÚÂÎÏ ¸yl厇[g3Ü~Δön¸U…¦K–²ÀÞ ·6 >æùã ªŠÈÓסѨœ¥FBïQ÷xÌó·¡Q¦W08æåhPÑ`#ç¹à°Ü$L(Ÿ÷¸dF?qÞÖD¿Ë!³4G±“Ê #Êþ|̤a_yí ýÁ|® •e·ƒõx c"ûÀE©BË'ËnGÇOJý`¯F¶}¯02Qu(M˜NmQ¤˜uLÛá³_Iü†’ ÃÜ`dÂÔ«|~œÉ(8) ªÍâÈê;G£`YÌâÈê›Á,¥ŽÈÇ'‡šF>“|×0t^ÈŠ ñ:ï‡ï( ™Á½ò€¡L–½<¹HYèÝè4IU³Ã* Å-cITW•óGkÃÙ¢E^ÒuÆ×y…V_^ù©ÍU¬Ó@y×.yûÈíN_–ar@äL Ù"´‚Õ&aaÖ’ñ>1FF°ydÏòõž‹’‰ÆYj¯GD·|*&ÈùÎ8°‹ãÌA”ØáqæÇƒ`­;§C?oÆb¸vNjïÆÀÆÈ#1ËÆ%œÖ”*/àì|°t±÷îx„n\çå;BF}§"ŒÄ™Í˜Îõ¾âc&%ÃÚYÙ½oaÌÎ#/iqÑkšÉ¾‘Ry…âbA½—e'ô—,Ê>èçxä ÆÉÁÜÍ„ƒòŸÜúŒ*¼[?—B--Ùc˜~N,]þûãí1§èE~ >æ3:ª)V1Nl[û±bøÉÿ¤P?†ª¡ëXŒ ÅPW´ûk}Z_þ®˜qý‰Æ9±tqPê“NVål˜øP =cy[[..ÆUïuK ךáVŽíIÚMiZõÅʹ™}d¨ÂŒ|–òúÞ0TUÙq„ÌBhi|l¸ªƒêuPkß§ÄjËÑy)½†Òu7Òókií»dOɃi‰]~=9b&¤Ÿ› éæ‘—ÄùÒ«¿•C%‡BÔƒDÈkê‘éÜ4r–ú…ª„¼!#%?ù®6ý)É _g‚ó9§i‰}Ûg¾#ddÁ™B‹ ÔwTЭž‡!ŸàGàŸìW'G¡³Bñ“ÿAÎ~®Ã>Wdi×Ê ç닯›Òë†ôl\â‚w=ºHyË¥±èh.tÌ„‘I6G½³àyÎVv癄U ?ÖÎù$#ø˜×Ô·õÅ£œõ|+‰·à¸•…'Å®|X>fô±iŸ“7h{‘ë;‚GôŒ.gÍ,w6CÉ2%tún_«Z}Ñj‘йý ­ýá²êH+ö³Hè´¡¥é¯û—É$ÆrÛ÷ !¯Éô ïp[¯’}²,e?¾zþç4¸÷Ç/¶´’!äù"aå‹¢—fvÆ®;žg7äZr ,áõÙ0МÞ+5ã¶è#”%¼>#¼— ´Út¬DÈó'’BÀ˜0ß DŽhv9}Hîèô]`ØzYd¾H‹ÍÙ£ÅB–ðú\Ñ֪ͯ9®úS’E¼Î¤&ó¦ÃÍ ã^ß¡Ãm,jöØáÎ.gäÓèʵԻ-éã‚¥Jv¹É;Þ¸)šIçÇ1¹\¿ù4š”îèv¨•¶ÝZ·¥Y‡¶$ä²7’±jZû!?4 ”iÀ1_š“i0„Ì>j£°^žßµÑA8*»<¿­6âoôü꾨bX}}oüÞ´Á}ÖùH‹“¨M0ÖNgþ³„Þõ:ó/­CȃÊ0Jioáw¿fèÛtüXW]T|5“°pÌäMÞíÜOU’‘…¯‰V°ÐBS¼×·5òòzL@n«Ž 0òM“µ3%žmˆMÖ„‹þ‡ÎX{ çÉB¾m²Ò¹r MÖÈE:6YWÛd%Ћ¶L/MÖQÔýBª!¯‰»2µÙœìeSÙõv˜ìMqkÞÅtêú½‰gÔ³”a„ªÊFz¤SfJ²ëã Ši©‚~YG=癊bzþ²>ïâ“?ÊN[ ½wA[J |öK<{~Þj¶èh5ìÚ׃ð^Y™ª—$±qØFLXÁœt¿Ð÷ÞN¤í{„<'©9m}¡Eéh~ì¶!/¡qKBmѼɴÓ_(¥yM˜Pµ“e7¶ÎE¡3D|G·0—W!þ\TW-õ^— !ïaªÃÓµÕ¨H+eMðu>o²›â*ÈЃ«žG>¤–0ÈB)E üä€wjµ¬ý_ϵ$4$£ÿÙPµ0'§–ü̈́ÒÀeÍn©Ù«Q: •6MtÞéñ˜çz¹úTNnèßnH e·ì3e·oz¤Lű£,’|ÇTJè, Dnçg·Hã µ#dö‰ƒ›ÛåKpÔòa–ºByûZ7ìæTpy?ÀSºbU¢d`Ö¨àòعMì†p´0íyþÔ’eDÞ¾¶$i¬X¦Ä!¬šµµ•êˆüØ’ìc¨z»}kIªhј%†?oÔ¹ÓÉ‚ÛýE1¬ ÆÁõ,+2„E$5ç‰r&Fún^Ûv_—ø†<°úœK#mÉÐbÎeüݸÙVØ2£–QÉ̇ŒIUÀZ¦™yÙç<Ÿõ®„×ú ˜ú޲zªBÞ`TÙÎ5ø5Dê¶¿û󠜚¬‹lõb·L0Y€ìqüÙC-®ïe Ó^Ùýçø”hã»3}.d.¡fxÿ9>¥Öj,R¯aRÆ:äý=¥¶ÃN3ÈŸŽyM­[k;QI‘oüpÌ[Z]„ëlõ!cè}®º\õÙ+jUÔò×ä:(CÊvö¥œ+„L+¾$Êi&*[¤ðäÍ–°a_Wi`‚­+ëË R æWÚ÷0uäÔ—å´®“#Ÿª3ÎÕ³ ÷ÙÐõôt”òÉ ³}ÕËw`—¹ ÚÝþHëÊ9ìs÷ó‹±}ë­ñ¾“²X2å¡y+ŸIò¹”²ÓûEB˜4ú£cþ Š—(AmŽdgQE!©¤;B^C¡¾°ó~ö|ßGÈÛçòíûQˆ¬ôÅj3H5Ï}µÃu&Z0×ìê#›•äP剶/ÛvY¶ÆvLfR:`u–Ôöå_Ðdr-<Φ¥á7º¡fŠ 0¨SÇaµØÄ1}dÖm:d2•#ÿ”ªr麡à°àÜoI€ñ¯[À[ç@MŒô_mÁ{ÜüÙ½¥ˆ>»~—&½8äó‘^ltâ“üb£¯óñ‹d÷ÇwfÃǼ it÷å:ܶØ8¾òí"pMô"ÖV:™‚ë|üÙ3¡^¹Ìj¤¤„|æ[9¹k;‹]ý™v BfiõÂ*lÇ—VNåm祎,›$F^Þå3Ìæ33>û5TâŒÌ~|Û’. LŠ$¬­—̇™Ì‡ã{¿§Û±+“›í˜29×!Ox|ä Ê,²öyÈç!³„‡æ]_ʽu!60x–(/ÃD¹™£ª‹mê;„„§„®s¼¯ê !¡Ášµý0¨½Y2ÑZZ{ƒ±~ºø.¿i”˜aPÙ§VøtDž?´ÂsF^ "S–Þ„¹Ü‡v(õ:¯óŠLƒ½Üú¤?9A é‘0ƧÑUd*YîÍ<‚µDö¸åÁ])Ì0*GÊs5NyÆöIîMî(YJ‘ïé9[¤Š’µ/ ñIìi‚,§÷«-å|Ÿ |G7$uän“ñmè¥yäqìÝw´ê祣ÀQ"ä#ayàÁf|Õ }õâ ¿»¡*ñ»n6‡XÏ^ŸžÑaéYΊ?ù5Kƒ™äqc°»Z ѯ> NFBe€Ú5D_©ŽAÈ¢3ÔýpÔh5j–z'¡)E;«¥!ð<¿[¢ÆñÁ„PùæÅ›¢•Î9!T{æ¦o- ‹>ÿœ^.ßVJ R ¶ãóÏé }B=éWçÆJå:ÆÁÇ ϼl½cF3«ºÎ£±‡G^¢IŒ5ޥނ'–f.àì/¼_àb†‚·²²g™…¥>wŽ?Ú7• V£çl¢i~N7^ÛN¤[Š}éZ„̒שqUžAp£¤­3 ²®]GtKÕ,|gB^àeªÂPuÍÇ’èT!ÕyE¯­Y¤"%é °ôȘQ„³MzXÈÎ~‰JKæC®C_nìõ;/˹o2yž^³«U©¶]/$!χ'ßÀ“‡JœGE´¨üŽÔšÂ¦N¸YÁÒÞû«‚æ›v“daL'ûBÞBEÆk³[¾Å¬óÝØx8§ÆrÆ£´«­ùâèn*Ð0QrŽÔËŠØ•Ñ2rämóÏõ˜I¢o³Qñ¿}íÄ!´;ÿÜ íBfé@ «*ë Q21ì3 ñøµUåtÂ<³¾{Î)‡7äù)wJÙ™${MÚ57t–lc!Ï‘Æ[—nYVy=ýŸ°+MrœU‚WjÙnÿìLÄ|G@´¯Ä;ýc-(Ùꙉ˜_9²„U•™ÅØ dvŠœ‚´0‰ôÃ0ë\‡¥a¡­ó´çAí’$ôC¿Å×pͶ—¯®õyjrÁ„ô}Äu2MÀA—ˆ$¬¾ÏÞëA*2ù:†ØTcÅôνãkf¡¯7·‹í,‡v“… y+¬>óuüùÏ+\™ÃTW½è ¶ _óÖ2ÔÚtÜÊu©û _óñY_–ÉúÈåò«¾lì_#—Ë/ú²iÿ¹\~Ñ—Mû×Èå‚t[ ŸEŸŠw}aÖ]°šJ¢Ì#©Ô ‡È%ÑDBz;†<®ˆC$åzJLí œØ–J…¶^ry·er!ýÀÛ…åÛv@&dçÄ7ª©”ÁÜ‚\0Å(7a7ÕÓgÈ"ßj†×´ŽšŠWÖõÓÜI‚Mµ­ŽØY§¿Ž×Æ÷2èoxdöIQorš a×¾œ*ÿQê4ív„¼žªèpX?/7d4U_\!|ir¸æýO¯Ü2ï á“þ!¯‰Ö½^@¹SÊqT댉JIÐ÷¤~Aõø  äò¦ãé‡FI¦ïÛ2®“hÔgi69èº)9ñ9§­œò‘•oü^fºÊ½!Ç#ïÔ#.Öëýnx!ä÷±´ï­…×U!ŸA{/ô[Yežšn{ܵ/‰&Úà]ˆMihÄд‹Ë'™ŒÅ&»|ƒïãñnåã•[Y—*Ì’„MÇ¡ÿ¸—½^sª !ÝŽät±>£èr„ü¬Ïh5Iw|ÍÏúŒV“´Ã÷y?¡PöU$µSD½R:ž—±.F.Ïw± ÇÕ‘2ekÛ†ñLIš¡7Ë©Êå¢jÛÐIO’¦÷©Ã5U®cÐ>ï’ ¤\”¿ZUø×³ØeX‡>*}(—£þ» ä-º..£¿Ñ–´ä¹QÔFH—ÀØ]¤Šw:Lå€ý‘ò ª@Òdbš¤IR2©ïæ ½§êa{„¼}F«°eÏ(Va‹ïÐMî‘$D†Ú¾9÷ìKÕ1@&©¸?¦?>¤´Õ2•m7ŽFFƒòT¿ ‡qGº^ ®°J`6þmZZ2 Ú”ä`)èlˆ]}¹àúó«!cBÁ‚&“±È%4´x$‰i3æË}ÙÆÄŠ‘YœŸ¾B`~½-‚&“G&ÊìÚ¶U“çE¿âût+¨õ¨)«Ð¹8ê#t›ÌO‚tžgÉšö*=ãzYÔB~GÁ›ÊeÍx§LhÙQ‰Od“mç²µÉfy¯ù®èhX¦sTÕ´îyýÜæ7* 6$5^ô<wêÒ;|'6 L©Á[ȉ8ZÓ¼†y¯åÞ!ä5"Cê¨iF½Å²9ÇHÂU¦¡Ã5 ¼ì'¡¯ŠÙû¹|iø O]ëEÈ Y¼áUÅ«}æAY5Ø#+{ 0÷Y Y “Øj|Ÿs#`Xi¯¿{|‰däÿ0>\óĘïâGþw¯Xì"×ǯFÀ1aI÷Ç#íü¬—vœKÚÃ5¿ßv™`«§÷Ìj^;B^Ò“Ç5²]¡˜@®ßGeè*f¢êuí2‹4óЯïsì·~n%BÞ’™*P×Y/ÊFÅ5$Q€Ûí~ä“‹bÕ/’+гöÈGºËxíRý¹umÓžèû]]wØÛŠ,Hjy”GXpWcÓZó$%&[fWé{¨”ÚÊ­˜üzBLÆîj–_4  ²dŽùãHÄî‹›KUNã{¹¾‰x3ܹ»™mbFH”“àþ<Áç¹Ð7Z dÜ*ÿ@†)·¨¢ãË€YR[÷Yr>Óyªu€Ó!äíÄì^ïÆq<ç3Ó?Vûûìº]‚‰”Ó·r¨ªÅ åPyŸÝ~DâFeEã‰É÷7FJòD*Jô‘”}‡} tÀ2 Õ@6ˆ|¿í2V̄ὗ«F ³ü™ÏFëPAl“¸ê}É+`­#I6訌íH^‡Ù™2Î&[y;5…âp–ʾΨþ?À3!Ùå¼ nfãÛÌ®¿ÌG½Ççsè óÈÓ‚¹ŽZBfr'Ã:Yo@’3õPCˆ±áŸdÙ9Ò5üwù¡©AQÓÔ€¯IÞ=Œµ>u‚ÇÉnÇnUŸiУ´K5Œ0?Sžžoðåz½~.ÅXQŒ¼Æ=qÀ¸`ߌŒ>]Pð§éxËBŽñÙȨq»È‘'Œ¾ÏHø6F_ Âû쯎C:¶ÒfÈóƒ÷à+Xoó¾Ÿ$BžKôÑiFHòîégb›¶T "ì‰Ú4ŽÂ{tÝñ}Þbä_{žžŽ‚ÆzÏûvBÈûŸÀÝú²?Q,DçÜ´šªÐ&^ãÉž‰†û®wÎB›Ýäáäg™ì‰4Üß•8ŒüWXn(PN»aꄜ;z€:¦óŸç åïtÕç 6”%†^Ó¾w (‡rèv6Õxð/$ýB¸þ;ÙC»sÓ^ïŠ0Ã%A‘Ô#³dõöqȪïX}=2õz‚=Μ¢¥Ü0¤§©!Øï]#ékMNÑ÷+Ž‚f|Ÿß±WÁö’EÒ–·uÇdŠï1VM›!®ëŒ /x»‘”tjrv 癕7ã…ÕHÊQônu†GëšKU/|ÅëÁ¹ËEVî½Ëii»°%E{š*œ#–G6K³îq ³§Â0—TU/°Ã&EãœJÆ‘¯ 9NE§—`^’>#Õt@ $|ÂÝÅ6^1W¯6æ0òDô°È#z$Áû&R†]« byÜÞ«•he?Æ':Æ`!õ®¯Ù×¼ok|M’dŽê@›g¹¨Š×†‘–õŠÎ»\›¶‘¿™]¯—Ý»š~­ÅÎ:†‘×¥yŽgøÈf´3YŸN½kÕ­zñÌSG6#æ(®–é¼ñ8—GGV¯DUN«Ž€i½^ª°Zƒg'>w¼ãç¸Ç#F,¦‹Éd:œÔ|·Œ{kÖ„Ì>ê!Q}ŒŠ™£ÔùÐ{¯¸“¹Ž*õœcM.áR~¤0”%¼Ç£¬°@nŸ$á=Zg"ØaÇÖ:·àžJ¾/¿í†’‚ê6I¹®AÝ'•”ŽrØãRÏ2'ÖÀ™?A³Qè%§œòc¥ÓQÍq¥ýNº+£µ¬LUtLŽ"‰„) &˜"£eaÍzßÁ‡|ßP¥-";igÈþß_O]±uS}&ïdNC›4IÈœ†÷•Óï¨Ü»q…9ÿ}n-ÁuÀ bïñÁ5 ÷4èWtrp s¬u/í: rDR‚oe÷u©Yû4I¨÷D‚Ï'ºVšÙŒ›Ot­4³ùüú%³™Òµ<’ ⌓֛]/N%ì mçÇ{crÏ'¤Tmó6bä5þð|ìIGkz­…Qz^=i z/ò\¶#8¦‘çåM¾Òú™ðfª„˜¢XƒGFnª«K9,E¡æ_óŽœòœ‹¦qÊ›¦úðìw³!³Ç™Ò%ìïÏëÛ~TùlŒÐÛGYÂüD>h)¿s<|%s„DK!ËQ‹zÀŽD"ÒQÁ]”zÞ«Ã}Þ>)¸+{Ž»Ä÷yŒèÒ Ž»ÚÌÔÄQ"¿«[ÅsG¤Ø|´}™È+ÌOKät:õºk tÀ>ß#»ØØzd½T UF2ÎÏ–2ß‹h”CNùù¦sé³1z—aÅÖ˜y¦ŽÖÎåÕÉ£4’ï¬hÓ!$9;¡ì<ŽüãPa­ '¬žçU°† ‚“òU‡W£ô¾®IN*CSRç{þF¥…<"?T†L.U†žgTJýu"­ %Ÿ;ìùºçóØÓÀ\C5ŸV>P}èñ£”EŽÉ'Z™žw!þÌRÓ.³¹ß6'”Qt—³À×$¡‡ßv;9½.ÓíÔ긲 È˹n(ׇrÎ\YÊ9Æ 1¿á>ÉyEPé¸r•Ù×Y%Øì\:¨‡·™}ÝΑÆÁçˆüX´ï}Œ÷yû¥"(Ý”DÈìÓí¦.:Ç'º¿÷ •`ÚIýuòqŒ—|ÅÁT‚×açm‡×„’Ì]¥­áe9mS*C黾bké•&š†Ð³iÄ¿ž}èÐ+e=FÞ"ËCO›5u¾QL‡ûŒqÈÏ—(b꘶. çcV³ö}Q¼™4Ï üW$™ðØÄ/ÌÙtš14®v•å%ؘºÕI^a._ÈA¹Èð|ÇÑ.Še3B~¬2WÜ’ü¢p È3…SqP8Í.Ù[þõ Ä ×¼ýK‰U"$VùôÏL¿'5 ðÍÝÞ¾ð“ûÜäô¾³„C°y’·€ãƒøò¯Ùå~ˆ@™k„ÔÇ>NÆA‰#d´ç 3—%ïø²/ÞÑç· ÒþºE–»^ùòzrÍ—¾&Üç÷ï×Ê !¯¸sÏe+™àƒ*‡! Ÿh< GÐÅ•ú‹oõôÔ;"B&j¤žH©¯™ ÒñM ’ûœÙÌõ;‚Þ‹Gf§]ôVåë×yÞá¯çÝAïð×Ë?vxØ‘’þðÏ;|8zä.Žíi0ZÊR«£ÿ…Z½Y³w}7aäõÓA9¦ÃŽä#Ò2B¬Gf >yw1¬ƒÞfXC®w³­hé>!äõÌŠvmH»ƒ˜"RÔcÅ:„<±@Òsþ^Ÿ’zu–örÿŽb{2ž[±7PEÉ® _êçoÚƒZóÖ¼FÅ2‘@¨˜³£Z¦µó( ùû¡"d†ôÒnÖÞ6 ¸6úcÉ{ºæ!¯çȽCÈØŸâXz×ÉA¶÷!³4Çã:ÞM¼¶ë!­ð¯ßΑþudãêêK¡V6ìª[ò;ŽJ¯ÅdÎåoxKðÈïT(ÂmÆF(Bvt”!Ÿ©ÈÛ;–‰®]ÍÆ õFþ ©£8Òl)ŠrÎ14ñ°·tWfªMtÖ]Àžà¡×(x:kù¬t¸ºKŠêBΡ þÅ¥E\óuHÛéÃþ\ëɇ_éåvU;†Þ Cë¹ô}œCùáÌËúcª¹Ñk³¯uXénðÐ/fÿ×;´óÐüõ<ûç+n¹û¢lt”%º?Öõúí t‡u6VÔôªï|ž04{‡vz¸×[€æPûjh×¢X^ †Þß¡‹‡òô‘8‘í2ZVƆð0 ¯ßçP~¨^ÔÃô+0½ ²Z8^¾Z3IΊJcÐK¢|ÏÌ„PLì¬tÅPÉ×Låâ˜R/sQä3ÃP’êyúªÕ ÉΡ‡†Ü>Cmä½§FðÎ]G©÷…¡ÝÀDÇ K Ÿtéy=Ñ Ô1—ÂÈ’åÖEG^pÆ<ð%¼_í iW6œ^ÈÑ\¾ö\i!ó¡’´ l¢Œ$Òêïž9»;ñ5í}þïóÌñ§æ©êe¿oAè9#±c£Ì`£}«Ì Ï.°‘Ëi¯ó¤OY‚¼ yÏŠ»Ê…©ÒŽùZ†Lf–p>»ÔÆ'ÊþaX9:ò/—Zˆ¡ v©-¬——_§™ŽNç ‘#3-h¡˜Ì°¨·bÚòšîý¡RY­L(D ©O”wY‰¼{ýûåB2*WAEwàF/r“¾æ-JBÛo¥Š†’•E1”yOÔ|WÆÒ6FMUŸòt•]šÕPôgÈy:¤]õý_n·2ó’­T¿ÉYâk:ù#ÏørÖt[Ѫ®÷ï;ù#Sª,ƒ,ÛkÞéðö¢8¼¤(dÖ{§9[WC ^z¹‰Hîe5 ç¿Ð Ъ.ý»ßVtÎÙŒ¡N2Ǽ(§·fô—ôªÿN9~Q6òˆ§2ZÙÅSySFŽÖísÞî,¨.d‰ûV" çú=¨[<•‘ô4þ“ÔË]c¼vÅÈ+þ–™ÏDÐ|‚îy$¨fg§þ2¬—Ó$'„̰xÈc³|o%9¯Ü&ûM|TêÉ7NêÅJ„„Hº(‚„]Ó•/qu»@ÈGÚ™ìC.9™ CQ|Ÿß©©osßåÐêCY…Ÿý Ìê"dÕŒ°§Pm I"i›VË}Âûµv¥è¦yï/é§ì2˜Wv­Ñ«Ï縒=>väëñ7´½“ó~¸—˶§ü’¹Ük'Çq™ÇW¼W¬`MÁÐXœõf¿«¸:ÇÝî¶‹ÚkH 3Nú´-Òõ‘ü„¼šŽÜ{º°Ã5É»¡1·†Æ| UÃ,û:³Sž¹êjœª,»í”ýéY©±å[¿A—xŠù® ð솗)ôJf Sê¯UïÝ´Æö¹(:¯IN:Nô—<öý8ÖH–e'fÎþÙ‹øD7üDvÞ3›I§ãlÊŸX^#k: PÏR’EÖ¾/]Ê„¹ ªYäLÿïÇ T>±6ñ±[¥þéò+Ž=ÇÕVñšwÛçûìe5ÒÆóû \z4ÍØ…pvϾešÎ3ÇÈD{ ôÃ2-ÜhœòùÎMôÙÜMÇ­ã ª©OÙ߃r97½îPˆ¬¦·ør4šØà•ݾ.iXi•0ž·ßUz°’ÎnÿPAcvû‡ R¬ݰ‹_Üçlž2Ýç ÞçþOØ•%¹ª#Ñ-UÙÈv}öwÄ}K“„bÅ[}k–RÆuëû¶M™g˜W×¹T…’è+—bëpxš‰bÄr>|®ÕÊÅjv·èm+óÞj¬/ 2c¬…´>Ûj÷Y3ïçU ”×§x#ÓN$›:Q÷fäÿ&š[a^a¼2€L5èM¼­§i>²¸ˆ…ÕFt‚¶¤±*ðŽî³6tÅÝ¿ç3TJß—èî»iÈW‚¤Ö0t¸L¨ã@ÚŽÔ?Æ7º×ÍËI½­ª¿ó_¦Z{z²~A—‰Æ†-B1ÐØ…£¸š¦.@´tê$|Jq•ÕåäÎ,4Lâ —¬î½' ²·Ð׳ 92(ðgv¦0RÍx5?x¾QQONA½^;ë8?<’7ÿ»v» ýÄh£Nà o±NL1_í5áv'¼¦õ–ÃÔD3å]ÝÛ8–À?7¦ƒDôZè¡¶}N ˆwÿù{b@¬ú'Ê¢ËÄ€ùKb…È_²ï‰>Y¢«Y<üö×¥%zGµ%º`K`øiBŸYŒ¥ƒ$úJ}‰ðŒ~ÀêY^i}Î;âÁ3i ô»•ç,ê ¡iê yÏTø–÷Ì:A›d¼äÌ»4O{­ŽGüí?°F:±½ØqVãÑ𢼠ԩ^ç] Š˜¦çßä`9ÍYÕ©?ýõ1%9蚊˜¦—içc+›à4S$Ê¢ë¨4 ‘·w%¡îö´{Ò™y|e Ã!2çyº’ª î¢EªVJê#†ŠeE©ü.YêHãõjÑ.Ér²"oé|ëΨjo9#Å ¡7Ÿût¹ ŽÏfÈ„ã}3g¦FFÕHôÉÆ:Ú‚+·§ Õý÷  -Ò0½wîo+#;èš¼wŽq1šBÔöÅ¿KQ×tÅ3S+MØc<ÏÌ„`éΡvŸ¥ê@¯yOÆ»‹J›x½o' ®ZÅÚ‚[•šU¢;9š±ZòôåáDc˜²c»gÞÿwù$z¼W×^³xwª¹ú®˜%÷ó•+ ¼Ã‡CE¢Ô‚¾A4ó *¥–®b%Œy?un’FWaÄýndI9²Ðá|@‚7îo¬3¦z!¿sÉZŒ· ÷·HBêþœ\Š·9yéÓñÄièî&!uû«®8¶ûÜVŠ$¤î’ûKÊCꮸ¿í|rˆ|\±Ãë“ÖãÞÌ´{2Ó>ïÜ_ÛÖÜßsŽÜߨªºäþâàpY$qpNXÍÉ2™“UU`ã™cÒÄ~îk?ú5î™G5ÔÎ]!Kκnœòµ‘v'€i¿Ïƒ÷ *žOÈ#¯ýŠ öuS­v-¡ð|w>s µ Z»¹ë@^fIŸZÙ,ðš÷À ÔxãÛö{XUÕu.<÷TUuÙŸËŸûs‘÷ü‚ü섪ՉBPïÊ]¤J-ãÛNÜŽZ{Î:£ƒ¤óæ°Õ¯ú“¬Wï³gÛiBs1¦0Úï Q ï>P$ê/ïÊíøš &')ïß]¼®Ó¬·¨íýÔ}ß`&Ë­È;ôÁ7ë{‡ëCíê¼fñŽÜ:Ü] ƒw¹I82=©Ç]ËŽ–Á_ôH›š®‰è0iÂòùŽÜô“SìÐé\øÐŒ§à𢶟ä ÖHCA¼²x‡dµ êÒØÉAA—Šï²lyÔ÷ýnR€B¾ä&±œ›ôº¿u3nÒ ÷wvоì;?ÕndñÎêsvP’‘ÉA"'½’ü‡kÂüíÏ_˜9+@¾~!æ0€ü…Ah1îÎ}຤´ýþ…À’=ÏÛgK`¥8èýª üýIý(ðGDÎqPI!zð5CßœmÕRˆƒ>~azÀÛjøNŸ˜ôõÎô9ÓÃA>vKd8§&É‹ïJ º,Sè{¦ñWqu³Èǧ¸ºÙÖfÂ./†å½9Ðq¸ÇŒÊÓw$Üc¾þâ…C ‹,ÏT£úîÐÂË)C~ph™JrŠ$ïúÓãóüù˧gÈ_>=ì1“`;;—yW;ºn;Yð1/’:÷é® Ñófê jÖ"QÈú9Âäýt´ÅS¿<ì_…쥣_Pái°Ý…£Ÿl0DÞÞèlD:©. ¶»ŒSŒÈû/qŠàýLÃÝ,w…ºÐÉsªŽ‘Ç^âOæše³Žtgxh+qPî‰Nó_—7d=I÷soG¡nçwÏ.m+QÏÎ}¿ãЬ=È")®;—'&g‚y?„îÓOv%XŸ¿ì<Þµ­Z¿ñÐä#x:›®±[{RŽÌ»8ä3T¬-HW›:~ldÙx¯_¼ÑÃ/BóF_òÂ]dÞèy¿Vöáu‰ý4-÷Qxyõú4LeÛvá~>“Êåÿœ{¾Kþ&C×”#DÞ¼ ‡^·Îg´‰]ÇŸ7çVjyeÚg¨›–Æû??oþõÞIfÑݼ9ÌÞI¾˜ÍWÐH»_N¾wuWäýC¿wãêù“T¬ÿ˜”ç€!69òSß*”d–ýûǦ´PWµÅ«Ä±£‚=i ˆÔ³©,Ç5tP¢'µç~ï¨FqS“uñ³ úúλâµ-Åêl ÖNÁ¥9h lÔ8JŸ2¸C¢$-«!iNZ’8¼f¤T—ž…Õ³¡ùX퉒ßîTêåŸû–—;üôÇU]JÝ¥U2.ò™ôÒZ[W×ÔÎ<ûí/_]6{1ó2©ˆ:«àš­ùs™Hu¦‰T(Õç^ñé~Ñ=w¸jôhS{Ù «‹O¤B_EîéÜxÁ=Õ¹b]@jÜRªÆr ú*€KµyC\a+ß'¿·Ci¾˜Ï)qÞè„ñºn¦ oNóÓøé(©6½æÕààY|8ÍË™SˆD==h|“ ‰þtkŸoÆQUÍêÉÊð4Ÿ™SG<-lݨVÍaÈÔAÈ¥h0¶×{|î±6c*Öµw.¥ë<àj ¡½(ªƒc-Áu¨½Y&lHÇžþ“t¥™º™xÚ—^S£Óú‘Ú†Žúžë,K>?R‡Ôãèüßÿø”=Ï Ý÷JVäëSîË,ãˆ{e÷Ó–¨õ±Y˜,à våÐÝZdž•Ñ5Ô#Q¢M¾¼æìi”èûë/×ô;@”*ŽÿBõ]Ú¤žæ·0×%Šcç!ImÞ§V™ã‡Š©a™Ã•NãORg×¼¿33E©[ UpB@©Š03M´q½ÌÍ ±njô]fÄUrßÔJ9@Þa ÞÖ‡‰’‰¶'@ÀÕÍåèì ÛÇÅ—1P¢b¾xCZüëQªãýã’ÈœŸáBâ¦[2u  g² |”¨sßܰvWX9@Þ>œ ÅÒÅ7þ­ž½½ö’βª¸äy}â.Žèûñˉ/uqDY—!*9 ž”Ã:á5ÜÏç{î¡™?µU]×ò ëæ7œÁ4ÿȾKÓ¢öö­Ð(I™ò½{‚ïÇyÛ³là5 ŸksN­ƒTí¦­N€DAI[ùµ¸Õû¤vgtÄuf·¦®‰§YKò™ärú»´ïêŒÒæŸþŠì'u:².¸¬f¥Ú2…9ùûtæîdª«õ=ÅÛYÑ"o0ïÇŽ÷#åÔäxaçMÎðìi][õ¾® W³Û©—”$òá׸õÕPÕÔßä4Úv¨–QV >òçg¡Öý˜Bä-xއl5u2F>cß@·Ì-­v%FË”éWêO((¦v]¸üÏ"™† Õ6•„„Y”j˜Á;¯34[¾V8\ó–ql[7+n¼îO^2ß'A·«y›ó$Þç1¬›·ð^Nˤæà D^©ËÔš°®ðÓáNÀ^sš¥–û„D‡|¼÷0¥ …n÷ÝN…•(”h˜³~xé¼°üØ*bèpµh‡«†—y»ìr³vÇÁáÊ!ï!C3plå„/V”(“¡O2êd¬}’ýü™dG½9*kdè ¢ÛÔmLˆ¼]etˆ¼e¼KO˜™k:½fï=ôý¦†R8wÜ^¢»DÆÎyÓ¸è*)g©K°aG}{ŸmÛEÄdåCUÖ ‹jŽ•õñ ÉØÍÆÔÂü¢NÖe³Ó½ÈÛ»î£/µá÷²pw ¢¢®Åç§€Ÿ~©91Iª…‰ÞÕ{«ÏxÞww5‡ö4VÛy²Ãïù|M`.4!œPn È.\ÂzÂïù“ø=j{DêÞ%¹ŒaÝ¿.Ôs>eJmi‡°¾ß¿U ÌUØ&м+¯ËØ·GiÚÐ¥ž ìTïÅ_ôò=AØYEE^¦'ÐúÊTOàÅgÕE8M¤Ú½«»t„·îþø]G2Çûùü‹Ž$~úë/:’x—^¿8C‚Õ0ªmÞ‘p5¼§l¦ .êÞÏTC¹¨3ä¢:äí=ÿ‚eù¨økþD^ä_°,ÿÂ!/ò/X–áEð0ו=g8.õâ)Ùà‘7˜y“Ï´Á£E­O6ÓŠ™¬k:Ó&©H0EùõðÛïŸSÔ“¢~ä-ž Ví¬„¬ZµúºMQ@OÚ•tMZl,Ž÷$Éí“uãÚŒwõ0G±p‰¾PÛçÜÖA;–ÅkŠ2*Œ¿«çr0µpÆç^€\ ;'{d½ˆrè2õÂ"N£ V˜ùœ«þÈg’ôÙ6Öáæeܸïb8ä+Î I²8O±Õ=@þ$Œb^õ§ë³ —ðÎ%TØÖªŠkRwdf' _4 q¤Y»ù¦«Zl—#˜£Dºå­\\Á®\ÙB÷&õñ”·uã”깇¶Š‘PﱜZj$ã+òÊ¥N¤‹û´‡f$*Òㄳë5ó’^fªãø=­%F>êÒ -i_úŸ¬™™YÏÞ@e’¨ÜÌZ}7ˆ5ß“z3k¶ÏÁ&Å!µY ²R=Çyðt ”A2Û8dƒo¢ ô&Â-!¢(Èz/€RõÒÅ(º}ˆú´DÜäÐ…î¿qñº†·.‘D]q#Ö!ï¡}•˜ì“£TçÓ°DÅ'“ýIÝSMöQ̓Ŝ급C»!”Qß=§|''fêÜ6Ê( q÷A£†*¡-éë¹¢ñÎÃ6[ràœ!q¡%žGzc³¸$ˆ|I@Ï¿- yKî|ãlFtqM­ó]@¾`¤Gãç)ëºóÊ1©ØÄnUÛf›É¬†§X|Ü%B‰XÒ’tÜÁ˜¶Û~Šcó"/„^ *Y‹|ü†ZgØÐ„ÒINcÅh~Ä©k⥢xìò¶,AJ°WÍ^’I d€|Fqú­iG5Æ$áQŒd3ÙwVIQS€Lì©ñ;×fÁá#[Ï ÞùÄ‘¸Ä›ž÷d,+~Àÿ5Í® uµ¬k6ÿzˇéŠÍêØS6l”ð«~ß“v½ímÓžcQ²’…°ƒ&]øÆˆCt­a;U¯tö³PB¿hˆ# —Gg’Øž©}²³ËAÖŠ_•§v¶¤f,ë ¼HØd5›6có¡Ö…^ó-}é_ð’YÆm}ÑävqºÝ$Ê@¿@Ød-k¿ U‡IÞ’~;üÆ%‘Û\ÉXæ@9Biµ›Nqc]·Þ'»¢û¾×D‰…(u;ðjnùq´ ^óñù] sããÒøÛÆ9²¶ndXå߇L ·)rÍ’­m;2€33¡&¼’•“ÏwჷðÔÈ*¾Ÿyñ¸X½vkêh(D&roXJ6—Að‚R¹+ P«‘Г¨8ãîî‘Ñ/˦ёïøM =‰4Æ=£8„—“`»ˆÉžÍ\ӺЬQÙ¯¼f´]lkogˆ{ÆNÜiùÛµÙ,ÉÑËMúw Äó£ÿÒý·aIãyÜAÅÖ¬C©Î§cX‘Ÿ·¼•b™<:ƳLŒc ‘DU9ùí&ÕÂÏÐæ|Þ`‘«ò‰ï YŠŠŸÇ1þD=#ûÛ§mÁ¢–nÈhƒRÇ.®Ï~gƒ· à.¹ÃÏÞ—«lgˆ bÉÒÚ—Z 摌:­ _i˜ µ…òuàl%±TýÌ¢ªíaÒš“óRÄgtÏï§³¢í5”ó“ÀkÞ³»¤Û3ú.‰­w€,3ÅðÛ‡ž¬óûÞÏÊ[oëŒÉ0¯K ÑV>#^/Þ¤É!ŸñÎû‚¾út5ød‹á÷|Ùš9v›lÝbåâóçÎóÖÓp&užÊz4žè†ž( TÁôߊÕþ‚@†yÞ’;-’aÌðЉ,È´xmh™þž­\ª$¡¤žÊ‚sŒo:œKö¡Ù{ZäÃ#í÷$îÓ×–otÈg"h%&'»««zÃU_ð.%ï§á™"×VµmÅÚ ²™Á7¾®ë8Â;ÿ¼UKªž¥ ð¢ßß鈷5h]R­gvÕ¨€ÛÙAMàb=–ìæ§Ò_»|tÓ1‘Jåx@h‘ú ØÛßuÃÖ–Ç–nMe×–/¡e×;Ûº—úˆPã>dv&DÝMš˜“úq_ŸÓtâWð©~¿à²¨úY˜íس/ðmS\åTí]7LÖ÷ð¾}…ƒˆ·½×ß‚¨s„ƨ ³w W_'w¶áª{‹»¥­¶¾Ö·{:úí c[›æ ·Ùw-¢òÈÖ’Ô„V/5;pÍfE©¯ºuæØÌ–ö8JøÞñ4`–õ»öQ=­¶»ìS¤; s²RRR‘¯0žwÌÒ´-:”ÕD;€üIˆÑ!:ðš¨A’Ýù¯„‰æÊ@J¸ZU+ýPG "+¦šfÐÀåW]W^OÞÒo(æ´k_ƒ›²Tÿ÷®dÙqU þRØ^Þý»}?M`ˆþúÇ %qg‘¡ÉPPEeæáY/ã`GtßÏ=1£”lzõÆ{ÿºÙĸlŠ¿mkEe?ZàÇr:Ìû°ÊxoÇ^æ8P:ºwv @dá@Ñ…pj~ª^H39@žã ¼S' G šj²ëYdæ²vIÃuÑfê›ý—Èë‡ï´WêpwÏ1w·È6´ÇP“X3E€¼•ňèhgÆ ¦”XÙUXs\Ç¢™xªXJãb@16/CSä8C¶3±ûšvy)½Öc·1ûŸaɃ´(¿þ‰.Í!@˜y'¶T ¹ÝÁòä~M·B˜_s¹ÜFøF7°?õÝ˼˜] ïÒs>ŽŠ~q,Mæî›¹$ÈÓ› 3ÙÚ¬ü ç·A§"”Ó<•J.HtXu :à:frÅÔÔÔð9ÑûHÂL$É‹ø$%’¹˜s@Þ_CŽ}NrŠ®q,FœGò"4»J=›)Ñ[´T¬&q41ÒpZÒGy‚°EiÓjbC³Cè9*ƒÖ¾±„¯ÿs)š~¼‚7¬è vÙ –oÒÙнh¿ˆ_É;VX$oðH²¬?½?Ž•á®L²jA÷Ÿƒhul¯¤ëº’ݤÅ5@Þ dð 6ÈÞlsÉášw`,çÂ÷XÑ©™b ¹…³‚dƒ­'ÓÍ$C)ÜÂYéwïWÜèQW+¼æ9/JAÍåÙcóœ£èU,‰6lö<ô¿&…ð½6 ¶4ùÖWx0䪅R/ûT™Œ4"ÏÀÜ·JF»à™ï• y†ë¾Iº]ÛΤWÑ0øšâ‚lûIÌݽôLî{jåÉa+›¤Ÿž·M² "¯Å‚ì=MÒDuS›™dr¨BÚ<'¶Ä})RÏÛþ¯?ðÑfhÛÁrµÒN8 ˆ:ʹHUO«5‡×|dÁˆ˜ÛóóÜžž ­r÷#u|n°É¶B¬¹S·xVÝ:<Ío?\5Éšû&{U3Z†µeDrõ²æfŒ¶]´Øèfö$Öß BËc‡§?”\ëVmfÖ‹ôã_`YÈjÏ©îiWógþ¡.`/˜5íÍ™•uj?¹_€&–?ôpG‚5fûÆëëع»XÍÆp׳¯ÀŽ-ô"8£ÝuUT̼ÈS)©,ÍùÚ1%eê•Éöãÿû%ýù4縢-@æÔªmÃtšš¶ÝÅNR_Ë=S=1%nqíú±ï¬ðSùv[§2;‚"Ž£ƒI{j†æf¢Kµš,A‡³#žš¯4Ì«ª$I•‚{–» ȰwYçu&±”ðî—¢žGýž@7x¨¶ÝÌ'€¼f¤oQ"i‚ófVˆD¥•„¿f(¾¨¼*£чÄ}Ûj¶p‚m)¿£b2…dÍ­ }o²¶}ÃTä#OPÖÚ†CC¶¥ÅðË—“)|¦j¯æÞäj#|Ð":û ów<É­Û„ž2‡;z„ZÝjkíŽíï·Î\Á„£­Syÿ΄›ÓAïú6»ƒ^·:.rYû‘åŽé7ûÖIF8§tlÆ’À O¯ÈÅ"Å ò êᢸu_7Kƒ†HÏŒù·d©Z¶Í‚—:§ÜÐIõ•3¿Òã×wΜJ‹]¡ò3¯ù3Çò gN9s_á̱ ßpæÄ‘3ç‘ß8sð9ï¥r\xN&í›yˆ“îñó¢1çc½CëUȯ¥ö hì0{½2>¥&¡GN-œ‡DÕ‘zŽÛIÔKjÒzü²Vo(ª÷2ÜnL2šFòã§P¦òš Á·™O¤ÓíNÓ»Ã6ÇþŒµ©YWUf>`¥­¥D ëìUeÞÃã¸r‘Ñ. £Émh¥RmªÐSyqJïÇcþJ—¢!°—Å{ÍæüœYOå·uuôÈÂç¼~rÍ~×Çõû»çRª¸D±|w¦‹jÛ}}÷yÌ¿;úþîTÀk~~÷=E›úþî™Uù¸½a]øÊýT†¯¯Ú'Á«\D¯òôœ^å"z•K€üàU.¬W¹È7^å"z•ïùÅ«V`+6ëVöéš'¨héWí†Í*®ŽMبP ù}P˨]™™q€<E˨:ƒum&|úžÐdi›}œ·žNƒÖ;U™Z«_®©לJÛMÐ&6½ €,ÜMHÕ†Æ.Ûù𰽇Öì<´ò–ÇÜžáI¢‹Ý‹ÈSécYþ&ÖnÏ¿Ñýƒb‹*héšßS›Á‰Ïß3+F¼CîòˆLša8¨øøyÔñ5i뢬-ñB=ÅÀ‰0 Aœ÷‹‡Ÿº3Q2]óô^ۧW)ˆ<½AÎÚ±@ž?Ï”¡œ<{ç •ÿžû>gäåe…íWQ¶ã&­°…¶ÄþoôRõ«¶Y*jAè|ý¦ Ú©D‘E¥/4ˆ!¢V4ߪ- ºë|3S³ž£j,:úýú¶{_åh•Ç%ÝýàÓS“ÐYcÖŽÞìUeÊ ÏW·Â¶Žä©eµ® ÈËKMÀ÷1RÛ¢W‘]Ž O¯ªÆfÿivUR¤wùù8æ™ÙqérúŒ´Â'G䩨nf›­jÖdÓi„\J¿«²fÅ ‘y›@^Þj?KVÍC<‘E…„u±‹v©mYsœ'‘—ÇøH)4ÿ)ðWÊ-wVŠÁs™™Ü×eÛöØ¡ç7ç.¶JdrFWèüÜÈ)\ao˜wdØRU¨”ÞyÓ}‚§*ýN…oE|Î r`Ò¯Ž%a*T¸L…ÌÀ¾™Í¢ØI9â O™"ÚíG{êÃl)-! Ÿç?Þkγ.ª¢j]Ÿ3D-_΄ÄRL©x•GÞ­pù ¤î8Å6 õ„µ9âd>I¢Èøf†êf§U³äµ<¿ô‹·•j±ùôž†Ó½ØdîþìÉ8=€<ÅíHÁjhfÚÖXïyŽç.þÍ f(iµ šT/>8Bgofk‘ÕÚ§ÈÄW^ÝÅéšV¯ÂÁ8œÌ%ãy31W¥:l!¾âago¢m‡=“¤¡¸óg$v+6×iƒ…Š.™ß¾ûÄ«nÚ³lò¤T+\‘g6?×:I¿ ôIËÝJCŠçüý@ÏŽÂÃlÆšOÏHbC§åðœÄwÉ,}Ï[…£§Z»ºL«øÔN K Õg ð©Û$Ået:r~B‡-³=dól&<@^sM?®sV“•O^!E¹· öcÞä“ó0¤Î›€¼åóu—õZu"“(ÔÖ¹»ÈûGá$D‡Ðù»‡ðž*#è»tÍÕ¥ËÂi4uB>š“yJ]èr¬V›5ëÀB»¦òúZUw*1¶ªÎX]ç7º‚þ9WU§ž6>´d”8ä+Ü]Õ±:ЛėtµŽ4Ç€¼\ø6"ÍÀÇe†È+$‚;n¢SMl„ HýÒ}õÊ»º<)îØ˜¿üõèÕÔAݬjW2R òþŠ4×4ùñ.Ó‰29ŠÄýíÙdˆ'ž[üò¿Jc•hDNÕfV„ìÐWs^ó ÒÏyûjÎ[á"OY®º --fÅ–ëÖá‘äGsÞ†QˆüdÎK±Òy}µ¸Öâ“%Ðû‹ f-.¬=.ÈOŠämuaÆí¾|ååc)íÙ¼ñm49FD>À¦ÁM9JÂVÀÌ©™€Ì‡c¶ Ø:M Ö}Û¤6ôœ¬|M;«†¬ù7*H~b­ÅM¹}Â&ÞáŠä¼ø#…вvÒö=}Í–ŸâZÍOF%Ò÷¼R4gDîÊl£¼§]¼ûÑbÛÕÂqôôœÍ6LdQ°-«NqˆS\[Ï[çB·Z»_ÞHŠkëJ•…nQ¶Ø~S™u±p–jK6ÔÖ]XŒµN+Ñ8#ÏPÑÑ>'õ-«^+11€<¹ˆùk ¯Yt$¶qÌd* "/YÔ&4öå×zm{Þ› ¯ ´Õ;|ÎÔ®kfGR…v±‹Ä@·ƒñi¶ÚÞjkyÿd 5sïþH&×^iÖ.ð­åùˆyƒw÷´èƒ]:ãØ¥x)N:'©snIÕÝ®/H_ ÔZ˜TNä ànÃ" ËœÉ'´®è~¸æùŽþAqÝÐwug,%@žÞëè30èÜ5´Qœ(hKQ9•ìøâîÏt÷tâV°ãÝ©#×ÇåTÛÊ¢0 *½ÀmÏUÛ…%a™Z<ô«L9_Á:Ùa<ŸšìYŽÈ¿fôÿ¹Âkgwwf¯ˆU:ɺ•}/ÝYTç.ÇÛ‘G@‚C‘Õ¼#KÜtÿõªWíæ‡Ó«®ZJlwX¹ÊÖc»™·$†JRëoבÅIk«ÊÝä9f3¹nf¦17ù¶Žî ¨ µúJK›ê'óJ5ƒ ¯å>Ýí©TßVï$•7K/ð£¸ï­M"W'Áhh¥A˜ÕË|ðÁºä°ÖŒš˜LÄ6%ͧõE=ãy—„¤ÎŠ´RóF€VŠþF+%È­Ô‘ŒðŠ«Nviø‘Vª­T €|C+óF­•´RÏŒYW¿Ú¾M“NA$z% R“ò,]Mñ·W*ÅPÑ‘VZ’E‡áÉyÚ0•´R¿Oµâ]ðiR]ÒhG£•2¶Áú–VÊWЧL+E€Vú»¤öm›‰af>ñBÏ êÕ]ÕìK–¬„ƒ>ÓJçºÝKZ)*i¥‘…至 «±ÙidI+ çctÆ‹I¼¤$ù†V:ט”´RôB+¥Q¾¢žXÝUŒÀç|G+­^ó ­”öf‚òz̃ô/´Ò®ò ­tnûe.h¥è3­”ZéáË¿£•òn°.E²†ÐŸ‚'ôÌ›7O&xß)ÐJÿ” TÅqÛO„Ë4ÑJÛt8KÌŽÀ¬6ûáwú¹|r-¤y{[ÐJýÊÔù¥ÉÆ\M„ä©·»ðçDiJ, Î^òÅp]#©ÈF" Ýo`—c©ç>¡ÕÚ©m—íÀÓ3ö½YaÖì©@~Þ‹Ê Nvxš”zÞsšh>ÒïÒ­R/­Z‡ÞA‰k»ŒQÕ›ÎXþô7p¦‚“ümêižzÌq¼t–üýÛwø)b»FD²•G¥³¹ãr¸¸ß_ZÐñ€<®…$,øªF½W[ç/þGi]üä$þGèþWÿ#ßüàÝ?ûå^äû_ýàÝ¿ùI€|ã$þGùÍÿÞýñ*±ìÎ>d£®zÀ½`á€iÅ­û±Á Oÿ'ìʶ%Eµà/Uަõ~ÏZõ 8à„¨°úë/lÙffÕéÕým¦)ž""÷k©ž+{Ð4 VHÊÕŒÏhŸ\èæšóYq˜ˆM¸š'™aád†¥ð§?ŽBBxA+Õ\+-þtà±ø~§ç©®6Zž›Ó%¢§Mh»íl &j\xsŸ§{¥ËEö¥Ðå €s’§¬¤ðvxU#!7A’IÓüúebÛ¾lb”6Çây;*ð4̤B¨Ña¶;¿~™Øül÷ÁËŽã i÷y7ówB>S?>z^í§jƒN~{÷Yö³gÎg¹,š-ž^ùý·Æ€·¦g»ßÄ=$? Mú5Ï\h½:Ùf{泬NãiùLÖ W[ á@þ@ûü!¶h?}1zÑ' ï < ]àYkÙôBF »ýûž«ÈšpÊËÏ'.‰µžÃcï¨çR"dv̨íÙÂ~v´K!Õ¼bä+-¢°˜-˜¡§ªŸ2Oºx ˆ ˹´ñzƒy­ÁÙî¼rú? C/ Q6 #×>B¯‡öRÔïåÜf”“KŽ¡·‰ï%ýáÛ2õº˜£ÆE„ÞS¨_PBÛkÓBÔ"q m!»¡²îxúOLÀ MˆB ýQmËŸï6rá%¡´·¯3Þù»õlxªt­zÃHýóìÃí¾Nr0Ë€‘Ø*5ÉeÉ;BÚ!oi37ß±tÝ„wf¬Yì´]eæF¾çI´þ˜7tµ¡8Tnó ÅáÄëvнÎYöTÐvEÈ,±_zÒ4¤9ìWò…ÜšZ_ Q|žHµý„(ŒíÀÔAבùxš/4¸*áí®ÆéT¿Ú 6ˆüœ+…jSS¥†žM B^÷–sk2*m·5„¼%V©¾Kµ#粚£ó3Ï? úË®•iš(B>½¹P2wGˆh¿@©/ÏÏÛ ÂÔd+ QøÞ³ï½&Ê"…¯“x¡§û/£P ŠXy~òyiB“Œ©Ê†Ööá; >/!^öš .^\su‚^ðª÷äRÊkÂ*( 扄^¶ÇÄÆÇ gžHèÅ­4±BŬð³÷¹ìºûö°6¤(Æq;ý—G2DÌšèIÃx¡T€ú2wh5á| -ŸTÑNš9­‰¶¶²› ÑdxM]^éÄq˜w&’Êh†æqè·¥IÚv¤3ûqñ#¸þú Ü2d²¹È6b("ô³à C{Ò7S ÉRúûO¨Éïµ9›6ÙÄBQ@&B#M÷²^ùÚ—rFH,óéÇ“ÅÜÙ¬Åf—y´~ëPõ¿iÍ̶uu‹ôxŽŸ¾.ÃÒò…#äó6g!«Dgó%ÒUBfxM{:Âh×4­ª!_çÅç»üâ‹H™_{ ß{4Þ Ððöõ¬ÐEÁð-ùÑìß¾¿ÔøCgZɲŽE­`#ôz‚ºè4-öËN?¦Ë-6É{À…QöÏÍQËÓ¸]ÑRž¾À#•`÷òˆ†™¶°sYbè3‘ì K»ø×¥)šÿ¬áíûJ´®eßÕlà$¡¯¯K_©MúL4LêÎK¶ÄëoWìÿàf®WûVá«^/gSò6F) 4—,•”ø ƀ즙}» äܽ€ZÛF32H„¼9´;\ò¶ªh‚Ù¯£aó›l ³ØŸ#"ooM ?~+™$l® CòŠÓßG°kD4ãñôo§âBrrN¯kÞ2©»ºž€¤jãjæ™61¢®·ªm°»)®2)ÕA…Ù" : j2K=¡<‡ÀÛ0*±ÍùBÇ©ï¡8]P±_3O Öbc¤bx,¥Ç_þWªíS³,•©M_1ôr¨ÊCbBZVŽ|="ôšÈ•……/ëVÚTkN_à–ÁÖq¶ô¶E·’½„.´l´>]õñ®QÙÌ¢êhùÀÐçSI&Ø »ÄÍ&Œ3'n øØÐ_ì'k›;Ú°SÎyý0Ã¥wûI-BÞÍ™0Î2љ̌·§kÞß§½&oT)¾æãïØÆŒÐùüÎ'5°øÞmÆhÐÁîÍ6òAÃ5³/ÆŸÎ Ú”t¢³DÓÃWŒªÀÏ5ã¼jÞ³îèuV)©iT)‘kþ/®Ñ’èÃÒ2K”:¼¢È^Ouu i8S%¬D©ã·Þmø•Yæªoz¶Á5/'“Î:¬e»î¾Ok‰é–RˆÎÔK9–¬úË¥Žûü¯/’ªÕ¾M Ä傿Þ÷~½÷1éÛɈE@XvIĈwåyÊ/=hÿˆž’%Š"®·¾ë0>©Í2›’Ä&K´2~\Íû„¤ÓyÌ-V^ŒÀUbÜĦôCÈÛa"UÇ BõÄn8ä@ÞQÃÏi° q \âvo/ :¬m=2ÐüÏ.ù_ì{¥HvÅ믿!ѯFÈë7M$ѸæåÌ Rq»è¯/"±Á3fîsÑ#>;´>0÷¥Ô,²ì³ë ŸÅ ×»o×B‚!qvMªãŸ8é k‘%Š ¿œ]w䣴­ õÖL>ýù—͈:T ²ë¹ìõå¼’V9mžˆ<˜4îÒ{†•ݬ‰PPs!/£¿¨ÖظQÂnsÍQizp¡é÷~à WÄ‹ZïÚ#Dì+3B^c¦v(ï9¶h6«î–£§)¹£Î@;ÍnÉ ë•`äÙî™âÂ5øô+2žO“оo_'×O×ôð%ê ï×\l¶Þj„<˜@žuºCµ¤ËÐÄ)»ìv?ßQ8 ýg»7 ;­ë—úPݘÁ˜N ÍŠG)sŸgØõ ¦Ùî6ô]³DÛÁwãl~7®Ë\n]Ô7Èn4¦¼ïKr«µàk9’Y¢íðI!°Ožæã¯ÊQæŒ<"–ÒÏ&¹ï9-¼äfÄÈçM$~èÃdHYâ'X&û;R· y‰Éä-;é|ÆqUûÈ{ºñ­y…ªôYÍj­ùŠ‘0ÛY‘¶ð¡t×CÍ%U«øñ³ˆ¾:ãîyµJˆ~oÇûþ¦“lwY #ïÙí̓&x2Øä\–6çòYªkl×| ;¨¥Ù#"?èÔE©æY øåï—³ûOÕ)7Í4É!oÀ“sûÒ>éä&u%›%ï‰ÇoŸwÐØ4öVqB!»_Oy ~ò•–uÅ 4x²û™±ÚäöšW­lû!ÑÌE0š+AŽ<.ÕÊøT5´*í¿Ðb È/ê^Jhƒe÷ÛWu¯Yfªn@Èë·©ÚNÀi˜èoà©ÚÁOÕ ˆüý$žwk¾œ]XÔrÉæô>…WWýÆ[RS‹qFÈë±’«Àzt4$ZMÝ2 ä ñùš¨§Ç‹ôôòPÞ«b²[ çºÙ—!©¶¯Øu…æá0•OléK&­¶FA¶ûH,¨ÝÙQGåüa1´fŠ´™€|AfZ×^ØlG.²Y;ŒÌãZ*"eÝ~[Òm‚ö¡<êÈs&Vž/U°¾^ñÍ_.‡Î}(±¥\M¦Râ»?l@wÇ ïëÑM|˜ =˜¹>ÄÔiŠ êkˆ ï‘4ø÷]5»ç äõ -ÍæHµ®WØ÷“´ñ^%îìœ*ÚI-òµ°jaC_­}¦÷ùHt:š:ØÊ.íDd-„|"lê­­ÛrpcYøÞ³dìJ÷ ×öü=_‰{°‹´Yt©Ts¾fžå6¾*1-ó0Šq8ÞäÔXÛ—Oà]Zª5XFD(ª´°Xƒejèg=îgk ßMõFŒÃÒ™ãª7s ß#r2p6D"d2wL¦ˆÎ@—æ‘8µx©©(tÕIÊÒŸþN1òÔnì½OB,B‚3X 9EO–m+@t2 ïï“)\ZÍY„||(è—3a†°Ù©\‹ï+Õ„KAŽGŸ%Âv~6ß›ïºT¶2%;–}öEÀtz{t–üX̯/% i“bÿ%Ë–Ÿ~“A€Y›ì‰™—GAj(ì1ÇË ÒøçåMF'  êjcÕ,kŒL‹àÔ•f]zrXÏó²ª!lê'F'´òž 37Q¿iW…šã`g@>Ð…©il L ÈH„bÙ.†ŒÒôZƒZö¼¾•íÈF·QÄ'K„poÿôr2~–üöGH勆vcT²±1‰FÈÇ»ðĦ3šK|GO4öì;øb®‹ÖÑ2;Ô›â0³œ%Q6A=]ó…C±˜z5“=>áÝ<:o.FeðÅyMÚ3Þ#•Y¤lu!$J“|±Ø}z?ðŸÌžïò4\“K…®yG)ûÜJ(ìªÚ~Ï^âk)·§ÀížXf(;½«.I?<}À[ÍC†µtFvá€L¹øçOÿ€¼~³ëhر겓e ‚ŵ¬UÛBkêùz3òGg¥WªÔ NÈëÑÈ©Cqs™{2•ì`)>~º¿£Ñ~ºŽrC†ÿù9_ÓÐÁ@±8eÃÿþŠ2áYö̳››Rnÿ·Ó‚z|Ò§‘-Çm8}×Äž”¶QÝŒ)¥¶ªŒ¯ûY· šý6µvìñfFÈk:B¾ÝÀ!/è@ò–è0Ÿvö„ÙócÇÒ¿£ž†/î"BL‘Ξ#P7M¹¾®ã«==.éJ(F^‘¶š×A—­Q›Þ0ò–¦ûrÃÄú‰n…çëæ_\èà_+&JÑÃüËëqâÖa®D–]mxÑáO"ÅßNR†*­ôéÞ3Îk„YÖù•ºÂú‰ro'ï®i3^»bF„¼áæO]s¨îª!“醘³—ª©ˆY{üéÈ6’|)oºZ¶øŽžÇŒR “÷©–v2}ƒÙqÊTA]lsÑ(SÄì# _ÉÔUÔÅo›Â—ÝD235¾¼Èü¯$GÍÁÜ#þò¿SàÛ,j֛ФƒWÊtŠzL­çðt}SÛ[\2 ˜B$À…šHA©ò†¶†}¿áD²µë·(Bw ¤…BÛN®¬Ü6¦ÈÄ…doMywÞ*ºª!OæÙ>í²ô5Õ3å%B&‰2/¼a_£ÿOØu$K®ÃÈ+½W*#-g?ñç”#EÊå¨èÓ-H¨Lﳤ’0‘¹,ä€[ο=¹×K ̪ìÊ©ƒ³Ã¹ÿ1Ru­ÕÂ5‰²‘=Wí_úkBÃH˜ ÔLaøüçlèSy]zsö¥i÷0 šŸ†w^¨Ål„WùþZ|(UöÈKzv—ÝèÜBU»^äà˜o¤Cdƒ·.ÕáuÛûVt{¸vLÙuã–&Tõ5­JÐõÈÔj¶ åDGk½ÈÍø˜Y¢™Û¹Ç©‘!ìQx¤ ô¾Ûá=PÚ¡.•€éR¼…½Sb÷-'ŒàúZµGÞC'ÒY'Ø+Òq©ÛqÀg I=;"Ð lhGZ |öÏRL,ÈHæ¿?Ÿ¥˜ŒÁtB^ÒD9¤Ô̤ÔKØŸÉ_zê~Xsͳ§¢ݸ<´q:&ùv}&&9Wò`™ý)÷™ÚÂþ…™ ‹:60˜-Ìo¯{§~AÚŽŽê›¾£Ä„‹l¨5rDݼ6dDHäæãI³ÕLxCÉÂ2ûHá#(“GkÔøÎÛ³oú7|ÇzFH—þþç:úbºqÒÕzä=N4;.¬>f·Éz¢eعõÈÇ;ËQIù\òxE'j\ÞäÞev%_2GåÙª—:ë‚bFÈ E커ß:A—?ئ¼ É¥”,Ëù˜Ñò¾¢¾òèG}§ÆzX:„„‡®ëb4²§²Ãg} #.å´!×êX;3]6"dúô•#u›8¿if‘zr¹a(þ”|߆gsºó?)ԭƺ=«'£j#½úã|Î<%³áœ Ò†b?@/JýB36%Ÿ¤˜j‚¡ÙûÁÉg 3å¿ù©)RûQŠg¥V*6 Øæ‰…­,¶}Xkhû°Œ³æ¿i¬·Vо6ï©×yWñ[б^™q×…57j#-7F€ø˜P$™âØn¦è„QÉFç-Y‘ŸÌnKø>kÕQ5Kh´äÉøV€Ö%…U€î1Ò¯ñF¹öÚ$ãÐ ÕÍ,(Sæ‰Ùm,†½7k oI2’d®È Ö‹AYo2ê5v'É™…“š•cÃÚ'†rœÆ$ã¥Î]„¼ºaðÚ²­YR]J*„ô2†®œòäQ#chHíyOT¼ צe/E0jñÈG*Áìþg?V‹š˜‚œé’$àfEtmHêd¸J^ÒÐÞËÓÁ-oðì”$}n«.ý”BÈKXcÁÅ»m¨†Ž™¥H/¨]õͰQôÈk$vÚð®ðÖqùÿÏ[Jt ê샔 !#ólý^»¹f†.Rë÷<0ûÏí÷yg*£¤^M‚¯#BfMâ‰ÂǼ~0‰ç TC¼¡Â˳ž”®‘Gòœ ß¶ìÓRMÐÌ/׳åu~hlÙ(çó ¹ò7®J(¸-ã‹ôõ ÿ31t·m`g ý¡ºe‡\$š¿#a3îÈû)W®©Ô1Ú§!ÕÚ;¼¾™%ˆž{äõ#C †Xòd\ðÝ‹e‘<û=Õ3f-´b‚‹.|v®â1“Ýp¡õcWó¾‡%>;úDî¢x«JÈé3l‹k㼫=ÖÃŒ9Q¨¦²ËG¢¼Îç¡Éä‘×t<#8¥Ô¼Ó%÷®e«ž[«‘¤_UØõÈû'#¡ÆÛòì«‘¡PùÑHè#?ÉâË8fŸ§cïD>;wþöU€ã;„<»àà12d÷o‰‰’G"§e8Å;ˆ!Ùý«G´[òÈb G!c’Ý¿ +ꈳÀ1_¾Ž]°e´Â¢Q^Ê+uÄû™¿aR¥Ñ&žý_цcä—hïç¿¢ ĺ,ÑÛóÞ¤.|›>É3 ñ¦œ‘µW¤“ºalÈšÊéX£WŽ l¢š0ÞŠøÜ_8B¡B1[mmGF^P„:Š‘·¸vœÎBÖyO·ë ×ä oæ#‰•dà~WûsÔKÂsDÈ<^ªÃ†$Ù§²wg, \ d‹lÊÖâ+âYÞÖΞª'ŠNÀÐä› #Ï:ƾÙ5á9ë°döuæå<Ääúêì-Îf3o½¯ðâÝNSÜ.*›¥SMGÅÁáþ%áKôI̯ó´JÆê~FÈK,‘l¢n?yýä§’Â"›Î@¢I'ÕÏa&½ÂÈËkácJ¤£å×üT"QoÌJVw4)‘l(‘¼þ°êœe~ „¼½UPBZ!ùõ‹ÖÒ ÉÓYÍ¿Î2.<÷mÞö¡‚Å+™ÕÄÏ].#~î7BßÌχ+J݈ßÏÏs„%ž›N™$ÀÉæŸajOÈ ˜à%ÖvɌ̀e†÷-Od•µÔh„9™ì{³ ƒrØ3ÏÑ XjÓεNs/+8æý”.†!#ç9>á­KǦðæÐdœ"ÆÂ’tËO#$`Ö'JAI ”Ý|Cÿhçc×ÍyÅ 6YÕï\×eêòµBmU'B/ñNwÂýLF±¼²›Ÿ*Ô‡-kžy2Še\Ž6iô*tö«$!`šßÏeW°^d»¤úýëÅDyœ‘Ù‡hsHgÍÕ?­A¥ÿâj5uSMŸPôÝoHgÊSöiŽ>dwÄcB ùï•£+»ÿyŒÆß€°0“ß“Q#¢jWbËF”f'c)|Ì,¶@«ð†T£}C ½H†¡œÜ©p¢¦”#Û¬#æ÷Ç'e"] )¾Ç-±0}[ Éø?óhPv¥v£§¸äÜ" „cS/n.ÖATLƦ^4ËÈÑêü.œýñÑyÄ~¶²Za¤ \H]HNµj:ˆ`éØÔ_Ç sþI©šMð<›B›C}u¬ƒÙšò£úIrçÿjAVùøÅ›m‰ã¼"ºTœ!.=./¬^ê]ýÖNFHòÔÆmñöa‹wDÈKØÈpÇtÛ±dàBŽ;>föfXoÞ¨þ4–Žùb査~“›vRuð9ÊÓ'Ÿú­¾ù8tP<FfÉyM=»µèêžQŒ`íw•Og}ÏN9>é‘óVömFšmhUü:’!#`àº!8¾mª¡û òú‰Ò±ÅÂã¥ÃÈŧyÇíߦñíßC/L‰ÚªqI)o¿à9†‹e­×ŒüB¿(áì9öt]b ­e#Ë¥ja…N–o3ÀCÆkQz NX+F±+ˆÉùÏYXÚ ‘­ËÐÓ‰ÅH›§‘!-xåSvRí{ƒ™}ªÎŒIK@þ¾*ºñóDtðÉ“§hYl×£i^§æàýLGœÞøžO(xÓq¤à´êxôÇá$àà^?jÙ¸¶ÿŒ‘—×¶ÿèÛþñΧÛ(‘áè¿8Ɉuùíœ+ú²ØøÈTF¬‚"$ïò.ž¬›çc^Bf±½%½e]­:iÚòŠ›<®Å¤3@eJòtÎy™ìWêJV®Ô{ÎeAÐ:7ÄfT~Rak¨—ƒ5ÌrY– ¡™'Þs`9âYçï;9 ŒÌÞ¶í«‰Ô©í?K•ðÍç~\ëqâ=´¾Ó™ çç }.Á¥¾4ŒLÂû鄎>¾!ũ޳÷Ó\»ƒJG2iáL}áÁ2Ðc‡i˜<´ðšÎÌkæõTNªHäÃe×M枦ÆáÑþ:O¦ ¼Ö’ß´•þsîsžL8—¥×^meòº!/¯zÖÆž•Gÿç'¹»Áªª Ö£“gVÙPP}—zå+øŠßß=ÍÐ jý<¡wò̲[̽ue¹Ôu¿)„¼œœÚ\Dù.âÖaê™…ÚJçÔÆñÙ¯1&7^óq}²­Ÿ÷yÀÇ|ëé6rµ+ôÊÄ3K™·®_¾‘qR±îH<³lnã e¼E¦³ŒÌ÷Õ³Ú'Q…XWüœÄLjd%ž³N‚ôM=2:”›½e»pnjk§JíÁS­ˆfv›Ï˜–P?JÙo¤¢Ë€ÏS¬$ˆÚuãÆg}çI }?"sÇ!Ö•ŽŽ£8]Ñ=|Gfuݾ'ÃÒr*0ÜšI(ô»Q'+³èæa@ÈgA–je² •U¡ËQ¤® ÙXc!æ躵ŠHñsÅòAu¸õVn®|FHp('ÞÀ|GÛLöi:ýšRn\¨ŸÑA§©%!orS•ÁTYrV+JÆ0í‘÷WJƒS@œ+~RmJ‡ôĤcœ–Eg,!“YFêwÅä,CG»Ó1?ôZ³ ÷óþ¥ÚÉFpéég-o“Q›„îÒã“ê7ÓÔÈôÍy‰šøFͺ& }?»:3ûDy? :+Ê»‰!nÌ®›ú˜¼;D×^¼ì¡4 ¤‚±i8F^>ÈpUQ†«H(ïÞú ²ôF‡T‹Ÿ”ôòÒ Ò¿kÿýFzi é%œý÷÷O¢÷ïïI£¯¥º¦ó*J Y¤Tò(¥â'ÚDöÄ#/©AVgéþ†ºÖ½ÎV2{3×UY1¦ðÙ¯ïæºÂÚ(fâ‘·ø4?ʪ^®ô¨G¸ö¨öî&í¸¾KЯѮÓ+ÎòòQ3WƳ_¿j沺Wùe÷ŠÁsî†{l¥6&/B dÖÙ ?y6ˆ“gC‘z6¼ó–XÂl}¤ó³·„8yK)éÜ矮>ÒY%Ʋ 3‚EJQVÿç} :/þ¶d„¼@^çVóŒtñ,ä³W„LM’)gac§€Äj°–ˆètl}ÇÄ.*Š—”õí'êÈax4à5VDÚsøŸ3{ª¿MAxƒ×t:Ó_‘^c„i˜1„¼}Þ;ƒ¯øòsúÞÃtû*†ŠÜŠË92Xá‘àÞ¾‹2ó7^{è×9ñ7£ó¸òtÌ ‘I¼q߬³?6[@^ÞF°º¯a€¡H ½aOŠ…)RqÌCÐ…/.Ùg œÖjúk(µ(zs§”ê¸â’¡Š¯Ei+ ÄÈÐÀÿ<9Ä$kF>ˆ€4Mq9©¡Ö¾ÍáÈcmßÃÊu9«¡¤%¤µÏ~Ú2™¹lü~œ=&Ûê ä‘·W¤=æ°ë´GÞ-Êfk†ºV6| !)ÒÅ%ƒÔ7uëñ1ýH†½"Ÿ'×jæÅx#d^up׳ÈQŽîîüÏgÚƒ[;µ³}ÜmWO}=Ã%Ý“6‡ùä¬Â*5›RòØÇ]°!?¶Je\8/”ØÅ9$#Õ\U3E—üc 8Û0~œÅYŸ6AŸŽF?œ=û9 t„‰%]FΩ(~5ÞŠâK„ÌÒ:„7Çs¯F¸¢”}ëdþ}&ŸLHAº}AÈ˳0‡Ù·ÑüĉdëÌWŠÌOŠ„« ´0ÇYíÛRËí"5Öð›(Ìò ×Ygj\ò Î~ýF÷iD@b±+öâd)D7#’„â0ûlç2“+z|CŽêŒ„–™¡û¸ù}E/[éEÂ× [¾D1[ÓÜÃ[—În6ºØœüÏëÏg¤þ4ÄyI\¹ÛÆ·ö Gc?ÂFW‘2&ÿÏïÎoZ9•;ÃÇüR/œ‚d‘šKœ“Ef“E8û%&‹nÙîB²H›, „¼$„›Ö1;WY×|œÆþg²t½ Gƒùns—-»LoŠkö‰Èâ‘°Ì &¢Õ³£mëµì ¥ŒÏè_›ñ˜ÿÚœ !³/S΀¼á)µ¦ D—޲TAº§H¨xHð?ÿ I@üL¨xïI#?“$ÀÃ#¿$`=º>ð†‡U1±ÿó jlª’›k~",RPèÓ«ñ"A·´Hˆ€^R,LÐ.dT”ަ_sÔŠrÚÜö˜‡œÛ ‡@Èkh’6L厲V\ßÞ ÿϼŸm0‰´ŠôñëÈ!ÁÛÀ[»Õ‹àS¼¢â»ÄïgB|5‚ÆB!dL×ÄXOH5WAǰ¸ý¾ˆ5Þ‚ÃøèÔ#£m‚]ã¼(û¶ms|î7,»aËÝÖ¥ÔÍ:èõ‹·_l›Ðß^¬wE'XnXvÃlNø²‡é_Í£Àg¿Ç-ÛÆÛ¶¯VÜI}Ê#©¯+äºn õÈÑäå´5Ò½Z¦îÕ¾-Ô"¡Kz'no°`®éi^A…‘ RÏn}ç+²÷ýQ!ä5zÖG-ý0÷ÈpyCt»ÏöÜɶ/=™žyO|w?»‰tC;̧k`?ëÙ½¾ëY.‰}{ýZÌô£Ü—@yñÈÔ··qÉE=ÕËDùØ |ç’z×jõêÃN~CÛj>A“m¾Æ{ávé('Írzžèz)&sûU§D-‰¡YTups‡6âÔKIŸòtT/1W!¦öeí7 …y˜è¯ë³úYvœá'õ %eëE†}ÑÏôÀÐGª¢Î±Ìs ³]Å-;«dûø´òštå#nj—â q=M¥ŸåÊg:C¾œuƒEex£K]õ’g°·(»” Äë¬Ë4²n„®¨z„¼ƒ tÔuʨær™Kü?ïiM(%‡˜Ñí È„*lÕæƒt“®~ľéF $ª“@9Vl:»…&[B*†c’“Ul Z¸úkö³ Œ“ši‚böv?Ùñ›³õÀÙÒò!/éV¸÷úkË(dÅí´…WW^¯A.F‚Ô³ e+T³ÖÑ š[&›hÈ â|{Ó|ÓÞ<Ú%f‰„×äá=³£4Ï “¼þïŸð4;÷ŒäZÇ[ñ¡îdlRÓÔ‚–J‘ÒƒìŸ«çæ­[Ë÷—¼Þ¿ó£à¥ %. QçõÙr!'hªß“ñ«™Ýwa##ªâ Y$*k¤ÉÅ,ÒÄq‡„‰­âþ‹æq^þglsÝ/_ÿ'™ ŠôãÓÿ”Üž¨˜E¤Ÿþ§G*†Ï~}m®] þ#"*;‹G«ûFÔDkøâî×—!ôÉ'®Ž˜ %n¶Rqz"& .·~Ò_ç<"d”›Œ®‚§fu=ïtUÕ-·/ °û¾ëšŽácÂ|½S/ê@½ˆÏ°Ýv?‘%š0À×C(B¨Òò³Ó¾£HÇül–R¯Œ3BfAòPïf™µZ÷¢¯È\I|Ìk¢sÄœEÍ(ÈaTžà‹»'fêÿOØ•,ËjÁ_º·æZzÿn„ý HB ÐÑ_ÿ˜á¨ªl·#Ü‹ ©4Á™22ñÚZÅ9 o¥_F´7V•ê6œß:X»*âúY_,•ßù,k‡ÇnMÊMz,»m˜2d“.#dl“&´‡È¤-€p²aîånŽÙ  ¯2Ì… sÌ­]CòVÕ½¨èȺ۩+ ÷7åwƒ4[çZÁc>RÓÇÍò¸+Â{[ñqÀ@> o ¤ï̇Áå&¼Ÿ¡ùÎJ§É‹È’I·J›çí³»1K2æi^¡´Öx“ÌfÎgi˜ñ†_”5NŸÅä÷»dq ‘çJ†4ý~Ü<öE6¹XOVº§— Ì^çî”Mñ: Ê#ÅýYNTá;ÁÕpžXÏûé#ÿMS“uÒThºCazËDòb‚&ÀÒ¼ey¢¥œÒ~wEuê5Õ¿]8ú^J³Yà|öëA0¬ ï’u[]Už;&qžÛIÖ|ET»HËMar`ƒEsíÔ«ˆ÷ãJF"D~Fw`²eÅüH˜ÿК‰%±ò\";˜X¹sˆ¼¼Eöly9æL¨{޹"V©âŠ tV%õã~¤ë8‰‰S€ô“7ApÑ«Mnd3áÿ.Û Ïo¯}XÚòw>^®(!%«_×ÂØÃK Ø a=B8ö3î/]É·&°cíÈÆT*ÙŒØ_8ráoôi|>¾ŽýËÎ7>Lrb—à1“„d…[ßäµrDfMuää%![ì¥m©ô4³*É¿ä5Ïaâ¡k/WQ r@ú…þùŽ‚¡¸½Ÿ}×ת5@޽ܣ÷Ê}kÔ¬´Â¼ÛÒ-ôf;4¿3ÈÒtõ6À¨¢Vp@>c‡“&øGDÔ“¥=Üù¯RÅ”'ŬçãÐùJR³)õ3EeùÏO!/+œ¼ìNˆÌc®nè¾ÐÔéfD½çã <í\½±5™nÐ ‘…žžÍÏŸST›˜)jr>  g9šÚ’©kÇO Œ_P•ÇüNÖ™àNä5·Omo¬ó"û£_NñZáƒáT¸Òn]Öå1™Âã’¢T+|0~ý÷d¯íµcÑŒ-]Яè #Pוý€[2Rxç¿@§5÷y—¾„-?¸i¡Ã6‘´Ü•>ÁÉÔ.õÄý€¦^Ô¬Ðs&*úV¯×3á£NjiÏÂ#há6AŒv«[¦ï=„^ÓȆ9ªW³¿Ñ‘ ¡· õÆ›ÚHÅšu<@-dê›ÍÍÊpŸÕ÷£„zo* ]ë) Dè3E즉®mWEîÀé«PlR>VöR™-<¿Ô—¿·Éš”€=ŽÛv÷n=;ÅFø8õ°ËC0, 3ýjž×Nn O¯HË6·Èç¾W“£³\ŽÌ,…W…$YÖbxf–Â-mµ@žŠ†E¬G[kDÖ9–xK>ƒkØû鶛̛8|h²˜ÃnZÏš³ÒrcÅt;dáÙÑÐбXv«ð€¦ /åìW ŠZ?ê½N~:Ï‚ÏæÉHPÖ ß«(®ü,ø ^Œàìs¼ 4¤­éy;\{´§šä >ò3€¼¾­±`´vøùÚÃàuÙŠTs’h|–|†ŸÀxñ3¾¼]–édÆpÎîa2©ë‘¬+ÈO¢¨‚wéÛ|>>ˆ|E³T+8oΖ4]ý|þCàŒAä¬}iƬU»¬þ ¹}ýuÆ×Ü€P:4ÈܹÄȢȗAž`Öð@iâÓ4ÈsQ‚ñ@¡É6/"ÃD¬ "_^3Š|‰h¶eåÀŒ "_ÄÅCV䫪Ãw‘…{‚#=wÞ˜–/‚0á¹ÿÆ6ìÂääÀ¦ÂœkD^>1ñ’™A^ÿÆÄc¬Ÿ@¾aâ ÏÄÃÈóûYùb¥5ÈÛçYùr¥ÈÓÇá™'d™uɆ!Äzrm-S• éÚ,D¯¾m¹[£–Ô1€<½J;ë¶e‰axD¦ øª ¦X‹­â¢ZxöË'iNG¿ òyä#1û[h7Š•hßp‡­Òp c¸u«ãý,gåý¾xét†f_¢`±ADsA´¥;_Š©gÓ>’LûænÈ`d¹âˆedM›bˆä9—wq½E´&­âžÝ Dš¯#p·ì¯¬Llþ¦oó;§_N.¹tq²Í±…2€¼•*Ù.c´—ŽÈ;äƒÙ7ÙòÁøØ¯D><òwn±» 5/"´†¿óY˜‰FÑ4“-Ë „º_ šïüpIßÅü, 'rδAhÉUcÚZ(´çu•”?–«ê6oN+52Ž?àòj¾|ÐÒ'(DMn§ã=%q-A²Ù‡ê)­­e˜f:ø¿Š©\ëª3+“úK€<§Z õe$Òi´Ø÷ã1/™-`pž¡­šuXë¥yMU—¶!¾‚GzÒI*Nò‘ö¿¹ÆÈ>³ß32j»¥i ²! žýáfuòma{v“"­Ûd¶%Ï7×nöø}ç{F^SÂ~v~ƆÃ$DMò”î’ ™ìŠ·ÐiÅÛÇ##òüþŠÙ“|í×|ç\… x7+ƇnfbyH·8ù½{Õ´JñÀ÷5ßùßöìÎÑœ¾î‡¾Ù62Öy/‘Ôåhmo{ŒãpQD>>¯Ìyû¬¯!}î“îü2uq4Ç5Q(W„÷Á.Æ o„/“œeÕÓvÈÓ'äJƒŠSDž? tæ+zþ-kš¨ pÿ*ï"1JHÿ;•çLú•Ùr&[“P¥w¾”§ÿïw!·ºÎÈÚ‹H‘§‚†wß[Þã&-L¥<½«uøÎ¬í=ÕËÚ5z2e®äªùжKxÌëýËíd² @áËè$ÅM : ]º¢Ó‘÷’œ¹úÁ–*­Ê%óäwv´ô|fÞº¶ÈÒÖÆ5œlq³!9´ð˜ec¸‹:tÚ|Å&Ä28Ezë ßF•ÌljUhÈÛ+CÆòJ™eȤ³Ÿa):ÉUÛcÊnèSöqº#Æ àJ%lT#™r´* *9ÞàV“Zæk/ù·¿‚jIªm-™ëQ@µÍj7HxökþÞ›ÀÌ·BázÄÇ/ît}éÐyFoª3G¡[ƒ¼¬œpLå‹É¶±NÑòé âS/Ä< ®kÆòôAØšRÍà1Ï@5í`ìi¥Æ¤+z4;HëùN´¦r·ö¬éi>_žf2–áÖX¦÷3“Dœ5–muûê ÛÌeÓO O¯ÅõÉ‘YPì5ä‘Ãß„â¶ÉSP=¬9›;Üè\qÝÕO&óO=‹ôŸ« Æ‘·êZMÛÖ€Lf5Þ}2ÈUWÕÚjÈkþŽpY·wGˆ,¿¸ä–h G²ç™dv ßäUóZé‰Á³?r%ÐÉØ.G+Y!RÁ»ô<¨¡ÙªˆUC“’6ðì¾ñc»*Žtn¨ÖBíµFüð¾ÁÊäéÎ²× Þûï´€ ž3k·)gØ”ÏZáÂ\~¡nç²2¶´K4S$!/ ¡sC®ÓÓF6bžiB^?ˆ.9¹I‹[zûLjEJè€ò{6"tÒ½#ïW™ÒÉóAÆûá'ŒÕ „ëäéX¨·Ç´…ú^O @¾átØ<‰Šrxö7â¤Lk‡L¡Ýù;onæÏ/¡Vn@þ\mÜbÛ…·iDº›š ­¤C\Y¦¨Ø²0/ˆ¶Ä„íš"€ÌÒ~)ifótÈkaê&èÖ˜8ÙÄþ@ÞÊÒ®3,¤¡l^v®Ò§ô,&8ý œ~†ÒNp‹X.*å•ß}QhkðÊv¶ägT ÌĻ䎹‘ÍdÝ,ÄÎÐ ¥‚˜z¢8;žýçG}“¾u^ÌhÞI ·w–Ä&‹Î–Ä÷¯Ë×aC µUË(Yf²®|Èüu¤åÎ|ïdT]Ÿ–»‚ÃõÖ’a™×–0³Ñ,Sh£Èkš8 l7þ´ ;Þç­ô´ôá¢õ´d²ívw If¥­ÝÓåm.{lD74MD(€‘†RžÞ5}Z¿u8QEζfäùÙT=ÊDFägSu™Ê™÷Âl5»S¹$R2Ý<‹*\¼m·mfSšò“ɲ\Xi²|ÿºBùÚж[U™UŒÎuB~¿È±y¥n³k3¹±fàY´/CÆÙM¼!\°%ÝÏëñÛôƒRv¸'ón¬òG¨Éä²Ná1ÏŸc°ô.x,5Ž+ÃJ›­!KôÌ3ÈË_Xçl®yJå Ö‡{áø/8ïZMšó |\}3i.(Ò"‹µ.‰mñzærÚút—®o}b[ã"O…8TâHȽëL¿ä9ò©°`Ïãz$2úOFäÄŠmˆ“G^Ë.EA¥8~àrtΪҶðèhâ0§¢´4­´™sòN”V/2?#èèã>M÷C§ÚÄž„7©lU0IÌjóÛûzy„'QOi»"Ô?Nt)²6_p2©Èó¾¿%Ë&ä~ï>\r!è@»k%;å¿Èlõ­±¾a{R#)³Sb¬HüÎ…êøØV©œ~˃‘¾I¥j˜& Q‘ /ïeaw"§U–Òü/¥°±,…•Òü/¥0eKayþ(ä„R¬x{/ädW0Â¬Ó ‘Ÿ„œxϸÈ÷BN’2šßÏÛß„œt+yzî·ÈPP˜Ü©©¦ù~ž_ò8x,ŒÍæŠRdUHóû> ö;šçAó ¯œ¶6ÙÅ —7×>#JgªSKôv.¢txíY½èþÎÛgAŸƒ•ž·‚>ù]ºüCÐçp̲Üìµ^%««è„g/ÂÁ Ež©]öºj€,EI˜0^;¬¾T™X½Ó¸V0™¶m+ö Vo6‰þÚ²yG€¼f^-.†yÄ8×óö*’n"+bóeŽ™TÁ·ù½’.p Õ„•.·tþ箋dÛ¤)Nßívp/ÃI±¤Ç;j÷-æÚ¥-çû‰~»/õ¸Œù­»ƒ¼£÷“ZÿóMÕ‹J¥ÅlKðf¡0é1ÈÇ_Æ “žˆ<•u†8 d ÕE¡ §¤:ƒ+ Ø¢®ÄxŒÖˆ<½zâ:]ÁÊÄB Ïп–$ÿZóÕy‰®ÑVÑÑyò:b2+xZ?ï_Çl1x³°‘¦»tÿ‡Oû–¾¸ûé(bE=ÿӬɒ™7ñ.”“_Ž%Ûdæ-Ò{-ÒÀÀÞX7b_gèi]×B-u\Á ÊÉ/¿Î‡Ý ›°•½ óˆN*S›:V™ý ó²§qoò:n’PÁš ý¾ùG¹³‡y¯…b¬X•Þ{!1ìYs¸ 9¬A²EHxv?†ú£\$6¹…R\Õ¹Ær¿¸ùÑŽÂjPÏj^ª Kn~Ö°U{E*A²àæGiÔmï˜ØÍú9Â;oKµ?6¨ªðu˜ô¬™§Í#<½+Õ–PËÜP;IsdxM®Tû ]¦µ) PßX·t' ëÌzºöLá>{?®`‰ vždÞ.™›V! ¡öI)³UQ^Є"µZu§á3uÓâ*N:Îæjhª^Ó{BlÃóç bCUUì}ÐpÔ¹EªMÁC€&úGííÚÍe uº#ŠÃûj§Å‹I÷²,”uÒNÃûzú"Âa%×J¡TÌ  øú^â~™5Ýò”f‰ð,ª¥ù •Yª25ÝPtqu Š‹(ëþ"3Ýv¡@Ä:‹!En÷ƒÌ´ËV§Ú,@VÒi„È,‡l·ì·/¥‰žè®è ­)¼ü’âÎÄámU¥¦Ûý #vÇ÷r÷SꞘœÿ€„o´ßœ´1÷H?x¦|E.´mè$µÔ @¦a•@Prµ»FÑn©u~‘[ØÁ} uéÐB¬Þr@4®¸ƒ{eM³ž,ã¼ç‘¿Ç1[‰ëÉDR㸳 3… ã°3v–ð%Æv„gÏã"¾guIZ³@ ÂHWà½ê[Òó†&ÜõM:û÷k#˜Ld®ë6U</µ‘.Ô1æM-û>ï;@ãͤõ£Ý‰È<6xÈK1J÷’˜¨¤ŸmòZtEÇlLÍÌ–)>RËoÿñ´¸¨ƒVʪ¥6âã; À8w^Ç”v­I“#ªÚë ÓÒäv÷Î+ÁQc¿#x?Ÿiu¦·ÁN€®tS©!þ8ý•ø sþU2ÃÞ4p‹L­ ¼¸¨Àé×ÙÙ"W¬Ôdvçµ.×^.“ZÍ|d6{€<j¡Ò-­à\íy×ä4­`Ë!¶ê:¶*e6ú1 ’=®78¤)Æ+ˆ9¿áDr;æ1 ºJûWibGЭ†›þ™0ú§Šñ£ÔÙóµå¨à014k‘ê-Ùêcÿãê«QØH2&%B‹„ÈÂâ=«©mVËÎIõÇó¥jÚM§¦k˜îÒ VÒXüHOŒ\°ÕNÕÀcžÁH¿+† ΕUlá#@Ôƒ¨íb~§ÍÒŪ² ÌÆ5Ùd æSJB¥yË5ð8n'¢\¡A5yíó2ó ÍÓÌ_ñ:=¾y®Õ6'AI,iåÔ¬µJb @~2{c‰ oßE!³þeÐkeúÞÙÇu™c$ -sn¦¸*,I’Y¼CFf¥8@Ö>9nºZñIÃckŸ, šy=Ñ /Ÿm ûì¥,rXö¡n6€,t·"Wy"ÛFç:Wäž™ Õ¬üµ[$™[ÙÀ+z€9÷;·vØ[dßäÒÖ\®Ônƒmwþ+KÆ Ø@Ͷ½Í«„Ð4ŠìUÃ=¡œ®Ìäòª‚ÐSÜ>¬E‚'B.µpÅö”~>K&hT| u“w/c›ú … ´TeÖRUW¹OS½Þ˜¯ä ‘寮Qj~z^>M-dþB.P“0ôf³ti¶”Q?áZïéšžà'Ì}2upŸ·ã®>Æ2LÍ^¥+ºðwäÆXê¶>¡ñ,mQ,èFÙbÑu ¬ ã‘}ÿþ:ô¨œ2™‹íÎ=›mAdölwÆ5Ž×lkZ®cUî»´dùù_a“åÎn²à1/qxÔsëlT¯&¬²ˆãœÐFbÿ'ìºrd·•è–Fêüéð[•H‘JT¢pWÿ‹,u÷ذ? hZ‰ª*ž0Om zäý] h‰_Q md=k:ÃÕßÀ®ðÈçÑàÈ¢ÁrØùÖÐpå`K¼ ìQ¹ã8,üç³,Èu{úqŸæƒL¾¢YŽ2–Ynü;„¾§†^ÒÇUX¬”Tì» ³‡Máü}Ä _?4_MÁkê Ìãè§~˜Þh†(ÆÙÈ넼n¦‰"džÚX´N¥³L£Ñ©Ç'*õ˙–Ú¯p§òßh©<ÒR³ŸüwZ*‰Ï^þ´ÔrAÈ_h© ÿÎÛ;£K?žJtÝ1Á_ÑoNf6*^¥Kâ%†Ìˆsò‚ÜEíú «ÙŽÆ”% ¯§HFcBä‘úu:¸Ç È<âÑpL¶ G9õy‰WÞó- ²Z–匄,‘ä¹ð‡@q6¿Sͤðnyû"ÞÁÇY#o_²̞V¹È–¥‘÷Sl{ˆBÒÈ¢ši/02OÜÑ `“ Þ]!í1ïL=ÐVqÀǼ&¡ñ~ÛëùJH¿äó°ÞÒ­ŸÍ’3#d²×N}æœ9÷V’¶ïÖY {VÝÔíø˜×På@œ0ÄeÚµÇH)BÞ;ÛÏÑvZ§£,—…ã3ºa˜•ˆ;šïÑÕk£šJ!ä#à kølßÍé í²„ ¦€|&]µ«y”dì72 ä7/ƒ,õ—.~¿i°À_o~ð„ÐÐçW}¦'KÓ5G‡.ð[@™×^Q“‰–;B>¤¯‚5²]È Š4|¢+ï÷•ô•7Sΰ,žR“P ÄÂÞ…¶;K• NT1o@:*6×$Ö^˜swšI¿%d¬U*;%™¡i–Eì:xè³S’HéØ-Ì#WÒq„R€Ñ4»E¤Ö–)ð1¯'dm·yK¾h°È’} Ë®x+Õ‘€Ü}/ŠyæAœe×Syg”©Í^ŠeéNùL·gÝX?ɼj9óõÅ€IòicÞ~7`:àÝÌnHfÀNÜ΄/ª êœ,»ãb½¶)“©ˆZÊ­•™‡<õ ª+¢ !£Sí ßÌ1SÒÖ …Qõd„ñî›j: ä-Ùtõ^9]׬ÍZ,ë„÷”`âÊ “Ù´–Uߣ{b îJÚgâôºKi ò™ÆÝ §­Êj%%9Н¤¤ö…7ÇÔýùãêpå¢uFðNï2 jÎÐ,ÒÖ[EµTàj14YB«&˜)6‘¾3ãu¥ånŸæà?DÉÚLÅ2ž’+@«ªvÜzÃïY«©[+ ½¨m)íúЖ%)ûŠLøúg ÏÙÞ(jb§ßv} àÑ ý¢ßÚMðÈ2A)2N‡`.ÇT¿Íý@hh+‰¥{”aK“)ýÎs2Çc>O!Ži\©~bY¡¾K…“ÿ¢>ÕòrÕR ™÷GžÂ×â|Ú)«å| @žŒͶŸyN5ïúÃ0Ç,ÇûÑvèZ1ZÃ%‚DìËçæÛYžc¯ØÙyÅ*ŒL:»ÑÚàm=¤¬à¯¿…fQà,œ,±ÄÉ/§*ØW¡†½1è¹ëz„¼$ÖÞ#X¯)m?î-,Íù[Ö¶n1Ë=éÈ¢¿ BÈÛ'wfê\¤y=‰òìù˜oÔ•°,è~éâ»35~Ó!/º´ÙùMÇ»'X§.Í!ƒ÷n@ÞÞA Ëżr0JH¥‹ŸÎ=¸‡käýÄ{LÏ}1çÎòë¹`Â{ä÷s—ó€ßÏL$<òû¹ƒ.,Ë¿yYá¤d©ò“Pïæë¤g‰®Ùh¸¸G‰ò¬·"FE2íìòó%—G·ÐfrÉ O2³0›¯MùØÙå´ `åÞöMüÐ5òlùX‚léZÝËè/iœžc óºº-w:ÆsÏ¿å’YüõË—«¤‘æ*É2ÿT‚ëúF ±OT~Æå¼€d±cœ×¥>zxß/×oWÞýõäwÞ~±;Kk5òþ™Öä—ÀZnk„¼à·ØM&x!†>>É—÷Àï0‡¦¼#¨*²ËãdTú˜cÃFžg—²&p3ŒÆO;x]¶;F^¿ÛàÀºtyã4®h2Fµúk¨f8æë?G¹Ž’oz‰†Z1¦ªA&¦£ññc8È"Œª“T5ÃZ/#¸UUpbË+8æå‹Q§ *®8˜fiª6ê4FÛr9óû•·/6ÖÑLñVaäõÝÒs²–žL Œ„ô1§)ö&0,öIªV°HuCÃã`“p•®ïª ‹”LàQõíö=ÖÜ|PËf·_²e%QüŒüžÄûÍ$ëS+Ù¡‹¼Ýß?N5Ù€ivSÊxoöÚ)’nñÝŒ«·2A¦Z«]ÉaCœ œ²²l]çÔñ½É7­¶ Îèù›Í²¾úÐíÞ¾mäè„·|î?ß‘xËeeyekãVÚrÅþ Ùý—¼Z²R¹ÁÔ(Q&ÊV{7­²uH¢üço§( wÓrÅãZ³²\•®èžùá åGø“yKbnÂêmzX:ÇUñžŸ·=¢n‘lTW除g:¶¡ANDÊÈiÏîùÉ”,æZQ€Uþú5­çÛÆ»ÚSefÅ%BÞ’ºÊ¿7¦Š±ò¿ç¨bqÁˆ–uÖͺNTÀi÷ÈÇÇaQ‹*Œ|¾›ÿèeI4ÿñÈ×Y³Ù2ÓM¬Ã:oø˜>ò/'me–6Hj(ͶahöQßi¾Æ$>Ë1òƒÀ“é.ötC3Ð~ÛD[µ¬=©e5Óéô®aKæAJVޗ늡veVÙ²°wMx9ì›î1ÔÉ„þM…ÍÆ††ÌûK^"1ýc·ãK³jÄN{¸ׯÒ8qZ nß‘§â†â׊Šú&­š[&)F@Þ¿PÔVçÏ ”ñìƒ(1ùŽ¥d€ûã+¹Bñr!‘\ñžYå#9u½¸—ûF¼$go2Çγ¯=]x‘¼$˜Žì¨_æ…Òm¼®—uU/ò’z¦3ûäuz}dž–!¯ õËûóš]î™Î Ðî¯ÄÌn{4.ήj“ñ94øwÞÃH=ˆ^X{”‡ÜwA8Fº½kÛ~T¬ñí‡Ùí#‚àßùL’~œ×ÛÄ6Œ|TÍŽ/ LÔ!s£®êu*ºJMøÊÿ`N®gÚ’Yè^:¼u7… kƒBE…«G¦¬/gãÕêîÔ˜qà§=~N¹ß  £ºG,ZU×yÈè³-Ô4·!oÉ~‚—»1½2ÎÅ\‹V¼-lQÛW<öÒÀõôHH”+ìÍ´uh«K:ªŸÑó=æ¨ë¶uáK¡„|9È?ÿ«Ë &™™¶ºNW)ûID"žäÜ4fmØËŸR–ØÎÍÒκî(14ÿX>È• ¿È¢t5ùÔ{«$ý©ßA~á‘¿¼Â%Íÿ+àU dþK-óò%ˆ–ã Ú€ÌÃæƒÒ@Ÿ-uç~ýÂq"•yƒ‚èqEcõÂÎ"}¶®®0GEëãúKR›ç Fõãjß. ¸ Hóß>¦ˆ@C™Šü\-Pœg5í ïG"òÃÅ êÆwAÈ5Z1ÄÆ"I6s«Xé¥Ò¼½¢@ Œ"?Ý&:Ù"ÜM#n.à¯?NoibäºSîù?qÉŒ-4f~t°ˆ¥¢´÷cú˜€Ì=&ƒ¬€,‰ìr‹Xrîj©›½,©D˜õç»JE[ŒÁÃ8‹Â¬ýó¥iìboœFΣ¿ ð$Ga–õõ´mc"ÌÒäsà=OãÕ:ؘUz­ïØLâÝÎÉÖë¹T|Ð}Ey"éðo‡,»zÙKQác^>¦gKš®§!Ó¸^Ú„wS³…ÞÍ4[ l\æÆ6_Í2Ù¥­+ÌQÏǼ¼%› ̦TW©,ìÓïŒ[sÏçï¿s8!¿ÿÎó1¿ÿÎV†çëm3‡¹Æfa‚eD‰4êlÀŒABÜxye¿#ÁÚ'{‰ÝµWé*°¤e¹ïM@^Îõ"ó”äMI ŒÌS¦#ªXÖÙ^–ð‘MeL®¥s#}ÝÒéQ, °R“ã yEq7¥«jžg©ŒÉ#[«F4ä#544d‰Œ)J`™V·ˆ½X€~’Ș¢ÉŠYj%Õ‹ç.æ#ŸqóÁ‡ËšÍ‡šUÄîDÆäêÚÆ7©úwV|Ÿ'&ñ•ÿAº0[\Ér«TMè=_i ] {æ—îÂæ½ ö%Ù+ ´¨'1öcqÔóé\['Ïÿ_˺ºý Κh€ýöq» ÙÑb_I¡I¾ ͧèè>6#”‚¯$ÐΫè3}[ÅÑ>pÏ0ô‘$nú’™Y÷ŸØ„¡Ï"Z3Ÿ¼ØõÆUÁÎÆ+Ú¹Ó{Òè‹¥ÁóЈCm ]¨F›¥Ùë~‰Fö›‡¦+—HuF¶K—Öç×õ[¬¶Ù =h [+‰<ìm¶(¥ŒcûTö‰ÖGD¯7µ ´&YN›”rmyûm#÷ +ôЉèëÃVª$‘~õº¡_m|#ãqê™$ï¹½v›û§Ža;zX%°y]ɽFgôê¼Á4áõÀ ®µ÷¦`C'õ—·èŒLLC+oÀeæKÏY…×”ôg ž,’óMèú!oI–¥µ›±èƦã€,—, Þþý[Y97z<†Á룠åõLL,Œ7¶}—ÜqÙÙR, B^Rz`ãéí45¤‡ùÈ9³ËlU5.­%í²nñ©{½}\>‰ù:¨¥(|ÌKšžäTíë2‰b žôÈ+"œ:ñæ@t㻌§c¦_絡¿•Œ 󞤺y£9w®8ð=Rn¿“@‰¹%«¡yÅaGaq # Qáyû¢oÆ™ýêR"s$!!‘Ԍ۱æ#Ž5ò‚ÕÿVÒâ\4Ú¾"3BæŸÇT‘„G4Gz3§V÷ñú4ôY6#$¨ž wƒùÈRQÝ4y{G®9¼!ï Ò×L‘mºq„|Àî\%ýÒµº&݆ÏtϤלùA' :‹¬‚¿Ÿô2ÏLzB:/‡¿-O­vEî %„€ohþs=ïZøáè&°÷ý†õ{nì`ƒŠéŽa!™WÐÍ€L þrYÈöŒlr9u3\ÏfuyÕ.sYÈ …=Òæ5 |¼£°yꬣ0|¯<*Ó>†oHPªç(þî_ç¾Ö¸ *ÑuÜ£Äþþçöþ֡ÿ!säM\Kû¥,TàèåÙ‡ÆÊ[1 ʂ­VŽd\yÖŒwS²ê2û혳b¡ðÈü}ˆ4Ø!’}ižå')SÐïusMV}“$œÑå—Z{·Fz>­¡ȳ˛+¤»HS©Ëuc82 dÂ…¡~/—‹¢à›~ô „L„iuYmX?ð…ü×o)¥õ÷½à½˜¦zAÈ{pæŽL[É'¹‰q=ðï||j½M®Â #‚ ¾>±õ×ðnf·Óêm(—6JÑ0G%ñ*ݰxКæØ‚fîõKW…kžÝNN“Ô3CYÉåªy}× A+€çí]+À­V€€V Ï"£Íê^ê@Ѝ¶I–|óñ]U ðï|~U ñ»%Ò°OQÉð•Id\ÏHKîP%Wþ‘¬ iÍÀ]Í ãÛñ@Lœ3KNÄõ3{ü>4n<ŸÏsÄ“úéïfÛ)¶Á÷({}CrR}@;ÒV¯.vÑt¬ÁÈKR‡øoøte´ñ™!oW]´–³Óéê‚•ªAÈÛ'ä*+“……yÿV‡%ÿÉ ;³ãº‹Ó o¼ò¯$–k¿¹Ó~dþsjåí7·Úï!s´éhg“˜›ýØ–± ÈìZU1Â-ÄHå1!džŠpCp2û¢ó²1|ÌdˆR9Ó1fŽÙ%͈ñ kVo·—§›¾¾ß’'AmA„Kƒ·î*É‚‹[žµégþ_']´E˜¾DõÞ´ð}Ïó³gªw%ßÊúØ8D:käå‹+yç]Éá¾G ÓÉ•œ{Wr¨ç£†)nóH§îõ)ÃÈßx¤yÍ#•14!¯<ÒñHòú´FÈO¡÷pX»µ›DW…`$Õ»ŠÎé{rî9nÐååÊͲ³ÊðHfùcXÁ—3©öºVÛ˜='ÓoGÕUìh‘o··|߯•9R·ÜÝÛýwävóÇ«~fjE_‹U·Á•OQ³’å!ù°ÉTQD‚öä†Ã–¬'ˆ1ª¦¢9Îý(oMn.u/›çÝ÷¬U] ŸþDKõFj^6P–^à±ä, ÄòB\f²’¼àöÖ7g >æí“dB40^„d¸¼eNr6nÉýë2šÈIÎL4,÷÷h3ǼB³Ð*£Þrîš`yÜ¿>KΦj4è÷¯ß$gãa푟$g•¾ð§?»Ô¦ Ɖ͸ъ¶áÊß¿?Üò‚—ã&`X~ˆ¾®®< ³Lî§mŸfÐæõÙT=”öoÑn5Øf6¹ÌËBÆ+U’l i`ƒ2üsOlÓf©U[ ÷ÈÉ ÉœãÛ¨jµ™i¬@ȃÅéBMLCiÈ„r;ž£û©u‹ ‰µíÍáÙŒ„OÿíÎY'„‰f`|B:S kmcSì ¶pý¦Ïy·¸õl|¼n3è×¼„Òþž¾7©ž,ÅÛ±ž:(ï¿§‰+~ÜŸQÉìdÀ‘µMÕ²ž÷ûYäi+±ÚÇë1ƸGM*Z—¬å^— #‰cØÞV›f,Ë#“ »mæVh¦秸”îR·ñÅ wòã6øÇo)¸yi£úlÏà˜á‰ó!.ùÃ\Ï<ë—®«`` b*?±‡4XYÌK¹êþ/GHœãîãŽT1eȪ“ŽüÉô¥i|2“Ѿw` ‘ áÓ»‘¢’|l¦¥m¦)FÂSl¶\!XH¡65÷K‡ä“=Áv´ÝÈÖ¯ŸŒIËÑ&ÆAhom·^k޶¡Ùm [0y/F.& =>Š'9öùKq@¸Ù– mâÂÆaÜõ“ª Çã,¯-Cė‚Co©i®šèŒÒλÎÇßba­{ü-vֺǧØÅFpÊÕ~l`ž:„¦×Ï:“l‡,Å\lå6„…˜B¢:Ä=q½Pj¨¹‚š>’‰xZG]Ú[yi >2QdIú»œ Hé_ìrÀâ$I““~`‚7rXk•Ká¤Ç¨éŸýJëÖf$ÆgÚ†xz2â/ƒ/3ïykŒøcâ W6O[ô_긞ñ¦¨9#ë†^;³³¬®l¥ÅëFZ3ŽJ“ô£~c§Ò$V?üØ00?ÆhÖ¦çra+> ƒ¬‘¹¤<Ú“ôžÍ#x›‚·“HÓð!x›!äEð6;o{äEð6;o{äísTÔÉqlÒçZyйAþD:‰#üÏZHˆ•ÖC_B&‘Œ©tƒí¥Ðïb‘ÕÐFÇaHa£À>Åë`¯F³¥¯_âKÇZA|ik/~lí§sß kK"íEø5Ý C¿µÕ¼å#®´)ÇȨ?ŠÒÏêiË»Ï{*æÅr©»mŸ‚×#8FÝ6»Õ²‹QŸŽi¼Òú÷{µP} œ?ˆÕ.ͺöºZƒÕûuÄIx±¬ï yME-2 ó‡+ÿ ìBzîÍÆ]nbÃÐïêž½&ê‹”w#>ûï(‘È%º™[´ÛŒñ¯¯x`jH_`ÙóM?¡SsºKnƒr¸Ö˜F¡fcKx,ûyãÊ4{&ÎI$û¹ä×ràœ½’ß¹2Øå‘䓤È$–½å·îQ~kr–=çL—-Rª¢Æp,<ø ><¾QÈ>mŽqn”÷fº¦¦ UªAHrEÂÎÙ*HØ ™ÚRêF½ÌwºYBÞQci ã\gÕÚík‹Ø/¿u¦Ø|îè fØúyE -'ïô¹Q\Œ5“™^ròRqÎlÔÃI,y¥'Æ›®-½‹Ú:ë÷㲆íõ|Ë·ª¼âg:qx%%¯ç‰=éæQ–+St¢ª{é‰2ÝÞ¤GÒILçcÞ"ÆpåºpØÕ<œéì›v¬²¢óÖ !7vë6paÅ>V™ºrà/¬‚È”´¡õzÛ<ÐX¥ÊJŒHJîÏrͺ(×,‰¤W¯Y]4ù§ƒÄýK¦xó8gæ’)N12ùÌ?!Ég¦xpEöȃ§n)Ðv¸¸ŒŠU9ÄüxäýÈñ¨ìKÉ® ù<ìÍÈŸ‘››cŽ\—ê›,12rQ«êàÕ¹ïºWOeר¬ ~°ÏfßtÌŒß0Bºûó¿Ÿÿ’{Ã(êh'»!?éXükìïm„Ênmb×ÕrÞÁ§ß.$Ͷ=ÍÇ]_L²­HÌhw,d?¬ÕËÔíªVðédÄbWZR©¨nF„L"樷<3ˆj’0.%Q~Ë¥K ²sòõ—ªâ¸C¢amÈpt¶\˜ Gý’CHò~=¹Ôå¦Ä¿Ñ›»”6Å9_q5MÀR"_8U,+‚)ƒ Øuƒäû ±+²"4sYeCç“ï·T1oko‘k6­IÞ9¦ºTÍØÏÏDâÏå*k`ŽnC† ä—wÓDDH&€»I¾¿N±V‚i÷÷¹1 wq…ˆEcyº¢~­iÑCˆùþzcWTÁØf­2Õ6pFç ÜÂÑ Ì»cåÞÐ!Ýúù¯0ñǤKÖ*ؘòHòiLgó;9¥ÞáamÇ`µùNNuHhÑtÛWé­‡§ãûw6•¢ú'6ËU‡‘wœèå#"ê½!%Œ|“÷ì¯ ç®÷½Þ*ŒŒ¥}~k]#Ç©'V!äÅëØâ­ sô¯·2$B^leô§­ …²œ·2Šmê([$e·¶åŸd5³šg8æý”ßÒ·ôÛ@êwçëg¤ð¬DîÚh$ºþ ¬r(¶ÿYÞUU8¯¦ßïÃÒLÇS õçîëäÖUµ&4G꧘ãïyÏÈÌ5³*fx:ç‘a¨~³Œ×è{>εó¾×ç.}îóÌÒÑö¿pFæ‰Óg4ó™UBâ3jü•²m‡ÐÈ’#@å} îœá׌Þï§¢€ôH±ù/4NÆšaDÈ$ Ø|‘Ýf»šJU§¿pwVVþ‚ν.s²M†¡2‰íiaÆFknh&r ?ˆÑ¾ýÏ6Çž[ÜÏ´PÙ…^Æ#É;rñÈ#o8Þ _‡‚×r¯ò!ïWÈÒ!'„|\¤Ì/%ïL67F¦²6(Ã0×»^lv„|¾#ËePÝv¸>yä+Rä?]{6éµ.ÇWþëÚ¯†ÖÝ¡ßïÐ…èûQ]b¬×z^b›íçÕ.¾¤ßä£^¡äÐ(\8R)Àþ‡$É™ÔÑÔ=Jk)Àמ$¸3÷~Ç©oÏ¢B\‰RIüêàõCú£ ÑÀÇ$ïUµák3Õ Ç}mŸ¼›ZûlŠj¦8™Ñ~4rj¹$¹ ý¨¼/]3BÅ–ÜI‰®‡$ ’Ä]ô¥@¸OŸuy“ç#m™ž¨Y…—6ͨ»Ãn:!ÝÛë?ËnöŠ=“l»Lt9®gzòµwsúáE?ê~ªÿˆ}ï’’s¯{Ðu-å\@n&I¢íK䥻Еê):Œ$¿àÓÿJl`y„zÖ9Án³ª1ï÷5ç³ïÿ³ˆEõÒóŒ‹}€ë1åÿùïüéHW/þü¸NÒV–œ5}^éfªÈO!®ï#ÊŒÊIÄU¿¸ëªƒWNÈí4árH¦VÖ½q·öpÏ“Ûi“Ó~š~#¯ýóf2×QG&ïó‹ÑÍ/¬!Ï/Æ.gÂÌ/v„L>šš,P­F\õ+S]Ïô7³½.NÇ$¿ŠÂEÕÀ•Ii©àÓÏfNfhç,…¸BvÄE"ª‹(ó;Ü&geÝDÓt™„ ‚™ò¸ EÓsr]ät B¸“KâaªPÚLt $Xr;Mylõm~MSUïúg T7D)­µÌ03åyÝe žÔž|Òø4ã'ƒ‘·0·òÓçÖ)5 e3˜y¤#Áþüã ÌÜ•§¬˜lð÷|8䟲Ò//¨€2Åmó#™©›úeÅÇ|ª2µqß®Zmrf¶)ð÷|úGV†·a¡[¾u°Í®ü×5T™-nüñÈ®#d>«ÑŒ ºbè!:)tl*-—C}Waz/³õá´x\Qj ¼1ôv 53Fzú®¨¯ÉË5«ô™ñPœ²^LÝæºD›d!«j2ù¸6B,$AtåxmÝÚ¸ª!cíA”}¬~œÒ›:¼ ÈU­ÔìŒ"dlëÄÙê×B]“Xr» Ïíú€v­ðoF£ÐéGÖ@ìw€¦@…®Â]ô}©X“/V,Ðwº.{%ô£·Ÿ®À+zú_K¿G9ËxµR|÷Å–¾~@Tô&ß`:Ý€É÷á¸V—nÓ¹ïé w 6jšÄ6jî´ŒÚ(ë®>=~Ĺúþü¯€dÌ=Ïi“×Rž 17ÕÉÚ‘ÑbXd¾¾À FÓc÷Ç+Y ªšÄú«« ðNÍFñ8MšZèŸØS™UfñÑ¿ÄÐ'p^ëpZ~IÒV诀¡/dæí¬ôä¬[Ѭ‚*2a;mo•U´rζ $¶ýní÷\ë§%‡¹_,×ð6ŽŽXgl§é"ãÌ÷d{6aä”%„Ì¿¤^Q!]Î#o—霙~¤¸ÀŸ~?„2fû³v!Üã´wùŒ?ýªr3!tÑPc—éõdr®G¦ Û Ø«T8;ý=GVÍóqÌç)Eô ÏÔ–>]c$@ySˆñÆ0ñ§ß :Ë)F¿£ú©›ò#ﱇˆë t‰ÊûªËV‰kÑ™’ªëð¥ñbæ ô1;H@<ò'ïøtÊ+6Ѣßþú”ziœÏòuéÁ¤Ï}5e‡( ¿;Oîo‚3'WoŒŒ¬ÓOU09%÷“?E^yaŸÑ:; ¡Ñ$’Ôü¸€co? Ä\֒ʶEÈ[Øã°Üç‡);™Ó%ßñ÷¼ÃüÜ Gm½.]½UŽDb¡Ì¥×I Èä/^''dòÙCDa$9ïCéÌ{ˆ@¿~²EŒÃ©¾xc¾~®Åä2¥#§ÿZ0 ]SQ G>Ž•í/íŒJw$fFÖºXúsœ­úýÁ@Fâ%‹¬}Zx“5E[G3ª8G)8@Å6‹<ƒcÞÞbï+LZßÑÙßoo†ŒM Òf£ÔK“DÈKCF«ýa2ú•A/sº¿;óÒ±”c¶u§c>b/|ÏVrãW¯Žèa,€õÓ¡{ö!Ÿ(áÀ ÚyÚ—¢+òÙÊz~+¸ Jwåø˜¶z [3µG¶®l((ÇPó+í{˜‘¹OòuåjÙO¿ç¡A1«²_HýM ¾ÃQïggöÂÍKÁd¬#B&ïHÓ´Y+ †ä=¸môÁmÇ-úøÜÆ|pÛqÛ?~n§Zrœ}ŸapsÆÁÂÜßiKÎúÁšÓ¾Xà{ÆC­ ·*zµ·rƒÖýùKÊ*=J¯‹è4KÛB­-9‘C¡ue'Ñè\ ä•[+¯åÆåÑŠD -oþUÛ¸-3xÓký(s8æw´öãm’›œPêÿ؅ѬÓ/xN ØÎŽtWžüè™æ¬ë¤~Ç–%þôÛEl1å&²™K|ÌûUÀ±2QÈÇëøñýRèUµO-,‰U_ÀTË'ä°ª ‰U_ï„Fv˜‘Ç)2ÏËZ‹ï;hÈãvÖ3Áõ¬¤^ÃUPûy$˜¥RpäÛ^µý°CÁö¸½Y&Åv¥ pÒI¤»º(o,%? Øòè@¡ÑPÆf ö…$RSýçƒ/뀔ͺBÔ¬GFºU7Nk¬ª¦.ê†¸ç‡ %³ROr‡qÚ¡»r& e°©]Zˆ­f“|0â‡ã³GÞâRÙ³Âu©¬r^R¸ò¯7Á@¢XçU×êðk¦_oiK® ëseœÆkXëÒ·"Ð9z™——É«î`]J¿>¶3Ô´3 ÚÓ¯·´¥Ö>k%öv—l]26t{þÆQ®”ö°MœF$Ÿ{îÞz̘'VCÅÅ€i<Íqfš#øÄ€F$K« NÊ3ïÛ|ÏÇÓUzEfj©ï%¶ÉMmøÜ½?òŸÐ¥4þ53Nù NÐïðF²£מö}¹d]5ãÏw×ÝÜNEÙºù=Ó‡­;Zç C#»,ŸHlh…Â4iÐI"%Ý…9ǨhЮ’#óçÒ›C1XCÓo¤¨2ÞgŽäÔÏ|ãÝOǦ•CÚÁ¬CòNl2ÃÈäãTa8Ù·³ÜõwIÂÛgFÛ)NYJ‘Kh¤Ó(ÊÔ¦V¾ mËF¬ÝÖ•!M>ØÊºõŽÍy¬ø» ¤w-l¿F‰C×Ên"¤÷¹"ÌæŸÀ[!RÒ½§…°wäQa”¹·82ÊÆqz„uädý <¬íÀÚÞˆéi,R†X¥L}§’!ÉuL&5(=Iúülñ3[‹@¾>úH8ã q¤¯·@÷`ÇÓvSdÇCÒ×§@wc²³í™ÌòvmÓý±Ç’j«'΄¥ äã£ÎÑü¤`´ýüq›¿íέƒEn6o<òùõ«ås»B›ôüþÕò9£#“÷¤)cçf¬Â€nñüþÕò¹õ¨G~²|ÖIaäý“Z|œàé Ý}´«ÿ'ìJ’$ŵà•2ˆaÙûN³ê#ˆI @€˜duú¯ñI"ò[—Y× ‚Iz“»ë¨zW9*39¹*W_VßPÑm²‡FÌó,~rKùžúΫ:S¢RY*àã|E–Àv­õÍr¬ã؃0bîÞˆ«ò=ÔO^ÉEÝÇþT­îÓiF¸÷'½¢ ¢z=†VÔ£7½LbG"¯îc2=†6ц;‰þþ¸ÜǬa³Ú‹Æe/´$r$2c·.;VW¤;ÉÓ<ôp›2,s©¯È¶²›¢à²%ÓGÄ@l\Û¥(š£jaŸ‰ˆ‘p¼Éhä¶’jÝ„L‘p¼mÎjò¦Zn䈎7oÓTw]ûaÆWtÇóG’ik„|D-w§—šT^oÕ8 äÚè…adêX`'óÈê‰2fÙÚò¦Ž˜(gŒq|—œ…ªú@*hb|ªæ†-;¾MߨMÒ¡fHt=ì4¯;Vsˆ¬7xCóqa¬˜ÂhYÙzƒáÕW"Tz‚Ç“è4æ‹ÖÿÁäõ<é*Gœ]YIÚœÏYÆdÇ?¶féıż2¡þŠ¿õ­M}Ô[zì°#FdÇ«ºÐV“7D$Âw¬þ™@&ýzýÆêgE1hðcº“F,0pœºá9«¼ëŒ¼EÙT]¹ÑäŽtEÂôë —ÙŒÂVøXÁè åÿôël[|¡s2ªƒªÕÎÕAëµÊš*:æí鈞¨ä0º¢ä×ÑÏ ’~¥x?>ë}TΞ]ÏNá~FN¯é×ýìôêÚjù.öm)¦ßWÍ WÕVë|ׯ •ߥK@¤®ýûè?ýŽja9KÝO§ì4¢ñaM+ò®ôûöf—±ž°Úà‰Õ°.Åô¸Óýœå!D7tUd¨ëà©õ¸í8áMþ>Ë8ëqÝ—#¼­f¹yä™væúëú¹ó‚4°¥1íìo¼Þ¸§Ér&Ñs7£/:ZÔÒšõ¸„û¢°ïqC᜵„Poß“F´3¯ ø¶Œ:\ ï§ûéÕšÔ»DhݵAȾKN7GÝ¥z–ð;Ȣݥ7³ wéqºK¦|á®}[j„ŒîRã+qME¨æ• „<ß%3øcîÒPõ™a q÷Ü«5—Ã0yä=÷Üv6XnÚ.ïöZ d˜zôØFWršçùɉbkŶ5Åvà½Îgwv¬M3 ôXŽ] $:»èõÙ…ú<<ó)ý>K}WÞ=³[¡Û0¸H9½}]¤>`õÎY5 °zGô¸¿‡íMùcʼ"åè+ÚiDƒ.–«1ɼdQà³§A)ÕO;rI»nVÿ­iéqÿÙÁLÃãÓ~e““ i¥>#õáTMÕ vI”>ûã4fmûœ£ èYWô} ð¾çü SÍ#O¶bס<ÿ†Ü’ÿ7”Çò·¡¼!ÊÃÇüm(¯CÈ߆òðÙß å±ÓPžC>>ö*O@Oo§ÁqØnp§EP=2»H§8O EŠ…î¾Í˜Ææë Ô/ØRnø˜Iè¶Ùý•êõSŽÃ>ˆ !Ó`ªL+÷†tüWùÑ®™ù}“@ÛAwƒ 0 ”FÔ8s—ªÚUŠ×©"ÃгÒ~›¦“D²…—ÚR-<÷ûÉn&ôÏø÷ÏÒˆn÷¶¤š42»ySͯUÎòÝ®){µ~®èÝ®Y„¥Û „üH·›ÁÑ8èvïÜ!—¹½®Ù®_½G*ÖÞ÷áÓäëLJtñ¼”{¹‚µ!1¡ß”ÖqS9WQx!œ4ù¾h•ÚU±êg,ãâë•i‚ecrð×ÚÙô Òëy9$(š/;Y?nëNúeÅgOø¾Þ2ǤݲžàVê7ÊKKuŠ#ï~pR×Ó[»q Òy·Ô B>ˆeeß¹¶Ñ"è ð1Ÿ¡ÇéJ‹ÚbiUØmXÒæÇ5R±D\c¤"D8û ÕÓ½=JcíQTÌÄ„¼…}³sÀcŸæ•x—ˆ4²ï1b0ÆŽÓÍò u-ÃZ—DµÚÿþrX]O§Lö¾”Fö=^î¢vgßNN}…‰fy¨é ª-Ø4IÎò`nþBGVËÜ%2~LU×¢ª¶<ØU]‡L®U#ݹd-ÂýÄ„ÌÜ~q֢֜@¼I#šå½‚A\íïtïå*áM¾Ÿ<*g„ÚÔ«¤Ëœpö뀼‚è¡Uñ$¼!Ÿ¦iŒÍвái>‘Î5”C´eië’,ð&¿.Õ_ÓöM¹õžBÞBA»rs"ú;*öb•62{±û‘á¢ÚÝp¥õTË!#‰‚¦r®¥z§;øÖº–(¨+Çxé˲d… çs„¼#fˆ9dWôºq¸#B>÷‰!dòaÂQ ˜ptÈ÷ÓˆºÎ3qùy\òþQã4UÓˆdèÈÒ6ð×$ù•äDÂ;ˆ;–eåz¶´íçMF„!£éœFŸ\ïëPÑCpß™qÈ$Îe\þ® 2vK¿"dç2vºSn*ôÜ0FtÈ(‡­Z›È©\»]*Q•p?ÏÚîÔñ†4!†Ë²(BÆb^`¦ËÛi™ç©EÈ$ÓöÈrH×oÕ†)hR›$ÒüN£7[¾õøwfѨ—ÛµùĘºIÛ$òO~[ÆãL.*îŸ1òqÕvoĦ"•û!"BýÙ}fj¿MyLZKŒ#ä-"Éë÷ÃÈJõ› Vňõó×Έ8;ÎNE ûTí4"ý Á…¾kTÉ'ØãÒ3õ½rùæ*6¶h£^ÿud_W•m[’XJ’wm^ y Ñš*›¥:–šq¨gg&3ídæNT¼ÀÔŠS dÄ×´&+:œUD»ïÓF3ÿšÚ…¡,i‚‘ÖSZƒÚEÉÛüØ;§Ç]VÕ¡›=BÂÞQÑҀŠzõéu§³?¯n4«w£ñ«b ã¼ë84"TJ³s_߫Ȯáµ8òÎŽ ÕN…ÆÜy²t¤÷V¹i ¯˜˜¶0?Sor³Tù.ç`žž"òŠ×ü5©L1Ï*ìo$üÎsdåÕÕïx«~&CÈÛùwj‰&û;'ŒŒ$E±è,›a/Žùÿ˜Q§¶ò‰ô›|v¸9UNäÎÉgØ.›žOoòЋLc®ƒ[Z©nBí‡ ÇÇLßM W4ïv.Bf±$‡<ËF)™ '•Á æù¼Œ.ëÔ±7" ¿†ÄL‹'(eçÔ sO«r)=òy–Fs“*òo„PÏhDÈ[LvŸ^ýŠq‰¾÷ØEãÇ: ØÈ_Jš&„L#]WTUHVé[›#döN†¦át>$…gôú(CóùV†¦áGsè²Ý¿>ÊмEÞÞu…ÚyØ1ù§yÿ>sœ½a‰¡‚Ìôþ}‘>55]céÛ¬„ÞDÄóøc¯ܧäZ-ÛPã³§q®í&–^åÙ|<ð13È‹+ß‹,e%ÕGviàyìÿ&3¦ŒF‘bæ„0è²Ý!+?Ž*º¡Vñ²š‹_ûóÃ{W*5Äg©c³$ëJÛ䳦Zãc¾®f­ZùP/^Éðÿ‚!ÐÊNeéæ.?´÷°8=¤X̪uy¤qcì%dœ÷ç‰ôyÑ…BqDEz«;Ë+Ž¿éÎâc¾Ñå'ÝY‡üEwöô;³O4 Z„éãÓºý”&ɱÃþø>qkÚõÝDÖJ« äíê´>­R++P¯Ö>¾Ï\g†9®3Õf˜ >¦eØÿ±Ö5Þ›»d­Ê¸w|Ì &Ùí¸d¤_¯{åÖŸúGaB%®íHµ×„ÊÛoT9µÑÀ²üH>n^Qÿªƒbéã2~€›Œ4Ù;š‡]B5Í£å»GÞÏê§ÞÈzê7šÅX $¨\³Ö^;#L-vì?7?TPK݃b~L†1Œpj'!õhÐzp1A’òx ö™-êÚcö*ú-z¯ëFT?úìà ™˜vm{0"d#ií‘êfž‘wP…3 ¸QH!ËyùÅR¿Í©Mv£¾KO 9õQ}í²ë:õôᘘÞs&©4©@ÈÛ•Î,ô†ÓÇëœ:¸”á­{}pÑM±šQ ±¦<šÊ€¼ã‡B„ön Ø\©8³¡â„¼Y¤¦¸¤þâUT© \Ñóës#ý§ƒc~2ßbÞ| ¿˜ousÜ‚ÞΓ6¨}‹æsøÉ‰~ LÖ*5ÃÙ“èÚã»4kTÁ€ “ÚÌé.9äp Í¸Aòx#yžû3=Û1R›Ä«o+i¾žAá»òÎmKæmì(„L‘¡~h~Ôe1–3BFd_lÆ•ªo¸†!·ç¥YïZÛØ0Áºçy‹Rc÷/IOiß„L"uE÷½—5)‹½$GƒQ2emz¨µ ßyáÕ†2nq¶nÈm$ûÈšãßy¹nìyÜøHµ B>b¤s]žsÊVÏ(¨¾ô˜®¥a騘 š‰i°=3IŸqr° 3NKxîwܸ<¹X ûfd{vjÖ uÌy™É\,íbÁÒ9 ¦ íh-ê%4bÛ3Xz\.IÎÉ4M9B:õOVn—éÅ&7õäÃ3zb€JûÙÚ’H£B y,;BƉ¹3Æh"Ž}ç#GH±XÚ¡ Ô·²Z Û»ž!¤~—~L«+7AµŽ¬6¢z‚âc> Rï°y鯳²ÚV²vùôw^ë6¹û9ÏTô|?ƒ:K:ýý\³u(K|?Â7–"HßÕy]úA·ºa}žwG}zžq´²i}?·j!Që†F>/A'yÛí¹P |^ÔdÝØbßm¢"?!ƒåI¹Íþ¡â€e/vhÏZ›i{Øn‚Ñ Ôñ|^ D´6½‚[JŸQÎ6”> léëë7;t]€ö¿3¢ ác6ÍxŒc-áûŒ)h qWÄëã€!é×íCL¯WÛr¯÷Ò?ÐØwìê%!‚ZZÑ ìý¬f€VüeùNF&~‰ÊLj¥›õ5c$"o¸µS]MhGÔªKu1“ö¸©SÙ4¢V½#d ­§¯ì3![…eÍhP1yºiyZt3B&Æ­Ô³?ð1ÓOãVºþŽÙ§fFb‘“—–åYT´ Åâ×ã:fGÝ`ÁÈ–ƒçp?Ÿça—Ï””Ló8 Ж{½> U25Íõ¤r/„¼¡‚¾ù6ûšP¦Y†Idz쉤ºD x¿„L#b—#’ªc®t§a¹yÅ”S¯mÈbí:Ïk^BÞ?|ÅZ³Ü½ÉYä&v© hsÑÞÄeÁæ­s <Íìëû IXsÑ#“7žV‹@žVY í\ˆ³iØwpEÉ'¤4døŽò™Hûò÷Ú ¼Û¡›Åô«¶ëvÙuz:60è·ÐêóýyšÛYmÈ>f9'Ö¶Ü Ñ¥³pÌìÒdõè^=„…•y{›Ãwu”Ãg¹È ”ÀPš\E9 uSÃ3z|ÜfÝm„o3ûz^Ó]£qåjY \ûëïÂe «Möý…ÖOâSISZmªyð;W9j¹ªæÖ{ܼsãÉÓÙ÷©Æ¤Ÿ»ë4ÎRe)óÚzäí<ˆI½e=혤`ÆžEPÿüè+ªJ_¿˜©îÓÇLÞ^{ ×_Üwzzî´¦žŠÓ µ¯BþröµòÈìJÉp¥ÿ¦:TÒÃÝqFŸuSp¥Gé ²ˆ’áÆÂì§ÇÂ(‹ÅÇvYDÉx+’Ñ38ûów‘ hñf)âç_Óâuæ-*ó˜ÇZp¯ŸE¤ˆ÷"ó‘Œ#³°Ãn8^ýÀVȵ!ð4_Q–bšm´rÄÔ¾Ÿ™g}û÷qçßkH O¼÷ï“^\+»}«¥ñ ð…³ÛçAá ;äíýøïHz±bdEkN©}*ú†íåèŲ2ÕÂÝ[§=$Ø‘{±‡Œ²èÊKw-–lò!}e³Vù™J(FŒ| +a3P2Õ«J¢y]`äó<|l¾¡‡a纅Aá¿ùë³otSáâ^=¾ó_ï§×…mÓŠ¡ßш£Ë<˜v&tìr ½ÅP+*Ï×z ͽöµ‡&íÎûnZ‹±¨á[B”Ûl´vð†l1wmxóÜ«|]Æ ŸìLËßõæµ“Š˜ZŽxGl@¼¨œ¦yGH¨ßȦxKó6ŸyM2=½¬Ž:Ú¦ …á I/õ?rErMxÍñï¼GÃnÎR-bj_˜Z‰‘±V² Vµþò8và(æÏØuØšø©Hh™'S¯ÏtƾÏì£ãƒ4ŽYÞîg:£w„éòŽ’\†¯î~¦¬+du7ätÌäÛ±™I™¾EaJˆZn÷H¬ÁŒ`8O+Mk›ud×þ¸\»Ëöe+÷Q-#ð%E»—ÉëÒ燔Åùav¤ÿ#ì:’×±à•ª%’’–?½˜#€è0þéö’j"zSÙ-ð\f^<ÂZq*ø:^8‹®:Ï€¦­žâ½.䀦 ¢±+g¢oz‰÷¯!à’'D3LdóXû‰uÕNê T‘ß“ÆD-måëab›è,·vh‰%¸+2b le ¢«{êlúN¯§MäÏ﮸ÎÍi×Ê4 Ýùý†\rñP^=IºmyBMð}N¯€l©ê³Q‡<¡¸ï½óTø]§\3+»ƒ#ä |¾ÛÆYr«PªšéÓ#Aô¯t«·þùZ4¢”¹<2ûî! ™ÏýRA·&Ó`ׯ¹Ü½øâÖĸsk‚÷ó^|sk’;™×|Ç<ÒÇa®ËÚøïT‡>Ï ±šßS—Ǽ'·íOÓXrEÞ ¶K"6‹œ OH¼¢>ìG'o þ¾?¿Ü%fî1ŽUùºÔ€ÃgÕ4îG …ââ~eî'‰ªôù=©î½‰y´¼:!~£P€wãÞô]%ó,©î9rª·¡ÐçÙÍâƒ&NU.Oði‚Éåˆ:$!IH ¸›AW²J½Š@.—úOýM{‚/ŠwÝW„ü§}$ÐÁ “}ƒYržëëÜx<¦uëá<¯n¾ÖÉ"ûe•GO1òöU”’Â.“ÒbÅÐ"– {=2{«zgõtš(FÞÒ×+u¶ÏùY1„Lz§ï™Ozéæ•‘,@Èì³´'c³™J^<ÍüJò‘ºXvÁypÌâŠtö¯:üo¶¹:æyEÈq.:.ÝqÌñÚ‹Ëp¸"ýÖmU×ç€Yêïîjvú<‰âržñy&ž>´ñS¸ë"Õ¡*ˆX"9À¹úÁE}žßçYoÞ!£ªiˆ:‘ºQèo³“+:äÓ—Ý Õ4q6 ˆ“³Çu´ƒú¯N$·VÅÔSùuZäÉF¨ò¤ž"Þ÷ʛ߫ªŠÚýù…`òÃ6¸n•SuPåÉ^o”S'%¢‘ó´ÎWd:(Mƒ˜]¦7cŽé ´KåŒPòf*à%%Œ™\V2BfH2€†§4uú))„Ì¿<¥yÚ©@ÈËó´_§}ž5 B>âSòˆ¾ö­7[,ì3)…Ã!½(¾K¤Ó§ÄÇ„çy9Ïr:ƒDH¸ó?Iéß[FÔê¬ãg°Q Ð4霅Õ4ô•„ZÞæÔÑÅÖ™‚_ÇR ¤«Êia)xÁ©ÄRY;Ñô#ïI|ã©—Ù ¢Ó”!3D\²ÁˆŽ•{Bzp`õH'×ëǪýü^K·R1úœYнí»Ù£Eº- Yà‘`ÈèfQm>sÖ¢×oý‰=uœ¶¢ß=­í̬1ZDHÛ>þ«¯ÈÍÏ™;ßÍre« dÒp碯G6%#Ø@÷-¨ræ){s­WyJFcÛ%eï¼¥>‡~Jö!¦Í•é=·'X›æ96•ÅLo¥6º„i–è~ú|VtÔ™,k3Ú¡Y/N3«¹ÙG(ñ½9•Ômp*‘ÊzšÀ]më‘ÎÿÙï^ENÎßÿ¦ãƒÔÔôuÈ—;Ø<¿ [xœÏwVvï6d¥ïÓ0BPŸ¿m‰½Ëd·yo™ê¦N!$„–~ÄÓ¤ûŽ¿-V|ÌÔ¶Ðj‡ÚW«ºr]ñ1³0t•ø¹ }Ǫšûyµüª2p˜åˆÃœ¾%ˆÞÎð„GqI×K‚=8>Ùù¦ bqCoñ‘ŽÃL»)¶3n†Ómj?Ö¡Ä*Êv„Ô¼HÔPMøŠ F—]´Kü:Š{òëN;Ô#­&^ó~ÂÇÌ0ÒiÖdß !éï<‡™ú+TïÞ !ãæU‡6ÖÂeS®æ1!ä5[O ¢V¶„³G>¿¸Þ;ôð%ž&ö+6÷ÓUê+ãæ»/Á,4/òK Ö¬ œ^—8é€Á’ùE§TBÚ‘vóÔ½›<᥄AmWÚÔ›¬^lç6Þ¥_ZSB ÈÇï*uôäów•ºØà.žßUêl3ú‚üîµÔC‘©xýêµdhéù}¸V@Û:úwO3è²×jÒW4€.{žè{¤ï'hdÕêÀaFÈ„—òR˜þ#¨E䉧IäºØdNÝQEþLžxšücG¥-ÝÙîG:\¢{auâiâ¶hÞ:Vw²ÝH’ROûÜÍ|õ…¹l´Ç¿þH-/»Àüì”NT8F>VLë™õÓ¬6~Íï<õ4¹ògZß)/wþ'V,ë@œ2²ÂDz1øù?ïR‚­Ÿcdââ ¢nyÊðòZ.õÒ¹$ß%`Û~\úmMK]<кžPá_Ïb¼V5^êRND‚ŒÌ?¼ z¡×7¹„ñ©bI„AÛÛüu °ß\¬ç?îèUvvG’s*Ea3~Ü;Á#í¯9±X3|Ü/Ó<0«!uh·Ê•¬é'í”ïaÙ*“¾Æ`äìbÿѺ1.3ÉD¶uêGÈ[˜E-M/Ü ÖžFz/vg®ý51`Y†YÔe¯Õ"„„úÉ*BaÆ3ÐÜ÷zcdŽ‘î˜FŠ¡ÄWäæFÿÅȺ›a˜ðyZB§Ý<Ê0i·ìþcèk|íOøŒ›`ã3§† ´wþJ´ 3:G1ç|`¶øu0>U˨Ȉ‘‰ [Ó†m{-™HÏ÷Hd4‚ovè}¦‰_q"ªáúþФ,«:š!‹÷À޹ÀŽ@gê‘ÌtÛŽ¤}˜ú⇭1üñ²ÅÈgR÷®¿¯w£A§Æt¯ò•Úýx·9¦’]…ï’_€ï­k™(÷:ÞÐâ*emã„ô7.<¹Ìþpˆ+X×Âæ]PÀ`Ë>Ad—XþM$Ûu1v¸:‹…Á´”À¢ÏÓŽKØæPM–†.TÅ[ÿzS?ªÂú-M×þüù aî½ÈJ½s6A3þ\”\iÕ´}tÊsœv¹„À‚õ±Í]uÐ ®è…z6«¾v^‚[þ¼½ÇÔ´óº@b— l)ÅG ®¼h"P¬Í0üò¼½ »’¶RÎÿz¢?ìiîÔÄ¿¬@ Ö#sWºŒSÖtU§BÙ.¥Ïxí§R²ñQçrÕcq‰ëL¢)g-võÌ[^u™ªÓ.-!lã 02 q#G8Þ«8÷]XèŸx¬Á áZµs¹ëx¥®/ÈÛe±ëa±ÛƒgBþFuiBt]kDÔ9BÞ’+¢îÚõÂ)BÞÓ§’·‘a¨æœÀògŽ”yŒ€+èÛaÖ© #AÝ‹˜¨ÒÌ:/å)BQYÂÛP“°r½ÇC‘§t%Xýo؇½ëdlQ<ã²è„<_?wɦ½Ü>¦ÒQƒ°¯ Ö[ìq”,L ç‘?ó ÉKVòúð©¨é„ ¼‚}¾E‹`}(Hy’À“ÌnBèàÙcê…n.ï8B¢WÄKëš¼|Ð/}ƒø±±€~ð{Åå ýígÂ7öH'\¥_&® "»çëíqï²~E&6ðª^²ø¥s^åÔrun§kçöõóÿ:·!¿unYÒ¹}ý|V›¸šur»Ôðç“\¥åI*„üœ2'‚»—¯?ߦiÌ,FNø×³/QªÃÜæë²y4Aú„҆Ϫ]ûð~¾îï, |ã=Ù8_ÙEž&èùéÍhdrˆ<åP\#&nF,!xå_ÊVrÑÜy8ÏâkYÀÝ%ˆ¾_Å…ÁþQ7 ¿Ø™XC*[1Å“U?LHö_7™<×IѨ\Ú}‡Óë8cWÕ€Cm!³D²6p=ÌgÌN0øòÈüó$?cUœU~=þO&ÈëyÙäZ/˜K×q¬WA ,y¤÷ôþ¥ÅâççM°¬·rit¥ª¬Ø¤Ž€¼|GÐó0Ý{ÅÏdªñžyt€ÄŽÄùÝûÍX® 9V„¼}ÏQ‚b‚G&a¥ÕÏ]þS‘S̾ç=GÈü{>qâ_/B˜î‹QöÛþM¹Ùi`#òs¸f•W|ÌÏáš~f™…åÛ]QJÊŒÕÙ—tBvl߈ ã4EB äX„id¹‹m ‚"EâNãÞÏðë¶3ÔMÐi+Š‘Ñ¸" @¬ŸæÀú“ÇûùxÛbCÙª’¼núE"äí31X°¦a !aý4Ä!×qÙ¦Q¨ªb3‹Õ¾¤kÔÖ9£MßÀÅàæ- :u ú^ÅŸ'¾K6XlÝ,9aûóBxÛæs·Å¯ø…D5–•t6G᯽Ä!,v|º ³à£‹ù&TíqÆ÷\} džûy»ªÆrìp!Ç mÉixÅÜŒú ëFÄ‹H[òƒv­÷]©Í[U•mæ)n?Øo² "Àç)G½€ÏóÏ—;ï»wÜ¥Ûí×î9áÝ’.8¾Ÿ:9äíÔG¼Gy˜WVšÏŽy%ÃǺæ@¶ŽÖîüU£ÚRœFõ1󦇧™gþý”ÿ¬3%Ùγe³"!΄‘'{Èø2ò¦Ñ·!³PR&53£4§ã%ì qæ£K ¸Ó)!åƒKÉÎ.È[LBÑL/±=—úƒSyGߦ+}¯ã¹³–Ä瞌Ç[}ÄÊ[GYBu¨àÀV¤ä‘‹×|ç¼æá×±Sœ#^ºz_Œ¢ÝyûìJß½óþQBµíLa­Ki&ŸÎ3®K÷ŸßÏÚgEâ=òñ<¯Çü~žq»ÿAd±·ª*yûµª:‚CK‘ºj€;KäŒ; YB««¸_¿Ý “›*03L~=€øë¥­˜à,w¥·bøŠïÙÕS.h*S±­lªB²]$ô 3Mâ͵ÀÇŒî^ΗÝPh/;?`"­HÈ8¾š¨×¯lŽu–¿ÓÑÄÓå73÷3z;¸Ê³_êÌX)©¥}À×þHV0/­¥×:5 ±øÚ­w¨±˜é[%ìG 'áÿmº§“;$ ùW¤ü°oº™,S¤sŒ—Rþ®Uö®VÙÃýÌ~•&lˆ?‹‹.T _ø˜ÉŽ@Û0^X³N ŒÌ>T5Ùh„b=$™àÿ ‡Tɯǵ0.ÈÛǘA¯ŸlŒoÈã·5™Jh-‰‚fnlÝÛ6#[+;E2C~z¾my’SÊ2ÅŠdÞ]Ù % ]kd]ž‹„êÖã2öQ×~]ÒoÈÚëÿ8`ä=Ùa}¤ÊŒ Y?Ò@ü+ØwÚN0¹¶ú¾×ÝÔM–[<~› qÊ.7Ô1Ý;#ɼû;#¢e‚Â[w#O\pE­s®è‚[$C×XXW_È×#¿ºàRðœñÈû'EEë&Xçã ÷;ò<bjñ¸ ù95$ëë»ueò+Ò¡k÷~ú¹g#̲-‰ç™½ïÚá 9u|!¡õaðØ=ÍÉN¿Ê1¾KXLÚóç ÕŸ"ø˜Ø_ËKþ r.=°VŠGqÞ2Uo»†­g«Os†¬ç‘t˜è¢aÝSp)Æ%°=òžÔiý,ž^àuàÏ6Ò#d†ž‘Ë"Í3²ìá€ü?2‚'Ôëâ<ï•¥&°Ófñx]†xBÕhâíº– .yÅó2 bé»N<‡tG§ƒå !oŸœ¸ê®äÓy\2{ëò÷P‘ØÖÌÓZŽø˜YôIv³á†ß2.«*OèA?ðL+¤åÛº3®Ùãc™Úñ)·&:©¶«ñ1§±‰.`ØÞ½O§œ6O—ýõÝUûÜ{Ó]•´;ò•:.ú¨Ò (4û¸_îüO|™\TiÚ–fìw¢Ç†¡¨·Pg'c gu]aè-B©Nì䪥ïG½G¦Zë†P³Ûÿ»’]ÉQ-øK7G;—µ%Ýþ`ð<úëããLgW©¤Z„œÛÀ"b_A¤ú™^œ6¢WFƒ”c¹õäRì|]íPó}Šm›B6†qî†Ô^aSëC-'„¼éek^Ï«Ë¬Ž«Ë¡óùh`, lžÈ8Ù0kš'õô†tL…ÀÝ'Ùó>tÑ?ã~æ_“9òb“£ÚçÉÞSŒ¼ž5…Ip¾~FýÌŸº^†º^ÒçɺlY s Ù½4Áv*¶0¤3Ús¥Nþ{8צ‘€¥‘¨+½®ƒ±B˜2hIK?äUÍ~l¬ò¬‚j}$ o¤æm^µ1ü]WÂ[˧§Úÿz6­ù Ì¿g, ï%êÌ7¿ÑMíq†¸H>BjƒÀmSS6Ô¢FÈgŒ4v°ÍÔn™Ø‡j±AÞ¾Ÿ6Þ5Q_ž}–o#B¦±ƒ§Vb­æ~AÈW8‹x­ªÎóþOÞñü˃^€kÑžx?êÆ^âèØ.N Ê iÿþ务&5M„òRÝ:†ÞÞ»ÞÛ¬­ ¢ûÐ14Ön2É ÍZ²¨Åâp¸Âm›‰ª*«r^çËú ¿^×B*h¹W{–ahye;[ÖºÎ&5³ƒ×|ôÐÔÈCª£FYyKÜb/7©öQïšá¡/U7 ÷;»3«°ºS÷KÐëO ♢æ;dWÔ§þkh®¡•ܳy! ‰ººqq™ò± èýT½ÞlÁˆo­à%”B_µ-<å>ͨƒµj\À(òúª:––H)¿q·´ “õñÍäwr[%]K„ŒH×.mØ‚ý’3¯#Õ¦K^õŒXCd…jãct£ð;ÖÓǼ×%áµ>Í3ʾ¡}Ý rEÈgŒ$®‘l“‹Úò8¾f}¥¥ëÿÎÔ)S Oö™‚V^¥Ï&`i²vælYð|¾b¤ýD42Ï™`‡™ÿ æ ¾ó©í²‘ŒÒ%Øz^#Ëz6ð¶ö4Š|í×d¼aGYŽ~å{Ý™[#¸dò¹ZO2I)BF&oÞ›ñ…¶y6ŽB¹hnÇ›G9Ž0¥÷c'›«é0.uM0êyF-õ¡{ÓÞ§˜ftŸW^²è‡?mêÓ\fˆ”Qó½–ܬ\å‹Ò±Õj¹”Èà÷]×™%Œ¤kªÜ ò>_8ó`%ÚMnjÙÚœå`óŒ›ï]~ÆêcNdÜVÔB7ßÿó×Ul…në:Å¿¯Ø.Æ"]ßBÑVÝÂCkõ+²³Î´Þ¬¦îÖ¾ïÙˆïóFdšï͈2ʆœ„å.=]¶±›³6Œ(}‘ïlÙ:Y«¨_3ñ­ò¹6G”¾ÈU”º•3ív†˲qK”NO¯×ÛÙ­r•YíÕ]–…Å– í©Ù×pg1Ïô¢¬Ï×ëC Í÷5«·q†0²d8˜a¨G®b y¸ÏÇ'3 ©^¤‰Í !Ÿg=™}éߥäHf0vž&/§"àb_˜?_'™Á÷£6Ä÷£N:yfŸ ÷¶Ë#?õ£Zm èûJbŠÂ'"ˆñ&Qïýa4MœñÕ³Tô5üz¤?ââ-Rë;°¡ÞÙŒ×HßÁÑçÕú™EF|Il´à,%ÍçáŒUr Ú;ä=¦äÛ¨V›v´ã¶QŒ|Dòôî×Ç•NÝÂdW!$Òsq–DdãÆ7É2‰ϵÑÈfuŬDÈÔq™­J›è[¯Ç2ßñØ_¶âù¯=´䯶)¸ÚðÌ;×Sa.êÂq“¼£Ô» xèÅ[j¨Ý¼4t\»â0£fCüû?í3‘—ÎV}ܪyÎ2h4õÐú–LÖIs®åÂGŠÇ¹Ÿ”k(¼¤“r ³å(#'?ƒâií„ õ5Å27^½çI‘зÀ‡49iï-ðù¡¾?´À;䇸þÐïßZà9B>"WÔ’À¢YúÚ.$y3Ã5_H‡£(¸Ö[ÍTX[yÖ^rùù^®‘~M"Bƒ-רc]¢T‡6Y0R ä <}¼DgÓÙÀÖr¬ð5ƒÿŽs}R¿Îi×7¡µ'‰ G¤4H†×¨éÏ%h$Ÿµ€.•y;C¶Ôo³É%*ÓéöT˜P-ÚãNŶùøŒ‰ýIÆ…rÍ þQXð.×swX1R†±ßp¹J¬m4É RìÉå~‚ì²ÇÈeO¦ËžÙ´†ÝOÊž¶˜9¬#ïçHx“/a±ÿè:…k>Þ[Mm g1MrŠŸûó ¹8$GÈëéû™‡÷óyð»=¼Ÿyý&œþu©ÎvíØ#äãyÑóŒöÁÆ ®™ Æ ½.ÙUJ:©ç9…ï=ÅHËsŽÈáØrÁmËÆ7ÚúQr[ózóéË$öLqx~œQÑ5¹¦çHTtMùÀ—þHm°©NžŠpTG”‚wgûJn?çΆz—°/¹ýœøêÆdci)>¼‡Yº´ˆ«²±i‰q±‹|)ò~tKl¨sKä¢ÝB™îƒ[¢öOîòyâ–8¨yÂcOPûª-Ó‰¼cÖäÛå°w§â¯Þº®ÕP dÐ’w­ æ›Ó]Mò¥œìd¹·YKšªÀ¿~÷aŠùŠÍ¢h|ÍgYz=u‡ŒõÔ‰{HËFêBì3¾æ3izA„¦©y¿4[×¼¾ËNZ‡¦%W£ÙÇaAÈheP»ŒùÞ55hmº|.ò¯ŠVVTµ›ý¾3„¼cÕyW„XÕKÝe-B†}ÓÉŠXÇYuLîXƒ‘s³‘?Ñ3?”u¿W`‡ ZòFÚ¼ÉU– yûT‡C¦ ÝU×…ÞdÙXä hó;äëÝQgßcÆ$¦¼ ¥À•–ÕÌæÖºˆò"Œz@I¼ —Ô*¢áü» ¼KYdbyû¢ÿç׺ÛãDÿôÿòƒþŸAÖõg›Ûã«þ_úy°ýØGÆhÅá\wÃþHÆAÌ&v—¬›éNàô‘N>Ê·N ¾£CtV«1ÖЖfYá÷âÛëHÞr¹ŽV;íª£UÛ#ä5ö2² $z+Úê(š¸½ŽÞm.Y«öÍiáL.3B\«k‡˜ m„||påÆtt ;BH°Y2GéÔé²Êe3ïB&ŸõyÔI€ò!Ów 5KÖ#ÈèŽcX+vjœ°…œ‹Bñ7¹_Î[Œg–O]‘×O-Æ½Ø‹ÐÆ˜Ä”—Omw­„û¼Ääl¨¡%÷7}çÞ ®)³bË|)‰éÞçÁy t³`ó Ïè~÷Ï5J)*RÅà}Í“ûý°&›cˆ‰V!êZø²t‚è #¯ÏK¼ìúAmÝBÆnl^ŒK2l€]û~?øRp ”š;vDB©;ÔÐVºµDˆ9Ÿ2:Zi-mÔZÇ7>0õ'GÈXÿÄ7êJóÚL^4ÂÏü’J1³¤½{IKeu€^°z±Íú ©8÷" z+Ͷ¹¦Ú²‰×uÁñcºÜÞ]Þzíò&sÉaü³´õn›`ÿ¸?Ãx”ªõnﺮù|ó¬Œ,7:J*7 ˆëÒ°fmŒÕsgå@{ù5Kðœ’}¯VœL¶vÿ–!¦„¨{ȲKøõù8‘Aj ¹'‡ÖW•¤}¾¬Ϥôç†@¥q2xÔØqh›ú®"l™ó!¯¾Ý4…56jÇ-¾´+BÞÒü´BkuåVr>2„¼‡ß (·r“»àF†±—&Ú7Os,YÏØïÿ¡÷℘tsPÚÒâ Sÿ!dßÀZ¹a|ÐÏR»±uI"7ŒO’÷ÁÃ+‰2ïúY5/¨À¿þ8œ„×3W²·]¿ˆ‡]OFÔ¿èú#Zð¯?ÞOú¼¨Y‹¥ÿ6·ï#‚C^Ïîs’_óvrŸ ‡"¯CÞãS £ðRŽ]×CŒløò¥WåFÛkˆ 6þèNs Žv½ ˆùIl°a¢>W hÖ™e=©B¹í§¬Ü©Mü«ˆ7ÛÔ™qÁ×| ïúšê.ûqƒÈüö¹¿0¢N«ù0™@¶¨I£ Ù®žÇc·~·¿‰‰ºkn´,¾Ï×¹ˆ?ddÿEU€5äñ_TXiOg…+¸h²¿ e·µñ›Ü#ùâV> Úî’Gú’F§©‡±s@¯‡ Ú¡“çª:¸—δȕØ'6R¼ü‡²—YHbÓŽBÈ*JãùE2qÏëYY€žÁ,=o=ÇÊíÅ£ŠRVQ€Be‘n,ù—Ô^#²(X'åX#dLZ4û&ѧѾ‘ !-‰^÷Õ‘àP­ô}|I0íº½“ùRÈA-8ðǦŸ•ùy¨y¼+ó3„t­ÿF¾æ¤¾¨Ûœò›†?GÈoþùEÃNÀÏ{”»qBÝÎ[°’£(ÖÞÏ÷ÈÜ·'²bU™7 ‘¹þÞ]Ñ\}ï­®]3„¼½¯Éú׳qlgŒ¼¿:ú\ªŠ}O3(´kdT¯J”{S¶!†F íh¥U» ç¦ð5xF…—ÓYó­U±GgÅç÷ƒü¶&ÀŽÓ %¾æ !`ž®Ú²‰ X?ŸÏs­3+ÃWœœ7ŠHã°Ìòs£ˆn)¡pbyW ?Km_©Q©0¬KX47Ž–®Y~¥»{ä™(?àt°Î}½ïùY°Øk¸æ°Ë¢£y§"ö|àud7• ¢Ù¯!æÛ·®,³ZýͼÈC’üà\­á Ø lS•½N"$ªdø|e“É’æ|BÈx¥uB…ë²¶÷}#äÓ^LÍ£V«Iß#DÆ*Þ£Óu–7êÜ¿}'ùDHwŸÕ¶ÉÁXÅrýíØÕ½ YÈ»ë…cS¨7¤Õ±ã´"ä+’s½ MQeEÖoó†gþ'°jgq±–mÛ’ºlñÔ_"=Úíu&øÎóêJû¿j[«5´©×U≠±±ÎrÙJc3dMSwór¸{”¶ë´J1:¤4Ϊ›¼²ºìÐÔ…'=yè›Ò¦ÑÞ¼åºãWê’œõ´Ð Öûˆ>ø9ž›àV¯Ø3\G½vÍ3ôVÒ†Ir{3'pþÉÇ=$¹Ÿì!ýq‰ |Ÿ÷·OçúÃ\SÎöŒü¶‡`äÙÒG{HpM9ÛCð5¿í! B¾`>Kß'Ó7m»6TäpÍŽ~‚Ĉ¦J¯d®{„¼âþwcü4ÍsQdä„"šc _ƒ$ݱ#äÝv:cs¡*˜rݨ‚¯ù8Õ*"l›‘xYGwrœMm §KD^üu™ «³¡¢N5M᣻¢ó´d;¾3$‡©³#R“1žÃé228ùóï_W ·Uf–¡{ר-‘T¶ÿ}Ó4¹ßð5£æMoS4’%#ÅTÂ>Ÿ¤Q~5öÝÔ³bèK†`Áp~¸ÏgD¿6¥A½ÚlY³Éõ&J„%1’•RÖPSHÒŽž¦ÒÚÑ®î ƒÜr¨DN¶Ùm7Úqw¬³.|GŸºJ,³ÉšeÝàd¼y“Æ]´+²Xò¢ŸƒaŒñÛ5›òºŒ<_xÞÏ7¯cÇq´Þ¸Ëp¸&ò:&ž´ªâŠ~çøšOLE%nìL02 „ ޸† )æ9Z½_HÙÛùfSWÍáB@5' ^ÇžÊàIKµT“Š)ñÌÿDåâ.äÚ”Mà i£ÖêB“ä—‰óLP ý Å¢‰A’ÌpäÖcTBu«Œãj«9]¼ÝY1†?ÙÅËPÄL/g%Ô©¬X\BžŸK¨‚¤×ï%T Éž뉚„œ]tÉo¯÷®yû¢`1±q„t`ä—ãK~^×g­X¾¿4‰X£â×ò¼OÒ´’UŠ_óþ±­%£r ©‘ô~–8´6k˜ùljK©5ïÈ¢k>Î\JÕ|‚tá=¢ÖÍw‡ªŒ‡_"M#×Zíú¥÷µëá(’FZAŸtOexîÉWÝÓ–‘’«#Ñè4[É3BÏ4lIöÀª‹úFG¢½XŠÀÑ%–V»Ö@È»á\ÿq­&1Só±Ì4/jFÈ õ+gQùº­:9°à=O)×$b#Vå žfúådUë¶+xš¯CòÌEÆÔ(LSüËôççDµšyuí!?hQ3¯™‘NÑó×½Ÿ–¥º¶+͹_çÓˆ‡g[; —i¢K?/ûÒ¶B^?ë…êœîÏ`il*ôÉÕNiÄ®óß»ºE—–~O‘³Í›*°fÃ|ÆÁ¾ÕáöÚÞƒèyÐ_Ožë%÷àBwõuô^;9ýÁ*:ÇeU…tÛj͆)ÌR‚¼ÚÝ)Ýæ¥ >ygÇ4¢#~[å){*š¢Ý<šœþ¤¸­ª\Ú’5’åÓº•0öH%ÔîN=A7K˜‚QD\úë½z¬Ê]ßwšz@^¡€•%2“Œbd¤ú_û³"g9'ùï|DG²o2h+rV«{|¹/ t¤ƒ if$áz„¼½«À8$ÄGiDG²-úÞ {Uçä–òj©=òzp{ Ž´¥ž{%²¢÷ÊyõçÏÜwU7jÏٞÉÚ!oQÓ—ç¥,U73&»Ö#o8 Yz…úuÚãXP„Œ¼?këdÕLz{\x—Ð48±ø€×Ñü'2ÍCÁ‹~FH›×ýç¯EºâmÖñ¥$Þn×!Áɵr¿N—q$eQŒùô:¹g#iqqÌåÐâ±G ÃÔ•>¨þŸP[Ü€©ß íÃ4ybQŽÍ(Š¢@ÈWØe¼ #ÛiÛ­ji³¤Cx¥Ž““mS«>'C/Ÿ rË>@¯µâŸzë¬4ojâêr;iþ‰âÃ4¢¢}hé‰âÃôr?‹™Š—¦—ûWlêáû|ÛØœf‡ìUˆ°QÙ`ä© ˆºÏ!ÿOØ•-;ª+Ë_ê¶± ûývÄ>Ÿ & HL±¿þj,TØ^ë5ƒI5de"*Wã÷Й*-öižò¢*ïÜ—ŽCÏ“$ GÈÇ"r{°ó-½k/5àŠ¬sÇü÷ë2íµ÷ûµk¬ê®y»(-3¯´Ìy+\3¿j2‡¯Ù m»ad: ‘L×’·¢R-BÞ‘JÐ[=vÙ4™ÅšˆU¢Ê"#[ÆI¶Ñu6 Ï5_ΰ%«ì‚˜T#Ÿ)ÙÏï¶} ÚNcùúRbçT~žŽÌ!r³I`çFnª‹ÈÎx«òszɽ ±ž¿ýïÑVS+^¯3Ä7·ßHaÛŸs>;µ2{¨ˆå·Û»ŽW¨…Q³ÜF "ä·w{Å.¨¤RÞU¬â.’ŽÌý{ñânùÒ÷F~õâf"Vòtd.ê!Dd=&ød†É÷u,+;¤<‰‘˜ã w-¦'¤ò~V:±S· Ä>Bf1n0[]<º»¾>T«/÷ù@ž_]¥ +éh«ò™ÐoÚ.è”Òj0Ûw·"ä+Ùm‚4Ÿ–´'©& s¬âŸÌ&¤žÏ7[S%$I¶&«uåyûècR¤º–!ïiM$4±„j„<%2Ú?QSÔü¤sßü×ëPQw£’í8Ñ$ o'­:F-RHjgɈw3ùÖ1;zZª N™ÛÑÎ|Û ;Î9…øæöDƒ[ÖщR7­kBçµGÈç»Þ‘öanbL{½={ç6šï”ϼ%‰¢Àà7aµë8׺DÈäÙmë3IbŸ]V!³wµ%ó>‰$<(òñ®¶$…¨kM’g%Š»§šMÕl ‰•#G§ ÃË+̼fs7ô‹@È ×Uñèòr‚ßçyýùÆd‘²–su$ú<ÿýyC’eÃ÷ù@$O,1€‘ÏÔCÍ׭̺h„2ëÅ%ësJõoo«VS‡÷%¯nâ¥öì:äɘèÛø¥50Kæüý0~y´æÁ×¼÷LŒ•Ž<¿ü×=;óQ¥•ÜÕ•òd~O»8lÝ?xüñiU‚n@»Ê“áºS“©DJ~¿*×m< ånŒGŽ7è:ÄÒ{ìO Þ/Ã6^tÖ®£•™èbƒAÍüþ®uµ?w^iÒÀY|¾…þ9:z1ÕCD¾®æÍáä2<-·‘kŽh|=”ƒÚ…ªM´•@È$C‹¦È3%Jn\¶!ÓQ´À1æ5! B>b¼T•y˜¥ÍÂ}æ×šH¨}›œS QÊóûÄ1Ø»¬¸ Éâêð:WvuD]ž ˜}NVÉêÈ~ÿ°:X{ì°:Ò³¸ƒµ¾CP¯ËÎæXÑγ«vÛÆ]‘š_h: ¶É®nk‘œfŸ½êÖcÐyÿúæA>OüN:‹£ð‡•ê ±š¿·…n“9¹\·Ií™Þg Ò'­ØqÊßáZׇ7¹Œ˜¨ù$Ä´é Ü¿ÿx·5ïE¸‘YìЃòtîÓ³kXÅÉ \PÁ…‰½M*GšaEÈøÇÕAÚÍ\“‘£:)2yv%ý½Ö îtRžo “~Ê0wì*¾æwyL{™EyL§såå“Ì·á d»Y’™FE*ƒ­VÑ F¾@œÓ ùUܵz˜2O‘!ã3ý¬g e÷“Œ'èÇ7ÿëƒ>¦9cS}ÌýýžëóƒZ—½.zdE(*@Ç2½Ü©Þ6(§³u¡XÜ›•¦3×ÁàVßRxêùýÄz½©mdþé¦dç¾®¶JC žåØ-H¦w]#»N´Úü¾y‡ãØr†}j<® ÅM–_”Jê †°V6ª$ë6#d˜:þã%Ó=»˜“U޵ì1ò™Hý†¦ËR÷do«*¶Ròu¦ð6;´_Iß[9G-έ)GŸÆYÈÙ7ßʺ™É(#o6 ‹ØjB•u»âf5ÿÿ÷³®òÝÎT3˜-:„Eè·)–ù‹Ú<+ÞÚ`×9j-Ï&Åã×'†' Ï­:ÆtbÏqØÚÀœœ'“&ÒAC!™ØsKÆê½©5-(,?°Î®Gv.Alê’3]Ó'II—r BžG¢#‘¹¹ãe&Ǿ õ:è‚:ÝÊŠ8™ž§3sžÙ$¶½šMT(øå7”x•1Zµì,ÊG.#/. _éšó½ÛŤ2b09FÚo¹_H¯v­! |œª€ì"’­„pàqKXØÁm$øŠ²Á„wUuyøßh.(È/ö&á7‰X=ahr~ÚbÛy1fÉ÷£0ô~ò¥ Ýnã&¸<ùÒš¡!"·FÍ>*Ø>­Q·;B_4¬Æ‘ï}E”PÂѳÙðgU;òdz7ëÈÞœÚz±²dP^}dŸæ$\׫îj~t&>²KIŒBILòEaÀÈûiWåØLž~³s²1"d…Ã:þPæ>móI.øš3ínBqÂ|Ê\µið=}ã)N8Q^NLÀJ†½FÈW²šêX3iÚ²öP¶|<~*-oÔ™Ž­Âr«WØžØz×={ÇbèÔL¼DÈbð»–CiùñD‘@«×«™}cV ­RÅú‡&ù[5B>/šŠ¶àá4K.ñ½¾q° Xdžš^°Î«(Åé×ã;Dëž>Z÷À5óïÖ=ÒY÷H„¼}™­l“Âaj%gõ‘Bì`¸K-Í«?W\ñ®Âç©›šL‚ªŽãkÞSvqœÓ&Vš(/>Q2Ùùç:Olâà]—!A .P¬û©Sí˜'ØÃŸ—y÷*öE¥°ì,ÖÀ‰ü¼½Ñ0ÀŒˆÐròOþ¼]Œì¼1`P,éÔp>ÑíR„Ži·IA´.Íf§2‹äŠSý¦¦&Ÿ¹‰E#φT~–ÁkqÈciÞR†ˆdéâ;‡l08ÊŸÙu½§×ìÌ5ã9‹f?]sRyîÞp|™#©Ÿ«i¥ð–®ª-PÎæ©çCò–žoÁ4Z“ŠKП È3 ¶š!­oOͽ’œNøšLH;Q+Zr@´þ<÷Ø „éšõ<ãžÏ¤%ý'´¤]ƒhÝÛ?û+i^‡2† ÌÕ²CH¯úÿ¯Ë‚Išµ[v:C¢æ‘Å“ɘ×€g]t×t±Üû®*¥Óã™Î¹õjÐVAVG?aäíká°‡²P25ç³c±Ç¼ûm¨à×|ýúÉRLs°®É_XM(]Å»YÅò\ůßH;ÁZ°úÆ‹¹žÙš-’Óò× Eõþ”q**ê‹ùëþÁJ.h<ôªja¾0O,Úþsmó*ÌíYjí@T'¤òžLЄ‘)›&góö•(O~’Tï¡•ôijÌï´¥‰×”Éäc¸øz| £&ȯ¯êa¥W;ÿûãŒz"µ 12;‹gÑè›[ÏxIÎÒr:»¢5hŸîT±Aad¢|ã\P¹ÑÚs¾W«DÈ{ªZ~÷öÐJ•'5îõºÌÅ4þ½ðšt¥úwþJJ¶®|E©WóÂ¥Pè:ç¡âïÞ[WÉvE÷­Ü2CÓXžP$ïñç99× ô0sMÉz§y29õO¤ìv1fÐl;†ˆˆüýÍ1d9Ì;:CŠdÐæâÒaÇ€üàÒ_Cò«cH Ž!ùø6h#º®yɵA¢—v Q/@‘šh!MAܯÈÛ×1Ÿä¿g?X¬§VÛůǗ:m°X§ ~Íç_,ÖGŽ·HL³µ5ŸwXžm&rÀ¯ùú‹•¯€gÏÿfå«òöݯ„²øAÛ¦J1ò/~ÿºÐŠ}°æh›‡‰„ V,Ò ÿ‹ú0Q¡…VŒbç˜ÏUÔù8éfÅoL½qTÐ š<˜}§^8‰ÈûeŸok´¿‘Zºcyû<"ZÚQx¢ìûØ©e 7]‘Ôáµ=Vÿ™|³>Öî€7Ž|Òâ5^¬<§KÎE‹WÚM¦K¯yÿ2Dlâ?XéhBPäò9,›9´j<Ñ•ðåBÞ1„«MS·´bÖ¹t™¾•Ô³Šdà ô-ûÄY#o´¢!³óÍŸΚ(a=e#²¸üFI§õ@ÈÛ)ÐÆìJW›BV+AÈûYÉ‘•A®åÜ1„Ä5ïÝÐ6+¥jžg„|¤fÏ~lj-ÅpUq0" ŸéØ”?¶ rÝÇuøš¯Ä -œ†Œ¬Lñ–o!Áo¶Œ³¹ìèŽ~Ô›ŒÃÎY$ìÓšk®æ(n[|MOç‰SÄ+RùX·R…¡ gâ¹ßîœéÙb™";þÿ^©{ûŸ½U§×làéûrkÕx¹ê=F°”ºÛQA:Ž—{ÍROh/ýn ÓÌh5îú@öÑ.þ·Ð•mÕÎ1ô™@;OD0Ðf^7q½W:Ö¹ \îæq‹½èÍ㜬gzÚ×°ˆfꩨaËM¦X‚úŠSê˜Mè¬<)v·ßëº*ˆŒ9aZbϲˆ¼½!)H•åÒÅVN‘̦؆¬C†¥g®9™<€#dbàL)°G»q([2K·ÜضfÝ&íèB>biÂÿøî™*KŠ´§SDÞßJg>9Žn“îâ–]y»!©±,W½s¥129DZ§È›ÎœÐ6üsŠeûÇzÞ:êª+5‘Õ„¢¼ ¡lXUQ‘`æƒäzÛ£tXqKíÛR¶œVÅ- žýbßÖDöý´¨cZõGííyI@šJ÷c#µýÓyK-c Q:ìtôç$ÇçƒlæŠÛ{8ä§Ö¤P\ODìðæóïQVKç<@Sž¾_6Y±d‰¹®¹%·'ûþM"Ô 1©)î¿p™ËÚ›;JϪŠí 1áÔ;ÚUS‡6«7ŸÛn$B¦åŽÎ7£gEv­ÚÞRbiÒó.~uDïBTÿ÷ M(»­q®æ£ÒµˆÅêâþ6ËÜz5[¹Úµ&p„%öCpŸ¾1§;­F ¶SÅi?äR¿Ò–;ü*Þ™RÊd~!O©rËnö±–ÝLXÙÂ5S§Ý'ò­÷’Õ{ÉOÇÝ€Lí]<Ñ:–ý2¯Ç€w0ˆ6Ó¾ÄG60ˆ È„SßÄ*†>lYd‡`ì~¿ZrÉUû©m“p&ÜaêùKUJûÙy#Y²5GSq|Í—CÚô¼¬ƒ\ˆA6ërœ Ýý~ô{0Fðe®uVývÔõ†E\GV4Úûýš0TJ!DœIŠoþW²}‡É»·³$1rJG9‚[O@N&¾ÜÖm}:v†Y8†zÔõ»’Eâi^=D+•Õ\"dèöíÁuÕWbG1Žíýýyqãk#ÝL/æ ìmÔ† È[ª3ÜMu³w‹“^Ü__;¬‡ P¸¿~ìàïÈsd/ ÎÚ ¹£{ÕÏ1^O4|-T…=0­Mz‘‰*¯5ÑuFõ=#Ã|°ž[–Wezf«¥\n-ß2©Z²à3g–Ǩ«ml1òþ%óä úmE2ò³kv¨¡d¿ßr_ÞœªžV怇@$»}Ï¥ Ê¥ÓQŽÿÂzNJ衯'‰÷OƒÕ¤>þï©s ,K¡gÍH)žé³ïO¦¦šp:]îó‰³]ÍÁ*f35ÂÆ”އ\ü8†yÖx”Ù›]Tí»j\§!vO‹dèãƒǸíDH4Ì뉨&?oÉ1õ»@È ä–ÎanGሻY¢èþæˆÁyu\žèåÕH^•b¢íÑì žèqÙ"c•µË0³²á>ŸŸxi~s95ýP!$ânß©ØÔDßÓ"{^ã|Ä<·•Éiá™céQéÕÖµù°ÎBÈÇ;·Õ<Ñ<š vÀÈä[ò ɼÏj_Ä*€­[d/$W\lm'ɺ؎£‚4;÷:ç@ õM³ÙÔjÛ9ÇÈû­òy^‡!¡j†¸mø« g"âl‘Lg`G:ËÉSŒï¢þìÔ“H4È©'ôÂ]Ðà×QIa_z\¤šÐd¶µ]*vºyCº> „ZiL8Œim÷OXq®6áV­‚~ýqA- Á9_xeòU‡ùe¬ŽÔ©ç³¦v|ŸoÃhvu˜§Ndvõ‡ +Î *+h¨òöƒh¼ÏÇßD8BÞPê«ê¶wœãuÅãùÝó•¬t>kú©‹ã²{Þ¹s>2iÏ, y\×{ˆÁ쮨­;¬Â×Ì>TÿM>{¾.bá+¾æN.wĸa^§e¾·qÚ¤HxҟƓ͞Œÿ{þe‘eiò•Ìz4ÞDTÝíú@È<±OcÁ>í+󑜷a~¦ã¬T¶ÛÁv“cå°:ŠÙC#PE-Šú¿1gh4CX™PÔ±¶±4÷¼Iõ>‹„x~Õn8™&º)„  sÍ6p®:9ML§HT È{âDØÿ'ìÊ–eE±è/œÓÇzïqêç â~}3nÙæPÑõ°J&{³†utÖ†"ä5’‰HQ»hƒÜÄ(!æ- Ý–åßÿýã‘þ‰ŠÑÆ}M ßýËŒåÜWÁÛ‚k3ð¢t){!Èu¿0ÕÞO/¾Î+סîàÍ'Tú_÷æËHð4Hó{*˜Dîç—kF‚¼–íRvÐYMhï¿×ì×rj%BžQàmÜú]Q²Ó`Q,ÀÆ‹jßݱ>™”ÑAÉ,Æ}¡Êzìòr˜j™Gª²e3CHä‹ä­–ª—–¨‰wyz¾ëùÃFÚñ¹K!8RÈŠò@ßã”϶øBÈsîì~´ ’]jÁ2í¿ºäÓöK§¡òº3Ìíí\×˱2Ë#Üýþ¡gÖÙüÜ.OÆüýC¬NçrŽó}›žPþ!PÔ ùAiy*ÐûOC}ü†×çrÝêÕ’`á˜" õñÉŸál¬æÅº°ÙìBΑÊ#ÍÏ?)}à¢"iURÞÒ4uCWB5BºïýO8¢ $qRðiR›¬òŽLÝ fÎ×¥.Û‹ûcWq¿ ZãàPž¥”$sVæb>¸ Þgö¾°|ü¼Dư_ïåÇ˼TF!*³¹Õ0!òÿ*«<ƒE;–ƒäPÀ?N/´¸¸­¬újÐ%{ô°e™¬gêb@ÞÞmY4á•Èøî÷T¤7vm½j~mY"8ØCÑÂñ¾äc5–qS›” E+£ù!ç#Ñf·ýìDpxùkV\utøÊvqÀ!Üc8Ü#Û#eáæ ¡pìqÅ"0©µÍTšº¶0/=nGÊ@›Ëì"î&„<§´#ß×ô´£QÌy‰þý®eæºÜ\tg‰×ôï .žs;¬<7;úˆLÈY¸É2»&KÍá7z|þ?ÖâÇóø»—žÜÚ9OkIà‹KH÷ØA_}‘;­Ú…æ‰ô*LißüóÓ·é|ÇMIOÙó%²›Áß©5Pš>?}›V—\– €—±Ž*Æ:f)ñüÕé¿i&h€&Dé?(=À{ɤ%¼¥„(ív• tr³ÀŽ#!NMŸ—Ï®ü¶4í ¿•¦2ñÚÏžÇh¦Cj"t%tÜ''ôg{jzðá RIJþûë¯Áu‘ô‚wMô7È’ÜÛqÒm·qÒmÂ;¥òúêÖÌgS‘«M­0BîGš!÷¢ݵr˧ ÆüóñÒ~ RiÖŽiÊÈ$[£ í×qZëy£Û:!ä%Òh8n13ƒµÚÏ)U döÜç!xƒ&ïsãd QÚž«ç±e‘mËÌ’€‘çL hS¶³Yè&„¼ì¤Që]ùóêQ1Ö±’J)Õo‘e¬øÒ4†?ÝïîGÈb-ˬ(ž§9o‘e¼{B@~W{Í•…ßTgÖ8­CÈó;b/¹ì¶èß”½R€!̇Ì"ß$ðR °£¨»Ýšu•øÚLÛ^#¤`&N8ÞÔTQˆ Èë>ê¢I¡5IÙæoøî·$û%Šÿhi¶ß½âO¶7”•=ÏËãíTh1ák>b.÷æ×VÓ4å’Ë ˜Ùu¯Ê}èO°Kî %ˆ„P„Ì>¢€<4{¡?ïVó4-õ¸Âï~ÿ€ì"R äù=i´Ûúr!÷DÔˆŒ>SYvOb\#éÉýî’h9ÙÌY„¼½÷†7?‘ØÇÒã…¾‡ÂD$dÏCK7L vf(E@h’eÙš6wQW\ ËÚòœ sýa¤Aæ}_M°·ÉñY.~‘9ƒ–Ú¬E²‡z3ÃñYŽÐí©ßª™º>ŸfüwÞ¤·„â¹Ùch¯¹‡_³7Ý+Õm‡¿ó‘ŠÀ|iö!…½.B>w«£*¤1ØH®\å-_2Û-£ͼù‘Í9«ñÝcø%Än˜yŸD`(–:{ºÙ¬×~•MU`èn†K£7gÓiÍzF¡ðɲÄ{ÛCý'oßTÛçfA>\u÷e¢ÑRÜnšh£èˆ_ ¿džD6°ÕÊ=:qx,P·wfî¶#ÄL÷¶ø; ÓÝš©äÞè¶šº¬”Y”{ Mš¬‘SšÕRõàS¡¦¹º‘*Í•ÉÌCõõü9¤W¤¸y¤ ¦ yFë/åÕdËÉHŽHÏÖøó²Ü˜ÚÕ¶85Ü=‰ ÿ="AcP¦Až±[¡Ú½ §ß« Ä3Èc² ÍM}»ßý«hnÛâÁuD&îU”îs™Ïy/¯d·7¢xoKehæ*ÌyÞ{=‘>Êg²Vh5 dÒŠGÜ|nF–k  Dä5=tЬ<ÒTÓ¤@Èê¡ør0ÿ61I%BÞcǬaÑwš˜˜s®Çˆ|u^ça¿ÎĨË)¬Lùø^uëîþü^uÇ.FD&l·(ѵÒeÖ[wÏþƒkG#òtÌv)A¾d¶CÖ2bBÈó{V^ïxyyùdq6Æ=Až^_Á©Ñ3¾b2—Až$8–Öi]{óÁ±! ![Ž’"2á°y#ëžÛ2ÚmSO2õ1å^0hÖoó¾6ò8"2™CƒbÏ\s`}ßÇÎ]DÞS¤ã×ÍÔ°©ïâqtD>ÀSÜò¸B¥Ä͵I"ò‰r.Ü\kß'Ý4%!³„°ÍÂO¬GäÖç ¿ùŸZ\FǼª+[*¦?Òi7t±U€§–+ÍèZè2Î"§ ¶~¡1iÍ"µ ѽ7"“ß3š…Hd.™äLü IA>c„ eŠî)T¾yC3¨Ë•¯ÔŸM¥6Â5ï/•Zìx¬­)¦G˜¿O÷C¥Æ‚ñ§ÓÖ *µˆ¼ì ŽlŸ‰6|azÝŸè2¯œÐßK²Ì"ÄŒù“ù)'scgÛ ŸhM8²•Ed+dvHªÄ'/¦øì;ûîÊ~˜¿sÜ„ÌÅŒ¸ƒäåó0޳$°£´ƒ“Œ&ј·Ù³å€<§”šÕ3[Ê‚%Î"äe×.«[m) Lv°Æž1eá¬XmQ–‘·då bކ–¹¤½èâÜpÆ”…dfª3Û‰bÕ™&ÆC³¿ÕÛ´¨!/iÈ £\;*ë•#ä‘ÝÜÐÈ‘±|Ë»!o8«Ç­”°ns/òžŠtÃÄ8×TÊŽ*†Tv죬†jajîº|BÈç>>÷IV£l*»aÀO”%g4^íÃM¥f ß~ ¿ùŸýµŒl&R ^μÄt‚óê*n¿Jj¦*6 {\M´-«yÛ4¢‚áWzº¤V¦þªzYÈ,¶Nn G:¹orZè@Ær[/1ô"ÔÐÀ³:X9è®þÚ½'‘|᪕¨êÆ,µÅÐGb‘ T¥\$£‡÷šº©ú_À\•Øz•±ÃU!Û¨(ƒì…Oý KÂTŽÇÊ9±S áZkIø"{¡§Z»æà¼¬M±ÖóŒßÀ²ÜÉ£ÖsSë ™:@œÇÎgE`£˜«Žš˜?v>þ­×WÓvMÛ ôrŒAŠÕÔ+o†fƒû__9Á¾Ef6-†ýS½á¢ð'Þæš¼2“äûãßË;ˆ ‡¹KÍ7MrÖ/›\¯¥²¤õ–ÔeW®™zðØwϬW;÷ý±IçBñBû5oؤbÑ}©ˆ™Gò ›Ô"i™Âw?²I½Ôbæî¶Â×¼½ÛØ—LˆY1xŸØº&·µbXµ·ÂŒ¬©TyNתhºff›¹"yIç%;£\TBWÄßöÙZÖ˜dÛöÝÅõñÍ8ŸZèÎ%‚¢£=pÇY®Ô>’û;«ÚsœÄ ›}Ô=¿IPð| 2;ä\–‹åÖÍyk¡‡¹Ë„¶_ÎU}¢r§9¨ž „<Ìô-á¼èvúšé;j˜Cn§ë‘ýâ*%÷ìv:X©Å4 ·j÷æÿã>ä þÉww„imç©êZ…ç$Y¶òߦîÌ?ó0WB¦¢¯º {›­­¤yøîi »Å Áw¿}°Ø1ÿÛßçùuSº•Ð3c%˜Ê1ò±{3ø}€Í'f„ÎôpÍ'²ÝõëfoöuE1”ðìx_GC¾öWd?ƒJb4Þ!59 ƒ1³5 *‚ÏGW“²2ãxÆw÷ßæß?a¯èN³M¹9«¢(B†à…pò鿸Ij²ñÝï驯GšB¾n×Q|÷–˜ºQ·hªÈ¸Ö !ŸðÇ£\‹dTêºñ· .ù‹"ôåJk8 tÙøÍÿ¤PßC´PÉZº¶êk)ŸSDh1_–C¡%NA„2¨ÉÌ}Ó°á?Õ—üoj9›i ïôúµ–ÓGä§ZN[¶$B^^…ž+ [ÙºÏ#·BÏÆ =÷s‹DH‡…žKz®ù^è)œÐ#¯ïóœa)<>1JvB‹–‚ªý4"UˆÒ&çÉ™¹Á}~àk¾ÃpË^’!YHf…Y•Š&Îb‰Né×u:¢tUÈ‘q=JÚ#$ÎM…ŒÓ9'-|ó‰þǯ‘ ìýµëÏawårSkûá#äåóû„gß•BǰvŽý´l×ÿ|@BƒõŽOès‰vfÔYóßøk¦úŸ?Ör9²¨ëÚ,[UÉæýö¿Qp@Þ¿ñ7ä¦÷'ºNIiè5ðy2Û§q„þþU0mvl°¯M5oLüºú,÷ƒ=ƒUª»kš’o¤Û, âM4xÓY3‰­A¾X)”Þ@ƒÏ£š&*á+~`KÛØX·_±¬+Š#ωº''›"Z»`Wý8c#»W1nuˈqF~ã „|/ÆU‰7"߈q;,ÆÈob\Œ|#Æí°7"¿‰q;„ü"Æ…þÚãòEŒ;íb\xó?e%|HëhâO²ÝêÊ4`ãHFâæÎ |…”弌M; äùƒ–’¹Æ×LÒÊÐÿEi6¶jSBî…l^÷p믔°È%’‘ð!Eù¦¤²J …—Œ L÷V‘îm¯Äp)äù|É&ñZ›MBs‘¹*—§E튬;ö©·O‚]‘kÉè…åk ×"ò’J1ÀCC^nPú<¾{)Œ0‰ìÜ*ãö UÜUžiÁq^[À1ø)‘¼ç™j¦CHÈÎ ÂY73Ø©NMÁxÀ “/îÏ_/ðuuÏb¾¬cûûLZ<öš^²l¯Ù6ZÕ+V„¼@›bî-’4vºCÈkBŒå,$´‘A(ªŠ!=ŸÅ}ï1É£1kCÙ÷Ó‚‘ÁAÛ»iñà¦m£–ùˆ¼®@roÉIÿÍÆ¿-ò R¶Ì6§=?û0ÛÔ‡ÙæÛ·sHמ=C­÷æ 2”|C$5Ä7ÿóÉb÷AK:µ¾Ü ±0.¦ŒÈýýƒ;DgÝ!xû®lYVU[þÒ*«<ïwG¬û Ø"( Øçë= «¬=#æ[†Z60š™‘3É' ŽÁMcƒ›øàŸGYOÜÜ YýµñÁ³þহ#yý Y˜Yvˆ¼"^ç=W‹oüì æ;™bÚs¹À¹ÝÆWñ.½Ï¾mí™îYd 3Q¤•Íl@zuòÈâgв¦åRüLQö”¢\ŠKQB™ãRœ¥(ì¢\Š,E1å×¹9.£$¶›¸€ü›\”×OË»à'À«Õ¼È"h£Um”º[Ö›v;4 ìRý½x'’ žý—E«¡átN";è’“ºý»„ýL‡ÞjJ¡$È,ÊÕЗ»=ÈëéúßäL}ÿ3T¦leÈèßN?¤2Erì7Î#'í’seM/Øn3½÷g Do  3‹õ°(›n쌖¡¦™ßMHQÌû9wˆµyËŒU½æX£/r– ªà1ïUºóú÷r×Yä¼zƒÍ€|œöByÜŒ‹×ï^èù£šÞä(IÀ$A§\s ì«ÖŽˆ$Ú?³´ÿ4tÉXµ_D™¹˜â·™seª :Lú yùj…dµ%­R(]ŠþVHÙ1‹Ãu‚>pÝ­©{¹^ö¥ŒÉL¦¾ÿ­Ü‘"ó>p×Ä>°ÈúÀ—L}ß)JùЪCoÜô}xîöc/VÊìÅ 3ýOgä`ûVI}û#òûMä¬CA§Â„ãåz?NyϤ¡j< id&@ô.‚mR¤Úø¸dRä4I,‘WÛÜ#$òšM—6îôf*ʶyËçPaR-ËBi¹x÷¨^ªš=F³þBªfò‘:/Þ·6}ÓJý>où ;—-ÜøÛÔãuÔ«>üí/`Åc:ôס•”Óï0;äJéæ:7½€Ì: ŠëÒ5÷’ýIJÕuM§%Fô×ç§ç²k¬+®·˜rïJ€ÌùW¯3~ÝDtŠDÌäôΟB*ûN»„È[Ê<­×gŸñFêôŠdK­óAò²5v «„»€||H[ìÉÇj+A«ˆä¤^?dè*µC;WmÜ®ß\½ÌCâ•~A·ª¢ oÙè v–:éè¦RÒVd”@.´‚ªåDÑ ”qâÆe±ÍˆZ–¤,ò™<¨LŸÍ³Ïj ݾQøÛ_®õë ÙÅL¼—:¡á@¾ƒs%ª=§W‡•‰nXÁ;ÿ礅i“V¦wfú×™†öA£«kˆþ™Y$ÀyBÅnçQÂ1o™åžðÂn¾L`Û_¥otÝzSÐvHs£„Ž-*"CÅ#¯ç ñÁg<åþë­”Ûh¥¼A›M#ej'~jŠ«À²%,f3¹IMNoqŸ(Yƒ‚]@g嵑Ǖ>3)ø¦L¬R‘çvœuðêF‡RʲA1¹Ý?ìoí´ž>&ê¶ŽN‚äW=­ºËô´òšÛX¸irÃ~˜˜,ãΙsŠÿq™‡ËQê}œå^Æ¢î%çÿãxa`nF]ËöÀiðÈGly8¡=[™ü¤íjø‹lb¾ïnÈ•©9Áˆ)Á¯X²«½´‘móéSãnÈhP‡š¨ÊŒõãiÖq=Üù?™ –WAÒ§ž0cx[ ôòE{KÖu¡E‚bÿœ˜Î¢[üyÔkîåÞãÅŒR|NYüµ|K£3ŽbÈ"Ÿ•ó‹Si"!…Èkt Ê™‹[-–f¤yË‘îFYe1óÌ€¼'6MØj†J­K?ϼΌ…l¸Ïƒ¢± Ÿai¾OwöEŸ#35A€|e+ŽßåuÞסUM¤Èw^Ðw»’1ü@ˆO"ÝÂ(yᆪ®W£¨àé/‘½WÙ}Þ­¥ÜVÞŽZd•eïÒè_7²y “ª â6·--d#ÓŸ¨›Rÿÿÿ Bã~P³ÖáãgÝ36SMkÚX‹wÜ{}H’蔟sý)@æ1së‡ÿ±ì¦­Úcåv s/ùÇ»^Ïq"ò–‡NNÆ„N”²©…È|êÁ· 8­«©#e ²nÏl…ò )GïܾÞé„áíDGƒ-¼N÷îÅ(˾|\§¾´2ê_z‰ºõÖ®ËÒ®³*4©Ãó,Ή«<>¦,*#1p1Ÿ3ÚqÚðÞÐ9ÉŠ|Ú„ÅèÒlz€,@âïÈrëŒÍRÛd‰2~ï½c– ÎT‡)È[&uâU'4jBt`tÈû—Bçvœ6v_ ÙÝØ¼ÿù-À‹b16 h|u÷žUYdÅ„¿žîgÅ[a‚S™Î^œôP]˜Å#›ê’ „ÀÑIÇp}´jÃUü<ï0xJÝÖZ %ˆbPr¿ÿ>å©›Q°¿ ŸêlžäéðéXÇ"gîòeøÔІòv&¥ƒÑøŒžg¡0Ó©E¢PÖåþ:Ar‡Œò>YüÑÈ÷¿èJ€ü5¢KòLj.…g¿Š·ãxÌÇŸ¬&Š·‹$ÞER„° :ÇúÚ…-ò»x;i×YÄrS2Ôø.Þ®×y&ÞnHË ßš&YZT,a%Býçø§%y>þ™ÊõßÉ’Š4ùË£8ij q+Gy=mj 2py\ÏÆ¨> ¯ßKÖR*»˜õö¹×v­õͬ)DŸf¤Ö?²[·%DÌ8nŠr^¼KE¦yŒ;Bf~a7î& Ÿš± …ëKˆg>Ú(!Þ RŠÇûù<ˆ¢Û/Î9ùµd«¢+`¬û`1ëƒÅ‡øÅ=²B´ùÞ›ÚÂJMl«ŠIòãõÑJ ¼@5¬ˆ÷"o™µ¬÷ÎTJ4U9–*ì†÷¯ž4ái?zþû{æ¶ã¶m÷ØÌz^~55¤Š" —gq:jÃv3jC ²øö. µþ’ê¸Îg#Aè¾#;龋Ègºä#Ž©ãÙç6E_ŠIr>"`’ÏÆ7Ù­·ÖÔ-KÇòÖd–ÏžÍ:›†eŽg¿}´ö>\$:UQjȘ¹TeæDÇ"=g™”tN+¶Öwd’±Aö¼e%Æn{*_—•‹6‹Ï̘濃‰wh'­Õë‘Ïûa]jÜTºùE•Ùe¦ ‹“Q6ÕXäõ|Ô&®óG[ÛÄ´-T>‡±B⃘<¦S‰£ÿ5ZS©=—8úÛnrþº·o²‰?õsŸh×Ïçó“Oïù ú#¶`ë ‘/ØlµC^yX‡þB%dþÿý@îGdL‘ѾM¶ÌÄ#Õן“k#ªŠ%c˜qô¿ø2ª~e„WñÉ×Qdq¶†àT’Ë lÆës9G„ÐWwØŒOo).Ècl L<ßÛ–ŽŽç»‰è´+"o¿ØÎ·ø5²é&%Œ.¯3¾;òí^§|;r`À¼ÎøvìÈ·{ñíØ‘o÷úW¾DþâÛ€ü·cG¾Ýë7ßnO|»×°Q?øß*~ï¯Ç¿ð¿Óoü&W¨ôÎ?~ñ¿•,%<ûíD\¢­ðßÏç…7ÿÅhlç:>ÍG)7àB™¾÷̨"Œ—¹¦^¸¶è`ˆ$ˆ½}-”nÄ<%UdæRŒƒQ5'GC]ä=÷ôuMLB'Ò˜@ème»µÔSE2“Ým}ã Ë“r—1Z{½Àp› ¨­}ú¬7¹²lWx—Þ¤‰.ÖuAS9Sx—rÉJ'—a»­zaê£Z€^²Ö¨ß94¬K[¶#¼ÒK‘‹¦9ÅJ U²ÝR¯ÙC¯P_Íäœpk&;[¢Wº2ë튑’¢W¡$“{[vw+nj‰Eßd‘Í”¶ÎŠ•”UµUyÍkl¾).çZ²×-@ÞÒ˜@pŒ®*•Ë<)€¼gÈÖWΤé¨ÔbXò‘1¼›þ˜ôç?ÏsÏdäíÅJLØÂY7&ÞÄ+s-”~ÿ‹$u¨>H€Ì+|¡&ký„%ðì¾Â¿[ê}¶A¸®½œ¿ú‡+õ/Ô·×s¡ß_(e^(z¸Ö[®,ÙÛ¢Ô0­%›JÊBqÿýç¸/z+¬[²s¼d‘´ÏnXß—£¬– ¯@TÔ>)ºp5ð¥‹ÝáwªÀát6ô©¦8ìùicêqu(ïfÓ9ß‘‘èð¾þÎ'ר Ímoöc¹œß[y\!r›€dI2e N9ÞY‰fÄá1³éFS ´–~J²Ò yûD2‹$Gä=Áqv&Ì6Ô¢H¸|?~Ä—Hߥ¸ä½ŸŸ–*ö'-rî&*DK2Õª +3°º7ŽX‘ãü†^âUésÙ~5©¤Øö "oá£CQö–ŒRgò¥Œ{mšÎÉÚ4¦°mÒïQI òq‘Pµ¶ñ yýª#…‰ÈâK±Ë@(@^?ã f•d³8#7³‰ WGèñ¼ñ6.·¹™›änBœÑ¬d+Nòú5vÒ±‹È[œ{nZ×zèùÐ`S³mz€¼F$„0"ÉÌl`œ±v:Gœ¦-¶^23›¸Ø:˜q¹—eŒ3’™Í1ÎXѲNYœ‘ÌlŽqÆz‰cnfcClW4?ËH×QÔWðñ_ž™€„葉¦}ÕÁóᨯ¯‘Ê#âÏGìE õU6ˆêbÈÜ)<8ª`ÞwúÐ ¡à²wÁh:91J$™^~¯¸ë"]N}àøxäý=¹”žëŒ©Z@>Îâ¬!ÆYùqV㬶Þa. _çZòý=zYôîüŸ$b¬±°ÄJ§q/¿÷E¼‘úæÎð7e/Ô…¯QÍ;V–|L ãîêhæå_Zä†$@oÙ'¨’½ZJýMU‡£Æ ¢Šš€ØøŽR}B™ò@ëÔSˆê:D)}f­Oo%¥¡¤ê)YwÀÑ%ý*í̆I§È"IöÜ}ŸŽFÆbsñçòÛS4øèjdq¦â¬‘ú3é‚¶Q‘FúòyZFblD ×OŸR܇D–—GÞÎÇBI¼ÎëÁaÃÉìÆc~;k‘70…c§|DNÕÔqJ³E6nùQS«‚÷šÄ"ë-–<òš› x›hÓ× oYÛ$“Šû*U9>˜sH’¦š§âuBAËzvóX*YINãu~–+ܲGŒEjŒg}q]j2]燲_‘{)9Ý_ìÞ:«û»‰j—yu<˜×ù_¿KD¿xœäíS[Ô(ïvú!QˆLsE«=á~Æ#º¦c@¾ö­oTºÁ·­]g…[€ÌÙÙžÃô¶¼Í > ¯ÙJÊ*œë‹\$ò‘¶˜§_b.B ïßš6Ì4mb±¤È§¾¾! g•2«A¨YU(4?‹|Œñ[ yßQæåÜ›ÖÑ£kT{9• “ ATHõ2W–K;†B{‘¹Cù r4]¿mze„×yOt˜ÚǤ¬Ç%/Q·Ãc>2‘™.4¬R3о\Er‡ ;ˆ 0!·)îEr‡ ‚E¾J¦oìÂIÙ)øÛãZÖ—SÐ/&¦•SD^©‰I)9Dñi–‘ÕÉf4P4Æ5är;ii×ÒÌîü D8 'q#‰Þ¾f¹$(´»‘•EŽ”ˆ2xujäýPP°í\³z“z [ÇÓ1ïЭ ÈaÆh•bl)@‚/®w‚ ×ÙoÐ77ÛhpЗZmDTð:ï!ývn®ÖÓ¸¹îËÌF€|äcé#js~½i–,V$Ÿ±{ø‚×0¢š°Ž…¦wQdZìÎ7»õlcd;a\$Ÿ±mÿm*úRŽŽÿHUÊ!ŒÀ™ÏX²ð^¢fbEn›ŠgÏco× ný”mÓë/5–n‹|r×;À7î¹ãš3"bϤ(îÇÌ{Ô{¿ÔÂ1?ÏM–þó×Ë÷¹BRG™íšdR¬;Kâ5ÇäM¬à1¯ÙtµHPj™—–‰™$0­rúî&^×®Fyÿæc*œi|FÏ>¦ˆ'ºV‘OÇ™T? =—¸C2dòÅë0ïØ™XÒžéØs«â¼c‘MÙ~³/±à2ÔŠ÷¯cöÈ"y£¶Qf”´+#M¯Èfgmé¶jcß´„ò)â=²øJäD–ò)òú9ýä‘RÁc¦Æ¯Õ*ÅNžbXz¼—ñ:tZ I–N´ “ηŸ1žöBT•¹Qy ´{L'eŽ©É}È[ P8r¨£‘^v8ûíÉåÆN«TAïJT¢A1‡Í&Œ¡ã¨E®:Pî²88Žz¤2ªí ¯pÆ}›ÖZ xödVvЇ Ñ~­È¦–ýÛ…øs&þLwþ–öK'´3väwÍ"ûôÖÁ¹ad¬½}û‡ AÉWÚëý ¹æ¬ÒŒL^ÉŽw¶ä¹LVœZ.®÷ƒ‡I°…ÕLÅ×.RŠëãÔ y7koâ1­!˜'òr|f¾Ñ‹B‡²ÈM!m‡xÚN¬ÆdÓŽ¶ÃmG¥cBB4rz²½›•'í<Ç»”ÍE~QÈ5¾=Yœ(ä¶z+y=s3ã8† àßòÅ£¬Ng¿´‰[?o§©çu<{ññ4;_cÑÙ’é¿ÌXùÒ…Þe[çeF€tùQ RÚ7ÄŽ(M[¿ÃcÞ@ëË :ÛE²¢%™QB ̉ÈQj,všxÌ빞¸‰ÔøuÜ®'©œØ‰Ô=®ó·ë ÉÚûñâtÌÛgõß·fõ7TÎ Šwéþ¥=iã%:wæž E6"ãÇÓÙcº31€ŒM2;Aé¸7Äé¾Ñ¸*Þ ~›Íúì‹N"' Èæ7“‚ˆ×"Ÿ%Ÿ×>ì·ÇQ7ÜS<øÂ{"p8@B©(ûÉÍÕ¾`Jû‰ä5“Á •( t­ˆõ¥lÖÐïï>4Tý‡Ò/úmô5@ŒõÓ•ì€,R$t˜>`÷yÌï.v{Û&ê@q{<Ú×½²‹£'Ìñ:éy~Çcž_'Ž×™Æ˜¾¯K<>Íûïu©®ÈaºŠmÿ#ìJ“de•è–º´Æ=¼q¿%8‚`¡â€qWÿ@ !-­ŽèŸ'¬V‘!ó *º7,Vø¤cCÝævFÇžŽ‘tláéØ !ÓÃúçª÷— Þ{,xúkÍWý ¥|¬U¸Hðäk¿ÔÑœsQñl~/™Î`›ªAu,$ óÒí¾Û]Ôî4¡ç%!ø0ÁœçXàlŒ¡Ôkû"¸wl×iG½fÎͺYÀÿ¹KØä­[Ñl‰\ØC$÷ŸÁ¸uµ§[)"129Ì3&2@žyÉnlu«!>Ïœª-Ïœ!äGΖx¯÷É+X,&;1Ͷºý'Ùö #?„æ‹jÑ{oXßïÉ—$7%¹%÷ô{ZT9À½_?Ò¢l;Ú¤E­½R> bšcùÚžüíDhNåRŸÉÜÑד÷V¥ v•÷lj!¶±ø^ ™I¸æó»#¿Ã½p V&ªÏärežÚ’Dr–žhÍÿ9•èIV"d‚(Év9\ã¥:„L#7Ç`,+û¡^<5Ó!¯ÁÜÒ¿Í‘çt­ùèó6Òf‰ë¹®‚^~‘ÙTrî-è,++âÊŸÍøÖPýyÖ5B>"ÛW Z×JE^ûì±Ë_µógãÍ-ëÌÛq;$ØÁäÎ;p!úûKM2=­­åoòHù‘ûß$Ä[¨iÏócí°N[fäúű”ç(奅y>èHOÄÙžÉãúa…ã¢NÆ–ñ®¡úº‹±0³¢ù4‰©n)S ïý†ORUíüÉ&³õl[ÈjJ"9‹]ðtÞ™L'Ø D‘›{IéË[ƒÞMYö!¼[3ýwßç"lŽ„YÉc/‰ÛwêÃ;úÄí:õ0Ó>•íÖO«²ÿg¹VMi¤f#Bn'”ÿÔ&[tE– fóÏŽ×cÏÈ‘uaòx}ËÝæºçÏ·¢Ïå0>P—í@œ×¼ü&Ny6+!ë/y&¿ä…Â{¦¿ä…î_òB¡òLÉ 0òK^èyžN»Oœ8g÷ÞÎýt6¶_-¼£ë>ÙˆT>Ùˆˆ(Ù(y^w (Ùh5A@™bo6¼SˆuÀ¿xË»pÎëXPÈjJž¸ºEcXò¨šgÙ=¾çÍŸyi^«¬¸ä"Œä¾æ6ÑšJ˜~žTÖbõ!/Éó±w“õýb÷<á û|~yžL?ÏB!d1ð]¯œq®šº„TÕäùÜ?OG3e&§‰fÙŠ‘×°ÊlÞÖaQÿ³ë óg¤}Ø9ëΪÿ ?ƒE¤ö³ŽFÊQŽÐŽIíV|ìVm6­õdŠ#B:G)î°§òáÓ O)"µÿûË žeÖ³_ó‘ÇÜIß0ÂXU3EÈ{”RëìE˜5 k\L”·ß»µëÔƒ>ãl.èè{g/\ûµ “[çnͨʤòŽRIca&‹ªÄc[Y5Ó!¡šmL¬OTË3E}’$y rUÿ6{“E©Ï2_3¶úªûöëä=C5û•Dsˆm*÷f†¬Ä¿þb†Ò3A ®ÔÜR|ïÏ€ZZQm³*I9è½8B¾|¥Ô3ôW¬O²àbº'ÿG(‘¯Df i!5ÇC² 훬H±œÁTKo¸/Œ+…>ƇœÁ™éÉ+ÏûÜäS äÏk(K}4å°r¾"ǵÿù}ºù?·5aªÇ×´ßÇ6‡ù6´>dÃ2Ð _óvÂÓ7gèWd1~Pw:±‘@ãaV¥µPÖsm> u PÉë~%Ñ“·‰’€Ñôá»u긓€7âNB/§ž(Z@ýà·ÀÀ†‹d¾“à¢NxÎÉš‡}úëÌ;[ ™1œÁX&ð3¹ïÙ¦ûÚÕN:X®}Á‡vöÈ(ÝÒÈe+O•6¤‚·ì+µÂNÙºBKêÇ|1Uvßï™í(áÑÖNô¤á2^R1U7«+Òn\O¬àô'ýtòu~¶¦fÆ[ÏèvȨ¿Z;wª¶6â_ gh‡´álÿÌ^ÕK…W&ûEt “y ÈʵQÊQÏE`é:ä-ü»{×û š ñ㑟Õt;æõ®vîç¢÷2«ô[Ø{·U=7’uì)B¦ñ©«ò†SŒ©qa BÆÉЛâÅŒd®‡|V¬!oŸZÌyhQ|GwX嬬×'—«¢ ðÞo'v¦þª?螥?÷Ïz÷Å™k*JF„LЯ»°;}MÁ`§ì‘ sK²Ø¤FÆWŽ™BÈàÜm¤ìÛã4Rö©kš®ùøØÚ÷ÞŠy0™¿GÈè´í«•}Ñ–$b2ãû¼^sfYS1Õ!äí©©;óqÑëåÿú-hhlª^;ÞóPv$_BÞ=3B®óÐÿ6Œ|÷–Ǩ·œF¬çƒ8/²Ôž£‘þìy^›c¢~ñ­>³®}å&½ü|2Âì¼4Ί)Eü4½üìa®Tñ–/|”~–^>4)V]×´E•çùÒåøš¡¯îŠQú)õ"c£NVzùA^¡˜ÿ÷*›óæ-[‚ Ó5oԱ̚¦V™ðá–iZqÁ5›eº¹÷é]*gˈÏÊr¶U”áŽ.'½ek ¡¿%‰I<‡XV>ããÆÊWøšv$[»«ÊQöd6Å@×PÏÞè§[=[Ò­žý†Xfž/™u\tî=ù°¤¶3­>ɼUÇÇ#¡wç¾wkZ×(1ð•"dz–8Ì*Xe.鮃„O]t†/.fVÃ;úÐ.TÁ§²\êèmÞQg&‡³)¥óDD½…ÉI\gžç%8­^žmEú×ëlèW× ß»²NýÄg·vÊš…ÿ3Ô·>“N:V¬#ÓóNÈO —ÌQ¯£”9ø¤(•ÄTƒ*לX™5¹€^h³ ·Þ2qúV“Dz³‡L㞘çÍÕ|œõ¹\!d¼7^òÌ+½ÃhÖ!o^Ô§gKÎÖ»´LLä!ïŸU+a£5Á )M.'Ñšl‹Ö\;–&‘q>#È9«¡’#äÁ;Òg™¡d!ƒ>Eé)ŸJ©•³ w–yBÅú§4I÷i4Î2Ol–y™!ÓÃ}ŠÒM#fåI”.Cȃ(]¶‹ÒM“ëI”.ÛEé:äõ4€,Óˆ×y@ºGž‚þÉ!£‘Lˆ]ïøj*~f\ÑO@cí·Žyn¸†wt߯ÅÔU×T_èe¦Oþ»Ð°¾³^êçI²vEÈ™êoÍÐYÍuW°…/ Õ5£r°Ÿ1mÛY?‰ñ-òÙï;i6›™Ô«L6 y‹Vmg¯1eYc:Ö»;£~³¾[>oÛfo¥?9ÎòxÇP]«¤”¼‘ï7B>q^<µ®áí´ÒÎ\Éó€ƒé [6qÎBî8˜ÛÊ5Heòu˜BHð×öiõt»æ{Åò#-çÚ ûµ\þõ8ÊÁy:®Ù¤‡Ã×¼Ç zûÞ5ˆN9‹V„çN_â&0cf´p^4CƒÏ3»@ýàÿ|Ìu±á`þŒn>Y'ò]ÂóLp^‘ ³5 N}ˆ$Yc)ýè¢Tömxܵ)ÐK„DIÍÖ:4õ¥–·‚ ™žqi˜½£ö380Ž‘·/&pïÉo&!¿™`0„<2ÁØ#µØCìL0ò› GÈ{”äàº=ý ‡‚ËüíÇRÄÒÝEJ–Ñ•ƒ­Gš^wLÿÒnÓ·ª RŒ!wÙWæ’[NÕ 2ʼnVħd™Å2²ÇÙšÛ;ª–ZèíZ7tŽk¬ÁÜ$rQïØ!ïáWR{îÐwTÙ¶>LÀ!±^ÇV$Z1td!…gñ8äiéÜwT­ú§i!ò¢Ý}Ž9ÇIEÖrÀOþç35²'2ëõ¾Ç½\B’„¿ªaµ’BU¾§KÊäÞ0¡2ÎÿRf>çÅC]'åÝ Xq½’&º»»QçÌÔÖëlîæEŸ·s‰Õåvó¨'I© æÑCïÁ}Ó6ÛH£Çk&õ]zŸc}DïßL÷ļF¯I#÷iiÌ·©.âH÷«x“AÌ™uhéí ÔÈŸó¹DÈhG=}¿'ÒMÔ¯Ÿéýó”æÝfªwNƒBÈ8਱³ÎÀ+UŒËR„LCÁÇmb2[òúF4YW,¢BÞpÄ«Ê\å£ÊòŽrµl½A¯KK‘)ßMIã*÷:]­EOõ²,5¾£gH¶òù CE+¥Ï)~J¯(|×FÞíºBïÇð“ÿ‰¡nržôáK©¥cz ÆX¥ó:ÍA¹—®ÆÐäÈãZYïh¸©ÇitÐ(ãè 4þ?\¦‡Íešãk¦GŽúÖe:,õ‘˜ó¯úȵ•äs—áM6YŸõ Ñö•D}¦¨o§çRÓ 8 §Ø!i‹±°ª:ªôpû_Â)l™ž˜l+¥÷Ötž¦O$Åw®`›e€‘O3ê¥!±Ê•ÀËÊ9Ь²]Ê*W+B>⸟¿Û“z­šw†ÏÈ;ºöîŽ}=eU×uùòm4tÍZ(³æŸüO`/]­pNM£ÔÓ댋JõYÏãPg‹«xO38j¤‘Šâ÷$à,%VýçyO¶ÛÊ„á=F¦'¹ŒTt^ Ÿ^“ƒlW3”Kn²3ÇPÕ¿bާCm®E*¨¢\SÌÏ‚“/5+˜I—ÂH»ýïzò}™1ÒÀ“G)XzÊðŽ®1ôP£ Èû^‹o­"š–éßž©G>P_2ß&¼Æ¦M¤Xe¶"$tÍS²ª”RÑÒØÊg#B¦>#Ù¼MϘXh§Ï J $®$xÅ7ÎEÈ[ØÛ[ÍÆØÕ«m<÷<“cŽ”—zÂ÷È'Ò§:CU›½Æ×ºêŽÉ™F“®áŽž¸‡ˆÎ_uÔœi¬9p‰˜V˜¼)Y× 1ÓHsp âGòí½Mç©iï¨[ ZA/)V|ć(F[ï“‘FJÏ•¶VK%)90=ÄXIpI_Üm÷ÅUžïf2>#Ž€_¿žð¯éØ6¥$Üâq'Ëk8ôwT,¤ƒÑízTg£ßmÝ¢;áÿÄÁ-Ëê«F3êkZŽ™ –ºíÑÈ*›Þó{wMä0æìÍŠŠuF(ò8³ÖìÆ¼Í“W’žÂù댞ÿüûëë–[­~–l’ß6-ié!Í òFLl€ÓÊí¾s•(ÝÙsUra£èà;Š´ÇÖêÐŒ´Ǽ¨Ì mÄ~åªdTµÇýSÿäï?¿õOB~ëŸ*„<蟊}ÿ4D§œõOñ¯ëŸbä·þ)F>Ϋ»°Y¼_~©îîçÕ]±bdŠ¢Ö·i”&aj¡÷õÝX͘§"›¼î35Îiرí8‘õ4OÍ‚ˆ{r|3Õ‚«D©=¶ÚdŠfXØ»)‡!£:†Ÿmon¨àÔ{¿}¸1Y{={³±Ï8Täî{kVÝa²KÚðÞ£Sß_«hô3ÃP*¶ŒoŒLOÕÆêê÷_ÔÆâ‘Þ×ÍÈÆ·ãå…ÿóy’º!MÖ¤BÈ0–l(i|¨‚ýgÇòw7ê¶,P>àkFNTnDõ¨3uØ¡$֯䖽ù¸T!ãè ÓÓÇž à}¸·ˆ„Ñã²Ë­œÝk+Þ[”3T# Çö6¡.3M«o›!S(Ë€7Ì4fú½£vÈk(à8£[sGTÊ÷{Ä×¼'|qôÿ9…ÈÞ=BÞ£y~³X"ÍÄ×–¼éÂ*„„ô¾Â:¾˜ùsZ3!rÁýwGÑävÜ. r}HEãk ÞÛ;#úx(}Äb¢hlzñm“5 “£ÀÈë'rj²òy‹R´·è]ÒômÖÔl©¾£·]{_œ¶mVR›ê!B>>‘“Gâ{Fº¥ÆžzXžÓ‰,Œaä Ûü:=º>I´„_OYaa}h²½*EŸ‹òíú½³¬°EÓ¢¬q±ÎÆ#ŸG¯°œSÏ¿N£(ÇRwÂy£\e;­ B^£"p‹…glðÞoy  RûކQf s’îCk*`c¶ ï2Òäqß1LCÃ/JÕ¼#b‡ {EÓt²YÊ“$jQ ”N8<¯€yÉ*3„.Ó#Tâ|HÕ–AÔ0ôa6Ày?`AÈl®y±îîýíçÿ„Ò•®‹îèñ¡96=[xW@­þ=)Ùy3ëun #ä‰XÂÿ$2n³þõVÿzVàk:®òvî ž­1—#gõ€‘·_1=+*cƒÈ×ééŒèÓÙZÁî÷ùsÎié²µo¡ÓúŒ‚îpÏËxK3J¡¿ÿ¼œpZ §ºcò cþy9×doAbÀ?‰tKØÅ°Ý\ ;ÌŠgºï›Ã&ž)ÄX¨ð^?•.¶\XO™lx—‰™¨Ô2ºßÓ*E L•gÔ!úû'Нø0p6€§tú¼îÎ\n‰3O^1½ciý×ñ¼í¸L´®½S›þŒ…ÊB&Ççb†ö6‘èDï OéqÀ"£¶™Õ³Ž- <ùçîyÖ–ix\3a›G„L;ËÊ ;+£(Ë&ÎÎÛ¨åfVé3¯Gîô¾¥aøàÀ\d»t¤QnÉAÆ{ùEêHås”ñNèɾ~vY(‘Y+eT¤ŽÔ3¶ëP8¾®~òÙ0È Fòë‚ÔÆ›Ö„XO 9£d(áýºàÙ;·öèæ‹X±Èöɯd¯Žu^Æõ¬<•åZ!$°ž¶>ïö<õØTí’…öyè]àx›&”nÖ[2Ø{¿’}4oÓÔ–å(Vã^)2„¼º5p˜bM ôy©ëó.zx5RkRBŸ×TLLÔ<4°‰5)Ðçݾwƒ,¦ÖŽH“rP…Ó³"|qAòÑð°að¾îçH6Œ‘Ñ)rãÞ7æó"Ÿá×ßÈ£¬KŒŒÌf®1ÇØ1«ÇŽ1à ¼ŸÑh[½nêôç.¸èü.èµÓÿUÛ86{†¡ŠEOÉ !£s‡ß/ékNdäæä8ºÂEG׮ϧÈRÕ™Ìòº ™6 äBsÚ…ô뉪[…·!pþk -œWRåR}œÀ¿ˆ’#„«;ä¶cQöÛ´r5Úë9©ë¤Ø]óy\%L•žÒë«“_ðYOc•ÍÖä#µm‰ ½ÿ,–öŸ×]ÆÁ6–¼?Ÿ¨‹bdBÆN~Pu§%ÅâÿÏkÈ8øóïÏ¿H„F·òëJsâ‘—}ª}òz3O¹d•ç~_#=v¤43Ùyt29ÿuï&rU6nåªü^ÑPfÁÃæ©W޹Lîýö —i‡L¾T‰áÿ¼ÿV%ÆÈoUbŒüV%fyP%»*±C~«yP%f»*±C>ÎÝ(ÜÑã»[œ;®;MJð!›A1ç€|~îÁœ¾ÞƒÕ…êB&þ׃ã5ãõÂêBg¯‘oý¿?Ð ¥o™IlÅ×¼†~œw:×{ZÊF6® !¡NxïeVÒ‰"ÃÈíÌõßæ¹âC]„Þ…˜ÃÔ*2æXR;DØÀÂõ|¶"äó4îwcþ…”ÛYÆV¢ŒG²Ù( „<‹û¥¬Ü!Ó³z]ɼ÷Ûõïë>êutÛu§1Šϱ|/l$ ÌŸ—Ë~þt^ãzV,dÁ|G—Ë~…%ÎúxÌ«ùãórA윘¢Al 9÷Èdï€ëO“IKzˆ‘G äÌÆ{•âõ’œP4ÄvvÏ¡ê~ýõWÙ~›/ }ÒÎüzúyÖŽj,ËP„LpUÓV õ/Ï1{½\?꟫œ¼‰`\yõßõrݽÍÒ~FM¯WØ®ëÚ,CÈÀLÚ~} ­³>s©Êsƒ2Jç)] Ð\SÿéÏîÿ„]G²ã¸²Ý’®È {þ*¢ÿèA€IÐ!zõ6‰¤¤[]]³S-Læ1IqŽmÆz›M€. ïGMµ‰n7sß5…èa6üI˜~ÇÚÆüµ¿nÖ6õP"ä3õ/÷7ÔþúØ´àœI:Oæ˜M/û!záÇ;I ¡ž=[ óÜáe¢oS¬/0Y;нࢅOKwÕËum26®µX9B^\® ·Z7õ¾Ã”ðsO"B\ân™,æ2ÿÏ9Bž"Bug«ºåôëË–b4Ì$:ÖÀ«Œ[Œ'ˬ<ß5 Ÿç È-ÌŸ>ïrxé_§üdl|c¦lùÈ^Ú¡¡’]¹ Ÿ&WL¿¶ÍòʯUÍiê5ÏÙ„×Äl¼ŽÒ²©Ì•yì !A´ï®ÝµšÜµgì”9”táÆ v¶ÔPM}Dþœ6±u „®–#x•\°ù†C††œYa´:šoDºó!&c˜!% Î6¯!Û\æ5ózJAOvvø’Ú¼Ÿv»k§Ç!oI~r  s1Ù‚²—’|¾Ý6’ …ôR»6±äzÅd;ÔÖÞ$yfÉR×pÌÛ9‹ûÛŠ/¢V[½m‰ä©m(RO®}­øÉgq–*ë– Kž5ÍΛãvsyÑB< Ažš>_tÓïz9B&ƒr W³¦Zfªlòq´¯"SÙœg—«e+BúÀ‚ÿBóÌ[¨±Zõ¸ŒøŠ^°-"+©+Öe_Ç"ÒSâ¿|ë«'{¾DÝõ¡¯nµKùµ¯žñã“#_×,ÊÓJá˜_+"Y¦S¯r¥ßh¥“'‹ž7ì’ìºgÖ%9Û™„áæ4ÍØ9ÖMsÖWWê†Ej%I4[Q¯æ+ \7ùЉnŸòK5ˆ›± Ö,×o¬ïØÅ4‡ûù|Ssú—UsnÖ­ ®èõ7ïÎx—R BÊ“Ë'¹]>í#íbïgk#Ý"òçÌy©ýjÖ,¥Í~‹Õ5’èl¢ÆÝÝÏ qßêèHn?ç “›e{L«qà.ÝN½åÂG0˜óÌÇ¥(ƩÓ}HîãìÍÔ™#äýDJOsÕtžWcLg!·ë©W_†à?‡l×jÅÈ+ªú‡^ Üljz¸Ÿ·o·]ŒŽã&ThÞÿ×+˜•™¸v I41>  ¬¼Iבk¹C'ÑĤ®©vdТ(Ì÷ O“¢ŠÈyhI¢JøgnP^—UæeÞg‰·è•ƒoáÙ<ïe¯ „„¤WpËJ«*z֜Γ¦Ü[´Ú>Á/! ïI5˜^Ë®-†l2„|¤“Gàu­Y¦ë¾òypZËàØUY³—¦-Ö!_P©Å­Õ®•Ò‘wïüå`±;¯usïÇŽe½kx™N6ÞyÕúÅÿ$§†Ë­æyÅ©¸Î®wÖÃ\l”nñÆÛ <¹$¬@ýÀ[AÛ ôú„¼~–ÜNVr çùü]r f;äöü.¹eh›rýÏE33Ø%E³ÛÛPÛaræ½Ö£BÈ+Z5x ž5e/Ì +òv“šP‰³$Ì™/Óñà_(6*šZ¸âó¤Íߨ’#$µ¥üÚР2 õÀ"éšá@˜Œ;9½H‘‰jAÈÛ±CŠ6´“bz/ª-Úò$I) Um%\k?ÞOòó¾(LmQ«¦f„¼ž6ûÎöÄL ²QjMÈiò(cp«ùà…2Û¤(Ú È4Þ*|ì9ß%Wø×“x«:˜ot2㢘óÓ¯ßÓ† ‹»®nP[Ã"ùÁ62AøéŽY‰ygQÏæ#Þys—X±iIYùBä±Ö`uµ[yn…ïü±²|JÝ®®t?k MC³B/£ËúÅì|ޱ!@ƒo«ï\yc;hZË­™ÀPT€ö;…qXeklqM„¡éâô¹N¶K++5±ü¢iÖ-—JÀîƒ\QĪEú1|F9X:BHrDÅU7碶²×1 ËI#ÿ»4O).›nªÀÌ…Ûǘ¯¬² ±î(ùSb{¢÷_bJØ ùŽ‘·OñI‹Obðëô—ø¤FL,B ýn9îⓎûI¿Ä'äQI‚-¬Y› ó¬Y­e¹˜¼LÉ<Å0nÍf¶+kÙä#THjûb©fÑ`¶mÍ ?ÈöæI\…WˆÑ|–f#[QøJP\Å;×¼!pí7M¨]íÛ¾ÂÈø|ÓÞy—­±¬u²K’È<°éŒ³ ÓS›òúÍtF ¶}Gº`ßð&7ý<–ã—-ôr¦‰ÔQ©Öšˆ€LdÌI½æƒÕÿ!äí°¨<ÓÌŒ7ºkìÝçy˜¨W!A¨U"7CÓ¾5 B&2û&Ô¤(Ì{TïR*\ù b¢¥ÝÆeUAkŠ&D óÖY«¸`:³N¢áf“ªòl°eãTŠj—f;ŽyÚR€0×…]*ÉÖ!‘?$y›c®û:³ØȤe\ž¹ë›Íø’öõU¢u›aéç­Žòõ€¤È 0Äöæ4ʉï߾Tí¤¯Ú2IC=>Ò˜`>¦©1û›ÌCm@î$‡ÀfÏ=È<$ïæUPÀ8D&ûþ'5×åó$]ãgÀñQô›ã4€ã]2T7Œ´4Y×þ <ÏiÎÖÒ&ÃCSëÚãªÅÓ˜äºK3mn9B‚ )‡¢ö2׺ÎËVÿ‰p%¶áý¨¸tõ²5õUzúBMëöm;gó¦:Ö"ä !™GòŒÏ›î+„$Ѣţû‚9Os*ˆ!ÀÈVk£µEòR–>Ï{DÕþ×ëáxî¯C†ôçÿçgž*ËøØ |—žïöã®›­àœòÍ\ð]ÚòA·+¾óð5Ž­1I¢<_ÒOJus3|Û®Û˜ñbÉW¡§9um`j/ú诡7¼ós³Â¶ %‡mÀwÿ‡àô?ÏÏ×B¨¥j|r¿|Hÿd·€~„$ú&Hÿó.ò©«z)Ñ7a—nnÍ†Øºîø˜ä[ƒM°¹ÿšw¤Êþ8æòÊ;§%g+|Lw<„» š¹IfL¶vÚ•ë»ÌsÖîÃÌa ´¨EªãÏÖ—“s(m³_ñÿywëºê¾Ýk|Ì#á¶Œ î‹+YcòãC­ûyûÅ<ÓÑÅ$z1œ[ë˜~:ÓÀez$á{øŽ¼Ù‘ù6³‰sh2?pYÄíÔMK¿oÓØ!äAX§iæ¸NõýØ‹BÈû)GÝÕß]ŽºèJ„|$‹†àNÎæUð|NWôüª³†ÜZò¸l\ê`ìˆZ´°•|$sÎLãã´Š¡‚×ãääľA:îÅÌ8æ%{ä–ŸJgÒ­v \ûã¬ÃòòÌìÚ%ÛÍ¿BHìÀ\û[ר"çÇ]zœ[ܾd¦Ö²áÒþ‡$É  k¶¾Lõ D•Çã½ãåZì ϺÆv£g„¼.K¸,G¸KOÔ¿<œ7¦ÙÌFõt̰‰éŸÿþñ='²ÝFn;Œ!Ï Z]øÄ`ž;3#8,«“ ¥yq‚ác&s1ƒžh¹YsÊ#ÓT¨8Ö,Û¶¼Èóç¤4©BßqØäÌWŒ¼¾?#žôD‘¾éC®¸“çí+©Dí¨¿þ$ß[$¸¿þ$¿·HØ yû’êÌEsÇ“žÈDUäu0ÍÖvZ‡ø.%Z¤è´c€½ÓŽä-’çÛ6%w~Êôhm7#òq*»ñË©t½m|‡âÿ‘b4) yqf~— Ï£¶+ oqà —âù(»õx—'gãDUÇ팫ßçó×¢ž€£þüÕ)zcà‰µ‡¹3ÉpkZÕ2³ºÈ«ü|}QÕ9Ò“Y¯M t‡ï·/ÉpÈÊ#¯ *ÁâÜ0^ ¯8QB}pXš’瞨–>(¶ú²WH¢ú Ø2o¬^7T¼yS’Šã<É׬ÜG3ÐÂJ Õø¼k$“,ñ€ü¦‘ªguæ{Sñ¼bùFH¬|cÊ%®·¼ß;½\?”É›˜·™+ßOz¹ýömò8ê4MTùX\Ôðëô/ÅÅòCq‘Š‹yûÐðQ8Ù˜^þ’l ŽUô‚ßÏw]p|Ch¢õÀ쟤£!c–& Ì>‘Ž}²û„& Ì>é"ûdFÈÛN‰œ|L’ò?ünÂŒŸfTìÿA/‰Í)ˆ#Ÿ|²J®ºEÈ{t?;ÒÀÊ}ÍDaQ†wN ‹œ…Ï4™36$Íf»XÆèFJ/¯· OÏfwHÍûA äõóºn’íW¿ôïa­Ÿ¶ßÃŽ“RS/YdGÑTmáÜfl©ö×ÎT#tdÈÓDm÷Åá¹ s+›²ªˆ¼¾­ë|Âm§VÖ(³ Ñy¼Ÿ!è‰9–aÃ7ð+ ‰Þaÿ÷ŸàŸï›H#_YYÀûyÒ;8BwÈEÚÍC¶= ßô.ÁëÌ®¾èYïàéž®0Èf—FÞNž­ŽöSÖ|gHS½8þÇ`óyH`XÒCïpdºwÞæNs‘Í]…÷“†7®.¶q©á×é—\9yÊ• ÈßråB~Ï•ã#>æo¹rø˜¿äÊÍyÿe­Ïèþ{ª¬éÏý/kEÁòìÒ*Ú`Ù/Î:íhxš¸…Æd7ËLH1œ×DÓW¾¬XçAï9Ì?IrG©¤‹*û¾ýÁÞÞ3Ê{ÈÈbìwÖÃý|a¡IS4Ír¥ãj›+Ž×÷Ì|qn;~ý…½@ºÊ­*Y™©ÜÌ]3B’ãÚ«P 7ÏÈ,½Å,ðyÒwò…Ü‘/à~^/_ÈYs1‡!=dç–{òŒ6‡,ãD¾HÈ쥩,ã_Ü0«]-œçÏ/ªdm½+B^¿×mâú“¦ŠÏLe@Þ>*s½ÄǺÍ8OòÞpOsâ%›ÚüÞiÊzSÿ~ ÅæE0)òÈÔ+¢Ÿ›EÊ¢_"‘‡¦™&vuqBf˦’¸ä˜QNŒÃçi¶Bo|ž÷¹3Ö7ɬûG8Ï„­k×Þ¾>³-Ì9´pÌû¯Õ˜ªâ;B^¿øÒ‡/ ½Þ¿VcªmåÚa$ùšÏ¨c>~Ígìø ™(IÁgræ¥Èš V€×d\r„£8*®* ¬wz=;¸5s©L/ê!/Òÿº“‹HÓ˜yÖg |e鑲ý÷Ç×ëÜGd¿M>ÌC½q„$1Ö%NͩЃVmAmÀçÿPÔ‘(a…VÇ÷þ:1ÔË:Ò4f•vFhª"øxÒ¶þi6¦¹ž– #¯x†uî(EV‰m¨`x»|˜‹#RnÃ3×í‚á­³–ÿu.ÌÞpj×#}%÷ÉnqL¶°’1iªa5@?#Ljbµ’C¬UÒjÈ8BÞNéèv=ïÓѧHÁ¥·ë‡zˆ[[9ÇiÎg8Ï[ò4?=w˜eÆÿ‡çÞ$ÏýF¾wŒüå¹ Œüå¹sž»ŒÏ}GHzÜÏÒj˜u_šµYcÞs—sqBw1’½°¬TÛÎOǼ}|?E=MÉûyÿ&Ô›&–šæÓ¯Dzé{åŒÉ·ÇÉà>Î\c§ô¸ÎËqçŸçÄIŸTÁ–¡’³ý³#$ª1WŒ²or3sȧ ‘þ¿S§+V×þzOD ½Èlb›„ª;%—wï wçËÝL†¹^û!¿TÌJu×ø˜7ü†¥se‹Ï‘¥LÉïL’ ø ”ü…IRž×¯ÎíÕqíWÔóÌ¿‡µÌ‡|e)¹ªî‡SYi¶=C-û)¹½9x"¤YØÔ3WBq„¼}öIköz*ñ1Q%8®Ô,5_c8 iÚYö{„©™25Ér`yOXøõyÑRLã_OxÑ)ÂÜÏ¥ ªÄù<º–Gnw»f”­‡èv/ŒtMŒ¹l¬ËÏé.yW€Úë±UÈ¹Üæ]©fÆÐP€äŸÜÅæ¹_ ¡×ïí³Øp¡„œ^okê…U{l ù­ ÃFMâŸmÿ:ùÜbJ%/3Å6\‰Ñe?Mó[FÉýKáÝNI¶ðÛr?Eo#SÊAÈØÚ¦ ›ûÔpÉ=K†&’ Ëo¦”/ ¡$ 黕´hL­¤)IË•¢Ó÷óyºKÑöÙÜ¥q-ͤ ¿~2wÆà>ìǪlÖN`dZb 6\4™œÕt¼ÌxßaÉdíEשU™jgš  ‘Ï9—ÿ:MŠf‘[:/Sí !áeÌÊì5ö­ù8B©£àªåy ,Ô€|&Fáë0C½ä{6øŠ^Ÿ|”…W‘¶GSÎûiÉ$wçC°#䛾߿!bmËèC@éå‹A\Š0|Ì$bÌ ™¸×\¹ˆ$LŠ˜ìÎT­v{}kªVÖ|ŸØŠ×D7ÔxNC©Vsæ"Ú¯QzPn\ÐP$I390]ŽÍ¦ „$q³·ÿâ*3ÊןBÙŠb¿kç›wãÔõÕÜd#Sã¦ò0b]·:‹-NšpÞ?˜™Å"ÃÇ$ßL¼³c¬Cœ÷N3:Pþ=8ïÛÿ±3ÚÝHVç¢ÓŒ‘‰KZ°é"‹¤J߬“ @6óõ¸KäD;©ê64‚×½àùK„„)Þ.éëH&Éó¥îad ä\b j·­h>&³Üª eUÞ²|ÊÍÊóž4ñifZ™–øÚ ©5Û-Y§Õ¼ _û3iu…ÖŒ¹±ËÄsÐ÷ä '<1×`5×âE¤kRJß-žœÙŽY´¨fÈkž#d¢ÉˆÑbf-Ð{?C‡âYËv ·`“ƒ‚°Jé)ͶüV®­ÍÆc2¥'©sU*¹Öla›Ú¡`˜jüž»ç'] M¶oÝýÜ.?©Àèj>©Àv›>þ¤r|qS—8ýL­ÙĶ5\Ñó-øÛiʬUïdlÅ€‘ˆéÇd)J=ö³l³ˆ|½‘oýÖÃZÔu KÆù"ßÔt)F½²~ÒM¢Šø_Bp›)Ö©¬Ryò›ñsǼ›}ŠŽæíôŽmBPš7Œ]e£wØzÜ/h½t¢™Wž{B¶ÿPþeÕøÿ„]ɶÛ(ü¥÷<Èö2ûÎ9O@Hƒ„4þúf¼peû%E/*’…p‡ªŠeýkñ—ô/˜_‹ï—RWT»a¢©êδÅé]xøôa—93A;Ç5kM‡¦V/¢h‘tÚÒ5Ï/ò•>¢°©½N)ä,ΨýõD3Üýò³D³.7„Ì„‚ÁÝÄœæÉÖµŒÍ¢×¼‰ÝËæ7Ðî^2.9+òôŠTV5ÊDÇPž(®Gë ¿šÓ/³öˆÐ$—\‰*šÈY±™wøî×l†o•„²?Qñi®ÚÍ,-®HÖ,GZì òþŠTñî=B>Þ"ÝÝ|ÍĉΡþöGè7‚úÖx3¢¢*~€ž2}×øPªËjP‡W~…Ú«jù ½ (ïŸP^#ôŠ5è²Jòã;ý.r¨ß–”,ÅSs> 7H«ÃÙáù$Ãb&t…çÔ÷ý34}Pú¾³ctºˆúIø0<ÅŽ¯zúòPGåe ®J^Àéû=ÔýÖ COȇÃ@gNq”ªú4–XtTd¢+Ís°8¶ÿøÄìNK·š0½‘™­uXPl¸y MZM³DãŸÃׯÅXŽ #/‘-™OëR ;ñï¼B#[ 検pRÚ¸ !ÁZœÖ1bRõS¹Nøšpv£MÔcÛÁ dåÖ"™¨®¬Ýªï„0ÿ‘ª*ˉª!‰§Z…ßYRó8f¨Æ#ÿõŽv<"Úñ5ãÚ¬ÞÃ5‰G^W«.'I2Q™ëè>ÃÇg½6”M !ßQ™[Ke)\›ÕVäÿØ4§ï:ºìF5=ç5ãÚ$§ *™ùH Ã\Üßø=Å ú™B†ÚK»M¼eÒDÉ=Bž³Š|`¢¹…—æ dîtV(!ƹ«0òúŠTR¾CÈS&¤\X+´Õ¾AÈ|+‰êô’±ºéæ´@ßQV¸L¸¯È3af ŸñÝ>ÎÕÌ;˜ÊC}0j“ZvF³®fÖ#仃Á¹.×> ²£ãoÇø[³A޳‰lòòºÝÛ¾D¼Ý?>lâvsÄîãuoó°á=P>m÷‡Mì\“ãZk£n¿ÖN%B>ÒwäæœÁ¶-oY#[ñÈ;×äíÏo/î <„ï|ãeµ`(êœ cßð­±cßgƲŠá…+±Š>tcà¤t½}!N§[ê]ýÞD´¼k¦:Ôn_ØÊ©ª¸.ÞÖ’)«HbY½{ú^ë(9טx ®!À¦|ÆŠÏ£98“! ìȃwîÜuŽ®9s+èGO›šõ²^ÜNG׸gBE&¹ì|ç\—ê_‚iéôÔ¨J!äé SceeþêZÃöq;„”׆m“¢®!p;Ý™‚ìu¢£][G§€´ãùï?›ëï}å»R.o,ð©sÖ_Òö೎hð È[î+XsÏ®[ø@Ô]o‰çôîî„§Tô-19þ±[¼ë¬ÃÆ(Ô4J-ð53Z> õ4³ *óFGH0ß®¸+“ºÊ›KñrʵUyFÈÓ;f¶¤ù)BžÛÆ“’,³ªá9"d~¾ÍÐ~L®׌¹õÎ-sèøË}±üÝC­´o¢ ìë‘ãå;=ðÍ^O°ÏQ~÷ˆÊ“BR1-lO×Ì|cGj4àÓnE‡"2ïÚøíŠ?¡ãoXöŽó)jɤ÷µþÇU†ëp÷Ñì„LܲÝ÷ ¡W(Žçý•»Ï½à©eä;…ˆÌÜë"×0È‘cä)gF¯Â±²_ñ^!äºï£.”¹¦œDg&ó‚ì¿í¿ëëb–Ñ8ž÷W'ÏàAh¿¸m\ +ó æ·_I½ê÷ÌÙÏ}qÌI![–Óë®Kïþi&ÛT ÜýüóLN©”ûy~¾p%kHgnW‰Ûçë¨jB-PŽ_‘ã¨A†iœ„YÀJpØ¸Þ }¼påúÎVµ5™Ô,«@â~VÛ6 Ú¯y>2Ýy`ºï)mœñ±’J¤+=M‚¨ŠÕë†W¬8jËgÝ•–©ñÝ‹œÓé,Þ§SP¥w¿EV:õOËéì ³òç !ïQÜ™úøÐñn»vS“hñï||dD¥”OÆ0{ˈJ;×ý~HZç|,½'Çûë7–:þZçD'$nG¹è2aVEÙ³*j„<½/š86Uïs-Wç§ÞVÐ2³7¹«i‰[ävõ'ç¢Íær›å¨D$fÛ_Ht=¶DîćBžÞtvO i¡Cíq>&ÛBë‚wáS¢„ÇG¦¦÷†ǧëãú5`XëØ+Æw;º¯Ø¹j“Ôåú¸áýݲX\”0³a){m"y„ ïh{¾Q >~}ܰ²Û"ršÊ#ò9îta£‹åB^“2„¼£ê—O/ZÛ‘€b^ñu>ŽgãMf”Ì£,‰'4ë5™FeÒõÉúÒç=B^ê ¾‚Þ¢3á1B^Áx¾Š•TAF14ÏaégÈ1}ãraæ˜×o+]1ò–%zBYÜì9viœ¦!ï™UdppPVtŸ>å€ç#‘0#5Ý«nZʈ,Uà…Ä^q˜u·ŸçUuÇâëþ³E(¬`EF+Mæ‚.yÌ'¸f&$dMõ“yÝzl«¥ùiý´§–xÍoìíBÀ$Þç´‰“bí§ø~Ñbºsi&² QY|¿Ñbn sÑùÁ¹cS‚Åp* /™õ{hâœË¥í•­ð€¼¦ä{–Ù2­+R!d^Ìâ1ý­ff6ÚØ[ (nÞ!q‘ˆ¯g¨i»øþ‹À4m]ó_hëw»ŒV&BmAëµÈiÿúƒm8®šƒ-ÝF¨v‰4ø6qÅ÷4CnY¯Rž:»P—:†Å÷퇣ºhfÅ÷ýu.ñhÍ%VÝ4pÍÇÁ/&æ&œªÍÂÐK½"dnjŒi+óÜRÚ9„ÌI­¡·†k¢˜dêp÷KfîrvŽx¼®k?EÙ"§í*`ða±TÀIN ÿÎ"[“}›5yë§~¢!oùJûô'+26³ÚV"ä)p»Û›•¶3¯þ éu\ÿÓ*‹wù¯T˜‹ùg>ïœRªåá%}Ç•>A‡y_tc…¡§Wè2W¶Û˜z>§¹õŽéEv” ½D(µž›¿t‹-÷ÑÃo½¾Bg U¯Ð"Ûlb+ÐΔœ¥®* ½Å¾GÊâ¹I±tæô ñ»òÕîw›HR-)N?úL›Ól7§£¡K÷øÌ¥6LªâtÌÖ7¡ƒxhˆ5çÕd.–^Ñ)]k³#kXr3“,¼ìˆ¸ìÄ)}:¶rFÅÊ|{-Ÿ@Œº8aµ¯ÌCÜڨYÙ„§Wñ也×F¯ÛŠ‘çœ•çŨ>/b]ìOGÆB¢ä§œ¹¤’Ï3B^1»ÀU…i[›Ð[¶ø‰2oàšâ¦6óyÓÛáÙoyEÅK¶Ì½yl½1…‘w,ÎêXŽýL7ÆèÚ äã“ ‡ÜvqºüèÜÂÁ©´Èx°£»²È¹Þ»è­^d<Ø7ÈÎ ŸyA™`¯1§Çj#½Šå¹"çÁ®Òo"c¥+U­3BÑNË×£‰E½lL§ä›èrHÎe…ì2ÛKsHyÇY±ÈÊÓ£FéŠ]­  Œniþjrï)Çèf¡ER˜xE¢#–¯9oKe6ex›¸RACÇŽÍ2ÖL–«¤ !3õ øÖ–ƒ)½Ž!ÏŸÚÇt;aºB:ö:Ý – Ž‚È¥Êåbßdñå&„i5ö EÞ¦TÈ´äûz>ý5­z†9ßä³ên˜ìÝ7.Úž ä)æ[­ Ã€ØÍ¾ŽÌóâüõZËŠÊq|]§5Ö^ ä‘… çLÈÓ† æôpLŽRï €™?.p|ÍK¦l òf—ÛÎæ ®™VïÿÜ(ùþLfó¦; pþ‹óù“âÕ´~c•ÄÈ3j[w§? 6[ÌÁçË ûÚ“:æanY³Ò^!dÆn tr—‹eæl;!òŒ´œ¢ŽAέè2Wy û‘Ñdnç!³Vxww\ï퀦‘¿fUŸ‡>¤6ºCˆzÎÄ -Ó<½ÍÇÞëlä¯G›Ãº4³ÿm]: OŸé^éwÞ^«Çp髨¥ÄÍZ×ÐuÚ0ò„v÷ެ>)U&žòœIô‡?O³‰'EöDOU­6Ýj¤äåëÃ:oû®ÜxÆßyùþ0žvÜÙ+2ëþñ˼S™Y¹² ‡šP_” h†ŒúRd&8a<ÃZÇõbš¦‡DSÎukHlF·4*µm¼~"dV9ß×Õ@…ž£Ik‘³FCœEó'óµqu¸&(™–±IÊ+ -BÅμ"c†“UøâÌ idÙh?rÖhp¤ö"ÃæÙ•Vе‚"§Mº´afaÜ2FÊh•Tä´I7C8{/ƒn*R„<¢<=[Xë.×)Oå¸a$h‘Øš›o!„µòš¦§@È”§ ªsEf¬ó΀ém@^s~¾o2m)©WÑÃ‘ÅјøÏ æÿÌ®«ÜÅåhßkƒ&<°~®i?Ê-x  àR=æ’eY#B^²Pš;Yq›–™ÕNØ_š\²Ú»ƒ(MÚQ„ôéM»#^±ùâlŽd˜ÆØÕ)^ÇÃJÛViäS‹ë/§¡2Ðæ2Òaîæ¨ãÐñFš‘zªÅ ‚ê—¨OGþ ò†ŽáÚýêU›Àt&C¿3hÐ÷3Ðz“ŒÐÃU3–‹91ÍŸ%k&/ôèr’#©E*„üÔ¶0ÊŽ‹,4ê>vat¥ýžc«NÈ[Ú…qžTùÕƒWQœuí~&ä*¶û×¼(ýF†À6—q,Sîîéå]Fºjlò§mhÈÄŽ³àý47Q­HnAQ&:¼¾ -,õÇrs[’«Nºòõh[BŸ¼~*‰+_Ÿ!„¿~*‰ W·ŠJžèWVwžéͺo !óNùZB·žUOÈž]/Ç&ì0—‡¥]tßÓž"äéÓ  nXdü=œÚB÷Óç"ø,7ùâé¶>HN¸l»tÍâÀÛɃ“Ég,öä9jÁéÀÍþÐN±I* 3f¯5Òµ/iÖK/úIô+B^³\hâ~›C4‡ßYäÈAÎ~à;c”®!o˜M»ûe Pï»ÈÔÔµGYŠr†¡ÃãùH64AiÍl43QŒ~ù¯÷P½ö¤0ôA½é¯…öYñˆf>8…µMÚÍC€ž3¨ï&³é°yÒÕÔΚ“aCÜi`_ÍG‚_Ô7¤Ü;õõk=Œfiíá$g êÏþ±šŠVê0X™ä…ö˜SÏšî¤ÕzÏòa³Jl›$ìbú88Ùú=[Ê©,{È\‡Ùÿ•NÍu0w$Ø&jÈâèwõBHJ7UÕ#†‚…aѳñü°ÌKY6ž‚§ójÃÊe™I_9B/q™òÉsæKŸËÜ”Írø¨Óá d/]í³©õsWEÅOÿU[J²n¬†ÞR .Ô’Ýê'ë‘@oÀõö“ ‘5R™òôQ"yOëyÞ•GwÇ{\žª1Ç-‰§\øØW*­ðñ´îJ3fìï ÓÎdTÂÝsnêoßfÞ„°zÚ¦©«·8ý2é»öX-¡ú™x¤ë§N’5½îæ ¹A:¥8‰7AŒ~Öí$¦\x‹Ä8G¸Ðvªvs|îÆšô™Ñ¶ËÆžÍy–#MÏ~ ¯šÚ· ¶%©ÌGöNEÎMEÈÙ"Õ òœ»ÆzµZ¾‘eê‹Ö ‚­ÔÅ"¾£vÑP¹ãk^“x´8ñy©K²E[š¢xÑ °‚~åß÷r¨£¨Yqà»Æj²ó?vÕd¨ü—×$^ïYûÞ„ê F­Åuø¸uo\M8 VI02SfA=‡Oœ­õˆ‘´/+ÏÓaÏ}[Ø*'Ý]ò'=Ûüè+Ô¶ùQ‰1ÍÏ+–&<$IÌÙÅñJ4‘±mGЉ( ÜH –¼ – ËUÚâöj–…¨ÈST2#(Ÿâ®BSˆ•Á’*IgÉê}£"‡“^qÿÜÒèÌ'Ò(Ý'¨:4η‹ÓI-ðD£Ðy´F§V何Ÿ"#SAòÖ…JšgŸó'J©ãHñ×4HQí{£%Bfâ¿M ¯.MW•›L›R"S9ö$©¢¸²î[󰧯ø‘…–¾?$Ã÷݆Õâ»g3¬v¢UϺã]£X %­âàNˆi›Ô]dd¦w¦#©5¸È¨?ïzWF5+õçл"vî{W6„<½wËUÖ-7¾£œ$"›î‹³"›ÓÔK¸fÖäîf2 CVdsM¼&ò”Y5°:j%óO@B±¸]Pz?þ)KxÓ<Å•Qæ·ý6ë*pö½W«9ä Œ<½–Þ/[Ÿ½£â(³žî>‰rìÒȧHäxwµåÆoyþÜÝ”žýö—î&8 äG¿ò5Ùì\Ïvã ƒ»ßò»)Hõùq‡Ý鎑ÙþnÜÝ.#*!˜VFfBüŒÇõ³ØÔgïýŽ’ÞÆ/Õ¼†.ÁÛ=³ËzùŽF~ÊÅíqLqr/×û¶1µÁ.“È7‰ÀçõAÚq ZîQ³©HfH·¸'ßk^ozzUEf†ô>ýýûHàã1Åmöa)Zø6sJ–X˜ÉÓlNa~&JÍ{Í‘TλŸ>Q”x5VÓ4ÁW|?ºÚìÊàâ]IËa¿_°,c*PZ}%j¢PŒ<}0ó¨E7aäùm)³ß¦ž!³RQlÆÒBJ2B+È=Xì·IÀIÏœè:&D‘,ý>|›ª«¬ÅFž !œ¥yRì™tvœ-º/‹wíhvðmæ¦MAÅ/‘ë­^Fæf €œŸlÛÔŽ‘缇ŠÝæ¨T%ÒCþMîvW–m6Î3 SWäÐX@šÃÚ$ú!3¶Ø—ki£»ZöHf*2JMXB"GÉ^õû´EnÚôOLóºœd;–õ³ìvŒÌz ª¨Í±o“Ѐ„ðýžHÀÁ<Ò¦/y¤‹¼EÈLd3Ò¹Þæ¾o[ع2BMÅÛ<’ÏïïjÜWs¢þŸ°+[vTG‚¿äclƒû}nDÏ'ˆMBÂ$¶˜¯­… Ûçv?uD6fÑRªÊÊ<æÑ±¬IÕÀ³ë’OûLøçå‹Ç½;EZû¸*>ΫbM'­”PjO \á¯qÈ>¨eUŒAaúyE&¶…® F;lš˜š8CÈ,VHß’=o²†˜GÏ ‰)j˜¶s_Љ's©ª‰Ô³‚-5ÕÕ ®y{+z6ñÙ©T•€\Ë—Ÿ¼/yð£ßº¶® FfIüÙø:•‰½…`vi@È[*éËyý«Ô ÆÒ‹>F¹ìçu ¬Ëçã_r0–R*/k º–2¡—<ó¡—´yýN/iBfßtH'‰›gq6z tÙwbØiñ穟å¬C*Õ,2{'Npm‰û±â³øE‡´åÕAÓzhïx#NÇ}>'‚éãù®Ø-LÈ0±Áª¨£¹zEHÖ•ÛñìÏ/9hÓWÅüÜQÑÍn¸+Ù÷óïóçç]±´ógXsœXÌ÷\òz”ÚAè|œ8ß Ô1ó££$ˆ¦¸Ù€ûåŨµÉyƒóQÃZ_£˜–y™T;Àj“t”¼W¥Ý×¼¢|È‘»ðD{ßý'î 8*ÕÖk[+x¢cvlÿóÁ±K¥æ¯ýUR‘wÜÚ ¶IvMVm« \óñ† ‹·A–¢í£xz~XFëµ:¼y›µ’zå„Y´Ç;öb‹dü”!a·Ã¶¾'Îì°fÒ „<uíiÂq¦{9wûö†|¤ùäÐõ£G*„®¢:uHQйÄ×,Þyj²YÛR ¯fAÈgb¹… ÷]‹i™ÇoþòyKÞøÔCzÍσ>luû®˜({ÖÆ…1íj@BcµÍf!Ç5uÒ¹cä¡>8®™}t:âÎAhCÈ[J) ÌÔÙf¹æž(éø¢ö=ûy/ñÛÉÁ!Ï®g÷ã:Ú PžÚ äÙõœb«£ ‚Ùá„üèUøhƒ ÕÑ«ðAî¯=Yá>¿µìÊišlñ2ª¬äÙw=b‹—Zͳۿ4uâ|0ûß c¡©["ä÷ÂX#ùxó+Ã'pPIYø>­z~¤U·QªŒ©«Éå«ð–ѵzÐÇû¼¬I‡Œùõu;ÞÒý—k+í펊ÖÄ–y¥Ðu²\cÀôfEåw.·JÑ÷@ÌÓ®† )Uþ1˜=¾Q™Eµ7¿†ø_ŸV±+гÊo_‰ß¹4¾æýÓε»Kâû||ÑBTûÒ2ÿU}tgQ ?hýëæ»Î}$Û}Á”D i‘[r;»^·ÖõÖϤàdØå]¯ÉqÍâ7×kQ¯™}Þa…Ýaá}þš›¦ã}&M^á´O­QÓ’›I«€#4QÚ’MjãÖY!$ô];ýÏУ²ŒýÞCg~~ÿA» ]Æ"›½>ÿú-]CšPÜÉ,´€LiLuŒ1§CµLDÈT?…#ÊNW!ªnê2ÿêëË bI>øú.ü„LŠ.U0‡™4ï„Ùdõ†ˆ&âµ:gÝp-+ó'"³79äHU–½"dJÙŒ+­$½nK BæióÃ?ÁÒÍS:tO/_ÝŒ·D"Š…Íc5qÎÆ$ãîoq¡k±kagã-B&ª,Ô¢ëªZû?QªJÀ\/yȪAi„ôœòÿþ“ÈÍÕËœ·ªyYò‰…Ÿìø¬YCh%Ú²Äoþr@YÓwFfÏåê÷,ébúãõ°½*Bß“…¯t]%†^ã-k/M»Qî›ÚZ%ðCýdÑTÀKWØq¿)2¾šrƒ’B€Þ@ ĦÀ=¶»¾-Ëzÿ«“uÝ K¦È—žKåÖÄœeÉÏÑ÷çwdO9?#¯ß͸ …ñ¸ ·D¼.;ï´mÔVbäõZa­’«€äÑãí_QßÄy¢ÖÜ’•ãwO¬–>k=(¸f†úŸß×8K&4qgßdû`}ÚîÕ÷3ÛeT-É÷úÀn¯1s™ÏR ‰¨“ÌQ'ÉñÝS³#ßh¸s !oÇ5Á,®]÷"#]ñ5ï‰AbÒßIF!^MÍŽBîÈ7_T“¹§#sˆpj°‘d„¯KG&|Ÿ$µË(9Ë×&Ý_„|ÂM>ƒìMZ#$1;úú-X qˆy¥ûñðÜÊ_ßZ'÷Üöƒ€õñxóV‹µ,³Ë÷•™%™E¤“{v€Ú &3LX/ò– CÓ ûe|{¿r„¼§Gn¿ÙX¿6a^+ÔEiü7Ô®}›VâÕ½v|Íüà¢F³æÞKÊž‘ER¡ê¼Ó̬»ªÕRÆF«ü‘V“B1§õ¿¾¶|­›™gÛÓ\A[ÂúÿÄAÞ‰ÀHÄ@‰Uî½·¢x§kÞ~éä[ “³wsŽ/!´M¸üšÔë×UÙ”¥þÁ—“ Ø8ó¯d©gne©m9>">ô[¸ì» C÷ã¨XYüÝ|·0"§ÆöT"$–«aþ}šàj!BbdvÈUAŠUrÚ&BŽûÌÎZ¡6l²ùWJÅ*éük®"ËÆÍ®­ò«¨Ï¾×üÕv‚í Ò óýtð“{8øq„¼"G¿à@g_;%ç†ïÙlõÊ„Wå/ž˜\4ôÄ]v‘ל?/ç§+û§Ö²‚ñù>D7WÒGyÊg?ùÂkå ¢!¯Ÿ›C.™}r7‘êÒíP:}þ aÅ*VÌIõÈuh`­{þ¼‰úxäìåùøVÞæÇXz ¾DWž‚®<ôædñ®vl}}Sµãê1ò‡ù(o<ò‡ùhÅ×ùÃ|´â³§É±màFÊv0;… B>Ó ÐÞ¦\†¶ YÍ™}¶ò˜oÙíSM»èQÁÔ´\çO5-³ñÛy9÷ã‰×Z–HÈμÖv`”e‰„ìÌkMíÁk-C²`ÃoÆ:}£Pª…^ëíà7TÒÆœjQå4Ã8Ÿˆ¸‚°Á9ë³¹+WepÏ’`œ·hƒ R”she%Á8à3Ѹ²N˜˜!Ïg™2$ÃwÅ@–š0Xð§²CZ²þ4ç F&ÉðMís Ê]¯÷H=UyEÍ9ï(?Pýrn°[%dvÆì×øÜÚr]”¥ä"ägœZÁ1þCz u3‚ÐKs±î°•ˆ¸Ü:®¡>äS¨—àu uq|.¬¤^¢ì»zßòú)Ùx»· íË[ï%;Ð’ýÅ• Ÿ; »—޾£¨¸£ü(2¬C´—aäòV=÷¯Ÿ¬f.ƒ›ivÿþ×¾|ëŽâ¨ã^ÿøY*dú2ûä'Å»©ƒ1ùŽ×›VèÖGFHä Ue“œ p'²(&9dJËÑgJãc^S'BfUâÝ´îfošÀ1?2 &ðíË) Ê®µ#*»?BšÖEí,¯µáª®óÀp®Ã^ÿ°*6s¥Ù=ûKã~÷™Í!¯©÷¼Àªi5ÊëyÆg¿Ú 0›!O)Éw¬•6dÈÓÝÚ „¼|b©±=*²Ç×9‡ì=«Ç§ž•A¢žÕã_=+?ö¬Ö(ÒðÈÏ=+{䇞•ip„<éY-üгz¤ÇxG-ÜQ`ƒd”;šÅ–õ7qRö4ŽŠ(kÂÝ8$µý@h@?.ÈËßß{ ÷>Ê !oi»Ö¯eô½ïå8V!ï )ðl¥ÖTË,–eÆ×ùˆ вµ! zÞKI¦rTù8µgÏoÔ)µïx«½Tÿší²or ‰jÊF°=ê&x+NÊD¡Bu‘¨9þþò>ÇNÓŒË>ÒX±r ŽUUPÔ}|¨‚”DÈ“*ˆ« CŽs­sl¥‘6›š6xòùQYRJñ½­¡Õ~ó¶v¶\z´1›(d ÌvL<È߯ã;/šṴÕ÷ÌO˜®NŸ²‹jÁ×yLB§ïóÕÅ>®!4Kµ$ÊQ|kfí6óv\2éœ8ŸaÃ5Ýø6².X«dÙ÷AJM›Ðó×¥Ÿ ¨Ò³oäEêd¯°Ó_`äïI¹'_èyf!Ð[ËR&ö[åÏçF›4EÁ­¤ { 9$á)Üõ,ÃÀ=¥EéÛo‚Ÿ}–WúvPrÁõÆ9ô²·TFÏ,’†g;óv[²ƒ­ŒUR»T1ZÈzªf#G‘°sHåÔÞ‰Fãݱ‹m ÁõY¢’ðkCßWÔËqýS<æa]»;3†pýûÏj ]¸ìÝC×y™{ïWZÅ;ÊÞfê=tG¶•Ñ©={ÓSçQseµÇ6{ã55ƒ´ê×®PT ä!G ôzÀ3B& gÛb¡¶¢¦¯×LK|ÌXº*ÈÖÞu[È]6y¤ qÛË}ÜJA bÉŽ¼&„ÜX§yä3Ibñ†–•õ¼Ì_#~J™ë­Ùq ¼)7"`]œE^ӯߦSö&–™èÁ†À=Kõ)GŽùÑf¹ž¹ CÈËçc.aW(Õ}œÞºD÷a2îÜlØúÙpZÛ!¨ž³4ñÀô“zb‘¯µæ%B^ŽÉ!­K!$îउ‰û»ÏÑÕêùC®,t·¢ò"æÕ¸q©;B_d Ò¨hðy5Ì_'Ó“Qy5Yš9à¼Ò=kz)ëŽ6²_+jëÂ,ïš}„u¤S«Ê< 3g%K^Ñ="ßFÈl¡Òtua~Ou NEn{•f\jæ¢n‡!ŒK «ßX>•EÈp0ù*Jê¢^"¤¯~{;3Ëìe#õ²¸|ùÛ÷î¹Ðú˜/e¾Íüëë}îp‹Øf¡¯©hBý™•µ÷½´LWÉ·2(ýó¯ƒÁ\(T ’tTõÁ,ÿ:Ì•µ{HæÞ«¹Ÿeøâ<òŽú´N.ªßS®Š"ŒKù8Wˆ™Cw+ÿú~iÝøÙz*ÓùýÖ!wãü¢Á…?û<ºþ[FK>L’ #3CÈ[b„W;»«j¨©ô®òŽhaî)-#»‚÷ð”.Ç;bÁÒ…¦›ÜÌ™ÎnŠc]1¦j)„Äê;¿/1ª=ò™=ò– z¦ë ÈZ¨AÏœw[Ê@IÔשƲ _±G>" =8 ×jtÝÖ­FÈgXé›4]WÓvÅòz½×™‡ž ”Š)ã[, ŠyÒ=¨ÃÈPª¡û ÏóŠÖ~Žs{R]ñ*(ƒ_ó†21Šàöj}O'¶K„¼¤H¯æ(»º7sGÈÄÄÊÌ.°Ä$¸•ç_ÓŸ°UÎ*Õ¿Šò%‹!SÖ´+êô·Yé妔Á+G) ¼ñMë´áõ@Vý+äÛ~‡_Møë,_B"õõ l2ª—׆×è¯ÌüFÂÚT-Wz‡cÆÑ[¹TI¿Œ\«zYù&:ŽQ h•,–‡É»…4-¬aóDƒçâS¢Êe• Bú¹8Xû9Þ+D/T“3´Ú ;é´¢ûH¼·KjoåÏx»Å>.£@È˹Tl¯ZH„¼~T€.óvjF<¿Œ_5GÈ;âÆ«DÞTu¼#¤Žùs´ÚY£ù÷÷ö@BÀ}úÉG­( º¹üûh™W{‡~sÌ~_·°+”'ꘀtý%ƒöjãøì÷ªR0ŒÎ£:&°)˜u'mõ%²¥ öÈ特¡OÌõ<2;Oܲ¶PpG—Ÿ|v÷Dqsâœ0ÐÚçß×ú”•¯ä¥hu@^ß¹FV›Sê…B˜ãR©kêóÅÙhìGfN8B^Ó©u£÷Èû(%ò¼ xؽ ]W·pÌûO»êS ;¡yÔæœ9Ï”%ñ1SoæÇ%.êí%ªµyKÖïµ¾g¦è4•ÜÑio½w—Œ×©ó4!dºWîlçM7[é %óoì”â]¡ÌSšM~˜ Èç»O‹}—ê¹S¬kX…‘IoÍ ]O`êrCÈkZƒ¹˜Ìµ¬Mô‘„º.Éy™NtÒM5á|â‡ë¼ÇŽ®Wœè¬(†a„,|Äþgí3[Ì^$ŸšfÀÇ|ÆJÀ¾óvŽ#l6•<Ïì­ðÙ›ºØÓ7CȤ µßÕ/XÕÒ¤øÎ}Ÿò^OÎIè%¤®iãø™2Z•W•RÛS5óë2îÖA7çò¾"÷5ÿÆÆÖ.;®Lõ1—¦ê !oˆÉlv6¬è!;"ÿÆs‡M9¶ƒ÷¾z…@¥ ùHÒœü¸45ºÀ=È™‡Ks¢·Õ0þŽŒ_qR’¼YÞŒíòË?òWë.I²]ÇéÑÛ1ˆv*)ß óì‘—O|JÀü’®µÑ®úîûÉ3B^NÌÇKl>ž_nÍÇ2Ï/·7Æ ×n˜ÅÙ²#äõƒM¹Œ6åy;·)§‰M¹GÞÏ,Åd)î‘h%œ=º®ny¡ ïýyÞáGQ=y’r†Ô“AÈË{/Èú'Í‚….‡G^?Ÿ}äãgg#BþpöµBÈ$¸ö_‡M‰Ÿ·F°ÈÞßþ(»~÷«36íŒå>WyAN)Ôe„ÒšˆaBOàrì©R¿c«o¥¥3Ýâo”µuè÷ßJPkzä5õacÞ{p36>Õº"dRÓº=!‹4F1{Û#ä à|Ø¥D#ÃŽdgÄ‹Êä¸ÓjªÈÚ äó3;Ö†‰¯Luõdz2US¸õuºœœ‘¤U[`ùõØ rZ{ë1s®'…!S¦¨ïfkdÿšë²¯ÒõV¬v§~ÕÃñ3Ñ8üþsDv¼\a6L4¿”Ó¡ÙVç%¬zö~d†{¤Ô?¥ ÌÆ»ØÿîCOŠÃ1cUi÷‹Ë·©=Ű%Œ`G¦}Ýxý}¯—]—þÄ “*,gÏïw Š–M+Ò]gHRõ쾡"\_3¼uÏŸŠ*;àù5û1 hža´Ib]Ί(xNæ×ãH<¸ñüIŠòërÈ´4¾ e©ƒ‘!ó*I‘Óy9I‰«±âÓ3WÊ`wN}Aw¶ì¼TDÁ¸”2Ø}檻£e¬tÅò’•”Gnö[$ÃnØ>{ÐbäI¼ÇYdHä ä)‹Û®a—Ã2sv.Ö5øÉä ‹¯ÎŒZ‡‰L¥óÛíluæÞºy\§¡ÃÈKêƒáöÊÇi$ÍÄA'•§,î ôµ“ö ¦šWÙ1òû •s’g|'JÖeŸÒý¸† Éi3‘ŠÒäÉßß2Õ™ígs2Ndïæ3ºh6•7n¤ã\‘ÆÏ„ïíõÈÌw ËÚx±ÉÞle^‚À^ õB®FÈKŠôë÷f\^éy©Ã­§)[Rªb{I…·DÃÈ›—5Älc´P'',ngÍÏBØ€Ø;ºq5X¦ öŽ‚ìg}` zä3°æ‹Æ]OI ìMÜ¢²ÆûXz®úq.ëŸ=O,ü½s×X±N‰MÅ7ä‘è[*êóºVÛ‚jÄÐokáÿ+¸ÐÙ*ŒëW„&û-7HÔtÐ"g§’ðU”¢œ0‚JCuß'%K?Ìeq€Þb†@¸€I–»þ#C˜k€Þ“JÌ4€Íˆ;1^nó ½Ž”oøN¦W<$Á6ùí¸#Yy]•a¯ñf  šðØÿ»ÒŽN¥Ñ.ì V²·<ñ&ýí½IM]o¼IY³+1!ä5é‚R÷‘èZ½¯fF ¿8¼9¦Äĉìª>\gäÆë³[}¿okz±Ä°B^RZÈ ÔKcþ3!ä‡0§¹‰Þ¤ùýrˆ 4ΨÖóS}ÅfL›òzªÕ VãøjÒ;uÿö•-õQ|œÕ[¼Îv1Õ×Éüþˆ×eï–ð…c,éÆ| •êèTúä÷·ßìd¥Ürƒ1ç~P2ºßÈ2ŸIW(FÖ !oð.á¥_¸®ê‡žÅß(ªf,ÿ¶²ä$f£ãxkä6ø:ŸõJP³Ýß½ ƒ2tžvýÎ/„|Ó+™.“Ó+ÁÅý¼ËlSÙn²®”°aDPŠå‰Ö@ý÷×Çæ¹žö¾ó=óæ÷3m»¹%ãã¤^Ýr8æ+q r,‡•íãêT•à“–k0þ!;¼u9vË}ãn·/z’g=B^R‘ÃK/õR"ä±Ü®1«ºfÞŠ-ã‘·Ø;Âl† !“9¿bV´ØŠYù@ž;ΜEŒûVµ´ùŒ™áMˆ‹ǡٶ vúîyT†ÚY)ðÇ~\¨R[¡2Þ T˾¶¿¾Šg¿|pò4,»qæ_§lÿ#ÃP/9¥ B"ž†œWU6RÁîöãvÌCfm㑼0É›!Óc¶¡ ]‹¦hæ`àâ‘©Ú«¶¥.ÀÕÄv†Ï~ûì¡:Âó¼ÿËCU $üç£úë Æm…³cΤe-:íÆÞ/Ûkšè„—„[·~ï’Õ£,*j¶ÇóÈØdž©kRf1çç‘¡}[›îá}õЦ\ö Ξ£9Î9yZç,“ÙAõª[ ¤[û(§š±Òz›î1.Æ!S^kki¦+ÒvóÄ¡ÏóÈQ¶È»Þç×?Ô($ÊëöÆAó¢ ùŠ{m‰‚ ¤F3Ïö'ú]%ÁÈ´¶iÀÞk’ ëoÐ#¯)ãÈsiª¶Ö¥Z‚Á<òöŽìH¿ˆbšy¨÷îêo]Þ.“˜i‘´_êî]ê⻘ö„|ž¼Kó²+ý. a=õ¼ ŽŸé›µ¾Ð¯™ÛðÎ?¯$µß;m¹>b;\ó$5Ã!ƒ·×ëw!LW!¯ç݆šoÓÞÏç‰c³å?,ÓJ:¦ë¥0Ò>¡\uë쀗™A0(‚ó'v§wšGï72‘yY— !¯©±žs²0Æz“^KŠ!o Ò‰ÔXðñiÛ€î‘wä+èÝ•àcW ð.EæÇ¥iœÂ…™í¦EWX!í“ÿûÛ»¾Û7yäLl\m0w$™AéÀ|F.ɰ°ÐÏ?dvuèŸÿ–‚ª ÆDåûàÞo™'ªæ`ç‘×È'©¼¿ß%ñ˜vB®ƒÆÌ 쵬GHøj¯Óí‡ê×I"d:‚1ï(.ÔB^ÃE’b¹ñ•ýâ r˜äC²ÉgH½¹=™¦~ †GÆó ÕH÷¥ ¾à¸ÄÎCÔìû&U˜^eæÍS±«ÉŸçëz¡­£êü^õ|¡"u­_ÇÚ^¨¾ÚÒBŸÒ yÝ}cØ &cÊ<^÷OªóAK¾_Z¹¥çùZÝAÉ%{“í¦šîë㔟ËùØŒ·yIQë¨o¹îz ‚ÛY‰ºE»Ù¥òZòŒ£UEXEÄáÓo¥'˜ïدûjéo]Ú^yÊïÿlÔFfn­ ë}Jõ˜’ßãûѯO5#µ¶Õé)ýjN„ÙáëççÔ‰aí™RR a5%ÛhjµsjÑN†Ažß´v¨Ãeð‚L&åÜò‹ ·*PéÓ/ÿ¡Åv€üªE5#yšIþ-ÞÉ*ä0ƒA~ä›ö‰ojâE€<“Q¥Œ4kƒU=Ȉ¼«A ¢\ÇŠrDŽŽ­/ÊXßiÜ4 /…Uº;;Ìî4ãŨ6"¯_{û-IÈû›þÿžæ-®7“I"‘2ªäºÝ»‘Ó‘™ër”yz®”÷Ç—`£ì÷E[:0xÍkÖ*hÂLÇÌä´Ë©^$@ú…ž5n™+í6™€'äó _hC@?-»˜©® Èó'Õ·ÑdÛÖp€¼”Ó e‹î`4ÐUm{ 3 úú Pç`:Oæõ‚;XŠq†ÐSž\ÈPóx%ÖÁ»/AASØAZ÷¸e^Ç>¬óåÊ¿@ËÒ)ŽEÖvàxÛ&¸²Î vê«ë j*÷ýMR§àªã¶o¼ãú(¡éª£Úwy„>ãø. Ãåæ0ÏË0 ¡¯”²µ±ÚØ)DQ7M®×ËO¤ LѸŠ@Nzýd/_œsÎЮ`ë)²«@–FÊAÚÊ r„Z½ä¥”‹Ža¶ ;a&"¯ð{† 57&ÚxKÕ,Ûù†Ñ‰Éça€<—­•À(!«½£:mVÕÌ϶÷Φ¦A]ñ= ª™4hÂë§µgc0{1ȃøwª¼Ø±\ͬ ‹Á.ghæËÐUZ¶ @^Ê´¥ ¢2«îqÓNñ…:]IhÛyWˆA®sÆh€<1RÖUV1ÈëËe"ÏŸ¤¶œ=r¤JDäå;’3€¼ñ0÷kR+6›x+}z #Õ,”0Í’ŒäùMD¯4!ï¿ÓDb9"“I¯K-ÃJ6©¥êI«îñFòóâvvÐxée3"ÏQ–À?yÿ!5£YÖ /E Lüð'¢YÆe#=@^‹ª vU«‰Ç9f¼æ­”a5YmÂ2Õ ¿ç½4¦nÃpÍØÏRD[-ƒ|¾‰­:«X‹Ü9W,ä§çAê Éà-’ïŒEK„ˆ|kò•VÁtŸBâD·ÚlIáß¶‰ÉÖeq•6ûÓ¡D“ÆèЛ¸ ɾ~ÎP°¤@úAƒ(Á‘çw¢0·Da$b!+"/_‰Â‹„Èëg¢0Ûª#òöQÏšœ“”ŒœO¿Ëà‰tÌc“ãÃBÄßý|þ}|øˆü2–KͲN+ä|ù-UïH^Ÿo$*°B0šSè^‰2mÑDlF˜ª((‘çRhÁ‡y3kÖòU¬y)äRÂÉe)2x7ßd!#Ú§žÁœLƒíR€¼ï}©w²E2žçà |5'ßMÜd‘²Åº¹EJ“^¥ó¨ 'ý/X†ª¨jZ…»Q €ôiu<ã½›S«Bc˜ È[¦³ø@„øá*ª=ÝûÇr§d¯òùž‘tÁ9 +hL™žîG{¤,,z"òMPÝ5ûDS&Û´oy².Ç~$ÁÜŽùÊ ~úí[a­{z;Eæ*­T¬t“} ¯Eäù]…DÒ›äØ_³ 5nЋlF1ëW(¬}bšÓô䯠±„êhålG°4_õ˜~Í·Ö°)›ødGX)@—/™ÍÖ¼ÑÕ¨!²¥mÂ9ǵ’T4Å ×b&"ŒóÙ˜ç£te;òVZløÌÜÄßæ7Ò]Ê$KÛÛ&t9g0Õµk8íŠ%=çìæM*Žæy®2´Êþù7ìÞ¾z¢WE7Üd¶·k-}ÏÇdŒ=×ÇѲ$zXYݶñ‰äí³4²ÒX;@ÚU÷ÏfWr‰ÒóжV·¹p}MB(ÿlöyV ñÏÓ ÛuA “™¨aÈ7Àì ¥eúÁçù*WHãŽ.cÓÀç¨aqÊÙÃvÀv¸ÞÒ v}åŠóhn›˜}\ŸoÔÞŒ\CbȲáò)[]dxÃØxD^JÛ¥0 ®ÈPakßE*JY;zŽU•öZ`EòÇ5Iã÷TDR™ï¨¤[ùÑ‘6Õ [¼#.€LQ½ÿ½ÙY{N‘2‘T¢á€‰Õ™5pGÃýít°‰«Þ!­:ÈsÙ(ìý­j·Ž› ¸HÐóÑÕ¢nÆRæu;Á˜ŸpO¾±ƒàRëmÈ[ÑJ"b›YNðŽîÀf ûfY«ÍG“~zÙV ´²£Õ¬zÝ€|r‰¹ÔzÅõÞŠ _‰ƒŒÖ0­ïüˆ -07ãâ†"°/Lì5¥½„P Çì¯jÛ¤S·õ)çÐsVð £æ]G9ɶ…7"Ûÿ†Bº ý$mVC!ôùç6±èƒò”Æšª†ËÄ·ÀþZ*€;”ýt€DˆÈ‰ÖÞ0g1Ãzfω> ú(r oŒÖ¯ÓºM“Š3x ú, §þ X%l¤ÑqIï?ÞnÛ7«}Rízláê/w3/ïÓk„ºí•Ü ôTRšQÎ!²ðœ‹åƒ4;í› “÷ƒs¼óæôÊĸ­l剿kójšì;2; ®ê oI‡ÔŠ]» i¦Çž©t@ÞΠÈí5\\!M¤7óÆ‚ßíÍ%·€„6ù‚ò¨ië•©Mº©T¾]Þ”×BŸÐ¬hªözÚòZNE‘XrÕÖ äíCbi¹|ÜJdñ–Æ-M°Ql|oÖØ^(8±{¾õ7$°}íÖ6·+4m"äohÐzÄLÕ] ¥ûîìè€Í~V§Àýö>CD¼³i=`*@–ê$8ú®µ%ë„*€,Üép`© õZ׿,ˇIsÝVÒ¥ »´ˆÊ¾2H‡<ÝÜTKfÌ6•ŠÜ·bô׿Çý%ÖUìrßÒÜÇí§9š.ìÏKÝVÌ„„<í#÷ãSê}Êdž’ɾ7š‚×Ûýí)…Ò`Ýö¼f}ÞÔE?ÝÚ$Àæ’ùt¸bßovÏ“Öf_ª+€L½ù0 íZ@¨ÇæÖ%¼ffDDN@ßΫ0L•š·Â…Ôova·Õ3z[1iòÕÜj³×z_–yè—^K„5@¾²TA$`aÌfÍ'\Køär ¿ ßÑ®”Úe ¡§¸3µÞºÜ@kÚ®ë‚Õ6Aè¹ÌÀ=ig¶”Ôí©ÛƒT÷"û-”­«"\° χÍÁÑw׎*)Sç³ CÇ¿§¸ lÔŒ¡*?ÒCïÑip9™à¾µn]4o¶°÷X{a/{Ö÷³ÙÄY—º·GÎÀwÿ‚øƒFôbäUµui9=¡}NFÆVà‰Ò ä¹D EÔôŒñJBä¥ $‡\hЬ&ŠÈ#/ÀNŒkc“RÎv{Ø­§ö‹hgÆ$V@ÞKžE@ŽÍbÖÒñÓåºóƒä•´l‚}£@>K«¿˜…\M˜ÙUUzž¯ƒ4LìE5J³/âä¹x‘[Ÿ7 fSæiæ_óúص'—±Ì¼Ú˜ÜòZ>ù`f<ŒfÁ*Uî3e=­¥°æ×¦1YË–šd£Øâ˜ïcæÉîJÓ%eÝñVÂt¸ÙÀ5iìÕϼáØB–‹/Çql˜jû _™»AL„·U]êAÝòè\€öØt6WÆ”OÕš%WÒû±1dÞd¶ï‡ß³ÐŒBjŽÁû\Nºÿ€Ô¶®bãbåÂ’Uš-½ÿSpì³`ï‡DÇ ^3Ew^ã‰xdD+ëVÞý"¸Ä%Ÿuf3¼æí»žˆñ@Áíÿ¬‘—Êñ÷óAeþ¨-› %gþ£¶ìù‹¶lþô `„ø„ÍîõÞ¿G©iS°ëÇÛi˺ҹӖ-Zš¿=·4ƒê‡‰…&V홵“ª6œ NO™Ó<PðÛí5]s>0öåL×zíÒ§?þ¦8$š‹F×ëš‘J‡¼ÀÁ½/Ÿ‘É"ð{œf«ã÷ˆ"¯ŸõìÌšÏÃ#%g>ø„ª­øÕDÄm¤äÌ»¦…Ùm½ªÕöÒh€,ü¢•Ö½ ¬ij —ïŠÛ‚$ÈÓý O™À£nd‹¸ç&í».¹ -÷5þî°–²(Ùµ¬k“×Ç÷¨àÌ;½{Òøò”A.£Q~-9—Ͷ‹Ç‡^ZÝëgÎ|p¯l¼%ºAÒºFv† “^˜oZ¸»wM %Xúžç O|äz—‚¦rJéäµ#ƒÁü—â‰Áðx+Ç7þж†6w6`H¯téµ'phWÎ"9¿GbP¨·Ï­“byíQèYxåå¤[D+†+Ð ~»W^Ž,=ƒìÌ*™ÒZÊüö£Ó¤yæfG&iÉüö£Ó¤G* ¯yýBõ%Z§ÚÌãþÔð<>èjkI;4§óðñü0“$eT4È×)H2€üMA’$ptó0çÁ [¹Ç§TÒœcé:hŒâv͘˜…ëtkàЭÁ wÿMn ù‹[Cjg>¿º5ŒÀ­!"?¹5ŒÀ­!"sk€×üàÖÀ¡[CD~pk Ð­!"ŸG?Ξ˜÷Ýùq¦ º$ƒg¤ß,§q˜‚â U>‡à5žÞ¸çÁí»ð­­o½Hã®ÏÛWßúÑùÖ+ˆÌªÓÙ{‘‹É£»ž$à›Æ÷ÈòM]1€®QÁE»Z‡‰%Úˆôm-W‹¥ÊZŠæeOcÏÛA;>F•”)ZñV§¸îy?pC£êÜ\×OñgÁŽ´ñತ,íp¢©õ|Õ‡‰÷*ãlEý¢u~7st±ïÿz·0—Ê JФê@¦±”¼œy?ì}z­òVŽÔ¶VgòNå¿çpÚ¼ö±µ°^fÞÏGÛù'pïÜ5W݈žsN ò™^»ímœHrGÓPÛó’ÔÊ á[g&ç "}sÃÍÌ;‰Ó>PÖGè‡ÐÊËBZS‹Mlš$´[tÇû [JMhÓMyÉV~QðÛ›Eˆ."ÏbNÏ"`Xá¸Q:ºž0°«Ã›ä-Äõnöœøs$ë?ÎÊ/š™8¤Ö*……¡¨³ôLï>Lld'D> :¶ Kö¯%2 ¥ã°¤NÿqéY˜Ïl¸@ ^Q è_g@Ï´ŸÂJûWóLè{ßÍH{Ï`5Y:€, R¼¤„³, ›fëÞä-«iøÁÜÞ›XóLxÍ{îÌ7±3Ï*ý³*v¯‚˜$$ˆIXŸþk df}«M-Ü ™¤˜Üýú»“pE·7\·s™ÌgÚk¶vq,;»‚V¥[ª9 yâÃ|l¡f@"Ë~R²“cCc |Ìë±ÍÑpö}_Æ¥‘S wþì.ûÁÜls’ì¬ÅÈ£o]ZÂܯóTò#/Ÿ*qÒVâ`=ûyž*qvÆÁ}\G¾Ë2¸ Gdâe]{‰:ëAш®†,;1Ü=Í0 ™óM Ð=Í~^'wš:貯Â,Ëf­;óòîÖ˃[¯ÆÇ çcRеY«Yð†ácÞ¾¬6U5‘,ûuµÙÙ™c÷$·q—z¡Dô‘bžexˆÕÖUý¾mÕQ¬*{× $¬ó鵜Ÿíãs,¡—F¤€-²&U ³YB/K÷9+Gµ„,q2 ºαÖf}YOj|LDÊ£aµé•šw[)Ù»ë`ÔÏéÚrXǾÅÈv°wd9êš'JçÜf»Œh‰·Ïµ0ÎË}ÂǼ#Òh Ï|bkÍyy‹XXPXÚ瑬Rs„Ì“t&¬Ÿ•®ÍrWPÏçð¥ï 2ïšÅd7R‰9Všô^Áýl~©”y¨d”ñÛìl=dã´y䜠àhòXj^ºræyûB& 7K¨µùÚ#yIÉIJ–ݾS€Igšò;ˆ?Yâ¸èªQUüqZLZ®£€÷óþž"yêÍdr§ظÍRºnèOx¤=f3ìulgÙ«â€;"+³ºI“DÈk2rIƒB³›È\>æ-‰i#ѯY‰¢»*ðÝáL¯R̬ºÔ>-ÕÞù€^BU± ý¦'ºMŠ !Ÿ_4§«^+8û#Yiß4§MX§$B~xî|wôRÅ™¸õþ—ºõÚØF6}Gá IãÏ·ßÙWÑÇû•å?¿ýN¶kع— «¯…Ñ0W‰ãÃ{Gž¿bZǹ´Êœ¾‹$•,?;~×àülºm+Ë!±ã·S0Ȇo6¹@ÈÔ=>NÉÈZkMeðäŒÈkê šÎCßfžŸH£–«àvXÚkÚ˜…_Ñ=¥ÁúìÌüNRÈOøˆ|¤QçBæö¸}§Sm„|žüÆýZ×kÙ JR8ÍT7¨÷q6ÿUøìa€ÖÄP]ʺ3ÁjW …LÎ+¨¸|B26mlÜðù³<ùòŸ¼=e ÑMæžXXÁÇaMP]Îø9eW¤`é’sE µª˜?¨ì˜Ì‹œòv1?7Ðè=5”ñ,k(S¤\ }$žaF˺¿¬ý0œoÖó˜ÔûÖZÌs_T?@|Ýté‰hš9ÅoÿÏ×Ö´e³ür2Hd®&^O=,º ·ûSØX)/õí×$5 n÷'’ýØšòû»|Të7pe6pkØ‘ST¦ïZ:ª}Fdž¦J,ˆ³[³ 9ËÉ%@>õ º ª,¤ŠLˆ€¼&ʱŽêèê‘Ä2 "G+ oðñ•!§rFòæ’úV!äfɼˆ†k+šÊ­‰s5ùHÕS}EpY:%̺³ „|&C¡£¥V¥,¥ÄwÉ×äìµ71M¬º®î&^Õ¾óÉܶ¿vóà{Õo&ašO){‡.:œ¡ÉXÔª®Õ®Ì"QCÓ)±Pq ³JBã;•]ß¡K7~„ÞqgïÞv©äL·òôZ×±½°ÈÓQÓI±ÖOsÑ3³ †>3¥8&§5û±0ˆ‚†lt6ÁÞ8šVhŠ¡Ÿ‰¨Õ8ÁÇ÷D¢4Ãm†C 8Ñæœ­6QÔÜí "“¥Nš¶¢QÕcǹ­Å‰W½ÔJT=>æ5­ ƹ=Ù¹"òö%¿¢›†Ü2¡.Ð9kÚ‰ÀÈÇ—¬I” òÀ«¼Üç ] H\J?¸ÏrDQ‡Kég÷ù–çÔ¥ôS´.YâRú1ÚƒæJvÉP¦eØ}7éˆ*NŽd—¿Köv^Uokµ@yyÛš*߃²¤²i1+GH$ ä)Ÿ\TÎ7»…³_qc©Šº´Ö;££ úØYBŽMp÷•õˆ‘ìˆÁÿ7*nûÖO%T².©˜ÈŸ‚«»«½ Ú\?ÙáŠ^oOA0+|G‘_¿}G<|Gh\ýŽfói„¼|ó3;X¯¿ûQ%0òÜ­¡®¦†FÏ-Gȯ~F½†*óõW?#³€1·/RúÓ4Æ)Î욟ú:±JÂÅ<ˆ©Þ!·D ³”èûwðr Ëz:<û"2O÷¸("CeâÙ‘—ož}BE…åì–}éer/ôàBtûæá˽ÙñÅ%ÜAŸ'‡6™É“û~Ê‚Õ[¢o£µ&v¦Çž´j®¦¶EHLþp՜݄՛*˜'/f4xÎöLQ“ùR)3¨|:WSòR ¤ã#ºß dQª±¯ôÖà³ßÁ,êÕÙÜUVì§„³_ß<åÔŽå¡ >o%¬Š)ÎiFG#@Ë4¿r‚È*åyÂ|`@X§3>Ï3ä¹×e ¤Ë^ÀÙŸhVËNŸµnY4ÈÍ„jå.Òï†ÿþq>þwJG÷âêøÏ/k²[½ÍKªáì¯·É Ï·2«w§ÌgG²„ý„PiœS“¼œ‰‚ï(u |{FT첄cæhÊØÍººN„Ée:³€w>eüå'Xi˜6íǪ8$²„ðÏß¾G¤3ÅH›eÚ 2sò×+\ j“™J×´l+Øýv¶ß W´ŒKGYF†e†¼ðB‡2Ü%ó„xÝS|ÌDÓ"äý¯©£ê\×[Yv5AÈG‚ŒM&Z¡š QÍ: Ÿ2¸º95ÇŒ¬â€| 8—ZiVͤ 3Fúºù?¾ý­3Ji]“ 4H?'ƨ«pš0R²NÌäg™ÇŠœ_ìbp£ùÆâŒ^@^ÎfÌ6\Ø00 dœ¢¸>L×(Ök­–¸m?ò¯Ïþ˜°Ð'„Ž¿þXdT…´5[³ìK|ð ¡ãÜm:s›Ô:«Z© ¥âó1ÛøŠ<°µ‹ŸŠu†Ùn*v¨ܥLJ©X S±óEÄ6ï¯ÿ¼ Œïê©¢|h@u.{p’Ü`?{<߬µƒ~ŒÞ©(‹‹ÇY£íÐÛ&¼ƒ„T*±÷ H/µãPQ½mæž"äõC£fl;J·9²e³ÄÞ/„™ÜUT+|„¦ÖaïèNq‚uÌDks#ñµRD«xÃ|ö'â>»ÒIe§>eSžîÒ+ DbZnÂ"H HJAÃ5kÉNè+Ãóç·áš5®IÈ,_†kð1¿ ט ‹J½ùÛp GÈ/Ã5*®ñÈ{jÓî5¼;Ix!äe£gvBñ4‹œy± x“Ò׿«M£ÙÚMÛÔO™Peë0H8ª®-u “àYBºñU@šgÄÍ ó’’nþû7Q„\œ ÆÀ[†÷³^,sÓÐr(« óz4~d¦ëê¥M‹ç3Õªs•æDpBJ„|}Lbçi*Á");ÑsèE™tB·MUA:qx5FJEí{srWB0²Ÿ—¯Ž–µ„ç~A©TЧm0 WÊšO\ "‘%lçÀ}¿âÔÙЛ…ED‰¾Ý ÑÁŽdÂï¡gF B¢æt–d>î ßÏçi 7 à([GW¼ŽÜ‹ìù®|(½;Å0•½@Èü…Ja UözÓHsÕ o¢5+;H‘Ù[¡–6±P;˜Ý ¯SÑ¿Šš^•n—e6ñ œýM“±‰áZµWíÚÂøUb1çÖϪ©£ÍZ[-i¡¼õºœ5ÒßÏáðýŒÈt/n}V¾ÌæsošFÎyC‰\û&§3ÅǼ'û¦çúÛ~ô¬Ëm(ð1S› ÿ¹Û@™Ši¾KÏoþ¤Lj|í‰ñL”Ê餧M÷ѯ ÞùŸ#ªõ-ûL†Ä– C³Ä™ÛírðÖ¿Î’B‡ÊEEM†RBÃ%¡=Œ°Ú±¹ÖB”3ÅÈŽB#ƒ­Ó¤Åñ”îoÎ^=–wW1ÈÇ;éÜëLÌ&üo™„Ä£íî’FAÖE3}cdhKôM°VQZÒ âÊV¹$e”}’b⌘¯¹BÈÛ¹Ñf7d×hS"®L¯çï60oË^©ç?^Ñ¥Ûû¾[²›ŽwYBipYBtÜ'ÑJÅ5,ÿ9Å,çŽYïÝÞMB!ä·iΠՕÿœ¸£X ®S0«’ÿäX¼”ë­„/×u晟ï½únË«*—$jXûcŽbª…ÜaÜ3 ¯_Ëkl‡³_ÞÄ U­3ig8æõT¢÷¤^×JØÍÍ/#2?ÖÚ¦ñc”Ùd”yAYBž¦Yí¦iÃgOT&ã@›YDDÁês@"•É6¶QlÈTÌøwb•IOÇÕœœHŽxíiÁn…T@lÍÎf¢aªß¬ÊJ´Ž7äŽ J´íÙE!öfBÈ$ï©[ßC2SÁ7YDž<%TDé8ßl2ùÙ,³Øüç¤#åßÛYHoÒCåèòŸ³¥{,J¬Ó^N³yD!/©ž/³¬ÍȹÖMœ{ÊkèùO”íöXÓ¾!o ÏÜD+Óz‰-W6!-¥¨šÁêž=s9ã+J'dÂÙ ^¨µÌ®€OpN¶wÓå±Í®ªzïõ„¯æcâ±¶kÖ-]ÁñÙÛúâ*sÕ&f™'Œ¼ù¹¨0²ë_‘i­4¥ûº"äý@ÚxÉÛ?,­iµMòqB:+‘¶ÖË´|ÌçÇù-f•$¼K¯/“^Š;$Ì0åÙë½#ŠÏ[ûµŠ®<ÿyï›z¶Si˪ZÆöDžšªA‡Õß¶ÃjyòrÌ®Q°ú)Í^¨À>(OLÕ/*¤|æ]’‚ôõ¸!ä 1ÎÏ‹¢Ü,ž„¿yvÉ~g.¦):ò<û¤ lwC= ó ‰yùnñÄ$Bž›ÌÆM3Çg¿½+Õ,ŽÃùw)Gš6N ΙX-8;âǼüŸ/âüú;RǼþþmî°#ägõàóï2yî^—š§¹ˆnZ;‰ç‡oSñÓ·™_¿|›l:}›ùõË·©øéÛôÈç¡øä‘Ýs_G¦ª ’„ÔÎΪÚ ¿Àœ}žÁô/Ïq:QØ¡k ÔÒlG[1Ÿ×¯çGbœNœŒi÷3‰i?ÎÔ2™¥vê^çÀ+%^1B™½ÉÏv£ÞÍ‹Lö"dþnkæÊFæ¹Ç©‚€ý.[¼ð”E˃\zÔ*„ô,Lí—~U¬yE‰É#Ý# o±¤ì "Þ"Ãò5…y¯ðÝßû°#¨nê{Ò/]²“ºu’mf ®|ÌgŒm øâ:®*«fÕò•¨ÐÀf;Û7)¡ÌqÉ¿Mô.»ÐÄNúEäåÛD¯õ°5;‰&zm¥1+˜æyy/’w§"y~I'~>¬`O&¹ßµK¹ Ø‹S[¯7=´Éê¡Á1oZ)Ñ’§syh¥äÉ,õÂéq?Ÿ'›b ³,ƒ©jŽI&åäÜ·)æÁkŸUUóxÆÇü®ªš`yW‰ì¢J$ _ßU"¥S‰äùA%’G•HßT"µ`#ÓVBY\æÎìƒùŒòн›om3bvé[2‰að;&½²hâLX³é •ÒVoÓÈ8Ýâd@^Sf< -ÊlÙéï;“ðiÜ2[Mq³¢ÄXñš¿*¸e¾ÒÕå¶!sÔ\vWßIBÍ¥Q_óÓ´SʲȕK *Jù5?M;/ç²aç¢"¯)¿æˆhùÄ s´­V„L €¬õº‚Ь³IøÄ€)0¬É–Q5Émhf„|&úYñµ4ÝN×!_‰õZ˜×4Çl§Á&œøÎÿ$Cv¡x1öÕb¢ 9áš¡¯3ª8™0=a¸ä ƒà¼2i10³àLù‰ï×°4ÎÁÛäóî&Ÿ%>{0¤wño˜³¢u[SŸ%\¯tP‡é ‹”¹ad~°R¤h–ê×jã³—)0é³ þ¨µ"ãÂàmºŸë,T#ÕÓ4!dŽ-Õ\ýb^ôDõLK„ í³¿œ>Ql£Læ~Eáwždiý?®d9B þ’ ôv|÷q„çÄ&!@ ö˜¯­%Mû9|Ì€f“jÉÊtño«â_95í†É{ÞÓ —÷À3zžõÈ\QWs¥k%{ûŸ¦r'h®ãôrÜòœ‡7çЮÄCMMW=ŸBfM%x–²]éÕ£äËJÖðÅ¿NÍ;Ç72}™ÕKŠç-6òsŒâcÞTz:ÎBFåtêmC›~¤ÓÖõùøÄ|–ÜÏ“MšÓ’7ê¤Ó붃};št¸Êbç2Î[r¡lmÈ,*¦Þ I ‹]}Þ§D[A¶}‹§ùþq‚’Ô›å^Bts»½›€ ¹q„Äß& Ûu_ @ÆÊëç³ Ùι»˜Ê u¶sÍ–G>f‡¦‹ZC-6·­Ö¾ƒ³Ç=ߊµ ܬêX»Ôþ{øö†2‰Z±lR‰£½$÷3}Œ:Ö·Ö˜Èe>xhrÿB=a¶ÈèjOøâþý/4LOpÈ?È•F¦Ÿ)“°#ݿѴԙ2)gyC.³Çj1Í}Þ[‚¯èråéŠáÚ  ¨Ìj?êzhŠÝOyOa<6ŒŠ—ìàÔ_ï ÖõÓ•ó†t£‘ \{ŠÈAAµM‚hÕ6ˆ©cW„ŸŸhr„·ÛÆ·ê -B¦Ÿ Ôe×b$!oó`2¹b?Fo„â·@à2Ÿ‘ŽD¦^:Bs|E÷(çkܮݪ\›t ïæÿ.Ø7EÓu¼Ñü1Äírbû把©­*y`dòÁÁ€WÔ·îYT¹A;—®ØZÎ!3LT°g—‡ÊP@#‰çA"ú±‹QŸ]Yž ª9M®}oeZÈÉ“×L³¾vެU‘²œ2 5m `B»©Ü‡‰á;ºÿéÑ->fxC ¯¸Ä[±OKÔø$š³°_\é®ý¦uçj™|¦ B^~šž(쥂®E5ÍS;AæqÇ$;G··5ò•ƒ€ºr™øñÖ•Ö‡d¥sN+Œ . ë׉£¢-ÂjM2Zë¯.¤+Yì=>æ-2X¬,‰^ÅéË8ŒÜ›&÷Rs·2!fj¦¬ºa.Ú­@ÈGìg[M‹J§/†°ÒûoåìªþDtùB.ó¹ÊVs^Z|L'ò»ÿ׊üZ—{"ëy–`ï/,(RTÌò´‹XUsõ@ M"éW¨×UÝüøæƒœ_ÅÌ„¹ºz®I4¾ñ¾:016Pz\u(¬¢ûHµ4*|K“î=Ö~œœ‘@é§)›–ü PF.?–LN½R£æçìBâoÉDle]­e.«3–¬fv€Xå ÷ªé2‹¾%gÚµýJÛ\½Ôy‹U?ͳ×$?0Nª"¸¿ì윭dµÊ »i;¼ñ“C>ü¬šVÍx‘ŽV‡*t¢¡¿lrN˜å+U/^9x‡|ÙÎén”çíïä+©[ºµ^ußßyû6+¨2­×º$rôéYÇæ †g’xtçâ2äGòþæ‘°Š?¢ÈZßýªrö:Êà*Mƒüøqöd7ù2[Cä’O<ø¸£îTaõòÀÆ•Nyô…Ü‘®£CªEg\Çu®óB;ÖÉ´ 6CRWIçNòuDÈGä´á<8U͵S£ùüðŽÌTæò™äº"_iâ¢"Ÿ1Ò’ž®_‘°àEÌ4=gSù±>õæ5d«Á¦5y<°Ó}鵦ô% Y–x†©)¿1™zœ ×I×QsoÑ›<xœ³ªl¶) !u½ï^¾)‰§¦® Ƽƒ‡ôü£`¼j¡ø!¯l…ÚSÁ8L8]4tÁø„ Êa¥w6Õ”wÐŒç~¼T…%RB{AJ„ ¶Wvf˲Fµ Ý^u™B: Ζ9‘¶({„Ìb¤WMë{:Ë‚aäíÚBm⬃ÒY<·d©LÚžÀÌô}9K0¢Iâ)Ÿ«VR ‡gò¡Ecš’…Rýó,,œó1ÔÃ0@¹ã™]ŒÜ2'R×íÔ°gv.-;Ó+=TÌí„…g†R*Ýšsláe""ÇÑ d† … P„~žÈD`iªžÑÊ»aïð1£AZ»Ï™wi¥}.'†8qí>¡Â •z‚O¿Ø™) g'EæY«õáûùŠ›$~„Y*­ã Ƽ< ßÔQB¢;ïå'I½©;_cdKjzùKu—è.I‰Ù‡gD…„'2á wÞøë;ßïuƒw¤hUå4uOû+ù$~î­€Ù\‡|ƃÉÔÍêu,ç}ï“ò‹8ûj•NŽí±B!4L8ýþg7d7§©q¡;Ü¡Ñú Ó»ÞäÊÆÄÕš²*'1´9l±Ï{$^tax !•~>þ6<¤ÑÈVÈ· ,ñG· Žš”Ж óUom#ˆ|ÌyÕP‡A†kMÑë‰1 ó o›ü´±µ <Ø0ãÚCÛÑ=éÛ#³h"ÆEþí2.‹dtÇ¿ÓHfYsor­—…C}Ó5BÞ R冯úÓ,µÅRõRêYZ„|„†BéFR„.O}®è‰4BŒ’еÆÕ­±Z–áÛŒ²3KÆtdvõ¹Â9ýzâðlNÛzsÚ4ùÇÎÑÖ®`ÛwòЕ;‡üþz“ÈóEྩöjõûf›¦ü8Š¥C.š*"ŒL‘Lù‰ZÁˆŽØú!AÒR5jŠvwÙ·™mg¨§YNÛú™q­Â5dÕu©EÝ0òæ õA=H œª‹“ái>P†rq—à˜§fJEiTJITPÙnp—^g2OícýG ¤~¿Þc0ׯ¢\ÕRúu)bø›(tÂ’ÕƒÊ#„L"¤º<޾¯Û6‡=.9}q¦®X[AãžmCτ̢§é´½„¥*C 2‡¬”sR5;Úº'^ÛÀ!ïa—aµ3âVÏæÛà):ô{tŒN=ñ¼T^ ×þýf³\Û‚:“lÙ9[z„<‰9[dÏÖyëË!Ó‹+šÙ!ÐáF¼‘1´,™™u™[Ù!d Å»T+·ÜŠMÂ1£áÉùIJšÛ wâNÓx0â~:Õ’£Ê>§EíÅ]Óäö Øž )»|ÎÛ¡EÈè­óÖG*¸+§vãº4y£f¹á*îó^Ð!Ã0¥5µg_+mýéw®˜òoÈ^@Re|rž·ìÿNWSi~¿·uQÃï<7O©Ÿ®ÙPk…+Žè+nQšò>W7ÞÏ“H]eXL…¾m^ÃÞIÇ›qœ¢öYOËg.s {q‚«šéD¼ÕOÌËQà³g¡Ñé«1㸖ù”oFÞiâs?)kmî²#ä¤PaØwdD=xÆ&‚H¶ÔѽºuíjUÖB>=±·rM*hÉsRåmÞ RçH£.®S{A¹ÍùorŒc[y^º£SÙ6õ¹v‰Ìï?èý$ŒqQ„X1Èê.•PÙãY›q.à.¥_!þü±{‡}—v•Bk]Ïø˜h̵QNÙ8öð;ñZgß;XFs®Ö»&GÈX€×u…´ !—K_b$ vW¤Î®h¶`d¼#„÷³å*‡öù{;üZóy/ÿËÛ’.¬Ï2ÎeàMVW4¥×TsÈô©ŽÚ/uÙRcß· ðä‘"§ó¬¿#ŠwD†´2ïjsmfÆF|EvØ×‰¢;”†Œë–ÞÀ×!­ð?î;2˧Bª§®Òø!_i”½Üš¬IÔ1KŒŒ½Jj׿ëIY…Ƚ ­‡~çÇÆ4””3¨Ô¦izV¦ ›žªïc§pþì’ÒÒ4ýV“]å5<ÏÛy ÜÅÔ‡hÊ£X$‡ût?5mkjÇÕʾ’tÖÍ#ƒà÷ÒË:–e·ó ÆÀÒWU h\2Y.ê6Ñ[šFUU³.Vn]\åÚÑ6°{œFMÂ1uCršÄ\ÃÙ_ŸŽYºcn™|ºö½†:û¸Ú‘µãƒØ½EKY\“×9óûÃýd%Á÷3øô&rM³¦]‹¦ÏyãkFHꮨê$› -Bž‡¦4ÕŒtã¶ñ‰ã³»Hä׸Lú;û [ì-ÖÝ»¯‡ WlEðc*Ú%(ôñQÅáü·?¹ºj4ð`ÄL A\ô@NÁÃz1¼+µÕ\áìw†ãOo¯³¯ŸË¡Ëé©>î{ÆéýëmÐæHåÞÓ­Páò† ªÝ„iï¾èiD®uyWUVýÑ·¥¨2–€pÃøêÉ7E±íð%Ý¿ÐúM¼Í‘~CÛA½) þw?¬gP“Ëq)‹Bm øÚ±º–}î%«–]%ñ°o[äó]4ÍÈï“e­|Ï£#¤˜ ØOc ¶eâ Ö±©˜ÄŽ‘I¢rä1¶Ì„̳q‡D«Hí?Gšs ÙÔ=}ãˆ4Þä™î¢-Â¥§³û+Ò5z*¦P9ºÇVCN¿ÝÉžµÑuDÂÓÌЯÉN½•ËÎÕ‚~çíÉ,]V!ÞêüFå÷½ÑæùœK°Oï§NpáJôL´ßVyÙƒDÝа†Üï'»ˆ¨¯½A»V dö~—äÌí]‚³cù „›º¼'K¥¶<òÝÞ ©ís×»ç³@È$ÔK§ç<.ÓB÷ Ô2õï&f~ðŽy¦3[I7æ$ݤ„Lîq?ï°î‡Z¡¶¬ÚÓÇý)ëˆôázFSbdê×y##c9"„Nm»rDÈ,ökðŽ œp•LAüñ8W¼üEM–…ñÆ ¦± sškß~’#\ûó4À¬ÃZ;úÈIÑ/”cäÅ`Û²jyÆI4!S,ØX‹”b'ëÚP„ÌÞGà²6#pBÞÞÇÕŒíŠWÃÈ;Ô¼ 2SÈa—’A)r ¸|CDo ÿ§7DBf½§7DNoHª°Jï^hˆbjû=÷£é#6h9‰íL<Ÿ@(#yºÎÌÏÆ!¬èª¢ÚÕ?Íg$ñß“ÉUVxDer*œoäŠÉ§á®ÜLÒˆÑ{„5ù™üe%xÿë4âþ^Ø(–eèÁGÜß+3T¶û±äô÷›Ö±IÔ—ÞÏb¸K7$³iG"l½RD´2Üùh ±üBjwx3Aóñ„ có¸è4Dj] ¶#d\-ÜܼÞêi+‡R"d±s`ȃæêd÷ÒçãÄΩÝè£Ú±kÚÊbÅÀ×|—³#Fø#ÓwãR‡ÜOgwµÃLrüZ¯å¬‡Ëà.=ÏÖb  ¡e6}74âk^ÕNz`¹¥_ó¢vr°ðÖ½¾Þlÿp?Òó5Ó˜[!mÏ#’L_É»˜€ C[JâÇ>Óˆy1´?Ï`›^ð ƒìžŠízX‘Îû¯ó,h\t!ÙQ–pö2ŸsÚÇf­#|RK“È2‰GÀ*Ç]Óž ¤“Ò“"¼ùnך¨PWp—Âû¹ÿÏëú.Ž^< Xi§¯Ç›°]m„ÍeЋõÓßù¯S_ú9‡ôõ<±õW{Ö5á+Ôt_ÖÌH+¾Î53{횣ÌÅ$[tHÄ"²$ú¥8Vª²_ƒÌ"nånòâ²öO#_YYL‰®Èó ûQ%`e}}_™¥™/nV‹÷ÚôB&a?*k_»˜v]»ð1Xö• ñ¡ªù¬"‡Ï"³¯¿w‚]ÙWú§D^.|M7ûz3—uyǺrVp¾{©Þ,b"^Šé0M)­_ˆé‰æ²XiÝ~q*Z³uÓ䇩ìëTá1 :bé„ù—ÀøÉÖù?VÒÍJZ Rª˜ºfKËÖžw4…(¶#Ówf§°ÌN¥Ì¾˜Â2;ÏÈOOSÅ`®ý_˜Ç\òu–á²èfd½ìhU ·#dß_'S ²¥õV¯ãÁj„<ùÝ0kÅÚn£º¹™¢¸ÎyÓH*UÆçëÙÙ7®/Y¤‰~U´ g2†yûT¡gËê¯=p¯+ôÏgAÄûªBÌ9¼Ÿßß(7´öú“_)aã:µáì vÝs?M·Fh³ïä"3Õo²ž¦Û‡nY[„Lã¡}f†}5»‘Î\ø)š²ÈËÊÕµ< mëÆ[ fßÙYÊÄ囹ÖdEÈäÿ„]Ù’ãªü¥¶l÷ã¼ß‰˜ó hE mÄ|ýe-(Ùî‰qžr¤¶„ –¬Ìé¾#ƒ<„ÁCr!ÈçˆZЭoÄ4ÁN{9;+TÖÐî´ÇЈö$%ýë¿è&Ò :ÐûW $0üÜ䛯'ëÜ0—þ;Aî›:‚ŒýâXÎú :3ùÄbL>V,‡µŸ#r9;¾øµñÉ Ð!¯Á©-=µé°ªv§¶GÞ^'"‚%<ìu—ûç‰e'"B~˜ˆ0Žô@ÈÛ ǹœy"áH.ÓöØBÔ*’p+1rðH‰‘o§•¨Q„H•\žŸäϦBRFGz8äz2Òöä5½’õíËf£óMR¾¦ö¬¼šcÖA³€ó(åk†HµuÏSpZîl­2/½üïÖî u!³ÐݵR •3¬=(„øš®¿ú÷·¯±8Yƒœéè&9,Iøšö`¬ëV²e«Ž@;ñHÇz9‚«šÛT^ÒFð=ò;Vö*/jvÅ’À@ Oþ+QýóÓÝ|šs¾Í4nÔÍn˜©’ƀ C+üë/14¥›øšš£‰¯éòâýܲ àSvÓ´K„¼†q}ûÊgU¬c„f’P£}§P:15»š¿Ã§ä‘ Û6!„¼~ôñÁàî·;ÔX^ÇX^#)µÔ‡L®uÙ s¹ä{EB^?A±Iu§ÏCPÌ AqhÞQgÊkƒ,`»Þ?Þ§†çuÍ12µmí-ëŒjÓÁ›A"d ‚¨ZÛM²ÔðDK„$ðŽÊÒ󲆾ãma 2ûX‚29¹þ#°<#¯©ƒ»·=Ñ1zcæ#ù|1þs”ŸYÌ]Ñ3™S„¼¦WžÆÌúÞÏ€ü>5Ú¼ñˆ±Â*«¥×`ÜÎfÁU`ÿ.U%+^õB¦ŽÆÇ"Ë¥( ‘ÛnuA{·óí]8¼n—Gëg(Ä‘”à´mÝ×a™QùVNy;=»™nâ"P IÔs†_ä)W 3¿ø‹n§WåûÖ¶uÑ©ñ‚$¸(%8Õ(ÑUK‹ 庂¶Ó{™ô›:š°-ÞÈIo¼òT…U0ZŒÛz„„ñ]kjlS¹uÔ¹®ZçP0ôÈ[Ð/,°ušƒT Aydß-K4'o…[ Ýx›‚jÝÝùÚò!ï¯eHEA™Äw|B2 GùLuoвt}1Ö=ë2KÒ„ß¼ÒŽùE:›àÍ® ¨¾ÝÏV°®«ÞŠçû>Äò8­Ïwm«ì¹þÜ;‰×To¼õ#‚]éÚů;¸ûf½ýE›’ÅPŸ{r;í!N’Ɠº|¢y‡I+¤‡úšSQ,k_ ©:·÷¢ —™6zWŽOé,8Rú>ŠŽXÖqìJ%msM¯éÖ´NÓmØa¨Œ$JÚï”ó+5†Ó0Q½ÆÊù<ÇÊù„|¡B\+Yq©r9Ó@ü $µ;ÿ4X½þ°RXó‰êµÑØ/àš«äTçÚ"ÇH¯±\ì©­‘Cµ¬lå‘÷8 Súf[öf4æøï|€Sú‹t´–¡´è‘ÏÔÉ%¶ÚFªå+B~§‰dhm7F&Yp÷ q1¬·.í™4‡•œUß4Gú¬u ‰1Ø›æˆNá¡t“êx›!½ªöHÃÈê»MBB‘èxe©Ð–š ÕiPBÚXñ?[¢·ó»–Û)gŸ-§kÞ>XHÖ±DOÈíƒÛŽ÷å…huŸÏH‰}y!ÊV~`žAÒGÎEr[%6qŽÁF±7;Ü“¾½’ÙC¦y’ÃQ7pÍHúC&nLN#«ZîK\uϤ‚Î Üýù¢n|òÏŸ‰º±KžgjgåôÜ”’ú -Óö:r*ÙíÊ!u´ÒöA%™L“°zf6‡7º¡bc|›I‘<óϬ˜g5ë´'¬äìëgI…<ó=òš¶M}j¼ÌªÙi7adZ@ð¤Es"˜ø3˜{$Ö:Û˜aôÝ) Í’ÌPÁâÔJT´û†±IBku;mTñÖŸPÑÅS;¡µb5çMïr»±áÂH‚ ßi‡²©ö!³$ï0«®¶¤¬œhs{ä)ü×®¼Ö5¼øâ² Rü+Üx¹-}´1ÂZévZ³{çÁÄ|Õ‰Ç1H‹øÞ¨­ÿ"äÑÃîiº äáýƒ¸bÍT¨¥DHhÞ¹¨ÒEA:ª”cßæ7<+ï@Ì÷ÈD§ñÂ\f êȉúk¨ñ>‹\˜¬u Ì „L)auFaÆFf‡æÝý¥´íÈf ûй_^U¼íé1G5ãcÈ2©3Tžª:7­ö\ž®™¸éùmÞ;ëy›fÕ#¤W þï×Õ5ÍÐnÞNG…ïž½£spC爧vBè}¥sp¡¯)ò3† ©—¼¤pn>.'I r 9ê ”Ö=F¬shб\•ú“§+>°œDDnUtý"^wGzq­®Ú¯OZû¶Pü‹]ê*Èë.usÌ ן\êÉ9SkÛ©„Ù‘\}è("ÿ” ýî,îüð ?Å»>‹„„5ÿÒGØ{ø;³ÏU¸&ß÷X§}`ï¢X…›VÑ7{ cÛyKâ%ÇŽÑû|I§JõÐ’{Ä=$P˜‚¤W©3Ã*ö&Ùiœ®òB3]¡—´)†½îq?Ÿ^lÅ8œòbÏó!±{Ïøº^ïËs)òå9‚ØJWT:™áSüŠOºÔ%ó²€P•8ô‘¸!d«)ùë?`*&ãy½À‰u©÷_&ïÙ_N§¯[×q„|œÄ(Ý×13S‹‚_ô8*J©–Ǽ̹ê{ŒD£(¬ö£(FÂCÄòxœd+KŸ•ë¡ÒÉþ Ý«ÇQ¾mÅ‹µ«*Æb‚»cÚ^îä ­Lmßë È çѳºu^eåÑ Y åFX´Èö¹‚T«<öC9’гÏ-xç_Üóë“\©²Íz õÈ“+%?˜š*0dAžØáÔ½#ƒ¬Žrבr»ÔÇ|íÀŽs¿PÛJÙîórr~&R•ÆÏcÂO*Í|¸¼Ã]s“ëû½‚ßóÅåÓ©Iè¼Xmúo÷5¼Æ8ÙÜÙlw8R?9ò$Ÿ+{3ŠT#‘û©²ºHU"dê}ìv¦ÂsH¹ˆ®wEC¤±$ö&ØwÉÄ!‰±ñ‚2ùf ™˜CÈ&«ÐfÓç×;CÿN/Q§?`ãyj–Gì„>? ÖëwDkÞ€^>IhäøÉ3«Qz$‡¿òà2O9üÍ“Ýçã•f† à+Neß@ ùÔÄHä|ÑÚ¢ª^ó^Í!;{~Ÿè¯ç¯#þ¢ï·+Ù¹¯‰M'BÞ>D¿ã8°!É™jûq– OéûëPÈø¾¿þA…S;þã]Í<Ê Ï”ÂúLèîám6mx›rNÞf”Öïè×Ë;ÒÇÑ€hè¯öâȃ>cú"ÕïëëðóÃ_¼V•„5ÿ};pB.Óì¼.{ e}¿qQ±‘À\Lú™W¨ì%z_󯜿*[¦CîEðïì…êï"íîy¡TΣ“@pá¬Q¬—E¿š ì„L+mí];¡sX‘x¸Û÷eZWó×_g¤E%ÄøØe³oÞPÂô _#@ç:ÍÕjÚÄlŸïógdÑz)–dÂ<’Àà†Õ]sÞñlÖÑw·r„tÈßÒ1sôêБ"¸${¤óš1¿~‘ΠÕÑnúoEÈHô·qƒÔ÷ þEOG±sUMoP¡óÉjFŠÿÎoäåëuì«cú‰•øÉ} )˜g‘Tqù•¦ Ý!äGš«Ö!oŸ&ߢÀ÷ic:M¾EmÌÀ6ª¬KOÞÒ»—ÞÁT‘÷·“o»ØŠÈF߉%æÛÉ·°1e_'óxOöwm5èåÄ«¡ç^P×íZý¤‚Zöu}± Mýj\Ž5B¦”—0°”|ÔÇaP7òHP¼3›HJQläcßQ„$HÝÈnv¥aÚ u4‹<2KÃÊPÐß»,Öàø‘}ÝNaeáUm©ïXÐUͽçÐjj¼3‰Ž˜¸êvŽ·XŽ1Âæ§o’o‚q‚ôMý_RÀ|ø[ì•™;P{wÏùÔÑ7 Oá‘÷¨¸Q7®ÆcÃß¼îCÀä‘SñוJuŠÆeÑ)YØ]Y§ù‘£Äwÿóá*LÏš͘ˆÇ»ŸIœ*¡If:9.hÂd_äLqkœ¾¤Ž€ô¢ßyPeɾÈy^¨r…}ÍJrɉ©’\¨ ×ÿ™¹‰5>¸Ù$L­!=§ö—W†v×Ôo^'»tBÈGŠ w×ÁêÞŸ‘OtÄ:“¸}[¤ÉßñÝ¿AÎîóVw¢Ðb-€SžüWؘ̮\¹ìPïÊÓ‡~ôÑÖËÌ·6åäêÈ• @ Ðkâì—è ö¼¹þ·ê ê&¨CƒÏª)*×JØ óRvs©ÓèµÐÓÐÐK¼eyýP'±Nî‘7Œt#KJobGQI>VÔ§PQ÷È,VZ<÷Ù06«#ߪ –Þý'ñ™–| ‰9£݉cÔÀJ ägÇqàLf_ÏŽã6‹?„$Ñ5äh&›+ŽjÚÙ×óe`? ¤Ði¦=‹‡R2Äjм­±äYw·S†×ðZb?¼³±¡íž#$˜¸P?4dsIC˜gŠxcö2;”ª¢˜U¸{2Ze9pÊC-½-–#d”pqÒk­3`Ø÷¾ µ÷,Oÿmœø‹„ª‹µ…ƒ‰§Ãx‘]Ÿ]Ùˆy€õy¹¼5Þ`nÌD5+J—àE : MvùT6rnãÒ”_óöq4:ÑÙåöãhjY!#ç¼îˆÑ!eñÎR™u{$†!ë•—´ÍçË.©ƒ“«rÈNÎ+— Œ¢gq jÿû˜äVàˆ§ù=ÇHò© Ï .‘%ãEúyþñ«Îs“T#x÷ÓØcZ‡4,úƒ „ŒF;.qԉͥ䰖¨ƒfg"ê Ì=+ ,‘,ÊÁû>„«f¤NôE¤œ³TIá›ñ¢’KÉàšO$r™\snöCoË3|qß?ˆæÏ\´¡†%c;oØkúË„5Å£¾oöd@^{5 ýÜ›¥Û›>ðI²ë«´j`¼Ó¥)TË®ç<:õÎÅ,Ä.b(”ÌYD¤yžó8C1è!oI7Ö ®´S¥ŸíQ7ãŽ$425k÷a™ô¹ ™™ômMÔ`ƒ½¡l؇ >æ‘÷ÄJ¤eÁJD'Üû±à»?Àö#èQêwDiK`>{äv¯1é¾é,~+Øë®!z±ý0Ób4Ú~„'ÿe¡Œj¨—eËØOzYãé%]"Ô}ð¬-J§Î000ô V´ßòøº¶--G1bè  N¯JÿOÒŽV--ÿ8@É»þ`ú7Åí!²± (lK­x7@¹:»Þñ„h2 ¤wѺÛxƒWÈ@Š@+¶Èn\y ¼j¼ì›QTÁŠ6K•Þ}ÓÉǤÞJh…פéäõ¥¦¢c8ºeAH°óvü$×mßpÙ«!ITIf~ªoªkvNÕ„Yñq 7»?Ô´—R®=CÈ{(ÙÆÑ™’ný,‹jÆ×ŒŽu°P-[ëq—õŽÏ ¹b”C?ã3¦›h:âóËÑÞ« mЖ‚ªø1}¿£NËå‡Ò7ˆ,k³v×ÜŽ‚Gêb–hׇö©c2Ùö©ÞÇN×$‰{se`}÷uïdx³¨]ÿ¿Ãæi¡Á®±nÓOB`ä=QP¸ÅÔ,Ðâ².¶*e]«†¹ãr_ ¬¾á-Õ½;î]v;¹Ô™”Šy¬N’LU!Ih’øCÉÏS *8fSõx_Vî®Ã1Õ:Ÿ„_tI!h²!†ŽêW Û”Ý.?…l\Æ-U·cÌóó·ºl¹þA%Ü=™†ÿåí¬í ÙÊjÝø.º!‘z¥óòÓËh”°@Þ>”l—Ÿ< 6qK=tþ&y¯ CDÈë«â 7Šƒ3«üö샗Ÿ­²µ²‡5ËNººÁìž‹eYr:/BÞ>yýˆj†çy?µ\íÌêÍôêØøŠo—QÎHìÇ$´Lw îÿN£`˜¡žÝ¾_›á^ `^æMN=F&%p³+ygFZKe`¼½E²Z#2ñIÚæ¼ìfu döÑ;©…Ó|¡·™ƒJryTsÓð¸’É%±n88u!™ê¸üI‡Õ¦Mí½‚WEF>­y£r¤Š†ÆKFnoöd7ìk˜ç]ü˜²d€ã—2¯=ýÄÄY´æ#$Üq€#q²v¤f£uÉ=òSkŽVùYG±ø‹î˜˜¦‘>ÖÈmU¬/òú©ªž$ˆä]ÔÞW× oU!d\K \¿±uÝêyÜZ„ÌÕ_©ô‘i†BÚ!ï‰ëЧë®=í¤àKhÍyä#E:¥Iƒ4ê#Ÿbi+NŰ¥” ~ù‡>-Â’_8EWý³ðä¿@h¨—{³@×^(x sglSMKm¼Î3ÿ$0+VϬ‰M³ì}LóNg%ê3 !Q.édŠ5Ê8jtÇŒ/-c×°pQPfx³ìëôw†ò¢23§*jdéœ Ô£l¸&·vRlƒŸ}½ˆúútŽ3ýuè”#I—¨¼)‘L/;Ö™Áü2±šO³Øh9×éò©ÃÚ(úºÔW‚Ëßý‘†kž9)õoÛ÷šìr2ß`>^ÓYG)êe‡Ê@vùÁ¨x®“:dvýÙ¨8V³ëg£b[]„–šñü=×µ÷3¼÷3{0l‹:IÐéa>¬B¦ò,Ìu®¹Øh»Fnm–ÌD±\×pÛx©T |" ÿ׋¿¹êÍV÷e~ˆ¶ï8?¶?b|´‡uR_Ó2¹ú‰»æ¤TÙõÐq„|Ä·iu\4´êY_Mw”„ÿ`“f¦²ŒüË&Y äõWdÑéQ«f@fh–3Š‘­Ês5¯'äõÿ„]×’ó(}¥d_îý¿Uß>J PB¹öébCËa«æò”<–%hºOˆÍNÊiXŽ´’ÛPÅ'ä~²¼ÈE#û-_ ü½Ç.ýKôò<¨fí0òþN~Hc Ëwªyƒ<(‹÷ä½ÿ±a½~ìÑÐJ¢÷¹GÈkÐ𺮲SûÒyÞËn*òöÆ®vòvµBÞãá°òÈrošnYÿOòjWÛ[»Zvµ™½šÐöÆ„VFZ|€rYzs˜jŸ¤dM¼<ò ü|xãÆ}ÒÖ4n§;ÿóÆ;é”&}¿ÿgš´DÈoiÒ;B&[‚}æÍ_Ll,Rêéöw ›-a+r¦GÒÔ~Í!àɲø<{{ù:½šË—²„ žü¼Š»\[y6Sf¹QŒ¼@ Øl‡µ£ÝwcÉÚfˆË>ͤթ}Û©ZºUv°yÄt}?­Ç¨M-¢¯òq­Ö !ï)€y΀^ð‡­ÿ'ö÷Oˆq¦|È ^øDôÎMoÞ|£“«Z¤&‹þÙÍy{Aò0ššU%FXÂvU+Ü·ÒIUÆ9'Il2^¯¹èk†ßÜO¼tÍV_s@HÄ~að„PΦ‰ÐÅ™ „~¡¾¦QÂS(ì¡‹Ïg©‡c¹ë©R…ßà^”™zx£ý·mœ<y“6é܇é±Ëíøš×4­Á¹¿‡>Où~BÞN)£Ü!ë)—ñ»§Ëâ_¬ :4ÁÙ%ç;w:4Îw‡šj„Ĺ”ܳôéH&ÿçi ©\Æ“º4ë&å– „¼½~wýêÒw:_óž }¢FšMfÎ%B’DS7½ns>™¡>1o|§a®TÇÃ–Š‘þ÷Çw”ÈG#§\hï‰) Ãó9p¡ åø%ûÿòŸÎòè yK\û½\M£±—]%BÞaG°’l7ŠnºahöªEH’þš=Ê™_sžE-àw¾¦ »hÉ[iÈÅ9B&”ÙÐ'6Ï’\ÚcéÌÿñe¥·  ¹GÆò–¾GîÄiÞ£z®gø?³ŸóÿéYê†Q1lrÞ0ò‚½½ïóQ(c¿§ˆÚ±F r(×®k;„¼œ¬Í5ó±¨hD‘ìœ` g.)EEiIñ§ßâÞa)ÆÙ–Tì\Â>Ê«BßÝ- ühŽ6ß·=dÞ£¼ Òn\Ì‘ ªîÚ®5Bf ¡Æ»¦.Ô®¬­B>9¥—êéZ°­%â¦G>“¨uõµã–î’ø¹2èäƒeR@üÅ=Uwyã=wóÇZ-g±¼È./¤+ˆ?žŠmŸ¡Í®/žUx@Õ4DO‹{jñ¯Ó:"oK¹—ý×·îܺ_„¼½k¯Mƒ.nb{-»aëåsG¤‡öoª;µ©Ý5‘(ÆÞhIõ­‡Yt¢K¨~Ö=Èxþõ‘'’h¶üÈ#(œòC´úìEØ‹f û!•% ²ì›’Ülr©ÂéM`—ç¤{†[ÊÑgÈp¥E¥{x=΄]/Æ·.G}NlrÙ7&ײÓÇ£b¥G5 ä5E:Í–A‚BË= ‹°O]É|4ù¼±þõØ"$ôc¬’ q<UÎ|Ø ×#É«=¶o–ЮL(‚}{ˆ.Ewt9Lì…ÓY•2!UÊ=ª‘>¨R€#ó¸ü‡ÅZUøÌ° ï~‡•áqýÔ¦·®ÞµMù9t02‰’¨ŠSè Ä¡ƒ÷Dáôª:MCïÛ›ÀEw”›¤þ£Àªxà’ú “ýù0FÑG)zˆ 4…÷GönŒbú¹Ýy[Ó#S6¢#è𵨌*XðÞÙ;;|ËNª¨“8}ú-eÏqÏcZ1Õõ‚‘÷¤#±ú”ÀiÓuIP€+è9÷t¬3\óñ5 é®%º¥Ýom’5ÒÛ$ÃŽè–0Íw)M:7ç·aèÎ:9#d¢´çM{—ŠYËÈÃ’ª‘þüäÇÈrãÁEæj$Ck‰ ¦d™jº4K?ÁÃ4F Òv+§ž.|éY^ ä˜/e[71ó´(d‘׈dî&id§ÖƒE†Îó7Æÿó×?fëJÕ©[•ª–:øGz䱓BPcC1Aq“è–^GœÜŒ8ÃÎõ|ŠùÂN¯!út¶öð=Ï夿~M¯úÄû»ÙãÜïÎsÞìLÆìyKº¿'…½þt.¡%ñ¼Lš} ¦¿Ñ²c@ixžMÄ«&ø¸#c+*¼F†³¥^!r„¼F®™="X÷5]*öŒÁêýLð8\vTÊŒÐÂÛ‘*±ìØ´ ³‘yÒì8¶5B^ÞöÉBMÂ]Ó,´æšÛ1°.=“¼Gr7ÇÐÈŠ–í± äýC.ÛÄéšäMBêÙûh[! 5Ø3ékþe­ë}< %WúÔ³ÀýÌ^»é!¦;únvaäòïÉÑMÿŸÜЯ©9ÃȘÔLaõ~>NlDîý8yèWS ñíxœGÆîknÒÈ~TBFŽamiæ7Rº°7 Ž !oá€TÔá©–žïýRÖá ÷| sܽ¥¨ôîÕB¸+ùù9;‚ó‡Þ7õJÛ·k…©Éïø\±AÖC¨—ÈÏïBE]«cäW§4!Ú°s‘ŸÿpJ«|ÍdºÏeîJ6O{p5#iä‹AHŠíƒ%B^>Vª\ÀÿyûöÝlY‚”¶efVEûŒèǃí*¼Gä‡|Чö&œÐ˜@ô™Þ¥:4æÜ8 w+òƒ}qε̦aÖ%‹€k>7?ò©=‹_(x–žïXüXü@­$‰Ús´ý5çÓ5¯ùrÍétÍHì„Pv§  U|êÒ h\ƒÞi&|M4NŒä´å¾›9Bf)•ÅÏpô¹¸[Fïç3™áØfº¶r\Š¡¨ãžüþœÅ]µ/v4²ƒ[It 'CïäWö‰c¼‹îXßGolò{yñq‰DD™oàm@~/ØÏã«;o #ߪaL8ta¤$*> û!QXY˜BëŠe¤Ð¤&¿7LL¯í]ð(#¿˜úk³¼Œ¶kÛEWࡵG~ɤñÖzƒ¼`?N»Ë?ÎEßû!¯¯Hë×õм}œ¯ÂÈÁ#?Ob)¬K¿Kñ„“ŽlÃÈìó,tßþHÈcV¡Ïq&iàP©zäó#r†ë7[zs÷€Žl¢mÑ©F`èï{èRŒ@ˆ ÐË«…dë,$÷ýßë·Éþ=ô†Ìm9˜ÛźÐÍ^Ó]ChŸ¨±Èæ !/‘yíûk͸u+{{4y2σYpÙ«’É¥ÙàšÏs¼Z«A©]/eƒ—Ð4ÇS'Ýé¶š6²æƒ@Èë9Ñ”ÖLŸ$©¢øÓoñØgŽ–…:îšà¡ûM.çâ¹–ù{2M­#ýMÆê(¤D“ËåÔl@6¸=Õ%A@^÷™‚¬No³Æ •‡¦ˆG^Þå^(÷š\nã7ʽ&‰|åœ<]¢äirI^È:¿wÖùJÁ5ï8‚"9Ðtʤ‹Á£œÆ„œŽ)³=¦Àb!¨h:) G ’hpãʶuVq$Æ„¼9R ")H‚ú“¹dœÚ“IôØ ¡=9!D?ñÞ Abä7'„!ß8!ô''’è'^¦Ä DýDàh{2Ó.ãñ$QE¼ãT(.àÿ|¢wóÌOÀO'©†à¥šù\á±hG&f ¥ú›×Ç‘ ŸÇ…™¼KI»´©Í®—MO7ªïB^?K¡´LãLÞJá™GÜüwÒG(î®—ÒG>aé£GÞ>s´ã5¯h8ãŠeËfÙˉ°ãÉõö¡¼êO6d$²øÏÈ“ IXü)ï›{Þ·þ‰I>wJ™kò >=ûl‚vØÿS äåH’—ªœ¢H’ ø¿]:¸Ý`MÄÔÀÚ…Á§?_÷‡”ý.êq„OOØñÿâ¦Ha›" !·4Ò›¹ØùHUvô¨0Ù'1Öâ]X?Ò8Hniê6Ê‚¥> vGHdKäJu½rc¯×yøôËi?r 6n¹4³ ÜÙò‚<(샼ÌMoæú5¾f¢m²õ¢K(ìó<¡µGFÖ¹"q—eÈè¥<òŽ(qܹjÌ,;š6Lƒ:¸ëÁ¶õ6³½ž)þô,VAŽ!Îr;êú#YÁœ¤ÎÞOÑK-‡|~ÜVî®.b†ek3,%0¸Èíö-Mæ*Þ¥û9»´ HQ0ºq¿G^Þ­ î}—!¯o‘n ÙòöqìPÅO'_Çúè·#äå}%PÏòˆ¿Q¬.þX*¹¸0Çd3íǰ#$$~Nc Ü׿3O¢¦cs’4Øâ]TG òÈæ†¨o¡¦E;Í‹BÈ Ž óã®]fx—ó¯Ù¸…^f»Iê÷ #“g)"ûE#ïOb ÄÛÌñ£Cb „‚µ´—h2Q©O‡ÅŽ‘À>.'͆ßÅÒ…9F˜·Ø³Pë…I]I#þü0F3¦Î”!¯‰*Â;ÿ9«yý¢VyK¡¸'QÕË1tسxä=¥‰0ïÐe®[øîISû®YôñDŸæ !/ÎúmrÖOÙñÈ+A/‡ƒÞÀ+ì|áÚßö„dN(гÙ ±`Ô—ð¾ß Ûæx6%œ(]vü(éºì\ÁJKž'wFò¦ërº· !Óq‚7]Ñÿg»Ž«(K„ m^…à?}—Žºžã F°SCLf7Bνg25¥79æ£ù&Š)<É û8Œc…Ž¡‰är˃D‘Dö±Šãµ«˜8Õ[Ûç}@Èk0‡©ü¦Í›ºÕEuÇêú-ÆUxó9s>Ó÷!ÆUì¤2ñÂX‹ìºyTð„œ#ò2„ UR¿Àúx¸cd¼óŽSáÜ›i,òvBjh¹/Ší‡yÃàʯŠË<êS±Þ·;„$éÐ:|wý4‹¾9}zVżl|^I%õΑCG92šýŽÍŠó|ÎÕ=³ìlVüzã¿pð*ÄM’ìòb³ïÞ8Î{ýˆ SÐ6-‘:5ôF¼\M-ì°ÙÝO©ìV›~SÕ@­øBhÅÔ1Mù¤&„¼€¿c$¾ªCÿ/Ìq"¡Ùžùh1æ«>êÒNuøÓoе CKxª¶:—MNW„¼§•?BU{>õP±d/Á@Þ‡ÏÕ4 Á ú=G`e€êàT?Ê“ÄÈDžY{Š¡Þ¹¸ØŠ™bdÊâ÷̨^æãÞѶ­ÒY¥í`oÅ]?»§ý»LŒÀ²q¯`ë»™îóŠI•n‡ræ~CA…øˆô¢J;ð0ë|ä”cÔùˆñ^µ'ùé}í¢âóI>’zçÉ’zw„|oÌhÇÆñI&ŸÝ€_óöq?âÐ×ÌÎ’ªÛ{ª.t/Ú÷iâ᩺0ŽÍߨº²8â³ô8‘™à ïúBwðݱ;‰u”p^|ŸUï ŽäñsÒ²ºòñIÜ­ó!/é ælz3lÈðÝ¿ïh Nõ(Ä6ÇIWBñçO8A›>œ9#Gìk¦!.@Ó>Êú««R/ S¯yùbâ ò¸ž´¡E%¦i»:ÜÏÇí5ÎêÆ…ŠzÅÈ=r]üÂý¼¸ú®IpôÍÓÂ5³ïÑ<=ôR:õÛhž¶GÈkP寀B!GÖ5Õ>àO¿½Fi‹¥?ýO»¥{‘¬÷ópt\ÁïŽÍ4¨?•›îÁ!ûN,P‡D’´Ø0¯‹•z S P$idƒJv‡Ãª×u­(ó!¼›ÏŸoºØ9Æ‘ç«ÌÎô™kõã\†ê"‰Bx3íéeœöâ™Ì…_Ô «&ï¾ÆŸžÀ…‰ÇQjK$mI> 7 2$Ìâ¬ÉVþÎÕK?VbóU|$”w^×àXlTøÓŸ_&r€üý¯‰ÜŒß&røšß&røšß&r;B~›Èaä·‰œ@Èo9‰ß&rø»?#§ œ& û .ḏ³Ÿ“Ð<°Ú‘*Æú¢—yAvµ¶ú]¤æ[Þ÷™Š ¼]íªëé}ӯ݄7|Ò÷‚BŸÞ÷‘%‰ εӘ7šÝPɶ-d¿†~²G ®™–¿£–JÚۉ!ã´§té4zµ¡•®Xtˆ¿û#Ñ3¯ÊÇeÛ6qºæ\½¬Ð×Úê¶TŸr6 |ç ü “C3Fiû½ ßPç²ïUÁ!:uYšYƾ½„”jG—µ#AýƒVÛ‚X€^^ïVÏõJ‹yÚ†ÞÔ^µžê¦Õå@(«L€K˜Ëí3=ÚŽåþõɫ©t©Éâ+ê Y u¿@­Ï e»3†_ëlÈDÑ kŸ(ëd]°ÓÍz†®­í`/׊ê'fÀ¿Öå'ê¡‚ƒ*ªKöMž Ðct„T»HíÇT±Ç˜ýœ ©Xpìy“³z:àHz¡»ÓÖ>êKè¾Tq…¼¿²,P³/¬MÍ.ò’ˆ¬ütŒÏÇ¢Š¢Ýº€|uœ s Zɼ-ª!Ókú0£V­†–+„¼Fÿ»ÚOñ”qƒbsïyK_7Jj£’C-· !ï‰É•+Iš¶G&jnðH’HSœ«rS­´µ>S „̾PÕá7Ê>QÕ{LUÏ~²Ó]J#Þxñ–ý|x;bÄ›G~ŽxƒT¼~¶þãðéÏÓÄÍiO¹^É…^IØHíÙï×óÂ0Ïð$'1v>U…-gá´œ6&B/4KbðÄM˜‰›R`Æ•¥1!\ÃÛa­ÇÜëƒÝç86˜ŽýŸ°+[rTW‚¿Ô6¶¡Ïûˆ™O«Ø$Ö˜¯¿ZK*lz&æ1Ú ¤Z²2¥®m«”¥CÈûédÔÏE­¦§O2:ï*ÇnP×,ä,·#è 5M…©žÔa«B<‰OŒÔ_ÇZl¬›Á+„;ä+B:ª¶Bš©Þ dP”„:ETž”çcŽA…¢ö‚óê¼ë›š°æoX…"‡oSm&dÞ$Œ(ø'ÿP§0 ^}¯‚’Zîà:è ¤ÜkߨQ–G¿KüDoÑD«ï;å»ÐÃFMƒþ-˜JFº»Ôƒé°ÛG"' ¶®DBütK>膅*gãFc¿µ‰Ï?*WµÙÂ5ñHV\‘”º"y„ïóu-ÑxÄ,©ôöº–hfäeGÈ™ô8›œ¾/g]3½ädZþdøB²k¤áO†ç™¡*|Ôif“XÕù}ÀݱU¹ŸÒõ‘]ª½AL^C)XúžaÛÔža» x³iÄÒ7;ãÙ(†ÌÒˆ¥ÿ÷Ï/[q¼Ù©$¬ŽkXúÛ_#ŸêÏN*Õ+—ݱ­ùø™ýìôþDÕÃwN{ÅòZ¶¡Ûñ5/ÙïA¶Á!¯Ùïa…ܱ¹µÎ­Y¸©;èMžçëdrlôu¶V5…6ñÚ2êÏùQe¿ûX̳¯ß¥±wÁoc;Jm$Ô ½xÉ=›*½ŸÌ­µ—¨UídUa—øšñX|íO…v¨y=ÔB¾blËÒ_¹ž:Vh©çâà µ´¤š†¶”!³ˆ{ï´‰ó¸´}‰ŸÒwôŽÜn' aï×t¹Í_ŸÙ"ë±Ö*¯9†™Y{›§/|óªÇÐ{7ö#³:çÖiŸ0ÔD—û/u^ *Fž·E…¡Ï4Ûd /*½Tò¤EQÁ`ée?"ÃØ‡Cž†ÍÄû¾N-ë2 ¤-Ži g’âKy4- ̸gHó3*ŽÉ²QÑ¡pÍïËF€cä]•©èš"ßH)c º*ƒÍ>¶0%Y'¯¡¥ËòuÝÑ#d‚i˶,™¡ÓïþˆN®OS¡z-'ŽÏËd‚£& V„žJ§É\V“‹ŽŒAØI|<<Ã5#]ª7+ý6¼$=¯¥º6ýæ[!†ð…†_ýìgÔ㇠rÝ…† ¤o¦Ñ@ƒ.%冃n»Ý”’]‚ÒVú¸á~äžÆø1@ñöqÿyæœÂ/:QàóÒÕYJN³ç¢ôS$âï’Y×Xézu2¨4 ‚‘ÇÑÞò¢nü!¿Nkò癪䈻êääuS–3F"¡Õ‹Öá@7t’ „L>ˆ¨—N)$³è¡µ–¢CÈgÔvt.¡ŒŒLðä_o´7j¹ ó²óm¯!©yœý Múa×<«G•s3„L"2›ޱEk-ƒGúAhÖ{aÓC,ž œ>¢pÕ&_µuæZúNw(ó ÝãûÚ³Ûj"øßëØë!H ³®mX1†ðÿyC 5ë¯mSÆÕ¿þGc­gi0É5öŒ¼}7<\ÈÖ…žÉ‰J‡ËÑÓóÒHw=Œ!šÖŒ!–UŸ#äi Ѩù)µþ¶Ä×|ÿG“¢•r&ò&èA¤Aw]ó7šÕ¶c\ˆe-îž‹V»i&4¤)ÏçMy’¤g”x¹@Œ:Z»`]/ÚžgŠv•W–¸Ûu}¥‡ ½öbúŒœøtÙ¼öⵓ vOnBF“Zrµ¥,—„çîÁœ†ÔШ|Rq=B>1ÃÞ]JQO…ßž½›Q;µZ¨¼—ö!ïïƒ,Z^Ð¥‚ªù3{3•±;ƒ6•Ùçaòƒé4* JÑŽ¨¥\„÷Ž¿M+lª´£²CxïØü&/¼kµzD*ZDì™|NæØÖ(þ¾Þ´®ly0Md•{òvÑD,­=¤§1e5‘5’¯íá›Èye3ŽÒ²8ä#’w*x*ñReÞxcªôu?Ó\Ýq¨[otУ²yÇ-ÂÆ&²*ø—ƒÄ×L )_x‚q§[ŽkZ|͈¶Q{%M®NͲ+fŒ|ÆN™Ÿ«{Óµ‚ѰÿþýãH#yÌY8 _Éq2žçãMÌŠ4ÒYû?îr†ßþ<{µ4þîÍÞíê eyÎ#·ê:Ò/|Û@-% âß¶£dÔ­6¨&Õždù¸.ŠxmÐ4ÿ>•ÍS6ó¶‚iD®v:5°ÓNL3ŒÞ¦\½ý1eíº²¥P=@®2Ô=Ü=E;ƒ»»ÕoÕwï¡õѰ5ÝØlaæGS‹2¼£°/íÖÕE¿ÇA Q1%”"±êO kFÓˆÚýI¹Œ³j@Èû%=¯ƒS&¢v.É@i5P»?•d"z^úúÉjK°`µ•¦_?ëg ?˜“¦·Ÿõ³Jø;Ó3•Î7RõaÄÙB\—Þ.è%îÔ†Qû4¦"Û¬ÚºŠ/ãZ.¤Z¼ÀCš&gq Ñ6Y0‰ÀÛL“s‘‰Zºø1h¸¿×4R7¶9‚ ÖÔ‰ Ž&ß % …¼p5&ºŒ¥üdãˆOÿÞs¨P=ðQå0!ä+ß+7Y·*vZÆBâk¦ŠŸüX¡¢ÆŸ?C´•OŠŸÚ…Ù(~J„„·ùVXµ©4"-Ç‚âfDxÔ%¦˜Ž‹Æ—´Ra<¾”¦é»›¼“È¡¤b*Iñy\š½Å ¶d¨}“‹šKh;¤Ù)C ñtœ·‘™\7áä „Ø«¢DȈP‚ ÚÊÛïÿL´®l×GêD_,‹¿{ Ù‚„‹¬$ÝU°Ä ;Ë0¥ªðÛ§®ÂulËÄóÙíGËŽ@M#Bì_gkŸ¼zJÕ>·Ò+¦Y¤Ée Nx†±ª€%÷ãûiÐ,vY¹å ë±6õ8CVž%'‡åº±¦rU»£ÚÂüè–C>âLß;m­ŸG[!dÜখÝr´}_o{{H– ·™€´Ftèe=ƒƒC¦þ|/jP=õ‡.R„Ìü|r^»š*=t¢¿  ŸåßÁ ÚRo’ômXƒŸ§sXö3B¢o®õïc½mT˜²7²§ºRÈ’mêðîò´’ʱ:ZY,GU©x­FÈä2N'§GTè÷ñS®ÇO9B~¢–çšZ.j Ýe8ÔäY;…¨-ãÖÌPÓͲ äà‘ !#¿>jž.¼ëXq«)ÎÏ>µcÃZ>Ùfœ†Ý9 »§ßç É@ÔrŸç£,¡ró}¶£ðC¥ZOrgÓïÛÛ0±Ýì†|fDR„ŒYœuãù2«ýÎÐL¶•0b÷}w•òñ^;Ø"d<Èâu˜§&¯W¾ñí;Œ›ÿö’¶Å+&Núcòƒ¿™Â`ÉvíÏ: 6ËžÒýʶŠìBE9&b›šnUÛ5¯^z=Æ5Ý郞ikÔ^t˜ˆŠ«©o^Æôê³_‰ýúÒˆ4í”]Ï|Ö4Û‘AS0"MvöÛñ56Ê=­C ”ŒÇL¼iG‘¦M Þe¬U9WAÚßýùî8ÕtÉw&{Œ|½{²“`k#Àõ(E; @îNƒqähè«êÊ…¬CCô;´úŒ…žÒ+”mµz˜*ëÃÈÈcÍ)÷šM¹TÁ•ðÌö4bŒ;Ó[&Ö…÷Šål¬w„¼‡¹ÚÀÚ-»ÜGÑÁÉÞ¦_](¢«þ$Ïoö!s‘\TUV*´ />Cv&°4‹É–„#¾HNŠ ôêDÓ“V†š!s=óyxh–UH¦b¾ú›ÚS%C;2 |õ“̓`TÇ€Ô'§Ù×í 98䎡•þôÇQ•Õ(Èe±À±-š™¸Ö>Ï’ËÉs®²¯÷iMÛß>FUlÓ®!“ ‘i£oÓ‡ŸöaZæ!#=EK…¦zk Ú}œ}ÝOÝõÖÎëÙÆ­‘3óæ Yľ`cÂ5“ŸÊ¿Bž{’}‘¢q„í Ås.jxòO¤©âÖ’9Öª˜­€kFJBû/…l‘êáŠ}ÄÈû•ÿwpMξÒy"Aö=‹D“?«$†÷K1÷n‘™\qO‚D»C>~hòy!Ñé):ä øºˆ,´œ<´<²˜é¬¦¨ÒÙµlò儼ƒñOe~‘¹¦Ê(FÞˆ!mûÌ4› Ï`›å^—Åè ÛY,m›8ž·É›\ý‡¢nvû:5qêÊk¿°ºáêôâyÿ¸‡hpˆÏódã³?f²ÀÆü¬î*ÙíJÝmÐên‡®­"äý“V‰hä¾å5\óŽÛ¦Ô„€êše·Šf. Pœ!qç_^5ÂÍO©¸á·¿YX¹É ZP²m;xf·º7to†™•yÿL;)™”áš‘fÅIR\± sxï±5TlF<ðJ;2@‚–ÅÜ=½–j#ue8ÀãU3yê}vÃÀ G·Ñ¢O°„à·×,eO9'9„,Éý'‘…yAC$ìlƒoÓG±Ô%t²$ù‡¼a1còƒ¼…]̘tî‹¶µ6;Û·´²ä#?оëÚ£d¾ªš%Ï )I­ Ê 2ÝYò6–ïºà걺œ&±!dè¸ä®ÈÒ.ŒtÛ©GÈG09B³:5YM'9pÈg„tûâpE7%¤úÉI˜æ »¨Î1އÀ.y#æOñ!ÕøšŸú(ŒA’¤?ŽEÓÈìþB粦*5c ‘%ß§Š]kY­šc§L5$±Éwd ð;…ÍA9Uü@È0fbåBtÙh2¾Ú´÷åƒÇÿC„TëS1z˜!£]Ñ|ÓyÓ…ÅÃãdÓ¨¿ÚæågÞŠaÓþŠÀzÑ¢i|Ðsù c`yiRCuÕc_›ËÂF;ä+’)+ä™ék¿"dzùÞÁç6{ÜÎ|#;ù¨CÀv™«uõoó,©íÉN†|»ïÁA+{œå}è¯ÇHš3‹™²šQ«N—$;:(²ÄbѶ7âZ±Œ¼Žz#ÙãyÔ]”ú â™=Î;CÕzYiÞΕ¬J¸ûY°#Läùp”íÔ d<ÖzA™¼ÕZ§^®9{¼%]YŠžðn­V„|€¼0µŒ N×|íðßùŒF"¨ëmOŒ|^§!õZÚ]Å1ü†©È’#Ó`’n²HÃi”ÛæYìYÌ”µHW°;†žæù~ÔykžÚQk•Ì”Í(ÙÞ{% šP»6Šu-æ‚ãk>.¹é¡ÌñÈ.D蘡´ka-½™A4ö9™ó]M !ï~%[ <{Êäù̲ϙ\z˜yöüºœ0ÑÈÀãÉb æÝ§¦HÝ«ÕrÌ;Äuϯ(ñøå\ÎLœ¬lö²÷¼R‡„ ëílveÉHÑÓ¦?¿PáûÝs©ÀwERên c][Œ*3o„ Ö•¯ hÞsÁ¾2C‚æ©“‹×M_Àö b%¦(¥“i—jHàoù'ÿo –x¢û›ƒžõyäóvšÏÒÍL)*„¼‡* ˆAÌ-Ý÷ªöú¾Yд6Pç%¯_éÖvó_\Ô…¢’⮄¶TkZ[õA¯“½ Nºñ€ 4Ò´öþôö•¤<òḟ!Óи4A¥ÑÕc¼îø¼”™Å:ÙµC6ÅÖòÆp;¤¥¨ß^ùBò¼êr²þÉ]±ìT–?é$;‰%ü¦…6Êóþ“í:¡Lý¼£ÂÑIì_„.£C^°ìTÂ’2ùŒ=†Ýw¬Nέ]Ö¾ÎäÝÁâx¾É²(=({ž¸]ÔtmË™LUI$YìçV2ÎÚ?wFÈÇ•ñ1Þì$®Â½ÔUÃäÒ+<Ïçéô°E+ݢ嬾¦™zä e0Ó²çƒNBÞOî)ĠޏfúÉýÑ”˜Ä¼‡:KÚÒ /$ÓÚÁÛÌPtã q¾³^ScöŒåÝ~9CûwŠMí¡5›2¹‚kD()Ÿïo_Dô'Æ{ø:†·¯ãûç¯C†¯ãûâë`o_Ç÷?¾ÈäbáqTNï\ÛÔOÉe'áñ܊ܚ⩌H(ÄEÂãoNfþÎÀcÿìém1ý?S|Æ’†仯äÒ6Må(yÞûë4Éh —t6““&ßYS$èm‡’}+¶›†²™çÉÛge‘ ·á±—ÖœjOGÖ+mñ5ŸŸ3NT‡2u౿´qÃ:ðØ?7¬AÊ2 *ÎRŸ2~–0‹Øéæ·W~›µGžb9!ï8°3ìô‚T|+Ž‘É;rQÈaˈC"áñ·Üt…Êbw„|^Éi'æ,½ýƒ¿¹~Äx×gœ›§£V8WTí+$b¼)lûS,ì6ã}ÿýÛÛ9š8¤ÔªÅŸyÌ"ùë?ÿû×ÌÔâ ÓjÏñ¾[{¢ªt.êÀÎù¸møïÔOi7¾Å0‰£¦“èsïpœã=žâl|SŒò Z‘Pöm$`ÏÍj(ǺhW¨(§ÏOÒµf>±ë«9'3FÞßyšs¾F²4Y$”ýk·Y—­Ü°µ¦W eÿÞm6cƒ+FBC0}^vÃÏz<Ó+KO†NiÈ^ÈQš8'n¼7—sƤõ2*YÄÿ4;|¨ÇbÑï³Ãã±Ïy= †uY$ýq2T„»£ï]çÐÎI¥Qb¢ÍŒ¯ù®,ÙuT néXõÙ ¸÷-M ÐünXJy”ùŒ“,®H¦fYÔ—< ä+JˆÔNÓà–] ›7/pÈ<–»·â„SwÔ” Ô_Ï7Ý û6uŽ~>‚îÄ+’7M•gÖsí¼Îv!0òƒ Olà^Q_þg8±"$ˆÃ^)»=ÅÌÔf&̯¨ƒß™ocd39Oeùk`.k÷ö„¯8¿¼ñg-”5«äêxù<æþq YqV‚ŠsÁc^#¤³í5ÖH‘ó+ôú{ÁdjÕ&Õ÷^•û*±ù%Q½ðQº4q²Úàß³´•šµÎƈ0­Ô»vž!CmäîuQêŽê`¼ dT¿òÚ5Ú G Øî¼òë—×õžRM¥}GÈì“*Ë4éj=4çä··Z“ÈöÞû r,ù=ùw7ãÕ˜á_Ê!³ø:›Ö?¥rßeY"ä5ª[úë\¡‚N^ýà•?Þîݵk2ýÍÉhÌÇÜ;|›Ic¼™ÈV'aUñe±/FíîIlé:2RÌ¥Ø%BÚ{׬.X)¤ÎÔöd·B»{ÄSÓ S½Ö“8н¤yCòªf~ÖkŠ})à\ÚÝÃ~dµAº­ãƒŠ…J„´Àz¯pN[Å4Ç<ã†Sçäê&7¢uá½cÉ÷€ÔœÇI·ñS„Ìb©j/[k£Öù<5Ë ††«,vÝQþ&jízUœHwîã¥ø­vesiÙ×MËoûúU‚ó»®NüÏæ4™eU1v.œ7y}ç³éFÙFëÎ-™®Š†›i‘…Ú ß®™)ÀóÙÿï‹zìj› ÿžˆ®WþÏU F¡¦õÈìûw¤v)JŸ¿b¢¾â‰ ö÷R‰E#ñ¿›S4 *bª µÞœyMx¾ž¡‘#-Sdöyˆ¶'y øjËŽléÖÓãK<æ-î’°m'•¨Ô²4ÏMƒwhU­k[26ÝxjAFêØæÏ®c›ÂË~ÏuZ ‰OƒÔY÷ÂWÏrÕe.xLÛüùë¸Øæ{¯«µë†r[ñ妶¬ËWpr7:S­” ð“ÿ‰H¤Ž0_”äÔVy`èå*tH (‰k6¡uÙ–­.µ.†^Ô¯¡”“±jÕ.‹ïß ¤ÛO¤rÅõ…Òñ¹Ù“Qïñ×ä–‡’­¬£»äúˆõÉmʲ$c¿µ3%ð¨>ÑX}òu¯ÔV¤ð PïØRndÇŽR<"tÓ…kÚÄW2Ö¤£¾"ìg?¤{Ç@Ö=©‰Ú™|Ùůf®Ê¬.bÓºªoz¦šÅR\®¿VÍ•a¯·¥óÐn(9}ݹJé~x/@‡ÌBiãšýŽš ê|qHŒ¼â…Ï,ÐGÛ1lø4ŸCÞÞ—Èr úE aÙõ"}ñë7«®šª¬+Y äш-Eu_ÙvJZâë|b¤Y ÷uOÍz@È×çiBF*ö!óÔ1±e£S­&TÃñ“ÿùÝÛZÇO ô‚¡F0ƒ õ:Éã+ ÊÎaÔ’ÍÛÊè “Q£Æ/§r¥KtÛ¤—ÞÚCSÿ:wfÐKêÔ ô!]Šâ0‹´9ÙµUÓRì;mZWᤪC=õæ—9lz÷TÖ…j‘î‡y(Ž÷é\éTC4U2̧{ ÐÒÇÝÒG„|FH·áóîlÒë|}X#wI´òÌ 2ôkW¬¶óžÎÓ1Í´(füäÂbV; ‡’ì=éã©wdzđ÷ͺG¶I}N%~öa–T¶u™Ød! oø€¡×tÙiÕáWsE˽Ü1Ôö·ü9þçh'­¥Ô»ÚW•R¤zS<|ÎIU©ö¶åɲ‰!¯ÑÔÓ%ÊÖQYD!ç!oÞ¢ÌRYìÔ#ÓXˆª&yÿ¸˜ôä¤`D”ƒ5Âû{*zýá%Bš õ÷_ÿ@õ˜ê›a¤™PšOlý} ëš«IzKXL¢Ü‡ÎŽÕÖáeÜzukXKž©FOjšŸò i νĄ¥§ÚuyXÆó”qN}_}ݪíðÙÆÙZ;¼£¯õò$Vøý@ÈìKešúk“Ç>Pg æÌ}ÀÕc"àg]"&ïkÆ›T!¾{ ÏÒnäÚ¹¯®ËY¨]AÍA„Œ4¤¨Û¿ªc\ª0¿AȈJí»R«CûžÂ«A8ä-F2ßÝRïû>vyš\ 'Ù8«á†‘ý•ÒöB¯jU7"äÓ½Œq¸·ÄØŠâ¨G<æëkí­ó•Ô<»ü^{›Œ„¼dYÔ.Q1r2 Í,½®‰CþR{;%BþR{ƒ•!ÃvbÖÔÊžWYwl†/.ÃÖž©Q+?}¥*Ï®ÿ±‚…ë¼ýÇ – ?¬`*Ã+XÄŠJ &{k0 ×yÿÝ`r™$BfߨéÓtÀó|üÖ«DhË12Öb³d#V=Uÿ }#až=ëÙÊÙ Œë¬óC;òöÄ.çš#äýKÿ9¡Ë7Ï¢:Ä{ÿ/ÏC äóÝ~•ûÕIÀZ«Ø›˜¡t|4£ÊÚ˳ä u¢æÛ4qȱ±ƒg;"äwsM ÛçYþ¦»C=O¡ÐÆ!>kŸ_ßµíʰ.Íɹºf?뮘Zº$bëz¡hçW\M •9ƒbr~½~1ø°È#EfŸ;ª9¹óë-ÙµmßFëû6|ï×ûïßû39bñ|Ô€>'@~®Ê[­)]•‡£×õ—ª¼ÚŒOséú[UþlN»öõ•fMAÍvÌË,@U0¿æH!ÝéÐéÌuÙnêÌ+ GÈ_ª‰õ¿TÉŒ·ï5ÂyGض·¼ª×qP;Hi5Ñ<%SMä'[ä32Es5˜µe•ä¥lðu¾¼Z©œL·®;–ôè¬`™-ßšéZkyµ*°’HîÉÿ|/f ³ EW»i·š×<ôúÕ;"D–±Š¿·Sr‚:ê9iUÿ¤"“[m©kDg7©«€=)°˜>w:Lp¢ܤ·N‡u:8$¿ñJtR­`Ãqò­º¶fkRЙ×sîè† Þ-…|0¿Ý?FêЛ Z³yª£ÿf±+ø-]G¼H1·¯&î÷8¤ÕÅÒHÎDê·¨Çù=ºê{°›vÈë—èJ…¶ ò–ôw3èïæ™êïfÐßVðˆÉ“Jq˜1—dÌ«G¾y$cÞ¢¾÷¿KBÈH%¬Œz‰-=´oÉF#B&ÚP¸Ì]Q¹Žµ 0÷ä"¿`©ˆBÐ3زå÷KÚCë£`‡œ12ûtæ&úÌ ¶<&}Dú®¶ü~A}Î¥õ·7gšŽò=ª*F¼›¿ÿþEUrj£Á#³Ø´Ñæl'Q×¥ì7Y#dlÅèþ}l65 dY®{–TÖ¼£®Òê<9à¤3LÆÜžÒŽ£áK˜÷Y2›[êujZ,Ã’ŒùñÔ»mR4•'G9$²ç²õIÔÙg[ï(GFZ¶â¯´fVÔ ?ùŸotÈ(1S‰¬YŽ]—RÍ{Z&¿§"õ”ºÔúÂærß(Ý署’i¿³æCR-xK‘8€,´ÛëjqÔ²CÈk\$¶—©[=„œØjî!ÿ¯¯pä­ÙªEðá„7¼šŸÊQþÕ2?©k…é‰e嬌ÛUœ’ÇÈ12(Ë@û²së„I =¦-è1§êXÉŽ7 @DÊ2YUxÌ»o++ÏÿÐÈF]gƒ¯óñíÞ+¶Â¿cëŽ÷;ª„̾ÜѦî¨DÈk|Gá:—õX!™>ÞûV y÷é#üŽ5æ€Ç„{›>Õñg—;$Fî9ž!•}JF¯p™Š³ïBb D'”©Î“Rå?ÈQÁsWOùQ̵ú@&‚‘@⟋vZ§µ?öÉó&sDy2M6®ô1­sßÝè©Y‰tÖjWžT›Ü~”#Q³…£ü/åÅ>xŠŽCÞ>ª§±}ŸA=-mKþù™¢©XH5¥ ¼z¤ê“A§²ªªaX½ÐDþÀ*o¦µËntçyê‚×Hà™yñŠU½£ý$xÌT}Ò8Ü×L·r”yŒÖ\ÂVý;¡Ó2CÈöxÛ<@§²ÒnÜÛ–;äó»ùºBæëh³ªyj/ÞÚ©”Pr{ÜÞšû%†v¼ëò\=òþÖíXÅyŒåÙ"d†š§M¬‘†Î>#ä…ê¹ï2AÞ‚5BE}X-Æ}'5$F±áˆ–cEÔFIùÀ¢O6P0±Wk‰Ç|ÆÍ©n ÑÈs¯8óõÉo÷Ð~» v™Ø %2à1Ö2³èº3Ì¥¯~»Ä’ !\{<¾„kêxj‰‹BÞÞUGy¢:šG´4¬:ÊÕÑ<2bùǵ"Ù ¾kIÅu3:ÌäTV\7’šôI—v&\Vim!´Rd剋œðB¶ÄËŠçÙLDž$nôàÈÁÀ20Èfº ëlŠœrmŠuë2NAÛNË ¦â‡~…$pL6³Mó´uäÒž/KÉŒ¼E¤ÍÆ'-‰”‡ú‘÷(mX†:Õ2Ïro8š?ò0“ÿõ~Ð6²*ƬýÊòù…Ì3—r2±e‹5sªìnX/š|-*ø6#Rœ+5ºw$×s¨ÒNyMˆvÔ"ÒÓÿ;4÷ësœZûM€Ai‘âpÛºÓÉŽ™ÀÛŒHqÁBÌî2ÚB¬ë¤@Ȉ(R™ †^çùÊu¦GÏ,IZj µ!œNÚˆÞ[M8¤Muük“LvÌs˜·eŸÕΉW@êÔ®ÛãT@u:!CéÁyMdÅHµÎûÙVy÷ 6±¬/Ó”]†º ï(ìGÇÿ#jnïHn¤Q›‘X „|¾ÛhêØ$^¿Ø($²É#ê % Ô®£‡ Œ Ë^CGODÉÓMX²o§Ý ‡øç-±£ ÐT_ 1ÿßߨ׎T¬‘jׄ(èyO IÎ9¤­e+.e˜Ÿw¼2¸f2‹,9 ò¯!ö½ë5„/M!à:¨˜RzöG«bÅ¡ØU€Ñ"dÐb‘"5¦ZfÙqvyDÝ9NE¿§:™Sè’y>"»¯@´k=ÑŽ@Ù%&º¤€{›*ªlD¹@Ràù|`4ÿ®¾ŽULÛYQ„¼¦ä½Ö“÷XøŠÃùÈÏ»Òê1¡Ž\!ïØèפ¸ŠžP.¦Ú¼bSŸ?¦Ní¿‡V2e´«2‹}¿çØ/ݼ°!¯‰XMkdÖ„ êÀw"$Zm<¯®sdî|÷wË-±1-<ÍŸù›þ¸K4ˆSÔÕYB<½Å]Ðoûs.J„̾féüuùÃlØbêàÃìvƒÕæuùb˜­I›t †Ùy’vQ»<äÊûI«`C_¢#þýkç"{*f}´NÂÆ¦N»ùOÚ ëÞ»³§ ­Åùî—ö=ír°u[Õ¾]"dÔ/í””˜¨ª®Ó2b0æÊkGTwµÕU5v ìGyD¼ù«ÿ½ur¯ü¨ëj$D,±õÐg DxïÙ¯ˆoH$ècwmÝÐÂuÐ÷g.dþ£×:êXïŒì܃M™ÿ|ló›`—ÉïßÛüX,©“çw$©k¯sã‹ù¥˜¼÷¦½®â›ÁKÿä¼÷Y{=NƒMÐíõpïqƒÐ{Ëçá:ŸÿÑ6þýõVŒµ;‚ÚßËtê<2OhŠb)¦3<ùR‘ê1劑÷/ùF&¶ë0ô•ÍðÜ~~~°Ë…“4âÒ“zLûb}z™}mûq»¶F^~oûI‘Ÿ-WrŽÍÂid$õÁ³DmÞ!?Vo|#ƒ˜{ÛþÈë»,Âyªmk™Õ'â‘×_í¸œyCmÒúm:É'uÎ=KV¸£û›«9 éœ?üäV T#i€ÊÌ$#ÿØ÷bhç±BÈ,"“û¬‘ºN>¶¡ò­MÚžß·mšÂó|~l“nm›ô\UB"dö‹Ç†ðÈ× Ž<6ù›ÇÆ<68òØä Ž<6ùÁcC" @>"Á©Úæç¥ú6OMe‡;Ê9ŸTÞCŽÛ¹¯½³Þd†Ú½\)t; ÑÇîQ#½³ƒ«­M{·Nš¡^ÙÂ> ƒ™½z˜VÚm“fi³úDÈ+2 ·´Im@.„$þ½_.‰ïQãäØÖe#dQ¯#¡‚£›Ÿ™[Ô¹XRYq„ ­×¥yð6N&œs‹ÇŒ²¯Um‰ßR°fíXkÝå‚Z*ˆMìi§!y5ŽÍÿž½åi™Ënr$ÛlI°€Ì>å¨g›£†¿~“·#$Ê<òSŽz²™çù)G"¼}׋#@f_›$¦ðïߢ >‘Iyr’E°bÌ3㺮 «Íå‘„:7dM;Ÿ–ew9j@†J¨©™š<ƒ:í2m'×ùD¹Ê²I^…œ=Ä‚Ù7$ÂLŽ\m¬SŽÎìéUQôíYˆî„{}D›Î’žÓÖ2µ*OLÂ;Ê~PÍÔUW[Kra‹z¨þ:cgT?2Èr>`çŠÚø}•Í®`êɳe—û„ÇŒE.Z'½^NÇ NÛžŽ“K[†¥–H_îÅ!)B†,Gí-ê-L aÌ+’ ‘•ÖäeÃú®l×u”Y¿ÒJìL—}ÿ·´Ï#àð„G´Ÿþ0”“¬Þ-µôÉ+¶1Å7lG‡Ø¢ÈÖ VVÈ)>Ïìl®Ç-AÅÌÞ+™æº2GY5^![;U²sò5Çf1u8ãs 4ú)u™††p§œf²S:ή› È,QòúÁ¤‘›g¢BÆn ¤Ú¶Q»9 yC$Ç(7ºPU‰w”c·g6ÿf^ûÈG²ßt^š–hVÎs'0|‹“Øfý¥wÔøa ä§T›Æ¤Ú¬ÀÏ3!šÑàZçp Xà¯yŒCþØ‹â<¬Æ×Û÷^7½¨òšöc\^¡1æ:–Ù[áäýkbà”È2 òñ_²Œ!¿É2Æ Ëäo²Œ!óï¶´u‹¿É2BÞ¿ÚÒªø?’8Žwƒ&Å㽟 š‚‘i;mS«Ç2Ô•ŸhÊŠK¨¢Øâœ¯§|¾^‹‰¡eéMÉä"ø¼õ\†’áùÛÊGì_7á*ryA«‡9¯rÕw¥«o]ÌPÙeçt¿Ú×AzVúUŠbAÈ,}ž>F@ÍzßCìºR©^Ù\Zkx5vðu&8X")œDRÁSJD!Âùª3ô1=bIH¼÷õØö«¹êÄt ¦áP5ÄKBõr?–ŽvW°GIp°(¤G¢ƒ¼½Ig܉Ǻ´Ät›Š0‡¥ò[Õ†ne/äÖ{å$>€¼ÆÐ’:œ¹ŽloÖ!³Or^vÕ ’¤¸{¶K•Ú¡^B~—rú"ƒáög..Æô_»†VUyMbÚ}ªŽÞy,Š´DadÊiõ§Ðz’o &Øj«D’a#Sêí¢g¦­ëæÖ£üòF™×z¶¡®Á“¾K¢}—å8Úræ!#î úž^Ô—5¾föI°5è­þBû!s°/³y¯vÝ™¸-¶¬yK„Pa—@dGZÓØFÈ{äû˜BÇ[䶪~ ½¨›ÞI´#sT‡±¼)Ú8B^gëuç€È{Q±Vè/iAH༔exò&@¬88ÙBæ u‹¤U [? zQyì•~2i¯xƒ¯yÿ¸×?ô^_Á¨»ý|ë»»½¾ò£|@™=4‡õ( –ùŸŸ“­Êêú‹—á)ݰ±ñ«¡Ùyè…ph×}FÈëç$S)š ÖÍ4àãÇ£q=‹E–qTð׳³ ! –’úÛÐåàP"äõSò»2 z™¥§åÞ†ºS…Ô»¾–!dŽö»þ¯ëý./Kú ׸x!+\ ÓÖÒ!¯É½37»B®kJXV>–É +“Û¼Li„—?亠$\Ê< ïoü>’] ºuÇÖ d:+ºiúF]µê5#³O!™ªåz³½Ã;JÿóÒX3–VÅÚò;xJÏ$4äM~VU-tDÆ÷'q¿Ñ: dÂ6ªůK½baÐIÙÙŽu⻕ë²JýCK¸fÂÎvÝtêgZ½?jظïF¦\f=Û˜µxÕÅ|Ûe d~æqs2#ÚC-°á¼ã('#N ñ† ¿´Ð½_¾íøVÕŠÕÐQ¾¿G_ú=Wg¢@¤:ð5³Ïažôè8ì7ïIîÑéäPâ~áרހ<B^Ñ9›—2²±ÜuÉæ{v¶¥¡µ›Ã¶mó4· Á\úÛôü)³I$´"P©ÞOÂñ:0ךf¨+ÁU× ä!§“ˆ2¶!ã±äBg[¥ÔdÞì‚yŒ„ð7dî½${ß«!£kUÅxÀ`GÒ4t˜O¿3íÇÔNè\Õ1ê•“â{$:ë­/:ê!Ïh9cä3Ö>ÔüÒ£Ñåçºà{¥U£dMeÏÊ¢ñÛ¼¿MwÜôsMÚvoF^“§²Ø¹ÓåM5ad†â™¥'Ö½áhÁ}÷–€¼¢YÑýN3+îtàŽ^#ŸBÅ2ÅžnÂ7?A…éDdÂÎþs8æõƃ¬§–3ŒD)®­*::Ò´°—IÙÙŸÂ¥g¨ÖÒxÐ*™×iøÑlcÜÑãúÛ)ô8 øŽ~ôŸýÿ<—Ùö9©æýhE‡Ÿ9/-•rð_ÏOˆfö¶ˆÇ¼„ì‘vèÿM¢¾VÈûrFÈkr¶BÅç­iˆÚŠYqìNLÄqß”zŒ"d;Êæ™O®jê‰ =Û-yC'Ûž7'‰š®àÞóÓ9†aŸÚ5aQtßÅHBúzþßèB¬ºYSÍ2‹!Œ»®‘~m1·+Tkó>b,—¬dÝî3œ =n'µe8±v/lZ)ÜÑý]ug¿÷ÚLþµgàÞ¢¢5O¾P f›„}n5táe[U¯­.¡Ë‘°³ÿ‚Ý Õ*±èú¦„Sègª€ÿÇ*{ü¾Ø4áºöü׽őÛE:#ÒmÖ×,:ï È;txœ^ܳølh°yÇAce0F±<…ºn%F^#ß<Ô´}©¶µ tÈùñ?§Yq²7ÑM_Õ§-ÏÇE‚µÔÛÒ½”>àà Ÿh¶y3㌻ÈçëW3Ϊ‚Š%‰AÁ½‹öÜ»HØÙ¸ÇÒž{,1ÜäÔcçK 79õXĹǒ°‰ªôgõÕ1«’*ÂÂlóJç]ΤÕÿ³ÍëúåÉ»yž(xJI‰×e:Ö`SÏ›éZÃÛ|]‘8ô\‡§\õCÝ2Õa›9‘:Ï ÃN‰×Ì~5‹•±÷›F– +PÑ-6¸ Î;^'=™7S0×<Œø_Ä{¿Ða[ ¥®üù¼ 2ÌŸ¯Çv‚ìU×÷+«®¦táBfï–I¹Œã ™'ýÚé!¬R­ê îŸÇY,·Â§•nû !?0jV‰È)îz.óáÔ-ŒÅ5N) 5Øëõ…QkºFãÑEžWÂec>(ËgÕŠ~ ~•¹üü ~²ÙwÔÜýu¶ÌÓ*›!¯ßµ²&€ÄIáÄ}G6¤½WM?Ïëòsýõ|³‡•ëò“ýv¾)öŽÏ™rÜx8çâl»œ—ËO~:iò§°æLJ•{Y–%B^±sŒ;jâd+XOz„Ì¢]+õ¼NÉkÒ‹yŽþaÁÂ[?«ãÐ%ˈ×óïtmï‚iìÀK²‰æöÓÔÃHrI˜*ò~r: _œ=U¯åÆá)áo3µ®ÔȤº¸üào3Ýõ´¤]¤\„tãó/öÐH=‡9ôüË`øWJ¯õy‹g»át §d] ]»!ï1îŠz_n[Ïå´„|Dž@0&œÂçcæd@HD+hpûÐCºjËÒëqùJù’‘Û¨·Ï2tx.?Oôä-’r[¥<òŠ*ß9Ñ‹Úeü:°£@œ“­é›Þø%BæIübíÏz6Ùm­qÒ È“É¥kÌó¬øÚTt÷±2yùfú¶"Ó7@~0}›Ê^M¬káw^¾™¾­Èô i¸^0­gÕPîSSy{·‡[‘= ïïöpÛX·å^x;a@~5}ë–°3õÈg‚dÛHø$:á§ôú”³»8Bg/<ùŸêÅ Úû<{€^Þ­ä²’‹ÐDžhûF†º¦¸2,·PXhöÕu.® šuÇ z‹CEÕW¦!¶P ½Ã²dO +˜jØX‰9ˆ. ‘>´•ÔGÖRofW$"0$*³ì|\õ|+Ò»BÚrÄ/ úÃÛK³â„1¸&ØrÄs–0¾•÷I6£ !¯_ ê&Çßê‰#= ¯ß(23Pd.‘ þ"³ äŠL{¢ÈxdÔ½í|!% ïhçÂ%¹"æ%¥²D.BfŸêJ—mc{BBªEjJS±^6‚ÂD†×HåÏ|lëJ:»€oédS–li™ni<òûF…ˆ!Ù¨´ø¯çïGúw¶öˆ‚"dâ _{¢†I±m»Ž—pÍ×—¤v“ÿ(ª^|„Ld¬ö½+÷ŽÌ²]2 ‰Ý¥í3ÙRL˜h¢YsIiü¦mW)#½w*l.©8š²cÞRÙY±žàkëÒLüÔ,·±cðm&4þ¿öкôi&riZ•c%2ÿ$e‰8Ô ¯¿ˆCˆCù‹8Ê»ëõwqèï=ÙÊz¨Ã­—J†@(¹\³·ùÓýN¾tjdjŽ×̾ |ŽTàs¹æ¿“~@às¹æßI?HàsIÿ)U·ª.,´×ÛW{ž] 4åK¤§ŸŸ¼Ð[é²Mþz¤ž`¤1¥ÑHßÎx#+¬ŒºÇ™"ƒÈ ‘(|¹>¾ 9çŒ «NÈ,mô¸ U[,m=‘j˜òùÖòÆ,9Od˜àÞ_˜ðTÖÑTŒ(X¹²“1 •›¡Ô Rq¹È@ÀõÈÏò·A,å>`dÅ¡äo¡eþëù':‹”Ì4QZ„¼ÅŒ’ˆÔóͼ[‡÷䘳 ÆV¢™¥÷5ùsmúêB®ëÔôã‚ÏoXUÊPÞ m‘€Ï¼I/\O7ËŽN/·Ëy}§ ófnbÅëQJy÷fìÛwèKëõã12 ­ÿ‚Ït“æm­á‹;‘ã-­!H›ŽeßçpØv¹eÈò.M©SŠI]-¯™EÙaØDrJÔ¼ÓZNg jÈnè»±Yê!oQ:¼é±Fª¢#í€ÿz:3ø‘\‘mh˜hê !€ÔïÝ<(.Ò”uW#ä3!jøˆ×UöMa¼'(B¾i=üìZ¼É†–] 3Ø-‹¹! û1ìbù°šdµ ñ¹<._òç¼i”\Š˜{ÿžÞÑ0qUøòÈY­Íurð£Ʊ^TóÛÚÂf/j£ªS}…×h„ê÷ÐæmN]I&A2 «Bfvƈj^Ú:† eÕd³þ‹óHý4'ü;oL´ Kµ‹µÝãvJå<Ï¡·ø¸ÿN<—0/%äV,FçåìÄèð6¿‰ÑyÙù]Œûk‰ý® ´ ÞÆP©fUæD8Ì ÿEðŒcþûV®±ù¶âr† ú¼<Þl›˜?mÚ¦hq—”àùTŽ(=(1¬FF"€9B³»SÕñ~ŒTBæ(ѱyL>"W:° Á…Üõ”ÙHUŸ<¢mþã)«vMàãÁÊ¡Ëó<ÉÝ>Á ŒšJ É\í?~$Ûw$šíØçr˜òšºÑгzPÑàkfȾÇÛ¬›1’} 2ÿ`³ÎRÿƒ=ü3Gõ¢;ŸpÉrÞ›u ²ËKjkûç·3vÈ£¨º¾ê1òwSá+ÖÕ/]ô•@$Nút[ˆQd4ÁtAÈH¬0ÇëŽþbl.Ù!gxž÷w!©[ø÷.ÒQM~§³Y·&q›ÞÇîfï'&_G“b#õ8‹¥ËóùfþK=RóÚ¨ ~gš|çmïÀbIR=Õ†k¾~ΡMÞÌÎX,ÑYŒ#¿Å~eèù—×å?F2tÞ_ÿOØul[Ž*Ë_:GÚvXóWkÝ_@rÈ¡Õ_ÿ° ©mjÐ=Š’Ž´¤‰ŒÈþ±’;Œü²’§!}Bù>Ÿ­F¹ ,Œ‡þ>óÓø¿Mn4դ߯òÃç©rd5Géh0fçkÂþI€PcÝ‹¹øš^¾\ùïÈ!'ÎY]ùùŒ™O@†kNœÌÇé†À‚ðœ“'ÞýNñÝMæó׊Í8[13l•Ò_;Ðu=,OŠªk d…}éyvºtÆ©v¬Mñ^‡‹;B¦K[2ÈQ ©j¸ûõsË º-ùylý€8ùyÅÒ'‰#kßÏW§\d]á›mƒ˜öy{ÕMåˆtø?#dþ†äXXŽãùî—÷rD£(aß#¯|…—„Dö¼ÿCÒ7~Å o$5Á^÷|uö…¡äÃH‘†=$K)–¾“á²X}n´˜Žz ÈßSU"ÔY&Óã )W„Ì’8¯ 5W ÔEÌ£Ä<¥ŽwR)ÉF|²Ÿ“ítÅÖ‚TTqÄÌ~²sÿŒZÞ5 ˜Çn!óÄZ  Ño¥#Ë]†ºªG^>Ê¥:ûÉߊuµÞC=ÆKÙÏå•Ìîc©¿r !£±T÷$?˜¢K++„L#+û晉¬ú¡.Šß=F÷Å fmTÒM3BºØ[Yk¿+²™ ‡úo–ŠÕþ –Qf[vÝ»aX(Bf ²vw¯¹”SEºU d²BjwÓœ–F(<ò’VÞ©ñ82woh5tûŠ×xÂVžý0Ñ™L'퀎•ežÝò¢Ìß9©YÇ_ó8p„¼#7k{"T„ÕÇÌ'V!ääæ òLgÑðæÏ¦#A(BÎ[K«’WpÍûK”˜OsWÝ‹Ø [è}aaý ȯÙ._øâ~Þô8Í5P™Î A.+ûý}uF÷ñ笸¬ªPOÏ~ÇT+OÒT¾'wÈ™wDöBæÁ‡4µGrSÈïM¼ˆØ1Õ–MTÇ!0’Eæ\06 ~Ìú¨kýš`d*‹Ì9O­eN›P/&—=Êãe‘9-œYB×ë•Dç±AHË04Ï^W®`Ù¶ú3¤XŠ¡@Èk"¯ïûÐ7|†™Žøî·€¬K7ˆÏÚRU®çø‰@²ß±Ì̪››º¯Öy.8BZÉ~3ÆêlÍš×ç1ýð B>z¥1ëÒwWƒþ>˜Ê¿ùŸèÔôwg±U¡j¤ê*°^8Ôe3:ô®ÚƒóQahÔ÷w^ ¦d§ã_c(Š{šZÍŒ(xS§¼h¢¿Ï‰È­å™%ßgëSc5MrGÈØ‹6oÊ 2´´h 94!QϾ)/Êmy34yM“ƒ!')„^ö~¢["íW'RljŒ¼§Õw7kRWµG!vüì< Õ8‰Óe"™J„|Æ·Dý ¢ÎN%3ÿÁ*9…éGnn<Ôµàéö“õÕÀJÛ¤0R~¾f~’þ0yW§ã¹½ ÈëiÐÛUUÍ>B:ÎËP"d݇™ãeKÕ†ù¹ÎÂ|E&{èKÆ[ÓÀRYFóíì÷ö"òi×’ù£ÑT£ùNä³›µ¨b)„´íp®]¡&ªî†nf!¯¨vãrøRò†•7#ä ö㬫ž°Qª…#äý}–"M–Èû÷,E.ù™gwĽþþ!í¸êÿÒV !£M±©Fùºÿ¨Ø\OÞÒóm=ÝåÛ›™Éo>K;o*Úm¨še)cÔÙ«úZƒÎ¤Œ¾þQ`ÂÙ Ì—säD[©0òýp™³k€¿3ÿf×`؃!?Ù5𹇯#i¶L̰3 B4:ç; ¸ûåÔÁ²qz»d¤<8B~ÙC¤BÈü­¹Á!÷]Ä7’»ImŠP°‚ß= £ÁŽ),ÚN²¢Ûy;q£‚P†Cn[="d–®%0èë{ãLN2GS~j3OË(25Óó#cúštÑg̰#ä5EËëžR³ y‹ëÓLzÛÊ‘˜i³,2ð˜<òž¬dêTÿÖ²îhÃÛ ¯ê‘„'âùAú-É¡Wز(×»oQß´éÃÀoxó?®E`Úa4@Šº•l'_ô÷7é…û3v%ÝÖoãÒ® Ëž‘JÍ(+PÑ ÐÔÊDéó¸+MÌØ`èåäf”˃ò]©0À’eo4„ì2©E-vQ@È,Õq´­S|õ¢Q;ßw„„¤Û“€™u$¥åÚlÅŒ—TÙÂѲÅV7=B^­Ä**Û:l×ÕÄÐÍøï¼}˜NfœCòIÀï´ŸÙEà,Ñ~Vf#©ZK™µíàyEH¢ýœLý¶~{0²ƒ!Hé–ÈE½x“ÌpòxÐ)ɺ°'×z×C}MÞODA¸šc¯¯'mUåÊ’í5(d)¹ÖÖÖ.Ø*òœƒ2P–c¯çvé5Ø$-” €ÌÎN6 ” +ýÅ+Hº•hëýl•¬®ªfZî5„)a÷5•–:•¿Q~yÛÆbÐÆŠOt}^Yj¯htx5cdv…˜-0v¢ÓBæoC!|Ðå×X`| …ŽF ‘×OWu RžväÁo’.råShúd©Jt˜ ÷S¿ŠQ9lc‹YRšr¬KÕÓqëç: ç"†oö±e=Æ}\¥DÈ,®:[¾¡fcî•h†‚¦„°ë¨T´ T*;õpÀñ•¿(F h{Yèó{AH¬2eŸÝ"·íèBæ±Àè#!Ój鍨ÀóÔ‹Ëš˜+^édÙËRöB¦ÃHÁÑDJû¢Ï0|Í:¾œ‚»9¾vZ¶ø‰îJ»¬9:.Ç„ïþˆ;-õC>¦¹O¥˜;‰OtÎù»ës®ØzHûü›ÿy×›Qo,K¸Ò'SPßoƒE9IîØ)4ûqê-YoÀ¹Ê.Ù?ú‚3GÈ/JAì(‹¼fψ´‘-5w|diý\>Ú­+k·Î+„LX–ŒÖΠûX†Y_>Ëå$Neé(jI:¸ûõ+OeéÔ,á̾«ñE˲ì‚cK+ìØnF.Xõ…·t? t{Ëq.n àPçBüÖwÆpĦÙhrˆ{c‹0%™¥Ù'c‹Ö[P„|Ÿóþu¬Ü%Ùo-D= äc‹ÁŒübl±àg¿§Ý>·7°ycÓ|l ŸßBr0è¦$Ü^²pÉ\È2#dŽ*¶¾ƒ¨f¾n] »ö­´ïYR®}+í«B'>K¥§cNá6&¥F£—X¬£^qfÂiÒ'7åe)7pfýt‚¬iY„]³“ˆºo$Ù,i,Ô&œ<2Þ÷R «Ð‘À¸¶!ä5©Q7çmäÖ9g T™®Ñþ¿`Eë¤N.l©› !ïIšà¹ÒF˜½ãfÞ!£„=7-S[Ö½(y37ù|kºh$b:Ø?¶ò»îé!OÈìC÷t0Õ—]ßq_œð‹<˜XüÝ/¯Òj¾¿®‘Ã<0Œü4}H(f¯Ýéô!‰¼Ÿìzý>}ë×WSzŸJ ­ûî òvê=°ÆKSndÓᯠlžìzûP;2\Ìcž&׼؜Ìi @¯çþBs|Y5Ï}- „|/sÊ›ÌÃŒù«á9G†çùü`xΑá9 ³ ÒbmJ¼,ç<é㣇ºîíÍÕ99+Q(f6÷Óo)ýVA·cŸèЂÈchà-¥¢ßþø)4Ôö}µ']ÉD Û0E,wÐ#ÅA}z,éÒg¼âe=,rœA*$‹Ý€L¯IÏÈK`Ÿ8³![¦×È’ÔzCÈ«cG)ûìÔZpèÀŠ#8_ ä-vOèkVFG½{w™-Z Õ¹þ°oFfIõ…ªc{ºfžÚUxyqttW Bê[†Ø¥¶öî«aDB#d:áäd[Û®ìÊEè@VHR±t]?ÀÈ4éÏ£Ú{dT[Û—’zF++2õ{yl !óÐí+ƒ FÛ4ÜTøÈò»}aŒÓQê_”Bí†'Û¢ÑwFK¾ÍTðýQD®&‚ça‚ÄÝ~Õ IèDnÆÈT.Øëq1ê‰l=¼Ï+zŸÄÏphd'‹z-ú#Ói¤ÊÏé•Ä—žCývEeŽ„+,t 4—Çß&–™* †¾Ñ!0ôYSÙmÊ„(HoŸ]©„+næ'r†ƒ÷넼Àä¥5Zj=Rñ£ƒTê–ÈÛÚ¯ØÜÝ2:í`:hPyK Œ Ï¸Ì¢×;(¾æý£äcòæ“z©+¶.‹]—¶lt’l5<òùqŠ—ÀùŽxüo¦xaÞ KÄÉ_¬%Dj-‘%âäoç}å隸sêf§i£sÑįãŽvâüM.³W¤Ø&„L;§¡oK$7ÎôŒ"ä=á0×^õJ¢‹ÞÎð=¾¼OXɽÏ!ß½OIé­!yŸ½O|Í7ïsÓ‡+ŸÇF5yM‘νI®Qû¸Ç½îl ˆë£˜7ßÅ8¤oþ&ÆHûšèw˜ŒÇ1B>ðoä‘ú#b[òùöפø×|ĉ±Px÷mÒéä°Ð/ C_ùîå—@å?´˜ƒQuS+JU oO¼…V®çjUÉÔ-Qht‡—G·i; :hkòÔô1ÕŸ¼â³ M¨æß1}ÐV޼šw?snØ™vÄ8=íßwHÌSU|KA­3>¾Ìê¨W„Œ£Þ•Ÿrã:ÒëB^q*çÿNÒðj˜&„Lêk!‘4$Îw6„¼§N§.lXEGEY.a„Ã#aÔ$†7SÃ6ªÊc:ò‰¤\øMä"‹£®ñûô ïo8­¸ßdY´ÄŸ,< u—n>{Õc(œ³eí7’vêd­`ZŒÓãÚŠs¶^ÏQ þûïÙ5-ŒèK®bâþ{ }ÿÔÖ•G¾oAƒ/»Ÿoë 'Þ¬B €Ã&‡rC9>Ù ÙéçYIÉWÇlÝÎ"[jb— ë—%NQëß;QbÞ 1#ä­¯*hâÕB#B^Ñ*qÆe Y)¦ ÿ·Ú†ÍaS§s­?ò囂—¤¤+™÷¡Û$B>R¤û5§Fn|×A›@È'l¸ÐÀäfHTJyà'Šã´…XY{ªZFëµ÷Ó8m |ËÎÖVËjÇÐ,AôµP6ªAguÐÈ:Y2DãŠAŒ¢‘-Wd÷+šÃ;1|õzŽóíUrÔÍ(,£>DÖN‘dÌ´§ Ö­<Ç¥UM&ŒÌ@ƒÎŽƒ…yV÷1Ÿ¼ß¿Y“š¿þÎÇyúÐldj&[È©R¹˜jku4Çî©]Ê;-hH£¹1¬ÆØàeß/j`ú/ËdÌÞ*M«I…‘oÔÀqG¡`.Ê mÝWú+ ¨#$3^ÖÎÇÜÝåÒú@â|Ø`y\_èÈÚB‡Çíµ‰éh8kÎŒÌB+žXÙ[Óáú°òâ˜2Oí9½„+9ø¤w¦M!¤71&»`³˜.”PGH&·Þ#7xöÇ·ïÉÚ¼“Ee]{Scw:ÆÔ#S)ù?AÝÂN[Ç3Ff©´´k´v³Ie‰ s9Y2¹lrÜÎPÕØ”3ˆ½fO¬ÏcR?×¹žd××KÙ×BBP ꬵï‡$x¦jŸ¼Ú§Ý—6rìz‡b"ÿWýõ ¢®mNÊÝ|s!¯éªÿNsè+©Wh7@V¡rg; Û²ŸžýîÿKxúîšzû\òáÔ–L~vÚJ­þ5E° ñÈ'>%×,u ¤_ÒŒßüÏ'ýo1C$ôÌ¿7²j½|(B»V’<…ÊêÍ"` Ë#ó¾‚Cw•Ý cVtHǬ²çM_†§"q5y½+ÿ+ÁNÈËë°¤hÝ÷™Ábº}|ÜàïyÃãŠVkÔît® 8î’q0ðãeA:–s ·çý³k±2®Å% g Ñ&8ÀÕ6U‡GÔæélíˆÃ!…0~ ñ7©ƒ§·^tåHו‡ô|ÑSþHœðz¯w¿èóŸä2qÒ>¯‹)lôy¢¸<—Bæ§‘eå@ÌQÓÅßVû|ªÃyä%Ža¦Ã(–í:ÀÁwö‹kжAOÖ$|ðy{ï1ï¸;vpÅrï|Îæ­ÓÛN@f§\˜9dóŸÔåìEúP]sl\75#dö©„#AØÎ#ótdÏêõúÔ¯SÔAÒÄ#/¼Üõ?‹w¿|ð2â'/£üçúÁˈŸ¼Œr4äÆ#ì©ÞÌxU+ ãWü?Óžª`€½ïÕRØè=2myùí[ÿ‘LÌQ?OG¢Ü5eµc(1‡µýR#d–x¸8™™Ö˜æq˜2O¡Áì`ÙéXȦÚòñM¬ƒ•[ü5ŸŸäq¤9 £¼BæèîÌWµ©(æ2Þýä e>Â5kºékJ„Dô(O2g7ìaèÁ#óO»ÍÔBd•=_Ç~ý²Ì¼!S(æùϧüè$ž'õS~t’Ïóßo$%Â=ò­ @]¥‚yž&#"‡ :OžçŸé<$¥óx$*6žô4ñùœÚ ›ýe›CÐ#ßXV RžXVxdþÅc ~£“¤õ‹³ìÉù‰4ZzEç]ÆtD¾¸üôu‚¼„]aû !#]W/µ`8µ´ì÷PÖÌós´F}+^ )÷š—­åwäþmIyÞ髿£h`Þ!ÏϨ¯Ù*¡ãU¸æÉLžvÚou~´“ОÉ/?ßÝVYÈôóKšsÙýÓ›pt#y½J6"dŽ÷:»–6¢÷ºÄ1óD*:þšvvÇ–t ø¶å)ùú?ä@¨3¾²_)¬Ë/Îej›ñ™}i3çóÐbdž|ïÔù¯G©È¶¿SLýÔ˜F6ÅÚô _"@~ñFê˜Nçí ùe=F%%«Bºò3$²¡mHéË/Ù×F pžÈd¿|‘£1ÿ ÈËé”±4»{¯å²”cw¿¾LløjÑQиŒèJÿYC½)./2O§o¯‘¥šÿ'ì:–dGà/M·P›ãÞw#Þ~r ·Ä~ý‚€‚R›™¹fH-e²2³¼CH;ÍÚÇ9ÊeïöMæøwž£5G×ÕÐqUy â'>ºÐg_­5òœÓ|”¾Ìe©Wäbo’¢@Dì-ªi+Ö!Ÿ±ì¸ÝŒ5RfRV3óö5;âyrÿà@(N„ yœLw|üi¾býîí ¾b\á±S!–ÇiÞïܾò<ùàÊY†ìfÖµŒ‹DÈ`#T”®ÂcŽ©òµèf„„5Ä›BÙß)ê=“;B‚Ðæö·‚‰¥ !o¯ë’±;Òë—øì÷OHN¾¢Ç[ñ“Id|…•!&³£½Xø½Ø3½|Ø‹;·CÈìoöâÃ>jBÈ$XAä. :ÌŒÿâÒë/5 #cF‰“ Ñ{\_Mzdò2ýgeRÆœÊ|ëòyCȸ_^9ñ}̹ßAÊ&‰ÝΩ›ÛY9½oVó<ï°ùé Ó!G1ŒëR̞֞ùéÈÜÂzΫRq{&òö*0«ãy$0›Ä¢Êof9<ÍôÙòúq’”‡·îöq’Ôeìi›|‡Ìiét¦Öj-f)äïéýƒ¤³p’ÎÆÔïWÁÞQuáw>¿‹ÖBÇ!¹ýœ\‹½õ"õñª‘ÃÎu» ì,‹/ƒ¬4¢ôˆ(ý×ßgä\)ÚòzŠXâ³÷ »v ¿¾V½ïw$·ä¼;iø%tî.:OfONÔÚ<÷nêK¶6}'h'òóÓC¬$&̚ݰÊ]Ó”/ß»¥ðò0ILn}×Ê‚Șn°¬¶½‰½—CÓÖpEÏÝŠÚÍ㎑Q5äæMk9¯ˆC"Qe,³ÈLRöëZ d´Ú¸&›‘]é·Üš dâïR&\jÍšZ*„$1{Ïšph¤Îø !Ó½3ችỈ{é­ •½ûχÞÙQKzgIàĽwW†Ñ®äþó­æ/8$’ûåÅ ÌOy/{&Ä uï;¦>XwH+ªLù>IÊpȈ¦ ¢ôJnä*2–íòF£‘‡±lBÔã«Ý®ÍÆFçú>¶¹'ߪшOr'ߪшOr'ß«mxFWcÌ[wl±J•J¯ÝVï{úQÆ^ÂJÈF¯HkxÙ!ä5ì°ÜDÌÌþ”oì°@Kr [•êØù0” ï C¹ßq·%÷ W‹^fSƒ„cžMKGÏ/ ¯½+Ú&CHìÃìdBô1 EŒLP/Ò)hd¯@BÓ!‰T³MµÐ­YNÈÔï2Álé8&­ø y‹^Ý”wW*Ö—ÃB'„¼á¨ÂëlÑT·B>by[+»¢óž²èêvjò­³’ùTÒ ~çó£³F®U !±³3RÒø—†+z~öa¦fe‚=îM¸›>léù¢zõÒÿ:¸ôßQ „EƒÎÖ·w>šàÈÑX°Ï;ZV C_rØ;—Ó^\ºZ%g Û&QeB^£ßiØj3k¾ø#ƒáeî¶MãèÁzšIȤbêXtíN…˜ÇÇŒ¤ûÝ1ýïdl.ò¬B‚ɫٵw¿sEÔ1wL'ëym7+B^á7Q•j› &Æh?zÜ ´wé¨Âé3÷=HÑ&'êØ)fX›Ö£'Û×X1Š·¢ …¬ëÒfßy? ïyQP‰EA2bn+æIä´S[‹I08ê ÌŠfúÒÐ!¤{îÿE2§ú˜Šépÿ3úÔQ÷¶½{ ëùw¾å'¡Q‡¼¿ÑfÉG¶ 9y½CZFï¿ÿ¹ìàÕ‘]‚p«C>‘qבIª#:žoK|çü\u;‚Þx•ɼnçCß¼#Bî;Š+s¥®—dé×Jìbç×ÏhXoˆ¡m„ŽŠˆg¬v–Í'$‰öC§z’%5J.Ð* ÷ñ)=²Ý†u`r“yýTÓåöؘ4x´>äÒà TÀri°w=/¿È¥AíäyAubó%Ù‘ÂRjì‡Å“ñ’ç'ÍcŸÉ'Õ‹ˆãöן?/ÈýŒŒLºK04Ü*±%Tƒù«líØ@v ™ûÈÎÓ‰Ucü~NÈ$pˆ¼Ù¨ýŽÇê[ÎÙ«ù¸Rf’Ñ,Äé-XIZ¤¨$íi8ûí£é9µ²ƒ!ßÊZ)ÃÓ1•iÿ o¯¢Vu%ý›ü¼¿•©‚ëÐñˆ™kï×B~\Ë„o×ÅIpÝ!¿®CÞó|œ{à5wwžµ´®èöÄâèþ²’çN…kZD3ÃÎ!ш»“›P³…r„ŒF^¹›Ò’6^ªÙ!£y~ÉEÌšé¿>ß2õZP¶‘pH.뢱Õ*òvBšï}]ÚgƒÄWt¦ÅxåGàx?×cxšÏ0,gmg|¤L›uÑ‘U;#ä3Ê¡¬Fª¹Úº_–c–Ρ¡¼Ò+ÞÎ0ôd±k‡ˆ ½oüÄù9ÛúU® Îç’Ny1y<qL‡ëyX¤Î=f„LÎOé»<ž’ïq’ÀY´÷¾òÒ¾ã2*º/‹ÄgOã{“z嬟¬Ÿ#³Äu+:Äuõê…ªò~2Á³Oi©4Ðïñ ÃÇd°,WÊ{™e¾¢gĽ¨ìf§£Rê­ßùŸÀö?~-Täµþäñ%Ùùž¿‚}€þË ží›Ÿ>ôÐëG%h¥Ÿ_”dæ2*HùPlÈ÷Å”v=…œŠÒSyd»2™é;‹×ØÁXFC“À¸'‘ÓÀ±4ñêÑžá´X¦MÕBO5³Ž9äàôeãI¨ Š ÎÏÆ,9+­„>½WlpHû:ý»;ÑêðÂ&ð1ï¨Ýå]vÚ§ô%6û8?0PÕ›]=A‡ÄÄV§ã†ÕÌ@å¼tDÈ0q )7Ÿ‡–åSë =ä'jü}h©—µÁªi3m“ÌB¦o¼²Í@å ^#ä-ˆHúyʦÑgŸY7K„¼ peÂE~ÈËxl}lKú.å¢ËÁã—ü¤/Ÿږk«EO¯¢=B†ÆméuÀ^4¬š²nBÈæÏræïÒÜÖœNÛV"$"@ØæÐ(é–uú䙢áÜ ·[×ðÜOôÊh8w,™ÌÅò¹¦¹2Ó(9íºyQ B&±¿Zåµp•œ™ªñ1 ¦Ñ‡©ðšÒ!ÓˆèV[y-ý43‘wYø:î/}[çÑÈÂð½(GÈ7^SõšRÖ¥Çï>ši­‘Kx—ÎR†•k#ñYo\] ;ä5 ÷Šë£hôGÖȹ÷]¿K7­ÕM²Ý³°ÖE-ÞP<2!F¥f•ÑQùû‰hÊo0æA./.»Ü΄ï• ¥'@ËõCÓ¥‘¸éB.Wüu8Í^ëÜ÷‚z¹Äê^ÖQÆ*E›yE6éËaärE_Ç¡)w”VÕ¾êuvÊa¥½\£±„åíIÖîžüs–Ç»¤÷$¥Šä\j)™/ËN‡XT ä‘*jKþÐߦk}nN"­û·S¤j†û™¾u¼Jñîü'ÄâýBü›ŒèÔz×ÎJ×l;üÕŽAN<‹‡zÜ1yÇæ ö÷Ëóäpæ ›l Kid‡¼¾HTµ£tèLJ 1c¤“Öý'r+²tXvxî×L‘9DNíw»5o_|'×sÓÅ‹'­l¬ß6?`CÚµ·Í…÷³©KÖOàlGá¶¹Þ4k›É®ó#æ$¢Sƒÿ¶Çn¨ÚLýB $8‹26ÇŸeÆé,™o#9ä-rá°ž*µìË¡¨»aäýK3د 1Eû}3#¿5ƒ™üÖ ÆÈOª˜s òHCþïC¾tŒQÑÔ:î¡ÔAÞ»/†ybP¬èᘷs©ŸI?#×S_ú½˜ó’l+¼T¹ž‡ \PiŠLåøÕ‘ˆþûf‚V¥O»®Ïo³¶¹øÈ*&õºË‘~ô^Ûèô v؈ÔkE¢mº¯) jêÑnÆ.\ÑíLòD±×: é:¶!d”#Ž494Ó´oûä[h™D‘.=3´B”íÏýþËèrÈÇ/£ËáŠßF—w *¸$–üÞý ¯Ó¡ÝU·Ž- Ÿˆ"Cò·nb¦1i/3;H©Ï+V™ó!“×a-3À0-õè=ÉYË©äu[Þ$"sÿ÷—f9¢ I•œ¤ôº”„¼ú%3§`É}Oßl#EÛæÚ¥Ý:Ž7Ys…5$¢hGg¯áì#§™„ÑOÔÐg¯»©i:_»ˆ5·AB†¹³‹NŽ-F^ý8_^zEP>¶\Õe !-ò?ƒUÖ]xÖmÏa]ŠèÔû*DZw‚ø3Óï³GFäçŽédÙ+ºÌ‚Õ…BHG ³EP§ÉI˵­öµÒüÎÝg‘¶W”r芦+B’åS¦„¤ßÊyx—Ò“l’^?«£Âs¨hï|…;;irž‘ÈýUÚ‹;’ôÜeó9y¼Aº1¤¾›ú센¢!(CPsWÒ!4TfÇföz‘ƒEH‚ÎîG°ªn¯X8ûó4‚U1v}L)—pöçK&!'É›!Ï¿“×þwîP_ŠHÒ/C&¬—Œ“ô›“ÞŒÁ… òñ ý7§ØËܬóÞzd«zNù1$’&g£÷8õý\e&FObíå“§5–i iú‹Lƒoã4ýM¦A"ä[Ï`ã´:R(ѧ·;Wgv.Åj¨œ¤_=ƒõZ&„LÞhD›=nTjÇÈ-¬Jä0fì)²‡±÷3;îçÎù"<á:æF§†™˜}¾‘zV¹F3¹a¸K¤ÜꟋÎ"Y¯“Ã!¡j”܆¯óVm’!$8Yæeð=,…NÍæÿÎ4ò§t¤4&Ǧཀ0}„|óÈv}ýsWëZ.4ÏðÙ_ØÊZ¬-“3¾öGœÃÚo3“‹þäôk·!äóUI[JÚ\Afš>_ò8+Ä$t×ì²è%B^AiÆ‹Ü6ÌÛ±4SuBFjüÞD§“Y6g£òÖMävðöþ¾¦u¹)^zwarÃZD¶¾ÄüPD95PóU¯ßí\d»·Ë·Kn0TFn—ÓÙCdåÆàáì×/cð“a žDjÒ!9 a} ?Ê¿u·äMõ•»ì,Ï ׎ITa î8¦š÷-CÈhxãPP7ã“^ê%9rÃÞçL°*ÞÈys={ç=Ú#?®`›ð‰$Vi>ûôU†x+ؼŽdâ‰ Ž¨™¾_ë„ÈT³-ò­`^ 6/E>m²ƒßGAÿ8ñÃw¼ZWÖ7E^ $ä°‘¿ïDwa^¨!“X;Ó®6ƒi”“Ú9B†ŠYÁ­ê”ØzQ…g”†LG¿Eé«…³¬šFN=¬É·h¤íÏA%güàB‘ˆrÚ¦îŽÖ"ïs¶{RTþ,âäÏB"?ögéNþ,i¿ñ‘,Ã÷þêM àXТmý]zŒ­!ÛÍv*f „æ,wÛ_æ¢ßM-_ d‚ècæ˜fH/ëÌ1ý(ï™U¨;Ì*r™‡ži$DjÏ^Z¢‚>f£ÏÝOáìäUqP¨8s⪻¨zˆXî¯Cãv\JG¿›ÅîÇ¥È+"„™›TÎ×Xî§ñrkýa\l†¶alî!ú½G’ ÿ€ú°ø,‹šåÕÄ*„¼†Ö5õù¦je4ê:ŒLÉܬA] ¬lI°¼ç!è°µœ«l¯z„L’Y¥^ž÷ÃR› ó !o1‘Ý,kIKðóvÈ{ÔmqénÓé-&S”Á[—¾ôelKÿ@æ¼è:„Œ¼iŽ¢»}“g‰ò÷ƒpd•å®ãŲ.áwbú˜U ;° Ø4WP‰éþˆšdÜ7Ú™Žk…ñX‚mÜÕJ…öðÅ¢J_«ùª_û} +ÃýŽ™~Û ù0K¾p„Œ{Ç»¤@»è+›õ.î‘ Wz/së<’‰¥(Ö‡ç9¼ÊímÝ yÇ=ª!çÖÎ:·†èâñU\iîa8“Ĥó·Ê¦¥¿(†ž•M¡hß'eÓÃ'9R6uÈ7ʦ ʦIÞ÷¦ÝìP_z|÷á ¾Qäñ‹oûû#ÁÙYY”^ÐajÔJ•ó ‚…UÖüVþþ­{|–Gžï;‡+ ßÑþ·½v/·7vªn÷ð;ãAʼ0ß‘¡Œ:=\w? H"½ÒàUq¸¿¯Šz”ƒ@Èx Þ}›|ÖK¢Î·a—‰ˆìÖBÒ;7ñ¹ú­Í ‹ÙßJ7Bôûxü"ÝýâÇ‹Ô`ag …™â4ú:_¤E4~FÑ(Î;š0(“HWõ-MøŒ¼B¼Tø.›ÏufÏ="S[“ªàîÛdˆýõ€¼|ðFC‹W2/º™®ù]îd„Q±ô'yeûÄ„^å ½éÏipº¨J/Ä©/gË)ëEANìÏ´9!‡ŒÚöË<Ë\Rå%Ò’|¡¿*„L#kï»§ßÏb*¨Áò$P}üYìm±Î†ÒŸô5GpüºRÃÓ´I„¼¾Š©-ó°ŠiâÝ„ñGa¿¸CCºžA"-9{G½Î{ÍÒÙT B^cÙ üP[‘ï}‡ÈùîÈÎ̱¾ªæ~ç9þ´É®¾¢uiŒW‘רvᦶͷ>Ó¥ñ"Pi,ÙytHß=˜x¯‚âyýÐ U ¤oÓˆ³÷¦:RÊJcÎÞkdµ3ˆ¬ÒŸç)ßÌ[²Ø÷1¯Zå»Béåç$¿eêø!é¥7¼¢ÅÈk”¡”ž2õE»®¾+”Î^ð¶ß‘éH•³Êk„¼Fn7ÌæÅ%¥ú6U™ pÈä5f0ÜÂ-ï ¢N/ׯ>†jééK7ZÐãŠ4r®6ðÈsÈh©*¼ã!±ã¡C&ï*ºlov‡$Ÿé›Ò ùX%¶Ç O3r þ×ö"-®Pe­S =Ü%Xë¶w+4cuÂt8? J¿äägO€gkzIa÷…cÞ>ÄK|Øu ²C¼”F<À7yœQ[™2úÞ™ãrèïRTz{*ý׃¯G\× „¼¾óˆ G&ûæåì\Y3(“/¢ÛrŸ#¤'©Ö£é˜$tÎ{Ù‹!Ã×a-ՌѻúŸ°+[rTW‚¿Ô F¶Ïû툙O`›±H1_µ*ŒÝ'bÞò@P©T••©R«J€ë´Cß&ƒ~‡>Eš~š!äíàìU®tÒŽéVª¨»Ì÷!fq)%|¼÷èëEX*”±Sé ß £ï;/ÄÉŒ'DÅ@(6¨¥{¹(™ <D§ñD,x·ÎS‰¯ §Ýà ‰.4emÉRø;£y#j«€‹ÚÝ—%g9BF¾{Uä¾{¥~M½Öz} dŒž¼aÞ*ä0­ãÈv„¼ùN“+«œoå°v0eà¶ö÷ç¯)±˜L€¯›LÕ޽㿓\¬¸MÌK¬¸€y¹âZXqQŒåÝO¾ øN$!òÂw‚ÃLHµž}'úaà#ËZ„|ç;Q¾ùÉwB ä[ß ¾ùÉw‚#ä'ß |÷w¾Ëá;áŸ|'NOþ ÔlûÊó|.µèЇá[ضP܆4_'‹ö­øóÇ“žM¨-Ôþ!kaÑq8üû?±Ð˸œõ‚ˆCê—$ìflÔAôv¸Ì2ëÆqÇw×/Iüüï+Ç8d;ͨ:ä¡ X€öÃÒ{Zí´ôȳyõ½Sj>/|ÔlM„ŒZ§ëko²ØD¾?‡î¡¿Cê ¾i†¹œ=ò~j·85ÕJÛ,MÙ#d°ÉU/EuE¡Kºyº»/s¨h2Ãvydgç\«˜(Ó!QJ ó³E‘ÖÁÝÈâÔèg7^?›ÏL%àùDæ5X?{nú9Í2H@A³³ëD[“טLNdb«©à ªÛjš| < ‚qY3W™"—Ž=¡B°%R;Ö? •ÊÒB^*£ÌóLU샻G/ ¨ò³ 6-ß1Òƒ~þ×f¶°àムeMg¤=k)¹=ÇH½âþìFá²pÁWÿ V2 Ëš.¡ßæ¥MËmê’`¤I¾·¹mÓ¡è1ò"í«r°Œv31ò°äÔ!ÄêÐOS¶ÕÛ0T SÆiðS7×¥§'ÿåyÇ©ÝaÕ“jë,SçýÎ zè÷[b§Üà/?%Ëyõ¥°$Ž?%—#ã·dѶ8Fä±ÃÈ®íF1j#;É…fè´M”ª³_ñ!Aúbô,…¢nß“Çyô,ýƒäP‘öã–…Ó󵯸,‡!o—£g;ßòÌ“ñ2ù@3ƒ»ÿJ3kòSÉ®CÈøÕNM­d§–ôlÜ´e§¦mP©ß´Œáï||nÅ“øq ¨¼sÏ0‡EÈ$~ž ~•×Õt'A4!š™¿êŠº³ÜS¾“€öìöX§#B«TÛÎ1H€Ú3¦AÎê™w¹Ê¾ñ5ã÷6pä hϰ˹'ŸùV€‹IrP”_‡T7Ú¼ÖvЉÿüs¬¶œžóYÌiJáš·“¿¨yEµVtH7NÕI’#dä5¬œšo£ˆv?VÜí†=pÃï“ÖÙ(Ž_ô2XäΜÌÒ·8HÞ’Ó*¶ß§Š6|K{ISˆu·³«AÙ˜ò]—TOÈÁˆœCFàA•û‘m?³6mÒU d8÷8õ1ý6)/'ˆß!ñø²Ý3Ã/ºöP¡'ïè‰Tz3ǘT‡Ó‘«'_PØáCê/<%«“«ÂלBÓ! iº^¹Ò‘ØåÜ.zM%P/SÀ:u~.›^ÂóÄT« 4~Œi¦Â'GÈ(@:]W™÷ÃÒ~{I@6:ãAÙ_;k¯€•$rϳÇQ_¦N{Á‡£¼’„/ŸÒñÞï¿<¥ãmÞ?úM ÄäñIÍ­A¥7 é¯/לµ;ˆ¿æ UÕwëb~ÍVÎ`)!çáY½Ç˜÷©þuR`~Ø3!'½¿“¶“KÛ„D¨ÁªwC×S›íªVˆ×ÞMþ’Sh\ê"y›v¥—hHº¦Šó?Ö“Ý© Î¬Ýhºv–ýý@Ç}§Ë‚¡ÛŸ“±T@¢ ÁãlÖÐ!ÇNÔgdTß»ÓÈZè§•!¤Ë‚MÂ9y¤*”çkÞüÈLnœùôݵ^*õîif &¯u±)(& òìþ•:÷/ŽÑû· ћܱn¦É.Ì!VÓNÄÖ{)¢$ L¿4—¾Ê«•Bœ'S¾TR+S@—fë|„Â&y Z”n2ºq`Y­úèKŸý<Øni¶]ÎÖ)•BBðþu¦®•€,SšQOŒOî_?Î+«Üå>B»çþêÝË©ÈTòï{@­üùƒOÆZvXtÝ¿ß)ŸYõ[Ð3KÂä$|!÷èÅP·v'±ŽcßC ¹,²½ƒH¸ÁþŽ$©`¢âýöJLrõ…dœQŒŒ®†êÀa(¹¿Súž×)}'÷ KË _ºß_tœ½ƒËœÖê@á·?Þ¨ê S:Oà>›ú³WÖ‰=¹¿kq: k ‡'÷@¿ûB‚%xòÀ„ãòhŸÓBµT8d•!mÏ|!6c1È¢åÃôDÛÓHãµm] h­öíÒ?ùоÛd€öÔcdIÖ<—•§ú'ÉM8¿=êVkå²Ób$¼÷°ª¿%&Û~ž´Q ú>u#Ø ì(¨:•×pMrª™©­Ø‹,|æM·#dtñ‹2ý‹æ èuíßߟ?nÜR?O>i[7Ó„´k&…¯.´Ú¾¬Æ@Ý($zájLsªÆVÛ¸ÆÒŸ«1Ï¯Õ˜ì¨Æ<¿ÞWcTy>µâ¯#üM[ÑM»ZG+\3å³ÊÔ6(¯KF;:ÌGÈètM“Í5©W±KžÑå5›‹kF/'}{˜ÐemÛ ˆóÏøUžÂ6;!Ú|øˆA¬+£˜Šuç%¾æ‘'ç¾Î°.C_‹¥òÚúy;†A¨[ïjoW9]½¬™9˜'‹¦s—¶ú;EH'>“3؆‹¶ãœ ˜ RK]³q~ç¹nU@y¤í¸¥%769Ë÷_3>í2zu,i*ÛÄ’gr®9)‰réí+Z, ¨ Ýôp͸3èx<\g°¨úïäeÚ¶¼=Ýý¤z¬?åRè L–¾{rPýlbÛeÙ4ͽqHâÛ|ZéÛ}!|“-¯ª _óþîÜ¡ŽGð<É) ªÜa»gé0,›:ÇI5wš²©6c¹ò!ÕßæŸýX¶£:JB&ð¼#ŠHf&ÝàpÓ{á±òdµñ`i¡â]é½E2 ‘VEÿÝR=EH #ÃÝÕ÷9.ÅÐ#äÆ[ŠÆvKF»‘±ó/z¼’s¬§]<#‡®‡£ý-K …~ä?ÿ Ô혘GCHèG¾ÿu²c¹µróñ“|á8oÖ¦_mç¢e[çXÉŽón7YS‰‘7,*AÑ@Ÿ<–±õÙùú~ëÐÖóqÉÕƒBÈÓ_íÐ__ò–SOntÈpl¤¶B”Vó¸]N×¼ù8ty:ifBÚ&ø?[ rgC…l§mK'„$!Òß] / gä=1.í@Ù´o‚ïYvº»U$ÿ￳"yÕŽ>WtÈgèàbåSŠt*'zȧø'ÿ0ÒjË/dRd²Ky–bhèAàNH­Ü³ªËÔÿ‹¡Q`OR»ÂÑ,ë¼L7Yaè…>3³@Ä$_ï¨äz,µ­hàkŽ?«æ•œ„òš'i&BiòõAC›·Ù<0¸f‚FŒXªÙ@¶¼]ë­Þ¸æmö¿&ð&Ú±)ûÂ;k‘0úïÇå"ÓU2„|§sä¤q”Þ9“"v„ ôƲv|—A‡€ 7xílP85 ]OïX7žîðZÁ™J©¢xí‘«¯CrΗ¼EȈ×göÅÖq„ ;¼þ³ëd‘r¯r„¼ÿƒ×rSQlèG6ˆyBÈäøê½k+UÊ2vë@’œé•ö»mó|¼÷³eédYf¾©?¶‡:òõüx2/ OÙ$ß_ÉI{çOÑ$¤«š8R)m(˹Rq¾_<ŽÜð0Õq¹[*xGßgA±Ú½wu>,E¾1Y äJ±¯’ïèJñ iǼ׷Yïs>L”曀¿3jô¯âÈt†H@-½ ûKuàÁþQxÓ=í'¼<_àïÄJøÚÍØŠ§S:Yžµ;ÜœEßj[C°"&¼èÉ÷ý$TxO³Edm¦vÅ!£ÀiÇõM§žËi[Ö¾¥ÇiH¯¡„…e¬”“¿çÜÎдàrÉF¶°#ãÐ[Õö8UnW«d :/ óЫ³Q{ò„ úgV‘ÜÄäl›¦É;oï':#å¹]Äz`iM—±Lw‰· oð=¸ËôX§™´u+Ó\³*ó’¥I®Uë¹V­gy÷]ðƒ0ºuj—mã}iò"mr¥‘¹³WrÈç{%ü¡ÅOþë­~Ó ßïî7ü›¾£° O½l~U.œN¯>~§†¯6åÓUo¾%z¦jµçC’èë£NÅarOÍÒ+õ 6Þ$Ô,½Òª-!܆š¥WfP°%žz±€`%CÈèÒö¤Jç©?]óÂ,‚³µÕvùÞ,Bž®™ˆ¡†Ù ¹‘\6žÐB¢øãTÝÒAÈ x°.r~7ºÅ¼s º$àÁ.¨V uFqtÖ·-EÈØsþ­Ð£•~S¹«X6oE‚§ULÍaKäÓÒ¤›/ii†ÎàŠé>Ê”ü÷¤ YNi1ø#z|´0Oa Œ”@ß¶¶i JšeÏwXÊñ«R„·^žŒõrå¿äø¬êP[A_ªŽ½õ>Ö@y"¡j¨/Œ8sDÍ‘©`ƜĿ̤¤°Íƶs¶={S œêªä0_Oâø =©µô¤Á1H@Ͳ¡1§¾ÍÅÒ/9¤Õ!åéʰöH1zÒ¥aí½ÕZÍRŸÉ­µË™Únd£Öäáéi3sj¦§³AbdÐ+leBŸçx» --ò†õuÙÒé7 ¯ßèIðÞËÚ¯bÁÃU®®V1¥ð%„««UÜͰŠCíÊÿÜb‰“ê+·Bp÷ç9]m\B°¬šwZô$¤fý±°ö[¢m²ºKFÆ×HQw Åä! ¡¶wo;móI;8¢ÅAâ€uiú¦ÍÇ”úi_rÖÄ9kuL™kgعnß§âÿ‹) £×‰[´Ü´¸gžVAnXÿÖ´Âmcn•U¶VƒÀÈã]z²n…çBN^Ì!㓆 Õ¥³¦«õÝû'»¡Y9S鱯^5¯@?œÜn¿ÌƒÃñôD÷ÊüÆ¥¾ºf•;[eã‘䵌5Oàš÷ß4O0òƒæ ¬ŽÛýeV.T±æƒW?#·¶Ó2eÇò¼¤~ëR‡Š Õ4ÁþP³^¨ßjiÊ# :¨YÔo9J ï‘€šF›PŠÌÛRz›8®N$ñL»g»aòmâ`ŠV¶\f|N=Iœ$á~ô?°õUû¦ÈÁ¶JgÉQ üÏO¯XÞ¦½Ê–2ŒL€žoòOSUHVªãT‡Ç„‘í²”¼½ÕÑGâkÞ= ý¢içi«8 ŠF1µpz/“¨w¶«lEÈçÉR_“5…Üf¹Â;ŠÎúhš2ßjxž1²E·ë¨¶KT—"ç!#;梮Yøc‚ž¦¤’‚ÿIâ³ @cE\Ô.Óu*9ÞûŒ265‹H+c«¯ƒ±½ó Y‡ŒBsBKÕXŠbØRõ02>¨/¾!Ûçr[³ª—ð”’7#z.8¡ )îr„l IB>PŒR@Á6 Å]ÑÎé ûQrÿèx2KˆÞÉýUÉ„ºI|mäÜ`d:V92¤¬y׉ ÊfÉÑ Ñ´ŸCEPŸÎÚ¾2$A¤¸?V%ØjÄ©L@êÍP"dH~n\¸*˜èÚÎÏ“€>wè3ÛhÓmÞW^%ƒê‘ÿ„#i›ÂÀTÅ›~)òøíEmåØÖÔ+[:¾Íy#XCy2«C¼Î÷ö£€¼§UÖ¤6—«ÙO’òþiôZaˆ€è³ÒxsBF¡"zí2ÿ¡Vw`Þ Õ!ƒÞ¢±ö®SÏk±ÆòöV¶+[„LÞéœË£ÈD‚Ñ™+ X Œ:äý½Þ œHü‹Þ ä´;p9#›ù‹¦*Š_3Æ®I¦u+U£º!¦ìj»né¦'=<ò†Ê{n,œ–¬ç¹ñц$g? W;‘²\‡}à^u„ò¢%R¹“i­Â’ºý€Q¨ê›’cËÕ¹x¨2ö´Ô¾d<]Øe9O÷»¼N[¶6|]Ÿ „ªŒâÔÙ NR BFGaÕé¥\é®Î=^³Ô!ãðY“þE*ܔޥÂ!o‡ç]m…z5]6Õ¿îþ8Q…K7äB«UEÙ†\HHq´f‹ÎKÅä"_rI7„Œƒ^m{Cr]ËfÕäÏqÅÑæÉ%-í„æVöen†á2zU“›×bí ~’'šÈ6Ž<µµäs!‚æ)9¦æõ RQÃ\j$%F¨'ªY2¹qÜÓdò™†6 ©˜Wº0fBîß¿x!A¤½G§wTÙc¹ÖAê½c~PÜãêµ!9Õ Ð&IHqü#\ݦöÊ‚ñÎu!ÅÑ!m;ØN÷¿ §ÅÚÍnÏ|–2´°î¡ï?G÷ŠýT]N(÷ŠÉ‡¿ÙaUê§žûí³²?žgò©‘2Á“'¿è&'ʨmš«ÄŸ‹Ô«€Šy$5UMy|K÷ÍÏ‹ÿša1ÆäuiÓŒØè‚º#–gYáýI  x ê‘=ø¾9d ­ZZ¥ µkoyÕr¾à»ßÊS]Vî¼9H&ƒZÐýÛEá5K;^-4Ë·Kí0:õ:*éÀúÆÊÈý‰ÍãóªöÙ…6ZŸÁx™<^Æ ¬ €¦¶.£?ãê|Fø£Ö4*m Þ3?^äñ»ó&M¾æíÝys†Ñ*‡|O÷òø~Cgš?wËñÛqý3µt/£HY•,;¨QŸ´+Ï4iÖQ¸f¼£Ð%uS»Ñ2ƒlíqûìkpd•Héñ' ^•6žKhÛÔÖ“&¤îty5«ÚŠâôù¨Iåñ‹N£™p_ØÚLƒß§ºwá“›B¨ ¯rç‘É´ÁõSÚT´éêrZB"5cjX2ÆÏ‚±£"h-^í”0bCB­E]Õ,,ƒªpI·jªÏ¯³ÇPå£MS‹QŸ2 jkn0Á81­èP‘ç"U8æªpY‡·FeY¨šFÕò¬…šÿA—5ujì•Ü©¼.×èÇ$¤Ë# &*¦Ó\§ÔOƒ““Òc:½êî åV5î·¥åõ{º®c±T+BÆa=ÙÆùa¯Ò®ê§ßýö–*ÜûQJPp¯©Âk‡Ñ•TK…ìVç ítkÝÐl@ÈÐõ¸ò.?2Í[u˜ë<2t/Ö¾£¦I‡vWÙš@HýÛvý޵̺YGÓ–NC9÷GÈÄ 5A=+œì‡BæÓD«¥FHrè±{7·,K³FŸ¶ñ5ŸˆÚkò~“ÅTŠ,CÈÇ•ÆWYÐámJžÉ/4 ˆuOò MㄌÞWJ¡ú¼¿Ñ9§|«…öhóÙʼn´™C·…NB"Çv„ç¹vaBrm²Ê…U¬‚Œúù@ÎV;½6Ök;¶tøòæéNT9(O9ïX”´çÉÄöÕE;ñ®dÛQ]Yþ’·m ÖüÖZï|‚è$D/Úu¾þ©M)e³O j ¨IefDfªê"wä¢õÝëe.É$/‰Ÿ=…È¿tú¢âÓTȺ@È Ô!ZS{œ8Ç–Â[ÂDcbÛ´÷ÄÙË÷§‰wèúd[µòež õ³W ªG´e­ W^ÛĹΥ·[ä¹\ÂZ·L#%½SeLCÕPÛLNm«°\Eú¥s4½ô†óÞ¤t\¼éºõ,¹ó’KoXŒQN!ùê½ÒÎ{›êª¦™ ¬( BŒ|\VF–÷ËJ¨nË:ÝŽÞ¿·eÅHˆ½u‹Š‰~eLWˆölV‡|âˆz9¸\ÁäJøi YúçFÓÌúU)M³³¬ú!×]n¾§·'jþìú8„L°Çºn®,Hµï#Ù˜C&.i¦í|£›Œ)ÛÍy`¥©ÉUºóæF×¹–ÁuǤ^‰ÔjBê+*-PùSiQb@Èç÷[¢Ýo‡#¿Ô"W‹„òú’_29¶±NþkFëgEÕ¢¦·¹8rˆJÙ¯2Rï^*‘ZX×wAÇáÜXÉNR:cVd[óa‚JhzË~õX×’ ›Ê‘'h™¬™¢®ÌÍ„÷€bc׺™²RìËÆB>ÏÐÚêœËQDÛº8B>Cm£©»sRNçÞú'ò9'úa^¨É3pÔM#uSÓ2 ó™M.çŸþ|qE ¤ÿì??±ßŸiôROÔ±£Ýg ˆNj§6¨2¤üî4a‘ÏX!Y· ï»N`8däk æJXàœ÷¢=Ýn˜M ÿ:77§b½«v°s@È/΀L‰p~:Ïú4T"ýŠô¿3Á´ÇÊtªoÄåpâÜ#?ò´T÷Vª./Þo´tŠô'žqµUÆ–3ŽíEÑîBÞC?t÷>iÞæòË™}¨›ÓDב•¬8BÞ?‘몄 B†nŽÝ¤öÚzq•;‹|†¾¦.#‘]öÅ‘,2 Ý™©m9§œ/M'0ò…Kݳ·Ê¼‡ãß™ÂXªjçÊJyä¡rsFÈì’¹ÛXÁ~¼÷Hy˜¸rd,ß%xÂoþ´Õ®7žrZõ+‹>’—&¬*›ç§„ikisÐ@uÄà*ÃkJUýÌA߸ñ#|Q9_äb‚‘÷¯H.êäúýÓ°7B¶JýzOðòÏniÉ\"d”ü§Ïå57g•¸`á Èf)'6 d ‡Sï‹Ãª^©?9BfaƒuI­üðò«"äûÛ°ßJ¹}ˆÖ÷[<‘aØojØï0ìï·Ï7oõ4è@I 2ïiتO¥¢ÒøšÏ‹ 2(X[dòmØozØo!__Çò0„cÙ Ó‹¡\ÀÚ±ÈÌ+VQkM8´GÛÉã±MµÈw()l_ç²Òq§Ã‚ŸÈNº/ë]°Š¡ŽÞÏõ.Xï?‘ÐÿðJ¶.üçüùðr¾RþˆÏ¯>×#“À¿œšzy7or4y?N‹|}ûœ•þœAÈôëçÌô9}‡Êו ú‰-òv3›3çÐÖ´•Ëcޝi?’ -ñ±Þìr¾ï Œ‘ûÇæÌÆéÐPùù„ôœBoÇ$ƒ‹fáeÙ!$žI0–å?û‡¿Ç3‰ÁLšøÐ—Ó‚ z¡0;‡V®a!_he2t1¶­Tõôbd(ºÁüÈÛYÎ æÇ#RžcÖ¢„-rÙ‡`~<€zA™-¤ÌÓÖ­ê(‰‘_èså&³*ç v“"ñã?ÿØC§]oÔ"!=gIL©m›äˆ_I‡XÝÕ&¿•E°*âÇÞÚË>¶rÏ÷}ÇÈ[{i6Î<“QÿCÈWÈÒrµ'Ô™~³5“#dQÂn™… Å5\³ES΋›PÝ,vò©dˆ1my0–ñcXBu0 —ÐU8'†þàâºi,X×½{ŸéçîÅü˜iåQÃi›¶c †>ܑʦL< žëc”€l©9(— ÄøM|1GsIk–k=k—<‚¾>¡ƒ‚Ê3zýÖÔY•…m¦lÐZ÷…Kó9höYVLÕ·YœsÕ„ÅQ×cŒ„ê‡F6Ž00yò‘æä-ü¤™ˆ@ÈÀeKµò±%¶×˰ø$Aƒ?žPUUÁ:þú^Ü„ªô„:r„ôL“ÛV=³óVÑ]ø|O$M=Å=òy5õÔpAÈä넚P/OÜŠ‡>Û…Xê!Ó°7ÍððT ±ï£ðÛ îj)œzi#‡UþçÔ€b+:£+s¾/»¿{†ýj£Q(jIÊ<§‚Ö{ä>­Øû¶«ºéèXïc:‡tü5Y³+«æ¬½§Ê!DV´yh¹8W+9á}¾#?m—FaB+(‰ü@È{€d6rD†à…?ÿÝß_ò冂¨òåõàrÆiÀ‰ òåæš*_œ‹Äî+zU ©Zù’à¤ø¸E9¹ÚÞýlH'Ýr3òð¬hén¾ÑyRîøš‰Ë¬W•“•/}ž‹a( „|HÈ!_6c½,øÙ¡J£Qõ×®¤FvÀøô«Í¡Þ§Þ¸4ç`Ú§û »Ìãý•œ¬Æúr™ ìÇåk'ìäXSé¥.xå¡xUú¼ì›á[û}óùˆ2—”9V;ëv—Û¡C>1‹Öy•™Ù§Þ!,(¨ý:€=3ˆÝÉ´¤‘ paÓŠRQ¹‚GwÊÿÕÂ6o:­mO÷z,„DÖà¡UÒgïúÈ,Ò²‘þXOj(=2ñu’Òi!4-QL˜q1ÓE‹–iYüºÚÊ|® N1]Tp«öC-sµ’‰WMˆCÕÂdD&1,K9:‡‹4OôÏñŸ¦6(Zºƒû´E&ášl:B:Êå_á'zu’Ê(Ë­ÝÜÐqÜý7ÉŸýÿ”nmu´¢I.c0Èm?AòÇùÚY›‰\ª†ûˆA¾¿¹}ª:ÞÁ ’öÌ.Ý>RÄÈû78#ê¼Á7zÇìCê¼_F.ûP äýk\WµJSÚ͸HÔYÇ`VRšæußu[÷O¤:$ÖÍòñ_Ц›1S÷ëÝš«Í{n2 Ý}M*T½¥¶ëÎɽ%ÏFúôÖŽX°¿{6Ò‡·0vÄJ6æ1Lõ: Ü;#¥#'à1¨f=¯¼èdì€1Aw­²uçl,„üÂcàÁ"ŸWžTòøØ/N˓ùƒœÍä:¤Ò÷ÔD¬ý³äp”NžQ=¤dƒ„ç£äyYW=l„-!WHFÄ‚Oà!j¤Èz2QX’'ª?8~•n|ž•¡!ÄóÉ¥BUÙd¯&*HWôgƒ‘©[狼2“ƒm|F9õ£kf—¾a¤…o„9ÀÌMÕ_ÀÆv9òöЙÃá:n5?òÎ2É•[<ë³EŽãò@Èûµ»¯ÿF/4;+ÅdFJ±Õ‚æË‚ïîEàJ»5³ ¨…˜Eå*Òˆ õ…ݵù¹™}xN6úØ#÷Ín&MïÇü®´0B~_i¿Òl¤Ø»µÓÞ­Pá÷Ì¡ H×Sc‘woâNÃIzTêN¯¨P,ÞAFÔE{ö…Kl$ÃêL3¨±4•lroþuÿÂîr<ï“§cw¥ F0x†1pw"Á`ÕµZ× ì†!wÇT¤©ó¨XGEOÜZòlþ~îG[Ùy¿Š¨ù Ý7¯C“ S;WwL[ß¹U1dä8NŒ²9f²N¬GÈÏ^5–8ï:Rõ+B>‚òsÌ¡|:&²:C€Ô3rœœve,åÈÒþ½|d¥ùz¥Óî¾c!Ãþ±œòuÉB«àŒ°|¾ñÀf_l|¥WÈŠvxë€ô•bám5ßÍ=Ø6‹nrÝ‹é ›`ä¥ë@Ñܘq¨6xöwt†­¬°W:%MC½™/qÝìzÓÒôç÷¸.FÞcþ_ãTdü:2]°G¡-8ÎsAH/ÚUX[ÐfærÂÑüŠ-òñÕ¬£ª<‡ÌIzG1XdÖ1Îñl,2 ú_lRs»&?Fà-¥ÀÈQN’ÿ© ³'Z2mU= BÞ¤‚Ú–4gÿ|8wJ\ZÂJ2òB äNÝ«9¥c®[dôéØŽ^“M.ò5¬ŸéÃw×zÁ`-SMØÉ襃LC¤5î¢Dn³"/ð[ÊÂ.!+?'‘Ó$Æ#B¾dc]Ç9éæ~¨Zƒ{ó7h"Ø!h· ¾Ã4¶ÐŸoнïD^ç5†ɽÆö§±¥”hÁa‹OŸ¿ZŸ¾ˆ˜†F*Ãjó~®dÀAKš|,¡¦[%êMÎ$ðÒQk˜N¬v¬œ«aÜý…%¦ °œ´Î«<Ÿ¹M!M/t$£#¹ù7êÑAÈÕÇ®‚UŽ^‡¸tDIy>`ËA+þÓ,V‹£ ǹ\FF'KsM«ÂÆDÉÄq0B“Â>úL÷å,r§8™¦±@K $³ˆ€t›f‘Bùé’{Ù-&¯cÒí!ANåd˜œÇ2Xvï3ûåЇ|®Òì?±ü)»ÇÿTwÜ©¤ÙFyÁ7¸æ#VÃ5Ú^l]š|¬å.ë&RöŒ=”ìÇT›ÂМ ÁÈ»WúתúîÇ:б‡D\@Ru9K]ÒÄ©YIá‚\Yš%OdH᪅P>{ Ç™€fä<¾=Ý'*7„­àþÍ¿‘×#7JØ´Õ­K!áØ¨‚:²ó¤õn iGÿUPC+”k—ãG™O…EÈVÂ>‘/'iW¸>u¦ÜÚ±[7üìé¤r-ûDš£Ü¡Âo§7?ô2Ð:±¸&¤XY{a´tœ,ËÁ:ؼ²4öã²¥™UlMCέ¯òÐ ©¥Óƒ¯gÑ'B>ÁR[7u룇\gÛQ=Â"“Ëäó Éç,‹œ(¢ñY΀|ÿ6>Ûp|¾¿¤tøqÒ½˜O8r´-*;þöÐ6¼X ¸l¥qÊÊ%[ú—sƒ¶Çäd-ROœrå6P5d–gŠÂÚ÷zóªqÕ´yvòÛlm{G@±ÂÊßê‰Båïôý¸PþVÈPù;}?.”¿»Hù;}?.”¿»Hù;}?ââ²k»ZäÖ±Ë Ñù÷ï.šóìßRò«œ‰œœ!½XšžºqÞÍò¢ùEÎd r/äLÒ@¿ÿÑÚ/?ä¼Ô}»ù±ôÂÅ&s8Õzó­œo|ÊÅÓò<å1zÆ×|\\S!ݺôN¯ï~žex÷ôƒHAá‰x×–£@È@º©´?êš-oª_óéÛÔöÉŸg?!vþß‘l•Wh ¥r®ÊnžÊjúŽf+烡Z†E{´Nn'}63§«±‰½‘aç5…T½Å {‡¥m#tTÕæ‰š’´b‡×û5?¨²¾i½'½ü•…¿ûG:èÍY·y—€º„ŸH"å5Û=ºæ3싳óˆõ›[ôö¾ŠÀÿþ"W“‘ÕÙ;úcº8¢¤=rJäÑ7Îw< èPéÆÒÈxWôn,e!êß?îš¹oe„|^Å!àwþ ƒ¹vûtgNx抡"9’¤ššî0•!ùâÔâ…²ºôrAN¸frù/|a] Èr #ÿqØ‹:a³[,6é4|”ÕVâgú«ÓÔLŒ¼ršâsû{†H9Ú? ±Q¶ .ZËnYDð\ßukÃŽîþ¾ ÁéÔâJE= äý’àÉÒìP!õ­ :õ½ÇŽ×T0]3 ¤†jª”°“ÊBªi7*Í7â-¦zÛ\S\ösûâ2g9Š8 ¾æÏ hp*Œ-ÈåZäóêÍ@*# ‰>. Iè`wÈ#äýꬽœt@Hß ê¶ŽFmØC³‚oAöƒÓVi­OÕ,\¹”]ösÿ(OµˆuéÛ¼h÷ž(jÐ":šJ+ÏïJnq»co"“qt¨cÕï3ùMp‘Ì×e}G `èD[T  €ö­ÌÓwtÄRTµ¥ÏÛ<ïÃPç;BBl#—Ê´m®ý¼-¹ 0‹°lnB_%«V‘>ßzùôH£E›³<Ë|¯‹bDÈ$”ä4×\»~ãmýwOq‚Ëœ$8_ò©,Ä8bdê©É«McÒ1N}q×ìd‘™_½+ˆ.ÈI–q<á}fÄ©Ú:ºpÞʈ¨/DJˆ5Ó«¢ YíZ³€ºô/d$,2Ÿ xRP— ŸŒÅ9;d SwÀÝ7ûÐO÷#ä2Ô9ÎFAJp¼³²€AbÓé–ê-¯ÙÍͶÁ0HðÎ¥<¥Ç±ÿ,$<˜2_m .r¥‹Vä=\óþ›H³Œ+9\óqí§¢vÃ^À5!X]°vO4°º-ÊaqÂfÙ=‰Ü’+«÷¨ÊgT¾SwîÈâVUë1 oè"òœÂÝÓߑԉbZäýyÐ!C‘+Ì#×ÅA‹ô')£KNuÁš¶cM ŒL®#-„|]!Zàß™†>lÌúmNM¡Œ¿'„Ìù"@ª¶EZöB¾(©ÊRÖaŒ­rU”'0üæoŸ[wÉ_ø¡ÙUòwPR Éßìž]$¹Kþbäã²î„­ë«M‚bíË¢^gL”}¨²Ç - ?Zœ)Õ)w.ùPdDÈ{Ø!mÛ VÖËOaã|Üc3qoâ)CôªpvYدùMk¨å&èÂüjŸÊÊSöˆm‘ Ån‘+*9¹‰ôxÅF:³g´†(ß!m”“®ËÍ”°Œz’ÜhB†Ú¡¶ëºkO¥Á;ºÞµì‘E=Ể­/SÁ‹=¸f†{”¡kpUd½c9Fz-­…¥}5Ú­¥MŽÏ ya NÊ7–vì¬z„ 4=\o(rR;èc[äËœJgóÊV«z9|£7Ö/ »„É¥›‰­c.%‘=÷Ô`'Œä'¶æŒCj¯-f‘÷0Åc–†UyÍ‹ruz¤Y¨aþ×"õ×Üäøät­6‹¼V6ƒj}ö||U635x¥l¶`$ÒMÕù:¥›ÚŽE UÆ,R;tSW±Ë‘»”®E>/ÔÒ†N0É•ª°W«°Èוª°|tŽé×îÛAÛ Á³‡óý¯©ëQwŠ©j•:"¼ù$¢–9QN¶TGÛËoéõAB3=72PVõ( eÏ×GjÏ'ˆ<ÇÌë !Ëó…”OeHn”!a] ºZÿ˜7L˜öOQ‘/èÂTÝÌiÊg YœâÄÈ»gWA÷C›·ôÌOXC|flÒ-cJeÒ ¡@Ô…©;:A/c0yBÙG8ö$·-WT…®}rÖ@Yr‹RUiH’ªî-q,Re7©gæç…à,TeÿŠ„ôA‚ß ñ|ôœ·®+“»nf¥]¿í5“3߉謢m"Œ¼[ö¾™ùüD2‹¬–¦é n–$ÿ,Âï|ýW°x äoÁ"GÈë`±ù[°ˆçoÁâ‚¿‹!¯ƒÅ ‚Åäõk°8ú`Ñ ¿‹ 훿ÂÔ¹xÒ£=+ eIú«S^ Ò¥YäÈÁ @W¬…ârœÏ’ gõQªvþ¾”Žy™…mƒ^Žÿÿ »²$Iq%x¥*rƒÏ9@›Í;‚Ø$Änsú§5¤ “ì6«?o¶ÔŠðpW—Ôtѱ$Ý2!ä-äÈ+wwMAç†)wÊgIP}ˆWw¯iÉ»mAÈà†[ÂIŽND8 „ª4ü«ß]ëmÝrŸTì= ßý…¶ÓÈXV©EÈ¿™FBÔ·ãK¦æ® ™Å†ò8TX;÷å°"dri5ÂôçIÞ«ð’L /U"¤ôwâLX^8õ95媊ojØ5ŒdJ?èË•ó4ï{è±K·Ë¦ë*Ÿj9V ”:Ãd‡H7¬r¡ó‚&ù£»T”Þ8Ù@öÝÓò‚Ó¢g69MwbÌËË:ä+"–:RA©&Û¤¶mŽïn Gžœn²VùTȲءZîÙ;5ˆOœšSOŒJŸÉ‰Žç-ƒõsRš“¦óÈw™f»{”íRÊŽ|GÈ$HqÅO_SljÊ!ä->È1@΃Ú$BÿÐÒ·fÊBªM“„ dD óy£a:Bw!„ŒIaîÈ7ì#!rã°|?o¨™¯°M3:W¤!|óÕ‡LƒœŸ¡i9¿íPk Ý|›šCfï•®·X]I€ïy¿¨$WI€u)Pe?UÚwí3gÄÅÕÓÊ Þ{hš0Ýeìt‹óqбI^Ã\6”%©åÚ!äéî¾ùŒô«”0ߟ'*wÝØ˜VÝBªcAÈèî6X3!`Y¶$ºûÕWMMÌætçÍÇÒ3xwÜ:lEN³» -+RadØ1ÌMµ.®ÂßrBȸ†ã‡3kÔ΂Úgzªp–.Ÿ­Yxbªs8ò=³K¬n³˜BfQeÿ}Cîgdre’ÄCÓ˜T‹ª=ºÖÄ™Úág„Œƒ°Æçò›bȧBêWrj櫨}÷NôÓPÔbÆÈÀвÖM6d‘*®: ¬üLªµÆL4{W¯yÔWbǃÖ3#B†¡ðíòË\ª ŒLAÈç'ÎK8/iÄ¿à¼t !Oœý eS5TmrPyÝNÌ «XKÕ5gº‘¶§ BÚêÄÿÔ¾i:7l£í¢g™ñÝÐ@D$!èF†éë;ë„„ê’ãgóÎ4ÈñÆØDGÎB;z`ä=4dx¾¤8ÄÖ®:{ƒˆ'kj8ê­æj£Ó<ÙôõønÖä×ó›=ÌA›ðî¸eçÝÊ"Õ×¥·N~y;FÞ/­\ØŒïþ¸8–Ë©„´&bÔ~òÈ¿QúÝ#›C’åõ–&v¢ÆjE§z˜ÅÙ›yg,jšäÒˆÓzn’›P“\šþœlBpC Èú¦êÉÖì\rìõ°Am)BZv¶>#èY\ÙQÇtQ?uaÿcD<õP[{¾‘ Rˆ„9äý³ßL7¥ÄHd_Äœ…8Í SñZ…ÏÏ9ÒAl^ü5»?ÎBì¦ÿ]· ©7šŠÉ‹g;äÉEÆ;ý ýÂàŒp (Ý<§Û iÞ/͸VyMÝ‚™ÈHç2÷Çû»ÃW’›TB>#©?à/1µo7ý wÇZ#¹iÃÖ7×]b­¼µìþÁÒ‰„ 07__Uˆ¢½øž~í¡œÊpÍôo=”©¿üŸÿþüõa3mP"%ãƒG v„ÈÿñsaÍOÑYLüýl‘É;•YEA’‹,·³@ç=#Õo¤PÁÉ"YÓb{!sˆ¿oDêóÝïWÈ·»_ ‹B ægÇãñ7U'Žßb0Œ¼]~CLÓŽo:`¥Ž‡uþ%ÆãîNxÕ¬0ãé‡î@æËºq„üØý¯Ý‡YÄh5uبû_!‹¾í\xà,b´úf |Ë–´jº÷ {þM·âϘÕiO»>ªÔ=´Y&¸æí4’¡ŽP¨HMkù_óy?)™4òDFíuâ͹³H°Ó¾‘+í6ët¨Ø"Ÿ¼~Iö¼Ÿ…™M'ŠiQS¼ X?Ÿa·Ìê×ÖiåöQ8Ë<Ï~ê—VñÊ 8¬ ϰ¿ûʈ«¶ÌLý¯­%B¾@ˆ½2¶IÆ‹I’f_w_‹Ìž'Õït©'éDÝôBFÕ–Ê{sÌe¿µ3)%BÞâÆ{Žk BEAϯsÈ{°M5odø;]›ð¼J‡´_éfsMã¦õ ÊfÀÈÀd®|’škÙÖVù‚^yhº+'"xAso+æé¥ nÈGüO¥ÿK OøÖ"µrÛZØ Ÿø7Ý ‡´VÚçëÄ5B•¦Hˆ=‹˜)Ú×ZH¸EÈóºä´¯Näcþ«ž–QøqÈ×Ï[6Û²öØÂWW;ËÊ3„ÕÙd"íÒ ÜìÒ¶I)°àÕ¢¦Ç´cäóR@ºƒ89bŠ^+ -x9ªÓ!|ÏÛ[÷¿¶?ÄHÖɳâ³W,šn{F,Ϫܫro[+Ãëtê˜v™WBæq„¨2f6Zžª³>èÔÑtT”!£ìÙÞMUHíÃ<Ÿ|÷{PS(«Æ©6²zéXÍw„|„Üu oó|ÎÕðôkÈë,¢ìey»ñí`Õ‘‘ ·.bPË‘˜x5u턟×9gâ!–†m¡ðœÏ·»37ãÔ ^—®k©’ÐÚé‚ÌÃ0OavnP;ÑdâlDÏÞAx‘>ÞÓpÞñ{4Žß~iHŸïé-gd]²™j+k„¼°§Ö¦Óž™Er²gÓiìã¥ØuâÚo¼Îì) XÑ3‡ìô„«0ˆ,Æ$Áîœj÷Õ¡jDö^±6h(‹…-%›@ÈH.^+æ{–CYsµÁÖ-BÞÐjã5<:-÷÷ɲÛ #Ûht,Z£.&Rl±€äEDe>Ñ’|‹F^µX¨ý8üFÓºtÖn*^LüýäÊw@",{›l”óé©Ù’ºßH›ôj^:Ì÷,»H›VbßÝ÷ûUÿ3óȆVÆçE·W_0öÈ öaç‘úÌUÖŽy‹iñÖÛˆÍM®B Íµ ùû&®Nx`S TMÍÖ#,®^z õ•T Üu=GÈàÚES­>¥¢’½—y‹Æ<µÆ·K{tm³q‚‘¨€äÖºYý@ùÒçðœ8e–ÛXUb‡UÒ]T®¸ë‘ ö*µŽ®Õ·=Ÿ8Bñ@KFÓâÕÕJÚºœ—ƒGÞc¤u„9ª¾çÛà×:4Á÷þ<¨ñ¨íwž‹ßÝQvÝòW9-ÆF/Šl—y¹"ä+vý¸L§IŰÃÝORùÐZ£Ç±±M™ÄúOÌæ5ç’­:ËÀH~„B‚+-Wf¡W‡™ñè6Ri¾¼:ÿ/×1¿ÉÐë¢TQlêBÞâã3R¹”ãR‘–¶yÇ­ V5gÙÅ& ïþ’ÁüÏ’³ÿiOß[„LüX"FðÂDª„óâ˜7&hUa¦Y3O{Ó©¡Ì „ #‹lU)§sKéÉ{Ëêª7jú¾ÞæcdäË\yçD½ÔÓb3.=wk7ãXÙH1óÉEþ ±Žÿi½že%²wùˆîîFÈØõU»Sï^­YpØ1_ÉËuÖÃ&å¶õ†6aç=@ͻˢÙQø"ÊïO,{ë ðŽ~TeÕN‹k'SÈßsbÑËqÏ‹Î&oáš¿g4ïTTúä•í™ËÍMµÄÛØ2#$JI¸6lmV4åÞÚ#ã”De ðc×Tõ\û˜Ö#ïQêÄù%±z!;ãE ot;E3ƒm7’‰01"dìˆíµÙZÙE»ÁºQÃÏåU©5¥Œäßûe!VêR¨ _þ~áÛȱo£B>.|9ömôÈ/¾á9ómÄ×üæÛˆ‘ß|9B~ómÄÏùÉ·Q ßFL¯­…Â5ŸˆÄC hj¢JM“…ç|}·­ñ­J ™"IÕÜetUì½ö¦°ä_Ú›}!ö÷'"RT‚ô¤R…üEtŸ¼´Á¯úò¢gœ—ùà¿R’|•aŸgÉ2¹lî~ûB½•B­ËpÍ+ó)îi~,% Ú÷´!“+¥ÒÝÓ><҉уgù¶Ök9·šƒé‘Ï“øuþO*ò,×™4žó$f[º¼Žü§bš¦­EÈ$Kªm¶&åóib0–’^{ Ö¹4ä`pÍí±t‹¦Å÷ô»LLeþ(•£.RT½Êç™ ó)G!Zöi«§®‰  x#ÉK&û¾[àš¼öœÆ¡ìÑ/F&ˆHí\ùˆÔ1(|¥[‚mªÞÄ–;¸f<’÷ÿ¹öfç×É‹h¥ê­M(›ã¦Ù¹Š­\B·=GÈ’Ô¥ç'1.‹ ëZxÎÇÛÊ ²€#áÿ »ŽeIa$øK¯»iwÜûNÄÛO +"æëW¶PÑfbÌ)©*eeäíEú Öe‘=#cùÑå»”C×Bduy|oPo¨¢® 'x>´«m]Øç‹=Y¨¶æsnÆ“BÈ”:VÆc¶®%}YÂwO©¢n,ÕeT°³2UK„á"2%ú»Åݵ„Œ#Ã×DÇWpÍ‘¬Ýo)¡Š’ùÌÔ Û¢ñ5¯©¬=Ô‚Z2ö£Ä×¼%$]{»ãÀ…ÖBr…‘÷dµiêPgèL*!ô‰]Ô¬ŠÒ}ßi„´õºßÿjg ZéÌæf¶C+'™X5ýï×U|ºÛ›ÈF2¡`U<èÎúVȧ$¯Æ‘Ã[Jü¸ß´C$»a–Öü_Û!6±MvF awõó!·A@¬˜_f‡‰¬¶Ž1©Bº»ÿÏIáTákšÐ†pB$ëòò±µ›Àº”jÿþ Â.C™Ì›T­¢mœÅ)ýôð+%k¾>8"ÏŸdÈÔó߿ €NDÚŠ|…g1´À:Ÿí{ܯ%o•àE>[݈H>ˆÈìÕŘccƒ|üËŸGÈsÒ*UoÛ†dŒ yØ7±ƒ³Y?!—IÕd_UíY¬!;Uô=±r‚Ùq=}&VÚ¼cƒü=Õˆõâ>AòŒ)9ZÊK×¶©ª¶ Yn˜îç¦'µM!ë¾ûõòî¤ÉÑSL~D‡HøŽÈ :Åð÷.Æ-7Cj•פÉDýÝK+€E#òš×X0Á¬æ­îH“k„¼%_TË”¤®Wª!ëI(­>Óg‘§PXêX^+øßwm0T5ÈÛ«\óDj©§¶ì¦!‘‘Dh²`ƒ6W%0’¯Çø³bþ̴Г”Ül°q7¼ZA|ÖábÚ­6¹LžK„LZAb%Ê {m²¸!GHd§ÕÔÑN‹K‘CxT5 £H0Öö„Ts¾"äGÞÒt®ôª*…ï~K8½xЉëˆ=2- „LˆU01c©«:UM3B> QÊž×ú6lAZ-ÔÒlùLäÉœ±½«‡ˆÎ¬aÂoþºêËØé¥Ýû åT¥õuGs‡ 8nÃy~eØñyãT“}Û¾¥ÝÿžÃÉr„¹yeñ…¦&ôý›]9&NÛùź»Тý¼']·x¯vl·®e\èXt™òd«0‘«†÷Z­0DUQ_âqÛ‘c„‰•1B7‰¡‡òn3ö¦¼Öš“i„¼‚ª“[o\Ú3ÈEóŽAèË>p¹ã N‘3h©:E䆻n6aâ…†ÌûÝo(‰woàî*ƒR¤ï0.cb\í ¤g·Ç¡ÛÒ=²·íÐð–=è¾ê»ÄÌë”-L·Í _Vt„6ãÔ!dâ \9D[”j(;†Yâ“êó‹ä‚‚þSD^_U RwlPP¨õÈ[‚ô'|îîÖa=oòz0E$ô:îíÑùðÝÿ.¬ $".È4U¥RùŒÔK ªB»²AvE—†„ªÝ|ߘ6²i)‰DÈó'¥½žC2s?ýKÚ®yFåwÌV…c¶¦àÛ,㌻_š(µ§;¤P&£a™háTaQ¶Ê‚®eÓ"äNÍ)ãXš–©©M"YÅytÏu‹Ëã|™x²*¾*—!ωGWض·Ž´Ãª¤‘‰º¤+úWQ£«m›­¥-¡ !³4Œç–mO[Ö"¤;øóû›„AŒÌ3¥˜12eä!M=@ñ÷žíl8ϵo<«t]›nYô)ŠG>Ó³;.k²l¶e;nÆ÷ä˜í?ÿIäD£ì€êçmP~M}å}øJ¬Ú–z¨†žèy䊭z¦ÕýëRB.ôÝæÁÝ,6KKE¿t BÂÑx6a‚°­C¹”5BúÖ–5CÝÆì›ljf. $H÷}õã3œBÏ’´2¯IŸ}§6FÊè!·åfÐ1²–yNºÿC#Ÿ¶:7«Ò$òƒ&ôÀæøÇ wt4Ú:ÚžèqŒ‚êpn×ä8Ot¥^õ¿N321–Zš¤§×øærá{÷SˆRÊàÛ úÇQ(—&/ „ü¢K7)„¼ Þ§«IÑïÅ_¤ÖéwØà"¬¦ÆP~ÝÉ…^™Ø‘%ýgUá„€5$õªg³¯Kû§9³„ØâäÇýp —:ª6[ÁU¤h$ĵwŠdÁc¼”è«b¡@Ÿ×ììÈ£…ÇÜ“ÖþÍØ!djhU_“xTÌ,Ÿ=B¦v+hïË3ÉEGbDi/$r¾™­,Êiz±bäý])Š;Ó>>Ÿ_JQüy~õ4åØÓôôs Øíž¦{šFäùUuŒ{Õ1±_æû»¨YÂ!ß vǨ%SlBÁXÚ vŠªP¸y^>\“‹ªÏ ²JaŠ˜to]÷'Êg¹UçõGM¥jµmã,B¦G8¡Íu¡¥ÙŽD¯ð5/ 9æÜ6ˆU2;Ü=b:-ƒôA+—˪šñݯI&šÐjRŒDUшÜ;MíŒóý£ÌæÏÍe÷Tý4 Cÿ¨A2]6FîÅJ8ùþ˜”ó¢2ÑÜ-‚N€ó¢iHÓ®™(„ZP³T²ãs½h"òŠn;$[V!ä-é4­=‰Ùî@®9@õÓ÷àþ5oÿŠ%B~‰!7|ÞŽžeô^­õ°” Ðû]2nB·¥ì´XjˆŸ÷M©DÙhi·¾Ñ㻲Ѷ¿¥Çwe£ý49Øïî:ø=Î çY‘Ø3‘Ù>‹YXçÍŒ[õ(Æ ‰‘ׄîSÅYìé>ÿNYýýã ßa­c=[© ¬hu'\§¥el¾jA6mœˆ<½$ÔQãf¬¶­ÁÈó«Q=ˆâï<}t3DZ ä¢Ð­‘—÷íO‰É A¾f=èÀ#ê"dv$å‡èw¤f7˜ãót}Ó]m/9ÉEÓU똿ŸÚè¨ùj¡ÕQ«{¥„L;õc]‘nUÅUtD‰È,íàŒ.jE¯•¹{…×Ý#« t–&Pñ¥DÈÛÏG/¯ž”¼#ªÝBÞÓžTÿ;·¥#½0?ßýsm§âæ»B—eÒµ"K@>ÒÇ I+%ßüÏÎy‰ôh¡ºv"¶»C¿Tzøò·¨[N=Bž_r¹WÈÞÓý•R´ÌÌôëÇYûô:CÂiÇݘÛÁ !Ï©Z}àÔ*Û­OºF"dÒ¼Ó®©^N·¾2CfËkÈPMm^¼Ò!ê¶kZ´õS±V™†6U\kK*•¢ƒBÈ{b¶ì?<3#´ÏÍ6Wi„|¤#Ô»:Ùº0“¥áßùL+Êñ¬i3T7¼ÏçKí9Eí¹WYBs£ÜŒµXçØ¸qJrÿhWË^ŒÜ:´ZjgYDÒ ôbïÞwÅ]ÓydµÈ'É—¦3;GÈ›Gþ&Nþš5!ï@nLÔ‰Ã5ﵘP8!ZéKë®uH‹×'™\<‚w¥­Üpa"çäÀ:VUÉTsfÏ›25È­B£«2éž4ó=®`ç„ ë¯>bZ¶Z²¹9Bžßç¦vÂi¸ûã[nºQ Êžv%ß÷¹)“!/ŸöŽ(ß§óóYBgB”}£8,“,!%ʾˈÄHðË$4l\6KèÇŽä‡k¥íð4òÉüa¬ —Ó!7eñxS½º'„³¤©]ÞÓÒæû%iøû3¤xMÞ‘V¤©êb«vXf³:åsÜò­[“Á™Ø¯Þ\ÃŒ»¤„s¼#Ø5™÷°^Ò& êÄéëÄrÕÊSBèHOµ²H¥Ö#r÷ì±H_µ²’k³­#ä%ñEªB.MË)з2ƒ& 8o™‹²†<§!í÷ÇN¤<‘ݸڒy4þ7‡´Î)R-Ñ4GÈ»³ ÷n •¯Ã™,u3±©FÈG4§4U˵\åÔ°!Ÿ XDãÝÍ»,»ž~"GΉ¥›Øk6w³Ë¨>çý0‘|Îd´j$áº@È3žr6ñ²SNškNB^>õx =ƒt´>ˆ:SæT ¹§Öu˜IL±¾¢TrŠ)妌•ÒëJ(ƒ.O\¥‘9«¥hó®…m;û9òÌ 8Ž2_÷„"åg»À.šp¶ýXæZŽ%CÈKÚÊ|÷laÁ¥,02{¥ ,Ó2q®t$œR~ö/Hb»P (ZA–œD$ß2£®l‚-‰ lúž ЉI¬kO´Œ^I&)u%‘TôŒ‘]èošj™2;l±þÈ£î·yc9B^Ó^ÿDfÂ×õºª!~Íì|è·dAH¸lH#*µ%`]G‰"”Yd;LV{v¥™ ŽbWÛ¥–òšRX@³ËKÏŒOÊž¡[BvA§]¾ƒí˜Y¾WÒª_Œ|XiÃïY.-çœBÁ0;X•Ô+]‡Íƒß(9J³z‡ôfõ‚ÅTô,èíHöô¬-8B,è½1ˆµ ŸK(JdÇnä"Lb“óN6”àßyE)t`7šº˜ „,‰èï~pé‰4–ˆHØ>‹SBš?žð‘ˆÙ§¼f¤åÙ +Y&wÚ¢™FLÙ€¼¼2¹¢î”@Æy ZUÑz«ädÜ{OY"eÉ$v+ö–kã(x½ŒeXþЏà—Óë^¬‚­™}6ñ€3{Ûõgm0›n½ÚõìyTí)|AÛ–ÂPAûú*…m4jžØhä •iáÎQ\áhëù¨GDη˜ìÑvDVÉ12á‘§H5›ñÈ$°û{¼û` #Ïé܌ᯙb XzÍŽê¥ï¯6ÑÒÊÈ(!•º.Kß©oC]É|€’Ýõµ Ô[̪ÈE_C!îz=†úÌÔ ·µ¦Ã £îz,V¡Ì1QØÈžBQàz=ÈšF‹{6’›uʪפ ÕF‚I‚YlÈ4ü;oizækA³êÏm2"oG3œ`]8çÄ伆ñ™0Î}©_ÿ%…ÎòœÁ‡d¦ëI§tÞCTyû9ÐBôí½”2n‰aûßpM@n²a]ºý¼•–w«M>š´|érße|s·íò–B¬ZFŠÝév:’ ÂêmïÎkYÂìHÈáðD ž(—Ý6!ä§'ÒvÍCÈ Rþj‚6\ÎæÖ¤h™ízIÑÄØ<Ñ4iÊ`?RÓÆÝQèÚ ³oå-Â.s˾—· ޝyy¾uÉöJ{ÈëWº›`$ßn v86؉ȷ¶xÈ`'"ßìôØ`'"³4®ó«w¡Ëz0Ë$±7ܵ’ KÆ[æV “Ÿi„<ïdÑ )`b•“²)·!/¨Ùw©I›èFÀZ÷"úëº(ÝìMEꢵ[Bø¯‹.*/°Ó“Û¿_óòQJ€|~4c´MšÁwÿùhÆh‘òˆül¦ÓýôÙ(u”!alÚ ª‡ÝþÔ ÏˆªçQc[QjjÂøî÷ËW“®²‰ÄãS*»û¦ÿ_™&r¶ïz8‰„u)!3ãNó–6™ôpžîX#Œ–±W߬!dªéûQJf~yÞI­N`ÇÕ1𽋕yy‹Ôm-4­v9Û²Íë[ä»kÞ’1 Ê–RK4› L¼ËÙ¾EÎå¨òU }5W&=0áwÝ#äí›®ðíöM5ÈÞüýe?: Bî¥g?5MT@%F^¾ %BfIA™yÕ ®ß&“ëpä°KäþqjM¹WVb¶6šÿÚßÝ•ÌV« ˜ÇÆ ƒ¤#YhŽŸýþv„ ›CGòñö»¿C>?}Í®$·S"‘ë?§KKÝç4/Ëüu¡'_x»åii…Jß÷C}ë)òŒ‘®¹%­Ô•:\óòŠœç·È Ž8iÅJ­*`…‘WPßrvõÙQ*¨ìê#ämï!­B½²4Kƒ‰ÅsŠ‘÷/HWäæ‘ëášÏ/H|Íä{†Cóé×Õ|OQW†â(âZÎ+ >÷çk¼ˆ‘!*OÎqV£2ŸµEÈË+²Læg½ÏObçç¾Ö?‘ùþå[ ë+%0òÍ÷ìü(~öû$~ö}e¬ËØPWç¹}õyŽÏ}§‰q¶˜ìPÕíÉ\AØUßìžTk®`÷z¼Lr’*‰ª' ÙTÒ>ñ¹ðmAÈ ‘i|§ê¤ä•ª)B^™& K! ²ÇHh—òj+vÑÑj)K"4Ô/?X<ܽ${x©Úqt•£!wñ𺴵ðil8_„|‘‹­‰‚³BäHLÌJ‘[oR¾¢–Çé %\Ue0ݰ} M§7„¼ªºn5}o}±%BfïGH£ê¦ òí¿¾·¾Š½õ–¨¿ÖyûôÝÚ6é© –¾VDí¦æ’ÈU*Š %ì{Ök—Inƒ†<*2äóݱt«J®é{¬m¸šMxúÎËýÀsüšN`±Ï3ã-£º®9†ž_ å]37}®Åpø—בg²„‘™Ò4K‹êžo6´=)ÈÞý¡@ØõžÏîX²H¡×®„÷~Ý?›¸êÁäBâý³‰û'ª²…Çùuÿlâþù¹gÝÐöiÇÉ`JIòšÒ£âðlífš}ìj pM6ôÜÒíòþi.Ç+z@>vkƒhZ:·M»VRè!ŸPÛ d)t¤0[½\%~ó?àzBKæO™yž/3Í÷M9@ñ áéµv-iMj¿ôòº–¤YKJ]îkɵÏà1Ò˜1B„¼|^uä„Ù‡UÇ,ŽßýúþË÷ª.ö/A é¼_1˜Q’#äýódÖ5B>ÒújЫUÿ'ì:’[×±è–lR²¤á›·«ü—&€¦z«oÄK\Jòû]Ý=9Ÿ–(†N˜„iF¨Æ<òÞó­A0'iÜJ˜‡3ÿ‘Ø‘†•»ëév0ôóù*éÃUdíÍŽ«¤‰úqJZ2+uú¨Ÿ‰”Â9lyé1 Ùc_w¿ WÎàµi¯gÒ-í2ýŒ0™²þ€Nd3vU äÑû ³ =ù"éÆˆò÷Ch¦AD]WugÕ`çw¿ çTâ&‚¾á¢é„†þó~9ª¬o¿§i’–k+èÔ!äí¥ÿœNýç>ÓÌØÏ93aº+B: MÜñÍOciÂ"õv&îçâ*Èr*­xIø¾ö™HËþq[á²®¶’s¨™Ó$ó^öò û1ÇÜ©yÓ¯y"+ï°å©:‹²1æ§Ïù…è*~tº)s!A|gDÞ^ $µuÆ@ÒÝuÿûˆ«Ž"f]»¶„sÿ:\Rþ§dWi8×.-Àm(žù¨b!Á<еk Q¶½–šzŽûrÍÚüõu£ <ÅoOlOš¨¶n5ɪ(B&þŒvØxòheºê醥pUÈȶ;ܩ؊¦.iºÃŠñŒ‹¤º @ÔOÓ~€ÊæýÚŽšK™lùnGà³ß ûNGZ2É[ÑͬÍÿLt¡ªŽÿú=霗§0šÎBê‘áïHw޽¬öŽCαwSC1â3ÿ‘ÜÈ­ïÖkðµ=Ðeî·´«t;Ïø³’kÖ7ûÌà÷LD'¿ÃÖÑW]c.¾…Q„DNÑmèÁÚ¹é¨J„ÌßÉ}Ú ¦÷Ç[6Ž|Ø>¡êKñ뙸Ò@Iõ$¥&æ—IfDŒ¹ò3æ¥\ê’ ^s„Ì^&,46aãcæ/d>aùñ‰™58aA”û yMƒ»ü€h—‚…â5òxŠvaÐ0¦W†­Î#?m6¢ï¢‹7k«ö‰øž n„דy*òAp„ÌÞïQáý‘Š_Ÿö¨›Ý£âc^ÞlG~ÌÂSñëi;Ê;´MįQ†D¢åz'¦e‹H,ô÷|.ï`_©m-)<ÁÓl Ðx²ú|ÜÎ[2ÿâf|ÞM•±µÑÈçóq?o›}Të†ÊœwóBÈ$ß¡ …æ|vtcdÙ2+µ—ÀXy<Þî¾L“œî¾ æi÷µK…v_‰ói÷µ©t÷õx ùÃ<`è»n¶æášÏ>>NnÞ14×"ùÌ›ø²ßIÜógIZGŠl'>Y*Ö‡ÆK?µ;[b%”%bMç ¶aû¨f-˜Œsë€ÌßS»5|£ì_Ôn…¿P»Fæo÷iRÂwÏß§¹Eö‘HíOÑÂ6VÏü?È ê҈׎¤ÒJ—!)^˜3ZÇ˽™mÒo‰!…-µ¤²Ȥœ—R#¤ŸZÿü ÀKb /ñ1“ú; í˘óºÑ!à6"¿ÞY¦íãg>©ª|]ëMw–²^8×b‚kéë$žŠOEÓ¥ÍtP`בyѽßåXŽX?•°8ïÈ>¾¡Ëáö9ØßH7šÁU÷ô nóæ VÌM RŽ,¿þýù¶"ž¡FôD&U*„Ì“$æ3M&kÖÏ—‘¥).fµf0-’öÒ™ìè|~¨³‚0§³‘ίç0Ú¥Ùõ^@­AÞßÚŸøäßèñ{„<$dtZEÎ]W¶‹ùw¸>?Îæ¡f°ymLó.Ö YšXñýý”gÝ5Òïä7·§ªá™¼®}·ÃwÿÌžS0œSµKÁàR0²ÏñølÏYûŽ¤ë¶—…ŒwÇI~♦ ¾ûõ½³1cÊTV !ß8³qßb’%òÓÍÚó8•lã¥FŠÓugð¾Î ‹@Y^ØÜña-øœç¨Ñc‚Btif#B¦ÖÔWµe?5CWòç-q`öLÏ(&ž8«w÷ûç |"€ãs¹DŽëÙçã)xÛ›lÍSMzS[)iFa8&w^÷¼!!8–”qfm>'möºÛÑ,‘Pˆ¹2Èf&5Œl³Dø÷ûțY‰5m–ÈO¿õ% ÓLS-†ØígÙÇË«Î2V†ÍùiÇ3ŸHö^øió Žïü´SÎãc¦.¯{µïý^¨!¦ÅäùŽK¾ÑJõ0Ä™i–¥†Xží软ݻC Åv„Ìß›§Âû=Í¡xižzBfÏöö|:6n¼êÒÄŠ˜r¼e֒ó.KÍ>ÿ OÇGXRËÈ/”œE@KaúBókVS gþö&)Ï&$’}÷þ ‰æÐïέº%#ä;†šP=ÜÙý7“-r°Š²ìqâí6uDò’’äŸù’©äùG #ó·Æ]翦;EŒŒpé¥RmU´ÎÊòs%¦æÝ4=‡ïw–¾ñývœ¦íðýÎÑÜ«$Üñ¸ãÒl‹W9)-¼‹ó“B¢Œ9ѳž„i%š¸ÏòËs‚ë ÅxccÐ6„LX0ÑNf™YÏmrFæ‰Ð?P–çeéÊ’BÂW@^’ä‚`±0ëš›—Gò9¯ˆ·ë>‹ì:²¬Åá¼.$g2¦iˆU@‚P4Ë“d7ûær9޶êÞŽõy¡òrxžW´‰‘ÎÓªô<Õ=¤bÞ!Ú†òö/q4\K÷‰£9Bþ"ŽæBæÏV:¶\KI4üuÌÃx¡ºˆW]¢Üª‹á¤ºÈ.ÿR]`äoª Œ¼D‰Ý%x¯’}gÒôR226²DåDÜnZéwÒí4®½"uDfo¿Ñ«}oFøëù[Ã!÷FØ—x>/©ˆÛç ùß}zk4%7øœ×7¹ >a6y#\°3¼«ç=wÕ çz‡ ^–¨mÎöÏjÜKÖƒY¢¡qÆÆEú¸Ž›Ï¹ ýQ’Úsb¦F¼1?R»ÝDï i¨½M‹ %“R dµSÚß×tj´ ¼FÈ<­½}Ui®Q˜N&šWd’í4Ia£T_CWž¨mpw ZÀ»ãHmXÿs÷{’ëa9¡S™Ç|Û#eÕÖŠ}[CÆV–*x^f-AåŸ(x^g-Á3$Éw€žËOýmÏUÙ5™±¸*¨ ¯ÃÙÔuÝVlD!dxÿ„„×Çq& ­褮Ùù.z¾S5›+¦×ìP+Ú볉ºnN§é6Ɇy=죜є3È1=ìR,PY]ó§w\4TééZ®ê8&¶w( ­xæ²*‡¶Ú&„Ì©ëà˜”*rôÚÖ´l7ÕÕŸóz2¯¢qTªYߘº*Úf©.Ù2Ùú3Iº7ÈÛ¯u]RÏ_o¿×uÕq-Ý–Â'Ýû”1­r‚4®,UƼBîó†`¹ã­îSD¦üìe%2œBžòX©Ï™¢Jêä,MpÛ3~MYJ©õ Žóù@jEkÍ2õÀÔÒ!Vöõq2G^âÝ0·lÝ äÉ&¥Œfɦžçd™»È‘ Ètã`ýX­9îõ8j`Ãdžîzü7r¶ôuáy‰|R‚Y²Ø·¾®‹3µƒ ßÝ\JŠO“©•ò+µb.¯ÃŠ;•Z5L9¾Ö×ËL½ã-ó…ÍæCEíç6´¤K[Â7ʱ:™ÕÁÂÈ<Àˆ( ³‹$2"ôïA;e¾ûººÂ!"/hßáîMojb-8ø¶Èë)ר%·Z«›Ó¦Eä×ÓtËÇÛéV¿Ðêøî§-t'¥6gµQ£ !³÷Ÿ“Ä'mïðãÓ|²—»\KqT•i¼ÃK$ô\_imœ]xÞ‰y&’Ls³$Þ«—LUiº ˜×Ý>B"Í[w]¹ yì;j µ‚˜vSÂU—FÄÌ\÷T4¯ï¥*ä‹e·´;ûv\¿xL"çB…‘ÁÊ^ÉUð{÷ ä]f‰ÞÅÍç=ñ„¶oÇwÿ‡ ðÑÃÞòß²ÕöäYwû û>Š® ¬4Eò½ö +Ý ØbøàBÆØÝR¥»3°[õª"í"B&Ûê¨_ïi5M#“°çJ54Á~Äsͺ†Ì3Ù}ÇíŠY ‰·HZ11„¼¾ÝÔ·ðüLt9k0hlBÔ›œ)>|÷fKƒ¡ å#nu£ª9"ïÏóäð>ržÞÅO–üuì ußðrXEÈ,åZùfÛ®/¥iÍ„h4Ú—_‰š,1ÚÕE¨~­ñݸ®Ç|)eŠ#¥™Uuj ”%lé×Jpw$léoÒR†cº@•™îŽ™ÚXþñQ ŒÆ@•rp%#KþpÝnÊÄtž˜ìî#MÌ.î¸V,¢ÜÛ!GRvÐÝS £ïẍ\I½bdþÜMpA/dÏùûõÙ@ ǯyÊ·µ¶H1m³­L3JÊŸr\§øÖÞ‡vÙVUv!ÁÍÅñ§Ü—·Çl¶f˜ð1ó_üà˜OF>JÜ!Á<Áîçí@t@žå"‰$¢S™n¢ZÑþuk‘Ã2O<‚=£­ë¨˜ûÿõ 0üj`oud&¦bŸð1¯É½i#åèÜÃ,ýþ8±>PÅZ›ï>yKª ²Êö½î‹²,xD¦öù?§ï.¸Ô)+)|NFcpAEÍs 3?¦ÙÇY¢æ?ýÜ”yI‚_ÒöꍦÈN ÈĽ¡¾¦–¶AØúÞÚÏseÅ”-½”€ó™p@ã]m[ka2ÙaÞAdž§Ì4)tQŒÇç£þלhUªŸt¼;#q¯—¡ÁQ¯“æDÙŠ¥@ÈWžÝqJåñ°G‹ ãrgɲ÷e¥<½³;ÒËØ)\œð˜be7†‘(‚ø!ëByö8ÍçiPm˜J@Jó_Æ2u Ÿ¤­2½¡â !²Ú)Fì1×F.“Œ~TyöøGôôŽ?ç5UŽ{'a:”©¯iTQæÀ_Š>MøÄ¶t¨ùùÌ[‹“|²+UÄíjž°’â5ȪØ'§š™Á•lžñÒwº5ÿb‡‘);:ºµ1ÓÁ·¦Àéò=;zð1}÷ß?!N6¼áͨãd/ ¿üÛÐ=¨÷þàîm([ Èü7äèÁvæ¿Mï´ŠuH³zíì{üõä.þ_½Ò‘e¶eHœ”æ Ï*™¾:6œU;él½"׳棠3ñÔ Á4ÖTk›j†Aòzî\(¨Û4•Ü4Ff Ú¨ãÔH2É-$Û2O}O<²^H't9@=0²¤S—X3“Õ2;òš =•Ä"[½6*úä׃ ö¯Ûüv9ãωB•ý¿®}Û÷:î#ˆÇ9Ü›|ìËR™[SvÑV"O˜c^ÂÝú,ldîØEE@žøˆû)GÔ-Ë~7 ¼nŽ3ÚéÇ¡‘yíµ±®™cɺ۪·ÓDy£ãv5 Ó3ÏÂvUÖ½PeqÜï7x.Y~H]EEÕ¦ÄÔoc±ÁõyÿÏ Žù‹.·3–¸ƒÎ/¿†eðÞÚ©?w˜”†Ø®ÂtÚéà9ø` cŽmÎ»Ž¨¨GÈ/ÙÉŸ%Γ»j"©Ê<˜_ò7“çn&æŸN…À:ÆÇ$¤½L~¸YÃUçë%ë&êå˜\ žÿ^œÍ~x&ÛàT-×äi”‹|!‹éçŠ?)r¨ ’´u½"ä-Ñb„ê‚Ëó™Èÿõû \E(KðÍ~]@†ÙšTöA»)¨C.—¤ú Sâ`N>U¤Z$TA—ËÙ¯78–Y¦ýÈiÑÀ_¿¢=¬uòpfï­¬;s·¯5ï2{)"¬Ô3"±úé˜ 0V÷…ùãÑ?>O8{qR"0ØÜº£BÈcë˜~¦Ú±Z,ÛëºËs‡¸1Vð¦×•h„<|D’iöܶÛ®@ùåqÒ0‚>nZ&ÎÆ1Ææ×ß9ä„Ì J¯ê`ezr°O2õÚ "‹¤ãjÜ€¼¼R.´H¹_?ÿ¥\ÀÈÊF¥]Ä"dþ&Yœ÷Ž™½p5vyD<É‹Èn÷ÝË8÷ÞM]5¨ŽC¿™°æþ:Ÿ€Ê0[ÉõÆ9QÇ1ósõuRÍLùÈ׸/Î.ܳöJ ‰ö*O¸p/•JÀæÍ¯_oý–²6íY»tpÌg¥’ïΖrç#Êã7ºýÂÃÆ ME©K¸’.Žé›šyô¡YÈËsL_wŠé ÈësL?Åôä×û˜>Ñ äí—˜>üÝïØ+Í/ksT éùxîãøI˜_ß©ùI˜'<À—OEàÏç goûë§F!êȼ‹™©b²Dž:d¿ ‡$Ð~}ž¼? g%³¤¤j†Ô£zó©Á §5ž[Yþ•£É^zíY­7ÖÁ”ø+?¹éUÁæt¡ïÚR4-B¦Šiˉ²Óõ®dÙU þÒ9 <,{ß7âõ'0 $,3‹x_ßK* ¾ ï2ÀLR Y™y?4/ü×xk~&ÔÅ`b/ôt¾Õ™ Ÿ‹wZ¼TøÉ2=sWÀ¬ø4âÂô&„h¡®øÁ…£ÞšRí„y'ºîüýXSuY¹Úe´D4̦íçÃÔð6FAú¡ý\Û€¾3LQÁËŽù¸d£É\]Ì™¦·çq‚Ò-7K[­ +€í“Þq½®t|ÍÈÊ•šU~f9½ÿ|èø9ý<"dzU§å¡N{ÿ½¬Ó \§½ÿ^Öi®ÓÞ¿×iÁ‡Á!ÉÕLS “‰i¬ýŸÿ8Í ÓGP¹vר4ÉG±J´«ƒ¹Ž­6ïÊ\ì™|΀ëL¿,Ä6W9„«rÀ:'Ua«k‘)š×¶õ]ïEQ’ÄFóÁ›u‰2^„g”û›ŽcfT0ñüýèVa˜Äæoù$¶2 o{±ðSÃð4ïŸÕBs̾ª²™CÄr|3cUë<ä\÷ç…z½Ícj«¯øñsŒ[²÷|û½³˜ææPÚÎD{ÎúQ=ü !Ñt‰3¿Ë5…\^55}bÅÓCȹ¿S06ÃÈTü;x ¢4VùüÇsž©íòR5±4Vo´HW=PÈ7—ôˆŒu$|v¶ìTê(¸@È4V3hí´£Š(ÕÆ}<& ºµ‹üuå¹éæ=RÒH½Ñk½»éfuEêÊ73ÅÊèGÕ3^K„LâÉw—x®«•2¾GŠl]gÙ¼óûN ³-é#æ‡üÇÖÖìl`5JV ˜Ocý£¯Úûª¥rí«6žjiÄîûðU›b_µ4b÷°Ž«JÀ~±ûÎXÇ-L*9d°Á­½S‡Î{ö‰·áÚaeÆ(9̈íÃÀ%F&WÓd%ƒšjÌÔÜÂÊùŒv*¨Ú'ª‡k<òñuJëÍaý|×3X“Ÿ1ÃÏ?ýPýªÛSï{ó^«Ý³ÍÉÏϧ˜Û;Τ è'„ŒºÕ´vD–¢í Êó #Ós¤¤*Ùew«ÝºÚ‹[9µ|ÇÇ oHM£È¨V°Ml0+D~~ni_?­¡g§HËë ¹ç>V$?¿Ç¼ÃWt¹ ^êOl™|0ñ@eå­\"d˜iª3ykúGz ²rrä×} [¸v¬ÃS˜é<;Ûò»÷^ûÌ”Ä\8ËK§v QqÝ Öyæç¹ÈOv¨­QÇáQÇlg±—>ç"î_Q»J©¯<3õÀý¼²žÆù•¼z©%qp?a;›jwP<#ÇLê½£êL£Kçí$Þ¼˜$B*{Ô²:©`²ïçóC»Ï†6½¨XÁû’À³ŠôyGŸV[ÔÕ™à:Cçö÷µ­ ¯f@~=”ÊM ý´«ú@ý›|ÐtÒL«»µ¼kMÜ^éÛ!ÑÄ48‚îZ]¾¸ßhºY3Ü|¼k÷º­å<ôþ¹GÜ-×Få©®E)¶É«É’ß+«÷ÞùúÂ;ÿ{êOh{ÐrÞÔ1ýrÔtªœ•Š*kõÌ9c3B&1—ÃÖ~«ñ¥Î^‚ò•C¦xÖÒäqK56²,Ãs¿¡¾aÙh‰,Óƒî[Q `6:dæ§!bï&*{Y®óŽêK&Ûµ:¼ÙX³‚B‰´§t´f8äÖiS§ü {ç3B¦ñD¿«n嚸ÕBäæãêÊih(È{žUâwéü3M¿Ãì2B÷;T¶ï#‡ o&4˜·~)òŠJ&r8ûïÚf¥Õwiù:½­8BÆorãŽ9?p̈9æíãÝ4™ÚŠ–¼s1ÇÎw¨]˜fjÔµ“ÖÙÄ›…LŠÄŠRÿE¾#]^i.¼KAQÊO.4–ϰ¼òJ¨+’!#Fkå ÔE³²˜û¶BÈ,ö*°Õ×E»žLï ÖÏëðøkבM®å÷rCÈ$šq_‡:æJé<ÁóÖü]òó†mAEÉßI"ÿ W=h …[¹Z2;Ìb´æì;ݦÙóH‚y,&±ü*VTáü2T?w[Ö4ÿS?ÑpíéçYª“¾".¦†"d|EÞ#¤(¤àmSá³gŠR{P" ¹Ô-4:QÀu'5w¾oŽð.ÜǾ¹Û}S ä‰÷óÞwðÎß¾j:ÕCx“Z^~t€ñŽ•K ¹â³ß"6ZJý{.ì\)¸)€?„³§ÈÇfžÇÝwòy9øIäý=oü½zµL‡|Æ1˜÷z©†Rç½Gf+˜µPQw^-ÏÓäkIš}÷õEh’Þ°>­¾ñµuĩƚmàUFÒû1›¨í¢¬gW×=°¦Ouq;â0ÕŒm3kà.Euï ŸÁu-Í÷nF_9!ä熟lªî<_Ù‚:‰˜NæŠ º·|”‚N^ûß!#Oµ I2±6_FX“É/Òê4³Õ®°µïéUyn!‰ÙSFY¨v¤=3[-§ â’üE¥ Öùˆ=uª·&vŒLN&€´"ßæw®ƒBWQ:ÂM·Oƒ¦ÆT¼EÈäª7\î ɾö&FÐu'$»PW Yí4À‰rȓބØé4E½ ‡$×q2…7$°¸Côkªš£Žëò|™Ä<@Ëc©ëüÅ›w)á]Š<·uØ”¬¬ ÐëÕRÑ® B&ÞÍ®°#wê ÚJ@l[é™N nY:}·9—\v•pmàýæOT™ ¥Ëk¾Q «7y4[;Û-ýÞ19C‡Dêd‡ÿ™·êê" B¦SÔe»Bô]½ÎT6yñ?Ký?ù¼þŸ5›âÿùüò?7õ?!Zu2o)F]Glî—Z-wÀ!wHîܵ ©›¢ê¾âìçPW´s|z²fÉ¥dã˯!îA¾-£žûkQ±Uå'(I†;b–f×|TËXÂŽý¼© T³FW‰ýØSÿý㵬ºŸZÑå=¬Š±’ØÉ<¬Jäüj1L†Òب®í*mln¼{ɲÃÜ„Ÿµlǵ£óL½*CÆY¹_”Ç¥S)-'„ Y9v´ºš÷6ÏðÎgúâÙÀ¾Ûû²Wa&BfÒùM¨ü}èEÙ·=Bš˜áÄ fÍÇvšt!ïá+vCZ±¼¯ºÁבeˆ•¤rç& ÆEt=ÝÞùŒuNl÷ŸÕºÝ  Wô¡qíTRuX+åì>’}úÛkﺵ+Ëmò}’Ý1»Ïoqºb7V[ n$VQ³ì”Ú>Ì¡©ºõyÕ $ö–µÆcÚaTÅŸ¡DÌ17Z[ÿÈA=yZL2ÜùûÁ‹´v“ ¯6QŒ I`ŽI[Ùs©LWÕ\æÓ+ß;fŽy;u`©ç“ ˜cÙè™7}ТZ«ZmdÇ;ÿsVdQÁüÜæ Ebs–üjV0jà Mü…t7;Êë˜ê–Ú£…zëæ!D6²äÛy,f>ÑÂ##’™?»U>Ðg/Ôõæt™\‹ÚCpsû«¨=CÈä|¨^¥g+ ·äZšik(íEÄ5lí#¬µÏeâ@\;³ö‘Qã–^ˆ2³crx#×”AœÞ*I|Š:As"¢£K-CA9¦£ý±â}v¹QIWG9í¼¨‰éh'Èw@F)ŸëÃê$a |[FŒtM}[ø®ÝÖ•—›vD™’x¤mêÛv xUû¤nBf€4D³wy²yƒRé-4ÿÈ"Ã7{LÊ8>»µl= KíóÂ%GÈG¼u9ËÐñ5ÎŒÍ3ó‹&òïl™¸îŽÃ·y;a¦B­gÿê{*§ù=#¤ÿc]X[«—™×íÄTæ!’„p­i­×‡kÛÛÄ12;»¢Õ^ Ÿ—WÔõ¬‰¯èyuE«¹¢w¸¢çéé-V_‘Zé „Œ®ˆ:¤ @U.¡‚ŒŒ ¥¨k×ee…ñ{rÿùõt¡ÿúR¡¿œý¸ „Åc{ ¯FõÊ…öÀ =‡öÀrlÜÐÈ_QÛ9}µ# y·MS…ÅûŒ´ž_†9.U÷ê6?à`Ч­EÝ.#LroùûÒÊùÈ0òZØ}gpEÉQð×5<´pL/yßû=ýJdÉÛ¨"‹Näb"‹C¦ OV{äÒ7ËF›m€ç˓馔m\æfg•€c‘ 524ätEE¿ï#CaÑ«hØcòª w‰ Ä#÷“=F2²•,_}Ë"û%#.ÙöýÌ2AÒÀv fV Ý,Ë7ÜÏÛq¬È é˜AhQ>„L.dg…æçxäý/²³lß1éÄ’x,nE©9×ÖÏÿ8«9Kv­œ¤J#ኞXˆ¤lUÌ€¤lÉãS‚3ŽC$‡äãH&nœŒ¡Ÿv¬‡H ¦6¢wž™w~ Ï=¢6âwž¹wZõÚøIÞÒbÜS‹ â’:¤®MÊׯêÀå$ ´ÑMð]¸:C»ˆ—R4°†D4Ä5ù ðY‚BöoP¿B¦åBÍ䆳“o‡bè Àè}ñÒ¨G,Ú€Œ- þá+{?7ÍY„+ºR®M^®‡½lWˆGiËÊËpµ¿Ê6/„L‘ÚžéÑÄì¬Hl«iËšNÊA·BñÙŸS:êÆŸ*¹Œ• !|<ÊFXSG,¬bLÌ`îHbñ>'Ùci^ºøËÔvèGHDï;¥Gž<OH'.»·®²xdòUZKî^!Ú E‘gr ­\º«©åH‡w…‘¡—bÔÔÆêäÏôÓvË‘¢k×D È“\ ò‰Ã yfä›òÛ CÈoƒ|!É¥äY(k>o+³+Ø+\Ñý@L?È ïÛÄ»3¹á…aäµÜ0ŒT‘ˆ`ç<¨o‰åbžÆpöèëøß?ÿ8Á ¶sd8^û÷3ûùùÛl|ô™TQÇβòÄO³Ÿï¦5Cç¯= ä­ ±c ÿ“\ˆ³ƒØq›&¢F‚àò­-{&8{†vCC´#”\½J•öñÈÛÉ@‚-íMÆ–c†ÿyG+mi¨ÌúýT9×XЄJ³Ø8ðT}‡+zàæ„³9Ñw^Ûœ(àè‘Ï¿XÑø‹ì÷ç"/v-1”Ê"¢Õ‰xŸ®3Ì™|ïcÄû²ˆhÉãvV¢ë=-»7Ë~Óï£ íWD¾‚@S?û%£ Ú¬%Œ‚d¿Çq0ùÛÅ4½d‘÷iM, 5‡šz2íFÖêì½õkHö›¡ûéšÐÞF‚—›/®eòVdt Ê"RÔÁ.è ”ýÞ¿ É ”E†|Øž–ìi³_,ïÙv§ÈäÓÈ–Œl2=±¼íN‘ä‹å-Ff×H9#ä =£ê`m9–»G>‘œ~çÝp zçµJª“³äSlÎ2^T$@߃l7K~/ßqlK cYò!ÄÓ´nÅÞ½$ÇH·ÚÄV4:ãè»U6!c!?‚ÞEÝ|ÀÈ¡½Ö|Å;¼ÂÿL/÷M›Û¡Z˜%Ø×´šìx³BæU7ø&t–C[¨qÍ]m{ W°6GÈ@Kºy5­*‘SYÒ‚$ι܀±&'ïu×Á3ʾ³é¢B&gÆ-2nÉ"9­ ã‰_Œ[<ùÀ!So–iï<5m6½kkµc¼»"¡®ÎþÀv•«ú›Ê‰¨$õ¤“,y~­¾Î-D‘Íž7èrZ¶óPÑmcí‘"­êˆ†Z9W3}‹·Ï&²ÈfOÚñ{ïñ7¿*.^ê5AÈk æ­)ü3Š ùά)X>!¤3]øWç~|Öâ íè)/YD6úDîcÛ®B^Y}Ì|ôÃÀ™^ŸÝSDzˆÀt~vOeÎRò—³/B¦×vVá¹g³³byIÚS»,óv+æ*VU¬È29_é±"Îê\ÅOp—îv[âÑöéÅÙkGÈ$Bv–­K/9-+„´VñÿµR8nôkÜ‹>¯T8€$îà´nü‰ªÿ©E‡¤vkÞZ-!ïY…M!lØ£ú%ï÷F˜"ä‰dïíëà~$õ-yËJĪÝèUÁ&síeIíts7ŠœmtÞ¼}Œ]ÍÊäQf‡]¾4lñ+CDuº)€³˜Îz]YEµ› éýú‘pïŒy;U@’o«7 Ö}!ßVoý6adz¹~†l"&e|Ä!‘´Ð¹i ì\±à©iÍ™|‰mü·I_3è@"ÏbÁ ½#Ô´Õy.µÉ ™\åÚã"ñ1Qí†À9]òÕÞh9#O4~_±²’ë@K½-"d[æØn ‘V±¯Hd±°‘±š3eâÎÆKr_ª#“iûÙïÓ⫚62fV·°kUl#¤hë !I ¯³(Dî|ö{bÿiÆ´ MV='í&TÝ[Ô#3B†Èß)4´Î´{oáÅ„›SËF^ d åÛ5ã kÖ² W_­D‚³`—z×Üá’ClÓ8Chµ*9Û`ýÌðÀva,Ltªä{’!ÉÈ7¹vΣ;õ;NEZá‹Ë² $ HÓ kÈòR”.™Ð´c=|/·!ÃW\yßJvœñ²œ)B†!F.iäPNeþZ’\“žŽÙ5éb0‹¼]S™+|ÌûÊl Ë •$#òq¤2›ÅÛP™¾Ÿ@6R·³¶U£¡ïê†MSñÆwþç2áÃAï¥R‹Á£5Ëp[¨°㯸]Þ­‹@H»yè³ŵ¾êèÈÅÌ’ Gh+d1×cŒ†³?ŽÞnEðfyÍùè熳 Ïh}2ÇÉÚçM<Ÿk„LCs—º_/RÏ¢I °C~V³_í2»(ä´cðÒ?¿•Nrµ| „<£¼°|mx¹‡ûZõ† ׸¼¸Û»aáb{Öpû( ´^«þ%E#¹çufGb‰m¨ûä˜T‹r… ÚºÌC2Èž¿½·dvÓ»æìnixMb›æpöäóì œò1œ=9;»]DôÙ_M‡é§›ë;Vªà ‚›Û— ¬ÉÇa‡Ð*òlÄ&ÆÍ~”CðF¾<Í7+âi_á–X;Ý>í]Hì¦eÚê6•Òmõw1æ>¼¸Ý>|ö¨›0nv­pã›»‰BïëÞìu»÷Ý‚iì)jŸ¦NfÄž×~z5‹LzÎÀ¸~µÞõ‹ ã ‘HûJ–®‘6]:ƒàí“ÝS?õ_Üíù7õSŽßÔO'„ü¦~Êò›ú)>æ‰ú©8¨Ÿ:ä‰ú);¨Ÿ:ä¹ú)/ó¼ÛK„|„‚ˆŸŒ\庿Ë6~­»ÿ|¥’L@%É""Ë•dFÈ‹¶zL%ÉîŸÓÿ˜Ú_ÜòòAm]ìžœÌX„vËš9Æ& ºd´–òµ{W!dô~6ÿ'ìJ–å™å+cöòÛߎèÿÄ$óLôÓ_EƒOï:"„†RUV¦¥þVÊc0—pNÏ»ÛÏâð‰|tÿXÇ]sܦtÛêš"}§"lSf™62êOx å;JéThÕËÅ©úÞÜŠ __Ëlòšßè܉b¯(ÊœaØ‹‘~ÔÍ]RU†•‰àMâ\åýªûœ´–Á Û?P^ŒN•N^ô[ÜòjâðFï³"‹)öŒuŒÛžÊÇn™jŽÖ·aYöËŒ9ú>—¤Åýúû>} ÖíEhÿý ©µŠÍV+º®|îVŠÄ.è:øæ*¤ê‹ùB‘¯;§&+"rÌ•ÿRÙ¤‚ ½Ûs¨9>"Ç\œ†X÷ëLü•Q Hõ½Ù”Ù4YÛ,%$Þ§n˦9ÆZî'-ôëøïçéŠb\²ÊI×”\f0áÆrØ‚rÕÔC;´ÍHý…ôqvà¸å|núu"H¸¢D ®.¿Q®\$&Š \2(uŸ4)ê¾í’&%Èp'Aª¤ªÖw¬”§Ó0BYè½ëa_)• ÐDñ߯Ç3S{ üíëbd}³Ï³sµùîÂìóõþÌð‹®çÜ5 ʫīóª‹qäÑ—CïÝ\kÀWs7 ( aºÏe¿#”W‰W'Uy©å2ÞU^üÏî¡¡TíÕÒ¥WRÙŠ9r·áéËÀùp(ïÄ ë‚1(Z¤w&²4λQ½ÝÓæ¹"$.Èý=!‡#Ò»÷æuÊ[þçëy$vo^ÿó¾Ÿ]g¦ýŸN4Xªh²¦ÉÚ4 ÄŠ„Ä£Ç35jIr½oͺ6‰ HS µ~,fˤ©Ó^dðëáA)*1Â…¹òY×íç>“ÿÑäo¬’¿t«û”vwɋܤ$j¶µ[9RäóÞ»"«Ïç›wÛ½û|äšxéÝ'Ò† ¿y÷ yçÝWîÞ}ùÅ»ïðFwµ¹£>áçµ¹üšöB`º(Ä UX£ë?ãiŸ:ãŠ5ò?CžH{6úÕÈ®éH¤Ý¢Y23ëŠQNP7낟ÇA5\Iœ¿w•qoä¨ö¹«ö$y2 +¨\X%ëÿþ‡tÔ”c¤ÊŒ/yP!7ƒ>fk;ᜃŸçQ‡|ÈÓ¬-ñ߉Iäö6a"ÝÜåyÂ#x÷×Wúƒ»v€È[W±wÎ\‘Ï"Ÿ8geõóÆI™Aò7@4¯ëÛn_3øvÛÍU>† qÁ#·Ê1cÝDM»‹àçÐGëãHÏ9n3‰ Ò£IU“·É“QF5E‚㙜uf&©göœws3$öîËL×›Rј†Níàç}ˆüÝÝ0שm“j÷Ï×·õ!øùÐ\%´lËQšçy¥“àqô¯ã¶y@­8Š–iIHNíò¦Í`Û:ù—0xæãè®c¯åI<±¸äÌÅÞ‰\yaø>I›dŒ+³’ qaÛÖ-Õ][žÙ5¬ŽÇ/g1h9_Îâ#Ò£÷8+ê{\•ºx)xUIR§)&„¢²$Öw´7¾.®ùêýœäó¬Y>E¬’[rv åjSrоšÑ$JÑŠ,"Hßݤâ,µ­Jó6wcÛ€ƒ‡E”v¬Ï8M;^Á)xø_w› nÐéQ.›é„Ö¬$ÈûœÐ-òuáš(¨kb€è}W̽Y(x„uu64DÞ ¹Œ]ö5x¼¿?3/áïü” R”ŒÒãžñÍe D\»öFËù8ï!¶µFî!}œâZày'B˜Õ½ÕÎÙÛæîÚ÷<¬Sý°öUÚ9_¸À{w¢ÈÒÑ?ð^ß< Ï¿PqC3$A"ƒéÛY5ÉÀjHÜ×Ä®‰šTš›@U~Íhl—’%)AÞh á\Pà…§ Ù—„Þ—Ê:ƒwÿ>CF |Ø Q¿(kÆ}/ø ô"o]+RïÈÇ/ŠÔ䥌¹Ãºœ€(Y—Êš…Ór®T2£×./|‘ ÷îOªÛÙj\‘§¢*³a‘ÃKRÁ´ÞrWä|à£R”Q£±J{ÓÆëuë:A/h,]hSÅòZ̺¸§Ïô¿d·ÜÚDD«£ßÍnØ»ï:»µä·ìE¢ìVÆÝ]FÞÞyÏ\Ö(xžò ¦»YE,cË“d HgÈ Ýe«î2UY‰œ"Ÿw·3U>t—9ßÎwŒ }ìZ¡•"ža.…÷>Q£R]ù>)|§NCN”JCÆ“®M½: K*m\9Ò^ðú9)ÃÒ‰R†[Òq‹ ‚ô°­Ã2V”mAøú¦añ(/¢dýûß¿£ÛpŸ/ŽÈ¼G}ñÔPsä(¥‘œÊ ÞÈ;iW§–dVÏ͋٭LÞ²o”YoËy⑼Ÿq‚„»¡Oë¥ ÷…’Gà{¼^$geµÕ R #‘Dô¡°”k.X©$ ò‰<Ç,EcÛætQΚùBßÝÕ¤ä¯ &Ÿ™¤O…¥`F¢’#À 2@JϨmYMò8Ú2Ä*ìVÓT‰Å§r¥ç{WŸÒºò¦©Æé8Jƒ´TQ7ò™(ÛÓÈÿì¼NÝí¨ú´z¹Ëʵ5ú8CÍ%ôðT1´%Ï&'ÓChg¡O‹Xï­mhVtŽü¼üS¶û4Má¡G‡ñýÛ§úÛ¯AzmOÕÈØÏ)—ë~¤Ï|ÞÍ’hìùºú¢­È (£ÂPãí5›¼!»\Ã+W#?î#©GÉÐä>?W¼\–Eú7s~”sžþzp;òÐfa‘áÕÈËULFÞ;ü8¹-MÒ8nÈî”^Ãq5δâ"["NÞ.rãirÛ(‰§^(½{þW{²tSRÁÚ|¹Ù¢]§³`J¯óέãpGñ°£mOþ–0tfðPQ÷Ï?huuJƒñ4AL¿kýíš„YM }æÓµŒG@•Õj¥òŒéà»cás?äà—”§} ÑÕz̉ȫ9<ó¨l¯u¡sÛš™/eI‘d:KL*š\`k™3—éð?„#Bh½¢ ;ç¯3&AQgŠã¢âÙ0B‹® Å›"C´üZ—‡+´f|ÇgÅ TÁ-ò…8a©ÍȰ~ìá¿!Hÿ¬x,¶vÀŠÇ`¦¬SDÌ”xw7Sdxã!ZP¾ 0[ôÊ §àïô¨>p’f®Þ“Ô±ˆ#Èî´‰s§ð»9·>ÄÂÔ"aQjùáªa(íJО ‚×=…¿Ífyh7ù¤Îž¹ñ¼(Æ%^j˜!þém˜jcÊÇÝxƒà€ä&TÕŽZlLg¸I­ÚÚÒ¡ÜëäìgM3Caga"^Í×L*¶ÊCÎŽààŽaÅ åS;6 1ˆa%HqDòB÷¡ËóH"ÇÒÑØ-2ØÏ8noû¢Œ¢±îç ž^¨Rs¤J ·‰€ê[F&#£˜4e7Åñ6 Š|biÃøQ±<ŽJˆ‚£x ò^µ4<“ÆÉ‘™!*_o3ËY ă\õièzvŒwLC­ yªRY)Óà’å®.@ŒI*+e\j• ÂÇ©k˜ñó0¯ÙµPm ½+÷ãU*o» ‡ø3<Öw3“f‘Èmáq bf‰Ýê¹Ñ«WõÝqhb¸M„ÞPe¨ï$/²¥¹ÕÀç£'<üúëð '7JìíÐCÎŽˆ„ý§›ºÌ®8wѼDQZ1‡¤U-ôbš¶W¹âVÆC:8zEz½k&¢ê“ ©Í’ªg›X‘)Ø8‚=9 ¾6¬çûm±©¤V?6JR .Ìn¼Üiáä ?§ñ4Õ;å*%·ùÚéîïcÝÔµMc·ñ8c¤Gó•Æ) ®Ö²©œÀO€üOÿÓ<]*N¬ê¶¸*Š%áHW'L%XiwÇ¥cY¤ïò¿ÆÃz„Éèsš ×½Ü ¤ -'‹’¢&HïÚzT®Ð A>o\¡Ëa?¹ ÓD…QR0‚Ë3ÉiŒ[$ίé9§[Ê () =Z‡Ög¡Q Ê;>ŒÐ`¾æœ5R mª»fÎòI|sìvÔ£‚plÑ`çVd–JmÑO}¯ÚnyIžf¹A/û̈GI¡äî8A>ïªMÃ^mz¿¾ú`¶ ¬Ž7ãAMÆ®n Ï<ˆñ$–°iø‚íÙ|"föÇŠEé6µ²(:y=KJ‚Ä]Un·QÈqJáäz‡´á2¶¥®bI%"Þ³Þ!½RN\å²¾˜!bAìFuÅŠnV±\AÛ´NP7ýüÄx$Òx^(¤Ú9Az7Ï,ä3Ýx~ߟÙ%Az{>]÷tiÁ㤎x¶:?…àã2ïNíyÛ:9ŸÖNÃÏóbŸWÔ–ÉÆÊ­wâ1Á‡fÞÕ>oTESÌrç ~á•§M4ÙJýz6lݰ%P›ùàšÜ‘m?ã ëç˜Ñ5•.õ5›¹«æœþÄD´7>»…ÕòyQ‰nRˆ_h9aVÿ?—'lËã¾æû^êOI#ƒøAðù|ì!²"\ÀSAµõÛw~~tñ|ˆ˜sÿþ‚›˜©÷”òü\bæÜ¥ÔßþÌ“_abj'à×4é}¹Ã®ù¼»ÃÖôþÐÊ­6i7ÆIS>¹ køó:ý¹å„¥ãØ´À+ N5cM¤Qü-6Ƚ.Šè3‘(ð72Z×ÂÍ:‹|í¾cVGC±^XY¯‘넱È]ôWk©¡Ëò¹‰Ë´ë2À<}EPÒ bŒ[ð§°H­ê¯8 V¥Kéj–£ŒÖ²±¡oôF1˜ush6Þ eQºØ;üñ¿Jå½€g¿9­4yí´²b§‹¼r?8­XäëNž­ì<[ˆ¹€Fh0q~Ç\ S±Í¥C¾‰›Ž*M‡ËXnmÜCÿUˆ]8â…ƒH‡FþA;aÔ>o™ÜrŸÝÚenÎcÉ·æDà€Ì$ÒÅáã(B‘£<¹Z@"ÆÏ¿ã¯·9ŽéÝð 妸Á3Ÿ¿4ëoðÌS[?ˆ=×Fì™"¯ÛúåUf— ¿´õ?;D|¸«Ûî ·Ýq×è ZnÐ!b­š¡â: ó!•ó³É2øî”=™õ&»IU. tׄðxGp®¦ò†"/å³a á™Éh ÆóC¿{êÄžÕ­+okÈœ„ÞÏ)fÈ­…t—Dq$œ(Kˆœ(¯EYJxæã«¤–<AÞKjÕ.¢=$uåÒß!v<ò·D‡<ì 4|r1æî2¡÷ú*©µ 7†ˆ»vÙ_ïo„"j'ådä”beÜÃ(…¿ÎÅiÆó¯arÙ˜¹_Æ.íÏ|.fÈGÛ´ýPÌù>0z=ÛˆÜ0õwÊà› =ä\“koÏ¢ßäñ!·òŒ"o%vÐLön{Ús>O.H6G]ÅÅÌã|„Ã'šŸÚ ¤,’ZFVÑêØÌáóAÆS•†G.OÂh2Øëž§žC;JÊ#l*‡Öå“-Òä‚Ô ÑYM#¿ ‘|-ˆ—žè¶K8vºÚ2iHïÄºÖæòÍên^øþFÏû9MØ8ŽÂÝ"Ã籂cܳ¯c)Ï„ Cšg¶*Ë‹Y¾õû¯ûǯi™Ç9F‹ÜoW‚$æ+`êRVÏm328V«wsåо·!â®ýù»Ú¼¢AÊÃ5OS— wÍ!Ý3;Á†íˆ|¹[ÓJÜæ?‹­^8ýuõ5ÿh)µ(±–EÝœ¬r³°6Ÿ(Ÿ¬OWµLÖyTÒ Î 2<²Üd  ×°Ü»ÞÈ/´4é$nãÏzC_wi²pïÐNè¢ëçRŽ|K/ä~•ë9R$s*§|<8ž®E‚A„.àè?4fcÍjåLÁîæò!röËÕñHáE^±çˈòŠá“ÊBŸ{ºö¹t×Ó%TO×¼÷tYä}Oך ‚|Þô#13‹|ÝŠ™AŽÅ"¿ôt ô™±’ØmÚ 2ø;—H.ã™ }Ä{¶‡yé”wJ´,ìg·zI*]™EK ™(ƒ ÷~KèkjæYÆÞIÕäñ‰‘úu&øÍA~ö¾&ž:ã…¹jy[LôŒ —i¼Ë¬9ñœ±bÈbðórP³˜¬@·Ì|ÈÚ¥¥oÿÀ¥CÛŠ#·Ð6“À–;臄ôqbRv™ðe˜!¤A{x%VÿªÆ™M“"f$´qšéT€oOÑ:É“ñL d©Vj•çQæJ3¡ÿs*\šêD!?Xœ-#\ö1ÏNÓ`£' _Wæ ±~¡1d̨\ 5o£„Èx´ÔU¨i-]Õd@ü¯l3¡ÊZ‰ÕÖCDÆsþEfþÎ^,QYBÊÎ ßôëWR>ÖŸ“ ?$¬Õõ…Œ²¦9 ÍÄûçê=Ü|$¶Y™¹š±ƒîV±ªaÔ0Ù¶ñLn÷tœ¦âóçÏÿL’I=4^X-ï‡d,ô¦ÝV vÛ“Obr£“s‹Ù?ÂõEE_úœ•K;@Å? ™¸¢(£n•7¥*%H#dâÂ#ÑQæ¬aÍ¡ØN³Û¯IzkV‰Èzdë8¤¿‡w:àÚ¼¯[(ÔBbòÜe ÅÀ ò¶C@GèûßD ù/Dôµ£ü Õàó„ ½;j”|ª |Z´i-m%A>p(úïaDàzìŸäIr ÇÏ|KÓÚ½ûQð/um›¼É-Q, ÀÂô5P¹,t -꥖o‡|œ~=s¿žÛÜÁ©€¥WSâµf±ñ:•sÉé'D´°?DvN‘‹¾J`E‚—VÊÓFŸy .m1¸•¡CN¯{%H±ÏãnJÎÓ°â} ‘Ò0²°THV:ÊfˆdØ-˺¨ÔCã  Þ=»«‚|&¯‹4já×÷¦O~sZß¼U>ënňYÊÑ•»"Þ%.D¾™U1Ãò™U“ËÖÊSnË9Az_œƒà™Ÿ¯žM»SCˆèVÿœêrn(u—oñ éÅðñ›‡‹[›¡÷‹‡ ¤ªwjÔÁÃE<\Âuðpi.a葦ˆxO©l<­V2bjÔ¥¿ÌOâŸxé´oäÿæ´H‘ßœ‚üæ´HŸyá´(N‹!¦FQJÜÁi1Dqt ³Š7G ûö寵/Ã\zsŒÊwǨ0ü|sPŽQ%Az—¶ñ†¨áž‰èV”Zúÿ„]I²ä¨¼ÒËTÒ²ö¿ÌºŽ€&ЄfÕé?r¨¶Þ´™·ô¤Dƒ‡{QKŸ SKyD-}†brï©¥!¿QK1òµßýµ”{j©E>¾8BÂ[ºþËR ¤OPÁ{Bï6RßC‰8;¼£bŸu|ç‘ôE@ 6)ø44é¥jm’¤‘myÐeš*„L°k§~õ³ŠÖŽu.Ê!oÞe²¶Rø;Û¤ÚœÈ;zK9ø–bž/)ìKé•oNi'Ó[.T ½DÈÄß}¯"*Khü³ßƒ19[Z5º ë0¨0HNøš÷ enóÖÌW‘÷Ð!äà 0œ4;+ÇÈÒûõùx‘ˆsmÞnóÔ@¼”>ÐoRŠ;Ñê`mDÈÄE€†^©iïvÖ,ÒÊvZWDsnvrégµ…„¼q„k>_²s÷¹+©ž˜6½{GÍïògúUhçè4]²ŸQuÝwúQ¾§ê¶Æ60-ug½€|; )"‘¡ÄiÑn°’³ë‹ODcWHIÛ£^¡$”%¯ëŒY7L•'6óÌBÖÿ\Æw7wvÌã:Ï™¢Œ6VÔŽ'¬@èÑ"on¼í¨£vX—ܲ,ÒŠÿ:¥¾ÍRî}Õ/í0 ùæÍ”úŽè¦þJ9"ä3—¢n\jÞèÒ­y‹é§ñÙA’çÞ;ûÓaW¯qÞ7²ÿÌß[Ñ3dRÙ7IH2ðZY<’z[]hÀÈëRï±Hh®‡BzÖ—P]°>Ý^æIÅ©«Ë"#!=-ëeŠ7êëXÕ?Ü9>§?¯Âí@ÑÎéÊ©ÛëÒŸŸ˜ìå¼à9Éù˜‹#Œ4â(dåBÐßý”AkG “ åB:w‹¼‡BPîì˜]øæ¾#‹|8 WY9¢°d™G+·ùtDa0km/äÌùXà'J=²¶…@Á ›YQGÈÌû¶ë@QG€bšÙ>m|ÅH[„µÅ Ãúѽh±.Ôi…¥?—×äÐ ÷¯³X–¢+„C^Q‘Å&rççщ¦.K×±O®1ƒÌ ˜J<ºŽ!“–'PæH6b4/Õêy©æ¥ÒŸO–'ÜÍK-™àú·S‹U'L¤?/j±Ôì7g¸¦¾‘nAÈëÇäL\ÒŸ{üæ™ãhKÑ®B8Uƒôçñ¢æa>¤¹cƒèFéø€i¨¹÷ŸíIZu©r ÝÀ]p“þ\(pZÈœÏÎI/Ú¢åµ@È'[åL¦ÙDzéÕ²dÌ ‹Õà¿2 ¸o'-Ï~ûZ~õüôôrÿ>ÅZ@>ÞLåšÂM_ª•Ç`§ ¬jíNë×§ú6ú]y 4l_®íŠ£Sg’¿»gýµF¦p£¾¸A¬Í\ÃJNc.¤M'ª†Tj…Ðî@È@ I‡u§§Â?T®½ d‚¼ÍßÏÃR¯­ èÓKà_óßid­­f•ð¨€þÈW„¼{ÅHädE*¡^ýŒlD°¢O/Ù¿~M÷]>¬%7g ×¼^>Úa ¢þ¯…2,íÉŒÍ8KÑ”ÛAšñÜ¡“ØÖ¦u[Û¿ÆjðVnEϪӮn¶É"·ƒ§”a±¾¨;éÓPð½(\óþÝ ´# B†í«Ê9 ë¨u½Üï~'’’;$üFÏï_œ„Ð*´kö;²…ïbí oZŸzÖ¤Ó„ôß&ïHSMB&hRíÐ7dwLÌ4dMz¤ n©+w÷äç_>n…$—¯ÎUãJfir}g&w¾y®Íä†Ü½Ï€øÛL•Õ6¶Y;Ië¹äiËšÿ;U‚ie¾#FTX+ýݱ“ˆk$0]Õ„nkÞ"•àÚê0©Ð_mÞjÕÃ5ï/H£<¬‘JœBFòÿ³#¥zù¬”*áWv6t=UNéKäP†S׬èØö²BÈ»÷î)gÒ9’¯’-;B> Ù®Ý,£dó¼ä*®]ò \³ÊÍG2Pób…It‹L½§˜S ­†Fî¢Ís„Ìüžìôñ66ê”=VŒ´‰‡urvr+ë¢Îâ‚Úäñ5\—~øç¿¤ÛÝvRCßÒ i!†¾^òúÑf‚­6 ¾_ ®n”Þ~"¹Xf™'mÇøAj"yù4ÈÉÍ 'Ü= °aWÛ6rµMoÉ¿\m„üâjÛQ„L^½ÛÈû7 œ]±÷/¼ÓÀÙ{ÿòÈû7õ¶Èû—GÞ¿©'°!Ô„4t\AP"½Ý?شήovê4„”ïöønWÐB^~{Ävn¶dמÛ7Ùü5ŸÑH²Õémörßê5çµÛÂn) ¼ùDïÌ'à‰²¯GÂ4qŒÄn± 3«‡ ùNÿ<"¶ÎR%Ss3!äÕ•Í[2²E{¯²â‚ï{0\ŽE¸Tªí{•ÅMÄÈÛÇ‘Oèt¥‘_kqº%8òžä­„#!d܈“Oahô:TÑÿZÕnûö¬áÆ]mrȵ#+Uê"âÜCüÈ'WÉáÛAR§{žû”/ðAýï0ubókjd±ä…랥÷¸Ðà½èÍó´+Óûó›%œƒ÷™"FƒïîjæÅš{™²ôž¡qÂd5È{öZ¡7áŸkƒ%îh‹iÄdÑ2e&°›æ¾,±Àú|üD¿;,G-÷×±¡DH?Êg´m»N¤;z„¼¹A¤"·/žM-áã¸p'éz!&Ÿê3S#/i?W9X¾<ì6›\x)Ý÷²cþšnymåþÔ&Ûä0j‘†üS{¶—Y…A+…T*à§ènOQ²ÊɃÈjYòêMq Ëd)Å"‹z€Êwú¸Ç\ZÒ(*¦Õ·LÒ×Ì>†AêÎ'’ÛDgmË¿jW$”æv°Àº».kªÐu9 8/ï’ý=ÿÁóòï3}±Ø4;ض¶Dmµ~W|d/¾ÜfÕidÕaß™ïd_“mclo(B&ŸÊ1më„/Ò€Gó–?Õ;çö4´o|Ë´‚òÄc¹¸‡Së\óúA¾†­ ’¯IŸÉWçö„˜ÒPè;ÙZŒ„cQUN©¶!ó–/À ²ÈÖ¼a œEÀy­[&å>}Æý«ª¤€Tï@2YþwŽTN Neù²#P¸y>pYS…6–/ɦ½'¼ÏXüöü8ÌPÓsãNìÅ")N ã®YÄ#(TÎ&í¦9Žc†·”Æw·åB•©ßGPÍôÃÝ¥¤Xr!“p-¹÷9²¶ž™ŸxÔ7d0)¤I„¼~o‡¯8´o|'é@ ÙŽ7zÿ´têuRéYA|MòS‘‰U ‚÷Î%M1÷öDšN,'¬h*„¼©©³¾hö¡[iN„ô|´S›DÿË»n_[ù§‘à È×HÞ”rnú­vÈ{ÀŠúmYQ'“E³¢ÈâKÏžKr¨­î±¤guwÚñ:÷ÂØé —„ZE³¹æ…åkoéáíñãÛäGZkšˆ2>`sØ._é„/IJUÓTÛÃ" éY3©ÇMNšR!òöÑЂuðDßO>C‰'ähÄeM¦þ¯öÏ4‹‡¬£¬âXºÇzš=ÛN Bàš¡ øåXQ)¥?ã²X~¡°ö$Z i'Ö¸’]ߨ;5Ë(·vDÈ+jùÞš+º²©œÜïž%(/>e] ïCe=tT‹nAȰPkz¦¬LDZ@Ë!{5Þ0O¤ >ëBÊB^C‹MƒÔ Ùt`±™z‘Çæ Ö¶“ôMQ¬Ögv‹å=mÄ¢¹N#Ûúßýî L§».g³j¢«s|ÍGœ•Ÿ"“gVîŸýþ9+W‡‡ôçQvÿ’•³Q ‘Éçj ›#dñœÈ³xÒ€Í3@Õ1#U<àvÚ€ÍñËŽ$[î˜B.˲-B^ÁØ[*ªH±íþÙýyd%Ü g'˼”4b3?ªö×ý­ú‘ÂI¸Xd(Öêªp²­ë±SB>>š\6þ}fßÛl þýàáäÞÚ¢ÿ<3î]³ˆÐ k€æãl7™ouÓiYQaÖÃ;¢©‰ºö@ös‰øÑ•«­ÉV%]5ÌXäíSIB) è†CášÉ×áІC³€úða8´CÈoáøî߆CBÞ=¯SGþ瞼멶…7ðkb1ÌóD0¿æ&kõ# ‚#ä54 +ºrrrjÙÏ Å`Ä2˜fÅììó€x!Nöke'{´‰³ÛÚIÉe?ïS8`‚•ä­ÕÖºò`ãF%dÜý—1P4ÂÔúîg×!¯Xhñ ’O¡ÅC%§ùÊ^ã˜VÙåç£g«sßÑ峉 P³árýÕ9AòìÅŠÕ©J£óâyŸÕBfn^' d‹>HÉ2xé” 8é}z÷nÅ6 ½hs@Þ²²jUêXï²o*…?ò" å…²QÓÈw¾gl6㜹1rîxK÷ˆIߪpÙåŽ+fñØø ß‘' |03f€|éŒXfeÛ7ÝHèûÒ%†¬MC­äŽI¾©¿#¯Žù[\mïÙ®³˜ Ôe—4æâ™C[í U›´ÿ³K†™ª•3ÖÚ·eh~ô!¯nˆ“œrjV ãt ðO”áßÈ>;Óâz÷ ì´A«Þ]Ó4'Ô>oHf B¾8šZ²×m!Ý܆EöNîî,—e—{{§,lÿò³º¢ÛkPÑÍ®Áy„*º§Ô¾uð–y¥Èúw3åÞú7 (o­¡Uo‘qíœÞ=ÇÛggGH>pÒ=ÆFZK÷P Ò=Ùõö)þÎû7)Àž9»ÞÿeÏÜ"ä7)!¿Ø3 ŒüfÏÜ!äã“´öJî; ͱ±žM!õÙŸ&L ÝÎ*Hͽ»“E&‘ÞçÏ쿎€6÷Æö¢ù¯,´E|ƒ Wrö Yt` ˜!Bƒ©äÔM×½U0Rn‰{¦çþIa2r¤ÇÈ«›oÎK[PùJ Uéú2Y‚ãºs¶Ýl2Ýz¸.[–\Ð,H”sDÕ è–#\”6çZ±Ë¢>`§M’ÈÄÚ™ƒT© •èCÌÜ> å‰ô6"YrCvº˜mD;û}ïëS)!“7†#[ÕSAÁp$óV‹¯†#Sh8’Õâ¡ÉšªÊ²y›â(ˆŠj×ë±H#ôç÷½'šÊ³ ‡j'ôÀOôô¶²…ÛiuŒ,%|ÅÉýÆ®°æ“~ŸŒ-ø¦R¯©«½€ap~ÿ5™©Q*àݾ´SÇø5ÓèŒ3:LLO5m}[5Ëà±­¬ë¡ðN­ŽHg•yÙ"?Áiú†ê{ŸWu „Lö‚9aéÐr¾òÃ]3`)DÀyù¾#äÕ#í¦ØLuYñvZ\u+óÂA–h<Ö©¥   Ý~^:õ¦»ª‰€¹8òîg¿Jk[®‹lIYõîwØ¿í\¦³Ç;'<€&›Ý.ˆùP€½h?hó«¥…3Îó.¡£²´ÔÆ–pŽ\˜ÂAFDº¨œiý2}±pÍ$þýesís¯kU®ÝÅî~ÍÛí³­,[[ÙìöU¼P‹Wih;å Vî‹»½Ø^4uc&¥š¢æÝ»âíù5¦¥¿{<³Baqq,Eo){ÓÚ¸NÒÆÉ@e÷¯qÝ,AÒ6»ëÔ·âk&oèæ¬œ«åXÜ,r0 œ•†ÉexW¶ÍPQˆî×è{§öì8Í0;B`· t,~ýþë:8éËÌŒI7aœšï‘®_œÝïÑTÓÙh:ï^¬G³íƒÛ“ƒî¿Ý—*»æ»üXÔAg\Ðýw“»†õ¡ž¨.W2U5B&s¤ÝëÔYØ ä¼ B^?D³Š.à‰îq.c¿#Í9Ù˜þâòϽ>3ôœ{ãGÁý y úé 5Ügg¡âÅëD,ošž(EF !ó«ðS k)Cj ÆŠþ¼{±Vý‡ëeAOÿ]nH|ôôOž@é:Ëú;Zê­‚ ú‘¡ù<_»8+{['¡²÷ðöšorXÞ-o>±|79¥¶Ï}iè{…é,ÔÛˆÞÒ:£·òÞ=;‰®ùåÙ!þ|^‚ª»î¡”vüIý­h椪,òŽ{Ræ‹Ó=©²„ììù=Ó?:¶ äõ³Ñ8DA‘½2¡Ñ¸E~3_ò›Ñ8GÈ/FãþÙ,£W9ã]{ïíqŒyÃ\£ª¶2z*/VϽŒùWÜ+·³³*b¬ùç G¿Z(ê$TÛyåwï4‰M}Aõ§nc¥’â&Œ³[‹¾20¡²iœ­Hê†lõ@ƒkÞ¿Õ¨+õ~ù@Ÿ‘´®æÖû y ñ¾š ûR Ʀfѯ¤+1BÞêX Jur©€ÅPfGÂòi©Ñ@Òò¯P«LÓ•,jµ…H[Zdâ¹…Ž‚©b0­]rèy{¶lËY´Ïý2¤Î(ÖD€ë0”*¶k™½(8¦“ÖU bÅËñk5µZ=;F^ *j>ã“1Hjà‡XdòVP2QÀ8n–}Ö L Ä„³,-©åÛ”¢É[¡¸ûõåì°Êpl˜é¸°‡d×Xe2{v0š]! „ ,zÀãi¤·1©†jþÚðÏ;{|KGá}Þ"ˤúls£ÃZºó(‹Þ©ý;çq¦bU8F^ƒ$;(ÅÛå8ê!ƒZ›\`»Š•rÝ7EÈ›ßi]%¿ÕLiÛ–ðìÁ÷®ëÉeiÙѦ¯]J¨ÆdQ5Û‰Ý5¦[Í‚òŒ˜·n„[Î DþCã]Ä"I„ü< ÒA!`hØXђݵ?ÙJs U¸PoÃ2„k£‰ÒÑ#WñçQ d¸’Mr¨®)©®öë÷Î ãi sÃyï;‰!oyÝi§*µDàÔÎ2¤¢q‰™¼¸'s¯Bj7 g‘™¯95)ã’vLL{MòÍx‹‡À¯?/Z#±" 5QÈËEÀ+:äÿ »²]Iq%øK§ ÖÇy¿#õ|«ƒÍªþúkcgK:j‡–BPlv.‘þiþ·õaÓ$°3¼SxLº§9ôÊmÌÏØç2Èø]8-ƒd&\óÒЀ ­ÀF¹éÔØ•25ARhkUk™òyX+@^"È J¦Á¬"l&Èè#ójVy4}Ûí‰YW®E½ òNuþ¨}#ÈÇ÷1ìuG>¿êë˜ONòuT—ž•Š2ïÓ ÏèòóÉxwY'ÐŠÈ /¿ l×€Œ~Ø–ùi`[ãÀ6 cÂcÙ™$‹‰ðŠâ7ì)7e`öMi¢+Hºw¤ ˆpÅk±du ÈÛQÐKíÉZH!ÇÖ÷7 ò~â+³qµ±wéí òqÜ­\¼4¦ Kõ"˜$Èg[òl‹T·ºÍ%cV76êði>Ïïç®ÉúQÀòœ‚]¢ñ¼Vݪ:F!+žmcËæºV¾Î¬I¢Ÿèç(1Ã!¶a=_tÞ2‚Üó£"ç0ƒ#x©± H\Ü´N寰¹y™¤·jäûÅ[Ù{û«R ÓM›òt«·Î²kFšý½7¿x^÷+о~Å LPä;«ÁM¨²Vƒ&ô^2:N¤ZÁ A}’{cƒ¼žt(½}¡Aê>i{<æí`à„kx5©A¨Ù¼øð†Ò¨3½íśδ^Agou¦•t¦¿­Ïë >o’%h‰h’Ž4¯›¼¡ÈhÏßASÔs9˜ b¿Ÿõy%H}¨~ê¹Ù•6ZuÂD>Ñä[ñ¹¿è—ƒ¹R+“vXR9µôm¶Ú&hyÞšå3[‚ŒHÄ⦟Ԕ×ó¢5œ=¾œÎî®Èž]0Ýã:§°Ý—iç+&“ô4UUdtæÂ5Ž §X½ƒîÿß·µVZÉk6d0To¿ŠÑÀÓŒoßæ"•’;ò~ª‡”¾ÒÖ:“r˜ 2 M‹ÜLh?j.WïÀ†éíìÔ 2°H{§z ‚,ù$â>.-ænºy#ÐçøÜ_§õ”ô(†våš ‰@(‘ÏbàÉÊ3‚Œ÷ÕÛÿL»wUÍ y‘Õõ‡vB$WÃ’O ASEÀÉ7H5Ìå¾&v<á\O…V­žæõ<õæbïµÓã· JHUºm³ÉÖ±J–…Ãý¼¾ï UØà]ßw…*ì Éš i5ÆYÙj̺æ EÆhæà v]²z’zRy -;ÁÄ™K5•k‹wéz6qÞºÿ²,ú¦#ÈèÃ1[sLx—®·_Ž™ ‚Œ>¡zºŠö°^é¶Óu}X³Ð*kæÈcÏ”mvÓæ~ÖTÊÜ{È瑯x`6j¼¢×/ÌÆý¹¿>00é1ãÏ¿SÁwtû9Õ½ WÛ+ùºX‹D^NÍÞyµZÕž žæ-:)VV•ïÜe©4Ë"¬É7:³lWÚÊO¶O´˜ ‚ $fv•Ö©bK—÷ñÝ®G.÷\¸¡XkvÜ– £ºò<›p¿Ýß&Ì^ñ!¯Ú¥Ý#[ ¾ï#ßqЉ‰X†Y¤I&gÙ^Ùkæ ³³ S5À½Z˜µ¹¨ r·Þå-ƒ–*É™ZÓ… cè„nÕÂç‹Y3.ùF¯ÝY•<‡!à Ðig=Ö6¸k<7{Ü,~Å!OàϿlj~“{õ’èçþó›=1ó~ùepí÷è—ý3ý{ôioû{àMá~'pá„Ù´Ù=p×x¾ÿÎ ì¿ë½SÈO÷SÖ¼†ýè~=î2ør4k?f ÖXÎýÜW¢†iaK½ÌA’ŠX7¶µ‰¿³äÎ÷FÕp“é÷™Î’j$ÈëþÜAåÚœ}bCÊzA·Ý¸ø`\ Ö±l­ òNêŠÌOçåë —œóÌñ•./.ò¢é†LfA>C­e—˜ŠD•àÀů])Ÿ;Pó†TE)´L;zç>µêMŠ„½pÞ•ÎywÅàûþ ­ú}(ÔI·$+ ÷ƒŠ[î:¶Î¿°0YôŠó$öáù§í\&Umþ3dôE#ÎþøùE#ÇÏÁ-µpLQnf•Èy9. Xd1ç®Ç6+ rÿ…Ë"·B-çS#gEñR£ó®¯0okOÏ~ ®żXj›=uJ· 5óu;bHýØ-¨{·Õº3¹L2‚|ìeæÉš¼çªaùTCðýˆŽw¨$öwòš³” £ðwbÑÊükÇ4#H¢Þ‡W$òšó–óJ›gNÖž·jA÷nƒŒépµ]C|;rZ+&\DB:Å;b%ò ’À‡í@U™Ä¼ð&”‚·žñ~›!¥àŸ:æ›Ð&I˜Æ´lpaz<>Êi ¡œ–A>“Ó’ùENk¡È8 Øy{ˆ¦Ïc&^Ãßù:Éiyzôh²È%e%EF¹Iå7Y§à¸ Èø½*sZw ËÐekÈA`§j”›5AFÒ–䢥”¸É=èÀ¶»"»qr5`‰÷óI)שãðlô¾ueºKG·pÌÀ õ+³€Î©ÄÐÿùCZ8¹%œ<1I¬Z&ÈG`µçI–q܉yYJ‚|Ba1Þ…={ËÙÀ±´÷ÜMO†V20´2È£º¹·{69ì´ds¶àÊÐ)v½óÏN˜îÊ®Ì2 Œc WXœŠ¶(ÍfœÎÃ`]Á¼CXÓò©-e2äGYîà 6-kß³i‚¼‘R>úÐólY°)Ð>þþK·”Ùd'†or@û H HzL|ë&›?Ѩ´UÝÓc^?R ÖýM¾~ ŸÚòkmV\CžoÄû|C.Bå9–9ž·£½› ­äj‚ä&Q¸zïÐ̱-4èvÝc†Àf3ŠÚÒr{ú"¬’DáeÔ ]ŒzJ¬{v‚Wô Ã^Î ê[5lÿ6G¥R/q8¦&?"Çh”Ž’gëZåI­AøÕ ŸgÁ5<³šLk‚$Í ·Ë˜cd=ñYîͼž}¢õ\àÙ_×Ìk’kË6Òùæì6Ðs}DÆïJ‰E²ïüåç,¸¶K³ÍS~@¢NÌÛ*™ Äd(ªäåà8¬6³E´Ë%øŠ‰”ƒpRj¥Èøã€G+Ø% ’„…¶Ðð¸\â“噳Z»‰1ó ûA>@;ÂV527 gIÓO™Hðw¢ÿþ: ‘ûŠÍn(V$ª2¡(ô’åv7\ºfÄ•á ·nÊ‘‰n™eÈÛgO-Ïå@:É6§D:K\BÒÉ?ǽ£–ãšâµ?†•öƳmoV<ÉVA_ž»2ÞwC ȺVB®Çßù"m¡,G#È¡)3ÖLÞ´<ºD'Så×Ï!góbòMØ;¢ËAòlSéßDy[¶]¦AF_†WáÚÚLJÁHDž…$øV¯4q²Ùj™ÀµG׎=Ò:öäMß"òöÖ˜Ã0p­ái†dŽбgCêEŒSSÁ÷=N4n_æŠÊ„×H¸¹ìÔ‡í߬îœÈ`µ&cš5~$ˆG§iéÏÞOÃÀzÕOŒ ß *ld¯ß„àëˆß˜!n=ÆÍ/ÈüÈË™’µ­Š%K ¹ö%>´–ý¦Í«bÑ5K‹ãøB ‹Ø8ÓɼKbÕô˜×½Âã7ØjìMÒ5 ¹÷$äí‹ø)¼!qô›ø)"ãßÄOAF_@ñ˜×ß@)2ú"iŠg¿ý&i* ò›¤)EÆ_ä\ñì÷ßä\%A~“s¥Èø³-2Ç÷óqlt9’ϵèLÎßºç© \ùئ]Ű ¸#„æ`;[q°mä „‡ã3°Qe&/ñw>Ò–ÌoÅYcvíI±¯ýùÕx`¯Q_îßãßPd(rÍ„‡¨õ˜ôuQµá/a<³ÁÞ&¸ö#±¸õ“ƒð«¹úrÂ=îqù0´,ýÐ2ÆÞ{÷7"wkHߨeº„•áq²ÈòÞhbU&1A ¬Ÿ@pÍ ÐsÏ(¨L*Së$©2ÚWZèbëÏê’'Pƒl·bÙ3èlj´çù!ÜZ «d¯ráÿ7#Ó)Æ!“30ð“eV¯¤Ù¯ýNFR==z{šKWOMÛàÙß׆ì—t¯6æÖ“š&Ý1–ãòü.¹›àŽôÿÙ¢‹{d>—9VÌž?ßDíçšc\÷¤#a¿ÃË=ú}FŸ©W“œ"ôÜ Ð—\Mì2Ïøƒ¼ ðyýÍ~!È/ð‹&Èä`ÂJi¹ŠÎ|"x—n„.™ˆlÊ1™›ñ€Œ°gJGþ’rÏ‹Ÿa¾ùïÆÝrT<ó©3³ž%kJ×@ø€9:oU¥c¾ò ëÞÏ© ìÐm7Ôfe„ÊIб¥ãâ>G€qq@FŸ½£ñ; eþ Ím!cÓˆëÒóTWd0¬>‹l°Ê‰€<ˆO¹ò’Ý;ø˜‹ÎÄA€|ýœ;#ž•T)9›[ ¿3èobgÄ#‹J¥S+)ò+Él#2:™C”¾%úºÓ0Ü.¯CÜM~4™x):<&è²´NYCÓuÝbtñ¢ƒvapÅߦ™ÆÌÊ’d#¥³vèó¾‡=nïožŒÖ† ²ÄÕæu;î›t ùK—×ýÈ[+\~dÍŸ¬ì-®ŸáXûÿþ8»µÊ™Ò™„+Ñ :õ— ¿é+ù¾{¥jn²íFVP»Øû›`_W¹ïHJQ UÕ*íÑÞßÜ‘Ì#›an+àœDAÓÆÉÐX¶KH•ìÈ0›øãN.“%\˜÷I‰ì”ݹš“‰ò^ö±1Ó€ŒßX}ì²JmqrôsýšõÌ×}r@ÞŽ‚€V›™kô°¿Ga/Ò®!%ZŸ®+K9OTFq8N査äsf/°hÁ žzÁÅ"– ÏþËþÎM‘„v뼕„Î:¹âs+ä[þ|†¼Mš%]MØ@îqr£¹J]z™?@Æ €§y‰•é±ÖËÄ rË ÿØ/®„C³&ë”ëd¡Ç¼}Îø4þÎ×þ’“ùÓ:ËV¬Ea/ÒŠdÙAS'¨jmѯUNC¸,}Ïšzrÿr‚Œw;çÞÌ­4†JY’@<ï‘×7ÛM•u»®A^>Øè¤y˜h£ È@¸{ó§Y*oÌû ßÑ%"Ö)nTÉc˜@yÉ€™]Kj²2R“@#F7Z=ª:žýzŠü(‰è•˜,‹ˆdDVL€Ì2,Ãûy;õ¹óÁvš&žg ïçý7»J<æãÀN)½Z¦Y½ù’™èbäó`šX:E«J±<é³UA‚é`Õi"À\Ha^(‚Œ‰l t™îôÐ ‚¼â:¿¥q¶&7<±…Œ©"È[íz†›ªÛj©y>ywÒWˆt ¹¦5Èòñ®ÆÒ›˜A à‡DÊûM°˜-%ÅØ¶\$V$ìE¸*‡¨XÕíœ(‚ŒÃ!1Nàºëìù=2¢æ¸Ûû Õ-³â'²é 24j*5™#ë¢To²w‰ÒM“&=»—:sªÊµ^ òÌœœy-ó¶0wTå-AÞSO7½jv®IOó’á.v–·:ƒŸsµ=ý$_Æ2Ó(:Ž*žó¼ 0¥s}Ã(ŠNã:•«],•ÐuŠã:¹»µƒ=ªZ)ä5DÂ`ϺšÓO#EÞ‚®às¾”KÛTy¾ÍÂ%(&;³‘›ìé1»9ˆ`òÖŠqgìpEOÜ;ò̹jrµ¤ÕØV}‹oH|†ó=5êÖì±=ÇDQ|Xëò’ûÜpîºT(¨¾zdüÉÒ©K'ƒ¼~aÍ…² ïÆÚ×ý˜÷ãd²îD­ª©Åc>#©›ø6¼Ê++(ùü©k‚ô’|ëŠ#c0ŠÎ6;3§ãk;áý|ŒWÝ×±!;+j‚Œ>웪Þ÷Íøkޱ÷ÞÓÏNá¸*ÆÑIˆÜ­`VÁ·ÖS6Â^Çg¦½—Aï‡Ò¬ C ÈSíÂÇ!V^Ç|ï%°:£ø`â{ ‚»tè€Ûzˆ2»6³4ÿÏ~“k;¾Ëµžýñ&×¶¿rmÈߣ°³ì˜˜›ï0ß³öh=¬´ñëÈ·«ck°2 ˆhDן“Õ±+ ðçŒÍ`,Èè³e#F× *ÒG•K§ˆ®Ñ›|Ó.Ë.ßäß]þþÿ„]Ù®«<³|¥L†Ë}ÿoiŸG0368Ì ïé§nl†DëjI¥€±{¨®ZtlCvÖNK¿¤M]Ã3"¾]zƒ z;C›—S·xHŒ*¦ú¢‰ŒR§F®’ÜC†ç&¾C‰&¾é ¿nâ§ÙÒ¯Eš) ƒ£Ó ¢ì‰±·’'³yq;­sÓ'{_ÊôÖb#ò5VTjÃxõç×¼ƒ–ÛswMÐ9‚Ü„‡ Pp-Ê٘®•Œ’1¢&Î^§«F‰•àÔ¶šm׬ø=ßÞÕM_F+ ñ¾ì›v¢ÌCнÒÖh¦RZv´[E¾ybí£æ"•µîÞ[gy›1Ý*÷Å­w\›(kŸa>“ÛçÒÃ…2f›‹eî x‹£ûN(Vœîê~½ë:5À‰Ÿ¹³‘°Eù=—¢Ÿ?q‡ç¦+=p¬ä·uS!’|“Qs*ù#=°™˜ÏŒ?É”¶øÜ£½4†[÷fªîW÷«¯ 2 ´´<æpÍ»‚ÿÓæy©Ù“E\c ‘Uô:9aM´&϶ÕTWú1Ÿi®ž¦4§yW÷ÂCš5¿üƒºweëÞqK?ÜC’m7µUbU£NzVƒ8…EbT™$¶X¥ùªN‡±É<¤UêX±J2:Ï}ÚùŸù¼4fãE¿ŒÙÒÁC®¥(L*É|3[<ß#‡•¤ç¤R;—.¢Ì;y€À¹é hÙÄÔV9V¹'÷ª–?{ÈËî*cø?î_kª kªÁ÷ûm{ÕHÝÕüÓ5°–\Ûƒ6—1K>N‹(@~dRª¯mXϪ¯]q±@ï,x£`¥/œÈè—p6÷ß„³™‡ ¯Í!¶ûùØKFâdwÇši]fx;œ9}œ˜¶Ü-ÁÒ‰vd‘Ž„–CTüdÁ–x{Fí,Ë `ʰ×xÒÿî¤ÛM*žô¿?AéO*O_øÄŠ‘Á/+šÞC^[ ‚ ãž³z38så§r™t»:Ùɨ•W׎SÁåùké]Ø­™‹$>5AÛz)h2yÈÈÕ°ls>ÉïÙç¢ð§T6E'J™ÈfN_ûÀ¼ý8¶šùòb&²:ƒ×ëbWœØ$£ª¾á>2Ü„öÒ $Mûzè r™Áë}ÑçjÛ¥TÓ)|æûö=úÝú\ŽTýáì ò›ab%ð¦†OÅyaÕ½ƒ q^¶ç Þá×Iùr‹üßärR~èÝIùÀé•ï&啟3)l½ò㤼XœIy‹$—õ%Z»ùŽ®"«!mŠb‰|œEAF»“±@Žõ÷sW9Q1C^£•o•wØ©j‚¤~UmÏ}/æåˆ:uJÔ ªîáíÀ»Ø:¡u‘÷Tá,28•Z•üÌÜY¤“osÇ¢j‹©ˆ²_I`þˆ¦È‰¢ÝЩšˆÿ=£­g Ù„X?2 øL]é!.{zÐù<¼|äsÇx)‘ñÖ}éVjëUô× ï•swÚ&€t"«3C”jÅûz“5öä‚SæÓL1ÞÏ]Òè]è;ß} ¥Îë#7ƒ.TƇle¹  óÈ=0¼ öt*d@M©‡$;¾¢Š—hZç Ï!3µHW¥4~,2¥¢…òìŽ=äcëà”–2˜eµ< Û´H=äÓãÛ€ñ@1³#ÀÐvÿÏòm¬ dÛU´†ÚC:ÓâšW©Â2ô”ÑEòñ¦{¥ÞŽÌGÛª›²O5¬©‡$hÕ‰ú6 ËTŸ/2úÂ}ÅU÷øÅ}eò’ûÚ#÷Õ"Ã+sÇ­ûÞž'HµÕ)û¥Yž›#"_g3}çcylÖÝÈ<äU^<|úm·y_ôßµTè:`!¼ß®úïÊRtÙúïáývÁ³½ž"ð~ÿÂlœZA;D;y™Vؽí—9)~Ïð;«OÃðþÕ,S¬t€Œ~ )ìunOߨmX[‰l9[™5‘Èç^(ß*k*ÙD¶ö d=á}ŸËÈ×(·t3ˆ´uð¾·ÎlXpË­OèÐ_ˆÚÃ] n×¢ö̵zÛÖŒ‚RWÈYÏPÿ ƒûE¬ˆuZxîAð«N+<ä—:-0ÃÃÀ¬<ÌLˆ ¿±¼ï;D~åƒ ÑEìe(s;‚^Ç2-äLüE¾¬ünV0Ê|dpµ–ø¶–‚sÆ tpxWâg¾Ž‹1AWK±˜C w]Kc…¨§p–U3 ®†·Ýä,h6Ö¢LÊ^Þ€tª1Ú°æv²Ë2¬ì…áÝcuj£Ðʲ¼f¾&1F,a°cïCƒ•CÌ^Ò ~¶«ç;¬´{¯ZÀ4Ç«“ãÙQb¼“_îRíºéZn¸«Zicï?VéΫOu¹ð¹d2.ÍÀâ…Õ5cmƒÜ-‹$ç}™\õe็ÃsiànM’aî|d°qáräQ³¼åŸ z¦¡;·»ï଺ƒÃ=$që6æ-V•½.î'<ßÃoÖ§È*ì‰UÒºbdåôaÿª•œ‚;„²}-ršâ»éôaÏ‘P_ >ìbæauù@st)-;œ¹ ÉÙ3^åóâÐéØžÛâ{ätl}£zæÕK¤o¶±×1ë((š†„ü°áYð.EbǪV°žBo"tú›'ÒÕk2 üíχÜ7ÇÅ·cg.®²³ª4‘ê˜|dh“ã]zŸˆ›Ûx>›åÏ…‡ .ÅŽQý)Œn' œÆœl¢Õ03ü¢­¸Ø¼ÃFAiÆ—zŒÇLxÈàB ¦ßø6¡Û7´öóæÔV¼ g+°âÃ(üf=0†k)òU•äJ¶ȲÔs8n=¾EwÀ0ÓbekÛràÓ†QäÅ!‡ÉšÏŽèq5Y£ªšyŽ:¥¡#D®k€ºÿ®sXÕ/›‰ÂN=¿šã Vâ/zØ)Ƨ²ž1Và»éôÎl¿ÃúÜ1žÍ@»®ò›A˱ÊÅÑr Èpëé3.Ö[²žnV u1Ì7£·cØóÏòõž,Ó¸sºÖ2ºÜm¶·øqÛá ÊµªË; Ðé²aE×ɵGÔ¼ ÷k»‹vP¥†;`†eŒÑÇ=¨ ‡®dùÞ—jsÜÉCnSE‰Éøô‰ ÿ֮ǫÿRÏÃØÛ‘,s\˜*8ëuCϦ¦ŠLœÜ¯ìM„ÈGâ<‚ZÉ FðìØz|óÿé5:fBîÜŒÒßâ‡cĈ3ŒšÑšÍyÌ+T ·Ÿ™ÆÍõÀŒŠÁêJžq=ßVÈÓS×Q¹¡Yu+»¥È× Ö¼;‘ºüq'ªÔ[<Ï%æG÷^Ø}¯ {Èó¶gqƒÅK×b˜j`6†Ï}¾™›ò’ªQSQ5[Æ÷ NvŠP" Tè Ÿá™¦¯Nö]!MÕÒÿéH³qûžÑÑpB?$‰L˜Œ©qW|ú5–w›ú“2&w¦ÏÇC†_Þb¼Ÿ_o±ðÁ¥ÖX2KäóBëCîu¢w´>Bo&ô¯1^Õë3]Vy?+dɆÏ×î~fhæ´eIûZàý|ê z«Ñu†±k«¦ñÎù:äŒó…M_>{åj!Ûym>•<ÆKÏÍ,óßîiÈd.QwÝ‚uÚçÛëËœ0Zùºª½Y†Û:6˜Ç¹½ÈS†[æ#‡[h©Sž®lIXê#¯n:wáëÌW׬äž\ô|î¡zðr¦°5@V uí!G¹º4–cÚŽC_  ù¾¾ñ“e¬¼å/âÕÖ¶_Äì/Âøó]jdµžFVøz|ÓÈZ6¬ÐéúzVõNÏ*t»P=£¦‚ÍJ, ކð?]¯³Õl¥Ì¶ˆltéšÒÙ9¾r)Kr÷ÓŸ"D±7¥T_3 Õ…ðõÞFëCÞ§JÅK`4¾o¿¬£aÕ¹æÍçÖÑÜC~³Žf2<›ö¬£%2¸œö¬£yUÿX‡Ñï;<°ül×ÒÛ× Òñ¼™P¬¹Ž­üEÑN]ŽCÆ—~šó­jô~x³«qZZÎTI¯&<Ǻ·«£{®§ kÉé]è©úÈ=U±ÓS ß;MQ}nÚ ‹ª-i•Áú|¿÷ƒÕ¢é•µy?{ÈàZWX4ävóò#S÷ÖZIºî`~DœîÕó–2øÁ¼eÂCž0oÅŽyKœ)×½ZQו‚¡.¹…jĘÕð'jE¨‰ÿ™áQYˆe!:øŸI.¦´ä¾rÛ±’Ò2·Õ®üƒ‹ôÖˆÓÃr£KÜ&mÁØ2@vF¶~œ©˜á\9£­Vw¬™‡D ¯fÅÒbé{yʧ2òŒBõRÖF¡r)7¸B¢C:·ÓMµ|>8åJn¾±ºÓNLKnNi›(åTf…2ÇÅ_ôÜ«—T&®deÑq> läë‡îÖö™ï ¤¤ð¯»¥#+%^²n•|â©øþñ8{¾Ú¹ß.jl§¶Aî‹[U sh¦uÕÅo`Ojþß›ékÑÙjYÚNÅ,P9!û)W£–.ÑBé4Éœ ªîÄUñµ™)°Sªqcž5ä¾gŸ¢·\"yß´0-NChsÌÈØ-}Â>òÄ<¯Ôæy¬Ëðêá… ÇäGåêÉÄ5„ö˜utbx—ƒ.˜Û]c¥ºÄäþàýd‘Äñ‚É´ÙE¥HÌ Wv,2Ú2h“Fe]Ó®>Ô.,òq¡ñRm/äþú®ñ‘Eœ ß î!Ãó˜¡ubrÎÃ}À}…»äô }î+î«ðWÜWž”‹ÿ™VÙr±&u—”ç×,³bàבÀ=‹ÿ³ý#@öòÞ!œ LÀªS!e`ÕA]Ñ"8$³z¿#Ki®NÜ)BË’í»‘õE—Õ2BÃr4V•1ë—Ü¿ú&ªS43k>+†OS¶Ùà!Ÿ›ï2’®,bžo¿(ðÌiÜWårÒ*ý+üÌ£&óNÉvÚ€üRrò›’Ãâ!O”ÄNÉÁ"O”ÄNÉÁ"£ÓiÁÖ!NÇyVf¯:yÀÎ1ÃûùðÂifgêWQ¥ëTÕ#ìK[ößÿmÍk]V!”ö¨È©ï’\žÿG =­2ÓB¢b>‰l¦ÝàUCÅ”)L “àuà”ÐûTý8V wìhW×è#šim¸µ ãL¡Ìåùž•£‡tÕuÊÜ*We¿N(Ìðv˜ð…«Ëw£¢SSxÈtc¼ï)z:V/…·j'»×ÿ™ì̘¹2ÞózÌÚjõWj¥|˜‹‡¼ìñ±mOvglµæ å+-šžâì }Õ]á±ZI¼ei›ÕÂCžt¯„í^uxuâ×½3+b¡2ýR¦3+0²ˆÓ×F‡¬Ü,©ÒDE}âôµ•“W¢Yþfª},eP›Aÿ8}mµæãÒL#¨úEI‹8.ŠÂC÷4´½òa,òx‰ XÉ[_{þûOk°C Vµõ8§]’zÈàâê‹ þ BÝ[?wýŒ›¢ü|Vàðy1éYõ’nÁ»äO¨Q;n|…(-QÁ˜„ïã[\ë£^xúaÒd‘‹¹ºÉ;T›µ ê”G;Ú>Í 4éÒÏb{šä„Ë¡ßâZ¬\ù½Š!§\•¯jv¡“iâè<Û÷Ý:†«úgîLô|Wjª1ª$á¥&|ßÉN7F—TÕ>¯8Ÿ<_ ÊA9΀&Þ4ÖŸåyè!/-=Ï¥wÅžt¬§ÚC†›C&@j_ªš fîÙO~eVŸ¡fiÍæ„<üŒÏ”8”†ð: Oå2pEÍÛ.÷䘖j’ϯÝ™öà]z]–‹a9qæ‹íŒCfÔuÖdÍæ|*ØÈ{·Û€bO9hò¾Î !{Ò¢0M~¼Ä¶xə۽ˆ—àEÁÞ¡5ž@ÁäNÛMˆ ¿EÔ´@§NâôßO"j*ï¿ð×õvÊDÄËLõ‰`ªêDè›&Æï}e¼tiï#¯/+î!Qä9>¨ç®åÊºÏÆjâÍöÛ÷nÐGPS™ ŸÑ=„¸=ý?v³ÊÕëÈ“ÝCˆc.njªYÎ)í4ZÅ“­ûoó¸Òž•r`W bÁ÷}ëþÛjŒ±Ö‘{H™QUSÛl²uÕ!¦-ME\,kŒÏh7»ª“3ýƵI]|Iñ~>‚Ý©ZÝ-¹}«âÙú›äîu¢`cšLÉLÃüqúÚÿfpÕ4tÕrWn+yâ»:¶Ôó]%_w+¶žÝ¥ªÆŒË²p<ãk, ©Ëu¹,rÍË;…»Íƒ  Bª*ƒÌY:¥õRþgnn€*fÐ÷“2ÚŽÉÌaõÕ¶¯Ô[ÜÊô«Gåjâ*B[¾ Ä!}û©“éƒßó±Ë&ŠÊ·¤Ÿ4Û"wröÌT¾ìñ~¾¼ÎÈ‘ÝWâg¾°û¨ \¥;èŒÄ|,â wZGçù„Ý× ì#X$Ù®²JJ壎xXÉÏÛ¯]¾§ÓÓ¿Ø{y=c»íŠÏ½wž¥˜™ŽXÇ0HžÁw†0Ǽø^·V¬U:<;SŸ#RÃ5\z¹.¸–žä›CkÕñÖG'ª´ñ§ž/Ê;#Ïh·/FŒ½W™AO)DÔÏÇ>RµþÚê4äÅØ€¿6y>¿Ïkã”+q¡Oçµ±¹9GÿýO³÷¡s'×g§I`OÞxH¬Æ¼nßç‹öz^÷C¼äº®[míìùІ_Êø'ùä2ç…ê«mô½­íªšÁé:P Ñ´Õ­?l½”Fþ¯£ò€yH2ªdLÆý½ ŽÞâÊÇÖÿÌÈéA£­yF|¤u³×Á]¦°÷‘•ÓU¿ˆÖ`…lpÛëÉ­îs\ Zá3rYIºþiÇŸ,+©Çðåœïêêò҆ǢD…ÊbXA˜¼o>R[¬èzvÚe´c ‘ÿû~QW x†Š=dïúª‚53]"ŸVÝ×8†“ë«QMÔ*U2ûb\ÔX1s\_/¡ái:=è Eh\k°ã yö½ú="G­N舱ŽO5öÎÞÏ£·Ž†6‚6à ˜¨"{Uä¬Ô˜ê¥MÎrTj"oß3A7«º›R>ËP¿çûpu³ƒ©«³¢o! Š\XŒ㺺‚¬'òfBU‡1+mÕ¨›ºnI:èGnZÏé'0aQ* y.ãÕƒ“LJn’®L¾ò>ò´j$¼ªQ´ÓO>Aö€ü:}/ŽÈè‡ D¿‘ë¦zR9Y±Ó¹ Æ'õŽ]ËèöÜU$¶}>ÿäEo‹ ¿L.à3Úgàî]¦“ÜBxÎð3ß[/ò¯ugÐ5–Y(…Ú9§èööxŽ’ó•Ä"ÏùÔÔMÆ7õlêùÔ‚ŠEäLçýµZIæ4\‹žÎEEጋî>›×UJÕDÓ ì©è¾óN€G-Ï£:^J:õÒÄ6ô/²|0ù‹äËÞ”¸êÜþæi™ãow8f'@å§Ä«ï¹™UË,‡Œò,§bdtз1ÜBÁc66+ž‘Óßük'(]–ìÒ–ltßùVgÀldãšÇcÞôx?_/lðZ< èþþåÄ=äµßòü£»ï4wœÎHät}÷OîŸpõàÿ »²dgqf¹%a?ö:â¿K“0`&1E¯þj,Tìþú%!!•ª²2ÿ¾ëRËp‹ƒà3ÆîV¯þ³׺qÏ=4ÇâÀóe;û,Ã3ã3o { ’üòÆÈà‹s4 “_ÎÑB_ü áÍÿôƒîò›4F~óƒ¶k)øéÝ!ä7?hŒt÷dÓk)ãyê>6»Î§ˆ¥Ð–œ†áß¿3{ã‹Cûz¨zN#WHFá×Óª§×dΪ˚uoÒqd¶ýÒS^„ÓË›ZdômÍïbÍÃßé©P‚:DÅG±>3Ná×ÉÕ… Fôs³+Ùíγ•eío(+ËŒG@|®wÀ-²îêNÜ"Í­<Ž7Ц­§h;µ‰KEÓÎv“ÅNmâêw¨iÅnmâŠñRÁièöÜ­ªâ ‹»ïœÑ¦CÚTÝ ÷&ßótO›B®J•žx2¥Ç¯G¸TÔ$2eKjà Òá3È[¤â34ÜõÙ`õX 2†H5³êyâ,zOåô¡øï$p‡µÍâï|«rΗn)2.©¦Uš¾‰qf㘥ù<ê&]¨ûøŠlÊg„|9vìb°,k&ü̿ǙÂÞzöø(ÌÜPØmóUÅ_(ìl·í!Cwâ5R.‘nà"`³HrZ")—H·óÆ–«ã›~¥¹m8œK©A”Ò÷!^ry3‹Kì8¦+BžäKdmwþô+ŸÊ !c÷ ­cÀeXæ¹N+ŠÝ‘/)MžCN’ØùÞ+EÈÄ•QÓ »Vìߥø8,Å-ŽïÚc¥ÕßMÕ”k?ñ !]K§·•kÞ\,O›¬Œ£'2­Ñ—-†˜vÝ'ŒteE“UÇö’õ¥Øêá-y-©¹=Õç1M|ÁHdw¡fÄçÁXŸu–6Çï"lßñ߭ܧ|•m#œ‘FÒTÒ÷·–΀œ+ȤÊgÒfh-Ï CKÞJ¡0Sˆ•,\ùâC¦ß1ÙY)½ZÎ)·„EƒŒ¡% ÓídÆ7Ë?–îcä¶ÁØyKá…©§–”jÙ´n‹qt²ÀÔ,ECìW6aä!%Vä†BT‹Óh£ÓfíCbWH×4l›±7tcR•„!¤ó½ç:é.UÙ:sV!d膆Åëª/ÇÆÚDÅP;Ê-ºp*Å¥kî&ØÁ רUš`õžúe™+Yñ@Èð(ÌØën=Õ#›r–!¤SÂa•iÓš>ã²³¯±c7Ÿ|•ØAz5vš¯DsÓš8~}ÍqLkb×ÌU…AV^\º¾‡DƒÓŽ«ˆ¿93õ¸jSÎh^4 J3›Ë@‹™îö}ž,Z-÷ š”Ûïd-™c§q× ÍZªD˜˜¥PZ 2¼ ˜(gÇ$ðÅy}IS{ømŽFÛÀ3£Ûë™Ø—Úu«”[ºû dv˜~Å®î?ªÍ•Qf±ÌŸ®‘N1ò2õĊ׽^?ˆVv_"Ç…xŸ–]Û|ò£äñ‡gÓP$=ºx§Ý‘ªAŽŒ…9‹g¾ämJ«ã™7"K“Åíl/h¾"ßO5‰©ìÁ{íÒ¦·…CòpÅ»!gE*Î8ktg‘S3-s3¶bÞgúFÈø0ñU›¢”Øf㺪¶…mƒ$­ |ÚÝÖòø.SÕC«'yDIÂhÞ*³á}¤ûo)öi4¥n­Ù›jïŠ4-'„¹ÍH¿äDOÑô}IOᓸv0‹|~%Øcò÷úE¹¶s<Îf„šnÎtÝ2+ÞG‚¿›PÑ:·ŒZÊ5 0õ!•@%e–OKÕ‰sË<ˆchjr,†œ=fÕ$uÈaÕʱœ¥ÿm˜xöŸ‡ôíIÿ“ ¼‘þ¯=érØzÒÿ'ýoÑ4Æ!E‚è«4ÆH9ŠPAÎøîC‚ø«À7;Œ[M¹ÛØgÒqN§ÊC†·¿>Ö0GßåÅéÐÕyÿëÔC†˜:¦ÛŠÞ5ßiaËÀ$H~E,ðw>E, B"é+îSuSO¥ýŠƒ×[¹Í¥“Ðÿâ<ÓYÜ%áß]+ΩŽöGBŸ.yÝó÷gûä°B޼¢Ÿff“ÔZ¯Œ¯VRŸ„!ΖT{c ÌǬüÀ½˜xÒÀ*K _œ´“û`dpkEs|aŒw›Ü&jÅûd¼š•é‘ár¸o d]­D•ŽŒ/–o–RËR¶ÆC†wH±Ó6ïªåo¢;…ÙLîd•̽ø˜#¿§캡‹VRñw·ÈçIýmòu]6Rq¡€7ÿújB!D¢Çíþ)BywÿŒwûç>vhÿ<Ïû'ŸÜý3z8ïó$}U¤ƒm‡ ÈÌUÞŽ\ïÒ®ãâÐnd|aì?eªy´c¦SâÔ®ÆumVˆ¢Ø·÷ÆÍ– |GùÚlÙe=GÈàhØ6þrì©Ø¡‰‘Dä–¸6! crÔ‹-1݈‹9JÇjÊa%»UàKQ{¸EF¯QûÚµ'Ñ뛨ýæD¿Žõ©lÓrEGö¡ïÉVÄH|j]Зw9›y'Ögkß’S¾²÷>äóHœÚÅ UT Üt"°´ÈЯ4™Öšq’ü¥‰¥öë8j¦žüèìÉ’7‰™ÍF<´œøò欃·ä´;^ÊÖ@–˜Äñ¯Ù´ßQL~Íf_fsÂÈð¾½ùøõäG.èøõä«eøUK⚤^ç‚ìn¿î„_;,üJÈã»`Ð ¸íŽ6#¡Jàö,Rî›älCn²±ê˜øæíؽº¡¤ïki¡v¦òÍìB¢äÜJd{Ä`›eŠ`§*#ã²´¬›æ !C·¹š³Ì¦®ù»µd#B<¢•#a\Pãï‚8­‰FnØ„Šò™¬øÌU†äÎÚ¼ªR†À¢Ñ§ŠäßÉŠ¡¤ŸtþνeMw·fŠH{â;JÅ3kKœš©þ;íKˆŠØ2EÈè6YC6†üÊ@ÂB.,4JównõT,VN‹øm™2ú5cßß [ÛÏ!ƒ»U箥ç×Uç®Ïç½pvÎ%s-EÈÐAjnŠD¶œo›‡Œ®U+‚_1ql‰íY¬é}Õœ×}Ó”=B’«•œÓŠ3q_BÈ |›öÑ\¥'ŠE¾0©ÔYŸ²Ð]Ÿ˜M~}ŸyCÇ!æ[>’ÈgM“¥é¼%£UÉO?qn[Iâ14T¾Ne¢ªAîó̶Xd€Ö’=Û—wWÓqAH·¹ÚœqÜ/ÓÔqÛH’CÀNñmòÒhB‹Ã0ÿÐŽÃZJ;ñÅåº&Äd.è3Ó¥€ 9I<.‡bd)q4ÅȪªÕλ[+GDÕj£-‡ÍÚƒ§VHÝÍ’„ &Fk¥0§ËÐö5«12rX^ˆüÚŽVÆ c'c¸…’¡±nôÝÌInM‘Áˆx5ýs묭Z’$ò™c•&¦W¼šÒM<ÔFk‰'>MõհϬ[Y—!dp_µìà×É·z‡ô*‚%_-0ûÊòXHòÓlæè§ÙÆ„ÁÍßÙt»mþ'n­üJ$'Èóï”Ôb^òäØyÞl B®°‘É+òBlue1Ø3¸1@’·]q/ãòÄ„o-š£NœÅýj(®.4_½­AWíœÚO.õ›µÐ²@æt¯Š!ƒkd1ïìŠÏÈ«€û\8¸o>ã¯ñgÇ!®óªÕª%ÀÚ@ŠØ“‚(3qwM«§–rèö±¦|áþîXÉf*ûúáE3Ñã}rÃZ GmǪ†²®;kJ¸¡8V² c¡/â#úÔâ Yާ/öÁŒØGû?kÝôpçzb«¬´B)•‘hg¶ÖÜ&^ž<®”>5†¦)ï׆BÄòJN­ ¶a[K AÅáu¶´·¢N-ËšŒÃNë6_ØY oȸ"ת^æGsµdXÙ¯™Î^ñmìþ™<þnšpfÓ„c… ¿m/¦ï|û Í« ~=Äí£ÜëiX§v¬'„ îmöl<Ÿ<. Œt Ÿ¤|óž{™(+= Þ|%.ÛÜ’<ÈiìЂ¾3Þ€ zòøa96Ô€|~ÍœòâÉãua.®;¤­dVeùçeÈ Ëî«æjï²µ³6f‰cÀyYm©lf/q[|¯ª- ©Ÿüý}£ãþž¸V&úÕ›²ˆ~ó4Kk+R¸ÕUT¯½ xòÝTÀk¯ž•P¯^{pƒ Ž„ö_’bÍšNS o>ö2ùî¾Ô‰Cq„÷I¾°Sзy¶ÿôeVà-=Ïõ#måÕÌŸq[r[ÁI\q^ŦÐ5Šÿ9¬M;w-BÞK°’ƒÇ/Ûl»B‚¿V¼Ê/U ä—’ ¸Ù½kµ{× !—á9NV7ñOÓÖ3kÔ”¸œÿ𼢆y=1n9¥‰#;«åu+SrEL±Ýò‹}ˆ¨““D¬+êT;¢N‰S ´ö`z[êštÈFú ‹¼3UZºeìåûš-òyc^bìX2cÝd5kk¼jg3|ܯnnV3 ?ŒW½g†~cäšlaWD5¾³…pï }¦hY@6»éæ¼à׿|ï$Œ.¬§ô©],U?€ eâšzj†0³ ábYëþ½Œøñ’ÅSñRHòÕF¢™ª$L~ÕÊ1òÞº;fÓ¯+%û5¾égØ-ò$…c‚›qXÚ¹æüx&ÎÆ(qIÑ`Ý›ñÙÊm$Ñ)¦-a§íê] e!dàì!Æ A ‡Z6Ýq„ Q¦ÔŠO‰s«X¬,râTÙìZ²/â2‘VU ¿þw—O¶Yâ!/r€³ÍEÈàfÞ;JküÌðrì]‡Æ~0s®˜xY§¡FÆŽ¥=ì [ÓŠ¡Ø’Ø|þŽìlÊ …¨Ò­k$Ó ‹Ê4±i|dà֠ߦ[‡1™¬R„~{SË:B‰‘ƒÔâOzábt=BÆØÜÑ>³AïÓ©¶Ø·dDÃÅ[šÅ%rGÈä°Na&«YËŸÇþt–-³¦÷‘¯ fãhøŠ~ó jãhH5†ºìõ‹8l¢[VólÚ0O“ ¯ä†óYX^ÁÖŸHî„E¿ï4/ÿ]‰O¾ÁjÏ7„ î¦^F^Nh?¡ %¨Ø„>º´æ‡»yâ9#$*Ÿ%nk¹‡lP!à ÃKåDñ)å3ƒŒ‚3 ß<ª!ãs¡M-<ê~J‡+‰ 0RЊÚËi_Óy_á-=Q°j\Üäe¿™*.)vöڽ·‚*6‰ãc¡L &›¸D…Íh®½íV/VëÇGüðä˜Ñ~móy.׌Á[ŠG‹±V|SÌê²…Òœ•pI‰G‹±øèT•OHÜÏ?EEÙš"d|‘8æ¼ùaƒv‹—ÿ K‘ÖïÏŽ‹,¹°ÌG†®2¾"‰·Ô²©Ÿà"ÿyê«e¡¯‡o¶|X·~f MU0¢Jþ”‰ÁS„”+䫺Dg¦9¤)ë—µê?™¸ÉRÜé<×k¶¥øï|^ÌÑjæhEÈ×Õ-zŽ8~óç…‚NA¾Œ[ÿþØ{Wø|#u/W9®Qüö·>GÑÀ(ƒ˜ü…SÖó’1„ ½ª t ìÍ­%uâ(ü‡¦S ßb:³rBÈØ{¡â] Å<7[Zò!‰+v¢ù)h‘veoûê 2qbz¦…àŪ†ŒÓÿW“TšI*òuôêWÆn®ïÅ-R**`¤œ$ -sNb3:-3e“mַп«©/ôÔãÑÿàTX?pMÕmÀ·'qþo3?²*ª.K;ë,jˆª[™åDÇ¥?ˆ:jȈ¹3±7Y]jƒ”Sÿ¯ú–¤!£Úm‡E,’<§+FÆ )»©»–ÈtXò4ÃH¢¨Q™–D•¦Tü±CÈÄN¨*;(=ÈTÌÒ\ˆð$Cȧ%+Ä)㘋ýT òåÜ•ÚÁÅØ''7½@çÛD¡œÓš2ž‹$Br9³d…T¼ù¸ ;x„öz•£WÐô#%ßò¬Ï2:¨V#šÙ@ЮPcœSe´hÛO»qŒ„.SþlJÛ)§m–ñ옣ìµG™üõѽ­Öue¸^ô%ó]zÓq„ •ÇÌ´Š)¿Péæ+Ù×#WŽ*Å–w›XŸüzr£îYkuÏq¯Ó§BZÊQ­(Gô¸Î92õudvÍ‹ÿeéš§Ö•õ 0…ÆâM‹¦LY³"$’‹Òž4ûÒ¶MßuV‚*qÝݵêpa%{õùtSuŒ;ç(¿&5Òƒvm¾Û/ŽDò,•¯ïúÿ'ìÊv%Õ‘à/U~œ÷i©çØ¡ ˜Uýõã-›J÷¡u¥u0^Ò™‘Ê^ÓCŽÊ¸5àó°±~£-õ¡×øG±ñOY…À\zEGm<Ë9êËI5aU÷;…«€ó˜K`6•Î׌oÐ란~‘oêÝ€Œ~nåctŒ"ßWÊꕚֻ©NVl¬Š.ô¶ÅÚ(¬7,]ÊÖQ^×¹-®cx žìÌJ€wwäPO| n%€<EÏ/~8Czëbg÷¥–ËW¯vZC½>}¶MÊR5®Œ‚Õ,ŠŽr'@ÝË×÷Ø­l…‡ ?•äTs»’3;<ó±ëÔšW”Ž)éÆy㉇|zH#§ù;ƒ’¹E¾ð׋Â6) ¤as»ÑGç- ²mä¢Yk,wEÑ­*á–ànÅ·%s†%ó("Ÿi¶m¦X›&quÄ?'šÜ¶Õõã4M«‡tEÊ,¯@ŽüÈØ˜áßéúÕÿ1r'Ôz8Ïu¥l?j‰©±™Q÷®¤Í‹µ/ðî± Oìât:ÑSäu±òµd¥‡42vjÁ³˜%ƒ¼ÉÎS»zÈç•'̈ž0ùº–7ÚÇó#aj[—§a–§–Ü•aWŒo’†Œ5Ó;+=d%I“0Õ1˜JÁÊ×ëýg†§éÅT9±aÔ"ÝÄæXS4Nö$v’† ajô³9)mp½Çáq”œ0£ ŘÁu*øë¿»úï=aÖ!<63þ,o(}ûÏ %­mOßÃúF¢p^|× l*àŒsOˆÔ3ynèÜÈ/ ~w¸"zöÆY‹D¼H € ¼»‹–‰±m ùÄ–àn(rÅÃÔÐÉÿ;÷k¬§Óåm.pš°ÖCF7Ò$¸ŠãoO£ÿª}Uß!n㯥SXÅäké”{È›Ò)¯-2 ŠiS¹#+­\Sб`ïùcØgÖ¦!¹£²Q±¿;ôµ3ÃÕ»®i¼aèÜò#f¡Æ3·ŽIýZ‰¥K‘”»*ÿ17 ¨J•ËQâ€thL µ´°;Xµ4[–‚ hüs¤}—pÛ7‘6k¹ øƒ¾æ7R²e¥×EK0;´Ç?ÑEK0;´Ç?Ñ—–`á#ïZ‚…‡|Ü80@Æ·D"†žø‡›ÆMºPîÞ+«…JZ䯟=°ò… *fº®û ÿþÄR­.ŸÉ÷Ö0Þƒó­E†—ò1˜ªýŒDŠÚ9º:2µªb±C³ûûOëúÛ<à ÀuHðo±H3òÚ« vå0PŠÞ³±CÈ;GnøîGº•ÑË×§aÆÇl}| ä¥EþóòÎí¹ðáðœ\aôåk2|£ø¾©lÛ¿;9Ð+ᄥ唬Ë0fxü| c5­>y9´}Òñã¸BûÙÐ Ò_¸‡ 1JÏ3©jWÕmw Š]: Á›s³¯D#Øþw~Æ ~x;p6½ßÔGbÎ?ÑN/ªÃ†×•œï2ù±K‰Ó uUan‘4U¼†]V v¨fÿäê8Åt¡>2Ï"k@MÍtàS¹Êøñ¸’}éðصÇ8qßR¬€tÿè[¹møl¶VFô=ò(Fm–˜Ž­œ,™°Øa¨œŠÓí³îñEœŽâ½ãùEœŽâÈ?ÏȲjÖ²,ÊÅÏKq:UíØv^Vü¼§K,RxÈ3qºqºÆC^QÞ¹üúøÌƒÔ f [ž«89gûøyhŸ( Ÿ,£*«fŽŸ¯o®éøî»·ÓŠ}§}Æ7â5T¹jồ»³Cˆýìxd@sÓ)¦2QsÅt>¿릹¼ÏÅÊåYŒ»#¬63&#Q×yR–ÍÊýg†.íĶ`õÓ$ßž»dgêîò,˜å9äü-rÏf«æ7“ÌßI©ÊÕ£‡|]Þʇ‘Á¡Õá£í¾‘S]=m ÝðþîÊúŸ 7Šq²#ÏñyëÙÔ­îG®À)r€û‘+'qÚÖ…ëý(¬Ÿ—Öãq¨zQÉ ¥Ã7Šý x^Ô&)04Ó*:Þà-òå´°ê=òKCß÷ï¥yã‰àH?œZ/`}3~‘oùOø;£Ÿ»3ŽË3žéÔ7P,-!÷»ÍZ%óì!³X¾¸þš³Œ©”û+ž›‘SÁÑ^¾¶ÃEîuýªÿZùÀs–{ÍójbnæÜCî–0ȱÛ6yÜubÊ!fˆ‚3¡mªÝt•$9tÞHS²ôx‹Ú0ªtD þó_ßPçì$þ8 ¿ÄKx+÷­#X‡=¹ü³Æ?Îó£R_€-Š\Å¢xC‰ÃZË/3Mz¥&HŸI’êN3&y¢ŽŽWñ¡Î¥,a ½P"›’‹,vb§Îå4xëxI7x¯DþñÓÏ¢,`uÐa뺼€UhK›å»¢e×@Ð6i²qíðÔv*8g™|N"}ãÍ1³U6ѳ~Ø3ùNCyϪ¤Qa%~*÷šco§Š±{Ë›J›äM†­ñ^ÅXÁJÍHy±ä‹|è{ôÁÑTG•Ú£ ûóÓd¢jãª*#Æ~€rpùö‘r ÷Cé!ƒ‹gªq²3™8õŽ“g9zÈ`¯ÃêH@½ûZ U5® j@ÜÊÈé7‚½Ž8•‘“oDå72pz'rä ð¥LÞÀJ"X±Â|9¬#µ6ÞTžï 2ײ,fÍÛ4Ug2@:qIêE½ÔÛ4+âoç!C/¯hîJÆN^ô!F~žŸ¦féæ¡Zy1L€|9{Ô0Z·¤˜Ø²¦ Üc‘^O‚lÊó9©ÒŒ£Õ"ÑL"E¥Jó^¾Nš2ù@CDuϯŒßs’Ð*Iê!ŸžÁ¤Ù½Uq¹ÊºýïŒÙlZÔ&{uº,+K=dà7V’ŠiµÊ‰â!Õ­º!9÷lÆ7¦Æ~Ÿ!ç»ÛˆÞÜëȹ%ÔH‘mP&¿?_²Ùp×&‡ºÌ‰úè!OÄÐÙA üng»ðD9%"£r…286CKÓV2ôn@d‡8^è†MAm½ch­±8'ÄõBÿûÇki[k&ÇrVÄ©õÀÉR%“›í—28›~{bÓÄ•¶ΞÎÃMcß°´,ŽçãÈNQƾJWVqî!wÇc°Ä®Û^Fôã˜'¹‡¼¼õ좮ä×g\ ÝME3×ïºÊ J'® ƒ'8•ì¯#8B~£;SÀa—? Ïv¸é+\Þ̱ÿº#ûmf÷uÚæQÞÊKá!ƒÏû{;¿ç’ï÷wâx¶­•FÏZ‰85© k%yc­´úÈpg:ePq ª×Tž8ðFNõ L?‚2à*`j<¤þõô\‚'è’ñfÁá <‘a­Gñë†5FDW‡^pêäR¼µah ½…¡ÇžR"¤&öª¡OÅ Àz–/¢ÖÙB½ö4yOË‚uXâÔVË- {Ë+Ï6 û¯?}[¾¢€{‡Œ«„$<µú‘}fiÓ1òt—`¬'ÁËsŒ×î٦Ƨܳ—rÉa_ îq¨èQÚž¸.ô§¢E¸'»2ôa<Ç8•wâqÜgÈÁ1>‡„D¾¾SÎR´I GqùÌÊä¦ÌDÇ¡›¸b†ÑJ­$M2Ì}C7 "Ž˜…[­¦X­†Ü ïOPòü”I˜{Ê„ÇS¦Ò”|- 8ô3ïFü;ƒ/¼5ŽÏ ¯…Œ=Þ Ão²Ô‡ OÄúù{X9Cƒ >¾‰'âßù<2éižÆ7/åÅX òõ!2bUT¢ÄØùÈg]9Õ–S}Ê£¦ðÈòJ³Â^ §±í ç¼#‚oeè 7EõÙryÕ¯ß „ölW©|H¦Ÿ ë=Œ?ßHŸG¯›fìÐŽÑ"ƒ½ËÀ’£©Ê±tI+&^Þø°~D¼z܉ÑËYwòø¹—\1övkg§"Î8ë<ÁúÕæ~ÍýHå~E×௻ùäÈU4¥‡ °o9/ìqXÈ;T•-˜}%Ž¤Â om˜°rG\QGæF›,²lM°cœ<žŸã(Á‘òxÙûÈÍfžôyø3Ùïg¼˜«ÒC†×Ò£ð3é‡Î“~ »¹»Uš9ÏåËH0õ¯›¾zD~ë«îùÚW@žöÕû’ÜÄí«·RÔFÔ ÓÂ¥‡ôûê­¦@ªÕ$zÿ™¯3¡æ ÍG|+4“ „ q­åOÅV²ÕCÞH¨€tŽE>.f“£¶Èk Êü_Í9JÞ ‰o…fÜ7"·B3î(‘¡æÍÇPád9Ê ù¸–Á3Î OW‡šÈk¡æ ÍXd´?Sž6sBë±IäXä^­¾lÂèâùó!¶wÃJ^áe¸7”çïɹ ö.Ú¾òÁ.wâÌ%¹/ÕTW‰£h`åNpä¹Üëä¡(<äãLh†yB3Ämê?Í0Oh†<ƒk¡æ Ígp)4Ã<¡â4õ#9<¬¥t®<äóL>¦óäcÈ38¬#Õôf£ Ö¸sioê?šaŸï~!4á‚Mý§B3Žz Ù›úO…fM²7õ_ Ížzù™vùò ïäcT%–{Èàêƒîò1Ä¡I¿cÂüГÙ‹èøž¹|)p°&Ïǯ• •ñˆÈá6GNUKÂÔ²¢æo@¾>ÔÜJ»<Ë¥œ“mŸ¢¯ãÅZ¥äÍp[}²zÈðÊ?{/´‘gä\Ta]ç\nc6ç[©Úgü474…Üä5ÃÅçÁuت‡«ÐîÝWk¹õøîä@PG‰¬E—·böÁMÃ#Lû×UÃ#?4@ÜvõU«]éÊš›œU=úE‡PñÇÐö¬<Æ[^µëFþÏê!÷‹O|w:.U×±r€Õùº kÙ1¬uÿþYò­ù;ß-«³VžK€|Ý4ƒ”› ªqäZ‡ÐËGÇfë‘ã5öQé]ñï$§-Û5¶lãÁRÊŸ­åðÌè÷ÐhPQpÕL÷nºZôp1‚‘³6Hèù‡ðï¯n 0Ù5Å,¨äH¤9\$ÍÝÚKÃTh1T"Pæ#ÑóâàV¾,è°zH;C´¬m¦›³b–±rƒ»¢Û²­ý·ôf£ .rw#æ`Ž$ëö7%- £ICÑ u¨ä.Ø:L= ã/HLÙEä y w†øç‹êqo Á6§«nüm½dËz”Ä!œ—bÀOâãz×’*¤óÆRÑ`h_+h ?¡í*û›3Ί ªP¤tè[$ö.µ¸­Ða\óö:à5Dh·T6i8€¿Ëÿ@»\2lÈ3^çlòçmoVq7WU—ñÖÑ×N¼&\¶p²ƒú-¹oá\wõ[â´pBJÙdŽx#Í{DnâP.öOy⇵©¦ êZ/ÿM† =üL–êlºJ–²1MA*‹8žñ6Yj¬kÔ¹™ªd)ÆKħ»»íÀÛV¥|ÃÒ ÷¶z»/Éå"¯gÛ4%óÏK-ãFà»?¾ù»ã»Pè Ó'¦R‹ÃÄú7\¦È­3ÊÒ $!÷©ï¢Æ’‡C*°åÚ¶@yZÉÝhQ„{m6oþ¨® )ßR‰<ÒNTuÂÈhlUÙqaS"€ Îéî2 œkH?1ÉgÔÉgy&ä€üFì´ ‰üJìdÒiÐäÆkyÕ^òz$~÷¿ÿ]uÛÙD$’+’¨r5Á“ª²¤,.¯(‚wM*2ºQfh4jDç~î« máOøó¥eFÀ×t•ýO[føu§pyÞ°ƒ'BžH®9N]Œ#òqGÒØ=*$òù­mŸùúl_µMUJ¯~]q_rÊ|ÿôê(¬ø€Dò¶ž+Ümv½~h«Œ\k‡´˜†¦÷‘¡C“P'‡&]JTuåøbŸLR@ò¹ß¶9åc‡39Œï¼^9ð×Éi‹qm[Œ7H}‡?NAðÏ?—î®Zày6Mãè!MIîߟd;-ÂC†§-Huµ· Iäï}\GÌÏGpŸ=Q‰ ïrª ˆoôøÒø†3äñ¼h™Qхغ$òu Î9„ó¶YêdÄw„ ȘÑrš+^m6%‘ñI«¾ZQ­úò"U i[bÿ‚d¥Ê Tõ›Ë›L‚Ï@~3h È“¹)ÜÜÄoôÜ÷¶SSšš*äíÚÔTàÝŸ·/¦¦"45dØ»Ñî\ W6}RÁ›ß˜|,VÇ{¾èŒïóš ÅÖyKwÞ-ê¶”CŒ³ÃççOJw½ëé—öœtêqÔùÖ¯§]ß0x¾N³Š^0x¾b¼ÜEÔSÒä2)a yî:ÅšÓ³ò­tèûa ‘ä$7á:Kaøº>íæÛi×còÿþç³1²œzõ=å O´+Üž]ìŸýu0Øq Úã˜èUü +Øk×ñ.w‡uÒg1“M[€|„e#nðEõå,ñyü¼1…ÖEýΊ\Fœ'#Žƒ¥êî\¼`¤ê±îáY[ìÏÚ뮥ªIìuñIN²aùŒŒDPÊw– ÅÖïû{f© wòöÍR5¤Ø,UIö×,ðš87ßdŸ—q%HZ=„Šƒº)@zYK¶e- ¦Vо¦_hL¥˜ëc§O‘¬+‡ª x‚NàÁôÉ”-IÖÁY;0Ì„“©áÒ¤é*C$ñ,­\Nг1bIRŒ/yÙËæÖå¥(’,šS§!’Çü”dBù~†1ÿ~žô] ¬cùºæÁ"Œ¨w…„›¹ÐE@C>¬ˆüŒ‘­™˜ZÁâ1/ª:DÚ½ø_Øì9.Ú¨e‰ ¡¹ëd,Ô“GCxÍûw6{ÙñùÕÕY¸ÏíX~eB@‘D)×TØ 1ôÐ=QmFQµ,3ÆKŸ½<Æ¥75G=µ•Œ:ˆ*?ôÒ~j]q¾{Lþ™©TÉ1öþ ]sW˜™7ù Ü ?÷Pävèh»"òqÏó‘Ï]ͽiy…oþu°2!M+x¶2˪+dhù«ö#«¥.ª<o¢räã:gºJüσ¡kÛ“¨ß« ®øK!÷™ekà¬ÇR¦¶mÑm€$Gëƒ*´>$ýn}0ˆy?µ>žõ ÞIŸAñl;–¬‡¦$ ù¤ÔÖLÌŠ­š¥irR+äç2Ï…–ôæåLwyýœp–6yQV ÷ø&gÖº¶SASŸ¯Ò[m2§³ÒMd=M|M/ã Y£Èº¯šB­Vˆ"ž<‘Ÿq8(²úM‘¥÷½,¿È]9[]Æe™ D>q]‘;ãD&‡Œòyeæ°u6UÈ×~?r…j?*Æh)jÈ÷ÁêÙf«+™ª×¤ÿ䦻Hl‡`SvW±…GÓ é· NßqüîŸÐR5™zŸkÒ'©3Ü 7²ß¹XæbmûPI™ÂºDÂ>ôæ-1[«O(CTÒ@-.RµÒƒ>RÑ_á×$·`/6CÉ`«(ªçr˜Nwv¸95;Ôºå I¾Ì#Û þ€$8;Òæ;4RE­³$ µ¬uLß bNz!䤨ß~ø>*¹ôå ÉVÊ—»®Ø]u]ZÕN€ HúÝf×d²_“­C­^i ÇËšÃX"—k²N܉I¾ùò¯¹ï’ f¡¶©S×áúéçe ¶‰çMS§X…kK€´Ì³Ñœ¤™=¡h湨+^Õ’~/‘«K@^w‚Ç9@¿F®ØÓt.;Þ§"??ò\Y¾y]œÁDζg“™¶&–jïä-X½­9†µÑàrÍ—nÁk†f¡¡Úgâ r|IΑ…BŽˆ¤‡»Û˜Aß=ʾÝý~¸;÷¯9VY€$çÈnˆ× ùØq,:3<ÏÆe)óïþünó2x6/ y0¦Óä’1JÙ¬raÓc ¼ûC§Ô&Œ.vÙ«‘•ìœt+ðÉ7ßñ`eÖ ´2SÈÛN!Ìr(cÔÑŠOt'—%]%æ¹n»Ž¶{{ Q¦xÍûåì@Bzìë¿&VkwÉ«$/Ak¤Ï3ÆL›³MuËú¹Ïñî¯_&œøDï˼!ZR+ägÇ3˜€…û>VóR$0ãN²®U“þîó²}÷Çíº¿{‰‘êãÀ+º¬z'‚Rh…¤?2bpê¹=îã‘}Å‘üx¬$¸-»«ÖLÅÉKŒw^X¦‹M󬯓aÆú@ ‰Šêø 1ƒ¯!÷Î2U-øD;ó–̲¿j©]£KûNú·çŸ‘oÅÈêT®å…‡Hraç»Ì3ÌEšâ{*/óYäÇ÷é±ÄjrüYïjfM'T†,‡C‹-5åÃÄbuƒâOÖJ§ØžÍÔEWu"ŸÕŸë HèÖܳ«™÷9(Çnó|rM9ËÝÛfʇ¼·}".ù2kJ"£>e³[\žÏKã…~››_8jOÁŽ¿óŒOÓCÃA£n²-·£¶Ïž[ P·5åk3³ç&rÔžÅ9õ¶òz‡² ôŒ³ ±éÍc³¿b÷òÊ;Džb‹Ð÷Ðü JùÆz…Z …¼}Í,«ÐSÎ#Õ€K7FÙf "«”áÝ\:+3)ª|Œoéþ½Ñ^Q}¼]óqÈÙ¦NêÌS—}—,@†fŒvµY³.[†µ®$ýžmÁYüzëelÐee‰ÈVÉë¾Ùq›lKiˆµ‘ÒWÚ»ÖB<»Y´jºro” ùbsÖN«®Æk~6^Q&2lž­âuûA”0摟ÒÖ^©²Ä¼ËÁ’I™YR!‡DÖY,fàüò‹-³Ð<|MOi¿üû¯k9áÚ‚ˆzZÈàÜÞä`†Ã*^ŠtŠº ¾æ›îs¸=®+Õg/Õ …÷(íõHÞÌ–ËlÝžèqÉÂEòš=@óU…|]ž¹d‡ç¿Òi\·Âªøþx†ÂéS—Râšìéça·ŠV¹ª_9F‚u’œ4>p­[ §óUñg­[8r•ŸÛ.‹<ƒ±—TsdÄ»{¬Ñbl0ÝÞÑõb*êe‘y€tþºF6Û’hij‰òô­9-'uûÐ_jDzêè·ŒxSCkK…|\1'BnÌÉgomäZ˜&˜j0+¾ùë±T®¢ žù€î1èÊê;!׌ã7ú¥dæøìŸðün¼pÌ7â]¤k랈ü9XÔ.Úa=î‚øz.{Åž¶Î’lΊAó)˾ª¡’öI>ô9 o?Lb!'È—•VØ•¶­IßÈZõ«ÝpŽu^hyÿf–ÀòÌ( ,«ä‰QÀò~^,_nÅò€¯•x#Çkz¹][a‘Û¼¶®Dfy”öðÝ=î×·\3ÏEÜK÷û÷?cAñ¼qfë8m!Ù¸ß/Hœïž&ßÿþÎî¾×ä­ M²ÀÀähÁÄuæÚ,˜’üªœÅ»Óë¨r^ðš÷pµÁŒ˜X…^f£( äd$wkÂÖíŒ@íu¶š»>¨¹#31К ÊEä"_ƒG»ÒN|ìD3,C Æ6‰ñùãVÔª…cŸ%6œ*ì›éÒµK•ͬä[ü¹BÕ°B~®¹_0•¢äþçNäîÕÃjUR® ê ¯›ÔŽ9üÎûÞ:ü÷…άʶÆyä7Í9Uû€^‘Üé®Ñ^ÊFÝWvÑ ÈûQ£ks|CZ'"éê“êóÔ4*“f‘ø;Ÿ¿Œ¿`„øšüþqßÝž&жXŽÑÅý½¯Ï#Á«T4½„ #ñ4ù‡zm[™ˆßè0f^M½6å[°¦ž’ÇN‚ÍŽuN?ZУ@!öæ êL;¡þzH²ÍbÆí³ËHöe¹ðVO?ÿŸÉVƒâZí}¹Ê£t¿Žcží"¢™gÑòïd¯!·y;cËœÕL&1dšÈ ›×,Äâ_ó¹Ó3ä™ýDU²ŽE´ô‘¯¯‘ªv€ëV°Ç¾Šù¥K}Ö.ñÍJ<ë¡•xlì“Þ’Çfÿçœplô[Z Wæ ›íµ8Ô‹]U©(«\rŒ¨wî%¦ˆÐº¬TjrÆLbä:j`x@m^&êÔQI!æI‘)Ímb„K:©ù•² wD2(+ëš©•n.<½fç-ŒI~µ0î$ùæà-ŒyÕÂXÈ{ؘ~çÒ,½Àg§_Z«#œßÂúwþ;›+q:Õ5I–dš—j tûîPµQUE5ç}¹Ìò¾Ù6f :Që'k¦ºÌyßÁHàyë’Ü­‰*ºP+N6_Gü<Â_“©g®~“§ê Ûȯy°XäpÞìG1Ô+î2ÏçA…³x´ò$@R°—Œ_:s7ÖS»ŒŸ›øßbö‡¬ &’f‹¬ž;ƒ\¿)IZ•Ñã|ÿ²W®f¤:]ˆ¼ÊiµšgPÓ(³³uerWȯîOØ”™’]à _=ÕõhÈÉ®aɸL=b–K¨H%¯Ðﻹ걔e]­0;^ô‡²¹ ?;`W0Ç«LdVÎðæ=¥½U÷™­Xa[M픈‘8–þê4F§Ö ‹·Sº´NX#}“ëÀjõäà4B= / LD†šé'2³cȪᆵÈ8~£uYæÉ5TÈ÷n|Z™ª‰~;µ'¬ äg2uYõnLëEK!3Bo¿j… ¡·} ãÔ½O>̺d”#2TÚÛ–ÐèÏPDÕŠÈmepï3w­ÝºtRÍó·ûµ’$zûÁèbE½=¯WÚVZz{}Yiån¥¥“¿{"yx¢ocIMõW±˜g` ©ïäò\à‰Çd!‡‘Éé+²Xf{} ³g6J}&s|Üõ×u”è“)Ù»æÖNÕ«x¾ÌËÜ=wwW¡…¶‘’zOĬFB=QY”ê‰b@’ƒk¢k\¸¦Y’÷=øÛP²W¸™>¥¶á…HfÙãj³SÅÛ úåWÍ(‘KÈ™Rrª 2JQõµq 2ÈP3’©èBÂy“’Ý›óŽmªvXµuàû|£Î6÷1u‘•:˜.*¾‘ä[¥ì ‡BÉ^ulÉBã£;›ËÆ<ÙóK¼pùÿ!]´éíÂdèõaž}bc—¨¯^à›ß·kOa¡×qHS§ÀQúç4š“Y=V€${žÁŒ:Ã3€¥·k&šG+$9¸.c+E­Î#"éeöªßÞ<½ïªŠ@¤"Æii– ôÉôqð³Õ¬kÐjR?ã`¸ c£ÇR•ú ­'MdÌÃ+–24-‡»«ÿzŒa„øYŒÿþ"‡!N[ɤ׺Úx ZyJ&ç8‡Sõ=ˆ,Ò9OÓÔ5qÜãܤ¡«çæÚ­®YË2†–‘ ùÙÿÎ g2Ìêw&k-7nÍܽãíî[Ý.è¨í,Vk¼zúd×zÿs©-®KA¾CëÁÒ”Kïµ@RHòÅEM{óÖ|sQ£wúµ"‹&–LU ½v„à\vÙª…ÜàJGï÷›+sk2WC~ÝP€Ü»¹øOýÎyÔ<8ÌÐ]fä¤ñ¾¥×—Æ["l¼Hrq~‡Qwÿ:¿÷ò“d ¯I}?U[ðtY˦)óÆÒÞ)Ô¾&sL>}ü t•`¦¥žhiƬiP´ÒGØpÍ:J™Ö8J5ȱP?/sR Rb%}êv­ñ«>I‰¹LJ9H[s÷Ñr0h(Ðu£Š®àMý ‹óÌqœêÐ{­B’^«‡çýGu ®óÐã:Ù<eW ñœA6Ž=ý C©Ýé#la¬›Å»vÃC§†'6iUÈw xÙ·ˆ-'Œ“ï]í@pÍ­™¬B~®®Ù©k&’xÞS̶«’uÒìpt癣ާ‹TÓŪ dÄèó¶Ï€{q“g}' áÙÐ)ˆÔÑ£²Î$Eµ¡¨sW3Ò±žG!òŽÑE–ºZ¶¶êפcm;ìó{£(ž$É2$øìßEid¿@=}ÒCc8uú£¦jÄkÞÏ|áœ.¨áÓ<-}>¾xÞZ5_q=÷g¨ U‘ÿÀš>Á=îzÉÎÊnCÑ‚·­aÁ±…NªÉ‹8ŸÆuT£Ÿ}Ó{kÈ ú©I›­m©€-@’½«’‰ÖÔï˜+§¾Ïa´ºëP߇çÿþq^ Ðh«Í ¼%éë×YšXï׿}0ß_ôJG­æ;Žù×u…ZQ@5 |xÎÚ Gˆ|žx´‚û¨´ûJ}ÿò×±îÆg¯S7•=Îÿ¼?‚À÷yÐùs¬©Ÿd¥‹y­-l \C<Î?Tq‹Š›¾ª¸E€ôùd3>˜n`‹&Æ,0}“ÝÖpéÌ8öM>#£Kßô»nðµpô}?*Øm²2±°JDÛìr»ËX?«®a3C?+êóÞè!lW†lUÓ.’ìT êöjD‹®"ôœ}-5ûŠOôú¡SÝÞüûWž ßççWžKÈ“<—Üå¹è晳s¿¡û½ ÒÃn,±ë§ªÙ׬z5@`„ø\º‹“-·¦ÙȪu^$ÙÜ6r§ÕQÇR5ß‹ðšß§ïxöÿ„]ɶ¤¸ü¥L0–½ï:§ß'0ƒ™§„S_ÿl°„m¦»¨•Š)Á–B¡þ£¯®Ÿ¾Þ?ŠÂDR9ª¦æ?P“"& ªô_zm`ŧªß_j`bö«j昵¦ikš9Wúó=|ïþà Ó^x$}dŽ­8Mfûîó”k„ߦï½èä÷ø<ý›9ÓfóïÇœ)ù|nu¢ö™;P!†¢þ…N”ù¤Å´È'(ý˜ä.gXqƒSÛW,yª³pd!žÝ6] · ú|ò¸¯2ÒºœÍ{'/“³y·sõC¼`¤‘/%RKLv-É¢àóû1ãt—úõaÖ÷M©EZÇü%¶–ÙRvóRA¤ûR¡¬xLÓÂXÑžª²li€IB>¾9ß‘ 1\ÙLBüJF~?o*pLÉ¿Qùk´H ÷â&»§¦®Ú²@;…(<ÿÿDÅ·±:%ãšeSÐÁ4ùÚ¦ÿQºã`¼F˜YºÔ€ƒUÏ_ô¹âmãÚê8¾Ô5å²”Z¤¥3Û=•ø1Ûj9ŽéµáրȪ\ŠB‹T² ùvŠŠoX~c“âS¢F™aÍ5%˪¸Ó"a`:UM2/eˆxˆŒ´íå:§¦j–"Ð"7õ§?ÿn©²¸Ýô+aˆ¿»š+nø’>ÐøyÚDÿÎ Ú«‰>X–>iðŽüg À?‰uš½Êv݃|¬xÂÄB˜*"–Áû•¸ xi•è]BTu·ïHf•|›Çlf3¬Þ–}ŽÜõ¨Ë|.S¾ÏÕZ¤u—ù·Çb‘gU¥d•DÁüϪJ¡PUj´ÈC‡g§óî_Ü\u;—Œ´¯ëÍL©7‰2¹p©“¯Ü‘û¬ÒºšDé\ªô¯Þ‘e**j„ÝTµ}ˆªE£{¬Ò®ÓþÞyš¹$D^yô½æe@TÃôÝ'±bÚqÔ-Œ´ôYKQåà 1vE¾b¤ý¢Q5±Éƒ*Ȥ¨‚¥;ðW*9ìUy_Ö¢ä€ÃCljf¿Rã:_ûuÇá¸÷çþÑ‚38DÅüÎñ2çm”øyb_1¯e’Ÿ‚˜[ííJŒ{ gNçx,Y¯é¿X¿Ž¨¨ûåÔ~Gä{§ùÊÀiö"Sɧ]×iŠ~ò‰¡ü/'Ð pJª«ã:¯] ÌÖ`Z‡çÌJÚ§\+éÇ+}Œ¤¬$ùÕ)«"˜‡%„j³~Ä%æ©o¼†ù8áûkz¨ãˆêð?±ç’ó6Bëƒ/"xïþ‰©ÍA£ q>ƒf[¦|ê¢%*oCœï[ g?£Ù™Ô=ó,d,ZZˆ´Ÿ*©rÀÙâÜ{ç5ªw4w8æÎ<³bAƒwD5tKÌbìÙßÝúV<0ø5UäùZ«¯Ó»àÓîÁ§ÍŽ5Äñ}šJTù#JáÔÙ¯Ë2þD!òû亥ð?‰¢o³¹n%›Êök.#Y¥iÝ­Þ˱zSû~ é_C°Ž£¦Wf,üýLÓaŽcÞ¹r0ÕƒhZ4ç繬Çót¿Ž5Üõ.ü;öï=®³hýª'¡zw`×”ô>aDàïî~^"¡/CôUç3ƒKL\ë4cð“áÞ]ûÑÄŒ¸äò)¨¥(q‡JP+}}½©zð:ñ7Z6D"‚Ü›¿ÈL`ºÇSòÎJŒ»t Pb—Ð-¢`ª—9ÕÁÓ÷¸Æãø½OÀbÐ#Þ³/Û¡•D<Ëô¨Ú`ÍMyu.òOáÞ½SF =©2oúy™€ GM¨E’ãìi ÝÕ‚'þiPzàSc¥ÆK—Î]ÖÔa^i‘Gsº˜GþÆ”šd¤}¥ÜR}3u˜¥ü䉦 {ðãuzÆ‘§ÿ bA GÑ}šò!ÎÇe]€ÅM~ò"æ6ÉÛ Ÿïæe¿/Îçcjqëþ›+øo:ŸÇL@ÑÌq¤Ôðßd†ÿ¦óùêS0|a¾¢0Š&˜;sLü»y/f!ʈá1íƒwÁ™lþÚ"6c¼ÞúlÎÇœM¤Ú[ÝM ÏEÊïè¤)º/!y—Ç]&DÇR-Rñ*’Pºè®ÖÕÔe “>ûÜ!ÏßQ°JÃkƒé^ÎçuóŸÔŸÐ­2Yx¸U:¦Òz—4†w‰óýÞ(ÕO†R½óµN®1;sŒ¯6Ñ—(ž]ŸG3˜aŒù*’ ,ÍZ-Ò:;OÅËœ i:‚B‚ó=3Eå1ST;&1hLßU<¦ó¶&Ãod0™çh¦;GóHל¬9PÍ´ó:ð†˜üäXbîBO`X¢¡e‰]Œ(„u~buµ4›1Ò«ÊáìÖYlG‰Ew5ä‡D×±¾}XˆÌV캣)\ôôQëñNÊrãKH4DM™¿cÓ ì°<ŸŸóvX÷ëX×èì7OéMi$éñì¦çlšÆ2%B£jCÇÒíM4& `¶Å±¼+fŽxJÃ\Sd•y7µ!Ô`ð×ôŸÑƒ&¦…÷»uÄâXº× gó¥òì‘ßsýŒáê>Cñ­å+È.Û¾‰å+\m[Ÿ¨:)_Mi_±yKM{JFU{j_mDd–ÔL ËHGŸ+ß#Å\yž‡™y©‘%ô’®ÄHr¯‘2E¡Ë±Í~ñ¡Ðů3àKT¨EÚ—hÌÀ’a^ð)º5­… É SíŽÊy§]O@8}ŒuPæéžÍ}­«‚™¿ÆA3C¤wš”ßÑW1S/ÖÄrÐ"U&ó1}/¾âáxCð뀙úÝ®GHßgÍ\fy­E’ ÌxšÒ_”OÞCwE]·7ÔqR*“ô hE»ÂÙÉç†k´ûAç9 p1à£p†¡§zÆu‰¨YWZI+FZÆê ¿QctWb_(€{H°ô=p³SEŸÐ$iÓp-r-Ríñ‰][j’A@㘠›”ê㥅ÂË8h‘äpÑ ªz9Ã]æ@t˦½/&g7D"hX´Ž¨¢&#U/lÈ~ˬmÖçãBÍÞ™m¦5 §´<Ä!îe¯¼À^ùé]öÊ ì•Fí¨ 3—š¢^§òXÉ·ÝP¼!Ë8d è( 3—ý8œ­vì;ಯ]<[+¡î8ÖËŒîïÎÉ9:É`¢j”‰*GÁ~o4ØáyªØïY}Tq9qz£ÕY.'2ÒzÀ“ñŽ\“ ''Ôò| ØÐ¤ ä8ÞË’ÀâœV¨"yäð« •ä¨(ñõû ×I¿F­gÀùemËRÐÌq¨õì ,D‡Úçî•Ìëæ.˜Çä8;¹‰ÜV°nˆ¯sM’›é'øÞéÉ1\V¦ü+Îy¦Ø3šCé)úÙœ­IRc¤{W ¼uTÿ5·ý˜$a*´, » &‡\Œôï¸Må ÿOpG*J¼ükH¾¯!y]_œ«+9¨yrßåC»&ð†¸ÆWŒŠR[§^,ii³ÕQÈóÌSï.h>%×Ò5ǨãDd?Ìi­Ó>Ÿ}c úb¤mLçîk_u}… ÌMÈHëAïÞ%UiäªWŽÜ-GE³Ï½òµCø:\úÔ+_Š£(˜½ò|ï•Z¤}Ë@oÇuŸyÇ.ã>3 ¢cw_8' t«!7¦´òAŸÒrráòŒwäYožtp†.‡`›ï¿;+›zlâ¸šŽ‚ïÈ}>nËÒCžÜõÀhuT„|SbLä'°_þÅ=F:/˜?Öï½`Ñà—¶Aµ¡ç>"χc£ã½vñÞ œ¬©¾s-mçäk |Ú­†¢*´Hë|O+7$œ]AÈAÍ5•ÇLyÔ¡_ç(Ý=ów2š¨MWµñ¼j‘–ÆÙ“êÍÏD"í3'jŸäyÙ1”QŠ×I.Tg paJŧ`é¨%+$SϽi]GöUjÃÎ¥Ÿž§˜‚Éú]AÈ·A|=’•Gýš¸Òªù®í“~]\D<õ_ñwà¥oU$¾Éþµ—V³XËøþóÔNeÒÏçÄú˜Y>U!_=AG‚žô½Áò¡ú~?àœÐõÖ/^ òÅ…ÙSTAžåd¢Dá6ž@øãKD:oÏs€H½#¶/K›ãa‹Œ´$p|XƒbZƒì‡ÇTfšþH=ížÂ°ê G=òB¯’­º^%ÕÔ6°SšxÙÚµD¾é'ÃLU˜·r!ß'R›¾ï§%ëiOUæíiÒ3ŽIOª2oIÏ|P'=é—Ü­ ¢ˆDTw|7D†°Œ¼õ‹dÈ| '¯Ì„$Æjh‡60ÒÔ‰Jr‰×k8´Q–âuº§ÉÄT¢ÙUÉš_ NÇTÑâ¾Ðã+}‰OÞÓv±kï=¡O˳À0ª ä—šcÑi‘¶¢#çµ§²®–²©:<¦îQuè¥oÓdƒøGFZŸ×Qíª®1TaÞ^»Æ«“ZßG¾ ðý´Ô,ý…¥ÄE=§M0ãuÚWuG±ïÚëä0UDÔ]Ï‚:# ¢1Nž °‚Y£`Ÿô ›º‚HzöÚÈÁY²ç[®ÞŠ.ÇŸÍÙgãne 6œ–9žÝ}æ˜ë¼åÝL29E¸âoä›s|°hÊblæ˜NTSÛø’DžÃ¦©y¦ªGZU9\§ý=yXò:uý:j[75l³×°+04¨mtîòyΊxMVžÏ^'1¾Íc®|ÑæÊé<_²ÑìAS…O«³ÑƒF5µ+6~F½åÉÑ>8+î~îæ.ãe4¼óöK}”xþ ‹PJ>/,n@ö(¹c\3ƒqMUDW¯7 ·Œ¼ª7y‚¾Õ›i›Ý9ºÇuÚo^„x÷Ž9;ïsâ\Ô›ùÁŽFª ¯û:¿½ñâþÇxØ€ŠÐô¤bqÒâÆ§äH(¯ò5DÀ's×é¿éäû¤òi5üÆÐɧΕûÒöäÅ·Éÿó{ž@ß¶Ã.Z³0GàÓR}5¦´ÖsoÇ~œÒ z`óÊHëÌa7†:ä¬CpÆ~#zaSç4·[l]!þ<ƒrY–0Ó#-µ†U'€¢©êµÈc7&€¢¹+´HtÌÑfš¦¡íÐ=‘Žâ³,½ã¥è›ª¬Ç@‹¤÷z¿¸o:ÔœøËvUyžU²¸Ï³Y´nÜiËÖªÈóµc#þîÞ•GþSŠï’ê€ïS™UÛ÷Kýˆ~ Ý-‘ÏoÕY7ñ'Ÿ-?X“äYÉ. ÄXz¨L©‚XÍë½!Á'oúg¹œ—Ió5m~E‡OÉaÅã½›ÚÑ  ÙyÞçKùc¸†¸ß“’Â’]šÔЍ«ÎõìàÞÛv„U@2ißdþÍžù÷˜ù»äabePØæÔuÞ¦!0òä1Í«Ý=W[l»`®¨ ¯r?Êwó|L~ûû‘ë½9Gã½ûOøgðH½³7î¾4ˆ)B¡Ã]`ê}_¦Ú1K÷îÔGÅþ‡ú(õÞÔGñ]R”–/ÝÒW†‘J…²ˆL ‰÷y§½ÆÒ¼wú‚¥Ãìõž³ÊuÀüSÃiOyÒ žÿ”×)ª(9˜yì#,Z¤}èHä)TúA2”ÂìDFžT‘irRDA+T…ó¿/¾Õˆn©ª ×¼5x? cÐúØî=Ì–5„ž>õÉSǶ=Ü©ï\ð.`б¸Æ/NÅTÿþg̲¢ŽçT‹´n˜ÍqL÷Nq‚éŠTÁT¯tÝÔu§¾ÿ¨ë®TRªÖñ¹2ìÝÿ2OÂ2 3â~>OuñoÀ Ðý|ßðOŒ|Ë?žý5ÿÔ#­‡7#O¬xüú1TTRÝÏú“DÝ{èºúÙcFí~¨>)¯èÆÁ<†¨è~ܧ‰•ß1±âª á¿â‹K¤V|2ÄkÓ|qîÇöµDa÷kV(èd`ªî÷U¹Îþ}Ü;åjù¤\Ýh‘¶ÖÁÙWÚqZšOVñìöÛ[ïç—¼¼uÀåp¿ÄÀÁˆ_ç2ü–¨Á³;O«bÓ`ÖýÒG¼nA¼ÎU0Õ¿’õ±/K]ÚÏì×Í !ì~½;ß@C¥ßýÞqD²6Á ®ª'p­çg·¾Æê½{PŠ^¹°ž–™i=?%Ä?]CCX­ô^éóÌ ¾K÷\ØÒª­u7VIÏÅk²« Æ~Ô蓨ûTÅU˄僉û{¸KшÅ!¨óeÉJЫt­£ÛòLXlïço X÷c t[d$nK,ü¶w~XÑÜ !g‘ΡõÜl^üŽâ9†H_ׯCß°ªO¢<\ûóö†ÀÙíï‹g ~ŶõÈ(8fî\Û¾Bž·¼N ÏMPI^n=žýM9ð¸NúÌ@'×vßÔñ˜Þó®à¾i?2ÛòX¬r›X‰£MìM0ñÊ* †ïܹÓV†;­K,S©I®ÞÍ´FSЧ=¼ŸÄ>¹˜åÒëmî³”e ésõ6uö_r‰ó†ƒáÑ·A´.t‰™ÎxqÉieH?_×Q;Í‘ÞY7fGòw 0Wèÿ+öâHbª›na™P˸ŽÙ …^y>ä_Xš¢Ž„ëXgÝí˜ÉT¯%¿ó V0MKV:ŽíK:ÏM™Æ=¬!Šà¦à Ƃ~ì§rN-òPä‹¡8¬cÖä¿xÒ"í{ŸåÏ®«„±˜óGùP¦y7C$Õóyx•DîÍ×ã| 7×9g€ ¨_Lk3µ5žÝ}óÆÅ{÷n|«™á[í:þo53|«]jdþèbVåñš Y“t.ý>:Ú3¬¹\zᫎ“ M=πƸÔ~ó°€wž’7Ì #ÛYKþ».Ór\'}éñR¨«ñ?¯”F |Jošc˜YQÿ¥î€ÚÐu?ou‡©tÕ7¶¤¸ù(  ©Bx“Ýï‹VR ^'TÂÙÞä¼ÏÛÙ§®{…Ûì9­ÀmŠ)h!’(ŽÌê”+3¦\]×¹ð†À‰¿ˆ¡j·‹xÝ‘îRõct]‡ Íëºî u÷žÕã\ÍxGÞ›7FÞÿš‚ §dÞç1rÍñÉ«¾lמòiNi)ʨU(ž¥¯´ ði™Ð¢™ë”«]Ï>ñö~ñV#ð…yÅ;Òä"¡÷›îZ²s5¿aÈ Òy™GHðŽèKÇëÏ}æ3¬Fz·¼ ÙeÓ#­û½ø8»ÿ¦: OÞÿ¼©Î–Zäƒê,tÕe¤Šì%ûWœë$ŒFpµñ¿Wƒ: ¢Ó‡ë¿ðòj.߬Îö$9ã•霕á¯]÷Y%•gªøÎû†Ûo’I~HWÕI:¦MkˆOuîk’Ë¥!OÖ.ÈzTrp}W_CÄun»u òßø;Ð-_ßaAnó „}rŠ÷îŸ"!0Fá#&ïÈ{™ÓoQ?Äû|µ®úž¥gàÆÂ÷8Ð-ô>_Ó•CNÒUý¨“tÞÇäÓÂ$]µMÒ8Iç>b|õ–Õ}NÇõØ!äVí‚¿÷_ÓR3xàÙã÷qg2ù~ÞxöùÕ|­rŒrÛŠI0Zˆ¼1{ûf¶$s_/-}¡¶±¨ ÒÛ® DÝâÉ~ÁéÂn~:@=ùü`I–ïÌ–Ùº¶cRÎðmªñ:­þ“ÉúϰÀ¹û/}=="É [»¼¦ôãˆQÙ¨ê®N]%tWa*‘==ã0¢Dö.˜p⃠‡XzÌ?D6÷åÌ&d&J¢Þ9ËýM­s–X¦bT¸­k³fü _qLçŇÍñwºŸªHlÕûeÊ}„¹…(15¿àÉÅU4–ñRjÈ£§ k‰;n•ñ¼.†´Ï=õÌè©'–ΰ%2¤›+º{gÎýÊ›ïˆß›tH€sŒ¨½ÿ<{ òìûs©$|è‹û°èS@~_t«Ac…ØÖM 3êXv¤uVÐ˜ã•µÙØ”ø;í»Hé”Tí3ˆ”•%à2{Ö±—h!ä ‰ý%Æ1^ Á‘%ýârmæl©Ž1ýRÖÆdͼù`‡laZˆð;0˜1ðvó…["ùŠ'­ÙÓ5=™¡éIÃ7”_¯éšD¿ì¸œ»XPR×]~Ä‚ˆcßðHô?½ñ¹â8wVºðÊÅåcºÏ¹‰)ǹ¿E_œ‘oö ;w|ÿV`'#§†\{Ž\ViǼ]+@¾DÝ1šM\û…_±Á¹;7Z®2¾”Vxoº§Ï^µå&†_[Á{w½·H)ì%׫¢A$1õ"ÓѳÒ†c4Pñí33Û5â7R2r”SˆÒ1ýGÄëDm¶ì‚á bé0w%^§ïÏÆÜŸþ ÿÒ„ ï?Ç?ûc•ÈEÿ¦ì3ý›aˆ§¢ÿÊ¢3Rù?ÿlìŽ[áöô>•×`±£31†|ßK}ücuRhH…Íà`rè‹8›¢*ÔöÁ_Gwö’tâ߯8FÀ÷KÔš½kµ X%£cú"» g2qLÆUý³‰2ü:ˆkö¶ìUMÅ,ù¡ú'!î“J©¢(J”à>&¨©–GI×àÊ+ôà‰Ú½ònþE ú†„<ÅXšáˆ±(•x'5jîorS~§Ùú°Â‘ÚV>O抶Më©FáŒnˆ&ÌÛz†úX7ê`ÌP#ÁÎò4r÷H(-ãï<+}H{>YzºP~ÃzwŠ¢ÌP%†®Ð¹ocÿÒ·‹ûÓàÕ¼ˆ<ãzš–U 5ÏÉ<ÑQH™Id Fá®ýMÈ×w4ÒzÔT 1ÿ¨q0É GA×2íÙcv5ø8ÏöªÓŸ§{SÕ2>ž©…˦ú|Ê;:ŒXAÁÇ¿«`Ÿó|)V°òbƒÍ8÷Ûˆ„¡º|•™eóû=g1d™Á¨|uæ+û-¶¥çg2å÷V~qð5ذ±scšê9ìé¼1·À;RâK7Ì-†´Îµ1Q=|½7–iDúú¹t®ÿÄ•'O:àMÃ]@š•¾Õ¥ËêSQ—¾° x ësÓ9ËŒÎÙÀzÍEÂïÔ¸%U¡2|„ÀzS_;°œ›ª¤Æ¨J ´ÞÕËÎYDzo³LCZ·uªh‡–ÿSE¤ÞÑ/³l› ¶„Irã‘GíÖÉ´ ª[K¸vk6KÀŽ´€y ‘_œ`à3â®ÔOZ+СϾ <Ýþ¼hÒA”#°¿ÏV:ÆÛzAO·²«s "m…{ÿ°Ö¶½4¯%Kù Hçö.®ZÖfC†cºw±vÍ”BÌ?PûL¯Î%Šç’k›]oÒ Ý5Ó"…·ivBð•[AiRF¿²Bë>T°Š·¸ÞƒŽé¿u;"’<ŬF~Ág*¼èÕSJÇJà}.3by‘±dNª…âžW;(¯3õð;=Co Z“%çÖÚ°¢mcè¶œ³Õ+"Çlu‰žTà9f¶Úô"áœ÷î¼Hfx‘;òÉ‹„ìÝy‘Ìð"ïÕ‹„·é‘SŸ”ä–ÌÇzd3D7j¡v¨U^'>Õ&‹VÜ!¾©ÿ~°¤Î¿¶°ÿhGZ÷­|†f·:f¡1¯ËŽ™ã˜¥à} ð_JveÉ.höËb´¬Tî¾Ó˜”9ã˜fD"Ù¹d»iš_6c*œ9ÿC†XÈÔ7eƒïÈ¿¬5û¨ù¨Šá×5ºøtÿ)«YõàJ³¶Ë¸Y¨p üÀÐ2 ;§7rÊmE¨· ˆ©ËvDN¸C^Nu Ö…³Úb°ç7Önn¢ ê€ÿÕÇdüo=O·Þ|XXOb1ÀC°­tùñóÎÉ ’‰<éºe2àåÈݭݘ·6ñžxáÊyáU‰æŠƒ;‘%¾ôß®'æ\Î¥`UúEMTÛûï¿›ŒØåo¼«ã¨E§ x­â†ß|ï«% ú˰ê#^«:áöUÿûƉ·õ¿×+ì¥À1˜Á+ŸÆ9ŒÆ•¯ ]ÃN†ìÀ4Ö-mG–•ÒºßK ÎÈ»±XÓb üï,7½³€ÜÅÒMëâ‘énëC‘c:ŸÏç-ûÈïØè GZo¼F í íY#Á¿Xœô€Ôkò6×® ç¥Ëº ®‰Üëmº9 »{/ -ìM÷rEŽ“¿gvûGO“P6ßvrGaØFñ±žîÁ.b÷º nÖÍMâ çî]ÍHÔrˆß¹ÌákH˘‘°ç;þg¦aVkHõwæ[)‰øiÂmÅ=¾È­÷JŒÉ¿¢dÿÞ¹)d%¿Žéë•Ì ÝëXÆršû®¥?“œ²âZ ëÙ6828YÒ…š¼QQ3¼÷¯Áù°é„Ч×MÇ-)ù¹¨?= ù”iHûúwò/*ÞOEŽüž­ í¨¿s࿳Ii]üNiRŠßÉͰFCj¿óXÏ©¢ôxºuú²oW ‹F?Ó~Ì# õˑΣå?€åÏ‘î[ÏòH]!Þœ„(‹àÛü*µîÇK¶ÇëD¤”²¶Á¯ãK®z@¡ ¯çvÝ7x®….Dçc}žâuÂ?‚§«5fZuÓ«û8Ò:u‚È“¡jÖIpi…! í‹[fãÕ·Ý1 i=T†ãŒœ{¦z~c#S=Gºæþ”ù9·¨#ýÚÇôN¬‰E&Yk6pÏg¤Re<Ë!¦J»|’‘O± XÄ‚`/YÄôµ ¹™ø/íÇ!JüÁ™1²È€1’-Àé|ìÏ“eÅвâÈï["­›® ¦wmp¤ýÆ% {I­»æ’ŧ:b2Û±ÕD…‚iùWâÓÏl®{ÝÚ]eSÙ`vö’¿MÇ}È¿¯Câ®s¼›õlÌõ4Xå/übœ;9ÇÁ¤,â`ñ̸ ó ¸\òdregina-4.96/engine/data/census/hyp-knot-link-census.dat.gz000644 000765 000024 00000064632 12400017715 023411 0ustar00babstaff000000 000000 ‹„´åSknot-link-census.dat•½Y–ã:®5üž£ø‡n#üèw{-Ǩ†Õ·”–Gÿa "²NÕ­úOʺ7MJ ¢ÇFúJ“$ñÅüÿ=çßìñ¤išåc‡¿»||ÿäW•¤ý“®e‚¿¾b¨}<¾Súû<Ï×õY¯¿ÿ¸Çãõ‡Xk çŒIƒþv¢‡Ýéaô´&/ëý‰)ò°<£§e™³‹Ñ_Nô°ðýä6³¹mò­5[¥¿ÿÇýUÑÃrëœËÒÄT¶túóåÈBh­£ð~ÛzZSqýSbÄó#ð3ýKC|0[:ë˜OZÚý™bÉôy™¼è/ì}çýÛÈw¶U³5Û¬¿ý½uëLcƒþv’y´,üX·¹ËÖU;óšŸØW—ÓÞÅ<5s9†¤ÔüU´#x´sô]EÖÕ™]Ÿqňû#h¾c·ÒU:âß^ô¬ Ovž¾½ó®s6'óŸ’ð‹ ¬Ïè÷o¼ñî=¾±{yAOÁîÍÙÚ®Ôo=|`Ì}}ÑâŒxDmg“ô¦ÓÕ*ZÍûû›2/J_zúƒÖ¼ËÚ´·:ìÈz>÷GaEe$/s£ž ‰8¨,Ë&ØÙYC'œè°óŸšžß¼Ï¥+*_ù²jºÅwa)}º8yÁÈ@§ÅTTzG#˲"*±Ó8¬µ]޼þiè™ëûÉûa WWuMCsã¦Üd&kãS?ÿ´ôÐp§±Uâ\YÔ¾nèýMÝ/®¤éýÖuóÜèð/ÜJC·²œ=žÃí LÚ¸1iºNS*¿?èVЧU‰ÍùV4Ƙ,k;ýùð›žMÑSÖMnôoJ¯‹øËñ”î… nÿ–š]«¿Å Êi)˜Ù/c|,“òëý ~C§#fáÆÄL:âúj¥c„˜ï<†oqá³t6iåLˆoúbÚ¡e&YNOrD;y’Ñ’“l‹‹½ ©ÒbAB_´¹D7KÝé!ççãûEäe DÔe|e‹N×#äL_M4Èǃ³ÕôƒiˆR;vÄ0º4,ßIUïFçÖ8ì¤O{V)X / æ}V~)’4;ÿ¢ÓÌøˆ Ë*K]Wù¤±Ýht$Sô]y øÆ–_¥Í”e×Åg^ù–Ð ñL›û O©*ŸæÆT~1K5êÈO~æë±ê3‰úi`¯g¼ 72žùxÝ…+co<¤­^œ[ŠrÈyã‘Ï'8PJÆ#鎔ðv¦_B¢Ï$‚—/ºï_TìoßÌœn~Ñ‘º£áþ&Æ âˆÕTµ§KÚ›¾7eï—.O­Ž=â>‡;qZÜçÂ×u‰MK­MWäs½d›’éñÄw_ž›Ç¥uÒð %ë–Ù7Ö…øÜ3}Üß‘oV¥£Öéûà×2~ÙEN€ø®X9Ÿ•÷É\º.k‰éHæ>Ï÷“Ù#íÝf?…3³™kcqº³Gp¬v÷Ár‰ùÔÌ}x½}¯ÎV•’Áñ Ã/¸bH›P6ôq sÁe©mAF¯ÈñÆO§áw.ØÔ5†ë&eçœ ?}`á¯÷ö.Iq}i5ôZJ3g~t$. ½Y§ÃŸîÁÏ^…ãÙuÕ¶ôìí–Íc(C<ÄÓ3Þ¯ð„”â›A¤ÑjÚ–vÓA.¦u—t~Ч?=^As¾õ€ˆBº®¦ ¼„6?”.„7ôt&®îx…ÍI âÊ/ÙR»*i­åIòõýÂÊ™K•Bøµ Î&^å“’ßez¿«Šª.•@Ú¾4s6ÛUÇ~âû˜HYÜ8‚¶¯¥åf)n|‡Ã×ã9}ÉBöñJòÊ7UuÛòçÕnîL6%fó:ãögÄù¿H\=yßI:·$°º¡îÛnèb”!ø-í'e’¤§îåùC(çEôK¤àËר¬nÀ6Ç5ókÑA·ñ|ø­“®r½·ç㟼­1bH¾&N<‘ Ø~yD@ôâµD‘k§»>³ªò$N–ñAU!6–˜¶NâK.Q¡%vœÏÓ0™øÄkeß,§|U€»V¼¿#I¢±SFxþdUæÁ7…½ Ìû³†5µzç¯?=ðI_Ä‚Æ2ïOMn|íÖ(%œo$Zï¸Ð Äî¶•í<@ì> ¬!Zï«ß´)Þæ=mZ«?ÿ!yç­7Õª?Ÿâl–ÚΉ:ÄÙ¼]/è¯î$vk˜Zc»a謎¹ügQhãk®¢ŽAxeØr>MMçéiEöù{±VÔ„m®JýùGx«&ªŠŸëç2®ø&brý1 ÖNÿ¡íèUI™Ê0’ß?B—„¼Èf–òKcZÖ}1ì Rê)RŠõ… ’ÏÃz(»Ù°‘,%î•HKT /—U´‹¢_ÒjÉuìIÆB¤éXÈŸ8–¾u왿‡îue²¼, e›o¹ièš5º5$Ìù{îú=¢l¨ÖÒµe¥Ãøî¬‹þC§PªÔ‹®aŸÌyîoÜV6HƒÀiÇÂÐÿ×K¡c¿Tä«@¯fñ¬"?,&itäíG‡s>ÇÕ#‹%³­+ÛH("ÂÅ–5ÑÝg=›î¨ £o’ÁèÑåhÖ'Db ¥ ÄȪïèûÿ(ID¡¬¼€ªA_“ù6_ÚiéœÒ…púpÒÞE…pt2ôéü9yy³é.‘o±™¯÷û[¬ ú  â°‰Çl~»ÌóG†ó¦Š_Ç!«uì¦Óš+–†Äkʆ…'Äáè’ÔÐþ)‘å¼ÖoíkHôhÞ ’A›·­RŠJq¢Ë»[5‹å<3K1‘í•TqÕ,Å_Ìd^ƒëA¡À趬5Ã2šqŒ)R*ØëûG«uÿ ƒ£Ôý#)ÞòªEAȈ9•5«´’vKI·Jª)”ÐNrÃH·|î†_µ?Êe—–Ê“N¬,‡ÄMV8 àËŒ †µ¨Hl(µDY~ñõÎ<±”’¯w†ÃXûPçñ~‰ÔÞGºüg$™ÛŒÎ™w€x *`Â3ãL3Ʊ¬€=¡¯1‘™c†\l*ô¶#f+!Ÿøèˆi“Ù¯¹œE–ÑQXykæE‡ß áŸë SYîfÁ[F*A SØÌ.gë:²r’Ó˜ñx?Å­NMÝ’Azsk“o*Æ*范Ìx²õ&Ÿ½­ÞÁß’¤n²¦ôºª3kbôŠ'©@0ºá/(+~E µÓw}Qw}_ÄÏ&©ŽDƒëS]8¤ûâ6°¦²Ñù|öy[çÊŒIÊwªKòª¢6)«Úõɼ C\Õ%ò&C]€#û¶²DU3Ý"ÃÌóñØÕYÏ. Öe»Ò=Ô3Û@áþÒÅÒ¨BdFžµÉVmy¯äwæó|¼`.Ññ“µ„ËB—¼n 7ׄÆäÞ½å¤àèß8}9|"-°ù`—llÛTwàÂ¥£¯âà†­£küO§wëÂWöÐã›hDÞ^†gciÊ|«H!ô…rò‹œ!xL­Œ.„£k[á@šfÉ.Ïòqí¶,r¨ óÕ¾Ù)B[‹¤d¦@—ÜŽ! :öüï ¾»á`“%þå"‹y±V‡ñе°xUdI%% ‘.}ªLêreÕÚ³yÒ$H‹¥›AŠ}× Šëgv͘Z%ô˧¼…ÖôŽçZð]jð2Z[;Ï9œZqÆ¿e}Ãjcu³Ïè:²  tÒMÓt4·Î¹ñ’>|g¡¢b¯Jz Yã˜S…Ì6'Ã;^Ú+Tâçàu¬õ–ý0;Æd³aÐ]½~IV±&Jq`±1Q˜¢Wòzäý'Úù†÷Œ„^íaë›!²tfIænqS6~•£Åƒq´¤ê–…* >mÓæd¦úÇUŽ–ÌÖÏTh¶7axC|‚lˆešôV^ùh_d8°ëå ˆ–Yï,nrR—˦’·°=1¥OÈ–3‹žÙçnßïj—:U/AA²=ŸÛ~Ð;üyò|=_ð±[‡¾žn .»vÚÅ,©í]×êv}žDb¿E°Â$#fèÙo$ƒ­M”~žñŠç{%fWoXVÛȇÀ!aB:æ-~ÈE™]á[¥ÿÍä–>ËÚ8öˆïWS%*¯ôféÆ]~Ê~CÉãh-%¨©aÉÓÑ—¸ÕVnŠ'ñ%Võ#º}q uÙÖ=pç2ïó|è¦V/ý'Ÿ6 V6iñÌKje† ¾Næ¾6ݪ×÷ëãÏ€ ïõ›¯0«Lô ]Ýömßõt-üh¼ &™ë8M”§÷—Ô°»¡fUîc—†mL'"Æ §ýŧ}оY}"…‚¸Q×BƒÊ·¢ÌÓ"di§wéëÄ+û~¬qÉ¢rõ 8Xß÷JÄ8ŽC¨7“­ªBÙ§M²tW ±¦"òmÚÍÙj.¶ÐÚ©R–ðuѕѭŠ++àõaž'+›ËtóaN¢}òu¥•…{玕ÁÍèéûºkha_Òv]‡.q¶Ù´R!ôõ ÆCB ñšêÛÒátÍÐß“Ísãê7l:ó+ÎÄÅ×™mUÑ":¥aèyffæÑ•óä’yS‚øbŽN›¾!+y˜´Ü®Ó-ìðItÎüO‰!ì–£Ó¢ïàk#&iû:3éT*kºpXñ¿*]`FCºT×—Í¡LˆÝT*n,Éi'ïŸÀF W{Ò8¶AÌ©76ž×í$3Èv§¤ï!Ú«ÁÏhFeýds;Mmäg·³.®éª\¹nˆïÓZ™,Íg¦ž-]­ÙÆ]˜üàm!M‘Ý(Ð /úާeDw3M˜é]‰Su»ê´ûS¸”'îÙ€Ô‰n±© Uê›ÁøyZóÑë´OÙsÚñÇ–¾ ÅÜPvÂ/µ5uIˆçôŶ¢‰·S¬u4Ö×C ÐK–™äŸ_hëU"ÜnªJ¬ßìz‡Gߘ®")ååB¬šî°Î 9ü¢ðZ_*×p{Kz ½¬‡ä!ÆâêÄ´dL»*­tÚ¿‰nâó)‘M„Jå¿líUiú6 ›*¹‡0ŠÀQ øV°lR@ ´ttR)}~f—j ÿ)tÎI錕ÞCŠq‹'UªÆÞ5aòÍÖ̾Ý8ꜳ¼ ßOu'Óê žcóÄ£¼ÚÕ¶´æ¾ÑiyŒH`YEKŸT7r5²*„ÙÚmJ†ÙÍ:çªô÷¹ÅôGºg‡mè#ý5f^WzÕ\Ô:M\ª´yr5൬=„6}›¸-óµŠÖZ«3@ÚÍ[\äúšfÛõôoVÏM爄LèhgÒA§ÝâVÜÕ&‡È«ÄŠ[±m5’1©P,ýËLðþº¯ ¾„í¨ZÓ9Í3.¤$d7º'dÇè"Ä(ð®÷ûN ^k,+Z!®#/©–}OÌbrkÞm:í(ðõ~<ÕFŒòƒö±'8¨ªM‹[ì¶™©Ô™§?cPŒ}?–ªƒnRwñÎ~HMfpj6Mmgˤ‹K=ÿ™°1¯h—ôB¢¢v ÊïHðÀãœõ[jšš®µMÃjS{g5YÏÞsÒ¿û¡£ùàØÍX×å:Ž&÷Ißz•/e®ECÒ÷PÝã—’úç¿ ÁåµÑ™/$–žtOŸÊNb#ØØfvƒÏR2ŽŒ-H U•¨}8¨|yÓí!²£¯­HÀˆkvŒ¸jHñ‹3o´G!d¾|߉mßUôº±o†f蚢èb]õP/ñ {üø3‹:KÌr7¶ˆù—t›š±¦iœävÌtDÞOfYý0)I¼Å!°˜Â¢ËÖ“m•±Q®H¶™Ìœ¹(z—¦“ÎÝ4ï&Eäu1dy¦o8ÄÅÒ¯…D52ö­«j±‡óá§!‘lHk+Ö. –gõöœ;Ùàsøk qT‡yÊ'=ð3Ìc’"+¿ÎÁoP!"\{cú4$ÃÒ‡T?çÌtüü6yf3kËÍl¤%éoš€"ê§ó°ß9¸ï}µš5í†N UýTð)J«”` ¢\KRG>§~ªoNÙݾd—¦è¤dd&z½Î_bá?Å^Ä6ñêšÕ½|Iìl7½Úç›x¿ÞêÀYñè¤5µOJ}*»¨À-¡Â'p[ œŸD_}æl:maÜ|^(·¹þ”ACoÎ"ǨðIâMcZÉxÁ˜ãÿ£3Ë vì Å*«Ë»œ8àÉÝ— *ÑVúÅ%ag —3#ÖTI‚QAG[Ž™qcyËå¢7䮑ÞA&Õœ.Ó”;äÛèØ+«᡼²r$àI¯"•·…Ì6†îjÓùÜç:C’ƒë÷K”KØÎjÞ‚tl6$ÛV%žË—æ±IdAŽðêã¶"XF@ê[cRU.·}'è%Ûªôc±ŒsYÒ…T*¿~ħÖY×.¦·óºêχÉ1ÊÌBt=ê]cèš.]5 Ñ7 ô²‘ÂkšmÉ”®0,°?+oƲ‘À.¶¬wvÍIÖ6i|:YšAäÝOj Ü1´CˆÈŽt¯FÛ“=§Ã/<<@ZU¸ÔÜZð«ÀQíÈôÇÙö•ÜUõ€ûûþÖ`}ôD’½û-±éŽ]âá·õL”š¯¤Ì¬:S|먰Ï.]6DA¾4s™øš„ïBÊ•Î8 ]ß¿å.—Èש©+¿³L*bæã?ç,I wÕŋʕpë¤f!ó©Z‰ãH6¶h!ëú}—-#Ç>EÚhÞ¯dY’dÉ–)(aÄ·þ ëë®Û\´;ýâ["c&MMëñË@á~ª_ÜfMÛ·Pœ‡ÝsFÖõ)é:SHÎ6…ÃQ ÛÎûe%ë,›É&A¦ÎA òú~§ÁѰ+_í|:…)l®ÌB&3‘ŠwD ™Ó`Q5G• ›wý¶u½ÉÎ3 âþÎ9léO °[hm+Τc2êVJ§c´:ºóÙB&ܘ¦ ± 0á[í $'•°ºÕ 3LÎè6—J$dzº2U2ƒû¦•‹|¢Ã>i“¦3:ã"fóCYˆ¡9ÉçVÝ6S æ·×wK?ùªGrgk„0®3­¬ªÙéà‰ÙlÝë­Ò|ƒâ×ëýó ´ë1Z³ÔS¨tš&¤=cBÙ.Ù³pö³fbÉÍÄ= ”ÝÃGp–OÒ’Ö’¡Ã"~ï,«cÔÆú!›—&N¯éé"J`>÷ðVC; SI Ã5Ì ûÄQ[)g=Õ}±~Ç+Ec-â”¶g²Ùd‰h×ÔévžÄáF$²>UGgz…s¢„$é’e¦+‰‡Í”*e®r ÐL+dv”°–x022Ê“™Ìgšl”>H½ßs¨$ýMò6R²¯ ŸÔMqï¿däKgbk´‡c3¹Ž¡s.޼‰‚ÊV7|BŽý„%ÔŒ1837vHt_Î:ö®n>úFM»Ü¦% ûßuì dh/+ëK´Äýà…9ß“}{R¥‘5ÏAG=¾"öÛÀçLgßÏ!_èI¡M2¢4¥²#Øq>9Ö «8‚Ô±³ºHŸJ×`‚™‡n$µÊêé•Á.â¨ïï»ô::ÿ’&‘ÀÇŠ‘Äæ·¹Í”Lvòi×{•¹Oºq8–ˆ±ó°d.üÃÌŒIw%E²s¡„pb‚ ïÚqw 1èHÓeÛ\H£žqþbWåá8θžÝç¬A˜¬I2-’¤P¦FæIÄ8â:,‘#×uËú™>´>3‰Ò™)?,ÜáFÐ'Á &…}Æ&VcwÃèá¡ ¯%œØÔž4oRÂê–ô„TÉörüM^÷%/¢­ßôÁäe—9•˜Î1õ‘ã®j€@Ö–ì#‡îÇáŒ9K«Älpm:·µ³ ²‹8Öày‹NS¶˜#†ÒŒì€a×M2mУ§‰8R¿ñ"'õ|¼ÄtÈæ$Ú¨á)϶:Ò5¯·6 ­Ó“bÛ‡÷…­Wl "Ämż;“ÕM¶es(¯¾|²ÕüàsQ劳{&tëI‚įùbÝŽ3uïêõ€ §Jßo’:±3Ucíš~Šúç…õÂ'Tn>ad° (Þc?ÒlR ‘·3o°ÔWâhzËÈ4!‰fQ̈ÜéÒñ‰š½ÚÈp ©ç¸Zª²âzP示D™öï;(áó ®§bÖ¶šÂ®‹’A5ˆs’Ø‘„yššöCæ9o· dlq©'½*ì67’—_Cˆ@“㰜و LS·õ…Î9ïÔÉ9п¨“¸æøó#îe}HB­Ìïza꼿$ Ùœ S"ú4dàË3ƒé ñ1תRwU>Â~IPgVWÑ÷>02u’`I+ÚžÎÙÐ.®óµÎýü+<%×/…µîÅÏï¬ç!"­ÑK~ýb pm‹°„Œç0/¨II±ïFÏd‰ªé×›úNùòEß)©`Ç-ikõΙñŽ™ëÍ¿ñóCnàƒ#:âÚ¦½é@8íØÓÞ Øq²¡÷[Rµi5u‰Þ¦ÏƒºÅ‘î)sÉÆD@#òèvØŽ‰¯Ñù(!|eÙ8~ìѤ_õÐ~ÁqÔåkfº§¶¶n®»x‘?E$q¨‚Í5NV3÷‘$‘²…H7ôè̳\Rø×WL¨§]«jÉü}m=[böv®íª§óyÁ¢9y?¼Ø¢ùûˆö¶ÉQ’Ã1‰?ëj³%%ñü4N¿Æo¾¿Þ{^QÕA€³crNá¾IflœþÉ+_á,}kVN ©¯g5Û©[šuv]‡ªŠ¹9$LšÀ¾Ÿ¯ïŸºBCÏÞÓXê|î›¶˜M$fM¯•ôïÇ[ìtÔÒ[;2І8—þêÈFž›T/ß“òøVæ0’f±¯Ï•T»º"^Ñ &[ª ïý:üß«äõŸ¾÷븯ù­%H²æ .“s÷5[’é6]R×|bVLçü bØsæ<\¨.}F ¢ïܼÌôW³ã{™ºîkxhœY’™Õ! GÎ̬5(;lGâ*j¾Tå Ú¨#¯¬ú¸ ] a7dHZâY†`[2EgÁ_W¥jº‰Ï(z$Ù¡¥S’«ˆä› ÞŠLº¶¬üKè yk¢Û‹jz—ZI憦 mĵ¡/VÈ×—ªZ¸\wYXº ddჰÀÈ,HcoŠÌÕHÓ¹±Œãþx c¶ÈPl‰ùÐFË6¤¤&‰I VdæMRUà›¸¿Ôâj|KÖŒ4Z¤ÝÁãÓ5¤ÅNj¬ÞviGLClÄlQƒØbw؆¬b3ÉD*eaz)AÇ5¼Ä*–»o«Š.Þ8Hˆ=˜¬ÚBï²´QFucFÅ,ãõ|ýTüÊÑ £Šü¢î’"7ëd•QÝÎ<“˜ÅCŒk¸Ô`'’jD÷®ã™i ™l¡f³I©„t»Ä]57eФÿµBÀX-Ùñ!£ Oì)l&^ט³À.-ƒ«Â4• ‰ÈTMÚÑE©´‚ î’úmé‘ÔC*¨/³ÆÙe@¦oGlfN:·=£åûyî-œÿ Ω¡¿¸†ä¼J¾ÛM¼5ï5º²I£'³’.L¼ ñÖ¸ÁÔf åHH9©¦1ü#5ƒ‹”8`­©‹ñI÷Åë´H?¯U“oZ#› 'Òƒ€Ã÷sŸ GT'Þ ˆo»wµgzS¿/¿/1¾E¢Sùbº„äK®î$<¨G#*i…“xHôh”‹õùVuNwåpP‚CRkƒ¾CGß² Þ¨Ê'u™‘eEŒGMä: ìTd¹[^[A\wI7›©+C´nlŠ´A§‰+JÆ+FlŠ’tO¢ÉäC8¢V-1€~ŠÓÎ:-ˆ…§u=ŒFu~ašOIrЙ'nÒi’7·¾ßï» <œ4VxÁ¹€´ã&OmWÅS*Y‰F‚8L-i#ð‚÷$6„Âêmô›¦iöi¹N!î¥øèHZ½%Ý‘r±<$ÐÖd#Õ3‘œ‰}­Ó´Üä·®æR«@ÍÖ&Ë2ûrT½øpæ²¢Îùñ”rc„&H[“¬´1ú~éÒÐú­tæñCœ‘:œ$-£(”¨#«ÛlBäd%sRg0u<‘*ìˆSÌj°kh¢mtiQ·yVui|‘0ÉÑ^u‰œ¥ ÷ ›Ýåik½-fJ!®÷C+©kÀ H¹Ä:CܺÏuÓga`Ï=ŒÀÕÏm9ax×<Õc¹²ÜÒ4¤M³¿KÓ*¡Z<s¡(ÙÁf:ªËI]¤Sêú²¸!,†è6¿ž+§~£n.ŒNø3*'FŽû,#)¡\ö¨i•Ä)¯WL«D±l­–ÞžM¾¯‹¬ŠŸÇî{Hé×[ëձʦÖa–ÐdZŽÏöS»É"‘dƒrBIæL=ΖÒühR‰û*IèG™vâ‚R˜ØlN1 ùÑHj7µK†zÅm‰Ãcêœx º„@&¥®æ˜O¶•~XHDÙ*­õ"Ã¥ ö$ÉŠ–k9}9ÓTHà­â°SÜ®÷sOÖFõ—ï™T>é‰U“UÜuxÄ¥ ٷ٢ŸÌ>){¦ =y7LÕ¬3Ø¥Ëud0ö´’¬AÈ‚s(µ˜¬H‡>[W)§=qÁÿk创5œVÈ{ÛÑ‹iCtdô܇ïûú+HÀ pÿ$ðkéjçÔN@Þ—Ùq‚EF¬‹+ÖÈò*¦Ú¦ÃRÔK‘ǯfQñz¼WIäâʯš“áIV`I¤ŒåóâèÿUY2<"" ‘2<–bÎÊ.„xÏ¥ålöUŠ-CÛÕâ&XyêGl‘µÝÍÈü4xI‹æ˜%‡H7å[L—¸³šx@H/¹ùš†)•ÜÕOÕsÏ!Ìs¼¾g‰Ï²¥L_\I°š.0­¦M—±7•çKd*;-ø¹™†ÜZ6’ÍÍfE_[?Û«u‹.ÿ R.ÉS" K?ørˆ¢굊JÍ´?¢’n윮V­3¤’0êí*íœ*RÑÓ'ҥݔõ–éHŽ5*˜;"†RKïIÊu¾«ÂÓ±MzdFCy|#oŸ«ØÛЍ²LãÏ|iaÌ’d×B?$€qb'í‡Z²yO¶ìÒL]\1ç+<ßáÅÖYOŒÍ¬LŽÅ$ˆ“¡•’Ù£3?weWr]‰,*\Wd®b&`ƒò¹O J6RRé•L.jE0×S+¢&…§ê¡`·š?÷DÝcmíêEoèåöW9 P)GZ<ÔFÿèHq³JÍ}ý—ÎÇü«ŠÆtVݬHNùBô¨æZLè}#Y_«­çø–£–öh‰܆’)Õ ±8_Üœeó”„ÄY%uöªbß^Èäf[WÈ®´`Û“ˆ]%Í?Αš˜‚ÏO)uP$>.“†L§¡ªD9»RIt­¯˜2Nb é$HÊnãÌ(-¥ãÙÈ:íVÉ4¡þ§û¯ª>ÊšÝýdPDå!3™&^D„g,¾"«.{ØMbÎ…lÒзCÖú¸Z–x½êñªÖãMnÔœÃõ&'|G–ÉnFp5PùÈÎà&úëÖ&}gzùÉR®û'W'¥d‚Ôê.¥oò&5©×«ú©ߊjõ§"C•¬ó±û\^c;;ä6YM¦÷CJ¥‚”¸!XR¶ôšNrè“Ò®!ë¡Iß%“2ýÏ“ªË0v¡K!¢F*OWX/ÙÞ$Öömÿ< ÉÞ%è ¹‹„€Gù Úlí“ùÄSO©ÔË9C~ x P`•@) óá¸gWAÉá_@¬©p÷>Y“ÅT¤¨ð©5ÐÄ%«j ®2Áå§ÚÛ<Ô¹Ÿ–AÍßOÁhxßE®3x u;V¹Æ§–ëŸe\" ;¡ø>ŒKhHô.YŸm“Ý×G,p{>÷F.£i„ªD†ú‰>ZgH§:]AÄÇR×®Õ3úÒ` )“ïhyyOë ‡$XDeî­ë·™2Ú¯“Vm#“•o° 7*É5Þ³‰ÙÍ&®ü,»¸Š"½AÉ­ø{ɾè|ŸLtqÇ®ÕÐÒá‹“=WÅ%Ys„ŠQÙ@t¶5}T¾®±WsUi»Ÿˆ ÿBݶy®ÈXRjþúŒ(8}9!œ}€µw†s _ S2c \ÂÅ"Iœš|ËtuÑpøºýÎE.÷\d2çäØPãÿ*ëj×N¤Ho0«²›ëpç-D¨µ%©Ì’,Ø$3Y|ËQ"åO”^<#rû:I BVXg[Xi ?&ݾÛIõü·–Z9’{t4R‰´`2 ©ùÓºÙM眣ë.1&T¼#íFR˜dS?“$Ìà–ŠÎ¨Û…-aÍϤ]B±­¥©ëÚrªéhg¥²›`Í:”L(É㶘-E:PdŸ·O\ÂÚ÷©õ&6–dýh¢äUKoìp¥68{§^86°Qé„Ü´R×í¦i²|§®ù†ÑŸ¼Ké‚ ~ÎG‘<Ç^¾b'yä-0o‹|.Úq-».ŽäÒÕ{x‹ó)çâóJ3“ DíŒÅ”Á§½Î~LS¾#¤GÚ ‰€¡.³š²¼svª´læœ~²« \ˆ kÎfïÌfúµ2É2u‹Ž=ÿ ã'´zP`#Æ¢iB€m9çZ®GÃ…£Ìõ¡|˜YBÇL¤ë÷BW’”ã¼u¹NÓ²$”g1DœTÑ#8$Ö¶Öч•ŽpHªN§IYÒ+|kŠ5²÷øf¶ŒôäÌj{pñ¶+uÆ—Ô#£þù‚’¼žnWRTEµqŽdÔHk†2m\Z:o¼!GÀ•’Û<|(E`@l@/œ\ø$õUdÛïf›Ôzi‡ƒ–j?5ƒž7™]CœD?ûº&Ã\®ãA…ð÷ý)…ð¸¥ú»<ÝÐ0u$…}:%S|ÅIP;ÞQÉäô (™¦·k?“M:ò,êßi>ß8 ë$à.ÝÝuuh§ÎdU¿[ÞŠ ‚¤/ǹæÙa´O}CrÐDÇã{ rQ÷wáJ„Þ3M–NUipd”È=à ÀG%LlÏò+à¤æÍtS\_pñçÞ¿«_îÜ–í‡onÞ­ù’6:í&¤=É_Š.2–&'û¹›ŒuÇŽrêë‹Qô*føþZŠƒùÔIÌ4Ó^†N/ Ãöpõ(ŒC¸Ô‚Sq} ™‘€«)täQ4e†6YE[U¶ Ñ@" i1.ßmëœÝÔfd¸S[Sü¢š@P8%õãy÷€ÐQ,SíXŽåä”Å%’¶ô \·T3Mñ± AC qp¦3ûÇ^uK¹˜GC(—¯›>0Ýê%%Ÿ†Fx§èELP¢nÑÑ)EÑg›¬—ËŽ .åHi.P¼d·¼(šYÓ?’û(~,ìnÙ˜è¥!¡ª#¹ÈMw' ìè£IUé;F<>2±¿¶‚cÈå1¨ݪeÓG.ƒR÷¬ëbî7ÒÊȰO¢@¿Q&{WxB¢“Ž3ÛÙ DEïj2Ùó©.ôÊŸb±1«[êB¨—,2£a2,éù:Mmî·‚! &ÎHÙ§y‚ Fÿñó’â¦}LmC|VÈRª—Зx»Eéì¤Ú4ݯ‡(÷®Fe|ÛJb,ñHbwd‡U¥ øbÀµ×ȦL>×BÎhl‰ä¤LSþŽâ%»¯´]€,jVô÷’u\Æã¾¢óÇ¿TÐóÊž„m˜ê®:烂F½îê ¼9â@Ù~±ß²RÇñÑä3Ò<Ýl“—dDÛ½µÍôž¹Fð¡™I€¥â²ÒÐRÓ•~ÕËqVäÌw¬*ä[¥8Œ43ÐC­f´/ ŠÈÝ¥iœÓz—x9÷*±Ç¹`B²‡}Ov_9z=ŠËQNlˆ%3ª 9Àk‘wYÖu£Jµ‹†5ày¦?H"\Á¼‰t¶ÏÖøEø‰Ù8 $¢†a0·.£2ê’—‹òÅ£[B#kPV1óÊÊÁ­y?¤½›²Y͈ãEnæe¬‘9/hËHNë|ct¬‚grvbûp9¾dÓsø-÷IÛ†Rþ wÏýlHßfLÚi#ãÁôY7ŵ«T%SáUýšà[MÚ9^É뇺ø%㜱b|œ’'ÞÐ…²œÊI-˜ãõ°£ê‘™æÑØû-_ÇD¼&R˜2ÕÑx¸ÙrÉ5üx=1ãat=#è•}¢ÂܘmÜo–@úpú䓚R\³,«Å¥Ý².&ï£2zÝ±Ø ²’q­ÊÊ åØ=«X´@d2#'K`³i=™tS§‰r§+*ƒh§ ië ‘H‹mÌÒ¶eÙ•drèHAÜBzàwµ?šñ~ôÉÔ¢þ)ÖÅÍ"&PdëЯë~¼â€âÙ»è@ ,˜¸ùäÚ|NÍ\ýúOá£/ ™ Ô Ü\µT,ç%ÁÕ•ûð£ªÈ߯»`õ1Ãài½ù$é]“N³Úç).÷>]æ´t‰Ê+q/qèëø,,FôÙAÙÊçåïbÔÁ ív•º¾§Äo ˆdhÚÔø‘ªØ†xÙ??cq6=ÈZà©ê½8~²ö‚Š<—LÃd®iÁ™i¢ö"#`äH ª@ätÈ`UPr\²–aŠDFá¡I*9WÓKA!h>‡8!†‘¬ú…Ô§‡8ÏáÆ¸cmCL©ÏÍ9;~•' BVˆÂLÖ×`œ­ÖÐÅ‘R õ@¸¯Ê„YxA™J )sàÙ~ÉfÝxq=VuEf 5“°s#Í=™ˆ`Sü%øŸï•«Ï#ì©8ÞHIu¿¿$ûµJ1×jö;‰A”=‘Z×:¼(ä¾#¾:aÕ(#@j0Pg!:Œ+–8\œ¿¯ðPlÚÏŽ£ˆ]tH5mN5#¸d4ã&€#êã2WxZD;-tÍê> i5*IÝ>~ªx°ˆâV_&Ù’e3]žH7¹m·äç½µ,£ÇÅ[Z›ofÔ€àñ¦Ð'oöZ¸¼ªƒ Ñ }âMšŒh!]µøåx;±«à%–/ï'üG|¡±f¦+µÇ= …CÛó¾ æ6íh”hL`¯paB[%I1,C\Ùå7Äše,Š]¹û€OòÙ’I3ëX·{ÅÑÀý+Õ†Pª<ÌEÑÚÖÆe}F]G<‚Ä”×±ê“vJ“7E>Sü#\(ºŒ¦¨†ÕF"Û®d6%qoç&¼%þ’’±‡œ[âÈðUôa Ëì=])´öñôñ±³dÝyÖ#ÎîÆÌnm_é°ƒ"h|—ݯ`ºôuÞù(|&Õ±U [. ^ 8^–ßµ‰Ž=)½¨‹ E±ŒÇÈ..0g‹ÊkM”=}¨c¶¼ÔÕ-§oV0cª­‰jSêœ 9< ªCp¬"bY6¦q³#•¦/ÝdãÇ"{ÞcF•a*sÞâUÍ8 ÷¹§)ËM¦|KIp¨0!òÖ韗ï®d">¥è ž“²k‡†fvý8/ó²àû&»fµÇÓœ[—~)ã¾þÍz0˜Šä¹’ž[€Û¢%L“<w$G†Y‹KÌ1¸%5ËLÊHïÓჿÅ2ᩈ0ŽSº&ðŠqæi\°R¬fà§–¥«\G\g~DØ û[‚¹ÀùCZ+"—À a´Öµ!Å!#þoݦ%{§£$¿34 W¤ ¡P§!Jm5³7pÕ"¾âµòõ x5Ì㸨uïmÕ{•' ¥Ž=íuvw.]&±Ò¡ª®ª^’¿SÚ 3‘ùD”0¶aÉãÜ3Ë©À ¾‘B@kC‰m‹Û,O’9Ÿ·Ôl&í#k;r €”èÃ"d ]-T²qœ²ðÁÖ…É’ZÒÚN9À1¦—"ŒüÞ«7Àé˜ôcž»ÏÙ܈•êÃ8?™¡$à ?‰àbAËkP'3  rbh, eÛ°æ¦öy3èµ;~ýrÜ3Д!ÒYƒŸç&tƒ3vŒ§'¥Ý4öýdW·Û'{Æ_"€Ù»CȶdÓ<}ÄôG„nm’Å1´‚ö ÷º¨ÍNÆ€æûžNZâ ŠÎÈø¨¸¹;Pü‰¶€A!14öÈ&D”‚ÀÇн)š¥0.Ä•œb¡ {•t«IëBYP;趺FÞûL¯4~Ñ­>)e<Ù‡’ä´`7sRÂ×umV2<»n%Ž¢s"P|wÌÔ<¼÷œ; ¾c·lƒõ9Õó´jbÆét•4Ù`Ç_,—À‰ ËpÜ£®íäÂÔ",ëú-QöuúÜS•hI¡ I˜¡öé7X¡Y²¢ÖÌÜÓéë×Ü×=έ!q‰u÷ã>·@ûÜ,¦Ð0Íét‹{ýÐp#JÌH4<üÑܶ µªÒO=K= ÀÖ8Ea‡C8ÂÁõ4 Š”7IR/uM¥¹RDÌÖ .8¢ÄÕÉÄó[.Aâ*ÏÊT}×4« ‰3õºêÍ=÷«w~¿~è¡çD}¼ZìŠÙ6mWœ«\æ¾;QX¸“[‹¹(-°+q™q0³é5r{:Ÿ¥”'<ßK@$X1ð•× bÁ)Y¢¤/ÍJ‡REŒÛt ˆJbÛãØ ¨›ælô”ÖL UŽ]ºÚ ÷Iªˆ~Árö{ÇÅîz%´:£*æEÛƒV`œÎLZˆÄ­l)ÆPqÚ'zï8Ä`Ül¦yñEç~1‡$Kù€Â¦Š–È4ÒtTD 2Îë%jSElÙOYëÉunP¤0v4uŠt ©us¹ ê2~ùˆ%n/Tsì%nÄcYÃPO¸'Ħ̜Ó6åž.ZˆM/5‘«®D*×ó2ÎJRБW5™„Ô"SëÜãOK”ŒAQ N, 34zw.'lcÆ |Øê¶¬$CgÄ™ŒY¾¹„>n3¦õŸ,{VÖº €›$@¯P‘B/¬Õeûâ62ó2YÓ[Π”͇†áô îBêSø\æqÍ;Aó¤™WÁD6ø],ÝÒ)°'õÎTÙÞ¹Û¬×|PŽÓEZqYwÔ‹ÅÍ=çó&ESø1÷¡oö%KE%ލ†Y¹ˆ£`€“zI7¦°KªÉm>nÿ-‚½~Ë õmx*©bGp‰¸)(®v’¤ÄA™~FÀ”œ;ÇÁÂõýÂ,Ç#ˆ/µ;]?ÒåþŒL éE\¨S=ô²FÑIC‰ìzŒu8Š*³_¸äQøÜ-´é`ë‰´æª ãGgŠL{>ÞRž§¨6‘uBïVd›Ù˜<¯·:‹i§ëy¯þù–ÏQFÒvè[¹ÜD@¶ÓÜ_…‡¸KJ>¨¼Œ`’1°…V‘YZÒß6Ø.lšýz’´9‰ÓÆ' J}Õ\{¤v#smŒ‹ÎÔbÑð ùôV]‚íOcnàSµ¡4.¯J;*ǽ~í§úØA†éTûžUÏX­Ä§Z†yަ3U´!s?Úç Ò0R°ÉRýãðU1LÎ-ê=}*-½C¼­R(§ñ{c×*iŸ9¯Ò%Ö!Óµ~¯Ñ3ð&ÚÛ† èGÁ*¶Ëf*gGRGcžæŠ¯%°Šó‚4E2FƒË |L*3–ùÖÑF zžœR‡UmŽôÖ’+úr^²¥ ÛîûÁ&½²ÖO†ï^@ŒjF<åÏkílÖÕmôºF§]\FKÕ…‘÷0CšTD‡6JùOñ¬Ý5-úð/ˆk_'3¤š¼&—ªÿð8r¶ Vuc@R5(UoaœåHó¥ÿÒ¾¯jœ)ùKáhJåÅÇÁƒ\cc²i¬¦xDì\Sœ o€ì5uÍ›Ñ³× õ8Ø"[¼ºÁN_‘•Ýõ=@Ÿ'Ó¤æ zfe~¥·Ó]­ÈÌ ™"œ¾ƒúý»¤÷T¸5=muÚÜØ’¹ª>´§áa‘ì±¢sµ(™¬¸ŽÈ1¾OC¾õv$òÝÒiUÂexrš†4&FÑA——šÃZ=W£Ò4¨Cð­ÕÐÍé+&÷<Ï^¦šÕš¦!³ÕÙµã2§i|Ë…•Ü×ß f€-ô}ÉÈéÐrW×úžDON$Ò}ÅA.`ÒYQ²Æà;¬%af F5þ/1¦é3$ÿ¸\ ,@bçÓ4)C2öCÏ‘â“ÛöÔâXËhü*'éf½ë×0…Ü)©â 9O3IW©¾ß/öày dÎ („9H‹ ]èÚ«‘à }«ù&°±H¢My>«ˆ× ö~œ ) b—i-ŠÖRRŽõnžŽ¢^Ú5âf J.Šštºñyݘٓ_x7•º³·£èiwxÞCìDŒ}"±‘¡†IµZcjÒj‡åšqúI¼8ï|8ï§¢=p]Túüyf/Nê­¢^’¶˜­k5ˆ{ºù °²ÞßÏ Å=EŸŸFzƒ(³Éª$$ÁÍsQ÷S|‚ã‚Cÿˆ%}ÝC¢Á QÌŸ`‘›f¦nȉíf‰ê7Á3@®BPM؇íˆliLMu6)œPe7‘¨Èº´ÉuºØã¬â(|~Îv$MiûGÙ’ËR“)4§ÎoÊ2•5·¯ÄœQ1Å€ý$àI+˜LéÊ0,f±]ô%Þˆ#qÈJ&Ð9¤gpŠÙÌ+ÒÑò¥[MÎ8|°°X·l4„r:€ÁÑÚ˜àMQ ¯®IT;pJÜZÂIT2m5qæ;iþ3¼u$ÏHg PΖ¤žæIž?Äß(;ŽÜDшú|º$Ý4 B)ŽY(]kêÏsîÔ´> 6#2À4Ð]³µÚ4‚É%ÍhËkBQT…N;ïïû÷ë£cèél‘Ï:ý`tx›“Ñg¢Ó/²nz/üű¶»ªÆôf^ÀS)ëÆüÒTÍ:ԩ鮲wôæzÒê‘Þ:Ìó05ŠÐÓüXÓ)Ç$ص$þk]üòÏè+…¹|ßÈv€L†QÖ@L¢ èܬsݶWg?¾x ¯Àüß*‡:ÎÍnfš LœŸ!‘·¬Ö®CÈê2±iÏï†'¼¥9ëwlåÉòøtø¢J;¨Áú¼Öh¼6£;œŠàö#b¼ô0I€àØINÂÏKµ8d̪·ç|8Äé¸)ÏŸÌÈž[h0«ŠÓ4ÝÓ—‰ëž%á‘! î{q$Kn\”Ÿž¥SÓy¡;˜»ÁÅÀ™;|A é6àܰïŠ``Pн”$-kŒoUâ{#Ñí-CVUšFÁϺ6DêiÞ'y1ÙQ7ý âæÌK*®=jЉæguÖ‘*Y/uXÓ$ÂÒœWÁ~•àB‚²l€ù þN3TÀ,Ï«†è/RØáSÍõÉ0æ¡Ù†œBJ´ÙM8Ý Šñš(¤NFSfõ~6 ùx½"äGék–“±6dzÙê×·Ýô•ÈÕJµ¦$¶× u;=K.šZÈ)Ñ&!2U@¤óñC;+ДEL°1vÉPŸ{bÕ‹Ér2ƒVÕqÎÇÃ~Þ÷m¡àTóvà 9Îãïº\™ëçnÓœÂ3²(ƒ 8~ à'Z.uâ=ïèê×&4®&Ó9Ø*Õ9§(à9Ý1"}ÀÀ„-ÑEÂM±ÎE¾]²äN%ôùxHzÅbaµ³.ûF\GÐ<ýhLG:îH–í¨UígõS+ä¿„mÿÂüŸÄ óôíÓ>ÓéZ Á×5exÓ†Õv®="£gó¶ÙH6KÜŸÏ(Lïϧ:ÆsŽáÒA:âÚlc ê;Æ0Ž‘EUrŠçª~õ¶’p=Ä1.Œçâ3"Â0Å­^Ü?—ƒ@Ød=M •ɉG i`[¦>ë‰x5‚|>1OBaòë¡å’\›\²»vê >ŒRŸ¼dÓH‹š–e®•†OÊ“H¹ç´5$ú:o“ø†/±‡lA¦©±=’Ò jYÆ~S>©Ù&QÀ$'¡G6›à «Iœa«‹n)RuÊÕ¡Õ'ª,xƒ9̽¹Hšië¶&ZçóYã×´ˆï=~ è1æHÐY—Iã×tMÊà’9fÏP­ U‚Uµþjh§b¢OÎYÓ›böíâד`íâ@«W À=¹q"Àqé p`ÄÌç¾ÝèõŠÙQ2’‘)EŸ?£ÝÀ*·Òö¥G?âU¸ú(”d9 €¤´¢vkÿ„¯ÿ?óù&™tphT,•H»*Ñ⃬<Äë'Dì‘,¼ÑñÑûÜè‰Ýims8_>ðÍá~‡&ùÏŸ+îÓ?dÃ$ÀUzÚª¸Uc|oVœ5IZøEµ)‡"Œ{ß’³•ÑE€“¼®ŒžxÏUèO¦Tþ|¯oi© ,w¤=ì‹ÌçÞyÎaÍrÕ¯¤jü‰Š†u¥[ÚÜö“¨×(P'âì´Tê¬.îÿa‘YhÉðŠ‹b ûÄ¥—™ÆPS b åVLêLÓ¤“Ðçõ_ ÆZ½*¦}9ä¾[¦°?µ®éõЪ,ô$òŒFÝÆ9i™yG:Nä¼êëFÏ@Öä‘¥\°£š|—¢—Æ2YŸMk<à›é‹MߨM[ÒºŽ+³í<GYš¤ÖÛ“„ŸÐ*<7LA:M˸#>Ï |‚Š€z–$á'òUµì®µì¦ÛÏÑ ÿ:þ/Ãó^©íKzéÞßÚ÷±à®öœ­HŒ0)22C\I„ à$a/È‹Áqݬ)Ÿ#æãYÒƒI1•4r.ŽFÎ,ÝDbQ¦ˆ¯—Ã]ï@ðÞ›Ôc©r¸Ò§ž®zêmÑ9RCsP€ç´ÒU5N¡(IÕl{#¿å¥Jã%B% ;-¥cìÉn‰‚¯›¾å..[~K¹—ÿó[ÐoѶЇ³4Ñ|œyOl•NÊbáO!ms¿ÖùÒå úr¾"tÅwäÃ̵‹ndŽd`k½ÆùvÆ%YàZux…i·vë—ÍÆLγtÎDA£@pA#GVø¸ž‘´ÆÚ8 øœoœaz#óäðuº+@¦ä-Ât‘zmÉt7Š#x‘¼b€ËAH½B‹M÷û¡ÿ¨[àòqù¯t¨]¬i,Ÿ7;F9E‘¼É—CÜ¡Ö-müj>oÒ™V.xb%ÏGô\Ig¾Ìõ4µq=_2ã °ÆTË)¹*¨ÕdÉŽ¦! µÓ\(õŒøiY†`^©Í<Ö±ïß–n[u“ÜÆ^pˆNœÛ_ײ3º!Wè‚‹TšC?wQL猈—Êá±Í`¯ép~‚“ûˆYFÞª*ZA?­õÚ÷ÊV/‡³UºœU‚†_ ùVE_ä.é½úT/‡³\|Á ”j´‚ ä¸á«™é‘çƒÏÏØ1ª0ÄÈ~þÚqèpÁkãÇs ³w¤-d ¤ëWzO­ïï΃ª^Æ£f”•ƒÏ|òK_Z2õæb@žPîIñÅXºTM–5qKä¹(¾ÚUY62wE6K{Eè¼ù_0ªÙ_‡ôŒ×::E“[“+¯½räP=ôÈ9ªZ ‚—ér»8¥ñ£4ç{aÍ ç›¢Ò‰>/ssáÇâ>?ö™Yͯ}.­–D]¤‰«žoá­¬yÖŠ½ zg6"¥^g\þy2Õ¯“©Mw⺹˜;>Õï#wi¿õ:\@?ЫØÄ´9’ A}mž¡È6iµÿÕ娧x¼µð³ 0ž ßl´Ú¹†ó)Ò±Ðõªd¢à* FK$«È$¶2UL½œ>þâ>ÊàJd$¦¶Í‡^Ǹª`~ÊI¸VÙH¾j%ËåtÔÎ';lPÔ$upq)™ªtäÊeO¬8 Œ‹Áæ1Ø—ô˜Ø?.K“6z¿¥¯å“«!÷3ç¾–‚2eçÄ+ôåt°$šêsq±*}ì–ÅT‹ËéŠâ»— àp{Т­¶ÎÔù¿üSêéŸ )ÇEü0ÊDJk¦ÛRiù«I7ÞDKÒÔ/õêt“Œý—dì3 ÀUæ¤WåãræÒt ¨tבØ/›¾t­Ö3^ξ7ˆ«1ö–[6ä[N^ã7%Ö³°È—𣗠^*4jØL‘—I§„w>ý.LKǦ,‡)o×™ŒÊý¥’ûÅX,‘¹‹âˆ£|hÈºŠ¯–J7©PÈ~¾—®H7ÏÕ¿÷ûj»VœØ6·ñ)Ÿ8­;×+óïEcè×"Þõ³Y=€NŒ³B_\qQìcnüftX ]!¤tFîrùП!õñ31ÙÅoûÏìI€„OУtÛÊvŽ×ûrü“?p±éå@ '2?~œÑYpÿëBº:?.ò×¼4šN×௯ýu?ŒþõQ ;c·\¢Ó9ýí¤ UstTí—uZøaŸx˜l¨ìºs #’èÏGü,\”‹ÐapÙÖ7ÿ|ÂÏl Õ¹%,CÏIïüóy‡ƒ`ÆGöI–Ö³Yæ5¾^,˜û#š· ® ¿[=ôG|Ïõ÷¾uÈýæ¿þü7ûö‰N‚¿¿Ö´-ç_øÚß¿ôëÔ/ú #Wܬ÷‚ëºB®5:â$´õRm-~YÏ›ëYGœ$-êô0‡• d²à1Þod׃—ö± þùú#àô ƒEG75Ÿãw|b³qQôPQWŠ’7’E6é°¯¿ZózÝÝ4‡+´ÞÒøeÌk/YÕ 1Œßj8AÐȶ~¡abÉP#Lbø849¶[^oEÜ‚ÃáïGÉÂþù¨£–ú)œ‹g Ök1°È¸c—Žeˆ'Aðá²@W _'ž^'¶vô½Àêå±ç‚h\ÿú"µÊÂ,î»I¬þv¿³,¬Yyÿn —8® ,DH‘±¬#8Ëú){bu W¤²5]sÒ7ä(á…c…´ƒR;ÿ4u¤ª4uNæl£ãnuŒ°FV ”ǯUíÈäÈåa¬-2èuª]ðzVÚÉvÜ”z¢ÎÁ³ƒžÖkÃl•Mt˜`м¿tUeÉ%)øUvÛy®pK|jܦe”¢ÔïV"Sa-åépÅ4Ó<ëqÜ@@è¥RØÉPùÒZ–]}á;¤¸óØcìn¬nãjs¨?Õ/M>ÜpÛÅAˆí.-r&°¼wÁ‰ ÇTpTb벺ôë<僞ÅAxëõ‰•k–¡Lu[Dy,—‘¤ ‡E¥Ã§*.z³#“!GDq™‹ºÈâJ¿ðÉpÉp$²`œ…$-szq"’ùüÌ@@d^E%ÃŽ õ茫g‘(A $µqMÌ‚à»îáQO„‡2d4C®·"k_M£žÞñWól¹ÖØpM†i\¹é0ÖÏüê9žMÄùàRqEî Ò„¬ÚˆÚ:»¦µ5J£Ã/b|°×=2!i߬lH,2«§$ùTc!âPeÃêKÛÇ5ª/[ë3 ¥®A¡8¥’#+z/!(®Uaæ†-3è#n¶-ˆh¾}&6@–!Ù@žÉ^F³¶ylõܽ EÝ€Úȹϲj*4ûÊ«¹È6§>©yŒ(_‘*^LZUsžÒºÉ'v¬áûþÚfT¢RK r±Éæ6eÄH]52$×Q>Sñl ©Ð @B\ùY ÒÒH [⸈®½Yt³OÜÓ}ÍîœÆêØšåŽ{ ¶o2´7ašôI¯J†cÙõ¸ÆxI‹H|ц|®ôáçõxïéì‚®á'„>TÚbÇOU·u,u)8¹B*å[ÅI¬³z¨+‰gܤ :ç>kæo>Y~’øDÕ A_pþˆTðý”«Ã•ï3g4”$BÑE‘r>HÒ‘$ò%'¥û¦d·XÛ¯®oý²šÎ¯’»ÌsŽÿF‡º¡¥ VsE* §Ùô®Š?ŸwñÈ¢³ë“)g8ÿ¥Ë8Ñeš$²òóõßãÛ‡èèÿY)¼¡$+¸ Gz²\í|‹Ê[Æ:Ê/;TR*ÍÌé;¬£o¼–Î] 7}!ب™YmÉAsT= §ÏÐ3t6>âñmÄÍÃB®ášr=Aé-žSåìñ`¨Ž4EöBN'—ú/ /¤*¼K±æƒ^–Ë•KJ¥Ió|[»CJBä]6<Ù «b\/¼ Yj³3sü¸/â‹yú8-=]»E»ýuÀ=8²þë}5ŒKâüMHFk‡±âÞ?<â ¼–!mñØñŒCœŽ–ÛÔ–ñ‡hSŠÈ—d RC:Ž–OH[sü ‰Á¾`2¶÷”ºaèKÃÊ<Æžâ‘rÆÚ6éuk2° 9½Dòˆà‘b$Í}(Œ_¸²“ç\X¸õ"APÏÙfb m%Á¼”m›ç|¹0ç*Ý „eE-,¥Ñ9<ÎHÁˆÎùÜ)&ËÕ¹GÉg¡ Æa_¢œhý[îžòÅŒßãSyû €I县åC@uGO|ÙÊpi€Î’GqXôT‚-· Ÿyg¼Î‰ïÿ¢¸cì1ºNt?Šb¨{ôh´z:Eæx<µ0Às ‹vZpW}×ý|ÒአƒgRm†°‰ï¸ê…›¨'žŒ1øÅT÷äÀÊÀ›K™8½‚ARiÁœU’Õ¶Õ—sý¯ f%àÍý=Y°—ìÃç“Nal3,yÇ*`úãýSõU· ‰¦nµÏôóX®k<ކ½PѤŒ¦P"b)Õ¨?Ù‚Xn4Cºã¼¸±N\5”mªÛH3ìG³éªH›û_ˆîÈvÍ›ívY2Ë4½q~Š÷/ö½Á»_¿Zú ŽÕþôóYCž <ã̦cØ“¬D‡6Iæ q=¸#ÅÂCy[ã‹ÔMŽGÀVF} É.Çš=0Âúa°©ái<3éBþB|ŽE6©ôÜÕ§—>ÈhÌj²ºï”ØŽ_qÚûõ3Íó´îgÚ,Ó|§ LR?¥VŸÕœªhÚ’‘’›< m­™ò\·úô!%f¯ ÁjnmŠM„ûY›.Cè§/ñ mq‚Ö†±€Åßh?ùÓj¦è ºv%™Oç™Ç?CÀ56ƒ‹K ©ÊWõðoÃÃYúC·ð$‘·JXË<¨$¹Nf º©”:LD Ð’³TzPÚˆ`én{Zb·O“¦­%ïbsq¹¶tWêúØ]…þ›$Mî”^ΊÖúä–5•öÀf§†¸Û(Ú¥ù¥h=ªóYÞ† 臾ۅ"o¥ÓfNÜ,4 øC/ôù¹>~-²”ªÆ~_¤M“Å5[¿íºO ß¿¦!H¼¿ Ó’Å’‘é‘?ßûñ^–=Œ†^ ŽR€$ŠÅ^Å·1_€@yò¹‰L©ÏWÉׇ+1ª§ÓnJ‹ÚêvïìÉ;‚"ÊØ×³(’ÒÆ+uùxìõ[ ò К3–‘[×ÍÜËÈÔ¥ÓWI_í@ú/ýGÛîïæ£I­s´OÊc½Ç6ƒÒï´ÛçH³Óµ²•^¯‹ôIA›À5z.YK°ic‹À¤Ã*â.g…`Íw´J –“GÅ.M‹|š’Vw\pB[wââ;ŒÅ ¼PFñm¶ÎŒ—뛳íubóeŸ#é R¡ñ\Ï‚pÇy™ÍàÇ!W ç"á·§ž±CØÿè@Ô -œÔZkÖ`Úøñb꯯õ® ìC`ƒyw"Ì]£ë¹~Ha4wêþ—>Ý|û~5é†Ö[t•lÔÄVÎhB]i9q¾º,!›rCžqå95Ou™°%ßþ(¯½ [ ƒxŽºp¸ ŠêÈ\³Ì ¡!ú˜Í xøY“Q¾Õ›Ê±w€éI÷˜4tEŽ|»êÞ^5õáýR ÷Ô‹þî¨Ç­¸xl¬Qka4x†HMŸl¤<9ôŽ\?÷ÀãT»¥#{¥LU\OaƒàÛh<Ð ¤¥ÏšàWO¬oJʼn97õ“é²ì˜a·ÓÜÏs_“©áôã>EoCaÿ3æjpë*–{?>MœÁÆ“ Ù"Ö… õ^ )ÜF7ùó(Ú 60Œ®|íöãüR÷fœþ»»ÃβÜ;§`¹|Úœ]Ð`¹~D¶h=σÒîç媴>5JÙÏØáä}PÜü¨Ž0Ë ^›¬(~»­k¬æ‘à?“CSçã¾ _’ªöî7èv«´~t›Ý‡ß¢ÿƒ]ìä/êÌé2%•ðI"S(¸ /"¢6ÖMaJu³¾ÿ=š‚aÇ¿°·9-À‹[Úzj¦ÊZ%دÓaà7É_’ï¹·ùjñÉíÞã‹jŽzà×eg÷-ÊTÙ£‚©‡2lYçü¸$lÁ@·*[²nHå _l…·ÔÇçè އù;ã2ÄýŠé3?Îô}gcÌÞºÊvQô~i  $ ɉìç#~³VƒYÛ©š”­Ý>þípÀ.ÿ '‡$â®ÞRð~ÄÔ°.•z·£zŒ¿Ÿ‚¡(=Î˶a9’xú§ÿ ­y pøJ›!m’(]†62ÐóZUå[l÷©¸GÀŠo^ÊíY¥Ù@Yn¤ÙºÐ]º]¹|nÜïÌå’rÆ™˜¤qmhë±ÍÔ„S„P0ýT›)¹$1ü§Žøë®zD>ÙõYjÆWCÆqUuý´%'ϸí¦øÁ8ˆ¹¦@y[®¢¦aè]1è ¢Ð*%Éjª› ø·«r¨ƒ´‘ù§‘ÙümdŽaè3q#ip9;­J±øCj¶X*ýR{ú12m42é?iô ïs'0—°ŠŒv&©Yým\ÕRtc>žRÑb â'ŒÍÑ€²·²Mç¢)G2ºã7þ2d ¸ñ˜±ÑÞva,§QE.:ëÌØmŠ®V%ñ>ô˜RQŽÖÍøäEl#`±\1òB5LEÞ¯ñy·}kY&sæ·Ceœ˜Ö7ꥈ6d†´j£¹¿öæÙh £­/ƲR?èzÉ(ᦑŠÛç•ôI[Hù*©`æÚ½>Ë\…““–R(]ôèsªŒ_ƒÎ`áõ”9C~àÂ2V{MºÑ¤ÃÎ;–÷K£GHm¯4zdÐynk7µ]ÿc„#÷Ô®ÇON?3£:¦v0mÜŠÏÿ>ÇnÐuF!YÓp7¦:+ó¡äì,©%çá·è€‡Þi¢ŠÉô¸Ž1™ì!½/€‹ÎìÓ)tÜêm~øï‘C ;j¡§¶V)³¸Š=„ â ÈIå±\~¾ÐŽÛb…)ô糆¬™—J§™’=ØÒd&ªø Ë¿õýãé{³–Ï«”–“|^ý† Ø2.üS|Õ`e쫎I‰ì«v¤¤•!‹ïûú“e—¿tѼN¸µö¼ýç”úY³èXÐsŠÄ ø=gè5†HªÙz{øÏü|ÕâÕ5Éè`Õ¢[PJ“¬¹=ÞŽ¦’ܹ@gžg³ñéÌ.þç/CºöØ2Ä/¸ ú]±f‰Ž-N Q»£mp*ÙÐ_xæJ..afðTõ¯kºp!é`ÀÊ£Ÿá¯œt:„3MÇèß´ç† ê «Ž@òÖÕQ‰`á#Û"/³â÷ro U׃ ½1*)3`¶š’´^‚Mòa,Ej¡µp¾ ×$Snk˜‹e)5=Ý»ôuç|y£sÑ…óˆGFOå–‡RŸƒòÁõƒ¦3eHgµµ_âñÓÎ5»±£}î›Â3üH|Õ)ö¿y}dž̥dæw±-S(ˆÈD_ì0éfœµÑ8G=£iÄm1†vëÅ:jb5®K“mñ…É––©à­V|ò¾ mašÕ+¯,uç\‡hÜÕ°Íüg`ç£öGq.и•Bgæv¸þl<£›‡íébÌ!œ•[ Ð5¨€øœ;n0n ™@IHR³v¤:)5žo?eßÒí[ʾ¹óO+¥ÅZöí] ¦—VИ{‰H|¯ E•Z2Þ¡<µ×¸˜JF¥qÅÜ‹Îdô4F|Dvé÷àcË]äÇñï1É ]â ºç—ãþÖç÷ë×[¹P½"þŸÖ©Ó_,Ê‚.'í]ø½ÞŸ£tp öÜóM=ƒ+uàRç&õ¡c±\Ø×‘Ô«´@q»o‰ „`r—¶!´yIìݵi>vñ:^.ŠÈŒ |©º$mУõvIvý„H÷ænZÓ¦ËãÜ«dIX“D1ãZÏêu¥Ž¸ˆ[ åaÕïê0Dá~jÌޫëU–»JåÀ^€Åïß˯\‡Ç¼ðnaÁ-j¸„ÅŒ‹†Îq¬ö á–3‡ê‰c”U_Ž™ ÎÅC‘8'Ò”áÇéðÐÃ÷Ä:HJÚ³­5p€nÂVü”ÝÔ,Ë5? êkD+a©?°Žå-pâìÅ-®é•„?ÿš\&ÉNÜX¨)“øú“f´I®# -jm΂º V±êCBŸ`IÀ¯F’Ðh\áPÏùEþþ|çÖÙ1ñ¿âü-¤ý™™”^>#ö{ìa©i|ÐcœéKÝTñ®À=¤@n·Ct…ª/cs³ë”ÚÚEq ¯yþ¯Yª2Ÿ’Ÿv“TX)tœrÁÛDkóõñϼÈ5þv4í—¦Òb>§içI6)Óû:þ3s3(Õ‹»ä%Õ¯Ö¢¿UîÒ'ÉŸ&£×Òu@º_$“zⲓ¤R["˜g@D“_ê/§¿üZ’žÌiO¨Ö.ðPáÊʵSÙò£¿4 b·¸-![ÙV žý$¹Èy"¸ ŠgO„‡'¢Òa§ß¹Â9gq2ýÕY]oóftØÃÞ’qÂ9Ū4æÙ”U´Ø“$&ÿkl¶ü›å`Fªc¯ÿ~81YºåœMÒ ³rN’¬íH¸$‰¢ˆ;çYjãæÜö$l:vvGôI‚@J¢#$•ô)±Ô·Ç©Rѵç:VGO’½ûw Ê~çÊ©Ý4ïäRÇrÆÞì“nÕ±âúŽ7_âÂ\¢SÇ 0Pçàw’_ÞõÚÝÇÊ|»D‡ýÓîäô]µ;ÕÁxÚ}ï`gÌÓ&y? ªk{©©ŽüÔl ÅT÷…¸Ð5[¾G 'Éö•Ý ßq·\­ânEGÜIR~;¸Åò)áõnëÒ„q´O’, Оšrgóªä@¢ôb3µ§'Œ«u†í†õ{q#+-¦ß&FÜ@ß-ã;ˆ°/'ã,'ä€kô·ÿro9ø·wÅ1›o˜s“:ÝOö <“DæR’ ûãBCÚc2Ú -éO’ýûŸ× poF ‘™XK¬…8âë§IaƆPAJüöÒöá&IñˆÖeâñ¨h®éFeYb¸æJO눼}&¬Dr)Äj¢;»,N÷îÈ»ýF¿ƒ»ì),~÷IÐ@ÿ¤’Í5H(¼ô (€(´ UHÈÝâÓy€çùô+Áë- ^™QzR‹Û,Þ™Ž%ÇÅÈÏŠaÕ<»$ mU6gY3Ç•œcØ#¼öó-½8’üîd\ÙøàË?f€7üëŒxç$¿«Ó6Ù’) x$…µ-7š®ˆ%]Ð¥Èèµe…CÚÝpCàñ¦z%ò'Iâú9šQò;ÇÃégœ‹(?.axÞ$e,ÖsÔYÞá}Ûé÷úau`36’PÒé^×ugW…‘är5mƒ¿Ž@!ý¼4¾ä’ˆ“$puœ9ÅEõCWŒ;ÔµœQ.u™éêqÑ{¢û-÷D IhÝ5ˆ¯'&tŽF«HíIù>Ã$IÞI§}QÛκ­É½«’ºÿfð Îήi‚N¶\jËañí¤tyÒž®ïˆÐŒ`-.¶ºç&©èðô?ñÓÅ¥„Ž/‡b¢ M€²Ñd#Ý¥´ f4épv „§€ýá~HewKF(¡Y£9‹Yùœw¨aulº =Œô¸KtìAq,ÖûOùHUrç®Û“?Ò™þkugÔMø|?Y%Ë8Y Ÿðrè«BCÛŽåhã{Ä7ð| x·N޾L ·$Ö´³òùü„©•QäùŸ„TÙ‡4\þg8œ~Âá%9Iv–fS?4Gœ$9ž¿gF#W¤êºtœM\ôÖgxîzˆ•™­…ô¬Õšx¾ç¯ÿS³“Ô«h–6æ{ ¹µ]«k¾|üwL­:Z’jm×!*jÄY2ŽL =ŸËñ¿-Vº.¿bsp1E~d#³±ÝºôªQi×åUúfþDñøíA¼¹œ'ɦÔ ˜ð“”¥Ø¼ÞÀèØ‚²Ï {Þ1s¶Ø³¶ÉZ"0<—ÏjâÐüjÒ2¶“$NýßV°dKý.àÎÐ…–ÔkJŒÅfµ®òúñÌNɇ’xû[“Ô€ ™Ìç °ãl+ðœ’"ù\,“KdsMaœ’©\uäé'mV>íÜ2ÓAÆŸÏQ„½ ²Û͵ÚÃá$ùMê¡–#—r’‰ ¿]5Îs)$~óØ>ß_ò©Ñ"£á¿²"“:‰ÌàÊ7Cš¨§fS»Z’»J ×Û¿µã%Ai÷¿HŽ‚/ [ÝÖÙN_ÿ©y†ïûX)$ˆ(¦Ò½*/Ö,›Òɧ4› ܇-’ûÔT%ƒer°ÑaJƒñëTØ}æ ½î’ÀuËRŽø¢’ƒ»À CêŒOÛ.ñ=â®Î,qæYvó­uQ³±›0!7¢·³xfþÕ=ÕŠr¢#¤Fœ‚P#„XY#ÀÈ3:âô/F4g½V»ËT4ñÓbq1žÆÑn'xéI¿ôèº{ëßš)MÛþ6S”ٞźŠðj Îî¥z–³%ü6ѵ©-™ÍL†g±±~¾ÚqÝ{*UÅ©ÕÿÃö‰MŨø¯§† ÐUŒ.m#çÓs’_æÛàG@€e›N»J}7ªbœ /0:ÙðL@'α`FíAT'zÄæK37f™IÄ=x» Êioûazƃ{‚4aó'‘ƒë^ÄáãZÄAÌãX¹{Tb¦}$Û‘i¹ï,†–VÜß¿ŠÐªí+ÌPT)|Lg±¹þ÷8Ëöhsyµ±=DX»³/åt† ?€eT]XnPµÃ<Û¸ˆëŸ ©!ïû›MÕ\§—F4hiÉð Í þèt®ÈRÒß{ð´Ëé¤\L>µôDÎ{m œW½ì±cu¶Ñpþœ×}¬R±ÖÖ<‚*ŽŒì5)ºíJ27´½9ïæÙûþkOËè#³Èk—–úéGu5r¸4çVDåóŒ„å‚$h‹Òî;c8ÀœÞR\Äû­<Â]õdu%a@Ë¢Ób∳º_‚tidEZBÕ)6$TƒfëuWOêíeg)ïð|H± ôPFüRÏY d§áøÍEXJ¤w»Ò{37~§÷‹ð‘ÿ>÷ŸlÞregina-4.96/engine/data/census/mkcensusdb.cpp000644 000765 000024 00000013031 12400017701 021116 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Create a census database from a list of key-value pairs * * * * Copyright (c) 2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include #include // cstdbool needs c++11 #include // cstdint needs c++11 #include #include #include #include "utilities/zstream.h" void usage(const char* progName, const std::string& error = std::string()) { if (! error.empty()) std::cerr << error << "\n\n"; std::cerr << "Usage:\n"; std::cerr << " " << progName << " \n"; std::cerr << std::endl; std::cerr << "Key-value data will be read from the input file:\n"; std::cerr << " \n"; std::cerr << " \n"; std::cerr << "...\n"; exit(1); } int main(int argc, char* argv[]) { // Parse the command line. if (argc != 3) usage(argv[0]); std::string outputFile = argv[2]; // Open the input file. std::cout << "Processing: " << argv[1] << std::endl; regina::DecompressionStream in(argv[1]); if (! in) { std::cerr << "ERROR: Could not open input file: " << argv[1] << std::endl; std::exit(1); } // Initialise the database. TCBDB* db = tcbdbnew(); if (! tcbdbopen(db, outputFile.c_str(), BDBOWRITER | BDBOCREAT | BDBOTRUNC)) { std::cerr << "ERROR: Could not open database: " << outputFile << std::endl; std::exit(1); } // Fill the database with the user-supplied key-value pairs. std::string sig, name; const char* pos; unsigned long tot = 0; while (true) { in >> sig; if (in.eof()) break; std::getline(in, name); if (in.eof()) { std::cerr << "ERROR: Signature " << sig << " is missing a corresponding name.\n\n"; tcbdbclose(db); tcbdbdel(db); usage(argv[0]); } // Skip initial whitespace in the manifold name (which will // always be present, since the previous in >> sig // does not eat the separating whitespace). const char* pos = name.c_str(); while (*pos && std::isspace(*pos)) ++pos; if (! *pos) { std::cerr << "ERROR: Signature " << sig << " has an empty name.\n\n"; tcbdbclose(db); tcbdbdel(db); usage(argv[0]); } if (! tcbdbputdup2(db, sig.c_str(), pos)) { std::cerr << "ERROR: Could not store the record for " << sig << " in the database." << std::endl; tcbdbclose(db); tcbdbdel(db); std::exit(1); } ++tot; } // Close and tidy up. in.close(); // The following call to tcbdboptimise() does not change any options // other than the bitwise compression option given in the final argument. if (! tcbdboptimize(db, 0, 0, 0, -1, -1, BDBTBZIP)) { std::cerr << "ERROR: Could not optimise database: " << outputFile << std::endl; tcbdbclose(db); tcbdbdel(db); std::exit(1); } if (! tcbdbclose(db)) { std::cerr << "ERROR: Could not close database: " << outputFile << std::endl; tcbdbdel(db); std::exit(1); } tcbdbdel(db); std::cout << "Success: " << tot << " records." << std::endl; return 0; } regina-4.96/engine/data/CMakeLists.txt000644 000765 000024 00000000071 12377774107 017543 0ustar00babstaff000000 000000 ADD_SUBDIRECTORY("census") ADD_SUBDIRECTORY("snappea") regina-4.96/engine/data/README.txt000644 000765 000024 00000000313 12234011536 016456 0ustar00babstaff000000 000000 Regina Internal Data Directory ------------------------------ This directory contains data files for internal use by Regina's calculation engine. Users should not need to access these files directly. regina-4.96/engine/data/snappea/CMakeLists.txt000644 000765 000024 00000000444 12377774107 021176 0ustar00babstaff000000 000000 SET(SNAPPEADATADIR ${PKGDATADIR}/data/snappea) SET(snappeadata_DATA snappea-census-sec5.dat snappea-census-sec6o.dat snappea-census-sec6n.dat snappea-census-sec7o.dat snappea-census-sec7n.dat ) INSTALL(FILES ${snappeadata_DATA} DESTINATION ${SNAPPEADATADIR} COMPONENT Runtime) regina-4.96/engine/data/snappea/create-snappea-census-data.py000644 000765 000024 00000003114 12377774107 024102 0ustar00babstaff000000 000000 #!/usr/bin/regina-python --nolibs # # Reads the given file and outputs a line for each triangulation. # Each line contains two alphabetical strings, encoding the face gluings # and the first homology group respectively. # # The face gluings are encoded using the Callahan-Hildebrand-Weeks # dehydration format. The first homology group is encoded by a string # of letters, where a..z represent 0..25 and A..Z represent 26..51. # The first letter gives the rank of the group, and the remaining # letters give the invariant factors. import sys if len(sys.argv) != 2: print "Usage: " + sys.argv[0] + " " sys.exit(1) tree = regina.readFileMagic(sys.argv[1]) if not tree: print "E: Could not open file " + sys.argv[1] + "." print print "Usage: " + sys.argv[0] + " " sys.exit(1) def encode(i): if i < 0: print 'ERROR: Negative integer:', i sys.exit(1) if i < 26: return chr(ord('a') + i) if i < 52: return chr(ord('A') + i - 26) print 'ERROR: Integer out of range:', i sys.exit(1) def grouprep(g): ans = encode(g.getRank()) for i in range(g.getNumberOfInvariantFactors()): ans = ans + encode(g.getInvariantFactor(i).longValue()) return ans def process(tri): dehydration = tri.dehydrate() if dehydration == '': print 'ERROR: No dehydration' sys.exit(1) print dehydration + ' ' + grouprep(tri.getHomologyH1()) sys.stdout.flush() p = tree while p != None: if p.getPacketType() == regina.NTriangulation.packetType: process(p) p = p.nextTreePacket() regina-4.96/engine/data/snappea/snappea-census-sec5.dat000644 000765 000024 00000017553 12377774107 022723 0ustar00babstaff000000 000000 baaaade b cabbbbabw bc cabbbbecs bc cabbbbmlq bf cabbbbdam b dafbcccaadl bd dagacccffon bf dafbcccauwg bd dafbcccekms b dadbcccaqgw bc dadbcccaqrb bg dadbbccaunk b dadbcccbbcv b dafbbcccwoo be ebdbcdddaaafj be dadbcccemjg b dadbbccptnk b dafbbccltcg bh dadbcccccdm b dajbbccmlwn b dajbbcctvik bc ealcbdddjbntr bd ebdcbdddqhhpe bh ebdcbdddqhhit bd ffdaabcdeeeaaaadl bf dadbcccaqhx bcc ecjbbcddapnhg b ecdbbcddlqbaf b ebjabcddghikt bc eanbddcdhwbog bf ebgaccddkbgqg bh ebgacdddggsfu b eanbcddddsnno b eanbdcddmnjno bj ebfbcdddlhqpt b eanbddcdhwbgg be ealccdddeonob bd ecgaccddffohf bi eahbcdddlgkrb b fffaabcdeeehhqhgw be fffaabcdeeeahqhkv bi eahcdbddbokpv bc fbhaabcedeeukxnjo bf ecfbbcddhlfhg bf ecfbbcddepwab b eahccdcddbfof bc ealbcdcdlgbgk bk fkdaabbcdeeqpbaab b eanadccdphfpk bc fkdaabbcdeelqbaab b fapaaccddeegmgegb be fddaabcceeeqqotlf be ecdbbcddlqghf b eahbccddigvnb b eaoaccddfkoab bl ecdbbcddqpghf b ebjabcddgqmnt bc fjkaaabddeenaunxe bf fbhaadcedeehfmclp bl fapaacedceegsgosg bd ecdbbcddihohf b fdkaaabddeefankak bj ffkaaabdeeekqghaq bh ffjaabaddeeafblqm b ecdbbcddptchf b ecfbbcdddjmqg be fdjaaabddeenqofhf bl fihaaccdceeqjofqn bf fehaacddceeqbtoqt bd eahdcccdaokrb b eahdcccdakrob b fkdaacccdeeienhhk b fkdaacccdeehtfhhk b fenaabdcedepffhng bn ffkaaabdeeeghfdad b fbhaabedddeqqgtlo bc fenaabdcedepfoqnn bn fbhaadceddelganwf bd fffaabcdeeeaatasf b fenaabdcedeewwafn bo fcoaaacdeeefkamfk bc ealcdbddhrfwb b ebgaccddbbkqg b fkjaabbcdeemlgqqg b fjfaaaccdeebbgqqb bm fdjaaabdeeenakhaq bi fihaaccdceebpfoan bc fkjaabbcdeehdoqqg b fkjaabbcdeetviaan bc fehaabdcedehofaon bn ffkaaabdeeefhghaq bh ealcddcdkejdm b fjfaaaccdeepdgqqb bd fchaabbddeehkbfhk bp ffjaaabdeeenqgeth b fkjaabbcdeelakqhk b fkjaabbcdeeapkqhk b fgjaaabceeefqafle be fkjaabbcdeeeqbqhk bf fkjaabbcdeepisqhk b ecgaccddnfohg b fgkaaabceeefaqgmi bc fkdaabbcdeeihoqak b fkdaacccdeeienhhf b fdjaaabddeegqngaf br fchaacdeceeablkau bd fkdaabbcdeeptcqak b fkgaaabcdeettbhan bc fkdaacccdeehtfhhf b fgkaaabcdeeohhpou be fjfaaaccdeenjgqqb bs fdkaaabdeeefhopih bc fkdaacccdeeienhqb b fkdaacccdeehtfhqb b fihaacdddeeqbuehf bc fclaaccdeeemfneam b eanbcdcdlcngn b ealcbdddhfgwb b ecdcccdddenan b ealcdddcqvbfb b fbnaaacdeeenklirb b finaabbddeeabnkxf b fbnaabedddeaawonf bh fihaadccceeaokraf b eahbcdddjxxxj cc ealcddcdicwcc c ebdbcdddccvca be ebdbcdddaccax bi eahbcdddjsssh c eahbcdddhsssj c ealccbddhffof bi ebdbcdddbbbbx c ebdbcdddaabbx be eahbdcddnxxxk bc eahbcdddhhhhx bcc ebfbcdddhhqha bce ebfbcdddhhqxq bcc ealccdddevbrj b ealbcdddkhdwh b fcnaabbddeeabonan bg fbhaabdeedeuoxibu bc eanbcdcdlcnon bc ealcdbddhrkwb b fcoaaacdeeefkaufb b fjgaaaccdeeoochab b ecfaccddbbgxk b eahdcbddhnkcn bc ealbdccdiofkg bc ealbcdddqvnkg bc ealbdcddannkg bg fjfaaaccdeebnkaab bd finaabbddeeabfohg b ebdbcdddaahkc bg ebdbcdddaajfa bc ealcbcddmnjof b feoaaacdeeebsqqgb b ealbdcddieojp b finaabbddeeabfohf b eahbdcddkebob bc ecfaccddnbgxk bh eanbdcddhoobg bd fjfaabccdeeaawqhg bc fbnaabecdeehhogit b fkjaabbcdeepdsqhk b fjdaaccdceemthoab b fihaadccceeakroak b fbnaabedddeaanwok b ffkaaabddeefhgbqn b fapaaeddeedsnksgs bc fdjaaabddeenaknab bd eanbdccdmwbbn b finaabdcceepffnhg b fihaadccceeakroqg bh fihaadccceeaokrqg b fapaaecdedefiifed b fjdaacbddeeqqqlgo b fchaacdedeeuiaiee b eahbdcddsoqtq b ecfaccddnbnan b fehaadccedeaokhbf bc ebfaccddnbjan b fenaabcdedelcnhnk bd fjkaaabddeebanwak b fchaadceddehnacnb b fihaadbddeedgvnhg bh ecfaccddnbnaf b fihaacbcdeeunjoan bd eahdccddakfhq b fihaacdcdeeeofwhf bc fjfaaaccdeenbjxaf b fjkaaabddeefabsan b fbhaadeddcedqvnkk b fbhaaccddeeqkkolk b finaabbddeehgwohg b fkfaaaccdeebbgqqk b fdfaabcddeehhlmgo b filaacbcdeeqbgbaf b filaabcdceelbgbhf b fkfaaaccdeenbgqqk b fdfaabcedeeaaembc b filaabdddeeawgrab bc fapaaccddeevkfnbg b ebfbbddddilph c ebfbcdddddiix c ebgaccddixidd bc eahbcdddtuutu bc ebdcbdddqhamu bf ebfbcdddahqmd bdd fehaabdcedeukkabf bk fehaabbdeeeqbchaq b fdfaabcddeehhlmwn b fcnaabbedeeabaoqh b filaacbcdeeqngbaf b fkfaaaccdeenbgqhf b fkfaaaccdeebbgqhf b fehaadbdededfvqkf b finaabbddeeabwohf bf finaabdcceeegwnhf bg fclaacceddehfhofg b fehaabdcedetknanb b fchaaccdeeeengtmi b fbhaaccdeeeekgelp b fcoaaadddeefaqhxn b fchaabcddeepfnwdb b fapaacdeceegononc b filaabdcceedoskhf b fbhaabededehhgkck bc fdkaaabdeeegqgahq bc fcnaabbdeeehfwhaq b ffjaabaddeehfocxg b fehaadccedehofxgn b filaaccbdeehfffhf be fbnaabeededaaifpf b filaaccbdeehfkfhf b ffdaacbdeeeqhhqfo bk ffdaacbdeeeqqaacv bg fbhaacdeceeagakhq b fffaabcdeeeaaafdv b finaabbddeeabwohg b ffjaabaddeehfcbxo b filaabdcceedofkhk b fdkaaabddeefhbfxo b finaabbddeeabwkhg b fblaacceddemjqofo b fkfaaaccdeebbnqqb b fffaabcdeeeaaaqhx bce filaaccbdeednkvhf b fbhaadcdeeeurgpeh bd filaabcdceeqggghf b fbhaadceedeiremfe bd fehaabbddeehkcfqb b fihaacbcdeemfbghk b fehaadccedehkfagk b fjfaaaccdeenbjaab bj fffaabcdeeeaaarec b fblaacceddeqgqbbg be fjjaaabddeegqsnqg b fclaacceddeinhnbg b filaabcdceeqggohf b fclaacddceeqfbbqn bj fbhaaddedeedkandu b fblaacdeedeqouunh bc fenaabcddeehoooxk bk fkfaaaccdeebbnqhf bc fapaaedeeddllilti bc fapaaeceddecgdobp b fblaacceddeqgqbkg b filaacbcdeemnjfhf bh fclaacdeedegaihdj b fbhaadeddcedqvnfk b fclaacceddeinanbn b filaabdcceeioffhf b finaabbddeehfwohg b finaabcdceelcnoan bc fchaacdeedeqbijap bg fchaabcddeepfnwdk b fkgaaaccdeeogoxqb b finaabdcceemgbbhf b fdkaaabddeefhobqk bc fkfaaaccdeenbnahg b fkfaaaccdeenbnaab bl fkfaaaccdeenbnqhf b filaabdcceedofkhf b ffdaabcdeeebbtbqb b finaabdcceeegbnhf bc fchaadcdeeeubgpeq bf fehaaccdeeeenodte bd fioaaaccdeegbfxqb bl fddaabcedeeqqaabf bd fbhaaceddeedlvoml b fdfaaacdedebbqxok bc fapaabcdedenjjonf b fenaabddeeehvndil c fblaabeecdeaaqknq bk fblaabededeaabqgq bg fblaaccedeeqwqwxq c finaabdcceeegwfhf bd fblaabeecdeaaqkkh bc fehaaddceeejknvep b filaabdcceedosbhf b fcoaaacdedefkhhff b felaacdceeedtkfla b fcnaaaddedenqhqag b fapaabddceefvnkvg bc fbhaabecedehhgqgq bc felaacddeeehrwaqx bc fapaaedceedsfojof bcc fchaacdcdeeannkan bce fddaabcdeeeccccwr b fchaaccddeefbglqg bc fcnaabdeedeebdubx b fehaaddcedejwejlg bc fapaabcdedenjfogf bc fapaadceddenhknhk be fddaabcedeeaaccxa bc ffdaabcdeeeaacccv bc finaabdcceeegbbhf b fbhaadcdedeafhaqk b filaabdcceedoffhf b filaabcddeeqjosqg bc fihaabdcdeeqbbbqk bk fapaacecedetbwlog b fbnaabcedeehoigld b fapaadedeceoitfko bcc fapaadedecemjuffj bc fapaaccddeehgghgk b fapaabdcdeenbggbg b fdfaabcedeeaaknbk bc fehaabcddeeljjvqk c fbnaabcceeehoolhi c fffaabcdeeeaaqqie bj fbhaadcedeeigqfvr bd fclaabdedeeaurnnb bd fchaabcddeekxxkcf b fbhaacecdeenkxnke b fapaacbdedeffjobf b fapaacbdedefkjobf bk fddaabcdedeqqahbo b fapaabdcdeeffksfn b fapaabcdedenjfoof b fbnaabedededinioa b fbhaadeddeeuggxlq b fblaacbeedehfqanx b fapaacedcdeggbonf bc fddaabcdeeeknglje b fehaaddceeetrklpu b fchaabdeddelbpgsg b fapaaceeddetumqde bd fcoaaaddeeegkwkmp b fclaacbeedehgaqnh b fapaabdcdeefvkkkn b fapaacbdedefkfoof b fblaaacdedefnahbo bc fbhaadcdedeafhhqg b fbhaaccedeeaxvava bg fbhaaccedeeaqnhna c felaacdcdeehgfohn b fdfaabbddeedihlfk c fapaacedcdeggbgbg be fbhaacdeeeddoddxo c fapaacbdedefkjobn bc fcoaaacdedefkhafk b fbhaadecdeekfqjnd bc fapaacbdedefkjonf b fapaaebceedrkbbbb b fapaacedceeggbgah be fjfaabbddeedilpff c fffaaacdeeenbldsk c fblaabeecdeaaqffq bi ffdaacbdeeeqhaqcn bm fffaabcdeeeahqhbw bi fblaabeeddeaaqofq be fapaacdceeekfoofo b fapaaeecdderwbobb bdd fapaacbdedeffjobn b fblaabceedebwdsdk bc fclaacdedeedkhndl bc fbhaadcdedeafhhqo bc felaacdcdeehgfoqk b fjdaacbddeewussik bc fbnaaacdeeenkggxl bc fdfaaacedeenbnnpl bc fblaabeeeddvuvuon bc fbhaabddeeejxjhss bc fapaacededeaaxvav bc fapaacbdedefffogn b felaabcddeevtfllt bc fddaabcedeeccccvc bc fgfaaacceeenbnkjg c fbhaadecdeeumorxt b fehaacdceeearkpud b feoaaacdeeefkitfr c fapaabcdedebjfogn b fdfaaacdedenbqxgk b fbhaaceddeenjhjsd b fdfaaacdedenbqagf b fcnaabdedeehepklf bc fdfaaacdedenbaxnk b filaabcddeeddddrn bcc fapaaeecdedixdnib bi felaacdcdeehgfohf bc fdfaaacdedenbaxnb bn fdfaaacdedenbqxgb b felaacdcdeehgfoqb b fcoaaacdeeefkxahq b fapaacdceeedeqdeq c fapaabcddeelnltkt bi ffdaabcdeeeaqhhet bl fapaadcceeebqnbqk bce fapaadcdeeebqkbnq cc fclaabdeedeisldoq bc fapaacdceeedemdeu bg fbhaacdedeedfdnxt cc fapaadcceeebfmbfu bc fapaacdceeedeodew bc regina-4.96/engine/data/snappea/snappea-census-sec6n.dat000644 000765 000024 00000013401 12377774107 023066 0ustar00babstaff000000 000000 gfdabbcdefffaaaaabr bg ggjababceeffbqqdkxp bh gkfabbcbdfefaabafdu bc glkaaabdfefffanxftn bh ggjabbacefffhkhfnmn bf ggfabbcbefffaabbcqj b glkaaabdfefffhoxkuo bi ghjaabadfeffhkfrhfd bh gofaabcbeeffaabniae be gkfabbcbdfffaabaekl bc ggjababcefffbqqbjxn bh glkaaabdfefffhorhuo bi gjdabbcdcfefaaakbet bc gkjabbacdfefafahglt bc ggjababceefffhhgdqd bc gokaaabceefffaqodhl bd ggkababceefffaqgdqd be gkjabbacdfffafahiom be gkkababcdffffaqqdnp bc ggjababceeffgqqgdqd bf gjdabbcdceffaaakmnt be gkkababcdefffhqqpou be gokaaabceffffhqnoba bd gkjababcdfffbahqdnp bc ggkababceefffhqbiqi bf gkkababcdfeffaqqbet bc gkjababcdfefbqqafdu bc gkjababcdfefbahqbet be gkkababcdfeffhqqglt bc gkjababcdfffbqqaekl bc gkkababcdfeffhqafdu be gkkababcdffffhqaekl bc gfhaabedfdffkknknan bc gchaccdceeffadtexgg b gfdabbcdefffaaaaffx bc gcpaadedfffejkqbtxk bc gfdabbcdefffaaaaqkv bk gnfaabcdefffaaallbs b gfdabbcdefffaaaarba be gdhaabfefeefkupfxph bd gapabddedfffngqnhxn b gchabcdedfffuoaonse b gbhabbcedfffukanqpe bk gflaaaceefffknameqe bg gkoaaacdfeffnkakdrl b ggoaaaceefffnkiqfmk b gkoaaacdfeffnkahkwm b gkoaaacdfeffnkaknqh bce gapabecdefefsiisvdg bc gnjaabadefffafbqfpg bc gnjaabadefffafbqcrm b gnjaabadefffafbqrba b gkoaaacdfefffkadkrp bc gkoaaacdfefffkakhwe be gkoaaacdfefffkaknqh bk gbpaafcdeeffepmqvka bc gepaaedeffdftftdlfx b ghjaabadfeffhkfrhms b ghjaabadfeffhkfkhot bg ghjaabadfeffhkfjhaf b ghkaaabffeeffhfffhx bc gflaacceefffdkxslae b gflaabefddffofofgfx b gnfaabcdfeffaaahqbk b gflaabefdfefofokseb c gnkaaabdfefffhgkqmb bcc gnkaaabdfefffhgjqrp b gnkaaabdfefffhgrqgh b glkaaabdfefffhorhjl bc glkaaabdfefffhokhpf bg glkaaabdfefffhojhoq be gjlaacedfdffnnnknnx bc gnkaaabdfefffhlxqgi b gbhacdcdedffafhaqak b ghjaabadfeffafiqalf bc gffabbcdefffaaaccax be gnfaabcdfeffaaaaaxa bcc gdlaacdefffeeqamgeb be gflaaaceefffknamqme bg gklaabddefffdffofxp b gcoabacdeffffkaobbk b gcoabacdefffnkaobbk bc gbhabbcedffflfndahq be gnkaaabdeffffasqxha bc gflaabefddffofoonfx b gknaabbdefffhgkhhmd b ghjaabadfeffafkqaqa b gdhaacdeefffaujfxeu b gcoabacdefffnkannok bc gdhaabfefeeflpbkxbr b gkoaaacdeffffkattqi bd gffabbcdefffaaaqhjs bm gffabbcdefffaaaqhof bm gnkaaabdfefffhvxqah b gcoabacdeffffkannok b gbhabbcdeffflfndqha be gbhabbcdeffflfndqqx be ghjaabadfeffafgqaqa b ghkaaabdfefffhdqhek b gflaaacdfefffnnwdhp b gknaabbdefffhgkxahq b gbpaaccfeefffqxfqrr bcc gbpaacdefeffqxqqxqx bcc gbpaacfdefeferoilih bcc gepaaceffdefbdsoomx be glkaaabdfefffanqqei b gjlaaacdeffffnxnkip bj gjlaaacdeffffnxnkld bj gfjabbadefffafbssbn bc gnjaabadfeffafbjjem bc ghkaaabdfefffhfqhqh bc gbpaaeffefedjqgobjn b ghkaaabdfefffhbqhqh b gmlaacdcefffdekxole b glkaaabdeffffanggem bcc glkaaabdeffffanjjxm be gfkababdeffffhgjsim bc gfkababdeffffhgvvam bc gnkaaabdfefffhghhpe b gbhabbcedefflfndkqo b gfnaabddfeffhpkrsps bc gddabbcdefffaaknnna c gddabbcedfffaacvcca bi ghjaabadefffhkfbbxe bc ghjaabadefffhkfvvme bc gbpaacdfdeffiwxdluj bc glkaaabdfefffhoqqld bc gblabacdefffknhhhkv bcc gflaaaceefffknanduk bd gflaaaceefffknanepk bd glkaaabdfefffanaxqh b gkhaabddfeffummhxkv b ghdaabcdfeffqqswphu bc gdkababdeffffhorwmi bc gdkababdeffffhovvai bc gelabbcdeffflhgbkje c gflaabdfdefflgrpjwx bg gglaaccdfeffmfpxcno b gnkaaabdfefffhgqxha b gfkababdeffffhgjsam bcc gfkababdeffffhgvvim bi gdlaacdefffeeqamgek b gblabbddeefflgekoxf bc gdkababdeffffhorwai bc gdkababdeffffhovvmi bc gkoaaacdfefffkanndu bg gkoaaacdfefffkannlm bg gapabdecefffwwxxxww bcc gbpaaccfeeffcxxxcxx bcg gbpaacdfeeffcaxacxx c gbpaaddfeeffacxacxx c gcpaacedeffftetkxje be gddabbcedfffaaccacv be gdhaaceeffefffrvxth c gdhaaceeffefffwlxps c gdhaadffeeefafcisij bd gdnaabfefeefbxthvde b gfdabbcdefffaaccaax bm gfhaabeddfffomqahwp bc glkaaabdfefffhohxqa be gdlaacdefffeeqhmgeg be gcoabacdeffffkhhqkc bc ghdaabcefeffqqjwlnc b gblabacdefffknaxakn bcc gcpaacfeedffbgtigqg b gclabbcdeeffpntfoxo b gflaabceefffiosvfvk bd gglaaccdefffmfqctxe bd gdlaacceefffqqxcqru bc gddabbcedfffaaxxcav be gddabbcedfffaaxxjfa be gipaaecdffeftctqiqs bc gbnabbedeeffaafnkhg b gbnabbedeeffaafnkak bc gapabcdcefffkfooafj bd gdlaacdefffeeqhmgeo b ghdaabceffefqqjnffq b gclacbcdeeffpntfvqn be gfhaadcfdeffccxxawo b gflaabddeeffqunprwf bc gdhaabdeffefsmisxkj b gmlaacdcfeffdlknchr b gflaaacffeeffnnwuti b gjnaabdeefffsfxkbmq bc gddabbcedfffaaaarxr bc gfdabbcdefffaahhhbw bo gbhabbdedfefrehppgt bc gclacccedeffmfkenxn bc gjhaabcedeffjdqnatd be gjhaadcefeffafofkko bd gbnabbedeeffaafnkhf b gapabcdeceffbmmbevo be gapabdeeddffjxjjijd be gbpaacdffeefcxxwjxc bce gbpaadffddefooxmukj be gdhaacedefffddlxxhu cc gdhaacefefefddkxxvh cc gdnaabddefffafqvvbh c gdnaabdfeeffafkvkvb c gbpaaefffdeeorxrfon bc gbpaaddefeffngkcgwp b gbpaacffdeefmonexeq b gldaabcdfeffwwxvckr bc gcoabacdeffffkxaank bc gcpaacfddfefggduxfr b gfhaabdedfffrexlpwx bc gapabcdeedffdoddobg bc gipaacdeedffioidovo bg gdlaaadfedfffhhagah b gbpaaeddffefnttsqnk b ggoaaacdfefffkkwuhe b ghdaabcdefffknodxbi b gdlaaadfedfffahabah b gbnabbcedeffhejkdfk b gbhabcdeedffwoccoln bc gchabdceceffcgsgcuk bc gcnabbcedffflkubqlm bh gdhaadceffeffaifrwa b ggoaaaceeffffkckfoq b gdlaacdfdffeqmmtqnf bc ggoaaacfeefffknmxna b gldaabcdfeffvvvxcph b ggoaaaceffefnkjofdv b ghdaabceffefaafrspb b gddabbcedfffaaaaccx be gfdabbcdefffaahhqfs bq gdlaabddfeffkfhjmmw b ggnaabdddfffnfqgsmt bc gbpaaddfeeffngjgkoq bd gblabbedefefwutxust be gdlaaadfedfffhhaoah bc gcoabacedefffkooioo bi gcoacacedefffkrrirf bcg gdnaabddfeffafillbt bd gdnaabddfeffafqllbh cd gdnaabdfeeffafqvhvb bi gdnaabdffeefafklklb c gdnaabdffeefafolslb bd gdnaabdffeefafqkhkb bcc gdlaaadfedfffahakah b gbpaacedfeffffccfir b ggoaaaceffeffkjofdv b gblabbcdefffiofxctf bd gcoabacedefffkooisn bc gdnaabdceeffafdgjbt bc gbhabbeddfffgiahqsl bc gclabbdedfffkfdhobi b gbhabccddeffqqkxmnt be gbhabccddfffqhkadnp be gapabcedefffaxaxxaa bcc gapabdcdefffrxxxxrx bce gbhabbeeefffoemjfkq c gbpaaccfeeffhxhhxxh bce gbpaaccffeefhqaaqhx cc gbpaacdeffefhhhxxhx d gbpaacdeffefxxxxxxx bccc gddabbcedfffccccccx cc gddabbcedfffccccvvx be gdhaabefeffehxxsxsh be regina-4.96/engine/data/snappea/snappea-census-sec6o.dat000644 000765 000024 00000052100 12377774107 023066 0ustar00babstaff000000 000000 gfdabbcdefffaaaaadm bf gfdabbcdefffaaaaalu bj gkfabbcbdfffaabafon b gkfabbcbdfffaabafwo b gbhaccceddffujqjbqb bn gldaacbdefffqhtfgog bf gddacbcceeffqqogbqb bl gokaaabceffffaakhaq bj gehacbcdedffqbgagab bo gkdacbccdeffqqkaqqn bg gkfabbcbdfffaabanko b gkfabbcbdfffaabawkn b gnkaaabdefffoqbxmvb be gokaaabceeffkqqngaf bq gbhaccedddffpqfokqf be gchacccddeffuggcxqo bq gojaaabcefffbaanmmq b ggkacabceeffkqqbsxk br gbpaacfedeefgqvbvbg bf gehacbdcdefflgnwlak br gjdabbcdcfffaaakbgk b gjdabbcdcfffaaakbsg bf gilaccbcdeffmgoohhk bt ggkababcefffkqqbeqp b gelacccddeffeojnuqk bt gapacedceefffowfghk bd gkjabbacdfffafahgbf b gkjabbacdfffafahgvb b gkfacaccdeffffohhhf bq gjfacbccdeffhhnaaak bm gilacaccdeffkknaahg br ggkababceffffaqghaq bl gkjabbacdfffafahfob b gokaaabceefffaqofhf bs gkdaccbcdeffqqohqaf bk gkjabbacdfffafahvof b gkkababcdffffaqqkng b gkkababcdffffaqqsnk b gkfacaccdeffffohaak bt ggkababcefffnaafahq bj gilaccbcdeffdfvvqqg bw ggkababcefffbqqbeae bc gjdabbcdcfffaaakkng b gkkababcdffffhqqfob b gjdabbcdcfffaaaksnk bf gkkababcdffffhqqvof bf gofaabcbeeffhafnkak bt gddabcbcefffqhbfahq bn gchacccddeffpbgoqqb bd gapacedceeffforfbhf bx gkjababcdfffbahqkng b gkgacaccdefffnwaqqb bx ggkababcefffnaafdhl bf gkjababcdfffbahqsnk b ggjababceeffnahgbqb bv gldaabccfeffqakqfah bl gokaaabceefffaqobhk by gchaccdeddffpoansqo be gkkababcdffffaqqbgk b gkkababcdffffaqqbsg b gilacbcdceffpknbaqo bz gilaccccdefftgknaqo bd gkjababcdfffbqqafon b gkjababcdfffbahqbgk bf gjfacaccdeffnjgqqqg bA gokaaabcefffohhopih bc gkjababcdfffbqqafwo b gkjababcdfffbahqbsg b gkkababcdffffhqqgbf b gkkababcdffffhqqgvb bf ginacbdcceffmgwnqak bB gclaccdeddfflkhfcqb bf gkjababcdfffbqqanko b gkkababcdffffhqafon b gkjababcdfffbqqawkn b gkkababcdffffhqafwo b gojaaabceeffnahobhk bD gokaaabcefffgqakiae bd gkkababcdffffhqanko b gkkababcdffffhqawkn b gfdabbcdefffqqqqplu bd gelaccdceeffdgkexgo b gkfabbcbdfffaabanwo b gkfabbcbdfffaabawon b ggjacbaceeffafankxf b gbhabbceefefufxdaub b genacbdcedffpfoqfqo b gkoaaacdfefffkakknf b gofaabcbeeffaabnkaf b gehacbdcdefftngbqqo b gcpaadfeedefoakvkbb b gkjabbacdfffafahfvb b gkjabbacdfffafahvbf b ggjababceeffbqqbgxn b gjdabbcdcfffaaakksg b gjdabbcdcfffaaaksgk b gofaabcbeeffaabgkak b gljaaabdefffnakaufb b gojaaabceeffbqqnkaf b gddabbcceeffaqofohg bd gkkababcdffffaqqksg b gkkababcdffffaqqsgk b ggkababceefffaqgbqn b ggjababceeffgqqgbqn b gkjababcdfffbahqksg b gkjababcdfffbahqsgk b gkkababcdffffhqqfvb b gkkababcdffffhqqvbf b gfdabbcdeeffqqqqkhg b genacbdcedffhfoqnak bd ggkababceefffhqbgqo b gkjababcdfffbqqanwo b gkjababcdfffbqqawon b gkkababcdffffhqanwo b gkkababcdffffhqawon b gflaabedfffeaasqhab bd gdjacbaddeffafnkahg b gioacaccdefffknaqqn b gblabbeedeffqqunitg bc gepaadeffdefrbepsbx bc gbhabcedcfffaqkfqgb b gfjacbaddeffafbgqhk b gioacaccdeffnknaqqn bc gilacaccdeffffraaab b gjkacabddefffhgvxqk b godaabcbfeffqqfhbaq bd ggjabbaceeffafanoho b gclabbbdefffqfnqqgb b gehabbcdefefpbgaqfn b genabadcefffbqkqqah b gjgacaccdeffnwnhhhg b gklaacdefffehrahitb b gilacbbddeffqfbsxqf b ggfabbcbeeffaabskqo bc gghaabbdefffqbfedrg b ggjababceeffgqqfbqb b gdkacabddefffhofhab b ggkacabceeffghhgvhf bi gfkacabddefffhgbqaf b ggkababceefffaqfbqb b gjkacabddefffaknxqg b gokaaabcefffkqqsqha bd ggfacbcbeeffaabksxb b gjkacabddefffhvoxhk b gclabcdecfffqghbhfo b gehacbdcdeffqnoftqo b gelabbcdefeflgbqqnf b gldaabccefffqqooqah bg gjkacabddefffaknxaf bf ggfabbcbeeffaabbgxb bc gokaaabcefffnaawhaq bd gelacccddeffqvojuqf b gokaaabceefffaqbfhf bd gelabbbdefffakbaank b gokaaabceefffaaonxk b gjhaacdefdffqoaqofj bc gjhaabeddfefqqcbqob bc gioacaccdeffnknaaab b ggkababceefffhqkgqg bc gflaabedfffeahsqhag b ggfabbcbeeffaabbgxn bh gfdabacdeffffkhhhaq b ggjababceefffhhfbqb b ggjababceeffgqqvfqn bc gilacbbddeffafksahf b gklaacddfeefqfbqqnf b gnjaaabdfeffgqbuenc b gioacaccdeffnwohhhg bi ggkababceefffaqvfqn b gioacaccdefffknaaab bh gmnaabbdfeffhgfelwg b gokaaabceefffaqvbhk bg gojaaabceeffnqqgkqg b gknaabbeeeffabhqaxf b gokaaabcfeffnaahnqa bg gblabccedfffigafqjf b gdjacabddeffnakoaaf b ggfabbcbefffahbvhaq b ggjabbaceeffhkhfoxf b gokaaabceefffhqgkak bg ggjababceefffhhvfqn b gjlaacdefeefhvqaahn bc gokaaabcfeffghaqkha b gjkacabddefffhfoxqb b gfgabacdefffgchhhaq b gdjacbaddeffafsgaab b ggkababceefffhqskqo b gokaaabcfefffaqqfah bc gnkaaabdeffffhgminv b gclaccdeddffhrhwbhf bd gofaabcbeeffaabnkxb b gokaaabceefffhqsgaf bd gioacaccdefffknaqqb b godaabcbfeffqqgqfah bd glkaaabdeffffhoimkv b gfnaabefdffeaqhnqag b ggjababcefffgqawahq bc gioacaccdeffnknaqqb b gilacaccdefffrnxhhk b gjkacabddefffhfoxhk b gfjacbaddeffafbgqqn b ggkacabceefffaqfohf bc gojaaabcfeffnahhbaq b ggkacabceefffaqfohn b gfkacabddeffbafnxab b gcpaacfeddefnaknbfb b gbhabcdecfffqgaoakn bh ginacbbddeffabfwaqf b gdkacabddeffgqngahg b ggjacbaceeffafawkhg b gioacaccdeffnkoaqqn b ggkacabceefffaqgbqb b gdjacbaddeffafnkaab b gjkacabddefffhgvxhk b ggkacabceefffaqgbqk b ggkacabceeffnaafwab b gfjacbaddeffafbkqhk b gofaabcbeeffaabngqg b ggdaccbbeeffhhkfwak b gojaaabceeffbaangqf b ggkacabceefffhqknaf b gdjacbaddeffafnkaho b ggkacabceefffhqknan b gihacdbddeffdfvnhhf b gjkacabddefffasnxqf b gfjacbaddeffafbgqhf b ggjababceeffbqqbgqg bi gndaabcdffefaaasoff be ggjababceefffhhgbxg b gokaaabceefffaqofxo bc gjgacaccdeffkskqqaf b ggfabbcbeeffaabskaf bc gfhaadcfeeefafleumf b ggjababceeffbqqbgqo b ggkababceefffaqgbxg b gbhabbcdefffunnaqnv bc ggjababceefffhhgbxo b gjdacaccdeffkonhqqo b gcnacbbddeffhgknxhg bl gdhaadcfdeffuomklob b gokaaabceefffaqofxg b gddacbcceeffaqofwak bi ggjababceeffgqqgbxg bi ggkacabceefffhqbgqg b gfoaaacdffefofikfov b ggkababceefffaqgbxo b godaabcbeeffqqgobqk b ggkacabceefffhqbgqf bh ggjacabceeffnqhfwab b genabbdcefefpffahnf b genabbbdefffabwaakn b ggkababceeffnaafnak b gbnabbedefefaafdein bc gjkacabddefffhfoxhf be gnfaabcdefefaaakkkk be gehacdccedffhokxoab b gblabacdefefknhhhok b gdfacbcceeffahobsaf b ggjababceeffgqqgbxo b gkgacaccdefffwkhhhg b genabbbdefffhfwaakn b gokaaabceefffhqnkxn b gjhaabeddfefqagchff b gihacbdccefflfskaqo b gehacbdcedfftknabqo bi gblaccecddffiqvnbak b ggkababceefffhqbgxb b gkhaaddedfefurhgqon b gokaaabceefffhqnkxb bh gihaccbcdeffefvnaan b gddabcbceeffhqkbkan b gdkacabddefffankxqo b gdjacbaddeffafngahg bf gioacaccdeffobcqahg b ggkacabceefffaqvbxf b gkoaaacdefffnkafsnw b ggkababceefffhqbgxn b gchacddecdffiohkshf bc gjkacabddefffhvoxqk b ggjababceeffbqqjgxn b gbhacdedcdffihfbsho b gcnabbbedfffabaoank b gldaacbceeffqhbkohg b gdkacabddefffhvbhhg b gihaccbcdeffefvkhqb b gelacbdcedffdosafho b ggdaccbbeeffqqbbnaf bc gnjaabadefefafbaanf bc gjgacaccdeffffnxhqn b gjkacabddefffasnxak b gioacaccdefffkoaqqn b gjkacabddefffhfohab b gjgacaccdeffffnxhhf b ggfabbcbeeffaabskqg b ggkacabceefffaqfvxg b gblaccecddffeqbwfak b gcpaacdedffffwfbelq bc gghaacceefffmohxiln bg gfdabbcdefffaaaaqha bce gfdabbcdefffaaaaqqx bcg gihacdbddefftnbraak b gfkacabddefffhgbqqo b ggkacabceefffaqvbqb bc gfkacabddefffhvfqqo b gdjacbaddeffafnkaan b gokaaabceeffgqakohf b gokaaabceeffkqhonxk bf gehacbdcedfftknhbqb b gdkacabddefffhofhhg b gdkacabddefffankxaf bj gdkacabddeffoqgkxqg b gjhaadedfdefdqvqkkf b gdfacbcedeffaaembdb b gapabdceefffknfvedd bd ggkacabceefffaqfvhf bf gjhaadcefeefhcqhptf b gelacbbddeffafbkahg b gjjacabddeffnafwhhf b gjkacabddeffnabsxak b ggnaaacdefffgohgwfv b gelabbcdefeflgghhfk b ggjababceeffbqqnjxb b gdkacabddefffhofhan b gfkacabddefffhgfqaf b gfkacabddefffhgbqak b gdjacabddeffnaonaaf b gdjacabddeffghkoaqg b gjdaccbddeffhhhmoan b gjkacabddefffhvoxhf b gclabccedfefinhvhgf b ggkacabceefffhqsgxk b gioacaccdeffnkoaqqb bc gfkacabddeffbanohhf bc gioacaccdefffkohqqf bl ggkacabceefffhqsgqg b gdkacabddefffhobhab b gjkacabddefffasnxqg b gokaaabceefffaqbfhk bd ggfabbcbeeffaabskan b gchabbbdefffhfbhhfo bh gfkacabddefffakgxqg bc ggkacabceefffhqksxb b gokaaabceefffaqvbqk bc ggkababceefffaqvfhn b ggjababceefffhhvfhn b gapabdecdeffnvvnvqf b ggkacabceefffhqksan b ggjababceeffgqqvfhn bc gboacaceddffgcqhfqo bi gknaabbdefefaboahnf bk gelabbcdeffflbgaqjf bc ggkababceefffhqkgqo b ggjababceefffhhfbqn b gjkacabddefffhgvhhg b gbhabddedfeftbqragn b gjkacabddefffasnqqk b ggkacabceefffaqvbqk b gioacaccdefffkoaaan b gfkacabddefffhgbxhk b gcpaacdcffefbkkxubm b gkgacaccdefffwkhhho b ggkababceefffaqvfqb b gdjacabddeffnakoaak b gilacbbddeffakbsqhf bl gokaaabceefffaqvbhf bj gdkacabddefffhofxqn b gokaaabceefffhqsgqf b gdjacbaddeffafngaho b ggkababceefffhqskaf b gchacbbddeffqbobhhg b gehaccddceffajnfqhk b gelaccddceffqvobqaf bl gokaaabceefffhqgkaf bj gjkacabddefffhvoxqb bc gfkacabddefffhgbqqg b ggkacabceefffaqfvhn b ggjababceefffhhvfqb b gapaceedcdffkwwkkpg b gdkacabddefffhofhho be gfkacabddefffhgbxqn b gdkacabddefffangqhk bd gapabbcedfefgbwwanb b gdkacabddeffgqngxaf b gdkacabddefffhofxhk bd gblabacdefefknhhhgk b gknaabbeeeffabhqaxn b gbhacccddeffafjsqqb bg gjnaabedefffaqfxhto bo gbhaccddceffqgjoqhk b ggkababceefffhqskqg b gokaaabceefffhqsgak bd ghjaabafefefhfdixhf bc gioacaccdefffkoaqqb b ggkacabceefffhqsgqf b gdhaacefffdeaqqhxng b gblabcecdfefihvnqff b glkaaabefefffhixpps bc gfjacabddeffnafnxan b gcnacbbddeffhfkoaqg b gjlaabeddfefqhkgxfn b gdhaacefffdeaaqhxnf b gclacbbddeffqfngqqb bn gclaccddceffqvfbhhg b gdlaacceefffhodeeqf b gelaccddceffqgvbhab b gclabccedfefinananf b gfkacabddefffhgfhab b ggkacabceefffhqksaf b gflaacdcfeefqokhxgn bg gdjacabddeffnakoaqg bc ggkababceefffaqvfhf b gdkacabddefffhobxqb b gehacbdcdeffhvncqaf bc gehacdcdedffhofxfhg bo gokaaabceefffaqvbqb b gioacaccdefffkohqqg b ggjababceefffhhvfhf b gepaabeefedfnjoqjnn b gelabbcdefefpcnqann bj gdjacabddeffnakohhk b glfaaacefeefggtoonb bc ggkababceefffhqskan b gokaaabceefffhqsgqg b gapabdcecfefnnkfakb bo ghfaabcfefefaaakkgk bg gdjacbaddeffhfbchho b gapacccddeffbwgrgaf bg gklaabbdfeffqfnaank bk ghjaabaefeefafqqhag b gchaccddceffajkfqqb b gelacbbddeffakskqqb b gfkacabddefffhgbxhf bn gnfaabcdfeffaaannbg bd gfkacabddefffhvfqaf bn gdkacabddefffhofxqb b gkoaaacdfefffkakngr bcc gbpaacfedeefgqbbgbg bci ghgaaacefdffbbecbbv bo gbnacadeddffnaxhqak bc gdkacabddefffhofxhf bm ghfaaaceefffbbqwcvw bg gdfacbbddeffdihlsqo c gnfaabcdefefaaannkn bm gnfaabcdfeffaaaccvc c gblabacdefefknhhhof b gghaacdfdffeerpcabb bd gcpaacfeddefnavnngb b ghjaabafffeeafaqhak b gbpaaedffdfegbxlslg bc gclabccedfefinhnqgg bd gapabdecdeffnvvnvao b gnfaabcdefefhhhfffg b gehabbdcefeflfsahkg b gdhaacdcfeffakfaank bo gapacccddeffbwgrgqf bc gflaacdfdeffenhbtgk bd gcoacacdedffnkhhfqk b gmlaabbdefefqfkxabn bc gfhaaddffeefakhuuin bd gbpaaefceedfbabbbnf b gbpaaefceedfjqoojno b genabbdcefefegwahnf bc gbhabdeddfefdqvnabn b gffabbcdefffaaaqhlu bn gffabbcdefffaaaqhmd bdd genacbbddeffanwnaak b gjkacabddeffgqjnaan b gddacbcdedffqqaabaf b gblabacdefefknaxaff b gddaccbedeffditdoxn b gboabacedfeffnaaabf bc gljaabadfeefafnqqff b gknaabbdefefhgkhhff b ghjaabadfeefafgqafg b gcoacacdedfffkhhfhf b gdkacabddeffnasgqhf bg gdkacabddeffkakohhf b gnjaaabdefefbanxafb bq ghdaabcdefffaaxfofr be gghaacdfefeftreethv be gbpaaefedeffnqkngha be gglaabdeffefdfxtuur bd gboacadeddfffhhaqqn b gboabacedfefbkaahfo bg glkaaabdfeeffagqafg b gnkaaabdfeeffhvxqng bc gapabceceeffgbwrghf bg gapacedceeffofofoan bo gjlaacdeffefqouqthc bl gjhaadcedffftgqbqoj bd gcoacacdedfffkhhghk b gapaccceeeffbgggbqg bci gihacbcddeffqvkcqak bcc gcpaadeffdfeckpabuk bd ghkaaabeefeffhqaqhb b gepaaedffefeonpunag bd gapabedccfefoofkqfn bj ghfaaaceefffnbqwcvw bd gblacacdedfffnhagaf bi gghaacdfdffeerpcabn bg gnfaabcdefefaaaknkn be ghkaaabfffeefhhaqhf bc gapabdecdeffnvvnvag b gnkaaabdfeffoqbhhvr c ghjaabadfeefafkqakg bc ghjaabaefeefafqqhao bc gnkaaabdfefffabhhrc c gapabbcedfefgbwwann b ghjaabadfeefhkfqqbb b gbpaafcdedefqojobnb b gapabcbedfefnfnkabn bc gcoacacdedfffkhhfqk b gboacaeedefffahaqqo bc gblacacdedffknaxbab bh glkaaabeefeffaahxqb b gnkaaabdefeffasqxok b gcpaacfeddefnavnngn b gcnabacedfefngxaabb b gknaabbdefefhgkhafb bc gepaabcdefffgbbrhah bc glkaaabdfeeffhvxhkg bc glkaaabefeeffhqxahf bc gnkaaabdefefghnxakk b ggnaaacdeffffohoowr bc gcoacacdedfffwhagak bc gbpaaefceedfjqgojno b gbpaaefffedebpxlcgg b gfnaaacdeeffbkuobsb bh gfhaacceefffqruiqib b gblabacdefefknhxhnk bc gknaabbdefefhgkxhfg bc gblacacdedffknhxgab b gblabacdefeffraaabf bf gblacacdedffkrxafaf b gapabbcedfeffbwwann b ghjaaabdfeefnqbxhko bh gnkaaabdfeeffhghhnn b gbpaaecfdeefoohfvcg b gbpaaefceedfjqoojng bc gblabacdefefknaxanf b gblacacdedffknahbqn b gblacacdedffknhhoqn b gcoacacdedfffkhafaf b ghgaaacdeeffggionjf b gljaaabdfeefgqgqxng b gflaacdcfeefqokhxgf bd gddabbcdefefaahhqbo b gnfaabcdefefhhhfofn b gkhaaccefffeufhhmtg c gbhaccdeeeffdoddxqn c ghjaabadfeefafgqakg bc ghjaabafffeeafaqhaf bc gknaabbdefefhgkxhkg b gcoacacdedfffkhhfqb bc gdhaacdeefffawhqxew bc gnkaaabdfeefnhfhqnf bh gnfaabcdefefhhhoofn bd gddacbcdedffqqaabqo bf gghaacdffefednapaun b glkaaabdfeeffhoqqkk b gboacadeddfffhhaqhk b gboabacedfeffnhaqoo b gapabbcedfeffbwbqng b glkaaabefeeffhhxaqg b gnkaaabdfeeffhvxqnf b gcoacacdedfffkhafqf b gldaabcdfeffqqhffkn b gboabacedfefnnhaqgo b gddaccbeeeffiixibak c gelabcddcfffqvobcfb c gepaadbdfeffokruotu bc gapaccedcdffggbgnhk b gelacccdeeffmfvppcg bf gnfaabcdefefhhhoffg b gcoabacdefeffkhhqfk b gnkaaabdfeeffhghhff b glkaaabdeffffhoaarj c gdkababddffffhvbgvf c gfjababdefffghfdufr c gjkababddfffghfwnor c gnfaabcdefefaaakkbb b gnfaabcdefffaaakkrw bd gboabacedfefnohaqoo b gcoacacdedffnkxafqf b gbpaaefceedfjqgojng bc glkaaabdfeeffhoqqbb b gddacbcdedffqqaabak b ghjaaabdfeefnqfhxff bd ghkaaabdfeeffhfqhfb b ghkaaabeefeffhqaqhn b gcoacacdedffnkxhfqk bf gcoacacdedfffkxafaf bh gblacacdedfffnhxgab b gkoaaacefdffbnmbfwn b gbpaadfcfeeffmghwgm bce gddabbcdefffaaqqhhx bcc gddabbcedfffaaxxaax cc gblabacdefefkrxaabb b gboacadeddfffhhaqqb b gboacadeedffkltdean b gknaabbdefefhgkxhff b gdjacbbddefftuapnhg c gbnacbeeedfftuxtgqf c glkaaabdfeeffanqqfg b gblacacdedffknahkqn bc gblacacdedfffnhxghg b ghkaaabdfeeffhbqhfb b ghkaaabfffeefhhaqhk b gblabacdefefknaxafk b ghjaabadfeefhkfhqbn bc gboacaeedefffahaqaf bc gcnacaceddffnnxafaf b gblacacdedfffnaxbab b gbhacdcdedffafkakaf b ghjaabadfeefhkfqxgn bk ggoaaacefefffkakjoo b gcoabacdefeffkahaff b ghkaaabdfeeffhfqhkn b gboabacedfefnnhaqoo b ghkaaabdfeeffhfqxon b ghkaaabdfeeffhbxhkg bc gdfacbcddeffdiidnak c gjhaaccefffemgqleqg c gghaacdcefefqboqxob b ghjaabafffeeafaqhxb b ghkaaabfffeefhhaqxo bc gflaacdeefefhbduqhb bc gghaabbdfeefhfbqhkb bo ghkaaabdfeeffhbqhkn bc ghjaaabdfeefnqchhkn bc ghjaabadfeefafgqqgg b glkaaabefeeffhhhaqf bc gipaacedfdefggbhngf bd gcoacacdedfffkxhfhk b gbnacaceddffgfqxoqg b gmnaabbdefefhgfxhkf b gblacacdedffkraabaf b gjjabbaddfffhfgocfb c gddaccbeeeffdixibak c gffabbcdefffaaaqhie bp gffabbcdefffaaaqhpt bl gblacacdedfffnahbqn b gblacacdedffknaxkab b gcpaadfdcfefbtnfxfp bn gjnaabcdefffakfhdnf bf gdlaabfedfefqmeopan be gdhaabcfffeeuktxemo be gdnaabfdfeefpxrlpxv c gdlaacdfefeflfpehmo b gcpaacefffeeoolhxcf bp gapaceededffvovvohn b ghkaaabdfeeffhbqqkb bc gapabdcceeffrfrrnan b gblacacdedffknaxban b gboacaeedefffahaqqg b ghjaaabdfeefbanhxko bo gnkaaabdfeeffhgqhfk bc gdnaabddfeffafwddbg b glkaaabdfeeffanqxnf b gbhacdcdedffafkhkhk bc gclabcddcfffqgfbovb c gdjababdefffnakitfr c ghjaabadfeefhkfhqbf b gdnaabefdeefmxtgdln bf gflaacdcfeefqobhxgf bj gipaabeefdefnnkagcn b gcoacacdedfffkhhgqk b gcpaadceffefnokxxkx b gnfaabcdefefaaaknbf b gnkaaabdfeeffhghxon bc gnkaaabdfeeffhvqqnb bc gblabacdefefkraaabf bc glkaaabdfeeffhvhhkn b gipaabeefffennkaqhk be ghkaaabdfeefgqgqxbg bq gblacacdedffknahbqb b gnfaabcdefefaaannff bj gnfaabcdefffaaannof bf gcoacacdedfffkxhkhk b gboabacedfeffohaqoo bc gcnabacedfefnnaxafk b ghkaaabdfeeffhfhhff bi gdnaabddfeffafwddbk b ghkaaabeefeffhqaxho be gnkaaabdfeeffhghhnf b ghkaaabdfeeffhbxqkg bo gcpaadeffdfeknlpspn b gcoabacdefeffkahqfg bn gbpaaefeffdebarduog b gcoacacdedfffkhhghf b gbpaaefdceffjurfwpq bc gepaadcedfffngobtpu b gcoacacdedfffkhagaf bh glkaaabdefefkakxafk b glkaaabdfeeffhohqbn bc gbnabacedfefgbqqabf b glkaaabefeeffhhhaqn b gboabacedfefnohaqog bc gipaacbeefffnknjmee bc gfnaabcffeefmghixes bc glkaaabdfeeffhoqxgk bc gblacacdedffknhhoqb bc gfhaabcdeeffqnfltgf bc gbpaaedcefffjgooxpm bd gcpaacdeffefnwnexgq b gbpaaefdedffwejbkth b gnkaaabdfeeffhvqqnk b gepaacecfeffgbglgmq bg gcnacbcedeffhjmkujn bg ggoaaacefefffkawjoo b glkaaabdfeeffanaqff bl gnkaaabdfeeffhghxgn b ghkaaabfffeefhhaqxg b glkaaabdfeeffhoqqkb bc ghkaaabdfeeffhfqxgn b ghkaaabdfeeffhbqqbb b ghkaaabdfeeffhbxhko bc gcoabacdefeffkhaqkk b ghfaaacdefffbbhvnvb be gehabbdceeffuskumjk bc gcoabacdefeffkhhhfk b gghaacddfffeabniqbn bj gapacdcceeffocvfohg bd gcoacadeedffopdtmxf b ghjaabadfeefhkfqxgb b gklaabcdefffpnbptsc br gknaabdeefffpotxqdg b gcoacacdedfffkxakaf b gnkaaabdfeeffhgqhfb b gbhabcddefffangedkv b gbhabcedefffqmkeudk b gnkaaabdfeeffhvxhnf b ghfaabcefeffahlgnkw bp gghaabdfdefftnakxbr bh ghdaabceefffaaqfrsj bc ghjaabadfeefafgqako b gghaabbdfeefhkfhxff b gdfabacdefefbjaqhgf b gnkaaabdfeeffhgqhnk b gblacacdedfffnaxbhg b gcoacacdedfffkxafqf b gfhaabcffeefucqiluw b glkaaabdfeeffhoqxok b gboabacedfefnohaqgo b gnkaaabdfeeffhvxqbf b gcpaadeffdfeckpabub bd ghdaabcefeffqqhwknc bc gcoacacdedfffkxhfqk b glkaaabdfeeffhohqbf b gbpaaefcedefbqbbogg br gghaadcfeeefhohxqag bf gglaacdedeffevxbtgk bf gnkaaabdfeeffhgqxgb bd gdoaaaedfdeffxxhfkg bc gnkaaabdfeeffhghxof b gchacbdeedffqcthfwn bc glkaaabdfeeffanaqfn b ginacbdcdeffakkfaqf b gchaccdceefftjoqlff bc gcoabacdefeffkxhafb b glkaaabdfeeffanqxng b ghgaaacefeffffangor b gcoabacdefeffkxaakb b gcpaabcffdefbbxxnkx bj gcpaaccffdefgbxxnkx bf ghjaaabdfeffbaohhbg bc gboabacedfeffohaaok b glkaaabdfeeffhohqkn b gcoabacdefeffkhhqfb b gcoacacdedfffkxafak b ghkaaabdfeeffhfqxob b gblabacdefefkraaanf b gbpaabfcdfeffxffxfx bm gbpaabfeedfffxoffxx bce gbpaaccfeeffcvxvcxx cd gbpaaccfeefffoxfoxx be gbpaacdfeeffccxccxx d gbpaacefdeffffxofxx be gbpaaddfeeffnkxnkxx bm gbpaaddfeeffofxofxx be gbpaaddfeeffvcxvcxx c gddabbcdefffaahhqah bce gddabbcedfffaaaaaax cc gdhaaceeffefqemtxth bd gdhaadeffefehmipuxd bdd gdnaabfefeefhxthpde c gfdabbcdefffaahhqah bee gfdabbcdefffaahhqqx bcg gbpaafcfdfeeqbhbabg bm gkhaaddceeffannaxkk c glkaaabdfeeffhoqxgb bl gbhacdcdedffafkakak bc ghjaabadfeefhffhxff be gghaacceefefaglxetk bc ghkaaabdfeeffhbxhfg bh gboabacedfeffohaqog b gblacacdedfffnaxban b ghkaaabdfeeffhfhxof bq gcoacaddeeffneiidub be gcoacacdedfffkxhfhf b gnkaaabdfeeffhgqhnb b gflaaccfeeffdkhuiuf bd gjlaacddefffhbfmtog bn gcoacacdedfffkxhkqk b gnkaaabdfeeffhghxgf b gdfacbcedeffaaqqbaf b gchabcddefffqnkahjs b ghkaaabdfeeffhfqhkb b ghkaaabdfeeffhbxqbg b gblacacdedfffnahbqb b ghkaaabdfefffhfhhnk b ghjaabadfeefafgqqgo b ghkaaabdfeeffhbqqkn bo gcpaabcfdffefgxoxxf bd gboabacedfeffohaqgo b gnkaaabdfeeffhvxhff b ghkaaabdfeeffhbqhfn bh gflaabedefffaawxalr be gmhaadcdfeffdgkqegb bm gjlaacdeffefhouhahs be gbpaacefdeeffnakfob bd gcoacaddeefffmiidun bc ghkaaabdfeeffhbxqko bc gblabcddeefftbfqmbb bc gnkaaabdfefffhvqqgb b gnkaaabdfeeffhvqqbb bc gdoaaafeddefgqqqnbb b gbnabbedeeffaafhhhg b gbnabacedfefgbqqanf br glkaaabdfeeffhohqkf b gnkaaabdfeeffhvqhfb bc ghjaabbeeffftulbfko c gepaaccfdffebgxoxxg bc glkaaabdfeeffhoqxob b ghkaaabdfefffhbqqnk b gdhaabfcffeeuikxemg b gjnaaaceefffbkqongs b gehabcdceeffqbgqqgn bd ghfaaaceefffnbqbrwg bp gdlaaadfedeffhhagnf b gdnaaaefddefnqxqggb b gdhaadcdffefuoredkk b gcoacacdedfffkxhkhf b ghfaaacefffebbxsngk c gkoaaacefeffnwqjjko b gdnaabefedefexitfuf b gdlaaadfedeffhhagng b gepaadeffefejjetfqs bd ghkaaabdfeeffhfhhkf b gjnaaacdfeffffagwrc b gdhaacdfdfefqkpblgf b ghkaaabdfeeffhfqxgb b gnkaaabdfeeffhvqqbk b gcoabacdefeffkhaqkb b gghaabddfefftnnqxck bc gbpaadededffofgobxg bc ghkaaabdfeeffhbxhfo b ghkaaabdfeeffhbqqbn b gdlaaadfedeffahabnf b gdgacacdeeffggaarhb cc gcpaaecdfeeffrohfwo bd gepaaebdefffrfkbied bf gmlaabdceeffdfctugk b gcoacaddeeffneiidun b gjnaaadddffffqahovb c gdlaacfdfeefdhndhqo b ghkaaabdfeeffhfhxgf b gnkaaabdfeeffhvqhfk b ghkaaabdfeeffhbxqbo b gapabdecdfffnnonuem b gnfaaacdfeffnblsgsw b gmhaacdcffefabjqtkk b gdlaaadfedeffahabbf b gclabcdceeffhgouirf b gbhabcddefffqgjxqvb bd gapabeccdeffffrowan b gldaaacefffekohfkrf c gdfacbcedeffaaqqban b gipaaceeffefgbfhegt bj ghdaabceefffqaigfkv b gmlaacbdfffelnnxlof cc gbpaabfcdfeffxfnxnx bp gbpaaccfeeffcvxjsqq bd gapabcdedfefvvkvhbb c gdfacbcedeffaaqqbqg bc gdhaacfdfeefuijhlds b gjnaaaddefffgtuukof b gknaaacefffennqbnjf c gdlaacedefffdmnedlb b gfhaacbeefefekeahmf bf gdhaadefeffeimphtqt b gffabbcdefffaaqqhet br gffabbcdefffaaqqhip bn gboacaededffoiidhan bf gdlaaadfedeffhhagbg b gdhaabfdfdefixkifgg c gclabbcedfffqbpnhbr b gchabcddefffqnkqxsj b gbhabcdeefffmremxec c gmlaacdcfeffdkkluco bdd gfnaabcfefefmghllqn bh gdhaacdfdfefqkpblof b gdlaaadfedeffhhaonf b gapabdcdeeffngknbqg bg gdlaaadfedeffahabbg b ggoaaaceefffnkakfon bc gelabbdcdfffqggksng c gglaaccefeffibllmpn b gbhabbcdeeffhogidog b gdlaaadfedeffahaknf b gfnaaacddfffnjafsng c gbpaabcffdeffbaabfx bn gbpaaddefeffvcwxrxx b gepaabeedfefbnvvqvf c gffabacdeeffbbldkaf c gcpaadefedffckpwbud bc gmnaabcdfefflknhqgk bc gbnacbcedeffhflkpog b gflaaacefefffnhwnrv bc ggoaaaceeffffkakfon bc ghfaabbdefefdilfsfb c ghdaabceefffqqhjknj b gdlaaadfedeffahabng b ggoaaaceffefnkhofnv bc ghdaabceffefaaqrsbb bc gdlaaadfedeffhhaong b gdlaaadfedeffhhagbf b gdlaaadfeffefhhafon bc gjhaadccfeffafrdmwn b gcpaabcffdeffgxqnkq b gfnaaacddfffffxgovb c gdlaaadfeeeffahankf b gdhaaddedfefakakabb bf gdlaaadfedeffhhxgfg bl gdlaaadfedeffahakbf bf gdlaaadfedeffhhaobg b gdlaaadfedeffahakbg bc gdhaacedefffddnxmun cd gdnaabddfeffafollbs bd gdnaabdffeefafilulb bd gdhaacedefffddnxdln c gjhaacdeedffdfdxngn c gbpaacdefefffgbefae bc ggoaaaceffeffkhofnv bc gdnaabddefffafwtpbs b gjoaaacefffefohwfng c gdlaaadfedeffahakng bc gdlaaadfedeffaxabnn b gdnaabcdeeffdogxdnb c gdhaabffdeeftdmcluc bd gdlaaadfedeffhhaobf bf gdlaaadfeeeffahankg b gdlaaadfeffefhhafob bc gdlaaadfedeffhhxgff b gdhaaddedfefakakabn bc gbpaabcfdffefohfxhf bu gbpaabefedffffhofxh bce gbpaaddefeffoffhoxh be gdhaabefffeehpilpet bd gdlaabffeefeixdxxxd cd gfdabbcdefffaqhhqax bck gfdabbcdefffaqhhqqh bee regina-4.96/engine/data/snappea/snappea-census-sec7n.dat000644 000765 000024 00000052655 12377774107 023105 0ustar00babstaff000000 000000 hfdafbcdefgggaaaaaadu bh hjdafbcdcffggqqqgdkxp bj hkfagbcbdegggaabaabpd be hkfajbcbdffggaabadkxt bg hkkadabcdfgggfaqqnggl bk hkfadbcbdffgghhghkmad b hgjadbacefggghkhfbxfe bj hbpaccefdgeggknxnqfld bl hkfadbcbdfgggaabakgaf bf hkfagbcbdegggaabaadnp bc hofacbcbegfggaabnratn bj hgkadabcegfggfaqgxkgi bl hgjadabcefgggbqqbxfig bm hfdadbcdeegggaaaanbpd bc hgkadabcefgggfhqbfxbd bn hjdadbcdcfgggaaaknggl bj hkfagbcbdegfgaabahglt be hkkajabcdffggfaqqbmxu bk hkfagbcbdefggaabahpou bc hgkadabcegfggfaqgjqtg bl hjdadbcdcffggqqqgmkae bc hkjafbacdfgggafahgjcq be hgjadabcefgggbqqbgqbx bm hkjadbacdffggafahodhl bf hkkagabcdegggfaqqqiom be hkjagbacdegggafahhekl bc hjdadbcdcffggaaakniae bh hkkafabcdfgggfhqqgffd bl hfdadbcdeegggaaaandnp be hkkadabcdfgggfaqqnoba bd hkkagabcdegggfhqqqdnp bc hgkadabcefgggfhqbqcub bn hkfagbcbdegggaabqhekl bc hkkafabcdffggfaqqbiqi bh hkjagabcdefggbahqqpou bc hkkadabcdfgggfhqqongh bd hkjadabcdffggbahqniae be hkjagbacdegfgafahhfdu be hkjadabcdffggfqahodhl bh hkkagabcdegfgfaqqqglt bc hkkafabcdfgggfhqqgjcq bi hkfagbcbdegggaabqhfle bc hkjadabcdffggfhhqniae bf hjdagbcdcegggaaakqiom bc hkjadabcdffggbqqakmad bh hkjagabcdegfgbqqaabet be hkkagabcdegfgfhqqqbet bc hjdagbcdcegfgaaakqglt bc hkkagabcdegfgfaqqafdu be hkjagabcdegfgbahqqglt be hkkagabcdegfgfhqaabet bc hkkadabcdffggnaqhkmad bf hkkadabcdfgggfhqakgaf bi hkjagabcdegfgbahqafdu bc hkkagabcdegggfaqqaekl bc hkjagabcdegfgbqqahglt be hkkagabcdegggfhqqhekl bc hkjagabcdefggbqqaamnt bc hkjagabcdegggbahqaekl bc hkkagabcdegfgfhqqhfdu be hkkagabcdegggfhqaadnp bc hkjagabcdefggbqqahpou bc hkkagabcdegfgfhqahglt bc hkkagabcdefggfhqahpou be hfdafbcdefgggaaaaafdv b hfdafbcdefgggaaaaaqhx bcg hfdafbcdefgggaaaaarec b hflacbefdgffgofofqfxk b hfdadbcdefgggaaaajjbs bc hbhakdcdedfggafhaqaab b hofabbcbgfgfgaabkkkax b hbpaccefdgffgkhxnqmjg b hgjadabcegfggfhhgxjbm bo hbhafbcedfgggukxnqvrl b hgjadbacefggghkhfbxji b hgjadbacefggghkhfjxaf b hgjadbacefggghkhfcxlo bk hgfadbcbefgggaabbqfpg bc hkoaeacdfegggnkakkfsq bc hgfadbcbefgggaabbqcrm be hokacabcegfggfaqoxkdj be hgfadbcbefgggaabbqrba bc hlkacabdffgggfanxkaxn bo hfnacbedfgfgghhkknjso b hkoaeacdfegggfkahkqkx b hofacbcbegfggaabnrace b hofacbcbegfggaabnfamk bce hlkababdeffggfhoddrct b hlkacabdffgggfhoxfqao bci hofacbcbegfggaabncanq b hhjabbadefggghkfhfacl b hhjabbadefggghkfhfuvt b hhjabbadefggghkfhfoxh bo hgjadabcefgggbqqbxfre bc hnkababdegfggfhgqagiv be hgjadabcefgggbqqbxclb bo hgkadabcefgggfhqbfxrm b hlkababdegfggfhohoave b hlkababdegfggfhohfoqa bci hgjadabcegfggfhhgkqmb bcc hpjaabagfegfgafbbaodi b hgjadabcegfggfhhgjqrp b hgjadabcegfggfhhgrqgh b hokacabcegfggfaqokhpf bg hokacabcegfggfaqorhjl be hokacabcegfggfaqojhoq bc hgkadabcegfggfaqgjqrp b hgkadabcegfggfaqgkqmb bce hpfaabceffgggaabcuvms b hgkadabcegfggfaqgrqgh b hgjadabcefgggbqqbcqer bc hgjadabcefgggbqqbfqbl bk hgjadabcefgggbqqbrqag be hfdadbcdegfggaaaaknbk bc hbpaccfedgffgknxnqokg b hokacabcegfggfhqnfamk bg hokacabcegfggfhqnrace b hokacabcegfggfhqncanq b hgjadbacefgggafadhxfe bc hgkadabcefgggfhqbqcrm b hgkadabcefgggfhqbqfpg bk hgkadabcefgggfhqbqrba b hpjaabafeggfgafqnnllf b hbpaeecfdffgganxankxf b hojababcfgfggbqqbxggx bc hflacbefdgffgofofqfxb b hlkababdefgggfhohttla bc hofabbcbegfggaabiqalf b hdhaidcedefggkqxsinaf b hbhakdcdedfggafhaqaan b hfjafbadefgggafbbgbbq b hnkababdefgggfhgquuap b hnjacbadefgggafbqtteh b hdkafabdefgggfannnnka b hhjacbadfggfghkfrgbdf bc hnkababdfgfggnabxeihl b hbpabdcfdgfggfoxfevhl b hpkaaabgefgfgfhhvvrdi bc hhjaebadfeggghkfbhklp b hbhakdcdedfggafhhqhhg b hgjadbacefgggafawhxqa b hpkaaabgeffggfhqvvmmj b hlkababdegfggfhojqqct b hnjaebadefgggafbqkobo b hgkadabcegfggfaqvxqah b hfdadbcdegfggaaaaccxa bc hfdafbcdefgggaaaacccv bc hkoabacdegfggfkakbulx bc hbpabdcfdggfgfoxfuefh bd hdkafabdefgggfhoooofh bc hgjadabcegfggfhhlxqgi b hdkafabdefgggfannnnnx b hnjaebadefgggafbqggkb b hofabbcbegfggaabgqaqa bc hgkadabcefgggfhqsqxha bc hlkacabdfgfggfhorgubo b hhjabbadegfgghkfhiiad b hlkacabdffgggfhoxepad bg hokacabcegfggfaqvxhaq b hhjaebadfeggghkfohfhi b hfkafabdefgggfhgggggx b hgfadbcbefgggaabbaalm be hokababcegfggfaqdqhek b hojababcegfggfhhdqhek b hlkaeabdfegggfhobhkok bc hnkababdefgggfhgquula b hnkaeabdfegggfhgfqngn b hdkafabdefgggfhooooox bc hgjadabcegfggfhhvxqah b hlkababdefgggfhohttap bc hnkaeabdfegggfhgbqbgf b hokacabcegfggfhqsxahq bc hojababcegfggfhhfqhqh bc hokababcegfggfhqiqalf bc hokababcegfggfaqbqhqh b hlkaeabdfegggfhofhfob bc hokababcegfggfaqfqhqh bc hojababcegfggfhhbqhqh b hgfadbcbefgggaabbxqah bc hokababcegfggfhqgqaqa b hokababcegfggfhqkqaqa b hgfadbcbegfggaabbkkxe bc hgfafbcbefgggaabbcvnj bc hgjadbacefggghkhfaapi b hfdafbcdefgggaaaaqqie bp hfdafbcdefgggaaaaqqlu bp hdpaaegfdgfegkriebxkq b hgjadbacegfgghkhfnnid bc hgjadbacegfgghkhfrrdx bc hbpaccefdefggkkxnakkk bc hbhafbcdefggglfndqqgb bf hbhafbcdefggglfndqqrw bf hofacbcbefgggaabnggxm be hofacbcbefgggaabnjjem bcc hgjadabcefgggfhhgccxl bc hgjafabcefgggfhhgvvam bc hdlaeceeffgfgmometquk b hgjadabcegfggfhhghhpe b hokacabcegfggfaqoqqld be hgjadbacefggghkhfxhaq b hokacabcefgggfaqobblp bc hokaeabcefgggfaqorwmi bc hgkadabcegfggfaqghhpe b hcpabcdffegfggggxbabf b hgkafabcefgggfaqgjsim bc hgkafabcefgggfaqgvvam bc hgjadabcefgggbqqbaape bc hgjadabcegfggfhhgqxha b hokacabcefgggfhqnggem bcc hokacabcefgggfhqnjjxm be hokacabcegfggfhqnqqei b hgjafabcefgggfhhgjsam bcc hgjafabcefgggfhhgvvim bi hnkababdfgfggnabxdgmg bp hnkababdfgfggnabxegig bp hokacabcegfggfaqohxqa bc hokacabcefgggfaqocclp bc hokaeabcefgggfaqovvmi bc hgjafabcefgggbqqbjjsk bc hgjafabcefgggbqqbvcsb bc hgkadabcefgggfhqbaalm b hgkafabcefgggfaqgjsam bcc hgkafabcefgggfaqgvvim be hknabbbdefggghgkktfhu b hgkadabcegfggfaqgqxha b hgjafabcefgggbqqbjjbk bc hgjafabcefgggbqqbvckb bc hgkafabcefgggfhqbcvbj be hgkafabcefgggfhqbssbj bcc hokacabcegfggfhqnaxqh b hokacabcefgggfhqnggxm bc hokacabcefgggfhqnjjem bc hgjadabcefgggbqqbqxha be hffafbcdefgggaaaqhhaq bci hgkafabcefgggfhqbcvnj bc hgkafabcefgggfhqbssbn bc hgkadabcefgggfhqbxqah b hkoaeacdfegggnkaknacv bm hkoaeacdfegggnkaknank bm hnfaebcdefgggaaahqkxn c hnfaebcdfegggaaaaxcca bk hdlaeaffefgggffhaegpc c hdoabaedfgfggfhaqhbww b hnjacbadegfggafbqgget bd hnjacbadegfggafbqggld bd hdlaeaefeegggfnhamgol c hhjabbadffggghkffpqev b hlkacabdffgggfhoxfmlf bp hlkacabdffgggfhoxfpef bp hjlabcedgggffnnnhxhab b hnfabbcdffggghhhilhtt bd hhfabbceegfggnkikkslw b hbpabcdfgegfgkvxjmfle bcc hbpacfdfegfggkdxcwmdg c hbpacfdfegfggkfxcwmfg bi hdpaacfegfgfgvoixiksp cc hjpaaccgefgfgqnckqtqw bc hdpaaeffdgfggqbgkxtge c hdpaadeeggffgkhnxxbtk bk hnlaaacffegfgfnwehjnf be hbnajbedeefggaafnkaaf b hhjabbadefggghkfhooie bj hhjabbadefggghkfhoolu bj hjlaeacdefgggfnxnkaoj bm hjlaeacdefgggfnxnkasf bm hblafacdefgggknhhhqpt bc hcnadbbdefggghgkkftlp b hepabedegdfggtotaoxjo bc hbpaecdffefggfhxdfoab bc hjpaaefegedggjqoqjnah b hpdaacbfgfgfgqqwtptpr bd hllaabeegfffgqxoxsqfn b hndabbcdfgfggqqqdmonm b hblafacdefgggfnxjgodv c hjlaeacdfegggfnxdljoa bk hflacaceeffggknammebn b hblajbddeefgglgekoxab b hdhaicdfdffggqunixmab b hbpabdcedgfggooqguclh bf hjpaacfddggfgknnbcgrw bf hbhajbcedefgglfndkqqn b hdpaaegfdgfegkriebxbq b hnkababdegfggfhgqbbei bg hnkababdegfggfhgqbblu bg hdlaicdefffggeqhmgehk b hknaebbdefggghgkhhqkc bc hdhaedeeffgggarxqaand b hlkababdegfggfhohffei bj hlkababdegfggfhohfflu bj hbhafcddefgggqnkxqbgx b hnkababdffgggfhggdlhc b hdlaeceeffgfgmometqub b hblafacdefgggknbagomv c hflabaceegfggknalrtxw bi hdlaeceeffgfgmomethuk b hnlaaacdfggfgkngbfinq b hcoadacdefgggfkaosuhe b hkoabacdffgggfkaddkwu b hlkababdffgggfhooepqc bi hcpabcdffgeggavnxqkxn bc hflacaceegfggknamaerg be hmpaaecfgegfgflogmkxx bc hnfaebcdfefggaaahqkak be hclajbcdeefggpntfoxqn b hcoadacdefgggnkaosuhe bc hkoabacdffgggnkaddkwu bc hflacaceegfggknanakbw be hflacaceegfggknanakrg be hcoafacdefgggfkhhqhmd b hffafbcdefgggaaaccacv bc hnfaebcdfegggaaaaaacv bc hbhajbcedefgglfndkqqb bc hfnaibeedefggaannkaqo bc hfjagbadeegfgafbfqneu bc hbhajcedeffggqkkxvqhn bc hhjaebaffegggafdqpbth b hdlaicdfdffggqmmtqnhg b hdpaadedggffgglqgxgnu bcc hcoafacdefgggfkabobcp c hkoaeacdefgggfkaeirqr bk hkoaeacdeffggfkattibf b hboafacedfgggfnhaqqah b hhjaebadfegggafkqahof bc hndabbcdfgfggqqqieomg bc hlkababeefgggfhippucp be hkoaeacdefgggfkattawb bcc hklaccdeeggfgkkhnkcgq b hdjadabdefgggbakkftlp b hooaaacefffggfkqfmkbg b hlkaeabdfegggfanqqhnc bc hhjacbaffefggafcqaemm bg hjlabacdggffgfnxbiaec bj hldacbceegggfqqcdetgt b hjlabcdeggffgknqbtwqh bd hcoadacdefgggnkanwuhm be hkoabacdfggfgnkahkblp be hdpaaedffgfggqnfoxetb c hkoaeacdfegggfkannagr bce hkoaeacdfegggfkannawb bce hfnacbefdgfggaafhblvv b hfkadabdegfggfhggouid b hhkababdffgggfhfvmxdo b hdlaccfeffgggetxmeqdl bd hdlacadfegeggfxhhhoof bcc hepabedegdfggefeafxjo bc hhkababefegggnapdahun b hepacdddfggfgngnobewp b hfnacbedfgfggbgghbrqb bc hkoabacdfggfgfkahkblp bf hkoabacdgffggfkanqdrp bf hhkababdffgggfhbvmxdo bc hbnajbedeefggaafnkaqf b hpkaaabgfeggffhxxhaqo be hflaccceeffggdkxsaekk bc hflaebddeffgglgobopwf bc hhkaeabfefgggfhimqgua be hnfabbcdffggghhhilmtt bg hnfaibcdfefggaaahqban b hflacaceeffggknammewn b hbnajbedeefggaafnkaak bc hdkadabdegfggfhoogtem bc hdhabbffedggglpbxdrfj bc hkoaeacdefgggnkaeiabw bc hhhaacefgfeggmxhhpvaj bc hnlaaacffegfgfnwehjng b hhkababefefggfhrqhlll be hdpaacfgeefggnxfqkwvk bg hflacccefefggdkxlkacg be hdpaaefdgdffghxnlnodo b hdpaafgeggefffrowqoqf b hcpaceedffgggqnckxkxa bc hhjaebadfegggafgqahof bc hcpabdedeffggcncaxnnf b hnkaeabdfegggfhghhagr bc hhkababffefggfhjqhlpp bg hkoaeacdeffggfkattqbf b hknabbbdegfgghgkkwuhe b hdpaacfdfegggnxwkkrfd b hkoaeacdefgggfkaeiabw bcc hglabcceeffggmfenaacf b hdhaicdfdffggqunixmhg b hlkacabdfgfggfhpxgobp b hcpabecdgfgfgaoapduen bc hapajcdedfegguuntjnaf bc hblajcededfggswnsnlaf bc hfpaafegfggefftwnfwds bd hflacaceeffggknammebb bc hdlabcefegegghfhoxxfc b hlkaeabdfegggfhoqqaoj bcc hboafacedfgggfohaqqah bc hcnadbbdegfgghgkkanlx b hlkaeabdfegggfanaxakn bc hflaibddeefggqunprwho bg hcoafacdefgggfkxaaahq b hfpaaceffegggifriioox be hfpaafgdfegfgkrnriouo c hnkaeabdfegggfhvxqqbg b hdgadacdefgggnfhjsxfb bc hflaeaceeffggknamqebb bcc hfhabbcdefggguknowpgs b hgoacadfefgfgdgdmrbak bd hflaibddeefggqunprwab b hpjaabafgeffgafqqaqaf bc hbpabddfefgfgaexawrwg b hlkababdegfggfhphomcv b hfhabbcfefgfglfcbwsmb b hhkaeabdfegggfhfqhank b hdnabbfdeggfghxkhaxbq bc hflacaceeffggknamqebn bc hfhaicdefeeggofxjcvqf b hnlaaacdfggfgknobfinq bc hglacccfeefggmfrcuxtg b hkoaeacdeffggfkattirf b hnkaeabdfegggfhgqxqgb bc hdlabbedfegggowcnughg b hnfaebcdfegggaaavvrba bf hghaidceeefgggbcvxbhf b hpkaaabgfeeggfhxqxgah b hdlabaefegfggfnhmjmfi bc hpkaaabgfeggffhxxhaqg b hkpaaedfggffgstesbeju bc hgpaadgfeefggpqnodnxf bf hcoafacdeffggnkannkak bcc hfpaadgefegfgmqasamer b hhkaeabdfegggfhbqhank b hhjaebaffegggaffqjbgj b hflabccefefggdkxakank b hlkaeabdeffggfanggmgo bc hlkaeabdeffggfanjjmjk bc hpjaabafgeffgafqaaqaf bc hkoabacdfgfggnkaupxcc bc hnjabbadffgggafbrbnkh bg hflacaceeffggknammewf b hnfaebcdfegggaaaccjxj bd hkoaiacdeffggfkattqbg be hlkaeabdfegggfhohxhof bcc hdlacadfegffgfhhahahk bd hfkafabdeffggfhgjsmjk bc hfkafabdeffggfhgvvmvg bc hapadcdeegffgdoddqbgn bc hbhadcdeegffgwoccqugn bc hbpabeddeffggwgiajggg b hbpabeffdfgggaoxajsqs bcc hffafbcdefgggaaaqhqdu bt hbhafbcdefggglfndqacn bd hbhafbcdefggglfndqakv bd hnkababdegfggfhlqgicv be hlkaeabdeffggfanggmwf bg hlkaeabdeffggfanjjmok bc hcoafacdeffggfkannkak bc hbpabfdfgfeggeuxgeect bc hglacbddegfggkrhlmihi b hflaccceeffggdkxsaenf b hdpaaefdgdffghxnlnodg b hkoabacdfggfgnkaivghu bd hkoabacdgffggnkafpxcu bd hkoaeacdeffggfkattibg b hhfaibceeffgghhggbxxb bc hglaccceegfggmfeiswnd bc hnjabbadfggfgafbcknmw bc hlkababdegfggfhojqocv b hhjacbadfggfghkfjgbfq bc hdlacadfegffgfahaaahf bg hcoadacdefgggnkajvtgk b hgpaaeegffdggevogxnid bc hcoadacdefgggfkacpttg b hhdacbcdfgfggqqrwqtrc bc hooaaacefffggfkqfmkbo b hlkababdfgfggfannppqg b hipabecdfegggriifdnan bc hnfaebcdfegggaaavvcav bc hdlaicdfdffggqmmtqnho bc hdlabadfeggfgkxhlmfli bc hdlabadfgegfgkxhdufmt bc hdpaacfdfegggnxtkkxkd bc hfpaaedggeffgwnckweot bf hbpacfcdeegggksisswib bc hblafccdefgggdknxhajo bn hbpabcdfegfggcaxccaca bc hbpabcdfegfggjhxjhjhj bc heoajacdeefggfkjsraaf bcc heoakacdeefggfkwwkaqo be hcoadacdefgggfkabcuxd bg hkoabacdfggfgfkaejvau bg hflacccefefggdkxlkaco b hdpaacfeegfggsbsbhcik bce hcpaccdefggfgggflswes bcc hhdabbceeffggqqjlncxk bi hhhaacgegfefgemeumsqw be hcpacecdfegggrnclkksl b hdlaicdfdffggqmmtqnab b hfhacdcfdfgfgscxcwcom b hhdabbcefefggqqjffqxk b hdkafabdeffggfhorwirn be hdkafabdeffggfhovvivf be hflaeacffefggfnnwuikk b hbpacdedfggfgajrcbesj cc hbpabecfgegfgxqxxqqha bce hbpacfefdgeggeixfjfwd bk hdpaaefdgfeggixfsiftn bg hepacdefegfggcurmsktu c hfpaacfeeggfgexdjinhp be hgpaadeffgeggcuavvavt c hgpaadgffeggfcwavxcvs c hpdaabceefgggbbbxgbxg be hpdaabceefgggbbhwaawh c hpfaabcegffggaaboeots bd hfkafabdeffggfhgjsmon bc hfkafabdeffggfhgvvmnb bc hpkaaabgfeffgfhqqhqhk b hdkadabdefgggfannaklx b hflaeacffefggfnnwuikb bc hpkaaabgfeffgfhhqhqhn b hcoadacdefgggfkajvtgk bc hkoaeacdeffggfkattirk bc hcpacdfefgeggctraskux bi hnkababdfgfggfhggiihf b hpkaaabgfeeggfhxqxoah bc hdkafabdeffggfhorwigk be hdkafabdeffggfhovvikf bm hhkababefegggnaojajkn b hhjacbadfgfgghkfrgmbj bc hflabcceegfggdkxdcjcx b hflaeaceeffggknamqebk bc hbpabcdeegfggjhsjeuig bq hbpabeddefgggacccimbu c hbpabeddefgggvacaimbv bcc hbpabfddefggglacaipmb c hbpacfefdgeggkixfxfwd bc hfpaadfdegfggbxgmmsse b holaaccffggfgmfxfxrri b hhkaeabfefgggfhkcqgbc be hhfabbcegefgghhjbxsdo b hbpaccefdgfgggnkbbpfe bd hnfabbcdfggfgaaaepule bc hlkababdefgggfhokdjcv b hnkababdffgggnabrbnkh bd hfkadabdefgggfhggqbdx b hfnacbedfggfghhkkncvk bc hndabbcdggffgknefxbfj b hbpabecdfggfgpuolxocc b hpjaabafgeffgafqqaqag b hhdabbcfeegggknrnxnxo b hbpabeddeffggwgiajggo b hlkacabdfgfggfhojgoba b hlkababdfgfggfhoommqb bi hdpaaceegfffgmecxbood b hdpaacfdgegfgxeqxggjf bc hcladbddegfggittdcmwi bc hdpaacdffgegguddmknkr bcc hpjaabafgeffgafqaaqan b hbpabfdegfggfiwfboxim b hfpaaefgdefggpgixplol be hdpaacgdgfgffmdsxbcwd bc hfdafbcdefgggaqhhqaet bv hcoafacdeffggnkannkab bc hnkababdfggfgnabcknmw b hdlabadfeggfgfxhlmfli bcc hdlabadfgegfgfxhdufmt bcc hpdaabcfdgfggknwevthq bc hdkadabdefgggfhoohfex bc hdoaiaedfeeggfhahhaqk b hkoaiacdeffggfkattqbo b hdoaiaedfeeggfhaahaqf bc hdpaadfegeggfhhhxwitg b hhlaaafegegfgfhawlxll bc hjlaeacdfegggfnxcvsoa bc hdnacbdeegfggfqkmaoca b hlkaeabdeffggfanggmgg bc hlkaeabdeffggfanjjmjb bc hhfacbcdeffggaawbawqf b hlkacabdfggfgfhorgbls b hflaccceegfggdkxmsslk bf hnfaebcdfegggaaaccccx bc hlhaadcfeggfghnhsswtu bd hlkaeabdeffggfanggmwk bcg hlkaeabdeffggfanjjmof be hjpaafdfdefgghgeutkjb bc hcoafacdeffggfkannkab b hgpaacefeggfgbqbssrxc c hbhajbdecffggnixlnlkg bd hkpaaecdfgfggxxkxcgdb b hdlacadfegffgfhhahahf bg hnlaaccffegfgdkxsjwpl bc hfkafabdeffggfhgjsmjf bcc hfkafabdeffggfhgvvmvf bi hohaacdgefgfgwbbxflgc bc hdpaacefegfggbgpdncgk bcc hdpaacfefgeggnxpkblwd bcc hghacccfegfggendxtmop bg hjhabcdedgfggfofoxhqa bcc hpdaabceefgggaafqxxfq cc hpdaabceefgggbbnuxxni bc hpdaabceefgggbbpswwjm bg hpdaabcegffggaafqxqxf cc hpdaabcgffgfgaaqcxvqx bce hepaedefeffggcurmokwb b hcpabdfegfeggpkekxwkx b hbpacededffggbwuhbvgf bc hdfadbcedgffgaaknaaff b hcnadbddefgggebbsnpsk b hgpaaecfgfggfcibsbkxs b hdlacadfegffgfahaaahk bd hhfaibceeffgghhggbxaf b hflabbeeegffgaaknxafk bc hdpaacegfegfgnekikwon bc hjhabbddegffgpbmkxhgf b hdlacadfegggffxxaankn bc hbpabccffgfggjsxhrhxr b hflacaceegfggknanhkkc bc hdhabceffdfggnpnxnmct bd hblafbcedfgggioxohhwr br hhdacbcdeffggknodbiff b hfkafabdeffggfhgjsmob bc hfkafabdeffggfhgvvmnn bc hdpaagdfeffggfmimikwn b hbpabfdfefgggeuxlekwl b hhdabbcefefggqqjffqhf bc hfpaafgeefgfgsxvcsxxx b hbpabeedfefggxjcxxigb be hcoadacdefgggnkacpggk b hpkaaabgfeffgfhqqhqhb b hdlabadfeggfgkxhudfgw bg hdlabadfgegfgkxhmlfgw bc hpkaaabgfeggffhhqxqab b hbpabededgggfviuuqmpf bc hhlaaafegfeggfhawiutd bg hhlaaafegfeggfhawplpl bc hpkaaabgfeffgfhhqhqhf bc hfhabceeffgggtixsrblo bg hpkaaabgfeggffhhqxqan b hdkafabdeffggfhorwirb bc hdkafabdeffggfhovvivg bc hcoadacdefgggfkacpggk bc hdlaibefdfeggqxrqwlqu b hfpaacegegffgctjjissw bc hdlaccdefgfggkbxnklpu bc hfnaebeefeggghhfoofko b hmlaccdcffgfgdlknhdrb b hipabdeeffgfgpbfofqrn bc hbpabfedfggegtnvuxvnt be hlkaeabdeffggfhobbpwf bg hlkaeabdeffggfhoccpnk bc hlhaacdfgggffqkvaowob bf hdhabcfefegggvcxcaxac bc hlhaabegfgffgrxjrjmae bc hcpacedefgggfuduaxffi bc hkoaeacdfegggfkannhkc bh hlnaabeefgggfsxkqbmqb bd hkoaeacdefgggfkakkrxr bc hpdaabceefgggaafkxxfk ce hpdaabceegfggaafirrfu be hpdaabcegffggaafkxnxf bce hpdaabceggffgaafirtrf be hpdaabceggffgaafkqnqf bce hpdaabceggffgaafqrqrf cc hpdaabcffgggfaalcrver be hpdaabcffgggfaaxcrvxr bci hpdaabcgffgfgaafctvod bc hpdaabcgffgfgaafcxvox bce hpdaabcgfggffaadcrvir c hpdaabcgfggffaafcmvoe c hpdaabcgfggffaafcqvoq cc hpdaabcgfggffaaqcrvqr cc hhdabbcefefggqqjffqhg b hbpabcedgffggcemekvsl be hdhaecdfeefggcjlcinld be hflacaceegfggknanakfj bi hnhaacdfgggffuaoktwsp bg hbhadbcedgffglfndxqok b hcoadacdegfggnkajjakg b hblafcdeefgggipuxbkqu bd hepacceffgegghvfienuo bc hbpabcfdgegfgxaxaaxcc bc hpdaabcdfgeggaaicvtel be hpdaabcedffggaafdmpfu be hpdaabcefegggaaeclvel cc hpdaabcffgggfaaiclvtm bm hpdaabcgfggffaaeclvpm cc hbpabddeggffgngsjbbut bc hbpabeedfgfggbfcwcimb bc hdlabbefggfgfcxaxcxcc bc hdpaadfegegfghxhhhxjs bc hfhacbcdffgggsxxswxsd bc hllaacdfeegggkhuslwin c hcpaecfddfgggfgfuxtvu bc hdpaafffggeegccxxxvcx bc hohaaccegfggfcdxeqndd bc hfhaicdfedfggwoxjowwd bc hndabbcdgfgfgkneffcbm b hfpaaceggffgfcejbaxxo bc hfhaecdfedfggcodcgcci be hapaddbedfgggoflpxgev b hkhabdcegefggahfxjohf bc hkoaeacdefgggfkaccrxr bc hdpaadfegeggfkanjwwtb b hdpaaefggefegkxpehdak be hgpaacgfffeggprexmhsp b hdhacdfeegfggeexlsxhg c hldaibcdeffggqqjpcnak bi hjhaedbeffgfgeexidvfe bc hdnabbdfeggfgafmmhtsi b hkoaeacdefgggnkaccccx bc hlhaadcfeggfgkqgexwcm b hhdabbceeffggqqjlncxf b hipacecedffggkmpeejvg b hfhabdcfgffggueecufnk b hbpabcdegfgfgcxepaboj bcc hdpaacgefgefgpqomjbtr bcc hhdacbcdeffggknodbiof b hcnafbcedfggglkubqhbr bl hcnafbcedfggglkubqhgw bl hnhaabcdffgggjdnhoxds b hcoadacdegfggfkajjakg bc hbpabdfegggffqwqffhrx b hdnacbdfeefggafvclacl c hepacedffggfgvordbgnq be hmpaaecdfgfggujksvrvh bc hkoaeacdefgggnkakkjjx be hfdafbcdefgggaahhqqdl bx hkoaeacdefgggfkaccccx b hlnaabdgfefggfqwrreww b hbpabcdegfffgctqtarfb b hfhacbcefgfgglfditqdv bg hfhacbcefggfglfdituav bg hkoaeacdfegggfkannafj bn hbhafdceefgggkgakltlb b hcpabcdegffggdtdvsilt bcc hbhadbcedgffglfndqqof bi hcpaccceffgggabaxkurn b hnnaabcggeffgmgtwrsha c hnnaabcggfffgmgtwbshq c hjpaacfdeegggmuexevpk b hgpaadfgeffggpwifxpkv bcc hpdaabcefegggknmfbolb b hdhabcfefgeggctwxatdu bm hdpaaggfegefftwgaxxti be hdlacadfegeggfxhxhfof bcc hipabcdegfeggaakvnkah bcc hjpaacdefggfgiipevudw bc hlhaabffeggfgixixmelt c hpdaabcfeegggknwqcwvq b hbhadbcedgfgglfkuhxhx bg hehadbdcegfgglqfbvkqa c hkoaeacdefgggfkakkjjx bf hhnaabdgeefgghkjpdgsh bi hhnaabdgeefgghkspdgsx bcc hnhaabcfggefgjdgxdouv bc hjhabcedgffggnihsuwdv b hgoaeacfeffggfkswflwd bc hdlaeadfedgggfhhagqbg bc hbpacdeffgeggmmxluefb be hcpabeffdggfgluremetj b hhlaaafegefggfhawkind bc hhlaaafegefggfhawkpnl bc hdfagbcdeegggaankbmtg bc hdfagbcedefggaacvbdgl bc hipaeecdffgfgtktqebsg bc hnlaaacffegggfnwqtfqi bcc hdlacadfegeggfxhxhnof bc hgoabacdfggfgfkrfjatr bc hbhafbcdefggglfndqqjs bi hbhafbcdefggglfndqqof bi hhdabbceeffggqqjlncab b hnlaaacffegggfnwevfuc b hnlaaacffegggfnwktfki c hnlaaacffegggfnwqvfqc bcc hnlaaacfgegfgfnwmvfpc c hnlaaacfgegfgfnwntfni c hnlaaacfgegfgfnwnufnd c hnlaaacfgfgfgfnwnmfnm bf hnlaaacfgfgfgfnwnqfnq bck hdpaaefdggfgfbhbjxajq bc hkpaadedggffgjqoudgeb b hnnaabcgfffggmgtdbskq bcc hnnaabcgfffggmgtjasur bd hnnaabcggeffgmgtwqshg bq hnnaabcggfffgmgtkaspr bd hnnaabcggfffgmgtubsnq c hnnaabcggfffgmgtwashr cd hnlaabcggeffgiouwkwii bc hlhaadcfegfgghnxjjhoh b hpdaabcegefggknrsurxk b hbpabfcfeggfghbrtkgkj bc hbpabcedggffgmqqrtewi bd hhlaaafegggfffhawkoah c hdpaaedgggfffnjhssdud bc hdpaacgdeffggcpxxdwsk bcc hjpaaccgfegfgcxsagcfw bcc hkpaaedgegffgetbokhwi cc hjhabbddegffgpbmkaxnb b hnlaaacfdggfgfnwefltm bm hnlaaacfefgfgfnwluftu bce hnlaaacfeggfgfnwldftm cc hnlaaacfgegfgfnwdlftm cc hffafbcdefgggaaqqhqax bcm hdlaeadfedgggfahabqbg bc hhlaaafegefggfhawlopf bc hhlaaafegefggfhawuotf bc hdlabbeefgeggdxfkcipg b hdhabbdegfgfghgvhkjos bg hdlaebeefegggqxldurwq bc hghacdcfffgggkbknjsmt bcc hcpacecfdegggofkwadsc b hdhabcddeffggwwwxslxt bc hbpabfddefggggkmqgqjm be hohaadcgfegfgthbwscdd be hdfafbcdefgggaaknknsk b hdhabbdfegfgghgxpokrm bc hjlabceddgfggnnkkxaqh bcc hhdacbcdeffggknodbijk b hfpaaedffgfggjcdxsijx b hdhabdcffefggvxcvjdpm be hjpaaccgfegfgcxsamcdw bcc hjpaaecfggefgwuqkplsw be hlnaabdfefgfgcsrxxacm bcc hbpabcfeeggfghbshkmtk c hbpabfddefgggfacawuru bcc hjpaacedggffgkhhlsmjw bd hhhaabdgdgffgknkbaqhx bc hbhadbcedgffglfndqxkf b hhlaaacgegffgllwqmlse bc hfhacbcefgfgglfdiemmg bc hhlaabddegfggkhnjwbir bc hhdacbcdeffggknodbijb bc hbpabcefegfggedxdwwlu b hbpabfefdegggeixwxwqu bc hdpaacfgefggfsxhxjjhj bc helagadceegggfknnwler c hohaacdfgegfgtptfsagc bc hjhabbddegffgpbmkaxnk b hbpabedefggfgvaltmenl bc hgpaadfgdffggdpgbbfsj bd hlhaacdfffgegnhtplwel bc hdlaeadfedgggfhhaoqbg b hdhabdcfgffggvuqmnruc b helafacdeegggffofrwdt c hpdaabcfgefggaavcacca bc hpdaabcfggffgaavcaacc bc hblafccedegggdkotsiao bc helafcdceefggdeksalxl bc hcpacecdfefggtsnlltsn b hbhadbcedgffglfndqxkg bc hddadbcdegfggaaknxahq c hddadbcedgfggaacvxaax bk hjhaiccdffeggqmkrjeoe bg hdlaeadfedgggfahakqbg b hflaeaedffgggeeqswmeq b hdhacbfedefggtnxhumsp b heoadacdegfggfkknxaqh bc hbpabcfffgegghbicshlc bd honaabcfefggglkearres bc honaabcfeggfglkeabrps bc hdpaadfegeggfkhnjwwtg b hcpabecfgegfgtavuwbdw b hhlaacfgegefgenomkjmu bcc hjpaadfceefggfmepelwe bcg hfhabdefdgfggsefkgett bc hchaddccegfggkhqabebf c hcladbcdegfggpnioxaax bk hboadadedfgggnghaaoni b hdlacbedegfggqlnpjfiw bc hgnabbdegfgfgmwebtppi be heoagacdeegggfkknfmop c hhhaadgefffggcxxxxcwr b hbpacfeedggfgeefpnpmh bc hboadadedfgggfghaaoni bc hdpaadfegeggfkhnjwwto bi hghacbdfefgggudetcsno c hjpaaedgdfgfghflxflfw c hbpaecdefegggxjspxikg bi hbpaeededfggghjshpikg bcc hjpaaccegffggfofhvhcw bc hbpabcdeggffgxfxopwqo be hdhacceefegggffrvtjsh bcc hdhacceefegggffrvtssx c hdhacceefegggqemttjsh bc hdhacceefegggwccftjsh bi hdhaccefeegggddlxtjsh cc hfhabbdcgfggfnjenwuxe bcc hghacbcfeegggmghxmgld c hhlaabfgfefggeurxdewq c hhlaabfgfefggfurvdewq bc hhlaabfgfefgglurpdewq bcc hhlaabfgfefggluwpdewx bi hhlaabfgfefggrurrdewq cc hfdafbcdefgggaqhhqadl bD regina-4.96/engine/data/snappea/snappea-census-sec7o.dat000644 000765 000024 00000251101 12377774107 023071 0ustar00babstaff000000 000000 hfdafbcdefgggaaaaaafo bg hfdafbcdefgggaaaaaajs bk hkfagbcbdegggaabaabgk b hkjagabcdegggghhhhgvb bf hjdadbcdcgfggqqqglklq bh hlhaacdgffggfqkhxuojk bp hkjajabcdffggnqqqgbqb bn henakbdddefgghwbgqqqn bl hkfagbcbdegggaabaakng b hfhaebeddfgfgqqofhqfn br hhdabcbfegggfqqqnqhaf bh hkfagbcbdegggaabaasnk bf hfnaebeddfgfghhkoahbg bt hkdadcbbdgfggqqnqefth bf hfnabbedeggfgaqkixgnn bh hnkababdffgggghfxffof bt hkjadbacdfgggafaanmmq b hkdajcbbdffgghhkhvoxg bv hlfaibcdfefgghaucfcun bi hhfabaceegfggnbqgqbml bu hjnabbedfgegghhfuxkfb bv hgkadabcefgggnhhfmxfg bf hfdadbcdeegggaaaanbgk bf hfdadbcdeegggaaaanbsg b hkkafabcdffggghhhfnhg bx hkkadabcdfgggfaaanmda b hgdadbcbegfggaqfgxpbs bx hblakccddefggtfrgthab bh hkfagbcbdegggaabahgbf b hkfagbcbdegggaabahgvb b hapajdedefeggowwfhohk by hokacabcefgggfaakamfk be hkfagbcbdegggaabahfob b hkfagbcbdegggaabahvof b hkkadabcdffggfhhhofhf bu hihakccdcefggqjofhhhf bq hkdafbcbdffggqqfhfoho bw hkkadabcdfgggfaahoqah bo hkjafabcdffggnqqafoho bx hkjafabcdfgggnqqafahq bn hkkagabcdegggfaqqqfob b hkkagabcdegggfaqqqvof b hkjagbacdegggafahhnko b hkjagbacdegggafahhwkn bf hkkadabcdffggohhhknan bz hkfafbcbdfgggaanafahq bl hokacabcefgggnaaktxkg bB hmnacbbdegfgganfhffjs bh hfdadbcdeegggaaaankng b hfdadbcdeegggaaaansnk b hkkagabcdegggfhqqqkng bf hilakcbcdefggqgbbqqaf bx hjdafcbdcfggghqqkghaq br hkkagabcdegggfhqqqsnk b hgdadbcbegfggaqkgxpbs bC hipaicedfeegggsgqsgak bi hkfagbcbdegggaabqhnko b hkfafbcbdffggaanafnhg bD hhdabbcfgeggfqqqefthb bh hkfagbcbdegggaabqhwkn b hjfakaccdefggnnkahhab bB hjdafbcdcfgggaqaobaqh bn hkjadabcdfgggnaaakihi bc hkfajbcbdffggaanawkxf bE hkjagabcdegggbahqqfob b hkjadabcdfgggghaakihi bd hndaibcddffggaahgwkxf bF hkjagabcdegggbahqqvof b hkjadabcdffggghhqngaf bF hkkafabcdfgggfaahglmq bf hkjafabcdffggnahhfoho bz hkjadabcdfggggqaanqha bt hkjagbacdegggafahhfon b hkjagbacdegggafahhfwo bf hjfakaccdefggbbgqqahg bA hjdadcbdcfgggqhaknqha bs hgkadabcefgggkqhfhmwo be hokacabcegfggghanuajk bG hkkadabcdffggkqqakoab bG hkjafabcdfgggghhqbeqp be hkkafabcdffggoqahgbqb bD hkfadbcbdfggghagqoqah bp hkkagabcdegggfaqqqgbf b hkkagabcdegggfaqqqgvb b hkjadabcdffggnahhknan bE hjhaicedfeeggqqkqhaak bo hkfagbcbdegggaabqhfon b hkfagbcbdegggaabqhfwo b hapajdedefeggowwfhohf bH hgjadabcefgggbqqbmqng bf hkjafabcdffggghaafnhg bH hkfakbccdefggdlnahhab bh hkkadabcdffggfhhhobhk bI hkjadabcdfgggnaaakiae bc hkjafabcdffggfhhqbgqg bD hhdaccbfegggfhqhbaqho bt hjdagbcdcegggaaakqfob bf hjdagbcdcegggaaakqvof b hjdafbcdcfgggqaqkblxd bd henakbdcedfggpffhnhan bJ hkjafabcdffggbqqafoho bF hkdakbccdefggaawhahhf br hkjagabcdegggbqqaabgk b hkjagabcdegggbqqaabsg b hkkagabcdegggfhqqqbgk b hkkagabcdegggfhqqqbsg b hjdagbcdcegggaaakqgbf b hkkagabcdegggfaqqafon b hjdagbcdcegggaaakqgvb b hkkagabcdegggfaqqafwo b hkfafbcbdffgghafafnhg bK hjdafcbdcfgggqhhbglmq bi hndacbcddffggaahgkoab bL hkfafbcbdfgggahbhfdhl bd hkjagabcdegggbahqqgbf b hkjagabcdegggbahqqgvb b hapajddeefeggorrfhoqb bf hojacabcegfggnahothcf bL hkkagabcdegggfhqaabgk b hkkagabcdegggfhqaabsg b hjdafbcdcffggqahkfoho bF hkkadabcdfgggfhqakhaq bv hkkafabcdffggnhqafnhg bL hkjadabcdfgggbahqnmda bh hbhafbeddfgfghagbqqbg bI hkdafcbbdfgggqhfafahq bs hkjagabcdegggbahqafon b hkjagabcdegggbahqafwo b hkkagabcdegggfaqqanko b hkkagabcdegggfaqqawkn b hkjadabcdffggfqahobhk bO hjdadcbdcfgggqhaknmda be hkjagabcdegggbqqahgbf b hkjagabcdegggbqqahgvb bf hihakbdccefgglfoghhan bP henakbdddefggdkbgqqhf bd hkkagabcdegggfhqqhnko bf hkkagabcdegggfhqqhwkn b hihakbdccefgglfogaqqb bP hhdabcbfegggfhqhnmdao bh hkjagabcdegggbqqaakng b hkjagabcdegggbqqaasnk b hkjagabcdegggbahqanko bf hkjagabcdegggbahqawkn b hihakcbcdefggebkkaqqb bR hjdadcbdcfggghhafnmda bf hkkagabcdegggfhqqhfon b hkkagabcdegggfhqqhfwo b hkkagabcdegggfhqaakng b hkkagabcdegggfhqaasnk b hkkafabcdffggbqhabkqo bS hihakccdcefggdgosqaho bi hkjagabcdegggbqqahfob b hkkagabcdegggfhqahgbf b hkjagabcdegggbqqahvof bf hkkagabcdegggfhqahgvb bf hkdafbcbdffggaqkhfnhg bV hkjafabcdfgggnahqbeqp bf hkkagabcdegggfhqahfob b hkkagabcdegggfhqahvof bf hfdafbcdefgggqqqqpqnv b hkfagbcbdegggaabaaksg b hkfagbcbdegggaabaasgk b hldabbccegfggqqgfxlkf bd hkfajbcbdffggaabankxf bd hhdabcbfeegfgqqqngafk b hlkacabdfgfggfanxjnkn b hojacabcegfggbaanxpno bd hkfadbcbdffggaabaknab b hlkacabdfgfggfhoxcofo b hkjajabcdffggghhqbgxk bd hlkababdegfggfanannkb b hkfagbcbdegggaabahfvb b hkfagbcbdegggaabahvbf bh hfdadbcdeegggaaaanksg b hfdadbcdeegggaaaansgk b hclakbcddefggpnvohaak bd hjdafbcdcffggqqqgbgxn bd hlkababdegfggfhohoogf b hokacabcefgggkqhkaiok b hkfafbcbdffggaanafohg b hkjafbacdffggafahgbqn b hkjagbacdegggafahhnwo bh hkjagbacdegggafahhwon b hojacabcegfggghantabf b hkjadbacdffggafahofhk b hkkagabcdegggfaqqqfvb b hkkagabcdegggfaqqqvbf b hapakdceddfggngkobaan bd hjdadbcdcffggaaaknkaf b hkfagbcbdegggaabqhnwo b hkfagbcbdegggaabqhwon b hihakbdccefgghfogaahg bd hkkajabcdffggfhqqgbxf b hkkagabcdegggfhqqqksg b hkkagabcdegggfhqqqsgk b hkkafabcdffggfaqqbgqo b hjfajbcdcffggahqogbxf b hkjagabcdegggbahqqfvb b hkjagabcdegggbahqqvbf b hkjadabcdffggnahhknab bd hkjafabcdffggfqahgbqn b hjdagbcdcegggaaakqfvb b hjdagbcdcegggaaakqvbf b hkjadabcdffggfqahofhk b hkkafabcdffggfhqqgbqn b hkkagabcdegggfaqqanwo b hkkagabcdegggfaqqawon b hndaccbddffggqhhonkaf b hkjagabcdegggbqqaaksg b hkjagabcdegggbqqaasgk b hkjadabcdffggbqqaknab b hkjagabcdegggbahqanwo b hkjagabcdegggbahqawon b hkkagabcdegggfhqaaksg b hkkagabcdegggfhqaasgk bh hjdafbcdcffggaqhggbqn b hkkagabcdegggfhqqhnwo bh hkkagabcdegggfhqqhwon b hkjagabcdegggbqqahfvb b hkjagabcdegggbqqahvbf b hkkadabcdffggfhqaknab b hkkagabcdegggfhqahfvb b hkkagabcdegggfhqahvbf b hgkadabcefgggghhgltoj b hkfadbcbdffggaabaonan bc hehafcbdefgggqgvqhqie b hjnaibedfffgghhwahqhg bc hofaibcbeefggaabnkahg b hofaebcbefgggaabnqqgb b hilakaccdefggffraaaaf b hgfajbcbeefggaabbgqhk b hjdadcbdcgfgghhhkqfah b hioakaccdefggfknaqqqo b hjkakabddefggnhfvxqqg b hkfadbcbdffgghhghonan bc hioakaccdefggnknaqqqo b hofaibcbeefggaabgkahg bh hojaiabceefggnqqgkaab b hkfadbcbdffgghhghwoab b hgkafabcefgggfaafaakn b hgkadabcegfggnaaftdkc b hhdaecbfeegfghhhwkhgg b hgjajabceefggnqqbjxqo b hjdadbcdcffggaaakgkak b hlkaeabdfefggfanxewmk b hkjafabcdfgggbaaawahq bc hjhabbedfgegghhgtlgnc b hglaicdffefgghgudltqo b hkdadbcbdgfggqqfqqkha b hkjadbacdffggafahbfhf b hkjafabcdffggnqqqcfqb b hgjakabceefggnqqbnqqk b hbhakdceddfggajqfsqqg b hboajacedefggofemwehf b hgjajabceefgggqqgbqaf b hgkajabceefggfaqgbqaf b hokaiabceefggfaqofhab b hkjafbacdffggafahfbqb b hkkafabcdffggfaqqkgqg bc hgjadabcegfggghabuenc b hgkadabcegfggnhhftdkc b hgjajabceefggfhhgbqaf b hddakbcceefggaqowkxab b hokaeabcefgggnaakhhfo b hgkafabcefgggfaqghhfo b hbnafbedcfgggaabnhadu b hkjafabcdfgggghhqsaqh b hilakaccdefggffraaaak bc hodacbcbefgggaqkopugr b hgjafabcefgggghabaank b hkkafabcdffggfhqqfbqb b hkjadbacdffggafahvbhk bc hgdadbcbefgggqqfgminv b hjfafbcdcfggghahbwahq bc hkfadbcbdffgghhghknxk b hgkajabceefggfhqbgqhk b hkjadabcdffggfqahbfhf b hjnacbedfgeggaafaakkn b hjfadbcdcgfgghhhoaoqh bc hkjafbacdffggafahvfqn b hjdadbcdcffggqqqgngak b hokaiabceefggfhqnkahg b hkjafabcdfgggnqqawahq b hgfakbcbeefggaansnxaf b hjhaecddfegfgqgkqaabb b hflabbedfgeggahnmtgbr b hclafcdecfgggqvhkhhaq bc hjlaicdefffggqnaqtpho b hojaiabceefggnqhkoaaf b hkkadabcdffggfaqqgkak bg hjdadbcdcffggqqqggjaf b hkjafabcdfgggnahhwahq b hkkadabcdgfggghhqaghq bc hkkafabcdffggfaqqskqo b hgfakbcbeefgghafsnxaf b hkfadbcbdffgghhghknxf b hddajcbeeefgghhtpcqqo b hkjadabcdffggbqqaonan bc hgdakcbbeefggqhkbnqqk b hkdadcbbdgfgghhkaaghq b hflacbedfgeggqhnqqfgb b hkkadabcdfgggoqahvqah bd hkjadabcdffggbahqgkak b hkkadabcdgfggfaqqaghq b hkkafabcdffggnhhhgfhn b hioakaccdefggnknaaaaf b hkkadabcdffggfaqqsgaf bd hflaibeddfeggaanganab b hbhakdceeefggarahqaan b hddadcbcegfgghhfftdkc b hkkafabcdffggfhqqvfqn b hfhacdcfegffgafdtagrk b hkjadabcdffggfqahvbhk bc hkkadabcdffggfhqaonan b hkkadabcdffggfhqqbfhf bd hkjadabcdffggfhhqgkak bc hokaiabceefggfhqngaab b hdjakbaddefggafnkahhk b hkdadcbbdfgggqqbqoqah b hjgakaccdefggnwnaaaaf b hokacabcefgggfaqoimkv b hfhaibefdffggqqqcahhk bc hojacabcefgggnahopugr b hjfadbcdcgfggahaohnqa b hkjadabcdffggbahqsgaf b hjdafbcdcfgggqqhgwahq bc hkjadabcdgfggfqahqfah bg hkkadabcdffggfhqqvbhk bg hgkadabcefgggfaqgminv b hioakaccdefggfknaaaaf b hgkajabceefggfhqbkqqn b hkjadabcdffggbqqawoab b hkjadabcdgfggnqhhhbaq b hndaccbddgfggqhabqjha bd hkkadabcdffggnaqhonan b hkkadabcdfgggfhqawhaq bd hkfadbcbdffggaabaknxk b hkjadabcdffggfhhqsgaf b hohaacdgfeffgqbqeuojb b hkdafcbbdfggghhfasaqh bc hkkadabcdfgggfhqqvqah b hgjadabcefgggnahgminv b hkkadabcdffggfhqawoab b hjlaicedfeeggqqfaahhg bd hjdadbcdcgfggqqhgaoqh b hjfadbcdcgfggahaoaoqh bc hkkadabcdffggnaqhwoab bc hclakcdcdefgghgwvmaqg b hndaccbddfgggqhhonqha b hfjakbaddefggafbgqhhg b hkfadbcbdgfgghafqhbaq bd hkkafabcdfgggbqhasaqh bd hkfajbcbdffggaabanwxf bd hkfadbcbdffggaabaknxf b hehafcbdefgggqbkqhqie b hkjadbacdgfgghfqaaoqh bg hkkadabcdffggfaaagkxn bc helakbdcedfggiosqgqqf b hchafbbedfggghkqfqqha b hblafccedfgggigafqaip b hioakaccdefggfknaqqqg b hgkakabceefggfaafwhhf b helafcdbefggghrkhahit b hioakaccdefggnknaqqqg b hjfajbcdcffggaaabwkhg bh hndabbcdgggffqqqqtpkk b hkjajbacdffggafahgbqb b hkjajbacdffggafahgbqk b hkkafabcdffggghhhfnak b hkjajabcdffggghhhfwak b hgjakbaceefggafankxhf b hkkajabcdffggnaaabsaf b hgjakbaceefggafankxab b hkjajbacdffggafahfohf bc hkfadbcbdffggaabakohg b henafbcdefgfgannhahbf b hkjajbacdffggafahfohn b hkkajabcdffggfaqqknaf b hkkajabcdffggfaqqknan b hkkajabcdffggbqqqvoqb b hgkajabceefggfaanohqn b hipacedcfgefgfofhqngn b hofaibcbeefggaabsgaab b hlhaadefgeffghmmqpugn b hjdadbcdcffggqqqgnkxk b hkjafbacdffggafahgbxg b hkkajabcdffggfhqqfohn b hndaecbddffggqhhgjkqo bh hkjadbacdffggafahofxo bc hjdafbcdcffggqqqgbgqg be hkkajabcdffggfhqqfohf bc hjdadbcdcffggqqqgnkxb b hkjajabcdffggbahqknaf b hkkajabcdffggfaqqsnqf b hkjajabcdffggbahqknan b hkdadbcbdffggqqfqgkxn bc hkjafbacdffggafahgbxo b hioakaccdefggfknaaaak b hinakbdccefggmwbnaqqn b hgfajbcbeefggaabbgqqn b hilakaccdefggfrnxhhhg bj hkkafabcdffggnaaabkaf b hkjadbacdffggafahofxg b hjkakabddefggnhfoxqaf b hjdadbcdcffggaaaknkxn be hkkajabcdffggghhqbsaf b hkkajabcdffggfaqqbgqg b hjnaebeddfgfgaafnaakn b hjdajcbdcffgghqqkvoqb b hkkadabcdffggfaqqnkxn b hkkajabcdffggfaqqbgqf b hjdafbcdcffggqaqkjkqo b hioakaccdefggnkoaqqqo b hjdadbcdcffggaaaknkxb b hkjajabcdffggghhqbsan bi hkhacdcefgggfabhaagrf b hehafbcdefgfgpgwhhhgg b hkkadabcdffggfaqqnkxb b hkjajabcdffggbqqafohg b hkjajabcdffggbqqafohf b hkjajabcdffggbahqbgqg bc hjdadbcdcffggqqhokohf b hfhaibedfeegghhgqitqo b hjdafcbdcffgghhakbkaf b hkkafabcdffggfaqqbgxb b hkfakaccdefggnjnqqahg b hkjajabcdffggbahqbgqf b hkkajabcdffggfhqqvoqb be hkkafabcdffggghhqbkan b hjkakabddefggfasnxaab b hkkadabcdffggfhqqofxo bc hkjadabcdffggbahqnkxn b hkjadbacdffggafahobqk bi hkkajabcdffggfhqqgbqb b hgfajbcbeefggaabbkqhk b hjlaicddfeeggqobqqkhk b hojaiabceefggfhhbfhab b hkjajabcdffggbqqankak b hkkafabcdffggfaqqbgxn b hndaebcddffggaahgfnak b hkkajabcdffggfhqafohg b hkkajabcdffggfhqafohf bc hjfajbcdcffggahqgvoqb b hofaibcbeefggaabnkaab b hchafccedfgfgtfhjahfk bh hkkajabcdffggohhhfwab b hkkajabcdffggfhqqgbqk b hkjajabcdffggbqqankab b hkkadabcdffggfhqqofxg b hkjadabcdffggfqahofxo bc hkjadabcdffggbahqnkxb b hkfadbcbdffgghhghwohg b hdkakabddefggfhofhaaf bc hkkajabcdffggnaaasnqg bc hkkafabcdffggfhqqgbxg b hbhakcceddfggtjqfoqqo b hkjadabcdffggnaaakohf b hkjajabcdffggnqhhvoqk b hndaecbddffggqhhojkqo b hkjadabcdffggfhhqnkxn b hkkafabcdffgggqaabkaf be hkjadabcdffggfqahofxg b hhfabbcfeegfghhhbfqfn bc hkkafabcdffgggqaabkan b hkkajabcdffggfhqankak b hfkakabddefggfhgbqaab b hkkafabcdffggfhqqgbxo b hkjadabcdffggbqqaknxk b hjdakaccdefggkonhqqqn b hkkajabcdffggfaqqbsan b hkjadabcdffggbahqngqf b hjlaicddfeeggqobaqbhg b hkkajabcdffggfhqankab b henajbdcefegghffahnqk b hjdajbcdcffggqqqongxk b hhdaebcfeegfgaqqfwabk b hkjadabcdffggfhhqnkxb b hhdaecbfeegfghqabsabf b hkkafabcdffggfaqqbkan b hjfajbcdcffggahqovoqk bh hgjajabceefggbqqjkxqo b hkkadabcdffggnaqhknxk bc hkkadabcdffggghaakohg b hkjadabcdffggbqqaknxf b hmlaicddfeeggqgvahfhg bi hbhajccedfeggujaoafaf b hkkajabcdffggohhqbsaf b hkdajbcbdffggaqkqbsaf bh hkkajabcdffgggqahgvhf be hkkadabcdffggfhqaknxk b hffafbcdeffgghhhhhuon b hofaibcbeefggaabnkaho b hkkadabcdffggnaqhknxf b hkkafabcdffggbahqbkan b hgkakabceefggfaqgbxqk bf hfkakabddefggfaskqqqo b hkjadabcdffggfhhqngqf b hkjadabcdffggfhhqngqg b hehakbcdedfggpbwqfhab bi hkdajcbbdffgghqbhvoqb b hkdajbcbdffggqqghfwak b hgfajbcbeefggaabbgqhf b hkkadabcdffggfhqaknxf b hkjadabcdffgggqaangqg b hkkafabcdffggfhqqgfhn b hkkadabcdffggbqqakohf b hkkajabcdffgggqahvoqk b hfnaiacdfffggnkefksqo b hgkakabceefggfhqknxaf b hkjadabcdffggbqqakohg b hkkafabcdffggbqhabkaf be hjfadbcdcffgghaqngkqg b hjfajbcdcffggahqogvhf b hkgakaccdefggfwkhhhhk b hgjakbaceefggafawkxhg b hhfabbcfeegfghaqbfqgb b hjnaebeddfgfghqfnaabk b hkfadbcbdffgghhghonab b hgkakabceefggnhhwohhk b hfhaidcfeffggafleepqg b hdlaccfdeggfgetjthfbf b hfhacbedfgggfqqfhaojk b hdgakacdeefggkbqtjeqf bc hjhacbedfgggfhhnaqckn bc hjkakabddefggfhfoxqqg b hjkakabddefggfhfoxhhg b hodaicbbeefggqhkngahg b hngacacdefgggfwakbuuq b hgkajabceefggfaafnhhf b hgkakabceefggfaqvoxqk b hofaibcbeefggaabngahg b hfhacbefdgeggqqqcqobg b hkfadbcbdffgghhghwoan b hgjajabceefggbqqbgxqo b hjpaafdgdeffgqfqkgumf b hfjakbaddefggafbgqqqo b hblakbedeefggqqviehho b hgjakabceefggfhhfoxqb b hclafccedfgfgmfhfqqkb bh hjhaedecfdggghhnhohqa b hjgakaccdefggffnxhqqo b hkjajbacdffgghkhaksxb bd hofacbcbffgfgaabqhxab bc hgkakabceefggnaafwhqk b hflaibefdeeggaaabduab b hglabcdcefggghgkqosvb b hkjajbacdffggafahfvhf b hkfakaccdefggbbnqqqqb b hgkajabceefggnhhfnxab b hjdafbcdcffggqqqgjgxn bd hgkakabceefggnhqknxak bc hkjajbacdffggafahvbxf bd hfkakabddefggkafnxhhk b hdjakbaddefggafnkaaaf b hgkakabceefggfhqbgxqf b hdfakbcedefggaautbehk b hbhajddedfeggtbqragaf b hgkakabceefggfhqsnxqf b hddakcbceefgghhkfwxhf b henafbdcefgfghffhaqnb b hgfajbcbeefggaabbgxaf b hkjajbacdffggafahvbqb bc hgkakabceefggfaqgvxhk b hchajccdeefggencqikhk b hgkafabcefgggfaqvhhfo b hfnaiacdeffggnkakkkqg b hfhacdcfegggfafleasff b hioakaccdefggfkoaqqqo b hgjajabceefggfhhgbqqo b hokaiabceefggfaqofhhg b hmhaecddfegfgangaxabf bn hgjakabceefggnqhwkaqf bc hgkajabceefggfaqgbqqo b hjdadbcdcffggaaakgkaf b hgjajabceefgggqqvfqqo b hehafbdcefgfgukcqqqgo bc hjkakabddefggfhfohaaf bc hmlaicddfeeggqvbqqbhk b hgkajabceefggfaqvfqqo b hehafbdcefgfgukkqqqgk b hehafdccefgfgakfxaakb b hgjajabceefgggqqgbqqo b hkkajabcdffggfaqqsgxk b hdkakabddefggfankxqqn b hokaiabceefggfaakoaak b hokaiabceefggfaqvbhhg b hkjadbacdffggafahbfhk b hmnaebbdfeggghfftdhmd bc hndaibcdeefggqqqojsak b hkkafabcdffggfaaakgxn b hioakaccdefggnkoaqqqg bc hgjajbaceefgghkhfoxab bl hgkajabceefggnaafnhqn b hdfakbcceefggaansnxqf b hfoabacdfgfgggfhfmjit b hjkakabddefggfhfohhhk b helafbbdefgggafsaaahq bc hnkaeabdefgggkqgmihlu b hdkakabddefggghkoaqqn b hdfafacedfgggbbeuqaoj b hklaecddfegfghvfhqqoo b hjjakabddefgggqsgxaho b hilakaccdefggfrnxhhho bd hkjafbacdffggafahvfhn b hjlaccdefgggfqvqaqbgf b hojaiabceefggnqhkoaqo b hkkafabcdffggkqhhfbxg bc hkjadbacdffggafahvbqk bc hhfabbcfeegfgahqgkxnn b hkjafbacdffggafahfbqn b hokaeabcefggggqawhhfo b hgjakabceefggnahgvqaf b hlkababdefgggnhohgwfv b hdjakbaddefggafnkahhf b hjhaidecfeeggaqfhldhf b hjdadbcdcffggqqqggjqo bf hkjajabcdffggbahqsgqg b hkjajabcdffgggqaaksan bc hioakaccdefggnkoaqqaf b hgkakabceefggfaqgbxqb b hgkakabceefggghasnxak b hjdakaccdefggkonhqqqb bk hokaiabceefggfhqnkaab b hgkakabceefggfhqbsxaf b hgjajabceefggnqhfnhqn bf hgkajabceefggfaqgbqak b hokaiabceefggfaqofhan b hgkajabceefggfaafnaaf b hkkajabcdffggfaqhwoxn b hgjajabceefgggqqgbqak b hgjajabceefggghhgfqak be hkkafabcdffggfaqqkgqo b hgjajabceefggfhhgbqak b hfjakbaddefggafbgqhho b hioakaccdefggfkohqqqk b hgkajabceefggfhqbgqqn b hgkakabceefggfhqknxak b hkkajabcdffggfhqqvbxf b hkkajabcdffggfaqqksxb b hokaiabceefggghangxqo bf hflacbefdgeggahqkqggb b hdkakabddefggfankxaab b hgjajabceefgggqqgfqaf b hgkajabceefggfaafnaqf b hgkajabceefggfhqskqqn b hblakcceddfggdkqnbhho bc hkjajabcdffggbahqksan bk hkfadbcbdffgghhghwohf b hjjakabddefggnafwxaaf b hfdafbcdefgggaaaaaqkc bk hfdafbcdefgggaaaaaqnv bo hkjadabcdffggnahhonxk b hgfakbcbeefggaanbsxak b hkjajabcdffggbqqanwak b hkkadabcdffggfaqqsgqf b hnjaeabdfegggnafelaud b hgjafabcefgggfhhvhhfo b hblafcecdfgfgiqvnqqgf be hgkajabceefgggqafnhqn b hfjakbaddefggafbgqhab b hdjakbaddefggafnkahqn b hkkafabcdffggfaqqskaf b hokaiabceefggfhqsgaab bh hkkafabcdffggfhhakgxb bc hkkajabcdffggfaqhnwxf b hojaeabcfegggnqhhnhfo b hkkajabcdffggfhqqfvhf b hdhaidcfdffggtopbdnho b hjdadbcdcffggqqqgngaf b hkjajabcdffggbqqanwxf bd hkjajabcdffggbqqawohf b hkgakaccdefggfwkhhhhf b hkjadbacdffggafahvbhf b hkkafabcdffggfhqqfbqn b hmlaecddfegfghvoahanb b hgdakbcbeefggaaffwaqg b hndaibcdeefggqqqojoqk b hkjadabcdffggfqahbfhk b hkjafbacdffggafahvfqb b hgkakabceefggohhvoxhf b hehafdccefgfgakfhahkf b hgdajcbbeefgghqbfnhqn b hkkajabcdffggfhqanwak bc hblajacdefeggknhhhohg bc hkjadabcdffggbahqsgqf b hnkaeabdfeggggqbeuqld bc hkkajabcdffggfhqqfvxg b hflacbefdgeggqqqkqbgb b hkjadabcdffggfqahvbqk bc hgkajabceefggfhqbgqhf b hkkadabcdffggfhqqvbqk bk hokaiabceefggfhqnkaho b hkjajabcdffggbqqawoxn bj hjkakabddefggfasnxqqk b hokaeabcefgggfhqsqqgb b hddajcbceefggqhbfnxab b hkkafabcdffggfhqqvfhn bf hodaecbbfeggghqbaoank b hdhabcdcefgggqkoqcksj bg hbhafddedfgfgtbqrahnk b hkkadabcdffggfaqqgkaf bd hnjacabdefggggqbqnvsg b hjdadbcdcffggqqqggjak b hkkajabcdffggfhqawohf b hkkajabcdffggfhqanwxf b hgjakabceefggnahvoxhf b hgjakbaceefggafawkxhf b hkjadabcdffggfhhqsgqf b hcnakbbddefgghgkohhhg b hkjadabcdffggbqqawohg b hgkajabceefggfaqgfqqg b hkkafabcdffggfaqqskqg b hkjadabcdffggbqqaonab b hgkakabceefggfaqgbqaf b hkjadabcdffggbahqgkaf b hgjajabceefggbqqbgxqg be hkkajabcdffggfhqawoxn b hldaebccefgggqakoqqbg b hgkajabceefggfhhfnhhf b henafbcdefgfglckhqhfg b hkkadabcdffggfaqqsgak bj hkkadabcdffggnaqhwohg bc hkkadabcdffggfhqawohg b hgkakabceefggfaqgbqqf b hkkadabcdffggfhqqbfhk bj hehajbdcefeggukcqabho b hkjadabcdffggfhhqgkaf b hfhacdcfegeggafltafgr b hkkadabcdffggfhqaonab b hhfaiacdfefggggqgggqb be hkjadabcdffggfqahvbhf b hkkafabcdffggfhqqvfqb b hndaibcdeefggqqqojsqg b hgfadbcbefgfgaabbaanf bg hkjadabcdffggbahqsgak b hkjajbacdffggafahfvhn b hjlaecddfegfghobahhno b hkkadabcdffggfhqqvbhf bd hioakaccdefggfkoaaaak b hfnaibeddfeggaakoafqg b hkkadabcdffggnaqhonab b hgkakabceefggfhqbgxqg b hkjadabcdffggbqqawoan b hdjakbaddefggafnkahqb b hgfakbcbeefgghhfgvqak b hehajbcdefeggpbbaqfqb b hkjadabcdffggfhhqsgak b hgkakabceefggfhqknahg b hdkakabddefgggqngaaaf b hioakaccdefggfkoaqhhg b hjkakabddefggghfwhqqf bn hipacbcdffgggngkluqlf b hkpaadcegffggnboippir b hmlaecddfegfghgvhhhog b hgkakabceefggghhvoqqf b hkkadabcdffggfhqawoan b henafbdcefgfgmgwhqhkf b hblafcedcfgggqhbbhhqa bi hgjajabceefggbqqbgqhk b hkkadabcdffggnaqhwoan b hfkakabddefggfhgbqqqn b hdjakbaddefggafngahhk b hjdafcbdcffggqqaknoxk b hgkakabceefggfaqvbqaf b hdkakabddefggfhofhhhk b henajbcdefegglnnhhfqb b hgdakcbbeefgghhkfwaqf b hgjajabceefggbqqbgqqn b hgnaiadedefgggelhochk bc hkkajabcdffggfaqqsgqf b helajbdcefeggissaqkhk b hdkakabddefggghwoaaan b hjhaededfdgfgihfashfg b hinakbbddefgghfwkxaak b hokaiabceefggfaqofhho bc hgjajabceefggfhhgbqqg b hhdabbcfeegfgaahonxgf b hgkajabceefggfaqgbqqg b hcnakbbddefggabkoxhhk b henajbdcefeggpffahnqk b hjkakabddefggfhvoxqqf bh hgpaacdffeeggvrexbfbg b hldaibcceefggaafkohhk b hgjajabceefgggqqgbqqg be hlfacbcdeffggaatbvgek be hioakaccdefggfkoaqqqg b hokaiabceefggfaqofxqn b hgjajabceefggfhhgbxhk b henajbdcefeggpsfaanab bl hgkakabceefggfhqbgqhk b hblajbeddfeggahbsagab b hndaibcdeefggqqqojoqb b hgjakabceefggnqhnwaqf b hgkajabceefggfaqgbxhk b hjhaededdfgfgiqffqqbg b hgkakabceefggfhqbgqqk b hkjajabcdffggbahqsgqf b hkkajabcdffggfhqqvbqk b hjkakabddefggfasnqqqf b hehafdccefgfgakfhaqkb b hgjajabceefgggqqgbxhk b hioakaccdefggfkoaqqaf bl hchakcddcefggajgkxqqb bc hgjajabceefggfhhgbxqn b hgfajbcbeefggaabbgxak b hokaiabceefggfaqofxhk bj hjdadcbdcffggqhhbbfxg b hgkakabceefggfaqgvqak b hgkakabceefggfaqvoqaf b hkjadbacdffggafahvbqb bl hjkakabddefggfasnxaan b hkjafbacdffggafahvfhf b hgkajabceefggfaqgbxqn b hgdajbcbeefggqaffnhqb be helajbdcefeggioohhfab b hdkakabddefggfhofxqqo bc hioakaccdefggfkohqqqb b hgkakabceefggfaqvbxqk b hgoaeacedffggfkxfskeg bc hepaedecdffggnbkkpurf bc hokaiabceefggfhqnkaan b hhdaebcfeegggaaafwhep b hehafdccefgfghokhhqfb bl hilakbbddefggakbsahhk b hfdadbcdefgfgaaaahhkk bg hgkajabceefggfhqbgqqb b hjdadbcdcffggqqqggjqg b hgjajabceefgggqqgbxqn b hkjajabcdffggbahqksaf b hjjakabddefggnafwxaqo b hgdakbcbeefggaqkgvxhf b hjkakabddefggghfwaqqk b hgkajabceefggfaqgfqak b hkjajabcdffggbqqanwab b hehafbdcefgfglffaaanf b hgkajabceefggfhqkgxaf b hddakcbceefgghqkbsaab b hgkakabceefggfhqsnqqk b hfkakabddefggfhgfqaab b hdkakabddefggfhofhaak b hehajdccefeggaokxqnhk b hkkafabcdffggohhqkgxn bl hfkakabddefggfhgbqaan b hfkakabddefggfhgbxqqo b hkkajabcdffggfhqqfvhn b hgkakabceefgggqqgoqak bc hldaicbceefgghhfkohhk b hkjajabcdffggbqqawohg b hjnaibeddfegghqnohkqb b hgkakabceefgggqanwaqf b hkkafabcdffggfaqqskan b hojaiabceefggbqqgkqhk b hokaiabceefggfhqnkxqo b hkkadabcdffggfaqqsgqg b hdgafacdefgfgfnhaqqbf b hndacbcddffggqqhfbfxg b hdkakabddefggfhofxhhg b hddakbcceefggaqowkhqk b hbhafdeddfgfgiqfoaank b hkkajabcdffggfhqanwab b hgkakabceefggfhqsnqhk b hofaibcbeefgghhfobxqb b hgkajabceefggfhqbgxaf b hddakcbceefggqhbfwhqb b hokaiabceefggfhqnkxaf bd hokaiabceefggfaqobqaf bd hgkajabceefggghabkaab b hfkakabddefggfhgbqahg b hdkakabddefggfhofhaqo bc hojaiabceefggghagkaab bn hgkakabceefggfaqfvxhk b hfjakabddefggghfnaqqk b hkkajabcdffggfhqawohg bl hkjadabcdffggfqahvbqb b henajbcdefegglnkhafho b hkjadabcdffggbahqsgqg b hkkafabcdffggfhqqvfhf b hgkajabceefggfhqbgxqo b hgkakabceefggnaawkhhk b hkkadabcdffggfhqqvbqb b hgdajbcbeefggaqkgfxhf b hhgabacdfggfgnflkhdce b hdkakabddefggfhobhaaf b hdfajbcceefggaabbkaan b hfkakabddefggghfnaaab b hgfajbcbeefggaabbkahf be hgkajabceefggfaqgfhab b hokaiabceefggghangqqk b hbhafccedfgfgujafhakn bl hlkababefeggggqqlakwf b hkhaecddfegfganjaaanb b hkjadabcdffggbqqawohf b hdjakabddefggnakoxhhk b hkjadabcdffggfhhqsgqg b hndacbcdefgggqqhjgeex bk hndaccbdefggghhacfpxp bs helakbbddefggqfbkqqaf b hddajbcceefggqakgchhg b hjjakabddefggnqgoxqqg b hofaibcbeefgghhfobqaf b hokacabcegffgkqqnaxbf bc hkkadabcdffggfhqawohf b hnkaeabdfegfgfhvhqqfo b hkkadabcdffggnaqhwohf b hldaicbceefggqhbkohhk b hojaiabceefggnaangqqk b hokaiabceefggfhqngqhk bj hjkakabddefggfhvoxhho b hjjakabddefggnafwxaak b hddajbcceefggqakgchab b hgkajabceefggnhhwnhqb b hjkakabddefggfasnahqk b hgdajcbbeefggqhkjgxqg bc hokaiabceefggkqhwohhk b hkoaeacdeffggfkafswhg b hokaiabceefggghasgqqk b hgkakabceefggfaqgbqak b hdkakabddefggfhofhhqn b hojaiabceefggbqqgjqqn b hlfaibcceefgghhobcqqo b hgkakabceefggfhqsgxqf b hblajccedfeggmjqohoqb b hojaiabceefgggqakohhk b hgjajabceefggbqqnjxaf b hehajbdcefeggtncqhbqb b hjkakabddefggfhvoqaab bo hdkakabddefggnhobhaqo bf hdkakabddefgggqgkqqqo b hjnaibeddfegghhwnakak b hdkakabddefggfhofhaqg b hmnaibbdeffgghffligxk b hfkakabddefggfhgbqaho b hblajcecdfeggeqbbqbhk b hfjakabddefggbqcfhaak b hblakcddcefggqobbhhhf b hfkakabddefggkqgfxhab bp hchakddcdefggabrwhqqo bc hojacabcegfggbaanxxkn bs hbhafdccefgfghkrxqann b hdlabccffefggqomqenvk b hnjacabdfggfgghfdfsfr bc hgkajabceefggnaanohhk b hdkakabddefgggqgkaaqo b hlkacabdfgfggnhoqgsbo bc hfkakabddefggfhgbqqqb b hokaiabceefggfhqsgqqk b hjlaecddfegfghvbaqqnf b hbhakdcdedfgghkcakqqk bce hapakedceefggfofofqqo bcg hgnaeacdfegggfohoohxh bce hldaecbdeffggqqhbwwhg bck hdkakabddefggfhofhhhf be hknaibbeeefggabhqaxab be hnkaeabdefgfggqbxaanf bc hojacbacfffggafaaqhxn b hgjakabceefggnahvbxqk b hojababcfgfggbqquxllc bg hclakcddcefggqvfbqqqb b hblajacdefeggknhhhghg b hofacbcbffgfgaabqhxak b hdhaicefffdggaqqhxnqb b hfjakabddefgggqskqhhg b hchakdccedfgghoraoaan bn henajbdcefeggpsohafab b hlfacbccffgggaandmxmv bg hgjakabceefggnahfvhhg b hchakdccedfgghoraoqqn b henakbbddefgghffnhhho b hdkakabddefggfhobqqqk bc hehakdccedfgghkfxohhf b hdjakbaddefggafngahhf b hjjakabddefggnawkaqhk b hlgaiacdeffggkbqnvsan b hbpacdcefgffgfosqhaig bd hdjakabddefggnakoaahg bc hofabbcbfgffgaabqqhag bc helajbcdefegglbwaakqo b hjkakabddefggkafwaaan b hgkakabceefggfhqsgxqg b hihakbbddefggqbcohaaf b hdjakbaddefgghfbfxhab b hokaiabceefggfaqvbhho b hgkakabceefggfhqbgqhf b hjpaadefeefgggflnrqgf bd hdkakabddefggbqobxqaf b hklaecddfegfgqgfqhhff b hchakdccedfgghonaoqhk b hgkakabceefggfhqbgqqb b hgjajabceefggfhhvfqqg b hcpaedfcdegfgnhkkvqgk b hbhajbeddfeggqacoqfaf b hjkakabddefggghfwaaan b hokaiabceefggfaqofxqb b hjjakabddefggnawkxhhf bc hgkajabceefggghaskqhk b hgjajabceefggfhhgbxhf b henajbdcefeggmwbaakqo be hchakcdcdefggannkaaaf bs hojacabcegfggghhoqhjf bc hbnajbcdeefgghvfeevho bk hhfabaceegfggnbqgqbha bw hgkajabceefggfaqgbxhf b hokaiabceefggfaqofxhf bg hdkakabddefggfhofxqqg b helakbbddefggakskqqaf b hojaiabceefggbqqgjahg b hgkajabceefggfaqgbxqb b hnnaabedgfefghhohakbo bc hbnakadeddfggnaxhqqhk bc helajbcdefegglbgqqgak bo hnjaeabdefgfgfqbqahfk bk hknaibbdefeggaboahnqk bo hgjajabceefgggqqgbxhf b hgjajabceefgggqqgbxqb be hgjakabceefggnahvbqqf b hmnacbbdegfgghgfhofwb bw hkpaacdgfeffgbgqxgmuf bg hnkababdfgfgggqbaswjb bc hdkakabddefggkakoaqhk b hcpaiededdfggvvvofqak bc hofabbcbgggffaabaqhak b hblakacdedfggfnhagqqn b hdkakabddefggnangxqhk bd hblakacdedfggknhhgqqo bc hgjajabceefggfhhfbqqg b hdkakabddefgggqgkaaqg b hojaiabceefggnahvbhho b hcnakaceddfgggvqqbqqb b hgnaiadedefggfelhochf b hnfaibcdefegghhhfffqk b hbhajbeddfegghacoqnqg b hgjakabceefggnahgvhhf b hgkakabceefggfaqgvhhf b hddakcbceefggqhbnwxan bh hclafccedfgggmfaoaahq bd hchajccedfeggufhohohf br hgfakbcbeefggahbvoqak b hgkakabceefggfhqsnqhf b hdkakabddefgggqgkahhf b hgkajabceefggnaafnaak b henafbdcefgfgpsoqaqkg b hchakdccedfggaonhbqaf b hfnaibeddfeggaqwoagqo b henajbdcefeggpsohqkhk bd hfdadbcdegfggaaaaqqbg bg hokaiabceefggfhqnkxqg b hgjajabceefgggqqvfhab b hgkajabceefgggqawnhqn b hokaiabceefggfhqnkxak bd hgkajabceefggfhqbgxak b hodaibcbeefggqqgvbqaf b hfnabbedfgefghhwaxkbn b hgkajabceefggfhqbgxqg b hdpaafedfggeguvkmxhgf b hblakacdedfggfnhhgqqo bi hodaicbbeefggqhkgkqhf bm hdfakbcceefgghabgohhf b hblafcecdfgfgdqvnqagk b hfdadbcdefgfgaaaaqqkn bo hfdadbcdegfggaaaaaavc c hgfagbcbeegggaabbskjg c hokacabcefgfgfaakxafb bc hojabbacfgffghkqqxhab b hjjakabddefggnawkaqhf bc hknaibbdefegghgkhhfhk b hljacabdegfggfhkankwg bcm hojacabcegfggnaanxqkc bcc hbnajbeddfeggaawkhkhf bc hokacabcffgfgfhqahxqk b hgkakabceefggnaawkhqb b hlfaibcceefgghabbfqak b hgkajabceefggfaqgfhhf b hfjakabddefgggqbkqhho bc hgjadabcegffgfhhgqxok bc hldaicbceefggqhbonxho b hepaibeefedggnjoqjnqo bj hgdakbcbeefggaqkfvhan b hehafbdcefgfglosqhhfk b hfkakabddefgggqbjaaak bc hclafccedfgfgdnavqqbo bc hgkakabceefgggqawkhhf b hgkakabceefgggqqgohan bc hnkababdfgfgggqbqfgsg bg hapakcecdefggbnrnnaak bA hcpaidfdceeggrhrfbgqn bc hgkakabceefgggqqgohhf bn hmlaecddfegfghvoaqank b hjhaecddfegfgqgkhqqfb b hokaiabceefggfhqngqhf bd hklaecddfegfghvfhqaok b hokababcegffgfaaohabo b hgkajabceefggfhqskahg b hokaiabceefggfhqsgqhk bd hlkacabdeggfgbaklkgnr b hclakcdcdefggqvcnqqqb bk hgkadabcefgggnaafhhfo bs hodabcbbegfggqhkkaank bck hojacabcefgggnqhkahcn bce hokacabcegffgfaqohxgn bc hchafdccefgfghorhqhnf b hodaibcbeefggqafwohhf br hihakbbddefggqbcohaqg b hgkajabceefggfhqbkaan b hapakedceefggfosjohab bg hgkadabcefgggkqhfhhfo bw hldaicbceefgghhfwohhf b hdkakabddefgggqgkqhho b hokacabcfffggfhhhqaxf bc hihakbbddefggqbgoqaho b hnhaabedgfegghhfqhoos bcc hddadcbcefggghhffhhfo bcm hmlaebbdefgfgafbqqqfn bs hclakcddcefggqgfbxhan bs hblajacdefeggfnxhaoaf b holaacdgfeefgqgaqxokf bg hljacabdefgggghkavvjs bd hofacbcbegffghafsxafk b hgdajbcbeefggaqkvfqak b hokacabcegffgfhqnaxbf bc hcpaiedeedfggrgvjwqhk bd hlkacabdfgffgnhotgcfn b hodaibcbeefggaqkvbhan bh hapakdceddfggkknnkhqb bw hgjadabcegfggnahghqrb bk hhjaibadfeegghkfqqbqo b hokacabcffgfgfhqqhxab b hokacabcegffgohhohxgn bc hgkadabcefgggfhqbqarg bg hfnabbedfgeggaqkaagkn bA hclakcddcefggqgfbhaqo b hokaiabceefggkqhwohqb bs hbpaicfeddeggkqvnbfqn b hfhaidcdeffgguwrmukxb b hchajccedfeggufafqnqg bc henafbdcefgfgmgbqhqfb b hojababcgggffbqqaqhak b hokababcgggfffaqhaqhf bc hfkakabddefggfhgfhhqb b hgkajabceefggfhqskaan b hokacabcefgfggqakxafb bg hokababcffgfgfaqqaqhb b hlgacacdegfggffhbubti b hblafacdefgfgknhhhqkn be hojababcgggfffhhhaqhf bc hnnaabedgfefgaanhakng b hgkadabcefgfgnaawhxgf bc hokababcegffgfaqbqhkb bc hapajdecdefggnvvnvqab bd hddakbcdedfggqqaabaab bc hljacabdeffggnakebfrn bc hmnacbdcfgfggpooabojj bd hnkaiabdefeggfakxxbqg bs hooaaacgfefggfkkffwrb bd hlkababdefgggfhohsssj bg hldaccbcefgfgqhbwaxbn b hokababcegffgfaqfqhfn b hlhaaddefefgghfiidfrb bd hokaiabceefgggqawohqb b hdfajbcceefggahoskahf bd hokababcgggfffhqaqhak b hdlaibecfeeggplfhhphg bd hblajacdefeggknaxafab bc hokababcfgffgfhqqqhag b hojacabcegffgbqqnqakf bc hdpaadgffgeeggdepxgkc bc hlkacabdfgeggfanmbkwn b hmnaibbdefegghgnhaoak bo hghaibbdfeegghkbqhfak bq hcoakacdedfggfkhhfhho b hgnaebbdfegfghgohxaob b hjpaaefegedfgjaoqjnfn bh hnkaeabdefgfgoqbxxqko bu hofabbcbegffgaabkqakg b hofabbcbfgffgaabqqhao b hgfadbcbefgfgaabbaann bd hokababcegffggqanhang b hcnakaceddfggngqqghhg b hihakbcddefgguvvvhqqk c hhfacacefgfggbbqfebde bg hgjafabceegggghhgbovb c hdnacbeffefgglutaiaob b hlgacaceefgggggqbnupt bd hjpaaefegedfgjaohjnfk b hipaeedcfdgfgofohfhkk b hbpaiefceedggjqoojnqn b hboakadeddfggfhhaqqqo bc hllaacdgfeefghbaqhkbn b hofacbcbegffgaabnqqff bd hkpaadcegeggfnnrikxkb b hcoafacdefgfgfkhhqhkk b hfdadbcdefgfgqqqqaabn bd hcoakacdedfggfkhhfqqf b hgjadbacefgfgafawhxgn bc hdhaecdcfegfgakfaaafb bw hojacbacfffggafaaqhxf bc hapakedccdfggsffkfaab bc hofacbcbegffgaabnqqgg bd hboajacedfeggnohxaoaf b hlkababdefgggnhohssrw bd hljacabdefgggbakavvrs bd hcoakacdedfggfkhafaab bc hcoakacdedfggfkhhfhab bc hodaecbbeeggghhkkowfn c hjhaccedfgggfqlkqiskn c hfhabbdeeffggpbetqwkk bc hblajacdefeggknhhhgho bc hojababcfgffgbqqaxhqb bc hljacabdefgggghkacccv b hepaeedffegfgfoetfqxn b hlkaiabdfeeggfhoxxghk bw hhfacacefgfggnbqfebde bd hapafdcecfgfgnckoaqbf bc hlgacaceefgggogqbnupt bg hofabbcbegffgaabgqakg b hofabbcbgggffaabaqhaf b hokacabcegffgkqqnaxbn b hdlacbeefgffgupqqhhcg b hboakaeedefggfahaqqqn b hepaedbfdegfgrfabgqff b hgkadabcefgfgnaanhxof b hblakacdedfggknhxgaaf bc hfdadbcdefgfgaaaahqkn bc hboajacedfeggfnhaqgqn bc hblajacdefeggfraaabab b hlkababdefgggnhohoowr b hblajacdefeggfnxxafaf b hdnaeaeeffgfgfiqifakb b hkhabdcdefgfguggxbbfg b hnkaeabdfegfgfhgqqqko by hgfadbcbefgfgaabbxanf bc hjpaacedgfffggrbqahdn b hofabbcbegffgaabgqafo b hgkadabcegffgfaqvxqnf b hokacabcfgffgfaqhxaqg b hblajacdefeggknhxhnhg b hghaicdfdffggarpcabak bd hnjacabdefgggnafhssvr bg hmpaacegefefgbnqneobg bc hcoakacdedfggfkhhfhan b hknaibbdefegghgkxafaf b hkpaadfegeffgoaoqkuun bg hblakacdedfggknhagqqb b hklaebbdfegggqfnlalxp b hdhacdcefgefgaohaqono bf hcoakacdedfggfkhhghhg b hblakacdedfggfnhagaab b hblakacdedfggknaxbaaf bc hokacabcegffgfaqvxhff b hlkaiabeefeggfaahxqqf be hblajacdefeggknaxanab b hlkaiabdfeeggnhoxqbhk be hbnadbeddegggaafwknor c hjnaibedfeeggdibaxdan c hddajbcdefeggaahhqbqn b hblakacdedfggknhhgqqg b hkpaaefegdefgfhohnfgf bA hblakacdedfggknhhgqaf bc hljacabdefgggnakavvjs bg hclajbdedefgglricprak bd hnkaiabdfeeggfhghhfhg b hknaibbdefegghgkhhghk b hnfaibcdefegghhhoofab b hgdafcbbefgggqqnbldsk c hgjagabceegggghhvocfb c hokacabcegffgfaqvxhkg bc hokacabcfgffgfaqqxahf bc hofabbcbgggffaabaqhxn b hbpacbecffgfgfffimpmk b hboakadeddfggfhhaqhhg b hojababcegffgbqqkqqoo bd hipaiedcfdeggsfohfbab b hgkadabcefgfgfhqsqxok b hokacabcffgfgfhqahxqb b hbpaccfedgffgkdjkaalb b hblakacdedfggkrxafaab bm hfdafbcdefgggaaaaqqgb bm hfdafbcdefgggaaaaqqrw bq hbpaiefceedggjqgojnqn b hapajdcecfeggnckghkhk b hokacabcegffgfaqoqqkk b hlkaiabefeeggfhqxahhk b hfpaaefgdeefgnhaknogb bc hblakacdedfggknahbqqo bc hojaeabceegggghhobgvf c hfdakbcddefggpplxnaaf c hlkaiabdfeeggfhoqqbqf b hokacabcegffgfaqvxqkf b hfdakbbddefggemxqbahg c hfnabbedgfegghqkqqkcj c hgjadabcegffgfhhvxqbg bc hgjagabceegggghabskjg c hfdakcbddefggllllgqaf c hojababcefgggbqqkhhrv c hddadcbcegfgghhffqqjc c hnjacabdefgggnafhjjjs b hblakacdedfggfraabaab b hepaideeddfggbbbsjqak b hojababcegffgfhhfqhfb b hojababcgggffbqqaqhaf b hnkaeabdfegfgnhgqxqkn b hcoafacdefgfgfwahahff b hlkababdefgggfhohjjsj bc hgjadabcegffgfhhvxqnf b hojababcfgffgbqqqxhan b hblakacdedfggfnhagqqb b hgkadabcegffgfaqghhnn b hdlaicddeefggqnwlxnak bc hfdadbcdefgfgqqqqhhgo b hhjaibaefeeggafqqhahk b hokababcegffgfaqbqhfb b hokababcgggfffaqhaqhk b hofabbcbegffgaabgqqfg b hhfabbcfgfefgaaaqnbnf b hokacabcegffgfhqsxakk b hipaecddfegggbngagacv bf hhdabbcfgefggqqqdfbhp bd hblakacdedfggfnaabaab b hokababcegffgfaqfqhfb b hokababcffgfgfaqqaqhn b hhjaebadfegfghkfqhhng bc hblakacdedfggknhagqhf bc hboajacedfeggfnhaqoqn bl hgfadbcbefgfgaabsqqog b hblakacdedfggfnhagqhk b hblakacdedfggknhagaan b hcpaedfdcffggbtnfxeqf b hgfagbcbeeggghafbskjg c hjhaccedfgggfqlkhibkf c hokacabcegffgfhqsxafb b hokacabcffgfgfhqqhxak b hblakacdedfggfnhhgqqg b hgoaiadfeffggnaaankqf b hknaibbdefeggabwaxbab be hcoakacdedfggfkhafaan b hgdafcbbefgggqhkbldsk c hgdagbcbeegggqafwknor c hojababcegffgfhhbqhfb b hojababcgggfffhhhaqhk b hokababcegffgfaqbqhkn bc hnkaeabdefgggkafhpihe bc hgjadabcefgfgbqqbaaff bj hgkadabcefgfgfhqsaxfb b hgkadabcefgfgnaawaxbf bc hgjadabcegffgfhhghhff bd hokacabcegffgfaqoqqbb b hddadbccefgggqakgaars c hodacbcbefgggaqkoaarj c hnfaibcdefegghhhfffhk b hokababcegffgfaqfqhkn b hojaeabceegggbqqgkbnj c hldaebccfegggqqgefdvf c hpkaaabfegfggfaqhhbww b hboajacedfeggnnhaqgqn b hlkaeabdfegggfhoehemx b hblakacdedfggknhhoqqo b hgjadabcefgfgnqqnaxfb b hgkadabcegffgfaqghhff b hhjaebadfegfgafkqahog b hokacabcegffgfhqnqqff b hojababcegffgfhhbqhkn bc hojacabcegffgbaanaxnf b hokababcegffgfhqgqakg bc hokababcgggfffhqaqhaf bc hddakbcdedfggqqaabaan b hlkaiabdefeggkakhxfhf b hfdadbcdefgfgqqqqahbo b hnhaabedeffggqqfhhofn bm hbpaecfddeggggqobbhcn be hblakacdedfggfnhxgaaf bi hljaeabdefgfgbakahqfo b hgfafbcbeegggahbgfovb c hgjafabcefgggghabetnj c hddafbcdefgfgaahhqqof bo hnfaibcdefegghhhfffqb b hblakacdedfggfnhhgqaf bi hokacabcefgfgfaakxafk b hnkaeabdefgfgnabaahfg b hjnabbedfgefgaafxhfff bc hgjafabceegggbqqbjsng c hjhaidecfffgglqbllxqg c hgjadabcefgfgbqqbaann bd hlkaeabdfegfgfhoqqakf bh hokababcegffgfhqkqakg bc hokababcfgffgfhqqqhao bc hddajacedfeggkohhqfqo b hnnaabedgfefghhohhfgo b hojababcegffgbqqkaxkf b hofabbcbegffgaabgxafn b hokacabcegffgfhqgqakg bc hgjafabceegggnqhfnwko c hokaeabcefgggghanmtjn c hgjadbacefgfgafanhxgf b hboakadeddfggfhhaqqqg b hokababcgggfffaqhaqxo bc hokababcegffgfhqgqafo b hcoajacdefeggfkahqfqn b hapafedccfgfgfofkqhnf bd hcnajbdedefggewpomwhg b hcnakaceddfggnnxakqqk bc hhjaibafffeggafaqhahg b hboajacedfeggnohaqoqn b hblakacdedfggfnhagahg b hhkaeabdfegfgghohaaof b hokababcegffgfhqkqafo b hojaeabcefgggnahopugo c hgkagabceegggfhqbskjg c hgkadabcefgfgfhqbaaff b hnfabbcdefggghhhvgttd bg hofacbcbegffgaabnaqgf bc hgkagabceeggggqqgocfb c hfhaibefdeeggmmakmean c hokacabcegffgfhqsxqfk b hlkaiabdfeeggfhoxqbhk bc hgjafabceegggnahgfovb c hldaebccfegggqakefdvf c hokacabcfgffgfaqhhaqf bc hofacbcbegffgaabnqxbf bc hgfadbcbefgfgaabbxann b hnjaebadfegfghkghhafb b hpjaaabfgegfgbahqqrrb bc hknaibbdefegghgkhhfhf b hdnaibfedefggpxpoldhn b hboakaeedefggfahaqaab b hfnabbedfgefgaawaakbk b hjpaaefegedfgjqoqjnon b hokababcegffgfaqbqqkb bc hcoajacedfeggobqxqbaf b hokababcegffgfaqbxhkg bc hokababcegffgfaqfqxon bf hokababcffgfgfaqqaxhg bf hjpaacedggfgfkkndmuuo b hokacabcegffgfhqnqqgg b hlkaiabdfeeggnhoxqbhf b hlkaiabefeeggfhhxaqqk b hojababcegffgfhhfqxon b hfdadbcdefgfgqqqqhagn bh hnhaabedgfefgqafhxffn b hlkaiabdefeggohoahnqk bh hofabbcbgggffaabaqhxb bc hojababcegffgfhhbxhkg bc hddafcbceegggqhbfnwko c hfhacbefdgegghaefdnvf c hjnabbedfgefgaafxhkkf b hcnakaceddfggbnxakqhk b hokacabcfgffgfaqqqahb b hipaiedcfdeggsfohfkhg bc hgfadbcbefgfgaabsqqof b hnfaibcdefegghhhoffqk b hgkadabcefgfgfhqbaann b hofabbcbegffgaabgqqgg bc hblakacdedfggfnhagqhf be hokacabcegffgfaqvxqbf b hbpacfcdegefghofohffk b hgkadabcegffgfaqvqqnb bc hgjadbacefgfghkhfaabk bd hokababcgggfffhqaqhxn b hokababcegffgkqhnaanb b hojababcgggfffhhhaqxo bc hgfadbcbegffgahbgqxob b hghaebbdfegfgqnbqxqbb b hblafacdefgfgknaxaafb bc hapajdecdefggnvvnvqan bg hojababcfgffgbqqqqhag bc hbpaccfedgefgkavnqgkg b hgjadabcefgfgnqhfxhfg bj hknaibbdefegghgkxhfhk b hbhakdcdedfggafkakaab bd hklaibbdfeeggafsaafhg b hcoakacdedfggfkxafaab bc hkhaecceeffggufhxxoon bc hdfafacdefgfgnjaqhqgb bi hodabcbbegffgqhkjaafn bf hokacabcffgfgfhqahaqn b hgkadabcefgfgfhqsaxnb b hnfaibcdefegghhhfofhg b hgkadabcefgfggqafxhfg b hipaebdceffggffgkuujf bd hapafedccfgfgfosbqhng b hlfabbccegffgahokaakf b hblakacdedfggfnhagaan b hblafacdefgfgknhhhqkb b holaacdgfeefgqgaqxobf bd hapajbcedfegggbbbakan b hmpaacegefefggnhneokf b hokababcegffgfhqgxafb b hokababcegffgfhqkqxno b hcoakaceddfgggohxfaak bc hdnaiaeddefggftthfbqk b hapakedccdfggffffnhhk b hlkaiabdfeeggfanxxnaf b hghaebdfdegggtnqkxqul bdd hhgacaceegfggnfxfhoul br hjlabbedfgefgqqbxqbbf b hgkadabcefgfgfhqsqqog b hokababcfgffgfhqqxhab b hojababcegffgbqqjaafn bc hgjadabcefgfggqafxhkf b hflacaceffgggfnxwraxa b hglaicdcfeeggqvkxhnhf b hnjacabdeffggfqbponfg b hgjadabcegffgfhhgqhfk bc hlkacabdfgffgfantwbfn b hokacabcffgfgfhqqhqag b hokacabcegffgohhohxgf b hboajacedfeggnnhaqoqn bn hgjadabcegffgfhhghxon bc hknaibbdefegghgwaxbhg be hcoajacdefeggfkhhqfqf bn hgkadabcefgfgnaawaxkf bc hboakaeedefggfahaqqqb b hcoakacdedfggfkxhfhhg bc hlkaeabdfegfgfhoqhhkg bc hklaecdedfgggqkhbphep bd hknaebbdefgfghgkxhagb b hhjaibadfeeggafgqafhk b hhjaebadfegfgafkaahng b hnfaibcdefegghhhfffhf be hblakacdedfggknahkqqo b hojacabcefgfggqakxakb bd hknaibbdefeggabwaabaf b hblakacdedfggkraabaab b hodabbcbegffgaqkfhhfn b hgjadabcefgfgbqqjqqof b hblajacdefeggkrxaabaf bc hdnaibfddefgghxonhgqn b hokacabcegffgfhqgqakf be hgjadbacefgfghkhfxafb b hblakacdedfggfnaxbaaf bi hokacabcegffgfaqohqbn bc hlfacbccegffgahonaxbn bj hokacabcegffgfhqsaafn b hokacabcegffgfaqoqxgk bc hofacbcbegffgaabnaqgn b hnhaacefggffgtitexlkw b hojababcgggffbqqaqhxb bi hokacabcfgffgfaqhhaqn b hojababcegffgfhhfhhff be hooaaacegffggnkffbbwk b hfdadbcdefgfgaaaahhbb c hfdadbcdefgggaaaahhrw be hjpaaefegedfgjaoqjnkn b hbhakdcdedfggafkhkhhg bd hknaebbdefgfghgkhaqbk b hbpaifcdedegghofogfan bc hmnaibbdefeggannhaoaf b hgkadabcegffgfaqvqqnk b hlkaiabdfeeggfanxqfaf b hpkaaabefgfggfhaqagww b hokacabcegffgfhqsxqgk b hmhaebbdfegfgqngxqqfo b hgkadabcegffgfaqgqhfk bc hepabccdggefgoknqaffn b hdoacaefdggfgktxaixcl b hmpaadegfeffgjjqhfaxg bd hblakacdedfggknhxoaaf b hapafbcedfgfggbwbqaon bc hokababcgggfffaqhaqxg b hgkadabcegffgfaqghxon bk hnkaeabdfegfgfhvxqqgo bc hokababcegffgfaqbqqbb b hblakacdedfggknaxbaak b hojacbacegffgafqbxhkf b hhjaebadfegfghkfhhhfg b hblakacdedfggfnahbqqo bq hhjaibaefeeggafqqhaqn b hapafdcecfgfgnckghqgg b hnkaeabdefgfgghfxhhgg b hokacabcfgffgfaqqqahk b hblakacdedfggknaxkaaf b hokababcegffgfaqbxqkg bc hhjaebadfegfgafkqahgg b hcoajacdefeggfkaaqkqn b hflaicdcfeeggqobhxghg b hlkaiabdfeeggnhvhqkhg b hblafacdefgfgfraaaaff b hklacbbdfegggqgnmnrwn b hfdafbcdefgggaaaaqqjs bo hfdafbcdefgggaaaaqqof bdg hokacabcegffgfaqvhhkn b hblafacdefgfgknhhhhkf b hcoakacdedfggfkhagaab b hokababcffgfgfaqqaxho bc hknaibbdefegghgkxhkhk b hokacabcegffgfhqnaqgf bc hhjacabefgggfbahxhfok b hbnakaceddfggbkxxbqqb b hnkaiabdefegggqbaqnhk b hgjadabcefgfgbqqbqaon bc hknaebbdefgfghgkhhqfk b hokababcegffgfaqbxhko bi hokacabcegffgfhqnqxbf bc hcoakacdedfggfkhhgqqf b hokababcegffgfaqfhhff bc hgjadabcefgfgbqqbaxfk bc hhkaiabeefeggfhqaqhaf bc hblajacdefeggkraaabab b hokababcegffgfaqfqxgn b hojababcegffgfhhfqxgn b hblakacdedfggknahbqqg b hhjaibadfeegghkfqqbqg b hdhaibcfffegguoexemqb b hokababcegffgfaqfhxon b hddafbcdefgfgqqaaaqfo bc hgkadabcegffgfaqvqhnb bc hlhaacegdfeggqaqoqfbg b hojababcegffgfhhbxhko bc hokacabcffgfgfhqahaqf bc hboajacedfeggfnhaaoab b hgjadabcegffgfhhghhnf bd hgoaiadfeffggnhhhfoqk b hghaecdcefgfgqnoxxakk b hojababcfgffgbqqqqhao b hddafacedfgfgfkaaqqof b hlkaiabdfeeggfanqqfqk bl hgkadabcefgfgfhqsqqof bc hhjaibadfeegghkfqqbaf b hlkaiabdfeeggfhoxxohk b hojababcgggfffhhhaqxg b hofacbcbegffgaabnqxbg b hhjaibadfeeggafkqakhk b hokacabcegffgfaqoqqkb be hpkaaabefgfggfhaqacck b hokacabcegffgfaqvhqkf b hgjadabcegffgfhhvqqnk b hhkaiabfffeggfhhaqhab b hnfaibcdefegghhhoofhg b hnjaebadfegfghkgxqaff b hcnafacedfgfgbnaahaob b hgpaadcgefgfgooxkuquf b hokababcgggfffhqaqhxb b hjpaacfdgeegggqbqbgoj bd hdhaedcdffgfghnoaiakf bp hojababcegffgfhhbqqbb b hokababcegffgfhqgqqgg b hgkadabcefgfgnhhfxhff b hgkadabcefgfgfhqkqxob b hjpaaefegedfgjqohjnok b hlkaiabeefeggfaahxqaf be hndaibcdefeggqqqgbgak b hlgabacdgfgfgffxhwhrx b hgkadabcefgfgfhqbaqnf bc hgkadabcefgfgfhqbxanf bc hojababcegffgfhhbxqkg bc hlgabacdgfgfgffhhfhkh bc hcoajacdefeggfkahafab b hbpaccfdegefgjqjoqfog b hgjadabcegffgfhhghxgn b hgkadabcegffgfaqghhnf b hcoakacdedfggfkxhkhhg b hboajacedfeggnohaqoqb bc hhjaebadfegfghkfqhhbg b hgnaebbdfegfghgohhqok bc hokacabcffgfgfhqqhqaf bc hhkaeabdfegfgfhfqhanb b hokababcegffgfhqgxafn b hboajacedfeggfohaqoqn b hnkaeabdefgfgfasqxqkn b hjpaaefegedfgjaohjnkk b hokababcegffgfhqkqxbo b hokababcegffgfhqgxqfb b hokacabcegffgfhqsaaff bc hokababcfgffgfhqqxhan b hjpaaefegedfgjqoqjngn bo hflaecdcfegfghbfqhhbg b hcoakacdedfggfkhhghho b hnfaibcdefegghhhoffhk bd hlkababdefgggfanxsssg b hokababcegffgfhqkaakn b hfdadbcdefgfgaaaaqqff bk hfdadbcdefgggaaaaqqof bg hcoafacdefgfgfkhhhhkk b hhkababfgeeggfhhhhffo be hblakacdedfggfnaabahg b hofabbcbegffgaabgqako b hokacabcegffgfaqoqxok bl hfnabbefgfeggaapdaxro bc hnkaeabdfegfgfhgqqqbo bd hknacaceeffgggvhrbbxg b hboajacedfeggfnhaqoqb b hgjadabcegffgfhhgqhfb b hbnajacedfegggbqqabab bc hhdacbcfegfggqqqrdrul bf hdnabafeggegffxhgofof bf hdlacccdfggfghsshgofo bd hboajacedfeggnohxagqo b hglaccdcfegggqgblgjgs bc hcoajacdefeggfkaaakab b hlkaiabdfeeggfhohxghg b hblakacdedfggknhaoqqb bc hgkadabcefgfgnaanhxgf b hgjadabcefgfgbqqbaanf bg hnjacabdegggfgqbdbfog bc hhjaibadfeegghkfhqbhg b hcoajacedfeggoohhafak b hfdadbcdefgfgaaaahqbf bf hgkadabcefgfgfhqsaqfg b hlkaeabdfegggfanxqhmd b hepaececefgfggnoneakk bl hnjaebadfegfghkgxhafb bd hipabcedgfggfkgshqemn b hhkaeabdfegfgfhfhhanb b hhkaiabdfeeggfhfqhfqo bc hboafacedfgfgfnhaqqon bd hcoafacdefgfgnkaaqqgf bc hokacabcegffgfaqohqbf b hcoafacdefgfgfkhhqhbk b hokababcegffgfhqkaxnf b hhkaiabdfeeggfhbqhkaf bc hokacabcegffgfhqnqqfg b hdhaecdcfegfgakkaxaff b hnfaibcdefegghhhoofan b hgkadabcegffgfaqghxgn b hgkadabcegffgfaqvxqbf b hcoafacdefgfgfkhhqhkf b hokacabcegffgfhqsaqfn b hcnafacedfgfgfvqqaakf b hgkadabcefgfgnaafxakk bl hokacabcegffgfaqohqkn b hlkaiabeefeggfaahxqqg b hnlaacdgfeefgqoahxoff bc hjlaccdedffggdnqgwrcn bd hcoakacdedfggfkxafqqk b hgkadabcegffgfaqgqhfb b hlkaeabdfegfgfhohhhfg b hlkaeabdfegfgfanqqhgk b hblakacdedfggfnaabaan b hepaecddffgfgonbqhahb bd hblajadedefggfuddofaf b hcoafacdefgfgfkhaqakf b hbpaeddfdegggnghkfqkc b hhjaibaefeeggafqqhahf bc hdnabbfdegeggppsuxowk b hdhaedcefdgfgaohxbqfb b hcoakacdedfggfkxhfqqf b hokacabcegffgfhqgxafk b hdhaicdcfeeggagkqafhk bt hipaidcefffggcknqtphg bd hipabbeefggfgnnkmemmj b hgkadabcefgfgfhqbaafn b hhjaibafffeggafaqhaab b hlkaeabdfegfgfanqxaff b hlkaeabdfegfgfhvxhhgg b hcoakacdedfggfkxakaab bn hokacabcegffgfaqoqxgb b hblakacdedfggknhhoqqg bc hknaebbdefgfghgkxaakb b hcoafacdefgfgfkhhqqkk b hbpaefceddgfghvknnakn bc hokacabcegffgfhqnqxnf b hgjadabcefgfgbqqbaxfb b henakbdcdefggakkoaqqn bg hnkaiabdfeeggfhghhnhg b hipaeedcfdgfgsofaoanf b hgkadabcegffgfaqvxhnf b hblakacdedfggfnaabqqb b hgoaiadfeffggfaaxnkab b hddajacedfeggkohhqgqo b hipaiedcfdeggofohffab b hgkadabcegffgfaqgqhnk b hgjadabcefgfgbqqbqagn b hlhaacddggefgmjbmwfob b hgjadabcefgfgnqhfxhff bd hhjaibadfeeggafgqakhk b hofabbcbegfggaabgqqof bd hblakacdedfggknhaoaan b hdhabbefgeeggpxuhhprv b hboajacedfeggnohaqgqn b hboajacedfeggnnhaaoab b hgjadbacefgfghkhfxafk b hmnabbbdffgfghgftkvgk b hokacabcegffgfhqnaqgn b hknaebbdefgfghgkxaabn b hddafbcdefgfgaahhqqgf b hokacabcegffgfaqvxhfg b hapafedccfgfgfoffhafb bh hgkadabcegffgfaqghxof b hbpabbeffegggkfhakddo b hipaibddfeeggnknhknqb b hokacabcegffgfhqnaqff b hnkaiabdefeggfasqxoqf be hldaibcdeffggaaefwbpn bg hghaccdeeffggabldqggn bs hokacabcegffgfaqvxqkg bc hlkaeabdfegfggqgxaabb bc hcoafacdefgfgfkxhahbk b hapafbcedfgfggvknqagb b hcoajacdefeggfkhaqkqf br hdlabadfdgfggfxhkfcnn b hblajacdefeggkrxaanaf b hdfafacdefgfgbbaqaqnb b hokacabcegffgohhohxof be hljaeabdefgfgghkaaakk bv hddajcbedefgghhaaohqn bf hbpaicfeddeggkqnnbkqb b hgjadabcefgfgbqqbqaof b hblakacdedfggknhaoqhf b hgkadabcefgfgfhqbxabf bl hhjaibadfeegghkfhqbab b hgkadabcefgfgfhqsqxgk b hhkaeabdfegfgfagqqqgk bc hdpaadeceffggjffjmmwn b hboafacedfgfgfohaaqfn bh hhjaibadfeegghkfqqbak bc hipaeedcfdgfgsffafanf b hdgajacdefeggfwhhhfan b hdlaecdcfegfgqbkxhagb b hgjadabcefgfgbqqbaxnk b hlkaiabefeeggfhqxahhf bc hnfaebcdfegggaaavvqha bc hbnafacedfgfgnjqaahbf b hfoaiadefffggoqxqbghf b hlkacabdffgggfanarngg bd hgkadabcefgfgfhqbaqng b hdnaibfddefgghxkohchn b hnfaibcdefegghhhoffqb b hnkaiabdfeeggfhgqhfqf b hblakacdedfggknaakaan be hhjaiabffefggbaahxqab bk hcoajacdefeggfkxhafaf b hhkaiabdfeeggfhbqqkaf bc hhjaibaefeeggafqqhaqb b hhjaibadfeegghkfqxgqo b hnfaibcdefegghhhoofhf be hchakdcddefggaokkaaan bg hboajacedfeggnnaxakqg bd hlkaiabdfeeggfhvxhkhk b hhkaeabdfegfgghohaaok bc hhfaebcfdfgfghhhgfhog b hnkaiabdfeeggfhghhfab b hlkaeabdfegfgfhvhhhfg b hepaidcfffeggrkxpugaf b hgjadabcegffgfhhvxhnf b hhjaibadfeeggafgqqghk b hlkaeabdfegfgfanqxqfo bf hgkadabcefgfgfhqbaqff b hblakacdedfggfnaabaho be hjpaaefegedfgjqoqjnob b hgjadabcegffgfhhvxqbf b hokacabcegffgfhqgqafg b hlkaeabdfegfgfanaqhfk b hlkaeabdfegfgfhoqhhbg b hcoakacdedfggfkxafaan b hblafacdefgfgkrxaaabf b hhfaeacefefggnbaswbqg bd hbpabbcfegfggkghklalo bf hnkaiabdfeeggfhghhfhf b hnjaiabdefeggghfaxbhf b hhkaeabdfegfgfhfqxqnn b hgkadabcefgfgfhqbxann b hblakacdedfggfnaabqhf be hdfafacdefgfgnjxqqhgk bc hknaebbdefgfghgkxhafb b hhkaiabfffeggfhhaqxqn bh hcoajacdefeggfkahqfhk b hkhaibddeefggucctxchk b hkoacacdegfggfkarxktl b hhjaebadfegfgafgqahgg b hboafacedfgggofqhaqos bcc hdnabbeffgeggmxiqmlvg bcc hcoafacdefgfgfkxaaabf b hlkaiabefeeggfhhxaqhk b honaaadffgeggnqunnkvk bp hklabccdggffgmfnhksof bh hlkababdefgggfhoxvvvb b hgkadabcefgfgfhqsaxfk b hcoajacdefeggfkahqfqb b hipaedcefdgfgcknqoagb br hkpaaefegeffgfaohjetk b hhjaeabdfegfgnqchhhng bj hcoakacdedfggfkxhfhho b hokababcegffgfaqbxhfg b hofacbcbegfggahbvhhof b hojababcegffgfhhfqhkb b hhjaibafffeggafaqhaho bc hnjabbadfgfggafbqsckk b hhkaiabdfeeggfhbxhkhk bc hlkaiabdfeeggfhoqqkqf b hhkaiabdfeeggnhfhhfhf b hojababcegffgfhhfqxob b hodabbcbegfggqqgbqqnk bd hcoakacdedfggfkxafahg bc hflacbedffgggqqnldbgs bg hokababcegffgfaqfqxob b hboajacedfeggnnhaqoqb b hokababcegffgfaqbqhfn b hnjaeabdfegggnqgxxqha bh hbpaccfedgefgkannakkf bt hgkadabcefgfgnaanxxkf b hknaebbdefgfghgkxahbo bc hnkaeabdfegfgfhvxqqfo b hblajacdefeggkraaanab b hblakacdedfggkraabaan b hfoabacdffggggfhfketd bc hloaaadegeffgnttfnonk bk hhjaebadfegfgafgxaanb b hgnaibbdfeeggabnaxkak b hipaedbdefgggokoohhkc bn hepabedegdfggfffhnhck bv hnfaibcdefegghhhoffhf bm hbnafacedfgfgnkqxaqfb bc hljacabdegfggghkannfo bh hchakbcdeefgghjgetjhk bdd hcoajacdefeggfkxaakaf b hokacabcegffgfhqsxakb b hokababcegffgfaqfqhkb b hhjaebadfegfgafgqaaob b hcoafacdefgfgfkhhhhfk b hojababcegffgfhhbxhfg b hcoakacdedfggfkxhfhab bc hboajacedfeggfohxaoqg b hgjadabcefgfgbqqjqaof b hlfacbccegfgghabohhnk b hlkaiabdfeeggfhoqqbaf b hnkaeabdfegfgfhvqqqbo bg hknabbbdfgfgghgkakjoo b hcoajacdefeggfkahafhg b hgkadabcegffgfaqvqhnk b hokacabcegffgfhqsxqfb b hhjaibadfeeggafkqakhf b hojababcegffgfhhbqhfn b hokacabcegffgfaqohqkf b hokacabcegffgfhqgqxbg b hnjacabdegfggfqbqggkn bn hljacabdegfggbakannjs bd hlkaeabdfegfgfhoqqqkf b hnkaiabdfeeggfhghxohg b hfpaaefgdeffgoaxfkmmn bc hmpaaedffdgggffxhnumo b hokacabcegfggfaqvhhof bc hokacabcegffgfaqoqxob b hnkaeabdfegfgfhghxqnn b hcoafacdefgfgfkhhqqkb b hlkaiabdfeeggfhoqqbqg b hokababcegffgfaqfhhkn b hpkaaabgfeefgnhxhhfng b hhjaiabdfeeggnqchhkhg bf hdhabdefdggfgtmpbqogk bd hklabccdfggfgmfnqgckj bt hlkababdeggfgfhomonnk b hblakacdedfggfnaxbaak b hlkaiabdfeeggfhohqbhg b hlkacabdffgggfanarsgg bd hgfadbcbefgfgaabsqqgf b hokacabcegffgfaqvhhff b hokacabcegffgfaqvhqkn b hnfaibcdefegghhhofkhk bd hnfaibcdefegghhhookhg b hojababcegffgfhhfhxof be hghacdcfegffghkaaqgbn b hhkaiabeefeggfhqaqhqo bc hboafacedfgfgfnhaqhof b hokababcegffgfaqbxqbg b hgkadabcefgggfhqsqqbg b hhkaeabdfegfgfhbxqqgf b hnkaeabdefgfgnabaahff b hokababcegffgfaqbxqko bq hofabbcbegffgaabgqqgo b hhkaeabdfegfgfhfqhabb b hblakacdedfggfnahbqqg b hokababcegffgfhqgqako b hhjaeabdfegfgbaohhqok bc hgkadabcegffgfaqgqhnb bn hcpaeefeedgggsasgsank bc hlkababefgggfnaaxaknb b hgkadabcegffgfaqghxgf b hokababcegffgfhqgqqfo b hokababcegffgfaqfhxof bc hojababcegfggbqqjaank bd hojababcegffgfhhbqqkn bc hokababcegffgfhqgxakb bc hlkaiabefeeggfhhxaqqb b hnkaeabdfegfgfhgqhakb b hbnafacedfgfgffhhaabb b hokababcegffgfhqkqafg b hgkadabcegffgfaqvqhfb bi hgjadabcegffgfhhvqqbb bc hcoajacdefeggfkhhqfqg b hblafacdefgfgkraaaaff b hokacabcegffgfhqgxxbk b hkhaedcceffgghonxhrab b hokababcegffgfhqkqxng bc hofabbcbegfggaangqqof bd hclajbddeefggissdxoqk bm hllaacdgfeffghfahhnkn bc hgkadabcefgfgfhqsqqgg b hboajacedfeggfohaqoqb b hnkaiabdfeeggfhvxqnqk b hnkaeabdfegfgfhghhafb b hokababcegffgfaqfhxgn b hhkaeabdfegfgfhfhhafb b hnkaiabdfeeggfhgqhfaf b hhjacabefgggfnahhhfog b hokacabcegffgfhqnaqfn b hlkaeabdfegfgfhoqqakk b hojababcegffgfhhbxqbg b hhjaebadfegfghkfqhhbo b hboafacedfgfgfnhaqqob bs hokacabcegffgfhqnqxng b hnkacabdffgggnhghnfbc b hgjadabcefgfgbqqbqagf b hbhajccdeefggakkxanqo b hmhaiddceefgghjfhqoab bp hgkadabcegffgfaqvxhff b hlkaeabdfegfgfhoqxhkk b hhjaibafffeggafaqhaan b hgjadabcefgfgbqqbaxnb b hhkaiabfffeggfhhaqhhg b hboafacedfgfgfohaqqon bd hhkaeabdfegfgfhbqqqbf b hflaicdcfeeggqvbhhkab b hlkaiabdfeeggfanaxnab b hlkaeabdfegfgfanaxqfo b hljaiabdefeggfhoxhfhk bx hmnaebbdefggghgfhhhaq bh hokacabcegffgfaqvhqbf b hhkaiabdfeeggfhfqhfaf bc hhjaibadfeegghkfhxgab b hcpabedfegffgrwmomidf be hlkaiabdfeeggfhvhhkhg bc hcoajacdefeggfkahafan b hlhaacdgfeffgqjhaankf b hcnajbdedefggavhkqcaf bv hehajcdceefggqbgqqbqk bj hcoajacdefeggfkaaqkhk b hcoajacdefeggfkahqfhf b hhkaiabdfeeggfhbqhfaf b hblafacdefgfgknhhqqnb b hpfaaacgfffegggsgkcfo b hhkaiabeefeggfhqaxhqn b hnjacabdefgggnafakkwo b hokababcegffgfhqkaaff b hgkadabcefgfgfhqsaqff bc hdnaibefedeggexetfuqf b hhkaeabdfegfgfhfqhhng b hldabcbcegfggqhbnaagb bc hokacabcegffgfhqsaakn b hjpaaefgedeggbqqbggbg bce hlkaiabdfeeggfanqxnqk b hlkaeabdfegfgfhoqqabf bl hlhaacfdeggfgmtglljbj bf hjhaccdcefgggtfolkwfg bl hnkaiabdfeeggfhgqxgqf b hojababcegffgfhhbxqko bc hlkaiabdfeeggfhvxqkqb bc hcoajacdefeggfkaaakhg b hlhaacddggefgmjbmwkob b hboajacedfeggfohaqgqn b hlkaiabdfeeggfhoqxgqf b hlkaeabdfegfgfhvhhhng b hfhacbdedfgggpblswjns b hbpabefdgefggnqotndur b hnkaeabdfegfgfhghxhnk b hgjadabcegffgfhhvqhfb bc hhjababdgfgfgnqfdwrsv bd hokababcegffgfhqgxqfn b hokababcegffgfhqgxqgb b hllaabedgfffgqxkxqbfn b hnkaiabdfeeggfhghhfan bc hgkadabcefgfgfhqbaqfg b hlnaaaeffdgfggiifkokk bf hgkadabcefgfgfhqbxabn b hhoaaaedfgeggghqsofob b hokacabcegffgfaqvxqbg bn hlkaeabdfegfgfanaxanf b hokacabcegffgfhqsaqff bc hlkaeabdfegggfhoxxhaq bi hknaibbdefegghfoxxfhf bu hhkaiabdfeeggfhbqhkqo bc hfnacaefdgffgghhxqfob b hbnajacedfegggbqqanab b hhkababfegeggkaaaabkn b hhhaabgfffeeguqtxemof bd hgkadabcefgfgfhqsaqng b hcoajacdefeggfkaaqkqb b hlkaeabdfegfgfhohqanf bn hcpaidffdefggrixsothg bh hgnaiadefffggnqqqgbhf b hhdaccbfefgfghhhwbhro bc hlkaiabdfeeggfanaqfab b hnkaeabdfegfgfhgqxhkk b hokababcegffgfhqkaxnn b hhkaiabdfeeggfhfqhkqo b hlkaiabdfeeggfanqqfhk b hnkaiabdfeeggfhgqxoaf b hhkaeabdfegfgfhbqhabb b hlhaabedgffggqlfxpnww b hcoakacdedfggfkxhkhho b hlkababdegfggfanqbbks b hlkaeabdfegfgfanaqhnk b hokacabcegffgfhqgqaff b hhkaiabdfeeggfhfhhfab b hhkaiabffeeggfadqpalg bg hbnakaeeddfggndideqqg bg hjlabacdgffggfnxhnwdl bc hlkaiabdfeeggfhohqbab b hhkaiabfffeggfhhaqxhk b hhjaibadfeegghkfqxgaf bf hboafacedfgfgfnhaaqfn b hfpaaefdgefggbxgeotdo bc hepabedegdfggsosaoxjo bcc hgnabaddgfgfggipgcrog bk hcoafacdefgfgnwahahkf bx hnjaeabdefgggnafhaqdl bd hnjacabdegfggnqcaossg b hokababcegffgfhqkaxbf b hhjaiabdfeeggghnhanhf bc hhkaiabdfeeggfhbqqbaf b hhkaeabdfegfgfhfqxhnk b hknaebbdefgfghgkhhqfb b hokacabcegffgfhqsaqgn b hlhaacefffgeguapxptfg bc hnlaacdefgggfhbmqtgjb bc hgkadabcegffgfaqvqqbk b hgkadabcefgfgfhqsaxnk b hnkaiabdefeggfasqxoqg b hgjadabcegffgfhhvxhff b hcoajacdefeggfkaaakan b hhkaiabeefeggfhqaqhak b hnkacabdegfggnhgaossg bf hnkaeabdefgfgnabaaafn bc hhkaeabdfegfgfhbqhhng b hlkaiabefeeggfhhxaqhf bc hnfaebcdefgggaaakkqqx bg hnfaebcdfegggaaavvaax c hhjaibadfeegghkfhxghf b hlkaeabdfegfgfhoqxqkn b hfpaafecgegfghffpoixo b hhkaiabdfeeggfhbxhkqn bc hdhaecdcfegfgakkqahgo bw hipacedcfgffgfosqhdlf bc hnkaeabdfegfgfhvqqqko bd hlkaiabdfeeggfhoqqbak bc hlkaeabdfegfgfanqqqgk br hlkacabdffgggfhoxfsjf by hcpaideeedfggnkknkxak bm hhjaibadfeeggafkqafhk b hcoakacdedfggfkxakaan b hnkaiabdfeeggfhghxghg b hnkaiabdfeeggfhvqqnqf b hgpaaeecfggfgvfkxildn b hlkaeabdfegfgfanaxafk bl hlkaeabdfegfgfanqxagf b hnkaiabdfeeggfhgqhnqf b hhkaiabdfeeggfhfqxgqo b hhkacabdffgggnhfhrbcb bd hepaeedfefgfgfoqoahhk bv hnkababdffgggoqbqbbgg bf hokababcegffgfaqbqqbn b hlkaiabdfeeggfhvxhkhf b hapafdcecfgfgnnkkaqng bB hbpacfcedgggfhbbbqahf bh hnkaeabdfegfgfhgqxqbn b hokacabcegffgfaqvhhfn b hhkaiabfffeggfhhaqhan b hokababcegffgfaqbxhfo b hojababcegffgfhhfqxgb b hhkaiabffeeggnhtttmtb b hcpabdfdgfggfbtnhxaqp bk hcoafacdefgfgfkxahagf b hhkababfgeeggfhhhxgfo b hhkaiabeffegggqmxpaek b hnkaiabdfeeggfhgqxoqg b hfnacbcffefgghoqtdcfk b hjhabbecfgffgqqkqqbgb bj hokababcegffgfaqfqxgb b hhhaadfggfefghahixtfj b hnkaiabdfeeggfhghxoab bd hcpaeecedffggkfbgxunf bd hcoadadedgffgnpdaubgg bd hhkaeabdfegfgfhbxhhog b hlkaiabdfeeggfhohxohg b hhkaeabdfegfgfhbqqabf b hfhaebefdffggqqifhwbg b hljababdegfgggqnakkbg bl hbpaeefedfgfgnqkntqig bdd hboafacedfgfgfnhaqqgn bd hnkaiabdfeeggfhfhqnan b hlkaeabdfegfgfhoqqqkg bo hlkaeabdefgfgkakxahbg bn hokababcegffgfaqfhhkf bn hokacabcegffgfhqsxqgb b hlkababdegfggfhohffgb bo hlkacabdegfggkakannjs bg hlkaiabdfeeggfhohxgab b hhjaebadfegfgafgqahgo b hhkaeabdfegfgfhfqhann b hcoajacdefeggfkaaqkhf b hojababcegffgfhhbxhfo b hklaecdeffgfghguhlcnk bc hblafacdefgfgkrxaaanf bt hhjacabdffgggnqfqnvbv b hljaiabdfeegggqsxafqg b hfhaedcdfffggikomhohk bd hjnaeaceeffggbjarggqg bd hnkababdfgfggnabqsckk b hhjaiabefefggghlhaeen bd hgkadabcefgfgfhqsqqgf b hlkacabdffgggfhohrobb bd hgjadabcegffgfhhvqqbk b hfpaacgdgfgffgtbteqaq b hfhaccedegfggtmfxhfvk b hepacedfedfggsolgoisk bc hgpaadfgdfgfgnpdbdxma bc hmhaibbdfeeggqbgqqbqg bC hmnaebbdefggghffhhhaq bi hlkaiabdfeeggfanqqfqb b hepaebddfegfgnbgqbhbf b hdnacbefegegglpmtadcv c hdpaacdeggffgvncxhaqk bc hpdaabceegfggaafwbbfo be hhjaibadfeeggafkqxbhk bt hlkacabdffgggfhohrvbb bd hokacabcegffgfhqgqxbf b hojababcegffgfhhbqqbn b hnkaiabdfeeggfhghhnab b hmnacbbdefggghffakkwo b hjhacbedfefgghhgddfob b hpdaabcffegggqqnffvco b hghaedcfedgfghohaoafk b hhkaiabdfeeggfhfqxoaf bc hflabbcdegfgglcflgwgf b hlkaiabdfeeggfanaqfhg b hcoafacdefgfgfkxaaqbf b hnkaiabdefeggfasqxgqf b hhkaiabeefeggfhqaqhqg b hnkaiabdefegggqbaqnqb b hnkababdfgfggnabqbckk b hddafbcdefgfgaahhqqgg bq hddafbcdefgggaahhqqbg be hfdafbcdefgggaahhqqbg bu hfdafbcdefgggaahhqqrw bq hokababcegffgfhqgqqgo b hhkaiabdfeeggfhbqhkak bc hfhaidcefdegghfhxoohg b hhkaeabdfegfgfhfhxqfn b hcoajacdefeggfkhaqkqg b hchakcdceefggtjoqpoqn bh hdnaeaefefgggbxqhwahq be hhkaiabdfeeggfhfhxoab b hdhaibfddefggqlofmkaf b hokababcegffgfhqgxakn b hfpaafgdfdgfghhnmbxda b hdhaeceeffegguemeqqbo bc hnkaeabdfegfgfhgqhabb b hflaccdcefgggqobavvok bh hokacabcegffgfhqsaakf b hhjaibadfeegghkfhxgan bc hokababcegffgfhqkqxbg b hgkadabcegffgfaqvqhfk b hhkaeabdfegfgfhbxhagb b hlkaiabdfeeggfhoqxoqf bc hcnakaddeefggbdiuiuhg bc hhjaibaffeeggafdqpadn b hkhabbdefeggghbuidsvf b hlkaeabdfegfgfanaxqfg bc hokababcegffgfhqkaafn b hipaieecdfegggbbbqbak b hljababdegfgggqnakkvc bv hhjaibadfeegghkfqxgqg b hboafacedfgfgfohaaqkn b hhkaiabfffeggfhhaqhho bc hchakcdceefggtjoqlfab b hhkaeabdfegfgfhfqxqbn bt hlkaiabdfeeggfhoqxgaf b hpdaacbeefgggqqkngbng b hlkaeabdfegfgfanqxqgo b hcoafacdefgfgfkhaqabf b hlkaeabdfegfgfhohqqnf b hmhaebbdfegfgqbgxqqfg bl hlkaiabdfeeggfhohqkhg bc hhkaiabeffeggnheiulhf be hdpaaedfegeggoolcxrob b hhjaeabdfegfgbaohhqob b hgpaaeffgeggfgdlanlil bc hnkaeabdfegfgfhghxqfn b hcoajacdefeggfkxaakak b hcoafacdefgfgfkhhhhkf b hlkaiabdfeegggqnqakqb b hepaeeefdfgfgcsunaqpo bd hokacabcegffgfaqvhqbn b hchakbcdeefggqgnipwhg bc hlkaeabdfegfgfanaqhff b hbnafacedfgfgnkqxaqkb b hgpaaddgefeggsoafxgon b hfoabacdegfggofhbdwlp bx hlkaiabdfeeggfhohqbhf b hlfaiacdeffggnbawbkxn bc hjpaaefgfdeggbaimogig bc hhkaiabfffeggfhhaqxqb b hmpaadcgefffgknhsplpg b hokababcegffgfaqbxqbo b hnkaiabdfeeggfhvxqnqb bc hflaicdfdefggenhbtgxk bf hnkaeabdfegfgfhghxqnb b hjpaafeegdefghoohnfff b hhfacaceegfggnbqwqwqx be hlfaibcdeffgghhhgrwho be hgnaeacdfeggggohffqah bi hbnafacedfgfgffhhaabn b hlkaiabdfeeggfanaxnhg b hlkaeabdfegfgfanqqhgf b hdoaiaeefdfggktddnnmf b hlhaabfgffeeguihxemog bd hdhaicddeefggaknxanak be hlkacabdegfggkakannvc by hnkaiabdfeeggfhgqxoak bc hflaebdfefggglgaatnvg b hbpabecfefeggnbxniogb be hfhabdcedgfggafanwgok b hblafacdefgfgkraaaakf b hcoafacdefgfgfkxhahbf b hbpaefdcdegfgqvkkkabn b hcoadacdegfggfkapxewj bc hhhaadgfdgfegtlebtnfn bw hnfaibcdfefggaaannbaf b hnkaeabdfegfgfhghhhfg b hokababcegffgfaqfhxgf b hlkaiabdfeeggfanqxnhk b hlkaeabdfegfgfhohqaff bo hnoaaacgffefggfrrfgvb bc hmlaibbdefeggqgsqqoqb b hnoaaacgffefggfrkfovb be hboafacedfgfgfohaqqgn bv hlkaeabdfegfgfanaxqno b hnkaiabdfeeggfhgqhnaf b hlkaiabdfeeggfhoqqkaf b hnkaeabdfegfgfhghxhnf bc hgjadabcegffgfhhvqhfk b hhjaebadfegfgafgqahog b hlkaiabdfeeggfhohqban bc hnkaeabdfegfgfhgqxhkf bc hnkaiabdfeeggfhghhnhf b hhkaiabdfeeggfhfhhfhf be hbpaeedfedgggbjxsbxnk b hbpaeeefddgggbfxobxnk b hhjaibadfeegghkfqxgak bc hcoafacdefgfgfkxaaanf b hlkaiabdfeeggfanqqfhf b hboafacedfggggfhhhhfo bk hnkaiabdfeeggfhghxohf b hboafacedfgfgfohaqhok b hcoafacdefgfgfkxaaabk b hlhaadfgdegfgthiblwwg b hjpaacfeffggggakmlhah b hldaecbeeffgghhxjosxf bce hbpaedcfedgggfohofafs bce hcpaidfeffeggoafqhohf bcc hgkadabcefgfgfhqsaqnf b hjpaaefedgggfnqcbxmpg b hojababcegffgfhhbxqbo b hcoafacdefgfgfkhhqqbk b hlkaeabdfegfgfanaqqfb bc hhkaiabfffeggfhhaqxhf bo hnfaebcdefgggaaannhaq bk hnfaebcdfegggaaaccaax c hepaidcefeeggnrkhwoqb bd hlkaeabdfegfgfhoqxhbk bc hgpaaddedgffgcccbhxon b hnfaibcdfefggaaannbqf b hhjaiabdfeeggnqchhfhg b hkoabacdfgfggnkablcxu bz hdnaibdfdefggtnaopgqg b hlkaeabdfegfgfhoqxhkf b hnkaiabdfeeggfhgqxgaf b hjhaibcdeffgglfkmqslg bc hbpaedceeffgggrfcpmng bi hcoafacdefgfgfkhhqhbf bf hhgabaceeffggfwhcnnan bj hcpaeedcdffggvvbkxenn b hnkacabdefgggghfakkwk b hklabcdeffggghgaquvcg b hdlaicdcfeeggqfbqhfak bc hokababcegffgfhqgxqgn b hhjaibadfeeggafkqafhf b hdfakbcedefggaaqqbaab bc hlkaeabdfegfgfhoqqqbf b hhjaiabdfeeggnanaanqg b hlkababdegfggnhvhffgb b hokacabcegffgfhqsaqgf br hjlaccecfefggehbplkgg b hdlaibfddefggqdngdcqk be hnkaeabdfegfgfhgqhakn b hlkaeabdfegfgfhoqxqkb bc hdhabddegfeggubaaqbnk b hnkaiabdfeeggfhghxgab bd hlkaeabdfegfggqgxahbo b hnkaiabdfeeggfhghxoan bs hipacceefeggggbfqgqrw bp hohaacdgfffggqbqdqbbg bh hokababcegffgfhqkaxbn b hlkaiabdfeeggfhohxgan bc hglaebcfeegggakqptcbg b honaaacgdfggfgogkkkon b hlkaeabdfegfgfanqqqgb b hdnaebfddefgghxkohbqn b hnkaiabdfeeggfhvqqbaf b hhjaeabdfegfgbaohhqgk b hcoafacdefgfgfkxahaof b hohaacdfegeggqnlaengc bu hhfabacefggfgbbqvumbq be hfoacaddefgfgkuttnmfo b hhhaacffeggfgaqhmmqrn bc hooaaacgfffegknrnoogg b hfpaaeedgdggfvknpntrk b hbnafacedfgfgffhhaanb b hnjababdefgggnqghnvov bd hpkaaabgfeefgfhqxxgok bg hhkaeabdfegfgfhbqqqbg b hblafacdefgfgkraaaafk b hlkaeabdfegfgfhohxqnb bc hljaiabeffeggnqlqthin b hcpaeeddcffggswrfiqsk bc hjlaccecfefggehbplkgo b hdoaeafeddgfggqqhfqbo bd hkpaadcefgggfnrkaeelf bA hdhaibddeffggiobhpnab bc hhdabcbeeffggqqhcnnan bcc hnkaiabdfeeggfhvxqbqk b hhkaeabdfegfgfhbqqqnf b hlnaaaeddfgggbqxkvnjn bl hdfafacdefgfgbbaxhafk bc hfhabcdefgggfqnxxqobb bc holaacdfgeeggqvuthnoj b hbnakadedefggntpllian bd hboafacedfgfgfnhaqqgb bg hlkaiabdfeeggfhohqkab bc hlkaiabdfeeggfhvhhfhg b hdhabcfeegefgmhxiemob b hbnajbedeefggaafhhhhk b hbpaefecefggghgoghadv b hlkaiabdfeeggfhoqxgqg b hhkaeabdfegfgfhfqhhbg b hlkaiabdfeeggfhoqqkqg bc hboafacedfgfgfohaqqob bj hhkaiabefefggkalhaeen b hnkaiabdfeeggfhghhnan b hfpaaefggedfgbaadbnhb b hloaaaefgfggfnhxgvfgf bd hpjaabafgeefgafqqakof b hhjaebadfegfgafgqaaon b hhnaabfgeffegpqhlpaff bc hhdabcbdffgfghhigoegk b hhjaeabdfegfgnaohhqob bc hhfaibbdefeggdilfokhk c hljacabdefgggnakhfffw b hbpaedccfegggoskigaoj b hgpaabegffgfgbwpxpiqh bc hlkaiabdfeeggfhohxoab b hlkaeabdfegfgfhohqank b hnkaiabdfeeggfhvxhfqk b hmnabbbdfgfgganfangrr b hhkaeabdfegfgfhfhhhfg b hgnabacdfggfggohoiqre bf hmpaadbfefgggoktopetn bt hjoabadeggffgkqtbgocn bf hbnakaededfggbueedtqg b hmpaaccggeffgokimbtpj b hhkaiabdfeeggfhbqhfqo b hcoakaddeefggfeiixuak bd hgoaeaceeffggnkhvrkab bg hhkababdffggggqkhrkrg bh hbpabecfgeffgboxhoxxf b hlkaiabdfeeggfanqxnqb bt hlkaeabdfegfgfhoqxqbn bc hfhaebcffefggukqeawnf b hhkaiabdfeeggfhfqhkaf b hjnaebedffggghhfthgwf bm hbpabefdgeeggnananobw bu hhhaacggefefgqhaammgf be hjoacaceefgggnohbndma bc hglaibbffeeggqfdqpaun b hlkaeabdfegfgfhohxqfn b hfpaaeedfdfggvkndnuof be hgoaeaceeffggfkhvfkak bj hnkaeabdfegfgfhghhafn b hlkaiabdfeeggfhoqxoaf bc hlkaiabdfeeggfhoqxgak bc hcoakadeedfggoldththk bd hlkaiabefefggbaldexhn bc hflaicddfffggivkptrab b hgpaaccfgffeggoxetdfb be hcoafacdefgfgfkhhhhff bf hbpaeecfdegfgjohsvqof b hhkaeabdfegfgfhfqxhbk b hhkaeabdfegfgfhfhhafn b hohaadcggffgfubauunjo b hlkaeabdfegfgfanaxank b hcpaeeefdfgfgcrindatf b hnjacabdfgfgggqbhccbk bi hhkaeabdfegfgfhfqhabn b hdpaaedggffegnnptienn b hlfaebbdefgfgdihffhfg c hpjaabafgeefgafqqakgf be hdnaiaefddeggbxqqgbqk b hnnaaadffgfggnupfjgnb bc hohaabbgfeefgqnqhxgnk bd hjhaedcefegggaftqqsgb b hcoafacdefgfgfkhhqqbb bf hlkaeabdfegfgfhohqqng bc hjnacbeddgfggaafnjswf b honaabbfegefghgxaxbkf b hlkacabdffgggfhoqkbcc bd honaabdffefggebpidwbk bk hdhabbdfeefgghgimukof b hlkaeabdfegfgfhohqqff bc hlkaeabdfegfgfanaqhnf b hfpaaedceffggvnfvmmfg b hkpaaccgfegfgkopdnuen b hdlaiccdeefggecbatkhf bd hbpaieddeefggwvrgkhqf b hkoacacdefgggfkakoiqi bf hhkaeabdfegfgfhbqhanb b hhkaiabdfeeggfhbxhfqn b hlkaeabdfegfgfhoqqabk bc hcpaeccdfffggbrnxtmqf b hhkaiabdfeeggfhbqqbqo bt hgpaaegefffggslgilpii b hdhaicecffeggaeklpuxo bg hnkaiabdfeeggfhvqqbqf b henajbdceefggmcgmdnqk b hpjaabafgeefgafqxxbob b hhkaiabdfeeggfhfhhkab b hpkaaabfefgggfaqttvkb bc hhjaiabffeeggnamitlxf b hnkaiabdfeeggfhghxghf b hnfabbcdffgggaaanrpuu bc hnkaeabdfegfgfhvqqakf b hooaaadeffgggnadnkbjg b hlkaiabdfeeggfhoqqkak b honaabbfegffghghhxbgf bc hnlaaacffggfgknwrcfvo c hjnacbdeegfgglkptqcbg be hpdaabcffggfgqqwrcnvo c hpfaabcegefggaabogoks bc hhkaiabdfeeggfhbqhfak b hcnakadeedfggfeplhdab bp hhjaebadfegfgafgqahoo b hhjabbaefegggafpdajkn bc hbnakaeeddfggbdidahab b hhkaiabdfeeggfhfqxgaf b hcpaebfcdfgfgfhffhahb b hdpaafcggdegfaoqxnbxf b hmpaadcgefgfgknaspipw b hlkaeabdfegfgfanaxqng b hnkaeabdfegfgfhghhhff b hdlacadfegefgfhhahngk bm hbpaifefdfegghjhsxohg bc hljaiabefefggnapdailk bd hhjaeabdeffggnqfaasqf c hdlaiceceffgghtfuiupb b hghabcdcefgggqjghvnvb b hdoacafedfggggqphnxpq b hflabbeffggfgqqpixhkj b hhkaiabdfeeggfhbqqbak b hlkaeabdfegfgfanaqqnb b hdpaaedefggfgkoguxmxo b hjhaedcdfegggurgahhep bf hkhabbcefgggftnahhsjf b hdoacaedfgefgfxhhqffb b hpkaaabgfeefgfhxxhkof b hhkaiabdfeeggfhfqhkqg b hhkaiabdfeeggfhfhxgab bx hjnabbedeggfghhshafoo bcc hcpaibcfdffggfoxoxxqk b hnkaeabdfegfgfhgqxqbb b hhkaeabdfegfgfhbxhaob b hhkababdefgggnhfhnvgb bc hdhabbedgfffgqxbqqsgb bc hjnaeaceeffggnjarggqf bd hbhaddeceggfghenphcnf bc hhkaeabdfegfgfhbqqanf b hjpaaecfdefggbrpggawf bf hdnaeaefddgggbqqqgqha bi hipacbeedgfggnnkcqhck bce hlhaadcfeefgganaaxnkk bee hjlabbedfefggqqbqargb bcc hhkacabdfggfgfakabgfs b hnkaeabdfegfgfhvqqqkg bd hcnakadeedfggnmuqpaab b hdgadacdegggfnfmxthok b hlkaiabdfeeggfhohxohf be hepaedcdefgfgsssoqhfg c hlfabacdgfgfgnbaakdnl b hcpaecdedffggbvsoxmnb b hepabdcfefgggojqwdahv bc hepabbdcfgffgffklmtlk b hhfacaceffgggnjqbkdmq bl hepabceceffggbgkcppbn b hcpaedcfefeggjoqolnoo b hljababdggffggqntjcjk bd hlkaiabdfeeggfhohqkhf b hnnaaacdgffggnkbrfjkn bc hllaabegfeefgplahdpfb bp hkpaabfffeggggheqcema b hhkaiabdfeeggfhfqxgqg b hhoaaaedfgeggohqsofov b hepaicdefffggnovdpihk b hlkaeabdfegfgfhoqqqbg b hdnaibefeedggmxtudghg bd hdhaeddedfgfgakxkxafb b hhjaebbdefgfgtuaknakf c hpjaabafgeefgafqaakgf be hdhaibfcffeggtikxedhg bc hcpabccefgfggbcsphmqs bc hfnacaceeffggnkhrrgho bce hpjaabafgeefgafqaafgf b hnkaeabdfegfgfhghxqfb b hnkaiabdfeeggfhvxqbqb bk hgpaaeegfdfggkkxxfaxk b hbpaieddcefggccnfcqhg c hhkaeabdfegfgfhbqhhno b hhkaeabdfegfgfhbxqaof b hdjadabdegfggnakifnvj bc hnkaeabdfegfgfhgqhabn b hcpaeedcdfgggvvbkxhcn bc hdnaeafeddgfgghhxghfg bf hffajacdeefggggltgmqo c hgnacbbdfgggfaboxwfnf c hdnabafeegggfgxhrbcbf b hkhabbddefgfguccxckgb b hdlabcdcffggghffarcwb b hlkaiabdfeeggfhoqxoqg b hhhaabefegfgghehxpesc b hdpaafgfegfgeaaeoxthn b hhkaeabdfegfgfhbxhhoo b hnhaabdgfffggqbhhqwrb bc hnhaabedggffghhkxusjk bd hlkaeabdfegfgfhohxhff be hnkaeabdfegfgfhgqxhbf b hlkaiabdfeeggfhohqkan b hdoaiaefddeggkqqqfgqb bc hhdabbcdefgggqeefrdml b hnfaibcdfefggaaannban bc hlhaabfdgffegiqbqdbbb bc hnkaeabdfegfgfhghxhff b hhnaabdefgggflsmhiwvn bc hdhaibcfffegguktxedan bd hkpaadffgfggecuaulieg b hnfaibcdfefggaaannbqg b hhlaacfgegfgfqpapllgk bc hcpabcdegfgfgnknahqhc bc hfhabdcegffggafxdmoff b hbhaddccegfggafoxvvbg b hhhaadfegegfghillhejg c hcnajbddeefggpowmtfqb bc hknacbbdeeggghgkxknor c hcpabbcffgfegggxxqxgn b hknaibbdfefgghfkqqcqn c hlkaiabefefggfhilppdn be hnhaadcfgeggfhrammfok b hnkababdgffgggqbdsrgs bc hhnaabeffeegghulmhxff c hbpaeecfdegfgjohsvqgf b hlkaiabdfeeggfhohxoan b hdpaacefdggfgbgufaxxg b hglabbcegefggqohaqjnk b hhkaiabdfeeggfhfqhkak b hboafacedfgfgfohaqqgb bd hlkaeabdfegfgfhoqxhbf b hcpabbcffgfegfgxxqxfn bf hpjaaabgegffgnqtddjob bf hboakadeedfggklqdeahg bd hdfakbcedefggaaqqbahg bc hnkababdegfggfhgxbgcv bc hbnakaededfggnteeaehg bc hlkaeabdfegfgfhohqafk b hcoafacdefgfgfkxaaank b hfpaafeddfgfgdsrkiquk b hhfabacegefggbbqagbax bcc hboafaedefgfgktuurmgk b hdnabbefegfggpidluaob b hdfakbcedefggaaqqbqhk b hknabbcdeffgglwcdkwnf b hmpaaecfedfggwchbnuvk bf hlkaiabdfeeggfhoqxoak b hkpaaeegfffegvkqtxebg bc hmlaebdcfegfgannqqhfk bc hjpaafefgdeggqoiuootw bh hcpacbfcegfggfhfjmqmb b hpkaaabgfeefgfhxqxgng b hcpaieddfffggojrleiqb bc hbhajdcedefggafegdfan bc hkoaiacdeffggfkavvrao bk hapajcdeedfggjojjoqhg c hdnaiafeddegggqqqbbak b hhkaiabdfeeggfhfqxgak b hfpaafggdefegilukvxfk bd hlkaeabdfegfgfhoqxqbb b hdpaafcggdegfqoqxnkxo b hlkaeabdfegfgfhohxqfb b hdnacbefeegfgexitmaff b hbnakaededfggfimqheaf bj hlkababdegfggfanxknsj bc hghabcdfegeggabuqtovb b hdpaafcggdegfaoqxnkxf b hclafcddefggghfbhxaax b hglaibbeffeggaklqdeaf be hdnaebfddefgghxonhbhk bf hhkaeabdfegfgfhbqhann bc hpjaabafgeefgafqqafof bc hkoaeaceeffggknqfgjqg bc hdhaibfcffegguikxmdho b honaaacgffefgforornkb b hdoacaedfgefgnxhhhkgf bc hnlaacdggegffqjqqqjfg be hkpaadegdfggfnkakaaxf bu hkoaeacdfegggfkannaqh bi hdlaecdfedfggtkatkrtk bcc hcpacefcdegggkhoggtbw b hcpaebcfdffggnbxfaxqg b hbpabddeegfggngkgdprg b hhkaiabfefeggfhimqhtn b hhkaiabdfeeggfhfhhkan b hlkaeabdfegfgfhohqqfg bh hhnaabddgffgghkohgojs bd hhnaabdfgefgghkhhxgjs b hglaibbefefggqfudttdk b hhkaeabdfegfgfhbxhaon bc hpdaacbegefgghhncovkn b hdoaiaedfdeggfaxxfbhg b hdpaacgfdegfgvieogttj bc hgpaaecegfgfgvoohpidj b hhkaeabdfegfgfhbqqqng b hpkaaabgfeefgfhqqhfnk b hbpaecefdegggcfhcchfo b hpjaaabfegefgbahxafob b hohaabdeeffggtnixeowf b hdlaeadfedgfgfhhagqgo b hdlacadfegefgfahaabff bp hpjaabafgeefgafqaafof bc hkpaadcfgfgfgcvatampi c hnoaaacgfgffggfgsbcvj c hdfakbcedefggaaqqbaan b hdlaeadfedgfgfhhagqfo b hapadcbedfgggnfnnxxnk b hgpaadceegggfrocvaebb b hkpaadedgfeggnknqxbck bc hhhaabgdfeegguqkxmgfj bk hapaddcdeggfgknwciafs bf hhfabbceffgggaahjwhaa b hgpaaccfgffeggoxetdgb b hghabbdffefggtnldmbkk b hglabbddfggfgdfohrsrg b hjpaaecfegeggnraneows bp hpjaaabgfeefgnqxqhknf b hbpaicefdeeggfnakfoqf b hmhaedccfefgghokipkxf b hepaiddcfffggofgxxxqk bf hdpaaecdfegggkoflfiob b hkhacddeeffggurheqowf b hdkafabdeffggfanmtnmo c hjhaiccdfffggqfkeuwho bce hnjaiabdfefgggqbhhrhb cc hbpabcffegegggainmopr b hknaibbdfefgghgkqqchb c hooaaacgffgegnkksoggk bc hdnabbefffegghapdqdkf b hhdabbcefefggqqhkfoab b hdlaeadfedgfgkahabqfo b hhkaeabdfegggfhfhhaqh bc hfpaaeedfdfggvkntnpbb bc hdhacbfdfgefgixkihogg c hnoaaacgdgfgfofgfwnfb b hnjabbadffgggafbqbnkg bc hdlaeadfedgfgkahabaff b hfpaabfgfdfegfhhanhff bd hmhaiddceefgganftmoho bc hpkaaabgfeefgfhhqhkbn b hhkaeabdfegfgfhbqqank bc hhfaiacdfefggfghoovhn b hbpabecfgeffgboxqoxxb bc hdnaeadedfgggneedohit b hdkafabedffgggqlkiklf c hdnabafeggegffhqgosof b hlhaacdffgeggtvexakwr b hdlaiceefdeggdtxdklaf bf hdhaedcdfffgghnotdghk bg hpkaaabgfeefgfhqqhfbk b hhjababdeegggnanxkwko c hjhabbcefggfglfeaqfro b hhfaibbdefeggdilfokqn c hdlacadfegefgfhhahbgk bg hfnacaddefgfgntllftfg b hdgadacdegfggkbqqulvo bv hkoacacdefgggfkacgueu bd hgoaeaceeffggfkhvrkab bd hfpaadgeffegggunmhgpv bcc hdlacbeedfggguxufufkr cc hldaicbdeffgghhqbgrhb bcc holaabbfgeefgakxqafnf bd hfhacbefdggfghhqklsrn bd hdnaibeeddfggtxtgbfhk c hgnaibbeffegghfueuuen b hkoaiacdeffggfkavvrhk bk hdhaibffdfeggtipkxuqf bc hglabbddfgfggqsnufgnf bh hnlaabdgegfgflnitegbf bl hdhacbfeegefglpelhafg b hnkaeabdfegggfhvqqqah b hpkaaabgfeefgfhhqhfbn b hhnaaaeddfggggqhksogo b hhhaabedfgggfpiwueorf b hdnacbefeegfgextumqnf b hdnabbfedegfgpxpkunng b hdlacadfegefgfxxhaonb bc hflaccdfdfgggqolgbfkk b hnlaacdefgggfqbeqlwjb bs hepaccceeffggoknsitko bg hdlaccdcfgggfhbkqgvfb c hldabcbdgfffgqqhqnorb c hjpaadcgdfffgosqolhig c hdlacadfegefgfahaabgf bd hooaaacdfgfggnkgswkgk b hhkaeabdfegggfhbqqahq b hnjabbadfggfgafbakngw bc hdnaeaefddgfgnaaakhfg b hdnaeaefddgggnqqqoqha bf hhjaeabffegggbqullgbs bc hdlaeadfedgfgkhhagqfo b hljacabdegfggnakxnkwr bc hhkaeabdeffgggqkhhvqk c hnkababdefgggfhghbrcv bc hcpaeeffedgfgkhpbghlk b hchafbdedffgglbpghwmk b hdnacadeefgfgguiufigf bc hhjacbadfggfghkfhgbfo bc hglaccdcfgfgghvkqogfb bf hdlacadfegefgfxhhagfb b hdlaeadfedgfgkhxagqno bc hhjacabdfgggfghoxwfnk c hfoacadedgffgkldexvnb b hpjaaabgfggffghddikgr bc hdhaecdffegfgqkahaknf bc hhkaeabfefgggfhimqgbc bce hhhaadegfdefghhxaognn b hjpaaefdfegggbunmkxxw b hljababdfgggfghwxwfnf c hhkababdefgggfhfhnvgb b hdnaibcdeefggdogxdnqo c hkoabacdgfgfgfwaaftri b hhdabbcefefggqqhkfohg b hgoaeaceeffggfkhvrkak bd hkhacccefefggufhetcfg be hcpaideeedfggbkbgkahf b hpjaaabfegefgnahxafgb b hlhaacddggffgmjbmwnkw b hapajcdeedfggjojjoqhf cc hcpaibcfdffggfgxgxxqk b hlkababdefgggfanqkcjs bc hbpabfddegffgqfgfhahf bc hdpaacefdggfgbgxfaxxg b hdlaeadfedgfgkhxaganf bc hnfaebbdfegfgdiposagf c hjhaicdeedfggdodxobqb cc hdhaecdefefggeviimrcf b hgoabaceffgggfkhropth b hdlacadfegefgfxhxhfgg b hmpaadbdeffggofvohufn b hdlaeadfedgfgkhhagqgo b hfhabcdceegggankakkjg c hfnaebedffggghhkuavcn b hjhacdecegfgghenphwcv bj hcnafbbdeffgghfkitrab c hdlacadfegefgfxhxaffb b hdlacadfegefgfahaangf bd hipaeedcffgfgonfdxieg b hhgabaceeffggnfhcnnxf b hpkaaabgfeefgfhxxxggg b hflaiccdfeegghfoqqkak b hlkababeefgggfhdppscv bc hjpaacffgdgeggamqnxfv b hhdabcbdfgfggqqdsmsui b hhgaeacefefggbbakojxk bg hbpabeffdegggvmxbkeej bc hpdaabcfgefggaagwbwbg be hkpaaceefggfgogbxmeuw bd hdpaaedgfegfgjjhxkumo b hflaccdffgeggqolulkjw bc hdoaiaefddeggkaaxbnhf bc hlkaeabdeffggfanhhcqf c hdlaeadfedgfgkxxakaff bd hlkababdegfgggqnajfbg bd hipaebeedffggbnkcmhkf bc hglaicbeeefggiglpluho bd hgnaibbeffegghfthuueb b hmpaabedfggfgbjkeeamk b hpkaaabgfeefgfhqqhknk b hipabebdgeggfkkodctbn b hflaecedfegggimkduvfg b hjnaiacefffggfbxgvfqb c hdlacadfegefgfxhxafgb b hnhaacdfggfegermmeffr c hpkaaabgfeefgfhxxxoof be hboafacedffggofphlpof b hpkaaabgfeefgfhhqhknn b hipaibeeffeggbnklarnb bc hdhaeddedfgfgakxkahbg bf hffafbcdefgggaaaqhhbw bw hffafbcdefgggaaaqhhgr bs hipacbeedffggbnkcdhnb b hfpaaeegfdgfgnfxtnhmn bc hglabbbdegfggqggqsfkn b hpkaaabgfeefgkqxxhfgg bc hpjaaabfegggfbahxxnkg b hdnacbefeegfgexiumqfg bm hpjaaabfegefgbahxxkgf b hbpaicfdffegggafmisqg b hmhabdccgffggakfawoww b hglaccddfgfggdsbhfgoc b hfpaaedfdggfgvnmwutdb bd hdpaaddeffgggjvgmtxev b hdpaafgcgdegfqafxbbxg b hdpaafcggdegfaoqxnbxk br hdpaaedeffgggbgopmdar bc hpjaaabgegffgbqtddjob b hboakadedefggflhaetqg b hhhaacegdeffgtxpftkfb b hdlaiceceffggqtbuqupb bd hhhaadggefgffhuhxxhob b hkhaccdcffgggabwpnjnc bc hdkafabdeffggfhopuoik cc hboakadeedfggbpqdalhf bj hgnabbddefgfghfkdssnb b hknaiacefffggngqbnjqb c hnhaacdefgggfqgtxuwck b hkoabacdgffggnkaqnwmu bm hdpaacfdegggfohfgiiqo bm hpjaaabfgeefggqxxakbk b hhlaacgdffgegmufulrfg b hdlaeadfedgfgfahabqfo b hdnaiaeeffdggfiuifkib b hghaccdfdfeggabufbbso bc hpjaabafgeefgafqqakog bf hdlacadfegefgfhhahbfk bp hfoaeacdefgggnnagwhaq b hhjacbadfgfgghkfqgobj bc hpkaaabgfeefgfhxxhkgf b hpkaaabgfeggffhxxxfog bc hcpabcdcggffggwohteqs b hdnaibefeedggmxtudgan bc hfpaadgefgfegflbpddkk b hdnaebedffgggtmwdmrok c hapadddcefgggorccxaor c hflabcddgegfgivkhonfv bq hjpaacfggfeegstuxtgkw c hfpaadegdfgfggjagqlqj b hcladccedfgggmfecggjw b hcoafacdeffggfkapplwk bc hpfaaacfggegfnbsbfncn b hcpaibcfdffggnkxoqqqk b hcoadacdefgggnkaapigk bc hlfaebbdefgfgdidooqfb c hcpaeccffefggknxxkxhg b hlkababdefgggfhoqfjcv bc hdoacadffgfggniidhfep b hdnaeaefddgfgnxqxbqgg b hdlacadfegefgfxhxhngg bf hdnaeaefddgfgnxqxbqfg b hdlacaffdggfgfthtqegi bk hnfabbcdfggfgaaakpufe bc hjhaidbeeefggiklpathf b hdlaeadfedgfgfhaagakf be hpkaaabgfeeggfhxxhkbg b hnfabbcdfgfgghhhoentu b hdnaeaefddgfgbqqqoqgb b hfpaadeggdffgosdlomus bd hgoabacdgffggoohagvud b hdnaiaefdffggbqqqfoqb b hpjaabafgeeggafqqakbg b hnfaebbdfegfgdilffhfg c hjlabbdeffgfgqbxqhwwf b hcoadacdefgggfkaapigk bc hdlacadfegefgfhhahngf bd hhlaabeffeggglehpaqwr b hnkababdffgggnabqbnkg bc hhkababdegfggfhbqvkof b hboakaeeddfggnehalpqb bd hpjaaabfegggfbahxxnko b hgpaaccgefgfggglgtqmb b hknaibbefefgghfpdailf b hglaccdcfgfgghvfqogfb b hhhaabfgffeegueqxmdfb bc hdlaeadfedgfgfahabaff b hglabbdegffggisdllbsf b hpkaaabgfeeggfhxxxobg b hhnaabedgffggaabairkj b hdlaeadfedgfgfhhagagf b hcpacccdeffgggvfjphgn b hhhaabedfgffghmcmqkob b hlkacabdfgfggfhohgobf bc hpjaabafgeefgafqqafog b hjoaiacefffggfoxwfnhg c hpjaabafgeefgafqaakof b hdnaeaefddgfgnxqxkafk b hdpaafcggdegfqoqxnkxg b hgpaaceefgffggfoxeudb b hfhacdcffggfgafehqoof bt hjlaecdedfgggenabpaei bl honaabbfegefgabxaabkb b hpjaabafgeefgafqqafgf b hbhadbcdefgfghogisobo b hpjaabafgeefgafqaafon b hgnacacdegfgggohoukua bp hmnaebdceffggebwmdkab bj hfhacbcffefggukqexwco bg hpkaaabgfeefgfhxxxggf b hcpabdcegefggnokhohjs b hcpaeeeddfgggfbobhhsj bd hdpaadfeggegfkanxxnxk be hhdabbcefefggqqhkfoan b hhhaabedgfgfgudsqpbko bc hpfaaacdfgffgbbgfvbok b hdnabbefdegfgexifunff b hdlaeadfedgfgkahabagf b hghabdcfeggfghohxhkgw b hdlacadfegefgfxhhaggb b hgnacaddefggggippcute b hcpaeecefegfgwwwhbqng c hdlacadfegffgfxhhabgb bc hdoaiaedfdeggfhaangqf b hghabcdcfgggfabkxsngb c hdlaeadfedgfgkhhagagf b hpjaabafgeefgafqaafgn b hfhabdcedfgggafanfsnk bc hgnabacdggffgnnahlngl b hdlacadfegefgfaxaabnf b hdlacadfegefgfxhxanfb bt hdnacaefdgefgbaxxankf b hdfajacedefggnbhhrahf c hpjaabafgeggfafqaankg b hhlaacfdeefgghefahkvf b hpkaaabfegefgkahxxfon b hdlaeadfedgfgkahabqfg b hpkaaabgfeefgfhxqqbng b hjpaafdggegefhfemflfk c hdlaeadfedgfgkahabafk bt hjhaicdeedfggdfdxngqo c hpkaaabgfeffgfhxhhnkf b hpgaaaceffgggkbsnjbns c hdlaeadfedgfgkhaagakf bc hhdabbcdeffggqqmfgvhf b hdoaiaedfdeggfhaabgqf b hdlaeadfedgfgkahakqfo b hlkacabdfggfgfhoqgbfs bc hhdabbcefefggqqhkfohf be hcpabdefdfeggcnpbuncg b hbladacdegfggfnxhuunk b hfjafabdeffggghfdurho c hnfabbcdfgfgghhhfmwui b hpkaaabgfeefgfhxqxong b hnlaabdgegfgfpfihekkb b hpkaaabgfeefgfhxxxoog b hhfaibbeeffggdilsnrpg c hpkaaabgfeefgfhqqhfbb b hdlaccecefgggqtbuukof b hgoabaddggffgoidgwgvf b hpjaaabfegefgbahxhkgg b hhnaabgfeffegpaampubn b hdoaiaedfdeggfhaaboqf b hhjababdeegggnaoanwko c hdhaeddedfgfgakhkxhff b hldaebcdfegggqqhffahq bc hpkaaabgfeefgfhhqhfbf b hpkaaabgfeggffhxqxfon bc hpkaaabgfeefgfhhqxobn b hdhabcefggefgamehxagj bc hdlaeadfedgfgfhhaoqfo bk hdlabcdfgefgghkuuhgfk b hdlaeadfedgfgkhhaoqfo bl hpkaaabgfeefgfhxhhknf b hcoadacdegfggfkaaqqbg b hpjaabafgeefgafqqxbof b hfkafabdeffggkafduran c hfnacbcfefgfgmgqpqggg b hohaadcgegffgibatpnoo b hklaccdeegfgghrulajfs bd hlnaabdefgfggdjedxosj bc hfpaacddfggfggobuplmo bc hlkababdfgggfohkhwfnf c hknacbdeffgggebpqqgbo b hdpaadfeggegfkhnxxnxo b hdlaeadfedgfgfhhagqgg bl hdlaeadfedgfgkhhagaff br hdhaibcfeffgglbeatlhf bd hnoaaacggffeggfwbfkno bc hipabedcgffggrkbtxmhk b hbpabddfefgfggkxkxaxf b hdlacadfegefgfahaabfk bd hdlacadfegefgfxhxangb b hdlacadfegefgfhhahbgf bd hhdabbcefefggqqhffohf bcc hfpaafgfefggehqqohipn bd hcoadacdegfggnkaheekn b hdoaiaedfdeggfhahboqk b hlhaabefdeggguxefuojf b hdlaeadfedgfgfhhagaff b hpkaaabgfeefgfhqxhkob bg hdpaafgcgdegfqakxbbxg b hlfabacdgfffgnbahkjgf c hhfabaceffgggbnxbjipx bc hdpaaddfefegggjeodfkf bd hfhabbcefgfgglfdxuojn bdg hfhabbcefggfglfdxusfn bc hdlacadfegefgfaxaannf b hdhaidefedfgghaaqwxhf b hcpaedcdfegggnonubawb bg hlhaadeegfeggimhhqtkv bc hdhabbdfeefggtwuxuskb c hpdaabceefgggaafovcfo b hpdaabcefegggaancovno bd hdlaiadfeffggfhhafoqo bcc hdnaiaefddeggbaxqgfak bg hfjafabdeffggnafdurho c hlfaebbdefgfgdihfohgo c hndaibbdfeeggemlgggqb c hdhabbedgfffgqxbqqsgk b hcpacdfcdggfgoagfphur b hpkaaabgfeggffhxqxfob bc hdlaeadfedgfgfahabagf b hkpaabfedfgggnaffaetj b hpjaabafgeefgafqaakon bf hdpaacfggeegfnaxxknxk be hdlaeadfedgfgkahabqgo b hdlaeadfedgfgfaxabanf be hdlaeadfedgfgkahakaff b hbpabddfgfggfnkxaxqhx bo hbpabddfgfggfvcxaxaxx c hcpabbcffgfggfoxxqxha bk hdlaeadfedgfgfahakqfo bf hdpaaeggdgfefkipkxmbg bc hpkaaabfgeefggqqxafgk b hloaaaedgfeggkqxknosj b hcoadacdefgggnkahahkg bc hdlaeadfedgfgfhhagqfg b hffajacdeefggfgltglan c hbpabcedffgfgrnriupln be hdhaiddedfeggakakabaf b hdlaeadfedgfgkaxabanf bc hdlaeadfedgfgkaxabqfo b hfpaaefgdeggfohafwmmg c hjpaafdcfgggfmwfahtad bc hfnacbcdffgfgmvfasbkk b hcpaccefdfgggfkdspips bc hjhabddcgffggevwtwjcj b hpgaaacdffgggkbnvbfsb bce hpkaaabgfeefgfhqqhfnb b hbpabdccgfgfgofkqlhdj b hklabacdgfffgkfhqnorb c hpkaaabgfeefgfhqqhknb bc hpjaabafgeefgafqqafgg b hdlaeadfedgfgfhhaoqgo b hpkaaabgfeefgfhhqqbbn b hpkaaabgfeefgfhhqhknf b hhdabbcefefggqqhffohg bc hpkaaabgfeefgfhhqxobf b hdlaiadfeeeggfahankqk bc hfoaeacdfefgggfqggcqb b hcpabecdgefggvochohfo b hdjafabdeffggnakitran c hpkaaabgfeffgfhxqqnkg b hdhaeddedfgfgakxkahbo b hdnaebddfefggafwddkak bc hddafbcedegggqqaafovb c hpkaaabgfeefgfhhqxonf b hfpaafeeffgggdknaiuit b hfpaacfgeeggffaxfohhk b hpjaabafgeggfafqaanko b hkoaeacdfegggnkannatp bl hbpacefeddgggnaknnasj b hdpaafdeegffgtconqiuo b hdlaeadfedgfgkhhagqgg bn hbpacfdcfegggejohodhc b hpkaaabgfeefgfhhqhkbf b hdlaeadfedgfgkhhagqfg b hpkaaabgfeefgfhxqqkng bc hpkaaabgfeefgfhhqxonn b hdlacadfegefgfxhxhfgo b hknabbdeffgfghfxhqssk b hpjaabafgeeggafqqafbg b hpkaaabgfeeggfhqqhfgb b hdlacadfegefgfxhxafgn bw hpkaaabgfeefgfhqxhfob bd hdpaaccfgefggffidglan be hepabdefgfgfgwntatxia b hnhaadecfggfgimfutoks b hpjaabafgeefgafqqxbog b hhhaabegffgfgtipxelos bc hipaeddefdgggngkqkagr bf hjlaebddfeggglgfamaet bn hdpaacfggeegfnhxxknxo b hfpaafggedefgilunocak b hpkaaabgfeggffhhqhofb bc hjpaaceggffegcnqiatnw be hdlaeadfedgfgfahabqgo b hdhabdcfeggfguotetfcc b hpkaaabgfeefgfhhqhfnn b hpkaaabgfeefgfhqqhkbk b hhnaabddgffgghknxgbss bd hhnaabdfgefgghklxdgss b hfhaccefdegggmiegdnwn b hlhaabdfegffghchxqwon b hbpacedffgeggvglqdbig b hdlacadfegefgfxhxaffn b hdlaeadfedgfgkhhaoqgo b hbpabdeedfggggkvkqacb bd hpkaaabgfeefgfhhqqbbf b hfhabdecfggfgieguigoj bi hgpaaedfgeeggsjhhongb bcc hbpaeefedegggnqkngqof c hblafcdedfggginqkahml bi hbpabccfgfggfcvxaxaxx c hbpabccfgfggfcvxhqhxq bc hbpabccfgfggffoxhxqax bg hcpabdcegefggnokxoxsj bd honaabcegefgghjahpsko bdd hdpaacfggefgfnaxxkqxh bcc hdpaacfggefgfnxhakxqx bcc hpdaabceegfggaafkrrfk ce hpdaabceegfggaaforrfw be hdhaccedegfggddnxqnjf cc hpdaabceggffgaaforwrf be hlnaabfeeefggdppxdpsb ce hlhaacegeffggaaaemxvf c hllaabegefeggdaapqijo c hdnaebeefegggtxtdmhvk cc hpdaabcgfggffaafcnvof bg hpdaabcgfggffaafcrvor d hpdaabcgfggffaancrvwr bm hfnabacdgfgfggbqaoacq b hpkaaabgfeefgfhhxhkgn b hbhafcddeffggqgjxqbxg bc hbpabcecffgggckgatipk b hdlaeadfedgfgfahabqfg b hdnaebddfefggafwddkaf b hpkaaabgfeefgfhhqxgbf b hpkaaabgfeefgfhhxhkon b hdlaeadfedgfgfaxakanf b hfpaacdfefgfgrodkdxuf bd hdlaeadfedgfgfahabafk bx hlnaabdfegeggmvadqngs b hdlaeadfedgfgfhhagafk b hcoadacdegfggfkaheekn b hcpabbcffgfggggxxqxha bi hcpacccffggfggbxxqaxh be hdhaedfefegggauxhqarb bd hffafbcdefgggaaqqhqbw bu hffafbcdefgggaaqqhqrg by hnlaaacgffgfgknvcvfco bd hkoabacdfggfgfktjatrp b hdlaeadfedgfgkhhagafk b hcpabecdgeffgvochoqbf b hfnacbcfeegggewhlqbvn b hpkaaabgfeefgfhqqxgnk b hpkaaabgfeefgfhqqxonk b hdlacadfegefgfxhxhffo be hdlaeadfedgfgkhhaoaff b hkhabdccefgggdkodcsbg b hnlaaccgfffggdkdtajfr b hipabecefegfgfjbhsabf bc hdnaebddfegggafwddqha b hpdaabceefgggaafwsjfw bf hpdaabcefegggaawcnvwn bp hcoadacdefgggfkahahkg bc hkpaaefcgdgfgkhkabalf bc hdlaeadfedgfgfaxabqno be hbpabbdfggefgfjquqfxf bf hdhaeccdfegfgankaaanb bc hcpabbcffgfggfgxxqxha b hdlaeadfedgfgkahakagf bz hdlaeadfedgfgfahakaff b hdlaeadfedgfgkhhaoagf bf hbpacefeddgggnaknbasj be hgnaeacdfeggggohffqud bq hhdaccbeffgggqqhwnieh b hfpaacggdffegcuhnqagv b hipaeecdfffggvkvqetag b hdnabbfdgeggfpqcqesng b hdhabdcefgegghraxhkko b hdlaeadfedgfgfhhaoagf b hchafbdedffgglbpghwlk bf hpkaaabgfeefgfhhxhkgf b hdlacadfegefgfhhxhffk bf hdnaebddfefggafwddgaf b hflacbcffgfggioqmhwjs b hjpaaceggffegcnqiatfw b hdlaeadfedgfgkaxabqno bc hdlacadfegefgfxhxhngo b hdpaafgdgfeegaafhifnn bd hdpaaegddegfgbmkgwtkk b hpkaaabgfeefgfhxxqbog b hpkaaabgfeefgfhxhxgff b hdpaacdgfefggngumkaar cc hhdabbceeffggqqhkncan bcc hkhaeddcffggghbnlidid cc hfhabbcdeffgglfsmfcjk b hdlaeadfedgfgkahabagk b hhdabbceeffggqqhkncxf bc hdlaiadfeeeggfahankhk bc hdpaadecfegggwfkhkqjg b hdhaiddedfeggakakabqo bf hdlaeadfedgfgkahakqgo b hfpaafcegegfgebbtgpqg b hpkaaabgfeefgfhqqxonb b hepaedcefegfgnrkhwhfo bd hglabccdgfgfgmffqngor bd hdlaeadfedgfgfhhaoaff bc hpjaabafgeefgafqqxbgf b hlhaadceefgggtopmdwof b hdlaeadfedgfgkahakqfg b hdpaaefdgeeggjxsxonsj b hpkaaabgfeefgfhhxhkof b hpkaaabgfeefgfhxxqkog bc hdlaeadfedgfgfahakagf bA hfnacbeddgfggaaonsjfr b hdlaiadfeffggfhhafoaf bcc hpkaaabgfeefgfhhqhfnf b hdlaeadfedgfgfahakqgo bc hbpabeffdfgggvqxchhah bc hgpaaegggefffopdhbdli c hgpaacdegffggfffqaddk b hdhabbedgfffgqxbxqsgf b hdlaeadfedgfgkahabqgg b hpkaaabgfeefgfhqqhkbb bc hdfadbcedgffgaaqqxqgb bc helafcddeffgghgbaqnqf b hdlaeadfedgfgkahakafk b hdhabbefegfggqxpeuqkb bd hfnabbdefffgglntieknf be hooaaacffgggffkofvvcc bd hpkaaabgfeefgfhqqxgnb b hfhacbcffefggucqiuwnf bc hpkaaabgfeggffhhqhofn bc hdlacbedegfggqlnphfgw bc hpkaaabgfeeggfhqqhkgb b hgpaacddefgggbjffxeon b hhfaibbfefeggditbkktf c hhlaacgdfgffgetbldobf bs hfhacbcefggfglfditwfv bc hbpabeedffgfgbfgmmqhn b hjlacbdedgfggpglbnwvc b hdlaeadfedgfgkhhaoqfg bc hdhaeccdfegfgankaahng bc hdlaeadfedgfgkaxakqno b hmlacccdfffggmfjlfvsf b hdlacadfegeggfhhahnaq b hdhabdfeggefguiahiqfv bd hddadbcdefgggqqhhiegv b hlhaabdfegffghgqaqnkb b hjhaidccfefggafohqwxf b hdlacadfegggffxhxaqhg b hdhacdffdegggitqfiwns bf hchafcddefgggqnkahhhx bc hfpaadeggfefgokdlxkuf b hdlaeadfedgfgfhhaoqfg b hdlaeadfedgfgfahabagk b hdhaccfdefgggudoxxogn b hdlaeadfedgfgkaxabank b hpdaabceegfggaanwbbwn b hbpaicffeefggctpnjatf b hdnabafegggefgqhgvffk c hflacaceffgggknhwrluh b hjhabbcefeggghrdeuswf b hdlaiadfeffggfhhafoqg bc hpkaaabgfeefgfhhxhfgn b hcpabecdgefggfropweno b hpkaaabgfeefgfhhqqknf b hdhaiddedfeggakakabak bc hdlaiadfeeeggfahankqb b hdlaeadfedgfgfahabqgg b hpkaaabgfeefgfhqhhkfk b hdlaeadfedgfgfahakqfg b hjhabdecgfgfgahbteosw b hfnabbceeffggejtmqssk b hhdabbceeffggqqhkncab bc hghacbdeffgggtnpqesjs b hgpaadegffgfgcvaxxaxx c hgpaadegfgfgfofxhxaxq bg hhdacbceegfggqqhjajqh bc hdhaebfdfefggixsihsog c hnlaaacffegggfnwrvfoc c hgpaaegdfdfggctndbqhn bd hmpaabedgfgfgbnwppxpf bp hlfaibbdfefggdidjjchb d hlnaabfeeefggdppxdpsk cf hnlaaacfgfgfgfnwnrfno c hgpaacceggffgbbwepitw bd hpfaaacfgegfgnbsjokjo bd hpkaaabgfeefgfhqqxobb b hpkaaabgfeefgfhqqxobk b hdnaebddfefggafwddgak bo hpkaaabgfeefgfhqhhkfb bc hcpabdecgffggrooautqf b hlhaabffgegfgixiidabs c hdpaagddgfffghobalhde bd hlhaadffefggghduailws bd hdlacbeeffggguxuitikc cd hflaebcffefggioqmhwsn b hdhaccdfegfggqkmplnws b hfpaadeggdffgosdlgmus bd hnlaaacfefgggfnwnrgbk bd hpkaaabgfeefgfhhqqbnn b hpkaaabgfeeggfhqqxogb b hdlaeadfedgfgfahakafk b hfhaebcffefggucqiawkk b hpkaaabgfeefgfhhqqknn b hpkaaabgfeffgfhhqqnkf b hpkaaabgfeefgfhhqqbnf b hmpaaddeggffgnggpeapc b hflacbcffefggdsquiwoo bh hdnabafdegggffhajfcsn b hddadbcedfgfgaahhaabb bk hddadbcedgfggaaaaxxwr bc hpkaaabgfeffgfhhqqnkn bc hpkaaabgfeefgfhhxhfon b hjlabacdgffggknaafoqq b hhnaaafddfgggfahfjjgf b hflabbddefgfgqbnewgfg bf hdnaebddeffggafwtpsaf be hlfaibbeeffggdilnvghn c hmpaadcgdgffgknhnaluv bd hdoabaedgfeggfhannofo b hdlabadfdfgggfxhfbknr b hlhaadefggffgdupqedof b hpkaaabgfeggffhhxhofo bce hdhabbdfegfgghgxpmkro bc hjhaccecfgfggplvapwrs c hcladccedgfggmfaovvof bs hbpabefdefgggcujktdaw bc hkpaadffeggegsuuoutnw c hpkaaabgfeefgfhqqxgbk b hepaecefefeggkganlkkk bd hdlaeadfedgfgkahakagk b hflabbddefgfgqbnebbbb b hhnaaafddfggggaxojjgf b hdoabaeddgfggfhanoonk bc hpkaaabgfeefgfhhxhfof be hghacccdeegggqbgxnkjg c hdlacadfegggffahaahqf bc hdnaebddfefggafwddgqg b hdlaeadfedgfgkahakqgg b hdpaafedfdgggmnnendlb bc hghaeddefdfggtrppbnak b hjpaaefgdefggoudfwpew b hjpaaeddeffggbwnopuwk bc hchaddccefggghonhsjvf bd hdoabaeddegggfhabonor c hpkaaabgfeeggfhqqxggb bc hjhaidccfefggafohqwxn b hpkaaabgfeefgfhqqxgbb b hdhabdcfeggfgicpidwno c hflabbddefgfgqbnewgff b hfhacdcdffgggigflbvwk bg hepaeecffegggvfehfthw bk hhdabbceffgggqqhknhxx bc hflaeaceffgggfnxwrhqa b hnhaacddgfgfgmfgmwwrw c hlhaadddgfgfghffqckfc bo hepabedffdgggsolhopeo be hdlaeadfedgfgfahakagk bc hdlaeadfedgfgfahakqgg bc hpfaabbegfefgdifoskbf c hohaacdfgefggtcthunbo b hdhabbfdgeffgqtbqtsgb bc hdlabcddegggfdorqvbkn bc hapadcecdfgfgkjosaqfk bc hdlacadfegeggfhhahbaq b hgpaaegddfgfgvtgsiuef bd hdnacbffdefggmxeceswk c hpdaabceefgggaanwsjnw b hpdaabcfeegggaaronron b hcpacccdeffggfvfjdhrb b hooaaaceffgggfkvfojsc bd hbnadbcedgffghflkofko b hdoabaedgfeggfhanngfo b hloaaaefgggeffxawfnfk c hjlabacdgfgfgknhhflom b hldabbcdgfgfgqqhhnlom b hdlacadfegggffahaahqg b hddadbcedfgfgaahhaabk b hjpaadcgdffggosqophpc be hgoabaceffgggfkafohqx b holaacddgegfgevbtfrbb b hnlaaacffgfggfnwrkkvc bd hbnadbcedgffghflkffkf b hnlaaaceffgggknnjsfok bd hpdaabcfefgggaaogfjrg bd hkoabacdgffggfkhqfwmm b hlnaaaeddegggnaakfkjg c hnhaaccgfggffacethrgk bd hflabcddggefgivkhvffv bi hohaabddegfggtnchccof bcc hclafccdefgggmfktaaei bi hhfabbcfegfggahqntsap bq hpdaabceggffgaajorwrs be hpdaabcfgggffaanwrnkr be hlnaaafddgggfghhfovbn c hmpaadegefgfgonlrilmc c hdhacbdffeggghgilqcsk bd hpdaabceffgggaajrsgbj bd hgnabbddefgfghfkdfoff bf hkpaaefdfdgggcdnxbidc c hgoacaceffgggfkhormla b hdoabaeddgfggfhaboonk bc hdpaadfegeggfkhnxwitg bc hhhaadfegefgglxiiixvv b hmpaabefgfggfbnlplxxl c hhhaabfefegggppqlptwj c hddadbcedfgfgaahhaank bi hddadbcedfgggaahhaakn be hfdafbcdefgggaahhqqcv bC hfdafbcdefgggaahhqqnk by hnlaaacgffggfknkcvfok bd hpdaabcfgfgfgaaosfrsj bd hdnabbdfgefggafutlbgv bd hooaaacffegggfkofnjsk bd hcladbdeefgggdfxiascv bd hhhaadfgeefgghdhtltwn bd hfpaafcdgffggekkxeemx c hnhaadcggeffguklqqgkj b holaabcggeffgpnempgso b hflacaceffgggfnhwrluh b hdpaafgdgfegfaanddbei b hkoabacdgffggfkxawouu b hgoacaceffgggfkawodla b hflabbddefgfgqbnebbbk bc hdpaadfegeggfkhnxwito bcc hjlaebdeffgggpkletjcg cc hcpabccfeegggonhkohsj bd hcpaccdefegggoknhohsj b hhoaaafddgggfkqaksngf c hdhabbdegffgghglxlnck b hgoaeaceffgggfkhofeih b hooaaacgffggffknfovcn bd hkoabacdgffggfkhqnwmm b hbnadbcedgffghflkofkg b hbpabecdgffggbbohuxtb b hpjaabbegfefgtuckcggn c hbnadbcedgffghflkffkn bc hbnadbcedgfgghflkffnk b hgnabbddefgfghfkdfofg b hgoacaceffgggfkhonmla b hdnabafegggfffqqgvfgb c hdpaacgdfegfgnmwekiln bd hhhaadgeeeggfdxdxiibn c hghacccdeegggqbgqgkjg cc hnhaadcgfgffglgltxbgb c hdoabaefgggefkqqbskog c hpdaabceefgggaqfkssgo c hhoaaaeddegggoqxgbcfb c hpfaabbegfefgdifosfbg c hpfaabbegfefgdiosffkb cc regina-4.96/engine/data/snappea/verify-snappea-census-data.py000644 000765 000024 00000002120 12377774107 024137 0ustar00babstaff000000 000000 #!/usr/bin/regina-python --nolibs # # TODO: Document this. import sys if len(sys.argv) != 2: print "Usage: " + sys.argv[0] + " " sys.exit(1) tree = regina.readFileMagic(sys.argv[1]) if not tree: print "E: Could not open file " + sys.argv[1] + "." print print "Usage: " + sys.argv[0] + " " sys.exit(1) def process(tri): label = tri.getPacketLabel() print label section = label[0] index = int(label[1:]) manifold = regina.NSnapPeaCensusManifold(section, index) con = manifold.construct() hom = manifold.getHomologyH1() if con == None: print 'ERROR: No construction' sys.exit(1) elif not con.isIsomorphicTo(tri): print 'ERROR: Non-isomorphic triangulation' sys.exit(1) if hom == None: print 'ERROR: No homology' sys.exit(1) elif not hom == tri.getHomologyH1(): print 'ERROR: Non-isomorphic homology' sys.exit(1) p = tree while p != None: if p.getPacketType() == regina.NTriangulation.packetType: process(p) p = p.nextTreePacket() regina-4.96/engine/dim2/CMakeLists.txt000644 000765 000024 00000001345 12377774107 017472 0ustar00babstaff000000 000000 # dim2 # Files to compile SET ( FILES dim2boundarycomponent dim2component dim2edge dim2exampletriangulation dim2triangle dim2isomorphism dim2triangulation dim2vertex isomorphic nxmldim2trireader skeleton simplify ) # Prepend folder name FOREACH ( SOURCE_FILE ${FILES} ) SET ( SOURCES ${SOURCES} dim2/${SOURCE_FILE}) ENDFOREACH(SOURCE_FILE) SET( SOURCES ${SOURCES} PARENT_SCOPE) if (${REGINA_INSTALL_DEV}) INSTALL(FILES dim2boundarycomponent.h dim2component.h dim2edge.h dim2exampletriangulation.h dim2triangle.h dim2isomorphism.h dim2triangulation.h dim2vertex.h nxmldim2trireader.h DESTINATION ${INCLUDEDIR}/dim2 COMPONENT Development) endif (${REGINA_INSTALL_DEV}) regina-4.96/engine/dim2/dim2boundarycomponent.cpp000644 000765 000024 00000005521 12377776545 021770 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "dim2/dim2boundarycomponent.h" #include "dim2/dim2edge.h" namespace regina { void Dim2BoundaryComponent::writeTextLong(std::ostream& out) const { writeTextShort(out); out << std::endl; out << (edges_.size() == 1 ? "Edge:" : "Edges:") << std::endl; std::vector::const_iterator it; for (it = edges_.begin(); it != edges_.end(); ++it) { const Dim2EdgeEmbedding& emb((*it)->getEmbedding(0)); out << " " << emb.getTriangle()->markedIndex() << " (" << emb.getVertices().trunc2() << ')' << std::endl; } } } // namespace regina regina-4.96/engine/dim2/dim2boundarycomponent.h000644 000765 000024 00000015365 12377774670 021441 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #ifndef __DIM2BOUNDARYCOMPONENT_H #ifndef __DOXYGEN #define __DIM2BOUNDARYCOMPONENT_H #endif /*! \file dim2/dim2boundarycomponent.h * \brief Deals with boundary components of a 2-manifold triangulation. */ #include #include "regina-core.h" #include "shareableobject.h" #include "utilities/nmarkedvector.h" // NOTE: More #includes follow after the class declarations. namespace regina { class Dim2Component; class Dim2Edge; class Dim2Vertex; /** * \weakgroup dim2 * @{ */ /** * Represents a component of the boundary of a 2-manifold triangulation. * * Boundary components are highly temporary; once a triangulation * changes, all its boundary component objects will be deleted and new * ones will be created. */ class REGINA_API Dim2BoundaryComponent : public ShareableObject, public NMarkedElement { private: std::vector edges_; /**< List of edges in the component. */ std::vector vertices_; /**< List of vertices in the component. */ public: /** * Default destructor. */ virtual ~Dim2BoundaryComponent(); /** * Returns the index of this boundary component in the underlying * triangulation. This is identical to calling * getTriangulation()->boundaryComponentIndex(this). * * @return the index of this boundary component vertex. */ unsigned long index() const; /** * Returns the number of edges in this boundary component. * * @return the number of edges. */ unsigned long getNumberOfEdges() const; /** * Returns the number of vertices in this boundary component. * * @return the number of vertices. */ unsigned long getNumberOfVertices() const; /** * Returns the requested edge in this boundary component. * * The index of a Dim2Edge in the boundary component need * not be the index of the same edge in the entire * 2-manifold triangulation. * * @param index the index of the requested edge in the boundary * component. This should be between 0 and getNumberOfEdges()-1 * inclusive. * @return the requested edge. */ Dim2Edge* getEdge(unsigned long index) const; /** * Returns the requested vertex in this boundary component. * * The index of a Dim2Vertex in the boundary component need * not be the index of the same vertex in the entire * 2-manifold triangulation. * * @param index the index of the requested vertex in the boundary * component. This should be between 0 and getNumberOfVertices()-1 * inclusive. * @return the requested vertex. */ Dim2Vertex* getVertex(unsigned long index) const; /** * Returns the component of the triangulation to which this * boundary component belongs. * * @return the component containing this boundary component. */ Dim2Component* getComponent() const; void writeTextShort(std::ostream& out) const; void writeTextLong(std::ostream& out) const; private: /** * Default constructor. */ Dim2BoundaryComponent(); friend class Dim2Triangulation; /**< Allow access to private members. */ }; /*@}*/ } // namespace regina // Some more headers that are required for inline functions: #include "dim2/dim2vertex.h" namespace regina { // Inline functions for Dim2BoundaryComponent inline Dim2BoundaryComponent::Dim2BoundaryComponent() { } inline Dim2BoundaryComponent::~Dim2BoundaryComponent() { } inline unsigned long Dim2BoundaryComponent::index() const { return markedIndex(); } inline unsigned long Dim2BoundaryComponent::getNumberOfEdges() const { return edges_.size(); } inline unsigned long Dim2BoundaryComponent::getNumberOfVertices() const { return vertices_.size(); } inline Dim2Edge* Dim2BoundaryComponent::getEdge(unsigned long index) const { return edges_[index]; } inline Dim2Vertex* Dim2BoundaryComponent::getVertex(unsigned long index) const { return vertices_[index]; } inline Dim2Component* Dim2BoundaryComponent::getComponent() const { return vertices_.front()->getComponent(); } inline void Dim2BoundaryComponent::writeTextShort(std::ostream& out) const { out << "Boundary component"; } } // namespace regina #endif regina-4.96/engine/dim2/dim2component.cpp000644 000765 000024 00000005657 12377776545 020236 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "dim2/dim2component.h" #include "dim2/dim2triangle.h" namespace regina { void Dim2Component::writeTextShort(std::ostream& out) const { if (triangles_.size() == 1) out << "Component with 1 triangle"; else out << "Component with " << getNumberOfTriangles() << " triangles"; } void Dim2Component::writeTextLong(std::ostream& out) const { writeTextShort(out); out << std::endl; out << (triangles_.size() == 1 ? "Triangle:" : "Triangles:"); std::vector::const_iterator it; for (it = triangles_.begin(); it != triangles_.end(); ++it) out << ' ' << (*it)->markedIndex(); out << std::endl; } } // namespace regina regina-4.96/engine/dim2/dim2component.h000644 000765 000024 00000027267 12377774672 017703 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #ifndef __DIM2COMPONENT_H #ifndef __DOXYGEN #define __DIM2COMPONENT_H #endif /*! \file dim2/dim2component.h * \brief Deals with components of a 2-manifold triangulation. */ #include #include "regina-core.h" #include "shareableobject.h" #include "utilities/nmarkedvector.h" namespace regina { class Dim2BoundaryComponent; class Dim2Edge; class Dim2Triangle; class Dim2Vertex; /** * \weakgroup dim2 * @{ */ /** * Represents a component of a 2-manifold triangulation. * Components are highly temporary; once a triangulation changes, all * its component objects will be deleted and new ones will be created. */ class REGINA_API Dim2Component : public ShareableObject, public NMarkedElement { private: std::vector triangles_; /**< List of triangles in the component. */ std::vector edges_; /**< List of edges in the component. */ std::vector vertices_; /**< List of vertices in the component. */ std::vector boundaryComponents_; /**< List of boundary components in the component. */ bool orientable_; /**< Is the component orientable? */ public: /** * Default destructor. */ virtual ~Dim2Component(); /** * Returns the index of this component in the underlying * triangulation. This is identical to calling * getTriangulation()->componentIndex(this). * * @return the index of this component vertex. */ unsigned long index() const; /** * Returns the number of triangles in this component. * * @return the number of triangles. */ unsigned long getNumberOfTriangles() const; /** * A dimension-agnostic alias for getNumberOfTriangles(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "simplex" refers to a top-dimensional simplex (which for * 2-manifold triangulations means a triangle). * * See getNumberOfTriangles() for further information. */ unsigned long getNumberOfSimplices() const; /** * Returns the number of edges in this component. * * @return the number of edges. */ unsigned long getNumberOfEdges() const; /** * Returns the number of vertices in this component. * * @return the number of vertices. */ unsigned long getNumberOfVertices() const; /** * Returns the number of boundary components in this component. * * @return the number of boundary components. */ unsigned long getNumberOfBoundaryComponents() const; /** * Returns all triangular faces in the component. * * The reference returned will remain valid for as long as this * component object exists, always reflecting the triangles currently * in the component. * * \ifacespython This routine returns a python list. */ const std::vector& getTriangles() const; /** * Returns all edges in the component. * * The reference returned will remain valid for as long as this * component object exists, always reflecting the edges currently * in the component. * * \ifacespython This routine returns a python list. */ const std::vector& getEdges() const; /** * Returns all vertices in the component. * * The reference returned will remain valid for as long as this * component object exists, always reflecting the vertices currently * in the component. * * \ifacespython This routine returns a python list. */ const std::vector& getVertices() const; /** * Returns the requested triangle in this component. * * @param index the index of the requested triangle in the * component. This should be between 0 and * getNumberOfTriangles()-1 inclusive. * Note that the index of a triangle in the component need * not be the index of the same triangle in the entire * triangulation. * @return the requested triangle. */ Dim2Triangle* getTriangle(unsigned long index) const; /** * A dimension-agnostic alias for getTriangle(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "simplex" refers to a top-dimensional simplex (which for * 2-manifold triangulations means a triangle). * * See getTriangle() for further information. */ Dim2Triangle* getSimplex(unsigned long index) const; /** * Returns the requested edge in this component. * * @param index the index of the requested edge in the * component. This should be between 0 and * getNumberOfEdges()-1 inclusive. * Note that the index of an edge in the component need * not be the index of the same edge in the entire * triangulation. * @return the requested edge. */ Dim2Edge* getEdge(unsigned long index) const; /** * Returns the requested vertex in this component. * * @param index the index of the requested vertex in the * component. This should be between 0 and * getNumberOfVertices()-1 inclusive. * Note that the index of a vertex in the component need * not be the index of the same vertex in the entire * triangulation. * @return the requested vertex. */ Dim2Vertex* getVertex(unsigned long index) const; /** * Returns the requested boundary component in this component. * * @param index the index of the requested boundary component in * this component. This should be between 0 and * getNumberOfBoundaryComponents()-1 inclusive. * Note that the index of a boundary component in the component * need not be the index of the same boundary component in the * entire triangulation. * @return the requested boundary component. */ Dim2BoundaryComponent* getBoundaryComponent(unsigned long index) const; /** * Determines if this component is orientable. * * @return \c true if and only if this component is orientable. */ bool isOrientable() const; /** * Determines if this component is closed. * This is the case if and only if it has no boundary. * * @return \c true if and only if this component is closed. */ bool isClosed() const; /** * Returns the number of boundary edges in this component. * * @return the number of boundary edges. */ unsigned long getNumberOfBoundaryEdges() const; void writeTextShort(std::ostream& out) const; void writeTextLong(std::ostream& out) const; private: /** * Default constructor. * * Marks the component as orientable. */ Dim2Component(); friend class Dim2Triangulation; /**< Allow access to private members. */ }; /*@}*/ // Inline functions for Dim2Component inline Dim2Component::Dim2Component() : orientable_(true) { } inline Dim2Component::~Dim2Component() { } inline unsigned long Dim2Component::index() const { return markedIndex(); } inline unsigned long Dim2Component::getNumberOfTriangles() const { return triangles_.size(); } inline unsigned long Dim2Component::getNumberOfSimplices() const { return triangles_.size(); } inline unsigned long Dim2Component::getNumberOfEdges() const { return edges_.size(); } inline unsigned long Dim2Component::getNumberOfVertices() const { return vertices_.size(); } inline unsigned long Dim2Component::getNumberOfBoundaryComponents() const { return boundaryComponents_.size(); } inline const std::vector& Dim2Component::getTriangles() const { return triangles_; } inline const std::vector& Dim2Component::getEdges() const { return edges_; } inline const std::vector& Dim2Component::getVertices() const { return vertices_; } inline Dim2Triangle* Dim2Component::getTriangle(unsigned long index) const { return triangles_[index]; } inline Dim2Triangle* Dim2Component::getSimplex(unsigned long index) const { return triangles_[index]; } inline Dim2Edge* Dim2Component::getEdge(unsigned long index) const { return edges_[index]; } inline Dim2Vertex* Dim2Component::getVertex(unsigned long index) const { return vertices_[index]; } inline Dim2BoundaryComponent* Dim2Component::getBoundaryComponent( unsigned long index) const { return boundaryComponents_[index]; } inline bool Dim2Component::isOrientable() const { return orientable_; } inline bool Dim2Component::isClosed() const { return (boundaryComponents_.empty()); } inline unsigned long Dim2Component::getNumberOfBoundaryEdges() const { return 2 * edges_.size() - 3 * triangles_.size(); } } // namespace regina #endif regina-4.96/engine/dim2/dim2edge.cpp000644 000765 000024 00000005343 12377776546 017131 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "dim2/dim2edge.h" namespace regina { const NPerm3 Dim2Edge::ordering[3] = { NPerm3(1,2,0), NPerm3(0,2,1), NPerm3(0,1,2), }; void Dim2Edge::writeTextLong(std::ostream& out) const { writeTextShort(out); out << std::endl; out << "Appears as:" << std::endl; for (int i = 0; i < nEmb_; ++i) out << " " << emb_[i].getTriangle()->markedIndex() << " (" << emb_[i].getVertices().trunc2() << ')' << std::endl; } } // namespace regina regina-4.96/engine/dim2/dim2edge.h000644 000765 000024 00000032127 12377774674 016576 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file dim2/dim2edge.h * \brief Deals with edges in the 1-skeleton of a 2-manifold triangulation. */ #ifndef __DIM2EDGE_H #ifndef __DOXYGEN #define __DIM2EDGE_H #endif #include "regina-core.h" #include "shareableobject.h" #include "maths/nperm3.h" #include "utilities/nmarkedvector.h" // NOTE: More #includes follow after the class declarations. namespace regina { class Dim2BoundaryComponent; class Dim2Component; class Dim2Triangle; class Dim2Triangulation; class Dim2Vertex; /** * \weakgroup dim2 * @{ */ /** * Details how an edge in the 1-skeleton of a 2-manifold triangulation * forms part of an individual triangle. */ class REGINA_API Dim2EdgeEmbedding { private: Dim2Triangle* triangle_; /**< The triangle in which this edge is contained. */ int edge_; /**< The edge number of the triangle that is this edge. */ public: /** * Default constructor. The embedding descriptor created is * unusable until it has some data assigned to it using * operator =. * * \ifacespython Not present. */ Dim2EdgeEmbedding(); /** * Creates an embedding descriptor containing the given data. * * @param tri the triangle in which this edge is contained. * @param edge the edge number of \a tri that is this edge. */ Dim2EdgeEmbedding(Dim2Triangle* tri, int edge); /** * Creates an embedding descriptor containing the same data as * the given embedding descriptor. * * @param cloneMe the embedding descriptor to clone. */ Dim2EdgeEmbedding(const Dim2EdgeEmbedding& cloneMe); /** * Assigns to this embedding descriptor the same data as is * contained in the given embedding descriptor. * * @param cloneMe the embedding descriptor to clone. */ Dim2EdgeEmbedding& operator = (const Dim2EdgeEmbedding& cloneMe); /** * Returns the triangle in which this edge is contained. * * @return the triangle. */ Dim2Triangle* getTriangle() const; /** * Returns the edge number within getTriangle() that is this edge. * * @return the edge number that is this edge. */ int getEdge() const; /** * Returns a mapping from vertices (0,1) of this edge to the * corresponding vertex numbers in getTriangle(), as described * in Dim2Triangle::getEdgeMapping(). * * @return a mapping from the vertices of this edge to the * corresponding vertices of getTriangle(). */ NPerm3 getVertices() const; /** * Tests whether this and the given embedding are identical. * Here "identical" means that they refer to the same edge of * the same triangle. * * @param rhs the embedding to compare with this. * @return \c true if and only if both embeddings are identical. */ bool operator == (const Dim2EdgeEmbedding& rhs) const; /** * Tests whether this and the given embedding are different. * Here "different" means that they do not refer to the same edge of * the same triangle. * * @param rhs the embedding to compare with this. * @return \c true if and only if both embeddings are identical. */ bool operator != (const Dim2EdgeEmbedding& rhs) const; }; /** * Represents an edge in the 1-skeleton of a 2-manifold triangulation. * Edges are highly temporary; once a triangulation changes, all its * edge objects will be deleted and new ones will be created. */ class REGINA_API Dim2Edge : public ShareableObject, public NMarkedElement { public: /** * An array that maps edge numbers within a triangle to the canonical * ordering of the individual triangle vertices that form each edge. * * This means that the vertices of edge \a i in a triangle * are, in canonical order, ordering[i][0,1]. As an * immediate consequence, we obtain ordering[i][2] == i. * * Regina defines canonical order to be \e increasing order. * That is, ordering[i][0] < ordering[i][1]. * * This table does \e not describe the mapping from specific * edges within a triangulation into individual triangles * (for that, see Dim2Triangle::getEdgeMapping() instead). * This table merely provides a neat and consistent way of * listing the vertices of any given edge of a triangle. */ static const NPerm3 ordering[3]; private: Dim2EdgeEmbedding emb_[2]; /**< A list of descriptors telling how this edge forms a part of each individual triangle that it belongs to. */ unsigned nEmb_; /**< The number of descriptors stored in the list \a emb_. This will never exceed two. */ Dim2Component* component_; /**< The component that this edge is a part of. */ Dim2BoundaryComponent* boundaryComponent_; /**< The boundary component that this edge is a part of, or 0 if this edge is internal. */ public: /** * Default destructor. */ ~Dim2Edge(); /** * Returns the index of this edge in the underlying * triangulation. This is identical to calling * getTriangulation()->edgeIndex(this). * * @return the index of this edge. */ unsigned long index() const; /** * Returns the number of descriptors available through getEmbedding(). * Note that this number will never be greater than two. * * @return the number of embedding descriptors. */ unsigned getNumberOfEmbeddings() const; /** * Returns the requested descriptor detailing how this edge * forms a part of a particular triangle in the triangulation. * Note that if this edge represents multiple edges of a * particular triangle, then there will be multiple embedding * descriptors available regarding that triangle. * * @param index the index of the requested descriptor. This * should be between 0 and getNumberOfEmbeddings()-1 inclusive. * @return the requested embedding descriptor. */ const Dim2EdgeEmbedding& getEmbedding(unsigned index) const; /** * Returns the triangulation to which this edge belongs. * * @return the triangulation containing this edge. */ Dim2Triangulation* getTriangulation() const; /** * Returns the component of the triangulation to which this * edge belongs. * * @return the component containing this edge. */ Dim2Component* getComponent() const; /** * Returns the boundary component of the triangulation to which * this edge belongs. * * @return the boundary component containing this edge, or 0 * if this edge does not lie entirely within the boundary of * the triangulation. */ Dim2BoundaryComponent* getBoundaryComponent() const; /** * Returns the vertex of the 2-manifold triangulation corresponding * to the given vertex of this edge. * * @param vertex the vertex of this edge to examine. This * should be either 0 or 1. * @return the corresponding vertex of the 2-manifold triangulation. */ Dim2Vertex* getVertex(int vertex) const; /** * Determines if this edge lies entirely on the boundary of the * triangulation. * * @return \c true if and only if this edge lies on the boundary. */ bool isBoundary() const; void writeTextShort(std::ostream& out) const; void writeTextLong(std::ostream& out) const; private: /** * Creates a new edge and marks it as belonging to the * given triangulation component. * * @param component the triangulation component to which this * edge belongs. */ Dim2Edge(Dim2Component* component); friend class Dim2Triangulation; /**< Allow access to private members. */ }; /*@}*/ } // namespace regina // Some more headers that are required for inline functions: #include "dim2/dim2triangle.h" namespace regina { // Inline functions for Dim2EdgeEmbedding inline Dim2EdgeEmbedding::Dim2EdgeEmbedding() : triangle_(0) { } inline Dim2EdgeEmbedding::Dim2EdgeEmbedding( Dim2Triangle* tri, int edge) : triangle_(tri), edge_(edge) { } inline Dim2EdgeEmbedding::Dim2EdgeEmbedding( const Dim2EdgeEmbedding& cloneMe) : triangle_(cloneMe.triangle_), edge_(cloneMe.edge_) { } inline Dim2EdgeEmbedding& Dim2EdgeEmbedding::operator = (const Dim2EdgeEmbedding& cloneMe) { triangle_ = cloneMe.triangle_; edge_ = cloneMe.edge_; return *this; } inline Dim2Triangle* Dim2EdgeEmbedding::getTriangle() const { return triangle_; } inline int Dim2EdgeEmbedding::getEdge() const { return edge_; } inline NPerm3 Dim2EdgeEmbedding::getVertices() const { return triangle_->getEdgeMapping(edge_); } inline bool Dim2EdgeEmbedding::operator == (const Dim2EdgeEmbedding& other) const { return ((triangle_ == other.triangle_) && (edge_ == other.edge_)); } inline bool Dim2EdgeEmbedding::operator != (const Dim2EdgeEmbedding& other) const { return ((triangle_ != other.triangle_) || (edge_ != other.edge_)); } // Inline functions for Dim2Edge inline Dim2Edge::Dim2Edge(Dim2Component* component) : nEmb_(0), component_(component), boundaryComponent_(0) { } inline Dim2Edge::~Dim2Edge() { } inline unsigned long Dim2Edge::index() const { return markedIndex(); } inline unsigned Dim2Edge::getNumberOfEmbeddings() const { return nEmb_; } inline const Dim2EdgeEmbedding& Dim2Edge::getEmbedding( unsigned index) const { return emb_[index]; } inline Dim2Triangulation* Dim2Edge::getTriangulation() const { return emb_[0].getTriangle()->getTriangulation(); } inline Dim2Component* Dim2Edge::getComponent() const { return component_; } inline Dim2BoundaryComponent* Dim2Edge::getBoundaryComponent() const { return boundaryComponent_; } inline Dim2Vertex* Dim2Edge::getVertex(int vertex) const { return emb_[0].getTriangle()->getVertex(emb_[0].getVertices()[vertex]); } inline bool Dim2Edge::isBoundary() const { return (boundaryComponent_ != 0); } inline void Dim2Edge::writeTextShort(std::ostream& out) const { out << (boundaryComponent_ ? "Boundary " : "Internal ") << "edge"; } } // namespace regina #endif regina-4.96/engine/dim2/dim2exampletriangulation.cpp000644 000765 000024 00000020773 12377776547 022466 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "dim2/dim2exampletriangulation.h" #include "dim2/dim2triangulation.h" namespace regina { Dim2Triangulation* Dim2ExampleTriangulation::orientable( unsigned genus, unsigned punctures) { Dim2Triangulation* ans = new Dim2Triangulation(); if (genus == 0) { if (punctures == 0) return sphere(); unsigned n = 3 * punctures - 2; unsigned i; for (i = 0; i < n; ++i) ans->newTriangle(); for (i = 0; i < n - 1; ++i) ans->getTriangle(i)->joinTo(1, ans->getTriangle(i + 1), NPerm3(1, 2)); ans->getTriangle(0)->joinTo(0, ans->getTriangle(n - 1), NPerm3(0, 1)); for (i = 1; i < punctures; ++i) ans->getTriangle(3 * i - 2)->joinTo(0, ans->getTriangle(3 * i), NPerm3(1, 2)); } else { unsigned n = 4 * genus + 3 * punctures - 2; unsigned i; for (i = 0; i < n; ++i) ans->newTriangle(); for (i = 0; i < n - 1; ++i) ans->getTriangle(i)->joinTo(1, ans->getTriangle(i + 1), NPerm3(1, 2)); ans->getTriangle(0)->joinTo(2, ans->getTriangle(n - 1), NPerm3(0, 2)); ans->getTriangle(0)->joinTo(0, ans->getTriangle(n - 1), NPerm3(0, 1)); for (i = 1; i < genus; ++i) { ans->getTriangle(4 * i - 3)->joinTo(0, ans->getTriangle(4 * i - 1), NPerm3(1, 2)); ans->getTriangle(4 * i - 2)->joinTo(0, ans->getTriangle(4 * i), NPerm3(1, 2)); } for (i = 0; i < punctures; ++i) ans->getTriangle(4 * genus + 3 * i - 3)->joinTo( 0, ans->getTriangle(4 * genus + 3 * i - 1), NPerm3(1, 2)); } return ans; } Dim2Triangulation* Dim2ExampleTriangulation::nonOrientable( unsigned genus, unsigned punctures) { if (genus == 0) return orientable(0, punctures); // Just in case. *shrug* if (genus == 1 && punctures == 0) return rp2(); // Avoid 2-gons. Dim2Triangulation* ans = new Dim2Triangulation(); unsigned n = 2 * genus + 3 * punctures - 2; unsigned i; for (i = 0; i < n; ++i) ans->newTriangle(); for (i = 0; i < n - 1; ++i) ans->getTriangle(i)->joinTo(1, ans->getTriangle(i + 1), NPerm3(1, 2)); ans->getTriangle(0)->joinTo(2, ans->getTriangle(n - 1), NPerm3(2, 0, 1)); for (i = 1; i < genus; ++i) ans->getTriangle(2 * i - 2)->joinTo(0, ans->getTriangle(2 * i - 1), NPerm3()); for (i = 0; i < punctures; ++i) ans->getTriangle(2 * genus + 3 * i - 2)->joinTo( 0, ans->getTriangle(2 * genus + 3 * i), NPerm3(1, 2)); return ans; } Dim2Triangulation* Dim2ExampleTriangulation::sphere() { Dim2Triangulation* ans = new Dim2Triangulation(); ans->setPacketLabel("Sphere"); Dim2Triangle* r = ans->newTriangle(); Dim2Triangle* s = ans->newTriangle(); r->joinTo(0, s, NPerm3()); r->joinTo(1, s, NPerm3()); r->joinTo(2, s, NPerm3()); return ans; } Dim2Triangulation* Dim2ExampleTriangulation::sphereTetrahedron() { Dim2Triangulation* ans = new Dim2Triangulation(); ans->setPacketLabel("Sphere (tetrahedron boundary)"); Dim2Triangle* r = ans->newTriangle(); Dim2Triangle* s = ans->newTriangle(); Dim2Triangle* t = ans->newTriangle(); Dim2Triangle* u = ans->newTriangle(); r->joinTo(1, s, NPerm3(1, 2)); s->joinTo(1, t, NPerm3(1, 2)); t->joinTo(1, r, NPerm3(1, 2)); r->joinTo(0, u, NPerm3(0, 1, 2)); s->joinTo(0, u, NPerm3(1, 2, 0)); t->joinTo(0, u, NPerm3(2, 0, 1)); return ans; } Dim2Triangulation* Dim2ExampleTriangulation::sphereOctahedron() { Dim2Triangulation* ans = new Dim2Triangulation(); ans->setPacketLabel("Sphere (octahedron boundary)"); Dim2Triangle* r = ans->newTriangle(); Dim2Triangle* s = ans->newTriangle(); Dim2Triangle* t = ans->newTriangle(); Dim2Triangle* u = ans->newTriangle(); Dim2Triangle* v = ans->newTriangle(); Dim2Triangle* w = ans->newTriangle(); Dim2Triangle* x = ans->newTriangle(); Dim2Triangle* y = ans->newTriangle(); r->joinTo(1, s, NPerm3(1, 2)); s->joinTo(1, t, NPerm3(1, 2)); t->joinTo(1, u, NPerm3(1, 2)); u->joinTo(1, r, NPerm3(1, 2)); v->joinTo(1, w, NPerm3(1, 2)); w->joinTo(1, x, NPerm3(1, 2)); x->joinTo(1, y, NPerm3(1, 2)); y->joinTo(1, v, NPerm3(1, 2)); r->joinTo(0, v, NPerm3()); s->joinTo(0, w, NPerm3()); t->joinTo(0, x, NPerm3()); u->joinTo(0, y, NPerm3()); return ans; } Dim2Triangulation* Dim2ExampleTriangulation::disc() { Dim2Triangulation* ans = new Dim2Triangulation(); ans->setPacketLabel("Disc"); ans->newTriangle(); return ans; } Dim2Triangulation* Dim2ExampleTriangulation::annulus() { Dim2Triangulation* ans = new Dim2Triangulation(); ans->setPacketLabel("Annulus"); Dim2Triangle* r = ans->newTriangle(); Dim2Triangle* s = ans->newTriangle(); r->joinTo(0, s, NPerm3(1, 2)); r->joinTo(2, s, NPerm3(0, 1)); return ans; } Dim2Triangulation* Dim2ExampleTriangulation::mobius() { Dim2Triangulation* ans = new Dim2Triangulation(); ans->setPacketLabel("Mobius band"); Dim2Triangle* r = ans->newTriangle(); r->joinTo(0, r, NPerm3(2, 0, 1)); return ans; } Dim2Triangulation* Dim2ExampleTriangulation::torus() { Dim2Triangulation* ans = new Dim2Triangulation(); ans->setPacketLabel("Torus"); Dim2Triangle* r = ans->newTriangle(); Dim2Triangle* s = ans->newTriangle(); r->joinTo(0, s, NPerm3(1, 2)); r->joinTo(1, s, NPerm3(2, 0)); r->joinTo(2, s, NPerm3(0, 1)); return ans; } Dim2Triangulation* Dim2ExampleTriangulation::rp2() { Dim2Triangulation* ans = new Dim2Triangulation(); ans->setPacketLabel("Projective plane"); Dim2Triangle* r = ans->newTriangle(); Dim2Triangle* s = ans->newTriangle(); r->joinTo(0, s, NPerm3(1, 2)); r->joinTo(1, s, NPerm3()); r->joinTo(2, s, NPerm3()); return ans; } Dim2Triangulation* Dim2ExampleTriangulation::kb() { Dim2Triangulation* ans = new Dim2Triangulation(); ans->setPacketLabel("Klein bottle"); Dim2Triangle* r = ans->newTriangle(); Dim2Triangle* s = ans->newTriangle(); r->joinTo(0, s, NPerm3(1, 2)); r->joinTo(1, s, NPerm3(2, 0)); r->joinTo(2, s, NPerm3()); return ans; } } // namespace regina regina-4.96/engine/dim2/dim2exampletriangulation.h000644 000765 000024 00000015323 12377775057 022121 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file dim2/dim2exampletriangulation.h * \brief Offers several example 2-manifold triangulations as starting * points for testing code or getting used to Regina. */ #ifndef __NEXAMPLETRIANGULATION_H #ifndef __DOXYGEN #define __NEXAMPLETRIANGULATION_H #endif #include "regina-core.h" namespace regina { class Dim2Triangulation; /** * \weakgroup triangulation * @{ */ /** * This class offers routines for constructing sample 2-manifold triangulations * of various types. These triangulations may be useful for testing new * code, or for simply getting a feel for how Regina works. * * The sample triangulations offered here may prove especially useful in * Regina's scripting interface, where working with pre-existing files * is more complicated than in the GUI. * * Note that each of these routines constructs a new triangulation from * scratch. It is up to the caller of each routine to destroy the * triangulation that is returned. */ class REGINA_API Dim2ExampleTriangulation { public: /** * Returns a triangulation of the given orientable surface. * * @param genus the genus of the surface; this must be greater * than or equal to zero. * @param punctures the number of punctures in the surface; * this must be greater than or equal to zero. * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static Dim2Triangulation* orientable( unsigned genus, unsigned punctures); /** * Returns a triangulation of the given non-orientable surface. * * @param genus the non-orientable genus of the surface, i.e., * the number of crosscaps that it contains; this must be greater * than or equal to one. * @param punctures the number of punctures in the surface; * this must be greater than or equal to zero. * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static Dim2Triangulation* nonOrientable( unsigned genus, unsigned punctures); /** * Returns a two-triangle 2-sphere. * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static Dim2Triangulation* sphere(); /** * Returns the four-triangle 2-sphere formed from the boundary * of a tetrahedron. * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static Dim2Triangulation* sphereTetrahedron(); /** * Returns the eight-triangle 2-sphere formed from the boundary * of an octahedron. * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static Dim2Triangulation* sphereOctahedron(); /** * Returns a one-triangle disc. * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static Dim2Triangulation* disc(); /** * Returns a two-triangle annulus. * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static Dim2Triangulation* annulus(); /** * Returns a one-triangle Mobius band. * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static Dim2Triangulation* mobius(); /** * Returns a two-triangle torus. * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static Dim2Triangulation* torus(); /** * Returns a two-triangle projective plane. * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static Dim2Triangulation* rp2(); /** * Returns a two-triangle Klein bottle. * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static Dim2Triangulation* kb(); }; /*@}*/ } // namespace regina #endif regina-4.96/engine/dim2/dim2isomorphism.cpp000644 000765 000024 00000006027 12377776547 020577 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include "dim2/dim2isomorphism.h" #include "dim2/dim2triangulation.h" #include "generic/ngenericisomorphism-impl.h" namespace regina { // Instantiate all templates from the -impl.h file. template void NGenericIsomorphism<2>::writeTextShort(std::ostream&) const; template void NGenericIsomorphism<2>::writeTextLong(std::ostream&) const; template bool NGenericIsomorphism<2>::isIdentity() const; template NGenericIsomorphism<2>::NGenericIsomorphism( const NGenericIsomorphism<2>&); template Dim2Isomorphism* NGenericIsomorphism<2>::random(unsigned); template Dim2Triangulation* NGenericIsomorphism<2>::apply( const Dim2Triangulation*) const; template void NGenericIsomorphism<2>::applyInPlace(Dim2Triangulation*) const; } // namespace regina regina-4.96/engine/dim2/dim2isomorphism.h000644 000765 000024 00000023004 12377775061 020224 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file dim2/dim2isomorphism.h * \brief Deals with combinatorial isomorphisms of 2-manifold triangulations. */ #ifndef __DIM2ISOMORPHISM_H #ifndef __DOXYGEN #define __DIM2ISOMORPHISM_H #endif #include "regina-core.h" #include "shareableobject.h" #include "generic/nfacetspec.h" #include "generic/ngenericisomorphism.h" #include "maths/nperm3.h" namespace regina { class Dim2Triangulation; /** * \weakgroup dim2 * @{ */ /** * Represents a combinatorial isomorphism from one 2-manifold triangulation * into another. * * In essence, a combinatorial isomorphism from triangulation T to * triangulation U is a one-to-one map from the triangles of T to the * triangles of U that allows relabelling of both the triangles and * their edges (or equivalently, their vertices), and that preserves * gluings across adjacent triangles. * * More precisely: An isomorphism consists of (i) a one-to-one map f * from the triangles of T to the triangles of U, and (ii) for each * triangle S of T, a permutation f_S of the edges (0,1,2) of S, * for which the following condition holds: * * - If edge k of triangle S and edge k' of triangle S' * are identified in T, then edge f_S(k) of f(S) and edge f_S'(k') * of f(S') are identified in U. Moreover, their gluing is consistent * with the edge/vertex permutations; that is, there is a commutative * square involving the gluing maps in T and U and the permutations * f_S and f_S'. * * Isomorphisms can be boundary complete or * boundary incomplete. A boundary complete isomorphism * satisfies the additional condition: * * - If edge x is a boundary edge of T then edge f(x) is a boundary * edge of U. * * A boundary complete isomorphism thus indicates that a copy of * triangulation T is present as an entire component (or components) of U, * whereas a boundary incomplete isomorphism represents an embedding of a * copy of triangulation T as a subcomplex of some possibly larger component * (or components) of U. * * Note that in all cases triangulation U may contain more triangles * than triangulation T. */ class REGINA_API Dim2Isomorphism : public NGenericIsomorphism<2> { public: /** * Creates a new isomorphism with no initialisation. * * \ifacespython Not present. * * @param sourceTriangles the number of triangles in the source * triangulation associated with this isomorphism; this may be zero. */ Dim2Isomorphism(unsigned sourceTriangles); /** * Creates a new isomorphism identical to the given isomorphism. * * @param cloneMe the isomorphism upon which to base the new * isomorphism. */ Dim2Isomorphism(const Dim2Isomorphism& cloneMe); /** * Returns the number of triangles in the source triangulation * associated with this isomorphism. Note that this is always * less than or equal to the number of triangles in the * destination triangulation. * * This is a convenience routine specific to two dimensions, and is * identical to the dimension-agnostic routine getSourceSimplices(). * * @return the number of triangles in the source triangulation. */ unsigned getSourceTriangles() const; /** * Determines the image of the given source triangle under * this isomorphism. * * This is a convenience routine specific to two dimensions, and is * identical to the dimension-agnostic routine simpImage(). * * \ifacespython Not present, though the read-only version of this * routine is. * * @param sourceTriangle the index of the source triangle; this must * be between 0 and getSourceSimplices()-1 inclusive. * @return a reference to the index of the destination triangle * that the source triangle maps to. */ int& triImage(unsigned sourceTriangle); /** * Determines the image of the given source triangle under * this isomorphism. * * This is a convenience routine specific to two dimensions, and is * identical to the dimension-agnostic routine simpImage(). * * @param sourceTriangle the index of the source triangle; this must * be between 0 and getSourceSimplices()-1 inclusive. * @return the index of the destination triangle * that the source triangle maps to. */ int triImage(unsigned sourceTriangle) const; /** * Returns a read-write reference to the permutation that is * applied to the three edges of the given source triangle * under this isomorphism. * Edge \a i of source triangle \a sourceTriangle will be mapped to * edge facetPerm(sourceTriangle)[i] of triangle * simpImage(sourceTriangle). * * This is a convenience routine specific to two dimensions, and is * identical to the dimension-agnostic routine facetPerm(). * * \ifacespython Not present, though the read-only version of this * routine is. * * @param sourceTriangle the index of the source triangle containing * the original three edges; this must be between 0 and * getSourceTriangles()-1 inclusive. * @return a read-write reference to the permutation applied to the * three edges of the source triangle. */ NPerm3& edgePerm(unsigned sourceTriangle); /** * Determines the permutation that is applied to the three edges * of the given source triangle under this isomorphism. * Edge \a i of source triangle \a sourceTriangle will be mapped to * triangle facetPerm(sourceTriangle)[i] of triangle * simpImage(sourceTriangle). * * This is a convenience routine specific to two dimensions, and is * identical to the dimension-agnostic routine facetPerm(). * * @param sourceTriangle the index of the source triangle containing * the original three edges; this must be between 0 and * getSourceTriangles()-1 inclusive. * @return the permutation applied to the three edges of the * source triangle. */ NPerm3 edgePerm(unsigned sourceTriangle) const; }; /*@}*/ // Inline functions for Dim2Isomorphism inline Dim2Isomorphism::Dim2Isomorphism(unsigned sourceTriangles) : NGenericIsomorphism<2>(sourceTriangles) { } inline Dim2Isomorphism::Dim2Isomorphism(const Dim2Isomorphism& cloneMe) : NGenericIsomorphism<2>(cloneMe) { } inline unsigned Dim2Isomorphism::getSourceTriangles() const { return nSimplices_; } inline int& Dim2Isomorphism::triImage(unsigned sourceTriangle) { return simpImage_[sourceTriangle]; } inline int Dim2Isomorphism::triImage(unsigned sourceTriangle) const { return simpImage_[sourceTriangle]; } inline NPerm3& Dim2Isomorphism::edgePerm(unsigned sourceTriangle) { return facetPerm_[sourceTriangle]; } inline NPerm3 Dim2Isomorphism::edgePerm(unsigned sourceTriangle) const { return facetPerm_[sourceTriangle]; } } // namespace regina #endif regina-4.96/engine/dim2/dim2triangle.cpp000644 000765 000024 00000007651 12377776550 020031 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "dim2/dim2triangle.h" #include "dim2/dim2triangulation.h" #include namespace regina { Dim2Triangle::Dim2Triangle(Dim2Triangulation* tri) : tri_(tri) { std::fill(adj_, adj_ + 3, static_cast(0)); } Dim2Triangle::Dim2Triangle(const std::string& desc, Dim2Triangulation* tri) : desc_(desc), tri_(tri) { std::fill(adj_, adj_ + 3, static_cast(0)); } bool Dim2Triangle::hasBoundary() const { for (int i=0; i<3; ++i) if (adj_[i] == 0) return true; return false; } void Dim2Triangle::joinTo(int myEdge, Dim2Triangle* you, NPerm3 gluing) { NPacket::ChangeEventSpan span(tri_); adj_[myEdge] = you; adjPerm_[myEdge] = gluing; int yourEdge = gluing[myEdge]; you->adj_[yourEdge] = this; you->adjPerm_[yourEdge] = gluing.inverse(); tri_->clearAllProperties(); } Dim2Triangle* Dim2Triangle::unjoin(int myEdge) { NPacket::ChangeEventSpan span(tri_); Dim2Triangle* you = adj_[myEdge]; int yourEdge = adjPerm_[myEdge][myEdge]; you->adj_[yourEdge] = 0; adj_[myEdge] = 0; tri_->clearAllProperties(); return you; } void Dim2Triangle::isolate() { for (int i=0; i<3; ++i) if (adj_[i]) unjoin(i); } void Dim2Triangle::writeTextLong(std::ostream& out) const { writeTextShort(out); out << std::endl; for (int i = 2; i >= 0; --i) { out << Dim2Edge::ordering[i].trunc2() << " -> "; if (! adj_[i]) out << "boundary"; else out << adj_[i]->markedIndex() << " (" << (adjPerm_[i] * Dim2Edge::ordering[i]).trunc2() << ')'; out << std::endl; } } } // namespace regina regina-4.96/engine/dim2/dim2triangle.h000644 000765 000024 00000051760 12377775062 017473 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file dim2/dim2triangle.h * \brief Deals with triangular faces in a 2-manifold triangulation. */ #ifndef __DIM2TRIANGLE_H #ifndef __DOXYGEN #define __DIM2TRIANGLE_H #endif #include "regina-core.h" #include "shareableobject.h" #include "maths/nperm3.h" #include "utilities/nmarkedvector.h" // NOTE: More #includes follow after the class declarations. namespace regina { class Dim2Edge; class Dim2Vertex; class Dim2Component; class Dim2Triangulation; /** * \weakgroup dim2 * @{ */ /** * Represents a triangular face in a 2-manifold triangulation. * * With each triangle is stored various pieces of information * regarding the overall skeletal structure and component structure of * the triangulation. This skeletal information will be allocated, calculated * and deallocated by the Dim2Triangulation object containing the * corresponding triangles. * * A triangle must always belong to a 2-manifold triangulation. You can * construct new triangles using either Dim2Triangulation::newTriangle() * or Dim2Triangulation::newTriangle(const std::string&); these * routines will automatically add the new triangles to the triangulation. * You can destroy triangles by calling Dim2Trianguation::removeTriangle(), * Dim2Trianguation::removeTriangleAt() or * Dim2Triangulation::removeAllTriangles(); these routines will * automatically destroy the triangles as they are removed. */ class REGINA_API Dim2Triangle : public ShareableObject, public NMarkedElement { private: Dim2Triangle* adj_[3]; /**< Stores the adjacent triangles glued to each edge of this triangle. Specifically, adj_[e] represents the triangle joined to edge \c e of this triangle, or is 0 if edge \c e lies on the triangulation boundary. Edges are numbered from 0 to 2 inclusive, where edge \c i is opposite vertex \c i. */ NPerm3 adjPerm_[3]; /**< Stores the corresponence between vertices of this triangle and adjacent triangles. If edge \c e is joined to another triangle, adjPerm_[3] represents the permutation \c p whereby vertex \c v of this triangle is identified with vertex p[v] of the adjacent triangle along edge \c e. */ std::string desc_; /**< A text description of this triangle. Descriptions are not mandatory and need not be unique. */ Dim2Vertex* vertex_[3]; /**< Vertices in the triangulation skeleton that are vertices of this triangle. */ Dim2Edge* edge_[3]; /**< Edges in the triangulation skeleton that are edges of this triangle. */ NPerm3 vertexMapping_[3]; /**< Maps 0 to each vertex of this triangle in turn whilst mapping (1,2) in a suitably "orientation-preserving" way, as described in getVertexMapping(). */ NPerm3 edgeMapping_[3]; /**< Maps (0,1) to the vertices of this triangle that form each edge, as described in getEdgeMapping(). */ int orientation_; /**< The orientation of this triangle in the triangulation. This will either be 1 or -1. */ Dim2Triangulation* tri_; /**< The triangulation to which this triangle belongs. */ Dim2Component* component_; /**< The component to which this triangle belongs in the triangulation. */ public: /** * Destroys this triangle. */ virtual ~Dim2Triangle(); /** * Returns the text description associated with this * triangle. * * @return the description of this triangle. */ const std::string& getDescription() const; /** * Sets the text description associated with this triangle. * Note that descriptions need not be unique, and may be empty. * * @param desc the new description to assign to this * triangle. */ void setDescription(const std::string& desc); /** * Returns the index of this triangle in the underlying * triangulation. This is identical to calling * getTriangulation()->triangleIndex(this). * * Note that triangle indexing may change when a triangle is * added or removed from the underlying triangulation. * * @return the index of this triangle. */ unsigned long index() const; /** * Returns the adjacent triangle glued to the given edge of this * triangle, or 0 if the given edge is on the boundary of the * 2-manifold triangulation. * * @param edge the edge of this triangle to examine. This * should be between 0 and 2 inclusive, where edge \c i is * opposite vertex \c i of the triangle. * @return the adjacent triangle glued to the given edge, or 0 * if the given edge lies on the boundary. */ Dim2Triangle* adjacentTriangle(int edge) const; /** * A dimension-agnostic alias for adjacentTriangle(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "simplex" refers to a top-dimensional simplex (which for * 2-manifold triangulations means a triangle). * * See adjacentTriangle() for further information. */ Dim2Triangle* adjacentSimplex(int edge) const; /** * Returns a permutation describing the correspondence between * vertices of this triangle and vertices of the adjacent * triangle glued to the given edge of this triangle. * * If we call this permutation \c p, then for each vertex \c v of this * triangle, p[v] will be the vertex of the adjacent * triangle that is identified with \c v according to the gluing * along the given edge of this triangle. * * \pre The given edge of this triangle has some triangle * (possibly this one) glued to it. * * @param edge the edge of this triangle whose gluing we * will examine. This should be between 0 and 2 inclusive, where * edge \c i is opposite vertex \c i of the triangle. * @return a permutation mapping the vertices of this * triangle to the vertices of the triangle adjacent along * the given edge. */ NPerm3 adjacentGluing(int edge) const; /** * Examines the triangle glued to the given edge of this * triangle, and returns the corresponding edge of that * triangle. That is, the returned edge of the adjacent * triangle is glued to the given edge of this triangle. * * \pre The given edge of this triangle has some triangle * (possibly this one) glued to it. * * @param edge the edge of this triangle whose gluing we * will examine. This should be between 0 and 2 inclusive, where * edge \c i is opposite vertex \c i of the triangle. * @return the edge of the triangle adjacent along the given * edge that is in fact glued to the given edge of this triangle. */ int adjacentEdge(int edge) const; /** * A dimension-agnostic alias for adjacentEdge(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "facet" refers to a facet of a top-dimensional simplex * (which for 2-manifold triangulations means an edge of a triangle). * * See adjacentEdge() for further information. */ int adjacentFacet(int facet) const; /** * Determines if this triangle has any edges that are boundary edges. * * @return \c true if and only if this triangle has any boundary edges. */ bool hasBoundary() const; /** * Joins the given edge of this triangle to another triangle. * The other triangle involved will be automatically updated. * * \pre This and the given triangle do not belong to * different triangulations. * \pre The given edge of this triangle is not currently glued * to anything. * \pre The edge of the other triangle that will be glued to the * given edge of this triangle is not currently glued to anything. * \pre If the other triangle involved is this triangle, we are * not attempting to glue an edge to itself. * * @param myEdge the edge of this triangle that will be glued to * the given other triangle. This should be between 0 and 2 * inclusive, where edge \c i is opposite vertex \c i of the triangle. * @param you the triangle (possibly this one) that will be * glued to the given edge of this triangle. * @param gluing a permutation describing the mapping of * vertices by which the two triangles will be joined. Each * vertex \c v of this triangle that lies on the given edge will * be identified with vertex gluing[v] of triangle * you. In addition, the edge of you that * will be glued to the given edge of this triangle will be * edge number gluing[myEdge]. */ void joinTo(int myEdge, Dim2Triangle* you, NPerm3 gluing); /** * Unglues the given edge of this triangle from whatever is * joined to it. The other triangle involved (possibly this * one) will be automatically updated. * * \pre The given edge of this triangle has some triangle * (possibly this one) glued to it. * * @param myEdge the edge of this triangle whose gluing we * will undo. This should be between 0 and 2 inclusive, where * edge \c i is opposite vertex \c i of the triangle. * @return the ex-adjacent triangle that was originally glued to the * given edge of this triangle. */ Dim2Triangle* unjoin(int myEdge); /** * Undoes any edge gluings involving this triangle. * Any other triangles involved will be automatically updated. */ void isolate(); /** * Returns the triangulation to which this triangle belongs. * * @return the triangulation containing this triangle. */ Dim2Triangulation* getTriangulation() const; /** * Returns the 2-manifold triangulation component to which this * triangle belongs. * * @return the component containing this triangle. */ Dim2Component* getComponent() const; /** * Returns the vertex in the 2-manifold triangulation skeleton * corresponding to the given vertex of this triangle. * * @param vertex the vertex of this triangle to examine. * This should be between 0 and 2 inclusive. * @return the vertex of the skeleton corresponding to the * requested triangle vertex. */ Dim2Vertex* getVertex(int vertex) const; /** * Returns the edge in the 2-manifold triangulation skeleton * corresponding to the given edge of this triangle. Edge \c i * of a triangle is always opposite vertex \c i of that triangle. * * @param edge the edge of this triangle to examine. * This should be between 0 and 2 inclusive. * @return the edge of the skeleton corresponding to the * requested triangle edge. */ Dim2Edge* getEdge(int edge) const; /** * Returns a permutation that maps 0 to the given vertex of this * triangle, and that maps (1,2) to the two remaining vertices * in the following "orientation-preserving" fashion. * * The images of 1 and 2 under the permutations that are returned * have the following properties. In each triangle, the images * of 1 and 2 under this map form a directed edge of the triangle * (running from the image of vertex 1 to the image of vertex 2). * For any given vertex of the triangulation, these corresponding * directed edges together form an ordered path within the * triangulation that circles the common vertex of the triangulation * (like a vertex link, except that it is not near to the vertex * and so might intersect itself). Furthermore, if we consider the * individual triangles in the order in which they appear in the list * Dim2Vertex::getEmbeddings(), these corresponding directed edges * appear in order from the start of this path to the finish * (for internal vertices this path is actually a cycle, and the * starting point is arbitrary). * * @param vertex the vertex of this triangle to examine. * This should be between 0 and 2 inclusive. * @return a permutation that maps 0 to the given vertex of this * triangle, with the properties outlined above. */ NPerm3 getVertexMapping(int vertex) const; /** * Examines the given edge of this triangle, and returns a mapping from * the "canonical" vertices of the corresponding edge of the * triangulation to the matching vertices of this triangle. * * In detail: Suppose two edges of two triangles are * identified within the overall 2-manifold triangulation. We call * this a single "edge of the triangulation", and arbitrarily * label its vertices (0,1). This routine then maps the vertices * (0,1) of this edge of the triangulation to the individual * vertices of this triangle that make up the given edge. * * Because we are passing the argument \a edge, we already know * \e which vertices of this triangle are involved. What this * routine tells us is the \a order in which they appear to form the * overall edge of the triangulation. * * As a consequence: Consider two triangle edges that are * identified together as a single edge of the triangulation, * and choose some \a i from the set {0,1}. Then the vertices * getEdgeMapping(...)[i] of the individual triangles * are identified together, since they both become the same * vertex of the same edge of the triangulation (assuming of * course that we pass the correct edge number in each case to * getEdgeMapping()). * * @param edge the edge of this triangle to examine. * This should be between 0 and 2 inclusive. * @return a mapping from vertices (0,1) of the requested * edge to the corresponding vertices of this triangle. */ NPerm3 getEdgeMapping(int edge) const; /** * Returns the orientation of this triangle in the 2-manifold * triangulation. * * The orientation of each triangle is always +1 or -1. * In an orientable component of a triangulation, * adjacent triangles have the same orientations if one could be * transposed onto the other without reflection, and they have * opposite orientations if a reflection would be required. * In a non-orientable component, orientations are still +1 and * -1 but no further guarantees can be made. * * @return +1 or -1 according to the orientation of this triangle. */ int orientation() const; void writeTextShort(std::ostream& out) const; void writeTextLong(std::ostream& out) const; private: /** * Creates a new triangle with empty description and no * edges joined to anything. * * @param tri the triangulation to which the new triangle belongs. */ Dim2Triangle(Dim2Triangulation* tri); /** * Creates a new triangle with the given description and * no edges joined to anything. * * @param desc the description to give the new triangle. * @param tri the triangulation to which the new triangle belongs. */ Dim2Triangle(const std::string& desc, Dim2Triangulation* tri); friend class Dim2Triangulation; /**< Allow access to private members. */ }; /*@}*/ } // namespace regina // Some more headers that are required for inline functions: #include "dim2/dim2triangulation.h" namespace regina { // Inline functions for Dim2Triangle inline Dim2Triangle::~Dim2Triangle() { } inline const std::string& Dim2Triangle::getDescription() const { return desc_; } inline void Dim2Triangle::setDescription(const std::string& desc) { NPacket::ChangeEventSpan span(tri_); desc_ = desc; } inline unsigned long Dim2Triangle::index() const { return markedIndex(); } inline Dim2Triangle* Dim2Triangle::adjacentTriangle(int edge) const { return adj_[edge]; } inline Dim2Triangle* Dim2Triangle::adjacentSimplex(int edge) const { return adj_[edge]; } inline NPerm3 Dim2Triangle::adjacentGluing(int edge) const { return adjPerm_[edge]; } inline int Dim2Triangle::adjacentEdge(int edge) const { return adjPerm_[edge][edge]; } inline int Dim2Triangle::adjacentFacet(int facet) const { return adjPerm_[facet][facet]; } inline Dim2Triangulation* Dim2Triangle::getTriangulation() const { return tri_; } inline Dim2Component* Dim2Triangle::getComponent() const { if (! tri_->calculatedSkeleton_) tri_->calculateSkeleton(); return component_; } inline Dim2Vertex* Dim2Triangle::getVertex(int vertex) const { if (! tri_->calculatedSkeleton_) tri_->calculateSkeleton(); return vertex_[vertex]; } inline Dim2Edge* Dim2Triangle::getEdge(int edge) const { if (! tri_->calculatedSkeleton_) tri_->calculateSkeleton(); return edge_[edge]; } inline NPerm3 Dim2Triangle::getVertexMapping(int vertex) const { if (! tri_->calculatedSkeleton_) tri_->calculateSkeleton(); return vertexMapping_[vertex]; } inline NPerm3 Dim2Triangle::getEdgeMapping(int edge) const { if (! tri_->calculatedSkeleton_) tri_->calculateSkeleton(); return edgeMapping_[edge]; } inline int Dim2Triangle::orientation() const { if (! tri_->calculatedSkeleton_) tri_->calculateSkeleton(); return orientation_; } inline void Dim2Triangle::writeTextShort(std::ostream& out) const { out << "Triangle"; if (desc_.length() > 0) out << ": " << desc_; } } // namespace regina #endif regina-4.96/engine/dim2/dim2triangulation.cpp000644 000765 000024 00000032620 12377776551 021077 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include #include #include "dim2/dim2triangulation.h" #include "utilities/xmlutils.h" namespace regina { Dim2Triangulation::Dim2Triangulation(const std::string& description) : calculatedSkeleton_(false) { Dim2Triangulation* attempt; if ((attempt = fromIsoSig(description))) { cloneFrom(*attempt); setPacketLabel(description); } delete attempt; } bool Dim2Triangulation::isMinimal() const { // 2-sphere: if (getEulerChar() == 2) return (triangles_.size() == 2); // Projective plane and disc: if (getEulerChar() == 1) return (triangles_.size() == (isClosed() ? 2 : 1)); // All other closed manifolds: if (isClosed()) return (vertices_.size() == 1); // All other bounded manifolds: return (vertices_.size() == boundaryComponents_.size()); } void Dim2Triangulation::swapContents(Dim2Triangulation& other) { ChangeEventSpan span1(this); ChangeEventSpan span2(&other); clearAllProperties(); other.clearAllProperties(); triangles_.swap(other.triangles_); TriangleIterator it; for (it = triangles_.begin(); it != triangles_.end(); ++it) (*it)->tri_ = this; for (it = other.triangles_.begin(); it != other.triangles_.end(); ++it) (*it)->tri_ = &other; } void Dim2Triangulation::moveContentsTo(Dim2Triangulation& dest) { ChangeEventSpan span1(this); ChangeEventSpan span2(&dest); clearAllProperties(); dest.clearAllProperties(); TriangleIterator it; for (it = triangles_.begin(); it != triangles_.end(); ++it) { // This is an abuse of NMarkedVector, since for a brief moment // each triangle belongs to both vectors triangles_ and dest.triangles_. // However, the subsequent clear() operation does not touch the // triangle markings (indices), and so we end up with the // correct result (i.e., the markings are correct for dest). (*it)->tri_ = &dest; dest.triangles_.push_back(*it); } triangles_.clear(); } void Dim2Triangulation::writeTextLong(std::ostream& out) const { if (! calculatedSkeleton_) calculateSkeleton(); out << "Size of the skeleton:\n"; out << " Triangles: " << triangles_.size() << '\n'; out << " Edges: " << edges_.size() << '\n'; out << " Vertices: " << vertices_.size() << '\n'; out << '\n'; Dim2Triangle* tri; Dim2Triangle* adjTri; unsigned triPos; int i, j; NPerm3 adjPerm; out << "Triangle gluing:\n"; out << " Triangle | glued to: (01) (02) (12)\n"; out << " ----------+--------------------------------------\n"; for (triPos=0; triPos < triangles_.size(); triPos++) { tri = triangles_[triPos]; out << " " << std::setw(4) << triPos << " | "; for (i = 2; i >= 0; --i) { out << " "; adjTri = tri->adjacentTriangle(i); if (! adjTri) out << "boundary"; else { adjPerm = tri->adjacentGluing(i); out << std::setw(3) << triangleIndex(adjTri) << " ("; for (j = 0; j < 3; ++j) { if (j == i) continue; out << adjPerm[j]; } out << ")"; } } out << '\n'; } out << '\n'; out << "Vertices:\n"; out << " Triangle | vertex: 0 1 2\n"; out << " ----------+----------------------\n"; for (triPos = 0; triPos < triangles_.size(); ++triPos) { tri = triangles_[triPos]; out << " " << std::setw(4) << triPos << " | "; for (i = 0; i < 3; ++i) out << ' ' << std::setw(3) << vertexIndex(tri->getVertex(i)); out << '\n'; } out << '\n'; out << "Edges:\n"; out << " Triangle | edge: 01 02 12\n"; out << " ----------+--------------------\n"; for (triPos = 0; triPos < triangles_.size(); ++triPos) { tri = triangles_[triPos]; out << " " << std::setw(4) << triPos << " | "; for (i = 2; i >= 0; --i) out << ' ' << std::setw(3) << edgeIndex(tri->getEdge(i)); out << '\n'; } out << '\n'; } void Dim2Triangulation::insertTriangulation(const Dim2Triangulation& X) { ChangeEventSpan span(this); unsigned long nOrig = getNumberOfTriangles(); unsigned long nX = X.getNumberOfTriangles(); unsigned long triPos; for (triPos = 0; triPos < nX; ++triPos) newTriangle(X.triangles_[triPos]->getDescription()); // Make the gluings. unsigned long adjPos; Dim2Triangle* tri; Dim2Triangle* adjTri; NPerm3 adjPerm; int edge; for (triPos = 0; triPos < nX; ++triPos) { tri = X.triangles_[triPos]; for (edge = 0; edge < 3; ++edge) { adjTri = tri->adjacentTriangle(edge); if (adjTri) { adjPos = X.triangleIndex(adjTri); adjPerm = tri->adjacentGluing(edge); if (adjPos > triPos || (adjPos == triPos && adjPerm[edge] > edge)) { triangles_[nOrig + triPos]->joinTo(edge, triangles_[nOrig + adjPos], adjPerm); } } } } } void Dim2Triangulation::insertConstruction(unsigned long nTriangles, const int adjacencies[][3], const int gluings[][3][3]) { if (nTriangles == 0) return; Dim2Triangle** tri = new Dim2Triangle*[nTriangles]; unsigned i, j; NPerm3 p; ChangeEventSpan span(this); for (i = 0; i < nTriangles; ++i) tri[i] = newTriangle(); for (i = 0; i < nTriangles; ++i) for (j = 0; j < 3; ++j) if (adjacencies[i][j] >= 0 && ! tri[i]->adjacentTriangle(j)) { p = NPerm3(gluings[i][j][0], gluings[i][j][1], gluings[i][j][2]); tri[i]->joinTo(j, tri[adjacencies[i][j]], p); } delete[] tri; } std::string Dim2Triangulation::dumpConstruction() const { std::ostringstream ans; ans << "/**\n"; if (! getPacketLabel().empty()) ans << " * 2-manifold triangulation: " << getPacketLabel() << "\n"; ans << " * Code automatically generated by dumpConstruction().\n" " */\n" "\n"; if (triangles_.empty()) { ans << "/* This triangulation is empty. No code is being generated. */\n"; return ans.str(); } ans << "/**\n" " * The following arrays describe the individual gluings of\n" " * triangle edges.\n" " */\n" "\n"; unsigned long nTriangles = triangles_.size(); Dim2Triangle* tri; NPerm3 perm; unsigned long p; int e, i; ans << "const int adjacencies[" << nTriangles << "][3] = {\n"; for (p = 0; p < nTriangles; ++p) { tri = triangles_[p]; ans << " { "; for (e = 0; e < 3; ++e) { if (tri->adjacentTriangle(e)) { ans << triangleIndex(tri->adjacentTriangle(e)); } else ans << "-1"; if (e < 2) ans << ", "; else if (p != nTriangles - 1) ans << "},\n"; else ans << "}\n"; } } ans << "};\n\n"; ans << "const int gluings[" << nTriangles << "][3][3] = {\n"; for (p = 0; p < nTriangles; ++p) { tri = triangles_[p]; ans << " { "; for (e = 0; e < 3; ++e) { if (tri->adjacentTriangle(e)) { perm = tri->adjacentGluing(e); ans << "{ "; for (i = 0; i < 3; ++i) { ans << perm[i]; if (i < 2) ans << ", "; else ans << " }"; } } else ans << "{ 0, 0, 0 }"; if (e < 2) ans << ", "; else if (p != nTriangles - 1) ans << " },\n"; else ans << " }\n"; } } ans << "};\n\n"; ans << "/**\n" " * The following code actually constructs a 2-manifold triangulation\n" " * based on the information stored in the arrays above.\n" " */\n" "\n" "Dim2Triangulation tri;\n" "tri.insertConstruction(" << nTriangles << ", adjacencies, gluings);\n" "\n"; return ans.str(); } void Dim2Triangulation::writeXMLPacketData(std::ostream& out) const { using regina::xml::xmlEncodeSpecialChars; using regina::xml::xmlValueTag; // Write the triangle gluings. TriangleIterator it; Dim2Triangle* adjTri; int edge; out << " \n"; for (it = triangles_.begin(); it != triangles_.end(); ++it) { out << " getDescription()) << "\"> "; for (edge = 0; edge < 3; ++edge) { adjTri = (*it)->adjacentTriangle(edge); if (adjTri) { out << triangleIndex(adjTri) << ' ' << static_cast((*it)-> adjacentGluing(edge).getPermCode()) << ' '; } else out << "-1 -1 "; } out << "\n"; } out << " \n"; } void Dim2Triangulation::cloneFrom(const Dim2Triangulation& X) { ChangeEventSpan span(this); removeAllTriangles(); TriangleIterator it; for (it = X.triangles_.begin(); it != X.triangles_.end(); ++it) newTriangle((*it)->getDescription()); // Make the gluings. long triPos, adjPos; Dim2Triangle* tri; Dim2Triangle* adjTri; NPerm3 adjPerm; int edge; triPos = 0; for (it = X.triangles_.begin(); it != X.triangles_.end(); ++it) { tri = *it; for (edge = 0; edge < 3; ++edge) { adjTri = tri->adjacentTriangle(edge); if (adjTri) { adjPos = X.triangleIndex(adjTri); adjPerm = tri->adjacentGluing(edge); if (adjPos > triPos || (adjPos == triPos && adjPerm[edge] > edge)) { triangles_[triPos]->joinTo(edge, triangles_[adjPos], adjPerm); } } } ++triPos; } // Properties: // None yet for 2-manifold triangulations. } void Dim2Triangulation::deleteTriangles() { for (TriangleIterator it = triangles_.begin(); it != triangles_.end(); ++it) delete *it; triangles_.clear(); } void Dim2Triangulation::deleteSkeleton() { for (VertexIterator it = vertices_.begin(); it != vertices_.end(); ++it) delete *it; for (EdgeIterator it = edges_.begin(); it != edges_.end(); ++it) delete *it; for (ComponentIterator it = components_.begin(); it != components_.end(); ++it) delete *it; for (BoundaryComponentIterator it = boundaryComponents_.begin(); it != boundaryComponents_.end(); ++it) delete *it; vertices_.clear(); edges_.clear(); components_.clear(); boundaryComponents_.clear(); calculatedSkeleton_ = false; } void Dim2Triangulation::clearAllProperties() { if (calculatedSkeleton_) deleteSkeleton(); } } // namespace regina regina-4.96/engine/dim2/dim2triangulation.h000644 000765 000024 00000145350 12377775064 020547 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file dim2/dim2triangulation.h * \brief Deals with 2-manifold triangulations. */ #ifndef __DIM2TRIANGULATION_H #ifndef __DOXYGEN #define __DIM2TRIANGULATION_H #endif #include #include #include "regina-core.h" #include "generic/ngenerictriangulation.h" #include "packet/npacket.h" #include "utilities/nmarkedvector.h" #include "utilities/nproperty.h" // The following headers are necessary so that std::auto_ptr can invoke // destructors where necessary. #include "dim2/dim2isomorphism.h" // NOTE: More #includes follow after the class declarations. namespace regina { class Dim2BoundaryComponent; class Dim2Component; class Dim2Edge; class Dim2Triangle; class Dim2Triangulation; class Dim2Vertex; class NXMLDim2TriangulationReader; class NXMLPacketReader; /** * \addtogroup dim2 2-Manifold Triangulations * Triangulations of 2-manifolds. * @{ */ /** * Stores information about the 2-manifold triangulation packet. * See the general PacketInfo template notes for further details. * * \ifacespython Not present. */ template <> struct PacketInfo { typedef Dim2Triangulation Class; inline static const char* name() { return "2-Manifold Triangulation"; } }; /** * Stores the triangulation of a 2-manifold along with its * various cellular structures and other information. A 2-manifold * triangulation is built from triangular faces. * * When the triangulation is deleted, the corresponding * triangles, the cellular structure and all other properties * will be deallocated. * * Elements of the 1- and 0-skeletons (edges and vertices respectively) are * always temporary, as are components and * boundary components. Whenever a change occurs with the triangulation, * these objects will all be deleted and a new skeletal structure will be * calculated. The same is true of various other triangulation properties. */ class REGINA_API Dim2Triangulation : public NPacket, public NGenericTriangulation<2> { REGINA_PACKET(Dim2Triangulation, PACKET_DIM2TRIANGULATION) public: typedef std::vector::const_iterator TriangleIterator; /**< Used to iterate through triangles. */ typedef std::vector::const_iterator EdgeIterator; /**< Used to iterate through edges. */ typedef std::vector::const_iterator VertexIterator; /**< Used to iterate through vertices. */ typedef std::vector::const_iterator ComponentIterator; /**< Used to iterate through components. */ typedef std::vector::const_iterator BoundaryComponentIterator; /**< Used to iterate through boundary components. */ private: mutable bool calculatedSkeleton_; /**< Has the skeleton been calculated? */ NMarkedVector triangles_; /**< The triangular faces that form the triangulation. */ mutable NMarkedVector edges_; /**< The edges in the triangulation skeleton. */ mutable NMarkedVector vertices_; /**< The vertices in the triangulation skeleton. */ mutable NMarkedVector components_; /**< The components that form the triangulation. */ mutable NMarkedVector boundaryComponents_; /**< The components that form the boundary of the triangulation. */ mutable bool orientable_; /**< Is the triangulation orientable? */ public: /** * \name Constructors and Destructors */ /*@{*/ /** * Default constructor. * * Creates an empty triangulation. */ Dim2Triangulation(); /** * Copy constructor. * * Creates a new triangulation identical to the given triangulation. * The packet tree structure and packet label are \e not copied. * * @param cloneMe the triangulation to clone. */ Dim2Triangulation(const Dim2Triangulation& cloneMe); /** * "Magic" constructor that tries to find some way to interpret * the given string as a triangulation. * * At present, Regina understands the following types of strings * (and attempts to parse them in the following order): * * - isomorphism signatures (see fromIsoSig()). * * This list may grow in future versions of Regina. * * Regina will also set the packet label accordingly. * * If Regina cannot interpret the given string, this will be * left as the empty triangulation. * * @param description a string that describes a 2-manifold * triangulation. */ Dim2Triangulation(const std::string& description); /** * Destroys this triangulation. * * The constituent triangles, the cellular structure and all other * properties will also be deallocated. */ virtual ~Dim2Triangulation(); /*@}*/ /** * \name Packet Administration */ /*@{*/ virtual void writeTextShort(std::ostream& out) const; virtual void writeTextLong(std::ostream& out) const; virtual bool dependsOnParent() const; /*@}*/ /** * \name Triangles */ /*@{*/ /** * Returns the number of triangular faces in the triangulation. * * @return the number of triangles. */ unsigned long getNumberOfTriangles() const; /** * A dimension-agnostic alias for getNumberOfTriangles(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "simplex" refers to a top-dimensional simplex (which for * 2-manifold triangulations means a triangle). * * See getNumberOfTriangles() for further information. */ unsigned long getNumberOfSimplices() const; /** * Returns all triangular faces in the triangulation. * * The reference returned will remain valid for as long as the * triangulation exists, always reflecting the triangles currently * in the triangulation. * * \ifacespython This routine returns a python list. * * @return the list of all triangles. */ const std::vector& getTriangles() const; /** * A dimension-agnostic alias for getTriangles(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "simplex" refers to a top-dimensional simplex (which for * 2-manifold triangulations means a triangle). * * See getTriangles() for further information. */ const std::vector& getSimplices() const; /** * Returns the triangle with the given index number in the * triangulation. Note that triangle indexing may change when * a triangle is added or removed from the triangulation. * * @param index specifies which triangle to return; this * value should be between 0 and getNumberOfTriangles()-1 inclusive. * @return the indexth triangle in the triangulation. */ Dim2Triangle* getTriangle(unsigned long index); /** * A dimension-agnostic alias for getTriangle(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "simplex" refers to a top-dimensional simplex (which for * 2-manifold triangulations means a triangle). * * See getTriangle() for further information. */ Dim2Triangle* getSimplex(unsigned long index); /** * Returns the triangle with the given index number in the * triangulation. Note that triangle indexing may change when * a triangle is added or removed from the triangulation. * * @param index specifies which triangle to return; this * value should be between 0 and getNumberOfTriangles()-1 inclusive. * @return the indexth triangle in the triangulation. */ const Dim2Triangle* getTriangle(unsigned long index) const; /** * A dimension-agnostic alias for getTriangle(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "simplex" refers to a top-dimensional simplex (which for * 2-manifold triangulations means a triangle). * * See getTriangle() for further information. */ const Dim2Triangle* getSimplex(unsigned long index) const; /** * Returns the index of the given triangle in the triangulation. * * Note that triangle indexing may change when a triangle * is added or removed from the triangulation. * * \pre The given triangle is contained in this triangulation. * * \warning Passing a null pointer to this routine will probably * crash your program. If you are passing the result of some other * routine that \e might return null (such as * Dim2Triangle::adjacentTriangle), it might be worth explicitly * testing for null beforehand. * * @param tri specifies which triangle to find in the triangulation. * @return the index of the specified triangle, where 0 is * the first triangle, 1 is the second and so on. */ long triangleIndex(const Dim2Triangle* tri) const; /** * A dimension-agnostic alias for triangleIndex(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "simplex" refers to a top-dimensional simplex (which for * 2-manifold triangulations means a triangle). * * See triangleIndex() for further information. */ long simplexIndex(const Dim2Triangle* tri) const; /** * Creates a new triangle and adds it to this triangulation. * The new triangle will have an empty description. * All three edges of the new triangle will be boundary edges. * * The new triangle will become the last triangle in this * triangulation. * * @return the new triangle. */ Dim2Triangle* newTriangle(); /** * A dimension-agnostic alias for newTriangle(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "simplex" refers to a top-dimensional simplex (which for * 2-manifold triangulations means a triangle). * * See newTriangle() for further information. */ Dim2Triangle* newSimplex(); /** * Creates a new triangle with the given description and adds * it to this triangulation. * All three edges of the new triangle will be boundary edges. * * @param desc the description to assign to the new triangle. * @return the new triangle. */ Dim2Triangle* newTriangle(const std::string& desc); /** * A dimension-agnostic alias for newTriangle(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "simplex" refers to a top-dimensional simplex (which for * 2-manifold triangulations means a triangle). * * See newTriangle() for further information. */ Dim2Triangle* newSimplex(const std::string& desc); /** * Removes the given triangle from the triangulation. * All triangles glued to this triangle will be unglued. * The triangle will be deallocated. * * \pre The given triangle exists in the triangulation. * * @param tri the triangle to remove. */ void removeTriangle(Dim2Triangle* tri); /** * A dimension-agnostic alias for removeTriangle(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "simplex" refers to a top-dimensional simplex (which for * 2-manifold triangulations means a triangle). * * See removeTriangle() for further information. */ void removeSimplex(Dim2Triangle* tri); /** * Removes the triangle with the given index number * from the triangulation. Note that triangle indexing may * change when a triangle is added or removed from the * triangulation. * * All triangles glued to this triangle will be unglued. * The triangle will be deallocated. * * @param index specifies which triangle to remove; this * should be between 0 and getNumberOfTriangles()-1 inclusive. */ void removeTriangleAt(unsigned long index); /** * A dimension-agnostic alias for removeTriangleAt(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "simplex" refers to a top-dimensional simplex (which for * 2-manifold triangulations means a triangle). * * See removeTriangleAt() for further information. */ void removeSimplexAt(unsigned long index); /** * Removes all triangles from the triangulation. * All triangles will be deallocated. */ void removeAllTriangles(); /** * A dimension-agnostic alias for removeAllTriangles(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "simplex" refers to a top-dimensional simplex (which for * 2-manifold triangulations means a triangle). * * See removeAllTriangles() for further information. */ void removeAllSimplices(); /** * Swaps the contents of this and the given triangulation. * That is, all triangles that belong to this triangulation * will be moved to \a other, and all triangles that belong to * \a other will be moved to this triangulation. * * All Dim2Triangle pointers or references will remain valid. * * @param other the triangulation whose contents should be * swapped with this. */ void swapContents(Dim2Triangulation& other); /** * Moves the contents of this triangulation into the given * destination triangulation, without destroying any pre-existing * contents. That is, all triangles that currently belong to * \a dest will remain there, and all triangles that belong to this * triangulation will be moved across as additional * triangles in \a dest. * * All Dim2Triangle pointers or references will remain valid. * After this operation, this triangulation will be empty. * * @param dest the triangulation to which triangles should be * moved. */ void moveContentsTo(Dim2Triangulation& dest); /*@}*/ /** * \name Skeletal Queries */ /*@{*/ /** * Returns the number of boundary components in this triangulation. * * @return the number of boundary components. */ unsigned long getNumberOfBoundaryComponents() const; /** * Returns the number of components in this triangulation. * * @return the number of components. */ unsigned long getNumberOfComponents() const; /** * Returns the number of vertices in this triangulation. * * @return the number of vertices. */ unsigned long getNumberOfVertices() const; /** * Returns the number of edges in this triangulation. * * @return the number of edges. */ unsigned long getNumberOfEdges() const; /** * Returns the number of faces of the given dimension in this * triangulation. * * This template function is to assist with writing dimension-agnostic * code that can be reused to work in different dimensions. * * \pre the template argument \a dim is between 0 and 2 inclusive. * * \ifacespython Not present. * * @return the number of faces of the given dimension. */ template unsigned long getNumberOfFaces() const; /** * Returns all components of this triangulation. * * Bear in mind that each time the triangulation changes, the * components will be deleted and replaced with new * ones. Thus the objects contained in this list should be * considered temporary only. * * This reference to the list however will remain valid and * up-to-date for as long as the triangulation exists. * * \ifacespython This routine returns a python list. * * @return the list of all components. */ const std::vector& getComponents() const; /** * Returns all boundary components of this triangulation. * * Bear in mind that each time the triangulation changes, the * boundary components will be deleted and replaced with new * ones. Thus the objects contained in this list should be * considered temporary only. * * This reference to the list however will remain valid and * up-to-date for as long as the triangulation exists. * * \ifacespython This routine returns a python list. * * @return the list of all boundary components. */ const std::vector& getBoundaryComponents() const; /** * Returns all vertices of this triangulation. * * Bear in mind that each time the triangulation changes, the * vertices will be deleted and replaced with new * ones. Thus the objects contained in this list should be * considered temporary only. * * This reference to the list however will remain valid and * up-to-date for as long as the triangulation exists. * * \ifacespython This routine returns a python list. * * @return the list of all vertices. */ const std::vector& getVertices() const; /** * Returns all edges of this triangulation. * * Bear in mind that each time the triangulation changes, the * edges will be deleted and replaced with new * ones. Thus the objects contained in this list should be * considered temporary only. * * This reference to the list however will remain valid and * up-to-date for as long as the triangulation exists. * * \ifacespython This routine returns a python list. * * @return the list of all edges. */ const std::vector& getEdges() const; /** * Returns the requested triangulation component. * * Bear in mind that each time the triangulation changes, the * components will be deleted and replaced with new * ones. Thus this object should be considered temporary only. * * @param index the index of the desired component, ranging from 0 * to getNumberOfComponents()-1 inclusive. * @return the requested component. */ Dim2Component* getComponent(unsigned long index) const; /** * Returns the requested triangulation boundary component. * * Bear in mind that each time the triangulation changes, the * boundary components will be deleted and replaced with new * ones. Thus this object should be considered temporary only. * * @param index the index of the desired boundary component, ranging * from 0 to getNumberOfBoundaryComponents()-1 inclusive. * @return the requested boundary component. */ Dim2BoundaryComponent* getBoundaryComponent(unsigned long index) const; /** * Returns the requested triangulation vertex. * * Bear in mind that each time the triangulation changes, the * vertices will be deleted and replaced with new * ones. Thus this object should be considered temporary only. * * @param index the index of the desired vertex, ranging from 0 * to getNumberOfVertices()-1 inclusive. * @return the requested vertex. */ Dim2Vertex* getVertex(unsigned long index) const; /** * Returns the requested triangulation edge. * * Bear in mind that each time the triangulation changes, the * edges will be deleted and replaced with new * ones. Thus this object should be considered temporary only. * * @param index the index of the desired edge, ranging from 0 * to getNumberOfEdges()-1 inclusive. * @return the requested edge. */ Dim2Edge* getEdge(unsigned long index) const; /** * Returns the index of the given component in the triangulation. * * \pre The given component belongs to this triangulation. * * \warning Passing a null pointer to this routine will probably * crash your program. * * @param component specifies which component to find in the * triangulation. * @return the index of the specified component, where 0 is the first * component, 1 is the second and so on. */ long componentIndex(const Dim2Component* component) const; /** * Returns the index of the given boundary component * in the triangulation. * * \pre The given boundary component belongs to this triangulation. * * \warning Passing a null pointer to this routine will probably * crash your program. * * @param bc specifies which boundary component to find in the * triangulation. * @return the index of the specified boundary component, * where 0 is the first boundary component, 1 is the second and so on. */ long boundaryComponentIndex(const Dim2BoundaryComponent* bc) const; /** * Returns the index of the given vertex in the triangulation. * * \pre The given vertex belongs to this triangulation. * * \warning Passing a null pointer to this routine will probably * crash your program. * * @param vertex specifies which vertex to find in the triangulation. * @return the index of the specified vertex, where 0 is the first * vertex, 1 is the second and so on. */ long vertexIndex(const Dim2Vertex* vertex) const; /** * Returns the index of the given edge in the triangulation. * * \pre The given edge belongs to this triangulation. * * \warning Passing a null pointer to this routine will probably * crash your program. * * @param edge specifies which edge to find in the triangulation. * @return the index of the specified edge, where 0 is the first * edge, 1 is the second and so on. */ long edgeIndex(const Dim2Edge* edge) const; /*@}*/ /** * \name Isomorphism Testing */ /*@{*/ using NGenericTriangulation<2>::isIdenticalTo; using NGenericTriangulation<2>::isIsomorphicTo; using NGenericTriangulation<2>::isContainedIn; using NGenericTriangulation<2>::findAllIsomorphisms; using NGenericTriangulation<2>::findAllSubcomplexesIn; using NGenericTriangulation<2>::makeCanonical; /*@}*/ /** * \name Basic Properties */ /*@{*/ using NGenericTriangulation<2>::isEmpty; /** * Always returns \c true. * * This routine determines if this triangulation is valid; however, * there is nothing that can go wrong with vertex links in 2-manifold * triangulations, and so this routine always returns \c true. * * This no-op routine is provided for consistency with higher * dimensional triangulations, and to assist with writing * dimension-agnostic code. * * @return \c true. */ bool isValid() const; /** * Returns the Euler characteristic of this triangulation. * This will be evaluated as \a V-E+F. * * @return the Euler characteristic of this triangulation. */ long getEulerChar() const; /** * Determines if this triangulation is closed. * This is the case if and only if it has no boundary components. * * @return \c true if and only if this triangulation is closed. */ bool isClosed() const; /** * Determines if this triangulation has any boundary edges. * * This routine is redundant in dimension two, since it returns * \c true if and only if isClosed() returns \c false. * It is provided simply for compatibility with higher-dimensional * triangulation classes. * * @return \c true if and only if there are boundary edges. */ bool hasBoundaryEdges() const; /** * Returns the number of boundary edges in this triangulation. * * @return the total number of boundary edges. */ unsigned long getNumberOfBoundaryEdges() const; /** * Determines if this triangulation is orientable. * * @return \c true if and only if this triangulation is orientable. */ bool isOrientable() const; /** * Determines if this triangulation is connected. * * @return \c true if and only if this triangulation is connected. */ bool isConnected() const; /** * Always returns \c false. * * This routine determines if this triangulation is ideal (has a * non-trivial vertex link); however, every vertex link in a * 2-manifold triangulation is either the interval or the * circle, and so ideal triangulations cannot exist. * Therefore this routine always returns \c false. * * This no-op routine is provided for consistency with higher * dimensional triangulations, and to assist with writing * dimension-agnostic code. * * @return \c false. */ bool isIdeal() const; /** * Determines whether this is a minimal triangulation of the * underlying 2-manifold; that is, it uses the fewest possible * triangles. * * Testing for minimality is simple in two dimensions (unlike * higher dimensions, where it becomes extremely difficult). * With the exception of the sphere, disc and projective plane * (which require a minimum of 2, 1 and 2 triangles respectively), * a closed triangulation is minimal if and only if it has one * vertex, and a bounded triangulation is minimal if and only if * it has one vertex per boundary component and no internal vertices. * * The proof is based on a simple Euler characteristic calculation, * whereby the number of triangles T is * T = 2Vi + Vb - 2C, where Vi and Vb * are the number of internal and boundary vertices respectively, * and where C is the Euler characteristic of the * underlying manifold. * * @return \c true if and only if this is a minimal triangulation. */ bool isMinimal() const; /*@}*/ /** * \name Skeletal Transformations */ /*@{*/ /** * Checks the eligibility of and/or performs a 1-3 move * upon the given triangle. * This involves replacing one triangle with three triangles: * each new triangle runs from one edge of * the original triangle to a new common internal degree three vertex. * * This move can always be performed. The \a check argument is * present (as for other moves), but is simply ignored (since * the move is always legal). The \a perform argument is also * present for consistency with other moves, but if it is set to * \c false then this routine does nothing and returns no useful * information. * * Note that after performing this move, all skeletal objects * (edges, components, etc.) will be reconstructed, which means * any pointers to old skeletal objects (such as the argument \a t) * can no longer be used. * * \pre The given triangle is a triangle of this triangulation. * * @param t the triangle about which to perform the move. * @param check this argument is ignored, since this move is * always legal (see the notes above). * @param perform \c true if we are to perform the move * (defaults to \c true). * @return \c true always. */ bool oneThreeMove(Dim2Triangle* t, bool check = true, bool perform = true); /*@}*/ /** * \name Building Triangulations */ /*@{*/ /** * Inserts a copy of the given triangulation into this triangulation. * * The new triangles will be inserted into this triangulation * in the order in which they appear in the given triangulation, * and the numbering of their vertices (0-2) will not change. * They will be given the same descriptions as appear in the * given triangulation. * * @param source the triangulation whose copy will be inserted. */ void insertTriangulation(const Dim2Triangulation& source); /** * Inserts into this triangulation a set of triangles and their * gluings as described by the given integer arrays. * * This routine is provided to make it easy to hard-code a * medium-sized triangulation in a C++ source file. All of the * pertinent data can be hard-coded into a pair of integer arrays at * the beginning of the source file, avoiding an otherwise tedious * sequence of many joinTo() calls. * * An additional \a nTriangles triangles will be inserted into * this triangulation. The relationships between these triangles * should be stored in the two arrays as follows. Note that the * new triangles are numbered from 0 to (\a nTriangles - 1), and * individual triangle edges are numbered from 0 to 2. * * The \a adjacencies array describes which triangle edges are * joined to which others. Specifically, adjacencies[f][e] * should contain the number of the triangle joined to edge \a e * of triangle \a f. If this edge is to be left as a * boundary edge, adjacencies[f][e] should be -1. * * The \a gluings array describes the particular gluing permutations * used when joining these triangle edges together. Specifically, * gluings[f][e][0..2] should describe the permutation * used to join edge \a e of triangle \a f to its adjacent * triangle. These three integers should be 0, 1 and 2 in some * order, so that gluings[f][e][i] contains the image of * \a i under this permutation. If edge \a e of triangle \a f * is to be left as a boundary edge, gluings[f][e][0..2] * may contain anything (and will be duly ignored). * * It is the responsibility of the caller of this routine to * ensure that the given arrays are correct and consistent. * No error checking will be performed by this routine. * * Note that, for an existing triangulation, dumpConstruction() * will output a pair of C++ arrays that can be copied into a * source file and used to reconstruct the triangulation via * this routine. * * \ifacespython Not present. * * @param nTriangles the number of additional triangles to insert. * @param adjacencies describes which of the new triangle edges * are to be identified. This array must have initial * dimension at least \a nTriangles. * @param gluings describes the specific gluing permutations by * which these new triangle edges should be identified. This * array must also have initial dimension at least \a nTriangles. */ void insertConstruction(unsigned long nTriangles, const int adjacencies[][3], const int gluings[][3][3]); /*@}*/ /** * \name Exporting Triangulations */ /*@{*/ using NGenericTriangulation<2>::isoSig; /** * Returns C++ code that can be used with insertConstruction() * to reconstruct this triangulation. * * The code produced will consist of the following: * * - the declaration and initialisation of two integer arrays, * describing the triangle gluings in this trianguation; * - two additional lines that declare a new Dim2Triangulation and * call insertConstruction() to rebuild this triangulation. * * The main purpose of this routine is to generate the two integer * arrays, which can be tedious and error-prone to code up by hand. * * Note that the number of lines of code produced grows linearly * with the number of triangles. If this triangulation is very * large, the returned string will be very large as well. * * @return the C++ code that was generated. */ std::string dumpConstruction() const; /*@}*/ /** * \name Importing Triangulations */ /*@{*/ using NGenericTriangulation<2>::fromIsoSig; using NGenericTriangulation<2>::isoSigComponentSize; /*@}*/ static NXMLPacketReader* getXMLReader(NPacket* parent, NXMLTreeResolver& resolver); protected: virtual NPacket* internalClonePacket(NPacket* parent) const; virtual void writeXMLPacketData(std::ostream& out) const; /** * Turns this triangulation into a clone of the given triangulation. * The tree structure and label of this triangulation are not touched. * * @param from the triangulation from which this triangulation * will be cloned. */ void cloneFrom(const Dim2Triangulation& from); private: void deleteTriangles(); /**< Deallocates all triangles and empties the list. */ void deleteSkeleton(); /**< Deallocates all skeletal objects and empties all corresponding lists. */ /** * Clears any calculated properties and declares them all * unknown. All dynamic memory used for storing known * properties is deallocated. * * In most cases this routine is followed immediately by firing * a packet change event. */ virtual void clearAllProperties(); /** * Recalculates vertices, edges, components and * boundary components, as well as various other skeletal properties. * All appropriate lists are filled. * * \pre All skeletal lists are empty. */ void calculateSkeleton() const; /** * Internal to calculateSkeleton(). See the comments within * calculateSkeleton() for precisely what this routine does. */ void calculateComponents() const; /** * Internal to calculateSkeleton(). See the comments within * calculateSkeleton() for precisely what this routine does. */ void calculateVertices() const; /** * Internal to calculateSkeleton(). See the comments within * calculateSkeleton() for precisely what this routine does. */ void calculateBoundary() const; /** * Determines if an isomorphic copy of this triangulation is * contained within the given triangulation. * * If the argument \a completeIsomorphism is \c true, the * isomorphism must be onto and boundary complete. * That is, this triangulation must be combinatorially * isomorphic to the given triangulation. * * If the argument \a completeIsomorphism is \c false, the * isomorphism may be boundary incomplete and may or may not be * onto. That is, this triangulation must appear as a * subcomplex of the given triangulation, possibly with some * original boundary edges joined to new triangles. * * See the Dim2Isomorphism class notes for further details * regarding boundary complete and boundary incomplete * isomorphisms. * * The isomorphisms found, if any, will be appended to the * list \a results. This list will not be emptied before * calculations begin. All isomorphisms will be newly created, * and the caller of this routine is responsible for destroying * them. * * If \a firstOnly is passed as \c true, only the first * isomorphism found (if any) will be returned, after which the * routine will return immediately. Otherwise all isomorphisms * will be returned. * * @param other the triangulation in which to search for an * isomorphic copy of this triangulation. * @param results the list in which any isomorphisms found will * be stored. * @param completeIsomorphism \c true if isomorphisms must be * onto and boundary complete, or \c false if neither of these * restrictions should be imposed. * @param firstOnly \c true if only one isomorphism should be * returned (if any), or \c false if all isomorphisms should be * returned. * @return the total number of isomorphisms found. */ unsigned long findIsomorphisms(const Dim2Triangulation& other, std::list& results, bool completeIsomorphism, bool firstOnly) const; /** * Internal to findIsomorphisms(). * * Examines properties of the given triangle to find any * immediate evidence that \a src may not map to \a dest in a * boundary complete isomorphism (in which the vertices of \a src * are mapped to the vertices of \a dest according to the * permutation \a p). * * In particular, the degrees of vertices are examined. * * @param src the first of the two triangles to examine. * @param dest the second of the two triangles to examine. * @param p the permutation under which the vertices of \a src * must map to the vertices of \a dest. * @return \c true if no immediate incompatibilities between the * triangles were found, or \c false if properties of the * triangles were found that differ between \a src and \a dest. */ static bool compatibleTriangles(Dim2Triangle* src, Dim2Triangle* dest, NPerm3 p); friend class regina::NGenericTriangulation<2>; friend class regina::Dim2Triangle; friend class regina::NXMLDim2TriangulationReader; }; /*@}*/ } // namespace regina // Some more headers that are required for inline functions: #include "dim2/dim2triangle.h" #include "dim2/dim2edge.h" #include "dim2/dim2vertex.h" #include "dim2/dim2component.h" #include "dim2/dim2boundarycomponent.h" namespace regina { // Inline functions for Dim2Triangulation inline Dim2Triangulation::Dim2Triangulation() : NPacket(), calculatedSkeleton_(false) { } inline Dim2Triangulation::Dim2Triangulation(const Dim2Triangulation& cloneMe) : NPacket(), calculatedSkeleton_(false) { cloneFrom(cloneMe); } inline Dim2Triangulation::~Dim2Triangulation() { clearAllProperties(); deleteTriangles(); } inline void Dim2Triangulation::writeTextShort(std::ostream& out) const { out << "Triangulation with " << triangles_.size() << (triangles_.size() == 1 ? " triangle" : " triangles"); } inline bool Dim2Triangulation::dependsOnParent() const { return false; } inline unsigned long Dim2Triangulation::getNumberOfTriangles() const { return triangles_.size(); } inline unsigned long Dim2Triangulation::getNumberOfSimplices() const { return triangles_.size(); } inline const std::vector& Dim2Triangulation::getTriangles() const { return (const std::vector&)(triangles_); } inline const std::vector& Dim2Triangulation::getSimplices() const { return (const std::vector&)(triangles_); } inline Dim2Triangle* Dim2Triangulation::getTriangle(unsigned long index) { return triangles_[index]; } inline Dim2Triangle* Dim2Triangulation::getSimplex(unsigned long index) { return triangles_[index]; } inline const Dim2Triangle* Dim2Triangulation::getTriangle(unsigned long index) const { return triangles_[index]; } inline const Dim2Triangle* Dim2Triangulation::getSimplex(unsigned long index) const { return triangles_[index]; } inline long Dim2Triangulation::triangleIndex(const Dim2Triangle* tri) const { return tri->markedIndex(); } inline long Dim2Triangulation::simplexIndex(const Dim2Triangle* tri) const { return tri->markedIndex(); } inline Dim2Triangle* Dim2Triangulation::newTriangle() { ChangeEventSpan span(this); Dim2Triangle* tri = new Dim2Triangle(this); triangles_.push_back(tri); clearAllProperties(); return tri; } inline Dim2Triangle* Dim2Triangulation::newSimplex() { return newTriangle(); } inline Dim2Triangle* Dim2Triangulation::newTriangle(const std::string& desc) { ChangeEventSpan span(this); Dim2Triangle* tri = new Dim2Triangle(desc, this); triangles_.push_back(tri); clearAllProperties(); return tri; } inline Dim2Triangle* Dim2Triangulation::newSimplex(const std::string& desc) { return newTriangle(desc); } inline void Dim2Triangulation::removeTriangle(Dim2Triangle* tri) { ChangeEventSpan span(this); tri->isolate(); triangles_.erase(triangles_.begin() + triangleIndex(tri)); delete tri; clearAllProperties(); } inline void Dim2Triangulation::removeSimplex(Dim2Triangle* tri) { removeTriangle(tri); } inline void Dim2Triangulation::removeTriangleAt(unsigned long index) { ChangeEventSpan span(this); Dim2Triangle* ans = triangles_[index]; ans->isolate(); triangles_.erase(triangles_.begin() + index); delete ans; clearAllProperties(); } inline void Dim2Triangulation::removeSimplexAt(unsigned long index) { removeTriangleAt(index); } inline void Dim2Triangulation::removeAllTriangles() { ChangeEventSpan span(this); deleteTriangles(); clearAllProperties(); } inline void Dim2Triangulation::removeAllSimplices() { removeAllTriangles(); } inline unsigned long Dim2Triangulation::getNumberOfBoundaryComponents() const { if (! calculatedSkeleton_) calculateSkeleton(); return boundaryComponents_.size(); } inline unsigned long Dim2Triangulation::getNumberOfComponents() const { if (! calculatedSkeleton_) calculateSkeleton(); return components_.size(); } inline unsigned long Dim2Triangulation::getNumberOfVertices() const { if (! calculatedSkeleton_) calculateSkeleton(); return vertices_.size(); } inline unsigned long Dim2Triangulation::getNumberOfEdges() const { if (! calculatedSkeleton_) calculateSkeleton(); return edges_.size(); } template <> inline unsigned long Dim2Triangulation::getNumberOfFaces<0>() const { return getNumberOfVertices(); } template <> inline unsigned long Dim2Triangulation::getNumberOfFaces<1>() const { return getNumberOfEdges(); } template <> inline unsigned long Dim2Triangulation::getNumberOfFaces<2>() const { return getNumberOfTriangles(); } inline const std::vector& Dim2Triangulation::getComponents() const { if (! calculatedSkeleton_) calculateSkeleton(); return (const std::vector&)(components_); } inline const std::vector& Dim2Triangulation::getBoundaryComponents() const { if (! calculatedSkeleton_) calculateSkeleton(); return (const std::vector&)(boundaryComponents_); } inline const std::vector& Dim2Triangulation::getVertices() const { if (! calculatedSkeleton_) calculateSkeleton(); return (const std::vector&)(vertices_); } inline const std::vector& Dim2Triangulation::getEdges() const { if (! calculatedSkeleton_) calculateSkeleton(); return (const std::vector&)(edges_); } inline Dim2Component* Dim2Triangulation::getComponent(unsigned long index) const { if (! calculatedSkeleton_) calculateSkeleton(); return components_[index]; } inline Dim2BoundaryComponent* Dim2Triangulation::getBoundaryComponent( unsigned long index) const { if (! calculatedSkeleton_) calculateSkeleton(); return boundaryComponents_[index]; } inline Dim2Vertex* Dim2Triangulation::getVertex(unsigned long index) const { if (! calculatedSkeleton_) calculateSkeleton(); return vertices_[index]; } inline Dim2Edge* Dim2Triangulation::getEdge(unsigned long index) const { if (! calculatedSkeleton_) calculateSkeleton(); return edges_[index]; } inline long Dim2Triangulation::componentIndex(const Dim2Component* component) const { return component->markedIndex(); } inline long Dim2Triangulation::boundaryComponentIndex( const Dim2BoundaryComponent* boundaryComponent) const { return boundaryComponent->markedIndex(); } inline long Dim2Triangulation::vertexIndex(const Dim2Vertex* vertex) const { return vertex->markedIndex(); } inline long Dim2Triangulation::edgeIndex(const Dim2Edge* edge) const { return edge->markedIndex(); } inline bool Dim2Triangulation::isValid() const { return true; } inline long Dim2Triangulation::getEulerChar() const { if (! calculatedSkeleton_) calculateSkeleton(); // Cast away the unsignedness of std::vector::size(). return static_cast(vertices_.size()) - static_cast(edges_.size()) + static_cast(triangles_.size()); } inline bool Dim2Triangulation::isClosed() const { if (! calculatedSkeleton_) calculateSkeleton(); return boundaryComponents_.empty(); } inline bool Dim2Triangulation::hasBoundaryEdges() const { return ! isClosed(); } inline unsigned long Dim2Triangulation::getNumberOfBoundaryEdges() const { if (! calculatedSkeleton_) calculateSkeleton(); return 2 * edges_.size() - 3 * triangles_.size(); } inline bool Dim2Triangulation::isOrientable() const { if (! calculatedSkeleton_) calculateSkeleton(); return orientable_; } inline bool Dim2Triangulation::isIdeal() const { return false; } inline bool Dim2Triangulation::isConnected() const { if (! calculatedSkeleton_) calculateSkeleton(); return (components_.size() <= 1); } inline NPacket* Dim2Triangulation::internalClonePacket(NPacket*) const { return new Dim2Triangulation(*this); } } // namespace regina #endif regina-4.96/engine/dim2/dim2vertex.cpp000644 000765 000024 00000005267 12377776551 017543 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "dim2/dim2vertex.h" namespace regina { void Dim2Vertex::writeTextLong(std::ostream& out) const { writeTextShort(out); out << std::endl; out << "Appears as:" << std::endl; std::deque::const_iterator it; for (it = emb_.begin(); it != emb_.end(); ++it) out << " " << it->getTriangle()->markedIndex() << " (" << it->getVertex() << ')' << std::endl; } } // namespace regina regina-4.96/engine/dim2/dim2vertex.h000644 000765 000024 00000031027 12377775065 017200 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file dim2/dim2vertex.h * \brief Deals with vertices in a 2-manifold triangulation. */ #ifndef __DIM2VERTEX_H #ifndef __DOXYGEN #define __DIM2VERTEX_H #endif #include #include "regina-core.h" #include "shareableobject.h" #include "maths/nperm3.h" #include "utilities/nmarkedvector.h" // NOTE: More #includes follow after the class declarations. namespace regina { class Dim2BoundaryComponent; class Dim2Component; class Dim2Triangle; class Dim2Triangulation; /** * \weakgroup dim2 * @{ */ /** * Details how a vertex in the skeleton of a 2-manifold triangulation forms * part of an individual triangle. */ class REGINA_API Dim2VertexEmbedding { private: Dim2Triangle* triangle_; /**< The triangle in which this vertex is contained. */ int vertex_; /**< The vertex number of the triangle that is this vertex. */ public: /** * Default constructor. The embedding descriptor created is * unusable until it has some data assigned to it using * operator =. * * \ifacespython Not present. */ Dim2VertexEmbedding(); /** * Creates an embedding descriptor containing the given data. * * @param tri the triangle in which this vertex is contained. * @param vertex the vertex number of \a tri that is this vertex. */ Dim2VertexEmbedding(Dim2Triangle* tri, int vertex); /** * Creates an embedding descriptor containing the same data as * the given embedding descriptor. * * @param cloneMe the embedding descriptor to clone. */ Dim2VertexEmbedding(const Dim2VertexEmbedding& cloneMe); /** * Assigns to this embedding descriptor the same data as is * contained in the given embedding descriptor. * * @param cloneMe the embedding descriptor to clone. */ Dim2VertexEmbedding& operator =(const Dim2VertexEmbedding& cloneMe); /** * Returns the triangle in which this vertex is contained. * * @return the triangle. */ Dim2Triangle* getTriangle() const; /** * Returns the vertex number within getTriangle() that is this vertex. * * @return the vertex number that is this vertex. */ int getVertex() const; /** * Returns a permutation that maps 0 to the vertex number within * getTriangle() that is this vertex. This permutation also maps * (1,2) to the two remaining triangle vertices in a manner that * preserves orientation as you walk around the vertex. * See Dim2Triangle::getVertexMapping() for details. * * @return a permutation that maps 0 to the corresponding * vertex number of getTriangle(). */ NPerm3 getVertices() const; /** * Tests whether this and the given embedding are identical. * Here "identical" means that they refer to the same vertex of * the same triangle. * * @param rhs the embedding to compare with this. * @return \c true if and only if both embeddings are identical. */ bool operator == (const Dim2VertexEmbedding& rhs) const; /** * Tests whether this and the given embedding are different. * Here "different" means that they do not refer to the same vertex of * the same triangle. * * @param rhs the embedding to compare with this. * @return \c true if and only if both embeddings are identical. */ bool operator != (const Dim2VertexEmbedding& rhs) const; }; /** * Represents a vertex in the skeleton of a 2-manifold triangulation. * Vertices are highly temporary; once a triangulation changes, all its * vertex objects will be deleted and new ones will be created. */ class REGINA_API Dim2Vertex : public ShareableObject, public NMarkedElement { private: std::deque emb_; /**< A list of descriptors telling how this vertex forms a part of each individual triangle that it belongs to. */ Dim2Component* component_; /**< The component that this vertex is a part of. */ Dim2BoundaryComponent* boundaryComponent_; /**< The boundary component that this vertex is a part of, or 0 if this vertex is internal. */ public: /** * Returns the index of this vertex in the underlying * triangulation. This is identical to calling * getTriangulation()->vertexIndex(this). * * @return the index of this vertex. */ unsigned long index() const; /** * Returns the list of descriptors detailing how this vertex forms * a part of various triangles in the triangulation. * Note that if this vertex represents multiple vertices of a * particular triangle, then there will be multiple embedding * descriptors in the list regarding that triangle. * * \ifacespython This routine returns a python list. * * @return the list of embedding descriptors. * @see Dim2VertexEmbedding */ const std::deque& getEmbeddings() const; /** * Returns the number of descriptors in the list returned by * getEmbeddings(). Note that this is identical to getDegree(). * * @return the number of embedding descriptors. */ unsigned long getNumberOfEmbeddings() const; /** * Returns the requested descriptor from the list returned by * getEmbeddings(). * * @param index the index of the requested descriptor. This * should be between 0 and getNumberOfEmbeddings()-1 inclusive. * @return the requested embedding descriptor. */ const Dim2VertexEmbedding& getEmbedding(unsigned long index) const; /** * Returns the triangulation to which this vertex belongs. * * @return the triangulation containing this vertex. */ Dim2Triangulation* getTriangulation() const; /** * Returns the component of the triangulation to which this * vertex belongs. * * @return the component containing this vertex. */ Dim2Component* getComponent() const; /** * Returns the boundary component of the triangulation to which * this vertex belongs. * * @return the boundary component containing this vertex, * or 0 if this vertex is not on the boundary of the triangulation. */ Dim2BoundaryComponent* getBoundaryComponent() const; /** * Returns the degree of this vertex. Note that this is * identical to getNumberOfEmbeddings(). * * @return the degree of this vertex. */ unsigned long getDegree() const; /** * Determines if this vertex lies on the boundary of the * triangulation. * * @return \c true if and only if this vertex lies on the boundary. */ bool isBoundary() const; void writeTextShort(std::ostream& out) const; void writeTextLong(std::ostream& out) const; private: /** * Creates a new vertex and marks it as belonging to the * given triangulation component. * * @param component the triangulation component to which this * vertex belongs. */ Dim2Vertex(Dim2Component* component); friend class Dim2Triangulation; /**< Allow access to private members. */ }; /*@}*/ } // namespace regina // Some more headers that are required for inline functions: #include "dim2/dim2triangle.h" namespace regina { // Inline functions for Dim2VertexEmbedding inline Dim2VertexEmbedding::Dim2VertexEmbedding() : triangle_(0) { } inline Dim2VertexEmbedding::Dim2VertexEmbedding(Dim2Triangle* tri, int vertex) : triangle_(tri), vertex_(vertex) { } inline Dim2VertexEmbedding::Dim2VertexEmbedding( const Dim2VertexEmbedding& cloneMe) : triangle_(cloneMe.triangle_), vertex_(cloneMe.vertex_) { } inline Dim2VertexEmbedding& Dim2VertexEmbedding::operator = (const Dim2VertexEmbedding& cloneMe) { triangle_ = cloneMe.triangle_; vertex_ = cloneMe.vertex_; return *this; } inline Dim2Triangle* Dim2VertexEmbedding::getTriangle() const { return triangle_; } inline int Dim2VertexEmbedding::getVertex() const { return vertex_; } inline bool Dim2VertexEmbedding::operator == (const Dim2VertexEmbedding& other) const { return ((triangle_ == other.triangle_) && (vertex_ == other.vertex_)); } inline bool Dim2VertexEmbedding::operator != (const Dim2VertexEmbedding& other) const { return ((triangle_ != other.triangle_) || (vertex_ != other.vertex_)); } // Inline functions for Dim2Vertex inline Dim2Vertex::Dim2Vertex(Dim2Component* component) : component_(component), boundaryComponent_(0) { } inline unsigned long Dim2Vertex::index() const { return markedIndex(); } inline const std::deque& Dim2Vertex::getEmbeddings() const { return emb_; } inline unsigned long Dim2Vertex::getNumberOfEmbeddings() const { return emb_.size(); } inline const Dim2VertexEmbedding& Dim2Vertex::getEmbedding(unsigned long index) const { return emb_[index]; } inline NPerm3 Dim2VertexEmbedding::getVertices() const { return triangle_->getVertexMapping(vertex_); } inline Dim2Triangulation* Dim2Vertex::getTriangulation() const { return emb_.front().getTriangle()->getTriangulation(); } inline Dim2Component* Dim2Vertex::getComponent() const { return component_; } inline Dim2BoundaryComponent* Dim2Vertex::getBoundaryComponent() const { return boundaryComponent_; } inline unsigned long Dim2Vertex::getDegree() const { return emb_.size(); } inline bool Dim2Vertex::isBoundary() const { return (boundaryComponent_ != 0); } inline void Dim2Vertex::writeTextShort(std::ostream& out) const { out << (boundaryComponent_ ? "Boundary " : "Internal ") << "vertex of degree " << emb_.size(); } } // namespace regina #endif regina-4.96/engine/dim2/isomorphic.cpp000644 000765 000024 00000037246 12377776552 017631 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include "dim2/dim2isomorphism.h" #include "dim2/dim2triangulation.h" namespace regina { unsigned long Dim2Triangulation::findIsomorphisms( const Dim2Triangulation& other, std::list& results, bool completeIsomorphism, bool firstOnly) const { if (! calculatedSkeleton_) calculateSkeleton(); if (! other.calculatedSkeleton_) other.calculateSkeleton(); // Deal with the empty triangulation first. if (triangles_.empty()) { if (completeIsomorphism && ! other.triangles_.empty()) return 0; results.push_back(new Dim2Isomorphism(0)); return 1; } // Basic property checks. Unfortunately, if we allow boundary // incomplete isomorphisms then we can't test that many properties. if (completeIsomorphism) { // Must be boundary complete, 1-to-1 and onto. // That is, combinatorially the two triangulations must be // identical. if (triangles_.size() != other.triangles_.size()) return 0; if (edges_.size() != other.edges_.size()) return 0; if (vertices_.size() != other.vertices_.size()) return 0; if (components_.size() != other.components_.size()) return 0; if (boundaryComponents_.size() != other.boundaryComponents_.size()) return 0; if (orientable_ ^ other.orientable_) return 0; // Test degree sequences and the like. std::map map1; std::map map2; std::map::iterator mapIt; { VertexIterator it; for (it = vertices_.begin(); it != vertices_.end(); it++) { mapIt = map1.insert( std::make_pair((*it)->getNumberOfEmbeddings(), 0)).first; (*mapIt).second++; } for (it = other.vertices_.begin(); it != other.vertices_.end(); it++) { mapIt = map2.insert( std::make_pair((*it)->getNumberOfEmbeddings(), 0)).first; (*mapIt).second++; } if (! (map1 == map2)) return 0; map1.clear(); map2.clear(); } { ComponentIterator it; for (it = components_.begin(); it != components_.end(); it++) { mapIt = map1.insert( std::make_pair((*it)->getNumberOfTriangles(), 0)).first; (*mapIt).second++; } for (it = other.components_.begin(); it != other.components_.end(); it++) { mapIt = map2.insert( std::make_pair((*it)->getNumberOfTriangles(), 0)).first; (*mapIt).second++; } if (! (map1 == map2)) return 0; map1.clear(); map2.clear(); } { BoundaryComponentIterator it; for (it = boundaryComponents_.begin(); it != boundaryComponents_.end(); it++) { mapIt = map1.insert( std::make_pair((*it)->getNumberOfEdges(), 0)).first; (*mapIt).second++; } for (it = other.boundaryComponents_.begin(); it != other.boundaryComponents_.end(); it++) { mapIt = map2.insert( std::make_pair((*it)->getNumberOfEdges(), 0)).first; (*mapIt).second++; } if (! (map1 == map2)) return 0; map1.clear(); map2.clear(); } } else { // May be boundary incomplete, and need not be onto. // Not much we can test for unfortunately. if (triangles_.size() > other.triangles_.size()) return 0; if ((! orientable_) && other.orientable_) return 0; } // Start searching for the isomorphism. // From the tests above, we are guaranteed that both triangulations // have at least one triangle. unsigned long nResults = 0; unsigned long nTriangles = triangles_.size(); unsigned long nDestTriangles = other.triangles_.size(); unsigned long nComponents = components_.size(); unsigned i; Dim2Isomorphism iso(nTriangles); for (i = 0; i < nTriangles; i++) iso.simpImage(i) = -1; // Which source component does each destination triangle correspond to? long* whichComp = new long[nDestTriangles]; std::fill(whichComp, whichComp + nDestTriangles, -1); // The image of the first source triangle of each component. The // remaining images can be derived by following gluings. unsigned long* startTri = new unsigned long[nComponents]; std::fill(startTri, startTri + nComponents, 0); int* startPerm = new int[nComponents]; std::fill(startPerm, startPerm + nComponents, 0); // The triangles whose neighbours must be processed when filling // out the current component. std::queue toProcess; // Temporary variables. unsigned long compSize; Dim2Triangle* tri; Dim2Triangle* adj; Dim2Triangle* destTri; Dim2Triangle* destAdj; unsigned long myTriIndex, adjIndex; unsigned long destTriIndex, destAdjIndex; NPerm3 triPerm, adjPerm; int edge; bool broken; long comp = 0; while (comp >= 0) { // Continue trying to find a mapping for the current component. // The next mapping to try is the one that starts with // startTri[comp] and startPerm[comp]. if (comp == static_cast(nComponents)) { // We have an isomorphism!!! results.push_back(new Dim2Isomorphism(iso)); if (firstOnly) { delete[] whichComp; delete[] startTri; delete[] startPerm; return 1; } else nResults++; // Back down to the previous component, and clear the // mapping for that previous component so we can make way // for a new one. // Since nComponents > 0, we are guaranteed that comp > 0 also. comp--; for (i = 0; i < nTriangles; i++) if (iso.simpImage(i) >= 0 && whichComp[iso.simpImage(i)] == comp) { whichComp[iso.simpImage(i)] = -1; iso.simpImage(i) = -1; } startPerm[comp]++; continue; } // Sort out the results of any previous startPerm++. if (startPerm[comp] == 6) { // Move on to the next destination triangle. startTri[comp]++; startPerm[comp] = 0; } // Be sure we're looking at a triangle we can use. compSize = components_[comp]->getNumberOfTriangles(); if (completeIsomorphism) { // Conditions: // 1) The destination triangle is unused. // 2) The component sizes match precisely. while (startTri[comp] < nDestTriangles && (whichComp[startTri[comp]] >= 0 || other.triangles_[startTri[comp]]->getComponent()-> getNumberOfTriangles() != compSize)) startTri[comp]++; } else { // Conditions: // 1) The destination triangle is unused. // 2) The destination component is at least as large as // the source component. while (startTri[comp] < nDestTriangles && (whichComp[startTri[comp]] >= 0 || other.triangles_[startTri[comp]]->getComponent()-> getNumberOfTriangles() < compSize)) startTri[comp]++; } // Have we run out of possibilities? if (startTri[comp] == nDestTriangles) { // No more possibilities for filling this component. // Move back to the previous component, and clear the // mapping for that previous component. startTri[comp] = 0; startPerm[comp] = 0; comp--; if (comp >= 0) { for (i = 0; i < nTriangles; i++) if (iso.simpImage(i) >= 0 && whichComp[iso.simpImage(i)] == comp) { whichComp[iso.simpImage(i)] = -1; iso.simpImage(i) = -1; } startPerm[comp]++; } continue; } // Try to fill the image of this component based on the selected // image of its first source triangle. // Note that there is only one way of doing this (as seen by // following adjacent triangle gluings). It either works or // it doesn't. myTriIndex = triangleIndex(components_[comp]->getTriangle(0)); whichComp[startTri[comp]] = comp; iso.simpImage(myTriIndex) = startTri[comp]; iso.facetPerm(myTriIndex) = NPerm3::S3[startPerm[comp]]; toProcess.push(myTriIndex); broken = false; while ((! broken) && (! toProcess.empty())) { myTriIndex = toProcess.front(); toProcess.pop(); tri = triangles_[myTriIndex]; triPerm = iso.facetPerm(myTriIndex); destTriIndex = iso.simpImage(myTriIndex); destTri = other.triangles_[destTriIndex]; // If we are after a complete isomorphism, we might as well // test whether the lower-dimensional face degrees match. if (completeIsomorphism && ! compatibleTriangles(tri, destTri, triPerm)) { broken = true; break; } for (edge = 0; edge < 3; ++edge) { adj = tri->adjacentTriangle(edge); if (adj) { // There is an adjacent source triangle. // Is there an adjacent destination triangle? destAdj = destTri->adjacentTriangle(triPerm[edge]); if (! destAdj) { broken = true; break; } // Work out what the isomorphism *should* say. adjIndex = triangleIndex(adj); destAdjIndex = other.triangleIndex(destAdj); adjPerm = destTri->adjacentGluing(triPerm[edge]) * triPerm * tri->adjacentGluing(edge).inverse(); if (iso.simpImage(adjIndex) >= 0) { // We've already decided upon an image for this // source triangle. Does it match? if (static_cast(destAdjIndex) != iso.simpImage(adjIndex) || adjPerm != iso.facetPerm(adjIndex)) { broken = true; break; } } else if (whichComp[destAdjIndex] >= 0) { // We haven't decided upon an image for this // source triangle but the destination // triangle has already been used. broken = true; break; } else { // We haven't seen either the source or the // destination triangle. whichComp[destAdjIndex] = comp; iso.simpImage(adjIndex) = destAdjIndex; iso.facetPerm(adjIndex) = adjPerm; toProcess.push(adjIndex); } } else if (completeIsomorphism) { // There is no adjacent source triangle, and we // are after a boundary complete isomorphism. // There had better be no adjacent destination // triangle also. if (destTri->adjacentTriangle(triPerm[edge])) { broken = true; break; } } } } if (! broken) { // Therefore toProcess is empty. // The image for this component was successfully filled out. // Move on to the next component. comp++; } else { // The image for this component was not successfully filled out. // Undo our partially created image, and then try another // starting image for this component. while (! toProcess.empty()) toProcess.pop(); for (i = 0; i < nTriangles; i++) if (iso.simpImage(i) >= 0 && whichComp[iso.simpImage(i)] == comp) { whichComp[iso.simpImage(i)] = -1; iso.simpImage(i) = -1; } startPerm[comp]++; } } // All out of options. delete[] whichComp; delete[] startTri; delete[] startPerm; return nResults; } bool Dim2Triangulation::compatibleTriangles( Dim2Triangle* src, Dim2Triangle* dest, NPerm3 p) { for (int vertex = 0; vertex < 3; vertex++) if (src->getVertex(vertex)->getNumberOfEmbeddings() != dest->getVertex(p[vertex])->getNumberOfEmbeddings()) return false; return true; } } // namespace regina regina-4.96/engine/dim2/nxmldim2trireader.cpp000644 000765 000024 00000014443 12377776553 021104 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "algebra/nxmlalgebrareader.h" #include "dim2/nxmldim2trireader.h" #include "utilities/stringutils.h" namespace regina { /** * A unique namespace containing various specific-task packet readers. */ namespace { /** * Reads a single triangle with its name and gluings. */ class Dim2TriangleReader : public NXMLElementReader { private: Dim2Triangulation* tri_; Dim2Triangle* triangle_; public: Dim2TriangleReader(Dim2Triangulation* tri, unsigned whichTri) : tri_(tri), triangle_(tri->getTriangles()[whichTri]) { } virtual void startElement(const std::string&, const regina::xml::XMLPropertyDict& props, NXMLElementReader*) { triangle_->setDescription(props.lookup("desc")); } virtual void initialChars(const std::string& chars) { std::vector tokens; if (basicTokenise(back_inserter(tokens), chars) != 6) return; long triIndex, permCode; NPerm3 perm; Dim2Triangle* adjTri; int adjEdge; for (int k = 0; k < 3; ++k) { if (! valueOf(tokens[2 * k], triIndex)) continue; if (! valueOf(tokens[2 * k + 1], permCode)) continue; if (triIndex < 0 || triIndex >= static_cast(tri_->getNumberOfTriangles())) continue; if (! NPerm3::isPermCode(permCode)) continue; perm.setPermCode(permCode); adjTri = tri_->getTriangles()[triIndex]; adjEdge = perm[k]; if (adjTri == triangle_ && adjEdge == k) continue; if (triangle_->adjacentTriangle(k)) continue; if (adjTri->adjacentTriangle(adjEdge)) continue; triangle_->joinTo(k, adjTri, perm); } } }; /** * Reads an entire set of triangles with their names and gluings. */ class Dim2TrianglesReader : public NXMLElementReader { private: Dim2Triangulation* tri_; unsigned readTriangles_; public: Dim2TrianglesReader(Dim2Triangulation* tri) : tri_(tri), readTriangles_(0) { } virtual void startElement(const std::string& /* tagName */, const regina::xml::XMLPropertyDict& props, NXMLElementReader*) { long nTriangles; if (valueOf(props.lookup("ntriangles"), nTriangles)) for ( ; nTriangles > 0; --nTriangles) tri_->newTriangle(); } virtual NXMLElementReader* startSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict&) { if (subTagName == "triangle") { if (readTriangles_ < tri_->getNumberOfTriangles()) return new Dim2TriangleReader(tri_, readTriangles_++); else return new NXMLElementReader(); } else return new NXMLElementReader(); } }; } NXMLElementReader* NXMLDim2TriangulationReader::startContentSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict&) { if (subTagName == "triangles") return new Dim2TrianglesReader(tri_); return new NXMLElementReader(); } void NXMLDim2TriangulationReader::endContentSubElement(const std::string&, NXMLElementReader*) { } NXMLPacketReader* Dim2Triangulation::getXMLReader(NPacket*, NXMLTreeResolver& resolver) { return new NXMLDim2TriangulationReader(resolver); } } // namespace regina regina-4.96/engine/dim2/nxmldim2trireader.h000644 000765 000024 00000007524 12377775067 020552 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file dim2/nxmldim2trireader.h * \brief Deals with parsing XML data for 4-manifold triangulation packets. */ #ifndef __NXMLDIM2TRIREADER_H #ifndef __DOXYGEN #define __NXMLDIM2TRIREADER_H #endif #include "regina-core.h" #include "packet/nxmlpacketreader.h" #include "dim2/dim2triangulation.h" namespace regina { /** * \weakgroup dim2 * @{ */ /** * An XML packet reader that reads a single 2-manifold triangulation. * * \ifacespython Not present. */ class REGINA_API NXMLDim2TriangulationReader : public NXMLPacketReader { private: Dim2Triangulation* tri_; /**< The triangulation currently being read. */ public: /** * Creates a new triangulation reader. * * @param resolver the master resolver that will be used to fix * dangling packet references after the entire XML file has been read. */ NXMLDim2TriangulationReader(NXMLTreeResolver& resolver); virtual NPacket* getPacket(); virtual NXMLElementReader* startContentSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict& subTagProps); virtual void endContentSubElement(const std::string& subTagName, NXMLElementReader* subReader); }; /*@}*/ // Inline functions for NXMLDim2TriangulationReader inline NXMLDim2TriangulationReader::NXMLDim2TriangulationReader( NXMLTreeResolver& resolver) : NXMLPacketReader(resolver), tri_(new Dim2Triangulation()) { } inline NPacket* NXMLDim2TriangulationReader::getPacket() { return tri_; } } // namespace regina #endif regina-4.96/engine/dim2/simplify.cpp000644 000765 000024 00000010111 12377776553 017270 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "dim2/dim2triangulation.h" namespace regina { bool Dim2Triangulation::oneThreeMove(Dim2Triangle* tri, bool /* check */, bool perform) { if ( !perform ) return true; // You can always do this move. ChangeEventSpan span(this); // Before we unglue, record how the adjacent triangles are glued to tri. Dim2Triangle* adjTri[3]; NPerm3 adjGlue[3]; unsigned i, j; for (i=0; i<3; i++) { adjTri[i] = tri->adjacentTriangle(i); if (adjTri[i]) adjGlue[i] = tri->adjacentGluing(i); } // Unglue the old triangle. tri->isolate(); // The new triangles. // Edge i of the old triangle will become a edge of newTri[i]. // Vertex i of newTri[i] will become the new internal vertex, and // the other two vertices of newTri[i] will keep the same vertex numbers // that they had in the old triangle. Dim2Triangle* newTri[3]; for (i = 0; i < 3; ++i) newTri[i] = newTriangle(); // Glue the new triangles to each other internally. for (i = 0; i < 3; ++i) for (j = i + 1; j < 3; ++j) newTri[i]->joinTo(j, newTri[j], NPerm3(i, j)); // Attach the new triangles to the old triangulation. for (i = 0; i < 3; ++i) { if (adjTri[i] == tri) { // The old triangle was glued to itself. // We might have already made this gluing from the other side: if (newTri[i]->adjacentTriangle(i)) continue; // Nope, do it now. newTri[i]->joinTo(i, newTri[adjGlue[i][i]], adjGlue[i]); } else if (adjTri[i]) { // The old triangle was glued elsewhere. newTri[i]->joinTo(i, adjTri[i], adjGlue[i]); } } // Delete the old triangle. removeTriangle(tri); // All done! return true; } } // namespace regina regina-4.96/engine/dim2/skeleton.cpp000644 000765 000024 00000035734 12377776554 017303 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include #include "dim2/dim2triangulation.h" namespace regina { void Dim2Triangulation::calculateSkeleton() const { // Triangulations are orientable until proven otherwise. orientable_ = true; // Set this now so that any triangle query routines do not try to // recursively recompute the skeleton again. calculatedSkeleton_ = true; // Get rid of the empty triangulation now, so that all the helper routines // can happily assume at least one triangle. if (triangles_.empty()) return; // Off we go! calculateComponents(); // Sets: // - components_ // - edges_ // - orientable_ // - Dim2Component::edges_ // - Dim2Component::orientable_ // - Dim2Triangle::component_ // - Dim2Triangle::orientation_ // - Dim2Triangle::edge_ // - Dim2Triangle::edgeMapping_ // - all Dim2Edge members except boundaryComponent_ calculateVertices(); // Sets: // - vertices_ // - Dim2Component::vertices_ // - Dim2Triangle::vertex_ // - Dim2Triangle::vertexMapping_ // - all Dim2Vertex members except boundaryComponent_ calculateBoundary(); // Sets: // - boundaryComponents_ // - Dim2Component::boundaryComponents_ // - Dim2 [ Edge, Vertex ]::boundaryComponent_ // - all Dim2BoundaryComponent members } void Dim2Triangulation::calculateComponents() const { TriangleIterator it; for (it = triangles_.begin(); it != triangles_.end(); ++it) { (*it)->component_ = 0; std::fill((*it)->edge_, (*it)->edge_ + 3, static_cast(0)); } Dim2Component* label; Dim2Triangle** stack = new Dim2Triangle*[triangles_.size()]; unsigned stackSize = 0; Dim2Triangle *loopTri, *tri, *adjTri; Dim2Edge* e; int edge, adjEdge, adjOrientation; for (it = triangles_.begin(); it != triangles_.end(); ++it) { loopTri = *it; if (loopTri->component_) continue; label = new Dim2Component(); components_.push_back(label); // Run a depth-first search from this triangle to // completely enumerate all triangles in this component. // // Since we are walking from one triangle to another via // edges, we might as well collect information on the // edges while we're at it. loopTri->component_ = label; label->triangles_.push_back(loopTri); loopTri->orientation_ = 1; stack[0] = loopTri; stackSize = 1; while (stackSize > 0) { tri = stack[--stackSize]; for (edge = 0; edge < 3; ++edge) { // Have we already checked out this edge from the other side? if (tri->edge_[edge]) continue; // Make a new edge, but leave the embeddings and // mappings until we see which side we're on. This is so // that the edges *look* as though we enumerated them in // lexicographical order (instead of via a depth-first search // through each triangulation component). e = new Dim2Edge(tri->component_); adjTri = tri->adjacentTriangle(edge); if (adjTri) { // We have an adjacent triangle. adjEdge = tri->adjacentEdge(edge); tri->edge_[edge] = e; adjTri->edge_[adjEdge] = e; // Choose an edge mapping according to which side // comes "first" lexicographically. Note that edge 2 is // really edge 01, and so is "less than" edge 0, which // is really edge 12. In short, edges get ordered in // reverse. if (tri->markedIndex() < adjTri->markedIndex() || (tri->markedIndex() == adjTri->markedIndex() && edge > adjEdge)) { // tri comes first. tri->edgeMapping_[edge] = Dim2Edge::ordering[edge]; adjTri->edgeMapping_[adjEdge] = tri->adjacentGluing(edge) * Dim2Edge::ordering[edge]; e->emb_[0] = Dim2EdgeEmbedding(tri, edge); e->emb_[1] = Dim2EdgeEmbedding(adjTri, adjEdge); } else { // adjTri comes first. adjTri->edgeMapping_[adjEdge] = Dim2Edge::ordering[adjEdge]; tri->edgeMapping_[edge] = adjTri->adjacentGluing(adjEdge) * Dim2Edge::ordering[adjEdge]; e->emb_[0] = Dim2EdgeEmbedding(adjTri, adjEdge); e->emb_[1] = Dim2EdgeEmbedding(tri, edge); } e->nEmb_ = 2; // Deal with orientations and connected components. adjOrientation = (tri->adjacentGluing(edge).sign() == 1 ? - tri->orientation_ : tri->orientation_); if (adjTri->component_) { if (adjOrientation != adjTri->orientation_) orientable_ = label->orientable_ = false; } else { // Wheee! A triangle we haven't seen before. adjTri->component_ = label; label->triangles_.push_back(adjTri); adjTri->orientation_ = adjOrientation; stack[stackSize++] = adjTri; } } else { // This is a boundary edge. tri->edge_[edge] = e; tri->edgeMapping_[edge] = Dim2Edge::ordering[edge]; e->emb_[0] = Dim2EdgeEmbedding(tri, edge); e->nEmb_ = 1; } } } } // Now run through again and number the edges (i.e., insert them // into the main list) in lexicographical order. Again, edges are // ordered in reverse. for (it = triangles_.begin(); it != triangles_.end(); ++it) { tri = *it; for (edge = 2; edge >= 0; --edge) { e = tri->edge_[edge]; if (e->nEmb_ == 2 && (e->emb_[0].getTriangle() != tri || e->emb_[0].getEdge() != edge)) continue; edges_.push_back(e); tri->component_->edges_.push_back(e); } } delete[] stack; } void Dim2Triangulation::calculateVertices() const { TriangleIterator it; int loopVtx; for (it = triangles_.begin(); it != triangles_.end(); ++it) for (loopVtx = 0; loopVtx < 3; ++loopVtx) (*it)->vertex_[loopVtx] = 0; Dim2Vertex* label; Dim2Triangle *loopTri, *tri, *adjTri; int adjVertex; NPerm3 map, adjMap; int dir, exitEdge; for (it = triangles_.begin(); it != triangles_.end(); ++it) { loopTri = *it; for (loopVtx = 2; loopVtx >= 0; --loopVtx) { if (loopTri->vertex_[loopVtx]) continue; label = new Dim2Vertex(loopTri->component_); vertices_.push_back(label); loopTri->component_->vertices_.push_back(label); // Since triangle vertices are joined together in a loop, the // depth-first search is really just a straight line in either // direction. We therefore do away with the usual stack and // just keep track of the next triangle to process in the current // direction. loopTri->vertex_[loopVtx] = label; loopTri->vertexMapping_[loopVtx] = NPerm3(loopVtx, (loopVtx + 1) % 3, (loopVtx + 2) % 3); label->emb_.push_back(Dim2VertexEmbedding(loopTri, loopVtx)); for (dir = 0; dir < 2; ++dir) { // Start at the start and walk in one particular direction. tri = loopTri; map = tri->vertexMapping_[loopVtx]; while (true) { // Move through to the next triangle. exitEdge = map[dir == 0 ? 1 : 2]; adjTri = tri->adjacentTriangle(exitEdge); if (! adjTri) break; adjMap = tri->adjacentGluing(exitEdge) * map * NPerm3(0, 2, 1); adjVertex = adjMap[0]; if (adjTri->vertex_[adjVertex]) { // We looped right around. break; } // We have not yet seen this triangle vertex. Label it. adjTri->vertex_[adjVertex] = label; adjTri->vertexMapping_[adjVertex] = adjMap; if (dir == 0) label->emb_.push_back(Dim2VertexEmbedding( adjTri, adjVertex)); else label->emb_.push_front(Dim2VertexEmbedding( adjTri, adjVertex)); tri = adjTri; map = adjMap; } } } } } void Dim2Triangulation::calculateBoundary() const { // Are there any boundary edges at all? long nBdry = 2 * edges_.size() - 3 * triangles_.size(); if (nBdry == 0) return; Dim2BoundaryComponent* label; EdgeIterator it; Dim2Triangle *tri, *adjTri; int edgeId, adjEdgeId; int vertexId, adjVertexId; Dim2Edge *edge, *adjEdge; Dim2Vertex* vertex; Dim2VertexEmbedding vertexEmb; for (it = edges_.begin(); it != edges_.end(); ++it) { edge = *it; // We only care about boundary edges that we haven't yet seen.. if (edge->nEmb_ == 2 || edge->boundaryComponent_) continue; label = new Dim2BoundaryComponent(); boundaryComponents_.push_back(label); edge->component_->boundaryComponents_.push_back(label); // Loop around from this boundary edge to // completely enumerate all edges in this boundary component. tri = edge->emb_[0].getTriangle(); edgeId = edge->emb_[0].getEdge(); vertexId = edge->emb_[0].getVertices()[0]; vertex = tri->vertex_[vertexId]; while (true) { if (! edge->boundaryComponent_) { edge->boundaryComponent_ = label; label->edges_.push_back(edge); vertex->boundaryComponent_ = label; label->vertices_.push_back(vertex); } else { // We've looped right around. break; } // Find the next edge along the boundary. // We can be clever about this. The current // boundary edge is one end of the vertex link; the // *adjacent* boundary edge must be at the other. vertexEmb = vertex->emb_.front(); if (vertexEmb.getTriangle() == tri && vertexEmb.getVertices()[0] == vertexId && vertexEmb.getVertices()[2] == edgeId) { // We are currently looking at the embedding at the // front of the list. Take the one at the back. vertexEmb = vertex->emb_.back(); adjTri = vertexEmb.getTriangle(); adjEdgeId = vertexEmb.getVertices()[1]; adjEdge = adjTri->edge_[adjEdgeId]; adjVertexId = vertexEmb.getVertices()[2]; } else { // We must be looking at the embedding at the back // of the list. Take the one at the front (which is // already stored in vertexEmb). adjTri = vertexEmb.getTriangle(); adjEdgeId = vertexEmb.getVertices()[2]; adjEdge = adjTri->edge_[adjEdgeId]; adjVertexId = vertexEmb.getVertices()[1]; // TODO: Sanity checking; remove this eventually. vertexEmb = vertex->emb_.back(); if (! (vertexEmb.getTriangle() == tri && vertexEmb.getVertices()[0] == vertexId && vertexEmb.getVertices()[1] == edgeId)) { std::cerr << "ERROR: Something has gone terribly " "wrong in computeBoundaryComponents()." << std::endl; ::exit(1); } } edge = adjEdge; tri = adjTri; edgeId = adjEdgeId; vertexId = adjVertexId; vertex = tri->vertex_[vertexId]; } } } } // namespace regina regina-4.96/engine/docs.h000644 000765 000024 00000021706 12377774107 015203 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file docs.h * \brief Contains miscellaneous documentation. */ /*! \mainpage * *

* Regina
* Software for 3-manifold topology and normal surface theory
* Copyright © 1999-2014, The Regina development team *
* * This documentation describes the functions, classes and related * entities in the C++ calculation engine, as well as how these can * be accessed through Python. * * This API documentation is written in terms of C++. * However, Python programmers can use exactly the same functions, * classes, methods and so on. If the Python version of a function * differs from the C++ version, you will see a bold Python: note * telling you how it differs. * * To start: visit the
Modules page and take * a look around, or browse through the classes regina::NTriangulation and * regina::NNormalSurfaceList. * *

Citation

* * If you find Regina useful in your research, please consider citing it as * you would any other paper that you use. A suggested form of reference is: * * Benjamin A. Burton, Ryan Budney, William Pettersson, et al., * "Regina: Software for 3-manifold topology and normal surface theory", * http://regina.sourceforge.net/ , 1999-2014. * *

Authors

* * The primary developers of Regina are: *
    *
  • Benjamin Burton <bab@debian.org>
  • *
  • Ryan Budney <rybu@uvic.ca>
  • *
  • William Pettersson <william.pettersson@gmail.com>
  • *
*

* Many others have been of assistance with this project, be it through * time, knowledge, testing or code. Please see the full list of * acknowledgements in the users' handbook. * *

Copying and Modification

* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Some of this code comes with additional permissions; see the * section below regarding online distribution. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. * *

Online Distribution

* * Regina's own source code comes with the following permissions in * addition to the GNU General Public License: * * As an exception, when this program is distributed through (i) the * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * (iii) Google Play by Google Inc., then that store may impose any * digital rights management, device limits and/or redistribution * restrictions that are required by its terms of service. * * Some third-party libraries included in Regina are not granted this * exception, and must be removed from any build that is distributed on * stores that cannot comply with the GNU General Public License (such as * Apple's App Store). See the third-party licenses below for details. * *

SnapPea and SnapPy

* * Regina includes portions of the SnapPea kernel and its successor SnapPy, * which it uses for some geometric calculations. The SnapPea kernel was * written by Jeff Weeks, and SnapPy was written by Marc Culler, Nathan * Dunfield, and others. SnapPy and the corresponding SnapPea kernel are * distributed under the terms of the GNU General Public License, version 2 * or any later version, as published by the Free Software Foundation. * *

Normaliz Library

* * Regina includes a copy of libnormaliz, which it uses to help with the * enumeration of fundamental normal surfaces. Normaliz was written by * Winfried Bruns, Bogdan Ichim and Christof Soeger. It is distributed * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your * option) any later version. * *

Orb Kernel

* * Regina includes snippets of code from Orb, for use in importing and * exporting files in Orb / Casson format. Orb is based on SnapPea * (see above) with additional code written by Damian Heard, who has also * given permission for his code to be distributed under the terms of the * GNU General Public License. */ /*! \page i18n Encodings for international strings * * As of version 4.5, Regina (finally) pays attention to character encodings. * * The calculation engine uses UTF-8 for all strings (except possibly * for filenames; see below). This means that programmers who pass * strings \e into routines must ensure that they use UTF-8, and * programmers who receive strings \e from routines may assume that * they are returned in UTF-8. Note that plain ASCII is a subset of * UTF-8, so plain ASCII text is always fine to use. * * Regina's XML data files are also stored using UTF-8. Older * versions of Regina used LATIN1 (the default for the Qt libraries) * and did not specify an encoding in the XML header; however, Regina's * file I/O routines are aware of this, and will convert older data into * UTF-8 as it is loaded into memory (the files themselves are * of course not modified). The routine versionUsesUTF8() may be * useful for programmers who need to work with older data files at a * low level. * * File \e names are a special case, since here Regina must interact with * the underlying operating system. All filenames that are passed into * routines must be presented in whatever encoding the operating system * expects; Regina will simply pass them through to the standard C/C++ file * I/O routines (such as fopen() or std::ifstream::open()) without modifying * them in any way. * * It should be noted that ancient data files that use the old binary * format (Regina 2.x, before mid-2002) only support plain ASCII text. * Support for the old binary format is likely to be removed entirely in the * very near future. * * \ifacespython Users and programmers who use the Python interface must * take special care, since Python does not pass strings around in UTF-8 * by default. * * Proper support for character encodings is quite new, and the main * author rarely uses this (being a native English speaker). If you * see Regina treating international characters in unexpected ways, * please mail the author(s) or file a bug report so the problem can be * fixed! */ regina-4.96/engine/doxygen/CMakeLists.txt000644 000765 000024 00000000136 12234011536 020267 0ustar00babstaff000000 000000 CONFIGURE_FILE ( docs.conf.in "${PROJECT_BINARY_DIR}/engine/doxygen/docs.conf" @ONLY ) regina-4.96/engine/doxygen/doc-footer.html000644 000765 000024 00000000550 12400001165 020446 0ustar00babstaff000000 000000
Copyright © 1999-2014, The Regina development team
This software is released under the GNU General Public License, with some additional permissions; see the source code for details.
For further information, or to submit a bug or other problem, please contact Ben Burton (bab@debian.org). regina-4.96/engine/doxygen/docs.conf.in000644 000765 000024 00000006565 12377774107 017771 0ustar00babstaff000000 000000 # # File docs.conf -- Doxygen configuration for Regina. # # General options PROJECT_NAME = "Regina Calculation Engine" OUTPUT_DIRECTORY = @PROJECT_BINARY_DIR@/docs/engine DISABLE_INDEX = NO EXTRACT_ALL = NO EXTRACT_PRIVATE = NO EXTRACT_STATIC = YES INLINE_INHERITED_MEMB = YES BRIEF_MEMBER_DESC = YES JAVADOC_AUTOBRIEF = YES REPEAT_BRIEF = YES ALWAYS_DETAILED_SEC = YES FULL_PATH_NAMES = YES STRIP_FROM_PATH = @PROJECT_SOURCE_DIR@/engine @PROJECT_SOURCE_DIR@ STRIP_FROM_INC_PATH = @PROJECT_SOURCE_DIR@/engine @PROJECT_SOURCE_DIR@ CLASS_DIAGRAMS = YES SOURCE_BROWSER = NO GENERATE_TODOLIST = YES GENERATE_TESTLIST = NO CASE_SENSE_NAMES = YES VERBATIM_HEADERS = NO # Aliases: ALIASES = \ "ifaces=\par Interfaces:\n" \ "ifacescpp=\par C++:\n" \ "ifacespython=\par Python:\n" \ "snappy=\par SnapPy:\n" \ "i18n=\par Internationalisation:\n" \ "proburgent=Bug (urgent):" \ "prob=Bug:" \ "problong=Bug (long-term):" \ "featureurgent=Feature (urgent):" \ "feature=Feature:" \ "featurelong=Feature (long-term):" \ "opturgent=Optimise (urgent):" \ "opt=Optimise:" \ "optlong=Optimise (long-term):" \ "tidyurgent=Tidy (urgent):" \ "tidy=Tidy:" \ "tidylong=Tidy (long-term):" \ "apinotfinal=\warning The API for this class has not yet been finalised. This means that the class interface may change in new versions of Regina, without maintaining backward compatibility. If you use this class directly in your own code, please watch the detailed changelogs upon new releases to see if you need to make changes to your code." # Warning and progress related options: QUIET = NO WARNINGS = YES WARN_IF_UNDOCUMENTED = YES # Input related options: INPUT = \ @PROJECT_SOURCE_DIR@/engine \ @PROJECT_SOURCE_DIR@/python/globalarray.h FILE_PATTERNS = *.h RECURSIVE = YES EXCLUDE = \ @PROJECT_SOURCE_DIR@/engine/utilities/nmatrix2.h \ @PROJECT_SOURCE_DIR@/engine/utilities/nmpi.h \ @PROJECT_SOURCE_DIR@/engine/utilities/nrational.h \ @PROJECT_SOURCE_DIR@/engine/enumerate/normaliz \ @PROJECT_SOURCE_DIR@/engine/foreign/casson.h \ @PROJECT_SOURCE_DIR@/engine/snappea/kernel EXCLUDE_PATTERNS = *-impl.h IMAGE_PATH = # Alphabetical index options: ALPHABETICAL_INDEX = YES IGNORE_PREFIX = N # HTML related options: GENERATE_HTML = YES HTML_OUTPUT = . HTML_FOOTER = @PROJECT_SOURCE_DIR@/engine/doxygen/doc-footer.html HTML_ALIGN_MEMBERS = YES GENERATE_HTMLHELP = NO # LaTeX related options: GENERATE_LATEX = NO # RTF related options: GENERATE_RTF = NO # Man page related options: GENERATE_MAN = NO # Preprocessor related options: ENABLE_PREPROCESSING = YES MACRO_EXPANSION = NO SEARCH_INCLUDES = YES INCLUDE_PATH = @PROJECT_SOURCE_DIR@/engine PREDEFINED = __DOXYGEN # External reference options: ALLEXTERNALS = NO PERL_PATH = /usr/bin/perl # Dot options: HAVE_DOT = NO CLASS_GRAPH = YES COLLABORATION_GRAPH = YES INCLUDE_GRAPH = YES INCLUDED_BY_GRAPH = YES GRAPHICAL_HIERARCHY = NO # Search engine options: SEARCHENGINE = NO regina-4.96/engine/engine.cpp000644 000765 000024 00000007503 12377776555 016063 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "engine.h" namespace regina { const char* getVersionString() { return PACKAGE_VERSION; } int getVersionMajor() { return PACKAGE_VERSION_MAJOR; } int getVersionMinor() { return PACKAGE_VERSION_MINOR; } bool versionUsesUTF8(const char* version) { // No version is fine. // Also any version that does not begin with 0-4 is fine. if (version[0] < '0' || version[0] > '4') return true; if (version[0] < '4') { // Deal with 0.x .. 3.x. // Unless this is the beginning of a larger number, // this is a bad version. return (version[0] != '0' && version[1] >= '0' && version[1] <= '9'); } else { // The 4.x case is a bit messier to deal with. // If it's the beginning of a larger number, we're fine. if (version[1] >= '0' && version[1] <= '9') return true; // Definitely begins with 4 and 4 alone. // The only way to save ourselves is to have 4.x for x >= 5. if (version[1] != '.') return false; // We definitely begin with "4.". // The only good possibilities now are to begin with: // - 4.[number larger than 4] if (version[2] == '0') return false; else if (version[2] >= '1' && version[2] <= '4') return (version[3] >= '0' && version[3] <= '9'); else if (version[2] >= '5' && version[2] <= '9') return true; else return false; } } int testEngine(int value) { return value; } } // namespace regina regina-4.96/engine/engine.h000644 000765 000024 00000012062 12377775101 015506 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file engine.h * \brief Provides global routines for interfacing with the Regina * calculation engine. */ #ifndef __ENGINE_H #ifndef __DOXYGEN #define __ENGINE_H #endif #include "regina-core.h" /** * Contains the entire Regina calculation engine. * * \todo \prob Derive from regina::boost::noncopyable where appropriate. * \todo \featurelong Enhance the test suite for the calculation engine. */ namespace regina { /** * \addtogroup engine Engine Structure * Overall structure of the calculation engine. * @{ */ /** * Returns the full version number of this calculation engine. * For instance, version 2.3.1 would have full version "2.3.1". * * @return the version of this calculation engine. */ REGINA_API const char* getVersionString(); /** * Returns the major version number of this calculation engine. * For instance, version 2.3.1 would have major version 2. * * @return the major version number of this calculation engine. */ REGINA_API int getVersionMajor(); /** * Returns the minor version number of this calculation engine. * For instance, version 2.3.1 would have minor version 3. * * @return the minor version number of this calculation engine. */ REGINA_API int getVersionMinor(); /** * Did the given version of Regina consistently use UTF-8 in its data * files? * * In Regina versions 4.4 and below, no particular attention was paid to * character encodings. As a result, the GUI typically stored data in * LATIN1 (the default for the Qt libraries). * * As of Regina 4.5, all strings are now stored in UTF-8 where possible. * * This routine allows programs to determine which regime a particular * version of Regina belongs to. This can be useful when working with * Regina data files on a low-level basis. * * Any whitespace in the version string will confuse the result, and the * return value will be undefined. * * As a special case, an empty string is treated as belonging to the * UTF-8 regime. * * @param version a version string from some release of Regina, such as "4.2". * This must not contain any whitespace padding. * @return \c true if the given version uses UTF-8 consistently, or * \c false if the given version is an older version that did not pay * attention to character encodings. */ REGINA_API bool versionUsesUTF8(const char* version); /** * Tests to see if an interface can successfully communicate with the * underlying C++ calculation engine. * * This routine simply uses the engine to return the same value that is * passed to it; it can be used to test whether communications between * the interface and the C++ engine are working properly. * * @param value any integer; this same integer will be returned. * @return the same integer that was passed as \a value. */ REGINA_API int testEngine(int value); /*@}*/ } // namespace regina #endif regina-4.96/engine/enumerate/CMakeLists.txt000644 000765 000024 00000002267 12311266525 020614 0ustar00babstaff000000 000000 # enumerate # Files to compile SET ( FILES nenumconstraint ndoubledescription ndoubledescriptor nhilbertcd nhilbertdual nhilbertprimal nmaxadmissible ntreeconstraint ntreelp ntreetraversal ntypetrie ) # Prepend folder name FOREACH ( SOURCE_FILE ${FILES} ) SET ( SOURCES ${SOURCES} enumerate/${SOURCE_FILE}) ENDFOREACH(SOURCE_FILE) IF (NOT EXCLUDE_NORMALIZ) ADD_SUBDIRECTORY("normaliz") ENDIF (NOT EXCLUDE_NORMALIZ) SET(SOURCES ${SOURCES} PARENT_SCOPE) if (${REGINA_INSTALL_DEV}) INSTALL(FILES nenumconstraint.h ndoubledescription.h ndoubledescription-impl.h ndoubledescription.tcc ndoubledescriptor.h ndoubledescriptor.tcc nhilbertcd.h nhilbertcd-impl.h nhilbertcd.tcc nhilbertdual.h nhilbertdual-impl.h nhilbertdual.tcc nhilbertprimal.h nhilbertprimal-impl.h nhilbertprimal.tcc nmaxadmissible.h nmaxadmissible-impl.h nmaxadmissible.tcc ntreeconstraint.h ntreelp.h ntreelp-impl.h ntreelp.tcc ntreetraversal.h ntreetraversal-impl.h ntreetraversal.tcc ntypetrie.h ordering.h DESTINATION ${INCLUDEDIR}/enumerate COMPONENT Development) endif (${REGINA_INSTALL_DEV}) regina-4.96/engine/enumerate/ndoubledescription-impl.h000644 000765 000024 00000046574 12377775103 023102 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /* To be included from ndoubledescription.h. */ #ifndef __NDOUBLEDESCRIPTION_IMPL_H #ifndef __DOXYGEN #define __NDOUBLEDESCRIPTION_IMPL_H #endif #include #include #include "regina-core.h" #include "regina-config.h" #include "enumerate/ndoubledescription.h" #include "enumerate/nenumconstraint.h" #include "maths/matrixops.h" #include "maths/nray.h" #include "progress/nprogresstracker.h" #include "utilities/boostutils.h" #include "utilities/memutils.h" #include "utilities/nbitmask.h" #include "utilities/ntrieset.h" namespace regina { template NDoubleDescription::RaySpec::RaySpec(unsigned long axis, const NMatrixInt& subspace, const long* hypOrder) : NRay(subspace.rows()), facets_(subspace.columns()) { size_t i; for (i = 0; i < subspace.columns(); ++i) if (i != axis) facets_.set(i, true); for (i = 0; i < size(); ++i) elements[i] = subspace.entry(hypOrder[i], axis); } template NDoubleDescription::RaySpec::RaySpec( const RaySpec& first, const RaySpec& second) : NRay(second.size() - 1), facets_(second.facets_) { for (size_t i = 0; i < size(); ++i) elements[i] = second.elements[i + 1] * (*first.elements) - first.elements[i + 1] * (*second.elements); scaleDown(); if (*first.elements < zero) negate(); // Compute the new set of facets. facets_ &= first.facets_; } template void NDoubleDescription::RaySpec::recover( NRay& dest, const NMatrixInt& subspace) const { unsigned long i, j; unsigned long rows = subspace.rows(); unsigned long cols = subspace.columns() - facets_.bits(); // Extract the set of columns that we actually care about. unsigned long* use = new unsigned long[cols]; for (i = 0, j = 0; i < subspace.columns(); ++i) if (facets_.get(i)) { // We know in advance that this coordinate will be zero. dest.setElement(i, NLargeInteger::zero); } else { use[j++] = i; } // We know the solution space has dimension one. // If there are no equations then there must be only one non-zero // coordinate, and vice versa. if (cols == 1) { dest.setElement(*use, 1); delete[] use; return; } // We have several non-zero coordinates with at least one // non-trivial equation relating them. // Form a submatrix for the equations, looking only at non-zero coordinates. NLargeInteger* m = new NLargeInteger[rows * cols]; for (i = 0; i < rows; ++i) for (j = 0; j < cols; ++j) m[i * cols + j] = subspace.entry(i, use[j]); // Put this submatrix in echelon form; moreover, for the leading // entry in each row, set all other entries in the corresponding // column to zero. unsigned long* lead = new unsigned long[cols]; for (i = 0; i < cols; ++i) lead[i] = i; // More or less a stripped-down copy of rowBasisAndOrthComp() from here. // See rowBasisAndOrthComp() for further details on how this works. unsigned long done = 0; unsigned long tmp; NLargeInteger coeff1, coeff2, common; while (done < rows) { // Find the first non-zero entry in row done. for (i = done; i < cols; ++i) if (m[done * cols + lead[i]] != NLargeInteger::zero) break; if (i == cols) { // We have a zero row. Trash it and replace it with something else. --rows; if (done < rows) { for (j = 0; j < cols; ++j) m[done * cols + j] = m[rows * cols + j]; } } else { // We have a non-zero row. // Save the column in which we found our non-zero entry. tmp = lead[done]; lead[done] = lead[i]; lead[i] = tmp; // Make all other entries in column lead[done] equal to zero. coeff1 = m[done * cols + lead[done]]; for (i = 0; i < rows; ++i) { if (i == done) continue; coeff2 = m[i * cols + lead[done]]; common = NLargeInteger::zero; if (coeff2 != NLargeInteger::zero) { for (j = 0; j < cols; ++j) { m[i * cols + j] = m[i * cols + j] * coeff1 - m[done * cols + j] * coeff2; common = common.gcd(m[i * cols + j]); } } if (common < NLargeInteger::zero) common.negate(); if (common > NLargeInteger::one) for (j = 0; j < cols; ++j) m[i * cols + j].divByExact(common); } ++done; } } // At this point we should have rows == (cols - 1), and the column // that is *not* zeroed out almost everywhere is lead[rows]. (We // know this because we know that our solution must be one-dimensional). // // Form a solution! common = NLargeInteger::one; for (i = 0; i < rows; ++i) common = common.lcm(m[i * cols + lead[i]]); if (common < NLargeInteger::zero) common.negate(); for (i = 0; i < rows; ++i) dest.setElement(use[lead[i]], - (common * m[i * cols + lead[rows]]). divExact(m[i * cols + lead[i]])); dest.setElement(use[lead[rows]], common); dest.scaleDown(); // All done! delete[] lead; delete[] m; delete[] use; } template void NDoubleDescription::enumerateExtremalRays(OutputIterator results, const NMatrixInt& subspace, const NEnumConstraintList* constraints, NProgressTracker* tracker, unsigned long initialRows) { unsigned long nFacets = subspace.columns(); // If the space has dimension zero, return no results. if (nFacets == 0) return; // Choose a bitmask type for representing the set of facets that a // ray belongs to; in particular, use a (much faster) optimised // bitmask type if we can. // Then farm the work out to the real enumeration routine that is // templated on the bitmask type. if (nFacets <= 8 * sizeof(unsigned)) enumerateUsingBitmask >(results, subspace, constraints, tracker, initialRows); else if (nFacets <= 8 * sizeof(unsigned long)) enumerateUsingBitmask >(results, subspace, constraints, tracker, initialRows); #ifdef LONG_LONG_FOUND else if (nFacets <= 8 * sizeof(unsigned long long)) enumerateUsingBitmask >(results, subspace, constraints, tracker, initialRows); else if (nFacets <= 8 * sizeof(unsigned long long) + 8 * sizeof(unsigned)) enumerateUsingBitmask >(results, subspace, constraints, tracker, initialRows); else if (nFacets <= 8 * sizeof(unsigned long long) + 8 * sizeof(unsigned long)) enumerateUsingBitmask >( results, subspace, constraints, tracker, initialRows); else if (nFacets <= 16 * sizeof(unsigned long long)) enumerateUsingBitmask >(results, subspace, constraints, tracker, initialRows); #else else if (nFacets <= 8 * sizeof(unsigned long) + 8 * sizeof(unsigned)) enumerateUsingBitmask >(results, subspace, constraints, tracker, initialRows); else if (nFacets <= 16 * sizeof(unsigned long)) enumerateUsingBitmask >(results, subspace, constraints, tracker, initialRows); #endif else enumerateUsingBitmask(results, subspace, constraints, tracker, initialRows); } template void NDoubleDescription::enumerateUsingBitmask(OutputIterator results, const NMatrixInt& subspace, const NEnumConstraintList* constraints, NProgressTracker* tracker, unsigned long initialRows) { // Get the dimension of the entire space in which we are working. unsigned long dim = subspace.columns(); // Are there any hyperplanes at all in the subspace? unsigned long nEqns = subspace.rows(); if (nEqns == 0) { // No! Just send back the vertices of the non-negative orthant. RayClass* ans; for (unsigned long i = 0; i < dim; ++i) { ans = new RayClass(dim); ans->setElement(i, NLargeInteger::one); *results++ = ans; } if (tracker) tracker->setPercent(100); return; } // We actually have some work to do. // We want to process the hyperplanes in a good order; // Fukuda and Prodon (1996) recommend this, and experimental // experience with Regina agrees. The ordering we use here // is based on position vectors, as described in // "Optimizing the double description method for normal surface // enumeration", B.A. Burton, Mathematics of Computation 79 (2010), 453-484. // See the class NPosOrder for details. // // Sort the integers 0..(nEqns-1) into the order in which we plan to // process the hyperplanes. long* hyperplanes = new long[nEqns]; unsigned long i; for (i = 0; i < nEqns; ++i) hyperplanes[i] = i; std::sort(hyperplanes + initialRows, hyperplanes + nEqns, NPosOrder(subspace)); // Create the two vector lists with which we will work. // Fill the first with the initial set of rays. typedef std::vector*> RaySpecList; RaySpecList list[2]; for (i = 0; i < dim; ++i) list[0].push_back(new RaySpec(i, subspace, hyperplanes)); // Convert the set of constraints into a bitmask, where for every original // facet listed in the constraint the corresponding bit is set to 1. BitmaskType* constraintsBegin = 0; BitmaskType* constraintsEnd = 0; if (constraints && ! constraints->empty()) { constraintsBegin = new BitmaskType[constraints->size()]; NEnumConstraintList::const_iterator cit; for (cit = constraints->begin(), constraintsEnd = constraintsBegin; cit != constraints->end(); ++cit, ++constraintsEnd) { constraintsEnd->reset(dim); constraintsEnd->set(cit->begin(), cit->end(), true); } } #if 0 std::cout << "Initial size: " << list[0].size() << std::endl; #endif // Intersect the hyperplanes one at a time. // At any point we should have the latest results in // list[workingList], with the other list empty. int workingList = 0; unsigned long used = 0; for (i=0; isetPercent(100.0 * i / nEqns)) break; } // We're done! delete[] hyperplanes; if (constraintsBegin) delete[] constraintsBegin; typename RaySpecList::iterator it; if (tracker && tracker->isCancelled()) { // The operation was cancelled. Clean up before returning. for (it = list[workingList].begin(); it != list[workingList].end(); ++it) delete *it; return; } // Convert the final solutions into the required ray class. RayClass* ans; for (it = list[workingList].begin(); it != list[workingList].end(); ++it) { ans = new RayClass(dim); (*it)->recover(*ans, subspace); *results++ = ans; delete *it; } // All done! if (tracker) tracker->setPercent(100); } template bool NDoubleDescription::intersectHyperplane( std::vector*>& src, std::vector*>& dest, unsigned long dim, unsigned long prevHyperplanes, const BitmaskType* constraintsBegin, const BitmaskType* constraintsEnd, NProgressTracker* tracker) { if (src.empty()) return false; typedef std::vector*> RayList; RayList pos, neg; // Run through the old rays and determine which side of the // new hyperplane they lie on. // Rays lying within the new hyperplane will be added directly to // the new solution set. typename RayList::iterator it; int sign; for (it = src.begin(); it != src.end(); it++) { sign = (*it)->sign(); if (sign == 0) dest.push_back(new RaySpec(**it)); else if (sign < 0) neg.push_back(*it); else pos.push_back(*it); } // Does one of the closed half-spaces defined by the hyperplane contain the // entire old solution set? If so, there will be no new vertices. if (pos.empty() || neg.empty()) { for (typename RayList::iterator it = src.begin(); it != src.end(); ++it) delete *it; src.clear(); return false; } // Run through the pairs of positive and negative rays. For every // pair of rays that are adjacent in the current solution space, // add the corresponding intersection with the new hyperplane to the // new solution set. typename RayList::iterator posit, negit, otherit; const BitmaskType* constraint; bool broken; // We use the NTrieSet data structure to speed up adjacency testing // in the code below. Construct an NTrieSet that records the facet // structure for every vertex in the old solution set. NTrieSet trie; for (otherit = src.begin(); otherit != src.end(); ++otherit) trie.insert((*otherit)->facets()); unsigned iterations = 0; for (posit = pos.begin(); posit != pos.end(); ++posit) for (negit = neg.begin(); negit != neg.end(); ++negit) { // Test for cancellation, but not every time (since this // involves expensive mutex locking). if (tracker && ++iterations == 100) { iterations = 0; if (tracker->isCancelled()) { for (otherit = src.begin(); otherit != src.end(); ++otherit) delete *otherit; src.clear(); for (otherit = dest.begin(); otherit != dest.end(); ++otherit) delete *otherit; dest.clear(); return false; } } BitmaskType join((*posit)->facets()); join &= ((*negit)->facets()); // We only care about adjacent rays, i.e., rays joined by an edge. // For the rays to be adjacent, the number of original facets that // both belong to must be >= dimension(subspace) - 2, // which is >= dimension(entire space) - prevHyperplanes - 2. // See Fukuda and Prodon (1996), Proposition 9. if (join.bits() + prevHyperplanes + 2 < dim) continue; // Are we supposed to check for compatibility? if (constraintsBegin) { BitmaskType inv(join); inv.flip(); broken = false; for (constraint = constraintsBegin; constraint != constraintsEnd; ++constraint) { BitmaskType mask(inv); mask &= *constraint; if (! mask.atMostOneBit()) { broken = true; break; } } if (broken) continue; } // Two rays are adjacent (joined by an edge) if and only if // there is no other ray belonging to all of their common facets. // // If the rays *are* adjacent, join them and put the // corresponding intersection in the new results set. if (! trie.hasExtraSuperset(join, (*posit)->facets(), (*negit)->facets(), dim)) dest.push_back(new RaySpec(**posit, **negit)); } // Clean up. for (otherit = src.begin(); otherit != src.end(); ++otherit) delete *otherit; src.clear(); return true; } } // namespace regina #endif regina-4.96/engine/enumerate/ndoubledescription.h000644 000765 000024 00000051603 12377775104 022131 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file enumerate/ndoubledescription.h * \brief Provides a modified double description method for polytope * vertex enumeration. */ #ifndef __NDOUBLEDESCRIPTION_H #ifndef __DOXYGEN #define __NDOUBLEDESCRIPTION_H #endif #include "regina-core.h" #include "enumerate/ordering.h" #include "maths/nray.h" #include "maths/nmatrixint.h" #include #include namespace regina { class NEnumConstraintList; class NMatrixInt; class NRay; class NProgressTracker; /** * \addtogroup enumerate Vertex Enumeration * Polytope vertex enumeration algorithms. * @{ */ /** * Implements a modified double description method for polytope vertex * enumeration. For details of the underlying algorithm, see * "Optimizing the double description method for normal surface enumeration", * Benjamin A. Burton, Math. Comp. 79 (2010), 453-484. * * All routines of interest within this class are static; no object of * this class should ever be created. * * \ifacespython Not present. */ class REGINA_API NDoubleDescription { public: /** * Determines the extremal rays of the intersection of the * n-dimensional non-negative orthant with the given linear * subspace. The resulting rays will be of the class \a RayClass, * will be newly allocated, and will be written to the given output * iterator. Their deallocation is the responsibility of whoever * called this routine. * * The non-negative orthant is an n-dimensional cone with * its vertex at the origin. The extremal rays of this cone are * the \a n non-negative coordinate axes. This cone also has \a n * facets, where the ith facet is the non-negative * orthant of the plane perpendicular to the ith coordinate * axis. * * This routine takes a linear subspace, defined by the * intersection of a set of hyperplanes through the origin (this * subspace is described as a matrix, with each row giving the * equation for one hyperplane). * * The purpose of this routine is to compute the extremal rays of * the new cone formed by intersecting the original cone with this * linear subspace. The resulting list of extremal rays will * contain no duplicates or redundancies. * * Parameter \a constraints may contain a set of validity constraints, * in which case this routine will only return \e valid extremal * rays. Each validity constraint is of the form "an extremal ray * may only lie outside at most one of these facets of the original * cone"; see the NEnumConstraintList class for details. These * contraints have the important property that, although validity is * not preserved under convex combination, \e invalidity is. * * An optional progress tracker may be passed. If so, this routine * will update the percentage progress and poll for cancellation * requests. It will be assumed that an appropriate stage has already * been declared via NProgressTracker::newStage() before this routine * is called, and that NProgressTracker::setFinished() will be * called after this routine returns. * * \pre The template argument RayClass is derived from NRay (or * may possibly be NRay itself). * * @param results the output iterator to which the resulting extremal * rays will be written; this must accept objects of type * RayClass*. * @param subspace a matrix defining the linear subspace to intersect * with the given cone. Each row of this matrix is the equation * for one of the hyperplanes whose intersection forms this linear * subspace. The number of columns in this matrix must be the * dimension of the overall space in which we are working. * @param constraints a set of validity constraints as described * above, or 0 if no additional constraints should be imposed. * @param tracker a progress tracker through which progress * will be reported, or 0 if no progress reporting is required. * @param initialRows specifies how many initial rows of \a subspace * are to be processed in the precise order in which they appear. * The remaining rows will be sorted using the NPosOrder class * before they are processed. */ template static void enumerateExtremalRays(OutputIterator results, const NMatrixInt& subspace, const NEnumConstraintList* constraints, NProgressTracker* tracker = 0, unsigned long initialRows = 0); private: /** * A helper class for vertex enumeration, describing a single ray * (typically a vertex in some partial solution space). * * Although this class represents a ray, it does not actually * store the coordinates of the ray. Instead it stores: * * - the dot products of this ray with each of the hyperplanes * passed to NDoubleDescription::enumerateExtremalRays(); * * - a bitmask indicating which facets of the original cone this * ray belongs to. * * The dot products are stored as coordinates of the * superclass NRay. Dot products are only stored * for hyperplanes that have not yet been intersected (thus * the vector length becomes smaller as the main algorithm progresses). * Dot products are stored in the order in which hyperplanes are * to be processed (thus the dot product with the next hyperplane * is the first element of this vector, and the dot product with * the final hyperplane is the last element). * * The \a BitmaskType template argument describes how the set of * facets will be stored. Specifically, the set of facets is * stored as a bitmask with one bit per facet; each bit is set if * and only if this ray belongs to the corresponding original facet. * * Since this class is used heavily, faster bitmask types such * as NBitmask1 and NBitmask2 are preferred; however, if the * number of facets is too large then the slower general-use NBitmask * class will need to be used instead. * * \pre The template argument \a BitmaskType is one of Regina's * bitmask types, such as NBitmask, NBitmask1 or NBitmask2. */ template class RaySpec : private NRay { private: BitmaskType facets_; /**< A bitmask listing which original facets this ray belongs to. */ public: /** * Creates a ray specification for the non-negative * portion of the given coordinate axis. * * \pre The dimension of the space in which we are * working is strictly positive, but is small enough that * \a BitmaskType can hold the corresponding number of bits * (one bit per dimension). * * @param axis indicates which coordinate axis to use; * this must be at least zero but strictly less than the * dimension of the entire space. * @param subspace the matrix containing the set of * hyperplanes to intersect with the original cone * (one hyperplane for each row of the matrix). * @param hypOrder the order in which we plan to * intersect the hyperplanes. The length of this array * must be the number of rows in \a subspace, and the * ith hyperplane to intersect must be described * by row hypOrder[i] of \a subspace. */ inline RaySpec(unsigned long axis, const NMatrixInt& subspace, const long* hypOrder); /** * Creates a copy of the given ray specification, with the * first dot product removed. The resulting list of dot * products is thus one element shorter. * * This routine is typically called when we intersect a * hyperplane with a partial solution space and some ray * lies directly in this hyperplane (not on either side). * * @param trunc the ray to copy and truncate. */ inline RaySpec(const RaySpec& trunc); /** * Creates a new ray, describing where the plane between * two given rays meets the next intersecting hyperplane. * * The list of dot products for the new ray will be one * element shorter than the lists for the given rays * (since there will be one less hyperplane remaining to * intersect). * * \pre The two given rays come from the same partial * solution space (i.e., their lists of dot products * are the same length). Moreover, this partial * solution space still has at least one hyperplane * remaining to intersect (i.e., the lists of dot * products are not empty). * \pre The two given rays lie on opposite sides of the * next hyperplane to intersect, and neither ray actually * lies \e in this next hyperplane. * * @param first the first of the given rays. * @param second the second of the given rays. */ RaySpec(const RaySpec& first, const RaySpec& second); /** * Returns the sign of the dot product of this ray with the * next hyperplane. This is simply the sign of the first * element in the list of remaining dot products. * * @return 1, 0 or -1 according to the sign of the next * dot product. */ int sign() const; /** * Returns the bitmask listing which facets of the original * cone this ray belongs to. Each bit is set to \c true * if and only if this ray belongs to the corresponding facet. * * @return a bitmask of facets. */ inline const BitmaskType& facets() const; /** * Determines whether this ray belongs to all of the * facets that are common to both given rays. * * For this routine to return \c true, every facet that * contains both \a x and \a y must contain this ray also. * * @param x the first of the given rays. * @param y the second of the given rays. * @return \c true if and only if this ray belongs to all * of the facets that \e both \a x and \a y belong to. */ inline bool onAllCommonFacets( const RaySpec& x, const RaySpec& y) const; /** * Recovers the coordinates of the actual ray that is * described by this object. This routine is not fast, * since it needs to solve a system of linear equations. * * \pre This ray is a member of the \e final solution * space. That is, all hyperplanes have been * intersected with the original cone, and the list of * dot products stored in this object is empty. * * @param dest the ray in which the final coordinates * will be stored; the length of this ray must be the * dimension of the overall space in which we are working. * @param subspace the matrix containing the set of * hyperplanes that were intersected with the original cone * (one hyperplane for each row of the matrix). */ void recover(NRay& dest, const NMatrixInt& subspace) const; }; /** * A comparison object that helps sort hyperplanes into a good * order before running the double description algorithm. * * @deprecated The inner class LexComp no longer exists; instead * its functionality has been moved to the standalone class * NPosOrder. This typedef is offered for backward compatibility, * and will be removed in a future version of Regina. */ typedef NPosOrder LexComp; /** * Private constructor to ensure that objects of this class are * never created. */ NDoubleDescription(); /** * Identical to the public routine enumerateExtremalRays(), except * that there is an extra template parameter \a BitmaskType. * This specifies what type should be used for the bitmask * describing which original facets a ray belongs to. * * All arguments to this function are identical to those for the * public routine enumerateExtremalRays(). * * \pre The bitmask type is one of Regina's bitmask types, such * as NBitmask, NBitmask1 or NBitmask2. * \pre The type \a BitmaskType can handle at least \a f bits, * where \a f is the number of original facets in the given range. * \pre The given range of facets is not empty. */ template static void enumerateUsingBitmask(OutputIterator results, const NMatrixInt& subspace, const NEnumConstraintList* constraints, NProgressTracker* tracker, unsigned long initialRows); /** * A part of the full double description algorithm that * intersects the current solution set with a new hyperplane. * * The input list \a src must contain the vertices of the * solution space after the first \a prevHyperplanes hyperplanes * have been intersected with the original cone. This routine * intersects this solution space with the next hyperplane, and * places the vertices of the new solution space in the output * list \a dest. * * The set of validity constraints must be passed here as a * C-style array of bitmasks. Each bitmask is a bitmask of facets, * as seen in the RaySpec inner class. Each constraint is of the * form "a point cannot live outside more than one of these facets"; * the bits for these facets must be set to 1 in the corresponding * bitmask, and all other bits must be set to 0. * * It should be noted that the hyperplane itself is not passed * to this routine. This is because all the necessary information * (in particular, the dot products with the new hyperplane) is * stored with the individual vertices of the current solution space. * * \pre The input list \a src owns its elements, and the output * list \a dest is empty. * \post The input list \a src will be empty, and the output * list \a dest will own all of the elements that it contains. * * @param src contains the vertices of the current solution space * before this routine is called. * @param dest contains the vertices of the new solution space * after this routine returns. * @param dim the dimension of the entire space in which we are working. * @param prevHyperplanes the number of hyperplanes that have * already been intersected with the original cone to form the * current solution set. This does not include the hyperplane * currently under consideration. * @param constraintsBegin the beginning of the C-style array of * validity constraints. This should be 0 if no additional * constraints are to be imposed. * @param constraintsEnd a pointer just past the end of the * C-style array of validity constraints. This should be 0 * if no additional constraints are to be imposed. * @param tracker an optional progress tracker that will be polled * for cancellation (though no incremental progress will be reported * within this routine). This may be null. * @return \c true if vertices of the old solution set were found * on both sides of the new hyperplane, \c false if one of * the closed half-spaces defined by the new hyperplane contained * the entire old solution set, or undefined if the operation * was cancelled via the progress tracker. */ template static bool intersectHyperplane( std::vector*>& src, std::vector*>& dest, unsigned long dim, unsigned long prevHyperplanes, const BitmaskType* constraintsBegin, const BitmaskType* constraintsEnd, NProgressTracker* tracker); }; /*@}*/ // Inline functions for NDoubleDescription::RaySpec template inline NDoubleDescription::RaySpec::RaySpec( const RaySpec& trunc) : NRay(trunc.size() - 1), facets_(trunc.facets_) { std::copy(trunc.elements + 1, trunc.end, elements); } template inline int NDoubleDescription::RaySpec::sign() const { if (*elements < NLargeInteger::zero) return -1; if (*elements > NLargeInteger::zero) return 1; return 0; } template inline const BitmaskType& NDoubleDescription::RaySpec::facets() const { return facets_; } template inline bool NDoubleDescription::RaySpec::onAllCommonFacets( const RaySpec& x, const RaySpec& y) const { return facets_.containsIntn(x.facets_, y.facets_); } // Inline functions for NDoubleDescription inline NDoubleDescription::NDoubleDescription() { } } // namespace regina // Template definitions #include "enumerate/ndoubledescription-impl.h" #endif regina-4.96/engine/enumerate/ndoubledescription.tcc000644 000765 000024 00000004714 12400001231 022416 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file enumerate/ndoubledescription.tcc * \brief Deprecated header. */ #warning This header is deprecated; please use ndoubledescription-impl.h instead. #include "enumerate/ndoubledescription-impl.h" regina-4.96/engine/enumerate/ndoubledescriptor.h000644 000765 000024 00000006337 12377775107 021773 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file enumerate/ndoubledescriptor.h * \brief Provides a modified double description method for polytope * vertex enumeration. */ #ifndef __NDOUBLEDESCRIPTOR_H #ifndef __DOXYGEN #define __NDOUBLEDESCRIPTOR_H #endif #warning This header is deprecated; please use ndoubledescription.h instead. #include "enumerate/ndoubledescription.h" namespace regina { /** * \weakgroup enumerate * @{ */ /** * A legacy typedef provided for backward compatibility only. * * \deprecated As of Regina 4.6, the class NDoubleDescriptor has been * renamed as NDoubleDescription. This renaming is merely for * consistency in documentation and nomenclature; the functionality * of the new NDoubleDescription class is identical to the old * NDoubleDescriptor class as it was in Regina 4.5.1. This typedef is * provided for backward compatibility, and will be removed in some * future version of Regina. */ typedef NDoubleDescription NDoubleDescriptor; /*@}*/ } // namespace regina #endif regina-4.96/engine/enumerate/ndoubledescriptor.tcc000644 000765 000024 00000004742 12400001232 022253 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #warning This header is deprecated; please use ndoubledescription-impl.h instead. // Include the outer header ndoubledescription.h so that we get the // backward-compatibility typedefs. #include "enumerate/ndoubledescription.h" regina-4.96/engine/enumerate/nenumconstraint.h000644 000765 000024 00000012051 12377775110 021453 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file enumerate/nenumconstraint.h * \brief Deals with validity constraints in polytope vertex enumeration. */ #ifndef __NENUMCONSTRAINT_H #ifndef __DOXYGEN #define __NENUMCONSTRAINT_H #endif #include #include #include #include "regina-core.h" namespace regina { /** * \weakgroup enumerate * @{ */ /** * Represents an individual validity constraint for use with * polytope vertex enumeration. * * Vertex enumeration routines such as * NDoubleDescription::enumerateExtremalRays() take a cone (specifically * the non-negative orthant), form the intersection of that cone with a * given linear subspace, and return the extremal rays of the new cone * that results. * * In some cases we are only interested in \e valid rays of the new cone. * The NEnumConstraintList class stores a number of "validity constraints"; * a ray is then "valid" if it satisfies all of these constraints. * * Each individual constraint is presented as a set of integers; the * meaning of such a constraint is as follows. We number the facets of * the original cone 0,1,2,... (where the ith facet is the plane * perpendicular to the ith coordinate axis). If a constraint is * described by the integers \a x, \a y, \a z, ..., then it indicates that a * ray can only lie outside at most one of the facets numbered * \a x, \a y, \a z, ... . * * In practice, this allows us to represent constraints in normal * surface theory. For instance, to insist that some tetrahedron * contains at most one quadrilateral disc type, we add a constraint * with three integers, representing the original facets * \a q1=0, \a q2=0, \a q3=0 (where \a q1, \a q2 and \a q3 are the three * quadrilateral coordinates for that tetrahedron). * * The NEnumConstraintList class is simply a std::vector of constraints, * where each constraint is a std::set of unsigned integers. Typically * one will create a vector containing the desired number of constraints * and then walk through each constraint, filling the sets as appropriate. * * \ifacespython Not present. */ class REGINA_API NEnumConstraintList : public std::vector > { public: /** * Creates an empty list of constraints. */ NEnumConstraintList(); /** * Creates a new list of constraints with the given size. * Each constraint will be initialised to an empty set. * * @param size the number of constraints to include in the new list. */ NEnumConstraintList(size_t size); }; /*@}*/ // Inline functions for NEnumConstraintList inline NEnumConstraintList::NEnumConstraintList() { } inline NEnumConstraintList::NEnumConstraintList(size_t size) : std::vector >(size) { } } // namespace regina #endif regina-4.96/engine/enumerate/nhilbertcd-impl.h000644 000765 000024 00000024555 12377775112 021317 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /* To be included from nhilbertcd.h. */ #ifndef __NHILBERTCD_IMPL_H #ifndef __DOXYGEN #define __NHILBERTCD_IMPL_H #endif #include "regina-core.h" #include "regina-config.h" #include "enumerate/nenumconstraint.h" #include "enumerate/nhilbertcd.h" #include "maths/nmatrixint.h" #include "maths/nray.h" #include "utilities/nbitmask.h" #include namespace regina { template void NHilbertCD::enumerateHilbertBasis(OutputIterator results, const NMatrixInt& subspace, const NEnumConstraintList* constraints) { // Get the dimension of the space. size_t dim = subspace.columns(); if (dim == 0) return; // Choose a bitmask type that can hold dim bits. // Use a (much faster) optimised bitmask type if we can. // Then farm the work out to the real enumeration routine that is // templated on the bitmask type. if (dim <= 8 * sizeof(unsigned)) enumerateUsingBitmask >(results, subspace, constraints); else if (dim <= 8 * sizeof(unsigned long)) enumerateUsingBitmask >(results, subspace, constraints); #ifdef LONG_LONG_FOUND else if (dim <= 8 * sizeof(unsigned long long)) enumerateUsingBitmask >(results, subspace, constraints); else if (dim <= 8 * sizeof(unsigned long long) + 8 * sizeof(unsigned)) enumerateUsingBitmask >(results, subspace, constraints); else if (dim <= 8 * sizeof(unsigned long long) + 8 * sizeof(unsigned long)) enumerateUsingBitmask >( results, subspace, constraints); else if (dim <= 16 * sizeof(unsigned long long)) enumerateUsingBitmask >(results, subspace, constraints); #else else if (dim <= 8 * sizeof(unsigned long) + 8 * sizeof(unsigned)) enumerateUsingBitmask >(results, subspace, constraints); else if (dim <= 16 * sizeof(unsigned long)) enumerateUsingBitmask >(results, subspace, constraints); #endif else enumerateUsingBitmask(results, subspace, constraints); } template void NHilbertCD::enumerateUsingBitmask(OutputIterator results, const NMatrixInt& subspace, const NEnumConstraintList* constraints) { // Stack-based Contejean-Devie algorithm (Information & Computation, 1994). size_t dim = subspace.columns(); size_t nEqns = subspace.rows(); // Convert the set of constraints into bitmasks, where for every // original coordinate listed in the constraint, the corresponding // bit is set to 1. BitmaskType* constraintsBegin = 0; BitmaskType* constraintsEnd = 0; if (constraints && ! constraints->empty()) { constraintsBegin = new BitmaskType[constraints->size()]; NEnumConstraintList::const_iterator cit; for (cit = constraints->begin(), constraintsEnd = constraintsBegin; cit != constraints->end(); ++cit, ++constraintsEnd) { constraintsEnd->reset(dim); constraintsEnd->set(cit->begin(), cit->end(), true); } } std::list*> basis; typename std::list*>::iterator bit; NRay** unitMatch = new NRay*[dim]; int i, j; for (i = 0; i < dim; ++i) { unitMatch[i] = new NRay(nEqns); for (j = 0; j < nEqns; ++j) unitMatch[i]->setElement(j, subspace.entry(j, i)); } unsigned stackSize; // All vectors/rays are created and destroyed. // Bitmasks on the other hand are reused. VecSpec** coord = new VecSpec*[dim]; NRay** match = new NRay*[dim]; BitmaskType* frozen = new BitmaskType[dim]; for (i = 0; i < dim; ++i) frozen[i].reset(dim); // All false. // Push the zero vector. coord[0] = new VecSpec(dim); match[0] = new NRay(nEqns); stackSize = 1; // The zero vector is already on top. bool first = true; VecSpec *c; NRay *m; BitmaskType f(dim); BitmaskType mask(dim), tmpMask(dim); BitmaskType* constraint; bool found, dom; while (stackSize) { c = coord[stackSize - 1]; m = match[stackSize - 1]; f = frozen[stackSize - 1]; --stackSize; // std::cerr << (*c) << " ... " << (*m) << " ... " // << stackSize << std::endl; // Do we have a non-zero solution? if (! first) { found = false; for (i = 0; i < nEqns; ++i) if ((*m)[i] != 0) { found = true; break; } if (! found) { // Yep, it's a solution. basis.push_back(c); delete m; continue; } } // Try incrementing along different coordinate axes. for (i = 0; i < dim; ++i) { if (f.get(i)) continue; // This coordinate is frozen. if (! first) { // Create the bitmask that we will have if we increment // the ith coordinate. mask = c->mask_; mask.set(i, true); // Constraint test. if (constraintsBegin) { found = false; for (constraint = constraintsBegin; constraint != constraintsEnd; ++constraint) { tmpMask = mask; tmpMask &= *constraint; if (! tmpMask.atMostOneBit()) { found = true; break; } } if (found) continue; } // Opposite direction test. if ((*unitMatch[i]) * (*m) >= 0) continue; // Domination test. found = false; for (bit = basis.begin(); bit != basis.end(); ++bit) { // Is (**bit) <= (*c + ith unit vector) ? // Quick pre-check using bitmasks. if (! ((*bit)->mask_ <= mask)) continue; // Full check. dom = true; for (j = 0; j < dim; ++j) { if ( (j != i && (*c)[j] < (**bit)[j]) || (j == i && (*c)[j] + 1 < (**bit)[j])) { dom = false; break; } } if (dom) { found = true; break; } } if (found) continue; } // Increment! if (stackSize == dim) { std::cerr << "ERROR: STACK OVERFLOW" << std::endl; std::exit(1); } coord[stackSize] = new VecSpec(*c); coord[stackSize]->setElement(i, (*coord[stackSize])[i] + 1); coord[stackSize]->mask_.set(i, true); match[stackSize] = new NRay(*m); (*match[stackSize]) += (*unitMatch[i]); frozen[stackSize] = f; f.set(i, true); ++stackSize; } // Clean up. delete c; delete m; first = false; } // Clean up. for (i = 0; i < dim; ++i) delete unitMatch[i]; delete[] unitMatch; delete[] coord; delete[] match; delete[] frozen; delete[] constraintsBegin; // Output basis elements. for (bit = basis.begin(); bit != basis.end(); ++bit) { *results++ = new RayClass(**bit); delete *bit; } } } // namespace regina #endif regina-4.96/engine/enumerate/nhilbertcd.h000644 000765 000024 00000022357 12377775113 020357 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file enumerate/nhilbertcd.h * \brief Provides a modified Contejean-Devie algorithm for Hilbert basis * enumeration. */ #ifndef __NHILBERTCD_H #ifndef __DOXYGEN #define __NHILBERTCD_H #endif #include "regina-core.h" #include "maths/nray.h" #include #include #include namespace regina { class NEnumConstraintList; class NMatrixInt; class NRay; /** * \weakgroup enumerate * @{ */ /** * Implements a modified Contejean-Devie algorithm for enumerating Hilbert * bases. This is based on the stack-based algorithm described in * "An efficient incremental algorithm for solving systems of linear * Diophantine equations", Inform. and Comput. 113 (1994), 143-172, * and has been modified to allow for additional constraints (such as * the quadrilateral constraints from normal surface theory). * * All routines of interest within this class are static; no object of * this class should ever be created. * * \warning For normal surface theory, the Contejean-Devie algorithm is * extremely slow, even when modified to incorporate admissibility * constraints. Consider using the much faster NHilbertPrimal or * NHilbertDual instead. * * \ifacespython Not present. */ class NHilbertCD { public: /** * Determines the Hilbert basis that generates all integer * points in the intersection of the n-dimensional * non-negative orthant with some linear subspace. * The resulting basis elements will be of the class \a RayClass, * will be newly allocated, and will be written to the given output * iterator. Their deallocation is the responsibility of whoever * called this routine. * * The non-negative orthant is an n-dimensional cone with * its vertex at the origin. The extremal rays of this cone are * the \a n non-negative coordinate axes. This cone also has \a n * facets, where the ith facet is the non-negative * orthant of the plane perpendicular to the ith coordinate * axis. * * This routine takes a linear subspace, defined by the * intersection of a set of hyperplanes through the origin (this * subspace is described as a matrix, with each row giving the * equation for one hyperplane). * * The purpose of this routine is to compute the Hilbert basis of * the set of all integer points in the intersection of the * original cone with this linear subspace. The resulting list * of basis vectors will contain no duplicates or redundancies. * * The parameter \a constraints may contain a set of validity * constraints, in which case this routine will only return \e valid * basis elements. Each validity constraint is of the form "at * most one of these coordinates may be non-zero"; see the * NEnumConstraintList class for details. These contraints have the * important property that, although validity is not preserved under * addition, \e invalidity is. * * \pre The template argument RayClass is derived from NRay (or * may possibly be NRay itself). * * \warning For normal surface theory, the Contejean-Devie algorithm is * extremely slow, even when modified to incorporate admissibility * constraints. Consider using the much faster NHilbertPrimal or * NHilbertDual instead. * * @param results the output iterator to which the resulting basis * elements will be written; this must accept objects of type * RayClass*. * @param subspace a matrix defining the linear subspace to intersect * with the given cone. Each row of this matrix is the equation * for one of the hyperplanes whose intersection forms this linear * subspace. The number of columns in this matrix must be the * dimension of the overall space in which we are working. * @param constraints a set of validity constraints as described * above, or 0 if no additional constraints should be imposed. */ template static void enumerateHilbertBasis(OutputIterator results, const NMatrixInt& subspace, const NEnumConstraintList* constraints); private: /** * A helper class for Hilbert basis enumeration, describing a * single candidate basis vector. * * The coordinates of the vector are inherited through the * superclass NRay. * * The \a BitmaskType template argument is used to store one bit * per coordinate, which is \c false if the coordinate is zero * or \c true if the coordinate is non-zero. * * \pre The template argument \a BitmaskType is one of Regina's * bitmask types, such as NBitmask, NBitmask1 or NBitmask2. */ template struct VecSpec : public NRay { BitmaskType mask_; /**< A bitmask indicating which coordinates are zero (\c false) and which are non-zero (\c true). */ /** * Creates the zero vector. * * @param dim the total dimension of the space (and * therefore the toatl length of this vector). */ inline VecSpec(size_t dim); }; /** * Identical to the public routine enumerateHilbertBasis(), * except that there is an extra template parameter \a BitmaskType. * This describes what type should be used for bitmasks that * assign flags to individual coordinate positions. * * All arguments to this function are identical to those for the * public routine enumerateHilbertBasis(). * * \pre The bitmask type is one of Regina's bitmask types, such * as NBitmask, NBitmask1 or NBitmask2. * \pre The type \a BitmaskType can handle at least \a n bits, * where \a n is the dimension of the Euclidean space (i.e., the * number of columns in \a subspace). */ template static void enumerateUsingBitmask(OutputIterator results, const NMatrixInt& subspace, const NEnumConstraintList* constraints); /** * Private constructor to ensure that objects of this class are * never created. */ NHilbertCD(); }; /*@}*/ // Inline functions for NHilbertCD inline NHilbertCD::NHilbertCD() { } // Inline functions for NHilbertCD::VecSpec template inline NHilbertCD::VecSpec::VecSpec(size_t dim) : NRay(dim), mask_(dim) { // All vector elements are initialised to zero thanks to the // NLargeInteger default constructor. } } // namespace regina // Template definitions #include "enumerate/nhilbertcd-impl.h" #endif regina-4.96/engine/enumerate/nhilbertcd.tcc000644 000765 000024 00000004664 12400001234 020647 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file enumerate/nhilbertcd.tcc * \brief Deprecated header. */ #warning This header is deprecated; please use nhilbertcd-impl.h instead. #include "enumerate/nhilbertcd-impl.h" regina-4.96/engine/enumerate/nhilbertdual-impl.h000644 000765 000024 00000041076 12377775115 021656 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /* To be included from nhilbertdual.h. */ #ifndef __NHILBERTDUAL_IMPL_H #ifndef __DOXYGEN #define __NHILBERTDUAL_IMPL_H #endif #include #include #include "enumerate/nenumconstraint.h" #include "enumerate/nhilbertdual.h" #include "enumerate/ordering.h" #include "progress/nprogresstracker.h" #include "utilities/nbitmask.h" namespace regina { template void NHilbertDual::enumerateHilbertBasis(OutputIterator results, const NMatrixInt& subspace, const NEnumConstraintList* constraints, NProgressTracker* tracker, unsigned initialRows) { // Get the dimension of the entire space in which we are working. size_t dim = subspace.columns(); // If the space has dimension zero, return no results. if (dim == 0) return; // Choose a bitmask type that can hold dim bits. // Use a (much faster) optimised bitmask type if we can. // Then farm the work out to the real enumeration routine that is // templated on the bitmask type. if (dim <= 8 * sizeof(unsigned)) enumerateUsingBitmask >(results, subspace, constraints, tracker, initialRows); else if (dim <= 8 * sizeof(unsigned long)) enumerateUsingBitmask >(results, subspace, constraints, tracker, initialRows); #ifdef LONG_LONG_FOUND else if (dim <= 8 * sizeof(unsigned long long)) enumerateUsingBitmask >(results, subspace, constraints, tracker, initialRows); else if (dim <= 8 * sizeof(unsigned long long) + 8 * sizeof(unsigned)) enumerateUsingBitmask >(results, subspace, constraints, tracker, initialRows); else if (dim <= 8 * sizeof(unsigned long long) + 8 * sizeof(unsigned long)) enumerateUsingBitmask >( results, subspace, constraints, tracker, initialRows); else if (dim <= 16 * sizeof(unsigned long long)) enumerateUsingBitmask >(results, subspace, constraints, tracker, initialRows); #else else if (dim <= 8 * sizeof(unsigned long) + 8 * sizeof(unsigned)) enumerateUsingBitmask >(results, subspace, constraints, tracker, initialRows); else if (dim <= 16 * sizeof(unsigned long)) enumerateUsingBitmask >(results, subspace, constraints, tracker, initialRows); #endif else enumerateUsingBitmask(results, subspace, constraints, tracker, initialRows); } template void NHilbertDual::enumerateUsingBitmask(OutputIterator results, const NMatrixInt& subspace, const NEnumConstraintList* constraints, NProgressTracker* tracker, unsigned initialRows) { // Get the dimension of the entire space in which we are working. // At this point we are guaranteed that the dimension is non-zero. size_t dim = subspace.columns(); // Are there any hyperplanes at all in the subspace? size_t nEqns = subspace.rows(); if (nEqns == 0) { // No! Just send back the unit vectors. RayClass* ans; for (unsigned i = 0; i < dim; ++i) { ans = new RayClass(dim); ans->setElement(i, NLargeInteger::one); *results++ = ans; } if (tracker) tracker->setPercent(100); return; } // We actually have some work to do. // Process the hyperplanes in a good order. // // Sort the integers 0..(nEqns-1) into the order in which we plan to // process the hyperplanes. int* hyperplanes = new int[nEqns]; unsigned i; for (i = 0; i < nEqns; ++i) hyperplanes[i] = i; std::sort(hyperplanes + initialRows, hyperplanes + nEqns, NPosOrder(subspace)); // Convert the set of constraints into bitmasks, where for every // original coordinate listed in the constraint, the corresponding // bit is set to 1. BitmaskType* constraintsBegin = 0; BitmaskType* constraintsEnd = 0; if (constraints && ! constraints->empty()) { constraintsBegin = new BitmaskType[constraints->size()]; NEnumConstraintList::const_iterator cit; for (cit = constraints->begin(), constraintsEnd = constraintsBegin; cit != constraints->end(); ++cit, ++constraintsEnd) { constraintsEnd->reset(dim); constraintsEnd->set(cit->begin(), cit->end(), true); } } // Create the vector list with which we will work. // Fill it with the initial basis elements. std::vector*> list; for (i = 0; i < dim; ++i) list.push_back(new VecSpec(i, dim)); #if 0 std::cout << "LIST SIZE: " << list.size() << std::endl; #endif // Intersect the hyperplanes one at a time. for (i=0; isetPercent(100.0 * i / nEqns)) break; } // We're done! delete[] hyperplanes; delete[] constraintsBegin; typename std::vector*>::iterator it; if (tracker && tracker->isCancelled()) { // The operation was cancelled. Clean up before returning. for (it = list.begin(); it != list.end(); ++it) delete *it; return; } RayClass* ans; for (it = list.begin(); it != list.end(); ++it) { ans = new RayClass(dim); for (i = 0; i < dim; ++i) ans->setElement(i, (**it)[i]); *results++ = ans; delete *it; } // All done! if (tracker) tracker->setPercent(100); } template bool NHilbertDual::reduces(const VecSpec& vec, const std::list*>& against, int listSign) { typename std::list*>::const_iterator it; for (it = against.begin(); it != against.end(); ++it) { if (! (**it <= vec)) continue; if (listSign > 0) { if ((**it).nextHyp() <= vec.nextHyp()) return true; } else if (listSign < 0) { if (vec.nextHyp() <= (**it).nextHyp()) return true; } else { if (vec.nextHyp() == (**it).nextHyp()) return true; } } return false; } template void NHilbertDual::reduceBasis(std::list*>& reduce, std::list*>& against, int listSign) { if (reduce.empty()) return; typename std::list*>::iterator i, next, red; bool processed; i = reduce.begin(); next = i; ++next; while (i != reduce.end()) { processed = true; for (red = against.begin(); red != against.end(); ++red) { if (red == i) { processed = false; continue; } if (! (**red <= **i)) continue; if (listSign > 0) { if ((**red).nextHyp() <= (**i).nextHyp()) break; } else if (listSign < 0) { if ((**i).nextHyp() <= (**red).nextHyp()) break; } else { if ((**i).nextHyp() == (**red).nextHyp()) break; } } if (red == against.end()) { i = next; if (next != reduce.end()) ++next; continue; } delete *i; reduce.erase(i); #ifdef __REGINA_HILBERT_DUAL_OPT_DARWIN // Darwinistic reordering of the list against. if (processed) { against.push_front(*red); against.erase(red); i = next; if (next != reduce.end()) ++next; } else { // Both reduce and against are the same list, and the // reducing vector is one we haven't processed yet. if (red == next) ++next; against.push_front(*red); against.erase(red); i = against.begin(); } #else i = next; if (next != reduce.end()) ++next; #endif } } template void NHilbertDual::intersectHyperplane(std::vector*>& list, const NMatrixInt& subspace, unsigned row, const BitmaskType* constraintsBegin, const BitmaskType* constraintsEnd) { // These must be linked lists because we need fast insertion and // deletion at arbitrary locations. std::list*> zero, pos, neg, newZero, newPos, newNeg; typename std::list*>::iterator it, posit, negit; typename std::list*>::iterator posPrevGen, negPrevGen; // Decant the existing basis elements into 0/+/- sets according to the // new hyperplane. int s; typename std::vector*>::iterator srcit; for (srcit = list.begin(); srcit != list.end(); srcit++) { (*srcit)->initNextHyp(subspace, row); s = (*srcit)->sign(); if (s == 0) zero.push_back(*srcit); else if (s < 0) neg.push_back(*srcit); else pos.push_back(*srcit); } list.clear(); posPrevGen = pos.begin(); negPrevGen = neg.begin(); // TODO: Optimise from here down: (d), Sec.3 // Keep enlarging these sets until they enlarge no more. const BitmaskType* cit; BitmaskType comb, tmpMask; std::set::const_iterator coordit; bool broken; bool reachedPosPrevGen; VecSpec sum(subspace.columns()); #if 0 std::cerr << "Start iteration:" << std::endl; #endif while (true) { #if 0 std::cerr << " Intermediate 0/+/-: " << zero.size() << ' ' << pos.size() << ' ' << neg.size() << std::endl; #endif // Generate all valid (pos + neg) pairs that cannot be reduced using // the present lists. reachedPosPrevGen = false; for (posit = pos.begin(); posit != pos.end(); ++posit) { if (posit == posPrevGen) reachedPosPrevGen = true; for (negit = (reachedPosPrevGen ? neg.begin() : negPrevGen); negit != neg.end(); ++negit) { #ifdef __REGINA_HILBERT_DUAL_OPT_BI16D // Check for guaranteed redundany. // See Bruns-Ichim, Remark 16(d). // Bruns and Ichim use strict inequalities, but the same // argument shows that non-strict inequalities will work also. if ((*posit)->srcNextHyp() > 0 && (*negit)->nextHyp() <= - (*posit)->srcNextHyp()) continue; if ((*negit)->srcNextHyp() < 0 && (*posit)->nextHyp() >= - (*negit)->srcNextHyp()) continue; #endif // Check for validity. if (constraintsBegin) { comb = (*posit)->mask(); comb |= (*negit)->mask(); broken = false; for (cit = constraintsBegin; cit != constraintsEnd; ++cit) { tmpMask = comb; tmpMask &= (*cit); if (! tmpMask.atMostOneBit()) { broken = true; break; } } if (broken) continue; } // Check whether the vector can be reduced; if not, use it. // We CANNOT reorder pos or neg at this point. sum.formSum(**posit, **negit); s = sum.sign(); if (s == 0) { if (! reduces(sum, zero, 0)) newZero.push_back(new VecSpec(sum)); } else if (s > 0) { // If this decomposes as a sum of (possibly many) // terms in pos and/or zero, at least one such term must // be in pos. Therefore we only need to test // reduction against pos, and not zero also. if (! reduces(sum, pos, 1)) #ifndef __REGINA_HILBERT_DUAL_OPT_NEWGEN_STRICT_ONLY if (! reduces(sum, zero, 1)) #endif newPos.push_back(new VecSpec(sum)); } else if (s < 0) { // Likewise: test only against neg, and not zero also. if (! reduces(sum, neg, -1)) #ifndef __REGINA_HILBERT_DUAL_OPT_NEWGEN_STRICT_ONLY if (! reduces(sum, zero, -1)) #endif newNeg.push_back(new VecSpec(sum)); } } } if (newZero.empty() && newPos.empty() && newNeg.empty()) { // The basis has not changed, which means we're done. break; } // Independently reduce the basis on each side. reduceBasis(newZero, newZero, 0); reduceBasis(zero, newZero, 0); reduceBasis(newPos, newPos, 1); reduceBasis(pos, newPos, 1); reduceBasis(newNeg, newNeg, -1); reduceBasis(neg, newNeg, -1); // Add the new vectors to the bases. zero.splice(zero.end(), newZero); if (newPos.empty()) { posPrevGen = pos.end(); } else { posPrevGen = newPos.begin(); pos.splice(pos.end(), newPos); } if (newNeg.empty()) { negPrevGen = neg.end(); } else { negPrevGen = newNeg.begin(); neg.splice(neg.end(), newNeg); } } // We have a final Hilbert basis! // Clean up and return. for (it = pos.begin(); it != pos.end(); ++it) delete *it; for (it = neg.begin(); it != neg.end(); ++it) delete *it; for (it = zero.begin(); it != zero.end(); ++it) list.push_back(*it); } } // namespace regina #endif regina-4.96/engine/enumerate/nhilbertdual.h000644 000765 000024 00000057232 12377775116 020721 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file enumerate/nhilbertdual.h * \brief Provides a modified dual algorithm for Hilbert basis enumeration. */ #ifndef __NHILBERTDUAL_H #ifndef __DOXYGEN #define __NHILBERTDUAL_H #endif #include "regina-core.h" #include "maths/nmatrixint.h" #include "maths/nray.h" #include #include #include #ifndef __DOXYGEN // Optimisations: /** * Bruns and Ichim, J. Algebra 324 (2010), 1098-1113, remark 16(d). * This doesn't seem to help for fundamental normal surfaces (and in * fact seems to slow things down a small amount). */ // #define __REGINA_HILBERT_DUAL_OPT_BI16D /** * When generating new vectors, only reduce against older vectors * that lie in the corresponding strict half-space, and do not perform * the additional (and unnecessary) reduction against older vectors that * lie directly on the hyperplane. * In practice this does speed things up, but only a little. */ #define __REGINA_HILBERT_DUAL_OPT_NEWGEN_STRICT_ONLY /** * When reducing a potential basis, "darwinistically" reorder it so * that successful reducers are near the front. See Bruns and Ichim, * J. Algebra 324 (2010), 1098-1113, remark 6(a). * In practice, for fundamental normal surfaces this does not seem * to help (and in fact it slows things down a little). */ // #define __REGINA_HILBERT_DUAL_OPT_DARWIN #endif namespace regina { class NEnumConstraintList; class NMatrixInt; class NProgressTracker; /** * \weakgroup enumerate * @{ */ /** * Implements a modified dual algorithm for enumerating Hilbert bases. * This is based on the dual algorithm as described in * "Normaliz: Algorithms for affine monoids and rational cones", * Winfried Bruns and Bogdan Ichim, J. Algebra 324 (2010), 1098-1113, * and has been modified to allow for additional constraints (such as * the quadrilateral constraints from normal surface theory). * * All routines of interest within this class are static; no object of * this class should ever be created. * * \ifacespython Not present. */ class NHilbertDual { public: /** * Determines the Hilbert basis that generates all integer * points in the intersection of the n-dimensional * non-negative orthant with the given linear subspace. * The resulting basis elements will be of the class \a RayClass, * will be newly allocated, and will be written to the given output * iterator. Their deallocation is the responsibility of whoever * called this routine. * * The non-negative orthant is an n-dimensional cone with * its vertex at the origin. The extremal rays of this cone are * the \a n non-negative coordinate axes. This cone also has \a n * facets, where the ith facet is the non-negative * orthant of the plane perpendicular to the ith coordinate * axis. * * This routine takes a linear subspace, defined by the * intersection of a set of hyperplanes through the origin (this * subspace is described as a matrix, with each row giving the * equation for one hyperplane). * * The purpose of this routine is to compute the Hilbert basis of * the set of all integer points in the intersection of the * original cone with this linear subspace. The resulting list * of basis vectors will contain no duplicates or redundancies. * * Parameter \a constraints may contain a set of validity constraints, * in which case this routine will only return \e valid basis elements. * Each validity constraint is of the form "a basis element may only * lie outside at most one of these facets of the original * cone"; see the NEnumConstraintList class for details. These * contraints have the important property that, although validity is * not preserved under addition, \e invalidity is. * * An optional progress tracker may be passed. If so, this routine * will update the percentage progress and poll for cancellation * requests. It will be assumed that an appropriate stage has already * been declared via NProgressTracker::newStage() before this routine * is called, and that NProgressTracker::setFinished() will be * called after this routine returns. * * \pre The template argument RayClass is derived from NRay (or * may possibly be NRay itself). * * @param results the output iterator to which the resulting basis * elements will be written; this must accept objects of type * RayClass*. * @param subspace a matrix defining the linear subspace to intersect * with the given cone. Each row of this matrix is the equation * for one of the hyperplanes whose intersection forms this linear * subspace. The number of columns in this matrix must be the * dimension of the overall space in which we are working. * @param constraints a set of validity constraints as described * above, or 0 if no additional constraints should be imposed. * @param tracker a progress tracker through which progress * will be reported, or 0 if no progress reporting is required. * @param initialRows specifies how many initial rows of \a subspace * are to be processed in the precise order in which they appear. * The remaining rows will be sorted using the NPosOrder class * before they are processed. */ template static void enumerateHilbertBasis(OutputIterator results, const NMatrixInt& subspace, const NEnumConstraintList* constraints, NProgressTracker* tracker = 0, unsigned initialRows = 0); private: /** * A helper class for Hilbert basis enumeration, describing a * single vector (which is typically a basis element in some * partial solution space). * * The coordinates of the vector are inherited through the * superclass NRay. * * In addition, this class stores a data member \a nextHyp_, * which gives fast access to the dot product of this vector * with the hyperplane currently being processed. * * The \a BitmaskType template argument is used to store one bit * per coordinate, which is \c false if the coordinate is zero * or \c true if the coordinate is non-zero. * * \pre The template argument \a BitmaskType is one of Regina's * bitmask types, such as NBitmask, NBitmask1 or NBitmask2. */ template class VecSpec : private NRay { private: NLargeInteger nextHyp_; /**< The dot product of this vector with the hyperplane currently being processed. */ BitmaskType mask_; /**< A bitmask indicating which coordinates are zero (\c false) and which are non-zero (\c true). */ #ifdef __REGINA_HILBERT_DUAL_OPT_BI16D NLargeInteger srcNextHyp_; /**< Stores information from the summands used to create this vector. See srcNextHyp() for details. */ #endif public: /** * Creates the zero vector. * * @param dim the total dimension of the space (and * therefore the toatl length of this vector). */ inline VecSpec(size_t dim); /** * Creates the given unit vector. * * The \a nextHyp_ data member will be left uninitialised. * * @param pos indicates which coordinate is set to one * in this unit vector. * @param dim the total dimension of the space (and * therefore the total length of this vector). */ inline VecSpec(size_t pos, size_t dim); /** * Creates a clone of the given vector. * * @param other the vector to clone. */ inline VecSpec(const VecSpec& other); /** * Updates the \a nextHyp_ member to reflect the dot * product with the given hyperplane. * * This routine also sets the member \a srcNextHyp_ to zero. * * @param subspace the matrix containing the full set of * hyperplanes. * @param row the row of the given matrix that stores * the specific hyperplane in which we are interested. */ inline void initNextHyp(const NMatrixInt& subspace, unsigned row); /** * Sets this to the sum of the two given vectors. * * \pre pos.nextHyp() > 0, and * neg.nextHyp() < 0. * * @param pos the first vector to add, which must lie on * the strictly positive side of the current hyperplane. * @param neg the second vector to add, which must lie * on the strictly negative side of the current hyperplane. */ inline void formSum(const VecSpec& pos, const VecSpec& neg); /** * Returns the dot product of this vector with the * hyperplane currently being processed. */ inline const NLargeInteger& nextHyp() const; /** * Returns the bitmask describing which coordinate are * non-zero. */ inline const BitmaskType& mask() const; /** * Returns the sign of the dot product of this vector * with the hyperplane currently being processed. This * is simply the sign of the data member \a nextHyp_. * * @return 1, 0 or -1 according to the sign of \a nextHyp_. */ inline int sign() const; #ifdef __REGINA_HILBERT_DUAL_OPT_BI16D /** * Returns information from the summands used to * create this vector. * * Specifically: Suppose this vector was created using * formSum(). If nextHyp() ≥ 0, then this routine returns * pos.nextHyp() where \a pos was the * positive summand passed to formSum(). * If nextHyp() < 0, then this routine returns * neg.nextHyp() where \a neg was the * negative summand passed to formSum(). * * If this vector was not created using formSum(), * or if initNextHyp() has since been called, then this * routine returns zero. * * @return the summand information as described above. */ inline const NLargeInteger& srcNextHyp() const; #endif /** * Determines if this and the given vector are identical. * * @param other the vector to compare with this. * @return \c true if this vector is identical to the * given vector, or \c false if not. */ inline bool operator == (const VecSpec& other) const; /** * Determines if every element of this vector is less * than or equal to every element of the given vector. * * @param other the vector to compare with this. * @return \c true if every element of this vector is * less than or equal to every element of \a other, or * \c false otherwise. */ inline bool operator <= (const VecSpec& other) const; using NRay::operator []; }; /** * Identical to the public routine enumerateHilbertBasis(), * except that there is an extra template parameter \a BitmaskType. * This describes what type should be used for bitmasks that * represent zero/non-zero coordinates in a vector. * * All argument are identical to those for the public routine * enumerateHilbertBasis(). * * \pre The bitmask type is one of Regina's bitmask types, such * as NBitmask, NBitmask1 or NBitmask2. * \pre The type \a BitmaskType can handle at least \a n bits, * where \a n is the number of coordinates in the underlying vectors. */ template static void enumerateUsingBitmask(OutputIterator results, const NMatrixInt& subspace, const NEnumConstraintList* constraints, NProgressTracker* tracker, unsigned initialRows); /** * Private constructor to ensure that objects of this class are * never created. */ NHilbertDual(); /** * Test whether the vector \a vec can be reduced using * any of the candidate basis vectors in \a against. * * We say that \a vec reduces against a candidate basis vector * \a b if and only if: * * - the vector vec-b is non-negative; * - if \a listSign is 0, then vec-b lies on the * hyperplane currently under investigation; * - if \a listSign is positive, then vec-b lies either * on or to the positive side of the hyperplane under investigation; * - if \a listSign is negative, then vec-b lies either * on or to the negative side of the hyperplane under investigation. * * This routine uses VecSpec::nextHyp() to determine the * relationships between vectors and the current hyperplane. * * @param vec the vector to test for reducibility. * @param against the list of candidate basis vectors to reduce * \a vec against. * @param listSign an integer indicating which sign of the * current hyperplane we are working on. * @return \c true if the given vector can be reduced, or \c false * otherwise. */ template static bool reduces(const VecSpec& vec, const std::list*>& against, int listSign); /** * Removes all vectors from \reduce that can be reduced against * any of the candidate basis vectors in \a against. * This routine might also reorder the list \a against in the * hope of detecting future reductions more quickly. * For details of what reduction means, see reduces() above. * * This routine will work even if \a reduce and \a against are * the same list. * * @param reduce the list of vectors to test for reducibility. * @param against the list of candidate basis vectors to reduce against. * @param listSign an integer indicating which sign of the * current hyperplane we are working on. */ template static void reduceBasis(std::list*>& reduce, std::list*>& against, int listSign); /** * Updates a Hilbert basis by intersecting with a new hyperplane. * * The input vectors in \a list should contain the Hilbert basis * of a cone (defined as the intersection of the non-negative * orthant with some linear subspace). This routine converts * \list into the Hilbert basis of this same cone intersected with * a new hyperplane. The new hyperplane is defined by the given * row of the \a subspace matrix. * * This routine can optionally enforce a set of validity * constraints (such as the normal surface quadrilateral * constraints), as described in enumerateHilbertBasis(). * * The set of validity constraints must be passed here as a * C-style array of bitmasks. Each bitmask contains one bit per * coordinate position, as seen in the VecSpec inner class. * Each constraint is of the form "at most one of these * coordinates can be non-zero"; the bits for these coordinates must * be set to 1 in the corresponding bitmask, and all other bits must * be set to 0. * * @param list contains the original Hilbert basis on entry to * this function, and will contain the updated Hilbert basis upon * returning. * @param subspace a matrix of hyperplanes. * @param row indicates which row of \a subspace contains the * hyperplane that we will intersect with the cone defined by * the old Hilbert basis. * @param constraintsBegin the beginning of the C-style array of * validity constraints. This should be 0 if no additional * constraints are to be imposed. * @param constraintsEnd a pointer just past the end of the * C-style array of validity constraints. This should be 0 * if no additional constraints are to be imposed. */ template static void intersectHyperplane( std::vector*>& list, const NMatrixInt& subspace, unsigned row, const BitmaskType* constraintsBegin, const BitmaskType* constraintsEnd); }; /*@}*/ // Inline functions for NHilbertDual inline NHilbertDual::NHilbertDual() { } // Inline functions for NHilbertDual::VecSpec template inline NHilbertDual::VecSpec::VecSpec(size_t dim) : NRay(dim), mask_(dim) { // All vector elements, nextHyp_ and srcNextHyp_ are initialised to // zero thanks to the NLargeInteger default constructor. } template inline NHilbertDual::VecSpec::VecSpec(size_t pos, size_t dim) : NRay(dim), mask_(dim) { // All coordinates are initialised to zero by default thanks to // the NLargeInteger constructor. setElement(pos, NLargeInteger::one); mask_.set(pos, true); } template inline NHilbertDual::VecSpec::VecSpec( const NHilbertDual::VecSpec& other) : NRay(other), nextHyp_(other.nextHyp_), #ifdef __REGINA_HILBERT_DUAL_OPT_BI16D srcNextHyp_(other.srcNextHyp_), #endif mask_(other.mask_) { } template inline void NHilbertDual::VecSpec::initNextHyp( const NMatrixInt& subspace, unsigned row) { nextHyp_ = NLargeInteger::zero; NLargeInteger tmp; for (int i = 0; i < subspace.columns(); ++i) if (subspace.entry(row, i) != 0 && (*this)[i] != 0) { tmp = subspace.entry(row, i); tmp *= (*this)[i]; nextHyp_ += tmp; } #ifdef __REGINA_HILBERT_DUAL_OPT_BI16D srcNextHyp_ = 0; #endif } template inline void NHilbertDual::VecSpec::formSum( const NHilbertDual::VecSpec& pos, const NHilbertDual::VecSpec& neg) { (*this) = pos; // The default assignment operator. (*this) += neg; nextHyp_ += neg.nextHyp_; mask_ |= neg.mask_; #ifdef __REGINA_HILBERT_DUAL_OPT_BI16D if (nextHyp_ >= 0) srcNextHyp_ = pos.nextHyp_; else srcNextHyp_ = neg.nextHyp_; #endif } template inline const NLargeInteger& NHilbertDual::VecSpec::nextHyp() const { return nextHyp_; } template inline const BitmaskType& NHilbertDual::VecSpec::mask() const { return mask_; } template inline int NHilbertDual::VecSpec::sign() const { return (nextHyp_ == 0 ? 0 : nextHyp_ > 0 ? 1 : -1); } #ifdef __REGINA_HILBERT_DUAL_OPT_BI16D template inline const NLargeInteger& NHilbertDual::VecSpec::srcNextHyp() const { return srcNextHyp_; } #endif template inline bool NHilbertDual::VecSpec::operator == ( const NHilbertDual::VecSpec& other) const { // Begin with simple tests that give us a fast way of saying no. if (! (mask_ == other.mask_)) return false; return (static_cast(*this) == static_cast(other)); } template inline bool NHilbertDual::VecSpec::operator <= ( const NHilbertDual::VecSpec& other) const { // Begin with simple tests that give us a fast way of saying no. if (! (mask_ <= other.mask_)) return false; for (unsigned i = 0; i < size(); ++i) if ((*this)[i] > other[i]) return false; return true; } } // namespace regina // Template definitions #include "enumerate/nhilbertdual-impl.h" #endif regina-4.96/engine/enumerate/nhilbertdual.tcc000644 000765 000024 00000004672 12400001235 021206 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file enumerate/nhilbertdual.tcc * \brief Deprecated header. */ #warning This header is deprecated; please use nhilbertdual-impl.h instead. #include "enumerate/nhilbertdual-impl.h" regina-4.96/engine/enumerate/nhilbertprimal-impl.h000644 000765 000024 00000021073 12377775117 022212 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /* To be included from nhilbertprimal.h. */ #ifndef __NHILBERTPRIMAL_IMPL_H #ifndef __DOXYGEN #define __NHILBERTPRIMAL_IMPL_H #endif #include "regina-core.h" #include "regina-config.h" #include "enumerate/nenumconstraint.h" #include "enumerate/nhilbertprimal.h" #include "enumerate/nmaxadmissible.h" #include "enumerate/normaliz/cone.h" #include "maths/nray.h" #include "progress/nprogresstracker.h" #include #include #include #include namespace regina { template void NHilbertPrimal::enumerateHilbertBasis(OutputIterator results, const RayIterator& raysBegin, const RayIterator& raysEnd, const NEnumConstraintList* constraints, NProgressTracker* tracker) { if (raysBegin == raysEnd) { // No extremal rays; no Hilbert basis. return; } // Get the dimension of the space. size_t dim = (*raysBegin)->size(); if (dim == 0) return; // Choose a bitmask type that can hold dim bits. // Use a (much faster) optimised bitmask type if we can. // Then farm the work out to the real enumeration routine that is // templated on the bitmask type. if (dim <= 8 * sizeof(unsigned)) enumerateUsingBitmask >(results, raysBegin, raysEnd, constraints, tracker); else if (dim <= 8 * sizeof(unsigned long)) enumerateUsingBitmask >(results, raysBegin, raysEnd, constraints, tracker); #ifdef LONG_LONG_FOUND else if (dim <= 8 * sizeof(unsigned long long)) enumerateUsingBitmask >(results, raysBegin, raysEnd, constraints, tracker); else if (dim <= 8 * sizeof(unsigned long long) + 8 * sizeof(unsigned)) enumerateUsingBitmask >(results, raysBegin, raysEnd, constraints, tracker); else if (dim <= 8 * sizeof(unsigned long long) + 8 * sizeof(unsigned long)) enumerateUsingBitmask >( results, raysBegin, raysEnd, constraints, tracker); else if (dim <= 16 * sizeof(unsigned long long)) enumerateUsingBitmask >(results, raysBegin, raysEnd, constraints, tracker); #else else if (dim <= 8 * sizeof(unsigned long) + 8 * sizeof(unsigned)) enumerateUsingBitmask >(results, raysBegin, raysEnd, constraints, tracker); else if (dim <= 16 * sizeof(unsigned long)) enumerateUsingBitmask >(results, raysBegin, raysEnd, constraints, tracker); #endif else enumerateUsingBitmask(results, raysBegin, raysEnd, constraints, tracker); } template void NHilbertPrimal::enumerateUsingBitmask(OutputIterator results, const RayIterator& raysBegin, const RayIterator& raysEnd, const NEnumConstraintList* constraints, NProgressTracker* tracker) { // We know at this point that the dimension is non-zero. size_t dim = (*raysBegin)->size(); // First enumerate all maximal admissible faces. if (tracker) tracker->setPercent(10); std::vector* maxFaces = NMaxAdmissible::enumerate( raysBegin, raysEnd, constraints); // Now use normaliz to process each face. if (tracker) tracker->setPercent(30); std::set > finalBasis; std::vector face; typename std::vector::const_iterator mit; RayIterator rit; unsigned i; std::vector >::const_iterator hlit; std::set >::const_iterator hsit; std::vector::const_iterator hvit; for (mit = maxFaces->begin(); mit != maxFaces->end(); ++mit) { // Locate the extremal rays that generate this face. std::vector > input; for (rit = raysBegin; rit != raysEnd; ++rit) if (inFace(**rit, *mit)) { input.push_back(std::vector()); std::vector& v(input.back()); v.reserve(dim); for (i = 0; i < dim; ++i) { if ((**rit)[i].isNative()) v.push_back(mpz_class((**rit)[i].longValue())); else v.push_back(mpz_class((**rit)[i].rawData())); } } libnormaliz::Cone cone(input, libnormaliz::Type::integral_closure); libnormaliz::ConeProperties wanted( libnormaliz::ConeProperty::HilbertBasis); cone.compute(wanted); if (! cone.isComputed(libnormaliz::ConeProperty::HilbertBasis)) { // TODO: Bail properly. std::cerr << "ERROR: Hilbert basis not computed!" << std::endl; continue; } const std::vector > basis = cone.getHilbertBasis(); for (hlit = basis.begin(); hlit != basis.end(); ++hlit) finalBasis.insert(*hlit); } if (tracker) tracker->setPercent(90); RayClass* ans; NLargeInteger tmpInt; for (hsit = finalBasis.begin(); hsit != finalBasis.end(); ++hsit) { ans = new RayClass(dim); for (i = 0, hvit = hsit->begin(); hvit != hsit->end(); ++hvit, ++i) { // We make two copies of the GMP integer instead of one. // This is because NVector/NRay does not give us direct // non-const access to its elements, and so we need a // temporary NLargeInteger to pass through setElement() instead. tmpInt.setRaw(hvit->get_mpz_t()); ans->setElement(i, tmpInt); } *results++ = ans; } // All done! delete maxFaces; if (tracker) tracker->setPercent(100); } template bool NHilbertPrimal::inFace(const NRay& ray, const BitmaskType& face) { for (unsigned i = 0; i < ray.size(); ++i) if ((! face.get(i)) && ray[i] > 0) return false; return true; } } // namespace regina #endif regina-4.96/engine/enumerate/nhilbertprimal.h000644 000765 000024 00000022735 12377775121 021254 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file enumerate/nhilbertprimal.h * \brief Provides a modified primal algorithm for Hilbert basis enumeration. */ #ifndef __NHILBERTPRIMAL_H #ifndef __DOXYGEN #define __NHILBERTPRIMAL_H #endif #include "regina-core.h" #include "maths/nmatrixint.h" #include #include namespace regina { class NEnumConstraintList; class NMatrixInt; class NProgressTracker; class NRay; /** * \weakgroup enumerate * @{ */ /** * Implements a modified primal algorithm for enumerating Hilbert bases. * This incorporates the primal algorithm described in * "Normaliz: Algorithms for affine monoids and rational cones", * Winfried Bruns and Bogdan Ichim, J. Algebra 324 (2010), 1098-1113, * and has been modified to allow for additional constraints (such as * the quadrilateral constraints from normal surface theory). * * To summarise: the algorithm first enumerates extremal rays of the rational * cone, and then decomposes the admissible region of the cone (where the * extra constraints are satisfied) into maximal admissible faces. * It calls Normaliz directly to enumerate the Hilbert basis for * each maximal admissible faces, and finally combines these into a basis * for the entire space. * * All routines of interest within this class are static; no object of * this class should ever be created. * * \ifacespython Not present. */ class NHilbertPrimal { public: /** * Determines the Hilbert basis that generates all integer * points in the intersection of the n-dimensional * non-negative orthant with some linear subspace. * The resulting basis elements will be of the class \a RayClass, * will be newly allocated, and will be written to the given output * iterator. Their deallocation is the responsibility of whoever * called this routine. * * The intersection of the non-negative orthant with this linear * subspace is a pointed polyhedral cone with apex at the origin, * and this routine requires the extremal rays of this cone to * be provided as input. The extremal rays can be computed * using NDoubleDescription::enumerate() in general cases, * though sometimes (such as with normal surface theory) more * efficient methods are available. * * This routine computes the Hilbert basis of all integer points in * this cone. The resulting list of basis vectors will contain * no duplicates or redundancies. * * The parameter \a constraints may contain a set of validity * constraints, in which case this routine will only return \e valid * basis elements. Each validity constraint is of the form "at * most one of these coordinates may be non-zero"; see the * NEnumConstraintList class for details. These contraints have the * important property that, although validity is not preserved under * addition, \e invalidity is. * * An optional progress tracker may be passed. If so, this routine * will update the percentage progress and poll for cancellation * requests. It will be assumed that an appropriate stage has already * been declared via NProgressTracker::newStage() before this routine * is called, and that NProgressTracker::setFinished() will be * called after this routine returns. * * \pre If \a constraints is passed, then the given list of * extremal rays contains \e only those extremal rays that satisfy * all of the given constraints. * \pre The template argument RayClass is derived from NRay (or * may possibly be NRay itself). * \pre The template argument RayIterator is a forward iterator type, * and when dereferenced can be cast to (const NRay*). * * \warning If a progress tracker is passed, be aware that the * present implementation updates percentage progress very infrequently, * and may take a very long time to honour cancellation requests. * * @param results the output iterator to which the resulting basis * elements will be written; this must accept objects of type * RayClass*. * @param raysBegin an iterator pointing to the beginning of the * list of extremal rays. * @param raysEnd an iterator pointing past the end of the * list of extremal rays. * @param constraints a set of validity constraints as described * above, or 0 if no additional constraints should be imposed. * @param tracker a progress tracker through which progress * will be reported, or 0 if no progress reporting is required. */ template static void enumerateHilbertBasis(OutputIterator results, const RayIterator& raysBegin, const RayIterator& raysEnd, const NEnumConstraintList* constraints, NProgressTracker* tracker = 0); private: /** * Identical to the public routine enumerateHilbertBasis(), * except that there is an extra template parameter \a BitmaskType. * This describes what type should be used for bitmasks that * represent maximal admissible faces. * * All arguments to this function are identical to those for the * public routine enumerateHilbertBasis(). * * \pre The bitmask type is one of Regina's bitmask types, such * as NBitmask, NBitmask1 or NBitmask2. * \pre The type \a BitmaskType can handle at least \a n bits, * where \a n is the dimension of the Euclidean space (i.e., the * number of columns in \a subspace). */ template static void enumerateUsingBitmask(OutputIterator results, const RayIterator& raysBegin, const RayIterator& raysEnd, const NEnumConstraintList* constraints, NProgressTracker* tracker); /** * Determines whether the given ray lies in the face specified * by the given bitmask. * * Faces are described using bitmasks in the same manner as described * by NMaxAdmissible::enumerate(), where \c true represents a * coordinate that is non-zero in the relative interior of the * face, and \c false represents a coordinate that is always * zero throughout the face. * * @param ray the ray to test, given as a vector of integers. * @param face the face to test, given as a bitmask. * @return \c true if the given ray lies within the given face, * or \c false otherwise. */ template static bool inFace(const NRay& ray, const BitmaskType& face); /** * Private constructor to ensure that objects of this class are * never created. */ NHilbertPrimal(); }; /*@}*/ // Inline functions for NHilbertPrimal inline NHilbertPrimal::NHilbertPrimal() { } } // namespace regina // Template definitions #include "enumerate/nhilbertprimal-impl.h" #endif regina-4.96/engine/enumerate/nhilbertprimal.tcc000644 000765 000024 00000004700 12400001237 021537 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file enumerate/nhilbertprimal.tcc * \brief Deprecated header. */ #warning This header is deprecated; please use nhilbertprimal-impl.h instead. #include "enumerate/nhilbertprimal-impl.h" regina-4.96/engine/enumerate/nmaxadmissible-impl.h000644 000765 000024 00000015044 12377775122 022173 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /* To be included from nmaxadmissible.h. */ #ifndef __NMAXADMISSIBLE_IMPL_H #ifndef __DOXYGEN #define __NMAXADMISSIBLE_IMPL_H #endif #include "enumerate/nenumconstraint.h" #include "enumerate/nmaxadmissible.h" #include #include namespace regina { template std::vector* NMaxAdmissible::enumerate( RayIterator beginExtremalRays, RayIterator endExtremalRays, const NEnumConstraintList* constraints) { if (beginExtremalRays == endExtremalRays) { // Input is empty, so output is empty. return new std::vector(); } size_t dim = (*beginExtremalRays)->size(); BitmaskType b(dim); int i; // Rewrite the constraints as bitmasks. std::vector constMasks; if (constraints) { NEnumConstraintList::const_iterator cit; std::set::const_iterator sit; for (cit = constraints->begin(); cit != constraints->end(); ++cit) { b.reset(); for (sit = cit->begin(); sit != cit->end(); ++sit) b.set(*sit, true); constMasks.push_back(b); } } // Create a set of bitmasks representing the admissible 1-faces of // the cone, i.e., the set of admissible extremal rays. std::vector rays; for (RayIterator rit = beginExtremalRays; rit != endExtremalRays; ++rit) { for (i = 0; i < dim; ++i) b.set(i, (**rit)[i] != 0); rays.push_back(b); } // Create a working set of admissible faces. // We initialise this to the set of all admissible 1-faces, as above. std::list faces(rays.begin(), rays.end()); // Create the final set of faces to return. std::vector* maxFaces = new std::vector(); // Keep expanding the faces using additional extremal rays until we can // expand no more. // The ith iteration of the following loop enumerates _all_ admissible // faces of dimension i+1, and identifies all _maximal_ admissible // faces of dimension i. std::list nextDim; typename std::vector::const_iterator r, c; typename std::list::const_iterator f; typename std::list::iterator n, next; bool isMax, broken; while (! faces.empty()) { for (f = faces.begin(); f != faces.end(); ++f) { // Expand this face by combining with other extremal rays. isMax = true; for (r = rays.begin(); r != rays.end(); ++r) { BitmaskType comb(*f); comb |= *r; // Ignore rays already in this face. if (comb == *f) continue; // Ignore rays that will break admissibility. broken = false; for (c = constMasks.begin(); c != constMasks.end(); ++c) { b = comb; b &= *c; if (! b.atMostOneBit()) { broken = true; break; } } if (broken) continue; // comb expands *f to a higher-dimensional superface. isMax = false; // Strip out duplicates, and also strip out superfaces of // too high a dimension (since we only want to step up one // dimension at a time). broken = false; n = nextDim.begin(); while (n != nextDim.end()) { next = n; ++next; if (*n <= comb) { // comb has too high a dimension, or is a duplicate. broken = true; break; } if (comb <= *n) { // *n has too high a dimension. nextDim.erase(n); } n = next; } if (! broken) nextDim.push_back(comb); } if (isMax) maxFaces->push_back(*f); } std::swap(nextDim, faces); nextDim.clear(); } // All done! return maxFaces; } } // namespace regina #endif regina-4.96/engine/enumerate/nmaxadmissible.h000644 000765 000024 00000015030 12377775124 021231 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file enumerate/nmaxadmissible.h * \brief Provides an algorithm for enumerating maximal faces of a * polyhedral cone that satisfy a set of admissibility constraints. */ #ifndef __NMAXADMISSIBLE_H #ifndef __DOXYGEN #define __NMAXADMISSIBLE_H #endif #include "regina-core.h" #include "utilities/nbitmask.h" #include namespace regina { class NEnumConstraintList; /** * \weakgroup enumerate * @{ */ /** * Used to enumerate all maximal admissible faces of a polyhedral cone * under a given set of admissibility constraints. See the routine * enumerate() for details. * * All routines of interest within this class are static; no object of * this class should ever be created. * * \ifacespython Not present. */ class NMaxAdmissible { public: /** * Enumerates all maximal admissible faces of the given polyhedral cone. * The cone must be the intersection of the non-negative orthant in some * Euclidean space R^n with a linear subspace. * * Admissibility is defined by the given set of constraints. Each * constraint requires that at most one of a given set of coordinates * can be non-zero; see the NEnumConstraintList class for details. * In particular, the quadrilateral constraints from normal surface * theory are of this type. * * It is simple to show that the admissible region of the cone is a * union of faces, which we call "admissible faces". Those admissible * faces that do not appear as a strict subface of some other * admissible face are called "maximal admissible faces". * The admissible region can therefore be expressed as the union of * all maximal admissible faces. * * The input for this routine is the set of all admissible extremal rays * of the cone. These should be computed beforehand; for instance, * using the routine NDoubleDescription::enumerateExtremalRays(). * * The return value is the set of all maximal admissible faces, stored * in a newly allocated vector. Each face \a F is described by a * bitmask. Specifically: if we are working in R^n, then each face is * described by a bitmask \a b of length n, where b[i] * is \c false if every point \a x in \a F has x[i]=0, * and b[i] is \c true if every point \a x in the relative * interior of \a F has x[i] > 0. * * \pre The template argument RayIterator should be an iterator * type that, when dereferenced, can be cast to a const NRay*. * * \pre The template argument BitmaskType is one of the bitmask * types NBitmask, NBitmask1 or NBitmask2. * * \pre Bitmasks of type BitmaskType can hold \a n bits, where * \a n is the dimension of the underlying space (i.e., the size * of the input vectors described by \a beginExtremalRays and * \a endExtremalRays). This is always true of NBitmask, but * you must be careful when using one of the fast but size-limited * types NBitmask1 or NBitmask2. * * @param beginExtremalRays an iterator that begins the set of * admissible extremal rays, as described above. Typically this would * be rays.begin() if \a rays is a standard container type. * @param endExtremalRays an iterator that is past-the-end of the set * of admissible extremal rays. Typically this would be rays.end() * if \a rays is a standard container type. * @param constraints a set of validity constraints as described * above. This may be 0 to indicate no constraints (in which * case there will be just one maximal admissible face). * @return a newly allocated list containing one bitmask * representing each maximal admissible face, as described above. */ template static std::vector* enumerate( RayIterator beginExtremalRays, RayIterator endExtremalRays, const NEnumConstraintList* constraints); }; /*@}*/ } // namespace regina // Template definitions #include "enumerate/nmaxadmissible-impl.h" #endif regina-4.96/engine/enumerate/nmaxadmissible.tcc000644 000765 000024 00000004700 12400001240 021515 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file enumerate/nmaxadmissible.tcc * \brief Deprecated header. */ #warning This header is deprecated; please use nmaxadmissible-impl.h instead. #include "enumerate/nmaxadmissible-impl.h" regina-4.96/engine/enumerate/normaliz/CMakeLists.txt000644 000765 000024 00000000634 12311266525 022443 0ustar00babstaff000000 000000 # enumerate/normaliz # Files to compile SET ( FILES HilbertSeries cone_property libnormaliz-templated ) # Prepend folder name FOREACH ( SOURCE_FILE ${FILES} ) SET ( SOURCES ${SOURCES} enumerate/normaliz/${SOURCE_FILE}) ENDFOREACH(SOURCE_FILE) # Set the variable in the parent directory SET(SOURCES ${SOURCES} PARENT_SCOPE) # Normaliz headers should not be shipped: these are for internal use only. regina-4.96/engine/enumerate/normaliz/cone.cpp000644 000765 000024 00000105103 12311266525 021330 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include #include "cone.h" #include "full_cone.h" namespace libnormaliz { using namespace std; // adds the signs inequalities given by Signs to Inequalities template Matrix sign_inequalities(const vector< vector >& Signs) { if (Signs.size() != 1) { errorOutput() << "ERROR: Bad signs matrix, has " << Signs.size() << " rows (should be 1)!" << endl; throw BadInputException(); } size_t dim = Signs[0].size(); Matrix Inequ(0,dim); vector ineq(dim,0); for (size_t i=0; i Cone::Cone(const vector< vector >& Input, InputType input_type) { initialize(); if (!Input.empty()) { dim = Input.front().size(); if (input_type == Type::rees_algebra || input_type == Type::polytope) { dim++; // we add one component } if (input_type == Type::congruences) { dim--; //congruences have one extra column } } single_matrix_input(Input, input_type); } template Cone::Cone(const map< InputType, vector< vector > >& multi_input_data) { initialize(); typename map< InputType , vector< vector > >::const_iterator it; //determine dimension it = multi_input_data.begin(); for(; it != multi_input_data.end(); ++it) { if (!it->second.empty()) { dim = it->second.front().size(); if (it->first == Type::rees_algebra || it->first == Type::polytope) { dim++; // we add one component } if (it->first == Type::congruences) { dim--; //congruences have one extra column } break; } } //check for a grading it = multi_input_data.find(Type::grading); if (it != multi_input_data.end()) { vector< vector > lf = it->second; if (lf.size() != 1) { errorOutput() << "ERROR: Bad grading, has " << lf.size() << " rows (should be 1)!" << endl; throw BadInputException(); } setGrading (lf[0]); } it = multi_input_data.begin(); if (multi_input_data.size() == 1) { // use the "one-matrix-input" method single_matrix_input(it->second,it->first); } else if (multi_input_data.size() == 2 && isComputed(ConeProperty::Grading)) { if (it->first == Type::grading) it++; single_matrix_input(it->second,it->first); } else { // now we have to have constraints! Matrix Inequalities(0,dim), Equations(0,dim), Congruences(0,dim+1), Signs(0,dim); for (; it != multi_input_data.end(); ++it) { if (it->second.size() == 0) { continue; } switch (it->first) { case Type::hyperplanes: if (it->second.begin()->size() != dim) { errorOutput() << "Dimensions of hyperplanes ("<second.begin()->size()<<") do not match dimension of other constraints ("<second; break; case Type::equations: if (it->second.begin()->size() != dim) { errorOutput() << "Dimensions of equations ("<second.begin()->size()<<") do not match dimension of other constraints ("<second; break; case Type::congruences: if (it->second.begin()->size() != dim+1) { errorOutput() << "Dimensions of congruences ("<second.begin()->size()<<") do not match dimension of other constraints ("<second; break; case Type::signs: if (it->second.begin()->size() != dim) { errorOutput() << "Dimensions of hyperplanes ("<second.begin()->size()<<") do not match dimension of other constraints ("<second); break; case Type::grading: break; //skip the grading default: errorOutput() << "This InputType combination is currently not supported!" << endl; throw BadInputException(); } } if(!BC_set) compose_basis_change(Sublattice_Representation(dim)); Inequalities.append(Signs); prepare_input_type_456(Congruences, Equations, Inequalities); } } /* only used by the constructors */ template void Cone::initialize() { BC_set=false; is_Computed = bitset(); //initialized to false dim = 0; rees_primary = false; } template void Cone::single_matrix_input(const vector< vector >& Input, InputType input_type) { switch (input_type) { case Type::integral_closure: prepare_input_type_0(Input); break; case Type::normalization: prepare_input_type_1(Input); break; case Type::polytope: prepare_input_type_2(Input); break; case Type::rees_algebra: prepare_input_type_3(Input); break; case Type::signs: prepare_input_type_45(vector >(), sign_inequalities(Input)); break; case Type::hyperplanes: prepare_input_type_45(vector >(), Input); break; case Type::equations: prepare_input_type_45(Input, vector >()); break; case Type::congruences: prepare_input_type_456(Input, vector >(), vector >()); break; case Type::lattice_ideal: prepare_input_type_10(Input); break; case Type::grading: errorOutput() << "Grading as only input not supported!" << endl; // no break, go to default default: throw BadInputException(); } if(!BC_set) compose_basis_change(Sublattice_Representation(dim)); } /* check what is computed */ template bool Cone::isComputed(ConeProperty::Enum prop) const { return is_Computed.test(prop); } template bool Cone::isComputed(ConeProperties CheckComputed) const { return CheckComputed.reset(is_Computed).any(); } /* getter */ template Sublattice_Representation Cone::getBasisChange() const{ return BasisChange; } template vector< vector > Cone::getGeneratorsOfToricRing() const { return GeneratorsOfToricRing; } template vector< vector > Cone::getGenerators() const { return Generators; } template vector< vector > Cone::getExtremeRays() const { return Matrix(Generators).submatrix(ExtremeRays).get_elements(); } template vector< vector > Cone::getSupportHyperplanes() const { return SupportHyperplanes; } //TODO gehts nicht auch in der SR? template vector< vector > Cone::getEquations() const { size_t rank = BasisChange.get_rank(); size_t nr_of_equ = dim-rank; if (rank == 0) // the zero cone return Matrix(dim).get_elements(); // identity matrix Matrix Equations(nr_of_equ,dim); if (nr_of_equ > 0) { Lineare_Transformation NewLT = Transformation(Matrix(getExtremeRays())); Matrix Help = NewLT.get_right().transpose(); for (size_t i = rank; i < dim; i++) { Equations.write(i-rank,Help.read(i)); } } return Equations.get_elements(); } template vector< vector > Cone::getCongruences() const { return BasisChange.get_congruences().get_elements(); } template map< InputType , vector< vector > > Cone::getConstraints () const { map > > c; c.insert(pair< InputType,vector< vector > >(Type::hyperplanes,SupportHyperplanes)); c.insert(pair< InputType,vector< vector > >(Type::equations,getEquations())); c.insert(pair< InputType,vector< vector > >(Type::congruences,getCongruences())); return c; } template const vector< pair,Integer> >& Cone::getTriangulation() const { return Triangulation; } template const list< STANLEYDATA >& Cone::getStanleyDec() const { return StanleyDec; } template size_t Cone::getTriangulationSize() const { return TriangulationSize; } template Integer Cone::getTriangulationDetSum() const { return TriangulationDetSum; } template vector< vector > Cone::getHilbertBasis() const { return HilbertBasis; } template vector< vector > Cone::getDeg1Elements() const { return Deg1Elements; } template const HilbertSeries& Cone::getHilbertSeries() const { return HSeries; } template vector Cone::getGrading() const { return Grading; } template Integer Cone::getGradingDenom() const { return GradingDenom; } template mpq_class Cone::getMultiplicity() const { return multiplicity; } template bool Cone::isPointed() const { return pointed; } template bool Cone::isDeg1ExtremeRays() const { return deg1_extreme_rays; } template bool Cone::isDeg1HilbertBasis() const { return deg1_hilbert_basis; } template bool Cone::isIntegrallyClosed() const { return integrally_closed; } template bool Cone::isReesPrimary() const { return rees_primary; } template Integer Cone::getReesPrimaryMultiplicity() const { return ReesPrimaryMultiplicity; } //--------------------------------------------------------------------------- template void Cone::compose_basis_change(const Sublattice_Representation& BC) { if (BC_set) { BasisChange.compose(BC); } else { BasisChange = BC; BC_set = true; } } //--------------------------------------------------------------------------- template void Cone::prepare_input_type_0(const vector< vector >& Input) { Generators = Input; is_Computed.set(ConeProperty::Generators); Sublattice_Representation Basis_Change(Matrix(Input),true); compose_basis_change(Basis_Change); } //--------------------------------------------------------------------------- template void Cone::prepare_input_type_1(const vector< vector >& Input) { Generators = Input; is_Computed.set(ConeProperty::Generators); Sublattice_Representation Basis_Change(Matrix(Input),false); compose_basis_change(Basis_Change); } //--------------------------------------------------------------------------- /* polytope input */ template void Cone::prepare_input_type_2(const vector< vector >& Input) { size_t j; size_t nr = Input.size(); if (nr == 0) { Generators = Input; } else { //append a column of 1 Generators = vector< vector >(nr, vector(dim)); for (size_t i=0; i(Matrix(Generators),true)); // use the added last component as grading Grading = vector(dim,0); Grading[dim-1] = 1; is_Computed.set(ConeProperty::Grading); } //--------------------------------------------------------------------------- /* rees input */ template void Cone::prepare_input_type_3(const vector< vector >& InputV) { Matrix Input(InputV); int i,j,k,l,nr_rows=Input.nr_of_rows(), nr_columns=Input.nr_of_columns(); rees_primary=true; Integer number; Matrix Full_Cone_Generators(nr_rows+nr_columns,nr_columns+1,0); for (i = 0; i < nr_columns; i++) { Full_Cone_Generators.write(i,i,1); } for(i=0; i Prim_Test=Input; for(i=0; i=nr_rows) { rees_primary=false; break; } } is_Computed.set(ConeProperty::ReesPrimary); Generators = Full_Cone_Generators.get_elements(); is_Computed.set(ConeProperty::Generators); compose_basis_change(Sublattice_Representation(Full_Cone_Generators.nr_of_columns())); } //--------------------------------------------------------------------------- template void Cone::prepare_input_type_456(const Matrix& Congruences, const Matrix& Equations, const Matrix& Inequalities) { size_t nr_cong = Congruences.nr_of_rows(); // handle Congurences if (nr_cong > 0) { size_t i,j; //add slack variables Matrix Cong_Slack(nr_cong, dim+nr_cong); for (i = 0; i < nr_cong; i++) { for (j = 0; j < dim; j++) { Cong_Slack.write(i,j,Congruences.read(i,j)); } Cong_Slack.write(i,dim+i,Congruences.read(i,dim)); } //compute kernel Lineare_Transformation Diagonalization = Transformation(Cong_Slack); size_t rank = Diagonalization.get_rank(); Matrix H = Diagonalization.get_right(); Matrix Ker_Basis_Transpose(dim, dim+nr_cong-rank); for (i = 0; i < dim; i++) { for (j = rank; j < dim+nr_cong; j++) { Ker_Basis_Transpose.write(i, j-rank, H.read(i,j)); } } //TODO now a new linear transformation is computed, necessary?? Sublattice_Representation Basis_Change(Ker_Basis_Transpose.transpose(),false); compose_basis_change(Basis_Change); } prepare_input_type_45(Equations, Inequalities); } //--------------------------------------------------------------------------- template void Cone::prepare_input_type_45(const Matrix& Equations, const Matrix& Inequalities) { // use positive orthant if no inequalities are given if (Inequalities.nr_of_rows() == 0) { if (verbose) { verboseOutput() << "No inequalities specified in constraint mode, using non-negative space." << endl; } SupportHyperplanes = (Matrix(dim)).get_elements(); } else { SupportHyperplanes = Inequalities.get_elements(); } is_Computed.set(ConeProperty::SupportHyperplanes); if(!BC_set) compose_basis_change(Sublattice_Representation(dim)); size_t i,j; if (Equations.nr_of_rows()>0) { Lineare_Transformation Diagonalization = Transformation(BasisChange.to_sublattice_dual(Equations)); size_t rank=Diagonalization.get_rank(); Matrix Help=Diagonalization.get_right(); Matrix Ker_Basis_Transpose(dim,dim-rank); for (i = 0; i < dim; i++) { for (j = rank; j < dim; j++) { Ker_Basis_Transpose.write(i,j-rank,Help.read(i,j)); } } Sublattice_Representation Basis_Change(Ker_Basis_Transpose.transpose(),true); compose_basis_change(Basis_Change); } } //--------------------------------------------------------------------------- template void Cone::prepare_input_type_10(const vector< vector >& BinomialsV) { Matrix Binomials(BinomialsV); size_t i,j, nr_of_monoid_generators = dim; if (isComputed(ConeProperty::Grading)) { //check if binomials are homogeneous vector degrees = Binomials.MxV(Grading); for (size_t i=0; i Diagonalization=Transformation(Binomials); size_t rank=Diagonalization.get_rank(); Matrix Help=Diagonalization.get_right(); Matrix Generators(nr_of_monoid_generators,nr_of_monoid_generators-rank); for (i = 0; i < nr_of_monoid_generators; i++) { for (j = rank; j < nr_of_monoid_generators; j++) { Generators.write(i,j-rank,Help.read(i,j)); } } Full_Cone FC(Generators); //TODO verboseOutput(), what is happening here? FC.support_hyperplanes(); Matrix Supp_Hyp=FC.getSupportHyperplanes(); Matrix Selected_Supp_Hyp_Trans=(Supp_Hyp.submatrix(Supp_Hyp.max_rank_submatrix_lex())).transpose(); Matrix Positive_Embedded_Generators=Generators.multiplication(Selected_Supp_Hyp_Trans); GeneratorsOfToricRing = Positive_Embedded_Generators.get_elements(); is_Computed.set(ConeProperty::GeneratorsOfToricRing); dim = Positive_Embedded_Generators.nr_of_columns(); if (isComputed(ConeProperty::Grading)) { // solve GeneratorsOfToricRing * grading = old_grading Grading = Positive_Embedded_Generators.solve(Grading); if (Grading.size() != dim) { errorOutput() << "Grading could not be transfered!"< void Cone::setGrading (const vector& lf) { if (lf.size() != dim) { errorOutput() << "Grading linear form has wrong dimension " << lf.size() << " (should be " << dim << ")" << endl; throw BadInputException(); } //check if the linear forms are the same if (isComputed(ConeProperty::Grading) && Grading == lf) { return; } if (isComputed(ConeProperty::Generators)) { vector degrees = Matrix(Generators).MxV(lf); for (size_t i=0; i ConeProperties Cone::compute(ConeProperties ToCompute) { if (ToCompute.test(ConeProperty::DualMode)) compute_dual(); /* preparation: get generators if necessary */ compute_generators(); if (!isComputed(ConeProperty::Generators)) { errorOutput()<<"FATAL ERROR: Could not get Generators. This should not happen!"< FC(BasisChange.to_sublattice(Matrix(Generators))); /* activate bools in FC */ bool only_support_hyperplanes = true; if (ToCompute.test(ConeProperty::HilbertSeries)) { FC.do_h_vector = true; only_support_hyperplanes = false; } if (ToCompute.test(ConeProperty::HilbertBasis)) { FC.do_Hilbert_basis = true; only_support_hyperplanes = false; } if (ToCompute.test(ConeProperty::Triangulation)) { FC.keep_triangulation = true; only_support_hyperplanes = false; } if (ToCompute.test(ConeProperty::Multiplicity)) { FC.do_multiplicity = true; only_support_hyperplanes = false; } if (ToCompute.test(ConeProperty::TriangulationSize)) { FC.do_triangulation = true; only_support_hyperplanes = false; } if (ToCompute.test(ConeProperty::Deg1Elements)) { FC.do_deg1_elements = true; only_support_hyperplanes = false; } if (ToCompute.test(ConeProperty::StanleyDec)) { FC.do_Stanley_dec = true; only_support_hyperplanes = false; } /* Give extra data to FC */ if ( isComputed(ConeProperty::ExtremeRays) ) { FC.Extreme_Rays = ExtremeRays; FC.is_Computed.set(ConeProperty::ExtremeRays); } if ( isComputed(ConeProperty::Grading) ) { FC.Grading = BasisChange.to_sublattice_dual(Grading); FC.is_Computed.set(ConeProperty::Grading); FC.set_degrees(); } /* Do the computation! */ if (only_support_hyperplanes) { // workaround for not dualizing twice if (isComputed(ConeProperty::SupportHyperplanes)) { vector< vector > vvSH = BasisChange.to_sublattice_dual(Matrix(SupportHyperplanes)).get_elements(); FC.Support_Hyperplanes = list< vector >(vvSH.begin(), vvSH.end()); FC.is_Computed.set(ConeProperty::SupportHyperplanes); } FC.support_hyperplanes(); } else { FC.compute(); } extract_data(FC); /* check if everything is computed*/ ToCompute.reset(is_Computed); //remove what is now computed if (ToCompute.any()) { errorOutput() << "Warning: Cone could not compute everything, that it was asked for!"< void Cone::compute_generators() { //create Generators from SupportHyperplanes if (!isComputed(ConeProperty::Generators) && isComputed(ConeProperty::SupportHyperplanes)) { if (verbose) { verboseOutput() < Dual_Cone(BasisChange.to_sublattice_dual(Matrix(SupportHyperplanes))); Dual_Cone.support_hyperplanes(); if (Dual_Cone.isComputed(ConeProperty::SupportHyperplanes)) { //get the extreme rays of the primal cone Matrix Extreme_Rays=Dual_Cone.getSupportHyperplanes(); Generators = BasisChange.from_sublattice(Extreme_Rays).get_elements(); is_Computed.set(ConeProperty::Generators); ExtremeRays = vector(Generators.size(),true); is_Computed.set(ConeProperty::ExtremeRays); if (Dual_Cone.isComputed(ConeProperty::ExtremeRays)) { //get minmal set of support_hyperplanes Matrix Supp_Hyp = Dual_Cone.getGenerators().submatrix(Dual_Cone.getExtremeRays()); SupportHyperplanes = BasisChange.from_sublattice_dual(Supp_Hyp).get_elements(); } Sublattice_Representation Basis_Change(Extreme_Rays,true); compose_basis_change(Basis_Change); //compute denominator of Grading if (isComputed(ConeProperty::Grading) && Generators.size() > 0) { GradingDenom = v_scalar_product(Grading,Generators[0]); GradingDenom /= v_scalar_product(BasisChange.to_sublattice_dual(Grading),BasisChange.to_sublattice(Generators[0])); //TODO in Sublattice Rep berechnen lassen } } } } template ConeProperties Cone::compute(ComputationMode mode) { if (mode == Mode::dual) { return compute_dual(); } else { ConeProperties cps; cps.set(mode); return compute(cps); } } template ConeProperties Cone::compute_dual() { if(isComputed(ConeProperty::Generators) && !isComputed(ConeProperty::SupportHyperplanes)){ if (verbose) { verboseOutput() < Tmp_Cone(BasisChange.to_sublattice(Matrix(Generators))); Tmp_Cone.support_hyperplanes(); extract_data(Tmp_Cone); } if (!isComputed(ConeProperty::SupportHyperplanes)) { errorOutput()<<"FATAL ERROR: Could not get SupportHyperplanes. This should not happen!"< Inequ_on_Ker = BasisChange.to_sublattice_dual(Matrix(SupportHyperplanes)); size_t newdim = Inequ_on_Ker.nr_of_columns(); //now sort the inequalities, hopefully this makes the computation faster Integer norm; vector< Integer > hyperplane; multimap > SortingHelp; typename multimap >::const_iterator ii; for (i = 0; i < Inequ_on_Ker.nr_of_rows() ; i++) { hyperplane=Inequ_on_Ker.read(i); norm=0; for (j = 0; j > (norm,hyperplane)); } Matrix Inequ_Ordered(Inequ_on_Ker.nr_of_rows(),newdim); i=0; for (ii=SortingHelp.begin(); ii != SortingHelp.end(); ii++) { Inequ_Ordered.write(i,(*ii).second); i++; } Cone_Dual_Mode ConeDM(Inequ_Ordered); ConeDM.hilbert_basis_dual(); //create a Full_Cone out of ConeDM if ( ConeDM.Generators.rank() < ConeDM.dim ) { Sublattice_Representation SR(ConeDM.Generators,true); ConeDM.to_sublattice(SR); compose_basis_change(SR); } Full_Cone FC(ConeDM); // Give extra data to FC if ( isComputed(ConeProperty::Grading) ) { FC.Grading = BasisChange.to_sublattice_dual(Grading); FC.is_Computed.set(ConeProperty::Grading); FC.set_degrees(); } FC.dual_mode(); extract_data(FC); is_Computed.set(ConeProperty::DualMode); return ConeProperties(); } template void Cone::extract_data(Full_Cone& FC) { //this function extracts ALL available data from the Full_Cone //even if it was in Cone already <- this may change //it is possible to delete the data in Full_Cone after extracting it if(verbose) { verboseOutput() << "transforming data..."<, Integer> >(tri_size); SHORTSIMPLEX simp; for (size_t i = 0; i 0) { GradingDenom = v_scalar_product(Grading,Generators[0]); GradingDenom /= v_scalar_product(FC.getGrading(),FC.Generators[0]); } } if (FC.isComputed(ConeProperty::IsDeg1HilbertBasis)) { deg1_hilbert_basis = FC.isDeg1HilbertBasis(); is_Computed.set(ConeProperty::IsDeg1HilbertBasis); } if (FC.isComputed(ConeProperty::IsIntegrallyClosed)) { integrally_closed = FC.isIntegrallyClosed(); is_Computed.set(ConeProperty::IsIntegrallyClosed); } if (verbose) { verboseOutput() << " done." <. * */ #ifndef CONE_H_ #define CONE_H_ #include #include #include "libnormaliz.h" #include "cone_property.h" #include "sublattice_representation.h" #include "HilbertSeries.h" namespace libnormaliz { using std::vector; using std::map; using std::pair; template class Full_Cone; template class Matrix; // type for simplex, short in contrast to class Simplex template struct SHORTSIMPLEX { vector key; // full key of simplex Integer height; // height of last vertex over opposite facet Integer vol; // volume if computed, 0 else }; template struct STANLEYDATA { vector key; Matrix offsets; }; template class Cone { //--------------------------------------------------------------------------- // public methods //--------------------------------------------------------------------------- public: //--------------------------------------------------------------------------- // Constructors, they preprocess the input //--------------------------------------------------------------------------- /* give a single matrix as input */ Cone(const vector< vector >& input_data, InputType type = Type::integral_closure); /* give multiple input */ Cone(const map< InputType , vector< vector > >& multi_input_data); //--------------------------------------------------------------------------- // give additional data //--------------------------------------------------------------------------- /* Sets the linear form which is used to grade. * It has to be an N-grading, i.e. all generators must have a value >=1. * If it is not, a subclass of NormalizException will be thrown at the * time of detection which can be in this method or later! * It will delete all data from the cone that depend on the grading! */ void setGrading (const vector& lf); //--------------------------------------------------------------------------- // make computations //--------------------------------------------------------------------------- // return what was NOT computed ConeProperties compute(ComputationMode mode = Mode::hilbertBasisSeries); //default: everything ConeProperties compute(ConeProperties ToCompute); //is done by compiler throug creation of CPies // return true iff it could be computed ConeProperties compute(ConeProperty::Enum prop); //--------------------------------------------------------------------------- // check what is computed //--------------------------------------------------------------------------- bool isComputed(ConeProperty::Enum prop) const; //returns true, when ALL properties in CheckComputed are computed bool isComputed(ConeProperties CheckComputed) const; //--------------------------------------------------------------------------- // get the results, these methods do not start a computation //--------------------------------------------------------------------------- size_t getDim() const { return dim; }; vector< vector > getGenerators() const; vector< vector > getExtremeRays() const; vector< vector > getSupportHyperplanes() const; vector< vector > getEquations() const; vector< vector > getCongruences() const; map< InputType , vector< vector > > getConstraints() const; size_t getTriangulationSize() const; Integer getTriangulationDetSum() const; vector< vector > getHilbertBasis() const; vector< vector > getDeg1Elements() const; vector getGrading() const; Integer getGradingDenom() const; mpq_class getMultiplicity() const; bool isPointed() const; bool isDeg1ExtremeRays() const; bool isDeg1HilbertBasis() const; bool isIntegrallyClosed() const; bool isReesPrimary() const; Integer getReesPrimaryMultiplicity() const; vector< vector > getGeneratorsOfToricRing() const; Sublattice_Representation getBasisChange() const; // the following methods return const refs to avoid copying of big data objects const HilbertSeries& getHilbertSeries() const; //general purpose object const vector< pair, Integer> >& getTriangulation() const; const list< STANLEYDATA >& getStanleyDec() const; //--------------------------------------------------------------------------- // private part //--------------------------------------------------------------------------- private: size_t dim; Sublattice_Representation BasisChange; //always use compose_basis_change() ! bool BC_set; ConeProperties is_Computed; vector< vector > GeneratorsOfToricRing; vector< vector > Generators; vector ExtremeRays; vector< vector > SupportHyperplanes; size_t TriangulationSize; Integer TriangulationDetSum; vector< pair, Integer> > Triangulation; list< STANLEYDATA > StanleyDec; mpq_class multiplicity; vector< vector > HilbertBasis; vector< vector > Deg1Elements; HilbertSeries HSeries; vector< vector > HilbertQuasiPolynomial; vector Grading; Integer GradingDenom; bool pointed; bool deg1_extreme_rays; bool deg1_hilbert_basis; bool integrally_closed; bool rees_primary; Integer ReesPrimaryMultiplicity; void compose_basis_change(const Sublattice_Representation& SR); // composes SR /* Progress input, depending on input_type */ void prepare_input_type_0(const vector< vector >& Input); void prepare_input_type_1(const vector< vector >& Input); void prepare_input_type_2(const vector< vector >& Input); void prepare_input_type_3(const vector< vector >& Input); void prepare_input_type_10(const vector< vector >& Binomials); void prepare_input_type_456(const Matrix& Congruences, const Matrix& Equations, const Matrix& Inequalities); void prepare_input_type_45(const Matrix& Equations, const Matrix& Inequalities); /* only used by the constructors */ void initialize(); void single_matrix_input(const vector< vector >& Input, InputType input_type); /* compute the generators using the support hyperplanes */ void compute_generators(); /* compute method for the dual_mode, used in compute(mode) */ ConeProperties compute_dual(); /* extract the data from Full_Cone, this may remove data from Full_Cone!*/ void extract_data(Full_Cone& FC); }; } //end namespace libnormaliz #endif /* CONE_H_ */ regina-4.96/engine/enumerate/normaliz/cone_dual_mode.cpp000644 000765 000024 00000056363 12311266525 023356 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ //--------------------------------------------------------------------------- #include #include #include #include #include #include #include #include "cone_dual_mode.h" #include "vector_operations.h" #include "lineare_transformation.h" #include "list_operations.h" //--------------------------------------------------------------------------- namespace libnormaliz { using namespace std; //--------------------------------------------------------------------------- //private //--------------------------------------------------------------------------- template void Cone_Dual_Mode::splice_them(list< vector< Integer > >& Total, vector > >& Parts){ for(int i=0;i void Cone_Dual_Mode::record_order(list< vector< Integer > >& Elements, list< vector< Integer >* >& Order){ Order.clear(); typename list < vector >::iterator it=Elements.begin(); for(;it!=Elements.end();++it) { Order.push_back(&(*it)); } } //--------------------------------------------------------------------------- template bool Cone_Dual_Mode::reducible( list< vector< Integer >* >& Irred, const vector< Integer >& new_element, const size_t& size, const bool ordered){ size_t i,c=1; typename list< vector* >::iterator j; vector *reducer; for (j =Irred.begin(); j != Irred.end(); j++) { reducer=(*j); if (ordered && new_element[0]<2*(*reducer)[0]) { break; // if element is reducible, divisor of smallest degree will be found later } if (new_element[0]<=(*reducer)[0]) continue; if ((*reducer)[c]<=new_element[c]){ for (i = 1; i <=size ; i++) { if ((*reducer)[i]>new_element[i]){ c=i; break; } } if (i==size+1) { Irred.splice(Irred.begin(),Irred,j); return true; } } //new_element is reducible } return false; } //--------------------------------------------------------------------------- template void Cone_Dual_Mode::reduce(list< vector< Integer > >& Irred, list< vector< Integer > >& Red, const size_t& size){ list< vector< Integer >* > Irred_Reorder; record_order(Irred, Irred_Reorder); typename list< vector >::iterator s; for (s = Red.begin(); s != Red.end();) if(reducible(Irred_Reorder,*s,size,true)) s=Red.erase(s); else ++s; } //--------------------------------------------------------------------------- template void Cone_Dual_Mode::reduce_and_insert(const vector< Integer >& new_element, list >& Irred,const size_t& size){ size_t i,c=1; typename list< vector >::iterator j; for (j =Irred.begin(); j != Irred.end(); j++) { if (new_element[0]<2*(*j)[0]) { break; // if element is reducible, divisor of smallest degree will be found later } else { if ((*j)[c]<=new_element[c]){ for (i = 1; i <= size; i++) { if ((*j)[i]>new_element[i]){ c=i; break; } } if (i==size+1) { Irred.splice(Irred.begin(),Irred,j); return; } } } } Irred.push_back(new_element); } //--------------------------------------------------------------------------- template void Cone_Dual_Mode::auto_reduce(list< vector< Integer> >& To_Reduce, const size_t& size){ To_Reduce.sort(); list > Irred; typename list < vector >::iterator c; for (c=To_Reduce.begin(); c != To_Reduce.end(); ++c) { reduce_and_insert((*c),Irred,size); } To_Reduce.clear(); To_Reduce.splice(To_Reduce.begin(),Irred); To_Reduce.sort(); } //--------------------------------------------------------------------------- //public //--------------------------------------------------------------------------- template Cone_Dual_Mode::Cone_Dual_Mode(Matrix M){ dim=M.nr_of_columns(); if (dim!=M.rank()) { errorOutput()<<"Cone_Dual_Mode error: Matrix with rank = number of columns needed in the constructor of the object Cone_Dual_Mode.\nProbable reason: The Cone is not pointed!"<(static_cast(nr_sh))) { errorOutput()<<"To many support hyperplanes to fit in range of key_t!"< gcds = SupportHyperplanes.make_prime(); vector key=v_non_zero_pos(gcds); if (key.size() < nr_sh) { SupportHyperplanes=SupportHyperplanes.submatrix(key); nr_sh=SupportHyperplanes.nr_of_rows(); } hyp_size=dim+nr_sh; GeneratorList = list< vector >(); Hilbert_Basis = list< vector >(); } //--------------------------------------------------------------------------- template void Cone_Dual_Mode::print()const{ verboseOutput()<<"dim="< Matrix Cone_Dual_Mode::get_support_hyperplanes() const { return SupportHyperplanes; } //--------------------------------------------------------------------------- template Matrix Cone_Dual_Mode::get_generators()const{ return Generators; } //--------------------------------------------------------------------------- template Matrix Cone_Dual_Mode::read_hilbert_basis()const{ size_t s= Hilbert_Basis.size(); Matrix M(s,dim); size_t i; typename list< vector >::const_iterator l; for (i=0, l =Hilbert_Basis.begin(); l != Hilbert_Basis.end(); ++l, ++i) { M.write(i,(*l)); } return M; } //--------------------------------------------------------------------------- template void Cone_Dual_Mode::cut_with_halfspace_hilbert_basis(const size_t& hyp_counter, const bool& lifting, vector& halfspace){ if (verbose==true) { verboseOutput()<<"cut with halfspace "< > Positive_Irred,Negative_Irred,Neutral_Irred; Integer orientation, scalar_product,diff,factor; vector hyperplane=SupportHyperplanes.read(hyp_counter-1); typename list< vector >::iterator h; if (lifting==true) { orientation=v_scalar_product(hyperplane,halfspace); if(orientation<0){ orientation=-orientation; v_scalar_multiplication(halfspace,-1); //transforming into the generator of the positive halfspace } for (h = Hilbert_Basis.begin(); h != Hilbert_Basis.end(); ++h) { //reduction modulo the generator of the positive halfspace scalar_product=v_scalar_product_unequal_vectors_end(hyperplane,(*h)); sign=1; if (scalar_product<0) { scalar_product=-scalar_product; sign=-1; } factor=scalar_product/orientation; for (i = 0; i < dim; i++) { (*h)[nr_sh+3+i]=(*h)[nr_sh+3+i]-sign*factor*halfspace[i]; } } //adding the generators of the halfspace to negative and positive vector hyp_element(hyp_size+3,0); for (i = 0; i < dim; i++) { hyp_element[nr_sh+3+i]= halfspace[i]; } hyp_element[hyp_counter]=orientation; hyp_element[0]=orientation; if (orientation==0){ //never Neutral_Irred.push_back(hyp_element); } else{ Positive_Irred.push_back(hyp_element); v_scalar_multiplication(hyp_element,-1); hyp_element[hyp_counter]=orientation; hyp_element[0]=orientation; Negative_Irred.push_back(hyp_element); } } //end lifting for (h = Hilbert_Basis.begin(); h != Hilbert_Basis.end(); ++h) { //dividing into negative and positive (*h)[hyp_counter]=v_scalar_product_unequal_vectors_end(hyperplane,(*h)); if ((*h)[hyp_counter]>0) { (*h)[nr_sh+1]=1; // generation (*h)[nr_sh+2]=0; //not sum (*h)[0]+=(*h)[hyp_counter]; Positive_Irred.push_back((*h)); } if ((*h)[hyp_counter]<0) { (*h)[hyp_counter]=-(*h)[hyp_counter]; (*h)[nr_sh+1]=1; (*h)[nr_sh+2]=0; (*h)[0]+=(*h)[hyp_counter]; Negative_Irred.push_back((*h)); } if ((*h)[hyp_counter]==0) { (*h)[nr_sh+1]=0; (*h)[nr_sh+2]=0; Neutral_Irred.push_back((*h)); } } Neutral_Irred.sort(); Positive_Irred.sort(); Negative_Irred.sort(); //long int counter=0; list < vector > New_Positive,New_Negative,New_Neutral,Pos,Neg,Neu; vector > > New_Positive_thread(omp_get_max_threads()), New_Negative_thread(omp_get_max_threads()), New_Neutral_thread(omp_get_max_threads()); typename list < vector >::const_iterator p,n; typename list < vector >::iterator c; not_done=true; while(not_done){ not_done=false; New_Positive.clear(); New_Negative.clear(); New_Neutral.clear(); //generating new elements list < vector* > Positive,Negative,Neutral; // pointer lists, used to move reducers to the front size_t psize=0; #pragma omp parallel { #pragma omp single nowait record_order(Negative_Irred,Negative); #pragma omp single nowait record_order(Positive_Irred,Positive); #pragma omp single nowait psize=Positive_Irred.size(); #pragma omp single nowait record_order(Neutral_Irred,Neutral); } // END PARALLEL if (verbose) { size_t nsize=Negative_Irred.size(); size_t zsize=Neutral_Irred.size(); if (psize*nsize>1000000) verboseOutput()<<"Positive: "< ppos; ++ppos, ++p) ; for(;i < ppos; --ppos, --p) ; for (n = Negative_Irred.begin(); n != Negative_Irred.end(); ++n){ if ((*p)[nr_sh+1]<=1 && (*n)[nr_sh+1]<=1 && ((*p)[nr_sh+1]!=0 || (*n)[nr_sh+1]!=0)) { if (((*p)[nr_sh+2]!=0&&(*p)[nr_sh+2]<=(*n)[hyp_counter]) || ((*n)[nr_sh+2]!=0&&(*n)[nr_sh+2]<=(*p)[hyp_counter])) continue; // counter++; diff=(*p)[hyp_counter]-(*n)[hyp_counter]; vector new_candidate=v_add((*p),(*n)); if (diff>0) { new_candidate[hyp_counter]=diff; new_candidate[0]-=2*(*n)[hyp_counter]; if(reducible(Positive,new_candidate,hyp_counter,false)) { continue; } if(reducible(Neutral,new_candidate,hyp_counter-1,false)) { continue; } new_candidate[nr_sh+1]=2; new_candidate[nr_sh+2]=(*p)[hyp_counter]; // #pragma omp critical(NEW_POSITIVE) New_Positive_thread[omp_get_thread_num()].push_back(new_candidate); } if (diff<0) { new_candidate[hyp_counter]=-diff; new_candidate[0]-=2*(*p)[hyp_counter]; if(reducible(Negative,new_candidate,hyp_counter,false)) { continue; } if(reducible(Neutral,new_candidate,hyp_counter-1,false)) { continue; } new_candidate[nr_sh+1]=2; new_candidate[nr_sh+2]=(*n)[hyp_counter]; // #pragma omp critical(NEW_NEGATIVE) New_Negative_thread[omp_get_thread_num()].push_back(new_candidate); } if (diff==0) { new_candidate[hyp_counter]=0; new_candidate[0]-=2*(*p)[hyp_counter]; if(reducible(Neutral,new_candidate,hyp_counter-1,false)) { continue; } new_candidate[nr_sh+1]=0; new_candidate[nr_sh+2]=0; #pragma omp critical(NEW_NEUTRAL) New_Neutral_thread[omp_get_thread_num()].push_back(new_candidate); } } } } //end generation of new elements } //END PARALLEL #pragma omp parallel { #pragma omp single nowait { splice_them(New_Neutral,New_Neutral_thread); auto_reduce(New_Neutral,hyp_counter-1); } #pragma omp single nowait { splice_them(New_Positive,New_Positive_thread); auto_reduce(New_Positive,hyp_counter-1); } #pragma omp single nowait { splice_them(New_Negative,New_Negative_thread); auto_reduce(New_Negative,hyp_counter-1); } } // END PARALLEL if (New_Neutral.size()!=0) { #pragma omp parallel { #pragma omp single nowait reduce(New_Neutral,New_Positive, hyp_counter-1); #pragma omp single nowait reduce(New_Neutral,New_Negative, hyp_counter-1); #pragma omp single nowait reduce(New_Neutral,Neutral_Irred, hyp_counter-1); #pragma omp single nowait reduce(New_Neutral,Positive_Irred, hyp_counter-1); #pragma omp single nowait reduce(New_Neutral,Negative_Irred, hyp_counter-1); } // END PARALLEL Neutral_Irred.merge(New_Neutral); } #pragma omp parallel { #pragma omp single nowait if (New_Positive.size()!=0) { not_done=true; reduce(New_Positive,Positive_Irred, hyp_counter); Positive_Irred.merge(New_Positive); } #pragma omp single nowait if (New_Negative.size()!=0) { not_done=true; reduce(New_Negative,Negative_Irred, hyp_counter); Negative_Irred.merge(New_Negative); } } // PARALLEL // adjust generation #pragma omp parallel { #pragma omp single nowait for (c = Positive_Irred.begin(); c != Positive_Irred.end(); ++c){ if((*c)[nr_sh+1]>0) { (*c)[nr_sh+1]--; } } #pragma omp single nowait for (typename list < vector >::iterator c2 = Negative_Irred.begin(); c2 != Negative_Irred.end(); ++c2){ if((*c2)[nr_sh+1]>0) { (*c2)[nr_sh+1]--; } } } // END PARALLEL // verboseOutput()< >::iterator c; list zero_list; size_t i,j,k; for (c=Hilbert_Basis.begin(); c!=Hilbert_Basis.end(); ++c){ zero_list.clear(); for (i = 0; i < nr_sh; i++) { if ((*c)[i+1]==0) { zero_list.push_back(i); } } k=zero_list.size(); if (k>=dim-1) { vector zero_vector(k); for (j = 0; j < k; j++) { zero_vector[j]=zero_list.front(); zero_list.pop_front(); } Matrix Test=SupportHyperplanes.submatrix(zero_vector); if (Test.rank()>=dim-1) { GeneratorList.push_back((*c)); } } } size_t s = GeneratorList.size(); Generators = Matrix(s,dim); typename list< vector >::const_iterator l; for (i=0, l=GeneratorList.begin(); l != GeneratorList.end(); ++l, ++i) { Generators.write( i, v_cut_front(*l, dim) ); } } //--------------------------------------------------------------------------- template void Cone_Dual_Mode::hilbert_basis_dual(){ if(dim>0){ //correction needed to include the 0 cone; if (verbose==true) { verboseOutput()<<"\n************************************************************\n"; verboseOutput()<<"computing Hilbert basis ..."< Basis_Max_Subspace(dim); //identity matrix for (hyp_counter = 1; hyp_counter <= nr_sh; hyp_counter++) { Basis_Max_Subspace=cut_with_halfspace(hyp_counter,Basis_Max_Subspace); } extreme_rays_rank(); l_cut_front(Hilbert_Basis,dim); relevant_support_hyperplanes(); GeneratorList.clear(); } } //--------------------------------------------------------------------------- template void Cone_Dual_Mode::relevant_support_hyperplanes(){ if (verbose) { verboseOutput() << "Find relevant support hyperplanes" << endl; } list zero_list; typename list >::iterator gen_it; vector relevant_sh; relevant_sh.reserve(nr_sh); size_t i,k; size_t realdim = Generators.rank(); for (i = 0; i < nr_sh; ++i) { Matrix Test(0,dim); k = 0; for (gen_it = GeneratorList.begin(); gen_it != GeneratorList.end(); ++gen_it) { if ((*gen_it)[i+1]==0) { Test.append( v_cut_front(*gen_it,dim) ); k++; } } if (k >= realdim-1 && Test.rank_destructive()>=realdim-1) { relevant_sh.push_back(i); } } SupportHyperplanes = SupportHyperplanes.submatrix(relevant_sh); } //--------------------------------------------------------------------------- template void Cone_Dual_Mode::to_sublattice(Sublattice_Representation SR) { assert(SR.get_dim() == dim); dim = SR.get_rank(); hyp_size = dim+nr_sh; SupportHyperplanes = SR.to_sublattice_dual(SupportHyperplanes); typename list >::iterator it; vector tmp; Generators = SR.to_sublattice(Generators); for (it = Hilbert_Basis.begin(); it != Hilbert_Basis.end(); ) { tmp = SR.to_sublattice(*it); it = Hilbert_Basis.erase(it); Hilbert_Basis.insert(it,tmp); } } } //end namespace libnormaliz regina-4.96/engine/enumerate/normaliz/cone_dual_mode.h000644 000765 000024 00000011635 12311266525 023014 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #ifndef CONE_DUAL_MODE_H #define CONE_DUAL_MODE_H #include #include #include "libnormaliz.h" #include "matrix.h" #include "sublattice_representation.h" namespace libnormaliz { using std::list; using std::vector; template class Cone_Dual_Mode { public: size_t dim; size_t nr_sh; size_t hyp_size; Matrix SupportHyperplanes; Matrix Generators; list > GeneratorList; //only temporarily used list > Hilbert_Basis; /* --------------------------------------------------------------------------- * Private routines, used in the public routines * --------------------------------------------------------------------------- */ /* splices a vector of lists into a total list*/ void splice_them(list< vector< Integer > >& Total, vector > >& Parts); /* records the order of Elements in pointer list Order */ void record_order(list< vector< Integer > >& Elements, list< vector< Integer >* >& Order); /* Returns true if new_element is reducible versus the elements in Irred used for dual algorithm * ATTENTION: this is "random access" for new_element if ordered==false. * Otherrwise it is assumed that the new elements tested come in ascending total degree * after the list underlying Irred has been ordered the last time */ bool reducible(list *> & Irred, const vector & new_element, const size_t & size, const bool ordered); /* reduce Red versus Irred ATTENTION: both lists must be ordered by total degree * Irred will not be changed, Red is returned without the reducible elements, but no other * change * ATTENTION: not suitable for autoreduction */ void reduce(list > & Irred, list > & Red, const size_t & size); /* adds a new element that is irreducible w.r.t. Irred to Irred * the new elements must come from a structure sorted by total degree * used for dual algorithm */ void reduce_and_insert(const vector & new_element, list >& Irred, const size_t & size); /* reduces a list against itself * the list must be sorted sorted by total degree as used for dual algorithm * The irreducible elements are reurned in ascendingorder */ void auto_reduce(list< vector< Integer> >& To_Reduce, const size_t& size); /* computes the Hilbert basis after adding a support hyperplane with the dual algorithm */ void cut_with_halfspace_hilbert_basis(const size_t & hyp_counter, const bool & lifting, vector & halfspace); /* computes the Hilbert basis after adding a support hyperplane with the dual algorithm , general case */ Matrix cut_with_halfspace(const size_t & hyp_counter, const Matrix& Basis_Max_Subspace); /* computes the extreme rays using reduction, used for the dual algorithm */ void extreme_rays_reduction(); /* computes the extreme rays using rank test, used for the dual algorithm */ void extreme_rays_rank(); void relevant_support_hyperplanes(); Cone_Dual_Mode(Matrix M); //main constructor /*--------------------------------------------------------------------------- * Data access *--------------------------------------------------------------------------- */ void print() const; //to be modified, just for tests Matrix get_support_hyperplanes() const; Matrix get_generators() const; Matrix read_hilbert_basis() const; /*--------------------------------------------------------------------------- * Computation Methods *--------------------------------------------------------------------------- */ void hilbert_basis_dual(); /* transforms all data to the sublattice */ void to_sublattice(Sublattice_Representation SR); }; //class end ***************************************************************** } //--------------------------------------------------------------------------- #endif //--------------------------------------------------------------------------- regina-4.96/engine/enumerate/normaliz/cone_property.cpp000644 000765 000024 00000015071 12311266525 023300 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include #include #include "cone_property.h" #include "normaliz_exception.h" namespace libnormaliz { using std::bitset; using std::vector; using std::string; /* Constructors */ ConeProperties::ConeProperties() { CPs = bitset(); } ConeProperties::ConeProperties(ConeProperty::Enum p1) { CPs = bitset(); CPs.set(p1); } ConeProperties::ConeProperties(ConeProperty::Enum p1, ConeProperty::Enum p2) { CPs = bitset(); CPs.set(p1); CPs.set(p2); } ConeProperties::ConeProperties(const bitset& props){ CPs = props; } /* set Properties */ ConeProperties& ConeProperties::set(ConeProperty::Enum p1, bool value) { CPs.set(p1, value); return *this; } ConeProperties& ConeProperties::set(ConeProperty::Enum p1, ConeProperty::Enum p2) { CPs.set(p1); CPs.set(p2); return *this; } ConeProperties& ConeProperties::set(const ConeProperties& ConeProps) { CPs ^= ConeProps.CPs; return *this; } /* reset (=unset) properties */ ConeProperties& ConeProperties::reset(ConeProperty::Enum Property) { CPs.set(Property, false); return *this; } ConeProperties& ConeProperties::reset(const ConeProperties& ConeProps) { CPs &= ~ConeProps.CPs; return *this; } /* test which/how many properties are set */ bool ConeProperties::test(ConeProperty::Enum Property) const { return CPs.test(Property); } bool ConeProperties::any() const { return CPs.any(); } bool ConeProperties::none() const { return CPs.none(); } size_t ConeProperties::count () const { return CPs.count(); } /* this method sets all fields that should be computed in that mode */ ConeProperties& ConeProperties::set(Mode::ComputationMode mode) { switch (mode) { case Mode::supportHyperplanes: set(ConeProperty::SupportHyperplanes, ConeProperty::ExtremeRays); break; case Mode::triangulationSize: set(ConeProperty::TriangulationSize); break; case Mode::triangulation: set(ConeProperty::Triangulation); break; case Mode::volumeTriangulation: set(ConeProperty::Triangulation, ConeProperty::Multiplicity); break; case Mode::volumeLarge: set(ConeProperty::Multiplicity); break; case Mode::degree1Elements: set(ConeProperty::Deg1Elements); break; case Mode::hilbertBasisTriangulation: set(ConeProperty::HilbertBasis, ConeProperty::Triangulation); break; case Mode::hilbertBasisMultiplicity: set(ConeProperty::HilbertBasis, ConeProperty::Multiplicity); break; case Mode::hilbertBasisLarge: set(ConeProperty::HilbertBasis); break; case Mode::hilbertSeries: set(ConeProperty::Triangulation); case Mode::hilbertSeriesLarge: set(ConeProperty::Deg1Elements, ConeProperty::HilbertSeries); break; case Mode::hilbertBasisSeries: set(ConeProperty::Triangulation); case Mode::hilbertBasisSeriesLarge: set(ConeProperty::HilbertSeries, ConeProperty::HilbertBasis); break; case Mode::dual: set(ConeProperty::DualMode); break; default: throw FatalException(); break; } return *this; } /* conversion */ namespace { // only to initialize the CPN in ConePropertyNames vector initializeCPN() { vector CPN(ConeProperty::EnumSize); if (ConeProperty::EnumSize != 21) { //to detect changes in size of Enum errorOutput() << "Fatal Error: ConeProperties Enum size does not fit!" << std::endl; throw FatalException(); } CPN.at(ConeProperty::Generators) = "Generators"; CPN.at(ConeProperty::ExtremeRays) = "ExtremeRays"; CPN.at(ConeProperty::SupportHyperplanes) = "SupportHyperplanes"; CPN.at(ConeProperty::TriangulationSize) = "TriangulationSize"; CPN.at(ConeProperty::TriangulationDetSum) = "TriangulationDetSum"; CPN.at(ConeProperty::Triangulation) = "Triangulation"; CPN.at(ConeProperty::Multiplicity) = "Multiplicity"; CPN.at(ConeProperty::HilbertBasis) = "HilbertBasis"; CPN.at(ConeProperty::Deg1Elements) = "Deg1Elements"; CPN.at(ConeProperty::HilbertSeries) = "HilbertSeries"; CPN.at(ConeProperty::Grading) = "Grading"; CPN.at(ConeProperty::IsPointed) = "IsPointed"; CPN.at(ConeProperty::IsDeg1Generated) = "IsDeg1Generated"; CPN.at(ConeProperty::IsDeg1ExtremeRays) = "IsDeg1ExtremeRays"; CPN.at(ConeProperty::IsDeg1HilbertBasis) = "IsDeg1HilbertBasis"; CPN.at(ConeProperty::IsIntegrallyClosed) = "IsIntegrallyClosed"; CPN.at(ConeProperty::GeneratorsOfToricRing) = "GeneratorsOfToricRing"; CPN.at(ConeProperty::ReesPrimary) = "ReesPrimary"; CPN.at(ConeProperty::ReesPrimaryMultiplicity) = "ReesPrimaryMultiplicity"; CPN.at(ConeProperty::StanleyDec) = "StanleyDec"; CPN.at(ConeProperty::DualMode) = "DualMode"; return CPN; } const vector& ConePropertyNames() { static vector CPN(initializeCPN()); return CPN; } } ConeProperty::Enum toConeProperty(const std::string& s) { const vector& CPN = ConePropertyNames(); for (size_t i=0; i(i); } errorOutput() << "Unknown ConeProperty string \"" << s << "\"" << std::endl; throw BadInputException(); } const std::string& toString(ConeProperty::Enum cp) { return ConePropertyNames()[cp]; } /* print it in a nice way */ std::ostream& operator<< (std::ostream& out, const ConeProperties& CP){ for (size_t i=0; i(i)) << " "; } return out; } } /* end namespace libnormaliz */ regina-4.96/engine/enumerate/normaliz/cone_property.h000644 000765 000024 00000005602 12311266525 022744 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #ifndef CONE_PROPERTY_H_ #define CONE_PROPERTY_H_ #include #include #include "libnormaliz.h" namespace libnormaliz { /* An enumeration of things, that can be computed for a cone. * The namespace prevents interfering with other names. */ namespace ConeProperty { enum Enum { Generators, ExtremeRays, SupportHyperplanes, TriangulationSize, TriangulationDetSum, Triangulation, Multiplicity, HilbertBasis, Deg1Elements, HilbertSeries, Grading, IsPointed, IsDeg1Generated, IsDeg1ExtremeRays, IsDeg1HilbertBasis, IsIntegrallyClosed, GeneratorsOfToricRing, ReesPrimary, ReesPrimaryMultiplicity, StanleyDec, DualMode, EnumSize // this has to be the last entry, to get the number of entries in the enum }; // remember to change also the string conversion function if you change this enum } class ConeProperties { public: /* Constructors */ ConeProperties(); ConeProperties(ConeProperty::Enum); ConeProperties(ConeProperty::Enum, ConeProperty::Enum); ConeProperties(const std::bitset&); /* set properties */ ConeProperties& set(ConeProperty::Enum, bool value=true); ConeProperties& set(ConeProperty::Enum, ConeProperty::Enum); ConeProperties& set(const ConeProperties&); ConeProperties& set(Mode::ComputationMode mode); /* reset (=unset) properties */ ConeProperties& reset(ConeProperty::Enum Property); ConeProperties& reset(const ConeProperties&); /* test which/how many properties are set */ bool test(ConeProperty::Enum Property) const; bool any() const; bool none() const; size_t count () const; /* print it in a nice way */ friend std::ostream& operator<<(std::ostream&, const ConeProperties&); private: std::bitset CPs; }; // conversion to/from strings ConeProperty::Enum toConeProperty(const std::string&); const std::string& toString(ConeProperty::Enum); std::ostream& operator<<(std::ostream&, const ConeProperties&); } #endif /* CONE_PROPERTY_H_ */ regina-4.96/engine/enumerate/normaliz/COPYING000644 000765 000024 00000104513 12234011536 020731 0ustar00babstaff000000 000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . regina-4.96/engine/enumerate/normaliz/full_cone.cpp000644 000765 000024 00000305451 12311266525 022362 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ //--------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include "full_cone.h" #include "vector_operations.h" #include "lineare_transformation.h" #include "list_operations.h" #include "map_operations.h" #include "my_omp.h" #include "integer.h" //--------------------------------------------------------------------------- const size_t RecBoundTriang=1000000; // if number(supphyps)*size(triang) > RecBoundTriang // we pass to (non-recirsive) pyramids const size_t EvalBoundTriang=2500000; // if more than EvalBoundTriang simplices have been stored // evaluation is started (whenever possible) const size_t EvalBoundPyr=200000; // the same for stored pyramids const size_t EvalBoundRecPyr=20000; // the same for stored RECURSIVE pyramids //--------------------------------------------------------------------------- namespace libnormaliz { using namespace std; //--------------------------------------------------------------------------- //private //--------------------------------------------------------------------------- template void Full_Cone::add_hyperplane(const size_t& new_generator, const FACETDATA & positive,const FACETDATA & negative, list& NewHyps){ // adds a new hyperplane found in find_new_facets to this cone (restricted to generators processed) size_t k; FACETDATA NewFacet; NewFacet.Hyp.resize(dim); NewFacet.GenInHyp.resize(nr_gen); Integer used_for_tests; if (test_arithmetic_overflow) { // does arithmetic tests for (k = 0; k void Full_Cone::find_new_facets(const size_t& new_generator){ // our Fourier-Motzkin implementation // the special treatment of simplicial facets was inserted because of line shellings. // At present these are not computed. //to see if possible to replace the function .end with constant iterator since push-back is performed. // NEW: new_generator is the index of the generator being inserted size_t i,k,nr_zero_i; size_t subfacet_dim=dim-2; // NEW dimension of subfacet size_t facet_dim=dim-1; // NEW dimension of facet const bool tv_verbose = false; //verbose && !is_pyramid; // && Support_Hyperplanes.size()>10000; //verbose in this method call // preparing the computations, the various types of facets are sorted into the deques deque Pos_Simp,Pos_Non_Simp; deque Neg_Simp,Neg_Non_Simp; deque Neutral_Simp, Neutral_Non_Simp; boost::dynamic_bitset<> Zero_Positive(nr_gen),Zero_Negative(nr_gen); bool simplex; if (tv_verbose) verboseOutput()<<"transform_values:"<::iterator ii = Facets.begin(); for (; ii != Facets.end(); ++ii) { simplex=true; nr_zero_i=0; for(size_t j=0;jGenInHyp.test(j)) nr_zero_i++; if(nr_zero_i>facet_dim){ simplex=false; break; } } if(ii->ValNewGen>0) Zero_Positive|=ii->GenInHyp; else if(ii->ValNewGen<0) Zero_Negative|=ii->GenInHyp; if (ii->ValNewGen==0) { ii->GenInHyp.set(new_generator); // Must be set explicitly !! if (simplex) { Neutral_Simp.push_back(&(*ii)); } else { Neutral_Non_Simp.push_back(&(*ii)); } } else if (ii->ValNewGen>0) { if (simplex) { Pos_Simp.push_back(&(*ii)); } else { Pos_Non_Simp.push_back(&(*ii)); } } else if (ii->ValNewGen<0) { if (simplex) { Neg_Simp.push_back(&(*ii)); } else { Neg_Non_Simp.push_back(&(*ii)); } } } boost::dynamic_bitset<> Zero_PN(nr_gen); Zero_PN=Zero_Positive & Zero_Negative; size_t nr_PosSimp = Pos_Simp.size(); size_t nr_PosNonSimp = Pos_Non_Simp.size(); size_t nr_NegSimp = Neg_Simp.size(); size_t nr_NegNonSimp = Neg_Non_Simp.size(); size_t nr_NeuSimp = Neutral_Simp.size(); size_t nr_NeuNonSimp = Neutral_Non_Simp.size(); if (tv_verbose) verboseOutput()<<" PS "<, int> > > Neg_Subfacet_Multi(omp_get_max_threads()) ; boost::dynamic_bitset<> zero_i(nr_gen); boost::dynamic_bitset<> subfacet(nr_gen); #pragma omp parallel for firstprivate(zero_i,subfacet) private(k,nr_zero_i) schedule(dynamic) for (i=0; iGenInHyp; nr_zero_i=0; for(size_t j=0;jsubfacet_dim){ break; } } if(nr_zero_i==subfacet_dim) // NEW This case treated separately Neg_Subfacet_Multi[omp_get_thread_num()].push_back(pair , int> (zero_i,i)); else{ for (k =0; k, int> (subfacet,i)); } } } } list < pair < boost::dynamic_bitset<>, int> > Neg_Subfacet_Multi_United; for(int i=0;i, int > >::iterator jj; list< pair < boost::dynamic_bitset<>, int > >::iterator del; jj =Neg_Subfacet_Multi_United.begin(); // remove negative subfacets shared while (jj!= Neg_Subfacet_Multi_United.end()) { // by two neg simpl facets del=jj++; if (jj!=Neg_Subfacet_Multi_United.end() && (*jj).first==(*del).first) { //delete since is the intersection of two negative simplicies Neg_Subfacet_Multi_United.erase(del); del=jj++; Neg_Subfacet_Multi_United.erase(del); } } size_t nr_NegSubfMult = Neg_Subfacet_Multi_United.size(); if (tv_verbose) verboseOutput() << nr_NegSubfMult << ", " << flush; vector > NewHypsSimp(nr_PosSimp); vector > NewHypsNonSimp(nr_PosNonSimp); map < boost::dynamic_bitset<>, int > Neg_Subfacet; size_t nr_NegSubf=0; #pragma omp parallel private(jj) //if(nr_NegNonSimp+nr_NegSimp>1000) { size_t i,j,k,nr_zero_i; boost::dynamic_bitset<> subfacet(dim-2); jj = Neg_Subfacet_Multi_United.begin(); size_t jjpos=0; bool found; #pragma omp for schedule(dynamic) for (size_t j=0; j jjpos; ++jjpos, ++jj) ; // by non-simpl neg or neutral facets for(;j < jjpos; --jjpos, --jj) ; subfacet=(*jj).first; found=false; for (i = 0; i GenInHyp); if(found) break; } if (!found) { for (i = 0; i GenInHyp); if(found) break; } if(!found) { for (i = 0; i GenInHyp); if(found) break; } } } if (found) { jj->second=-1; } } #pragma omp single { //remove elements that where found in the previous loop jj = Neg_Subfacet_Multi_United.begin(); map < boost::dynamic_bitset<>, int > ::iterator last_inserted=Neg_Subfacet.begin(); // used to speedup insertion into the new map for (; jj!= Neg_Subfacet_Multi_United.end(); ++jj) { if ((*jj).second != -1) { last_inserted = Neg_Subfacet.insert(last_inserted,*jj); } } nr_NegSubf=Neg_Subfacet.size(); } #pragma omp single nowait {Neg_Subfacet_Multi_United.clear();} #pragma omp single nowait if (tv_verbose) { verboseOutput()<< nr_NegSubf < zero_i(nr_gen); map , int> ::iterator jj_map; #pragma omp for schedule(dynamic) // nowait // Now matching positive and negative (sub)facets for (i =0; iGenInHyp & Zero_PN; nr_zero_i=0; for(size_t m=0;msubfacet_dim){ break; } } if (nr_zero_i==subfacet_dim) { // NEW slight change in logic. Positive simpl facet shared at most jj_map=Neg_Subfacet.find(zero_i); // one subfacet with negative simpl facet if (jj_map!=Neg_Subfacet.end()) { add_hyperplane(new_generator,*Pos_Simp[i],*Neg_Simp[(*jj_map).second],NewHypsSimp[i]); (*jj_map).second = -1; // block subfacet in further searches } } if (nr_zero_i==facet_dim){ // now there could be more such subfacets. We make all and search them. for (k =0; k jjpos; ++jjpos, ++jj_map) ; for( ; j < jjpos; --jjpos, --jj_map) ; if ( (*jj_map).second != -1 ) { // skip used subfacets if(jj_map->first.is_subset_of(Pos_Non_Simp[i]->GenInHyp)){ add_hyperplane(new_generator,*Pos_Non_Simp[i],*Neg_Simp[(*jj_map).second],NewHypsNonSimp[i]); (*jj_map).second = -1; // has now been used } } } } // P vs NS #pragma omp single nowait if (tv_verbose) { verboseOutput() << "PS vs N, " << flush; } vector key(nr_gen); size_t nr_missing; bool common_subfacet; #pragma omp for schedule(dynamic) nowait for (size_t i =0; iGenInHyp; nr_zero_i=0; for(j=0;j=subfacet_dim) { for (j=0; jGenInHyp.test(key[k])) { nr_missing++; if(nr_missing==2 || nr_zero_i==subfacet_dim) { common_subfacet=false; break; } } } if(common_subfacet){ add_hyperplane(new_generator,*Pos_Simp[i],*Neg_Non_Simp[j],NewHypsSimp[i]); if(nr_zero_i==subfacet_dim) // only one subfacet can lie in negative hyperplane break; } } } } // PS vs N #pragma omp single nowait if (tv_verbose) { verboseOutput() << "P vs N" << endl; } list AllNonSimpHyp; typename list::iterator a; for(i=0;i common_zero(nr_gen); vector common_key(nr_gen); #pragma omp for schedule(dynamic) // nowait for (size_t i =0; iGenInHyp; nr_zero_i=0; for(j=0;j=subfacet_dim) { missing_bound=nr_zero_i-subfacet_dim; // at most this number of generators can be missing // to have a chance for common subfacet for (j=0; jGenInHyp.test(key[k])) { nr_missing++; if(nr_missing>missing_bound || nr_zero_i==subfacet_dim) { common_subfacet=false; break; } } else { common_key[nr_common_zero]=key[k]; nr_common_zero++; } } if(common_subfacet){//intersection of *i and *j may be a subfacet exactly_two=true; ranktest=((nr_PosNonSimp+nr_NegNonSimp+nr_NeuNonSimp>dim*dim*nr_common_zero/3)); if (ranktest) { Matrix Test(nr_common_zero,dim); for (k = 0; k < nr_common_zero; k++) Test.write(k,Generators[common_key[k]]); if (Test.rank_destructive()GenInHyp; for (a=AllNonSimpHyp.begin();a!=AllNonSimpHyp.end();++a){ hp_t=*a; if ((hp_t!=hp_i) && (hp_t!=hp_j) && common_zero.is_subset_of(hp_t->GenInHyp)) { exactly_two=false; AllNonSimpHyp.splice(AllNonSimpHyp.begin(),AllNonSimpHyp,a); break; } } } // else if (exactly_two) { //intersection of i and j is a subfacet add_hyperplane(new_generator,*hp_i,*hp_j,NewHypsNonSimp[i]); } } } } } } //END parallel for(i=0;i void Full_Cone::extend_triangulation(const size_t& new_generator){ // extends the triangulation of this cone by including new_generator // simplicial facets save us from searching the "brother" in the existing triangulation // to which the new simplex gets attached size_t listsize = Facets.size(); vector::iterator> visible; visible.reserve(listsize); typename list::iterator i = Facets.begin(); // #pragma omp critical(VERBOSE) // verboseOutput() << "L " << pyr_level << " H " << listsize << " T " << TriangulationSize << endl; for (; i!=Facets.end(); ++i) if (i->ValNewGen < 0) // visible facet visible.push_back(i); listsize = visible.size(); // cout << "Pyr Level " << pyr_level << " Visible " << listsize << " Triang " << TriangulationSize << endl; typename list< SHORTSIMPLEX >::iterator oldTriBack = --Triangulation.end(); #pragma omp parallel private(i) if(TriangulationSize>1000) { size_t k,l; bool one_not_in_i, not_in_facet; size_t not_in_i=0; size_t facet_dim=dim-1; size_t nr_in_i=0; list< SHORTSIMPLEX > Triangulation_kk; typename list< SHORTSIMPLEX >::iterator j; vector key(dim); #pragma omp for schedule(dynamic) for (size_t kk=0; kkGenInHyp.test(m)) nr_in_i++; if(nr_in_i>facet_dim){ break; } } if (nr_in_i==facet_dim){ // simplicial l=0; for (k = 0; k GenInHyp[k]==1) { key[l]=k; l++; } } key[dim-1]=new_generator; if(parallel_inside_pyramid) { #pragma omp critical(TRIANG) // critical only on top level store_key(key,-i->ValNewGen,0,Triangulation); } else { store_key(key,-i->ValNewGen,0,Triangulation); } continue; } size_t irrelevant_vertices=0; for(size_t vertex=0;vertexGenInHyp[VertInTri[vertex]]==0) // lead vertex not in hyperplane continue; if(irrelevant_verticeskey; one_not_in_i=false; // true indicates that one gen of simplex is not in hyperplane not_in_facet=false; // true indicates that a second gen of simplex is not in hyperplane for(k=0;kGenInHyp.test(key[k])) { if(one_not_in_i){ not_in_facet=true; break; } one_not_in_i=true; not_in_i=k; } } if(not_in_facet) // simplex does not share facet with hyperplane continue; key[not_in_i]=new_generator; store_key(key,-i->ValNewGen,j->vol,Triangulation_kk); } // j } // for vertex if(parallel_inside_pyramid) { #pragma omp critical(TRIANG) Triangulation.splice(Triangulation.end(),Triangulation_kk); } else Triangulation.splice(Triangulation.end(),Triangulation_kk); } // for kk } // parallel VertInTri.push_back(new_generator); TriSectionFirst.push_back(++oldTriBack); TriSectionLast.push_back(--Triangulation.end()); } //--------------------------------------------------------------------------- template void Full_Cone::store_key(const vector& key, const Integer& height, const Integer& mother_vol, list< SHORTSIMPLEX >& Triangulation){ // stores a simplex given by key and height in Triangulation // mother_vol is the volume of the simplex to which the new one is attached SHORTSIMPLEX newsimplex; newsimplex.key=key; newsimplex.height=height; newsimplex.vol=0; #pragma omp atomic TriangulationSize++; int tn; if(omp_get_level()==0) tn=0; else tn = omp_get_ancestor_thread_num(1); if (do_only_multiplicity) { // directly compute the volume if (mother_vol==1) newsimplex.vol = height; // the multiplicity is computed in SimplexEvaluator for(size_t i=0; iSimplexEval[tn].evaluate(newsimplex); // restore the local generator numbering, needed in extend_triangulation newsimplex.key=key; } if (keep_triangulation){ Triangulation.push_back(newsimplex); return; } bool Simpl_available=true; typename list< SHORTSIMPLEX >::iterator F; if(Top_Cone->FS[tn].empty()){ #pragma omp critical(FREESIMPL) { if(Top_Cone->FreeSimpl.empty()) Simpl_available=false; else{ F=Top_Cone->FreeSimpl.begin(); // take 100 simplices from FreeSimpl size_t q; for(q=0;q<1000;++q){ // or what you can get if(F==Top_Cone->FreeSimpl.end()) break; ++F; } if(q<1000) Top_Cone->FS[tn].splice(Top_Cone->FS[tn].begin(), Top_Cone->FreeSimpl); else Top_Cone->FS[tn].splice(Top_Cone->FS[tn].begin(), Top_Cone->FreeSimpl,Top_Cone->FreeSimpl.begin(),++F); } // else } // critical } // if empty if(Simpl_available){ Triangulation.splice(Triangulation.end(),Top_Cone->FS[tn], Top_Cone->FS[tn].begin()); Triangulation.back()=newsimplex; } else Triangulation.push_back(newsimplex); } //--------------------------------------------------------------------------- template void Full_Cone::process_pyramids(const size_t new_generator,const bool recursive){ /* We distinguish two types of pyramids: (i) recursive pyramids that give their support hyperplanes back to the mother. (ii) independent pyramids that are not linked to the mother. Pyramids of type (i) are The parameter recursive indicates whether the pyramids that will be created in process_pyramid(s) are of type (i) or (ii). We must also know whether "this" is of type (i) or (ii). This is indicted by do_all_hyperplanes. recursion_allowed indicates whether recursive pyramids can be created from "this". It has the same value as do_all_hyperplanes, except possibly for the top cone. By setting recursion_allowed=false in the constructor of the top cone, one can suppress recursive pyramids completely, but do_all_hyperplanes must be set to true for the top cone. Pyramids of type (ii) set recursion_allowed=false. Pyramids of type (i) are stored in RecPyramids, those of type (ii) in Pyramids. The store_level of the created pyramids is the one of the mother +1, EXCEPT that all pyramids of type (ii) created from pyramids of type (i) are stored at level 0. Note: the top cone has pyr_level=-1. */ long store_level; if(recursion_allowed && !recursive) store_level=0; else store_level=pyr_level+1; size_t start_level=omp_get_level(); // allows us to check that we are on level 0 // outside the loop and can therefore call evaluation // NOW the level doesn't go up in the loop // because parallelization has been dropped vector Pyramid_key; Pyramid_key.reserve(nr_gen); boost::dynamic_bitset<> in_Pyramid(nr_gen); typename list< FACETDATA >::iterator l=Facets.begin(); size_t listsize=Facets.size(); Integer ov_sp; // Order_Vector scalar product bool skip_triang; // make hyperplanes but skip triangulation (recursive pyramids only) // no need to parallelize the followqing loop since ALL pyramids // are now processed in parallel (see version 2.8 for parallel version) // BUT: new hyperplanes can be added before the loop has been finished. // Therefore we must work with listsize. for (size_t kk=0; kkValNewGen>=0) // facet not visible continue; skip_triang = false; if (Top_Cone->do_partial_triangulation && l->ValNewGen>=-1) { //ht1 criterion if (!is_pyramid) { // in the topcone we always have ov_sp > 0 skip_triang = true; } else { //check if it would be an excluded hyperplane ov_sp = v_scalar_product(l->Hyp,Order_Vector); if (ov_sp > 0) { skip_triang = true; } else if (ov_sp == 0) { for (size_t i=0; iHyp[i]>0) { skip_triang = true; break; } else if (l->Hyp[i]<0) { break; } } } } if (skip_triang && !recursive) { continue; } } Pyramid_key.clear(); // make data of new pyramid Pyramid_key.push_back(new_generator); for(size_t i=0;iHyp,Generators[i])==0){ // incidence data may no longer exist Pyramid_key.push_back(i); in_Pyramid.set(i); } } in_Pyramid.set(new_generator); // now we can store the new pyramid at the right place (or finish the simplicial ones) if (recursive && skip_triang) { // mark as "do not triangulate" process_pyramid(Pyramid_key, in_Pyramid, new_generator,store_level,0, recursive); } else { //default process_pyramid(Pyramid_key, in_Pyramid, new_generator,store_level,-l->ValNewGen, recursive); } if(Top_Cone->nrRecPyrs[store_level]>EvalBoundRecPyr && start_level==0){ Top_Cone->evaluate_rec_pyramids(store_level); } if(Top_Cone->nrPyramids[store_level] > EvalBoundPyr && start_level==0){ Top_Cone->evaluate_stored_pyramids(store_level); } } } //--------------------------------------------------------------------------- template void Full_Cone::process_pyramid(const vector& Pyramid_key, const boost::dynamic_bitset<>& in_Pyramid, const size_t new_generator,const size_t store_level, Integer height, const bool recursive){ // processes simplicial pyramids directly, stores other pyramids into their depots #pragma omp atomic Top_Cone->totalNrPyr++; if(Pyramid_key.size()==dim){ // simplicial pyramid completely done here #pragma omp atomic // only for saving memory Top_Cone->nrSimplicialPyr++; if(recursive){ // the facets may be facets of the mother cone and if recursive==true must be given back Simplex S(Pyramid_key, Generators); height = S.read_volume(); //update our lower bound for the volume Matrix H=S.read_support_hyperplanes(); list > NewFacets; for (size_t i=0; i Pyramid(*this,Pyramid_key); Pyramid.Mother=this; Pyramid.in_Pyramid=in_Pyramid; // need these data to give back supphyps Pyramid.new_generator=new_generator; if (height == 0) { //indicates "do not triangulate" Pyramid.do_partial_triangulation = false; Pyramid.do_Hilbert_basis = false; } nrRecPyramidsDue++; #pragma omp critical(RECPYRAMIDS) { Top_Cone->RecPyrs[store_level].push_back(Pyramid); Top_Cone->nrRecPyrs[store_level]++; } // critical } else { //not recursive vector key_wrt_top(Pyramid_key.size()); for(size_t i=0;iPyramids[store_level].push_back(key_wrt_top); Top_Cone->nrPyramids[store_level]++; } // critical } } } //--------------------------------------------------------------------------- template void Full_Cone::find_and_evaluate_start_simplex(){ size_t i,j; Integer factor; Simplex S = find_start_simplex(); vector key=S.read_key(); // generators indexed from 0 for (i = 0; i < dim; i++) { in_triang[key[i]]=true; if (deg1_triangulation && isComputed(ConeProperty::Grading)) deg1_triangulation = (gen_degrees[i] == 1); } Matrix H=S.read_support_hyperplanes(); for (i = 0; i (dim,0); Matrix G=S.read_generators(); //srand(12345); for(i=0;i1)) { store_key(key,S.read_volume(),1,Triangulation); if(do_only_multiplicity) { #pragma omp atomic TotDet++; } } if(do_triangulation){ // we must prepare the sections of the triangulation for(i=0;i void Full_Cone::select_supphyps_from(list >& NewFacets, const size_t new_generator, const boost::dynamic_bitset<>& in_Pyr){ // the mother cone (=this) selects supphyps from the list NewFacets supplied by the daughter // the daughter provides the necessary information via the parameters size_t i; typename list >::iterator pyr_hyp = NewFacets.begin(); bool new_global_hyp; FACETDATA NewFacet; Integer test; for(;pyr_hyp!= NewFacets.end();pyr_hyp++){ if(v_scalar_product(Generators[new_generator],*pyr_hyp)>0) continue; new_global_hyp=true; for(i=0;i void Full_Cone::evaluate_rec_pyramids(const size_t level){ // evaluates the stored recursive pyramids // Note that we must call extend_cone for every new_generator added to a given pyramid, // once we have left extend_cone to make recursive pyramids. // extend_cone is locked until all subpyramids have been finished. // Therefore we need not take care of this question here. // The "skip_remaining" technique is applied here and later on since we cannot interrupt // parallelized loops to do paralleized ecaluation. (No nested parallelization) assert(omp_get_level()==0); if(RecPyrs[level].empty()) return; if (verbose){ verboseOutput() << "++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; for (size_t l=0; l0) { verboseOutput() << "level " << l << " recursive pyramids remaining: " << nrRecPyrs[l] << endl; } } if (nrRecPyrs[level]>0) { verboseOutput() << "Computing support hyperplanes of " << nrRecPyrs[level] << " level " << level << " recursive pyramids." << endl; } verboseOutput() << "++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; } RecPyrs.resize(level+2); // provide space for a new generation nrRecPyrs.resize(level+2); nrRecPyrs[level+1]=0; size_t nr_pyramids=nrRecPyrs[level]; typename list >::iterator p; size_t ppos; bool skip_remaining_tri,skip_remaining_pyr,skip_remaining_rec_pyr; do { p = RecPyrs[level].begin(); ppos=0; skip_remaining_tri=false; skip_remaining_pyr=false; skip_remaining_rec_pyr=false; #pragma omp parallel for firstprivate(p,ppos) schedule(dynamic) for(size_t i=0; i ppos; ++ppos, ++p) ; for(; i < ppos; --ppos, --p) ; p->pyr_level=level; p->extend_cone(); if(check_evaluation_buffer_size()) // we interrupt parallel execution if it is really parallel skip_remaining_tri=true; // to keep the triangulation buffer under control if(nrRecPyrs[level+1]>EvalBoundRecPyr) skip_remaining_rec_pyr=true; if(nrPyramids[0]>EvalBoundPyr) skip_remaining_pyr=true; } if (!skip_remaining_tri && !skip_remaining_pyr) evaluate_rec_pyramids(level+1); // remove done pyramids p = RecPyrs[level].begin(); for(size_t i=0; iDone) { p=RecPyrs[level].erase(p); nrRecPyrs[level]--; } else { ++p; } } nr_pyramids = nrRecPyrs[level]; if (skip_remaining_tri) { if (verbose) verboseOutput() << nr_pyramids << " recursive pyramids remaining on level " << level << ", "; Top_Cone->evaluate_triangulation(); } if(skip_remaining_pyr){ if (verbose) verboseOutput() << nr_pyramids << " recursive pyramids remaining on level " << level << endl; evaluate_stored_pyramids(0); } } while(nr_pyramids>0); // indicates: not all pyramids done /* if (verbose) { verboseOutput() << "++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; verboseOutput() << "all recursive pyramids on level "<< level << " done!"<0) { verboseOutput() << "level " << l << " recursive pyramids remaining: " << nrRecPyrs[l] << endl; } } verboseOutput() << "++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; } */ if(check_evaluation_buffer()) { Top_Cone->evaluate_triangulation(); } } //--------------------------------------------------------------------------- template void Full_Cone::evaluate_stored_pyramids(const size_t level){ // evaluates the stored non-recursive pyramids // In contrast to the the recusrive pyramids, extend_cone is called // only once for every stored pyramid since we set recursion_allowed=false. assert(omp_get_level()==0); if(Pyramids[level].empty()) return; Pyramids.resize(level+2); // provide space for a new generation nrPyramids.resize(level+2); nrPyramids[level+1]=0; size_t nr_done=0; size_t nr_pyramids=nrPyramids[level]; vector Done(nr_pyramids,0); if (verbose) { verboseOutput() << "**************************************************" << endl; for (size_t l=0; l<=level; ++l) { if (nrPyramids[l]>0) { verboseOutput() << "level " << l << " pyramids remaining: " << nrPyramids[l] << endl; } } verboseOutput() << "**************************************************" << endl; } typename list >::iterator p; size_t ppos; bool skip_remaining_tri,skip_remaining_pyr; do { p = Pyramids[level].begin(); ppos=0; skip_remaining_tri=false; skip_remaining_pyr=false; #pragma omp parallel for firstprivate(p,ppos) schedule(dynamic) for(size_t i=0; i ppos; ++ppos, ++p) ; for(; i < ppos; --ppos, --p) ; if(Done[i]) continue; Done[i]=1; #pragma omp atomic nr_done++; Full_Cone Pyramid(*this,*p); Pyramid.recursion_allowed=false; // ABSOLUTELY NECESSARY HERE Pyramid.pyr_level=level; Pyramid.do_all_hyperplanes=false; if(level>=2 && do_partial_triangulation){ // limits the descent of do_partial_triangulation Pyramid.do_triangulation=true; Pyramid.do_partial_triangulation=false; } Pyramid.extend_cone(); if(check_evaluation_buffer_size() && nr_done < nr_pyramids) // we interrupt parallel execution if it is really parallel skip_remaining_tri=true; // to keep the triangulation buffer under control if(nrPyramids[level+1]>EvalBoundPyr && nr_done < nr_pyramids) skip_remaining_pyr=true; } // remove done pyramids p = Pyramids[level].begin(); for(size_t i=0; ievaluate_triangulation(); } if(skip_remaining_pyr){ evaluate_stored_pyramids(level+1); } } while(skip_remaining_tri || skip_remaining_pyr); if (verbose) { verboseOutput() << "**************************************************" << endl; verboseOutput() << "all pyramids on level "<< level << " done!"<0) { verboseOutput() << "level " << l << " pyramids remaining: " << nrPyramids[l] << endl; } } verboseOutput() << "**************************************************" << endl; } if(check_evaluation_buffer()) { Top_Cone->evaluate_triangulation(); } Pyramids[level].clear(); nrPyramids[level]=0; evaluate_stored_pyramids(level+1); } //--------------------------------------------------------------------------- /* builds the top cone successively by inserting generators, computes all essential data except global reduction */ template void Full_Cone::build_top_cone() { if(dim==0) return; if (verbose) { verboseOutput()< void Full_Cone::extend_cone() { assert(nrRecPyramidsDone <= nrRecPyramidsDue); // cout << "In extend " << allRecPyramidsBuilt << " " << nrRecPyramidsDone << " " << nrRecPyramidsDue << endl; if(!allRecPyramidsBuilt || nrRecPyramidsDone < nrRecPyramidsDue) // must wait for completion of subpyramids return; // of recursive pyramids built from previous generator long i; typename list< FACETDATA >::iterator l; // DECIDE WHETHER TO BUILD RECURSIVE PYRAMIDS long long RecBoundSuppHyp = dim*dim; RecBoundSuppHyp *= RecBoundSuppHyp*3000; //dim^4 * 3000 // int bound_div = nr_gen-dim+1; // if(bound_div > 3* (int) dim) bound_div = 3*dim; // RecBoundSuppHyp /= bound_div; if(nextGen==-1){ // indicates the first call of extend_cone for this cone find_and_evaluate_start_simplex(); nextGen=0; last_to_be_inserted=nr_gen-1; for(long j=nr_gen-1;j>=0;--j){ if(isComputed(ConeProperty::ExtremeRays)){ if(!in_triang[j] && Extreme_Rays[j]){ last_to_be_inserted=j; break; } } else if(!in_triang[j]){ last_to_be_inserted=j; break; } } } else // in this case we have left this function last time for this cone // via the explicit return since we had to form recursive pyramids. // The steps at the end of the loop that were skipped have to be done now. { // removing the negative hyperplanes if necessary if(do_all_hyperplanes || nextGen!=last_to_be_inserted){ l=Facets.begin(); for (size_t j=0; jValNewGen<0) l=Facets.erase(l); else l++; } } if(verbose && !is_pyramid) { verboseOutput() << "gen="<< nextGen <<", "<0) verboseOutput() << ", " << nrPyramids[0] << " pyr"; if(do_triangulation||do_partial_triangulation) verboseOutput() << ", " << TriangulationSize << " simpl"; verboseOutput()<< endl; } } // else Integer scalar_product; bool is_new_generator; for (i=nextGen;i(nr_gen);++i) { if(in_triang[i] || (isComputed(ConeProperty::ExtremeRays) && !Extreme_Rays[i])) continue; if(do_triangulation && TriangulationSize > 2*RecBoundTriang) // emermergency brake tri_recursion=true; // to switch off production of simplices in favor // of non-recursive pyramids is_new_generator=false; l=Facets.begin(); long long nr_pos=0; long long nr_neg=0; vector L; old_nr_supp_hyps=Facets.size(); // Facets will be xtended in the loop size_t lpos=0; #pragma omp parallel for private(L,scalar_product) firstprivate(lpos,l) reduction(+: nr_pos, nr_neg) schedule(dynamic) if(old_nr_supp_hyps>10000) for (size_t k=0; k lpos; lpos++, l++) ; for(;k < lpos; lpos--, l--) ; L=Generators[i]; scalar_product=v_scalar_product(L,(*l).Hyp); // l->ValPrevGen=l->ValNewGen; // last new generator is now previous generator l->ValNewGen=scalar_product; if (scalar_product<0) { is_new_generator=true; nr_neg++; } if (scalar_product>0) { nr_pos++; } } //end parallel for if(!is_new_generator) continue; // the i-th generator is used in the triangulation in_triang[i]=true; if (deg1_triangulation && isComputed(ConeProperty::Grading)) deg1_triangulation = (gen_degrees[i] == 1); // First we test whether to go to recursive pyramids because of too many supphyps // Once we have done so, we must stay with it if( supphyp_recursion || (recursion_allowed && nr_neg*nr_pos>RecBoundSuppHyp)){ // go to pyramids because of supphyps if(check_evaluation_buffer()){ // cout << "Evaluation Build Mitte" << endl; Top_Cone->evaluate_triangulation(); } // cout << "In SuppHyp Rec" << endl; supphyp_recursion=true; allRecPyramidsBuilt=false; // must lock extend_cone for this cone nrRecPyramidsDue=0; nrRecPyramidsDone=0; process_pyramids(i,true); //recursive allRecPyramidsBuilt=true; nextGen=i+1; return; // in recursive mode we stop at this point and come back later // to proceed with nextGen } else{ // now we check whether to go to pyramids because of the size of triangulation if( tri_recursion || (do_triangulation && (nr_neg*TriangulationSize > RecBoundTriang || 3*omp_get_max_threads()*TriangulationSize>EvalBoundTriang ))){ // go to pyramids because of triangulation if(check_evaluation_buffer()){ Top_Cone->evaluate_triangulation(); } tri_recursion=true; process_pyramids(i,false); //non-recursive } else{ // no pyramids necesary if(do_partial_triangulation) process_pyramids(i,false); // non-recursive if(do_triangulation) extend_triangulation(i); } if(do_all_hyperplanes || i!=last_to_be_inserted) find_new_facets(i); } // removing the negative hyperplanes if necessary if(do_all_hyperplanes || i!=last_to_be_inserted){ l=Facets.begin(); for (size_t j=0; jValNewGen<0) { l=Facets.erase(l); } else ++l; } } if(verbose && !is_pyramid) { verboseOutput() << "gen="<< i+1 <<", "<0) verboseOutput() << ", " << nrPyramids[0] << " pyr"; if(do_triangulation||do_partial_triangulation) verboseOutput() << ", " << TriangulationSize << " simpl"; verboseOutput()<< endl; } } // transfer Facets --> SupportHyperplanes if (do_all_hyperplanes) { typename list::const_iterator IHV=Facets.begin(); for(;IHV!=Facets.end();IHV++){ Support_Hyperplanes.push_back(IHV->Hyp); } } Facets.clear(); is_Computed.set(ConeProperty::SupportHyperplanes); if(is_pyramid && do_all_hyperplanes){ // must give supphyps back to maother Mother->select_supphyps_from(Support_Hyperplanes,new_generator,in_Pyramid); #pragma omp atomic Mother->nrRecPyramidsDone++; } transfer_triangulation_to_top(); // transfer remaining simplices to top if(check_evaluation_buffer()){ // cout << "Evaluating in build_cone at end, pyr level " << pyr_level << endl; // cout << "Evaluation Build Ende " << is_pyramid << endl; Top_Cone->evaluate_triangulation(); } Done=true; // this cone now finished } //--------------------------------------------------------------------------- template bool Full_Cone::check_evaluation_buffer(){ return(omp_get_level()==0 && check_evaluation_buffer_size()); } //--------------------------------------------------------------------------- template bool Full_Cone::check_evaluation_buffer_size(){ return(!Top_Cone->keep_triangulation && Top_Cone->TriangulationSize > EvalBoundTriang); } //--------------------------------------------------------------------------- template void Full_Cone::transfer_triangulation_to_top(){ // NEW EVA size_t i; // cout << "Pyr level " << pyr_level << endl; if(!is_pyramid) { // we are in top cone if(check_evaluation_buffer()){ evaluate_triangulation(); } return; // no transfer necessary } // now we are in a pyramid // cout << "In pyramid " << endl; typename list< SHORTSIMPLEX >::iterator pyr_simp=Triangulation.begin(); for(;pyr_simp!=Triangulation.end();pyr_simp++) for(i=0;ikey[i]=Top_Key[pyr_simp->key[i]]; // cout << "Keys transferred " << endl; #pragma omp critical(TRIANG) { Top_Cone->Triangulation.splice(Top_Cone->Triangulation.end(),Triangulation); Top_Cone->TriangulationSize+=TriangulationSize; } TriangulationSize = 0; // cout << "Done." << endl; } //--------------------------------------------------------------------------- template void Full_Cone::evaluate_triangulation(){ assert(omp_get_level()==0); if(TriangulationSize>0) { const long VERBOSE_STEPS = 50; long step_x_size = TriangulationSize-VERBOSE_STEPS; if (verbose) { verboseOutput() << "evaluating "< >::iterator s = Triangulation.begin(); size_t spos=0; int tn = omp_get_thread_num(); #pragma omp for schedule(dynamic) for(size_t i=0; i spos; ++spos, ++s) ; for(; i < spos; --spos, --s) ; if(keep_triangulation || do_Stanley_dec) sort(s->key.begin(),s->key.end()); SimplexEval[tn].evaluate(*s); if (verbose) { #pragma omp critical(VERBOSE) while ((long)(i*VERBOSE_STEPS) >= step_x_size) { step_x_size += TriangulationSize; verboseOutput() << "|" < void Full_Cone::primal_algorithm(){ // set needed do_ vars if (do_Hilbert_basis||do_deg1_elements||do_h_vector) do_evaluation = true; // look for a grading if it is needed deg1_check(); if (!isComputed(ConeProperty::Grading) && (do_multiplicity || do_deg1_elements || do_h_vector)) { if (!isComputed(ConeProperty::ExtremeRays)) { if (verbose) { verboseOutput() << "Cannot find grading s.t. all generators have the same degree! Computing Extreme rays first:" << endl; } compute_support_hyperplanes(); extreme_rays_and_deg1_check(); if(!pointed) return; // We keep the SupportHyperplanes, so we do not need to recompute them // for the last generator, and use them to make a global reduction earlier do_all_hyperplanes = false; supphyp_recursion = false; for(size_t i=0;i >(omp_get_max_threads(),SimplexEvaluator(*this)); } /***** Main Work is done in build_cone() *****/ build_top_cone(); // evaluates if keep_triangulation==false /***** Main Work is done in build_cone() *****/ if (verbose) { verboseOutput() << "Total number of pyramids = "<< totalNrPyr << endl; // cout << "Uni "<< Unimod << " Ht1NonUni " << Ht1NonUni << " NonDecided " << NonDecided << " TotNonDec " << NonDecidedHyp<< endl; if(do_only_multiplicity) verboseOutput() << "Determinantes computed = " << TotDet << endl; } extreme_rays_and_deg1_check(); if(!pointed) return; if (keep_triangulation) { if (isComputed(ConeProperty::Grading) && !deg1_generated) { deg1_triangulation = false; } evaluate_triangulation(); } FreeSimpl.clear(); // collect accumulated data from the SimplexEvaluators if(!is_pyramid) { for (int zi=0; zi void Full_Cone::dualize_cone() { compute_support_hyperplanes(); reset_tasks(); } // check the do_* bools, they must be set in advance // this method (de)activate them according to dependencies between them template void Full_Cone::do_vars_check() { // activate implications if (do_Stanley_dec) keep_triangulation = true; if (keep_triangulation) do_triangulation = true; if (do_multiplicity) do_triangulation = true; if (do_h_vector) do_triangulation = true; if (do_deg1_elements) do_partial_triangulation = true; if (do_Hilbert_basis) do_partial_triangulation = true; // activate do_only_multiplicity = do_multiplicity; if (do_Stanley_dec || do_h_vector || do_deg1_elements || do_Hilbert_basis) { do_only_multiplicity = false; do_evaluation = true; } if (do_multiplicity) do_evaluation = true; if (do_triangulation) do_partial_triangulation = false; if (do_Hilbert_basis) do_deg1_elements = false; //they will be extracted later } // general purpose compute method // do_* bools must be set in advance, this method does sanity checks for it // if no bool is set it does support hyperplanes and extreme rays template void Full_Cone::compute() { do_vars_check(); if (!do_triangulation && !do_partial_triangulation) support_hyperplanes(); else primal_algorithm(); } // -s template void Full_Cone::support_hyperplanes() { // recursion_allowed=true; compute_support_hyperplanes(); extreme_rays_and_deg1_check(); reset_tasks(); } template void Full_Cone::dual_mode() { Support_Hyperplanes.sort(); Support_Hyperplanes.unique(); Support_Hyperplanes.remove(vector(dim,0)); if(dim>0) { //correction needed to include the 0 cone; deg1_check(); if (isComputed(ConeProperty::Grading)) { if (verbose) { verboseOutput() << "Find degree 1 elements" << endl; } select_deg1_elements(); } } else { deg1_extreme_rays = deg1_generated = true; Grading=vector(dim); is_Computed.set(ConeProperty::IsDeg1ExtremeRays); is_Computed.set(ConeProperty::IsDeg1Generated); is_Computed.set(ConeProperty::Grading); } if (isComputed(ConeProperty::Grading)) check_deg1_hilbert_basis(); check_integrally_closed(); } //--------------------------------------------------------------------------- // Checks and auxiliary algorithms //--------------------------------------------------------------------------- template void Full_Cone::extreme_rays_and_deg1_check() { check_pointed(); if(!pointed) return; compute_extreme_rays(); deg1_check(); } //--------------------------------------------------------------------------- template void Full_Cone::set_degrees() { if(gen_degrees.size()==0 && isComputed(ConeProperty::Grading)) // now we set the degrees { gen_degrees.resize(nr_gen); vector gen_degrees_Integer=Generators.MxV(Grading); for (size_t i=0; i void Full_Cone::sort_gens_by_degree() { if(gen_degrees.size()==0 || deg1_extreme_rays) return; list > genList; vector v(dim+3); vector w(dim); unsigned long i,j; for(i=0;i >::iterator g=genList.begin(); for(;g!=genList.end();++g){ v=*g; gen_degrees[i]=explicit_cast_to_long(v[0]); Extreme_Rays[i]=false; if(v[dim+2]>0) Extreme_Rays[i]=true; for(j=0;j(gen_degrees); } } //--------------------------------------------------------------------------- template void Full_Cone::compute_support_hyperplanes(){ if(isComputed(ConeProperty::SupportHyperplanes)) return; bool save_tri = do_triangulation; bool save_part_tri = do_partial_triangulation; do_triangulation = false; do_partial_triangulation = false; build_top_cone(); do_triangulation = save_tri; do_partial_triangulation = save_part_tri; } //--------------------------------------------------------------------------- template Simplex Full_Cone::find_start_simplex() const { if (isComputed(ConeProperty::ExtremeRays)) { vector marked_extreme_rays(0); for (size_t i=0; i key_extreme = Generators.submatrix(Extreme_Rays).max_rank_submatrix_lex(dim); assert(key_extreme.size() == dim); vector key(dim); for (key_t i=0; i(key, Generators); } else { // assert(Generators.rank()>=dim); return Simplex(Generators); } } //--------------------------------------------------------------------------- template Matrix Full_Cone::select_matrix_from_list(const list >& S, vector& selection){ sort(selection.begin(),selection.end()); assert(selection.back() M(selection.size(),S.front().size()); typename list >::const_iterator ll=S.begin(); for(;ll!=S.end()&&i void Full_Cone::compute_extreme_rays(){ if (isComputed(ConeProperty::ExtremeRays)) return; assert(isComputed(ConeProperty::SupportHyperplanes)); if(dim*Support_Hyperplanes.size() < nr_gen) compute_extreme_rays_rank(); else compute_extreme_rays_compare(); } //--------------------------------------------------------------------------- template void Full_Cone::compute_extreme_rays_rank(){ size_t i,j; typename list >::iterator s; vector gen_in_hyperplanes; gen_in_hyperplanes.reserve(Support_Hyperplanes.size()); Matrix M; for(i=0;i=dim-1) Extreme_Rays[i]=true; } is_Computed.set(ConeProperty::ExtremeRays); } //--------------------------------------------------------------------------- template void Full_Cone::compute_extreme_rays_compare(){ size_t i,j,k,l,t; // Matrix SH=getSupportHyperplanes().transpose(); // Matrix Val=Generators.multiplication(SH); size_t nc=Support_Hyperplanes.size(); vector > Val(nr_gen); for (i=0;i Zero(nc); vector nr_zeroes(nr_gen); typename list >::iterator s; for (i = 0; i =nr_zeroes[i]) { Extreme_Rays[i]=false; break; } } } } } is_Computed.set(ConeProperty::ExtremeRays); } //--------------------------------------------------------------------------- template void Full_Cone::select_deg1_elements() { typename list >::iterator h = Hilbert_Basis.begin(); for(;h!=Hilbert_Basis.end();h++) if(v_scalar_product(Grading,*h)==1) Deg1_Elements.push_back(*h); is_Computed.set(ConeProperty::Deg1Elements,true); } //--------------------------------------------------------------------------- template void Full_Cone::check_pointed() { assert(isComputed(ConeProperty::SupportHyperplanes)); if (isComputed(ConeProperty::IsPointed)) return; Matrix SH = getSupportHyperplanes(); pointed = (SH.rank_destructive() == dim); is_Computed.set(ConeProperty::IsPointed); } //--------------------------------------------------------------------------- template void Full_Cone::deg1_check() { if (!isComputed(ConeProperty::Grading) // we still need it and && !isComputed(ConeProperty::IsDeg1ExtremeRays)) { // we have not tried it if (isComputed(ConeProperty::ExtremeRays)) { Matrix Extreme=Generators.submatrix(Extreme_Rays); Grading = Extreme.find_linear_form(); if (Grading.size() == dim) { is_Computed.set(ConeProperty::Grading); } else { deg1_extreme_rays = false; is_Computed.set(ConeProperty::IsDeg1ExtremeRays); } } else // extreme rays not known if (!isComputed(ConeProperty::IsDeg1Generated)) { Grading = Generators.find_linear_form(); if (Grading.size() == dim) { is_Computed.set(ConeProperty::Grading); } else { deg1_generated = false; is_Computed.set(ConeProperty::IsDeg1Generated); } } } //now we hopefully have a grading if (!isComputed(ConeProperty::Grading)) { if (isComputed(ConeProperty::ExtremeRays)) { // there is no hope to find a grading later deg1_generated = false; is_Computed.set(ConeProperty::IsDeg1Generated); deg1_extreme_rays = false; is_Computed.set(ConeProperty::IsDeg1ExtremeRays); if (do_deg1_elements || do_h_vector) { errorOutput() << "No grading specified and cannot find one. " << "Disabling some computations!" << endl; do_deg1_elements = false; do_h_vector = false; } } return; // we are done } set_degrees(); if (!isComputed(ConeProperty::IsDeg1Generated)) { deg1_generated = true; for (size_t i = 0; i < nr_gen; i++) { if (gen_degrees[i] != 1) { deg1_generated = false; break; } } is_Computed.set(ConeProperty::IsDeg1Generated); if (deg1_generated) { deg1_extreme_rays = true; is_Computed.set(ConeProperty::IsDeg1ExtremeRays); } } if (!isComputed(ConeProperty::IsDeg1ExtremeRays) && isComputed(ConeProperty::ExtremeRays)) { deg1_extreme_rays = true; for (size_t i = 0; i < nr_gen; i++) { if (Extreme_Rays[i] && gen_degrees[i] != 1) { deg1_extreme_rays = false; break; } } is_Computed.set(ConeProperty::IsDeg1ExtremeRays); } } //--------------------------------------------------------------------------- template void Full_Cone::check_deg1_hilbert_basis() { if (isComputed(ConeProperty::IsDeg1HilbertBasis)) return; if ( !isComputed(ConeProperty::Grading) || !isComputed(ConeProperty::HilbertBasis)) { errorOutput() << "WARNING: unsatisfied preconditions in check_deg1_hilbert_basis()!" < >::iterator h; for (h = Hilbert_Basis.begin(); h != Hilbert_Basis.end(); ++h) { if (v_scalar_product((*h),Grading)!=1) { deg1_hilbert_basis = false; break; } } } is_Computed.set(ConeProperty::IsDeg1HilbertBasis); } //--------------------------------------------------------------------------- template void Full_Cone::check_integrally_closed() { if (isComputed(ConeProperty::IsIntegrallyClosed)) return; if ( !isComputed(ConeProperty::HilbertBasis)) { errorOutput() << "WARNING: unsatisfied preconditions in check_integrally_closed()!" < >::iterator h; for (h = Hilbert_Basis.begin(); h != Hilbert_Basis.end(); ++h) { integrally_closed = false; for (size_t i=0; i< nr_gen; i++) { if ((*h) == Generators[i]) { integrally_closed = true; break; } } if (!integrally_closed) { break; } } } is_Computed.set(ConeProperty::IsIntegrallyClosed); } //--------------------------------------------------------------------------- // Global reduction //--------------------------------------------------------------------------- // Returns true if new_element is reducible versus the elements in Irred template bool Full_Cone::is_reducible(list< vector* >& Irred, const vector< Integer >& new_element){ size_t i; size_t s=Support_Hyperplanes.size(); // new_element can be longer than dim (it has one extra entry for the norm) // the scalar product function just takes the first dim entries vector scalar_product=l_multiplication(Support_Hyperplanes,new_element); typename list< vector* >::iterator j; vector *reducer; for (j =Irred.begin(); j != Irred.end(); j++) { reducer=(*j); for (i = 0; i < s; i++) { if ((*reducer)[i]>scalar_product[i]){ break; } } if (i==s) { //found a "reducer" and move it to the front Irred.push_front(*j); Irred.erase(j); return true; } } return false; } //--------------------------------------------------------------------------- // reduce the Candidates against itself and stores the remaining elements in Hilbert_Basis */ template void Full_Cone::global_reduction() { Integer norm; list > HB; typename list >::iterator c; for (size_t i = 0; i degree_function=compute_degree_function(); c = Candidates.begin(); size_t cpos = 0; size_t csize=Candidates.size(); if(verbose) { verboseOutput()<<"computing the degrees of the candidates... "< scalar_product; for (size_t j=0; j cpos; ++cpos, ++c) ; for(;j < cpos; --cpos, --c) ; norm=v_scalar_product(degree_function,(*c)); c->reserve(dim+1); c->push_back(norm); } if(verbose) { verboseOutput()<<"sorting the list... "<); if (verbose) { verboseOutput()<< csize <<" candidate vectors sorted."< > HBtmp; Integer norm_crit; while ( !Candidates.empty() ) { //use norm criterion to find irreducible elements c=Candidates.begin(); norm_crit=(*c)[dim]*2; //candidates with smaller norm are irreducible if ( Candidates.back()[dim] < norm_crit) { //all candidates are irreducible if (verbose) { verboseOutput()<pop_back(); } Hilbert_Basis.splice(Hilbert_Basis.end(), Candidates); break; } while ( (*c)[dim] < norm_crit ) { //can't go over the end because of the previous if // remove norm c->pop_back(); // push the scalar products to the reducer list HBtmp.push_back(l_multiplication(Support_Hyperplanes, *c)); // and the candidate itself to the Hilbert basis Hilbert_Basis.splice(Hilbert_Basis.end(), Candidates, c++); } csize = Candidates.size(); if (verbose) { verboseOutput()<* > HBpointers; // used to put "reducer" to the front c = HBtmp.begin(); while (c != HBtmp.end()) { HBpointers.push_back(&(*(c++))); } long VERBOSE_STEPS = 50; //print | for 2% if (verbose && csize>50000) { //print | for 1000 candidates VERBOSE_STEPS=csize/1000; } long step_x_size = csize-VERBOSE_STEPS; long counter = 0; long steps_done = 0; if (verbose) { verboseOutput() << "---------+---------+---------+---------+---------+"; if (VERBOSE_STEPS == 50) { verboseOutput() << " (one | per 2%)" << endl; } else { verboseOutput() << " (one | per 1000 candidates)" << endl; } } #pragma omp parallel private(c,cpos) firstprivate(HBpointers) { c=Candidates.begin(); cpos=0; #pragma omp for schedule(dynamic) for (size_t k=0; k cpos; ++cpos, ++c) ; for(;k < cpos; --cpos, --c) ; if ( is_reducible(HBpointers, *c) ) { (*c)[dim]=-1; //mark as reducible } if (verbose) { #pragma omp critical(VERBOSE) { counter++; while (counter*VERBOSE_STEPS >= step_x_size) { steps_done++; step_x_size += csize; verboseOutput() << "|" < 50 && steps_done%50 == 0) { verboseOutput() << " " << (steps_done) << "000" << endl; } } } //end critical(VERBOSE) } } //end for } //end parallel if (verbose) verboseOutput() << endl; // delete reducible candidates c = Candidates.begin(); while (c != Candidates.end()) { if ((*c)[dim]==-1) { c = Candidates.erase(c); } else { ++c; } } HBtmp.clear(); } if (verbose) { verboseOutput()<0 */ template vector Full_Cone::compute_degree_function() const { size_t i; vector degree_function(dim,0); if (isComputed(ConeProperty::Grading)) { //use the grading if we have one for (i=0; i >::const_iterator h; for (h=Support_Hyperplanes.begin(); h!=Support_Hyperplanes.end(); ++h) { for (i=0; i Integer Full_Cone::primary_multiplicity() const{ size_t i,j,k; Integer primary_multiplicity=0; vector key,new_key(dim-1); Matrix Projection(nr_gen,dim-1); for (i = 0; i < nr_gen; i++) { for (j = 0; j < dim-1; j++) { Projection.write(i,j,Generators[i][j]); } } typename list< vector >::const_iterator h; typename list< SHORTSIMPLEX >::const_iterator t; for (h =Support_Hyperplanes.begin(); h != Support_Hyperplanes.end(); ++h){ if ((*h)[dim-1]!=0) { for (t =Triangulation.begin(); t!=Triangulation.end(); ++t){ key=t->key; for (i = 0; i void Full_Cone::reset_tasks(){ do_triangulation = false; do_partial_triangulation = false; do_multiplicity=false; do_Hilbert_basis = false; do_deg1_elements = false; keep_triangulation = false; do_Stanley_dec=false; do_h_vector=false; do_evaluation = false; do_only_multiplicity=false; nrSimplicialPyr=0; totalNrPyr=0; is_pyramid = false; } //--------------------------------------------------------------------------- template Full_Cone::Full_Cone(Matrix M){ // constructor of the top cone dim=M.nr_of_columns(); if (dim!=M.rank()) { error_msg("error: Matrix with rank = number of columns needed in the constructor of the object Full_Cone.\nProbable reason: Cone not full dimensional (<=> dual cone not pointed)!"); throw BadInputException(); } Generators = M; nr_gen=Generators.nr_of_rows(); if (nr_gen != static_cast(static_cast(nr_gen))) { error_msg("To many generators to fit in range of key_t!"); throw FatalException(); } //make the generators coprime, remove 0 rows and duplicates vector gcds = Generators.make_prime(); bool remove_some = false; vector key(nr_gen, true); for (size_t i = 0; i(); //initialized to false is_Computed.set(ConeProperty::Generators); pointed = false; deg1_extreme_rays = false; deg1_generated = false; deg1_hilbert_basis = false; integrally_closed = false; reset_tasks(); Extreme_Rays = vector(nr_gen,false); in_triang = vector (nr_gen,false); deg1_triangulation = true; if(dim==0){ //correction needed to include the 0 cone; multiplicity = 1; Hilbert_Series.add(vector(1,1),vector()); is_Computed.set(ConeProperty::HilbertSeries); is_Computed.set(ConeProperty::Triangulation); } pyr_level=-1; Top_Cone=this; Top_Key.resize(nr_gen); for(size_t i=0;i Full_Cone::Full_Cone(const Cone_Dual_Mode &C) { dim = C.dim; Generators = C.get_generators(); nr_gen = Generators.nr_of_rows(); multiplicity = 0; is_Computed = bitset(); //initialized to false is_Computed.set(ConeProperty::Generators); pointed = true; is_Computed.set(ConeProperty::IsPointed); deg1_extreme_rays = false; deg1_generated = false; deg1_triangulation = false; deg1_hilbert_basis = false; integrally_closed = false; reset_tasks(); Extreme_Rays = vector(nr_gen,true); //all generators are extreme rays is_Computed.set(ConeProperty::ExtremeRays); Matrix SH = C.SupportHyperplanes; for (size_t i=0; i < SH.nr_of_rows(); i++) { Support_Hyperplanes.push_back(SH[i]); } is_Computed.set(ConeProperty::SupportHyperplanes); in_triang = vector(nr_gen,false); Hilbert_Basis = C.Hilbert_Basis; is_Computed.set(ConeProperty::HilbertBasis); if(dim==0){ //correction needed to include the 0 cone; multiplicity = 1; Hilbert_Series.add(vector(1,1),vector()); is_Computed.set(ConeProperty::HilbertSeries); } pyr_level=-1; Top_Cone=this; Top_Key.resize(nr_gen); for(size_t i=0;i Full_Cone::Full_Cone(Full_Cone& C, const vector& Key) { Generators = C.Generators.submatrix(Key); dim = Generators.nr_of_columns(); nr_gen = Generators.nr_of_rows(); Top_Cone=C.Top_Cone; // relate to top cone Top_Key.resize(nr_gen); for(size_t i=0;i(nr_gen,false); is_Computed.set(ConeProperty::ExtremeRays, C.isComputed(ConeProperty::ExtremeRays)); if(isComputed(ConeProperty::ExtremeRays)) for(size_t i=0;i (nr_gen,false); deg1_triangulation = true; Grading=C.Grading; is_Computed.set(ConeProperty::Grading, C.isComputed(ConeProperty::Grading)); Order_Vector=C.Order_Vector; do_triangulation=C.do_triangulation; do_partial_triangulation=C.do_partial_triangulation; do_multiplicity=C.do_multiplicity; do_deg1_elements=C.do_deg1_elements; do_h_vector=C.do_h_vector; do_Hilbert_basis=C.do_Hilbert_basis; keep_triangulation=C.keep_triangulation; do_only_multiplicity=C.do_only_multiplicity; do_evaluation=C.do_evaluation; do_Stanley_dec=C.do_Stanley_dec; is_pyramid=true; // pyr_level set by the calling routine totalNrSimplices=0; detSum = 0; if(C.gen_degrees.size()>0){ // now we copy the degrees gen_degrees.resize(nr_gen); for (size_t i=0; i bool Full_Cone::isComputed(ConeProperty::Enum prop) const{ return is_Computed.test(prop); } //--------------------------------------------------------------------------- // Data access //--------------------------------------------------------------------------- template size_t Full_Cone::getDimension()const{ return dim; } //--------------------------------------------------------------------------- template size_t Full_Cone::getNrGenerators()const{ return nr_gen; } //--------------------------------------------------------------------------- template bool Full_Cone::isPointed()const{ return pointed; } //--------------------------------------------------------------------------- template bool Full_Cone::isDeg1ExtremeRays() const{ return deg1_extreme_rays; } template bool Full_Cone::isDeg1HilbertBasis() const{ return deg1_hilbert_basis; } template bool Full_Cone::isIntegrallyClosed() const{ return integrally_closed; } //--------------------------------------------------------------------------- template vector Full_Cone::getGrading() const{ return Grading; } //--------------------------------------------------------------------------- template mpq_class Full_Cone::getMultiplicity()const{ return multiplicity; } //--------------------------------------------------------------------------- template const Matrix& Full_Cone::getGenerators()const{ return Generators; } //--------------------------------------------------------------------------- template vector Full_Cone::getExtremeRays()const{ return Extreme_Rays; } //--------------------------------------------------------------------------- template Matrix Full_Cone::getSupportHyperplanes()const{ size_t s= Support_Hyperplanes.size(); Matrix M(s,dim); size_t i=0; typename list< vector >::const_iterator l; for (l =Support_Hyperplanes.begin(); l != Support_Hyperplanes.end(); l++) { M.write(i,(*l)); i++; } return M; } //--------------------------------------------------------------------------- template void Full_Cone::getTriangulation(list< vector >& Triang, list& TriangVol) const { Triang.clear(); TriangVol.clear(); vector key(dim); typename list< SHORTSIMPLEX >::const_iterator l; for (l =Triangulation.begin(); l != Triangulation.end(); l++) { key=l->key; Triang.push_back(key); TriangVol.push_back(l->height); } } //--------------------------------------------------------------------------- template Matrix Full_Cone::getHilbertBasis()const{ size_t s= Hilbert_Basis.size(); Matrix M(s,dim); size_t i=0; typename list< vector >::const_iterator l; for (l =Hilbert_Basis.begin(); l != Hilbert_Basis.end(); l++) { M.write(i,(*l)); i++; } return M; } //--------------------------------------------------------------------------- template Matrix Full_Cone::getDeg1Elements()const{ size_t s= Deg1_Elements.size(); Matrix M(s,dim); size_t i=0; typename list< vector >::const_iterator l; for (l =Deg1_Elements.begin(); l != Deg1_Elements.end(); l++) { M.write(i,(*l)); i++; } return M; } //--------------------------------------------------------------------------- template void Full_Cone::error_msg(string s) const{ errorOutput() <<"\nFull Cone "<< s<<"\n"; } //--------------------------------------------------------------------------- template void Full_Cone::print()const{ verboseOutput()<<"\ndim="<. * */ #ifndef FULL_CONE_H #define FULL_CONE_H #include #include //#include #include #include "libnormaliz.h" #include "cone_property.h" #include "matrix.h" #include "simplex.h" #include "cone_dual_mode.h" #include "HilbertSeries.h" namespace libnormaliz { using std::list; using std::vector; //using std::set; using std::pair; using boost::dynamic_bitset; template class Cone; template class Full_Cone { friend class Cone; friend class SimplexEvaluator; size_t dim; size_t nr_gen; size_t hyp_size; // not used at present bool pointed; bool deg1_generated; bool deg1_extreme_rays; bool deg1_triangulation; bool deg1_hilbert_basis; bool integrally_closed; // control of what to compute bool do_triangulation; bool do_partial_triangulation; bool do_multiplicity; bool do_Hilbert_basis; bool do_deg1_elements; bool do_h_vector; bool keep_triangulation; bool do_Stanley_dec; // internal helper control variables bool do_only_multiplicity; bool do_evaluation; ConeProperties is_Computed; vector Grading; mpq_class multiplicity; Matrix Generators; vector Extreme_Rays; list > Support_Hyperplanes; vector in_triang; list > Hilbert_Basis; list > Candidates; // for the Hilbert basis size_t CandidatesSize; list > Deg1_Elements; HilbertSeries Hilbert_Series; vector gen_degrees; // will contain the degrees of the generators // list< SHORTSIMPLEX > CheckTri; list < SHORTSIMPLEX > Triangulation; // triangulation of cone size_t TriangulationSize; // number of elements in Triangulation, for efficiency Integer detSum; // sum of the det vector >::iterator> TriSectionFirst; // first simplex with lead vertex i vector >::iterator> TriSectionLast; // last simplex with lead vertex i vector VertInTri; // generators in the order in which they are inserted into the triangulation list< SHORTSIMPLEX > FreeSimpl; // list of short simplices already evaluated, kept for recycling vector > > FS; // the same per thread vector< SimplexEvaluator > SimplexEval; // one per thread struct FACETDATA { vector Hyp; // linear form of the hyperplane boost::dynamic_bitset<> GenInHyp; // incidence hyperplane/generators Integer ValNewGen; // value of linear form on the generator to be added // value on last generator added }; list Facets; // contains the data for Fourier-Motzkin and extension of triangulation vector Order_Vector; // vector for the disjoint decomposition of the cone list< STANLEYDATA > StanleyDec; // Stanley decomposition Full_Cone* Top_Cone; // reference to cone on top level vector Top_Key; // indices of generators w.r.t Top_Cone // control of pyramids and recusrion int pyr_level; // -1 for top cone, increased by 1 for each level of pyramids bool is_pyramid; // false for top cone bool do_all_hyperplanes; // controls whether all support hyperplanes must be computed long last_to_be_inserted; // good to know in case of do_all_hyperplanes==false bool recursion_allowed; // to allow or block recursive formation of pytamids bool parallel_inside_pyramid; // indicates that paralleization is taking place INSIDE the pyramid bool supphyp_recursion; // true if we have gone to pyramids because of support hyperplanes bool tri_recursion; // true if we have gone to pyramids because of triangulation vector< list > > Pyramids; //storage for pyramids vector nrPyramids; // number of pyramids on the various levels long nextGen; // the next generator to be processed size_t old_nr_supp_hyps; // must be remembered since we may leave extend_cone // before discarding "negative" hyperplanes Full_Cone* Mother; // reference to the mother of the pyramid boost::dynamic_bitset<> in_Pyramid; // indicates which generators of the MOTHER are in pyramid size_t new_generator; // indicates which generator of mother cone is apex of pyramid vector > > RecPyrs; // storage for recursive pyramids vector nrRecPyrs; size_t nrRecPyramidsDue; // number of recursive pyramids created from this at the current extension size_t nrRecPyramidsDone; // number of recursive pyramids that have returned supphyps bool allRecPyramidsBuilt; // indicates that all recursive pyramids from the current generator have been built bool Done; // true if this cone has been finished // statistics size_t totalNrSimplices; // total number of simplices evaluated size_t nrSimplicialPyr; size_t totalNrPyr; /* --------------------------------------------------------------------------- * Private routines, used in the public routines * --------------------------------------------------------------------------- */ void add_hyperplane(const size_t& new_generator, const FACETDATA & positive,const FACETDATA & negative, list& NewHyps); void extend_triangulation(const size_t& new_generator); void find_new_facets(const size_t& new_generator); void process_pyramids(const size_t new_generator,const bool recursive); void process_pyramid(const vector& Pyramid_key, const boost::dynamic_bitset<>& in_Pyramid, const size_t new_generator, const size_t store_level, Integer height, const bool recursive); void select_supphyps_from(list >& NewFacets, const size_t new_generator, const boost::dynamic_bitset<>& in_Pyramid); void evaluate_stored_pyramids(const size_t level); void evaluate_rec_pyramids(const size_t level); void find_and_evaluate_start_simplex(); Simplex find_start_simplex() const; void store_key(const vector&, const Integer& height, const Integer& mother_vol, list< SHORTSIMPLEX >& Triangulation); void build_top_cone(); void extend_cone(); bool is_reducible(list *> & Irred, const vector & new_element); void global_reduction(); vector compute_degree_function() const; Matrix select_matrix_from_list(const list >& S,vector& selection); void extreme_rays_and_deg1_check(); void set_degrees(); void sort_gens_by_degree(); void compute_support_hyperplanes(); bool check_evaluation_buffer(); bool check_evaluation_buffer_size(); void evaluate_triangulation(); void transfer_triangulation_to_top(); void primal_algorithm(); void compute_extreme_rays(); void compute_extreme_rays_compare(); void compute_extreme_rays_rank(); void select_deg1_elements(); void check_pointed(); void deg1_check(); void check_deg1_extreme_rays(); void check_deg1_hilbert_basis(); void check_integrally_closed(); void compute_multiplicity(); void do_vars_check(); void reset_tasks(); void addMult(Integer& volume, const vector& key, const int& tn); // multiplicity sum over thread tn public: /*--------------------------------------------------------------------------- * Constructors *--------------------------------------------------------------------------- */ Full_Cone(Matrix M); //main constructor Full_Cone(const Cone_Dual_Mode &C); Full_Cone(Full_Cone& C, const vector& Key); // for pyramids /*--------------------------------------------------------------------------- * Data access *--------------------------------------------------------------------------- */ void print() const; //to be modified, just for tests size_t getDimension() const; size_t getNrGenerators() const; bool isPointed() const; bool isDeg1ExtremeRays() const; bool isDeg1HilbertBasis() const; bool isIntegrallyClosed() const; vector getGrading() const; mpq_class getMultiplicity() const; const Matrix& getGenerators() const; vector getExtremeRays() const; Matrix getSupportHyperplanes() const; void getTriangulation(list< vector >& Triang, list& TriangVol) const; Matrix getHilbertBasis() const; Matrix getDeg1Elements() const; vector getHVector() const; bool isComputed(ConeProperty::Enum prop) const; /*--------------------------------------------------------------------------- * Computation Methods *--------------------------------------------------------------------------- */ void dualize_cone(); void support_hyperplanes(); void compute(); /* computes the multiplicity of the ideal in case of a Rees algebra * (not the same as the multiplicity of the semigroup) */ Integer primary_multiplicity() const; void dual_mode(); void error_msg(string s) const; }; //class end ***************************************************************** //--------------------------------------------------------------------------- } //--------------------------------------------------------------------------- #endif //--------------------------------------------------------------------------- regina-4.96/engine/enumerate/normaliz/general.h000644 000765 000024 00000002377 12311266525 021477 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #ifndef GENERAL_H_ #define GENERAL_H_ #include #include #include /* // Regina will use GMP everywhere, even on Windows. #ifdef _WIN32 //for 32 and 64 bit windows #define NMZ_MPIR //always use MPIR #endif */ #ifdef NMZ_MPIR // use MPIR #include #else // otherwise use GMP #include #endif #include "libnormaliz.h" #include "normaliz_exception.h" #include "cone_property.h" namespace libnormaliz { } /* end namespace libnormaliz */ #endif /* GENERAL_H_ */ regina-4.96/engine/enumerate/normaliz/HilbertSeries.cpp000644 000765 000024 00000045707 12311266525 023165 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include #include #include #include #include "HilbertSeries.h" #include "vector_operations.h" #include "map_operations.h" #include "integer.h" #include "matrix.h" //--------------------------------------------------------------------------- namespace libnormaliz { using std::cout; using std::endl; using std::flush; long lcm_of_keys(const map& m){ long l = 1; map::const_iterator it; for (it = m.begin(); it != m.end(); ++it) { if (it->second != 0) l = lcm(l,it->first); } return l; } //--------------------------------------------------------------------------- // Constructor, creates 0/1 HilbertSeries::HilbertSeries() { num = vector(1,0); //denom just default constructed } // Constructor, creates num/denom, see class description for format HilbertSeries::HilbertSeries(const vector& numerator, const vector& gen_degrees) { num = vector(1,0); add(numerator, gen_degrees); } // Constructor, creates num/denom, see class description for format HilbertSeries::HilbertSeries(const vector& numerator, const map& denominator) { num = numerator; denom = denominator; is_simplified = false; } void HilbertSeries::reset() { num.clear(); num.push_back(0); denom.clear(); denom_classes.clear(); is_simplified = false; } // add another HilbertSeries to this void HilbertSeries::add(const vector& num, const vector& gen_degrees) { vector sorted_gd(gen_degrees); sort(sorted_gd.begin(), sorted_gd.end()); if (gen_degrees.size() > 0) assert(sorted_gd[0]>0); //TODO InputException? poly_add_to(denom_classes[sorted_gd], num); if (denom_classes.size() > DENOM_CLASSES_BOUND) collectData(); is_simplified = false; } // add another HilbertSeries to this HilbertSeries& HilbertSeries::operator+=(const HilbertSeries& other) { // add denom_classes map< vector, vector >::const_iterator it; for (it = other.denom_classes.begin(); it != other.denom_classes.end(); ++it) { poly_add_to(denom_classes[it->first], it->second); } // add accumulated data vector num_copy(other.num); performAdd(num_copy, other.denom); return (*this); } void HilbertSeries::performAdd(const vector& numerator, const vector& gen_degrees) const { map other_denom; size_t i, s = gen_degrees.size(); for (i=0; i0); other_denom[gen_degrees[i]]++; } // convert numerator to mpz s = numerator.size(); vector other_num(s); for (i=0; i& other_num, const map& oth_denom) const { map other_denom(oth_denom); //TODO redesign, dont change other_denom // adjust denominators denom_t diff; map::iterator it; for (it = denom.begin(); it != denom.end(); ++it) { // augment other denom_t& ref = other_denom[it->first]; diff = it->second - ref; if (diff > 0) { ref += diff; poly_mult_to(other_num, it->first, diff); } } for (it = other_denom.begin(); it != other_denom.end(); ++it) { // augment this denom_t& ref = denom[it->first]; diff = it->second - ref; if (diff > 0) { ref += diff; poly_mult_to(num, it->first, diff); } } assert (denom == other_denom); // now just add the numerators poly_add_to(num,other_num); remove_zeros(num); is_simplified = false; } void HilbertSeries::collectData() const { if (verbose) verboseOutput() << "Adding " << denom_classes.size() << " denominator classes..." << flush; map< vector, vector >::iterator it; for (it = denom_classes.begin(); it != denom_classes.end(); ++it) { performAdd(it->second, it->first); } denom_classes.clear(); if (verbose) verboseOutput() << " done." << endl; } // simplify, see class description void HilbertSeries::simplify() const { if (is_simplified) return; collectData(); /* if (verbose) { cout << "Hilbert series before simplification: "<< endl << *this; }*/ vector q, r, poly; //polynomials // In denom_cyclo we collect cyclotomic polynomials in the denominator. // During this method the Hilbert series is given by num/(denom*cdenom) // where denom | cdenom are exponent vectors of (1-t^i) | i-th cyclotminc poly. map cdenom; map::reverse_iterator rit; long i; for (rit = denom.rbegin(); rit != denom.rend(); ++rit) { // check if we can divide the numerator by (1-t^i) i = rit->first; denom_t& denom_i = rit->second; poly = coeff_vector(i); while (denom_i > 0) { poly_div(q, r, num, poly); if (r.size() == 0) { // numerator is divisable by poly num = q; denom_i--; } else { break; } } if (denom_i == 0) continue; // decompose (1-t^i) into cyclotomic polynomial for(long d=1; d<=i/2; ++d) { if (i % d == 0) cdenom[d] += denom_i; } cdenom[i] += denom_i; // the product of the cyclo. is t^i-1 = -(1-t^i) if (denom_i%2 == 1) v_scalar_multiplication(num,mpz_class(-1)); } // end for denom.clear(); map::iterator it = cdenom.begin(); while (it != cdenom.end()) { // check if we can divide the numerator by i-th cyclotomic polynomial i = it->first; denom_t& cyclo_i = it->second; poly = cyclotomicPoly(i); while (cyclo_i > 0) { poly_div(q, r, num, poly); if (r.size() == 0) { // numerator is divisable by poly num = q; cyclo_i--; } else { break; } } if (cyclo_i == 0) { cdenom.erase(it++); } else { ++it; } } // done with canceling // save this representation cyclo_num = num; cyclo_denom = cdenom; // now collect the cyclotomic polynomials in (1-t^i) factors it = cdenom.find(1); if (it != cdenom.end()) dim = it->second; else dim = 0; period = lcm_of_keys(cdenom); i = period; if (period > 2000) { errorOutput() << "WARNING: Period is to big, the representation of the Hilbert series may have more than dimensional many factors in the denominator!" << endl; i = cdenom.rbegin()->first; } while (!cdenom.empty()) { //create a (1-t^i) factor out of all cyclotomic poly. denom[i]++; v_scalar_multiplication(num,mpz_class(-1)); for (long d = 1; d <= i; ++d) { if (i % d == 0) { it = cdenom.find(d); if (it != cdenom.end() && it->second>0) { it->second--; if (it->second == 0) cdenom.erase(it); } else { num = poly_mult(num, cyclotomicPoly(d)); } } } i = lcm_of_keys(cdenom); if (i > 2000) { i = cdenom.rbegin()->first; } } /* if (verbose) { cout << "Simplified Hilbert series: " << endl << *this; }*/ is_simplified = true; } long HilbertSeries::getPeriod() const { simplify(); return period; } vector< vector > HilbertSeries::getHilbertQuasiPolynomial() const { if(!is_simplified || quasi_poly.size()==0) { computeHilbertQuasiPolynomial(); } return quasi_poly; } mpz_class HilbertSeries::getHilbertQuasiPolynomialDenom() const { if(!is_simplified || quasi_poly.size()==0) { computeHilbertQuasiPolynomial(); } return quasi_denom; } void HilbertSeries::computeHilbertQuasiPolynomial() const { simplify(); if (period > 2000) { errorOutput()<<"WARNING: We skip the computation of the Hilbert-quasi-polynomial because the period "<< period <<" is to big!" < norm_num(num_size); //normalized numerator for (i = 0; i < num_size; ++i) { norm_num[i] = to_mpz(num[i]); } map::reverse_iterator rit; long d; vector factor, r; for (rit = denom.rbegin(); rit != denom.rend(); ++rit) { d = rit->first; //nothing to do if it already has the correct t-power if (d != period) { //norm_num *= (1-t^p / 1-t^d)^denom[d] poly_div(factor, r, coeff_vector(period), coeff_vector(d)); assert(r.size()==0); //assert remainder r is 0 //TODO more efficient method *= //TODO Exponentiation by squaring of factor, then *= for (i=0; i < rit->second; ++i) { norm_num = poly_mult(norm_num, factor); } } } //cut numerator into period many pieces and apply standard method quasi_poly = vector< vector >(period); long nn_size = norm_num.size(); for (j=0; j= 0; --i) { pp *= period; //p^i ok, it is p^(dim-1-i) for (j=0; j(1,dim) * pp; //substitute t by t-j for (j=0; j(quasi_poly[j], j); // replaces quasi_poly[j] } //divide by gcd //TODO operate directly on vector Matrix QP(quasi_poly); mpz_class g = QP.matrix_gcd(); g = gcd(g,quasi_denom); quasi_denom /= g; QP.scalar_division(g); quasi_poly = QP.get_elements(); } // returns the numerator, repr. as vector of coefficients, the h-vector const vector& HilbertSeries::getNum() const { return num; } // returns the denominator, repr. as a map of the exponents of (1-t^i)^e const map& HilbertSeries::getDenom() const { return denom; } // returns the numerator, repr. as vector of coefficients const vector& HilbertSeries::getCyclotomicNum() const { simplify(); return cyclo_num; } // returns the denominator, repr. as a map of the exponents of (1-t^i)^e const map& HilbertSeries::getCyclotomicDenom() const { simplify(); return cyclo_denom; } ostream& operator<< (ostream& out, const HilbertSeries& HS) { HS.collectData(); out << "("; if (HS.num.size()>0) out << " " << HS.num[0]; for (size_t i=1; i 0 ) out << " +"<::const_iterator it; for (it = HS.denom.begin(); it != HS.denom.end(); ++it) { if ( it->second != 0 ) out << " (1-t^"<< it->first <<")^" << it->second; } out << " )" << std::endl; return out; } //--------------------------------------------------------------------------- // polynomial operations, for polynomials repr. as vector of coefficients //--------------------------------------------------------------------------- // returns the coefficient vector of 1-t^i template vector coeff_vector(size_t i) { vector p(i+1,0); p[0] = 1; p[i] = -1; return p; } template void remove_zeros(vector& a) { size_t i=a.size(); while ( i>0 && a[i-1]==0 ) --i; if (i < a.size()) { a.resize(i); } } // a += b (also possible to define the += op for vector) template void poly_add_to (vector& a, const vector& b) { size_t b_size = b.size(); if (a.size() < b_size) { a.resize(b_size); } for (size_t i=0; i void poly_sub_to (vector& a, const vector& b) { size_t b_size = b.size(); if (a.size() < b_size) { a.resize(b_size); } for (size_t i=0; i vector poly_mult(const vector& a, const vector& b) { size_t a_size = a.size(); size_t b_size = b.size(); vector p( a_size + b_size - 1 ); size_t i,j; for (i=0; i void poly_mult_to(vector& a, long d, long e) { assert(d>0); assert(e>=0); long i; a.reserve(a.size() + d*e); while (e>0) { a.resize(a.size() + d); for (i=a.size()-1; i>=d; --i) { a[i] -= a[i-d]; } e--; } } // division with remainder, a = q * b + r, deg(r) < deg(b), needs |leadcoef(b)| = 1 template void poly_div(vector& q, vector& r, const vector& a, const vector&b) { assert(b.back()!=0); // no unneeded zeros assert(b.back()==1 || b.back()==-1); // then division is always possible r = a; remove_zeros(r); size_t b_size = b.size(); int degdiff = r.size()-b_size; // degree differenz if (r.size() < b_size) { q = vector(); } else { q = vector(degdiff+1); } Integer divisor; size_t i=0; while (r.size() >= b_size) { divisor = r.back()/b.back(); q[degdiff] = divisor; // r -= divisor * t^degdiff * b for (i=0; i vector cyclotomicPoly(long n) { // the static variable is initialized only once and then stored static map > CyclotomicPoly = map >(); if (CyclotomicPoly.count(n) == 0) { //it was not computed so far vector poly, q, r; for (long i = 1; i <= n; ++i) { // compute needed and uncomputed factors if( n % i == 0 && CyclotomicPoly.count(i) == 0) { // compute the i-th poly by dividing X^i-1 by the // d-th cycl.poly. with d divides i poly = vector(i+1); poly[0] = -1; poly[i] = 1; // X^i - 1 for (long d = 1; d < i; ++d) { // <= i/2 should be ok if( i % d == 0) { poly_div(q, r, poly, CyclotomicPoly[d]); assert(r.size()==0); poly = q; } } CyclotomicPoly[i] = poly; //cout << i << "-th cycl. pol.: " << CyclotomicPoly[i]; } } } assert(CyclotomicPoly.count(n)>0); return CyclotomicPoly[n]; } //--------------------------------------------------------------------------- // computing the Hilbert polynomial from h-vector //--------------------------------------------------------------------------- template vector compute_e_vector(vector Q, int dim){ int i,j; vector E_Vector(dim,0); Q.resize(dim+1); for (i = 0; i (1,i); for (j = 1; j <=dim; j++) { Q[j-1]=j*Q[j]; } } return E_Vector; } //--------------------------------------------------------------------------- template vector compute_polynomial(vector h_vector, int dim) { // handle dimension 0 if (dim == 0) return vector(dim); vector Hilbert_Polynomial = vector(dim); int i,j; Integer mult_factor; vector E_Vector=compute_e_vector(h_vector, dim); vector C(dim,0); C[0]=1; for (i = 0; i (i,dim); if (((dim-1-i)%2)==0) { for (j = 0; j (1,i+1); } return Hilbert_Polynomial; } //--------------------------------------------------------------------------- // substitutes t by (t-a), overwrites the polynomial! template void linear_substitution(vector& poly, const Integer& a) { long deg = poly.size()-1; // Iterated division by (t+a) for (long step=0; step= step; --i) { poly[i] -= a * poly[i+1]; } //the remainders are the coefficients of the transformed polynomial } } } //end namespace libnormaliz regina-4.96/engine/enumerate/normaliz/HilbertSeries.h000644 000765 000024 00000015722 12311266525 022624 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ /* * HilbertSeries represents a Hilbert series of a (ZZ_+)-graded algebra * with generators of different degrees. * It is represented as a polynomial divided by a product of (1-t^i). * The numerator is represented as vector of coefficients, the h-vector * h vector repr.: sum of h[i]*t^i * and the denominator is represented as a map d of the exponents of (1-t^i) * d vector repr.: product of (1-t^i)^d[i] over i in d * Input of the denominator is also possible as a vector of degrees of the * generators. * * The class offers basic operations on the series, a simplification and * different forms of representation of the series. * * Furthermore this file include operations for the polynomials used. */ //--------------------------------------------------------------------------- #ifndef HILBERT_SERIES_H #define HILBERT_SERIES_H //--------------------------------------------------------------------------- #include #include #include #include "general.h" //--------------------------------------------------------------------------- namespace libnormaliz { using std::vector; using std::map; using std::ostream; class HilbertSeries; // write a readable representation to the stream ostream& operator<< (ostream& out, const HilbertSeries& HS); typedef long long num_t; //integer type for numerator typedef long denom_t; //integer type for denominator class HilbertSeries { public: // Constructor, creates 0/1 HilbertSeries(); // Constructor, creates num/denom, see class description for format HilbertSeries(const vector& num, const vector& gen_degrees); // Constructor, creates num/denom, see class description for format HilbertSeries(const vector& num, const map& denom); // resets to 0/1 void reset(); // add another HilbertSeries to this HilbertSeries& operator+=(const HilbertSeries& other); // add another HilbertSeries to this void add(const vector& num, const vector& gen_degrees); // simplify, see class description // it changes the representation of the series, but not the series itself // therefore it is declared const void simplify() const; // collect data from the denom_classes void collectData() const; // returns the numerator, repr. as vector of coefficients, the h-vector const vector& getNum() const; // returns the denominator, repr. as a map of the exponents of (1-t^i)^e const map& getDenom() const; // returns the numerator, repr. as vector of coefficients const vector& getCyclotomicNum() const; // returns the denominator, repr. as a map of the exponents of the cyclotomic polynomials const map& getCyclotomicDenom() const; long getPeriod() const; vector< vector > getHilbertQuasiPolynomial() const; mpz_class getHilbertQuasiPolynomialDenom() const; private: // collected data in denominator classes mutable map< vector, vector > denom_classes; // add the classes if they get too many static const size_t DENOM_CLASSES_BOUND = 50000; // the numerator, repr. as vector of coefficients, the h-vector mutable vector num; // the denominator, repr. as a map of the exponents of (1-t^i)^e mutable map denom; // the numerator, repr. as vector of coefficients mutable vector cyclo_num; // the denominator, repr. as a map of the exponents of the cyclotomic polynomials mutable map cyclo_denom; mutable bool is_simplified; mutable long dim; mutable long period; // the quasi polynomial, can have big coefficients mutable vector< vector > quasi_poly; mutable mpz_class quasi_denom; // these are only const when used properly!! void performAdd(const vector& num, const vector& gen_degrees) const; void performAdd(vector& num, const map& denom) const; void computeHilbertQuasiPolynomial() const; friend ostream& operator<< (ostream& out, const HilbertSeries& HS); }; //class end ***************************************************************** //--------------------------------------------------------------------------- // polynomial operations, for polynomials repr. as vector of coefficients //--------------------------------------------------------------------------- // a += b template void poly_add_to (vector& a, const vector& b); // a -= b template void poly_sub_to (vector& a, const vector& b); // a * b template vector poly_mult(const vector& a, const vector& b); // a *= (1-t^d)^e template void poly_mult_to(vector& a, long d, long e = 1); // division with remainder, a = q * b + r template void poly_div(vector& q, vector& r, const vector& a, const vector&b); // remove leading zero coefficients, 0 polynomial leads to empty list template void remove_zeros(vector& a); // Returns the n-th cyclotomic polynomial, all smaller are computed and stored. // The n-th cyclotomic polynomial is the product of (X-w) over all // n-th primitive roots of unity w. template vector cyclotomicPoly(long n); // returns the coefficient vector of 1-t^i template vector coeff_vector(size_t i); // substitutes t by (t-a), overwrites the polynomial! template void linear_substitution(vector& poly, const Integer& a); //--------------------------------------------------------------------------- // computing the Hilbert polynomial from h-vector //--------------------------------------------------------------------------- template vector compute_e_vector(vector h_vector, int dim); template vector compute_polynomial(vector h_vector, int dim); } //end namespace libnormaliz //--------------------------------------------------------------------------- #endif //--------------------------------------------------------------------------- regina-4.96/engine/enumerate/normaliz/integer.cpp000644 000765 000024 00000006400 12311266525 022041 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ //--------------------------------------------------------------------------- #include #include "integer.h" #include "limits.h" //--------------------------------------------------------------------------- namespace libnormaliz { using namespace std; bool fits_long_range(long long a) { //TODO make it return true without check when ranges are the same return ( a <= LONG_MAX && a >= LONG_MIN); } mpz_class to_mpz(long a) { return mpz_class(a); } mpz_class to_mpz(long long a) { if (fits_long_range(a)) { return mpz_class(long(a)); } else { static long long mod = LONG_MAX; // to ensure the following % and / are done in long long return mpz_class(long (a % mod)) + mpz_class(LONG_MAX) * to_mpz(long(a/mod)); } } template Integer gcd(const Integer& a, const Integer& b){ if (a==0) { return Iabs(b); } if (b==0) { return Iabs(a); } Integer q0,q1,r; q0=Iabs(a); r=Iabs(b); do { q1=r; r=q0%q1; q0=q1; } while (r!=0); return q1; } template<> mpz_class gcd(const mpz_class& a, const mpz_class& b) { mpz_class g; mpz_gcd (g.get_mpz_t(), a.get_mpz_t(), b.get_mpz_t()); return g; } //--------------------------------------------------------------------------- template Integer lcm(const Integer& a, const Integer& b){ if ((a==0)||(b==0)) { return 0; } else return Iabs(a*b/gcd(a,b)); } template<> mpz_class lcm(const mpz_class& a, const mpz_class& b) { mpz_class g; mpz_lcm (g.get_mpz_t(), a.get_mpz_t(), b.get_mpz_t()); return g; } //--------------------------------------------------------------------------- template size_t decimal_length(Integer a){ size_t l=1; if (a<0) { a=-a; l++; } while((a/=10)!=0) l++; return l; } //--------------------------------------------------------------------------- template Integer permutations(const size_t& a, const size_t& b){ unsigned long i; Integer P=1; for (i = a+1; i <= b; i++) { P*=i; } return P; } //--------------------------------------------------------------------------- template Integer permutations_modulo(const size_t& a, const size_t& b, long m) { unsigned long i; Integer P=1; for (i = a+1; i <= b; i++) { P*=i; P%=m; } return P; } //--------------------------------------------------------------------------- } regina-4.96/engine/enumerate/normaliz/integer.h000644 000765 000024 00000006310 12311266525 021506 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #ifndef INTEGER_H_ #define INTEGER_H_ #include "general.h" // Integer should (may) support: // Integer abs(Integer); here implemented as Iabs // Integer min(Integer, Integer); here we use the template min in // It provides abs, gcd and lcm //--------------------------------------------------------------------------- namespace libnormaliz { //--------------------------------------------------------------------------- bool fits_long_range(long long a); mpz_class to_mpz(long a); mpz_class to_mpz(long long a); inline mpz_class to_mpz(const mpz_class& a) {return a;} template inline long explicit_cast_to_long(const Integer& a) { // check for overflow if (!fits_long_range(a)) { throw ArithmeticException(); } return (long)a; } template<> inline long explicit_cast_to_long(const long& a) { return a; } template<> inline long explicit_cast_to_long (const mpz_class& a) { // check for overflow if (!a.fits_slong_p()) { throw ArithmeticException(); } return a.get_si(); } //--------------------------------------------------------------------------- // Basic functions //--------------------------------------------------------------------------- // returns the absolute value of a template inline Integer Iabs(const Integer& a) { return (a>=0) ? (a) : Integer(-a); } //returns gcd of a and b, if one is 0 returns the other integer template Integer gcd(const Integer& a, const Integer& b); template<> mpz_class gcd(const mpz_class& a, const mpz_class& b); //returns lcm of a and b, returns 0 if one is 0 template Integer lcm(const Integer& a, const Integer& b); template<> mpz_class lcm(const mpz_class& a, const mpz_class& b); //--------------------------------------------------------------------------- // Special functions //--------------------------------------------------------------------------- //return the number of decimals, needed to write the Integer a template size_t decimal_length(Integer a); //returns b!/a! template Integer permutations(const size_t& a, const size_t& b); template Integer permutations_modulo(const size_t& a, const size_t& b, long m); } //--------------------------------------------------------------------------- #endif /* INTEGER_H_ */ //--------------------------------------------------------------------------- regina-4.96/engine/enumerate/normaliz/libnormaliz-templated.cpp000644 000765 000024 00000005516 12311266525 024712 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "libnormaliz.cpp" #include "integer.cpp" #include "vector_operations.cpp" #include "matrix.cpp" #include "simplex.cpp" #include "list_operations.cpp" #include "lineare_transformation.cpp" #include "sublattice_representation.cpp" #include "full_cone.cpp" #include "cone_dual_mode.cpp" #include "cone.cpp" namespace libnormaliz { template class Cone; template class Cone; template class Cone; template class Matrix; template class Matrix; template class Matrix; template class Sublattice_Representation; template class Sublattice_Representation; template class Sublattice_Representation; template class Lineare_Transformation; template class Lineare_Transformation; template class Lineare_Transformation; template Lineare_Transformation Transformation(const Matrix& M); template Lineare_Transformation Transformation(const Matrix& M); template Lineare_Transformation Transformation(const Matrix& M); template size_t decimal_length(long); template size_t decimal_length(long long int); template size_t decimal_length(mpz_class); template long gcd(const long& a, const long& b); template long lcm(const long& a, const long& b); template long permutations(const size_t& a, const size_t& b); template long long gcd(const long long& a, const long long& b); template long long lcm(const long long& a, const long long& b); template long long permutations(const size_t& a, const size_t& b); //template mpz_class gcd(const mpz_class& a, const mpz_class& b); //template mpz_class lcm(const mpz_class& a, const mpz_class& b); template mpz_class permutations(const size_t& a, const size_t& b); template ostream& operator<< (ostream& out, const vector& v); template ostream& operator<< (ostream& out, const vector& v); template ostream& operator<< (ostream& out, const vector& v); } regina-4.96/engine/enumerate/normaliz/libnormaliz.cpp000644 000765 000024 00000004773 12311266525 022741 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "libnormaliz.h" #include "general.h" namespace libnormaliz { bool verbose = false; bool test_arithmetic_overflow = false; long overflow_test_modulus = 15401; namespace { std::ostream* verbose_ostream_ptr = &std::cout; std::ostream* error_ostream_ptr = &std::cerr; } // end anonymous namespace, only accessible in this file (and when it is included) void setVerboseOutput(std::ostream& v_out) { verbose_ostream_ptr = &v_out; } void setErrorOutput(std::ostream& e_out) { error_ostream_ptr = &e_out; } std::ostream& verboseOutput() { return *verbose_ostream_ptr; } std::ostream& errorOutput() { return *error_ostream_ptr; } InputType to_type(const std::string& type_string) { if (type_string=="0"||type_string=="integral_closure") { return Type::integral_closure; } if (type_string=="1"||type_string=="normalization") { return Type::normalization; } if (type_string=="2"||type_string=="polytope") { return Type::polytope; } if (type_string=="3"||type_string=="rees_algebra") { return Type::rees_algebra; } if (type_string=="4"||type_string=="hyperplanes") { return Type::hyperplanes; } if (type_string=="5"||type_string=="equations") { return Type::equations; } if (type_string=="6"||type_string=="congruences") { return Type::congruences; } if (type_string=="signs") { return Type::signs; } if (type_string=="10"||type_string=="lattice_ideal") { return Type::lattice_ideal; } if (type_string=="grading") { return Type::grading; } std::cerr<<"ERROR: Unknown type \""<. * */ #ifndef LIBNORMALIZ_H_ #define LIBNORMALIZ_H_ #include #include namespace libnormaliz { namespace Type { enum InputType { integral_closure, normalization, polytope, rees_algebra, hyperplanes, signs, equations, congruences, inhomogeneous_hyperplanes, inhomogeneous_equations, inhomogeneous_congruences, lattice_ideal, grading }; } //end namespace Type namespace Mode { enum ComputationMode { supportHyperplanes, triangulationSize, triangulation, volumeTriangulation, volumeLarge, degree1Elements, hilbertBasisTriangulation, hilbertBasisMultiplicity, hilbertBasisLarge, hilbertSeries, hilbertSeriesLarge, hilbertBasisSeries, hilbertBasisSeriesLarge, dual }; } //end namespace Mode using Type::InputType; using Mode::ComputationMode; /* converts a string to an InputType * throws an BadInputException if the string cannot be converted */ InputType to_type(const std::string& type_string); /* this type is used in the entries of keys * it has to be able to hold number of generators */ typedef unsigned int key_t; extern bool verbose; /* if test_arithmetic_overflow is true, many operations are also done * modulo overflow_test_modulus to ensure the correctness of the calculations */ extern bool test_arithmetic_overflow; extern long overflow_test_modulus; /* methods to set and use the output streams */ void setVerboseOutput(std::ostream&); void setErrorOutput(std::ostream&); std::ostream& verboseOutput(); std::ostream& errorOutput(); } /* end namespace libnormaliz */ #endif /* LIBNORMALIZ_H_ */ regina-4.96/engine/enumerate/normaliz/lineare_transformation.cpp000644 000765 000024 00000015350 12311266525 025155 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ //--------------------------------------------------------------------------- #include #include #include #include #include #include "lineare_transformation.h" #include "integer.h" //--------------------------------------------------------------------------- namespace libnormaliz { using namespace std; //--------------------------------------------------------------------------- template Lineare_Transformation::Lineare_Transformation(){ rk=0; status="non initialized"; index=1; } //--------------------------------------------------------------------------- template Lineare_Transformation::Lineare_Transformation(const Matrix& M){ rk=0; status="initialized, before transformation"; index=1; Center = Matrix(M); Right = Matrix(M.nr_of_columns()); Right_Inv = Matrix(M.nr_of_columns()); } //--------------------------------------------------------------------------- template void Lineare_Transformation::read() const{ cout<<"\nRank="< long Lineare_Transformation::get_rank() const{ return rk; } //--------------------------------------------------------------------------- template string Lineare_Transformation::get_status() const{ return status; } //--------------------------------------------------------------------------- template Integer Lineare_Transformation::get_index() const{ return index; } //--------------------------------------------------------------------------- template Matrix Lineare_Transformation::get_center()const{ return Center; } //--------------------------------------------------------------------------- template Matrix Lineare_Transformation::get_right() const{ return Right; } //--------------------------------------------------------------------------- template Matrix Lineare_Transformation::get_right_inv() const{ return Right_Inv; } //--------------------------------------------------------------------------- template void Lineare_Transformation::set_rank(const size_t rank) { rk = rank; } //--------------------------------------------------------------------------- template void Lineare_Transformation::set_center(const Matrix& M){ Center=M; } //--------------------------------------------------------------------------- template void Lineare_Transformation::set_right(const Matrix& M){ Right=M; } //--------------------------------------------------------------------------- template void Lineare_Transformation::set_right_inv(const Matrix& M){ Right_Inv=M; } //--------------------------------------------------------------------------- template void Lineare_Transformation::exchange_rows(size_t row1, size_t row2){ Center.exchange_rows(row1,row2); } //--------------------------------------------------------------------------- template void Lineare_Transformation::exchange_columns(size_t col1, size_t col2){ Center.exchange_columns(col1,col2); Right.exchange_columns(col1,col2); Right_Inv.exchange_rows(col1,col2); } //--------------------------------------------------------------------------- template void Lineare_Transformation::reduce_row(size_t corner){ Center.reduce_row(corner); } //--------------------------------------------------------------------------- template void Lineare_Transformation::reduce_column(size_t corner){ Center.reduce_column(corner, Right, Right_Inv); } //--------------------------------------------------------------------------- template void Lineare_Transformation::transformation(){ long r; long rk_max=min(Center.nr_of_rows(),Center.nr_of_columns()); vector piv(2,0); for (r = 0; r < rk_max; r++) { piv=Center.pivot(r); if (piv[0]>=0) { do { exchange_rows (r,piv[0]); exchange_columns (r,piv[1]); reduce_row (r); reduce_column (r); piv=Center.pivot(r); } while ((piv[0]>r)||(piv[1]>r)); } else break; } rk=r; for (r = 0; r < rk; r++) { index*=Center.read(r,r); } index=Iabs(index); status="initialized, after transformation"; } //--------------------------------------------------------------------------- template bool Lineare_Transformation::test_transformation(const Matrix& M,const size_t& m) const{ size_t nc=Center.nr_of_columns(); Matrix N=Right.multiplication(Right_Inv, m); Matrix I(nc); return I.equal(N,m); } //--------------------------------------------------------------------------- template Lineare_Transformation Transformation(const Matrix& M) { Lineare_Transformation LT(M); LT.transformation(); if (test_arithmetic_overflow==true) { bool test=LT.test_transformation(M,overflow_test_modulus); if (test==false) { errorOutput()<<"Arithmetic failure in linear transformation. Most likely overflow.\n"; throw ArithmeticException(); } } return LT; } //--------------------------------------------------------------------------- } regina-4.96/engine/enumerate/normaliz/lineare_transformation.h000644 000765 000024 00000012611 12311266525 024617 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ //--------------------------------------------------------------------------- // This class implements the elementary divisor algoritm. // An object Lineare_transformation consists of four matrices. // Given a matrix M we want to obtain matrices U and V such that // UMV=the diagonal form of M. // In this class U is called Left, M Center and V Right. // The inverse of V is also computed as Right_Inv. // A Lineare_transormation should be initialized with a matrix M by the main // constructor. After using the procedure transformation the result should be // interpreted as follows: // Left=U; Center=the diagonal form of M; Right=V; // Right_Inv=the inverse of V; rk=rank of M. // We recommend using the non-member function Transformation, which also test // for possible arithmetic overflows //--------------------------------------------------------------------------- #ifndef LINEARE_TRANSFORMATION_H #define LINEARE_TRANSFORMATION_H #include #include "libnormaliz.h" #include "matrix.h" //--------------------------------------------------------------------------- namespace libnormaliz { template class Lineare_Transformation { long rk; string status; Integer index; Matrix Center; Matrix Right; Matrix Right_Inv; //--------------------------------------------------------------------------- public: //--------------------------------------------------------------------------- // Construction and destruction //--------------------------------------------------------------------------- Lineare_Transformation(); Lineare_Transformation(const Matrix& M); //main constructor //--------------------------------------------------------------------------- // Data acces //--------------------------------------------------------------------------- void read() const; // to be modified, just for tests long get_rank() const; //returns rank if status is // "initialized, after transformation" string get_status()const; //returns status, may be: // "non initialized" // "initialized, before transformation" // "initialized, after transformation" Integer get_index() const; Matrix get_center() const; //read center matrix Matrix get_right() const; //read right matrix Matrix get_right_inv() const; //read the inverse of the right matrix void set_rank(const size_t rank); void set_center(const Matrix& M); //write center matrix void set_right(const Matrix& M); //write right matrix void set_right_inv(const Matrix& M); //write the inverse of the right matrix //--------------------------------------------------------------------------- // Rows and columns exchange //--------------------------------------------------------------------------- void exchange_rows(size_t row1, size_t row2); //similar to Matrix::exchange_rows void exchange_columns(size_t col1, size_t col2); //similar to Matrix::exchange_columns //--------------------------------------------------------------------------- // Rows and columns reduction //--------------------------------------------------------------------------- void reduce_row(size_t corner); //similar to Matrix::reduce_row void reduce_column(size_t corner); //similar to Matrix::reduce_column //--------------------------------------------------------------------------- // Algorithms //--------------------------------------------------------------------------- void transformation(); //makes the main computation //no tests for errors //--------------------------------------------------------------------------- //Tests //--------------------------------------------------------------------------- /* test the main computation for arithmetic overflow * uses multiplication mod m */ bool test_transformation(const Matrix& M, const size_t& m) const; }; //class end ***************************************************************** //--------------------------------------------------------------------------- //makes the main computation, test for errors template Lineare_Transformation Transformation(const Matrix& M); } /* end namespace libnormaliz */ //--------------------------------------------------------------------------- #endif //--------------------------------------------------------------------------- regina-4.96/engine/enumerate/normaliz/list_operations.cpp000644 000765 000024 00000005354 12311266525 023631 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ //--------------------------------------------------------------------------- #include #include #include "integer.h" #include "vector_operations.h" #include "matrix.h" #include "simplex.h" #include "list_operations.h" //--------------------------------------------------------------------------- namespace libnormaliz { using namespace std; //--------------------------------------------------------------------------- template vector l_multiplication(const list< vector >& l,const vector& v){ int s=l.size(); vector p(s); typename list< vector >::const_iterator i; s=0; for (i =l.begin(); i != l.end(); ++i, ++s) { p[s]=v_scalar_product(*i,v); //maybe we loose time here? } return p; } //--------------------------------------------------------------------------- template list< vector > l_list_x_matrix(const list< vector >& l,const Matrix& M){ list< vector > result; vector p; typename list< vector >::const_iterator i; for (i =l.begin(); i != l.end(); i++) { p=M.VxM(*i); result.push_back(p); } return result; } //--------------------------------------------------------------------------- template void l_cut(list< vector >& l, int size){ typename list< vector >::iterator i; for (i =l.begin(); i != l.end(); i++) { (*i).resize(size); } } //--------------------------------------------------------------------------- template void l_cut_front(list< vector >& l, int size){ typename list< vector >::iterator i; vector tmp; for (i =l.begin(); i != l.end(); ) { tmp=v_cut_front(*i, size); i=l.erase(i); //important to decrease memory consumption l.insert(i,tmp); } } //--------------------------------------------------------------------------- } regina-4.96/engine/enumerate/normaliz/list_operations.h000644 000765 000024 00000005230 12311266525 023267 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ //--------------------------------------------------------------------------- #ifndef LIST_OPERATIONS_H #define LIST_OPERATIONS_H //--------------------------------------------------------------------------- #include #include #include "libnormaliz.h" #include "simplex.h" namespace libnormaliz { //--------------------------------------------------------------------------- // Data access //--------------------------------------------------------------------------- template ostream& operator<< (ostream& out, const list& l) { typename list< vector >::const_iterator i; for (i =l.begin(); i != l.end(); i++) { out << *i <<" "; } out << std::endl; return out; } //--------------------------------------------------------------------------- // List operations //--------------------------------------------------------------------------- template vector l_multiplication(const list< vector >& l,const vector& v); //the list shall contain only vectors of size=v.size(). Returns a vector //containing all the scalar products (we see l as as matrix and return l*v). template list< vector > l_list_x_matrix(const list< vector >& l,const Matrix& M); //the list shall contain only vectors of size=M.nr_of_rows(). Returns a list //containing the product (we see l as as matrix and return l*M). template void l_cut(list< vector >& l,int size ); //cuts all the vectors in l to a given size. template void l_cut_front(list< vector >& l,int size ); //cuts all the vectors in l to a given size, maintaining the back } //--------------------------------------------------------------------------- #endif //--------------------------------------------------------------------------- regina-4.96/engine/enumerate/normaliz/map_operations.h000644 000765 000024 00000004101 12311266525 023065 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ //--------------------------------------------------------------------------- #ifndef MAP_OPERATIONS_H #define MAP_OPERATIONS_H //--------------------------------------------------------------------------- #include #include namespace libnormaliz { using std::ostream; template ostream& operator<< (ostream& out, const map M) { typename map::const_iterator it; for (it = M.begin(); it != M.end(); ++it) { out << it->first << ": " << it-> second << " "; } out << std::endl; return out; } //--------------------------------------------------------------------------- template map count_in_map (const vector v) { map m; T size = v.size(); for (T i = 0; i < size; ++i) { m[v[i]]++; } return m; } template vector to_vector (const map M) { vector v; typename map::const_iterator it; for (it = M.begin(); it != M.end(); ++it) { for (T i = 0; i < it-> second; i++) { v.push_back(it->first); } } return v; } } //end namespace //--------------------------------------------------------------------------- #endif //--------------------------------------------------------------------------- regina-4.96/engine/enumerate/normaliz/matrix.cpp000644 000765 000024 00000106111 12311266525 021710 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ //--------------------------------------------------------------------------- #include #include #include "matrix.h" #include "vector_operations.h" #include "lineare_transformation.h" #include "normaliz_exception.h" //--------------------------------------------------------------------------- namespace libnormaliz { using namespace std; //--------------------------------------------------------------------------- //Private //--------------------------------------------------------------------------- template void Matrix::max_rank_submatrix_lex(vector& v, const size_t& rank) const{ size_t level=v.size(); if (level==rank) { return; } if (level==0) { v.push_back(0); } else{ v.push_back(v[level-1]); } for (; v[level] < nr; v[level]++) { Matrix S=submatrix(v); if (S.rank()==S.nr_of_rows()) { max_rank_submatrix_lex(v,rank); return; } } } //--------------------------------------------------------------------------- //Public //--------------------------------------------------------------------------- template Matrix::Matrix(){ nr=0; nc=0; } //--------------------------------------------------------------------------- template Matrix::Matrix(size_t dim){ assert(dim>=0); nr=dim; nc=dim; elements = vector< vector >(dim, vector(dim)); for (size_t i = 0; i < dim; i++) { elements[i][i]=1; } } //--------------------------------------------------------------------------- template Matrix::Matrix(size_t row, size_t col){ assert(row>=0); assert(col>=0); nr=row; nc=col; elements = vector< vector >(row, vector(col)); } //--------------------------------------------------------------------------- template Matrix::Matrix(size_t row, size_t col, Integer value){ assert(row>=0); assert(col>=0); nr=row; nc=col; elements = vector< vector > (row, vector(col,value)); } //--------------------------------------------------------------------------- template Matrix::Matrix(const vector< vector >& elem){ nr=elem.size(); if (nr>0) { nc=elem[0].size(); elements=elem; //check if all rows have the same length for (size_t i=1; i Matrix::Matrix(const list< vector >& elem){ nr = elem.size(); elements = vector< vector > (nr); nc = 0; size_t i=0; typename list< vector >::const_iterator it=elem.begin(); for(; it!=elem.end(); ++it, ++i) { if(i == 0) { nc = (*it).size(); } else { if ((*it).size() != nc) { throw BadInputException(); } } elements[i]=(*it); } } //--------------------------------------------------------------------------- template void Matrix::write(istream& in){ size_t i,j; for(i=0; i> elements[i][j]; } } } //--------------------------------------------------------------------------- template void Matrix::write(size_t row, const vector& data){ assert(row >= 0); assert(row < nr); assert(nc == data.size()); elements[row]=data; } //--------------------------------------------------------------------------- template void Matrix::write(size_t row, const vector& data){ assert(row >= 0); assert(row < nr); assert(nc == data.size()); for (size_t i = 0; i < nc; i++) { elements[row][i]=data[i]; } } //--------------------------------------------------------------------------- template void Matrix::write_column(size_t col, const vector& data){ assert(col >= 0); assert(col < nc); assert(nr == data.size()); for (size_t i = 0; i < nr; i++) { elements[i][col]=data[i]; } } //--------------------------------------------------------------------------- template void Matrix::write(size_t row, size_t col, Integer data){ assert(row >= 0); assert(row < nr); assert(col >= 0); assert(col < nc); elements[row][col]=data; } //--------------------------------------------------------------------------- template void Matrix::print(const string& name,const string& suffix) const{ string file_name = name+"."+suffix; const char* file = file_name.c_str(); ofstream out(file); print(out); out.close(); } //--------------------------------------------------------------------------- template void Matrix::print(ostream& out) const{ size_t i,j; out< void Matrix::pretty_print(ostream& out, bool with_row_nr) const{ size_t i,j,k; size_t max_length = maximal_decimal_length(); size_t max_index_length = decimal_length(nr); for (i = 0; i < nr; i++) { if (with_row_nr) { for (k= 0; k <= max_index_length - decimal_length(i); k++) { out<<" "; } out << i << ": "; } for (j = 0; j < nc; j++) { for (k= 0; k <= max_length - decimal_length(elements[i][j]); k++) { out<<" "; } out< void Matrix::read() const{ //to overload for files size_t i,j; for(i=0; i vector Matrix::read(size_t row) const{ assert(row >= 0); assert(row < nr); return elements[row]; } //--------------------------------------------------------------------------- template Integer Matrix::read (size_t row, size_t col) const{ assert(row >= 0); assert(row < nr); assert(col >= 0); assert(col < nc); return elements[row][col]; } //--------------------------------------------------------------------------- template size_t Matrix::nr_of_rows () const{ return nr; } //--------------------------------------------------------------------------- template size_t Matrix::nr_of_columns () const{ return nc; } //--------------------------------------------------------------------------- template void Matrix::random (int mod) { size_t i,j; int k; for (i = 0; i < nr; i++) { for (j = 0; j < nc; j++) { k = rand(); elements[i][j]=k % mod; } } } //--------------------------------------------------------------------------- template Matrix Matrix::submatrix(const vector& rows) const{ size_t size=rows.size(), j; Matrix M(size, nc); for (size_t i=0; i < size; i++) { j=rows[i]; assert(j >= 0); assert(j < nr); M.elements[i]=elements[j]; } return M; } //--------------------------------------------------------------------------- template Matrix Matrix::submatrix(const vector& rows) const{ size_t size=rows.size(), j; Matrix M(size, nc); for (size_t i=0; i < size; i++) { j=rows[i]; assert(j >= 0); assert(j < nr); M.elements[i]=elements[j]; } return M; } //--------------------------------------------------------------------------- template Matrix Matrix::submatrix(const vector& rows) const{ assert(rows.size() == nr); size_t size=0; for (size_t i = 0; i M(size, nc); size_t j = 0; for (size_t i = 0; i < nr; i++) { if (rows[i]) { M.elements[j++] = elements[i]; } } return M; } //--------------------------------------------------------------------------- template vector Matrix::diagonale() const{ assert(nr == nc); vector diag(nr); for(size_t i=0; i size_t Matrix::maximal_decimal_length() const{ size_t i,j,maxim=0; for (i = 0; i void Matrix::append(const Matrix& M) { assert (nc == M.nc); elements.reserve(nr+M.nr); for (size_t i=0; i void Matrix::append(const vector& V) { assert (nc == V.size()); elements.push_back(V); nr++; } //--------------------------------------------------------------------------- template void Matrix::cut_columns(size_t c) { assert (c >= 0); assert (c <= nc); for (size_t i=0; i Matrix Matrix::add(const Matrix& A) const{ assert (nr == A.nr); assert (nc == A.nc); Matrix B(nr,nc); size_t i,j; for(i=0; i Matrix Matrix::multiplication(const Matrix& A) const{ assert (nc == A.nr); Matrix B(nr,A.nc,0); //initialized with 0 size_t i,j,k; for(i=0; i Matrix Matrix::multiplication_cut(const Matrix& A, const size_t& c) const{ assert (nc == A.nr); assert(c<= A.nc); Matrix B(nr,c,0); //initialized with 0 size_t i,j,k; for(i=0; i Matrix Matrix::multiplication(const Matrix& A, long m) const{ assert (nc == A.nr); Matrix B(nr,A.nc,0); //initialized with 0 size_t i,j,k; for(i=0; i bool Matrix::equal(const Matrix& A) const{ if ((nr!=A.nr)||(nc!=A.nc)){ return false; } size_t i,j; for (i=0; i < nr; i++) { for (j = 0; j < nc; j++) { if (elements[i][j]!=A.elements[i][j]) { return false; } } } return true; } //--------------------------------------------------------------------------- template bool Matrix::equal(const Matrix& A, long m) const{ if ((nr!=A.nr)||(nc!=A.nc)){ return false; } size_t i,j; for (i=0; i < nr; i++) { for (j = 0; j < nc; j++) { if (((elements[i][j]-A.elements[i][j]) % m)!=0) { return false; } } } return true; } //--------------------------------------------------------------------------- template Matrix Matrix::transpose()const{ Matrix B(nc,nr); size_t i,j; for(i=0; i void Matrix::scalar_multiplication(const Integer& scalar){ size_t i,j; for(i=0; i void Matrix::scalar_division(const Integer& scalar){ size_t i,j; assert(scalar != 0); for(i=0; i void Matrix::reduction_modulo(const Integer& modulo){ size_t i,j; for(i=0; i Integer Matrix::matrix_gcd() const{ Integer g=0,h; for (size_t i = 0; i (g, h); if (g==1) return g; } return g; } //--------------------------------------------------------------------------- template vector Matrix::make_prime() { vector g(nr); for (size_t i = 0; i Matrix Matrix::multiply_rows(const vector& m) const{ //row i is multiplied by m[i] Matrix M = Matrix(nr,nc); size_t i,j; for (i = 0; i vector Matrix::MxV(const vector& v) const{ assert (nc == v.size()); vector w(nr); for(size_t i=0; i vector Matrix::VxM(const vector& v) const{ assert (nr == v.size()); vector w(nc,0); size_t i,j; for (i=0; i void Matrix::exchange_rows(const size_t& row1, const size_t& row2){ if (row1 == row2) return; assert(row1 >= 0); assert(row1 < nr); assert(row2 >= 0); assert(row2 < nr); elements[row1].swap(elements[row2]); } //--------------------------------------------------------------------------- template void Matrix::exchange_columns(const size_t& col1, const size_t& col2){ if (col1 == col2) return; assert(col1 >= 0); assert(col1 < nc); assert(col2 >= 0); assert(col2 < nc); for(size_t i=0; i void Matrix::reduce_row (size_t corner) { assert(corner >= 0); assert(corner < nc); assert(corner < nr); size_t i,j; Integer help; for (i = corner+1; i < nr; i++) { if (elements[i][corner]!=0) { help=elements[i][corner] / elements[corner][corner]; for (j = corner; j < nc; j++) { elements[i][j] -= help*elements[corner][j]; } } } } //--------------------------------------------------------------------------- template void Matrix::reduce_row (size_t corner, Matrix& Left) { assert(corner >= 0); assert(corner < nc); assert(corner < nr); assert(Left.nr == nr); size_t i,j; Integer help1, help2=elements[corner][corner]; for ( i = corner+1; i < nr; i++) { help1=elements[i][corner] / help2; if (help1!=0) { for (j = corner; j < nc; j++) { elements[i][j] -= help1*elements[corner][j]; } for (j = 0; j < Left.nc; j++) { Left.elements[i][j] -= help1*Left.elements[corner][j]; } } } } //--------------------------------------------------------------------------- template void Matrix::reduce_column (size_t corner) { assert(corner >= 0); assert(corner < nc); assert(corner < nr); size_t i,j; Integer help1, help2=elements[corner][corner]; for ( j = corner+1; j < nc; j++) { help1=elements[corner][j] / help2; if (help1!=0) { for (i = corner; i < nr; i++) { elements[i][j] -= help1*elements[i][corner]; } } } } //--------------------------------------------------------------------------- template void Matrix::reduce_column (size_t corner, Matrix& Right, Matrix& Right_Inv) { assert(corner >= 0); assert(corner < nc); assert(corner < nr); assert(Right.nr == nc); assert(Right.nc == nc); assert(Right_Inv.nr == nc); assert(Right_Inv.nc ==nc); size_t i,j; Integer help1, help2=elements[corner][corner]; for ( j = corner+1; j < nc; j++) { help1=elements[corner][j] / help2; if (help1!=0) { for (i = corner; i < nr; i++) { elements[i][j] -= help1*elements[i][corner]; } for (i = 0; i < nc; i++) { Right.elements[i][j] -= help1*Right.elements[i][corner]; Right_Inv.elements[corner][i] += help1*Right_Inv.elements[j][i]; } } } } //--------------------------------------------------------------------------- template vector Matrix::pivot(size_t corner){ assert(corner >= 0); assert(corner < nc); assert(corner < nr); size_t i,j; Integer help=0; vector v(2,-1); for (i = corner; i < nr; i++) { for (j = corner; j < nc; j++) { if (elements[i][j]!=0) { if ((help==0)||(Iabs(elements[i][j]) long Matrix::pivot_column(size_t col){ assert(col >= 0); assert(col < nc); assert(col < nr); size_t i,j=-1; Integer help=0; for (i = col; i < nr; i++) { if (elements[i][col]!=0) { if ((help==0)||(Iabs(elements[i][col]) size_t Matrix::diagonalize(){ long rk; long rk_max=min(nr,nc); vector piv(2,-1); for (rk = 0; rk < rk_max; rk++) { piv=pivot(rk); if (piv[0]>=0) { do { exchange_rows (rk,piv[0]); exchange_columns (rk,piv[1]); reduce_row (rk); reduce_column (rk); piv=pivot(rk); } while ((piv[0]>rk)||(piv[1]>rk)); } else break; } return rk; } //--------------------------------------------------------------------------- template size_t Matrix::rank() const{ Matrix N(*this); return N.rank_destructive(); } //--------------------------------------------------------------------------- template size_t Matrix::rank_destructive(){ size_t rk,i,j,Min_Row, rk_max=min(nr,nc); bool empty; Integer Test, Min; for (rk = 0; rk < rk_max; rk++) { for (i = rk; i < nr; i++) { //TODO exchange i,j loops? for (j = rk; j < nc; j++) if (elements[i][j]!=0) break; if (j < nc) break; } if (i >= nr) break; //no element != 0 left if (rk!=i) exchange_rows (rk,i); if (rk!=j) exchange_columns (rk,j); do { Min=Iabs(elements[rk][rk]); Min_Row=rk; empty=true; for (i = rk+1; i < nr; i++) { Test=Iabs(elements[i][rk]); empty = empty && (Test==0); if (Test!=0 && (Test Integer Matrix::vol_destructive(){ size_t rk,i,j,Min_Row, rk_max=nr; // we assume nr==nc bool empty; Integer Test, Min; for (rk = 0; rk < rk_max; rk++) { for (i = rk; i < nr; i++) { for (j = rk; j < nc; j++) if (elements[i][j]!=0) break; if (j=nr) break; if (rk!=i) exchange_rows (rk,i); if (rk!=j) exchange_columns (rk,j); do { Min=Iabs(elements[rk][rk]); Min_Row=rk; empty=true; for (i = rk+1; i < nr; i++) { Test=Iabs(elements[i][rk]); empty=empty && (Test==0); if (Test!=0&& (Test vector Matrix::max_rank_submatrix() const{ //may be optimized in two ways //first only a triangular matrix is realy needed, no full diagonalization is necesary //second the matrix Rows_Exchanges may be computed by Lineare_transformation::transformation size_t i,j,k; long rk, rk_max=min(nr,nc); vector piv(2); Matrix M(*this); Matrix Rows_Exchanges(nr); for (rk = 0; rk < rk_max; rk++) { piv=M.pivot(rk); if (piv[0]>=0) { do { M.exchange_rows (rk,piv[0]); Rows_Exchanges.exchange_columns(rk,piv[0]); M.exchange_columns (rk,piv[1]); M.reduce_row (rk); M.reduce_column (rk); //optimization posible here piv=M.pivot(rk); } while ((piv[0]>rk)||(piv[1]>rk)); } else break; } M=Rows_Exchanges.multiplication(M); vector simplex(rk); k=0; for (i = 0; i < nr; i++) { for (j = 0; j < nc; j++) { if (M.elements[i][j]!=0) { simplex[k]=i; k++; //TODO break } } } return simplex; } //--------------------------------------------------------------------------- template vector Matrix::max_rank_submatrix_lex() const{ size_t rk=rank(); vector v(0); max_rank_submatrix_lex(v,rk); return v; } //--------------------------------------------------------------------------- template vector Matrix::max_rank_submatrix_lex(const size_t& rank) const { vector v(0); max_rank_submatrix_lex(v,rank); return v; } //--------------------------------------------------------------------------- template void Matrix::solve_destructive_Sol_inner(Matrix& Right_side, vector< Integer >& diagonal, Integer& denom, Matrix& Solution) { size_t dim=Right_side.nr; size_t nr_sys=Right_side.nc; // cout << endl << "Sol.nc " << Solution.nc << " Sol.nr " << Solution.nr << " " << nr_sys << endl; assert(nr == nc); assert(nc == dim); assert(dim == diagonal.size()); assert(Solution.nc>=nr_sys); assert(Solution.nr==dim); Integer S; size_t i; long rk, piv; for (rk = 0; rk < (long)dim; rk++) { piv=(*this).pivot_column(rk); if (piv>=0) { do { (*this).exchange_rows (rk,piv); Right_side.exchange_rows (rk,piv); (*this).reduce_row(rk, Right_side); piv=(*this).pivot_column(rk); } while (piv>rk); } } denom = 1; for (i = 0; i < dim; i++) { denom *= (*this).elements[i][i]; diagonal[i] = (*this).elements[i][i]; } if (denom==0) { throw BadInputException(); //TODO welche Exception? } denom=Iabs(denom); long j; size_t k; for (i = 0; i < nr_sys; i++) { for (j = dim-1; j >= 0; j--) { S=denom*Right_side.elements[j][i]; for (k = j+1; k < dim; k++) { S-=(*this).elements[j][k]*Solution.elements[k][i]; } Solution.elements[j][i]=S/(*this).elements[j][j]; } } } //--------------------------------------------------------------------------- template void Matrix::solve_destructive_Sol(Matrix& Right_side, vector< Integer >& diagonal, Integer& denom, Matrix& Solution) { if(!test_arithmetic_overflow){ solve_destructive_Sol_inner(Right_side,diagonal,denom,Solution); return; } // now with test_arithmetic_overflow Matrix LS_Copy=*this; Matrix RS_x_denom=Right_side; solve_destructive_Sol_inner(Right_side,diagonal,denom,Solution); RS_x_denom.scalar_multiplication(denom); // cout << endl; // cout << RS_x_denom.nr << " " << RS_x_denom.nc << endl; // RS_x_denom.pretty_print(cout); // cout << endl; Matrix RS_test=LS_Copy.multiplication_cut(Solution,RS_x_denom.nc); // cout << RS_test.nr << " " << RS_test.nc << endl; // RS_test.pretty_print(cout); if (!RS_x_denom.equal(RS_test)) { errorOutput()<<"Arithmetic failure in solving a linear system. Most likely overflow.\n"; throw ArithmeticException(); } } //--------------------------------------------------------------------------- template Matrix Matrix::solve_destructive(Matrix& Right_side, vector< Integer >& diagonal, Integer& denom) { Matrix Solution(Right_side.nr,Right_side.nc); solve_destructive_Sol(Right_side,diagonal,denom,Solution); return Solution; } //--------------------------------------------------------------------------- template Matrix Matrix::solve(Matrix Right_side, Integer& denom) const { Matrix Left_side(*this); vector dummy_diag(nr); return Left_side.solve_destructive(Right_side, dummy_diag, denom); } //--------------------------------------------------------------------------- template Matrix Matrix::solve(Matrix Right_side, vector< Integer >& diagonal, Integer& denom) const { Matrix Left_side(*this); return Left_side.solve_destructive(Right_side, diagonal, denom); } //--------------------------------------------------------------------------- template Matrix Matrix::invert(vector< Integer >& diagonal, Integer& denom) const{ assert(nr == nc); assert(nr == diagonal.size()); Matrix Left_side(*this); Matrix Right_side(nr); return Left_side.solve_destructive(Right_side,diagonal,denom); } //--------------------------------------------------------------------------- template vector Matrix::solve(vector v) const { if (nc == 0 || nr == 0) { //return zero-vector as solution return vector(nc,0); } size_t i; Integer denom; vector rows=max_rank_submatrix_lex(); Matrix Left_Side=submatrix(rows); assert(nc == Left_Side.nr); //otherwise input hadn't full rank //TODO Matrix Right_Side(v.size(),1); Right_Side.write_column(0,v); Right_Side = Right_Side.submatrix(rows); Matrix Solution=Left_Side.solve(Right_Side, denom); vector Linear_Form(nc); for (i = 0; i test = MxV(Linear_Form); denom = test[0]/v[0]; //cout << denom << " v= " << v; //cout << denom << " t= " << test; for (i = 0; i (); } } return Linear_Form; } template vector Matrix::find_linear_form() const { return solve(vector(nr,1)); } //--------------------------------------------------------------------------- template vector Matrix::find_linear_form_low_dim () const{ size_t rank=(*this).rank(); if (rank == 0) { //return zero-vector as linear form return vector(nc,0); } if (rank == nc) { // basis change not necessary return (*this).find_linear_form(); } // prepare basis change vector key = max_rank_submatrix_lex(rank); Matrix Full_Rank_Matrix = submatrix(key); // has maximal number of linear independent lines Lineare_Transformation Basis_Change = Transformation(Full_Rank_Matrix); rank=Basis_Change.get_rank(); Matrix V=Basis_Change.get_right(); Matrix Change_To_Full_Emb(nc,rank); size_t i,j; for (i = 0; i Full_Cone_Generators = Full_Rank_Matrix.multiplication(Change_To_Full_Emb); //compute linear form vector Linear_Form = Full_Cone_Generators.find_linear_form(); if (Linear_Form.size()==nc) { //lift linear form back Change_To_Full_Emb = Change_To_Full_Emb.transpose(); // preparing the matrix for transformation on the dual space vector v; Linear_Form = Change_To_Full_Emb.VxM(Linear_Form); v_make_prime(Linear_Form); } return Linear_Form; } //--------------------------------------------------------------------------- template Matrix solve(const Matrix& Left_side, const Matrix& Right_side,Integer& denom){ return Left_side.solve(Right_side,denom); } //--------------------------------------------------------------------------- template Matrix invert(const Matrix& Left_side, vector< Integer >& diagonal, Integer& denom){ return Left_side.invert(diagonal,denom); } //--------------------------------------------------------------------------- } // namespace regina-4.96/engine/enumerate/normaliz/matrix.h000644 000765 000024 00000027765 12311266525 021376 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ //--------------------------------------------------------------------------- #ifndef MATRIX_HPP #define MATRIX_HPP //--------------------------------------------------------------------------- #include #include #include #include #include "libnormaliz.h" //--------------------------------------------------------------------------- namespace libnormaliz { using std::list; using std::vector; using std::string; template class Matrix { size_t nr; size_t nc; vector< vector > elements; //--------------------------------------------------------------------------- // Private routines, used in the public routines //--------------------------------------------------------------------------- void max_rank_submatrix_lex(vector& v, const size_t& rank) const; //v will be a vector with entries the indices of the first rows in lexicographic //order of this forming a submatrix of maximal rank. //v shoud be a vector of size 0 by call!!! // Does the computation for the solution of linear systems void solve_destructive_Sol_inner(Matrix& Right_side, vector< Integer >& diagonal, Integer& denom, Matrix& Solution); //--------------------------------------------------------------------------- public: //--------------------------------------------------------------------------- // Construction and destruction //--------------------------------------------------------------------------- Matrix(); Matrix(size_t dim); //constructor of identity matrix Matrix(size_t row, size_t col); //main constructor, all entries 0 Matrix(size_t row, size_t col, Integer value); //constructor, all entries set to value Matrix(const vector< vector >& elem); //constuctor, elements=elem Matrix(const list< vector >& elems); //--------------------------------------------------------------------------- // Data access //--------------------------------------------------------------------------- void write(std::istream& in = std::cin); // to be modified, just for tests void write(size_t row, const vector& data); //write a row void write(size_t row, const vector& data); //write a row void write_column(size_t col, const vector& data); //write a column void write(size_t row, size_t col, Integer data); // write data at (row,col) void print(const string& name, const string& suffix) const; // writes matrix into name.suffix void print(std::ostream& out) const; // writes matrix to the stream void pretty_print(std::ostream& out, bool with_row_nr=false) const; // writes matrix in a nice format to the stream void read() const; // to be modified, just for tests vector read(size_t row) const; // read a row Integer read (size_t row, size_t col) const; // read data at (row,col) size_t nr_of_rows() const; // returns nr size_t nr_of_columns() const; // returns nc /* generates a pseudo random matrix for tests, entries form 0 to mod-1 */ void random(int mod=3); /* returns a submatrix with rows corresponding to indices given by * the entries of rows, Numbering from 0 to n-1 ! */ Matrix submatrix(const vector& rows) const; Matrix submatrix(const vector& rows) const; Matrix submatrix(const vector& rows) const; vector diagonale() const; //returns the diagonale of this //this should be a quadratic matrix size_t maximal_decimal_length() const; //return the maximal number of decimals //needed to write an entry void append(const Matrix& M); // appends the rows of M to this void append(const vector& v); // append the row v to this void cut_columns(size_t c); // remove columns, only the first c columns will survive inline const Integer& get_elem(size_t row, size_t col) const { return elements[row][col]; } inline const vector< vector >& get_elements() const { return elements; } inline vector const& operator[] (size_t row) const { return elements[row]; } inline vector& operator[] (size_t row) { return elements[row]; } //--------------------------------------------------------------------------- // Basic matrices operations //--------------------------------------------------------------------------- Matrix add(const Matrix& A) const; // returns this+A Matrix multiplication(const Matrix& A) const; // returns this*A Matrix multiplication(const Matrix& A, long m) const;// returns this*A (mod m) Matrix multiplication_cut(const Matrix& A, const size_t& c) const; // returns // this*(first c columns of A) bool equal(const Matrix& A) const; // returns this==A bool equal(const Matrix& A, long m) const; // returns this==A (mod m) Matrix transpose() const; // returns the transpose of this //--------------------------------------------------------------------------- // Scalar operations //--------------------------------------------------------------------------- void scalar_multiplication(const Integer& scalar); //this=this*scalar void scalar_division(const Integer& scalar); //this=this div scalar, all the elements of this must be divisible with the scalar void reduction_modulo(const Integer& modulo); //this=this mod scalar Integer matrix_gcd() const; //returns the gcd of all elements vector make_prime(); //each row of this is reduced by its gcd //return a vector containing the gcd of the rows Matrix multiply_rows(const vector& m) const; //returns matrix were row i is multiplied by m[i] //--------------------------------------------------------------------------- // Vector operations //--------------------------------------------------------------------------- vector MxV(const vector& v) const;//returns this*V vector VxM(const vector& v) const;//returns V*this //--------------------------------------------------------------------------- // Rows and columns exchange //--------------------------------------------------------------------------- void exchange_rows(const size_t& row1, const size_t& row2); //row1 is exchanged with row2 void exchange_columns(const size_t& col1, const size_t& col2); // col1 is exchanged with col2 //--------------------------------------------------------------------------- // Rows and columns reduction in respect to // the right-lower submatrix of this described by an int corner //--------------------------------------------------------------------------- void reduce_row(size_t corner); //reduction by the corner-th row void reduce_row(size_t corner, Matrix& Left);//row reduction, Left used //for saving or copying the linear transformations void reduce_column(size_t corner); //reduction by the corner-th column void reduce_column(size_t corner, Matrix& Right, Matrix& Right_Inv); //column reduction, Right used for saving or copying the linear //transformations, Right_Inv used for saving the inverse linear transformations //--------------------------------------------------------------------------- // Pivots for rows/columns operations //--------------------------------------------------------------------------- vector pivot(size_t corner); //Find the position of an element x with //0 max_rank_submatrix() const; //returns a vector with entries the //indices of the rows of this forming a submatrix of maximal rank vector max_rank_submatrix_lex() const; //returns a vector with entries //the indices of the first rows in lexicographic order of this forming //a submatrix of maximal rank. vector max_rank_submatrix_lex(const size_t& rank) const; //returns a vector with entries the indices of the first rows in lexicographic //order of this forming a submatrix of maximal rank, assuming that //the rank of this is known. // In the following routines denom is the absolute value of the determinant of the // left side matrix ( =this). Matrix solve(Matrix Right_side, Integer& denom) const;// solves the system //this*Solution=denom*Right_side. this should be a quadratic matrix with nonzero determinant. Matrix solve(Matrix Right_side, vector< Integer >& diagonal, Integer& denom) const;// solves the system //this*Solution=denom*Right_side. this should be a quadratic /matrix with nonzero determinant. //The diagonal of this after transformation into an upper triangular matrix //is saved in diagonal // Right_side and this get destroyed! Matrix solve_destructive(Matrix& Right_side, vector< Integer >& diagonal, Integer& denom); // Returns the solution of the system in Solution (for efficiency) void solve_destructive_Sol(Matrix& Right_side, vector< Integer >& diagonal, Integer& denom, Matrix& Solution); Matrix invert(vector< Integer >& diagonal, Integer& denom) const;// solves the system //this*Solution=denom*I. this should be a quadratic matrix with nonzero determinant. //The diagonal of this after transformation into an upper triangular matrix //is saved in diagonal vector find_linear_form () const; // Tries to find a linear form which gives the same value an all rows of this // this should be a m x n matrix (m>=n) of maxinal rank // returns an empty vector if there does not exist such a linear form vector find_linear_form_low_dim () const; //same as find_linear_form but also works with not maximal rank //uses a linear transformation to get a full rank matrix vector solve(vector v) const; // like find_linear_form, but for right side v }; //class end ***************************************************************** } // namespace //--------------------------------------------------------------------------- #endif //--------------------------------------------------------------------------- regina-4.96/engine/enumerate/normaliz/my_omp.h000644 000765 000024 00000002323 12311266525 021351 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2012,2013 Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ /* * This header provide some dummy replacements of OpenMP functions. We use it * to compile Normaliz without OpenMP. */ #ifndef MY_OMP_H_ #define MY_OMP_H_ #ifdef _OPENMP #include #else inline int omp_get_level(){ return 0; } inline int omp_get_active_level() { return 0; } inline int omp_get_thread_num() { return 0; } inline int omp_get_max_threads() { return 1; } inline int omp_get_ancestor_thread_num(int level) { return 0; } #endif /* ifndef _OPENMP */ #endif /* MY_OMP_H_ */ regina-4.96/engine/enumerate/normaliz/normaliz_exception.h000644 000765 000024 00000003071 12311266525 023763 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #ifndef NORMALIZ_EXEPTION_H_ #define NORMALIZ_EXEPTION_H_ #include //#include "libnormaliz.h" namespace libnormaliz { class NormalizException: public std::exception { public: virtual const char* what() const throw() = 0; }; class ArithmeticException: public NormalizException { public: virtual const char* what() const throw() { return "Arithmetic Overflow detected, try a bigger integer type!"; } }; class BadInputException: public NormalizException { public: virtual const char* what() const throw() { return "Some error in the normaliz input data detected!"; } }; class FatalException: public NormalizException { public: virtual const char* what() const throw() { return "Fatal error! This should not happen, please contact the developers."; } }; } /* end namespace */ #endif /* LIBNORMALIZ_H_ */ regina-4.96/engine/enumerate/normaliz/README.txt000644 000765 000024 00000001033 12311266525 021373 0ustar00babstaff000000 000000 Normaliz Library ---------------- This directory contains a copy of the Normaliz kernel libnormaliz. This is currently synced with Normaliz version 2.10.1. Normaliz is distributed under the terms of the GNU General Public License, version 3. The full text of this license is included in the file COPYING in this directory. Normaliz was written by Winfried Bruns (wbruns@uos.de), Bogdan Ichim (bogdan_ichim@yahoo.com) and Christof Söger (csoeger@uos.de), and can be downloaded from http://www.mathematik.uni-osnabrueck.de/normaliz/ . regina-4.96/engine/enumerate/normaliz/regina.patch000644 000765 000024 00000001145 12311266525 022167 0ustar00babstaff000000 000000 --- general.h (revision 7811) +++ general.h (working copy) @@ -21,11 +21,15 @@ #include +#include #include +/* +// Regina will use GMP everywhere, even on Windows. #ifdef _WIN32 //for 32 and 64 bit windows #define NMZ_MPIR //always use MPIR #endif +*/ #ifdef NMZ_MPIR // use MPIR #include --- list_operations.h +++ list_operations.h @@ -41,7 +41,7 @@ ostream& operator<< (ostream& out, const list& l) { for (i =l.begin(); i != l.end(); i++) { out << *i <<" "; } - out << endl; + out << std::endl; return out; } regina-4.96/engine/enumerate/normaliz/simplex.cpp000644 000765 000024 00000046075 12311266525 022101 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ //--------------------------------------------------------------------------- #include #include #include #include #include "integer.h" #include "vector_operations.h" #include "matrix.h" #include "simplex.h" #include "list_operations.h" #include "HilbertSeries.h" #include "cone.h" //--------------------------------------------------------------------------- namespace libnormaliz { using namespace std; //--------------------------------------------------------------------------- template Simplex::Simplex(const Matrix& Map){ dim=Map.nr_of_columns(); key=Map.max_rank_submatrix_lex(dim); Generators=Map.submatrix(key); diagonal = vector< Integer >(dim); Support_Hyperplanes=invert(Generators, diagonal, volume); //test for arithmetic //overflow performed v_abs(diagonal); Support_Hyperplanes = Support_Hyperplanes.transpose(); multiplicators = Support_Hyperplanes.make_prime(); } //--------------------------------------------------------------------------- template Simplex::Simplex(const vector& k, const Matrix& Map){ key=k; Generators=Map.submatrix(k); dim=k.size(); diagonal = vector< Integer >(dim); Support_Hyperplanes=invert(Generators, diagonal, volume); //test for arithmetic //overflow performed v_abs(diagonal); Support_Hyperplanes=Support_Hyperplanes.transpose(); multiplicators=Support_Hyperplanes.make_prime(); } //--------------------------------------------------------------------------- template size_t Simplex::read_dimension() const{ return dim; } //--------------------------------------------------------------------------- template void Simplex::write_volume(const Integer& vol){ volume=vol; } //--------------------------------------------------------------------------- template Integer Simplex::read_volume() const{ return volume; } //--------------------------------------------------------------------------- template vector Simplex::read_key() const{ return key; } //--------------------------------------------------------------------------- template Matrix Simplex::read_generators() const{ return Generators; } //--------------------------------------------------------------------------- template vector Simplex::read_diagonal() const{ return diagonal; } //--------------------------------------------------------------------------- template vector Simplex::read_multiplicators() const{ return multiplicators; } //--------------------------------------------------------------------------- template Matrix Simplex::read_support_hyperplanes() const{ return Support_Hyperplanes; } //--------------------------------------------------------------------------- // SimplexEvaluator //--------------------------------------------------------------------------- template SimplexEvaluator::SimplexEvaluator(Full_Cone& fc) : C_ptr(&fc), dim(fc.dim), det_sum(0), mult_sum(0), collected_elements_size(0), Generators(dim,dim), TGenerators(dim,dim), GenCopy(dim,dim), InvGenSelRows(dim,dim), InvGenSelCols(dim,dim), Sol(dim,dim+1), InvSol(dim,dim+1), GDiag(dim), TDiag(dim), Excluded(dim), Indicator(dim), gen_degrees(dim), RS(dim,1) { if (C_ptr->do_h_vector) { // we need the generators to be sorted by degree size_t hv_max=0; for (size_t i=C_ptr->nr_gen-dim; inr_gen; i++) hv_max += C_ptr->gen_degrees[i]; hvector.resize(hv_max); } } //--------------------------------------------------------------------------- size_t Unimod=0, Ht1NonUni=0, Gcd1NonUni=0, NonDecided=0, NonDecidedHyp=0; size_t TotDet=0; /* evaluates a simplex in regard to all data */ template Integer SimplexEvaluator::evaluate(SHORTSIMPLEX& s) { Integer& volume = s.vol; vector& key = s.key; Full_Cone& C = *C_ptr; bool do_only_multiplicity = C.do_only_multiplicity; // || (s.height==1 && C.do_partial_triangulation); size_t i,j; //degrees of the generators according to the Grading of C if(C.isComputed(ConeProperty::Grading)) for (i=0; i Ind0_key; //contains the indices i as above Ind0_key.reserve(dim-1); if(potentially_unimodular) for(i=0;i0){ for(i=0; i0){ Matrix RSmult(dim,Ind0_key.size()); for(i=0;i RSmult(dim,Ind0_key.size()); Generators.solve_destructive_Sol(RSmult,GDiag,volume,InvSol); v_abs(GDiag); GDiag_computed=true; } } addMult(volume); // now we must compute the matrix InvGenSelRows (selected rows of InvGen) // for those i for which Gdiag[i]>1 combined with computation // of Indicator in case of potentially_unimodular==false (uses transpose of Gen) vector Last_key; Last_key.reserve(dim); if (!unimodular) { for(i=0; i1) Last_key.push_back(i); } size_t RScol; if(potentially_unimodular) RScol=Last_key.size(); else RScol=Last_key.size()+1; Matrix RSmult(dim,RScol); for(i=0;i0 (if there are any) if(!potentially_unimodular){ for(i=0;i0){ Generators=GenCopy; Matrix RSmult(dim,Ind0_key.size()); for(i=0;i0){ #pragma omp atomic NonDecided++; #pragma omp atomic NonDecidedHyp+=Ind0_key.size(); } for(i=0;i0) // facet included break; } } } if(C.do_h_vector) { // count the 0-vector in h-vector with the right shift hvector[Deg]++; } Matrix* StanleyMat=&GenCopy; //just to initialize it and make GCC happy if(C.do_Stanley_dec){ STANLEYDATA SimplStanley; SimplStanley.key=key; Matrix offsets(explicit_cast_to_long(volume),dim); SimplStanley.offsets=offsets; #pragma omp critical(STANLEY) { C.StanleyDec.push_back(SimplStanley); StanleyMat= &C.StanleyDec.back().offsets; } for(i=0;i > Candidates; typename list >::iterator c; size_t last; vector point(dim,0); Matrix elements(dim,dim); //all 0 matrix vector help; //now we need to create the candidates while (true) { last = dim; for (int k = dim-1; k >= 0; k--) { if (point[k] < GDiag[k]-1) { last = k; break; } } if (last >= dim) { break; } point[last]++; v_add_to_mod(elements[last], InvGenSelRows[last], volume); for (i = last+1; i (normG/volume); for(i=0;i=2 // if (!C.do_partial_triangulation || s.height >= 2) { if (C.do_Hilbert_basis) { Candidates.push_back(v_merge(elements[last],norm)); continue; } if(C.do_deg1_elements && normG==volume && !isDuplicate(elements[last])) { help=GenCopy.VxM(elements[last]); v_scalar_division(help,volume); Collected_Elements.push_back(help); collected_elements_size++; } // } } if(C.do_h_vector) { // #pragma omp critical(HSERIES) Hilbert_Series.add(hvector,gen_degrees); } if(!C.do_Hilbert_basis) return volume; // no local reduction in this case Candidates.sort(compare_last); typename list >::iterator cand=Candidates.begin(); while(cand != Candidates.end()) { if (is_reducible_interior(*cand)) // erase the candidate cand = Candidates.erase(cand); else // move it to the Hilbert basis Hilbert_Basis.splice(Hilbert_Basis.end(), Candidates, cand++); } //inverse transformation //some test for arithmetic overflow may be implemented here typename list< vector >::iterator jj = Hilbert_Basis.begin(); while (jj != Hilbert_Basis.end()) { if (isDuplicate(*jj)) { //delete the element jj = Hilbert_Basis.erase(jj); } else { jj->pop_back(); //remove the norm entry at the end *jj = GenCopy.VxM(*jj); v_scalar_division(*jj,volume); ++jj; collected_elements_size++; } } Collected_Elements.splice(Collected_Elements.end(),Hilbert_Basis); return volume; } //--------------------------------------------------------------------------- template bool SimplexEvaluator::isDuplicate(const vector& cand) const { for (size_t i=0; i void SimplexEvaluator::addMult(const Integer& volume) { if (volume==0) throw volume; det_sum += volume; if (!C_ptr->isComputed(ConeProperty::Grading)) return; if (C_ptr->deg1_triangulation) { mult_sum += to_mpz(volume); } else { mpz_class deg_prod=gen_degrees[0]; for (size_t i=1; i bool SimplexEvaluator::is_reducible_interior(const vector< Integer >& new_element){ // the norm is at position dim if (new_element[dim]==0) { return true; // new_element=0 } else { size_t i,c=0; typename list< vector >::iterator j; for (j =Hilbert_Basis.begin(); j != Hilbert_Basis.end(); ++j) { if (new_element[dim]<2*(*j)[dim]) { break; //new_element is not reducible; } else { if ((*j)[c]<=new_element[c]){ for (i = 0; i < dim; i++) { if ((*j)[i]>new_element[i]){ c=i; break; } } if (i==dim) { // move the reducer to the begin Hilbert_Basis.splice(Hilbert_Basis.begin(), Hilbert_Basis, j); return true; } //new_element is not in the Hilbert Basis } } } return false; } } //--------------------------------------------------------------------------- template void SimplexEvaluator::transfer_candidates() { if ( (C_ptr->do_deg1_elements || C_ptr->do_Hilbert_basis) && collected_elements_size > 0 ) { #pragma omp critical(CANDIDATES) C_ptr->Candidates.splice(C_ptr->Candidates.begin(),Collected_Elements); #pragma omp atomic C_ptr->CandidatesSize += collected_elements_size; collected_elements_size = 0; } } template Integer SimplexEvaluator::getDetSum() const { return det_sum; } template mpq_class SimplexEvaluator::getMultiplicitySum() const { return mult_sum; } template const HilbertSeries& SimplexEvaluator::getHilbertSeriesSum() const { return Hilbert_Series; } } /* end namespace */ regina-4.96/engine/enumerate/normaliz/simplex.h000644 000765 000024 00000012342 12311266525 021534 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ //--------------------------------------------------------------------------- // The matrix Map is assumed to be such that the rank of Map equals // the number of columns of Map and no test is performed in the constructor //--------------------------------------------------------------------------- #ifndef SIMPLEX_H #define SIMPLEX_H //--------------------------------------------------------------------------- #include #include #include "libnormaliz.h" #include "cone.h" #include "HilbertSeries.h" //--------------------------------------------------------------------------- namespace libnormaliz { using std::list; using std::vector; template class Full_Cone; template class Simplex { size_t dim; Integer volume; vector key; Matrix Generators; vector< Integer > diagonal; vector< Integer > multiplicators; Matrix Support_Hyperplanes; //--------------------------------------------------------------------------- public: // Construction and destruction Simplex(const Matrix& Map); //contructor of the first in lexicographic //order simplex inside Map, the rank of Map is assumed to equal the number of //columns of Map Simplex(const vector& k, const Matrix& Map); //main constuctor //the rank of M is assumed to equal the number of columns of M // Data acces size_t read_dimension() const; // returns dim void write_volume(const Integer& vol); // writes volume Integer read_volume() const; // returns volume vector read_key() const; // returns key Matrix read_generators() const; // returns generators vector read_diagonal() const; // returns diagonal vector read_multiplicators() const; // returns multiplicators Matrix read_support_hyperplanes() const; // returns the support hyperplanes }; //class Simplex end template class SimplexEvaluator { Full_Cone * C_ptr; size_t dim; //Integer volume; Integer det_sum; // sum of the determinants of all evaluated simplices mpq_class mult_sum; // sum of the multiplicities of all evaluated simplices size_t collected_elements_size; Matrix Generators; Matrix TGenerators; Matrix GenCopy; Matrix InvGenSelRows; // selected rows of inverse of Gen Matrix InvGenSelCols; // selected columns of inverse of Gen Matrix Sol; Matrix InvSol; vector< Integer > GDiag; // diagonal of generator matrix after trigonalization vector< Integer > TDiag; // diagonal of transpose of generaor matrix after trigonalization vector< bool > Excluded; vector< Integer > Indicator; vector< long > gen_degrees; vector< num_t > hvector; //h-vector of the current evaluation HilbertSeries Hilbert_Series; //this is the summed Hilbert Series list< vector > Candidates; list< vector > Hilbert_Basis; list< vector > Collected_Elements; //temporary objects are kept to prevent repeated alloc and dealloc Matrix RS; // right hand side to hold order vector // Matrix RSmult; // for multiple right hand sides //checks whether a new element is reducible by the local Hilbert basis bool is_reducible_interior(const vector< Integer >& new_element); bool isDuplicate(const vector& cand) const; void addMult(const Integer& volume); //--------------------------------------------------------------------------- public: SimplexEvaluator(Full_Cone& fc); // full evaluation of the simplex, writes data back to the cone, // returns volume Integer evaluate(SHORTSIMPLEX& s); // moves the union of Hilbert basis / deg1 elements to the cone // for partial triangulation it merges the sorted list void transfer_candidates(); // returns sum of the determinants of all evaluated simplices Integer getDetSum() const; // returns sum of the multiplicities of all evaluated simplices mpq_class getMultiplicitySum() const; // returns sum of the Hilbert Series of all evaluated simplices const HilbertSeries& getHilbertSeriesSum() const; }; //class SimplexEvaluater end } //--------------------------------------------------------------------------- #endif //--------------------------------------------------------------------------- regina-4.96/engine/enumerate/normaliz/sublattice_representation.cpp000644 000765 000024 00000022616 12311266525 025674 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ /** * The class Sublattice_Representation represents a sublattice of Z^n as Z^r. * To transform vectors of the sublattice use: * Z^r --> Z^n and Z^n --> Z^r * v |-> vA u |-> (uB)/c * A r x n matrix * B n x r matrix * c Integer */ #include "sublattice_representation.h" #include "lineare_transformation.h" #include "vector_operations.h" //--------------------------------------------------------------------------- namespace libnormaliz { using namespace std; /** * creates a representation of Z^n as a sublattice of itself */ template Sublattice_Representation::Sublattice_Representation(size_t n) { dim = n; rank = n; index = 1; A = Matrix(n); B = Matrix(n); c = 1; } //--------------------------------------------------------------------------- /** * Main Constructor * creates a representation of a sublattice of Z^n * if direct_summand is false the sublattice is generated by the rows of M * otherwise it is a direct summand of Z^n containing the rows of M */ template Sublattice_Representation::Sublattice_Representation(const Matrix& M, bool direct_summand) { Lineare_Transformation Basis_Change = Transformation(M); initialize(Basis_Change, direct_summand); } template Sublattice_Representation::Sublattice_Representation(const Lineare_Transformation& Basis_Change, bool direct_summand) { initialize(Basis_Change, direct_summand); } template void Sublattice_Representation::initialize(const Lineare_Transformation& Basis_Change, bool direct_summand) { size_t i,j; rank = Basis_Change.get_rank(); if (rank==0) { errorOutput()<<"warning: matrix has rank 0. Please check input data."< R = Basis_Change.get_right_inv(); Matrix R_Inv = Basis_Change.get_right(); dim = R.nr_of_columns(); c = 1; index = 1; Matrix D = Basis_Change.get_center(); //use the identity matrix when possible bool is_identity = (dim==rank); if (is_identity && !direct_summand) { for (i = 0; i < rank; i++) { if (Iabs(D.read(i,i)) != 1) { is_identity = false; break; } } } if (is_identity) { A = B = Matrix(dim); } else { A = Matrix(rank, dim); B = Matrix(dim, rank); for (i = 0; i < rank; i++) { for (j = 0; j < dim; j++) { A.write(i,j, R.read(i,j)); B.write(j,i, R_Inv.read(j,i)); } } } if ( direct_summand ) { for (i = 0; i < rank; i++) { index *= D.read(i,i); } index = Iabs(index); } else if(!is_identity) { Matrix Diagonal(rank); for (i = 0; i < rank; i++) { Diagonal.write(i,i,D.read(i,i)); } A = Diagonal.multiplication(A); vector c_vector = Diagonal.diagonale(); c = v_lcm(c_vector); //invert Diagonal, multiply c to maintain integer coefficients for (i = 0; i < rank; i++) { Diagonal.write(i,i,c/c_vector[i]); } B = B.multiplication(Diagonal); } } //--------------------------------------------------------------------------- // Manipulation operations //--------------------------------------------------------------------------- /* first this then SR when going from Z^n to Z^r */ template void Sublattice_Representation::compose(const Sublattice_Representation& SR) { assert(rank == SR.dim); //TODO vielleicht doch exception? rank = SR.rank; index = index * SR.index; // A = SR.A * A A = SR.A.multiplication(A); // B = B * SR.B B = B.multiplication(SR.B); c = c * SR.c; //check if a factor can be extraced from B //TODO necessary? Integer g = B.matrix_gcd(); g = gcd(g,c); //TODO necessary?? if (g > 1) { c /= g; B.scalar_division(g); } } //--------------------------------------------------------------------------- // Transformations //--------------------------------------------------------------------------- template Matrix Sublattice_Representation::to_sublattice (const Matrix& M) const { Matrix N = M.multiplication(B); if (c!=1) N.scalar_division(c); return N; } template Matrix Sublattice_Representation::from_sublattice (const Matrix& M) const { Matrix N = M.multiplication(A); return N; } template Matrix Sublattice_Representation::to_sublattice_dual (const Matrix& M) const { Matrix N = M.multiplication(A.transpose()); N.make_prime(); return N; } template Matrix Sublattice_Representation::from_sublattice_dual (const Matrix& M) const { Matrix N = M.multiplication(B.transpose()); N.make_prime(); return N; } template vector Sublattice_Representation::to_sublattice (const vector& V) const { vector N = B.VxM(V); if (c!=1) v_scalar_division(N,c); return N; } template vector Sublattice_Representation::from_sublattice (const vector& V) const { vector N = A.VxM(V); return N; } template vector Sublattice_Representation::to_sublattice_dual (const vector& V) const { vector N = A.MxV(V); v_make_prime(N); return N; } template vector Sublattice_Representation::from_sublattice_dual (const vector& V) const { vector N = B.MxV(V); v_make_prime(N); return N; } template vector Sublattice_Representation::to_sublattice_dual_no_div (const vector& V) const { vector N = A.MxV(V); return N; } //--------------------------------------------------------------------------- // Data access //--------------------------------------------------------------------------- /* returns the dimension of the ambient space */ template size_t Sublattice_Representation::get_dim() const { return dim; } //--------------------------------------------------------------------------- /* returns the rank of the sublattice */ template size_t Sublattice_Representation::get_rank() const { return rank; } //--------------------------------------------------------------------------- /* returns the index of the sublattice */ template Integer Sublattice_Representation::get_index() const { return index; } //--------------------------------------------------------------------------- template Matrix Sublattice_Representation::get_A() const { return A; } //--------------------------------------------------------------------------- template Matrix Sublattice_Representation::get_B() const { return B; } //--------------------------------------------------------------------------- template Integer Sublattice_Representation::get_c() const { return c; } //--------------------------------------------------------------------------- /* returns the congruences defining the sublattice */ template Matrix Sublattice_Representation::get_congruences() const { if ( c == 1 ) { // no congruences then return Matrix(0,dim+1); } // Cong is B transposed and with an extra column for the modul m Matrix Cong = B; Cong.append(Matrix(1,rank)); Cong = Cong.transpose(); vector gcds = Cong.make_prime(); Integer m; //the modul Integer rowgcd; Matrix Cong2(0,dim+1); //only the relavant congruences vector new_row; for (size_t j=0; j. * */ /** * The class Sublattice_Representation represents a sublattice of Z^n as Z^r. * To transform vectors of the sublattice use: * Z^r --> Z^n and Z^n --> Z^r * v |-> vA u |-> (uB)/c * A r x n matrix * B n x r matrix * c Integer */ #ifndef SUBLATTICE_REPRESENTATION_H #define SUBLATTICE_REPRESENTATION_H #include #include "libnormaliz.h" #include "matrix.h" //--------------------------------------------------------------------------- namespace libnormaliz { template class Matrix; template class Lineare_Transformation; using std::vector; template class Sublattice_Representation { size_t dim, rank; Matrix A; Matrix B; Integer c; Integer index; //--------------------------------------------------------------------------- public: //--------------------------------------------------------------------------- // Construction and destruction //--------------------------------------------------------------------------- /** * creates a dummy object */ Sublattice_Representation() {} /** * creates a representation of Z^n as a sublattice of itself */ Sublattice_Representation(size_t n); /** * Main Constructor * creates a representation of a sublattice of Z^n * if direct_summand is false the sublattice is generated by the rows of M * otherwise it is a direct summand of Z^n containing the rows of M */ Sublattice_Representation(const Matrix& M, bool direct_summand); Sublattice_Representation(const Lineare_Transformation& LT, bool direct_summand); //--------------------------------------------------------------------------- // Manipulation operations //--------------------------------------------------------------------------- /* like the matching constructor */ void initialize(const Lineare_Transformation& LT, bool direct_summand); /* first this then SR when going from Z^n to Z^r */ void compose(const Sublattice_Representation& SR); //--------------------------------------------------------------------------- // Transformations //--------------------------------------------------------------------------- Matrix to_sublattice (const Matrix& M) const; Matrix from_sublattice (const Matrix& M) const; Matrix to_sublattice_dual (const Matrix& M) const; Matrix from_sublattice_dual (const Matrix& M) const; vector to_sublattice (const vector& V) const; vector from_sublattice (const vector& V) const; vector to_sublattice_dual (const vector& M) const; vector from_sublattice_dual (const vector& V) const; vector to_sublattice_dual_no_div (const vector& M) const; //--------------------------------------------------------------------------- // Data acces //--------------------------------------------------------------------------- /* returns the dimension of the ambient space */ size_t get_dim() const; /* returns the rank of the sublattice */ size_t get_rank() const; /* returns the index of the sublattice */ Integer get_index() const; Matrix get_A() const; Matrix get_B() const; Integer get_c() const; /* returns the congruences defining the sublattice */ Matrix get_congruences() const; }; } //--------------------------------------------------------------------------- #endif //--------------------------------------------------------------------------- regina-4.96/engine/enumerate/normaliz/unused/libnormaliz-all.cpp000644 000765 000024 00000002133 12311266525 024776 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "libnormaliz.cpp" #include "integer.cpp" #include "vector_operations.cpp" #include "matrix.cpp" #include "simplex.cpp" #include "list_operations.cpp" #include "lineare_transformation.cpp" #include "sublattice_representation.cpp" #include "full_cone.cpp" #include "cone_dual_mode.cpp" #include "cone.cpp" #include "cone_property.cpp" #include "HilbertSeries.cpp" regina-4.96/engine/enumerate/normaliz/unused/libnormaliz-impl.cpp000644 000765 000024 00000004263 12311266525 025175 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "libnormaliz.cpp" namespace libnormaliz { template class Cone; template class Cone; template class Cone; template class Matrix; template class Matrix; template class Matrix; template class Sublattice_Representation; template class Sublattice_Representation; template class Sublattice_Representation; template class Lineare_Transformation; template class Lineare_Transformation; template class Lineare_Transformation; template Lineare_Transformation Transformation(const Matrix& M); template Lineare_Transformation Transformation(const Matrix& M); template Lineare_Transformation Transformation(const Matrix& M); template size_t decimal_length(long); template size_t decimal_length(long long int); template size_t decimal_length(mpz_class); template mpz_class gcd(const mpz_class& a, const mpz_class& b); template mpz_class lcm(const mpz_class& a, const mpz_class& b); template mpz_class permutations(const size_t& a, const size_t& b); template ostream& operator<< (ostream& out, const vector& v); template ostream& operator<< (ostream& out, const vector& v); template ostream& operator<< < vector >(ostream& out, const vector< vector >& v); } regina-4.96/engine/enumerate/normaliz/vector_operations.cpp000644 000765 000024 00000024200 12311266525 024147 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ //--------------------------------------------------------------------------- #include #include #include #include "integer.h" #include "vector_operations.h" //--------------------------------------------------------------------------- namespace libnormaliz { using namespace std; //--------------------------------------------------------------------------- template Integer v_scalar_product(const vector& av,const vector& bv){ //loop stretching ; brings some small speed improvement Integer ans = 0; size_t i,n=av.size(); typename vector::const_iterator a=av.begin(), b=bv.begin(); if( n >= 16 ) { for( i = 0; i < ( n >> 4 ); ++i, a += 16, b +=16 ){ ans += a[0] * b[0]; ans += a[1] * b[1]; ans += a[2] * b[2]; ans += a[3] * b[3]; ans += a[4] * b[4]; ans += a[5] * b[5]; ans += a[6] * b[6]; ans += a[7] * b[7]; ans += a[8] * b[8]; ans += a[9] * b[9]; ans += a[10] * b[10]; ans += a[11] * b[11]; ans += a[12] * b[12]; ans += a[13] * b[13]; ans += a[14] * b[14]; ans += a[15] * b[15]; } n -= i<<4; } if( n >= 8) { ans += a[0] * b[0]; ans += a[1] * b[1]; ans += a[2] * b[2]; ans += a[3] * b[3]; ans += a[4] * b[4]; ans += a[5] * b[5]; ans += a[6] * b[6]; ans += a[7] * b[7]; n -= 8; a += 8; b += 8; } if( n >= 4) { ans += a[0] * b[0]; ans += a[1] * b[1]; ans += a[2] * b[2]; ans += a[3] * b[3]; n -= 4; a += 4; b += 4; } if( n >= 2) { ans += a[0] * b[0]; ans += a[1] * b[1]; n -= 2; a += 2; b += 2; } if(n>0) ans += a[0]*b[0]; return ans; } //--------------------------------------------------------------------------- template Integer v_scalar_product_unequal_vectors_end(const vector& a,const vector& b){ Integer ans = 0; size_t i,n=a.size(),m=b.size(); for (i = 1; i <= n; i++) { ans+=a[n-i]*b[m-i]; } return ans; } //--------------------------------------------------------------------------- template vector v_add(const vector& a,const vector& b){ assert(a.size() == b.size()); size_t i,s=a.size(); vector d(s); for (i = 0; i vector& v_add_to_mod(vector& a, const vector& b, const Integer& m) { // assert(a.size() == b.size()); size_t i, s=a.size(); for (i = 0; i = m) { a[i] -= m; } } return a; } //--------------------------------------------------------------------------- template vector& v_abs(vector& v){ size_t i, size=v.size(); for (i = 0; i < size; i++) { if (v[i]<0) v[i] = Iabs(v[i]); } return v; } //--------------------------------------------------------------------------- template Integer v_gcd(const vector& v){ size_t i, size=v.size(); Integer g=0; for (i = 0; i < size; i++) { g=gcd(g,v[i]); if (g==1) { return 1; } } return g; } //--------------------------------------------------------------------------- template Integer v_lcm(const vector& v){ size_t i,size=v.size(); Integer g=1; for (i = 0; i < size; i++) { g=lcm(g,v[i]); if (g==0) { return 0; } } return g; } //--------------------------------------------------------------------------- template Integer v_make_prime(vector& v){ size_t i, size=v.size(); Integer g=v_gcd(v); if (g!=0) { for (i = 0; i < size; i++) { v[i] /= g; } } return g; } //--------------------------------------------------------------------------- template vector v_scalar_multiplication_two(const vector& v, const Integer& scalar){ size_t i,size=v.size(); vector w(size); for (i = 0; i void v_scalar_division(vector& v, const Integer& scalar){ size_t i,size=v.size(); for (i = 0; i void v_reduction_modulo(vector& v, const Integer& modulo){ size_t i,size=v.size(); for (i = 0; i bool v_test_scalar_product(const vector& av,const vector& bv, const Integer& result, const long& m){ Integer ans = 0; size_t i,n=av.size(); typename vector::const_iterator a=av.begin(),b=bv.begin(); if( n >= 16 ) { for( i = 0; i < ( n >> 4 ); ++i, a += 16, b += 16 ){ ans += a[0] * b[0]; ans += a[1] * b[1]; ans += a[2] * b[2]; ans += a[3] * b[3]; ans %= m; ans += a[4] * b[4]; ans += a[5] * b[5]; ans += a[6] * b[6]; ans += a[7] * b[7]; ans %= m; ans += a[8] * b[8]; ans += a[9] * b[9]; ans += a[10] * b[10]; ans += a[11] * b[11]; ans %= m; ans += a[12] * b[12]; ans += a[13] * b[13]; ans += a[14] * b[14]; ans += a[15] * b[15]; ans %= m; } n -= i << 4; } if( n >= 8) { ans += a[0] * b[0]; ans += a[1] * b[1]; ans += a[2] * b[2]; ans += a[3] * b[3]; ans %= m; ans += a[4] * b[4]; ans += a[5] * b[5]; ans += a[6] * b[6]; ans += a[7] * b[7]; ans %= m; n -= 8; a += 8; b += 8; } if( n >= 4) { ans += a[0] * b[0]; ans += a[1] * b[1]; ans += a[2] * b[2]; ans += a[3] * b[3]; ans %= m; n -= 4; a += 4; b += 4; } if( n >= 2) { ans += a[0] * b[0]; ans += a[1] * b[1]; n -= 2; a += 2; b += 2; } if(n>0) ans += a[0]*b[0]; ans %= m; if (((result-ans) % m)!=0) { return false; } return true; } //--------------------------------------------------------------------------- template vector v_merge(const vector& a, const T& b) { size_t s=a.size(); vector c(s+1); for (size_t i = 0; i < s; i++) { c[i]=a[i]; } c[s] = b; return c; } //--------------------------------------------------------------------------- template vector v_merge(const vector& a,const vector& b){ size_t s1=a.size(), s2=b.size(), i; vector c(s1+s2); for (i = 0; i < s1; i++) { c[i]=a[i]; } for (i = 0; i < s2; i++) { c[s1+i]=b[i]; } return c; } //--------------------------------------------------------------------------- template vector v_cut_front(const vector& v, size_t size){ size_t s,k; vector tmp(size); s=v.size()-size; for (k = 0; k < size; k++) { tmp[k]=v[s+k]; } return tmp; } //--------------------------------------------------------------------------- template vector v_non_zero_pos(vector v){ vector key; size_t size=v.size(); key.reserve(size); for (key_t i = 0; i void v_el_trans(const vector& av,vector& bv, const Integer& F, const size_t& start){ size_t i,n=av.size(); typename vector::const_iterator a=av.begin(); typename vector::iterator b=bv.begin(); a += start; b += start; n -= start; if( n >= 8 ) { for( i = 0; i < ( n >> 3 ); ++i, a += 8, b += 8 ){ b[0] += F*a[0]; b[1] += F*a[1]; b[2] += F*a[2]; b[3] += F*a[3]; b[4] += F*a[4]; b[5] += F*a[5]; b[6] += F*a[6]; b[7] += F*a[7]; } n -= i << 3; } if( n >= 4) { b[0] += F*a[0]; b[1] += F*a[1]; b[2] += F*a[2]; b[3] += F*a[3]; n -=4; a +=4; b +=4; } if( n >= 2) { b[0] += F*a[0]; b[1] += F*a[1]; n -=2; a +=2; b +=2; } if(n>0) b[0] += F*a[0]; } } // end namespace libnormaliz regina-4.96/engine/enumerate/normaliz/vector_operations.h000644 000765 000024 00000012605 12311266525 023622 0ustar00babstaff000000 000000 /* * Normaliz * Copyright (C) 2007-2013 Winfried Bruns, Bogdan Ichim, Christof Soeger * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ //--------------------------------------------------------------------------- #ifndef VECTOR_OPERATIONS_H #define VECTOR_OPERATIONS_H //--------------------------------------------------------------------------- #include #include #include "libnormaliz.h" namespace libnormaliz { using std::vector; using std::ostream; //--------------------------------------------------------------------------- // Data access //--------------------------------------------------------------------------- template ostream& operator<< (ostream& out, const vector& vec) { for (size_t i=0; i Integer v_scalar_product(const vector& a,const vector& b); //returns the scalar product of the vector a with the end of the vector b template Integer v_scalar_product_unequal_vectors_end(const vector& a,const vector& b); //returns the addition a + b, vectors must be of equal size template vector v_add(const vector& a,const vector& b); //adds b to a reduces the result modulo m, a and b must be reduced modulo m! template vector& v_add_to_mod(vector& a, const vector& b, const Integer& m); //--------------------------------------------------------------------------- // abs, gcd and lcm //--------------------------------------------------------------------------- //takes the absolute value of the elements and returns a reference to the changed vector template vector& v_abs(vector& v); //returns gcd of the elements of v template Integer v_gcd(const vector& v); //returns lcm of the elements of v template Integer v_lcm(const vector& v); //divides the elements by their gcd and returns the gcd template Integer v_make_prime(vector& v); //--------------------------------------------------------------------------- // Scalar operations //--------------------------------------------------------------------------- //v = v * scalar template void v_scalar_multiplication(vector& v, const Integer& scalar){ size_t i,size=v.size(); for (i = 0; i vector v_scalar_multiplication_two(const vector& v, const Integer& scalar); template void v_scalar_division(vector& v, const Integer& scalar); //v = v / scalar, all the elements of v must be divisible with the scalar template void v_reduction_modulo(vector& v, const Integer& modulo); //v = v mod modulo //--------------------------------------------------------------------------- // Test //--------------------------------------------------------------------------- template bool v_test_scalar_product(const vector& a,const vector& b, const Integer& result, const long& m); // test the main computation for arithmetic overflow // uses multiplication mod m //--------------------------------------------------------------------------- // General vector operations //--------------------------------------------------------------------------- //returns a new vector with the content of a extended by b template vector v_merge(const vector& a, const T& b); //returns a new vector with the content of a and b template vector v_merge(const vector& a, const vector& b); //returns a new vector with the last size entries of v template vector v_cut_front(const vector& v, size_t size); //the input vectors must be ordered of equal size //if u is different from v by just one element, it returns that element //else returns 0 (the elements of u and v are >0) //int v_difference_ordered_fast(const vector& u,const vector& v); template bool compare_last (const vector& a, const vector& b) { return a.back() < b.back(); } //returns a key vector containing the positions of non-zero entrys of v template vector v_non_zero_pos(vector v); } //--------------------------------------------------------------------------- #endif //--------------------------------------------------------------------------- regina-4.96/engine/enumerate/ntreeconstraint.cpp000644 000765 000024 00000023624 12377776601 022017 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 2011-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "enumerate/ntreeconstraint.h" #include "snappea/nsnappeatriangulation.h" #include "triangulation/ntriangulation.h" namespace regina { bool LPConstraintEuler::addRows( LPInitialTableaux::Col* col, const int* columnPerm, const NTriangulation* tri) { int* obj = new int[7 * tri->getNumberOfTetrahedra()]; unsigned tet, i; NPerm4 p; for (i = 0; i < 7 * tri->getNumberOfTetrahedra(); ++i) obj[i] = 1; for (i = 0; i < tri->getNumberOfTriangles(); ++i) { tet = tri->tetrahedronIndex( tri->getTriangle(i)->getEmbedding(0).getTetrahedron()); p = tri->getTriangle(i)->getEmbedding(0).getVertices(); --obj[7 * tet + p[0]]; --obj[7 * tet + p[1]]; --obj[7 * tet + p[2]]; --obj[7 * tet + 4]; --obj[7 * tet + 5]; --obj[7 * tet + 6]; } for (i = 0; i < tri->getNumberOfEdges(); ++i) { tet = tri->tetrahedronIndex( tri->getEdge(i)->getEmbedding(0).getTetrahedron()); p = tri->getEdge(i)->getEmbedding(0).getVertices(); ++obj[7 * tet + p[0]]; ++obj[7 * tet + p[1]]; ++obj[7 * tet + 4 + vertexSplitMeeting[p[0]][p[1]][0]]; ++obj[7 * tet + 4 + vertexSplitMeeting[p[0]][p[1]][1]]; } for (i = 0; i < 7 * tri->getNumberOfTetrahedra(); ++i) col[i].euler = obj[columnPerm[i]]; col[7 * tri->getNumberOfTetrahedra()].euler = -1; delete[] obj; return true; } #ifndef EXCLUDE_SNAPPEA bool LPConstraintNonSpun::addRows( LPInitialTableaux::Col* col, const int* columnPerm, const NTriangulation* tri) { // Regardless of whether the constraints are broken, // we need to ensure that the matrix has full rank. // Therefore add the coefficients for the two new variables now. col[3 * tri->getNumberOfTetrahedra()].meridian = -1; col[3 * tri->getNumberOfTetrahedra() + 1].longitude = -1; // For the time being we insist on one vertex, which must be // ideal with torus link. if (tri->getNumberOfVertices() != 1 || (! tri->getVertex(0)->isIdeal()) || (! tri->getVertex(0)->isLinkOrientable()) || tri->getVertex(0)->getLinkEulerChar() != 0) return false; // Compute the two slope equations for the torus cusp, if we can. NSnapPeaTriangulation snapPea(*tri, false); NMatrixInt* coeffs = snapPea.slopeEquations(); if (! coeffs) return false; // Check that SnapPea hasn't changed the triangulation on us. if (! snapPea.verifyTriangulation(*tri)) { delete coeffs; return false; } // All good! Add the two slope equations as extra rows to // our constraint matrix. // // The coefficients here are differences of terms from // SnapPy's get_cusp_equation(), which works in native // integers; therefore we will happily convert them back to // native integers now. for (int i = 0; i < 3 * tri->getNumberOfTetrahedra(); ++i) { col[i].meridian = coeffs->entry(0, columnPerm[i]).longValue(); col[i].longitude = coeffs->entry(1, columnPerm[i]).longValue(); } delete coeffs; return true; } #endif // EXCLUDE_SNAPPEA BanConstraintBase::BanConstraintBase(const NTriangulation* tri, int coords) : tri_(tri), coords_(coords) { unsigned nCols = (coords == NS_QUAD || coords == NS_AN_QUAD_OCT ? 3 * tri->getNumberOfTetrahedra() : coords == NS_ANGLE ? 3 * tri->getNumberOfTetrahedra() + 1 : 7 * tri->getNumberOfTetrahedra()); banned_ = new bool[nCols]; marked_ = new bool[nCols]; std::fill(banned_, banned_ + nCols, false); std::fill(marked_, marked_ + nCols, false); } void BanBoundary::init(const int* columnPerm) { unsigned n = tri_->getNumberOfTetrahedra(); unsigned tet, type, i, k; bool quadOnly = (coords_ == NS_QUAD || coords_ == NS_AN_QUAD_OCT); // The implementation here is a little inefficient (we repeat tests // three or four times over), but this routine is only called at // the beginning of the enumeration process so no need to worry. // Ban quadrilaterals in tetrahedra that meet the boundary // (every such quadrilateral meets a boundary face). for (i = 0; i < 3 * n; ++i) { if (quadOnly) tet = columnPerm[i] / 3; else tet = columnPerm[i] / 7; for (k = 0; k < 4; ++k) if (! tri_->getTetrahedron(tet)->adjacentTetrahedron(k)) { banned_[i] = true; break; } } // Ban normal triangles in tetrahedra that meet the boundary (but // only those normal triangles that meet the boundary faces). if (! quadOnly) for (i = 3 * n; i < 7 * n; ++i) { tet = columnPerm[i] / 7; type = columnPerm[i] % 7; for (k = 0; k < 4; ++k) if (k != type && ! tri_->getTetrahedron(tet)-> adjacentTetrahedron(k)) { banned_[i] = true; break; } } } void BanTorusBoundary::init(const int* columnPerm) { unsigned n = tri_->getNumberOfTetrahedra(); unsigned tet, type, i, k; // Which boundary faces are we banning? unsigned nTriangles = tri_->getNumberOfTriangles(); bool* banTriangle = new bool[nTriangles]; std::fill(banTriangle, banTriangle + nTriangles, false); // Which vertex links are we marking normal triangles around? unsigned nVertices = tri_->getNumberOfVertices(); bool* markVtx = new bool[nVertices]; std::fill(markVtx, markVtx + nVertices, false); NBoundaryComponent* bc; for (i = 0; i < tri_->getNumberOfBoundaryComponents(); ++i) { bc = tri_->getBoundaryComponent(i); if ((! bc->isIdeal()) && bc->isOrientable() && bc->getEulerChar() == 0) { // We've found a real torus boundary. for (k = 0; k < bc->getNumberOfTriangles(); ++k) banTriangle[bc->getTriangle(k)->markedIndex()] = true; for (k = 0; k < bc->getNumberOfVertices(); ++k) markVtx[bc->getVertex(k)->markedIndex()] = true; } } bool quadOnly = (coords_ == NS_QUAD || coords_ == NS_AN_QUAD_OCT); // The implementation here is a little inefficient (we repeat tests // three or four times over), but this routine is only called at // the beginning of the enumeration process so no need to worry. // Ban quadrilaterals that touch torus boundaries. for (i = 0; i < 3 * n; ++i) { if (quadOnly) tet = columnPerm[i] / 3; else tet = columnPerm[i] / 7; for (k = 0; k < 4; ++k) if (banTriangle[tri_->getTetrahedron(tet)->getTriangle(k)-> markedIndex()]) { banned_[i] = true; break; } } // Ban normal triangles that touch torus boundaries, and mark all // normal triangles that surround vertices on torus boundaries // (even if the normal triangles do not actually touch the boundary). if (! quadOnly) for (i = 3 * n; i < 7 * n; ++i) { tet = columnPerm[i] / 7; type = columnPerm[i] % 7; if (markVtx[tri_->getTetrahedron(tet)->getVertex(type)-> markedIndex()]) marked_[i] = true; for (k = 0; k < 4; ++k) if (k != type && banTriangle[tri_->getTetrahedron(tet)->getTriangle(k)-> markedIndex()]) { banned_[i] = true; break; } } delete[] banTriangle; delete[] markVtx; } } // namespace regina regina-4.96/engine/enumerate/ntreeconstraint.h000644 000765 000024 00000124375 12377775143 021471 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 2011-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file enumerate/ntreeconstraint.h * \brief Constraint classes for use with tree traversal enumeration methods. */ #ifndef __NTREECONSTRAINT_H #ifndef __DOXYGEN #define __NTREECONSTRAINT_H #endif #include "regina-config.h" // For EXCLUDE_SNAPPEA #include "enumerate/ntreelp.h" #include "maths/ninteger.h" #include "surfaces/nnormalsurfacelist.h" namespace regina { class NAngleStructure; class NNormalSurface; class NTriangulation; template class LPMatrix; /** * \weakgroup enumerate * @{ */ /** * A base class for additional linear constraints that we can add to the * tableaux of normal surface or angle structure matching equations. This is * used with NTreeEnumeration, NTreeSingleSoln and related algorithms for * enumerating and locating normal surfaces or angle structures in a * 3-manifold triangulation. See the LPInitialTableaux class notes for * details on how these constraints interact with the tableaux of * matching equations. * * The linear constraints may be equalities or inequalities, and there * may be more than one such constraint. If all constraints are * homogeneous equalities, the class should derive from LPConstraintSubspace * instead (not this base class). * * In angle structure coordinates, these linear constraints must \e not * involve the scaling coordinate (the final coordinate that is used to * convert the angle structure polytope into a polyhedral cone). * The coefficient for the final scaling coordinate in each additional * linear constraint will be assumed to be zero. * * This base class provides no functionality. For documentation's sake * only, the notes here describe the functionality that any subclass * \e must implement. We note again that LPConstraintBase does not * provide any implementations at all, and subclasses are completely * responsible for their own implementations. * * \apinotfinal * * \ifacespython Not present. */ class LPConstraintBase { #ifdef __DOXYGEN public: enum { /** * The number of additional linear constraints that we impose. * Each constraint will generate one new variable (column) * and one new equation (row) in the tableaux. */ nConstraints }; /** * Stores the extra coefficients in a single column for the * \a nConstraints additional rows that we add to the tableaux * to describe the \a nConstraints additional linear equations * or inequalities. * * Subclasses may store these coefficients however they like * (in particular, they may optimise for sparse coefficients, * binary coefficients, and so on). They will only ever be * accessed through the member functions of this Coefficients class. */ struct Coefficients { /** * Creates an uninitialised set of coefficients for a single * column. These cofficients must be initialised through a * call to addRows() before they can be used. */ Coefficients(); /** * Explicitly fills the final row(s) of the given tableaux matrix * with the coefficients stored in this Coefficients structure. * In essence, this routine simply copies this sparse and/or * specialised representation of the final row(s) into a * more standard dense matrix representation. * * This routine should only affect the final \a nConstraints * entries in the given column of the matrix. It may assume * that these final row(s) have already been initialised to zero. * * \pre The given matrix has at least \a nConstraints rows * and at least \a col + 1 columns. * \pre The final \a nConstraints entries in column \a col * of the given matrix have already been set to zero. * * @param m the matrix in which to place these column * coefficients. * @param col the column of the given matrix in which to * place these coefficients. */ template void fillFinalRows(LPMatrix& m, unsigned col) const; /** * Computes the inner product of (i) the final \a nConstraints * entries in the given row of the given matrix with (ii) the * \a nConstraints column coefficients stored in this data * structure. * * \pre The given matrix has at least \a nConstraints columns * and at least \a mRow + 1 rows. * * @param m the matrix whose row we will use in the inner product. * @param mRow the row of the matrix \a m to use in the inner * product. * @return the resulting portion of the inner product. */ template Integer innerProduct(const LPMatrix& m, unsigned mRow) const; /** * A variant of innerProduct() that takes into account any * adjustments to these linear constraint(s) that are required when * this is a quadrilateral column being used to represent an * octagon type. * * The LPData class offers support for octagonal almost normal * surfaces, in which exactly one tetrahedron is allowed to have * exactly one octagon type. We represent such an octagon as a * \e pair of incompatible quadrilaterals within the same * tetrahedron. See the LPData class notes for details on how * this works. * * In some settings, our extra linear constraints must behave * differently in the presence of octagons (i.e., the coefficient * of the octagon type is not just the sum of coefficients of the * two constituent quadrilateral types). This routine effectively * allows us to adjust the tableaux accordingly. * * Specifically: this routine computes the inner product of (i) the * final \a nConstraints entries in the given row of the given * matrix with (ii) the \a nConstraints column coefficients * stored in this data structure. We assume that this column * in the underlying tableaux describes one of the two * quadrilateral coordinates in some tetrahedron that together * form an octagon type, and if necessary we implicitly adjust * the coefficients stored in this data structure accordingly. * * This routine is not used with angle structure coordinates. * * \pre The given matrix has at least \a nConstraints columns * and at least \a mRow + 1 rows. * * \pre This column of the underlying tableaux describes one * of the two quadrilateral coordinates that are being * combined to form an octagon type within some tetrahedron. * * @param m the matrix whose row we will use in the inner product. * @param mRow the row of the matrix \a m to use in the inner * product. * @return the resulting portion of the inner product. */ template Integer innerProductOct(const LPMatrix& m, unsigned mRow) const; }; /** * Explicitly constructs equations for the linear function(s) * constrained by this class. Specifically, this routine takes an * array of Coefficients objects (one for each column of the initial * tableaux) and fills in the necessary coefficient data. * * The precise form of the linear function(s) will typically * depend upon the underlying triangulation. For this reason, * the triangulation is explicitly passed, along with the * permutation that indicates which columns of the initial tableaux * correspond to which normal or angle structure coordinates. * * More precisely: recall that, for each linear function, the initial * tableaux acquires one new variable \a x_i that evaluates this linear * function f(x). This routine must create the corresponding row that * sets f(x) - x_i = 0. Thus it must construct the * coefficients of f(x) in the columns corresponding to normal * coordinates, and it must also set a coefficient of -1 in the * column for the corresponding new variable. * * For each subclass \a S of LPConstraintBase, the array \a col * must be an array of objects of type LPInitialTableaux::Col. * The class LPInitialTableaux::Col is itself a larger subclass of * the Coefficients class. This exact type must be used because the * compiler must know how large each column object is in * order to correct access each element of the given array. * * As described in the LPInitialTableaux class notes, it might * not be possible to construct the linear functions (since the * triangulation might not satisfy the necessary requirements). * In this case, this routine should ensure that the linear * functions are in fact the zero functions, and should return * \c false (but it must still set -1 coefficients for the new * variables as described above). Otherwise (if the linear function * were successfully constructed) this routine should return \c true. * * If you are implementing this routine in a subclass that * works with angle structure coordinates, remember that your * linear constraints must not interact with the scaling coordinate * (the final angle structure coordinate that is used to projectivise * the angle structure polytope into a polyhedral cone). Your * implementation of this routine \e must ensure that your * linear constraints all have coefficient zero in this column. * * \pre For all coefficients in the array \a col, the * Coefficients substructures have all been initialised with the * default constructor and not modified since. * * @param col the array of columns as stored in the initial * tableaux (i.e., the data member LPInitialTableaux::col_). * @param columnPerm the corresponding permutation of columns * that describes how columns of the tableaux correspond to normal or * angle structure coordinates in the underlying triangulation * (i.e., the data member LPInitialTableaux::columnPerm_). * @param tri the underlying triangulation. * @return \c true if the linear functions were successfully * constructed, or \c false if not (in which case they will be * replaced with the zero functions instead). */ static bool addRows(LPInitialTableaux::Col* col, const int* columnPerm, const NTriangulation* tri); /** * Explicitly constraints each of these linear functions to an * equality or inequality in the underlying tableaux. This will * typically consist of a series of calls to LPData::constrainZero() * and/or LPData::constrainPositive(). * * The variables for these extra linear functions are stored in * columns numCols - nConstraints, ..., numCols - 1 * of the given tableaux, and so your calls to LPData::constrainZero() * and/or LPData::constrainPositive() should operate on these * (and only these) columns. * * \pre These column coefficients belong to the initial starting * tableaux (LPInitialTableaux) from which the given tableaux is * derived. * * @param lp the tableaux in which to constrain these linear * functions. * @param numCols the number of columns in the given tableaux. */ template static void constrain(LPData& lp, unsigned numCols); /** * Ensures that the given normal surface satisfies the extra * constraints described by this class. * * Ideally this test is not based on explicitly recomputing the * linear function(s), but instead runs independent tests. * For instance, if this class is used to constraint Euler * characteristic, then ideally this routine would call * s->getEulerChar() and test the return value of that * routine instead. * * If these linear constraints work with angle structure coordinates * (not normal or almost normal surfaces), then this routine should * return \c false. * * @param s the surface to test. * @return \c true if the given surface satisfies these linear * constraints, or \c false if it does not. */ static bool verify(const NNormalSurface* s); /** * Ensures that the given angle structure satisfies the extra * constraints described by this class. * * Ideally this test is not based on explicitly recomputing the * linear function(s), but instead runs independent tests; * see the related routine verify(const NNormalSurface*) for examples. * * If these linear constraints work with normal or almost normal * surfaces (not angle structure coordinates), then this routine should * return \c false. * * @param s the angle structure to test. * @return \c true if the given angle structure satisfies these linear * constraints, or \c false if it does not. */ static bool verify(const NAngleStructure* s); /** * Indicates whether the given coordinate system is supported by * this constraint class. * * This routine assumes that the given system is already known to be * supported by the generic tree traversal infrastructure, and only * returns \c false if there are additional prerequisites * imposed by this particular constraint class that the given * system does not satisfy. If this constraint class does not impose * any of its own additional conditions, this routine may * simply return \c true. * * @param coords the coordinate system being queried; this must * be one of the coordinate systems known to be supported by the * generic NTreeTraversal infrastructure. * @return \c true if and only if this coordinate system is * also supported by this specific constraint class. */ static bool supported(NormalCoords coords); #endif }; /** * A subclass of LPConstraintBase used for constraints defined entirely * by homogeneous linear equations. * * Any set of constraints defined entirely by homogeneous linear * equations should derive from LPConstraintSubspace, not LPConstraintBase. * In other words, any set of constraints derived from LPConstraintSubspace * should simply restrict our attention to a vector subspace of the * normal surface or angle structure coordinate system. * * This class does not provide any additional functionality. It is * merely a convenience to help describe and enforce preconditions. * * \apinotfinal * * \ifacespython Not present. */ class LPConstraintSubspace : public LPConstraintBase { }; /** * A do-nothing class that imposes no additional linear constraints on * the tableaux of normal surface or angle structure matching equations. * * See the LPConstraintBase class notes for details on all member * functions and structs. * * \ifacespython Not present. */ class LPConstraintNone : public LPConstraintSubspace { public: enum { nConstraints = 0 }; /** * Stores the extra coefficients in the tableaux associated * with this constraint class (which for this class is a no-op, * since in this case there are no extra coefficients). * * See the LPConstraintBase::Coefficients notes for further details. */ struct Coefficients { Coefficients(); template void fillFinalRows(LPMatrix& m, unsigned col) const; template Integer innerProduct(const LPMatrix&, unsigned) const; template Integer innerProductOct(const LPMatrix&, unsigned) const; }; static bool addRows(LPInitialTableaux::Col*, const int*, const NTriangulation*); template static void constrain( LPData&, unsigned); static bool verify(const NNormalSurface*); static bool verify(const NAngleStructure*); static bool supported(NormalCoords coords); }; /** * A class that constraints the tableaux of normal surface matching equations * to ensure that Euler characteristic is strictly positive. * * There are many ways of writing Euler characteritic as a linear * function. The function constructed here has integer coefficients, * but otherwise has no special properties of note. * * This constraint can work with either normal or almost normal * coordinates. In the case of almost normal coordinates, the function * is modified to measure Euler characteristic minus the number of * octagons (a technique of Casson, also employed by Jaco and Rubinstein, that * is used to ensure we do not have more than two octagons when searching for * a normal or almost normal sphere in the 3-sphere recognition algorithm). * * See the LPConstraintBase class notes for details on all member * functions and structs. * * \pre We are working in standard normal or almost normal coordinates * (not quadrilateral or quadrilateral-octagon coordinates). In * particular, the coordinate system passed to the corresponding * LPInitialTableaux class constructor must be NS_STANDARD. * * \apinotfinal * * \ifacespython Not present. */ class LPConstraintEuler : public LPConstraintBase { public: enum { nConstraints = 1 }; /** * Stores the extra coefficients in the tableaux associated with this * constraint class (in this case, one extra integer per column). * * See the LPConstraintBase::Coefficients notes for further details. */ struct Coefficients { int euler; /**< The coefficient of the Euler characteristic function for the corresponding column of the matching equation matrix. */ Coefficients(); template void fillFinalRows(LPMatrix& m, unsigned col) const; template Integer innerProduct(const LPMatrix& m, unsigned mRow) const; template Integer innerProductOct(const LPMatrix& m, unsigned mRow) const; }; static bool addRows( LPInitialTableaux::Col* col, const int* columnPerm, const NTriangulation* tri); template static void constrain( LPData& lp, unsigned numCols); static bool verify(const NNormalSurface* s); static bool verify(const NAngleStructure*); static bool supported(NormalCoords coords); }; #ifndef EXCLUDE_SNAPPEA /** * A class that constraints the tableaux of normal surface matching equations * to ensure that normal surfaces in an ideal triangulation are compact * (thereby avoiding spun normal surfaces with infinitely many triangles). * * At present this class can only work with oriented triangulations that have * precisely one vertex, which is ideal with torus link. These * constraints are explicitly checked by addRows(), which returns \c false * if they are not satisfied. Moreover, this constraint calls on * SnapPea for some calculations: in the unexpected situation where * SnapPea retriangulates, the linear function cannot be constructed and * addRows() will again return \c false. You should always test * LPInitialTableaux::constraintsBroken() to verify that the linear * functions have been constructed correctly. * * Also, at present this class can only work with quadrilateral normal * coordinates (and cannot handle almost normal coordinates at all). * This is \e not explicitly checked; instead it appears as a * precondition (see below). * * See the LPConstraintBase class notes for details on all member * functions and structs. * * \pre We are working in quadrilateral normal coordinates. In particular, * the coordinate system passed to the corresponding LPInitialTableaux class * must be NS_QUAD, and constrainOct() must never be * called on any of the corresponding LPData tableaux. * * \apinotfinal * * \ifacespython Not present. */ class LPConstraintNonSpun : public LPConstraintSubspace { public: enum { nConstraints = 2 }; /** * Stores the extra coefficients in the tableaux associated with this * constraint class (in this case, two extra integers per column). * * See the LPConstraintBase::Coefficients notes for further details. */ struct Coefficients { int meridian; /**< The coefficient of the meridian equation for the corresponding column of the matching equation matrix. */ int longitude; /**< The coefficient of the longitude equation for the corresponding column of the matching equation matrix. */ Coefficients(); template void fillFinalRows(LPMatrix& m, unsigned col) const; template Integer innerProduct(const LPMatrix& m, unsigned mRow) const; template Integer innerProductOct(const LPMatrix& m, unsigned mRow) const; }; static bool addRows( LPInitialTableaux::Col* col, const int* columnPerm, const NTriangulation* tri); template static void constrain( LPData& lp, unsigned numCols); static bool verify(const NNormalSurface* s); static bool verify(const NAngleStructure*); static bool supported(NormalCoords coords); }; #endif // EXCLUDE_SNAPPEA /** * A base class for additional banning and marking constraints that we * can place on tree traversal algorithms. This is used with * NTreeEnumeration, NTreeSingleSoln and related algorithms for * enumerating and locating normal surfaces and angle structures in a * 3-manifold triangulation. * * This class adds constraints of two types: * * - \e Banning constraints, which ensure that certain coordinates * are set to zero; * * - \e Marking constraints, which are more flexible and can be used in * different ways by different algorithms. * * All of these constraints operate only on normal or angle structure * coordinates in the underlying tableaux (and in particular not the * additional variables introduced by additional linear constraints, * as described by LPConstraintBase and its subclasses). * * Currently marking is used in the following ways: * * - The NTreeEnumeration and NTautEnumeration algorithms do not use marking * at all. * * - In the NTreeSingleSoln algorithm, marking affects what is considered * a non-trivial normal surface. Normally, a non-trivial surface is defined * to be one in which some triangle coordinate is zero. With marking, * a non-trivial surface is redefined to be one in which some \e unmarked * triangle coordinate is zero. In other words, marked triangle types * are effectively ignored when determining whether a surface is non-trivial * or not. * * At present, marking is not used at all for quadrilateral coordinates * or angle structures. However, marking is a very new feature, and this * concept may be expanded in future versions of Regina. * * This class does not record disc types in the order of their normal or * angle structure coordinates; instead it records them in the order of their * columns in a tableaux for linear programming (as used in LPInitialTableaux). * This means that there is a little more work required in setting up * the initial lists of banned and marked columns, but then these lists are * easy to use on the fly during tree traversal algorithms. * * This base class provides limited functionality (as documented below). * Subclasses \e must implement a constructor (which, like this base * class, takes a triangulation and a coordinate system), must implement * init() which determines which coordinates are banned and/or marked, * and must implement supported(), which indicates which normal or angle * structure coordinate system this constraint class can work with. * * \apinotfinal * * \ifacespython Not present. */ class BanConstraintBase { protected: const NTriangulation* tri_; /**< The triangulation with which we are working. */ int coords_; /**< The normal or almost normal coordinate system in which we are working. This must be one of NS_QUAD, NS_STANDARD, NS_AN_QUAD_OCT, NS_AN_STANDARD, or NS_ANGLE. */ bool* banned_; /**< Indicates which columns of a tableaux correspond to banned coordinates (e.g., banned normal disc types). The size of this array is the number of normal or angle structure coordinates (so we explicitly exclude extra columns that arise from the template parameter LPConstraint. */ bool* marked_; /**< Indicates which columns of a tableaux correspond to marked coordinates (e.g., marked normal disc types). The size of this array is the number of normal or angle structure coordinates (so we explicitly exclude extra columns that arise from the template parameter LPConstraint. */ protected: /** * Constructs and initialises the \a banned_ and \a marked_ arrays * to be entirely \c false. The only purpose of passing the * triangulation and coordinate system is to determine how many * normal or angle structure coordinates we are dealing with. * * \warning Before you use this object, the routine init() must be * called to fill in the \a banned_ and \a marked_ arrays with the * correct data. Otherwise you will have no banned or marked disc * types at all. * * @param tri the triangulation with which we are working. * @param coords the coordinate system in * which we are working. This must be one of NS_QUAD, * NS_STANDARD, NS_AN_QUAD_OCT, NS_AN_STANDARD, or NS_ANGLE. */ BanConstraintBase(const NTriangulation* tri, int coords); /** * Destroys this object and all associated data. */ ~BanConstraintBase(); /** * Enforces all bans described by this class in the given * tableaux. Specifically, for each banned coordinate, this * routine calls LPData::constrainZero() on the corresponding * coordinate column. * * @param lp the tableaux in which to enforce the bans. */ template void enforceBans(LPData& lp) const; #ifdef __DOXYGEN /** * Identifies which coordinates to ban and mark, and records the * corresponding tableaux columns in the \a banned_ and \a marked_ * arrays respectively. * * @param columnPerm the permutation of columns that describes how * columns of the tableaux correspond to normal or angle strutcure * coordinates in the underlying triangulation. Specifically, this * permutation must be the same permutation returned by * LPInitialTableaux::columnPerm(). */ void init(const int* columnPerm); /** * Indicates whether the given coordinate system is supported by * this constraint class. * * This routine assumes that the given system is already known to be * supported by the generic tree traversal infrastructure, and only * returns \c false if there are additional prerequisites * imposed by this particular constraint class that the given * system does not satisfy. If this constraint class does not impose * any of its own additional conditions, this routine may * simply return \c true. * * @param coords the coordinate system being queried; this must * be one of the coordinate systems known to be supported by the * generic NTreeTraversal infrastructure. * @return \c true if and only if this coordinate system is * also supported by this specific constraint class. */ static bool supported(NormalCoords coords); #endif }; /** * A do-nothing class that bans no coordinates and marks no coordinates. * * See the BanConstraintBase class notes for details on all member * functions and structs. * * \apinotfinal * * \ifacespython Not present. */ class BanNone : public BanConstraintBase { protected: /** * Constructs and initialises the \a banned_ and \a marked_ arrays * to be entirely \c false, as described in the BanConstraintBase * superclass constructor. * * Although one should normally call the routine init() before * using this object, for BanNone this is not strictly necessary * since there are no coordinates to ban or mark. * * @param tri the triangulation with which we are working. * @param coords the coordinate system in * which we are working. This must be one of NS_QUAD, * NS_STANDARD, NS_AN_QUAD_OCT, NS_AN_STANDARD, or NS_ANGLE. */ BanNone(const NTriangulation* tri, int coords); void init(const int*); static bool supported(NormalCoords coords); }; /** * A class that bans normal disc types that meet the boundary of the * underlying triangulation. No disc types are marked at all. * * This class is only for use with normal or almost normal surfaces, not * angle structures. * * \warning This class only works as expected in \e standard normal or * almost normal coordinates. In quadrilateral or quadrilateral-octagon * coordinates it will only ban quadrilaterals or octagons that touch * the boundary, but it will still allow \e triangles that meet the boundary * (since triangle types are not counted in these coordinate systems). * The supported() routine will only return \c true in standard normal or * almost normal coordinates. * * See the BanConstraintBase class notes for details on all member * functions and structs. * * \apinotfinal * * \ifacespython Not present. */ class BanBoundary : public BanConstraintBase { protected: /** * Constructs and initialises the \a banned_ and \a marked_ arrays * to be entirely \c false, as described in the BanConstraintBase * superclass constructor. * * \warning Before you use this object, the routine init() must be * called to fill in the \a banned_ and \a marked_ arrays with the * correct data. Otherwise you will have no banned or marked disc * types at all. * * @param tri the triangulation with which we are working. * @param coords the normal or almost normal coordinate system in * which we are working. This must be one of NS_QUAD, * NS_STANDARD, NS_AN_QUAD_OCT, or NS_AN_STANDARD. */ BanBoundary(const NTriangulation* tri, int coords); void init(const int* columnPerm); static bool supported(NormalCoords coords); }; /** * A class that bans and marks disc types associated with torus boundary * components. Here we refer exclusively to real torus boundary * components (not ideal vertices with torus cusps). Specifically: * * - this class bans any normal triangle or quadrilateral that meets a * torus boundary; * * - this class marks any normal triangle in the link of a vertex on a * torus boundary. * * This class is only for use with normal or almost normal surfaces, not * angle structures. * * \warning As with BanBoundary, this class only works as expected in * \e standard normal or almost normal coordinates. In quadrilateral or * quadrilateral-octagon coordinates it will only ban quadrilaterals or * octagons that touch torus boundaries, but it will still allow \e triangles * that meet torus boundaries (since triangle types are not counted in these * coordinate systems). The supported() routine will only return \c true * in standard normal or almost normal coordinates. * * See the BanConstraintBase class notes for details on all member * functions and structs. * * \apinotfinal * * \ifacespython Not present. */ class BanTorusBoundary : public BanConstraintBase { protected: /** * Constructs and initialises the \a banned_ and \a marked_ arrays * to be entirely \c false, as described in the BanConstraintBase * superclass constructor. * * \warning Before you use this object, the routine init() must be * called to fill in the \a banned_ and \a marked_ arrays with the * correct data. Otherwise you will have no banned or marked disc * types at all. * * @param tri the triangulation with which we are working. * @param coords the normal or almost normal coordinate system in * which we are working. This must be one of NS_QUAD, * NS_STANDARD, NS_AN_QUAD_OCT, or NS_AN_STANDARD. */ BanTorusBoundary(const NTriangulation* tri, int coords); void init(const int* columnPerm); static bool supported(NormalCoords coords); }; // Inline functions inline LPConstraintNone::Coefficients::Coefficients() { } template inline void LPConstraintNone::Coefficients::fillFinalRows( LPMatrix& m, unsigned col) const { } template inline Integer LPConstraintNone::Coefficients::innerProduct( const LPMatrix&, unsigned) const { return 0; } template inline Integer LPConstraintNone::Coefficients::innerProductOct( const LPMatrix&, unsigned) const { return 0; } inline bool LPConstraintNone::addRows( LPInitialTableaux::Col*, const int*, const NTriangulation*) { return true; } template inline void LPConstraintNone::constrain( LPData&, unsigned) { } inline bool LPConstraintNone::verify(const NNormalSurface*) { return true; } inline bool LPConstraintNone::verify(const NAngleStructure*) { return true; } inline bool LPConstraintNone::supported(NormalCoords) { return true; } inline LPConstraintEuler::Coefficients::Coefficients() : euler(0) {} template inline void LPConstraintEuler::Coefficients::fillFinalRows( LPMatrix& m, unsigned col) const { m.entry(m.rows() - 1, col) = euler; } template inline Integer LPConstraintEuler::Coefficients::innerProduct( const LPMatrix& m, unsigned mRow) const { Integer ans(m.entry(mRow, m.rows() - 1)); ans *= euler; return ans; } template inline Integer LPConstraintEuler::Coefficients::innerProductOct( const LPMatrix& m, unsigned mRow) const { // This is called for *two* quad columns (the two quads // that combine to give a single octagon). // // The adjustment in this case is to subtract two from // the overall Euler characteristic coefficient for this // octagon type (-1 because an octagon has lower Euler // characteristic than two quads, and -1 again because // we are measuring Euler - #octagons. // // Happily we can do this by subtracting one from the // coefficient in each of the two columns, as // implemented below. Integer ans(m.entry(mRow, m.rows() - 1)); ans *= (euler - 1); return ans; } template inline void LPConstraintEuler::constrain( LPData& lp, unsigned numCols) { lp.constrainPositive(numCols - 1); } inline bool LPConstraintEuler::verify(const NNormalSurface* s) { return (s->getEulerChar() > 0); } inline bool LPConstraintEuler::verify(const NAngleStructure*) { return false; } inline bool LPConstraintEuler::supported(NormalCoords coords) { return (coords == NS_STANDARD || coords == NS_AN_STANDARD); } #ifndef EXCLUDE_SNAPPEA inline LPConstraintNonSpun::Coefficients::Coefficients() : meridian(0), longitude(0) { } template inline void LPConstraintNonSpun::Coefficients::fillFinalRows( LPMatrix& m, unsigned col) const { m.entry(m.rows() - 2, col) = meridian; m.entry(m.rows() - 1, col) = longitude; } template inline Integer LPConstraintNonSpun::Coefficients::innerProduct( const LPMatrix& m, unsigned mRow) const { Integer ans1(m.entry(mRow, m.rows() - 2)); ans1 *= meridian; Integer ans2(m.entry(mRow, m.rows() - 1)); ans2 *= longitude; ans1 += ans2; return ans1; } template inline Integer LPConstraintNonSpun::Coefficients::innerProductOct( const LPMatrix& m, unsigned mRow) const { // This should never be called, since we never use this // constraint with almost normal surfaces. // For compilation's sake though, just return the usual // inner product. return innerProduct(m, mRow); } template inline void LPConstraintNonSpun::constrain( LPData& lp, unsigned numCols) { lp.constrainZero(numCols - 2); lp.constrainZero(numCols - 1); } inline bool LPConstraintNonSpun::verify(const NNormalSurface* s) { return s->isCompact(); } inline bool LPConstraintNonSpun::verify(const NAngleStructure*) { return false; } inline bool LPConstraintNonSpun::supported(NormalCoords coords) { return (coords == NS_QUAD); } #endif // EXCLUDE_SNAPPEA inline BanConstraintBase::~BanConstraintBase() { delete[] banned_; delete[] marked_; } template inline void BanConstraintBase::enforceBans(LPData& lp) const { for (unsigned i = 0; i < lp.coordinateColumns(); ++i) if (banned_[i]) lp.constrainZero(i); } inline BanNone::BanNone(const NTriangulation* tri, int coords) : BanConstraintBase(tri, coords) { } inline void BanNone::init(const int*) { } inline bool BanNone::supported(NormalCoords) { return true; } inline BanBoundary::BanBoundary(const NTriangulation* tri, int coords) : BanConstraintBase(tri, coords) { } inline bool BanBoundary::supported(NormalCoords coords) { return (coords == NS_STANDARD || NS_AN_STANDARD); } inline BanTorusBoundary::BanTorusBoundary( const NTriangulation* tri, int coords) : BanConstraintBase(tri, coords) { } inline bool BanTorusBoundary::supported(NormalCoords coords) { return (coords == NS_STANDARD || NS_AN_STANDARD); } } // namespace regina #endif regina-4.96/engine/enumerate/ntreelp-impl.h000644 000765 000024 00000136073 12377775144 020656 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 2011-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /* Definitions of template member functions from ntreelp.h. If your template arguments are classes from ntreeconstraint.h, then you never need to include this file (since all templates will already be instantiated for you). You will, however, need to include this file if you provide your own custom classes as template arguments. */ #ifndef __NTREELP_IMPL_H #ifndef __DOXYGEN #define __NTREELP_IMPL_H #endif /** * Optimisation flags: * Define any combination of the following flags to switch \e off * various optimisations. * This is for diagnostic purposes only. */ // #define REGINA_NOOPT_REORDER_COLUMNS #include "angle/nanglestructure.h" #include "enumerate/ntreeconstraint.h" #include "enumerate/ntreelp.h" #include "maths/matrixops.h" #include "surfaces/nnormalsurfacelist.h" #include "triangulation/ntriangulation.h" #include "utilities/nbitmask.h" #include namespace regina { template void LPMatrix::combRow(const Integer& destCoeff, unsigned dest, const Integer& srcCoeff, unsigned src, const Integer& div) { Integer* ps = dat_ + src * cols_; Integer* pd = dat_ + dest * cols_; Integer tmp; // Use this to avoid spurious temporary Integers. for (unsigned i = 0; i < cols_; ++i) { *pd *= destCoeff; tmp = srcCoeff; tmp *= *ps++; *pd -= tmp; (*pd++).divByExact(div); } } template Integer LPMatrix::combRowAndNorm(const Integer& destCoeff, unsigned dest, const Integer& srcCoeff, unsigned src) { Integer gcdRow; // Initialised to zero. Integer* ps = dat_ + src * cols_; Integer* pd = dat_ + dest * cols_; Integer tmp; // Use this to avoid spurious temporary Integers. unsigned i; for (i = 0; i < cols_; ++i, ++pd, ++ps) { *pd *= destCoeff; tmp = srcCoeff; tmp *= *ps; *pd -= tmp; if (gcdRow != 1) gcdRow.gcdWith(*pd); // gcd() guarantees to be >= 0. } if (gcdRow > 1) { pd = dat_ + dest * cols_; for (i = 0; i < cols_; ++i) (*pd++).divByExact(gcdRow); } return gcdRow; } template void LPMatrix::dump(std::ostream& out) const { out << "---------------------------------" << std::endl; unsigned r, c; for (r = 0; r < rows_; ++r) { for (c = 0; c < cols_; ++c) out << entry(r, c) << ' '; out << std::endl; } out << "---------------------------------" << std::endl; } template LPInitialTableaux::LPInitialTableaux( const NTriangulation* tri, NormalCoords coords, bool enumeration) : tri_(tri), coords_(coords) { unsigned r, c; // Fetch the original (unadjusted) matrix of matching equations. if (coords_ != NS_ANGLE) { eqns_ = regina::makeMatchingEquations(tri, coords); scaling_ = 0; } else { eqns_ = NAngleStructureVector::makeAngleEquations(tri); // Scale each row so that the rightmost entry (used for // projectivising the angle structure polytope) is always -2. // This is possible since the matrix returned by NAngleStructureVector // will have final entries of -1 and -2 only. scaling_ = -2; long rightmost; for (r = 0; r < eqns_->rows(); ++r) { rightmost = eqns_->entry(r, eqns_->columns() - 1).longValue(); if (rightmost != scaling_) for (c = 0; c < eqns_->columns(); ++c) eqns_->entry(r, c) *= (scaling_ / rightmost); } } // Compute the rank of the matrix, and reorder its rows so // the first \a rank_ rows are full rank. rank_ = regina::rowBasis(*eqns_); // Reorder the columns using a good heuristic. cols_ = eqns_->columns() + LPConstraint::nConstraints; columnPerm_ = new int[cols_]; reorder(enumeration); // Create and fill the sparse columns. col_ = new Col[cols_]; for (c = 0; c < eqns_->columns() - (scaling_ ? 1 : 0); ++c) for (r = 0; r < rank_; ++r) if (eqns_->entry(r, c) != 0) col_[c].push(r, eqns_->entry(r, c).longValue()); // Add in the final row(s) for any additional constraints. constraintsBroken_ = ! LPConstraint::addRows(col_, columnPerm_, tri); rank_ += LPConstraint::nConstraints; } #ifdef REGINA_NOOPT_REORDER_COLUMNS template void LPInitialTableaux::reorder(bool) { // This is a "do-nothing" version of reorder(). int i, j; if (coords_ == NS_QUAD || coords_ == NS_ANGLE) { // Leave the columns exactly as they were. for (i = 0; i < cols_; ++i) columnPerm_[i] = i; return; } else { // Keep the tetrahedra in the same order, but move // quadrilaterals to the front and triangles to the back // as required by columnPerm(). int n = tri_->getNumberOfTetrahedra(); for (i = 0; i < n; ++i) { columnPerm_[3 * i] = 7 * i + 4; columnPerm_[3 * i + 1] = 7 * i + 5; columnPerm_[3 * i + 2] = 7 * i + 6; columnPerm_[3 * n + 4 * i] = 7 * i; columnPerm_[3 * n + 4 * i + 1] = 7 * i + 1; columnPerm_[3 * n + 4 * i + 2] = 7 * i + 2; columnPerm_[3 * n + 4 * i + 3] = 7 * i + 3; } } // This fills the columnPerm_ array; now we need to move the // columns of eqns_ around accordingly, and then finish off // columnPerm_ with the columns for additional constraints // from LPConstraint (if we have any). // // From here on we copy code directly from the "real" reorder() // below. int* tmp = new int[eqns_->columns()]; std::copy(columnPerm_, columnPerm_ + eqns_->columns(), tmp); for (i = 0; i < eqns_->columns(); ++i) { // Column tmp[i] of the matrix should be moved to // column i. if (tmp[i] == i) continue; eqns_->swapColumns(i, tmp[i]); // Adjust links to the old column i, which is now column tmp[i]. for (j = i + 1; j < eqns_->columns(); ++j) if (tmp[j] == i) break; // This is the link we need to change. #ifdef REGINA_VERIFY_LPDATA if (j == eqns_->columns()) { std::cerr << "ERROR: Sorting error." << std::endl; ::exit(1); } #endif tmp[j] = tmp[i]; tmp[i] = i; } delete[] tmp; // If we have extra variables for additional constraints or // objectives, append the corresponding entries to the end of // the permutation for completeness. for (i = 0; i < LPConstraint::nConstraints; ++i) columnPerm_[cols_ - i - 1] = cols_ - i - 1; } #else template void LPInitialTableaux::reorder(bool enumeration) { int n = tri_->getNumberOfTetrahedra(); int i, j, k; // Fill the columnPerm_ array according to what kind of // problem we're trying to solve. if (coords_ == NS_STANDARD && enumeration) { // We're doing vertex enumeration in standard coordinates. // // Use exactly the same ordering of quadrilaterals that we // use in quadrilateral coordinates, and then just fill // in the triangles at the end. LPInitialTableaux quad(tri_, NS_QUAD, true /* enumeration */); for (i = 0; i < n; ++i) { k = quad.columnPerm()[3 * i] / 3; columnPerm_[3 * i] = 7 * k + 4; columnPerm_[3 * i + 1] = 7 * k + 5; columnPerm_[3 * i + 2] = 7 * k + 6; columnPerm_[3 * n + 4 * i] = 7 * k; columnPerm_[3 * n + 4 * i + 1] = 7 * k + 1; columnPerm_[3 * n + 4 * i + 2] = 7 * k + 2; columnPerm_[3 * n + 4 * i + 3] = 7 * k + 3; } } else if (coords_ == NS_ANGLE) { // TODO: Find a good heuristic to use for angle structure coordinates. // For now, we'll leave the columns exactly as they were. for (i = 0; i < cols_; ++i) columnPerm_[i] = i; return; } else { // Either we're doing vertex enumeration in quad coordinates, // or we're in standard coordinates but just searching for a // single solution under some constraints. // // Process the rows in increasing order by number of tetrahedra // touched, and place the columns for each tetrahedron in the // order that we see them. We place columns at the "back" of // the matrix, so that we fill the matrix in "reverse" order // from the last column to the first. // Track which rows have been processed so far. bool* used = new bool[rank_]; std::fill(used, used + rank_, false); // Also track which tetrahedra have been used so far. bool* touched = new bool[n]; std::fill(touched, touched + n, false); int nTouched = 0; // Off we go, one row at a time. int bestRow, best, curr; for (i = 0; i < rank_; ++i) { // Seek out the ith row to process. // Because the first rank_ rows of the matrix are full rank, // we are guaranteed that this row will be non-zero. best = n + 1; // No row touches more than n tetrahedra. for (j = 0; j < rank_; ++j) { if (used[j]) continue; curr = 0; for (k = 0; k < n; ++k) { if (touched[k]) continue; if (coords_ == NS_QUAD) { // We're in quadrilateral or angle structure // coordinates. if (eqns_->entry(j, 3 * k) != 0 || eqns_->entry(j, 3 * k + 1) != 0 || eqns_->entry(j, 3 * k + 2) != 0) ++curr; } else { // We're in standard coordinates. if (eqns_->entry(j, 7 * k + 4) != 0 || eqns_->entry(j, 7 * k + 5) != 0 || eqns_->entry(j, 7 * k + 6) != 0) ++curr; } if (curr >= best) break; // We cannot beat best from here. } if (curr < best) { bestRow = j; best = curr; } } // The next row to process is bestRow. // Find all the tetrahedra that it touches that we // haven't already used yet, and place the corresponding // columns at the end of the matrix. used[bestRow] = true; for (k = 0; k < n; ++k) { if (touched[k]) continue; if (coords_ == NS_QUAD) { // We're in quadrilateral or angle structure coordinates. if ((eqns_->entry(bestRow, 3 * k) != 0 || eqns_->entry(bestRow, 3 * k + 1) != 0 || eqns_->entry(bestRow, 3 * k + 2) != 0)) { touched[k] = true; columnPerm_[3 * (n - nTouched) - 3] = 3 * k; columnPerm_[3 * (n - nTouched) - 2] = 3 * k + 1; columnPerm_[3 * (n - nTouched) - 1] = 3 * k + 2; ++nTouched; } } else { // We're in standard coordinates. if ((eqns_->entry(bestRow, 7 * k + 4) != 0 || eqns_->entry(bestRow, 7 * k + 5) != 0 || eqns_->entry(bestRow, 7 * k + 6) != 0)) { touched[k] = true; // The quadrilateral columns... columnPerm_[3 * (n - nTouched) - 3] = 7 * k + 4; columnPerm_[3 * (n - nTouched) - 2] = 7 * k + 5; columnPerm_[3 * (n - nTouched) - 1] = 7 * k + 6; // ... and the triangle columns. columnPerm_[3 * n + 4 * (n - nTouched) - 4] = 7 * k; columnPerm_[3 * n + 4 * (n - nTouched) - 3] = 7 * k + 1; columnPerm_[3 * n + 4 * (n - nTouched) - 2] = 7 * k + 2; columnPerm_[3 * n + 4 * (n - nTouched) - 1] = 7 * k + 3; ++nTouched; } } } } // We have now processed all rows. However, there may be some // tetrahedra that appear in no rows at all. // Make sure we catch these tetrahedra as well. for (k = 0; k < n; ++k) { if (touched[k]) continue; touched[k] = true; if (coords_ == NS_QUAD) { // We're in quadrilateral or angle structure coordinates. columnPerm_[3 * (n - nTouched) - 3] = 3 * k; columnPerm_[3 * (n - nTouched) - 2] = 3 * k + 1; columnPerm_[3 * (n - nTouched) - 1] = 3 * k + 2; } else { // We're in standard coordinates. columnPerm_[3 * (n - nTouched) - 3] = 7 * k + 4; columnPerm_[3 * (n - nTouched) - 2] = 7 * k + 5; columnPerm_[3 * (n - nTouched) - 1] = 7 * k + 6; columnPerm_[3 * n + 4 * (n - nTouched) - 4] = 7 * k; columnPerm_[3 * n + 4 * (n - nTouched) - 3] = 7 * k + 1; columnPerm_[3 * n + 4 * (n - nTouched) - 2] = 7 * k + 2; columnPerm_[3 * n + 4 * (n - nTouched) - 1] = 7 * k + 3; } ++nTouched; } delete[] touched; delete[] used; } // At this point we have filled the columnPerm_ array // (except for the final columns for additional constraints // from LPConstraint, which we will deal with later). // // Now go ahead and actually move the columns around accordingly. int* tmp = new int[eqns_->columns()]; std::copy(columnPerm_, columnPerm_ + eqns_->columns(), tmp); for (i = 0; i < eqns_->columns(); ++i) { // Column tmp[i] of the matrix should be moved to // column i. if (tmp[i] == i) continue; eqns_->swapColumns(i, tmp[i]); // Adjust links to the old column i, which is now column tmp[i]. for (j = i + 1; j < eqns_->columns(); ++j) if (tmp[j] == i) break; // This is the link we need to change. #ifdef REGINA_VERIFY_LPDATA if (j == eqns_->columns()) { std::cerr << "ERROR: Sorting error." << std::endl; ::exit(1); } #endif tmp[j] = tmp[i]; tmp[i] = i; } delete[] tmp; // If we have extra variables for additional constraints or // objectives, append the corresponding entries to the end of // the permutation for completeness. for (i = 0; i < LPConstraint::nConstraints; ++i) columnPerm_[cols_ - i - 1] = cols_ - i - 1; } #endif template void LPData::initStart() { // In this routine we rely on the fact that the // LPInitialTableaux constructor ensures that the original // tableaux has full rank. // Begin at the original tableaux, with no row operations performed // and with all equations having a right-hand side of zero. rowOps_.initIdentity(origTableaux_->rank()); std::fill(rhs_, rhs_ + origTableaux_->rank(), 0); rank_ = origTableaux_->rank(); octPrimary_ = -1; // From here, find any feasible basis. findInitialBasis(); // Since RHS = 0, this basis is already feasible. feasible_ = true; // Finally, enforce our additional linear constraints. // This might break feasibility. LPConstraint::constrain(*this, origTableaux_->columns()); } template void LPData::initClone(const LPData& parent) { // If the parent tableaux is infeasible, mark this tableaux as // infeasible also and abort. feasible_ = parent.feasible_; if (! feasible_) return; // The parent tableaux is feasible: clone all of its data. std::copy(parent.rhs_, parent.rhs_ + parent.rank_, rhs_); rowOps_.initClone(parent.rowOps_); rank_ = parent.rank_; memcpy(basis_, parent.basis_, parent.rank_ * sizeof(int)); memcpy(basisRow_, parent.basisRow_, origTableaux_->columns() * sizeof(int)); octPrimary_ = parent.octPrimary_; octSecondary_ = parent.octSecondary_; } template void LPData::constrainZero(unsigned pos) { // If the variable has already been deactivated, there is // nothing to do. if (! isActive(pos)) return; // If the system is infeasible beforehand, it will certainly // be infeasible afterwards. In this case, abort. if (! feasible_) return; // If we ever do something that *might* make the basis // infeasible, we will set perhapsInfeasible to true as a // reminder to fix things later. bool perhapsInfeasible = false; // Is the variable currently in the basis? If so, get it out. if (basisRow_[pos] >= 0) { int r = basisRow_[pos]; int c; if (rhs_[r].isZero()) { // We can pivot in any other variable that appears in // this basis row. Choose the one with largest index. for (c = origTableaux_->columns() - 1; c >= 0; --c) if (basisRow_[c] < 0 /* c is active and non-basic */ && entrySign(r, c)) break; if (c >= 0) { pivot(pos, c); // Because rhs_[r] == 0, this pivot can never create // infeasibility. } else { // There are no other variables in this basis row! // Our equation just looks like x_pos = 0. // // This means that, if we deactivate pos, we lose rank // and we need to delete the corresponding row entirely. --rank_; // "Delete" the row by moving it to index rank_, which // is now outside our scope of interest (since we are // now only interested in rows 0,...,rank_-1). if (r != rank_) { std::swap(rhs_[r], rhs_[rank_]); rowOps_.swapRows(r, rank_); basis_[r] = basis_[rank_]; basisRow_[basis_[r]] = r; } // This column is already filled with zeroes // from row 0 to rank_-1, because pos was in the basis. // If we're in paranoid mode, check this. #ifdef REGINA_VERIFY_LPDATA for (r = 0; r < rank_; ++r) if (! entry(r, pos).isZero()) { std::cerr << "VERIFY: Drop error." << std::endl; ::exit(1); } #endif } } else { // Because the system is feasible, we have rhs_[r] > 0. // This means we can only pivot in a variable with positive // coefficient in this basis row. If there is one, // choose the one with largest index. If there is // no such variable, the entire system becomes infeasible. for (c = origTableaux_->columns() - 1; c >= 0; --c) if (basisRow_[c] < 0 /* c is active and non-basic */ && entrySign(r, c) > 0) break; if (c < 0) { // There is no possible variable to pivot in. // The system must be infeasible. feasible_ = false; return; } pivot(pos, c); // The pivot *might* have made the new basis infeasible. // Remember this so we can fix things afterwards. perhapsInfeasible = true; } } // The variable is out of the basis. Deactivate the column // (which simply means setting basisRow to some non-negative // integer). basisRow_[pos] = 0; #ifdef REGINA_VERIFY_LPDATA verify(); #endif // The variable is gone, but we might have pivoted to an // infeasible basis. If this is a possibility, then move to a // feasible basis if we can. If we cannot, then makeFeasible() // will detect this and set \a feasible_ to \c false. if (perhapsInfeasible) makeFeasible(); #ifdef REGINA_VERIFY_LPDATA verify(); #endif } template void LPData::constrainPositive(unsigned pos) { // If the variable has already been deactivated, it cannot // be positive. if (! isActive(pos)) { feasible_ = false; return; } // If the system is infeasible beforehand, it will certainly // be infeasible afterwards. In this case, abort. if (! feasible_) return; // Just replace x with (1+x'), where now x' must be non-negative. // This corresponds to subtracting column pos of this tableaux // from the right-hand side. // If there is any possibility that some entry on the // right-hand side could become negative, we must remember to // pivot back to feasibility. int r = basisRow_[pos]; Integer tmp; if (r >= 0) { // This variable is in the basis, and so there is only // one non-zero entry in column pos. // This makes subtracting column pos from rhs_ very easy // (just a single operation): entry(r, pos, tmp); if ((rhs_[r] -= tmp) < 0) makeFeasible(); } else { // This variable is not in the basis. // We know nothing about the column, so just do a full // element-by-element column subtraction. for (r = 0; r < rank_; ++r) { entry(r, pos, tmp); rhs_[r] -= tmp; } makeFeasible(); } } template void LPData::constrainOct( unsigned quad1, unsigned quad2) { // If either variable has already been deactivated, it cannot // be positive. if (! (isActive(quad1) && isActive(quad2))) { feasible_ = false; return; } // If the system is infeasible beforehand, it will certainly // be infeasible afterwards. In this case, abort. if (! feasible_) return; // Suppose we choose to count octagons using column i, and // to zero out and deactivate column j (where i and j are // quad1 and quad2 in some order). Then our tasks are to: // // (i) Set x_i = x_j, by replacing the variable x_j with // x_j' = x_j - x_i; // (ii) If we have any additional linear constraints through // the template parameter LPConstraints, adjust the // coefficients in columns i and/or j if necessary to // reflect the presence of octagons (recalling that the // coefficients for an octagon type need not be the sum // of coefficients for the corresponding two // quadrilateral types); // (iii) Set x_i >= 1 and x_j' = 0. // // We do this as follows: // // (i) Add column j to column i; // (ii) Add or subtract further multiples of the final column(s) // to/from column i to reflect any change in coefficients; // (iii) Call constrainZero(j) and constrainPositive(i). // // We perform steps (i) and (ii) just by setting octPrimary_ and // octSecondary_ (this works because the implementation of entry() // adjusts its results according to the current values of // octPrimary_ and octSecondary_). However, if we change a // column corresponding to a basic variable then we must // remember to reorganise the tableaux so that the column once // again contains all zeroes except for a single positive entry. int row1 = basisRow_[quad1]; int row2 = basisRow_[quad2]; if (row1 < 0) { if (row2 < 0) { // Both variables are non-basic. // We will use quad1 to count octagons. // First adjust the columns in the tableaux... octPrimary_ = quad1; octSecondary_ = quad2; // ... and then constrain variables as required. // Since quad2 is non-basic, it is already zero so // we can simply deactivate it. basisRow_[quad2] = 0; constrainPositive(quad1); } else { // quad1 is non-basic, but quad2 is basic. // Once again we will use quad1 to count octagons. // First adjust the columns in the tableaux... octPrimary_ = quad1; octSecondary_ = quad2; // ... and then constrain variables as required. // This time quad2 might be non-zero, so we need to // call the more expensive constrainZero(quad2). constrainZero(quad2); constrainPositive(quad1); } } else if (row2 < 0) { // quad2 is non-basic, but quad1 is basic. // This time we will use quad2 to count octagons. // Do what we did in the previous case, but the other way // around. // First adjust the columns in the tableaux... octPrimary_ = quad2; octSecondary_ = quad1; // ... and then constrain variables as required. constrainZero(quad1); constrainPositive(quad2); } else { // Both quad1 and quad2 are basic. // // Because we might need to adjust columns to reflect changes // in our additional linear constraints, whichever column we // keep could change in any crazy way. We will need to adjust // things to make sure it looks like a basis column once again. // For no particular reason, let's choose to count // octagons using quad1, and eventually drop quad2. // It's going to be messy whichever we choose. // Adjust column quad1 now. octPrimary_ = quad1; octSecondary_ = quad2; // Although quad1 is in the basis, its column could now // look like anything. We need to repair it so it // contains all zeroes except for cell (row1, quad1), // which must be strictly positive. Integer e1; entry(row1, quad1, e1); if (! e1.isZero()) { // The (row1, quad1) entry is non-zero. // It's clear what to do from here: make sure // this entry is positive, perform row operations to // clear out the rest of column quad1, and then restore // feasibility. if (e1 < 0) { e1.negate(); rhs_[row1].negate(); rowOps_.negateRow(row1); } Integer coeff, gcdRow; for (int r = 0; r < rank_; ++r) { if (r == row1) continue; // We will reuse coeff, to avoid too many temporary Integers. // We first set coeff here, and then we reuse and alter it // within the IF block below. entry(r, quad1, coeff); if (! coeff.isZero()) { gcdRow = rowOps_.combRowAndNorm(e1, r, coeff, row1); // As usual, we already know in advance that // gcdRow must divide into rhs_[r]. rhs_[r] *= e1; coeff *= rhs_[row1]; rhs_[r] -= coeff; rhs_[r].divByExact(gcdRow); } } makeFeasible(); // Right: that takes care of the column adjustments. // Now constrain the variables as required. constrainZero(quad2); constrainPositive(quad1); } else { // The (row1, quad1) entry is now zero. // Our solution here is to get quad1 out of the basis. // Try to find some other non-zero coefficient in row1; // note that the only possible locations for another // non-zero coefficient are in non-basic columns. // Choose the column with largest index. int c; for (c = origTableaux_->columns() - 1; c >= 0; --c) if (basisRow_[c] < 0 /* active and non-basic */ && entrySign(row1, c)) break; if (c >= 0) { // We've found an alternative. // Pivot quad1 out of the basis, and put column c // in its place. pivot(quad1, c); // We now have a basis again with a corresponding // tableaux, but the pivot may have broken feasibility. makeFeasible(); // This takes care of the column adjustments. // Now constrain the variables as required. constrainZero(quad2); constrainPositive(quad1); } else { // Every single entry in this row is zero! // // If rhs_[row1] == 0, this is a tautology. // If rhs_[row1] != 0, this is an impossibility. if (rhs_[row1] != 0) { feasible_ = false; } else { // Just pull quad1 out of the basis. Since // the rank drops, we don't need another // variable to replace it. basisRow_[quad1] = -1; // Move the empty row out of the active area // of the matrix. --rank_; if (row1 != rank_) { std::swap(rhs_[row1], rhs_[rank_]); rowOps_.swapRows(row1, rank_); basis_[row1] = basis_[rank_]; basisRow_[basis_[row1]] = row1; } // Since the RHS did not change, the system // is still feasible. // Constrain the variables as required. constrainZero(quad2); constrainPositive(quad1); } } } } } template void LPData::dump(std::ostream& out) const { unsigned r, c; out << "========================" << std::endl; for (r = 0; r < rank_; ++r) out << basis_[r] << ' '; out << std::endl; out << "========================" << std::endl; for (r = 0; r < rank_; ++r) { for (c = 0; c < origTableaux_->columns(); ++c) out << entry(r, c) << ' '; out << std::endl; } out << "========================" << std::endl; } template void LPData::extractSolution( NRay& v, const char* type) const { // Fetch details on how to undo the column permutation. const int* columnPerm = origTableaux_->columnPerm(); // We will multiply the solution vector by // lcm(basis coefficients in the tableaux), which will // ensure that the variables will all be integers. // This multiple might be too large, but we will shrink the // vector down again at the end of this routine. // // First compute this lcm. unsigned i; NLargeInteger lcm(1); for (i = 0; i < rank_; ++i) lcm = lcm.lcm(NLargeInteger(entry(i, basis_[i]))); // Now compute (lcm * the solution vector). We do not yet // take into account the change of variables x_i -> x_i - 1 // that occurred each time we called constrainPositive(), // or the more complex changes of variables that occurred // each time we called constrainOct(). // // All non-basic variables will be zero (and so we do // nothing, since the precondition states that they are // already zero in \a v). // // For basic variables, compute the values from the tableaux. // Because we are multiplying everything by lcm, the // divisions in the following code are all perfectly safe // (and give precise integer results). NLargeInteger coord; for (i = 0; i < rank_; ++i) { if (basis_[i] >= v.size()) continue; coord = lcm; coord *= NLargeInteger(rhs_[i]); coord /= NLargeInteger(entry(i, basis_[i])); v.setElement(columnPerm[basis_[i]], coord); } // Now we take into account the changes of variable due // to past calls to constrainPositive(), as described above. // Since we have multiplied everything by lcm, instead of // adding +1 to each relevant variable we must add +lcm. size_t pos; if (origTableaux_->coords() == NS_ANGLE) { if (type) { // For taut angle structures, the only coordinate that is explicitly // constrained to be positive is the final scaling coordinate. // Even better, this coordinate is never moved by the column // permutation. pos = 3 * origTableaux_->tri()->getNumberOfTetrahedra(); v.setElement(pos, v[pos] + lcm); } else { // For strict angle structures, we pass type == 0, and we // constrain *all* coordinates as positive. for (pos = 0; pos <= 3 * origTableaux_->tri()->getNumberOfTetrahedra(); ++pos) v.setElement(pos, v[pos] + lcm); } } else { // For normal and almost normal surfaces, we need to work through // each past call to constrainPositive() and/or constrainOct(). const unsigned long nTets = origTableaux_->tri()->getNumberOfTetrahedra(); // First take into account the quadrilateral types... for (i = 0; i < nTets; ++i) if (type[i] && type[i] < 4) { pos = columnPerm[3 * i + type[i] - 1]; v.setElement(pos, v[pos] + lcm); } // ... and then the triangle types. for (i = 3 * nTets; i < v.size(); ++i) if (type[i - 2 * nTets]) { pos = columnPerm[i]; v.setElement(pos, v[pos] + lcm); } // Next take into account the changes of variable due to // past calls to constrainOct(). if (octPrimary_ >= 0) { pos = columnPerm[octPrimary_]; v.setElement(pos, v[pos] + lcm); v.setElement(columnPerm[octSecondary_], v[pos]); } } // To finish, divide through by the gcd so we have the // smallest multiple that is an integer vector. v.scaleDown(); } template void LPData::pivot(unsigned outCol, unsigned inCol) { unsigned defRow = basisRow_[outCol]; basisRow_[outCol] = -1; basisRow_[inCol] = defRow; basis_[defRow] = inCol; // Make sure that inCol has a positive coefficient in row defRow. Integer base; entry(defRow, inCol, base); if (base < 0) { base.negate(); rhs_[defRow].negate(); rowOps_.negateRow(defRow); } // Walk through the entire tableaux and perform row operations // to ensure that the only non-zero entry in column \a inCol // is the entry base in row defRow (as extracted above). Integer coeff, gcdRow; unsigned r; for (r = 0; r < rank_; ++r) { if (r == defRow) continue; // We will reuse coeff, to avoid too many temporary Integers. // We first set coeff here, and then we reuse and alter it within the // IF block below. entry(r, inCol, coeff); if (! coeff.isZero()) { // Perform the row operation on the matrix... gcdRow = rowOps_.combRowAndNorm(base, r, coeff, defRow); // ... and on the right-hand side also. // We already know that gcdRow must divide into rhs_[r], // since rhs_ is obtained by multiplying the integer // matrix rowOps_ with an integer vector. rhs_[r] *= base; coeff *= rhs_[defRow]; rhs_[r] -= coeff; rhs_[r].divByExact(gcdRow); } } } template void LPData::findInitialBasis() { // Start with all variables active but non-basic. std::fill(basisRow_, basisRow_ + origTableaux_->columns(), -1); // We find our initial basis using Gauss-Jordan elimination. // Until we sit down and prove some results about the magnitude of // the intermediate integers that appear, we will need to do this // entire process using the arbitrary-precision NInteger class. // We do not touch rhs_ at all, since our preconditions ensure that // rhs_ is the zero vector. // Temporary matrices: // tab = begins as starting tableaux, becomes identity in the basis columns. // ops = begins as identity matrix, becomes the final row operation matrix. // Build a dense copy of the starting tableaux, which we // will work with as we perform our Gauss-Jordan elimination. LPMatrix tab(rank_, origTableaux_->columns()); origTableaux_->fillInitialTableaux(tab); LPMatrix ops(rank_, rank_); ops.initIdentity(rank_); // Off we go with our Gauss-Jordan elimination. // Since the original tableaux is full rank, we know in // advance that every row will define some basic variable. unsigned row; unsigned r, c; NInteger base, coeff; NInteger gcdRow; for (row = 0; row < rank_; ++row) { // Find the first non-zero entry in this row. // The corresponding column will become our next basic variable. for (c = 0; c < origTableaux_->columns(); ++c) if (basisRow_[c] < 0 /* non-basic variable */ && ! tab.entry(row, c).isZero()) break; // Since the original tableaux has full rank, we must // have found a non-zero entry. However, for sanity, // add some code to deal with the situation where we did not. if (c == origTableaux_->columns()) { // Impossible, assuming the matrix had the correct rank... #ifdef REGINA_VERIFY_LPDATA std::cerr << "ERROR: No initial basis, bad rank." << std::endl; ::exit(1); #endif // ... but deal with it anyway by just dropping rank. --rank_; if (row != rank_) { tab.swapRows(row, rank_); ops.swapRows(row, rank_); } --row; // We will ++row again for the next loop iteration. continue; } // Here is our non-zero entry. // Make this a basis variable. basis_[row] = c; basisRow_[c] = row; // Make the corresponding non-zero entry positive. base = tab.entry(row, c); if (base < 0) { base.negate(); tab.negateRow(row); ops.negateRow(row); } // Make sure this basis variable has zero coefficients // in all other rows. for (r = 0; r < rank_; ++r) { if (r == row) continue; coeff = tab.entry(r, c); if (! coeff.isZero()) { gcdRow = ops.combRowAndNorm(base, r, coeff, row); tab.combRow(base, r, coeff, row, gcdRow); } } } // Copy the final tableaux into our own rowOps_ matrix. for (r = 0; r < rank_; ++r) for (c = 0; c < rank_; ++c) rowOps_.entry(r, c) = Integer(ops.entry(r, c)); } template void LPData::makeFeasible() { int r, c, outCol, outRow; Integer outEntry, tmp, v1, v2; // Variables for detecting cycling. // // The bits in oldBasis are a snapshot of which variables were in // the basis at some point in the past, and the bits in currBasis // indicate which variables are in the basis right now. // // We use Brent's method for detecting cycles: // We store a snapshot in oldBasis after 2^k pivots, for all k. // This means that, regardless of the length of the cycle or // the number of pivots that precede the cycle, we will // detect oldBasis == currBasis shortly after cycling occurs // (in particular, the total number of pivots that we take // overall is at most three times the total number of pivots // before the first repeated basis). unsigned nCols = origTableaux_->columns(); NBitmask currBasis(nCols); for (r = 0; r < rank_; ++r) currBasis.set(basis_[r], true); NBitmask oldBasis(currBasis); unsigned long pow2 = 1; unsigned long nPivots = 0; while (true) { // Locate a variable in the basis with negative value. // If there are many, choose the variable with largest // magnitude negative value. outCol = -1; for (r = 0; r < rank_; ++r) if (rhs_[r] < 0) { if (outCol < 0) { // First candidate we've seen. // Use it until we find something better. outRow = r; outCol = basis_[r]; entry(r, outCol, outEntry); continue; } // Compare which variable is most negative. entry(r, basis_[r], tmp); v1 = rhs_[r]; v1 *= outEntry; // Avoid spurious temporaries. v2 = rhs_[outRow]; v2 *= tmp; // Avoid spurious temporaries. if (v1 < v2) { outRow = r; outCol = basis_[r]; outEntry = tmp; } } if (outCol < 0) { // All basis variables are non-negative! // This is a feasible basis; we're done. return; } // Fix this bad variable by pivoting it out. // The pivot-in variable must be the largest-index // column with negative coefficient in this row. for (c = nCols - 1; c >= 0; --c) if (basisRow_[c] < 0 /* active, non-basic variable */ && entrySign(outRow, c) < 0) break; if (c < 0) { // There is no possible variable to pivot in. // The system is infeasible. feasible_ = false; return; } pivot(outCol, c); // Run our cycle-detection machinery. currBasis.set(outCol, false); currBasis.set(c, true); if (currBasis == oldBasis) { // We've cycled! // Switch to a slower but cycle-free pivot rule. makeFeasibleAntiCycling(); return; } if (++nPivots == pow2) { oldBasis = currBasis; pow2 <<= 1; // On a modern (64-bit) system, pow2 will only overflow // after something like 10^19 pivots, and the human // will have given up in frustration long before this. // Nevertheless, make sure things work even in this case: if (! pow2) { makeFeasibleAntiCycling(); return; } } } } template void LPData::makeFeasibleAntiCycling() { int r, c, outCol; while (true) { // Locate a variable in the basis with negative value. // If there are many, choose the one with largest index. outCol = -1; for (r = 0; r < rank_; ++r) if (rhs_[r] < 0) { if (basis_[r] > outCol) outCol = basis_[r]; } if (outCol < 0) { // All basis variables are non-negative! // This is a feasible basis; we're done. return; } // Fix this bad variable by pivoting it out. // The pivot-in variable must be the largest-index // column with negative coefficient in this row. for (c = origTableaux_->columns() - 1; c >= 0; --c) if (basisRow_[c] < 0 /* active, non-basic variable */ && entrySign(basisRow_[outCol], c) < 0) break; if (c < 0) { // There is no possible variable to pivot in. // The system is infeasible. feasible_ = false; return; } pivot(outCol, c); } } template void LPData::verify() const { unsigned r, c; for (r = 0; r < rank_; ++r) { // Check that rowOps_ is an inverse matrix. for (c = 0; c < rank_; ++c) if (r != c && entrySign(r, basis_[c])) { std::cerr << "VERIFY: Inverse error" << std::endl; ::exit(1); } // Check that each row has gcd = 1. Integer g; // Initialised to zero. for (c = 0; c < rowOps_.columns(); ++c) g.gcdWith(rowOps_.entry(r, c)); if (g != 1) { std::cerr << "VERIFY: GCD error" << std::endl; ::exit(1); } } } } // namespace regina #endif regina-4.96/engine/enumerate/ntreelp.cpp000644 000765 000024 00000006204 12377776605 020245 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 2011-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "enumerate/ntreelp-impl.h" namespace regina { // Instantiate templates: template class LPInitialTableaux; template class LPInitialTableaux; #ifndef EXCLUDE_SNAPPEA template class LPInitialTableaux; #endif template class LPData; template class LPData; template class LPData; template class LPData; #ifndef EXCLUDE_SNAPPEA template class LPData; template class LPData; #endif #ifdef INT128_AVAILABLE template class LPData >; template class LPData >; #ifndef EXCLUDE_SNAPPEA template class LPData >; #endif #endif } // namespace regina regina-4.96/engine/enumerate/ntreelp.h000644 000765 000024 00000223663 12377775145 017722 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 2011-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file enumerate/ntreelp.h * \brief Linear programming code for tree traversal enumeration methods. */ #ifndef __NTREELP_H #ifndef __DOXYGEN #define __NTREELP_H #endif #include "maths/ninteger.h" #include "maths/nmatrixint.h" #include "surfaces/normalcoords.h" #include /** * Define REGINA_VERIFY_LPDATA to check invariants as the algorithm runs. * This checking is slow and can increase the running time significantly. */ // #define REGINA_VERIFY_LPDATA namespace regina { class NMatrixInt; class NRay; class NTriangulation; /** * \weakgroup enumerate * @{ */ /** * A matrix class for use with linear programming. * * This class is used in the tree traversal algorithms for enumerating * and locating vertex normal surfaces, as described in "A tree traversal * algorithm for decision problems in knot theory and 3-manifold topology", * Burton and Ozlen, Algorithmica 65:4 (2013), pp. 772-801, * and "A fast branching algorithm for unknot recognition with * experimental polynomial-time behaviour", Burton and Ozlen, arXiv:1211.1079. * It is also used for locating a single strict angle structure, and for * enumerating all taut angle structures. * * The operations on this matrix class are tailored and optimised * specifically for use with the dual simplex method in the context * of a repetitive backtracking search. As a result, the API is * cumbersome and highly specialised, which makes this matrix class * inappropriate for general use. * * It is \e critical that, before using such a matrix, you reserve space * for its elements, and then fix a specific size. A matrix for which * both tasks have been done will be called \a initialised. You can * initialise a matrix in one of two ways: * * - by using the (\a rows, \a columns) constructor, which does * everything for you; * * - by using the default (no-arguments) constructor, then calling reserve(), * and then calling one of the initialisation routines initClone() or * initIdentity(). * * You may call the initialisation initClone() and initIdentity() routines * more than once (e.g., during a backtracking search), and you may use * different matrix sizes each time. However, you may never use more * elements than you originally reserved space for. * * This matrix is stored in dense form. All elements are of the integer class * \a Integer, which is supplied as a template argument. * * \pre The default constructor for the template class Integer must intialise * each new integer to zero. The classes NInteger and NNativeInteger, * for instance, have this property. * * \apinotfinal * * \ifacespython Not present. */ template class LPMatrix { private: Integer* dat_; /**< The elements of this matrix as a single long array, stored in row-major order. This array stores as many elements as were originally reserved, which might be more than (but can never be less than) the current size of the matrix according to \a rows_ and \a cols_. */ unsigned rows_; /**< The number of rows in this matrix. */ unsigned cols_; /**< The number of columns in this matrix. */ public: /** * Creates an uninitialised matrix with no memory storage. * * You \e must call reserve() and then either initClone() or * initIdentity() before this matrix will become initialised. */ inline LPMatrix(); /** * Creates a fully initialised \a rows by \a cols matrix * with all elements set to zero. * * This routine reserves space for precisely \a rows * \a cols * elements. In other words, you may later re-initialise the matrix * to become smaller if you like, but you cannot re-initialise the * matrix to become larger. * * @param rows the number of rows in the new matrix. This must * be strictly positive. * @param cols the number of columns in the new matrix. This must * be strictly positive. */ inline LPMatrix(unsigned rows, unsigned cols); /** * Destroys this matrix and all of the data it contains. * * You can safely destroy a matrix that is uninitialised * or only partially initialised (i.e., space has been reserved but * the matrix size is not set). */ inline ~LPMatrix(); /** * Reserves enough space to store the elements of a * \a maxRows by \a maxCols matrix. This is just an upper * bound: your matrix may end up using fewer elements than this, * but it cannot use more. * * This matrix will still not be initialised until you call * either initClone() or initIdentity(). See the class notes for * details. * * \pre This matrix was created using the default (no-argument) * constructor, and you have not called any other routines on * this matrix since. * * \warning To elaborate on the precondition above: you can only * call reserve() once, and if you did not use the default * LPMatrix constructor then you cannot call it at all. * Any additional calls to reserve() will result in a memory leak. * * @param maxRows an upper bound on the number of rows that you * will need for this matrix. This must be strictly positive. * @param maxCols an upper bound on the number of columns that * you will need for this matrix. This must be strictly positive. */ inline void reserve(unsigned maxRows, unsigned maxCols); /** * Initialises this matrix to a copy of the given matrix. * * This matrix does not yet need to be initialised, but it does * need to have enough space reserved. * * You may call this routine on an already-initialised matrix, * and you may use this routine to assign it a different size * (as long as enough space was originally reserved). * * \pre If this matrix has not been initialised before, then * reserve() must have already been called. * * \pre This matrix has enough space reserved for at least * clone.rows() * clone.columns() elements. * * @param clone the matrix to copy. */ inline void initClone(const LPMatrix& clone); /** * Initialises this matrix to the identity matrix of the given size. * * This matrix does not yet need to be initialised, but it does * need to have enough space reserved. * * You may call this routine on an already-initialised matrix, * and you may use this routine to assign it a different size * (as long as enough space was originally reserved). * * \pre If this matrix has not been initialised before, then * reserve() must have already been called. * * \pre This matrix has enough space reserved for at least * \a size * \a size elements. * * @param size the number of rows, and also the number of * columns, that will be assigned to this matrix. * This must be strictly positive. */ void initIdentity(unsigned size); /** * Returns a read-write reference to the given element of this * matrix. * * @param row the row of the requested element. This must be * between 0 and rows()-1 inclusive. * @param col the column of the requested element. This must be * between 0 and columns()-1 inclusive. */ inline Integer& entry(unsigned row, unsigned col); /** * Returns a read-only reference to the given element of this * matrix. * * @param row the row of the requested element. This must be * between 0 and rows()-1 inclusive. * @param col the column of the requested element. This must be * between 0 and columns()-1 inclusive. */ inline const Integer& entry(unsigned row, unsigned col) const; /** * Returns the number of rows in this matrix. This relates to * the currently assigned matrix size, not the total amount of * memory that was originally reserved. * * @return the number of rows. */ inline unsigned rows() const; /** * Returns the number of columns in this matrix. This relates to * the currently assigned matrix size, not the total amount of * memory that was originally reserved. * * @return the number of columns. */ inline unsigned columns() const; /** * Swaps the two given rows of this matrix. * The two arguments \a r1 and \a r2 may be equal (in which case * the matrix will be left unchanged). * * @param r1 the index of the first row to swap. This must be * between 0 and rows()-1 inclusive. * @param r2 the index of the second row to swap. This must be * between 0 and rows()-1 inclusive. */ inline void swapRows(unsigned r1, unsigned r2); /** * Applies a particular row operation to this matrix. * * Specifically, row \a dest will be replaced with the linear * combination: * (\a destCoeff * row \a dest - \a srcCoeff * row \a src) / \a div. * * \pre \a dest and \a src are not equal. * \pre It is known in advance that every integer in * (\a destCoeff * row \a dest - \a srcCoeff * row \a src) * will be divisible by \a div. In other words, it is known in * advance that we can use exact integer division without remainders. * * @param destCoeff the coefficient applied to row \a dest in * the linear combination. * @param dest the index of the row to replace. This must be * between 0 and rows()-1 inclusive. * @param srcCoeff the coefficient applied to row \a src in * the linear combination. * @param src the index of the other row used in this linear * combination. This must be between 0 and rows()-1 inclusive. * @param div the integer to divide the final row by. This must * be non-zero. */ inline void combRow(const Integer& destCoeff, unsigned dest, const Integer& srcCoeff, unsigned src, const Integer& div); /** * Applies a particular row operation to this matrix, and then * normalises. * * Specifically, row \a dest will be replaced with the linear * combination: * (\a destCoeff * row \a dest - \a srcCoeff * row \a src); * then, if row \a dest is non-zero, it will be normalised by * dividing through by the gcd of its elements. Note that this gcd * is always taken to be positive (i.e., the final normalisation * will never change the signs of the elements in the row). * * \pre \a dest and \a src are not equal. * * @param destCoeff the coefficient applied to row \a dest in * the linear combination. * @param dest the index of the row to replace. This must be * between 0 and rows()-1 inclusive. * @param srcCoeff the coefficient applied to row \a src in * the linear combination. * @param src the index of the other row used in this linear * combination. This must be between 0 and rows()-1 inclusive. * @return the positive gcd that row \a dest was scaled down by, * or 0 if row \a dest is entirely zero. */ inline Integer combRowAndNorm(const Integer& destCoeff, unsigned dest, const Integer& srcCoeff, unsigned src); /** * Negates all elements in the given row of this matrix. * * @param row the row whose elements should be negated. * This must be between 0 and rows()-1 inclusive. */ inline void negateRow(unsigned row); /** * Writes this matrix to the given output stream. * The output is "rough" and wasteful, and is intended for * debugging purposes only. The precise output format is * subject to change in future versions of Regina. * * @param out the output stream to write to. */ void dump(std::ostream& out) const; }; /** * Stores an adjusted matrix of homogeneous linear matching equations based on * a given triangulation, in sparse form. Typically these will be * the normal surface matching equations in some coordinate system, * or the angle structure equations. * * This class forms part of the tree traversal algorithms for enumerating * and locating normal surfaces, as described in "A tree traversal algorithm * for decision problems in knot theory and 3-manifold topology", * Burton and Ozlen, Algorithmica 65:4 (2013), pp. 772-801, * and "A fast branching algorithm for unknot recognition with * experimental polynomial-time behaviour", Burton and Ozlen, arXiv:1211.1079. * It is also used for locating a single strict angle structure, and for * enumerating all taut angle structures. * * The adjustments (which are all carried out in the LPInitialTableaux * class constructor) are as follows: * * - the rows of the matching equation matrix have been reordered so * that the first rank() rows are full rank; * - the columns of the matching equation matrix have been reordered * according to the permutation returned by columnPerm(). This is a * heuristic reordering designed to improve the performance of the tree * traversal algorithm; see columnPerm() for a list of constraints that * such a reordering must satisfy. * * There is also optional support for adding extra linear constraints (such as * a constraint on Euler characteristic for normal surfaces). These extra * constraints are supplied by the template parameter \a LPConstraint, * and will generate LPConstraint::nConstraints additional rows and columns * (used by the additional variables that evaluate the corresponding linear * functions). If there are no additional constraints, simply use the * template parameter LPConstraintNone. * * In some cases, it may be impossible to add the extra linear constraints * that you would like (for instance, the constraints might require some * preconditions on the underlying triangulation that are not met). If this * is a possibility in your setting, you should call constraintsBroken() to * test this as soon as the LPInitialTableaux has been constructed. Even if * the constraints could not be added correctly, the tableaux will be left in a * consistent state (the constraints will just be treated as zero functions * instead). * * This class is optimised for working with \e columns of the matrix * (in particular, multiplying columns of this matrix by rows of some * other matrix). * * This class can only work in quadrilateral normal coordinates (NS_QUAD), * standard normal coordinates (NS_STANDARD), or angle structure coordinates * (NS_ANGLE). No other coordinate systems are supported. * * \warning The implementation of this class relies on the fact that the * sum of absolute values of all coefficients in each column is * at most four (not counting the rows for any optional extra constraints). * If you are extending this class to work with more general matching * equation matrices, you may need to change the implementation accordingly. * * \pre The template parameter LPConstraint must be one of the subclasses of * LPConstraintBase. See the LPConstraintBase class notes for further details. * * \apinotfinal * * \ifacespython Not present. */ template class LPInitialTableaux { public: /** * Stores a single column of the adjusted matching equation matrix * in sparse form. * * Specifically, this stores the location of each +1 entry, * and the location of each -1 entry. If some entry in the matrix * is greater than +1 or less than -1, we represent it using * multiple +1 or -1 entries in the same matrix location. * * For any additional rows that represent extra linear constraints, * we inherit the coefficients directly from LPConstraint::Coefficients. */ struct Col : public LPConstraint::Coefficients { unsigned nPlus; /**< The total number of +1 entries in this column. */ unsigned plus[4]; /**< The rows containing these +1 entries, in any order. The same row may appear in this list more than once (indicating a +2, +3 or +4 entry in the matrix). */ unsigned nMinus; /**< The total number of -1 entries in this column. */ unsigned minus[4]; /**< The rows containing these -1 entries, in any order. The same row may appear in this list more than once (indicating a -2, -3 or -4 entry in the matrix). */ /** * Initialises an empty column. */ inline Col(); /** * Adds the given entry in the given row to this column. * * \pre No entry in the given row has been added to this column * yet. * * \pre The sum of absolute values of all entries in this * column must never exceed 4. * * @param row the row containing the given value. * @param val the value at this location in the matrix. */ inline void push(unsigned row, int val); }; private: const NTriangulation* tri_; /**< The underlying triangulation. */ NormalCoords coords_; /**< The coordinate system used for the matrix of matching equations; this must be one of NS_QUAD, NS_STANDARD, or NS_ANGLE. */ NMatrixInt* eqns_; /**< The adjusted matching equation matrix, in dense form. The precise adjustments that we make are described in the LPInitialTableaux class notes. */ unsigned rank_; /**< The rank of this tableaux, taking into account any additional constraints from the template parameter LPConstraint. */ unsigned cols_; /**< The number of columns in this tableaux, taking into account any additional constraints from the template parameter LPConstraint. */ int scaling_; /**< In angle structure coordinates, the final coordinate is a scaling coordinate used to projectivise the angle structure polytope to become a polyhedral cone. As a result, the final coordinate is given the same coefficient \a scaling_ in every equation. In other words, every entry in column coordinateColumns()-1 of the matrix is equal to \a scaling_. In all normal surface coordinate systems (which do not need to be projectivised), \a scaling_ will be zero. */ Col* col_; /**< An array of size \a cols_ that stores the individual columns of this adjusted matrix in sparse form. In angle structure coordinates, the column col_[coordinateColumns()-1] will be ignored, since this column of the matrix is described by the \a scaling_ member instead. */ int* columnPerm_; /**< A permutation of 0,...,cols_-1 that maps column numbers in the adjusted matrix to column numbers in the original (unmodified) matrix of matching equations that was originally derived from the triangulation. See columnPerm() for more details on what this permutation means and what constraints it must adhere to. */ bool constraintsBroken_; /**< Indicates whether or not the extra constraints from the template parameter \a LPConstraints were added successfully. See the LPInitialTableaux class notes for details. */ public: /** * Construts this adjusted sparse matrix of matching equations. * * \pre The given triangulation is non-empty. * * @param tri the underlying 3-manifold triangulation. * @param coords the coordinate system to use for the matrix of * matching equations; this must be one of NS_QUAD, NS_STANDARD, * or NS_ANGLE. * @param enumeration \c true if we should optimise the tableaux * for a full enumeration of vertex surfaces or taut angle structures, * or \c false if we should optimise the tableaux for an existence test * (such as searching for a non-trivial normal disc or sphere, or * a strict angle structure). */ LPInitialTableaux(const NTriangulation* tri, NormalCoords coords, bool enumeration); /** * Destroys this matrix. */ inline ~LPInitialTableaux(); /** * Returns the underlying 3-manifold triangulation from which the * matching equations were derived. * * @return the underlying triangulation. */ inline const NTriangulation* tri() const; /** * Returns the coordinate system that is used for the matrix of * matching equations. This will be the same coordinate system * that was passed to the LPInitialTableaux constructor; in particular, * it will always be one of NS_QUAD, NS_STANDARD, or NS_ANGLE. * * @return the coordinate system. */ NormalCoords coords() const; /** * Returns the rank of this matrix. * * Note that, if we are imposing extra constraints through the * template parameter LPConstraint, then there will be extra variables * to enforce these, and so the rank will be larger than the rank of * the original matching equation matrix. * * @return the matrix rank. */ inline unsigned rank() const; /** * Returns the number of columns in this matrix. * * Note that, if we are imposing extra constraints through the * template parameter LPConstraint, then there will be extra variables * to enforce these, and so the number of columns will be larger than * in the original matching equation matrix. * * @return the number of columns. */ inline unsigned columns() const; /** * Returns the number of columns that correspond to normal coordinates * or angle structure coordinates. This is precisely the number of * columns in the original matrix of matching equations. * * @return the number of normal or angle structure coordinate columns. */ inline unsigned coordinateColumns() const; /** * Indicates whether or not the extra constraints from the template * parameter \a LPConstraints were added successfully. * This query function is important because some constraints require * additional preconditions on the underlying triangulation, and * cannot be added if these preconditions are not satisfied. * * Even if the extra constraints were not added successfully, this * tableaux will be left in a consistent state (the extra constraints * will be treated as zero functions). See the LPInitialTableaux class * notes for further details. * * @return \c true if the constraints were \e not added * successfully, or \c false if the constraints were added successfully. */ inline bool constraintsBroken() const; /** * Returns the permutation that describes how the columns of * the matching equation matrix were reordered. This permutation maps * column numbers in this adjusted matching equation matrix to * column numbers in the original (unmodified) matching equation * matrix that was originally derived from the triangulation. * * The permutation is returned as an array of columns() integers, * such that column \a i of this adjusted matrix corresponds to * column columnPerm()[i] of the original matrix. * * If you are imposing additional constraints through the * template parameter LPConstraint, then the corresponding extra * variables will be included in the permutation; however, these are * never moved and will always remain the rightmost variables in * this system (i.e., the columns of highest index). * * As well as the requirement that this is a genuine permutation of * 0,...,columns()-1, this array will also adhere to the * following constraints. In the following discussion, \a n refers * to the number of tetrahedra in the underlying triangulation. * * - The quadrilateral coordinate columns must appear as the * first 3n columns of the adjusted matrix. * In particular, when working in the 7n-dimensional * standard normal coordinate system, the remaining 4n * triangle coordinate columns must appear last. * * - The quadrilateral coordinate columns must be grouped by * tetrahedron and ordered by quadrilateral type. In other * words, for each \a i = 0,...,\a n-1, there will be some * tetrahedron \a j for which the three columns * 3i, 3i+1 and 3i+2 refer to the * quadrilaterals in tetrahedron \a j of types 0, 1 and 2 * respectively. Phrased loosely, we are allowed to reorder * the tetrahedra, but not the quadrilateral coordinates * within each tetrahedron. * * - The triangle coordinate columns (if we are working in standard * normal coordinates) must likewise be grouped by tetrahedron, * and these tetrahedra must appear in the same order as for the * quadrilateral types. In other words, for each * \a i = 0,...,\a n-1, the quadrilateral columns * 3i, 3i+1 and 3i+2 and the triangle columns * 3n+4i, 3n+4i+1, 3n+4i+2 * and 3n+4i+3 all refer to the same tetrahedron. * * - For angle structure coordinates, the constraints are analogous to * those for quadrilateral coordinates: the angle coordinates * must be grouped by tetrahedron and ordered by angle type, * and the final scaling coordinate must remain last. * * @return details of the permutation describing how columns * were reordered. */ inline const int* columnPerm() const; /** * Computes the inner product of (i) the given row of the given * matrix with (ii) the given column of this matrix. * * This routine is optimised to use the sparse representation of * columns in this matrix. * * \pre The given matrix \a m has precisely rank() columns. * * @param m the matrix whose row we will use in the inner product. * @param mRow the row of the matrix \a m to use in the inner product. * @param thisCol the column of this matrix to use in the inner product. * @return the resulting inner product. */ template inline Integer multColByRow(const LPMatrix& m, unsigned mRow, unsigned thisCol) const; /** * A variant of multColByRow() that takes into account any adjustments * to the tableaux that are required when this is a quadrilateral * column being used to represent an octagon type. * * The LPData class offers support for octagonal almost normal * surfaces, in which exactly one tetrahedron is allowed to have * exactly one octagon type. We represent such an octagon as a * \e pair of incompatible quadrilaterals within the same tetrahedron. * See the LPData class notes for details on how this works. * * In some settings where we are using additional constraints * through the template parameter LPConstraint, these extra * constraints behave differently in the presence of octagons * (i.e., the coefficient of the octagon type is not just the * sum of coefficients of the two constituent quadrilateral types). * This routine effectively allows us to adjust the tableaux * accordingly. * * Specifically: this routine computes the inner product of * (i) the given row of the given matrix with (ii) the given * column of this matrix. We assume that the given column of * this matrix describes one of the two quadrilateral coordinates * in some tetrahedron that together form an octagon type, and * (via the helper routine LPConstraint::Coefficients::innerProductOct) * we implicitly adjust the coefficients of our extra constraints * accordingly. * * This routine is optimised to use the sparse representation of * columns in this matrix. * * This routine is not used with angle structure coordinates. * * \pre The given matrix \a m has precisely rank() columns. * * \pre Column \a thisCol of this matrix describes one of the * two quadrilateral coordinates that are being combined to form * an octagon type within some tetrahedron. * * @param m the matrix whose row we will use in the adjusted * inner product. * @param mRow the row of the matrix \a m to use in the adjusted * inner product. * @param thisCol the column of this matrix to use in the adjusted * inner product. * @return the resulting adjusted inner product. */ template inline Integer multColByRowOct(const LPMatrix& m, unsigned mRow, unsigned thisCol) const; /** * Fills the given matrix with the contents of this matrix. * This effectively copies this sparse * but highly specialised matrix representation into a dense * but more flexible matrix representation. * * \pre The given matrix has already been initialised to size * rank() * columns(), and all of its elements have already been * set to zero. Note that this can all be arranged by calling * the constructor LPMatrix::LPMatrix(unsigned, unsigned). * * @param m the matrix to fill. */ template void fillInitialTableaux(LPMatrix& m) const; private: /** * Reorders the columns of the matching equation matrix. * This is a heuristic reordering that aims to reduce the number * of dead ends in the tree traversal algorithm, and thereby * improve the running time. * * Details of the reordering will be stored in the array * columnPerm_; see the columnPerm() notes for more information * on the constraints that this reordering is required to satisfy. * * This routine is called before any additional constraints are * added from the template parameter LPConstraint; that is, the * rows of the matrix are just the matching equations. However, * we do already have the extra placeholder columns for the new * variables that correspond to these extra constraint(s). * * @param enumeration \c true if we should optimise the ordering * for a full enumeration of vertex surfaces or taut angle structures, * or \c false if we should optimise the ordering for an existence test * (such as searching for a non-trivial normal disc or sphere, or * a strict angle structure). */ void reorder(bool enumeration); }; /** * Stores an intermediate tableaux for the dual simplex method, and * contains all of the core machinery for using the dual simplex method. * * This class forms part of the tree traversal algorithms for enumerating * and locating normal surfaces, as described in "A tree traversal algorithm * for decision problems in knot theory and 3-manifold topology", * Burton and Ozlen, Algorithmica 65:4 (2013), pp. 772-801, * and "A fast branching algorithm for unknot recognition with * experimental polynomial-time behaviour", Burton and Ozlen, arXiv:1211.1079. * It is also used for locating a single strict angle structure, and for * enumerating all taut angle structures. * * This class is designed to represent a state partway through the tree * traversal algorithm, where the tableaux has been altered to * constrain some variables: * * - Some variables have been "deactivated". This means we fix them to * zero permanently, and pretend that the corresponding columns do not * exist in the matrix. As a result, the rank of the matrix may * smaller than it was when we began the tree traversal. * * - Some variables have been constrained to be positive; as described * in Burton and Ozlen, it is safe to do this using the non-strict * inequality x_i >= 1 (instead of the strict inequality x_i > 0, which * is more difficult to enforce). We enforce this constraing using a * change of variable: we replace the variable x_i with (x_i - 1), * which is then constrained to be non-negative as usual. The new * variable (x_i - 1) uses the same column in the tableaux (we perform * the actual change of variable by editing the tableaux itself using * column operations). Be warned: as a result, when we arrive at a * final solution and collect the values of the variables, we must * remember to \e increment the values of any such variables by one. * * We do not store the full tableaux (which is dense and slow to work * with). Instead we store the matrix of row operations that were * applied to the original starting tableaux (in the notation of Burton * and Ozlen, we store the matrix M_beta^{-1}, where M is the original * matrix stored in the class LPInitialTableaux, and beta is the current * basis). * * If the system is infeasible (because the constraints on variables as * described above are too severe), then the contents of the internal * data members are undefined (other than the data member \a feasible_, * which is guaranteed to be \c false). This is because the code * is optimised to abort any operation as soon as infeasibility is detected, * which may leave the data members in a broken state. If you are not sure, * you should always call isFeasible() before performing any other query * or operation on this tableaux. * * This class is designed to be used in a backtracking search, which * means the API is cumbersome but we can quickly rewrite and copy data. * The rules are as follows: * * - Before using an LPData object, you must reserve the necessary memory * by calling reserve() and passing the original starting tableaux. * * - After this, you can reset the data by calling one of the initialisation * routines initStart() or initClone(), and you can call these * initialisation routines as often as you like. * * Like LPInitialTableaux, this class can enforce additional linear * constraints (such as positive Euler characteristic) through the template * parameter LPConstraint. If there are no such constraints, simply use * the template parameter LPConstraintNone. * * In the context of normal surfaces (not angle structures): * Although the underlying coordinate system is based on quadrilaterals * and (optionally) triangles, this class has elementary support for * octagons also, as seen in \e almost normal surface theory. For the * purposes of this class, an octagon is represented as a pair of * quadrilaterals of different types in the same tetrahedron: these meet * the boundary of the tetrahedron in the same arcs as a single octagon, * and therefore interact with the matching equations in the same way. * * To declare that you will be using octagons in some tetrahedron, you * must call constrainOct(quad1, quad2), where \a quad1 and \a quad2 are the * two corresponding quadrilateral columns. This will have the following * effects, all of which may alter the tableaux: * * - There will be some changes of variable. One of the two variables * x_i will be replaced with (x_i - 1), forcing the number of octagons * to be positive. The other variable x_j will be replaced with * (x_j - x_i), which will be set to zero and deactivated. There is no * guarantee as to which of the two variables \a quad1 and \a quad2 * will be kept and which will be deactivated: this will depend on the * layout of the tableaux when constrainOct() is called. * * - If you are imposing additional constraints through the \a LPConstraint * template parameter, the corresponding linear constraint functions * may change their values (since the coefficients they use for * octagon types need not be related to the coefficients for the two * corresponding quadrilateral columns). Any such changes are managed * through the function LPConstraint::Coefficients::innerProductOct. * * This class has been optimised to ensure that you only have one * octagon type declared at any given time (which is consistent with the * constraints of almost normal surface theory). * * All tableaux elements are of the integer class \a Integer, which is * supplied as a template argument. This same integer class will be * used as a template argument for \a LPConstraint. * * \pre The template parameter LPConstraint must be one of the subclasses of * LPConstraintBase. See the LPConstraintBase class notes for further details. * * \pre The default constructor for the template class Integer must intialise * each new integer to zero. The classes NInteger and NNativeInteger, * for instance, have this property. * * \apinotfinal * * \ifacespython Not present. */ template class LPData { private: const LPInitialTableaux* origTableaux_; /**< The original starting tableaux that holds the adjusted matrix of matching equations, before the tree traversal algorithm began. */ Integer* rhs_; /**< An array of length origTableaux_->rank() that stores the column vector of constants on the right-hand side of the current tableaux. In the notation of Burton and Ozlen, this is the column vector M_beta^{-1} * b. If \a rank_ is smaller than origTableaux_->rank() then the "extra" entries rhs_[rank_, rank_+1, ...] may have undefined values, and should simply be ignored. */ LPMatrix rowOps_; /**< The matrix of row operations that we apply to the original starting tableaux, as described in the class notes. In the notation of Burton and Ozlen, this is the matrix M_beta^{-1}. This is a square matrix of side length origTableaux_->rank(). */ unsigned rank_; /**< The rank of the current tableaux, taking into account any changes such as deactivation of variables. This will be at most (but quite possibly less than) origTableaux_->rank(). We guarantee that the first \a rank_ rows of the current tableaux are full rank (and so any subsequent rows should simply be ignored from here on). */ int* basis_; /**< An array of length origTableaux_->rank() that stores the \a rank_ variables that form the current basis. In particular, for each i = 0,...,rank_-1, basis_[i] is the basis variable whose defining row is row i. If \a rank_ is smaller than origTableaux_->rank() then any trailing entries in this array have undefined values, and should simply be ignored. */ int* basisRow_; /**< An array of length origTableaux_->columns() that indicates which row of the current tableaux holds the defining equation for each basis variable. Specifically: - if column \a i corresponds to a basic variable, then the defining row for this basis variable is row basisRow_[i]; - if column \a i corresponds to an active non-basic variable, then basisRow_[i] will be strictly negative; - if column \a i has been deactivated, then basisRow_[i] will be zero. For each i = 0,...,rank_-1, basisRow_[basis_[i]] == i. */ bool feasible_; /**< Indicates whether or not the current system of constraints is feasible. */ int octPrimary_; /**< If we have declared an octagon type, this stores the column that we use to count the octagons. This will be one of the two quadrilateral columns that together "represent" the octagon type, as described in the class notes. If we have not declared an octagon type (or if we are working with angle structures), this is -1. */ int octSecondary_; /**< If we have declared an octagon type, this stores the second of the two quadrilateral columns that together "represent" the octagon type, as described in the class notes. This is the quadrilateral column that we set to zero and deactivate (as opposed to \a octPrimary_, which we keep to count the number of octagons). If we have not declared an octagon type (or if we are working with angle structures), this variable is undefined. */ public: /** * Constructs a new tableaux. You \e must call reserve() before * doing anything else with this tableaux. */ inline LPData(); /** * Destroys this tableaux. This is safe even if reserve() was * never called. */ inline ~LPData(); /** * Reserves enough memory for this tableaux to work with. * You \e must call this routine before doing anything else with * this tableaux. * * The data in this tableaux will not be initialised, and the * contents and behaviour of this tableaux will remain undefined * until you call one of the initialisation routines initStart() * or initClone(). * * @param origTableaux the original starting tableaux that holds the * adjusted matrix of matching equations, before the tree traversal * algorithm began. */ void reserve(const LPInitialTableaux* origTableaux); /** * Initialises this tableaux by beginning at the original * starting tableaux and working our way to any feasible basis. * * This routine also explicitly enforces the additional constraints * from the template parameter LPConstraint (i.e., this routine * is responsible for forcing the corresponding linear * function(s) to be zero or strictly positive as appropriate). * * It is possible that a feasible basis cannot be found; you * should test isFeasible() after running this routine to see * whether this is the case. * * \pre reserve() has already been called. */ void initStart(); /** * Initialises this tableaux to be a clone of the given tableaux. * This is used in the tree traversal algorithm as we work our way * down the search tree, and child nodes "inherit" tableaux from * their parent nodes. * * \pre reserve() has already been called. * * @param parent the tableaux to clone. */ void initClone(const LPData& parent); /** * Returns the number of columns in this tableaux. * * Note that, if we are imposing extra constraints through the * template parameter LPConstraint, then there will be extra variables * to enforce these, and so the number of columns will be larger than * in the original matching equation matrix. * * @return the number of columns. */ inline unsigned columns() const; /** * Returns the number of columns in this tableaux that correspond to * normal coordinates or angle structure coordinates. This is * precisely the number of columns in the original matrix of * matching equations. * * @return the number of normal or angle structure coordinate columns. */ inline unsigned coordinateColumns() const; /** * Returns whether or not this system is feasible. * * A system may become infeasible when we add too many extra * constraints on the variables (such as forcing them to be * positive, or setting them to zero); see the LPData class * notes for details on these constraints. * * \warning As explained in the class notes, if this system is * infeasible then any queries or operations (other than calling * isFeasible() itself) are undefined. * * @return \c true if this system is feasible, or \c false if it * is infeasible. */ inline bool isFeasible() const; /** * Determines whether the given variable is currently active. * See the LPData class notes for details. * * @param pos the index of the variable to query. * This must be between 0 and origTableaux_->columns()-1 inclusive. */ inline bool isActive(unsigned pos) const; /** * Returns the sign of the given variable under the current * basis. This does \e not attempt to "undo" any changes of variable * caused by prior calls to constrainPositive() or constrainOct(); * it simply tests the sign of the variable in the given column * of the tableaux in its current form. * * Specifically: if the given variable is inactive or non-basic, * this routine returns zero. If the given variable is in the * basis, this routine returns the sign of the corresponding * integer on the right-hand side of the tableaux. * * @param pos the index of the variable to query. * This must be between 0 and origTableaux_->columns()-1 inclusive. * @return the sign of the variable as described above; * this will be either 1, 0 or -1. */ inline int sign(unsigned pos) const; /** * Constrains this system further by setting the given variable * to zero and deactivating it. See the LPData class notes for * details. * * This routine will work even if the given variable has already * been deactivated (and it will do nothing in this case). * * \warning If you have previously called constrainPositive() * or constrainOct() on this variable, then these prior routines * will have performed a change of variable. Any new call to * constraintZero() on this same variable will constraint the * \e new variable, not the original, and so might not have the * intended effect. * * @param pos the index of the variable that is to be set to * zero. This must be between 0 and origTableaux_->columns()-1 * inclusive. */ void constrainZero(unsigned pos); /** * Constrains this system further by constraining the given variable * to be strictly positive. We do this using a change of variable * that effectively replaces x_pos with the new variable * x'_pos = x_pos - 1 (which we simply constrain to be non-negative * as usual). See the LPData class notes for details. * * This routine will work even if the given variable has already * been deactivated, but in this case the routine will * immediately set the system to infeasible and return. * * \warning If you have previously called constrainPositive() * or constrainOct() on this variable, then these prior routines * will have performed a change of variable. Any new call to * constrainPositive() on this same variable will constrain the * \e new variable, not the original, and so might not have the * intended effect. * * @param pos the index of the variable that is to be constrained as * positive. This must be between 0 and origTableaux_->columns()-1 * inclusive. */ void constrainPositive(unsigned pos); /** * Declares that two quadrilateral coordinates within a tetrahedron * are to be combined into a single octagon coordinate, for use * with almost normal surfaces, and constrains the system accordingly. * * This constrains the system in several ways, as discussed in detail * in the LPData class notes. In theory, we set the two quadrilateral * coordinates to be equal, and also insist that the number of octagons * be strictly positive. In practice, we do this through several * changes of variable; see the LPData class notes for a detailed * discussion of precisely how the variables and tableaux will change. * * This routine will work even if one of the given quadrilateral * variables has already been deactivated, but in this case the * routine will immediately set the system to infeasible and return. * * This routine is not used with angle structure coordinates. * * \pre This is the first time constrainOct() has been called on * this tableaux. This is because this class can only handle one * octagon type in the entire system. * * \pre Variables \a quad1 and \a quad2 represent different * quadrilateral coordinates in the same tetrahedron of the * underlying triangulation. * * \warning If you have previously called constrainPositive() or * constrainOct() on one of the given variables, then these prior * routines will have performed a change of variable. Any new call * to constrainOct() involving this same variable will constrain the * \e new variable, not the original, and so might not have the * intended effect. * * @param quad1 one of the two quadrilateral types that we * combine to form the new octagon type. * @param quad2 the other of the two quadrilateral types that we * combine to form the new octagon type. */ void constrainOct(unsigned quad1, unsigned quad2); /** * Writes details of this tableaux to the given output stream. * The output is "rough" and wasteful, and is intended for * debugging purposes only. * * The precise output is subject to change in future versions * of Regina. * * @param out the output stream to write to. */ void dump(std::ostream& out) const; /** * Extracts the values of the individual variables from the * current basis, with some modifications (as described below). * The values of the variables are store in the given vector \a v. * * The modifications are as follows: * * - We extract variables that correspond to the original * matching equations obtained from the underlying * triangulation, \e not the current tableaux and \e not even * the original starting tableaux stored in origTableaux_. * In other words, when we fill the vector \a v we undo the * column permutation described by LPInitialTableaux::columnPerm(), * and we undo any changes of variable that were caused by * calls to constrainPositive() and/or constrainOct(). * * - To ensure that the variables are all integers, we scale the * final vector by the smallest positive rational multiple * for which all elements of the vector are integers. * (This is why the output class is NRay and not NVector.) * * This routine is not used as an internal part of the tree traversal * algorithm; instead it is offered as a helper routine for * reconstructing the normal surfaces or angle structures that result. * * \pre The given vector \a v has been initialised to the zero vector * of length origTableaux_->columns(). Note that the NRay constructor * will automatically initialise all elements to zero as required. * * \pre No individual coordinate column has had more than one call * to either of constrainPositive() or constrainOct() (otherwise * the coordinate will not be correctly reconstructed). Any * additional columns arising from LPConstraint are exempt from * this requirement. * * @param v the vector into which the values of the variables * will be placed. * @param type the type vector corresponding to the current state of * this tableaux, indicating which variables were previously fixed as * positive via calls to constrainPositive(). This is necessary * because LPData does not keep such historical data on its own. * As a special case, when extracting a strict angle structure * one may pass \a type = 0, in which case this routine will * assume that \e every coordinate was constrained as positive. */ void extractSolution(NRay& v, const char* type) const; private: /** * Returns the given entry in this tableaux. * * Since we do not store the full tableaux, this entry is * computed on the fly. However, this computation is fast * because the computations use sparse vector multiplication. * * There is an alternate version of this function that avoids * creating spurious temporaries (which may help with performance). * * @param the row of the requested entry; this must be between 0 * and rank_-1 inclusive. * @param the column of the requested entry; this must be between 0 * and origTableaux_->columns()-1 inclusive. * @return the requested entry in this tableaux. */ inline Integer entry(unsigned row, unsigned col) const; /** * Sets \a ans to the given entry in this tableaux. * * Since we do not store the full tableaux, this entry is * computed on the fly. However, this computation is fast * because the computations use sparse vector multiplication. * * There is an alternate version of this function that is more * natural (it returns its answer), but creates an additional * temporary variable (which may hinder performance). * * @param the row of the requested entry; this must be between 0 * and rank_-1 inclusive. * @param the column of the requested entry; this must be between 0 * and origTableaux_->columns()-1 inclusive. * @param ans an integer that will be set to the requested entry * in this tableaux. */ inline void entry(unsigned row, unsigned col, Integer& ans) const; /** * Determines the sign of the given entry in this tableaux. * * Since we do not store the full tableaux, the entry is * computed on the fly. However, this computation is fast * because the computations use sparse vector multiplication. * * @param the row of the requested entry; this must be between 0 * and rank_-1 inclusive. * @param the column of the requested entry; this must be between 0 * and origTableaux_->columns()-1 inclusive. * @return +1, -1 or 0 according to whether the requested entry * is positive, negative or zero. */ inline int entrySign(unsigned row, unsigned col) const; /** * Performs a pivot in the dual simplex method. * * The column \a outCol is pivoted out of the current basis, and * the column \a inCol is pivoted in. * * No assumptions are made about the current state of column \a outCol; * in particular, it may be in a state "under construction" * whereby it has more than the one expected non-zero element. * However, assumptions \a are made about the current state of * column \a inCol, as noted in the preconditions below. * * \pre \a outCol represents an active basic variable, and * \a inCol represents an active non-basic variable. * * \pre The non-basic variable \a inCol has a non-zero entry in the * row of the tableaux that defines the basic variable \a outCol. * * @param outCol the index of the variable to pivot out of the basis. * @param inCol the index of the variable to pivot into the basis. */ void pivot(unsigned outCol, unsigned inCol); /** * Finds an initial basis for the system using Gauss-Jordan * elimination. * * This routine is only ever called from initStart(), and * assumes that the current tableaux is just the original * starting tableaux (i.e., no changes have been made to the * tableaux at all). * * The implementation of this routine is a little naive and * heavy-handed, but since we only call it once in the entire * tree traversal algorithm, this does not really matter. * * In particular, it performs the entire Gauss-Jordan elimination * using the arbitrary-precision NInteger class, so there is no need * to worry about the magnitudes of any intermediate matrix * entries that might appear during the process. The final * row operation matrix will of course be copied into rowOps_ * using the Integer class specified in the template arguments. * * \pre The current tableaux is precisely the original starting * tableaux; in particular, rhs_ is the zero vector, rowOps_ is the * identity matrix, and rank_ is precisely origTableaux_->rank(). */ void findInitialBasis(); /** * Pivots from the current basis to a feasible basis, or else * marks the entire system as infeasible if this is not possible. * This uses a heuristic pivot rule with good performance but * also includes safety checks to break cycling; see below for details. * * This routine is called after we take a feasible basis and make * some modification that might (or might not) cause some basis * variables to become negative. * * The pivot rule that we use is greedy: the variable that exits * the basis is the one with largest magnitude negative value. * This rule is fast to test and in most cases leads to a small * number of pivots, giving good performance overall. However, * this rule can lead to cycling, and so we include cycle-detection * code that falls back to Bland's rule to break cycling in the * rare cases when it occurs. * * \pre feasible_ is currently marked as \c true (as a leftover * from the feasible basis before our recent modification). */ void makeFeasible(); /** * Pivots from the current basis to a feasible basis, or else * marks the entire system as infeasible if this is not possible. * The pivot rule has poor performance but guarantees to avoid * cycling; see below for details. * * This routine is called after we take a feasible basis and make * some modification that might (or might not) cause some basis * variables to become negative. * * This routine uses a variant of Bland's rule (but without an * objective function) to avoid cycling. The rule to decide on * each individual pivot is fast to run, but the total number of * pivots required to reach feasibility is often very large, leading * to a poor performance overall. It is recommended that you * use a different pivoting rule in general, and only call this * function to break cycles when they occur. * * \pre feasible_ is currently marked as \c true (as a leftover * from the feasible basis before our recent modification). */ void makeFeasibleAntiCycling(); /** * Runs some tests to ensure that the tableaux is in a * consistent state. This is for use in debugging only, since * running these tests might have a severe impact on performance. * * If any tests fail, this routine reports the error and exits * the program immediately. */ void verify() const; }; // Inline functions for LPMatrix template inline LPMatrix::LPMatrix() : dat_(0) { } template inline LPMatrix::LPMatrix(unsigned rows, unsigned cols) : dat_(new Integer[rows * cols]), rows_(rows), cols_(cols) { } template inline LPMatrix::~LPMatrix() { delete[] dat_; } template inline void LPMatrix::reserve(unsigned maxRows, unsigned maxCols) { dat_ = new Integer[maxRows * maxCols]; } template inline void LPMatrix::initClone(const LPMatrix& clone) { rows_ = clone.rows_; cols_ = clone.cols_; std::copy(clone.dat_, clone.dat_ + clone.rows_ * clone.cols_, dat_); } template inline void LPMatrix::initIdentity(unsigned size) { // Don't fuss about optimising this, since we only call it once // in the entire tree traversal algorithm. rows_ = cols_ = size; unsigned r, c; for (r = 0; r < rows_; ++r) for (c = 0; c < cols_; ++c) entry(r, c) = (r == c ? 1 : long(0)); } template inline Integer& LPMatrix::entry(unsigned row, unsigned col) { return dat_[row * cols_ + col]; } template inline const Integer& LPMatrix::entry(unsigned row, unsigned col) const { return dat_[row * cols_ + col]; } template inline unsigned LPMatrix::rows() const { return rows_; } template inline unsigned LPMatrix::columns() const { return cols_; } template inline void LPMatrix::swapRows(unsigned r1, unsigned r2) { if (r1 != r2) std::swap_ranges(dat_ + r1 * cols_, dat_ + r1 * cols_ + cols_, dat_ + r2 * cols_); } template inline void LPMatrix::negateRow(unsigned row) { Integer *p = dat_ + row * cols_; for (unsigned i = 0; i < cols_; ++p, ++i) p->negate(); } // Inline functions for LPInitialTableaux template inline LPInitialTableaux::Col::Col() : nPlus(0), nMinus(0) { } template inline void LPInitialTableaux::Col::push(unsigned row, int val) { #ifdef REGINA_VERIFY_LPDATA if ((val > 0 && val + nPlus > 4) || (val < 0 && val - nMinus < -4)) { std::cerr << "BAD MATRIX" << std::endl; ::exit(1); } #endif for (; val > 0; --val) plus[nPlus++] = row; for (; val < 0; ++val) minus[nMinus++] = row; } template inline LPInitialTableaux::~LPInitialTableaux() { delete eqns_; delete[] col_; delete[] columnPerm_; } template inline const NTriangulation* LPInitialTableaux::tri() const { return tri_; } template inline NormalCoords LPInitialTableaux::coords() const { return coords_; } template inline unsigned LPInitialTableaux::rank() const { return rank_; } template inline unsigned LPInitialTableaux::columns() const { return cols_; } template inline unsigned LPInitialTableaux::coordinateColumns() const { return eqns_->columns(); } template inline bool LPInitialTableaux::constraintsBroken() const { return constraintsBroken_; } template inline const int* LPInitialTableaux::columnPerm() const { return columnPerm_; } template template inline Integer LPInitialTableaux::multColByRow( const LPMatrix& m, unsigned mRow, unsigned thisCol) const { if (scaling_ && thisCol == coordinateColumns() - 1) { // Multiply the entire row by the scaling coefficient. Integer ans; // Initialised to zero. for (unsigned i = 0; i < rank_; ++i) ans += m.entry(mRow, i); ans *= scaling_; return ans; } else { // Just pick out individual coefficients using the sparse // representation of the column. Integer ans = col_[thisCol].innerProduct(m, mRow); unsigned i; for (i = 0; i < col_[thisCol].nPlus; ++i) ans += m.entry(mRow, col_[thisCol].plus[i]); for (i = 0; i < col_[thisCol].nMinus; ++i) ans -= m.entry(mRow, col_[thisCol].minus[i]); return ans; } } template template inline Integer LPInitialTableaux::multColByRowOct( const LPMatrix& m, unsigned mRow, unsigned thisCol) const { // By the preconditions of this routine, we must be working in some normal // or almost normal coordinate system, and so there is no scaling // coordinate to worry about. Integer ans = col_[thisCol].innerProductOct(m, mRow); unsigned i; for (i = 0; i < col_[thisCol].nPlus; ++i) ans += m.entry(mRow, col_[thisCol].plus[i]); for (i = 0; i < col_[thisCol].nMinus; ++i) ans -= m.entry(mRow, col_[thisCol].minus[i]); return ans; } template template inline void LPInitialTableaux::fillInitialTableaux( LPMatrix& m) const { unsigned c, i; for (c = 0; c < cols_; ++c) { for (i = 0; i < col_[c].nPlus; ++i) ++m.entry(col_[c].plus[i], c); for (i = 0; i < col_[c].nMinus; ++i) --m.entry(col_[c].minus[i], c); // Don't forget any additional constraints that we added // as final rows to the matrix. col_[c].fillFinalRows(m, c); } if (scaling_) for (i = 0; i < rank_; ++i) m.entry(i, coordinateColumns() - 1) = scaling_; } // Template functions for LPData template inline LPData::LPData() : rhs_(0), basis_(0), basisRow_(0) { } template inline LPData::~LPData() { delete[] rhs_; delete[] basis_; delete[] basisRow_; } template inline void LPData::reserve( const LPInitialTableaux* origTableaux) { origTableaux_ = origTableaux; rhs_ = new Integer[origTableaux->rank()]; rowOps_.reserve(origTableaux->rank(), origTableaux->rank()); basis_ = new int[origTableaux->rank()]; basisRow_ = new int[origTableaux->columns()]; } template inline unsigned LPData::columns() const { return origTableaux_->columns(); } template inline unsigned LPData::coordinateColumns() const { return origTableaux_->coordinateColumns(); } template inline bool LPData::isFeasible() const { return feasible_; } template inline bool LPData::isActive(unsigned pos) const { // If basisRow_[pos] < 0, the variable is active and non-basic. // If basisRow_[pos] > 0, the variable is active and basic. // If basisRow_[pos] == 0, then: // - if rank_ > 0 and basis_[0] == pos, then the variable // is active and basic; // - otherwise the variable is not active. return ! (basisRow_[pos] == 0 && (rank_ == 0 || basis_[0] != pos)); } template inline int LPData::sign(unsigned pos) const { // If basisRow_[pos] < 0, the variable is active and non-basic. // If basisRow_[pos] > 0, the variable is active and basic. // If basisRow_[pos] == 0, then: // - if rank_ > 0 and basis_[0] == pos, then the variable // is active and basic; // - otherwise the variable is not active. return ((basisRow_[pos] > 0 || (rank_ > 0 && basis_[0] == pos)) ? rhs_[basisRow_[pos]].sign() : 0); } template inline Integer LPData::entry(unsigned row, unsigned col) const { // Remember to take into account any changes of variable due // to previous calls to constrainOct(). if (octPrimary_ != col) return origTableaux_->multColByRow(rowOps_, row, col); else { Integer ans = origTableaux_->multColByRowOct(rowOps_, row, col); ans += origTableaux_->multColByRowOct(rowOps_, row, octSecondary_); return ans; } } template inline void LPData::entry(unsigned row, unsigned col, Integer& ans) const { // Remember to take into account any changes of variable due // to previous calls to constrainOct(). if (octPrimary_ != col) ans = origTableaux_->multColByRow(rowOps_, row, col); else { ans = origTableaux_->multColByRowOct(rowOps_, row, col); ans += origTableaux_->multColByRowOct(rowOps_, row, octSecondary_); } } template inline int LPData::entrySign(unsigned row, unsigned col) const { // Remember to take into account any changes of variable due // to previous calls to constrainOct(). if (octPrimary_ != col) return origTableaux_->multColByRow(rowOps_, row, col).sign(); else { Integer ans = origTableaux_->multColByRowOct(rowOps_, row, col); ans += origTableaux_->multColByRowOct(rowOps_, row, octSecondary_); return ans.sign(); } } } // namespace regina #endif regina-4.96/engine/enumerate/ntreelp.tcc000644 000765 000024 00000004653 12400001242 020177 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file enumerate/ntreelp.tcc * \brief Deprecated header. */ #warning This header is deprecated; please use ntreelp-impl.h instead. #include "enumerate/ntreelp-impl.h" regina-4.96/engine/enumerate/ntreetraversal-impl.h000644 000765 000024 00000152356 12377775146 022252 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 2011-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /* Definitions of template member functions from ntreetraversal.h. For common combinations of template arguments, the templates are already instatiated and so you will not need to include this file. For more exotic combinations of template arguments, or if the template arguments are your own classes, then you will need to include this file. */ #ifndef __NTREETRAVERSAL_IMPL_H #ifndef __DOXYGEN #define __NTREETRAVERSAL_IMPL_H #endif #include "angle/nanglestructure.h" #include "enumerate/ntreetraversal.h" #include "progress/nprogresstracker.h" #include "surfaces/nsanstandard.h" #include "surfaces/nsquad.h" #include "surfaces/nsquadoct.h" #include "surfaces/nsstandard.h" #include "surfaces/nnormalsurfacelist.h" #include "triangulation/ntriangulation.h" /** * Optimisation flags: * Define any combination of the following flags to switch \e off * various optimisations. * This is for diagnostic purposes only. */ // #define REGINA_NOOPT_MIN_FEASIBLE /** * Define REGINA_TREE_TRACE to output details of the type vectors as we * walk through the search tree. This is for diagnostic purposes only. */ // #define REGINA_TREE_TRACE /** * Define REGINA_SURFACE_TRACE to output details of full normal surfaces * (possibly immersed, or branched), as well as their corresponding * type vectors, as we walk through the search tree. * This is for diagnostic purposes only. */ // #define REGINA_SURFACE_TRACE namespace regina { template NNormalSurface* NTreeTraversal:: buildSurface() const { // Note that the vector constructors automatically set all // elements to zero, as required by LPData::extractSolution(). NNormalSurfaceVector* v; if (coords_ == NS_QUAD || coords_ == NS_AN_QUAD_OCT) v = new NNormalSurfaceVectorQuad(3 * nTets_); else if (coords_ == NS_STANDARD || coords_ == NS_AN_STANDARD) v = new NNormalSurfaceVectorStandard(7 * nTets_); else return 0; lpSlot_[nTypes_]->extractSolution(*v, type_); if (coords_ == NS_QUAD || coords_ == NS_STANDARD) return new NNormalSurface(origTableaux_.tri(), v); // We have an almost normal surface: restore the octagon // coordinates. NNormalSurfaceVector* an; unsigned i, j; if (coords_ == NS_AN_QUAD_OCT) { an = new NNormalSurfaceVectorQuadOct(6 * nTets_); for (i = 0; i < nTets_; ++i) for (j = 0; j < 3; ++j) an->setElement(6 * i + j, (*v)[3 * i + j]); if (octLevel_ >= 0) { unsigned octTet = (origTableaux_.columnPerm()[ 3 * typeOrder_[octLevel_]] / 3); unsigned octType = type_[typeOrder_[octLevel_]] - 4; an->setElement(6 * octTet + 3 + octType, (*v)[3 * octTet + (octType + 1) % 3]); for (j = 0; j < 3; ++j) an->setElement(6 * octTet + j, 0); } } else { an = new NNormalSurfaceVectorANStandard(10 * nTets_); for (i = 0; i < nTets_; ++i) for (j = 0; j < 7; ++j) an->setElement(10 * i + j, (*v)[7 * i + j]); if (octLevel_ >= 0) { unsigned octTet = (origTableaux_.columnPerm()[ 3 * typeOrder_[octLevel_]] / 7); unsigned octType = type_[typeOrder_[octLevel_]] - 4; an->setElement(10 * octTet + 7 + octType, (*v)[7 * octTet + 4 + (octType + 1) % 3]); for (j = 0; j < 3; ++j) an->setElement(10 * octTet + 4 + j, 0); } } delete v; return new NNormalSurface(origTableaux_.tri(), an); } template NAngleStructure* NTreeTraversal:: buildStructure() const { // Note that the vector constructors automatically set all // elements to zero, as required by LPData::extractSolution(). if (coords_ != NS_ANGLE) return 0; NAngleStructureVector* v = new NAngleStructureVector(3 * nTets_ + 1); lpSlot_[nTypes_]->extractSolution(*v, type_); return new NAngleStructure(origTableaux_.tri(), v); } template bool NTreeTraversal::verify( const NNormalSurface* s, const NMatrixInt* matchingEqns) const { if (coords_ == NS_ANGLE) return false; // Rebuild the matching equations if necessary. NMatrixInt* tmpEqns = 0; if (! matchingEqns) { tmpEqns = regina::makeMatchingEquations( origTableaux_.tri(), coords_); matchingEqns = tmpEqns; } // Verify the matching equations. unsigned row, col; for (row = 0; row < matchingEqns->rows(); ++row) { NLargeInteger ans; // Initialised to zero. for (col = 0; col < matchingEqns->columns(); ++col) ans += (matchingEqns->entry(row, col) * (*s->rawVector())[col]); if (ans != 0) { delete tmpEqns; return false; } } delete tmpEqns; // Verify any additional constraints. return LPConstraint::verify(s); } template bool NTreeTraversal::verify( const NAngleStructure* s, const NMatrixInt* angleEqns) const { if (coords_ != NS_ANGLE) return false; // Rebuild the matching equations if necessary. NMatrixInt* tmpEqns = 0; if (! angleEqns) { tmpEqns = NAngleStructureVector::makeAngleEquations( origTableaux_.tri()); angleEqns = tmpEqns; } // Verify the angle equations. unsigned row, col; for (row = 0; row < angleEqns->rows(); ++row) { NLargeInteger ans; // Initialised to zero. for (col = 0; col < angleEqns->columns(); ++col) ans += (angleEqns->entry(row, col) * (*s->rawVector())[col]); if (ans != 0) { delete tmpEqns; return false; } } delete tmpEqns; // Verify any additional constraints. return LPConstraint::verify(s); } template NTreeTraversal::NTreeTraversal( const NTriangulation* tri, NormalCoords coords, int branchesPerQuad, int branchesPerTri, bool enumeration) : BanConstraint(tri, coords), origTableaux_(tri, (coords == NS_AN_QUAD_OCT ? NS_QUAD : coords == NS_AN_STANDARD ? NS_STANDARD : coords), enumeration), coords_(coords), nTets_(tri->getNumberOfTetrahedra()), nTypes_(coords == NS_QUAD || coords == NS_AN_QUAD_OCT || coords == NS_ANGLE ? nTets_ : 5 * nTets_), /* Each time we branch, one LP can be solved in-place: therefore we use branchesPerQuad-1 and branchesPerTri-1. The final +1 is for the root node. */ nTableaux_(coords == NS_QUAD || coords == NS_AN_QUAD_OCT || coords == NS_ANGLE ? (branchesPerQuad - 1) * nTets_ + 1 : (branchesPerQuad - 1) * nTets_ + (branchesPerTri - 1) * nTets_ * 4 + 1), type_(new char[nTypes_ + 1]), typeOrder_(new int[nTypes_]), level_(0), octLevel_(coords == NS_AN_STANDARD || coords == NS_AN_QUAD_OCT ? -1 : nTypes_), lp_(new LPData[nTableaux_]), lpSlot_(new LPData*[nTypes_ + 1]), nextSlot_(new LPData*[nTypes_ + 1]), nVisited_(0) { // Initialise the type vector to the zero vector. std::fill(type_, type_ + nTypes_ + 1, 0); // Set a default type order. unsigned i; for (i = 0; i < nTypes_; ++i) typeOrder_[i] = i; // Reserve space for all the tableaux that we will ever need. for (i = 0; i < nTableaux_; ++i) lp_[i].reserve(&origTableaux_); // Mark the location of the initial tableaux at the root node. lpSlot_[0] = lp_; nextSlot_[0] = lp_ + 1; // Set up the ban list. BanConstraint::init(origTableaux_.columnPerm()); // Reserve space for our additional temporary tableaux. tmpLP_[0].reserve(&origTableaux_); tmpLP_[1].reserve(&origTableaux_); tmpLP_[2].reserve(&origTableaux_); tmpLP_[3].reserve(&origTableaux_); } /** * Destroys this object. */ template NTreeTraversal::~NTreeTraversal() { delete[] type_; delete[] typeOrder_; delete[] lp_; delete[] lpSlot_; delete[] nextSlot_; } template void NTreeTraversal::setNext( int nextType) { int* pos = std::find(typeOrder_ + level_ + 1, typeOrder_ + nTypes_, nextType); if (pos != typeOrder_ + level_ + 1) { // Use memmove(), which is safe when the source and // destination ranges overlap. memmove(typeOrder_ + level_ + 2 /* dest */, typeOrder_ + level_ + 1 /* src */, (pos - (typeOrder_ + level_ + 1)) * sizeof(int)); typeOrder_[level_ + 1] = nextType; } } template int NTreeTraversal::feasibleBranches( int quadType) { // Spin off clones for the new linear programs (reusing as much // work as possible). if (coords_ == NS_ANGLE) { // Only spin off three clones, since we know at least one angle // must be non-zero. // Also, there is no need to use constrainPositive here, since // the angle equations already enforce at least one positive // angle per tetrahedra (assuming the final scaling coordinate // has already been enforced to be positive). tmpLP_[0].initClone(*lpSlot_[level_ + 1]); tmpLP_[1].initClone(tmpLP_[0]); tmpLP_[1].constrainZero(3 * quadType); tmpLP_[1].constrainZero(3 * quadType + 2); tmpLP_[0].constrainZero(3 * quadType + 1); if (! tmpLP_[0].isFeasible()) { // The first and third branches will both be infeasible. // Save some work and jump straight to the solution. return (tmpLP_[1].isFeasible() ? 1 : 0); } tmpLP_[2].initClone(tmpLP_[0]); tmpLP_[2].constrainZero(3 * quadType); tmpLP_[0].constrainZero(3 * quadType + 2); // Determine which of these systems are feasible. return ((tmpLP_[0].isFeasible() ? 1 : 0) + (tmpLP_[1].isFeasible() ? 1 : 0) + (tmpLP_[2].isFeasible() ? 1 : 0)); } else { tmpLP_[0].initClone(*lpSlot_[level_ + 1]); tmpLP_[1].initClone(tmpLP_[0]); tmpLP_[1].constrainZero(3 * quadType + 1); tmpLP_[1].constrainZero(3 * quadType + 2); tmpLP_[1].constrainPositive(3 * quadType); tmpLP_[0].constrainZero(3 * quadType); if (! tmpLP_[0].isFeasible()) { // Branches 0, 2 and 3 will all be infeasible. // Save some work and jump straight to the solution. return (tmpLP_[1].isFeasible() ? 1 : 0); } tmpLP_[2].initClone(tmpLP_[0]); tmpLP_[2].constrainZero(3 * quadType + 2); tmpLP_[2].constrainPositive(3 * quadType + 1); tmpLP_[0].constrainZero(3 * quadType + 1); if (! tmpLP_[0].isFeasible()) { // Branches 0 and 3 will both be infeasible. return (tmpLP_[1].isFeasible() ? 1 : 0) + (tmpLP_[2].isFeasible() ? 1 : 0); } tmpLP_[3].initClone(tmpLP_[0]); tmpLP_[3].constrainPositive(3 * quadType + 2); tmpLP_[0].constrainZero(3 * quadType + 2); // Determine which of these systems are feasible. return ((tmpLP_[0].isFeasible() ? 1 : 0) + (tmpLP_[1].isFeasible() ? 1 : 0) + (tmpLP_[2].isFeasible() ? 1 : 0) + (tmpLP_[3].isFeasible() ? 1 : 0)); } } template double NTreeTraversal::percent() const { double percent = 0.0; double range = 100.0; unsigned den; unsigned quadsRemaining = nTets_; // Just check the first few types, until the margin of // error is sufficiently small. for (unsigned i = 0; range > 0.01 && i < nTypes_; ++i) { if (coords_ == NS_ANGLE) { // Angle structure coordinates. range /= 3.0; if (type_[typeOrder_[i]] == 0) break; // All zeroes from here down. percent += (range * (type_[typeOrder_[i]] - 1)); } else if (typeOrder_[i] >= nTets_) { // Triangle coordinate. range /= 2.0; percent += (range * type_[typeOrder_[i]]); } else { // Quadrilateral or octagon coordinate. if (octLevel_ == nTypes_ || octLevel_ < i) { // Octagons have already been used, or were never available. range /= 4.0; percent += (range * type_[typeOrder_[i]]); } else if (octLevel_ == i) { // This coordinate is an octagon coordinate. den = 3 * quadsRemaining + 4; range /= den; percent += range * ((den - 3) + (type_[typeOrder_[i]] - 4)); } else { // This is a quad coordinate, but octagons are still // available for use either here or deeper in the tree. den = 3 * quadsRemaining + 4; range = (range * (den - 3)) / (4 * den); // Floating pt division percent += (range * type_[typeOrder_[i]]); } --quadsRemaining; } } return percent; } template bool NTreeEnumeration::next( NProgressTracker* tracker) { if (lastNonZero_ < 0) { // Our type vector is the zero vector. // This means we are starting the search from the very // beginning. // // Prepare the root node by finding an initial basis // from the original starting tableaux. lp_[0].initStart(); BanConstraint::enforceBans(lp_[0]); ++nVisited_; // Is the system feasible at the root node? // If not, there can be no solutions at all. if (! lp_[0].isFeasible()) return false; /** * If we ever need to reorder the search tree at the very * beginning, here is where we do it. * * Note that, since setNext() works on typeOrder_[level_ + 1], * we must temporarily set level_ = -1 before we call it. * level_ = -1; setNext(...); level_ = 0; */ } else { // We are starting the search from a previous solution. // Make the next incremental change to the type vector // to continue the search. // // We *should* increment type_[typeOrder_[nTypes_-1]]. // However, if type_[typeOrder_[nTypes_-1]] is zero then this // will fail the domination test. In fact, incrementing *any* // trailing zeroes in our type vector will likewise fail // the domination test (since it will dominate the // previous solution that we are now stepping away from). // We can therefore shortcut the search and wind our way // back to the last *non-zero* element in the type // vector, and increment that instead. // // Note: we must have *some* non-zero element in the // type vector, because we know that lastNonZero_ >= 0. level_ = lastNonZero_; ++type_[typeOrder_[level_]]; } // And... continue the search! unsigned idx; /* Index of the type we are currently choosing. */ bool outOfRange; while (true) { // Update the state of progress and test for cancellation. if (tracker && ! tracker->setPercent(percent())) break; #ifdef REGINA_TREE_TRACE dumpTypes(std::cout); std::cout << std::endl; #endif /* INVARIANTS: * * - 0 <= level_ < nTypes_. * * - We have explicitly set type_[typeOrder_[0,...,level_]], * though it is possible that type_[typeOrder_[level_]] is * out of range (too large). All later elements * type_[typeOrder_[level_+1,...,nTypes_-1]] are 0. * * - The parent node in the tree (where * type_[typeOrder_[level_]] == 0) passes the feasibility * and domination tests; however we do not yet know whether * this node in the tree (with our new value for * type_[typeOrder_[level_]]) passes these tests. */ idx = typeOrder_[level_]; // Check whether type_[idx] is out of range, // and if so then backtrack further up the tree. outOfRange = false; if (type_[idx] == 4) { // This quadrilateral column is out of range. if (octLevel_ < 0) { // But... we can make it an octagon column instead. octLevel_ = level_; } else outOfRange = true; } else if (type_[idx] == 7) { // This octagon column is out of range. // Clear octLevel_ again so that some other level can // claim the one and only octagon column if it likes. octLevel_ = -1; outOfRange = true; } else if (idx >= nTets_ && type_[idx] == 2) { // This triangle column is out of range. outOfRange = true; } if (outOfRange) { // Backtrack. type_[idx] = 0; --level_; if (level_ < 0) { // Out of options: the tree traversal is finished. return false; } ++type_[typeOrder_[level_]]; lastNonZero_ = level_; continue; } // This is a node in the search tree that we need to // examine. ++nVisited_; // Check the domination test. // If this fails then abandon this subtree, increment the // type at the current level, and continue searching. // // Note that if type_[idx] == 0 then we do not // need to check the domination test, since we know the parent // node passed the domination test and setting // type_[idx] = 0 will not change the result. if (type_[idx] && solns_.dominates(type_, nTypes_)) { ++type_[idx]; lastNonZero_ = level_; continue; } // Leave the zero test until a bit later; there is some // dual simplex work we need to do with the zero vector // even though we know we don't want it as a solution. // All that's left is the feasibility test. // Bring on the linear programming. // First, prepare the tableaux for our new type at this level // of the tree. if (! type_[idx]) { // This is the first time we have visited this node. // Since the parent node already passes the // feasibility test, we will simply overwrite the // parent tableaux "in place", avoiding the need for // an expensive copy operation. lpSlot_[level_ + 1] = lpSlot_[level_]; // Since type_[idx] = 0, we will be adding // up to three new constraints x_i = x_{i+1} = x_{i+2} = 0. // So that we can reuse as much work as possible, we // will gradually spin off clones of this tableaux // that we can later use with // type_[idx] == 1, 2 or 3 (and 4, 5 or 6 if we allow // octagons). // // How we add these constraints and spin off clones // depends on whether are working with quadrilateral // columns or triangle columns. if (idx < nTets_) { // We're working with a quadrilateral column. if (octLevel_ < 0) { // We must support both quadrilaterals and octagons. nextSlot_[level_ + 1] = nextSlot_[level_] + 6; // Here we have three constraints // x_{3k} = x_{3k+1} = x_{3k+2} = 0, // and later we will be trying quadrilateral types // 1, 2 and 3, and octagon types 4, 5 and 6. // First spin off clones that we will later use with // type_[idx] = 1, 5 and 6. These clones inherit // no extra constraints: for type 1 we will need to // fix x_{3k} >= 1 and x_{3k+1} = x_{3k+2} = 0 // later, and for types 5 and 6 we must likewise // fix all constraints later on. nextSlot_[level_]->initClone(*lpSlot_[level_]); (nextSlot_[level_] + 4)->initClone(*lpSlot_[level_]); (nextSlot_[level_] + 5)->initClone(*lpSlot_[level_]); // Now we can fix x_{3k} = 0. lpSlot_[level_]->constrainZero(3 * idx); // Next spin off clones that we will later use with // type_[idx] = 2 and 4. These clones already // inherit the constraint x_{3k} = 0, and we // will add the other constraints later (for // instance, for type 2 we will add x_{3k+1} >= 1 // and x_{3k+2} = 0 later). (nextSlot_[level_] + 1)->initClone(*lpSlot_[level_]); (nextSlot_[level_] + 3)->initClone(*lpSlot_[level_]); // Now we can fix x_{3k+1} = 0. lpSlot_[level_]->constrainZero(3 * idx + 1); // Finally spin off a clone that we will later use // with type_[idx] = 3. This clone already // inherits the constraint x_{3k} = x_{3k+1} = 0, // which only leaves us x_{3k+2} >= 1 to add later. (nextSlot_[level_] + 2)->initClone(*lpSlot_[level_]); // At last we add the final constraint x_{3k+2} = 0 // for this node. lpSlot_[level_]->constrainZero(3 * idx + 2); // This node now has all of the necessary // constraints x_{3k} = x_{3k+1} = x_{3k+2} = 0. } else { // We are supporting quadrilaterals only. // As above, but with types 1, 2 and 3 only. nextSlot_[level_ + 1] = nextSlot_[level_] + 3; nextSlot_[level_]->initClone(*lpSlot_[level_]); lpSlot_[level_]->constrainZero(3 * idx); (nextSlot_[level_] + 1)->initClone(*lpSlot_[level_]); lpSlot_[level_]->constrainZero(3 * idx + 1); (nextSlot_[level_] + 2)->initClone(*lpSlot_[level_]); lpSlot_[level_]->constrainZero(3 * idx + 2); } } else { // We're working with a triangle column. nextSlot_[level_ + 1] = nextSlot_[level_] + 1; // Here we only have one constraint x_k = 0, // and later we only have type 1 to try. // Spin off a clone that we will later use with // type_[idx] = 1. This clone inherits // no extra constraints. nextSlot_[level_]->initClone(*lpSlot_[level_]); // Now add the one and only constraint x_k = 0 for // this node. lpSlot_[level_]->constrainZero(2 * nTets_ + idx); } } else { // This is not the first time we have visited this node. // Find the appropriate clone that we spun off earlier when // type_[idx] was 0, and add the missing // constraints that we did not enforce during the // cloning process. // // We always enforce constraints of the form x_i = 0 // before constraints of the form x_i >= 1. // This is in the hope that x_i = 0 is easier to // deal with, and if we break feasibility earlier then // this saves us some work later on. // // (Note that we did indeed spin off clones earlier, // since if we pass the domination test now for // type_[idx] != 0 then we must have passed // it earlier for type_[idx] == 0.) if (idx < nTets_) { // Quadrilateral columns (type is 1, 2 or 3, // or 4, 5 or 6 if we allow octagons): lpSlot_[level_ + 1] = nextSlot_[level_] + type_[idx] - 1; switch (type_[idx]) { case 1: lpSlot_[level_ + 1]->constrainZero(3 * idx + 1); lpSlot_[level_ + 1]->constrainZero(3 * idx + 2); lpSlot_[level_ + 1]->constrainPositive(3 * idx); break; case 2: lpSlot_[level_ + 1]->constrainZero(3 * idx + 2); lpSlot_[level_ + 1]->constrainPositive(3 * idx + 1); break; case 3: lpSlot_[level_ + 1]->constrainPositive(3 * idx + 2); break; case 4: lpSlot_[level_ + 1]->constrainOct( 3 * idx + 1, 3 * idx + 2); break; case 5: lpSlot_[level_ + 1]->constrainZero(3 * idx + 1); lpSlot_[level_ + 1]->constrainOct(3 * idx, 3 * idx + 2); break; case 6: lpSlot_[level_ + 1]->constrainZero(3 * idx + 2); lpSlot_[level_ + 1]->constrainOct(3 * idx, 3 * idx + 1); break; } } else { // Triangle columns (type is 1): lpSlot_[level_ + 1] = nextSlot_[level_]; lpSlot_[level_ + 1]->constrainPositive(2 * nTets_ + idx); } } // *Now* we can enforce the zero test. // We could not do this earlier because, even if we have // the zero vector, we still needed to spin off clones // for type_[idx] = 1, 2 and 3. if (lastNonZero_ < 0 && level_ == nTypes_ - 1) { // We failed the zero test. // Abandon this subtree, increment the type at the // current level, and continue searching. ++type_[idx]; lastNonZero_ = level_; continue; } // Now all our constraints are enforced, and we can // simply test the tableaux for feasibility. if (lpSlot_[level_ + 1]->isFeasible()) { if (level_ < nTypes_ - 1) { // We pass the feasibility test, but we're // not at a leaf node. // Head deeper into the tree. #if 0 if (level_ < nTets_) { // The next level is a quadrilateral type. // See if we can't find a better quadrilateral // type to branch on instead. We will choose the // quadrilateral type that branches into the // fewest possible feasible subtrees. // Here we measure the old types 0, 1, 2, 3 as // four separate branches (not the three merged // branches 0=1, 2, 3 that we use in the actual // search). int bestQuad = -1; int minBranches = 5; // Greater than any soln. int tmp; for (int i = level_ + 1; i < nTypes_; ++i) { if (typeOrder_[i] < nTets_) { // It's an available quad type. tmp = feasibleBranches(typeOrder_[i]); if (tmp < minBranches) { minBranches = tmp; bestQuad = typeOrder_[i]; if (tmp == 0) break; // Can't get any better! } } } if (bestQuad >= 0) setNext(bestQuad); } #endif ++level_; } else { // We pass the feasibility test, *and* we're at // a leaf node. This means we've found a solution! solns_.insert(type_, nTypes_); ++nSolns_; return true; } } else { // We failed the feasibility test. // Abandon this subtree, increment the type at the // current level, and continue searching. ++type_[idx]; lastNonZero_ = level_; } } // If we ever make it out here, it's because some other // thread cancelled the search. The result should be ignored. return false; } template bool NTautEnumeration::next( NProgressTracker* tracker) { // Note that for taut angle structures we have no domination test and // no zero test. The domination comes for free (every taut angle // structure is at a vertex of the angle structure polytope), and the // zero test will always be satisfied because we have enforced the // scaling coordinate to be positive. if (type_[typeOrder_[0]] == 0) { // We are starting the search from the very beginning. // (We know this because the very first thing that happens at // the very first branch is that type_[typeOrder_[0]] is // incremented to 1. For taut angle structures, type 0 is // simply a placeholder for "we haven't reached this type yet".) // // Prepare the root node by finding an initial basis // from the original starting tableaux. lp_[0].initStart(); // Ensure that we avoid the zero solution, by insisting that the // final scaling coordinate be positive. lp_[0].constrainPositive(origTableaux_.coordinateColumns() - 1); BanConstraint::enforceBans(lp_[0]); ++nVisited_; // Is the system feasible at the root node? // If not, there can be no solutions at all. if (! lp_[0].isFeasible()) return false; /** * If we ever need to reorder the search tree at the very * beginning, here is where we do it. * * Note that, since setNext() works on typeOrder_[level_ + 1], * we must temporarily set level_ = -1 before we call it. * level_ = -1; setNext(...); level_ = 0; */ } else { // We are starting the search from a previous solution. // Make the next incremental change to the type vector // to continue the search. ++type_[typeOrder_[level_]]; } // And... continue the search! unsigned idx; /* Index of the type we are currently choosing. */ while (true) { // Update the state of progress and test for cancellation. if (tracker && ! tracker->setPercent(percent())) break; #ifdef REGINA_TREE_TRACE dumpTypes(std::cout); std::cout << std::endl; #endif /* INVARIANTS: * * - 0 <= level_ < nTypes_. * * - We have explicitly set type_[typeOrder_[0,...,level_]], * though it is possible that type_[typeOrder_[level_]] is * out of range (too large). All later elements * type_[typeOrder_[level_+1,...,nTypes_-1]] are 0. * * - The parent node in the tree (where type_[typeOrder_[level_]] == 0) * passes the feasibility test; however we do not yet know whether * this node in the tree (with our new value for * type_[typeOrder_[level_]]) passes these tests. */ idx = typeOrder_[level_]; // Check whether type_[idx] is out of range, and if so then // backtrack further up the tree. if (type_[idx] == 4) { // This column is out of range. // Backtrack. type_[idx] = 0; --level_; if (level_ < 0) { // Out of options: the tree traversal is finished. return false; } ++type_[typeOrder_[level_]]; continue; } // This is a node in the search tree that we need to examine. ++nVisited_; // All that's left is the feasibility test. // Bring on the linear programming. // First, prepare the tableaux for our new type at this level // of the tree. if (! type_[idx]) { // This is the first time we have visited this node. // Jump straight to type 1, since taut angle structures must // have some non-zero angle in each tetrahedron. ++type_[idx]; // Since the parent node already passes the // feasibility test, we will simply overwrite the // parent tableaux "in place", avoiding the need for // an expensive copy operation. lpSlot_[level_ + 1] = lpSlot_[level_]; // So that we can reuse as much work as possible, we // will gradually spin off clones of this tableaux // that we can later use with type_[idx] == 1, 2 or 3. nextSlot_[level_ + 1] = nextSlot_[level_] + 2; nextSlot_[level_]->initClone(*lpSlot_[level_]); lpSlot_[level_]->constrainZero(3 * idx + 1); (nextSlot_[level_] + 1)->initClone(*lpSlot_[level_]); lpSlot_[level_]->constrainZero(3 * idx + 2); } else { // We have type_[idx] == 2 or 3. // // Find the appropriate clone that we spun off earlier when // type_[idx] was 0 (but immediately incremented to 1), and // then add the missing constraints that we did not // enforce during the cloning process. lpSlot_[level_ + 1] = nextSlot_[level_] + type_[idx] - 2; switch (type_[idx]) { case 2: lpSlot_[level_ + 1]->constrainZero(3 * idx); lpSlot_[level_ + 1]->constrainZero(3 * idx + 2); break; case 3: lpSlot_[level_ + 1]->constrainZero(3 * idx); break; } } // Now all our constraints are enforced, and we can // simply test the tableaux for feasibility. if (lpSlot_[level_ + 1]->isFeasible()) { if (level_ < nTypes_ - 1) { // We pass the feasibility test, but we're not at a leaf node. // Head deeper into the tree. ++level_; } else { // We pass the feasibility test, *and* we're at a leaf node. // This means we've found a solution! ++nSolns_; return true; } } else { // We failed the feasibility test. // Abandon this subtree, increment the type at the // current level, and continue searching. ++type_[idx]; } } // If we ever make it out here, it's because some other // thread cancelled the search. The result should be ignored. return false; } template bool NTautEnumeration:: writeStructure(const NTautEnumeration& tree, void*) { std::cout << "SOLN #" << tree.nSolns() << ": "; NAngleStructure* s = tree.buildStructure(); std::cout << s->str() << std::endl; delete s; return true; } template bool NTreeSingleSoln::find() { // This code is similar to next(), but makes some changes to // account for the facts that: // - we only need a single solution that satisfies our // constraints, not all solutions; // - this single solution does not need to be a vertex solution. // // Amongst other things, we make the following key changes: // - there is no domination test (since we stop at the first // solution); // - we insist that at least one unmarked triangle coordinate is // zero at all stages of the search, so that we can avoid surfaces // with trivial (and unwanted) vertex linking components. // // Furthermore, we only take three branches for each quadrilateral // type, not four. We do this by combining types 0 and 1, // so the three branches are: // ( >= 0, 0, 0 ) --> type 1 // ( 0, >= 1, 0 ) --> type 2 // ( 0, 0, >= 1 ) --> type 3 // Start the search from the very beginning. // // Prepare the root node by finding an initial basis from // the original starting tableaux. lp_[0].initStart(); BanConstraint::enforceBans(lp_[0]); ++nVisited_; if (! lp_[0].isFeasible()) return false; // To kick off our vertex-link-avoiding regime, make // nextZeroLevel_ the first level in the search tree, and // choose an appropriate triangle type to branch on. We will // return to the quadrilateral types as soon as some triangle // coordinate is safely constrained to zero. // // Since setNext() works on typeOrder_[level_ + 1], we must // temporarily set level_ = -1 before we call it. int useTriangle = nextUnmarkedTriangleType(nTets_); if (useTriangle < 0) { // There are no triangle types available to set to zero! return false; } level_ = -1; setNext(useTriangle); level_ = 0; // Run the search! unsigned idx; /* Index of the type we are currently choosing. */ bool outOfRange; while (! cancelled()) { // We can safely return from this point. #ifdef REGINA_TREE_TRACE dumpTypes(std::cout); std::cout << std::endl; #endif // This code is based on NTreeEnumeration::next(). // For details on how it works, see the implementation of // NTreeEnumeration::next(), which is very thoroughly // documented. idx = typeOrder_[level_]; // Check whether type_[idx] is out of range, // and if so then backtrack further up the tree. outOfRange = false; if (type_[idx] == 4) { // Quadrilateral column if (octLevel_ < 0) octLevel_ = level_; // Make it an octagon column else outOfRange = true; } else if (type_[idx] == 7) { // Octagon column octLevel_ = -1; outOfRange = true; } else if (idx >= nTets_ && type_[idx] == 2) // Triangle column outOfRange = true; if (outOfRange) { // Backtrack. type_[idx] = 0; --level_; if (level_ < 0) { // Out of options: there is no solution. return false; } ++type_[typeOrder_[level_]]; continue; } ++nVisited_; // Skip the domination test and the zero test (which // are irrelevant here). Note in particular that, if we // are searching for a surface with positive Euler // characteristic, the zero vector will not be a solution. // Prepare the tableaux for our new type at this level // of the tree. if (! type_[idx]) { // This is the first time we have visited this node. // Spin off clones and add some preliminary x_i = 0 // constraints as we go, reusing as much work as possible. if (idx < nTets_) { // We're working with a quadrilateral column. // // First, ignore type 0; instead step directly to // type 1 (which merges the old types 0 and 1 together). ++type_[idx]; // Now spin off clones for type 2 and 3, and // overwrite the parent tableaux in-place for type 1. // // As we go, we add the following constraints: // - type 1: x_{3k+1} = x_{3k+2} = 0 // - type 2: x_{3k+2} = 0 // - type 3: none // // If we allow octagons, we also spin off: // - type 4: none // - type 5: none // - type 6: x_{3k+2} = 0 if (octLevel_ < 0) { // We must support both quadrilaterals and octagons. nextSlot_[level_ + 1] = nextSlot_[level_] + 5; (nextSlot_[level_] + 1)->initClone(*lpSlot_[level_]); (nextSlot_[level_] + 2)->initClone(*lpSlot_[level_]); (nextSlot_[level_] + 3)->initClone(*lpSlot_[level_]); lpSlot_[level_]->constrainZero(3 * idx + 2); nextSlot_[level_]->initClone(*lpSlot_[level_]); (nextSlot_[level_] + 4)->initClone(*lpSlot_[level_]); lpSlot_[level_]->constrainZero(3 * idx + 1); } else { // We only support quadrilaterals. nextSlot_[level_ + 1] = nextSlot_[level_] + 2; (nextSlot_[level_] + 1)->initClone(*lpSlot_[level_]); lpSlot_[level_]->constrainZero(3 * idx + 2); nextSlot_[level_]->initClone(*lpSlot_[level_]); lpSlot_[level_]->constrainZero(3 * idx + 1); } } else { // We're working with a triangle column. // // Since we are going to process type 0 right now, // mark which tableaux we will use. lpSlot_[level_ + 1] = lpSlot_[level_]; // Spin off a clone for type 1, and overwrite // the parent tableaux in-place for type 0. // // As we go, we add the following constraints: // - type 0: x_k = 0 // - type 1: none nextSlot_[level_ + 1] = nextSlot_[level_] + 1; nextSlot_[level_]->initClone(*lpSlot_[level_]); lpSlot_[level_]->constrainZero(2 * nTets_ + idx); } } if (type_[idx]) { // Find the appropriate clone that we spun off earlier when // type_[idx] was 0, and add any missing constraints. if (idx < nTets_) { // Quadrilateral columns (type is 1, 2 or 3, // or 4, 5 or 6 if we allow octagons): lpSlot_[level_ + 1] = (type_[idx] == 1 ? lpSlot_[level_] : nextSlot_[level_] + type_[idx] - 2); switch (type_[idx]) { // Nothing required for type 1, which already // has all necessary constraints. Since we merge // types 0 and 1 together, there is not even a // positivity constraint to add. case 2: lpSlot_[level_ + 1]->constrainZero(3 * idx); lpSlot_[level_ + 1]->constrainPositive(3 * idx + 1); break; case 3: lpSlot_[level_ + 1]->constrainZero(3 * idx); lpSlot_[level_ + 1]->constrainZero(3 * idx + 1); lpSlot_[level_ + 1]->constrainPositive(3 * idx + 2); break; case 4: lpSlot_[level_ + 1]->constrainZero(3 * idx); lpSlot_[level_ + 1]->constrainOct( 3 * idx + 1, 3 * idx + 2); break; case 5: lpSlot_[level_ + 1]->constrainZero(3 * idx + 1); lpSlot_[level_ + 1]->constrainOct(3 * idx, 3 * idx + 2); break; case 6: lpSlot_[level_ + 1]->constrainOct(3 * idx, 3 * idx + 1); break; } } else { // Triangle columns (type is 1): lpSlot_[level_ + 1] = nextSlot_[level_]; lpSlot_[level_ + 1]->constrainPositive(2 * nTets_ + idx); } } // Now all our constraints are enforced, and we can // simply test the tableaux for feasibility. if (lpSlot_[level_ + 1]->isFeasible()) { #ifdef REGINA_SURFACE_TRACE { dumpTypes(std::cout); std::cout << " (" << idx << " -> " << (int)type_[idx] << ")" << std::endl; NNormalSurfaceVector* v = new NNormalSurfaceVectorStandard(7 * nTets_); lpSlot_[level_ + 1]->extractSolution(*v, type_); NNormalSurface* f = new NNormalSurface( origTableaux_.tri(), v); std::cout << f->str() << std::endl; delete f; } #endif if (level_ < nTypes_ - 1) { // We pass the feasibility test, but we're // not at a leaf node. // Head deeper into the tree. if (level_ == nextZeroLevel_) { // We're avoiding vertex links, and we're // still in the upper region of the search // tree where we force triangles to be zero // as early as possible in the search. // // Either we've just started setting the current // triangle type to 0, or we've just finished // setting the current triangle type to 0. // Either way, we need to do some rearrangement // of the search tree now. if (! type_[idx]) { // We've just started setting this triangle // type to 0. // This means that we're happy, and we // can move onto quadrilaterals. // Make sure the type we process next is the // corresponding quadrilateral type. setNext((idx - nTets_) / 4); } else { // We've just finished setting this // triangle type to 0, and so we need to try // setting a new triangle type to 0 instead. // Find the next candidate triangle type, // and make sure we process it next. useTriangle = nextUnmarkedTriangleType(idx + 1); if (useTriangle >= 0) { setNext(useTriangle); ++nextZeroLevel_; } else { // There are no more triangles types left // to try setting to 0. // The only solutions remaining have all // unmarked triangle coordinates // positive, i.e., they involve multiples // of undesirable vertex links. We don't // want such solutions, // so abandon the search now. return false; } } } else if (typeOrder_[level_ + 1] < nTets_) { // The next level is a quadrilateral type. // See if we can't find a better quadrilateral // type to branch on instead. We will choose the // quadrilateral type that branches into the // fewest possible feasible subtrees. // Here we measure the old types 0, 1, 2, 3 as // four separate branches (not the three merged // branches 0=1, 2, 3 that we use in the actual // search). int bestQuad = -1; int minBranches = 5; // Greater than any soln. int tmp; for (int i = level_ + 1; i < nTypes_; ++i) { if (typeOrder_[i] < nTets_) { // It's an available quad type. #ifdef REGINA_NOOPT_MIN_FEASIBLE bestQuad = typeOrder_[i]; break; #else tmp = feasibleBranches(typeOrder_[i]); if (tmp < minBranches) { minBranches = tmp; bestQuad = typeOrder_[i]; if (tmp == 0) break; // Can't get any better! } #endif } } if (bestQuad >= 0) setNext(bestQuad); } ++level_; } else { // We pass the feasibility test, *and* we're at // a leaf node. This means we've found a solution! // However: we have no guarantee that it's a // vertex solution, since we merged quad types 0/1 // together. Explicitly try setting each type 1 // quadrilateral coordinate to zero, and change // the type to 0 if the system is still feasible. // If the system is not feasible, call // constrainPositive() to enact the change of // variable so that we can reconstruct the // surface correctly. for (int i = 0; i < nTets_; ++i) { if (type_[i] == 1) { tmpLP_[0].initClone(*lpSlot_[level_ + 1]); tmpLP_[0].constrainZero(3 * i); // TODO: Use initClone() here instead? if (tmpLP_[0].isFeasible()) { lpSlot_[level_ + 1]->constrainZero(3 * i); type_[i] = 0; } else { lpSlot_[level_ + 1]->constrainPositive( 3 * i); } } } return true; } } else { // We failed the feasibility test. // Abandon this subtree, increment the type at the // current level, and continue searching. ++type_[idx]; } } // If we ever make it out here, it's because some other // thread cancelled the search. The result should be ignored. return false; } } // namespace regina #endif regina-4.96/engine/enumerate/ntreetraversal.cpp000644 000765 000024 00000006745 12377776606 021650 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 2011-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "enumerate/ntreetraversal-impl.h" namespace regina { // Instantiate templates: template class NTreeTraversal; template class NTreeTraversal; template class NTreeEnumeration; template class NTreeEnumeration; template class NTautEnumeration; template class NTautEnumeration; template class NTreeTraversal; template class NTreeTraversal; template class NTreeSingleSoln; template class NTreeSingleSoln; #ifdef INT128_AVAILABLE template class NTreeTraversal >; template class NTreeEnumeration >; template class NTautEnumeration >; template class NTreeTraversal >; template class NTreeSingleSoln >; #endif } // namespace regina regina-4.96/engine/enumerate/ntreetraversal.h000644 000765 000024 00000226435 12377775150 021306 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 2011-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file enumerate/ntreetraversal.h * \brief Tree traversal methods for normal surface and angle structure * enumeration and optimisation. */ #ifndef __NTREETRAVERSAL_H #ifndef __DOXYGEN #define __NTREETRAVERSAL_H #endif #include "enumerate/ntreeconstraint.h" #include "enumerate/ntreelp.h" #include "enumerate/ntypetrie.h" #include "utilities/nthread.h" namespace regina { class NProgressTracker; class NTriangulation; /** * \weakgroup enumerate * @{ */ /** * A base class for searches that employ the tree traversal algorithm for * enumerating and locating vertex normal surfaces and taut angle structures. * Users should not use this base class directly; instead use one of the * subclasses NTreeEnumeration (for enumerating all vertex normal surfaces), * NTautEnumeration (for enumerating all taut angle structures), or * NTreeSingleSoln (for locating a single non-trivial solution under * additional constraints, such as positive Euler characteristic). * * For normal surfaces, the full algorithms are described respectively in * "A tree traversal algorithm for decision problems in knot theory and * 3-manifold topology", Burton and Ozlen, Algorithmica 65:4 (2013), * pp. 772-801, and "A fast branching algorithm for unknot recognition with * experimental polynomial-time behaviour", Burton and Ozlen, arXiv:1211.1079. * * This base class provides the infrastructure for the search tree, and the * subclasses handle the mechanics of the moving through the tree according * to the backtracking search. The domination test is handled separately by * the class NTypeTrie, and the feasibility test is handled separately by the * class LPData. * * This class holds the particular state of the tree traversal * at any point in time, as described by the current \e level (indicating * our current depth in the search tree) and type vector * (indicating which branches of the search tree we have followed). * For details on these concepts, see the Algorithmica paper cited above. * The key details are summarised below; throughout this discussion * \a n represents the number of tetrahedra in the underlying triangulation. * * - In quadrilateral coordinates, the type vector is a sequence of \a n * integers, each equal to 0, 1, 2 or 3, where the ith integer * describes the choice of quadrilateral location in the ith * tetrahedron. * * - In standard coordinates, the type vector begins with the \a n * quadrilateral choices outlined above. This is then followed by an * additional 4n integers, each equal to 0 or 1; these * correspond to the 4n triangle coordinates, and indicate * whether each coordinate is zero or non-zero. * * - In angle structure coordinates, this class identifies taut angle * structures only. Here the type vector is a sequence of \a n integers, * each equal to 1, 2 or 3, where the ith integer describes the * location of the two π angles in the ith tetrahedron. * * In the original Algorithmica paper, we choose types in the order * type_[0], type_[1] and so on, working from the root of the tree down * to the leaves. Here we support a more flexible system: there is an * internal permutation \a typeOrder_, and we choose types in the order * type_[typeOrder_[0]], type_[typeOrder_[1]] and so on. This * permutation may mix quadrilateral and triangle processing, and may * even change as the algorithm runs. * * This class can also support octagon types in almost normal surfaces. * However, we still do our linear programming in standard or quadrilateral * coordinates, where we represent an octagon using two conflicting * quadrilaterals in the same tetrahedron (which meet the tetrahedron boundary * in the same set of arcs as a single octagon would). As with the almost * normal coordinate systems in NNormalSurfaceList, we allow multiple octagons * of the same type, but only one octagon type in the entire tetrahedron. * In the type vector, octagons are indicated by setting a quadrilateral * type to 4, 5 or 6. * * There is optional support for adding extra linear constraints * (such as a constraint on Euler characteristic), supplied by the * template parameter \a LPConstraint. If there are no additional * constraints, simply use the template parameter LPConstraintNone. * * Also, there is optional support for banning coordinates (i.e., insisting * that certain coordinates must be set to zero), and/or marking coordinates * (for normal and almost normal surfaces this affects what is meant by a * "non-trivial" surface for the NTreeSingleSoln algorithm; the concept of * marking may be expanded further in future versions of Regina). These * options are supplied by the template parameter \a BanConstraint. * If there are no coordinates to ban or mark, simply use the template * parameter \a BanNone. * * In some cases, it is impossible to add the extra linear constraints * that we would like (for instance, if they require additional * preconditions on the underlying triangulation). If this is a possibility * in your setting, you should call constraintsBroken() to test for this * once the NTreeTraversal object has been constructed. * * The template argument \a Integer indicates the integer type that * will be used throughout the underlying linear programming machinery. * Unless you have a good reason to do otherwise, you should use the * arbitrary-precision NInteger class (in which integers can grow * arbitrarily large, and overflow can never occur). * * \pre The parameters LPConstraint and BanConstraint must be subclasses of * LPConstraintBase and BanConstraintBase respectively. See the * LPConstraintBase and BanConstraintBase class notes for further details. * * \pre The default constructor for the template class Integer must intialise * each new integer to zero. The classes NInteger and NNativeInteger, * for instance, have this property. * * \apinotfinal * * \ifacespython Not present. */ template class REGINA_API NTreeTraversal : public BanConstraint { protected: // Global information about the search: const LPInitialTableaux origTableaux_; /**< The original starting tableaux that holds the adjusted matrix of matching equations, before the tree traversal algorithm begins. */ const NormalCoords coords_; /**< The coordinate system in which we are enumerating or searching for normal surfaces, almost normal surfaces, or taut angle structures. This must be one of NS_QUAD or NS_STANDARD if we are only supporting normal surfaces, one of NS_AN_QUAD_OCT or NS_AN_STANDARD if we are allowing octagons in almost normal surfaces, or NS_ANGLE if we are searching for taut angle structures. */ const int nTets_; /**< The number of tetrahedra in the underlying triangulation. */ const int nTypes_; /**< The total length of a type vector. */ const int nTableaux_; /**< The maximum number of tableaux that we need to keep in memory at any given time during the backtracking search. */ // Details of the current state of the backtracking search: char* type_; /**< The current working type vector. As the search runs, we modify this type vector in-place. Any types beyond the current level in the search tree will always be set to zero. */ int* typeOrder_; /**< A permutation of 0,...,\a nTypes_-1 that indicates in which order we select types: the first type we select (at the root of the tree) is type_[typeOrder_[0]], and the last type we select (at the leaves of the tree) is type_[typeOrder_[nTypes_-1]]. This permutation is allowed to change as the algorithm runs (though of course you can only change sections of the permutation that correspond to types not yet selected). */ int level_; /**< The current level in the search tree. As the search runs, this holds the index into typeOrder_ corresponding to the last type that we chose. */ int octLevel_; /**< The level at which we are enforcing an octagon type (with a strictly positive number of octagons). If we are working with angle structures or normal surfaces only (and so we do not allow octagons at all), then \a octLevel_ = \a nTypes_. If we are allowing almost normal surfaces but we have not yet chosen an octagon type, then \a octLevel_ = -1. */ LPData* lp_; /**< Stores tableaux for linear programming at various nodes in the search tree. We only store a limited number of tableaux at any given time, and as the search progresses we overwrite old tableaux with new tableaux. More precisely, we store a linear number of tableaux, essentially corresponding to the current node in the search tree and all of its ancestores, all the way up to the root node. In addition to these tableaux, we also store other immediate children of these ancestores that we have pre-prepared for future processing. See the documentation within routines such as NTreeEnumeration::next() for details of when and how these tableaux are constructed. */ LPData** lpSlot_; /**< Recall from above that the array \a lp_ stores tableaux for the current node in the search tree and all of its ancestors. This means we have one tableaux for the root node, as well as additional tableaux at each level 0,1,...,\a level_. The array lpSlot_ indicates which element of the array \a lp_ holds each of these tableaux. Specifically: lpSlot_[0] points to the tableaux for the root node, and for each level \a i in the range 0,...,\a level_, the corresponding tableaux is *lpSlot_[i+1]. Again, see the documentation within routines such as NTreeEnumeration::next() for details of when and how these tableaux are constructed and later overwritten. */ LPData** nextSlot_; /**< Points to the next available tableaux in lp_ that is free to use at each level of the search tree. Specifically: nextSlot_[0] points to the next free tableaux at the root node, and for each level \a i in the range 0,...,\a level_, the corresponding next free tableaux is *nextSlot_[i+1]. The precise layout of the nextSlot_ array depends on the order in which we process quadrilateral, triangle and/or angle types. */ unsigned long nVisited_; /**< Counts the total number of nodes in the search tree that we have visited thus far. This may grow much faster than the number of solutions, since it also counts traversals through "dead ends" in the search tree. */ LPData tmpLP_[4]; /**< Temporary tableaux used by the function feasibleBranches() to determine which quadrilateral types or angle types have good potential for pruning the search tree. Other routines are welcome to use these temporary tableaux also (as "scratch space"); however, be aware that any call to feasibleBranches() will overwrite them. */ public: /** * Indicates whether the given coordinate system is supported by * this tree traversal infrastructure. * * Currently this is true only for NS_STANDARD and NS_QUAD (for * normal surfaces), NS_AN_STANDARD and NS_AN_QUAD_OCT (for * almost normal surfaces), and NS_ANGLE (for taut angle structures). * Any additional restrictions imposed by LPConstraint and * BanConstraint will also be taken into account. * * @param coords the coordinate system being queried. * @return \c true if and only if this coordinate system is * supported. */ static bool supported(NormalCoords coords); /** * Indicates whether or not the extra constraints from the template * parameter \a LPConstraints were added successfully to the * infrastructure for the search tree. * * This query function is important because some constraints require * additional preconditions on the underlying triangulation, and * so these constraints cannot be added in some circumstances. * If it is possible that the constraints * might not be added successfully, this function should be * tested as soon as the NTreeTraversal object has been created. * * If the extra constraints were not added successfully, the search * tree will be left in a consistent state but will give incorrect * results (specifically, the extra constraints will be treated as * zero functions). * * @return \c true if the constraints were \e not added * successfully, or \c false if the constraints were added successfully. */ bool constraintsBroken() const; /** * Returns the total number of nodes in the search tree that we * have visited thus far in the tree traversal. * This figure might grow much faster than the number of solutions, * since it also counts traversals through "dead ends" in the * search tree. * * This counts all nodes that we visit, including those that fail * any or all of the domination, feasibility and zero tests. * The precise way that this number is calculated is subject to * change in future versions of Regina. * * If you called an "all at once" routine such as * NTreeEnumeration::run() or NTreeSingleSoln::find(), then this will * be the total number of nodes that were visited in the entire tree * traversal. If you are calling an "incremental" routine such as * NTreeEnumeration::next() (i.e., you are generating one solution * at time), then this will be the partial count of how many nodes * have been visited so far. * * @return the number of nodes visited so far. */ unsigned long nVisited() const; /** * Writes the current type vector to the given output stream. * There will be no spaces between the types, and there will be * no final newline. * * @param out the output stream to which to write. */ void dumpTypes(std::ostream& out) const; /** * Reconstructs the full normal surface that is represented by * the type vector at the current stage of the search. * This routine is for use only with normal (or almost normal) * surfaces, not taut angle structures. * * The surface that is returned will be newly constructed, and * it is the caller's responsibility to destroy it when it is no * longer required. * * If the current type vector does not represent a \e vertex * normal surface (which may be the case when calling * NTreeSingleSoln::find()), then there may be many normal surfaces * all represented by the same type vector; in this case there are * no further guarantees about \e which of these normal surfaces * you will get. * * \pre This tree traversal is at a point in the search where * it has found a feasible solution that represents a normal surface * (though this need not be a vertex surface). * This condition is always true after NTreeEnumeration::next() * or NTreeSingleSoln::find() returns \c true, or any time that * NTreeEnumeration::run() calls its callback function. * * \pre We are working with normal or almost normal surfaces. * That is, the coordinate system passed to the NTreeTraversal * constructor was not NS_ANGLE. * * @return a normal surface that has been found at the current stage * of the search. */ NNormalSurface* buildSurface() const; /** * Reconstructs the full taut angle structure that is represented by * the type vector at the current stage of the search. * This routine is for use only with taut angle structures, * not normal or almost normal surfaces. * * The angle structure that is returned will be newly constructed, and * it is the caller's responsibility to destroy it when it is no * longer required. * * There will always be a unique taut angle structure corresponding * to this type vector (this follows from the preconditions below). * * \pre This tree traversal is at a point in the search where it has * found a feasible solution that represents a taut angle structure. * This condition is always true after NTautEnumeration::next() * returns \c true, or any time that NTautEnumeration::run() calls * its callback function. * * \pre We are working with angle structure coordinates; that is, * the coordinate system passed to the NTreeTraversal constructor * was NS_ANGLE. * * @return the taut angle structure that has been found at the * current stage of the search. */ NAngleStructure* buildStructure() const; /** * Ensures that the given normal or almost normal surface satisfies * the matching equations, as well as any additional constraints * from the template parameter LPConstraint. * This routine is for use only with normal (or almost normal) * surfaces, not angle structures. * * This routine is provided for diagnostic, debugging and verification * purposes. * * Instead of using the initial tableaux to verify the matching * equations, this routine goes back to the original matching * equations matrix as constructed by regina::makeMatchingEquations(). * This ensures that the test is independent of any potential * problems with the tableaux. You are not required to pass * your own matching equations (if you don't, they will be temporarily * reconstructed for you); however, you may pass your own if you * wish to use a non-standard matching equation matrix, and/or * reuse the same matrix to avoid the overhead of reconstructing it * every time this routine is called. * * \pre The normal or almost normal surface \a s uses the same * coordinate system as was passed to the NTreeTraversal constructor. * Moreover, this coordinate system is in fact a normal or * almost normal coordinate system (i.e., not NS_ANGLE). * * \pre If \a matchingEqns is non-null, then the number of columns * in \a matchingEqns is equal to the number of coordinates in the * underlying normal or almost normal coordinate system. * * @param s the normal surface to verify. * @param matchingEqns the matching equations to check against * the given surface; this may be 0, in which case the matching * equations will be temporarily reconstructed for you using * regina::makeMatchingEquations(). * @return \c true if the given surface passes all of the tests * described above, or \c false if it fails one or more tests * (indicating a problem or error). */ bool verify(const NNormalSurface* s, const NMatrixInt* matchingEqns = 0) const; /** * Ensures that the given angle structure satisfies * the angle equations, as well as any additional constraints * from the template parameter LPConstraint. * This routine is for use only with angle structures, * not normal (or almost normal) surfaces. * * This routine is provided for diagnostic, debugging and verification * purposes. * * Instead of using the initial tableaux to verify the angle equations, * this routine goes back to the original angle equations matrix as * constructed by NAngleStructureVector::makeAngleEquations(). * This ensures that the test is independent of any potential * problems with the tableaux. You are not required to pass * your own angle equations (if you don't, they will be temporarily * reconstructed for you); however, you may pass your own if you * wish to use a non-standard angle equation matrix, and/or * reuse the same matrix to avoid the overhead of reconstructing it * every time this routine is called. * * \pre The coordinate system passed to the NTreeTraversal constructor * was NS_ANGLE. * * \pre If \a angleEqns is non-null, then the number of columns * in \a angleEqns is equal to the number of coordinates in the * underlying angle structure coordinate system. * * @param s the angle structure to verify. * @param angleEqns the angle equations to check against * the given angle structure; this may be 0, in which case the angle * equations will be temporarily reconstructed for you using * NAngleStructureVector::makeMatchingEquations(). * @return \c true if the given angle structure passes all of the tests * described above, or \c false if it fails one or more tests * (indicating a problem or error). */ bool verify(const NAngleStructure* s, const NMatrixInt* angleEqns = 0) const; protected: /** * Initialises a new base object for running the tree traversal * algorithm. This routine may only be called by subclass constructors; * for more information on how to create and run a tree * traversal, see subclasses such as NTreeEnumeration, NTautEnumeration * or NTreeSingleSoln instead. * * \pre The given triangulation is non-empty. * * @param tri the triangulation in which we wish to search for * normal surfaces or taut angle structures. * @param coords the coordinate system in which wish to search for * normal surfaces or taut angle structures. This must be one of * NS_QUAD, NS_STANDARD, NS_AN_QUAD_OCT, NS_AN_STANDARD, or NS_ANGLE. * @param branchesPerQuad the maximum number of branches we * spawn in the search tree for each quadrilateral or angle type * (e.g., 4 for a vanilla normal surface tree traversal algorithm, * or 3 for enumerating taut angle structures). * @param branchesPerTri the maximum number of branches we * spawn in the search tree for each triangle type * (e.g., 2 for a vanilla normal surface tree traversal algorithm). * If the underlying coordinate system does not support triangles * then this argument will be ignored. * @param enumeration \c true if we should optimise the tableaux * for a full enumeration of vertex surfaces or taut angle structures, * or \c false if we should optimise the tableaux for an existence test * (such as searching for a non-trivial normal disc or sphere). */ NTreeTraversal(const NTriangulation* tri, NormalCoords coords, int branchesPerQuad, int branchesPerTri, bool enumeration); /** * Destroys this object. */ ~NTreeTraversal(); /** * Rearranges the search tree so that \a nextType becomes the next * type that we process. * * Specifically, this routine will set typeOrder_[level_ + 1] * to \a nextType_, and will move other elements of typeOrder_ * back by one position to make space as required. * * \pre \a nextType is in the range 0,...,\a nTypes-1 inclusive. * \pre \a nextType is still waiting to be processed; that is, * \a nextType does not appear in the list * typeOrder_[0,...,level_]. * * @param nextType the next type to process. */ void setNext(int nextType); /** * Returns the next unmarked triangle type from a given starting * point. Specifically, this routine returns the first unmarked * triangle type whose type number is greater than or equal to * \a startFrom. For more information on marking, see the * BanConstraintBase class notes. * * This routine simply searches through types by increasing index * into the type vector; in particular, it does \e not make any use * of the reordering defined by the \a typeOrder_ array. * * \pre We are working in standard normal or almost normal * coordinates. That is, the coordinate system passed to the * NTreeTraversal constructor was one of NS_STANDARD * or NS_AN_STANDARD. * * \pre The argument \a startFrom is at least \a nTets_ (i.e., * it is at least as large as the index of the first triangle type). * * @param startFrom the index into the type vector of the triangle type * from which we begin searching. * @return the index into the type vector of the next unmarked * triangle type from \a startFrom onwards, or -1 if there are no * more remaining. */ int nextUnmarkedTriangleType(int startFrom); /** * Determines how many different values we could assign to the given * quadrilateral or angle type and still obtain a feasible system. * * This will involve solving three or four linear programs, all based * on the current state of the tableaux at the current level of the * search tree. These assign 0, 1, 2 and 3 to the given quadrilateral * or angle type in turn (here 0 is not used for angle types), * and then enforce the corresponding constraints. * For quadrilateral types, we count types 0 and 1 separately as in * NTreeEnumeration, not merged together as in NTreeSingleSoln. * * \pre The given quadrilateral or angle type has not yet been * processed in the search tree (i.e., it has not had an explicit * value selected). * * \pre When using angle structure coordinates, the final * scaling coordinate has already been enforced as positive. * (This is because, for angle structures, this routine does * nothing to eliminate the zero solution.) * * @param quadType the quadrilateral or angle type to examine. * @return the number of type values 0, 1, 2 or 3 that yield a * feasible system; this will be between 0 and 4 inclusive for * quadrilateral types, or between 0 and 3 inclusive for angle types. */ int feasibleBranches(int quadType); /** * Gives a rough estimate as to what percentage of the way the * current type vector is through a full enumeration of the * search tree. This is useful for progress tracking. * * This routine only attemps to determine the percentage within * a reasonable range of error (at the time of writing, 0.01%). * This allows it to be more efficient (in particular, by only * examining the branches closest to the root of the search tree). * * @return the percentage, as a number between 0 and 100 inclusive. */ double percent() const; }; /** * The main entry point for the tree traversal algorithm to enumerate all * vertex normal or almost normal surfaces in a 3-manifold triangulation. * For the analogous algorithm to enumerate taut angle structures, see the * class NTautEnumeration instead. * * This class essentially implements the algorithm from "A tree traversal * algorithm for decision problems in knot theory and 3-manifold topology", * Burton and Ozlen, Algorithmica 65:4 (2013), pp. 772-801. * * To enumerate all vertex surfaces for a given 3-manifold * triangulation, simply construct a NTreeEnumeration object and call run(). * * Alternatively, you can have more fine-grained control over the search. * Instead of calling run(), you can construct an NTreeEnumeration object and * repeatedly call next() to step through each vertex surface one at * a time. This allows you to pause and resume the search as you please. * * If you simply wish to detect a single non-trivial solution under * additional constraints (such as positive Euler characteristic), then * use the class NTreeSingleSoln instead, which is optimised for this purpose. * * This tree traversal can only enumerate surfaces in quadrilateral normal * coordinates (NS_QUAD), standard normal coordinates (NS_STANDARD), * quadrilateral-octagon almost normal coordinates (NS_AN_QUAD_OCT), or * standard almost normal coordinates (NS_AN_STANDARD). For almost * normal surfaces, we allow any number of octagons (including zero), * but we only allow at most one octagon \e type in the entire triangulation. * No coordinate systems other than these are supported. * * By using appropriate template parameters \a LPConstraint and/or * \a BanConstraint, it is possible to impose additional linear * constraints on the normal surface solution cone, and/or explicitly force * particular normal coordinates to zero. In this case, the notion of * "vertex surface" is modified to mean a normal surface whose coordinates * lie on an extreme ray of the restricted solution cone under these additional * constraints (and whose coordinates are integers with no common divisor). * See the LPConstraintBase and BanConstraintBase class notes for * details. * * The template argument \a Integer indicates the integer type that * will be used throughout the underlying linear programming machinery. * Unless you have a good reason to do otherwise, you should use the * arbitrary-precision NInteger class (in which integers can grow * arbitrarily large, and overflow can never occur). * * \pre The parameters LPConstraint and BanConstraint must be subclasses of * LPConstraintSubspace and BanConstraintBase respectively. Note in * particular that the base class LPConstraintBase is not enough here. * See the LPConstraintBase, LPConstraintSubspace and BanConstraintBase * class notes for further details. * * \pre The default constructor for the template class Integer must intialise * each new integer to zero. The classes NInteger and NNativeInteger, * for instance, have this property. * * \warning Although the tree traversal algorithm can run in standard * normal or almost normal coordinates, this is not recommended: it is likely * to be \e much slower than in quadrilateral or quadrilateral-octagon * coordinates respectively. Instead you should enumerate vertex * solutions using quadrilateral or quadrilateral-octagon coordinates, and * then run the conversion procedure NNormalSurfaceList::quadToStandard() * or NNormalSurfaceList::quadOctToStandardAN(). * * \apinotfinal * * \ifacespython Not present. */ template class REGINA_API NTreeEnumeration : public NTreeTraversal { public: using NTreeTraversal::dumpTypes; protected: // Since we have a template base class, we need to explicitly // list the inherited member variables that we use. // Note that these are all protected in the base class, and so // we are not changing any access restrictions here. using NTreeTraversal::level_; using NTreeTraversal::lp_; using NTreeTraversal::lpSlot_; using NTreeTraversal::nextSlot_; using NTreeTraversal::nTets_; using NTreeTraversal::nTypes_; using NTreeTraversal::nVisited_; using NTreeTraversal::octLevel_; using NTreeTraversal::type_; using NTreeTraversal::typeOrder_; using NTreeTraversal:: feasibleBranches; using NTreeTraversal::percent; using NTreeTraversal::setNext; private: NTypeTrie<7> solns_; /**< A trie that holds the type vectors for all vertex surfaces found so far. We wastefully allow for 7 possible types always (which are required for almost normal surfaces); the performance loss from changing 4 to 7 is negligible. */ unsigned long nSolns_; /**< The number of vertex surfaces found so far. */ int lastNonZero_; /**< The index into typeOrder_ corresponding to the last non-zero type that was selected, or -1 if we still have the zero vector. Here "last" means "last chosen"; that is, the highest index into typeOrder_ that gives a non-zero type. */ public: /** * Creates a new object for running the tree traversal algorithm. * * This prepares the algorithm; in order to run the algorithm * and enumerate vertex surfaces, you can either: * * - call run(), which enumerates all vertex surfaces * with a single function call; * * - repeatedly call next(), which will step to the next vertex * surface each time you call it. * * \warning Although it is supported, it is highly recommended that you * do \e not run a full vertex enumeration in standard normal * or almost normal coordinates (this is for performance reasons). * See the class notes for further discussion and better alternatives. * In normal circumstances you should run a full vertex enumeration * in quadrilateral or quadrilateral-octagon coordinates only. * * \pre The given triangulation is non-empty. * * \pre Both the trianglation and the given coordinate system * adhere to any preconditions required by the template * parameters LPConstraint and BanConstraint. * * @param tri the triangulation in which we wish to enumerate * vertex surfaces. * @param coords the coordinate system in which wish to enumerate * vertex surfaces. This must be one of NS_QUAD, NS_STANDARD, * NS_AN_QUAD_OCT, or NS_AN_STANDARD. */ NTreeEnumeration(const NTriangulation* tri, NormalCoords coords); /** * Returns the total number of vertex normal or almost normal surfaces * found thus far in the tree traversal search. * * If you called run(), then this will simply be the total number of * vertex surfaces. If you are calling next() one * surface at time, this will be the partial count of how many * vertex surfaces have been found until now. * * @return the number of solutions found so far. */ unsigned long nSolns() const; /** * Runs the complete tree traversal algorithm to enumerate * vertex normal or almost normal surfaces. * * For each vertex surface that is found, this routine * will call the function \a useSoln. It will pass two * arguments to this function: (i) this tree enumeration object, * and (ii) an arbitrary piece of data that you can supply via * the argument \a arg. * * You can extract details of the solution directly from the * tree enumeration object: for instance, you can dump the type * vector using dumpTypes(), or you can reconstruct the full normal or * almost normal surface using buildSurface() and perform some other * operations upon it. If you do call buildSurface(), remember * to delete the normal surface once you are finished with it. * * The tree traversal will block until your callback function * \a useSoln returns. If the callback function returns \c true, * then run() will continue the tree traversal. If it returns * \c false, then run() will abort the search and return immediately. * * The usual way of using this routine is to construct a * NTreeEnumeration object and then immediately call run(). However, * if you prefer, you may call run() after one or more calls to next(). * In this case, run() will continue the search from the current point * and run it to its completion. In other words, run() will locate * and call \a useSoln for all vertex surfaces that had not yet * been found, but it will not call \a useSoln on those surfaces * that had previously been found during earlier calls to next(). * * \pre The tree traversal algorithm has not yet finished. * That is, you have not called run() before, and if you have * called next() then it has always returned \c true (indicating * that it has not yet finished the search). * * @param useSoln a callback function that will be called each * time we locate a vertex surface, as described above. * @param arg the second argument to pass to the callback * function; this may be any type of data that you like. */ void run(bool (*useSoln)(const NTreeEnumeration&, void*), void* arg = 0); /** * An incremental step in the tree traversal algorithm that * runs forward until it finds the next solution. * Specifically: this continues the tree traversal from the * current point until either it finds the next vertex normal * or almost normal surface (in which case it returns \c true), or * until the tree traversal is completely finished with no more * solutions to be found (in which case it returns \c false). * * If you simply wish to find and process all vertex surfaces, * you may wish to consider the all-in-one routine * run() instead. By using next() to step through one solution * at a time however, you obtain more fine-grained control: for * instance, you can "pause" and restart the search, or have * tighter control over multithreading. * * If next() does return \c true because it found a solution, * you can extract details of the solution directly from this * tree enumeration object: for instance, you can dump the type * vector using dumpTypes(), or you can reconstruct the full normal or * almost normal surface using buildSurface() and perform some other * operations upon it. If you do call buildSurface(), remember * to delete the normal surface once you are finished with it. * * An optional progress tracker may be passed. If so, this routine * will update the percentage progress and poll for cancellation * requests. It will be assumed that an appropriate stage has already * been declared via NProgressTracker::newStage() before this routine * is called, and that NProgressTracker::setFinished() will be * called after this routine returns (and presumably not until * the entire search tree is exhausted). * The percentage progress will be given in the context of a complete * enumeration of the entire search tree (i.e., it will typically * start at a percentage greater than 0, and end at a percentage less * than 100). * * \pre The tree traversal algorithm has not yet finished. * That is, you have not called run() before, and if you have * called next() then it has always returned \c true (indicating * that it has not yet finished the search). * * @param tracker a progress tracker through which progress * will be reported, or 0 if no progress reporting is required. * @return \c true if we found another vertex surface, or * \c false if the search has now finished and no more vertex * surfaces were found. */ bool next(NProgressTracker* tracker = 0); /** * A callback function that writes to standard output the type vector * at the current point in the given tree traversal search. * You can use this as the callback function \a useSoln that is * passed to run(). * * The type vector will be written on a single line, with no * spaces between types, with a prefix indicating which solution * we are up to, and with a final newline appended. * This output format is subject to change in future versions of Regina. * * The second (void*) argument is ignored. It is only present * for compatibility with run(). * * \pre The given tree traversal is at a point in the search where * it has reached the deepest level of the search tree and found a * feasible solution that represents a vertex normal or almost * normal surface. This is always the case any time after next() * returns \c true, or any time that run() calls its callback function. * * @param tree the tree traversal object from which we are * extracting the current type vector. * @return \c true (which indicates to run() that we should * continue the tree traversal). */ static bool writeTypes(const NTreeEnumeration& tree, void*); /** * A callback function that writes to standard output the full * triangle-quadrilateral coordinates of the vertex normal * or almost normal surface at the current point in the given * tree traversal search. You can use this as the callback function * \a useSoln that is passed to run(). * * The normal surface coordinates will be written on a single line, with * spaces and punctuation separating them, a prefix indicating which * solution we are up to, and a final newline appended. * This output format is subject to change in future versions of Regina. * * The second (void*) argument is ignored. It is only present * for compatibility with run(). * * \pre The given tree traversal is at a point in the search where * it has reached the deepest level of the search tree and found a * feasible solution that represents a vertex normal or almost * normal surface. This is always the case any time after next() * returns \c true, or any time that run() calls its callback function. * * @param tree the tree traversal object from which we are * extracting the current vertex normal or almost normal surface. * @return \c true (which indicates to run() that we should * continue the tree traversal). */ static bool writeSurface(const NTreeEnumeration& tree, void*); }; /** * The main entry point for the tree traversal algorithm to enumerate all * taut angle structures in a 3-manifold triangulation. * For the analogous algorithm to enumerate vertex normal or almost * normal surfaces, see the class NTreeEnumeration instead. * * This class follows a similar structure to the enumeration of vertex * normal surfaces, as described in "A tree traversal algorithm for decision * problems in knot theory and 3-manifold topology", Burton and Ozlen, * Algorithmica 65:4 (2013), pp. 772-801. * * To enumerate all taut angle structures on a given 3-manifold * triangulation, simply construct an NTautEnumeration object and call run(). * * Alternatively, you can have more fine-grained control over the search. * Instead of calling run(), you can construct an NTautEnumeration object and * repeatedly call next() to step through each taut angle structure one at * a time. This allows you to pause and resume the search as you please. * * By using appropriate template parameters \a LPConstraint and/or * \a BanConstraint, it is possible to impose additional linear constraints * on the angle structure solution space, and/or explicitly force particular * angles to be zero. See the LPConstraintBase and BanConstraintBase * class notes for details. * * The template argument \a Integer indicates the integer type that * will be used throughout the underlying linear programming machinery. * Unless you have a good reason to do otherwise, you should use the * arbitrary-precision NInteger class (in which integers can grow * arbitrarily large, and overflow can never occur). * * \pre The parameters LPConstraint and BanConstraint must be subclasses of * LPConstraintSubspace and BanConstraintBase respectively. Note in * particular that the base class LPConstraintBase is not enough here. * See the LPConstraintBase, LPConstraintSubspace and BanConstraintBase * class notes for further details. * * \pre The default constructor for the template class Integer must intialise * each new integer to zero. The classes NInteger and NNativeInteger, * for instance, have this property. * * \apinotfinal * * \ifacespython Not present. */ template class REGINA_API NTautEnumeration : public NTreeTraversal { public: using NTreeTraversal::dumpTypes; protected: // Since we have a template base class, we need to explicitly // list the inherited member variables that we use. // Note that these are all protected in the base class, and so // we are not changing any access restrictions here. using NTreeTraversal::level_; using NTreeTraversal::lp_; using NTreeTraversal::lpSlot_; using NTreeTraversal::nextSlot_; using NTreeTraversal::nTets_; using NTreeTraversal::nTypes_; using NTreeTraversal::nVisited_; using NTreeTraversal:: origTableaux_; using NTreeTraversal::type_; using NTreeTraversal::typeOrder_; using NTreeTraversal::percent; using NTreeTraversal::setNext; private: unsigned long nSolns_; /**< The number of taut angle structures found so far. */ public: /** * Creates a new object for running the tree traversal algorithm. * * This prepares the algorithm; in order to run the algorithm * and enumerate taut angle structures, you can either: * * - call run(), which enumerates all taut angle structures * with a single function call; * * - repeatedly call next(), which will step to the next taut * angle struture surface each time you call it. * * \pre The given triangulation is non-empty. * * \pre The trianglation adheres to any preconditions required by the * template parameters LPConstraint and BanConstraint. * * @param tri the triangulation in which we wish to enumerate * taut angle structures. */ NTautEnumeration(const NTriangulation* tri); /** * Returns the total number of taut angle structures * found thus far in the tree traversal search. * * If you called run(), then this will simply be the total number of * taut angle structures. If you are calling next() one * surface at time, this will be the partial count of how many * taut angle structures have been found until now. * * @return the number of solutions found so far. */ unsigned long nSolns() const; /** * Runs the complete tree traversal algorithm to enumerate * all taut angle structures. * * For each taut angle structure that is found, this routine * will call the function \a useSoln. It will pass two * arguments to this function: (i) this enumeration object, * and (ii) an arbitrary piece of data that you can supply via * the argument \a arg. * * You can extract details of the solution directly from the * enumeration object: for instance, you can dump the type * vector using dumpTypes(), or you can reconstruct the full taut * angle structure using buildStructure() and perform some other * operations upon it. If you do call buildStructure(), remember * to delete the angle structure once you are finished with it. * * The enumeration will block until your callback function * \a useSoln returns. If the callback function returns \c true, * then run() will continue the enumeration. If it returns * \c false, then run() will abort the search and return immediately. * * The usual way of using this routine is to construct an * NTautEnumeration object and then immediately call run(). However, * if you prefer, you may call run() after one or more calls to next(). * In this case, run() will continue the search from the current point * and run it to its completion. In other words, run() will locate * and call \a useSoln for all taut angle structures that had not yet * been found, but it will not call \a useSoln on those solutions * that had previously been found during earlier calls to next(). * * \pre The enumeration algorithm has not yet finished. * That is, you have not called run() before, and if you have * called next() then it has always returned \c true (indicating * that it has not yet finished the search). * * @param useSoln a callback function that will be called each * time we locate a taut angle structure, as described above. * @param arg the second argument to pass to the callback * function; this may be any type of data that you like. */ void run(bool (*useSoln)(const NTautEnumeration&, void*), void* arg = 0); /** * An incremental step in the enumeration algorithm that * runs forward until it finds the next solution. * Specifically: this continues the enumeration from the * current point until either it finds the next taut angle structure * (in which case it returns \c true), or until the * enumeration algorithm is completely finished with no more * solutions to be found (in which case it returns \c false). * * If you simply wish to find and process all taut angle structures, * you may wish to consider the all-in-one routine * run() instead. By using next() to step through one solution * at a time however, you obtain more fine-grained control: for * instance, you can "pause" and restart the search, or have * tighter control over multithreading. * * If next() does return \c true because it found a solution, * you can extract details of the solution directly from this * enumeration object: for instance, you can dump the type * vector using dumpTypes(), or you can reconstruct the full * taut angle structure using buildStructure() and perform some other * operations upon it. If you do call buildStructure(), remember * to delete the angle structure once you are finished with it. * * An optional progress tracker may be passed. If so, this routine * will update the percentage progress and poll for cancellation * requests. It will be assumed that an appropriate stage has already * been declared via NProgressTracker::newStage() before this routine * is called, and that NProgressTracker::setFinished() will be * called after this routine returns (and presumably not until * the entire search tree is exhausted). * The percentage progress will be given in the context of a complete * enumeration of the entire search tree (i.e., it will typically * start at a percentage greater than 0, and end at a percentage less * than 100). * * \pre The enumeration algorithm has not yet finished. * That is, you have not called run() before, and if you have * called next() then it has always returned \c true (indicating * that it has not yet finished the search). * * @param tracker a progress tracker through which progress * will be reported, or 0 if no progress reporting is required. * @return \c true if we found another vertex surface, or * \c false if the search has now finished and no more taut angle * strutures were found. */ bool next(NProgressTracker* tracker = 0); /** * A callback function that writes to standard output the type vector * at the current point in the given tree traversal search. * You can use this as the callback function \a useSoln that is * passed to run(). * * The type vector will be written on a single line, with no * spaces between types, with a prefix indicating which solution * we are up to, and with a final newline appended. * This output format is subject to change in future versions of Regina. * * The second (void*) argument is ignored. It is only present * for compatibility with run(). * * \pre The given tree traversal is at a point in the search where * it has reached the deepest level of the search tree and found a * feasible solution that represents a taut angle structure. * This is always the case any time after next() * returns \c true, or any time that run() calls its callback function. * * @param tree the tree traversal object from which we are * extracting the current type vector. * @return \c true (which indicates to run() that we should * continue the tree traversal). */ static bool writeTypes(const NTautEnumeration& tree, void*); /** * A callback function that writes to standard output the full * angle structure coordinates of the taut angle structure at the * current point in the given tree traversal search. You can use * this as the callback function \a useSoln that is passed to run(). * * The angle structure coordinates will be written on a single line, * with spaces and punctuation separating them, a prefix indicating * which solution we are up to, and a final newline appended. * The final scaling coordinate (used to projectivise the angle * structure polytope) will also be written. * This output format is subject to change in future versions of Regina. * * The second (void*) argument is ignored. It is only present * for compatibility with run(). * * \pre The given tree traversal is at a point in the search where * it has reached the deepest level of the search tree and found a * feasible solution that represents a taut angle structure. * This is always the case any time after next() returns \c true, * or any time that run() calls its callback function. * * @param tree the tree traversal object from which we are * extracting the current taut angle structure. * @return \c true (which indicates to run() that we should * continue the tree traversal). */ static bool writeStructure(const NTautEnumeration& tree, void*); }; /** * The main entry point for the tree traversal / branching algorithm to locate * a single non-trivial normal surface satisfying given constraints within * a 3-manifold triangulation. The constraints are passed using a * combination of the template arguments LPConstraint and BanConstraint. * * A common application of this algorithm is to find a surface of positive * Euler characteristic, using the template argument LPConstraintEuler. * This is useful for tasks such as 0-efficiency testing * and prime decomposition (when this is done in standard normal coordinates), * and also 3-sphere recognition (when this is done in standard almost normal * coordinates). Indeed, the underlying algorithm is optimised for * precisely this application. * * By a "non-trivial" surface, we mean that at least one triangle coordinate * is zero. Philosophically this is to avoid vertex linking surfaces, * though if the triangulation has more than one vertex then this takes * on a different meaning. See the warning on this matter below. * * Be warned that this routine does not eliminate the zero vector, and so * the template argument LPConstraint should include at least one * constraint that eliminates the zero vector (e.g., positive Euler * characteristic). Otherwise this algorithm may simply return the zero * vector, and the information gained will not be very useful. * * For any given normal coordinate, this routine will always try setting * that coordinate to zero before it tries setting it to non-zero. In * other words, if it does find a surface satisfying the given constraints, * then it is guaranteed that the set of non-zero coordinate positions * will be minimal (though not necessary a global \e minimum). * In many settings (such as when using LPConstraintEuler), this guarantees * that the final surface (if it exists) will be a vertex normal or * almost normal surface. * * The underlying algorithm is described in "A fast branching algorithm for * unknot recognition with experimental polynomial-time behaviour", * Burton and Ozlen, arXiv:1211.1079, and uses significant material from * "A tree traversal algorithm for decision problems in knot theory and * 3-manifold topology", Burton and Ozlen, Algorithmica 65:4 (2013), * pp. 772-801. * * To use this class, i.e., to locate a non-trivial normal or almost normal * surface under the given constraints or to prove that no such surface exists, * you can simply construct a NTreeSingleSoln object and call find(). You can * then call buildSurface() to extract the details of the surface that was * found. * * If you wish to enumerate \e all vertex surfaces in a 3-manifold * triangulation (instead of finding just one), you should use the class * NTreeEnumeration instead. * * This tree traversal can only enumerate surfaces in quadrilateral normal * coordinates (NS_QUAD), standard normal coordinates (NS_STANDARD), * quadrilateral-octagon almost normal coordinates (NS_AN_QUAD_OCT), or * standard almost normal coordinates (NS_AN_STANDARD). For almost * normal surfaces, we allow any number of octagons (including zero), * but we only allow at most one octagon \e type in the entire triangulation. * No coordinate systems other than these are supported. * * The template argument \a Integer indicates the integer type that * will be used throughout the underlying linear programming machinery. * Unless you have a good reason to do otherwise, you should use the * arbitrary-precision NInteger class (in which integers can grow * arbitrarily large, and overflow can never occur). * * \warning Typically one should only use this class with \e one-vertex * triangulations (since otherwise, setting at least one triangle coordinate * to zero is not enough to rule out trivial vertex linking surfaces). * Of course there may be settings in which multiple vertices make sense * (for instance, in ideal triangulations with multiple cusps, or when * using ban constraints), and in such settings this class will still work * precisely as described. * * \warning If you examine the type vector (for instance, by calling * dumpTypes()), be aware that this class merges the old types 0 and 1 * together into a single branch of the search tree. This means that * type 0 never appears, and that type 1 could indicate \e either positive * quadrilaterals in the first position, or else no quadrilaterals at all. * * \pre The parameters LPConstraint and BanConstraint must be subclasses of * LPConstraintBase and BanConstraintBase respectively. See the * LPConstraintBase and BanConstraintBase class notes for further details. * * \pre The default constructor for the template class Integer must intialise * each new integer to zero. The classes NInteger and NNativeInteger, * for instance, have this property. * * \apinotfinal * * \ifacespython Not present. */ template class REGINA_API NTreeSingleSoln : public NTreeTraversal { public: using NTreeTraversal::dumpTypes; protected: using NTreeTraversal::level_; using NTreeTraversal::lp_; using NTreeTraversal::lpSlot_; using NTreeTraversal::nextSlot_; using NTreeTraversal::nTets_; using NTreeTraversal::nTypes_; using NTreeTraversal::nVisited_; using NTreeTraversal::octLevel_; using NTreeTraversal:: origTableaux_; using NTreeTraversal::tmpLP_; using NTreeTraversal::type_; using NTreeTraversal::typeOrder_; using NTreeTraversal:: feasibleBranches; using NTreeTraversal:: nextUnmarkedTriangleType; using NTreeTraversal::percent; using NTreeTraversal::setNext; private: int nextZeroLevel_; /**< The next level in the search tree at which we will force some triangle coordinate to zero. We use this to avoid vertex links by dynamically reorganising the search tree as we run to ensure that at least one relevant triangle coordinate is set to zero at all stages and all levels of the search. */ bool cancelled_; /**< Has the search been cancelled by another thread? See the cancel() and cancelled() routines for details. */ regina::NMutex mCancel_; /**< A mutex used to serialise cancellation tests and requests. */ public: /** * Creates a new object for running the tree traversal / branching * algorithm to locate a non-trivial surface that satisfies the * chosen constraints. * * This constructor prepares the algorithm; in order to run the * algorithm you should call find(), which returns \c true or \c false * according to whether or not such a surface was found. * * \pre The given triangulation is non-empty. * * \pre Both the trianglation and the given coordinate system * adhere to any preconditions required by the template * parameters LPConstraint and BanConstraint. * * @param tri the triangulation in which we wish to search for a * non-trivial surface. * @param coords the normal or almost normal coordinate system in * which to work. This must be one of NS_QUAD, NS_STANDARD, * NS_AN_QUAD_OCT, or NS_AN_STANDARD. */ NTreeSingleSoln(const NTriangulation* tri, NormalCoords coords); /** * Runs the tree traversal algorithm until it finds some non-trivial * surface that satisfies the chosen constraints, or else proves that * no such solution exists. * * Note that, if a solution is found, it will have a maximal * (but not necessarily maximum) set of zero coordinates, which * in some settings is enough to guarantee a vertex normal surface. * See the NTreeSingleSoln class notes for details. * * If find() does return \c true, you can extract details of the * corresponding surface directly from this tree enumeration * object: for instance, you can dump the type vector using * dumpTypes(), or you can reconstruct the full surface using * buildSurface(). Be warned that this class defines the type * vector in an unusual way (see the NTreeSingleSoln class notes * for details). If you call buildSurface(), remember * to delete the surface once you are finished with it. * * \pre The algorithm has not yet been run, i.e., you have not called * find() before. * * @return \c true if we found a non-trivial solution as described * in the class notes, or \c false if no such solution exists. */ bool find(); /** * Cancels the current find() operation. * * This may be called from another thread (it is thread-safe). * If called, it signals that if find() is currently running * then it should be cancelled at the earliest convenient opportunity. */ void cancel(); private: /** * Returns whether some thread has requested that the current * search operation be cancelled. This routine is thread-safe. * * See cancel() for details on how cancellation works. * * @return \c true if some thread has called cancel() on this object. */ bool cancelled() const; }; // Inline functions template inline bool NTreeTraversal::supported( NormalCoords coords) { return (coords == NS_STANDARD || coords == NS_AN_STANDARD || coords == NS_QUAD || coords == NS_AN_QUAD_OCT || coords == NS_ANGLE) && LPConstraint::supported(coords) && BanConstraint::supported(coords); } template inline bool NTreeTraversal:: constraintsBroken() const { return origTableaux_.constraintsBroken(); } template inline unsigned long NTreeTraversal:: nVisited() const { return nVisited_; } template inline void NTreeTraversal::dumpTypes( std::ostream& out) const { for (unsigned i = 0; i < nTypes_; ++i) out << static_cast(type_[i]); } template inline int NTreeTraversal:: nextUnmarkedTriangleType(int startFrom) { while (startFrom < nTypes_ && BanConstraint::marked_[2 * nTets_ + startFrom]) ++startFrom; return (startFrom == nTypes_ ? -1 : startFrom); } template inline NTreeEnumeration::NTreeEnumeration( const NTriangulation* tri, NormalCoords coords) : NTreeTraversal(tri, coords, (coords == NS_AN_QUAD_OCT || coords == NS_AN_STANDARD ? 7 : 4) /* branches per quad */, 2 /* branches per triangle */, true /* enumeration */), nSolns_(0), lastNonZero_(-1) { } template inline unsigned long NTreeEnumeration:: nSolns() const { return nSolns_; } template inline void NTreeEnumeration::run( bool (*useSoln)(const NTreeEnumeration&, void*), void* arg) { while (next()) if (! useSoln(*this, arg)) return; } template inline bool NTreeEnumeration::writeTypes( const NTreeEnumeration& tree, void*) { std::cout << "SOLN #" << tree.nSolns() << ": "; tree.dumpTypes(std::cout); std::cout << std::endl; return true; } template inline bool NTreeEnumeration:: writeSurface(const NTreeEnumeration& tree, void*) { std::cout << "SOLN #" << tree.nSolns() << ": "; NNormalSurface* f = tree.buildSurface(); std::cout << f->str() << std::endl; delete f; return true; } template inline NTautEnumeration::NTautEnumeration( const NTriangulation* tri) : NTreeTraversal(tri, NS_ANGLE, 3 /* branches per quad */, 0 /* branches per triangle; irrelevant here */, true /* enumeration */), nSolns_(0) { } template inline unsigned long NTautEnumeration:: nSolns() const { return nSolns_; } template inline void NTautEnumeration::run( bool (*useSoln)(const NTautEnumeration&, void*), void* arg) { while (next()) if (! useSoln(*this, arg)) return; } template inline bool NTautEnumeration::writeTypes( const NTautEnumeration& tree, void*) { std::cout << "SOLN #" << tree.nSolns() << ": "; tree.dumpTypes(std::cout); std::cout << std::endl; return true; } template inline NTreeSingleSoln::NTreeSingleSoln( const NTriangulation* tri, NormalCoords coords) : NTreeTraversal(tri, coords, (coords == NS_AN_QUAD_OCT || coords == NS_AN_STANDARD ? 6 : 3) /* branches per quad */, 2 /* branches per triangle */, false /* enumeration */), nextZeroLevel_(0), cancelled_(false) { } template inline void NTreeSingleSoln::cancel() { regina::NMutex::MutexLock lock(mCancel_); cancelled_ = true; } template inline bool NTreeSingleSoln::cancelled() const { regina::NMutex::MutexLock lock(mCancel_); return cancelled_; } } // namespace regina #endif regina-4.96/engine/enumerate/ntreetraversal.tcc000644 000765 000024 00000004700 12400001243 021561 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file enumerate/ntreetraversal.tcc * \brief Deprecated header. */ #warning This header is deprecated; please use ntreetraversal-impl.h instead. #include "enumerate/ntreetraversal-impl.h" regina-4.96/engine/enumerate/ntypetrie.cpp000644 000765 000024 00000012254 12377776606 020622 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 2011-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "enumerate/ntypetrie.h" namespace regina { template void NTypeTrie::insert(const char* entry, unsigned len) { // Strip off trailing zeroes. while (len > 0 && ! entry[len - 1]) --len; // Insert this type vector, creating new nodes only when required. NTypeTrie* node = this; const char* next = entry; for (int pos = 0; pos < len; ++pos, ++next) { if (! node->child_[*next]) node->child_[*next] = new NTypeTrie(); node = node->child_[*next]; } node->elementHere_ = true; } template bool NTypeTrie::dominates(const char* vec, unsigned len) const { // Strip off trailing zeroes. while (len > 0 && ! vec[len - 1]) --len; // At worst we have a recursive O(2^len) search on our hands. // Create a stack of options that describe which branch of the // trie we follow at each stage of the search. // // Here node[i] will store the next candidate node to try at // depth i in the tree (where the root is at depth 0), or 0 // if we have exhausted our options at that level of the search. const NTypeTrie** node = new const NTypeTrie*[len + 2]; int level = 0; node[0] = this; while (level >= 0) { if ((! node[level]) || level > len) { // If node[level] is 0, then we ran out of siblings // at this level. // If level > len, then any vector in this subtree // must have non-zero elements where vec only has zeros. // Either way, we need to backtrack. // Move back up one level... --level; // ... and then move to the next sibling at this (higher) // level. if (level > 0 && node[level] == node[level - 1]->child_[0] && vec[level - 1]) node[level] = node[level - 1]->child_[vec[level - 1]]; else if (level >= 0) node[level] = 0; continue; } // Process the node at the current level. if (node[level]->elementHere_) { // This node (padded with trailing zeroes) is // dominated by the given type vector. delete[] node; return true; } // Descend further into the tree. // // If vec[level] == 0, we must descend to child_[0]. // Otherwise we try child_[0] and then child_[type]. // // The following code sets node[level + 1] to the first non-zero // child in this selection, or to 0 if all such children are 0. if (node[level]->child_[0]) node[level + 1] = node[level]->child_[0]; else node[level + 1] = node[level]->child_[vec[level]]; ++level; } delete[] node; return false; } // Instantiate the templates! template class NTypeTrie<7>; } // namespace regina regina-4.96/engine/enumerate/ntypetrie.h000644 000765 000024 00000016504 12377775161 020264 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 2011-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file enumerate/ntypetrie.h * \brief A supporting data structure for tree traversal enumeration methods. */ #ifndef __NTYPETRIE_H #ifndef __DOXYGEN #define __NTYPETRIE_H #endif #include namespace regina { /** * \weakgroup enumerate * @{ */ /** * A trie that stores a set of type vectors of a fixed length. * * This class forms part of the tree traversal algorithm for enumerating * vertex normal surfaces, as described in "A tree traversal algorithm * for decision problems in knot theory and 3-manifold topology", * Burton and Ozlen, Algorithmica 65:4 (2013), pp. 772-801. * * A type vector is a sequence of digits, each between 0 and \a nTypes-1 * inclusive. Type vectors are represented as arrays of characters: * these are not strings, but simply sequences of one-byte integers. * In particular, you cannot print them (since they use raw integer * values, not ASCII digits). The length of a type vector must be * passed alongside it (i.e., there is no special terminating character). * * A type vector \a v is said to \e dominate \a u if, for each position * \a i, either v[i] == u[i] or else u[i] == 0. So, for instance, * (1,0,2,3) dominates (1,0,2,0), which in turn dominates (1,0,0,0). * Domination is a partial order, not a total order: for instance, * neither of (1,0,2,0) or (1,0,3,0) dominates the other. * * We assume that all type vectors used in this trie have the same * length. This is important, since we optimise the implementation by * ignoring trailing zeroes, which means that this trie cannot distinguish * between a vector \a v and the same vector with additional zeroes * appended to its end. * * Internally, each node of the trie is represented by a separate * NTypeTrie object, each of which is responsible for managing the * lifespan of its descendant nodes. Externally, a user only needs * to create and manage a single NTypeTrie object (which becomes * the root of the trie). * * \pre \a nTypes is at most 256. The typical value for \a nTypes for * normal surface enumeration is \a nTypes = 4. * * \ifacespython Not present. */ template class NTypeTrie { private: NTypeTrie* child_[nTypes]; /**< If this node is \a k levels deeper than the root of the trie (that is, it corresponds to the \a kth position in the type vector), then child_[i] stores the subtrie of type vectors \a v for which v[k] == i. */ bool elementHere_; /**< \c true if the path from the root of the trie to this node precisely describes the elements of some type vector in the set, ignoring any trailing zeroes. (In particular, the zero vector is in the set if and only if \a elementHere_ is \c true at the root node.) If this is \c false at a non-root node, then the fact that the node was ever constructed means that the path from the root to this node describes some \e prefix of a longer type vector in the set that has additional subsequent non-zero elements. */ public: /** * Initialises an empty trie. */ inline NTypeTrie(); /** * Destroys this trie. */ inline ~NTypeTrie(); /** * Resets this to the empty trie. */ inline void clear(); /** * Inserts the given type vector into this trie. * * \pre The given length \a len is non-zero, and is fixed throughout * the life of this trie; that is, it is the same every time * insert() or dominates() is called. * * @param entry the type vector to insert. * @param len the number of elements in the given type vector. */ void insert(const char* entry, unsigned len); /** * Determines whether the given type vector dominates any vector * in this trie. * * \pre The given length \a len is non-zero, and is fixed throughout * the life of this trie; that is, it is the same every time * insert() or dominates() is called. * * @param vec the type vector to test. * @param len the number of elements in the given type vector. * @return \c true if and only if \a vec dominates some type * vector stored in this trie. */ bool dominates(const char* vec, unsigned len) const; }; // Inline functions for NTypeTrie template inline NTypeTrie::NTypeTrie() : elementHere_(false) { ::memset(child_, 0, sizeof(NTypeTrie*) * nTypes); } /** * Destroys this trie. */ template inline NTypeTrie::~NTypeTrie() { for (int i = 0; i < nTypes; ++i) delete child_[i]; } /** * Resets this to the empty trie. */ template inline void NTypeTrie::clear() { for (int i = 0; i < nTypes; ++i) { delete child_[i]; child_[i] = 0; } elementHere_ = false; } } // namespace regina #endif regina-4.96/engine/enumerate/ordering.h000644 000765 000024 00000012226 12377775162 020050 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file enumerate/ordering.h * \brief Provides different ways of sorting hyperplanes (or matching * equations) when performing normal surface enumeration. */ #ifndef __ORDERING_H #ifndef __DOXYGEN #define __ORDERING_H #endif #include "regina-core.h" #include "maths/nmatrixint.h" namespace regina { /** * \weakgroup enumerate * @{ */ /** * A comparison object that sorts hyperplanes by position vectors. * This ordering is described in "Optimizing the double description * method for normal surface enumeration", B.A. Burton, * Mathematics of Computation 79 (2010), 453-484. * * This comparison object is used to sort hyperplanes into a good * order before enumerating vertex or fundamental normal surfaces * A hyperplane is described by a row of the \a subspace matrix, * as passed to an enumeration routine such as * NDoubleDescription::enumerateExtremalRays() or * NHilbertDual::enumerateHilbertBasis(). * * The ordering is defined as follows. For each hyperplane, we * create a position vector (h_1, ..., h_f), where h_i is 0 if the * hyperplane contains the ith coordinate axis, or 1 if not. * We then compare these position vectors lexicographically. * * \ifacespython Not present. */ class NPosOrder { private: const NMatrixInt& matrix_; /**< The \a subspace matrix as passed to the enumeration routine. */ public: /** * Creates a new helper object for comparing hyperplanes. * * @param matrix the \a subspace matrix as passed to * the normal surface enumeration routine. */ inline NPosOrder(const NMatrixInt& matrix); /** * Determines whether the hyperplane described by * row \a i of the matrix is smaller * than the hyperplane described by row \a j. * Here "smaller" is defined by position vectors; * see the NPosOrder class notes for details. * * @param i the first matrix row index; this must be between * 0 and matrix.rows()-1 inclusive, where \a matrix is * the matrix passed to the class constructor. * @param j the second matrix row index; this must also be * between 0 and matrix.rows()-1 inclusive. * @return \c true if and only if the hyperplane described by * row \a i is smaller than the hyperplane described by row \a j. */ inline bool operator () (long i, long j) const; }; /*@}*/ // Inline functions for NPosOrder inline NPosOrder::NPosOrder(const NMatrixInt& matrix) : matrix_(matrix) { } inline bool NPosOrder::operator () ( long i, long j) const { for (unsigned long c = 0; c < matrix_.columns(); ++c) { if (matrix_.entry(i, c) == 0 && matrix_.entry(j, c) != 0) return true; if (matrix_.entry(i, c) != 0 && matrix_.entry(j, c) == 0) return false; } return false; } } // namespace regina #endif regina-4.96/engine/file/CMakeLists.txt000644 000765 000024 00000000710 12377774107 017551 0ustar00babstaff000000 000000 # file # Files to compile SET ( FILES nfileinfo nglobaldirs) # Prepend folder name FOREACH ( SOURCE_FILE ${FILES} ) SET ( SOURCES ${SOURCES} file/${SOURCE_FILE}) ENDFOREACH(SOURCE_FILE) SET(SOURCES ${SOURCES} PARENT_SCOPE) if (${REGINA_INSTALL_DEV}) INSTALL(FILES nfileinfo.h nglobaldirs.h nxmlcallback.h nxmlelementreader.h nxmlfile.h DESTINATION ${INCLUDEDIR}/file COMPONENT Development) endif (${REGINA_INSTALL_DEV}) regina-4.96/engine/file/nfileinfo.cpp000644 000765 000024 00000014702 12377776607 017503 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include #include "file/nfileinfo.h" #include "utilities/zstream.h" namespace regina { #define STARTS_FALSE 0 #define STARTS_TRUE 1 #define STARTS_COULD_NOT_OPEN 2 // const int NFileInfo::TYPE_BINARY = 1; // OBSOLETE as of Regina 4.94. const int NFileInfo::TYPE_XML = 2; namespace { /** * Does the given file begin with the given set of characters? * * Returns STARTS_FALSE, STARTS_TRUE or STARTS_COULD_NOT_OPEN. */ int fileStartsWith(const char* file, const char* prefix) { FILE* f = fopen(file, "rb"); if (! f) return STARTS_COULD_NOT_OPEN; int ans = STARTS_FALSE; size_t len = strlen(prefix); char* buf = new char[len]; if (fread(buf, sizeof(char), len, f) == len) if (strncmp(buf, prefix, len) == 0) ans = STARTS_TRUE; delete[] buf; fclose(f); return ans; } } NFileInfo* NFileInfo::identify(const std::string& idPathname) { // Check for an old-style binary file. int starts = fileStartsWith(idPathname.c_str(), "compressed = false; } else { regina::DecompressionStream in(idPathname.c_str()); if (in) { std::string s; in >> s; if ((! in.eof()) && (s == "compressed = true; } } } if (ans) { ans->pathname = idPathname; ans->type = NFileInfo::TYPE_XML; ans->typeDescription = "XML Regina data file"; // Make it an invalid file until we know otherwise. ans->invalid = true; regina::DecompressionStream in(idPathname.c_str()); if (! in) return ans; std::string s; // Start by slurping in the opening "> s; if (s != "". // Try skipping through several strings in case there are extra // arguments in the XML prologue (such as encoding or standalone // declarations). int i; for (i = 0; ; i++) { if (in.eof()) return ans; in >> s; if (s.length() >= 2 && s[s.length() - 2] == '?' && s[s.length() - 1] == '>') break; // If we can't find it after enough tries, just give up. // Ten tries should be more than sufficient, since the current XML // spec supports only version, encoding and standalone arguments // at present. if (i >= 10) return ans; } // The next thing we see should be the element. if (in.eof()) return ans; in >> s; if (s != "> s; if (s.length() < 8) return ans; if (s.substr(0, 8).compare("engine=\"") != 0) return ans; // We've found the engine attribute; extract its value. std::string::size_type pos = s.find('"', 8); if (pos == std::string::npos) return ans; ans->engine = s.substr(8, pos - 8); // That's as far as we need to go; we've extracted everything we want. ans->invalid = false; return ans; } // Unknown format. return 0; } void NFileInfo::writeTextShort(std::ostream& out) const { out << "File information: " << typeDescription; if (compressed) out << " (compressed)"; } void NFileInfo::writeTextLong(std::ostream& out) const { out << "Regina data\n" << typeDescription; if (compressed) out << " (compressed)"; out << '\n'; if (invalid) out << "File contains invalid metadata.\n"; else out << "Engine " << engine << '\n'; } } // namespace regina regina-4.96/engine/file/nfileinfo.h000644 000765 000024 00000016031 12377775163 017141 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file file/nfileinfo.h * \brief Deals with determining information about Regina data files. */ #ifndef __NFILEINFO_H #ifndef __DOXYGEN #define __NFILEINFO_H #endif #include "regina-core.h" #include "shareableobject.h" namespace regina { /** * \weakgroup file * @{ */ /** * Stores information about a Regina data file, including file type and * version. * * Routine identify() can be used to determine this information for a * given file. * * As of Regina 4.94, the old-style binary files are no longer supported. * These have not been in use for over a decade. The only file type * that this class now recognises is TYPE_XML (compressed or uncompressed * XML data files). */ class REGINA_API NFileInfo : public ShareableObject { public: static const int TYPE_XML; /**< Represents a new-style XML data file. */ private: std::string pathname; /**< The pathname of the data file being described. */ int type; /**< The type of data file; this will be one of the file type constants defined in this class. */ std::string typeDescription; /**< A human-readable description of the type of data file. */ std::string engine; /**< The version of the calculation engine that wrote this file. */ bool compressed; /**< \c true if this file is stored in compressed format, \c false otherwise. Currently this option only applies to XML data files. */ bool invalid; /**< \c true if the file metadata could not be read, \c false otherwise. */ public: /** * Returns the pathname of the data file being described. * * \i18n The \ref i18n "character encoding" used in the pathname will * be whatever was originally passed to identify(). This might or * might not be UTF-8, since it needs to be understood by the * low-level C/C++ file I/O routines. * * @return the pathname. */ const std::string& getPathname() const; /** * Returns the type of data file. The type will be given as one * of the file type constants defined in this class. * * @return the type of data file. */ int getType() const; /** * Returns a human-readable description of the type of data file. * * @return a description of the type of data file. */ const std::string& getTypeDescription() const; /** * Returns the version of the calculation engine that wrote this file. * * @return the engine version for this file. */ const std::string& getEngine() const; /** * Returns whether this file is stored in compressed format. * Currently this option only applies to XML data files. * * @return \c true if this file is compressed or \c false otherwise. */ bool isCompressed() const; /** * Returns whether the file metadata could not be read. * * @return \c true if the metadata could not be read, \c false * otherwise. */ bool isInvalid() const; /** * Return information about the given Regina data file. * * \i18n This routine makes no assumptions about the * \ref i18n "character encoding" used in the given path \e name, * and simply passes it through unchanged to low-level C/C++ file I/O * routines. If an NFileInfo structure is returned, its getPathname() * routine will use the same encoding that is passed here. * * @param idPathname the pathname of the data file to be examined. * @return a newly created NFileInfo structure containing * information about the given file, or 0 if the file type could not * be identified. */ static NFileInfo* identify(const std::string& idPathname); void writeTextShort(std::ostream& out) const; void writeTextLong(std::ostream& out) const; private: /** * Create a new uninitialised structure. */ NFileInfo(); }; /*@}*/ // Inline functions for NFileInfo inline NFileInfo::NFileInfo() { } inline const std::string& NFileInfo::getPathname() const { return pathname; } inline int NFileInfo::getType() const { return type; } inline const std::string& NFileInfo::getTypeDescription() const { return typeDescription; } inline const std::string& NFileInfo::getEngine() const { return engine; } inline bool NFileInfo::isCompressed() const { return compressed; } inline bool NFileInfo::isInvalid() const { return invalid; } } // namespace regina #endif regina-4.96/engine/file/nglobaldirs.cpp000644 000765 000024 00000006011 12377776610 020016 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "regina-config.h" #include "file/nglobaldirs.h" namespace regina { std::string NGlobalDirs::home_(REGINA_DATADIR); std::string NGlobalDirs::pythonModule_(REGINA_PYLIBDIR); std::string NGlobalDirs::home() { return home_; } std::string NGlobalDirs::pythonModule() { return pythonModule_; } std::string NGlobalDirs::pythonLibs() { return home_ + "/pylib"; } std::string NGlobalDirs::examples() { return home_ + "/examples"; } std::string NGlobalDirs::engineDocs() { return home_ + "/engine-docs"; } std::string NGlobalDirs::data() { return home_ + "/data"; } void NGlobalDirs::setDirs(const std::string& homeDir, const std::string& pythonModuleDir) { home_ = homeDir; pythonModule_ = pythonModuleDir; } } // namespace regina regina-4.96/engine/file/nglobaldirs.h000644 000765 000024 00000020745 12377775164 017500 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file file/nglobaldirs.h * \brief Gives information about system installation directories. */ #ifndef __NGLOBALDIRS_H #ifndef __DOXYGEN #define __NGLOBALDIRS_H #endif #include #include "regina-core.h" namespace regina { /** * \weakgroup file * @{ */ /** * Provides global routines that return directories in which various * components of Regina are installed on the system. * * By default, these routines are only useful with a fixed filesystem * installation of Regina (e.g., a typical Linux install). Specifically, * they return the relevant directories as they were configured by \e cmake * at build time. * * If Regina may have been moved around on the filesystem (e.g., if you are * running an app bundle on MacOS), you \e must call setDirs() when your * application starts. Otherwise the directories that NGlobalDirs returns * might be incorrect, and might not even exist. * * At present this class does not support running Regina directly out of * the source tree. This might be supported in future versions of Regina. */ class REGINA_API NGlobalDirs { public: /** * Returns Regina's primary home directory on the system. This * directory should contains subdirectories \e icons/, * \e examples/ and so on. * * \warning If Regina is not installed in the exact location * configured at compile time (e.g., if you are running a MacOSX * app bundle), you \e must call setDirs() before calling this routine. * \warning If you are running out of the source tree, this * routine will almost certainly return an incorrect (and possibly * non-existent) directory. * * @return Regina's primary home directory. */ static std::string home(); /** * Returns the directory in which Regina's python module is installed, * or the empty string if the module is installed in python's * standard site-packages directory. * * \warning If Regina is not installed in the exact location * configured at compile time (e.g., if you are running a MacOSX * app bundle), you \e must call setDirs() before calling this routine. * \warning If you are running out of the source tree, this * routine will almost certainly return an incorrect (and possibly * non-existent) directory. * * @return Regina's python module directory. */ static std::string pythonModule(); /** * Returns the directory in which optional "helper" Python libraries * are installed. These libraries are not a formal part of Regina, * but can be made to load automatically as extra user libraries * through Regina's python settings. * * \warning If Regina is not installed in the exact location * configured at compile time (e.g., if you are running a MacOSX * app bundle), you \e must call setDirs() before calling this routine. * \warning If you are running out of the source tree, this * routine will almost certainly return an incorrect (and possibly * non-existent) directory. * * @return Regina's optional Python library directory. */ static std::string pythonLibs(); /** * Returns the directory in which example data files and census * data files are installed. * * \warning If Regina is not installed in the exact location * configured at compile time (e.g., if you are running a MacOSX * app bundle), you \e must call setDirs() before calling this routine. * \warning If you are running out of the source tree, this * routine will almost certainly return an incorrect (and possibly * non-existent) directory. * * @return Regina's example and census data directory. */ static std::string examples(); /** * Returns the directory in which API documentation for Regina's * calculation engine is installed. * * \warning If Regina is not installed in the exact location * configured at compile time (e.g., if you are running a MacOSX * app bundle), you \e must call setDirs() before calling this routine. * \warning If you are running out of the source tree, this * routine will almost certainly return an incorrect (and possibly * non-existent) directory. * * @return Regina's calculation engine documentation directory. */ static std::string engineDocs(); /** * Returns the directory containing internal data files for Regina's * calculation engine. * * \warning If Regina is not installed in the exact location * configured at compile time (e.g., if you are running a MacOSX * app bundle), you \e must call setDirs() before calling this routine. * \warning If you are running out of the source tree, this * routine will almost certainly return an incorrect (and possibly * non-existent) directory. * * @return Regina's calculation engine data directory. */ static std::string data(); /** * Tells Regina where data files are installed. This is * necessary if Regina is not installed in the location that was * configured by \e cmake at build time (e.g., if you are * running a MacOSX app bundle). * * @param homeDir Regina's primary home directory; this will be * returned by homeDir(). * @param pythonModuleDir the directory containing Regina's * python module, or the empty string if the module has been * installed in python's standard site-packages directory; * this will be returned by pythonModule(). */ static void setDirs(const std::string& homeDir, const std::string& pythonModuleDir); private: static std::string home_; /**< Regina's primary home directory. */ static std::string pythonModule_; /**< The directory containing Regina's python module. */ }; /*@}*/ } // namespace regina #endif regina-4.96/engine/file/nxmlcallback.h000644 000765 000024 00000004723 12377775166 017633 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #ifndef __LEGACY_NXMLCALLBACK_H #ifndef __DOXYGEN #define __LEGACY_NXMLCALLBACK_H #endif #warning This header is deprecated; please use utilities/nxmlcallback.h instead. #include "utilities/nxmlcallback.h" #endif regina-4.96/engine/file/nxmlelementreader.h000644 000765 000024 00000004747 12377775170 020714 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #ifndef __LEGACY_NXMLELEMENTREADER_H #ifndef __DOXYGEN #define __LEGACY_NXMLELEMENTREADER_H #endif #warning This header is deprecated; please use utilities/nxmlelementreader.h instead. #include "utilities/nxmlelementreader.h" #endif regina-4.96/engine/file/nxmlfile.h000644 000765 000024 00000010302 12377775172 017001 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file file/nxmlfile.h * \brief Deals with storing program data (including packet trees) * in XML data files. * * \deprecated The global functions that were once declared in this file have * been renamed, and are now declared in npacket.h. */ #ifndef __NXMLFILE_H #ifndef __DOXYGEN #define __NXMLFILE_H #endif #include #include "regina-core.h" #include "packet/npacket.h" namespace regina { class NPacket; /** * \addtogroup file File I/O * File reading and writing. * @{ */ /** * Deprecated routine that writes a packet tree (or subtree) to a Regina * data file using Regina's native XML file format. * * \deprecated This routine has been renamed as NPacket::save(). * See the documentation of NPacket::save() for further details. */ REGINA_API bool writeXMLFile(const char* filename, NPacket* subtree, bool compressed = true); /** * Deprecated routine that reads a packet tree from the given Regina * data file using Regina's native XML file format. * * \deprecated This routine has been renamed as regina::open(), and is * now declared in npacket.h. See the documentation for regina::open() * for further details. */ REGINA_API NPacket* readXMLFile(const char* filename); /** * Deprecated routine that reads a packet tree from the given Regina * data file using Regina's native XML file format. * * \deprecated This routine has been renamed as regina::open(), and is * now declared in npacket.h. See the documentation for regina::open() * for further details. */ REGINA_API NPacket* readFileMagic(const std::string& filename); /*@}*/ // Inline functions: inline bool writeXMLFile(const char* filename, NPacket* subtree, bool compressed) { return subtree->save(filename, compressed); } inline NPacket* readXMLFile(const char* filename) { return regina::open(filename); } inline NPacket* readFileMagic(const std::string& filename) { return regina::open(filename.c_str()); } } // namespace regina #endif regina-4.96/engine/foreign/casson.h000644 000765 000024 00000002576 12234011536 017154 0ustar00babstaff000000 000000 /** * This is the file casson.h. It was initially written by Damien Heard * as part of the program Orb (http://www.ms.unimelb.edu.au/~snap/orb.html). * * This header was introduced into Regina for the Orb / Casson import * and export routines, which were contributed by Ryan Budney. It is * for internal use by these routines only; any other code should call * the public routines from orb.h. * * Many thanks to Damien Heard for giving permission for his code to * be distributed under the terms of the GNU General Public License. */ #ifndef CASSON_H #define CASSON_H #include "regina-core.h" #define LN(ch) (ch=='u') ? 0 : ((ch=='v') ? 1 : ((ch=='w') ? 2 : 3)) const int vertex_at_faces[4][4] = {{9,2,3,1}, {3,9,0,2}, {1,3,9,0}, {2,0,1,9}}; typedef struct CassonFormat CassonFormat; typedef struct EdgeInfo EdgeInfo; typedef struct TetEdgeInfo TetEdgeInfo; struct REGINA_LOCAL CassonFormat { int num_tet; EdgeInfo *head; }; struct REGINA_LOCAL EdgeInfo { int index, singular_index; double singular_order; TetEdgeInfo *head; EdgeInfo *prev, *next; }; struct REGINA_LOCAL TetEdgeInfo { int tet_index,f1,f2; TetEdgeInfo *prev, *next; }; #endif regina-4.96/engine/foreign/CMakeLists.txt000644 000765 000024 00000000761 12377774107 020271 0ustar00babstaff000000 000000 # foreign # Files to compile SET ( FILES dehydration isosig orb pdf snappea ) # Prepend folder name FOREACH ( SOURCE_FILE ${FILES} ) SET ( SOURCES ${SOURCES} foreign/${SOURCE_FILE}) ENDFOREACH(SOURCE_FILE) SET(SOURCES ${SOURCES} PARENT_SCOPE) if (${REGINA_INSTALL_DEV}) INSTALL(FILES csvsurfacelist.h dehydration.h isosig.h orb.h pdf.h recogniser.h snappea.h DESTINATION ${INCLUDEDIR}/foreign COMPONENT Development) endif (${REGINA_INSTALL_DEV}) regina-4.96/engine/foreign/csvsurfacelist.h000644 000765 000024 00000010451 12377775176 020746 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file foreign/csvsurfacelist.h * \brief Exports normal surface lists to plain text CSV files. * * \deprecated The enumeration type SurfaceExportFields (which was once * declared in this file) is now declared in surfaces/nnormalsurfacelist.h. * Moreover, all global functions that were once declared in this file have * now been renamed to member functions of NNormalSurfaceList. * Please include surfaces/nnormalsurfacelist.h instead. */ #ifndef __CSVSURFACELIST_H #ifndef __DOXYGEN #define __CSVSURFACELIST_H #endif #include #include "regina-core.h" #include "surfaces/nnormalsurfacelist.h" namespace regina { class NNormalSurfaceList; /** * \weakgroup foreign * @{ */ /** * Deprecated function that exports the given list of normal surfaces as a * plain text CSV (comma-separated value) file, using standard * triangle-quadrilateral coordinates. * * \deprecated This routine has been renamed as * NNormalSurfaceList::saveCSVStandard(). See the documentation for * NNormalSurfaceList::saveCSVStandard() for further details. */ REGINA_API bool writeCSVStandard(const char* filename, NNormalSurfaceList& surfaces, int additionalFields = surfaceExportAll); /** * Deprecated function that exports the given list of normal surfaces as a * plain text CSV (comma-separated value) file, using edge weight coordinates. * * \deprecated This routine has been renamed as * NNormalSurfaceList::saveCSVEdgeWeight(). See the documentation for * NNormalSurfaceList::saveCSVEdgeWeight() for further details. */ REGINA_API bool writeCSVEdgeWeight(const char* filename, NNormalSurfaceList& surfaces, int additionalFields = surfaceExportAll); /*@}*/ inline bool writeCSVStandard(const char* filename, NNormalSurfaceList& surfaces, int additionalFields) { return surfaces.saveCSVStandard(filename, additionalFields); } inline bool writeCSVEdgeWeight(const char* filename, NNormalSurfaceList& surfaces, int additionalFields) { return surfaces.saveCSVEdgeWeight(filename, additionalFields); } } // namespace regina #endif regina-4.96/engine/foreign/dehydration.cpp000644 000765 000024 00000010766 12377776610 020556 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include "foreign/dehydration.h" #include "packet/ncontainer.h" #include "packet/ntext.h" #include "triangulation/ntriangulation.h" namespace regina { NContainer* readDehydrationList(const char *filename, unsigned colDehydrations, int colLabels, unsigned long ignoreLines) { // Open the file. std::ifstream in(filename); if (! in) return 0; // Ignore the specified number of lines. std::string line; unsigned long i; for (i = 0; i < ignoreLines; i++) { std::getline(in, line); if (in.eof()) return new NContainer(); } // Read in and process the remaining lines. NContainer* ans = new NContainer(); std::string errStrings; int col; std::string token; std::string dehydration; std::string label; NTriangulation* tri; while(! in.eof()) { // Read in the next line. line.clear(); std::getline(in, line); if (line.empty()) continue; // Find the appropriate tokens. std::istringstream tokens(line); dehydration.clear(); label.clear(); for (col = 0; col <= static_cast(colDehydrations) || col <= colLabels; col++) { tokens >> token; if (token.empty()) break; if (col == static_cast(colDehydrations)) dehydration = token; if (col == colLabels) label = token; } if (! dehydration.empty()) { // Process this dehydration string. tri = new NTriangulation(); if (tri->insertRehydration(dehydration)) { tri->setPacketLabel(label.empty() ? dehydration : label); ans->insertChildLast(tri); } else { errStrings = errStrings + '\n' + dehydration; delete tri; } } } // Finish off. if (! errStrings.empty()) { NText* errPkt = new NText(std::string( "The following dehydration string(s) could not be rehydrated:\n") + errStrings); errPkt->setPacketLabel("Errors"); ans->insertChildLast(errPkt); } return ans; } } // namespace regina regina-4.96/engine/foreign/dehydration.h000644 000765 000024 00000011362 12377775200 020206 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file foreign/dehydration.h * \brief Allows reading lists of dehydrated triangulations. */ #ifndef __DEHYDRATION_H #ifndef __DOXYGEN #define __DEHYDRATION_H #endif #include "regina-core.h" namespace regina { class NContainer; /** * \weakgroup foreign * @{ */ /** * Reads a list of dehydrated triangulations from the given text file. * The file should contain one dehydration string per line. These * strings will be rehydrated as described in * NTriangulation::insertRehydration(). * * A newly allocated container will be returned; the imported * triangulations will be inserted as children of this container. * The container will not be assigned a label. The individual * triangulations will be assigned labels according to the parameter * \a colLabels. * * If any dehydrations strings are invalid, these will be recorded in an * additional text packet that will be the last child of the returned * container. * * If an I/O error occurred while trying to read the given file, 0 will be * returned. * * In its simplest form, the text file can simply contain one * dehydration string per line and nothing else. However, more complex * formats are allowed. In particular, by passing appropriate values * for the arguments \a colDehydrations and \a colLabels, the dehydration * strings and triangulation packet labels can be taken from arbitrary * columns of the text file. Columns are considered to be separated by * whitespace and are numbered beginning at 0. * * \i18n This routine makes no assumptions about the * \ref i18n "character encoding" used in the given file \e name, and * simply passes it through unchanged to low-level C/C++ file I/O routines. * It assumes however that the \e contents of the file are in UTF-8. * * @param filename the name of the text file from which to read. * @param colDehydrations the column of the text file containing the * dehydration strings. * @param colLabels the column of the text file containing the * triangulation packet labels. If this is negative then the dehydration * strings themselves will be used as packet labels. * @param ignoreLines the number of lines at the beginning of the text * file that should be ignored completely. * @return a new container as described above, or 0 if an I/O error occurred * whilst reading the given file. */ REGINA_API NContainer* readDehydrationList(const char *filename, unsigned colDehydrations = 0, int colLabels = -1, unsigned long ignoreLines = 0); /*@}*/ } // namespace regina #endif regina-4.96/engine/foreign/isosig.cpp000644 000765 000024 00000011132 12377776611 017526 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include "foreign/isosig.h" #include "packet/ncontainer.h" #include "packet/ntext.h" #include "triangulation/ntriangulation.h" namespace regina { NContainer* readIsoSigList(const char *filename, unsigned dimension, unsigned colSigs, int colLabels, unsigned long ignoreLines) { // Open the file. std::ifstream in(filename); if (! in) return 0; // Ignore the specified number of lines. std::string line; unsigned long i; for (i = 0; i < ignoreLines; i++) { std::getline(in, line); if (in.eof()) return new NContainer(); } // Read in and process the remaining lines. NContainer* ans = new NContainer(); std::string errStrings; int col; std::string token; std::string isoSig; std::string label; NTriangulation* tri3; while(! in.eof()) { // Read in the next line. line.clear(); std::getline(in, line); if (line.empty()) continue; // Find the appropriate tokens. std::istringstream tokens(line); isoSig.clear(); label.clear(); for (col = 0; col <= static_cast(colSigs) || col <= colLabels; col++) { tokens >> token; if (token.empty()) break; if (col == static_cast(colSigs)) isoSig = token; if (col == colLabels) label = token; } if (! isoSig.empty()) { // Process this isomorphism signature. if (dimension == 3) { if ((tri3 = NTriangulation::fromIsoSig(isoSig))) { tri3->setPacketLabel(label.empty() ? isoSig : label); ans->insertChildLast(tri3); } else errStrings = errStrings + '\n' + isoSig; } else errStrings = errStrings + '\n' + isoSig; } } // Finish off. if (! errStrings.empty()) { std::ostringstream msg; msg << "The following isomorphism string(s) could not be interpreted " "as " << dimension << "-manifold triangulations:\n" << errStrings; NText* errPkt = new NText(msg.str()); errPkt->setPacketLabel("Errors"); ans->insertChildLast(errPkt); } return ans; } } // namespace regina regina-4.96/engine/foreign/isosig.h000644 000765 000024 00000011747 12377775201 017201 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file foreign/isosig.h * \brief Allows reading lists of isomorphism signatures. */ #ifndef __ISOSIG_H #ifndef __DOXYGEN #define __ISOSIG_H #endif #include "regina-core.h" namespace regina { class NContainer; /** * \weakgroup foreign * @{ */ /** * Reads a list of isomorphism signatures from the given text file. * The file should contain one isomorphism signature per line. * These isomorphism signatures will be converted into triangulations using * NTriangulation::fromIsoSig(). * * A newly allocated container will be returned; the imported * triangulations will be inserted as children of this container. * The container will not be assigned a label. The individual * triangulations will be assigned labels according to the parameter * \a colLabels. * * If any isomorphism signatures are invalid, these will be recorded in an * additional text packet that will be the last child of the returned * container. * * If an I/O error occurred while trying to read the given file, 0 will be * returned. * * In its simplest form, the text file can simply contain one * isomorphism signature per line and nothing else. However, more complex * formats are allowed. In particular, by passing appropriate values * for the arguments \a colSigs and \a colLabels, the isomorphism signatures * and triangulation packet labels can be taken from arbitrary * columns of the text file. Columns are considered to be separated by * whitespace and are numbered beginning at 0. * * \i18n This routine makes no assumptions about the * \ref i18n "character encoding" used in the given file \e name, and * simply passes it through unchanged to low-level C/C++ file I/O routines. * It assumes however that the \e contents of the file are in UTF-8. * * @param filename the name of the text file from which to read. * @param dimension must be set to 3, indicating that isomorphism * signatures should be expanded into 3-manifold triangulations. * This argument is a placeholder for future expansion, and currently no * value other than 3 is allowed. * @param colSigs the column of the text file containing the * isomorphism signatures. * @param colLabels the column of the text file containing the * triangulation packet labels. If this is negative then the * isomorphism signatures themselves will be used as packet labels. * @param ignoreLines the number of lines at the beginning of the text * file that should be ignored completely. * @return a new container as described above, or 0 if an I/O error occurred * whilst reading the given file. */ REGINA_API NContainer* readIsoSigList(const char *filename, unsigned dimension = 3, unsigned colSigs = 0, int colLabels = -1, unsigned long ignoreLines = 0); /*@}*/ } // namespace regina #endif regina-4.96/engine/foreign/orb.cpp000644 000765 000024 00000030477 12377776612 017031 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /** * Thanks to Ryan Budney and Damien Heard for providing the bulk of the * code in this file. * * Ryan Budney contributed the Orb / Casson import filters for Regina. * From his initial comments: * * This file contains the engine routines to read Casson/Orb format * triangulations and import them into Regina. The main routines are * adapted from Damian Heard's Orb. * -Ryan Budney (April 3rd, 2006) * * For information on which routines are adapted from Orb and how they * have been modified, see the comments above each routine. For information * on Orb itself, see http://www.ms.unimelb.edu.au/~snap/orb.html . */ #include #include #include #include #include #include #include #include "foreign/casson.h" #include "foreign/orb.h" #include "triangulation/ntriangulation.h" #include "utilities/stringutils.h" namespace regina { // Anonymous namespace for the private routines used only by this file. namespace { /** * Modified from Orb's cassonToTriangulation() routine. * * The routine was changed to be compatible with Regina's NTriangulation * data structure. */ NTriangulation *cassonToNTriangulation( CassonFormat *cf ) { int i; NTriangulation *triang = new NTriangulation(); // since CassonFormat does not allow naming of triangulations, // triang is given a name in the readOrb() function. // I try to mimic NTriangulation::readSnapPea and // Orb::cassonToTriangulation as much as possible. // If the triangulation is empty, leave now before we start allocating // empty arrays. if (cf->num_tet == 0) return triang; NTetrahedron **tet = new NTetrahedron*[cf->num_tet]; // tet corresponds to tet_array in Orb for (i=0; inum_tet; i++) tet[i]=triang->newTetrahedron(); // now tet is a pointer to an array of NTetrahedrons, // so for each tet[i] we need to run // for (j=0; j<4; j++) // tet[i]->joinTo(j,tet[g[j]],NPerm4(p[j][0],p[j][1],p[j][2],p[j][3],p[j][4])) // where g[j] is the tetrahedron adjacent to face j of tet[i] // p[j][k] is the permutation specifying how the faces are glued together. EdgeInfo *ei; TetEdgeInfo *tei1, *tei2; int t1, t2, a1, a2, a3, a4, b1, b2, b3, b4; ei = cf->head; // this routine goes through the edges of cf, picking off the adjacent // tetrahedra and assembled the information into tet. this code is // adapted from Orb::cassonToTriangulation in Orb's organizer.cpp while (ei!=NULL) // if we have a non-trivial edge, proceed { tei1 = ei->head; while (tei1!=NULL) // now we spin about the tetrahedra adj to ei. { if (tei1->next==NULL) tei2 = ei->head; else tei2 = tei1->next; t1 = tei1->tet_index; a1 = tei1->f1; a2 = tei1->f2; a3 = vertex_at_faces[a1][a2]; a4 = vertex_at_faces[a2][a1]; t2 = tei2->tet_index; b1 = tei2->f1; b2 = tei2->f2; b3 = vertex_at_faces[b1][b2]; b4 = vertex_at_faces[b2][b1]; tet[t1]->joinTo( tei1->f1 , tet[t2], // 1st entry is the face of tet[t1] NPerm4(a1,b2,a2,b1,a3,b3,a4,b4) ); // being attached to tet[t2] tet[t2]->joinTo( tei2->f2 , tet[t1], NPerm4(b1,a2,b2,a1,b3,a3,b4,a4) ); tei1 = tei1->next; } ei = ei->next; } delete[] tet; return triang; } /** * Modified from Orb's readCassonFormat() routine. * * This routine was modified to remove the dependence on Qt strings and * I/O streams, and work only with standard C++ strings and I/O streams * instead. * * On entering this routine we assume the lines containing "% orb" and * the manifold name have already been read. */ CassonFormat *readCassonFormat( std::istream &ts ) { CassonFormat *cf; std::string line, section; EdgeInfo *nei, *ei; TetEdgeInfo *ntei, *tei; bool vertices_known = false; cf = new CassonFormat; cf->head = NULL; cf->num_tet = 0; // Skip any initial non-empty lines (looking whether there is // "vertices_known") and then some empty lines. // After that there should be the real information. // The code from Orb used QString::skipWhiteSpace(); we do it // manually. do { getline(ts, line); stripWhitespace(line); if (line == "vertices_known") vertices_known=true; } while ((!ts.eof()) && (!line.empty())); do { getline(ts,line); stripWhitespace(line); } while ((! ts.eof()) && line.empty()); // Process lines one at a time until we hit an empty line or EOF. while ((! ts.eof()) && (! line.empty()) && (line != "% diagram")) { // The code from Orb used QString's record separation // routines. We don't have that in std::string, so // we'll do it all with istringstreams instead. std::istringstream tokens(line); nei = new EdgeInfo; if (cf->head==NULL) cf->head = nei; else ei->next = nei; nei->next = NULL; nei->head = NULL; ei = nei; tokens >> ei->index; ei->index--; // We never use these two values; just suck them in and // forget them. tokens >> ei->singular_index >> ei->singular_order; // if vertices are listed, discard if (vertices_known) { tokens >> section; tokens>>section; } tokens >> section; while (!section.empty()) { ntei = new TetEdgeInfo; if (ei->head==NULL) ei->head = ntei; else tei->next = ntei; ntei->next = NULL; tei = ntei; tei->f1 = LN(section[section.length()-2]); tei->f2 = LN(section[section.length()-1]); section.resize(section.length()-2); tei->tet_index = atoi(section.c_str()) - 1; if (tei->tet_index + 1 > cf->num_tet) cf->num_tet = tei->tet_index + 1; section.clear(); tokens >> section; } getline(ts, line); } return cf; } /** * A direct copy of Orb's verifyCassonFormat() routine. */ bool verifyCassonFormat( CassonFormat *cf ) { int i,j,k; bool check[4][4]; EdgeInfo *ei; TetEdgeInfo *tei; for(i=0;inum_tet;i++) { for(j=0;j<4;j++) for(k=0;k<4;k++) if (j==k) check[j][k] = true; else check[j][k] = false; ei = cf->head; if (ei == NULL) return false; while(ei!=NULL) { tei = ei->head; if (tei == NULL) return false; while(tei!=NULL) { if (tei->tet_index == i ) { if (check[tei->f1][tei->f2]) return true; check[tei->f1][tei->f2] = true; check[tei->f2][tei->f1] = true; } tei = tei->next; } ei = ei->next; } for(j=0;j<4;j++) for(k=0;k<4;k++) if (check[j][k]==false) return false; } return true; } /** * A direct copy of Orb's freeCassonFormat() routine. */ void freeCassonFormat( CassonFormat *cf ) { EdgeInfo *e1, *e2; TetEdgeInfo *t1, *t2; e1 = cf->head; while (e1!=NULL) { e2 = e1->next; t1 = e1->head; while (t1!=NULL) { t2 = t1->next; delete t1; t1 = t2; } delete e1; e1 = e2; } delete cf; } /** * Modified from Orb's readTriangulation() routine. * * The routine was changed to be compatible with Regina's NTriangulation * data structure, and to use standard C++ string and I/O streams * instead of Qt strings and I/O streams. */ NTriangulation *readTriangulation( std::istream &ts) { std::string line, file_id; getline(ts, line); if (line != "% orb") { std::cerr << "Orb / Casson file is not in the correct format." << std::endl; return 0; } getline(ts, file_id); CassonFormat* cf = readCassonFormat( ts ); if (! verifyCassonFormat( cf )) { std::cerr << "Error verifying Orb / Casson file." << std::endl; freeCassonFormat( cf ); return 0; } NTriangulation* manifold = cassonToNTriangulation( cf ); freeCassonFormat( cf ); manifold->setPacketLabel(file_id); return manifold; } } // End anonymous namespace NTriangulation *readOrb(const char *filename) { std::ifstream file(filename); if (! file) { std::cerr << "Error opening Orb / Casson file." << std::endl; return 0; } return readTriangulation(file); } } // namespace regina regina-4.96/engine/foreign/orb.h000644 000765 000024 00000007153 12377775204 016465 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file foreign/orb.h * \brief Allows reading Orb / Casson triangulation files. */ #ifndef __ORB_H #ifndef __DOXYGEN #define __ORB_H #endif #include #include "regina-core.h" namespace regina { class NTriangulation; /** * \weakgroup foreign * @{ */ /** * Reads a triangulation from the given Orb / Casson file. A newly * allocated triangulation will be returned; it is the user's * responsibility to deallocate this when it is finished with. * * The packet label of the new triangulation will be the manifold name * read from the second line of the Orb / Casson file. The first line * of the Orb / Casson file must simply be ``% orb''. * * If the file could not be read or if the data was not in the correct * format, 0 will be returned. * * \i18n This routine makes no assumptions about the * \ref i18n "character encoding" used in the given file \e name, and * simply passes it through unchanged to low-level C/C++ file I/O routines. * It assumes however that the \e contents of the file are in UTF-8. * * @param filename the name of the Orb / Casson file from which to read. * @return a new triangulation containing the data read from the Orb / Casson * file, or 0 on error. * * @author Ryan Budney, also with code from Damien Heard */ REGINA_API NTriangulation* readOrb(const char *filename); /*@}*/ } // namespace regina #endif regina-4.96/engine/foreign/pdf.cpp000644 000765 000024 00000005572 12377776612 017016 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "foreign/pdf.h" #include "packet/npdf.h" #include namespace regina { NPDF* readPDF(const char* filename) { NPDF* ans = new NPDF(filename); if (ans->isNull()) { delete ans; return 0; } else return ans; } bool writePDF(const char* filename, const NPDF& pdf) { if (pdf.isNull()) { // Preserve old behaviour for backward compatibility: create an // empty file. FILE* out = fopen(filename, "wb"); if (! out) return false; fclose(out); return true; } else return pdf.savePDF(filename); } } // namespace regina regina-4.96/engine/foreign/pdf.h000644 000765 000024 00000007566 12377775206 016466 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file foreign/pdf.h * \brief Allows reading and writing PDF documents. * * \deprecated All global functions that were once declared in this file have * now been renamed to member functions of NPDF. */ #ifndef __PDF_H #ifndef __DOXYGEN #define __PDF_H #endif #include "regina-core.h" namespace regina { class NPDF; /** * \weakgroup foreign * @{ */ /** * Deprecated function that reads a PDF document from the given file. * * If the file could not be read, or if the file is empty, then 0 will be * returned. Otherwise a newly allocated PDF packet will be returned, and it * is the user's responsibility to deallocate this when it is finished with. * * \deprecated You should use the NPDF constructor NPDF::NPDF(const char*), * and you should pass the filename as the single string argument. * In situations where this routine would have returned a null pointer, the * NPDF constructor will instead create a null document (i.e., one for which * NPDF::isNull() returns \c true). See the NPDF constructor for further * details. */ REGINA_API NPDF* readPDF(const char *filename); /** * Deprecated function that writes the given PDF document to the given file. * * \deprecated This routine has been renamed as NPDF::savePDF(). This old * routine behaves exactly as in the past, but the new NPDF::savePDF() has * a slight change in behaviour: if the PDF packet contains no data then * it no longer creates an empty file, but instead does nothing and returns * \c false. See NPDF::savePDF() for further details. */ REGINA_API bool writePDF(const char* filename, const NPDF& pdf); /*@}*/ } // namespace regina #endif regina-4.96/engine/foreign/recogniser.h000644 000765 000024 00000010630 12377775207 020040 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file foreign/recogniser.h * \brief Allows exports to Matveev's 3-manifold recogniser. * * \deprecated All global functions that were once declared in this file have * now been renamed to member functions of NTriangulation. */ #ifndef __RECOGNISER_H #ifndef __DOXYGEN #define __RECOGNISER_H #endif #include #include "regina-core.h" #include "triangulation/ntriangulation.h" namespace regina { class NTriangulation; /** * \weakgroup foreign * @{ */ /** * Deprecated function that writes the given triangulation to the given file * in Matveev's 3-manifold recogniser format. * * \deprecated This routine has been renamed as * NTriangulation::saveRecogniser(). This old routine behaves exactly as in * the past, but the new NTriangulation::saveRecogniser() has a slight change * of behaviour: unlike the old routine, it now requires a non-empty filename. * To send data to standard output (as in the old routine), you may call * NTriangulation::recogniser() and simply print the resulting string. * See the NTriangulation::saveRecogniser() documentation for further details. */ REGINA_API bool writeRecogniser(const char* filename, NTriangulation& tri); /** * Deprecated function that writes the given triangulation to the given file * in Matveev's 3-manifold recogniser format. * * \deprecated This routine has been renamed as * NTriangulation::saveRecogniser(). This old routine behaves exactly as in * the past, but the new NTriangulation::saveRecogniser() has a slight change * of behaviour: unlike the old routine, it now requires a non-empty filename. * To send data to standard output (as in the old routine), you may call * NTriangulation::recogniser() and simply print the resulting string. * See the NTriangulation::saveRecogniser() documentation for further details. */ REGINA_API bool writeRecognizer(const char* filename, NTriangulation& tri); /*@}*/ // Inline functions: inline bool writeRecogniser(const char* filename, NTriangulation& tri) { return tri.saveRecogniser(filename); } inline bool writeRecognizer(const char* filename, NTriangulation& tri) { return tri.saveRecogniser(filename); } } // namespace regina #endif regina-4.96/engine/foreign/snappea.cpp000644 000765 000024 00000013067 12377776613 017673 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include #include #include "foreign/snappea.h" #include "triangulation/ntriangulation.h" #include "utilities/stringutils.h" namespace regina { NTriangulation* readSnapPea(const char* filename) { std::ifstream in(filename); if (!in) return 0; else return readSnapPea(in); } NTriangulation* readSnapPea(std::istream& in) { // Check that this is a SnapPea triangulation. char name[1001]; unsigned len; in.getline(name, 1000); if (in.fail() || in.eof()) return 0; // Allow junk on the same line following the triangulation marker. if (strncmp(name, "% Triangulation", 15) && strncmp(name, "% triangulation", 15)) return 0; // Read in the manifold name. in.getline(name, 1000); if (in.fail() || in.eof()) return 0; if ((len = strlen(name)) > 0 && name[len - 1] == '\r') name[len - 1] = 0; // Read in junk. std::string tempStr; double tempDbl; in >> tempStr; // Solution type in >> tempDbl; // Volume in >> tempStr; // Orientability in >> tempStr; // Chern-Simmon if (tempStr[3] == 'k') in >> tempDbl; // Chern-Simmon is known unsigned i,j,k; // Read in cusp details and ignore them. unsigned numOrientCusps, numNonOrientCusps; in >> numOrientCusps >> numNonOrientCusps; for (i=0; i> tempStr; // Cusp type in >> tempDbl >> tempDbl; // Filling information } // Create the new tetrahedra. NTriangulation* triang = new NTriangulation(); triang->setPacketLabel(name); unsigned numTet; in >> numTet; NTetrahedron **tet = new NTetrahedron*[numTet]; for (i=0; inewTetrahedron(); int g[4]; int p[4][4]; for (i=0; i> g[j]; // Read in gluing permutations. for (j=0; j<4; j++) { in >> tempStr; for (k=0; k<4; k++) switch( tempStr[k] ) { case '0': p[j][k] = 0; break; case '1': p[j][k] = 1; break; case '2': p[j][k] = 2; break; case '3': p[j][k] = 3; break; default: delete triang; delete[] tet; return 0; } } // Perform the gluings. for (j=0; j<4; j++) tet[i]->joinTo(j, tet[g[j]], NPerm4(p[j][0], p[j][1], p[j][2], p[j][3])); // Read in junk. for (j=0; j<4; j++) in >> tempStr; for (j=0; j<64; j++) in >> tempStr; for (j=0; j<2; j++) in >> tempStr; } // All done! delete[] tet; return triang; } bool writeSnapPea(const char* filename, const NTriangulation& tri) { return tri.saveSnapPea(filename); } void writeSnapPea(std::ostream& out, const NTriangulation& tri) { tri.snapPea(out); } } // namespace regina regina-4.96/engine/foreign/snappea.h000644 000765 000024 00000014431 12377775211 017325 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file foreign/snappea.h * \brief Allows reading and writing SnapPea files. * * \deprecated All global functions that were once declared in this * file have now been renamed to member functions of NSnapPeaTriangulation. */ #ifndef __SNAPPEA_H #ifndef __DOXYGEN #define __SNAPPEA_H #endif #include #include "regina-core.h" namespace regina { class NTriangulation; /** * \addtogroup foreign Foreign File Formats * Reading and writing foreign file formats. * @{ */ /** * Deprecated function that reads the given SnapPea data file and converts * the result to Regina's NTriangulation class (thereby losing some * SnapPea-specific information in the process). * * If the file could not be read or if the data was not in the correct * format, 0 will be returned. Otherwise a newly allocated triangulation * will be returned, and it is the user's responsibility to deallocate this * when it is finished with. * * \deprecated You should use the NSnapPeaTriangulation constructor * NSnapPeaTriangulation::NSnapPeaTriangulation(const std::string&) * instead. In situations where this routine would have returned a * null pointer, the NSnapPeaTriangulation constructor will instead * create a null triangulation (i.e., one for which isNull() returns \c true). * See the NSnapPeaTriangulation constructor for further details. * * \warning Since this routine returns an NTriangulation (Regina's native data * type), it will lose any SnapPea-specific information (such as peripheral * curves). It is strongly recommended that you use the NSnapPeaTriangulation * constructor instead (as described above), since this will return an * NSnapPeaTriangulation object that preserves SnapPea's additional data. */ REGINA_API NTriangulation* readSnapPea(const char *filename); /** * Deprecated function that reads the contents of a SnapPea data file from * the given input stream, and converts the result to Regina's NTriangulation * class (thereby losing some SnapPea-specific information in the process). * * If the input stream could not be read or if the data was not in the correct * format, 0 will be returned. Otherwise a newly allocated triangulation will * be returned, and it is the user's responsibility to deallocate this when * it is finished with. * * \deprecated You should use the NSnapPeaTriangulation constructor * NSnapPeaTriangulation::NSnapPeaTriangulation(const std::string&) * instead (you will need to pass the contents of the input stream, not * the input stream itself). In situations where this routine would have * returned a null pointer, the NSnapPeaTriangulation constructor will instead * create a null triangulation (i.e., one for which isNull() returns \c true). * See the NSnapPeaTriangulation constructor for further details. * * \warning Since this routine returns an NTriangulation (Regina's native data * type), it will lose any SnapPea-specific information (such as peripheral * curves). It is strongly recommended that you use the NSnapPeaTriangulation * constructor instead (as described above), since this will return an * NSnapPeaTriangulation object that preserves SnapPea's additional data. * * \ifacespython Not present. */ REGINA_API NTriangulation* readSnapPea(std::istream& in); /** * Deprecated function that writes the given triangulation to the given file * using SnapPea's native file format. * * \deprecated This routine has been renamed as NTriangulation::saveSnapPea(). * See the documentation of NTriangulation::saveSnapPea() for further details. */ REGINA_API bool writeSnapPea(const char* filename, const NTriangulation& tri); /** * Deprecated function that writes the given triangulation to the * given output stream using SnapPea's native file format. * * \deprecated This routine has been renamed as * NTriangulation::snapPea(std::ostream&). See the documentation for * NTriangulation::snapPea(std::ostream&) for further information. * * \ifacespython Not present. */ REGINA_API void writeSnapPea(std::ostream& out, const NTriangulation& tri); /*@}*/ } // namespace regina #endif regina-4.96/engine/generic/canonical-impl.h000644 000765 000024 00000023500 12377775212 020545 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "generic/ngenerictriangulation.h" namespace regina { namespace { /** * For internal use by makeCanonical(). This routines assumes that * the preimage of simplex 0 has been fixed (along with the * corresponding vertex permutation), and tries to extend * this to a "possibly canonical" isomorphism. * * If it becomes clear that the isomorphism cannot be made canonical * and/or cannot be made better (i.e., lexicographically smaller) than * the best isomorphism found so far, this routine returns \c false * (possibly before the full isomorphism has been constructed). * Otherwise it returns \c true (and it is guaranteed that the * isomorphism is both fully constructed and moreover a strict * improvement upon the best found so far). * * This routine currently only works for connected triangulations. */ template bool extendIsomorphism( const typename DimTraits::Triangulation* tri, typename DimTraits::Isomorphism& current, typename DimTraits::Isomorphism& currentInv, const typename DimTraits::Isomorphism& best, const typename DimTraits::Isomorphism& bestInv) { bool better = false; unsigned nSimp = tri->getNumberOfSimplices(); unsigned simplex; for (simplex = 0; simplex < nSimp; ++simplex) if (simplex != currentInv.simpImage(0)) current.simpImage(simplex) = -1; int facet; unsigned origTri, origTriBest; int origFacet, origFacetBest; typename DimTraits::Simplex *adjTri, *adjTriBest; unsigned adjTriIndex, adjTriIndexBest; unsigned finalImage, finalImageBest; typename DimTraits::Perm gluingPerm, gluingPermBest; typename DimTraits::Perm finalGluing, finalGluingBest; int comp; bool justAssigned; unsigned lastAssigned = 0; for (simplex = 0; simplex < nSimp; ++simplex) { // INV: We have already selected the preimage of simplex and // the corresponding facet permutation by the time we reach // this point. origTri = currentInv.simpImage(simplex); origTriBest = bestInv.simpImage(simplex); for (facet = 0; facet <= dim; ++facet) { origFacet = current.facetPerm(origTri).preImageOf(facet); origFacetBest = best.facetPerm(origTriBest).preImageOf(facet); // Check out the adjacency along simplex/facet. adjTri = tri->getSimplex(origTri)->adjacentSimplex(origFacet); adjTriIndex = (adjTri ? tri->simplexIndex(adjTri) : nSimp); adjTriBest = tri->getSimplex(origTriBest)-> adjacentSimplex(origFacetBest); adjTriIndexBest = (adjTriBest ? tri->simplexIndex(adjTriBest) : nSimp); justAssigned = false; if (adjTri && current.simpImage(adjTriIndex) < 0) { // We have a new simplex that needs assignment. ++lastAssigned; current.simpImage(adjTriIndex) = lastAssigned; currentInv.simpImage(lastAssigned) = adjTriIndex; justAssigned = true; } finalImage = (adjTri ? current.simpImage(adjTriIndex) : nSimp); finalImageBest = (adjTriBest ? best.simpImage(adjTriIndexBest) : nSimp); // We now have a gluing (but possibly not a gluing // permutation). Compare adjacent simplex indices. if ((! better) && finalImage > finalImageBest) return false; // Worse than best-so-far. if (finalImage < finalImageBest) better = true; // Time now to look at the gluing permutation. if (! adjTri) continue; gluingPerm = tri->getSimplex(origTri)->adjacentGluing( origFacet); gluingPermBest = tri->getSimplex(origTriBest)-> adjacentGluing(origFacetBest); if (justAssigned) { // We can choose the permutation ourselves. // Make it so that the final gluing (computed later // below) becomes the identity. current.facetPerm(adjTriIndex) = current.facetPerm(origTri) * gluingPerm.inverse(); currentInv.facetPerm(lastAssigned) = current.facetPerm(adjTriIndex).inverse(); } // Although adjTri is guaranteed to exist, adjTriBest is // not. However, if adjTriBest does not exist then our // isomorphism-under-construction must already be an // improvement over best. if (better) continue; // Now we are guaranteed that adjTriBest exists. finalGluing = current.facetPerm(adjTriIndex) * gluingPerm * current.facetPerm(origTri).inverse(); finalGluingBest = best.facetPerm(adjTriIndexBest) * gluingPermBest * best.facetPerm(origTriBest).inverse(); comp = finalGluing.compareWith(finalGluingBest); if ((! better) && comp > 0) return false; // Worse than best-so-far. if (comp < 0) better = true; } } return better; } } template bool NGenericTriangulation::makeCanonical() { typename DimTraits::Triangulation* me = static_cast::Triangulation*>(this); typedef typename DimTraits::Perm Perm; unsigned nSimp = me->getNumberOfSimplices(); // Get the empty triangulation out of the way. if (nSimp == 0) return false; // Prepare to search for isomorphisms. typename DimTraits::Isomorphism current(nSimp), currentInv(nSimp); typename DimTraits::Isomorphism best(nSimp), bestInv(nSimp); // The thing to best is the identity isomorphism. unsigned simp, inner; for (simp = 0; simp < nSimp; ++simp) { best.simpImage(simp) = bestInv.simpImage(simp) = simp; best.facetPerm(simp) = bestInv.facetPerm(simp) = Perm(); } // Run through potential preimages of simplex 0. int perm; for (simp = 0; simp < nSimp; ++simp) { for (perm = 0; perm < Perm::nPerms; ++perm) { // Build a "perhaps canonical" isomorphism based on this // preimage of simplex 0. current.simpImage(simp) = 0; currentInv.simpImage(0) = simp; current.facetPerm(simp) = Perm::Sn[Perm::invSn[perm]]; currentInv.facetPerm(0) = Perm::Sn[perm]; if (extendIsomorphism(me, current, currentInv, best, bestInv)) { // This is better than anything we've seen before. for (inner = 0; inner < nSimp; ++inner) { best.simpImage(inner) = current.simpImage(inner); best.facetPerm(inner) = current.facetPerm(inner); bestInv.simpImage(inner) = currentInv.simpImage(inner); bestInv.facetPerm(inner) = currentInv.facetPerm(inner); } } } } // Is there anything to do? if (best.isIdentity()) return false; // Do it. best.applyInPlace(me); return true; } } // namespace regina regina-4.96/engine/generic/CMakeLists.txt000644 000765 000024 00000001127 12377774107 020251 0ustar00babstaff000000 000000 # generic # Files to compile SET ( FILES ngenerictriangulation ) # Prepend folder name FOREACH ( SOURCE_FILE ${FILES} ) SET ( SOURCES ${SOURCES} generic/${SOURCE_FILE}) ENDFOREACH(SOURCE_FILE) # Set the variable in the parent directory SET( SOURCES ${SOURCES} PARENT_SCOPE) if (${REGINA_INSTALL_DEV}) INSTALL(FILES canonical-impl.h dimtraits.h isomorphism-impl.h isosig-impl.h nfacetspec.h ngenericisomorphism-impl.h ngenericisomorphism.h ngenerictriangulation.h DESTINATION ${INCLUDEDIR}/generic COMPONENT Development) endif (${REGINA_INSTALL_DEV}) regina-4.96/engine/generic/dimtraits.h000644 000765 000024 00000010430 12377775214 017657 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file generic/dimtraits.h * \brief A template class that provides information on working in * different dimensions. */ #ifndef __DIMTRAITS_H #ifndef __DOXYGEN #define __DIMTRAITS_H #endif #include "regina-core.h" namespace regina { /** * \addtogroup generic Generic code * Template code to work with triangulations of arbitrary dimension. * @{ */ /** * A template class that provides typedefs and other information about * working in each of the supported dimensions. * * Note that this file does not bring in all of the headers for the * individual types. * * \ifacespython Not present. */ template struct DimTraits { typedef void Triangulation; /**< The main data type for a \a dim-manifold triangulation. */ typedef void Simplex; /**< The data type for a top-dimensional simplex in a \a dim-manifold triangulation. */ typedef void Isomorphism; /**< The data type for an isomorphism between two \a dim-manifold triangulations. */ typedef void FacetPairing; /**< The data type that represents a pairing of facets of top-dimensional simplices in a \a dim-manifold triangulation. */ typedef void Perm; /**< The permutation type used to describe gluings between top-dimensional simplices in a \a dim-manifold triangulation. */ }; #ifndef __DOXYGEN class Dim2Triangulation; class Dim2Triangle; class Dim2Isomorphism; class Dim2EdgePairing; class NPerm3; template <> struct DimTraits<2> { typedef Dim2Triangulation Triangulation; typedef Dim2Triangle Simplex; typedef Dim2Isomorphism Isomorphism; typedef Dim2EdgePairing FacetPairing; typedef NPerm3 Perm; }; class NTriangulation; class NTetrahedron; class NIsomorphism; class NFacePairing; class NPerm4; template <> struct DimTraits<3> { typedef NTriangulation Triangulation; typedef NTetrahedron Simplex; typedef NIsomorphism Isomorphism; typedef NFacePairing FacetPairing; typedef NPerm4 Perm; }; #endif } // namespace regina #endif regina-4.96/engine/generic/isomorphism-impl.h000644 000765 000024 00000012433 12377775215 021175 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "generic/ngenerictriangulation.h" namespace regina { template bool NGenericTriangulation::isIdenticalTo( const typename DimTraits::Triangulation& other) const { const typename DimTraits::Triangulation& me( static_cast::Triangulation&>(*this)); if (me.getNumberOfSimplices() != other.getNumberOfSimplices()) return false; unsigned long i; unsigned j; for (i = 0; i < me.getNumberOfSimplices(); ++i) for (j = 0; j <= dim; ++j) { if (me.getSimplex(i)->adjacentSimplex(j)) { if (! other.getSimplex(i)->adjacentSimplex(j)) return false; if (me.getSimplex(i)->adjacentSimplex(j)->markedIndex() != other.getSimplex(i)->adjacentSimplex(j)->markedIndex()) return false; if (me.getSimplex(i)->adjacentGluing(j) != other.getSimplex(i)->adjacentGluing(j)) return false; } else { if (other.getSimplex(i)->adjacentSimplex(j)) return false; } } return true; } template inline std::auto_ptr::Isomorphism> NGenericTriangulation::isIsomorphicTo( const typename DimTraits::Triangulation& other) const { std::list::Isomorphism*> results; if (static_cast::Triangulation&>(*this). findIsomorphisms(other, results, true, true)) return std::auto_ptr::Isomorphism>( results.front()); else return std::auto_ptr::Isomorphism>(0); } template inline std::auto_ptr::Isomorphism> NGenericTriangulation::isContainedIn( const typename DimTraits::Triangulation& other) const { std::list::Isomorphism*> results; if (static_cast::Triangulation&>(*this). findIsomorphisms(other, results, false, true)) return std::auto_ptr::Isomorphism>( results.front()); else return std::auto_ptr::Isomorphism>(0); } template inline unsigned long NGenericTriangulation::findAllIsomorphisms( const typename DimTraits::Triangulation& other, std::list::Isomorphism*>& results) const { return static_cast::Triangulation&>(*this). findIsomorphisms(other, results, true, false); } template inline unsigned long NGenericTriangulation::findAllSubcomplexesIn( const typename DimTraits::Triangulation& other, std::list::Isomorphism*>& results) const { return static_cast::Triangulation&>(*this). findIsomorphisms(other, results, false, false); } } // namespace regina regina-4.96/engine/generic/isosig-impl.h000644 000765 000024 00000050441 12377775217 020124 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include "generic/ngenerictriangulation.h" #include "packet/npacket.h" /** * The numbers of base64 characters required to store an index into * DimTraits::Perm::Sn. * * This is 1 if dim <= 3 (since 4! <= 64), and 2 if dim = 4 (since 5! > 64). */ #define CHARS_PER_PERM(dim) ((dim) <= 3 ? 1 : 2) namespace regina { namespace { /** * Determine the integer value represented by the given character in * a signature string. */ inline unsigned SVAL(char c) { if (c >= 'a' && c <= 'z') return (c - 'a'); if (c >= 'A' && c <= 'Z') return (c - 'A' + 26); if (c >= '0' && c <= '9') return (c - '0' + 52); if (c == '+') return 62; return 63; } /** * Determine the character that represents the given integer value * in a signature string. */ inline char SCHAR(unsigned c) { if (c < 26) return (char(c) + 'a'); if (c < 52) return (char(c - 26) + 'A'); if (c < 62) return (char(c - 52) + '0'); if (c == 62) return '+'; return '-'; } /** * Is the given character a valid character in a signature string? */ inline bool SVALID(char c) { return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '+' || c == '-'); } /** * Does the given string contain at least nChars characters? */ inline bool SHASCHARS(const char* s, unsigned nChars) { for ( ; nChars > 0; --nChars) if (! *s) return false; return true; } /** * Append an encoding of the given integer to the given string. * The integer is broken into nChars distinct 6-bit blocks, and the * lowest-significance blocks are written first. */ void SAPPEND(std::string& s, unsigned val, unsigned nChars) { for ( ; nChars > 0; --nChars) { s += SCHAR(val & 0x3F); val >>= 6; } } /** * Read the integer at the beginning of the given string. * Assumes the string has length >= nChars. */ unsigned SREAD(const char* s, unsigned nChars) { unsigned ans = 0; for (unsigned i = 0; i < nChars; ++i) ans += (SVAL(s[i]) << (6 * i)); return ans; } /** * Append up to three trits (0, 1 or 2) to the given string. * These are packed into a single character, with the first trit * representing the lowest-significance bits and so on. */ void SAPPENDTRITS(std::string& s, const char* trits, unsigned nTrits) { char ans = 0; if (nTrits >= 1) ans |= trits[0]; if (nTrits >= 2) ans |= (trits[1] << 2); if (nTrits >= 3) ans |= (trits[2] << 4); s += SCHAR(ans); } /** * Reads three trits (0, 1 or 2) from the given character. */ void SREADTRITS(char c, char* result) { unsigned val = SVAL(c); result[0] = val & 3; result[1] = (val >> 2) & 3; result[2] = (val >> 4) & 3; } } template std::string NGenericTriangulation::isoSigFrom( const typename DimTraits::Triangulation& tri, unsigned simp, const typename DimTraits::Perm& vertices, typename DimTraits::Isomorphism* relabelling) { // These typedefs are already present in the class declaration, // but gcc 4.4 seems to break unless we include them here also. typedef typename DimTraits::Perm Perm; typedef typename DimTraits::Simplex Simplex; // Only process the component that simp belongs to. // --------------------------------------------------------------------- // Data for reconstructing a triangulation from an isomorphism signature // --------------------------------------------------------------------- // The number of simplices. unsigned nSimp = tri.getNumberOfSimplices(); // What happens to each new facet that we encounter? // Options are: // 0 -> boundary // 1 -> joined to a simplex not yet seen [gluing perm = identity] // 2 -> joined to a simplex already seen // These actions are stored in lexicographical order by (simplex, facet), // but only once for each facet (so we "skip" gluings that we've // already seen from the other direction). char* facetAction = new char[tri.template getNumberOfFaces()]; // What are the destination simplices and gluing permutations for // each facet under case #2 above? // For gluing permutations, we store the index of the permutation in // Perm::orderedSn. unsigned* joinDest = new unsigned[tri.template getNumberOfFaces()]; unsigned* joinGluing = new unsigned[tri.template getNumberOfFaces()]; // --------------------------------------------------------------------- // Data for finding the unique canonical isomorphism from this // connected component that maps (simplex, vertices) -> (0, 0..dim) // --------------------------------------------------------------------- // The image for each simplex and its vertices: int* image = new int[nSimp]; Perm* vertexMap = new Perm[nSimp]; // The preimage for each simplex: int* preImage = new int[nSimp]; // --------------------------------------------------------------------- // Looping variables // --------------------------------------------------------------------- unsigned facetPos, joinPos, nextUnusedSimp; unsigned simpImg, facetImg; unsigned simpSrc, facetSrc, dest; const Simplex* s; // --------------------------------------------------------------------- // The code! // --------------------------------------------------------------------- std::fill(image, image + nSimp, -1); std::fill(preImage, preImage + nSimp, -1); image[simp] = 0; vertexMap[simp] = vertices.inverse(); preImage[0] = simp; facetPos = 0; joinPos = 0; nextUnusedSimp = 1; // To obtain a canonical isomorphism, we must run through the simplices // and their facets in image order, not preimage order. // // This main loop is guaranteed to exit when (and only when) we have // exhausted a single connected component of the triangulation. for (simpImg = 0; simpImg < nSimp && preImage[simpImg] >= 0; ++simpImg) { simpSrc = preImage[simpImg]; s = tri.getSimplex(simpSrc); for (facetImg = 0; facetImg <= dim; ++facetImg) { facetSrc = vertexMap[simpSrc].preImageOf(facetImg); // INVARIANTS (held while we stay within a single component): // - nextUnusedSimp > simpImg // - image[simpSrc], preImage[image[simpSrc]] and vertexMap[simpSrc] // are already filled in. // Work out what happens to our source facet. if (! s->adjacentSimplex(facetSrc)) { // A boundary facet. facetAction[facetPos++] = 0; continue; } // We have a real gluing. Is it a gluing we've already seen // from the other side? dest = tri.simplexIndex(s->adjacentSimplex(facetSrc)); if (image[dest] >= 0) if (image[dest] < image[simpSrc] || (dest == simpSrc && vertexMap[simpSrc][s->adjacentFacet(facetSrc)] < vertexMap[simpSrc][facetSrc])) { // Yes. Just skip this gluing entirely. continue; } // Is it a completely new simplex? if (image[dest] < 0) { // Yes. The new simplex takes the next available // index, and the canonical gluing becomes the identity. image[dest] = nextUnusedSimp++; preImage[image[dest]] = dest; vertexMap[dest] = vertexMap[simpSrc] * s->adjacentGluing(facetSrc).inverse(); facetAction[facetPos++] = 1; continue; } // It's a simplex we've seen before. Record the gluing. joinDest[joinPos] = image[dest]; joinGluing[joinPos] = (vertexMap[dest] * s->adjacentGluing(facetSrc) * vertexMap[simpSrc].inverse()). orderedSnIndex(); ++joinPos; facetAction[facetPos++] = 2; } } // We have all we need. Pack it all together into a string. // We need to encode: // - the number of simplices in this component; // - facetAction[i], 0 <= i < facetPos; // - joinDest[i], 0 <= i < joinPos; // - joinGluing[i], 0 <= i < joinPos. std::string ans; // Keep it simple for small triangulations (1 character per integer). // For large triangulations, start with a special marker followed by // the number of chars per integer. unsigned nCompSimp = simpImg; unsigned nChars; if (nCompSimp < 63) nChars = 1; else { nChars = 0; unsigned tmp = nCompSimp; while (tmp > 0) { tmp >>= 6; ++nChars; } ans = SCHAR(63); ans += SCHAR(nChars); } // Off we go. unsigned i; SAPPEND(ans, nCompSimp, nChars); for (i = 0; i < facetPos; i += 3) SAPPENDTRITS(ans, facetAction + i, (facetPos >= i + 3 ? 3 : facetPos - i)); for (i = 0; i < joinPos; ++i) SAPPEND(ans, joinDest[i], nChars); for (i = 0; i < joinPos; ++i) SAPPEND(ans, joinGluing[i], CHARS_PER_PERM(dim)); // Record the canonical isomorphism if required. if (relabelling) for (i = 0; i < nCompSimp; ++i) { relabelling->simpImage(i) = image[i]; relabelling->facetPerm(i) = vertexMap[i]; } // Done! delete[] image; delete[] vertexMap; delete[] preImage; delete[] facetAction; delete[] joinDest; delete[] joinGluing; return ans; } template std::string NGenericTriangulation::isoSig( typename DimTraits::Isomorphism** relabelling) const { // These typedefs are already present in the class declaration, // but gcc 4.7.3 seems to break unless we include them here also. typedef typename DimTraits::Perm Perm; typedef typename DimTraits::Triangulation Triangulation; typedef typename DimTraits::Isomorphism Isomorphism; const Triangulation& tri(static_cast(*this)); // Make sure the user is not trying to do something illegal. if (relabelling && tri.getNumberOfComponents() != 1) { *relabelling = 0; // Return 0 to the user... relabelling = 0; // ... and forget they ever asked for an isomorphism. } Isomorphism* currRelabelling = 0; if (relabelling) { *relabelling = new Isomorphism(tri.getNumberOfSimplices()); currRelabelling = new Isomorphism(tri.getNumberOfSimplices()); } if (tri.getSimplices().empty()) { char c[2]; c[0] = SCHAR(0); c[1] = 0; return c; } // The triangulation is non-empty. Get a signature string for each // connected component. unsigned i; typename Triangulation::ComponentIterator it; unsigned cSimp; unsigned simp, perm; std::string curr; std::string* comp = new std::string[tri.getNumberOfComponents()]; for (it = tri.getComponents().begin(), i = 0; it != tri.getComponents().end(); ++it, ++i) { cSimp = (*it)->getNumberOfSimplices(); for (simp = 0; simp < (*it)->getNumberOfSimplices(); ++simp) for (perm = 0; perm < Perm::nPerms; ++perm) { curr = isoSigFrom(tri, (*it)->getSimplex(simp)->markedIndex(), Perm::orderedSn[perm], currRelabelling); if ((simp == 0 && perm == 0) || (curr < comp[i])) { comp[i].swap(curr); if (relabelling) std::swap(*relabelling, currRelabelling); } } } // Pack the components together. std::sort(comp, comp + tri.getNumberOfComponents()); std::string ans; for (i = 0; i < tri.getNumberOfComponents(); ++i) ans += comp[i]; delete[] comp; delete currRelabelling; return ans; } template typename DimTraits::Triangulation* NGenericTriangulation::fromIsoSig(const std::string& sig) { // These typedefs are already present in the class declaration, // but gcc 4.4 seems to break unless we include them here also. typedef typename DimTraits::Perm Perm; typedef typename DimTraits::Simplex Simplex; typedef typename DimTraits::Triangulation Triangulation; std::auto_ptr ans(new Triangulation()); NPacket::ChangeEventSpan span(ans.get()); const char* c = sig.c_str(); // Initial check for invalid characters. const char* d; for (d = c; *d; ++d) if (! SVALID(*d)) return 0; unsigned i, j; unsigned nSimp, nChars; while (*c) { // Read one component at a time. nSimp = SVAL(*c++); if (nSimp < 63) nChars = 1; else { if (! *c) return 0; nChars = SVAL(*c++); if (! SHASCHARS(c, nChars)) return 0; nSimp = SREAD(c, nChars); c += nChars; } if (nSimp == 0) { // Empty component. continue; } // Non-empty component; keep going. char* facetAction = new char[(dim+1) * nSimp + 2]; unsigned nFacets = 0; unsigned facetPos = 0; unsigned nJoins = 0; for ( ; nFacets < (dim+1) * nSimp; facetPos += 3) { if (! *c) { delete[] facetAction; return 0; } SREADTRITS(*c++, facetAction + facetPos); for (i = 0; i < 3; ++i) { // If we're already finished, make sure the leftover trits // are zero. if (nFacets == (dim+1) * nSimp) { if (facetAction[facetPos + i] != 0) { delete[] facetAction; return 0; } continue; } if (facetAction[facetPos + i] == 0) ++nFacets; else if (facetAction[facetPos + i] == 1) nFacets += 2; else if (facetAction[facetPos + i] == 2) { nFacets += 2; ++nJoins; } else { delete[] facetAction; return 0; } if (nFacets > (dim+1) * nSimp) { delete[] facetAction; return 0; } } } unsigned* joinDest = new unsigned[nJoins + 1]; for (i = 0; i < nJoins; ++i) { if (! SHASCHARS(c, nChars)) { delete[] facetAction; delete[] joinDest; return 0; } joinDest[i] = SREAD(c, nChars); c += nChars; } unsigned* joinGluing = new unsigned[nJoins + 1]; for (i = 0; i < nJoins; ++i) { if (! SHASCHARS(c, 1)) { delete[] facetAction; delete[] joinDest; delete[] joinGluing; return 0; } joinGluing[i] = SREAD(c, CHARS_PER_PERM(dim)); c += CHARS_PER_PERM(dim); if (joinGluing[i] >= Perm::nPerms) { delete[] facetAction; delete[] joinDest; delete[] joinGluing; return 0; } } // End of component! Simplex** simp = new Simplex*[nSimp]; for (i = 0; i < nSimp; ++i) simp[i] = ans->newSimplex(); facetPos = 0; unsigned nextUnused = 1; unsigned joinPos = 0; for (i = 0; i < nSimp; ++i) for (j = 0; j <= dim; ++j) { // Already glued from the other side: if (simp[i]->adjacentSimplex(j)) continue; if (facetAction[facetPos] == 0) { // Boundary facet. } else if (facetAction[facetPos] == 1) { // Join to new simplex. simp[i]->joinTo(j, simp[nextUnused++], Perm()); } else { // Join to existing simplex. if (joinDest[joinPos] >= nextUnused || simp[joinDest[joinPos]]->adjacentSimplex( Perm::orderedSn[joinGluing[joinPos]][j])) { delete[] facetAction; delete[] joinDest; delete[] joinGluing; for (int k = 0; k < nSimp; ++k) delete simp[k]; delete[] simp; return 0; } simp[i]->joinTo(j, simp[joinDest[joinPos]], Perm::orderedSn[joinGluing[joinPos]]); ++joinPos; } ++facetPos; } delete[] facetAction; delete[] joinDest; delete[] joinGluing; delete[] simp; } return ans.release(); } template size_t NGenericTriangulation::isoSigComponentSize(const std::string& sig) { const char* c = sig.c_str(); // Examine the first character. // Note that SVALID also ensures that *c is non-null (i.e., it // detects premature end of string). if (! SVALID(*c)) return 0; size_t nSimp = SVAL(*c); if (nSimp < 63) return nSimp; // The number of simplices is so large that it requires several // characters to store. ++c; if (! *c) return 0; size_t nChars = SVAL(*c++); for (const char* d = c; d < c + nChars; ++d) if (! SVALID(*d)) return 0; return SREAD(c, nChars); } } // namespace regina regina-4.96/engine/generic/nfacetspec.h000644 000765 000024 00000033643 12377775222 020004 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file generic/nfacetspec.h * \brief Allows lightweight representation of individual facets of * simplices. */ #ifndef __NFACETSPEC_H #ifndef __DOXYGEN #define __NFACETSPEC_H #endif #include "regina-core.h" namespace regina { /** * \weakgroup generic * @{ */ /** * A lightweight class used to refer to a particular facet of a * particular simplex in a triangulation. Only the simplex index * and the facet number are stored. * * The template parameter gives the dimension of the triangulation * (so for dimension three, this class describes a face of a tetrahedron, * and for dimension four it describes a facet of a pentachoron). * * Facilities are provided for iterating through simplex facets. * With this in mind, it is also possible to represent the overall * boundary, a past-the-end value and a before-the-start value. * * When iterating through the simplex facets, the facets will be * ordered first by simplex index and then by facet number. The * overall boundary appears after all other simplex facets. * * If there are \a n simplices, the simplices will be numbered from 0 * to n-1 inclusive. The boundary will be represented as * simplex \a n, facet 0. The past-the-end value will be represented * as simplex \a n, facet 1, and the before-the-start value will be * represented as simplex -1, facet \a dim. * * \ifacespython The generic template NFacetSpec is not available to * Python users, although the special 3-dimensional case NTetFace is. * All Python notes in this class refer to the special case * NTetFace only. */ template struct NFacetSpec { int simp; /**< The simplex referred to. Simplex numbering begins * at 0. */ int facet; /**< The facet of the simplex referred to. The facet number * is between 0 and \a dim inclusive. */ /** * Creates a new specifier with no initialisation. This * specifier must be initialised before it is used. */ NFacetSpec(); /** * Creates a new specifier referring to the given facet of the given * simplex. * * @param newSimp the given simplex; see the class notes for * allowable values of this parameter. * @param newFacet the given facet; this should be between 0 and * \a dim inclusive. */ NFacetSpec(int newSimp, int newFacet); /** * Creates a new specifier referring to the same simplex facet as * the given specifier. * * @param cloneMe the specifier to clone. */ NFacetSpec(const NFacetSpec& cloneMe); /** * Determines if this specifier represents the overall boundary. * * @param nSimplices the number of simplices under consideration. * Note that the boundary is represented in this specifier as * simplex \a nSimplices, facet 0. * @return \c true if and only if this specifier represents the * overall boundary. */ bool isBoundary(unsigned nSimplices) const; /** * Determines if this specifier represents a before-the-start value. * * @return \c true if and only if this specifier is before-the-start. */ bool isBeforeStart() const; /** * Determines if this specifier represents a past-the-end value. * You can optionally declare the overall boundary to be * past-the-end as well as the already predefined past-the-end value. * * @param nSimplices the number of simplices under consideration. * Note that past-the-end is represented in this specifier as * simplex \a nSimplices, facet 1. * @param boundaryAlso \c true if the overall boundary should be * considered past-the-end in addition to the predefined past-the-end * value. * @return \c true if and only if this specifier is past-the-end. */ bool isPastEnd(unsigned nSimplices, bool boundaryAlso) const; /** * Sets this specifier to the first facet of the first simplex. */ void setFirst(); /** * Sets this specifier to the overall boundary. * * @param nSimplices the number of simplices under consideration. * Note that the boundary is represented in this specifier as * simplex \a nSimplices, facet 0. */ void setBoundary(unsigned nSimplices); /** * Sets this specifier to before-the-start. */ void setBeforeStart(); /** * Sets this specifier to past-the-end. * * @param nSimplices the number of simplices under consideration. * Note that past-the-end is represented in this specifier as * simplex \a nSimplices, facet 1. */ void setPastEnd(unsigned nSimplices); /** * Sets this specifier to the value of the given specifier. * * @param other the given specifier. * @return a reference to this specifier. */ NFacetSpec& operator = (const NFacetSpec& other); /** * Increments this specifier. It will be changed to point to the * next simplex facet. * * Facets are ordered first by simplex index and then by facet * number. The overall boundary appears after all other facets. * * \pre This specifier is not past-the-end. * * \ifacespython Not present, although the preincrement operator is * present in python as the member function inc(). * * @return A copy of this specifier after it has been incremented. */ NFacetSpec operator ++ (); /** * Increments this specifier. It will be changed to point to the * next simplex facet. * * Facets are ordered first by simplex index and then by facet * number. The overall boundary appears after all other facets. * * \pre This specifier is not past-the-end. * * \ifacespython This routine is named inc() since python does not * support the increment operator. * * @return A copy of this specifier before it was incremented. */ NFacetSpec operator ++ (int); /** * Decrements this specifier. It will be changed to point to the * previous simplex facet. * * Facets are ordered first by simplex index and then by facet * number. The overall boundary appears after all other facets. * * \pre This specifier is not before-the-start. * * \ifacespython Not present, although the predecrement operator is * present in python as the member function dec(). * * @return A copy of this specifier after it has been decremented. */ NFacetSpec operator -- (); /** * Decrements this specifier. It will be changed to point to the * previous simplex facet. * * Facets are ordered first by simplex index and then by facet * number. The overall boundary appears after all other facets. * * \pre This specifier is not before-the-start. * * \ifacespython This routine is named dec() since python does not * support the decrement operator. * * @return A copy of this specifier before it was decremented. */ NFacetSpec operator -- (int); /** * Determines if this and the given specifier are identical. * * @param other the specifier to compare with this. * @return \c true if and only if this and the given specifier are * equal. */ bool operator == (const NFacetSpec& other) const; /** * Determines if this is less than the given specifier. * * @param other the specifier to compare with this. * @return \c true if and only if this is less than the given * specifier. */ bool operator < (const NFacetSpec& other) const; /** * Determines if this is less than or equal to the given specifier. * * @param other the specifier to compare with this. * @return \c true if and only if this is less than or equal to * the given specifier. */ bool operator <= (const NFacetSpec& other) const; }; /** * A lightweight class used to refer to a particular edge of a * particular triangle in a 2-manifold triangulation. This is a * convenience typedef for the template instance NFacetSpec<2>. * * \ifacespython The specific class Dim2TriangleEdge is available through * Python, even though the generic template NFacetSpec is not. */ typedef NFacetSpec<2> Dim2TriangleEdge; /** * A lightweight class used to refer to a particular face of a * particular tetrahedron in a 3-manifold triangulation. This is a * convenience typedef for the template instance NFacetSpec<3>. * * \ifacespython The specific class NTetFace is available through Python, * even though the generic template NFacetSpec is not. Both the old field * names (\a tet and \a face) and the new field names (\a simp and \a facet) * are provided, though the old names are deprecated and will be removed * in a future version of Regina. * * \deprecated For the 3-dimensional class NTetFace, the old field names * \a tet and \a face are deprecated. Please use the new (generic) names * \a simp and \a facet instead. The old names are no longer supported * in C++, but will continue to be supported in Python until Regina 5.0. */ typedef NFacetSpec<3> NTetFace; /*@}*/ // Inline functions for NFacetSpec template inline NFacetSpec::NFacetSpec() { } template inline NFacetSpec::NFacetSpec(int newSimp, int newFacet) : simp(newSimp), facet(newFacet) { } template inline NFacetSpec::NFacetSpec(const NFacetSpec& cloneMe) : simp(cloneMe.simp), facet(cloneMe.facet) { } template inline bool NFacetSpec::isBoundary(unsigned nSimplices) const { return (simp == static_cast(nSimplices) && facet == 0); } template inline bool NFacetSpec::isBeforeStart() const { return (simp < 0); } template inline bool NFacetSpec::isPastEnd(unsigned nSimplices, bool boundaryAlso) const { return (simp == static_cast(nSimplices) && (boundaryAlso || facet > 0)); } template inline void NFacetSpec::setFirst() { simp = facet = 0; } template inline void NFacetSpec::setBoundary(unsigned nSimplices) { simp = nSimplices; facet = 0; } template inline void NFacetSpec::setBeforeStart() { simp = -1; facet = dim; } template inline void NFacetSpec::setPastEnd(unsigned nSimplices) { simp = nSimplices; facet = 1; } template inline NFacetSpec& NFacetSpec::operator = ( const NFacetSpec& other) { simp = other.simp; facet = other.facet; return *this; } template inline NFacetSpec NFacetSpec::operator ++ () { if (++facet > dim) { facet = 0; ++simp; } return *this; } template inline NFacetSpec NFacetSpec::operator ++ (int) { NFacetSpec ans(*this); if (++facet > dim) { facet = 0; ++simp; } return ans; } template inline NFacetSpec NFacetSpec::operator -- () { if (--facet < 0) { facet = dim; --simp; } return *this; } template inline NFacetSpec NFacetSpec::operator -- (int) { NFacetSpec ans(*this); if (--facet < 0) { facet = dim; --simp; } return ans; } template inline bool NFacetSpec::operator == (const NFacetSpec& other) const { return (simp == other.simp && facet == other.facet); } template inline bool NFacetSpec::operator < (const NFacetSpec& other) const { return (simp < other.simp || (simp == other.simp && facet < other.facet)); } template inline bool NFacetSpec::operator <= (const NFacetSpec& other) const { return (simp < other.simp || (simp == other.simp && facet <= other.facet)); } } // namespace regina #endif regina-4.96/engine/generic/ngenericisomorphism-impl.h000644 000765 000024 00000016453 12377775223 022715 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /* Template definitions for ngenericisomorphism.h. */ #include #include #include "packet/npacket.h" #include "generic/ngenericisomorphism.h" namespace regina { template void NGenericIsomorphism::writeTextShort(std::ostream& out) const { out << "Isomorphism between " << dim << "-manifold triangulations"; } template void NGenericIsomorphism::writeTextLong(std::ostream& out) const { for (unsigned i = 0; i < nSimplices_; ++i) out << i << " -> " << simpImage_[i] << " (" << facetPerm_[i] << ")\n"; } template bool NGenericIsomorphism::isIdentity() const { for (unsigned p = 0; p < nSimplices_; ++p) { if (simpImage_[p] != static_cast(p)) return false; if (! facetPerm_[p].isIdentity()) return false; } return true; } template NGenericIsomorphism::NGenericIsomorphism( const NGenericIsomorphism& cloneMe) : ShareableObject(), nSimplices_(cloneMe.nSimplices_), simpImage_(cloneMe.nSimplices_ > 0 ? new int[cloneMe.nSimplices_] : 0), facetPerm_(cloneMe.nSimplices_ > 0 ? new Perm[cloneMe.nSimplices_] : 0) { std::copy(cloneMe.simpImage_, cloneMe.simpImage_ + nSimplices_, simpImage_); std::copy(cloneMe.facetPerm_, cloneMe.facetPerm_ + nSimplices_, facetPerm_); } template typename NGenericIsomorphism::Isomorphism* NGenericIsomorphism:: random(unsigned nSimplices) { Isomorphism* ans = new Isomorphism(nSimplices); // Randomly choose the destination simplices. unsigned i; for (i = 0; i < nSimplices; i++) ans->simpImage_[i] = i; std::random_shuffle(ans->simpImage_, ans->simpImage_ + nSimplices); // Randomly choose the individual permutations. for (i = 0; i < nSimplices; i++) ans->facetPerm_[i] = Perm::Sn[rand() % Perm::nPerms]; return ans; } template typename NGenericIsomorphism::Triangulation* NGenericIsomorphism::apply( const typename NGenericIsomorphism::Triangulation* original) const { if (original->getNumberOfSimplices() != nSimplices_) return 0; if (nSimplices_ == 0) return new Triangulation(); Triangulation* ans = new Triangulation(); Simplex** tet = new Simplex*[nSimplices_]; unsigned long t; int f; NPacket::ChangeEventSpan span(ans); for (t = 0; t < nSimplices_; t++) tet[t] = ans->newSimplex(); for (t = 0; t < nSimplices_; t++) tet[simpImage_[t]]->setDescription( original->getSimplex(t)->getDescription()); const Simplex *myTet, *adjTet; unsigned long adjTetIndex; Perm gluingPerm; for (t = 0; t < nSimplices_; t++) { myTet = original->getSimplex(t); for (f = 0; f <= dim; f++) if ((adjTet = myTet->adjacentSimplex(f))) { // We have an adjacent simplex. adjTetIndex = original->simplexIndex(adjTet); gluingPerm = myTet->adjacentGluing(f); // Make the gluing from one side only. if (adjTetIndex > t || (adjTetIndex == t && gluingPerm[f] > f)) tet[simpImage_[t]]->joinTo(facetPerm_[t][f], tet[simpImage_[adjTetIndex]], facetPerm_[adjTetIndex] * gluingPerm * facetPerm_[t].inverse()); } } delete[] tet; return ans; } template void NGenericIsomorphism::applyInPlace( typename NGenericIsomorphism::Triangulation* tri) const { if (tri->getNumberOfSimplices() != nSimplices_) return; if (nSimplices_ == 0) return; Triangulation staging; Simplex** tet = new Simplex*[nSimplices_]; unsigned long t; int f; NPacket::ChangeEventSpan span1(&staging); for (t = 0; t < nSimplices_; t++) tet[t] = staging.newSimplex(); for (t = 0; t < nSimplices_; t++) tet[simpImage_[t]]->setDescription( tri->getSimplex(t)->getDescription()); const Simplex *myTet, *adjTet; unsigned long adjTetIndex; Perm gluingPerm; for (t = 0; t < nSimplices_; t++) { myTet = tri->getSimplex(t); for (f = 0; f <= dim; f++) if ((adjTet = myTet->adjacentSimplex(f))) { // We have an adjacent simplex. adjTetIndex = tri->simplexIndex(adjTet); gluingPerm = myTet->adjacentGluing(f); // Make the gluing from one side only. if (adjTetIndex > t || (adjTetIndex == t && gluingPerm[f] > f)) tet[simpImage_[t]]->joinTo(facetPerm_[t][f], tet[simpImage_[adjTetIndex]], facetPerm_[adjTetIndex] * gluingPerm * facetPerm_[t].inverse()); } } delete[] tet; NPacket::ChangeEventSpan span2(tri); tri->removeAllSimplices(); tri->swapContents(staging); } } // namespace regina regina-4.96/engine/generic/ngenericisomorphism.h000644 000765 000024 00000042263 12377775226 021757 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file generic/ngenericisomorphism.h * \brief Deals with combinatorial isomorphisms of \a n-manifold * triangulations. */ #ifndef __NGENERALISOMORPHISM_H #ifndef __DOXYGEN #define __NGENERALISOMORPHISM_H #endif #include "regina-core.h" #include "shareableobject.h" #include "generic/dimtraits.h" #include "generic/nfacetspec.h" namespace regina { /** * \weakgroup generic * @{ */ /** * A dimension-agnostic base class that represents a combinatorial * isomorphism from one \a dim-manifold triangulation into another. * * Each dimension that Regina works with (2, 3 and 4) offers its own * subclass with richer functionality; users typically do not need to * work with this template base class directly. * * In essence, a combinatorial isomorphism from triangulation T to * triangulation U is a one-to-one map from the simplices of T to the * simplices of U that allows relabelling of both the simplices and * their facets (or equivalently, their vertices), and that preserves * gluings across adjacent simplices. * * More precisely: An isomorphism consists of (i) a one-to-one map f * from the simplices of T to the simplices of U, and (ii) for each * simplex S of T, a permutation f_S of the facets (0,...,\a dim) of S, * for which the following condition holds: * * - If facet k of simplex S and facet k' of simplex S' * are identified in T, then facet f_S(k) of f(S) and facet f_S'(k') * of f(S') are identified in U. Moreover, their gluing is consistent * with the facet/vertex permutations; that is, there is a commutative * square involving the gluing maps in T and U and the permutations * f_S and f_S'. * * Isomorphisms can be boundary complete or * boundary incomplete. A boundary complete isomorphism * satisfies the additional condition: * * - If facet x is a boundary facet of T then facet f(x) is a boundary * facet of U. * * A boundary complete isomorphism thus indicates that a copy of * triangulation T is present as an entire component (or components) of U, * whereas a boundary incomplete isomorphism represents an embedding of a * copy of triangulation T as a subcomplex of some possibly larger component * (or components) of U. * * Note that in all cases triangulation U may contain more simplices * than triangulation T. * * \pre The dimension argument \a dim is either 2, 3 or 4. * * \ifacespython Not present, though the dimension-specific subclasses * (such as NIsomorphism and Dim4Isomorphism) are available for Python users. */ template class REGINA_API NGenericIsomorphism : public ShareableObject { public: typedef typename DimTraits::Isomorphism Isomorphism; /**< The isomorphism class used by triangulations of this specific dimension. Typically this is a subclass of NGenericIsomorphism. */ typedef typename DimTraits::Perm Perm; /**< The permutation class used to glue together facets of simplices when building triangulations in this dimension. */ typedef typename DimTraits::Simplex Simplex; /**< The class that represents a top-level simplex of a triangulation in this dimension. */ typedef typename DimTraits::Triangulation Triangulation; /**< The triangulation class specific to this dimension. */ protected: unsigned nSimplices_; /**< The number of simplices in the source triangulation. */ int* simpImage_; /**< The simplex of the destination triangulation that each simplex of the source triangulation maps to. */ Perm* facetPerm_; /**< The permutation applied to the facets of each source simplex. */ public: /** * Creates a new isomorphism with no initialisation. * * @param nSimplices the number of simplices in the source * triangulation associated with this isomorphism; this may be zero. */ NGenericIsomorphism(unsigned nSimplices); /** * Creates a new isomorphism identical to the given isomorphism. * * @param cloneMe the isomorphism upon which to base the new * isomorphism. */ NGenericIsomorphism(const NGenericIsomorphism& cloneMe); /** * Destroys this isomorphism. */ ~NGenericIsomorphism(); /** * Returns the number of simplices in the source triangulation * associated with this isomorphism. Note that this is always * less than or equal to the number of simplices in the * destination triangulation. * * @return the number of simplices in the source triangulation. */ unsigned getSourceSimplices() const; /** * Determines the image of the given source simplex under * this isomorphism. * * \ifacespython This is not available for Python users, even in * the dimension-specific subclasses. However, the read-only * version of this routine is. * * @param sourceSimp the index of the source simplex; this must * be between 0 and getSourceSimplices()-1 inclusive. * @return a reference to the index of the destination simplex * that the source simplex maps to. */ int& simpImage(unsigned sourceSimp); /** * Determines the image of the given source simplex under * this isomorphism. * * @param sourceSimp the index of the source simplex; this must * be between 0 and getSourceSimplices()-1 inclusive. * @return the index of the destination simplex * that the source simplex maps to. */ int simpImage(unsigned sourceSimp) const; /** * Returns a read-write reference to the permutation that is * applied to the (\a dim + 1) facets of the given source simplex * under this isomorphism. * Facet \a i of source simplex \a sourceSimp will be mapped to * facet facetPerm(sourceSimp)[i] of simplex * simpImage(sourceSimp). * * \ifacespython This is not available for Python users, even in * the dimension-specific subclasses. However, the read-only * version of this routine is. * * @param sourceSimp the index of the source simplex containing * the original (\a dim + 1) facets; this must be between 0 and * getSourceSimplices()-1 inclusive. * @return a read-write reference to the permutation applied to the * facets of the source simplex. */ Perm& facetPerm(unsigned sourceSimp); /** * Determines the permutation that is applied to the (\a dim + 1) * facets of the given source simplex under this isomorphism. * Facet \a i of source simplex \a sourceSimp will be mapped to * face facetPerm(sourceSimp)[i] of simplex * simpImage(sourceSimp). * * @param sourceSimp the index of the source simplex containing * the original (\a dim + 1) facets; this must be between 0 and * getSourceSimplices()-1 inclusive. * @return the permutation applied to the facets of the * source simplex. */ Perm facetPerm(unsigned sourceSimp) const; /** * Determines the image of the given source simplex facet * under this isomorphism. Note that a value only is returned; this * routine cannot be used to alter the isomorphism. * * @param source the given source simplex facet; this must * be one of the (\a dim + 1) facets of one of the getSourceSimplices() * simplices in the source triangulation. * @return the image of the source simplex facet under this * isomorphism. */ NFacetSpec operator [] (const NFacetSpec& source) const; /** * Determines whether or not this is an identity isomorphism. * * In an identity isomorphism, each simplex image is itself, * and within each simplex the facet/vertex permutation is * the identity permutation. * * @return \c true if this is an identity isomorphism, or * \c false otherwise. */ bool isIdentity() const; /** * This NGenericIsomorphism object represents a combinatorial * identification from a triangulation T to a triangulation U. * This routine produces the triangulation U, i.e. the range. The * input parameter (original) represents the domain, T. * * The given triangulation (call this T) is not modified in any way. * A new triangulation (call this U) is returned, so that this * isomorphism represents a one-to-one, onto and boundary complete * isomorphism from T to U. That is, T and U are combinatorially * identical triangulations, and this isomorphism describes the * corresponding mapping between simplex and simplex facets. * * The resulting triangulation U is newly created, and must be * destroyed by the caller of this routine. * * There are several preconditions to this routine. This * routine does a small amount of sanity checking (and returns 0 * if an error is detected), but it certainly does not check the * entire set of preconditions. It is up to the caller of this * routine to verify that all of the following preconditions are * met. * * \pre The number of simplices in the given triangulation is * precisely the number returned by getSourceSimplices() for * this isomorphism. * \pre This is a valid isomorphism (i.e., it has been properly * initialised, so that all simplex images are non-negative * and distinct, and all facet permutations are real permutations * of (0,...,\a dim). * \pre Each simplex image for this isomorphism lies * between 0 and getSourceSimplices()-1 inclusive * (i.e., this isomorphism does not represent a mapping from a * smaller triangulation into a larger triangulation). * * @param original the triangulation to which this isomorphism * should be applied. * @return the resulting new triangulation, or 0 if a problem * was encountered (i.e., an unmet precondition was noticed). */ Triangulation* apply(const Triangulation* original) const; /** * Applies this isomorphism to the given triangulation, * modifying the given triangulation directly. * * This is similar to apply(), except that instead of creating a * new triangulation, the simplices and vertices of the given * triangulation are modified directly. * * See apply() for further details on how this operation is performed. * * As with apply(), there are several preconditions to this routine. * This routine does a small amount of sanity checking (and returns * without changes if an error is detected), but it certainly does * not check the entire set of preconditions. It is up to the * caller of this routine to verify that all of the following * preconditions are met. * * \pre The number of simplices in the given triangulation is * precisely the number returned by getSourceSimplices() for * this isomorphism. * \pre This is a valid isomorphism (i.e., it has been properly * initialised, so that all simplex images are non-negative * and distinct, and all facet permutations are real permutations * of (0,...,\a dim). * \pre Each simplex image for this isomorphism lies * between 0 and getSourceSimplices()-1 inclusive * (i.e., this isomorphism does not represent a mapping from a * smaller triangulation into a larger triangulation). * * @param tri the triangulation to which this isomorphism * should be applied. */ void applyInPlace(Triangulation* tri) const; void writeTextShort(std::ostream& out) const; void writeTextLong(std::ostream& out) const; /** * Returns a random isomorphism for the given number of * simplices. This isomorphism will reorder simplices * 0 to nSimplices-1 in a random fashion, and for * each simplex a random permutation of its (\a dim + 1) vertices * will be selected. * * The isomorphism will be newly constructed, and must be * destroyed by the caller of this routine. The new isomorphism * will be of the appropriate dimension-specific subclass * (e.g., NIsomorphism for \a dim=3, or Dim2Isomorphism for * \a dim=2). * * Note that both the STL random number generator and the * standard C function rand() are used in this routine. All * possible isomorphisms for the given number of simplices are * equally likely. * * @param nSimplices the number of simplices that the new * isomorphism should operate upon. * @return the newly constructed random isomorphism. */ static Isomorphism* random(unsigned nSimplices); }; /*@}*/ // Inline functions for NGenericIsomorphism template inline NGenericIsomorphism::NGenericIsomorphism(unsigned nSimplices) : nSimplices_(nSimplices), simpImage_(nSimplices > 0 ? new int[nSimplices] : 0), facetPerm_(nSimplices > 0 ? new Perm[nSimplices] : 0) { } template inline NGenericIsomorphism::~NGenericIsomorphism() { // Always safe to delete null. delete[] simpImage_; delete[] facetPerm_; } template inline unsigned NGenericIsomorphism::getSourceSimplices() const { return nSimplices_; } template inline int& NGenericIsomorphism::simpImage(unsigned sourceSimp) { return simpImage_[sourceSimp]; } template inline int NGenericIsomorphism::simpImage(unsigned sourceSimp) const { return simpImage_[sourceSimp]; } template inline typename NGenericIsomorphism::Perm& NGenericIsomorphism::facetPerm( unsigned sourceSimp) { return facetPerm_[sourceSimp]; } template inline typename NGenericIsomorphism::Perm NGenericIsomorphism::facetPerm( unsigned sourceSimp) const { return facetPerm_[sourceSimp]; } template inline NFacetSpec NGenericIsomorphism::operator [] ( const NFacetSpec& source) const { return NFacetSpec(simpImage_[source.simp], facetPerm_[source.simp][source.facet]); } } // namespace regina #endif regina-4.96/engine/generic/ngenerictriangulation.cpp000644 000765 000024 00000005305 12377776614 022617 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "generic/ngenerictriangulation.h" // Template implementations: #include "generic/canonical-impl.h" #include "generic/isomorphism-impl.h" #include "generic/isosig-impl.h" // Dimension-specific headers required for template instantiations: #include "dim2/dim2triangulation.h" #include "triangulation/ntriangulation.h" // Instantiate the templates! template class regina::NGenericTriangulation<2>; template class regina::NGenericTriangulation<3>; regina-4.96/engine/generic/ngenerictriangulation.h000644 000765 000024 00000054355 12377775230 022266 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file generic/ngenerictriangulation.h * \brief Generic code for working with triangulations of arbitrary dimension. */ #ifndef __NGENERICTRIANGULATION_H #ifndef __DOXYGEN #define __NGENERICTRIANGULATION_H #endif #include "regina-core.h" #include "generic/dimtraits.h" #include #include #include namespace regina { /** * \weakgroup generic * @{ */ /** * A generic helper class for working with triangulations of arbitrary * dimension. * * This class is designed to implement member functions of the various * triangulation classes in a unified, dimension-agnostic manner. * * End users should not use this class directly. Instead they should * call the corresponding member functions from the corresponding * triangulation classes (NTriangulation and so on). * * \apinotfinal * * \ifacespython Not present. * * \pre The template argument \a dim must be one of the dimensions that * Regina supports. */ template class REGINA_API NGenericTriangulation : public DimTraits { public: using typename DimTraits::Isomorphism; using typename DimTraits::Perm; using typename DimTraits::Simplex; using typename DimTraits::Triangulation; public: /** * \name Basic Properties */ /*@{*/ /** * Determines whether this triangulation is empty. * An empty triangulation is one with no simplices at all. * * @return \c true if and only if this triangulation is empty. */ bool isEmpty() const; /*@}*/ /** * \name Isomorphism Testing */ /*@{*/ /** * Determines if this triangulation is combinatorially identical * to the given triangulation. * * Here "identical" means that the triangulations have the same * number of top-dimensional simplices, with gluings between the same * pairs of numbered simplices using the same gluing permutations. * In other words, "identical" means that the triangulations * are isomorphic via the identity isomorphism. * * To test for the less strict combinatorial isomorphism (which * allows relabelling of the top-dimensional simplices and their * vertices), see isIsomorphicTo() instead. * * This test does \e not examine the textual simplex descriptions, * as seen in Simplex::getDescription(); these may still differ. * It also does not test the numbering of vertices, edges and so on, * as used by getVertex(), getEdge() and so on; * although at the time of writing these will always be * numbered the same for identical triangulations, it is * conceivable that in future versions of Regina there may * be situations in which identical triangulations can acquire * different numberings for vertices, edges, etc. * * @param other the triangulation to compare with this one. * @return \c true if and only if the two triangulations are * combinatorially identical. */ bool isIdenticalTo(const typename DimTraits::Triangulation& other) const; /** * Determines if this triangulation is combinatorially * isomorphic to the given triangulation. * * Specifically, this routine determines if there is a * one-to-one and onto boundary complete combinatorial * isomorphism from this triangulation to \a other. Boundary * complete isomorphisms are described in detail in the * Isomorphism class notes. * * In particular, note that this triangulation and \a other must * contain the same number of top-dimensional simplices for such an * isomorphism to exist. * * If you need to ensure that top-dimensional simplices are labelled * the same in both triangulations, see the stricter test * isIdenticalTo() instead. * * If a boundary complete isomorphism is found, the details of * this isomorphism are returned. The isomorphism is newly * constructed, and so to assist with memory management is * returned as a std::auto_ptr. Thus, to test whether an * isomorphism exists without having to explicitly deal with the * isomorphism itself, you can call * if (isIsomorphicTo(other).get()) and the newly * created isomorphism (if it exists) will be automatically * destroyed. * * If more than one such isomorphism exists, only one will be * returned. For a routine that returns all such isomorphisms, * see findAllIsomorphisms(). * * \todo \opt Improve the complexity by choosing a simplex * mapping from each component and following gluings to * determine the others. * * @param other the triangulation to compare with this one. * @return details of the isomorphism if the two triangulations * are combinatorially isomorphic, or a null pointer otherwise. */ std::auto_ptr::Isomorphism> isIsomorphicTo( const typename DimTraits::Triangulation& other) const; /** * Determines if an isomorphic copy of this triangulation is * contained within the given triangulation, possibly as a * subcomplex of some larger component (or components). * * Specifically, this routine determines if there is a boundary * incomplete combinatorial isomorphism from this triangulation * to \a other. Boundary incomplete isomorphisms are described * in detail in the Isomorphism class notes. * * In particular, note that facets of top-dimensional simplices that * lie on the boundary of this triangulation need not correspond to * boundary facets of \a other, and that \a other may contain more * top-dimensional simplices than this triangulation. * * If a boundary incomplete isomorphism is found, the details of * this isomorphism are returned. The isomorphism is newly * constructed, and so to assist with memory management is * returned as a std::auto_ptr. Thus, to test whether an * isomorphism exists without having to explicitly deal with the * isomorphism itself, you can call * if (isContainedIn(other).get()) and the newly * created isomorphism (if it exists) will be automatically * destroyed. * * If more than one such isomorphism exists, only one will be * returned. For a routine that returns all such isomorphisms, * see findAllSubcomplexesIn(). * * @param other the triangulation in which to search for an * isomorphic copy of this triangulation. * @return details of the isomorphism if such a copy is found, * or a null pointer otherwise. */ std::auto_ptr::Isomorphism> isContainedIn( const typename DimTraits::Triangulation& other) const; /** * Finds all ways in which this triangulation is combinatorially * isomorphic to the given triangulation. * * This routine behaves identically to isIsomorphicTo(), except that * instead of returning just one isomorphism, all such isomorphisms * are returned. * * See the isIsomorphicTo() notes for additional information. * * The isomorphisms that are found will be inserted into the * given list. These isomorphisms will be newly created, and * the caller of this routine is responsible for destroying * them. The given list will not be emptied before the new * isomorphisms are inserted. * * \ifacespython Not present. * * @param other the triangulation to compare with this one. * @param results the list in which any isomorphisms found will * be stored. * @return the number of isomorphisms that were found. */ unsigned long findAllIsomorphisms( const typename DimTraits::Triangulation& other, std::list::Isomorphism*>& results) const; /** * Finds all ways in which an isomorphic copy of this triangulation * is contained within the given triangulation, possibly as a * subcomplex of some larger component (or components). * * This routine behaves identically to isContainedIn(), except * that instead of returning just one isomorphism (which may be * boundary incomplete and need not be onto), all such isomorphisms * are returned. * * See the isContainedIn() notes for additional information. * * The isomorphisms that are found will be inserted into the * given list. These isomorphisms will be newly created, and * the caller of this routine is responsible for destroying * them. The given list will not be emptied before the new * isomorphisms are inserted. * * \ifacespython Not present. * * @param other the triangulation in which to search for * isomorphic copies of this triangulation. * @param results the list in which any isomorphisms found will * be stored. * @return the number of isomorphisms that were found. */ unsigned long findAllSubcomplexesIn( const typename DimTraits::Triangulation& other, std::list::Isomorphism*>& results) const; /** * Relabel the top-dimensional simplices and their vertices so that * this triangulation is in canonical form. This is essentially * the lexicographically smallest labelling when the facet * gluings are written out in order. * * Two triangulations are isomorphic if and only if their canonical * forms are identical. * * The lexicographic ordering assumes that the facet gluings are * written in order of simplex index and then facet number. * Each gluing is written as the destination simplex index * followed by the gluing permutation (which in turn is written * as the images of 0,1,...,dim in order). * * \pre This routine currently works only when the triangulation * is connected. It may be extended to work with disconnected * triangulations in later versions of Regina. * * @return \c true if the triangulation was changed, or \c false * if the triangulation was in canonical form to begin with. */ bool makeCanonical(); /*@}*/ /** * \name Exporting Triangulations */ /*@{*/ /** * Constructs the isomorphism signature for this triangulation. * * An isomorphism signature is a compact text representation of * a triangulation. Unlike dehydrations for 3-manifold triangulations, * an isomorphism signature uniquely determines a triangulation up * to combinatorial isomorphism (assuming the dimension is known in * advance). * That is, two triangulations of dimension \a dim are combinatorially * isomorphic if and only if their isomorphism signatures are the same. * * The isomorphism signature is constructed entirely of printable * characters, and has length proportional to n log n, * where \a n is the number of top-dimenisonal simplices. * * Isomorphism signatures are more general than dehydrations: * they can be used with any triangulation (including closed, * bounded and/or disconnected triangulations, as well * as triangulations with large numbers of triangles). * * The time required to construct the isomorphism signature of a * triangulation is O(n^2 log^2 n). * * The routine fromIsoSig() can be used to recover a * triangulation from an isomorphism signature. The triangulation * recovered might not be identical to the original, but it will be * combinatorially isomorphic. * * If \a relabelling is non-null (i.e., it points to some * Isomorphism pointer \a p), then it will be modified to point * to a new isomorphism that describes the precise relationship * between this triangulation and the reconstruction from fromIsoSig(). * Specifically, the triangulation that is reconstructed from * fromIsoSig() will be combinatorially identical to * relabelling.apply(this). * * For a full and precise description of the isomorphism signature * format for 3-manifold triangulations, see Simplification paths * in the Pachner graphs of closed orientable 3-manifold * triangulations, Burton, 2011, arXiv:1110.6080. * The format for other dimensions is essentially the same, but with * minor dimension-specific adjustments. * * \ifacespython The isomorphism argument is not present. * Instead there are two routines: fromIsoSig(), which returns a * string only, and fromIsoSigDetail(), which returns a pair * (signature, relabelling). * * \pre If \a relabelling is non-null, then this triangulation * must be non-empty and connected. The facility to return a * relabelling for disconnected triangulations may be added to * Regina in a later release. * * \warning Do not mix isomorphism signatures between dimensions! * It is possible that the same string could corresponding to both a * \a p-dimensional triangulation and a \a q-dimensional triangulation * for different \a p and \a q. * * @param relabelling if non-null, this will be modified to point to a * new isomorphism describing the relationship between this * triangulation and that reconstructed from fromIsoSig(), as * described above. * @return the isomorphism signature of this triangulation. */ std::string isoSig( typename DimTraits::Isomorphism** relabelling = 0) const; /*@}*/ /** * \name Importing Triangulations */ /*@{*/ /** * Recovers a full triangulation from an isomorphism signature. * * See isoSig() for more information on isomorphism signatures. * It will be assumed that the signature describes a triangulation of * dimension \a dim. * * The triangulation that is returned will be newly created. * * Calling isoSig() followed by fromIsoSig() is not guaranteed to * produce an identical triangulation to the original, but it * \e is guaranteed to produce a combinatorially isomorphic * triangulation. * * For a full and precise description of the isomorphism signature * format for 3-manifold triangulations, see Simplification paths * in the Pachner graphs of closed orientable 3-manifold * triangulations, Burton, 2011, arXiv:1110.6080. * The format for other dimensions is essentially the same, but with * minor dimension-specific adjustments. * * \warning Do not mix isomorphism signatures between dimensions! * It is possible that the same string could corresponding to both a * \a p-dimensional triangulation and a \a q-dimensional triangulation * for different \a p and \a q. * * @param sig the isomorphism signature of the * triangulation to construct. Note that, unlike dehydration * strings for 3-manifold triangulations, case is important for * isomorphism signatures. * @return a newly allocated triangulation if the reconstruction was * successful, or null if the given string was not a valid * isomorphism signature. */ static typename DimTraits::Triangulation* fromIsoSig( const std::string& sig); /** * Deduces the number of top-dimensional simplices in a * connected triangulation from its isomorphism signature. * * See isoSig() for more information on isomorphism signatures. * It will be assumed that the signature describes a triangulation of * dimension \a dim. * * If the signature describes a connected triangulation, this * routine will simply return the size of that triangulation * (e.g., the number of tetrahedra in the case \a dim = 3). * You can also pass an isomorphism signature that describes a * disconnected triangulation; however, this routine will only * return the number of simplices in the first connected component. * If you need the total number of simplices in a disconnected * triangulation, you will need to reconstruct the full triangulation * by calling fromIsoSig() instead. * * This routine is very fast, since it only examines the first * few characters of the isomorphism signature (in which the size * of the first component is encoded). However, it is therefore * possible to pass an invalid isomorphism signature and still * receive a positive result. If you need to \e test whether a * signature is valid or not, you must call fromIsoSig() * instead, which will examine the entire signature in full. * * \warning Do not mix isomorphism signatures between dimensions! * It is possible that the same string could corresponding to both a * \a p-dimensional triangulation and a \a q-dimensional triangulation * for different \a p and \a q. * * @param sig an isomorphism signature of a \a dim-dimensional * triangulation. Note that, unlike dehydration strings for * 3-manifold triangulations, case is important for isomorphism * signatures. * @return the number of top-dimensional simplices in the first * connected component, or 0 if this could not be determined * because the given string was not a valid isomorphism signature. */ static size_t isoSigComponentSize(const std::string& sig); /*@}*/ private: /** * Internal to isoSig(). * * Constructs a candidate isomorphism signature for a single * component of this triangulation. This candidate signature * assumes that the given simplex with the given labelling * of its vertices becomes simplex zero with vertices 0..dim * under the "canonical isomorphism". * * @param simp the index of some simplex in this triangulation. * @param vertices some ordering of the vertices of the * given tetrahedron. * @param if this is non-null, it will be filled with the canonical * isomorphism; in this case it must already have been constructed * for the correct number of simplices. * @return the candidate isomorphism signature. */ static std::string isoSigFrom( const typename DimTraits::Triangulation& tri, unsigned simp, const typename DimTraits::Perm& vertices, typename DimTraits::Isomorphism* relabelling); }; /*@}*/ // Inline functions: template inline bool NGenericTriangulation::isEmpty() const { return (static_cast::Triangulation*>(this)-> getNumberOfSimplices() == 0); } } // namespace regina #endif regina-4.96/engine/manifold/CMakeLists.txt000644 000765 000024 00000001340 12311266525 020407 0ustar00babstaff000000 000000 # manifold # Files to compile SET ( FILES ngraphloop ngraphpair ngraphtriple nhandlebody nlensspace nmanifold nsfs nsfsaltset nsimplesurfacebundle nsnappeacensusmfd ntorusbundle order ) # Prepend folder name FOREACH ( SOURCE_FILE ${FILES} ) SET ( SOURCES ${SOURCES} manifold/${SOURCE_FILE}) ENDFOREACH(SOURCE_FILE) SET(SOURCES ${SOURCES} PARENT_SCOPE) if (${REGINA_INSTALL_DEV}) INSTALL(FILES ngraphloop.h ngraphpair.h ngraphtriple.h nhandlebody.h nlensspace.h nmanifold.h notation.h nsfs.h nsfsaltset.h nsimplesurfacebundle.h nsnappeacensusmfd.h ntorusbundle.h DESTINATION ${INCLUDEDIR}/manifold COMPONENT Development) endif (${REGINA_INSTALL_DEV}) regina-4.96/engine/manifold/ngraphloop.cpp000644 000765 000024 00000022342 12377776614 020552 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "algebra/nabeliangroup.h" #include "manifold/ngraphloop.h" #include "manifold/nsfs.h" #include "maths/nmatrixint.h" #include // For labs(). namespace regina { NGraphLoop::~NGraphLoop() { delete sfs_; } bool NGraphLoop::operator < (const NGraphLoop& compare) const { if (*sfs_ < *compare.sfs_) return true; if (*compare.sfs_ < *sfs_) return false; return simpler(matchingReln_, compare.matchingReln_); } NAbelianGroup* NGraphLoop::getHomologyH1() const { // Just for safety (this should always be true anyway): if (sfs_->punctures(false) != 2 || sfs_->punctures(true) != 0) return 0; // Construct a matrix. // Generators: fibre, base curves, two base boundaries, exceptional // fibre boundaries, obstruction boundary, // reflector boundaries, reflector half-fibres, plus one // for the loop created by the joining of boundaries. // Relations: base curve relation, exception fibre relations, // obstruction relation, reflector relations, // fibre constraint, joining boundaries. unsigned long genus = sfs_->baseGenus(); unsigned long fibres = sfs_->fibreCount(); unsigned long ref = sfs_->reflectors(); // If we have an orientable base space, we get two curves per genus. // The easiest thing to do is just to double the genus now. if (sfs_->baseOrientable()) genus *= 2; NMatrixInt m(fibres + ref + 5, genus + fibres + 2 * ref + 5); unsigned long i, f; // The relation for the base orbifold: for (i = 1 + genus; i < 1 + genus + 2 + fibres + 1 + ref; i++) m.entry(0, i) = 1; if (! sfs_->baseOrientable()) for (i = 1; i < 1 + genus; i++) m.entry(0, i) = 2; // A relation for each exceptional fibre: NSFSFibre fibre; for (f = 0; f < fibres; f++) { fibre = sfs_->fibre(f); m.entry(f + 1, 1 + genus + 2 + f) = fibre.alpha; m.entry(f + 1, 0) = fibre.beta; } // A relation for the obstruction constant: m.entry(1 + fibres, 1 + genus + 2 + fibres) = 1; m.entry(1 + fibres, 0) = sfs_->obstruction(); // A relation for each reflector boundary: for (i = 0; i < ref; i++) { m.entry(2 + fibres + i, 0) = -1; m.entry(2 + fibres + i, 1 + genus + 2 + fibres + 1 + ref + i) = 2; } // A relation constraining the fibre. This relationship only // appears in some cases; otherwise we will just have a (harmless) // zero row in the matrix. if (sfs_->reflectors(true)) m.entry(2 + fibres + ref, 0) = 1; else if (sfs_->fibreReversing()) m.entry(2 + fibres + ref, 0) = 2; // Two relations for the joining of boundaries: m.entry(3 + fibres + ref, 0) = -1; m.entry(3 + fibres + ref, 0) += matchingReln_[0][0]; m.entry(3 + fibres + ref, 2 + genus) = matchingReln_[0][1]; m.entry(4 + fibres + ref, 1 + genus) = -1; m.entry(4 + fibres + ref, 0) = matchingReln_[1][0]; m.entry(4 + fibres + ref, 2 + genus) = matchingReln_[1][1]; NAbelianGroup* ans = new NAbelianGroup(); ans->addGroup(m); return ans; } std::ostream& NGraphLoop::writeName(std::ostream& out) const { sfs_->writeName(out); return out << " / [ " << matchingReln_[0][0] << ',' << matchingReln_[0][1] << " | " << matchingReln_[1][0] << ',' << matchingReln_[1][1] << " ]"; } std::ostream& NGraphLoop::writeTeXName(std::ostream& out) const { sfs_->writeTeXName(out); return out << "_{\\homtwo{" << matchingReln_[0][0] << "}{" << matchingReln_[0][1] << "}{" << matchingReln_[1][0] << "}{" << matchingReln_[1][1] << "}}"; } void NGraphLoop::reduce() { /** * Things to observe: * * 1. Inverting the matching matrix is harmless (it corresponds to * rotating the space a half-turn to switch the two boundary tori). * * 2. If we add a (1,1) twist to the SFS we can compensate by either: * - setting row 2 -> row 2 + row 1, or * - setting col 1 -> col 1 - col 2. */ sfs_->reduce(false); // Bring the SFS obstruction constant back to zero. long b = sfs_->obstruction(); if (b != 0) { sfs_->insertFibre(1, -b); matchingReln_[0][0] += b * matchingReln_[0][1]; matchingReln_[1][0] += b * matchingReln_[1][1]; } reduce(matchingReln_); // See if we can do any better by reflecting the entire space // and adding (1,1) twists to bring the obstruction constant back // up to zero again. // TODO: For non-orientable manifolds, reflect()/reduce() may yield // better results. NMatrix2 compMatch = NMatrix2(1, 0, sfs_->fibreCount(), 1) * NMatrix2(1, 0, 0, -1) * matchingReln_ * NMatrix2(1, 0, 0, -1); reduce(compMatch); if (simpler(compMatch, matchingReln_)) { // Do it. matchingReln_ = compMatch; sfs_->complementAllFibres(); } } void NGraphLoop::reduce(NMatrix2& reln) { // Reduce both the original and the inverse, and see who comes out // on top. reduceBasis(reln); NMatrix2 inv = reln.inverse(); reduceBasis(inv); if (simpler(inv, reln)) reln = inv; } void NGraphLoop::reduceBasis(NMatrix2& reln) { // Use (1,1) / (1,-1) pairs to make the top-left element of the // matrix as close to zero as possible. if (reln[0][1] != 0 && reln[0][0] != 0) { long nOps = (labs(reln[0][0]) + ((labs(reln[0][1]) - 1) / 2)) / labs(reln[0][1]); if ((reln[0][0] > 0 && reln[0][1] > 0) || (reln[0][0] < 0 && reln[0][1] < 0)) { // Same signs. for (long i = 0; i < nOps; i++) { reln[0][0] -= reln[0][1]; reln[1][0] -= reln[1][1]; reln[1][0] -= reln[0][0]; reln[1][1] -= reln[0][1]; } } else { // Opposite signs. for (long i = 0; i < nOps; i++) { reln[0][0] += reln[0][1]; reln[1][0] += reln[1][1]; reln[1][0] += reln[0][0]; reln[1][1] += reln[0][1]; } } // If abs(0,0) is half abs(0,1) then we might do better with yet // another operation. Check with simpler() in this case. if (labs(reln[0][0]) * 2 == labs(reln[0][1])) { NMatrix2 alt = reln; if ((alt[0][0] > 0 && alt[0][1] > 0) || (alt[0][0] < 0 && alt[0][1] < 0)) { // Same signs. alt[0][0] -= alt[0][1]; alt[1][0] -= alt[1][1]; alt[1][0] -= alt[0][0]; alt[1][1] -= alt[0][1]; } else { // Opposite signs. alt[0][0] += alt[0][1]; alt[1][0] += alt[1][1]; alt[1][0] += alt[0][0]; alt[1][1] += alt[0][1]; } if (simpler(alt, reln)) reln = alt; } } else { // TODO: We can still do something here. } } } // namespace regina regina-4.96/engine/manifold/ngraphloop.h000644 000765 000024 00000023701 12377775231 020211 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file manifold/ngraphloop.h * \brief Deals with graph manifolds formed from self-identified Seifert * fibred spaces. */ #ifndef __NGRAPHLOOP_H #ifndef __DOXYGEN #define __NGRAPHLOOP_H #endif #include "regina-core.h" #include "manifold/nmanifold.h" #include "maths/nmatrix2.h" namespace regina { class NSFSpace; /** * \weakgroup manifold * @{ */ /** * Represents a closed graph manifold formed by joining a * single bounded Seifert fibred space to itself along a torus. * * The Seifert fibred space must have two boundary components, each a * torus corresponding to a puncture in the base orbifold (with no * fibre-reversing twist as one travels around the boundary). * * The way in which the two torus boundaries are joined together is specified * by a 2-by-2 matrix \a M. This matrix relates the locations of the fibres * and base orbifold on the two boundary tori. * * More specifically, suppose that \a f0 and \a o0 are generators of the * first boundary torus, where \a f0 represents a directed fibre in the * Seifert fibred space and \a o0 represents the oriented boundary of * the base orbifold. Likewise, let \a f1 and \a o1 be generators of the * second boundary torus representing a directed fibre and the oriented * boundary of the base orbifold. Then the tori are joined together so * that the curves \a f0, \a o0, \a f1 and \a o1 become related as follows: * *
 *     [f1]       [f0]
 *     [  ] = M * [  ]
 *     [o1]       [o0]
 * 
* * See the page on \ref sfsnotation for details on some of the * terminology used above. * * The optional NManifold routine getHomologyH1() is implemented, but * the optional routine construct() is not. * * \todo \opt Speed up homology calculations involving orientable base * spaces by adding rank afterwards, instead of adding generators for * genus into the presentation matrix. */ class REGINA_API NGraphLoop : public NManifold { private: NSFSpace* sfs_; /**< The bounded Seifert fibred space that is joined to itself. */ NMatrix2 matchingReln_; /**< The matrix describing how the two boundary tori are joined; see the class notes for details. */ public: /** * Creates a new graph manifold as a self-identified Seifert fibred * space. The bounded Seifert fibred space and the four elements of * the 2-by-2 matching matrix are all passed separately. The elements * of the matching matrix combine to give the full matrix \a M as * follows: * *
         *           [ mat00  mat01 ]
         *     M  =  [              ]
         *           [ mat10  mat11 ]
         * 
* * Note that the new object will take ownership of the given * Seifert fibred space, and when this object is destroyed the * Seifert fibred space will be destroyed also. * * \pre The given Seifert fibred space has precisely two torus * boundaries, corresponding to two untwisted punctures in the * base orbifold. * \pre The given matching matrix has determinant +1 or -1. * * @param sfs the bounded Seifert fibred space. * @param mat00 the (0,0) element of the matching matrix. * @param mat01 the (0,1) element of the matching matrix. * @param mat10 the (1,0) element of the matching matrix. * @param mat11 the (1,1) element of the matching matrix. */ NGraphLoop(NSFSpace* sfs, long mat00, long mat01, long mat10, long mat11); /** * Creates a new graph manifold as a self-identified Seifert fibred * space. The bounded Seifert fibred space and the entire 2-by-2 * matching matrix are each passed separately. * * Note that the new object will take ownership of the given * Seifert fibred space, and when this object is destroyed the * Seifert fibred space will be destroyed also. * * \pre The given Seifert fibred space has precisely two torus * boundaries, corresponding to two punctures in the base orbifold. * \pre The given matching matrix has determinant +1 or -1. * * @param sfs the bounded Seifert fibred space. * @param matchingReln the 2-by-2 matching matrix. */ NGraphLoop(NSFSpace* sfs, const NMatrix2& matchingReln); /** * Destroys this structure along with the bounded Seifert * fibred space and the matching matrix. */ ~NGraphLoop(); /** * Returns a reference to the bounded Seifert fibred space that * is joined to itself. * * @return a reference to the bounded Seifert fibred space. */ const NSFSpace& sfs() const; /** * Returns a reference to the 2-by-2 matrix describing how the * two boundary tori of the Seifert fibred space are joined together. * See the class notes for details on precisely how this matrix is * represented. * * @return a reference to the matching matrix. */ const NMatrix2& matchingReln() const; /** * Determines in a fairly ad-hoc fashion whether this * representation of this space is "smaller" than the given * representation of the given space. * * The ordering imposed on graph manifolds is purely aesthetic * on the part of the author, and is subject to change in future * versions of Regina. It also depends upon the particular * representation, so that different representations of the same * space may be ordered differently. * * All that this routine really offers is a well-defined way of * ordering graph manifold representations. * * @param compare the representation with which this will be compared. * @return \c true if and only if this is "smaller" than the * given graph manifold representation. */ bool operator < (const NGraphLoop& compare) const; NAbelianGroup* getHomologyH1() const; bool isHyperbolic() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; private: /** * Uses (1,1) twists, inversion and/or reflection to make the * presentation of this space more aesthetically pleasing. */ void reduce(); /** * Uses (1,1) twists and/or inversion to make the given matching * matrix more aesthetically pleasing. * * This routine is for internal use by reduce(). * * @param reln the matching matrix to simplify. */ static void reduce(NMatrix2& reln); /** * Uses (1,1) twists to make the given matching matrix more * aesthetically pleasing. * * This routine is for internal use by reduce(). * * @param reln the matching matrix to simplify. */ static void reduceBasis(NMatrix2& reln); }; /*@}*/ // Inline functions for NGraphLoop inline NGraphLoop::NGraphLoop(NSFSpace* sfs, long mat00, long mat01, long mat10, long mat11) : sfs_(sfs), matchingReln_(mat00, mat01, mat10, mat11) { reduce(); } inline NGraphLoop::NGraphLoop(NSFSpace* sfs, const NMatrix2& matchingReln) : sfs_(sfs), matchingReln_(matchingReln) { reduce(); } inline const NSFSpace& NGraphLoop::sfs() const { return *sfs_; } inline const NMatrix2& NGraphLoop::matchingReln() const { return matchingReln_; } inline bool NGraphLoop::isHyperbolic() const { return false; } } // namespace regina #endif regina-4.96/engine/manifold/ngraphpair.cpp000644 000765 000024 00000027721 12377776615 020543 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "algebra/nabeliangroup.h" #include "manifold/ngraphpair.h" #include "manifold/nsfs.h" #include "manifold/nsfsaltset.h" #include "maths/nmatrixint.h" namespace regina { NGraphPair::~NGraphPair() { delete sfs_[0]; delete sfs_[1]; } bool NGraphPair::operator < (const NGraphPair& compare) const { if (*sfs_[0] < *compare.sfs_[0]) return true; if (*compare.sfs_[0] < *sfs_[0]) return false; if (*sfs_[1] < *compare.sfs_[1]) return true; if (*compare.sfs_[1] < *sfs_[1]) return false; return simpler(matchingReln_, compare.matchingReln_); } NAbelianGroup* NGraphPair::getHomologyH1() const { // Just for safety (this should always be true anyway): if (sfs_[0]->punctures(false) != 1 || sfs_[0]->punctures(true) != 0) return 0; if (sfs_[1]->punctures(false) != 1 || sfs_[1]->punctures(true) != 0) return 0; // Construct a matrix. // Generators: fibre 0, base curves 0, base boundary 0, // exceptional fibre boundaries 0, obstruction 0, // reflector boundaries 0, reflector half-fibres 0, // fibre 1, base curves 1, base boundary 1, // exceptional fibre boundaries 1, obstruction 1, // reflector boundaries 0, reflector half-fibres 1. // Relations: base curve relation 0, exceptional fibre relations 0, // obstruction relation 0, reflector relations 0, // fibre constraint 0, // base curve relation 1, exceptional fibre relations 1, // obstruction relation 1, reflector relations 1, // fibre constraint 1, // joining of boundaries. unsigned long genus0 = sfs_[0]->baseGenus(); unsigned long fibres0 = sfs_[0]->fibreCount(); unsigned long ref0 = sfs_[0]->reflectors(); unsigned long all0 = 3 + genus0 + fibres0 + 2 * ref0; unsigned long genus1 = sfs_[1]->baseGenus(); unsigned long fibres1 = sfs_[1]->fibreCount(); unsigned long ref1 = sfs_[1]->reflectors(); // If we have an orientable base space, we get two curves per genus. // The easiest thing to do is just to double each genus now. if (sfs_[0]->baseOrientable()) genus0 *= 2; if (sfs_[1]->baseOrientable()) genus1 *= 2; NMatrixInt m(fibres0 + fibres1 + ref0 + ref1 + 8, genus0 + fibres0 + 2 * ref0 + genus1 + fibres1 + 2 * ref1 + 6); unsigned long i, f; // The relation for each base orbifold: for (i = 1 + genus0; i < 1 + genus0 + 1 + fibres0 + 1 + ref0; i++) m.entry(0, i) = 1; if (! sfs_[0]->baseOrientable()) for (i = 1; i < 1 + genus0; i++) m.entry(0, i) = 2; for (i = 1 + genus1; i < 1 + genus1 + 1 + fibres1 + 1 + ref1; i++) m.entry(1, all0 + i) = 1; if (! sfs_[1]->baseOrientable()) for (i = 1; i < 1 + genus1; i++) m.entry(1, all0 + i) = 2; // A relation for each exceptional fibre and obstruction constant: NSFSFibre fibre; for (f = 0; f < fibres0; f++) { fibre = sfs_[0]->fibre(f); m.entry(2 + f, 1 + genus0 + 1 + f) = fibre.alpha; m.entry(2 + f, 0) = fibre.beta; } m.entry(2 + fibres0, 1 + genus0 + 1 + fibres0) = 1; m.entry(2 + fibres0, 0) = sfs_[0]->obstruction(); for (f = 0; f < fibres1; f++) { fibre = sfs_[1]->fibre(f); m.entry(3 + fibres0 + f, all0 + 1 + genus1 + 1 + f) = fibre.alpha; m.entry(3 + fibres0 + f, all0) = fibre.beta; } m.entry(3 + fibres0 + fibres1, all0 + 1 + genus1 + 1 + fibres1) = 1; m.entry(3 + fibres0 + fibres1, all0) = sfs_[1]->obstruction(); // A relation for each reflector boundary: for (i = 0; i < ref0; i++) { m.entry(4 + fibres0 + fibres1 + i, 0) = -1; m.entry(4 + fibres0 + fibres1 + i, 1 + genus0 + 1 + fibres0 + 1 + ref0 + i) = 2; } for (i = 0; i < ref1; i++) { m.entry(4 + fibres0 + fibres1 + ref0 + i, all0) = -1; m.entry(4 + fibres0 + fibres1 + ref0 + i, all0 + 1 + genus1 + 1 + fibres1 + 1 + ref1 + i) = 2; } // A relation contraining each fibre type. This relationship only // appears in some cases; otherwise we will just have a (harmless) // zero row in the matrix. if (sfs_[0]->reflectors(true)) m.entry(4 + fibres0 + fibres1 + ref0 + ref1, 0) = 1; else if (sfs_[0]->fibreReversing()) m.entry(4 + fibres0 + fibres1 + ref0 + ref1, 0) = 2; if (sfs_[1]->reflectors(true)) m.entry(5 + fibres0 + fibres1 + ref0 + ref1, all0) = 1; else if (sfs_[1]->fibreReversing()) m.entry(5 + fibres0 + fibres1 + ref0 + ref1, all0) = 2; // Finally, two relations for the joining of boundaries: m.entry(6 + fibres0 + fibres1 + ref0 + ref1, all0) = -1; m.entry(6 + fibres0 + fibres1 + ref0 + ref1, 0) = matchingReln_[0][0]; m.entry(6 + fibres0 + fibres1 + ref0 + ref1, 1 + genus0) = matchingReln_[0][1]; m.entry(7 + fibres0 + fibres1 + ref0 + ref1, all0 + 1 + genus1) = -1; m.entry(7 + fibres0 + fibres1 + ref0 + ref1, 0) = matchingReln_[1][0]; m.entry(7 + fibres0 + fibres1 + ref0 + ref1, 1 + genus0) = matchingReln_[1][1]; NAbelianGroup* ans = new NAbelianGroup(); ans->addGroup(m); return ans; } std::ostream& NGraphPair::writeName(std::ostream& out) const { sfs_[0]->writeName(out); out << " U/m "; sfs_[1]->writeName(out); return out << ", m = [ " << matchingReln_[0][0] << ',' << matchingReln_[0][1] << " | " << matchingReln_[1][0] << ',' << matchingReln_[1][1] << " ]"; } std::ostream& NGraphPair::writeTeXName(std::ostream& out) const { sfs_[0]->writeTeXName(out); out << " \\bigcup_{\\homtwo{" << matchingReln_[0][0] << "}{" << matchingReln_[0][1] << "}{" << matchingReln_[1][0] << "}{" << matchingReln_[1][1] << "}} "; return sfs_[1]->writeTeXName(out); } void NGraphPair::reduce() { /** * Things to observe: * * 1. If we add a (1,1) twist to sfs_[0] we can compensate by setting * col 1 -> col 1 - col 2. * * 2. If we add a (1,1) twist to sfs_[1] we can compensate by setting * row 2 -> row 2 + row 1. * * 3. We can negate the entire matrix without problems (this * corresponds to rotating one space by 180 degrees). * * 4. If we negate all fibres in sfs_[0] we can compensate by * negating col 1, though note that this negates the determinant * of the matrix. * * 5. If we negate all fibres in sfs_[1] we can compensate by * negating row 1, though again note that this negates the * determinant of the matrix. * * 6. If we wish to swap the two spaces, we invert M. */ // Simplify each space and build a list of possible reflections and // other representations that we wish to experiment with using. NSFSAltSet alt0(sfs_[0]); NSFSAltSet alt1(sfs_[1]); delete sfs_[0]; delete sfs_[1]; // Decide which of these possible representations gives the nicest // matching relation. NSFSpace* use0 = 0; NSFSpace* use1 = 0; NMatrix2 useReln; NMatrix2 tryReln; unsigned i, j; for (i = 0; i < alt0.size(); i++) for (j = 0; j < alt1.size(); j++) { // Insist on the leftmost space being at least as simple as // the rightmost. // See if the (i,j) combination is better than what we've // seen so far. tryReln = alt1.conversion(j) * matchingReln_ * alt0.conversion(i).inverse(); reduceSign(tryReln); // Try without space swapping. if (! (*alt1[j] < *alt0[i])) { if ((! use0) || simpler(tryReln, useReln)) { use0 = alt0[i]; use1 = alt1[j]; useReln = tryReln; } else if (! simpler(useReln, tryReln)) { // The matrix is the same as our best. Compare spaces. if (*alt0[i] < *use0 || (*alt0[i] == *use0 && *alt1[j] < *use1)) { use0 = alt0[i]; use1 = alt1[j]; useReln = tryReln; } } } // Now try with space swapping. if (! (*alt0[i] < *alt1[j])) { tryReln = tryReln.inverse(); reduceSign(tryReln); if ((! use0) || simpler(tryReln, useReln)) { use0 = alt1[j]; use1 = alt0[i]; useReln = tryReln; } else if (! simpler(useReln, tryReln)) { // The matrix is the same as our best. Compare spaces. if (*alt1[j] < *use0 || (*alt1[j] == *use0 && *alt0[i] < *use1)) { use0 = alt1[j]; use1 = alt0[i]; useReln = tryReln; } } } } // This should never happen, but just in case... let's not crash. if (! (use0 && use1)) { use0 = alt0[0]; use1 = alt1[0]; useReln = alt1.conversion(0) * matchingReln_ * alt0.conversion(0).inverse(); reduceSign(useReln); } // Use what we found. sfs_[0] = use0; sfs_[1] = use1; matchingReln_ = useReln; // And what we don't use, delete. alt0.deleteAll(use0, use1); alt1.deleteAll(use0, use1); // TODO: Exploit the (1,2) = (1,0) and (1,1) = (1,0) relations in // the relevant non-orientable cases. } void NGraphPair::reduceSign(NMatrix2& reln) { // All we can do is negate the entire matrix (180 degree rotation // along the join). if (simpler(- reln, reln)) reln.negate(); } } // namespace regina regina-4.96/engine/manifold/ngraphpair.h000644 000765 000024 00000024023 12377775233 020173 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file manifold/ngraphpair.h * \brief Deals with graph manifolds formed from pairs of Seifert fibred * spaces. */ #ifndef __NGRAPHPAIR_H #ifndef __DOXYGEN #define __NGRAPHPAIR_H #endif #include "regina-core.h" #include "manifold/nmanifold.h" #include "maths/nmatrix2.h" namespace regina { class NSFSpace; /** * \weakgroup manifold * @{ */ /** * Represents a closed graph manifold formed by joining * two bounded Seifert fibred spaces along a common torus. * * Each Seifert fibred space must have just one boundary component, * corresponding to a puncture in the base orbifold (with no * fibre-reversing twist as one travels around this boundary). * * The way in which the two spaces are joined is specified by a 2-by-2 * matrix \a M. This matrix expresses the locations of the fibres and * base orbifold of the second Seifert fibred space in terms of the first. * * More specifically, suppose that \a f0 and \a o0 are generators of the * common torus, where \a f0 represents a directed fibre in the first * Seifert fibred space and \a o0 represents the oriented boundary of * the corresponding base orbifold. Likewise, let \a f1 and \a o1 be * generators of the common torus representing a directed fibre and * the base orbifold of the second Seifert fibred space. Then the curves * \a f0, \a o0, \a f1 and \a o1 are related as follows: * *
 *     [f1]       [f0]
 *     [  ] = M * [  ]
 *     [o1]       [o0]
 * 
* * See the page on \ref sfsnotation for details on some of the * terminology used above. * * The optional NManifold routine getHomologyH1() is implemented, but * the optional routine construct() is not. * * \todo \opt Speed up homology calculations involving orientable base * spaces by adding rank afterwards, instead of adding generators for * genus into the presentation matrix. */ class REGINA_API NGraphPair : public NManifold { private: NSFSpace* sfs_[2]; /**< The two bounded Seifert fibred spaces that are joined together. */ NMatrix2 matchingReln_; /**< The matrix describing how the two spaces are joined; see the class notes for details. */ public: /** * Creates a new graph manifold as a pair of joined Seifert fibred * spaces. The two bounded Seifert fibred spaces and the four * elements of the 2-by-2 matching matrix are all passed separately. * The elements of the matching matrix combine to give the full * matrix \a M as follows: * *
         *           [ mat00  mat01 ]
         *     M  =  [              ]
         *           [ mat10  mat11 ]
         * 
* * Note that the new object will take ownership of the two given * Seifert fibred spaces, and when this object is destroyed the * Seifert fibred spaces will be destroyed also. * * \pre Each Seifert fibred space has a single torus boundary, * corresponding to a single untwisted puncture in the base orbifold. * \pre The given matching matrix has determinant +1 or -1. * * @param sfs0 the first Seifert fibred space. * @param sfs1 the second Seifert fibred space. * @param mat00 the (0,0) element of the matching matrix. * @param mat01 the (0,1) element of the matching matrix. * @param mat10 the (1,0) element of the matching matrix. * @param mat11 the (1,1) element of the matching matrix. */ NGraphPair(NSFSpace* sfs0, NSFSpace* sfs1, long mat00, long mat01, long mat10, long mat11); /** * Creates a new graph manifold as a pair of joined Seifert fibred * spaces. The two bounded Seifert fibred spaces and the entire * 2-by-2 matching matrix are each passed separately. * * Note that the new object will take ownership of the two given * Seifert fibred spaces, and when this object is destroyed the * Seifert fibred spaces will be destroyed also. * * \pre Each Seifert fibred space has a single torus boundary, * corresponding to a single untwisted puncture in the base orbifold. * \pre The given matching matrix has determinant +1 or -1. * * @param sfs0 the first Seifert fibred space. * @param sfs1 the second Seifert fibred space. * @param matchingReln the 2-by-2 matching matrix. */ NGraphPair(NSFSpace* sfs0, NSFSpace* sfs1, const NMatrix2& matchingReln); /** * Destroys this structure along with the component Seifert * fibred spaces and the matching matrix. */ ~NGraphPair(); /** * Returns a reference to one of the two bounded Seifert fibred * spaces that are joined together. * * @param which 0 if the first Seifert fibred space is to be * returned, or 1 if the second space is to be returned. * @return a reference to the requested Seifert fibred space. */ const NSFSpace& sfs(unsigned which) const; /** * Returns a reference to the 2-by-2 matrix describing how the * two Seifert fibred spaces are joined together. See the class * notes for details on precisely how this matrix is represented. * * @return a reference to the matching matrix. */ const NMatrix2& matchingReln() const; /** * Determines in a fairly ad-hoc fashion whether this * representation of this space is "smaller" than the given * representation of the given space. * * The ordering imposed on graph manifolds is purely aesthetic * on the part of the author, and is subject to change in future * versions of Regina. It also depends upon the particular * representation, so that different representations of the same * space may be ordered differently. * * All that this routine really offers is a well-defined way of * ordering graph manifold representations. * * @param compare the representation with which this will be compared. * @return \c true if and only if this is "smaller" than the * given graph manifold representation. */ bool operator < (const NGraphPair& compare) const; NAbelianGroup* getHomologyH1() const; bool isHyperbolic() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; private: /** * Uses (1,1) twists, reflections and other techniques to make * the presentation of this space more aesthetically pleasing. */ void reduce(); /** * Uses 180 degree rotation to make the given matching matrix * more aesthetically pleasing. * * This routine is for internal use by reduce(). * * @param reln the matching matrix to simplify. */ static void reduceSign(NMatrix2& reln); }; /*@}*/ // Inline functions for NGraphPair inline NGraphPair::NGraphPair(NSFSpace* sfs0, NSFSpace* sfs1, long mat00, long mat01, long mat10, long mat11) : matchingReln_(mat00, mat01, mat10, mat11) { sfs_[0] = sfs0; sfs_[1] = sfs1; reduce(); } inline NGraphPair::NGraphPair(NSFSpace* sfs0, NSFSpace* sfs1, const NMatrix2& matchingReln) : matchingReln_(matchingReln) { sfs_[0] = sfs0; sfs_[1] = sfs1; reduce(); } inline const NSFSpace& NGraphPair::sfs(unsigned which) const { return *sfs_[which]; } inline const NMatrix2& NGraphPair::matchingReln() const { return matchingReln_; } inline bool NGraphPair::isHyperbolic() const { return false; } } // namespace regina #endif regina-4.96/engine/manifold/ngraphtriple.cpp000644 000765 000024 00000040470 12377776616 021104 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "algebra/nabeliangroup.h" #include "manifold/ngraphtriple.h" #include "manifold/nsfs.h" #include "manifold/nsfsaltset.h" #include "maths/nmatrixint.h" namespace regina { NGraphTriple::~NGraphTriple() { delete end_[0]; delete end_[1]; delete centre_; } bool NGraphTriple::operator < (const NGraphTriple& compare) const { if (*centre_ < *compare.centre_) return true; if (*compare.centre_ < *centre_) return false; if (*end_[0] < *compare.end_[0]) return true; if (*compare.end_[0] < *end_[0]) return false; if (*end_[1] < *compare.end_[1]) return true; if (*compare.end_[1] < *end_[1]) return false; if (simpler(matchingReln_[0], compare.matchingReln_[0])) return true; if (simpler(compare.matchingReln_[0], matchingReln_[0])) return false; return simpler(matchingReln_[1], compare.matchingReln_[1]); } NAbelianGroup* NGraphTriple::getHomologyH1() const { // Just for safety (this should always be true anyway): if (end_[0]->punctures(false) != 1 || end_[0]->punctures(true) != 0) return 0; if (end_[1]->punctures(false) != 1 || end_[1]->punctures(true) != 0) return 0; if (centre_->punctures(false) != 2 || centre_->punctures(true) != 0) return 0; // Construct a matrix. // Generators: // - Spaces are ordered centre, end 0, end 1. // - For each space, generators are: // - fibre // - base curves // - base boundary // - exceptional fibre boundaries // - obstruction // - reflector boundaries // - reflector half-fibres // Relations: // - For each space: // - base curve relation // - exceptional fibre relations // - obstruction relation // - reflector relations // - fibre constraint // - Plus two boundary joinings. NSFSpace* sfs[3]; unsigned long genus[3], punc[3], fibres[3], ref[3], gens[3]; unsigned long start[3]; sfs[0] = centre_; sfs[1] = end_[0]; sfs[2] = end_[1]; punc[0] = 2; punc[1] = 1; punc[2] = 1; int s; for (s = 0; s < 3; s++) { genus[s] = sfs[s]->baseGenus(); fibres[s] = sfs[s]->fibreCount(); ref[s] = sfs[s]->reflectors(); // If we have an orientable base space, we get two curves per genus. // The easiest thing seems to be to just double the genus now. if (sfs[s]->baseOrientable()) genus[s] *= 2; gens[s] = 1 + genus[s] + punc[s] + fibres[s] + 1 + ref[s] + ref[s]; } start[0] = 0; start[1] = gens[0]; start[2] = gens[0] + gens[1]; NMatrixInt m(fibres[0] + fibres[1] + fibres[2] + ref[0] + ref[1] + ref[2] + 13, gens[0] + gens[1] + gens[2]); unsigned long i, f; NSFSFibre fibre; unsigned long reln = 0; // Relations internal to each space: for (s = 0; s < 3; s++) { // The relation for the base orbifold: for (i = 1 + genus[s]; i < 1 + genus[s] + punc[s] + fibres[s] + 1 + ref[s]; i++) m.entry(reln, start[s] + i) = 1; if (! sfs[s]->baseOrientable()) for (i = 1; i < 1 + genus[s]; i++) m.entry(reln, start[s] + i) = 2; reln++; // A relation for each exception fibre: for (f = 0; f < fibres[s]; f++) { fibre = sfs[s]->fibre(f); m.entry(reln, start[s] + 1 + genus[s] + punc[s] + f) = fibre.alpha; m.entry(reln, start[s]) = fibre.beta; reln++; } // The obstruction constant: m.entry(reln, start[s] + 1 + genus[s] + punc[s] + fibres[s]) = 1; m.entry(reln, start[s]) = sfs[s]->obstruction(); reln++; // A relation for each reflector boundary: for (i = 0; i < ref[s]; i++) { m.entry(reln, start[s]) = -1; m.entry(reln, start[s] + 1 + genus[s] + punc[s] + fibres[s] + 1 + ref[s] + i) = 2; reln++; } // A relation constraining the fibre. This relation only // appears in some cases; otherwise we will just have a // (harmless) zero row in the matrix. if (sfs[s]->reflectors(true)) m.entry(reln, start[s]) = 1; else if (sfs[s]->fibreReversing()) m.entry(reln, start[s]) = 2; reln++; } // Joining of boundaries: m.entry(reln, start[1]) = -1; m.entry(reln, 0) = matchingReln_[0][0][0]; m.entry(reln, 1 + genus[0]) = matchingReln_[0][0][1]; reln++; m.entry(reln, start[1] + 1 + genus[1]) = -1; m.entry(reln, 0) = matchingReln_[0][1][0]; m.entry(reln, 1 + genus[0]) = matchingReln_[0][1][1]; reln++; m.entry(reln, start[2]) = -1; m.entry(reln, 0) = matchingReln_[1][0][0]; m.entry(reln, 1 + genus[0] + 1) = matchingReln_[1][0][1]; reln++; m.entry(reln, start[2] + 1 + genus[2]) = -1; m.entry(reln, 0) = matchingReln_[1][1][0]; m.entry(reln, 1 + genus[0] + 1) = matchingReln_[1][1][1]; reln++; // Phew. NAbelianGroup* ans = new NAbelianGroup(); ans->addGroup(m); return ans; } std::ostream& NGraphTriple::writeName(std::ostream& out) const { end_[0]->writeName(out); out << " U/m "; centre_->writeName(out); out << " U/n "; end_[1]->writeName(out); NMatrix2 m0 = matchingReln_[0].inverse(); out << ", m = [ " << m0[0][0] << ',' << m0[0][1] << " | " << m0[1][0] << ',' << m0[1][1] << " ]"; out << ", n = [ " << matchingReln_[1][0][0] << ',' << matchingReln_[1][0][1] << " | " << matchingReln_[1][1][0] << ',' << matchingReln_[1][1][1] << " ]"; return out; } std::ostream& NGraphTriple::writeTeXName(std::ostream& out) const { end_[0]->writeTeXName(out); NMatrix2 m0 = matchingReln_[0].inverse(); out << " \\bigcup_{\\homtwo{" << m0[0][0] << "}{" << m0[0][1] << "}{" << m0[1][0] << "}{" << m0[1][1] << "}} "; centre_->writeTeXName(out); out << " \\bigcup_{\\homtwo{" << matchingReln_[1][0][0] << "}{" << matchingReln_[1][0][1] << "}{" << matchingReln_[1][1][0] << "}{" << matchingReln_[1][1][1] << "}} "; end_[1]->writeTeXName(out); return out; } void NGraphTriple::reduce() { /** * Things to observe: * * 1. If we add a (1,1) twist to centre_ we can compensate by setting * col 1 -> col 1 - col 2 in one of the matching relations. * * 2. If we add a (1,1) twist to end_[i] we can compensate by setting * row 2 -> row 2 + row 1 in matching relation i. * * 3. We can negate an entire matrix without problems (this * corresponds to rotating some spaces by 180 degrees). * * 4. If we negate all fibres in centre_ we can compensate by * negating col 1 of both matching relations, though note * that this negates the determinant of each matrix. * * 5. If we negate all fibres in end_[i] we can compensate by * negating row 1 of matching relation i, though again note that * this negates the determinant of the matrix. * * 6. If we wish to swap the order of spaces, we swap both matrices. */ // Simplify each space and build a list of possible reflections and // other representations that we wish to experiment with using. NSFSAltSet alt0(end_[0]); NSFSAltSet alt1(end_[1]); NSFSAltSet altCentre(centre_); delete end_[0]; delete end_[1]; delete centre_; // Decide which of these possible representations gives the nicest // matching relations. NSFSpace* use0 = 0; NSFSpace* use1 = 0; NSFSpace* useCentre = 0; NMatrix2 useReln[2]; NMatrix2 tryReln[2], tmpReln; unsigned i0, i1, c; for (i0 = 0; i0 < alt0.size(); i0++) for (i1 = 0; i1 < alt1.size(); i1++) for (c = 0; c < altCentre.size(); c++) { // See if (i0, i1, c) gives us a combination better than // anything we've seen so far. tryReln[0] = alt0.conversion(i0) * matchingReln_[0] * altCentre.conversion(c).inverse(); if (altCentre.reflected(c)) tryReln[1] = alt1.conversion(i1) * matchingReln_[1] * NMatrix2(1, 0, 0, -1); else tryReln[1] = alt1.conversion(i1) * matchingReln_[1]; reduceBasis(tryReln[0], tryReln[1]); // Insist on the first end space being at least as // simple as the second. // First try without end space swapping. if (! (*alt1[i1] < *alt0[i0])) { if ((! use0) || simpler(tryReln[0], tryReln[1], useReln[0], useReln[1])) { use0 = alt0[i0]; use1 = alt1[i1]; useCentre = altCentre[c]; useReln[0] = tryReln[0]; useReln[1] = tryReln[1]; } else if (! simpler(useReln[0], useReln[1], tryReln[0], tryReln[1])) { // The matrices are the same as our best. // Compare spaces. if (*altCentre[c] < *useCentre || (*altCentre[c] == *useCentre && *alt0[i0] < *use0) || (*altCentre[c] == *useCentre && *alt0[i0] == *use0 && *alt1[i1] < *use1)) { use0 = alt0[i0]; use1 = alt1[i1]; useCentre = altCentre[c]; useReln[0] = tryReln[0]; useReln[1] = tryReln[1]; } } } // Now try with end space swapping. if (! (*alt0[i0] < *alt1[i1])) { reduceBasis(tryReln[1], tryReln[0]); if ((! use0) || simpler(tryReln[1], tryReln[0], useReln[0], useReln[1])) { use0 = alt1[i1]; use1 = alt0[i0]; useCentre = altCentre[c]; useReln[0] = tryReln[1]; useReln[1] = tryReln[0]; } else if (! simpler(useReln[0], useReln[1], tryReln[1], tryReln[0])) { // The matrices are the same as our best. // Compare spaces. if (*altCentre[c] < *useCentre || (*altCentre[c] == *useCentre && *alt1[i1] < *use0) || (*altCentre[c] == *useCentre && *alt1[i1] == *use0 && *alt0[i0] < *use1)) { use0 = alt1[i1]; use1 = alt0[i0]; useCentre = altCentre[c]; useReln[0] = tryReln[1]; useReln[1] = tryReln[0]; } } } } // This should never happen, but just in case... let's not crash. if (! (use0 && use1 && useCentre)) { use0 = alt0[0]; use1 = alt1[0]; useCentre = altCentre[0]; useReln[0] = alt0.conversion(0) * matchingReln_[0] * altCentre.conversion(0).inverse(); useReln[1] = alt1.conversion(0) * matchingReln_[1] * altCentre.conversion(0).inverse(); reduceBasis(useReln[0], useReln[1]); } // Use what we found. end_[0] = use0; end_[1] = use1; centre_ = useCentre; matchingReln_[0] = useReln[0]; matchingReln_[1] = useReln[1]; // And what we don't use, delete. alt0.deleteAll(use0, use1); alt1.deleteAll(use0, use1); altCentre.deleteAll(useCentre); // TODO: More reductions! } void NGraphTriple::reduceBasis(NMatrix2& reln0, NMatrix2& reln1) { /** * The operation we allow here is to add a (1,1) / (1,-1) pair of * twists to centre_, which means: * * col 1 -> col 1 + col 2 in one of the matching relations; * col 1 -> col 1 - col 2 in the other. */ // Start by making the first entry in each column 2 positive (for // consistency). if (reln0[0][1] < 0 || (reln0[0][1] == 0 && reln0[1][1] < 0)) reln0.negate(); if (reln1[0][1] < 0 || (reln1[0][1] == 0 && reln1[1][1] < 0)) reln1.negate(); // Go for the local minimum. // TODO: We can certainly do better than this (both in terms of being // faster [use division] and simpler matrices coming out the end). NMatrix2 alt0, alt1; while (true) { alt0 = reln0 * NMatrix2(1, 0, 1, 1); alt1 = reln1 * NMatrix2(1, 0, -1, 1); if (simpler(alt0, alt1, reln0, reln1)) { reln0 = alt0; reln1 = alt1; continue; } alt0 = reln0 * NMatrix2(1, 0, -1, 1); alt1 = reln1 * NMatrix2(1, 0, 1, 1); if (simpler(alt0, alt1, reln0, reln1)) { reln0 = alt0; reln1 = alt1; continue; } // We're at a local minimum. Call it enough for now. break; } // Final tidying up. reduceSign(reln0); reduceSign(reln1); } void NGraphTriple::reduceSign(NMatrix2& reln) { // Make the first non-zero entry positive. int i, j; for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) { if (reln[i][j] > 0) return; if (reln[i][j] < 0) { // Negate everything (180 degree rotation along the join) // and return. for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) reln[i][j] = - reln[i][j]; return; } } // The matrix is entirely zero (which, incidentally, should never // happen). Do nothing. } } // namespace regina regina-4.96/engine/manifold/ngraphtriple.h000644 000765 000024 00000033124 12377775234 020542 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file manifold/ngraphtriple.h * \brief Deals with graph manifolds formed from sequences of three Seifert * fibred spaces. */ #ifndef __NGRAPHTRIPLE_H #ifndef __DOXYGEN #define __NGRAPHTRIPLE_H #endif #include "regina-core.h" #include "manifold/nmanifold.h" #include "maths/nmatrix2.h" namespace regina { class NSFSpace; /** * \weakgroup manifold * @{ */ /** * Represents a closed graph manifold formed by joining * three bounded Seifert fibred spaces along their torus boundaries. * * There must be one Seifert fibred space at either end, each with a * single torus boundary (corresponding to a single puncture in the * base orbifold, with no fibre-reversing twist around this puncture). * Each of these end spaces is joined to the space in the centre, which * has two disjoint torus boundaries (corresponding to two punctures * in the base orbifold, again with no fibre-reversing twists around * these punctures). * * This configuration is illustrated in the diagram below. The large * boxes represent the bounded Seifert fibred spaces, and the small * tunnels show how their boundaries are joined. * *
 *     /---------------\   /-----------------\   /---------------\
 *     |               |   |                 |   |               |
 *     |  End space 0   ---   Central space   ---   End space 1  |
 *     |                ---                   ---                |
 *     |               |   |                 |   |               |
 *     \---------------/   \-----------------/   \---------------/
 * 
* * The way in which each pair of spaces is joined is specified by a * 2-by-2 matrix. This matrix expresses the locations of the fibres and * base orbifold of the corresponding end space in terms of the central * space. * Note that these are not the same matrices that appear in the * manifold name in the census data files! See the warning below. * * More specifically, consider the matrix \a M that describes the * joining of the central space and the first end space (marked above as * end space 0). Suppose that \a f and \a o are generators of the common * boundary torus, where \a f represents a directed fibre in the central * space and \a o represents the oriented boundary of the corresponding * base orbifold. Likewise, let \a f0 and \a o0 be generators of the * common boundary torus representing a directed fibre and the base * orbifold of the first end space. Then the curves \a f, \a o, * \a f0 and \a o0 are related as follows: * *
 *     [f0]       [f ]
 *     [  ] = M * [  ]
 *     [o0]       [o ]
 * 
* * Likewise, let matrix \a M' describe the joining of the central * space and the second end space (marked in the diagram above as end * space 1). Let \a f' and \a o' be curves on the common boundary torus * representing the fibres and the base orbifold of the central space, * and let \a f1 and \a o1 be curves on this same torus representing the * fibres and the base orbifold of the second end space. Then the curves * \a f', \a o', \a f1 and \a o1 are related as follows: * *
 *     [f1]        [f']
 *     [  ] = M' * [  ]
 *     [o1]        [o']
 * 
* * See the page on \ref sfsnotation for details on some of the * terminology used above. * * The optional NManifold routine getHomologyH1() is implemented, but * the optional routine construct() is not. * * \warning The 2-by-2 matrices used in this class are \e not the same * matrices that appear in the manifold name returned by getName() * and getTeXName() and seen in the census data files. The matrices * used in this class work from the inside out, describing the boundary torus * on each end space in terms of a boundary torus on the central space. * The matrices used in the manifold name work from left to right in the * diagram above, describing a boundary torus on the central space or * rightmost end space in terms of a boundary torus on the leftmost end * space or central space respectively. The upshot of all this is that * the first matrix becomes inverted (and the second matrix * remains unchanged). It is likely that future versions of Regina will * replace this class with a more general class that (amongst other * things) removes this inconsistency. * * \todo \opt Speed up homology calculations involving orientable base * spaces by adding rank afterwards, instead of adding generators for * genus into the presentation matrix. */ class REGINA_API NGraphTriple : public NManifold { private: NSFSpace* end_[2]; /**< The two end spaces, i.e., the Seifert fibred spaces with just one boundary torus. */ NSFSpace* centre_; /**< The central space, i.e., the Seifert fibred space with two boundary tori that meets both end spaces. */ NMatrix2 matchingReln_[2]; /**< The matrices describing how the various spaces are joined. In particular, matrix \a matchingReln_[i] describes how the central space is joined to end space \a i. See the class notes for further details. */ public: /** * Creates a new graph manifold from three bounded * Seifert fibred spaces, as described in the class notes. * The three Seifert fibred spaces and both 2-by-2 matching * matrices are passed separately. * * Note that the new object will take ownership of the three given * Seifert fibred spaces, and when this object is destroyed the * Seifert fibred spaces will be destroyed also. * * \pre Spaces \a end0 and \a end1 each have a single torus * boundary, corresponding to a single untwisted puncture in the * base orbifold. * \pre Space \a centre has two disjoint torus boundaries, * corresponding to two untwisted punctures in the base orbifold. * \pre Each of the given matrices has determinant +1 or -1. * * @param end0 the first end space, as described in the class notes. * @param centre the central space, as described in the class notes. * @param end1 the second end space, as described in the class notes. * @param matchingReln0 the 2-by-2 matching matrix that * specifies how spaces \a end0 and \a centre are joined. * @param matchingReln1 the 2-by-2 matching matrix that * specifies how spaces \a end1 and \a centre are joined. */ NGraphTriple(NSFSpace* end0, NSFSpace* centre, NSFSpace* end1, const NMatrix2& matchingReln0, const NMatrix2& matchingReln1); /** * Destroys this structure along with the component Seifert * fibred spaces and matching matrices. */ ~NGraphTriple(); /** * Returns a reference to one of the two end spaces. * These are the Seifert fibred spaces with just one boundary * component, to be joined to the central space. See the class * notes for further discussion. * * @param which 0 if the first end space is to be returned, or * 1 if the second end space is to be returned. * @return a reference to the requested Seifert fibred space. */ const NSFSpace& end(unsigned which) const; /** * Returns a reference to the central space. * This is the Seifert fibred space with two boundary components, * to which the two end spaces are joined. See the class notes * for further discussion. * * @return a reference to the requested Seifert fibred space. */ const NSFSpace& centre() const; /** * Returns a reference to the 2-by-2 matrix describing how the * two requested bounded Seifert fibred spaces are joined together. * See the class notes for details on precisely how these matrices * are represented. * * The argument \a which indicates which particular join should be * examined. A value of 0 denotes the join between the central * space and the first end space (corresponding to matrix \a M * in the class notes), whereas a value of 1 denotes the join * between the central space and the second end space * (corresponding to matrix \a M' in the class notes). * * @param which indicates which particular join should be * examined; this should be 0 or 1 as described above. * @return a reference to the requested matching matrix. */ const NMatrix2& matchingReln(unsigned which) const; /** * Determines in a fairly ad-hoc fashion whether this * representation of this space is "smaller" than the given * representation of the given space. * * The ordering imposed on graph manifolds is purely aesthetic * on the part of the author, and is subject to change in future * versions of Regina. It also depends upon the particular * representation, so that different representations of the same * space may be ordered differently. * * All that this routine really offers is a well-defined way of * ordering graph manifold representations. * * @param compare the representation with which this will be compared. * @return \c true if and only if this is "smaller" than the * given graph manifold representation. */ bool operator < (const NGraphTriple& compare) const; NAbelianGroup* getHomologyH1() const; bool isHyperbolic() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; private: /** * Uses (1,1) twists and other techniques to make the presentation * of this manifold more aesthetically pleasing. */ void reduce(); /** * Uses 180 degree rotation and/or (1,1) twists to make the * given pair of matching matrices more aesthetically pleasing. * * This routine is for internal use by reduce(). * * @param reln0 the first matching matrix in the pair to simplify. * @param reln1 the second matching matrix in the pair to simplify. */ static void reduceBasis(NMatrix2& reln0, NMatrix2& reln1); /** * Uses 180 degree rotation to make the given matching matrix * more aesthetically pleasing. * * This routine is for internal use by reduce(). * * @param reln the matching matrix to simplify. */ static void reduceSign(NMatrix2& reln); }; /*@}*/ // Inline functions for NGraphTriple inline NGraphTriple::NGraphTriple(NSFSpace* end0, NSFSpace* centre, NSFSpace* end1, const NMatrix2& matchingReln0, const NMatrix2& matchingReln1) { end_[0] = end0; centre_ = centre; end_[1] = end1; matchingReln_[0] = matchingReln0; matchingReln_[1] = matchingReln1; reduce(); } inline const NSFSpace& NGraphTriple::end(unsigned which) const { return *end_[which]; } inline const NSFSpace& NGraphTriple::centre() const { return *centre_; } inline const NMatrix2& NGraphTriple::matchingReln(unsigned which) const { return matchingReln_[which]; } inline bool NGraphTriple::isHyperbolic() const { return false; } } // namespace regina #endif regina-4.96/engine/manifold/nhandlebody.cpp000644 000765 000024 00000006574 12377776616 020703 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "algebra/nabeliangroup.h" #include "manifold/nhandlebody.h" namespace regina { NAbelianGroup* NHandlebody::getHomologyH1() const { NAbelianGroup* ans = new NAbelianGroup(); if (nHandles) ans->addRank(nHandles); return ans; } std::ostream& NHandlebody::writeName(std::ostream& out) const { if (nHandles == 0) out << "B3"; else if (nHandles == 1) { if (orientable) out << "B2 x S1"; else out << "B2 x~ S1"; } else { if (orientable) out << "Handle-Or(" << nHandles << ')'; else out << "Handle-Nor(" << nHandles << ')'; } return out; } std::ostream& NHandlebody::writeTeXName(std::ostream& out) const { if (nHandles == 0) out << "B^3"; else if (nHandles == 1) { if (orientable) out << "B^2 \\times S^1"; else out << "B^2 \\twisted S^1"; } else { if (orientable) out << "\\mathit{Handle-Or}(" << nHandles << ')'; else out << "\\mathit{Handle-Nor}(" << nHandles << ')'; } return out; } } // namespace regina regina-4.96/engine/manifold/nhandlebody.h000644 000765 000024 00000012660 12377775236 020336 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file manifold/nhandlebody.h * \brief Deals with arbitrary handlebodies. */ #ifndef __NHANDLEBODY_H #ifndef __DOXYGEN #define __NHANDLEBODY_H #endif #include "regina-core.h" #include "nmanifold.h" namespace regina { /** * \weakgroup manifold * @{ */ /** * Represents an arbitrary handlebody. * * All optional NManifold routines except for NManifold::construct() are * implemented for this class. */ class REGINA_API NHandlebody : public NManifold { private: unsigned long nHandles; /**< The number of handles. */ bool orientable; /**< Is the handlebody orientable? */ public: /** * Creates a new handlebody with the given parameters. * * @param newHandles the number of handles of the handlebody. * @param newOrientable \c true if the handlebody is to be orientable * or \c false if the handlebody is to be non-orientable. This * must be \c true if the handlebody has no handles. */ NHandlebody(unsigned long newHandles, bool newOrientable); /** * Creates a clone of the given handlebody. * * @param cloneMe the handlebody to clone. */ NHandlebody(const NHandlebody& cloneMe); /** * Destroys this handlebody. */ virtual ~NHandlebody(); /** * Returns the number of handles of this handlebody. * * @return the number of handles. */ unsigned long getHandles() const; /** * Returns whether this handlebody is orientable. * * @return \c true if this handlebody is orientable, or \c false * if this handlebody is non-orientable. */ bool isOrientable() const; /** * Determines whether this and the given handlebody represent * the same 3-manifold. * * @param compare the handlebody with which this will be compared. * @return \c true if and only if this and the given handlebody * are homeomorphic. */ bool operator == (const NHandlebody& compare) const; NAbelianGroup* getHomologyH1() const; bool isHyperbolic() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; }; /*@}*/ // Inline functions for NHandlebody inline NHandlebody::NHandlebody(unsigned long newHandles, bool newOrientable) : nHandles(newHandles), orientable(newOrientable) { } inline NHandlebody::NHandlebody(const NHandlebody& cloneMe) : NManifold(), nHandles(cloneMe.nHandles), orientable(cloneMe.orientable) { } inline NHandlebody::~NHandlebody() { } inline unsigned long NHandlebody::getHandles() const { return nHandles; } inline bool NHandlebody::isOrientable() const { return orientable; } inline bool NHandlebody::operator == (const NHandlebody& compare) const { if (orientable && ! compare.orientable) return false; if (compare.orientable && ! orientable) return false; return (nHandles == compare.nHandles); } inline bool NHandlebody::isHyperbolic() const { return false; } } // namespace regina #endif regina-4.96/engine/manifold/nlensspace.cpp000644 000765 000024 00000007331 12377776617 020540 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "algebra/nabeliangroup.h" #include "manifold/nlensspace.h" #include "maths/numbertheory.h" #include "triangulation/ntriangulation.h" namespace regina { void NLensSpace::reduce() { if (p == 0) { q = 1; return; } else if (p == 1) { q = 0; return; } // p > 1 and gcd(p,q) = 1. // Reduce q to +/-q. q = q % p; if (2 * q > p) q = p - q; unsigned long inv = modularInverse(p, q); if (2 * inv > p) inv = p - inv; if (inv < q) q = inv; } NTriangulation* NLensSpace::construct() const { NTriangulation* ans = new NTriangulation(); ans->insertLayeredLensSpace(p, q); return ans; } NAbelianGroup* NLensSpace::getHomologyH1() const { NAbelianGroup* ans = new NAbelianGroup(); if (p == 0) ans->addRank(); else if (p > 1) ans->addTorsionElement(p); return ans; } std::ostream& NLensSpace::writeName(std::ostream& out) const { if (p == 0) out << "S2 x S1"; else if (p == 1) out << "S3"; else if (p == 2 && q == 1) out << "RP3"; else out << "L(" << p << ',' << q << ')'; return out; } std::ostream& NLensSpace::writeTeXName(std::ostream& out) const { if (p == 0) out << "S^2 \\times S^1"; else if (p == 1) out << "S^3"; else if (p == 2 && q == 1) out << "\\mathbb{R}P^3"; else out << "L(" << p << ',' << q << ')'; return out; } } // namespace regina regina-4.96/engine/manifold/nlensspace.h000644 000765 000024 00000014542 12377775240 020176 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file manifold/nlensspace.h * \brief Deals with general lens spaces. */ #ifndef __NLENSSPACE_H #ifndef __DOXYGEN #define __NLENSSPACE_H #endif #include "regina-core.h" #include "nmanifold.h" namespace regina { /** * \weakgroup manifold * @{ */ /** * Represents a general lens space. * * The lens space L(\a p,\a q) is the 3-manifold you get by * \a p/q Dehn surgery on the unknot. For instance, L(1,0) and L(1,1) * are the 3-sphere, L(0,1) is the product S^1 x S^2, and L(\a p,1) is the * circle bundle over S^2 with Euler class \a p. In L(\a p,\a q) if you * take a generator \a g of H_1 and evaluate the torsion linking form on it, * then <\a g,\a g> = [+/- \a r^2 \a q/\a p] in Q/Z where \a r is an * integer. * * All optional NManifold routines are implemented for this class. */ class REGINA_API NLensSpace : public NManifold { private: unsigned long p; /**< The first parameter of the lens space. */ unsigned long q; /**< The second parameter of the lens space. This will always be stored in reduced form. */ public: /** * Creates a new lens space with the given parameters. * See the class notes for details. * * \pre The two given parameters are coprime (have a gcd of 1). * * @param newP the first parameter \a p of the lens space L(p,q). * @param newQ the second parameter \a q of the lens space L(p,q). * Note that there are no range restrictions whatsoever on this * parameter. */ NLensSpace(unsigned long newP, unsigned long newQ); /** * Creates a clone of the given lens space. * * @param cloneMe the lens space to clone. */ NLensSpace(const NLensSpace& cloneMe); /** * Destroys this lens space. */ virtual ~NLensSpace(); /** * Returns the first parameter \a p of this lens space L(p,q). * See the class notes for details. * * @return the first parameter. */ unsigned long getP() const; /** * Returns the second parameter \a q of this lens space L(p,q). * See the class notes for details. * * The value of \a q returned will be the smallest \a q between * 0 and p-1 inclusive that produces the same 3-manifold * as this lens space. This means it might not be the value of \a q * that was used to initialise this lens space. */ unsigned long getQ() const; /** * Determines whether this and the given lens space are * homeomorphic 3-manifolds. Note that this may be true * even if they were initialised with different parameters. * * @param compare the lens space with which this will be compared. * @return \c true if and only if this and the given lens space * are homeomorphic. */ bool operator == (const NLensSpace& compare) const; NTriangulation* construct() const; NAbelianGroup* getHomologyH1() const; bool isHyperbolic() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; private: /** * Reduces the second parameter \a q to the smallest non-negative * value that gives the same (i.e., a homeomorphic) 3-manifold. */ void reduce(); }; /*@}*/ // Inline functions for NLensSpace inline NLensSpace::NLensSpace(unsigned long newP, unsigned long newQ) : p(newP), q(newQ) { reduce(); } inline NLensSpace::NLensSpace(const NLensSpace& cloneMe) : NManifold(), p(cloneMe.p), q(cloneMe.q) { } inline NLensSpace::~NLensSpace() { } inline unsigned long NLensSpace::getP() const { return p; } inline unsigned long NLensSpace::getQ() const { return q; } inline bool NLensSpace::operator == (const NLensSpace& compare) const { return (p == compare.p && q == compare.q); } inline bool NLensSpace::isHyperbolic() const { return false; } } // namespace regina #endif regina-4.96/engine/manifold/nmanifold.cpp000644 000765 000024 00000005300 12377776617 020346 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "manifold/nmanifold.h" namespace regina { std::string NManifold::getName() const { std::ostringstream ans; writeName(ans); return ans.str(); } std::string NManifold::getTeXName() const { std::ostringstream ans; writeTeXName(ans); return ans.str(); } std::string NManifold::getStructure() const { std::ostringstream ans; writeStructure(ans); return ans.str(); } } // namespace regina regina-4.96/engine/manifold/nmanifold.h000644 000765 000024 00000024251 12377775241 020011 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file manifold/nmanifold.h * \brief Deals with the underlying 3-manifolds of triangulations. */ #ifndef __NMANIFOLD_H #ifndef __DOXYGEN #define __NMANIFOLD_H #endif #include "regina-core.h" #include "shareableobject.h" namespace regina { class NAbelianGroup; class NTriangulation; /** * \addtogroup manifold Standard 3-Manifolds * Standard 3-manifolds whose structures are well-understood. * @{ */ /** * Represents a particular 3-manifold. The triangulation of this * 3-manifold that may be in use is not of interest. * * Subclasses corresponding to the different types of 3-manifold must * (of course) override all pure virtual functions. * They do not need to override writeTextShort() or writeTextLong() * since these routines are properly implemented in the base class * NManifold. */ class REGINA_API NManifold : public ShareableObject { public: /** * A destructor that does nothing. */ virtual ~NManifold(); /** * Returns the common name of this 3-manifold as a * human-readable string. * * @return the common name of this 3-manifold. */ std::string getName() const; /** * Returns the common name of this 3-manifold in TeX format. * No leading or trailing dollar signs will be included. * * \warning The behaviour of this routine has changed as of * Regina 4.3; in earlier versions, leading and trailing dollar * signs were provided. * * @return the common name of this 3-manifold in TeX format. */ std::string getTeXName() const; /** * Returns details of the structure of this 3-manifold that * might not be evident from its common name. For instance, for * an orbit space S^3/G this routine might return the full * Seifert structure. * * This routine may return the empty string if no additional * details are deemed necessary. * * @return a string describing additional structural details. */ std::string getStructure() const; /** * Returns a triangulation of this 3-manifold, if such a * construction has been implemented. If no construction routine * has yet been implemented for this 3-manifold (for instance, * if this 3-manifold is a Seifert fibred space with * sufficiently many exceptional fibres) then this routine will * return 0. * * The details of which 3-manifolds have construction routines * can be found in the notes for the corresponding subclasses of * NManifold. The default implemention of this routine returns 0. * * @return a triangulation of this 3-manifold, or 0 if the * appropriate construction routine has not yet been implemented. */ virtual NTriangulation* construct() const; /** * Returns the first homology group of this 3-manifold, if such * a routine has been implemented. If the calculation of * homology has not yet been implemented for this 3-manifold * then this routine will return 0. * * The details of which 3-manifolds have homology calculation routines * can be found in the notes for the corresponding subclasses of * NManifold. The default implemention of this routine returns 0. * * The homology group will be newly allocated and must be destroyed * by the caller of this routine. * * @return the first homology group of this 3-manifold, or 0 if * the appropriate calculation routine has not yet been implemented. */ virtual NAbelianGroup* getHomologyH1() const; /** * Returns whether or not this is a finite-volume hyperbolic manifold. * * @return \c true if this is a finite-volume hyperbolic * manifold, or \c false if not. */ virtual bool isHyperbolic() const = 0; /** * Determines in a fairly ad-hoc fashion whether this representation * of this 3-manifold is "smaller" than the given representation * of the given 3-manifold. * * The ordering imposed on 3-manifolds is purely aesthetic on * the part of the author, and is subject to change in future * versions of Regina. * * The ordering also depends on the particular representation of * the 3-manifold that is used. As an example, different * representations of the same Seifert fibred space might well * be ordered differently. * * All that this routine really offers is a well-defined way of * ordering 3-manifold representations. * * \warning Currently this routine is only implemented in full for * closed 3-manifolds. For most classes of bounded 3-manifolds, * this routine simply compares the strings returned by getName(). * * @param compare the 3-manifold representation with which this * will be compared. * @return \c true if and only if this is "smaller" than the * given 3-manifold representation. */ bool operator < (const NManifold& compare) const; /** * Writes the common name of this 3-manifold as a * human-readable string to the given output stream. * * \ifacespython The parameter \a out does not exist; * standard output will be used. * * @param out the output stream to which to write. * @return a reference to the given output stream. */ virtual std::ostream& writeName(std::ostream& out) const = 0; /** * Writes the common name of this 3-manifold in TeX format to * the given output stream. No leading or trailing dollar signs * will be included. * * \warning The behaviour of this routine has changed as of * Regina 4.3; in earlier versions, leading and trailing dollar * signs were provided. * * \ifacespython The parameter \a out does not exist; * standard output will be used. * * @param out the output stream to which to write. * @return a reference to the given output stream. */ virtual std::ostream& writeTeXName(std::ostream& out) const = 0; /** * Writes details of the structure of this 3-manifold that * might not be evident from its common name to the given output * stream. For instance, for an orbit space S^3/G this routine * might write the full Seifert structure. * * This routine may write nothing if no additional * details are deemed necessary. The default implementation of * this routine behaves in this way. * * \ifacespython The parameter \a out does not exist; * standard output will be used. * * @param out the output stream to which to write. * @return a reference to the given output stream. */ virtual std::ostream& writeStructure(std::ostream& out) const; virtual void writeTextShort(std::ostream& out) const; virtual void writeTextLong(std::ostream& out) const; }; /*@}*/ // Inline functions for NManifold inline NManifold::~NManifold() { } inline NTriangulation* NManifold::construct() const { return 0; } inline NAbelianGroup* NManifold::getHomologyH1() const { return 0; } inline std::ostream& NManifold::writeStructure(std::ostream& out) const { return out; } inline void NManifold::writeTextShort(std::ostream& out) const { writeName(out); } inline void NManifold::writeTextLong(std::ostream& out) const { writeName(out); std::string details = getStructure(); if (! details.empty()) out << " ( " << details << " )"; } } // namespace regina #endif regina-4.96/engine/manifold/notation.h000644 000765 000024 00000011127 12377775243 017675 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file manifold/notation.h * \brief Explains notation used for describing various types of 3-manifold. */ /*! \page sfsnotation Notation for Seifert fibred spaces * * Consider a Seifert fibred space over some base orbifold, containing * one or more exceptional fibres and optionally one or more boundary * components. Here we describe the notation used for the exceptional * fibres, as well as their relationship to curves on the boundary * components. * * Consider the illustration below. Here the base orbifold is * an annulus, with boundary components at the top and bottom of the * diagram. The two circles in the middle correspond to two * exceptional fibres. * * \image html sfsnotation.png * * The boundary curves \a o1 and \a o2, as well as the curves \a e1 and * \a e2 bounding the exceptional fibres, can be given consistent * orientations as illustrated by the arrows. The fibres can also be * consistently oriented; let them be parallel copies of some curve \a f. * * Suppose that we describe the space as having exceptional fibres * with parameters (\a p1, \a q1) and (\a p2, \a q2). This corresponds * to removing all fibres inside curves \a e1 and \a e2, and filling * the resulting boundaries with solid tori whose meridinal curves are * (\a p1 * \a e1 + \a q1 * \a f) and (\a p2 * \a e2 + \a q2 * \a f). * * An obstruction constant of \a b is treated as an additional * exceptional fibre with parameters (1, \a b) according to the * description above. * * Where necessary, we use the oriented curves \a o1 and \a o2 as * curves on the boundaries "representing the base orbifold", * and parallel copies of \a f as curves on the boundaries * "representing the fibres". This becomes particularly * important when joining different boundary components together. * * It is worth noting the following observation. Suppose we have a * Seifert fibred space with boundary, and let one of its * boundary components have oriented curves (\a f, \a o) representing the * fibres and base orbifold respectively. Then exactly the same space can * be written with an additional (1,1) fibre (i.e., the obstruction * constant \a b is incremented by one), with the effect that the * curves on that boundary representing the fibres and base orbifold * become (\a f, \a o + \a f) instead. */ regina-4.96/engine/manifold/nsfs.cpp000644 000765 000024 00000127776 12377776620 017370 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include #include "algebra/nabeliangroup.h" #include "manifold/nlensspace.h" #include "manifold/nsfs.h" #include "maths/nmatrixint.h" #include "maths/numbertheory.h" #include "subcomplex/nsatannulus.h" #include "triangulation/ntriangulation.h" #include "utilities/boostutils.h" namespace regina { namespace { /** * Some small exceptional fibres that we will use for comparisons. */ NSFSFibre two(2, 1); NSFSFibre three(3, 1); NSFSFibre threeB(3, 2); NSFSFibre four(4, 1); } typedef std::list::iterator FibreIterator; typedef std::list::const_iterator FibreIteratorConst; std::ostream& operator << (std::ostream& out, const NSFSFibre& f) { return (out << '(' << f.alpha << ',' << f.beta << ')'); } void NSFSpace::operator = (const NSFSpace& cloneMe) { class_ = cloneMe.class_; genus_ = cloneMe.genus_; punctures_ = cloneMe.punctures_; puncturesTwisted_ = cloneMe.puncturesTwisted_; reflectors_ = cloneMe.reflectors_; reflectorsTwisted_ = cloneMe.reflectorsTwisted_; fibres_ = cloneMe.fibres_; nFibres_ = cloneMe.nFibres_; b_ = cloneMe.b_; } NSFSFibre NSFSpace::fibre(unsigned long which) const { FibreIteratorConst pos = fibres_.begin(); advance(pos, which); return *pos; } void NSFSpace::addHandle(bool fibreReversing) { // First fix the class. // The transitions between classes have been worked out on paper // case by case (in particular, following how the generators of the // handle relate to the new crosscap generators in the non-orientable // case). // Recall also that in the orientable case we can convert +/- to -/-, // and in the non-orientable case we can convert +/+/+/- to +/-/-/- // (where + and - correspond to fibre-preserving and fibre-reversing // generators respectively). See Orlik [1972], p89 for details. if (fibreReversing) { // Fibre-reversing. switch (class_) { case o1: class_ = o2; break; case n1: class_ = (genus_ % 2 == 0 ? n4 : n3); break; case n2: class_ = n4; break; case bo1: class_ = bo2; break; case bn1: case bn2: class_ = bn3; break; default: // No change. break; } } else { // Fibre-preserving. // Never changes the class. } // Finally increment the genus (either orientable or non-orientable). if (baseOrientable()) genus_++; else genus_ += 2; } void NSFSpace::addCrosscap(bool fibreReversing) { // We're making the base orbifold non-orientable. // Convert orientable genus to non-orientable genus if required. if (baseOrientable()) genus_ *= 2; // Now fix the class. // The transitions between classes have been worked out on paper // case by case (in particular, following how the generators of the // original handles relate to the reformulated crosscap generators in // the orientable case). // Recall also that in the orientable case we can convert +/- to -/-, // and in the non-orientable case we can convert +/+/+/- to +/-/-/- // (where + and - correspond to fibre-preserving and fibre-reversing // generators respectively). See Orlik [1972], p89 for details. if (fibreReversing) { // Fibre-reversing. switch(class_) { case o1: class_ = n2; break; case o2: class_ = n4; break; case n1: class_ = (genus_ % 2 == 0 ? n4 : n3); break; case bo1: class_ = bn2; break; case bo2: case bn1: class_ = bn3; break; default: // No change. break; } } else { // Fibre-preserving. switch(class_) { case o1: class_ = n1; break; case o2: case n2: case n4: class_ = n3; break; case n3: class_ = n4; break; case bo1: class_ = bn1; break; case bo2: case bn2: class_ = bn3; break; default: // No change. break; } } // Finally increment the genus. // We always have non-orientable genus here. genus_++; } void NSFSpace::addPuncture(bool twisted, unsigned long nPunctures) { if (twisted) { puncturesTwisted_ += nPunctures; if (baseOrientable()) class_ = bo2; else class_ = bn3; } else { punctures_ += nPunctures; switch(class_) { case o1: class_ = bo1; break; case o2: class_ = bo2; break; case n1: class_ = bn1; break; case n2: class_ = bn2; break; case n3: case n4: class_ = bn3; break; default: // No change. break; } } } void NSFSpace::addReflector(bool twisted, unsigned long nReflectors) { if (twisted) { reflectorsTwisted_ += nReflectors; if (baseOrientable()) class_ = bo2; else class_ = bn3; } else { reflectors_ += nReflectors; switch(class_) { case o1: class_ = bo1; break; case o2: class_ = bo2; break; case n1: class_ = bn1; break; case n2: class_ = bn2; break; case n3: case n4: class_ = bn3; break; default: // No change. break; } } } void NSFSpace::insertFibre(long alpha, long beta) { // We are assuming that the parameters of this fibre are coprime and // that alpha is strictly positive. // Sanity check. if (alpha == 0) { // TODO: We should probably throw an exception here or something. std::cerr << "ERROR: Inserting illegal fibre (0," << beta << ")." << std::endl; return; } // Is it a regular fibre? if (alpha == 1) { b_ += beta; return; } // Put the fibre in standard form. b_ += (beta / alpha); beta = beta % alpha; if (beta < 0) { beta += alpha; b_--; } // Now we have 0 <= beta < alpha and alpha >= 2. nFibres_++; NSFSFibre f(alpha, beta); fibres_.insert(lower_bound(fibres_.begin(), fibres_.end(), f), f); // We're done! } void NSFSpace::reduce(bool mayReflect) { FibreIterator it, it2; // If the SFS is non-orientable, we can get rid of b completely and // convert most (if not all) exceptional fibres to beta <= alpha / 2. if (reflectors_ || reflectorsTwisted_) { // (1,1) == (1,0). b_ = 0; } else if (fibreNegating() && b_) { // (p,q) == (p,-q), and so (1,2) == (1,0). b_ = b_ % 2; if (b_ && nFibres_) { // We have b == +/-1. // Merge this into the first exceptional fibre instead. // Instead of modifying the fibre directly, delete and reinsert // so that sorted order is maintained. NSFSFibre f(fibres_.front().alpha, fibres_.front().alpha - fibres_.front().beta); fibres_.pop_front(); // Rather than doing a binary search, just hunt from the // front (since we haven't changed alpha, so the fibre will // generally stay near the front). it = fibres_.begin(); while (it != fibres_.end() && (*it) < f) it++; fibres_.insert(it, f); b_ = 0; } } // Completely finish off the case with no exceptional fibres. if (! nFibres_) { // Not much more we can do. // Just reflect if it helps. if (mayReflect && b_ < 0) b_ = -b_; return; } // FACT: There is at least one fibre. // Normalise them as best we can. if (fibreNegating()) { // (p,q) == (p,-q) == (1,1) (p,p-q) == (1,-1) (p,p-q). // We can therefore reduce fibres with large beta in pairs. // Except for the following cases, where we can simply reduce // all of them. if (reflectors_ || reflectorsTwisted_ || fibres_.front().alpha == 2) { // (1,1) == (1,0) if we have reflectors, and // (1,1) (2,1) == (1,2) (2,-1) == (2,1) if we have some alpha = 2. // So we can reduce _all_ fibres with large beta. it = fibres_.begin(); while (it != fibres_.end()) if (it->beta * 2 > it->alpha) it = negateFibreDown(it); else it++; } else { // We have to do them in pairs. // A place to store the first of a pair while we look for // the second: it2 = fibres_.end(); it = fibres_.begin(); while (it != fibres_.end()) { if (it->beta * 2 > it->alpha) { // This one's worth reducing. if (it2 == fibres_.end()) { // First in a pair. // Remember it and move on. it2 = it++; } else { // Second in a pair. // Process them both (first then last, so we // don't mess up the sequence of iterators in // the loop). negateFibreDown(it2); it = negateFibreDown(it); it2 = fibres_.end(); } } else it++; } // Was there anything left over? If so, pair it with the // final fibre (which will get larger, not smaller). if (it2 != fibres_.end()) { // It can be shown that, if we are already looking at // the final fibre, this code will do the right thing // (specifically, switch this with another fibre if this // will improve things, and switch this with itself if // it won't). negateFibreDown(it2); // No need to resort the final fibre, since it gets // larger anyway. fibres_.back().beta = fibres_.back().alpha - fibres_.back().beta; } } } else if (reflectors_ || reflectorsTwisted_) { // Individual fibres cannot be negated, but we have reflector // boundaries. // We still have the option of simultaneously replacing all (p,q) // with (p,-q) == (1,-1) (p,p-q) == (p,p-q) if it's worth it. if (mayReflect) { unsigned long nLarge = 0; unsigned long nSmall = 0; // Don't count (2,1) fibres, they don't get changed anyway. for (it = fibres_.begin(); it != fibres_.end() && it->alpha == 2; it++) ; // Remember where we really started. it2 = it; for ( ; it != fibres_.end(); it++) { if (it->beta * 2 > it->alpha) nLarge++; else nSmall++; } // So. Was it worth it? if (nLarge > nSmall) complementAllFibres(); else if (nLarge == nSmall && it2 != fibres_.end()) { // We need to look in a little more detail. FibreIterator next; bool shouldReflect = false; // Restore our starting position, and let it2 become a // temporary variable again. it = it2; while (it != fibres_.end()) { // INV: it points to the next block with the same // value of alpha. it2 = it; for (it2++; it2 != fibres_.end() && it2->alpha == it->alpha; it2++) ; // Now it2 points to the first element of the // following block. next = it2; it2--; // Now it2 points to the last element of this block. // If the block were negated, it would also be // reversed; see what would happen. while (it != next) { if (it2->alpha - it2->beta < it->beta) { shouldReflect = true; next = fibres_.end(); break; } else if (it2->alpha - it2->beta > it->beta) { shouldReflect = false; next = fibres_.end(); break; } // Still tied. it++; it2--; } // Move on to the next block. it = next; } if (shouldReflect) complementAllFibres(); } } } else { // Individual fibres cannot be negated, no reflector boundaries. // The best we can do is just reflect everything if b is far enough // negative. if (mayReflect) { if (b_ < (-b_ - static_cast(nFibres_))) { b_ = -b_ - static_cast(nFibres_); complementAllFibres(); } else if (b_ == (-b_ - static_cast(nFibres_))) { // Reflecting won't change b, but it will complement all // fibres. See whether this is worthwhile. FibreIterator next; bool shouldReflect = false; it = fibres_.begin(); while (it != fibres_.end()) { // INV: it points to the next block with the same // value of alpha. it2 = it; for (it2++; it2 != fibres_.end() && it2->alpha == it->alpha; it2++) ; // Now it2 points to the first element of the // following block. next = it2; it2--; // Now it2 points to the last element of this block. // If the block were negated, it would also be // reversed; see what would happen. while (it != next) { if (it2->alpha - it2->beta < it->beta) { shouldReflect = true; next = fibres_.end(); break; } else if (it2->alpha - it2->beta > it->beta) { shouldReflect = false; next = fibres_.end(); break; } // Still tied. it++; it2--; } // Move on to the next block. it = next; } if (shouldReflect) complementAllFibres(); } } } } std::list::iterator NSFSpace::negateFibreDown( std::list::iterator it) { // The replacement fibre. NSFSFibre f(it->alpha, it->alpha - it->beta); // The return value. This is also a strict upper bound for the // location of the replacement fibre. std::list::iterator next = it; next++; // Delete the old iterator. fibres_.erase(it); // Insert the new. Treat front insertion specially, so we don't // find ourselves doing an it-- past the beginning. if (fibres_.empty() || f < fibres_.front()) { fibres_.push_front(f); return next; } // It's not a front insertion. Find the insertion place. // Note that this loop is guaranteed at least one iteration. for (it = next; it == fibres_.end() || f < *it; it--) ; // We have the first instance of *it <= f. // This means the insertion should take place immediately after it. it++; fibres_.insert(it, f); return next; } void NSFSpace::complementAllFibres() { FibreIterator it, it2, next; for (it = fibres_.begin(); it != fibres_.end(); it++) it->beta = it->alpha - it->beta; // Ensure that the array remains in sorted order. // Each portion of the array with fixed index must be reversed. NSFSFibre tmpFibre; it = fibres_.begin(); while (it != fibres_.end()) { // INV: it points to the next block to be reversed. it2 = it; for (it2++; it2 != fibres_.end() && (*it2).alpha == (*it).alpha; it2++) ; // Now it2 points to the first element of the following block. next = it2; it2--; // Now it2 points to the last element of this block. // Reverse this block by swapping elements at each end and // working towards the centre. while (it != it2) { tmpFibre = (*it); (*it) = (*it2); (*it2) = tmpFibre; it++; if (it == it2) break; it2--; } // Move on to the next block. it = next; } } NLensSpace* NSFSpace::isLensSpace() const { if (punctures_ || puncturesTwisted_ || reflectors_ || reflectorsTwisted_) { // Not a chance. return 0; } if (genus_ == 0 && class_ == o1) { // Base orbifold is the sphere. if (fibres_.empty()) return new NLensSpace(b_ >= 0 ? b_ : -b_, 1); else if (nFibres_ == 1) { long q = fibres_.front().alpha; long p = fibres_.front().beta + (b_ * q); // We have SFS [S2 : (q,p)]. return new NLensSpace(p >= 0 ? p : -p, q >= 0 ? q : -q); } else if (nFibres_ == 2) { // Precisely two fibres. long q = fibres_.back().alpha; long p = fibres_.back().beta + (b_ * q); long x = fibres_.front().alpha; long y = fibres_.front().beta; // INV: We have SFS [S2 : (x,y) (q,p)] with 0 <= y < x. while (y > 0) { x = x - y; q = q + p; if (y >= x) { p += (q * (y / x)); y = y % x; } } // We should now have (x,y) == (1,0). return new NLensSpace(p >= 0 ? p : -p, q >= 0 ? q : -q); } // Not a lens space. return 0; } else if (genus_ == 1 && class_ == n2) { // Base orbifold is the projective plane. if (nFibres_ == 1) { // We have precisely one exceptional fibre. long a = fibres_.front().alpha; long n = b_ * a + fibres_.front().beta; if (n == 1 || n == -1) return new NLensSpace(4 * a, 2 * a - 1); } // Not a lens space. return 0; } return 0; } bool NSFSpace::operator == (const NSFSpace& compare) const { if (class_ != compare.class_) return false; if (genus_ != compare.genus_) return false; if (punctures_ != compare.punctures_) return false; if (puncturesTwisted_ != compare.puncturesTwisted_) return false; if (reflectors_ != compare.reflectors_) return false; if (reflectorsTwisted_ != compare.reflectorsTwisted_) return false; if (nFibres_ != compare.nFibres_) return false; if (! (fibres_ == compare.fibres_)) return false; if (b_ != compare.b_) return false; // Exactly the same! return true; } bool NSFSpace::operator < (const NSFSpace& compare) const { // Double the genus if it's orientable, so that we can line up tori // with Klein bottles, etc. unsigned long adjGenus1 = (baseOrientable() ? genus_ * 2 : genus_); unsigned long adjGenus2 = (compare.baseOrientable() ? compare.genus_ * 2 : compare.genus_); // Too many punctures is worse than anything. if (punctures_ + puncturesTwisted_ < compare.punctures_ + compare.puncturesTwisted_) return true; if (punctures_ + puncturesTwisted_ > compare.punctures_ + compare.puncturesTwisted_) return false; // After this, order by a combination of genus and reflectors to // group closed spaces with approximately the same complexity. if (adjGenus1 + reflectors_ + reflectorsTwisted_ < adjGenus2 + compare.reflectors_ + compare.reflectorsTwisted_) return true; if (adjGenus1 + reflectors_ + reflectorsTwisted_ > adjGenus2 + compare.reflectors_ + compare.reflectorsTwisted_) return false; // Within this genus + reflectors combination, reflectors are worse. if (reflectors_ + reflectorsTwisted_ < compare.reflectors_ + compare.reflectorsTwisted_) return true; if (reflectors_ + reflectorsTwisted_ > compare.reflectors_ + compare.reflectorsTwisted_) return false; // If we reach this point, we must have adjGenus1 == adjGenus2. // Down to more mundane comparisons. // Comparing class will catch orientability also (placing orientable // before non-orientable). if (class_ < compare.class_) return true; if (class_ > compare.class_) return false; if (reflectorsTwisted_ < compare.reflectorsTwisted_) return true; if (reflectorsTwisted_ > compare.reflectorsTwisted_) return false; if (puncturesTwisted_ < compare.puncturesTwisted_) return true; if (puncturesTwisted_ > compare.puncturesTwisted_) return false; if (nFibres_ < compare.nFibres_) return true; if (nFibres_ > compare.nFibres_) return false; if (fibres_ < compare.fibres_) return true; if (compare.fibres_ < fibres_) return false; if (b_ < compare.b_) return true; if (b_ > compare.b_) return false; // Exactly the same! return false; } NTriangulation* NSFSpace::construct() const { // Things that we don't deal with just yet. if (punctures_ || puncturesTwisted_ || reflectors_ || reflectorsTwisted_) return 0; // We already know how to construct lens spaces. NLensSpace* lens = isLensSpace(); if (lens) { NTriangulation* t = lens->construct(); delete lens; return t; } // Currently we work over the 2-sphere only. if (genus_ != 0 || class_ != o1) return 0; // Since we've already dealt with lens spaces, we must have at least // three exceptional fibres. Build a blocked structure. NTriangulation* ans = new NTriangulation(); NTetrahedron *a, *b, *c; // Begin with the first triangular solid torus. a = ans->newTetrahedron(); b = ans->newTetrahedron(); c = ans->newTetrahedron(); a->joinTo(1, b, NPerm4()); b->joinTo(2, c, NPerm4()); c->joinTo(3, a, NPerm4(1, 2, 3, 0)); std::list::const_iterator fit = fibres_.begin(); NSatAnnulus(a, NPerm4(1, 0, 2, 3), b, NPerm4(1, 2, 0, 3)). attachLST(ans, fit->alpha, fit->beta); fit++; NSatAnnulus(b, NPerm4(2, 1, 3, 0), c, NPerm4(2, 3, 1, 0)). attachLST(ans, fit->alpha, fit->beta); fit++; // Run through the rest of the fibres, one at a time. Each extra // fibre (aside from the third) will require another triangular // solid torus. NTetrahedron* prevA = a; NTetrahedron* prevC = c; NSFSFibre nextFibre = *fit++; while (fit != fibres_.end()) { a = ans->newTetrahedron(); b = ans->newTetrahedron(); c = ans->newTetrahedron(); a->joinTo(3, prevA, NPerm4(2, 3)); b->joinTo(3, prevC, NPerm4(0, 2, 3, 1)); a->joinTo(1, b, NPerm4()); b->joinTo(2, c, NPerm4()); c->joinTo(3, a, NPerm4(1, 2, 3, 0)); NSatAnnulus(b, NPerm4(2, 1, 3, 0), c, NPerm4(2, 3, 1, 0)). attachLST(ans, nextFibre.alpha, nextFibre.beta); prevA = a; prevC = c; nextFibre = *fit++; } // We have one remaining fibre. Fill in the final annulus of the // last triangular solid torus. NSatAnnulus(a, NPerm4(1, 0, 3, 2), c, NPerm4(2, 3, 0, 1)).attachLST(ans, nextFibre.alpha, -(nextFibre.beta + b_ * nextFibre.alpha)); return ans; } NAbelianGroup* NSFSpace::getHomologyH1() const { if (punctures_ || puncturesTwisted_) { // Not just now. return 0; } // Construct the presentation of the fundamental group and // abelianise. The presentation without reflectors is given on // p91 of Orlik [1972]. Each reflector gives additional generators // y and z, for which y acts as a boundary component and z^2 = fibre. NAbelianGroup* ans = new NAbelianGroup(); unsigned long nRef = reflectors_ + reflectorsTwisted_; bool twisted = fibreReversing(); if (baseOrientable()) { // Orientable base surface. // Generators: a_1, b_1, ..., a_g, b_g, q_1, q_2, ..., q_r, h, // y_1, z_1, ..., y_t, z_t (for reflectors) // Relations: // q_j^alpha_j h^beta_j = 1 // z_j^2 = h // q_1 ... q_r y_1 ... y_t = h^b // h^2 = 1 (if twisted), or h = 1 (if twisted reflectors) // // We ignore a_i and b_i, and just add extra rank 2g at the end. // Generators in the matrix are q_1, ..., q_r, h, z_1, ..., z_t, // y_1, ..., y_t. NMatrixInt pres(nFibres_ + nRef + (twisted ? 2 : 1), nFibres_ + 1 + 2 * nRef); unsigned long which = 0; for (FibreIteratorConst it = fibres_.begin(); it != fibres_.end(); it++) { pres.entry(nFibres_ + nRef, which) = 1; pres.entry(which, nFibres_) = it->beta; pres.entry(which, which) = it->alpha; which++; } unsigned long ref; for (ref = 0; ref < nRef; ref++) { pres.entry(nFibres_ + ref, nFibres_) = -1; pres.entry(nFibres_ + ref, nFibres_ + 1 + ref) = 2; pres.entry(nFibres_ + nRef, nFibres_ + 1 + nRef + ref) = 1; } pres.entry(nFibres_ + nRef, nFibres_) = -b_; if (reflectorsTwisted_) pres.entry(nFibres_ + nRef + 1, nFibres_) = 1; else if (twisted) pres.entry(nFibres_ + nRef + 1, nFibres_) = 2; ans->addGroup(pres); ans->addRank(2 * genus_); } else { // Non-orientable base surface. // Generators: v_1, v_2, ..., v_g, q_1, q_2, ..., q_r, h, // y_1, z_1, ..., y_t, z_t (for reflectors) // Relations: // q_j^alpha_j h^beta_j = 1 // z_j^2 = h // q_1 ... q_r v_1^2 ... v_g^2 y_1 ... y_t = h^b // h^2 = 1 (if twisted), or h = 1 (if twisted reflectors) // // Generators in the matrix are q_1, ..., q_r, v_1, ..., v_g, h, // z_1, ..., z_t, y_1, ..., y_t. NMatrixInt pres(nFibres_ + nRef + (twisted ? 2 : 1), nFibres_ + genus_ + 1 + 2 * nRef); unsigned long which = 0; for (FibreIteratorConst it = fibres_.begin(); it != fibres_.end(); it++) { pres.entry(nFibres_ + nRef, which) = 1; pres.entry(which, nFibres_ + genus_) = it->beta; pres.entry(which, which) = it->alpha; which++; } unsigned long ref; for (ref = 0; ref < nRef; ref++) { pres.entry(nFibres_ + ref, nFibres_ + genus_) = -1; pres.entry(nFibres_ + ref, nFibres_ + genus_ + 1 + ref) = 2; pres.entry(nFibres_ + nRef, nFibres_ + genus_ + 1 + nRef + ref) = 1; } for (which = 0; which < genus_; which++) pres.entry(nFibres_ + nRef, nFibres_ + which) = 2; pres.entry(nFibres_ + nRef, nFibres_ + genus_) = -b_; if (reflectorsTwisted_) pres.entry(nFibres_ + nRef + 1, nFibres_ + genus_) = 1; else if (twisted) pres.entry(nFibres_ + nRef + 1, nFibres_ + genus_) = 2; ans->addGroup(pres); } return ans; } void NSFSpace::writeBaseExtraCount(std::ostream& out, unsigned long count, const char* object, bool tex) { out << " + " << count << (tex ? "\\ \\mbox{" : " ") << object; if (count != 1) out << 's'; if (tex) out << '}'; } std::ostream& NSFSpace::writeCommonBase(std::ostream& out, bool tex) const { bool named = false; // IMPORTANT: We do not allow spaces with > 2 reflector boundary // components to be named. Otherwise this messes up the reflector // boundary output. unsigned long totRef = reflectors_ + reflectorsTwisted_; unsigned long totBdries = totRef + punctures_ + puncturesTwisted_; if (baseOrientable()) { // Orientable base surface. if (genus_ == 0 && totBdries == 0) { out << (tex ? "S^2" : "S2"); named = true; } else if (genus_ == 0 && totBdries == 1) { if (totRef && tex) out << "\\overline{"; out << 'D'; if (totRef) out << (tex ? '}' : '_'); named = true; } else if (genus_ == 0 && totBdries == 2) { if (totRef == 1 && tex) out << "\\overline{"; else if (totRef == 2 && tex) out << "\\overline{\\overline{"; out << 'A'; if (totRef == 1) out << (tex ? '}' : '_'); else if (totRef == 2) out << (tex ? "}}" : "="); named = true; } else if (genus_ == 1 && totBdries == 0) { out << (tex ? "T^2" : "T"); named = true; } } else { // Non-orientable base surface. if (genus_ == 1 && totBdries == 0) { out << (tex ? "\\mathbb{R}P^2" : "RP2"); named = true; } else if (genus_ == 1 && totBdries == 1) { if (totRef && tex) out << "\\overline{"; out << 'M'; if (totRef) out << (tex ? '}' : '_'); named = true; } else if (genus_ == 2 && totBdries == 0) { out << (tex ? "K^2" : "KB"); named = true; } } if (! named) { if (baseOrientable()) out << (tex ? "\\mathrm{Or},\\ " : "Or, ") << "g=" << genus_; else out << (tex ? "\\mathrm{Non-or},\\ " : "Non-or, ") << "g=" << genus_; if (punctures_) writeBaseExtraCount(out, punctures_, "puncture", tex); if (puncturesTwisted_) writeBaseExtraCount(out, puncturesTwisted_, "twisted puncture", tex); if (reflectors_) writeBaseExtraCount(out, reflectors_, "reflector", tex); if (reflectorsTwisted_) writeBaseExtraCount(out, reflectorsTwisted_, "twisted reflector", tex); } if (class_ == o2 || class_ == bo2) out << (tex ? "/o_2" : "/o2"); else if (class_ == n2 || class_ == bn2) out << (tex ? "/n_2" : "/n2"); else if (class_ == n3 || class_ == bn3) out << (tex ? "/n_3" : "/n3"); else if (class_ == n4) out << (tex ? "/n_4" : "/n4"); return out; } std::ostream& NSFSpace::writeCommonStructure(std::ostream& out, bool tex) const { if (b_ == 0 && fibres_.empty()) { // We have a straightforward product (possibly twisted). writeCommonBase(out, tex); // The o1/o2/n1/n2/etc specification has already been written in // writeCommonBase(). Just do the pretty x S1 and get out. if (fibreReversing()) return out << (tex ? " \\twisted S^1" : " x~ S1"); else return out << (tex ? " \\times S^1" : " x S1"); } // We have at least one fibre, even if it's only (1,b). out << (tex ? "\\mathrm{SFS}\\left(" : "SFS ["); writeCommonBase(out, tex); out << ':'; if (fibres_.empty()) { // We have b non-zero. out << ' ' << NSFSFibre(1, b_); } else { out << ' '; copy(fibres_.begin(), --fibres_.end(), std::ostream_iterator(out, " ")); NSFSFibre final = fibres_.back(); final.beta += final.alpha * b_; out << final; } return out << (tex ? "\\right)" : "]"); } std::ostream& NSFSpace::writeCommonName(std::ostream& out, bool tex) const { // Things we don't deal with just yet. if (fibreNegating()) return writeStructure(out); if (reflectors_ || reflectorsTwisted_ || punctures_ || puncturesTwisted_) return writeStructure(out); // We're looking at an orientable SFS (with either orientable or // non-orientable base orbifold), where the base orbifold has no // punctures or reflector boundaries. // Take out the lens spaces first. NLensSpace* lens = isLensSpace(); if (lens) { if (tex) lens->writeTeXName(out); else lens->writeName(out); delete lens; return out; } // Pull off the number of fibres we're capable of dealing with. // At this moment this is four. if (nFibres_ > 4) return writeStructure(out); NSFSFibre fibre[4]; std::copy(fibres_.begin(), fibres_.end(), fibre); // Note that with three fibres our reduced form will always have // b >= -1. // TODO: The four non-orientable flat manifolds are on Orlik p140. // SFS over the 2-sphere: if (genus_ == 0 && class_ == o1) { if (nFibres_ == 4 && fibre[0] == two && fibre[1] == two && fibre[2] == two && fibre[3] == two && b_ == -2) { // [ S2 : (2,1), (2,1), (2,-1), (2,-1) ] // Orlik, p138, case M2. return out << (tex ? "K^2/n2 \\twisted S^1" : "KB/n2 x~ S1"); } else if (nFibres_ == 3 && fibre[0] == two && gcd(fibre[2].alpha, fibre[2].beta) == 1 && b_ >= -1) { // [ S2 : (2,1), (...), (...) ] if (fibre[1] == two) { // [ S2 : (2,1), (2,1), (a,b) ]. // Orlik, p112, case (ii). long a = fibre[2].alpha; long m = fibre[2].beta + a * (b_ + 1); // Note that a,m >= 0. if (gcd(m, 2 * a) == 1) { // S3/Q{4a} x Z{m}. if (tex) out << "S^3/Q_{" << (a * 4) << '}'; else out << "S3/Q" << (a * 4); if (m > 1) { if (tex) out << " \\times \\mathbb{Z}_{" << m << '}'; else out << " x Z" << m; } return out; } else if (m % 2 == 0) { // S3/D{2^{k+2}a} x Z{2m''+1} where m=2^k(2m''+1). // It seems Orlik is missing a factor of two here? // He uses m=2^{k+1}(2m''+1). long odd = m; long twos = 1; while (! (odd & 1)) { odd >>= 1; twos <<= 1; } if (tex) out << "S^3/D_{" << ((twos << 2) * a) << '}'; else out << "S3/D" << ((twos << 2) * a); if (odd > 1) { if (tex) out << " \\times \\mathbb{Z}_{" << odd << '}'; else out << " x Z" << odd; } return out; } } else if (fibre[1] == three || fibre[1] == threeB) { // [ S2 : (2,1), (3,1/2), (a,b) ] long a = fibre[2].alpha; if (a == 3) { // [ S2 : (2,1), (3,x), (3,y) ] // Orlik, p112, case (iii). long m = 6 * b_ + 3 + 2 * (fibre[1].beta + fibre[2].beta); // Note that m >= 1. if (m % 2 != 0 && m % 3 != 0) { out << (tex ? "S^3/P_{24}" : "S3/P24"); if (m > 1) { if (tex) out << " \\times \\mathbb{Z}_{" << m << '}'; else out << " x Z" << m; } return out; } else if (m % 2 != 0) { long threes = 1; while (m % 3 == 0) { m = m / 3; threes *= 3; } // I believe Orlik is missing a factor of three. // He claims this should be (threes * 8). if (tex) out << "S^3/P'_{" << (threes * 24) << '}'; else out << "S3/P'" << (threes * 24); if (m > 1) { if (tex) out << " \\times \\mathbb{Z}_{" << m << '}'; else out << " x Z" << m; } return out; } } else if (a == 4) { // [ S2 : (2,1), (3,x), (4,y) ] // Orlik, p112, case (iv). long m = 12 * b_ + 6 + 4 * fibre[1].beta + 3 * fibre[2].beta; // Note that m >= 1. out << (tex ? "S^3/P_{48}" : "S3/P48"); if (m > 1) { if (tex) out << " \\times \\mathbb{Z}_{" << m << '}'; else out << " x Z" << m; } return out; } else if (a == 5) { // [ S2 : (2,1), (3,x), (5,y) ] // Orlik, p112, case (v). long m = 30 * b_ + 15 + 10 * fibre[1].beta + 6 * fibre[2].beta; // Note that m >= 1. out << (tex ? "S^3/P_{120}" : "S3/P120"); if (m > 1) { if (tex) out << " \\times \\mathbb{Z}_{" << m << '}'; else out << " x Z" << m; } return out; } else if (a == 6 && fibre[1].beta == 1 && fibre[2].beta == 1 && b_ == -1) { // [ S2 : (2,1), (3,1), (6,-5) ]. // Orlik, p138, case M5. if (tex) return out << "T^2 \\times I / \\homtwo{1}{1}{-1}{0}"; else return out << "T x I / [ 1,1 | -1,0 ]"; } } else if (fibre[1] == four && fibre[2] == four && b_ == -1) { // [ S2 : (2,1), (4,1), (4,-3) ]. // Orlik, p138, case M4. if (tex) return out << "T^2 \\times I / \\homtwo{0}{-1}{1}{0}"; else return out << "T x I / [ 0,1 | -1,0 ]"; } } else if (nFibres_ == 3 && fibre[0] == three && fibre[1] == three && fibre[2] == three && b_ == -1) { // [ S2 : (3,1), (3,1), (3,-2) ] // Orlik, p138, case M3. if (tex) return out << "T^2 \\times I / \\homtwo{0}{-1}{1}{-1}"; else return out << "T x I / [ -1,1 | -1,0 ]"; } } // SFS over the real projective plane: if (genus_ == 1 && class_ == n2) { if (nFibres_ == 0) { // No exceptional fibres. if (b_ == 0) { // [ RP2 ] // Orlik, p113, remark. return out << (tex ? "\\mathbb{R}P^3 \\# \\mathbb{R}P^3" : "RP3 # RP3"); } else { // TODO: [ RP2 : (1,b) ] // Is this Orlik, p112, case (vi)? What is this? // ans << "S3/Q" << (4 * (b > 0 ? b : -b)); } } else if (nFibres_ == 1 && fibre[0].alpha > 1) { // Just one exceptional fibre. long a = fibre[0].alpha; long n = b_ * a + fibre[0].beta; if (n < 0) n = -n; if (n > 1) { // We have a prism manifold. // Orlik, p112, case (vi). if (a % 2 != 0) { return (tex ? out << "S^3/Q_{" << (4 * n) << "} \\times \\mathbb{Z}_{" << a << "}": out << "S3/Q" << (4 * n) << " x Z" << a); } else { long odd = a; long twos = 1; while (! (odd & 1)) { odd >>= 1; twos <<= 1; } if (tex) out << "S^3/D_{" << ((twos << 2) * n) << '}'; else out << "S3/D" << ((twos << 2) * n); if (odd > 1) { if (tex) out << " \\times \\mathbb{Z}_{" << odd << '}'; else out << " x Z" << odd; } return out; } } } } return writeStructure(out); } } // namespace regina regina-4.96/engine/manifold/nsfs.h000644 000765 000024 00000121053 12377775245 017015 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file manifold/nsfs.h * \brief Deals with general Seifert fibred spaces. */ #ifndef __NSFS_H #ifndef __DOXYGEN #define __NSFS_H #endif #include #include "regina-core.h" #include "nmanifold.h" namespace regina { class NAbelianGroup; class NLensSpace; /** * \weakgroup manifold * @{ */ /** * Represents an exceptional (alpha, beta) fibre in a Seifert * fibred space. * * The first parameter \a alpha must be strictly positive, and * the two parameters \a alpha and \a beta must be coprime. * * Note that we allow regular fibres with \a alpha = 1, and we do not * impose range limits on \a beta (thus \a beta may be negative, or it * may be larger than \a alpha). This is to allow more flexibility in * routines such as NSFSpace::insertFibre(). * * \warning In Regina 4.2.1 and earlier, this class was named * NExceptionalFibre. The new NSFSFibre class was introduced with * Regina 4.3, and has changed its behaviour (in particular, the * natural ordering of fibres has changed). Code that was written * to work with the old NExceptionalFibre class should be looked at closely * before being adapted to the new NSFSFibre class (i.e., it may require * more than just substituting class names). */ struct REGINA_API NSFSFibre { long alpha; /**< The first parameter of this (alpha, beta) fibre. Note that this is the index of the exceptional fibre. This parameter must always be strictly positive. */ long beta; /**< The second parameter of this (alpha, beta) fibre. This parameter must have no common factors with \a alpha. */ /** * Creates a new uninitialised exceptional fibre. */ NSFSFibre(); /** * Creates a new exceptional fibre with the given parameters. * * @param newAlpha the first parameter (the index) of this * exceptional fibre; this must be strictly positive. * @param newBeta the second parameter of this exceptional fibre; * this must have no common factors with the first parameter \a newAlpha. */ NSFSFibre(long newAlpha, long newBeta); /** * Creates a new exceptional fibre that is a clone of the given * fibre. * * @param cloneMe the exceptional fibre to clone. */ NSFSFibre(const NSFSFibre& cloneMe); /** * Makes this exceptional fibre a clone of the given fibre. * * @param cloneMe the exceptional fibre to clone. */ void operator = (const NSFSFibre& cloneMe); /** * Determines if this and the given exceptional fibre are identical. * This requires both fibres to have the same values for \a alpha * and the same values for \a beta. * * @param compare the fibre with which this will be compared. * @return \c true if and only if this and the given fibre are * identical. */ bool operator == (const NSFSFibre& compare) const; /** * Determines if this exceptional fibre is smaller than the given * fibre. Fibres are sorted by \a alpha and then by \a beta. * * @param compare the fibre with which this will be compared. * @return \c true if and only if this is smaller than the given fibre. */ bool operator < (const NSFSFibre& compare) const; }; /** * Writes the given fibre in human-readable format to the given output * stream. The fibre will be written in the format * (alpha,beta) with no newline appended. * * @param out the output stream to which to write. * @param f the fibre to write. * @return the output stream \a out. */ REGINA_API std::ostream& operator << (std::ostream& out, const NSFSFibre& f); /** * Represents a general Seifert fibred space, which may be orientable or * non-orientable. Punctures and reflector boundaries in the base orbifold * are supported. * * A Seifert fibred space whose base orbifold has no punctures or * reflector boundaries can be placed into one of the six classes * \c o1, \c o2, \c n1, \c n2, \c n3 and \c n4, as detailed on page 88 * of "Seifert Manifolds", Peter Orlik, Springer-Verlag, 1972. * These classes describe whether this base surface is orientable, as well * as how many of its generators give fibre-reversing paths in the 3-manifold. * * In the case where the base orbifold has punctures and/or reflector * boundaries, we use the five simplified classes \c bo1, \c bo2, \c bn1, * \c bn2 and \c bn3. These classes are not standard terminology (i.e., * they have been created explicitly for Regina), and generally they do not * provide enough information to uniquely identify the 3-manifold. They do * however identify whether or not the base orbifold is orientable, * and whether or not it contains any fibre-reversing paths. * * When describing punctures and reflector boundaries, a \e twisted * boundary is one that gives a fibre-reversing path, and an \e untwisted * boundary is one around which the direction of fibres is preserved. * * Exceptional fibres are sorted first by \a alpha (the index) and then * by \a beta. The obstruction constant \a b is stored separately, * though in output routines such as getName() and getStructure() it is * merged in with the exceptional fibres. Specifically, it is merged in * with the \a beta of the final exceptional fibre (replacing it with * beta + b.alpha), or if there are no exceptional fibres then * it is presented as a single (1,b) fibre. * * The NManifold routines getHomologyH1() and construct() are only * implemented in some cases. The getHomologyH1() routine is * implemented if and only if the base orbifold has no punctures. * The construct() routine is implemented only for lens spaces and * Seifert fibred spaces over the 2-sphere without punctures or reflector * boundaries. * * \warning In Regina 4.2.1 and earlier, this class was named NSFS. * The new NSFSpace class was introduced with Regina 4.3, and has changed * its behaviour in siginficant ways (becoming more general, as well as * keeping the obstruction parameter \a b separate). Code that was written * to work with the old NSFS class should be looked at closely before * being adapted to the new NSFSpace class (i.e., it may require more * than just substituting class names). * * \todo \featurelong Implement recognition of more common names. * \todo \featurelong Implement triangulation construction and homology * calculation for more Seifert fibred spaces. */ class REGINA_API NSFSpace : public NManifold { public: /** * Lists the six classes \c o1, \c o2, \c n1, \c n2, \c n3, \c n4 * for base orbifolds without boundaries, plus five classes * \c bo1, \c b02, \c bn1, \c bn2, \c bn3 for base orbifolds * with boundaries. */ enum classType { o1 = 101, /**< Indicates that the base orbifold is orientable with no punctures or reflector boundaries, and that none of its generators give fibre-reversing paths. */ o2 = 102, /**< Indicates that the base orbifold is orientable with no punctures or reflector boundaries, and that all of its generators give fibre-reversing paths. */ n1 = 201, /**< Indicates that the base orbifold is non-orientable with no punctures or reflector boundaries, and that none of its generators give fibre-reversing paths. */ n2 = 202, /**< Indicates that the base orbifold is non-orientable with no punctures or reflector boundaries, and that all of its generators give fibre-reversing paths. */ n3 = 203, /**< Indicates that the base orbifold is non-orientable with no punctures or reflector boundaries, that it has non-orientable genus at least two, and that precisely one of its generators gives a fibre-reversing path. */ n4 = 204, /**< Indicates that the base orbifold is non-orientable with no punctures or reflector boundaries, that it has non-orientable genus at least three, and that precisely two of its generators give fibre-reversing paths. */ bo1 = 301, /**< Indicates that the base orbifold contains punctures and/or reflector boundaries, that it is orientable, and that it contains no fibre-reversing paths. */ bo2 = 302, /**< Indicates that the base orbifold contains punctures and/or reflector boundaries, that it is orientable, and that it contains at least one fibre-reversing path. */ bn1 = 401, /**< Indicates that the base orbifold contains punctures and/or reflector boundaries, that it is non-orientable, and that it contains no fibre-reversing paths. */ bn2 = 402, /**< Indicates that the base orbifold contains punctures and/or reflector boundaries, that it is non-orientable, and that its fibre-reversing paths correspond precisely to its orientation-reversing paths. */ bn3 = 403 /**< Indicates that the base orbifold contains punctures and/or reflector boundaries, that it is non-orientable, that it contains at least one fibre-reversing path, and that its fibre-reversing paths do not correspond precisely to its orientation-reversing paths. */ }; private: classType class_; /**< Indicates which of the classes above this space belongs to. */ unsigned long genus_; /**< The genus of the base orbifold. For non-orientable base orbifolds this is the non-orientable genus. */ unsigned long punctures_; /**< The number of punctures in the base orbifold whose boundaries are fibre-preserving. This only counts ordinary boundary components, not reflector boundary components. */ unsigned long puncturesTwisted_; /**< The number of punctures in the base orbifold whose boundaries are fibre-reversing. This only counts ordinary boundary components, not reflector boundary components. */ unsigned long reflectors_; /**< The number of reflector boundary components in the base orbifold whose boundaries are fibre-preserving. These are in addition to the regular boundary components described by \a punctures_. */ unsigned long reflectorsTwisted_; /**< The number of reflector boundary components in the base orbifold whose boundaries are fibre-reversing. These are in addition to the regular boundary components described by \a puncturesTwisted_. */ std::list fibres_; /**< The exceptional fibres. This list will be sorted, and will only contain fibres for which \a alpha and \a beta are coprime and 0 <= beta < alpha > 1. */ unsigned long nFibres_; /**< The size of the \a fibres_ list, used to avoid calling the linear time fibres_.size(). */ long b_; /**< The obstruction parameter \a b, which corresponds to an additional (1,b) fibre. */ public: /** * Creates a new Seifert fibred space with base orbifold the * 2-sphere and no exceptional fibres. */ NSFSpace(); /** * Creates a new Seifert fibred space of the given class with the * given base orbifold and no exceptional fibres. * * \pre If there are no punctures or reflector boundary components, * then \a useClass is one of the six classes \c o1, \c o2, \c n1, * \c n2, \c n3 or \c n4. Likewise, if there are punctures and/or * reflector boundary components, then \a useClass is one of the * five classes \c bo1, \c bo2, \c bn1, \c bn2 or \c bn3. * \pre If there are any twisted punctures or reflector boundary * components, then \a useClass is either \c bo2 or \c bn3. * * @param useClass indicates whether the base orbifold is closed * and/or orientable, and gives information about fibre-reversing * paths in the 3-manifold. See the NSFSpace class notes and the * classType enumeration notes for details. * @param genus the genus of the base orbifold (the * number of tori or projective planes that it contains). * Note that for non-orientable base surfaces, this is the * non-orientable genus. * @param punctures the number of untwisted ordinary boundary * components of the base orbifold. Here "ordinary" means that * the puncture gives rise to a real 3-manifold boundary (i.e., * this is not a reflector boundary of the base orbifold). * @param puncturesTwisted the number of twisted ordinary boundary * components of the base orbifold. Here "ordinary" means that * the puncture gives rise to a real 3-manifold boundary (i.e., * this is not a reflector boundary of the base orbifold). * @param reflectors the number of untwisted reflector boundary * components of the base orbifold. These are in addition to * the ordinary boundary components described by \a punctures. * @param reflectorsTwisted the number of twisted reflector boundary * components of the base orbifold. These are in addition to * the ordinary boundary components described by \a puncturesTwisted. */ NSFSpace(classType useClass, unsigned long genus, unsigned long punctures = 0, unsigned long puncturesTwisted = 0, unsigned long reflectors = 0, unsigned long reflectorsTwisted = 0); /** * Creates a new Seifert fibred space that is a clone of * the given space. * * @param cloneMe the Seifert fibred space to clone. */ NSFSpace(const NSFSpace& cloneMe); /** * Destroys this Seifert fibred space. */ virtual ~NSFSpace(); /** * Modifies this Seifert fibred space to be a clone of the given * space. * * @param cloneMe the Seifert fibred space to clone. */ void operator = (const NSFSpace& cloneMe); /** * Returns which of the eleven predefined classes this space * belongs to. The specific class indicates whether the * base orbifold has punctures and/or reflector boundaries, * whether the base orbifold is orientable, and gives information * on fibre-reversing paths. * * The class can be (indirectly) modified by calling * addHandle(), addCrosscap(), addPuncture() or addReflector(). * * For more information on the eleven predefined classes, see the * NSFSpace class notes or the classType enumeration notes. * * @return the particular class to which this space belongs. */ classType baseClass() const; /** * Returns the genus of the base orbifold. All punctures and * reflector boundaries in the base orbifold are ignored (i.e., * they are treated as though they had been replaced with ordinary * filled discs). * * The genus is the number of tori or projective planes that the * base surface is formed from. In particular, if the base * surface is non-orientable then this is the non-orientable genus. * * @return the genus of the base orbifold. */ unsigned long baseGenus() const; /** * Returns whether or not the base surface is orientable. * Reflector boundary components of the base orbifold are not * considered here. * * The orientability of the base surface can be (indirectly) * modified by calling addCrosscap(). * * @return \c true if and only if the base surface is orientable. */ bool baseOrientable() const; /** * Returns whether or not this space contains any fibre-reversing * paths. * * @return \c true if and only if a fibre-reversing path exists. */ bool fibreReversing() const; /** * Returns whether or not we can negate an exceptional fibre by * passing it around the interior of the base orbifold. That is, * this routine determines whether a (\a p, \a q) exceptional * fibre can become a (\a p, -\a q) exceptional fibre simply by * sliding it around. * * This is possible if either * - the base orbifold has an orientation-reversing loop that * does not reverse fibres in the 3-manifold, or * - the base orbifold has an orientation-preserving loop that * does reverse fibres in the 3-manifold. * * Note that reflector boundary components, whilst making the * overall 3-manifold non-orientable, have no bearing on the * outcome of this routine. * * @return \c true if and only an exceptional fibre can be * reflected as described above. */ bool fibreNegating() const; /** * Returns the total number of punctures in the base orbifold. * In other words, this routine returns the total number of real * torus or Klein bottle boundary components in the overall * 3-manifold. * * Note that reflector boundaries on the base orbifold are \e not * counted here; only the ordinary boundary components that give rise * to real 3-manifold boundaries are included. * * Both untwisted and twisted punctures (giving rise to torus * and Klein bottle boundaries respectively in the 3-manifold) * are counted by this routine. * * @return the total number of punctures. */ unsigned long punctures() const; /** * Returns the number of punctures of the given type in the base * orbifold. In other words, this routine returns the number of * real boundary components of the given type in the overall * 3-manifold. * * This routine either counts only twisted punctures (which give * rise to Klein bottle boundaries), or only untwisted punctures * (which give rise to torus boundaries). * * Either way, reflector boundaries on the base orbifold are * \e not counted here; only ordinary boundary components that * give rise to real 3-manifold boundaries are considered. * * @param twisted \c true if only twisted punctures should be * counted (those that give fibre-reversing paths and Klein * bottle boundaries), or \c false if only untwisted punctures * should be counted (those that are fibre-preserving and give * torus boundaries). * @return the number of punctures of the given type. */ unsigned long punctures(bool twisted) const; /** * Returns the total number of reflector boundary components of the * base orbifold. This includes both twisted and untwisted * reflector boundaries. * * @return the total number of reflector boundary components. */ unsigned long reflectors() const; /** * Returns the number of reflector boundary components of the * given type in the base orbifold. This either counts only twisted * reflector boundaries, or only untwisted reflector boundaries. * * @param twisted \c true if only twisted reflector boundaries * should be counted (those that give fibre-reversing paths), or * \c false if only untwisted reflector boundaries should be counted. * @return the number of reflector boundaries of the given type. */ unsigned long reflectors(bool twisted) const; /** * Returns the number of exceptional fibres in this Seifert fibred * space. * * Note that the obstruction parameter \a b is not included in * this count. That is, any (1,k) fibres are ignored. * * @return the number of exceptional fibres. */ unsigned long fibreCount() const; /** * Returns the requested exceptional fibre. Fibres are stored * in sorted order by \a alpha (the index) and then by \a beta. * See the NSFSpace class notes for details. * * \warning This routine takes linear time (specifically, * linear in the argument \a which). * * @param which determines which fibre to return; this must be between * 0 and getFibreCount()-1 inclusive. * @return the requested fibre. */ NSFSFibre fibre(unsigned long which) const; /** * Returns the obstruction constant \a b for this Seifert fibred * space. * * The obstruction constant corresponds to the insertion of an * additional (1,\a b) fibre. It can be modified by calling * insertFibre() with a value of \a alpha = 1. It will also be * modified whenever insertFibre() is called with \a beta out of * range (\a beta < 0 or \a beta >= \a alpha), since each exceptional * fibre must be stored in standard form (0 <= \a beta < \a alpha). * * @return the obstruction constant \a b. */ long obstruction() const; /** * Inserts a new handle into the base orbifold. * * This increases the orientable genus of the base orbifold by * one, or the non-orientable genus by two. It is equivalent to * removing a disc from the base orbifold and replacing it with * a punctured torus. * * Note that this operation may alter which of the classes * described by classType this space belongs to. * * The exceptional fibres and the obstruction constant \a b are * not modified by this routine. * * @param fibreReversing \c true if one or both generators of * the new handle should give fibre-reversing curves in the * overall 3-manifold, or \c false (the default) if both * generators should preserve the directions of the fibres. */ void addHandle(bool fibreReversing = false); /** * Inserts a new crosscap into the base orbifold. * * This makes the base orbifold non-orientable, and increases * its non-orientable genus by one. It is equivalent to * removing a disc from the base orbifold and replacing it with * a Mobius band. * * Note that this operation may alter which of the classes * described by classType this space belongs to. * * The exceptional fibres and the obstruction constant \a b are * not modified by this routine. * * @param fibreReversing \c true if the generator of the new * crosscap should give a fibre-reversing curve in the * overall 3-manifold, or \c false (the default) if it should * preserve the directions of the fibres. */ void addCrosscap(bool fibreReversing = false); /** * Inserts one or more new punctures into the base orbifold. * The punctures may be twisted or untwisted. * * Each puncture insertion is equivalent to removing a disc from * the base orbifold. In the untwisted case this results in a * new torus boundary for the 3-manifold, and in the twisted * case it results in a new Klein bottle boundary. * * The exceptional fibres and the obstruction constant \a b are * not modified by this routine. * * @param twisted \c true if the new punctures should be twisted * (i.e., their boundaries should be fibre-reversing), or \c false * if the new punctures should be untwisted. * @param nPunctures the number of new punctures to insert. */ void addPuncture(bool twisted = false, unsigned long nPunctures = 1); /** * Adds one or more new reflector boundary components to the base * orbifold. The new reflector boundaries may be twisted or * untwisted. * * Each addition of a reflector boundary component is equivalent to * removing a disc from the base orbifold and replacing it with an * annulus with one reflector boundary. * * In the untwisted case, it has the effect of removing a trivially * fibred solid torus from the overall 3-manifold and replacing it * with an appropriately fibred twisted I-bundle over the torus. * * The exceptional fibres and the obstruction constant \a b are * not modified by this routine. * * @param twisted \c true if the new reflector boundaries should be * twisted (i.e., the boundaries should be fibre-reversing), or * \c false if the new reflector boundaries should be untwisted. * @param nReflectors the number of new reflector boundaries to add. */ void addReflector(bool twisted = false, unsigned long nReflectors = 1); /** * Adds the given fibre to this Seifert fibred space. * * This may be an exceptional fibre (\a alpha > 1) or it may be * a regular fibre (\a alpha = 1). If it is a regular fibre, * the obstruction constant \a b will be adjusted according to * the value of \a beta. * * Note that there is no restriction on the range of the second * parameter \a beta. If it is out of the usual range * 0 <= \a beta < \a alpha, it will be pulled back into this * range and the excess will be pushed into the obstruction * constant \a b. * * @param fibre the fibre to insert. The first parameter of * this fibre (i.e., its index) must be strictly positive, and * the two parameters of this fibre must be coprime. */ void insertFibre(const NSFSFibre& fibre); /** * Adds the given fibre to this Seifert fibred space. * * This may be an exceptional fibre (\a alpha > 1) or it may be * a regular fibre (\a alpha = 1). If it is a regular fibre, * the obstruction constant \a b will be adjusted according to * the value of \a beta. * * Note that there is no restriction on the range of the second * parameter \a beta. If it is out of the usual range * 0 <= \a beta < \a alpha, it will be pulled back into this * range and the excess will be pushed into the obstruction * constant \a b. * * @param alpha the first parameter (i.e., the index) of the * fibre to insert; this must be strictly positive. * @param beta the second parameter of the fibre to insert; this * must have no common factors with the first parameter \a alpha. */ void insertFibre(long alpha, long beta); /** * Replaces this space with its mirror image. Specifically, all * exceptional fibres and the obstruction constant \a b will be * negated. Note that the obstruction constant will generally * undergo further change as the exceptional fibres are * standardised into the usual 0 <= \a beta < \a alpha form. * * This routine will not change the curves made by the fibres * and the base orbifold on any boundary components (i.e., * boundaries caused by punctures in the base orbifold), with * the exception that each base curve will be reflected. * * \warning The space is \e not reduced after reflecting. * It may be that the space can be further simplified * (especially in the case of non-orientable manifolds). */ void reflect(); /** * Replaces each exceptional fibre of the form (\a alpha, \a beta) * with a fibre of the form (\a alpha, \a alpha - \a beta). * The obstruction constant \a b is not touched. */ void complementAllFibres(); /** * Reduces the parameters of this Seifert fibred space to a * simpler form if possible, without changing the underlying * fibration. * * In some cases the parameters of the Seifert fibred space may * be simplified by taking a mirror image of the entire 3-manifold. * The argument \a mayReflect signifies whether this is allowed. * * This routine will not change the curves made by the fibres * and the base orbifold on any boundary components (i.e., * boundaries caused by punctures in the base orbifold). * * \warning If \a mayReflect is \c true then the entire 3-manifold * might be replaced with its mirror image, in which case any * subsequent modifications (such as inserting additional fibres * or altering the base orbifold) may give unexpected results. * * @param mayReflect \c true if we are allowed to take a mirror * image of the entire 3-manifold, or \c false if we are not. */ void reduce(bool mayReflect = true); /** * Determines if this Seifert fibred space is a Lens space. * * If this is a Lens space, the NLensSpace returned will be * newly created and it will be up to the caller * of this routine to destroy it. * * @return a structure containing the details of this Lens * space, or \c null if this is not a Lens space. */ NLensSpace* isLensSpace() const; /** * Determines whether this and the given structure contain * precisely the same representations of precisely the same * Seifert fibred spaces. * * Note that this routine examines the particular representation of * the Seifert fibred space. Different Seifert parameters that give * the same 3-manifold will be regarded as not equal by this routine. * * @param compare the representation with which this will be compared. * @return \c true if and only if this and the given Seifert * fibred space representations are identical. */ bool operator == (const NSFSpace& compare) const; /** * Determines in a fairly ad-hoc fashion whether this representation * of this space is "smaller" than the given representation of the * given space. * * The ordering imposed on Seifert fibred space representations * is purely aesthetic on the part of the author, and is subject to * change in future versions of Regina. It also depends upon the * particular representation, so that different representations * of the same space may be ordered differently. * * All that this routine really offers is a well-defined way of * ordering Seifert fibred space representations. * * @param compare the representation with which this will be compared. * @return \c true if and only if this is "smaller" than the given * Seifert fibred space representation. */ bool operator < (const NSFSpace& compare) const; NTriangulation* construct() const; NAbelianGroup* getHomologyH1() const; bool isHyperbolic() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; std::ostream& writeStructure(std::ostream& out) const; private: /** * Replaces the fibre (\a alpha, \a beta) at the given iterator * with the fibre (\a alpha, \alpha - \a beta) instead. The fibre * is also moved backwards through the list in order to maintain * sorted order. * * The given iterator will be invalidated (since the * corresponding list element will be erased). * * \pre The fibre at the given iterator satisfies * \a beta * 2 > \a alpha. * * @return the iterator that was immediately after the given * iterator before this routine was called. Note that the given * iterator will be invalidated. */ std::list::iterator negateFibreDown( std::list::iterator it); /** * Internal to writeCommonBase(). * * Writes a particular countable feature of the base orbifold to * the given output stream in either TeX or plain format. */ static void writeBaseExtraCount(std::ostream& out, unsigned long count, const char* object, bool tex); /** * Writes the base orbifold to the given output stream in either * TeX or plain format. * * @param out the output stream to which to write. * @param tex \c true if we are writing in TeX format, or * \c false if we are writing in plain text format. * @return a reference to \a out. */ std::ostream& writeCommonBase(std::ostream& out, bool tex) const; /** * Provides the implementation of writeStructure() in both TeX * and plain formats. This is so that both writeName() and * writeTeXName() can call upon it if required. * * @param out the output stream to which to write. * @param tex \c true if we are writing in TeX format, or * \c false if we are writing in plain text format. * @return a reference to \a out. */ std::ostream& writeCommonStructure(std::ostream& out, bool tex) const; /** * Provides the implementation of both routines writeName() and * writeTeXName(). These routines are implemented together in * writeCommonName() since they share a common internal structure. * * @param out the output stream to which to write. * @param tex \c true if we are handling writeTeXName(), or * \c false if we are handling writeName(). * @return a reference to \a out. */ std::ostream& writeCommonName(std::ostream& out, bool tex) const; }; /*@}*/ // Inline functions for NSFSFibre inline NSFSFibre::NSFSFibre() { } inline NSFSFibre::NSFSFibre(long newAlpha, long newBeta) : alpha(newAlpha), beta(newBeta) { } inline NSFSFibre::NSFSFibre(const NSFSFibre& cloneMe) : alpha(cloneMe.alpha), beta(cloneMe.beta) { } inline void NSFSFibre::operator = (const NSFSFibre& cloneMe) { alpha = cloneMe.alpha; beta = cloneMe.beta; } inline bool NSFSFibre::operator == (const NSFSFibre& compare) const { return (alpha == compare.alpha && beta == compare.beta); } inline bool NSFSFibre::operator < (const NSFSFibre& compare) const { return (alpha < compare.alpha || (alpha == compare.alpha && beta < compare.beta)); } // Inline functions for NSFSpace inline NSFSpace::NSFSpace() : class_(o1), genus_(0), punctures_(0), puncturesTwisted_(0), reflectors_(0), reflectorsTwisted_(0), nFibres_(0), b_(0) { } inline NSFSpace::NSFSpace(NSFSpace::classType useClass, unsigned long genus, unsigned long punctures, unsigned long puncturesTwisted, unsigned long reflectors, unsigned long reflectorsTwisted) : class_(useClass), genus_(genus), punctures_(punctures), puncturesTwisted_(puncturesTwisted), reflectors_(reflectors), reflectorsTwisted_(reflectorsTwisted), nFibres_(0), b_(0) { } inline NSFSpace::NSFSpace(const NSFSpace& cloneMe) : NManifold(), class_(cloneMe.class_), genus_(cloneMe.genus_), punctures_(cloneMe.punctures_), puncturesTwisted_(cloneMe.puncturesTwisted_), reflectors_(cloneMe.reflectors_), reflectorsTwisted_(cloneMe.reflectorsTwisted_), fibres_(cloneMe.fibres_), nFibres_(cloneMe.nFibres_), b_(cloneMe.b_) { } inline NSFSpace::~NSFSpace() { } inline NSFSpace::classType NSFSpace::baseClass() const { return class_; } inline unsigned long NSFSpace::baseGenus() const { return genus_; } inline bool NSFSpace::baseOrientable() const { return (class_ == o1 || class_ == o2 || class_ == bo1 || class_ == bo2); } inline bool NSFSpace::fibreReversing() const { return ! (class_ == o1 || class_ == n1 || class_ == bo1 || class_ == bn1); } inline bool NSFSpace::fibreNegating() const { return ! (class_ == o1 || class_ == n2 || class_ == bo1 || class_ == bn2); } inline unsigned long NSFSpace::punctures() const { return punctures_ + puncturesTwisted_; } inline unsigned long NSFSpace::punctures(bool twisted) const { return (twisted ? puncturesTwisted_ : punctures_); } inline unsigned long NSFSpace::reflectors() const { return reflectors_ + reflectorsTwisted_; } inline unsigned long NSFSpace::reflectors(bool twisted) const { return (twisted ? reflectorsTwisted_ : reflectors_); } inline unsigned long NSFSpace::fibreCount() const { return nFibres_; } inline long NSFSpace::obstruction() const { return b_; } inline void NSFSpace::insertFibre(const NSFSFibre& fibre) { insertFibre(fibre.alpha, fibre.beta); } inline void NSFSpace::reflect() { complementAllFibres(); b_ = -b_ - static_cast(nFibres_); } inline bool NSFSpace::isHyperbolic() const { return false; } inline std::ostream& NSFSpace::writeName(std::ostream& out) const { return writeCommonName(out, false); } inline std::ostream& NSFSpace::writeTeXName(std::ostream& out) const { return writeCommonName(out, true); } inline std::ostream& NSFSpace::writeStructure(std::ostream& out) const { return writeCommonStructure(out, false); } } // namespace regina #endif regina-4.96/engine/manifold/nsfsaltset.cpp000644 000765 000024 00000014076 12377776620 020571 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "manifold/nsfs.h" #include "manifold/nsfsaltset.h" namespace regina { NSFSAltSet::NSFSAltSet(const NSFSpace* sfs) { /** * Note that whenever we add a (1,1) twist, we compensate by setting * row 2 -> row 2 + row 1 in our conversion matrix. */ // Start with the original, reduced to give obstruction constant zero. data_[0] = new NSFSpace(*sfs); data_[0]->reduce(false); long b = data_[0]->obstruction(); if (b) data_[0]->insertFibre(1, -b); conversion_[0] = NMatrix2(1, 0, -b, 1); reflected_[0] = false; /** * If the space is M/n2, we can replace it with D:(2,1)(2,-1) * with fibre and orbifold curves switched. To preserve the * determinant of the matching matrix we will actually use a * [0,1,-1,0] switch instead of a [0,1,1,0] switch. * * In fact we will use D:(2,1)(2,1) instead, which means: * * M_basis = [ 0 1 ] [ 1 0 ] D_basis = [ -1 1 ] D_basis; * [ -1 0 ] [ -1 1 ] [ -1 0 ] * * D_basis = [ 1 0 ] [ 0 -1 ] M_basis = [ 0 -1 ] M_basis. * [ 1 1 ] [ 1 0 ] [ 1 -1 ] */ if (data_[0]->baseClass() == NSFSpace::bn2 && data_[0]->baseGenus() == 1 && (! data_[0]->baseOrientable()) && data_[0]->punctures(false) == 1 && data_[0]->punctures(true) == 0 && data_[0]->reflectors() == 0 && data_[0]->fibreCount() == 0 && data_[0]->obstruction() == 0) { delete data_[0]; data_[0] = new NSFSpace(NSFSpace::bo1, 0 /* genus */, 1 /* punctures */, 0 /* twisted */, 0 /* reflectors */, 0 /* twisted */); data_[0]->insertFibre(2, 1); data_[0]->insertFibre(2, 1); conversion_[0] = NMatrix2(0, -1, 1, -1) * conversion_[0]; } // Using data_[0] as a foundation, try now for a reflection. data_[1] = new NSFSpace(*data_[0]); data_[1]->reflect(); data_[1]->reduce(false); b = data_[1]->obstruction(); data_[1]->insertFibre(1, -b); conversion_[1] = NMatrix2(1, 0, -b, -1) * conversion_[0]; reflected_[1] = true; size_ = 2; // In the vanilla case, this is all. However, we can occasionally // do a little more. // Can we negate all fibres without reflecting? // Note that (1,2) == (1,0) in this case, so this is only // interesting if we have an odd number of exceptional fibres. if (data_[0]->fibreNegating() && (data_[0]->fibreCount() % 2 != 0)) { // Do it by adding a single (1,1). The subsequent reduce() will // negate fibres to bring the obstruction constant back down to // zero, giving the desired effect. data_[2] = new NSFSpace(*data_[0]); data_[2]->insertFibre(1, 1); data_[2]->reduce(false); b = data_[2]->obstruction(); data_[2]->insertFibre(1, -b); conversion_[2] = NMatrix2(1, 0, -b + 1, 1) * conversion_[0]; reflected_[2] = false; // And do it again with an added reflection. data_[3] = new NSFSpace(*data_[0]); data_[3]->insertFibre(1, 1); data_[3]->reflect(); data_[3]->reduce(false); b = data_[3]->obstruction(); data_[3]->insertFibre(1, -b); conversion_[3] = NMatrix2(1, 0, -b - 1, -1) * conversion_[0]; reflected_[3] = true; size_ = 4; } } void NSFSAltSet::deleteAll() { for (unsigned i = 0; i < size_; i++) delete data_[i]; } void NSFSAltSet::deleteAll(NSFSpace* exception) { for (unsigned i = 0; i < size_; i++) if (data_[i] != exception) delete data_[i]; } void NSFSAltSet::deleteAll(NSFSpace* exception1, NSFSpace* exception2) { for (unsigned i = 0; i < size_; i++) if (data_[i] != exception1 && data_[i] != exception2) delete data_[i]; } } // namespace regina regina-4.96/engine/manifold/nsfsaltset.h000644 000765 000024 00000025746 12377775246 020247 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file manifold/nsfsaltset.h * \brief Assists with providing different representations of the same * Seifert fibred space. */ #ifndef __NSFSALTSET_H #ifndef __DOXYGEN #define __NSFSALTSET_H #endif #include "regina-core.h" #include "maths/nmatrix2.h" namespace regina { class NSFSpace; /** * \weakgroup manifold * @{ */ /** * Provides a variety of alternative representations of a single bounded * Seifert fibred space. These alternatives are made possible by altering * the curves made by the fibre and base orbifold on a boundary torus. * * This class is designed to help in finding simple representations of * graph manifolds (or, indeed, any non-geometric manifolds containing * Seifert fibred blocks). * * Each alternative comes with its own representation of the original Seifert * fibred space, along with instructions for converting fibre/base * curves on the boundary tori between the original and alternative spaces. * * The alternative representations will generally be as simple as * possible (and indeed simpler than the original where possible). * In particular, each alternative space is guaranteed to have obstruction * constant zero. The base orbifold may be changed entirely (for instance, * an orientable Seifert fibred space over the Mobius band with no exceptional * fibres will be converted to a Seifert fibred space over the disc with * two exceptional fibres). * * The conversions between boundary curves are described by a conversion * matrix \a M as follows. Consider the first boundary torus. Let \a f_old * and \a o_old be directed curves on this boundary representing the fibre * and base orbifold of the original space, and let \a f_alt and \a o_alt * be directed curves on this same boundary representing the fibre and * base orbifold of the new alternative space. Then * *
 *     [f_alt]         [f_old]
 *     [     ]  =  M * [     ].
 *     [o_alt]         [o_old]
 * 
* * Note that this \e only applies to the first boundary torus! If the * Seifert fibred space has more than one boundary, then for the * remaining boundaries the unoriented fibre and base curves remain the * same. More specifically, the directed fibre remains identical, and * the directed curve representing the base orbifold is reversed if and * only if a reflection was used in creating the alternative space, as * returned by reflected(). * * See the page on \ref sfsnotation for details on some of the * terminology used above. * * \warning When an object of this class is destroyed, the alternative * spaces it holds are \e not destroyed with it. One of the deleteAll() * routines must be explicitly called to clean up properly. * * \ifacespython Not present. */ class REGINA_API NSFSAltSet { private: unsigned size_; /**< The number of alternative spaces in this set. */ NSFSpace* data_[4]; /**< The list of alternative representations of this Seifert fibred space. */ NMatrix2 conversion_[4]; /**< A list of conversion matrices for each alternative representation, as described in the class notes above. */ bool reflected_[4]; /**< Indicates for each alternative whether a reflection was used in its creation. */ public: /** * Creates a new set of alternatives for the given Seifert * fibred space. Note that in general, none of the alternatives * will have a representation identical to the given space * (generally these alternative representations will be simpler * if possible). * * \pre The given Seifert fibred space has at least one torus * boundary. * * @param sfs the original Seifert fibred space for which we are * creating a set of alternative representations. */ NSFSAltSet(const NSFSpace* sfs); /** * Destroys all of the alternative representations in this set. * * This routine is for situations where none of the alternatives * here are appropriate for keeping and using elsewhere. */ void deleteAll(); /** * Destroys all of the alternative representations in this set, * except for the given exception. * * If the given exception is null or is not one of the * alternatives in this set, every alternative will be destroyed. * * This routine is for situations where one of the alternatives * has been kept for later use, and the rest are to be discarded. * * @param exception the one alternative that should not be destroyed. */ void deleteAll(NSFSpace* exception); /** * Destroys all of the alternative representations in this set, * except for the two given exceptions. * * If either exception is null or is not one of the alternatives * in this set, it will be ignored (and this routine will behave * like the one-exception or no-exceptions variant). Likewise, * if both exceptions are the same then this routine will behave * like the one-exception variant. * * This routine is for situations where one of the alternatives * has been kept for later use, but due to other operations * that may have taken place (such as space swapping) it is only * known that the alternative we kept is one of two possibilities. * * @param exception1 the first alternative that should not be * destroyed. * @param exception2 the second alternative that should not be * destroyed. */ void deleteAll(NSFSpace* exception1, NSFSpace* exception2); /** * Returns the number of alternative spaces in this set. */ unsigned size() const; /** * Returns the requested alternative space. * * @param which indicates which of the alternatives should be * returned; this must be between 0 and size()-1 inclusive. * @return the requested alternative space. */ NSFSpace* operator [] (unsigned which) const; /** * Returns the conversion matrix for the requested alternative * space. This matrix describes the fibre and base curves of * the alternative space on the first boundary torus in terms of * the fibre and base curves of the original space (which was * passed to the NSFSAltSet constructor). See the class notes * above for details. * * Note that this conversion matrix applies \e only to the first * boundary torus! If there is more than one boundary, the * remaining boundary conversions are simpler and depend only * on whether a reflection has been used or not. See reflected() * or the class notes for details. * * @param which indicates which of the alternatives we should * return the conversion matrix for; this must be between 0 and * size()-1 inclusive. * @return the conversion matrix for the requested alternative * space. */ const NMatrix2& conversion(unsigned which) const; /** * Returns whether or not a reflection was used when creating * the requested alternative space. This determines the * conversion between boundary curves for all boundary tori * after the first. * * More specifically, if no reflection was used then the directed * fibre and base curves are identical for the original and * alternative spaces. If a reflection was used, then the * directed fibres are identical but the directed base curves * are reversed. * * The conversion between curves on the first boundary torus is * generally more complex, and is returned as a matrix by the * conversion() routine. * * @param which indicates which of the alternatives is being * queried; this must be between 0 and size()-1 inclusive. * @return \c true if a reflection was used in creating the * requested alternative space, or \c false if no reflection was * used. */ bool reflected(unsigned which) const; }; /*@}*/ // Inline functions for NSFSAltSet inline unsigned NSFSAltSet::size() const { return size_; } inline NSFSpace* NSFSAltSet::operator [] (unsigned which) const { return data_[which]; } inline const NMatrix2& NSFSAltSet::conversion(unsigned which) const { return conversion_[which]; } inline bool NSFSAltSet::reflected(unsigned which) const { return reflected_[which]; } } // namespace regina #endif regina-4.96/engine/manifold/nsimplesurfacebundle.cpp000644 000765 000024 00000010534 12377776621 022611 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "algebra/nabeliangroup.h" #include "manifold/nsimplesurfacebundle.h" #include "triangulation/ntriangulation.h" namespace regina { const int NSimpleSurfaceBundle::S2xS1 = 1; const int NSimpleSurfaceBundle::S2xS1_TWISTED = 2; const int NSimpleSurfaceBundle::RP2xS1 = 3; NTriangulation* NSimpleSurfaceBundle::construct() const { NTriangulation* ans = new NTriangulation(); if (type == S2xS1) { ans->insertLayeredLensSpace(0, 1); } else if (type == S2xS1_TWISTED) { // Taken from section 3.5.1 of Ben Burton's PhD thesis. NTetrahedron* r = ans->newTetrahedron(); NTetrahedron* s = ans->newTetrahedron(); r->joinTo(1, s, NPerm4()); r->joinTo(3, s, NPerm4()); r->joinTo(2, s, NPerm4(3, 2, 0, 1)); s->joinTo(2, r, NPerm4(3, 2, 0, 1)); } else if (type == RP2xS1) { // Taken from section 3.5.1 of Ben Burton's PhD thesis. NTetrahedron* r = ans->newTetrahedron(); NTetrahedron* s = ans->newTetrahedron(); NTetrahedron* t = ans->newTetrahedron(); s->joinTo(0, r, NPerm4(0, 1, 2, 3)); s->joinTo(3, r, NPerm4(3, 0, 1, 2)); s->joinTo(1, t, NPerm4(3, 0, 1, 2)); s->joinTo(2, t, NPerm4(0, 1, 2, 3)); r->joinTo(1, t, NPerm4(2, 3, 0, 1)); r->joinTo(3, t, NPerm4(2, 3, 0, 1)); } return ans; } NAbelianGroup* NSimpleSurfaceBundle::getHomologyH1() const { NAbelianGroup* ans = new NAbelianGroup(); ans->addRank(); if (type == RP2xS1) ans->addTorsionElement(2); return ans; } std::ostream& NSimpleSurfaceBundle::writeName(std::ostream& out) const { if (type == S2xS1) out << "S2 x S1"; else if (type == S2xS1_TWISTED) out << "S2 x~ S1"; else if (type == RP2xS1) out << "RP2 x S1"; return out; } std::ostream& NSimpleSurfaceBundle::writeTeXName(std::ostream& out) const { if (type == S2xS1) out << "S^2 \\times S^1"; else if (type == S2xS1_TWISTED) out << "S^2 \\twisted S^1"; else if (type == RP2xS1) out << "\\mathbb{R}P^2 \\times S^1"; return out; } } // namespace regina regina-4.96/engine/manifold/nsimplesurfacebundle.h000644 000765 000024 00000012713 12377775250 022254 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file manifold/nsimplesurfacebundle.h * \brief Deals with simple closed surface bundles. */ #ifndef __NSIMPLESURFACEBUNDLE_H #ifndef __DOXYGEN #define __NSIMPLESURFACEBUNDLE_H #endif #include "regina-core.h" #include "nmanifold.h" namespace regina { /** * \weakgroup manifold * @{ */ /** * Represents a particularly simple closed surface bundle over the circle. * Only 2-sphere bundles, twisted 2-sphere bundles and projective plane * bundles are considered. * * All optional NManifold routines are implemented for this class. */ class REGINA_API NSimpleSurfaceBundle : public NManifold { public: /** * Represents the orientable 2-sphere bundle over the circle. */ static const int S2xS1; /** * Represents the non-orientable twisted 2-sphere bundle over the * circle. */ static const int S2xS1_TWISTED; /** * Represents the projective plane bundle over the circle. */ static const int RP2xS1; private: int type; /**< The specific surface bundle being represented. This must be one of the 3-manifold constants defined in this class. */ public: /** * Creates a new surface bundle of the given type. * * @param newType the specific type of surface bundle to * represent. This must be one of the 3-manifold constants * defined in this class. */ NSimpleSurfaceBundle(int newType); /** * Creates a clone of the given surface bundle. * * @param cloneMe the surface bundle to clone. */ NSimpleSurfaceBundle(const NSimpleSurfaceBundle& cloneMe); /** * Returns the specific type of surface bundle being represented. * * @return the type of surface bundle. This will be one of the * 3-manifold constants defined in this class. */ int getType() const; /** * Determines whether this and the given surface bundle represent * the same 3-manifold. * * @param compare the surface bundle with which this will be compared. * @return \c true if and only if this and the given surface bundle * are homeomorphic. */ bool operator == (const NSimpleSurfaceBundle& compare) const; virtual NTriangulation* construct() const; NAbelianGroup* getHomologyH1() const; bool isHyperbolic() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; }; /*@}*/ // Inline functions for NSimpleSurfaceBundle inline NSimpleSurfaceBundle::NSimpleSurfaceBundle( int newType) : type(newType) { } inline NSimpleSurfaceBundle::NSimpleSurfaceBundle( const NSimpleSurfaceBundle& cloneMe) : NManifold(), type(cloneMe.type) { } inline int NSimpleSurfaceBundle::getType() const { return type; } inline bool NSimpleSurfaceBundle::operator == (const NSimpleSurfaceBundle& compare) const { return (type == compare.type); } inline bool NSimpleSurfaceBundle::isHyperbolic() const { return false; } } // namespace regina #endif regina-4.96/engine/manifold/nsnappeacensusmfd.cpp000644 000765 000024 00000021747 12377776622 022125 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "file/nglobaldirs.h" #include "manifold/nsnappeacensusmfd.h" #include "subcomplex/nsnappeacensustri.h" #include "triangulation/nexampletriangulation.h" #include "triangulation/ntriangulation.h" #include #include namespace regina { namespace { int homDecode(char c) { if (c >= 'a' && c <= 'z') return c - 'a'; if (c >= 'A' && c <= 'Z') return c - 'A' + 26; return -1; } } const char NSnapPeaCensusManifold::SEC_5 = 'm'; const char NSnapPeaCensusManifold::SEC_6_OR = 's'; const char NSnapPeaCensusManifold::SEC_6_NOR = 'x'; const char NSnapPeaCensusManifold::SEC_7_OR = 'v'; const char NSnapPeaCensusManifold::SEC_7_NOR = 'y'; NTriangulation* NSnapPeaCensusManifold::construct() const { NTriangulation* ans = 0; // Hard-code a few special cases so that the numbering of tetrahedra // and vertices is compatible with earlier versions of Regina. if (section == SEC_5) { if (index == 0) { ans = NExampleTriangulation::gieseking(); ans->setPacketLabel(""); } else if (index == 1) { ans = new NTriangulation(); NTetrahedron* r = ans->newTetrahedron(); NTetrahedron* s = ans->newTetrahedron(); r->joinTo(0, s, NPerm4(0, 1, 3, 2)); r->joinTo(1, s, NPerm4(2, 3, 1, 0)); r->joinTo(2, s, NPerm4(3, 2, 1, 0)); r->joinTo(3, s, NPerm4(1, 0, 3, 2)); } else if (index == 2) { ans = new NTriangulation(); NTetrahedron* r = ans->newTetrahedron(); NTetrahedron* s = ans->newTetrahedron(); r->joinTo(0, s, NPerm4(0, 1, 3, 2)); r->joinTo(1, s, NPerm4(3, 1, 2, 0)); r->joinTo(2, s, NPerm4(2, 1, 3, 0)); r->joinTo(3, s, NPerm4(3, 1, 0, 2)); } else if (index == 3) { ans = new NTriangulation(); NTetrahedron* r = ans->newTetrahedron(); NTetrahedron* s = ans->newTetrahedron(); r->joinTo(0, s, NPerm4(0, 1, 3, 2)); r->joinTo(1, s, NPerm4(2, 1, 0, 3)); r->joinTo(2, s, NPerm4(0, 3, 2, 1)); r->joinTo(3, s, NPerm4(1, 0, 2, 3)); } else if (index == 4) { ans = NExampleTriangulation::figureEightKnotComplement(); ans->setPacketLabel(""); } else if (index == 129) { ans = NExampleTriangulation::whiteheadLinkComplement(); ans->setPacketLabel(""); } } if (ans) return ans; // Fetch the relevant data from the census dehydration files. std::string file = NGlobalDirs::data() + "/snappea"; switch (section) { case SEC_5: file += "/snappea-census-sec5.dat"; break; case SEC_6_OR: file += "/snappea-census-sec6o.dat"; break; case SEC_6_NOR: file += "/snappea-census-sec6n.dat"; break; case SEC_7_OR: file += "/snappea-census-sec7o.dat"; break; case SEC_7_NOR: file += "/snappea-census-sec7n.dat"; break; default: return 0; } FILE* dat = fopen(file.c_str(), "r"); if (! dat) { std::cerr << "Cannot open data file: " << file << std::endl; return 0; } char tri[30], hom[30]; /* Long enough to deal with the snappea census files for <= 7 tetrahedra. */ for (unsigned i = 0; i <= index; ++i) { if (fscanf(dat, "%s%s", tri, hom) != 2) { if (feof(dat)) std::cerr << "Read beyond end of data file: " << file << std::endl; else std::cerr << "Error reading data file: " << file << std::endl; return 0; } } fclose(dat); ans = NTriangulation::rehydrate(tri); return ans; } NAbelianGroup* NSnapPeaCensusManifold::getHomologyH1() const { // Fetch the relevant data from the census dehydration files. std::string file = NGlobalDirs::data() + "/snappea"; switch (section) { case SEC_5: file += "/snappea-census-sec5.dat"; break; case SEC_6_OR: file += "/snappea-census-sec6o.dat"; break; case SEC_6_NOR: file += "/snappea-census-sec6n.dat"; break; case SEC_7_OR: file += "/snappea-census-sec7o.dat"; break; case SEC_7_NOR: file += "/snappea-census-sec7n.dat"; break; default: return 0; } FILE* dat = fopen(file.c_str(), "r"); if (! dat) { std::cerr << "Cannot open data file: " << file << std::endl; return 0; } char tri[30], hom[30]; /* Long enough to deal with the snappea census files for <= 7 tetrahedra. */ for (unsigned i = 0; i <= index; ++i) { if (fscanf(dat, "%s%s", tri, hom) != 2) { if (feof(dat)) std::cerr << "Read beyond end of data file: " << file << std::endl; else std::cerr << "Error reading data file: " << file << std::endl; return 0; } } fclose(dat); NAbelianGroup* ans = new NAbelianGroup(); char* c; int val; // First character of the homology string represents rank. val = homDecode(hom[0]); // Empty string is picked up and dealt with here. if (val < 0) { delete ans; return 0; } ans->addRank(val); // The remaining characters represent torsion. std::multiset torsion; for (c = hom + 1; *c; ++c) { val = homDecode(*c); if (val < 0) { delete ans; return 0; } torsion.insert(val); } ans->addTorsionElements(torsion); return ans; } std::ostream& NSnapPeaCensusManifold::writeName(std::ostream& out) const { // Some manifolds will get special names, and will have their usual // SnapPea names written in writeStructure() instead. if (section == SEC_5) { if (index == 0) return out << "Gieseking manifold"; if (index == 4) return out << "Figure eight knot complement"; if (index == 129) return out << "Whitehead link complement"; } // No special names, just the usual SnapPea notation. return NSnapPeaCensusTri(section, index).writeName(out); } std::ostream& NSnapPeaCensusManifold::writeTeXName(std::ostream& out) const { return NSnapPeaCensusTri(section, index).writeTeXName(out); } std::ostream& NSnapPeaCensusManifold::writeStructure(std::ostream& out) const { // If we didn't give the usual SnapPea name in writeName(), give it here. if (section == SEC_5) { if (index == 0 || index == 4 || index == 129) return NSnapPeaCensusTri(section, index).writeName(out); } return out; } } // namespace regina regina-4.96/engine/manifold/nsnappeacensusmfd.h000644 000765 000024 00000021447 12377775255 021570 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file manifold/nsnappeacensusmfd.h * \brief Deals with 3-manifolds from the SnapPea census. */ #ifndef __NSNAPPEACENSUSMFD_H #ifndef __DOXYGEN #define __NSNAPPEACENSUSMFD_H #endif #include "regina-core.h" #include "nmanifold.h" namespace regina { /** * \weakgroup manifold * @{ */ /** * Represents a 3-manifold from the SnapPea cusped census. * * The SnapPea cusped census is the census of cusped hyperbolic 3-manifolds * formed from up to seven tetrahedra. This census was tabulated by * Callahan, Hildebrand and Weeks, and is shipped with SnapPea 3.0d3 * (and also with Regina). * * \note The modern cusped hyperbolic census now extends to nine tetrahedra, * and indeed the 9-tetrahedron database is accessible through the * NCensus lookup routines. However, for the time being, the scope of these * NSnapPeaCensusManifold and NSnapPeaCensusTri classes is restricted to the * original Callahan-Hildebrand-Weeks 7-tetrahedron census only. * * The census is split into five different sections according to number * of tetrahedra and orientability. Each of these sections corresponds * to one of the section constants defined in this class. * * For further details regarding the SnapPea census, see "A census of cusped * hyperbolic 3-manifolds", Patrick J. Callahan, Martin V. Hildebrand and * Jeffrey R. Weeks, Math. Comp. 68 (1999), no. 225, pp. 321--332. * * Note that this class is closely tied to NSnapPeaCensusTri. * In particular, the section constants defined in NSnapPeaCensusTri and * NSnapPeaCensusManifold are identical, and so may be freely mixed. * Furthermore, the section and index parameters of an NSnapPeaCensusTri * are identical to those of its corresponding NSnapPeaCensusManifold. * * All of the optional NManifold routines are implemented for this class. */ class REGINA_API NSnapPeaCensusManifold : public NManifold { public: static const char SEC_5; /**< Represents the collection of manifolds formed from five or fewer tetrahedra (both orientable and non-orientable). There are 415 manifolds in this section. */ static const char SEC_6_OR; /**< Represents the collection of orientable manifolds formed from six tetrahedra. There are 962 manifolds in this section. */ static const char SEC_6_NOR; /**< Represents the collection of non-orientable manifolds formed from six tetrahedra. There are 259 manifolds in this section. */ static const char SEC_7_OR; /**< Represents the collection of orientable manifolds formed from seven tetrahedra. There are 3552 manifolds in this section. */ static const char SEC_7_NOR; /**< Represents the collection of non-orientable manifolds formed from seven tetrahedra. There are 887 manifolds in this section. */ private: char section; /**< The section of the SnapPea census to which this manifold belongs. This must be one of the section constants defined in this class. */ unsigned long index; /**< The index within the given section of this specific manifold. Note that the first index in each section is zero. */ public: /** * Creates a new SnapPea census manifold with the given parameters. * * @param newSection the section of the SnapPea census to which * this manifold belongs. This must be one of the section * constants defined in this class. * @param newIndex specifies which particular manifold within the * given section is represented. The indices for each section * begin counting at zero, and so this index * must be between 0 and k-1, where k is the total * number of manifolds in the given section. */ NSnapPeaCensusManifold(char newSection, unsigned long newIndex); /** * Creates a clone of the given SnapPea census manifold. * * @param cloneMe the census manifold to clone. */ NSnapPeaCensusManifold(const NSnapPeaCensusManifold& cloneMe); /** * Destroys this structure. */ virtual ~NSnapPeaCensusManifold(); /** * Returns the section of the SnapPea census to which this * manifold belongs. This will be one of the section constants * defined in this class. * * @return the section of the SnapPea census. */ char getSection() const; /** * Returns the index of this manifold within its particular * section of the SnapPea census. Note that indices for each * section begin counting at zero. * * @return the index of this manifold within its section. */ unsigned long getIndex() const; /** * Determines whether this and the given structure represent * the same 3-manifold from the SnapPea census. * * @param compare the structure with which this will be compared. * @return \c true if and only if this and the given structure * represent the same SnapPea census manifold. */ bool operator == (const NSnapPeaCensusManifold& compare) const; NTriangulation* construct() const; NAbelianGroup* getHomologyH1() const; bool isHyperbolic() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; std::ostream& writeStructure(std::ostream& out) const; }; /*@}*/ // Inline functions for NSnapPeaCensusManifold inline NSnapPeaCensusManifold::NSnapPeaCensusManifold(char newSection, unsigned long newIndex) : section(newSection), index(newIndex) { } inline NSnapPeaCensusManifold::NSnapPeaCensusManifold( const NSnapPeaCensusManifold& cloneMe) : NManifold(), section(cloneMe.section), index(cloneMe.index) { } inline NSnapPeaCensusManifold::~NSnapPeaCensusManifold() { } inline char NSnapPeaCensusManifold::getSection() const { return section; } inline unsigned long NSnapPeaCensusManifold::getIndex() const { return index; } inline bool NSnapPeaCensusManifold::operator == ( const NSnapPeaCensusManifold& compare) const { return (section == compare.section && index == compare.index); } inline bool NSnapPeaCensusManifold::isHyperbolic() const { return true; } } // namespace regina #endif regina-4.96/engine/manifold/ntorusbundle.cpp000644 000765 000024 00000031272 12377776622 021126 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "algebra/nabeliangroup.h" #include "maths/nmatrixint.h" #include "manifold/ntorusbundle.h" namespace regina { NAbelianGroup* NTorusBundle::getHomologyH1() const { NMatrixInt relns(2, 2); relns.entry(0, 0) = monodromy[0][0] - 1; relns.entry(0, 1) = monodromy[0][1]; relns.entry(1, 0) = monodromy[1][0]; relns.entry(1, 1) = monodromy[1][1] - 1; NAbelianGroup* ans = new NAbelianGroup(); ans->addGroup(relns); ans->addRank(); return ans; } std::ostream& NTorusBundle::writeName(std::ostream& out) const { if (monodromy.isIdentity()) return out << "T x I"; else return out << "T x I / [ " << monodromy[0][0] << ',' << monodromy[0][1] << " | " << monodromy[1][0] << ',' << monodromy[1][1] << " ]"; } std::ostream& NTorusBundle::writeTeXName(std::ostream& out) const { if (monodromy.isIdentity()) return out << "T^2 \\times I"; else return out << "T^2 \\times I / \\homtwo{" << monodromy[0][0] << "}{" << monodromy[0][1] << "}{" << monodromy[1][0] << "}{" << monodromy[1][1] << "}"; } void NTorusBundle::reduce() { // Make the monodromy prettier. // In general we are allowed to: // // - Replace M with A M A^-1 // - Replace M with M^-1 // // Some specific tricks we can pull include: // // - Rotate the matrix 180 degrees (A = [ 0 1 | 1 0 ]) // - Negate the off-diagonal (A = [ 1 0 | 0 -1 ]) // // If det == +1, we can also: // // - Swap either diagonal individually (invert, then negate the // off-diagonal, then optionally rotate by 180 degrees) // // If det == -1, we can also: // // - Simultaneously swap and negate the main diagonal (invert) // The determinant should be +/-1 according to our preconditions, // but we'd better check that anyway. long det = monodromy.determinant(); if (det != 1 && det != -1) { // Something is very wrong. Don't touch it. std::cerr << "ERROR: NTorusBundle monodromy does not have " "determinant +/-1.\n"; return; } // Deal with the case where the main diagonal has strictly opposite // signs. long x; if (monodromy[0][0] < 0 && monodromy[1][1] > 0) { // Rotate 180 degrees to put the positive element up top. rotate(); } while (monodromy[0][0] > 0 && monodromy[1][1] < 0) { // Set x to the greatest absolute value of any main diagonal element. if (monodromy[0][0] >= - monodromy[1][1]) x = monodromy[0][0]; else x = - monodromy[1][1]; // If we catch any of the following four cases, the main diagonal // will either no longer have opposite signs, or it will have a // strictly smaller maximum absolute value. if (0 < monodromy[0][1] && monodromy[0][1] <= x) { addRCDown(); continue; } else if (0 < - monodromy[0][1] && - monodromy[0][1] <= x) { subtractRCDown(); continue; } else if (0 < monodromy[1][0] && monodromy[1][0] <= x) { subtractRCUp(); continue; } else if (0 < - monodromy[1][0] && - monodromy[1][0] <= x) { addRCUp(); continue; } // Since the determinant is +/-1 and neither element of the // main diagonal is zero, we cannot have both elements of the // off-diagonal with absolute value strictly greater than x. // The only remaining possibility is that some element of the // off-diagonal is zero (and therefore the main diagonal // contains +1 and -1). // The non-zero off-diagonal element (if any) can be reduced // modulo 2. This leaves us with the following possibilities: // [ 1 0 | 0 -1 ] , [ 1 1 | 0 -1 ], [ 1 0 | 1 -1 ]. // The final two possibilities are both equivalent to [ 0 1 | 1 0 ]. if ((monodromy[0][1] % 2) || (monodromy[1][0] % 2)) { monodromy[0][0] = monodromy[1][1] = 0; monodromy[0][1] = monodromy[1][0] = 1; } else { monodromy[0][1] = monodromy[1][0] = 0; // The main diagonal elements stay as they are (1, -1). } // In these cases we are completely finished. return; } // We are now guaranteed that the main diagonal does not have // strictly opposite signs. // Time to arrange the same for the off-diagonal. // If the off-diagonal has strictly opposite signs, the elements // must be +1 and -1, and the main diagonal must contain a zero. // Otherwise there is no way we can get determinant +/-1. if (monodromy[0][1] < 0 && monodromy[1][0] > 0) { // We have [ a -1 | 1 d ]. // Move the -1 to the bottom left corner by negating the off-diagonal. monodromy[0][1] = 1; monodromy[1][0] = -1; } if (monodromy[0][1] > 0 && monodromy[1][0] < 0) { // We have [ a 1 | -1 d ], where one of a or d is zero. // Rotate by 180 degrees to move the 0 to the bottom right // corner, negating the off-diagonal if necessary to preserve // the 1/-1 positions. if (monodromy[1][1]) { monodromy[0][0] = monodromy[1][1]; monodromy[1][1] = 0; } // Now we have [ a 1 | -1 0 ]. if (monodromy[0][0] > 1) { addRCDown(); // Everything becomes non-negative. } else if (monodromy[0][0] < -1) { subtractRCUp(); // Everything becomes non-positive. } else { // We have [ 1 1 | -1 0 ], [ 0 1 | -1 0 ] or [ -1 1 | -1 0 ]. // All of these are canonical. return; } } // Neither diagonal has strictly opposite signs. // Time to give all elements of the matrix the same sign (or zero). bool allNegative = false; if (det == 1) { // Either all non-negative or all non-positive, as determined by // the main diagonal. // If it's going to end up negative, just switch the signs for // now and remember this fact for later on. if (monodromy[0][0] < 0 || monodromy[1][1] < 0) { allNegative = true; monodromy[0][0] = - monodromy[0][0]; monodromy[1][1] = - monodromy[1][1]; } if (monodromy[0][1] < 0 || monodromy[1][0] < 0) { // We're always allowed to do this. monodromy[0][1] = - monodromy[0][1]; monodromy[1][0] = - monodromy[1][0]; } } else { // The determinant is -1. // The entire matrix can be made non-negative. if (monodromy[0][0] < 0 || monodromy[1][1] < 0) { // Invert (swap and negate the main diagonal). x = monodromy[0][0]; monodromy[0][0] = - monodromy[1][1]; monodromy[1][1] = -x; } if (monodromy[0][1] < 0 || monodromy[1][0] < 0) { // Negate the off-diagonal as usual. monodromy[0][1] = - monodromy[0][1]; monodromy[1][0] = - monodromy[1][0]; } } // We now have a matrix whose entries are all non-negative. // Run through a cycle of equivalent matrices, and choose the nicest. // I'm pretty sure I can prove that this is a cycle, but the proof // really should be written down. NMatrix2 start = monodromy; NMatrix2 best = monodromy; while (1) { // INV: monodromy has all non-negative entries. // INV: best contains the best seen matrix, including the current one. // It can be proven (via det = +/-1) that one row must dominate // another, unless we have [ 1 0 | 0 1 ] or [ 0 1 | 1 0 ]. if (monodromy.isIdentity()) { if (allNegative) monodromy.negate(); return; } if (monodromy[0][0] == 0 && monodromy[0][1] == 1 && monodromy[1][0] == 1 && monodromy[1][1] == 0) { if (allNegative) monodromy.negate(); return; } // We know at this point that one row dominates the other. if (monodromy[0][0] >= monodromy[1][0] && monodromy[0][1] >= monodromy[1][1]) subtractRCUp(); else subtractRCDown(); // Looking at a new matrix. if (monodromy == start) break; if (NTorusBundle::simplerNonNeg(monodromy, best)) best = monodromy; } // In the orientable case, run this all again for the rotated matrix. // This is not necessary in the non-orientable case since the // rotated matrix belongs to the same cycle as the original. if (det > 0) { rotate(); if (NTorusBundle::simplerNonNeg(monodromy, best)) best = monodromy; start = monodromy; while (1) { if (monodromy.isIdentity()) { if (allNegative) monodromy.negate(); return; } if (monodromy[0][0] == 0 && monodromy[0][1] == 1 && monodromy[1][0] == 1 && monodromy[1][1] == 0) { if (allNegative) monodromy.negate(); return; } // We know at this point that one row dominates the other. if (monodromy[0][0] >= monodromy[1][0] && monodromy[0][1] >= monodromy[1][1]) subtractRCUp(); else subtractRCDown(); // Looking at a new matrix. if (monodromy == start) break; if (NTorusBundle::simplerNonNeg(monodromy, best)) best = monodromy; } } monodromy = best; // Don't forget that negative case. if (allNegative) monodromy.negate(); } bool NTorusBundle::simplerNonNeg(const NMatrix2& m1, const NMatrix2& m2) { // Value symmetric matrices above all else. if (m1[0][1] == m1[1][0] && m2[0][1] != m2[1][0]) return true; if (m1[0][1] != m1[1][0] && m2[0][1] == m2[1][0]) return false; // Go for the smallest possible bottom-right element, then so on // working our way up. if (m1[1][1] < m2[1][1]) return true; if (m1[1][1] > m2[1][1]) return false; if (m1[1][0] < m2[1][0]) return true; if (m1[1][0] > m2[1][0]) return false; if (m1[0][1] < m2[0][1]) return true; if (m1[0][1] > m2[0][1]) return false; if (m1[0][0] < m2[0][0]) return true; return false; } } // namespace regina regina-4.96/engine/manifold/ntorusbundle.h000644 000765 000024 00000024445 12377775256 020601 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file manifold/ntorusbundle.h * \brief Deals with torus bundles over the circle. */ #ifndef __NTORUSBUNDLE_H #ifndef __DOXYGEN #define __NTORUSBUNDLE_H #endif #include "regina-core.h" #include "manifold/nmanifold.h" #include "maths/nmatrix2.h" namespace regina { /** * \weakgroup manifold * @{ */ /** * Represents a torus bundle over the circle. This is expressed as the * product of the torus and the interval, with the two torus boundaries * identified according to some specified monodromy. * * The monodromy is described by a 2-by-2 matrix \a M as follows. * Let \a a and \a b be generating curves of the upper torus boundary, * and let \a p and \a q be the corresponding curves on the lower torus * boundary (so that \a a and \a p are parallel and \a b and \a q are * parallel). Then we identify the torus boundaries so that, in * additive terms: * *
 *     [a]       [p]
 *     [ ] = M * [ ]
 *     [b]       [q]
 * 
* * All optional NManifold routines except for construct() are implemented * for this class. * * \todo \feature Implement the == operator for finding conjugate and * inverse matrices. */ class REGINA_API NTorusBundle : public NManifold { private: NMatrix2 monodromy; /**< The monodromy describing how the two torus boundaries are identified. See the class notes for details. */ public: /** * Creates a new trivial torus bundle over the circle. * In other words, this routine creates a torus bundle with the * identity monodromy. */ NTorusBundle(); /** * Creates a new torus bundle over the circle using the given * monodromy. * * \pre The given matrix has determinant +1 or -1. * * @param newMonodromy describes precisely how the upper and lower * torus boundaries are identified. See the class notes for details. */ NTorusBundle(const NMatrix2& newMonodromy); /** * Creates a new torus bundle over the circle using the given * monodromy. The four elements of the monodromy matrix are * passed separately. They combine to give the full monodromy * matrix \a M as follows: * *
         *           [ mon00  mon01 ]
         *     M  =  [              ]
         *           [ mon10  mon11 ]
         * 
* * \pre The monodromy matrix formed from the given parameters * has determinant +1 or -1. * * @param mon00 the (0,0) element of the monodromy matrix. * @param mon01 the (0,1) element of the monodromy matrix. * @param mon10 the (1,0) element of the monodromy matrix. * @param mon11 the (1,1) element of the monodromy matrix. */ NTorusBundle(long mon00, long mon01, long mon10, long mon11); /** * Creates a clone of the given torus bundle. * * @param cloneMe the torus bundle to clone. */ NTorusBundle(const NTorusBundle& cloneMe); /** * Returns the monodromy describing how the upper and lower * torus boundaries are identified. See the class notes for * details. * * @return the monodromy for this torus bundle. */ const NMatrix2& getMonodromy() const; NAbelianGroup* getHomologyH1() const; bool isHyperbolic() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; private: /** * Uses change of basis and/or inversion to reduces the monodromy * representation to something more aesthetically pleasing. */ void reduce(); /** * Rotate the monodromy matrix by 180 degrees (i.e., swap the * main diagonal and also swap the off-diagonal). * * This gives an alternate monodromy matrix for the same 3-manifold; * the transformation merely represents a change of basis. */ void rotate(); /** * Add the first row of the monodromy matrix to the second, * and then subtract the second column from the first. * * This gives an alternate monodromy matrix for the same 3-manifold; * the transformation merely represents a change of basis. */ void addRCDown(); /** * Subtract the first row of the monodromy matrix from the second, * and then add the second column to the first. * * This gives an alternate monodromy matrix for the same 3-manifold; * the transformation merely represents a change of basis. */ void subtractRCDown(); /** * Add the second row of the monodromy matrix to the first, * and then subtract the first column from the second. * * This gives an alternate monodromy matrix for the same 3-manifold; * the transformation merely represents a change of basis. */ void addRCUp(); /** * Subtract the second row of the monodromy matrix from the first, * and then add the first column to the second. * * This gives an alternate monodromy matrix for the same 3-manifold; * the transformation merely represents a change of basis. */ void subtractRCUp(); /** * Determines whether the first given monodromy matrix is more * aesthetically pleasing than the second. The way in which * this judgement is made is purely aesthetic on the part of the * author, and is subject to change in future versions of Regina. * * Note that this routine is not equivalent to the global * simpler(const NMatrix2&, const NMatrix2&). This routine is * tweaked specifically for use with torus bundle monodromies. * * \pre Both matrices consist entirely of non-negative elements. * * @param m1 the first monodromy matrix to examine. * @param m2 the second monodromy matrix to examine. * @return \c true if \a m1 is deemed to be more pleasing than \a m2, * or \c false if either the matrices are equal or \a m2 is more * pleasing than \a m1. */ static bool simplerNonNeg(const NMatrix2& m1, const NMatrix2& m2); }; /*@}*/ // Inline functions for NTorusBundle inline NTorusBundle::NTorusBundle() : monodromy(1, 0, 0, 1) { } inline NTorusBundle::NTorusBundle(const NMatrix2& newMonodromy) : monodromy(newMonodromy) { reduce(); } inline NTorusBundle::NTorusBundle(long mon00, long mon01, long mon10, long mon11) : monodromy(mon00, mon01, mon10, mon11) { reduce(); } inline NTorusBundle::NTorusBundle(const NTorusBundle& cloneMe) : NManifold(), monodromy(cloneMe.monodromy) { } inline const NMatrix2& NTorusBundle::getMonodromy() const { return monodromy; } inline void NTorusBundle::rotate() { long x = monodromy[0][0]; monodromy[0][0] = monodromy[1][1]; monodromy[1][1] = x; x = monodromy[0][1]; monodromy[0][1] = monodromy[1][0]; monodromy[1][0] = x; } inline void NTorusBundle::addRCDown() { monodromy[1][0] += monodromy[0][0]; monodromy[1][1] += monodromy[0][1]; monodromy[0][0] -= monodromy[0][1]; monodromy[1][0] -= monodromy[1][1]; } inline void NTorusBundle::subtractRCDown() { monodromy[1][0] -= monodromy[0][0]; monodromy[1][1] -= monodromy[0][1]; monodromy[0][0] += monodromy[0][1]; monodromy[1][0] += monodromy[1][1]; } inline void NTorusBundle::addRCUp() { monodromy[0][0] += monodromy[1][0]; monodromy[0][1] += monodromy[1][1]; monodromy[0][1] -= monodromy[0][0]; monodromy[1][1] -= monodromy[1][0]; } inline void NTorusBundle::subtractRCUp() { monodromy[0][0] -= monodromy[1][0]; monodromy[0][1] -= monodromy[1][1]; monodromy[0][1] += monodromy[0][0]; monodromy[1][1] += monodromy[1][0]; } inline bool NTorusBundle::isHyperbolic() const { return false; } } // namespace regina #endif regina-4.96/engine/manifold/order.cpp000644 000765 000024 00000011457 12377776623 017521 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include #include #include #include namespace regina { bool NManifold::operator < (const NManifold& compare) const { // Lens spaces go first. const NLensSpace* lens1 = dynamic_cast(this); const NLensSpace* lens2 = dynamic_cast(&compare); if (lens1 && ! lens2) return true; if (lens2 && ! lens1) return false; if (lens1 && lens2) { return (lens1->getP() < lens2->getP() || (lens1->getP() == lens2->getP() && lens1->getQ() < lens2->getQ())); } // Next go through Seifert fibred spaces. const NSFSpace* sfs1 = dynamic_cast(this); const NSFSpace* sfs2 = dynamic_cast(&compare); if (sfs1 && ! sfs2) return true; if (sfs2 && ! sfs1) return false; if (sfs1 && sfs2) return (*sfs1 < *sfs2); // Now for torus bundles. const NTorusBundle* bundle1 = dynamic_cast(this); const NTorusBundle* bundle2 = dynamic_cast(&compare); if (bundle1 && ! bundle2) return true; if (bundle2 && ! bundle1) return false; if (bundle1 && bundle2) { // TODO: Just sort by name here, since bundle parameters will // probably need to be made canonical anyway. return getName() < compare.getName(); } // Finally graph manifolds (SFS pairs, triples and loops). const NGraphPair* pair1 = dynamic_cast(this); const NGraphPair* pair2 = dynamic_cast(&compare); if (pair1 && ! pair2) return true; if (pair2 && ! pair1) return false; if (pair1 && pair2) return (*pair1 < *pair2); const NGraphTriple* triple1 = dynamic_cast(this); const NGraphTriple* triple2 = dynamic_cast(&compare); if (triple1 && ! triple2) return true; if (triple2 && ! triple1) return false; if (triple1 && triple2) return (*triple1 < *triple2); const NGraphLoop* loop1 = dynamic_cast(this); const NGraphLoop* loop2 = dynamic_cast(&compare); if (loop1 && ! loop2) return true; if (loop2 && ! loop1) return false; if (loop1 && loop2) return (*loop1 < *loop2); // No idea. Use the dictionary. return getName() < compare.getName(); } } // namespace regina regina-4.96/engine/manifold/sfsnotation.eps000644 000765 000024 00000013304 12234011536 020724 0ustar00babstaff000000 000000 %!PS-Adobe-2.0 EPSF-2.0 %%Title: sfsnotation.fig %%Creator: fig2dev Version 3.2 Patchlevel 5-alpha7 %%CreationDate: Sat Feb 18 18:49:54 2006 %%BoundingBox: 0 0 172 128 %Magnification: 1.0000 %%EndComments /$F2psDict 200 dict def $F2psDict begin $F2psDict /mtrx matrix put /col-1 {0 setgray} bind def /col0 {0.000 0.000 0.000 srgb} bind def /col1 {0.000 0.000 1.000 srgb} bind def /col2 {0.000 1.000 0.000 srgb} bind def /col3 {0.000 1.000 1.000 srgb} bind def /col4 {1.000 0.000 0.000 srgb} bind def /col5 {1.000 0.000 1.000 srgb} bind def /col6 {1.000 1.000 0.000 srgb} bind def /col7 {1.000 1.000 1.000 srgb} bind def /col8 {0.000 0.000 0.560 srgb} bind def /col9 {0.000 0.000 0.690 srgb} bind def /col10 {0.000 0.000 0.820 srgb} bind def /col11 {0.530 0.810 1.000 srgb} bind def /col12 {0.000 0.560 0.000 srgb} bind def /col13 {0.000 0.690 0.000 srgb} bind def /col14 {0.000 0.820 0.000 srgb} bind def /col15 {0.000 0.560 0.560 srgb} bind def /col16 {0.000 0.690 0.690 srgb} bind def /col17 {0.000 0.820 0.820 srgb} bind def /col18 {0.560 0.000 0.000 srgb} bind def /col19 {0.690 0.000 0.000 srgb} bind def /col20 {0.820 0.000 0.000 srgb} bind def /col21 {0.560 0.000 0.560 srgb} bind def /col22 {0.690 0.000 0.690 srgb} bind def /col23 {0.820 0.000 0.820 srgb} bind def /col24 {0.500 0.190 0.000 srgb} bind def /col25 {0.630 0.250 0.000 srgb} bind def /col26 {0.750 0.380 0.000 srgb} bind def /col27 {1.000 0.500 0.500 srgb} bind def /col28 {1.000 0.630 0.630 srgb} bind def /col29 {1.000 0.750 0.750 srgb} bind def /col30 {1.000 0.880 0.880 srgb} bind def /col31 {1.000 0.840 0.000 srgb} bind def end save newpath 0 128 moveto 0 0 lineto 172 0 lineto 172 128 lineto closepath clip newpath -169.3 241.9 translate 1 -1 scale /cp {closepath} bind def /ef {eofill} bind def /gr {grestore} bind def /gs {gsave} bind def /sa {save} bind def /rs {restore} bind def /l {lineto} bind def /m {moveto} bind def /rm {rmoveto} bind def /n {newpath} bind def /s {stroke} bind def /sh {show} bind def /slc {setlinecap} bind def /slj {setlinejoin} bind def /slw {setlinewidth} bind def /srgb {setrgbcolor} bind def /rot {rotate} bind def /sc {scale} bind def /sd {setdash} bind def /ff {findfont} bind def /sf {setfont} bind def /scf {scalefont} bind def /sw {stringwidth} bind def /tr {translate} bind def /tnt {dup dup currentrgbcolor 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} bind def /shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul 4 -2 roll mul srgb} bind def /DrawEllipse { /endangle exch def /startangle exch def /yrad exch def /xrad exch def /y exch def /x exch def /savematrix mtrx currentmatrix def x y tr xrad yrad sc 0 0 1 startangle endangle arc closepath savematrix setmatrix } def /$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def /$F2psEnd {$F2psEnteredState restore end} def $F2psBegin 10 setmiterlimit 0 slj 0 slc 0.06299 0.06299 sc % % Fig objects follow % % % here starts figure with depth 65 % Polyline 0 slj 0 slc 0.000 slw n 2700 2250 m 5400 2250 l 5400 3600 l 2700 3600 l cp gs col7 0.65 shd ef gr % here ends figure; % % here starts figure with depth 60 % Ellipse 0.000 slw n 4725 2925 318 318 0 360 DrawEllipse gs col7 0.85 shd ef gr % Ellipse n 3375 2925 318 318 0 360 DrawEllipse gs col7 0.85 shd ef gr % here ends figure; % % here starts figure with depth 55 % Arc 7.500 slw 0 slc n 3375.0 2925.0 318.2 -135.0000 45.0000 arcn gs col0 s gr % Arc n 4725.0 2925.0 318.2 -135.0000 45.0000 arcn gs col0 s gr % Polyline 0 slj n 3825 2250 m 5400 2250 l gs col0 s gr % Polyline n 4275 3600 m 2700 3600 l gs col0 s gr % here ends figure; % % here starts figure with depth 50 % Arc 7.500 slw 0 slc gs clippath 4668 2562 m 4466 2666 l 4507 2746 l 4709 2643 l 4709 2643 l 4529 2685 l 4668 2562 l cp eoclip n 4725.0 2925.0 318.2 45.0000 -135.0000 arcn gs col0 s gr gr % arrowhead 0 slj n 4668 2562 m 4529 2685 l 4709 2643 l 4668 2562 l cp gs col7 1.00 shd ef gr col0 s % Arc gs clippath 3318 2562 m 3116 2666 l 3157 2746 l 3359 2643 l 3359 2643 l 3179 2685 l 3318 2562 l cp eoclip n 3375.0 2925.0 318.2 45.0000 -135.0000 arcn gs col0 s gr gr % arrowhead n 3318 2562 m 3179 2685 l 3359 2643 l 3318 2562 l cp gs col7 1.00 shd ef gr col0 s % Polyline gs clippath 3838 2295 m 4065 2295 l 4065 2205 l 3838 2205 l 3838 2205 l 4018 2250 l 3838 2295 l cp eoclip n 2700 2250 m 4050 2250 l gs col0 s gr gr % arrowhead n 3838 2295 m 4018 2250 l 3838 2205 l 3838 2295 l cp gs col7 1.00 shd ef gr col0 s % Polyline gs clippath 4262 3555 m 4035 3555 l 4035 3645 l 4262 3645 l 4262 3645 l 4082 3600 l 4262 3555 l cp eoclip n 5400 3600 m 4050 3600 l gs col0 s gr gr % arrowhead n 4262 3555 m 4082 3600 l 4262 3645 l 4262 3555 l cp gs col7 1.00 shd ef gr col0 s % here ends figure; % % here starts figure with depth 40 % Polyline 0 slj 0 slc 7.500 slw n 5085 2610 m 5175 2700 l gs col0 s gr % Polyline n 5085 2700 m 5175 2610 l gs col0 s gr % Polyline [60] 0 sd gs clippath 5270 2152 m 5311 1928 l 5223 1911 l 5181 2135 l 5181 2135 l 5259 1967 l 5270 2152 l cp eoclip n 5130 2655 m 5265 1935 l gs col0 s gr gr [] 0 sd % arrowhead n 5270 2152 m 5259 1967 l 5181 2135 l 5270 2152 l cp gs col7 1.00 shd ef gr col0 s /Times-Italic ff 190.50 scf sf 3060 2655 m gs 1 -1 sc (e1) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Italic ff 190.50 scf sf 4365 2655 m gs 1 -1 sc (e2) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Italic ff 190.50 scf sf 4050 3825 m gs 1 -1 sc (o2) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Italic ff 190.50 scf sf 4050 2160 m gs 1 -1 sc (o1) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Italic ff 190.50 scf sf 5130 2025 m gs 1 -1 sc (f) dup sw pop 2 div neg 0 rm col0 sh gr % here ends figure; $F2psEnd rs showpage %%Trailer %EOF regina-4.96/engine/manifold/sfsnotation.fig000644 000765 000024 00000002707 12234011536 020707 0ustar00babstaff000000 000000 #FIG 3.2 Produced by xfig version 3.2.5-alpha5 Landscape Center Metric A4 100.00 Single -2 1200 2 5 1 0 1 0 7 55 -1 -1 0.000 0 1 0 0 3375.000 2925.000 3150 2700 3150 3150 3600 3150 5 1 0 1 0 7 50 -1 -1 0.000 0 1 1 0 4725.000 2925.000 4950 3150 4950 2700 4500 2700 1 0 1.00 90.00 180.00 5 1 0 1 0 7 55 -1 -1 0.000 0 1 0 0 4725.000 2925.000 4500 2700 4500 3150 4950 3150 5 1 0 1 0 7 50 -1 -1 0.000 0 1 1 0 3375.000 2925.000 3600 3150 3600 2700 3150 2700 1 0 1.00 90.00 180.00 1 3 0 0 0 7 60 -1 17 0.000 1 0.0000 4725 2925 318 318 4725 2925 4950 3150 1 3 0 0 0 7 60 -1 17 0.000 1 0.0000 3375 2925 318 318 3375 2925 3600 3150 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 1 0 1.00 90.00 180.00 2700 2250 4050 2250 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 1 0 1.00 90.00 180.00 5400 3600 4050 3600 2 1 0 1 0 7 55 -1 -1 0.000 0 0 -1 0 0 2 3825 2250 5400 2250 2 1 0 1 0 7 55 -1 -1 0.000 0 0 -1 0 0 2 4275 3600 2700 3600 2 2 0 0 0 7 65 -1 13 0.000 0 0 -1 0 0 5 2700 2250 5400 2250 5400 3600 2700 3600 2700 2250 2 1 0 1 0 7 40 -1 -1 0.000 0 0 -1 0 0 2 5085 2610 5175 2700 2 1 0 1 0 7 40 -1 -1 0.000 0 0 -1 0 0 2 5085 2700 5175 2610 2 1 1 1 0 7 40 -1 -1 4.000 0 0 -1 1 0 2 1 0 1.00 90.00 180.00 5130 2655 5265 1935 4 1 0 40 -1 3 12 0.0000 0 135 195 3060 2655 e1\001 4 1 0 40 -1 3 12 0.0000 0 135 195 4365 2655 e2\001 4 1 0 40 -1 3 12 0.0000 0 135 210 4050 3825 o2\001 4 1 0 40 -1 3 12 0.0000 0 135 210 4050 2160 o1\001 4 1 0 40 -1 3 12 0.0000 0 195 60 5130 2025 f\001 regina-4.96/engine/manifold/sfsnotation.png000644 000765 000024 00000005251 12234011536 020723 0ustar00babstaff000000 000000 ‰PNG  IHDRï² ÇL pHYsaa¨?§itIMEÖ2 [2ûÚ HIDATxÚílçÇ¿†lh5$s4b‡RJ­0,ÅÐÒff )Qm * $jÅ‚¦E A)… 2Òj‹Zmq–­ÛJƨBKªœ `ˆ+”^ ã‡0 a±xnh¬Ùí8Áع»÷½»à»ç/˾ó÷>÷üxŸ÷½óÙ$@W6¯Ákð¼¯Á«ž•™6Ç}ß”˜ãïf_{|²¤„Ä Õv¡YGñÜbq PG¼ŒCOõÊmjaLÌPl'~½ =¾«rÈÕp%|ËPþúð2÷Ý[[šøõ*ä»ïÞvWâóF¤¯{ó¨|ÊðÚýbJí¾ÑÂëw›ÜJœCŸ{h0ª-„=êcACCƒ_ê@åÐk{¯ ¸øTËùBË0=.™uE4Z…–Ñ4?b…Ëö˜¡Aþ¶Ì7e2À*Œë°phœ¿•öf¡Ý.Bº”Ur]Íó·Å}Ñ—@‹Ý¡lºØí£`>X»Ë¸ UçÁVÒ§)¯¯Õ–~Ÿ²îõùü~p„4­ÏÆÅl®t!ä†KQ!{3ÓrbÚóö¶õªÙG³ ´ˆh ”ªûÛw•>PM }=ti³EëuC-zLC“Øþ Y4ÜŒF¼±ýª*þ]ê`,—k4x\Þv„ߨ`V‹w`µA{f“°QqÀ…žû„ñ~bꟗª \[^Ôg%!YqÙ©—#pO7>æ .79–- ÙÊ Ÿ³žüì±i3¶ª»\F4Û7ÕêŸÃ¬›UÍU>Ž+Uáퟫ:+pEñ¾bƒ–æûÚà"W+ÞQd¯ÁûˆZ«¾xyV_¼œM_¼¬Îxƒ©úâMÕ™‹Œñ×à5xÙáWg¼MúâåRõÅ$ãå9ÿfËç zÖxT=ØÎê5;y%f âxSsÕ]b¹*wjÙwT™ â¹3f©*Ú šÍEq#Mñ—µE-þÝ?)ˆ› qüÃÿšü~Ú‡®?³­¬m6je“;XsˆUä:Ì "ZcSùwt¾c‰‚þõì-ppÁÙ¸†÷ «¹d?¨.öÚ÷óšÒ-ÇŒg®µÊÖZ óÁ©¤¯í/سYp,KyTä=å1Ÿ5ü¾–üqªÕ2â¹ÕÖŠÜTìÕª£ó°@õwÌIþƒ«S¦;hUïAE¾¾(:};αØ2ïèœä[ ®Mɘ9LBuò¹€œgƒDÞN÷€h+ˆx÷À½Ã°¿¸È9ðNÛ±=¶™9TÆÝ°bS‘-ªAêøÛ X '¬ «z÷gΜ§ªå4yrYW_.5žÍ:Þy‰øóðM/[>¿•·ããUw¶¦ÀVl*°E­¦îû÷‘°jÕŸUk>^k[GœoÙÀy¸ÿÔ—Ç:“0ìÈÒêÉAŽÝ   \=ø÷WlÈaæ|Wr]ÊýûvwÎ&ŽgOrl{[ *â$7Ø ð3'™i[­ªG—-ˆ37ºr³".nnÚCxDTÓý¿ª·J†9ç·Îz.:} ŠIoˈQ€{»×VŒï¤oÎÓ9±ªþ•1h\ͲUÎm};ßÁ©®^gšÓ÷soõÆéôǨq?Üä`NúÍZ_•­Î‹r1W_î±å’òŽ­;›ôÌìY S†ß$PþâbÚ¸wË¿6‚jß:G^® Mq%ðŽ}â¯Vçˆð–ù5ª´c§ïËQÕ·Š£pX<?µ]u?M`îsqªìÚˆ©ú@>ÇkxsÓDÎ÷ïîC܆;øcy÷ü@Üv%ö ½¶Ù"fr×7ç[EâOŽ\¦†{ðy±“’×OQœ⊿Dì1¦Ô¿Gkn|³»Bô¶¿hãèñÞÛS#þ(­õ¿£T«¶‹ß8eÇûôx/³J8ÎìgèÌœR¦ØÙË:hñ^:_"é@Ë~C÷Æé iªy:¼üj¤©õå ¼îíÒ¶OÉ?D‡—É·J<Ô’#<1îþÅRŒ*ÎðTx»K¤kÊbò f+$ï²¼ƒï—2ZâüsÄc‘Œ™GÞY¼×­Ò•³/’ò§IßÇz—§À{3KÆá>Cº’wÉ)c§ü. ¼çå,4;Iú‚œ³¼ð,9ïY¿çÈ»D†ûõ;)2öʾAÎÛ“%뀯“ñ†¬²vK!çåä)§“ñ¾%k·1AbÞòü;–l’tÁ)k·9ä¼—w],›Œ÷\”±‘ë´0Yå °²Ä¼”R‰yoËSî!»†&óW«Wmļ2•¯˜‰xefKÎ;^žð,²À4ËêGûFGä}L–rOïä[²TŸ"çtUVá˜KØOdñN&çµvËRžJÆ›%kÕ>0œ7ç¸,eÂqÎÖ#ë,?Aa>8CF³O’ޤÎ69U®ŸïÊW'’ò>+# ½úI|û¨tåcÄþµyeð&Óà5g|$Y˜#¿ùnAä$:ú ^¼ú¡Ôa¿n-y+üò§}÷x{¨ðš³¥ 7.žDÎk^.QµîY+^|ïCI§ÚûÅP°%ŸHê9Xo(ñš—ì–Íïl 3¹[ý3IÑ\ÖO‹ËïH(Y‹ÌtxŒ¯“ÍârH\´ò¢‡o÷P²×|¢O3{¼yÍÕ"“©o÷zËo´Šíí¶÷Óä…ùÍ¢€û¶.šD×¼¢\pߦl±«ÆbûzÛëÅ"BºmåÓ/¢ÙÞÜ%"¤½ëR_ûâï' þrÍêNóÛÿýþ7@×ø_ÍáBp_c÷±1%ú~3©'ª:·½úÜzÚ¸0ÿ8ðpUïú1›$¤”ûcÑ|ªlõðÎýj½2ÏÂ;õé %)Ã:÷‹ †?)þ°j[÷жá2×±N¡Gÿ-¨4\æŽ)—6ÚKò/€`Û¥åyQÅ0ÐßôºÊÿÙ‰ü¼¨9W_÷ò?‹¥Òî÷kw}y!ß™•2ˆÚ˜š™ž®ôù“ÿ¸¸hnø6è¾ïÕ€Y†ª^è¼Æ™®§×Òg<55¹êXç5ÿ˜ëéÀí 3Ÿ”§š›&ïyná_ßðfP —Š*Ñ:¢Z‘ªñ< ƒ×à5x ^ƒ×à5x ^ƒ×à5x ^ƒ×à5x ^ƒ×à5x ^ƒ7¡yyV™¤ÑÁìžxy§.xy6Ø=ѹÁ…ß¿C¬êYöjÃzïô¤Û©ß‰`½»u¶â¢™iI(×ȹŸwܸûUèþ?|Ž+§¸æLÿ/•a|!—Ãe†þ”QaÓþÿa™õÂ;ÈìïÕ/0.}ñý³Ákð>:¼-óMKCúáe|í½ö2Õe5«ÏŒ =.è†B™½:ˆç–ù¦Ì§û×–ª¯.¨m•öf¡Ý.‚ÐåR]\P·ÙÒ–í-íUŸWõx®ÝeÜ…@hU©‰Ï¡×Þ.…]‚p1ñýkaÀ,­t¡¬Ò“øþm¶ÃÑ,•€vÕý«·ùàÿ1ª]éþ}DzIEND®B`‚regina-4.96/engine/maths/approx.cpp000644 000765 000024 00000004545 12377776623 017242 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "maths/approx.h" namespace regina { const double epsilon = 0.00000001; } // namespace regina regina-4.96/engine/maths/approx.h000644 000765 000024 00000012551 12377775257 016705 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file maths/approx.h * \brief Provides facilities for working around rounding errors when * dealing with real numbers. */ #ifndef __APPROX_H #ifndef __DOXYGEN #define __APPROX_H #endif #include "regina-core.h" namespace regina { /** * \weakgroup maths * @{ */ /** * A very small positive real designed to accommodate for rounding error. * Any two numbers within \a epsilon of each other are considered to be * equal by the generic zero-testing and sign-testing routines defined in * this file (isZero(), isPositive(), isNonNegative() and so on). */ REGINA_API extern const double epsilon; /** * Determines whether the given real number is zero. * Any number within \a regina::epsilon of zero is considered to be zero. * * \pre R must be of a floating point real type. * * \ifacespython Not present. * * @param x the number to examine. * @return \c true if and only if the given number is approximately zero. */ template inline bool isZero(R x) { return (x > -epsilon && x < epsilon); } /** * Determines whether the given real number is non-zero. * Any number within \a regina::epsilon of zero is considered to be zero. * * \pre R must be of a floating point real type. * * \ifacespython Not present. * * @param x the number to examine. * @return \c true if and only if the given number is approximately non-zero. */ template inline bool isNonZero(R x) { return (x < -epsilon || x > epsilon); } /** * Determines whether the given real number is strictly positive. * Any number within \a regina::epsilon of zero is considered to be zero. * * \pre R must be of a floating point real type. * * \ifacespython Not present. * * @param x the number to examine. * @return \c true if and only if the given number is strictly positive. */ template inline bool isPositive(R x) { return (x > epsilon); } /** * Determines whether the given real number is strictly negative. * Any number within \a regina::epsilon of zero is considered to be zero. * * \pre R must be of a floating point real type. * * \ifacespython Not present. * * @param x the number to examine. * @return \c true if and only if the given number is strictly negative. */ template inline bool isNegative(R x) { return (x < -epsilon); } /** * Determines whether the given real number is non-negative. * Any number within \a regina::epsilon of zero is considered to be zero. * * \pre R must be of a floating point real type. * * \ifacespython Not present. * * @param x the number to examine. * @return \c true if and only if the given number is non-negative. */ template inline bool isNonNegative(R x) { return (x > -epsilon); } /** * Determines whether the given real number is non-positive. * Any number within \a regina::epsilon of zero is considered to be zero. * * \pre R must be of a floating point real type. * * \ifacespython Not present. * * @param x the number to examine. * @return \c true if and only if the given number is non-positive. */ template inline bool isNonPositive(R x) { return (x < epsilon); } /*@}*/ } // namespace regina #endif regina-4.96/engine/maths/CMakeLists.txt000644 000765 000024 00000001306 12377772667 017761 0ustar00babstaff000000 000000 # maths # Files to compile SET ( FILES approx matrixops ninteger nmatrix2 nperm3 nperm4 nperm5 nprimes nrational nray numbertheory seedprimes ) # Prepend folder name FOREACH ( SOURCE_FILE ${FILES} ) SET ( SOURCES ${SOURCES} maths/${SOURCE_FILE}) ENDFOREACH(SOURCE_FILE) SET(SOURCES ${SOURCES} PARENT_SCOPE) if (${REGINA_INSTALL_DEV}) INSTALL( FILES approx.h matrixops.h ninteger.h nlargeinteger.h nmatrix.h nmatrix2.h nmatrixint.h nperm3.h nperm4.h nperm5.h nprimes.h nrational.h nray.h numbertheory.h nvector.h permconv.h DESTINATION ${INCLUDEDIR}/maths COMPONENT Development) endif (${REGINA_INSTALL_DEV}) regina-4.96/engine/maths/matrixops.cpp000644 000765 000024 00000145034 12377776624 017757 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "maths/matrixops.h" #include "maths/numbertheory.h" namespace regina { void smithNormalForm(NMatrixInt& matrix) { unsigned long currStage = 0; unsigned long nonEmptyRows = matrix.rows(); unsigned long nonEmptyCols = matrix.columns(); bool flag; unsigned long i, j, k; NLargeInteger d, u, v, a, b; NLargeInteger tmp; while ((currStage < nonEmptyRows) && (currStage < nonEmptyCols)) { loopStart: // Have we got an empty row? flag = true; for (i=currStage; i i. // Find the first non-zero entry in row doneRows. for (c = doneRows; c < n; ++c) if (echelon.entry(doneRows, lead[c]) != NMatrixInt::zero) break; if (c == n) { // We have a zero row. Push it to the bottom. --rank; if (doneRows < rank) { echelon.swapRows(doneRows, rank); matrix.swapRows(doneRows, rank); } } else { // We have a non-zero row. // Save the column in which we found our non-zero entry. tmp = lead[doneRows]; lead[doneRows] = lead[c]; lead[c] = tmp; // Make all lower entries in column lead[doneRows] equal to zero. // Do this with only integer arithmetic. This could lead to // some very large matrix entries, though we're using NLargeInteger // so the worst that can happen is that things get slow. coeff1 = echelon.entry(doneRows, lead[doneRows]); for (r = doneRows + 1; r < rank; ++r) { coeff2 = echelon.entry(r, lead[doneRows]); if (coeff2 != NMatrixInt::zero) { echelon.multRow(r, coeff1); echelon.addRow(doneRows, r, -coeff2); // Factor out the gcd of this row. echelon.reduceRow(r); } } ++doneRows; } } // All done! delete[] lead; return rank; } unsigned rowBasisAndOrthComp(NMatrixInt& input, NMatrixInt& complement) { unsigned n = input.columns(); // Make a copy of the input matrix, and reduce it to row echelon form. NMatrixInt echelon(input); unsigned doneRows = 0; unsigned rank = echelon.rows(); unsigned* lead = new unsigned[n]; unsigned r, c, tmp; for (c = 0; c < n; ++c) lead[c] = c; NLargeInteger coeff1, coeff2; while (doneRows < rank) { // INV: For i < doneRows, echelon[i, lead[i]] is non-zero, and // every other entry echelon[j, lead[i]] is zero for j > i. // Find the first non-zero entry in row doneRows. for (c = doneRows; c < n; ++c) if (echelon.entry(doneRows, lead[c]) != NMatrixInt::zero) break; if (c == n) { // We have a zero row. Push it to the bottom. --rank; if (doneRows < rank) { echelon.swapRows(doneRows, rank); input.swapRows(doneRows, rank); } } else { // We have a non-zero row. // Save the column in which we found our non-zero entry. tmp = lead[doneRows]; lead[doneRows] = lead[c]; lead[c] = tmp; // Make all lower entries in column lead[doneRows] equal to zero. // Do this with only integer arithmetic. This could lead to // some very large matrix entries, though we're using NLargeInteger // so the worst that can happen is that things get slow. coeff1 = echelon.entry(doneRows, lead[doneRows]); for (r = doneRows + 1; r < rank; ++r) { coeff2 = echelon.entry(r, lead[doneRows]); if (coeff2 != NMatrixInt::zero) { echelon.multRow(r, coeff1); echelon.addRow(doneRows, r, -coeff2); // Factor out the gcd of this row. echelon.reduceRow(r); } } ++doneRows; } } // Now form the basis for the orthogonal complement. complement.initialise(NMatrixInt::zero); NLargeInteger lcmLead = 1; for (r = 0; r < n; ++r) { complement.entry(r, lead[r]) = lcmLead; complement.entry(r, lead[r]).negate(); for (c = 0; c < r && c < rank; ++c) { complement.entry(r, lead[c]) = echelon.entry(c, lead[r]) * lcmLead; complement.entry(r, lead[c]).divByExact(echelon.entry(c, lead[c])); } complement.reduceRow(r); if (r < rank) { coeff1 = echelon.entry(r, lead[r]); lcmLead = lcmLead.lcm(coeff1); for (tmp = 0; tmp < r; ++tmp) { coeff2 = echelon.entry(tmp, lead[r]); if (coeff2 != NMatrixInt::zero) { echelon.multRow(tmp, coeff1); echelon.addRow(r, tmp, -coeff2); // Factor out the gcd of this row. echelon.reduceRow(tmp); } // TODO: Is this actually necessary? lcmLead = lcmLead.lcm(echelon.entry(tmp, lead[tmp])); } } } // All done! delete[] lead; return rank; } void columnEchelonForm(NMatrixInt &M, NMatrixInt &R, NMatrixInt &Ri, const std::vector &rowList) { unsigned i,j; unsigned CR=0; unsigned CC=0; // these are the indices of the current WORKING rows and columns // respectively. // thus the entries of M above CR will not change, and to the left of // CC all that can happen is some reduction. std::vector rowNZlist; // in the current row, this is the // list of column coordinates // for the non-zero entries. NLargeInteger d,r; // given two NLargeIntegers a and b, we will represent // a/b by d and a % b by r in the algorithm. NLargeInteger u,v,gcd, a,b; // for column operations u,v,a,b represent // a 2x2 matrix. NLargeInteger tmp; // the algorithm will think of itself as working top to bottom. while ( (CR1) { // do column reduction on columns rowNZlist[0] and rowNZlist[1] // first we need to find the approp modification matrix. // This will be the matrix ( u -b ) where ua+vb = 1. We get // ( v a ) // a and b from entry(CR, r[0]) and entry(CR, r[1]) // by dividing by their GCD, found with // rowNZlist[0].gcdWithCoeffs(rowNZlist[1],u,v) gcd = M.entry(rowList[CR], rowNZlist[0]).gcdWithCoeffs( M.entry(rowList[CR], rowNZlist[1]), u,v); a = M.entry(rowList[CR], rowNZlist[0]).divExact(gcd); b = M.entry(rowList[CR], rowNZlist[1]).divExact(gcd); // so multiplication on the right by the above matrix // corresponds to replacing column r[0] by u r[0] + v r[1] // and column r[1] by -b r[0] + a r[1]. for (i=0;i preImageOfLattice(const NMatrixInt& hom, const std::vector& L) { // there are two main steps to this algorithm. // 1) find a basis for the domain which splits into a) vectors sent to the // complement of the primitive subspace generated by the range lattice // and b) a basis of vectors sent to the primitive subspace generated // by the range lattice. // 2) modify the basis (b) by column ops to get the preimage of the lattice. // step (1) is an application of the columnEchelonForm // step (2) starts with another application of columnEchelonForm, but then // it finishes with a variation on it... unsigned i,j; NMatrixInt basis(hom.columns(), hom.columns() ); basis.makeIdentity(); NMatrixInt basisi(hom.columns(), hom.columns() ); basisi.makeIdentity(); // and we proceed to modify it solely via column operations. // one for every column operation performed on homModL NMatrixInt homModL(hom); // set up two lists: the coordinates that correspond to free generators // of the range and coordinates corresponding to torsion generators. // these lists need to be built from L std::vector freeList; std::vector torList; for (i=0;i torCol(0); bool zeroCol; for (i=0; i tBasis( new NMatrixInt( basis.rows(), torCol.size() )); // this will be the // eventual retval. NMatrixInt dummy( torCol.size(), 0 ); // needed when we call // columnEchelonForm. choosing it to have 0 columns speeds up // the algorithm. for (i=0;ientry(i,j) = basis.entry(i, torCol[j]); columnEchelonForm( tHom, *tBasis, dummy, torList ); // so now we have a primitive collection of vectors being sent to the // primitive subspace generated by the torsion lattice in the target. // The idea is to run through the rows, for each non-zero row, through // a basis change we can ensure there is at most one non-zero entry. // multiply this column by the smallest factor so that it is in // the torsion lattice, repeat. etc. unsigned CR=0; // current row under consideration. The actual row index // will of course be torList[CR] since all other rows are already zero. std::vector rowNZlist; // in the current row, this is the list // of column coordinates for the non-zero entries. NLargeInteger d,r; // given two NLargeIntegers a and b, we will represent // a/b by d and a % b by r in the algorithm. NLargeInteger u,v,gcd, a,b; // for column operations u,v,a,b represent // a 2x2 matrix. NLargeInteger tmp; while (CRrows();i++) tBasis->entry( i, rowNZlist[0] ) *= d; // done. CR++; continue; } // case 3: rowNZlist.size()>1.row ops to reduce rowNZlist.size(). // then continue while (rowNZlist.size()>1) { // do column op on columns rowNZlist[0] and rowNZlist[1] // first we need to find the approp modification matrix. This will // be the matrix ( u -b ) where ua+vb = 1. We get a and b from // ( v a ) from entry(torList[CR], r[0]) and // entry(torlist[CR], r[1]) by dividing by their GCD, found with // rowNZlist[0].gcdWithCoeffs(rowNZlist[1],u,v) gcd = tHom.entry(torList[CR], rowNZlist[0]).gcdWithCoeffs( tHom.entry(torList[CR], rowNZlist[1]), u,v); a = tHom.entry(torList[CR], rowNZlist[0]).divExact(gcd); b = tHom.entry(torList[CR], rowNZlist[1]).divExact(gcd); // so multiplication on the right by the above matrix corresponds // to replacing column r[0] by u r[0] + v r[1] and column r[1] by // -b r[0] + a r[1]. for (i=0;irows();i++) { tmp = u * tBasis->entry( i, rowNZlist[0] ) + v * tBasis->entry(i, rowNZlist[1] ); tBasis->entry(i,rowNZlist[1]) = a * tBasis->entry( i, rowNZlist[1]) - b * tBasis->entry( i, rowNZlist[0]); tBasis->entry(i,rowNZlist[0]) = tmp; } // now rowNZlist[1] entry is zero, remove it from the list. rowNZlist.erase( rowNZlist.begin()+1 ); } } return tBasis; } // Lemma 1: [a b | c d] representing an element of End(Z_n x Z_{mn}) is in // Aut(Z_n x Z_{mn}) if and only if dA-bc is a unit of Z_{mn} for some lift // A \in Z_{mn} of a \in Z_n // // You can get an explicit formula for the inverse, basically it boils down // to a comparison with the Z_n^2 case, and the observation that // Z_{mn} --> Z_n is surjective on units. // The algorithm: // // Step 1: reduce all entries mod p_i where i is the row index. // Step 2: Consider the bottom row of A. Consider a group of columns for which // they all share the same p_i. standard Gaussian elimination works to // put zeros in all but one entry of this row. Potential problem here // the 1x1 case where the entry is a unit mod p_1 // Step 3: Now we are in the situation where in this row, any two non-zero // entries have distinct p_i's, where now i is the column index. // Let them be in columns i and n respectively. // Let l_1a_{ni} + l_2a_{nn} = gcd(a_{ni},a_{nn})=g, // consider matrix [ v_n l_1 | -v_i l_2 ] where // v_n = a_{nn}/g and v_i=a_{ni}/g. This is a valid // column operation by Lemma 1 and some congruence munching. // Apply, this reduces this bottom row to the point where it has only // one non-zero entry and it is a unit mod the relevant p_i, // so we can multiply by its inverse // Step 4: repeat inductively to square submatrix above and to the left of the // nn entry. This results in an upper diagonal matrix. // Reapply step 1 gives all 1's down diagonal. // Step 5: row ops to convert to identity. // *Step 6: keep track of all the corresponding matrices, put together to // assemble inverse. Notice it's all standard Gaussian elimination, // just done in a funny order and with some modular arithmatic // stuffed in there. std::auto_ptr torsionAutInverse(const NMatrixInt& input, const std::vector &invF) { // inductive step begins right away. Start at bottom row. NMatrixInt workMat( input ); NMatrixInt colOps( input.rows(), input.columns() ); colOps.makeIdentity(); unsigned long wRow = input.rows(); while (wRow > 0) { wRow--; // step 1 modular reduction on the current row. And find last non-zero // entry in this row up to wRow column NLargeInteger R; // divisionAlg needs a remainder so we give it one, // although we discard it. unsigned long pivCol=0; for (unsigned long i=0; i<=wRow; i++) { workMat.entry(wRow, i).divisionAlg(invF[wRow], R); workMat.entry(wRow, i) = R; if (R!=0) pivCol=i; } // now pivCol is the last non-zero entry in the 0..wRow square smatrix // Step 2: transpose pivCol and column wRow if (wRow != pivCol) for (unsigned long i=0; i 0) { wCol--; NLargeInteger g, l1, l2; g = workMat.entry( wRow, wCol ).gcdWithCoeffs( workMat.entry(wRow, pivCol), l1, l2 ); NLargeInteger u1, u2; u1 = workMat.entry(wRow, wCol).divExact(g); u2 = workMat.entry(wRow, pivCol).divExact(g); // u1 l1 + u2 l2 = 1 // [ u2 l1 | -u1 l2 ] is column op matrix for wCol and pivCol for (unsigned long i=0; i u2 wCol - u1 pivCol, pivCol -> l1 wCol + l2 pivCol NLargeInteger W(workMat.entry(i, wCol)), P(workMat.entry(i, pivCol)); workMat.entry(i, wCol) = u2*W - u1*P; workMat.entry(i, pivCol) = l1*W + l2*P; W = colOps.entry(i, wCol); P = colOps.entry(i, pivCol); colOps.entry(i, wCol) = u2*W - u1*P; colOps.entry(i, pivCol) = l1*W + l2*P; } } // now workMat.entry(wRow, pivCol) is a unit mod invF[pivCol], // so find its inverse NLargeInteger g, a1, a2; g= workMat.entry( wRow, pivCol ).gcdWithCoeffs( invF[pivCol], a1, a2 ); // a1 represents this multiplicative inverse so multiply column by it. for (unsigned long i=0; i identity. Use row i to kill i-th entry of row j. for (unsigned long i=1; ientry(i,j) += colOps.entry(i,k)*rowOps.entry(k,j); retval->entry(i,j) %= invF[i]; if (retval->entry(i,j) < 0) retval->entry(i,j) += invF[i]; } // done return std::auto_ptr(retval); } bool metricFindPivot(const unsigned long &currStage, const NMatrixInt &matrix, unsigned long &pr, unsigned long &pc, const std::vector &rowNorm, const std::vector &colNorm, const std::vector &rowGCD) { bool pivotFound = false; // find the smallest positive rowGCD NLargeInteger SProwGCD(NLargeInteger::zero); for (unsigned long i=currStage; i rowGCD[i].abs()) SProwGCD = rowGCD[i].abs(); } for (unsigned long i=currStage; i 1 we use the rowNorm comparison. else // if rows the same? use colNorm... { if (i == pr) { if ( colNorm[j] < colNorm[pc] ) { pr = i; pc =j; } } else { if ( rowNorm[i] < rowNorm[pr] ) { pr = i; pc = j; } } } } } } return pivotFound; } // switch rows i and j in matrix. Keep track of change-of-basis void metricSwitchRows(const unsigned long &currStage, const unsigned long &i, const unsigned long &j, NMatrixInt &matrix, NMatrixInt *colBasis, NMatrixInt *colBasisInv, std::vector &rowNorm, std::vector &rowGCD) { rowNorm[i].swap(rowNorm[j]); rowGCD[i].swap(rowGCD[j]); if (colBasis) colBasis->swapRows(i, j); if (colBasisInv) colBasisInv->swapColumns(i, j); for (unsigned long k=currStage; k &colNorm) { colNorm[i].swap(colNorm[j]); if (rowBasis) rowBasis->swapColumns(i, j); if (rowBasisInv) rowBasisInv->swapRows(i, j); for (unsigned long k=currStage; k &rowNorm, std::vector &colNorm) { NLargeInteger t1, t2; // smart rowMetric recomputation and transformation colNorm[i] = NLargeInteger::zero; colNorm[j] = NLargeInteger::zero; for (unsigned long k=currStage; kentry(k, i) + c*rowBasis->entry(k, j); t2 = b*rowBasis->entry(k, i) + d*rowBasis->entry(k, j); rowBasis->entry(k, i) = t1; rowBasis->entry(k, j) = t2; } if (rowBasisInv) for (unsigned long k=0; kentry(i, k) - b*rowBasisInv->entry(j, k); t2 = -c*rowBasisInv->entry(i, k) + a*rowBasisInv->entry(j, k); rowBasisInv->entry(i, k) = t1; rowBasisInv->entry(j, k) = t2; } } // row operation using 2x2-matrix [a b|c d] on rows i, j resp. void metricRowOp(const unsigned long &currStage, const unsigned long &i, const unsigned long &j, NMatrixInt &matrix, const NLargeInteger a, const NLargeInteger b, const NLargeInteger c, const NLargeInteger d, NMatrixInt *colBasis, NMatrixInt *colBasisInv, std::vector &rowNorm, std::vector &colNorm, std::vector &rowGCD) { NLargeInteger t1, t2; // smart norm recomputation and transformation rowNorm[i] = NLargeInteger::zero; rowNorm[j] = NLargeInteger::zero; rowGCD[i] = NLargeInteger::zero; rowGCD[j] = NLargeInteger::zero; for (unsigned long k=currStage; kentry(i, k) + b*colBasis->entry(j, k); t2 = c*colBasis->entry(i, k) + d*colBasis->entry(j, k); colBasis->entry(i, k) = t1; colBasis->entry(j, k) = t2; } if (colBasisInv) for (unsigned long k=0; kentry(k, i) - c*colBasisInv->entry(k, j); t2 = -b*colBasisInv->entry(k, i) + a*colBasisInv->entry(k, j); colBasisInv->entry(k, i) = t1; colBasisInv->entry(k, j) = t2; } } /** * This routine converts mxn matrix "matrix" into its Smith Normal Form. * It assumes rowSpaceBasis and rowSpaceBasisInv are pointers to NMatrixInts, * if alloceted, having dimension mxm, and colSpaceBasis and colSpaceBasisInv * has dimensions nxn. These matrices record the row and columns operations * used to convert between "matrix" and its Smith Normal Form. Specifically, * if orig_matrix is "matrix" before metricalSmithNormalForm is called, and * after_matrix is "matrix" after metricalSmithNormalForm is called, then * we have the relations: * * (*colSpaceBasis) * orig_matrix * (*rowSpaceBasis) == after_matrix * * (*colSpaceBasisInv) * after_matrix * (*rowSpaceBasisInv) == orig_matrix * * If any of rowSpaceBasis, colSpaceBasis or rowSpaceBasisInv or * colSpaceBasisInv are not allocated, this algotithm does not bother to compute * them (and is correspondingly faster. * * This routine uses a first-order technique to intelligently choose the * pivot when computing the Smith Normal Form, attempting to keep the matrix * sparse and its norm small throughout the reduction process. The technique * is loosely based on the papers: * * Havas, Holt, Rees. Recognizing badly Presented Z-modules. Linear Algebra * and its Applications. 192:137--163 (1993). * * Markowitz. The elimination form of the inverse and its application to linear * programming. Management Sci. 3:255--269 (1957). */ void metricalSmithNormalForm(NMatrixInt& matrix, NMatrixInt *rowSpaceBasis, NMatrixInt *rowSpaceBasisInv, NMatrixInt *colSpaceBasis, NMatrixInt *colSpaceBasisInv) { if (rowSpaceBasis) rowSpaceBasis->makeIdentity(); if (rowSpaceBasisInv) rowSpaceBasisInv->makeIdentity(); if (colSpaceBasis) colSpaceBasis->makeIdentity(); if (colSpaceBasisInv) colSpaceBasisInv->makeIdentity(); // set up metrics. std::vector rowNorm(matrix.rows(), NLargeInteger::zero); std::vector colNorm(matrix.columns(), NLargeInteger::zero); std::vector rowGCD(matrix.rows(), NLargeInteger::zero); for (unsigned long i=0; ientry( i, currStage ).negate(); if (rowSpaceBasisInv) for (i=0; ientry( currStage, i ).negate(); } // run through rows currStage+1 to bottom, check if divisible by // matrix.entry(cs,cs). if not, record row and gcd( matrix.entry(cs,cs), // rowGCD[this row], pick the row with the lowest of these gcds... unsigned long rowT=currStage; NLargeInteger bestGCD(matrix.entry(currStage, currStage).abs()); for (i=currStage+1; i currStage ) { metricRowOp(currStage, currStage, rowT, matrix, NLargeInteger::one, NLargeInteger::one, NLargeInteger::zero, NLargeInteger::one, colSpaceBasis, colSpaceBasisInv, rowNorm, colNorm, rowGCD); goto rowMuckerLoop; } // done currStage++; } // no pivot found -- matrix down and to the right of currStage is zero. // so we're done. } } // namespace regina regina-4.96/engine/maths/matrixops.h000644 000765 000024 00000037127 12377775260 017422 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #ifndef __MATRIXOPS_H #ifndef __DOXYGEN #define __MATRIXOPS_H #endif /*! \file maths/matrixops.h * \brief Provides various complex matrix calculations. * \todo \featurelong Add a routine to find the rank of an integer * matrix; use this to show the rank of the matching equations. */ #include "regina-core.h" #include "maths/nmatrixint.h" #include namespace regina { /** * \weakgroup maths * @{ */ /** * Transforms the given integer matrix into Smith normal form. * Note that the given matrix need not be square and need not be of full * rank. * * Reading down the diagonal, the final Smith normal form will have a * series of non-negative, non-decreasing invariant factors followed by * zeroes. "Invariant factor" refers to the convention that the ith * term divides the (i+1)th term, and so they are unique. * * The algorithm used is due to Hafner and McCurley (1991). * It does not use modular arithmetic to control the intermediate * coefficient explosion. * * @param matrix the matrix to transform. */ REGINA_API void smithNormalForm(NMatrixInt& matrix); /** * A Smith normal form algorithm that also returns change of basis matrices. * * This is a modification of the one-argument smithNormalForm(NMatrixInt&). * As well as converting the given matrix \a matrix into Smith normal form, * it also returns the appropriate change-of-basis matrices corresponding * to all the row and column operations that were performed. * * The only input argument is \a matrix. The four remaining arguments * (the change of basis matrices) will be refilled, though they must be * constructed with the correct dimensions as seen in the preconditions * below. All five arguments are used to return information as follows. * * Let \a M be the initial value of \a matrix, and let \a S be the Smith * normal form of \a M. After this routine exits: * * - The argument \a matrix will contain the Smith normal form \a S; * - colSpaceBasis * M * rowSpaceBasis = S; * - colSpaceBasisInv * S * rowSpaceBasisInv = M; * - colSpaceBasis * colSpaceBasisInv and * rowSpaceBasis * rowSpaceBasisInv are both identity matrices. * * Thus, one obtains the Smith normal form the original matrix by multiplying * on the left by ColSpaceBasis and on the right by RowSpaceBasis. * * \pre The matrices \a rowSpaceBasis and \a rowSpaceBasisInv that are * passed are square, with side length matrix.columns(). * \pre The matrices \a colSpaceBasis and \a colSpaceBasisInv that are * passed are square, with side length matrix.rows(). * * @param matrix the original matrix to put into Smith Normal Form (this * need not be square). When the algorithm terminates, this matrix \e is * in its Smith Normal Form. * @param rowSpaceBasis used to return a change of basis matrix (see * above for details). * @param rowSpaceBasisInv used to return the inverse of \a rowSpaceBasis. * @param colSpaceBasis used to return a change of basis matrix (see * above for details). * @param colSpaceBasisInv used to return the inverse of \a colSpaceBasis. * * \author Ryan Budney */ REGINA_API void smithNormalForm(NMatrixInt& matrix, NMatrixInt& rowSpaceBasis, NMatrixInt& rowSpaceBasisInv, NMatrixInt& colSpaceBasis, NMatrixInt& colSpaceBasisInv); /** * An alternative Smith normal form algorithm that also returns change of * basis matrices. This routine may be preferable for extremely large * matrices. This is a variant of Hafner-McCurley and Havas-Holt-Rees's * description of pivoting methods. * * The only input argument is \a matrix. The four remaining arguments * (the change of basis matrices), if passed, will be refilled, though they * must be constructed with the correct dimensions as seen in the preconditions * below. All five arguments are used to return information as follows. * * Let \a M be the initial value of \a matrix, and let \a S be the Smith * normal form of \a M. After this routine exits: * * - The argument \a matrix will contain the Smith normal form \a S; * - colSpaceBasis * M * rowSpaceBasis = S; * - colSpaceBasisInv * S * rowSpaceBasisInv = M; * - colSpaceBasis * colSpaceBasisInv and * rowSpaceBasis * rowSpaceBasisInv are both identity matrices. * * Thus, one obtains the Smith normal form the original matrix by multiplying * on the left by ColSpaceBasis and on the right by RowSpaceBasis. * * \pre The matrices \a rowSpaceBasis and \a rowSpaceBasisInv, if passed, * must be square with side length matrix.columns(). * \pre The matrices \a colSpaceBasis and \a colSpaceBasisInv, if passed, * must be square, with side length matrix.rows(). * * @param matrix the original matrix to put into Smith Normal Form (this * need not be square). When the algorithm terminates, this matrix \e is * in its Smith Normal Form. * @param rowSpaceBasis used to return a change of basis matrix (see * above for details). This is optional; you may pass a null pointer instead. * @param rowSpaceBasisInv used to return the inverse of \a rowSpaceBasis. * This is optional; you may pass a null pointer instead. * @param colSpaceBasis used to return a change of basis matrix (see * above for details). This is optional; you may pass a null pointer instead. * @param colSpaceBasisInv used to return the inverse of \a colSpaceBasis. * This is optional; you may pass a null pointer instead. * * \author Ryan Budney */ REGINA_API void metricalSmithNormalForm(NMatrixInt& matrix, NMatrixInt *rowSpaceBasis=0, NMatrixInt *rowSpaceBasisInv=0, NMatrixInt *colSpaceBasis=0, NMatrixInt *colSpaceBasisInv=0); /** * Find a basis for the row space of the given matrix. * * This routine will rearrange the rows of the given matrix so that the * first \a rank rows form a basis for the row space (where \a rank is * the rank of the matrix). The rank itself will be returned. No other * changes will be made to the matrix aside from swapping rows. * * Although this routine takes an integer matrix (and only uses integer * operations), we consider the row space to be over the \e rationals. * That is, although we never divide, we act as though we could if we * wanted to. * * @param matrix the matrix to examine and rearrange. * @return the rank of the given matrix. */ REGINA_API unsigned rowBasis(NMatrixInt& matrix); /** * Finds a basis for the row space of the given matrix, as well as an * "incremental" basis for its orthogonal complement. * * This routine takes an (\a r by \a c) matrix \a input, as well as a * square (\a c by \a c) matrix \a complement, and does the following: * * - The rows of \a input are rearranged so that the first \a rank rows form * a basis for the row space (where \a rank is the rank of the matrix). * No other changes are made to this matrix aside from swapping rows. * * - The matrix \a complement is re-filled (any previous contents are * thrown away) so that, for any \a i between 0 and \a rank-1 inclusive, * the final (\a c - \a i) rows of \a complement form a basis for the * orthogonal complement of the first \a i rows of the rearranged \a input. * * - The rank of the matrix \a input is returned from this routine. * * This routine can help with larger procedures that need to build up a row * space and simultaneously cut down the complement one dimension at a time. * * Although this routine takes integer matrices (and only uses integer * operations), we consider all bases to be over the \e rationals. * That is, although we never divide, we act as though we could if we * wanted to. * * \pre The matrix \a complement is a square matrix, whose size is equal * to the number of columns in \a input. * * @param input the input matrix whose row space we will describe; this * matrix will be changed (though only by swapping rows). * @param complement the square matrix that will be re-filled with the * "incremental" basis for the orthogonal complement of \a input. * @return the rank of the given matrix \a input. */ REGINA_API unsigned rowBasisAndOrthComp(NMatrixInt& input, NMatrixInt& complement); /** * Transforms a given matrix into column echelon form with respect to a * collection of rows. * * Given the matrix \a M and the list \a rowList of rows from \a M, this * algorithm puts \a M in column echelon form with respect to the rows * in \a rowList. The only purpose of \a rowList is to clarify and/or * weaken precisely what is meant by "column echelon form"; all rows of * \a M are affected by the resulting column operations that take place. * * This routine also returns the corresponding change of coordinate * matrices \a R and \a Ri: * * - If \a R and \a Ri are passed as identity matrices, the returned * matrices will be such that original_M * R = final_M and * final_M * Ri = original_M (and of course final_M is * in column echelon form with respect to the given row list). * - If \a R and \a Ri are already non-trivial coordinate transformations, * they are modified appropriately by the algorithm. * * Our convention is that a matrix is in column echelon form if: * * -# each column is either zero or there is a first non-zero entry which * is positive (but see the note regarding \a rowList below); * -# moving from the leftmost column to the rightmost column, the rows * containing the first non-zero entries for these columns have strictly * increasing indices in \a rowList; * -# given a first non-zero column entry, in that row all the elements to * the left are smaller and non-negative (all elements to the right are * already zero by the previous condition); * -# all the zero columns are on the right hand side of the matrix. * * By a "zero column" here we simply mean "zero for every row in \a * rowList". Likewise, by "first non-zero entry" we mean "first row in * \a rowList with a non-zero entry". * * In a pinch, you can also use this routine to compute the inverse of an * invertible square matrix. * * \pre Both \a R and \a Ri are square matrices with side length M.columns(), * and these matrices are inverses of each other. * * \ifacespython The argument \a rowList should be supplied as a python list. * * @param M the matrix to reduce. * @param R used to return the row-reduction matrix, as described above. * @param Ri used to return the inverse of \a R. * @param rowList the rows to pay attention to. This list must contain * distinct integers, all between 0 and M.rows()-1 inclusive. The * integers may appear in any order (though changing the order will * change the resulting column echelon form). * * \author Ryan Budney */ REGINA_API void columnEchelonForm(NMatrixInt &M, NMatrixInt &R, NMatrixInt &Ri, const std::vector &rowList); /** * Given a homomorphism from Z^n to Z^k and a sublattice of Z^k, * compute the preimage of this sublattice under this homomorphism. * * The homomorphism from Z^n to Z^k is described by the given * \a k by \a n matrix \a hom. The sublattice is of the form * (p1 Z) * (p2 Z) * ... * (pk Z), where the non-negative integers * \a p1, ..., \a pk are passed in the given list \a sublattice. * * An equivalent problem is to consider \a hom to be a homomorphism * from Z^n to Z_p1 + ... + Z_pk; this routine then finds the kernel * of this homomorphism. * * The preimage of the sublattice (equivalently, the kernel described * above) is some rank \a n lattice in Z^n. This algorithm finds and * returns a basis for the lattice. * * \ifacespython The argument \a sublattice should be supplied as a python list. * * @param hom the matrix representing the homomorphism from Z^n to Z^k; * this must be a \a k by \a n matrix. * @param sublattice a list of length \a k describing the sublattice of Z^k; * the elements of this list must be the non-negative integers * \a p1, ..., \a pk as described above. * @return a new matrix whose columns are a basis for the preimage lattice. * This matrix will have precisely \a n rows. * * \author Ryan Budney */ REGINA_API std::auto_ptr preImageOfLattice(const NMatrixInt& hom, const std::vector& sublattice); /** * Given an automorphism of an abelian group, * this procedure computes the inverse automorphism. * * The abelian group is of the form Z_p1 + Z_p2 + ... + Z_pn. * The input is an n-by-n matrix \a A which represents a lift of the * automorphism to just some n-by-n matrix. Specifically, you have a little * commutative diagram with Z^n --A--> Z^n covering the automorphism * of Z_p1 + Z_p2 + ... + Z_pn, where the maps down are the direct * sum of the standard quotients Z --> Z_pi. So if you want this * procedure to give you meaningful output, \a A must be a lift of a genuine * automorphism of Z_p1 + ... + Z_pn. * * \pre The list p1, p2, ..., pn is a list of invariant factors, * which means that p1|p2, ..., p{n-1}|pn. * * \ifacespython The argument \a invF should be supplied as a python list. * * @param input the n-by-n matrix \a A, which must be a lift of a genuine * automorphism as described above. * @param invF the list p1, p2, ..., pn. * @return the inverse automorphism, also described as an n-by-n matrix * as per the discussion above. * * \author Ryan Budney */ REGINA_API std::auto_ptr torsionAutInverse(const NMatrixInt& input, const std::vector &invF); /*@}*/ } // namespace regina #endif regina-4.96/engine/maths/ninteger.cpp000644 000765 000024 00000104365 12377776625 017547 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include "maths/ninteger.h" #include "maths/numbertheory.h" #include "utilities/nthread.h" // We instantiate both variants of the NIntegerBase template at the bottom // of this file. /** * Old macros for testing signed integer overflow, given in order from * fastest to slowest (by experimentation). All are based on section * 2-21 from Hacker's Delight by Warren. * * These tests are all abandoned now because the 128-bit cast solution is * significantly faster than any of these. * * Note that a slicker test (such as checking whether answer / y == x) is * not possible, because compiler optimisations are too clever nowadays * and strip out the very tests we are trying to perform * (e.g., whether (x * y) / y == x). * * - Ben, 19/08/2013. * #define LONG_OVERFLOW(x, y) \ (((x) > 0 && ( \ ((y) > 0 && (y) > LONG_MAX / (x)) || \ (y) < 0 && (y) < LONG_MIN / (x))) || \ ((x) < 0 && ( \ ((y) > 0 && (x) < LONG_MIN / (y)) || \ ((y) < 0 && (x) < LONG_MAX / (y))))) #define LONG_OVERFLOW(x, y) \ (((x) > 0 && (y) > 0 && (y) > LONG_MAX / (x)) || \ ((x) > 0 && (y) < 0 && (y) < LONG_MIN / (x)) || \ ((x) < 0 && (y) > 0 && (x) < LONG_MIN / (y)) || \ ((x) < 0 && (y) < 0 && (x) < LONG_MAX / (y))) #define LONG_OVERFLOW(x, y) \ ((y) && labs(x) > (((~((x) ^ (y))) >> (sizeof(long)*8-1)) / labs(y))) */ namespace regina { namespace { /** * Global variables for the GMP random state data. */ NMutex randMutex; gmp_randstate_t randState; bool randInitialised(false); } // Initialize const static data: template const NIntegerBase NIntegerBase::zero; template const NIntegerBase NIntegerBase::one(1); template <> const NIntegerBase NIntegerBase::infinity(false, false); // The use of errno in this file should be threadsafe, since (as I // understand it) each thread gets its own errno. However, there may be // thread safety issues regarding locales when using strtol(), in // particular when another thread changes the locale mid-flight. // I could be wrong about this. template NIntegerBase::NIntegerBase( const char* value, int base, bool* valid) : large_(0) { char* endptr; errno = 0; small_ = strtol(value, &endptr, base); if (errno || *endptr) { // Something went wrong. Try again with large integers. // Note that in the case of overflow, we may have errno != 0 but // *endptr == 0. bool maybeTrailingWhitespace = (*endptr && ! errno); large_ = new mpz_t; if (valid) *valid = (mpz_init_set_str(large_, value, base) == 0); else mpz_init_set_str(large_, value, base); // If the error was just trailing whitespace, we might still fit // into a native long. if (maybeTrailingWhitespace) tryReduce(); } else { // All good. if (valid) *valid = true; } } template NIntegerBase::NIntegerBase( const std::string& value, int base, bool* valid) : large_(0) { char* endptr; errno = 0; small_ = strtol(value.c_str(), &endptr, base); if (errno || *endptr) { // Something went wrong. Try again with large integers. // Note that in the case of overflow, we may have errno != 0 but // *endptr == 0. bool maybeTrailingWhitespace = (*endptr && ! errno); large_ = new mpz_t; if (valid) *valid = (mpz_init_set_str(large_, value.c_str(), base) == 0); else mpz_init_set_str(large_, value.c_str(), base); // If the error was just trailing whitespace, we might still fit // into a native long. if (maybeTrailingWhitespace) tryReduce(); } else { // All good. if (valid) *valid = true; } } template std::string NIntegerBase::stringValue(int base) const { if (isInfinite()) return "inf"; else if (large_) { char* str = mpz_get_str(0, base, large_); std::string ans(str); free(str); return ans; } else { // Hmm. std::setbase() only takes 8, 10 or 16 as i understand it. // For now, be wasteful and always go through GMP. mpz_t tmp; mpz_init_set_si(tmp, small_); char* str = mpz_get_str(0, base, tmp); std::string ans(str); free(str); mpz_clear(tmp); return ans; } } template NIntegerBase& NIntegerBase::operator =( const char* value) { makeFinite(); char* endptr; errno = 0; small_ = strtol(value, &endptr, 10 /* base */); if (errno || *endptr) { // Something went wrong. Try again with large integers. // Note that in the case of overflow, we may have errno != 0 but // *endptr == 0. bool maybeTrailingWhitespace = (*endptr && ! errno); if (large_) mpz_set_str(large_, value, 10 /* base */); else { large_ = new mpz_t; mpz_init_set_str(large_, value, 10 /* base */); } // If the error was just trailing whitespace, we might still fit // into a native long. if (maybeTrailingWhitespace) tryReduce(); } else if (large_) { // All good, but we must clear out the old large integer. clearLarge(); } return *this; } template std::ostream& operator << (std::ostream& out, const NIntegerBase& i) { if (i.isInfinite()) out << "inf"; else if (i.large_) { char* str = mpz_get_str(0, 10, i.large_); out << str; free(str); } else out << i.small_; return out; } template NIntegerBase& NIntegerBase::operator +=(long other) { if (isInfinite()) return *this; if (! large_) { // Use native arithmetic if we can. if ( (small_ > 0 && other > (LONG_MAX - small_)) || (small_ < 0 && other < (LONG_MIN - small_))) { // Boom. It's an overflow. // Fall back to large integer arithmetic in the next block. forceLarge(); } else { // All good: we're done. small_ += other; return *this; } } // And now we're down to large integer arithmetic. // The following code should work even if other == LONG_MIN (in which case // -other == LONG_MIN also), since passing -other to mpz_sub_ui casts it // to an unsigned long (and gives it the correct positive value). if (other >= 0) mpz_add_ui(large_, large_, other); else mpz_sub_ui(large_, large_, -other); return *this; } template NIntegerBase& NIntegerBase::operator -=(long other) { if (isInfinite()) return *this; if (! large_) { // Use native arithmetic if we can. if ( (other > 0 && small_ < (LONG_MIN + other)) || (other < 0 && small_ > (LONG_MAX + other))) { // Boom. It's an overflow. // Fall back to large integer arithmetic in the next block. forceLarge(); } else { // All good: we're done. small_ -= other; return *this; } } // And now we're down to large integer arithmetic. // The following code should work even if other == LONG_MIN (in which case // -other == LONG_MIN also), since passing -other to mpz_add_ui casts it // to an unsigned long (and gives it the correct positive value). if (other >= 0) mpz_sub_ui(large_, large_, other); else mpz_add_ui(large_, large_, -other); return *this; } template NIntegerBase& NIntegerBase::operator *=( const NIntegerBase& other) { if (isInfinite()) return *this; else if (other.isInfinite()) { makeInfinite(); return *this; } if (large_) { if (other.large_) mpz_mul(large_, large_, other.large_); else mpz_mul_si(large_, large_, other.small_); } else if (other.large_) { large_ = new mpz_t; mpz_init(large_); mpz_mul_si(large_, other.large_, small_); } else { typedef typename IntOfSize<2 * sizeof(long)>::type Wide; Wide ans = static_cast(small_) * static_cast(other.small_); if (ans > LONG_MAX || ans < LONG_MIN) { // Overflow. large_ = new mpz_t; mpz_init_set_si(large_, small_); mpz_mul_si(large_, large_, other.small_); } else small_ = static_cast(ans); } return *this; } template NIntegerBase& NIntegerBase::operator *=(long other) { if (isInfinite()) return *this; if (large_) mpz_mul_si(large_, large_, other); else { typedef IntOfSize<2 * sizeof(long)>::type Wide; Wide ans = static_cast(small_) * static_cast(other); if (ans > LONG_MAX || ans < LONG_MIN) { // Overflow. large_ = new mpz_t; mpz_init_set_si(large_, small_); mpz_mul_si(large_, large_, other); } else small_ = static_cast(ans); } return *this; } template NIntegerBase& NIntegerBase::operator /=( const NIntegerBase& other) { if (isInfinite()) return *this; if (other.isInfinite()) return (*this = 0); if (supportInfinity && other.isZero()) { makeInfinite(); return *this; } if (other.large_) { if (large_) { mpz_tdiv_q(large_, large_, other.large_); return *this; } // This is a native C/C++ long. // One of four things must happen: // (i) |other| > |this|, in which case the result = 0; // (ii) this = LONG_MIN and OTHER = -1, in which case the result // is the large integer -LONG_MIN; // (iii) this = LONG_MIN and OTHER is the large integer -LONG_MIN, // in which case the result = -1; // (iv) other can be converted to a native long, and the result // is a native long also. // // Deal with the problematic LONG_MIN case first. if (small_ == LONG_MIN) { if (! mpz_cmp_ui(other.large_, LONG_MIN /* casting to unsigned makes this -LONG_MIN */)) { small_ = -1; return *this; } if (! mpz_cmp_si(other.large_, -1)) { // The result is -LONG_MIN, which requires large integers. // Reduce other while we're at it. const_cast&>(other).forceReduce(); large_ = new mpz_t; mpz_init_set_si(large_, LONG_MIN); mpz_neg(large_, large_); return *this; } if (mpz_cmp_ui(other.large_, LONG_MIN /* cast to ui makes this -LONG_MIN */) > 0 || mpz_cmp_si(other.large_, LONG_MIN) < 0) { small_ = 0; return *this; } // other is in [ LONG_MIN, -LONG_MIN ) \ {-1}. // Reduce it and use native arithmetic. const_cast&>(other).forceReduce(); small_ /= other.small_; return *this; } // From here we have this in ( LONG_MIN, -LONG_MIN ). if (small_ >= 0) { if (mpz_cmp_si(other.large_, small_) > 0 || mpz_cmp_si(other.large_, -small_) < 0) { small_ = 0; return *this; } } else { // We can negate, since small_ != LONG_MIN. if (mpz_cmp_si(other.large_, -small_) > 0 || mpz_cmp_si(other.large_, small_) < 0) { small_ = 0; return *this; } } // We can do this all in native longs from here. // Opportunistically reduce other, since we know we can. const_cast&>(other).forceReduce(); small_ /= other.small_; return *this; } else return (*this) /= other.small_; } template NIntegerBase& NIntegerBase::operator /=(long other) { if (isInfinite()) return *this; if (supportInfinity && other == 0) { makeInfinite(); return *this; } if (large_) { if (other >= 0) mpz_tdiv_q_ui(large_, large_, other); else { // The cast to (unsigned long) makes this correct even if // other = LONG_MIN. mpz_tdiv_q_ui(large_, large_, - other); mpz_neg(large_, large_); } } else if (small_ == LONG_MIN && other == -1) { // This is the special case where we must switch from native to // large integers. large_ = new mpz_t; mpz_init_set_si(large_, LONG_MIN); mpz_neg(large_, large_); } else { // We can do this entirely in native arithmetic. small_ /= other; } return *this; } template NIntegerBase& NIntegerBase::divByExact( const NIntegerBase& other) { if (other.large_) { if (large_) { mpz_divexact(large_, large_, other.large_); return *this; } // This is a native C/C++ long. // Because we are guaranteed other | this, it follows that // other must likewise fit within a native long, or else // (i) this == 0, or (ii) this == LONG_MIN and other == -LONG_MIN. // It also follows that the result must fit within a native long, // or else this == LONG_MIN and other == -1. if (small_ == 0) { // 0 / anything = 0 (we know from preconditions that other != 0). return *this; } else if (small_ == LONG_MIN) { if (! mpz_cmp_ui(other.large_, LONG_MIN /* casting to unsigned makes this -LONG_MIN */)) { // The result is -1, since we have LONG_MIN / -LONG_MIN. small_ = -1; return *this; } // At this point we know that other fits within a native long. // Opportunistically reduce its representation. const_cast&>(other).forceReduce(); if (other.small_ == -1) { // The result is -LONG_MIN, which requires large integers. large_ = new mpz_t; mpz_init_set_si(large_, LONG_MIN); mpz_neg(large_, large_); } else { // The result will fit within a native long also. small_ /= other.small_; } return *this; } // Here we know that other always fits within a native long, // and so does the result. // Opportunisticaly reduce the representation of other, since // we know we can. const_cast&>(other).forceReduce(); small_ /= other.small_; return *this; } else { // other is already a native int. // Use the native version of this routine instead. return divByExact(other.small_); } } template NIntegerBase& NIntegerBase::divByExact(long other) { if (large_) { if (other >= 0) mpz_divexact_ui(large_, large_, other); else { // The cast to (unsigned long) makes this correct even if // other = LONG_MIN. mpz_divexact_ui(large_, large_, - other); mpz_neg(large_, large_); } } else if (small_ == LONG_MIN && other == -1) { // This is the special case where we must switch from native to // large integers. large_ = new mpz_t; mpz_init_set_si(large_, LONG_MIN); mpz_neg(large_, large_); } else { // We can do this entirely in native arithmetic. small_ /= other; } return *this; } template NIntegerBase& NIntegerBase::operator %=( const NIntegerBase& other) { if (other.large_) { if (large_) { mpz_tdiv_r(large_, large_, other.large_); return *this; } // We fit into a native long. Either: // (i) |other| > |this|, in which case the result is just this; // (ii) |other| == |this|, in which case the result is 0; // (iii) |other| < |this|, in which case we can convert // everything to native C/C++ integer arithmetic. // Test other <=> |this|: int res = (small_ >= 0 ? mpz_cmp_si(other.large_, small_) : mpz_cmp_ui(other.large_, - small_) /* ui cast makes this work even if small_ = LONG_MIN */); if (res > 0) return *this; if (res == 0) { small_ = 0; return *this; } // Test other <=> -|this|: res = (small_ >= 0 ? mpz_cmp_si(other.large_, - small_) : mpz_cmp_si(other.large_, small_)); if (res < 0) return *this; if (res == 0) { small_ = 0; return *this; } // Everything can be made native integer arithmetic. // Opportunistically reduce other while we're at it. const_cast&>(other).forceReduce(); // Some compilers will crash on LONG_MIN % -1, sigh. if (other.small_ == -1) small_ = 0; else small_ %= other.small_; return *this; } else return (*this) %= other.small_; } template NIntegerBase& NIntegerBase::operator %=(long other) { // Since |result| < |other|, whatever happens we can fit the result // into a native C/C++ long. if (large_) { // We can safely cast other to an unsigned long, because the rounding // rules imply that (this % LONG_MIN) == (this % -LONG_MIN). mpz_tdiv_r_ui(large_, large_, other >= 0 ? other : -other); forceReduce(); } else { // All native arithmetic from here. // Some compilers will crash on LONG_MIN % -1, sigh. if (other == -1) small_ = 0; else small_ %= other; } return *this; } template void NIntegerBase::raiseToPower(unsigned long exp) { if (exp == 0) (*this) = one; else if (! isInfinite()) { if (large_) { // Outsource it all to MPI. mpz_pow_ui(large_, large_, exp); } else { // Implement fast modular exponentiation ourselves. NIntegerBase base(*this); *this = 1; while (exp) { // INV: desired result = (base ^ exp) * this. if (exp & 1) (*this) *= base; exp >>= 1; base *= base; } } } } template void NIntegerBase::gcdWith( const NIntegerBase& other) { if (large_) { if (other.large_) { mpz_gcd(large_, large_, other.large_); } else { mpz_t tmp; mpz_init_set_si(tmp, other.small_); mpz_gcd(large_, large_, tmp); mpz_clear(tmp); } mpz_abs(large_, large_); } else if (other.large_) { makeLarge(); mpz_gcd(large_, large_, other.large_); mpz_abs(large_, large_); } else { // Both integers are native. long a = small_; long b = other.small_; if ((a == LONG_MIN && (b == LONG_MIN || b == 0)) || (b == LONG_MIN && a == 0)) { // gcd(a,b) = LONG_MIN, which means we can't make it // non-negative without switching to large integers. large_ = new mpz_t; mpz_init_set_si(large_, LONG_MIN); mpz_neg(large_, large_); return; } if (a == LONG_MIN) { a >>= 1; // Won't affect the gcd, but allows us to negate. } else if (b == LONG_MIN) { b >>= 1; // Won't affect the gcd, but allows us to negate. } if (a < 0) a = -a; if (b < 0) b = -b; /** * Now everything is non-negative. * The following code is based on Stein's binary GCD algorithm. */ if (! a) { small_ = b; return; } if (! b) { small_ = a; return; } // Compute the largest common power of 2. int pow2; for (pow2 = 0; ! ((a | b) & 1); ++pow2) { a >>= 1; b >>= 1; } // Strip out all remaining powers of 2 from a and b. while (! (a & 1)) a >>= 1; while (! (b & 1)) b >>= 1; while (a != b) { // INV: a and b are both odd and non-zero. if (a < b) { b -= a; do b >>= 1; while (! (b & 1)); } else { a -= b; do a >>= 1; while (! (a & 1)); } } small_ = (a << pow2); } } template void NIntegerBase::lcmWith( const NIntegerBase& other) { if (isZero()) return; if (other.isZero()) { if (large_) clearLarge(); small_ = 0; return; } NIntegerBase gcd(*this); gcd.gcdWith(other); divByExact(gcd); (*this) *= other; } template NIntegerBase NIntegerBase::gcdWithCoeffs( const NIntegerBase& other, NIntegerBase& u, NIntegerBase& v) const { // TODO: Implement properly for native types. const_cast(*this).makeLarge(); const_cast(other).makeLarge(); u.makeLarge(); v.makeLarge(); // TODO: Fix for natives: // regina::gcdWithCoeffs(small_, other.small_, u.small_, v.small_); // TODO: Escalate to GMP if anyone is equal to MINLONG. // Otherwise smalls are fine, but check gmpWithCoeffs() for overflow. NIntegerBase ans; ans.makeLarge(); // Check for zero arguments. if (isZero()) { u = 0L; if (other.isZero()) { v = 0L; // ans is already zero. return ans; } v = 1; ans = other; if (ans < 0) { v.negate(); ans.negate(); } return ans; } if (other.isZero()) { v = 0L; u = 1; ans = *this; if (ans < 0) { u.negate(); ans.negate(); } return ans; } // Neither argument is zero. // Run the gcd algorithm. mpz_gcdext(ans.large_, u.large_, v.large_, large_, other.large_); // Ensure the gcd is positive. if (ans < 0) { ans.negate(); u.negate(); v.negate(); } // Get u and v in the correct range. NIntegerBase addToU(other); NIntegerBase addToV(*this); addToU.divByExact(ans); addToV.divByExact(ans); if (addToV < 0) addToV.negate(); else addToU.negate(); // We can add (addToU, addToV) to u and v. // We also know that addToV is positive. // Add enough copies to make v*sign(other) just non-positive. NIntegerBase copies(v); if (other > 0) { // v must be just non-positive. if (v > 0) { copies -= 1; copies /= addToV; copies.negate(); copies -= 1; } else { copies /= addToV; copies.negate(); } } else { // v must be just non-negative. if (v < 0) { copies += 1; copies /= addToV; copies.negate(); copies += 1; } else { copies /= addToV; copies.negate(); } } addToU *= copies; addToV *= copies; u += addToU; v += addToV; return ans; } template NIntegerBase NIntegerBase::divisionAlg( const NIntegerBase& divisor, NIntegerBase& remainder) const { if (divisor.isZero()) { remainder = *this; return zero; } // Preconditions state that nothing is infinite, and we've dealt with d=0. NIntegerBase quotient; // Throughout the following code: // - GMP mpz_fdiv_qr() could give a negative remainder, but that this // will only ever happen if the divisor is also negative. // - native integer division could leave a negative remainder // regardless of the sign of the divisor (I think the standard // indicates that the decision is based on the sign of *this?). if (large_) { // We will have to use GMP routines. quotient.makeLarge(); remainder.makeLarge(); if (divisor.large_) { // Just pass everything straight through to GMP. mpz_fdiv_qr(quotient.large_, remainder.large_, large_, divisor.large_); if (remainder < 0) { remainder -= divisor; ++quotient; } } else { // Put the divisor in GMP format for the GMP routines to use. mpz_t divisorGMP; mpz_init_set_si(divisorGMP, divisor.small_); mpz_fdiv_qr(quotient.large_, remainder.large_, large_, divisorGMP); mpz_clear(divisorGMP); // The remainder must fit into a long, since // 0 <= remainder < |divisor|. remainder.forceReduce(); if (remainder.small_ < 0) { remainder.small_ -= divisor.small_; ++quotient; } } } else { // This integer fits into a long. if (divisor.large_) { // Cases: // // 1) Divisor needs to be large (does not fit into long). // Subcases: // 1a) |divisor| > |this|. // --> quotient = -1/0/+1, remainder is large. // 1b) divisor = |LONG_MIN| and this = LONG_MIN. // --> quotient = -1, remainder = 0. // // 2) Otherwise, divisor actually fits into a long. // Fall through to the next code block. // // NOTE: Be careful not to take -small_ when small_ is negative! if (small_ >= 0 && (divisor > small_ || divisor < -small_)) { quotient = 0; remainder = small_; } else if (small_ < 0 && divisor < small_) { quotient = 1; remainder = small_; remainder -= divisor; } else if (small_ < 0 && -divisor < small_) { quotient = -1; remainder = small_; remainder += divisor; } else if (small_ == LONG_MIN && -divisor == small_) { quotient = -1; remainder = 0; } else { // Since we know we can reduce divisor to a native integer, // be kind: cast away the const and reduce it. const_cast(divisor).forceReduce(); // Fall through to the next block. } } if (! divisor.large_) { // Here we know divisor fits into a long. // Thus remainder also fits into a long, since // 0 <= |remainder| < |divisor|. // // Cases: // 1) quotient = |LONG_MIN|. // Only happens if this = LONG_MIN, divisor = -1. // 2) |quotient| < |LONG_MIN| --> quotient fits into a long also. if (small_ == LONG_MIN && divisor.small_ == -1) { quotient = LONG_MIN; quotient.negate(); remainder = 0; } else { quotient = small_ / divisor.small_; remainder = small_ - (quotient.small_ * divisor.small_); if (remainder.small_ < 0) { if (divisor.small_ > 0) { remainder.small_ += divisor.small_; --quotient; } else { remainder.small_ -= divisor.small_; ++quotient; } } } } } return quotient; } template int NIntegerBase::legendre( const NIntegerBase& p) const { // For now, just do this entirely through GMP. mpz_ptr gmp_this = large_; mpz_ptr gmp_p = p.large_; if (! large_) { gmp_this = new mpz_t; mpz_init_set_si(gmp_this, small_); } if (! p.large_) { gmp_p = new mpz_t; mpz_init_set_si(gmp_p, p.small_); } int ans = mpz_legendre(gmp_this, gmp_p); if (! large_) { mpz_clear(gmp_this); delete gmp_this; } if (! p.large_) { mpz_clear(gmp_p); delete gmp_p; } return ans; } template NIntegerBase NIntegerBase::randomBoundedByThis() const { NMutex::MutexLock ml(randMutex); if (! randInitialised) { gmp_randinit_default(randState); randInitialised = true; } NIntegerBase retval; retval.makeLarge(); if (large_) mpz_urandomm(retval.large_, randState, large_); else { // Go through GMP anyway, for the rand() routine, so that all // our random number generators use a consistent algorithm. mpz_t tmp; mpz_init_set_si(tmp, small_); mpz_urandomm(retval.large_, randState, tmp); mpz_clear(tmp); // Since this fits within a long, the result will also. retval.forceReduce(); } return retval; } template NIntegerBase NIntegerBase::randomBinary(unsigned long n) { NMutex::MutexLock ml(randMutex); if (! randInitialised) { gmp_randinit_default(randState); randInitialised = true; } NIntegerBase retval; retval.makeLarge(); mpz_urandomb(retval.large_, randState, n); // If n bits will fit within a signed long, reduce. if (n < sizeof(long) * 8) retval.forceReduce(); return retval; } template NIntegerBase NIntegerBase::randomCornerBinary(unsigned long n) { NMutex::MutexLock ml(randMutex); if (! randInitialised) { gmp_randinit_default(randState); randInitialised = true; } NIntegerBase retval; retval.makeLarge(); mpz_rrandomb(retval.large_, randState, n); // If n bits will fit within a signed long, reduce. if (n < sizeof(long) * 8) retval.forceReduce(); return retval; } // Instantiate the templates! template class NIntegerBase; template class NIntegerBase; template std::ostream& operator << (std::ostream&, const NIntegerBase&); template std::ostream& operator << (std::ostream&, const NIntegerBase&); } // namespace regina regina-4.96/engine/maths/ninteger.h000644 000765 000024 00000364301 12377775262 017206 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #ifndef __NINTEGER_H #ifndef __DOXYGEN #define __NINTEGER_H #endif /*! \file maths/ninteger.h * \brief Provides arbitrary-precision and fixed-precision integer types. */ #include #include #include // MPIR (and thus SAGE) needs this *before* gmp.h. #include #include #include #include "regina-core.h" #include "utilities/intutils.h" /** * \hideinitializer * * An internal copy of the GMP signed comparison optimisations. * This macro should not be used outside this class. * * By making our own copy of such optimisation macros we can use * C++-style casts instead of C-style casts and avoid noisy compiler * warnings. I'd love a better way of doing this. */ #ifdef __GNUC__ #define mpz_cmp_si_cpp(z, si) \ (__builtin_constant_p(si) && (si) == 0 ? mpz_sgn(z) : \ __builtin_constant_p(si) && (si) > 0 ? _mpz_cmp_ui(z, \ static_cast(si)) : \ _mpz_cmp_si(z, si)) #else #define mpz_cmp_si_cpp(z, si) _mpz_cmp_si(z, si) #endif namespace regina { /** * \weakgroup maths * @{ */ template class NNativeInteger; /** * Internal base classes for use with NIntegerBase, templated on whether we * should support infinity as an allowed value. * * See the NIntegerBase class notes for details. */ template struct InfinityBase; #ifndef __DOXYGEN /** * An internal base class inherited by NLargeInteger, which provides * support for infinity as an allowed value. */ template <> struct InfinityBase { bool infinite_; /**< Does this integer represent infinity? */ /** * Default constructor that sets this integer to be finite. */ inline InfinityBase() : infinite_(false) { } }; /** * An empty internal base class inherited by NInteger, which does not * support infinity as an allowed value. */ template <> struct InfinityBase { }; #endif // __DOXYGEN /** * Represents an arbitrary precision integer. * Calculations are always guaranteed to be exact, regardless of how * large the integers become. * * The current implementation uses fast native integer arithmetic wherever * possible, whilst always testing for potential overflow. If a potential * overflow is detected, this class switches to using the GNU multiple * precision arithmetic library (libgmp) instead. * * This class takes a single boolean argument \a supportInfinity. * If this is \c true, then this class will support infinity as an allowed * value. If this is \c false (the default), then infinity is not supported, * and any attempt to work with infinity will lead to undefined behaviour. * Supporting infinity is more flexible, but also comes with a slight * performance cost (very roughly estimated at around 10%-20%). * * For the purposes of comparison, infinity is * considered larger than any other integer but equal to itself. * * All routines in this class, including random number generation, are * thread-safe. * * The opportunistic use of native arithmetic where possible was inspired by * the (much more complex and powerful) lazy exact arithmetic in CGAL. * Thanks to Menelaos Karavelas for encouraging me to take another look at * these ideas. * * \ifacespython Both variants of this template are available through Python. * For \a supportInfinity = \c false (the default), simply use NIntegerBase. * For \a supportInfinity = \c true, use NLargeInteger. */ template class REGINA_API NIntegerBase : private InfinityBase { public: static const NIntegerBase zero; /**< Globally available zero. */ static const NIntegerBase one; /**< Globally available one. */ static const NIntegerBase infinity; /**< Globally available infinity. This is only defined if \a supportInfinity is \c true. Any attempt to use it when \a supportInfinity is \c false should generate a linker error. */ private: long small_; /**< Contains the native representation of this integer, if we are still using native representations (i.e., if large_ is null). If we are using GMP large integer representations, or if this integer is infinity, then this native integer is ignored (and may be set to anything). */ mpz_ptr large_; /**< 0 if we are using native representations, or a pointer to the full GMP large integer if we are now using these instead. We require that, whenever this pointer is non-null, the corresponding GMP large integer is initialised. If this integer is infinity then large_ must be null. */ public: /** * Initialises this integer to zero. */ NIntegerBase(); /** * Initialises this integer to the given value. * * \ifacespython In Python, the only native-integer constructor * is NIntegerBase(long). * * @param value the new value of this integer. */ NIntegerBase(int value); /** * Initialises this integer to the given value. * * \ifacespython In Python, the only native-integer constructor * is NIntegerBase(long). * * @param value the new value of this integer. */ NIntegerBase(unsigned value); /** * Initialises this integer to the given value. * * \ifacespython In Python, this is the only native-integer * constructor available. * * @param value the new value of this integer. */ NIntegerBase(long value); /** * Initialises this integer to the given value. * * \ifacespython In Python, the only native-integer constructor * is NIntegerBase(long). * * @param value the new value of this integer. */ NIntegerBase(unsigned long value); /** * Initialises this integer to the given value. * * @param value the new value of this integer. */ NIntegerBase(const NIntegerBase& value); /** * Initialises this integer to the given value. * * This constructor is marked as explicit in the hope of * avoiding accidental (and unintentional) mixing of template * parameters. * * \pre The given integer is not infinite. * * @param value the new value of this integer. */ explicit NIntegerBase(const NIntegerBase& value); /** * Initialises this integer to the given value. * * This constructor is marked as explicit in the hope of * avoiding accidental (and unintentional) mixing of integer classes. * * \pre If \a bytes is larger than sizeof(long), then * \a bytes is a strict \e multiple of sizeof(long). For * instance, if longs are 8 bytes then you can use \a bytes=16 * but not \a bytes=12. This restriction is enforced through a * compile-time assertion, but may be lifted in future versions * of Regina. * * \ifacespython Not present. * * @param value the new value of this integer. */ template explicit NIntegerBase(const NNativeInteger& value); /** * Initialises this integer to the given value which is * represented as a string of digits in a given base. * * If not specified, the base defaults to 10. * If the given base is zero, the base will be automatically * determined. If the given string begins with \c 0x or \c 0X, * the base will be assumed to be 16. Otherwise, if the string * begins with \c 0, the base will be assumed to be 8. * Otherwise it will be taken as base 10. * * Whitespace may be present at the beginning or the end * of the given string, and will simply be ignored. * * Error detection is possible by passing a non-null boolean * pointer as the third parameter to this constructor. * * For finer details on how the string parsing works, see * strtol() from the standard C library (on which this method * is based). * * \pre The given base is zero, or is between 2 and 36 inclusive. * \pre The given string represents a finite integer * in the given base, with optional whitespace beforehand. * * \ifacespython The final parameter \a valid is not present. * * @param value the new value of this integer, represented as a string * of digits in base \a base. * @param base the base in which \a value is given. * @param valid if this pointer is not null, the boolean referenced * will be set to \c true if the entire given string was a valid * large integer representation and \c false otherwise. */ NIntegerBase(const char* value, int base = 10, bool* valid = 0); /** * Initialises this integer to the given value which is * represented as a string of digits in a given base. * * If not specified, the base defaults to 10. * If the given base is zero, the base will be automatically * determined. If the given string begins with \c 0x or \c 0X, * the base will be assumed to be 16. Otherwise, if the string * begins with \c 0, the base will be assumed to be 8. * Otherwise it will be taken as base 10. * * Whitespace may be present at the beginning or the end * of the given string, and will simply be ignored. * * Error detection is possible by passing a non-null boolean * pointer as the third parameter to this constructor. * * For finer details on how the string parsing works, see * strtol() from the standard C library (on which this method * is based). * * \pre The given base is zero, or is between 2 and 36 inclusive. * \pre The given string represents an integer * in the given base, with optional whitespace beforehand. * * \ifacespython The final parameter \a valid is not present. * * @param value the new value of this integer, represented as a string * of digits in base \a base. * @param base the base in which \a value is given. * @param valid if this pointer is not null, the boolean referenced * will be set to \c true if the entire given string was a valid * large integer representation and \c false otherwise. */ NIntegerBase(const std::string& value, int base = 10, bool* valid = 0); /** * Destroys this integer. */ ~NIntegerBase(); /** * Returns whether we are currently working with a native C/C++ * long, or whether we have switched to GMP large integer arithmetic * for this integer. * * If this integer is infinite, this routine will return \c false. * * @return \c true if and only if we are still using a native * C/C++ long. */ bool isNative() const; /** * Returns whether or not this integer is zero. * * This is micro-optimised to be faster than simply testing * whether (*this) == 0. * * @return \c true if and only if this integer is zero. */ bool isZero() const; /** * Returns the sign of this integer. * * In this routine, infinity is considered to have sign +1. * * @return +1, -1 or 0 according to whether this integer is * positive, negative or zero. */ int sign() const; /** * Returns whether this integer is infinity. * * @return \c true if and only if this integer is infinity. */ bool isInfinite() const; /** * Sets this integer to be infinity. * * If the template parameter \a supportInfinity is \c false, * this routine safely does nothing. */ inline void makeInfinite(); /** * Returns the value of this integer as a long. * * It is the programmer's reponsibility to ensure that this integer * is within the required range. If this integer is too large or * small to fit into a long, then the result will be undefined. * * Note that, assuming the value is within the required range, * this routine will give correct results regardless of whether the * underlying representation is a native or large integer. * * \pre This integer is not infinity. * * @return the value of this integer. */ long longValue() const; /** * Returns the value of this integer as a native integer of some * fixed byte length. * * It is the programmer's reponsibility to ensure that this integer * is within the required range. If this integer is too large or * small to fit into the return type, then the result will be undefined. * * Note that, assuming the value is within the required range, * this routine will give correct results regardless of whether the * underlying representation is a native or large integer. * * \pre If \a bytes is larger than sizeof(long), then * \a bytes is a strict \e multiple of sizeof(long). For * instance, if longs are 8 bytes then you can use this * routine with \a bytes=16 but not \a bytes=12. * This restriction is enforced through a compile-time assertion, * but may be lifted in future versions of Regina. * * \pre This integer is not infinity. * * \ifacespython Not present. * * @return the value of this integer. */ template typename IntOfSize::type nativeValue() const; /** * Returns the value of this integer as a string in the given * base. If not specified, the base defaults to 10. * * If this integer is infinity, the string returned will be * \c inf. * * \pre The given base is between 2 and 36 inclusive. * * @return the value of this integer as a newly allocated * string. */ std::string stringValue(int base = 10) const; /** * Sets this integer to the given value. * * @param value the new value of this integer. * @return a reference to this integer with its new value. */ NIntegerBase& operator =(const NIntegerBase& value); /** * Sets this integer to the given value. * * \pre The given integer is not infinite. * * @param value the new value of this integer. * @return a reference to this integer with its new value. */ NIntegerBase& operator = (const NIntegerBase& value); /** * Sets this integer to the given value. * * @param value the new value of this integer. * @return a reference to this integer with its new value. */ NIntegerBase& operator =(int value); /** * Sets this integer to the given value. * * @param value the new value of this integer. * @return a reference to this integer with its new value. */ NIntegerBase& operator =(unsigned value); /** * Sets this integer to the given value. * * @param value the new value of this integer. * @return a reference to this integer with its new value. */ NIntegerBase& operator =(long value); /** * Sets this integer to the given value. * * @param value the new value of this integer. * @return a reference to this integer with its new value. */ NIntegerBase& operator =(unsigned long value); /** * Sets this integer to the given value which is * represented as a string of digits in base 10. * * Whitespace may be present at the beginning or end of the given * string and will simply be ignored. * * \pre The given string represents an integer * in base 10, with optional whitespace added. * * @param value the new value of this integer, represented as a string * of digits in base 10. * @return a reference to this integer with its new value. */ NIntegerBase& operator =(const char* value); /** * Sets this integer to the given value which is * represented as a string of digits in base 10. * * Whitespace may be present at the beginning or end of the given * string and will simply be ignored. * * \pre The given string represents an integer * in base 10, with optional whitespace added. * * @param value the new value of this integer, represented as a string * of digits in base 10. * @return a reference to this integer with its new value. */ NIntegerBase& operator =(const std::string& value); /** * Swaps the values of this and the given integer. * * @param other the integer whose value will be swapped with * this. */ void swap(NIntegerBase& other); /** * Determines if this is equal to the given integer. * * @param rhs the integer with which this will be compared. * @return \c true if and only if this and the given integer are * equal. */ bool operator ==(const NIntegerBase& rhs) const; /** * Determines if this is equal to the given integer. * * @param rhs the integer with which this will be compared. * @return \c true if and only if this and the given integer are * equal. */ bool operator ==(const NIntegerBase& rhs) const; /** * Determines if this is equal to the given integer. * * @param rhs the integer with which this will be compared. * @return \c true if and only if this and the given integer are * equal. */ bool operator ==(long rhs) const; /** * Determines if this is not equal to the given integer. * * @param rhs the integer with which this will be compared. * @return \c true if and only if this and the given integer are * not equal. */ bool operator !=(const NIntegerBase& rhs) const; /** * Determines if this is not equal to the given integer. * * @param rhs the integer with which this will be compared. * @return \c true if and only if this and the given integer are * not equal. */ bool operator !=(const NIntegerBase& rhs) const; /** * Determines if this is not equal to the given integer. * * @param rhs the integer with which this will be compared. * @return \c true if and only if this and the given integer are * not equal. */ bool operator !=(long rhs) const; /** * Determines if this is less than the given integer. * * @param rhs the integer with which this will be compared. * @return \c true if and only if this is less than the given * integer. */ bool operator <(const NIntegerBase& rhs) const; /** * Determines if this is less than the given integer. * * @param rhs the integer with which this will be compared. * @return \c true if and only if this is less than the given * integer. */ bool operator <(long rhs) const; /** * Determines if this is greater than the given integer. * * @param rhs the integer with which this will be compared. * @return \c true if and only if this is greater than the given * integer. */ bool operator >(const NIntegerBase& rhs) const; /** * Determines if this is greater than the given integer. * * @param rhs the integer with which this will be compared. * @return \c true if and only if this is greater than the given * integer. */ bool operator >(long rhs) const; /** * Determines if this is less than or equal to the given integer. * * @param rhs the integer with which this will be compared. * @return \c true if and only if this is less than or equal to * the given integer. */ bool operator <=(const NIntegerBase& rhs) const; /** * Determines if this is less than or equal to the given integer. * * @param rhs the integer with which this will be compared. * @return \c true if and only if this is less than or equal to * the given integer. */ bool operator <=(long rhs) const; /** * Determines if this is greater than or equal to the given integer. * * @param rhs the integer with which this will be compared. * @return \c true if and only if this is greater than or equal * to the given integer. */ bool operator >=(const NIntegerBase& rhs) const; /** * Determines if this is greater than or equal to the given integer. * * @param rhs the integer with which this will be compared. * @return \c true if and only if this is greater than or equal * to the given integer. */ bool operator >=(long rhs) const; /** * The preincrement operator. * This operator increments this integer by one, and returns a * reference to the integer \e after the increment. * * \ifacespython Not available. * * @return a reference to this integer after the increment. */ NIntegerBase& operator ++(); /** * The postincrement operator. * This operator increments this integer by one, and returns a * copy of the integer \e before the increment. * * \ifacespython Not available. * * @return a copy of this integer before the * increment took place. */ NIntegerBase operator ++(int); /** * The predecrement operator. * This operator decrements this integer by one, and returns a * reference to the integer \e after the decrement. * * \ifacespython Not available. * * @return a reference to this integer after the decrement. */ NIntegerBase& operator --(); /** * The postdecrement operator. * This operator decrements this integer by one, and returns a * copy of the integer \e before the decrement. * * \ifacespython Not available. * * @return a copy of this integer before the * decrement took place. */ NIntegerBase operator --(int); /** * Adds this to the given integer and returns the result. * This integer is not changed. * * If either term of the sum is infinite, the result will be * infinity. * * @param other the integer to add to this integer. * @return the sum \a this plus \a other. */ NIntegerBase operator +(const NIntegerBase& other) const; /** * Adds this to the given integer and returns the result. * This integer is not changed. * * If either term of the sum is infinite, the result will be * infinity. * * @param other the integer to add to this integer. * @return the sum \a this plus \a other. */ NIntegerBase operator +(long other) const; /** * Subtracts the given integer from this and returns the result. * This integer is not changed. * * If either term of the difference is infinite, the result will be * infinity. * * @param other the integer to subtract from this integer. * @return the difference \a this minus \a other. */ NIntegerBase operator -(const NIntegerBase& other) const; /** * Subtracts the given integer from this and returns the result. * This integer is not changed. * * If either term of the difference is infinite, the result will be * infinity. * * @param other the integer to subtract from this integer. * @return the difference \a this minus \a other. */ NIntegerBase operator -(long other) const; /** * Multiplies this by the given integer and returns the * result. * This integer is not changed. * * If either factor of the product is infinite, the result will be * infinity. * * @param other the integer to multiply by this integer. * @return the product \a this times \a other. */ NIntegerBase operator *(const NIntegerBase& other) const; /** * Multiplies this by the given integer and returns the * result. * This integer is not changed. * * If either factor of the product is infinite, the result will be * infinity. * * @param other the integer to multiply by this integer. * @return the product \a this times \a other. */ NIntegerBase operator *(long other) const; /** * Divides this by the given integer and returns the result. * The result will be truncated to an integer, i.e. rounded * towards zero. * This integer is not changed. * * If \a other is known to divide this integer exactly, * divExact() should be used instead. * * Infinity divided by anything will return infinity. * Anything finite divided by infinity will return zero. * Anything finite divided by zero will return infinity. * * For a division routine that always rounds down, see divisionAlg(). * * \pre If this class does not support infinity, then * \a other must be non-zero. * * \warning As I understand it, the direction of rounding for * native C/C++ integer division was fixed in the C++11 * specification, but left to the compiler implementation in * earlier versions of the specification; however, any modern * hardware should satisfy the C++11 rounding rule as described above. * * @param other the integer to divide this by. * @return the quotient \a this divided by \a other. */ NIntegerBase operator /(const NIntegerBase& other) const; /** * Divides this by the given integer and returns the result. * The result will be truncated to an integer, i.e. rounded * towards zero. * This integer is not changed. * * If \a other is known to divide this integer exactly, * divExact() should be used instead. * * Infinity divided by anything will return infinity. * Anything finite divided by zero will return infinity. * * For a division routine that always rounds down, see divisionAlg(). * * \pre If this class does not support infinity, then * \a other must be non-zero. * * \warning As I understand it, the direction of rounding for * native C/C++ integer division was fixed in the C++11 * specification, but left to the compiler implementation in * earlier versions of the specification; however, any modern * hardware should satisfy the C++11 rounding rule as described above. * * @param other the integer to divide this by. * @return the quotient \a this divided by \a other. */ NIntegerBase operator /(long other) const; /** * Divides this by the given integer and returns the result. * This can only be used when the given integer divides into * this exactly, and for large integers can be much faster than * ordinary division. This integer is not changed. * * \pre The given integer divides exactly into * this integer, i.e. \a this divided by \a other is an integer. * \pre \a other is not zero. * \pre Neither this nor \a other is infinite. * * @param other the integer to divide this by. * @return the quotient \a this divided by \a other. */ NIntegerBase divExact(const NIntegerBase& other) const; /** * Divides this by the given integer and returns the result. * This can only be used when the given integer divides into * this exactly, and for large integers can be much faster than * ordinary division. This integer is not changed. * * \pre The given integer divides exactly into * this integer, i.e. \a this divided by \a other is an integer. * \pre \a other is not zero. * \pre This integer is not infinite. * * @param other the integer to divide this by. * @return the quotient \a this divided by \a other. */ NIntegerBase divExact(long other) const; /** * Determines the remainder when this integer is divided by the * given integer. If non-zero, the result will have the same sign * as this integer. * This integer is not changed. * * For a division routine that always returns a non-negative * remainder, see divisionAlg(). * * \pre \a other is not zero. * \pre Neither this nor \a other is infinite. * * \warning As I understand it, the sign of the result under * native C/C++ integer division when the second operand is * negative was fixed in the C++11 specification, but left to the * compiler implementation in earlier versions of the specification; * however, any modern hardware should satisfy the C++11 sign rule * as described above. * * @param other the integer to divide this by. * @return the remainder \a this modulo \a other. */ NIntegerBase operator %(const NIntegerBase& other) const; /** * Determines the remainder when this integer is divided by the * given integer. If non-zero, the result will have the same sign * as this integer. * This integer is not changed. * * For a division routine that always returns a non-negative * remainder, see divisionAlg(). * * \pre \a other is not zero. * \pre This integer is not infinite. * * \warning As I understand it, the sign of the result under * native C/C++ integer division when the second operand is * negative was fixed in the C++11 specification, but left to the * compiler implementation in earlier versions of the specification; * however, any modern hardware should satisfy the C++11 sign rule * as described above. * * @param other the integer to divide this by. * @return the remainder \a this modulo \a other. */ NIntegerBase operator %(long other) const; /** * Uses the division algorithm to obtain a quotient and * remainder when dividing by the given integer. * * Suppose this integer is \a n and we pass the divisor \a d. * The division algorithm describes the result of * dividing \a n by \a d; in particular, it expresses * n = qd + r, where \a q is the quotient and * \a r is the remainder. * * The division algorithm is precise about which values of \a q * and \a r are chosen; in particular it chooses the unique \a r * in the range 0 <= r < |d|. * * Note that this differs from other division routines in this * class, in that it always rounds to give a non-negative remainder. * Thus NIntegerBase(-7).divisionAlg(3) gives quotient -3 and * remainder 2, whereas (-7)/3 gives quotient -2 and (-7)\%3 gives * remainder -1. * * The two results are passed back to the caller as follows: * The quotient \a q is passed back as the return value of the * function, and the remainder \a r is stored in the reference * argument \a r. * * In the special case where the given divisor is 0 (not * allowed by the usual division algorithm), this routine selects * quotient 0 and remainder \a n. * * \pre Neither this nor the divisor are infinite. * * \ifacespython The argument \a remainder is missing; instead both * the quotient and remainder are passed back through the return * value of the function. Specifically, this function returns a * (\a quotient, \a remainder) pair. * * @param divisor the divisor \a d. * @param remainder used to store the remainder \a r when the * functon returns. The initial value of this argument is ignored. * @return the quotient \a q. * * @author Ryan Budney & B.B. */ NIntegerBase divisionAlg( const NIntegerBase& divisor, NIntegerBase& remainder) const; /** * Determines the negative of this integer. * This integer is not changed. * * Negative infinity will return infinity. * * @return the negative of this integer. */ NIntegerBase operator -() const; /** * Adds the given integer to this. * This integer is changed to reflect the result. * * If either term of the sum is infinite, the result will be * infinity. * * @param other the integer to add to this integer. * @return a reference to this integer with its new value. */ NIntegerBase& operator +=(const NIntegerBase& other); /** * Adds the given integer to this. * This integer is changed to reflect the result. * * If either term of the sum is infinite, the result will be * infinity. * * @param other the integer to add to this integer. * @return a reference to this integer with its new value. */ NIntegerBase& operator +=(long other); /** * Subtracts the given integer from this. * This integer is changed to reflect the result. * * If either term of the difference is infinite, the result will be * infinity. * * @param other the integer to subtract from this integer. * @return a reference to this integer with its new value. */ NIntegerBase& operator -=(const NIntegerBase& other); /** * Subtracts the given integer from this. * This integer is changed to reflect the result. * * If either term of the difference is infinite, the result will be * infinity. * * @param other the integer to subtract from this integer. * @return a reference to this integer with its new value. */ NIntegerBase& operator -=(long other); /** * Multiplies the given integer by this. * This integer is changed to reflect the result. * * If either factor of the product is infinite, the result will be * infinity. * * @param other the integer to multiply with this integer. * @return a reference to this integer with its new value. */ NIntegerBase& operator *=(const NIntegerBase& other); /** * Multiplies the given integer by this. * This integer is changed to reflect the result. * * If either factor of the product is infinite, the result will be * infinity. * * @param other the integer to multiply with this integer. * @return a reference to this integer with its new value. */ NIntegerBase& operator *=(long other); /** * Divides this by the given integer. * The result will be truncated to an integer, i.e. rounded * towards zero. * This integer is changed to reflect the result. * * If \a other is known to divide this integer exactly, * divByExact() should be used instead. * * Infinity divided by anything will return infinity. * Anything finite divided by infinity will return zero. * Anything finite divided by zero will return infinity. * * For a division routine that always rounds down, see divisionAlg(). * * \pre If this class does not support infinity, then * \a other must be non-zero. * * \warning As I understand it, the direction of rounding for * native C/C++ integer division was fixed in the C++11 * specification, but left to the compiler implementation in * earlier versions of the specification; however, any modern * hardware should satisfy the C++11 rounding rule as described above. * * @param other the integer to divide this by. * @return a reference to this integer with its new value. */ NIntegerBase& operator /=(const NIntegerBase& other); /** * Divides this by the given integer. * The result will be truncated to an integer, i.e. rounded * towards zero. * This integer is changed to reflect the result. * * If \a other is known to divide this integer exactly, * divByExact() should be used instead. * * Infinity divided by anything will return infinity. * Anything finite divided by zero will return infinity. * * For a division routine that always rounds down, see divisionAlg(). * * \pre If this class does not support infinity, then * \a other must be non-zero. * * \warning As I understand it, the direction of rounding for * native C/C++ integer division was fixed in the C++11 * specification, but left to the compiler implementation in * earlier versions of the specification; however, any modern * hardware should satisfy the C++11 rounding rule as described above. * * @param other the integer to divide this by. * @return a reference to this integer with its new value. */ NIntegerBase& operator /=(long other); /** * Divides this by the given integer. * This can only be used when the given integer divides into * this exactly, and for large integers this is much faster than * ordinary division. This integer is changed to reflect the result. * * \pre The given integer divides exactly into * this integer, i.e. \a this divided by \a other is an integer. * \pre \a other is not zero. * \pre Neither this nor \a other is infinite. * * @param other the integer to divide this by. * @return a reference to this integer with its new value. */ NIntegerBase& divByExact(const NIntegerBase& other); /** * Divides this by the given integer. * This can only be used when the given integer divides into * this exactly, and for large integers this is much faster than * ordinary division. This integer is changed to reflect the result. * * \pre The given integer divides exactly into * this integer, i.e. \a this divided by \a other is an integer. * \pre \a other is not zero. * \pre This integer is not infinite. * * @param other the integer to divide this by. * @return a reference to this integer with its new value. */ NIntegerBase& divByExact(long other); /** * Reduces this integer modulo the given integer. * If non-zero, the result will have the same sign as the original * value of this integer. * This integer is changed to reflect the result. * * For a mod routine that always returns a non-negative * remainder, see divisionAlg(). * * \pre \a other is not zero. * \pre Neither this nor \a other is infinite. * * \warning As I understand it, the sign of the result under * native C/C++ integer division when the second operand is * negative was fixed in the C++11 specification, but left to the * compiler implementation in earlier versions of the specification; * however, any modern hardware should satisfy the C++11 sign rule * as described above. * * @param other the integer modulo which this integer will be * reduced. * @return a reference to this integer with its new value. */ NIntegerBase& operator %=(const NIntegerBase& other); /** * Reduces this integer modulo the given integer. * If non-zero, the result will have the same sign as the original * value of this integer. * This integer is changed to reflect the result. * * For a mod routine that always returns a non-negative * remainder, see divisionAlg(). * * \pre \a other is not zero. * \pre This integer is not infinite. * * \warning As I understand it, the sign of the result under * native C/C++ integer division when the second operand is * negative was fixed in the C++11 specification, but left to the * compiler implementation in earlier versions of the specification; * however, any modern hardware should satisfy the C++11 sign rule * as described above. * * @param other the integer modulo which this integer will be * reduced. * @return a reference to this integer with its new value. */ NIntegerBase& operator %=(long other); /** * Negates this integer. * This integer is changed to reflect the result. * * Negating infinity will result in infinity. */ void negate(); /** * Raises this integer to the power of the given exponent. * This integer is changed to reflect the result. * * Note that 0 to the power of 0 will be 1, infinity to the * power of 0 will be 1, and infinity to the power of anything * else will be infinity. * * \pre The given exponent is non-negative. * * @param exp the power to which this integer will be raised. */ void raiseToPower(unsigned long exp); /** * Determines the absolute value of this integer. * This integer is not changed. * * @return the absolute value of this integer. */ NIntegerBase abs() const; /** * Sets this integer to be the greatest common divisor of this * and the given integer. * * The result is guaranteed to be non-negative. As a * special case, gcd(0,0) is considered to be zero. * * \pre Neither this integer nor \a other is infinite. * * @param other the integer whose greatest common divisor with * this will be found. */ void gcdWith(const NIntegerBase& other); /** * Determines the greatest common divisor of this and the given * integer. This integer is not changed. * * The result is guaranteed to be non-negative. As a * special case, gcd(0,0) is considered to be zero. * * \pre Neither this integer nor \a other is infinite. * * @param other the integer whose greatest common divisor with * this will be found. * @return the greatest common divisor of this and the given * integer. */ NIntegerBase gcd(const NIntegerBase& other) const; /** * Sets this integer to be the lowest common multiple of this * and the given integer. * * Note that the result might possibly be negative. * * \pre Neither this integer nor \a other is infinite. * * @param other the integer whose lowest common multiple with * this will be found. */ void lcmWith(const NIntegerBase& other); /** * Determines the lowest common multiple of this and the given * integer. This integer is not changed. * * Note that the result might possibly be negative. * * \pre Neither this integer nor \a other is infinite. * * @param other the integer whose lowest common multiple with * this will be found. * @return the lowest common multiple of this and the given * integer. */ NIntegerBase lcm(const NIntegerBase& other) const; /** * Determines the greatest common divisor of this and the given * integer and finds the smallest coefficients with which these * integers combine to give their gcd. * * Note that the given integers need not be non-negative. * However, the gcd returned is guaranteed to be non-negative. * * If \a d is the gcd of \a this and \a other, the values placed * into \a u and \a v will be those for which * u*this + v*other = d, * -abs(this)/d < v*sign(other) <= 0 and * 1 <= u*sign(this) <= abs(other)/d. * These equations are not satisfied when either of \a this or * \a other are zero, but in this case \a u and \a v are both * 0, 1 or -1, using as many zeros as possible. * * \pre Neither this integer nor \a other is infinite. * * @param other the integer whose greatest common divisor with * this will be found. * @param u a variable into which the final coefficient of * \a this will be placed. * @param v a variable into which the final coefficient of * \a other will be placed. * @return the greatest common divisor of \a this and \a other. */ NIntegerBase gcdWithCoeffs( const NIntegerBase& other, NIntegerBase& u, NIntegerBase& v) const; /** * Returns the Legendre symbol (\a a/\a p), where * \a a is this integer and \a p is an odd prime. * * The Legendre symbol is equal to 0 if this integer * is divisible by \a p, 1 if this integer is congruent * to a square mod \a p (but not divisible by \a p), * and -1 otherwise. * * \pre The given integer \a p is an odd positive prime. * \pre This integer is not infinite. * * @param p the given odd prime. * @return The Legendre symbol (0, 1 or -1) as described above. * * @author Ryan Budney */ int legendre(const NIntegerBase& p) const; /** * Generate a pseudo-random integer that is uniformly * distributed in the interval [0,*this). * * \pre This integer is strictly positive. * * \warning Even if this integer is small, this routine is still * slow - it always goes through the GMP large integer routines * so that the random number generation algorithm is consistent. * If you need a fast random number generator and this integer * is small, consider using the standard rand() function instead. * * @return a pseudo-random integer. */ NIntegerBase randomBoundedByThis() const; /** * Generate a pseudo-random integer that is uniformly * distributed in the interval [0,2^n). * * @param n the maximum number of bits in the pseudo-random * integer. * @return a pseudo-random integer. */ static NIntegerBase randomBinary(unsigned long n); /** * Generate a pseudo-random integer that is distributed in the * interval [0,2^n), with a tendency to have long strings of 0s * and 1s in its binary expansion. * * @param n the maximum number of bits in the pseudo-random integer. * @return a pseudo-random integer. */ static NIntegerBase randomCornerBinary( unsigned long n); /** * Set this to a copy of the given raw GMP integer. * * This routine allows NIntegerBase to interact directly with * libgmp and libgmpxx if necessary. * * \ifacespython Not available. * * @param fromData the raw GMP integer to clone. */ void setRaw(mpz_srcptr fromData); /** * Returns the raw GMP data that describes this integer. * * This routine allows NIntegerBase to interact directly with * libgmp and libgmpxx if necessary. * * \warning This routine will have the side-effect of converting * this integer to a (bulkier and slower) GMP representation, * regardless of whether it is small enough to fit within a native * integer. Excessive use of this routine could lead to a significant * performance loss. It is best to use this only when isNative() is * already known to return \c false. * * \pre This integer is not infinite. * * \ifacespython Not available. * * @return the raw GMP data. */ mpz_srcptr rawData() const; /** * Returns the raw GMP data that describes this integer. * * This routine allows NIntegerBase to interact directly with * libgmp and libgmpxx if necessary. * * \warning This routine will have the side-effect of converting * this integer to a (bulkier and slower) GMP representation, * regardless of whether it is small enough to fit within a native * integer. Excessive use of this routine could lead to a significant * performance loss. It is best to use this only when isNative() is * already known to return \c false. * * \pre This integer is not infinite. * * \ifacespython Not available. * * @return the raw GMP data. */ mpz_ptr rawData(); /** * Converts this integer to use a GMP large integer representation, * regardless of whether this is actually necessary. The contents * of this integer will be preserved. * * It does not matter which kind of representation this integer * is currently using. * * \pre This integer is not infinite. */ void makeLarge(); /** * Converts this integer to use a native C/C++ long representation, * if this is possible. However, if this integer is outside the range * of a C/C++ long, then it will remain as a GMP large integer instead * (i.e., nothing will change). Whatever happens, the contents of this * integer will be preserved. * * It does not matter which kind of representation this integer * is currently using. * * \pre This integer is not infinite. */ void tryReduce(); private: /** * Initialises this integer to infinity. * All parameters are ignored. * * This constructor is only defined if \a supportInfinity is \c true. * Any attempt to use it when \a supportInfinity is \c false * will generate a linker error. */ NIntegerBase(bool, bool); /** * Sets this integer to be finite. * Its new value will be determined by the current contents of * \a small_ which will not be touched. * * If the template parameter \a supportInfinity is \c false, * this routine safely does nothing. */ inline void makeFinite(); /** * Converts this integer from a native C/C++ long representation * into a GMP large integer representation. * * The contents of \a small will be copied into \a large. * * \pre \a large_ is null (i.e., we are indeed using a native * C/C++ long representation at present). * \pre This integer is not infinite. */ void forceLarge(); /** * Destroys the GMP large integer representation and reverts to * a native C/C++ long. * * The new value of this integer will be the current contents of * \a small_ (i.e., there is no attempt to "extract" a native long * from the contents of \a large_). * * \pre \a large_ is non-null (i.e., we are indeed using a large * integer reprentation at present). * \pre This integer is not infinite. */ void clearLarge(); /** * Converts this integer from a GMP large integer representation * into a native C/C++ long representation. * * The contents of \a large will be extracted and copied into \a small. * * \pre \a large_ is non-null, and the large integer that it * represents lies between LONG_MIN and LONG_MAX inclusive. * \pre This integer is not infinite. */ void forceReduce(); friend class NIntegerBase; // For conversions. template friend class NNativeInteger; // For conversions. template friend std::ostream& operator << (std::ostream& out, const NIntegerBase& large); }; /** * NLargeInteger is a typedef for NIntegerBase, which offers * arbitrary precision integers with support for infinity. * * \ifacespython This typedef is available in Python. */ typedef NIntegerBase NLargeInteger; /** * NInteger is a typedef for NIntegerBase, which offers * arbitrary precision integers without support for infinity. * * \ifacespython This typedef is available in Python. */ typedef NIntegerBase NInteger; /** * Writes the given integer to the given output stream. * * @param out the output stream to which to write. * @param i the integer to write. * @return a reference to \a out. */ template REGINA_API std::ostream& operator << (std::ostream& out, const NIntegerBase& i); /** * Adds the given native integer to the given large integer. * If the large integer is infinite, the result will also be infinity. * * \ifacespython Not available. * * @param lhs the native integer to add. * @param rhs the large integer to add. * @return the sum \a lhs plus \a rhs. */ template REGINA_API NIntegerBase operator + (long lhs, const NIntegerBase& rhs); /** * Multiplies the given native integer with the given large integer. * If the large integer is infinite, the result will also be infinity. * * \ifacespython Not available. * * @param lhs the native integer to multiply. * @param rhs the large integer to multiply. * @return the product \a lhs times \a rhs. */ template REGINA_API NIntegerBase operator * (long lhs, const NIntegerBase& rhs); /*@}*/ } // namespace regina #ifndef __DOXYGEN namespace libnormaliz { /** * Explicit integer cast functions, for compatibility with Normaliz. * * We define functions separately for each variant of \a supportInfinity * to avoid partial template specialisation. * * @param a an instance of some arbitrary integer type. * @return the given integer, cast as a native long. */ template long explicit_cast_to_long(const Integer& a); template <> inline long explicit_cast_to_long >( const regina::NIntegerBase& a) { return a.longValue(); } template <> inline long explicit_cast_to_long >( const regina::NIntegerBase& a) { return a.longValue(); } } //namespace libnormaliz #endif namespace regina { /** * A wrapper class for a native, fixed-precision integer type of the * given size. * * This class behaves just like native integer arithmetic, where the * underlying integer type is signed and stores the given number of bytes. * There is no overflow testing, and it is up to the user to ensure that * overflows do not occur. On the other hand, this class is almost as * fast as native integer arithmetic (i.e., there is very little overhead). * * The reason for using this class, instead of working directly in a native * integer type, is that this class offers an interface that is compatible with * NInteger. Only some of the NInteger member functions are offered here; * however, those that are offered behave just like their NInteger * counterparts (with the single exception that all arithmetic in * NNativeInteger is subject to overflow). Developers can therefore * switch between integer types easily with minimal changes to * their code, or support both NInteger and NNativeInteger types as * template arguments. * * \pre The system must support integers of the given size; in particular, * there must be an appropriate specialisation IntOfSize. * * \ifacespython Not present. */ template class REGINA_API NNativeInteger { public: typedef typename IntOfSize::type Native; /**< The native data type used to store this integer. */ private: Native data_; /**< The value of this integer. */ public: /** * Initialises this integer to zero. */ NNativeInteger(); /** * Initialises this integer to the given value. * * @param value the new value of this integer. */ NNativeInteger(Native value); /** * Initialises this integer to the given value. * * @param value the new value of this integer. */ NNativeInteger(const NNativeInteger& value); /** * Initialises this integer to the given value. * * This constructor is marked as explicit in the hope of * avoiding accidental (and unintentional) mixing of integer classes. * * It is the programmer's reponsibility to ensure that the given value * fits within the required range. If the given value is too large or * small to fit into this native type, then this new NNativeInteger * will have an undefined initial value. * * \pre If \a bytes is larger than sizeof(long), then * \a bytes is a strict \e multiple of sizeof(long). For * instance, if longs are 8 bytes then you can use this * routine with \a bytes=16 but not \a bytes=12. * This restriction is enforced through a compile-time assertion, * but may be lifted in future versions of Regina. * * \pre The given integer is not infinity. * * \ifacespython Not present. * * @param value the new value of this integer. */ template explicit NNativeInteger(const NIntegerBase& value); /** * Returns whether or not this integer is zero. * * @return \c true if and only if this integer is zero. */ bool isZero() const; /** * Returns the sign of this integer. * * @return +1, -1 or 0 according to whether this integer is * positive, negative or zero. */ int sign() const; /** * Returns the value of this integer in its native type. * * @return the value of this integer. */ Native nativeValue() const; /** * Sets this integer to the given value. * * @param value the new value of this integer. * @return a reference to this integer with its new value. */ NNativeInteger& operator =(const NNativeInteger& value); /** * Sets this integer to the given value. * * @param value the new value of this integer. * @return a reference to this integer with its new value. */ NNativeInteger& operator =(Native value); /** * Swaps the values of this and the given integer. * * @param other the integer whose value will be swapped with * this. */ void swap(NNativeInteger& other); /** * Determines if this is equal to the given integer. * * @param rhs the integer with which this will be compared. * @return \c true if and only if this and the given integer are * equal. */ bool operator ==(const NNativeInteger& rhs) const; /** * Determines if this is equal to the given integer. * * @param rhs the integer with which this will be compared. * @return \c true if and only if this and the given integer are * equal. */ bool operator ==(Native rhs) const; /** * Determines if this is not equal to the given integer. * * @param rhs the integer with which this will be compared. * @return \c true if and only if this and the given integer are * not equal. */ bool operator !=(const NNativeInteger& rhs) const; /** * Determines if this is not equal to the given integer. * * @param rhs the integer with which this will be compared. * @return \c true if and only if this and the given integer are * not equal. */ bool operator !=(Native rhs) const; /** * Determines if this is less than the given integer. * * @param rhs the integer with which this will be compared. * @return \c true if and only if this is less than the given * integer. */ bool operator <(const NNativeInteger& rhs) const; /** * Determines if this is less than the given integer. * * @param rhs the integer with which this will be compared. * @return \c true if and only if this is less than the given * integer. */ bool operator <(Native rhs) const; /** * Determines if this is greater than the given integer. * * @param rhs the integer with which this will be compared. * @return \c true if and only if this is greater than the given * integer. */ bool operator >(const NNativeInteger& rhs) const; /** * Determines if this is greater than the given integer. * * @param rhs the integer with which this will be compared. * @return \c true if and only if this is greater than the given * integer. */ bool operator >(Native rhs) const; /** * Determines if this is less than or equal to the given integer. * * @param rhs the integer with which this will be compared. * @return \c true if and only if this is less than or equal to * the given integer. */ bool operator <=(const NNativeInteger& rhs) const; /** * Determines if this is less than or equal to the given integer. * * @param rhs the integer with which this will be compared. * @return \c true if and only if this is less than or equal to * the given integer. */ bool operator <=(Native rhs) const; /** * Determines if this is greater than or equal to the given integer. * * @param rhs the integer with which this will be compared. * @return \c true if and only if this is greater than or equal * to the given integer. */ bool operator >=(const NNativeInteger& rhs) const; /** * Determines if this is greater than or equal to the given integer. * * @param rhs the integer with which this will be compared. * @return \c true if and only if this is greater than or equal * to the given integer. */ bool operator >=(Native rhs) const; /** * The preincrement operator. * This operator increments this integer by one, and returns a * reference to the integer \e after the increment. * * \ifacespython Not available. * * @return a reference to this integer after the increment. */ NNativeInteger& operator ++(); /** * The postincrement operator. * This operator increments this integer by one, and returns a * copy of the integer \e before the increment. * * \ifacespython Not available. * * @return a copy of this integer before the * increment took place. */ NNativeInteger operator ++(int); /** * The predecrement operator. * This operator decrements this integer by one, and returns a * reference to the integer \e after the decrement. * * \ifacespython Not available. * * @return a reference to this integer after the decrement. */ NNativeInteger& operator --(); /** * The postdecrement operator. * This operator decrements this integer by one, and returns a * copy of the integer \e before the decrement. * * \ifacespython Not available. * * @return a copy of this integer before the * decrement took place. */ NNativeInteger operator --(int); /** * Adds this to the given integer and returns the result. * This integer is not changed. * * @param other the integer to add to this integer. * @return the sum \a this plus \a other. */ NNativeInteger operator +(const NNativeInteger& other) const; /** * Adds this to the given integer and returns the result. * This integer is not changed. * * @param other the integer to add to this integer. * @return the sum \a this plus \a other. */ NNativeInteger operator +(Native other) const; /** * Subtracts the given integer from this and returns the result. * This integer is not changed. * * @param other the integer to subtract from this integer. * @return the difference \a this minus \a other. */ NNativeInteger operator -(const NNativeInteger& other) const; /** * Subtracts the given integer from this and returns the result. * This integer is not changed. * * @param other the integer to subtract from this integer. * @return the difference \a this minus \a other. */ NNativeInteger operator -(Native other) const; /** * Multiplies this by the given integer and returns the * result. * This integer is not changed. * * @param other the integer to multiply by this integer. * @return the product \a this times \a other. */ NNativeInteger operator *(const NNativeInteger& other) const; /** * Multiplies this by the given integer and returns the * result. * This integer is not changed. * * @param other the integer to multiply by this integer. * @return the product \a this times \a other. */ NNativeInteger operator *(Native other) const; /** * Divides this by the given integer and returns the result. * The result will be truncated to an integer, i.e. rounded * towards zero. * This integer is not changed. * * For a division routine that always rounds down, see divisionAlg(). * * \pre \a other must be non-zero. * * \warning As I understand it, the direction of rounding for * native C/C++ integer division was fixed in the C++11 * specification, but left to the compiler implementation in * earlier versions of the specification; however, any modern * hardware should satisfy the C++11 rounding rule as described above. * * @param other the integer to divide this by. * @return the quotient \a this divided by \a other. */ NNativeInteger operator /(const NNativeInteger& other) const; /** * Divides this by the given integer and returns the result. * The result will be truncated to an integer, i.e. rounded * towards zero. * This integer is not changed. * * For a division routine that always rounds down, see divisionAlg(). * * \pre \a other must be non-zero. * * \warning As I understand it, the direction of rounding for * native C/C++ integer division was fixed in the C++11 * specification, but left to the compiler implementation in * earlier versions of the specification; however, any modern * hardware should satisfy the C++11 rounding rule as described above. * * @param other the integer to divide this by. * @return the quotient \a this divided by \a other. */ NNativeInteger operator /(Native other) const; /** * Divides this by the given integer and returns the result. * For native integers, this is identical to operator /. * * \pre \a other is not zero. * * @param other the integer to divide this by. * @return the quotient \a this divided by \a other. */ NNativeInteger divExact(const NNativeInteger& other) const; /** * Divides this by the given integer and returns the result. * For native integers, this is identical to operator /. * * \pre \a other is not zero. * * @param other the integer to divide this by. * @return the quotient \a this divided by \a other. */ NNativeInteger divExact(Native other) const; /** * Determines the remainder when this integer is divided by the * given integer. If non-zero, the result will have the same sign * as this integer. * This integer is not changed. * * For a division routine that always returns a non-negative * remainder, see divisionAlg(). * * \pre \a other is not zero. * * \warning As I understand it, the sign of the result under * native C/C++ integer division when the second operand is * negative was fixed in the C++11 specification, but left to the * compiler implementation in earlier versions of the specification; * however, any modern hardware should satisfy the C++11 sign rule * as described above. * * @param other the integer to divide this by. * @return the remainder \a this modulo \a other. */ NNativeInteger operator %(const NNativeInteger& other) const; /** * Determines the remainder when this integer is divided by the * given integer. If non-zero, the result will have the same sign * as this integer. * This integer is not changed. * * For a division routine that always returns a non-negative * remainder, see divisionAlg(). * * \pre \a other is not zero. * * \warning As I understand it, the sign of the result under * native C/C++ integer division when the second operand is * negative was fixed in the C++11 specification, but left to the * compiler implementation in earlier versions of the specification; * however, any modern hardware should satisfy the C++11 sign rule * as described above. * * @param other the integer to divide this by. * @return the remainder \a this modulo \a other. */ NNativeInteger operator %(Native other) const; /** * Uses the division algorithm to obtain a quotient and * remainder when dividing by the given integer. * * Suppose this integer is \a n and we pass the divisor \a d. * The division algorithm describes the result of * dividing \a n by \a d; in particular, it expresses * n = qd + r, where \a q is the quotient and * \a r is the remainder. * * The division algorithm is precise about which values of \a q * and \a r are chosen; in particular it chooses the unique \a r * in the range 0 <= r < |d|. * * Note that this differs from other division routines in this * class, in that it always rounds to give a non-negative remainder. * Thus NNativeInteger(-7).divisionAlg(3) gives quotient -3 and * remainder 2, whereas (-7)/3 gives quotient -2 and (-7)\%3 gives * remainder -1. * * The two results are passed back to the caller as follows: * The quotient \a q is passed back as the return value of the * function, and the remainder \a r is stored in the reference * argument \a r. * * In the special case where the given divisor is 0 (not * allowed by the usual division algorithm), this routine selects * quotient 0 and remainder \a n. * * @param divisor the divisor \a d. * @param remainder used to store the remainder \a r when the * functon returns. The initial value of this argument is ignored. * @return the quotient \a q. * * @author Ryan Budney & B.B. */ NNativeInteger divisionAlg( const NNativeInteger& divisor, NNativeInteger& remainder) const; /** * Determines the negative of this integer. * This integer is not changed. * * @return the negative of this integer. */ NNativeInteger operator -() const; /** * Adds the given integer to this. * This integer is changed to reflect the result. * * @param other the integer to add to this integer. * @return a reference to this integer with its new value. */ NNativeInteger& operator +=(const NNativeInteger& other); /** * Adds the given integer to this. * This integer is changed to reflect the result. * * @param other the integer to add to this integer. * @return a reference to this integer with its new value. */ NNativeInteger& operator +=(Native other); /** * Subtracts the given integer from this. * This integer is changed to reflect the result. * * @param other the integer to subtract from this integer. * @return a reference to this integer with its new value. */ NNativeInteger& operator -=(const NNativeInteger& other); /** * Subtracts the given integer from this. * This integer is changed to reflect the result. * * @param other the integer to subtract from this integer. * @return a reference to this integer with its new value. */ NNativeInteger& operator -=(Native other); /** * Multiplies the given integer by this. * This integer is changed to reflect the result. * * @param other the integer to multiply with this integer. * @return a reference to this integer with its new value. */ NNativeInteger& operator *=(const NNativeInteger& other); /** * Multiplies the given integer by this. * This integer is changed to reflect the result. * * @param other the integer to multiply with this integer. * @return a reference to this integer with its new value. */ NNativeInteger& operator *=(Native other); /** * Divides this by the given integer. * The result will be truncated to an integer, i.e. rounded * towards zero. * This integer is changed to reflect the result. * * For a division routine that always rounds down, see divisionAlg(). * * \pre \a other must be non-zero. * * \warning As I understand it, the direction of rounding for * native C/C++ integer division was fixed in the C++11 * specification, but left to the compiler implementation in * earlier versions of the specification; however, any modern * hardware should satisfy the C++11 rounding rule as described above. * * @param other the integer to divide this by. * @return a reference to this integer with its new value. */ NNativeInteger& operator /=(const NNativeInteger& other); /** * Divides this by the given integer. * The result will be truncated to an integer, i.e. rounded * towards zero. * This integer is changed to reflect the result. * * For a division routine that always rounds down, see divisionAlg(). * * \pre \a other must be non-zero. * * \warning As I understand it, the direction of rounding for * native C/C++ integer division was fixed in the C++11 * specification, but left to the compiler implementation in * earlier versions of the specification; however, any modern * hardware should satisfy the C++11 rounding rule as described above. * * @param other the integer to divide this by. * @return a reference to this integer with its new value. */ NNativeInteger& operator /=(Native other); /** * Divides this by the given integer. * For native integers, this routine is identical to operator /=. * * \pre \a other is not zero. * * @param other the integer to divide this by. * @return a reference to this integer with its new value. */ NNativeInteger& divByExact(const NNativeInteger& other); /** * Divides this by the given integer. * For native integers, this routine is identical to operator /=. * * \pre \a other is not zero. * * @param other the integer to divide this by. * @return a reference to this integer with its new value. */ NNativeInteger& divByExact(Native other); /** * Reduces this integer modulo the given integer. * If non-zero, the result will have the same sign as the original * value of this integer. * This integer is changed to reflect the result. * * For a mod routine that always returns a non-negative * remainder, see divisionAlg(). * * \pre \a other is not zero. * * \warning As I understand it, the sign of the result under * native C/C++ integer division when the second operand is * negative was fixed in the C++11 specification, but left to the * compiler implementation in earlier versions of the specification; * however, any modern hardware should satisfy the C++11 sign rule * as described above. * * @param other the integer modulo which this integer will be * reduced. * @return a reference to this integer with its new value. */ NNativeInteger& operator %=(const NNativeInteger& other); /** * Reduces this integer modulo the given integer. * If non-zero, the result will have the same sign as the original * value of this integer. * This integer is changed to reflect the result. * * For a mod routine that always returns a non-negative * remainder, see divisionAlg(). * * \pre \a other is not zero. * * \warning As I understand it, the sign of the result under * native C/C++ integer division when the second operand is * negative was fixed in the C++11 specification, but left to the * compiler implementation in earlier versions of the specification; * however, any modern hardware should satisfy the C++11 sign rule * as described above. * * @param other the integer modulo which this integer will be * reduced. * @return a reference to this integer with its new value. */ NNativeInteger& operator %=(Native other); /** * Negates this integer. * This integer is changed to reflect the result. */ void negate(); /** * Sets this integer to be the greatest common divisor of this * and the given integer. * * The result is guaranteed to be non-negative. As a * special case, gcd(0,0) is considered to be zero. * * @param other the integer whose greatest common divisor with * this will be found. */ void gcdWith(const NNativeInteger& other); /** * Determines the greatest common divisor of this and the given * integer. This integer is not changed. * * The result is guaranteed to be non-negative. As a * special case, gcd(0,0) is considered to be zero. * * @param other the integer whose greatest common divisor with * this will be found. * @return the greatest common divisor of this and the given * integer. */ NNativeInteger gcd(const NNativeInteger& other) const; template friend std::ostream& operator << (std::ostream& out, const NNativeInteger& large); }; /** * Writes the given integer to the given output stream. * * @param out the output stream to which to write. * @param i the integer to write. * @return a reference to \a out. */ template REGINA_API std::ostream& operator << (std::ostream& out, const NNativeInteger& i); /** * NNativeLong is a typedef for the NNativeInteger template class whose * underlying integer type is a native long. * * \ifacespython Not present. */ typedef NNativeInteger NNativeLong; /*@}*/ // Inline functions for NIntegerBase template inline NIntegerBase::NIntegerBase() : small_(0), large_(0) { } template inline NIntegerBase::NIntegerBase(int value) : small_(value), large_(0) { } template inline NIntegerBase::NIntegerBase(unsigned value) : small_(value) { // Detect overflow. if (small_ < 0) { large_ = new mpz_t; mpz_init_set_ui(large_, value); } else large_ = 0; } template inline NIntegerBase::NIntegerBase(long value) : small_(value), large_(0) { } template inline NIntegerBase::NIntegerBase(unsigned long value) : small_(value) { // Detect overflow. if (small_ < 0) { large_ = new mpz_t; mpz_init_set_ui(large_, value); } else large_ = 0; } template inline NIntegerBase::NIntegerBase( const NIntegerBase& value) { if (value.isInfinite()) { large_ = 0; makeInfinite(); } else if (value.large_) { large_ = new mpz_t; mpz_init_set(large_, value.large_); } else { small_ = value.small_; large_ = 0; } } template inline NIntegerBase::NIntegerBase( const NIntegerBase& value) { // If value is infinite, we cannot make this infinite. // This is why we insist via preconditions that value is finite. if (value.large_) { large_ = new mpz_t; mpz_init_set(large_, value.large_); } else { small_ = value.small_; large_ = 0; } } template template inline NIntegerBase::NIntegerBase( const NNativeInteger& value) : small_(value.nativeValue()), large_(0) { BOOST_STATIC_ASSERT(bytes % sizeof(long) == 0); if (sizeof(long) < bytes && value.nativeValue() != small_) { // It didn't fit. Take things one long at a time. unsigned blocks = bytes / sizeof(long); large_ = new mpz_t; mpz_init_set_si(large_, static_cast( value.nativeValue() >> ((blocks - 1) * 8 * sizeof(long)))); for (unsigned i = 2; i <= blocks; ++i) { mpz_mul_2exp(large_, large_, 8 * sizeof(long)); mpz_add_ui(large_, large_, static_cast( value.nativeValue() >> ((blocks - i) * 8 * sizeof(long)))); } } } template template inline typename IntOfSize::type NIntegerBase::nativeValue() const { typedef typename IntOfSize::type Native; typedef typename IntOfSize::utype UNative; BOOST_STATIC_ASSERT(bytes % sizeof(long) == 0); if (sizeof(long) >= bytes || ! large_) { // Suppose this integer lies within the given byte range. // If sizeof(long) >= bytes, then it can be made to fit inside a long. // If sizeof(long) < bytes but this is a native long, then we // have already got it inside a long. // Either way, we can just pass the long value across. return static_cast(longValue()); } // From here: this is a GMP integer, and the return type is too // large for a long. Take one long-sized chunk at a time. Native ans = 0; unsigned blocks = bytes / sizeof(long); mpz_t tmp; mpz_init_set(tmp, large_); for (unsigned i = 0; i < blocks - 1; ++i) { ans += (static_cast(mpz_get_ui(tmp)) << (i * 8 * sizeof(long))); mpz_fdiv_q_2exp(tmp, tmp, 8 * sizeof(long)); } ans += (static_cast(mpz_get_si(tmp)) << ((blocks - 1) * 8 * sizeof(long))); mpz_clear(tmp); return ans; } template inline NIntegerBase::~NIntegerBase() { if (large_) { mpz_clear(large_); delete[] large_; } } template inline bool NIntegerBase::isNative() const { return (! isInfinite()) && (! large_); } template inline bool NIntegerBase::isZero() const { return (! isInfinite()) && (((! large_) && (! small_)) || (large_ && mpz_sgn(large_) == 0)); } template inline int NIntegerBase::sign() const { return (isInfinite() ? 1 : large_ ? mpz_sgn(large_) : small_ > 0 ? 1 : small_ < 0 ? -1 : 0); } template <> inline bool NIntegerBase::isInfinite() const { return infinite_; } template <> inline bool NIntegerBase::isInfinite() const { return false; } template <> inline void NIntegerBase::makeInfinite() { infinite_ = true; if (large_) clearLarge(); } template <> inline void NIntegerBase::makeInfinite() { } template inline long NIntegerBase::longValue() const { return (large_ ? mpz_get_si(large_) : small_); } template inline NIntegerBase& NIntegerBase::operator =( const NIntegerBase& value) { if (value.isInfinite()) { makeInfinite(); return *this; } makeFinite(); if (value.large_) { if (large_) mpz_set(large_, value.large_); else { large_ = new mpz_t; mpz_init_set(large_, value.large_); } } else { small_ = value.small_; if (large_) clearLarge(); } return *this; } template inline NIntegerBase& NIntegerBase::operator =( const NIntegerBase& value) { // If value is infinite, we cannot make this infinite. // This is why we insist via preconditions that value is finite. makeFinite(); if (value.large_) { if (large_) mpz_set(large_, value.large_); else { large_ = new mpz_t; mpz_init_set(large_, value.large_); } } else { small_ = value.small_; if (large_) clearLarge(); } return *this; } template inline NIntegerBase& NIntegerBase::operator =(int value) { makeFinite(); small_ = value; if (large_) clearLarge(); return *this; } template inline NIntegerBase& NIntegerBase::operator =(unsigned value) { makeFinite(); small_ = value; // Did we overflow? if (small_ < 0) { // Yes, it's an overflow: just a bit too large for a signed long // (literally). if (large_) mpz_set_ui(large_, value); else { large_ = new mpz_t; mpz_init_set_ui(large_, value); } } else if (large_) { // No overflow, but we must clear out any old large integer value. clearLarge(); } return *this; } template inline NIntegerBase& NIntegerBase::operator =(long value) { makeFinite(); small_ = value; if (large_) clearLarge(); return *this; } template inline NIntegerBase& NIntegerBase::operator =(unsigned long value) { makeFinite(); small_ = value; // Did we overflow? if (small_ < 0) { // Yes, it's an overflow: just a bit too large for a signed long // (literally). if (large_) mpz_set_ui(large_, value); else { large_ = new mpz_t; mpz_init_set_ui(large_, value); } } else if (large_) { // No overflow, but we must clear out any old large integer value. clearLarge(); } return *this; } template inline NIntegerBase& NIntegerBase::operator =(const std::string& value) { return (*this) = value.c_str(); } template <> inline void NIntegerBase::swap(NIntegerBase& other) { // This should just work, since large_ is a pointer. std::swap(infinite_, other.infinite_); std::swap(small_, other.small_); std::swap(large_, other.large_); } template <> inline void NIntegerBase::swap(NIntegerBase& other) { // This should just work, since large_ is a pointer. std::swap(small_, other.small_); std::swap(large_, other.large_); } template inline bool NIntegerBase::operator ==( const NIntegerBase& rhs) const { if (isInfinite() && rhs.isInfinite()) return true; else if (isInfinite() || rhs.isInfinite()) return false; else if (large_) { if (rhs.large_) return (mpz_cmp(large_, rhs.large_) == 0); else return (mpz_cmp_si_cpp(large_, rhs.small_) == 0); } else { if (rhs.large_) return (mpz_cmp_si_cpp(rhs.large_, small_) == 0); else return (small_ == rhs.small_); } } template inline bool NIntegerBase::operator ==( const NIntegerBase& rhs) const { // The types are different, so both cannot be infinity. if (isInfinite() || rhs.isInfinite()) return false; else if (large_) { if (rhs.large_) return (mpz_cmp(large_, rhs.large_) == 0); else return (mpz_cmp_si_cpp(large_, rhs.small_) == 0); } else { if (rhs.large_) return (mpz_cmp_si_cpp(rhs.large_, small_) == 0); else return (small_ == rhs.small_); } } template inline bool NIntegerBase::operator ==(long rhs) const { if (isInfinite()) return false; else if (large_) return (mpz_cmp_si_cpp(large_, rhs) == 0); else return (small_ == rhs); } template inline bool NIntegerBase::operator !=( const NIntegerBase& rhs) const { if (isInfinite() && rhs.isInfinite()) return false; else if (isInfinite() || rhs.isInfinite()) return true; else if (large_) { if (rhs.large_) return (mpz_cmp(large_, rhs.large_) != 0); else return (mpz_cmp_si_cpp(large_, rhs.small_) != 0); } else { if (rhs.large_) return (mpz_cmp_si_cpp(rhs.large_, small_) != 0); else return (small_ != rhs.small_); } } template inline bool NIntegerBase::operator !=( const NIntegerBase& rhs) const { // The types are different, so both cannot be infinity. if (isInfinite() || rhs.isInfinite()) return true; else if (large_) { if (rhs.large_) return (mpz_cmp(large_, rhs.large_) != 0); else return (mpz_cmp_si_cpp(large_, rhs.small_) != 0); } else { if (rhs.large_) return (mpz_cmp_si_cpp(rhs.large_, small_) != 0); else return (small_ != rhs.small_); } } template inline bool NIntegerBase::operator !=(long rhs) const { if (isInfinite()) return true; else if (large_) return (mpz_cmp_si_cpp(large_, rhs) != 0); else return (small_ != rhs); } template inline bool NIntegerBase::operator <( const NIntegerBase& rhs) const { if (isInfinite()) return false; else if (rhs.isInfinite()) return true; else if (large_) { if (rhs.large_) return (mpz_cmp(large_, rhs.large_) < 0); else return (mpz_cmp_si_cpp(large_, rhs.small_) < 0); } else { if (rhs.large_) return (mpz_cmp_si_cpp(rhs.large_, small_) > 0); // back-to-front else return (small_ < rhs.small_); } } template inline bool NIntegerBase::operator <(long rhs) const { if (isInfinite()) return false; else if (large_) return (mpz_cmp_si_cpp(large_, rhs) < 0); else return (small_ < rhs); } template inline bool NIntegerBase::operator >( const NIntegerBase& rhs) const { if (rhs.isInfinite()) return false; else if (isInfinite()) return true; else if (large_) { if (rhs.large_) return (mpz_cmp(large_, rhs.large_) > 0); else return (mpz_cmp_si_cpp(large_, rhs.small_) > 0); } else { if (rhs.large_) return (mpz_cmp_si_cpp(rhs.large_, small_) < 0); // back-to-front else return (small_ > rhs.small_); } } template inline bool NIntegerBase::operator >(long rhs) const { if (isInfinite()) return true; else if (large_) return (mpz_cmp_si_cpp(large_, rhs) > 0); else return (small_ > rhs); } template inline bool NIntegerBase::operator <=( const NIntegerBase& rhs) const { if (rhs.isInfinite()) return true; else if (isInfinite()) return false; else if (large_) { if (rhs.large_) return (mpz_cmp(large_, rhs.large_) <= 0); else return (mpz_cmp_si_cpp(large_, rhs.small_) <= 0); } else { if (rhs.large_) return (mpz_cmp_si_cpp(rhs.large_, small_) >= 0); // back-to-front else return (small_ <= rhs.small_); } } template inline bool NIntegerBase::operator <=(long rhs) const { if (isInfinite()) return false; else if (large_) return (mpz_cmp_si_cpp(large_, rhs) <= 0); else return (small_ <= rhs); } template inline bool NIntegerBase::operator >=( const NIntegerBase& rhs) const { if (isInfinite()) return true; else if (rhs.isInfinite()) return false; else if (large_) { if (rhs.large_) return (mpz_cmp(large_, rhs.large_) >= 0); else return (mpz_cmp_si_cpp(large_, rhs.small_) >= 0); } else { if (rhs.large_) return (mpz_cmp_si_cpp(rhs.large_, small_) <= 0); // back-to-front else return (small_ >= rhs.small_); } } template inline bool NIntegerBase::operator >=(long rhs) const { if (isInfinite()) return true; else if (large_) return (mpz_cmp_si_cpp(large_, rhs) >= 0); else return (small_ >= rhs); } template inline NIntegerBase& NIntegerBase::operator ++() { if (! isInfinite()) { if (large_) mpz_add_ui(large_, large_, 1); else if (small_ != LONG_MAX) ++small_; else { // This is the point at which we overflow. forceLarge(); mpz_add_ui(large_, large_, 1); } } return *this; } template inline NIntegerBase NIntegerBase::operator ++(int) { if (isInfinite()) return *this; // Hrmph, just do the standard thing for now. // It's not clear how much microoptimisation will help..? NIntegerBase ans(*this); ++(*this); return ans; } template inline NIntegerBase& NIntegerBase::operator --() { if (! isInfinite()) { if (large_) mpz_sub_ui(large_, large_, 1); else if (small_ != LONG_MIN) --small_; else { // This is the point at which we overflow. forceLarge(); mpz_sub_ui(large_, large_, 1); } } return *this; } template inline NIntegerBase NIntegerBase::operator --(int) { if (isInfinite()) return *this; // Hrmph, just do the standard thing for now. // It's not clear how much microoptimisation will help..? NIntegerBase ans(*this); --(*this); return ans; } template inline NIntegerBase NIntegerBase::operator +( const NIntegerBase& other) const { if (isInfinite()) return *this; if (other.isInfinite()) return other; // Do the standard thing for now. NIntegerBase ans(*this); return ans += other; } template inline NIntegerBase NIntegerBase::operator +(long other) const { if (isInfinite()) return *this; // Do the standard thing for now. NIntegerBase ans(*this); return ans += other; } template inline NIntegerBase NIntegerBase::operator -( const NIntegerBase& other) const { if (isInfinite()) return *this; if (other.isInfinite()) return other; // Do the standard thing for now. NIntegerBase ans(*this); return ans -= other; } template inline NIntegerBase NIntegerBase::operator -(long other) const { if (isInfinite()) return *this; // Do the standard thing for now. NIntegerBase ans(*this); return ans -= other; } template inline NIntegerBase NIntegerBase::operator *( const NIntegerBase& other) const { if (isInfinite()) return *this; if (other.isInfinite()) return other; // Do the standard thing for now. NIntegerBase ans(*this); return ans *= other; } template inline NIntegerBase NIntegerBase::operator *(long other) const { if (isInfinite()) return *this; // Do the standard thing for now. NIntegerBase ans(*this); return ans *= other; } template inline NIntegerBase NIntegerBase::operator /( const NIntegerBase& other) const { if (isInfinite()) return *this; if (other.isInfinite()) return (long)0; if (other.isZero()) { NIntegerBase ans; ans.makeInfinite(); return ans; } // Do the standard thing for now. NIntegerBase ans(*this); return ans /= other; } template inline NIntegerBase NIntegerBase::operator /(long other) const { if (isInfinite()) return *this; if (other == 0) { NIntegerBase ans; ans.makeInfinite(); return ans; } // Do the standard thing for now. NIntegerBase ans(*this); return ans /= other; } template inline NIntegerBase NIntegerBase::divExact( const NIntegerBase& other) const { // Do the standard thing for now. NIntegerBase ans(*this); return ans.divByExact(other); } template inline NIntegerBase NIntegerBase::divExact(long other) const { // Do the standard thing for now. NIntegerBase ans(*this); return ans.divByExact(other); } template inline NIntegerBase NIntegerBase::operator %( const NIntegerBase& other) const { // Do the standard thing for now. NIntegerBase ans(*this); return ans %= other; } template inline NIntegerBase NIntegerBase::operator %(long other) const { // Do the standard thing for now. NIntegerBase ans(*this); return ans %= other; } template inline NIntegerBase NIntegerBase::operator -() const { if (isInfinite()) return *this; if (large_) { NIntegerBase ans; ans.large_ = new mpz_t; mpz_init(ans.large_); mpz_neg(ans.large_, large_); return ans; } else if (small_ == LONG_MIN) { // Overflow, just. NIntegerBase ans; ans.large_ = new mpz_t; mpz_init_set_si(ans.large_, small_); mpz_neg(ans.large_, ans.large_); return ans; } else return NIntegerBase(-small_); } template inline NIntegerBase& NIntegerBase::operator +=( const NIntegerBase& other) { if (isInfinite()) return *this; else if (other.isInfinite()) { makeInfinite(); return *this; } if (other.large_) { if (! large_) forceLarge(); mpz_add(large_, large_, other.large_); return *this; } else return (*this) += other.small_; } template inline NIntegerBase& NIntegerBase::operator -=( const NIntegerBase& other) { if (isInfinite()) return *this; else if (other.isInfinite()) { makeInfinite(); return *this; } if (other.large_) { if (! large_) forceLarge(); mpz_sub(large_, large_, other.large_); return *this; } else return (*this) -= other.small_; } template inline void NIntegerBase::negate() { if (isInfinite()) return; if (large_) mpz_neg(large_, large_); else if (small_ == LONG_MIN) { // Overflow, just. forceLarge(); mpz_neg(large_, large_); } else small_ = -small_; } template inline NIntegerBase NIntegerBase::abs() const { if (isInfinite()) return *this; if (large_) { NIntegerBase ans; ans.large_ = new mpz_t; mpz_init_set(ans.large_, large_); mpz_abs(ans.large_, large_); return ans; } else if (small_ == LONG_MIN) { // Overflow, just. NIntegerBase ans; ans.large_ = new mpz_t; mpz_init_set_si(ans.large_, small_); mpz_neg(ans.large_, ans.large_); return ans; } else return NIntegerBase(small_ >= 0 ? small_ : - small_); } template NIntegerBase NIntegerBase::gcd( const NIntegerBase& other) const { // Do the standard thing for now. NIntegerBase ans(*this); ans.gcdWith(other); return ans; } template NIntegerBase NIntegerBase::lcm( const NIntegerBase& other) const { // Do the standard thing for now. NIntegerBase ans(*this); ans.lcmWith(other); return ans; } template inline NIntegerBase operator +(long lhs, const NIntegerBase& rhs) { return rhs + lhs; } template inline NIntegerBase operator *(long lhs, const NIntegerBase& rhs) { return rhs * lhs; } template inline void NIntegerBase::setRaw(mpz_srcptr fromData) { makeFinite(); if (! large_) { large_ = new mpz_t; mpz_init_set(large_, fromData); } else { mpz_set(large_, fromData); } } template inline mpz_srcptr NIntegerBase::rawData() const { // Cast away the const, since we are not changing the mathematical value. // We are, however, bulking up the representation. const_cast&>(*this).makeLarge(); return large_; } template inline mpz_ptr NIntegerBase::rawData() { makeLarge(); return large_; } template inline void NIntegerBase::makeLarge() { if (! large_) forceLarge(); } template inline void NIntegerBase::tryReduce() { if (large_ && mpz_cmp_si(large_, LONG_MAX) <= 0 && mpz_cmp_si(large_, LONG_MIN) >= 0) forceReduce(); } template inline void NIntegerBase::forceLarge() { large_ = new mpz_t; mpz_init_set_si(large_, small_); } template inline void NIntegerBase::clearLarge() { mpz_clear(large_); delete[] large_; large_ = 0; } template inline void NIntegerBase::forceReduce() { small_ = mpz_get_si(large_); mpz_clear(large_); delete[] large_; large_ = 0; } template <> inline void NIntegerBase::makeFinite() { infinite_ = false; } template <> inline void NIntegerBase::makeFinite() { } // This definition must come *after* the definition of makeInfinite() // to keep the compiler happy. template <> inline NIntegerBase::NIntegerBase(bool, bool) : large_(0) { // The infinity constructor. makeInfinite(); } // Inline functions for NNativeInteger template inline NNativeInteger::NNativeInteger() : data_(0) { } template inline NNativeInteger::NNativeInteger(Native value) : data_(value) { } template inline NNativeInteger::NNativeInteger( const NNativeInteger& value) : data_(value.data_) { } template template inline NNativeInteger::NNativeInteger( const NIntegerBase& value) : data_(value.template nativeValue()) { } template inline bool NNativeInteger::isZero() const { return (data_ == 0); } template inline int NNativeInteger::sign() const { return (data_ > 0 ? 1 : data_ < 0 ? -1 : 0); } template inline typename NNativeInteger::Native NNativeInteger:: nativeValue() const { return data_; } template inline NNativeInteger& NNativeInteger::operator =( const NNativeInteger& value) { data_ = value.data_; return *this; } template inline NNativeInteger& NNativeInteger::operator =(Native value) { data_ = value; return *this; } template inline void NNativeInteger::swap(NNativeInteger& other) { std::swap(data_, other.data_); } template inline bool NNativeInteger::operator ==( const NNativeInteger& rhs) const { return (data_ == rhs.data_); } template inline bool NNativeInteger::operator ==(Native rhs) const { return (data_ == rhs); } template inline bool NNativeInteger::operator !=( const NNativeInteger& rhs) const { return (data_ != rhs.data_); } template inline bool NNativeInteger::operator !=(Native rhs) const { return (data_ != rhs); } template inline bool NNativeInteger::operator <( const NNativeInteger& rhs) const { return (data_ < rhs.data_); } template inline bool NNativeInteger::operator <(Native rhs) const { return (data_ < rhs); } template inline bool NNativeInteger::operator >( const NNativeInteger& rhs) const { return (data_ > rhs.data_); } template inline bool NNativeInteger::operator >(Native rhs) const { return (data_ > rhs); } template inline bool NNativeInteger::operator <=( const NNativeInteger& rhs) const { return (data_ <= rhs.data_); } template inline bool NNativeInteger::operator <=(Native rhs) const { return (data_ <= rhs); } template inline bool NNativeInteger::operator >=( const NNativeInteger& rhs) const { return (data_ >= rhs.data_); } template inline bool NNativeInteger::operator >=(Native rhs) const { return (data_ >= rhs); } template inline NNativeInteger& NNativeInteger::operator ++() { ++data_; return *this; } template inline NNativeInteger NNativeInteger::operator ++(int) { return NNativeInteger(data_++); } template inline NNativeInteger& NNativeInteger::operator --() { --data_; return *this; } template inline NNativeInteger NNativeInteger::operator --(int) { return NNativeInteger(data_--); } template inline NNativeInteger NNativeInteger::operator +( const NNativeInteger& other) const { return NNativeInteger(data_ + other.data_); } template inline NNativeInteger NNativeInteger::operator +( Native other) const { return NNativeInteger(data_ + other); } template inline NNativeInteger NNativeInteger::operator -( const NNativeInteger& other) const { return NNativeInteger(data_ - other.data_); } template inline NNativeInteger NNativeInteger::operator -( Native other) const { return NNativeInteger(data_ - other); } template inline NNativeInteger NNativeInteger::operator *( const NNativeInteger& other) const { return NNativeInteger(data_ * other.data_); } template inline NNativeInteger NNativeInteger::operator *( Native other) const { return NNativeInteger(data_ * other); } template inline NNativeInteger NNativeInteger::operator /( const NNativeInteger& other) const { return NNativeInteger(data_ / other.data_); } template inline NNativeInteger NNativeInteger::operator /( Native other) const { return NNativeInteger(data_ / other); } template inline NNativeInteger NNativeInteger::divExact( const NNativeInteger& other) const { return NNativeInteger(data_ / other.data_); } template inline NNativeInteger NNativeInteger::divExact( Native other) const { return NNativeInteger(data_ / other); } template inline NNativeInteger NNativeInteger::operator %( const NNativeInteger& other) const { return NNativeInteger(data_ % other.data_); } template inline NNativeInteger NNativeInteger::operator %( Native other) const { return NNativeInteger(data_ % other); } template inline NNativeInteger NNativeInteger::divisionAlg( const NNativeInteger& divisor, NNativeInteger& remainder) const { if (divisor == 0) { remainder.data_ = data_; return 0; } // Native integer division could leave a negative remainder // regardless of the sign of the divisor (I think the standard // indicates that the decision is based on the sign of *this?). NNativeInteger quotient = data_ / divisor.data_; remainder = data_ - (quotient.data_ * divisor.data_); if (remainder.data_ < 0) { if (divisor.data_ > 0) { remainder.data_ += divisor.data_; --quotient.data_; } else { remainder.data_ -= divisor.data_; ++quotient.data_; } } return quotient; } template inline NNativeInteger NNativeInteger::operator -() const { return NNativeInteger(- data_); } template inline NNativeInteger& NNativeInteger::operator += ( const NNativeInteger& other) { data_ += other.data_; return *this; } template inline NNativeInteger& NNativeInteger::operator += ( Native other) { data_ += other; return *this; } template inline NNativeInteger& NNativeInteger::operator -= ( const NNativeInteger& other) { data_ -= other.data_; return *this; } template inline NNativeInteger& NNativeInteger::operator -= ( Native other) { data_ -= other; return *this; } template inline NNativeInteger& NNativeInteger::operator *= ( const NNativeInteger& other) { data_ *= other.data_; return *this; } template inline NNativeInteger& NNativeInteger::operator *= ( Native other) { data_ *= other; return *this; } template inline NNativeInteger& NNativeInteger::operator /= ( const NNativeInteger& other) { data_ /= other.data_; return *this; } template inline NNativeInteger& NNativeInteger::operator /= ( Native other) { data_ /= other; return *this; } template inline NNativeInteger& NNativeInteger::divByExact( const NNativeInteger& other) { data_ /= other.data_; return *this; } template inline NNativeInteger& NNativeInteger::divByExact(Native other) { data_ /= other; return *this; } template inline NNativeInteger& NNativeInteger::operator %= ( const NNativeInteger& other) { data_ %= other.data_; return *this; } template inline NNativeInteger& NNativeInteger::operator %= ( Native other) { data_ %= other; return *this; } template inline void NNativeInteger::negate() { data_ = - data_; } template void NNativeInteger::gcdWith(const NNativeInteger& other) { Native a = data_; Native b = other.data_; if (a < 0) a = -a; if (b < 0) b = -b; /** * Now everything is non-negative. * The following code is based on Stein's binary GCD algorithm. */ if (! a) { data_ = b; return; } if (! b) { data_ = a; return; } // Compute the largest common power of 2. int pow2; for (pow2 = 0; ! ((a | b) & 1); ++pow2) { a >>= 1; b >>= 1; } // Strip out all remaining powers of 2 from a and b. while (! (a & 1)) a >>= 1; while (! (b & 1)) b >>= 1; while (a != b) { // INV: a and b are both odd and non-zero. if (a < b) { b -= a; do b >>= 1; while (! (b & 1)); } else { a -= b; do a >>= 1; while (! (a & 1)); } } data_ = (a << pow2); } template inline NNativeInteger NNativeInteger::gcd( const NNativeInteger& other) const { NNativeInteger ans(data_); ans.gcdWith(other); return ans; } template inline std::ostream& operator << (std::ostream& out, const NNativeInteger& i) { return out << i.data_; } #ifdef INT128_AVAILABLE template <> inline std::ostream& operator << (std::ostream& out, const NNativeInteger<16>& i) { // The standard library does not support 128-bit integers (at least not // always). Go through NInteger and GMP instead (for now). return out << NInteger(i); } #endif } // namespace regina #endif regina-4.96/engine/maths/nlargeinteger.h000644 000765 000024 00000005201 12377775263 020211 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file maths/nlargeinteger.h * \brief A deprecated header for dealing with arbitrary precision integers. */ #ifndef __NLARGEINTEGER_H #ifndef __DOXYGEN #define __NLARGEINTEGER_H #endif #warning This header is deprecated; please use maths/ninteger.h instead. #include "maths/ninteger.h" namespace regina { /** * \weakgroup maths * @{ */ /*@}*/ } // namespace regina #endif regina-4.96/engine/maths/nmatrix.h000644 000765 000024 00000063653 12377775264 017065 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file maths/nmatrix.h * \brief Deals with matrices of elements of various types. */ #ifndef __NMATRIX_H #ifndef __DOXYGEN #define __NMATRIX_H #endif #include #include #include "regina-core.h" namespace regina { /** * \weakgroup maths * @{ */ /** * Represents a matrix of elements of the given type T. * * \pre Type T has a default constructor and overloads the assignment * (=) operator. * \pre An element t of type T can be written to an output stream * out using the standard expression out << t. * * \ifacespython Not present, although the subclass NMatrixInt is. */ template class NMatrix { protected: unsigned long nRows; /**< The number of rows in the matrix. */ unsigned long nCols; /**< The number of columns in the matrix. */ T** data; /**< The actual entries in the matrix. * data[r][c] is the element in row \a r, * column \a c. */ public: /** * Creates a new matrix of the given size. * All entries will be initialised using their default * constructors. * * \pre The given number of rows and columns are * both strictly positive. * * @param rows the number of rows in the new matrix. * @param cols the number of columns in the new matrix. */ NMatrix(unsigned long rows, unsigned long cols) : nRows(rows), nCols(cols), data(new T*[rows]){ for (unsigned long i = 0; i < rows; i++) data[i] = new T[cols]; } /** * Creates a new matrix that is a clone of the given matrix. * * @param cloneMe the matrix to clone. */ NMatrix(const NMatrix& cloneMe) : nRows(cloneMe.nRows), nCols(cloneMe.nCols), data(new T*[cloneMe.nRows]) { unsigned long r, c; for (r = 0; r < nRows; r++) { data[r] = new T[nCols]; for (c = 0; c < nCols; c++) data[r][c] = cloneMe.data[r][c]; } } /** * Destroys this matrix. */ virtual ~NMatrix() { for (unsigned long i = 0; i < nRows; i++) delete[] data[i]; delete[] data; } /** * Sets every entry in the matrix to the given value. * * @param value the value to assign to each entry. */ void initialise(const T& value) { unsigned long r, c; for (r = 0; r < nRows; r++) for (c = 0; c < nCols; c++) data[r][c] = value; } #ifdef __DOXYGEN /** * A Python-only routine that fills the matrix with the given * set of elements. * * The argument \a allValues must be a Python list of length * rows() * columns(). Its values will be inserted into the * matrix row by row (i.e., the first row will be filled, then * the second row, and so on). * * \ifacescpp Not available; this routine is for Python only. * * @param allValues the individual elements to place into the matrix. */ void initialise(List allValues); #endif /** * Returns the number of rows in this matrix. * * @return the number of rows. */ unsigned long rows() const { return nRows; } /** * Returns the number of columns in this matrix. * * @return the number of columns. */ unsigned long columns() const { return nCols; } /** * Returns the entry at the given row and column. * Rows and columns are numbered beginning at zero. * * \pre \a row is between 0 and rows()-1 inclusive. * \pre \a column is between 0 and columns()-1 inclusive. * * \ifacespython Although the entry() routine gives direct * read-write access to matrix elements, the syntax * matrix.entry(row, column) = value still cannot be * used in python to set a matrix element directly. For this, * you can use the syntax matrix.set(row, column, value). * This set() routine returns nothing, and is provided for python * only (i.e., it is not part of the C++ calculation engine). * * @param row the row of the desired entry. * @param column the column of the desired entry. * @return a reference to the entry in the given row and column. */ T& entry(unsigned long row, unsigned long column) { return data[row][column]; } /** * Returns the entry at the given row and column. * Rows and columns are numbered beginning at zero. * * \pre \a row is between 0 and rows()-1 inclusive. * \pre \a column is between 0 and columns()-1 inclusive. * * \ifacespython Not present, although the non-const form of * this routine is. * * @param row the row of the desired entry. * @param column the column of the desired entry. * @return a reference to the entry in the given row and column. */ const T& entry(unsigned long row, unsigned long column) const { return data[row][column]; } /** * Determines whether this and the given matrix are identical. * * Two matrices are identical if and only if (i) their dimensions * are the same, and (ii) the corresponding elements of each * matrix are equal. * * Note that this routine can happily deal with two matrices of * different dimensions (in which case it will always return * \c false). * * This routine returns \c true if and only if the inequality operator * (!=) returns \c false. * * \pre The type \a T provides an equality operator (==). * * @param other the matrix to compare with this. * @return \c true if the matrices are equal as described above, * or \c false otherwise. */ bool operator == (const NMatrix& other) const { if (nRows != other.nRows || nCols != other.nCols) return false; unsigned long r, c; for (r = 0; r < nRows; ++r) for (c = 0; c < nCols; ++c) if (! (data[r][c] == other.data[r][c])) return false; return true; } /** * Determines whether this and the given matrix are different. * * Two matrices are different if either (i) their dimensions * differ, or (ii) the corresponding elements of each matrix differ * in at least one location. * * Note that this routine can happily deal with two matrices of * different dimensions (in which case it will always return * \c true). * * This routine returns \c true if and only if the equality operator * (==) returns \c false. * * \pre The type \a T provides an equality operator (==). * * @param other the matrix to compare with this. * @return \c true if the matrices are different as described above, * or \c false otherwise. */ bool operator != (const NMatrix& other) const { return ! ((*this) == other); } /** * Writes a complete representation of the matrix to the given * output stream. * Each row will be written on a separate line with elements in * each row separated by single spaces. * * \ifacespython Not present, even if a subclass of NMatrix * is mirrored and its inherited routines are mirrored also. * * @param out the output stream to which to write. */ virtual void writeMatrix(std::ostream& out) const { unsigned long r, c; for (r = 0; r < nRows; r++) { for (c = 0; c < nCols; c++) { if (c > 0) out << ' '; out << data[r][c]; } out << '\n'; } } /** * Swaps the elements of the two given rows in the matrix. * * \pre The two given rows are between 0 and rows()-1 inclusive. * * @param first the first row to swap. * @param second the second row to swap. */ void swapRows(unsigned long first, unsigned long second) { T tmp; for (unsigned long i = 0; i < nCols; i++) { tmp = data[first][i]; data[first][i] = data[second][i]; data[second][i] = tmp; } } /** * Swaps the elements of the two given columns in the matrix. * * \pre The two given columns are between 0 and columns()-1 inclusive. * * @param first the first column to swap. * @param second the second column to swap. */ void swapColumns(unsigned long first, unsigned long second) { T tmp; for (unsigned long i = 0; i < nRows; i++) { tmp = data[i][first]; data[i][first] = data[i][second]; data[i][second] = tmp; } } }; /** * Represents a matrix of elements from a given ring T. * * Note that many important functions (such as entry()) are inherited * from the parent class NMatrix, and are not documented again here. * * \pre Type T has a default constructor and overloads the assignment * (=) operator. * \pre An element t of type T can be written to an output stream * out using the standard expression out << t. * \pre Type T provides binary operators +, - and * * and unary operators +=, -= and *=. * \pre Type T has a long integer constructor. That is, if \c a is of type T, * then \c a can be initialised to a long integer \c l using a(l). * Here the value 1 refers to the multiplicative identity in the ring T. * * \ifacespython Not present, although the subclass NMatrixInt is. */ template class NMatrixRing : public NMatrix { public: static T zero; /**< Zero in the underlying ring. * This would be \c const if it weren't for the fact that * some compilers don't like this. It should never be * modified! */ static T one; /**< One (the multiplicative identity) in the underlying ring. * This would be \c const if it weren't for the fact that * some compilers don't like this. It should never be * modified! */ public: /** * Creates a new matrix of the given size. * All entries will be initialised using their default * constructors. * * \pre The given number of rows and columns are * both strictly positive. * * @param rows the number of rows in the new matrix. * @param cols the number of columns in the new matrix. */ NMatrixRing(unsigned long rows, unsigned long cols) : NMatrix(rows, cols) { } /** * Creates a new matrix that is a clone of the given matrix. * * @param cloneMe the matrix to clone. */ NMatrixRing(const NMatrix& cloneMe) : NMatrix(cloneMe) { } /** * Turns this matrix into an identity matrix. * This matrix need not be square; after this routine it will * have entry(r,c) equal to one if * r == c and zero otherwise. */ void makeIdentity() { this->initialise(zero); for (unsigned long i = 0; i < this->nRows && i < this->nCols; i++) this->data[i][i] = one; } /** * Determines whether this matrix is a square identity matrix. * * If this matrix is square, isIdentity() will return \c true if * and only if the matrix has ones in the main diagonal and zeroes * everywhere else. * * If this matrix is not square, isIdentity() will always return * \c false (even if makeIdentity() was called earlier). * * @return \c true if and only if this is a square identity matrix. */ bool isIdentity() const { if (this->nRows != this->nCols) return false; unsigned long r, c; for (r = 0; r < this->nRows; ++r) for (c = 0; c < this->nCols; ++c) { if (r == c && this->data[r][c] != one) return false; if (r != c && this->data[r][c] != zero) return false; } return true; } /** * Determines whether this is the zero matrix. * * @return \c true if and only if all entries in the matrix are zero. */ bool isZero() const { for (size_t r=0; rnRows; ++r) for (size_t c=0; cnCols; ++c) if (this->data[r][c] != zero) return false; return true; } /** * Adds the given source row to the given destination row. * * \pre The two given rows are distinct and between 0 and * rows()-1 inclusive. * * @param source the row to add. * @param dest the row that will be added to. */ void addRow(unsigned long source, unsigned long dest) { for (unsigned long i = 0; i < this->nCols; i++) this->data[dest][i] += this->data[source][i]; } /** * Adds the given number of copies of the given source row to * the given destination row. * * Note that \a copies is passed by value in case it is an * element of the row to be changed. * * \pre The two given rows are distinct and between 0 and * rows()-1 inclusive. * * @param source the row to add. * @param dest the row that will be added to. * @param copies the number of copies of \a source to add to * \a dest. */ void addRow(unsigned long source, unsigned long dest, T copies) { for (unsigned long i = 0; i < this->nCols; i++) this->data[dest][i] += copies * this->data[source][i]; } /** * Adds the given source column to the given destination column. * * \pre The two given columns are distinct and between 0 and * columns()-1 inclusive. * * @param source the columns to add. * @param dest the column that will be added to. */ void addCol(unsigned long source, unsigned long dest) { for (unsigned long i = 0; i < this->nRows; i++) this->data[i][dest] += this->data[i][source]; } /** * Adds the given number of copies of the given source column to * the given destination column. * * Note that \a copies is passed by value in case it is an * element of the row to be changed. * * \pre The two given columns are distinct and between 0 and * columns()-1 inclusive. * * @param source the columns to add. * @param dest the column that will be added to. * @param copies the number of copies of \a source to add to * \a dest. */ void addCol(unsigned long source, unsigned long dest, T copies) { for (unsigned long i = 0; i < this->nRows; i++) this->data[i][dest] += copies * this->data[i][source]; } /** * Multiplies the given row by the given factor. * * Note that \a factor is passed by value in case it is an * element of the row to be changed. * * \pre The given row is between 0 and rows()-1 inclusive. * * @param row the row to work with. * @param factor the factor by which to multiply the given row. */ void multRow(unsigned long row, T factor) { for (unsigned long i = 0; i < this->nCols; i++) this->data[row][i] *= factor; } /** * Multiplies the given column by the given factor. * * Note that \a factor is passed by value in case it is an * element of the row to be changed. * * \pre The given column is between 0 and columns()-1 inclusive. * * @param column the column to work with. * @param factor the factor by which to multiply the given column. */ void multCol(unsigned long column, T factor) { for (unsigned long i = 0; i < this->nRows; i++) this->data[i][column] *= factor; } /** * Multiplies this by the given matrix, and returns the result. * This matrix is not changed. * * \pre The number of columns in this matrix equals the number * of rows in the given matrix. * * \warning The returned matrix will be of the exact class * NMatrixRing, even if both this and \a other are of some common * subclass of NMatrixRing. If you need a subclass to be returned, * consider calling multiplyAs() instead. * * \ifacespython The multiplication operator for a subclass (such as * NMatrixInt) will return a new matrix of that same subclass. * That is, the python multiplication operator really calls * multiplyAs(), not this routine. * * @param other the matrix by which to multiply this matrix. * @return a newly allocated matrix representing * this * other. */ std::auto_ptr > operator * (const NMatrixRing& other) const { std::auto_ptr > ans(new NMatrixRing( this->nRows, other.nCols)); unsigned long row, col, k; for (row = 0; row < this->nRows; row++) for (col = 0; col < other.nCols; col++) { ans->data[row][col] = zero; for (k = 0; k < this->nCols; k++) ans->data[row][col] += (this->data[row][k] * other.data[k][col]); } return ans; } /** * Multiplies this by the given matrix, and returns a new matrix of * subclass \a MatrixClass. This matrix is not changed. * * \pre The number of columns in this matrix equals the number * of rows in the given matrix. * \pre The class \a MatrixClass is a subclass of NMatrixRing, * and can be fully initialised by calling the two-argument constructor * (passing the row and column counts) and then settng individual * elements via \a data[r][c]. In particular, there should not be any * new data members that need explicit initialisation. * * \ifacespython Not present, but the python multiplication operator * performs the same task (see the python notes for operator *). * * @param other the matrix by which to multiply this matrix. * @return a newly allocated matrix representing * this * other. */ template std::auto_ptr multiplyAs(const NMatrixRing& other) const { std::auto_ptr ans(new MatrixClass( this->nRows, other.nCols)); unsigned long row, col, k; for (row = 0; row < this->nRows; row++) for (col = 0; col < other.nCols; col++) { ans->data[row][col] = zero; for (k = 0; k < this->nCols; k++) ans->data[row][col] += (this->data[row][k] * other.data[k][col]); } return ans; } /** * Evaluates the determinant of the matrix. * * This algorithm has quartic complexity, and uses the dynamic * programming approach of Mahajan and Vinay. For further * details, see Meena Mahajan and V. Vinay, "Determinant: * Combinatorics, algorithms, and complexity", Chicago J. Theor. * Comput. Sci., Vol. 1997, Article 5. * * \pre This is a square matrix. * * @return the determinant of this matrix. */ T det() const { unsigned long n = this->nRows; // Just in case... if (n != this->nCols || n == 0) return zero; T* partial[2]; partial[0] = new T[n * n]; partial[1] = new T[n * n]; unsigned long len, head, curr, prevHead, prevCurr; // Treat the smallest cases of len = 1 separately. int layer = 0; for (head = 0; head < n; head++) { partial[0][head + head * n] = one; for (curr = head + 1; curr < n; curr++) partial[0][head + curr * n] = zero; } // Work up through incrementing values of len. for (len = 2; len <= n; len++) { layer ^= 1; for (head = 0; head < n; head++) { // If curr == head, we need to open a new clow. partial[layer][head + head * n] = zero; for (prevHead = 0; prevHead < head; prevHead++) for (prevCurr = prevHead; prevCurr < n; prevCurr++) partial[layer][head + head * n] -= (partial[layer ^ 1][prevHead + prevCurr * n] * this->data[prevCurr][prevHead]); // If curr > head, we need to continue an existing clow. for (curr = head + 1; curr < n; curr++) { partial[layer][head + curr * n] = zero; for (prevCurr = head; prevCurr < n; prevCurr++) partial[layer][head + curr * n] += (partial[layer ^ 1][head + prevCurr * n] * this->data[prevCurr][curr]); } } } // All done. Sum up the determinant. T ans = zero; for (head = 0; head < n; head++) for (curr = head; curr < n; curr++) ans += (partial[layer][head + curr * n] * this->data[curr][head]); delete[] partial[0]; delete[] partial[1]; return (n % 2 == 0 ? -ans : ans); } }; template T NMatrixRing::zero(0L); /**< Zero in the underlying ring. * This would be \c const if it weren't for the fact that * some compilers don't like this. It should never be * modified! */ template T NMatrixRing::one(1L); /**< One (the multiplicative identity) in the underlying ring. * This would be \c const if it weren't for the fact that * some compilers don't like this. It should never be * modified! */ /*@}*/ } // namespace regina #endif regina-4.96/engine/maths/nmatrix2.cpp000644 000765 000024 00000016446 12377776625 017502 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "maths/nmatrix2.h" namespace regina { NMatrix2 NMatrix2::inverse() const { long det = data[0][0] * data[1][1] - data[0][1] * data[1][0]; if (det == 1) return NMatrix2(data[1][1], -data[0][1], -data[1][0], data[0][0]); else if (det == -1) return NMatrix2(-data[1][1], data[0][1], data[1][0], -data[0][0]); else return NMatrix2(); } NMatrix2& NMatrix2::operator *= (const NMatrix2& other) { long tmp00 = data[0][0] * other.data[0][0] + data[0][1] * other.data[1][0]; long tmp01 = data[0][0] * other.data[0][1] + data[0][1] * other.data[1][1]; long tmp10 = data[1][0] * other.data[0][0] + data[1][1] * other.data[1][0]; long tmp11 = data[1][0] * other.data[0][1] + data[1][1] * other.data[1][1]; data[0][0] = tmp00; data[0][1] = tmp01; data[1][0] = tmp10; data[1][1] = tmp11; return *this; } bool NMatrix2::invert() { long det = data[0][0] * data[1][1] - data[0][1] * data[1][0]; if (det == 1) { long tmp = data[0][0]; data[0][0] = data[1][1]; data[1][1] = tmp; data[0][1] = -data[0][1]; data[1][0] = -data[1][0]; return true; } else if (det == -1) { long tmp = data[0][0]; data[0][0] = -data[1][1]; data[1][1] = -tmp; return true; } else return false; } bool simpler(const NMatrix2& m1, const NMatrix2& m2) { long maxAbs1 = 0, maxAbs2 = 0; unsigned nZeroes1 = 0, nZeroes2 = 0; unsigned nNeg1 = 0, nNeg2 = 0; int i, j; for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) { if (m1[i][j] > maxAbs1) maxAbs1 = m1[i][j]; if (m1[i][j] < -maxAbs1) maxAbs1 = -m1[i][j]; if (m2[i][j] > maxAbs2) maxAbs2 = m2[i][j]; if (m2[i][j] < -maxAbs2) maxAbs2 = -m2[i][j]; if (m1[i][j] == 0) nZeroes1++; else if (m1[i][j] < 0) nNeg1++; if (m2[i][j] == 0) nZeroes2++; else if (m2[i][j] < 0) nNeg2++; } if (maxAbs1 < maxAbs2) return true; if (maxAbs1 > maxAbs2) return false; if (nZeroes1 > nZeroes2) return true; if (nZeroes1 < nZeroes2) return false; if (nNeg1 < nNeg2) return true; if (nNeg1 > nNeg2) return false; // Go lexicograhpic. for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) if (m1[i][j] < m2[i][j]) return true; else if (m1[i][j] > m2[i][j]) return false; // They're the same. return false; } bool simpler(const NMatrix2& pair1first, const NMatrix2& pair1second, const NMatrix2& pair2first, const NMatrix2& pair2second) { long maxAbs0 = 0, maxAbs1 = 0; unsigned nZeroes0 = 0, nZeroes1 = 0; unsigned nNeg0 = 0, nNeg1 = 0; int i, j; for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) { if (pair1first[i][j] > maxAbs0) maxAbs0 = pair1first[i][j]; if (pair1first[i][j] < -maxAbs0) maxAbs0 = -pair1first[i][j]; if (pair1second[i][j] > maxAbs0) maxAbs0 = pair1second[i][j]; if (pair1second[i][j] < -maxAbs0) maxAbs0 = -pair1second[i][j]; if (pair2first[i][j] > maxAbs1) maxAbs1 = pair2first[i][j]; if (pair2first[i][j] < -maxAbs1) maxAbs1 = -pair2first[i][j]; if (pair2second[i][j] > maxAbs1) maxAbs1 = pair2second[i][j]; if (pair2second[i][j] < -maxAbs1) maxAbs1 = -pair2second[i][j]; if (pair1first[i][j] == 0) nZeroes0++; else if (pair1first[i][j] < 0) nNeg0++; if (pair1second[i][j] == 0) nZeroes0++; else if (pair1second[i][j] < 0) nNeg0++; if (pair2first[i][j] == 0) nZeroes1++; else if (pair2first[i][j] < 0) nNeg1++; if (pair2second[i][j] == 0) nZeroes1++; else if (pair2second[i][j] < 0) nNeg1++; } if (maxAbs0 < maxAbs1) return true; if (maxAbs0 > maxAbs1) return false; if (nZeroes0 > nZeroes1) return true; if (nZeroes0 < nZeroes1) return false; if (nNeg0 < nNeg1) return true; if (nNeg0 > nNeg1) return false; // Go lexicograhpic. for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) if (pair1first[i][j] < pair2first[i][j]) return true; else if (pair1first[i][j] > pair2first[i][j]) return false; for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) if (pair1second[i][j] < pair2second[i][j]) return true; else if (pair1second[i][j] > pair2second[i][j]) return false; // They're the same. return false; } } // namespace regina regina-4.96/engine/maths/nmatrix2.h000644 000765 000024 00000042127 12377775266 017142 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #ifndef __NMATRIX2_H #ifndef __DOXYGEN #define __NMATRIX2_H #endif #include #include "regina-core.h" /*! \file maths/nmatrix2.h * \brief Deals with 2x2 integer matrices. */ namespace regina { /** * \weakgroup maths * @{ */ /** * Represents a 2-by-2 integer matrix. The advantages of using this * class over the larger NMatrixInt and friends is that this class has * less overhead and offers additional mathematical support routines * that the larger classes do not. * * This class only contains four long integers, and so it may be considered * small enough to pass about by value. */ class REGINA_API NMatrix2 { private: long data[2][2]; /**< The four entries in this matrix, indexed by row and then by column. */ public: /** * Initialises to the zero matrix. */ NMatrix2(); /** * Initialises to a copy of the given matrix. * * @param cloneMe the matrix to be copied. */ NMatrix2(const NMatrix2& cloneMe); /** * Initialises to the given integer values. * * Each given integer values[r][c] will be placed in * row \a r, column \a c. * * \ifacespython Not present. * * @param values the four values to insert into the new matrix. */ NMatrix2(const long values[2][2]); /** * Initialises to the given integer values. * * @param val00 the value to place in row 0, column 0. * @param val01 the value to place in row 0, column 1. * @param val10 the value to place in row 1, column 0. * @param val11 the value to place in row 1, column 1. */ NMatrix2(long val00, long val01, long val10, long val11); /** * Sets this matrix to be a copy of the given matrix. * * @param cloneMe the matrix to be copied. * @return a reference to this matrix. */ NMatrix2& operator = (const NMatrix2& cloneMe); /** * Sets the elements of this matrix to the given integer values. * * Each given integer values[r][c] will be placed in * row \a r, column \a c. * * \ifacespython Not present. * * @param values the four values to copy into this matrix. * @return a reference to this matrix. */ NMatrix2& operator = (const long values[2][2]); /** * Returns a single row of this matrix. * * This means that the integer in row \a r, column \a c can be * accessed as myMatrix[r][c] (where \a r and \a c are * each 0 or 1). * * @param row the index of the requested row; this must be 0 or 1. * @return a two-integer array containing the elements of the * requested row. */ const long* operator [] (unsigned row) const; /** * Returns a single row of this matrix. * * This means that the integer in row \a r, column \a c can be * accessed as myMatrix[r][c] (where \a r and \a c are * each 0 or 1). Each such element may be modified directly. * * @param row the index of the requested row; this must be 0 or 1. * @return a two-integer array containing the elements of the * requested row. */ long* operator [] (unsigned row); /** * Calculates the matrix product of this and the given matrix. * Neither this nor the given matrix is changed. * * @param other the matrix that this should be multiplied by. * @return the product \a this * \a other. */ NMatrix2 operator * (const NMatrix2& other) const; /** * Calculates the scalar product of this matrix and the given * integer. This matrix is not changed. * * @param scalar the integer that this matrix should be multiplied by. * @return the product \a this * \a scalar. */ NMatrix2 operator * (long scalar) const; /** * Calculates the sum of two matrices. * Neither this nor the given matrix is changed. * * @param other the matrix to add to this. * @return the sum \a this + \a other. */ NMatrix2 operator + (const NMatrix2& other) const; /** * Calculates the difference of two matrices. * Neither this nor the given matrix is changed. * * @param other the matrix to subtract from this. * @return the difference \a this - \a other. */ NMatrix2 operator - (const NMatrix2& other) const; /** * Determines the negative of this matrix. * This matrix is not changed. * * @return the negative of this matrix. */ NMatrix2 operator - () const; /** * Returns the transpose of this matrix. * This matrix is not changed. * * @return the transpose of this matrix. */ NMatrix2 transpose() const; /** * Calculates the inverse of this matrix. * This matrix is not changed. * * This routine only works for integer matrices whose determinant is * either +1 or -1. * * @return the inverse of this matrix. If this matrix does not * have determinant +1 or -1, the zero matrix will be returned * instead. */ NMatrix2 inverse() const; /** * Adds the given matrix to this. * This matrix is changed to reflect the result. * * @param other the matrix to add to this. * @return a reference to this matrix with its new value. */ NMatrix2& operator += (const NMatrix2& other); /** * Subtracts the given matrix from this. * This matrix is changed to reflect the result. * * @param other the matrix to subtract from this. * @return a reference to this matrix with its new value. */ NMatrix2& operator -= (const NMatrix2& other); /** * Multiplies this by the given matrix. * This matrix is changed to reflect the result. * * @param other the matrix by which this should be multiplied. * @return a reference to this matrix with its new value. */ NMatrix2& operator *= (const NMatrix2& other); /** * Multiplies this by the given scalar. * This matrix is changed to reflect the result. * * @param scalar the scalar by which this should be multiplied. * @return a reference to this matrix with its new value. */ NMatrix2& operator *= (long scalar); /** * Negates this matrix. * This matrix is changed to reflect the result. */ void negate(); /** * Inverts this matrix. * * This routine only works for integer matrices whose determinant is * either +1 or -1. Otherwise this matrix is left unchanged. * * @return \c true if this matrix was successfully inverted * (i.e., its determinant was +1 or -1), or \c false otherwise. */ bool invert(); /** * Determines if this is equal to the given matrix. * * @param compare the matrix with which this will be compared. * @return \c true if and only if this matrix is equal to \a compare. */ bool operator == (const NMatrix2& compare) const; /** * Determines if this is not equal to the given matrix. * * @param compare the matrix with which this will be compared. * @return \c true if and only if this matrix is not equal to * \a compare. */ bool operator != (const NMatrix2& compare) const; /** * Returns the determinant of this matrix. * * @return the determinant of this matrix. */ long determinant() const; /** * Determines if this is the 2x2 identity matrix. * * @return \c true if this is the identity matrix, or \c false * otherwise. */ bool isIdentity() const; /** * Determines if this is the 2x2 zero matrix. * * @return \c true if this is the zero matrix, or \c false * otherwise. */ bool isZero() const; friend std::ostream& operator << (std::ostream& out, const NMatrix2& mat); }; /** * Writes the given matrix to the given output stream. The matrix will * be written entirely on a single line, with the first row followed by the * second row. * * @param out the output stream to which to write. * @param mat the matrix to write. * @return a reference to \a out. */ REGINA_API std::ostream& operator << (std::ostream& out, const NMatrix2& mat); /** * Determines whether the first given matrix is more aesthetically * pleasing than the second. The way in which this judgement is made * is purely aesthetic on the part of the author, and is subject to * change in future versions of Regina. * * @param m1 the first matrix to examine. * @param m2 the second matrix to examine. * @return \c true if \a m1 is deemed to be more pleasing than \a m2, * or \c false if either the matrices are equal or \a m2 is more * pleasing than \a m1. */ REGINA_API bool simpler(const NMatrix2& m1, const NMatrix2& m2); /** * Determines whether the first given pair of matrices is more aesthetically * pleasing than the second pair. The way in which this judgement is made * is purely aesthetic on the part of the author, and is subject to * change in future versions of Regina. * * Note that pairs are ordered, so the pair (\a M, \a N) may be more * (or perhaps less) pleasing than the pair (\a N, \a M). * * @param pair1first the first matrix of the first pair to examine. * @param pair1second the second matrix of the first pair to examine. * @param pair2first the first matrix of the second pair to examine. * @param pair2second the second matrix of the second pair to examine. * @return \c true if the first pair is deemed to be more pleasing than * the second pair, or \c false if either the ordered pairs are equal or * the second pair is more pleasing than the first. */ REGINA_API bool simpler(const NMatrix2& pair1first, const NMatrix2& pair1second, const NMatrix2& pair2first, const NMatrix2& pair2second); /*@}*/ // Inline functions for NMatrix2 inline NMatrix2::NMatrix2() { data[0][0] = data[0][1] = data[1][0] = data[1][1] = 0; } inline NMatrix2::NMatrix2(const NMatrix2& cloneMe) { data[0][0] = cloneMe.data[0][0]; data[0][1] = cloneMe.data[0][1]; data[1][0] = cloneMe.data[1][0]; data[1][1] = cloneMe.data[1][1]; } inline NMatrix2::NMatrix2(const long values[2][2]) { data[0][0] = values[0][0]; data[0][1] = values[0][1]; data[1][0] = values[1][0]; data[1][1] = values[1][1]; } inline NMatrix2::NMatrix2(long val00, long val01, long val10, long val11) { data[0][0] = val00; data[0][1] = val01; data[1][0] = val10; data[1][1] = val11; } inline NMatrix2& NMatrix2::operator = (const NMatrix2& cloneMe) { data[0][0] = cloneMe.data[0][0]; data[0][1] = cloneMe.data[0][1]; data[1][0] = cloneMe.data[1][0]; data[1][1] = cloneMe.data[1][1]; return *this; } inline NMatrix2& NMatrix2::operator = (const long values[2][2]) { data[0][0] = values[0][0]; data[0][1] = values[0][1]; data[1][0] = values[1][0]; data[1][1] = values[1][1]; return *this; } inline const long* NMatrix2::operator [] (unsigned row) const { return data[row]; } inline long* NMatrix2::operator [] (unsigned row) { return data[row]; } inline NMatrix2 NMatrix2::operator * (const NMatrix2& other) const { return NMatrix2( data[0][0] * other.data[0][0] + data[0][1] * other.data[1][0], data[0][0] * other.data[0][1] + data[0][1] * other.data[1][1], data[1][0] * other.data[0][0] + data[1][1] * other.data[1][0], data[1][0] * other.data[0][1] + data[1][1] * other.data[1][1]); } inline NMatrix2 NMatrix2::operator * (long scalar) const { return NMatrix2( data[0][0] * scalar, data[0][1] * scalar, data[1][0] * scalar, data[1][1] * scalar); } inline NMatrix2 NMatrix2::operator + (const NMatrix2& other) const { return NMatrix2( data[0][0] + other.data[0][0], data[0][1] + other.data[0][1], data[1][0] + other.data[1][0], data[1][1] + other.data[1][1]); } inline NMatrix2 NMatrix2::operator - (const NMatrix2& other) const { return NMatrix2( data[0][0] - other.data[0][0], data[0][1] - other.data[0][1], data[1][0] - other.data[1][0], data[1][1] - other.data[1][1]); } inline NMatrix2 NMatrix2::operator - () const { return NMatrix2(-data[0][0], -data[0][1], -data[1][0], -data[1][1]); } inline NMatrix2 NMatrix2::transpose() const { return NMatrix2(data[0][0], data[1][0], data[0][1], data[1][1]); } inline NMatrix2& NMatrix2::operator += (const NMatrix2& other) { data[0][0] += other.data[0][0]; data[0][1] += other.data[0][1]; data[1][0] += other.data[1][0]; data[1][1] += other.data[1][1]; return *this; } inline NMatrix2& NMatrix2::operator -= (const NMatrix2& other) { data[0][0] -= other.data[0][0]; data[0][1] -= other.data[0][1]; data[1][0] -= other.data[1][0]; data[1][1] -= other.data[1][1]; return *this; } inline NMatrix2& NMatrix2::operator *= (long scalar) { data[0][0] *= scalar; data[0][1] *= scalar; data[1][0] *= scalar; data[1][1] *= scalar; return *this; } inline void NMatrix2::negate() { data[0][0] = -data[0][0]; data[0][1] = -data[0][1]; data[1][0] = -data[1][0]; data[1][1] = -data[1][1]; } inline bool NMatrix2::operator == (const NMatrix2& compare) const { return ( data[0][0] == compare.data[0][0] && data[0][1] == compare.data[0][1] && data[1][0] == compare.data[1][0] && data[1][1] == compare.data[1][1]); } inline bool NMatrix2::operator != (const NMatrix2& compare) const { return ( data[0][0] != compare.data[0][0] || data[0][1] != compare.data[0][1] || data[1][0] != compare.data[1][0] || data[1][1] != compare.data[1][1]); } inline long NMatrix2::determinant() const { return data[0][0] * data[1][1] - data[0][1] * data[1][0]; } inline bool NMatrix2::isIdentity() const { return (data[0][0] == 1 && data[0][1] == 0 && data[1][0] == 0 && data[1][1] == 1); } inline bool NMatrix2::isZero() const { return (data[0][0] == 0 && data[0][1] == 0 && data[1][0] == 0 && data[1][1] == 0); } inline std::ostream& operator << (std::ostream& out, const NMatrix2& mat) { return out << "[[ " << mat.data[0][0] << ' ' << mat.data[0][1] << " ] [ " << mat.data[1][0] << ' ' << mat.data[1][1] << " ]]"; } } // namespace regina #endif regina-4.96/engine/maths/nmatrixint.h000644 000765 000024 00000022402 12377775267 017566 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #ifndef __NMATRIXINT_H #ifndef __DOXYGEN #define __NMATRIXINT_H #endif /*! \file maths/nmatrixint.h * \brief Deals with matrices of arbitrary precision integers. */ #include "regina-core.h" #include "shareableobject.h" #include "maths/ninteger.h" #include "maths/nmatrix.h" namespace regina { /** * \weakgroup maths * @{ */ /** * Represents a matrix of arbitrary precision integers. * Calculations will be exact no matter how large the integers become. * * Note that many important functions (such as entry()) are inherited * from the superclasses NMatrix and NMatrixRing, and are not documented * again here. Many other algorithms that work on the NMatrixInt class * are available in the maths/matrixops.h file. * * \ifacespython Most inherited member functions are implemented. * Exceptions are noted in the documentation for each individual member * function. */ class REGINA_API NMatrixInt : public NMatrixRing, public ShareableObject { public: /** * Creates a new matrix of the given size. * All entries will be initialised to zero. * * \pre The given number of rows and columns are * both strictly positive. * * @param rows the number of rows in the new matrix. * @param cols the number of columns in the new matrix. */ NMatrixInt(unsigned long rows, unsigned long cols); /** * Creates a new matrix that is a clone of the given matrix. * * @param cloneMe the matrix to clone. */ NMatrixInt(const NMatrixInt& cloneMe); /** * Divides all elements of the given row by the given integer. * This can only be used when the given integer divides into all * row elements exactly (with no remainder), and is much faster * than ordinary division. * * \pre The argument \a divBy is neither zero nor infinity, and * none of the elements of the given row are infinity. * \pre The argument \a divBy divides exactly into every element * of the given row (i.e., it leaves no remainder). * \pre The given row number is between 0 and rows()-1 inclusive. * * @param row the index of the row whose elements should be * divided by \a divBy. * @param divBy the integer to divide each row element by. */ void divRowExact(unsigned long row, const NLargeInteger& divBy) { for (NLargeInteger* x = this->data[row]; x != this->data[row] + nCols; ++x) x->divByExact(divBy); } /** * Divides all elements of the given column by the given integer. * This can only be used when the given integer divides into all * column elements exactly (with no remainder), and is much faster * than ordinary division. * * \pre The argument \a divBy is neither zero nor infinity, and * none of the elements of the given column are infinity. * \pre The argument \a divBy divides exactly into every element * of the given column (i.e., it leaves no remainder). * \pre The given column number is between 0 and columns()-1 inclusive. * * @param col the index of the column whose elements should be * divided by \a divBy. * @param divBy the integer to divide each column element by. */ void divColExact(unsigned long col, const NLargeInteger& divBy) { for (NLargeInteger** row = this->data; row != this->data + nRows; ++row) (*row)[col].divByExact(divBy); } /** * Computes the greatest common divisor of all elements of the * given row. The value returned is guaranteed to be non-negative. * * \pre The given row number is between 0 and rows()-1 inclusive. * * @param row the index of the row whose gcd should be computed. * @return the greatest common divisor of all elements of this row. */ NLargeInteger gcdRow(unsigned long row) { NLargeInteger* x = this->data[row]; NLargeInteger gcd = *x++; while (x != this->data[row] + nCols && gcd != 1 && gcd != -1) gcd = gcd.gcd(*x++); if (gcd < 0) gcd.negate(); return gcd; } /** * Computes the greatest common divisor of all elements of the * given column. The value returned is guaranteed to be non-negative. * * \pre The given column number is between 0 and columns()-1 inclusive. * * @param col the index of the column whose gcd should be computed. * @return the greatest common divisor of all elements of this column. */ NLargeInteger gcdCol(unsigned long col) { NLargeInteger** row = this->data; NLargeInteger gcd = (*row++)[col]; while (row != this->data + nRows && gcd != 1 && gcd != -1) gcd = gcd.gcd((*row++)[col]); if (gcd < 0) gcd.negate(); return gcd; } /** * Reduces the given row by dividing all its elements by their * greatest common divisor. It is guaranteed that, if the row is * changed at all, it will be divided by a \e positive integer. * * \pre The given row number is between 0 and rows()-1 inclusive. * * @param row the index of the row to reduce. */ void reduceRow(unsigned long row) { NLargeInteger gcd = gcdRow(row); if (gcd != NLargeInteger::zero && gcd != NLargeInteger::one) divRowExact(row, gcd); } /** * Reduces the given column by dividing all its elements by their * greatest common divisor. It is guaranteed that, if the column is * changed at all, it will be divided by a \e positive integer. * * \pre The given column number is between 0 and columns()-1 inclusive. * * @param col the index of the column to reduce. */ void reduceCol(unsigned long col) { NLargeInteger gcd = gcdCol(col); if (gcd != NLargeInteger::zero && gcd != NLargeInteger::one) divColExact(col, gcd); } virtual void writeTextShort(std::ostream& out) const; virtual void writeTextLong(std::ostream& out) const; }; // Inline functions for NMatrixInt inline NMatrixInt::NMatrixInt(unsigned long rows, unsigned long cols) : NMatrixRing(rows, cols), ShareableObject() { } inline NMatrixInt::NMatrixInt(const NMatrixInt& cloneMe) : NMatrixRing(cloneMe), ShareableObject() { } inline void NMatrixInt::writeTextShort(std::ostream& out) const { out << nRows << " x " << nCols << " integer matrix"; } inline void NMatrixInt::writeTextLong(std::ostream& out) const { writeMatrix(out); } /*@}*/ } // namespace regina #endif regina-4.96/engine/maths/nperm3.cpp000644 000765 000024 00000007356 12377776626 017143 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "maths/nperm3.h" namespace regina { const NPerm3 NPerm3::S3[6] = { NPerm3((unsigned char)0), NPerm3(1), NPerm3(2), NPerm3(3), NPerm3(4), NPerm3(5) }; const NPerm3* NPerm3::Sn = NPerm3::S3; const unsigned NPerm3::invS3[6] = { 0, 1, 4, 3, 2, 5 }; const unsigned* NPerm3::invSn = NPerm3::invS3; const NPerm3 NPerm3::orderedS3[6] = { NPerm3(code012), NPerm3(code021), NPerm3(code102), NPerm3(code120), NPerm3(code201), NPerm3(code210) }; const NPerm3* NPerm3::orderedSn = NPerm3::orderedS3; const NPerm3 NPerm3::S2[2] = { NPerm3(code012), NPerm3(code102) }; const NPerm3* NPerm3::Sn_1 = NPerm3::S2; const unsigned char NPerm3::imageTable[6][3] = { { 0, 1, 2 }, { 0, 2, 1 }, { 1, 2, 0 }, { 1, 0, 2 }, { 2, 0, 1 }, { 2, 1, 0 } }; const unsigned char NPerm3::productTable[6][6] = { { 0, 1, 2, 3, 4, 5 }, { 1, 0, 5, 4, 3, 2 }, { 2, 3, 4, 5, 0, 1 }, { 3, 2, 1, 0, 5, 4 }, { 4, 5, 0, 1, 2, 3 }, { 5, 4, 3, 2, 1, 0 } }; std::string NPerm3::str() const { char ans[4]; ans[0] = static_cast('0' + imageTable[code_][0]); ans[1] = static_cast('0' + imageTable[code_][1]); ans[2] = static_cast('0' + imageTable[code_][2]); ans[3] = 0; return ans; } std::string NPerm3::trunc2() const { char ans[3]; ans[0] = static_cast('0' + imageTable[code_][0]); ans[1] = static_cast('0' + imageTable[code_][1]); ans[2] = 0; return ans; } } // namespace regina regina-4.96/engine/maths/nperm3.h000644 000765 000024 00000051434 12377775270 016576 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file maths/nperm3.h * \brief Deals with permutations of {0,1,2}. */ #ifndef __NPERM3_H #ifndef __DOXYGEN #define __NPERM3_H #endif #include #include "regina-core.h" namespace regina { /** * \weakgroup maths * @{ */ /** * Represents a permutation of {0,1,2}. * * These objects are small enough to pass about by value instead of by * reference. Moreover, they are extremely fast to work with. * * Each permutation has an internal code, and this code is sufficient to * reconstruct the permutation. * Thus the internal code may be a useful means for passing * permutation objects to and from the engine. * * The internal code is an integer between 0 and 5 inclusive, * representing the index of the permutation in the array NPerm3::S3. * * This class is faster and sleeker than related classes such as NPerm4 and * NPerm5. On the other hand, this class does not offer quite as rich an * interface as the others. */ class REGINA_API NPerm3 { public: /** * Contains all possible permutations of three elements. * * The permutations with even indices in the array are the even * permutations, and those with odd indices in the array are the * odd permutations. * * For all permutation classes (NPerm3, NPerm4 and so on), * the S3 array stores the same permutations in the same order * (but of course using different data types). * * Note that these permutations are not necessarily in * lexicographical order. */ static const NPerm3 S3[6]; /** * A dimension-agnostic alias for NPerm3::S3. In general, for * each \a K the class NPermK will define an alias \a Sn * that references the list of all permutations NPermK::SK. */ static const NPerm3* Sn; /** * Contains the inverses of the permutations in the array \a S3. * * Specifically, the inverse of permutation S3[i] is * the permutation S3[ invS3[i] ]. */ static const unsigned invS3[6]; /** * A dimension-agnostic alias for NPerm3::invS3. In general, for * each \a K the class NPermK will define an alias \a invSn * that references the list of all permutations NPermK::invSK. */ static const unsigned* invSn; /** * Contains all possible permutations of three elements in * lexicographical order. */ static const NPerm3 orderedS3[6]; /** * A dimension-agnostic alias for NPerm3::orderedS3. In general, for * each \a K the class NPermK will define an alias \a orderedSn * that references the list of all permutations NPermK::orderedSK. */ static const NPerm3* orderedSn; /** * Contains all possible permutations of two elements. * In each permutation, 2 maps to 2 and 3 maps to 3. * * The permutations with even indices in the array are the even * permutations, and those with odd indices in the array are the * odd permutations. * * For all permutation classes (NPerm3, NPerm4 and so on), * the S2 array stores the same permutations in the same order * (but of course using different data types). * * Note that these permutations are already in lexicographical order. */ static const NPerm3 S2[2]; /** * A dimension-agnostic alias for NPerm3::S2. In general, for * each \a K the class NPermK will define an alias \a Sn_1 * that references the list of all permutations NPermK::S(K-1). */ static const NPerm3* Sn_1; enum { /** * The total number of permutations on three elements. * This is the size of the array Sn. * * \ifacespython Not present. */ nPerms = 6, /** * The total number of permutations on two elements. * This is the size of the array Sn_1. * * \ifacespython Not present. */ nPerms_1 = 2 }; enum { /** * The internal code for the permutation (0,1,2). * * \ifacespython Not present. */ code012 = 0, /** * The internal code for the permutation (0,2,1). * * \ifacespython Not present. */ code021 = 1, /** * The internal code for the permutation (1,2,0). * * \ifacespython Not present. */ code120 = 2, /** * The internal code for the permutation (1,0,2). * * \ifacespython Not present. */ code102 = 3, /** * The internal code for the permutation (2,0,1). * * \ifacespython Not present. */ code201 = 4, /** * The internal code for the permutation (2,1,0). * * \ifacespython Not present. */ code210 = 5 }; private: unsigned char code_; /**< The internal code representing this permutation. */ public: /** * Creates the identity permutation. */ NPerm3(); /** * Creates the transposition of \a a and \a b. * Note that \a a and \a b need not be distinct. * * \pre \a a and \a b are in {0,1,2}. * * @param a the element to switch with \a b. * @param b the element to switch with \a a. */ NPerm3(int a, int b); /** * Creates a permutation mapping (0,1,2) to * (a,b,c) respectively. * * \pre {a,b,c} = {0,1,2}. * * @param a the desired image of 0. * @param b the desired image of 1. * @param c the desired image of 2. */ NPerm3(int a, int b, int c); /** * Creates a permutation mapping \a i to \a image[i] for each * \a i = 0,1,2. * * \pre The array \a image contains three elements, which are * 0, 1 and 2 in some order. * * \ifacespython Not present. * * @param image the array of images. */ NPerm3(const int* image); /** * Creates a permutation that is a clone of the given * permutation. * * @param cloneMe the permutation to clone. */ NPerm3(const NPerm3& cloneMe); /** * Returns the internal code representing this permutation. * Note that the internal code is sufficient to reproduce the * entire permutation. * * The code returned will be a valid permutation code as * determined by isPermCode(). * * @return the internal code. */ unsigned char getPermCode() const; /** * Sets this permutation to that represented by the given * internal code. * * \pre the given code is a valid permutation code; see * isPermCode() for details. * * @param code the internal code that will determine the * new value of this permutation. */ void setPermCode(unsigned char code); /** * Creates a permutation from the given internal code. * * \pre the given code is a valid permutation code; see * isPermCode() for details. * * @param code the internal code for the new permutation. * @return the permutation represented by the given internal code. */ static NPerm3 fromPermCode(unsigned char code); /** * Determines whether the given integer is a valid internal * permutation code. Valid permutation codes can be passed to * setPermCode() or fromPermCode(), and are returned by getPermCode(). * * @return \c true if and only if the given code is a valid * internal permutation code. */ static bool isPermCode(unsigned char code); /** * Sets this permutation to be equal to the given permutation. * * @param cloneMe the permutation whose value will be assigned * to this permutation. * @return a reference to this permutation. */ NPerm3& operator = (const NPerm3& cloneMe); /** * Returns the composition of this permutation with the given * permutation. If this permutation is p, the * resulting permutation will be p o q, satisfying * (p*q)[x] == p[q[x]]. * * @param q the permutation with which to compose this. * @return the composition of both permutations. */ NPerm3 operator * (const NPerm3& q) const; /** * Finds the inverse of this permutation. * * @return the inverse of this permutation. */ NPerm3 inverse() const; /** * Determines the sign of this permutation. * * @return 1 if this permutation is even, or -1 if this * permutation is odd. */ int sign() const; /** * Determines the image of the given integer under this * permutation. * * @param source the integer whose image we wish to find. This * should be between 0 and 2 inclusive. * @return the image of \a source. */ int operator[](int source) const; /** * Determines the preimage of the given integer under this * permutation. * * @param image the integer whose preimage we wish to find. This * should be between 0 and 2 inclusive. * @return the preimage of \a image. */ int preImageOf(int image) const; /** * Determines if this is equal to the given permutation. * This is true if and only if both permutations have the same * images for 0, 1 and 2. * * @param other the permutation with which to compare this. * @return \c true if and only if this and the given permutation * are equal. */ bool operator == (const NPerm3& other) const; /** * Determines if this differs from the given permutation. * This is true if and only if the two permutations have * different images for at least one of 0, 1 or 2. * * @param other the permutation with which to compare this. * @return \c true if and only if this and the given permutation * differ. */ bool operator != (const NPerm3& other) const; /** * Lexicographically compares the images of (0,1,2) under this * and the given permutation. * * @param other the permutation with which to compare this. * @return -1 if this permutation produces a smaller image, 0 if * the permutations are equal and 1 if this permutation produces * a greater image. */ int compareWith(const NPerm3& other) const; /** * Determines if this is the identity permutation. * This is true if and only if each of 0, 1 and 2 is mapped to itself. * * @return \c true if and only if this is the identity permutation. */ bool isIdentity() const; /** * A deprecated alias for str(), which returns a string representation * of this permutation. * * \deprecated This routine has (at long last) been deprecated; * use the simpler-to-type str() instead. * * @return a string representation of this permutation. */ std::string toString() const; /** * Returns a string representation of this permutation. * The representation will consist of three adjacent digits * representing the images of 0, 1 and 2 respectively. An * example of a string representation is 120. * * @return a string representation of this permutation. */ std::string str() const; /** * Returns a string representation of this permutation with only * the images of 0 and 1. The resulting string will therefore * have length two. * * @return a truncated string representation of this permutation. */ std::string trunc2() const; /** * Returns the index of this permutation in the NPerm3::S3 array. * * @return the index \a i for which this permutation is equal to * NPerm3::S3[i]. This will be between 0 and 5 inclusive. */ int S3Index() const; /** * Returns the index of this permutation in the NPerm3::S3 array. * This is a dimension-agnostic alias for S3Index(). * * @return the index \a i for which this permutation is equal to * NPerm3::S3[i]. This will be between 0 and 5 inclusive. */ int SnIndex() const; /** * Returns the index of this permutation in the NPerm3::orderedS3 array. * * @return the index \a i for which this permutation is equal to * NPerm3::orderedS3[i]. This will be between 0 and 5 inclusive. */ int orderedS3Index() const; /** * Returns the index of this permutation in the NPerm3::orderedS3 array. * This is a dimension-agnostic alias for orderedS3Index(). * * @return the index \a i for which this permutation is equal to * NPerm3::orderedS3[i]. This will be between 0 and 5 inclusive. */ int orderedSnIndex() const; private: /** * Contains the images of every element under every possible * permutation. * * Specifically, the image of \a x under the permutation S3[i] * is imageTable[i][x]. */ static const unsigned char imageTable[6][3]; /** * Contains the full multiplication table for all possible * permutations. * * Specifically, the product S3[x] * S3[y] is * the permutation S3[product[x][y]]. */ static const unsigned char productTable[6][6]; private: /** * Creates a permutation from the given internal code. * * \pre the given code is a valid permutation code; see * isPermCode() for details. * * @param code the internal code from which the new * permutation will be created. */ NPerm3(unsigned char code); friend std::ostream& operator << (std::ostream& out, const NPerm3& p); }; /** * Writes a string representation of the given permutation to the given * output stream. The format will be the same as is used by * NPerm3::str(). * * @param out the output stream to which to write. * @param p the permutation to write. * @return a reference to \a out. */ inline REGINA_API std::ostream& operator << (std::ostream& out, const NPerm3& p) { return (out << p.str()); } /*@}*/ // Inline functions for NPerm3 inline NPerm3::NPerm3() : code_(0) { } inline NPerm3::NPerm3(unsigned char code) : code_(code) { } inline NPerm3::NPerm3(int a, int b) { // Transposition. if (a == b) code_ = code012; else switch (a) { case 0: code_ = (b == 1 ? code102 : code210); break; case 1: code_ = (b == 0 ? code102 : code021); break; case 2: code_ = (b == 0 ? code210 : code021); break; } } inline NPerm3::NPerm3(int a, int b, int) { // Images of (0, 1, 2). switch (a) { case 0: code_ = static_cast(b == 1 ? 0 : 1); break; case 1: code_ = static_cast(b == 2 ? 2 : 3); break; case 2: code_ = static_cast(b == 0 ? 4 : 5); break; } } inline NPerm3::NPerm3(const int* image) { switch (image[0]) { case 0: code_ = static_cast(image[1] == 1 ? 0 : 1); break; case 1: code_ = static_cast(image[1] == 2 ? 2 : 3); break; case 2: code_ = static_cast(image[1] == 0 ? 4 : 5); break; } } inline NPerm3::NPerm3(const NPerm3& cloneMe) : code_(cloneMe.code_) { } inline unsigned char NPerm3::getPermCode() const { return code_; } inline void NPerm3::setPermCode(unsigned char code) { code_ = code; } inline NPerm3 NPerm3::fromPermCode(unsigned char code) { return NPerm3(code); } inline bool NPerm3::isPermCode(unsigned char code) { // code >= 0 is a no-op because we are using an unsigned data type. return (code < 6); } inline NPerm3& NPerm3::operator = (const NPerm3& cloneMe) { code_ = cloneMe.code_; return *this; } inline NPerm3 NPerm3::operator * (const NPerm3& q) const { return NPerm3(productTable[code_][q.code_]); } inline NPerm3 NPerm3::inverse() const { return NPerm3(static_cast(invS3[code_])); } inline int NPerm3::sign() const { return (code_ % 2 ? -1 : 1); } inline int NPerm3::operator[](int source) const { return imageTable[code_][source]; } inline int NPerm3::preImageOf(int image) const { return imageTable[invS3[code_]][image]; } inline bool NPerm3::operator == (const NPerm3& other) const { return (code_ == other.code_); } inline bool NPerm3::operator != (const NPerm3& other) const { return (code_ != other.code_); } inline int NPerm3::compareWith(const NPerm3& other) const { // Computing orderedS3Index() is very fast. // Use this instead of comparing images one at a time. int o1 = orderedS3Index(); int o2 = other.orderedS3Index(); return (o1 == o2 ? 0 : o1 < o2 ? -1 : 1); } inline bool NPerm3::isIdentity() const { return (code_ == 0); } inline std::string NPerm3::toString() const { return str(); } inline int NPerm3::S3Index() const { return code_; } inline int NPerm3::SnIndex() const { return code_; } inline int NPerm3::orderedS3Index() const { if (code_ == 2 || code_ == 3) return code_ ^ 1; else return code_; } inline int NPerm3::orderedSnIndex() const { return orderedS3Index(); } } // namespace regina #endif regina-4.96/engine/maths/nperm4.cpp000644 000765 000024 00000021426 12377776626 017136 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "maths/nperm4.h" #include "triangulation/nedge.h" // deprecated #include "triangulation/ntriangle.h" // deprecated namespace regina { const NPerm4 NPerm4::S4[24] = { NPerm4((unsigned char)0), NPerm4(1), NPerm4(2), NPerm4(3), NPerm4(4), NPerm4(5), NPerm4(6), NPerm4(7), NPerm4(8), NPerm4(9), NPerm4(10), NPerm4(11), NPerm4(12), NPerm4(13), NPerm4(14), NPerm4(15), NPerm4(16), NPerm4(17), NPerm4(18), NPerm4(19), NPerm4(20), NPerm4(21), NPerm4(22), NPerm4(23) }; const NPerm4* NPerm4::Sn = NPerm4::S4; const NPerm4* allPermsS4 = NPerm4::S4; const unsigned NPerm4::invS4[24] = { 0, 1, 4, 3, 2, 5, 6, 7, 12, 19, 18, 13, 8, 11, 20, 15, 16, 23, 10, 9, 14, 21, 22, 17 }; const unsigned* NPerm4::invSn = NPerm4::invS4; const unsigned* allPermsS4Inv = NPerm4::invS4; const NPerm4 NPerm4::orderedS4[24] = { NPerm4((unsigned char)0), NPerm4(1), NPerm4(3), NPerm4(2), NPerm4(4), NPerm4(5), NPerm4(7), NPerm4(6), NPerm4(8), NPerm4(9), NPerm4(11), NPerm4(10), NPerm4(12), NPerm4(13), NPerm4(15), NPerm4(14), NPerm4(16), NPerm4(17), NPerm4(19), NPerm4(18), NPerm4(20), NPerm4(21), NPerm4(23), NPerm4(22) }; const NPerm4* NPerm4::orderedSn = NPerm4::orderedS4; const NPerm4* orderedPermsS4 = NPerm4::orderedS4; const NPerm4 NPerm4::S3[6] = { NPerm4(0,1,2,3), NPerm4(0,2,1,3), NPerm4(1,2,0,3), NPerm4(1,0,2,3), NPerm4(2,0,1,3), NPerm4(2,1,0,3) }; const NPerm4* NPerm4::Sn_1 = NPerm4::S3; const NPerm4* allPermsS3 = NPerm4::S3; const unsigned NPerm4::invS3[6] = { 0, 1, 4, 3, 2, 5 }; const unsigned* allPermsS3Inv = NPerm4::invS3; const NPerm4 NPerm4::orderedS3[6] = { NPerm4(0,1,2,3), NPerm4(0,2,1,3), NPerm4(1,0,2,3), NPerm4(1,2,0,3), NPerm4(2,0,1,3), NPerm4(2,1,0,3) }; const NPerm4* orderedPermsS3 = NPerm4::orderedS3; const NPerm4 NPerm4::S2[2] = { NPerm4(0,1,2,3), NPerm4(1,0,2,3) }; const NPerm4* allPermsS2 = NPerm4::S2; const unsigned NPerm4::invS2[2] = { 0, 1 }; const unsigned* allPermsS2Inv = NPerm4::invS2; const unsigned char NPerm4::imageTable[24][4] = { { 0, 1, 2, 3 }, { 0, 1, 3, 2 }, { 0, 2, 3, 1 }, { 0, 2, 1, 3 }, { 0, 3, 1, 2 }, { 0, 3, 2, 1 }, { 1, 0, 3, 2 }, { 1, 0, 2, 3 }, { 1, 2, 0, 3 }, { 1, 2, 3, 0 }, { 1, 3, 2, 0 }, { 1, 3, 0, 2 }, { 2, 0, 1, 3 }, { 2, 0, 3, 1 }, { 2, 1, 3, 0 }, { 2, 1, 0, 3 }, { 2, 3, 0, 1 }, { 2, 3, 1, 0 }, { 3, 0, 2, 1 }, { 3, 0, 1, 2 }, { 3, 1, 0, 2 }, { 3, 1, 2, 0 }, { 3, 2, 1, 0 }, { 3, 2, 0, 1 } }; const unsigned char NPerm4::productTable[24][24] = { // Generated using an older version of Regina in which products were // computed (not simply looked up from a dictionary like the one below). { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23 }, { 1,0,5,4,3,2,7,6,11,10,9,8,19,18,21,20,23,22,13,12,15,14,17,16 }, { 2,3,4,5,0,1,12,13,16,17,14,15,18,19,22,23,20,21,6,7,8,9,10,11 }, { 3,2,1,0,5,4,13,12,15,14,17,16,7,6,9,8,11,10,19,18,23,22,21,20 }, { 4,5,0,1,2,3,18,19,20,21,22,23,6,7,10,11,8,9,12,13,16,17,14,15 }, { 5,4,3,2,1,0,19,18,23,22,21,20,13,12,17,16,15,14,7,6,11,10,9,8 }, { 6,7,10,11,8,9,0,1,4,5,2,3,20,21,18,19,22,23,14,15,12,13,16,17 }, { 7,6,9,8,11,10,1,0,3,2,5,4,15,14,13,12,17,16,21,20,19,18,23,22 }, { 8,9,6,7,10,11,14,15,12,13,16,17,0,1,2,3,4,5,20,21,22,23,18,19 }, { 9,8,11,10,7,6,15,14,17,16,13,12,21,20,23,22,19,18,1,0,3,2,5,4 }, { 10,11,8,9,6,7,20,21,22,23,18,19,14,15,16,17,12,13,0,1,4,5,2,3 }, { 11,10,7,6,9,8,21,20,19,18,23,22,1,0,5,4,3,2,15,14,17,16,13,12 }, { 12,13,14,15,16,17,2,3,0,1,4,5,8,9,6,7,10,11,22,23,18,19,20,21 }, { 13,12,17,16,15,14,3,2,5,4,1,0,23,22,19,18,21,20,9,8,7,6,11,10 }, { 14,15,16,17,12,13,8,9,10,11,6,7,22,23,20,21,18,19,2,3,0,1,4,5 }, { 15,14,13,12,17,16,9,8,7,6,11,10,3,2,1,0,5,4,23,22,21,20,19,18 }, { 16,17,12,13,14,15,22,23,18,19,20,21,2,3,4,5,0,1,8,9,10,11,6,7 }, { 17,16,15,14,13,12,23,22,21,20,19,18,9,8,11,10,7,6,3,2,5,4,1,0 }, { 18,19,22,23,20,21,4,5,2,3,0,1,16,17,12,13,14,15,10,11,6,7,8,9 }, { 19,18,21,20,23,22,5,4,1,0,3,2,11,10,7,6,9,8,17,16,13,12,15,14 }, { 20,21,18,19,22,23,10,11,6,7,8,9,4,5,0,1,2,3,16,17,14,15,12,13 }, { 21,20,23,22,19,18,11,10,9,8,7,6,17,16,15,14,13,12,5,4,1,0,3,2 }, { 22,23,20,21,18,19,16,17,14,15,12,13,10,11,8,9,6,7,4,5,2,3,0,1 }, { 23,22,19,18,21,20,17,16,13,12,15,14,5,4,3,2,1,0,11,10,9,8,7,6 } }; const unsigned char NPerm4::swapTable[4][4] = { { 0, 7, 15, 21 }, { 7, 0, 3, 5 }, { 15, 3, 0, 1 }, { 21, 5, 1, 0 } }; NPerm4::NPerm4(int a0, int a1, int b0, int b1, int c0, int c1, int d0, int d1) { int image[4]; image[a0] = a1; image[b0] = b1; image[c0] = c1; image[d0] = d1; code_ = static_cast( S4Index(image[0], image[1], image[2], image[3])); } bool NPerm4::isPermCode(unsigned char code) { unsigned mask = 0; for (int i = 0; i < 4; i++) mask |= (1 << ((code >> (2 * i)) & 3)); // mask |= (1 << imageOf(i)); return (mask == 15); } std::string NPerm4::str() const { char ans[5]; for (int i = 0; i < 4; i++) ans[i] = static_cast('0' + imageTable[code_][i]); ans[4] = 0; return ans; } std::string NPerm4::trunc2() const { char ans[3]; ans[0] = static_cast('0' + imageTable[code_][0]); ans[1] = static_cast('0' + imageTable[code_][1]); ans[2] = 0; return ans; } std::string NPerm4::trunc3() const { char ans[4]; ans[0] = static_cast('0' + imageTable[code_][0]); ans[1] = static_cast('0' + imageTable[code_][1]); ans[2] = static_cast('0' + imageTable[code_][2]); ans[3] = 0; return ans; } NPerm4 faceOrdering(int face) { switch(face) { case 0: return NPerm4(1,2,3,0); case 1: return NPerm4(0,2,3,1); case 2: return NPerm4(0,1,3,2); case 3: return NPerm4(0,1,2,3); } return NPerm4(); } NPerm4 edgeOrdering(int edge) { switch(edge) { case 0: return NPerm4(0,1,2,3); case 1: return NPerm4(0,2,3,1); case 2: return NPerm4(0,3,1,2); case 3: return NPerm4(1,2,0,3); case 4: return NPerm4(1,3,2,0); case 5: return NPerm4(2,3,0,1); } return NPerm4(); } std::string faceDescription(int face) { // deprecated return NTriangle::ordering[face].trunc3(); } std::string edgeDescription(int edge) { // deprecated return NEdge::ordering[edge].trunc2(); } } // namespace regina regina-4.96/engine/maths/nperm4.h000644 000765 000024 00000115740 12377775272 016602 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file maths/nperm4.h * \brief Deals with permutations of {0,1,2,3}. */ #ifndef __NPERM4_H #ifndef __DOXYGEN #define __NPERM4_H #endif #include #include "regina-core.h" namespace regina { /** * \weakgroup maths * @{ */ /** * Represents a permutation of {0,1,2,3}. * Amongst other things, such permutations are used in specifying how * simplices of a 3-manifold triangulation are glued together. * NPerm4 objects are small enough to pass about by value instead of by * reference. * * Each permutation has an internal code, and this code is sufficient to * reconstruct the permutation. * Thus the internal code may be a useful means for passing * permutation objects to and from the engine. * * The internal permutation codes have changed as of Regina 4.6.1: * * - \e First-generation codes were used internally in Regina 4.6 and earlier. * These codes were characters whose lowest two bits represented the * image of 0, whose next lowest two bits represented the image of 1, * and so on. The routines getPermCode(), setPermCode(), fromPermCode() * and isPermCode() continue to work with first-generation codes for * backward compatibility. Likewise, the XML data file format * continues to use first-generation codes to describe tetrahedron gluings. * * - \e Second-generation codes are used internally in Regina 4.6.1 and above. * These codes are integers between 0 and 23 inclusive, representing the * index of the permutation in the array NPerm4::S4. The routines * getPermCode2(), setPermCode2(), fromPermCode2() and isPermCode2() * work with second-generation codes. * * It is highly recommended that, if you need to work with permutation * codes at all, you use second-generation codes where possible. This * is because the first-generation routines incur additional overhead * in converting back and forth between the second-generation codes * (which are used internally by NPerm4). */ class REGINA_API NPerm4 { public: /** * Contains all possible permutations of four elements. * * The permutations with even indices in the array are the even * permutations, and those with odd indices in the array are the * odd permutations. * * For all permutation classes (NPerm4, NPerm5 and so on), the * S4 array stores the same permutations in the same order (but * of course using different data types). * * Note that the permutations are not necessarily in * lexicographical order. */ static const NPerm4 S4[24]; /** * A dimension-agnostic alias for NPerm4::S4. In general, for * each \a K the class NPermK will define an alias \a Sn * that references the list of all permutations NPermK::SK. */ static const NPerm4* Sn; /** * Contains the inverses of the permutations in the array \a S4. * * Specifically, the inverse of permutation S4[i] is * the permutation S4[ invS4[i] ]. */ static const unsigned invS4[24]; /** * A dimension-agnostic alias for NPerm4::invS4. In general, for * each \a K the class NPermK will define an alias \a invSn * that references the list of all permutations NPermK::invSK. */ static const unsigned* invSn; /** * Contains all possible permutations of four elements in * lexicographical order. */ static const NPerm4 orderedS4[24]; /** * A dimension-agnostic alias for NPerm4::orderedS4. In general, for * each \a K the class NPermK will define an alias \a orderedSn * that references the list of all permutations NPermK::orderedSK. */ static const NPerm4* orderedSn; /** * Contains all possible permutations of three elements. * In each permutation, 3 maps to 3. * * The permutations with even indices in the array are the even * permutations, and those with odd indices in the array are the * odd permutations. * * For all permutation classes (NPerm4, NPerm5 and so on), the * S3 array stores the same permutations in the same order (but * of course using different data types). * * Note that the permutations are not necessarily in * lexicographical order. For the corresponding inverse array, * see NPerm3::invS3. */ static const NPerm4 S3[6]; /** * A dimension-agnostic alias for NPerm4::S3. In general, for * each \a K the class NPermK will define an alias \a Sn_1 * that references the list of all permutations NPermK::S(K-1). */ static const NPerm4* Sn_1; /** * Contains the inverses of the permutations in the array \a S3. * * Specifically, the inverse of permutation S3[i] is * the permutation S3[ invS3[i] ]. * * \deprecated This is identical to the array NPerm3::invS3. * This unnecessary copy in NPerm4 will be removed in some * future version of Regina. */ static const unsigned invS3[6]; /** * Contains all possible permutations of three elements in * lexicographical order. In each permutation, 3 maps to 3. */ static const NPerm4 orderedS3[6]; /** * Contains all possible permutations of two elements. * In each permutation, 2 maps to 2 and 3 maps to 3. * * The permutations with even indices in the array are the even * permutations, and those with odd indices in the array are the * odd permutations. * * For all permutation classes (NPerm4, NPerm5 and so on), the * S2 array stores the same permutations in the same order (but * of course using different data types). * * Note that these permutations are already in lexicographical order. */ static const NPerm4 S2[2]; /** * Contains the inverses of the permutations in the array \a S2. * * Specifically, the inverse of permutation S2[i] is * the permutation S2[ invS2[i] ]. * * \deprecated This array is unnecessary, since all elements of S2 are * their own inverses. This array will be removed in some future * version of Regina. */ static const unsigned invS2[2]; enum { /** * The total number of permutations on four elements. * This is the size of the array Sn. * * \ifacespython Not present. */ nPerms = 24, /** * The total number of permutations on three elements. * This is the size of the array Sn_1. * * \ifacespython Not present. */ nPerms_1 = 6 }; private: unsigned char code_; /**< The internal code representing this permutation. */ public: /** * Creates the identity permutation. */ NPerm4(); /** * Creates the transposition of \a a and \a b. * Note that \a a and \a b need not be distinct. * * \pre \a a and \a b are in {0,1,2,3}. * * @param a the element to switch with \a b. * @param b the element to switch with \a a. */ NPerm4(int a, int b); /** * Creates a permutation mapping (0,1,2,3) to * (a,b,c,d) respectively. * * \pre {a,b,c,d} = {0,1,2,3}. * * @param a the desired image of 0. * @param b the desired image of 1. * @param c the desired image of 2. * @param d the desired image of 3. */ NPerm4(int a, int b, int c, int d); /** * Creates a permutation mapping \a i to \a image[i] for each * \a i = 0,1,2,3. * * \pre The array \a image contains four elements, which are * 0, 1, 2 and 3 in some order. * * \ifacespython Not present. * * @param image the array of images. */ NPerm4(const int* image); /** * Creates a permutation mapping * (a0,b0,c0,d0) to * (a1,b1,c1,d1) respectively. * * \pre {a0,b0,c0,d0} = * {a1,b1,c1,d1} = * {0,1,2,3}. * * @param a0 the desired preimage of a1. * @param b0 the desired preimage of b1. * @param c0 the desired preimage of c1. * @param d0 the desired preimage of d1. * @param a1 the desired image of a0. * @param b1 the desired image of b0. * @param c1 the desired image of c0. * @param d1 the desired image of d0. */ NPerm4(int a0, int a1, int b0, int b1, int c0, int c1, int d0, int d1); /** * Creates a permutation that is a clone of the given * permutation. * * @param cloneMe the permutation to clone. */ NPerm4(const NPerm4& cloneMe); /** * Returns the first-generation code representing this permutation. * This code is sufficient to reproduce the entire permutation. * * The code returned will be a valid first-generation permutation * code as determined by isPermCode(). * * \warning This routine will incur additional overhead, since * NPerm4 now uses second-generation codes internally. * See the class notes and the routine getPermCode2() for details. * * @return the first-generation permutation code. */ unsigned char getPermCode() const; /** * Returns the second-generation code representing this permutation. * This code is sufficient to reproduce the entire permutation. * * The code returned will be a valid second-generation permutation * code as determined by isPermCode2(). * * Second-generation codes are fast to work with, since they are * used internally by the NPerm4 class. * * @return the second-generation permutation code. */ unsigned char getPermCode2() const; /** * Sets this permutation to that represented by the given * first-generation permutation code. * * \pre the given code is a valid first-generation permutation code; * see isPermCode() for details. * * \warning This routine will incur additional overhead, since * NPerm4 now uses second-generation codes internally. * See the class notes and the routine setPermCode2() for details. * * @param code the first-generation code that will determine the * new value of this permutation. */ void setPermCode(unsigned char code); /** * Sets this permutation to that represented by the given * second-generation permutation code. * * Second-generation codes are fast to work with, since they are * used internally by the NPerm4 class. * * \pre the given code is a valid second-generation permutation code; * see isPermCode2() for details. * * @param code the second-generation code that will determine the * new value of this permutation. */ void setPermCode2(unsigned char code); /** * Creates a permutation from the given first-generation * permutation code. * * \pre the given code is a valid first-generation permutation code; * see isPermCode() for details. * * \warning This routine will incur additional overhead, since * NPerm4 now uses second-generation codes internally. * See the class notes and the routine fromPermCode2() for details. * * @param code the first-generation code for the new permutation. * @return the permutation represented by the given code. */ static NPerm4 fromPermCode(unsigned char code); /** * Creates a permutation from the given second-generation * permutation code. * * Second-generation codes are fast to work with, since they are * used internally by the NPerm4 class. * * \pre the given code is a valid second-generation permutation code; * see isPermCode2() for details. * * @param code the second-generation code for the new permutation. * @return the permutation represented by the given code. */ static NPerm4 fromPermCode2(unsigned char code); /** * Determines whether the given character is a valid first-generation * permutation code. Valid first-generation codes can be passed to * setPermCode() or fromPermCode(), and are returned by getPermCode(). * * \warning This routine will incur additional overhead, since * NPerm4 now uses second-generation codes internally. * See the class notes and the routine isPermCode2() for details. * * @param code the permutation code to test. * @return \c true if and only if the given code is a valid * first-generation permutation code. */ static bool isPermCode(unsigned char code); /** * Determines whether the given character is a valid second-generation * permutation code. Valid second-generation codes can be passed * to setPermCode2() or fromPermCode2(), and are returned by * getPermCode2(). * * Second-generation codes are fast to work with, since they are * used internally by the NPerm4 class. * * @param code the permutation code to test. * @return \c true if and only if the given code is a valid * second-generation permutation code. */ static bool isPermCode2(unsigned char code); /** * Sets this permutation to the transposition of * \a a and \a b. * Note that \a a and \a b need not be distinct. * * \pre \a a and \a b are in {0,1,2,3}. * * \deprecated This routine is largely unnecessary, since NPerm4 * objects are tiny and cheap. Just use the assignment operator * instead. This routine will eventually be removed entirely in * a future version of Regina. * * @param a the element to switch with \a b. * @param b the element to switch with \a a. */ void setPerm(int a, int b); /** * Sets this permutation to that mapping (0,1,2,3) to * (a,b,c,d) respectively. * * \pre {a,b,c,d} = {0,1,2,3}. * * \deprecated This routine is largely unnecessary, since NPerm4 * objects are tiny and cheap. Just use the assignment operator * instead. This routine will eventually be removed entirely in * a future version of Regina. * * @param a the desired image of 0. * @param b the desired image of 1. * @param c the desired image of 2. * @param d the desired image of 3. */ void setPerm(int a, int b, int c, int d); /** * Sets this permutation to be equal to the given permutation. * * @param cloneMe the permutation whose value will be assigned * to this permutation. * @return a reference to this permutation. */ NPerm4& operator = (const NPerm4& cloneMe); /** * Returns the composition of this permutation with the given * permutation. If this permutation is p, the * resulting permutation will be p o q, satisfying * (p*q)[x] == p[q[x]]. * * @param q the permutation with which to compose this. * @return the composition of both permutations. */ NPerm4 operator *(const NPerm4& q) const; /** * Finds the inverse of this permutation. * * @return the inverse of this permutation. */ NPerm4 inverse() const; /** * Determines the sign of this permutation. * * @return 1 if this permutation is even, or -1 if this * permutation is odd. */ int sign() const; /** * Determines the image of the given integer under this * permutation. * * @param source the integer whose image we wish to find. This * should be between 0 and 3 inclusive. * @return the image of \a source. */ int operator[](int source) const; /** * Determines the preimage of the given integer under this * permutation. * * @param image the integer whose preimage we wish to find. This * should be between 0 and 3 inclusive. * @return the preimage of \a image. */ int preImageOf(int image) const; /** * Determines if this is equal to the given permutation. * This is true if and only if both permutations have the same * images for 0, 1, 2 and 3. * * @param other the permutation with which to compare this. * @return \c true if and only if this and the given permutation * are equal. */ bool operator == (const NPerm4& other) const; /** * Determines if this differs from the given permutation. * This is true if and only if the two permutations have * different images for at least one of 0, 1, 2 or 3. * * @param other the permutation with which to compare this. * @return \c true if and only if this and the given permutation * differ. */ bool operator != (const NPerm4& other) const; /** * Lexicographically compares the images of (0,1,2,3) under this * and the given permutation. * * @param other the permutation with which to compare this. * @return -1 if this permutation produces a smaller image, 0 if * the permutations are equal and 1 if this permutation produces * a greater image. */ int compareWith(const NPerm4& other) const; /** * Determines if this is the identity permutation. * This is true if and only if each of 0, 1, 2 and 3 is * mapped to itself. * * @return \c true if and only if this is the identity * permutation. */ bool isIdentity() const; /** * A deprecated alias for str(), which returns a string representation * of this permutation. * * \deprecated This routine has (at long last) been deprecated; * use the simpler-to-type str() instead. * * @return a string representation of this permutation. */ std::string toString() const; /** * Returns a string representation of this permutation. * The representation will consist of four adjacent digits * representing the images of 0, 1, 2 and 3 respectively. An * example of a string representation is 1302. * * @return a string representation of this permutation. */ std::string str() const; /** * Returns a string representation of this permutation with only * the images of 0 and 1. The resulting string will therefore * have length two. * * @return a truncated string representation of this permutation. */ std::string trunc2() const; /** * Returns a string representation of this permutation with only * the images of 0, 1 and 2 included. The resulting string will * therefore have length three. * * @return a truncated string representation of this permutation. */ std::string trunc3() const; /** * Returns the index of this permutation in the NPerm4::S4 array. * * @return the index \a i for which this permutation is equal to * NPerm4::S4[i]. This will be between 0 and 23 inclusive. */ int S4Index() const; /** * Returns the index of this permutation in the NPerm4::S4 array. * This is a dimension-agnostic alias for S4Index(). * * @return the index \a i for which this permutation is equal to * NPerm4::S4[i]. This will be between 0 and 23 inclusive. */ int SnIndex() const; /** * Returns the index of this permutation in the NPerm4::orderedS4 array. * * @return the index \a i for which this permutation is equal to * NPerm4::orderedS4[i]. This will be between 0 and 23 inclusive. */ int orderedS4Index() const; /** * Returns the index of this permutation in the NPerm4::orderedS4 array. * This is a dimension-agnostic alias for orderedS4Index(). * * @return the index \a i for which this permutation is equal to * NPerm4::orderedS4[i]. This will be between 0 and 23 inclusive. */ int orderedSnIndex() const; private: /** * Contains the images of every element under every possible * permutation. * * Specifically, the image of \a x under the permutation S4[i] * is imageTable[i][x]. */ static const unsigned char imageTable[24][4]; /** * Contains the full multiplication table for all possible * permutations. * * Specifically, the product S4[x] * S4[y] is the * permutation S4[product[x][y]]. */ static const unsigned char productTable[24][24]; /** * Contains a full table of two-element swaps. * * Specifically, the permutation that swaps \a x and \a y is * S4[swapTable[x][y]]. Here \a x and \a y may be equal. */ static const unsigned char swapTable[4][4]; private: /** * Creates a permutation from the given second-generation * permutation code. * * \pre the given code is a valid second-generation permutation code; * see isPermCode2() for details. * * @param code the second-generation code from which the new * permutation will be created. */ NPerm4(unsigned char code); /** * Returns the index into the NPerm4::S4 array of the permutation that * maps (0,1,2,3) to (a,b,c,d) respectively. * * \pre {a,b,c,d} = {0,1,2,3}. * * @param a the desired image of 0. * @param b the desired image of 1. * @param c the desired image of 2. * @param d the desired image of 3. * @return the index \a i for which the given permutation is equal to * NPerm4::S4[i]. This will be between 0 and 23 inclusive. */ static int S4Index(int a, int b, int c, int d); friend std::ostream& operator << (std::ostream& out, const NPerm4& p); }; /** * Writes a string representation of the given permutation to the given * output stream. The format will be the same as is used by * NPerm4::str(). * * @param out the output stream to which to write. * @param p the permutation to write. * @return a reference to \a out. */ inline REGINA_API std::ostream& operator << (std::ostream& out, const NPerm4& p) { return (out << p.str()); } // Constants /** * An array of size 24 containing all possible permutations of four elements. * * The permutations with even indices in the array are the even permutations, * and those with odd indices in the array are the odd permutations. * * Note that the permutations are not necessarily in lexicographical order. * * \deprecated This array has been moved into the NPerm4 class, and can now * be accessed as the static array NPerm4::S4. The deprecated name * regina::allPermsS4 now just points to NPerm4::S4, and will be removed * in some future version of Regina. */ REGINA_API extern const NPerm4* allPermsS4; /** * An array of size 24 containing the inverses of the permutations in the * array \a allPermsS4. * * Specifically, the inverse of permutation allPermsS4[i] is * the permutation allPermsS4[ allPermsS4Inv[i] ]. * * \deprecated This array has been moved into the NPerm4 class, and can now * be accessed as the static array NPerm4::invS4. The deprecated name * regina::allPermsS4Inv now just points to NPerm4::invS4, and will * be removed in some future version of Regina. */ REGINA_API extern const unsigned* allPermsS4Inv; /** * An array of size 24 containing all possible permutations of four elements * in lexicographical order. * * \deprecated This array has been moved into the NPerm4 class, and can now * be accessed as the static array NPerm4::orderedS4. The deprecated name * regina::orderedPermsS4 now just points to NPerm4::orderedS4, and will be * removed in some future version of Regina. */ REGINA_API extern const NPerm4* orderedPermsS4; /** * An array of size 6 containing all possible permutations of three elements. * In each permutation, 3 maps to 3. * * The permutations with even indices in the array are the even permutations, * and those with odd indices in the array are the odd permutations. * * Note that the permutations are not necessarily in lexicographical order. * * \deprecated This array has been moved into the NPerm4 class, and can now * be accessed as the static array NPerm4::S3. The deprecated name * regina::allPermsS4 now just points to NPerm4::S3, and will be removed * in some future version of Regina. */ REGINA_API extern const NPerm4* allPermsS3; /** * An array of size 6 containing the inverses of the permutations in the * array \a allPermsS3. * * Specifically, the inverse of permutation allPermsS3[i] is * the permutation allPermsS3[ allPermsS3Inv[i] ]. * * \deprecated This array has been moved into the NPerm3 class, and can now * be accessed as the static array NPerm3::invS3. The deprecated name * regina::allPermsS3Inv now just points to NPerm3::invS3, and will be * removed in some future version of Regina. */ REGINA_API extern const unsigned* allPermsS3Inv; /** * An array of size 6 containing all possible permutations of three elements * in lexicographical order. In each permutation, 3 maps to 3. * * \deprecated This array has been moved into the NPerm4 class, and can now * be accessed as the static array NPerm4::orderedS3. The deprecated name * regina::orderedPermsS3 now just points to NPerm4::orderedS3, and will be * removed in some future version of Regina. */ REGINA_API extern const NPerm4* orderedPermsS3; /** * An array of size 2 containing all possible permutations of two elements. * In each permutation, 2 maps to 2 and 3 maps to 3. * * The permutations with even indices in the array are the even permutations, * and those with odd indices in the array are the odd permutations. * * Note that the permutations are also in lexicographical order. * * \deprecated This array has been moved into the NPerm4 class, and can now * be accessed as the static array NPerm4::S2. The deprecated name * regina::allPermsS2 now just points to NPerm4::S2, and will be removed in * some future version of Regina. */ REGINA_API extern const NPerm4* allPermsS2; /** * An array of size 2 containing the inverses of the permutations in the * array \a allPermsS2. * * Specifically, the inverse of permutation allPermsS2[i] is * the permutation allPermsS2[ allPermsS2Inv[i] ]. * * \deprecated This array is unnecessary, since all elements of S2 are * their own inverses. This array will be removed in some future version * of Regina. */ REGINA_API extern const unsigned* allPermsS2Inv; // Routines for constructing the permutations associated to // triangles and edges of the triangulation /** * Returns a permutation mapping (0,1,2) to the vertices of the * given tetrahedron face in their canonical order. The images of * (0,1,2) will be the vertex numbers of the vertices that make up the * given face of a generic tetrahedron. * * \deprecated This routine is no longer recommended, and will be * removed in some future version of Regina. Please use the lookup * table NTriangle::ordering instead (which gives identical results). * * @param face a face number in a tetrahedron. This should be between 0 * and 3 inclusive. Note that face i is opposite vertex * i. * @return the permutation representing the canonical ordering of * vertices in the given face. */ REGINA_API NPerm4 faceOrdering(int face); /** * Returns a permutation mapping (0,1) to the vertices of the * given tetrahedron edge in their canonical order. The images of * (0,1) will be the vertex numbers of the vertices that make up the * given edge of a generic tetrahedron. * * The images of 2 and 3 in the returned permutation will be chosen so * that the permutation will be even. * * \deprecated This routine is no longer recommended, and will be * removed in some future version of Regina. Please use the lookup * table NEdge::ordering instead (which gives identical results). * * @param edge an edge number in a tetrahedron. This should be between 0 and * 5 inclusive. The constant arrays NEdge::edgeNumber and NEdge::edgeVertex * describe which vertex numbers are joined by which edge numbers. * @return the permutation representing the canonical ordering of * vertices in the given edge. */ REGINA_API NPerm4 edgeOrdering(int edge); /** * Returns a string representation of the permutation mapping * (0,1,2) to the vertices of the given tetrahedron face in their * canonical order, as described in faceOrdering(). * Only the images of 0, 1 and 2 will be put in the string. * * \deprecated This routine is no longer recommended, and will be * removed in some future version of Regina. Please use * NTriangle::ordering[face].trunc3() (which gives identical results). * * @param face a face number in a tetrahedron. This should be between 0 * and 3 inclusive. Note that face i is opposite vertex * i. * @return a string representing the * canonical ordering of vertices in the given face. */ REGINA_API std::string faceDescription(int face); /** * Returns a string representation of the given permutation with only * the images of 0, 1 and 2 included. * * \deprecated This routine is no longer recommended, and will be * removed in some future version of Regina. Please use NPerm4::trunc3() * instead (which gives identical results). * * @param facePerm the permutation to represent. * @return a restricted string representation of the given permutation. */ REGINA_API std::string faceDescription(const NPerm4& facePerm); /** * Returns a string representation of the permutation mapping * (0,1) to the vertices of the given tetrahedron edge in their * canonical order, as described in edgeOrdering(). * Only the images of 0 and 1 will be put in the string. * * \deprecated This routine is no longer recommended, and will be * removed in some future version of Regina. Please use * NEdge::ordering[edge].trunc2() (which gives identical results). * * @param edge an edge number in a tetrahedron. This should be between 0 and * 5 inclusive. The constant arrays NEdge::edgeNumber and NEdge::edgeVertex * describe which vertex numbers are joined by which edge numbers. * @return a string representing the canonical ordering of * vertices in the given edge. */ REGINA_API std::string edgeDescription(int edge); /** * Returns a string representation of the given permutation with only * the images of 0 and 1 included. * * \deprecated This routine is no longer recommended, and will be * removed in some future version of Regina. Please use NPerm4::trunc2() * instead (which gives identical results). * * @param edgePerm the permutation to represent. * @return a restricted string representation of the given permutation. */ REGINA_API std::string edgeDescription(const NPerm4& edgePerm); /*@}*/ // Inline functions for NPerm4 inline NPerm4::NPerm4() : code_(0) { } inline NPerm4::NPerm4(unsigned char code) : code_(code) { } inline NPerm4::NPerm4(int a, int b) : code_(swapTable[a][b]) { } inline NPerm4::NPerm4(int a, int b, int c, int d) : code_(static_cast(S4Index(a, b, c, d))) { } inline NPerm4::NPerm4(const int* image) : code_(static_cast(S4Index( image[0], image[1], image[2], image[3]))) { } inline NPerm4::NPerm4(const NPerm4& cloneMe) : code_(cloneMe.code_) { } inline void NPerm4::setPerm(int a, int b) { code_ = swapTable[a][b]; } inline void NPerm4::setPerm(int a, int b, int c, int d) { code_ = static_cast(S4Index(a, b, c, d)); } inline unsigned char NPerm4::getPermCode() const { return static_cast( imageTable[code_][0] | (imageTable[code_][1] << 2) | (imageTable[code_][2] << 4) | (imageTable[code_][3] << 6)); } inline unsigned char NPerm4::getPermCode2() const { return code_; } inline void NPerm4::setPermCode(unsigned char code) { code_ = static_cast(S4Index( code & 0x03, (code >> 2) & 0x03, (code >> 4) & 0x03, (code >> 6) & 0x03)); } inline void NPerm4::setPermCode2(unsigned char code) { code_ = code; } inline NPerm4 NPerm4::fromPermCode(unsigned char code) { return NPerm4(static_cast(S4Index( code & 0x03, (code >> 2) & 0x03, (code >> 4) & 0x03, (code >> 6) & 0x03))); } inline NPerm4 NPerm4::fromPermCode2(unsigned char code) { return NPerm4(code); } inline bool NPerm4::isPermCode2(unsigned char code) { // code >= 0 is automatic because we are using an unsigned data type. return (code < 24); } inline NPerm4& NPerm4::operator = (const NPerm4& cloneMe) { code_ = cloneMe.code_; return *this; } inline NPerm4 NPerm4::operator *(const NPerm4& q) const { return NPerm4(productTable[code_][q.code_]); } inline NPerm4 NPerm4::inverse() const { return NPerm4(static_cast(invS4[code_])); } inline int NPerm4::sign() const { return (code_ % 2 ? -1 : 1); } inline int NPerm4::operator[](int source) const { return imageTable[code_][source]; } inline int NPerm4::preImageOf(int image) const { return imageTable[invS4[code_]][image]; } inline int NPerm4::compareWith(const NPerm4& other) const { // Computing orderedS4Index() is very fast, now that we use S4 indices // for internal permutation codes. Use this instead of comparing images // one at a time. int o1 = orderedS4Index(); int o2 = other.orderedS4Index(); return (o1 == o2 ? 0 : o1 < o2 ? -1 : 1); } inline bool NPerm4::isIdentity() const { return (code_ == 0); } inline std::string NPerm4::toString() const { return str(); } inline bool NPerm4::operator == (const NPerm4& other) const { return (code_ == other.code_); } inline bool NPerm4::operator != (const NPerm4& other) const { return (code_ != other.code_); } inline int NPerm4::S4Index() const { return code_; } inline int NPerm4::orderedS4Index() const { // S4 is almost the same as orderedS4, except that some pairs // S4[2i] <--> S4[2i+1] have been swapped to ensure that all // permutations S4[2i] are even and all permutations S4[2i+1] are odd. // // Specifically, we must interchange all pairs 4i+2 <--> 4i+3. return ((code_ & 2) ? (code_ ^ 1) : code_); } inline int NPerm4::orderedSnIndex() const { return orderedS4Index(); } inline int NPerm4::S4Index(int a, int b, int c, int d) { int orderedS4Index = 6 * a + 2 * (b - (b > a ? 1 : 0)) + (c > d ? 1 : 0); // As above, to obtain an S4 index, interchange all pairs 4i+2 <--> 4i+3. return ((orderedS4Index & 2) ? (orderedS4Index ^ 1) : orderedS4Index); } inline int NPerm4::SnIndex() const { return S4Index(); } inline std::string faceDescription(const NPerm4& facePerm) { return facePerm.trunc3(); } inline std::string edgeDescription(const NPerm4& edgePerm) { return edgePerm.trunc2(); } } // namespace regina #endif regina-4.96/engine/maths/nperm5.cpp000644 000765 000024 00000031721 12377776627 017137 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "maths/nperm5.h" namespace regina { const NPerm5 NPerm5::S5[120] = { NPerm5(0,1,2,3,4), NPerm5(0,1,2,4,3), NPerm5(0,1,3,4,2), NPerm5(0,1,3,2,4), NPerm5(0,1,4,2,3), NPerm5(0,1,4,3,2), NPerm5(0,2,1,4,3), NPerm5(0,2,1,3,4), NPerm5(0,2,3,1,4), NPerm5(0,2,3,4,1), NPerm5(0,2,4,3,1), NPerm5(0,2,4,1,3), NPerm5(0,3,1,2,4), NPerm5(0,3,1,4,2), NPerm5(0,3,2,4,1), NPerm5(0,3,2,1,4), NPerm5(0,3,4,1,2), NPerm5(0,3,4,2,1), NPerm5(0,4,1,3,2), NPerm5(0,4,1,2,3), NPerm5(0,4,2,1,3), NPerm5(0,4,2,3,1), NPerm5(0,4,3,2,1), NPerm5(0,4,3,1,2), NPerm5(1,0,2,4,3), NPerm5(1,0,2,3,4), NPerm5(1,0,3,2,4), NPerm5(1,0,3,4,2), NPerm5(1,0,4,3,2), NPerm5(1,0,4,2,3), NPerm5(1,2,0,3,4), NPerm5(1,2,0,4,3), NPerm5(1,2,3,4,0), NPerm5(1,2,3,0,4), NPerm5(1,2,4,0,3), NPerm5(1,2,4,3,0), NPerm5(1,3,0,4,2), NPerm5(1,3,0,2,4), NPerm5(1,3,2,0,4), NPerm5(1,3,2,4,0), NPerm5(1,3,4,2,0), NPerm5(1,3,4,0,2), NPerm5(1,4,0,2,3), NPerm5(1,4,0,3,2), NPerm5(1,4,2,3,0), NPerm5(1,4,2,0,3), NPerm5(1,4,3,0,2), NPerm5(1,4,3,2,0), NPerm5(2,0,1,3,4), NPerm5(2,0,1,4,3), NPerm5(2,0,3,4,1), NPerm5(2,0,3,1,4), NPerm5(2,0,4,1,3), NPerm5(2,0,4,3,1), NPerm5(2,1,0,4,3), NPerm5(2,1,0,3,4), NPerm5(2,1,3,0,4), NPerm5(2,1,3,4,0), NPerm5(2,1,4,3,0), NPerm5(2,1,4,0,3), NPerm5(2,3,0,1,4), NPerm5(2,3,0,4,1), NPerm5(2,3,1,4,0), NPerm5(2,3,1,0,4), NPerm5(2,3,4,0,1), NPerm5(2,3,4,1,0), NPerm5(2,4,0,3,1), NPerm5(2,4,0,1,3), NPerm5(2,4,1,0,3), NPerm5(2,4,1,3,0), NPerm5(2,4,3,1,0), NPerm5(2,4,3,0,1), NPerm5(3,0,1,4,2), NPerm5(3,0,1,2,4), NPerm5(3,0,2,1,4), NPerm5(3,0,2,4,1), NPerm5(3,0,4,2,1), NPerm5(3,0,4,1,2), NPerm5(3,1,0,2,4), NPerm5(3,1,0,4,2), NPerm5(3,1,2,4,0), NPerm5(3,1,2,0,4), NPerm5(3,1,4,0,2), NPerm5(3,1,4,2,0), NPerm5(3,2,0,4,1), NPerm5(3,2,0,1,4), NPerm5(3,2,1,0,4), NPerm5(3,2,1,4,0), NPerm5(3,2,4,1,0), NPerm5(3,2,4,0,1), NPerm5(3,4,0,1,2), NPerm5(3,4,0,2,1), NPerm5(3,4,1,2,0), NPerm5(3,4,1,0,2), NPerm5(3,4,2,0,1), NPerm5(3,4,2,1,0), NPerm5(4,0,1,2,3), NPerm5(4,0,1,3,2), NPerm5(4,0,2,3,1), NPerm5(4,0,2,1,3), NPerm5(4,0,3,1,2), NPerm5(4,0,3,2,1), NPerm5(4,1,0,3,2), NPerm5(4,1,0,2,3), NPerm5(4,1,2,0,3), NPerm5(4,1,2,3,0), NPerm5(4,1,3,2,0), NPerm5(4,1,3,0,2), NPerm5(4,2,0,1,3), NPerm5(4,2,0,3,1), NPerm5(4,2,1,3,0), NPerm5(4,2,1,0,3), NPerm5(4,2,3,0,1), NPerm5(4,2,3,1,0), NPerm5(4,3,0,2,1), NPerm5(4,3,0,1,2), NPerm5(4,3,1,0,2), NPerm5(4,3,1,2,0), NPerm5(4,3,2,1,0), NPerm5(4,3,2,0,1), }; const NPerm5* NPerm5::Sn = NPerm5::S5; const NPerm5 NPerm5::orderedS5[120] = { NPerm5(0,1,2,3,4), NPerm5(0,1,2,4,3), NPerm5(0,1,3,2,4), NPerm5(0,1,3,4,2), NPerm5(0,1,4,2,3), NPerm5(0,1,4,3,2), NPerm5(0,2,1,3,4), NPerm5(0,2,1,4,3), NPerm5(0,2,3,1,4), NPerm5(0,2,3,4,1), NPerm5(0,2,4,1,3), NPerm5(0,2,4,3,1), NPerm5(0,3,1,2,4), NPerm5(0,3,1,4,2), NPerm5(0,3,2,1,4), NPerm5(0,3,2,4,1), NPerm5(0,3,4,1,2), NPerm5(0,3,4,2,1), NPerm5(0,4,1,2,3), NPerm5(0,4,1,3,2), NPerm5(0,4,2,1,3), NPerm5(0,4,2,3,1), NPerm5(0,4,3,1,2), NPerm5(0,4,3,2,1), NPerm5(1,0,2,3,4), NPerm5(1,0,2,4,3), NPerm5(1,0,3,2,4), NPerm5(1,0,3,4,2), NPerm5(1,0,4,2,3), NPerm5(1,0,4,3,2), NPerm5(1,2,0,3,4), NPerm5(1,2,0,4,3), NPerm5(1,2,3,0,4), NPerm5(1,2,3,4,0), NPerm5(1,2,4,0,3), NPerm5(1,2,4,3,0), NPerm5(1,3,0,2,4), NPerm5(1,3,0,4,2), NPerm5(1,3,2,0,4), NPerm5(1,3,2,4,0), NPerm5(1,3,4,0,2), NPerm5(1,3,4,2,0), NPerm5(1,4,0,2,3), NPerm5(1,4,0,3,2), NPerm5(1,4,2,0,3), NPerm5(1,4,2,3,0), NPerm5(1,4,3,0,2), NPerm5(1,4,3,2,0), NPerm5(2,0,1,3,4), NPerm5(2,0,1,4,3), NPerm5(2,0,3,1,4), NPerm5(2,0,3,4,1), NPerm5(2,0,4,1,3), NPerm5(2,0,4,3,1), NPerm5(2,1,0,3,4), NPerm5(2,1,0,4,3), NPerm5(2,1,3,0,4), NPerm5(2,1,3,4,0), NPerm5(2,1,4,0,3), NPerm5(2,1,4,3,0), NPerm5(2,3,0,1,4), NPerm5(2,3,0,4,1), NPerm5(2,3,1,0,4), NPerm5(2,3,1,4,0), NPerm5(2,3,4,0,1), NPerm5(2,3,4,1,0), NPerm5(2,4,0,1,3), NPerm5(2,4,0,3,1), NPerm5(2,4,1,0,3), NPerm5(2,4,1,3,0), NPerm5(2,4,3,0,1), NPerm5(2,4,3,1,0), NPerm5(3,0,1,2,4), NPerm5(3,0,1,4,2), NPerm5(3,0,2,1,4), NPerm5(3,0,2,4,1), NPerm5(3,0,4,1,2), NPerm5(3,0,4,2,1), NPerm5(3,1,0,2,4), NPerm5(3,1,0,4,2), NPerm5(3,1,2,0,4), NPerm5(3,1,2,4,0), NPerm5(3,1,4,0,2), NPerm5(3,1,4,2,0), NPerm5(3,2,0,1,4), NPerm5(3,2,0,4,1), NPerm5(3,2,1,0,4), NPerm5(3,2,1,4,0), NPerm5(3,2,4,0,1), NPerm5(3,2,4,1,0), NPerm5(3,4,0,1,2), NPerm5(3,4,0,2,1), NPerm5(3,4,1,0,2), NPerm5(3,4,1,2,0), NPerm5(3,4,2,0,1), NPerm5(3,4,2,1,0), NPerm5(4,0,1,2,3), NPerm5(4,0,1,3,2), NPerm5(4,0,2,1,3), NPerm5(4,0,2,3,1), NPerm5(4,0,3,1,2), NPerm5(4,0,3,2,1), NPerm5(4,1,0,2,3), NPerm5(4,1,0,3,2), NPerm5(4,1,2,0,3), NPerm5(4,1,2,3,0), NPerm5(4,1,3,0,2), NPerm5(4,1,3,2,0), NPerm5(4,2,0,1,3), NPerm5(4,2,0,3,1), NPerm5(4,2,1,0,3), NPerm5(4,2,1,3,0), NPerm5(4,2,3,0,1), NPerm5(4,2,3,1,0), NPerm5(4,3,0,1,2), NPerm5(4,3,0,2,1), NPerm5(4,3,1,0,2), NPerm5(4,3,1,2,0), NPerm5(4,3,2,0,1), NPerm5(4,3,2,1,0), }; const NPerm5* NPerm5::orderedSn = NPerm5::orderedS5; const unsigned NPerm5::invS5[120] = { 0, 1, 4, 3, 2, 5, 6, 7, 12, 19, 18, 13, 8, 11, 20, 15, 16, 23, 10, 9, 14, 21, 22, 17, 24, 25, 26, 29, 28, 27, 48, 49, 96, 73, 72, 97, 52, 51, 74, 99,100, 77, 50, 53, 98, 75, 76,101, 30, 31, 42, 37, 36, 43, 54, 55, 78,103,102, 79, 60, 67,108, 85, 90,115, 66, 61, 84,109,114, 91, 34, 33, 38, 45, 46, 41, 56, 59,104, 81, 82,107, 68, 63, 86,111,116, 93, 64, 71,112, 89, 94,119, 32, 35, 44, 39, 40, 47, 58, 57, 80,105,106, 83, 62, 69,110, 87, 92,117, 70, 65, 88,113,118, 95 }; const unsigned* NPerm5::invSn = NPerm5::invS5; const NPerm5 NPerm5::S4[24] = { NPerm5(0,1,2,3,4), NPerm5(0,1,3,2,4), NPerm5(0,2,3,1,4), NPerm5(0,2,1,3,4), NPerm5(0,3,1,2,4), NPerm5(0,3,2,1,4), NPerm5(1,0,3,2,4), NPerm5(1,0,2,3,4), NPerm5(1,2,0,3,4), NPerm5(1,2,3,0,4), NPerm5(1,3,2,0,4), NPerm5(1,3,0,2,4), NPerm5(2,0,1,3,4), NPerm5(2,0,3,1,4), NPerm5(2,1,3,0,4), NPerm5(2,1,0,3,4), NPerm5(2,3,0,1,4), NPerm5(2,3,1,0,4), NPerm5(3,0,2,1,4), NPerm5(3,0,1,2,4), NPerm5(3,1,0,2,4), NPerm5(3,1,2,0,4), NPerm5(3,2,1,0,4), NPerm5(3,2,0,1,4) }; const NPerm5* NPerm5::Sn_1 = NPerm5::S4; const NPerm5 NPerm5::orderedS4[24] = { NPerm5(0,1,2,3,4), NPerm5(0,1,3,2,4), NPerm5(0,2,1,3,4), NPerm5(0,2,3,1,4), NPerm5(0,3,1,2,4), NPerm5(0,3,2,1,4), NPerm5(1,0,2,3,4), NPerm5(1,0,3,2,4), NPerm5(1,2,0,3,4), NPerm5(1,2,3,0,4), NPerm5(1,3,0,2,4), NPerm5(1,3,2,0,4), NPerm5(2,0,1,3,4), NPerm5(2,0,3,1,4), NPerm5(2,1,0,3,4), NPerm5(2,1,3,0,4), NPerm5(2,3,0,1,4), NPerm5(2,3,1,0,4), NPerm5(3,0,1,2,4), NPerm5(3,0,2,1,4), NPerm5(3,1,0,2,4), NPerm5(3,1,2,0,4), NPerm5(3,2,0,1,4), NPerm5(3,2,1,0,4) }; const NPerm5 NPerm5::S3[6] = { NPerm5(0,1,2,3,4), NPerm5(0,2,1,3,4), NPerm5(1,2,0,3,4), NPerm5(1,0,2,3,4), NPerm5(2,0,1,3,4), NPerm5(2,1,0,3,4) }; const NPerm5 NPerm5::orderedS3[6] = { NPerm5(0,1,2,3,4), NPerm5(0,2,1,3,4), NPerm5(1,0,2,3,4), NPerm5(1,2,0,3,4), NPerm5(2,0,1,3,4), NPerm5(2,1,0,3,4) }; const NPerm5 NPerm5::S2[2] = { NPerm5(0,1,2,3,4), NPerm5(1,0,2,3,4) }; bool NPerm5::isPermCode(unsigned code) { unsigned mask = 0; for (int i = 0; i < 5; i++) mask |= (1 << ((code >> (3 * i)) & 7)); // mask |= (1 << imageOf(i)); return (mask == 31); } int NPerm5::sign() const { // Try to streamline this routine. // Count the number of elements that map to themselves. unsigned matches = 0; if ((code & 7) == 0) ++matches; if ((code & (7 << 3)) == (1 << 3)) ++matches; if ((code & (7 << 6)) == (2 << 6)) ++matches; if ((code & (7 << 9)) == (3 << 9)) ++matches; if ((code & (7 << 12)) == (4 << 12)) ++matches; if (matches == 5) return 1; if (matches == 3) return -1; if (matches == 2) return 1; // We have at most one fixed point. // Now count the number of order two points. unsigned two = 0; if (((code >> (3 * (code & 7))) & 7) == 0) ++two; if (((code >> (3 * ((code >> 3) & 7))) & 7) == 1) ++two; if (((code >> (3 * ((code >> 6) & 7))) & 7) == 2) ++two; if (((code >> (3 * ((code >> 9) & 7))) & 7) == 3) ++two; if (((code >> (3 * ((code >> 12) & 7))) & 7) == 4) ++two; if (matches == 1) { // We have one fixed point, which means we have a permutation // of four elements that leaves nothing fixed. // This means either (a b)(c d) or (a b c d). if (two == 5) return 1; return -1; } // We have no fixed points, which means we have either // (a b)(c d e) or (a b c d e). if (two == 0) return 1; return -1; } int NPerm5::compareWith(const NPerm5& other) const { for (int i = 0; i < 5; i++) { if (imageOf(i) < other.imageOf(i)) return -1; if (imageOf(i) > other.imageOf(i)) return 1; } return 0; } std::string NPerm5::str() const { char ans[6]; for (int i = 0; i < 5; i++) ans[i] = static_cast('0' + imageOf(i)); ans[5] = 0; return ans; } std::string NPerm5::trunc2() const { char ans[3]; ans[0] = static_cast('0' + imageOf(0)); ans[1] = static_cast('0' + imageOf(1)); ans[2] = 0; return ans; } std::string NPerm5::trunc3() const { char ans[4]; ans[0] = static_cast('0' + imageOf(0)); ans[1] = static_cast('0' + imageOf(1)); ans[2] = static_cast('0' + imageOf(2)); ans[3] = 0; return ans; } std::string NPerm5::trunc4() const { char ans[5]; ans[0] = static_cast('0' + imageOf(0)); ans[1] = static_cast('0' + imageOf(1)); ans[2] = static_cast('0' + imageOf(2)); ans[3] = static_cast('0' + imageOf(3)); ans[4] = 0; return ans; } /** * Returns the number n such that NPerm5::orderedS5[n] == *this. */ int NPerm5::orderedS5Index() const { return 24*imageOf(0) + 6*( imageOf(1)-( (imageOf(1) > imageOf(0)) ? 1 : 0) ) + 2*( imageOf(2)-( ( (imageOf(2) > imageOf(1)) ? 1 : 0) + ( (imageOf(2) > imageOf(0)) ? 1 : 0) ) ) + ( (imageOf(3) > imageOf(4)) ? 1 : 0 ); } /** * Returns the number n such that NPerm5::S5[n] == *this. */ int NPerm5::S5Index() const { // S5 is almost the same as orderedS5, except that some pairs // S5[2i] <--> S5[2i+1] have been swapped to ensure that all // permutations S5[2i] are even and all permutations S5[2i+1] are odd. int retval = orderedS5Index(); // Flip between 2i <--> 2i+1 if and only if // one but not both of (retval / 2) and (retval / 24) is even. // Here we use (retval >> 1), which is equivalent to (retval / 2). if (((retval >> 1) ^ (retval / 24)) & 1) retval ^= 1; return retval; } } // namespace regina regina-4.96/engine/maths/nperm5.h000644 000765 000024 00000054671 12377775273 016611 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file maths/nperm5.h * \brief Deals with permutations of {0,1,2,3,4}. */ #ifndef __NPERM5_H #ifndef __DOXYGEN #define __NPERM5_H #endif #include #include "regina-core.h" namespace regina { /** * \weakgroup maths * @{ */ /** * Represents a permutation of {0,1,2,3,4}. * Amongst other things, such permutations are used in describing * simplex gluings in 4-manifold triangulations. NPerm5 objects are small * enough to pass about by value instead of by reference. * * Each permutation has an internal code, and this code is sufficient to * reconstruct the permutation. * Thus the internal code may be a useful means for passing * permutation objects to and from the engine. * * The internal code is an unsigned integer. The lowest three bits represent * the image of 0, the next lowest three bits represent the image of 1 and so * on. */ class REGINA_API NPerm5 { public: /** * Contains all possible permutations of five elements. * * The permutations with even indices in the array are the even * permutations, and those with odd indices in the array are the * odd permutations. * * Note that the permutations are not necessarily in * lexicographical order. */ static const NPerm5 S5[120]; /** * A dimension-agnostic alias for NPerm5::S5. In general, for * each \a K the class NPermK will define an alias \a Sn * that references the list of all permutations NPermK::SK. */ static const NPerm5* Sn; /** * Contains all possible permutations of five elements in * lexicographical order. */ static const NPerm5 orderedS5[120]; /** * A dimension-agnostic alias for NPerm5::orderedS5. In general, for * each \a K the class NPermK will define an alias \a orderedSn * that references the list of all permutations NPermK::orderedSK. */ static const NPerm5* orderedSn; /** * Contains the inverses of the permutations in the array \a S5. * * Specifically, the inverse of permutation S5[i] is * the permutation S5[ invS5[i] ]. */ static const unsigned invS5[120]; /** * A dimension-agnostic alias for NPerm5::invS5. In general, for * each \a K the class NPermK will define an alias \a invSn * that references the list of all permutations NPermK::invSK. */ static const unsigned* invSn; /** * Contains all possible permutations of four elements. * In each permutation, 4 maps to 4. * * The permutations with even indices in the array are the even * permutations, and those with odd indices in the array are the * odd permutations. * * For all permutation classes (NPerm4, NPerm5 and so on), the * S4 array stores the same permutations in the same order (but * of course using different data types). * * Note that the permutations are not necessarily in * lexicographical order. For the corresponding inverse array, * see NPerm4::invS4. */ static const NPerm5 S4[24]; /** * A dimension-agnostic alias for NPerm5::S4. In general, for * each \a K the class NPermK will define an alias \a Sn_1 * that references the list of all permutations NPermK::S(K-1). */ static const NPerm5* Sn_1; /** * Contains all possible permutations of four elements in * lexicographical order. In each permutation, 4 maps to 4. */ static const NPerm5 orderedS4[24]; /** * Contains all possible permutations of three elements. * In each permutation, 3 maps to 3 and 4 maps to 4. * * The permutations with even indices in the array are the even * permutations, and those with odd indices in the array are the * odd permutations. * * For all permutation classes (NPerm4, NPerm5 and so on), the * S3 array stores the same permutations in the same order (but * of course using different data types). * * Note that the permutations are not necessarily in * lexicographical order. For the corresponding inverse array, * see NPerm3::invS3. */ static const NPerm5 S3[6]; /** * Contains all possible permutations of three elements in * lexicographical order. In each permutation, 3 maps to 3 and * 4 maps to 4. */ static const NPerm5 orderedS3[6]; /** * Contains all possible permutations of two elements. * In each permutation, 2 maps to 2, 3 maps to 3, and 4 maps to 4. * * The permutations with even indices in the array are the even * permutations, and those with odd indices in the array are the * odd permutations. * * For all permutation classes (NPerm4, NPerm5 and so on), the * S2 array stores the same permutations in the same order (but * of course using different data types). * * Note that these permutations are already in lexicographical order. */ static const NPerm5 S2[2]; enum { /** * The total number of permutations on five elements. * This is the size of the array Sn. * * \ifacespython Not present. */ nPerms = 120, /** * The total number of permutations on four elements. * This is the size of the array Sn_1. * * \ifacespython Not present. */ nPerms_1 = 24 }; private: unsigned code; /**< The internal code representing this permutation. */ public: /** * Creates the identity permutation. */ NPerm5(); /** * Creates the transposition of \a a and \a b. * Note that \a a and \a b need not be distinct. * * \pre \a a and \a b are in {0,1,2,3,4}. * * @param a the element to switch with \a b. * @param b the element to switch with \a a. */ NPerm5(int a, int b); /** * Creates a permutation mapping (0,1,2,3,4) to * (a,b,c,d,e) respectively. * * \pre {a,b,c,d,e} = {0,1,2,3,4}. * * @param a the desired image of 0. * @param b the desired image of 1. * @param c the desired image of 2. * @param d the desired image of 3. * @param e the desired image of 4. */ NPerm5(int a, int b, int c, int d, int e); /** * Creates a permutation mapping \a i to \a image[i] for each * \a i = 0,1,2,3,4. * * \pre The array \a image contains five elements, which are * 0, 1, 2, 3 and 4 in some order. * * \ifacespython Not present. * * @param image the array of images. */ NPerm5(const int* image); /** * Creates a permutation mapping * (a0,b0,c0,d0,e0) to * (a1,b1,c1,d1,e1) respectively. * * \pre {a0,b0,c0,d0,e0} = * {a1,b1,c1,d1,e1} = * {0,1,2,3,4}. * * @param a0 the desired preimage of a1. * @param b0 the desired preimage of b1. * @param c0 the desired preimage of c1. * @param d0 the desired preimage of d1. * @param e0 the desired preimage of e1. * @param a1 the desired image of a0. * @param b1 the desired image of b0. * @param c1 the desired image of c0. * @param d1 the desired image of d0. * @param e1 the desired image of e0. */ NPerm5(int a0, int a1, int b0, int b1, int c0, int c1, int d0, int d1, int e0, int e1); /** * Creates a permutation that is a clone of the given * permutation. * * @param cloneMe the permutation to clone. */ NPerm5(const NPerm5& cloneMe); /** * Returns the internal code representing this permutation. * Note that the internal code is sufficient to reproduce the * entire permutation. * * The code returned will be a valid permutation code as * determined by isPermCode(). * * @return the internal code. */ unsigned getPermCode() const; /** * Sets this permutation to that represented by the given * internal code. * * \pre the given code is a valid permutation code; see * isPermCode() for details. * * @param newCode the internal code that will determine the * new value of this permutation. */ void setPermCode(unsigned newCode); /** * Creates a permutation from the given internal code. * * \pre the given code is a valid permutation code; see * isPermCode() for details. * * @param newCode the internal code for the new permutation. * @return the permutation reprsented by the given internal code. */ static NPerm5 fromPermCode(unsigned newCode); /** * Determines whether the given integer is a valid internal * permutation code. Valid permutation codes can be passed to * setPermCode() or fromPermCode(), and are returned by getPermCode(). * * @return \c true if and only if the given code is a valid * internal permutation code. */ static bool isPermCode(unsigned newCode); /** * Sets this permutation to be equal to the given permutation. * * @param cloneMe the permutation whose value will be assigned * to this permutation. * @return a reference to this permutation. */ NPerm5& operator = (const NPerm5& cloneMe); /** * Returns the composition of this permutation with the given * permutation. If this permutation is p, the * resulting permutation will be p o q, satisfying * (p*q)[x] == p[q[x]]. * * @param q the permutation with which to compose this. * @return the composition of both permutations. */ NPerm5 operator * (const NPerm5& q) const; /** * Finds the inverse of this permutation. * * @return the inverse of this permutation. */ NPerm5 inverse() const; /** * Determines the sign of this permutation. * * @return 1 if this permutation is even, or -1 if this * permutation is odd. */ int sign() const; /** * Determines the image of the given integer under this * permutation. * * @param source the integer whose image we wish to find. This * should be between 0 and 4 inclusive. * @return the image of \a source. */ int operator[](int source) const; /** * Determines the preimage of the given integer under this * permutation. * * @param image the integer whose preimage we wish to find. This * should be between 0 and 4 inclusive. * @return the preimage of \a image. */ int preImageOf(int image) const; /** * Determines if this is equal to the given permutation. * This is true if and only if both permutations have the same * images for 0, 1, 2, 3 and 4. * * @param other the permutation with which to compare this. * @return \c true if and only if this and the given permutation * are equal. */ bool operator == (const NPerm5& other) const; /** * Determines if this differs from the given permutation. * This is true if and only if the two permutations have * different images for at least one of 0, 1, 2, 3 or 4. * * @param other the permutation with which to compare this. * @return \c true if and only if this and the given permutation * differ. */ bool operator != (const NPerm5& other) const; /** * Lexicographically compares the images of (0,1,2,3,4) under this * and the given permutation. * * @param other the permutation with which to compare this. * @return -1 if this permutation produces a smaller image, 0 if * the permutations are equal and 1 if this permutation produces * a greater image. */ int compareWith(const NPerm5& other) const; /** * Determines if this is the identity permutation. * This is true if and only if each of 0, 1, 2, 3 and 4 is * mapped to itself. * * @return \c true if and only if this is the identity * permutation. */ bool isIdentity() const; /** * A deprecated alias for str(), which returns a string representation * of this permutation. * * \deprecated This routine has (at long last) been deprecated; * use the simpler-to-type str() instead. * * @return a string representation of this permutation. */ std::string toString() const; /** * Returns a string representation of this permutation. * The representation will consist of five adjacent digits * representing the images of 0, 1, 2, 3 and 4 respectively. * An example of a string representation is 30421. * * @return a string representation of this permutation. */ std::string str() const; /** * Returns a string representation of this permutation with only * the images of 0 and 1. The resulting string will therefore * have length two. * * @return a truncated string representation of this permutation. */ std::string trunc2() const; /** * Returns a string representation of this permutation with only * the images of 0, 1 and 2. The resulting string will therefore * have length three. * * @return a truncated string representation of this permutation. */ std::string trunc3() const; /** * Returns a string representation of this permutation with only * the images of 0, 1, 2 and 3. The resulting string will therefore * have length four. * * @return a truncated string representation of this permutation. */ std::string trunc4() const; /** * Returns the index of this permutation in the NPerm5::S5 array. * * @return the index \a i for which this permutation is equal to * NPerm5::S5[i]. This will be between 0 and 119 inclusive. * * @author Ryan Budney */ int S5Index() const; /** * Returns the index of this permutation in the NPerm5::S5 array. * This is a dimension-agnostic alias for S5Index(). * * @return the index \a i for which this permutation is equal to * NPerm5::S5[i]. This will be between 0 and 119 inclusive. */ int SnIndex() const; /** * Returns the index of this permutation in the NPerm5::orderedS5 array. * * @return the index \a i for which this permutation is equal to * NPerm5::orderedS5[i]. This will be between 0 and 119 inclusive. * * @author Ryan Budney */ int orderedS5Index() const; /** * Returns the index of this permutation in the NPerm5::orderedS5 array. * This is a dimension-agnostic alias for orderedS5Index(). * * @return the index \a i for which this permutation is equal to * NPerm5::orderedS5[i]. This will be between 0 and 119 inclusive. */ int orderedSnIndex() const; private: /** * Creates a permutation from the given internal code. * * \pre the given code is a valid permutation code; see * isPermCode() for details. * * @param newCode the internal code from which the new * permutation will be created. */ NPerm5(unsigned newCode); /** * Determines the image of the given integer under this * permutation. * * @param source the integer whose image we wish to find. This * should be between 0 and 4 inclusive. * @return the image of \a source. */ int imageOf(int source) const; friend std::ostream& operator << (std::ostream& out, const NPerm5& p); }; /** * Writes a string representation of the given permutation to the given * output stream. The format will be the same as is used by * NPerm5::str(). * * @param out the output stream to which to write. * @param p the permutation to write. * @return a reference to \a out. */ inline REGINA_API std::ostream& operator << (std::ostream& out, const NPerm5& p) { return (out << p.str()); } /*@}*/ // Inline functions for NPerm5 inline NPerm5::NPerm5() : code(18056) { } inline NPerm5::NPerm5(unsigned newCode) : code(newCode) { } inline NPerm5::NPerm5(int a, int b) { code = 18056; code += ((a << (3*b)) - (b << (3*b))); code += ((b << (3*a)) - (a << (3*a))); } inline NPerm5::NPerm5(int a, int b, int c, int d, int e) { code = (e << 12) | (d << 9) | (c << 6) | (b << 3) | a; } inline NPerm5::NPerm5(const int* image) { code = (image[4] << 12) | (image[3] << 9) | (image[2] << 6) | (image[1] << 3) | image[0]; } inline NPerm5::NPerm5(int a0, int a1, int b0, int b1, int c0, int c1, int d0, int d1, int e0, int e1) { code = (a1 << (3*a0)) | (b1 << (3*b0)) | (c1 << (3*c0)) | (d1 << (3*d0)) | (e1 << (3*e0)); } inline NPerm5::NPerm5(const NPerm5& cloneMe) : code(cloneMe.code) { } inline unsigned NPerm5::getPermCode() const { return code; } inline void NPerm5::setPermCode(unsigned newCode) { code = newCode; } inline NPerm5 NPerm5::fromPermCode(unsigned newCode) { return NPerm5(newCode); } inline NPerm5& NPerm5::operator = (const NPerm5& cloneMe) { code = cloneMe.code; return *this; } inline NPerm5 NPerm5::operator *(const NPerm5& q) const { return NPerm5(imageOf(q[0]), imageOf(q[1]), imageOf(q[2]), imageOf(q[3]), imageOf(q[4])); } inline NPerm5 NPerm5::inverse() const { // Specify the inverse by its internal code. return NPerm5(static_cast( (1 << (3*imageOf(1))) | (2 << (3*imageOf(2))) | (3 << (3*imageOf(3))) | (4 << (3*imageOf(4))))); } inline int NPerm5::operator[](int source) const { return (code >> (3*source)) & 7; } inline int NPerm5::preImageOf(int image) const { if (( code & 7) == static_cast(image)) return 0; if (((code >> 3) & 7) == static_cast(image)) return 1; if (((code >> 6) & 7) == static_cast(image)) return 2; if (((code >> 9) & 7) == static_cast(image)) return 3; return 4; } inline bool NPerm5::operator == (const NPerm5& other) const { return (code == other.code); } inline bool NPerm5::operator != (const NPerm5& other) const { return (code != other.code); } inline std::string NPerm5::toString() const { return str(); } inline bool NPerm5::isIdentity() const { return (code == 18056); } inline int NPerm5::imageOf(int source) const { return (code >> (3*source)) & 7; } inline int NPerm5::SnIndex() const { return S5Index(); } inline int NPerm5::orderedSnIndex() const { return orderedS5Index(); } } // namespace regina #endif regina-4.96/engine/maths/nprimes.cpp000644 000765 000024 00000015415 12377776627 017410 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "maths/nprimes.h" namespace regina { std::vector NPrimes::largePrimes; NLargeInteger NPrimes::prime(unsigned long which, bool autoGrow) { // Can we grab it straight out of the hard-coded seed list? if (which < numPrimeSeeds) return primeSeedList[which]; // Do we even have the requested prime stored? if (which >= numPrimeSeeds + largePrimes.size()) { if (autoGrow) growPrimeList(which - numPrimeSeeds - largePrimes.size() + 1); else return NLargeInteger::zero; } // Got it. return largePrimes[which - numPrimeSeeds]; } void NPrimes::growPrimeList(unsigned long extras) { NLargeInteger lastPrime = (largePrimes.empty() ? primeSeedList[numPrimeSeeds - 1] : largePrimes[largePrimes.size() - 1]); NLargeInteger newPrime; // Since this is all being done through GMP, just bite the bullet // and make them all GMP integers (not native integers). // This means we can call rawData() with abandon. while (extras) { mpz_nextprime(newPrime.rawData(), lastPrime.rawData()); newPrime.tryReduce(); // since rawData() forced it into GMP format largePrimes.push_back(newPrime); lastPrime = newPrime; extras--; } } std::vector NPrimes::primeDecomp(const NLargeInteger& n) { std::vector retval; // Deal with n=0 first. if (n == NLargeInteger::zero) { retval.push_back(NLargeInteger::zero); return retval; } NLargeInteger temp(n); NLargeInteger r,q; // if the number is negative, put -1 as first factor. if (temp < NLargeInteger::zero) { temp.negate(); retval.push_back(NLargeInteger(-1)); } // repeatedly divide the number by the smallest primes until no // longer divisible. // at present the algorithm is only guaranteed to factorize the integer // into its prime factors if none of them are larger than the 500th smallest // prime. it always produces a factorization, but after the 500th it uses // a probabilistic test to speed things up. This algorithm is at present // ad-hoc since the current usage in Regina rarely demands the // factorization of even a 4-digit number. unsigned long cpi=0; // current prime index. unsigned long iterSinceDivision=0; // keeps track of how many iterations // since the last successful division while ( temp != NLargeInteger::one ) { // now cpi > NPrimes::primePowerDecomp(const NLargeInteger& n) { std::vector list1(primeDecomp(n)); std::vector< std::pair > retlist; // go through list1, record number of each prime, put in retlist. if (! list1.empty()) { NLargeInteger cp(list1.front()); // current prime unsigned long cc(1); // current count std::vector::const_iterator it = list1.begin(); for (++it; it != list1.end(); ++it) { if (*it == cp) cc++; else { // a new prime is coming up. retlist.push_back(std::make_pair( cp, cc ) ); cp = *it; cc = 1; } } retlist.push_back(std::make_pair( cp, cc ) ); } return retlist; } } // namespace regina regina-4.96/engine/maths/nprimes.h000644 000765 000024 00000030447 12377775300 017042 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #ifndef __NPRIMES_H #ifndef __DOXYGEN #define __NPRIMES_H #endif /*! \file maths/nprimes.h * \brief Support for finding primes and factorising integers. */ #include "regina-core.h" #include "maths/ninteger.h" #include namespace regina { /** * \weakgroup maths * @{ */ /** * A helper class for finding primes and factorising integers. * * This class has two functions: (i) to maintain a list of known primes, * and (ii) to use this list to factorise integers into prime factors. * * The primes stored by this class will always be the smallest \a k * suspected primes, where \a k may grow dynamically as the program runs. * Specifically: * * - An initial hard-coded list of seed primes is loaded into the class on * startup. This list contains precisely the smallest 10,000 primes (the * size of this list is subject to change in future versions of Regina). * * - Whenever a prime beyond the known list is requested (e.g., when a * number greater than the largest stored prime is to be factorised), the * list is extended on the fly. The extension uses the probabilistic * algorithm shipped with GMP (hence the phrase "suspected primes" above); * regarding this algorithm, the GMP documentation states that "for * practical purposes it's adequate, the chance of a composite passing * will be extremely small." * * This list is used by the high-level factorisation routines in this * class, such as primeDecomp() and primePowerDecomp(). For users only * interested in these high-level routines, there is no need to worry * about the size of the list; the high-level routines will extend it if * necessary. * * @author Ryan Budney, B.B. */ class REGINA_API NPrimes { private: static const unsigned long numPrimeSeeds; /**< The size of the hard-coded list of seed primes. */ static const unsigned long primeSeedList[]; /**< The full hard-coded list of seed primes. */ static std::vector largePrimes; /**< Primes (or suspected primes) that have been found thus far, not including the initial seed primes. This list begins empty, and is expanded as required throughout the life of the program. */ public: /** * Returns the number of primes (or suspected primes) currently * stored. * * Primes that are already stored can be accessed instantly; * primes larger than those currently stored must be generated * on the fly (which takes time). * * This number may increase as the program runs (according to * whether larger primes are requested), but it will never * decrease. * * @return the number of primes or suspected primes currently stored. */ static unsigned long size(); /** * Returns the requested prime (or suspected prime). More * specifically, this routine returns the (\a which + 1)th * smallest prime. Thus prime(0) returns 2, prime(1) returns 3, * prime(2) returns 5, and so on. * * If \a which is smaller than the number of initial seed primes, * the result is guaranteed to be the (\a which + 1)th smallest * prime (see the NPrimes class notes for the size of the initial * seed list). If \a which is larger, a probabilistic algorithm * is used and so there is a possibility that non-primes are * included in the list. * * If \a which < size() then this routine is essentially * instantaneous, since the (\a which + 1)th smallest (suspected) * prime is already stored. Otherwise the behaviour depends on * the argument \a autoGrow. If \a autoGrow is \c true (the * default) then this routine calculates the requested prime, * which might take some time. If \a autoGrow is \c false then * this routine returns zero. * * @param which indicates which prime is requested. * @param autoGrow specifies what to do if the requested * prime lies beyond the list currently stored (see above). * @return the requested prime (or suspected prime), or zero if * \a which was too large and \a autoGrow was \c false. */ static NLargeInteger prime(unsigned long which, bool autoGrow = true); /** * Returns the prime factorisation of the given integer as a list * of individual primes (or suspected primes). * * Prime factors are returned in increasing order. Where * a prime power appears in the factorisation, the relevant * prime will appear several times in the list. * * For very large integers, the factorisation becomes * probabilistic: (i) this routine examines suspected primes * instead of primes (see the class notes), and (ii) if the * routine is having trouble finding factors then it will run a * probabilistic prime test on whatever portion of \a n still * remains (and will assume that portion to be prime if the test * passes). * * The given integer may be negative, in which case -1 will be * listed as the first factor (even though -1 is not prime). * If 0 is passed then a single factor of 0 will be returned; * if 1 is passed then an empty list will be returned. * In all cases, the given integer \a n will be the product of * all elements of the final list (where an empty product is * assumed to be 1). * * As an example, the prime factors of 54 will be listed as * (2, 3, 3, 3), and the prime factors of -90 will be listed as * (-1, 2, 3, 3, 5). * * Note that the internal list of known primes and suspected * primes will be expanded as necessary; there is no need for * the caller to manage this list manually. * * \todo \opt Add a version that does not return the factors by value. * * \ifacespython In addition to this routine, the routine * primeDecompInt() is also available. The routine * primeDecompInt() behaves identically to this routine except * that the (i) return values are of ordinary integer type, not * NLargeInteger; (ii) the input value \a n must lie within * the C++ long integer range (otherwise the behaviour is undefined). * * @param n the integer to factorise. * @return the list of prime factors as described above. */ static std::vector primeDecomp(const NLargeInteger& n); /** * Returns the prime factorisation of the given integer as a * list of prime powers (or suspected prime powers). * * Factors are returned as (prime, exponent) pairs. Different * pairs describe different primes, and the pairs are sorted * in order from smallest prime to largest. All exponents are * strictly positive. * * For very large integers, the factorisation becomes * probabilistic: (i) this routine examines suspected primes * instead of primes (see the class notes), and (ii) if the * routine is having trouble finding factors then it will run a * probabilistic prime test on whatever portion of \a n still * remains (and will assume that portion to be prime if the test * passes). * * The given integer may be negative, in which case (-1,1) will * be listed as the first prime power (even though -1 is not prime). * If 0 is passed then a single pair (0,1) will be returned; * if 1 is passed then an empty list will be returned. * In all cases, the given integer \a n will be the product of * all powers described by the final list (where an empty product * is assumed to be 1). * * As an example, the factorisation of 54 will be reported as * [(2,1) (3,3)], and the factorisation of -90 will be reported * as [(-1,1) (2,1) (3,2) (5,1)]. * * Note that the internal list of known primes and suspected * primes will be expanded as necessary; there is no need for * the caller to manage this list manually. * * The current implementation of this routine merely calls * primeDecomp() and rewrites the list of factors by grouping primes. * * \todo \opt Implement this routine natively to avoid the overhead * of the temporary primeDecomp() vector. * * \todo \opt Add a version that does not return the factors by value. * * \ifacespython In addition to this routine, the routine * primePowerDecompInt() is also available. The routine * primePowerDecompInt() behaves identically to this routine except * that the (i) return values are of ordinary integer type, not * NLargeInteger; (ii) the input value \a n must lie within * the C++ long integer range (otherwise the behaviour is undefined). * * @param n the integer to factorise. * @return the list of prime power factors as described above. */ static std::vector > primePowerDecomp(const NLargeInteger& n); private: /** * Private constructor. No instance of this class is allowed, * since everything of interest is static. */ NPrimes(); /** * Adds the given number of primes (or suspected primes) to the * list already stored. * * @param extras the number of additional suspected primes to * calculate. */ static void growPrimeList(unsigned long extras = 1); }; /*@}*/ // Inline functions for NPrimes inline NPrimes::NPrimes() { } inline unsigned long NPrimes::size() { return numPrimeSeeds + largePrimes.size(); } } // namespace regina #endif regina-4.96/engine/maths/nrational.cpp000644 000765 000024 00000026514 12377776630 017716 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "maths/nrational.h" #include #include namespace regina { const NRational NRational::zero; const NRational NRational::one(1); const NRational NRational::infinity(1, 0); const NRational NRational::undefined(0, 0); // These two constants are initialised to their intended values in // initDoubleBounds(). const NRational NRational::maxDouble(0, 0); const NRational NRational::minDouble(0, 0); NRational::NRational(long newNum, unsigned long newDen) { mpq_init(data); if (newDen == 0) { if (newNum == 0) flavour = f_undefined; else flavour = f_infinity; } else { flavour = f_normal; mpq_set_si(data, newNum, newDen); } } NInteger NRational::getNumerator() const { if (flavour == f_infinity) return NInteger::one; else if (flavour == f_undefined) return NInteger::zero; NInteger ans; ans.setRaw(mpq_numref(data)); return ans; } NInteger NRational::getDenominator() const { if (flavour != f_normal) return NInteger::zero; NInteger ans; ans.setRaw(mpq_denref(data)); return ans; } NRational NRational::operator *(const NRational& r) const { if (flavour == f_undefined || r.flavour == f_undefined) return undefined; if (flavour == f_infinity) { if (r == zero) return undefined; return infinity; } if (r.flavour == f_infinity) { if (*this == zero) return undefined; return infinity; } NRational ans; mpq_mul(ans.data, data, r.data); return ans; } NRational NRational::operator /(const NRational& r) const { if (flavour == f_undefined || r.flavour == f_undefined) return undefined; if (flavour == f_infinity) { if (r.flavour == f_infinity) return undefined; return infinity; } if (r.flavour == f_infinity) return zero; if (r == zero) { if (*this == zero) return undefined; return infinity; } NRational ans; mpq_div(ans.data, data, r.data); return ans; } NRational NRational::operator +(const NRational& r) const { if (flavour == f_undefined || r.flavour == f_undefined) return undefined; if (flavour == f_infinity || r.flavour == f_infinity) return infinity; NRational ans; mpq_add(ans.data, data, r.data); return ans; } NRational NRational::operator -(const NRational& r) const { if (flavour == f_undefined || r.flavour == f_undefined) return undefined; if (flavour == f_infinity || r.flavour == f_infinity) return infinity; NRational ans; mpq_sub(ans.data, data, r.data); return ans; } NRational NRational::operator - () const { if (flavour != f_normal) return *this; NRational ans; mpq_neg(ans.data, data); return ans; } NRational NRational::inverse() const { if (flavour == f_undefined) return undefined; if (flavour == f_infinity) return zero; if (*this == zero) return infinity; NRational ans; mpq_inv(ans.data, data); return ans; } NRational NRational::abs() const { if (flavour != f_normal || mpq_cmp(data, zero.data) >= 0) return *this; NRational ans; mpq_neg(ans.data, data); return ans; } NRational& NRational::operator += (const NRational& other) { if (flavour == f_undefined || other.flavour == f_undefined) flavour = f_undefined; else if (flavour == f_infinity || other.flavour == f_infinity) flavour = f_infinity; else mpq_add(data, data, other.data); return *this; } NRational& NRational::operator -= (const NRational& other) { if (flavour == f_undefined || other.flavour == f_undefined) flavour = f_undefined; else if (flavour == f_infinity || other.flavour == f_infinity) flavour = f_infinity; else mpq_sub(data, data, other.data); return *this; } NRational& NRational::operator *= (const NRational& other) { if (flavour == f_undefined || other.flavour == f_undefined) flavour = f_undefined; else if (flavour == f_infinity) { if (other == zero) flavour = f_undefined; else flavour = f_infinity; } else if (other.flavour == f_infinity) { if (*this == zero) flavour = f_undefined; else flavour = f_infinity; } else mpq_mul(data, data, other.data); return *this; } NRational& NRational::operator /= (const NRational& other) { if (flavour == f_undefined || other.flavour == f_undefined) flavour = f_undefined; else if (flavour == f_infinity) { if (other.flavour == f_infinity) flavour = f_undefined; else flavour = f_infinity; } else if (other.flavour == f_infinity) mpq_set(data, zero.data); else if (other == zero) { if (*this == zero) flavour = f_undefined; else flavour = f_infinity; } else mpq_div(data, data, other.data); return *this; } void NRational::invert() { if (flavour == f_undefined) return; else if (flavour == f_infinity) { flavour = f_normal; mpq_set(data, zero.data); } else if (*this == zero) { flavour = f_infinity; } else mpq_inv(data, data); } bool NRational::operator == (const NRational& compare) const { if (flavour != compare.flavour) return false; if (flavour != f_normal) return true; return mpq_equal(data, compare.data); } bool NRational::operator < (const NRational& compare) const { if (flavour == f_infinity || compare.flavour == f_undefined) return false; if (flavour == f_undefined || compare.flavour == f_infinity) return (compare.flavour != flavour); return (mpq_cmp(data, compare.data) < 0); } bool NRational::operator > (const NRational& compare) const { if (flavour == f_undefined || compare.flavour == f_infinity) return false; if (flavour == f_infinity || compare.flavour == f_undefined) return (compare.flavour != flavour); return (mpq_cmp(data, compare.data) > 0); } std::ostream& operator << (std::ostream& out, const NRational& rat) { if (rat.flavour == NRational::f_infinity) out << "Inf"; else if (rat.flavour == NRational::f_undefined) out << "Undef"; else if (rat.getDenominator() == 1) out << rat.getNumerator(); else out << rat.getNumerator() << '/' << rat.getDenominator(); return out; } std::string NRational::getTeX() const { std::ostringstream out; writeTeX(out); return out.str(); } std::ostream& NRational::writeTeX(std::ostream &out) const { if (flavour == NRational::f_infinity) out << "\\infty"; else if (flavour == NRational::f_undefined) out << "0/0"; else if (getDenominator() == 1) out << getNumerator(); else out << "\\frac{" << getNumerator() << "}{" << getDenominator() << "}"; return out; } double NRational::doubleApprox(bool* inRange) const { // Initialise maxDouble and minDouble if this has not already been done. // Do this even if the current doubleApprox() call is trivial, since we // promise this initialisation on the very first call to doubleApprox(). if (maxDouble.flavour == f_undefined) initDoubleBounds(); // Trivial cases. if (flavour == NRational::f_infinity || flavour == NRational::f_undefined) { if (inRange) *inRange = false; return 0.0; } // Treat zero separately so that "abs < minDouble" is meaningful later on. if (*this == zero) { if (inRange) *inRange = true; return 0.0; } // In bounds or out of bounds? NRational magnitude = this->abs(); if (magnitude < minDouble || magnitude > maxDouble) { if (inRange) *inRange = false; return 0.0; } // The rational is in range. Use GMP's native conversion routines, // since GMP knows best. if (inRange) *inRange = true; return mpq_get_d(data); } void NRational::initDoubleBounds() { // The largest and smallest possible (positive) doubles should be: // FLT_RADIX ^ DBL_MAX_EXP (minus a small amount) // FLT_RADIX ^ (DBL_MIN_EXP - 1) // // However, I have also seen the following crop up in some places: // FLT_RADIX ^ (DBL_MAX_EXP + 1) (minus a small amount) // FLT_RADIX ^ DBL_MIN_EXP // // Best to be conservative here and choose the weaker in each case: // FLT_RADIX ^ DBL_MAX_EXP (minus a small amount) // FLT_RADIX ^ DBL_MIN_EXP // // In fact, we'll be even more conservative and divide by an extra // factor of FLT_RADIX to account for "minus a small amount". NInteger maxNum = FLT_RADIX; maxNum.raiseToPower(DBL_MAX_EXP - 1); NInteger minNum = FLT_RADIX; minNum.raiseToPower(- DBL_MIN_EXP); // Cast away constness so we can actually change these variables. const_cast(maxDouble) = NRational(maxNum, NInteger(1)); const_cast(minDouble) = NRational(NInteger(1), minNum); } } // namespace regina regina-4.96/engine/maths/nrational.h000644 000765 000024 00000053070 12377775302 017353 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #ifndef __NRATIONAL_H #ifndef __DOXYGEN #define __NRATIONAL_H #endif /*! \file maths/nrational.h * \brief Deals with artibrary precision rational numbers. */ #include "regina-core.h" #include "maths/ninteger.h" namespace regina { /** * \weakgroup maths * @{ */ /** * Represents an arbitrary precision rational number. * Calculations with NRational objects will be exact. * * Infinity (1/0) and undefined (0/0) are catered for. (-1/0) is considered * the same as (1/0), and is represented as (1/0). * Any operation involving (0/0) will return (0/0). * * Since infinity is the same as negative infinity, both infinity plus * infinity and infinity minus infinity will return infinity. Infinity * divided by infinity returns undefined, as does infinity times zero. * * For the purposes of ordering, undefined is the smallest rational and * infinity is the largest. Undefined is always equal to itself, and * infinity is always equal to itself. * * Rationals will always be stored in lowest terms (i.e., with relatively * prime numerator and denominator), and with a non-negative denominator. */ class REGINA_API NRational { public: static const NRational zero; /**< Globally available zero. */ static const NRational one; /**< Globally available one. */ static const NRational infinity; /**< Globally available infinity. Note that both 1/0 and * -1/0 evaluate to this same rational. When queried, * the representation 1/0 will be returned. */ static const NRational undefined; /**< Globally available undefined. This is represented as * 0/0. */ private: /** * Represents the available flavours of rational number. */ enum flavourType { f_infinity, /**< Infinity; there is only one rational of this type. */ f_undefined, /**< Undefined; there is only one rational of this type. */ f_normal /**< An ordinary rational (the denominator is non-zero). */ }; flavourType flavour; /**< Stores whether this rational is infinity, undefined or * normal (non-zero denominator). */ mpq_t data; /**< Contains the arbitrary precision rational data for normal * (non-zero denominator) rationals. * This is initialised even if the rational is infinite. */ static const NRational maxDouble; /**< The largest positive rational number that can be converted * to a finite double. This begins as undefined, and is set * to its correct value on the first call to doubleApprox(). */ static const NRational minDouble; /**< The smallest positive rational number that can be converted * to a non-zero double. This begins as undefined, and is set * to its correct value on the first call to doubleApprox(). */ public: /** * Initialises to 0/1. */ NRational(); /** * Initialises to the given rational value. * * @param value the new rational value of this rational. */ NRational(const NRational& value); /** * Initialises to the given integer value. * The given integer may be infinite. * * @param value the new integer value of this rational. */ template NRational(const NIntegerBase& value); /** * Initialises to the given integer value. * * @param value the new integer value of this rational. */ NRational(long value); /** * Initialises to newNum/newDen. * * \pre gcd(newNum, newDen) = 1 or newDen = 0. * \pre \a newDen is non-negative. * * \warning Failing to meet the preconditions above can result * in misleading or even undefined behaviour. As an example, * NRational(4,4) (which breaks the gcd requirement) is * considered different from NRational(1,1) (a valid rational), * which is different again from NRational(-1,-1) (which breaks * the non-negativity requirement). * * \pre Neither of the given integers is infinite. * * @param newNum the new numerator. * @param newDen the new denominator. */ template NRational(const NIntegerBase& newNum, const NIntegerBase& newDen); /** * Initialises to newNum/newDen. * * \pre gcd(newNum, newDen) = 1 or newDen = 0. * \pre \a newDen is non-negative. * * \warning Failing to meet the preconditions above can result * in misleading or even undefined behaviour. As an example, * NRational(4,4) (which breaks the gcd requirement) is * considered different from NRational(1,1) (a valid rational), * which is different again from NRational(-1,-1) (which breaks * the non-negativity requirement). * * @param newNum the new numerator. * @param newDen the new denominator. */ NRational(long newNum, unsigned long newDen); /** * Destroys this rational. */ virtual ~NRational(); /** * Sets this rational to the given rational value. * * @param value the new value of this rational. * @return a reference to this rational with its new value. */ NRational& operator = (const NRational& value); /** * Sets this rational to the given integer value. * The given integer may be infinite. * * @param value the new value of this rational. * @return a reference to this rational with its new value. */ template NRational& operator = (const NIntegerBase& value); /** * Sets this rational to the given integer value. * * @param value the new value of this rational. * @return a reference to this rational with its new value. */ NRational& operator = (long value); /** * Swaps the values of this and the given rational. * * @param other the rational whose value will be swapped with * this. */ void swap(NRational& other); /** * Returns the numerator of this rational. * Note that rationals are always stored in lowest terms with * non-negative denominator. Infinity will be stored as 1/0. * * @return the numerator. */ NInteger getNumerator() const; /** * Returns the denominator of this rational. * Note that rationals are always stored in lowest terms with * non-negative denominator. Infinity will be stored as 1/0. * * @return the denominator. */ NInteger getDenominator() const; /** * Calculates the product of two rationals. * This rational is not changed. * * @param r the rational with which to multiply this. * @return the product \a this * \a r. */ NRational operator *(const NRational& r) const; /** * Calculates the ratio of two rationals. * This rational is not changed. * * @param r the rational to divide this by. * @return the ratio \a this / \a r. */ NRational operator /(const NRational& r) const; /** * Calculates the sum of two rationals. * This rational is not changed. * * @param r the rational to add to this. * @return the sum \a this + \a r. */ NRational operator +(const NRational& r) const; /** * Calculates the difference of two rationals. * This rational is not changed. * * @param r the rational to subtract from this. * @return the difference \a this - \a r. */ NRational operator -(const NRational& r) const; /** * Determines the negative of this rational. * This rational is not changed. * * @return the negative of this rational. */ NRational operator - () const; /** * Calculates the inverse of this rational. * This rational is not changed. * * @return the inverse 1 / \a this. */ NRational inverse() const; /** * Determines the absolute value of this rational. * This rational is not changed. * * @return the absolute value of this rational. */ NRational abs() const; /** * Adds the given rational to this. * This rational is changed to reflect the result. * * @param other the rational to add to this. * @return a reference to this rational with its new value. */ NRational& operator += (const NRational& other); /** * Subtracts the given rational from this. * This rational is changed to reflect the result. * * @param other the rational to subtract from this. * @return a reference to this rational with its new value. */ NRational& operator -= (const NRational& other); /** * Multiplies the given rational by this. * This rational is changed to reflect the result. * * @param other the rational to multiply by this. * @return a reference to this rational with its new value. */ NRational& operator *= (const NRational& other); /** * Divides this by the given rational. * This rational is changed to reflect the result. * * @param other the rational to divide this by. * @return a reference to this rational with its new value. */ NRational& operator /= (const NRational& other); /** * Negates this rational. * This rational is changed to reflect the result. */ void negate(); /** * Inverts this rational. * This rational is changed to reflect the result. */ void invert(); /** * Determines if this is equal to the given rational. * * @param compare the rational with which this will be compared. * @return \c true if and only if this rational is equal to * \a compare. */ bool operator == (const NRational& compare) const; /** * Determines if this is not equal to the given rational. * * @param compare the rational with which this will be compared. * @return \c true if and only if this rational is not equal to * \a compare. */ bool operator != (const NRational& compare) const; /** * Determines if this is less than the given rational. * * @param compare the rational with which this will be compared. * @return \c true if and only if this rational is less than * \a compare. */ bool operator < (const NRational& compare) const; /** * Determines if this is greater than the given rational. * * @param compare the rational with which this will be compared. * @return \c true if and only if this rational is greater than * \a compare. */ bool operator > (const NRational& compare) const; /** * Determines if this is less than or equal to the given rational. * * @param compare the rational with which this will be compared. * @return \c true if and only if this rational is less than or * equal to \a compare. */ bool operator <= (const NRational& compare) const; /** * Determines if this is greater than or equal to the given rational. * * @param compare the rational with which this will be compared. * @return \c true if and only if this rational is greater than * or equal to \a compare. */ bool operator >= (const NRational& compare) const; /** * Attempts to convert this rational to a real number. * * If this rational can be approximated by a double * (specifically, if it lies within double's allowable range) * then a such an approximation is returned. Otherwise zero is * returned instead. * * The optional \a inRange argument allows the result of range * checking to be returned explicitly as a boolean * (*inRange will be set to \c true if a double * approximation is possible and \c false otherwise). * * It is safe to pass \a inRange as \c null, in which case this * boolean is not returned. Range checking is still performed * internally however, i.e., zero is still returned if the rational * is out of range. * * Note that "lies with double's allowable range" is * machine-dependent, and may vary between different installations. * Infinity and undefined are always considered out of range. * Otherwise a rational is out of range if its absolute value is * finite but too large (e.g., 10^10000) or non-zero but too small * (e.g., 10^-10000). * * @param inRange returns the result of range checking as * described above; this pointer may be passed as \c null if * the caller does not care about this result. * @return the double approximation to this rational, or zero if * this rational lies outside double's allowable range. * * \ifacespython The \a inRange argument is not present. * Instead there are two versions of this routine. * The first is \a doubleApprox(), which returns a single real * number. The second is \a doubleApproxCheck(), which returns * a (real, bool) pair containing the converted real number * followed by the result of range checking. * * @author Ryan Budney, B.B. */ double doubleApprox(bool* inRange = 0) const; /** * Returns this rational as written using TeX formatting. * No leading or trailing dollar signs will be included. * * @return this rational as written using TeX formatting. * * @author Ryan Budney */ std::string getTeX() const; /** * Writes this rational in TeX format to the given output stream. * No leading or trailing dollar signs will be included. * * \ifacespython The parameter \a out does not exist; instead * standard output will be used. * * @param out the output stream to which to write. * @return a reference to the given output stream. * * @author Ryan Budney */ std::ostream& writeTeX(std::ostream& out) const; private: /** * Initialises the class constants \a maxDouble and \a minDouble. * These constants are used by doubleApprox(), and so this routine * is called the first time that doubleApprox() is run. */ static void initDoubleBounds(); friend std::ostream& operator << (std::ostream& out, const NRational& rat); }; /** * Writes the given rational to the given output stream. * Infinity will be written as Inf. Undefined will be written * as Undef. A rational with denominator one will be written * as a single integer. All other rationals will be written in the form * r/s. * * @param out the output stream to which to write. * @param rat the rational to write. * @return a reference to \a out. */ REGINA_API std::ostream& operator << (std::ostream& out, const NRational& rat); /*@}*/ // Inline functions for NRational inline NRational::NRational() : flavour(f_normal) { mpq_init(data); } inline NRational::NRational(const NRational& value) : flavour(value.flavour) { mpq_init(data); if (flavour == f_normal) mpq_set(data, value.data); } template inline NRational::NRational(const NIntegerBase& value) : flavour(f_normal) { mpq_init(data); if (value.isInfinite()) flavour = f_infinity; else if (value.isNative()) mpq_set_si(data, value.longValue(), 1); else mpq_set_z(data, value.rawData()); } inline NRational::NRational(long value) : flavour(f_normal) { mpq_init(data); mpq_set_si(data, value, 1); } template NRational::NRational(const NIntegerBase& newNum, const NIntegerBase& newDen) { mpq_init(data); if (newDen.isZero()) { if (newNum.isZero()) flavour = f_undefined; else flavour = f_infinity; } else { flavour = f_normal; if (newNum.isNative() && newDen.isNative()) mpq_set_si(data, newNum.longValue(), newDen.longValue()); else if (newNum.isNative()) { // Avoid bloating newNum with a GMP representation. NIntegerBase tmp(newNum); mpz_set(mpq_numref(data), tmp.rawData()); mpz_set(mpq_denref(data), newDen.rawData()); } else if (newDen.isNative()) { // Avoid bloating newDen with a GMP representation. NIntegerBase tmp(newDen); mpz_set(mpq_numref(data), newNum.rawData()); mpz_set(mpq_denref(data), tmp.rawData()); } else { mpz_set(mpq_numref(data), newNum.rawData()); mpz_set(mpq_denref(data), newDen.rawData()); } } } inline NRational::~NRational() { mpq_clear(data); } inline NRational& NRational::operator = (const NRational& value) { flavour = value.flavour; if (flavour == f_normal) mpq_set(data, value.data); return *this; } template inline NRational& NRational::operator = ( const NIntegerBase& value) { if (value.isInfinite()) flavour = f_infinity; else if (value.isNative()) { flavour = f_normal; mpq_set_si(data, value.longValue(), 1); } else { flavour = f_normal; mpq_set_z(data, value.rawData()); } return *this; } inline NRational& NRational::operator = (long value) { flavour = f_normal; mpq_set_si(data, value, 1); return *this; } inline void NRational::swap(NRational& other) { std::swap(flavour, other.flavour); mpq_swap(data, other.data); } inline void NRational::negate() { if (flavour == f_normal) mpq_neg(data, data); } inline bool NRational::operator <= (const NRational& compare) const { return ! (*this > compare); } inline bool NRational::operator >= (const NRational& compare) const { return ! (*this < compare); } inline bool NRational::operator != (const NRational& compare) const { return ! (*this == compare); } } // namespace regina #endif regina-4.96/engine/maths/nray.cpp000644 000765 000024 00000005506 12377776631 016677 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "maths/nray.h" namespace regina { void NRay::scaleDown() { NLargeInteger gcd; // Initialised to 0. NLargeInteger* e; for (e = elements; e < end; ++e) { if (e->isInfinite() || (*e) == zero) continue; gcd = gcd.gcd(*e); if (gcd < 0) gcd.negate(); if (gcd == one) return; } if (gcd == zero) return; for (e = elements; e < end; ++e) if ((! e->isInfinite()) && (*e) != zero) { e->divByExact(gcd); e->tryReduce(); } } } // namespace regina regina-4.96/engine/maths/nray.h000644 000765 000024 00000012545 12377775303 016340 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file maths/nray.h * \brief Provides a fast class for rational rays rooted at the origin. */ #ifndef __NRAY_H #ifndef __DOXYGEN #define __NRAY_H #endif #include "regina-core.h" #include "maths/ninteger.h" #include "maths/nvector.h" namespace regina { /** * \weakgroup maths * @{ */ /** * A fast class for storing a ray rooted at the origin whose * coordinates are rational. Such a ray is a half-line beginning at * the origin and is represented by an integer point that it passes through. * Positive scalar multiples of a ray are considered to represent the same ray. * * This class is intended for serious computation, and as a result it * has a streamlined implementation with no virtual methods. It can be * subclassed, but since there are no virtual methods, type information * must generally be known at compile time. Nevertheless, in many respects, * different subclasses of NRay can happily interact with one another. * * \warning As of Regina 4.90, this class merges the old functionality * of NFastRay and NRay from Regina 4.6. Since functions are no longer * virtual, the old clone() method and intersect() function are gone * completely. Instead you can just use the copy constructor and standard * linear operators respectively. * * \ifacespython Not present. */ class REGINA_API NRay : public NVector { public: /** * Creates a new ray all of whose coordinates are initialised to zero. * * @param length the number of elements in the new vector. */ NRay(size_t length); /** * Creates a new ray that is a clone of the given ray. * * @param cloneMe the ray to clone. */ NRay(const NVector& cloneMe); /** * Scales this vector down by the greatest common divisor of all * its elements. The resulting vector will be the smallest * multiple of the original that maintains integral entries, and * these entries will have the same signs as the originals. * * This routine thus reduces a ray to its smallest possible * representation. * * This routine poses no problem for vectors containing infinite * elements; such elements are simply ignored and left at * infinity. */ void scaleDown(); /** * Negates every element of this vector. * * This is an optimised implementation that overrides * NVector::negate(). */ inline void negate(); }; /*@}*/ // Inline functions for NRay inline NRay::NRay(size_t length) : NVector(length) { // Don't bother passing zero to the parent constructor, since the // default NLargeInteger constructor already sets elements to zero. } inline NRay::NRay(const NVector& cloneMe) : NVector(cloneMe) { } inline void NRay::negate() { // Slightly more efficient than the default implementation. for (NLargeInteger* e = elements; e < end; ++e) e->negate(); } } // namespace regina #endif regina-4.96/engine/maths/numbertheory.cpp000644 000765 000024 00000015675 12377776631 020461 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include "maths/numbertheory.h" #include "utilities/stlutils.h" namespace regina { long reducedMod(long k, long modBase) { long ans = k % modBase; if (ans < 0) { if ((ans + modBase) <= (-ans)) return (ans + modBase); } else if (-(ans - modBase) < ans) return (ans - modBase); return ans; } long gcd(long a, long b) { long tmp; while (a != b && b != 0) { tmp = a; a = b; b = tmp % b; } return (a >= 0 ? a : -a); } namespace { long gcdWithCoeffsInternal(long a, long b, long& u, long& v) { // This routine assumes a and b to be non-negative. long a_orig = a; long b_orig = b; u = 1; v = 0; long uu = 0; long vv = 1; long tmp1, tmp2, q; while (a != b && b != 0) { // At each stage: // u*(a_orig) + v*(b_orig) = a_curr; // uu*(a_orig) + vv*(b_orig) = b_curr. tmp1 = u; tmp2 = v; u = uu; v = vv; q = a / b; uu = tmp1 - (q * uu); vv = tmp2 - (q * vv); tmp1 = a; a = b; b = tmp1 % b; } // a is now our gcd. // Put u and v in the correct range. if (b_orig == 0) return a; // We are allowed to add (b_orig/d, -a_orig/d) to (u,v). a_orig = -(a_orig / a); b_orig = b_orig / a; // Now we are allowed to add (b_orig, a_orig), where b_orig >= 0. // Add enough copies to put u between 1 and b_orig inclusive. long k; if (u > 0) k = -((u-1) / b_orig); else k = (b_orig-u) / b_orig; if (k) { u += k * b_orig; v += k * a_orig; } return a; } } long gcdWithCoeffs(long a, long b, long& u, long& v) { long signA = (a > 0 ? 1 : a == 0 ? 0 : -1); long signB = (b > 0 ? 1 : b == 0 ? 0 : -1); long ans = gcdWithCoeffsInternal(a >= 0 ? a : -a, b >= 0 ? b : -b, u, v); u *= signA; v *= signB; return ans; } long lcm(long a, long b) { if (a == 0 || b == 0) return 0; long tmp = regina::gcd(a, b); tmp = (a / tmp) * b; return (tmp >= 0 ? tmp : -tmp); } unsigned long modularInverse(unsigned long n, unsigned long k) { if (n == 1) return 0; long u, v; gcdWithCoeffs(n, k % n, u, v); // GCD should equal 1, so u*n + k*v = 1. // Inverse is v; note that -n < v <= 0. // Since n >= 2 now and (n,k) = 1, we know v != 0. return v + n; } namespace { /** * Finds the smallest prime factor of the given odd integer. * You may specify a known lower bound for this smallest prime factor. * If the given integer is prime, 0 is returned. * * \pre \a n is odd. * \pre The smallest prime factor of \a n is known to * be at least as large as (and possibly equal to) \a lowerBound. * \pre \a lowerBound is odd. * * @param n the integer whose smallest prime factor we wish to find. * @param lowerBound a known lower bound for this smallest prime factor. * @return the smallest prime factor of \a n, or 0 if \a n is prime. */ unsigned long smallestPrimeFactor(unsigned long n, unsigned long lowerBound = 1) { while (lowerBound * lowerBound <= n) { if (n % lowerBound == 0) return lowerBound; lowerBound += 2; } return 0; } } void factorise(unsigned long n, std::list& factors) { // n > 0 is a precondition, but the effects are too unpleasant if // it's broken (infinite memory consumption). if (n == 0) return; // First take out all factors of 2. while (n % 2 == 0) { n = n / 2; factors.push_back(2); } // Run through finding smallest factors. unsigned long factor = 3; while ((factor = smallestPrimeFactor(n, factor))) { factors.push_back(factor); n = n / factor; } // Anything left is prime. if (n > 1) factors.push_back(n); } void primesUpTo(const NLargeInteger& roof, std::list& primes) { // First check 2. if (roof < 2) return; primes.push_back(NLargeInteger(2)); // Run through the rest. NLargeInteger current(3); while (current <= roof) { // Is current prime? if (find_if(primes.begin(), primes.end(), regina::stl::compose1( bind2nd(std::equal_to(), NLargeInteger::zero), bind1st(std::modulus(), current))) == primes.end()) primes.push_back(current); current += 2; } } } // namespace regina regina-4.96/engine/maths/numbertheory.h000644 000765 000024 00000017300 12377775305 020106 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #ifndef __NUMBERTHEORY_H #ifndef __DOXYGEN #define __NUMBERTHEORY_H #endif /*! \file maths/numbertheory.h * \brief Provides miscellaneous number theory routines. */ #include #include "regina-core.h" #include "maths/ninteger.h" namespace regina { /** * \addtogroup maths Mathematical Support * Underlying mathematical gruntwork. * @{ */ /** * Reduces \a k modulo \a modBase to give the smallest possible * absolute value. For instance, reducedMod(4,10) = 4 but * reducedMod(6,10) = -4. In the case of a tie, the positive * solution is taken. * * \pre \a modBase is strictly positive. * * @param k the number to reduce modulo \a modBase. * @param modBase the modular base in which to work. */ REGINA_API long reducedMod(long k, long modBase); /** * Calculates the greatest common divisor of two signed integers. * This routine is not recursive. * * Although the arguments may be negative, the result is guaranteed to * be non-negative. As a special case, gcd(0,0) is considered to be zero. * * @param a one of the two integers to work with. * @param b the other integer with which to work. * @return the greatest common divisor of \a a and \a b. */ REGINA_API long gcd(long a, long b); /** * Calculates the greatest common divisor of two given integers and finds the * smallest coefficients with which these integers combine to give their * gcd. This routine is not recursive. * * Note that the given integers need not be non-negative. However, the * gcd returned is guaranteed to be non-negative. * As a special case, gcd(0,0) is considered to be zero. * * If \a d is the gcd of \a a and \a b, the values placed in \a u and \a v * will be those for which * u*a + v*b = d, * -abs(a)/d < v*sign(b) <= 0 and * 1 <= u*sign(a) <= abs(b)/d. * * In the special case where one of the given integers is zero, the * corresponding coefficient will also be zero and the other coefficient * will be 1 or -1 so that u*a + v*b = d still holds. If both * given integers are zero, both of the coefficients will be set to zero. * * @param a one of the integers to work with. * @param b the other integer with which to work. * @param u a variable into which the final coefficient of \a a will be * placed. * @param v a variable into which the final coefficient of \a b will be * placed. * @return the greatest common divisor of \a a and \a b. */ REGINA_API long gcdWithCoeffs(long a, long b, long& u, long& v); /** * Calculates the lowest common multiple of two signed integers. * Although the arguments may be negative, the result is guaranteed to * be non-negative. * * If either of the arguments is zero, the return value will also be zero. * * Regarding possible overflow: This routine does not create any temporary * integers that are larger than the final LCM. * * @param a one of the two integers to work with. * @param b the other integer with which to work. * @return the lowest common multiple of \a a and \a b. */ REGINA_API long lcm(long a, long b); /** * Calculates the multiplicative inverse of one integer modulo another. * The inverse returned will be between 0 and n-1 inclusive. * * \pre \a n and \a k are both strictly positive; * \pre \a n and \a k have no common factors. * * @param n the modular base in which to work. * @param k the number whose multiplicative inverse should be found. * @return the inverse \a v for which k * v == 1 (mod n). */ REGINA_API unsigned long modularInverse(unsigned long n, unsigned long k); /** * Calculates the prime factorisation of the given integer. * All the prime factors will be inserted into the given list. * The algorithm used is very neanderthal and should only be used with * reasonably sized integers. Don't use it to do RSA! * * If a prime factor is repeated, it will be inserted multiple times into * the list. The primes in the list are not guaranteed to appear in any * specific order, nor are multiple occurrences of the same prime * guaranteed to appear together. * * Note that once finished the list will contain the prime factors as well * as whatever happened to be in the list before this function was * called. * * \pre The given integer is at least 1. * * \deprecated This routine is old and slow; please consider using the * much faster routines from the NPrimes class instead. * * \ifacespython Argument \a factors is not present; instead this * routine returns a python list containing the prime factors. * * @param n the integer to factorise. * @param factors the list into which prime factors will be inserted. */ REGINA_API void factorise(unsigned long n, std::list& factors); /** * Determines all primes up to and including the given upper bound. * All the primes found will be inserted into the given list in * increasing order. * * The algorithm currently used is fairly neanderthal. * * \pre The given list is empty. * * \deprecated This routine is old and slow; please consider using the * much faster routines from the NPrimes class instead. * * \ifacespython Argument \a primes is not present; instead this routine * returns a python list containing the primes up to and including \a roof. * * @param roof the upper bound up to which primes will be found. * @param primes the list into which the primes will be inserted. */ REGINA_API void primesUpTo(const NLargeInteger& roof, std::list& primes); /*@}*/ } // namespace regina #endif regina-4.96/engine/maths/nvector.h000644 000765 000024 00000035443 12377775307 017055 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file maths/nvector.h * \brief Provides a fast and generic vector class. */ #ifndef __NVECTOR_H #ifndef __DOXYGEN #define __NVECTOR_H #endif #include #include #include "regina-core.h" namespace regina { /** * \weakgroup maths * @{ */ /** * An optimised vector class of elements from a given ring T. * Various mathematical vector operations are available. * * This class is intended for serious computation, and as a result it has a * streamlined implementation with no virtual methods. It can be subclassed, * but since there are no virtual methods, type information must generally * be known at compile time. Nevertheless, in many respects, different * subclasses of NVector can happily interact with one another. * * This class is written with bulky types in mind (such as * arbitrary precision integers), and so creations and operations are kept * to a minimum. * * \warning As of Regina 4.90, this class merges the old functionality of * NFastVector and the NVector hierarchy from Regina 4.6. As a side-effect, * the hierarchy has been compressed into just one class (NVectorUnit, * NVectorMatrix and NVectorDense are gone), elements are always stored as * dense vectors, and functions are no longer virtual (since the storage * model is now fixed). The virtual clone() method is gone completely * (since there are no longer virtual functions you should use the copy * constructor instead), and the old makeLinComb() method is also gone * (just use operator *= and addCopies()). * * \pre Type T has a copy constructor. That is, * if \c a and \c b are of type T, then \c a can be initialised to the value * of \c b using a(b). * \pre Type T has a default constructor. That is, * an object of type T can be declared with no arguments. No specific * default value is required. * \pre Type T allows for operators =, ==, +=, * -= and *=. * \pre Type T has a long integer constructor. That is, if \c a is of type T, * then \c a can be initialised to a long integer \c l using a(l). * \pre An element \c t of type T can be written to an output stream * \c out using the standard expression out << t. * * \ifacespython Not present. */ template class NVector { public: static T zero; /**< Zero in the underlying number system. * This would be \c const if it weren't for the fact that * some compilers don't like this. It should never be * modified! */ static T one; /**< One in the underlying number system. * This would be \c const if it weren't for the fact that * some compilers don't like this. It should never be * modified! */ static T minusOne; /**< Negative one in the underlying number system. * This would be \c const if it weren't for the fact that * some compilers don't like this. It should never be * modified! */ protected: T* elements; /**< The internal array containing all vector elements. */ T* end; /**< A pointer just beyond the end of the internal array. The size of the vector can be computed as (end - elements). */ public: /** * Creates a new vector. * Its elements will not be initialised. * * @param newVectorSize the number of elements in the new * vector; this must be strictly positive. */ inline NVector(size_t newVectorSize) : elements(new T[newVectorSize]), end(elements + newVectorSize) { } /** * Creates a new vector and initialises every element to the * given value. * * @param newVectorSize the number of elements in the new * vector; this must be strictly positive. * @param initValue the value to assign to every element of the * vector. */ inline NVector(size_t newVectorSize, const T& initValue) : elements(new T[newVectorSize]), end(elements + newVectorSize) { std::fill(elements, end, initValue); } /** * Creates a new vector that is a clone of the given vector. * * @param cloneMe the vector to clone. */ inline NVector(const NVector& cloneMe) : elements(new T[cloneMe.end - cloneMe.elements]), end(elements + (cloneMe.end - cloneMe.elements)) { std::copy(cloneMe.elements, cloneMe.end, elements); } /** * Destroys this vector. */ inline ~NVector() { delete[] elements; } /** * Returns the number of elements in the vector. * * @return the vector size. */ inline size_t size() const { return end - elements; } /** * Returns the element at the given index in the vector. * A constant reference to the element is returned; the element * may not be altered. * * \pre \c index is between 0 and size()-1 inclusive. * * @param index the vector index to examine. * @return the vector element at the given index. */ inline const T& operator[](size_t index) const { return elements[index]; } /** * Sets the element at the given index in the vector to the * given value. * * \pre \c index is between 0 and size()-1 inclusive. * * @param index the vector index to examine. * @param value the new value to assign to the element. * @return the vector element at the given index. */ inline void setElement(size_t index, const T& value) { elements[index] = value; } /** * Determines if this vector is equal to the given vector. * * \pre This and the given vector have the same size. * * @param compare the vector with which this will be compared. * @return \c true if and only if the this and the given vector * are equal. */ inline bool operator == (const NVector& compare) const { return std::equal(elements, end, compare.elements); } /** * Sets this vector equal to the given vector. * * \pre This and the given vector have the same size. * * @param cloneMe the vector whose value shall be assigned to this * vector. */ inline NVector& operator = (const NVector& cloneMe) { std::copy(cloneMe.elements, cloneMe.end, elements); return *this; } /** * Adds the given vector to this vector. * * \pre This and the given vector have the same size. * * @param other the vector to add to this vector. */ inline void operator += (const NVector& other) { T* e = elements; const T* o = other.elements; for ( ; e < end; ++e, ++o) *e += *o; } /** * Subtracts the given vector from this vector. * * \pre This and the given vector have the same size. * * @param other the vector to subtract from this vector. */ inline void operator -= (const NVector& other) { T* e = elements; const T* o = other.elements; for ( ; e < end; ++e, ++o) *e -= *o; } /** * Multiplies this vector by the given scalar. * * @param factor the scalar with which this will be multiplied. */ inline void operator *= (const T& factor) { if (factor == NVector::one) return; for (T* e = elements; e < end; ++e) *e *= factor; } /** * Calculates the dot product of this vector and the given vector. * * \pre This and the given vector have the same size. * * @param other the vector with which this will be multiplied. * @return the dot product of this and the given vector. */ inline T operator * (const NVector& other) const { T ans(zero); const T* e = elements; const T* o = other.elements; for ( ; e < end; ++e, ++o) ans += (*e) * (*o); return ans; } /** * Negates every element of this vector. */ inline void negate() { for (T* e = elements; e < end; ++e) *e = -*e; } /** * Returns the norm of this vector. * This is the dot product of the vector with itself. * * @return the norm of this vector. */ inline T norm() const { T ans(zero); for (const T* e = elements; e < end; ++e) ans += (*e) * (*e); return ans; } /** * Returns the sum of all elements of this vector. * * @return the sum of the elements of this vector. */ inline T elementSum() const { T ans(zero); for (const T* e = elements; e < end; ++e) ans += *e; return ans; } /** * Adds the given multiple of the given vector to this vector. * * \pre This and the given vector have the same size. * * @param other the vector a multiple of which will be added to * this vector. * @param multiple the multiple of \a other to be added to this * vector. */ void addCopies(const NVector& other, const T& multiple) { if (multiple == NVector::zero) return; if (multiple == NVector::one) { (*this) += other; return; } if (multiple == NVector::minusOne) { (*this) -= other; return; } T* e = elements; const T* o = other.elements; for ( ; e < end; ++e, ++o) *e += *o * multiple; } /** * Subtracts the given multiple of the given vector to this vector. * * \pre This and the given vector have the same size. * * @param other the vector a multiple of which will be * subtracted from this vector. * @param multiple the multiple of \a other to be subtracted * from this vector. */ void subtractCopies(const NVector& other, const T& multiple) { if (multiple == NVector::zero) return; if (multiple == NVector::one) { (*this) -= other; return; } if (multiple == NVector::minusOne) { (*this) += other; return; } T* e = elements; const T* o = other.elements; for ( ; e < end; ++e, ++o) *e -= *o * multiple; } }; /** * Writes the given vector to the given output stream. * The vector will be written on a single line with elements separated * by a single space. No newline will be written. * * \ifacespython Not present. * * @param out the output stream to which to write. * @param vector the vector to write. * @return a reference to \a out. */ template std::ostream& operator << (std::ostream& out, const NVector& vector) { size_t size = vector.size(); if (size == 0) return out; out << vector[0]; for (size_t i=1; i T NVector::zero(0L); /**< Zero in the underlying number system. * This would be \c const if it weren't for the fact that * some compilers don't like this. It should never be * modified! */ template T NVector::one(1L); /**< One in the underlying number system. * This would be \c const if it weren't for the fact that * some compilers don't like this. It should never be * modified! */ template T NVector::minusOne(-1L); /**< Negative one in the underlying number system. * This would be \c const if it weren't for the fact that * some compilers don't like this. It should never be * modified! */ /*@}*/ } // namespace regina #endif regina-4.96/engine/maths/permconv.h000644 000765 000024 00000014300 12377775310 017205 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file maths/permconv.h * \brief Conversions between various permutation classes. */ #ifndef __PERMCONV_H #ifndef __DOXYGEN #define __PERMCONV_H #endif #include "regina-core.h" #include "maths/nperm3.h" #include "maths/nperm4.h" #include "maths/nperm5.h" namespace regina { /** * \weakgroup maths * @{ */ /** * Converts the given 4-element permutation to a 5-element permutation. * The resulting 5-element permutation will map 4 to 4, and will map * 0, 1, 2 and 3 to their respective images under \a p. * * @param p the given 4-element permutation. * @return the permutation \a p expressed as a permutation of five * elements, not four. */ REGINA_API NPerm5 perm4to5(const NPerm4& p); /** * Expresses the given 5-element permutation as a 4-element permutation. * The resulting 4-element permutation will map 0, 1, 2 and 3 to their * respective images under \a p. It is assumed that the image of 4 is 4 * under \a p; otherwise this conversion cannot be performed. * * \pre The given permutation maps 4 to 4. * * @param p the given 5-element permutation. * @return the permutation \a p expressed as a permutation of four * elements, not five. */ REGINA_API NPerm4 perm5to4(const NPerm5& p); /** * Converts the given 3-element permutation to a 4-element permutation. * The resulting 4-element permutation will map 3 to 3, and will map * 0, 1 and 2 to their respective images under \a p. * * @param p the given 3-element permutation. * @return the permutation \a p expressed as a permutation of four * elements, not three. */ REGINA_API NPerm4 perm3to4(const NPerm3& p); /** * Expresses the given 4-element permutation as a 3-element permutation. * The resulting 3-element permutation will map 0, 1 and 2 to their * respective images under \a p. It is assumed that the image of 3 is 3 * under \a p; otherwise this conversion cannot be performed. * * \pre The given permutation maps 3 to 3. * * @param p the given 4-element permutation. * @return the permutation \a p expressed as a permutation of three * elements, not four. */ REGINA_API NPerm3 perm4to3(const NPerm4& p); /** * Converts the given 3-element permutation to a 5-element permutation. * The resulting 5-element permutation will map 3 to 3 and 4 to 4, and will * map 0, 1 and 2 to their respective images under \a p. * * @param p the given 3-element permutation. * @return the permutation \a p expressed as a permutation of five * elements, not three. */ REGINA_API NPerm5 perm3to5(const NPerm3& p); /** * Expresses the given 5-element permutation as a 3-element permutation. * The resulting 3-element permutation will map 0, 1 and 2 to their * respective images under \a p. It is assumed that \p maps 3,4 to 3,4 * (but it may do so in either order); otherwise this conversion cannot * be performed. * * \pre The given permutation maps 3,4 to 3,4 in some order. * * @param p the given 5-element permutation. * @return the permutation \a p expressed as a permutation of three * elements, not five. */ REGINA_API NPerm3 perm5to3(const NPerm5& p); /*@}*/ // Inline conversion functions inline NPerm5 perm4to5(const NPerm4& p) { return NPerm5(p[0], p[1], p[2], p[3], 4); } inline NPerm4 perm5to4(const NPerm5& p) { unsigned code = p.getPermCode(); return NPerm4(code & 0x03, (code >> 3) & 0x03, (code >> 6) & 0x03, (code >> 9) & 0x03); } inline NPerm4 perm3to4(const NPerm3& p) { // Code map: 0,1,2,3,4,5 -> 0,3,8,7,12,15. unsigned char c = p.getPermCode(); return NPerm4::fromPermCode2(c == 2 ? 8 : c == 3 ? 7 : 3 * c); } inline NPerm3 perm4to3(const NPerm4& p) { // Code map: 0,3,8,7,12,15 -> 0,1,2,3,4,5. unsigned char c = p.getPermCode2(); return NPerm3::fromPermCode(c == 8 ? 2 : c == 7 ? 3 : c / 3); } inline NPerm5 perm3to5(const NPerm3& p) { return NPerm5(p[0], p[1], p[2], 3, 4); } inline NPerm3 perm5to3(const NPerm5& p) { // This can probably be streamlined... return NPerm3(p[0], p[1], p[2]); } } // namespace regina #endif regina-4.96/engine/maths/seedprimes.cpp000644 000765 000024 00000243166 12377776632 020075 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "maths/nprimes.h" namespace regina { // Keep the seed primes in a separate file so they're nicely out of the // way of everything else. const unsigned long NPrimes::numPrimeSeeds = 10000; const unsigned long NPrimes::primeSeedList[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, 8147, 8161, 8167, 8171, 8179, 8191, 8209, 8219, 8221, 8231, 8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291, 8293, 8297, 8311, 8317, 8329, 8353, 8363, 8369, 8377, 8387, 8389, 8419, 8423, 8429, 8431, 8443, 8447, 8461, 8467, 8501, 8513, 8521, 8527, 8537, 8539, 8543, 8563, 8573, 8581, 8597, 8599, 8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677, 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741, 8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831, 8837, 8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929, 8933, 8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011, 9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109, 9127, 9133, 9137, 9151, 9157, 9161, 9173, 9181, 9187, 9199, 9203, 9209, 9221, 9227, 9239, 9241, 9257, 9277, 9281, 9283, 9293, 9311, 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377, 9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439, 9461, 9463, 9467, 9473, 9479, 9491, 9497, 9511, 9521, 9533, 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623, 9629, 9631, 9643, 9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733, 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811, 9817, 9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887, 9901, 9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973, 10007, 10009, 10037, 10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099, 10103, 10111, 10133, 10139, 10141, 10151, 10159, 10163, 10169, 10177, 10181, 10193, 10211, 10223, 10243, 10247, 10253, 10259, 10267, 10271, 10273, 10289, 10301, 10303, 10313, 10321, 10331, 10333, 10337, 10343, 10357, 10369, 10391, 10399, 10427, 10429, 10433, 10453, 10457, 10459, 10463, 10477, 10487, 10499, 10501, 10513, 10529, 10531, 10559, 10567, 10589, 10597, 10601, 10607, 10613, 10627, 10631, 10639, 10651, 10657, 10663, 10667, 10687, 10691, 10709, 10711, 10723, 10729, 10733, 10739, 10753, 10771, 10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859, 10861, 10867, 10883, 10889, 10891, 10903, 10909, 10937, 10939, 10949, 10957, 10973, 10979, 10987, 10993, 11003, 11027, 11047, 11057, 11059, 11069, 11071, 11083, 11087, 11093, 11113, 11117, 11119, 11131, 11149, 11159, 11161, 11171, 11173, 11177, 11197, 11213, 11239, 11243, 11251, 11257, 11261, 11273, 11279, 11287, 11299, 11311, 11317, 11321, 11329, 11351, 11353, 11369, 11383, 11393, 11399, 11411, 11423, 11437, 11443, 11447, 11467, 11471, 11483, 11489, 11491, 11497, 11503, 11519, 11527, 11549, 11551, 11579, 11587, 11593, 11597, 11617, 11621, 11633, 11657, 11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731, 11743, 11777, 11779, 11783, 11789, 11801, 11807, 11813, 11821, 11827, 11831, 11833, 11839, 11863, 11867, 11887, 11897, 11903, 11909, 11923, 11927, 11933, 11939, 11941, 11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011, 12037, 12041, 12043, 12049, 12071, 12073, 12097, 12101, 12107, 12109, 12113, 12119, 12143, 12149, 12157, 12161, 12163, 12197, 12203, 12211, 12227, 12239, 12241, 12251, 12253, 12263, 12269, 12277, 12281, 12289, 12301, 12323, 12329, 12343, 12347, 12373, 12377, 12379, 12391, 12401, 12409, 12413, 12421, 12433, 12437, 12451, 12457, 12473, 12479, 12487, 12491, 12497, 12503, 12511, 12517, 12527, 12539, 12541, 12547, 12553, 12569, 12577, 12583, 12589, 12601, 12611, 12613, 12619, 12637, 12641, 12647, 12653, 12659, 12671, 12689, 12697, 12703, 12713, 12721, 12739, 12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821, 12823, 12829, 12841, 12853, 12889, 12893, 12899, 12907, 12911, 12917, 12919, 12923, 12941, 12953, 12959, 12967, 12973, 12979, 12983, 13001, 13003, 13007, 13009, 13033, 13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109, 13121, 13127, 13147, 13151, 13159, 13163, 13171, 13177, 13183, 13187, 13217, 13219, 13229, 13241, 13249, 13259, 13267, 13291, 13297, 13309, 13313, 13327, 13331, 13337, 13339, 13367, 13381, 13397, 13399, 13411, 13417, 13421, 13441, 13451, 13457, 13463, 13469, 13477, 13487, 13499, 13513, 13523, 13537, 13553, 13567, 13577, 13591, 13597, 13613, 13619, 13627, 13633, 13649, 13669, 13679, 13681, 13687, 13691, 13693, 13697, 13709, 13711, 13721, 13723, 13729, 13751, 13757, 13759, 13763, 13781, 13789, 13799, 13807, 13829, 13831, 13841, 13859, 13873, 13877, 13879, 13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933, 13963, 13967, 13997, 13999, 14009, 14011, 14029, 14033, 14051, 14057, 14071, 14081, 14083, 14087, 14107, 14143, 14149, 14153, 14159, 14173, 14177, 14197, 14207, 14221, 14243, 14249, 14251, 14281, 14293, 14303, 14321, 14323, 14327, 14341, 14347, 14369, 14387, 14389, 14401, 14407, 14411, 14419, 14423, 14431, 14437, 14447, 14449, 14461, 14479, 14489, 14503, 14519, 14533, 14537, 14543, 14549, 14551, 14557, 14561, 14563, 14591, 14593, 14621, 14627, 14629, 14633, 14639, 14653, 14657, 14669, 14683, 14699, 14713, 14717, 14723, 14731, 14737, 14741, 14747, 14753, 14759, 14767, 14771, 14779, 14783, 14797, 14813, 14821, 14827, 14831, 14843, 14851, 14867, 14869, 14879, 14887, 14891, 14897, 14923, 14929, 14939, 14947, 14951, 14957, 14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073, 15077, 15083, 15091, 15101, 15107, 15121, 15131, 15137, 15139, 15149, 15161, 15173, 15187, 15193, 15199, 15217, 15227, 15233, 15241, 15259, 15263, 15269, 15271, 15277, 15287, 15289, 15299, 15307, 15313, 15319, 15329, 15331, 15349, 15359, 15361, 15373, 15377, 15383, 15391, 15401, 15413, 15427, 15439, 15443, 15451, 15461, 15467, 15473, 15493, 15497, 15511, 15527, 15541, 15551, 15559, 15569, 15581, 15583, 15601, 15607, 15619, 15629, 15641, 15643, 15647, 15649, 15661, 15667, 15671, 15679, 15683, 15727, 15731, 15733, 15737, 15739, 15749, 15761, 15767, 15773, 15787, 15791, 15797, 15803, 15809, 15817, 15823, 15859, 15877, 15881, 15887, 15889, 15901, 15907, 15913, 15919, 15923, 15937, 15959, 15971, 15973, 15991, 16001, 16007, 16033, 16057, 16061, 16063, 16067, 16069, 16073, 16087, 16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183, 16187, 16189, 16193, 16217, 16223, 16229, 16231, 16249, 16253, 16267, 16273, 16301, 16319, 16333, 16339, 16349, 16361, 16363, 16369, 16381, 16411, 16417, 16421, 16427, 16433, 16447, 16451, 16453, 16477, 16481, 16487, 16493, 16519, 16529, 16547, 16553, 16561, 16567, 16573, 16603, 16607, 16619, 16631, 16633, 16649, 16651, 16657, 16661, 16673, 16691, 16693, 16699, 16703, 16729, 16741, 16747, 16759, 16763, 16787, 16811, 16823, 16829, 16831, 16843, 16871, 16879, 16883, 16889, 16901, 16903, 16921, 16927, 16931, 16937, 16943, 16963, 16979, 16981, 16987, 16993, 17011, 17021, 17027, 17029, 17033, 17041, 17047, 17053, 17077, 17093, 17099, 17107, 17117, 17123, 17137, 17159, 17167, 17183, 17189, 17191, 17203, 17207, 17209, 17231, 17239, 17257, 17291, 17293, 17299, 17317, 17321, 17327, 17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389, 17393, 17401, 17417, 17419, 17431, 17443, 17449, 17467, 17471, 17477, 17483, 17489, 17491, 17497, 17509, 17519, 17539, 17551, 17569, 17573, 17579, 17581, 17597, 17599, 17609, 17623, 17627, 17657, 17659, 17669, 17681, 17683, 17707, 17713, 17729, 17737, 17747, 17749, 17761, 17783, 17789, 17791, 17807, 17827, 17837, 17839, 17851, 17863, 17881, 17891, 17903, 17909, 17911, 17921, 17923, 17929, 17939, 17957, 17959, 17971, 17977, 17981, 17987, 17989, 18013, 18041, 18043, 18047, 18049, 18059, 18061, 18077, 18089, 18097, 18119, 18121, 18127, 18131, 18133, 18143, 18149, 18169, 18181, 18191, 18199, 18211, 18217, 18223, 18229, 18233, 18251, 18253, 18257, 18269, 18287, 18289, 18301, 18307, 18311, 18313, 18329, 18341, 18353, 18367, 18371, 18379, 18397, 18401, 18413, 18427, 18433, 18439, 18443, 18451, 18457, 18461, 18481, 18493, 18503, 18517, 18521, 18523, 18539, 18541, 18553, 18583, 18587, 18593, 18617, 18637, 18661, 18671, 18679, 18691, 18701, 18713, 18719, 18731, 18743, 18749, 18757, 18773, 18787, 18793, 18797, 18803, 18839, 18859, 18869, 18899, 18911, 18913, 18917, 18919, 18947, 18959, 18973, 18979, 19001, 19009, 19013, 19031, 19037, 19051, 19069, 19073, 19079, 19081, 19087, 19121, 19139, 19141, 19157, 19163, 19181, 19183, 19207, 19211, 19213, 19219, 19231, 19237, 19249, 19259, 19267, 19273, 19289, 19301, 19309, 19319, 19333, 19373, 19379, 19381, 19387, 19391, 19403, 19417, 19421, 19423, 19427, 19429, 19433, 19441, 19447, 19457, 19463, 19469, 19471, 19477, 19483, 19489, 19501, 19507, 19531, 19541, 19543, 19553, 19559, 19571, 19577, 19583, 19597, 19603, 19609, 19661, 19681, 19687, 19697, 19699, 19709, 19717, 19727, 19739, 19751, 19753, 19759, 19763, 19777, 19793, 19801, 19813, 19819, 19841, 19843, 19853, 19861, 19867, 19889, 19891, 19913, 19919, 19927, 19937, 19949, 19961, 19963, 19973, 19979, 19991, 19993, 19997, 20011, 20021, 20023, 20029, 20047, 20051, 20063, 20071, 20089, 20101, 20107, 20113, 20117, 20123, 20129, 20143, 20147, 20149, 20161, 20173, 20177, 20183, 20201, 20219, 20231, 20233, 20249, 20261, 20269, 20287, 20297, 20323, 20327, 20333, 20341, 20347, 20353, 20357, 20359, 20369, 20389, 20393, 20399, 20407, 20411, 20431, 20441, 20443, 20477, 20479, 20483, 20507, 20509, 20521, 20533, 20543, 20549, 20551, 20563, 20593, 20599, 20611, 20627, 20639, 20641, 20663, 20681, 20693, 20707, 20717, 20719, 20731, 20743, 20747, 20749, 20753, 20759, 20771, 20773, 20789, 20807, 20809, 20849, 20857, 20873, 20879, 20887, 20897, 20899, 20903, 20921, 20929, 20939, 20947, 20959, 20963, 20981, 20983, 21001, 21011, 21013, 21017, 21019, 21023, 21031, 21059, 21061, 21067, 21089, 21101, 21107, 21121, 21139, 21143, 21149, 21157, 21163, 21169, 21179, 21187, 21191, 21193, 21211, 21221, 21227, 21247, 21269, 21277, 21283, 21313, 21317, 21319, 21323, 21341, 21347, 21377, 21379, 21383, 21391, 21397, 21401, 21407, 21419, 21433, 21467, 21481, 21487, 21491, 21493, 21499, 21503, 21517, 21521, 21523, 21529, 21557, 21559, 21563, 21569, 21577, 21587, 21589, 21599, 21601, 21611, 21613, 21617, 21647, 21649, 21661, 21673, 21683, 21701, 21713, 21727, 21737, 21739, 21751, 21757, 21767, 21773, 21787, 21799, 21803, 21817, 21821, 21839, 21841, 21851, 21859, 21863, 21871, 21881, 21893, 21911, 21929, 21937, 21943, 21961, 21977, 21991, 21997, 22003, 22013, 22027, 22031, 22037, 22039, 22051, 22063, 22067, 22073, 22079, 22091, 22093, 22109, 22111, 22123, 22129, 22133, 22147, 22153, 22157, 22159, 22171, 22189, 22193, 22229, 22247, 22259, 22271, 22273, 22277, 22279, 22283, 22291, 22303, 22307, 22343, 22349, 22367, 22369, 22381, 22391, 22397, 22409, 22433, 22441, 22447, 22453, 22469, 22481, 22483, 22501, 22511, 22531, 22541, 22543, 22549, 22567, 22571, 22573, 22613, 22619, 22621, 22637, 22639, 22643, 22651, 22669, 22679, 22691, 22697, 22699, 22709, 22717, 22721, 22727, 22739, 22741, 22751, 22769, 22777, 22783, 22787, 22807, 22811, 22817, 22853, 22859, 22861, 22871, 22877, 22901, 22907, 22921, 22937, 22943, 22961, 22963, 22973, 22993, 23003, 23011, 23017, 23021, 23027, 23029, 23039, 23041, 23053, 23057, 23059, 23063, 23071, 23081, 23087, 23099, 23117, 23131, 23143, 23159, 23167, 23173, 23189, 23197, 23201, 23203, 23209, 23227, 23251, 23269, 23279, 23291, 23293, 23297, 23311, 23321, 23327, 23333, 23339, 23357, 23369, 23371, 23399, 23417, 23431, 23447, 23459, 23473, 23497, 23509, 23531, 23537, 23539, 23549, 23557, 23561, 23563, 23567, 23581, 23593, 23599, 23603, 23609, 23623, 23627, 23629, 23633, 23663, 23669, 23671, 23677, 23687, 23689, 23719, 23741, 23743, 23747, 23753, 23761, 23767, 23773, 23789, 23801, 23813, 23819, 23827, 23831, 23833, 23857, 23869, 23873, 23879, 23887, 23893, 23899, 23909, 23911, 23917, 23929, 23957, 23971, 23977, 23981, 23993, 24001, 24007, 24019, 24023, 24029, 24043, 24049, 24061, 24071, 24077, 24083, 24091, 24097, 24103, 24107, 24109, 24113, 24121, 24133, 24137, 24151, 24169, 24179, 24181, 24197, 24203, 24223, 24229, 24239, 24247, 24251, 24281, 24317, 24329, 24337, 24359, 24371, 24373, 24379, 24391, 24407, 24413, 24419, 24421, 24439, 24443, 24469, 24473, 24481, 24499, 24509, 24517, 24527, 24533, 24547, 24551, 24571, 24593, 24611, 24623, 24631, 24659, 24671, 24677, 24683, 24691, 24697, 24709, 24733, 24749, 24763, 24767, 24781, 24793, 24799, 24809, 24821, 24841, 24847, 24851, 24859, 24877, 24889, 24907, 24917, 24919, 24923, 24943, 24953, 24967, 24971, 24977, 24979, 24989, 25013, 25031, 25033, 25037, 25057, 25073, 25087, 25097, 25111, 25117, 25121, 25127, 25147, 25153, 25163, 25169, 25171, 25183, 25189, 25219, 25229, 25237, 25243, 25247, 25253, 25261, 25301, 25303, 25307, 25309, 25321, 25339, 25343, 25349, 25357, 25367, 25373, 25391, 25409, 25411, 25423, 25439, 25447, 25453, 25457, 25463, 25469, 25471, 25523, 25537, 25541, 25561, 25577, 25579, 25583, 25589, 25601, 25603, 25609, 25621, 25633, 25639, 25643, 25657, 25667, 25673, 25679, 25693, 25703, 25717, 25733, 25741, 25747, 25759, 25763, 25771, 25793, 25799, 25801, 25819, 25841, 25847, 25849, 25867, 25873, 25889, 25903, 25913, 25919, 25931, 25933, 25939, 25943, 25951, 25969, 25981, 25997, 25999, 26003, 26017, 26021, 26029, 26041, 26053, 26083, 26099, 26107, 26111, 26113, 26119, 26141, 26153, 26161, 26171, 26177, 26183, 26189, 26203, 26209, 26227, 26237, 26249, 26251, 26261, 26263, 26267, 26293, 26297, 26309, 26317, 26321, 26339, 26347, 26357, 26371, 26387, 26393, 26399, 26407, 26417, 26423, 26431, 26437, 26449, 26459, 26479, 26489, 26497, 26501, 26513, 26539, 26557, 26561, 26573, 26591, 26597, 26627, 26633, 26641, 26647, 26669, 26681, 26683, 26687, 26693, 26699, 26701, 26711, 26713, 26717, 26723, 26729, 26731, 26737, 26759, 26777, 26783, 26801, 26813, 26821, 26833, 26839, 26849, 26861, 26863, 26879, 26881, 26891, 26893, 26903, 26921, 26927, 26947, 26951, 26953, 26959, 26981, 26987, 26993, 27011, 27017, 27031, 27043, 27059, 27061, 27067, 27073, 27077, 27091, 27103, 27107, 27109, 27127, 27143, 27179, 27191, 27197, 27211, 27239, 27241, 27253, 27259, 27271, 27277, 27281, 27283, 27299, 27329, 27337, 27361, 27367, 27397, 27407, 27409, 27427, 27431, 27437, 27449, 27457, 27479, 27481, 27487, 27509, 27527, 27529, 27539, 27541, 27551, 27581, 27583, 27611, 27617, 27631, 27647, 27653, 27673, 27689, 27691, 27697, 27701, 27733, 27737, 27739, 27743, 27749, 27751, 27763, 27767, 27773, 27779, 27791, 27793, 27799, 27803, 27809, 27817, 27823, 27827, 27847, 27851, 27883, 27893, 27901, 27917, 27919, 27941, 27943, 27947, 27953, 27961, 27967, 27983, 27997, 28001, 28019, 28027, 28031, 28051, 28057, 28069, 28081, 28087, 28097, 28099, 28109, 28111, 28123, 28151, 28163, 28181, 28183, 28201, 28211, 28219, 28229, 28277, 28279, 28283, 28289, 28297, 28307, 28309, 28319, 28349, 28351, 28387, 28393, 28403, 28409, 28411, 28429, 28433, 28439, 28447, 28463, 28477, 28493, 28499, 28513, 28517, 28537, 28541, 28547, 28549, 28559, 28571, 28573, 28579, 28591, 28597, 28603, 28607, 28619, 28621, 28627, 28631, 28643, 28649, 28657, 28661, 28663, 28669, 28687, 28697, 28703, 28711, 28723, 28729, 28751, 28753, 28759, 28771, 28789, 28793, 28807, 28813, 28817, 28837, 28843, 28859, 28867, 28871, 28879, 28901, 28909, 28921, 28927, 28933, 28949, 28961, 28979, 29009, 29017, 29021, 29023, 29027, 29033, 29059, 29063, 29077, 29101, 29123, 29129, 29131, 29137, 29147, 29153, 29167, 29173, 29179, 29191, 29201, 29207, 29209, 29221, 29231, 29243, 29251, 29269, 29287, 29297, 29303, 29311, 29327, 29333, 29339, 29347, 29363, 29383, 29387, 29389, 29399, 29401, 29411, 29423, 29429, 29437, 29443, 29453, 29473, 29483, 29501, 29527, 29531, 29537, 29567, 29569, 29573, 29581, 29587, 29599, 29611, 29629, 29633, 29641, 29663, 29669, 29671, 29683, 29717, 29723, 29741, 29753, 29759, 29761, 29789, 29803, 29819, 29833, 29837, 29851, 29863, 29867, 29873, 29879, 29881, 29917, 29921, 29927, 29947, 29959, 29983, 29989, 30011, 30013, 30029, 30047, 30059, 30071, 30089, 30091, 30097, 30103, 30109, 30113, 30119, 30133, 30137, 30139, 30161, 30169, 30181, 30187, 30197, 30203, 30211, 30223, 30241, 30253, 30259, 30269, 30271, 30293, 30307, 30313, 30319, 30323, 30341, 30347, 30367, 30389, 30391, 30403, 30427, 30431, 30449, 30467, 30469, 30491, 30493, 30497, 30509, 30517, 30529, 30539, 30553, 30557, 30559, 30577, 30593, 30631, 30637, 30643, 30649, 30661, 30671, 30677, 30689, 30697, 30703, 30707, 30713, 30727, 30757, 30763, 30773, 30781, 30803, 30809, 30817, 30829, 30839, 30841, 30851, 30853, 30859, 30869, 30871, 30881, 30893, 30911, 30931, 30937, 30941, 30949, 30971, 30977, 30983, 31013, 31019, 31033, 31039, 31051, 31063, 31069, 31079, 31081, 31091, 31121, 31123, 31139, 31147, 31151, 31153, 31159, 31177, 31181, 31183, 31189, 31193, 31219, 31223, 31231, 31237, 31247, 31249, 31253, 31259, 31267, 31271, 31277, 31307, 31319, 31321, 31327, 31333, 31337, 31357, 31379, 31387, 31391, 31393, 31397, 31469, 31477, 31481, 31489, 31511, 31513, 31517, 31531, 31541, 31543, 31547, 31567, 31573, 31583, 31601, 31607, 31627, 31643, 31649, 31657, 31663, 31667, 31687, 31699, 31721, 31723, 31727, 31729, 31741, 31751, 31769, 31771, 31793, 31799, 31817, 31847, 31849, 31859, 31873, 31883, 31891, 31907, 31957, 31963, 31973, 31981, 31991, 32003, 32009, 32027, 32029, 32051, 32057, 32059, 32063, 32069, 32077, 32083, 32089, 32099, 32117, 32119, 32141, 32143, 32159, 32173, 32183, 32189, 32191, 32203, 32213, 32233, 32237, 32251, 32257, 32261, 32297, 32299, 32303, 32309, 32321, 32323, 32327, 32341, 32353, 32359, 32363, 32369, 32371, 32377, 32381, 32401, 32411, 32413, 32423, 32429, 32441, 32443, 32467, 32479, 32491, 32497, 32503, 32507, 32531, 32533, 32537, 32561, 32563, 32569, 32573, 32579, 32587, 32603, 32609, 32611, 32621, 32633, 32647, 32653, 32687, 32693, 32707, 32713, 32717, 32719, 32749, 32771, 32779, 32783, 32789, 32797, 32801, 32803, 32831, 32833, 32839, 32843, 32869, 32887, 32909, 32911, 32917, 32933, 32939, 32941, 32957, 32969, 32971, 32983, 32987, 32993, 32999, 33013, 33023, 33029, 33037, 33049, 33053, 33071, 33073, 33083, 33091, 33107, 33113, 33119, 33149, 33151, 33161, 33179, 33181, 33191, 33199, 33203, 33211, 33223, 33247, 33287, 33289, 33301, 33311, 33317, 33329, 33331, 33343, 33347, 33349, 33353, 33359, 33377, 33391, 33403, 33409, 33413, 33427, 33457, 33461, 33469, 33479, 33487, 33493, 33503, 33521, 33529, 33533, 33547, 33563, 33569, 33577, 33581, 33587, 33589, 33599, 33601, 33613, 33617, 33619, 33623, 33629, 33637, 33641, 33647, 33679, 33703, 33713, 33721, 33739, 33749, 33751, 33757, 33767, 33769, 33773, 33791, 33797, 33809, 33811, 33827, 33829, 33851, 33857, 33863, 33871, 33889, 33893, 33911, 33923, 33931, 33937, 33941, 33961, 33967, 33997, 34019, 34031, 34033, 34039, 34057, 34061, 34123, 34127, 34129, 34141, 34147, 34157, 34159, 34171, 34183, 34211, 34213, 34217, 34231, 34253, 34259, 34261, 34267, 34273, 34283, 34297, 34301, 34303, 34313, 34319, 34327, 34337, 34351, 34361, 34367, 34369, 34381, 34403, 34421, 34429, 34439, 34457, 34469, 34471, 34483, 34487, 34499, 34501, 34511, 34513, 34519, 34537, 34543, 34549, 34583, 34589, 34591, 34603, 34607, 34613, 34631, 34649, 34651, 34667, 34673, 34679, 34687, 34693, 34703, 34721, 34729, 34739, 34747, 34757, 34759, 34763, 34781, 34807, 34819, 34841, 34843, 34847, 34849, 34871, 34877, 34883, 34897, 34913, 34919, 34939, 34949, 34961, 34963, 34981, 35023, 35027, 35051, 35053, 35059, 35069, 35081, 35083, 35089, 35099, 35107, 35111, 35117, 35129, 35141, 35149, 35153, 35159, 35171, 35201, 35221, 35227, 35251, 35257, 35267, 35279, 35281, 35291, 35311, 35317, 35323, 35327, 35339, 35353, 35363, 35381, 35393, 35401, 35407, 35419, 35423, 35437, 35447, 35449, 35461, 35491, 35507, 35509, 35521, 35527, 35531, 35533, 35537, 35543, 35569, 35573, 35591, 35593, 35597, 35603, 35617, 35671, 35677, 35729, 35731, 35747, 35753, 35759, 35771, 35797, 35801, 35803, 35809, 35831, 35837, 35839, 35851, 35863, 35869, 35879, 35897, 35899, 35911, 35923, 35933, 35951, 35963, 35969, 35977, 35983, 35993, 35999, 36007, 36011, 36013, 36017, 36037, 36061, 36067, 36073, 36083, 36097, 36107, 36109, 36131, 36137, 36151, 36161, 36187, 36191, 36209, 36217, 36229, 36241, 36251, 36263, 36269, 36277, 36293, 36299, 36307, 36313, 36319, 36341, 36343, 36353, 36373, 36383, 36389, 36433, 36451, 36457, 36467, 36469, 36473, 36479, 36493, 36497, 36523, 36527, 36529, 36541, 36551, 36559, 36563, 36571, 36583, 36587, 36599, 36607, 36629, 36637, 36643, 36653, 36671, 36677, 36683, 36691, 36697, 36709, 36713, 36721, 36739, 36749, 36761, 36767, 36779, 36781, 36787, 36791, 36793, 36809, 36821, 36833, 36847, 36857, 36871, 36877, 36887, 36899, 36901, 36913, 36919, 36923, 36929, 36931, 36943, 36947, 36973, 36979, 36997, 37003, 37013, 37019, 37021, 37039, 37049, 37057, 37061, 37087, 37097, 37117, 37123, 37139, 37159, 37171, 37181, 37189, 37199, 37201, 37217, 37223, 37243, 37253, 37273, 37277, 37307, 37309, 37313, 37321, 37337, 37339, 37357, 37361, 37363, 37369, 37379, 37397, 37409, 37423, 37441, 37447, 37463, 37483, 37489, 37493, 37501, 37507, 37511, 37517, 37529, 37537, 37547, 37549, 37561, 37567, 37571, 37573, 37579, 37589, 37591, 37607, 37619, 37633, 37643, 37649, 37657, 37663, 37691, 37693, 37699, 37717, 37747, 37781, 37783, 37799, 37811, 37813, 37831, 37847, 37853, 37861, 37871, 37879, 37889, 37897, 37907, 37951, 37957, 37963, 37967, 37987, 37991, 37993, 37997, 38011, 38039, 38047, 38053, 38069, 38083, 38113, 38119, 38149, 38153, 38167, 38177, 38183, 38189, 38197, 38201, 38219, 38231, 38237, 38239, 38261, 38273, 38281, 38287, 38299, 38303, 38317, 38321, 38327, 38329, 38333, 38351, 38371, 38377, 38393, 38431, 38447, 38449, 38453, 38459, 38461, 38501, 38543, 38557, 38561, 38567, 38569, 38593, 38603, 38609, 38611, 38629, 38639, 38651, 38653, 38669, 38671, 38677, 38693, 38699, 38707, 38711, 38713, 38723, 38729, 38737, 38747, 38749, 38767, 38783, 38791, 38803, 38821, 38833, 38839, 38851, 38861, 38867, 38873, 38891, 38903, 38917, 38921, 38923, 38933, 38953, 38959, 38971, 38977, 38993, 39019, 39023, 39041, 39043, 39047, 39079, 39089, 39097, 39103, 39107, 39113, 39119, 39133, 39139, 39157, 39161, 39163, 39181, 39191, 39199, 39209, 39217, 39227, 39229, 39233, 39239, 39241, 39251, 39293, 39301, 39313, 39317, 39323, 39341, 39343, 39359, 39367, 39371, 39373, 39383, 39397, 39409, 39419, 39439, 39443, 39451, 39461, 39499, 39503, 39509, 39511, 39521, 39541, 39551, 39563, 39569, 39581, 39607, 39619, 39623, 39631, 39659, 39667, 39671, 39679, 39703, 39709, 39719, 39727, 39733, 39749, 39761, 39769, 39779, 39791, 39799, 39821, 39827, 39829, 39839, 39841, 39847, 39857, 39863, 39869, 39877, 39883, 39887, 39901, 39929, 39937, 39953, 39971, 39979, 39983, 39989, 40009, 40013, 40031, 40037, 40039, 40063, 40087, 40093, 40099, 40111, 40123, 40127, 40129, 40151, 40153, 40163, 40169, 40177, 40189, 40193, 40213, 40231, 40237, 40241, 40253, 40277, 40283, 40289, 40343, 40351, 40357, 40361, 40387, 40423, 40427, 40429, 40433, 40459, 40471, 40483, 40487, 40493, 40499, 40507, 40519, 40529, 40531, 40543, 40559, 40577, 40583, 40591, 40597, 40609, 40627, 40637, 40639, 40693, 40697, 40699, 40709, 40739, 40751, 40759, 40763, 40771, 40787, 40801, 40813, 40819, 40823, 40829, 40841, 40847, 40849, 40853, 40867, 40879, 40883, 40897, 40903, 40927, 40933, 40939, 40949, 40961, 40973, 40993, 41011, 41017, 41023, 41039, 41047, 41051, 41057, 41077, 41081, 41113, 41117, 41131, 41141, 41143, 41149, 41161, 41177, 41179, 41183, 41189, 41201, 41203, 41213, 41221, 41227, 41231, 41233, 41243, 41257, 41263, 41269, 41281, 41299, 41333, 41341, 41351, 41357, 41381, 41387, 41389, 41399, 41411, 41413, 41443, 41453, 41467, 41479, 41491, 41507, 41513, 41519, 41521, 41539, 41543, 41549, 41579, 41593, 41597, 41603, 41609, 41611, 41617, 41621, 41627, 41641, 41647, 41651, 41659, 41669, 41681, 41687, 41719, 41729, 41737, 41759, 41761, 41771, 41777, 41801, 41809, 41813, 41843, 41849, 41851, 41863, 41879, 41887, 41893, 41897, 41903, 41911, 41927, 41941, 41947, 41953, 41957, 41959, 41969, 41981, 41983, 41999, 42013, 42017, 42019, 42023, 42043, 42061, 42071, 42073, 42083, 42089, 42101, 42131, 42139, 42157, 42169, 42179, 42181, 42187, 42193, 42197, 42209, 42221, 42223, 42227, 42239, 42257, 42281, 42283, 42293, 42299, 42307, 42323, 42331, 42337, 42349, 42359, 42373, 42379, 42391, 42397, 42403, 42407, 42409, 42433, 42437, 42443, 42451, 42457, 42461, 42463, 42467, 42473, 42487, 42491, 42499, 42509, 42533, 42557, 42569, 42571, 42577, 42589, 42611, 42641, 42643, 42649, 42667, 42677, 42683, 42689, 42697, 42701, 42703, 42709, 42719, 42727, 42737, 42743, 42751, 42767, 42773, 42787, 42793, 42797, 42821, 42829, 42839, 42841, 42853, 42859, 42863, 42899, 42901, 42923, 42929, 42937, 42943, 42953, 42961, 42967, 42979, 42989, 43003, 43013, 43019, 43037, 43049, 43051, 43063, 43067, 43093, 43103, 43117, 43133, 43151, 43159, 43177, 43189, 43201, 43207, 43223, 43237, 43261, 43271, 43283, 43291, 43313, 43319, 43321, 43331, 43391, 43397, 43399, 43403, 43411, 43427, 43441, 43451, 43457, 43481, 43487, 43499, 43517, 43541, 43543, 43573, 43577, 43579, 43591, 43597, 43607, 43609, 43613, 43627, 43633, 43649, 43651, 43661, 43669, 43691, 43711, 43717, 43721, 43753, 43759, 43777, 43781, 43783, 43787, 43789, 43793, 43801, 43853, 43867, 43889, 43891, 43913, 43933, 43943, 43951, 43961, 43963, 43969, 43973, 43987, 43991, 43997, 44017, 44021, 44027, 44029, 44041, 44053, 44059, 44071, 44087, 44089, 44101, 44111, 44119, 44123, 44129, 44131, 44159, 44171, 44179, 44189, 44201, 44203, 44207, 44221, 44249, 44257, 44263, 44267, 44269, 44273, 44279, 44281, 44293, 44351, 44357, 44371, 44381, 44383, 44389, 44417, 44449, 44453, 44483, 44491, 44497, 44501, 44507, 44519, 44531, 44533, 44537, 44543, 44549, 44563, 44579, 44587, 44617, 44621, 44623, 44633, 44641, 44647, 44651, 44657, 44683, 44687, 44699, 44701, 44711, 44729, 44741, 44753, 44771, 44773, 44777, 44789, 44797, 44809, 44819, 44839, 44843, 44851, 44867, 44879, 44887, 44893, 44909, 44917, 44927, 44939, 44953, 44959, 44963, 44971, 44983, 44987, 45007, 45013, 45053, 45061, 45077, 45083, 45119, 45121, 45127, 45131, 45137, 45139, 45161, 45179, 45181, 45191, 45197, 45233, 45247, 45259, 45263, 45281, 45289, 45293, 45307, 45317, 45319, 45329, 45337, 45341, 45343, 45361, 45377, 45389, 45403, 45413, 45427, 45433, 45439, 45481, 45491, 45497, 45503, 45523, 45533, 45541, 45553, 45557, 45569, 45587, 45589, 45599, 45613, 45631, 45641, 45659, 45667, 45673, 45677, 45691, 45697, 45707, 45737, 45751, 45757, 45763, 45767, 45779, 45817, 45821, 45823, 45827, 45833, 45841, 45853, 45863, 45869, 45887, 45893, 45943, 45949, 45953, 45959, 45971, 45979, 45989, 46021, 46027, 46049, 46051, 46061, 46073, 46091, 46093, 46099, 46103, 46133, 46141, 46147, 46153, 46171, 46181, 46183, 46187, 46199, 46219, 46229, 46237, 46261, 46271, 46273, 46279, 46301, 46307, 46309, 46327, 46337, 46349, 46351, 46381, 46399, 46411, 46439, 46441, 46447, 46451, 46457, 46471, 46477, 46489, 46499, 46507, 46511, 46523, 46549, 46559, 46567, 46573, 46589, 46591, 46601, 46619, 46633, 46639, 46643, 46649, 46663, 46679, 46681, 46687, 46691, 46703, 46723, 46727, 46747, 46751, 46757, 46769, 46771, 46807, 46811, 46817, 46819, 46829, 46831, 46853, 46861, 46867, 46877, 46889, 46901, 46919, 46933, 46957, 46993, 46997, 47017, 47041, 47051, 47057, 47059, 47087, 47093, 47111, 47119, 47123, 47129, 47137, 47143, 47147, 47149, 47161, 47189, 47207, 47221, 47237, 47251, 47269, 47279, 47287, 47293, 47297, 47303, 47309, 47317, 47339, 47351, 47353, 47363, 47381, 47387, 47389, 47407, 47417, 47419, 47431, 47441, 47459, 47491, 47497, 47501, 47507, 47513, 47521, 47527, 47533, 47543, 47563, 47569, 47581, 47591, 47599, 47609, 47623, 47629, 47639, 47653, 47657, 47659, 47681, 47699, 47701, 47711, 47713, 47717, 47737, 47741, 47743, 47777, 47779, 47791, 47797, 47807, 47809, 47819, 47837, 47843, 47857, 47869, 47881, 47903, 47911, 47917, 47933, 47939, 47947, 47951, 47963, 47969, 47977, 47981, 48017, 48023, 48029, 48049, 48073, 48079, 48091, 48109, 48119, 48121, 48131, 48157, 48163, 48179, 48187, 48193, 48197, 48221, 48239, 48247, 48259, 48271, 48281, 48299, 48311, 48313, 48337, 48341, 48353, 48371, 48383, 48397, 48407, 48409, 48413, 48437, 48449, 48463, 48473, 48479, 48481, 48487, 48491, 48497, 48523, 48527, 48533, 48539, 48541, 48563, 48571, 48589, 48593, 48611, 48619, 48623, 48647, 48649, 48661, 48673, 48677, 48679, 48731, 48733, 48751, 48757, 48761, 48767, 48779, 48781, 48787, 48799, 48809, 48817, 48821, 48823, 48847, 48857, 48859, 48869, 48871, 48883, 48889, 48907, 48947, 48953, 48973, 48989, 48991, 49003, 49009, 49019, 49031, 49033, 49037, 49043, 49057, 49069, 49081, 49103, 49109, 49117, 49121, 49123, 49139, 49157, 49169, 49171, 49177, 49193, 49199, 49201, 49207, 49211, 49223, 49253, 49261, 49277, 49279, 49297, 49307, 49331, 49333, 49339, 49363, 49367, 49369, 49391, 49393, 49409, 49411, 49417, 49429, 49433, 49451, 49459, 49463, 49477, 49481, 49499, 49523, 49529, 49531, 49537, 49547, 49549, 49559, 49597, 49603, 49613, 49627, 49633, 49639, 49663, 49667, 49669, 49681, 49697, 49711, 49727, 49739, 49741, 49747, 49757, 49783, 49787, 49789, 49801, 49807, 49811, 49823, 49831, 49843, 49853, 49871, 49877, 49891, 49919, 49921, 49927, 49937, 49939, 49943, 49957, 49991, 49993, 49999, 50021, 50023, 50033, 50047, 50051, 50053, 50069, 50077, 50087, 50093, 50101, 50111, 50119, 50123, 50129, 50131, 50147, 50153, 50159, 50177, 50207, 50221, 50227, 50231, 50261, 50263, 50273, 50287, 50291, 50311, 50321, 50329, 50333, 50341, 50359, 50363, 50377, 50383, 50387, 50411, 50417, 50423, 50441, 50459, 50461, 50497, 50503, 50513, 50527, 50539, 50543, 50549, 50551, 50581, 50587, 50591, 50593, 50599, 50627, 50647, 50651, 50671, 50683, 50707, 50723, 50741, 50753, 50767, 50773, 50777, 50789, 50821, 50833, 50839, 50849, 50857, 50867, 50873, 50891, 50893, 50909, 50923, 50929, 50951, 50957, 50969, 50971, 50989, 50993, 51001, 51031, 51043, 51047, 51059, 51061, 51071, 51109, 51131, 51133, 51137, 51151, 51157, 51169, 51193, 51197, 51199, 51203, 51217, 51229, 51239, 51241, 51257, 51263, 51283, 51287, 51307, 51329, 51341, 51343, 51347, 51349, 51361, 51383, 51407, 51413, 51419, 51421, 51427, 51431, 51437, 51439, 51449, 51461, 51473, 51479, 51481, 51487, 51503, 51511, 51517, 51521, 51539, 51551, 51563, 51577, 51581, 51593, 51599, 51607, 51613, 51631, 51637, 51647, 51659, 51673, 51679, 51683, 51691, 51713, 51719, 51721, 51749, 51767, 51769, 51787, 51797, 51803, 51817, 51827, 51829, 51839, 51853, 51859, 51869, 51871, 51893, 51899, 51907, 51913, 51929, 51941, 51949, 51971, 51973, 51977, 51991, 52009, 52021, 52027, 52051, 52057, 52067, 52069, 52081, 52103, 52121, 52127, 52147, 52153, 52163, 52177, 52181, 52183, 52189, 52201, 52223, 52237, 52249, 52253, 52259, 52267, 52289, 52291, 52301, 52313, 52321, 52361, 52363, 52369, 52379, 52387, 52391, 52433, 52453, 52457, 52489, 52501, 52511, 52517, 52529, 52541, 52543, 52553, 52561, 52567, 52571, 52579, 52583, 52609, 52627, 52631, 52639, 52667, 52673, 52691, 52697, 52709, 52711, 52721, 52727, 52733, 52747, 52757, 52769, 52783, 52807, 52813, 52817, 52837, 52859, 52861, 52879, 52883, 52889, 52901, 52903, 52919, 52937, 52951, 52957, 52963, 52967, 52973, 52981, 52999, 53003, 53017, 53047, 53051, 53069, 53077, 53087, 53089, 53093, 53101, 53113, 53117, 53129, 53147, 53149, 53161, 53171, 53173, 53189, 53197, 53201, 53231, 53233, 53239, 53267, 53269, 53279, 53281, 53299, 53309, 53323, 53327, 53353, 53359, 53377, 53381, 53401, 53407, 53411, 53419, 53437, 53441, 53453, 53479, 53503, 53507, 53527, 53549, 53551, 53569, 53591, 53593, 53597, 53609, 53611, 53617, 53623, 53629, 53633, 53639, 53653, 53657, 53681, 53693, 53699, 53717, 53719, 53731, 53759, 53773, 53777, 53783, 53791, 53813, 53819, 53831, 53849, 53857, 53861, 53881, 53887, 53891, 53897, 53899, 53917, 53923, 53927, 53939, 53951, 53959, 53987, 53993, 54001, 54011, 54013, 54037, 54049, 54059, 54083, 54091, 54101, 54121, 54133, 54139, 54151, 54163, 54167, 54181, 54193, 54217, 54251, 54269, 54277, 54287, 54293, 54311, 54319, 54323, 54331, 54347, 54361, 54367, 54371, 54377, 54401, 54403, 54409, 54413, 54419, 54421, 54437, 54443, 54449, 54469, 54493, 54497, 54499, 54503, 54517, 54521, 54539, 54541, 54547, 54559, 54563, 54577, 54581, 54583, 54601, 54617, 54623, 54629, 54631, 54647, 54667, 54673, 54679, 54709, 54713, 54721, 54727, 54751, 54767, 54773, 54779, 54787, 54799, 54829, 54833, 54851, 54869, 54877, 54881, 54907, 54917, 54919, 54941, 54949, 54959, 54973, 54979, 54983, 55001, 55009, 55021, 55049, 55051, 55057, 55061, 55073, 55079, 55103, 55109, 55117, 55127, 55147, 55163, 55171, 55201, 55207, 55213, 55217, 55219, 55229, 55243, 55249, 55259, 55291, 55313, 55331, 55333, 55337, 55339, 55343, 55351, 55373, 55381, 55399, 55411, 55439, 55441, 55457, 55469, 55487, 55501, 55511, 55529, 55541, 55547, 55579, 55589, 55603, 55609, 55619, 55621, 55631, 55633, 55639, 55661, 55663, 55667, 55673, 55681, 55691, 55697, 55711, 55717, 55721, 55733, 55763, 55787, 55793, 55799, 55807, 55813, 55817, 55819, 55823, 55829, 55837, 55843, 55849, 55871, 55889, 55897, 55901, 55903, 55921, 55927, 55931, 55933, 55949, 55967, 55987, 55997, 56003, 56009, 56039, 56041, 56053, 56081, 56087, 56093, 56099, 56101, 56113, 56123, 56131, 56149, 56167, 56171, 56179, 56197, 56207, 56209, 56237, 56239, 56249, 56263, 56267, 56269, 56299, 56311, 56333, 56359, 56369, 56377, 56383, 56393, 56401, 56417, 56431, 56437, 56443, 56453, 56467, 56473, 56477, 56479, 56489, 56501, 56503, 56509, 56519, 56527, 56531, 56533, 56543, 56569, 56591, 56597, 56599, 56611, 56629, 56633, 56659, 56663, 56671, 56681, 56687, 56701, 56711, 56713, 56731, 56737, 56747, 56767, 56773, 56779, 56783, 56807, 56809, 56813, 56821, 56827, 56843, 56857, 56873, 56891, 56893, 56897, 56909, 56911, 56921, 56923, 56929, 56941, 56951, 56957, 56963, 56983, 56989, 56993, 56999, 57037, 57041, 57047, 57059, 57073, 57077, 57089, 57097, 57107, 57119, 57131, 57139, 57143, 57149, 57163, 57173, 57179, 57191, 57193, 57203, 57221, 57223, 57241, 57251, 57259, 57269, 57271, 57283, 57287, 57301, 57329, 57331, 57347, 57349, 57367, 57373, 57383, 57389, 57397, 57413, 57427, 57457, 57467, 57487, 57493, 57503, 57527, 57529, 57557, 57559, 57571, 57587, 57593, 57601, 57637, 57641, 57649, 57653, 57667, 57679, 57689, 57697, 57709, 57713, 57719, 57727, 57731, 57737, 57751, 57773, 57781, 57787, 57791, 57793, 57803, 57809, 57829, 57839, 57847, 57853, 57859, 57881, 57899, 57901, 57917, 57923, 57943, 57947, 57973, 57977, 57991, 58013, 58027, 58031, 58043, 58049, 58057, 58061, 58067, 58073, 58099, 58109, 58111, 58129, 58147, 58151, 58153, 58169, 58171, 58189, 58193, 58199, 58207, 58211, 58217, 58229, 58231, 58237, 58243, 58271, 58309, 58313, 58321, 58337, 58363, 58367, 58369, 58379, 58391, 58393, 58403, 58411, 58417, 58427, 58439, 58441, 58451, 58453, 58477, 58481, 58511, 58537, 58543, 58549, 58567, 58573, 58579, 58601, 58603, 58613, 58631, 58657, 58661, 58679, 58687, 58693, 58699, 58711, 58727, 58733, 58741, 58757, 58763, 58771, 58787, 58789, 58831, 58889, 58897, 58901, 58907, 58909, 58913, 58921, 58937, 58943, 58963, 58967, 58979, 58991, 58997, 59009, 59011, 59021, 59023, 59029, 59051, 59053, 59063, 59069, 59077, 59083, 59093, 59107, 59113, 59119, 59123, 59141, 59149, 59159, 59167, 59183, 59197, 59207, 59209, 59219, 59221, 59233, 59239, 59243, 59263, 59273, 59281, 59333, 59341, 59351, 59357, 59359, 59369, 59377, 59387, 59393, 59399, 59407, 59417, 59419, 59441, 59443, 59447, 59453, 59467, 59471, 59473, 59497, 59509, 59513, 59539, 59557, 59561, 59567, 59581, 59611, 59617, 59621, 59627, 59629, 59651, 59659, 59663, 59669, 59671, 59693, 59699, 59707, 59723, 59729, 59743, 59747, 59753, 59771, 59779, 59791, 59797, 59809, 59833, 59863, 59879, 59887, 59921, 59929, 59951, 59957, 59971, 59981, 59999, 60013, 60017, 60029, 60037, 60041, 60077, 60083, 60089, 60091, 60101, 60103, 60107, 60127, 60133, 60139, 60149, 60161, 60167, 60169, 60209, 60217, 60223, 60251, 60257, 60259, 60271, 60289, 60293, 60317, 60331, 60337, 60343, 60353, 60373, 60383, 60397, 60413, 60427, 60443, 60449, 60457, 60493, 60497, 60509, 60521, 60527, 60539, 60589, 60601, 60607, 60611, 60617, 60623, 60631, 60637, 60647, 60649, 60659, 60661, 60679, 60689, 60703, 60719, 60727, 60733, 60737, 60757, 60761, 60763, 60773, 60779, 60793, 60811, 60821, 60859, 60869, 60887, 60889, 60899, 60901, 60913, 60917, 60919, 60923, 60937, 60943, 60953, 60961, 61001, 61007, 61027, 61031, 61043, 61051, 61057, 61091, 61099, 61121, 61129, 61141, 61151, 61153, 61169, 61211, 61223, 61231, 61253, 61261, 61283, 61291, 61297, 61331, 61333, 61339, 61343, 61357, 61363, 61379, 61381, 61403, 61409, 61417, 61441, 61463, 61469, 61471, 61483, 61487, 61493, 61507, 61511, 61519, 61543, 61547, 61553, 61559, 61561, 61583, 61603, 61609, 61613, 61627, 61631, 61637, 61643, 61651, 61657, 61667, 61673, 61681, 61687, 61703, 61717, 61723, 61729, 61751, 61757, 61781, 61813, 61819, 61837, 61843, 61861, 61871, 61879, 61909, 61927, 61933, 61949, 61961, 61967, 61979, 61981, 61987, 61991, 62003, 62011, 62017, 62039, 62047, 62053, 62057, 62071, 62081, 62099, 62119, 62129, 62131, 62137, 62141, 62143, 62171, 62189, 62191, 62201, 62207, 62213, 62219, 62233, 62273, 62297, 62299, 62303, 62311, 62323, 62327, 62347, 62351, 62383, 62401, 62417, 62423, 62459, 62467, 62473, 62477, 62483, 62497, 62501, 62507, 62533, 62539, 62549, 62563, 62581, 62591, 62597, 62603, 62617, 62627, 62633, 62639, 62653, 62659, 62683, 62687, 62701, 62723, 62731, 62743, 62753, 62761, 62773, 62791, 62801, 62819, 62827, 62851, 62861, 62869, 62873, 62897, 62903, 62921, 62927, 62929, 62939, 62969, 62971, 62981, 62983, 62987, 62989, 63029, 63031, 63059, 63067, 63073, 63079, 63097, 63103, 63113, 63127, 63131, 63149, 63179, 63197, 63199, 63211, 63241, 63247, 63277, 63281, 63299, 63311, 63313, 63317, 63331, 63337, 63347, 63353, 63361, 63367, 63377, 63389, 63391, 63397, 63409, 63419, 63421, 63439, 63443, 63463, 63467, 63473, 63487, 63493, 63499, 63521, 63527, 63533, 63541, 63559, 63577, 63587, 63589, 63599, 63601, 63607, 63611, 63617, 63629, 63647, 63649, 63659, 63667, 63671, 63689, 63691, 63697, 63703, 63709, 63719, 63727, 63737, 63743, 63761, 63773, 63781, 63793, 63799, 63803, 63809, 63823, 63839, 63841, 63853, 63857, 63863, 63901, 63907, 63913, 63929, 63949, 63977, 63997, 64007, 64013, 64019, 64033, 64037, 64063, 64067, 64081, 64091, 64109, 64123, 64151, 64153, 64157, 64171, 64187, 64189, 64217, 64223, 64231, 64237, 64271, 64279, 64283, 64301, 64303, 64319, 64327, 64333, 64373, 64381, 64399, 64403, 64433, 64439, 64451, 64453, 64483, 64489, 64499, 64513, 64553, 64567, 64577, 64579, 64591, 64601, 64609, 64613, 64621, 64627, 64633, 64661, 64663, 64667, 64679, 64693, 64709, 64717, 64747, 64763, 64781, 64783, 64793, 64811, 64817, 64849, 64853, 64871, 64877, 64879, 64891, 64901, 64919, 64921, 64927, 64937, 64951, 64969, 64997, 65003, 65011, 65027, 65029, 65033, 65053, 65063, 65071, 65089, 65099, 65101, 65111, 65119, 65123, 65129, 65141, 65147, 65167, 65171, 65173, 65179, 65183, 65203, 65213, 65239, 65257, 65267, 65269, 65287, 65293, 65309, 65323, 65327, 65353, 65357, 65371, 65381, 65393, 65407, 65413, 65419, 65423, 65437, 65447, 65449, 65479, 65497, 65519, 65521, 65537, 65539, 65543, 65551, 65557, 65563, 65579, 65581, 65587, 65599, 65609, 65617, 65629, 65633, 65647, 65651, 65657, 65677, 65687, 65699, 65701, 65707, 65713, 65717, 65719, 65729, 65731, 65761, 65777, 65789, 65809, 65827, 65831, 65837, 65839, 65843, 65851, 65867, 65881, 65899, 65921, 65927, 65929, 65951, 65957, 65963, 65981, 65983, 65993, 66029, 66037, 66041, 66047, 66067, 66071, 66083, 66089, 66103, 66107, 66109, 66137, 66161, 66169, 66173, 66179, 66191, 66221, 66239, 66271, 66293, 66301, 66337, 66343, 66347, 66359, 66361, 66373, 66377, 66383, 66403, 66413, 66431, 66449, 66457, 66463, 66467, 66491, 66499, 66509, 66523, 66529, 66533, 66541, 66553, 66569, 66571, 66587, 66593, 66601, 66617, 66629, 66643, 66653, 66683, 66697, 66701, 66713, 66721, 66733, 66739, 66749, 66751, 66763, 66791, 66797, 66809, 66821, 66841, 66851, 66853, 66863, 66877, 66883, 66889, 66919, 66923, 66931, 66943, 66947, 66949, 66959, 66973, 66977, 67003, 67021, 67033, 67043, 67049, 67057, 67061, 67073, 67079, 67103, 67121, 67129, 67139, 67141, 67153, 67157, 67169, 67181, 67187, 67189, 67211, 67213, 67217, 67219, 67231, 67247, 67261, 67271, 67273, 67289, 67307, 67339, 67343, 67349, 67369, 67391, 67399, 67409, 67411, 67421, 67427, 67429, 67433, 67447, 67453, 67477, 67481, 67489, 67493, 67499, 67511, 67523, 67531, 67537, 67547, 67559, 67567, 67577, 67579, 67589, 67601, 67607, 67619, 67631, 67651, 67679, 67699, 67709, 67723, 67733, 67741, 67751, 67757, 67759, 67763, 67777, 67783, 67789, 67801, 67807, 67819, 67829, 67843, 67853, 67867, 67883, 67891, 67901, 67927, 67931, 67933, 67939, 67943, 67957, 67961, 67967, 67979, 67987, 67993, 68023, 68041, 68053, 68059, 68071, 68087, 68099, 68111, 68113, 68141, 68147, 68161, 68171, 68207, 68209, 68213, 68219, 68227, 68239, 68261, 68279, 68281, 68311, 68329, 68351, 68371, 68389, 68399, 68437, 68443, 68447, 68449, 68473, 68477, 68483, 68489, 68491, 68501, 68507, 68521, 68531, 68539, 68543, 68567, 68581, 68597, 68611, 68633, 68639, 68659, 68669, 68683, 68687, 68699, 68711, 68713, 68729, 68737, 68743, 68749, 68767, 68771, 68777, 68791, 68813, 68819, 68821, 68863, 68879, 68881, 68891, 68897, 68899, 68903, 68909, 68917, 68927, 68947, 68963, 68993, 69001, 69011, 69019, 69029, 69031, 69061, 69067, 69073, 69109, 69119, 69127, 69143, 69149, 69151, 69163, 69191, 69193, 69197, 69203, 69221, 69233, 69239, 69247, 69257, 69259, 69263, 69313, 69317, 69337, 69341, 69371, 69379, 69383, 69389, 69401, 69403, 69427, 69431, 69439, 69457, 69463, 69467, 69473, 69481, 69491, 69493, 69497, 69499, 69539, 69557, 69593, 69623, 69653, 69661, 69677, 69691, 69697, 69709, 69737, 69739, 69761, 69763, 69767, 69779, 69809, 69821, 69827, 69829, 69833, 69847, 69857, 69859, 69877, 69899, 69911, 69929, 69931, 69941, 69959, 69991, 69997, 70001, 70003, 70009, 70019, 70039, 70051, 70061, 70067, 70079, 70099, 70111, 70117, 70121, 70123, 70139, 70141, 70157, 70163, 70177, 70181, 70183, 70199, 70201, 70207, 70223, 70229, 70237, 70241, 70249, 70271, 70289, 70297, 70309, 70313, 70321, 70327, 70351, 70373, 70379, 70381, 70393, 70423, 70429, 70439, 70451, 70457, 70459, 70481, 70487, 70489, 70501, 70507, 70529, 70537, 70549, 70571, 70573, 70583, 70589, 70607, 70619, 70621, 70627, 70639, 70657, 70663, 70667, 70687, 70709, 70717, 70729, 70753, 70769, 70783, 70793, 70823, 70841, 70843, 70849, 70853, 70867, 70877, 70879, 70891, 70901, 70913, 70919, 70921, 70937, 70949, 70951, 70957, 70969, 70979, 70981, 70991, 70997, 70999, 71011, 71023, 71039, 71059, 71069, 71081, 71089, 71119, 71129, 71143, 71147, 71153, 71161, 71167, 71171, 71191, 71209, 71233, 71237, 71249, 71257, 71261, 71263, 71287, 71293, 71317, 71327, 71329, 71333, 71339, 71341, 71347, 71353, 71359, 71363, 71387, 71389, 71399, 71411, 71413, 71419, 71429, 71437, 71443, 71453, 71471, 71473, 71479, 71483, 71503, 71527, 71537, 71549, 71551, 71563, 71569, 71593, 71597, 71633, 71647, 71663, 71671, 71693, 71699, 71707, 71711, 71713, 71719, 71741, 71761, 71777, 71789, 71807, 71809, 71821, 71837, 71843, 71849, 71861, 71867, 71879, 71881, 71887, 71899, 71909, 71917, 71933, 71941, 71947, 71963, 71971, 71983, 71987, 71993, 71999, 72019, 72031, 72043, 72047, 72053, 72073, 72077, 72089, 72091, 72101, 72103, 72109, 72139, 72161, 72167, 72169, 72173, 72211, 72221, 72223, 72227, 72229, 72251, 72253, 72269, 72271, 72277, 72287, 72307, 72313, 72337, 72341, 72353, 72367, 72379, 72383, 72421, 72431, 72461, 72467, 72469, 72481, 72493, 72497, 72503, 72533, 72547, 72551, 72559, 72577, 72613, 72617, 72623, 72643, 72647, 72649, 72661, 72671, 72673, 72679, 72689, 72701, 72707, 72719, 72727, 72733, 72739, 72763, 72767, 72797, 72817, 72823, 72859, 72869, 72871, 72883, 72889, 72893, 72901, 72907, 72911, 72923, 72931, 72937, 72949, 72953, 72959, 72973, 72977, 72997, 73009, 73013, 73019, 73037, 73039, 73043, 73061, 73063, 73079, 73091, 73121, 73127, 73133, 73141, 73181, 73189, 73237, 73243, 73259, 73277, 73291, 73303, 73309, 73327, 73331, 73351, 73361, 73363, 73369, 73379, 73387, 73417, 73421, 73433, 73453, 73459, 73471, 73477, 73483, 73517, 73523, 73529, 73547, 73553, 73561, 73571, 73583, 73589, 73597, 73607, 73609, 73613, 73637, 73643, 73651, 73673, 73679, 73681, 73693, 73699, 73709, 73721, 73727, 73751, 73757, 73771, 73783, 73819, 73823, 73847, 73849, 73859, 73867, 73877, 73883, 73897, 73907, 73939, 73943, 73951, 73961, 73973, 73999, 74017, 74021, 74027, 74047, 74051, 74071, 74077, 74093, 74099, 74101, 74131, 74143, 74149, 74159, 74161, 74167, 74177, 74189, 74197, 74201, 74203, 74209, 74219, 74231, 74257, 74279, 74287, 74293, 74297, 74311, 74317, 74323, 74353, 74357, 74363, 74377, 74381, 74383, 74411, 74413, 74419, 74441, 74449, 74453, 74471, 74489, 74507, 74509, 74521, 74527, 74531, 74551, 74561, 74567, 74573, 74587, 74597, 74609, 74611, 74623, 74653, 74687, 74699, 74707, 74713, 74717, 74719, 74729, 74731, 74747, 74759, 74761, 74771, 74779, 74797, 74821, 74827, 74831, 74843, 74857, 74861, 74869, 74873, 74887, 74891, 74897, 74903, 74923, 74929, 74933, 74941, 74959, 75011, 75013, 75017, 75029, 75037, 75041, 75079, 75083, 75109, 75133, 75149, 75161, 75167, 75169, 75181, 75193, 75209, 75211, 75217, 75223, 75227, 75239, 75253, 75269, 75277, 75289, 75307, 75323, 75329, 75337, 75347, 75353, 75367, 75377, 75389, 75391, 75401, 75403, 75407, 75431, 75437, 75479, 75503, 75511, 75521, 75527, 75533, 75539, 75541, 75553, 75557, 75571, 75577, 75583, 75611, 75617, 75619, 75629, 75641, 75653, 75659, 75679, 75683, 75689, 75703, 75707, 75709, 75721, 75731, 75743, 75767, 75773, 75781, 75787, 75793, 75797, 75821, 75833, 75853, 75869, 75883, 75913, 75931, 75937, 75941, 75967, 75979, 75983, 75989, 75991, 75997, 76001, 76003, 76031, 76039, 76079, 76081, 76091, 76099, 76103, 76123, 76129, 76147, 76157, 76159, 76163, 76207, 76213, 76231, 76243, 76249, 76253, 76259, 76261, 76283, 76289, 76303, 76333, 76343, 76367, 76369, 76379, 76387, 76403, 76421, 76423, 76441, 76463, 76471, 76481, 76487, 76493, 76507, 76511, 76519, 76537, 76541, 76543, 76561, 76579, 76597, 76603, 76607, 76631, 76649, 76651, 76667, 76673, 76679, 76697, 76717, 76733, 76753, 76757, 76771, 76777, 76781, 76801, 76819, 76829, 76831, 76837, 76847, 76871, 76873, 76883, 76907, 76913, 76919, 76943, 76949, 76961, 76963, 76991, 77003, 77017, 77023, 77029, 77041, 77047, 77069, 77081, 77093, 77101, 77137, 77141, 77153, 77167, 77171, 77191, 77201, 77213, 77237, 77239, 77243, 77249, 77261, 77263, 77267, 77269, 77279, 77291, 77317, 77323, 77339, 77347, 77351, 77359, 77369, 77377, 77383, 77417, 77419, 77431, 77447, 77471, 77477, 77479, 77489, 77491, 77509, 77513, 77521, 77527, 77543, 77549, 77551, 77557, 77563, 77569, 77573, 77587, 77591, 77611, 77617, 77621, 77641, 77647, 77659, 77681, 77687, 77689, 77699, 77711, 77713, 77719, 77723, 77731, 77743, 77747, 77761, 77773, 77783, 77797, 77801, 77813, 77839, 77849, 77863, 77867, 77893, 77899, 77929, 77933, 77951, 77969, 77977, 77983, 77999, 78007, 78017, 78031, 78041, 78049, 78059, 78079, 78101, 78121, 78137, 78139, 78157, 78163, 78167, 78173, 78179, 78191, 78193, 78203, 78229, 78233, 78241, 78259, 78277, 78283, 78301, 78307, 78311, 78317, 78341, 78347, 78367, 78401, 78427, 78437, 78439, 78467, 78479, 78487, 78497, 78509, 78511, 78517, 78539, 78541, 78553, 78569, 78571, 78577, 78583, 78593, 78607, 78623, 78643, 78649, 78653, 78691, 78697, 78707, 78713, 78721, 78737, 78779, 78781, 78787, 78791, 78797, 78803, 78809, 78823, 78839, 78853, 78857, 78877, 78887, 78889, 78893, 78901, 78919, 78929, 78941, 78977, 78979, 78989, 79031, 79039, 79043, 79063, 79087, 79103, 79111, 79133, 79139, 79147, 79151, 79153, 79159, 79181, 79187, 79193, 79201, 79229, 79231, 79241, 79259, 79273, 79279, 79283, 79301, 79309, 79319, 79333, 79337, 79349, 79357, 79367, 79379, 79393, 79397, 79399, 79411, 79423, 79427, 79433, 79451, 79481, 79493, 79531, 79537, 79549, 79559, 79561, 79579, 79589, 79601, 79609, 79613, 79621, 79627, 79631, 79633, 79657, 79669, 79687, 79691, 79693, 79697, 79699, 79757, 79769, 79777, 79801, 79811, 79813, 79817, 79823, 79829, 79841, 79843, 79847, 79861, 79867, 79873, 79889, 79901, 79903, 79907, 79939, 79943, 79967, 79973, 79979, 79987, 79997, 79999, 80021, 80039, 80051, 80071, 80077, 80107, 80111, 80141, 80147, 80149, 80153, 80167, 80173, 80177, 80191, 80207, 80209, 80221, 80231, 80233, 80239, 80251, 80263, 80273, 80279, 80287, 80309, 80317, 80329, 80341, 80347, 80363, 80369, 80387, 80407, 80429, 80447, 80449, 80471, 80473, 80489, 80491, 80513, 80527, 80537, 80557, 80567, 80599, 80603, 80611, 80621, 80627, 80629, 80651, 80657, 80669, 80671, 80677, 80681, 80683, 80687, 80701, 80713, 80737, 80747, 80749, 80761, 80777, 80779, 80783, 80789, 80803, 80809, 80819, 80831, 80833, 80849, 80863, 80897, 80909, 80911, 80917, 80923, 80929, 80933, 80953, 80963, 80989, 81001, 81013, 81017, 81019, 81023, 81031, 81041, 81043, 81047, 81049, 81071, 81077, 81083, 81097, 81101, 81119, 81131, 81157, 81163, 81173, 81181, 81197, 81199, 81203, 81223, 81233, 81239, 81281, 81283, 81293, 81299, 81307, 81331, 81343, 81349, 81353, 81359, 81371, 81373, 81401, 81409, 81421, 81439, 81457, 81463, 81509, 81517, 81527, 81533, 81547, 81551, 81553, 81559, 81563, 81569, 81611, 81619, 81629, 81637, 81647, 81649, 81667, 81671, 81677, 81689, 81701, 81703, 81707, 81727, 81737, 81749, 81761, 81769, 81773, 81799, 81817, 81839, 81847, 81853, 81869, 81883, 81899, 81901, 81919, 81929, 81931, 81937, 81943, 81953, 81967, 81971, 81973, 82003, 82007, 82009, 82013, 82021, 82031, 82037, 82039, 82051, 82067, 82073, 82129, 82139, 82141, 82153, 82163, 82171, 82183, 82189, 82193, 82207, 82217, 82219, 82223, 82231, 82237, 82241, 82261, 82267, 82279, 82301, 82307, 82339, 82349, 82351, 82361, 82373, 82387, 82393, 82421, 82457, 82463, 82469, 82471, 82483, 82487, 82493, 82499, 82507, 82529, 82531, 82549, 82559, 82561, 82567, 82571, 82591, 82601, 82609, 82613, 82619, 82633, 82651, 82657, 82699, 82721, 82723, 82727, 82729, 82757, 82759, 82763, 82781, 82787, 82793, 82799, 82811, 82813, 82837, 82847, 82883, 82889, 82891, 82903, 82913, 82939, 82963, 82981, 82997, 83003, 83009, 83023, 83047, 83059, 83063, 83071, 83077, 83089, 83093, 83101, 83117, 83137, 83177, 83203, 83207, 83219, 83221, 83227, 83231, 83233, 83243, 83257, 83267, 83269, 83273, 83299, 83311, 83339, 83341, 83357, 83383, 83389, 83399, 83401, 83407, 83417, 83423, 83431, 83437, 83443, 83449, 83459, 83471, 83477, 83497, 83537, 83557, 83561, 83563, 83579, 83591, 83597, 83609, 83617, 83621, 83639, 83641, 83653, 83663, 83689, 83701, 83717, 83719, 83737, 83761, 83773, 83777, 83791, 83813, 83833, 83843, 83857, 83869, 83873, 83891, 83903, 83911, 83921, 83933, 83939, 83969, 83983, 83987, 84011, 84017, 84047, 84053, 84059, 84061, 84067, 84089, 84121, 84127, 84131, 84137, 84143, 84163, 84179, 84181, 84191, 84199, 84211, 84221, 84223, 84229, 84239, 84247, 84263, 84299, 84307, 84313, 84317, 84319, 84347, 84349, 84377, 84389, 84391, 84401, 84407, 84421, 84431, 84437, 84443, 84449, 84457, 84463, 84467, 84481, 84499, 84503, 84509, 84521, 84523, 84533, 84551, 84559, 84589, 84629, 84631, 84649, 84653, 84659, 84673, 84691, 84697, 84701, 84713, 84719, 84731, 84737, 84751, 84761, 84787, 84793, 84809, 84811, 84827, 84857, 84859, 84869, 84871, 84913, 84919, 84947, 84961, 84967, 84977, 84979, 84991, 85009, 85021, 85027, 85037, 85049, 85061, 85081, 85087, 85091, 85093, 85103, 85109, 85121, 85133, 85147, 85159, 85193, 85199, 85201, 85213, 85223, 85229, 85237, 85243, 85247, 85259, 85297, 85303, 85313, 85331, 85333, 85361, 85363, 85369, 85381, 85411, 85427, 85429, 85439, 85447, 85451, 85453, 85469, 85487, 85513, 85517, 85523, 85531, 85549, 85571, 85577, 85597, 85601, 85607, 85619, 85621, 85627, 85639, 85643, 85661, 85667, 85669, 85691, 85703, 85711, 85717, 85733, 85751, 85781, 85793, 85817, 85819, 85829, 85831, 85837, 85843, 85847, 85853, 85889, 85903, 85909, 85931, 85933, 85991, 85999, 86011, 86017, 86027, 86029, 86069, 86077, 86083, 86111, 86113, 86117, 86131, 86137, 86143, 86161, 86171, 86179, 86183, 86197, 86201, 86209, 86239, 86243, 86249, 86257, 86263, 86269, 86287, 86291, 86293, 86297, 86311, 86323, 86341, 86351, 86353, 86357, 86369, 86371, 86381, 86389, 86399, 86413, 86423, 86441, 86453, 86461, 86467, 86477, 86491, 86501, 86509, 86531, 86533, 86539, 86561, 86573, 86579, 86587, 86599, 86627, 86629, 86677, 86689, 86693, 86711, 86719, 86729, 86743, 86753, 86767, 86771, 86783, 86813, 86837, 86843, 86851, 86857, 86861, 86869, 86923, 86927, 86929, 86939, 86951, 86959, 86969, 86981, 86993, 87011, 87013, 87037, 87041, 87049, 87071, 87083, 87103, 87107, 87119, 87121, 87133, 87149, 87151, 87179, 87181, 87187, 87211, 87221, 87223, 87251, 87253, 87257, 87277, 87281, 87293, 87299, 87313, 87317, 87323, 87337, 87359, 87383, 87403, 87407, 87421, 87427, 87433, 87443, 87473, 87481, 87491, 87509, 87511, 87517, 87523, 87539, 87541, 87547, 87553, 87557, 87559, 87583, 87587, 87589, 87613, 87623, 87629, 87631, 87641, 87643, 87649, 87671, 87679, 87683, 87691, 87697, 87701, 87719, 87721, 87739, 87743, 87751, 87767, 87793, 87797, 87803, 87811, 87833, 87853, 87869, 87877, 87881, 87887, 87911, 87917, 87931, 87943, 87959, 87961, 87973, 87977, 87991, 88001, 88003, 88007, 88019, 88037, 88069, 88079, 88093, 88117, 88129, 88169, 88177, 88211, 88223, 88237, 88241, 88259, 88261, 88289, 88301, 88321, 88327, 88337, 88339, 88379, 88397, 88411, 88423, 88427, 88463, 88469, 88471, 88493, 88499, 88513, 88523, 88547, 88589, 88591, 88607, 88609, 88643, 88651, 88657, 88661, 88663, 88667, 88681, 88721, 88729, 88741, 88747, 88771, 88789, 88793, 88799, 88801, 88807, 88811, 88813, 88817, 88819, 88843, 88853, 88861, 88867, 88873, 88883, 88897, 88903, 88919, 88937, 88951, 88969, 88993, 88997, 89003, 89009, 89017, 89021, 89041, 89051, 89057, 89069, 89071, 89083, 89087, 89101, 89107, 89113, 89119, 89123, 89137, 89153, 89189, 89203, 89209, 89213, 89227, 89231, 89237, 89261, 89269, 89273, 89293, 89303, 89317, 89329, 89363, 89371, 89381, 89387, 89393, 89399, 89413, 89417, 89431, 89443, 89449, 89459, 89477, 89491, 89501, 89513, 89519, 89521, 89527, 89533, 89561, 89563, 89567, 89591, 89597, 89599, 89603, 89611, 89627, 89633, 89653, 89657, 89659, 89669, 89671, 89681, 89689, 89753, 89759, 89767, 89779, 89783, 89797, 89809, 89819, 89821, 89833, 89839, 89849, 89867, 89891, 89897, 89899, 89909, 89917, 89923, 89939, 89959, 89963, 89977, 89983, 89989, 90001, 90007, 90011, 90017, 90019, 90023, 90031, 90053, 90059, 90067, 90071, 90073, 90089, 90107, 90121, 90127, 90149, 90163, 90173, 90187, 90191, 90197, 90199, 90203, 90217, 90227, 90239, 90247, 90263, 90271, 90281, 90289, 90313, 90353, 90359, 90371, 90373, 90379, 90397, 90401, 90403, 90407, 90437, 90439, 90469, 90473, 90481, 90499, 90511, 90523, 90527, 90529, 90533, 90547, 90583, 90599, 90617, 90619, 90631, 90641, 90647, 90659, 90677, 90679, 90697, 90703, 90709, 90731, 90749, 90787, 90793, 90803, 90821, 90823, 90833, 90841, 90847, 90863, 90887, 90901, 90907, 90911, 90917, 90931, 90947, 90971, 90977, 90989, 90997, 91009, 91019, 91033, 91079, 91081, 91097, 91099, 91121, 91127, 91129, 91139, 91141, 91151, 91153, 91159, 91163, 91183, 91193, 91199, 91229, 91237, 91243, 91249, 91253, 91283, 91291, 91297, 91303, 91309, 91331, 91367, 91369, 91373, 91381, 91387, 91393, 91397, 91411, 91423, 91433, 91453, 91457, 91459, 91463, 91493, 91499, 91513, 91529, 91541, 91571, 91573, 91577, 91583, 91591, 91621, 91631, 91639, 91673, 91691, 91703, 91711, 91733, 91753, 91757, 91771, 91781, 91801, 91807, 91811, 91813, 91823, 91837, 91841, 91867, 91873, 91909, 91921, 91939, 91943, 91951, 91957, 91961, 91967, 91969, 91997, 92003, 92009, 92033, 92041, 92051, 92077, 92083, 92107, 92111, 92119, 92143, 92153, 92173, 92177, 92179, 92189, 92203, 92219, 92221, 92227, 92233, 92237, 92243, 92251, 92269, 92297, 92311, 92317, 92333, 92347, 92353, 92357, 92363, 92369, 92377, 92381, 92383, 92387, 92399, 92401, 92413, 92419, 92431, 92459, 92461, 92467, 92479, 92489, 92503, 92507, 92551, 92557, 92567, 92569, 92581, 92593, 92623, 92627, 92639, 92641, 92647, 92657, 92669, 92671, 92681, 92683, 92693, 92699, 92707, 92717, 92723, 92737, 92753, 92761, 92767, 92779, 92789, 92791, 92801, 92809, 92821, 92831, 92849, 92857, 92861, 92863, 92867, 92893, 92899, 92921, 92927, 92941, 92951, 92957, 92959, 92987, 92993, 93001, 93047, 93053, 93059, 93077, 93083, 93089, 93097, 93103, 93113, 93131, 93133, 93139, 93151, 93169, 93179, 93187, 93199, 93229, 93239, 93241, 93251, 93253, 93257, 93263, 93281, 93283, 93287, 93307, 93319, 93323, 93329, 93337, 93371, 93377, 93383, 93407, 93419, 93427, 93463, 93479, 93481, 93487, 93491, 93493, 93497, 93503, 93523, 93529, 93553, 93557, 93559, 93563, 93581, 93601, 93607, 93629, 93637, 93683, 93701, 93703, 93719, 93739, 93761, 93763, 93787, 93809, 93811, 93827, 93851, 93871, 93887, 93889, 93893, 93901, 93911, 93913, 93923, 93937, 93941, 93949, 93967, 93971, 93979, 93983, 93997, 94007, 94009, 94033, 94049, 94057, 94063, 94079, 94099, 94109, 94111, 94117, 94121, 94151, 94153, 94169, 94201, 94207, 94219, 94229, 94253, 94261, 94273, 94291, 94307, 94309, 94321, 94327, 94331, 94343, 94349, 94351, 94379, 94397, 94399, 94421, 94427, 94433, 94439, 94441, 94447, 94463, 94477, 94483, 94513, 94529, 94531, 94541, 94543, 94547, 94559, 94561, 94573, 94583, 94597, 94603, 94613, 94621, 94649, 94651, 94687, 94693, 94709, 94723, 94727, 94747, 94771, 94777, 94781, 94789, 94793, 94811, 94819, 94823, 94837, 94841, 94847, 94849, 94873, 94889, 94903, 94907, 94933, 94949, 94951, 94961, 94993, 94999, 95003, 95009, 95021, 95027, 95063, 95071, 95083, 95087, 95089, 95093, 95101, 95107, 95111, 95131, 95143, 95153, 95177, 95189, 95191, 95203, 95213, 95219, 95231, 95233, 95239, 95257, 95261, 95267, 95273, 95279, 95287, 95311, 95317, 95327, 95339, 95369, 95383, 95393, 95401, 95413, 95419, 95429, 95441, 95443, 95461, 95467, 95471, 95479, 95483, 95507, 95527, 95531, 95539, 95549, 95561, 95569, 95581, 95597, 95603, 95617, 95621, 95629, 95633, 95651, 95701, 95707, 95713, 95717, 95723, 95731, 95737, 95747, 95773, 95783, 95789, 95791, 95801, 95803, 95813, 95819, 95857, 95869, 95873, 95881, 95891, 95911, 95917, 95923, 95929, 95947, 95957, 95959, 95971, 95987, 95989, 96001, 96013, 96017, 96043, 96053, 96059, 96079, 96097, 96137, 96149, 96157, 96167, 96179, 96181, 96199, 96211, 96221, 96223, 96233, 96259, 96263, 96269, 96281, 96289, 96293, 96323, 96329, 96331, 96337, 96353, 96377, 96401, 96419, 96431, 96443, 96451, 96457, 96461, 96469, 96479, 96487, 96493, 96497, 96517, 96527, 96553, 96557, 96581, 96587, 96589, 96601, 96643, 96661, 96667, 96671, 96697, 96703, 96731, 96737, 96739, 96749, 96757, 96763, 96769, 96779, 96787, 96797, 96799, 96821, 96823, 96827, 96847, 96851, 96857, 96893, 96907, 96911, 96931, 96953, 96959, 96973, 96979, 96989, 96997, 97001, 97003, 97007, 97021, 97039, 97073, 97081, 97103, 97117, 97127, 97151, 97157, 97159, 97169, 97171, 97177, 97187, 97213, 97231, 97241, 97259, 97283, 97301, 97303, 97327, 97367, 97369, 97373, 97379, 97381, 97387, 97397, 97423, 97429, 97441, 97453, 97459, 97463, 97499, 97501, 97511, 97523, 97547, 97549, 97553, 97561, 97571, 97577, 97579, 97583, 97607, 97609, 97613, 97649, 97651, 97673, 97687, 97711, 97729, 97771, 97777, 97787, 97789, 97813, 97829, 97841, 97843, 97847, 97849, 97859, 97861, 97871, 97879, 97883, 97919, 97927, 97931, 97943, 97961, 97967, 97973, 97987, 98009, 98011, 98017, 98041, 98047, 98057, 98081, 98101, 98123, 98129, 98143, 98179, 98207, 98213, 98221, 98227, 98251, 98257, 98269, 98297, 98299, 98317, 98321, 98323, 98327, 98347, 98369, 98377, 98387, 98389, 98407, 98411, 98419, 98429, 98443, 98453, 98459, 98467, 98473, 98479, 98491, 98507, 98519, 98533, 98543, 98561, 98563, 98573, 98597, 98621, 98627, 98639, 98641, 98663, 98669, 98689, 98711, 98713, 98717, 98729, 98731, 98737, 98773, 98779, 98801, 98807, 98809, 98837, 98849, 98867, 98869, 98873, 98887, 98893, 98897, 98899, 98909, 98911, 98927, 98929, 98939, 98947, 98953, 98963, 98981, 98993, 98999, 99013, 99017, 99023, 99041, 99053, 99079, 99083, 99089, 99103, 99109, 99119, 99131, 99133, 99137, 99139, 99149, 99173, 99181, 99191, 99223, 99233, 99241, 99251, 99257, 99259, 99277, 99289, 99317, 99347, 99349, 99367, 99371, 99377, 99391, 99397, 99401, 99409, 99431, 99439, 99469, 99487, 99497, 99523, 99527, 99529, 99551, 99559, 99563, 99571, 99577, 99581, 99607, 99611, 99623, 99643, 99661, 99667, 99679, 99689, 99707, 99709, 99713, 99719, 99721, 99733, 99761, 99767, 99787, 99793, 99809, 99817, 99823, 99829, 99833, 99839, 99859, 99871, 99877, 99881, 99901, 99907, 99923, 99929, 99961, 99971, 99989, 99991, 100003, 100019, 100043, 100049, 100057, 100069, 100103, 100109, 100129, 100151, 100153, 100169, 100183, 100189, 100193, 100207, 100213, 100237, 100267, 100271, 100279, 100291, 100297, 100313, 100333, 100343, 100357, 100361, 100363, 100379, 100391, 100393, 100403, 100411, 100417, 100447, 100459, 100469, 100483, 100493, 100501, 100511, 100517, 100519, 100523, 100537, 100547, 100549, 100559, 100591, 100609, 100613, 100621, 100649, 100669, 100673, 100693, 100699, 100703, 100733, 100741, 100747, 100769, 100787, 100799, 100801, 100811, 100823, 100829, 100847, 100853, 100907, 100913, 100927, 100931, 100937, 100943, 100957, 100981, 100987, 100999, 101009, 101021, 101027, 101051, 101063, 101081, 101089, 101107, 101111, 101113, 101117, 101119, 101141, 101149, 101159, 101161, 101173, 101183, 101197, 101203, 101207, 101209, 101221, 101267, 101273, 101279, 101281, 101287, 101293, 101323, 101333, 101341, 101347, 101359, 101363, 101377, 101383, 101399, 101411, 101419, 101429, 101449, 101467, 101477, 101483, 101489, 101501, 101503, 101513, 101527, 101531, 101533, 101537, 101561, 101573, 101581, 101599, 101603, 101611, 101627, 101641, 101653, 101663, 101681, 101693, 101701, 101719, 101723, 101737, 101741, 101747, 101749, 101771, 101789, 101797, 101807, 101833, 101837, 101839, 101863, 101869, 101873, 101879, 101891, 101917, 101921, 101929, 101939, 101957, 101963, 101977, 101987, 101999, 102001, 102013, 102019, 102023, 102031, 102043, 102059, 102061, 102071, 102077, 102079, 102101, 102103, 102107, 102121, 102139, 102149, 102161, 102181, 102191, 102197, 102199, 102203, 102217, 102229, 102233, 102241, 102251, 102253, 102259, 102293, 102299, 102301, 102317, 102329, 102337, 102359, 102367, 102397, 102407, 102409, 102433, 102437, 102451, 102461, 102481, 102497, 102499, 102503, 102523, 102533, 102539, 102547, 102551, 102559, 102563, 102587, 102593, 102607, 102611, 102643, 102647, 102653, 102667, 102673, 102677, 102679, 102701, 102761, 102763, 102769, 102793, 102797, 102811, 102829, 102841, 102859, 102871, 102877, 102881, 102911, 102913, 102929, 102931, 102953, 102967, 102983, 103001, 103007, 103043, 103049, 103067, 103069, 103079, 103087, 103091, 103093, 103099, 103123, 103141, 103171, 103177, 103183, 103217, 103231, 103237, 103289, 103291, 103307, 103319, 103333, 103349, 103357, 103387, 103391, 103393, 103399, 103409, 103421, 103423, 103451, 103457, 103471, 103483, 103511, 103529, 103549, 103553, 103561, 103567, 103573, 103577, 103583, 103591, 103613, 103619, 103643, 103651, 103657, 103669, 103681, 103687, 103699, 103703, 103723, 103769, 103787, 103801, 103811, 103813, 103837, 103841, 103843, 103867, 103889, 103903, 103913, 103919, 103951, 103963, 103967, 103969, 103979, 103981, 103991, 103993, 103997, 104003, 104009, 104021, 104033, 104047, 104053, 104059, 104087, 104089, 104107, 104113, 104119, 104123, 104147, 104149, 104161, 104173, 104179, 104183, 104207, 104231, 104233, 104239, 104243, 104281, 104287, 104297, 104309, 104311, 104323, 104327, 104347, 104369, 104381, 104383, 104393, 104399, 104417, 104459, 104471, 104473, 104479, 104491, 104513, 104527, 104537, 104543, 104549, 104551, 104561, 104579, 104593, 104597, 104623, 104639, 104651, 104659, 104677, 104681, 104683, 104693, 104701, 104707, 104711, 104717, 104723, 104729 }; } // namespace regina regina-4.96/engine/packet/CMakeLists.txt000644 000765 000024 00000001326 12377774107 020105 0ustar00babstaff000000 000000 # packet # Files to compile SET ( FILES ncontainer npacket npacketlistener npdf nscript ntext nxmlpacketreader nxmlpacketreaders open ) # Prepend folder name FOREACH ( SOURCE_FILE ${FILES} ) SET ( SOURCES ${SOURCES} packet/${SOURCE_FILE}) ENDFOREACH(SOURCE_FILE) # Set the variable in the parent directory SET(SOURCES ${SOURCES} PARENT_SCOPE) if (${REGINA_INSTALL_DEV}) INSTALL(FILES ncontainer.h npacket.h npacketlistener.h npdf.h nscript.h ntext.h nxmlpacketreader.h nxmlpacketreaders.h nxmltreeresolver.h packetregistry.h packetregistry-impl.h packettype.h DESTINATION ${INCLUDEDIR}/packet COMPONENT Development) endif (${REGINA_INSTALL_DEV}) regina-4.96/engine/packet/ncontainer.h000644 000765 000024 00000007723 12377775311 017663 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file packet/ncontainer.h * \brief Contains a packet whose entire life purpose is to contain * other packets. */ #ifndef __NCONTAINER_H #ifndef __DOXYGEN #define __NCONTAINER_H #endif #include "regina-core.h" #include "packet/npacket.h" namespace regina { class NXMLPacketReader; class NContainer; /** * \weakgroup packet * @{ */ /** * Stores information about the container packet. * See the general PacketInfo template notes for further details. * * \ifacespython Not present. */ template <> struct PacketInfo { typedef NContainer Class; inline static const char* name() { return "Container"; } }; /** * A packet that simply contains other packets. Such * a packet contains no real data. */ class REGINA_API NContainer : public NPacket { REGINA_PACKET(NContainer, PACKET_CONTAINER) public: /** * Default constructor. */ NContainer(); virtual void writeTextShort(std::ostream& out) const; static NXMLPacketReader* getXMLReader(NPacket* parent, NXMLTreeResolver& resolver); virtual bool dependsOnParent() const; protected: virtual NPacket* internalClonePacket(NPacket* parent) const; virtual void writeXMLPacketData(std::ostream& out) const; }; /*@}*/ // Inline functions for NContainer inline NContainer::NContainer() { } inline void NContainer::writeTextShort(std::ostream& o) const { o << "Container"; } inline bool NContainer::dependsOnParent() const { return false; } inline NPacket* NContainer::internalClonePacket(NPacket*) const { return new NContainer(); } inline void NContainer::writeXMLPacketData(std::ostream&) const { } } // namespace regina #endif regina-4.96/engine/packet/npacket.cpp000644 000765 000024 00000054420 12377776632 017506 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include #include "engine.h" #include "packet/npacket.h" #include "packet/npacketlistener.h" #include "packet/nscript.h" #include "utilities/base64.h" #include "utilities/xmlutils.h" #include "utilities/zstream.h" namespace regina { NPacket::~NPacket() { inDestructor = true; // Orphan this packet before doing anything else. // The destructor can lead to callbacks for packet listeners, which // might in turn involve tree traversal. It can't be good for // anyone to start querying packets whose destructors are already // being carried out. if (treeParent) makeOrphan(); // Destroy all descendants. // Note that the NPacket destructor now orphans the packet as well. while(firstTreeChild) delete firstTreeChild; // Fire a packet event and unregister all listeners. fireDestructionEvent(); } std::string NPacket::getFullName() const { return getHumanLabel() + " (" + getPacketTypeName() + ")"; } void NPacket::setPacketLabel(const std::string& newLabel) { fireEvent(&NPacketListener::packetToBeRenamed); packetLabel = newLabel; fireEvent(&NPacketListener::packetWasRenamed); } bool NPacket::listen(NPacketListener* listener) { if (! listeners.get()) listeners.reset(new std::set()); listener->packets.insert(this); return listeners->insert(listener).second; } bool NPacket::unlisten(NPacketListener* listener) { if (! listeners.get()) return false; listener->packets.erase(this); return listeners->erase(listener); } NPacket* NPacket::getTreeMatriarch() const { NPacket* p = const_cast(this); while (p->treeParent) p = p->treeParent; return p; } void NPacket::insertChildFirst(NPacket* child) { fireEvent(&NPacketListener::childToBeAdded, child); child->treeParent = this; child->prevTreeSibling = 0; child->nextTreeSibling = firstTreeChild; if (firstTreeChild) { firstTreeChild->prevTreeSibling = child; firstTreeChild = child; } else { firstTreeChild = child; lastTreeChild = child; } fireEvent(&NPacketListener::childWasAdded, child); } void NPacket::insertChildLast(NPacket* child) { fireEvent(&NPacketListener::childToBeAdded, child); child->treeParent = this; child->prevTreeSibling = lastTreeChild; child->nextTreeSibling = 0; if (lastTreeChild) { lastTreeChild->nextTreeSibling = child; lastTreeChild = child; } else { firstTreeChild = child; lastTreeChild = child; } fireEvent(&NPacketListener::childWasAdded, child); } void NPacket::insertChildAfter(NPacket* newChild, NPacket* prevChild) { fireEvent(&NPacketListener::childToBeAdded, newChild); if (prevChild == 0) insertChildFirst(newChild); else { newChild->treeParent = this; newChild->nextTreeSibling = prevChild->nextTreeSibling; newChild->prevTreeSibling = prevChild; prevChild->nextTreeSibling = newChild; if (newChild->nextTreeSibling) newChild->nextTreeSibling->prevTreeSibling = newChild; else lastTreeChild = newChild; } fireEvent(&NPacketListener::childWasAdded, newChild); } void NPacket::makeOrphan() { if (! treeParent) return; NPacket* oldParent = treeParent; oldParent->fireEvent(&NPacketListener::childToBeRemoved, this, oldParent->inDestructor); if (treeParent->firstTreeChild == this) treeParent->firstTreeChild = nextTreeSibling; else prevTreeSibling->nextTreeSibling = nextTreeSibling; if (treeParent->lastTreeChild == this) treeParent->lastTreeChild = prevTreeSibling; else nextTreeSibling->prevTreeSibling = prevTreeSibling; treeParent = 0; oldParent->fireEvent(&NPacketListener::childWasRemoved, this, oldParent->inDestructor); } void NPacket::reparent(NPacket* newParent, bool first) { if (treeParent) makeOrphan(); if (first) newParent->insertChildFirst(this); else newParent->insertChildLast(this); } void NPacket::moveUp(unsigned steps) { if (steps == 0 || ! prevTreeSibling) return; // This packet is not the first packet in the child list. treeParent->fireEvent(&NPacketListener::childrenToBeReordered); NPacket* prev = prevTreeSibling; while (prev && steps) { prev = prev->prevTreeSibling; steps--; } // Pull us out of the tree. if (nextTreeSibling) nextTreeSibling->prevTreeSibling = prevTreeSibling; else treeParent->lastTreeChild = prevTreeSibling; prevTreeSibling->nextTreeSibling = nextTreeSibling; // Reinsert ourselves into the tree. prevTreeSibling = prev; nextTreeSibling = (prev ? prev->nextTreeSibling : treeParent->firstTreeChild); nextTreeSibling->prevTreeSibling = this; if (prev) prev->nextTreeSibling = this; else treeParent->firstTreeChild = this; treeParent->fireEvent(&NPacketListener::childrenWereReordered); } void NPacket::moveDown(unsigned steps) { if (steps == 0 || ! nextTreeSibling) return; // This packet is not the last packet in the child list. treeParent->fireEvent(&NPacketListener::childrenToBeReordered); NPacket* next = nextTreeSibling; while (next && steps) { next = next->nextTreeSibling; steps--; } // Pull us out of the tree. if (prevTreeSibling) prevTreeSibling->nextTreeSibling = nextTreeSibling; else treeParent->firstTreeChild = nextTreeSibling; nextTreeSibling->prevTreeSibling = prevTreeSibling; // Reinsert ourselves into the tree. nextTreeSibling = next; prevTreeSibling = (next ? next->prevTreeSibling : treeParent->lastTreeChild); prevTreeSibling->nextTreeSibling = this; if (next) next->prevTreeSibling = this; else treeParent->lastTreeChild = this; treeParent->fireEvent(&NPacketListener::childrenWereReordered); } void NPacket::moveToFirst() { if (! prevTreeSibling) return; // This packet is not the first packet in the child list. treeParent->fireEvent(&NPacketListener::childrenToBeReordered); // Pull us out of the tree. if (nextTreeSibling) nextTreeSibling->prevTreeSibling = prevTreeSibling; else treeParent->lastTreeChild = prevTreeSibling; prevTreeSibling->nextTreeSibling = nextTreeSibling; // Reinsert ourselves into the tree. treeParent->firstTreeChild->prevTreeSibling = this; nextTreeSibling = treeParent->firstTreeChild; prevTreeSibling = 0; treeParent->firstTreeChild = this; treeParent->fireEvent(&NPacketListener::childrenWereReordered); } void NPacket::moveToLast() { if (! nextTreeSibling) return; // This packet is not the last packet in the child list. treeParent->fireEvent(&NPacketListener::childrenToBeReordered); // Pull us out of the tree. if (prevTreeSibling) prevTreeSibling->nextTreeSibling = nextTreeSibling; else treeParent->firstTreeChild = nextTreeSibling; nextTreeSibling->prevTreeSibling = prevTreeSibling; // Reinsert ourselves into the tree. treeParent->lastTreeChild->nextTreeSibling = this; prevTreeSibling = treeParent->lastTreeChild; nextTreeSibling = 0; treeParent->lastTreeChild = this; treeParent->fireEvent(&NPacketListener::childrenWereReordered); } void NPacket::sortChildren() { // Run through the packets from largest to smallest, moving each to // the beginning of the child list in turn. NPacket* endpoint = 0; NPacket* current; NPacket* largest; fireEvent(&NPacketListener::childrenToBeReordered); while (1) { // Put current at the beginning of the clump of yet-unsorted children. if (! endpoint) current = firstTreeChild; else current = endpoint->nextTreeSibling; if (! current) break; // Find the largest amongst the yet-unsorted children. largest = current; current = current->nextTreeSibling; while (current) { if (current->getPacketLabel() > largest->getPacketLabel()) largest = current; current = current->nextTreeSibling; } // Move the largest to the front of the list. if (firstTreeChild != largest) { // We know that largest has a previous sibling. largest->prevTreeSibling->nextTreeSibling = largest->nextTreeSibling; if (largest->nextTreeSibling) largest->nextTreeSibling->prevTreeSibling = largest->prevTreeSibling; else lastTreeChild = largest->prevTreeSibling; firstTreeChild->prevTreeSibling = largest; largest->nextTreeSibling = firstTreeChild; largest->prevTreeSibling = 0; firstTreeChild = largest; } if (! endpoint) endpoint = largest; } fireEvent(&NPacketListener::childrenWereReordered); } void NPacket::swapWithNextSibling() { if (! nextTreeSibling) return; treeParent->fireEvent(&NPacketListener::childrenToBeReordered); if (prevTreeSibling) prevTreeSibling->nextTreeSibling = nextTreeSibling; else treeParent->firstTreeChild = nextTreeSibling; if (nextTreeSibling->nextTreeSibling) nextTreeSibling->nextTreeSibling->prevTreeSibling = this; else treeParent->lastTreeChild = this; NPacket* other = nextTreeSibling; nextTreeSibling = other->nextTreeSibling; other->prevTreeSibling = prevTreeSibling; prevTreeSibling = other; other->nextTreeSibling = this; treeParent->fireEvent(&NPacketListener::childrenWereReordered); } NPacket* NPacket::nextTreePacket() { if (firstTreeChild) return firstTreeChild; if (nextTreeSibling) return nextTreeSibling; NPacket* tmp = treeParent; while (tmp) { if (tmp->nextTreeSibling) return tmp->nextTreeSibling; tmp = tmp->treeParent; } return 0; } const NPacket* NPacket::nextTreePacket() const { if (firstTreeChild) return firstTreeChild; if (nextTreeSibling) return nextTreeSibling; NPacket* tmp = treeParent; while (tmp) { if (tmp->nextTreeSibling) return tmp->nextTreeSibling; tmp = tmp->treeParent; } return 0; } NPacket* NPacket::firstTreePacket(const std::string& type) { if (getPacketTypeName() == type) return this; return nextTreePacket(type); } const NPacket* NPacket::firstTreePacket(const std::string& type) const { if (getPacketTypeName() == type) return this; return nextTreePacket(type); } NPacket* NPacket::nextTreePacket(const std::string& type) { NPacket* ans = nextTreePacket(); while (ans) { if (ans->getPacketTypeName() == type) return ans; ans = ans->nextTreePacket(); } return 0; } const NPacket* NPacket::nextTreePacket(const std::string& type) const { const NPacket* ans = nextTreePacket(); while (ans) { if (ans->getPacketTypeName() == type) return ans; ans = ans->nextTreePacket(); } return 0; } NPacket* NPacket::findPacketLabel(const std::string& label) { if (packetLabel == label) return this; NPacket* tmp = firstTreeChild; NPacket* ans; while (tmp) { ans = tmp->findPacketLabel(label); if (ans) return ans; tmp = tmp->nextTreeSibling; } return 0; } const NPacket* NPacket::findPacketLabel(const std::string& label) const { if (packetLabel == label) return this; NPacket* tmp = firstTreeChild; NPacket* ans; while (tmp) { ans = tmp->findPacketLabel(label); if (ans) return ans; tmp = tmp->nextTreeSibling; } return 0; } unsigned NPacket::levelsDownTo(const NPacket* descendant) const { unsigned levels = 0; while (descendant != this) { descendant = descendant->treeParent; levels++; } return levels; } bool NPacket::isGrandparentOf(const NPacket* descendant) const { while (descendant) { if (descendant == this) return true; descendant = descendant->treeParent; } return false; } unsigned long NPacket::getNumberOfChildren() const { unsigned long tot = 0; for (NPacket* tmp = firstTreeChild; tmp; tmp = tmp->nextTreeSibling) tot++; return tot; } unsigned long NPacket::getTotalTreeSize() const { unsigned long tot = 1; for (NPacket* tmp = firstTreeChild; tmp; tmp = tmp->nextTreeSibling) tot += tmp->getTotalTreeSize(); return tot; } bool NPacket::isPacketEditable() const { NPacket* tmp = firstTreeChild; while (tmp) { if (tmp->dependsOnParent()) return false; tmp = tmp->nextTreeSibling; } return true; } NPacket* NPacket::clone(bool cloneDescendants, bool end) const { if (treeParent == 0) return 0; NPacket* ans = internalClonePacket(treeParent); ans->setPacketLabel(packetLabel + " - clone"); if (end) treeParent->insertChildLast(ans); else treeParent->insertChildAfter(ans, const_cast(this)); if (cloneDescendants) internalCloneDescendants(ans); return ans; } bool NPacket::save(const char* filename, bool compressed) const { if (compressed) { CompressionStream out(filename); if (! out) return false; writeXMLFile(out); } else { std::ofstream out(filename); if (! out) return false; writeXMLFile(out); } return true; } void NPacket::internalCloneDescendants(NPacket* parent) const { NPacket* child = firstTreeChild; NPacket* clone; while (child) { clone = child->internalClonePacket(parent); clone->setPacketLabel(child->packetLabel + " - clone"); parent->insertChildLast(clone); child->internalCloneDescendants(clone); child = child->nextTreeSibling; } } std::string NPacket::makeUniqueLabel(const std::string& base) const { const NPacket* topLevel = this; while (topLevel->treeParent) topLevel = topLevel->treeParent; if (! topLevel->findPacketLabel(base)) return base; std::string ans; unsigned long extraInt = 2; while(1) { std::ostringstream out; out << ' ' << extraInt; ans = base + out.str(); if (! topLevel->findPacketLabel(ans)) return ans; else extraInt++; } return ""; } bool NPacket::makeUniqueLabels(NPacket* reference) { NPacket* tree[3]; if (reference) { tree[0] = reference; tree[1] = this; tree[2] = 0; } else { tree[0] = this; tree[1] = 0; } std::set labels; int whichTree; NPacket* p; std::string label, newLabel; unsigned long extraInt; bool changed = false; for (whichTree = 0; tree[whichTree]; whichTree++) for (p = tree[whichTree]; p; p = p->nextTreePacket()) { label = p->getPacketLabel(); if (! labels.insert(label).second) { extraInt = 1; do { extraInt++; std::ostringstream out; out << ' ' << extraInt; newLabel = label + out.str(); } while (! labels.insert(newLabel).second); p->setPacketLabel(newLabel); changed = true; } } return changed; } bool NPacket::addTag(const std::string& tag) { fireEvent(&NPacketListener::packetToBeRenamed); if (! tags.get()) tags.reset(new std::set()); bool ans = tags->insert(tag).second; fireEvent(&NPacketListener::packetWasRenamed); return ans; } bool NPacket::removeTag(const std::string& tag) { if (! tags.get()) return false; fireEvent(&NPacketListener::packetToBeRenamed); bool ans = tags->erase(tag); fireEvent(&NPacketListener::packetWasRenamed); return ans; } void NPacket::removeAllTags() { if (tags.get() && ! tags->empty()) { fireEvent(&NPacketListener::packetToBeRenamed); tags->clear(); fireEvent(&NPacketListener::packetWasRenamed); } } void NPacket::writeXMLFile(std::ostream& out) const { // Write the XML header. out << "\n"; // Write the regina data opening tag including engine version. out << "\n"; // Write the packet tree. writeXMLPacketTree(out); // Write the regina data closing tag. out << "\n"; } void NPacket::fireEvent(void (NPacketListener::*event)(NPacket*)) { if (listeners.get()) { std::set::const_iterator it = listeners->begin(); while (it != listeners->end()) ((*it++)->*event)(this); } } void NPacket::fireEvent(void (NPacketListener::*event)(NPacket*, NPacket*), NPacket* arg2) { if (listeners.get()) { std::set::const_iterator it = listeners->begin(); while (it != listeners->end()) ((*it++)->*event)(this, arg2); } } void NPacket::fireEvent(void (NPacketListener::*event)(NPacket*, NPacket*, bool), NPacket* arg2, bool arg3) { if (listeners.get()) { std::set::const_iterator it = listeners->begin(); while (it != listeners->end()) ((*it++)->*event)(this, arg2, arg3); } } void NPacket::fireDestructionEvent() { if (listeners.get()) { std::set::const_iterator it; NPacketListener* tmp; while (! listeners->empty()) { it = listeners->begin(); tmp = *it; // Unregister *before* we fire the event for each listener. // If we have a listener that deletes itself (or other listeners), // we don't want things to get nasty. listeners->erase(it); tmp->packets.erase(this); tmp->packetToBeDestroyed(this); } } } void NPacket::writeXMLPacketTree(std::ostream& out) const { using regina::xml::xmlEncodeSpecialChars; using regina::xml::xmlEncodeComment; // Write the packet opening tag including packet label and type. out << "::const_iterator it = listeners->begin(); it != listeners->end(); ++it) if (dynamic_cast(*it)) { out << "\tid=\"" << internalID() << "\"\n"; break; } out << "\tparent=\""; if (treeParent) out << xmlEncodeSpecialChars(treeParent->packetLabel); out << "\">\n"; // Write the internal packet data. writeXMLPacketData(out); // Write any packet tags. if (tags.get()) for (std::set::const_iterator it = tags->begin(); it != tags->end(); it++) out << " \n"; // Write the child packets. for (NPacket* p = firstTreeChild; p; p = p->nextTreeSibling) p->writeXMLPacketTree(out); // Write the packet closing tag. out << " \n"; } std::string NPacket::internalID() const { char ptrAsBytes[sizeof(NPacket*)]; *(reinterpret_cast(&ptrAsBytes)) = this; char* id = 0; base64Encode(ptrAsBytes, sizeof(NPacket*), &id); std::string ans = id; delete[] id; return ans; } } // namespace regina regina-4.96/engine/packet/npacket.h000644 000765 000024 00000153322 12377775312 017146 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file packet/npacket.h * \brief Deals with packets of information that form the working data * objects. */ #ifndef __NPACKET_H #ifndef __DOXYGEN #define __NPACKET_H #endif #include #include #include #include "regina-core.h" #include "shareableobject.h" #include "packet/npacketlistener.h" #include "packet/packettype.h" #include "utilities/boostutils.h" namespace regina { class NPacketListener; class NXMLPacketReader; class NXMLTreeResolver; /** * \addtogroup packet Basic Packet Types * Packet administration and some basic packet types. * @{ */ /** * A template that stores information about a particular type of packet. * Much of this information is given in the form of compile-time constants * and types. * * To iterate through cases for a given value of PacketInfo that is not * known until runtime, see the various forPacket() routines defined in * packetregistry.h. * * At a bare minimum, each specialisation of this template must provide: * * - a typedef \a Class that represents the corresponding NPacket subclass; * - a static function name() that returns a C-style string giving the * human-readable name of the packet type. * * \ifacespython Not present. */ template struct PacketInfo; /** * Defines various constants, types and virtual functions for a * subclass of NPacket. * * Every subclass of NPacket \a must include REGINA_PACKET at the beginning * of the class definition. * * This macro provides the class with: * * - a compile-time enum constant \a packetType, which is equal to the * corresponding PacketType constant; * - declarations and implementations of the virtual functions * NPacket::getPacketType() and NPacket::getPacketTypeName(). * * @param class_ the name of this descendant class of NSurfaceFilter. * @param id the corresponding PacketType constant. */ #define REGINA_PACKET(class_, id) \ public: \ enum { packetType = id }; \ inline virtual PacketType getPacketType() const { \ return id; \ } \ inline virtual std::string getPacketTypeName() const { \ return PacketInfo::name(); \ } /** * Represents a packet of information that may be individually edited or * operated upon. Packets are stored in a dependency tree, * where child packets fit within the context of (or otherwise * cannot live without) parent packets. * * When deriving classes from NPacket: *
    *
  • A new value must be added to the PacketType enum in packettype.h * to represent the new packet type.
  • *
  • The file packetregistry-impl.h must be updated to reflect the new * packet type (the file itself contains instructions on how to do * this).
  • *
  • A corresponding specialisation of PacketInfo<> must be defined, * typically in the same header as the new packet class.
  • *
  • The macro REGINA_PACKET must be added to the beginning of the new * packet class. This will declare and define various constants, typedefs * and virtual functions (see the REGINA_PACKET macro documentation for * details). *
  • All abstract functions must be implemented, except for those * already provided by REGINA_PACKET.
  • *
  • A public function * static NXMLPacketReader* getXMLReader(NPacket* parent, * NXMLTreeResolver& resolver) * must be declared and implemented. See the notes for getXMLReader() * for further details.
  • *
  • Whenever the contents of the packet are changed, a local * ChangeEventSpan must be declared on the stack to notify listeners of * the change.
  • *
* * Note that external objects can listen for events on packets, such as * when packets are changed or about to be destroyed. See the * NPacketListener class notes for details. * * \todo \feature Provide automatic name selection/specification upon * child packet insertion. */ class REGINA_API NPacket : public ShareableObject { private: std::string packetLabel; /**< The unique label for this individual packet of information. */ NPacket* treeParent; /**< Parent packet in the tree structure (0 if none). */ NPacket* firstTreeChild; /**< First child packet in the tree structure (0 if none). */ NPacket* lastTreeChild; /**< Last child packet in the tree structure (0 if none). */ NPacket* prevTreeSibling; /**< Previous sibling packet in the tree structure (0 if none). */ NPacket* nextTreeSibling; /**< Next sibling packet in the tree structure (0 if none). */ std::auto_ptr > tags; /**< The set of all tags associated with this packet. */ std::auto_ptr > listeners; /**< All objects listening for events on this packet. */ unsigned changeEventSpans; /**< The number of change event spans currently registered. Change events will only be fired when this count is zero. */ bool inDestructor; /**< Have we entered the packet destructor? */ public: /** * \name Constructors and Destructors */ /*@{*/ /** * Constructor that inserts the new packet into the * overall tree structure. The new packet will be inserted as * the last child of the given parent, and will be initialised * with no children of its own. * * Note that NPacket is an abstract class and cannot be * instantiated directly. * * \ifacespython Not present. * * @param parent the parent beneath which to insert this packet, * or 0 if this packet is to be the matriarch of a new tree. */ NPacket(NPacket* parent = 0); /** * Destructor that also orphans this packet and destroys * all of its descendants. */ virtual ~NPacket(); /*@}*/ /** * \name Packet Identification */ /*@{*/ /** * Returns the unique integer ID representing this type of packet. * This is the same for all packets of this class. * * @return the packet type ID. */ virtual PacketType getPacketType() const = 0; /** * Returns an English name for this type of packet. * An example is \c NTriangulation. * This is the same for all packets of this class. * * @return the packet type name. */ virtual std::string getPacketTypeName() const = 0; /** * Returns the label associated with this individual packet. * An example is \c MyTriangulation. * Each individual packet in the overall tree structure must * have a unique label. * * @return this individual packet's label. */ const std::string& getPacketLabel() const; /** * Returns the label associated with this individual packet, * adjusted if necessary for human-readable output. * * In particular, if the packet has no label assigned then this * routine will return "(no label)", not the empty string. * * \warning The method by which this routine adjusts packet labels * is subject to change in future versions of Regina. * * @return this individual packet's label. */ std::string getHumanLabel() const; /** * Sets the label associated with this individual packet. * * \pre No other packet in the overall tree * structure has the same label. * * @param newLabel the new label to give this packet. */ void setPacketLabel(const std::string& newLabel); /** * Returns a descriptive text string for the packet. * The string is of the form label (packet-type). * * The packet label will be adjusted for human-readable output * according to the behaviour of getHumanLabel(). * * @return the descriptive text string. */ std::string getFullName() const; /** * Returns a new label that cannot be found anywhere in the * entire tree structure. This packet need not be the tree * matriarch; this routine will search the entire tree to which * this packet belongs. * * The new label will consist of the given base, possibly * followed by a space and a number. * * \deprecated This routine is deprecated, since (as of Regina 4.95) * packet labels in a data file are no longer required to be distinct. * * @param base a string upon which the new label will be based. * @return a new unique label. */ std::string makeUniqueLabel(const std::string& base) const; /** * Ensures that all packet labels in both this and the given * packet tree combined are distinct. If two packets have the * same label, one will be renamed by adding a space and a number. * * Packets in the given packet tree will be given priority over * the labels; that is, if a packet in this tree has the same * label as a packet in the given tree, it will be the packet in * this tree that is renamed. * * The given packet tree may be \c null, in which case only this * tree will be examined. * * \deprecated This routine is deprecated, since (as of Regina 4.95) * packet labels in a data file are no longer required to be distinct. * * \pre This and the given packet belong to different packet * trees, and are each matriarchs in their respective trees. * * @param reference the packet tree with which to compare this * tree. * @return \c true if and only if any of the packets were * relabelled. */ bool makeUniqueLabels(NPacket* reference); /*@}*/ /** * \name Tags */ /*@{*/ /** * Determines whether this packet has the given associated tag. * * Each packet can have an arbitrary set of string tags associated * with it. The tags are not used by this calculation engine; the * feature is provided for whatever use a developer or user chooses * to make of it. * * Tags are case-sensitive. Tags associated with a single packet * must be distinct, i.e., a particular tag cannot be associated * more than once with the same packet. * * @param tag the tag to search for. * @return \c true if the given tag is found, \c false otherwise. */ bool hasTag(const std::string& tag) const; /** * Determines whether this packet has any associated tags at all. * * Each packet can have an arbitrary set of string tags associated * with it. The tags are not used by this calculation engine; the * feature is provided for whatever use a developer or user chooses * to make of it. * * Tags are case-sensitive. Tags associated with a single packet * must be distinct, i.e., a particular tag cannot be associated * more than once with the same packet. * * @return \c true if this packet has any tags, \c false otherwise. */ bool hasTags() const; /** * Associates the given tag with this packet. * * Each packet can have an arbitrary set of string tags associated * with it. The tags are not used by this calculation engine; the * feature is provided for whatever use a developer or user chooses * to make of it. * * Tags are case-sensitive. Tags associated with a single packet * must be distinct, i.e., a particular tag cannot be associated * more than once with the same packet. * * \pre The given tag is not the empty string. * * @param tag the tag to add. * @return \c true if the given tag was successfully added, * or \c false if the given tag was already present beforehand. */ bool addTag(const std::string& tag); /** * Removes the association of the given tag with this packet. * * Each packet can have an arbitrary set of string tags associated * with it. The tags are not used by this calculation engine; the * feature is provided for whatever use a developer or user chooses * to make of it. * * Tags are case-sensitive. Tags associated with a single packet * must be distinct, i.e., a particular tag cannot be associated * more than once with the same packet. * * @param tag the tag to remove. * @return \c true if the given tag was removed, or \c false if the * given tag was not actually associated with this packet. */ bool removeTag(const std::string& tag); /** * Removes all associated tags from this packet. * * Each packet can have an arbitrary set of string tags associated * with it. The tags are not used by this calculation engine; the * feature is provided for whatever use a developer or user chooses * to make of it. * * Tags are case-sensitive. Tags associated with a single packet * must be distinct, i.e., a particular tag cannot be associated * more than once with the same packet. */ void removeAllTags(); /** * Returns the set of all tags associated with this packet. * * Each packet can have an arbitrary set of string tags associated * with it. The tags are not used by this calculation engine; the * feature is provided for whatever use a developer or user chooses * to make of it. * * Tags are case-sensitive. Tags associated with a single packet * must be distinct, i.e., a particular tag cannot be associated * more than once with the same packet. * * \ifacespython This routine returns a python list of strings. * * @return the set of all tags associated with this packet. */ const std::set& getTags() const; /*@}*/ /** * \name Event Handling */ /*@{*/ /** * Registers the given packet listener to listen for events on * this packet. See the NPacketListener class notes for * details. * * \ifacespython Not present. * * @param listener the listener to register. * @return \c true if the given listener was successfully registered, * or \c false if the given listener was already registered * beforehand. */ bool listen(NPacketListener* listener); /** * Determines whether the given packet listener is currently * listening for events on this packet. See the NPacketListener * class notes for details. * * \ifacespython Not present. * * @param listener the listener to search for. * @return \c true if the given listener is currently registered * with this packet, or \c false otherwise. */ bool isListening(NPacketListener* listener); /** * Unregisters the given packet listener so that it no longer * listens for events on this packet. See the NPacketListener * class notes for details. * * \ifacespython Not present. * * @param listener the listener to unregister. * @return \c true if the given listener was successfully unregistered, * or \c false if the given listener was not registered in the * first place. */ bool unlisten(NPacketListener* listener); /*@}*/ /** * \name Tree Queries */ /*@{*/ /** * Determines the parent packet in the tree structure. * * This routine takes small constant time. * * @return the parent packet, or 0 if there is none. */ NPacket* getTreeParent() const; /** * Determines the first child of this packet in the tree * structure. * * This routine takes small constant time. * * @return the first child packet, or 0 if there is none. */ NPacket* getFirstTreeChild() const; /** * Determines the last child of this packet in the tree * structure. * * This routine takes small constant time. * * @return the last child packet, or 0 if there is none. */ NPacket* getLastTreeChild() const; /** * Determines the next sibling of this packet in the tree * structure. This is the child of the parent that follows this * packet. * * This routine takes small constant time. * * @return the next sibling of this packet, or 0 if there is * none. */ NPacket* getNextTreeSibling() const; /** * Determines the previous sibling of this packet in the tree * structure. This is the child of the parent that precedes * this packet. * * This routine takes small constant time. * * @return the previous sibling of this packet, or 0 if there is * none. */ NPacket* getPrevTreeSibling() const; /** * Determines the matriarch (the root) of the tree to which this * packet belongs. * * @return the matriarch of the packet tree. */ NPacket* getTreeMatriarch() const; /** * Counts the number of levels between this packet and its given * descendant in the tree structure. If \c descendant is this * packet, the number of levels is zero. * * \pre This packet is equal to \c descendant, or * can be obtained from \c descendant using only child-to-parent * steps. * * @param descendant the packet whose relationship with this * packet we are examining. * @return the number of levels difference. */ unsigned levelsDownTo(const NPacket* descendant) const; /** * Counts the number of levels between this packet and its given * ancestor in the tree structure. If \c ancestor is this * packet, the number of levels is zero. * * \pre This packet is equal to \c ancestor, or * can be obtained from \c ancestor using only parent-to-child * steps. * * @param ancestor the packet whose relationship with this * packet we are examining. * @return the number of levels difference. */ unsigned levelsUpTo(const NPacket* ancestor) const; /** * Determines if this packet is equal to or an ancestor of * the given packet in the tree structure. * * @param descendant the other packet whose relationships we are * examining. * @return \c true if and only if this packet is equal to or an * ancestor of \c descendant. */ bool isGrandparentOf(const NPacket* descendant) const; /** * Returns the number of immediate children of this packet. * Grandchildren and so on are not counted. * * @return the number of immediate children. */ unsigned long getNumberOfChildren() const; /** * Returns the total number of descendants of this packet. This * includes children, grandchildren and so on. This packet is not * included in the count. * * @return the total number of descendants. */ unsigned long getNumberOfDescendants() const; /** * Determines the total number of packets in the tree or subtree * for which this packet is matriarch. This packet is included * in the count. * * @return the total tree or subtree size. */ unsigned long getTotalTreeSize() const; /*@}*/ /** * \name Tree Manipulation */ /*@{*/ /** * Inserts the given packet as the first child of this packet. * * This routine takes small constant time. * * \pre The given child has no parent packet. * \pre This packet is not a descendant of the given child. * * \ifacespython Since this packet takes ownership of the given * child packet, the python object containing the given child * packet becomes a null object and should no longer be used. * See reparent() for a way of avoiding these problems in some cases. * * @param child the child to insert. */ void insertChildFirst(NPacket* child); /** * Inserts the given packet as the last child of this packet. * * This routine takes small constant time. * * \pre The given child has no parent packet. * \pre This packet is not a descendant of the given child. * * \ifacespython Since this packet takes ownership of the given * child packet, the python object containing the given child * packet becomes a null object and should no longer be used. * See reparent() for a way of avoiding these problems in some cases. * * @param child the child to insert. */ void insertChildLast(NPacket* child); /** * Inserts the given packet as a child of this packet at the * given location in this packet's child list. * * This routine takes small constant time. * * \pre Parameter \a newChild has no parent packet. * \pre Parameter \a prevChild is already a child of this packet. * \pre This packet is not a descendant of \a newChild. * * \ifacespython Since this packet takes ownership of the given * child packet, the python object containing the given child * packet becomes a null object and should no longer be used. * See reparent() for a way of avoiding these problems in some cases. * * @param newChild the child to insert. * @param prevChild the preexisting child of this packet after * which \a newChild will be inserted, or 0 if \a newChild * is to be the first child of this packet. */ void insertChildAfter(NPacket* newChild, NPacket* prevChild); /** * Cuts this packet away from its parent in the tree structure * and instead makes it matriarch of its own tree. The tree * information for both this packet and its parent will be * updated. * * This routine takes small constant time. * * \pre This packet has a parent. * \pre This packet does not depend on its parent; see * dependsOnParent() for details. * * \ifacespython As of Regina 4.6.1, this routine returns the packet * itself, and the ownership of this packet becomes the responsibility * of whoever takes this return value. In particular, if you call * makeOrphan() and ignore the return value then the entire * packet subtree is automatically destroyed. The reason for * this behaviour is to avoid memory leaks where subtrees are * orphaned and then silently forgotten. */ void makeOrphan(); /** * Cuts this packet away from its parent in the tree structure, * and inserts it as a child of the given packet instead. * * This routine is essentially a combination of makeOrphan() * followed by either insertChildFirst() or insertChildLast(). * * This routine takes small constant time. It is safe to use * regardless of whether this packet has a parent or not. * * \pre This packet does not depend on its parent; see * dependsOnParent() for details. * \pre The given parent is not a descendant of this packet. * * \ifacespython This routine is much simpler than combinations of * makeOrphan() and insertChildFirst() / insertChildLast(), since * there are no unpleasant ownership issues to deal with. * However, if this packet currently has no parent then the ownership * issues are unavoidable; in this case reparent() will do nothing, * and one of the insertChild...() routines must be used instead. * * @param newParent the new parent of this packet, i.e., the * packet beneath which this packet will be inserted. * @param first \c true if this packet should be inserted as the * first child of the given parent, or \c false (the default) if * it should be inserted as the last child. */ void reparent(NPacket* newParent, bool first = false); /** * Swaps this packet with its next sibling in the sequence of * children beneath their common parent packet. Calling this * routine is equivalent to calling moveDown(). * * This routine takes small constant time. * * If this packet has no next sibling then this routine does * nothing. */ void swapWithNextSibling(); /** * Moves this packet the given number of steps towards the * beginning of its sibling list. If the number of steps is * larger than the greatest possible movement, the packet will * be moved to the very beginning of its sibling list. * * This routine takes time proportional to the number of steps. * * \pre The given number of steps is strictly positive. */ void moveUp(unsigned steps = 1); /** * Moves this packet the given number of steps towards the * end of its sibling list. If the number of steps is * larger than the greatest possible movement, the packet will * be moved to the very end of its sibling list. * * This routine takes time proportional to the number of steps. * * \pre The given number of steps is strictly positive. */ void moveDown(unsigned steps = 1); /** * Moves this packet to be the first in its sibling list. * * This routine takes small constant time. */ void moveToFirst(); /** * Moves this packet to be the last in its sibling list. * * This routine takes small constant time. */ void moveToLast(); /** * Sorts the immediate children of this packet according to * their packet labels. Note that this routine is not * recursive (for instance, grandchildren will not be sorted * within each child packet). * * This routine takes quadratic time in the number of * immediate children (and it's slow quadratic at that). */ void sortChildren(); /*@}*/ /** * \name Searching and Iterating */ /*@{*/ /** * Finds the next packet after this in a complete depth-first * iteration of the entire tree structure to which this packet * belongs. Note that this packet need not be the tree * matriarch. * * A parent packet is always reached before its children. The * tree matriarch will be the first packet visited in a complete * depth-first iteration. * * @return the next packet, or 0 if this is the last packet in * such an iteration. */ NPacket* nextTreePacket(); /** * Finds the next packet after this in a complete depth-first * iteration of the entire tree structure to which this packet * belongs. Note that this packet need not be the tree * matriarch. * * A parent packet is always reached before its children. The * tree matriarch will be the first packet visited in a complete * depth-first iteration. * * @return the next packet, or 0 if this is the last packet in * such an iteration. */ const NPacket* nextTreePacket() const; /** * Finds the first packet of the requested type in a complete * depth-first iteration of the tree structure. * Note that this packet must be the matriarch of the * entire tree. * * A parent packet is always reached before its children. The * tree matriarch will be the first packet visited in a complete * depth-first iteration. * * @param type the type of packet to search for, as returned by * getPacketTypeName(). Note that string comparisons are case * sensitive. * @return the first such packet, or 0 if there are no packets of * the requested type. */ NPacket* firstTreePacket(const std::string& type); /** * Finds the first packet of the requested type in a complete * depth-first iteration of the tree structure. * Note that this packet must be the matriarch of the * entire tree. * * A parent packet is always reached before its children. The * tree matriarch will be the first packet visited in a complete * depth-first iteration. * * @param type the type of packet to search for, as returned by * getPacketTypeName(). Note that string comparisons are case * sensitive. * @return the first such packet, or 0 if there are no packets of * the requested type. */ const NPacket* firstTreePacket(const std::string& type) const; /** * Finds the next packet after this of the requested type in a * complete depth-first iteration of the entire tree structure. * Note that this packet need not be the tree matriarch. * The order of tree searching is described in * firstTreePacket(). * * @param type the type of packet to search for, as returned by * getPacketTypeName(). Note that string comparisons are case * sensitive. * @return the next such packet, or 0 if this is the last packet * of the requested type in such an iteration. */ NPacket* nextTreePacket(const std::string& type); /** * Finds the next packet after this of the requested type in a * complete depth-first iteration of the entire tree structure. * Note that this packet need not be the tree matriarch. * The order of tree searching is described in * firstTreePacket(). * * @param type the type of packet to search for, as returned by * getPacketTypeName(). Note that string comparisons are case * sensitive. * @return the next such packet, or 0 if this is the last packet * of the requested type in such an iteration. */ const NPacket* nextTreePacket(const std::string& type) const; /** * Finds the packet with the requested label in the tree or * subtree for which this packet is matriarch. Note that label * comparisons are case sensitive. * * @param label the label to search for. * @return the packet with the requested label, or 0 if there is * no such packet. */ NPacket* findPacketLabel(const std::string& label); /** * Finds the packet with the requested label in the tree or * subtree for which this packet is matriarch. Note that label * comparisons are case sensitive. * * @param label the label to search for. * @return the packet with the requested label, or 0 if there is * no such packet. */ const NPacket* findPacketLabel(const std::string& label) const; /*@}*/ /** * \name Packet Dependencies */ /*@{*/ /** * Determines if this packet depends upon its parent. * This is true if the parent cannot be altered without * invalidating or otherwise upsetting this packet. * * @return \c true if and only if this packet depends on * its parent. */ virtual bool dependsOnParent() const = 0; /** * Determines whether this packet can be altered without * invalidating or otherwise upsetting any of its immediate * children. Descendants further down the packet tree are not * (and should not need to be) considered. * * @return \c true if and only if this packet may be edited. */ bool isPacketEditable() const; /*@}*/ /** * \name Cloning */ /*@{*/ /** * Clones this packet (and possibly its descendants), assigns to it * a suitable unused label and * inserts the clone into the tree as a sibling of this packet. * * Note that any string tags associated with this packet will * \e not be cloned. * * If this packet has no parent in the tree structure, no clone * will be created and 0 will be returned. * * @param cloneDescendants \c true if the descendants of this * packet should also be cloned and inserted as descendants of * the new packet. If this is passed as \c false (the default), * only this packet will be cloned. * @param end \c true if the new packet should be inserted at * the end of the parent's list of children (the default), or * \c false if the new packet should be inserted as the sibling * immediately after this packet. * @return the newly inserted packet, or 0 if this packet has no * parent. */ NPacket* clone(bool cloneDescendants = false, bool end = true) const; /*@}*/ /** * \name File I/O */ /*@{*/ /** * Saves the subtree rooted at this packet to the given Regina * data file, using Regina's native XML file format. The XML * file may be optionally compressed (Regina can happily read both * compressed and uncompressed XML). * * This is the preferred way of saving a Regina data file. * Typically this will be called from the root of the packet * tree, which will save the entire packet tree to file. * * \pre The given packet does not depend on its parent. * * \i18n This routine makes no assumptions about the * \ref i18n "character encoding" used in the given file \e name, * and simply passes it through unchanged to low-level C/C++ file I/O * routines. The \e contents of the file will be written usign UTF-8. * * @param filename the pathname of the file to write to. * @param compressed \c true if the XML data should be compressed, * or \c false if it should be written as plain text. * @return \c true if and only if the file was successfully written. */ bool save(const char* filename, bool compressed = true) const; /** * Writes the subtree rooted at this packet to the given output * stream in Regina's native XML file format. Ths is similar to * calling save(), except that (i) the user has a more flexible * choice of output stream, and (ii) the XML will always be * written in plain text (i.e., it will not be compressed). * * If you simply wish to save your data to a file on the * filesystem, you should call save() instead. * * Typically this will be called from the root of the packet tree, * which will write the entire packet tree to the output stream. * * The output from this routine cannot be used as a piece of an * XML file; it must be the entire XML file. For a piece of an * XML file, see routine writeXMLPacketTree() instead. * * \pre This packet does not depend upon its parent. * * \ifacespython Not present. * * @param out the output stream to which the XML data file should * be written. */ void writeXMLFile(std::ostream& out) const; /** * Returns a unique string ID that identifies this packet. * * The user has no control over this ID, and it is not human * readable. It is guaranteed to remain fixed throughout * the lifetime of the program for a given packet, and it is * guaranteed not to clash with the ID of any other packet. * * If you change the contents of a packet, its ID will not change. * * If you clone a packet, the new clone will receive a different ID. * If you save and then load a packet to/from file, the ID will change. * These behaviours are necessary to ensure that IDs remain unique * (since, for instance, you could load several copies of the same * data file into memory simultaneously). * * The ID is implemented as an encoding of the underlying C++ pointer. * This encoding is subject to change in later versions of Regina. * * @return a unique ID that identifies this packet. */ std::string internalID() const; /*@}*/ /** * Returns a newly created XML element reader that will read the * contents of a single XML packet element. You may assume that * the packet to be read is of the same type as the class in which * you are implementing this routine. * * The XML element reader should read exactly what * writeXMLPacketData() writes, and vice versa. * * \a parent represents the packet which will become the new * packet's parent in the tree structure, and may be assumed to * have already been read from the file. This information is * for reference only, and does not need to be used. The XML * element reader can either insert or not insert the new packet * beneath \a parent in the tree structure as it pleases. Note * however that \a parent will be 0 if the new packet is to * become a tree matriarch. * * If the new packet needs to store pointers to other packets that * might not have been read yet (such as a script packet that * needs pointers to its variables), then it should queue a new * NXMLTreeResolutionTask to the given NXMLTreeResolver. After the * complete data file has been read, NXMLTreeResolver::resolve() * will run all of its queued tasks, at which point the new packet can * resolve any dangling references. * * This routine is not actually provided for NPacket itself, but * must be declared and implemented for every packet subclass that * will be instantiated. * * \ifacespython Not present. * * @param parent the packet which will become the new packet's * parent in the tree structure, or 0 if the new packet is to be * tree matriarch. * @param resolver the master resolver that will be used to fix * dangling packet references after the entire XML file has been read. * @return the newly created XML element reader. */ #ifdef __DOXYGEN static NXMLPacketReader* getXMLReader(NPacket* parent, NXMLTreeResolver& resolver); #endif /** * An object that facilitates firing packetToBeChanged() and * packetWasChanged() events. * * Objects of this type should be created on the stack before * data within a packet is changed. On creation, this object * will fire a NPacketListener::packetToBeChanged() event to all * registered listeners. On destruction (i.e., when the object * goes out of scope), it will fire a * NPacketListener::packetWasChanged() event. * * It may be the case that several objects of this type all * exist at the same time for the same packet. In this case, only * the outermost object will fire events; that is, only the first * object to be constructed will fire * NPacketListener::packetToBeChanged(), and only the last * object to be destroyed will fire * NPacketListener::packetWasChanged(). This is because the * "inner" ChangeEventSpan objects earlier represent smaller events * that are part of a larger suite of changes. * * If you are writing code that makes a large number of changes * to a packet, it is highly recommended that you declare a * ChangeEventSpan at the beginning of your code. This will ensure * that listeners only receive one pair of events for the * entire change set, instead of many events representing each * individual modification. */ class ChangeEventSpan : public regina::boost::noncopyable { private: NPacket* packet_; /**< The packet for which change events are fired. */ public: /** * Creates a new change event object for the given * packet. * * If this is the only ChangeEventSpan currently in existence * for the given packet, this constructor will call * NPacketListener::packetToBeChanged() for all * registered listeners for the given packet. * * @param packet the packet whose data is about to change. */ ChangeEventSpan(NPacket* packet); /** * Destroys this change event object. * * If this is the only ChangeEventSpan currently in existence * for the given packet, this destructor will call * NPacketListener::packetWasChanged() for all * registered listeners for the given packet. */ ~ChangeEventSpan(); }; /** * A deprecated typedef for ChangeEventSpan. * * \deprecated ChangeEventSpan is now the correct way to fire a * "packet changed" event. The class ChangeEventSpan is similar * to the old ChangeEventBlock except that it fires both * NPacketListener::packetToBeChanged() and * NPacketListener::packetWasChanged() (on construction and * destruction respectively), and the old boolean argument * \a fireOnDestruction is gone (events are now fired always). */ typedef ChangeEventSpan ChangeEventBlock; protected: /** * Makes a newly allocated copy of this packet. * This routine should not insert the new packet into the * tree structure, clone the packet's associated tags or give the * packet a label. It should also not clone any descendants of * this packet. * * You may assume that the new packet will eventually be * inserted into the tree beneath either the same parent as this * packet or a clone of that parent. * * @param parent the parent beneath which the new packet will * eventually be inserted. * @return the newly allocated packet. */ virtual NPacket* internalClonePacket(NPacket* parent) const = 0; /** * Writes a chunk of XML containing the subtree with this packet * as matriarch. This is the preferred way of writing a packet * tree to file. * * The output from this routine is only a piece of XML; it * should not be used as a complete XML file. For a complete * XML file, see routine writeXMLFile() instead. * * @param out the output stream to which the XML should be written. */ void writeXMLPacketTree(std::ostream& out) const; /** * Writes a chunk of XML containing the data for this packet * only. * * You may assume that the packet opening tag (including * the packet type and label) has already been written, and that * all child packets followed by the corresponding packet closing * tag will be written immediately after this routine is called. * This routine need only write the internal data stored in * this specific packet. * * @param out the output stream to which the XML should be written. */ virtual void writeXMLPacketData(std::ostream& out) const = 0; private: /** * Clones the descendants of this packet and inserts them as * descendants of the given parent. The entire descendant tree * will be cloned recursively, and suitable labels will be * assigned to the new clones. * * \pre The given parent is a clone of this packet. * * @param parent the parent beneath which the descendant clones * will be inserted. */ void internalCloneDescendants(NPacket* parent) const; /** * Calls the given NPacketListener event for all registered * packet listeners. The first argument to the event function * will be this packet. * * Calling this routine is better than iterating through listeners * manually, since it behaves correctly even if listeners unregister * themselves as they handle the event. * * @param event the member function of NPacketListener to be called * for each listener. */ void fireEvent(void (NPacketListener::*event)(NPacket*)); /** * Calls the given NPacketListener event for all registered * packet listeners. The first argument to the event function * will be this packet. * * Calling this routine is better than iterating through listeners * manually, since it behaves correctly even if listeners unregister * themselves as they handle the event. * * @param event the member function of NPacketListener to be called * for each listener. * @param arg2 the second argument to pass to the event function. */ void fireEvent(void (NPacketListener::*event)(NPacket*, NPacket*), NPacket* arg2); /** * Calls the given NPacketListener event for all registered * packet listeners. The first argument to the event function * will be this packet * * Calling this routine is better than iterating through listeners * manually, since it behaves correctly even if listeners unregister * themselves as they handle the event. * * @param event the member function of NPacketListener to be called * for each listener. * @param arg2 the second argument to pass to the event function. * @param arg3 the third argument to pass to the event function. */ void fireEvent(void (NPacketListener::*event)(NPacket*, NPacket*, bool), NPacket* arg2, bool arg3); /** * Calls NPacketListener::packetToBeDestroyed() for all registered * packet listeners. * * This routine unregisters each listener just before it calls * packetToBeDestroyed() for that listener. * * Calling this routine is better than iterating through listeners * manually, since it behaves correctly even if listeners unregister * themselves or even destroy themselves and/or other listeners as * they handle the event. */ void fireDestructionEvent(); }; /** * Reads a Regina data file, and returns the corresponding packet tree. * This uses Regina's native XML file format; it does not matter whether * the XML file is compressed or uncompressed. * * If the file could not be opened or the top-level packet in the tree * could not be read, this routine will return 0. If some packet deeper * within the tree could not be read then that particular packet (and * its descendants, if any) will simply be ignored. * * \i18n This routine makes no assumptions about the * \ref i18n "character encoding" used in the given file \e name, and simply * passes it through unchanged to low-level C/C++ file I/O routines. * * @param filename the pathname of the file to read from. * @return the packet tree read from file, or 0 on error (as explained above). */ REGINA_API NPacket* open(const char* filename); /*@}*/ // Inline functions for NPacket inline NPacket::NPacket(NPacket* parent) : firstTreeChild(0), lastTreeChild(0), prevTreeSibling(0), nextTreeSibling(0), changeEventSpans(0), inDestructor(false) { if (parent) parent->insertChildLast(this); else treeParent = 0; } inline const std::string& NPacket::getPacketLabel() const { return packetLabel; } inline std::string NPacket::getHumanLabel() const { if (packetLabel.empty()) return "(no label)"; return packetLabel; } inline bool NPacket::hasTag(const std::string& tag) const { if (! tags.get()) return false; return tags->count(tag); } inline bool NPacket::hasTags() const { if (! tags.get()) return false; return (! tags->empty()); } inline const std::set& NPacket::getTags() const { if (! tags.get()) const_cast(this)->tags.reset(new std::set()); return *tags; } inline bool NPacket::isListening(NPacketListener* listener) { if (! listeners.get()) return false; return listeners->count(listener); } inline NPacket* NPacket::getTreeParent() const { return treeParent; } inline NPacket* NPacket::getFirstTreeChild() const { return firstTreeChild; } inline NPacket* NPacket::getLastTreeChild() const { return lastTreeChild; } inline NPacket* NPacket::getPrevTreeSibling() const { return prevTreeSibling; } inline NPacket* NPacket::getNextTreeSibling() const { return nextTreeSibling; } inline unsigned NPacket::levelsUpTo(const NPacket* ancestor) const { return ancestor->levelsDownTo(this); } inline unsigned long NPacket::getNumberOfDescendants() const { return getTotalTreeSize() - 1; } inline NPacket::ChangeEventSpan::ChangeEventSpan(NPacket* packet) : packet_(packet) { if (! packet_->changeEventSpans) packet_->fireEvent(&NPacketListener::packetToBeChanged); packet_->changeEventSpans++; } inline NPacket::ChangeEventSpan::~ChangeEventSpan() { packet_->changeEventSpans--; if (! packet_->changeEventSpans) packet_->fireEvent(&NPacketListener::packetWasChanged); } } // namespace regina #endif regina-4.96/engine/packet/npacketlistener.cpp000644 000765 000024 00000005751 12377776633 021260 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "packet/npacket.h" #include "packet/npacketlistener.h" namespace regina { NPacketListener::~NPacketListener() { unregisterFromAllPackets(); } void NPacketListener::unregisterFromAllPackets() { std::set::iterator it, next; it = packets.begin(); next = it; while (it != packets.end()) { // INV: next == it. // Step forwards before we actually deregister (*it), since // the deregistration will remove (*it) from the set and // invalidate the iterator. next++; // This deregistration removes (*it) from the set, but other // iterators (i.e., next) are not invalidated. (*it)->unlisten(this); it = next; } } } // namespace regina regina-4.96/engine/packet/npacketlistener.h000644 000765 000024 00000032057 12377775314 020717 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file packet/npacketlistener.h * \brief Deals with objects that can listen for packet events. */ #ifndef __NPACKETLISTENER_H #ifndef __DOXYGEN #define __NPACKETLISTENER_H #endif #include #include "regina-core.h" namespace regina { class NPacket; /** * \weakgroup packet * @{ */ /** * An object that can be registered to listen for packet events. * * A packet listener can be registered to listen for events on a * packet by calling NPacket::listen(). * * Each time that one of the events listed in this class occurs, * the packet will call the appropriate routine for all registered * packet listeners. * * These events come in future/past pairs: packetToBeChanged() and * packetWasChanged(), childToBeAdded() and childWasAdded(), and so on. * These event pairs are mutually exclusive: any event will * cause at most one pair of routines to be called for each listener. For * instance, if a packet is renamed then packetToBeRenamed() and * packetWasRenamed() will be called but packetToBeChanged() and * packetWasChanged() will not. * * As a special case, when a packet is destroyed there is only the future * event packetToBeDestroyed() with no matching "past" event, since \e after * the packet has been destroyed the set of listeners is no longer available. * * No guarantees are made as to the order in which the different packet * listeners are notified of an event. * * When a listener is destroyed, it is automatically unregistered * from any packets to which it is currently listening. Similarly, when * a packet is destroyed all listeners are automatically unregistered. * * When using multiple threads, there are restrictions upon what any thread * other than the main thread may do. If these restrictions are properly * adhered to, packet listeners may assume that no routines other than * childWasAdded() will be called from a non-main thread. Of course it is * up to the multithreading code to ensure that these restrictions are in * fact met; see the NThread class notes for further information. * * \warning If the multithreading restrictions noted above are \e not * adhered to, this can result in the GUI crashing within either Qt or * Xlib. Again, see the NThread class notes for further information. * * \ifacespython Not present. */ class REGINA_API NPacketListener { private: std::set packets; /**< The set of packets upon which this object is currently listening. */ public: /** * \name Constructors and Destructors */ /*@{*/ /** * Destroys this listener. This listener will be unregistered * from any packets to which it is currently listening. */ virtual ~NPacketListener(); /*@}*/ /** * \name Packet Listener Interface */ /*@{*/ /** * Unregisters this listener from any packets to which it is * currently listening. */ void unregisterFromAllPackets(); /** * Called before the contents of the packet are to be changed. * Once the contents are changed, packetWasChanged() will be * called also. * * The default implementation of this routine is to do nothing. * * @param packet the packet being listened to. */ virtual void packetToBeChanged(NPacket* packet); /** * Called after the contents of the packet have been changed. * Before the contents are changed, packetToBeChanged() will be * called also. * * The default implementation of this routine is to do nothing. * * @param packet the packet being listened to. */ virtual void packetWasChanged(NPacket* packet); /** * Called before the packet label or tags are to be changed. * Once the label or tags are changed, packetWasRenamed() will be * called also. * * The default implementation of this routine is to do nothing. * * @param packet the packet being listened to. */ virtual void packetToBeRenamed(NPacket* packet); /** * Called after the packet label or tags have been changed. * Before the label or tags are changed, packetToBeRenamed() will be * called also. * * The default implementation of this routine is to do nothing. * * @param packet the packet being listened to. */ virtual void packetWasRenamed(NPacket* packet); /** * Called before the packet is about to be destroyed. Note that * there is no matching function called \e after the * packet is destroyed, since the set of listeners will no * longer be available at that stage. * * When an entire packet subtree is to be destroyed, child packets * will notify their listeners of the impending destruction * before parent packets will. * * Note that the packet will forcibly unregister this listener * immediately \e before packetToBeDestroyed() is called, to avoid * any unpleasant consequences if this listener should also try to * unregister itself. This means that, by the time this routine is * called, this listener will no longer be registered with the * packet in question (and any attempt to unregister it again * will be harmless). * * The default implementation of this routine is to do nothing. * * @param packet the packet being listened to. */ virtual void packetToBeDestroyed(NPacket* packet); /** * Called before a child packet is to be inserted directly beneath * the packet. * Once the child is removed, childWasAdded() will be * called also. * * The default implementation of this routine is to do nothing. * * @param packet the packet being listened to. * @param child the child packet to be added. */ virtual void childToBeAdded(NPacket* packet, NPacket* child); /** * Called after a child packet has been inserted directly beneath * the packet. * Before this child is added, childToBeAdded() will be * called also. * * The default implementation of this routine is to do nothing. * * @param packet the packet being listened to. * @param child the child packet that was added. */ virtual void childWasAdded(NPacket* packet, NPacket* child); /** * Called before a child packet is to be removed from directly beneath * the packet. Note that the child packet may be about to be * destroyed (although this destruction will not have happened yet). * Once the child is removed, childWasRemoved() will be * called also. * * Note also that this packet (the parent) may have already * entered its destructor (which removes and destroys all child * packets as a matter of course). In this situation it may be * unsafe to query or update this packet, and so the third argument * \a inParentDestructor is provided to indicate such a situation. * * The default implementation of this routine is to do nothing. * * @param packet the packet being listened to. * @param child the child packet to be removed. * @param inParentDestructor set to \c true if the parent packet * is in fact being destroyed, and the child was simply removed * as part of the standard subtree destruction. */ virtual void childToBeRemoved(NPacket* packet, NPacket* child, bool inParentDestructor); /** * Called after a child packet has been removed from directly beneath * the packet. Note that the child packet may be about to be * destroyed (although this destruction will not have happened yet). * Before this child is removed, childToBeRemoved() will be * called also. * * Note also that this packet (the parent) may have already * entered its destructor (which removes and destroys all child * packets as a matter of course). In this situation it may be * unsafe to query or update this packet, and so the third argument * \a inParentDestructor is provided to indicate such a situation. * * The default implementation of this routine is to do nothing. * * @param packet the packet being listened to. * @param child the child packet that was removed. * @param inParentDestructor set to \c true if the parent packet * is in fact being destroyed, and the child was simply removed * as part of the standard subtree destruction. */ virtual void childWasRemoved(NPacket* packet, NPacket* child, bool inParentDestructor); /** * Called before the child packets directly beneath the packet * are to be reordered. * Once the reordering is done, childrenWereReordered() will be * called also. * * The default implementation of this routine is to do nothing. * * @param packet the packet being listened to. */ virtual void childrenToBeReordered(NPacket* packet); /** * Called after the child packets directly beneath the packet * have been reordered. * Before this reordering is done, childrenToBeReordered() will be * called also. * * The default implementation of this routine is to do nothing. * * @param packet the packet being listened to. */ virtual void childrenWereReordered(NPacket* packet); /*@}*/ /** * Allow packets to automatically deregister listeners as they are * destroyed. */ friend class NPacket; }; /*@}*/ // Inline functions for NPacketListener inline void NPacketListener::packetToBeChanged(NPacket*) { } inline void NPacketListener::packetWasChanged(NPacket*) { } inline void NPacketListener::packetToBeRenamed(NPacket*) { } inline void NPacketListener::packetWasRenamed(NPacket*) { } inline void NPacketListener::packetToBeDestroyed(NPacket*) { } inline void NPacketListener::childToBeAdded(NPacket*, NPacket*) { } inline void NPacketListener::childWasAdded(NPacket*, NPacket*) { } inline void NPacketListener::childToBeRemoved(NPacket*, NPacket*, bool) { } inline void NPacketListener::childWasRemoved(NPacket*, NPacket*, bool) { } inline void NPacketListener::childrenToBeReordered(NPacket*) { } inline void NPacketListener::childrenWereReordered(NPacket*) { } } // namespace regina #endif regina-4.96/engine/packet/npdf.cpp000644 000765 000024 00000012446 12400000215 016746 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include "packet/npdf.h" #include "utilities/base64.h" #include "utilities/xmlutils.h" #define BASE64_LINE_LEN 76 namespace regina { NPDF::NPDF(const char* filename) : data_(0), size_(0), alloc_(OWN_NEW) { // Use FILE* so we can call fstat(). // Open the file. FILE* in = fopen(filename, "rb"); if (! in) return; // Get the file size. struct stat s; if (fstat(fileno(in), &s)) { fclose(in); return; } size_t size = s.st_size; if (size == 0) { fclose(in); return; } // Read the file contents. char* data = new char[size]; if (fread(data, 1, size, in) != size) { fclose(in); delete[] data; return; } // Is there more to the file that we weren't expecting? char c; if (fread(&c, 1, 1, in) > 0) { fclose(in); delete[] data; return; } // All good! fclose(in); data_ = data; size_ = size; } void NPDF::reset() { ChangeEventSpan span(this); if (data_) { if (alloc_ == OWN_MALLOC) ::free(data_); else delete[] data_; } data_ = 0; size_ = 0; alloc_ = OWN_NEW; } void NPDF::reset(char* data, size_t size, OwnershipPolicy alloc) { ChangeEventSpan span(this); // Out with the old data. if (data_) { if (alloc_ == OWN_MALLOC) ::free(data_); else delete[] data_; } // In with the new. if (data) { data_ = data; size_ = size; if (alloc == DEEP_COPY) { data_ = static_cast(::malloc(size_)); ::memcpy(data_, static_cast(data), size_); alloc_ = OWN_MALLOC; } else alloc_ = alloc; } else { data_ = 0; size_ = 0; alloc_ = OWN_NEW; } } bool NPDF::savePDF(const char* filename) const { if (! data_) return false; // Use FILE* for symmetry with the PDF load routine. // Open the file. FILE* out = fopen(filename, "wb"); if (!out) return false; // Is there anything to write? if (fwrite(data_, 1, size_, out) != size_) { fclose(out); return false; } // All done. fclose(out); return true; } void NPDF::writeXMLPacketData(std::ostream& out) const { if (! data_) { // We have an empty PDF packet. out << " \n"; return; } char* base64; size_t len64 = base64Encode(data_, size_, &base64); if (! base64) { out << " \n"; return; } out << " \n"; const char* pos = base64; while (len64 > BASE64_LINE_LEN) { out.write(pos, BASE64_LINE_LEN); out << std::endl; pos += BASE64_LINE_LEN; len64 -= BASE64_LINE_LEN; } if (len64 > 0) { out.write(pos, len64); out << std::endl; } out << " \n"; delete[] base64; } } // namespace regina regina-4.96/engine/packet/npdf.h000644 000765 000024 00000026316 12377775315 016455 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file packet/npdf.h * \brief A packet that contains a PDF document. */ #ifndef __NPDF_H #ifndef __DOXYGEN #define __NPDF_H #endif #include #include #include "regina-core.h" #include "packet/npacket.h" namespace regina { class NXMLPacketReader; class NPDF; /** * \weakgroup packet * @{ */ /** * Stores information about the PDF packet. * See the general PacketInfo template notes for further details. * * \ifacespython Not present. */ template <> struct PacketInfo { typedef NPDF Class; inline static const char* name() { return "PDF"; } }; /** * A packet that can hold a PDF document. * * This packet may or may not contain a PDF document at any given time. * This can be tested by calling isNull(), and can be changed by calling * reset(). */ class REGINA_API NPDF : public NPacket { REGINA_PACKET(NPDF, PACKET_PDF) public: /** * Describes how a PDF packet should claim ownership of a block * of binary data. * * \ifacespython Not present. */ enum OwnershipPolicy { /** * The packet should claim ownership of the block, and * should assume that it was allocated using \a malloc(). */ OWN_MALLOC, /** * The packet should claim ownership of the block, and * should assume that it was allocated using \c new[]. */ OWN_NEW, /** * The packet should not claim ownership of the block, but * should instead make its own deep copy. */ DEEP_COPY }; private: char* data_; /**< The binary data of the PDF document that is stored in this packet, or 0 if no PDF document is currently stored. */ size_t size_; /**< The size of the binary data in bytes, or 0 if no PDF document is currently stored. */ OwnershipPolicy alloc_; /**< Describes how the binary data (if any) was allocated; this must be either \a OWN_MALLOC or \a OWN_NEW. */ public: /** * Creates a PDF packet with no document stored. */ NPDF(); /** * Creates a PDF packet with data read from the given PDF file. * * This routine does not check whether the given file \e looks * like a PDF document; it simply loads the file contents blindly. * * If the file could not be read or is empty, then no PDF document will * be stored in this packet. You can test this by calling isNull(). * * \i18n This routine makes no assumptions about the * \ref i18n "character encoding" used in the given file \e name, and * simply passes it through unchanged to low-level C/C++ file I/O * routines. * * @param filename the filename of the PDF document to read. */ NPDF(const char* filename); /** * Creates a packet to store the given PDF data. * * The \a data array must contain a full PDF document as a * block of binary data. * * The \a alloc argument shows if/how this packet claims ownership of * the data. In particular, unless \a alloc is \a DEEP_COPY, this * packet will claim ownership of the given data block and will * deallocate it when the packet is destroyed. If \a alloc is * \a DEEP_COPY then the given block of data will not be modified in * any way. * * It is possible to pass a null pointer as the data array, in * which case the new packet will have no PDF document stored * (so isNull() will return \c true). * * \ifacespython Not present. * * @param data the block of binary data that forms the PDF document, * or \c null if no document is to be stored. * @param size the number of bytes in this block of binary data; * if actual data is passed (i.e., \a data is not \c null) then * this must be strictly positive. * @param alloc describes if/how this packet should claim ownership * of the given block of data; see the notes above for details. */ NPDF(char* data, size_t size, OwnershipPolicy alloc); /** * Destroys this PDF packet and deallocates data if required. */ ~NPDF(); /** * Determines whether this packet is currently holding a PDF * document. * * @return \c true if and only if this packet is holding a * PDF document. */ bool isNull() const; /** * Returns a pointer to the block of raw data that forms this * PDF document. The number of bytes in this block can be found * by calling size(). * * If no PDF document is currently stored (i.e., isNull() * returns \c true), then this routine will return a null pointer. * * \ifacespython Not present. * * @return the raw PDF data. */ const char* data() const; /** * Returns the size of this PDF document in bytes. * * If no PDF document is currently stored (i.e., isNull() * returns \c true), then this routine will return zero. * * @return the number of bytes. */ size_t size() const; /** * Empties this PDF packet so that no document is stored. * After calling this routine, isNull() will return \c true. * * The old data will be deallocated if required. */ void reset(); /** * Refills this PDF packet with the given PDF data. * The old data will be deallocated if required. * * This routine behaves like the class constructor; see the * constructor documentation for details. * * \ifacespython Not present. * * @param data the block of binary data that forms the new PDF * document, or \c null if no document is to be stored. * @param size the number of bytes in this new block of binary data; * if actual data is passed (i.e., \a data is not \c null) then * this must be strictly positive. * @param alloc describes if/how this packet should claim ownership * of the given block of data; see the notes above for details. */ void reset(char* data, size_t size, OwnershipPolicy alloc); /** * Saves this PDF document to the given file in PDF format. * * This routine does not check whether the contents of this * packet \e look like a PDF document; it simply writes them * blindly to the filesystem. * * If no PDF document is currently stored in this PDF packet * (i.e., isNull() returns \c true), then this routine will do * nothing and simply return \c false. * * \i18n This routine makes no assumptions about the * \ref i18n "character encoding" used in the given file \e name, and * simply passes it unchanged to low-level C/C++ file I/O routines. * * @param filename the name of the PDF file to write. * @return \c true if the file was successfully written, or * \c false otherwise. */ bool savePDF(const char* filename) const; virtual void writeTextShort(std::ostream& out) const; static NXMLPacketReader* getXMLReader(NPacket* parent, NXMLTreeResolver& resolver); virtual bool dependsOnParent() const; protected: virtual NPacket* internalClonePacket(NPacket* parent) const; virtual void writeXMLPacketData(std::ostream& out) const; }; /*@}*/ // Inline functions for NPDF inline NPDF::NPDF() : data_(0), size_(0), alloc_(OWN_NEW) { } inline NPDF::NPDF(char* data, size_t size, OwnershipPolicy alloc) : data_(data), size_(size), alloc_(alloc) { if (alloc_ == DEEP_COPY) { if (data_) { data_ = static_cast(::malloc(size_)); ::memcpy(data_, static_cast(data), size_); } alloc_ = OWN_MALLOC; } else if (! data_) size_ = 0; } inline NPDF::~NPDF() { if (data_) { if (alloc_ == OWN_MALLOC) ::free(data_); else delete[] data_; } } inline const char* NPDF::data() const { return data_; } inline bool NPDF::isNull() const { return ! data_; } inline size_t NPDF::size() const { return size_; } inline void NPDF::writeTextShort(std::ostream& o) const { o << "PDF packet (" << size_ << (size_ == 1 ? " byte)" : " bytes)"); } inline bool NPDF::dependsOnParent() const { return false; } inline NPacket* NPDF::internalClonePacket(NPacket*) const { return new NPDF(data_, size_, DEEP_COPY); } } // namespace regina #endif regina-4.96/engine/packet/nscript.cpp000644 000765 000024 00000014570 12377776640 017544 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "packet/nscript.h" #include "utilities/xmlutils.h" #define PROP_VARIABLE 1 namespace regina { const std::string& NScript::getVariableName(unsigned long index) const { std::map::const_iterator it = variables.begin(); advance(it, index); return (*it).first; } NPacket* NScript::getVariableValue(unsigned long index) const { std::map::const_iterator it = variables.begin(); advance(it, index); return (*it).second; } NPacket* NScript::getVariableValue(const std::string& name) const { std::map::const_iterator it = variables.find(name); if (it == variables.end()) return 0; return (*it).second; } long NScript::getVariableIndex(const std::string& name) const { std::map::const_iterator it = variables.find(name); if (it == variables.end()) return -1; return distance(variables.begin(), it); } void NScript::setVariableName(unsigned long index, const std::string& name) { std::map::iterator it = variables.begin(); advance(it, index); if (name == it->first) return; ChangeEventSpan span(this); NPacket* value = it->second; variables.erase(it); variables.insert(std::make_pair(name, value)); } void NScript::setVariableValue(unsigned long index, NPacket* value) { std::map::iterator it = variables.begin(); advance(it, index); if (it->second == value) return; ChangeEventSpan span(this); if (it->second) it->second->unlisten(this); it->second = value; if (it->second) it->second->listen(this); } void NScript::removeVariable(const std::string& name) { std::map::iterator it = variables.find(name); if (it == variables.end()) return; if (it->second) it->second->unlisten(this); ChangeEventSpan span(this); variables.erase(it); } void NScript::removeVariable(unsigned long index) { std::map::iterator it = variables.begin(); advance(it, index); if (it->second) it->second->unlisten(this); ChangeEventSpan span(this); variables.erase(it); } void NScript::writeTextLong(std::ostream& o) const { if (variables.empty()) o << "No variables.\n"; else { for (std::map::const_iterator vit = variables.begin(); vit != variables.end(); vit++) { o << "Variable: " << vit->first << " = "; if (vit->second) o << vit->second->getPacketLabel() << '\n'; else o << "(null)" << '\n'; } } o << '\n' << text; } NPacket* NScript::internalClonePacket(NPacket*) const { NScript* ans = new NScript(); ans->text = text; ans->variables = variables; return ans; } void NScript::writeXMLPacketData(std::ostream& out) const { using regina::xml::xmlEncodeSpecialChars; for (std::map::const_iterator vit = variables.begin(); vit != variables.end(); vit++) { out << " second) out << vit->second->internalID(); out << "\" value=\""; if (vit->second) out << xmlEncodeSpecialChars(vit->second->getPacketLabel()); out << "\"/>\n"; } out << " " << xmlEncodeSpecialChars(text) << "\n"; } void NScript::packetWasRenamed(NPacket*) { // We assume that the packet that was renamed is one of the // variables for this packet. // There is nothing to update here; just fire the update. ChangeEventSpan span(this); } void NScript::packetToBeDestroyed(NPacket* packet) { // We know the script will change, because one of our variables is // listening on this packet. ChangeEventSpan span(this); for (std::map::iterator vit = variables.begin(); vit != variables.end(); vit++) if (vit->second == packet) vit->second = 0; } } // namespace regina regina-4.96/engine/packet/nscript.h000644 000765 000024 00000027257 12377775316 017216 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file packet/nscript.h * \brief Contains a packet representing a script. */ #ifndef __NSCRIPT_H #ifndef __DOXYGEN #define __NSCRIPT_H #endif #include #include #include #include "regina-core.h" #include "packet/npacket.h" namespace regina { class NXMLPacketReader; class NScript; /** * \weakgroup packet * @{ */ /** * Stores information about the script packet. * See the general PacketInfo template notes for further details. * * \ifacespython Not present. */ template <> struct PacketInfo { typedef NScript Class; inline static const char* name() { return "Script"; } }; /** * A packet representing a Python script that can be run. * * A script consists of two parts: (i) the \e text, which contains the * Python code; and (ii) a set of \e variables, which refer to packets * in your packet tree. When running a script, the variables should be * instantiated in the default namespace before the script is run. * * The values of variables are given by pointers to packets (not packet * labels, as in some old versions of Regina). This affects how variables * react to changes in the packets that they point to. In particular, if a * variable \a V points to some packet \a P, then: * * - if \a P is renamed then \a V will still point to it and the script will * notify listeners that the script has changed; * - if \a P is deleted then \a V will take the value \c None, and the script * will likewise notify listeners of the change. */ class REGINA_API NScript : public NPacket, public NPacketListener { REGINA_PACKET(NScript, PACKET_SCRIPT) private: std::string text; /**< The complete text of this script, including newlines. */ std::map variables; /**< A map storing the variables with which this script is to be run. Variable names are mapped to their corresponding values. */ public: /** * Initialises to a script with no text and no variables. */ NScript(); /** * Returns the complete text of this script. * * Variables are not considered part of the text; you can get * and set them through other member functions (see below). * * @return the complete text of this script. */ const std::string& getText() const; /** * Replaces the complete text of this script with the given * string. * * Variables are not considered part of the text; you can get * and set them through other member functions (see below). * * @param newText the new text for this script. */ void setText(const std::string& newText); /** * Adds the given text to the end of this script. * * @param extraText the text to add. */ void append(const std::string& extraText); /** * Returns the number of variables associated with this script. * * @return the number of variables. */ unsigned long getNumberOfVariables() const; /** * Returns the name of the requested variable associated with * this script. * * @param index the index of the requested variable; this must * be between 0 and getNumberOfVariables()-1 inclusive. * @return the name of the requested variable. */ const std::string& getVariableName(unsigned long index) const; /** * Returns the index of the variable stored with the given name. * * @param name the name of the requested variable; note that * names are case sensitive. * @return the index of the requested variable as an integer * between 0 and getNumberOfVariables()-1 inclusive, or -1 if * there is no variable with the given name. */ long getVariableIndex(const std::string& name) const; /** * Returns the value of the requested variable associated with * this script. Variables may take the value \c null. * * @param index the index of the requested variable; this must * be between 0 and getNumberOfVariables()-1 inclusive. * @return the value of the requested variable. */ NPacket* getVariableValue(unsigned long index) const; /** * Returns the value of the variable stored with the given * name. Variables may take the value \c null. * * If no variable is stored with the given name, then \c null * will likewise be returned. * * @param name the name of the requested variable; note that * names are case sensitive. * @return the value of the requested variable. */ NPacket* getVariableValue(const std::string& name) const; /** * Changes the name of an existing variable associated with * this script. * * \warning This may change the indices of this and other * variables, since (at present) variables are kept stored in * sorted order by name. * * @param index the index of the variable whose name should change; * this must be between 0 and getNumberOfVariables()-1 inclusive. * @param name the new name to assign to the variable. */ void setVariableName(unsigned long index, const std::string& name); /** * Changes the value of an existing variable associated with * this script. * * @param index the index of the variable whose value should change; * this must be between 0 and getNumberOfVariables()-1 inclusive. * @param value the new value to assign to the variable. */ void setVariableValue(unsigned long index, NPacket* value); /** * Adds a new variable to be associated with this script. * If a variable with the given name is already stored, this * routine will do nothing. * * \warning The index of the new variable might not be * getNumberOfVariables()-1, and this operation may change the * indices of other variables also. This is because (at present) * variables are kept stored in sorted order by name. * * @param name the name of the new variable. * @param value the value of the new variable; this is allowed * to be \c null. * @return \c true if the variable was successfully added, or * \c false if a variable with the given name was already stored. */ bool addVariable(const std::string& name, NPacket* value); /** * Removes the variable stored with the given name. * If no variable is stored with the given name, this routine * will do nothing. * * \warning This may change the indices of other variables, since * (at present) variables are kept stored in sorted order by name. * * @param name the name of the variable to remove; note that * names are case sensitive. */ void removeVariable(const std::string& name); /** * Removes the variable stored at the given index. * * \warning This may change the indices of other variables, since * (at present) variables are kept stored in sorted order by name. * * @param index the index of the variable to remove; * this must be between 0 and getNumberOfVariables()-1 inclusive. */ void removeVariable(unsigned long index); /** * Removes all variables associated with this script. */ void removeAllVariables(); virtual void writeTextShort(std::ostream& out) const; virtual void writeTextLong(std::ostream& out) const; static NXMLPacketReader* getXMLReader(NPacket* parent, NXMLTreeResolver& resolver); virtual bool dependsOnParent() const; virtual void packetWasRenamed(NPacket* packet); virtual void packetToBeDestroyed(NPacket* packet); protected: virtual NPacket* internalClonePacket(NPacket* parent) const; virtual void writeXMLPacketData(std::ostream& out) const; }; /*@}*/ // Inline functions for NScript inline NScript::NScript() { } inline const std::string& NScript::getText() const { return text; } inline void NScript::setText(const std::string& newText) { if (text == newText) return; // No change event fired. ChangeEventSpan span(this); text = newText; } inline void NScript::append(const std::string& extraText) { if (extraText.empty()) return; // No change event fired. ChangeEventSpan span(this); text += extraText; } inline unsigned long NScript::getNumberOfVariables() const { return variables.size(); } inline bool NScript::addVariable(const std::string& name, NPacket* value) { ChangeEventSpan span(this); bool ans = variables.insert(std::make_pair(name, value)).second; if (value) value->listen(this); return ans; } inline void NScript::removeAllVariables() { unregisterFromAllPackets(); ChangeEventSpan span(this); variables.clear(); } inline void NScript::writeTextShort(std::ostream& o) const { o << "Python script"; } inline bool NScript::dependsOnParent() const { return false; } } // namespace regina #endif regina-4.96/engine/packet/ntext.cpp000644 000765 000024 00000004770 12377776640 017225 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "packet/ntext.h" #include "utilities/xmlutils.h" namespace regina { void NText::writeXMLPacketData(std::ostream& out) const { out << " " << regina::xml::xmlEncodeSpecialChars(text) << "\n"; } } // namespace regina regina-4.96/engine/packet/ntext.h000644 000765 000024 00000012670 12377775321 016663 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file packet/ntext.h * \brief Contains a packet representing a text string. */ #ifndef __NTEXT_H #ifndef __DOXYGEN #define __NTEXT_H #endif #include "regina-core.h" #include "packet/npacket.h" namespace regina { class NXMLPacketReader; class NText; /** * \weakgroup packet * @{ */ /** * Stores information about the text packet. * See the general PacketInfo template notes for further details. * * \ifacespython Not present. */ template <> struct PacketInfo { typedef NText Class; inline static const char* name() { return "Text"; } }; /** * A packet representing a text string. */ class REGINA_API NText : public NPacket { REGINA_PACKET(NText, PACKET_TEXT) private: std::string text; /**< The text string stored in this packet. */ public: /** * Initialises the packet to the empty string. */ NText(); /** * Initialises the packet to the given string. * * @param newText the new value for the packet. */ NText(const std::string& newText); /** * Initialises the packet to the given string. * * @param newText the new value for the packet. */ NText(const char* newText); /** * Returns the string stored in the packet. * * @return the stored string. */ const std::string& getText() const; /** * Sets the packet data to the given string. * * @param newText the new value for the packet. */ void setText(const std::string& newText); /** * Sets the packet data to the given string. * * @param newText the new value for the packet. */ void setText(const char* newText); virtual void writeTextShort(std::ostream& out) const; virtual void writeTextLong(std::ostream& out) const; static NXMLPacketReader* getXMLReader(NPacket* parent, NXMLTreeResolver& resolver); virtual bool dependsOnParent() const; protected: virtual NPacket* internalClonePacket(NPacket* parent) const; virtual void writeXMLPacketData(std::ostream& out) const; }; /*@}*/ // Inline functions for NText inline NText::NText() { } inline NText::NText(const std::string& newText) : text(newText) { } inline NText::NText(const char* newText) : text(newText) { } inline const std::string& NText::getText() const { return text; } inline void NText::setText(const std::string& newText) { if (text == newText) return; // No change event fired. ChangeEventSpan span(this); text = newText; } inline void NText::setText(const char* newText) { if (text == newText) return; // No change event fired. ChangeEventSpan span(this); text = newText; } inline void NText::writeTextShort(std::ostream& o) const { o << "Text packet"; } inline void NText::writeTextLong(std::ostream& o) const { o << text << '\n'; } inline bool NText::dependsOnParent() const { return false; } inline NPacket* NText::internalClonePacket(NPacket*) const { return new NText(text); } } // namespace regina #endif regina-4.96/engine/packet/nxmlpacketreader.cpp000644 000765 000024 00000012455 12377776641 021414 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "packet/npacket.h" #include "packet/nxmlpacketreader.h" #include "packet/nxmltreeresolver.h" #include "packet/packetregistry.h" #include "utilities/stringutils.h" namespace regina { namespace { struct XMLReaderFunction : public Returns { NPacket* me_; NXMLTreeResolver& resolver_; XMLReaderFunction(NPacket* me, NXMLTreeResolver& resolver) : me_(me), resolver_(resolver) {} template inline NXMLElementReader* operator() (Packet) { return Packet::Class::getXMLReader(me_, resolver_); } }; } NXMLElementReader* NXMLPacketReader::startSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict& subTagProps) { if (subTagName == "packet") { NPacket* me = getPacket(); if (! me) return new NXMLPacketReader(resolver_); regina::xml::XMLPropertyDict::const_iterator it = subTagProps.find("label"); if (it == subTagProps.end()) childLabel = ""; else childLabel = it->second; it = subTagProps.find("id"); if (it == subTagProps.end()) childID = ""; else childID = it->second; it = subTagProps.find("typeid"); if (it == subTagProps.end()) return new NXMLPacketReader(resolver_); long typeID; if (! valueOf((*it).second, typeID)) return new NXMLPacketReader(resolver_); if (typeID <= 0) return new NXMLPacketReader(resolver_); NXMLElementReader* ans = forPacket( static_cast(typeID), XMLReaderFunction(me, resolver_), 0); if (ans) return ans; else return new NXMLPacketReader(resolver_); } else if (subTagName == "tag") { if (NPacket* me = getPacket()) { std::string packetTag = subTagProps.lookup("name"); if (! packetTag.empty()) me->addTag(packetTag); } return new NXMLElementReader(); } else return startContentSubElement(subTagName, subTagProps); } void NXMLPacketReader::endSubElement(const std::string& subTagName, NXMLElementReader* subReader) { if (subTagName == "packet") { NPacket* child = dynamic_cast(subReader)->getPacket(); if (child) { NPacket* me = getPacket(); if (me) { child->setPacketLabel(childLabel); if (! childID.empty()) resolver_.storeID(childID, child); if (! child->getTreeParent()) me->insertChildLast(child); } else delete child; } } else if (subTagName == "tag") return; else endContentSubElement(subTagName, subReader); } void NXMLPacketReader::abort(NXMLElementReader* /* subReader */) { NPacket* me = getPacket(); if (me) if (! me->getTreeParent()) delete me; } } // namespace regina regina-4.96/engine/packet/nxmlpacketreader.h000644 000765 000024 00000021042 12377775323 021045 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file packet/nxmlpacketreader.h * \brief Deals with parsing XML data for individual packets. */ #ifndef __NXMLPACKETREADER_H #ifndef __DOXYGEN #define __NXMLPACKETREADER_H #endif #include "regina-core.h" #include "utilities/nxmlelementreader.h" namespace regina { class NPacket; class NXMLTreeResolver; /** * \weakgroup packet * @{ */ /** * An XML element reader that reads the data for an individual packet. * * Generally a subclass of NXMLPacketReader will be used to receive and * store packets that you care about. However, if you simply wish to * ignore a particular packet (and all of its descendants), you can use * class NXMLPacketReader itself for the packet(s) you wish to ignore. * * Routine getPacket() is used to return the packet that was read; see * its documentation for further notes on how the packet should be * constructed. * * Routines startSubElement() and endSubElement() should \e not be * overridden by derived classes. They determine whether the subelement * is another packet element or a packet tag; if so then they deal with * the subelement themselves (packet elements will be read using a new * NXMLPacketReader of the correct type), and if not then they call * startContentSubElement() and endContentSubElement() which \e should * be overridden for processing of non-packet XML subelements. * * If routine abort() is overridden, it \e must at some point call * NXMLPacketReader::abort() which will destroy whatever new packets * have already been created. * * \ifacespython Not present. */ class REGINA_API NXMLPacketReader : public NXMLElementReader { private: std::string childLabel; /**< The packet label to give the child packet currently being read. */ std::string childID; /**< The internal ID stored in the data file for the child packet currently being read. */ protected: NXMLTreeResolver& resolver_; /**< The master resolver that will be used to fix dangling packet references after the entire XML file has been read. */ public: /** * Creates a new packet element reader. * * @param resolver the master resolver that will be used to fix * dangling packet references after the entire XML file has been read. */ NXMLPacketReader(NXMLTreeResolver& resolver); /** * Returns the newly allocated packet that has been read by * this element reader. * * Deallocation of this new packet is not the responsibility of * this class. Once this routine gives a non-zero return value, * it should continue to give the same non-zero return value * from this point onwards. * * If this routine is ever to give a non-zero return value, it * \e must be giving that non-zero return value by the time the * first child packet or packet tag is encountered; otherwise * child packets will not be inserted into the packet tree and/or * packet tags will not be added. * * The newly allocated packet should not be given a packet * label. This will be done by NXMLPacketReader::endSubElement(). * * The newly allocated packet may or may not be inserted in the * packet tree structure; this does not matter (although if it * is inserted it must be inserted in the correct place). * * The newly allocated packet should not be given any associated * packet tags. This will be done by * NXMLPacketReader::startSubElement(). * * The default implementation returns 0. * * @return the packet that has been read, or 0 if packet reading * is incomplete, the packet should be ignored or an error * occurred. */ virtual NPacket* getPacket(); /** * Used instead of startSubElement() for XML subelements that * are not child packets or packet tags. * * The default implementation returns a new NXMLElementReader * which can be used to ignore the subelement completely. * * @param subTagName the name of the subelement opening tag. * @param subTagProps the properties associated with the * subelement opening tag. * @return a newly created element reader that will be used to * parse the subelement. This class should \e not take care of * the new reader's destruction; that will be done by the parser. */ virtual NXMLElementReader* startContentSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict& subTagProps); /** * Used instead of endSubElement() for XML subelements that are * not child packets or packet tags. * * The default implementation does nothing. * * @param subTagName the name of the subelement closing tag. * @param subReader the child reader that was used to parse the * subelement (this is the reader that was returned by the * corresponding startContentSubElement() call). It is guaranteed * that endElement() has already been called upon this child reader * and that the child reader has not yet been destroyed. */ virtual void endContentSubElement(const std::string& subTagName, NXMLElementReader* subReader); virtual NXMLElementReader* startSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict& subTagProps); virtual void endSubElement(const std::string& subTagName, NXMLElementReader* subReader); virtual void abort(NXMLElementReader *subReader); }; /*@}*/ // Inline functions for NXMLPacketReader inline NXMLPacketReader::NXMLPacketReader(NXMLTreeResolver& resolver) : resolver_(resolver) { } inline NPacket* NXMLPacketReader::getPacket() { return 0; } inline NXMLElementReader* NXMLPacketReader::startContentSubElement( const std::string&, const regina::xml::XMLPropertyDict&) { return new NXMLElementReader(); } inline void NXMLPacketReader::endContentSubElement(const std::string&, NXMLElementReader*) { } } // namespace regina #endif regina-4.96/engine/packet/nxmlpacketreaders.cpp000644 000765 000024 00000017275 12377776642 021605 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "packet/nxmlpacketreaders.h" #include "packet/nxmltreeresolver.h" #include "utilities/base64.h" #include #include namespace regina { /** * A unique namespace containing various task-specific packet readers. */ namespace { /** * Reads a single script variable and its value. */ class NScriptVarReader : public NXMLElementReader { private: std::string name, valueID, valueLabel; public: inline void startElement(const std::string& /* tagName */, const regina::xml::XMLPropertyDict& props, NXMLElementReader*) { name = props.lookup("name"); valueID = props.lookup("valueid"); valueLabel = props.lookup("value"); } inline const std::string& getName() { return name; } inline const std::string& getValueID() { return valueID; } inline const std::string& getValueLabel() { return valueLabel; } }; /** * A resolution task that, after the entire XML file has been read, * will bind a script variable to its corresponding packet reference. */ class VariableResolutionTask : public NXMLTreeResolutionTask { private: NScript* script_; std::string name_; std::string valueID_; /**< An internal packet ID. Used by Regina >= 4.95. */ std::string valueLabel_; /**< A packet label. Used by Regina <= 4.94. */ public: inline VariableResolutionTask(NScript* script, const std::string& name, const std::string& valueID, const std::string& valueLabel) : script_(script), name_(name), valueID_(valueID), valueLabel_(valueLabel) { } inline void resolve(const NXMLTreeResolver& resolver) { NPacket* resolution = 0; if (! valueID_.empty()) { NXMLTreeResolver::IDMap::const_iterator it = resolver.ids().find(valueID_); resolution = (it == resolver.ids().end() ? 0 : it->second); } if ((! resolution) && (! valueLabel_.empty())) resolution = script_->getTreeMatriarch()-> findPacketLabel(valueLabel_); script_->addVariable(name_, resolution); } }; } NXMLElementReader* NXMLPDFReader::startContentSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict&) { if (subTagName == "pdf") return new NXMLCharsReader(); else return new NXMLElementReader(); } void NXMLPDFReader::endContentSubElement(const std::string& subTagName, NXMLElementReader* subReader) { if (subTagName == "pdf") { std::string base64 = dynamic_cast(subReader)-> getChars(); // Strip out whitespace. std::string::iterator in = base64.begin(); std::string::iterator out = base64.begin(); while (in != base64.end()) { if (::isspace(*in)) ++in; else { if (in == out) { ++in; ++out; } else *out++ = *in++; } } // Is there any data at all? if (out == base64.begin()) { pdf->reset(); return; } // Convert from base64. char* data; size_t dataLen; if (base64Decode(base64.c_str(), out - base64.begin(), &data, &dataLen)) pdf->reset(data, dataLen, NPDF::OWN_NEW); else pdf->reset(); } } NXMLElementReader* NXMLScriptReader::startContentSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict&) { if (subTagName == "text") return new NXMLCharsReader(); else if (subTagName == "line") // Old-style return new NXMLCharsReader(); else if (subTagName == "var") return new NScriptVarReader(); else return new NXMLElementReader(); } void NXMLScriptReader::endContentSubElement(const std::string& subTagName, NXMLElementReader* subReader) { if (subTagName == "text") script->setText(dynamic_cast(subReader)->getChars()); else if (subTagName == "line") { // Old-style script->append(dynamic_cast(subReader)->getChars()); script->append("\n"); } else if (subTagName == "var") { NScriptVarReader* var = dynamic_cast(subReader); if (! var->getName().empty()) resolver_.queueTask(new VariableResolutionTask( script, var->getName(), var->getValueID(), var->getValueLabel())); } } NXMLPacketReader* NContainer::getXMLReader(NPacket*, NXMLTreeResolver& resolver) { return new NXMLContainerReader(resolver); } NXMLPacketReader* NPDF::getXMLReader(NPacket*, NXMLTreeResolver& resolver) { return new NXMLPDFReader(resolver); } NXMLPacketReader* NScript::getXMLReader(NPacket*, NXMLTreeResolver& resolver) { return new NXMLScriptReader(resolver); } NXMLPacketReader* NText::getXMLReader(NPacket*, NXMLTreeResolver& resolver) { return new NXMLTextReader(resolver); } } // namespace regina regina-4.96/engine/packet/nxmlpacketreaders.h000644 000765 000024 00000016400 12377775324 021233 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file packet/nxmlpacketreaders.h * \brief Deals with parsing XML data for various basic packet types. */ #ifndef __NXMLPACKETREADERS_H #ifndef __DOXYGEN #define __NXMLPACKETREADERS_H #endif #include "regina-core.h" #include "packet/nxmlpacketreader.h" #include "packet/ncontainer.h" #include "packet/npdf.h" #include "packet/nscript.h" #include "packet/ntext.h" namespace regina { /** * \weakgroup packet * @{ */ /** * An XML packet reader that reads a single container. * * \ifacespython Not present. */ class REGINA_API NXMLContainerReader : public NXMLPacketReader { private: NContainer* container; /**< The container currently being read. */ public: /** * Creates a new container reader. * * @param resolver the master resolver that will be used to fix * dangling packet references after the entire XML file has been read. */ NXMLContainerReader(NXMLTreeResolver& resolver); virtual NPacket* getPacket(); }; /** * An XML packet reader that reads a single PDF packet. * * \ifacespython Not present. */ class REGINA_API NXMLPDFReader : public NXMLPacketReader { private: NPDF* pdf; /**< The PDF packet currently being read. */ public: /** * Creates a new PDF reader. * * @param resolver the master resolver that will be used to fix * dangling packet references after the entire XML file has been read. */ NXMLPDFReader(NXMLTreeResolver& resolver); virtual NPacket* getPacket(); virtual NXMLElementReader* startContentSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict& subTagProps); virtual void endContentSubElement(const std::string& subTagName, NXMLElementReader* subReader); }; /** * An XML packet reader that reads a single script. * * \ifacespython Not present. */ class REGINA_API NXMLScriptReader : public NXMLPacketReader { private: NScript* script; /**< The script currently being read. */ public: /** * Creates a new script reader. * * @param resolver the master resolver that will be used to fix * dangling packet references after the entire XML file has been read. */ NXMLScriptReader(NXMLTreeResolver& resolver); virtual NPacket* getPacket(); virtual NXMLElementReader* startContentSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict& subTagProps); virtual void endContentSubElement(const std::string& subTagName, NXMLElementReader* subReader); }; /** * An XML packet reader that reads a single text packet. * * \ifacespython Not present. */ class REGINA_API NXMLTextReader : public NXMLPacketReader { private: NText* text; /**< The text packet currently being read. */ public: /** * Creates a new text packet reader. * * @param resolver the master resolver that will be used to fix * dangling packet references after the entire XML file has been read. */ NXMLTextReader(NXMLTreeResolver& resolver); virtual NPacket* getPacket(); virtual NXMLElementReader* startContentSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict& subTagProps); virtual void endContentSubElement(const std::string& subTagName, NXMLElementReader* subReader); }; /*@}*/ // Inline functions for NXMLContainerReader inline NXMLContainerReader::NXMLContainerReader(NXMLTreeResolver& resolver) : NXMLPacketReader(resolver), container(new NContainer()) { } inline NPacket* NXMLContainerReader::getPacket() { return container; } // Inline functions for NXMLPDFReader inline NXMLPDFReader::NXMLPDFReader(NXMLTreeResolver& resolver) : NXMLPacketReader(resolver), pdf(new NPDF()) { } inline NPacket* NXMLPDFReader::getPacket() { return pdf; } // Inline functions for NXMLScriptReader inline NXMLScriptReader::NXMLScriptReader(NXMLTreeResolver& resolver) : NXMLPacketReader(resolver), script(new NScript()) { } inline NPacket* NXMLScriptReader::getPacket() { return script; } // Inline functions for NXMLTextReader inline NXMLTextReader::NXMLTextReader(NXMLTreeResolver& resolver) : NXMLPacketReader(resolver), text(new NText()) { } inline NPacket* NXMLTextReader::getPacket() { return text; } inline NXMLElementReader* NXMLTextReader::startContentSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict&) { if (subTagName == "text") return new NXMLCharsReader(); else return new NXMLElementReader(); } inline void NXMLTextReader::endContentSubElement(const std::string& subTagName, NXMLElementReader* subReader) { if (subTagName == "text") text->setText(dynamic_cast(subReader)->getChars()); } } // namespace regina #endif regina-4.96/engine/packet/nxmltreeresolver.h000644 000765 000024 00000024702 12377775325 021144 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file packet/nxmltreeresolver.h * \brief Support for resolving dangling packet references after a * complete packet tree has been read from file. */ #ifndef __NXMLTREERESOLVER_H #ifndef __DOXYGEN #define __NXMLTREERESOLVER_H #endif #include "regina-core.h" #include #include namespace regina { class NPacket; /** * \weakgroup packet * @{ */ class NXMLTreeResolver; /** * An individual task for resolving dangling packet references after an * XML data file has been read. * * See the NXMLTreeResolver class notes for an overview of how dangling * references and related issues are resolved, and the role that * NXMLTreeResolutionTask plays in this process. * * Specifically, if an individual NXMLPacketReader cannot * completely flesh out the internal data for a packet as the packet is * being read, it should construct a new NXMLTreeResolutionTask and * queue it to the master NXMLTreeResolver. The NXMLTreeResolver will * then call resolve() for each queued task after the complete data file * has been read, at which point whatever information was missing when the * packet was initially read should now be available. * * Each packet reader that requires this machinery should subclass * NXMLTreeResolutionTask, and override resolve() to perform whatever * "fleshing out" procedure is required for its particular type of packet. */ class REGINA_API NXMLTreeResolutionTask { public: /** * A default construct that does nothing. */ virtual ~NXMLTreeResolutionTask(); /** * Called by NXMLTreeResolver after the entire data file has * been read. Subclasses should override this routine to * perform whatever "fleshing out" is necessary for a packet * whose internal data is not yet complete. * * @param resolver the master resolver managing the resolution * process, as outlined in the NXMLTreeResolver class notes. */ virtual void resolve(const NXMLTreeResolver& resolver) = 0; }; /** * Provides a mechanism to resolve dangling packet references after a * complete packet tree has been read from an XML data file. * * There are situations in which, when reading an XML data file, the data * stored in an individual packet cannot be fully constructed until after * the entire data file has been read. For instance, a packet might need to * store pointers or references to other packets that could appear later in * the packet tree (e.g., a script storing pointers to its variables). * * This problem is solved by the NXMLTreeResolver class. The complete * process of reading an XML data file works as follows: * * - The top-level routine managing the file I/O constructs a new * NXMLTreeResolver. This resolver is then passed to each * NXMLPacketReader in turn as each individual packet is read. * * - If an NXMLPacketReader is not able to fully flesh out its data * because it requires information that is not yet available, it * should create a new NXMLTreeResolutionTask and queue this task to * the resolver via NXMLTreeResolver::queueTask(). * * - Once the entire packet tree has been read, the top-level file I/O * manager will call NXMLTreeResolver::resolve(). This will run * NXMLTreeResolutionTask::resolve() for each task in turn, whereby any * missing data for individual packets can be resolved. * * Each task should be an instance of a subclass of NXMLTreeResolutionTask, * whose virtual resolve() function is overridden to perform whatever * "fleshing out" work is required for the type of packet under consideration. */ class REGINA_API NXMLTreeResolver { public: typedef std::map IDMap; /**< A type that maps internal IDs from the data file to the corresponding packets. See ids() for details. */ private: IDMap ids_; /**< Maps internal IDs from the data file to the corresponding packets. */ std::list tasks_; /**< The list of tasks that have been queued for processing. */ public: /** * Constructs a resolver with no tasks queued. */ NXMLTreeResolver(); /** * Destroys any tasks that were queued but not performed. */ ~NXMLTreeResolver(); /** * Queues a task for processing. When the file I/O manager * calls resolve(), this will call NXMLTreeResolutionTask::resolve() * for each task that has been queued. * * This object will claim ownership of the given task, and will * destroy it after resolve() has been called (or, if resolve() * is never called, when this NXMLTreeResolver is destroyed). * * @param task the task to be queued. */ void queueTask(NXMLTreeResolutionTask* task); /** * Stores the fact that the given packet is stored in the data * file using the given internal ID. Associations between IDs * and packets can be queried through the ids() function. * See ids() for further information on internal IDs. * * This will be called automatically by NXMLPacketReader as it * processes packet tags in the data file. Users and/or subclasses * of NXMLPacketReader do not need to call this function themselves. * * @param id the internal ID of the given packet, as stored in * the data file. * @param packet the corresponding packet. */ void storeID(const std::string& id, NPacket* packet); /** * Returns the map from internal IDs to packets, as stored in * the data file. * * Packets in a data file may have individual string IDs stored * alongside them, in the \a id attribute of the * <packet> tag. These strings are optional, * and do not need to be human-readable. * Although packets are not required to have IDs, any IDs that \e are * stored must be unique (i.e., two different packets cannot * share the same ID). * * Note that IDs read from the data file need not bear any * relation to the IDs that are returned from NPacket::internalID(), * although this is typically how they are constructed when a * file is saved. * * This map will be fleshed out as the data file is read. In * particular, since each task runs NXMLTreeResolutionTask::resolve() * only after the entire tree has been read, tasks may assume that * this map contains all IDs that were explicitly stored in the * data file. * * Only packets with IDs will appear in this map (i.e., there may well * be packets in the data file that do not appear in this map at all). * * @return the map from internal file IDs to packets. */ const IDMap& ids() const; /** * Calls NXMLTreeResolutionTask::resolve() for all queued tasks. * * The tasks will then be destroyed and removed from the queue * (so subsequent calls to resolve() are safe and will do nothing). */ void resolve(); }; /*@}*/ // Inline functions for NXMLTreeResolutionTask inline NXMLTreeResolutionTask::~NXMLTreeResolutionTask() { } // Inline functions for NXMLTreeResolver inline NXMLTreeResolver::NXMLTreeResolver() { } inline NXMLTreeResolver::~NXMLTreeResolver() { for (std::list::iterator it = tasks_.begin(); it != tasks_.end(); ++it) delete *it; } inline void NXMLTreeResolver::queueTask(NXMLTreeResolutionTask* task) { tasks_.push_back(task); } inline void NXMLTreeResolver::storeID(const std::string& id, NPacket* packet) { ids_.insert(std::make_pair(id, packet)); } inline const NXMLTreeResolver::IDMap& NXMLTreeResolver::ids() const { return ids_; } inline void NXMLTreeResolver::resolve() { for (std::list::iterator it = tasks_.begin(); it != tasks_.end(); ++it) { (*it)->resolve(*this); delete *it; } tasks_.clear(); } } // namespace regina #endif regina-4.96/engine/packet/open.cpp000644 000765 000024 00000023140 12377776642 017016 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include "engine.h" #include "packet/ncontainer.h" #include "packet/nxmlpacketreader.h" #include "packet/nxmltreeresolver.h" #include "utilities/nxmlcallback.h" #include "utilities/stringutils.h" #include "utilities/zstream.h" namespace regina { namespace { /** * Reads the outermost \ XML element. */ class ReginaDataReader : public regina::NXMLPacketReader { private: NContainer container; /**< Sits above the entire packet tree read from file. */ bool isReginaData; /**< Are we actually reading a \ element? */ std::string version; /**< The version of Regina that created this file, or the empty string if this is not known. */ public: /** * Create a new top-level reader. */ ReginaDataReader(NXMLTreeResolver& resolver) : NXMLPacketReader(resolver), isReginaData(false) { } virtual NPacket* getPacket() { if (isReginaData) return &container; else return 0; } const std::string& getVersion() const { return version; } virtual void startElement(const std::string& n, const regina::xml::XMLPropertyDict& props, NXMLElementReader*) { if (n == "reginadata") { isReginaData = true; regina::xml::XMLPropertyDict::const_iterator it = props.find("engine"); if (it != props.end()) version = stripWhitespace(it->second); } } virtual void abort(NXMLElementReader*) { // Delete all children of the top-level container. while (NPacket* child = container.getFirstTreeChild()) { child->makeOrphan(); delete child; } } }; /** * The number of characters by which we expect to have finished the * opening tag in an old pre-utf8 XML data stream. */ const int regDataOpenBy = 200; /** * The size of the XML chunks that are sent through to libxml2 for parsing. * * Since we plan to perform surgery on pre-utf8 data streams, the chunk * size must be large enough to catch the regina engine version in the * first bite. In particular, we require regChunkSize > regDataOpenBy. */ const int regChunkSize = 1024; } NPacket* open(const char* filename) { DecompressionStream in(filename); if (! in) return 0; NXMLTreeResolver resolver; ReginaDataReader reader(resolver); regina::NXMLCallback callback(reader, std::cerr); // Instead of using the ready-made regina::xml::XMLParser::parse_stream(), // we split the stream into parseable chunks manually. This allows us to // perform surgery on pre-utf8 streams and tell the parser that old files // actually store their data in latin1 (which the old file format // neglected to specify in the XML prologue). { regina::xml::XMLParser parser(callback); char* buf = new char[regChunkSize]; int chunkRead; bool seenFirstChunk = false; while (true) { // Read in the next chunk. for (chunkRead = 0; chunkRead < regChunkSize; chunkRead++) { buf[chunkRead] = static_cast(in.get()); if (in.eof()) break; } if (chunkRead == 0) break; // Parse the chunk that has just been read. // Interesting things (i.e., surgery) can only happen in the // first chunk. if (seenFirstChunk) { parser.parse_chunk(std::string(buf, chunkRead)); continue; } seenFirstChunk = true; // This is the first chunk in the data stream. See if we // need to perform surgery upon it. // // We will be fairly rigid in looking for substrings, since // we are only trying to match old pre-utf8 data files. If // future versions of the calculation engine change the // opening "signature" then this does not matter, since they // will not need surgery anyway. // // If anything looks out of place, just abort the surgery // and send everything straight through to the XML parser, // in the hope that either the file is new enough to not // need surgery (i.e., it uses utf8 already) or it's old but // only uses plain ASCII. char tmp = buf[regDataOpenBy]; buf[regDataOpenBy] = 0; char* start = ::strstr(buf, ""); if (! start) { // Can't find the end of the opening sequence! *finish = tmp; parser.parse_chunk(std::string(buf, chunkRead)); continue; } // Good to go. Parse the chunk with a new encoding squeezed in // just before the "?>". *finish = tmp; parser.parse_chunk(std::string(buf, start - buf)); parser.parse_chunk(" encoding=\"ISO-8859-1\""); parser.parse_chunk(std::string(start, chunkRead - (start - buf))); } parser.finish(); delete[] buf; } // See if we read anything. // If so, break it away from the top-level container and return it. NPacket* p = reader.getPacket(); if (p) { p = p->getFirstTreeChild(); if (p) p->makeOrphan(); // Resolve any dangling packet references. resolver.resolve(); return p; } else return 0; } } // namespace regina regina-4.96/engine/packet/packetregistry-impl.h000644 000765 000024 00000012637 12377775327 021531 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file packet/packetregistry-impl.h * \brief Contains the registry of all packet types known to Regina. * * Each time a new packet type is created, this registry must be updated to: * * - add a #include line for the corresponding packet class; * - add a corresponding case to each implementation of forPacket(). * * See packetregistry.h for how other routines can use this registry. */ #ifndef __PACKETREGISTRY_IMPL_H #ifndef __DOXYGEN #define __PACKETREGISTRY_IMPL_H #endif #include "packet/ncontainer.h" #include "packet/ntext.h" #include "triangulation/ntriangulation.h" #include "surfaces/nnormalsurfacelist.h" #include "packet/nscript.h" #include "surfaces/nsurfacefilter.h" #include "angle/nanglestructurelist.h" #include "packet/npdf.h" #include "dim2/dim2triangulation.h" #include "snappea/nsnappeatriangulation.h" namespace regina { template inline typename FunctionObject::ReturnType forPacket( PacketType packetType, FunctionObject func, typename FunctionObject::ReturnType defaultReturn) { switch (packetType) { case PACKET_CONTAINER : return func(PacketInfo()); case PACKET_TEXT : return func(PacketInfo()); case PACKET_TRIANGULATION : return func(PacketInfo()); case PACKET_NORMALSURFACELIST : return func(PacketInfo()); case PACKET_SCRIPT : return func(PacketInfo()); case PACKET_SURFACEFILTER : return func(PacketInfo()); case PACKET_ANGLESTRUCTURELIST : return func(PacketInfo()); case PACKET_PDF : return func(PacketInfo()); case PACKET_DIM2TRIANGULATION : return func(PacketInfo()); case PACKET_SNAPPEATRIANGULATION : return func(PacketInfo()); default: return defaultReturn; } } template inline void forPacket(PacketType packetType, VoidFunctionObject func) { switch (packetType) { case PACKET_CONTAINER : func(PacketInfo()); break; case PACKET_TEXT : func(PacketInfo()); break; case PACKET_TRIANGULATION : func(PacketInfo()); break; case PACKET_NORMALSURFACELIST : func(PacketInfo()); break; case PACKET_SCRIPT : func(PacketInfo()); break; case PACKET_SURFACEFILTER : func(PacketInfo()); break; case PACKET_ANGLESTRUCTURELIST : func(PacketInfo()); break; case PACKET_PDF : func(PacketInfo()); break; case PACKET_DIM2TRIANGULATION : func(PacketInfo()); break; case PACKET_SNAPPEATRIANGULATION : func(PacketInfo()); break; default: break; } } } // namespace regina #endif regina-4.96/engine/packet/packetregistry.h000644 000765 000024 00000015333 12377775331 020561 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file packet/packetregistry.h * \brief Provides access to a registry of all packet types known to Regina. * * Each time a new packet type is created, the file packetregistry-impl.h * must be updated to include it. Instructions on how to do this are * included in packetregistry-impl.h. * * External routines can access the registry by calling one of the * forPacket() template functions defined in packetregistry.h. * * \warning You should not include this header unless it is necessary, * since it will automatically import every header for every packet type * in the registry. */ // The old registry macros will silently compile but do nothing. // This could lead to nasty surprises, so throw an error if it looks like // people are still trying to use them. #ifdef __PACKET_REGISTRY_BODY #error "The old REGISTER_PACKET macros have been removed. Use forPacket() instead." #endif #ifndef __PACKETREGISTRY_H #ifndef __DOXYGEN #define __PACKETREGISTRY_H #endif #include "packet/packettype.h" #include "utilities/registryutils.h" namespace regina { /** * \weakgroup packet * @{ */ /** * Allows the user to call a template function whose template parameter * matches a given value of PacketType, which is not known * until runtime. In essence, this routine contains a switch/case statement * that runs through all possible packet types known to Regina. * * The advantages of this routine are that (i) the user does not need to * repeatedly type such switch/case statements themselves; and (ii) if * a new packet type is added then only a small amount of code * needs to be extended to incorporate it. * * In detail: the function object \a func must define a templated * unary bracket operator, so that func(PacketInfo) is * defined for any valid PacketType enum value \a t. Then, * when the user calls forPacket(packetType, func, defaultReturn), * this routine will call func(PacketInfo) and pass * back the corresponding return value. If \a packetType does not denote a * valid packet type, then forPacket() will pass back \a defaultReturn instead. * * There is also a two-argument variant of forPacket() that works with * void functions. * * \pre The function object must have a typedef \a ReturnType indicating * the return type of the corresponding templated unary bracket operator. * Inheriting from Returns<...> is a convenient way to ensure this. * * \ifacespython Not present. * * @param packetType the given packet type. * @param func the function object whose unary bracket operator we will * call with a PacketInfo object. * @param defaultReturn the value to return if the given packet type * is not valid. * @return the return value from the corresponding unary bracket * operator of \a func, or \a defaultReturn if the given packet type * is not valid. */ template typename FunctionObject::ReturnType forPacket( PacketType packetType, FunctionObject func, typename FunctionObject::ReturnType defaultReturn); /** * Allows the user to call a template function whose template parameter * matches a given value of PacketType, which is not known * until runtime. In essence, this routine contains a switch/case statement * that runs through all possible packet types known to Regina. * * The advantages of this routine are that (i) the user does not need to * repeatedly type such switch/case statements themselves; and (ii) if * a new packet type is added then only a small amount of code * needs to be extended to incorporate it. * * In detail: the function object \a func must define a templated * unary bracket operator, so that func(PacketInfo) is * defined for any valid PacketType enum value \a t. Then, * when the user calls forPacket(packetType, func), * this routine will call func(PacketInfo) in turn. * If \a packetType does not denote a valid packet type, then forPacket() * will do nothing. * * There is also a three-argument variant of forPacket() that works with * functions with return values. * * \ifacespython Not present. * * @param packetType the given packet type. * @param func the function object whose unary bracket operator we will * call with a PacketInfo object. */ template void forPacket(PacketType packetType, VoidFunctionObject func); /*@}*/ } // namespace regina // Import template implementations: #include "packet/packetregistry-impl.h" #endif regina-4.96/engine/packet/packettype.h000644 000765 000024 00000007670 12377775333 017701 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file packet/packettype.h * \brief Defines constants for the various packet types known to Regina. */ #ifndef __PACKETTYPE_H #ifndef __DOXYGEN #define __PACKETTYPE_H #endif #include "regina-core.h" namespace regina { /** * \weakgroup packet * @{ */ /** * Represents the different types of packet that are available in Regina. * * IDs 0-9999 are reserved for future use by Regina. If you are extending * Regina to include your own packet type, you should choose an ID >= 10000. */ enum PacketType { /** * Represents a container packet, of class NContainer. */ PACKET_CONTAINER = 1, /** * Represents a text packet, of class NText. */ PACKET_TEXT = 2, /** * Represents a 3-manifold triangulation, of class NTriangulation. */ PACKET_TRIANGULATION = 3, /** * Represents a normal surface list, of class NNormalSurfaceList. */ PACKET_NORMALSURFACELIST = 6, /** * Represents a script packet, of class NScript. */ PACKET_SCRIPT = 7, /** * Represents a normal surface filter, of class NSurfaceFilter or * one of its descendant classes. */ PACKET_SURFACEFILTER = 8, /** * Represents an angle structure list, of class NAngleStructureList. */ PACKET_ANGLESTRUCTURELIST = 9, /** * Represents a PDF document, of class NPDF. */ PACKET_PDF = 10, /** * Represents a 2-manifold triangulation, of class Dim2Triangulation. */ PACKET_DIM2TRIANGULATION = 15, /** * Represents a triangulation in the embedded SnapPea kernel, of * class NSnapPeaTriangulation. */ PACKET_SNAPPEATRIANGULATION = 16 }; /*@}*/ } // namespace regina #endif regina-4.96/engine/progress/CMakeLists.txt000644 000765 000024 00000000761 12311266525 020470 0ustar00babstaff000000 000000 # progress # Files to compile SET ( FILES nprogresstypes ) # Prepend folder name FOREACH ( SOURCE_FILE ${FILES} ) SET ( SOURCES ${SOURCES} progress/${SOURCE_FILE}) ENDFOREACH(SOURCE_FILE) # Set the variable in the parent directory SET( SOURCES ${SOURCES} PARENT_SCOPE) if (${REGINA_INSTALL_DEV}) INSTALL(FILES nprogress.h nprogressmanager.h nprogresstypes.h nprogresstracker.h DESTINATION ${INCLUDEDIR}/progress COMPONENT Development) endif (${REGINA_INSTALL_DEV}) regina-4.96/engine/progress/nprogress.h000644 000765 000024 00000036364 12377775334 020152 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file progress/nprogress.h * \brief Allows external interfaces to obtain progress reports when * running long calculations. */ #ifndef __NPROGRESS_H #ifndef __DOXYGEN #define __NPROGRESS_H #endif #include #include "regina-core.h" #include "shareableobject.h" #include "utilities/nthread.h" namespace regina { /** * \addtogroup progress Progress Management * Progress reports during long calculations. * @{ */ /** * An object through which external interfaces can obtain progress * reports when running long calculations. * The running calculation writes to this object to * store the current state of progress, and the external interface reads * from this object from a different thread. * * When writing progress information to an NProgress object, the last * call should be to setFinished(). This informs all threads * that the operation is finished and that the NProgress object can be * deleted without the risk that the writing thread will attempt to * access it again. * * If the operation allows it, the reading thread * may at any time request that the operation be cancelled by calling * cancel(). The writing thread should regularly poll isCancelled(), * and if it detects a cancellation request should exit cleanly as soon * as possible. Note that the writing thread should still call * setFinished() in this situation. * * NProgress contains multithreading support; a mutex is used to ensure * that the reading and writing threads do not interfere. * * NProgress also contains timing support, with measurements in both * real time and CPU time. See the routines getRealTime() and * totalCPUTime() for details. * * Subclasses of NProgress represent the various ways in which progress * can be internally stored. Note that subclass member functions * must lock the mutex whenever internal data is being * accessed or modified (see NMutex::MutexLock for how this is done). * Any public subclass member function that changes the state of * progress must set the \a changed flag to \c true, and all public * subclass query functions must set the \a changed flag to \c false. * * \deprecated This class is deprecated. Please use the more flexible * and more streamlined NProgressTracker class instead. */ class REGINA_API NProgress : public ShareableObject, protected NMutex { protected: mutable bool changed; /**< Has the state of progress changed since the last query? */ bool cancelled; /**< Has this operation been cancelled? */ private: bool finished; /**< Is the operation whose progress we are reporting * completely finished? */ time_t startReal; /**< A real time marker representing when this progress object was constructed. */ clock_t startCPU; /**< A CPU time marker representing when this progress object was constructed. */ time_t endReal; /**< A real time marker representing when this progress object was marked finished. */ clock_t endCPU; /**< A CPU time marker representing when this progress object was marked finished. */ public: /** * Performs basic initialisation. * Note that the internal mutex is not locked during construction. * * The internal state-has-changed flag is set to \c true. * * \ifacespython Not present; NProgress objects should only be * created within calculation engine routines whose progress is * being watched. */ NProgress(); /** * Destroys this object. */ virtual ~NProgress(); /** * Determines if the state of progress has changed since the * last query. A query is defined to be a call to * getDescription(), getPercent() or any of the * subclass-specific query routines. * * This routine allows interfaces to avoid calls to the slower * query routines when they can avoid it. * * If no query has yet been made, this routine will return \c true. * * @return \c true if and only if the state of progress has * changed since the last query. */ bool hasChanged() const; /** * Is the operation whose progress we are reporting completely * finished? * * Once this routine returns \c true, it will always return \c * true; thus there will be no need to call it again. * * @return \c true if and only if the operation is finished. */ bool isFinished() const; /** * Signifies that the operation whose progress we are reporting * is completely finished. This must be the final * member function call to this NProgress object made by the thread * performing the corresponding operation. It notifies all * other threads that the operation is complete and that this * NProgress object can be safely deleted. * * This routine should still be called by the operation thread * if it cancels itself in response to a request by an external * interface (see cancel()). * * \ifacespython Not present; this should only be called from * within the calculation engine routine whose progress is being * watched. */ void setFinished(); /** * Called by an external interface to request that the operation * whose progress we are reporting be cancelled. * The operation itself should regularly poll * isCancelled() to check if an external interface has made this * request. * * Note that if cancellation is not sensible or appropriate, the * operation may freely ignore such cancellation requests and need * not poll isCancelled() at all. * * This routine is made const since an external interface should be * able to cancel an operation even though it should never * modify the state of progress. */ void cancel() const; /** * Determines whether an external interface has requested that * the operation whose progress we are reporting be cancelled. * * If the operation is polling for cancellation requests and it finds * that isCancelled() returns \c true, it should generally exit * (cleanly) as soon as possible with only partial or no results. * However, if cancellation is not sensible or appropriate, the * operation may freely ignore such cancellation requests. * * Note that even if the underlying operation cancels itself, it * should still call setFinished(). * * @return \c true if and only if an external interface has * requested that the operation be cancelled. */ bool isCancelled() const; /** * Returns a string description of the current state of * progress. Note that subclasses must override * internalGetDescription(), not this routine. * * @return the current state of progress. */ std::string getDescription() const; /** * Determines if the state of progress can be expressed as a * percentage. * * The default implementation returns \c false. * * @return \c true if and only if progress can be expressed as a * percentage. */ virtual bool isPercent() const; /** * Returns the current state of progress as a percentage. * Note that subclasses must override internalGetPercent(), * not this routine. * * \pre Progress can be expressed as a percentage (see isPercent()). * * @return the current state of progress as a percentage. */ double getPercent() const; /** * Returns the real time elapsed since this operation began. * This routine may be called both during and after the * operation. * * If the operation has been marked as finished, the total * elapsed time from start to finish will be reported. * Otherwise the time elasped thus far will be reported. * * @return the total elapsed real time, measured in seconds. * * @see totalCPUTime() */ long getRealTime() const; /** * Returns the total CPU time consumed by the program from the * beginning to the end of this operation. This routine will * only return useful results after the operation has finished. * * If the operation has not yet been marked as finished, this * routine will return 0. * * \warning For CPU time calculations to be correct, the same * thread that constructs this progress object must also mark it * finished. * * @return the total CPU time consumed, measured in seconds. * * @see getRealTime() */ long totalCPUTime() const; void writeTextShort(std::ostream& out) const; protected: /** * Returns a string description of the current state of progress. * * This function must not touch the mutex, and is not required * to alter the \a changed flag. The getDescription() routine takes * care of all of these issues. * * \pre The mutex is currently locked. * * @return the current state of progress. */ virtual std::string internalGetDescription() const = 0; /** * Returns the current state of progress as a percentage. * The default implementation returns 0. * * This function must not touch the mutex, and is not required * to alter the \a changed flag. The getDescription() routine takes * care of all of these issues. * * \pre Progress can be expressed as a percentage (see isPercent()). * \pre The mutex is currently locked. * * @return the current state of progress as a percentage. */ virtual double internalGetPercent() const; }; /** * A progress report that immediately claims it is finished. * There is no need to call setFinished(); this will be done * automatically by the constructor. * * \ifacespython Not present; all progress classes communicate with * external interfaces through the NProgress interface. * * \deprecated This class is deprecated. Please use the more flexible * and more streamlined NProgressTracker class instead. */ class REGINA_API NProgressFinished : public NProgress { public: /** * Creates a new finished progress report. * This constructor will automatically call setFinished(). */ NProgressFinished(); virtual bool isPercent() const; protected: virtual std::string internalGetDescription() const; virtual double internalGetPercent() const; }; /*@}*/ // Inline functions for NProgress inline NProgress::NProgress() : changed(true), finished(false), cancelled(false) { startReal = std::time(0); startCPU = std::clock(); } inline NProgress::~NProgress() { } inline bool NProgress::hasChanged() const { MutexLock(this); return changed; } inline bool NProgress::isFinished() const { MutexLock(this); return finished; } inline void NProgress::setFinished() { MutexLock(this); endReal = std::time(0); endCPU = std::clock(); finished = true; } inline void NProgress::cancel() const { MutexLock(this); const_cast(this)->cancelled = true; } inline bool NProgress::isCancelled() const { MutexLock(this); return cancelled; } inline std::string NProgress::getDescription() const { MutexLock(this); changed = false; return internalGetDescription(); } inline bool NProgress::isPercent() const { return false; } inline double NProgress::getPercent() const { MutexLock(this); changed = false; return internalGetPercent(); } inline void NProgress::writeTextShort(std::ostream& out) const { out << "Progress: " << getDescription(); } inline double NProgress::internalGetPercent() const { return 0; } inline long NProgress::getRealTime() const { MutexLock(this); return (finished ? endReal : std::time(0)) - startReal; } inline long NProgress::totalCPUTime() const { MutexLock(this); return (finished ? (endCPU - startCPU) / CLOCKS_PER_SEC : 0); }; // Inline functions for NProgressFinished inline NProgressFinished::NProgressFinished() { setFinished(); } inline bool NProgressFinished::isPercent() const { return true; } inline std::string NProgressFinished::internalGetDescription() const { return "Finished."; } inline double NProgressFinished::internalGetPercent() const { return 100; } } // namespace regina #endif regina-4.96/engine/progress/nprogressmanager.h000644 000765 000024 00000017750 12377775337 021506 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file progress/nprogressmanager.h * \brief Facilitates sharing NProgress objects between an * operation thread and an external interface. */ #ifndef __NPROGRESSMANAGER_H #ifndef __DOXYGEN #define __NPROGRESSMANAGER_H #endif #include "regina-core.h" #include "progress/nprogress.h" namespace regina { /** * \weakgroup progress * @{ */ /** * Manages the sharing of an NProgress object between reading and * writing threads. * * The life cycle of an NProgressManager and the corresponding NProgress * is as follows. Note that the reading thread is the interface * thread that is querying the state of progress, and the writing * thread is the thread in which the operation is actually being * performed. * * - Before the operation begins, an NProgressManager is created and * both the reading and writing threads have access to it. This can * be achieved for instance by having the reading thread create an * NProgressManager and pass it to the writing thread as a parameter * of the actual operation function call. * - The writing thread: * - creates a new NProgress and stores it in the NProgressManager * using setProgress(); * - updates the NProgress throughout the operation; * - finally calls NProgress::setFinished() when the operation is * complete; * - does not touch either the NProgress or the NProgressManager * again. * - The reading thread: * - repeatedly calls isStarted() and waits until this returns \c true; * - now knows the NProgress has been created and begins querying it * using getProgress() and displaying progress reports; * - whilst querying, repeatedly calls isFinished() to test if the * operation is complete; * - once isFinished() returns \c true, displays the final progress * message to the user and destroys the NProgressManager. * - Note that the NProgressManager destructor will automatically destroy the * NProgress. It is imperative that the writing thread does not touch * either the NProgress or the NProgressManager after calling * NProgress::setFinished(), since once isFinished() * returns \c true the reading * thread might destroy the NProgressManager and thus the NProgress at * any time. The writing thread cannot destroy these objects because * it has no guarantee that the reading thread is not still reading * progress reports from them. * * \deprecated This class is deprecated. Please use the more flexible * and more streamlined NProgressTracker class instead. */ class NProgressManager : public ShareableObject { private: NProgress* progress; /**< The progress report object that we are managing. */ public: /** * Creates a new progress manager with no NProgress to manage. */ NProgressManager(); /** * Destroys this manager as well as the corresponding NProgress. * * \pre There is an NProgress assigned to this manager; that is, * isStarted() returns \c true. * \pre The NProgress that we are managing has finished, that is, * isFinished() returns \c true. */ ~NProgressManager(); /** * Determines if an NProgress has been assigned to this * manager yet. * * Once this routine returns \c true, it will always return \c * true; thus there will be no need to call it again. * * @return \c true if and only if an NProgress has been assigned * to this manager. */ bool isStarted() const; /** * Determines if the NProgress that we are managing has finished. * That is, this routine determines if NProgress::isFinished() * returns \c true. * * Once this routine returns \c true, it will always return \c * true; thus there will be no need to call it again. * * \pre There is an NProgress assigned to this manager; that is, * isStarted() returns \c true. * * @return \c true if and only if the NProgress that we are * managing has finished. */ bool isFinished() const; /** * Returns the NProgress that this manager is managing. * If isStarted() returns \c true, you are guaranteed that * this routine will not return zero. * * @return the NProgress that this manager is managing, or 0 if * an NProgress has not yet been assigned to this manager. */ const NProgress* getProgress() const; /** * Assigns the given NProgress to this manager to manage. * * \pre setProgress() has not already been called. * * \ifacespython Not present; this routine should only be called * from within calculation engine routines whose progress is * being watched. * * @param newProgress the NProgress that this manager will manage. */ void setProgress(NProgress* newProgress); void writeTextShort(std::ostream& out) const; }; /*@}*/ // Inline functions for NProgressManager inline NProgressManager::NProgressManager() : progress(0) { } inline NProgressManager::~NProgressManager() { if (progress) delete progress; } inline bool NProgressManager::isStarted() const { return (progress != 0); } inline bool NProgressManager::isFinished() const { return progress->isFinished(); } inline const NProgress* NProgressManager::getProgress() const { return progress; } inline void NProgressManager::setProgress(NProgress* newProgress) { progress = newProgress; } inline void NProgressManager::writeTextShort(std::ostream& out) const { out << "[Progress Manager]"; } } // namespace regina #endif regina-4.96/engine/progress/nprogresstracker.h000644 000765 000024 00000035002 12377775341 021510 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file progress/nprogresstracker.h * \brief Facilitates progress tracking and cancellation for long operations. */ #ifndef __NPROGRESSTRACKER_H #ifndef __DOXYGEN #define __NPROGRESSTRACKER_H #endif #include "regina-core.h" #include "utilities/nthread.h" #include namespace regina { /** * \weakgroup progress * @{ */ /** * Manages progress tracking and cancellation polling for long operations. * A typical progress tracker is simultaneously used by a \e writing thread, * which is performing the long calculations, and a \e reading thread, * which displays progress updates to the user and/or takes cancellation * requests from the user. * * Progress works through a series of \e stages. Each stage has a text * description, as well as a percentage progress that rises from 0 to 100 * as the stage progresses. Each stage also has a fractional weight * (between 0 and 1 inclusive), and the percentage progress of the entire * calculation is taken to be the weighted sum of the progress of the * individual stages. The weights of all stages should sum to 1. * * The life cycle of an NProgressTracker is as follows. * * - The reading thread creates an NProgressTracker, and passes it to * the writing thread when the calculation begins. * * - The writing thread: * - creates the first stage by calling newStage(); * - as the stage progresses, repeatedly updates the percentage progress of * this stage by calling setPercent() and polls for cancellation by calling * isCancelled(); * - moves through any additional stages in a similar fashion, by * calling newStage() and then repeatedly calling setPercent() and * isCancelled(); * - calls setFinished() once all processing is complete (regardless * of whether the operation finished naturally or was cancelled by * the user); * - never touches the progress tracker again. * * - The reading thread: * - passes the progress tracker to the writing thread; * - repeatedly polls the state of the tracker by calling * percentChanged(), descriptionChanged() and/or isFinished(); * - if percentChanged() returns \c true, collects the total * percentage progress by calling percent() and displays this to the user; * - if descriptionChanged() returns \c true, collects the description of * the current stage by calling description() and displays this to the user; * - if the user ever chooses to cancel the operation, calls cancel() * but continues polling the state of the tracker as above; * - once isFinished() returns \c true, displays any final information * to the user and destroys the NProgressTracker. * * It is imperative that the writing thread does not access the tracker * after calling setFinished(), and it is imperative that the reading * thread does not destroy the tracker until after isFinished() returns * \c true. In particular, even if the reading thread has called cancel(), * it must still wait upon isFinished() before destroying the tracker. * Until isFinished() returns \c true, there is no guarantee that the * writing thread has detected and honoured the cancellation request. */ class REGINA_API NProgressTracker { private: double percent_; /**< The percentage progress through the current stage. Note that this is typically not the same as the percentage progress through the entire operation. */ std::string desc_; /**< The human-readable description of the current stage. */ bool percentChanged_; /**< Has the percentage progress changed since the last call to percentChanged()? */ bool descChanged_; /**< Has the description changed since the last call to descriptionChanged()? */ bool cancelled_; /**< Has the reading thread requested that the operation be cancelled? */ bool finished_; /**< Has the writing thread declared that it has finished all processing? */ double prevPercent_; /**< The total percentage progress of all previous stages, measured as a percentage of the entire operation. */ double currWeight_; /**< The fractional weight assigned to the current stage; this must be between 0 and 1 inclusive. */ NMutex lock_; /**< A mutex to stop the reading and writing threads from interfering with each other. */ public: /** * Creates a new progress tracker. * This sets a sensible state description (which declares that * the operation is initialising), and marks the current * progress as zero percent complete. * * This is typically called by the reading thread. */ NProgressTracker(); /** * Queries whether the writing thread has finished all * processing. This will eventually return \c true regardless * of whether the processing finished naturally or was cancelled * by the reading thread. * * This is typically called by the reading thread. * * @return \c true if and only if the writing thread has * finished all processing. */ bool isFinished() const; /** * Queries whether the percentage progress has changed since the * last call to percentChanged(). If this is the first time * percentChanged() is called, the result will be \c true. * * This is typically called by the reading thread. * * @return \c true if and only if the percentage progress has changed. */ bool percentChanged() const; /** * Queries whether the stage description has changed since the * last call to descriptionChanged(). If this is the first time * descriptionChanged() is called, the result will be \c true. * * This is typically called by the reading thread. * * @return \c true if and only if the stage description has changed. */ bool descriptionChanged() const; /** * Returns the percentage progress through the entire operation. * This combines the progress through the current stage with all * previous stages, taking into account the relative weights that the * writing thread has passed to newStage(). * * This is typically called by the reading thread. * * @return \c the current percentage progress. */ double percent() const; /** * Returns the human-readable description of the current stage. * * This is typically called by the reading thread. * * @return \c the current stage description. */ std::string description() const; /** * Indicates to the writing thread that the user wishes to * cancel the operation. The writing thread might not detect * and/or respond to this request immediately (or indeed ever), * and so the reading thread should continue to wait until * isFinished() returns \c true before it cleans up and destroys * this progress tracker. * * This is typically called by the reading thread. */ void cancel(); /** * Used by the writing thread to indicate that it has moved on * to a new stage of processing. The percentage progress through * the current stage will automatically be set to 100. * * This is typically called by the writing thread. * * @param desc a human-readable description of the new stage. * Typically this begins with a capital and does not include a * final period (full stop). * @param weight the relative weight of this stage as a fraction * of the entire operation. This weight must be between 0 and 1 * inclusive, and the weights of \e all stages must sum to 1 * in total. */ void newStage(const char* desc, double weight = 1); /** * Queries whether the reading thread has made a request for the * writing thread to cancel the operation; in other words, whether * cancel() has been called. * * This is typically called by the writing thread. * * @return \c true if and only if a cancellation request has * been made. */ bool isCancelled() const; /** * Used by the writing thread to indicate the level of progress * through the current stage. * * Unlike percent(), which measures progress in the context of * the entire operation, this routine takes a percentage that * is strictly relative to the current stage (i.e., the stage most * recently declared through a call to newStage()). When the * stage begins, setPercent() would typically be given a figure * close to 0; when the stage is finished, setPercent() would * typically be given a figure close to 100. * * There is no actual need to call setPercent(0) at the * beginning of the stage or setPercent(100) at the end of the * stage, since other routines (such as the constructor, * newStage() and setFinished()) will take care of this for you. * * This is typically called by the writing thread. * * @param percent the percentage progress through this stage, as * a number between 0 and 100 inclusive. * @return \c true if there has been no cancellation request, or * \c false if cancel() has been called (typically by the reading * thread). */ bool setPercent(double percent); /** * Used by the writing thread to indicate that it has finished * all processing. The percentage progress through both the * current stage and the entire operation will automatically * be set to 100, and the stage description will be updated to * indicate that the operation is finished. * * This is typically called by the writing thread. */ void setFinished(); }; /*@}*/ // Inline functions for NProgressTracker inline NProgressTracker::NProgressTracker() : percent_(0), percentChanged_(true), descChanged_(true), cancelled_(false), finished_(false), prevPercent_(0), currWeight_(0) { desc_ = "Initialising"; } inline bool NProgressTracker::isFinished() const { NMutex::MutexLock lock(lock_); return finished_; } inline bool NProgressTracker::percentChanged() const { NMutex::MutexLock lock(lock_); if (percentChanged_) { const_cast(this)->percentChanged_ = false; return true; } else return false; } inline bool NProgressTracker::descriptionChanged() const { NMutex::MutexLock lock(lock_); if (descChanged_) { const_cast(this)->descChanged_ = false; return true; } else return false; } inline double NProgressTracker::percent() const { NMutex::MutexLock lock(lock_); return prevPercent_ + currWeight_ * percent_; } inline std::string NProgressTracker::description() const { NMutex::MutexLock lock(lock_); return desc_; } inline void NProgressTracker::cancel() { NMutex::MutexLock lock(lock_); cancelled_ = true; } inline void NProgressTracker::newStage(const char* desc, double weight) { NMutex::MutexLock lock(lock_); desc_ = desc; percent_ = 0; prevPercent_ += 100 * currWeight_; currWeight_ = weight; percentChanged_ = descChanged_ = true; } inline bool NProgressTracker::isCancelled() const { NMutex::MutexLock lock(lock_); return cancelled_; } inline bool NProgressTracker::setPercent(double percent) { NMutex::MutexLock lock(lock_); percent_ = percent; percentChanged_ = true; return ! cancelled_; } inline void NProgressTracker::setFinished() { NMutex::MutexLock lock(lock_); prevPercent_ = 100; currWeight_ = 0; percent_ = 0; desc_ = "Finished"; finished_ = true; percentChanged_ = descChanged_ = true; } } // namespace regina #endif regina-4.96/engine/progress/nprogresstypes.cpp000644 000765 000024 00000005033 12377776643 021563 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "progress/nprogresstypes.h" #include namespace regina { std::string NProgressNumber::internalGetDescription() const { std::ostringstream out; out << completed; if (outOf >= 0) out << '/' << outOf; return out.str(); } } // namespace regina regina-4.96/engine/progress/nprogresstypes.h000644 000765 000024 00000025400 12377775343 021224 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file progress/nprogresstypes.h * \brief Provides specific methods of representing progress reports. */ #ifndef __NPROGRESSTYPES_H #ifndef __DOXYGEN #define __NPROGRESSTYPES_H #endif #include "regina-core.h" #include "progress/nprogress.h" namespace regina { /** * \weakgroup progress * @{ */ /** * A progress report in which the current state of progress is stored as a * string message. * * \ifacespython Not present; all progress classes communicate with * external interfaces through the NProgress interface. * * \deprecated This class is deprecated. Please use the more flexible * and more streamlined NProgressTracker class instead. */ class REGINA_API NProgressMessage : public NProgress { private: std::string message; /**< The current state of progress. */ public: /** * Creates a new progress report with an empty progress message. * Note that the internal mutex is not locked during construction. */ NProgressMessage(); /** * Creates a new progress report with the given progress message. * Note that the internal mutex is not locked during construction. * * @param newMessage the current state of progress. */ NProgressMessage(const std::string& newMessage); /** * Creates a new progress report with the given progress message. * Note that the internal mutex is not locked during construction. * * @param newMessage the current state of progress. */ NProgressMessage(const char* newMessage); /** * Returns a reference to the current progress message. * * @return the current progress message. */ std::string getMessage() const; /** * Sets the current progress message to the given string. * * @param newMessage the new state of progress. */ void setMessage(const std::string& newMessage); /** * Sets the current progress message to the given string. * * @param newMessage the new state of progress. */ void setMessage(const char* newMessage); protected: virtual std::string internalGetDescription() const; }; /** * A simple structure used for passing around a numeric state of * progress. * * \deprecated This class is deprecated. Please use the more flexible * and more streamlined NProgressTracker class instead. */ struct REGINA_API NProgressStateNumeric { long completed; /**< The number of items that have already been completed. */ long outOf; /**< The expected total number of items, or -1 if this is not known. */ /** * Initialises a new structure using the given values. * * @param newCompleted the number of items that have already been * completed. * @param newOutOf the expected total number of items, or -1 if this * is not known. */ NProgressStateNumeric(long newCompleted = 0, long newOutOf = -1); }; /** * A progress report in which the current state of progress is stored as * a number of items completed. * The expected total number of items can be optionally specified. * * \ifacespython Not present; all progress classes communicate with * external interfaces through the NProgress interface. * * \deprecated This class is deprecated. Please use the more flexible * and more streamlined NProgressTracker class instead. */ class REGINA_API NProgressNumber : public NProgress { private: long completed; /**< The number of items completed. */ long outOf; /**< The expected total number of items, or -1 if this * total is not known. */ public: /** * Creates a new progress report containing the given details. * Note that the internal mutex is not locked during construction. * * \pre The new number of items completed is non-negative. * \pre If the new expected total is non-negative, then the new * number of items completed is at most the new expected total. * * @param newCompleted the number of items completed; this * defaults to 0. * @param newOutOf the expected total number of items, or -1 if * this total is not known (the default). */ NProgressNumber(long newCompleted = 0, long newOutOf = -1); /** * Returns the number of items completed. * * @return the number of items completed. */ long getCompleted() const; /** * Returns the expected total number of items. * * @return the expected total number of items, or -1 if this * total is not known. */ long getOutOf() const; /** * Returns both the number of items completed and the expected * total number of items. * * @return the current state of progress. */ NProgressStateNumeric getNumericState() const; /** * Sets the number of items completed. * * \pre The new number of items completed is non-negative. * \pre If the expected total is non-negative, then the new * number of items completed is at most the expected total. * * @param newCompleted the number of items completed. */ void setCompleted(long newCompleted); /** * Increases the number of items completed by the given amount. * * \pre If the expected total is non-negative, then the new * total number of items completed is at most the expected total. * * @param extraCompleted the number of items to add to the number of * items already completed. */ void incCompleted(unsigned long extraCompleted = 1); /** * Sets the expected total number of items. * * \pre If the new expected total is non-negative, then the * new expected total is at least the number of items completed. * * @param newOutOf the expected total number of items, or -1 if * this total is not known. */ void setOutOf(long newOutOf); virtual bool isPercent() const; protected: virtual std::string internalGetDescription() const; virtual double internalGetPercent() const; }; /*@}*/ // Inline functions inline NProgressMessage::NProgressMessage() : NProgress() { } inline NProgressMessage::NProgressMessage(const std::string& newMessage) : NProgress(), message(newMessage) { } inline NProgressMessage::NProgressMessage(const char* newMessage) : NProgress(), message(newMessage) { } inline std::string NProgressMessage::getMessage() const { MutexLock(this); changed = false; return message; } inline void NProgressMessage::setMessage(const std::string& newMessage) { MutexLock(this); message = newMessage; changed = true; } inline void NProgressMessage::setMessage(const char* newMessage) { MutexLock(this); message = newMessage; changed = true; } inline std::string NProgressMessage::internalGetDescription() const { return message; } inline NProgressStateNumeric::NProgressStateNumeric(long newCompleted, long newOutOf) : completed(newCompleted), outOf(newOutOf) { } inline NProgressNumber::NProgressNumber(long newCompleted, long newOutOf) : NProgress(), completed(newCompleted), outOf(newOutOf) { } inline long NProgressNumber::getCompleted() const { MutexLock(this); changed = false; return completed; } inline long NProgressNumber::getOutOf() const { MutexLock(this); changed = false; return outOf; } inline NProgressStateNumeric NProgressNumber::getNumericState() const { MutexLock(this); changed = false; return NProgressStateNumeric(completed, outOf); } inline void NProgressNumber::setCompleted(long newCompleted) { MutexLock(this); completed = newCompleted; changed = true; } inline void NProgressNumber::incCompleted(unsigned long extraCompleted) { MutexLock(this); completed += extraCompleted; changed = true; } inline void NProgressNumber::setOutOf(long newOutOf) { MutexLock(this); outOf = newOutOf; changed = true; } inline bool NProgressNumber::isPercent() const { MutexLock(this); return (outOf >= 0); } inline double NProgressNumber::internalGetPercent() const { return (outOf > 0 ? double(completed) * 100 / double(outOf) : double(0)); } } // namespace regina #endif regina-4.96/engine/README.txt000644 000765 000024 00000000270 12234011536 015547 0ustar00babstaff000000 000000 Regina Engine Directory ----------------------- This directory tree contains the C++ sources for the main calculation engine. This is where you will find all the "real mathematics". regina-4.96/engine/regina-config.h.in000644 000765 000024 00000004120 12311266525 017343 0ustar00babstaff000000 000000 /* Define if both signed and unsigned long long types are available. */ #cmakedefine LONG_LONG_FOUND /* Define if both int128_t and uint128_t types are available. */ #cmakedefine INT128_T_FOUND /* Define if both __int128_t and __uint128_t types are available. */ #cmakedefine __INT128_T_FOUND /* Define if native 128-bit arithmetic is available through either of the types defined above. */ #cmakedefine INT128_AVAILABLE /* Define if 64-bit integer literals are available with no suffix */ #cmakedefine NUMERIC_64_FOUND /* Define if 64-bit integer literals are available using the LL suffix */ #cmakedefine NUMERIC_64_LL_FOUND /* Define if Boost.Python is available. */ #cmakedefine BOOST_PYTHON_FOUND /* Define if langinfo.h and nl_langinfo() are available. */ #cmakedefine LANGINFO_FOUND /* Define if we are excluding Normaliz from the build. */ #cmakedefine EXCLUDE_NORMALIZ /* Define if we are excluding SnapPea / SnapPy from the build. */ #cmakedefine EXCLUDE_SNAPPEA /* Define as const if the declaration of iconv() needs const, or empty if not. */ #define ICONV_CONST @ICONV_CONST@ /* Define to Regina's primary home directory on the system. This can always be changed at runtime vi NGlobalDirs::setDirs(). */ #define REGINA_DATADIR "@PKGDATADIR@" /* Define to the directory on the system in which Regina's python module is installed, or the empty string if the module is installed in a standard python location (i.e., it can be found automatically on python's sys.path). This can always be changed at runtime vi NGlobalDirs::setDirs(). */ #define REGINA_PYLIBDIR "@PYLIBDIR@" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "@PACKAGE_STRING@" /* Define to the version of this package. */ #define PACKAGE_VERSION "@PACKAGE_VERSION@" /* Major version number of the package. */ #define PACKAGE_VERSION_MAJOR @PACKAGE_VERSION_MAJOR@ /* Minor version number of the package. */ #define PACKAGE_VERSION_MINOR @PACKAGE_VERSION_MINOR@ regina-4.96/engine/regina-core.h000644 000765 000024 00000011107 12377775347 016447 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file regina-core.h * \brief Core definitions that must be included in every Regina header file. */ #ifndef __REGINA_CORE_H #ifndef __DOXYGEN #define __REGINA_CORE_H #endif /** * \weakgroup engine * @{ */ #ifdef __DOXYGEN // Fake definitions just for doxygen. /** * All non-templated, non-static functions, classes and global variables * that are part of Regina's public interface \b must be declared with * REGINA_API. * In addition, global variables must also be declared with \c extern * as per normal. * Otherwise things may (and in some environments will) break when external * applications try to use Regina with optimisations such as gcc's * -fvisibility=hidden. * * Note: When building the Regina calculation engine shared library, * REGINA_DLL_EXPORTS must be defined (this ensures that API symbols are * marked for export). When importing (using) this library, * REGINA_DLL_EXPORTS must \e not be defined (this ensures that API symbols * are marked for import instead). */ #define REGINA_API /** * Classes and functions that are local to the current compilation unit * and should not be publicly exported may be declared with REGINA_LOCAL. * Use of this macro is optional. */ #define REGINA_LOCAL #else // The real definitions go here. // The macros below are modified from the instructions at // http://gcc.gnu.org/wiki/Visibility (retrieved on 22 May 2011). #if defined _WIN32 || defined __CYGWIN__ #define REGINA_HELPER_DLL_IMPORT __declspec(dllimport) #define REGINA_HELPER_DLL_EXPORT __declspec(dllexport) #define REGINA_HELPER_DLL_LOCAL #else #if __GNUC__ >= 4 #define REGINA_HELPER_DLL_IMPORT __attribute__ ((visibility("default"))) #define REGINA_HELPER_DLL_EXPORT __attribute__ ((visibility("default"))) #define REGINA_HELPER_DLL_LOCAL __attribute__ ((visibility("hidden"))) #else #define REGINA_HELPER_DLL_IMPORT #define REGINA_HELPER_DLL_EXPORT #define REGINA_HELPER_DLL_LOCAL #endif #endif // Assume that the library is always built as a shared library (not static). #ifdef REGINA_DLL_EXPORTS #define REGINA_API REGINA_HELPER_DLL_EXPORT #else #define REGINA_API REGINA_HELPER_DLL_IMPORT #endif #define REGINA_LOCAL REGINA_HELPER_DLL_LOCAL #endif // doxygen /*@}*/ #endif regina-4.96/engine/regina-engine-config.1000644 000765 000024 00000005753 12234011536 020121 0ustar00babstaff000000 000000 .TH REGINA-ENGINE-CONFIG 1 "September 8, 2011" .SH NAME regina-engine-config - get information about the installed version of Regina .SH SYNOPSIS .B regina-engine-config [\fB\-\-prefix\fP[=\fIDIR\fP]] [\fB\-\-exec\-prefix\fP[=\fIDIR\fP]] [\fB\-\-version\fP] [\fB\-\-libs\fP] [\fB\-\-cflags\fP] .SH DESCRIPTION .PP \fIregina-engine-config\fP tells you which compiler and linker flags should be used to build the mathematical engine of Regina into your own programs. Regina's mathematical engine is in the library \fIlibregina-engine.so\fP. .PP Regina is a software package for studying 3-manifold triangulations and normal surfaces. Other key features include angle structures, census enumeration, combinatorial recognition of triangulations, and high-level tasks such as 3-sphere recognition and connected sum decomposition. .SH OPTIONS \fIregina-engine-config\fP accepts the following options. .TP \fB\-\-prefix\fP=\fIDIR\fP Use DIR instead of the installation prefix that Regina was built with when computing the output for the \-\-cflags and \-\-libs options. This option is also used for the exec prefix if \-\-exec\-prefix is not specified. This option must be specified before any \-\-libs or \-\-cflags options. If no DIR is specified then the current installation prefix will be written to standard output. Most people will not need this option. .TP \fB\-\-exec\-prefix\fP=\fIDIR\fP Use DIR instead of the installation exec prefix that Regina was built with when computing the output for the \-\-cflags and \-\-libs options. This option must be specified before any \-\-libs or \-\-cflags options. If no DIR is specified then the current installation exec prefix will be written to standard output. Most people will not need this option. .TP .B \-\-version Print the currently installed version of Regina. .TP .B \-\-libs Print the linker flags that are required to link a program against the Regina calculation engine. .TP .B \-\-cflags Print the compiler flags that are required to compile a program that uses the Regina calculation engine. .SH SEE ALSO Regina includes a detailed users' handbook, which may be accessed through Regina's help menu or read online at \fIhttp://regina.sourceforge.net/\fP . .SH AUTHOR This utility was written by Ben Burton , and is licensed under the GNU General Public License. Many people have been involved in the development of Regina; see the users' handbook for a full list of acknowledgements. .PP This script regina-engine-config and its manual page were modified from \fIgtk-config\fP, which contains the following notice: .PP .RS Copyright \(co 1998 Owen Taylor .PP Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. .RE .PP Note that the permission statement above applies only to regina-engine-config, and not to Regina as a whole. regina-4.96/engine/regina-engine-config.in000644 000765 000024 00000004166 12376517454 020405 0ustar00babstaff000000 000000 #!/bin/sh # # This script is based on gtk-config, whose documentation contains the # following notice: # # Copyright (C) 1998 Owen Taylor # # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose and without fee is hereby granted, # provided that the above copyright notice appear in all copies and that # both that copyright notice and this permission notice appear in # supporting documentation. # # Changes to this script were made by Ben Burton and are # released under the same license as above. prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix_set=no usage() { cat <&2 fi while test $# -gt 0; do case "$1" in -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;; *) optarg= ;; esac case $1 in --prefix=*) prefix=$optarg if test $exec_prefix_set = no ; then exec_prefix=$optarg fi ;; --prefix) echo_prefix=yes ;; --exec-prefix=*) exec_prefix=$optarg exec_prefix_set=yes ;; --exec-prefix) echo_exec_prefix=yes ;; --version) echo @PACKAGE_VERSION@ ;; --cflags) echo_cflags=yes ;; --libs) echo_libs=yes ;; *) usage 1 1>&2 ;; esac shift done if test "$echo_prefix" = "yes"; then echo $prefix fi if test "$echo_exec_prefix" = "yes"; then echo $exec_prefix fi regina_engine_libs="-lregina-engine @RECONFIG_LINK_FLAGS@" if test "$echo_cflags" = "yes"; then includes="@RECONFIG_INCLUDE_FLAGS@" includes="-I@INCLUDEDIR@ $includes" echo $includes fi if test "$echo_libs" = "yes"; then libdirs=-L@LIBDIR@ my_regina_engine_libs= for i in $regina_engine_libs ; do if test "x$i" != "x-L@LIBDIR@" ; then if test -z "$my_regina_engine_libs" ; then my_regina_engine_libs="$i" else my_regina_engine_libs="$my_regina_engine_libs $i" fi fi done echo $libdirs $my_regina_engine_libs fi regina-4.96/engine/shareableobject.cpp000644 000765 000024 00000005113 12377776645 017726 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "shareableobject.h" namespace regina { std::string ShareableObject::str() const { std::ostringstream out; writeTextShort(out); return out.str(); } std::string ShareableObject::detail() const { std::ostringstream out; writeTextLong(out); return out.str(); } } // namespace regina regina-4.96/engine/shareableobject.h000644 000765 000024 00000015125 12377775350 017367 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file shareableobject.h * \brief Deals with objects that can be shared from the * calculation engine with the outside world. */ #ifndef __SHAREABLEOBJECT_H #ifndef __DOXYGEN #define __SHAREABLEOBJECT_H #endif #include #include #include "regina-core.h" #include "utilities/boostutils.h" namespace regina { /** * \weakgroup engine * @{ */ /** * Facilitates mirroring objects in the underlying C++ calculation * engine using the various wrapper classes provided in the various * external interfaces (such as the Python interface). * * In the underlying C++ engine, a ShareableObject is an object that can * be shared with the outside world. In the external * interfaces, a ShareableObject is a vacuous wrapper that allows access * to the data and methods of the corresponding object in the underlying * engine. * * See the various interface notes pages for more details regarding * using classes derived from ShareableObject. */ class REGINA_API ShareableObject : public regina::boost::noncopyable { public: /** * \name Constructors and Destructors */ /*@{*/ /** * Default constructor that does nothing. * * \ifacespython Not present. */ ShareableObject(); /** * Default destructor that does nothing. */ virtual ~ShareableObject(); /*@}*/ /** * \name Input and Output */ /*@{*/ /** * Writes this object in short text format to the given output stream. * The output should be human-readable, should fit on a single line, * and should not end with a newline. * * \ifacespython The parameter \a out does not exist; * standard output will be used. * * @param out the output stream to which to write. */ virtual void writeTextShort(std::ostream& out) const = 0; /** * Writes this object in long text format to the given output stream. * The output should provide the user with all the information they * could want. The output should be human-readable, should not * contain extremely long lines (so users can read the output * in a terminal), and should end with a final newline. * * The default implementation of this routine merely calls * writeTextShort() and adds a newline. * * \ifacespython The parameter \a out does not exist; * standard output will be used. * * @param out the output stream to which to write. */ virtual void writeTextLong(std::ostream& out) const; /** * Returns the output from writeTextShort() as a string. * * \ifacespython This implements the __str__() function. * * @return a short text representation of this object. */ std::string str() const; /** * A deprecated alias for str(), which returns the output from * writeTextShort() as a string. * * \deprecated This routine has (at long last) been deprecated; * use the simpler-to-type str() instead. * * @return a short text representation of this object. */ std::string toString() const; /** * Returns the output from writeTextLong() as a string. * * @return a long text representation of this object. */ std::string detail() const; /** * A deprecated alias for detail(), which returns the output * from writeTextLong() as a string. * * \deprecated This routine has (at long last) been deprecated; * use the simpler-to-type detail() instead. * * @return a long text representation of this object. */ std::string toStringLong() const; /*@}*/ }; /*@}*/ // Inline functions for ShareableObject inline ShareableObject::ShareableObject() { } inline ShareableObject::~ShareableObject() { } inline void ShareableObject::writeTextLong(std::ostream& out) const { writeTextShort(out); out << '\n'; } inline std::string ShareableObject::toString() const { return str(); } inline std::string ShareableObject::toStringLong() const { return detail(); } } // namespace regina #endif regina-4.96/engine/snappea/CMakeLists.txt000644 000765 000024 00000001170 12377774107 020262 0ustar00babstaff000000 000000 # snappea # Files to compile SET ( FILES fundgroup homology nsnappeatriangulation nxmlsnappeareader uimessages) # Prepend folder name FOREACH ( SOURCE_FILE ${FILES} ) SET ( SOURCES ${SOURCES} snappea/${SOURCE_FILE}) ENDFOREACH(SOURCE_FILE) ADD_SUBDIRECTORY(kernel) ADD_SUBDIRECTORY(snappy) # Set the variable in the parent directory SET(SOURCES ${SOURCES} PARENT_SCOPE) SET(SOURCES_C_AS_CPP ${SOURCES_C_AS_CPP} PARENT_SCOPE) if (${REGINA_INSTALL_DEV}) INSTALL(FILES nsnappeatriangulation.h nxmlsnappeareader.h DESTINATION ${INCLUDEDIR}/snappea COMPONENT Development) endif (${REGINA_INSTALL_DEV}) regina-4.96/engine/snappea/fundgroup.cpp000644 000765 000024 00000010774 12377776646 020263 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "snappea/nsnappeatriangulation.h" #include "snappea/kernel/SnapPea.h" namespace regina { const NGroupPresentation* NSnapPeaTriangulation::fundamentalGroupFilled( bool simplifyPresentation, bool fillingsMayAffectGenerators, bool minimiseNumberOfGenerators) const { if (fundGroupFilled_.known()) return fundGroupFilled_.value(); if (! data_) return 0; // Note: TRUE and FALSE are #defines in SnapPea, and so don't live in any // namespace. We avoid them here, and directly use 0 and 1 instead. // Pass all the work to SnapPea. regina::snappea::GroupPresentation* pres = regina::snappea::fundamental_group(data_, (simplifyPresentation ? 1 : 0), (fillingsMayAffectGenerators ? 1 : 0), (minimiseNumberOfGenerators ? 1 : 0)); // Convert the results into Regina's NGroupPresentation class. // Note that SnapPea gives a sequence of generators, whereas Regina // gives a sequence of (generator, exponent) pairs. Therefore we // "compress" relations below to group consecutive occurrences of // the same generator, even if simplifyPresentation is false. NGroupPresentation* ans = new NGroupPresentation(); ans->addGenerator(regina::snappea::fg_get_num_generators(pres)); unsigned i; int *sReln, *sPos; int gen, currGen, currExp; NGroupExpression* rReln; for (i = 0; i < regina::snappea::fg_get_num_relations(pres); ++i) { sReln = regina::snappea::fg_get_relation(pres, i); rReln = new NGroupExpression(); currGen = currExp = 0; for (sPos = sReln; *sPos; ++sPos) { gen = (*sPos > 0 ? *sPos : -*sPos); if (gen != currGen) { if (currExp) rReln->addTermLast(currGen - 1, currExp); currGen = gen; currExp = 0; } if (*sPos > 0) ++currExp; else --currExp; } if (currExp) rReln->addTermLast(currGen - 1, currExp); ans->addRelation(rReln); regina::snappea::fg_free_relation(sReln); } regina::snappea::free_group_presentation(pres); return (fundGroupFilled_ = ans); } } // namespace regina regina-4.96/engine/snappea/homology.cpp000644 000765 000024 00000006343 12377776646 020104 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "maths/nmatrixint.h" #include "snappea/nsnappeatriangulation.h" #include "snappea/kernel/kernel_prototypes.h" namespace regina { const NAbelianGroup* NSnapPeaTriangulation::homologyFilled() const { if (! data_) return 0; if (h1Filled_.known()) return h1Filled_.value(); // Fetch the relation matrix from SnapPea. regina::snappea::RelationMatrix sRelns; regina::snappea::homology_presentation(data_, &sRelns); if (! sRelns.relations) return (h1Filled_ = 0); // Pass the relations to Regina. NMatrixInt rRelns(sRelns.num_rows, sRelns.num_columns); unsigned i, j; for (i = 0; i < sRelns.num_rows; ++i) for (j = 0; j < sRelns.num_columns; ++j) rRelns.entry(i, j) = sRelns.relations[i][j]; regina::snappea::free_relations(&sRelns); // Let Regina run Smith normal form. NAbelianGroup* ans = new NAbelianGroup(); ans->addGroup(rRelns); return (h1Filled_ = ans); } } // namespace regina regina-4.96/engine/snappea/kernel/abelian_group.c000644 000765 000024 00000024346 12377774107 021767 0ustar00babstaff000000 000000 /* * abelian_group.c * * This file contains the following functions which the kernel * provides for the UI: * * void expand_abelian_group(AbelianGroup *g); * void compress_abelian_group(AbelianGroup *g); * void free_abelian_group(AbelianGroup *g); * * expand_abelian_group() expands an AbelianGroup into its most * factored form, e.g. Z/2 + Z/2 + Z/4 + Z/3 + Z/9 + Z. * Each nonzero torsion coefficient is a power of a prime. * These are the "primary invariants" of the group * (cf. Hartley & Hawkes' Rings, Modules and Linear Algebra, * Chapman & Hall 1970, page 154). * * compress_abelian_group compresses an AbelianGroup into its least * factored form, e.g. Z/2 + Z/6 + Z/36 + Z. * Each torsion coefficient divides all subsequent torsion coefficients. * These are the "torsion invariants" of the group * (cf. Hartley & Hawkes' Rings, Modules and Linear Algebra, * Chapman & Hall 1970, page 153). * * free_abelian_group() frees the memory used to hold the AbelianGroup *g. * As explained in the documentation preceding the definition of an * AbelianGroup in SnapPea.h, only the kernel may allocate or deallocate * AbelianGroups. */ #include "kernel.h" #include /* needed for qsort() */ #include "kernel_namespace.h" typedef struct prime_power { int prime, power; struct prime_power *next; } PrimePower; static int compare_prime_powers(const void *pp0, const void *pp1); void expand_abelian_group( AbelianGroup *g) { PrimePower *prime_power_list, *new_prime_power, **array_of_pointers, *this_prime_power; int num_prime_powers, torsion_free_rank; long int m, p, this_coefficient; int i, count; /* * The documentation at the top of this file specifies the behavior * of expand_abelian_group(). */ /* * Ignore nonexistent groups. */ if (g == NULL) return; /* * The algorithm is to factor each torsion coefficient into prime * powers, combine the prime powers for all the torsion coefficients * into a single list, sort the list, and write the results back * to the torsion coefficients array (after allocating more memory * for the array, of course). */ prime_power_list = NULL; num_prime_powers = 0; torsion_free_rank = 0; for (i = 0; i < g->num_torsion_coefficients; i++) { /* * For notational convenience, let m be the torsion coefficient * under consideration. */ m = g->torsion_coefficients[i]; /* * If m is zero (indicating an infinite cyclic factor), make a * note of it and move on to the next torsion coefficient. */ if (m == 0L) { torsion_free_rank++; continue; } /* * Factor m. * (Much more efficient algorithms could be used to factor m, but at the * moment I'm assuming the numbers involved will be small, so the * simplicity of the code is more important than its efficiency.) */ /* * Consider each potential prime divisor p of m. * (We "accidently" consider composite divisors as well, * but the wasted effort shouldn't be too significant.) */ for (p = 2; m > 1L; p++) { /* * Does p divide m? * If so, then p must be prime, since otherwise some previous value * of p would have divided m, and would have been factored out. * Find the largest power of p which divides m, and record it on * the prime_power_list. */ if (m%p == 0L) { new_prime_power = NEW_STRUCT(PrimePower); new_prime_power->prime = p; new_prime_power->power = 0; new_prime_power->next = prime_power_list; prime_power_list = new_prime_power; num_prime_powers++; while (m%p == 0L) { m /= p; new_prime_power->power++; } } /* * If m is less than p^2, then m must be prime or one. * * if m is prime, we set p = m - 1, so that on the next * pass through the loop (after the "p++"), p will * equal m, and we'll finish up. * * If m is one, then the loop will terminate no matter * what p is, so there's no harm in setting p = m - 1. */ if (m < p * p) p = m - 1; } } /* * Set num_torsion_coefficients, and reallocate space * for the (presumably larger) array. */ g->num_torsion_coefficients = num_prime_powers + torsion_free_rank; if (g->torsion_coefficients != NULL) my_free(g->torsion_coefficients); if (g->num_torsion_coefficients > 0) g->torsion_coefficients = NEW_ARRAY(g->num_torsion_coefficients, long int); else g->torsion_coefficients = NULL; /* * If the list of PrimePowers is nonempty, sort it and read it * into the torsion_coefficients array. */ if (num_prime_powers > 0) { /* * Create an array of pointers to the PrimePowers. */ array_of_pointers = NEW_ARRAY(num_prime_powers, PrimePower *); for ( i = 0, this_prime_power = prime_power_list; i < num_prime_powers; i++, this_prime_power = this_prime_power->next) array_of_pointers[i] = this_prime_power; if (this_prime_power != NULL) uFatalError("expand_abelian_group", "abelian_group"); qsort(array_of_pointers, num_prime_powers, sizeof(PrimePower *), compare_prime_powers); for (i = 0; i < num_prime_powers; i++) { /* * Multiply out the current torsion coefficient . . . */ this_coefficient = 1L; for (count = 0; count < array_of_pointers[i]->power; count++) this_coefficient *= array_of_pointers[i]->prime; /* * . . . write it into the array . . . */ g->torsion_coefficients[i] = this_coefficient; /* * . . . and free the PrimePower. */ my_free(array_of_pointers[i]); } my_free(array_of_pointers); } /* * Write a torsion coefficient of zero for each infinite cyclic factor. */ for (i = num_prime_powers; i < g->num_torsion_coefficients; i++) g->torsion_coefficients[i] = 0L; } static int compare_prime_powers( const void *pp0, const void *pp1) { if ((*(PrimePower **)pp0)->prime < (*(PrimePower **)pp1)->prime) return -1; if ((*(PrimePower **)pp0)->prime > (*(PrimePower **)pp1)->prime) return +1; if ((*(PrimePower **)pp0)->power < (*(PrimePower **)pp1)->power) return -1; if ((*(PrimePower **)pp0)->power > (*(PrimePower **)pp1)->power) return +1; return 0; } void compress_abelian_group( AbelianGroup *g) { int i, ii, j; long int m, n, d; /* * The documentation at the top of this file specifies the behavior * of compress_abelian_group(). */ /* * Ignore nonexistent groups. */ if (g == NULL) return; /* * Beginning at the start of the list, adjust each torsion coefficient * so that it divides all subsequent torsion coefficients. */ for (i = 0; i < g->num_torsion_coefficients; i++) for (j = i + 1; j < g->num_torsion_coefficients; j++) { /* * For clarity, let the torsion coefficients under * consideration be called m and n. */ m = g->torsion_coefficients[i]; n = g->torsion_coefficients[j]; /* * If both m and n are zero, go on to the next * iteration of the loop. */ if (m == 0L && n == 0L) continue; /* * Compute the greatest common divisor of m and n. * Note that the greatest common divisor, which is * defined iff m and n are not both zero, will always * be nonzero. */ d = gcd(m, n); /* * Define m' = m/d. Replace m with d, and n with n * m'. * To convince yourself that this is valid, consider * the factorizations of m and n into powers of primes. * In effect, we are swapping the higher power of a given * prime from m to n, e.g. {m = 8, n = 4} -> {m = 4, n = 8}. */ n *= m / d; m = d; /* * Write the values of m and n back into the torsion_coefficients * array. */ g->torsion_coefficients[i] = m; g->torsion_coefficients[j] = n; } /* * Delete torsion coefficients of one, and adjust * g->num_torsion_coefficients accordingly. */ /* * First set ii to be the index of the first non-one, if any. */ for ( ii = 0; ii < g->num_torsion_coefficients && g->torsion_coefficients[ii] == 1L; ii++) ; /* * Now shift all the non-ones to the start of the array, * overwriting the ones. (Note that this algorithm is valid * even if the array contains all ones, or no ones.) */ for (i = 0; ii < g->num_torsion_coefficients; i++, ii++) g->torsion_coefficients[i] = g->torsion_coefficients[ii]; /* * Set g->num_torsion_coefficients to its correct value; */ g->num_torsion_coefficients = i; } void free_abelian_group( AbelianGroup *g) { if (g != NULL) { if (g->torsion_coefficients != NULL) my_free(g->torsion_coefficients); my_free(g); } } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/canonize.c000644 000765 000024 00000002613 12377774107 020757 0ustar00babstaff000000 000000 /* * canonize.c * * This file provides the function * * FuncResult canonize(Triangulation *manifold); * * canonize() is a shell, which calls the functions * * proto_canonize() [found in canonize_part_1.c] * canonical_retriangulation() [found in canonize_part_2.c] * * The purpose of these functions is explained in the code below. * For the mathematical details, please see canonize_part_1.c * and canonize_part_2.c. * * canonize() does not preserve the original Triangulation; * if you need to keep it, make a copy with copy_triangulation() * before calling canonize(). */ #include "kernel.h" #include "kernel_namespace.h" FuncResult canonize( Triangulation *manifold) { /* * Apply the tilt theorem to compute a Triangulation * which is a subdivision of the canonical cell decomposition. * Please see canonize_part_1.c for details. */ if (proto_canonize(manifold) == func_failed) return func_failed; /* * Replace the given subdivision of the canonical cell * decomposition with the canonical retriangulation. * This operation introduces finite vertices whenever * the canonical cell decomposition is not a triangulation * to begin with. Please see canonize_part_2.c for details. */ canonical_retriangulation(manifold); return func_OK; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/canonize.h000644 000765 000024 00000002144 12354465077 020761 0ustar00babstaff000000 000000 /* * canonize.h * * In canonize_part_1.c, canonize_part_2.c, and canonize_result.c, the sum * of the tilts of two Tetrahedra relative to their common face is * considered to be zero iff it lies between -CONCAVITY_EPSILON and * +CONCAVITY_EPSILON. * * 95/10/20 cusp_neighborhoods.c now includes this file as well, * so it can supress the drawing of faces which serve only to subdivide * the canonical cell decomposition into tetrahedra. * * 97/3/1 The processing of the data for 16-crossing knots led * to several examples which sometimes were reported to have * canonical decompositions with cells other than tetrahedra, * and sometimes not. This led me to suspect that CONCAVITY_EPSILON * was too big, so I changed it from 1e-6 to 1e-7. (This problem * hadn't arisen with snappea 1.3.x because the latter normalized * cusp volumes to 1.0, whereas SnapPea 2.x normalizes them to * (3/16)sqrt(3).) Eventually I may need to adopt a more sophisticated * approach to using CONCAVITY_EPSILON, somehow taking into account * the volume of the cusp. */ #define CONCAVITY_EPSILON 1e-7 regina-4.96/engine/snappea/kernel/canonize_part_1.c000644 000765 000024 00000044006 12377774107 022227 0ustar00babstaff000000 000000 /* * canonize_part_1.c * * This file provides the function * * FuncResult proto_canonize(Triangulation *manifold); * * which replaces a Triangulation by the canonical triangulation * of the same manifold (if the canonical cell decomposition is a * triangulation) or by an arbitrary subdivision of the canonical * cell decomposition into Tetrahedra (if the canonical cell * decomposition contains cells other than tetrahedra). The * primary purpose of proto_canonize() is to be called by the * function canonize() (in canonize.c), although it can be called * for other reasons, too, such as checking whether a manifold * is a 2-bridge knot or link complement. * * proto_canonize() does not preserve the original Triangulation * (if you want to keep it, copy it with copy_triangulation() before * calling proto_canonize()). The Triangulation must admit a hyperbolic * structure. If one is not already present, proto_canonize() will call * find_complete_hyperbolic_structure() to compute it. * * proto_canonize() returns * * func_OK if the hyperbolic structure is of type * geometric_solution or nongeometric_solution * (in which case it will have found a subdivision * of the canonical cell decomposition) * * func_failed if the hyperbolic structure is of type * flat_solution, degenerate_solution, other_solution, * or no_solution (in which case it will not have * attempted the canonization) * * When proto_canonize() returns func_OK, a subdivision of the * canonical cell decomposition will be present, but because of the * possible need for random retriangulation (see below) I cannot * prove that proto_canonize() will terminate in all cases (but in * practice it always does). * * proto_canonize() uses the algorithm of * * J. Weeks, Convex hulls and isometries of cusped hyperbolic * 3-manifolds, Topology Appl. 52 (1993) 127-149. * * The Tilt Theorem (contained in the above paper) is generalized * and given a nicer proof in * * M. Sakuma and J. Weeks, The generalized tilt formula, * Geometriae Dedicata 55 (1995) 115-123. * * Although the algorithm of "Convex hulls..." works fine in practice, * it has the aesthetic flaw that it does occasionally get stuck on * negatively oriented Tetrahedra, in which case it randomly retriangulates * the manifold and starts over. I've tried to find a new algorithm * which avoids this problem (while retaining the present algorithm's * virtues, namely that it's super fast, and provides an iron-clad * guarantee that the topology of the manifold does not change), but * so far without success. Maybe someday. * * Technical note: The canonization algorithm uses only the complete * hyperbolic structure, but the low-level retriangulation operations * (e.g. two_to_three()) will object if the filled structure is degenerate. * We take a strong precaution: we overwrite the filled structure with * the complete structure and let polish_hyperbolic_structures() recompute * the correct filled structure at the end. This really isn't as * inefficient as it sounds. Either the filled structure will be fairly * close to the complete structure, in which case it will be computed * quickly, or it will be far from the complete structure, in which * case the need to provide valid shape histories will force * polish_hyperbolic_structures() to recompute the filled structure * from scratch anyhow. * * Programming note: The old version of canonize.c shuffled the * tetrahedra about on various queues. The present code does not * do this. Instead, every time it makes some progress (cancellation * or a 2-3 or 3-2 move) it starts the loop over. This causes some * unnecessary scanning of the EdgeClass list, but I feel the wasted * time is small, and is more than compensated for by the reduced * complexity of the code. */ #include "kernel.h" #include "canonize.h" #include "kernel_namespace.h" #define MAX_ATTEMPTS 64 #define MAX_RETRIANGULATIONS 64 #define MAX_MOVES 1000 #define ANGLE_EPSILON 1e-6 static FuncResult validate_hyperbolic_structure(Triangulation *manifold); static Boolean attempt_cancellation(Triangulation *manifold); static Boolean attempt_three_to_two(Triangulation *manifold); static Boolean concave_edge(EdgeClass *edge); static Boolean attempt_two_to_three(Triangulation *manifold); static Boolean concave_face(Tetrahedron *tet, FaceIndex f); static Real sum_of_tilts(Tetrahedron *tet0, FaceIndex f0); static Boolean would_create_negatively_oriented_tetrahedra(Tetrahedron *tet0, FaceIndex f0); static Boolean validate_canonical_triangulation(Triangulation *manifold); FuncResult proto_canonize( Triangulation *manifold) { /* * 95/10/12 JRW * I added the needs_polishing flag so that the solution will be * polished iff it needs to be. In the past this was no big deal, * but now we want the cusp neighborhoods module to be able to * maintain a canonical triangulation in real time. If no changes * need to be made and all cusps are complete (so we don't have to * worry about restoring the filled solution), we want to get out * of here as quickly as possible. */ Boolean all_done, needs_polishing; int num_attempts, i; num_attempts = 0; needs_polishing = FALSE; do { /* * First make sure that a hyperbolic structure is present, and * all Tetrahedra are positively oriented. Overwrite the filled * structure with the complete one. */ if (manifold->solution_type[complete] == geometric_solution && all_cusps_are_complete(manifold) == TRUE) { /* * This is the express route. * * No polishing will be required if the triangulation is * already canonical, because the hyperbolic structure won't * change and there is no need to restore the filled solution. */ } else { /* * This is the generic algorithm. * * (validate_hyperbolic_structure() overwrites the filled * solution with the complete solution.) */ if (validate_hyperbolic_structure(manifold) == func_failed) { compute_CS_fudge_from_value(manifold); return func_failed; } needs_polishing = TRUE; } /* * Choose cusp cross sections bounding equal volumes, * and use the Tilt Theorem to compute the tilts. * (See "Convex hulls..." for details.) */ allocate_cross_sections(manifold); compute_cross_sections(manifold); compute_tilts(manifold); /* * Keep going through the following loop as long as we * continue to keep improving the triangulation. * Do not perform any operation (i.e. any two_to_three() * move) that would create negatively oriented Tetrahedra. * * It is possible to get into an infinite loop here, doing an * endless series of 2->3 and 3->2 moves, presumably * do to numerical instability. Thus the total number of * moves is capped. */ for(i = 0; i < MAX_MOVES*manifold->num_tetrahedra; i++) { /* * Cancel pairs of Tetrahedra sharing an EdgeClass * of order two. (Since the Triangulation contains * no negatively oriented Tetrahedra, Tetrahedra sharing * an EdgeClass of order two will be within epsilon of * being flat.) */ if (attempt_cancellation(manifold) == TRUE) { needs_polishing = TRUE; continue; } /* * Perform 3-2 moves whereever necessary. */ if (attempt_three_to_two(manifold) == TRUE) { needs_polishing = TRUE; continue; } /* * Perform 2-3 moves whereever necessary. */ if (attempt_two_to_three(manifold) == TRUE) { needs_polishing = TRUE; continue; } /* * We can't make any more progress. * Break out of the loop, and then check whether we've * really found a subdivision of the canonical cell * decomposition, or whether we've had the misfortune to * get stuck on (potential) negatively oriented Tetrahedra. */ break; } /* * We don't need the VertexCrossSections any more, so * we might as well get rid of them before (possibly) * randomizing the manifold. */ free_cross_sections(manifold); /* * Did we really find a subdivision of the canonical * cell decomposition? * Or did we just get stuck on (potential) negatively * oriented Tetrahedra? */ all_done = validate_canonical_triangulation(manifold); /* * If we got stuck on (potential) negatively oriented * Tetrahedra, randomize the Triangulation and try * again. */ if (all_done == FALSE) randomize_triangulation(manifold); /* * The documentation says that if a hyperbolic structure * with all positively oriented tetrahedra is present, then * proto_canonize() will never fail. And indeed with enough * random retriangulations it should always be able to find * a subdivision of the canonical cell decomposition. But * if a bug shows up somewhere we don't want this loop to run * forever, so if num_attempts exceeds MAX_ATTEMPTS we should * declare a fatal error and quit. */ if (++num_attempts > MAX_ATTEMPTS) uFatalError("proto_canonize", "canonize_part_1"); } while (all_done == FALSE); /* * Clean up. */ if (needs_polishing == TRUE) { /* * polish_hyperbolic_structures() takes responsibility for * the shape_histories. */ tidy_peripheral_curves(manifold); polish_hyperbolic_structures(manifold); /* * If the Chern-Simons invariant is present, update the fudge factor. */ compute_CS_fudge_from_value(manifold); } return func_OK; } static FuncResult validate_hyperbolic_structure( Triangulation *manifold) { int i; /* * First make sure some sort of solution is in place. */ if (manifold->solution_type[complete] == not_attempted) find_complete_hyperbolic_structure(manifold); /* * If the solution is something other than geometric_solution * or nongeometric_solution, we're out of luck. */ if (manifold->solution_type[complete] != geometric_solution && manifold->solution_type[complete] != nongeometric_solution) return func_failed; /* * Overwrite the filled structure with the complete structure * to keep the low-level retriangulation routines happy. * (See the technical note at the top of this file for a * more complete explanation.) */ copy_solution(manifold, complete, filled); /* * If all Tetrahedra are positively oriented, we're golden. */ if (manifold->solution_type[complete] == geometric_solution) return func_OK; /* * Try to find a geometric_solution by randomizing the Triangulation. * If we can't find one within MAX_RETRIANGULATIONS randomizations, * give up and return func_failed. */ for (i = 0; i < MAX_RETRIANGULATIONS; i++) { randomize_triangulation(manifold); if (manifold->solution_type[complete] == geometric_solution) return func_OK; } /* * Before we go, we'd better restore the filled solution. */ polish_hyperbolic_structures(manifold); return func_failed; } static Boolean attempt_cancellation( Triangulation *manifold) { EdgeClass *edge, *where_to_resume; for (edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) if (edge->order == 2) if (cancel_tetrahedra(edge, &where_to_resume, &manifold->num_tetrahedra) == func_OK) return TRUE; return FALSE; } static Boolean attempt_three_to_two( Triangulation *manifold) { EdgeClass *edge, *where_to_resume; /* * Note: It's easy to prove that if the three original Tetrahedra * are positively oriented, then the two new Tetrahedra must be * positively oriented as well. So we needn't worry about negatively * oriented Tetrahedra here. */ for (edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) if (edge->order == 3) if (concave_edge(edge) == TRUE) { if (three_to_two(edge, &where_to_resume, &manifold->num_tetrahedra) == func_OK) return TRUE; else /* * The only reason three_to_two() can fail is that the * three Tetrahedra surrounding the EdgeClass are not * distinct. But by Corolloary 3 of "Convex hulls..." * this cannot happen where the hull is concave. */ uFatalError("attempt_three_to_two", "canonize_part_1"); } return FALSE; } static Boolean concave_edge( EdgeClass *edge) { Tetrahedron *tet; FaceIndex f; /* * The hull in Minkowski space will be concave at an EdgeClass * of order 3 iff it is concave at each of the ideal 2-simplices * incident to the EdgeClass. */ tet = edge->incident_tet; f = one_face_at_edge[edge->incident_edge_index]; /* * According to Section 5 of "Convex hulls..." or Proposition 1.2 * of "Canonical cell decompositions...", a dihedral angle on the * hull will be concave iff the sum of the tilts is positive. * * We want to create a triangulation with as few Tetrahedra as possible, * so when the sum of the tilts is zero, we should return TRUE so the * three_to_two() move will be performed. Thus we return TRUE iff * the sum of the tilts is greater than some small negative epsilon. */ return ( sum_of_tilts(tet, f) > - CONCAVITY_EPSILON ); } static Boolean attempt_two_to_three( Triangulation *manifold) { Tetrahedron *tet; FaceIndex f; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (f = 0; f < 4; f++) if (concave_face(tet, f) == TRUE && would_create_negatively_oriented_tetrahedra(tet, f) == FALSE) { if (two_to_three(tet, f, &manifold->num_tetrahedra) == func_OK) return TRUE; else /* * We should never get to this point. */ uFatalError("attempt_two_to_three", "canonize_part_1.c"); } return FALSE; } static Boolean concave_face( Tetrahedron *tet, FaceIndex f) { /* * According to Section 5 of "Convex hulls..." or Proposition 1.2 * of "Canonical cell decompositions...", a dihedral angle on the * hull will be concave iff the sum of the tilts is positive. * * If the sum of the tilts is zero we want to return FALSE, * to avoid an unnecessary two_to_three() move. * So we check whether the sum is greater than some small * positive epsilon. */ return ( sum_of_tilts(tet, f) > CONCAVITY_EPSILON ); } static Real sum_of_tilts( Tetrahedron *tet0, FaceIndex f0) { Tetrahedron *tet1; FaceIndex f1; tet1 = tet0->neighbor[f0]; f1 = EVALUATE(tet0->gluing[f0], f0); return ( tet0->tilt[f0] + tet1->tilt[f1] ); } static Boolean would_create_negatively_oriented_tetrahedra( Tetrahedron *tet0, FaceIndex f0) { Permutation gluing; Tetrahedron *tet1; FaceIndex f1, side0, side1; gluing = tet0->gluing[f0]; tet1 = tet0->neighbor[f0]; f1 = EVALUATE(gluing, f0); /* * tet0 and tet1 meet at a common 2-simplex. For each edge * of that 2-simplex, add the incident dihedral angles of * tet0 and tet1. If any such sum is greater than pi, then * the two_to_three() move would create a negatively oriented * Tetrahedron on that side, and we return TRUE. Otherwise * no negatively oriented Tetrahedra will be created, and we * return FALSE. * * Choose ANGLE_EPSILON to allow the creation of Tetrahedra which * are just barely negatively oriented, but essentially flat. */ for (side0 = 0; side0 < 4; side0++) { if (side0 == f0) continue; side1 = EVALUATE(gluing, side0); if (tet0->shape[complete]->cwl[ultimate][edge3_between_faces[f0][side0]].log.imag + tet1->shape[complete]->cwl[ultimate][edge3_between_faces[f1][side1]].log.imag > PI + ANGLE_EPSILON) return TRUE; } return FALSE; } static Boolean validate_canonical_triangulation( Triangulation *manifold) { Tetrahedron *tet; FaceIndex f; /* * Check whether the sum of the tilts is nonnegative at each 2-simplex. */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (f = 0; f < 4; f++) if (concave_face(tet, f) == TRUE) return FALSE; return TRUE; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/canonize_part_2.c000644 000765 000024 00000052263 12377774107 022234 0ustar00babstaff000000 000000 /* * canonize_part_2.c * * This file provides the function * * void canonical_retriangulation(Triangulation *manifold); * * which accepts an arbitrary subdivision of a canonical cell decomposition * into Tetrahedra, and replaces it with a canonical retriangulation * (defined below). If the canonical cell decomposition is itself a * triangulation (as is typically the case) then the canonical retriangulation * is just the canonical cell decomposition itself. If the canonical cell * decomposition is not a triangulation, the canonical retriangulation will * introduce a finite vertex at the center of each 3-cell. * canonical_retriangulation() is intended to follow a call to proto_canonize() * (cf. the function canonize() in canonize.c); it assumes the tet->tilt[] * fields are correct. * * If *manifold has a hyperbolic structure and/or VertexCrossSections, * they are discarded. * * * Definition of the canonical retriangulation. * * The canonical cell decomposition of a cusped hyperbolic 3-manifold * is defined in * * J. Weeks, Convex hulls and isometries of cusped hyperbolic * 3-manifolds, Topology Appl. 52 (1993) 127-149. * * and * * M. Sakuma and J. Weeks, The generalized tilt formula, * Geometriae Dedicata 55 (1995) 115-123. * * If the canonical cell decomposition is a triangulation (as is * typically the case), then the canonical retriangulation is just * the canonical cell decomposition itself. Otherwise, the canonical * retriangulation is defined by the following two step procedure. * * Step #1. Subdivide each 3-cell by coning its boundary to a point * in its interior. * * Step #2. Each 2-cell in the canonical cell decomposition (just * the original 2-cells, not the 2-cells introduced in Step #1) * is the boundary between two 3-cells created at Step #1. * The union of the two 3-cells is the suspension of the * 2-cell between two of the vertices introduced in Step #1. * Triangulate this suspension in the "obvious" symmetrical way, * as n tetrahedra surrounding a common edge, where n is the * number of sides of the 2-cell, and the common edge runs * from one finite vertex to the other. * * This two-step procedure defines a canonical retriangulation of * the canonical cell decomposition. Note that it's not a subdivision. * * * Computing the canonical retriangulation. * * The following is a mathematical explanation of the algorithm. * The details of the implementation are documented in the code itself. * * We begin with an arbitrary subdivision of the canonical cell * decomposition into Tetrahedra. * * Definition. A 2-cell in the Triangulation is called "opaque" if * it lies in the 2-skeleton of the canonical cell decomposition, * and "transparent" if lies in the interior of a 3-cell of the * canonical decomposition. * * Step #1. * To cone a 3-cell to a point in its interior, first do a one-to-four * move to cone a single Tetrahedron to a point in its interior. * If that was the only Tetrahedron in the 3-cell, we're done. * Otherwise, perform a two-to-three move across a transparent face of * the coned tetrahedron. This yields a coned hexahedron. Continue * in this fashion until all the Tetrahedra in the 3-cell have been * absorbed into the coned polyhedron. This coned polyhedron may have * some pair of faces on its boundary identified to yield the original * 3-cell. Where this occurs, call cancel_tetrahedra() to simplify the * coned polyhedron. (This operation is documented more thoroughly * in the code itself.) * * Step #2. * Do a two-to-three move across each opaque face, then cancel * all pairs of Tetrahedra surrounding EdgeClasses of order 2. * You may take it as an exercise for the reader to prove that this * has the desired effect, or you may read the explanation provided * in the function step_two() below. * * * Programming note: I have coded this algorithm for simplicity * rather than speed. But even though the code is "less efficient" * because it does, e.g., some unnecessary rescanning of lists, I don't * think this will make a measurable difference in practice, and * in any case I think it's a small price to pay to keep the logic * of the code clean and simple. */ #include "kernel.h" #include "canonize.h" #include "kernel_namespace.h" static void remove_vertex_cross_sections(Triangulation *manifold); static void attach_canonize_info(Triangulation *manifold); static void free_canonize_info(Triangulation *manifold); static void label_opaque_faces(Triangulation *manifold); static void step_one(Triangulation *manifold); static void initialize_tet_status(Triangulation *manifold); static Boolean cone_3_cell(Triangulation *manifold, int *num_finite_vertices); static Boolean find_unconed_tet(Triangulation *manifold, Tetrahedron **tet0); static Boolean expand_coned_region(Triangulation *manifold); static Boolean attempt_cancellation(Triangulation *manifold); static Boolean verify_coned_region(Triangulation *manifold); static void step_two(Triangulation *manifold); static Boolean eliminate_opaque_face(Triangulation *manifold); void canonical_retriangulation( Triangulation *manifold) { /* * Remove the hyperbolic structures and VertexCrossSections, if any. */ remove_hyperbolic_structures(manifold); remove_vertex_cross_sections(manifold); /* * If the canonical cell decomposition is a triangulation, we're done. * (Note: Comment out this line if you want to invoke the more * elaborate canonical retriangulation scheme for all manifolds, not * just those whose canonical cell decompositions contain cells other * than tetrahedra.) */ if (is_canonical_triangulation(manifold) == TRUE) return; /* * Add a CanonizeInfo field to each Tetrahedron to hold local variables. * These variables must be accessible to the low-level retriangulation * routines in simplify_triangulation.c, which is why we use the * special purpose pointer canonize_info in the Tetrahedron data * structure, rather than using the general purpose "extra" pointer. */ attach_canonize_info(manifold); /* * Note which 2-cells are opaque and which are transparent. */ label_opaque_faces(manifold); /* * Carry out the two step retriangulation algorithm described above. */ step_one(manifold); step_two(manifold); /* * Free the CanonizeInfo fields. */ free_canonize_info(manifold); /* * We can't possibly compute the Chern-Simons invariant * for a manifold with finite vertices, so we set * CS_fudge_is_known to FALSE. However, we can leave * CS_value_is_known as TRUE if it is already TRUE, since * the manifold is still the same. */ manifold->CS_fudge_is_known = FALSE; } static void remove_vertex_cross_sections( Triangulation *manifold) { Tetrahedron *tet; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) if (tet->cross_section != NULL) { my_free(tet->cross_section); tet->cross_section = NULL; } } static void attach_canonize_info( Triangulation *manifold) { Tetrahedron *tet; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) { /* * Just to be safe . . . */ if (tet->canonize_info != NULL) uFatalError("attach_canonize_info", "canonize_part_2"); /* * Attach the CanonizeInfo. */ tet->canonize_info = NEW_STRUCT(CanonizeInfo); } } static void free_canonize_info( Triangulation *manifold) { Tetrahedron *tet; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) { /* * Free the CanonizeInfo structure. */ my_free(tet->canonize_info); /* * Set the canonize_info pointer to NULL just to be safe. */ tet->canonize_info = NULL; } } static void label_opaque_faces( Triangulation *manifold) { Tetrahedron *tet, *nbr_tet; FaceIndex f, nbr_f; Real sum_of_tilts; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (f = 0; f < 4; f++) { nbr_tet = tet->neighbor[f]; nbr_f = EVALUATE(tet->gluing[f], f); sum_of_tilts = tet->tilt[f] + nbr_tet->tilt[nbr_f]; tet->canonize_info->face_status[f] = sum_of_tilts < - CONCAVITY_EPSILON ? opaque_face : transparent_face; } } static void step_one( Triangulation *manifold) { int num_finite_vertices; /* * Initialize each part_of_coned_cell flag to FALSE. */ initialize_tet_status(manifold); /* * Keep track of the number of finite vertices that * have been introduced, so they can be given consecutive * negative integers as indices. */ num_finite_vertices = 0; /* * Cone each 3-cell of the canonical cell decomposition to a point * in its interior. Each call to cone_3_cell() cones a single 3-cell, * so we must keep calling cone_3_cell() until it returns FALSE. */ while (cone_3_cell(manifold, &num_finite_vertices) == TRUE) ; } static void initialize_tet_status( Triangulation *manifold) { Tetrahedron *tet; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) tet->canonize_info->part_of_coned_cell = FALSE; } static Boolean cone_3_cell( Triangulation *manifold, int *num_finite_vertices) { Tetrahedron *tet0; /* * Is there a Tetrahedron which is not yet part of a coned cell? * If so, proceed. * If not, return FALSE. */ if (find_unconed_tet(manifold, &tet0) == FALSE) return FALSE; /* * Cone tet0 to its center. This will introduce a finite vertex. * Each of the four new Tetrahedra will have part_of_coned_cell * set to TRUE. The face_status for the "exterior" faces will * be preserved, and the face_status for the "interior" faces * will be set to inside_cone_face. */ one_to_four(tet0, &manifold->num_tetrahedra, -++*num_finite_vertices); /* * Expand the coned region. Whenever a Tetrahedron with * part_of_coned_cell == TRUE borders a Tetrahedron with * part_of_coned_cell == FALSE across a transparent face, * do a two-to-three move across the face to include the * (space occupied by the) latter Tetrahedron in the (growing) * coned region. Keep doing this as long as progress is * being made. The two-to-three move will set * part_of_coned_cell = TRUE for the three new Tetrahedra * it creates. It will preserve the face_status of the * "exterior" faces of the new Tetrahedra, and set the face_status * of the "interior" faces to inside_cone_face. * * (Yes, I know this isn't the optimally efficient way to do this, * but I don't think that's important. Please see the programming * note at the end of the documentation at the top of this file.) */ while (expand_coned_region(manifold) == TRUE) ; /* * If the initial, arbitrary subdivision of the 3-cell contained * edges in its interior (as would be the case with an octahedron, * for example), then the coned 3-cell we just produced will have * some identifications on its boundary (for example, in the case * of the octahedron we'd have a coned decahedron with two adjacent * boundary faces identified to yield the octahedron). Assuming at * least one pair of identified faces are adjacent, we can call * cancel_tetrahedra() to simplify the structure of the coned region * from a coned n-hedron with k pairs of faces identified to a coned * (n-2)-hedron with (k-1) pairs of faces identified. As long as some * pair of identified faces are adjacent (and identified in the obvious * way) we can keep repeating the simplification to arrive at a coned * (n-2k)-hedron with no faces identified, which is exactly what * we want in Step #1 of this algorithm. * * It's theoretically possible to have faces of a coned polyehdron * identified with no pair of identified faces adjacent to each other. * For example, consider the complement of the house-with-two-rooms * in the 3-sphere. Fortunately such examples are so rare and so * complicated that I doubt any will ever show up as triangulations * of 3-cells in canonical cell decompositions. If one did show up, * verify_coned_region() would detect the condition and call uFatalError(). * * Proposition. Identifying two adjacent faces (in the "obvious" way) * creates an EdgeClass of order 2, and this is the only way * EdgeClasses of order 2 arise. * * Proof. It's obvious that such an identification creates an * EdgeClass of order 2. We must prove that this is the only way * they may arise. Consider separately EdgeClasses from the * original Triangulation (i.e. from the original arbitrary subdivision * of the canonical cell decomposition), which connect one ideal * vertex to another, and EdgeClasses which are added during the * coning process, which connect an ideal vertex to a finite vertex. * * Case 1. Original EdgeClasses, which connect one ideal vertex * to another. There are no EdgeClasses of order 2 in the initial * Triangulation, because it is geometric. In a coned polyhedron * (ignoring boundary identifications for the moment) each * EdgeClass connecting one ideal vertex to another is incident * to precisely two of the coned polyhedron's Tetrahedra. If the * EdgeClass lies on the boundary of the 3-cell (of the canonical * cell decomposition) then its true order will be greater than two. * If it lies in the interior of the 3-cell, then the only way for * the order to be exactly two is to have the two adjacent faces * identified. * * Case 2. EdgeClasses added during the coning process, which * connect an ideal vertex to a finite vertex. We assume such * an EdgeClass has order 2, and will deduce a contradiction. * Consider the coned polyhedron, ignoring boundary identifications * for the moment. Consider the two faces on the boundary of * incident to the ideal endpoint of the given EdgeClass. These * faces are part of the original (geometric!) subdivision of the * canonical cell decomposition. They have all three ideal vertices * in common, therefore they must coincide. But this implies that * the boundary component at the ideal vertex of the given EdgeClass * is topologically a sphere. * * Q.E.D. */ while (attempt_cancellation(manifold) == TRUE) ; /* * As explained above, once we've cancelled all Tetrahedra incident * to EdgeClasses of order 2, we will almost surely have the required * coning of the 3-cell's boundary to a point in its interior, unless * we encounter a situation like the complement of the * house-with-two-rooms. verify_coned_region() checks that we * do in fact have a coning of the original 3-cell; that is, * no Tetrahedron with part_of_coned_cell == TRUE has a face with * face_status transparent_face. */ if (verify_coned_region(manifold) == FALSE) uFatalError("cone_3_cell", "canonize_part_2"); return TRUE; } static Boolean find_unconed_tet( Triangulation *manifold, Tetrahedron **tet0) { Tetrahedron *tet; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) if (tet->canonize_info->part_of_coned_cell == FALSE) { *tet0 = tet; return TRUE; } return FALSE; } static Boolean expand_coned_region( Triangulation *manifold) { Tetrahedron *tet; FaceIndex f; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) if (tet->canonize_info->part_of_coned_cell == TRUE) for (f = 0; f < 4; f++) if (tet->canonize_info->face_status[f] == transparent_face) if (tet->neighbor[f]->canonize_info->part_of_coned_cell == FALSE) { if (two_to_three(tet, f, &manifold->num_tetrahedra) == func_OK) return TRUE; else /* this should never occur */ uFatalError("expand_coned_region", "canonize_part_2"); } return FALSE; } static Boolean attempt_cancellation( Triangulation *manifold) { EdgeClass *edge, *where_to_resume; for (edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) if (edge->order == 2) { if (cancel_tetrahedra(edge, &where_to_resume, &manifold->num_tetrahedra) == func_OK) return TRUE; else /* * I don't think failure is possible, but if it is * I want to know about it. */ uFatalError("attempt_cancellation", "canonize_part_2"); } return FALSE; } static Boolean verify_coned_region( Triangulation *manifold) { /* * Because one_to_four(), two_to_three() and cancel_tetrahedra() * all maintain the coned polyhedron as some sort of coned * polyhedron, all we need to check is that it has no remaining * identifications on its boundary. That is, we need to check * that the faces of each Tetrahedron with part_of_coned_cell == TRUE * have face_status opaque_face or inside_cone_face, but never * transparent_face. */ Tetrahedron *tet; FaceIndex f; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) if (tet->canonize_info->part_of_coned_cell == TRUE) for (f = 0; f < 4; f++) if (tet->canonize_info->face_status[f] == transparent_face) return FALSE; return TRUE; } static void step_two( Triangulation *manifold) { /* * Step #1 of the algorithm has already been carried out, so * we know that every 3-cell in the canonical cell decomposition * has been subdivided by coning the boundary to a point in * the interior. There are three types of EdgeClasses: * * (A) Those which lie in the 1-skeleton of the canonical * cell decomposition. They have order at least 6. * * (B) Those which lie in the 2-skeleton of the canonical * cell decomposition, but not in the 1-skeleton. They * serve to (artificially) subdivide the faces of the 3-cells * into triangles. Each has order precisely 4. * * (C) Those in the interior of the 3-cells. They connect ideal * vertices to finite vertices, and have order at least 3. * * Step #2 of the algorithm consists of two substeps: * * Substep A. Do a two-to-three move across every opaque face. * * Substep B. Perform all possible cancellations of Tetrahedra * surrounding EdgeClasses of order 2. * * After Substep A is complete, we know that * * EdgeClasses of type A will have order at least 3. * EdgeClasses of type B will have order precisely 2. * EdgeClasses of type C will have order at least 6. * The new EdgeClasses introduced in Substep A will have * order precisely 3. * * Therefore Substep B will eliminate precisely the EdgeClasses * of type B. It's easy to see that removing these EdgeClasses * creates the Triangulation specified in Step #2 of the definition * of the canonical retriangulation at the top of this file. */ while (eliminate_opaque_face(manifold) == TRUE) ; while (attempt_cancellation(manifold) == TRUE) ; } static Boolean eliminate_opaque_face( Triangulation *manifold) { Tetrahedron *tet; FaceIndex f; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (f = 0; f < 4; f++) if (tet->canonize_info->face_status[f] == opaque_face) { if (two_to_three(tet, f, &manifold->num_tetrahedra) == func_OK) return TRUE; else /* this should never occur */ uFatalError("expand_coned_region", "canonize_part_2"); } return FALSE; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/canonize_result.c000644 000765 000024 00000004170 12377774107 022355 0ustar00babstaff000000 000000 /* * canonize_result.c * * The function * * Boolean is_canonical_triangulation(Triangulation *manifold); * * accepts a Triangulation which it assumes to be a subdivision of a canonical * cell decomposition (as produced by proto_canonize(), for example), and * says whether it is indeed the canonical cell decomposition itself. * In other words, is_canonical_triangulation() will return TRUE * when the canonical cell decomposition is a triangulation, and FALSE when * it is not. * * is_canonical_triangulation() assumes all Tetrahedra in the Triangulation * have valid "tilt" fields, as will be the case following a call to * proto_canonize(). */ #include "kernel.h" #include "canonize.h" #include "kernel_namespace.h" Boolean is_canonical_triangulation( Triangulation *manifold) { Tetrahedron *tet, *nbr_tet; FaceIndex f, nbr_f; Real sum_of_tilts; Boolean result; /* * We'll assume the canonical cell decomposition is a triangulation * unless we discover otherwise. */ result = TRUE; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (f = 0; f < 4; f++) { nbr_tet = tet->neighbor[f]; nbr_f = EVALUATE(tet->gluing[f], f); sum_of_tilts = tet->tilt[f] + nbr_tet->tilt[nbr_f]; /* * The sum of the tilts should never be positive, because * this would mean that we didn't have a subdivision of the * canonical cell decomposition after all. */ if (sum_of_tilts > CONCAVITY_EPSILON) uFatalError("is_canonical_triangulation", "canonize_result"); /* * If the sum of the tilts is zero, then the canonical cell * decomposition contains cell other than tetrahedra. */ if (sum_of_tilts > -CONCAVITY_EPSILON) result = FALSE; /* * Otherwise we're OK. */ } return result; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/change_peripheral_curves.c000644 000765 000024 00000020526 12377774107 024203 0ustar00babstaff000000 000000 /* * change_peripheral_curves.c * * This file provides the function * * FuncResult change_peripheral_curves( * Triangulation *manifold, * CONST MatrixInt22 change_matrices[]); * * If all the change_matrices (there should be one for each Cusp) have * determinant +1, then on each Cusp change_peripheral_curves() replaces * * the meridian with change_matrices[i][0][0] meridians plus * change_matrices[i][0][1] longitudes, and * the longitude with change_matrices[i][1][0] meridians plus * change_matrices[i][1][1] longitudes, * * where i is the index of the Cusp. It returns func_OK. * * If some change_matrix has determinant != +1, change_peripheral_curves() * returns func_bad_input. */ #include "kernel.h" #include "kernel_namespace.h" FuncResult change_peripheral_curves( Triangulation *manifold, CONST MatrixInt22 change_matrices[]) { int i, v, f, old_m, old_l; Real old_m_coef, /* changed from int to Real, JRW 2000/01/18 */ old_l_coef; Tetrahedron *tet; Cusp *cusp; Complex old_Hm, old_Hl; /* * First make sure all the change_matrices have determinant +1. */ for (i = 0; i < manifold->num_cusps; i++) if (DET2(change_matrices[i]) != +1) return func_bad_input; /* * The change_matrices for Klein bottle cusps must have zeros in the * off-diagonal entries. (Nothing else makes sense topologically.) */ for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) if (cusp->topology == Klein_cusp) for (i = 0; i < 2; i++) if (change_matrices[cusp->index][i][!i] != 0) uFatalError("change_peripheral_curves", "change_peripheral_curves"); /* * Change the peripheral curves according to the change_matrices. * As stated at the top of this file, the transformation rule is * * | new m | | | | old m | * | | = | change_matrices[i] | | | * | new l | | | | old l | */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (i = 0; i < 2; i++) /* which orientation */ for (v = 0; v < 4; v++) /* which vertex */ for (f = 0; f < 4; f++) /* which side */ { old_m = tet->curve[M][i][v][f]; old_l = tet->curve[L][i][v][f]; tet->curve[M][i][v][f] = change_matrices[tet->cusp[v]->index][0][0] * old_m + change_matrices[tet->cusp[v]->index][0][1] * old_l; tet->curve[L][i][v][f] = change_matrices[tet->cusp[v]->index][1][0] * old_m + change_matrices[tet->cusp[v]->index][1][1] * old_l; } /* * Change the Dehn filling coefficients to reflect the new * peripheral curves. That is, we want the Dehn filling curves * to be topologically the same as before, even though the * coefficients will be different because we changed the basis. * * To keep our thinking straight, let's imagine all peripheral * curves -- old and new -- in terms of some arbitrary but * fixed basis for pi_1(T^2) = Z + Z. We never actually compute * such a basis, but it helps keep our thinking straight. * Relative to this fixed basis, we have * * old m = (old m [0], old m [1]) * old l = (old l [0], old l [1]) * new m = (new m [0], new m [1]) * new l = (new l [0], new l [1]) * * Note that these m's and l's are curves, not coefficients! * They are elements of pi_1(T^2) = Z + Z. * * We can then rewrite the above transformation rule, with * each peripheral curve (old m, old l, new m and new l) * appearing as a row in a 2 x 2 matrix: * * | <--new m--> | | | | <--old m--> | * | | = | change_matrices[i] | | | * | <--new l--> | | | | <--old l--> | * * We can invert the change_matrix to solve for the old curves * in terms of the new ones: * -1 * | <--old m--> | | | | <--new m--> | * | | = | change_matrices[i] | | | * | <--old l--> | | | | <--new l--> | * * The Dehn filling curve is * * old_m_coef * old_m + old_l_coef * old_l * * = old_m_coef * [ change_matrices[i][1][1] * new_m * - change_matrices[i][0][1] * new_l] * + old_l_coef * [- change_matrices[i][1][0] * new_m * + change_matrices[i][0][0] * new_l] * * = new_m * [ old_m_coef * change_matrices[i][1][1] * - old_l_coef * change_matrices[i][1][0] ] * + new_l * [- old_m_coef * change_matrices[i][0][1] * + old_l_coef * change_matrices[i][0][0] ] * * Therefore * * new_m_coef = old_m_coef * change_matrices[i][1][1] * - old_l_coef * change_matrices[i][1][0] * new_l_coef = - old_m_coef * change_matrices[i][0][1] * + old_l_coef * change_matrices[i][0][0] */ for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) if (cusp->is_complete == FALSE) { old_m_coef = cusp->m; old_l_coef = cusp->l; cusp->m = old_m_coef * change_matrices[cusp->index][1][1] - old_l_coef * change_matrices[cusp->index][1][0]; cusp->l = - old_m_coef * change_matrices[cusp->index][0][1] + old_l_coef * change_matrices[cusp->index][0][0]; } /* * Update the holonomies according to the rule * * | new H(m) | | | | old H(m) | * | | = | change_matrices[i] | | | * | new H(l) | | | | old H(l) | * * (These are actually logs of holonomies, so it's correct to * add -- not multiply -- them.) * * For complete Cusps the holonomies should be zero, but that's OK. */ for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) for (i = 0; i < 2; i++) /* i = ultimate, penultimate */ { old_Hm = cusp->holonomy[i][M]; old_Hl = cusp->holonomy[i][L]; cusp->holonomy[i][M] = complex_plus( complex_real_mult( change_matrices[cusp->index][0][0], old_Hm ), complex_real_mult( change_matrices[cusp->index][0][1], old_Hl ) ); cusp->holonomy[i][L] = complex_plus( complex_real_mult( change_matrices[cusp->index][1][0], old_Hm ), complex_real_mult( change_matrices[cusp->index][1][1], old_Hl ) ); } /* * Update the cusp_shapes. */ for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) { cusp->cusp_shape[initial] = transformed_cusp_shape( cusp->cusp_shape[initial], change_matrices[cusp->index]); if (cusp->is_complete == TRUE) cusp->cusp_shape[current] = transformed_cusp_shape( cusp->cusp_shape[current], change_matrices[cusp->index]); /* * else cusp->cusp_shape[current] == Zero, and needn't be changed. */ } return func_OK; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/chern_simons.c000644 000765 000024 00000076231 12377774107 021647 0ustar00babstaff000000 000000 /* * chern_simons.c * * The computation of the Chern-Simons invariant is a little * delicate because the formula depends on a constant which * must initially be supplied by the user. * * For the UI, this file provides the functions * * void set_CS_value( Triangulation *manifold, * double a_value); * void get_CS_value( Triangulation *manifold, * Boolean *value_is_known, * double *the_value, * int *the_precision, * Boolean *requires_initialization); * * The UI calls set_CS_value() to pass to the kernel a user-supplied * value of the Chern-Simons invariant for the current manifold. * * The UI calls get_CS_value() to request the current value. If the * current value is known (or can be computed), get_CS_value() sets * *value_is_known to TRUE and writes the current value and its precision * (the number of significant digits to the right of the decimal point) * to *the_value and *the_precision, respectively. If the current value * is not known and cannot be computed, it sets *value_is_known to FALSE, * and then sets *requires_initialization to TRUE if the_value * is unknown because no fudge factor is available, or * to FALSE if the_value is unknown because the solution contains * negatively oriented Tetrahedra. The UI might want to convey * these situations to the user in different ways. * * get_CS_value() normalizes *the_value to the range (-1/4,+1/4]. * This is the ONLY point in code where such an adjustment is made; * all internal computations are done mod 0. * * * The kernel manages the Chern-Simons computation by keeping track of * both the current value and the arbitrary constant ("fudge factor") * which appears in the formula. It uses the following fields of * the Triangulation data structure: * * Boolean CS_value_is_known, * CS_fudge_is_known; * double CS_value[2], * CS_fudge[2]; * * The Boolean flags indicate whether the corresponding double is * presently known or unknown. To provide an estimate of precision, * CS_value[ultimate] and CS_value[penultimate] store the value of the * Chern-Simons invariant computed relative to the hyperbolic structure * at the ultimate and penultimate iterations of Newton's method, and * similarly for the fudge factor CS_fudge[]. * * For the kernel, this file provides the functions * * void compute_CS_value_from_fudge(Triangulation *manifold); * void compute_CS_fudge_from_value(Triangulation *manifold); * * compute_CS_value_from_fudge() computes the CS_value in terms of * CS_fudge, if CS_fudge_is_known is TRUE. (If CS_fudge_is_known is FALSE, * it sets CS_value_is_known to FALSE as well.) The kernel calls this * function when doing Dehn fillings on a fixed Triangulation, where * the CS_fudge will be known (and constant) but the CS_value will be * changing. * * compute_CS_fudge_from_value() computes the CS_fudge in terms of * CS_value, if CS_value_is_known is TRUE. (If CS_value_is_known is FALSE, * it sets CS_fudge_is_known to FALSE as well.) The kernel calls this * function when it changes a Triangulation without changing the manifold * it represents. * * * Bob Meyerhoff, Craig Hodgson and Walter Neumann have found at least * two different algorithms for computing the Chern-Simons invariant. * The following code allows easy substitution of algorithms, in the * function compute_CS(). * * 96/4/16 David Eppstein pointed out that when he does (1,0) Dehn filling * on m074(1,0), SnapPea quits with the message "The argument in the * dilogarithm function is too large to guarantee accuracy". I've modified * the code so that it displays the message "The argument in the dilogarithm * function is too large to guarantee an accurate value for the Chern-Simons * invariant" but does not quit. Instead it sets * * manifold->CS_value_is_known = FALSE; * or * manifold->CS_fudge_is_known = FALSE; * * (as appropriate) and continues normally. [By the way, I rejected the * idea of providing more coefficients for the series. The set of manifolds * for which the existing coefficients do not suffice is very, very small: * no problems arise for any of the manifolds in the cusped or closed censuses. * (Eppstein's example of m074(1,0) is a 3-sphere, but other descriptions * of the 3-sphere seem to work fine.) So I don't want to slow down the * computation of the Chern-Simons invariant in the generic case for the * sake of an almost vanishingly small set of exceptions.] */ /* * Marc Culler 2014/02/15 - Now can use a function stored in the triangulation * structure to computer dilogarithms for high precision manifolds. */ #include "kernel.h" #include "kernel_namespace.h" #define CS_EPSILON 1e-8 static FuncResult compute_CS(Triangulation *manifold, Real value[2]); static FuncResult algorithm_one(Triangulation *manifold, Real value[2]); static Complex alg1_compute_Fu(Triangulation *manifold, int which_approximation, Boolean *Li2_error_flag); static Complex Li2(Complex w, ShapeInversion *z_history, Boolean *Li2_error_flag); static Complex log_w_minus_k_with_history(Complex w, int k, Real regular_arg, ShapeInversion *z_history); static int get_history_length(ShapeInversion *z_history); static int get_wide_angle(ShapeInversion *z_history, int requested_index); void set_CS_value( Triangulation *manifold, Real a_value) { manifold->CS_value_is_known = TRUE; manifold->CS_value[ultimate] = a_value; manifold->CS_value[penultimate] = a_value; compute_CS_fudge_from_value(manifold); } void get_CS_value( Triangulation *manifold, Boolean *value_is_known, Real *the_value, int *the_precision, Boolean *requires_initialization) { if (manifold->CS_value_is_known) { *value_is_known = TRUE; *the_value = manifold->CS_value[ultimate]; *the_precision = decimal_places_of_accuracy( manifold->CS_value[ultimate], manifold->CS_value[penultimate]); *requires_initialization = FALSE; /* * Normalize reported value to the range (-1/4, 1/4]. */ while (*the_value < -0.25 + CS_EPSILON) *the_value += 0.5; while (*the_value > 0.25 + CS_EPSILON) *the_value -= 0.5; } else { *value_is_known = FALSE; *the_value = 0.0; *the_precision = 0; *requires_initialization = (manifold->CS_fudge_is_known == FALSE); } } void compute_CS_value_from_fudge( Triangulation *manifold) { Real computed_value[2]; if (manifold->CS_fudge_is_known == TRUE && compute_CS(manifold, computed_value) == func_OK) { manifold->CS_value_is_known = TRUE; manifold->CS_value[ultimate] = computed_value[ultimate] + manifold->CS_fudge[ultimate]; manifold->CS_value[penultimate] = computed_value[penultimate] + manifold->CS_fudge[penultimate]; } else { manifold->CS_value_is_known = FALSE; manifold->CS_value[ultimate] = 0.0; manifold->CS_value[penultimate] = 0.0; } } void compute_CS_fudge_from_value( Triangulation *manifold) { Real computed_value[2]; if (manifold->CS_value_is_known == TRUE && compute_CS(manifold, computed_value) == func_OK) { manifold->CS_fudge_is_known = TRUE; manifold->CS_fudge[ultimate] = manifold->CS_value[ultimate] - computed_value[ultimate]; manifold->CS_fudge[penultimate] = manifold->CS_value[penultimate] - computed_value[penultimate]; } else { manifold->CS_fudge_is_known = FALSE; manifold->CS_fudge[ultimate] = 0.0; manifold->CS_fudge[penultimate] = 0.0; } } static FuncResult compute_CS( Triangulation *manifold, Real value[2] ) { Cusp *cusp; /* * We can handle only orientable manifolds. */ if (manifold->orientability != oriented_manifold) return func_failed; /* * Cusps must either be complete, or have Dehn filling * coefficients which are relatively prime integers. */ for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) if (Dehn_coefficients_are_relatively_prime_integers(cusp) == FALSE) return func_failed; /* * Here we plug in the algorithm of our choice. */ return algorithm_one(manifold, value); } static FuncResult algorithm_one( Triangulation *manifold, Real value[2] ) { Boolean Li2_error_flag; int i; Complex Fu[2], core_length_sum[2], complex_volume[2], length[2]; int singularity_index; Cusp *cusp; /* * This algorithm is taken directly from Craig Hodgson's * preprint "Computation of the Chern-Simons invariants". * It extends previous implementations in that it uses * the shape_histories of the Tetrahedra to compute * the dilogarithms, which allows solutions with negatively * oriented Tetrahedra. */ /* * To use the Chern-Simons formula, both the complete and filled * solutions must be geometric, nongeometric or flat. */ for (i = 0; i < 2; i++) /* i = complete, filled */ if (manifold->solution_type[i] != geometric_solution && manifold->solution_type[i] != nongeometric_solution && manifold->solution_type[i] != flat_solution) return func_failed; /* * Initialize the Li2_error_flag to FALSE. * If the coefficients in Li2() don't suffice to compute the dilogaritm * to full precision, Li2() will set Li2_error_flag to TRUE. */ Li2_error_flag = FALSE; /* * Compute F(u) relative to the ultimate and penultimate * hyperbolic structures, to allow an estimatation of precision. */ for (i = 0; i < 2; i++) /* i = ultimate, penultimate */ Fu[i] = alg1_compute_Fu(manifold, i, &Li2_error_flag); /* * If Li2() failed, return func_failed; */ if (Li2_error_flag == TRUE) { uAcknowledge("An argument in the dilogarithm function is too large to guarantee an accurate value for the Chern-Simons invariant."); return func_failed; } /* * F(u) is * * (complex volume) + pi/2 (sum of complex core lengths) * * So we subtract off the complex lengths of the core geodesics * to be obtain the complex volume. */ for (i = 0; i < 2; i++) /* i = ultimate, penultimate */ core_length_sum[i] = Zero; for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) { compute_core_geodesic(cusp, &singularity_index, length); switch (singularity_index) { case 0: /* * The cusp is complete. Do nothing. */ break; case 1: /* * Add this core length to the sum. */ for (i = 0; i < 2; i++) /* i = ultimate, penultimate */ core_length_sum[i] = complex_plus( core_length_sum[i], length[i]); break; default: /* * We should never arrive here. */ uFatalError("algorithm_one", "chern_simons"); } } /* * (complex volume) = F(u) - (pi/2)(sum of core lengths) */ for (i = 0; i < 2; i++) /* i = ultimate, penultimate */ { complex_volume[i] = complex_minus( Fu[i], complex_real_mult( PI_OVER_2, core_length_sum[i] ) ); value[i] = complex_volume[i].imag / (2.0 * PI * PI); } return func_OK; } static Complex alg1_compute_Fu( Triangulation *manifold, int which_approximation, /* ultimate or penultimate */ Boolean *Li2_error_flag ) { Complex Fu, dilog; Tetrahedron *tet; static const Complex minus_i = {0.0, -1.0}; /* * We compute the function F(u), which Yoshida has proved holomorphic. * (See Craig's preprint mentioned above.) */ /* * Initialize F(u) to Zero. */ Fu = Zero; /* * Add up the log terms. */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) { Fu = complex_minus( Fu, complex_mult( tet->shape[ filled ]->cwl[which_approximation][0].log, tet->shape[ filled ]->cwl[which_approximation][1].log ) ); Fu = complex_plus( Fu, complex_mult( tet->shape[ filled ]->cwl[which_approximation][0].log, complex_conjugate( tet->shape[complete]->cwl[which_approximation][1].log) ) ); Fu = complex_minus( Fu, complex_mult( tet->shape[ filled ]->cwl[which_approximation][1].log, complex_conjugate( tet->shape[complete]->cwl[which_approximation][0].log) ) ); Fu = complex_minus( Fu, complex_mult( tet->shape[complete]->cwl[which_approximation][0].log, complex_conjugate( tet->shape[complete]->cwl[which_approximation][1].log) ) ); } /* * Multiply through by one half. */ Fu = complex_real_mult(0.5, Fu); /* * Add in the dilogarithms. */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) { /* * To compute the dilogarithm of z, Li2() wants to be * passed w = log(z) / 2 pi i and the shape_history of z. * (MC) But the external dilog function should accept z. */ if (manifold->dilog == NULL) dilog = Li2 ( complex_div ( tet->shape[filled]->cwl[which_approximation][0].log, TwoPiI ), tet->shape_history[filled], Li2_error_flag ); else dilog = manifold->dilog ( tet->shape[filled]->cwl[which_approximation][0].rect ); Fu = complex_plus(Fu, dilog); } /* * Multiply by -i. */ Fu = complex_mult(minus_i, Fu); return Fu; } static Complex Li2( Complex w, ShapeInversion *z_history, Boolean *Li2_error_flag) { /* * Compute the dilogarithm of z = exp(2 pi i w) as explained * in Craig's preprint mentioned above. Note that we use * the variable w instead of the z which appears in Craig's * preprint, to avoid confusion with the z which appears * in the formula for F(u). * * The term Craig calls "S" we compute in two parts * * s0 = sum from i = 1 to infinity . . . * s1 = sum from k = 1 to N . . . + Nw * * The remaining part of the formula we call * * t = pi^2/6 + 2 pi i w - 2 pi i w log(-2 pi i w) + (pi w)^2 */ Complex s0, s1, s, t, w_squared, two_pi_i_w, kk, k_plus_w, k_minus_w, result; int i, k; static const Complex pi_squared_over_6 = {PI*PI/6.0, 0.0}, four_pi_i = {0.0, 4.0*PI}, minus_pi_i = {0.0, -PI}, log_minus_two_pi_i = {LOG_TWO_PI, -PI_OVER_2}; /* * The array a[] contains the coefficients for the infinite series * in s0. The constant num_terms tells how many we need to use to * insure accuracy (see Analysis of Convergence below). * * The following Mathematica code computed these coefficients * for N = 2. (I use "n" where Craig used "N" to conform both * to proramming conventions regarding capital letters, and also * to Mathematica's conventions.) * * a[i_, n_] := * N[(Zeta[2i] - Sum[k^(-2i), {k,1,n}]) / (2i(2i + 1)), 60] * a2[i_] := a[i, 2] * Array[a2, 30] * * Note that to get 20 significant digits in a2[30] = 6.4e-33, we * must request at least 53 decimal places of accuracy from * Mathematica, and probably a little more since the accuracy we * request is the accuracy to which the intermediate calculations * are truncated -- the final accuracy could be a little worse. * By the way, we really do need a lot of that accuracy even in * the tiny coefficients, because they will be multiplied by high * powers of w, and |w| may be greater than one. */ static const int num_terms = 30; static const int n = 2; static const Real a[] ={ 0.0, 6.58223444747044060787e-2, 9.91161685556909575800e-4, 4.09062377249795170123e-5, 2.37647497144915803729e-6, 1.63751161982593974054e-7, 1.24738994105660169102e-8, 1.01418480335632980259e-9, 8.62880373230578403363e-11, 7.59064144690016509252e-12, 6.85041587014555123901e-13, 6.30901702974110744035e-14, 5.90712644809102073367e-15, 5.60732930747841393884e-16, 5.38501558411235458177e-17, 5.22344536523359867175e-18, 5.11092595568460128406e-19, 5.03912265560217431595e-20, 5.00200835767964640183e-21, 4.99518851712940000071e-22, 5.01545492014257760830e-23, 5.06048349504093155712e-24, 5.12862546072263579933e-25, 5.21876054821516289501e-26, 5.33019249317297967524e-27, 5.46257395282628942810e-28, 5.61585233364316675625e-29, 5.79023077981676178469e-30, 5.98614037451033538648e-31, 6.20422080422041301360e-32, 6.44530754870034591211e-33}; /* * Analysis of convergence. * * The i-th coefficient in the (partial) zeta function is * * (N+1)^(-2i) + (N+2)^(-2i) + (N+3)^(-2i) + ... * * Lemma. For large i, this series may be approximated by its first * term (N+1)^(-2i). * * Proof. [Probably not worth reading, but I figured I ought to * include it.] Get an upper bound on the sum of the neglected * terms by comparing them to an integral: * * (N+2)^(-2i) + (N+3)^(-2i) + ... * < (N+2)^(-2i) + integral from x = N+2 to infinity of x^(-2i) dx * = (N+2)^(-2i) + (N+2)^(-2i+1)/(2i-1) * < (N+2)^(-2i) + (N+2)^(-2i) * = 2 (N+2)^(-2i) * * Therefore the ratio (error)/(first term) is less than * * [2 (N+2)^(-2i)] / [(N+1)^(-2i)] * = 2 ((N+1)/(N+2))^(2i) * * Thus, for example, if N = 2 and i >= 10, the ratio * (error)/(first term) will be less than 2 (3/4)^10 = 1%. * When N = 4 we need i >= 15 to obtain 1% accuracy. * Q.E.D. * * * The preceding lemma implies that the infinite series * for S has the same convergence behavior as the series * * S' = (w/(N+1))^2i / i^2 * * so we analyze S' instead of S. The error introduced * by truncating the series after some i = i0 is bounded * by the corresponding error in the geometric series * * S" = |w/(N+1)|^2i / i0^2 * * The latter error is * * (first neglected term) / (1 - ratio) * * = (|w/(N+1)|^2i0 / i0^2) / (1 - |w/(N+1)|^2) * * = |w/(N+1)|^2i0 / (i0^2 (1 - |w/(N+1)|^2)) * * A quick calculcation in Mathematica shows that if * we are willing to calculate 30 terms in the series, * then |w/(N+1)| < 0.5 implies the error will be * less than 1e-20. In other words, the series can * be used successfully for |w| < (N+1)/2. What values * of z (i.e. what actual simplex shapes) does this * correspond to? * * Letting w = x + iy, we get * * z = exp(2 pi i (x + i y)) * = exp(-2 pi y + 2 pi i x) * = exp(-2 pi y) * (cos(2 pi x) + i sin(2 pi x)) * * In other words, at an argument of 2 pi x, the acceptable * parameters z are those with moduli between * exp(-2 pi sqrt(((N+1)/2)^2 - x^2)) and * exp(+2 pi sqrt(((N+1)/2)^2 - x^2)). * * For N = 2: * When x = 0 we get values of z along the positive real axis * from 0.00008 to 12000. * When x = 1/2 we get values of z along the negative real axis * from -0.0001 to -7000. * When x = 1 we get values of z along the positive real axis * from 0.0008 to 1000. * * This is good news: it means that the 30-term series for S will * be accurate to 1e-20 for all (reasonable) nondegenerate values * of z. I don't foresee the need for a greater radius of * convergence, but if one is ever needed, just switch to N = 4. */ /* * According to the preceding Analysis of Convergence, our * computations will be accurate to 1e-20 whenever * |w| < (N+1)/2 = 3/2. */ if (complex_modulus(w) > 1.5) { *Li2_error_flag = TRUE; return Zero; } /* * Note the values of w^2 and 2 pi i w. */ w_squared = complex_mult(w, w); two_pi_i_w = complex_mult(TwoPiI, w); /* * Compute t. * * In the third term, - 2 pi i w will lie in the strip * 0 < Im(- 2 pi i w) < - pi i, so we choose the argument * in its log to be in the range (0, - pi). */ t = pi_squared_over_6; t = complex_plus( t, two_pi_i_w ); t = complex_minus( t, complex_mult( two_pi_i_w, complex_plus( log_minus_two_pi_i, log_w_minus_k_with_history(w, 0, 0.0, z_history) ) ) ); t = complex_plus( t, complex_real_mult(PI * PI, w_squared) ); /* * Compute s0. * * Start with the high order terms and work backwards. * It's a little faster, because fewer multiplications * are required, and might also be a little more accurate. */ s0 = Zero; for (i = num_terms; i > 0; --i) { s0.real += a[i]; s0 = complex_mult(s0, w_squared); } s0 = complex_mult(s0, w); /* * Compute s1. */ s1 = Zero; for (k = 1; k <= n; k++) { kk = complex_real_mult(k, One); k_plus_w = complex_plus (kk, w); k_minus_w = complex_minus(kk, w); s1 = complex_plus( s1, complex_real_mult(log(k), w) ); s1 = complex_minus( s1, complex_real_mult( 0.5, complex_mult( k_plus_w, log_w_minus_k_with_history(w, -k, 0.0, z_history) ) ) ); s1 = complex_plus( s1, complex_real_mult( 0.5, complex_mult( k_minus_w, /* * We write Craig's log(k - w), which had an * argument of 0 for the regular case, as * log(-1) + log(w - k), and choose arg(log(-1)) = -pi * and arg(log(w - k)) = +pi for the regular case. */ complex_plus( minus_pi_i, log_w_minus_k_with_history(w, k, PI, z_history) ) ) ) ); } s1 = complex_plus( s1, complex_real_mult(n, w) ); /* * Add t + (4 pi i)(s0 + s1) to get the final answer. */ s = complex_plus(s0, s1); result = complex_plus( t, complex_mult(four_pi_i, s) ); return result; } static Complex log_w_minus_k_with_history( Complex w, int k, Real regular_arg, ShapeInversion *z_history) { int which_strip; Real estimated_argument; int i; /* * This function computes log(w - k), taking into account the "history" * of the shape z from which w is derived (z = exp(2 pi i w), as * explained above). That is, it takes into account z's precise * path through the parameter space, up to isotopy. * * regular_arg supplies the correct argument for the case of a * regular ideal tetrahedron, with z = (1/2) + (sqrt(3)/2)i, * w = 1/6, and a trivial "history". Typically regular_arg * will be 0 for k <= 0, and +pi for k > 0. * * To understand what's going on here, it will be helpful to make * yourself pictures of the z- and w-planes, as follows: * * z-plane. Draw axes for the complex plane representing z. * Draw small circles at 0 and 1 to show where * z is singular. * Color the real axis blue from -infinity to 0, and label * it '0' to indicate that z crosses this segment when * there is a ShapeInversion with wide_angle == 0. * Color the real axis red from 1 to +infinity, and label * it '1' to indicate that z crosses this segment when * there is a ShapeInversion with wide_angle == 1. * Color the real axis green from 0 to 1, and label * it '2' to indicate that z crosses this segment when * there is a ShapeInversion with wide_angle == 2. * * w-plane. Draw the preimage of the z-plane picture under the * map z = exp(2 pi i w). * The singularities occur at the integer points on * the real axis. * Red half-lines labeled 1 extend from each singularity * downward to infinity. * Green half-lines labeled 2 extend from each singularity * upward to infinity. * Blue lines labelled 0 pass vertically through each * half-integer point on the real axis. * * We will use the z_history to trace the path of w through the * w-plane picture, keeping track of the argument of log(w - k) * as we go. We begin with the shape of a regular ideal tetrahedron, * namely z = (1/2) + (sqrt(3)/2) i, w = 1/6 + 0 i. * * It suffices to keep track of the approximate argument to the * nearest multiple of pi, since the true argument will be within * pi/2 of that estimate. * * The vertical strips in the w-plane (which are preimages of * the halfplane z.imag > 0 and z.imag < 0 in the z-plane) * are indexed by integers. Strip n is the strip extending * from w.real = n/2 to w.real = (n+1)/2. */ /* * We begin at w = 1/6, and set the estimated_argument to * regular_arg (this will typically be 0 if k <= 0, or pi if k > 0, * corresponding to Walter and Craig's choices for the case of * positively oriented Tetrahedra). */ which_strip = 0; estimated_argument = regular_arg; /* * Now we read off the z_history, adjusting which_strip * and estimated_argument accordingly. * * Typically the z_history will be NULL, so nothing happens here. * * Technical note: this isn't the most efficient way to read * a linked list backwards, but clarity is more important than * efficiency here, but the z_histories are likely to be so short. */ for (i = 0; i < get_history_length(z_history); i++) switch (get_wide_angle(z_history, i)) { case 0: /* * If we're in an even numbered strip, move to the right. * If we're in an odd numbered strip, move to the left. * The estimated_argument does not change. */ if (which_strip % 2 == 0) which_strip++; else which_strip--; break; case 1: /* * If we're in an even numbered strip, move to the left, * and if we pass under the singularity at k, * subtract pi from the estimated_argument. * If we're in an odd numbered strip, move to the right, * and if we pass under the singularity at k, * add pi to the estimated_argument. */ if (which_strip % 2 == 0) { which_strip--; if (which_strip == 2*k - 1) estimated_argument -= PI; } else { which_strip++; if (which_strip == 2*k) estimated_argument += PI; } break; case 2: /* * If we're in an even numbered strip, move to the left, * and if we pass over the singularity at k, * add pi to the estimated_argument. * If we're in an odd numbered strip, move to the right, * and if we pass over the singularity at k, * subtract pi from the estimated_argument. */ if (which_strip % 2 == 0) { which_strip--; if (which_strip == 2*k - 1) estimated_argument += PI; } else { which_strip++; if (which_strip == 2*k) estimated_argument -= PI; } break; default: uFatalError("log_w_minus_k_with_history", "chern_simons"); } /* * Compute log(w - k) using the estimated_argument. */ return ( complex_log( complex_minus( w, complex_real_mult((Real)k, One) ), estimated_argument ) ); } static int get_history_length( ShapeInversion *z_history) { int length; length = 0; while (z_history != NULL) { length++; z_history = z_history->next; } return length; } static int get_wide_angle( ShapeInversion *z_history, int requested_index) { while (--requested_index >= 0) z_history = z_history->next; return z_history->wide_angle; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/choose_generators.c000644 000765 000024 00000112523 12377774107 022664 0ustar00babstaff000000 000000 /* * choose_generators.c * * This file contains the function * * void choose_generators( Triangulation *manifold, * Boolean compute_corners, * Boolean centroid_at_origin) * * which chooses a set of generators for the fundamental group * of the Triangulation *manifold. (The Dehn filling coefficients * are irrelevant.) * * A function which needs to use the generating set must first call * choose_generators(). [Note that this differs from the previous * SnapPea 2.0- convention, under which all functions which changed the * triangulation were responsible for calling choose_generators(). * The old convention was more efficient at runtime, but the new one * makes programming easier.] * * The algorithm begins with an arbitrary Tetrahedron, and recursively * attaches neighboring Tetrahedra to create a fundamental domain for * the manifold which is topologically a ball. Whenever a face of a * Tetrahedron lies in the interior of this fundamental domain, * tet->generator_status[face] is set to not_a_generator. Faces on the * exterior of the fundmental domain correspond to active generators, * and will have status outbound_generator or inbound_generator, depending * on how a particular generator is oriented (one face of a matching pair * will have status outbound_generator, and the other inbound_generator). * * The algorithm simplifies the generating set in two ways: * * (1) When it finds an EdgeClass with only one incident 2-cell which * is dual to an active generator, it does a "handle cancellation" * to eliminate that generator, and also sets the EdgeClass's * active_relation field to FALSE. The algorithm continues doing * this type of simplification until it can make no further progress. * * (2) At this point the boundary of the fundamental domain is likely * to contain groups of faces which are essentially n-gons (n > 3) * arbitrarily divided into triangles. The generators for such * triangular faces are all equivalent, and get merged. The * active_relation fields of the interior EdgeClasses are set to * FALSE. * * active_relation fields which are not set to FALSE in (1) or (2) * are set to TRUE. Each EdgeClass's num_incident_generators field * says, not surprisingly, how many active generators it is incident to. * Note that num_incident_generators becomes 0 when a handle cancellation * occurs in (1) above, but num_incident_generators remains 2 when the * EdgeClass's active_relation field is set to FALSE in (2) (the rationale * is that there are still two active incident generators, even though * they happen to be the same (yeah, it sounds suspicious to me too, but * that's how it is)). * * Each generator is a 1-cell in the dual to the Triangulation. * The generator dual to a given face of a given Tetrahedron is * described by three variables: * * tet->generator_status[face] takes the value * * outbound_generator if the generator is directed from * tet towards its neighbor, * inbound_generator if the generator is directed from * the neighbor towards tet, * not_a_generator if no generator corresponds to this * face (more on this in a minute), and * unassigned_generator if the algorithm hasn't gotten around * to considering this face yet. * * tet->generator_index[face] tells the index of the generator. * The numbering runs from 0 to (number-of-generators - 1). * tet->generator_index[face] is defined iff tet->generator_status[face] * is outbound_generator or inbound_generator. * * tet->generator_parity[face] tells whether the generator is * orientation_preserving or orientation_reversing. * * The field tet->generator_path lets you reconstruct the complete path of * a generator: it says by which face the given Tetrahedron was added to the * fundamental domain (cf. the recursive algorithm described above). The * central Tetrahedron used to begin the recursion has tet->generator_path = -1. * * If compute_corners is TRUE, * choose_generators() also computes the location on the sphere at infinity * of each ideal vertex of each Tetrahedron in the fundamental domain, and * stores it in the field tet->corner[vertex]. That is, tet->corner[vertex] * contains the complex number representing the location of the vertex in * the boundary of the upper half space model. The (relative) locations of * the corners are computed using the hyperbolic structure of the Dehn filled * manifold. If centroid_at_origin is TRUE, the initial tetrahedron is * positioned with its centroid at the origin; otherwise the initial tetrahedron * is positioned with its vertices at {0, 1/sqrt(z), sqrt(z), infinity}. */ #include "kernel.h" #include "kernel_namespace.h" static void initialize_flags(Triangulation *manifold); static void visit_tetrahedra(Triangulation *manifold, Boolean compute_corners, Boolean centroid_at_origin); static void initial_tetrahedron(Triangulation *manifold, Tetrahedron **tet, Boolean compute_corners, Boolean centroid_at_origin); static void count_incident_generators(Triangulation *manifold); static void eliminate_trivial_generators(Triangulation *manifold); static void kill_the_incident_generator(Triangulation *manifold, EdgeClass *edge); static void merge_equivalent_generators(Triangulation *manifold); static void merge_incident_generators(Triangulation *manifold, EdgeClass *edge); static void eliminate_empty_relations(Triangulation *manifold); void choose_generators( Triangulation *manifold, Boolean compute_corners, Boolean centroid_at_origin) { /* * To compute the corners we need some sort of geometric structure. */ if (compute_corners == TRUE && manifold->solution_type[filled] == not_attempted) uFatalError("choose_generators", "choose_generators.c"); /* * For each Tetrahedron tet, set tet->flag to unknown_orientation * to indicate that the Tetrahedron has not yet been visited, and * set each tet->generator_status[i] to unassigned_generator to * indicate that no generator has yet been assigned to any face. */ initialize_flags(manifold); /* * Start a recursion which visits each tetrahedron, assigns * generators to its faces, and recursively visits any unvisited * neighbors. */ visit_tetrahedra(manifold, compute_corners, centroid_at_origin); /* * The number_of_generators should be one plus the number of tetrahedra. */ if (manifold->num_generators != manifold->num_tetrahedra + 1) uFatalError("choose_generators", "choose_generators.c"); /* * At this point we have a valid set of generators, but it's * not as simple as it might be. We'll perform two types of * simplifications. First we need to count how many of the * faces incident to each EdgeClass correspond to active generators. * Initialize all the active_relation flags to TRUE while we're at it. */ count_incident_generators(manifold); /* * Now look for EdgeClasses in the Triangulation (2-cells in the * dual complex) which show that a single generator is homotopically * trivial, and eliminate the trivial generator. Topologically, this * corresponds to folding together two adjacent triangular faces * on the boundary of the fundamental domain (the close-the-book * move). Geometrically, this corresponds to realizing that two * faces of the (geometric) fundamental domain are in fact already * superimposed on each other. In Heegaard terms, it's a handle * cancellation. */ eliminate_trivial_generators(manifold); /* * At this point the boundary of the fundamental domain is likely * to contain groups of faces which are essentially n-gons (n > 3) * arbitrarily divided into triangles. The generators for such * triangular faces are all equivalent, and can be merged. They * can be recognized by looking for EdgeClasses with exactly two * incident (and distinct) generators. */ merge_equivalent_generators(manifold); /* * 2008/6/12 JRW * * Eliminate relations with zero generators. * * How can such relations arise? * * Under normal operation, eliminate_trivial_generators() finds an active generator * whose dual 2-cell is incident to an EdgeClass whose other incident 2-cells are * all dual to inactive generators (i.e. they lie in the interior * of the fundamental domain). The EdgeClass's relation (of length 1) cancels * the generator and all is well. One may visualize this operation as taking * two adjacent triangles on the boundary of the fundamental domain, which share * a common edge, and gluing them together via a "close-the-book move". * * Now consider two adjacent triangles (still on the boundary of the fundamental * domain) that share two common edges -- in effect a sort of triangular "pita pocket" * with two closed edges and one open edge. When eliminate_trivial_generators() * cancels the generator (dual to the triangular face) against one of the * incident EdgeClasses, the other EdgeClass is left with zero generators, * and may be eliminated. * * Note: Thinking in term of truncated tetrahedra, the above description seems * to imply that the boundary component at the tip of the pita pocket * between the two "closed edges" becomes a spherical boundary component * of the manifold. This suggests that this case would arise for finite * triangulations (as opposed to ideal triangulations), or for highly degenerate * ideal triangulations, but I confess that I haven't thought this through carefully. */ eliminate_empty_relations(manifold); } static void initialize_flags( Triangulation *manifold) { Tetrahedron *tet; FaceIndex face; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) { tet->flag = unknown_orientation; for (face = 0; face < 4; face++) { tet->generator_status[face] = unassigned_generator; tet->generator_index[face] = -2; /* garbage value */ } } } static void visit_tetrahedra( Triangulation *manifold, Boolean compute_corners, Boolean centroid_at_origin) { Tetrahedron **queue, *tet; int queue_first, queue_last; Tetrahedron *nbr_tet; Permutation gluing; FaceIndex face, nbr_face; int i; VertexIndex nbr_i; /* * choose_generators() has already called initialize_flags(). */ /* * Initialize num_generators to zero. */ manifold->num_generators = 0; /* * Allocate space for a queue of pointers to the Tetrahedra. * Each Tetrahedron will appear on the queue exactly once, * so an array of length manifold->num_tetrahedra will be just right. */ queue = NEW_ARRAY(manifold->num_tetrahedra, Tetrahedron *); /* * Initialize the queue. */ queue_first = 0; queue_last = 0; /* * Choose the initial Tetrahedron according to some criterion. * If compute_corners is TRUE, position its corners. * 2000/4/2 The choice of initial tetrahedron is independent * of compute_corners. */ initial_tetrahedron(manifold, &queue[0], compute_corners, centroid_at_origin); /* * Mark the initial Tetrahedron as visited. */ queue[0]->generator_path = -1; queue[0]->flag = right_handed; /* * Start processing the queue. */ do { /* * Pull a Tetrahedron off the front of the queue. */ tet = queue[queue_first++]; /* * Look at the four neighboring Tetrahedra. */ for (face = 0; face < 4; face++) { /* * Note who the neighbor is, and which of * its faces we're glued to. */ nbr_tet = tet->neighbor[face]; gluing = tet->gluing[face]; nbr_face = EVALUATE(gluing, face); /* * If nbr_tet hasn't been visited, set the appropriate * generator_statuses to not_a_generator, and then put * nbr_tet on the back of the queue. */ if (nbr_tet->flag == unknown_orientation) { tet ->generator_status[face] = not_a_generator; nbr_tet->generator_status[nbr_face] = not_a_generator; tet ->generator_index[face] = -1; /* garbage value */ nbr_tet->generator_index[nbr_face] = -1; nbr_tet->generator_path = nbr_face; nbr_tet->flag = (parity[gluing] == orientation_preserving) ? tet->flag : ! tet->flag; if (compute_corners) { for (i = 0; i < 4; i++) { if (i == face) continue; nbr_i = EVALUATE(gluing, i); nbr_tet->corner[nbr_i] = tet->corner[i]; } compute_fourth_corner( nbr_tet->corner, /* array of corner coordinates */ nbr_face, /* the corner to be computed */ nbr_tet->flag, /* nbr_tet's current orientation */ nbr_tet->shape[filled]->cwl[ultimate]); /* shapes */ } queue[++queue_last] = nbr_tet; } /* * If nbr_tet has been visited, check whether a generator * has been assigned to common face, and if not, assign one. */ else if (tet->generator_status[face] == unassigned_generator) { tet ->generator_status[face] = outbound_generator; nbr_tet->generator_status[nbr_face] = inbound_generator; tet ->generator_index[face] = manifold->num_generators; nbr_tet->generator_index[nbr_face] = manifold->num_generators; tet ->generator_parity[face] = nbr_tet->generator_parity[nbr_face] = ((parity[gluing] == orientation_preserving) == (tet->flag == nbr_tet->flag)) ? orientation_preserving : orientation_reversing; manifold->num_generators++; } } } while (queue_first <= queue_last); /* * Free the memory used for the queue. */ my_free(queue); /* * An "unnecessary" (but quick) error check. */ if ( queue_first != manifold->num_tetrahedra || queue_last != manifold->num_tetrahedra - 1) uFatalError("visit_tetrahedra", "choose_generators.c"); } static void initial_tetrahedron( Triangulation *manifold, Tetrahedron **initial_tet, Boolean compute_corners, Boolean centroid_at_origin) { VertexIndex v[4]; Complex z, sqrt_z, w[4]; Tetrahedron *tet; EdgeIndex best_edge, edge; /* * Set a default choice of tetrahedron and edge. */ *initial_tet = manifold->tet_list_begin.next; best_edge = 0; /* * 2000/02/11 JRW Can we choose the initial tetrahedron in such * a way that if we happen to have the canonical triangulation * of a 2-bridge knot or link complement, the basepoint falls * at a center of D2 symmetry? That is, can we find a Tetrahedron * that looks like the "top of the tower" in the canonical * triangulation of a 2-bridge knot or link complement? */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (edge = 0; edge < 6; edge++) if (tet->neighbor[one_face_at_edge [edge]] == tet->neighbor[other_face_at_edge[edge]]) { *initial_tet = tet; best_edge = edge; } if (compute_corners) { if (centroid_at_origin == TRUE) { /* * Proposition. For any value of w, positioning the corners at * * corner[0] = w * corner[1] = w^-1 * corner[2] = -w^-1 * corner[3] = -w * * defines a tetrahedron with its centroid at the "origin" and * the common perpendiculars between pairs of opposite edges * coincident with the "coordinate axes". [In the Klein model, * the tetrahedron is inscribed in a rectangular box whose faces * are parallel to the coordinate axes.] * * Proof: Use the observation that the line from a0 to a1 will * intersect the line from b0 to b1 iff the cross ratio * * (b0 - a0) (b1 - a1) * ------------------- * (b1 - a0) (b0 - a1) * * of the tetrahedron they span is real, and they will be * orthogonal iff the cross ratio is -1. * * [-w, w] is orthogonal to [0, infinity] because * * (0 - -w) (infinity - w) * ----------------------- = -1 * (infinity - -w) (0 - w) * * and similarly for [-w^-1, w^-1] and [0, infinity]. * * [w^-1, w] is orthogonal to [-1, 1] because * * (-1 - w^-1) (1 - w) * ------------------- = -1 * (1 - w^-1) (-1 - w) * * and similarly for [-w^-1, -w] and [-1, 1]. * * [-w^-1, w] is orthogonal to [-i, i] because * * (-i - -w^-1) (i - w) * -------------------- = -1 * (i - -w^-1) (-i - w) * * and similarly for [w^-1, -w] and [-i, i]. * * Q.E.D. * * * The tetrahedron will have the correct cross ratio z iff * * (w - -w^-1) (w^-1 - -w ) (w + w^-1)^2 * z = -------------------------- = -------------- * (w - -w ) (w^-1 - -w^-1) 4 * * Solving for w in terms of z gives the four possibilities * * w = +- (sqrt(z) +- sqrt(z - 1)) * * Note that sqrt(z) + sqrt(z - 1) and sqrt(z) - sqrt(z - 1) are * inverses of one another. We can choose any of the four solutions * to be "w", and the other three will automatically become w^-1, * -w, and -w^-1. * * Comment: This position for the initial corners brings out * nice numerical properties in the O(3,1) matrices for manifolds * composed of regular ideal tetrahedra (cf. the proofs in the * directory "Tilings of H^3", which aren't part of SnapPea, but * I could give you a copy). */ z = (*initial_tet)->shape[filled]->cwl[ultimate][0].rect; w[0] = complex_plus( complex_sqrt(z), complex_sqrt(complex_minus(z, One)) ); w[1] = complex_div(One, w[0]); w[2] = complex_negate(w[1]); w[3] = complex_negate(w[0]); (*initial_tet)->corner[0] = w[0]; (*initial_tet)->corner[1] = w[1]; (*initial_tet)->corner[2] = w[2]; (*initial_tet)->corner[3] = w[3]; } else { /* * Originally this code positioned the Tetrahedron's vertices * at {0, 1, z, infinity}. As of 2000/02/04 I modified it * to put the vertices at {0, 1/sqrt(z), sqrt(z), infinity} instead, * so that the basepoint (0,0,1) falls at the midpoint * of the edge extending from 0 to infinity, and the * tetrahedron's symmetry axis lies parallel to the x-axis. * To convince yourself that the tetrahedron's axis of * symmetry does indeed pass through that point, note * that a half turn around the axis of symmetry factors * as a reflection in the plane |z| = 1 followed by * a reflection in the vertical plane sitting over x-axis. */ /* * Order the vertices so that the tetrahedron is positively * oriented, and the selected edge is between vertices * v[0] and v[1]. */ v[0] = one_vertex_at_edge[best_edge]; v[1] = other_vertex_at_edge[best_edge]; v[2] = remaining_face[v[1]][v[0]]; v[3] = remaining_face[v[0]][v[1]]; /* * Set the coordinates of the corners. */ z = (*initial_tet)->shape[filled]->cwl[ultimate][edge3[best_edge]].rect; sqrt_z = complex_sqrt(z); (*initial_tet)->corner[v[0]] = Infinity; (*initial_tet)->corner[v[1]] = Zero; (*initial_tet)->corner[v[2]] = complex_div(One, sqrt_z); (*initial_tet)->corner[v[3]] = sqrt_z; } } } void compute_fourth_corner( Complex corner[4], VertexIndex missing_corner, Orientation orientation, ComplexWithLog cwl[3]) { int i; VertexIndex v[4]; Complex z[4], cross_ratio, diff20, diff21, numerator, denominator; /* * Given the locations on the sphere at infinity in * the upper half space model of three of a Tetrahedron's * four ideal vertices, compute_fourth_corner() computes * the location of the remaining corner. * * corner[4] is the array which contains the three known * corners, and into which the fourth will be * written. * * missing_corner is the index of the unknown corner. * * orientation is the Orientation with which the Tetrahedron * is currently being viewed. * * cwl[3] describes the shape of the Tetrahedron. */ /* * Set up an indexing scheme v[] for the vertices. * * If some vertex (!= missing_corner) is positioned at infinity, let its * index be v0. Otherwise choose v0 arbitrarily. Then choose * v2 and v3 so that the Tetrahedron looks right_handed relative * to the v[]. */ v[3] = missing_corner; v[0] = ! missing_corner; for (i = 0; i < 4; i++) if (i != missing_corner && complex_infinite(corner[i])) v[0] = i; if (orientation == right_handed) { v[1] = remaining_face[v[3]][v[0]]; v[2] = remaining_face[v[0]][v[3]]; } else { v[1] = remaining_face[v[0]][v[3]]; v[2] = remaining_face[v[3]][v[0]]; } /* * Let z[i] be the location of v[i]. * The z[i] are known for i < 3, unknown for i == 3. */ for (i = 0; i < 3; i++) z[i] = corner[v[i]]; /* * Note the cross_ratio at the edge connecting v0 to v1. */ cross_ratio = cwl[edge3_between_faces[v[0]][v[1]]].rect; if (orientation == left_handed) cross_ratio = complex_conjugate(complex_div(One, cross_ratio)); /* * The cross ratio is defined as * * (z3 - z1) (z2 - z0) * cross_ratio = ----------------------- * (z2 - z1) (z3 - z0) * * Solve for z3. * * z1*(z2 - z0) - cross_ratio*z0*(z2 - z1) * z3 = ----------------------------------------- * (z2 - z0) - cross_ratio*(z2 - z1) * * If z0 is infinite, this reduces to * * z3 = z1 + cross_ratio * (z2 - z1) * * which makes sense geometrically. */ if (complex_infinite(z[0]) == TRUE) z[3] = complex_plus( z[1], complex_mult( cross_ratio, complex_minus(z[2], z[1]) ) ); else { diff20 = complex_minus(z[2], z[0]); diff21 = complex_minus(z[2], z[1]); numerator = complex_minus( complex_mult(z[1], diff20), complex_mult( cross_ratio, complex_mult(z[0], diff21) ) ); denominator = complex_minus( diff20, complex_mult(cross_ratio, diff21) ); z[3] = complex_div(numerator, denominator); /* will handle division by Zero correctly */ } corner[missing_corner] = z[3]; } static void count_incident_generators( Triangulation *manifold) { EdgeClass *edge; Tetrahedron *tet; FaceIndex face, face1; /* * For each EdgeClass, initialize num_incident_generators to zero. * Initialize all the active_relation flags to TRUE while we're at it. */ for ( edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) { edge->num_incident_generators = 0; edge->active_relation = TRUE; } /* * For each face of a Tetrahedron dual to an outbound_generator, * increment the num_incident_generators count of the three * adjacent EdgeClasses. Ignore inbound_generators, to avoid * counting each generator twice. */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (face = 0; face < 4; face++) if (tet->generator_status[face] == outbound_generator) for (face1 = 0; face1 < 4; face1++) if (face1 != face) tet->edge_class[edge_between_faces[face][face1]]->num_incident_generators++; } static void eliminate_trivial_generators( Triangulation *manifold) { Boolean progress; EdgeClass *edge; do { progress = FALSE; for ( edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) if (edge->num_incident_generators == 1) { kill_the_incident_generator(manifold, edge); progress = TRUE; } } while (progress == TRUE); } static void kill_the_incident_generator( Triangulation *manifold, EdgeClass *edge) { PositionedTet ptet, ptet0; int dead_index; Tetrahedron *tet, *nbr_tet; Permutation gluing; FaceIndex face, nbr_face; /* * The EdgeClass edge is incident to a unique generator. * Find it. */ set_left_edge(edge, &ptet0); ptet = ptet0; while (TRUE) { /* * If we've found the active generator, * break out of the while loop. Otherwise . . . */ if (ptet.tet->generator_status[ptet.near_face] != not_a_generator) break; /* * . . . move on to the next Tetrahedron incident to the EdgeClass. */ veer_left(&ptet); /* * If we've come all the way around the EdgeClass without * finding a generator, something has gone terribly wrong. */ if (same_positioned_tet(&ptet, &ptet0)) uFatalError("kill_the_incident_generator", "choose_generators.c"); } /* * Note the index of the about to be killed generator . . . */ dead_index = ptet.tet->generator_index[ptet.near_face]; /* * . . . then kill it. */ nbr_tet = ptet.tet->neighbor[ptet.near_face]; gluing = ptet.tet->gluing[ptet.near_face]; nbr_face = EVALUATE(gluing, ptet.near_face); ptet.tet->generator_status[ptet.near_face] = not_a_generator; nbr_tet ->generator_status[nbr_face] = not_a_generator; ptet.tet->generator_index[ptet.near_face] = -1; /* garbage value */ nbr_tet ->generator_index[nbr_face] = -1; /* * The EdgeClass no longer represents an active relation. */ edge->active_relation = FALSE; /* * Decrement the num_incident_generators count at each of * the incident EdgeClasses. */ ptet.tet->edge_class[edge_between_faces[ptet.near_face][ptet.left_face] ]->num_incident_generators--; ptet.tet->edge_class[edge_between_faces[ptet.near_face][ptet.right_face] ]->num_incident_generators--; ptet.tet->edge_class[edge_between_faces[ptet.near_face][ptet.bottom_face]]->num_incident_generators--; /* * Decrement *number_of_generators. */ manifold->num_generators--; /* * If dead_index was not the highest numbered generator, then removing * it will have left a gap in the numbering scheme. Renumber the highest * numbered generator to keep the numbering contiguous. */ if (dead_index != manifold->num_generators) { for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (face = 0; face < 4; face++) if (tet->generator_index[face] == manifold->num_generators) { if (tet->generator_status[face] == not_a_generator) uFatalError("kill_the_incident_generator", "choose_generators.c"); nbr_tet = tet->neighbor[face]; gluing = tet->gluing[face]; nbr_face = EVALUATE(gluing, face); tet ->generator_index[face] = dead_index; nbr_tet->generator_index[nbr_face] = dead_index; /* * Rather than worrying about breaking out of a * double loop, let's just return from here. */ return; } /* * The program should return from within the above double loop. */ uFatalError("kill_the_incident_generator", "choose_generators.c"); } else /* dead_index == manifold->num_generators, so nothing else to do */ return; } static void merge_equivalent_generators( Triangulation *manifold) { EdgeClass *edge; for ( edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) if (edge->num_incident_generators == 2) merge_incident_generators(manifold, edge); } static void merge_incident_generators( Triangulation *manifold, EdgeClass *edge) { PositionedTet ptet, ptet0; Tetrahedron *tetA = NULL, *tetB = NULL, *tet; FaceIndex faceA = 0, faceB = 0, face; int indexA, indexB; Boolean generator_A_has_been_found, directions_agree; /* * Find the two incident generators by letting ptet * rotate around the EdgeClass. The first time we * encounter a nontrivial generator, call it * faceA of tetA; the second time, faceB of tetB. */ set_left_edge(edge, &ptet0); ptet = ptet0; generator_A_has_been_found = FALSE; while (TRUE) { /* * If we've found an active generator, record it. * If this is the second one we've found, break out of the loop. */ if (ptet.tet->generator_status[ptet.near_face] != not_a_generator) { if (generator_A_has_been_found == FALSE) { tetA = ptet.tet; faceA = ptet.near_face; generator_A_has_been_found = TRUE; } else { tetB = ptet.tet; faceB = ptet.near_face; break; } } /* * Move on to the next Tetrahedron incident to the EdgeClass. */ veer_left(&ptet); /* * If we've come all the way around the EdgeClass without * finding both generators, something has gone terribly wrong. */ if (same_positioned_tet(&ptet, &ptet0)) uFatalError("kill_the_incident_generator", "choose_generators.c"); } /* * If the two generators are the same, then either their product is * aA (in which case there is no further work to be done) or aa (in * which case they cannot be merged). Either way, we simply return. * [JRW 95/1/19. Actually, I don't think the first case (aA) is * likely to occur. The n-gons which are subdivided into triangles * have no interior vertices, so under normal circumstances the * generators we're merging should be distinct. If they're not, * it means we have a "face" which is topologically a cylinder, * or something weird like that. At any rate, we should return * without taking any action.] */ indexA = tetA->generator_index[faceA]; indexB = tetB->generator_index[faceB]; if (indexA == indexB) return; /* * Do the directions of the generators agree or disagree? * Note that the generator will point in the same direction * relative to the boundary of the fundamental domain iff * one is an outbound_generator and the other is an inbound_generator * relative to the preceding cyclic traversal around the EdgeClass. */ directions_agree = (tetA->generator_status[faceA] != tetB->generator_status[faceB]); /* * If directions_agree is FALSE, reverse the direction of generator A. * Then let generator A inherit the index of generator B. * * Let the highest numbered generator inherit the former index * of generator A, and decrement the number_of_generators count. * * Even in the special cases where indexA or indexB is the highest * index, generators A and B get merged, and the previously highest * index will no longer occur. This keeps the indices contiguous. */ manifold->num_generators--; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (face = 0; face < 4; face++) { if (tet->generator_index[face] == indexA) { if (directions_agree == FALSE) { if (tet->generator_status[face] == outbound_generator) tet->generator_status[face] = inbound_generator; else if (tet->generator_status[face] == inbound_generator) tet->generator_status[face] = outbound_generator; else uFatalError("merge_incident_generators", "choose_generators.c"); } tet->generator_index[face] = indexB; } if (tet->generator_index[face] == manifold->num_generators) tet->generator_index[face] = indexA; } /* * The EdgeClass no longer represents an active relation. */ edge->active_relation = FALSE; } static void eliminate_empty_relations(Triangulation *manifold) { EdgeClass *edge; for ( edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) if (edge->num_incident_generators == 0) edge->active_relation = FALSE; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/close_cusps.c000644 000765 000024 00000151446 12377774107 021504 0ustar00babstaff000000 000000 /* * close_cusps.c * * This file contains the function * * void close_cusps(Triangulation *manifold, Boolean fill_cusp[]); * * which is used by the function fill_cusps() to permanently * close the indicated cusps (those for which fill_cusp[cusp->index] * is TRUE). The Triangulation *manifold must be a manifold with * finite vertices, prepared as in subdivide(). Specifically, we * assume that the Tetrahedra incident to the cusps form disjoint * regular neighborhoods of the cusps in the manifold. close_cusps() * removes the regular neighborhood of each cusp, and fills in the * hole in such a way that the given Dehn filling curve (as specified * by cusp->m and cusp->l) becomes a trivial curve in the new manifold. * I.e. it does the Dehn filling. We assume the Dehn filling coefficients * are relatively prime integers (fill_cusps() checks this). * * * The remainder of this comment briefly explains the algorithm used * to fill the cusps. It is not a polished exposition, but I hope it * is mathematically clear and complete. * * We consider the 2-dimensional triangulation of a boundary component * of the manifold obtained when the regular neighborhood of a cusp * (as mentioned above) is stripped off. The basic idea is to fold * together adjacent triangles (which are really exposed faces of * tetrahedra) using a "close-the-book" move. Proposition 1 below * gives a sufficient condition that the folding does not change the * topology of either the manifold or its boundary. Proposition 2 * proves that if we keep folding as long as possible (i.e. as long * as we can find a pair of triangles satisfying the hypothesis of * Proposition 1), we will end up with no more than six triangles in * the (2-dimensional) triangulation. Further fussing around will * reduce the number of triangles to two. * * Before stating Propositions 1 and 2, we need a definition. * * Consider a triangle, along with one of its neighbors, which may or * may not be distinct from the first triangle. The neighbor won't be * distinct iff the first triangle is glued to itself along the given edge. * Strictly speaking, the illustration below lies in the universal cover. * * o * /|\ * / | \ * / | \ * A o | o B * \ | / * \ | / * \|/ * o * * Definition. When discussing two adjacent (but not necessarily * distinct) triangles sharing a common edge, the vertices further * from the common edge are called the "opposite vertices". In the * above illustration, the opposite vertices are labelled A and B. * * Proposition A. The close-the-book move is valid if the * opposite vertices are distinct. * * Proposition B. If we apply the close-the-book move * until there are no more adjacent triangles with * distinct opposite vertices, then we will have reached * a triangulation with at most 6 triangles. Attaching * one or two tetrahedra to the boundary lets us further * simplify the triangulation to have exactly two triangles. * * First a few preparatory lemmas. * * Lemma 1. If the opposite vertices are distinct, * then the triangles are distinct too. * * Proof. There are two ways a triangle may be glued * to itself (orientation preserving and orientation * reversing). It's trivial to check each case, and see * that the vertices opposite the identifed edge are * themselves identified. [In the figure below, I * attempted to draw arrows showing the edge identifications.] * * B A * o o * / \ / \ * _/ \_ _/ \ * /| |\ /| _\| * / \ / \ * A o---------o A A o---------o A * * * Lemma 2. The number of vertices in a triangulation of a * torus or Klein bottle is half the number of triangles. * * Proof. This is an easy Euler characteristic argument. * * chi = 0 = v - e + f = v - (3/2)f + f * * => v = f/2. * * Comment: We will think of the close-the-book move in * purely two-dimensional terms. We think of it as a two-step * process. First we collapse a line segment connecting the * opposite vertices, then we collapse the two resulting bigons. * * draw the line * connecting collapse collapse * opposite the the * vertices line bigons * o o o o * /|\ / \ / \ | * / | \ / \ | | | * / | \ / \ \ / | * A o | o B A o-------o B o A = B o * \ | / \ / / \ | * \ | / \ / | | | * \|/ \ / \ / | * o o o o * * Proposition A addresses the question of when these operations * are valid. * * Proof of Proposition A. * By Lemma 1 the triangles are distinct, so the * segment connecting A to B is an embedded arc with distinct * endpoints, and may therefore by collapsed to a point as * shown in the above illustration. * The two edges of the upper bigon (see the third frame * of the above illustration) are distinct, since otherwise * the top two edges in the second frame of the illustration * would be identified, and Lemma 1 would imply A = B. * Similarly, the two edges of the lower bigon are distinct. * It's possible that one edge of the upper bigon is identified * with an edge of the lower bigon, but both edges of the upper * bigon cannot be identified to edges of the lower, since that * would imply that the original triangulation contained only the * two triangles shown, and Lemma 2 would then imply that there * is only one vertex. It follows that the bigons may be collapsed. * Q.E.D. * * Comment. The converse to the Proposition A is almost true. If the * opposite vertices are not distinct (A = B in the above * illustration) then the line connecting them is a circle. * If this circle is homotopically nontrivial, then it certainly * cannot be collapsed to a point. However, if it's homotopically * trivial, then a modification of the close-the-book move is still * possible (but is not used in SnapPea's algorithm). * * Proof of Proposition B. * If opposite vertices are equivalent for each pair of adjacent * triangles, then all triangles will have the same set of vertices * (the torus or Klein bottle is connected). * Therefore the triangulation contains at most three vertices, * and, by Lemma 2, at most six triangles. * We now address the question of how to reduce the triangulation * to only two vertices. The basic idea is to find an edge connecting * two inequivalent vertices, and attach a (solid!) tetrahedron * so as to implement a "two-to-two move" in the triangulation of the * boundary. * * attach a * tetrahedron * to alter the * triangulation * as shown * o o * / \ /|\ * / \ / | \ * / \ / | \ * A o-------o B A o | o B * \ / \ | / * \ / \ | / * \ / \|/ * o o * * Clearly an edge connecting inequivalent vertices must exist * (by the connectivity of the torus or Klein bottle). The only * question is whether the two incident triangles are distinct. * If they weren't distinct, then the edge identifications would * have to have the pattern shown on the left side of the * illustration accompanying the proof of Lemma 1. (They couldn't * have the pattern shown on the right side of that illustration, * because then there wouldn't be two inequivalent vertices.) * Vertex B in the left side of the illustration accompanying * the proof of Lemma 1 would be isolated from the rest of the * boundary manifold. Therefore it would be opposite a distinct * vertex, and the close-the-book move would still be possible. * Q.E.D. * * Technical note: close_cusps() always performs the two-to-two * move in such a way that the subsequent close-the-book move does * not fold together two faces of the same tetrahedron. This * avoids needlessly creating an EdgeClass of order one in the * manifold. Maybe such an EdgeClass would do no harm, but who knows? */ #include "kernel.h" #include "kernel_namespace.h" struct extra { VertexIndex ideal_vertex_index; int Dehn_filling_curve[4]; }; static void transfer_to_short_list(Triangulation *manifold, Boolean fill_cusp[], Tetrahedron *short_list_begin, Tetrahedron *short_list_end); static Boolean incident_to_filled_cusp(Tetrahedron *tet, Boolean fill_cusp[]); static void simplify_cusps(Triangulation *manifold, Tetrahedron *short_list_begin, Tetrahedron *short_list_end); static void fold_boundary(Tetrahedron *short_list_begin, Tetrahedron *short_list_end); static Boolean cancel_triangles(Tetrahedron *tet, FaceIndex f0); static Boolean further_simplification(Triangulation *manifold, Tetrahedron *short_list_begin, Tetrahedron *short_list_end); static Boolean two_to_two(Triangulation *manifold, Tetrahedron *tet, FaceIndex f0, Boolean require_distinct_edges); static void transfer_curves(Tetrahedron *short_list_begin, Tetrahedron *short_list_end); static void standard_form(Triangulation *manifold, Tetrahedron *short_list_begin, Tetrahedron *short_list_end); static void standard_torus_form(Triangulation *manifold, Tetrahedron *tet); static int max_abs_intersection_number(Tetrahedron *tet); static void apply_two_to_two_to_eliminate(Triangulation *manifold, Tetrahedron *tet, int target); static void standard_Klein_bottle_form(Triangulation *manifold, Tetrahedron *tet); static void fold_cusps(Triangulation *manifold, Tetrahedron *short_list_begin, Tetrahedron *short_list_end); static void fold_one_cusp(Triangulation *manifold, Tetrahedron *tet0); static void replace_fake_cusps(Triangulation *manifold); static void renumber_real_cusps(Triangulation *manifold); void close_cusps( Triangulation *manifold, Boolean fill_cusp[]) { Tetrahedron short_list_begin, short_list_end; /* * Move the Tetrahedra incident to cusps-to-be-filled onto a * separate short list, so we don't have to be constantly sifting * through vast numbers of irrelevant Tetrahedra. Attach and * initialize an Extra structure on each Tetrahedron on the * short list. */ transfer_to_short_list(manifold, fill_cusp, &short_list_begin, &short_list_end); /* * Simplify the cusps to be filled until each is triangulated * by at most two triangles. Ignore (1) fake "Cusps" at finite * vertices and (2) EdgeClasses not incident to a real Cusp; * we'll fix them up at the end. We maintain the tet->edge_class() * fields for edges incident to real Cusps so that we can tell * whether two EdgeClasses are distinct. The fields within an * EdgeClass are not maintained. */ simplify_cusps(manifold, &short_list_begin, &short_list_end); /* * Transfer the Dehn filling curves to tet->extra->Dehn_filling_curve[]. */ transfer_curves(&short_list_begin, &short_list_end); /* * Put each boundary triangulation at each cusp to be filled into * the standard form: * * torus Klein bottle * ------>>----- ------>------ * | @ /| | @ /| * | @ / | | @ / | * | @ | | @ | * | / @ | | / @ | * | / @| | / @| * ^@ / ^ ^@ / ^ * | @ / | | @ / ^ * | @/ | | @/ | * | /@ | | /@ | * | / @ | | / @ | * |/ @ | |/ @ | * ------>>----- ------>>----- * * * where the line of @'s is the Dehn filling curve. */ standard_form(manifold, &short_list_begin, &short_list_end); /* * Collapse each cusp by folding along the diagonal in * the above illustrations. */ fold_cusps(manifold, &short_list_begin, &short_list_end); /* * Get rid of the old EdgeClasses and install new ones. */ replace_edge_classes(manifold); /* * Get rid of the old fake Cusps and install new ones. */ replace_fake_cusps(manifold); /* * Renumber the remaining real Cusps, so the indices * are contiguous. */ renumber_real_cusps(manifold); /* * 96/9/28 I haven't actually observed any incorrect behavior * (and I don't think there is any) but I was looking through * the kernel code to see how orient() was being used, and I * got to wondering whether close_cusps() is guaranteed to preserve * the orientation. Just to make sure it does, call orient() now, * to transfer the orientation from one of the untouched tetrahedra * (i.e. an original tetrahedron not incident to one of the * cusps-to-be-filled) to all remaining tetrahedra, including the * new ones. * * 96/9/30 After adding the call to orient() I rechecked all * Chern-Simons value for the cusped census, and they are all correct. */ orient(manifold); } static void transfer_to_short_list( Triangulation *manifold, Boolean fill_cusp[], Tetrahedron *short_list_begin, Tetrahedron *short_list_end) { Tetrahedron *tet, *this_tet; /* * Initialize the short list. */ short_list_begin->prev = NULL; short_list_begin->next = short_list_end; short_list_end ->prev = short_list_begin; short_list_end ->next = NULL; /* * Transfer Tetrahedra incident to cusps-to-be-filled * to the short list. */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) if (incident_to_filled_cusp(tet, fill_cusp) == TRUE) { this_tet = tet; tet = tet->prev; /* so the loop proceeds correctly */ REMOVE_NODE(this_tet); INSERT_BEFORE(this_tet, short_list_end); manifold->num_tetrahedra--; } } static Boolean incident_to_filled_cusp( Tetrahedron *tet, Boolean fill_cusp[]) { int i; for (i = 0; i < 4; i++) if (tet->cusp[i]->is_finite == FALSE && fill_cusp[tet->cusp[i]->index] == TRUE) { /* * Make sure no other routine is using the "extra" * field in the Tetrahedron data structure. */ if (tet->extra != NULL) uFatalError("incident_to_filled_cusp", "close_cusps"); /* * Attach the locally defined struct extra. */ tet->extra = NEW_STRUCT(Extra); /* * Record for posterity the index of the ideal vertex. */ tet->extra->ideal_vertex_index = i; return TRUE; } return FALSE; } static void simplify_cusps( Triangulation *manifold, Tetrahedron *short_list_begin, Tetrahedron *short_list_end) { /* * simplify_cusps() simplifies a triangulation until each * boundary component is triangulated by exactly two triangles. * * It calls two other functions: * * fold_boundary() folds together adjacent boundary * triangles whereever possible, as explained in the proofs * at the top of this file. It is guaranteed to reduce the * triangulation of each boundary component to at most six * triangles. * * further_simplification() look for an edge (in the 2-dimensional * triangulation of the boundary) with distinct endpoints. * When it finds one it does a two-to-two move, as shown in * the illustration below, so that fold_boundary() can * make further progress. Because the number of vertices is * exactly half the number of triangles, further_simplification() * is guaranteed to make progress as long as the number of * triangles in a given boundary component exceeds two. * * before after * /\ c /|\ c * / \ / | \ * / \ / | \ * / \ / | \ * a /________\ b a / | \ b * \ / \ | / * \ / \ | / * \ / \ | / * \ / \ | / * \/ c \|/ c * * Note that this algorithm risks the creation of edges of order one * in the (3-dimenisional) triangulation of the manifold. But we * bravely press on, confident that if we get into trouble further * down the road, we can call a general purpose simplification * routine to remove the offending edges. */ do { fold_boundary(short_list_begin, short_list_end); } while (further_simplification(manifold, short_list_begin, short_list_end) == TRUE); } static void fold_boundary( Tetrahedron *short_list_begin, Tetrahedron *short_list_end) { Tetrahedron *tet; FaceIndex f; /* * Scan down the list of boundary Tetrahedra, looking for * one which can be cancelled with one of its neighbors. * (One expects almost any pair of adjacent boundary Tetraheda * to be cancellable.) When one is found, do the cancellation * and resume the search from the start of the list. */ for (tet = short_list_begin->next; tet != short_list_end; tet = tet->next) for (f = 0; f < 4; f++) { if (f == tet->extra->ideal_vertex_index) continue; if (cancel_triangles(tet, f) == TRUE) { tet = short_list_begin; break; } } } static Boolean cancel_triangles( Tetrahedron *tet, FaceIndex f0) { Tetrahedron *nbr_tet, *t, *nbr_t; FaceIndex f[4], nbr_f[4], v[4], nbr_v[4]; EdgeIndex edge, nbr_edge; EdgeClass *e_class, *nbr_class; int i, ii, j; int b[2], c[2], delta[2][2]; PositionedTet ptet, ptet0; /* * f0 will be part of an array. */ f[0] = f0; /* * Find the neighbor adjacent to face f[0]. */ nbr_tet = tet->neighbor[f[0]]; nbr_f[0] = EVALUATE(tet->gluing[f[0]], f[0]); /* * Note the base of each Tetrahedron. */ f[1] = tet->extra->ideal_vertex_index; nbr_f[1] = nbr_tet->extra->ideal_vertex_index; /* * Do a quick error check. */ if (nbr_f[1] != EVALUATE(tet->gluing[f[0]], f[1])) uFatalError("cancel_triangles", "close_cusps"); /* * Note the EdgeIndices of the "vertical" edges farthest from * the common face. According to the propositions at the top * of this file, the Tetrahedra may be cancelled iff these * two edges belong to different EdgeClasses. */ edge = edge_between_vertices[f[0]][f[1]]; nbr_edge = edge_between_vertices[nbr_f[0]][nbr_f[1]]; e_class = tet->edge_class[edge]; nbr_class = nbr_tet->edge_class[nbr_edge]; if (e_class == nbr_class) return FALSE; /* * According to the propositions at the top of this file, * the fact that the EdgeClasses are distinct implies that * the Tetrahedra are distinct as well. Let's check, just * to be sure. */ if (tet == nbr_tet) uFatalError("cancel_triangles", "close_cusps"); /* * The following line isn't really necessary, but it serves to avoid * creating EdgeClasses of order one. If further_simplification() * has just laid down a Tetrahedron to implement a two-to-two * move, we want to avoid folding that Tetrahedron onto itself. * By checking cases (cf. the documentation and illustrations * in two_to_two() below) it's easy to see that some other * call to cancel_triangles() (not involving gluing a Tetrahedron * to itself) must succeed. */ if (tet->neighbor[f[1]] == nbr_tet->neighbor[nbr_f[1]]) return FALSE; /* * Adjust the peripheral curves so that when we collapse * the Tetrahedra, the curves match up correctly. * * /\ * / \ * a / \ b * / \ * /________\ * \ / * \ / * d \ / c * \ / * \/ E * * We want to insure that b = -c, which automatically imples a = -d. * Geometrically, all strands at c should pass to b, and all strands * at d should pass to a. Nothing should cut across the middle * from c to a, or from d to b. To accomplish this, we subtract * (b + c) all the way around the (vertical) EdgeClass E. * * As long as we're travelling around the EdgeClass, set the * tet->edge_class pointers to the address of the EdgeClass * this one is merging into. */ f[2] = remaining_face[f[1]][f[0]]; f[3] = remaining_face[f[0]][f[1]]; nbr_f[2] = EVALUATE(tet->gluing[f[0]], f[2]); nbr_f[3] = EVALUATE(tet->gluing[f[0]], f[3]); for (i = 0; i < 2; i++) /* which sheet */ { ii = (parity[tet->gluing[f[0]]] == orientation_preserving) ? i : !i; for (j = 0; j < 2; j++) /* which curve */ { b[j] = nbr_tet->curve[j][ii][nbr_f[1]][nbr_f[2]]; c[j] = tet->curve[j][i ][ f[1]][ f[2]]; delta[j][i] = b[j] + c[j]; } } ptet0.tet = tet; ptet0.near_face = f[2]; ptet0.left_face = f[3]; ptet0.right_face = f[0]; ptet0.bottom_face = f[1]; ptet0.orientation = right_handed; ptet = ptet0; do { for (i = 0; i < 2; i++) { ii = (ptet.orientation == ptet0.orientation) ? i : !i; for (j = 0; j < 2; j++) /* which curve */ { ptet.tet->curve[j][i][ptet.bottom_face][ptet.left_face] += delta[j][ii]; ptet.tet->curve[j][i][ptet.bottom_face][ptet.near_face] -= delta[j][ii]; } } ptet.tet->edge_class[edge_between_faces[ptet.near_face][ptet.left_face]] = nbr_class; veer_left(&ptet); } while ( ! same_positioned_tet(&ptet, &ptet0)); /* * Imagine removing tet and nbr_tet from the manifold. * Glues together the three exposed pairs of faces. * * Miraculously, this code is correct even in degenerate * cases (corresponding to when the bigons collapse in * the proofs at the top of this file). */ for (i = 1; i < 4; i++) { t = tet->neighbor[f[i]]; nbr_t = nbr_tet->neighbor[nbr_f[i]]; for (j = 0; j < 4; j++) { v[j] = EVALUATE(tet->gluing[f[i]], f[j]); nbr_v[j] = EVALUATE(nbr_tet->gluing[nbr_f[i]], nbr_f[j]); } t->neighbor[v[i]] = nbr_t; nbr_t->neighbor[nbr_v[i]] = t; t->gluing[v[i]] = CREATE_PERMUTATION(v[0], nbr_v[0], v[1], nbr_v[1], v[2], nbr_v[2], v[3], nbr_v[3]); nbr_t->gluing[nbr_v[i]] = CREATE_PERMUTATION(nbr_v[0], v[0], nbr_v[1], v[1], nbr_v[2], v[2], nbr_v[3], v[3]); } /* * Free tet and nbr_tet. */ REMOVE_NODE(tet); REMOVE_NODE(nbr_tet); free_tetrahedron(tet); free_tetrahedron(nbr_tet); return TRUE; } static Boolean further_simplification( Triangulation *manifold, Tetrahedron *short_list_begin, Tetrahedron *short_list_end) { Tetrahedron *tet; FaceIndex f; /* * Scan down the list of boundary Tetrahedra, looking for * an edge (in the 2-dimensional triangulation of the boundary) * with distinct endpoints. If one is found, do the necessary * retriangulation (as illustrated in simplify_cusps() above) * and return TRUE. If none are found, return FALSE. * * Note that at most one retriangulation will be performed in * a single call to further_simplification(). */ for (tet = short_list_begin->next; tet != short_list_end; tet = tet->next) for (f = 0; f < 4; f++) { if (f == tet->extra->ideal_vertex_index) continue; if (two_to_two(manifold, tet, f, TRUE) == TRUE) return TRUE; } return FALSE; } /* * two_to_two() is called from two different parts of close_cusps(). * * (1) further_simplification() calls it to alter a triangulation * so that the number of triangles in the triangulation of * a boundary component can be reduced from 4 or 6 to 2. * In this case, two_to_two() should do nothing and return * FALSE if a certain pair of EdgeClasses are not distinct. * * (2) standard_form() calls it (indirectly) to put 2-triangle * triangulations into the standard form. Here there is no * need for any EdgeClasses to be distinct (in fact, they never * will be). * * The argument require_distinct_edges says whether distinct EdgeClasses * should be required. */ static Boolean two_to_two( Triangulation *manifold, Tetrahedron *tet, FaceIndex f0, Boolean require_distinct_edges) { int i, ii, j; FaceIndex f[4], nbr_f[4]; Tetrahedron *nbr_tet, *new_tet, *tetA, *tetB; EdgeClass *e_class[4]; /* * Get set up as in cancel_triangles() above. */ f[0] = f0; nbr_tet = tet->neighbor[f[0]]; nbr_f[0] = EVALUATE(tet->gluing[f[0]], f[0]); f[1] = tet->extra->ideal_vertex_index; nbr_f[1] = nbr_tet->extra->ideal_vertex_index; if (nbr_f[1] != EVALUATE(tet->gluing[f[0]], f[1])) uFatalError("two_to_two", "close_cusps"); f[2] = remaining_face[f[1]][f[0]]; f[3] = remaining_face[f[0]][f[1]]; nbr_f[2] = EVALUATE(tet->gluing[f[0]], f[2]); nbr_f[3] = EVALUATE(tet->gluing[f[0]], f[3]); /* * Note the EdgeClasses. */ e_class[0] = tet->edge_class[ edge_between_faces[ f[2]][ f[3]] ]; e_class[1] = nbr_tet->edge_class[ edge_between_faces[nbr_f[2]][nbr_f[3]] ]; e_class[2] = tet->edge_class[ edge_between_faces[ f[0]][ f[2]] ]; e_class[3] = tet->edge_class[ edge_between_faces[ f[0]][ f[3]] ]; /* * If require_distinct_edges is TRUE, check the EdgeClasses. * (See comment preceeding this function.) * further_simplification() can make progress iff e_class[2] != e_class[3]. */ if (require_distinct_edges == TRUE && e_class[2] == e_class[3]) return FALSE; /* * In further_simplification() . . . * * We now know that no triangle in the * 2-dimensional triangulation of the boundary is * glued to itself, because if it were glued to itself with * * an orientation preserving gluing, then there would * be an isolated vertex, and further progress would * have been possible in fold_boundary() * * an orientation reversing gluing, then there would be * only one vertex in the triangulation of the boundary, * and class2 would have equalled class3. (Recall * that when fold_boundary() can make no more * progress, all boundary triangles have the same set * of vertices, including multiplicity.) * * In standard_form() . . . * * We know that no triangle can be glued to itself, because * otherwise the boundary would be a Klein bottle already in * standard form. */ if (tet == nbr_tet) uFatalError("two_to_two", "close_cusps"); /* * [This comment applies on if we were called from * further_simplification().] * * Continuing with the idea that all boundary triangles * have the same vertex set, it follows that each triangle * must be of the form * * A A * o o * / \ / \ * / \ OR / \ * / \ / \ * / \ / \ * B o---------o B B o---------o C * * In the first case, the boundary component is formed * by identifying sides of the square * * B o-------------o B * |\ /| * | \ / | * | \ / | * | \ / | * | \ / | * | \ / | * | A o | * | / \ | * | / \ | * | / \ | * | / \ | * | / \ | * |/ \| * B o-------------o B * * and in the second case by identifying sides of the * hexagon * * B ____________ C * /\ /\ * / \ / \ * / \ / \ * / \ / \ * / \ / \ * C /_________A\/__________\ B * \ /\ / * \ / \ / * \ / \ / * \ / \ / * \ / \ / * \/__________\/ * B C * * It's easy to figure out that there are three possible * gluing patterns for the square (xyXY, xyXy and xxyy) * and two for the hexagon (xyzXYZ and xyzXzy). In all * but one case (the xxyy gluing of the square) we may * conclude that tet and nbr_tet's neighbors are distinct * from tet and nbr_tet (except for obvious place they meet). * Even in the exceptional case, there are other places * where we could do the two-to-two move where the * neighbors are distinct from tet and nbr_tet. So * if the neighbors aren't distinct from tet and nbr_tet, * we simply return FALSE and wait for one of those * more convenient places to show up. */ /* * First label everything in sight. * Use macros rather than writing quantities into * arrays, so that in cases where tet and nbr_tet are glued * nontrivially to each other, the results will be correct. * That is, we want the quantities to be reevaluated every * time they are used. */ #define TET_T(i) tet->neighbor[f[i]] #define NBR_T(i) nbr_tet->neighbor[nbr_f[i]] #define TET_V(i,j) EVALUATE(tet->gluing[f[i]], f[j]) #define NBR_V(i,j) EVALUATE(nbr_tet->gluing[nbr_f[i]], nbr_f[j]) /* * In the event we were called from further_simplification, * check that the TET_T(i) and NBR_T(i) are distinct from * tet and nbr_tet. This avoids unnecessarily creating an * EdgeClass of order one (maybe it doesn't matter, but * why risk it?). */ if (require_distinct_edges == TRUE) for (i = 2; i < 4; i++) if (TET_T(i) == tet || TET_T(i) == nbr_tet || NBR_T(i) == tet || NBR_T(i) == nbr_tet) return FALSE; /* * We introduce a new Tetrahedron which realizes the * two-to-two move on the boundary triangulation, and * adjust tet and nbr_tet to sit correctly above it. * * We could just reuse the tet and nbr_tet structures, but * then there'd be problems if either is glued to itself or * the other (aside from the obvious place they're glued). * So we replace tet and nbr_tet with tetA and tetB * respectively. * * You might want to draw a picture to keep track of what's * going on. * * Vertex 0 of the new_tet sits at vertex (not face) f[0] of tet. * Vertex 1 of the new_tet sits at vertex (not face) nbr_f[0] of nbr_tet. * Vertex 2 of the new_tet sits at vertex (not face) f[3] of tet. * Vertex 3 of the new_tet sits at vertex (not face) f[2] of tet. * * Vertex 0 of tetA will be over vertex 0 of new_tet. * Vertex 1 of tetA will be at the cusp. * Vertex 2 of tetA will be over vertex 1 of new_tet. * Vertex 3 of tetA will be over vertex 2 of new_tet. * * Vertex 0 of tetB will be over vertex 1 of new_tet. * Vertex 1 of tetB will be at the cusp. * Vertex 2 of tetB will be over vertex 3 of new_tet. * Vertex 3 of tetB will be over vertex 0 of new_tet. * * Take a deep breath and set all the necessary fields . . . */ new_tet = NEW_STRUCT(Tetrahedron); tetA = NEW_STRUCT(Tetrahedron); tetB = NEW_STRUCT(Tetrahedron); initialize_tetrahedron(new_tet); initialize_tetrahedron(tetA); initialize_tetrahedron(tetB); new_tet->cusp[0] = tet->cusp[ f[0]]; new_tet->cusp[1] = nbr_tet->cusp[nbr_f[0]]; new_tet->cusp[2] = tet->cusp[ f[3]]; new_tet->cusp[3] = tet->cusp[ f[2]]; new_tet->neighbor[0] = NBR_T(1); new_tet->neighbor[1] = TET_T(1); new_tet->gluing[0] = CREATE_PERMUTATION( 0, NBR_V(1, 1), 1, NBR_V(1, 0), 2, NBR_V(1, 3), 3, NBR_V(1, 2)); new_tet->gluing[1] = CREATE_PERMUTATION( 0, TET_V(1, 0), 1, TET_V(1, 1), 2, TET_V(1, 3), 3, TET_V(1, 2)); NBR_T(1)->neighbor[NBR_V(1, 1)] = new_tet; TET_T(1)->neighbor[TET_V(1, 1)] = new_tet; NBR_T(1)->gluing[NBR_V(1, 1)] = inverse_permutation[new_tet->gluing[0]]; TET_T(1)->gluing[TET_V(1, 1)] = inverse_permutation[new_tet->gluing[1]]; new_tet->neighbor[2] = tetB; new_tet->neighbor[3] = tetA; new_tet->gluing[2] = CREATE_PERMUTATION(0, 3, 1, 0, 2, 1, 3, 2); new_tet->gluing[3] = CREATE_PERMUTATION(0, 0, 1, 2, 2, 3, 3, 1); tetA->neighbor[1] = new_tet; tetB->neighbor[1] = new_tet; tetA->gluing[1] = inverse_permutation[new_tet->gluing[3]]; tetB->gluing[1] = inverse_permutation[new_tet->gluing[2]]; tetA->neighbor[2] = TET_T(2); tetA->gluing[2] = CREATE_PERMUTATION(0, TET_V(2, 0), 1, TET_V(2, 1), 2, TET_V(2, 2), 3, TET_V(2, 3)); TET_T(2)->neighbor[TET_V(2, 2)] = tetA; TET_T(2)->gluing[TET_V(2, 2)] = inverse_permutation[tetA->gluing[2]]; tetA->neighbor[0] = NBR_T(2); tetA->gluing[0] = CREATE_PERMUTATION(0, NBR_V(2, 2), 1, NBR_V(2, 1), 2, NBR_V(2, 0), 3, NBR_V(2, 3)); NBR_T(2)->neighbor[NBR_V(2, 2)] = tetA; NBR_T(2)->gluing[NBR_V(2, 2)] = inverse_permutation[tetA->gluing[0]]; tetB->neighbor[0] = TET_T(3); tetB->gluing[0] = CREATE_PERMUTATION(0, TET_V(3, 3), 1, TET_V(3, 1), 2, TET_V(3, 2), 3, TET_V(3, 0)); TET_T(3)->neighbor[TET_V(3, 3)] = tetB; TET_T(3)->gluing[TET_V(3, 3)] = inverse_permutation[tetB->gluing[0]]; tetB->neighbor[3] = NBR_T(3); tetB->gluing[3] = CREATE_PERMUTATION(0, NBR_V(3, 0), 1, NBR_V(3, 1), 2, NBR_V(3, 2), 3, NBR_V(3, 3)); NBR_T(3)->neighbor[NBR_V(3, 3)] = tetB; NBR_T(3)->gluing[NBR_V(3, 3)] = inverse_permutation[tetB->gluing[3]]; tetA->neighbor[3] = tetB; tetB->neighbor[2] = tetA; tetA->gluing[3] = CREATE_PERMUTATION(0, 3, 1, 1, 2, 0, 3, 2); tetB->gluing[2] = inverse_permutation[tetA->gluing[3]]; for (j = 0; j < 2; j++) /* which curve */ for (i = 0; i < 2; i++) /* which sheet */ { ii = (parity[CREATE_PERMUTATION(0, f[0], 1, f[1], 2, f[2], 3, f[3])] == 0) ? i : !i; tetA->curve[j][i][1][2] = tet->curve[j][ii][f[1]][f[2]]; ii = (parity[CREATE_PERMUTATION(0, nbr_f[2], 1, nbr_f[1], 2, nbr_f[0], 3, nbr_f[3])] == 0) ? i : !i; tetA->curve[j][i][1][0] = nbr_tet->curve[j][ii][nbr_f[1]][nbr_f[2]]; tetA->curve[j][i][1][3] = - (tetA->curve[j][i][1][2] + tetA->curve[j][i][1][0]); ii = (parity[CREATE_PERMUTATION(0, f[3], 1, f[1], 2, f[2], 3, f[0])] == 0) ? i : !i; tetB->curve[j][i][1][0] = tet->curve[j][ii][f[1]][f[3]]; ii = (parity[CREATE_PERMUTATION(0, nbr_f[0], 1, nbr_f[1], 2, nbr_f[2], 3, nbr_f[3])] == 0) ? i : !i; tetB->curve[j][i][1][3] = nbr_tet->curve[j][ii][nbr_f[1]][nbr_f[3]]; tetB->curve[j][i][1][2] = - (tetB->curve[j][i][1][0] + tetB->curve[j][i][1][3]); } tetA->edge_class[edge_between_faces[2][3]] = e_class[0]; tetA->edge_class[edge_between_faces[3][0]] = e_class[1]; tetA->edge_class[edge_between_faces[0][2]] = e_class[2]; tetB->edge_class[edge_between_faces[0][2]] = e_class[0]; tetB->edge_class[edge_between_faces[2][3]] = e_class[1]; tetB->edge_class[edge_between_faces[3][0]] = e_class[3]; tetA->cusp[1] = tet->cusp[f[1]]; tetB->cusp[1] = tet->cusp[f[1]]; tetA->cusp[0] = new_tet->cusp[0]; tetA->cusp[2] = new_tet->cusp[1]; tetA->cusp[3] = new_tet->cusp[2]; tetB->cusp[0] = new_tet->cusp[1]; tetB->cusp[2] = new_tet->cusp[3]; tetB->cusp[3] = new_tet->cusp[0]; tetA->extra = NEW_STRUCT(Extra); tetB->extra = NEW_STRUCT(Extra); tetA->extra->ideal_vertex_index = 1; tetB->extra->ideal_vertex_index = 1; if (require_distinct_edges == FALSE) { tetA->extra->Dehn_filling_curve[2] = tet->extra->Dehn_filling_curve[ f[2]]; tetB->extra->Dehn_filling_curve[0] = tet->extra->Dehn_filling_curve[ f[3]]; tetA->extra->Dehn_filling_curve[0] = nbr_tet->extra->Dehn_filling_curve[nbr_f[2]]; tetB->extra->Dehn_filling_curve[3] = nbr_tet->extra->Dehn_filling_curve[nbr_f[3]]; tetA->extra->Dehn_filling_curve[3] = - (tetA->extra->Dehn_filling_curve[2] + tetA->extra->Dehn_filling_curve[0]); tetB->extra->Dehn_filling_curve[2] = - (tetB->extra->Dehn_filling_curve[0] + tetB->extra->Dehn_filling_curve[3]); } INSERT_BEFORE(new_tet, &manifold->tet_list_end); /* * To avoid screwing up linked lists of Tetrahedra * (i.e. the short list, which standard_form() traverses * in a for(;;) loop), we copy tetA and tetB onto the * storage formerly used by tet and nbr_tet. * In spirit they are new Tetrahedra, but we want * them to occupy the same physical memory as the old * Tetrahedra, so as not to screw up a higher level * function which holds a pointer to one of the old * Tetrahedra. */ tetA->prev = tet->prev; tetB->prev = nbr_tet->prev; tetA->next = tet->next; tetB->next = nbr_tet->next; my_free( tet->extra); my_free(nbr_tet->extra); *tet = *tetA; *nbr_tet = *tetB; /* * If they are glued to themselves, correct the * neighbor fields. */ for (i = 0; i < 4; i++) { if (tet->neighbor[i] == tetA) tet->neighbor[i] = tet; if (tet->neighbor[i] == tetB) tet->neighbor[i] = nbr_tet; if (nbr_tet->neighbor[i] == tetA) nbr_tet->neighbor[i] = tet; if (nbr_tet->neighbor[i] == tetB) nbr_tet->neighbor[i] = nbr_tet; } /* * Correct the neighbor fields for remaining neighbors. */ for (i = 0; i < 4; i++) { tet->neighbor[i]->neighbor[EVALUATE( tet->gluing[i],i)] = tet; nbr_tet->neighbor[i]->neighbor[EVALUATE(nbr_tet->gluing[i],i)] = nbr_tet; } my_free(tetA); my_free(tetB); manifold->num_tetrahedra++; return TRUE; } static void transfer_curves( Tetrahedron *short_list_begin, Tetrahedron *short_list_end) { Tetrahedron *tet; VertexIndex v; Cusp *cusp; int i, j; /* * Transfer the Dehn filling curves to tet->extra->Dehn_filling_curve[]. */ for (tet = short_list_begin->next; tet != short_list_end; tet = tet->next) { v = tet->extra->ideal_vertex_index; cusp = tet->cusp[v]; for (i = 0; i < 4; i++) { if (i == v) continue; tet->extra->Dehn_filling_curve[i] = 0; for (j = 0; j < 2; j++) tet->extra->Dehn_filling_curve[i] += (int)(cusp->m * (Real) tet->curve[M][j][v][i]) + (int)(cusp->l * (Real) tet->curve[L][j][v][i]); } } } static void standard_form( Triangulation *manifold, Tetrahedron *short_list_begin, Tetrahedron *short_list_end) { Tetrahedron *tet; /* * See the documentation in close_cusps() for an illustration of * the standard forms. */ for (tet = short_list_begin->next; tet != short_list_end; tet = tet->next) if (tet->cusp[tet->extra->ideal_vertex_index]->topology == torus_cusp) standard_torus_form(manifold, tet); else standard_Klein_bottle_form(manifold, tet); } static void standard_torus_form( Triangulation *manifold, Tetrahedron *tet) { int max; /* * The idea here is to modify the triangulation of the * boundary torus so that the Dehn filling curve * looks simpler. Geometrically, we are going to do Dehn * twists which realize the Euclidean algorithm, but you * needn't think in terms of Dehn twists as you read the * following code. * * The Dehn filling curve will intersect the sides of a * boundary triangle with intersection numbers a, b and c, * where a + b + c = 0. If, say, c has the greatest absolute * value, then a and b will have the same sign, and c = -(a + b). * The intersection numbers on the other triangle in the triangulation * are of course the negatives of these. * * If we do a two-to-two move across the edge with intersection * number c, then the new intersection numbers will be a, -b and * (b - a). Each time we do this we reduce the absolute value of * the largest intersection number, until we reach a state where * one of the intersection numbers is zero and the other two are * negatives of each other. The latter two must be +1 and -1, * because the Dehn filling curve is a simple closed curve. * Thus, we eventually reach a state where the intersection * numbers are {0, +1, -1}. * * The state just before this (if any) must have been {1, 1, 2}. * {1, 1, 2} is the standard form. * * So . . . the algorithm is * * if (state = {0, +1, -1}) * back up to {1, 1, 2} * else * while (state is not {1, 1, 2}) * apply a two-to-two move to reduce the absolute value * of the largest intersection number * * Technical comment: in the case where we have to back up * to {1, 1, 2}, when we seal the cusp we'll be creating an * EdgeClass of order 1 in the 3-manifold. */ max = max_abs_intersection_number(tet); if (max == 1) apply_two_to_two_to_eliminate(manifold, tet, 0); else while (max > 2) { apply_two_to_two_to_eliminate(manifold, tet, max); max = max_abs_intersection_number(tet); } } static int max_abs_intersection_number( Tetrahedron *tet) { VertexIndex v; int max; int i; v = tet->extra->ideal_vertex_index; max = 0; for (i = 0; i < 4; i++) { if (i == v) continue; if (ABS(tet->extra->Dehn_filling_curve[i]) > max) max = ABS(tet->extra->Dehn_filling_curve[i]); } return max; } static void apply_two_to_two_to_eliminate( Triangulation *manifold, Tetrahedron *tet, int target) { VertexIndex v; FaceIndex f; /* * apply_two_to_two_to_eliminate() applies a two-to-two move * to alter the boundary triangulation in such a way as to * eliminate the edge whose intersection number with the * Dehn filling curve has absolute value target. */ v = tet->extra->ideal_vertex_index; /* * Find the FaceIndex f of the face of tet corresponding to the * 2-d edge we want to eliminate. */ for (f = 0; f < 4; f++) { if (f == v) continue; if (ABS(tet->extra->Dehn_filling_curve[f]) == target) break; } if (f == 4) /* didn't find the right f */ uFatalError("apply_two_to_two_to_eliminate", "close_cusps"); (void) two_to_two(manifold, tet, f, FALSE); } static void standard_Klein_bottle_form( Triangulation *manifold, Tetrahedron *tet) { VertexIndex v; FaceIndex f; v = tet->extra->ideal_vertex_index; /* * Consider the triangle corresponding to tet in the * (2-dimensional) triangulation of the boundary Klein bottle. * The triangulation of the Klein bottle is in the standard * form iff this triangle has two sides glued to each other. */ for (f = 0; f < 4; f++) { if (f == v) continue; if (tet->neighbor[f] == tet) return; } /* * The boundary triangulation must have one of the following * two forms, where the line of @'s is the meridian. * (In fact the two forms represent the same triangulation. * I've drawn them separately to convince the reader--and * myself--that this is the only triangulation other than * than the standard one.) * * ------>>----- -----<<------ * | /| | @ /| * | / | | @ / | * | / | | @ / | * | / | | @ / | * | / | | @ / | * ^@@@@@/@@@@@^ ^@ / @^ * | / | | / @ ^ * | / | | / @ | * | / | | / @ | * | / | | / @ | * |/ | |/ @ | * ------<<----- ------<------ * * A two-to-two move across the edge disjoint from the meridian * will put the Klein bottle into standard form. */ for (f = 0; f < 4; f++) { if (f == v) continue; if (tet->extra->Dehn_filling_curve[f] == 0) { (void) two_to_two(manifold, tet, f, FALSE); break; } } } static void fold_cusps( Triangulation *manifold, Tetrahedron *short_list_begin, Tetrahedron *short_list_end) { while (short_list_begin->next != short_list_end) fold_one_cusp(manifold, short_list_begin->next); } static void fold_one_cusp( Triangulation *manifold, Tetrahedron *tet0) { Tetrahedron *tet[2], *nbr[2]; FaceIndex f[2][4], nf[2][4]; int i, j; int abs_int_num; Cusp *dead_cusp; /* * The illustrations in close_cusps() show the standard forms * for torus and Klein bottle cusps. We are going to fold * along the diagonal. Note that the absolute value of the * intersection number of the Dehn filling curve with the edge * we're folding along is 2 for a torus and 0 for a Klein bottle. * For all other edges it's 1. */ /* * f[0][0] will be the FaceIndex of the bottom face of tet[0] (the * one furthest from the ideal vertex). f[0][1] will be the face * incident to the edge we're folding along. f[0][2] and f[0][3] * will be the remaining faces. f[1][0-3] will be the corresponding * faces of tet[1], the other Tetrahedron at this cusp. */ tet[0] = tet0; f[0][0] = tet[0]->extra->ideal_vertex_index; for (f[0][1] = 0; f[0][1] < 4; f[0][1]++) { if (f[0][1] == f[0][0]) continue; abs_int_num = ABS(tet[0]->extra->Dehn_filling_curve[f[0][1]]); if (abs_int_num == 2 || abs_int_num == 0) break; } if (f[0][1] == 4) uFatalError("fold_one_cusp", "close_cusps"); f[0][2] = remaining_face[f[0][0]][f[0][1]]; f[0][3] = remaining_face[f[0][1]][f[0][0]]; tet[1] = tet[0]->neighbor[f[0][1]]; for (i = 0; i < 4; i++) f[1][i] = EVALUATE(tet[0]->gluing[f[0][1]], f[0][i]); /* * nbr[0] (resp. nbr[1]) is the Tetrahedron (with all finite vertices) * which sits underneath tet[0] (resp. tet[1]). Their FaceIndices * are nf[0][] and nf[1][], and are indexed in the natural way * relative to tet[0] and tet[1]. */ for (i = 0; i < 2; i++) { nbr[i] = tet[i]->neighbor[f[i][0]]; for (j = 0; j < 4; j++) nf[i][j] = EVALUATE(tet[i]->gluing[f[i][0]], f[i][j]); } /* * To fold the cusp, we simply identify similarly indexed * vertices of nbr[0] and nbr[1]. */ for (i = 0; i < 2; i++) { nbr[i]->neighbor[nf[i][0]] = nbr[!i]; nbr[i]->gluing[nf[i][0]] = CREATE_PERMUTATION( nf[i][0], nf[!i][0], nf[i][1], nf[!i][1], nf[i][2], nf[!i][2], nf[i][3], nf[!i][3]); } /* * Discard tet[0] and tet[1]. */ dead_cusp = tet[0]->cusp[f[0][0]]; if (dead_cusp->topology == torus_cusp) manifold->num_or_cusps--; else manifold->num_nonor_cusps--; manifold->num_cusps--; REMOVE_NODE(dead_cusp); my_free(dead_cusp); for (i = 0; i < 2; i++) { REMOVE_NODE(tet[i]); free_tetrahedron(tet[i]); } } static void replace_fake_cusps( Triangulation *manifold) { Tetrahedron *tet; int i; Cusp *cusp, *dead_cusp; /* * Set to NULL all tet->cusp pointers which point to fake Cusps. */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (i = 0; i < 4; i++) if (tet->cusp[i]->is_finite == TRUE) tet->cusp[i] = NULL; /* * Free the fake Cusps. */ for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) if (cusp->is_finite == TRUE) { dead_cusp = cusp; cusp = cusp->prev; /* so the loop will proceed correctly */ REMOVE_NODE(dead_cusp); my_free(dead_cusp); } /* * Assign new fake Cusps. */ create_fake_cusps(manifold); } static void renumber_real_cusps( Triangulation *manifold) { Cusp *cusp; int cusp_count; cusp_count = 0; for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) if (cusp->is_finite == FALSE) cusp->index = cusp_count++; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/CMakeLists.txt000644 000765 000024 00000002474 12377774107 021552 0ustar00babstaff000000 000000 # snappea kernel # Files to compile SET ( FILES Dehn_coefficients Moebius_transformations abelian_group canonize canonize_part_1 canonize_part_2 canonize_result change_peripheral_curves chern_simons choose_generators close_cusps complex core_geodesics current_curve_basis cusp_cross_sections cusp_neighborhoods cusp_shapes cusps edge_classes filling find_cusp finite_vertices fundamental_group gcd gluing_equations holonomy homology hyperbolic_structure identify_solution_type interface intersection_numbers matrix_conversion matrix_generators my_malloc o31_matrices orient peripheral_curves positioned_tet precision shortest_cusp_basis simplify_triangulation sl2c_matrices solve_equations subdivide tables tet_shapes tidy_peripheral_curves transcendentals triangulations unix_file_io update_shapes volume ) # Prepend folder name FOREACH ( SOURCE_FILE ${FILES} ) SET ( SOURCES ${SOURCES} snappea/kernel/${SOURCE_FILE}) SET ( SOURCES_C_AS_CPP ${SOURCES_C_AS_CPP} snappea/kernel/${SOURCE_FILE}) ENDFOREACH(SOURCE_FILE) # Set the variable in the parent directory SET(SOURCES ${SOURCES} PARENT_SCOPE) SET(SOURCES_C_AS_CPP ${SOURCES_C_AS_CPP} PARENT_SCOPE) # SnapPea headers should not be shipped: these are for internal use only. regina-4.96/engine/snappea/kernel/complex.c000644 000765 000024 00000010066 12377774107 020621 0ustar00babstaff000000 000000 /* * complex.c * * This file provides the standard complex arithmetic functions: * * Complex complex_minus (Complex z0, Complex z1), * complex_plus (Complex z0, Complex z1), * complex_mult (Complex z0, Complex z1), * complex_div (Complex z0, Complex z1), * complex_sqrt (Complex z), * complex_conjugate (Complex z), * complex_negate (Complex z), * complex_real_mult (double r, Complex z), * complex_exp (Complex z), * complex_log (Complex z, double approx_arg); * double complex_modulus (Complex z); * double complex_modulus_squared (Complex z); * Boolean complex_nonzero (Complex z); * Boolean complex_infinite (Complex z); */ #include "kernel.h" #include "kernel_namespace.h" Complex Zero = { 0.0, 0.0}; Complex One = { 1.0, 0.0}; Complex Two = { 2.0, 0.0}; Complex Four = { 4.0, 0.0}; Complex MinusOne = {-1.0, 0.0}; Complex I = { 0.0, 1.0}; Complex TwoPiI = { 0.0, TWO_PI}; Complex Infinity = {1e64, 0.0}; Complex complex_plus( Complex z0, Complex z1) { Complex sum; sum.real = z0.real + z1.real; sum.imag = z0.imag + z1.imag; return sum; } Complex complex_minus( Complex z0, Complex z1) { Complex diff; diff.real = z0.real - z1.real; diff.imag = z0.imag - z1.imag; return diff; } Complex complex_div( Complex z0, Complex z1) { Real mod_sq; Complex quotient; mod_sq = z1.real * z1.real + z1.imag * z1.imag; if (mod_sq == 0.0) { if (z0.real != 0.0 || z0.imag != 0.0) return Infinity; else uFatalError("complex_div", "complex"); } quotient.real = (z0.real * z1.real + z0.imag * z1.imag)/mod_sq; quotient.imag = (z0.imag * z1.real - z0.real * z1.imag)/mod_sq; return quotient; } Complex complex_mult( Complex z0, Complex z1) { Complex product; product.real = z0.real * z1.real - z0.imag * z1.imag; product.imag = z0.real * z1.imag + z0.imag * z1.real; return product; } Complex complex_sqrt( Complex z) { Real mod, arg; Complex root; mod = sqrt(complex_modulus(z)); /* no need for safe_sqrt() */ if (mod == 0.0) return Zero; arg = 0.5 * atan2(z.imag, z.real); root.real = mod * cos(arg); root.imag = mod * sin(arg); return root; } Complex complex_conjugate( Complex z) { z.imag = - z.imag; return z; } Complex complex_negate( Complex z) { z.real = - z.real; z.imag = - z.imag; return z; } Complex complex_real_mult( Real r, Complex z) { Complex multiple; multiple.real = r * z.real; multiple.imag = r * z.imag; return multiple; } Complex complex_exp( Complex z) { Real modulus; Complex result; modulus = exp(z.real); result.real = modulus * cos(z.imag); result.imag = modulus * sin(z.imag); return result; } Complex complex_log( Complex z, Real approx_arg) { Complex result; if (z.real == 0.0 && z.imag == 0.0) { uAcknowledge("log(0 + 0i) encountered"); result.real = - REAL_MAX; result.imag = approx_arg; return result; } result.real = 0.5 * log(z.real * z.real + z.imag * z.imag); result.imag = atan2(z.imag, z.real); while (result.imag - approx_arg > PI) result.imag -= TWO_PI; while (approx_arg - result.imag > PI) result.imag += TWO_PI; return result; } Real complex_modulus( Complex z) { return sqrt(z.real * z.real + z.imag * z.imag); /* no need for safe_sqrt() */ } Real complex_modulus_squared( Complex z) { return (z.real * z.real + z.imag * z.imag); } Boolean complex_nonzero( Complex z) { return (z.real != (Real)0.0 || z.imag != (Real)0.0); } Boolean complex_infinite( Complex z) { return (z.real == Infinity.real && z.imag == Infinity.imag); } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/core_geodesics.c000644 000765 000024 00000017273 12377774107 022136 0ustar00babstaff000000 000000 /* * core_geodesics.c * * This file provides the function * * void core_geodesic( Triangulation *manifold, * int cusp_index, * int *singularity_index, * Complex *core_length, * int *precision); * * which computes the core_length and singularity_index for the * Cusp of index cusp_index in Triangulation *manifold. The * singularity_index describes the nature of the cusp: * * If the Cusp is unfilled or the Dehn filling coefficients are * not integers, then * * *singularity_index is set to zero, * *core_length is undefined. * * If the Cusp is filled and the Dehn filling coefficients are * relatively prime integers (so we have a manifold locally), then * * *singularity_index is set to one, * *core_length is set to the complex length * of the central geodesic, * * If the Cusp is filled and the Dehn filling coefficients are * non relatively prime integers (so we have an orbifold locally), then * * *singularity_index is set to the index of the singular locus, * *core_length is set to the complex length of the central * geodesic in the smallest manifold cover of * a neighborhood of the singular set. * * If the precision pointer is not NULL, *precision is set to the * number of decimal places of accuracy in the computed value of * core_length. * * Klein bottle cusps are OK. Their torsion will always be zero. * * This file also provides the function * * void compute_core_geodesic( Cusp *cusp, * int *singularity_index, * Complex length[2]); * * for use within the kernel. It is similar to core_geodesic(), * only it takes a Cusp pointer as input, and outputs the complex * lengths relative to the ultimate and penultimate hyperbolic * structures, rather than reporting a precision. * * * The Algorithm. * * Say we're doing (p, q) Dehn filling on some Cusp. The (closed) core * geodesic lifts to a set of (infinite) geodesics in the universal cover. * Let L be one such (infinite) geodesic in the univeral cover, and * consider the group G of covering transformations fixing L (setwise). * G is generated by the holonomies of the meridian and longitude, * which we denote H(m) and H(l), subject to the single relation * p H(m) + q H(l) = 0. We would like to find new generators g and h * for the group such that the relation takes the form n g + 0 h = 0. * The generator g will be the purely rotational part of the group G * (n will be the order of the singular locus), and h will generate * the translational part of G. * * One approach to finding g and h would be to proceed in the general * context of finitely generated abelian groups, and apply the Euclidean * algorithm to the relation p H(m) + q H(l) = 0, changing bases until * the relation simplifies down to something of the form n g + 0 h = 0. * But rather than messing with the bookkeeping of this approach, we'll * use a more pedestrian method. * * Let (a, b; c, d) be the matrix expressing (g, h) in terms * of (H(m), H(l)): * * | g | | a b | | H(m) | * | | = | | | | * | h | | c d | | H(l) | * * Because 0 = n g = n (a H(m) + b H(l)) = na H(m) + nb H(l) is * the identity, and p H(m) + q H(l) is the only relation in the * presentation of the group, it follows that (a, b) must be * proportional to (p, q). Furthermore, since the matrix (a, b; c, d) * has determinant one, a and b must be relatively prime, so therefore * (a, b) = (p, q)/gcd(p,q). It now follows that c and d are integers * satisfying * 1 = a d - b c = d p/gcd(p,q) - c q/gcd(p,q) * <=> * d p - c q = gcd(p,q) * * We can find such integers using SnapPea's standard * euclidean_algorithm() function. */ #include "kernel.h" #include "kernel_namespace.h" #define TORSION_EPSILON 1e-5 void core_geodesic( Triangulation *manifold, int cusp_index, int *singularity_index, Complex *core_length, int *precision) { Cusp *cusp; Complex length[2]; cusp = find_cusp(manifold, cusp_index); /* * Compute the complex length relative to the ultimate * and penultimate hyperbolic structures. */ compute_core_geodesic(cusp, singularity_index, length); /* * Package up the results. */ if (*singularity_index != 0) { *core_length = length[ultimate]; if (precision != NULL) *precision = complex_decimal_places_of_accuracy( length[ultimate], length[penultimate]); } else { *core_length = Zero; if (precision != NULL) *precision = 0; } } void compute_core_geodesic( Cusp *cusp, int *singularity_index, Complex length[2]) { int i; long int positive_d, negative_c; Real pi_over_n; /* * If the Cusp is unfilled or the Dehn filling coefficients aren't * integers, then just write in some zeros (as explained at the top * of this file) and return. */ if (cusp->is_complete == TRUE || Dehn_coefficients_are_integers(cusp) == FALSE) { *singularity_index = 0; length[ultimate] = Zero; length[penultimate] = Zero; return; } /* * The euclidean_algorithm() will give the singularity index * directly (as the g.c.d.), and the coefficients lead to the * complex length (cf. the explanation at the top of this file). */ *singularity_index = euclidean_algorithm( (long int) cusp->m, (long int) cusp->l, &positive_d, &negative_c); for (i = 0; i < 2; i++) /* i = ultimate, penultimate */ { /* * length[i] = c H(m) + d H(l) * * (The holonomies are already in logarithmic form.) */ length[i] = complex_plus( complex_real_mult( (Real) (double)(- negative_c), cusp->holonomy[i][M] ), complex_real_mult( (Real) (double) positive_d, cusp->holonomy[i][L] ) ); /* * Make sure the length is positive. */ if (length[i].real < 0.0) length[i] = complex_negate(length[i]); /* * We want to normalize the torsion to the range * [-pi/n + epsilon, pi/n + epsilon], where n is * the order of the singular locus. */ pi_over_n = PI / *singularity_index; while (length[i].imag < - pi_over_n + TORSION_EPSILON) length[i].imag += 2.0 * pi_over_n; while (length[i].imag > pi_over_n + TORSION_EPSILON) length[i].imag -= 2.0 * pi_over_n; /* * In the case of a Klein bottle cusp, H(m) will be purely * rotational and H(l) will be purely translational * (cf. the documentation at the top of holonomy.c). * But the longitude used in practice is actually the * double cover of the true longitude, so we have to * divide the core_length by two to compensate. */ if (cusp->topology == Klein_cusp) length[i].real /= 2.0; } } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/covers.h000644 000765 000024 00000011156 12377774107 020461 0ustar00babstaff000000 000000 /* * covers.h * * SnapPea constructs an n-sheeted cover of a given manifold as follows. * First it creates n copies of a fundamental domain. For convenience it * uses the fundamental domain defined in choose_generators.c, which is * a union of the triangulation's tetrahedra. It assigns to each generator * (defined in choose_generators.c) a permutation of the n sheets, and * glues the sheets accordingly. The product of the permutations * surrounding an edge class must, of course, be the identity. * Algebraically this is equivalent to finding transitive representations * of the fundamental group into S(n), the symmetric group on n letters. * ("Transitive" means that the corresponding covering space is connected.) * * The algorithm for computing all connected n-sheeted covers of a * given manifold consists of two parts: * * (1) Find all transitive representations of the manifold's fundamental * group into S(n). [cf. representations.c] * * (2) For each representation, construct the corresponding cover. * [cover.c] * * This naive algorithm can, of course, be simplified. For example, * representations which are conjugate by an element of S(n) yield * equivalent covering spaces. The file representations.c describes * these optimizations. */ /* * This file (covers.h) is intended solely for inclusion in SnapPea.h. */ #include "kernel_namespace.h" /* * A covering is "regular" iff for any two lifts of a point in the base * manifold, there is a covering transformation taking one to the other. * (An alternative definition is that the cover's fundamental group * projects down to a normal subgroup of the base manifold's fundamental * group. For a proof that the two definitions are equivalent, please * see page 362 of Rolfsen's Knots and Links.) * * All cyclic coverings are regular. */ typedef int CoveringType; enum { unknown_cover, irregular_cover, regular_cover, cyclic_cover }; typedef struct RepresentationIntoSn RepresentationIntoSn; typedef struct { /* * How many face pairs does the fundamental domain * (defined in choose_generators.c) have? */ int num_generators; /* * How many sheets does the covering have? */ int num_sheets; /* * How many cusps (filled or unfilled) does the manifold have? * (For use with primitive_Dehn_image below.) */ int num_cusps; /* * The representations themselves are kept on a NULL-terminated * singly linked list. */ RepresentationIntoSn *list; } RepresentationList; struct RepresentationIntoSn { /* * The permutation corresponding to generator i takes sheet j * of the cover to sheet image[i][j]. * * Note that the size of the image array depends on both the * num_generators and the num_sheets defined in the RepresentationList. */ int **image; /* * The algorithm in construct_cover() in cover.c would like to know * the permutation assigned to each "primitive" Dehn filling curve. * If the Dehn filling coefficients are (a,b), the primitive Dehn * filling curve is defined to be (a/c, b/c), where c = gcd(a,b). * (When the Dehn filling coefficients are relative prime -- as is * always the case for a manifold -- the primitive Dehn filling curve * is just the Dehn filling curve itself, and the assigned permutation * is perforce the identity. The concept of a primitive Dehn filling * curve is useful only for orbifolds.) * * The permutation corresponding to the primitive Dehn filling curve * on cusp i takes sheet j of the cover to sheet Dehn_image[i][j]. * (For unfilled cusps, the identity permutation is given instead.) */ int **primitive_Dehn_image; /* * Is the cover defined by this representation irregular, * regular or cyclic? */ CoveringType covering_type; /* * The RepresentationList keeps RepresentationIntoSn's on * a NULL-terminated singly linked list. */ RepresentationIntoSn *next; }; /* * find_representations() takes a PermutationSubgroup parameter * specifying the subgroup of the symmetric group S(n) into which * the representations are to be found. */ typedef int PermutationSubgroup; enum { permutation_subgroup_Zn, /* finds cyclic covers only */ permutation_subgroup_Sn /* finds all n-fold covers */ /* eventually an option for dihedral covers could be added */ }; #include "end_namespace.h" regina-4.96/engine/snappea/kernel/current_curve_basis.c000644 000765 000024 00000013016 12377774107 023217 0ustar00babstaff000000 000000 /* * current_curve_basis.c * * This file provides the functions * * void current_curve_basis( Triangulation *manifold, * int cusp_index, * MatrixInt22 basis_change); * * void install_current_curve_bases( Triangulation *manifold); * * * current_curve_basis() accepts a Triangulation and a cusp index, * and computes a 2 x 2 integer matrix basis_change with the property that * * if the Cusp of index cusp_index is filled, and has * integer Dehn filling coefficients, * * the first row of basis_change is set to the current * Dehn filling coefficients (divided by their gcd), and * the second row of basis_change is set to the shortest * curve which completes a basis. * * else * * basis_change is set to the identity * * Note that for nonorientable cusps, the only possible Dehn * filling coefficients are +/- (m,0), and +/- the longitude will be the * shortest curve which completes the basis. * * install_current_curve_bases() installs the current curve basis * on each Cusp of manifold. * * 96/9/28 Modified to accept non relatively prime integer coefficients. * For example, (15, 20) is treated the same as (3,4). Thus in * the new basis the surgery coefficients will be of the form (m,0), * where m is the gcd of the original coefficients. * * 99/11/05 Added install_current_curve_bases(). */ #include "kernel.h" #include "kernel_namespace.h" #define EPSILON 1e-5 #define BIG_MODULUS 1e+5 static void current_curve_basis_on_cusp(Cusp *cusp, MatrixInt22 basis_change); void current_curve_basis( Triangulation *manifold, int cusp_index, MatrixInt22 basis_change) { current_curve_basis_on_cusp( find_cusp(manifold, cusp_index), basis_change); } static void current_curve_basis_on_cusp( Cusp *cusp, MatrixInt22 basis_change) { int m_int, l_int, the_gcd; long a, b; Complex new_shape; int multiple; int i, j; m_int = (int) cusp->m; l_int = (int) cusp->l; if (cusp->is_complete == FALSE /* cusp is filled and */ && m_int == cusp->m /* coefficients are integers */ && l_int == cusp->l) { /* * Find a and b such that am + bl = gcd(m, l). */ the_gcd = euclidean_algorithm(m_int, l_int, &a, &b); /* * Divide through by the g.c.d. */ m_int /= the_gcd; l_int /= the_gcd; /* * Set basis_change to * * m l * -b a */ basis_change[0][0] = m_int; basis_change[0][1] = l_int; basis_change[1][0] = -b; basis_change[1][1] = a; /* * Make sure the new longitude is as short as possible. * The ratio (new longitude)/(new meridian) should have a * real part in the interval (-1/2, +1/2]. */ /* * Compute the new_shape, using the tentative longitude. */ new_shape = transformed_cusp_shape( cusp->cusp_shape[initial], basis_change); /* * 96/10/1 There is a danger that for nonhyperbolic solutions * the cusp shape will be ill-defined (either very large or NaN). * However for some nonhyperbolic solutions (flat solutions * for example) it may make good sense. So we attempt to * make the longitude short iff the new_shape is defined and * not outrageously large; otherwise we're content with an * arbitrary longitude. */ if (complex_modulus(new_shape) < BIG_MODULUS) { /* * Figure out how many meridians we need to subtract * from the longitude. */ multiple = (int) floor(new_shape.real - (-0.5 + EPSILON)); /* * longitude -= multiple * meridian */ for (j = 0; j < 2; j++) basis_change[1][j] -= multiple * basis_change[0][j]; } } else { /* * Set basis_change to the identity. */ for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) basis_change[i][j] = (i == j); } } void install_current_curve_bases( Triangulation *manifold) { Cusp *cusp; MatrixInt22 *change_matrices; /* * Allocate an array to store the change of basis matrices. */ change_matrices = NEW_ARRAY(manifold->num_cusps, MatrixInt22); /* * Compute the change of basis matrices. */ for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) { if (cusp->index < 0 || cusp->index >= manifold->num_cusps) uFatalError("install_current_curve_bases", "current_curve_basis"); current_curve_basis_on_cusp(cusp, change_matrices[cusp->index]); } /* * Install the change of basis matrices. */ if (change_peripheral_curves(manifold, change_matrices) != func_OK) uFatalError("install_current_curve_bases", "current_curve_basis"); /* * Free the array used to store the change of basis matrices. */ my_free(change_matrices); } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/cusp_cross_sections.c000644 000765 000024 00000043377 12377774107 023257 0ustar00babstaff000000 000000 /* * cusp_cross_sections.c * * This file provides the high-level functions * * void allocate_cross_sections(Triangulation *manifold); * void free_cross_sections(Triangulation *manifold); * void compute_cross_sections(Triangulation *manifold); * void compute_tilts(Triangulation *manifold); * * for use within the kernel, in particular by canonize(). * * It also provides the low-level functions * * void compute_three_edge_lengths(Tetrahedron *tet, VertexIndex v, * FaceIndex f, double known_length); * void compute_tilts_for_one_tet(Tetrahedron *tet); * * for its own use, and for the use of two_to_three() and * three_to_two() in simplify_triangulation.c (so they can * maintain cusp cross sections and tilts correctly). * Further documentation of compute_three_edge_lengths() * and compute_tilts_for_one_tet() appears in the code itself. * * The cusp cross section functions, as well as canonize(), use the * concepts and terminology of * * J. Weeks, Convex hulls and isometries of cusped hyperbolic * 3-manifolds, Topology Appl. 52 (1993) 127-149. * * The Tilt Theorem (contained in the above paper) is generalized * and given a nicer proof in * * M. Sakuma and J. Weeks, The generalized tilt formula, * Geometriae Dedicata 55 (1995) 115-123. * * compute_cross_sections() and compute_tilts() set the cross_section * and tilt fields, respectively, of the Tetrahedron data structure. * * The vertex cross section at vertex v of Tetrahedron tet is a * triangle. The length of its edge incident to face f of tet is * stored as tet->cross_section->edge_length[v][f]. (The edge_length * is undefined when v == f.) * * tet->tilt[f] stores the tilt of the Tetrahedron tet relative to face f. * * By convention, * * when no cusp cross sections are in place, the cross_section field * of each Tetrahedron is set to NULL, and * * when cusp cross sections are created, the routine that creates * them must allocate the VertexCrossSections structures. * * Thus, routines which modify a triangulation (e.g. the two_to_three() * and three_to_two() moves) know that they must keep track of cusp cross * sections if and only if the cross_section fields of the Tetrahedra are * not NULL. * * allocate_cross_sections() and free_cross_sections() allocate and * free the VertexCrossSections. * * compute_cross_sections() sets the (already allocated) VertexCrossSections * to correspond to cusp cross sections of area (3/8)sqrt(3). As explained * in cusp_neighborhoods.c, such cusp cross sections will always have * nonoverlapping interiors. * * compute_tilts() applies the Tilt Theorem (see "Convex hulls...") * to compute the tilts from the VertexCrossSections. * * The standard way to use these functions is * * allocate_cross_sections(manifold); * compute_cross_sections(manifold); * compute_tilts(manifold); * *** Do stuff with the tilts, possibly including calls to *** * *** two_to_three() and three_to_two(), which update the *** * *** cross_sections and tilts correctly whenever the *** * *** cross_section pointers are not NULL. *** * free_cross_sections(manifold); */ #include "kernel.h" #include "kernel_namespace.h" #define CIRCUMRADIUS_EPSILON 1e-10 typedef struct ideal_vertex { Tetrahedron *tet; VertexIndex v; struct ideal_vertex *next; } IdealVertex; static void initialize_flags(Triangulation *manifold); static void cross_section(Triangulation *manifold, Cusp *cusp); static void find_starting_point(Triangulation *manifold, Cusp *cusp, Tetrahedron **tet0, VertexIndex *v0); static Real vertex_area(IdealVertex *ideal_vertex); static void normalize_cusp(Triangulation *manifold, Cusp *cusp, Real cusp_area); void allocate_cross_sections( Triangulation *manifold) { Tetrahedron *tet; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) { /* * Just for good measure, make sure no VertexCrossSections * are already allocated. */ if (tet->cross_section != NULL) uFatalError("allocate_cross_sections", "cusp_cross_sections"); /* * Allocate a VertexCrossSections structure. */ tet->cross_section = NEW_STRUCT(VertexCrossSections); } } void free_cross_sections( Triangulation *manifold) { Tetrahedron *tet; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) { /* * Just for good measure, make sure the VertexCrossSections * really are there. */ if (tet->cross_section == NULL) uFatalError("free_cross_sections", "cusp_cross_sections"); /* * Free the VertexCrossSections structure, and set the pointer * to NULL. */ my_free(tet->cross_section); tet->cross_section = NULL; } } void compute_cross_sections( Triangulation *manifold) { Cusp *cusp; /* * Initialize cross_section->has_been_set flags to FALSE. */ initialize_flags(manifold); /* * Compute a cross section of area (3/8)sqrt(3) for each cusp. */ for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) cross_section(manifold, cusp); } static void initialize_flags( Triangulation *manifold) { Tetrahedron *tet; VertexIndex v; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (v = 0; v < 4; v++) tet->cross_section->has_been_set[v] = FALSE; } static void cross_section( Triangulation *manifold, Cusp *cusp) { Real cusp_area; Tetrahedron *tet0, *nbr_tet; VertexIndex v0 = 0, nbr_v; FaceIndex f, nbr_f; IdealVertex *vertex_stack, *initial_vertex, *this_vertex, *nbr_vertex; Permutation gluing; /* * The plan is to compute an arbitrary cross section of the * cusp, and then normalize it to have area (3/8)sqrt(3). */ /* * The variable cusp_area will keep track of the area of the * cusp cross section. Initialize it to zero. */ cusp_area = 0.0; /* * Find an ideal vertex belonging to this cusp. */ find_starting_point(manifold, cusp, &tet0, &v0); /* * Set the edge_length of some edge of the initial vertex cross section * to some arbitrary value, say 1.0, and compute the other two * edge_lengths at the initial vertex in terms of it. * Set the has_been_set flag to TRUE. */ compute_three_edge_lengths(tet0, v0, !v0, 1.0); /* * At this point the simplest thing would be to write a * recursive function to set the edge_lengths of the remaining * vertices. However, recursive functions can cause trouble * (e.g. stack/heap collisions) if the recursion is exceptionally * deep, so I'll create my own stack explicitly. The stack will * contain vertices whose edge_lengths are set, but whose neighbors * have not yet been checked. Each ideal vertex experiences the * following operations in the following order: * * (1) edge_lengths are computed * (2) has_been_set flag is set to TRUE * (3) IdealVertex is put on stack * (4) IdealVertex comes off stack * (5) area of vertex cross section is added to cusp_area * (6) neighboring ideal vertices are checked, and * added to stack as necessary * (7) IdealVertex data structure is destroyed * * Proposition. Each ideal vertex goes onto the stack exactly once. * Proof. No ideal vertex can go onto the stack more than once, * because once its has_been_set flag is TRUE it is excluded from * further consideration. When a vertex comes off the * stack its neighbors are considered for addition to the stack, * therefore because the cusp is connected all its ideal vertices * will eventually go onto the stack. */ initial_vertex = NEW_STRUCT(IdealVertex); initial_vertex->tet = tet0; initial_vertex->v = v0; initial_vertex->next = NULL; vertex_stack = initial_vertex; while (vertex_stack != NULL) { /* * Pull an IdealVertex off the vertex_stack. */ this_vertex = vertex_stack; vertex_stack = vertex_stack->next; /* * Add the area of the vertex cross section to cusp_area. */ cusp_area += vertex_area(this_vertex); /* * Check the three neighbors of this IdealVertex. */ for (f = 0; f < 4; f++) { if (f == this_vertex->v) continue; /* * Locate this_vertex's neighbor by face f. */ gluing = this_vertex->tet->gluing[f]; nbr_tet = this_vertex->tet->neighbor[f]; nbr_v = EVALUATE(gluing, this_vertex->v); /* * If the neighbor's edge_lengths have not yet been computed, * compute them and add the neighbor to the stack. */ if (nbr_tet->cross_section->has_been_set[nbr_v] == FALSE) { /* * Find the face of nbr_tet which glues to * face f of this_vertex->tet. */ nbr_f = EVALUATE(gluing, f); /* * Set the edge_lengths of vertex nbr_v of Tetrahedron * nbr_tet, and set its has_been_set flag to TRUE. */ compute_three_edge_lengths( nbr_tet, nbr_v, nbr_f, this_vertex->tet->cross_section->edge_length[this_vertex->v][f]); /* * Add the neighbor to the stack. */ nbr_vertex = NEW_STRUCT(IdealVertex); nbr_vertex->tet = nbr_tet; nbr_vertex->v = nbr_v; nbr_vertex->next = vertex_stack; vertex_stack = nbr_vertex; } } /* * Free this IdealVertex. */ my_free(this_vertex); } /* * We have constructed a cusp cross section of area cusp_area. * To normalize it to have area (3/8)sqrt(3), we must multiply all * edge_lengths by sqrt( (3/8)sqrt(3) / cusp_area ). */ normalize_cusp(manifold, cusp, cusp_area); } static void find_starting_point( Triangulation *manifold, Cusp *cusp, Tetrahedron **tet0, VertexIndex *v0) { for (*tet0 = manifold->tet_list_begin.next; *tet0 != &manifold->tet_list_end; *tet0 = (*tet0)->next) for (*v0 = 0; *v0 < 4; (*v0)++) if ((*tet0)->cusp[*v0] == cusp) return; /* * We should never get to this point. */ uFatalError("find_starting_point", "cusp_cross_sections"); } /* * compute_three_edge_lengths() sets tet->cross_section->edge_length[v][f] * to known_length, computes the remaining two edge_lengths at vertex v * in terms of it, and sets the has_been_set flag to TRUE. */ void compute_three_edge_lengths( Tetrahedron *tet, VertexIndex v, FaceIndex f, Real known_length) { Real *this_triangle; FaceIndex left_face, right_face; /* * For convenience, note which triangle we're working with. */ this_triangle = tet->cross_section->edge_length[v]; /* * Set the given edge_length. */ this_triangle[f] = known_length; /* * Find the left and right edges of the triangle, corresponding * to the left_face and right_face of the Tetrahedron, in the * imagery of positioned_tet.h. Work relative to the right_handed * Orientation of the Tetrahedron, since that's how the TetShapes * are defined. */ left_face = remaining_face[v][f]; right_face = remaining_face[f][v]; /* * The real part of the logarithmic form of the angle between the * near and left faces gives us the log of the ratio of the lengths * of the near and left sides of this_triangle, and similarly for * the right side. */ this_triangle[left_face] = known_length * exp(tet->shape[complete]->cwl[ultimate][edge3_between_faces[f][left_face ]].log.real); this_triangle[right_face] = known_length / exp(tet->shape[complete]->cwl[ultimate][edge3_between_faces[f][right_face]].log.real); /* * Set the has_been_set flag to TRUE. */ tet->cross_section->has_been_set[v] = TRUE; } static Real vertex_area( IdealVertex *ideal_vertex) { /* * We compute the area of a triangular vertex cross section * using Heron's formula * * area = sqrt( s * (s - a) * (s - b) * (s - c) ) * * where a, b and c are the length of the triangle's sides, * and s is the semiperimeter (a + b + c)/2. */ Real *this_triangle, a, b, c, s, area; VertexIndex v; FaceIndex face_a, face_b, face_c; v = ideal_vertex->v; face_a = ! v; face_b = remaining_face[v][face_a]; face_c = remaining_face[face_a][v]; this_triangle = ideal_vertex->tet->cross_section->edge_length[v]; a = this_triangle[face_a]; b = this_triangle[face_b]; c = this_triangle[face_c]; s = 0.5 * (a + b + c); area = safe_sqrt( s * (s - a) * (s - b) * (s - c) ); return area; } static void normalize_cusp( Triangulation *manifold, Cusp *cusp, Real cusp_area) { Real factor; Tetrahedron *tet; VertexIndex v; FaceIndex f; /* * The given cusp has area cusp_area. * Multiply all the edge_lengths by sqrt( (3/8)sqrt(3) / cusp_area ) * to normalize the area to (3/8)sqrt(3). */ factor = safe_sqrt(0.375 * ROOT_3 / cusp_area); for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (v = 0; v < 4; v++) if (tet->cusp[v] == cusp) for (f = 0; f < 4; f++) if (f != v) tet->cross_section->edge_length[v][f] *= factor; } void compute_tilts( Triangulation *manifold) { Tetrahedron *tet; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) compute_tilts_for_one_tet(tet); } void compute_tilts_for_one_tet( Tetrahedron *tet) { Real factor, R[4]; int i, j; /* * Theorem 2 of "Convex hulls..." gives the tilts in terms * of the circumradii. A generalization of the theorem and * a cleaner proof appear in "Canonical cell decompositions...". * * We may compute the circumradius of a triangle in terms * of the length of any side c and its opposite angle C, * according to the formula * * R = c / (2 sin(C)) * * We must be careful in the case of flat (or almost flat) * ideal Tetrahedra. As sin(C) goes to zero, the circumradii * and the tilts go to infinity. We must take care that the * numerical values computed for the circumradii are in * proportion to the linear dimensions of the four vertex * cross sections. That way even though the numerical values * of the tilts will be very large numbers, they will have * the correct signs, and the canonization algorithm will proceed * correctly. To insure that the circumradii are computed * correctly, we use a fixed value for sin(C) (rather than reading * the sines of different angles at different vertex cross sections), * and we make sure its value exceeds some small epsilon (in * particular, we don't want it to be zero). */ /* * Compute the circumradii. */ /* * Let factor = 2 sin(C), where C is the angle at edge 0. * Make sure factor is at least CIRCUMRADIUS_EPSILON. */ factor = (Real)2.0 * sin(tet->shape[complete]->cwl[ultimate][0].log.imag); if (factor < CIRCUMRADIUS_EPSILON) factor = CIRCUMRADIUS_EPSILON; /* * Use the relationship R = c / factor (cf. above) to compute * the circumradii. */ R[0] = tet->cross_section->edge_length[0][1] / factor; R[1] = tet->cross_section->edge_length[1][0] / factor; R[2] = tet->cross_section->edge_length[2][3] / factor; R[3] = tet->cross_section->edge_length[3][2] / factor; /* * 95/9/19 JRW * Scale the circumradii according to the cusps' displacements. * As explained in cusp_neighborhoods.c, a cusp's linear * dimensions vary as the exponential of the displacement. */ for (i = 0; i < 4; i++) R[i] *= tet->cusp[i]->displacement_exp; /* * Apply the Tilt Theorem to compute the tilts in terms * of the circumradii. */ for (i = 0; i < 4; i++) { tet->tilt[i] = 0.0; for (j = 0; j < 4; j++) if (j == i) tet->tilt[i] += R[j]; else tet->tilt[i] -= R[j] * cos(tet->shape[complete]->cwl[ultimate][edge3_between_vertices[i][j]].log.imag); } } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/cusp_neighborhoods.c000644 000765 000024 00000450001 12377774107 023033 0ustar00babstaff000000 000000 /* * cusp_neighborhoods.c * * This file provides the following functions for creating and manipulating * horospherical cross sections of a manifold's cusps, and computing the * triangulation dual to the corresponding Ford complex. These functions * communicate with the UI by passing pointers to CuspNeighborhoods * data structures; but even though the UI may keep pointers to * CuspNeighborhoods, the structure's internal details are private * to this file. * * CuspNeighborhoods *initialize_cusp_neighborhoods( * Triangulation *manifold); * * void free_cusp_neighborhoods( * CuspNeighborhoods *cusp_neighborhoods); * * [Many other externally available functions are provided -- please see * SnapPea.h for details.] * * When the canonical cell decomposition dual to the Ford complex is not * a triangulation, it is arbitrarily subdivided into tetrahedra. * * Note: This file uses the fields "displacement" and "displacement_exp" * in the Cusp data structure to keep track of where the cusp cross * sections are (details appear below). Manifolds not under the care * of a CuspNeighborhoods structure should keep the "displacement" set * to 0 and the "displacement_exp" set to 1 at all times, so that * canonical cell decompositions will be computed relative to cusps * cross sections of equal volume. */ /* * Proposition 1. The area of a horospherical cusp cross section is * exactly twice the volume it contains. * * Proof. Do an integral in the upper half space model of hyperbolic * 3-space. Consider a unit square in the horosphere z == 1, and calculate * the volume lying above it as the integral of 1/z^3 dz from z = 1 to * z = infinity. QED * * Comment. This proposition relies on the hyperbolic manifold having * curvature -1. If the curvature had some other value, the proportionality * constant would be something other than 2. * * Comment. The proportionality constant has units of 1 / distance. * Normally, though, one doesn't have to think about units in hyperbolic * geometry, because one uses the canonical ones. I just wanted to make * sure that nobody is bothered by the fact that we're specifying an area * as twice a volume. * * Comment. We can measure the size of a cusp cross section by area or * by volume. The two measures are the same modulo a factor of two. * * * Proposition 2. If we choose a manifold's cusp cross sections to each * have area (3/8)sqrt(3), then their interiors cannot overlap themselves * or each other. * * Proof. By Lemma A below, we can choose a set of cusp cross sections * with nonoverlapping interiors. Advance each cusp cross section into * the fat part of the manifold, until it bumps into itself or another * cross section. Look at the horoball packing as seen from a given cusp. * Because the cusp is tangent to itself or some other cusp, there'll be * a maximally large horoball. If we draw the given cusp as the plane * z == 1 in the upper half space model, the maximal horoball (and each of * its translates) will appear as a sphere of diameter 1. The view as * seen from the given cusp therefore includes a packing of disjoint circles * of diameter 1/2. If it's a hexagonal packing the area of the cusp will * equal the area of a hexagon of outradius 1/2, which works out to be * (3/8)sqrt(3). If it's not a hexagonal packing, the cusp's area will be * even greater. In the latter case, we retract the cusp cross section * until its area is exactly (3/8)sqrt(3). QED * * Lemma A. We can choose a set of cusp cross sections with nonoverlapping * interiors. * * Comment. One expects the proof of this lemma to be completely trivial, * but I don't think it is. * * Proof #1. Lemma A follows directly from the Margulis Lemma. The * required cusp cross sections are portions of the boundary of the thin * part of the manifold. QED * * Proof #2. Start with any decomposition of the manifold into positively * oriented 3-cells. For example, we could start with the canonical cell * decomposition constructed in * * J. Weeks, Convex hulls and isometries of cusped hyperbolic * 3-manifolds, Topology Appl. 52 (1993) 127-149. * * Choose arbitrary cusp cross sections. Retract each cusp as necessary * so that its intersection with each 3-cell is "standard". (I don't want * to spend a lot of time fussing over the wording of this -- the idea is * that the cross section shouldn't be so far forward that it has * unnecessary intersections with other faces of the 3-cell.) Then further * retract each cusp cross section so that it doesn't intersect the other * cross sections incident to the same 3-call. This gives the nonoverlapping * cross sections, as required. QED * * * Definition. The "home position" of a cusp cross section is the one * at which its area is (3/8)sqrt(3) and its enclosed volume is (3/16)sqrt(3). * * By Proposition 2 above, when all the cusps are at their home positions, * their interiors are disjoint. * * The displacement field in the Cusp data structure measures how far * a cusp cross section is from its home position. The displacement is * measured towards the fat part of the manifold, so a positive displacement * means the cusp cross section is larger, and a negative displacement * means it is smaller. * * If we visualize a cusp's home position as a plane at height z == 1 in * the upper half space model, then after a displacement d > 0 it will be * at some height h < 1. Set d equal to the integral of dz/z from z = h * to z = 1 to obtain d = - log h, or h = exp(-d). It follows that a cusp's * linear dimensions vary as exp(d), while its area (and therefore its * enclosed volume) vary as exp(2d). The Cusp data structure stores the * quantity exp(d) in its displacement_exp field, to avoid excessive * recomputation. * * * Definition. The "reach" of a cusp is the distance from the cross * section's home position to the position at which it first bumps into * itself. * * Note that the reach is half the distance from the cusp to itself, * measured along the shortest homotopically nontrivial path. * Proposition 2 implies that the reach of each cusp will be nonnegative. * * Definition. As a given cusp cross section moves forward into the * fat part of the manifold, the first cusp cross section it bumps into * is called its "stopper". The displacement (measured from the home * position) at which the given cusp meets its stopper is called the * "stopping displacement". * * Comment. Unlike the reach, the stopper and the stopping displacement * depend on the current displacements of all the cusps in the triangulation. * They vary dynamically as the user moves the cusp cross sections. * * * Sometimes the user may wish to change two or more cusp displacements * in unison. The Cusp's is_tied field supports this. The displacements * of "tied" cusps always stay the same -- when one changes they all do. * The tie_group_reach keeps track of the reach of the tied cusps: * it tells the displacement at which some cusp in the group first * bumps into itself or some other cusp in the group. Note that the * tie_group_reach might be less than the stopping displacement of any * of its constituent cusps; this is because when a cusp moves forward * its (ordinary) stopper stays still, but members of its tie group * move towards it. */ #include "kernel.h" #include "canonize.h" #include /* needed for qsort() and rand() */ #include "kernel_namespace.h" /* * Report all horoballs higher than the requested cutoff_height * minus CUTOFF_HEIGHT_EPSILON. For example, if the user wants to see * all horoballs of height at least 0.25, we should report a horoball * of height 0.249999999963843. */ #define CUTOFF_HEIGHT_EPSILON 1e-6 /* * A horoball is considered to be "maximal" iff it's distance from a fixed * cusp is within INTERCUSP_EPSILON of being minimal. (The idea is that * if there are several different maximal cusps, whose distances from the * fixed cusp differ only by roundoff error, we want to consider all them * to be maximal.) */ #define INTERCUSP_EPSILON 1e-6 /* * If a given cusp does not have a maximal horoball, all other cusp cross * sections are retracted in increments of DELTA_DISPLACEMENT until it does. * The value of DELTA_DISPLACEMENT should be large enough that the algorithm * has a fair shot at the getting a maximal horoball on the first try, * but not so large that the canonization algorithm has to do a lot of * thrasing around (in particular, we don't want it to have to randomize * very often). */ #define DELTA_DISPLACEMENT 0.5 /* * If the longitudinal translation has length zero, * something has gone very, very wrong. */ #define LONGITUDE_EPSILON 1e-2 /* * contains_north_pole() uses NORTH_POLE_EPSILON to decide when a face * of a tetrahedron stands vertically over a vertex. */ #define NORTH_POLE_EPSILON 1e-6 /* * A complex number of modulus greater than KEY_INFINITY is considered * to be infinite, at least for the purpose of computing key values. */ #define KEY_INFINITY 1e+6 /* * tiling_tet_on_tree() will compare two TilingTets iff their key values * are within KEY_EPSILON of each other. KEY_EPSILON can be fairly large; * other than a loss of speed there is no harm in having the program make * some occasional unnecessary comparisons. */ #define KEY_EPSILON 1e-4 /* * Two TilingTets are considered equivalent under the Z + Z action of * the cusp translations iff their corresponding (transformed) corners * lie within CORNER_EPSILON of each other. */ #define CORNER_EPSILON 1e-6 /* * cull_duplicate_horoballs() checks whether two horoballs are equivalent * iff their radii differ by less than DUPLICATE_RADIUS_EPSILON. * We should make DUPLICATE_RADIUS_EPSILON fairly large, to be sure we * don't miss any horoballs even when their precision is low. */ #define DUPLICATE_RADIUS_EPSILON 1e-3 typedef int MinDistanceType; enum { dist_self_to_self, dist_self_to_any, dist_group_to_group, dist_group_to_any }; typedef struct { Tetrahedron *tet; Orientation h; VertexIndex v; } CuspTriangle; typedef struct TilingHoroball { CuspNbhdHoroball data; struct TilingHoroball *next; } TilingHoroball; typedef struct TilingTet { /* * Which Tetrahedron in the original manifold lifts to this TilingTet? */ Tetrahedron *underlying_tet; /* * Does it appear with the left_handed or right_handed orientation? */ Orientation orientation; /* * Where are its four corners on the boundary of upper half space? */ Complex corner[4]; /* * What is the Euclidean diameter of the horoball at each corner? */ Real horoball_height[4]; /* * If the neighboring TilingTet incident to face f has already been * found, neighbor_found[f] is set to TRUE so we won't waste time * finding it again. More importantly, we won't have to worry about * the special case of "finding" the initial TilingTets incident to * the "horoball of infinite Euclidean radius". */ Boolean neighbor_found[4]; /* * Pointer for the NULL-terminated queue. */ struct TilingTet *next; /* * Pointers for the tree. */ /* * The left child and right child pointers implement the binary tree. */ struct TilingTet *left, *right; /* * The sort key is a continuous function of the TilingTet's corners, * and is well defined under the Z + Z action of the group of * covering transformations of the cusp. */ Real key; /* * We don't want our tree handling functions to be recursive, * for fear of stack/heap collisions. So we implement them using * our own private stack, which is a NULL-terminated linked list * using the next_subtree pointer. Unlike the "left" and "right" * fields (which are maintained throughout the algorithm) the * "next_subtree" field is used only locally within a given tree * handling function. */ struct TilingTet *next_subtree; } TilingTet; typedef struct { TilingTet *begin, *end; } TilingQueue; static void initialize_cusp_displacements(CuspNeighborhoods *cusp_neighborhoods); static void compute_cusp_reaches(CuspNeighborhoods *cusp_neighborhoods); static void compute_one_reach(CuspNeighborhoods *cusp_neighborhoods, Cusp *cusp); static void compute_tie_group_reach(CuspNeighborhoods *cusp_neighborhoods); static Cusp *some_tied_cusp(CuspNeighborhoods *cusp_neighborhoods); static void compute_cusp_stoppers(CuspNeighborhoods *cusp_neighborhoods); static void compute_intercusp_distances(Triangulation *manifold); static void compute_one_intercusp_distance(EdgeClass *edge); static Real compute_min_dist(Triangulation *manifold, Cusp *cusp, MinDistanceType min_distance_type); static void initialize_cusp_ties(CuspNeighborhoods *cusp_neighborhoods); static void initialize_cusp_nbhd_positions(CuspNeighborhoods *cusp_neighborhoods); static void allocate_cusp_nbhd_positions(CuspNeighborhoods *cusp_neighborhoods); static void compute_cusp_nbhd_positions(CuspNeighborhoods *cusp_neighborhoods); static Boolean contains_meridian(Tetrahedron *tet, Orientation h, VertexIndex v); static void set_one_component(Tetrahedron *tet, Orientation h, VertexIndex v, int max_triangles); static CuspNbhdHoroballList *get_quick_horoball_list(CuspNeighborhoods *cusp_neighborhoods, Cusp *cusp); static void get_quick_edge_horoballs(Triangulation *manifold, Cusp *cusp, CuspNbhdHoroball **next_horoball); static void get_quick_face_horoballs(Triangulation *manifold, Cusp *cusp, CuspNbhdHoroball **next_horoball); static CuspNbhdHoroballList *get_full_horoball_list(CuspNeighborhoods *cusp_neighborhoods, Cusp *cusp, Real cutoff_height); static void compute_exp_min_d(Triangulation *manifold); static void compute_parallelogram_to_square(Complex meridian, Complex longitude, Real parallelogram_to_square[2][2]); static void read_initial_tetrahedra(Triangulation *manifold, Cusp *cusp, TilingQueue *tiling_queue, TilingTet **tiling_tree_root, TilingHoroball **horoball_linked_list, Real cutoff_height); static TilingTet *get_tiling_tet_from_queue(TilingQueue *tiling_queue); static void add_tiling_tet_to_queue(TilingTet *tiling_tet, TilingQueue *tiling_queue); static void add_tiling_horoball_to_list(TilingTet *tiling_tet, VertexIndex v, TilingHoroball **horoball_linked_list); static Boolean face_contains_useful_edge(TilingTet *tiling_tet, FaceIndex f, Real cutoff_height); static TilingTet *make_neighbor_tiling_tet(TilingTet *tiling_tet, FaceIndex f); static void prepare_sort_key(TilingTet *tiling_tet, Real parallelogram_to_square[2][2]); static Boolean tiling_tet_on_tree(TilingTet *tiling_tet, TilingTet *tiling_tree_root, Complex meridian, Complex longitude); static Boolean same_corners(TilingTet *tiling_tet1, TilingTet *tiling_tet2, Complex meridian, Complex longitude); static void add_tiling_tet_to_tree(TilingTet *tiling_tet, TilingTet **tiling_tree_root); static void add_horoball_if_necessary(TilingTet *tiling_tet, TilingHoroball **horoball_linked_list, Real cutoff_height); static Boolean contains_north_pole(TilingTet *tiling_tet, VertexIndex v); static void free_tiling_tet_tree(TilingTet *tiling_tree_root); static CuspNbhdHoroballList *transfer_horoballs(TilingHoroball **horoball_linked_list); static int compare_horoballs(const void *horoball0, const void *horoball1); static void cull_duplicate_horoballs(Cusp *cusp, CuspNbhdHoroballList *aHoroballList); /* * Conceptually, the CuspNeighborhoods structure stores cross sections * of a manifold's cusps, and also keeps a Triangulation dual to the * corresponding Ford complex. In the present implementation, the * information about the cross sections is stored entriely within the * copy of the triangulation (specifically, in the Cusp's displacment, * displacement_exp and reach fields, the EdgeClass's intercusp_distance * field, and the Triangulation's max_reach field). * * SnapPea.h (the only header file common to the user interface and the * computational kernel) contains the opaque typedef * * typedef struct CuspNeighborhoods CuspNeighborhoods; * * This opaque typedef allows the user interface to declare and pass * a pointer to a CuspNeighborhoods structure, without being able to * access a CuspNeighborhoods structure's fields directly. Here is * the actual definition, which is private to this file. */ struct CuspNeighborhoods { /* * We'll keep our own private copy of the Triangulation, to avoid * messing up the original one. */ Triangulation *its_triangulation; }; /* * Technical musings. * * There are different approaches to maintaining a canonical * triangulation as the cusp displacements change. * * Low-level approach. * Handle the 2-3 and 3-2 moves explicitly. Calculate which * move will be required next as the given cusp moves towards * the requested displacement. * * High-level approach. * Set the requested cusp displacement directly, and call the * standard proto_canonize() function to compute the corresponding * canonical triangulation. * * The low-level approach would be much more efficient at run time. * The overhead of setting up the cusp cross sections at the beginning, * and polishing the hyperbolic structure at the end, would be done * only once. It would also be efficient in that it tracks the convex * hull (i.e. the canonical triangulation) precisely as the cusp moves * toward the requested displacement. (At each step it finds the next * 2-3 or 3-2 move which would be required as the cusp cross section * moves continuously towards the requested displacement.) * * The drawback of the low-level approach is that it would require * a lot of low-level programming, which is time consuming, tends to * make a mess, and can be error prone. The high-level approach keeps * the code cleaner, even though it's less efficient at run time. * * For now I have implemented the high-level approach. If it turns * out that it is too slow, I can consider replacing it with the * low-level approach. An even better approach might be to make * some simple changes to speed up the high-level approach. For example, * I was concerned that for large manifolds proto_canonize()'s bottleneck * might be polishing the hyperbolic structure at the end. I modified * proto_canonize() to polish the hyperbolic structure iff the * triangulation has been changed. */ CuspNeighborhoods *initialize_cusp_neighborhoods( Triangulation *manifold) { Triangulation *simplified_manifold; CuspNeighborhoods *cusp_neighborhoods; /* * If the space isn't a manifold, return NULL. */ if (all_Dehn_coefficients_are_relatively_prime_integers(manifold) == FALSE) return NULL; /* * Get rid of "unnecessary" cusps. * If we encounter topological obstructions, return NULL. */ simplified_manifold = fill_reasonable_cusps(manifold); if (simplified_manifold == NULL) return NULL; /* * If the manifold is closed, free it and return NULL. */ if (all_cusps_are_filled(simplified_manifold) == TRUE) { free_triangulation(simplified_manifold); return NULL; } /* * Attempt to canonize the manifold. */ if (proto_canonize(simplified_manifold) == func_failed) { free_triangulation(simplified_manifold); return NULL; } /* * Our manifold has passed all its tests, * so set up a CuspNeighborhoods structure. */ cusp_neighborhoods = NEW_STRUCT(CuspNeighborhoods); /* * Install our private copy of the triangulation. */ cusp_neighborhoods->its_triangulation = simplified_manifold; simplified_manifold = NULL; /* * Most likely the displacements will be zero already, * but we set them anyhow, just to be safe. */ initialize_cusp_displacements(cusp_neighborhoods); /* * Compute all cusp reaches. */ compute_cusp_reaches(cusp_neighborhoods); /* * Find the stoppers. */ compute_cusp_stoppers(cusp_neighborhoods); /* * Initially no cusps are tied. */ initialize_cusp_ties(cusp_neighborhoods); /* * Set up an implicit coordinate system on each cusp cross section * so that we can report the position of horoballs etc. consistently, * even as the canonical triangulation changes. */ initialize_cusp_nbhd_positions(cusp_neighborhoods); /* * Record the volume so we don't have to recompute it * over and over in real time. */ cusp_neighborhoods->its_triangulation->volume = volume(cusp_neighborhoods->its_triangulation, NULL); /* * Done. */ return cusp_neighborhoods; } void free_cusp_neighborhoods( CuspNeighborhoods *cusp_neighborhoods) { if (cusp_neighborhoods != NULL) { free_triangulation(cusp_neighborhoods->its_triangulation); my_free(cusp_neighborhoods); } } static void initialize_cusp_displacements( CuspNeighborhoods *cusp_neighborhoods) { Cusp *cusp; for (cusp = cusp_neighborhoods->its_triangulation->cusp_list_begin.next; cusp != &cusp_neighborhoods->its_triangulation->cusp_list_end; cusp = cusp->next) { cusp->displacement = 0.0; cusp->displacement_exp = 1.0; } } static void compute_cusp_reaches( CuspNeighborhoods *cusp_neighborhoods) { Cusp *cusp; cusp_neighborhoods->its_triangulation->max_reach = 0.0; for (cusp = cusp_neighborhoods->its_triangulation->cusp_list_begin.next; cusp != &cusp_neighborhoods->its_triangulation->cusp_list_end; cusp = cusp->next) { compute_one_reach(cusp_neighborhoods, cusp); if (cusp->reach > cusp_neighborhoods->its_triangulation->max_reach) cusp_neighborhoods->its_triangulation->max_reach = cusp->reach; } } static void compute_one_reach( CuspNeighborhoods *cusp_neighborhoods, Cusp *cusp) { /* * The key observation is the following. Think of a horoball * packing corresponding to the cusp cross sections in their home * positions, with the given cusp lifting to the plane z == 1 in * the upper half space model. The vertical line passing through * the top of a maximally (Eucliean-)large round horoball is * guaranteed to be an edge in the canonical triangulation. * (Proof: As the horoballs expand equivariantly, the largest round * horoball(s) is(are) the first one(s) to touch the z == 1 horoball.) * So by measuring the distance between cusp cross sections along the * edges of the canonical triangulation, we can deduce the distance * from the given cusp to the largest round horoball(s). If a largest * round horoball corresponds to the given cusp, then we know the * cusp's reach and we're done. If the largest horoballs all belong * to other cusps, then we retract the other cusps a bit (i.e. give * them a negative displacement) and try again. Eventually a horoball * corresponding to the given cusp will be maximal. */ Triangulation *triangulation_copy; Cusp *cusp_copy, *other_cusp; Real dist_any, dist_self; /* * Make a copy of the triangulation, so we don't disturb the original. */ copy_triangulation(cusp_neighborhoods->its_triangulation, &triangulation_copy); cusp_copy = find_cusp(triangulation_copy, cusp->index); /* * Carry out the algorithm described above. */ while (TRUE) { /* * Compute the distances between cusp cross sections along each * edge of the (already canonical) triangulation, and store the * results in the EdgeClass's intercusp_distance field. * * Technical note: There is a small inefficiency here in that * proto_canonize() creates and discards the cusp cross sections, * and here we create and discard them again. If this turns out * to be a problem we could have proto_canonize() compute the * intercusp distances when it does the canonization, but for * now I'll put up with the inefficiency to keep the code clean. */ compute_intercusp_distances(triangulation_copy); /* * Does a maximally large round horoball belong to the given cusp? * If so, we know the reach and we're done. */ dist_self = compute_min_dist(triangulation_copy, cusp_copy, dist_self_to_self); dist_any = compute_min_dist(triangulation_copy, cusp_copy, dist_self_to_any); if (dist_self < dist_any + INTERCUSP_EPSILON) { cusp->reach = 0.5 * dist_self; break; } /* * Otherwise, retract all cross sections except the given one, * recanonize, and continue with the loop. * * Note: initialize_cusp_neighborhoods() has already checked * that the manifold is hyperbolic, so proto_canonize() should * not fail. */ for (other_cusp = triangulation_copy->cusp_list_begin.next; other_cusp != &triangulation_copy->cusp_list_end; other_cusp = other_cusp->next) if (other_cusp != cusp_copy) { other_cusp->displacement -= DELTA_DISPLACEMENT; other_cusp->displacement_exp = exp(other_cusp->displacement); } if (proto_canonize(triangulation_copy) != func_OK) uFatalError("compute_one_reach", "cusp_neighborhoods.c"); } /* * Free the copy of the triangulation. */ free_triangulation(triangulation_copy); } static void compute_tie_group_reach( CuspNeighborhoods *cusp_neighborhoods) { /* * This function is similar to compute_one_reach(), but instead of * computing the reach of a single cusp, it computes the reach of * a group of tied cusps (that is a group of cusp neighborhoods which * move forward and backward in unison). Please see compute_one_reach() * above for detailed documentation. */ Triangulation *triangulation_copy; Real dist_any, dist_self; Cusp *cusp; /* * If no cusps are tied, there is nothing to be done. */ if (some_tied_cusp(cusp_neighborhoods) == NULL) { cusp_neighborhoods->its_triangulation->tie_group_reach = 0.0; return; } /* * Make a copy of the triangulation, so we don't disturb the original. * copy_triangulation() copies the is_tied field, even though it is * in some sense private to this file. */ copy_triangulation(cusp_neighborhoods->its_triangulation, &triangulation_copy); /* * Carry out the algorithm described in compute_one_reach(). */ while (TRUE) { compute_intercusp_distances(triangulation_copy); dist_self = compute_min_dist(triangulation_copy, NULL, dist_group_to_group); dist_any = compute_min_dist(triangulation_copy, NULL, dist_group_to_any); if (dist_self < dist_any + INTERCUSP_EPSILON) { cusp_neighborhoods->its_triangulation->tie_group_reach = some_tied_cusp(cusp_neighborhoods)->displacement + 0.5 * dist_self; break; } for (cusp = triangulation_copy->cusp_list_begin.next; cusp != &triangulation_copy->cusp_list_end; cusp = cusp->next) if (cusp->is_tied == FALSE) { cusp->displacement -= DELTA_DISPLACEMENT; cusp->displacement_exp = exp(cusp->displacement); } if (proto_canonize(triangulation_copy) != func_OK) uFatalError("compute_tie_group_reach", "cusp_neighborhoods.c"); } free_triangulation(triangulation_copy); } static Cusp *some_tied_cusp( CuspNeighborhoods *cusp_neighborhoods) { Cusp *cusp; for (cusp = cusp_neighborhoods->its_triangulation->cusp_list_begin.next; cusp != &cusp_neighborhoods->its_triangulation->cusp_list_end; cusp = cusp->next) if (cusp->is_tied) return cusp; return NULL; } static void compute_cusp_stoppers( CuspNeighborhoods *cusp_neighborhoods) { /* * Think of a horoball packing corresponding to the cusp cross sections * in their current positions, with a given cusp lifting to the plane * z == 1 in the upper half space model. The vertical line passing * through the top of a maximally (Eucliean-)large round horoball is * guaranteed to be an edge in the canonical cell decomposition. * (Proof: As the horoballs expand equivariantly, the largest * round horoballs will be the first to touch the z == 1 horoball.) * * Case 1. The maximal horoball belongs to the given cusp. * * In this case, the given cusp is its own stopper, and the * stopping displacement is its reach. * * Case 2. The maximal horoball belongs to some other cusp. * * The displacement at which the given cusp meets the other cusp * may or may not be less than the given cusp's reach. * (A less-than-maximal horoball belonging to the given cusp may * overtake a formerly maximal cusp, because horoballs belonging * to the given cusp grow as the given cusp moves forward, while * other horoballs do not.) If the stopping displacement is * less than the given cusp's reach, then we've found a stopper * cusp and stopping displacement (the stopping displacement is * unique, even though the stopper cusp may not be). If the * stopping is greater than or equal to the given cusp's reach, * then the cusp is its own stopper, as in case 1. */ Cusp *cusp, *c[2]; EdgeClass *edge; int i; Real possible_stopping_displacement; /* * Initialize each stopper to be the cusp itself, and the stopping * displacement to be its reach. */ for (cusp = cusp_neighborhoods->its_triangulation->cusp_list_begin.next; cusp != &cusp_neighborhoods->its_triangulation->cusp_list_end; cusp = cusp->next) { cusp->stopper_cusp = cusp; cusp->stopping_displacement = cusp->reach; } /* * Now look at each edge of the canonical triangulation, to see * whether some other cusp cross section is closer. * * cusp_neighborhoods->its_triangulation is always the canonical * triangulation (or an arbitrary subdivision of the canonical * cell decomposition). */ compute_intercusp_distances(cusp_neighborhoods->its_triangulation); for (edge = cusp_neighborhoods->its_triangulation->edge_list_begin.next; edge != &cusp_neighborhoods->its_triangulation->edge_list_end; edge = edge->next) { c[0] = edge->incident_tet->cusp[ one_vertex_at_edge[edge->incident_edge_index]]; c[1] = edge->incident_tet->cusp[other_vertex_at_edge[edge->incident_edge_index]]; for (i = 0; i < 2; i++) { possible_stopping_displacement = c[i]->displacement + edge->intercusp_distance; if (possible_stopping_displacement < c[i]->stopping_displacement) { c[i]->stopping_displacement = possible_stopping_displacement; c[i]->stopper_cusp = c[!i]; } } } } static void compute_intercusp_distances( Triangulation *manifold) { /* * In the present context we may assume the triangulation is * canonical (although all we really need to know is that it * has a geometric_solution). */ EdgeClass *edge; /* * Set up the cusp cross sections. */ allocate_cross_sections(manifold); compute_cross_sections(manifold); /* * Compute the intercusp_distances. */ for (edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) compute_one_intercusp_distance(edge); /* * Release the cusp cross sections. */ free_cross_sections(manifold); } static void compute_one_intercusp_distance( EdgeClass *edge) { int i, j; Tetrahedron *tet; EdgeIndex e; VertexIndex v[2]; FaceIndex f[2]; Real length[2][2], product; /* * Find an arbitrary Tetrahedron incident to the given EdgeClass. */ tet = edge->incident_tet; e = edge->incident_edge_index; /* * Note which vertices and faces are incident to the EdgeClass. */ v[0] = one_vertex_at_edge[e]; v[1] = other_vertex_at_edge[e]; f[0] = one_face_at_edge[e]; f[1] = other_face_at_edge[e]; /* * The vertex cross section at each vertex v[i] is a triangle. * Note the lengths of the triangle's edges incident to the EdgeClass. */ for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) length[i][j] = tet->cusp[v[i]]->displacement_exp * tet->cross_section->edge_length[v[i]][f[j]]; /* * Our task is to compute the distance between the vertex cross sections * as a function of the length[][]'s. Fortunately this is easier than * you might except. I recommend you make sketches for yourself as * you read through the following. (It's much simpler in pictures * than it is in words.) * * Proposition. There is a unique common perpendicular to a pair of * opposite edges of an ideal tetrahedron. * * Proof. Consider the line segment which minimizes the distance * between the two opposite edges. If it weren't perpendicular to * each edge, then a shorter line segement could be found. QED * * Definition. The "midpoint" of an edge of an ideal tetrahedron is * the point where the edge intersects the unique common perpendicular * to the opposite edge. * * Proposition. A half turn about the aforementioned unique common * perpendicular is a symmetry of the ideal tetrahedron. * * Proof. It preserves (setwise) a pair of opposite edges. Therefore * it preserves (setwise) the tetrahedron's four ideal vertices, and * therefore the whole tetrahedron. QED * * Proposition. Consider a vertex cross section which passes through * the midpoint of an edge. The two sides of the vertex cross section * which are incident to the given edge of the tetrahedron have lengths * which are reciprocals of one another. * * Proof. Position the tetrahedron in the upper half space model so * that the given edge is vertical and its midpoint is at height one. * * Let P1 be the unique plane which contains the aforementioned unique * common perpendicular and also contains the edge itself. * * Let P2 be the unique plane which contains the aforementioned unique * common perpendicular and is orthogonal to the edge itself. * * Let S be the symmetry defined by a reflection in P1 followed by a * reflection in P2. * * S is equivalent to a half turn about the unique common perpendicular * (proof: P1 and P2 are orthogonal to each other, and both contain * the unique common perpendicular). Therefore S is a symmetry of the * ideal tetrahedron, by the preceding proposition. * * Let L1 and L2 be the lengths of the two sides of the vertex cross * section which are incident to the given edge. Because the vertex * cross section is at height one in the upper half space model, * L1 and L2 also represent the Euclidean lengths of two sides of the * triangle obtained by projecting the ideal tetrahedron onto the * plane z == 0 in the upper half space model. Reflection in the * plane P1 does not change the lengths of those two sides of the * triangle, while reflection in the plane P2 (which, in Euclidean * terms, is inversion in a hemisphere of radius one) sends each * length to its inverse. Since the composition S of the two * reflections preserves the triangle, it follows that L1 and L2 * must be inverses of one another. QED * * If a vertex cross section passes through the midpoint of an edge, * then the product of the lengths L1 and L2 (using the notation of * the preceding proof) is L1 L2 = 1. Now consider a vertex cross * section which is a distance d away from the midpoint (towards * the fat part of the manifold if d is positive, towards the cusp * if d is negative). According to the documentation at the top of * this file, a cusp cross section's linear dimensions vary as exp(d), * so the lengths of the corresponding sides of the new vertex cross * section will be exp(d)L1 and exp(d)L2. Their product is * exp(d)L1 exp(d)L2 = exp(2d) L1 L2 = exp(2d). * * If the lengths of the sides of the vertex cross section at the * other end of the given edge are exp(d')L1 and exp(d')L2, then * their product is exp(2d'). The product of all four lengths is * * exp(d)L1 exp(d)L2 exp(d')L1 exp(d')L2 = exp(2(d + d')). * * This is exactly what we need to know: d + d' is the negative * of the intercusp distance. (Note that the midpoint has dropped * out of the picture!) */ product = 1.0; for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) product *= length[i][j]; edge->intercusp_distance = -0.5 * log(product); } static Real compute_min_dist( Triangulation *manifold, Cusp *cusp, /* ignored for tie group distances */ MinDistanceType min_distance_type) { /* * This function assumes the intercusp_distances * have already been computed. */ Real min_dist; EdgeClass *edge; Cusp *cusp1, *cusp2; min_dist = REAL_MAX; for (edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) { cusp1 = edge->incident_tet->cusp[ one_vertex_at_edge[edge->incident_edge_index]]; cusp2 = edge->incident_tet->cusp[other_vertex_at_edge[edge->incident_edge_index]]; if (edge->intercusp_distance < min_dist) switch (min_distance_type) { case dist_self_to_self: if (cusp == cusp1 && cusp == cusp2) min_dist = edge->intercusp_distance; break; case dist_self_to_any: if (cusp == cusp1 || cusp == cusp2) min_dist = edge->intercusp_distance; break; case dist_group_to_group: if (cusp1->is_tied && cusp2->is_tied) min_dist = edge->intercusp_distance; break; case dist_group_to_any: if (cusp1->is_tied || cusp2->is_tied) min_dist = edge->intercusp_distance; break; } } return min_dist; } int get_num_cusp_neighborhoods( CuspNeighborhoods *cusp_neighborhoods) { if (cusp_neighborhoods == NULL) return 0; else return get_num_cusps(cusp_neighborhoods->its_triangulation); } CuspTopology get_cusp_neighborhood_topology( CuspNeighborhoods *cusp_neighborhoods, int cusp_index) { return find_cusp(cusp_neighborhoods->its_triangulation, cusp_index)->topology; } Real get_cusp_neighborhood_displacement( CuspNeighborhoods *cusp_neighborhoods, int cusp_index) { return find_cusp(cusp_neighborhoods->its_triangulation, cusp_index)->displacement; } Boolean get_cusp_neighborhood_tie( CuspNeighborhoods *cusp_neighborhoods, int cusp_index) { return find_cusp(cusp_neighborhoods->its_triangulation, cusp_index)->is_tied; } Real get_cusp_neighborhood_cusp_volume( CuspNeighborhoods *cusp_neighborhoods, int cusp_index) { /* * As explained in the documentation at the top of this file, * the volume will be the volume enclosed by the cusp in its * home position, multiplied by exp(2 * displacement). */ return 0.1875 * ROOT_3 * exp(2.0 * find_cusp(cusp_neighborhoods->its_triangulation, cusp_index)->displacement); } Real get_cusp_neighborhood_manifold_volume( CuspNeighborhoods *cusp_neighborhoods) { return cusp_neighborhoods->its_triangulation->volume; } Triangulation *get_cusp_neighborhood_manifold( CuspNeighborhoods *cusp_neighborhoods) { Triangulation *manifold_copy; Cusp *cusp; /* * Make a copy of its_triangulation. */ copy_triangulation(cusp_neighborhoods->its_triangulation, &manifold_copy); /* * Reset the cusp displacements to zero, so if a canonical triangulation * is needed later it will be computed relative to cusp cross sections * of equal volume. */ for (cusp = manifold_copy->cusp_list_begin.next; cusp != &manifold_copy->cusp_list_end; cusp = cusp->next) { cusp->displacement = 0.0; cusp->displacement_exp = 1.0; } return manifold_copy; } Real get_cusp_neighborhood_reach( CuspNeighborhoods *cusp_neighborhoods, int cusp_index) { return find_cusp(cusp_neighborhoods->its_triangulation, cusp_index)->reach; } Real get_cusp_neighborhood_max_reach( CuspNeighborhoods *cusp_neighborhoods) { return cusp_neighborhoods->its_triangulation->max_reach; } Real get_cusp_neighborhood_stopping_displacement( CuspNeighborhoods *cusp_neighborhoods, int cusp_index) { return find_cusp(cusp_neighborhoods->its_triangulation, cusp_index)->stopping_displacement; } int get_cusp_neighborhood_stopper_cusp_index( CuspNeighborhoods *cusp_neighborhoods, int cusp_index) { return find_cusp(cusp_neighborhoods->its_triangulation, cusp_index)->stopper_cusp->index; } void set_cusp_neighborhood_displacement( CuspNeighborhoods *cusp_neighborhoods, int cusp_index, Real new_displacement) { Cusp *cusp, *other_cusp; /* * Get a pointer to the cusp whose displacement is being changed. */ cusp = find_cusp(cusp_neighborhoods->its_triangulation, cusp_index); /* * Clip the displacement to the feasible range. */ /* MC 2013-06-17 if (new_displacement < 0.0) new_displacement = 0.0; */ if (cusp->is_tied == FALSE) { /* * The stopping_displacement has already been set to be less than or * equal to the reach, so by clipping to the stopping_displacement * we know the cusp neighborhood won't overlap itself or any * other cusp neighborhood. */ if (new_displacement > cusp->stopping_displacement) new_displacement = cusp->stopping_displacement; } else /* cusp->is_tied == TRUE */ { /* * Make sure the new_displacement doesn't exceed the tie_group_reach. * Other cusps in the tie group will be coming at us as we move * toward them, so collisions might not be detected by the * stopping_displacement alone. (The latter assumes the other * cusp is stationary.) */ if (new_displacement > cusp_neighborhoods->its_triangulation->tie_group_reach) new_displacement = cusp_neighborhoods->its_triangulation->tie_group_reach; /* * Don't overlap untied stoppers either. */ for (other_cusp = cusp_neighborhoods->its_triangulation->cusp_list_begin.next; other_cusp != &cusp_neighborhoods->its_triangulation->cusp_list_end; other_cusp = other_cusp->next) if (other_cusp->is_tied && new_displacement > other_cusp->stopping_displacement) new_displacement = other_cusp->stopping_displacement; } /* * Set the new displacement. */ if (cusp->is_tied == FALSE) { cusp->displacement = new_displacement; cusp->displacement_exp = exp(new_displacement); } else /* cusp->is_tied == TRUE */ { for (other_cusp = cusp_neighborhoods->its_triangulation->cusp_list_begin.next; other_cusp != &cusp_neighborhoods->its_triangulation->cusp_list_end; other_cusp = other_cusp->next) if (other_cusp->is_tied) { other_cusp->displacement = new_displacement; other_cusp->displacement_exp = exp(new_displacement); } } /* * Compute the canonical cell decomposition * relative to the new displacement. */ if (proto_canonize(cusp_neighborhoods->its_triangulation) != func_OK) uFatalError("set_cusp_neighborhood_displacement", "cusp_neighborhoods"); /* * The cusp reaches won't have changed, but the stoppers might have. */ compute_cusp_stoppers(cusp_neighborhoods); } void set_cusp_neighborhood_tie( CuspNeighborhoods *cusp_neighborhoods, int cusp_index, Boolean new_tie) { Cusp *cusp, *other_cusp; Real min_displacement; /* * Get a pointer to the cusp which is being tied or untied. */ cusp = find_cusp(cusp_neighborhoods->its_triangulation, cusp_index); /* * Tie or untie the cusp. */ cusp->is_tied = new_tie; /* * If the cusp is being tied, bring it and its mates into line. */ if (cusp->is_tied == TRUE) { /* * Find the minimum displacement for a tied cusp . . . */ min_displacement = REAL_MAX; for (other_cusp = cusp_neighborhoods->its_triangulation->cusp_list_begin.next; other_cusp != &cusp_neighborhoods->its_triangulation->cusp_list_end; other_cusp = other_cusp->next) if (other_cusp->is_tied && other_cusp->displacement < min_displacement) min_displacement = other_cusp->displacement; /* * . . . and set all tied cusps to that minimum value. */ for (other_cusp = cusp_neighborhoods->its_triangulation->cusp_list_begin.next; other_cusp != &cusp_neighborhoods->its_triangulation->cusp_list_end; other_cusp = other_cusp->next) if (other_cusp->is_tied) { other_cusp->displacement = min_displacement; other_cusp->displacement_exp = exp(min_displacement); } /* * Compute the canonical cell decomposition * relative to the minimum displacement. */ if (proto_canonize(cusp_neighborhoods->its_triangulation) != func_OK) uFatalError("set_cusp_neighborhood_tie", "cusp_neighborhoods"); /* * The cusp reaches won't have changed, * but the stoppers might have. */ compute_cusp_stoppers(cusp_neighborhoods); } /* * How far can the group of tied cusps go before bumping into itself? */ compute_tie_group_reach(cusp_neighborhoods); } static void initialize_cusp_ties( CuspNeighborhoods *cusp_neighborhoods) { Cusp *cusp; /* * Initially no cusps are tied . . . */ for (cusp = cusp_neighborhoods->its_triangulation->cusp_list_begin.next; cusp != &cusp_neighborhoods->its_triangulation->cusp_list_end; cusp = cusp->next) cusp->is_tied = FALSE; /* * . . . and the tie_group_reach is undefined. */ cusp_neighborhoods->its_triangulation->tie_group_reach = 0.0; } static void initialize_cusp_nbhd_positions( CuspNeighborhoods *cusp_neighborhoods) { /* * Install VertexCrossSections so that we know the size of each * vertex cross section in the cusp's home position. */ allocate_cross_sections(cusp_neighborhoods->its_triangulation); compute_cross_sections(cusp_neighborhoods->its_triangulation); /* * Allocate storage for the CuspNbhdPositions . . . */ allocate_cusp_nbhd_positions(cusp_neighborhoods); /* * . . . and then compute them. */ compute_cusp_nbhd_positions(cusp_neighborhoods); /* * Free the VertexCrossSections now that we're done with them. * (proto_canonize() will of course need them again, but it likes * to allocate them for itself -- this keeps its interaction with * the rest of the kernel cleaner.) */ free_cross_sections(cusp_neighborhoods->its_triangulation); } static void allocate_cusp_nbhd_positions( CuspNeighborhoods *cusp_neighborhoods) { Tetrahedron *tet; for (tet = cusp_neighborhoods->its_triangulation->tet_list_begin.next; tet != &cusp_neighborhoods->its_triangulation->tet_list_end; tet = tet->next) { /* * Just for good measure, make sure no CuspNbhdPositions * are already allocated. */ if (tet->cusp_nbhd_position != NULL) uFatalError("allocate_cusp_nbhd_positions", "cusp_neighborhoods"); /* * Allocate a CuspNbhdPosition structure. */ tet->cusp_nbhd_position = NEW_STRUCT(CuspNbhdPosition); } } static void compute_cusp_nbhd_positions( CuspNeighborhoods *cusp_neighborhoods) { Tetrahedron *tet; Orientation h; VertexIndex v; int max_triangles; Cusp *cusp; PeripheralCurve c; Complex (*x)[4][4], *translation; Boolean (*in_use)[4]; FaceIndex f, f0, f1, f2; int strands1, strands2, flow; Real length; Complex factor; /* * Initialize all the tet->in_use[][] fields to FALSE, * and all tet->x[][][] to Zero. */ for (tet = cusp_neighborhoods->its_triangulation->tet_list_begin.next; tet != &cusp_neighborhoods->its_triangulation->tet_list_end; tet = tet->next) for (h = 0; h < 2; h++) /* h = right_handed, left_handed */ for (v = 0; v < 4; v++) { for (f = 0; f < 4; f++) tet->cusp_nbhd_position->x[h][v][f] = Zero; tet->cusp_nbhd_position->in_use[h][v] = FALSE; } /* * For each vertex cross section which has not yet been set, set the * positions of its three vertices, and then recursively set the * positions of neighboring vertex cross sections. The positions * are relative to each cusp cross section's home position. * (Recall that initialize_cusp_nbhd_positions() has already called * compute_cross_sections() for us.) For torus cusps, do only the * sheet of the double cover which contains the peripheral curves * (this will be the right_handed sheet if the manifold is orientable). */ max_triangles = 2 * 4 * cusp_neighborhoods->its_triangulation->num_tetrahedra; for (tet = cusp_neighborhoods->its_triangulation->tet_list_begin.next; tet != &cusp_neighborhoods->its_triangulation->tet_list_end; tet = tet->next) for (v = 0; v < 4; v++) if (tet->cusp_nbhd_position->in_use[right_handed][v] == FALSE && tet->cusp_nbhd_position->in_use[ left_handed][v] == FALSE) { /* * Use the sheet which contains the peripheral curves. * If neither does, do nothing for now. They'll show * up eventually. */ for (h = 0; h < 2; h++) /* h = right_handed, left_handed */ if (contains_meridian(tet, h, v) == TRUE) { set_one_component(tet, h, v, max_triangles); break; } } /* * Compute the meridional and longitudinal translation on each * cusp cross section. For Klein bottle cusps, the longitude * will actually be that of the double cover. The translations * are stored in the Cusp data structure as translation[M] and * translation[L]. */ /* * The Algorithm * * The calls to set_one_component() have assigned coordinates to all * the triangles in the induced triangulation of the cusp cross section. * The problem is that these coordinates are well defined only up * to translations in the covering transformation group (or the * orientation preserving subgroup, in the case of a Klein bottle cusp). * So we want an algorithm which uses only the local coordinates within * each triangle, without requiring global consistency. * * Imagine following a peripheral curve around the cusp cross section, * and look at the sides of the triangles it passes through. As we * go along, we can keep track of the coordinates of the left and * right hand edges. When we "veer left" the left hand endpoint stays * constant, while the right hand endpoint moves forward, and vice * versa when we "veer right". By adding up all the displacements to * each endpoint, by the time we get back to our starting point we will * have computed the total translation along the curve. Actually, * it suffices to compute the total displacement for only one endpoint * (left or right) since both will give the same answer. * * Finally, note that it doesn't matter in what order we sum the * displacements. We can just iterate through all tetrahedra in the * triangulation without explicitly tracing curves. */ /* * Initialize all translations to (0.0, 0.0), and then . . . */ for (cusp = cusp_neighborhoods->its_triangulation->cusp_list_begin.next; cusp != &cusp_neighborhoods->its_triangulation->cusp_list_end; cusp = cusp->next) for (c = 0; c < 2; c++) cusp->translation[c] = Zero; /* * . . . add in the contribution of each piece of each curve. */ for (tet = cusp_neighborhoods->its_triangulation->tet_list_begin.next; tet != &cusp_neighborhoods->its_triangulation->tet_list_end; tet = tet->next) { x = tet->cusp_nbhd_position->x; in_use = tet->cusp_nbhd_position->in_use; for (v = 0; v < 4; v++) { cusp = tet->cusp[v]; for (c = 0; c < 2; c++) { translation = &cusp->translation[c]; for (f0 = 0; f0 < 4; f0++) { if (f0 == v) continue; /* * Relative to the right_handed Orientation, the faces * f0, f1 and f2 are arranged around the ideal vertex v * like this * * /\ * f1 / \ f0 * /____\ * f2 * * The triangles corners inherit the indices of the * opposite sides. */ f1 = remaining_face[f0][v]; f2 = remaining_face[v][f0]; for (h = 0; h < 2; h++) /* h = right_handed, left_handed */ { if (in_use[h][v] == FALSE) continue; strands1 = tet->curve[c][h][v][f1]; strands2 = tet->curve[c][h][v][f2]; flow = FLOW(strands2, strands1); /* * We're interested only in displacements of the * left hand endpoint (cf. above), which occur when * the flow is negative (if h == right_handed) or * the flow is positive (if h == left_handed). */ if ((h == right_handed) ? (flow < 0) : (flow > 0)) *translation = complex_plus( *translation, complex_real_mult( flow, complex_minus(x[h][v][f2], x[h][v][f1]))); } } } } } /* * Rotate the coordinates so that the longitudes point in the * direction of the positive x-axis. */ /* * Find the rotation needed for each cusp, * and use it to rotate the meridian and longitude. */ for (cusp = cusp_neighborhoods->its_triangulation->cusp_list_begin.next; cusp != &cusp_neighborhoods->its_triangulation->cusp_list_end; cusp = cusp->next) { cusp->scratch = cusp->translation[L]; length = complex_modulus(cusp->scratch); if (length < LONGITUDE_EPSILON) uFatalError("compute_cusp_nbhd_positions", "cusp_neighborhoods"); cusp->scratch = complex_real_mult(1.0/length, cusp->scratch); cusp->scratch = complex_div(One, cusp->scratch); cusp->translation[M] = complex_mult(cusp->scratch, cusp->translation[M]); cusp->translation[L] = complex_mult(cusp->scratch, cusp->translation[L]); cusp->translation[L].imag = 0.0; /* kill the roundoff error */ } /* * Use the same rotation (stored in cusp->scratch) to rotate * the coordinates in the triangulation of the cusp. */ for (tet = cusp_neighborhoods->its_triangulation->tet_list_begin.next; tet != &cusp_neighborhoods->its_triangulation->tet_list_end; tet = tet->next) { x = tet->cusp_nbhd_position->x; in_use = tet->cusp_nbhd_position->in_use; for (h = 0; h < 2; h++) /* h = right_handed, left_handed */ for (v = 0; v < 4; v++) { if (in_use[h][v] == FALSE) continue; factor = tet->cusp[v]->scratch; for (f = 0; f < 4; f++) { if (f == v) continue; x[h][v][f] = complex_mult(factor, x[h][v][f]); } } } } static Boolean contains_meridian( Tetrahedron *tet, Orientation h, VertexIndex v) { /* * It suffices to check any two sides, because the meridian * can't possibly intersect only one side of a triangle. * (These are signed intersection numbers.) */ VertexIndex w0, w1; w0 = ! v; w1 = remaining_face[v][w0]; return (tet->curve[M][h][v][w0] != 0 || tet->curve[M][h][v][w1] != 0); } static void set_one_component( Tetrahedron *tet, Orientation h, VertexIndex v, int max_triangles) { /* * FaceIndices are the natural way to index the corners * of a vertex cross section. * * The VertexIndex v tells which vertex cross section we're at. * The vertex cross section is (a triangular component of) the * intersection of a cusp cross section with the ideal tetrahedron. * Each side of the triangle is the intersection of the cusp cross * section with some face of the ideal tetrahedron, so FaceIndices * may naturally be used to index them. Each corner of the triangle * then inherits the FaceIndex of the opposite side. */ FaceIndex f[3], ff, nbr_f[3]; int i; CuspTriangle *queue, tri, nbr; int queue_begin, queue_end; Permutation gluing; CuspNbhdPosition *our_data, *nbr_data; /* * Find the three FaceIndices for the corners of the triangle. * (f == v is excluded.) */ for ( i = 0, ff = 0; i < 3; i++, ff++) { if (ff == v) ff++; f[i] = ff; } /* * Let the corner f[0] be at the origin. */ tet->cusp_nbhd_position->x[h][v][f[0]] = Zero; /* * Let the corner f[1] be on the positive x-axis. */ tet->cusp_nbhd_position->x[h][v][f[1]].real = tet->cross_section->edge_length[v][f[2]]; tet->cusp_nbhd_position->x[h][v][f[1]].imag = 0.0; /* * Use the TetShape to find the position of corner f[2]. */ cn_find_third_corner(tet, h, v, f[0], f[1], f[2]); /* * Mark this triangle as being in_use. */ tet->cusp_nbhd_position->in_use[h][v] = TRUE; /* * We'll now "recursively" set the remaining triangles of this * cusp cross section. We'll keep a queue of the triangles whose * positions have been set, but whose neighbors have not yet * been examined. */ queue = NEW_ARRAY(max_triangles, CuspTriangle); queue[0].tet = tet; queue[0].h = h; queue[0].v = v; queue_begin = 0; queue_end = 0; while (queue_begin <= queue_end) { /* * Pull a CuspTriangle off the queue. */ tri = queue[queue_begin++]; /* * Consider each of its three neighbors. */ for (ff = 0; ff < 4; ff++) { if (ff == tri.v) continue; gluing = tri.tet->gluing[ff]; nbr.tet = tri.tet->neighbor[ff]; nbr.h = (parity[gluing] == orientation_preserving) ? tri.h : ! tri.h; nbr.v = EVALUATE(gluing, tri.v); our_data = tri.tet->cusp_nbhd_position; nbr_data = nbr.tet->cusp_nbhd_position; /* * If the neighbor hasn't been set . . . */ if (nbr_data->in_use[nbr.h][nbr.v] == FALSE) { /* * . . . set it . . . */ f[0] = remaining_face[tri.v][ff]; f[1] = remaining_face[ff][tri.v]; f[2] = ff; for (i = 0; i < 3; i++) nbr_f[i] = EVALUATE(gluing, f[i]); for (i = 0; i < 2; i++) nbr_data->x[nbr.h][nbr.v][nbr_f[i]] = our_data->x[tri.h][tri.v][f[i]]; cn_find_third_corner(nbr.tet, nbr.h, nbr.v, nbr_f[0], nbr_f[1], nbr_f[2]); nbr_data->in_use[nbr.h][nbr.v] = TRUE; /* * . . . and put it on the queue. */ queue[++queue_end] = nbr; } } } /* * An "unnecessary" error check. */ if (queue_begin > max_triangles) uFatalError("set_one_component", "cusp_neighborhoods"); /* * Free the queue. */ my_free(queue); } void cn_find_third_corner( Tetrahedron *tet, /* which tetrahedron */ Orientation h, /* right_handed or left_handed sheet */ VertexIndex v, /* which ideal vertex */ FaceIndex f0, /* known corner */ FaceIndex f1, /* known corner */ FaceIndex f2) /* corner to be computed */ { /* * We want to position the Tetrahedron so that the following * two conditions hold. * * (1) The corners f0, f1 and f2 are arranged counterclockwise * around the triangle's perimeter. * * f2 * / \ * / \ * f0------f1 * * (2) The cusp cross section is seen with its preferred orientation. * (Cf. the discussion in the second paragraph of section (2) in * the documentation at the top of the file peripheral_curves.c.) * If this is the right handed sheet (h == right_handed), * the Tetrahedron should appear right handed. * (Cf. the definition of Orientation in kernel_typedefs.h.) * If this is the left handed sheet (h == left_handed), the * Tetrahedron should appear left handed (the left_handed sheet has * the opposite orientation of the Tetrahedron, so if this is the * left handed sheet and the Tetrahedron is viewed in a left handed * position, the sheet will be appear right handed -- got that?). * * Of course these two conditions may not be compatible. * If we position the corners as in (1) and then find that (2) doesn't * hold (or vice versa), then we must swap the indices f0 and f1. * * Note: We could force the conditions to hold by making our * recursive calls carefully and consistently, but fixing the * ordering of f0 and f1 as needed is simpler and more robust. */ Orientation tet_orientation; FaceIndex temp; Complex s, t, z; /* * Position the tetrahedron as in Condition (1) above. * If the tetrahedron appears in its right_handed Orientation, * then remaining_face[f0][f1] == f2, according to the definition of * remaining_face[][] in tables.c. If the tetrahedron appears in * its left_handed Orientation, then remaining_face[f0][f1] == v. */ tet_orientation = (remaining_face[f0][f1] == f2) ? right_handed : left_handed; /* * Does the vertex cross section appear with its preferred orientation, * as discussed in Condition (2) above? If not, fix it. */ if (h != tet_orientation) { temp = f0; f0 = f1; f1 = temp; tet_orientation = ! tet_orientation; } /* * Let s be the vector from f0 to f1, * t be the vector from f0 to f2, * z be the complex edge angle v/u. */ s = complex_minus( tet->cusp_nbhd_position->x[h][v][f1], tet->cusp_nbhd_position->x[h][v][f0]); /* * TetShapes are always stored relative to the right_handed Orientation. * If we're viewing the tetrahedron relative to the left_handed * Orientation, we need to use the conjugate-inverse instead. */ z = tet->shape[complete]->cwl[ultimate][edge3_between_vertices[v][f0]].rect; if (tet_orientation == left_handed) z = complex_conjugate(complex_div(One, z)); t = complex_mult(z, s); tet->cusp_nbhd_position->x[h][v][f2] = complex_plus(tet->cusp_nbhd_position->x[h][v][f0], t); } void get_cusp_neighborhood_translations( CuspNeighborhoods *cusp_neighborhoods, int cusp_index, Complex *meridian, Complex *longitude) { Cusp *cusp; cusp = find_cusp(cusp_neighborhoods->its_triangulation, cusp_index); *meridian = complex_real_mult(cusp->displacement_exp, cusp->translation[M]); *longitude = complex_real_mult(cusp->displacement_exp, cusp->translation[L]); } CuspNbhdSegmentList *get_cusp_neighborhood_triangulation( CuspNeighborhoods *cusp_neighborhoods, int cusp_index) { Cusp *cusp; CuspNbhdSegmentList *theSegmentList; CuspNbhdSegment *next_segment; Tetrahedron *tet, *nbr_tet; Complex (*x)[4][4]; Boolean (*in_use)[4]; VertexIndex v; Orientation h; FaceIndex f, nbr_f; /* * Make sure the EdgeClasses are numbered. */ number_the_edge_classes(cusp_neighborhoods->its_triangulation); /* * Find the requested Cusp. */ cusp = find_cusp(cusp_neighborhoods->its_triangulation, cusp_index); /* * Allocate the wrapper for the array. */ theSegmentList = NEW_STRUCT(CuspNbhdSegmentList); /* * We don't know ahead of time exactly how many CuspNbhdSegments * we'll need. Torus cusps report each segment once, but Klein * bottle cusps report each segment twice, once for each sheet. * * To get an upper bound on the number of segments, * assume all cusps are Klein bottle cusps. * * n tetrahedra * * 4 vertices/tetrahedron * * 2 triangles/vertex (left_handed and right_handed) * * 3 sides/triangle * / 2 sides/visible side (no need to draw each edge twice) * * = 12n visible sides */ theSegmentList->segment = NEW_ARRAY(12*cusp_neighborhoods->its_triangulation->num_tetrahedra, CuspNbhdSegment); /* * Keep a pointer to the first empty CuspNbhdSegment. */ next_segment = theSegmentList->segment; for (tet = cusp_neighborhoods->its_triangulation->tet_list_begin.next; tet != &cusp_neighborhoods->its_triangulation->tet_list_end; tet = tet->next) { x = tet->cusp_nbhd_position->x; in_use = tet->cusp_nbhd_position->in_use; for (v = 0; v < 4; v++) { /* * If this isn't the cusp the user wants, ignore it. */ if (tet->cusp[v] != cusp) continue; for (h = 0; h < 2; h++) /* h = right_handed, left_handed */ { if (in_use[h][v] == FALSE) continue; for (f = 0; f < 4; f++) { if (f == v) continue; nbr_tet = tet->neighbor[f]; nbr_f = EVALUATE(tet->gluing[f], f); /* * We want to report each segment only once, so we * make the (arbitrary) convention that we report * a segment only from the Tetrahedron whose address * in memory is less. In the case of a Tetrahedron * glued to itself, we report it from the lower * FaceIndex. */ if (tet > nbr_tet || (tet == nbr_tet && f > nbr_f)) continue; /* * Don't report edges which are part of the arbitrary * subdivision of the canonical cell decomposition * into tetrahdra. We rely on the fact that * proto_canonize() has computed the tilts and left * them in place. The sum of the tilts will never be * positive for a subdivision of the canonical cell * decomposition. If it's close to zero, ignore that * face. */ if (tet->tilt[f] + nbr_tet->tilt[nbr_f] > -CONCAVITY_EPSILON) continue; /* * This edge has passed all its tests, so record it. */ next_segment->endpoint[0] = complex_real_mult(cusp->displacement_exp, x[h][v][remaining_face[f][v]]); next_segment->endpoint[1] = complex_real_mult(cusp->displacement_exp, x[h][v][remaining_face[v][f]]); next_segment->start_index = tet->edge_class[edge_between_vertices[v][remaining_face[f][v]]]->index; next_segment->middle_index = tet->edge_class[edge_between_faces[v][f]]->index; next_segment->end_index = tet->edge_class[edge_between_vertices[v][remaining_face[v][f]]]->index; /* * Move on. */ next_segment++; } } } } /* * How many segments did we find? * * (ANSI C will subtract the pointers correctly, automatically * dividing by sizeof(CuspNbhdSegment).) */ theSegmentList->num_segments = next_segment - theSegmentList->segment; /* * Did we find more segments than we had allocated space for? * This should be impossible, but it doesn't hurt to check. */ if (theSegmentList->num_segments > 12*cusp_neighborhoods->its_triangulation->num_tetrahedra) uFatalError("get_cusp_neighborhood_triangulation", "cusp_neighborhoods"); return theSegmentList; } void free_cusp_neighborhood_segment_list( CuspNbhdSegmentList *segment_list) { if (segment_list != NULL) { if (segment_list->segment != NULL) my_free(segment_list->segment); my_free(segment_list); } } CuspNbhdHoroballList *get_cusp_neighborhood_horoballs( CuspNeighborhoods *cusp_neighborhoods, int cusp_index, Boolean full_list, Real cutoff_height) { Cusp *cusp; CuspNbhdHoroballList *theHoroballList; /* * Find the requested Cusp. */ cusp = find_cusp(cusp_neighborhoods->its_triangulation, cusp_index); /* * Provide a small margin to allow for roundoff error. */ cutoff_height -= CUTOFF_HEIGHT_EPSILON; /* * Use the appropriate algorithm for finding * the quick or full list of horoballs. */ if (full_list == FALSE) theHoroballList = get_quick_horoball_list(cusp_neighborhoods, cusp); else theHoroballList = get_full_horoball_list(cusp_neighborhoods, cusp, cutoff_height); /* * Sort the horoballs in order of increasing size. */ qsort( theHoroballList->horoball, theHoroballList->num_horoballs, sizeof(CuspNbhdHoroball), &compare_horoballs); /* * There's a chance that get_full_horoball_list() may produce duplicate * horoballs (when a 2-cell passes through a horoball's north pole) or * that get_quick_horoball_list() may produce duplicatate horoballs * (when face horoballs coincide). Remove any such duplications. */ cull_duplicate_horoballs(cusp, theHoroballList); return theHoroballList; } static CuspNbhdHoroballList *get_quick_horoball_list( CuspNeighborhoods *cusp_neighborhoods, Cusp *cusp) { CuspNbhdHoroballList *theHoroballList; CuspNbhdHoroball *next_horoball; /* * Allocate the wrapper for the array. */ theHoroballList = NEW_STRUCT(CuspNbhdHoroballList); /* * We don't know ahead of time exactly how many CuspNbhdHoroballs * we'll need. Torus cusps report each horoball once, but Klein * bottle cusps report each horoball twice, once for each sheet. * To get an upper bound on the number of horoballs, assume all * cusps are Klein bottle cusps. We report two types of horoballs. * * Edge Horoballs * * Edge horoballs are horoballs which the given cusp sees along an * edge of the canonical triangulation (i.e. along a vertical edge * in the usual upper half space picture). The total number of * edges in the canonical triangulation is the same as the number * of tetrahedra (by an Euler characteristic argument), so the * following gives an upper bound on the number of edge horoballs. * * n edges * * 2 endpoints/edge * * 2 sheets/endpoint (left_handed and right_handed) * * = 4n edge horoballs * * Face Horoballs * * Face horoballs are horoballs which the given cusp sees across * a face of the canonical triangulation. The number of triangles * in the cusp triangulation provides an upper bound on the number * of face horoballs. * * n tetrahedra * * 4 vertices/tetrahedron * * 2 triangles/vertex (left_handed and right_handed) * * = 8n visible sides * * Therefore the total number of horoballs we will report will be * at most 4n + 8n = 12n. (The maximum will be realized in the case * of a manifold like the Gieseking with one nonorientable cusp.) */ theHoroballList->horoball = NEW_ARRAY(12*cusp_neighborhoods->its_triangulation->num_tetrahedra, CuspNbhdHoroball); /* * Keep a pointer to the first empty CuspNbhdHoroball. */ next_horoball = theHoroballList->horoball; /* * Find the edge horoballs. */ get_quick_edge_horoballs( cusp_neighborhoods->its_triangulation, cusp, &next_horoball); /* * Find the face horoballs. */ get_quick_face_horoballs( cusp_neighborhoods->its_triangulation, cusp, &next_horoball); /* * How many horoballs did we find? * * (ANSI C will subtract the pointers correctly, automatically * dividing by sizeof(CuspNbhdHoroball).) */ theHoroballList->num_horoballs = next_horoball - theHoroballList->horoball; /* * Did we find more horoballs than we had allocated space for? * This should be impossible, but it doesn't hurt to check. */ if (theHoroballList->num_horoballs > 12*cusp_neighborhoods->its_triangulation->num_tetrahedra) uFatalError("get_cusp_neighborhood_triangulation", "cusp_neighborhoods"); return theHoroballList; } static void get_quick_edge_horoballs( Triangulation *manifold, Cusp *cusp, CuspNbhdHoroball **next_horoball) { EdgeClass *edge; Real radius; Tetrahedron *tet; Complex (*x)[4][4]; Boolean (*in_use)[4]; VertexIndex v[2]; int i; int other_index; Orientation h; for (edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) { /* * Consider a horosphere of Euclidean height h in the upper half * space model. Integrate along a vertical edge connecting the * horosphere to the horosphere at infinity to compute the distance * between the two as * * d = integral of dz/z from z=h to z=1 * = log 1 - log h * = - log h * or * h = exp(-d) * * set_cusp_neighborhood_displacement() calls compute_cusp_stoppers(), * which in turn calls compute_intercusp_distances(), so we may use * the edge->intercusp_distance fields for d. */ radius = 0.5 * exp( - edge->intercusp_distance); /* * Dereference tet, x and in_use for clarity. */ tet = edge->incident_tet; x = tet->cusp_nbhd_position->x; in_use = tet->cusp_nbhd_position->in_use; /* * Consider each of the edge's endpoints. */ v[0] = one_vertex_at_edge[edge->incident_edge_index]; v[1] = other_vertex_at_edge[edge->incident_edge_index]; for (i = 0; i < 2; i++) { /* * Are we at the right cusp? */ if (tet->cusp[v[i]] != cusp) continue; /* * What is the index of the other cusp? */ other_index = tet->cusp[v[!i]]->index; for (h = 0; h < 2; h++) /* h = right_handed, left_handed */ { if (in_use[h][v[i]] == FALSE) continue; (*next_horoball)->center = complex_real_mult(cusp->displacement_exp, x[h][v[i]][v[!i]]); (*next_horoball)->radius = radius; (*next_horoball)->cusp_index = other_index; (*next_horoball)++; } } } } static void get_quick_face_horoballs( Triangulation *manifold, Cusp *cusp, CuspNbhdHoroball **next_horoball) { /* * There are several ways we might find the location and size of * the face horoballs. * * (1) Use the TetShape to locate the center, and then use the * lemma below to find the size. * * This method is fairly efficient computationally, and lets * us use the existing function compute_fourth_corner() from * choose_generators.c. * * (2) Ignore the TetShape, and rely entirely on the intercusp_distances * to find both the location and size. * * This method is conceptually straightforward. Using the lemma * below, one obtains three equations involving the location (x,y) * and the height h of the face horoball. The equations are * quadratic in x and y, but they are monic, so subtracting * equations gives linear dependencies between x, y and h. * One can solve for x and y in terms of h, and obtain a quadratic * equation to solve for h. It's easy to prove that the lesser * value of h will be the desired solution. Confession: I haven't * actually worked out the equation for h. It seems like it would * be messy. * * (3) Work in the Minkowski space model, and use linear algebra * to compute the horoball as a vector on the light cone. * * For background ideas, see * * Weeks, Convex hulls and isometries of cusped hyperbolic * 3-manifolds, Topology Appl. 52 (1993) 127-149 * and * Sakuma and Weeks, The generalized tilt formula, * Geometriae Dedicata 55 (1995) 115-123. * * The method might prove to be more-or-less equivalent to (2). * By Lemma 4.2(c) of Weeks, the equation = constant gives * all the horospheres v a fixed distance from a horosphere u. * So to find a horosphere a given distance from three given * horospheres, one ends up intersecting three hyperplanes in * E^(3,1) to get a line, and then intersecting the line with the * upper light cone. As in approach (2), the calculations are * initially linear, but become quadratic at the end. Again, I * haven't worked through the details. * * (4) Find a matrix in PSL(2,C) which takes an ideal tetrahedron * in standard position to the desired ideal tetrahedron. * * This is the approach used in snappea 1.3. The formulas are * simpler than you might expect. The main disadvantage is that * the 1.3 treatment applies only to orientable manifolds. It * might be possible to fix it up using MoebiusTransformations. * * We use method (1), because it seems simplest. * * Lemma. Consider two horospheres of Euclidean height h1 and h2 (resp.) * in the upper half space model of hyperbolic 3-space. If the * Euclidean distances between their centers (on the sphere at infinity) * is c, then the hyperbolic distance d between the horospheres is * * d = log( c^2 / h1*h2 ) * * Proof. Draw yourself a picture of the horospheres (or horocycles -- * a 2D cross sectional picture will serve just as well). Label the * distances h1, h2, c and d. Now sketch a Euclidean hemisphere of * radius c centered at the base of the first horosphere; this is * a plane in hyperbolic space. Reflect the whole picture in this * plane (in Euclidean terms, the reflection is an inversion in the * hemisphere). One of the horospheres gets taken to a horizontal * Euclidean plane at height c^2/h1. The other horosphere remains * (setwise) invariant. It is now obvious that the shortest distance * from one horosphere to the other is along the vertical arc connecting * them. The distance is the integral of dz/z from h=h2 to h=c^2/h1, * which works out to be log( c^2 / h1*h2 ). QED * * Comment. We don't need it for the present code, but I can't * resist pointing out that the above lemma has a nice intrinsic * formulation, which doesn't rely on the upper half space model. * Let H be the horosphere which appears as a horizontal plane z == 1 * in the upper half space model, and draw in the vertical geodesics * connecting it to each of the two horospheres mentioned in the lemma. * Let a = -log(h1) and b = -log(h2) be the respective distances from * H to each of the old horospheres. Interpret c as the distance along * H from one of those segments to the other. Now redraw the picture * in, say, the Poincare ball model. It'll be more symmetric now, * since there's no longer a preferred "horosphere at infinity". * You'll have an ideal triangle, with a horosphere at each vertex. * The quantities a, b and d are the length of the shortest geodesics * between horospheres, while c is the distance along a horosphere * between two such geodesics. The above lemma becomes * * Lemma. 2 log c = d - a - b. * * With better notation, namely a, b and c are the distances between * cusp cross sections, and A, B and C are the distances along the * cusps, the lemma becomes * * 2 log A = a - b - c * 2 log B = b - c - a * 2 log C = c - a - b * * Add two of those equations (say the first two) to get * * log AB = -c * * As a special case, when c == 0, AB = 1. */ Tetrahedron *tet; Complex (*x)[4][4]; Boolean (*in_use)[4]; VertexIndex u, v, w, missing_corner; Permutation gluing; Complex corner[4]; Orientation h; Real height_u, exp_d, c_squared; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) { x = tet->cusp_nbhd_position->x; in_use = tet->cusp_nbhd_position->in_use; for (v = 0; v < 4; v++) { /* * Are we at the right cusp? */ if (tet->cusp[v] != cusp) continue; gluing = tet->gluing[v]; for (h = 0; h < 2; h++) /* h = right_handed, left_handed */ { if (in_use[h][v] == FALSE) continue; /* * Prepare for a call to compute_fourth_corner(). */ for (w = 0; w < 4; w++) if (w != v) corner[EVALUATE(gluing, w)] = complex_real_mult(cusp->displacement_exp, x[h][v][w]); missing_corner = EVALUATE(gluing, v); /* * Call compute_fourth_corner() to compute * corner[missing_corner]. */ compute_fourth_corner( corner, missing_corner, (parity[gluing] == orientation_preserving) ? h : !h, tet->neighbor[v]->shape[complete]->cwl[ultimate]); /* * The missing_corner gives us the horoball's center. */ (*next_horoball)->center = corner[missing_corner]; /* * Prepare to use the above lemma to compute the radius. */ /* * Let u be any vertex of the original Tetrahedron except v. */ u = !v; /* * According to the explanation in get_quick_edge_horoballs(), * the height of the edge horoball at vertex u is * exp( - intercusp_distance). */ height_u = exp( - tet->edge_class[edge_between_vertices[u][v]]->intercusp_distance); /* * A different intercusp_distance gives the distance d * in the lemma. */ exp_d = exp(tet->neighbor[v]->edge_class[edge_between_vertices[EVALUATE(gluing,u)][missing_corner]]->intercusp_distance); /* * Compute the squared distance between the edge horoball * at vertex u and the face horoball we are interested in. */ c_squared = complex_modulus_squared(complex_minus( (*next_horoball)->center, complex_real_mult(cusp->displacement_exp, x[h][v][u]))); /* * Apply the lemma. * * exp(d) = c^2 / h1*h2 * => * h1 = c^2 / exp(d)*h2 */ (*next_horoball)->radius = 0.5 * c_squared / (exp_d * height_u); /* * Note the cusp index of the new horoball. */ (*next_horoball)->cusp_index = tet->neighbor[v]->cusp[missing_corner]->index; /* * Move on. */ (*next_horoball)++; } } } } static CuspNbhdHoroballList *get_full_horoball_list( CuspNeighborhoods *cusp_neighborhoods, Cusp *cusp, Real cutoff_height) { /* * We want to find all horoballs of Euclidean height at least * cutoff_height, up to the Z + Z action of the group of covering * transformations of the cusp. (We work with the double cover * of Klein bottle cusps, so in effect all cusps are torus cusps.) * * Let M' be H^3 / (Z + Z), where the Z + Z is the group of covering * transformations of the cusp. Visualize M' as a chimney in the * upper half space model; when its sides are glued together its * parallelogram cross section becomes the torus cross section * of the cusp. * * Our plan is to lift ideal tetrahedra from the original manifold M * to the chimney manifold M'. We begin with the tetrahedra incident * to the chimney's cusp (i.e. its top end), and then gradually tile * our way downward. Whenever a new tetrahedron introduces a new * ideal vertex, we consider the horoball centered at that vertex. * If its Euclidean height is greater than cutoff_height, we add it * to a list. Our challenge is to find an algorithm which does as * little tiling as possible, yet still finds all horoballs higher * than the cutoff_height. * * The Naive Algorithm * * The naive algorithm is to consider the neighbors of each tetrahedron * already in the tiling. If adding a neighbor would introduce no * new vertices, add it. If adding a neighbor would introduce a new * vertex, add it iff the horoball at the new vertex is higher than * the cutoff_height. * * Unfortunately the naive algorithm fails. The Whitehead link * provides a counterexample. Visualize the Whitehead link as an * octahedron with faces identified. The ideal vertices at the * "north and south poles" form one cusp ("the red cusp") while the * "equatorial ideal vertices" form the other cusp ("the blue cusp"). * Push the blue cusp cross section forward until it meets itself, * but retract the red cusp cross section until it's tiny. The * canonical cell decomposition is a subdivision of the octahedron * into two square pyramids (a "northern" and a "southern" one). * SnapPea will, of course, arbitrarily subdivide each pyramid into * two tetrahedra. Now consider what happens when we apply the naive * algorithm to this example, with the red cusp at infinity. Each * of the initial tetrahedra has a red vertex at infinity, and three * blue vertices on the horizontal plane. Its three neighbors to the * sides are other tetrahedra of the same type (red at infinity and * blue on the horizontal plane). Its underneath neighbor shares the * same three blue vetices, and introduce a new red vertex on the * horizontal plane. But because the red horoball is tiny, the naive * algorithm will say not to add this tetrahedron. So no new tetrahedra * will be added, and the algorithm will terminate. The naive * algorithm has therefore failed, because it's missed blue horoballs * of varying sizes. (Assuming we've chosen the size of the tiny * red cusp cross section to be small enough that the largest red * horoballs are smaller than the medium sized blue one.) * * The naive algorithm's failure was the bad news. The good news * is that if we take into account the varying sizes of the horoballs, * the algorithm can be patched up and made to work. First a few * background lemmas. * * Lemma 1. For each horoball H, there is (a lift of) an edge * of the canonical cell decompostion which connects H to some * larger horoball H'. * * Proof. The horoball H is surrounded by (lifts of) 2-cells * of the Ford complex. Consider a 2-cell F which lies above some * point of H (in the upper half space model). F is dual to an edge * of the canonical cell decomposition which connects H to some other * horoball H'. F lies above H, so by Lemma 2 below, H' is larger * than H. QED * * Lemma 2. Consider two horoballs H and H'. If H' has a larger * Euclidean height than H when viewed in some fixed way in the upper * half space model of hyperbolic 3-space, then the plane P lying * midway between them appears as a Euclidean hemisphere enclosing * H and excluding H'. In particular, every point of H is directly * below some point of P, while no point of H' is. * * Proof. Draw the horoballs and construct P. QED * * Definition. Two horoballs are "edge-connected" if (a lift of) an * edge of the canonical cell decomposition connects one to the other. * * Lemma 3. Let H' be a horoball which is edge-connected to a smaller * horoball H. Then the Euclidean distance c between their centers * (on the boundary plane of the upper half space model) is * * c = sqrt( a * b * exp(d) ) * * where * a = Euclidean height of H' * b = Euclidean height of H * d = hyperbolic distance from H' to H. * * Proof. The lemma in get_quick_face_horoballs() says that * d = log(c^2 / a*b). Solve for c = sqrt( a * b * exp(d) ). QED * * Lemma 4. Let H' be a horoball which is edge-connected to a smaller * horoball H. If the Euclidean height of H is at least cutoff_height, * then the Euclidean distance c between the centers of H and H' is * at least * c >= sqrt( a * cutoff_height * exp(min_d) ) * * where a is the height of H' and min_d is the least distance from * the horoball H' to any other horoball. * * Proof. Follows immediately from Lemma 3. * * Comment. The exp(min_d) factor makes H' act like a bigger horoball * than it really is. If you were to increase the cusp displacement * by min_d, the height of H' would increase to a*exp(min_d). * * Definition. (A lift of) an edge of the canonical triangulation * is "potentially useful" if one endpoint lies at the center of * a horoball H' of height at least cutoff_height, and the distance * between its two endpoints is at least c (as defined in Lemma 4). * (As a special case, vertical edges (in the upper half space) are * always "potentially useful". The informal justification for this * is that the horosphere at infinity is infinity large and its center * is infinitely far away.) * * Definition. (A lift of) an ideal tetrahedron is "potentially useful" * iff it contains at least one potentially useful edge. * * The Corrected Algorithm * * As before, begin with the tetrahedra incident to the chimney's cusp * and gradually tile downward. For each tetrahedron already in the * tiling, consider its four neighbors and add those which are * potentially useful. * * Lemma 5. Let H' be a horoball higher than the cutoff_height. * If the Corrected Algorithm adds one potentially useful tetrahedron * incident to H', then it adds them all. * * Proof. Look at the surface of the horoball H', which intrinsically * is a Euclidean plane E. An edge of the triangulation intersects * the plane E in point P. The edge is potentially useful iff P lies * within a disk D (of intrinsic radius a/c in the Euclidean geometry * of the horosphere E, but we don't need that fact). A tetrahedron * incident to H' is potentially useful iff it intersects the disk D. * The set of all such tetrahedra forms a connected set (this follows * from the path connectedness of the disk D). Therefore if the * algorithm adds one such tetrahedron, it will add them all. QED * * Proposition 6. The Corrected Algorithm finds all horoballs higher * than the cutoff_height. * * Proof. Let H be a horoball of maximal height (greater than the * cutoff_height) which the algorithm missed. By Lemma 1, there * is a higher horoball H', and an edge connecting H' to H. The * edge is potentially useful, by Lemma 4 and the definition of a * potentially useful edge. By the assumed maximal height of H * (among all horoballs which the Corrected Algorithm should have * found but didn't), we know that the algorithm did find H', i.e. * it added some potentially useful tetrahedron incident to the center * of H'. By Lemma 5, it must have added all potentially useful * tetrahedra incident to H', and therefore must have found H. QED * * Corollary 7. We can refine the Corrected Algorithm as follows. * For each tetrahedron T already added, we consider only those * neighbors T' incident to a face of T which contains at least * one potentially useful edge. * * Proof. The proof of Proposition 6 still works. QED */ TilingHoroball *horoball_linked_list; TilingQueue tiling_queue; TilingTet *tiling_tree_root, *tiling_tet, *tiling_nbr; Complex meridian, longitude; Real parallelogram_to_square[2][2]; FaceIndex f; CuspNbhdHoroballList *theHoroballList; /* * We don't know a priori how many horoballs we'll find. * So we temporarily keep them on a NULL-terminated linked list, * and transfer them to an array when we're done. * * To avoid recording multiple copies of each horoball, we make the * convention that each horoball is recorded only by the TilingTet * which contains its north pole. If the north pole lies on the * boundary of two TilingTets, they both record it. * get_cusp_neighborhood_horoballs() will remove the duplications. * If three or more TilingTets meet at the north pole, then a vertical * edge connects the horoball to infinity in the upper half space model; * read_initial_tetrahedra() records such horoballs without duplication. * (Other strategies are possible, like preferring the Tetrahedron * with the lower address in memory, but the present approach is * least vulnerable to roundoff error.) */ horoball_linked_list = NULL; /* * We'll need to store the potentially useful tetrahedra in two ways. * * Queue * The Tetrahedra which have been added, but whose neighbors have * not been examined, go on a queue, so we know which one * to process next. When we remove a tetrahedron from the queue * we examine its neighbors. We use a queue rather than a stack * so that we tile generally downwards (rather than snaking around) * in hopes of obtaining the best numerical precision. * * Tree * All tetrahedra which have been added are kept on a tree, so that * we can tell whether new tetrahedra are duplications of old ones * or not. (Note: Checking whether a tetrahedron is "the same as" * an old one means checking whether they are equivalent under * the Z + Z action of the covering transformations. * * The TilingTet structure supports both the queue and the tree, * simultaneously and independently. */ /* * Initialize the data structures. */ tiling_queue.begin = NULL; tiling_queue.end = NULL; tiling_tree_root = NULL; /* * For each cusp, compute the quantity exp(min_d) needed in Lemma 4. */ compute_exp_min_d(cusp_neighborhoods->its_triangulation); /* * Compute the current meridional and longitudinal translations. */ meridian = complex_real_mult(cusp->displacement_exp, cusp->translation[M]); longitude = complex_real_mult(cusp->displacement_exp, cusp->translation[L]); /* * prepare_sort_key() will need a linear transformation which * maps a fundamental parallelogram for the cusp (or the double * cover, in the case of a Klein bottle cusp) to the unit square. */ compute_parallelogram_to_square(meridian, longitude, parallelogram_to_square); /* * Read in the tetrahedra incident to the vertex at infinity, * and record the incident horoballs. * * Note: We check the horoballs when we put TilingTets onto the * tiling_queue (rather than when we pull it off) so we can handle * the special case of the initial tetrahedra more efficiently. */ read_initial_tetrahedra( cusp_neighborhoods->its_triangulation, cusp, &tiling_queue, &tiling_tree_root, &horoball_linked_list, cutoff_height); /* * Carry out the Corrected Algorithm, refined as in Lemma 7. */ while (tiling_queue.begin != NULL) { tiling_tet = get_tiling_tet_from_queue(&tiling_queue); for (f = 0; f < 4; f++) if (tiling_tet->neighbor_found[f] == FALSE && face_contains_useful_edge(tiling_tet, f, cutoff_height) == TRUE) { tiling_nbr = make_neighbor_tiling_tet(tiling_tet, f); prepare_sort_key(tiling_nbr, parallelogram_to_square); if (tiling_tet_on_tree(tiling_nbr, tiling_tree_root, meridian, longitude) == FALSE) { add_horoball_if_necessary(tiling_nbr, &horoball_linked_list, cutoff_height); add_tiling_tet_to_tree(tiling_nbr, &tiling_tree_root); add_tiling_tet_to_queue(tiling_nbr, &tiling_queue); } else my_free(tiling_nbr); } } /* * Free the TilingTets. */ free_tiling_tet_tree(tiling_tree_root); /* * Transfer the horoballs from the linked list * to a CuspNbhdHoroballList, and free the linked list. */ theHoroballList = transfer_horoballs(&horoball_linked_list); return theHoroballList; } static void compute_exp_min_d( Triangulation *manifold) { /* * Compute the quantity exp(min_d) needed * in Lemma 4 of get_full_horoball_list(). */ Cusp *cusp; EdgeClass *edge; Real exp_d; VertexIndex v[2]; int i; /* * Initialize all exp_min_d's to infinity. */ for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) cusp->exp_min_d = REAL_MAX; /* * The closest horoball to a given cusp will lie along an edge * of the canonical cell decomposition, so look at all edges * to find the true exp_min_d's. */ for (edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) { /* * set_cusp_neighborhood_displacement() calls compute_cusp_stoppers(), * which in turn calls compute_intercusp_distances(), so we may use * the edge->intercusp_distance fields for exp_d. */ exp_d = exp(edge->intercusp_distance); v[0] = one_vertex_at_edge[edge->incident_edge_index]; v[1] = other_vertex_at_edge[edge->incident_edge_index]; for (i = 0; i < 2; i++) { cusp = edge->incident_tet->cusp[v[i]]; if (cusp->exp_min_d > exp_d) cusp->exp_min_d = exp_d; } } } static void compute_parallelogram_to_square( Complex meridian, Complex longitude, Real parallelogram_to_square[2][2]) { /* * prepare_sort_key() needs a linear transformation which takes * a meridian to (1,0) and a longitude to (0,1), so TilingTets which * are equivalent under the Z + Z action of the group of covering * translations of the cusp be assigned corner coordinates which * differ by integers. The required linear transformation is * the inverse of * * ( meridian.real longitude.real ) * ( meridian.imag longitude.imag ) */ Real det; det = meridian.real * longitude.imag - meridian.imag * longitude.real; parallelogram_to_square[0][0] = longitude.imag / det; parallelogram_to_square[0][1] = - longitude.real / det; parallelogram_to_square[1][0] = - meridian.imag / det; parallelogram_to_square[1][1] = meridian.real / det; } static void read_initial_tetrahedra( Triangulation *manifold, Cusp *cusp, TilingQueue *tiling_queue, TilingTet **tiling_tree_root, TilingHoroball **horoball_linked_list, Real cutoff_height) { Tetrahedron *tet; Complex (*x)[4][4]; Boolean (*in_use)[4]; VertexIndex v, w; Orientation h; TilingTet *tiling_tet; EdgeIndex edge_index; EdgeClass *edge; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) { x = tet->cusp_nbhd_position->x; in_use = tet->cusp_nbhd_position->in_use; for (v = 0; v < 4; v++) { if (tet->cusp[v] != cusp) continue; for (h = 0; h < 2; h++) /* h = right_handed, left_handed */ { if (in_use[h][v] == FALSE) continue; tiling_tet = NEW_STRUCT(TilingTet); tiling_tet->underlying_tet = tet; tiling_tet->orientation = h; for (w = 0; w < 4; w++) if (w != v) { /* * Please see get_quick_edge_horoballs() for * an explanation of the horoball height. */ edge_index = edge_between_vertices[v][w]; edge = tet->edge_class[edge_index]; tiling_tet->corner[w] = complex_real_mult(cusp->displacement_exp, x[h][v][w]); tiling_tet->horoball_height[w] = exp( - edge->intercusp_distance); tiling_tet->neighbor_found[w] = TRUE; /* * To avoid duplications, record the TilingHoroball * iff this is the preferred tet and edge_index * to see it from. */ if (edge->incident_tet == tet && edge->incident_edge_index == edge_index && tiling_tet->horoball_height[w] >= cutoff_height) add_tiling_horoball_to_list(tiling_tet, w, horoball_linked_list); } else { tiling_tet->corner[w] = Infinity; tiling_tet->horoball_height[w] = REAL_MAX; tiling_tet->neighbor_found[w] = FALSE; } /* * Give each tiling_tet a random value of the sort key, * to keep the tree broad. */ tiling_tet->key = 0.5 * ((Real) rand() / (Real) RAND_MAX); add_tiling_tet_to_queue(tiling_tet, tiling_queue); add_tiling_tet_to_tree(tiling_tet, tiling_tree_root); } } } } static TilingTet *get_tiling_tet_from_queue( TilingQueue *tiling_queue) { TilingTet *tiling_tet; tiling_tet = tiling_queue->begin; if (tiling_queue->begin != NULL) tiling_queue->begin = tiling_queue->begin->next; if (tiling_queue->begin == NULL) tiling_queue->end = NULL; return tiling_tet; } static void add_tiling_tet_to_queue( TilingTet *tiling_tet, TilingQueue *tiling_queue) { tiling_tet->next = NULL; if (tiling_queue->end != NULL) { tiling_queue->end->next = tiling_tet; tiling_queue->end = tiling_tet; } else { tiling_queue->begin = tiling_tet; tiling_queue->end = tiling_tet; } } static void add_tiling_horoball_to_list( TilingTet *tiling_tet, VertexIndex v, TilingHoroball **horoball_linked_list) { TilingHoroball *tiling_horoball; tiling_horoball = NEW_STRUCT(TilingHoroball); tiling_horoball->data.center = tiling_tet->corner[v]; tiling_horoball->data.radius = 0.5 * tiling_tet->horoball_height[v]; tiling_horoball->data.cusp_index = tiling_tet->underlying_tet->cusp[v]->index; tiling_horoball->next = *horoball_linked_list; *horoball_linked_list = tiling_horoball; } static Boolean face_contains_useful_edge( TilingTet *tiling_tet, FaceIndex f, Real cutoff_height) { /* * Note: We may assume that the face f has no vertices at the point * at infinity in upper half space. The reason is that the intial * tetrahedra have neighbor_found[] == TRUE for their side faces, and * get_full_horoball_list() calls us only if neighbor_found[f] is FALSE. */ /* * How many vertices incident to face f have horoballs * higher than cutoff_height? */ int num_big_horoballs; VertexIndex v, big_vertex; Real min_separation_sq; num_big_horoballs = 0; for (v = 0; v < 4; v++) { if (v == f) continue; if (tiling_tet->horoball_height[v] > cutoff_height) { num_big_horoballs++; big_vertex = v; } } /* * If there are no big horoballs, * the face cannot contain a useful edge. */ if (num_big_horoballs == 0) return FALSE; /* * If there are two or more big horoballs, * the face must contain a useful edge. */ if (num_big_horoballs >= 2) return TRUE; /* * At this point we know that the unique large horoball lies * at the vertex big_vertex. There will be a useful edge iff * the distance from big_vertex to some other vertex of face f * is at least sqrt( height_of_big_vertex * cutoff_height * exp(min_d) ). * For a detailed explanation, please see Lemma 4 and the definition * of "useful edge" in get_full_horoball_list(). */ min_separation_sq = tiling_tet->horoball_height[big_vertex] * cutoff_height * tiling_tet->underlying_tet->cusp[big_vertex]->exp_min_d; for (v = 0; v < 4; v++) { if (v == f || v == big_vertex) continue; if (complex_modulus_squared( complex_minus( tiling_tet->corner[big_vertex], tiling_tet->corner[v] ) ) > min_separation_sq) return TRUE; } return FALSE; } static TilingTet *make_neighbor_tiling_tet( TilingTet *tiling_tet, FaceIndex f) { Tetrahedron *tet, *nbr; Permutation gluing; TilingTet *tiling_nbr; VertexIndex v, w, ff, some_vertex; Real exp_d, c_squared; /* * Find the underlying tetrahedra and the gluing between them. */ tet = tiling_tet->underlying_tet; nbr = tet->neighbor[f]; gluing = tet->gluing[f]; /* * Set up the new TilingTet. */ tiling_nbr = NEW_STRUCT(TilingTet); tiling_nbr->underlying_tet = nbr; tiling_nbr->orientation = (parity[gluing] == orientation_preserving) ? tiling_tet->orientation : ! tiling_tet->orientation; for (v = 0; v < 4; v++) { if (v == f) continue; w = EVALUATE(gluing, v); tiling_nbr->corner[w] = tiling_tet->corner[v]; tiling_nbr->horoball_height[w] = tiling_tet->horoball_height[v]; tiling_nbr->neighbor_found[w] = FALSE; } /* * Deal with the remaining corner. */ ff = EVALUATE(gluing, f); /* * Call compute_fourth_corner() to locate the remaining ideal vertex. */ compute_fourth_corner( tiling_nbr->corner, ff, tiling_nbr->orientation, nbr->shape[complete]->cwl[ultimate]); /* * Use the lemma from get_quick_face_horoballs() to compute * the height of the remaining horoball. */ some_vertex = ! ff; exp_d = exp(nbr->edge_class[edge_between_vertices[ff][some_vertex]]->intercusp_distance); c_squared = complex_modulus_squared(complex_minus( tiling_nbr->corner[ff], tiling_nbr->corner[some_vertex])); tiling_nbr->horoball_height[ff] = c_squared / (exp_d * tiling_nbr->horoball_height[some_vertex]); /* * Don't backtrack to the TilingTet we just came from. */ tiling_nbr->neighbor_found[ff] = TRUE; /* * get_full_horoball_list() will decide whether to add tiling_nbr * to the linked list and tree, and whether to add the new horoball * to the horoball list. */ tiling_nbr->next = NULL; tiling_nbr->left = NULL; tiling_nbr->right = NULL; tiling_nbr->key = 0.0; return tiling_nbr; } static void prepare_sort_key( TilingTet *tiling_tet, Real parallelogram_to_square[2][2]) { VertexIndex v; Complex transformed_corner[4]; static const Real coefficient[4][2] = {{37.0, 25.0}, {43.0, 13.0}, {2.0, 29.0}, {11.0, 7.0}}; /* * Special case: To avoid questions of numerical accuracy, assign * the "illegal" key value of -1 to TilingTets incident to infinity * in upper half space. read_initial_tetrahedra() puts all such * TilingTets on the tree, so none need be added again. */ for (v = 0; v < 4; v++) if (complex_modulus(tiling_tet->corner[v]) > KEY_INFINITY) { tiling_tet->key = -1.0; return; } /* * Recall that we are tiling H^3 / (Z + Z), where the Z + Z is * the group of covering transformations of the cusp. In other words, * two TilingTets are equivalent iff corresponding corners differ * by some combination of meridional and/or longitudinal translations. * The linear transformation parallelogram_to_square maps a meridian * to (1,0) and a longitude to (0,1). We apply it to the TilingTets' * corners, so corresponding corners will differ by integers. */ for (v = 0; v < 4; v++) { transformed_corner[v].real = parallelogram_to_square[0][0] * tiling_tet->corner[v].real + parallelogram_to_square[0][1] * tiling_tet->corner[v].imag; transformed_corner[v].imag = parallelogram_to_square[1][0] * tiling_tet->corner[v].real + parallelogram_to_square[1][1] * tiling_tet->corner[v].imag; } /* * To implement a binary tree, we need a search key which is well * defined under the action of the meridional and longitudinal * translations. In terms of the transformed_corners, it should be * well defined under integer translations. Any integer linear * combination of the real and imaginary parts of the transformed * corners will do. We choose a random looking one, to reduce the * chances that distinct points will be assigned the same value of * the search key. (Of course the algorithm works correctly in any * case -- it's just faster if all the search key values are distinct.) * The linear combination provides a continuous map from the transformed * corners modulo integers to the reals modulo integers, i.e. to the * circle. We then map the circle to the interval [0, 1/2] in a * continuous way. (It's a two-to-one map, but that's unavoidable.) */ /* * Form a random looking integer combination of the corner coordinates. */ tiling_tet->key = 0.0; for (v = 0; v < 4; v++) { tiling_tet->key += coefficient[v][0] * transformed_corner[v].real; tiling_tet->key += coefficient[v][1] * transformed_corner[v].imag; } /* * Take the fractional part. */ tiling_tet->key -= floor(tiling_tet->key); /* * Fold the unit interval [0,1] onto the half interval [0, 1/2] * in ensure continuity. */ if (tiling_tet->key > 0.5) tiling_tet->key = 1.0 - tiling_tet->key; } static Boolean tiling_tet_on_tree( TilingTet *tiling_tet, TilingTet *tiling_tree_root, Complex meridian, Complex longitude) { TilingTet *subtree_stack, *subtree; Real delta; Boolean left_flag, right_flag; FaceIndex f; /* * As a special case, TilingTets incident to infinity in upper half * space are already all on the tree. prepare_sort_key() marks * duplicates of such TilingTets with a key value of -1. (Computing * and comparing the usual key value is awkward when some of the * numbers are infinite.) */ if (tiling_tet->key == -1.0) return TRUE; /* * Reliability is our first priority. Speed is second. So if * tiling_tet->key and subtree->key are close, we want to search both * the left and right subtrees. Otherwise we search only one or the * other. We implement the recursion using our own stack, rather than * the system stack, to avoid the possibility of a stack/heap collision * during deep recursions. */ /* * Initialize the stack to contain the whole tree. */ subtree_stack = tiling_tree_root; if (tiling_tree_root != NULL) tiling_tree_root->next_subtree = NULL; /* * Process the subtrees on the stack, * adding additional subtrees as needed. */ while (subtree_stack != NULL) { /* * Pull a subtree off the stack. */ subtree = subtree_stack; subtree_stack = subtree_stack->next_subtree; subtree->next_subtree = NULL; /* * Compare the key values of the tiling_tet and the subtree's root. */ delta = tiling_tet->key - subtree->key; /* * Which side(s) should we search? */ left_flag = (delta < +KEY_EPSILON); right_flag = (delta > -KEY_EPSILON); /* * Put the subtrees we need to search onto the stack. */ if (left_flag && subtree->left) { subtree->left->next_subtree = subtree_stack; subtree_stack = subtree->left; } if (right_flag && subtree->right) { subtree->right->next_subtree = subtree_stack; subtree_stack = subtree->right; } /* * Check this TilingTet if the key values match. */ if (left_flag && right_flag) /* * Are the TilingTets translations of one another? */ if (same_corners(tiling_tet, subtree, meridian, longitude)) { /* * *subtree is a TilingTet which may or may not have been * processed yet. If not, then when we do process it, we * know there's no need to recreate tiling_tet's "parent". */ for (f = 0; f < 4; f++) subtree->neighbor_found[f] |= tiling_tet->neighbor_found[f]; return TRUE; } } return FALSE; } static Boolean same_corners( TilingTet *tiling_tet1, TilingTet *tiling_tet2, Complex meridian, Complex longitude) { /* * Are tiling_tet1 and tiling_tet2 translations of the same tetrahedron * in H^3/(Z + Z) ? * * Note: This function does *not* take into account the size of the * TilingTets. Two TilingsTets which were very tiny and very close * could cause a false positive, and such TilingTets could be mistakenly * omitted from the tiling. But that's not likely to happen for any * computationally feasible value of cutoff_epsilon. */ Complex offset, fractional_part, diff; Real num_meridians, num_longitudes, error; VertexIndex v; /* * Is the offset between a pair of corresponding vertices * an integer combination of meridians and longitudes? */ offset = complex_minus( tiling_tet2->corner[0], tiling_tet1->corner[0]); fractional_part = offset; num_meridians = floor(fractional_part.imag / meridian.imag + 0.5); fractional_part = complex_minus( fractional_part, complex_real_mult(num_meridians, meridian)); num_longitudes = floor(fractional_part.real / longitude.real + 0.5); fractional_part = complex_minus( fractional_part, complex_real_mult(num_longitudes, longitude)); if (complex_modulus(fractional_part) > CORNER_EPSILON) return FALSE; /* * Do all pairs of corresponding vertices differ by the same offset? */ for (v = 1; v < 4; v++) { diff = complex_minus( tiling_tet2->corner[v], tiling_tet1->corner[v]); error = complex_modulus(complex_minus(offset, diff)); if (error > CORNER_EPSILON) return FALSE; } return TRUE; } static void add_tiling_tet_to_tree( TilingTet *tiling_tet, TilingTet **tiling_tree_root) { /* * tiling_tet_on_tree() has already checked that tiling_tet is not * a translation of any TilingTet already on the tree. So here we * just add it in the appropriate spot, based on the key value. */ TilingTet **location; location = tiling_tree_root; while (*location != NULL) { if (tiling_tet->key <= (*location)->key) location = &(*location)->left; else location = &(*location)->right; } *location = tiling_tet; tiling_tet->left = NULL; tiling_tet->right = NULL; } static void add_horoball_if_necessary( TilingTet *tiling_tet, TilingHoroball **horoball_linked_list, Real cutoff_height) { VertexIndex v; for (v = 0; v < 4; v++) { /* * Ignore horoballs which are too small. */ if (tiling_tet->horoball_height[v] < cutoff_height) continue; /* * Recall the convention made in get_full_horoball_list() that * each horoball is recorded only by the TilingTet * which contains its north pole. If the north pole lies on the * boundary of two TilingTets, they both record it. */ if (contains_north_pole(tiling_tet, v) == TRUE) add_tiling_horoball_to_list(tiling_tet, v, horoball_linked_list); } } static Boolean contains_north_pole( TilingTet *tiling_tet, VertexIndex v) { /* * Check whether vertex v lies within the triangle defined * by the remaining three vertices. */ int i; VertexIndex w[3]; Complex u[3]; Real s[3], det; /* * Label the remaining three vertices w[0], w[1] and w[2] * as you go counterclockwise around the triangle they define * on the boundary of upper half space. * * w[2] * / \ * / \ * / \ * w[0]-------w[1] * * If v lies inside that triangle we'll return TRUE; * otherwise we'll return FALSE. */ w[0] = !v; if (tiling_tet->orientation == right_handed) { w[1] = remaining_face[v][w[0]]; w[2] = remaining_face[w[0]][v]; } else { w[1] = remaining_face[w[0]][v]; w[2] = remaining_face[v][w[0]]; } /* * The vector u[i] runs from v to w[i]. * * w[2] * / | \ * / v \ * / / \ \ * w[0]-------w[1] */ for (i = 0; i < 3; i++) u[i] = complex_minus(tiling_tet->corner[w[i]], tiling_tet->corner[v]); /* * s[i] is the squared length of the triangle's i-th side. */ for (i = 0; i < 3; i++) s[i] = complex_modulus_squared(complex_minus(tiling_tet->corner[w[(i+1)%3]], tiling_tet->corner[w[i]])); /* * If v lies in the triangle's interior, we of course return TRUE. * But if v lies (approximately) on one of the triangle's sides, we * also want to return TRUE, so that in ambiguous cases horoballs are * recorded twice, not zero times. * * We need a scale invariant measure of the signed distance from v * to each side of the triangle, so that we can apply our error epsilon * in a meaningful way. (We don't want to return TRUE for *all* tiny * triangles, simply because they are tiny!) The determinant * * | u[i].real u[i+1].real | * det = | | * | u[i].imag u[i+1].imag | * * gives twice the area of the triangle (v, w[i], w[i+1]). * Therefore det/dist(w[i], w[i+1]) gives the triangle's altitude, * and det/dist(w[i], w[i+1])^2 = det/s[i] gives the ratio of * the altitude to the length of the side. If that ratio is at least * -NORTH_POLE_EPSILON for all sides, we return TRUE. */ for (i = 0; i < 3; i++) { det = u[i].real * u[(i+1)%3].imag - u[i].imag * u[(i+1)%3].real; if (det / s[i] < -NORTH_POLE_EPSILON) return FALSE; } return TRUE; } static void free_tiling_tet_tree( TilingTet *tiling_tree_root) { TilingTet *subtree_stack, *subtree; /* * Implement the recursive freeing algorithm using our own stack * rather than the system stack, to avoid the possibility of a * stack/heap collision. */ /* * Initialize the stack to contain the whole tree. */ subtree_stack = tiling_tree_root; if (tiling_tree_root != NULL) tiling_tree_root->next_subtree = NULL; /* * Process the subtrees on the stack one at a time. */ while (subtree_stack != NULL) { /* * Pull a subtree off the stack. */ subtree = subtree_stack; subtree_stack = subtree_stack->next_subtree; subtree->next_subtree = NULL; /* * If the subtree's root has nonempty left and/or right subtrees, * add them to the stack. */ if (subtree->left != NULL) { subtree->left->next_subtree = subtree_stack; subtree_stack = subtree->left; } if (subtree->right != NULL) { subtree->right->next_subtree = subtree_stack; subtree_stack = subtree->right; } /* * Free the subtree's root node. */ my_free(subtree); } } static CuspNbhdHoroballList *transfer_horoballs( TilingHoroball **horoball_linked_list) { CuspNbhdHoroballList *theHoroballList; TilingHoroball *the_tiling_horoball, *the_dead_horoball; int i; /* * Allocate the wrapper. */ theHoroballList = NEW_STRUCT(CuspNbhdHoroballList); /* * Count the horoballs. */ for ( the_tiling_horoball = *horoball_linked_list, theHoroballList->num_horoballs = 0; the_tiling_horoball != NULL; the_tiling_horoball = the_tiling_horoball->next, theHoroballList->num_horoballs++) ; /* * If we found some horoballs, allocate an array * for the CuspNbhdHoroballs. */ if (theHoroballList->num_horoballs > 0) theHoroballList->horoball = NEW_ARRAY(theHoroballList->num_horoballs, CuspNbhdHoroball); else theHoroballList->horoball = NULL; /* * Copy the data from the linked list to the array. */ for ( the_tiling_horoball = *horoball_linked_list, i = 0; the_tiling_horoball != NULL; the_tiling_horoball = the_tiling_horoball->next, i++) theHoroballList->horoball[i] = the_tiling_horoball->data; /* * Free the linked list. */ while (*horoball_linked_list != NULL) { the_dead_horoball = *horoball_linked_list; *horoball_linked_list = the_dead_horoball->next; my_free(the_dead_horoball); } return theHoroballList; } void free_cusp_neighborhood_horoball_list( CuspNbhdHoroballList *horoball_list) { if (horoball_list != NULL) { if (horoball_list->horoball != NULL) my_free(horoball_list->horoball); my_free(horoball_list); } } static int compare_horoballs( const void *horoball0, const void *horoball1) { if (((CuspNbhdHoroball *)horoball0)->radius < ((CuspNbhdHoroball *)horoball1)->radius) return -1; else if (((CuspNbhdHoroball *)horoball0)->radius > ((CuspNbhdHoroball *)horoball1)->radius) return +1; else return 0; } static void cull_duplicate_horoballs( Cusp *cusp, CuspNbhdHoroballList *aHoroballList) { int original_num_horoballs, i, j, k; Complex meridian, longitude, delta; Real cutoff_radius, mult; Boolean distinct; /* * Note the meridional and longitudinal translations. */ meridian = complex_real_mult(cusp->displacement_exp, cusp->translation[M]); longitude = complex_real_mult(cusp->displacement_exp, cusp->translation[L]); /* * Examine each horoball on the list. * If it's distinct from all previously examined horoballs, keep it. * Otherwise ignore it. * * We could implement this algorithm by copying the horoballs * we want to keep from the array aHoroballList->horoball onto * a new array. But it's simpler just to copy the array onto itself. * (This sounds distressing at first, but if you think it through * you'll realize that it's perfectly safe.) * * The index i keeps track of the horoball we're examining. * The index j keeps track of where we're writing it to. */ original_num_horoballs = aHoroballList->num_horoballs; for (i = 0, j = 0; j < original_num_horoballs; j++) { /* * If the j-th horoball is distinct from all previous ones, copy * it into the i-th position of the array. In practice, of course, * we compare it only to previous horoballs of the same radius. * We may assume that get_cusp_neighborhood_horoballs() has * already sorted the horoballs in order of increasing size. */ /* * Assume the j-th horoball is distinct from horoballs * 0 through i - 1, unless we discover otherwise. */ distinct = TRUE; /* * What is the smallest radius we should consider? */ cutoff_radius = aHoroballList->horoball[j].radius - DUPLICATE_RADIUS_EPSILON; /* * Start with horoball i - 1, and work downwards until either * we reach horoball 0, or the radii drop below the cutoff_radius. */ for (k = i; --k >= 0; ) { /* * If horoball k is too small, there is no need to examine * the remaining ones, which are even smaller. */ if (aHoroballList->horoball[k].radius < cutoff_radius) break; /* * Let delta be the difference between the center of j and * the center of k, modulo the Z + Z action of the group * of covering transformations of the cusp. */ delta = complex_minus(aHoroballList->horoball[j].center, aHoroballList->horoball[k].center); mult = floor(delta.imag / meridian.imag + 0.5); delta = complex_minus(delta, complex_real_mult(mult, meridian)); mult = floor(delta.real / longitude.real + 0.5); delta = complex_minus(delta, complex_real_mult(mult, longitude)); /* * If the distance between the centers of horoballs j and k is * less than the radius, then the horoballs must be equivalent. */ if (complex_modulus(delta) < cutoff_radius) { distinct = FALSE; break; } } if (distinct == TRUE) { aHoroballList->horoball[i] = aHoroballList->horoball[j]; i++; } else aHoroballList->num_horoballs--; } } CuspNbhdSegmentList *get_cusp_neighborhood_Ford_domain( CuspNeighborhoods *cusp_neighborhoods, int cusp_index) { Cusp *cusp; CuspNbhdSegmentList *theSegmentList; CuspNbhdSegment *next_segment; Tetrahedron *tet, *nbr_tet; Complex (*x)[4][4]; Boolean (*in_use)[4]; VertexIndex v, nbr_v, u, nbr_u, w[3]; Orientation h, nbr_h; FaceIndex f, nbr_f; Permutation gluing; int i; Complex corner[3], delta, inward_normal, offset, p; Real length, tilt, a[2], b[2], c[2], det; /* * Find the requested Cusp. */ cusp = find_cusp(cusp_neighborhoods->its_triangulation, cusp_index); /* * Allocate the wrapper for the array. */ theSegmentList = NEW_STRUCT(CuspNbhdSegmentList); /* * We don't know ahead of time exactly how many CuspNbhdSegments * we'll need. Torus cusps report each segment once, but Klein * bottle cusps report each segment twice, once for each sheet. * * To get an upper bound on the number of segments, * assume all cusps are Klein bottle cusps. * * n tetrahedra * * 4 vertices/tetrahedron * * 2 triangles/vertex (left_handed and right_handed) * * 3 sides/triangle * / 2 Ford edges/side (no need to draw each edge twice) * * = 12n Ford edges */ theSegmentList->segment = NEW_ARRAY(12*cusp_neighborhoods->its_triangulation->num_tetrahedra, CuspNbhdSegment); /* * Keep a pointer to the first empty CuspNbhdSegment. */ next_segment = theSegmentList->segment; /* * Compute the Ford domain's vertices. */ for (tet = cusp_neighborhoods->its_triangulation->tet_list_begin.next; tet != &cusp_neighborhoods->its_triangulation->tet_list_end; tet = tet->next) { x = tet->cusp_nbhd_position->x; in_use = tet->cusp_nbhd_position->in_use; for (v = 0; v < 4; v++) { /* * If this isn't the cusp the user wants, ignore it. */ if (tet->cusp[v] != cusp) continue; for (h = 0; h < 2; h++) /* h = right_handed, left_handed */ { if (in_use[h][v] == FALSE) continue; /* * There are at least two ways to locate the Ford vertex. * * (1) Use Theorem 3.1 of * * M. Sakuma and J. Weeks, The generalized tilt * formula, Geometriae Dedicata 55 (115-123) 1995, * * which states that the Euclidean distance in the * cusp from (the projection of) the Ford vertex * to a side of the enclosing triangle equals the * tilt on that side. (Or better yet, see the * preprint version of the article, which has a lot * more pictures and fuller explanations.) * * (2) Write down the equations for the three planes * which lie halfway between the cusp at infinity * and the cusp at each of the three remaining ideal * vertices. Each such plane appears at a Euclidean * hemisphere. Subtracting the equations for two * such hemispheres gives a linear equation, and * two such linear equations may be solved * simultaneously to locate the Ford vertex. * * Either of the above approaches should work fine. * Here we choose approach (1) because it looks a tiny * bit simpler numerically. */ /* * Label the triangles corners w[0], w[1] and w[2], * going counterclockwise around the triangle. * * w[2] * / \ * / \ * / \ * w[0]-------w[1] */ w[0] = !v; if (h == right_handed) { w[1] = remaining_face[w[0]][v]; w[2] = remaining_face[v][w[0]]; } else { w[1] = remaining_face[v][w[0]]; w[2] = remaining_face[w[0]][v]; } /* * Record the triangle's corners. */ for (i = 0; i < 3; i++) corner[i] = complex_real_mult(cusp->displacement_exp, x[h][v][w[i]]); /* * w[2] * / \ * ------/---*--\------- * / \ * w[0]-------w[1] * * The Ford vertex lies on a line parallel to a side of * the triangle at a distance "tilt" away (by Theorem 3.1 * of Sakuma & Weeks). Find the equations of such lines * (the third is redundant -- it could perhaps be used * to enhance accuracy if desired). */ for (i = 0; i < 2; i++) { /* * Make yourself a sketch as you follow along. */ delta = complex_minus(corner[(i+1)%3], corner[i]); inward_normal.real = delta.imag; inward_normal.imag = -delta.real; length = complex_modulus(inward_normal); tilt = tet->tilt[w[(i+2)%3]]; offset = complex_real_mult(tilt/length, inward_normal); p = complex_plus(corner[i], offset); /* * The equation of the desired line is * * y - p.imag delta.imag * ---------- = ---------- * x - p.real delta.real * * Cross multiply to get * * delta.imag * x - delta.real * y * = delta.imag * p.real - delta.real * p.imag * * This last equation also has a natural cross product * interpretation: delta X (x,y) = p X (x,y). * * Record the equation as ax + by = c. */ a[i] = delta.imag; b[i] = -delta.real; c[i] = delta.imag * p.real - delta.real * p.imag; } /* * Solve the matrix equation * * ( a[0] b[0] ) (x) = (c[0]) * ( a[1] b[1] ) (y) (c[1]) * => * (x) = _1_ ( b[1] -b[0] ) (c[0]) * (y) det (-a[1] a[0] ) (c[1]) */ det = a[0]*b[1] - a[1]*b[0]; FORD_VERTEX(x,h,v).real = (b[1]*c[0] - b[0]*c[1]) / det; FORD_VERTEX(x,h,v).imag = (a[0]*c[1] - a[1]*c[0]) / det; } } } /* * Record the Ford domain edges. */ for (tet = cusp_neighborhoods->its_triangulation->tet_list_begin.next; tet != &cusp_neighborhoods->its_triangulation->tet_list_end; tet = tet->next) { x = tet->cusp_nbhd_position->x; in_use = tet->cusp_nbhd_position->in_use; for (v = 0; v < 4; v++) { /* * If this isn't the cusp the user wants, ignore it. */ if (tet->cusp[v] != cusp) continue; for (h = 0; h < 2; h++) /* h = right_handed, left_handed */ { if (in_use[h][v] == FALSE) continue; for (f = 0; f < 4; f++) { if (f == v) continue; gluing = tet->gluing[f]; nbr_tet = tet->neighbor[f]; nbr_f = EVALUATE(gluing, f); /* * We want to report each segment only once, so we * make the (arbitrary) convention that we report * a segment only from the Tetrahedron whose address * in memory is less. In the case of a Tetrahedron * glued to itself, we report it from the lower * FaceIndex. */ if (tet > nbr_tet || (tet == nbr_tet && f > nbr_f)) continue; /* * Don't report Ford edges dual to 2-cells which are * part of the arbitrary subdivision of the canonical * cell decomposition into tetrahdra. (They'd have * length zero anyway, but we want to be consistent * with how we report the triangulation. We rely on * the fact that proto_canonize() has computed the * tilts and left them in place. The sum of the tilts * will never be positive for a subdivision of the * canonical cell decomposition. If it's close to * zero, ignore the Ford edge dual to that face. */ if (tet->tilt[f] + nbr_tet->tilt[nbr_f] > -CONCAVITY_EPSILON) continue; /* * This edge has passed all its tests, so record it. * Keep in mind that the coordinate systems in * neighboring Tetrahedra may differing by translations. */ nbr_v = EVALUATE(gluing, v); nbr_h = (parity[gluing] == orientation_preserving) ? h : !h; next_segment->endpoint[0] = FORD_VERTEX( tet->cusp_nbhd_position->x, h, v); next_segment->endpoint[1] = FORD_VERTEX(nbr_tet->cusp_nbhd_position->x, nbr_h, nbr_v); /* * The segment indices are currently used only * for the triangulation, not the Ford domain. */ next_segment->start_index = -1; next_segment->middle_index = -1; next_segment->end_index = -1; /* * Compensate for the (possibly) translated * coordinate systems. Compare the position of * a vertex u as seen by tet and nbr_tet. */ u = remaining_face[v][f]; nbr_u = EVALUATE(gluing, u); next_segment->endpoint[1] = complex_plus ( next_segment->endpoint[1], complex_real_mult ( cusp->displacement_exp, complex_minus ( tet->cusp_nbhd_position->x[ h][ v][ u], nbr_tet->cusp_nbhd_position->x[nbr_h][nbr_v][nbr_u] ) ) ); /* * Move on. */ next_segment++; } } } } /* * How many segments did we find? * * (ANSI C will subtract the pointers correctly, automatically * dividing by sizeof(CuspNbhdSegment).) */ theSegmentList->num_segments = next_segment - theSegmentList->segment; /* * Did we find more segments than we had allocated space for? * This should be impossible, but it doesn't hurt to check. */ if (theSegmentList->num_segments > 12*cusp_neighborhoods->its_triangulation->num_tetrahedra) uFatalError("get_cusp_neighborhood_Ford_domain", "cusp_neighborhoods"); return theSegmentList; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/cusp_shapes.c000644 000765 000024 00000042572 12377774107 021476 0ustar00babstaff000000 000000 /* * cusp_shapes.c * * This file provides the function * * void compute_cusp_shapes(Triangulation *manifold, * FillingStatus which_structure); * * which computes the shape of each unfilled cusp. The shape of an * orientable cusp is defined to be the ratio of the complex numbers * representing the longitudinal and meridional translations * (i.e. longitude/meridian). The shape of a nonorientable cusp is * defined to be the shape of the cusp's orientation double cover; * it is always pure imaginary. (Another reasonable definition for * the shape of a nonorientable cusp would be to divide the shape * of the orientation double cover by two, to correspond more closely * to the geometry of the nonorientable cusp's fundamental domain, * but I decided not to do this.) * * compute_cusp_shapes() computes the cusp shapes using the which_structure * (initial or current) hyperbolic structure, and stores each computed cusp * shape in the cusp_shape[which_structure] field of the Cusp data structure. * * To estimate the computed cusp shape's precision, compute_cusp_shapes() * computes the cusp shape using both the ultimate and penultimate values of * the Tetrahedron shapes. The number of digits to which the answers agree * is stored in the shape_precision[which_structure] field of the Cusp data * structure. * * do_Dehn_filling() calls compute_cusp_shapes() to maintain correct values * in the cusp_shape[current] field of each unfilled cusp whenever a * hyperbolic structure is present. find_complete_hyperbolic_structure() * takes responsibility for copying the original shape of each cusp into * the cusp_shape[initial] field. * * Cusp shapes are computed iff manifold->solution_type[which_structure] * is geometric_solution, nongeometric_solution, flat_solution, or * (tentatively) other_solution. For other solution types (degenerate_solution, * etc.) all cusp shapes are set to zero. * * Technical note: with the usual orientation conventions for the * longitude and meridian, we must view the cusp from the fat part * of the manifold looking out towards infinity in order to have the * imaginary part of the cusp shape be positive. The code * in compute_translation() views the cusp from infinity looking in * towards the fat part of the manifold (as usual), and then * compute_one_cusp_shape() takes the complex conjugate of the shape * at the very end. * * The function shortest_cusp_basis() in shortest_cusp_basis.c converts * the (meridian, longitude) basis to the (shortest, second shortest) * basis. cusp_modulus() uses the latter to compute the cusp modulus * as (second shortest translation)/(shortest translation). * * 96/9/27 Added the which_structure parameter to compute_cusp_shapes() * so it can compute the cusp shapes for either the initial (complete) * or the current (filled) hyperbolic structure. Previously it used only * the current structure. */ #include "kernel.h" #include "kernel_namespace.h" static void compute_the_cusp_shapes(Triangulation *manifold, FillingStatus which_structure); static void set_all_shapes_to_zero(Triangulation *manifold, FillingStatus which_structure); static void compute_one_cusp_shape(Triangulation *manifold, Cusp *cusp, FillingStatus which_structure); static void compute_translation(PositionedTet *initial_ptet, PeripheralCurve which_curve, TraceDirection which_direction, Complex translation[2], FillingStatus which_structure); static PositionedTet find_start(Triangulation *manifold, Cusp *cusp); void compute_cusp_shapes( Triangulation *manifold, FillingStatus which_structure) { /* * If we have some reasonable (or semi-reasonable) hyperbolic * structure, then compute the cusp shapes. Otherwise, fill in * all shapes with zeros. */ switch (manifold->solution_type[which_structure]) { case geometric_solution: case nongeometric_solution: case flat_solution: case other_solution: /* we'll give the cusps of other_solution a try */ /* other_solution can be moved below if its */ /* cusp shapes can't be computed meaningfully */ compute_the_cusp_shapes(manifold, which_structure); break; case not_attempted: case degenerate_solution: case no_solution: set_all_shapes_to_zero(manifold, which_structure); break; } } static void compute_the_cusp_shapes( Triangulation *manifold, FillingStatus which_structure) { Cusp *cusp; /* * Call compute_one_cusp_shape() for each unfilled cusp. */ for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) if ( which_structure == initial || (which_structure == current && cusp->is_complete)) compute_one_cusp_shape(manifold, cusp, which_structure); else { cusp->cusp_shape[which_structure] = Zero; cusp->shape_precision[which_structure] = 0; } } static void set_all_shapes_to_zero( Triangulation *manifold, FillingStatus which_structure) { Cusp *cusp; for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) { cusp->cusp_shape[which_structure] = Zero; cusp->shape_precision[which_structure] = 0; } } static void compute_one_cusp_shape( Triangulation *manifold, Cusp *cusp, FillingStatus which_structure) { PositionedTet initial_ptet; TraceDirection direction[2]; /* direction[M/L] */ Complex translation[2][2], /* translation[M/L][ultimate/penultimate] */ shape[2]; /* shape[ultimate/penultimate] */ int i; /* * Compute the longitudinal and meridional translations, and * divide them to get the cusp shape. * * Do parallel computations for the ultimate and penultimate shapes, * to estimate the accuracy of the final answer. */ /* * Find and position a tetrahedron so that the near edge of the top * vertex intersects both the meridian and the longitude. */ initial_ptet = find_start(manifold, cusp); for (i = 0; i < 2; i++) /* which curve */ { /* * Decide whether the meridian and longitude cross the near edge of the * top vertex in a forwards or backwards direction. */ direction[i] = (initial_ptet.tet->curve[i][initial_ptet.orientation] [initial_ptet.bottom_face] [initial_ptet.near_face] > 0) ? trace_forwards: trace_backwards; /* * Compute the translation. */ compute_translation(&initial_ptet, i, direction[i], translation[i], which_structure); } /* * Compute the cusp shape. */ for (i = 0; i < 2; i++) /* i = ultimate, penultimate */ shape[i] = complex_div(translation[L][i], translation[M][i]); /* will handle division by Zero correctly */ /* * Record the cusp shape and its accuracy. */ cusp->cusp_shape[which_structure] = shape[ultimate]; cusp->shape_precision[which_structure] = complex_decimal_places_of_accuracy(shape[ultimate], shape[penultimate]); /* * Adjust for the fact that the meridian and/or the longitude may have * been traced backwards. */ if (direction[M] != direction[L]) { cusp->cusp_shape[which_structure].real = - cusp->cusp_shape[which_structure].real; cusp->cusp_shape[which_structure].imag = - cusp->cusp_shape[which_structure].imag; } /* * As explained at the top of this file, the usual convention for the * cusp shape requires viewing the cusp from the fat part of * the manifold looking out, rather than from the cusp looking in, as * in done in the rest of SnapPea. For this reason, we must take the * complex conjugate of the final cusp shape. */ cusp->cusp_shape[which_structure].imag = - cusp->cusp_shape[which_structure].imag; } static void compute_translation( PositionedTet *initial_ptet, PeripheralCurve which_curve, TraceDirection which_direction, Complex translation[2], /* returns translations based on ultimate */ /* and penultimate shapes */ FillingStatus which_structure) { PositionedTet ptet; int i, initial_strand, strand, *this_vertex, near_strands, left_strands; Complex left_endpoint[2], /* left_endpoint[ultimate/penultimate] */ right_endpoint[2], /* right_endpoint[ultimate/penultimate] */ old_diff, new_diff, rotation; /* * Place the near edge of the top vertex of the initial_ptet in the * complex plane with its left endpoint at zero and its right endpoint at one. * Trace the curve which_curve in the direction which_direction, using the * shapes of the ideal tetrahedra to compute the position of endpoints of * each edge we cross. When we return to our starting point in the manifold, * the position of the left endpoint (or the position of the right endpoint * minus one) will tell us the translation. * * Note that we are working in the orientation double cover of the cusp. * * Here's how we keep track of where we are. At each step, we are always * at the near edge of the top vertex (i.e. the truncated vertex opposite * the bottom face) of the PositionedTet ptet. The curve (i.e. the * meridian or longitude) may cross that edge several times. The variable * "strand" keeps track of which intersection we are at; 0 means we're at * the strand on the far left, 1 means we're at the next strand, etc. */ ptet = *initial_ptet; initial_strand = 0; strand = initial_strand; for (i = 0; i < 2; i++) /* i = ultimate, penultimate */ { left_endpoint[i] = Zero; right_endpoint[i] = One; } do { /* * Note the curve's intersection numbers with the near side and left side. */ this_vertex = ptet.tet->curve[which_curve][ptet.orientation][ptet.bottom_face]; near_strands = this_vertex[ptet.near_face]; left_strands = this_vertex[ptet.left_face]; /* * If we are tracing the curve backwards, negate the intersection numbers * so the rest of compute_translation() can enjoy the illusion that we * are tracing the curve forwards. */ if (which_direction == trace_backwards) { near_strands = - near_strands; left_strands = - left_strands; } /* * Does the current strand bend to the left or to the right? */ if (strand < FLOW(near_strands, left_strands)) { /* * The current strand bends to the left. */ /* * The left_endpoint remains fixed. * Update the right_endpoint. * * The plan is to compute the vector old_diff which runs * from left_endpoint to right_endpoint, multiply it by the * complex edge parameter to get the vector new_diff which * runs from left_endpoint to the new value of right_endpoint, * and then add new_diff to left_endpoint to get the new * value of right_endpoint itself. * * Note that the complex edge parameters are always expressed * relative to the right_handed Orientation, so if we are * viewing this Tetrahedron relative to the left_handed * Orientation, we must take the conjugate-inverse of the * edge parameter. */ for (i = 0; i < 2; i++) /* i = ultimate, penultimate */ { old_diff = complex_minus(right_endpoint[i], left_endpoint[i]); rotation = ptet.tet->shape[which_structure]->cwl[i][edge3_between_faces[ptet.near_face][ptet.left_face]].rect; if (ptet.orientation == left_handed) { rotation = complex_div(One, rotation); /* invert . . . */ rotation.imag = - rotation.imag; /* . . . and conjugate */ } new_diff = complex_mult(old_diff, rotation); right_endpoint[i] = complex_plus(left_endpoint[i], new_diff); } /* * strand remains unchanged. */ /* * Move the PositionedTet onward, following the curve. */ veer_left(&ptet); } else { /* * The current strand bends to the right. * * Proceed as above, but note that * * (1) We now divide by the complex edge parameter * instead of multiplying by it. * * (2) We must adjust the variable "strand". Some of the strands * from the near edge may be peeling off to the left (in which * case left_strands is negative), or some strands from the left * edge may be joining those from the near edge in passing to * the right edge (in which case left_strands is positive). * Either way, the code "strand += left_strands" is correct. */ for (i = 0; i < 2; i++) /* i = ultimate, penultimate */ { old_diff = complex_minus(left_endpoint[i], right_endpoint[i]); rotation = ptet.tet->shape[which_structure]->cwl[i][edge3_between_faces[ptet.near_face][ptet.right_face]].rect; if (ptet.orientation == left_handed) { rotation = complex_div(One, rotation); rotation.imag = - rotation.imag; } new_diff = complex_div(old_diff, rotation); left_endpoint[i] = complex_plus(right_endpoint[i], new_diff); } strand += left_strands; veer_right(&ptet); } } while ( ! same_positioned_tet(&ptet, initial_ptet) || strand != initial_strand); /* * Write the computed translations, and return. */ for (i = 0; i < 2; i++) /* i = ultimate, penultimate */ translation[i] = left_endpoint[i]; } static PositionedTet find_start( Triangulation *manifold, Cusp *cusp) { Tetrahedron *tet; VertexIndex vertex; Orientation orientation; FaceIndex side; PositionedTet ptet; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (vertex = 0; vertex < 4; vertex++) { if (tet->cusp[vertex] != cusp) continue; for (orientation = right_handed; orientation <= left_handed; orientation++) for (side = 0; side < 4; side++) if (side != vertex && tet->curve[M][orientation][vertex][side] != 0 && tet->curve[L][orientation][vertex][side] != 0) { /* * Record the current position of the Tetrahedron in * a PositionedTet structure . . . */ ptet.tet = tet; ptet.bottom_face = vertex; ptet.near_face = side; if (orientation == right_handed) { ptet.left_face = remaining_face[ptet.bottom_face][ptet.near_face]; ptet.right_face = remaining_face[ptet.near_face][ptet.bottom_face]; } else { ptet.left_face = remaining_face[ptet.near_face][ptet.bottom_face]; ptet.right_face = remaining_face[ptet.bottom_face][ptet.near_face]; } ptet.orientation = orientation; /* * . . . and return it. */ return ptet; } } /* * The program should never get to this point. */ uFatalError("find_start", "cusp_shapes"); /* * The compiler would like a return value, even though * we never return from the uFatalError() call. * The Metrowerks compiler would, in addition, like * the data to be initialized before use. */ ptet.tet = NULL; ptet.near_face = 0; ptet.left_face = 0; ptet.right_face = 0; ptet.bottom_face = 0; ptet.orientation = unknown_orientation; return ptet; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/cusps.c000644 000765 000024 00000026163 12377774107 020314 0ustar00babstaff000000 000000 /* * cusps.c * * This file contains the functions * * void create_cusps(Triangulation *manifold); * void create_fake_cusps(Triangulation *manifold); * void count_cusps(Triangulation *manifold); * Boolean mark_fake_cusps(Triangulation *manifold); * * create_cusps() is used within the kernel to assign Cusp data * structures to Triangulations. It assumes the neighbor and gluing * fields have been set (all other fields are optional). It assigns * cusp indices, but does not install peripheral curves, determine * the CuspTopologies, or count the cusps. You should call * peripheral_curves() to install the peripheral curves and determine * the CuspTopologies, then call count_cusps() to set num_cusps, * num_or_cusps and num_nonor_cusps. * * create_fake_cusps() is used within the kernel to assign Cusp data * structures to the "fake cusps" corresponding to finite vertices. * It assumes fake cusps are indicated by tet->cusp[v] fields of NULL. * The fake cusps are numbered -1, -2, etc. As explained in the * documentation at the top of finite_vertices.c, finite vertices use * only the is_finite, index, prev and next fields of the Cusp data * structure. create_fake_cusps() does not disturb the real cusps or * the non-NULL tet->cusp[v] fields. * * count_cusps() counts the Cusps of each CuspTopology, and sets * manifold->num_cusps, manifold->num_or_cusps and manifold->num_nonor_cusps. * * mark_fake_cusps() distinguishes real cusps from fake cusps * ( = finite vertices) by computing the Euler characteristic. * Sets is_finite to TRUE for fake cusps, and renumbers all cusps so that * real cusps have consecutive nonnegative indices beginning at 0 and * fake cusps have consecutive negative indices beginning at -1. * Returns TRUE if fake cusps are present, FALSE otherwise. */ #include "kernel.h" #include "kernel_namespace.h" typedef struct { Tetrahedron *tet; VertexIndex v; } IdealVertex; static void compute_cusp_Euler_characteristics(Triangulation *manifold); void create_cusps( Triangulation *manifold) { int count; Tetrahedron *tet; VertexIndex v; /* * Make sure no Cusps are present, and everything is neat and tidy. */ error_check_for_create_cusps(manifold); /* * The variable "count" will keep track of the next index * to be assigned. The first Cusp we create will have * index 0, the next will have 1, and so on. */ count = 0; /* * We look at each vertex of each Tetrahedron, and whenever we * encounter a vertex with no assigned Cusp, we create a Cusp * for it and recursively assign it to neighboring ideal vertices. */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (v = 0; v < 4; v++) if (tet->cusp[v] == NULL) create_one_cusp(manifold, tet, FALSE, v, count++); } void error_check_for_create_cusps( Triangulation *manifold) { Tetrahedron *tet; VertexIndex v; if (manifold->num_cusps != 0 || manifold->num_or_cusps != 0 || manifold->num_nonor_cusps != 0 || manifold->cusp_list_begin.next != &manifold->cusp_list_end) uFatalError("error_check_for_create_cusps", "cusps"); for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (v = 0; v < 4; v++) if (tet->cusp[v] != NULL) uFatalError("error_check_for_create_cusps", "cusps"); } void create_fake_cusps( Triangulation *manifold) { int count; Tetrahedron *tet; VertexIndex v; /* * The variable "count" will keep track of the (negative) index * most recently assigned. The first finite vertex we create * will have index -1, the next will have -2, and so on. */ count = 0; /* * We look at each vertex of each Tetrahedron, and whenever we * encounter an ideal vertex with no assigned Cusp, we create a Cusp * for it and assign it recursively to neighboring ideal vertices. */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (v = 0; v < 4; v++) if (tet->cusp[v] == NULL) create_one_cusp(manifold, tet, TRUE, v, --count); } void create_one_cusp( Triangulation *manifold, Tetrahedron *tet, Boolean is_finite, VertexIndex v, int cusp_index) { Cusp *cusp; IdealVertex *queue; int queue_first, queue_last; Tetrahedron *tet1, *nbr; VertexIndex v1, nbr_v; FaceIndex f; /* * Create the cusp, add it to the list, and set * the is_finite and index fields. */ cusp = NEW_STRUCT(Cusp); initialize_cusp(cusp); INSERT_BEFORE(cusp, &manifold->cusp_list_end); cusp->is_finite = is_finite; cusp->index = cusp_index; /* * We don't set the topology, is_complete, m, l, holonomy, * cusp_shape or shape_precision fields. * * For "real" cusps the calling routine may * * (1) call peripheral_curves() to set the cusp->topology, * * (2) keep the default values of cusp->is_complete, * cusp->m and cusp->l as set by initialize_cusp(), and * * (3) let the holonomy and cusp_shape be computed automatically * when hyperbolic structure is computed. * * Alternatively, the calling routine may set these fields in other * ways, as it sees fit. * * If we were called by create_fake_cusps(), then the above fields * are all irrelevant and ignored. */ /* * Set the tet->cusp field at all vertices incident to the new cusp. */ /* * Allocate space for a queue of pointers to the IdealVertices. * Each IdealVertex will appear on the queue at most once, so an * array of length 4 * manifold->num_tetrahedra will suffice. */ queue = NEW_ARRAY(4 * manifold->num_tetrahedra, IdealVertex); /* * Set the cusp of the given IdealVertex... */ tet->cusp[v] = cusp; /* * ...and put it on the queue. */ queue_first = 0; queue_last = 0; queue[0].tet = tet; queue[0].v = v; /* * Start processing the queue. */ do { /* * Pull an IdealVertex off the front of the queue. */ tet1 = queue[queue_first].tet; v1 = queue[queue_first].v; queue_first++; /* * Look at the three neighboring IdealVertices. */ for (f = 0; f < 4; f++) { if (f == v1) continue; nbr = tet1->neighbor[f]; nbr_v = EVALUATE(tet1->gluing[f], v1); /* * If the neighbor's cusp hasn't been set... */ if (nbr->cusp[nbr_v] == NULL) { /* * ...set it... */ nbr->cusp[nbr_v] = cusp; /* * ...and add it to the end of the queue. */ ++queue_last; queue[queue_last].tet = nbr; queue[queue_last].v = nbr_v; } } } while (queue_first <= queue_last); /* * Free the memory used for the queue. */ my_free(queue); } void count_cusps( Triangulation *manifold) { Cusp *cusp; manifold->num_cusps = 0; manifold->num_or_cusps = 0; manifold->num_nonor_cusps = 0; for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) { manifold->num_cusps++; switch (cusp->topology) { case torus_cusp: manifold->num_or_cusps++; break; case Klein_cusp: manifold->num_nonor_cusps++; break; default: uFatalError("count_cusps", "cusps"); } } } Boolean mark_fake_cusps( Triangulation *manifold) { int real_cusp_count, fake_cusp_count; Cusp *cusp; compute_cusp_Euler_characteristics(manifold); real_cusp_count = 0; fake_cusp_count = 0; for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) switch (cusp->euler_characteristic) { case 0: cusp->is_finite = FALSE; cusp->index = real_cusp_count++; break; case 2: cusp->is_finite = TRUE; cusp->index = --fake_cusp_count; break; default: uFatalError("mark_fake_cusps", "cusps"); } return (fake_cusp_count < 0); } static void compute_cusp_Euler_characteristics( Triangulation *manifold) { Cusp *cusp; EdgeClass *edge; Tetrahedron *tet; VertexIndex v, v0, v1; /* * Initialize all Euler characteristics to zero. */ for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) cusp->euler_characteristic = 0; /* * It'll be easier to count the edges twice (once from each side) * so compute twice the Euler characteristic and divide by two * at the end. */ /* * Count the vertices in the triangulation of the boundary, * which come from edges in the manifold itself. */ for (edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) { tet = edge->incident_tet; v0 = one_vertex_at_edge[edge->incident_edge_index]; v1 = other_vertex_at_edge[edge->incident_edge_index]; tet->cusp[v0]->euler_characteristic += 2; tet->cusp[v1]->euler_characteristic += 2; } /* * Count the edges in the triangulation of the boundary, * which come from faces in the manifold itself. */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (v = 0; v < 4; v++) tet->cusp[v]->euler_characteristic -= 3; /* * Count the faces in the triangulation of the boundary, * which come from tetrahedra in the manifold itself. */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (v = 0; v < 4; v++) tet->cusp[v]->euler_characteristic += 2; /* * Divide by two (cf. above). */ for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) { if (cusp->euler_characteristic % 2 != 0) uFatalError("compute_cusp_Euler_characteristics", "cusps"); cusp->euler_characteristic /= 2; } } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/Dehn_coefficients.c000644 000765 000024 00000004715 12377774107 022555 0ustar00babstaff000000 000000 /* * This file contains the functions * * Boolean all_Dehn_coefficients_are_integers(Triangulation *manifold); * Boolean Dehn_coefficients_are_integers(Cusp *cusp); * * Boolean all_Dehn_coefficients_are_relatively_prime_integers(Triangulation *manifold); * Boolean Dehn_coefficients_are_relatively_prime_integers(Cusp *cusp); * * Boolean all_cusps_are_complete(Triangulation *manifold); * Boolean all_cusps_are_filled(Triangulation *manifold); * * which are used within the kernel to test whether Dehn filling coefficients * are (relatively prime) integers. */ #include "kernel.h" #include "kernel_namespace.h" Boolean all_Dehn_coefficients_are_integers( Triangulation *manifold) { Cusp *cusp; for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) if (Dehn_coefficients_are_integers(cusp) == FALSE) return FALSE; return TRUE; } Boolean all_Dehn_coefficients_are_relatively_prime_integers( Triangulation *manifold) { Cusp *cusp; for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) if (Dehn_coefficients_are_relatively_prime_integers(cusp) == FALSE) return FALSE; return TRUE; } Boolean Dehn_coefficients_are_integers( Cusp *cusp) { return ( cusp->is_complete == TRUE || ( cusp->m == (Real)(int)cusp->m && cusp->l == (Real)(int)cusp->l ) ); } Boolean Dehn_coefficients_are_relatively_prime_integers( Cusp *cusp) { return ( cusp->is_complete == TRUE || ( cusp->m == (Real)(int)cusp->m && cusp->l == (Real)(int)cusp->l && gcd((long int)cusp->m, (long int)cusp->l) == 1 ) ); } Boolean all_cusps_are_complete( Triangulation *manifold) { Cusp *cusp; for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) if (cusp->is_complete == FALSE) return FALSE; return TRUE; } Boolean all_cusps_are_filled( Triangulation *manifold) { Cusp *cusp; for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) if (cusp->is_complete == TRUE) return FALSE; return TRUE; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/double_SnapPy.h000644 000765 000024 00000003233 12377774107 021721 0ustar00babstaff000000 000000 #ifndef _DOUBLE_SNAPPY_ #define _DOUBLE_SNAPPY_ #include "kernel_namespace.h" typedef double Real; /* * This is used to work around a Cython bug which prevents declaring * arrays of C++ objects. See SnapPy.pxi. */ typedef double Real_struct; #include "end_namespace.h" #define Real_from_string(x) (atof((char *)x)) #define Real_write(real, buffer, size, digits) (snprintf(buffer, size, "%e", real)) #define REAL_DIG DBL_DIG #define REAL_MAX DBL_MAX #define REAL_EPSILON DBL_EPSILON #define default_vertex_epsilon 1.0e-8 #define det_error_epsilon 1.0e-9 #define PI 3.14159265358979323846 #define TWO_PI 6.28318530717958647693 #define FOUR_PI 12.56637061435917295385 #define PI_OVER_2 1.57079632679489661923 #define PI_OVER_3 1.04719755119659774615 #define PI_SQUARED_BY_2 19.7392088021787172376 #define THREE_PI_OVER_2 4.71238898038468985769 #define ROOT_3_OVER_2 0.86602540378443864676 #define ROOT_3 1.73205080756887729352 #define ROOT_2 1.41421356237309504880 #define LOG_TWO_PI 1.83787706640934548356 /* Constants used in various kernel modules. */ /* Dirichlet.h */ #define MATRIX_EPSILON 1e-5 /* Dirichlet.cpp */ #define FIXED_BASEPOINT_EPSILON 1e-6 /* Dirichlet_construction.cpp */ #define DIRICHLET_ERROR_EPSILON 1e-4 #define HYPERIDEAL_EPSILON 1e-3 #define VERIFY_EPSILON 1e-4 #define DEVIATION_EPSILON 1e-3 /* Dirichlet_extras.cpp */ #define DIST_EPSILON 1e-3 #define EDGE_EPSILON 1e-3 #define IDEAL_EPSILON 4e-7 #define HALF_TWIST_EPSILON 1e-2 #define PI_EPSILON 1e-1 #define SOLID_ANGLE_EPSILON 1e-4 #endif regina-4.96/engine/snappea/kernel/dual_one_skeleton_curve.h000644 000765 000024 00000007524 12377774107 024062 0ustar00babstaff000000 000000 /* * dual_one_skeleton_curve.h * * This file defines the data structure used to represent * a simple closed curve in the 1-skeleton of a Triangulation's * dual complex. * * The 0-skeleton of the Triangulation's dual complex consists * of one vertex in the interior of each Tetrahedron. * * The 1-skeleton of the Triangulation's dual complex (the * "dual 1-skeleton") consists of one edge transverse to each * face of each Tetrahedron (more precisely, to each pair * of identified faces in the Triangulation). * * To specify a curve in the dual 1-skeleton, we specify the * 2-cells which it intersects in the original Triangulation. * Specifically, for each Tetrahedron we keep four Boolean * flags which say whether the given dual curve intersects * each of the Tetrahedron's four faces. * * Note that a dual curve is described in terms of a specific * Triangulation. If the Triangulation is modified, the * description of the dual curve becomes meaningless. * * The file SnapPea.h contains the "opaque typedef" * * typedef struct DualOneSkeletonCurve DualOneSkeletonCurve; * * which lets the UI declare and pass pointers to DualOneSkeletonCurves * without actually knowing what they are. This file provides the kernel * with the actual definition. */ #ifndef _dual_one_skeleton_curve_ #define _dual_one_skeleton_curve_ #include "SnapPea.h" #include "kernel_namespace.h" /* * An array of four Booleans represents the intersection * of a dual curve with the four faces of a given * Tetrahedron. The i-th Boolean is TRUE iff the dual * curve passes through the Tetrahedron's i-th face. */ typedef Boolean DualOneSkeletonCurvePiece[4]; /* * An array of DualOneSkeletonCurvePieces represents * a complete curve in the dual 1-skeleton. The i-th * element in the array describes the curve's intersection * with the Triangulation's i-th Tetrahedron. * * Note that this definition relies on the Tetrahedra * being consecutively indexed, e.g. by the kernel function * number_the_tetrahedra(). The numbering is that of * the indices rather than the position in the doubly- * linked list (normally the two will be the same, but * we don't assume this). */ struct DualOneSkeletonCurve { /* * tet_intersection will contain the address of * an array of n DualOneSkeletonCurvePieces, where n * is the number of Tetrahedra in the Triangulation. * tet_intersection[i][j] will be TRUE iff the dual * curve passes through face j of Tetrahedron i. */ DualOneSkeletonCurvePiece *tet_intersection; /* * Is this curve orientation_reversing or orientation_preserving? */ MatrixParity parity; /* * The length field will contain the complex length of * the geodesic in the homotopy class of the dual curve. * length[complete] and length[filled] give the length * relative to the complete and filled hyperbolic * structures, respectively. */ Complex length[2]; /* * The size field will contain the number * of segments in the curve. */ int size; /* * We'll be working with large numbers of DualOneSkeletonCurves, * many of which will be homotopic to each other, so for efficiency * in sorting them out we'll keep them on a binary tree, keyed by * complex length (i.e. keyed by length.real, with length.imag * considered in case of ties). The next_subtree field is used * locally for tree-handling operations to avoid doing recursions * on the system stack; the latter run the risk of stack/heap * collisions. */ DualOneSkeletonCurve *left_child, *right_child, *next_subtree; }; #include "end_namespace.h" #endif regina-4.96/engine/snappea/kernel/edge_classes.c000644 000765 000024 00000016776 12377774107 021611 0ustar00babstaff000000 000000 /* * edge_classes.c * * This file provides the functions * * void create_edge_classes(Triangulation *manifold); * void replace_edge_classes(Triangulation *manifold); * void orient_edge_classes(Triangulation *manifold); * * which are used within the kernel. * * create_edge_classes() adds EdgeClasses to a partially * constructed manifold which does not yet have them. * It assumes the tet->neighbor and tet->gluing fields * contain correct values. * * replace_edge_classes() removes all EdgeClasses from a manifold * and adds fresh ones. replace_edge_classes() is typically called * by functions which would rather replace invalid EdgeClasses * at the end of an algorithm rather than try to maintain them * as they go along. * * orient_edge_classes() orients a neighborhood of each EdgeClass. * Relative to this orientation, each of the incident tetrahedra * will be seen as right_ or left_handed. * * The edges of a tetrahedron are indexed according to the following table: * * lies lies * edge between between * faces vertices * 0 0,1 2,3 * 1 0,2 1,3 * 2 0,3 1,2 * 3 1,2 0,3 * 4 1,3 0,2 * 5 2,3 0,1 * * orient_edge_classes() sets the field tet->edge_orientation[e] to be the * orientation of Tetrahedron tet as seen by EdgeClass tet->edge_class[e]. * In an oriented manifold, all edge_orientations will be right_handed. * * orient_edge_classes() should be called as soon as a Triangulation * is created, and functions which modify a Triangulation should * maintain the edge_orientation[] fields. * * As explained in the documentation at the top of orient.c, orient() * and orient_edge_classes() may be called in either order, but both * should be called. */ #include "kernel.h" #include "kernel_namespace.h" static void initialize_tet_edge_classes(Triangulation *manifold); static void create_one_edge_class(Triangulation *manifold, Tetrahedron *tet, EdgeIndex e); void create_edge_classes( Triangulation *manifold) { Tetrahedron *tet; EdgeIndex e; /* * First set tet->edge_class[] to NULL for all * edges of all Tetrahedra. */ initialize_tet_edge_classes(manifold); /* * Go down the list of Tetrahedra, and whenever * an edge is found with no EdgeClass, create one * for it. */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (e = 0; e < 6; e++) if (tet->edge_class[e] == NULL) create_one_edge_class(manifold, tet, e); } static void initialize_tet_edge_classes( Triangulation *manifold) { Tetrahedron *tet; EdgeIndex e; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (e = 0; e < 6; e++) tet->edge_class[e] = NULL; } static void create_one_edge_class( Triangulation *manifold, Tetrahedron *tet, EdgeIndex e) { EdgeClass *new_edge_class; FaceIndex front, back, temp; Permutation gluing; Tetrahedron *tet0; EdgeIndex e0; /* * Create the new EdgeClass and add it to the list. */ new_edge_class = NEW_STRUCT(EdgeClass); initialize_edge_class(new_edge_class); INSERT_BEFORE(new_edge_class, &manifold->edge_list_end); /* * Initialize the fields of the EdgeClass. */ new_edge_class->order = 0; new_edge_class->incident_tet = tet; new_edge_class->incident_edge_index = e; /* * Walk around the edge class, setting the tet->edge_class * field for each edge we encounter. */ front = one_face_at_edge[e]; back = other_face_at_edge[e]; tet0 = tet; e0 = e; do { /* * Set the edge_class pointer . . . */ tet->edge_class[e] = new_edge_class; /* * . . . increment new_edge_class->order . . . */ new_edge_class->order++; /* * . . . and move on to the next edge. */ gluing = tet->gluing[front]; tet = tet->neighbor[front]; temp = front; front = EVALUATE(gluing, back); back = EVALUATE(gluing, temp); e = edge_between_faces[front][back]; } while (tet != tet0 || e != e0); } void replace_edge_classes( Triangulation *manifold) { EdgeClass *dead_edge_class; /* * Remove all existing EdgeClasses . . . */ while (manifold->edge_list_begin.next != &manifold->edge_list_end) { dead_edge_class = manifold->edge_list_begin.next; REMOVE_NODE(dead_edge_class); my_free(dead_edge_class); } /* * . . . and add fresh ones. */ create_edge_classes(manifold); } void orient_edge_classes( Triangulation *manifold) { EdgeClass *edge; Tetrahedron *tet; EdgeIndex e; FaceIndex front, back, temp; Orientation relative_orientation; Permutation gluing; int count; /* * For each EdgeClass in the Triangulation . . . */ for (edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) { /* * Find an incident edge. */ tet = edge->incident_tet; e = edge->incident_edge_index; front = one_face_at_edge[e]; back = other_face_at_edge[e]; /* * View the incident Tetrahedron relative to the * right_handed Orientation. */ relative_orientation = right_handed; /* * We'll walk around the EdgeClass, setting * the Orientation of each incident edge. */ for (count = edge->order; --count >= 0; ) { /* * Set the edge_orientation of the present edge . . . */ tet->edge_orientation[e] = relative_orientation; /* * . . . and move on to the next edge. */ gluing = tet->gluing[front]; tet = tet->neighbor[front]; temp = front; front = EVALUATE(gluing, back); back = EVALUATE(gluing, temp); e = edge_between_faces[front][back]; /* * Change the relative_orientation iff the new * new Tetrahedron is oriented differently than * the old one. */ if (parity[gluing] == orientation_reversing) relative_orientation = ! relative_orientation; } /* * When we return to the initial Tetrahedron, * the relative_orientation should again be right_handed. * If it isn't, the triangulation defines an orbifold * with a cone-on-a-projective-plane at the center of * the current edge class. This error should be rare -- * in fact is should be possible only for hand-coded * Triangulations. */ if (relative_orientation != right_handed) { uAcknowledge("The triangulation has a cone-on-a-projective-plane singularity at the midpoint of an edge class."); uFatalError("orient_edge_classes", "edge_classes"); } } } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/end_namespace.h000644 000765 000024 00000000155 12377774107 021737 0ustar00babstaff000000 000000 /* * If you declared a namespace block in kernel_namespace.h then * you can close the block here. */ } } regina-4.96/engine/snappea/kernel/filling.c000644 000765 000024 00000021670 12377774107 020601 0ustar00babstaff000000 000000 /* * filling.c * * This file contains the functions * * Triangulation *fill_cusps(Triangulation *manifold, * Boolean fill_cusp[], * const char *new_name, * Boolean fill_all_cusps); * * Triangulation *fill_reasonable_cusps(Triangulation *manifold); * * Boolean cusp_is_fillable(Cusp *cusp); * Boolean is_closed_manifold(Triangulation *manifold); * * which the kernel provides to the UI. * * fill_cusps() permanently fills k of the cusps of an n-cusp manifold. * It returns an ideal Triangulation of the resulting (n - k)-cusp manifold. * * 99/06/04 Previous versions of fill_cusps() insisted that at least * one cusp be left unfilled. The current version allows all cusps * to be filled, in which case it produces a finite triangulation. * Warning: Most SnapPea functions insist on an ideal triangulation -- * the finite triagulation is provided mainly for writing to disk. * * Arguments: * * manifold is the original manifold. The Dehn filling * coefficients cusp->m and cusp->l specify how * each cusp is to be filled. * * fill_cusp says which cusps are to be filled. The cusp * of index i will be filled iff fill_cusp[i] is TRUE. * If fill_all_cusps (see below) is TRUE, then * fill_cusp is ignored and may be NULL. * * new_name provides the name for the new Triangulation. * * fill_all_cusps says whether to fill all the cusps, producing * a triangulation with finite vertices only. * Usually fill_all_cusps is FALSE. * * The UI should decide how to present fill_cusps() to the user. * Should all currently Dehn filled cusps be filled at once? * Should the user be presented with a list of check boxes to * specify which cusps to fill? Should cusps be filled one at a time? * My hope is that fill_cusps() is sufficiently general to support * whatever approach the UI developer prefers. * * Having said that, let me now mention fill_reasonable_cusps(), which * makes a decision about which cusps to fill, and then makes a call * to fill_cusp(). fill_reasonable_cusps() will fill all cusps which * have relatively prime Dehn filling coefficients, unless this would * leave no unfilled cusps, in which case it leaves cusp 0 unfilled. * It copies the name from the manifold being filled. * * cusp_is_fillable() determines whether an individual cusp is fillable. * * The original manifold is always left unaltered. * * The files subdivide.c, close_cusps.c, and remove_finite_vertices.c * document the algorithm in detail. */ #include "kernel.h" #include "kernel_namespace.h" static Boolean check_fill_cusp_array(Triangulation *manifold, Boolean fill_cusp[]); static Boolean cusp_is_fillable_x(Cusp *cusp); static Boolean no_cusps_to_be_filled(int num_cusps, Boolean fill_cusp[]); Triangulation *fill_cusps( Triangulation *manifold, Boolean fill_cusp[], const char *new_name, Boolean fill_all_cusps) { Triangulation *new_triangulation; Boolean at_least_one_cusp_is_left; Boolean *all_true; int i; /* * 95/10/1 JRW * The following algorithm works correctly even if no cusps are * to be filled, but we can speed it up a bit by simply copying * the Triangulation. */ if (fill_all_cusps == FALSE && no_cusps_to_be_filled(manifold->num_cusps, fill_cusp) == TRUE) { copy_triangulation(manifold, &new_triangulation); return new_triangulation; } /* * First let's do a little error checking on the fill_cusp[] array. */ if (fill_all_cusps == FALSE) { /* * Check that Dehn filling coefficients are relatively prime integers, * and also that at least one cusp is left unfilled. */ at_least_one_cusp_is_left = check_fill_cusp_array(manifold, fill_cusp); if (at_least_one_cusp_is_left == FALSE) uFatalError("fill_cusps", "filling"); } else { /* * Check that Dehn filling coefficients are relatively prime integers. */ all_true = NEW_ARRAY(manifold->num_cusps, Boolean); for (i = 0; i < manifold->num_cusps; i++) all_true[i] = TRUE; (void) check_fill_cusp_array(manifold, all_true); /* * Do NOT free all_true just yet. */ } /* * Subdivide the triangulation, introducing finite vertices. * Note that the original triangulation is left unharmed. */ new_triangulation = subdivide(manifold, new_name); /* * Close the Cusps specified in the fill_cusp[] array. */ close_cusps(new_triangulation, fill_all_cusps ? all_true : fill_cusp); /* * We're done with the all_true array. */ if (fill_all_cusps == TRUE) my_free(all_true); /* * Retriangulate with no finite vertices. */ if (fill_all_cusps == FALSE) remove_finite_vertices(new_triangulation); /* includes basic_simplification() */ else basic_simplification(new_triangulation); /* * If the old manifold had a hyperbolic structure, * try to find one for the new_triangulation as well. */ if (fill_all_cusps == FALSE && manifold->solution_type[complete] != not_attempted) { find_complete_hyperbolic_structure(new_triangulation); do_Dehn_filling(new_triangulation); /* * If the old manifold had a known Chern-Simons invariant, * pass it to the new_triangulation. */ if (manifold->CS_value_is_known == TRUE) { new_triangulation->CS_value_is_known = manifold->CS_value_is_known; new_triangulation->CS_value[ultimate] = manifold->CS_value[ultimate]; new_triangulation->CS_value[penultimate] = manifold->CS_value[penultimate]; /* * The solution_type may or may not be good enough to compute * the fudge factor, but we'll let compute_CS_fudge_from_value() * worry about that. */ compute_CS_fudge_from_value(new_triangulation); } } return new_triangulation; } Triangulation *fill_reasonable_cusps( Triangulation *manifold) { Boolean *fill_cusp; Cusp *cusp; int i; Boolean all_cusps_are_fillable; Triangulation *new_triangulation; /* * Allocate the fill_cusp[] array. */ fill_cusp = NEW_ARRAY(manifold->num_cusps, Boolean); /* * See which cusps are fillable. */ for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) fill_cusp[cusp->index] = cusp_is_fillable_x(cusp); /* * If all the cusps are fillable, leave cusp 0 unfilled. */ all_cusps_are_fillable = TRUE; for (i = 0; i < manifold->num_cusps; i++) if (fill_cusp[i] == FALSE) all_cusps_are_fillable = FALSE; if (all_cusps_are_fillable == TRUE) fill_cusp[0] = FALSE; /* * Call fill_cusps(). */ new_triangulation = fill_cusps(manifold, fill_cusp, manifold->name, FALSE); /* * Free the fill_cusp[] array. */ my_free(fill_cusp); /* * Done. */ return new_triangulation; } static Boolean check_fill_cusp_array( Triangulation *manifold, Boolean fill_cusp[]) { Boolean at_least_one_cusp_is_left; Cusp *cusp; at_least_one_cusp_is_left = FALSE; for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) if (fill_cusp[cusp->index]) { if (cusp_is_fillable_x(cusp) == FALSE) uFatalError("check_fill_cusp_array", "filling"); } else at_least_one_cusp_is_left = TRUE; return at_least_one_cusp_is_left; } Boolean cusp_is_fillable( /* For external use */ Triangulation *manifold, int cusp_index) { return cusp_is_fillable_x(find_cusp(manifold, cusp_index)); } static Boolean cusp_is_fillable_x( /* For internal use */ Cusp *cusp) { return( cusp->is_complete == FALSE && Dehn_coefficients_are_relatively_prime_integers(cusp) == TRUE); } static Boolean no_cusps_to_be_filled( int num_cusps, Boolean fill_cusp[]) { int i; for (i = 0; i < num_cusps; i++) if (fill_cusp[i] == TRUE) return FALSE; return TRUE; } Boolean is_closed_manifold( Triangulation *manifold) { return (all_cusps_are_filled(manifold) && all_Dehn_coefficients_are_relatively_prime_integers(manifold)); } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/find_cusp.c000644 000765 000024 00000002221 12377774107 021116 0ustar00babstaff000000 000000 /* * find_cusp.c * * This function provides the following utility for use within the kernel. * * Cusp *find_cusp(Triangulation *manifold, int cusp_index); * * The UI refers to cusps by their indices, because it doesn't know about * the Cusp data structure. When a kernel function receives a cusp_index, * it may call the function find_cusp() to convert the index to an actual * pointer to the corresponding Cusp data structure. If find_cusp() cannot * find a Cusp with the given cusp_index, it calls uFatalError(). */ #include "kernel.h" #include "kernel_namespace.h" Cusp *find_cusp( Triangulation *manifold, int cusp_index) { Cusp *cusp; for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) if (cusp->index == cusp_index) return cusp; /* * No Cusp with the given index was found. */ uFatalError("find_cusp", "find_cusp"); /* * The C++ compiler would like a return value, even though * we never return from the uFatalError() call. */ return NULL; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/finite_vertices.c000644 000765 000024 00000050134 12377774107 022334 0ustar00babstaff000000 000000 /* * finite_vertices.c * * Certain routines make temporary use of finite (as opposed to ideal) * vertices; e.g. they are used in triangulating a link complement, * in retriangulating a partially filled multicusp manifold, and in * splitting along a normal surface. SnapPea represents a finite vertex * as a cusp whose is_finite field is set to TRUE. Except for the * is_finite, index, prev and next fields, all other fields of the Cusp * data structure are ignored. The indices are negative integers. * Functions which do not use finite vertices may safely ignore the * is_finite field, and assume no finite vertices are present. * Finite vertices are never counted in the num_cusps, num_or_cusps, * or num_nonor_cusps fields of a Triangulation. * * This file contains the function * * void remove_finite_vertices(Triangulation *manifold); * * which is used within the kernel to retriangulate the manifold * to remove the finite vertices. If manifold has no real cusps, * a single real cusp is created (it may be either a torus or * Klein bottle cusp). * * Technical note: It's OK to pass a manifold with some or all * of the peripheral curves missing, the cusp topologies unknown, * and num_or_cusps and/or num_nonor_cusps not set. (For example, * normal_surface_splitting.c does exactly that.) Of course any * peripheral curves which are known will be preserved. */ /* * The Algorithm * * Overview * * A finite vertex is represented by a "cusp" whose cross section is * topologically a sphere (in contrast to real cusps, whose cross sections * are always tori or Klein bottles). Throughout this documentation, * please imagine all tetrahedra to have truncated vertices, so that * a finite vertex appears as a spherical boundary component, and a * real cusp appears as a torus or Klein bottle boundary component. * To "remove a finite vertex", we'll modify the triangulation so as * to drill out a tube connecting a spherical boundary component to * a nearby torus or Klein bottle boundary component. We'll repeat * the procedure until no spherical boundary components remain. * * Details * * The manifold is assumed to be connected, so as long as spherical * boundary components remain we may find an edge E (in the triangulation * of the manifold) connecting a spherical boundary component to a * torus or Klein bottle boundary component. Let T be any triangle * (in the triangulation of the manifold) incident to E. * * If we cut along the triangle T, insert a triangular pillow, and reglue, * the topology of the manifold doesn't change. But instead of inserting * an ordinary triangular pillow, we'll insert a triangular pillow from * which a "tunnel" has been drilled out, so as to connect one of its * truncated vertices to another. (The tunnel is unknotted, but it * really doesn't matter.) * * A triangular-pillow-with-tunnel may be constructed from only two * ideal tetrahedra, according to the following gluings (the notation * is as in the file TriangulationFileFormat). * * tetrahedron 0 * 1 free free 1 * 0213 ---- ---- 1023 * * tetrahedron 1 * 0 1 1 0 * 0213 0213 0213 1023 * * Note: In my drawing the two tetrahedra are glued together along * face 0 to form a hexahedron. Vertex 0 of tetrahedron 0 appears * at the "north pole", vertex 0 of tetrahedron 1 appears at the * "south pole", and the remain three vertices appear along the "equator". * * Closed Manifolds * * If the triangulation has no real cusps, then an arbitrary spherical * boundary component is selected, and all other spherical boundary * components are connected to it as above. This yields a manifold * with a single spherical boundary component. An additional * triangular-pillow-with-tunnel is added to convert the spherical * boundary component to a torus or Klein bottle boundary. * * Acknowledgements * * My path to this algorithm was indirect. I thank Sergei Matveev * for suggesting I think about manifolds in terms of spines, and * I thank Carlo Petronio for helpful discussions which led me in * the direction of this construction. */ #include "kernel.h" #include "kernel_namespace.h" static void initialize_matching_cusps(Triangulation *manifold, Cusp **special_fake_cusp); static void merge_cusps(Triangulation *manifold); static void drill_tube(Triangulation *manifold, Tetrahedron *tet, EdgeIndex e, Boolean creating_new_cusp); static void set_real_cusps(Triangulation *manifold, Cusp *special_fake_cusp); void remove_finite_vertices( Triangulation *manifold) { Cusp *special_fake_cusp; /* * Simplify the triangulation before we begin. * basic_simplification() should work OK even with finite vertices. */ basic_simplification(manifold); /* * The matching_cusp field of each fake cusp records the real cusp * to which the fake cusp has been connected. It's initialized to * NULL to indicate that the fake cusp has not yet been connected * to anything. For real cusps, it's convenient to have the * matching_cusp field always point to the cusp itself. If the * manifold has no real cusps, then choose a "special fake cusp" * to which all other fake cusps will be connected, and set its * matching_cusp field to point to itself. */ initialize_matching_cusps(manifold, &special_fake_cusp); /* * Keep merging fake cusps with real cusps until no further progress * is possible. */ merge_cusps(manifold); /* * Ideal vertices which used to be incident to fake cusps are * now all incident to real cusps. Update the tet->cusp[] fields, * and free the fake cusps (except for the special_fake_cusp, if any). */ set_real_cusps(manifold, special_fake_cusp); /* * If the manifold is closed (no real cusps) it will, at this point, * have one spherical "cusp", namely the special_fake_cusp. * Drill out a tube connecting the special_fake_cusp to itself, * to convert it from a sphere to a torus or Klein bottle. */ if (special_fake_cusp != NULL) { /* * Simplify the triangulation before drilling, * to increases the chances that the drilled out tube will * follow a topologically nontrivial loop through the manifold. * (This is essential if we want to express the resulting * closed manifold as a hyperbolic Dehn filling.) */ basic_simplification(manifold); drill_tube(manifold, manifold->tet_list_begin.next, 0, TRUE); } /* * The triangulation is now correct, but it is horribly inefficient. * Simplify it. * * Note: basic_simplification() calls tidy_peripheral_curves() * and compute_CS_fudge_from_value(). */ basic_simplification(manifold); } static void initialize_matching_cusps( Triangulation *manifold, Cusp **special_fake_cusp) { Boolean has_real_cusp; Cusp *cusp; has_real_cusp = FALSE; for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) if (cusp->is_finite) cusp->matching_cusp = NULL; else { cusp->matching_cusp = cusp; has_real_cusp = TRUE; } if (has_real_cusp == FALSE) { *special_fake_cusp = manifold->cusp_list_begin.next; (*special_fake_cusp)->matching_cusp = *special_fake_cusp; } else *special_fake_cusp = NULL; } static void merge_cusps( Triangulation *manifold) { Boolean progress; EdgeClass *edge; Tetrahedron *tet; EdgeIndex e; Cusp *one_cusp, *other_cusp; do { progress = FALSE; for (edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) { tet = edge->incident_tet; e = edge->incident_edge_index; one_cusp = tet->cusp[one_vertex_at_edge[e]]; other_cusp = tet->cusp[other_vertex_at_edge[e]]; if (one_cusp->matching_cusp == NULL && other_cusp->matching_cusp != NULL) { one_cusp->matching_cusp = other_cusp->matching_cusp; drill_tube(manifold, tet, e, FALSE); progress = TRUE; } if (other_cusp->matching_cusp == NULL && one_cusp->matching_cusp != NULL) { other_cusp->matching_cusp = one_cusp->matching_cusp; drill_tube(manifold, tet, e, FALSE); progress = TRUE; } } } while (progress == TRUE); } static void drill_tube( Triangulation *manifold, Tetrahedron *tet, EdgeIndex e, Boolean creating_new_cusp) { /* * Insert a triangular-pillow-with-tunnel (as described at the top * of this file) so as to connect the boundary component at one * end of the given edge to the boundary component at the other end. * The orientation on the triangular pillow will match the * orientation on tet, so that the orientation on the manifold * (if there is one) will be preserved. Edge orientations are also * respected. */ VertexIndex v0, v1, v2, vv0, vv1, vv2; FaceIndex f, ff; Tetrahedron *nbr_tet, *new_tet0, *new_tet1; Permutation gluing; EdgeClass *edge0, *edge1, *edge2, *new_edge; Orientation edge_orientation0, edge_orientation1, edge_orientation2; PeripheralCurve c; Orientation h; int num_strands, intersection_number[2], the_gcd; Cusp *unique_cusp; MatrixInt22 basis_change[1]; /* * Relative to the orientation of tet, the vertices v0, v1 and v2 * are arranged in counterclockwise order around the face f. */ v0 = one_vertex_at_edge[e]; v1 = other_vertex_at_edge[e]; v2 = remaining_face[v1][v0]; f = remaining_face[v0][v1]; /* * Note the matching face and its vertices. */ nbr_tet = tet->neighbor[f]; gluing = tet->gluing[f]; ff = EVALUATE(gluing, f); vv0 = EVALUATE(gluing, v0); vv1 = EVALUATE(gluing, v1); vv2 = EVALUATE(gluing, v2); /* * Note the incident EdgeClasses (which may or may not be distinct). */ edge0 = tet->edge_class[e]; edge1 = tet->edge_class[edge_between_vertices[v1][v2]]; edge2 = tet->edge_class[edge_between_vertices[v2][v0]]; /* * Construct the triangular-pillow-with-tunnel, as described * at the top of this file. */ new_tet0 = NEW_STRUCT(Tetrahedron); new_tet1 = NEW_STRUCT(Tetrahedron); initialize_tetrahedron(new_tet0); initialize_tetrahedron(new_tet1); INSERT_BEFORE(new_tet0, &manifold->tet_list_end); INSERT_BEFORE(new_tet1, &manifold->tet_list_end); manifold->num_tetrahedra += 2; new_edge = NEW_STRUCT(EdgeClass); initialize_edge_class(new_edge); INSERT_BEFORE(new_edge, &manifold->edge_list_end); new_tet0->neighbor[0] = new_tet1; new_tet0->neighbor[1] = NULL; /* assigned below */ new_tet0->neighbor[2] = NULL; /* assigned below */ new_tet0->neighbor[3] = new_tet1; new_tet1->neighbor[0] = new_tet0; new_tet1->neighbor[1] = new_tet1; new_tet1->neighbor[2] = new_tet1; new_tet1->neighbor[3] = new_tet0; new_tet0->gluing[0] = CREATE_PERMUTATION(0, 0, 1, 2, 2, 1, 3, 3); new_tet0->gluing[1] = 0x00; /* assigned below */ new_tet0->gluing[2] = 0x00; /* assigned below */ new_tet0->gluing[3] = CREATE_PERMUTATION(0, 1, 1, 0, 2, 2, 3, 3); new_tet1->gluing[0] = CREATE_PERMUTATION(0, 0, 1, 2, 2, 1, 3, 3); new_tet1->gluing[1] = CREATE_PERMUTATION(0, 0, 1, 2, 2, 1, 3, 3); new_tet1->gluing[2] = CREATE_PERMUTATION(0, 0, 1, 2, 2, 1, 3, 3); new_tet1->gluing[3] = CREATE_PERMUTATION(0, 1, 1, 0, 2, 2, 3, 3); new_tet0->edge_class[0] = edge1; new_tet0->edge_class[1] = edge1; new_tet0->edge_class[2] = edge0; new_tet0->edge_class[3] = edge2; new_tet0->edge_class[4] = edge0; new_tet0->edge_class[5] = edge0; new_tet1->edge_class[0] = edge1; new_tet1->edge_class[1] = edge1; new_tet1->edge_class[2] = edge0; new_tet1->edge_class[3] = new_edge; new_tet1->edge_class[4] = edge0; new_tet1->edge_class[5] = edge0; edge0->order += 6; edge1->order += 4; edge2->order += 1; new_edge->order = 1; new_edge->incident_tet = new_tet1; new_edge->incident_edge_index = 3; edge_orientation0 = tet->edge_orientation[e]; edge_orientation1 = tet->edge_orientation[edge_between_vertices[v1][v2]]; edge_orientation2 = tet->edge_orientation[edge_between_vertices[v2][v0]]; new_tet0->edge_orientation[0] = edge_orientation1; new_tet0->edge_orientation[1] = edge_orientation1; new_tet0->edge_orientation[2] = edge_orientation0; new_tet0->edge_orientation[3] = edge_orientation2; new_tet0->edge_orientation[4] = edge_orientation0; new_tet0->edge_orientation[5] = edge_orientation0; new_tet1->edge_orientation[0] = edge_orientation1; new_tet1->edge_orientation[1] = edge_orientation1; new_tet1->edge_orientation[2] = edge_orientation0; new_tet1->edge_orientation[3] = right_handed; new_tet1->edge_orientation[4] = edge_orientation0; new_tet1->edge_orientation[5] = edge_orientation0; new_tet0->cusp[0] = tet->cusp[v0]; new_tet0->cusp[1] = tet->cusp[v0]; new_tet0->cusp[2] = tet->cusp[v0]; new_tet0->cusp[3] = tet->cusp[v2]; new_tet1->cusp[0] = tet->cusp[v0]; new_tet1->cusp[1] = tet->cusp[v0]; new_tet1->cusp[2] = tet->cusp[v0]; new_tet1->cusp[3] = tet->cusp[v2]; /* * Install the triangular-pillow-with-tunnel. */ tet->neighbor[f] = new_tet0; tet->gluing[f] = CREATE_PERMUTATION(f, 2, v0, 0, v1, 1, v2, 3); new_tet0->neighbor[2] = tet; new_tet0->gluing[2] = inverse_permutation[tet->gluing[f]]; nbr_tet->neighbor[ff] = new_tet0; nbr_tet->gluing[ff] = CREATE_PERMUTATION(ff, 1, vv0, 0, vv1, 2, vv2, 3); new_tet0->neighbor[1] = nbr_tet; new_tet0->gluing[1] = inverse_permutation[nbr_tet->gluing[ff]]; /* * Typically creating_new_cusp is FALSE, meaning that we are * connecting a spherical boundary component to a torus or * Klein bottle boundary component, and we simply extend the * existing peripheral curves across the new tetrahedra. * * In the exceptional case that creating_new_cusp is TRUE, * meaning that the manifold has no real cusps and we are * connecting the "special fake cusp" to itself, we must * install a meridian and longitude, and set up the Dehn filling. */ if (creating_new_cusp == FALSE) { /* * Extend the peripheral curves across the boundary of the * triangular-pillow-with-tunnel. * * Note: The orientations of new_tet0 and new_tet1 match that * of tet, so the right_handed and left_handed sheets match up * in the obvious way. */ for (c = 0; c < 2; c++) /* c = M, L */ for (h = 0; h < 2; h++) /* h = right_handed, left_handed */ { num_strands = tet->curve[c][h][v0][f]; new_tet0->curve[c][h][0][2] = -num_strands; new_tet0->curve[c][h][0][1] = +num_strands; num_strands = tet->curve[c][h][v1][f]; new_tet0->curve[c][h][1][2] = -num_strands; new_tet0->curve[c][h][1][0] = +num_strands; new_tet1->curve[c][h][2][0] = -num_strands; new_tet1->curve[c][h][2][1] = +num_strands; new_tet1->curve[c][h][1][2] = -num_strands; new_tet1->curve[c][h][1][0] = +num_strands; new_tet0->curve[c][h][2][0] = -num_strands; new_tet0->curve[c][h][2][1] = +num_strands; num_strands = tet->curve[c][h][v2][f]; new_tet0->curve[c][h][3][2] = -num_strands; new_tet0->curve[c][h][3][1] = +num_strands; } } else /* creating_new_cusp == TRUE */ { /* * We have just installed a tube connecting the (unique) * spherical "cusp" to itself, to convert it to a torus or * Klein bottle. */ unique_cusp = tet->cusp[v0]->matching_cusp; unique_cusp->is_complete = TRUE; /* to be filled below */ unique_cusp->index = 0; unique_cusp->is_finite = FALSE; manifold->num_cusps = 1; /* * Install an arbitrary meridian and longitude. */ peripheral_curves(manifold); count_cusps(manifold); /* * Two sides of the (truncated) vertex 0 of new_tet0 * (namely the sides incident to faces 1 and 2 of new_tet0) * define the Dehn filling curve by which we can recover * the closed manifold. Count how many times the newly * installed meridian and longitude cross this Dehn filling curve. * To avoid messy questions about which sheet of the cusp's * double cover we're on, use two (parallel) copies of the * Dehn filling curve, one on each sheet of the cover. * Ultimately we're looking for a linear combination of the * meridian and longitude whose intersection number with * the Dehn filling curve is zero, so it won't matter if * we're off by a factor of two. */ for (c = 0; c < 2; c++) /* c = M, L */ { intersection_number[c] = 0; for (h = 0; h < 2; h++) /* h = right_handed, left_handed */ { intersection_number[c] += new_tet0->curve[c][h][0][1]; intersection_number[c] += new_tet0->curve[c][h][0][2]; } } /* * Use the intersection numbers to deduce * the desired Dehn filling coefficients. */ the_gcd = gcd(intersection_number[M], intersection_number[L]); unique_cusp->is_complete = FALSE; unique_cusp->m = -intersection_number[L] / the_gcd; unique_cusp->l = +intersection_number[M] / the_gcd; /* * Switch to a basis in which the Dehn filling curve is a meridian. */ unique_cusp->cusp_shape[initial] = Zero; /* force current_curve_basis() to ignore the cusp shape */ current_curve_basis(manifold, 0, basis_change[0]); if (change_peripheral_curves(manifold, basis_change) != func_OK) uFatalError("drill_tube", "finite_vertices"); } } static void set_real_cusps( Triangulation *manifold, Cusp *special_fake_cusp) { Tetrahedron *tet; int i; Cusp *cusp, *dead_cusp; /* * Update the cusp fields. */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (i = 0; i < 4; i++) tet->cusp[i] = tet->cusp[i]->matching_cusp; /* * Free the Cusp structures which had been used for finite vertices. */ for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) if (cusp->is_finite == TRUE && cusp != special_fake_cusp) { dead_cusp = cusp; cusp = cusp->prev; /* so the loop will proceed correctly */ REMOVE_NODE(dead_cusp); my_free(dead_cusp); } } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/fundamental_group.c000644 000765 000024 00000451350 12377774107 022671 0ustar00babstaff000000 000000 /* * fundamental_group.c * * This file exports the following functions to the UI: * * GroupPresentation *fundamental_group( * Triangulation *manifold, * Boolean simplify_presentation, * Boolean fillings_may_affect_generators, * Boolean minimize_number_of_generators); * * int fg_get_num_generators (GroupPresentation *group); * int fg_get_num_orig_gens (GroupPresentation *group); * Boolean fg_integer_fillings (GroupPresentation *group); * int fg_get_num_relations (GroupPresentation *group); * int *fg_get_relation (GroupPresentation *group, * int which_relation); * int fg_get_num_cusps (GroupPresentation *group); * int *fg_get_meridian (GroupPresentation *group, * int which_cusp); * int *fg_get_longitude (GroupPresentation *group, * int which_cusp); * void fg_free_relation (int *relation); * * void free_group_presentation(GroupPresentation *group); * * The UI will call fundamental_group() to compute a GroupPresentation, * then make calls as needed to the fg_get_.../fg_free... functions, * and finally call free_group_presentation() to release the memory. * The actual structure of a GroupPresentation is private to this file; * SnapPea.h contains an "opaque typedef" which lets the UI pass pointers * to GroupPresentations without knowing their internal structure. * * fundamental_group() computes the fundamental group of the manifold, * and returns a pointer to it. It takes into account Dehn fillings * with relatively prime integer coefficients, but ignores all * other Dehn fillings. The Boolean arguments correspond * to the fields in the GroupPresentation typedef below. * * fg_get_num_generators() returns the number of generators in the * GroupPresentation. * * fg_get_num_geom_gens() returns the number of original generators for * of the GroupPresentation. * * fg_integer_fillings() says whether the space is a manifold or orbifold, * as opposed to some other generalized Dehn filling. * * fg_get_num_relations() returns the number of relations in the * GroupPresentation. * * fg_get_relation() returns the specified relation. It allocates * the memory for it, so you should pass the pointer back to * fg_free_relation() when you're done with it. * Each relation is a string of integers. The integer 1 means the * first generator, 2 means the second, etc., while -1 is the inverse * of the first generator, -2 is the inverse of the second, etc. * The integer 0 indicates the end of the string. * * fg_get_num_cusps() returns the number of cusps of the underlying * manifold. This *includes* the filled cusps. So, for example, * if you do (5,1) Dehn filling on the figure eight knot complement, * you can see the words in the fundamental group corresponding to * the (former!) cusp's meridian and longitude. * * fg_get_meridian() and fg_get_longitude() return the word corresponding * to a meridian or longitude, in the same format used by * fg_get_relation() above. They allocate the memory for the string * of integers, so you should pass the pointer back to * fg_free_relation() when you're done with it. Meridians and * longitudes are available whether the cusps are filled or not as * explained for fg_get_num_cusps() above. * * fg_free_relation() frees relations allocated by fg_get_relation(). * * free_group_presentation() frees the memory occupied by a GroupPresentation. */ /* * 96/9/13 There are two sets of generators kicking around: * * (1) the "geometric generators" defined in choose_generators.c, and * * (2) the "simplified generators" used by fundamental_group() * in its final simplified presentation. * * The algorithm in representations.c needs to express the former as words * in the latter, so we now keep track of that information. As with * the expressions for meridians and longitudes, we use words with well * defined basepoints, and don't do any cyclic cancellations. * * * * 2010/3/17 [NMD] Added keeping track of the latter as words in the * former. Rather that storing the entire words, which can get * *really* long, we store the sequence of moves done during * simplification. These are recorded in group->itsWordMoves in the * following scheme: * * (a, a) with a > 0 means that the generator "a" is removed, and * replaced with the final generator. * * (a, -a) with a > 0 means that the generator "a" is replaced with * it's inverse. * * (a, b) not of the above form means do the (a,b) handle slide. * * (n, word, n) where n is greater than the current number of * generators means introduce a new generator, namely n, which is * equal to "word" in terms of the current generators. * * * 96/9/29 fundamental_group() nows records the basepoint of each Cusp * in the Cusp's basepoint_tet, basepoint_vertex and basepoint_orientation * fields. The basepoint is the point where the meridian and longitude * meet; the meridional and longitudinal words are computed relative to * this point to guarantee that they compute. */ /* * Visualizing the fundamental group. * * Sometimes we'll think of a presentation of a manifold's * fundamental group not just as an abstract presentation, but as a * sort of Heegaard diagram. To be precise, we'll think of it as a * handlebody with a collection of disjoint simple closed curves showing * where (thickened) disks are to be attached. In a true Heegaard * diagram the boundary of the handlebody-with-disks-attached is * a single 3-sphere, but in our case the boundary will consist of * a 2-torus or Klein bottle for each unfilled cusp, and a 2-sphere * for each filled cusp. The number of relations may be less than, * equal to, or greater than the genus of the handlebody. * * Constructing the pseudo-Heegaard diagram. * * The manifold's Triangulation provides a pseudo-Heegaard diagram, * which we use to obtain the initial, unsimplified presentation * of the fundamental group. * * The handlebody is the thickened 1-skeleton of the ideal * triangulation's dual complex. (Please see choose_generators.c for an * explanation of how a set of generators is chosen for the handlebody, * and how the generators are represented internally.) There are two * types of relations. Each thickened edge (in the original ideal * triangulation, not the dual) is a relation (note that a thickened edge * is topologically the same as a thickened disk), and each Dehn filling * curve specifies a relation. * * Visualizing the pseudo-Heegaard diagram. * * Visualize the pseudo-Heegaard diagram as follows. Start with the * pseudo-Heegaard diagram drawn as an actual handlebody, then make * a meridional cut through each handle, so that the handlebody opens * into a 3-ball. Label the cut-disks A+ and A-, B+ and B-, etc., * so that identifying A+ to A-, B+ to B-, etc. restores the original * handlebody. The relation aBc would then be a curve which goes in A+ * and comes out A-, goes in B- and comes out B+, then goes in C+ and * comes out C- to its starting point. * * Operations which do or do not respect the Heegaard diagram. * * My original hope in developing this code was to provide an option * whereby the algorithm uses only simplifications which respect the * Heegaard diagram. This would have let us conclude, for example, * that a manifold with a genus zero presentation is a topological * 3-sphere, a manifold with a genus one presentation is a lens space, * etc. Some simplifications (e.g. handle slides) can rigorously * be interpreted as operations on the pseudo-Heegaard diagram. * Others, unfortunately, are slipperier. For example, cancellation * of inverses (e.g. "abBcAd" -> "acAd") is almost always a valid * operation on the Heegaard diagram -- just isotope the little loop * "bB" across the B- disk -- but one has to worry about whether the * loop encloses other disks. I had worked out an algorithm to * removed any such other disks (by isotoping them across the B- * disk) but then the proof that the algorithm terminates was no * longer so clear. At that point I finally decided to abandon the * Heegaard interpretation of the simplifications. I was feeling too * uncomfortable working with a data structure (the GroupPresentation) * which contained only a subset of the information needed for the * calculations and for the proofs that the calculations are correct. * Solid, reliable code requires a data structure which models the * underlying mathematics as directly as possible. * * If you want a topological description of the space, you can compute * an unsimplified presentation (which *does* correspond to a pseudo- * Heegaard diagram, as explained above) and pass it to John Berge's * program "Heegaard". "Heegaard" does an excellent job of recognizing * lens space, for example. If you give it a sufficiently complicated * presentation, it can even distinguish, say, L(5,1) from L(5,2)! * (Note: The unsimplified presentation uses the standard generators * defined in choose_generators.c. The code in representations.c * relies on this fact.) * * * Conventions. * * (1) The generators of an abstract group presentation are represented * by lowercase letters. Their inverses are respresented by the * corresponding uppercase letters. For example, "A" is the inverse * of "a". * * (2) Words in an abstract group presentation are read left to right. * For example, "abC" means do "a", "b" and "c inverse", in that order. * However, O(3,1) matrices act on column vectors (matrix times column * vector equals column vector), so products of such matrices are read * right to left. For example, (M2)(M1) means do matrix M1, then do * matrix M2. */ #include "kernel.h" #include #include "kernel_namespace.h" typedef struct Letter { /* * itsValue contains the index of a generator. * The generators are implicitly numbered 1, 2 ..., n, and their * inverses are -1, -2, ..., -n, where n is the number of generators. */ int itsValue; /* * Letters are kept on circular doubly-linked lists. */ struct Letter *prev, *next; } Letter; typedef struct CyclicWord { /* * itsLength gives the number of Letters in the CyclicWord. */ int itsLength; /* * itsLetters points to an arbitrary Letter in the CyclicWord. * The Letters are kept on a circular doubly-linked list. * * If a Cyclic Word is empty, itsLength is set to 0 and * itsLetters is set to NULL. */ Letter *itsLetters; /* * is_Dehn_relation says whether this relation comes from a Dehn * filling. When group->fillings_may_affect_generators is FALSE, * such relations may not influence the choice of generators. */ Boolean is_Dehn_relation; /* * The "next" field points to the next CyclicWord * in the GroupPresentation. */ struct CyclicWord *next; } CyclicWord; struct GroupPresentation { /* * How many generators does the GroupPresentation have? * (Geometrically, what is the genus of the handlebody in * the pseudo-Heegaard diagram?) */ int itsNumGenerators; /* * We maintain an array of matrices, one for each generator, * which defines the representation of the fundamental group * into Isom(H^3). The matrices could be given in either O(3,1) * or PSL(2,C); I chose the former because it handles orientation- * reversing isometries more naturally. */ /* * [MC 2014-06-19] I choose *both*. The O31 matrices accumulate * errors much faster than the Moebius transformations. */ O31Matrix *itsMatrices; MoebiusTransformation *itsMTs; /* * How many relations does the presentation have? * (Geometrically, how many thickened disks are glued to the * boundary of the handlebody? See "Constructing the pseudo-Heegaard * diagram" above for more details.) */ int itsNumRelations; /* * itsRelations points to a NULL-terminated, singly-linked list * of relations. Typically the relations are interpreted as curves * on a handlebody, as explained above. */ CyclicWord *itsRelations; /* * Is this space a manifold or orbifold (e.g. FigureEight(5,1) * or FigureEight(6,3)) as opposed to some other generalized * Dehn filling (e.g. FigureEight(5.01, 1.0))? We compute * Dehn relations only for cusps with integer coefficients, * and ignore other (generalized) Dehn fillings. The UI should * display the relations only for integer fillings, but should * display the matrix representation for all generalized * Dehn fillings. */ Boolean integer_fillings; /* * We keep track of the words corresponding to the meridians and * longitudes. Note that * * (1) we keep track of the meridian and longitude even * on filled cusps, * * (2) the two longitudes on a Klein bottle are not homotopic to one * another, so we report the lift to the orientation double cover, * * (3) the words have well defined basepoints -- cyclic cancellations * are not allowed. */ int itsNumCusps; CyclicWord *itsMeridians, *itsLongitudes; /* * We keep track of words which express each of the original generators * (the ones defined in choose_generators.c) as products of the * current generators, and vis versa. The words have well defined basepoints -- * cyclic cancellations are not allowed. */ int itsNumOriginalGenerators; CyclicWord *itsOriginalGenerators; /* Original in terms of current */ CyclicWord *itsWordMoves; /* Record of how the current generators relate to the current ones */ /* * Should we simplify the presentation? * * For most purposes simplify_presentation should be TRUE, but * occasionally the user may want access to the unsimplified * presentation. For example, you can pass an unsimplified * presentation of a lens space to John Berge's program Heegaard, * and it will most likley be able to recognize the exact lens space. * Yes, it distinguishes L(5,1) from L(5,2), but only if it * begins with a sufficiently complicated presentation. * Passing it the presentation < a | a^5 = 1 > isn't good enough! * * 96/9/11 The code in representations.c relies on the fact that * the unsimplified presentation uses the standard generators * defined in choose_generators.c. */ Boolean simplify_presentation; /* * Is it OK for the choice of generators to depend on the Dehn fillings? * Sometimes the user may want this flag to be FALSE, for example * when he or she is studying how the matrix generators vary across * a Dehn filling plane, and wants a consistent choice of generators. * Other times the user may want this flag to be TRUE, for example * when he or she wants to see which Dehn fillings give lens spaces. */ Boolean fillings_may_affect_generators; /* * If minimize_number_of_generators is TRUE, simplify_presentation() * will try to reduce the number of generators at the expense of * increasing the total length of the relations. If it's FALSE, * it does the opposite. */ Boolean minimize_number_of_generators; }; static GroupPresentation *compute_unsimplified_presentation(Triangulation *manifold); static void compute_matrix_generators(Triangulation *manifold, GroupPresentation *group); static void compute_relations(Triangulation *manifold, GroupPresentation *group); static void compute_edge_relations(Triangulation *manifold, GroupPresentation *group); static void compute_one_edge_relation(EdgeClass *edge, GroupPresentation *group); static void compute_Dehn_relations(Triangulation *manifold, GroupPresentation *group); static void compute_peripheral_word(Cusp *cusp, PeripheralCurve which_curve, CyclicWord **word_list); static void find_standard_basepoint(Triangulation *manifold, Cusp *cusp); static void find_curve_start(Cusp *cusp, PeripheralCurve which_curve, PositionedTet *ptet); static void compute_Dehn_word(CyclicWord *meridian, CyclicWord *longitude, int m, int l, CyclicWord **word_list); static void append_copies(CyclicWord *source, int n, CyclicWord *dest); static void append_word(CyclicWord *source, CyclicWord *dest); static void append_inverse(CyclicWord *source, CyclicWord *dest); /* Not used static void prepend_word(CyclicWord *source, CyclicWord *dest); static void prepend_inverse(CyclicWord *source, CyclicWord *dest); */ static void initialize_original_generators(GroupPresentation *group, int num_generators); static void simplify(GroupPresentation *group); static void insert_basepoints(GroupPresentation *group); static void insert_basepoints_on_list(CyclicWord *list); static void insert_basepoint_in_word(CyclicWord *word); static void remove_basepoints(GroupPresentation *group); static void remove_basepoints_on_list(CyclicWord *list); static void remove_basepoint_in_word(CyclicWord *word); static Boolean word_length_one(GroupPresentation *group); static Boolean word_length_two(GroupPresentation *group); static Boolean try_handle_slides(GroupPresentation *group); static Boolean substring_occurs_in_group(GroupPresentation *group, int a, int b); static Boolean substring_occurs_in_word(CyclicWord *word, int a, int b); static Boolean handle_slide_improves_presentation(GroupPresentation *group, int a, int b); static void evaluate_handle_slide_in_group(GroupPresentation *group, int a, int b, int *shortest_nonempty_relation_before, int *shortest_nonempty_relation_after, int *change_in_total_length, int *change_in_num_runs); static void evaluate_handle_slide_on_word(CyclicWord *word, int a, int b, int *shortest_nonempty_relation_before, int *shortest_nonempty_relation_after, int *change_in_total_length, int *change_in_num_runs); static int compute_delta_length(CyclicWord *word, int a, int b); static int compute_delta_runs(CyclicWord *word, int a, int b); static Boolean two_singletons_in_group(GroupPresentation *group); static Boolean generator_occurs_as_two_singletons_in_group(GroupPresentation *group, int value, CyclicWord **word_containing_singletons); static Boolean generator_occurs_as_two_singletons_in_word(CyclicWord *word, int value); static Boolean generator_occurs_in_no_other_word_in_group(GroupPresentation *group, int value, CyclicWord *word_containing_singletons); static Boolean generator_occurs_in_word(CyclicWord *word, int value); static void make_singletons_adjacent(GroupPresentation *group, int value, CyclicWord *word); static Boolean eliminate_word_in_group(GroupPresentation *group); static CyclicWord *shortest_word_in_which_generator_occurs_precisely_once(GroupPresentation *group, int generator); static Boolean generator_occurs_precisely_once_in_word(CyclicWord *word, int generator); static int occurrences_in_group(GroupPresentation *group, int generator); static int occurrences_in_word(CyclicWord *word, int generator); static void eliminate_word(GroupPresentation *group, CyclicWord *word, int generator); static Boolean remove_empty_relations(GroupPresentation *group); static Boolean insert_word_from_group(GroupPresentation *group); static Boolean insert_word_into_group(GroupPresentation *group, CyclicWord *word); static Boolean insert_word_into_list(CyclicWord *list, CyclicWord *word); static Boolean insert_word_into_word(CyclicWord *word, CyclicWord *target); static Boolean insert_word_forwards(CyclicWord *word, CyclicWord *target); static Boolean insert_word_backwards(CyclicWord *word, CyclicWord *target); static Boolean simplify_one_word_presentations(GroupPresentation *group); static Boolean word_contains_pattern(Letter *unmatched_letter, int period, int repetitions); static CyclicWord *introduce_generator(GroupPresentation *group, Letter *substring, int length); static void lens_space_recognition(GroupPresentation *group); static int count_runs(CyclicWord *word); static Boolean lens_space_recognition_using_generator(GroupPresentation *group, int generator0); static Boolean invert_generators_where_necessary(GroupPresentation *group); static void count_signed_occurrences_in_group(GroupPresentation *group, int a, int *positive_occurrences, int *negative_occurrences); static void increment_signed_occurrences_in_group(GroupPresentation *group, int a, int *positive_occurrences, int *negative_occurrences); static void increment_signed_occurrences_in_word(CyclicWord *word, int a, int *positive_occurrences, int *negative_occurrences); static int count_signed_occurrences_in_word(CyclicWord *word, int a); static void invert_generator_in_group(GroupPresentation *group, int a); static void invert_generator_on_list(CyclicWord *list, int a); static void invert_generator_in_word(CyclicWord *word, int a); static Boolean invert_words_where_necessary(GroupPresentation *group); static Boolean invert_word_if_necessary(CyclicWord *word); static int sum_of_powers(CyclicWord *word); static void invert_word(CyclicWord *word); static void choose_word_starts(GroupPresentation *group); static void choose_word_start(CyclicWord *word); static void conjugate_peripheral_words(GroupPresentation *group); static Boolean conjugate_peripheral_pair(CyclicWord *word0, CyclicWord *word1); static void conjugate_word(CyclicWord *word, int value); static void cancel_inverses(GroupPresentation *group); static void cancel_inverses_word_list(CyclicWord *list); static void cancel_inverses_word(CyclicWord *word); static void handle_slide(GroupPresentation *group, int a, int b); static void handle_slide_word_list(CyclicWord *list, int a, int b); static void handle_slide_word(CyclicWord *word, int a, int b); static void handle_slide_matrices(GroupPresentation *group, int a, int b); static void cancel_handles(GroupPresentation *group, CyclicWord *word); static void remove_word(GroupPresentation *group, CyclicWord *word); static void remove_generator(GroupPresentation *group, int dead_generator); static void remove_generator_from_list(CyclicWord *list, int dead_generator); static void remove_generator_from_word(CyclicWord *word, int dead_generator); static void renumber_generator(GroupPresentation *group, int old_index, int new_index); static void renumber_generator_on_word_list(CyclicWord *list, int old_index, int new_index); static void renumber_generator_in_word(CyclicWord *word, int old_index, int new_index); static int *fg_get_cyclic_word(CyclicWord *list, int which_relation); static void free_word_list(CyclicWord *aWordList); static void free_cyclic_word(CyclicWord *aCyclicWord); static void update_word_moves(GroupPresentation *group, int a); static void update_word_moves2(GroupPresentation *group, int a, int b); /* Debugging tool static void print_word(CyclicWord *word); */ GroupPresentation *fundamental_group( Triangulation *manifold, Boolean simplify_presentation, Boolean fillings_may_affect_generators, Boolean minimize_number_of_generators) { GroupPresentation *group; uLongComputationBegins("Computing the fundamental group.", TRUE); /* * Read a group presentation from the manifold, without worrying * about simplifying it. This group presentation will be that * of a pseudo-Heegaard diagram, as discussed above. */ group = compute_unsimplified_presentation(manifold); /* * Note the user's preferences. * * (Please see the GroupPresentation typedef above for * an explanation of these flags.) */ group->simplify_presentation = simplify_presentation; group->fillings_may_affect_generators = fillings_may_affect_generators; group->minimize_number_of_generators = minimize_number_of_generators; /* * Simplify the group presentation if requested to do so. */ if (group->simplify_presentation == TRUE) simplify(group); uLongComputationEnds(); return group; } static GroupPresentation *compute_unsimplified_presentation( Triangulation *manifold) { GroupPresentation *group; Boolean compute_vertices; SolutionType solution_type = get_filled_solution_type(manifold); group = NEW_STRUCT(GroupPresentation); /* * MC 2012-03-20 added the test for degenerate solutions to avoid * division by zero errors when computing the fundamental groups * of certain MorwenLinks on platforms with accurate arithmetic. */ compute_vertices = (solution_type != not_attempted && solution_type != no_solution && solution_type != degenerate_solution); choose_generators(manifold, compute_vertices, FALSE); group->itsNumGenerators = manifold->num_generators; compute_matrix_generators(manifold, group); compute_relations(manifold, group); initialize_original_generators(group, group->itsNumGenerators); group->integer_fillings = all_Dehn_coefficients_are_integers(manifold); return group; } static void compute_matrix_generators( Triangulation *manifold, GroupPresentation *group) { SolutionType solution_type = get_filled_solution_type(manifold); Boolean use_identities; /* * Pass centroid_at_origin = FALSE to matrix_generators() * so the initial Tetrahedron will be positioned with vertices * at {0, 1, infinity, z}. This brings out nice number theoretic * properties in the matrix generators, and also forces Triangulations * with all flat tetrahedra to lie in a coordinate plane. */ group->itsMatrices = NEW_ARRAY(manifold->num_generators, O31Matrix); group->itsMTs = NEW_ARRAY(manifold->num_generators, MoebiusTransformation); /* MC 2013-03-20: now checks if matrix_generators fails.*/ use_identities = ( solution_type == not_attempted || solution_type == no_solution ); if ( !use_identities ) { if ( matrix_generators(manifold, group->itsMTs) == func_failed ){ uAcknowledge("Failed to find matrix generators."); use_identities = TRUE; } else { Moebius_array_to_O31_array( group->itsMTs, group->itsMatrices, manifold->num_generators); } } if ( use_identities ) { int i; for (i = 0; i < manifold->num_generators; i++){ o31_copy(group->itsMatrices[i], O31_identity); Moebius_copy(&group->itsMTs[i], &Moebius_identity); } } } static void compute_relations( Triangulation *manifold, GroupPresentation *group) { group->itsNumRelations = 0; group->itsRelations = NULL; /* * Compute the Dehn relations first, so they appear * on the linked list *after* the edge relations. */ compute_Dehn_relations(manifold, group); compute_edge_relations(manifold, group); } static void compute_edge_relations( Triangulation *manifold, GroupPresentation *group) { EdgeClass *edge; for (edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) compute_one_edge_relation(edge, group); } static void compute_one_edge_relation( EdgeClass *edge, GroupPresentation *group) { CyclicWord *new_word; PositionedTet ptet0, ptet; Letter dummy_letter, *new_letter; int index = 0; /* * Ignore EdgeClasses which choose_generators() has already * eliminated via handle cancellations or handle merging. * (choose_generators() doesn't eliminate them from the Triangulation; * it just eliminates them from its picture of the pseudo-Heegaard * diagram.) */ if (edge->active_relation == FALSE) return; /* * choose_generator()'s algorithm ensures that each active relation * has at least two letters. (They may cancel, but there are * nominally at least two of them.) */ if (edge->num_incident_generators < 2) uFatalError("compute_one_edge_relation", "fundamental_group"); /* * Initialize the new_word, and install it on the linked list. */ new_word = NEW_STRUCT(CyclicWord); new_word->itsLength = 0; new_word->is_Dehn_relation = FALSE; new_word->next = group->itsRelations; group->itsRelations = new_word; group->itsNumRelations++; /* * We'll use a temporary dummy_letter to initialize * the circular doubly linked list. */ dummy_letter.next = &dummy_letter; dummy_letter.prev = &dummy_letter; /* * Traverse the EdgeClass, recording each generator we find. */ set_left_edge(edge, &ptet0); ptet = ptet0; do { /* * Are we passing a generator? * If so, convert from the generator_index's 0-based numbering * to the GroupPresentation's 1-based numbering (with negative * numbers for inverses). inbound_generators are considered * positively oriented (for later consistency with the conventions * for storing peripheral curves). */ switch (ptet.tet->generator_status[ptet.near_face]) { case inbound_generator: index = ptet.tet->generator_index[ptet.near_face] + 1; break; case outbound_generator: index = -(ptet.tet->generator_index[ptet.near_face] + 1); break; case not_a_generator: index = 0; break; default: uFatalError("compute_one_edge_relation", "fundamental_group"); } if (index != 0) { new_letter = NEW_STRUCT(Letter); new_letter->itsValue = index; INSERT_BEFORE(new_letter, &dummy_letter); new_word->itsLength++; } veer_left(&ptet); } while (same_positioned_tet(&ptet, &ptet0) == FALSE); /* * Did we find the right number of generators? */ if (new_word->itsLength != edge->num_incident_generators) uFatalError("compute_one_edge_relation", "fundamental_group"); /* * Give new_word a valid pointer to the circular doubly linked list * of Letters, and then remove the temporary dummy_letter. */ new_word->itsLetters = dummy_letter.next; REMOVE_NODE(&dummy_letter); } static void compute_Dehn_relations( Triangulation *manifold, GroupPresentation *group) { Cusp *cusp; int i; group->itsNumCusps = manifold->num_cusps; group->itsMeridians = NULL; group->itsLongitudes = NULL; /* * Examine the cusps in reverse order, so the Dehn filling relations * get pushed onto the relation list in the correct order. */ for (i = manifold->num_cusps; --i >= 0; ) { cusp = find_cusp(manifold, i); /* * First compute the meridian and longitude... */ find_standard_basepoint(manifold, cusp); compute_peripheral_word(cusp, M, &group->itsMeridians); compute_peripheral_word(cusp, L, &group->itsLongitudes); /* * ...and then, if the Dehn coefficients are integers, * compute the Dehn relation by concatenating copies * of the meridian and longitude. */ if (cusp->is_complete == FALSE && Dehn_coefficients_are_integers(cusp) == TRUE) { compute_Dehn_word( group->itsMeridians, group->itsLongitudes, (int) cusp->m, (int) cusp->l, &group->itsRelations); group->itsNumRelations++; } } } static void compute_peripheral_word( Cusp *cusp, PeripheralCurve which_curve, CyclicWord **word_list) { /* * Note that the triangulation.h data structure works with the * orientation double cover of each cusp, so both torus and Klein * bottle cusps appear as tori, and can be handled the same. * The only difference is that the "longitude" of a Klein bottle * cusp is actually the double cover of a longitude. Please * see peripheral_curves.c for a careful and complete discussion * of these issues. */ PositionedTet ptet0, ptet; int strand0, strand, near_strands, left_strands; CyclicWord *new_word; Letter dummy_letter, *new_letter; int index = 0; /* * Initialize the new_word, and install it on the linked list. * * Use a temporary dummy_letter to initialize * the circular doubly linked list. */ new_word = NEW_STRUCT(CyclicWord); new_word->itsLength = 0; new_word->itsLetters = &dummy_letter; dummy_letter.next = &dummy_letter; dummy_letter.prev = &dummy_letter; new_word->is_Dehn_relation = TRUE; new_word->next = *word_list; *word_list = new_word; /* * Start where the meridian and longitude intersect. * This insures that * * (1) the meridian and longitude commute, and * * (2) we can form linear combinations of meridians and * longitudes by concatenation. */ find_curve_start(cusp, which_curve, &ptet0); /* * Here's how we keep track of where we are. At each step, we are * always at the near edge of the top vertex (i.e. the truncated vertex * opposite the bottom face) of the PositionedTet ptet (please see * positioned_tet.h if necessary). The curve may cross that edge * several times. The variable "strand" keeps track of which * intersection we are at; 0 means we're at the strand on the * far left, 1 means we're at the next strand, etc. */ /* * Start at the leftmost strand. */ strand0 = 0; ptet = ptet0; strand = strand0; do { /* * Record the generator (if any) corresponding to the near_face. */ switch (ptet.tet->generator_status[ptet.near_face]) { case inbound_generator: index = ptet.tet->generator_index[ptet.near_face] + 1; break; case outbound_generator: index = -(ptet.tet->generator_index[ptet.near_face] + 1); break; case not_a_generator: index = 0; break; default: uFatalError("compute_peripheral_word", "fundamental_group"); } if (index != 0) { new_letter = NEW_STRUCT(Letter); new_letter->itsValue = index; INSERT_BEFORE(new_letter, &dummy_letter); new_word->itsLength++; } /* * Decide whether to veer_left() or veer_right(). */ /* * Note the curve's intersection numbers * with the near side and the left side. */ near_strands = ptet.tet->curve [which_curve] [ptet.orientation] [ptet.bottom_face] [ptet.near_face]; left_strands = ptet.tet->curve [which_curve] [ptet.orientation] [ptet.bottom_face] [ptet.left_face]; /* * Does the current strand bend to the left or to the right? */ if (strand < FLOW(near_strands, left_strands)) { /* * The current strand bends to the left. */ /* * Some of the near strands may branch off towards the * right, or some strands may come in from the right and * join the near strands as they head out to the left. * But either way, the variable "strand" remains unchanged. */ /* * Move the PositionedTet onward, following the curve. */ veer_left(&ptet); } else { /* * The current strand bends to the right. */ /* * Some strands from the near edge may have gone off * to the left edge, in which case the variable "strand" * should be decreased by that amount. * Alternatively, some strands may have come in from the * left edge, joining us at the right edge, in which case * the variable "strand" should be increased by that amount. * The code "strand += left_strands" works for both cases, * because left_strands will be negative in the former case * and positive in the latter. */ strand += left_strands; /* * Move the PositionedTet onward, following the curve. */ veer_right(&ptet); } } while ( same_positioned_tet(&ptet, &ptet0) == FALSE || strand != strand0); /* * Give new_word a valid pointer to the circular doubly linked list * of Letters, and then remove the temporary dummy_letter. * * Note that for meridians and longitudes, new_word->itsLetters * is set to the beginning of the based word, so the basepoints * for the meridian and longitude are the same, and the words will * commute. */ new_word->itsLetters = dummy_letter.next; REMOVE_NODE(&dummy_letter); } static void find_standard_basepoint( Triangulation *manifold, Cusp *cusp) { /* * Find an ideal vertex where both the meridian and longitude * both pass through, and let an arbitrary point in its interior * be the basepoint for the cusp. */ FaceIndex face; for (cusp->basepoint_tet = manifold->tet_list_begin.next; cusp->basepoint_tet != &manifold->tet_list_end; cusp->basepoint_tet = cusp->basepoint_tet->next) for (cusp->basepoint_vertex = 0; cusp->basepoint_vertex < 4; cusp->basepoint_vertex++) { if (cusp->basepoint_tet->cusp[cusp->basepoint_vertex] != cusp) continue; for (face = 0; face < 4; face++) { if (face == cusp->basepoint_vertex) continue; for (cusp->basepoint_orientation = 0; cusp->basepoint_orientation < 2; cusp->basepoint_orientation++) if (cusp->basepoint_tet->curve [M] [cusp->basepoint_orientation] [cusp->basepoint_vertex] [face] != 0 && cusp->basepoint_tet->curve [L] [cusp->basepoint_orientation] [cusp->basepoint_vertex] [face] != 0) /* * We found the basepoint! */ return; } } /* * If we get to this point, it means that no intersection * was found, which is impossible. */ uFatalError("find_standard_basepoint", "fundamental_group"); } static void find_curve_start( Cusp *cusp, PeripheralCurve which_curve, PositionedTet *ptet) { /* * We assume the standard basepoint has already been found by a * previous call to find_standard_basepoint(), and use it to * find the PositionedTet where the requested curve leaves * the standard basepoint. (So ptet->tet typically will NOT be * cusp->basepoint_tet.) */ /* * Temporarily set ptet to be the standard basepoint. * We'll change it in a moment. */ ptet->tet = cusp->basepoint_tet; ptet->bottom_face = cusp->basepoint_vertex; ptet->orientation = cusp->basepoint_orientation; /* * Let near_face be where the requested curve leaves the triangle. */ for (ptet->near_face = 0; ptet->near_face < 4; ptet->near_face++) { if (ptet->near_face == ptet->bottom_face) continue; if (0 > ptet->tet->curve[which_curve][ptet->orientation][ptet->bottom_face][ptet->near_face]) { /* * We've found where the curve leaves the triangle. * Our starting ptet will be just on the other side. * * First fill in the remaining details for this ptet... */ if (ptet->orientation == right_handed) { ptet->left_face = remaining_face[ptet->bottom_face][ptet->near_face]; ptet->right_face = remaining_face[ptet->near_face][ptet->bottom_face]; } else /* ptet->orientation == left_handed */ { ptet->left_face = remaining_face[ptet->near_face][ptet->bottom_face]; ptet->right_face = remaining_face[ptet->bottom_face][ptet->near_face]; } /* * ...then turn around. */ veer_backwards(ptet); /* * Make sure it worked out like we planned. */ if (0 >= ptet->tet->curve[which_curve][ptet->orientation][ptet->bottom_face][ptet->near_face]) uFatalError("find_curve_start", "fundamental_group"); return; } } /* * We should find a negative intersection number somewhere within * the above loop, so we should never get to this point. */ uFatalError("find_curve_start", "fundamental_group"); } static void compute_Dehn_word( CyclicWord *meridian, CyclicWord *longitude, int m, int l, CyclicWord **word_list) { CyclicWord *new_word; Letter dummy_letter; /* * We should never be passed (m,l) = (0,0) when * cusp->is_complete is FALSE, but we check anyhow. */ if (m == 0 && l == 0) uFatalError("compute_Dehn_word", "fundamental_group"); /* * Initialize the new_word, and install it on the linked list. * * Use a temporary dummy_letter to initialize * the circular doubly linked list. */ new_word = NEW_STRUCT(CyclicWord); new_word->itsLength = 0; new_word->itsLetters = &dummy_letter; dummy_letter.next = &dummy_letter; dummy_letter.prev = &dummy_letter; new_word->is_Dehn_relation = TRUE; new_word->next = *word_list; *word_list = new_word; /* * Append m meridians and l longitudes to new_word, * taking into account the signs of m and l. */ /* append_copies(meridian, m, new_word); append_copies(longitude, l, new_word); MC 2013/02/12: Following a suggestion from John Berge we now use the dth power of a primitive p/q word in meridian and longitude, where d=(m,l), p=m/d, q=l/d, instead of mer^mlong^l. This is more likely to give a geometric presentation. */ { int M=ABS(m), L=ABS(l); int m_sign=(M == m ? 1 : -1), l_sign=(L == l ? 1 : -1); int i=0, d = gcd(M,L); if (d > 1) { M /= d; L /= d; } while (d > 0) { do { if (i < M) append_copies(meridian, m_sign, new_word); else append_copies(longitude, l_sign, new_word); i += M; if (i >= M+L ) i -= (M+L); } while (i != 0); d -= 1; } } /* * Give new_word a valid pointer to the circular doubly linked list * of Letters, and then remove the temporary dummy_letter. * * Note that for meridians and longitudes, new_word->itsLetters * is set to the beginning of the based word, so the basepoints * for the meridian and longitude are the same, and the words will * commute. */ new_word->itsLetters = dummy_letter.next; REMOVE_NODE(&dummy_letter); } static void append_copies( CyclicWord *source, int n, CyclicWord *dest) { int i; for (i = 0; i < ABS(n); i++) if (n > 0) append_word(source, dest); else append_inverse(source, dest); } static void append_word( CyclicWord *source, CyclicWord *dest) { int i; Letter *letter, *letter_copy; for ( letter = source->itsLetters, i = 0; i < source->itsLength; letter = letter->next, i++) { letter_copy = NEW_STRUCT(Letter); letter_copy->itsValue = letter->itsValue; INSERT_BEFORE(letter_copy, dest->itsLetters); dest->itsLength++; } } /* Not used static void prepend_word( CyclicWord *source, CyclicWord *dest) { int i; Letter *letter, *letter_copy; for ( letter = source->itsLetters->prev, i = 0; i < source->itsLength; letter = letter->prev, i++) { letter_copy = NEW_STRUCT(Letter); letter_copy->itsValue = letter->itsValue; INSERT_BEFORE(letter_copy, dest->itsLetters); dest->itsLetters = letter_copy; dest->itsLength++; } } */ static void append_inverse( CyclicWord *source, CyclicWord *dest) { int i; Letter *letter, *letter_copy; for ( letter = source->itsLetters->prev, i = 0; i < source->itsLength; letter = letter->prev, i++) { letter_copy = NEW_STRUCT(Letter); letter_copy->itsValue = - letter->itsValue; INSERT_BEFORE(letter_copy, dest->itsLetters); dest->itsLength++; } } /* Not used static void prepend_inverse( CyclicWord *source, CyclicWord *dest) { int i; Letter *letter, *letter_copy; for ( letter = source->itsLetters, i = 0; i < source->itsLength; letter = letter->next, i++) { letter_copy = NEW_STRUCT(Letter); letter_copy->itsValue = - letter->itsValue; INSERT_BEFORE(letter_copy, dest->itsLetters); dest->itsLetters = letter_copy; dest->itsLength++; } } */ static void initialize_original_generators( GroupPresentation *group, int num_generators) { int index; Letter *new_letter; CyclicWord *new_word; group->itsNumOriginalGenerators = num_generators; /* * Initially the original generators are the current generators. * Put the highest numbered generator on the linked list first, * and work backwards, so that they will appear in the correct order. */ group->itsOriginalGenerators = NULL; for (index = num_generators; index >= 1; --index) { new_letter = NEW_STRUCT(Letter); new_letter->itsValue = index; new_letter->prev = new_letter; new_letter->next = new_letter; new_word = NEW_STRUCT(CyclicWord); new_word->itsLength = 1; new_word->itsLetters = new_letter; new_word->is_Dehn_relation = FALSE; new_word->next = group->itsOriginalGenerators; group->itsOriginalGenerators = new_word; } /* * Initially the current generators are the original generators, * so we just start with a dummy record. */ new_letter = NEW_STRUCT(Letter); new_letter->itsValue = 0; new_letter->prev = new_letter; new_letter->next = new_letter; new_word = NEW_STRUCT(CyclicWord); new_word->itsLength = 1; new_word->itsLetters = new_letter; new_word->is_Dehn_relation = FALSE; new_word->next = NULL; group->itsWordMoves = new_word; } static void simplify( GroupPresentation *group) { /* * The Induction Variable * * If group->minimize_number_of_generators is TRUE, then * each operation in the simplification algorithm decreases * the value of the ordered quintuple * * (number of generators, * length of shortest nonempty relation, * total length of all relations, * total number of runs in all relations, * total length of all meridians and longitudes) * * relative to the lexicographic ordering. In other words, each * operation either decreases the number of generators, or leaves * the number of generators constant while decreasing the length * of the shortest nonempty relation, or leaves both the number of * generators and the length of the shortest relation constant while * decreasing the total length of all relations, etc. This provides * a simple proof that the algorithm terminates in a finite number * of steps. * * If group->minimize_number_of_generators is FALSE, then we ignore * the number of generators and try to minimize the ordered quadruple * * (total length of all relations, * total number of runs in all relations, * length of shortest nonempty relation, * total length of all meridians and longitudes). * * By the "total number of runs" I mean that "aaabb" is simpler than * "aabAb" because the former has two runs ("aaa" and "bb") while * the latter has four ("aa", "b", "A" and "b"). The two words are * equivalent via a handle slide. Actually, for technical simplicity * we count the number of transitions from one run to another. * For words with at least two runs, the number of runs equals the * number of transitions. But a word with only one run has no * transitions. * * "length of shortest nonempty relation" may be defined as zero * if there are no nonempty relations. */ /* * Comment: eliminate_word_in_group() is called after * try_handle_slides() on the assumption that the former is more * likely to make a mess of the presentation than the latter, but I * don't have any hard evidence to support this assumption. */ /* * Insert a dummy basepoint Letter into each meridian and longitude, * and also into the expressions for the original generators, to make * sure they remain based at the same point. The basepoint has * itsValue == 0 so that it can't possibly cancel with anything. */ insert_basepoints(group); /* * Cancel obvious inverses in each CyclicWord, * e.g. "abCcBefA" -> "ef". Hereafter, each low-level function * which changes the GroupPresentation (e.g. handle_slide() etc.) * will call cancel_inverses() before returning. cancel_inverses() * decreases the total length of all relations without increasing * any other component of The Induction Variable. */ cancel_inverses(group); /* * The following while() loop call various mid-level functions * in the preferred order. As soon as some mid-level function * returns TRUE, the while() loop begins again at the start of * the list. The idea is that we want to do the more basic * simplifications before considering the fancier ones, and when we * do make some progress with the fancier ones, we want to try the * basic ones again. */ while ( remove_empty_relations(group) /* * If there is a relation of length one, e.g. "a", do a handle * slide to cancel the relation (which is topologically a * thickened disk) with the generator (which is topologically * a handle of the handlebody). word_length_one() decreases both * the number of generators and the total length of all relations. */ || word_length_one(group) /* * If there is a relation of the form "ab", do the handle slide * and then a handle cancellation. word_length_two() decreases both * the number of generators and the total length of all relations. */ || word_length_two(group) /* * Consider all possible handle slides. If we find one which * reduces The Induction Variable (cf. above), do it. */ || try_handle_slides(group) /* * If a generator occurs in precisely one word, and occurs in that * word precisely twice, both times with the same sign, then we may * do handle slides to make the two occurrences of the generator * adjacent to one another. This decreases the number of runs * without increasing any other component of The Induction Variable. * For example, we could simplify the word "aabAAb" to "aaaabb". */ || two_singletons_in_group(group) /* * Look for a word in which a generator occurs precisely once, * and use that word to eliminate the generator. (Say the word * is "bcacb". First do handle slides to reduce it to "a", and * then do a handle cancellation.) * If group->minimize_number_of_generators is FALSE, a word will * be eliminated only if it does not increase the total length * of all relations. */ || eliminate_word_in_group(group) /* * Try to insert a copy of one word into another so that * after cancellations the second word is shorter than it * used to be. This reduces the total length of all * relations without increasing either the number of * generators or the length of the shortest nonempty * relation (unless a relation is eliminated entirely, * but that's OK). */ || insert_word_from_group(group) /* * If we have a GroupPresentation with exactly one word, * we can looks for patterns in that word, and introduce * a new generator which simplifies the presentation. E.g. * {(bbaa)b(bbaa)(bbaa)} -> {Cbbaa, (bbaa)b(bbaa)(bbaa)} * -> {Cbbaa, bccc} -> {CCCCCCCaa}. This approach is * particular useful for recognizing fundamental groups * of torus knots as a^n = b^m. */ || simplify_one_word_presentations(group) ) { /*NMD 2008/5/31*/ if (uLongComputationContinues() == func_cancelled) break; } /* * Try to simplify presentations of finite cyclic groups. */ lens_space_recognition(group); /* * If a generator appears more often as an inverse than as a * positive power, replace it with its inverse. * E.g. {AAbbc, abCCC, cB} -> {aabbC, Abccc, CB}. * * If a word contains more inverses than positive powers, * invert it. E.g. {aabbC, Abccc, CB} -> {aabbC, Abccc, bc}. * * Repeat as necessary. */ while ( invert_generators_where_necessary(group) == TRUE || invert_words_where_necessary(group) == TRUE) { /*NMD 2008/5/31*/ if (uLongComputationContinues() == func_cancelled) break; } /* * The starting point of a cyclic word is arbitrary. * Choose it to meet the following aesthetic criteria, * in descending order of importance: * * (1) Don't start a word in the middle of a run. * (2) Start with a positive power of a generator. * (3) Start with the lowest-numbered generator. * * These criteria are applied only to the relations, * not to the peripheral curves, because we want the * latter to commute. */ choose_word_starts(group); /* * Can we conjugate any (meridian, longitude) pairs * to shorten their length? E.g. (CBCbcc, Cac) -> (BCbc, a) * or (cbbc, Caac) -> (ccbb, aa). */ conjugate_peripheral_words(group); /* * Remove the dummy basepoint Letters from the meridians and longitudes, * and from the expressions for the original generators. */ remove_basepoints(group); } static void insert_basepoints( GroupPresentation *group) { insert_basepoints_on_list(group->itsMeridians); insert_basepoints_on_list(group->itsLongitudes); insert_basepoints_on_list(group->itsOriginalGenerators); } static void insert_basepoints_on_list( CyclicWord *list) { CyclicWord *word; for (word = list; word != NULL; word = word->next) insert_basepoint_in_word(word); } static void insert_basepoint_in_word( CyclicWord *word) { Letter *basepoint; basepoint = NEW_STRUCT(Letter); basepoint->itsValue = 0; if (word->itsLength > 0) INSERT_BEFORE(basepoint, word->itsLetters) else { basepoint->prev = basepoint; basepoint->next = basepoint; } word->itsLetters = basepoint; word->itsLength++; } static void remove_basepoints( GroupPresentation *group) { remove_basepoints_on_list(group->itsMeridians); remove_basepoints_on_list(group->itsLongitudes); remove_basepoints_on_list(group->itsOriginalGenerators); } static void remove_basepoints_on_list( CyclicWord *list) { CyclicWord *word; for (word = list; word != NULL; word = word->next) remove_basepoint_in_word(word); } static void remove_basepoint_in_word( CyclicWord *word) { Letter *letter, *basepoint; int i; /* * Find the basepoint. * There should be precisely one. */ basepoint = NULL; for ( letter = word->itsLetters, i = 0; i < word->itsLength; letter = letter->next, i++) if (letter->itsValue == 0) { /* * Report an error if we've already found a basepoint before this one. */ if (basepoint != NULL) uFatalError("remove_basepoint_in_word", "fundamental_group"); basepoint = letter; } /* * Report an error if we found no basepoint. */ if (basepoint == NULL) uFatalError("remove_basepoint_in_word", "fundamental_group"); if (word->itsLength > 1) { word->itsLetters = basepoint->next; REMOVE_NODE(basepoint); } else word->itsLetters = NULL; my_free(basepoint); word->itsLength--; } static Boolean word_length_one( GroupPresentation *group) { CyclicWord *word; for (word = group->itsRelations; word != NULL; word = word->next) if (word->is_Dehn_relation == FALSE || group->fillings_may_affect_generators == TRUE) if (word->itsLength == 1) { cancel_handles(group, word); return TRUE; } return FALSE; } static Boolean word_length_two( GroupPresentation *group) { CyclicWord *word; int a, b; for (word = group->itsRelations; word != NULL; word = word->next) if (word->is_Dehn_relation == FALSE || group->fillings_may_affect_generators == TRUE) if (word->itsLength == 2) { a = word->itsLetters->itsValue; b = word->itsLetters->next->itsValue; if (a != b && a != -b) { handle_slide(group, a, b); cancel_handles(group, word); return TRUE; } } return FALSE; } static Boolean try_handle_slides( GroupPresentation *group) { /* * We want to consider all possible handles slides. * As explained in handle_slide(), a handle slide is determined by * two generators. For example, if the generators are {a, b}, * the potential handle slides are * * (BB) BA Ba (Bb) * AB (AA) (Aa) Ab * aB (aA) (aa) ab * (bB) bA ba (bb) * * Geometrically impossible combinations are shown in parentheses. * In a GroupPresentation with n generators, the above chart would have * (2n)*(2n) entries, (2n)2 of which are impossible, leaving 4n(n-1) * potential handle slides to consider. */ int a, b; /* * Abuse notation and let "ab" be a generic entry in the above table. * That is, "ab" will range over all possible handle slides. */ for (a = - group->itsNumGenerators; a <= group->itsNumGenerators; a++) { if (a == 0) /* There is no generator 0. */ continue; for (b = - group->itsNumGenerators; b <= group->itsNumGenerators; b++) { if (b == 0) /* There is no generator 0. */ continue; if (b == a || b == -a) /* Geometrically meaningless, cf. above. */ continue; if (substring_occurs_in_group(group, a, b) == TRUE && handle_slide_improves_presentation(group, a, b) == TRUE) { handle_slide(group, a, b); return TRUE; } } } return FALSE; } static Boolean substring_occurs_in_group( GroupPresentation *group, int a, int b) { CyclicWord *word; /* * a and b should be distinct generators. */ if (a == b || a == -b) uFatalError("substring_occurs_in_group", "fundamental_group"); /* * Does the substring "ab" occur somewhere in the group? */ for (word = group->itsRelations; word != NULL; word = word->next) if (word->is_Dehn_relation == FALSE || group->fillings_may_affect_generators == TRUE) if (substring_occurs_in_word(word, a, b) == TRUE) return TRUE; return FALSE; } static Boolean substring_occurs_in_word( CyclicWord *word, int a, int b) { Letter *letter; int i; for ( letter = word->itsLetters, i = 0; i < word->itsLength; letter = letter->next, i++) if ((letter->itsValue == a && letter->next->itsValue == b) || (letter->itsValue == -a && letter->prev->itsValue == -b)) return TRUE; return FALSE; } static Boolean handle_slide_improves_presentation( GroupPresentation *group, int a, int b) { /* * We want to evaluate the effect of the handle slide "ab". * As explained in handle_slide(), the handle slide "ab" acts by * * "a" -> "aB" * "A" -> "bA" * * If group->minimize_number_of_generators is TRUE, we want to see * whether the handle slide would decrease The Induction Variable * defined in simplify() as * * (number of generators, * length of shortest nonempty relation, * total length of all relations, * total number of runs in all relations, * total length of all meridians and longitudes). * * If group->minimize_number_of_generators is FALSE, we want to see * whether the handle slide would decrease The Induction Variable * * (total length of all relations, * total number of runs in all relations, * length of shortest nonempty relation, * total length of all meridians and longitudes). * * Handle slides never change the number of generators, * so we may ignore that component of The Induction Variable. * We check how the handle slide would change the other components * of The Induction Variable, and return TRUE if it would be improved, * or FALSE if it would be the same or worse. */ int shortest_nonempty_relation_before, shortest_nonempty_relation_after, change_in_total_length, change_in_num_runs; shortest_nonempty_relation_before = INT_MAX; shortest_nonempty_relation_after = INT_MAX; change_in_total_length = 0; change_in_num_runs = 0; evaluate_handle_slide_in_group( group, a, b, &shortest_nonempty_relation_before, &shortest_nonempty_relation_after, &change_in_total_length, &change_in_num_runs); if (group->minimize_number_of_generators == TRUE) { if (shortest_nonempty_relation_after < shortest_nonempty_relation_before) return TRUE; if (shortest_nonempty_relation_after > shortest_nonempty_relation_before) return FALSE; } if (change_in_total_length < 0) return TRUE; if (change_in_total_length > 0) return FALSE; if (change_in_num_runs < 0) return TRUE; if (change_in_num_runs > 0) return FALSE; if (group->minimize_number_of_generators == FALSE) { if (shortest_nonempty_relation_after < shortest_nonempty_relation_before) return TRUE; if (shortest_nonempty_relation_after > shortest_nonempty_relation_before) return FALSE; } /* * The value of The Induction Variable wouldn't change, * so return FALSE. */ return FALSE; } static void evaluate_handle_slide_in_group( GroupPresentation *group, int a, int b, int *shortest_nonempty_relation_before, int *shortest_nonempty_relation_after, int *change_in_total_length, int *change_in_num_runs) { CyclicWord *word; for (word = group->itsRelations; word != NULL; word = word->next) if (word->is_Dehn_relation == FALSE || group->fillings_may_affect_generators == TRUE) evaluate_handle_slide_on_word( word, a, b, shortest_nonempty_relation_before, shortest_nonempty_relation_after, change_in_total_length, change_in_num_runs); } static void evaluate_handle_slide_on_word( CyclicWord *word, int a, int b, int *shortest_nonempty_relation_before, int *shortest_nonempty_relation_after, int *change_in_total_length, int *change_in_num_runs) { int delta_length, delta_runs, old_length, new_length; delta_length = compute_delta_length(word, a, b); delta_runs = compute_delta_runs (word, a, b); old_length = word->itsLength; new_length = old_length + delta_length; if (old_length < *shortest_nonempty_relation_before) *shortest_nonempty_relation_before = old_length; if (new_length < *shortest_nonempty_relation_after) *shortest_nonempty_relation_after = new_length; *change_in_total_length += delta_length; *change_in_num_runs += delta_runs; } static int compute_delta_length( CyclicWord *word, int a, int b) { /* * Lemma. Handle slides may cause cancellations, but they don't * cause "secondary cancellations". That is, when you do "a" -> "aB" * you may find that the following letter is a 'b', so you get * "ab" -> "aBb" -> "a" (indeed, this is the whole purpose of * handle slides). However, the "Bb" cancellation won't allow * any additional cancellations to occur. If you had "abA", * you'd just get "abA" -> "aBbbA" -> "abA". This last example * is an important special case in the following code. */ int delta_length, i; Letter *letter; delta_length = 0; for ( letter = word->itsLetters, i = 0; i < word->itsLength; letter = letter->next, i++) { /* * When we see 'a' or 'A' we increment the length of the word * to account for the handle slide. (Cancellations will be * dealt with momentarily.) */ if (letter->itsValue == a || letter->itsValue == -a) delta_length++; /* * When we see a 'b' immediately preceded by an 'a' we decrement * the length of the word by two to account for the cancellation, * and similarly for a 'B' immediately followed by an 'A'. * As explained in the above lemma, these are the only * cancellations which may occur. */ if ((letter->itsValue == b && letter->prev->itsValue == a) || (letter->itsValue == -b && letter->next->itsValue == -a)) delta_length -= 2; } return delta_length; } static int compute_delta_runs( CyclicWord *word, int a, int b) { /* * Counting the change in the number of runs is trickier than * counting the change in the length. * * Recall that the number of runs is actually the number of * transitions from one run to another; i.e. a word with one * run has no transitions. * * The number of transitions can change just after an 'a' or just * before an 'A', but nowhere else. Typically a handle slide * introduces one new transition after an 'a': "ac" -> "aBc". * The exceptional cases appear in the table below, along with * the number of new transitions each introduces. * * "aa" -> "aBa" +2 * "aA" (shouldn't occur) * "aba" -> "aa" -2 * "abA" -> "abA" 0 * "abb" -> "ab" 0 * "abB" (shouldn't occur) * "abc" -> "ac" -1 * "aB" -> "aBB" 0 * "ac" -> "aBc" +1 * * A similar table lists the possible transition changes * preceding an 'A'. * * "AA" -> "AbA" +2 * "aA" (shouldn't occur) * "ABA" -> "AA" -2 * "aBA" -> "aBA" 0 * "BBA" -> "BA" 0 * "bBA" (shouldn't occur) * "CBA" -> "CA" -1 * "bA" -> "bbA" 0 * "CA" -> "CbA" +1 * * The only case where we have to worry about "double counting" * is "aBA" -> "aBA". It gets considered once when we examine * the 'a' and again when we examine the 'A'. Fortunately the * net change in transitions is zero, so this "double counting" * is harmless. */ int delta_runs, i; Letter *letter; delta_runs = 0; for ( letter = word->itsLetters, i = 0; i < word->itsLength; letter = letter->next, i++) { if (letter->itsValue == a) { if (letter->next->itsValue == a) /* * "aa" -> "aBa" */ delta_runs += 2; else if (letter->next->itsValue == -a) /* * "aA" should not occur. */ uFatalError("compute_delta_runs", "fundamental_group"); else if (letter->next->itsValue == b) /* * "ab" -> "aBb" -> "a" * * Break into cases according to the value * of the next letter. */ { if (letter->next->next->itsValue == a) /* * "aba" -> "aBba" -> "aa" */ delta_runs -= 2; else if (letter->next->next->itsValue == -a) /* * "abA" -> "aBbbA" -> "abA" */ delta_runs += 0; else if (letter->next->next->itsValue == b) /* * "abb" -> "aBbb" -> "ab" */ delta_runs += 0; else if (letter->next->next->itsValue == -b) /* * "abB" should not occur. */ uFatalError("compute_delta_runs", "fundamental_group"); else /* * "abc" -> "aBbc" -> "ac" */ delta_runs -= 1; } else if (letter->next->itsValue == -b) /* * "aB" -> "aBB" */ delta_runs += 0; else /* * "ac" -> "aBc" */ delta_runs += 1; } if (letter->itsValue == -a) { if (letter->prev->itsValue == -a) /* * "AA" -> "AbA" */ delta_runs += 2; else if (letter->prev->itsValue == a) /* * "aA" should not occur. */ uFatalError("compute_delta_runs", "fundamental_group"); else if (letter->prev->itsValue == -b) /* * "BA" -> "BbA" -> "A" * * Break into cases according to the value * of the preceding letter. */ { if (letter->prev->prev->itsValue == -a) /* * "ABA" -> "ABbA" -> "AA" */ delta_runs -= 2; else if (letter->prev->prev->itsValue == a) /* * "aBA" -> "aBBbA" -> "aBA" */ delta_runs += 0; else if (letter->prev->prev->itsValue == -b) /* * "BBA" -> "BBbA" -> "BA" */ delta_runs += 0; else if (letter->prev->prev->itsValue == b) /* * "bBA" should not occur. */ uFatalError("compute_delta_runs", "fundamental_group"); else /* * "CBA" -> "CBbA" -> "CA" */ delta_runs -= 1; } else if (letter->prev->itsValue == b) /* * "bA" -> "bbA" */ delta_runs += 0; else /* * "CA" -> "CbA" */ delta_runs += 1; } } return delta_runs; } static Boolean two_singletons_in_group( GroupPresentation *group) { /* * If a generator occurs in precisely one word, and occurs in that * word precisely twice, both times with the same sign, * then we may do handle slides to make the two occurrences of the * generator adjacent to one another, without lengthening the word. * For example, we could simplify the word "aabAAb" to "aaaabb". * * This is a geometric operation. It preserves the pseudo-Heegaard * diagram discussed at the top of this file. */ int i; CyclicWord *word_containing_singletons; for (i = 1; i <= group->itsNumGenerators; i++) if (generator_occurs_as_two_singletons_in_group(group, i, &word_containing_singletons) && generator_occurs_in_no_other_word_in_group(group, i, word_containing_singletons)) { make_singletons_adjacent(group, i, word_containing_singletons); return TRUE; } return FALSE; } static Boolean generator_occurs_as_two_singletons_in_group( GroupPresentation *group, int value, CyclicWord **word_containing_singletons) { CyclicWord *word; for (word = group->itsRelations; word != NULL; word = word->next) if (word->is_Dehn_relation == FALSE || group->fillings_may_affect_generators == TRUE) if (generator_occurs_as_two_singletons_in_word(word, value) == TRUE) { *word_containing_singletons = word; return TRUE; } *word_containing_singletons = NULL; return FALSE; } static Boolean generator_occurs_as_two_singletons_in_word( CyclicWord *word, int value) { int num_plus, num_minus, i; Letter *letter; num_plus = 0; num_minus = 0; for ( letter = word->itsLetters, i = 0; i < word->itsLength; letter = letter->next, i++) { /* * Count positive occurrences. */ if (letter->itsValue == value) num_plus++; /* * Count negative occurrences. */ if (letter->itsValue == - value) num_minus++; /* * Reject consecutive occurrences. */ if ( ( letter->itsValue == value || letter->itsValue == - value) && ( letter->next->itsValue == value || letter->next->itsValue == - value) ) return FALSE; } return ((num_plus == 2 && num_minus == 0) || (num_plus == 0 && num_minus == 2)); } static Boolean generator_occurs_in_no_other_word_in_group( GroupPresentation *group, int value, CyclicWord *word_containing_singletons) { CyclicWord *word; for (word = group->itsRelations; word != NULL; word = word->next) if (word->is_Dehn_relation == FALSE || group->fillings_may_affect_generators == TRUE) if (word != word_containing_singletons && generator_occurs_in_word(word, value) == TRUE) return FALSE; return TRUE; } static Boolean generator_occurs_in_word( CyclicWord *word, int value) { Letter *letter; int i; for ( letter = word->itsLetters, i = 0; i < word->itsLength; letter = letter->next, i++) if (letter->itsValue == value || letter->itsValue == - value) return TRUE; return FALSE; } static void make_singletons_adjacent( GroupPresentation *group, int value, CyclicWord *word) { /* * Other functions have already verified that value occurs exactly * twice in word, both times with the same sign, and occurs nowhere * else in the GroupPresentation. */ /* * Advance word->itsLetters to point at an occurrence of value * or its inverse. */ while ( word->itsLetters->itsValue != value && word->itsLetters->itsValue != - value) word->itsLetters = word->itsLetters->next; /* * Do handle slides until the two occurrence of value are adjacent. */ while (word->itsLetters->itsValue != word->itsLetters->next->itsValue) handle_slide( group, word->itsLetters->itsValue, word->itsLetters->next->itsValue); } static Boolean eliminate_word_in_group( GroupPresentation *group) { /* * Look for a generator which occurs precisely once in some word, * and use the word to eliminate the generator. For example, * say the word is "bcacb". First do handle slides to reduce it * to "a", and then do a handle cancellation. * * Try to choose a generator and a word which increase the total * length of all relations as little as possible. * If group->minimize_number_of_generators is FALSE, insist that * the total length of all relations must decrease. * * Return TRUE if successful, FALSE if no such word exists. */ int delta_length, best_delta, best_generator, m, n, generator; CyclicWord *word_with_singleton, *best_word; best_delta = INT_MAX; best_generator = 0; best_word = NULL; for (generator = 1; generator <= group->itsNumGenerators; generator++) { word_with_singleton = shortest_word_in_which_generator_occurs_precisely_once (group, generator); if (word_with_singleton != NULL) { /* * By how much would the total length of all relations increase * if we eliminated this generator via this word? */ m = word_with_singleton->itsLength; n = occurrences_in_group(group, generator); delta_length = n*(m-1) /* effect of handle slides */ - 2*(m-1) /* effect of cancellations in this word */ - n; /* effect of eliminating generator */ if (delta_length < best_delta) { best_delta = delta_length; best_generator = generator; best_word = word_with_singleton; } } } if ( best_word != NULL && ( group->minimize_number_of_generators == TRUE || best_delta < 0 ) ) { eliminate_word(group, best_word, best_generator); return TRUE; } else return FALSE; } static CyclicWord *shortest_word_in_which_generator_occurs_precisely_once( GroupPresentation *group, int generator) { /* * Find the shortest word in which the generator occurs precisely once. */ CyclicWord *word, *best_word; best_word = NULL; for (word = group->itsRelations; word != NULL; word = word->next) if (word->is_Dehn_relation == FALSE || group->fillings_may_affect_generators == TRUE) if (generator_occurs_precisely_once_in_word(word, generator) == TRUE) if (best_word == NULL || word->itsLength < best_word->itsLength) best_word = word; return best_word; } static Boolean generator_occurs_precisely_once_in_word( CyclicWord *word, int generator) { return (occurrences_in_word(word, generator) == 1); } static int occurrences_in_group( GroupPresentation *group, int generator) { int occurrences; CyclicWord *word; occurrences = 0; for (word = group->itsRelations; word != NULL; word = word->next) if (word->is_Dehn_relation == FALSE || group->fillings_may_affect_generators == TRUE) occurrences += occurrences_in_word(word, generator); return occurrences; } static int occurrences_in_word( CyclicWord *word, int generator) { int i, num_occurrences; Letter *letter; num_occurrences = 0; for ( letter = word->itsLetters, i = 0; i < word->itsLength; letter = letter->next, i++) if (letter->itsValue == generator || letter->itsValue == - generator) num_occurrences++; return num_occurrences; } static void eliminate_word( GroupPresentation *group, CyclicWord *word, int generator) { Letter *letter; /* * eliminate_word_in_group() should have already checked * that generator occurs precisely once in word. */ if (generator_occurs_precisely_once_in_word(word, generator) == FALSE) uFatalError("eliminate_word", "fundamental_group"); /* * Find the Letter containing the unique occurrence of the generator. */ for ( letter = word->itsLetters; letter->itsValue != generator && letter->itsValue != - generator; letter = letter->next ) ; /* * Do handle slides until only "letter" is left, then * do a handle cancellation. */ while (word->itsLength > 1) handle_slide(group, letter->itsValue, letter->next->itsValue); cancel_handles(group, word); } static Boolean remove_empty_relations( GroupPresentation *group) { Boolean words_were_removed; CyclicWord **list, *dead_word; words_were_removed = FALSE; list = &group->itsRelations; while (*list != NULL) { if ((*list)->itsLength == 0) { dead_word = *list; *list = (*list)->next; free_cyclic_word(dead_word); group->itsNumRelations--; words_were_removed = TRUE; } else list = &(*list)->next; } return words_were_removed; } static Boolean insert_word_from_group( GroupPresentation *group) { /* * Try to insert a copy of one word into another so that after * cancellations the second word is shorter than it used to be. * For example, in the presentation * * BaBABABaB * BaBAA * * we can substitute the inverse of the second word into the * first word to obtain * * BaBA(abAba)BABaB * BaBAA * * which simplifies to * * aBABaB * BaBAA * * Do it again to obtain * * aBABaB(bAbaa) * BaBAA * * which simplifies to * * aBa * BaBAA * * The usual geometric simplifications now reduce this presentation to * * AAAAA */ CyclicWord *word; /* * Consider all possible words which we might want to insert * into another word. */ for (word = group->itsRelations; word != NULL; word = word->next) if (word->is_Dehn_relation == FALSE || group->fillings_may_affect_generators == TRUE) if (insert_word_into_group(group, word) == TRUE) return TRUE; return FALSE; } static Boolean insert_word_into_group( GroupPresentation *group, CyclicWord *word) { /* * The "word" shouldn't be a Dehn relation if * group->fillings_may_affect_generators is FALSE, * but the "target" can always be any kinds of relation. * Simplifying the Dehn relations won't have any effect * on either the choice of generators or the edge relations. */ return ( insert_word_into_list(group->itsRelations, word) == TRUE || insert_word_into_list(group->itsMeridians, word) == TRUE || insert_word_into_list(group->itsLongitudes, word) == TRUE || insert_word_into_list(group->itsOriginalGenerators, word) == TRUE); } static Boolean insert_word_into_list( CyclicWord *list, CyclicWord *word) { CyclicWord *target; for (target = list; target != NULL; target = target->next) if (insert_word_into_word(word, target) == TRUE) return TRUE; return FALSE; } static Boolean insert_word_into_word( CyclicWord *word, CyclicWord *target) { int i, j; /* * Don't insert a word into itself. */ if (word == target) return FALSE; /* * One CyclicWord may be inserted into another in many different * ways. For example, if word = "abc" and target = "defg", there * are 24 ways to insert word into target: * * (abc)defg d(abc)efg de(abc)fg def(abc)g * (bca)defg d(bca)efg de(bca)fg def(bca)g * (cab)defg d(cab)efg de(cab)fg def(cab)g * * (CBA)defg d(CBA)efg de(CBA)fg def(CBA)g * (ACB)defg d(ACB)efg de(ACB)fg def(ACB)g * (BAC)defg d(BAC)efg de(BAC)fg def(BAC)g * * Comment: The algorithm considers cancellations at only one end * of the inserted word. For example, when it inserts "abcd" into * "ADCef" to obtain "A(abcd)DCef", the program will consider the * cancellations "cdDC", but will ignore the "Aa". This is OK. * At some other point in its nested loops it will consider * "(bcda)ADCef", thereby recognizing the fullest cancellation. * * We use word->itsLetters and target->itsLetters to mark * the possible insertion points. Note too that the following * code automatically ignores relations of length zero. */ for (i = 0; i < word->itsLength; i++) { for (j = 0; j < target->itsLength; j++) { if (insert_word_forwards(word, target) == TRUE || insert_word_backwards(word, target) == TRUE) return TRUE; target->itsLetters = target->itsLetters->next; } word->itsLetters = word->itsLetters->next; } return FALSE; } static Boolean insert_word_forwards( CyclicWord *word, CyclicWord *target) { /* * If, say, word = "abc" and target = "defg", * would replacing target with "abcdefg" reduce the length * of target after cancelling inverses? */ int remaining_cancellations, i; Letter *next_letter_in_word, *next_letter_in_target, *letter, *letter_copy; /* * insert_word_into_word guarantees that * both word and target are nonempty. */ if (word->itsLength == 0 || target->itsLength == 0) uFatalError("insert_word_forwards", "fundamental_group"); /* * More than half the Letters in word must cancel with letters in target. */ remaining_cancellations = (word->itsLength + 2) / 2; /* * If target isn't long enough, let's give up now so we can ignore * the cyclic nature of the target in the code below. (Otherwise * a target "ab" might gives the illusion of completely cancelling * a word "BABABABABA".) */ if (target->itsLength < remaining_cancellations) return FALSE; /* * Check whether the last remaining_cancellations Letters in word * cancel with the first remaining_cancellations Letters in target. * (See the comment in insert_word_into_word() for an explanation * of why it's OK to ignore possible cancellations of letters * at the beginning of word with letters at the end of target.) */ next_letter_in_word = word->itsLetters->prev; next_letter_in_target = target->itsLetters; while (remaining_cancellations > 0) { if (next_letter_in_word->itsValue + next_letter_in_target->itsValue == 0) { remaining_cancellations--; next_letter_in_word = next_letter_in_word ->prev; next_letter_in_target = next_letter_in_target->next; } else return FALSE; } /* * Great! They cancel! * Let's insert a copy of word into target, and do the cancellations. * If we're lucky, we may even get more cancellations than just the * minimum. */ /* * Insert the copy. */ for ( letter = word->itsLetters, i = 0; i < word->itsLength; letter = letter->next, i++) { letter_copy = NEW_STRUCT(Letter); letter_copy->itsValue = letter->itsValue; INSERT_BEFORE(letter_copy, target->itsLetters); target->itsLength++; } /* * Do the cancellations. */ cancel_inverses_word(target); return TRUE; } static Boolean insert_word_backwards( CyclicWord *word, CyclicWord *target) { /* * If, say, word = "abc" and target = "defg", * would replacing target with "CBAdefg" reduce the length * of target after cancelling inverses? */ int remaining_cancellations, i; Letter *next_letter_in_word, *next_letter_in_target, *letter, *letter_copy; /* * insert_word_into_word guarantees that * both word and target are nonempty. */ if (word->itsLength == 0 || target->itsLength == 0) uFatalError("insert_word_backwards", "fundamental_group"); /* * More than half the Letters in word must cancel with letters in target. */ remaining_cancellations = (word->itsLength + 2) / 2; /* * If target isn't long enough, let's give up now so we can ignore * the cyclic nature of the target in the code below. (Otherwise * a target "ab" might gives the illusion of completely cancelling * a word "abababababab".) */ if (target->itsLength < remaining_cancellations) return FALSE; /* * Check whether the first remaining_cancellations Letters in word * match the first remaining_cancellations Letters in target. * (See the comment in insert_word_into_word() for an explanation * of why it's OK to ignore possible matches of letters at the ends * of word and target.) */ next_letter_in_word = word->itsLetters; next_letter_in_target = target->itsLetters; while (remaining_cancellations > 0) { if (next_letter_in_word->itsValue == next_letter_in_target->itsValue) { remaining_cancellations--; next_letter_in_word = next_letter_in_word ->next; next_letter_in_target = next_letter_in_target->next; } else return FALSE; } /* * Great! They cancel! * Let's insert a copy of word's inverse into target, and do the * cancellations. If we're lucky, we may even get more cancellations * than just the minimum. */ /* * Insert the copy. */ for ( letter = word->itsLetters->prev, i = 0; i < word->itsLength; letter = letter->prev, i++) { letter_copy = NEW_STRUCT(Letter); letter_copy->itsValue = - letter->itsValue; INSERT_BEFORE(letter_copy, target->itsLetters); target->itsLength++; } /* * Do the cancellations. */ cancel_inverses_word(target); return TRUE; } static Boolean simplify_one_word_presentations( GroupPresentation *group) { /* * In general we'd like one-word presentations to be as simple * as possible. In particular, we'd like to display the fundamental * group of a torus knot as a^n = b^m, so the user can recognize * it easily. * * Often the presentation for a torus knot group is something like * bbaabbbaabbaa. We can use the repeating pattern (bbaa)b(bbaa)(bbaa) * to simplify the presentation. Introduce c = bbaa, so the * presentation becomes {Cbbaa, bccc}, then eliminate b = CCC to get * {CCCCCCCaa}. * * It's easy to prove that the word gets shorter iff it's * not a power of a single variable, like b^13 = b(bbbb)(bbbb)(bbbb). * [added 2008/5/31 by JRW] */ CyclicWord *word, *new_word; int num_matched_letters, period, repetitions; Letter *unmatched_letter; int i, j; /* * If this isn't a one-word presentation with at least two generators, * don't do anything. */ if (group->itsNumRelations != 1 || group->itsNumGenerators < 2) return FALSE; /* * Find the unique relation. */ word = group->itsRelations; /* * If the unique relation is a power of a single variable, don't do anything. * [added 2008/5/31 by JRW] */ if (count_runs(word) == 0) return FALSE; /* * Is it OK for this relation to influence the choice of generators? */ if (word->is_Dehn_relation == TRUE && group->fillings_may_affect_generators == FALSE) return FALSE; /* * Terminology. In the example (bbaa)b(bbaa)(bbaa), the 'b' not * in parentheses is called the "unmatched" letter. The remaining * letters are "matched". The period is 4, and the number of * repetitions is 3. */ /* * We can ignore patterns of period one, because they will be either of * the form "aaaaaa" (which needs no simplification) or "baaaaaa" (which * would have already been eliminated by eliminate_word_in_group()). * * We can ignore patterns of period two, because they will be of the * form "bbabababa", which would have already been simplified by * try_handle_slides() -- this is a one-word presentation. * * We can ignore patterns of period three, for the same reason. * * Therefore we look only for patterns of period four or greater. */ num_matched_letters = word->itsLength - 1; for (period = 4; period < num_matched_letters; period++) if (num_matched_letters % period == 0) { repetitions = num_matched_letters / period; /* * Try all possibilities for the unmatched_letter. */ for ( unmatched_letter = word->itsLetters, i = 0; i < word->itsLength; unmatched_letter = unmatched_letter->next, i++) if (word_contains_pattern( unmatched_letter, period, repetitions) == TRUE) { /* * Create the new word, * e.g. {bbaabbbaabbaa} -> {bbaabbbaabbaa, Cbbaa}. */ new_word = introduce_generator( group, unmatched_letter->next, period); /* * Make sure the new_word is inserted * at the correct positon. * JRW 28 Feb 2002 */ /* Cbbaa -> bbaaC */ new_word->itsLetters = new_word->itsLetters->next; /* bbaabbbaabbaa -> bbaabbaabbaab */ word->itsLetters = unmatched_letter->next; /* * Insert the new word into the old, * e.g. {bbaabbaabbaab, bbaaC} * -> {cbbaabbaab, bbaaC} * -> {bbaabbaabc, bbaaC} * -> {cbbaabc, bbaaC} * -> {bbaabcc, bbaaC} * -> {cbcc, bbaaC} * -> {bccc, bbaaC} */ for (j = 0; j < repetitions; j++) { if (insert_word_backwards(new_word, word) == FALSE) uFatalError("simplify_one_word_presentations", "fundamental_group.c"); word->itsLetters = word->itsLetters->next; } /* * Eliminate the original word, * e.g. {bccc, bbaaC} -> {CCCCCCCaa}. */ eliminate_word(group, word, unmatched_letter->itsValue); /* * All done. */ return TRUE; } } return FALSE; } static Boolean word_contains_pattern( Letter *unmatched_letter, int period, int repetitions) { int i, j, k; Letter *letter, *image; for ( i = 0, letter = unmatched_letter->next; i < period; i++, letter = letter->next) { image = letter; for ( j = 0; j < repetitions; j++) { if (image->itsValue != letter->itsValue) return FALSE; for (k = 0; k < period; k++) image = image->next; } } return TRUE; } static CyclicWord *introduce_generator( GroupPresentation *group, Letter *substring, int length) { /* * Introduce a new generator into the group presentation. * It will be of the form c = baaba, where baaba is a substring of * some other word; the function argument "substring" points to the * first letter in the substring, and "length" gives its length. */ O31Matrix *new_array, the_inverse; MoebiusTransformation *new_MT_array, the_MT_inverse; int i; Letter *letter, *new_generator_letter, *letter_copy; CyclicWord *new_word; /* * Should the new relation be an edge relation or a Dehn relation? * Really, of course, it is neither. * But to have gotten this far, either * group->fillings_may_affect_generators is TRUE, or it is FALSE and * the only relation is an edge relation. So it is safe to call * the new relation an edge relation. */ if ( group->fillings_may_affect_generators == FALSE && ( group->itsNumRelations != 1 || group->itsRelations->is_Dehn_relation == TRUE ) ) uFatalError("introduce_generator", "fundamental_group"); /* * Create the new generator. */ /* * Allocate a bigger array for the matrix generators, * copy in the existing values, and free the old array. */ new_array = NEW_ARRAY(group->itsNumGenerators + 1, O31Matrix); new_MT_array = NEW_ARRAY(group->itsNumGenerators + 1, MoebiusTransformation); for (i = 0; i < group->itsNumGenerators; i++) { o31_copy(new_array[i], group->itsMatrices[i]); Moebius_copy(&new_MT_array[i], &group->itsMTs[i]); } my_free(group->itsMatrices); group->itsMatrices = new_array; my_free(group->itsMTs); group->itsMTs = new_MT_array; /* * Create the new matrix. */ o31_copy(group->itsMatrices[group->itsNumGenerators], O31_identity); Moebius_copy(&group->itsMTs[group->itsNumGenerators], &Moebius_identity); for ( i = 0, letter = substring; i < length; i++, letter = letter->next) if (letter->itsValue > 0) { o31_product(group->itsMatrices[group->itsNumGenerators], group->itsMatrices[letter->itsValue - 1], group->itsMatrices[group->itsNumGenerators]); Moebius_product(&group->itsMTs[group->itsNumGenerators], &group->itsMTs[letter->itsValue - 1], &group->itsMTs[group->itsNumGenerators]); } else { o31_invert( group->itsMatrices[(-letter->itsValue) - 1], the_inverse); o31_product(group->itsMatrices[group->itsNumGenerators], the_inverse, group->itsMatrices[group->itsNumGenerators]); Moebius_invert( &group->itsMTs[(-letter->itsValue) - 1], &the_MT_inverse); Moebius_product(&group->itsMTs[group->itsNumGenerators], &the_MT_inverse, &group->itsMTs[group->itsNumGenerators]); } /* * Increment group->itsNumGenerators. */ group->itsNumGenerators++; /* * Create the new relation. * * If the new word is, say, c = babba, we'll construct it as Cbabba. * Note that it begins with the inverse of the new generator. */ new_generator_letter = NEW_STRUCT(Letter); new_generator_letter->itsValue = - group->itsNumGenerators; new_generator_letter->next = new_generator_letter; new_generator_letter->prev = new_generator_letter; new_word = NEW_STRUCT(CyclicWord); new_word->itsLength = length + 1; new_word->itsLetters = new_generator_letter; for ( i = 0, letter = substring; i < length; i++, letter = letter->next) { letter_copy = NEW_STRUCT(Letter); letter_copy->itsValue = letter->itsValue; INSERT_BEFORE(letter_copy, new_generator_letter); } /* * Record what we done so we can later reconstruct the current * generators in terms of the original ones. */ update_word_moves(group, group->itsNumGenerators); for (i = 0, letter = substring; i < length; i++, letter=letter->next) update_word_moves(group, letter->itsValue); update_word_moves(group, group->itsNumGenerators); /* * The new_word may be considered an edge relation, as explained above. */ new_word->is_Dehn_relation = FALSE; new_word->next = group->itsRelations; group->itsRelations = new_word; group->itsNumRelations++; return new_word; } static void lens_space_recognition( GroupPresentation *group) { /* * We want to be able to recognize a presentation like * * bbbaaaa * bbbbbbbbaaa * * as a lens space. We use the Euclidean algorithm. * (In this example it would be more efficient to start with the a's, * but I'll start with the b's instead so I can show two iterations * of the basic process.) * Interpret the first relation as bbb = AAAA, and substitute it * into the second relation. * * bbbaaaa * AAAAAAAAbbaaa * * Cancel AAA with aaa. * * bbbaaaa * AAAAAbb * * Now interpret the second relation as bb = aaaaa and substitute * it back into the first relation. * * baaaaaaaaa * AAAAAbb * * Interpret the first relation as b = AAAAAAAAA and substitute it * into the second relation. * * baaaaaaaaa * AAAAAAAAAAAAAAAAAAAAAAA * * Eliminate generator b. * * AAAAAAAAAAAAAAAAAAAAAAA * * This shows that the group is Z/23. * * (The actual code in lens_space_recognition_using_generator() uses * a slightly different implementation, but this is the general idea.) */ int generator; /* * Do we have permission to reduce the number of generators? */ if (group->fillings_may_affect_generators == FALSE) return; /* * A more general version of this code would apply to free * products of finite cyclic groups with other groups. * For now we insist that the group as a whole is finite cyclic. */ /* * Are there exactly two generators? */ if (group->itsNumGenerators != 2) return; /* * Are there exactly two relations? * (Note: By this point empty relations will have been eliminated.) */ if (group->itsNumRelations != 2) return; /* * Do a quick error check. */ if (group->itsRelations == NULL || group->itsRelations->next == NULL || group->itsRelations->next->next != NULL) uFatalError("lens_space_recognition", "fundamental_group"); /* * Are both words of the form a^m = b^n ? */ if (count_runs( group->itsRelations ) > 2 || count_runs( group->itsRelations->next ) > 2) return; /* * Try the Euclidean algorithm on each generator in turn. * Break if successful. */ for (generator = 1; generator <= 2; generator++) if (lens_space_recognition_using_generator(group, generator) == TRUE) break; } static int count_runs( CyclicWord *word) { int num_runs, i; Letter *letter; num_runs = 0; for ( letter = word->itsLetters, i = 0; i < word->itsLength; letter = letter->next, i++) if (letter->itsValue != letter->next->itsValue) num_runs++; return num_runs; } static Boolean lens_space_recognition_using_generator( GroupPresentation *group, int generator0) { int i, j, value_of_b, power_of_b, occurrences[2], generator[2], n[2][2]; long int p, q; CyclicWord *word[2], *new_word; Letter *letter_a, *letter_b; /* * Note the two words. */ word[0] = group->itsRelations; word[1] = group->itsRelations->next; /* * How many times does the generator occur in each word? */ for (i = 0; i < 2; i++) occurrences[i] = occurrences_in_word(word[i], generator0); /* * If this generator occurs in only one word, give up. */ for (i = 0; i < 2; i++) if (occurrences[i] == 0) return FALSE; /* * If the number of occurrences are not relatively prime, * give up. */ if (gcd(occurrences[0], occurrences[1]) > 1) return FALSE; /* * Think of the given generator as 'a' and the * other generator as 'b'. */ generator[0] = generator0; generator[1] = 3 - generator0; /* * Count the number of signed occurrences * of each generator in each word. */ for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) n[i][j] = count_signed_occurrences_in_word(word[i], generator[j]); /* * The relations are * * a^n[0][0] * b^n[0][1] = 1 * a^n[1][0] * b^n[1][1] = 1 * or * a^n[0][0] = b^-n[0][1] * a^n[1][0] = b^-n[1][1] * * Find p and q such that p*n[0][0] + q*n[1][0] = gcd(n[0][0], n[1][0]) = 1. */ (void) euclidean_algorithm(n[0][0], n[1][0], &p, &q); /* * a = a^1 * = a^(p*n[0][0] + q*n[1][0]) * = a^(p*n[0][0]) * a^(q*n[1][0]) * = (a^n[0][0])^p * (a^n[1][0])^q * = (b^-n[0][1])^p * (b^-n[1][1])^q * = b^(-p*n[0][1]) * b^(-q*n[1][1]) * = b^-(p*n[0][1] + q*n[1][1]) * * Add the redundant relation * * a * b^(p*n[0][1] + q*n[1][1]) = 1 * * (Remember -- nongeometric operations are OK.) */ value_of_b = (p*n[0][1] + q*n[1][1] >= 0) ? generator[1] : -generator[1]; power_of_b = ABS(p*n[0][1] + q*n[1][1]); new_word = NEW_STRUCT(CyclicWord); new_word->itsLength = 1 + power_of_b; new_word->is_Dehn_relation = FALSE; new_word->next = group->itsRelations; group->itsRelations = new_word; group->itsNumRelations++; letter_a = NEW_STRUCT(Letter); letter_a->itsValue = generator[0]; letter_a->prev = letter_a; letter_a->next = letter_a; new_word->itsLetters = letter_a; for (i = 0; i < power_of_b; i++) { letter_b = NEW_STRUCT(Letter); letter_b->itsValue = value_of_b; INSERT_AFTER(letter_b, letter_a); } /* * Use the new_word to eliminate generator 'a'. */ eliminate_word(group, new_word, generator[0]); /* * We're left with two relations of the form * * b^r = 1 * b^s = 1 * * Keep substituting one into the other until one * becomes trivial and can be removed. */ while (remove_empty_relations(group) == FALSE) if (insert_word_from_group(group) == FALSE) uFatalError("lens_space_recognition_using_generator", "fundamental_group"); return TRUE; } static Boolean invert_generators_where_necessary( GroupPresentation *group) { /* * If a generator appears more often as an inverse than as a * positive power, replace it with its inverse. * E.g. {AAbbc, abCCC} -> {aabbC, Abccc}. */ int a, positive_occurrences, negative_occurrences; Boolean progress; progress = FALSE; for (a = 1; a <= group->itsNumGenerators; a++) { count_signed_occurrences_in_group( group, a, &positive_occurrences, &negative_occurrences); if (negative_occurrences > positive_occurrences) { invert_generator_in_group(group, a); progress = TRUE; } } return progress; } static void count_signed_occurrences_in_group( GroupPresentation *group, int a, int *positive_occurrences, int *negative_occurrences) { *positive_occurrences = 0; *negative_occurrences = 0; increment_signed_occurrences_in_group( group, a, positive_occurrences, negative_occurrences); } static void increment_signed_occurrences_in_group( GroupPresentation *group, int a, int *positive_occurrences, int *negative_occurrences) { CyclicWord *word; for (word = group->itsRelations; word != NULL; word = word->next) if (word->is_Dehn_relation == FALSE || group->fillings_may_affect_generators == TRUE) increment_signed_occurrences_in_word( word, a, positive_occurrences, negative_occurrences); } static void increment_signed_occurrences_in_word( CyclicWord *word, int a, int *positive_occurrences, int *negative_occurrences) { Letter *letter; int i; for ( letter = word->itsLetters, i = 0; i < word->itsLength; letter = letter->next, i++) { if (letter->itsValue == a) (*positive_occurrences)++; if (letter->itsValue == -a) (*negative_occurrences)++; } } static int count_signed_occurrences_in_word( CyclicWord *word, int a) { Letter *letter; int i, num_occurrences; num_occurrences = 0; for ( letter = word->itsLetters, i = 0; i < word->itsLength; letter = letter->next, i++) { if (letter->itsValue == a) num_occurrences++; if (letter->itsValue == -a) num_occurrences--; } return num_occurrences; } static void invert_generator_in_group( GroupPresentation *group, int a) { if (a < 1 || a > group->itsNumGenerators) uFatalError("invert_generator_in_group", "fundamental_group"); o31_invert(group->itsMatrices[a - 1], group->itsMatrices[a - 1]); Moebius_invert(&group->itsMTs[a - 1], &group->itsMTs[a - 1]); invert_generator_on_list(group->itsRelations, a); invert_generator_on_list(group->itsMeridians, a); invert_generator_on_list(group->itsLongitudes, a); invert_generator_on_list(group->itsOriginalGenerators, a); update_word_moves2(group, a, -a); } static void invert_generator_on_list( CyclicWord *list, int a) { CyclicWord *word; for (word = list; word != NULL; word = word->next) invert_generator_in_word(word, a); } static void invert_generator_in_word( CyclicWord *word, int a) { Letter *letter; int i; for ( letter = word->itsLetters, i = 0; i < word->itsLength; letter = letter->next, i++) { if (letter->itsValue == a) letter->itsValue = -a; else if (letter->itsValue == -a) letter->itsValue = a; } } static Boolean invert_words_where_necessary( GroupPresentation *group) { /* * Design decision: I considered inverting peripheral words where * necessary as well, but decided against it. Inverting a peripheral * word corresponds to reorienting the curve it represents. We * would still get the same length and torsion, so the reorientation * may be harmless, but it seems like a less than robust approach. * Who knows what somebody may someday do with this code. I'd hate * to introduce a bizarre bug. Better to just live with peripheral * curves which may contain more inverses than absolutely necessary. */ CyclicWord *word; Boolean progress; progress = FALSE; for (word = group->itsRelations; word != NULL; word = word->next) /* * Fix the word no matter what, but ... */ if (invert_word_if_necessary(word) == TRUE) /* * ...set progress = TRUE iff this inversion might allow * some generator to be profitably inverted as well. */ if (word->is_Dehn_relation == FALSE || group->fillings_may_affect_generators == TRUE) progress = TRUE; return progress; } static Boolean invert_word_if_necessary( CyclicWord *word) { if (sum_of_powers(word) < 0) { invert_word(word); return TRUE; } else return FALSE; } static int sum_of_powers( CyclicWord *word) { Letter *letter; int i, sum; sum = 0; for ( letter = word->itsLetters, i = 0; i < word->itsLength; letter = letter->next, i++) { if (letter->itsValue > 0) sum++; if (letter->itsValue < 0) sum--; } return sum; } static void invert_word( CyclicWord *word) { /* * For each Letter we must * * (1) negate itsValue, and * * (2) switch prev and next. * * The tricky part is keeping track of the Letters * while their prev and next fields are in flux. */ Letter *letter, *temp; if (word->itsLength == 0) return; letter = word->itsLetters; do { letter->itsValue = - letter->itsValue; temp = letter->prev; letter->prev = letter->next; letter->next = temp; /* * This is the delicate step. * We've swapped prev and next, so to move on to what used * to be the next Letter, we follow the prev pointer. */ letter = letter->prev; } while (letter != word->itsLetters); } static void choose_word_starts( GroupPresentation *group) { CyclicWord *word; for (word = group->itsRelations; word != NULL; word = word->next) choose_word_start(word); } static void choose_word_start( CyclicWord *word) { /* * The starting point of a cyclic word is arbitrary. * Choose it to meet the following criteria, in descending * order of importance: * * (1) Don't start a word in the middle of a run. * (2) Start with a positive power of a generator. * (3) Start with the lowest-numbered generator. * * Note the following code considers the letters of the CyclicWord * in order, so once it switches word->itsLetters to the beginning * of a run, it will always be at the beginning of a run. * Similarly, once it switches to a positive value, it will always * be at a positive value. */ Letter *letter; int i; for ( letter = word->itsLetters, i = 0; i < word->itsLength; letter = letter->next, i++) if ( ( word->itsLetters->itsValue == word->itsLetters->prev->itsValue && letter->itsValue != letter->prev->itsValue) || ( word->itsLetters->itsValue < 0 && letter->itsValue > 0) || ( letter->itsValue > 0 && letter->itsValue < word->itsLetters->itsValue) || ( letter->itsValue < 0 && letter->itsValue > word->itsLetters->itsValue) ) word->itsLetters = letter; } static void conjugate_peripheral_words( GroupPresentation *group) { /* * Can we conjugate any (meridian, longitude) pairs * to shorten their length? E.g. (CBCbcc, Cac) -> (BCbc, a) * or (cbbc, Caac) -> (ccbb, aa). */ int i; CyclicWord *theMeridian, *theLongitude; for ( i = 0, theMeridian = group->itsMeridians, theLongitude = group->itsLongitudes; i < group->itsNumCusps; i++, theMeridian = theMeridian ->next, theLongitude = theLongitude->next ) { if (theMeridian == NULL || theLongitude == NULL) uFatalError("conjugate_peripheral_words", "fundamental_group"); /* * Conjugate as necessary. */ while ( conjugate_peripheral_pair(theMeridian, theLongitude) == TRUE || conjugate_peripheral_pair(theLongitude, theMeridian) == TRUE) ; } } static Boolean conjugate_peripheral_pair( CyclicWord *word0, CyclicWord *word1) { int value; /* * For each peripheral word, set itsLetters * to point to the dummy basepoint Letter. */ while (word0->itsLetters->itsValue != 0) word0->itsLetters = word0->itsLetters->next; while (word1->itsLetters->itsValue != 0) word1->itsLetters = word1->itsLetters->next; if /* If... */ ( /* ...word0 contain more than just the dummy */ /* basepoint letter... */ word0->itsLength > 1 && /* ...the ends of word0 are inverses of one another... */ word0->itsLetters->next->itsValue + word0->itsLetters->prev->itsValue == 0 && /* ...and at least one end matches the corresponding */ /* end of word1, or word1 contains only the dummy */ /* basepoint Letter, ... */ ( word0->itsLetters->next->itsValue == word1->itsLetters->next->itsValue || word0->itsLetters->prev->itsValue == word1->itsLetters->prev->itsValue || word1->itsLength == 1 ) ) { /* * ...do the conjugation. */ value = -word0->itsLetters->next->itsValue; conjugate_word(word0, value); conjugate_word(word1, value); return TRUE; } else return FALSE; } static void conjugate_word( CyclicWord *word, int value) { Letter *new_letter; /* * This function assumes word->itsLetters is already * pointing to the dummy basepoint Letter. */ if (word->itsLetters->itsValue != 0) uFatalError("conjugate_word", "fundamental_group"); new_letter = NEW_STRUCT(Letter); new_letter->itsValue = value; INSERT_AFTER(new_letter, word->itsLetters); new_letter = NEW_STRUCT(Letter); new_letter->itsValue = -value; INSERT_BEFORE(new_letter, word->itsLetters); word->itsLength += 2; cancel_inverses_word(word); } static void cancel_inverses( GroupPresentation *group) { /* * This routine cancels subwords of the form "aA". * It works "recursively", so that "bAaBc" gets cancelled properly. */ cancel_inverses_word_list(group->itsRelations); /* * The meridians and longitudes aren't part of the pseudo-Heegaard * diagram, but we want to simplify them anyhow, and similarly * for the expressions for the original generators. */ cancel_inverses_word_list(group->itsMeridians); cancel_inverses_word_list(group->itsLongitudes); cancel_inverses_word_list(group->itsOriginalGenerators); } static void cancel_inverses_word_list( CyclicWord *list) { CyclicWord *word; for (word = list; word != NULL; word = word->next) cancel_inverses_word(word); } static void cancel_inverses_word( CyclicWord *word) { /* * Attempt to verify that no cancellations are possible, * by checking that each letter is not followed by its inverse. * * If some letter is followed by its inverse, cancel them * and reset the loop counter. */ int i; Letter *letter, *dead_letter; /* * Look for adjacent Letters which cancel. * Continue cyclically until we've checked itsLength * consecutive Letters which don't cancel. * * Meridians and longitudes use a temporary "basepoint" * Letter with itsValue == 0. Don't let it cancel with itself * if the word becomes trivial! */ for ( i = 0, letter = word->itsLetters; i < word->itsLength; i++, letter = letter->next) if (letter->itsValue + letter->next->itsValue == 0 && letter->itsValue != 0) { if (word->itsLength == 2) { my_free(letter->next); my_free(letter); word->itsLetters = NULL; word->itsLength = 0; break; } else { /* * Remove the letter following the current one. */ dead_letter = letter->next; REMOVE_NODE(dead_letter); my_free(dead_letter); /* * Back up one space. * (We hit some letter other than the one we're cancelling, * because word->itsLength > 2.) */ letter = letter->prev; /* * Remove what used to be the current letter. */ dead_letter = letter->next; REMOVE_NODE(dead_letter); my_free(dead_letter); /* * Make sure word->itsLetters isn't left dangling. */ word->itsLetters = letter; /* * The word is now two letters shorter. */ word->itsLength -= 2; /* * We want to resume the for(;;) loop at i == 0. * If we set i to -1, the i++ in the for(;;) statement * will immediately increment i to 0. */ i = -1; } } } static void handle_slide( GroupPresentation *group, int a, int b) { /* * Visualize the pseudo-Heegaard diagram as in "Visualizing * the pseudo-Heegaard diagram" at the top of this file. * If some word contains the substring "ab", this means that * a curve runs from the disk A- to the disk B+. At this point * it may be helpful to draw yourself an illustration showing * a curve running into A+, out of A-, into B+ and out of B-. * For future reference it will also be helpful to draw a few * other random curves going in or out of A-. Slide the disk A- * into B+ so that it comes out at B-, and redraw your sketch to * show this. Note that the existence of the substring "ab" * guarantees that we can do this "handle slide" without crossing * any curves. Now look what's happened to the random curves * coming in an out of A-. Each curve which comes out of A- now * goes into B- and out of B+ before proceeding on its way. * Algebraically, this means each occurrence of the letter "a" * is replaced by "aB". Each curve going into A- now goes first * into B+ and out of B-. Algebraically, this means that "A" * is replaced by "bA". Symbolically, * * "a" -> "aB" * "A" -> "bA" * * Note that the original substring "ab" which got us started * is replaced by "aBb", which simplifies to "a". */ /* * We assume that the calling function has already checked * that "ab" occurs as a substring of some word. */ /* * a and b should be distinct generators. */ if (a == b || a == -b) uFatalError("handle_slide", "fundamental_group"); /* * Fix up the relations. */ handle_slide_word_list(group->itsRelations, a, b); /* * The meridians and longitudes aren't part of the pseudo-Heegaard * diagram, but we want to keep track of them anyhow, and similarly * for the expressions for the original generators. */ handle_slide_word_list(group->itsMeridians, a, b); handle_slide_word_list(group->itsLongitudes, a, b); handle_slide_word_list(group->itsOriginalGenerators, a, b); /* * Fix up the matrices. */ handle_slide_matrices(group, a, b); /* * Record what we've done */ update_word_moves2(group, a, b); /* * Cancel any pairs of inverses we may have created. */ cancel_inverses(group); } static void handle_slide_word_list( CyclicWord *list, int a, int b) { CyclicWord *word; for (word = list; word != NULL; word = word->next) handle_slide_word(word, a, b); } static void handle_slide_word( CyclicWord *word, int a, int b) { Letter *letter, *new_letter; if (word->itsLength > 0) { letter = word->itsLetters; do { if (letter->itsValue == a) { new_letter = NEW_STRUCT(Letter); new_letter->itsValue = -b; INSERT_AFTER(new_letter, letter); word->itsLength++; } if (letter->itsValue == -a) { new_letter = NEW_STRUCT(Letter); new_letter->itsValue = b; INSERT_BEFORE(new_letter, letter); word->itsLength++; } letter = letter->next; } while (letter != word->itsLetters); } } static void handle_slide_matrices( GroupPresentation *group, int a, int b) { /* * Initially, generators a, b, etc. may be visualized as curves * in the interior of the handlebody which pass once around their * respective handles. Now assume we are doing a handle slide * as described in handle_slide() above. Generator b is not affected, * but the curve (in the interior of the handle body) corresponding * to generator a gets dragged across handle b. In otherwords, it * takes the trip a'B, where a' is the loop which passes once * around handle a in its new location, avoiding all other handles. * Symbolically, a = a'B. This corresponds to the matrix equation * M(a) = M(a') M(B). (As explained in fg_word_to_matrix(), the * order of the factors is reversed for two different reasons, so * it doesn't get reversed at all.) Solve for M(a') = M(a) M(B)^-1 * or M(a') = M(a) M(b). */ O31Matrix temp; MoebiusTransformation MT_temp; /* * Split into four cases, according to whether a and b * are positive or negative. */ if (a > 0) { if (b > 0) { /* * Use M(a') = M(a) M(b). */ o31_product( group->itsMatrices[a-1], group->itsMatrices[b-1], group->itsMatrices[a-1]); Moebius_product(&group->itsMTs[a-1], &group->itsMTs[b-1], &group->itsMTs[a-1]); } else /* b < 0 */ { /* * Use M(a') = M(a) [M(B)^-1]. */ o31_invert( group->itsMatrices[(-b)-1], temp); o31_product( group->itsMatrices[a-1], temp, group->itsMatrices[a-1]); Moebius_invert( &group->itsMTs[(-b)-1], &MT_temp); Moebius_product(&group->itsMTs[a-1], &MT_temp, &group->itsMTs[a-1]); } } else /* a < 0 */ { if (b > 0) { /* * Use M(A') = [M(b)^-1] M(A) */ o31_invert( group->itsMatrices[b-1], temp); o31_product( temp, group->itsMatrices[(-a)-1], group->itsMatrices[(-a)-1]); Moebius_invert( &group->itsMTs[b-1], &MT_temp); Moebius_product(&MT_temp, &group->itsMTs[(-a)-1], &group->itsMTs[(-a)-1]); } else /* b < 0 */ { /* * Use M(A') = M(B) M(A) */ o31_product( group->itsMatrices[(-b)-1], group->itsMatrices[(-a)-1], group->itsMatrices[(-a)-1]); Moebius_product(&group->itsMTs[(-b)-1], &group->itsMTs[(-a)-1], &group->itsMTs[(-a)-1]); } } } static void cancel_handles( GroupPresentation *group, CyclicWord *word) { /* * cancel_handles() cancels a relation of length one (a 2-handle) * with its corresponding generator (a 1-handle). This is a * geometric operation, in the sense that it corresponds to a * simplification of the pseudo-Heegaard diagram discussed in * "Visualizing the fundamental group" at the top of this file. * The proof is trivial when you visualize the pseudo-Heegaard diagram * as in "Visualizing the pseudo-Heegaard diagram" at the top of * this file (but oddly, the proof is less obvious when you visualize * the pseudo-Heegaard diagram as a handlebody). * * Comment: The 1-handle must be orientable, even in a nonorientable * manifold. Proof #1: The boundary of the thickened disk is a * cylinder, so the handle's "A+" and "A-" disks must be identified * in an orientation-preserving way. Proof #2: The handle's core * curve is homotopically trivial, so it must be orientation-preserving. */ int dead_generator; /* * Double check that the word has length one. */ if (word->itsLength != 1) uFatalError("cancel_handles", "fundamental_group"); /* * Which generator is being cancelled? */ dead_generator = ABS(word->itsLetters->itsValue); /* * Remove the word from the GroupPresentation, and decrement * group->itsNumRelations. */ remove_word(group, word); /* * Remove all occurences of the generator from all other words. * Note that even if a word becomes empty, it is *not* deleted, * because empty words have geometrical significance in the * pseudo-Heegaard diagram. For example, S^2 X S^1 has a presentation * with one generator and one empty word. */ remove_generator(group, dead_generator); /* * The highest numbered generator should assume the index of the * dead_generator, to keep the indexing contiguous. */ renumber_generator(group, group->itsNumGenerators, dead_generator); o31_copy( group->itsMatrices[dead_generator - 1], group->itsMatrices[group->itsNumGenerators - 1]); Moebius_copy(&group->itsMTs[dead_generator - 1], &group->itsMTs[group->itsNumGenerators - 1]); update_word_moves2(group, dead_generator, dead_generator); group->itsNumGenerators--; /* * Cancel any adjacent inverses which may have been created. */ cancel_inverses(group); } static void remove_word( GroupPresentation *group, CyclicWord *word) { CyclicWord **list; list = &group->itsRelations; while (*list != NULL) { if (*list == word) { *list = word->next; free_cyclic_word(word); group->itsNumRelations--; return; } list = &(*list)->next; } uFatalError("remove_word", "fundamental_group"); } static void remove_generator( GroupPresentation *group, int dead_generator) { remove_generator_from_list( group->itsRelations, dead_generator); /* * Strictly speaking, the peripheral curves and the original * generator expressions are not part of the pseudo-Heegaard * diagram, but we want to keep them up to date. */ remove_generator_from_list( group->itsMeridians, dead_generator); remove_generator_from_list( group->itsLongitudes, dead_generator); remove_generator_from_list( group->itsOriginalGenerators, dead_generator); } static void remove_generator_from_list( CyclicWord *list, int dead_generator) { CyclicWord *word; for (word = list; word != NULL; word = word->next) remove_generator_from_word(word, dead_generator); } static void remove_generator_from_word( CyclicWord *word, int dead_generator) { /* * We want to keep looking at Letters until the number of non-removed * Letters equals the length of the word. A "non-removed Letter" is * one which we have examined and found to be something other than * dead_generator. */ Letter *letter; int nonremoved; for ( letter = word->itsLetters, nonremoved = 0; nonremoved < word->itsLength; ) { if (letter->itsValue == dead_generator || letter->itsValue == -dead_generator) { if (word->itsLength > 1) { word->itsLetters = letter->next; REMOVE_NODE(letter); my_free(letter); letter = word->itsLetters; } else { word->itsLetters = NULL; my_free(letter); } word->itsLength--; } else { nonremoved++; letter = letter->next; } } } static void renumber_generator( GroupPresentation *group, int old_index, int new_index) { /* * Each occurrence of the old_index should be replaced * with the new_index. */ renumber_generator_on_word_list(group->itsRelations, old_index, new_index); /* * Strictly speaking, the peripheral curves and the original * generator expressions are not part of the pseudo-Heegaard * diagram, but we want to keep them up to date. */ renumber_generator_on_word_list(group->itsMeridians, old_index, new_index); renumber_generator_on_word_list(group->itsLongitudes, old_index, new_index); renumber_generator_on_word_list(group->itsOriginalGenerators, old_index, new_index); } static void renumber_generator_on_word_list( CyclicWord *list, int old_index, int new_index) { CyclicWord *word; for (word = list; word != NULL; word = word->next) renumber_generator_in_word(word, old_index, new_index); } static void renumber_generator_in_word( CyclicWord *word, int old_index, int new_index) { Letter *letter; int i; for ( letter = word->itsLetters, i = 0; i < word->itsLength; letter = letter->next, i++) { if (letter->itsValue == old_index) letter->itsValue = new_index; if (letter->itsValue == - old_index) letter->itsValue = - new_index; } } int fg_get_num_generators( GroupPresentation *group) { return group->itsNumGenerators; } /* Added by MC 01/26/08 */ int fg_get_num_orig_gens( GroupPresentation *group) { return group->itsNumOriginalGenerators; } Boolean fg_integer_fillings( GroupPresentation *group) { return group->integer_fillings; } FuncResult fg_word_to_matrix( GroupPresentation *group, int *word, O31Matrix result_O31, MoebiusTransformation *result_Moebius) { /* * In an abstract presentation of the fundamental group, * the word "ab" means "do 'a', then do 'b'". However, * when we map elements of the abstract group to elements * of the group of covering transformations, we find that * the isometry corresponding to "ab" is obtained by first * doing 'b', then 'a'. (Try it out in the case where * 'a' and 'b' are generators of the fundamental group * of an octagon-with-opposite-sides-glued, and all will * be clear.) Matrix products are read right-to-left, * so the isometry "'b' followed by 'a'" is M(a)M(b), * where M(a) and M(b) are the matrices representing * 'a' and 'b'. In summary, the order of the factors * is reversed for two different reasons, so therefore * it remains the same: "ab" maps to M(a)M(b). */ /* * Alan Reid and Craig Hodgson have pointed out that sometimes one * wants to look at the trace of a product of generators in SL(2,C) * (not just PSL(2,C)). To accomodate this, fg_word_to_matrix() now * computes the value of a word not only as an O31Matrix, but also * as a MoebiusTransformation, taking care to do the inversions and * matrix multiplications in SL(2,C). * * A more ambitious project would be to provide a consistent * representation into SL(2,C) whenever one is possible, but this * has *not* been implemented in the current code. * * JRW 96/1/6 */ /* * When input word is not valid, returns func_bad_input instead * of posting a fatal error. JRW 99/10/30 */ MoebiusTransformation theMoebiusFactor; O31Matrix theO31Factor; o31_copy (result_O31, O31_identity ); Moebius_copy(result_Moebius, &Moebius_identity); for ( ; *word != 0; word++) { /* * Find the matrix corresponding to this letter in the word... */ if (*word > 0 && *word <= group->itsNumGenerators) { o31_copy( theO31Factor, group->itsMatrices[*word - 1]); Moebius_copy(&theMoebiusFactor, &group->itsMTs[*word - 1]); } else if (*word < 0 && *word >= - group->itsNumGenerators) { o31_invert( group->itsMatrices[-(*word) - 1], theO31Factor ); Moebius_invert( &group->itsMTs[-(*word) - 1], &theMoebiusFactor); } else { return func_bad_input; } /* * ...and right-multiply it onto the matrix_generator. */ o31_product (result_O31, theO31Factor, result_O31); Moebius_product(result_Moebius, &theMoebiusFactor, result_Moebius); } return func_OK; } int fg_get_num_relations( GroupPresentation *group) { return group->itsNumRelations; } int fg_get_num_cusps( GroupPresentation *group) { return group->itsNumCusps; } int *fg_get_relation( GroupPresentation *group, int which_relation) { if (which_relation < 0 || which_relation >= group->itsNumRelations) uFatalError("fg_get_relation", "fundamental_group"); return fg_get_cyclic_word(group->itsRelations, which_relation); } int *fg_get_meridian( GroupPresentation *group, int which_cusp) { if (which_cusp < 0 || which_cusp >= group->itsNumCusps) uFatalError("fg_get_meridian", "fundamental_group"); return fg_get_cyclic_word(group->itsMeridians, which_cusp); } int *fg_get_longitude( GroupPresentation *group, int which_cusp) { if (which_cusp < 0 || which_cusp >= group->itsNumCusps) uFatalError("fg_get_longitude", "fundamental_group"); return fg_get_cyclic_word(group->itsLongitudes, which_cusp); } int *fg_get_original_generator( GroupPresentation *group, int which_generator) { if (which_generator < 0 || which_generator >= group->itsNumOriginalGenerators) uFatalError("fg_get_original_generator", "fundamental_group"); return fg_get_cyclic_word(group->itsOriginalGenerators, which_generator); } /* Added by NMD 2010/3/14 */ int * fg_get_word_moves(GroupPresentation *group){ int i; CyclicWord *word; Letter *letter; int *result; int length; /* Have to skip the first dummy letter */ word = group->itsWordMoves; length = word->itsLength; result = NEW_ARRAY(length, int); for ( i = 1, letter = word->itsLetters->next; i < length; i++, letter = letter->next) { result[i-1] = letter->itsValue; } result[length - 1] = 0; return result; } static int *fg_get_cyclic_word( CyclicWord *list, int which_relation) { int i; CyclicWord *word; Letter *letter; int *result; word = list; for (i = 0; i < which_relation; i++) if (word != NULL) word = word->next; if (word == NULL) uFatalError("fg_get_cyclic_word", "fundamental_group"); result = NEW_ARRAY(word->itsLength + 1, int); for ( i = 0, letter = word->itsLetters; i < word->itsLength; i++, letter = letter->next) { result[i] = letter->itsValue; } result[word->itsLength] = 0; return result; } void fg_free_relation( int *relation) { my_free(relation); } void free_group_presentation( GroupPresentation *group) { if (group != NULL) { if (group->itsMatrices != NULL) my_free(group->itsMatrices); if (group->itsMTs != NULL) my_free(group->itsMTs); free_word_list(group->itsRelations); free_word_list(group->itsMeridians); free_word_list(group->itsLongitudes); free_word_list(group->itsOriginalGenerators); free_word_list(group->itsWordMoves); my_free(group); } } static void free_word_list( CyclicWord *aWordList) { CyclicWord *theDeadWord; while (aWordList != NULL) { theDeadWord = aWordList; aWordList = aWordList->next; free_cyclic_word(theDeadWord); } } static void free_cyclic_word( CyclicWord *aCyclicWord) { Letter *theDeadLetter; while (aCyclicWord->itsLength > 1) { theDeadLetter = aCyclicWord->itsLetters; aCyclicWord->itsLetters = aCyclicWord->itsLetters->next; REMOVE_NODE(theDeadLetter); my_free(theDeadLetter); aCyclicWord->itsLength--; } /* * The preceding code would typically work fine right down to * aCyclicWord->itsLength == 1, but I don't want to write code which * depends on the implementation of the REMOVE_NODE() macro, so I'll * go ahead and make a special case for aCyclicWord->itsLength == 1. */ if (aCyclicWord->itsLength == 1) my_free(aCyclicWord->itsLetters); my_free(aCyclicWord); } static void update_word_moves(GroupPresentation *group, int a){ Letter *letter; letter = NEW_STRUCT(Letter); letter->itsValue = a; INSERT_BEFORE(letter, group->itsWordMoves->itsLetters); group->itsWordMoves->itsLength++; } static void update_word_moves2(GroupPresentation *group, int a, int b){ Letter *letter; letter = NEW_STRUCT(Letter); letter->itsValue = a; INSERT_BEFORE(letter, group->itsWordMoves->itsLetters); letter = NEW_STRUCT(Letter); letter->itsValue = b; INSERT_BEFORE(letter, group->itsWordMoves->itsLetters); group->itsWordMoves->itsLength += 2; } /* Debugging tool void print_word(CyclicWord *word){ int i; Letter *letter; printf("["); for (i = 0, letter = word->itsLetters; i < word->itsLength; i++, letter = letter->next) printf("%d ", letter->itsValue); printf("] "); } */ #include "end_namespace.h" regina-4.96/engine/snappea/kernel/gcd.c000644 000765 000024 00000010575 12377774107 017714 0ustar00babstaff000000 000000 /* * gcd.c * * This file contains the kernel functions * * long int gcd(long int a, long int b); * long int euclidean_algorithm(long int m, long int n, long int *a, long int *b); * long int Zq_inverse(long int p, long int q); * * gcd() returns the greatest common divisor of two long integers, * at least one of which is nonzero. * * euclidean_algorithm() returns the greatest common divisor of two long * integers m and n, and also finds long integers a and b such that * am + bn = gcd(m,n). The integers m and n may be negative, but cannot * both be zero. * * Zq_inverse() returns the inverse of p in the ring Z/q. Assumes p and q * are relatively prime integers satisfying 0 < p < q. * * 97/3/31 gcd() modified to accept negative integers. */ #include "kernel.h" #include "kernel_namespace.h" long int gcd( long int a, long int b) { a = ABS(a); b = ABS(b); if (a == 0) { if (b == 0) uFatalError("gcd", "gcd"); else return b; } while (TRUE) { if ((b = b%a) == 0) return a; if ((a = a%b) == 0) return b; } } long int euclidean_algorithm( long int m, long int n, long int *a, long int *b) { /* * Given two long integers m and n, use the Euclidean algorithm to * find integers a and b such that a*m + b*n = g.c.d.(m,n). * * Recall the Euclidean algorithm is to keep subtracting the * smaller of {m, n} from the larger until one of them reaches * zero. At that point the other will equal the g.c.d. * * As the algorithm progresses, we'll use the coefficients * mm, mn, nm, and nn to express the current values of m and n * in terms of the original values: * * current m = mm*(original m) + mn*(original n) * current n = nm*(original m) + nn*(original n) */ long int mm, mn, nm, nn, quotient; /* * Begin with a quick error check. */ if (m == 0 && n == 0) uFatalError("euclidean_algorithm", "gcd"); /* * Initially we have * * current m = 1 (original m) + 0 (original n) * current n = 0 (original m) + 1 (original n) */ mm = nn = 1; mn = nm = 0; /* * It will be convenient to work with nonnegative m and n. */ if (m < 0) { m = - m; mm = -1; } if (n < 0) { n = - n; nn = -1; } while (TRUE) { /* * If m is zero, then n is the g.c.d. and we're done. */ if (m == 0) { *a = nm; *b = nn; return n; } /* * Let n = n % m, and adjust the coefficients nm and nn accordingly. */ quotient = n / m; nm -= quotient * mm; nn -= quotient * mn; n -= quotient * m; /* * If n is zero, then m is the g.c.d. and we're done. */ if (n == 0) { *a = mm; *b = mn; return m; } /* * Let m = m % n, and adjust the coefficients mm and mn accordingly. */ quotient = m / n; mm -= quotient * nm; mn -= quotient * nn; m -= quotient * n; } /* * We never reach this point. */ } long int Zq_inverse( long int p, long int q) { long int a, b, g; /* * Make sure 0 < p < q. */ if (p <= 0 || p >= q) uFatalError("Zq_inverse", "gcd"); /* * Find a and b such that ap + bq = gcd(p,q) = 1. */ g = euclidean_algorithm(p, q, &a, &b); /* * Check that p and q are relatively prime. */ if (g != 1) uFatalError("Zq_inverse", "gcd"); /* * ap + bq = 1 * => ap = 1 (mod q) * => The inverse of p in Z/q is a. * * Normalize a to the range (0, q). * * [My guess is that a must always fall in the range -q < a < q, * in which case the follwing code would simplify to * * if (a < 0) * a += q; * * but I haven't worked out a proof.] */ while (a < 0) a += q; while (a > q) a -= q; return a; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/gluing_equations.c000644 000765 000024 00000045367 12377774107 022543 0ustar00babstaff000000 000000 /* * gluing_equations.c * * This file provides the function * * void compute_gluing_equations(Triangulation *manifold); * * which the function do_Dehn_filling() in hyperbolic_structure.c calls * to compute the edge and cusp equations and their derivatives. * It computes complex gluing equations for oriented manifolds, and * real gluing equations for nonoriented manifolds. It assumes that * space for the equations has already been assigned to the cusps and * edges, and that a coordinate system has been chosen for each * tetrahedron (cf. allocate_equations() and choose_coordinate_system() * in hyperbolic_structures.c). */ #include "kernel.h" #include "kernel_namespace.h" static void initialize_gluing_equations(Triangulation *manifold); static void compute_derivative(Triangulation *manifold); static void compute_rhs(Triangulation *manifold); void compute_gluing_equations( Triangulation *manifold) { compute_holonomies(manifold); compute_edge_angle_sums(manifold); initialize_gluing_equations(manifold); compute_derivative(manifold); compute_rhs(manifold); } void compute_gluing_equations_with_old_derivative( Triangulation *manifold) { compute_holonomies(manifold); compute_edge_angle_sums(manifold); initialize_gluing_equations(manifold); compute_rhs(manifold); } static void initialize_gluing_equations( Triangulation *manifold) { EdgeClass *edge; Cusp *cusp; int i; /* * Initialize edge equations. */ for ( edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) for (i = 0; i < manifold->num_tetrahedra; i++) if (manifold->orientability == oriented_manifold) edge->complex_edge_equation[i] = Zero; else { edge->real_edge_equation_re[2*i] = 0.0; edge->real_edge_equation_re[2*i + 1] = 0.0; edge->real_edge_equation_im[2*i] = 0.0; edge->real_edge_equation_im[2*i + 1] = 0.0; } /* * Initialize cusp equations. */ for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) for (i = 0; i < manifold->num_tetrahedra; i++) if (manifold->orientability == oriented_manifold) cusp->complex_cusp_equation[i] = Zero; else { cusp->real_cusp_equation_re[2*i] = 0.0; cusp->real_cusp_equation_re[2*i + 1] = 0.0; cusp->real_cusp_equation_im[2*i] = 0.0; cusp->real_cusp_equation_im[2*i + 1] = 0.0; } } /* * The coordinate system for the parameter space of each * tetrahedron has already been chosen as explained in * the comment preceding the function choose_coordinate_system() * in the file hyperbolic_structure.c. The derivatives computed * in that comment may be expressed as * * d(log z0) d(log z0) d(log z0) -1 * --------- = 1 --------- = -z2 --------- = -- * d(log z0) d(log z1) d(log z2) z1 * * d(log z1) -1 d(log z1) d(log z1) * --------- = -- --------- = 1 --------- = -z0 * d(log z0) z2 d(log z1) d(log z2) * * d(log z2) d(log z2) -1 d(log z2) * --------- = -z1 --------- = -- --------- = 1 * d(log z0) d(log z1) z0 d(log z2) * * compute_derivative() uses these forms to compute the entries * of the derivative matrix. If the manifold is oriented, these complex * numbers are added directly to the appropriate entries in the matrix. * If the manifold is unoriented, each complex number (a + bi) is * converted to a 2 x 2 real matrix * * a -b * * b a * * This matrix mimics the action of the complex derivative. That is, * (a + bi)(dx + i dy) = (a dx - b dy) + i(b dx + a dy), and * * | a dx - b dy | | a -b | | dx | * | | = | | | | * | b dx + a dy | | b a | | dy | * * If the Tetrahedron is seen as right_handed by its EdgeClass, then * the above matrix is added directly to the appropriate 2 x 2 block * in the derivative matrix. If the Tetrahedron is seen as left_handed * by it EdgeClass, then we must account for the fact that the EdgeClass * sees the conjugate-inverse of the edge parameter. That is, the * imaginary part of the log (i.e. the angle) will be the same, but * the real part of the log (i.e. the compression/expansion factor) * will be negated. We therefore use the following matrix instead. * * -a b * * b a * */ static void compute_derivative( Triangulation *manifold) { Tetrahedron *tet; Complex z[3], d[3], *eqn_coef = NULL, dz[2]; EdgeIndex e; VertexIndex v; FaceIndex initial_side, terminal_side; int init[2][2], term[2][2]; Real m, l, a, b, *eqn_coef_00 = NULL, *eqn_coef_01 = NULL, *eqn_coef_10 = NULL, *eqn_coef_11 = NULL; int i, j; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) { /* * Note the three edge parameters. */ for (i = 0; i < 3; i++) z[i] = tet->shape[filled]->cwl[ultimate][i].rect; /* * Set the derivatives of log(z0), log(z1) and log(z2) * with respect to the given coordinate system, as * indicated by the above table. */ switch (tet->coordinate_system) { case 0: d[0] = One; d[1] = complex_div(MinusOne, z[2]); d[2] = complex_minus(Zero, z[1]); break; case 1: d[0] = complex_minus(Zero, z[2]); d[1] = One; d[2] = complex_div(MinusOne, z[0]); break; case 2: d[0] = complex_div(MinusOne, z[1]); d[1] = complex_minus(Zero, z[0]); d[2] = One; break; } /* * Record this tetrahedron's contribution to the edge equations. */ for (e = 0; e < 6; e++) /* Look at each of the six edges. */ { /* * Find the matrix entry(ies) corresponding to the * derivative of the edge equation with respect to this * tetrahedron. If the manifold is oriented it will be * a single entry in the complex matrix. If the manifold * is unoriented it will be a 2 x 2 block in the real matrix. */ if (manifold->orientability == oriented_manifold) eqn_coef = &tet->edge_class[e]->complex_edge_equation[tet->index]; else { eqn_coef_00 = &tet->edge_class[e]->real_edge_equation_re[2 * tet->index]; eqn_coef_01 = &tet->edge_class[e]->real_edge_equation_re[2 * tet->index + 1]; eqn_coef_10 = &tet->edge_class[e]->real_edge_equation_im[2 * tet->index]; eqn_coef_11 = &tet->edge_class[e]->real_edge_equation_im[2 * tet->index + 1]; } /* * Add in the derivative of the log of the edge parameter * with respect to the chosen coordinate system. Please * see the comment preceding this function for details. */ if (manifold->orientability == oriented_manifold) *eqn_coef = complex_plus(*eqn_coef, d[edge3[e]]); else { /* * These are the same a and b as in the comment * preceding this function. */ a = d[edge3[e]].real; b = d[edge3[e]].imag; if (tet->edge_orientation[e] == right_handed) { *eqn_coef_00 += a; *eqn_coef_01 -= b; *eqn_coef_10 += b; *eqn_coef_11 += a; } else { *eqn_coef_00 -= a; *eqn_coef_01 += b; *eqn_coef_10 += b; *eqn_coef_11 += a; } } } /* * Record this tetrahedron's contribution to the cusp equations. */ for (v = 0; v < 4; v++) /* Look at each ideal vertex. */ { /* * Note the Dehn filling coefficients on this cusp. * If the cusp is complete, use m = 1.0 and l = 0.0. */ if (tet->cusp[v]->is_complete) { m = 1.0; l = 0.0; } else { m = tet->cusp[v]->m; l = tet->cusp[v]->l; } /* * Find the matrix entry(ies) corresponding to the * derivative of the cusp equation with respect to this * tetrahedron. If the manifold is oriented it will be * a single entry in the complex matrix. If the manifold * is unoriented it will be a 2 x 2 block in the real matrix. */ if (manifold->orientability == oriented_manifold) eqn_coef = &tet->cusp[v]->complex_cusp_equation[tet->index]; else { eqn_coef_00 = &tet->cusp[v]->real_cusp_equation_re[2 * tet->index]; eqn_coef_01 = &tet->cusp[v]->real_cusp_equation_re[2 * tet->index + 1]; eqn_coef_10 = &tet->cusp[v]->real_cusp_equation_im[2 * tet->index]; eqn_coef_11 = &tet->cusp[v]->real_cusp_equation_im[2 * tet->index + 1]; } /* * Each ideal vertex contains two triangular cross sections, * one right_handed and the other left_handed. We want to * compute the contribution of each angle of each triangle * to the holonomy. We begin by considering the right_handed * triangle, looking at each of its three angles. A directed * angle is specified by its initial and terminal sides. * We find the number of strands of the Dehn filling curve * passing from the initial side to the terminal side; * it is m * (number of strands of meridian) * + l * (number of strands of longitude), where (m,l) are * the Dehn filling coefficients (in practice, m and l need * not be integers, but it's simpler to imagine them to be * integers as you try to understand the following code). * The number of strands of the Dehn filling curves passing * from the initial to the terminal side is multiplied by * the derivative of the log of the complex angle, to yield * the contribution to the derivative matrix. If the manifold * is oriented, that complex number is added directly to * the relevant matrix entry. If the manifold is unoriented, * we convert the complex number to a 2 x 2 real matrix * (cf. the comments preceding this function) and add it to * the appropriate 2 x 2 block of the real derivative matrix. * The 2 x 2 matrix for the left_handed triangle is modified * to account for the fact that although the real part of the * derivative of the log (i.e. the compression/expansion * factor) is the same, the imaginary part (i.e. the rotation) * is negated. [Note that in computing the edge equations * the real part was negated, while for the cusp equations * the imaginary part is negated. I will leave an explanation * of the difference as an exercise for the reader.] * * Note that we cannot possibly handle curves on the * left_handed sheet of the orientation double cover of * a cusp of an oriented manifold. The reason is that the * log of the holonomy of the Dehn filling curve is not * a complex analytic function of the shape of the tetrahedron * (it's the complex conjugate of such a function). I.e. * it doesn't have a derivative in the complex sense. This * is why we make the convention that all peripheral curves * in oriented manifolds lie on the right_handed sheet of * the double cover. */ for (initial_side = 0; initial_side < 4; initial_side++) { if (initial_side == v) continue; terminal_side = remaining_face[v][initial_side]; /* * Note the intersection numbers of the meridian and * longitude with the initial and terminal sides. */ for (i = 0; i < 2; i++) { /* which curve */ for (j = 0; j < 2; j++) { /* which sheet */ init[i][j] = tet->curve[i][j][v][initial_side]; term[i][j] = tet->curve[i][j][v][terminal_side]; } } /* * For each triangle (right_handed and left_handed), * multiply the number of strands of the Dehn filling * curve running from initial_side to terminal_side * by the derivative of the log of the edge parameter. */ for (i = 0; i < 2; i++) /* which sheet */ dz[i] = complex_real_mult( m * (Real)FLOW(init[M][i],term[M][i]) + l * (Real)FLOW(init[L][i],term[L][i]), d[ edge3_between_faces[initial_side][terminal_side] ] ); /* * If the manifold is oriented, the Dehn filling curve * must lie of the right_handed sheet of the orientation * double cover (cf. above). Add its contributation to * the cusp equation. */ if (manifold->orientability == oriented_manifold) *eqn_coef = complex_plus(*eqn_coef, dz[right_handed]); /* "else" follows below */ /* * If the manifold is unoriented, treat the right_ and * left_handed sheets separately. Add in the contribution * of the right_handed sheet normally. For the left_handed * sheet, we must account for the fact that even though * the modulus of the derivative (i.e. the expansion/ * contraction factor) is correct, its argument (i.e. the * angle of rotation) is the negative of what it should be. */ else { a = dz[right_handed].real; b = dz[right_handed].imag; *eqn_coef_00 += a; *eqn_coef_01 -= b; *eqn_coef_10 += b; *eqn_coef_11 += a; a = dz[left_handed].real; b = dz[left_handed].imag; *eqn_coef_00 += a; *eqn_coef_01 -= b; *eqn_coef_10 -= b; *eqn_coef_11 -= a; } } } } } /* * compute_complex_rhs() assumes that compute_holonomies() and * compute_edge_angle_sums() have already been called. */ static void compute_rhs( Triangulation *manifold) { EdgeClass *edge; Cusp *cusp; Complex desired_holonomy, current_holonomy, rhs; /* * The right hand side of each equation will be the desired value * of the edge angle sum or the holonomy (depending on whether it's * an edge equation or a cusp equation) minus the current value. * Thus, when the equations are solved and the Shapes of the * Tetrahedra are updated, the edge angle sums and the holonomies * will take on their desired values, to the accuracy of the * linear approximation. */ /* * Set the right hand side (rhs) of each edge equation. */ for ( edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) { /* * The desired value of the sum of the logs of the complex * edge parameters is 2 pi i. The current value is * edge->edge_angle_sum. */ rhs = complex_minus(edge->target_angle_sum, edge->edge_angle_sum); if (manifold->orientability == oriented_manifold) edge->complex_edge_equation[manifold->num_tetrahedra] = rhs; else { edge->real_edge_equation_re[2 * manifold->num_tetrahedra] = rhs.real; edge->real_edge_equation_im[2 * manifold->num_tetrahedra] = rhs.imag; } } /* * Set the right hand side (rhs) of each cusp equation. */ for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) { /* * For complete cusps we want the log of the holonomy of the * meridian to be zero. For Dehn filled cusps we want the * log of the holonomy of the Dehn filling curve to be 2 pi i. */ if (cusp->is_complete) { desired_holonomy = Zero; current_holonomy = cusp->holonomy[ultimate][M]; } else { desired_holonomy = cusp->target_holonomy; current_holonomy = complex_plus( complex_real_mult(cusp->m, cusp->holonomy[ultimate][M]), complex_real_mult(cusp->l, cusp->holonomy[ultimate][L]) ); } rhs = complex_minus(desired_holonomy, current_holonomy); if (manifold->orientability == oriented_manifold) cusp->complex_cusp_equation[manifold->num_tetrahedra] = rhs; else { cusp->real_cusp_equation_re[2 * manifold->num_tetrahedra] = rhs.real; cusp->real_cusp_equation_im[2 * manifold->num_tetrahedra] = rhs.imag; } } } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/holonomy.c000644 000765 000024 00000021277 12377774107 021024 0ustar00babstaff000000 000000 /* * holonomy.c * * This file provides the functions * * void compute_holonomies(Triangulation *manifold); * void compute_edge_angle_sums(Triangulation *manifold); * * which the functions compute_complex_equations() and * compute_real_equations() in gluing_equations.c call. They store * their results directly into Triangulation *manifold, so whenever * a hyperbolic structure has been found, you may also assume the * holonomies are present. (The edge angle sums will be present too, * but since they'll all be 2 pi i they won't be very interesting.) * * The most accurate holonomies are stored in holonomy[ultimate][M] * and holonomy[ultimate][L]. The fields holonomy[penultimate][M] * and holonomy[penultimate][L] store the holonomies from the * penultimate iteration of Newton's method, for use in estimating * the numerical error. * * * The holonomy of a Klein bottle cusp deserves special discussion. * * (1) The holonomy of the meridian may have a rotational part, but * never has a contraction part. I.e. it's log is pure imaginary. * Proof: the meridian is freely homotopic to it's own inverse. * * (2) The holonomy of the longitude doesn't even make sense. As * you tilt the angle of the curve at the basepoint, the angle * of the next lift down the line rotates in the opposite * direction. The rotational part of the holonomy is not an * isotopy invariant for an orientation-reversing curve. The * contraction is an isotopy invariant, but it's cleaner and * simpler to work with the preimage of the longitude in the * Klein bottle's orientation double cover, which is a torus. * The curve on the double cover must have zero rotational part, * because the orientation-reversing covering transformation * takes the curve to itself. * * These observations imply that a Dehn filling on a Klein bottle cusp * must be of the form (m,0). * * * 96/9/27 I split compute_holonomies() into separate functions * copy_holonomies_ultimate_to_penultimate() and compute_the_holonomies(), * so that other functions (e.g. cover.c) can call compute_the_holonomies() * to compute the penultimate holonomies directly. */ #include "kernel.h" #include "kernel_namespace.h" static void copy_holonomies_ultimate_to_penultimate(Triangulation *manifold); void compute_holonomies( Triangulation *manifold) { copy_holonomies_ultimate_to_penultimate(manifold); compute_the_holonomies(manifold, ultimate); } static void copy_holonomies_ultimate_to_penultimate( Triangulation *manifold) { /* * Copy holonomy[ultimate][] into holonomy[penultimate][]. */ Cusp *cusp; int i; for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) for (i = 0; i < 2; i++) /* i = M, L */ cusp->holonomy[penultimate][i] = cusp->holonomy[ultimate][i]; } void compute_the_holonomies( Triangulation *manifold, Ultimateness which_iteration) { Cusp *cusp; Tetrahedron *tet; Complex log_z[2]; VertexIndex v; FaceIndex initial_side, terminal_side; int init[2][2], term[2][2]; int i, j; /* * Initialize holonomy[which_iteration][] to zero. */ for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) for (i = 0; i < 2; i++) /* i = M, L */ cusp->holonomy[which_iteration][i] = Zero; /* * Now add the contribution of each tetrahedron. * * The cross section of the ideal vertex v is the union * of two triangles, one with the right_handed orientation * and one with the left_handed orientation (please see the * documentationvat the top of peripheral_curves.c for details). * * This loop is similar to the loop in compute_complex_derivative() * in gluing_equations.c. */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (v = 0; v < 4; v++) for (initial_side = 0; initial_side < 4; initial_side++) { if (initial_side == v) continue; terminal_side = remaining_face[v][initial_side]; /* * Note the log of the complex edge parameter, * for use with the right_handed triangle. */ log_z[right_handed] = tet->shape[filled]->cwl[which_iteration][ edge3_between_faces[initial_side][terminal_side] ].log; /* * The conjugate of log_z[right_handed] will apply to * the left_handed triangle. */ log_z[left_handed] = complex_conjugate(log_z[right_handed]); /* * Note the intersection numbers of the meridian and * longitude with the initial and terminal sides. */ for (i = 0; i < 2; i++) { /* which curve */ for (j = 0; j < 2; j++) { /* which sheet */ init[i][j] = tet->curve[i][j][v][initial_side]; term[i][j] = tet->curve[i][j][v][terminal_side]; } } /* * holonomy[which_iteration][i] += * FLOW(init[i][right_handed], term[i][right_handed]) * log_z[right_handed] * + FLOW(init[i][left_handed ], term[i][left_handed ]) * log_z[left_handed ]; */ for (i = 0; i < 2; i++) /* which curve */ #if 0 The stupid Symantec C compiler is choking on the following expression. So I am breaking it into two parts to make its work easier. original version: tet->cusp[v]->holonomy[which_iteration][i] = complex_plus( tet->cusp[v]->holonomy[which_iteration][i], complex_plus( complex_real_mult( FLOW(init[i][right_handed], term[i][right_handed]), log_z[right_handed] ), complex_real_mult( FLOW(init[i][left_handed], term[i][left_handed]), log_z[left_handed] ) ) ); modified version: #else { Complex temp; temp = complex_plus( tet->cusp[v]->holonomy[which_iteration][i], complex_plus( complex_real_mult( FLOW(init[i][right_handed], term[i][right_handed]), log_z[right_handed] ), complex_real_mult( FLOW(init[i][left_handed], term[i][left_handed]), log_z[left_handed] ) ) ); tet->cusp[v]->holonomy[which_iteration][i] = temp; } #endif } } void compute_edge_angle_sums( Triangulation *manifold) { EdgeClass *edge; Tetrahedron *tet; EdgeIndex e; /* * Initialize all edge_angle_sums to zero. */ for ( edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) edge->edge_angle_sum = Zero; /* * Add in the contribution of each edge of each tetrahedron. * * If the EdgeClass sees the Tetrahedron as right_handed, * add in the log of the edge parameter directly. If it sees * it as left_handed, add in the log of the conjugate-inverse * (i.e. add the imaginary part of the log as usual, but subtract * the real part). */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (e = 0; e < 6; e++) { tet->edge_class[e]->edge_angle_sum.imag += tet->shape[filled]->cwl[ultimate][edge3[e]].log.imag; if (tet->edge_orientation[e] == right_handed) tet->edge_class[e]->edge_angle_sum.real += tet->shape[filled]->cwl[ultimate][edge3[e]].log.real; else tet->edge_class[e]->edge_angle_sum.real -= tet->shape[filled]->cwl[ultimate][edge3[e]].log.real; } } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/homology.c000644 000765 000024 00000105700 12377774107 021007 0ustar00babstaff000000 000000 /* * homology.c * * This file contains the following functions which the kernel * provides for the UI: * * AbelianGroup *homology(Triangulation *manifold); * * AbelianGroup *homology_from_fundamental_group( * GroupPresentation *group); * * Added by MC 01/26/08: * void homology_presentation(Triangulation *manifold, * RelationMatrix *relation_matrix); * * void free_relations(RelationMatrix *relation_matrix) * * * If all Dehn filling coefficients are integers, homology() returns * a pointer to the first homology group of *manifold. Otherwise * it returns NULL. Note that homology() will compute homology groups * of orbifolds as well as manifolds. * * 96/12/11 homology() and homology_from_fundamental_group() now * check for overflows, and return NULL if any occur. * * MC: 01/26/08 homology_presentation sets relation_matrix=>relations * to NULL if overflow occurs while generating the matrix. The other * entries in the structure are meaningless in this case. * * The comments in homology() below describe the algorithm. * * homology() returns NULL if some Dehn filling coefficients * are not integers (or if overflows occur). * * homology_from_fundamental_group() is a variant of homology which * computes the homology by abelianizing a presentation of the * fundamental group. */ #include "kernel.h" #include "kernel_namespace.h" static void group_to_relation_matrix(GroupPresentation *group, RelationMatrix *relation_matrix, Boolean *overflow); static void allocate_relation_matrix_from_group(GroupPresentation *group, RelationMatrix *relation_matrix); static void read_relations_from_group(GroupPresentation *group, RelationMatrix *relation_matrix, Boolean *overflow); static void find_relations(Triangulation *manifold, RelationMatrix *relation_matrix, Boolean *overflow); static void allocate_relation_matrix(Triangulation *manifold, RelationMatrix *relation_matrix); static void initialize_relations(RelationMatrix *relation_matrix); static void find_edge_relations(Triangulation *manifold, RelationMatrix *relation_matrix); static void find_cusp_relations(Triangulation *manifold, RelationMatrix *relation_matrix, Boolean *overflow); static void eliminate_generators(RelationMatrix *relation_matrix, Boolean *overflow); static void delete_empty_relations(RelationMatrix *relation_matrix); static void compute_homology_group(RelationMatrix *relation_matrix, AbelianGroup **g, Boolean *overflow); static void add_row_multiple(RelationMatrix *relation_matrix, int src, int dst, MatrixEntry mult, Boolean *overflow); static void add_column_multiple(RelationMatrix *relation_matrix, int src, int dst, MatrixEntry mult, Boolean *overflow); static MatrixEntry safe_addition(MatrixEntry a, MatrixEntry b, Boolean *overflow); static MatrixEntry safe_multiplication(MatrixEntry a, MatrixEntry b, Boolean *overflow); void free_relations(RelationMatrix *relation_matrix); AbelianGroup *homology( Triangulation *manifold) { Boolean overflow; RelationMatrix relation_matrix; AbelianGroup *g; /* * Make sure all the Dehn filling coefficients are integers. */ if ( ! all_Dehn_coefficients_are_integers(manifold) ) return NULL; /* * Compute a set of generators. */ choose_generators(manifold, FALSE, FALSE); /* * The overflow flag keeps track of whether an overflow has occurred. */ overflow = FALSE; /* * Read the edge and cusp relations out of the manifold. * Each row of the relation_matrix represents a relation; * each column corresponds to a generator. For example, * the relation X0 - X5 + 2*X8 = 0 would be encoded as the * row 1 0 0 0 0 -1 0 0 2 0. The edge relations are read * into the matrix before the cusp relations because they * are simpler (typically 3 to 5 nonzero entries); this * minimizes the fill-in during the presimplification phase * below. */ find_relations(manifold, &relation_matrix, &overflow); if (overflow == TRUE) { free_relations(&relation_matrix); return NULL; } /* * Presimplify the relations. * * First check each relation to see whether some generator * appears with coefficient +1 or -1. If one does, * use the relation to substitute out the generator. * For example, in the matrix * * 0 0 1 0 0 -1 2 0 0 1 0 * 0 1 0 0 0 0 0 1 1 0 0 * 1 0 1 0 0 0 1 0 0 0 1 * 0 1 -1 0 1 0 1 0 0 0 0 * * we can use the first row to eliminate the third generator, * yielding * * 0 0 1 0 0 -1 2 0 0 1 0 * 0 1 0 0 0 0 0 1 1 0 0 <-- no change * 1 0 0 0 0 1 -1 0 0 -1 1 <-- first row was subtracted * 0 1 0 0 1 -1 3 0 0 1 0 <-- first row was added * * We can now eliminate both the first row and the third column. * In practice, the third column would be overwritten with the * contents of the last column to keep the data contiguous. * For the moment the first row is left with all zeros. * * 0 0 0 0 0 0 0 0 0 0 * 0 1 0 0 0 0 0 1 1 0 * 1 0 1 0 0 1 -1 0 0 -1 * 0 1 0 0 1 -1 3 0 0 1 * * The cusp relations (which typically have many nonzero entries) * appear at the bottom of the matrix, after the gluing relations * (which typically have 3 to 5 nonzero entries, regardless of the * size of the manifold). This minimizes the "fill-in" (overwriting * of zeros with nonzero values) during the presimplification process. */ eliminate_generators(&relation_matrix, &overflow); if (overflow == TRUE) { free_relations(&relation_matrix); return NULL; } /* * delete_empty_relations() now removes rows containing only * zeros. This includes the rows of zeros created by * eliminate_generators() as well as the rows which were initially * all zeros. */ delete_empty_relations(&relation_matrix); /* * Apply a general algorithm to the relations to compute * the homology group. * * The torsion coefficients of the homology group are the * invariant factors of the relation matrix. (A torsion * coefficient of 0 indicates an infinite cyclic factor.) * That is, one performs row and column operations on the * matrix to put it into diagonal form, then reads the * torsion coefficients directly from the diagonal entries. * It's not hard to convince oneself that both row and column * operations are "legal"; for the full story on invariant * factors, see Hartley & Hawkes' Rings, Modules and Linear * Algebra, Chapman & Hall 1970. * * compute_homology_group() uses the following algorithm. * It performs row and column operations as necessary to * create a matrix element which divides its entire row * and column. For example, if it starts with the element * 10 in the first row (see below), it would notice that 10 does not * divide the 28 in the first row, so it would subtract twice the * second column from the last column, and continue with the 8 * at the end of the first row as its candidate. But this 8 does * not divide the 10 in the first row, so it would subtract the * last column from the second column, and continue with the 2 * as its candidate. * * 0 10 0 28 0 10 0 8 0 2 0 8 * 3 0 2 6 3 0 2 6 3 -6 2 6 * 2 10 4 16 2 10 4 -4 2 14 4 -4 * 0 2 0 8 0 2 0 4 0 -2 0 4 * * The 2 in the first row now divides its entire row, and, as it * turns out, its entire column as well. If it didn't divide each * entry in its column, similar operations would be performed * repeatedly until it divided both row and column. Note that * the absolute value of the candidate decreases at each step, * so this process is sure to succeed in a finite number of steps. * * Once we have an element that divides its row and column, we * perform row operations to clear out its column * * 0 2 0 8 * 3 0 2 30 <-- 3 times the first row was added * 2 0 4 -60 <-- -7 times the first row was added * 0 0 0 12 <-- 1 times the first row was added * * and column operations to clear out its row * * 0 2 0 0 * 3 0 2 30 * 2 0 4 -60 * 0 0 0 12 * * We can now read off a torsion coefficient (in this case, 2), * and eliminate a row and column. In practice, the deleted * row is swapped with the last row, and the deleted column * is overwritten with the contents of the last column, to keep * the matrix contiguous. * * swap rows: overwrite column: reduce matrix dimensions: * * 0 0 0 12 0 12 0 12 0 12 0 * 3 0 2 30 3 30 2 30 3 30 2 * 2 0 4 -60 2 -60 4 -60 2 -60 4 * 0 2 0 0 0 0 0 0 * * We repeat this process until no relations remain. If there * are any generators left over, they will correspond to infinite * cyclic factors of the group (represented as torsion coefficients * of 0). */ compute_homology_group(&relation_matrix, &g, &overflow); if (overflow == TRUE) { free_relations(&relation_matrix); free_abelian_group(g); return NULL; } /* * Clean up. */ free_relations(&relation_matrix); return g; } AbelianGroup *homology_from_fundamental_group( GroupPresentation *group) { /* * This function is a variation on the above homology() function. * The difference is that here we use a presentation of the fundamental * group as our starting point, instead of a triangulation. * Please see homology() for a complete explanation of the algorithm. */ Boolean overflow; RelationMatrix relation_matrix; AbelianGroup *g; overflow = FALSE; group_to_relation_matrix(group, &relation_matrix, &overflow); if (overflow == TRUE) { free_relations(&relation_matrix); return NULL; } eliminate_generators(&relation_matrix, &overflow); if (overflow == TRUE) { free_relations(&relation_matrix); return NULL; } delete_empty_relations(&relation_matrix); compute_homology_group(&relation_matrix, &g, &overflow); if (overflow == TRUE) { free_relations(&relation_matrix); free_abelian_group(g); return NULL; } free_relations(&relation_matrix); return g; } void homology_presentation( Triangulation *manifold, RelationMatrix *relation_matrix) { Boolean overflow; if ( ! all_Dehn_coefficients_are_integers(manifold) ) { relation_matrix->relations = NULL; return; } choose_generators(manifold, FALSE, FALSE); overflow = FALSE; find_relations(manifold, relation_matrix, &overflow); if (overflow == TRUE) { free_relations(relation_matrix); relation_matrix->relations = NULL; return; } eliminate_generators(relation_matrix, &overflow); if (overflow == TRUE) { free_relations(relation_matrix); relation_matrix->relations = NULL; return; } delete_empty_relations(relation_matrix); } static void group_to_relation_matrix( GroupPresentation *group, RelationMatrix *relation_matrix, Boolean *overflow) { allocate_relation_matrix_from_group(group, relation_matrix); initialize_relations(relation_matrix); read_relations_from_group(group, relation_matrix, overflow); } static void allocate_relation_matrix_from_group( GroupPresentation *group, RelationMatrix *relation_matrix) { int i; relation_matrix->max_rows = fg_get_num_relations (group); relation_matrix->num_rows = fg_get_num_relations (group); relation_matrix->num_columns = fg_get_num_generators(group); if (relation_matrix->max_rows > 0) relation_matrix->relations = NEW_ARRAY(relation_matrix->max_rows, MatrixEntry *); else relation_matrix->relations = NULL; for (i = 0; i < relation_matrix->max_rows; i++) relation_matrix->relations[i] = NEW_ARRAY(relation_matrix->num_columns, MatrixEntry); } static void read_relations_from_group( GroupPresentation *group, RelationMatrix *relation_matrix, Boolean *overflow) { int i, j, *relation; for (i = 0; i < relation_matrix->num_rows; i++) { relation = fg_get_relation(group, i); for (j = 0; relation[j] != 0; j++) { if (ABS(relation[j]) > relation_matrix->num_columns) uFatalError("read_relations_from_group", "homology"); if (relation[j] > 0) { if (relation_matrix->relations[i][ relation[j] - 1] < ENTRY_MAX) relation_matrix->relations[i][ relation[j] - 1]++; else *overflow = TRUE; } else /* relation[j] < 0 */ { if (relation_matrix->relations[i][-relation[j] - 1] > ENTRY_MIN) relation_matrix->relations[i][-relation[j] - 1]--; else *overflow = TRUE; } } fg_free_relation(relation); } } static void find_relations( Triangulation *manifold, RelationMatrix *relation_matrix, Boolean *overflow) { allocate_relation_matrix(manifold, relation_matrix); initialize_relations(relation_matrix); find_edge_relations(manifold, relation_matrix); find_cusp_relations(manifold, relation_matrix, overflow); } static void allocate_relation_matrix( Triangulation *manifold, RelationMatrix *relation_matrix) { int i, num_edges; /* * There will be, at most, one relation for each EdgeClass and one * relation for each Cusp. We'll worry about the exact number of * relations later. By an Euler characteristic argument, * the number of EdgeClasses equals the number of Tetrahedra. * * relation_matrix->num_rows records the number of active rows, * which is initially zero. * * The number of generators is found in the manifold->num_generators field. */ num_edges = get_num_edge_classes(manifold, 0, TRUE); relation_matrix->max_rows = num_edges + manifold->num_cusps; relation_matrix->num_rows = 0; relation_matrix->num_columns = manifold->num_generators; /* * Allocate storage for the relations. */ relation_matrix->relations = NEW_ARRAY(relation_matrix->max_rows, MatrixEntry *); for (i = 0; i < relation_matrix->max_rows; i++) relation_matrix->relations[i] = NEW_ARRAY(relation_matrix->num_columns, MatrixEntry); } static void initialize_relations( RelationMatrix *relation_matrix) { int i, j; for (i = 0; i < relation_matrix->max_rows; i++) for (j = 0; j < relation_matrix->num_columns; j++) relation_matrix->relations[i][j] = 0; } static void find_edge_relations( Triangulation *manifold, RelationMatrix *relation_matrix) { EdgeClass *edge; PositionedTet ptet, ptet0; MatrixEntry *entry; /* * We compute a relation for each EdgeClass in the manifold. * The functions set_left_edge(), veer_left() and same_positioned_tet() * (from positioned_tet.c -- see documentation in kernel_prototypes.h) * walk a PositionedTet around an EdgeClass. At each step, we examine * the generator (see choose_generators.c) dual to ptet.near_face. */ for (edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) { set_left_edge(edge, &ptet0); ptet = ptet0; do { entry = &relation_matrix->relations [relation_matrix->num_rows] [ptet.tet->generator_index[ptet.near_face]]; switch (ptet.tet->generator_status[ptet.near_face]) { case outbound_generator: *entry += 1; break; case inbound_generator: *entry -= 1; break; case not_a_generator: /* do nothing */ break; default: uFatalError("find_edge_relations", "homology"); } veer_left(&ptet); } while ( ! same_positioned_tet(&ptet, &ptet0) ); relation_matrix->num_rows++; } } static void find_cusp_relations( Triangulation *manifold, RelationMatrix *relation_matrix, Boolean *overflow) { Tetrahedron *tet; VertexIndex vertex; FaceIndex side; Orientation orientation; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (vertex = 0; vertex < 4; vertex++) { if (tet->cusp[vertex]->is_complete) continue; for (side = 0; side < 4; side++) { if (side == vertex) continue; if (tet->generator_status[side] != inbound_generator) continue; for (orientation = 0; orientation < 2; orientation++) /* orientation = right_handed, left_handed */ /* * Here's the version of the code which didn't * check for overflows: * relation_matrix->relations [relation_matrix->num_rows + tet->cusp[vertex]->index] [tet->generator_index[side]] += (MatrixEntry) tet->cusp[vertex]->m * tet->curve[M][orientation][vertex][side] + (MatrixEntry) tet->cusp[vertex]->l * tet->curve[L][orientation][vertex][side]; * * Here's the current version: */ { relation_matrix->relations [relation_matrix->num_rows + tet->cusp[vertex]->index] [tet->generator_index[side]] = safe_addition( relation_matrix->relations [relation_matrix->num_rows + tet->cusp[vertex]->index] [tet->generator_index[side]], safe_multiplication((MatrixEntry) tet->cusp[vertex]->m, (MatrixEntry) tet->curve[M][orientation][vertex][side], overflow), overflow); relation_matrix->relations [relation_matrix->num_rows + tet->cusp[vertex]->index] [tet->generator_index[side]] = safe_addition( relation_matrix->relations [relation_matrix->num_rows + tet->cusp[vertex]->index] [tet->generator_index[side]], safe_multiplication((MatrixEntry) tet->cusp[vertex]->l, (MatrixEntry) tet->curve[L][orientation][vertex][side], overflow), overflow); /* * If an overflow occurs, don't worry about it here. * Nothing bad will happen. Just keep going, and let * the calling function deal with it. */ } } } relation_matrix->num_rows += manifold->num_cusps; } static void eliminate_generators( RelationMatrix *relation_matrix, Boolean *overflow) { int i, j, ii, jj; MatrixEntry mult; /* * eliminate_generators() tries to substitute out as many generators * as possible. To do so, it looks at the rows of the matrix one * at a time, and whenever it finds a row containing +1 or -1 times * a generator, it eliminates that generator. */ for (i = 0; i < relation_matrix->num_rows; i++) for (j = 0; j < relation_matrix->num_columns; j++) if (relation_matrix->relations[i][j] == 1 || relation_matrix->relations[i][j] == -1) { /* * Substitute this generator out of all the other rows. */ for (ii = 0; ii < relation_matrix->num_rows; ii++) if (ii != i && relation_matrix->relations[ii][j]) { mult = (relation_matrix->relations[i][j] == -1) ? relation_matrix->relations[ii][j] : - relation_matrix->relations[ii][j]; add_row_multiple(relation_matrix, i, ii, mult, overflow); if (*overflow == TRUE) return; } /* * Make this row all zeros. */ for (jj = 0; jj < relation_matrix->num_columns; jj++) relation_matrix->relations[i][jj] = 0; /* * Generator j may now be eliminated. Let the highest * numbered generator inherit its index (i.e. overwrite * column j with with contents of the last column), and * decrement num_columns. */ relation_matrix->num_columns--; for (ii = 0; ii < relation_matrix->num_rows; ii++) relation_matrix->relations[ii][j] = relation_matrix->relations[ii][relation_matrix->num_columns]; /* * Break out of the j loop, and move on to the next i. */ break; } } static void delete_empty_relations( RelationMatrix *relation_matrix) { int i, j; Boolean all_zeros; MatrixEntry *temp; /* * Eliminate rows consisting entirely of zeros. */ /* * For each row . . . */ for (i = 0; i < relation_matrix->num_rows; i++) { /* * . . . check whether all entries are zero . . . */ all_zeros = TRUE; for (j = 0; j < relation_matrix->num_columns; j++) if (relation_matrix->relations[i][j]) { all_zeros = FALSE; break; } /* * . . . and if so, eliminate the row. */ if (all_zeros) { /* * Decrement num_rows . . . */ relation_matrix->num_rows--; /* * . . . and swap the zero row with the last active row * of the matrix. (Because num_rows was decremented, * the zero row will be "invisible" in its new location, * but its storage will still be there to be freed when * the time comes.) */ temp = relation_matrix->relations[i]; relation_matrix->relations[i] = relation_matrix->relations[relation_matrix->num_rows]; relation_matrix->relations[relation_matrix->num_rows] = temp; /* * We want to consider the new row we just swapped into position i. * The following i-- will "cancel" the i++ in the for(;;) loop. */ i--; } } } static void compute_homology_group( RelationMatrix *relation_matrix, AbelianGroup **g, Boolean *overflow) { int i, /* i and j are dummy variables, as usual. */ j, ii, /* ii and jj are the indices of the entry which is */ jj; /* supposed to divide all the other entries in its */ /* row and column. */ Boolean all_zeros, desired_entry_has_been_found; MatrixEntry **m, *temp, mult; /* * Allocate space for the AbelianGroup data structure. */ *g = NEW_STRUCT(AbelianGroup); /* * Initialize (*g)->num_torsion_coefficients to zero, and * allocate enough space for the array of torsion coefficients. * We probably won't need all the space we're allocating, but * given that the relation_matrix is presimplified, we shouldn't * be overshooting by too much. * * Note that NEW_ARRAY uses my_malloc(), which will gracefully handle * a request for zero bytes when relation_matrix->num_columns is zero. */ (*g)->num_torsion_coefficients = 0; (*g)->torsion_coefficients = NEW_ARRAY(relation_matrix->num_columns, long int); /* * Let "m" (for "matrix") be a synonym for relation_matrix->relations, * to make the following code more legible. */ m = relation_matrix->relations; /* * Note that the following code will work fine even if * relation_matrix->num_columns == 0. (It will keep * decrementing relation_matrix->num_rows until it * reaches zero.) */ while (relation_matrix->num_rows > 0) { /* * If the last row contains all zeros, eliminate it. * Otherwise, perform matrix operations as necessary * to create a nonzero MatrixEntry which divides both * its row and its column. */ all_zeros = TRUE; ii = relation_matrix->num_rows - 1; for (jj = 0; jj < relation_matrix->num_columns; jj++) if (m[ii][jj]) { all_zeros = FALSE; break; } if (all_zeros) relation_matrix->num_rows--; else { /* * Find an entry (ii,jj) which divides every entry * in its row and column. */ do { desired_entry_has_been_found = TRUE; /* Does entry (ii,jj) divide its row? */ for (j = 0; j < relation_matrix->num_columns; j++) if (m[ii][j] % m[ii][jj]) { mult = - (m[ii][j] / m[ii][jj]); add_column_multiple(relation_matrix, jj, j, mult, overflow); if (*overflow == TRUE) return; jj = j; desired_entry_has_been_found = FALSE; break; } /* Does entry (ii,jj) divide its column? */ for (i = 0; i < relation_matrix->num_rows; i++) if (m[i][jj] % m[ii][jj]) { mult = - (m[i][jj] / m[ii][jj]); add_row_multiple(relation_matrix, ii, i, mult, overflow); if (*overflow == TRUE) return; ii = i; desired_entry_has_been_found = FALSE; break; } } while ( ! desired_entry_has_been_found); /* * Use row ii to eliminate generator jj from all other rows. */ for (i = 0; i < relation_matrix->num_rows; i++) if (i != ii) { mult = - (m[i][jj] / m[ii][jj]); add_row_multiple(relation_matrix, ii, i, mult, overflow); if (*overflow == TRUE) return; } /* * Pretend we also zeroed out the entries in row ii, * except for entry (ii,jj) itself. (There is no need * to do actually write the zeros.) */ /* * Write the torsion coefficient iff it isn't 1, * and increment num_torsion_coefficients. */ if (ABS(m[ii][jj]) != 1) (*g)->torsion_coefficients[(*g)->num_torsion_coefficients++] = ABS(m[ii][jj]); /* * Overwrite column jj with the last column, and decrement num_columns. */ relation_matrix->num_columns--; for (i = 0; i < relation_matrix->num_rows; i++) m[i][jj] = m[i][relation_matrix->num_columns]; /* * Eliminate row ii by swapping it with the last active row, * and decrementing num_rows. */ relation_matrix->num_rows--; temp = m[ii]; m[ii] = m[relation_matrix->num_rows]; m[relation_matrix->num_rows] = temp; } } /* * Now that all the relations are gone, any remaining * generators represent torsion coefficients of zero. */ while (relation_matrix->num_columns--) (*g)->torsion_coefficients[(*g)->num_torsion_coefficients++] = 0L; } static void add_row_multiple( RelationMatrix *relation_matrix, int src, int dst, MatrixEntry mult, Boolean *overflow) { MatrixEntry factor_max, term0, term1, sum; int j; /* * If we weren't concerned about overflows, * this function could be written * for (j = 0; j < relation_matrix->num_columns; j++) relation_matrix->relations[dst][j] += mult * relation_matrix->relations[src][j]; * */ /* * If mult == 0 there's no work to be done, * so return now and avoid having to worry about special cases. */ if (mult == 0) return; /* * Let factor_max be the largest number you can multiply * times "mult" without getting an overflow. * (Division is slow compared to multiplication, but we only * do one division for the whole row, so it won't be noticable * for large matrices.) */ factor_max = ENTRY_MAX / ABS(mult); for (j = 0; j < relation_matrix->num_columns; j++) { if (ABS(relation_matrix->relations[src][j]) <= factor_max) { term0 = relation_matrix->relations[dst][j]; term1 = mult * relation_matrix->relations[src][j]; sum = term0 + term1; if ( (term0 > 0 && term1 > 0 && sum < 0) || (term0 < 0 && term1 < 0 && (sum > 0 || sum == LIMIT_MIN))) /* * The addition would cause an overflow. * Set *overflow to TRUE and let the calling function * decide what to do about it. */ *overflow = TRUE; else relation_matrix->relations[dst][j] = sum; } else { /* * The multiplication would cause an overflow. * Set *overflow to TRUE and let the calling function * decide what to do about it. */ *overflow = TRUE; } } } static void add_column_multiple( RelationMatrix *relation_matrix, int src, int dst, MatrixEntry mult, Boolean *overflow) { MatrixEntry factor_max, term0, term1, sum; int i; /* * If we weren't concerned about overflows, * this function could be written * for (i = 0; i < relation_matrix->num_rows; i++) relation_matrix->relations[i][dst] += mult * relation_matrix->relations[i][src]; * */ /* * If mult == 0 there's no work to be done, * so return now and avoid having to worry about special cases. */ if (mult == 0) return; /* * Let factor_max be the largest number you can multiply * times "mult" without getting an overflow. * (Division is slow compared to multiplication, but we only * do one division for the whole row, so it won't be noticable * for large matrices.) */ factor_max = ENTRY_MAX / ABS(mult); for (i = 0; i < relation_matrix->num_rows; i++) { if (ABS(relation_matrix->relations[i][src]) <= factor_max) { term0 = relation_matrix->relations[i][dst]; term1 = mult * relation_matrix->relations[i][src]; sum = term0 + term1; if ( (term0 > 0 && term1 > 0 && sum < 0) || (term0 < 0 && term1 < 0 && (sum > 0 || sum == LIMIT_MIN))) /* * The addition would cause an overflow. * Set *overflow to TRUE and let the calling function * decide what to do about it. */ *overflow = TRUE; else relation_matrix->relations[i][dst] = sum; } else { /* * The multiplication would cause an overflow. * Set *overflow to TRUE and let the calling function * decide what to do about it. */ *overflow = TRUE; } } } static MatrixEntry safe_addition( MatrixEntry a, MatrixEntry b, Boolean *overflow) { /* * If we weren't concerned about overflows, * this function would be simple indeed: * return a + b; * */ MatrixEntry sum; sum = a + b; if ( (a > 0 && b > 0 && sum < 0) || (a < 0 && b < 0 && (sum > 0 || sum == LONG_MIN))) { *overflow = TRUE; return 0; } else return sum; } static MatrixEntry safe_multiplication( MatrixEntry a, MatrixEntry b, Boolean *overflow) { /* * If we weren't concerned about overflows, * this function would be simple indeed: * return a * b; * */ MatrixEntry factor_max; if (a == 0) return 0; /* * Division is slow compared to multiplication, * but safe_multiplication() isn't used in any time-critical functions. */ factor_max = ENTRY_MAX / ABS(a); if (ABS(b) <= factor_max) return a * b; else { *overflow = TRUE; return 0; } } void free_relations( RelationMatrix *relation_matrix) { int i; for (i = 0; i < relation_matrix->max_rows; i++) my_free(relation_matrix->relations[i]); if (relation_matrix->relations != NULL) my_free(relation_matrix->relations); } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/homology.h000644 000765 000024 00000004044 12377774107 021013 0ustar00babstaff000000 000000 /* * homology.h * * This file defines a structure used in homology.c to hold a * relation matrix for a finitely generated abelian group. * MC 01/26/08 * */ /* * This file (homology.h) is intended solely for inclusion in SnapPea.h. */ #include "kernel_namespace.h" /* * To minimize the possibility of overflows, we use long integers instead * of regular integers to do the matrix computations. Take ENTRY_MIN * to be -LONG_MAX instead of LONG_MIN, to minimize the (unlikely) * possibility that negation causes an overflow (i.e. -LONG_MIN * = -(0x80000000) = (0x80000000) = LONG_MIN). */ /* Note added by MC: in fact, overflow is extremely common in the * classical algorithm for computing Smith normal form. See the * paper "Asymptotically Fast Triangularization of Matrices over * Rings" by James L. Hafner and Kevin S. McCurley. They give an * example of a 20x20 matrix with entries between 0 and 10 such that * the classical integer triangularization algorithm produces a * matrix entry larger than 10^5011. A typical matrix of that type * leads to entries of size 10^500. The algorithm discussed in the * paper avoids the overflow by doing computations modulo a multiple * of the exponent of the torsion subgroup. This algorithm is * implemented in PARI, so need not be implemented in SnapPea. * However, to use an external library to compute the Smith form * we need access to the relation matrix. This is the reason that * I moved this declaration here, from homology.c */ typedef long int MatrixEntry; #define ENTRY_MAX LLONG_MAX #define ENTRY_MIN (-LLONG_MAX) #define LIMIT_MIN LLONG_MIN /* * The number of meaningful rows and columns in a RelationMatrix are * are given by num_rows and num_columns, respectively. max_rows * records the original number of rows allocated, so we know how many * rows to free at the end. */ typedef struct { int num_rows, num_columns, max_rows; MatrixEntry **relations; } RelationMatrix; #include "end_namespace.h" regina-4.96/engine/snappea/kernel/hyperbolic_structure.c000644 000765 000024 00000140627 12377774107 023441 0ustar00babstaff000000 000000 /* * hyperbolic_structure.c * * This file contains the following functions which the kernel * provides for the UI: * * SolutionType find_complete_hyperbolic_structure(Triangulation *manifold); * SolutionType do_Dehn_filling(Triangulation *manifold); * SolutionType remove_Dehn_fillings(Triangulation *manifold); * * Their use is described in SnapPea.h. * * This file also provides the following functions for use * within the kernel * * void remove_hyperbolic_structures(Triangulation *manifold); * void polish_hyperbolic_structures(Triangulation *manifold); * * remove_hyperbolic_structures() frees the TetShapes (if any) pointed to * by each tet->shape[] and sets manifold->solution_type[complete] and * manifold->solution_type[filled] to not_attempted. * * polish_hyperbolic_structures() attempts to increase the accuracy of * both the complete and the Dehn filled hyperbolic structures already * present in *manifold. It's designed to be called following * retriangulation operations which diminish the accuracy of the TetShapes. * * * SnapPea uses Newton's method to solve the gluing equations (see * Thurston's notes for an explanation of the gluing equations). The * linear equations generated at each iteration of Newton's method are * solved using Gaussian elimination with partial pivoting. * * The number of gluing equations is (number of tetrahedra + number of cusps), * while the number of variables is just the number of tetrahedra. * Unlike previous versions of SnapPea, this version does not select out * a linearly independent subset of the gluing equations, but rather * solves the whole system. My hope is that in cases where the gluing * equations are degenerate (or nearly so) the pivoting will tend to * select a more robust subset of the equations. In any case, once the * equations have been solved, there will be some rows of zeros at the * bottom, one for each cusp. The constants on the right hand side of * these zero rows provide a measure of how accurately the equations were * solved. For example, in the case of the Whitehead link complement, * which has four tetrahedra and two cusps, the matrix will reduce to * * 1 0 0 0 a <- solution * 0 1 0 0 b * 0 0 1 0 c * 0 0 0 1 d * 0 0 0 0 e <- should be zero * 0 0 0 0 f * * where the constants a - d represent the solution to the equations, * and the constants e - f (which will be close to zero) measure the * solution's accuracy. * * The coordinate systems used to parameterize the shapes of the * tetrahedra are chosen dynamically so as to avoid singularities. * The comment preceding the function choose_coordinate_system() * (see below) explains the underlying mathematics. * * The gluing equations are written in terms of complex variables, * namely the edge parameters of the tetrahedra. If the manifold is * oriented, they are analytic functions of these variables, and * Newton's method is applied directly. If the manifold is unoriented, * they are almost analytic, but not quite: they are analytic functions * of the variables and their complex conjugates. (Reversing the * orientation of a tetrahedron replaces its edge parameter with the * inverse of its complex conjugate.) Newton's method is applied by * writing the n x m system of complex equations as a 2n x 2m system of * real equations. * * [One could of course use real equations for oriented manifolds as * well, but the speed suffers. The arithmetic involved in the row * operations (mulitplying an entry in one row by a constant and adding * it to the corresponding entry in another row) is four times faster * for real numbers than for complex numbers, but a 2n x 2m real system * requires eight times as many such steps as does an n x m complex system. * Hence the speed decreases by a factor of two. This is why SnapPea * handles oriented and unoriented manifolds differently. Other than * loss of speed, there is no harm in passing an unoriented (but * orientable) manifold, with manifold->orientability == * unknown_orientability).] * * do_Dehn_filling() computes the shape of each unfilled cusp and * stores it in the field cusp->cusp_shape[current]. * find_complete_hyperbolic_structure(), after calling do_Dehn_filling(), * copies cusp->cusp_shape[current] to cusp->cusp_shape[initial]. */ #include "kernel.h" #include "kernel_namespace.h" static const ComplexWithLog regular_shape = { {0.5, ROOT_3_OVER_2}, {0.0, PI_OVER_3} }; /* * RIGHT_BALLPARK must be set fairly large to allow for degenerate * solutions, which cannot be computed to great accuracy. */ #define RIGHT_BALLPARK 1e-2 #define QUADRATIC_THRESHOLD 1e-4 /* * If the solution is degenerate and Newton's method has been * iterated at least DEGENERACY_ITERATIONS times, then * do_Dehn_filling() will keep going iff the distance to * the solution decreases by a factor of at least DEGENERACY_RATIO * each time. */ #define DEGENERACY_ITERATIONS 10 #define DEGENERACY_RATIO 0.9 /* * If we haven't converged and aren't making progress after * ITERATION_LIMIT iterations, we give up. */ #define ITERATION_LIMIT 101 /* * The CuspInfo and ChernSimonsInfo data structures are * used only in polish_hyperbolic_structures(). */ typedef struct { Boolean is_complete; Real m, l; } CuspInfo; typedef struct { Boolean CS_value_is_known, CS_fudge_is_known; Real CS_value[2], CS_fudge[2]; } ChernSimonsInfo; static void allocate_cusp_status_arrays(Triangulation *manifold, Boolean **is_complete_array, Real **m_array, Real **l_array); static void free_cusp_status_arrays(Boolean *is_complete_array, Real *m_array, Real *l_array); static void record_cusp_status(Triangulation *manifold, Boolean is_complete_array[], Real m_array[], Real l_array[]); static void restore_cusp_status(Triangulation *manifold, Boolean is_complete_array[], Real m_array[], Real l_array[]); static void copy_tet_shapes(Triangulation *manifold, FillingStatus source, FillingStatus dest); static void copy_cusp_shapes(Triangulation *manifold, FillingStatus source, FillingStatus dest); static void verify_coefficients(Triangulation *manifold); static void allocate_equations(Triangulation *manifold, Complex ***complex_equations, Real ***real_equations, int *num_rows, int *num_columns); static void free_equations(Triangulation *manifold, Complex **complex_equations, Real **real_equations, int num_rows); static void allocate_complex_equations(Triangulation *manifold, Complex ***complex_equations, int *num_rows, int *num_columns); static void allocate_real_equations(Triangulation *manifold, Real ***real_equations, int *num_rows, int *num_columns); static void free_complex_equations(Complex **complex_equations, int num_rows); static void free_real_equations(Real **real_equations, int num_rows); static void associate_complex_eqns_to_edges_and_cusps(Triangulation *manifold, Complex **complex_equations); static void associate_real_eqns_to_edges_and_cusps(Triangulation *manifold, Real **real_equations); static void dissociate_eqns_from_edges_and_cusps(Triangulation *manifold); static void choose_coordinate_system(Triangulation *manifold); static Boolean check_convergence(Orientability orientability, Complex **complex_equations, Real **real_equations, int num_rows, int num_columns, Real *distance_to_solution, Boolean *convergence_is_quadratic, Real *distance_ratio); static Real compute_distance_complex(Complex **complex_equations, int num_rows, int num_columns); static Real compute_distance_real(Real **real_equations, int num_rows, int num_columns); static FuncResult solve_equations(Orientability orientability, Complex **complex_equations, Real **real_equations, int num_rows, int num_columns, Complex *solution); static void convert_solution(Real *real_solution, Complex *solution, int num_columns); static void save_chern_simons(Triangulation *manifold, ChernSimonsInfo *chern_simons_info); static void restore_chern_simons(Triangulation *manifold, ChernSimonsInfo *chern_simons_info); static void allocate_arrays(Triangulation *manifold, TetShape **save_shapes, CuspInfo **save_cusp_info); static void save_filled_solution(Triangulation *manifold, TetShape *save_shapes, CuspInfo *save_cusp_info); static void restore_filled_solution(Triangulation *manifold, TetShape *save_shapes, CuspInfo *save_cusp_info); static void validate_null_history(Triangulation *manifold); static void free_arrays(TetShape *save_shapes, CuspInfo *save_cusp_info); static void copy_ultimate_to_penultimate(Triangulation *manifold); static void suppress_imaginary_parts(Triangulation *manifold); SolutionType find_complete_hyperbolic_structure( Triangulation *manifold) { Boolean *is_complete_array; Real *m_array, *l_array; /* * Set all Tetrahedra to be regular ideal tetrahedra. * Allocate the TetShapes if necessary. * Clear the shape_histories if necessary. */ initialize_tet_shapes(manifold); /* * We don't want to destroy any preexisting Dehn filling * coefficients, so copy them out to arrays. */ allocate_cusp_status_arrays(manifold, &is_complete_array, &m_array, &l_array); record_cusp_status(manifold, is_complete_array, m_array, l_array); /* * Complete all the cusps. */ complete_all_cusps(manifold); /* * Call do_Dehn_filling(). * In general it thinks it's finding a filled hyperbolic structure, * but since all the cusps are complete it's really finding the * complete hyperbolic structure. */ do_Dehn_filling(manifold); /* * Copy the "filled solution" (which is really the complete * solution) to where the complete solution belongs. */ copy_solution(manifold, filled, complete); /* * Restore the preexisting Dehn filling coefficients. */ restore_cusp_status(manifold, is_complete_array, m_array, l_array); free_cusp_status_arrays(is_complete_array, m_array, l_array); /* * Done. */ return manifold->solution_type[complete]; } void initialize_tet_shapes( Triangulation *manifold) { Tetrahedron *tet; int i, j; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) { for (i = 0; i < 2; i++) /* i = complete, filled */ { if (tet->shape[i] == NULL) tet->shape[i] = NEW_STRUCT(TetShape); for (j = 0; j < 3; j++) tet->shape[i]->cwl[ultimate][j] = regular_shape; } clear_shape_history(tet); } } static void allocate_cusp_status_arrays( Triangulation *manifold, Boolean **is_complete_array, Real **m_array, Real **l_array) { *is_complete_array = NEW_ARRAY(manifold->num_cusps, Boolean); *m_array = NEW_ARRAY(manifold->num_cusps, Real); *l_array = NEW_ARRAY(manifold->num_cusps, Real); } static void free_cusp_status_arrays( Boolean *is_complete_array, Real *m_array, Real *l_array) { my_free(is_complete_array); my_free(m_array); my_free(l_array); } static void record_cusp_status( Triangulation *manifold, Boolean is_complete_array[], Real m_array[], Real l_array[]) { Cusp *cusp; for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) { is_complete_array[cusp->index] = cusp->is_complete; m_array[cusp->index] = cusp->m; l_array[cusp->index] = cusp->l; } } static void restore_cusp_status( Triangulation *manifold, Boolean is_complete_array[], Real m_array[], Real l_array[]) { Cusp *cusp; for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) { cusp->is_complete = is_complete_array[cusp->index]; cusp->m = m_array[cusp->index]; cusp->l = l_array[cusp->index]; } } void complete_all_cusps( Triangulation *manifold) { Cusp *cusp; for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) { cusp->is_complete = TRUE; cusp->m = 0.0; cusp->l = 0.0; } } void copy_solution( Triangulation *manifold, FillingStatus source, /* complete or filled */ FillingStatus dest) /* filled or complete */ { copy_tet_shapes(manifold, source, dest); copy_cusp_shapes(manifold, source, dest); manifold->solution_type[dest] = manifold->solution_type[source]; } static void copy_tet_shapes( Triangulation *manifold, FillingStatus source, /* complete or filled */ FillingStatus dest) /* filled or complete */ { Tetrahedron *tet; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) { *tet->shape[dest] = *tet->shape[source]; clear_one_shape_history(tet, dest); copy_shape_history(tet->shape_history[source], &tet->shape_history[dest]); } } static void copy_cusp_shapes( Triangulation *manifold, FillingStatus source, /* complete/initial or filled/current */ FillingStatus dest) /* filled/current or complete/initial */ { Cusp *cusp; for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) { cusp->cusp_shape[dest] = cusp->cusp_shape[source]; cusp->shape_precision[dest] = cusp->shape_precision[source]; } } /* * do_Dehn_filling() uses complex gluing equations for oriented * manifolds and real gluing equations for unoriented manifolds. * To keep the structure of its algorithm as clear as possible, * do_Dehn_filling() passes variables for both the complex_equations * and real_equations to the lower level routines, and lets the lower * level routines sort out which is the correct one to use for the * given manifold. */ SolutionType do_Dehn_filling( Triangulation *manifold) { Complex **complex_equations = NULL, *delta; Real **real_equations = NULL, distance_to_solution, distance_ratio; int num_rows, num_columns, iterations, result = func_failed; Boolean convergence_is_quadratic, solution_was_found, iteration_limit_exceeded; /* * Notify the UI that a potentially long computation is beginning. * The user may abort the computation if desired. */ uLongComputationBegins("Computing hyperbolic structure . . .", TRUE); /* * Check that the Dehn filling coefficients are valid. */ verify_coefficients(manifold); /* * Number the Tetrahedra. This implicitly assigns each Tetrahedron * to one of the complex variables. */ number_the_tetrahedra(manifold); /* * The following call to compute_holonomies() will rarely be needed, * but it guarantees holonomy[penultimate][] will be correct * even if Newton's method terminates after only one iteration. */ compute_holonomies(manifold); /* * allocate_equations() not only allocates the appropriate * set of equations, it also associates each equation to an edge * or cusp in the manifold. This is why the equations are not * explicitly passed to compute_equations(). */ allocate_equations( manifold, &complex_equations, &real_equations, &num_rows, &num_columns); /* * Allocate an array to hold the changes to the Tetrahedron shapes * specified by Newton's method. */ delta = NEW_ARRAY(manifold->num_tetrahedra, Complex); /* * distance_to_solution is initialized to RIGHT_BALLPARK * to get the proper behavior the first time through the loop. */ distance_to_solution = RIGHT_BALLPARK; convergence_is_quadratic = FALSE; iterations = 0; iteration_limit_exceeded = FALSE; do { choose_coordinate_system(manifold); compute_gluing_equations(manifold); /* * We're done if either * * (1) the solution has converged, or * * (2) the solution is degenerate (in which case it * would take a long, long time to converge). */ if ( check_convergence( manifold->orientability, complex_equations, real_equations, num_rows, num_columns, &distance_to_solution, &convergence_is_quadratic, &distance_ratio) || ( solution_is_degenerate(manifold) && iterations > DEGENERACY_ITERATIONS && distance_ratio > DEGENERACY_RATIO ) ) { solution_was_found = TRUE; break; /* break out of the do {} while (TRUE) loop */ } /* * iterations almost never exceeds ITERATION_LIMIT. * In fact, SnapPea was used for years without this check, and * it always found solutions. The first examples where the * solutions didn't converge were the meridional Dehn fillings * on the nonorientable 6-tetrahedron census manifolds * x045, x048, x063, x084 and x175. For further comments, * please see the file "failure to solve gluing eqns". */ if (iterations > ITERATION_LIMIT && distance_ratio >= 1.0) { iteration_limit_exceeded = TRUE; solution_was_found = FALSE; break; /* break out of the do {} while (TRUE) loop */ } result = solve_equations( manifold->orientability, complex_equations, real_equations, num_rows, num_columns, delta); if (result == func_cancelled || result == func_failed) { solution_was_found = FALSE; break; /* break out of the do {} while (TRUE) loop */ } update_shapes(manifold, delta); iterations++; } while (TRUE); /* The loop terminates in one of the break statements. */ /* * In the rare case that distance_to_solution is exactly zero, * copy the ultimate solution to the penultimate one, to indicate * that we've solved the equations to full accuracy. */ if (distance_to_solution == 0.0) copy_ultimate_to_penultimate(manifold); free_equations(manifold, complex_equations, real_equations, num_rows); my_free(delta); if (solution_was_found == TRUE) identify_solution_type(manifold); else if (iteration_limit_exceeded == TRUE) manifold->solution_type[filled] = no_solution; else switch (result) { case func_cancelled: manifold->solution_type[filled] = not_attempted; break; case func_failed: manifold->solution_type[filled] = no_solution; break; } /* * 96/1/12 Craig has requested that for flat solutions SnapPea's * complex length function provide consistent signs for rotation * angles of elliptic isometries (see complex_length.c). I was * concerned about distinguishing flat solutions from almost flat * solutions, so here we check whether the solution is provably flat, * and if so set the imaginary parts of all tet shapes to zero. * * Proposition. If a solution (to the gluing equations) is * almost flat and the Dehn filling coefficients are all integers, * then the solution obtained by setting the imaginary parts * of all tetrahedron shapes to zero is stable, in the sense that * Newton's method would keep all imaginary parts zero. * * Proof. In Newton's method, both the derivative matrix and the * "right hand side" would be real, so the computed array "delta" * would also be real. QED */ if (manifold->solution_type[filled] == flat_solution && all_Dehn_coefficients_are_integers(manifold) == TRUE) suppress_imaginary_parts(manifold); compute_cusp_shapes(manifold, current); compute_CS_value_from_fudge(manifold); uLongComputationEnds(); return manifold->solution_type[filled]; } /* * verify_coefficients() alerts the user and exits if the current set * of Dehn filling coefficients includes * * (0,0) Dehn filling on any cusp, or * * (p,q) Dehn filling, with q != 0, on a nonorientable cusp. * * set_cusp_info() should have already checked the coefficients * for errors, so verify_coefficients() should be unnecessary. It is * included to guard against programming errors (e.g. passing a manifold * whose coefficients have not been set at all), not user errors. */ static void verify_coefficients( Triangulation *manifold) { Cusp *cusp; for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) if ( cusp->is_complete ? cusp->m != 0.0 || cusp->l != 0.0 : (cusp->m == 0.0 && cusp->l == 0.0) || (cusp->topology == Klein_cusp && cusp->l != 0.0) ) uFatalError("verify_coefficients", "hyperbolic_structure"); } /* * allocate_equations() allocates space for the equations as a matrix, * and also associates each equation to an edge or cusp in the manifold. */ static void allocate_equations( Triangulation *manifold, Complex ***complex_equations, Real ***real_equations, int *num_rows, int *num_columns) { if (manifold->orientability == oriented_manifold) { real_equations = NULL; allocate_complex_equations(manifold, complex_equations, num_rows, num_columns); associate_complex_eqns_to_edges_and_cusps(manifold, *complex_equations); } else { complex_equations = NULL; allocate_real_equations(manifold, real_equations, num_rows, num_columns); associate_real_eqns_to_edges_and_cusps(manifold, *real_equations); } } static void free_equations( Triangulation *manifold, Complex **complex_equations, Real **real_equations, int num_rows) { if (manifold->orientability == oriented_manifold) free_complex_equations(complex_equations, num_rows); else free_real_equations(real_equations, num_rows); dissociate_eqns_from_edges_and_cusps(manifold); } /* * allocate_complex_equations() sets *num_rows and *num_columns, * and allocates memory for a complex matrix of dimensions * (*num_rows) x (*num_columns + 1). The extra column will * hold the constant on the right hand side of the equations. */ static void allocate_complex_equations( Triangulation *manifold, Complex ***complex_equations, int *num_rows, int *num_columns) { int i; /* * We'll have an equation for each edge, and also an equation * for each cusp. The number of edges in an ideal triangulation * equals the number of tetrahedra, by an Euler characteristic * argument. */ *num_rows = manifold->num_tetrahedra + manifold->num_cusps; /* * We'll have one complex variable for each ideal tetrahedron. */ *num_columns = manifold->num_tetrahedra; /* * The matrix is stored as an array of row pointers. */ *complex_equations = NEW_ARRAY(*num_rows, Complex *); for (i = 0; i < *num_rows; i++) (*complex_equations)[i] = NEW_ARRAY(*num_columns + 1, Complex); } /* * allocate_real_equations() sets *num_rows and *num_columns, * and allocates memory for a real matrix of dimensions * 2*(*num_rows) x 2*(*num_columns + 1). The extra column will * hold the constant on the right hand side of the equations. */ static void allocate_real_equations( Triangulation *manifold, Real ***real_equations, int *num_rows, int *num_columns) { int i; /* * Cf. allocate_complex_equations() above. */ *num_rows = 2 * (manifold->num_tetrahedra + manifold->num_cusps); *num_columns = 2 * manifold->num_tetrahedra; *real_equations = NEW_ARRAY(*num_rows, Real *); for (i = 0; i < *num_rows; i++) (*real_equations)[i] = NEW_ARRAY(*num_columns + 1, Real); } /* * free_complex_equations() frees the memory allocated * in allocate_complex_equations(). */ static void free_complex_equations( Complex **complex_equations, int num_rows) { int i; for (i = 0; i < num_rows; i++) my_free(complex_equations[i]); my_free(complex_equations); } /* * free_real_equations() frees the memory allocated * in allocate_real_equations(). */ static void free_real_equations( Real **real_equations, int num_rows) { int i; for (i = 0; i < num_rows; i++) my_free(real_equations[i]); my_free(real_equations); } /* * associate_complex_eqns_to_edges_and_cusps() associates the first * num_tetrahedra equations to edge classes, and the remaining * num_cusps equations to cusps. */ static void associate_complex_eqns_to_edges_and_cusps( Triangulation *manifold, Complex **complex_equations) { EdgeClass *edge; Cusp *cusp; for ( edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) { edge->complex_edge_equation = *complex_equations++; edge->real_edge_equation_re = NULL; edge->real_edge_equation_im = NULL; } for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) { cusp->complex_cusp_equation = *complex_equations++; cusp->real_cusp_equation_re = NULL; cusp->real_cusp_equation_im = NULL; } } /* * associate_real_eqns_to_edges_and_cusps() associates the first * 2*num_tetrahedra equations to edge classes, and the remaining * 2*num_cusps equations to cusps. */ static void associate_real_eqns_to_edges_and_cusps( Triangulation *manifold, Real **real_equations) { EdgeClass *edge; Cusp *cusp; for ( edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) { edge->complex_edge_equation = NULL; edge->real_edge_equation_re = *real_equations++; edge->real_edge_equation_im = *real_equations++; } for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) { cusp->complex_cusp_equation = NULL; cusp->real_cusp_equation_re = *real_equations++; cusp->real_cusp_equation_im = *real_equations++; } } /* * dissociate_eqns_from_edges_and_cusps() dissociates the gluing * equations from the edges and cusps. Note that this function * works for both complex and real equations. */ static void dissociate_eqns_from_edges_and_cusps( Triangulation *manifold) { EdgeClass *edge; Cusp *cusp; for ( edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) { edge->complex_edge_equation = NULL; edge->real_edge_equation_re = NULL; edge->real_edge_equation_im = NULL; } for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) { cusp->complex_cusp_equation = NULL; cusp->real_cusp_equation_re = NULL; cusp->real_cusp_equation_im = NULL; } } /* * The shape of an ideal tetrahedron is traditionally parameterized * by one of the three forms of its cross ratio. Cross ratios of * 0, 1 and infinity represent degenerate tetrahedra. Near these * points, bad things happen. The two main problems are that (1) some * of the entries in the derivative matrix (used in Newton's method) * approach infinity, and (2) incrementing the solution can move it * too close to a singularity, resulting in wild swings in the arguments * of the cross ratios. Switching the coordinates from the cross * ratio to the log of the cross ratio helps a bit. Rather than having * two singularities (0 and 1) embedded in the parameter space, you * have only one (the singularity which used to be at 1 is now at 0, * but the singularity which used to be at 0 has been happily pushed * out to infinity). * * This scheme can be further improved by choosing a (logarithmic) * coordinate system based on the current shape of * the tetrahedron. The coordinate system is chosen so that the * current shape of the tetrahedron stays away from the singularity * in the parameter space. Specifically, let * * z0 = z * * 1 * z1 = ----- * 1 - z * * z - 1 * z2 = ----- * z * * and divide the complex plane into three regions: * * region A: |z-1| > 1 && Re(z) < 1/2 * region B: |z| > 1 && Re(z) > 1/2 * region C: |z-1| < 1 && |z| < 1 * * Viewed on the Riemann sphere, the singularities are equally * spaced points on the equator, and the regions are separated * by meridians spaced 120 degrees apart. The points along the * boundaries may be arbitrarily assigned to either neighboring region. * * In region A, use log(z0) coordinates. * In region B, use log(z1) coordinates. * In region C, use log(z2) coordinates. * * Each entry in the derivative matrix used in Newton's method is * a linear combination of the derivatives of log(z0), log(z1) * and log(z2). The above choice of coordinates implies that each * such derivative will have modulus less than or equal to one. * Here's the proof. First compute * * d(log z0) 1 * --------- = - * dz z * * d(log z1) 1 * --------- = ----- * dz 1 - z * * d(log z2) 1 * --------- = -------- * dz z(z - 1) * * Now take ratios of the above to compute * * d(log z0) d(log z0) 1 - z d(log z0) * --------- = 1 --------- = ----- --------- = z - 1 * d(log z0) d(log z1) z d(log z2) * * d(log z1) z d(log z1) d(log z1) * --------- = ----- --------- = 1 --------- = -z * d(log z0) 1 - z d(log z1) d(log z2) * * d(log z2) 1 d(log z2) -1 d(log z2) * --------- = ----- --------- = ----- --------- = 1 * d(log z0) z - 1 d(log z1) z d(log z2) * * Say z lies in region A, and we have chosen log(z0) coordinates * as indicated previously. The derivatives in the first column of the * above table have modulus less than or equal to 1. This is obvious * for the first entry in the column. For the third entry it's an * immediate consequence of the condition |1 - z| > 1. For the second * entry, note that * * | Im(z) | = | Im(1 - z) | * and * | Re(z) | < | Re(1 - z) | iff Re(z) < 1/2 * * hence |z| < |1-z|. * * Similar arguments show that when z lies in region B (resp. region C) * the derivatives in the second column (resp. third column) have * modulus less than or equal to 1. (In fact, the derivatives all * lie in region C, as can be seen from the fact that the two nonconstant * derivatives in each column sum to -1. For our purposes, though, it's * enough just to know that the derivatives are bounded, so the entries * in the derivative matrix used in Newton's method cannot diverge to * infinity.) * * Theoretical note: I briefly entertained the idea of finding a * single coordinate system which avoids all three singularities. * Picard's Little Theorem shows that this is not possible for an * analytic function. It might be possible for a nonanalytic function * (perhaps a simple function of z and z-bar?) but I haven't pursued * this, and in any case such a function wouldn't be conformal. * However, each Tetrahedron's shape_history fields record the topological * information such a master coordinate system would contain. */ static void choose_coordinate_system( Triangulation *manifold) { Tetrahedron *tet; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) if ( tet->shape[filled]->cwl[ultimate][0].log.real < 0.0 /* |z| < 1 */ && tet->shape[filled]->cwl[ultimate][1].log.real > 0.0 /* |z-1| < 1 */ ) tet->coordinate_system = 2; /* region C, log(z2) coordinates */ else if (tet->shape[filled]->cwl[ultimate][0].rect.real > 0.5) /* Re(z) < 1/2 */ tet->coordinate_system = 1; /* region B, log(z1) coordinates */ else tet->coordinate_system = 0; /* region A, log(z0) coordinates */ } /* * check_convergence() checks whether Newton's method has converged to * a solution. We check for convergence in the range rather than the * domain. In other words, we check how precisely the gluing equations * are satisfied, without regard to whether the logs of the tetrahedra's * edge parameters are converging. The reason for this is that degenerate * equations will be satisfied more and more precisely by edge parameters * whose logs are diverging to infinity. * * We know Newton's method has converged when it begins making * small random changes. We check this by seeing whether * * (1) it's in the right ballpark (meaning it should be * converging quadratically), and * * (2) the new distance is greater than the old one. * * We also offer a shortcut, to avoid the possibility of having to * wait through several essentially random iterations of Newton's * method which just happen to decrease the distance to the solution * each time. The shortcut is that we note when quadratic convergence * begins, and then as soon as it ends we know we've converged. * * Finally, if the equations are satisfied perfectly, we return TRUE. * I realize this is not very likely, but it makes the function * logically correct. (Without this provision a perfect solution * would cycle endlessly through Newton's method.) * * check_convergence() returns TRUE when it considers Newton's method * to have converged, and FALSE otherwise. */ static Boolean check_convergence( Orientability orientability, Complex **complex_equations, Real **real_equations, int num_rows, int num_columns, Real *distance_to_solution, Boolean *convergence_is_quadratic, Real *distance_ratio) { Real old_distance; old_distance = *distance_to_solution; *distance_to_solution = orientability == oriented_manifold ? compute_distance_complex(complex_equations, num_rows, num_columns) : compute_distance_real(real_equations, num_rows, num_columns); *distance_ratio = *distance_to_solution / old_distance; if (*distance_ratio < QUADRATIC_THRESHOLD) *convergence_is_quadratic = TRUE; return ( (*distance_to_solution < RIGHT_BALLPARK && *distance_ratio > 1.0) || (*convergence_is_quadratic && *distance_ratio > 0.5) || (*distance_to_solution == 0.0) /* seems unlikely, but who knows */ ); } static Real compute_distance_complex( Complex **complex_equations, int num_rows, int num_columns) { Real distance_squared; int i; distance_squared = 0.0; for (i = 0; i < num_rows; i++) distance_squared += complex_modulus_squared(complex_equations[i][num_columns]); return sqrt(distance_squared); /* no need for safe_sqrt() */ } static Real compute_distance_real( Real **real_equations, int num_rows, int num_columns) { Real distance_squared; int i; distance_squared = 0.0; for (i = 0; i < num_rows; i++) distance_squared += real_equations[i][num_columns] * real_equations[i][num_columns]; return sqrt(distance_squared); /* no need for safe_sqrt() */ } /* * In practice a typecast would suffice to convert the real_solution * to the Complex solution, since an array of n Complex numbers is stored * as an array of 2n reals. But we do an explicit conversion anyhow, * in the interest of good style and robust code (and also in the * interest of maintaining solve_real_equations() as a general purpose * routine for solving real equations). */ static FuncResult solve_equations( Orientability orientability, Complex **complex_equations, Real **real_equations, int num_rows, int num_columns, Complex *solution) { Real *real_solution; FuncResult result; if (orientability == oriented_manifold) result = solve_complex_equations(complex_equations, num_rows, num_columns, solution); else { real_solution = NEW_ARRAY(num_columns, Real); result = solve_real_equations(real_equations, num_rows, num_columns, real_solution); if (result == func_OK) convert_solution(real_solution, solution, num_columns); my_free(real_solution); } return result; } static void convert_solution( Real *real_solution, Complex *solution, int num_columns) { int count; for (count = num_columns/2; --count >= 0; ) { solution->real = *real_solution++; solution->imag = *real_solution++; solution++; } } void remove_hyperbolic_structures( Triangulation *manifold) { Tetrahedron *tet; int i; /* * If TetShapes are present, remove them. */ if (manifold->solution_type[complete] != not_attempted) for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) { for (i = 0; i < 2; i++) /* i = complete, filled */ { my_free(tet->shape[i]); tet->shape[i] = NULL; } clear_shape_history(tet); } /* * Set solution_type[complete] and solution_type[filled] * to not_attempted. */ for (i = 0; i < 2; i++) /* i = complete, filled */ manifold->solution_type[i] = not_attempted; } void polish_hyperbolic_structures( Triangulation *manifold) { TetShape *save_shapes; CuspInfo *save_cusp_info; ChernSimonsInfo chern_simons_info; if (manifold->solution_type[complete] == not_attempted) uFatalError("polish_hyperbolic_structures", "hyperbolic_structures"); save_chern_simons(manifold, &chern_simons_info); allocate_arrays(manifold, &save_shapes, &save_cusp_info); save_filled_solution(manifold, save_shapes, save_cusp_info); complete_all_cusps(manifold); copy_tet_shapes(manifold, complete, filled); validate_null_history(manifold); do_Dehn_filling(manifold); copy_solution(manifold, filled, complete); restore_filled_solution(manifold, save_shapes, save_cusp_info); validate_null_history(manifold); do_Dehn_filling(manifold); free_arrays(save_shapes, save_cusp_info); restore_chern_simons(manifold, &chern_simons_info); } static void save_chern_simons( Triangulation *manifold, ChernSimonsInfo *chern_simons_info) { /* * Why do we need to save and restore the Chern-Simons info? * * polish_hyperbolic_structures() is called just after a * Triangulation has been modified (e.g. by basic_simplification() * or randomize_triangulation()). At this point the TetShapes are * slightly inaccurate, the CS_value is accurate, and the * CS_fudge is completely wrong. We don't want to call * compute_CS_fudge_from_value() just yet, because then the * CS_fudge would inherit the inaccuracies of the TetShapes. * But it we call find_complete_hyperbolic_structure() or * do_Dehn_filling() right way, they will recompute the CS_value * based on the completely wrong CS_fudge. So we save the * CS_value until after we've polished the hyperbolic structure, * then we restore it and compute the CS_fudge using the accurate * TetShapes. */ /* * Record the Chern-Simons data. */ chern_simons_info->CS_value_is_known = manifold->CS_value_is_known; chern_simons_info->CS_fudge_is_known = manifold->CS_fudge_is_known; chern_simons_info->CS_value[ultimate] = manifold->CS_value[ultimate]; chern_simons_info->CS_value[penultimate] = manifold->CS_value[penultimate]; chern_simons_info->CS_fudge[ultimate] = manifold->CS_fudge[ultimate]; chern_simons_info->CS_fudge[penultimate] = manifold->CS_fudge[penultimate]; /* * Pretend it's no longer there, to save some useless computations. */ manifold->CS_value_is_known = FALSE; manifold->CS_fudge_is_known = FALSE; } static void restore_chern_simons( Triangulation *manifold, ChernSimonsInfo *chern_simons_info) { manifold->CS_value_is_known = chern_simons_info->CS_value_is_known; manifold->CS_fudge_is_known = chern_simons_info->CS_fudge_is_known; manifold->CS_value[ultimate] = chern_simons_info->CS_value[ultimate]; manifold->CS_value[penultimate] = chern_simons_info->CS_value[penultimate]; manifold->CS_fudge[ultimate] = chern_simons_info->CS_fudge[ultimate]; manifold->CS_fudge[penultimate] = chern_simons_info->CS_fudge[penultimate]; /* * It might makes sense to call compute_CS_fudge_from_value() at * this point, but in the interest of modularity I decided not to. */ } static void allocate_arrays( Triangulation *manifold, TetShape **save_shapes, CuspInfo **save_cusp_info) { *save_shapes = NEW_ARRAY(manifold->num_tetrahedra, TetShape); *save_cusp_info = NEW_ARRAY(manifold->num_cusps, CuspInfo); } static void save_filled_solution( Triangulation *manifold, TetShape *save_shapes, CuspInfo *save_cusp_info) { int i; Tetrahedron *tet; Cusp *cusp; /* * Save the Tetrahedron shapes. */ for (i = 0, tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; i++, tet = tet->next) save_shapes[i] = *tet->shape[filled]; /* * Save the Cusp information. */ for (i = 0, cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; i++, cusp = cusp->next) { save_cusp_info[i].is_complete = cusp->is_complete; save_cusp_info[i].m = cusp->m; save_cusp_info[i].l = cusp->l; } } static void restore_filled_solution( Triangulation *manifold, TetShape *save_shapes, CuspInfo *save_cusp_info) { int i; Tetrahedron *tet; Cusp *cusp; /* * Restore the Tetrahedron shapes. */ for (i = 0, tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; i++, tet = tet->next) *tet->shape[filled] = save_shapes[i]; /* * Restore the Cusp information. */ for (i = 0, cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; i++, cusp = cusp->next) { cusp->is_complete = save_cusp_info[i].is_complete; cusp->m = save_cusp_info[i].m; cusp->l = save_cusp_info[i].l; } } static void validate_null_history( Triangulation *manifold) { /* * The basic_simplification() and randomize_triangulation() * functions can't be guaranteed to find correct arguments * for the logarithmic forms of the TetShapes, let alone produce * a valid history for each new Tetrahedron it introduces. * * validate_null_history() enforces a trivial shape_history * for each Tetrahedron. It does this by * * (1) clearing all shape_histories, * * (2) making sure all Tetrahedra are positively oriented, and * * (3) making sure all logs lie in the range (0, pi). * * In the nice case that these conditions are all already met, * validate_null_history() doesn't change anything, and * polish_hyperbolic_structures() ends up making only small * changes to the hyperbolic structures ("polishing" them). * * If the conditions are not met, validate_null_history() sets * the offending Tetrahedron shapes to something acceptable, and * in effect the hyperbolic structure is recomputed from scratch. */ Tetrahedron *tet; int i; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) { clear_one_shape_history(tet, filled); /* * The algorithm in update_shapes() guarantees that the * three shapes (for edge j = 0, 1, 2) will have the same sign * for rect.imag, regardless of roundoff errors, so if. * * Only the ultimate shapes are relevant. The penultimate * shapes are ignored. */ for (i = 0; i < 3; i++) { if (tet->shape[filled]->cwl[ultimate][i].rect.imag <= 0.0) tet->shape[filled]->cwl[ultimate][i] = regular_shape; tet->shape[filled]->cwl[ultimate][i].log = complex_log( tet->shape[filled]->cwl[ultimate][i].rect, PI_OVER_2); } } } static void free_arrays( TetShape *save_shapes, CuspInfo *save_cusp_info) { my_free(save_shapes); my_free(save_cusp_info); } static void copy_ultimate_to_penultimate( Triangulation *manifold) { Tetrahedron *tet; int i; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (i = 0; i < 3; i++) tet->shape[filled]->cwl[penultimate][i] = tet->shape[filled]->cwl[ultimate][i]; } static void suppress_imaginary_parts( Triangulation *manifold) { Tetrahedron *tet; int i, j; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (i = 0; i < 2; i++) /* ultimate, penultimate */ for (j = 0; j < 3; j++) { tet->shape[filled]->cwl[i][j].rect.imag = 0.0; tet->shape[filled]->cwl[i][j].log = complex_log( tet->shape[filled]->cwl[i][j].rect, tet->shape[filled]->cwl[i][j].log.imag); } } extern SolutionType remove_Dehn_fillings(Triangulation *manifold) { /* * Set all cusps to be unfilled. */ complete_all_cusps(manifold); /* * Copy the complete solution to the "filled" solution. */ copy_solution(manifold, complete, filled); /* * Call do_Dehn_filling(), to insure that all internal * data (such as the Chern-Simons invariant) are updated * correctly. This invokes an unnecessary computation, * but it keeps the code simple, and guarantees that * all internal data will be up-to-date. */ return do_Dehn_filling(manifold); } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/identify_solution_type.c000644 000765 000024 00000011313 12377774107 023756 0ustar00babstaff000000 000000 /* * identify_solution_type.c * * This file provides the function * * void identify_solution_type(Triangulation *manifold); * * which identifies the type of solution contained in the * tet->shape[filled] structures of the Tetrahedra of Triangulation *manifold, * and writes the result to manifold->solution_type[filled]. Possible * values are given by the SolutionType enum (see SnapPea.h). * * Its subroutine * * Boolean solution_is_degenerate(Triangulation *manifold); * * Is also available within the kernel, so do_Dehn_filling() can tell * whether it is converging towards a degenerate structure. */ #include "kernel.h" #include "kernel_namespace.h" /* * A solution must have volume at least VOLUME_EPSILON to count * as a positive volume solution. Otherwise the volume will be * considered zero or negative. */ #define VOLUME_EPSILON 1e-2 /* * DEGENERACY_EPSILON defines how close a tetrahedron shape must * be to zero to count as zero. It is given in logarithmic form. * E.g., if DEGENERACY_EPSILON is -6, then the tetrahedron shape * (in rectangular form) must lie within a distance exp(-6) = 0.0024... * of the origin. */ #define DEGENERACY_EPSILON -6 /* * A solution is considered flat iff it's not degenerate and the * argument of each edge parameter is within FLAT_EPSILON of 0.0 or PI. */ #define FLAT_EPSILON 1e-2 static Boolean solution_is_flat(Triangulation *manifold); static Boolean solution_is_geometric(Triangulation *manifold); void identify_solution_type( Triangulation *manifold) { if (solution_is_degenerate(manifold)) { manifold->solution_type[filled] = degenerate_solution; return; } if (solution_is_flat(manifold)) { manifold->solution_type[filled] = flat_solution; return; } if (solution_is_geometric(manifold)) { manifold->solution_type[filled] = geometric_solution; return; } if (volume(manifold, NULL) > VOLUME_EPSILON) { manifold->solution_type[filled] = nongeometric_solution; return; } manifold->solution_type[filled] = other_solution; } Boolean solution_is_degenerate( Triangulation *manifold) { Tetrahedron *tet; int i; /* * If any complex edge parameter of any Tetrahedron is * close to zero, return TRUE. Otherwise return FALSE. * * Note that it's enough to check for shapes close to * zero: if an edge parameter is close to one or infinity, * then some other edge parameter of the same Tetrahedron * will be close to zero. */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (i = 0; i < 3; i++) if (tet->shape[filled]->cwl[ultimate][i].log.real < DEGENERACY_EPSILON) return TRUE; return FALSE; } static Boolean solution_is_flat( Triangulation *manifold) { Tetrahedron *tet; int i; Real the_angle; /* * If any edge parameter has angle more than FLAT_EPSILON away * from 0.0 or PI, return FALSE. Otherwise, return TRUE. */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (i = 0; i < 3; i++) { the_angle = tet->shape[filled]->cwl[ultimate][i].log.imag; if (fabs(the_angle) > FLAT_EPSILON && fabs(the_angle - PI) > FLAT_EPSILON) return FALSE; } return TRUE; } static Boolean solution_is_geometric( Triangulation *manifold) { Tetrahedron *tet; /* * If any edge parameter has argument less than minus FLAT_EPSILON * or greater than PI + FLAT_EPSILON, return FALSE. * Otherwise, return TRUE. * * This allows a solution with some flat tetrahedra to count as geometric. * However, if all the tetrahedra were flat, the SolutionType would have * been previously identified as flat_solution, and we wouldn't have * gotten to this function. */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) if (tetrahedron_is_geometric(tet) == FALSE) return FALSE; return TRUE; } Boolean tetrahedron_is_geometric( Tetrahedron *tet) { int i; Real the_angle; /* * See comments in solution_is_geometric() above. */ for (i = 0; i < 3; i++) { the_angle = tet->shape[filled]->cwl[ultimate][i].log.imag; if (the_angle < - FLAT_EPSILON || the_angle > PI + FLAT_EPSILON) return FALSE; } return TRUE; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/interface.c000644 000765 000024 00000036456 12377774107 021125 0ustar00babstaff000000 000000 /* * interface.c * * This file contains the following functions, which the * user interface uses to read the fields in the Triangulation * data structure. * * char *get_triangulation_name(Triangulation *manifold); * char set_triangulation_name(Triangulation *manifold, char *new_name); * SolutionType get_complete_solution_type(Triangulation *manifold); * SolutionType get_filled_solution_type(Triangulation *manifold); * int get_num_tetrahedra(Triangulation *manifold); * Orientability get_orientability(Triangulation *manifold); * int get_num_cusps(Triangulation *manifold); * int get_num_or_cusps(Triangulation *manifold); * int get_num_nonor_cusps(Triangulation *manifold); * int get_max_singularity(Triangulation *manifold); * int get_num_generators(Triangulation *manifold); * void get_cusp_info( Triangulation *manifold, * int cusp_index, * CuspTopology *topology, * Boolean *is_complete, * double *m, * double *l, * Complex *initial_shape, * Complex *current_shape, * int *initial_shape_precision, * int *current_shape_precision, * Complex *initial_modulus, * Complex *current_modulus); * FuncResult set_cusp_info( Triangulation *manifold, * int cusp_index, * Boolean cusp_is_complete, * double m, * double l); * void get_holonomy( Triangulation *manifold, * int cusp_index, * Complex *meridional_holonomy, * Complex *longitudinal_holonomy, * int *meridional_precision, * int *longitudinal_precision); * void get_tet_shape( Triangulation *manifold, * int which_tet, * FillingStatus which_solution, * Boolean fixed_alignment, * double *shape_rect_real, * double *shape_rect_imag, * double *shape_log_real, * double *shape_log_imag, * int *precision_rect_real, * int *precision_rect_imag, * int *precision_log_real, * int *precision_log_imag, * Boolean *is_geometric); * int get_num_edge_classes( * Triangulation *manifold, * int edge_class_order, * Boolean greater_than_or_equal); * * The Triangulation data structure itself, as well as its * component data structures, remain private to the kernel. * * These functions are documented more thoroughly in SnapPea.h. */ #include "kernel.h" #include "kernel_namespace.h" static int longest_side(Tetrahedron *tet); char *get_triangulation_name( Triangulation *manifold) { return manifold->name; } void set_triangulation_name( Triangulation *manifold, const char *new_name) { /* * Free the old name, if there is one. */ if (manifold->name != NULL) my_free(manifold->name); /* * Allocate space for the new name . . . */ manifold->name = NEW_ARRAY(strlen(new_name) + 1, char); /* * . . . and copy it in. */ strcpy(manifold->name, new_name); } SolutionType get_complete_solution_type( Triangulation *manifold) { return manifold->solution_type[complete]; } SolutionType get_filled_solution_type( Triangulation *manifold) { return manifold->solution_type[filled]; } int get_num_tetrahedra( Triangulation *manifold) { return manifold->num_tetrahedra; } Orientability get_orientability( Triangulation *manifold) { return manifold->orientability; } int get_num_cusps( Triangulation *manifold) { return manifold->num_cusps; } int get_num_or_cusps( Triangulation *manifold) { return manifold->num_or_cusps; } int get_num_nonor_cusps( Triangulation *manifold) { return manifold->num_nonor_cusps; } int get_max_singularity( Triangulation *manifold) { Cusp *cusp; int m, l, singularity, max_singularity; max_singularity = 1; for ( cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) { if (cusp->is_complete == FALSE) { m = (int) cusp->m; l = (int) cusp->l; if ( cusp->m == (Real) m && cusp->l == (Real) l) { singularity = gcd(m, l); if (max_singularity < singularity) max_singularity = singularity; } } } return max_singularity; } int get_num_generators( Triangulation *manifold) { return manifold->num_generators; } void get_cusp_info( Triangulation *manifold, int cusp_index, CuspTopology *topology, Boolean *is_complete, Real *m, Real *l, Complex *initial_shape, Complex *current_shape, int *initial_shape_precision, int *current_shape_precision, Complex *initial_modulus, Complex *current_modulus) { Cusp *cusp; cusp = find_cusp(manifold, cusp_index); /* * Write information corresponding to nonNULL pointers. */ if (topology != NULL) *topology = cusp->topology; if (is_complete != NULL) *is_complete = cusp->is_complete; if (m != NULL) *m = cusp->m; if (l != NULL) *l = cusp->l; if (initial_shape != NULL) *initial_shape = cusp->cusp_shape[initial]; /* = Zero if initial hyperbolic structure is degenerate */ if (current_shape != NULL) *current_shape = cusp->cusp_shape[current]; /* = Zero if cusp is filled or hyperbolic structure is degenerate */ if (initial_shape_precision != NULL) *initial_shape_precision = cusp->shape_precision[initial]; /* = 0 if initial hyperbolic structure is degenerate */ if (current_shape_precision != NULL) *current_shape_precision = cusp->shape_precision[current]; /* = 0 if cusp is filled or hyperbolic structure is degenerate */ if (initial_modulus != NULL) { if (cusp->shape_precision[initial] > 0) *initial_modulus = cusp_modulus(cusp->cusp_shape[initial]); else *initial_modulus = Zero; } if (current_modulus != NULL) { if (cusp->shape_precision[current] > 0) *current_modulus = cusp_modulus(cusp->cusp_shape[current]); else *current_modulus = Zero; } } FuncResult set_cusp_info( Triangulation *manifold, int cusp_index, Boolean cusp_is_complete, Real m, Real l) { Cusp *cusp; cusp = find_cusp(manifold, cusp_index); /* MC 2008-09-30 */ if ( cusp == NULL) return func_failed; /* * Write the given Dehn coefficients into the cusp. */ if (cusp_is_complete) { cusp->is_complete = TRUE; cusp->m = 0.0; cusp->l = 0.0; } else { /* * Check the input. * * The comment at the top of holonomy.c explains why only * (m,0) Dehn fillings are possible on nonorientable cusps. */ if (m == 0.0 && l == 0.0) { uAcknowledge("Can't do (0,0) Dehn filling."); return func_bad_input; } if (cusp->topology == Klein_cusp && l != 0.0) { uAcknowledge("Only (p,0) Dehn fillings are possible on a nonorientable cusp."); return func_bad_input; } /* * Copy the input into the cusp. */ cusp->is_complete = FALSE; cusp->m = m; cusp->l = l; } return func_OK; } void get_holonomy( Triangulation *manifold, int cusp_index, Complex *meridional_holonomy, Complex *longitudinal_holonomy, int *meridional_precision, int *longitudinal_precision) { Cusp *cusp; cusp = find_cusp(manifold, cusp_index); if (meridional_holonomy != NULL) *meridional_holonomy = cusp->holonomy[ultimate][M]; if (longitudinal_holonomy != NULL) { *longitudinal_holonomy = cusp->holonomy[ultimate][L]; /* * Longitudes on Klein bottle cusps are stored as their * double covers (cf. peripheral_curves.c), so we divide * by two to compensate. (Recall that this isn't actually * the holonomy, but the log of the holonomy, i.e. the * complex length.) * * As explained at the top of holonomy.c, the holonomy * in this case must be real, so we clear any roundoff * error in the imaginary part. */ if (cusp->topology == Klein_cusp) { longitudinal_holonomy->real /= 2.0; longitudinal_holonomy->imag = 0.0; } } if (meridional_precision != NULL) *meridional_precision = complex_decimal_places_of_accuracy( cusp->holonomy[ ultimate ][M], cusp->holonomy[penultimate][M]); if (longitudinal_precision != NULL) *longitudinal_precision = complex_decimal_places_of_accuracy( cusp->holonomy[ ultimate ][L], cusp->holonomy[penultimate][L]); } void get_tet_shape( Triangulation *manifold, int which_tet, FillingStatus which_solution, Boolean fixed_alignment, Real *shape_rect_real, Real *shape_rect_imag, Real *shape_log_real, Real *shape_log_imag, int *precision_rect_real, int *precision_rect_imag, int *precision_log_real, int *precision_log_imag, Boolean *is_geometric) { int count, the_coordinate_system; Tetrahedron *tet; ComplexWithLog *ultimate_shape, *penultimate_shape; /* * If no solution is present, return all zeros. */ if (manifold->solution_type[which_solution] == not_attempted) { *shape_rect_real = 0.0; *shape_rect_imag = 0.0; *shape_log_real = 0.0; *shape_log_imag = 0.0; *precision_rect_real = 0; *precision_rect_imag = 0; *precision_log_real = 0; *precision_log_imag = 0; *is_geometric = FALSE; return; } /* * Check that which_tet is within bounds. */ if (which_tet < 0 || which_tet >= manifold->num_tetrahedra) uFatalError("get_tet_shape", "interface"); /* * Find the Tetrahedron in position which_tet. */ for (tet = manifold->tet_list_begin.next, count = 0; tet != &manifold->tet_list_end && count != which_tet; tet = tet->next, count++) ; /* * If we went all the way through the list of Tetrahedra * without finding position which_tet, then something * is very wrong. */ if (tet == &manifold->tet_list_end) uFatalError("get_tet_shape", "interface"); /* * If fixed_alignment is TRUE, use a fixed coordinate system. * Otherwise choose the_coordinate_system so that the longest side * of the triangle is the initial side of the angle. */ if (fixed_alignment == TRUE) the_coordinate_system = 0; else the_coordinate_system = (longest_side(tet) + 1) % 3; /* * Note the addresses of the ultimate and penultimate shapes. */ ultimate_shape = &tet->shape[which_solution]->cwl[ ultimate ][the_coordinate_system]; penultimate_shape = &tet->shape[which_solution]->cwl[penultimate][the_coordinate_system]; /* * Report the ultimate shapes. */ *shape_rect_real = ultimate_shape->rect.real; *shape_rect_imag = ultimate_shape->rect.imag; *shape_log_real = ultimate_shape->log.real; *shape_log_imag = ultimate_shape->log.imag; /* * Estimate the precision. */ *precision_rect_real = decimal_places_of_accuracy(ultimate_shape->rect.real, penultimate_shape->rect.real); *precision_rect_imag = decimal_places_of_accuracy(ultimate_shape->rect.imag, penultimate_shape->rect.imag); *precision_log_real = decimal_places_of_accuracy(ultimate_shape->log.real, penultimate_shape->log.real); *precision_log_imag = decimal_places_of_accuracy(ultimate_shape->log.imag, penultimate_shape->log.imag); /* * Check whether the tetrahedron is geometric. */ *is_geometric = tetrahedron_is_geometric(tet); } static int longest_side( Tetrahedron *tet) { int i, desired_index = 0; Real sine[3], max_sine; /* * longest_side() returns the index (0, 1 or 2) of the edge opposite * the longest side of tet's triangular vertex cross section. * * We'll use the Law of Sines, which says that the lengths of a triangle's * sides are proportional to the sines of the opposite angles. * * We take the absolute value of each sine, just in case the * Tetrahedron is negatively oriented. */ for (i = 0; i < 3; i++) sine[i] = fabs(tet->shape[filled]->cwl[ultimate][i].rect.imag) / complex_modulus(tet->shape[filled]->cwl[ultimate][i].rect); max_sine = -1.0; for (i = 0; i < 3; i++) if (sine[i] > max_sine) { max_sine = sine[i]; desired_index = i; } return desired_index; } int get_num_edge_classes( Triangulation *manifold, int edge_class_order, Boolean greater_than_or_equal) { int count; EdgeClass *edge; count = 0; for (edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) if ( greater_than_or_equal ? edge->order >= edge_class_order : edge->order == edge_class_order) count++; return count; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/intersection_numbers.c000644 000765 000024 00000024241 12377774107 023413 0ustar00babstaff000000 000000 /* * intersection_numbers.c * * This file provides the kernel function * * void compute_intersection_numbers(Triangulation *manifold); * * which computes the intersection numbers of the curves stored * in the scratch_curve[][][][][] fields of the Tetrahedra, and * writes the results to the intersection_number[][] fields of * the Cusps. That is, * * intersection_number[M][M] will be the intersection number of * scratch_curve[0][M] with scratch_curve[1][M], * * intersection_number[M][L] will be the intersection number of * scratch_curve[0][M] with scratch_curve[1][L], * * intersection_number[L][M] will be the intersection number of * scratch_curve[0][L] with scratch_curve[1][M], * * intersection_number[L][L] will be the intersection number of * scratch_curve[0][L] with scratch_curve[1][L]. * * Each intersection number is the algebraic sum of the crossing * numbers. As viewed from infinity (looking toward the fat * part of the manifold), each crossing of the form * * scratch_curve[1] * ^ * | contributes +1, * ----|---> scratch_curve[0] * | * | * * while each crossing of the form * * * scratch_curve[0] * ^ * | contributes -1, * ----|---> scratch_curve[1] * | * | * * This file also provides the utility * * void copy_curves_to_scratch( Triangulation *manifold, * int which_set, * Boolean double_copy_on_tori); * * which copies the current peripheral curves to the scratch_curves[which_set] * fields of the manifold's Tetrahedra. If double_copy_on_tori is TRUE, * it copies peripheral curves on orientable cusps to both sheets of * the Cusps' orientation double covers. * * * Overview of Intersection Number Algorithm. * * Consider the triangulation of the boundary components by the * triangles at the (truncated) ideal vertices. As explained * in peripheral_curves.c, we work in the orientation double cover, * so in fact each ideal vertex contributes two triangles, one * left_handed and the other right_handed. Relative to the * orientation on the cusp (and even nonorientable cusps are * effectively oriented, since we work in the orientation double * cover) we imagine each scratch_curve[0] entering a given triangle * on the right side of a given edge, and each scratch_curve[1] * entering on the left: * * /\ * / \ * / \ * / \ * / \ * / \ * / \ * / \ * / \ * / \ * / 1 \ / 0 \ * /__________\/__________\ * \ /\ / * \ 0 / \ 1 / * \ / * \ / * \ / * \ / * \ / * \ / * \ / * \ / * \ / * \/ * * Of necessity, the curves must cross on the edge (if both are * nonzero). There may be additional crossings in the interior of * the triangle, depending on where the various curves are entering * and exiting. To avoid counting the intersections on the edges * twice (once for each of the two incident triangles) we make the * convention to count edge crossings only where scratch_curve[0] is * entering (not exiting) the triangle. */ #include "kernel.h" #include "kernel_namespace.h" void compute_intersection_numbers( Triangulation *manifold) { Cusp *cusp; Tetrahedron *tet; int f, g, h, i, j, face_on_the_left, face_on_the_right; /* * Initialize all the intersection numbers to zero. */ for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) for (i = 0; i < 2; i++) /* i = M, L */ for (j = 0; j < 2; j++) /* j = M, L */ cusp->intersection_number[i][j] = 0; /* * Count the intersections on the edges. */ /* which Tetrahedron */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) /* which ideal vertex */ for (i = 0; i < 4; i++) /* which side of the vertex */ for (j = 0; j < 4; j++) { if (i == j) continue; /* which sheet (right_handed or left_handed) */ for (f = 0; f < 2; f++) /* which scratch_curve[0] (meridian or longitude) */ for (g = 0; g < 2; g++) /* which scratch_curve[1] (meridian or longitude) */ for (h = 0; h < 2; h++) /* * Recall the convention (described at the top * of this file) that edge crossings are counted * only where scratch_curve[0] is entering -- * not exiting -- the triangle. */ if (tet->scratch_curve[0][g][f][i][j] > 0) tet->cusp[i]->intersection_number[g][h] += tet->scratch_curve[0][g][f][i][j] * tet->scratch_curve[1][h][f][i][j]; } /* * Count the intersections in the interiors of triangles. */ /* which Tetrahedron */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) /* which ideal vertex */ for (i = 0; i < 4; i++) /* which side of the vertex */ for (j = 0; j < 4; j++) { if (i == j) continue; /* * Name the two remaining faces of the Tetrahedron * according to the right_handed orientation of * the Tetrahedron. */ face_on_the_left = remaining_face[i][j]; face_on_the_right = remaining_face[j][i]; /* which scratch_curve[0] (meridian or longitude) */ for (g = 0; g < 2; g++) /* which scratch_curve[1] (meridian or longitude) */ for (h = 0; h < 2; h++) { /* * We'll count only those intersections on the * strand of scratch_curve[0] running from the * current side of the triangle (side j) towards * the right. The other possibilities will be * handled by other values of j. * * When we see the Tetrahedron as left_handed * relative to the Orientation of the cusp, the * face on the right is face_on_the_left. * Got that? */ tet->cusp[i]->intersection_number[g][h] += FLOW(tet->scratch_curve[0][g][right_handed][i][j], tet->scratch_curve[0][g][right_handed][i][face_on_the_right]) * tet->scratch_curve[1][h][right_handed][i][face_on_the_right]; tet->cusp[i]->intersection_number[g][h] += FLOW(tet->scratch_curve[0][g][left_handed][i][j], tet->scratch_curve[0][g][left_handed][i][face_on_the_left]) * tet->scratch_curve[1][h][left_handed][i][face_on_the_left]; } } } void copy_curves_to_scratch( Triangulation *manifold, int which_set, Boolean Real_copy_on_tori) { Tetrahedron *tet; int i, j, k, l; /* * When computing intersection numbers on orientable cusps * (especially in nonorientable manifolds) there is a danger that * scratch_curves[0] will lie on one sheet of the Cusp's orientation * double cover while scratch_curves[1] lies on the other sheet. * To avoid this danger, copy_curves_to_scratch() offers the * option to copy the peripheral curves on orientable cusps to * both sheets of the double cover. You should use this option * for one set of scratch_curves (e.g. scratch_curves[0]) but not * the other (scratch_curves[1]) to guarantee correct intersection * numbers. */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (i = 0; i < 2; i++) for (k = 0; k < 4; k++) for (l = 0; l < 4; l++) if (tet->cusp[k]->topology == torus_cusp && Real_copy_on_tori == TRUE) tet->scratch_curve[which_set][i][right_handed][k][l] = tet->scratch_curve[which_set][i][ left_handed][k][l] = tet->curve[i][right_handed][k][l] + tet->curve[i][ left_handed][k][l]; else /* * tet->cusp[k]->topology == Klein_cusp * || double_copy_on_tori == FALSE */ for (j = 0; j < 2; j++) tet->scratch_curve[which_set][i][j][k][l] = tet->curve[i][j][k][l]; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/isometry.h000644 000765 000024 00000015251 12377774107 021033 0ustar00babstaff000000 000000 /* * isometry.h * * This file provides the definition of an IsometryList. It is private * to the kernel. * * An isometry is a map which takes the Tetrahedra of one Triangulation * to the Tetrahedra of another, preserving the gluings. Strictly speaking * this is a combinatorial equivalence of the two Triangulations, but * the Triangulations are typically the canonical ones for their respective * manifolds, so the notions of combinatorial equivalence and isometry * coincide. * * The two Triangulations need not be distinct -- if they're the same * then an "isometry" is what one normally calls a symmetry. * * An isometry may be represented in two ways: internally within the * Triangulation data structure, and externally using the Isometry data * structure. * * (1) Internal representation. The Triangulation data structure may * represent at most one isometry at a time. Each Tetrahedron contains * the fields * Tetrahedron *image; * Permutation map; * * The image field contains a pointer to the image of the given * Tetrahedron under the isometry. The map field says how the * vertices of the given Tetrahedron are taken to the vertices * of its image. E.g. if the Permutation is 2013 (meaning 3210 -> 2013) * then vertex 0 of the given Tetrahedron maps to vertex 3 of the image * Tetrahedron, vertex 1 maps to vertex 1 of the image, vertex 2 maps * to vertex 0, and vertex 3 maps to vertex 2. * * (2) External representation. The Isometry data structure is similar * to the internal representation described in the preceding paragraph, * only it refers to Tetrahedra by indices rather than pointers. * Each Tetrahedron in each manifold is numbered by setting its index * field equal to the Tetrahedron's position in its Triangulation's * doubly-linked list (the indices run from 0 through n-1). * * The images and maps are stored in the tet_image and tet_map arrays * in the Isometry data structure. The elements of each array are * implicitly indexed by the indices of the Tetrahedra in the domain * manifold. For example, if * * my_isometry->tet_image = {1, 0, 2} * and * my_isometry->tet_map = {3102, 3201, 1023}, * * then Tetrahedron #0 of the domain Triangulation will map to * Tetrahedron #1 of the image Triangulation via the Permutation * 3102; Tetrahedron #1 will map to Tetrahedron #0 via 3201; * and Tetrahedron #2 will map to Tetrahedron #2 via 1023. * * In addition, the Isometry data structure records the action * of the Isometry on the Cusps, as explained in the Isometry * definition below. * * The IsometryList data structure contains an array of pointers to * Isometries, an integer saying how many there are, and an integer * say how many Tetrahedra each Triangulation has. The file SnapPea.h * contains the "opaque typedef" * * typedef struct IsometryList IsometryList; * * which lets the UI declare and pass pointers to IsometryLists without * actually knowing what they are. This file provides the kernel with * the actual definition. * * The Isometry data structure also contains a "next" field, which the * function compute_cusped_isometries() uses internally while assembling * its IsometryList. Other functions ignore the "next" field. */ #ifndef _isometry_ #define _isometry_ #include "kernel.h" #include "kernel_namespace.h" typedef struct Isometry Isometry; struct Isometry { /* * How many Tetrahedra and Cusps are there? */ int num_tetrahedra, num_cusps; /* * The Isometry sends Tetrahedron n in the domain * manifold to Tetrahedron tet_image[n] in the image manifold. */ int *tet_image; /* * The Isometry sends vertex v of Tetrahedron n in the * domain manifold to vertex EVALUATE(tet_map[n], v) of * Tetrahedron tet_image[n] in the image manifold. */ Permutation *tet_map; /* * The Isometry sends Cusp k of the domain manifold * to Cusp cusp_image[k] in the image manifold. */ int *cusp_image; /* * The matrix cusp_map[k][][] takes the peripheral curves * of Cusp k in the domain manifold to the peripheral curves * of Cusp cusp_image[k] in the image manifold. That is, * the image of a meridian of Cusp k in the domain is * cusp_matrix[k][M][M] meridians plus cusp_matrix[k][L][M] * longitudes in the image, and similarly for the image of * a longitude. * * Note that the cusp_map matrix is defined even for * nonorientable Cusps, since the peripheral curves are stored * in the Cusp's orientation double cover. For nonorientable * cusps, cusp_matrix[k][L][M] will be a diagonal matrix. * The entry cusp_matrix[k][L][L] tells whether the direction * of the cusp is reversed. Det(cusp_matrix[k]) tells whether * the Isometry acts in an orientation-preserving or orientation- * reversing way on the Cusp's orientation double cover (Question: * what is the significance of this information, if any?). * * This scheme applies only to the real cusps -- finite vertices * (whose cusp indices are negative) are ignored. */ MatrixInt22 *cusp_map; /* * Does this Isometry from one cusped manifold to another extend * to the closed manifolds obtained by meridional Dehn fillings? * If the cusp manifolds are link complements (in any manifolds, * not necessarily 3-spheres) this is equivalent to asking whether * the Isometry extends to a link homeomorphism. */ Boolean extends_to_link; /* * This "next" field is used internally in isometry_cusped.c * while assembling the IsometryList. (The Isometries are * temporarily stored on a linked list, then eventually * transferred to an array of pointers for external use.) */ Isometry *next; }; struct IsometryList { /* * How many Isometries are on the list? */ int num_isometries; /* * isometry[n] is a pointer to the n-th Isometry * on the list. (The "isometry" field itself * contains a pointer to an array. Each element of * the array is a pointer to an Isometry.) * * If there are no isometries (num_isometries == 0) * then the isometry field is set to NULL. That is, * we don't try to allocate an array of zero pointers. */ Isometry **isometry; }; #include "end_namespace.h" #endif regina-4.96/engine/snappea/kernel/kernel.h000644 000765 000024 00000001423 12377774107 020434 0ustar00babstaff000000 000000 /* * kernel.h * * This file #includes all header files needed for the kernel. * It should be #included in all kernel .c files, but nowhere else. */ #ifndef _kernel_ #define _kernel_ #include "SnapPea.h" /* We build the snappea kernel as C++, so link it as C++. - B.B., 27/03/2014. #ifdef __cplusplus extern "C" { #endif */ #include #include #include #include #include "kernel_typedefs.h" #include "triangulation.h" #include "positioned_tet.h" #include "isometry.h" #include "symmetry_group.h" #include "dual_one_skeleton_curve.h" #include "terse_triangulation.h" #include "kernel_prototypes.h" #include "tables.h" /* We build the snappea kernel as C++, so link it as C++. - B.B., 27/03/2014. #ifdef __cplusplus } #endif */ #endif regina-4.96/engine/snappea/kernel/kernel_namespace.h000644 000765 000024 00000000247 12377774107 022453 0ustar00babstaff000000 000000 /* * If you wish to build the snappea kernel within a C++ namespace * you can declare the namespace block in this file. */ namespace regina { namespace snappea { regina-4.96/engine/snappea/kernel/kernel_prototypes.h000644 000765 000024 00000137271 12377774107 022757 0ustar00babstaff000000 000000 /* * kernel_prototypes.h * * This file contains prototypes for functions which are externally * available within the kernel, but not available to the user-interface. */ #ifndef _kernel_prototypes_ #define _kernel_prototypes_ #include "SnapPea.h" #include "positioned_tet.h" #include "kernel_namespace.h" /************************************************************************/ /* */ /* chern_simons.c */ /* */ /************************************************************************/ extern void compute_CS_value_from_fudge(Triangulation *manifold); extern void compute_CS_fudge_from_value(Triangulation *manifold); /* * Compute the Chern-Simons value in terms of the fudge factor, and * vice-versa. Please see chern_simons.c for details. */ /************************************************************************/ /* */ /* choose_generators.c */ /* */ /************************************************************************/ extern void choose_generators( Triangulation *manifold, Boolean compute_corners, Boolean centroid_at_origin); /* * Chooses a set of generators for the fundamental group of the * Triangulation *manifold. Various functions which use generators all * call choose_generators(), so they are sure to be using the same * generator set, and their results are directly comparable. * If compute_corners is TRUE, choose_generators() computes the location * on the sphere at infinity of each ideal vertex of each Tetrahedron, * using the hyperbolic structure of the Dehn filled manifold. * If centroid_at_origin is TRUE, the initial tetrahedron is positioned * with its centroid at the origin; otherwise the initial tetrahedron * is positioned with its vertices at {0, 1, infinity, z}. * If compute_corners is FALSE, centroid_at_origin is ignored. */ void compute_fourth_corner( Complex corner[4], VertexIndex missing_corner, Orientation orientation, ComplexWithLog cwl[3]); /* * Given the location on the sphere at infinity of three of a Tetrahedron's * ideal vertices, compute the location of the fourth. */ /************************************************************************/ /* */ /* close_cusps.c */ /* */ /************************************************************************/ extern void close_cusps(Triangulation *manifold, Boolean fill_cusp[]); /* * Permanently closes the cusps of *manifold for which fill_cusp[cusp->index] * is TRUE. Assumes *manifold is triangulated as in subdivide(). */ /************************************************************************/ /* */ /* complex.c */ /* */ /************************************************************************/ extern Complex Zero, One, Two, Four, MinusOne, I, TwoPiI, Infinity; /************************************************************************/ /* */ /* core_geodesics.c */ /* */ /************************************************************************/ extern void compute_core_geodesic( Cusp *cusp, int *singularity_index, Complex length[2]); /* * This function is similar to the function core_geodesic() defined in * SnapPea.h, only it accepts a Cusp pointer as input and returns * the complex length relative to the ultimate and penultimate * hyperbolic structures (rather than reporting a precision). */ /************************************************************************/ /* */ /* cusps.c */ /* */ /************************************************************************/ extern void create_cusps(Triangulation *manifold); /* * Creates Cusp data structures for a Triangulation with valid * neighbor and gluing fields (and perhaps nothing else). */ extern void error_check_for_create_cusps(Triangulation *manifold); /* * Checks that no Cusps are present, and that all tet->cusp[] * fields are NULL. */ extern void create_one_cusp(Triangulation *manifold, Tetrahedron *tet, Boolean is_finite, VertexIndex v, int cusp_index); /* * Creates a single Cusp, incident to the given Tetrahedron at * the given ideal vertex. Assumes ideal vertices which haven't * been assigned to Cusps have tetrahedron->cusp[vertex] == NULL. */ extern void create_fake_cusps(Triangulation *manifold); /* * Creates Cusp data structures for the "fake cusps" corresponding to * finite vertices. */ extern void count_cusps(Triangulation *manifold); /* * counts the Cusps of each CuspTopology, and sets manifold->num_cusps, * manifold->num_or_cusps and manifold->num_nonor_cusps. */ extern Boolean mark_fake_cusps(Triangulation *manifold); /* * Distinguishes real cusps from fake cusps ( = finite vertices) by * computing the Euler characteristic. Sets is_finite to TRUE for * fake cusps, and renumbers all cusps so that real cusps have * consecutive nonnegative indices beginning at 0 and fake cusps * have consecutive negative indices beginning at -1. */ /************************************************************************/ /* */ /* cusp_cross_sections.c */ /* */ /************************************************************************/ extern void allocate_cross_sections(Triangulation *manifold); /* * Allocates a VertexCrossSections structure for each tet->cross_section * in manifold. */ extern void free_cross_sections(Triangulation *manifold); /* * Frees the VertexCrossSections structure and resets the * tet->cross_section pointer to NULL for each tet in manifold. */ extern void compute_cross_sections(Triangulation *manifold); /* * Sets the (already allocated) VertexCrossSections to correspond to * cusp cross sections bounding equal volumes. In general these cross * sections will NOT represent maximal disjoint horoball neighborhoods * of the cusps. */ extern void compute_tilts(Triangulation *manifold); /* * Applies the Tilt Theorem to compute the tilts from the * VertexCrossSections. Assumes the TetShapes are correct. */ extern void compute_three_edge_lengths( Tetrahedron *tet, VertexIndex v, FaceIndex f, Real known_length); /* * Sets tet->cross_section->edge_length[v][f] to known_length, computes * the remaining two edge_lengths at vertex v in terms of it, and sets * the has_been_set flag to TRUE. */ extern void compute_tilts_for_one_tet(Tetrahedron *tet); /* * Applies the Tilt Theorem to compute the tilts from the * VertexCrossSections. Assumes the TetShapes are correct. */ /************************************************************************/ /* */ /* cusp_neighborhoods.c */ /* */ /************************************************************************/ extern void cn_find_third_corner( Tetrahedron *tet, Orientation h, VertexIndex v, FaceIndex f0, FaceIndex f1, FaceIndex f2); /* * Given the locations of corners f0 and f1 on the given triangle, * compute and record the location of corner f2. * This function is in spirit local to cusp_neighborhoods.c, but we * want to make it available to the 2-3 and 3-2 simplifications * in simplify_triangulation.c. */ /************************************************************************/ /* */ /* cusp_shapes.c */ /* */ /************************************************************************/ extern void compute_cusp_shapes(Triangulation *manifold, FillingStatus which_structure); /* * Computes the shape of each unfilled cusp and stores the result in * cusp->cusp_shape[which_structure]. (which_structure = initial or * current) Stores the number of decimal places of accuracy in * cusp->shape_precision[which_structure]. */ /************************************************************************/ /* */ /* Dehn_coefficients.c */ /* */ /************************************************************************/ extern Boolean all_Dehn_coefficients_are_integers(Triangulation *manifold); /* * Returns FALSE if some cusp has noninteger Dehn filling coefficients. * Returns TRUE if each cusp is either unfilled, or has integer * Dehn filling coefficients. */ extern Boolean Dehn_coefficients_are_integers(Cusp *cusp); /* * Returns FALSE if the Dehn filling coefficients of *cusp are * nonintegers. * Returns TRUE if *cusp is unfilled, or has integer Dehn filling * coefficients. */ extern Boolean all_Dehn_coefficients_are_relatively_prime_integers( Triangulation *manifold); extern Boolean Dehn_coefficients_are_relatively_prime_integers(Cusp *cusp); /* * Same as above, but integer coefficients must be relatively prime. */ extern Boolean all_cusps_are_complete(Triangulation *manifold); extern Boolean all_cusps_are_filled(Triangulation *manifold); /* * Returns TRUE if all cusps are complete (resp. filled), FALSE otherwise. */ /************************************************************************/ /* */ /* direct_product.c */ /* */ /************************************************************************/ extern Boolean is_group_direct_product(SymmetryGroup *the_group); /* * Checks whether the_group is a nonabelian, nontrivial direct product, * and sets it is_direct_product and factor[] fields accordingly. */ /************************************************************************/ /* */ /* edge_classes.c */ /* */ /************************************************************************/ extern void create_edge_classes(Triangulation *manifold); /* * Adds EdgeClasses to a partially constructed manifold which does not * yet have them. */ extern void replace_edge_classes(Triangulation *manifold); /* * Removes all EdgeClasses from a manifold and addes fresh ones. */ extern void orient_edge_classes(Triangulation *manifold); /* * Orients a neighborhood of each EdgeClass, and fills in the fields * tet->edge_class[] to described how the EdgeClass views each * incident Tetrahedron. */ /************************************************************************/ /* */ /* elements_generate_group.c */ /* */ /************************************************************************/ extern Boolean elements_generate_group(SymmetryGroup *the_group, int num_possible_generators, int possible_generators[]); /* * The array possible_generators[] contains num_possible_generators * elements of the_group. Do these elements generate the_group? */ /************************************************************************/ /* */ /* find_cusp.c */ /* */ /************************************************************************/ extern Cusp *find_cusp(Triangulation *manifold, int cusp_index); /* * Converts a cusp_index to a Cusp pointer. */ /************************************************************************/ /* */ /* finite_vertices.c */ /* */ /************************************************************************/ extern void remove_finite_vertices(Triangulation *manifold); /* * Removes finite vertices from the manifold. */ /************************************************************************/ /* */ /* gcd.c */ /* */ /************************************************************************/ extern long int gcd(long int a, long int b); /* * Returns the greatest common divisor of two nonnegative long integers, * at least one of which is nonzero. */ extern long int euclidean_algorithm(long int m, long int n, long int *a, long int *b); /* * Returns the greatest common divisor of two long integers m and n, * and also finds long integers a and b such that am + bn = gcd(m,n). * The integers m and n may be negative, but may not both be zero. */ extern long int Zq_inverse(long int p, long int q); /* * Returns the inverse of p in the ring Z/q. Assumes p and q are * relatively prime integers satisfying 0 < p < q. */ /************************************************************************/ /* */ /* gluing_equations.c */ /* */ /************************************************************************/ extern void compute_gluing_equations(Triangulation *manifold); /* * compute_gluing_equations() computes the complex gluing equations * if Triangulation *manifold is orientable, and the real gluing * equations if it's nonorientable. It assumes that space for the * appropriate set of equations has already been assigned to the cusps * and edges. */ /************************************************************************/ /* */ /* holonomy.c */ /* */ /************************************************************************/ extern void compute_holonomies(Triangulation *manifold); /* * Computes the log of the holonomy of each cusp based on the current * shapes of the tetrahedra, and stores the results into the * holonomy[ultimate][] field of the Cusp data structure. The previous * contents of that field are transferred to holonomy[penultimate][]. * * compute_holonomies() is called whenever a hyperbolic structure is * computed. Therefore if you have a manifold with a hyperbolic structure * you may assume correct values of the holonomy are already in place. */ extern void compute_the_holonomies( Triangulation *manifold, Ultimateness which_iteration); /* * Computes the holonomies for either the ultimate or penultimate * solution, according to the value of which_iteration. */ extern void compute_edge_angle_sums(Triangulation *manifold); /* * For each EdgeClass, computes the sum of the logs of the complex * edge parameters and records the result in the edge_angle_sum field. * compute_edge_angle_sums() is used in finding the hyperbolic structure; * once the hyperbolic structure is found, each edge_angle_sum will of * course be 2 pi i. */ /************************************************************************/ /* */ /* hyperbolic_structure.c */ /* */ /************************************************************************/ extern void remove_hyperbolic_structures(Triangulation *manifold); /* * Frees the TetShapes (if any) pointed to by each tet->shape[] and sets * manifold->solution_type[complete] and manifold->solution_type[filled] * to not_attempted. */ extern void initialize_tet_shapes(Triangulation *manifold); /* * Sets all Tetrahedra to be regular ideal tetrahedra. Allocates the * TetShapes if necessary. Clears the shape_histories if necessary. */ extern void polish_hyperbolic_structures(Triangulation *manifold); /* * Attempts to increase the accuracy of both the complete and the Dehn * filled hyperbolic structures already present in *manifold. It's * designed to be called following retriangulation operations which * diminish the accuracy of the TetShapes. */ extern void copy_solution(Triangulation *manifold, FillingStatus source, FillingStatus dest); extern void complete_all_cusps(Triangulation *manifold); /* * These are low-level routines used mainly within hyperbolic_structure.c, * but also to transfer the Chern-Simons invariant in drilling.c. */ /************************************************************************/ /* */ /* identify_solution_type.c */ /* */ /************************************************************************/ extern void identify_solution_type(Triangulation *manifold); /* * Identifies the type of solution contained in the *tet->shape[filled] * structures of the Tetrahedra of Triangulation *manifold, and writes * the result to manifold->solution_type[filled]. Possible values are * given by the SolutionType enum. */ extern Boolean solution_is_degenerate(Triangulation *manifold); /* * Returns TRUE if any TetShape is close to {0, 1, infinity}. * Otherwise returns FALSE. */ extern Boolean tetrahedron_is_geometric(Tetrahedron *tet); /* * Returns TRUE if all tetrahedra are geometric; returns FALSE otherwise. * A tetrahedron is geometric iff all dihedral angles lie in the * range [-FLAT_EPSILON, pi + FLAT_EPSILON]. */ /************************************************************************/ /* */ /* intersection_numbers.c */ /* */ /************************************************************************/ extern void compute_intersection_numbers(Triangulation *manifold); /* * Computes the intersection numbers of the curves stored * in the scratch_curve[][][][][] fields of the Tetrahedra, and * writes the results to the intersection_number[][] fields of * the Cusps. Please see intersection_numbers.c for details. */ extern void copy_curves_to_scratch( Triangulation *manifold, int which_set, Boolean Real_copy_on_tori); /* * Copies the current peripheral curves to the scratch_curves[which_set] * fields of the manifold's Tetrahedra. If double_copy_on_tori is TRUE, * it copies peripheral curves on orientable cusps to both sheets of * the Cusps' orientation double covers. */ /************************************************************************/ /* */ /* isometry_closed.c */ /* */ /************************************************************************/ extern FuncResult compute_closed_isometry( Triangulation *manifold0, Triangulation *manifold1, Boolean *are_isometric); /* * If it determines with absolute rigor that manifold0 and manifold1 are * isometric, sets *are_isometric to TRUE and returns func_OK. * If it determines with absolute rigor that manifold0 and manifold1 are * nonhomeomorphic, sets *are_isometric to FALSE and returns func_OK. * If it fails to decide, returns func_failed. */ /************************************************************************/ /* */ /* isometry_cusped.c */ /* */ /************************************************************************/ extern FuncResult compute_cusped_isometries( Triangulation *manifold0, Triangulation *manifold1, IsometryList **isometry_list, IsometryList **isometry_list_of_links); /* * Finds all isometries from manifold0 to manifold1 (ignoring Dehn * fillings), stores them in an IsometryList data structure, and sets * isometry_list to point to it. If isometry_list_of_links is not NULL, * it copies those Isometries which extend to Isometries of the associated * links (i.e. those which take meridians to plus-or-minus meridians) * onto a separate list, and stores its address in *isometry_list_of_links. * If manifold0 == manifold1, this function is finding all symmetries. */ extern void compute_cusped_isomorphisms( Triangulation *manifold0, Triangulation *manifold1, IsometryList **isometry_list, IsometryList **isometry_list_of_links); /* * Computes a list of combinatorial isomorphisms between two * triangulations. It is identical to compute_cusped_isometries, * except it does not make any changes to the triangulations and in * particular does not attempt to compute canonical triangulations. * Thus it can be used on triangulations of non-hyperbolic manifolds. */ extern Boolean same_triangulation( Triangulation *manifold0, Triangulation *manifold1); /* * Simply reports the existence of a combinatorial isomorphism, * without finding a list. This is also usable with triangulations * of non-hyperbolic manifolds. */ /************************************************************************/ /* */ /* Moebius_transformations.c */ /* */ /************************************************************************/ extern CONST MoebiusTransformation Moebius_identity; extern void Moebius_copy( MoebiusTransformation *dest, MoebiusTransformation *source); extern void Moebius_invert( MoebiusTransformation *mt, MoebiusTransformation *mt_inverse); extern void Moebius_product(MoebiusTransformation *a, MoebiusTransformation *b, MoebiusTransformation *product); /* * These functions do what you would expect. */ /************************************************************************/ /* */ /* my_malloc.c */ /* */ /************************************************************************/ extern void *my_malloc(size_t bytes); /* * Calls malloc() to request a block of memory of size "bytes". * If successful, returns a pointer to the memory. * If unsuccessful, calls uAcknowledge() to notify the user, then exits. */ extern void my_free(void *ptr); /* * Calls free() to deallocate the block of memory pointed to by ptr. */ extern int malloc_calls(void); /* * Returns the number of calls to my_malloc() minus the number of * calls to my_free(), for use in debugging. */ /************************************************************************/ /* */ /* normal_surface_construction.c */ /* */ /************************************************************************/ extern void recognize_embedded_surface( Triangulation *manifold, Boolean *connected, Boolean *orientable, Boolean *two_sided, int *Euler_characteristic); /* * Reports the connectedness, orientability, two-sidedness and Euler * characteristic of the normal surface described in the parallel_edge, * num_squares and num_triangles fields of the manifold's Tetrahedra. * The present implementation assumes the manifold has no filled cusps. */ /************************************************************************/ /* */ /* o31_matrices.c */ /* */ /************************************************************************/ extern O31Matrix O31_identity; extern void o31_copy(O31Matrix dest, O31Matrix source); extern void o31_invert(O31Matrix m, O31Matrix m_inverse); extern FuncResult gl4R_invert(GL4RMatrix m, GL4RMatrix m_inverse); extern void o31_product(O31Matrix a, O31Matrix b, O31Matrix product); extern Boolean o31_equal(O31Matrix a, O31Matrix b, Real epsilon); extern Real o31_deviation(O31Matrix m); extern void o31_GramSchmidt(O31Matrix m); extern void o31_conjugate(O31Matrix m, O31Matrix t, O31Matrix Tmt); extern Real o31_inner_product(O31Vector u, O31Vector v); extern void o31_matrix_times_vector(O31Matrix m, O31Vector v, O31Vector product); extern void o31_constant_times_vector(Real r, O31Vector v, O31Vector product); extern void o31_copy_vector(O31Vector dest, O31Vector source); extern void o31_vector_sum(O31Vector a, O31Vector b, O31Vector sum); extern void o31_vector_diff(O31Vector a, O31Vector b, O31Vector diff); /* * These functions all do what you would expect. * o31_conjugate() replaces m with (t^-1) m t. */ /************************************************************************/ /* */ /* orient.c */ /* */ /************************************************************************/ extern void orient(Triangulation *manifold); /* * Attempts to consistently orient the Tetrahedra of the * Triangulation *manifold. Sets manifold->orientability to * oriented_manifold or nonorientable_manifold, as appropriate. */ extern void extend_orientation( Triangulation *manifold, Tetrahedron *initial_tet); /* * Extends the orientation of the given initial_tet to the entire manifold. */ extern void fix_peripheral_orientations(Triangulation *manifold); /* * Makes sure each {meridian, longitude} pairs obeys the right-hand rule. * Should be called only for orientable manifolds, typically following * a call to orient(). */ /************************************************************************/ /* */ /* peripheral_curves.c */ /* */ /************************************************************************/ extern void peripheral_curves(Triangulation *manifold); /* * Puts a meridian and longitude on each cusp, and records each cusp's * CuspTopology in the field cusp->topology. If the manifold is * oriented, the meridian and longitude adhere to the usual * orientation convention (see peripheral_curves.c for details). */ extern void peripheral_curves_as_needed(Triangulation *manifold); /* * Like peripheral_curves(), but puts a meridian and longitude * only onto cusps which don't already have them. Pre-exisiting * meridians and longitudes are left untouched. */ /************************************************************************/ /* */ /* polyhedral_group.c */ /* */ /************************************************************************/ extern Boolean is_group_polyhedral(SymmetryGroup *the_group); /* * Checks whether the_group is a polyhedral group (i.e. (binary) dihedral, * tetrahedral, octahedral or icosahedral), and fills in the_group's * is_polyhedral, is_full_group, p, q and r fields accordingly. Assumes * the_group's is_dihedral field has already been set (but this * restriction could be eliminated -- see the documentation at the top * of triangle_group.c). */ /************************************************************************/ /* */ /* positioned_tet.c */ /* */ /************************************************************************/ extern void veer_left(PositionedTet *ptet); extern void veer_right(PositionedTet *ptet); /* * Accepts a PositionedTet and replaces it with the neighboring * tetrahedron incident to the left (resp. right) face. The positioning * is as if you rotated the old tetrahedron onto the new one about the * axis defined by the edge of the old tetrahedron lying between * near_face and left_face (resp. right_face). */ extern void veer_backwards(PositionedTet *ptet); /* * Accepts a PositionedTet and replaces it with the neighboring * tetrahedron incident to the near_face. The positioning * is as if you rotated the old tetrahedron onto the new one * about an axis running up the center of the near_face from * the bottom_face to the ideal vertex opposite the bottom_face. */ extern Boolean same_positioned_tet(PositionedTet *ptet0, PositionedTet *ptet1); /* * Returns TRUE if the two PositionedTets are equal, FALSE otherwise. */ extern void set_left_edge(EdgeClass *edge, PositionedTet *ptet); /* * Fills in the fields of *ptet so as to position the EdgeClass *edge * between the near_face and the left_face of *ptet. */ /************************************************************************/ /* */ /* precision.c */ /* */ /************************************************************************/ extern int decimal_places_of_accuracy(Real x, Real y); extern int complex_decimal_places_of_accuracy(Complex x, Complex y); /* * Returns the number of decimal places which x and y have in * common. Typically x and y will be two estimates of the same * computed quantity (e.g. the volume of a manifold), and * decimal_places_of_accuracy() will be used to tell the user * interface how many decimal places should be printed. */ /************************************************************************/ /* */ /* simplify_triangulation.c */ /* */ /************************************************************************/ /* * The high-level functions basic_simplification() and * randomize_triangulation() are declared in SnapPea.h. */ extern FuncResult cancel_tetrahedra(EdgeClass *edge, EdgeClass **where_to_resume, int *num_tetrahedra_ptr); extern FuncResult three_to_two(EdgeClass *edge, EdgeClass **where_to_resume, int *num_tetrahedra_ptr); extern FuncResult two_to_three(Tetrahedron *tet0, FaceIndex f, int *num_tetrahedra_ptr); extern void one_to_four(Tetrahedron *tet, int *num_tetrahedra_ptr, int new_cusp_index); /* * Low-level functions for * * cancelling two Tetrahedra which share a common edge of order 2, * * replacing three Tetrahedra surrounding a common edge with * two Tetrahedra sharing a common face * * replacing two Tetrahedra sharing a common face with * three Tetrahedra surrounding a common edge * * replacing a Tetrahedron with four Tetrahedra meeting a point. * * If an operation cannot be performed because of a topological or geometric * obstruction, the function does nothing and returns func_failed. * Otherwise, it performs the operation and returns func_OK. * * The function one_to_four() will always succeed, and therefore returns void. * It introduces a finite vertex at the center of the Tetrahedron, and therefore * cannot be used when a hyperbolic structure is present. * * The three_to_two(), two_to_three() and one_to_four() operations each correspond * to a projection of a 4-simplex. * * For further details, see the documentation in simplify_triangulation.c, * both at the top of file and immediately preceding each function. */ /************************************************************************/ /* */ /* sl2c_matrices.c */ /* */ /************************************************************************/ extern void sl2c_copy(SL2CMatrix dest, CONST SL2CMatrix source); extern void sl2c_invert(CONST SL2CMatrix a, SL2CMatrix inverse); extern void sl2c_complex_conjugate(CONST SL2CMatrix a, SL2CMatrix conjugate); extern void sl2c_product(CONST SL2CMatrix a, CONST SL2CMatrix b, SL2CMatrix product); extern void sl2c_adjoint(CONST SL2CMatrix a, SL2CMatrix adjoint); extern void sl2c_normalize(SL2CMatrix a); extern Boolean sl2c_matrix_is_real(CONST SL2CMatrix a); /************************************************************************/ /* */ /* solve_equations.c */ /* */ /************************************************************************/ extern FuncResult solve_complex_equations(Complex **complex_equations, int num_rows, int num_columns, Complex *solution); extern FuncResult solve_real_equations(Real **real_equations, int num_rows, int num_columns, Real *solution); /* * These functions solve num_rows linear equations in num_columns * variables. For more information, see solve_equations.c. */ /************************************************************************/ /* */ /* subdivide.c */ /* */ /************************************************************************/ extern Triangulation *subdivide(Triangulation *manifold, const char *new_name); /* * Returns a pointer to a subdivision of *manifold. See subdivide.c for * more details. subdivide() does not change *manifold in any way. */ /************************************************************************/ /* */ /* symmetric_group.c */ /* */ /************************************************************************/ extern Boolean is_group_S5(SymmetryGroup *the_group); /* * Is the_group S5? */ /************************************************************************/ /* */ /* symmetry_group_cusped.c */ /* */ /************************************************************************/ extern FuncResult compute_cusped_symmetry_group( Triangulation *manifold, SymmetryGroup **symmetry_group_of_manifold, SymmetryGroup **symmetry_group_of_link); /* * Computes the SymmetryGroup of a cusped manifold, and also the * SymmetryGroup of the corresponding link (defined at the top of * symmetry_group_cusped.c). */ extern void compute_orders_of_elements(SymmetryGroup *the_group); /* * Assumes the_group->order and the_group->product[][] are already * in place, and computes the_group->order_of_element[]. */ extern void compute_inverses(SymmetryGroup *the_group); /* * Assumes the_group->order and the_group->product[][] are already * in place, and computes the_group->inverse[]. */ extern void recognize_group(SymmetryGroup *the_group); /* * Attempts to recognize the_group as abelian, cyclic, dihedral, * polyhedral or a direct product. */ /************************************************************************/ /* */ /* symmetry_group_closed.c */ /* */ /************************************************************************/ extern FuncResult compute_closed_symmetry_group( Triangulation *manifold, SymmetryGroup **symmetry_group, Triangulation **symmetric_triangulation, Boolean *is_full_group); /* * Attempts to compute the symmetry group of a closed manifold. * Also provides a symmetry Dehn filling description. */ /************************************************************************/ /* */ /* terse_triangulation.c */ /* */ /************************************************************************/ extern TerseTriangulation *alloc_terse(int num_tetrahedra); /* * Allocates a TerseTriangulation. */ extern TerseTriangulation *tri_to_terse_with_base( Triangulation *manifold, Tetrahedron *base_tetrahedron, Permutation base_permutation); /* * Similar to tri_to_terse(), but allows an explicit choice * of base tetrahedron. */ /************************************************************************/ /* */ /* tet_shapes.c */ /* */ /************************************************************************/ extern void add_edge_angles( Tetrahedron *tet0, EdgeIndex e0, Tetrahedron *tet1, EdgeIndex e1, Tetrahedron *tet2, EdgeIndex e2); /* * Add the angles of edge e0 of tet0 and edge e1 of tet1 and writes the * results to edge e2 of tet2. Accounts for edge_orientations. The * EdgeIndices should be in the range 0-5, not 0-2. Chooses arguments * in the range [(-1/2) pi, (3/2) pi], regardless of the angles of the * summands. */ extern Boolean angles_sum_to_zero(Tetrahedron *tet0, EdgeIndex e0, Tetrahedron *tet1, EdgeIndex e1); /* * angles_sum_to_zero() returns TRUE iff one of the angles * (shape[complete]->cwl[ultimate] or shape[filled]->cwl[ultimate]) * at edge e0 of tet0 cancels the corresponding angle at edge e1 * of tet1 (mod 2 pi). Accounts for edge_orientations. */ extern void compute_remaining_angles(Tetrahedron *tet, EdgeIndex e); /* * Assumes the angle at edge e is correct, and computes the remaining * angles in terms of it. Chooses arguments in the range [(-1/2) pi, * (3/2) pi]. */ /************************************************************************/ /* */ /* tidy_peripheral_curves.c */ /* */ /************************************************************************/ extern void tidy_peripheral_curves(Triangulation *manifold); /* * Replaces the existing peripheral curves on *manifold with an * equivalent set which is efficient and contains no trivial loops. */ /************************************************************************/ /* */ /* transcendentals.c */ /* */ /************************************************************************/ extern Real safe_acos(Real x); extern Real safe_asin(Real x); extern Real safe_sqrt(Real x); /* * These are like the usual acos(), asin() and sqrt(), * except that they round almost-legal values to legal ones. * E.g. safe_acos(1.00000001) = acos(1.0) = 0.0, not NaN. */ extern Real arcsinh(Real x); extern Real arccosh(Real x); /* * The inverse hyperbolic sine and cosine, which the standard ANSI * libraries lack. [Some but not all platforms now include asinh() * and acosh(), so I've renamed my own implementations arcsinh() * and arccosh() to avoid conflicts. JRW 2000/02/20] */ /************************************************************************/ /* */ /* triangulations.c */ /* */ /************************************************************************/ extern void initialize_triangulation(Triangulation *manifold); /* * Initializes the fields of *manifold to correspond to the * empty Triangulation. */ extern void initialize_tetrahedron(Tetrahedron *tet); extern void initialize_cusp(Cusp *cusp); extern void initialize_edge_class(EdgeClass *edge_class); /* * Initialize the fields of Tetrahedra, Cusps and EdgeClasses to the * most benign values possible. */ extern void free_tetrahedron(Tetrahedron *tet); /* * Frees a Tetrahedron and all attached data structures, but does NOT * remove the Tetrahedron from any doubly linked list it may be on. */ extern void clear_shape_history(Tetrahedron *tet); extern void copy_shape_history(ShapeInversion *source, ShapeInversion **dest); extern void clear_one_shape_history(Tetrahedron *tet, FillingStatus which_history); /* * What you'd expect. See triangulation.c for details. */ extern FuncResult check_Euler_characteristic_of_boundary(Triangulation *manifold); /* * Returns func_OK if the Euler characteristic of the total boundary of * the manifold is zero. Otherwise returns func_failed. */ extern void number_the_tetrahedra(Triangulation *manifold); /* * Sets each Tetrahedron's index field equal to its position in * the linked list. Indices range from 0 to (num_tetrahedra - 1). */ extern void number_the_edge_classes(Triangulation *manifold); /* * Sets each EdgeClass's index field equal to its position in the * linked list. Indices range from 0 to ((number of EdgeClasses) - 1). */ extern Permutation compose_permutations(Permutation p1, Permutation p0); /* * Returns the composition of two permutations. Permutations are * composed right-to-left: the composition p1 o p0 is what you get * by first doing p0, then p1. */ /************************************************************************/ /* */ /* update_shapes.c */ /* */ /************************************************************************/ extern void update_shapes(Triangulation *manifold, Complex *delta); /* * Updates the shapes of the tetrahedra in *manifold by the amounts * specified in the array delta. If necessary, delta is first scaled * so that no delta[i].real or delta[i].imag exceeds the limit * specified by the constant allowable_change (see update_shapes.c * for more details). The entries in delta are interpreted relative * to the coordinate system given by the coordinate_system field of * each Tetrahedron, and the indexing of delta is assumed to correspond * to the index field of each tetrahedron. */ /************************************************************************/ /* */ /* volume.c */ /* */ /************************************************************************/ extern Real birectangular_tetrahedron_volume( O31Vector a, O31Vector b, O31Vector c, O31Vector d); /* * Computes the volume of a birectangular tetrahedron using Vinberg's * article. Please see volume.c for a citation to Vinberg's article. */ #include "end_namespace.h" #endif regina-4.96/engine/snappea/kernel/kernel_typedefs.h000644 000765 000024 00000041721 12377774107 022344 0ustar00babstaff000000 000000 /* * kernel_typedefs.h * * This file contains #defines, typedefs and enums common to * many parts of the SnapPea kernel (but hidden from the UI). * Typedefs for more complicated data structures are found in * separate files (e.g. triangulation.h). * * For C++ compatibility I've avoided definitions of the form * * typedef enum * { * foo_up, * foo_down * } Foo; * * in favor of * * typedef int Foo; * enum * { * foo_up, * foo_down * }; * * The problem with the former definition is that C++ insists on an * explicit typecast to assign an integer to a variable of type Foo, * so code like "for (foo = 0; foo < 2; foo++)" won't compile. */ #ifndef _kernel_typedefs_ #define _kernel_typedefs_ #include "SnapPea.h" #include "kernel_namespace.h" #define NEW_STRUCT(struct_type) (struct_type *) my_malloc((size_t) sizeof(struct_type)) #define NEW_ARRAY(n, struct_type) (struct_type *) my_malloc((size_t) (n) * sizeof(struct_type)) #define INSERT_BEFORE(new, old) { \ (new)->next = (old); \ (new)->prev = (old)->prev; \ (new)->prev->next = (new); \ (new)->next->prev = (new); \ } #define INSERT_AFTER(new, old) { \ (new)->prev = (old); \ (new)->next = (old)->next; \ (new)->prev->next = (new); \ (new)->next->prev = (new); \ } #define REMOVE_NODE(node) { \ (node)->next->prev = (node)->prev; \ (node)->prev->next = (node)->next; \ } #define ABS(x) (((x) >= 0) ? (x) : -(x)) /* * Gluings of ideal tetrahedra. * * The neighbor and gluing fields of a Tetrahedron tell how the Tetrahedron * is glued to the other Tetrahedra in the Triangulation. The vertices of * each Tetrahedron in the Triangulation are implicitly indexed by the integers * {0,1,2,3}, and the faces are indexed according to the index of the opposite * vertex. The field tet->neighbor[i] contains a pointer to the Tetrahedron * which face i of Tetrahedron tet glues to. The field tet->gluing[i] describes * the gluing as a Permutation of the set {0,1,2,3}, using the following scheme * devised by Bill Thurston. If j {j = 0,1,2,3} does not equal i, then j is the * index of a vertex on face i of Tetrahedron tet, and the Permutation * tet->gluing[i] applied to j gives the index of the vertex of Tetrahedron * tet->neighbor[i] that vertex j glues to. If j equals i, then j is the index * of the vertex of Tetrahedron tet opposite face i, and the Permutation * tet->gluing[i] applied to j gives the index of the vertex of Tetrahedron * tet->neighbor[i] opposite the image of face i; equivalently -- and more * usefully -- j is the index of the given face on Tetrahedron tet, and the * Permutation applied to j gives the index of its image face on * tet->neighbor[i]. * * Each gluing field contains a permutation on {0,1,2,3}, represented in a * single byte as follows. The byte is conceptually divided into four two-bit * fields. The two high-order bits contain the image of 3 under the * permutation, the next two bits contain the image of 2, etc. So, for example, * the permutation which takes 3210 to 2013 would be represented as 10000111. * This representation is space-efficient, and also allows the definition of * the following macro for evaluating permuations. */ typedef unsigned char Permutation; /* * EVALUATE(p,n) is the image of n (n = 0,1,2,3) under the permutation p. */ #define EVALUATE(p,n) ( ((p) >> 2*(n)) & 0x03 ) /* * CREATE_PERMUTATION() is, roughly speaking, the inverse of EVALUATE(). * CREATE_PERMUTATION(a,pa,b,pb,c,pc,d,pd) creates the one-byte Permutation * which takes a to pa, b to pb, c to pc and d to pd. For example, * CREATE_PERMUTATION(1,1,3,2,0,3,2,0) defines the permutation 2013 (base 4), * which equals 10000111 (binary) or 0x87 (hex). Symbolically this is * the permutation {3->2, 2->0, 1->1, 0->3}. */ #define CREATE_PERMUTATION(a,pa,b,pb,c,pc,d,pd) ((Permutation) (((pa) << 2*(a)) + ((pb) << 2*(b)) + ((pc) << 2*(c)) + ((pd) << 2*(d)))) /* * For convenience, we #define the IDENTITY_PERMUTATION. */ #define IDENTITY_PERMUTATION 0xE4 /* = 11100100 = 3210 */ /* * FLOW(,) is used in reconstructing simple closed curves from * homological information. Specifically, let A be the number of times * a curve intersects one side of a triangle, and B be the number of times * it intersects a different side (of the same triangle). Then FLOW(A,B) * is the number of strands of the curve passing from the first side to * the second. */ #define FLOW(A,B) ( ((A<0)^(B<0)) ? \ (((A<0)^(A+B<0)) ? A : -B) : \ 0 ) #define MAX(A,B) ((A) > (B) ? (A) : (B)) #define MIN(A,B) ((A) < (B) ? (A) : (B)) #define DET2(M) ((M[0][0])*(M[1][1]) - (M[0][1])*(M[1][0])) /* Some unix C libraries define PI in math.h, */ /* and complain about a second definition. */ /* #ifndef PI #define PI 3.14159265358979323846 #endif #define TWO_PI 6.28318530717958647693 #define FOUR_PI 12.56637061435917295385 #define PI_OVER_2 1.57079632679489661923 #define PI_OVER_3 1.04719755119659774615 #define THREE_PI_OVER_2 4.71238898038468985769 #define ROOT_3_OVER_2 0.86602540378443864676 #define ROOT_3 1.73205080756887729352 */ #define TRUE 1 #define FALSE 0 typedef signed char VertexIndex, EdgeIndex, FaceIndex; /* * The Orientation of a tetrahedron is determined by placing your hand * inside the tetrahedron with your wrist at face 0, your thumb at face 1, * your index finger at face 2 and your middle finger at face 3. If this * is most comfortably accomplished with your right hand, then the * tetrahedron is right_handed. Otherwise it's left_handed. * * Portions of the code assume that right_handed == 0 and * left_handed ==1, so please don't change them. */ typedef int Orientation; enum { right_handed = 0, left_handed = 1, unknown_orientation }; typedef MatrixParity GluingParity; /* * The constants initial and current are synonymous with complete * and filled, respectively. They are used to refer to cusp shapes. * That is, cusp_shape[initial] is the cusp shape defined by the * complete hyperbolic structure, and cusp_shape[current] is the * cusp shape defined by the current Dehn filling. In both cases * the cusp in question is complete (even though other cusps might * not be) which is why I decided to use the terms initial and current * instead of complete and filled. */ enum { initial, current }; /* * The constants ultimate and penultimate facilitate reference * to the approximate solutions at the ultimate and penultimate * iterations of Newton's method. */ typedef int Ultimateness; enum { ultimate, penultimate }; /* * The ShapeInversion data structure records the event that * a Tetrahedron changes it shape, i.e. goes from having z.real >= 0 * to z.real < 0. This allows the Chern-Simons code (and potentially * other, future additions to SnapPea) to work out the exact path * of the Tetrahedron shape through the parameter space, up to isotopy. * * Each ShapeInversion records which of the three edge parameters * (0, 1 or 2) passed through pi (mod 2 pi) as the Tetrahedron changed * shape. The other two parameters will have passed through 0 (mod 2 pi). * * A stack of ShapeInversions represents the history of a shape. The * stack is implemented as a NULL-terminated linked list. Two consecutive * ShapeInversions with the same edge parameter passing through pi * will cancel. * * Each Tetrahedron has two ShapeInversion stacks, one for the complete * hyperbolic structure and the other for the filled hyperbolic structure. * Both are computed relative to the ultimate hyperbolic structure. */ typedef struct ShapeInversion { /* * Which edge parameter passed through pi (mod 2 pi) ? */ EdgeIndex wide_angle; /* * The next field points to the next ShapeInversion on the * linked list, or is NULL if there are no more. */ struct ShapeInversion *next; } ShapeInversion; /* * The constants M and L provide indices for 2-element arrays * and 2 x 2 matrices which refer to peripheral curves. * * For example, the Tetrahedron data structure records a meridian * as curve[M] and a longitude as curve[L]. * * The file i/o routines assume M == 0 and L == 1, so please * don't change them. */ typedef int PeripheralCurve; enum { M = 0, L = 1 }; /* * The TraceDirection typedef is used to specify whether a curve * should be traced forwards or backwards. */ typedef int TraceDirection; enum { trace_forwards, trace_backwards }; /* * The GeneratorStatus typedef specifies the existence and direction * of a generator of a manifold's fundamental group. See choose_generators.c * for details. */ typedef int GeneratorStatus; enum { unassigned_generator, /* the algorithm has not yet considered the face */ outbound_generator, /* the generator is directed outwards */ inbound_generator, /* the generator is directed inwards */ not_a_generator /* the face does not correspond to a generator */ }; /* * The VertexCrossSections data structure represents a cross section * of each ideal vertex of the Tetrahedron which owns it. * The vertex cross section at vertex v of Tetrahedron tet is a * triangle. The length of its edge incident to face f of tet is * stored as tet->cross_section->edge_length[v][f]. (The edge_length * is undefined when v == f.) Please see cusp_cross_sections.c for * more details. * * By convention, * * when no cusp cross sections are in place, the cross_section field * of each Tetrahedron is set to NULL, and * * when cusp cross sections are created, the routine that creates * them must allocate the VertexCrossSections structures. * * Thus, routines which modify a triangulation (e.g. the two_to_three() * and three_to_two() moves) know that they must keep track of cusp cross * sections if and only if the cross_section fields of the Tetrahedra are * not NULL. */ typedef struct { Real edge_length[4][4]; Boolean has_been_set[4]; } VertexCrossSections; /* * cusp_neighborhoods.c needs to maintain a consistent coordinate system * on each cusp cross section, so that horoballs etc. appear at consistent * positions even as the canonical Triangulation changes. * Each Tetrahedron's cusp_nbhd_position field keeps a pointer to a * struct CuspNbhdPosition while cusp neighborhoods are being maintained; * at all other times that pointer is set to NULL. This offers the same * two advantages described in triangulation.h for the TetShape pointer, * namely, * * (1) we save memory when CuspNbhdPositions aren't needed, and * * (2) the low-level retriangulation routines can tell whether * they need to maintain CuspNbhdPositions or not. * * * The cusp cross sections intersect each ideal tetrahedron in four small * triangles. The CuspNbhdPosition structure records the positions of * each of the four triangles' three vertices. Actually, we keep track * of the left_handed and right_handed sheets separately, so we can work * with the double covers of Klein bottle cusps; that way we're always * working with a torus. The indices of x[h][v][f] are as follows: * * h = left_handed or right_handed tells the sheet we're on, * v = 0,1,2,3 tells the vertex * f = 0,1,2,3 (for f != v) tells the face opposite the * ideal vertex of interest * * Note: The fields x[h][v][v], which are not needed for storing * the corner coordinates of triangles, are pressed into service in * get_cusp_neighborhood_Ford_domain() to store the locations of the * Ford domain vertices. Cf. the FORD_VERTEX(h,v) macro below. * * The Boolean field in_use[h][v] records which x[h][v][] fields * are actually in use. For a Klein bottle cusp, they all will be in use * (because we work with the double cover). For a torus cusp only half * will be in use (in an orientable manifold they'll be the ones on the * right_handed sheet, in a nonorientable manifold one sheet is chosen * arbitrarily). */ typedef struct { Complex x[2][4][4]; Boolean in_use[2][4]; } CuspNbhdPosition; #define FORD_VERTEX(x,h,v) x[h][v][v] /* * The CanonizeInfo data structure records information used by * canonical_retriangulation() in canonize_part_2.c. It is almost local * to that file, but not quite. The low-level retriangulation functions * two_to_three() and one_to_four() in simplify_triangulation.c need to be * able to check whether CanonizeInfo is present, and if so transfer the * information correctly to the new Tetrahedra they create. Thus we make * the convention that the canonize_info field of each Tetrahedron is NULL * if no CanonizeInfo is present, and points to a CanonizeInfo structure if * such information is present. */ typedef int FaceStatus; enum { opaque_face, /* The face lies in the 2-skeleton of the */ /* canonical cell decomposition. */ transparent_face, /* The face lies in the interior of a 3-cell */ /* in the canonical cell decomposition, but */ /* has not yet been worked into the coned */ /* polyhedron. */ inside_cone_face /* The face lies in the interior of a 3-cell */ /* in the canonical cell decomposition, and */ /* also lies in the interior of the coned */ /* polyhedron. */ }; typedef struct { FaceStatus face_status[4]; Boolean part_of_coned_cell; } CanonizeInfo; /* * In the definition of a Tetrahedron, it's useful to include a * general purpose pointer which different kernel modules may use * to temporarily append different data structures to the Tetrahedron. * Even though different modules will append different temporary * data structures, we must have a single global declaration of the * pointer in triangulation.h. One solution would be to declare the * pointer as a pointer to a void, but this leads to a lot of messy * typecasting. Instead, we use the following opaque typedef of a * (globally nonexistent) struct extra. Each module may then define * struct extra as it sees fit. There is no need for the definition * of struct extra found in one source file to be consistent with * that of another source file, although obviously when a function in * one file calls a function in another the programmer must be absolutely * certain that the files do not make conflicting definitions of * struct extra. * * As a guard against conflicts, we make the convention that the * Extra field in the Tetrahedron data structure is always set to NULL * when not in use. Any module that wants to use the fields first * checks whether it is NULL, and reports an error and exits if it isn't. */ typedef struct extra Extra; #include "end_namespace.h" /* * Normally one expects all the code to be compiled with the same set * of calling conventions. An exception arises when using C++ * in conjunction with ANSI library routines that require callback functions. * Specifically, qsort() wants a comparision function declared using * C calling conventions. Typically this requires that the C++ code * declare the callback function as cdecl or _cdecl ("C declaration"). * If this doesn't work, try the following syntax (which will require * something like "#define CDECL_END }" to provide the closing bracket). * * extern "C" * { * int comp(const void *a, const void *b) * { * ... * } * } * * If all else fails, read the documentation for your C++ compiler, * and contact weeks@northnet.org if you have problems. If this * gets to be a headache, I can replace the standard library's qsort() * with a hard-coded qsort (such as the one on page 120 of K&R 2nd ed.). */ #ifdef __cplusplus #define CDECL __cdecl //#define CDECL cdecl #else #define CDECL /* We're not using C++, so CDECL may be empty. */ #endif #endif regina-4.96/engine/snappea/kernel/link_projection.h000644 000765 000024 00000010712 12377774107 022346 0ustar00babstaff000000 000000 /* Modified 8/19/98 by NMD to add a label field to each crossing */ /* * link_projection.h * * This file provides the data format in which the UI passes * link projections to the kernel. All typedefs begin with * "KLP" ("Kernel Link Projection") to avoid name conflicts * with the UI's private link projection data structure. */ #ifndef _link_projection_ #define _link_projection_ #include "kernel_namespace.h" typedef struct KLPCrossing KLPCrossing; typedef struct KLPProjection KLPProjection; /* * The KLPStrandType and KLPDirectionType enums are used to index * array entires, so their values must be 0 and 1. (But the code * does not rely on which has value 0 and which has value 1.) * * JRW 2000/11/12 Use fake "typedef enums" instead of real ones, * for the reasons explained at the top of kernel_typedefs.h. */ /* * If you view a crossing (from above) so that the strands go in the * direction of the postive x- and y-axes, then the strand going in * the x-direction is the KLPStrandX, and the strand going in the * y-direction is the KLPStrandY. Note that this definition does not * depend on which is the overstrand and which is the understrand. * * KLPStrandY * ^ * | * ----+---> KLPStrandX * | * | */ typedef int KLPStrandType; enum { KLPStrandX = 0, KLPStrandY, KLPStrandUnknown }; /* * The backward and forward directions are what you would expect. * * KLPBackward ---------> KLPForward */ typedef int KLPDirectionType; enum { KLPBackward = 0, KLPForward, KLPDirectionUnknown }; /* * A crossing is either a clockwise (CL) or counterclockwise (CCL) * half twist. * * _ _ _ _ * |\ /| |\ /| * \ / \ / * / \ * / \ / \ * / \ / \ * KLPHalfTwistCL KLPHalfTwistCCL */ typedef int KLPCrossingType; enum { KLPHalfTwistCL, KLPHalfTwistCCL, KLPCrossingTypeUnknown }; /* * A link projection is essentially an array of crossings. */ struct KLPProjection { /* * How many crossings are there? */ int num_crossings; /* * How many free loops (i.e. link components with no crossings) are * there? For a hyperbolic link, the number of free loops must be 0. */ int num_free_loops; /* * How many link components (including the free loops) are there? */ int num_components; /* * Here's a pointer to the array of crossings. */ KLPCrossing *crossings; }; /* * Each crossing has pointers to its four neighbors, * along with information about its own handedness. */ struct KLPCrossing { /* * The four neighbors are * * neighbor[KLPStrandX][KLPBackward] * neighbor[KLPStrandX][KLPForward ] * neighbor[KLPStrandY][KLPBackward] * neighbor[KLPStrandY][KLPForward ] * * For example, if you follow the x-strand in the backward direction, * you'll arrive at neighbor[KLPStrandX][KLPBackward]. */ KLPCrossing *neighbor[2][2]; /* * When you arrive at a neighbor, you could arrive at either the * x-strand or the y-strand. The strand[][] field says which it is. * * For example, if you follow the x-strand in the backward direction, * you'll arrive at strand[KLPStrandX][KLPBackward]. */ KLPStrandType strand[2][2]; /* * The crossing is either a clockwise or counterclockwise half twist. */ KLPCrossingType handedness; /* * To which component of the link does each strand belong? A link * component is given by an integer from 0 to (#components - 1). * For example, if component[KLPStrandX] == 0 and * component[KLPStrandY] == 2, then the x-strand is part of component * number 0 and the y-strand is part of component number 2. */ int component[2]; /* Field added 8/19/98 by NMD to store info about wirt. presentation */ /* first index should be a KLPStrand and the second a KLPDirectionType */ int label[2][2]; }; #include "end_namespace.h" #endif regina-4.96/engine/snappea/kernel/matrix_conversion.c000644 000765 000024 00000047226 12377774107 022733 0ustar00babstaff000000 000000 /* * matrix_conversion.c * * This file provides the two functions * * void Moebius_to_O31(MoebiusTransformation *A, O31Matrix B); * void O31_to_Moebius(O31Matrix B, MoebiusTransformation *A); * * which convert matrices back and forth between SL(2,C) and O(3,1), * as well as the functions * * void Moebius_array_to_O31_array(MoebiusTransformation arrayA[], * O31Matrix arrayB[], * int num_matrices); * void O31_array_to_Moebius_array(O31Matrix arrayB[], * MoebiusTransformation arrayA[], * int num_matrices); * * which do the same for arrays of matrices. * * As an add-on, this file also provides * * Boolean O31_determinants_OK( O31Matrix arrayB[], * int num_matrices, * double epsilon); * * which returns TRUE if all the O31Matrices in the array have determinants * within epsilon of plus or minus one, and FALSE otherwise. * * The algorithm in Moebius_to_O31() is based on an explanation provided * by Craig Hodgson of a program written by Diane Hoffoss which in turn * was based on an algorithm explained to her by Bill Thurston. * One would expect a more straightforward algorithm (i.e. something * which makes a direct correspondence between the Minkowski space * model and the upper half space model), but two problems arise: * (1) Whenever you work with points on the sphere at infinity, you * encounter the problem that there is no good way to normalize * the lengths of vectors on the light cone. The most promising * approach to solving this problem is to work with the basis * which is dual to a basis of lightlike vectors, but this is * at best a nuisance. * (2) The computations required to pass from one model to the * other appear, superficially, more complicated than the simple * calculations used in Thurston's algorithm, but obviously they * have to simplify down to the same thing eventually. * So . . . for now I'll just stick with Thurston's algorithm. */ #include "kernel.h" #include "kernel_namespace.h" void Moebius_array_to_O31_array( MoebiusTransformation arrayA[], O31Matrix arrayB[], int num_matrices) { int i; for (i = 0; i < num_matrices; i++) Moebius_to_O31(&arrayA[i], arrayB[i]); } void O31_array_to_Moebius_array( O31Matrix arrayB[], MoebiusTransformation arrayA[], int num_matrices) { int i; for (i = 0; i < num_matrices; i++) O31_to_Moebius(arrayB[i], &arrayA[i]); } void Moebius_to_O31( MoebiusTransformation *A, O31Matrix B) { /* * The trick here is to consider the Minkowski space E(3,1) * not just as an abstract space, but as the space of all * 2 x 2 Hermitian matrices. Roughly speaking, "Hermitian" * is the complex version of "symmetric". * * Definition. The adjoint M* of a complex matrix is * the transpose of the complex conjugate of M. * * Definition. A complex matrix is Hermitian iff M* = M. * * A 2 x 2 complex matrix is Hermitian matrix iff it has the form * * a + 0i c + di * c - di b + 0i * * Such matrices form a 4-dimensional real vector space V. * We choose the following basis for V: * * M0 = 1 0 M1 = 1 0 M2 = 0 1 M3 = 0 i * 0 1 0 -1 1 0 -i 0 * * The determinant -det() defines a (squared) norm on V. * (We use -det() instead of det() so that we end up with * a metric of signature (-+++) instead of (+---).) * This norm leads us to an inner product <,> on V. * We want the inner product to satisfy * * = + 2 + * * which is equivalent to * * -det(M+N) = -det(M) + 2 - det(N), * * so we define the inner product to be * * = (1/2)(det(M) + det(N) - det(M+N)). * * Relative to this inner product, the vectors {M0, M1, M2, M3} * are mutually orthogonal and have squared norms {-1, +1, +1, +1}. * I.e. this is the usual metric for the Minkowski space E(3,1). * * Assume for the moment that the MoebiusTransformation we want * to convert to O(3,1) represents an orientation_preserving isometry. * * We will let a matrix A in SL(2,C) act on the Minkowski * space V, and compute the matrix B in O(3,1) which describes * the action. The action of the matrix A will be denoted f(A). * Thus, f(A) is itself a function which acts on elements of V. * To define f(A), we must say how it acts on each element M of V: * * [f(A)](M) = A M A* * * It's trivial to see that f(A) is a linear function. * f(A) preserves norms [det(AMA*) = det(A)det(M)det(A*) = det(M), * because det(A) = 1], hence it also preserves the inner product; * therefore f(A) is an isometry of V. * * To show that f() is a homomorphism from SL(2,C) to Isom(V), * we must show that the isometries f(A) o f(A') and f(AA') * are equal (where "o" denotes composition of functions). * That is, we must show that [f(A) o f(A')](M) = f(AA')(M) * for all M in V. * * [f(A) o f(A')](M) = f(A)( f(A')(M) ) * = f(A)( A' M A'* ) * = A A' M A'* A* * = (AA') M (AA')* * = f(AA')(M) * * It's easy to check that f(A) fixes the basis {M0, M1, M2, M3} * iff A is plus or minus the identity. That is, the kernel * of f() is {+-I}, and we may think of f() as an injective * map from PSL(2,C) into Isom(V). * * Exercise for the reader: prove that f() maps PSL(2,C) * onto the set of isometries of V which preserve the "time * direction". I.e. the set of all isometries which don't * interchange the past and future light cones. * * So far we have only established the correspondence between * isometries in the upper half space model (as represented * by SL(2,C) matrices) and isometries in the Minkowski space * model (as represented by O(3,1) matrices). We haven't made * a direct correspondence between the points of the upper half * space model and the points of the Minkowski space model. * For some purposes (e.g. dealing with orientation_reversing * isometries) we need to know the precise correspondence between * the spheres at infinity in the two models. We deduce the * correspondence by converting several carefully chosen matrices * from one model to the other, and comparing their fixed points * on the sphere at infinity in each model. Each isometry is * a translation along a geodesic (without rotation). * * Upper Half Space Minkowski Space * * matrix axis matrix axis * * 17/8 15/8 0 0 from * 2 0 from 0 15/8 17/8 0 0 (1,-1, 0, 0) * 0 1/2 towards 0 0 1 0 towards * infinity 0 0 0 1 (1, 1, 0, 0) * * 17/8 0 15/8 0 from * 5/4 3/4 from -1 0 1 0 0 (1, 0,-1, 0) * 3/4 5/4 towards 1 15/8 0 17/8 0 towards * 0 0 0 1 (1, 0, 1, 0) * * 17/8 0 0 15/8 from * 5/4 3i/4 from -i 0 1 0 0 (1, 0, 0,-1) * -3i/4 5/4 towards i 0 0 1 0 towards * 15/8 0 0 17/8 (1, 0, 0, 1) * * Comparison of the above fixed points reveals the correspondence * * 0 <-> (1,-1, 0, 0) * infinity <-> (1, 1, 0, 0) * -1 <-> (1, 0,-1, 0) * 1 <-> (1, 0, 1, 0) * -i <-> (1, 0, 0,-1) * i <-> (1, 0, 0, 1) * * As a corollary, we may deduce the matrix in Minkowski space * which corresponds to complex conjugation in the sphere at * infinity in the upper half space model. In the upper half * space model, complex conjugation fixes 0, infinity, -1 and 1, * and interchanges -i and i. Therefore in the Minkowski space * model it must fix (1,-1, 0, 0), (1, 1, 0, 0), (1, 0,-1, 0) * and (1, 0, 1, 0), and interchange (1, 0, 0,-1) and (1, 0, 0, 1). * The matrix which does this is * * 1 0 0 0 * 0 1 0 0 * 0 0 1 0 * 0 0 0 -1 * * Therefore, to convert an orientation_reversing MoebiusTransformation * to SO(3,1), we first convert the SL(2,C) matrix (as if the isometry * were orientation_preserving), and then multiply the resulting O(3,1) * matrix on the right by the matrix shown above, to account for the * complex conjugation. * * After that long-winded documentation, the code itself is very * simple. The (i,j)-th entry of the O(3,1) matrix B is the * i-th component (relative to the basis {m[0], m[1], m[2], m[3]}) * of A m[j] A*. */ SL2CMatrix ad_A, /* A* = adjoint of A */ fAmj, /* f(A)(m[j]) = A m[j] A* */ temp; int i, /* which row of B */ j; /* which column of B */ CONST static SL2CMatrix m[4] = { {{{ 1.0, 0.0},{ 0.0, 0.0}}, {{ 0.0, 0.0},{ 1.0, 0.0}}}, {{{ 1.0, 0.0},{ 0.0, 0.0}}, {{ 0.0, 0.0},{-1.0, 0.0}}}, {{{ 0.0, 0.0},{ 1.0, 0.0}}, {{ 1.0, 0.0},{ 0.0, 0.0}}}, {{{ 0.0, 0.0},{ 0.0, 1.0}}, {{ 0.0,-1.0},{ 0.0, 0.0}}} }; /* * First convert A->matrix to SO(3,1), without * worrying about A->parity. */ /* * For each basis vector m[j] . . . */ for (j = 0; j < 4; j++) { /* * . . . compute f(A)(m[j]) = A m[j] A* . . . */ sl2c_adjoint(A->matrix, ad_A); sl2c_product(A->matrix, m[j], temp); sl2c_product(temp, ad_A, fAmj); /* * . . . and find its components relative to the basis m[]. */ B[0][j] = 0.5 * (fAmj[0][0].real + fAmj[1][1].real); B[1][j] = 0.5 * (fAmj[0][0].real - fAmj[1][1].real); B[2][j] = fAmj[0][1].real; B[3][j] = fAmj[0][1].imag; } /* * If A->parity is orientation_reversing, multiply on the * right by * 1 0 0 0 * 0 1 0 0 * 0 0 1 0 * 0 0 0 -1 */ if (A->parity == orientation_reversing) for (i = 0; i < 4; i++) B[i][3] = - B[i][3]; } void O31_to_Moebius( O31Matrix B, MoebiusTransformation *A) { /* * We want to invert the transformation described in Moebius_to_O31(). * * If the isometry is orientation_reversing (i.e. if det(B) == -1), * we first factor it as * * ( original ) ( new ) (1 0 0 0) * ( matrix ) = ( matrix ) (0 1 0 0) * ( B ) ( B ) (0 0 1 0) * ( ) ( ) (0 0 0 -1) * * We then convert the "new matrix B" to an SL(2,C) matrix to get * A->matrix, and we set A->parity to orientation_reversing. * The matrix on the far right (= diag(1, 1, 1, -1)) corresponds * to complex conjugation, as explained in the documentation in * Moebius_to_O31() above. * * First write out what Moebius_to_O31() does to a typical Moebius * transformation A. Assume for the moment that the Moebius * transformation is orientation_preserving, and denote the matrix * by A (rather than A->matrix) to save space. As usual, the entries * of A are * * a b * c d * * and the complex conjugate of a number z is written z' (read "z-bar"). * You should also imagine a single set of parentheses around each * 2 x 2 matrix, in spite of the limitations of this text-only file. * Each of the following lines computes A M A* for one of the four * basis vectors {M0, M1, M2, M3}. * * (a b) ( 1 0) (a' c') = ( aa' + bb' ac' + bd') * (c d) ( 0 1) (b' d') ( a'c + b'd cc' + dd') * * (a b) ( 1 0) (a' c') = ( aa' - bb' ac' - bd') * (c d) ( 0 -1) (b' d') ( a'c - b'd cc' - dd') * * (a b) ( 0 1) (a' c') = ( ab' + a'b ad' + bc') * (c d) ( 1 0) (b' d') ( a'd + b'c cd' + c'd) * * (a b) ( 0 i) (a' c') = i ( ab' - a'b ad' - bc') * (c d) (-i 0) (b' d') (-a'd + b'c cd' - c'd) * * The right side of each of the above equations is a * linear combination of the {M0, M1, M2, M3}. The coefficients * are the entries of the O(3,1) matrix B. For the j-th line above, * * A M[j] A* * * = B[0][j] M0 + B[1][j] M1 + B[2][j] M2 + B[3][j] M3 * * = B[0][j] (1 0) + B[1][j] (1 0) + B[2][j] (0 1) + B[3][j] ( 0 i) * (0 1) (0 -1) (1 0) (-i 0) * * = ( B[0][j] + B[1][j] B[2][j] + i B[3][j] ) * ( B[2][j] - i B[3][j] B[0][j] + B[1][j] ) * * Comparing matrix entries in the two computations of A M[j] A* gives * relations like aa' + bb' = B[0][0] + B[1][0], etc. * There is no need to write out all 16 relations -- we'll get the * ones we need later on, as we need them. * * It's not so easy to compute the matrix * * a b * c d * * from the above relations, but it is easy to compute * * 2a'a 2a'b or 2b'a 2b'b * 2a'c 2a'd 2b'c 2b'd * * (The details are in the code below.) * Each of the latter two matrices, if nonzero, can be normalized * to give the former. At least one of them will be nonzero, * because if a and b were both zero, the determinant would * be zero. * * So . . . the algorithm is to decided whether a or b is * nonzero, then compute one of the above two matrices, and * normalize it to give the matrix A. */ int i; Real AM0A_00, /* The (0, 0) entry of A M0 A* */ AM1A_00, /* The (0, 0) entry of A M1 A* */ aa, /* 2 * |a|^2 */ bb; /* 2 * |b|^2 */ /* * Now deal with the orientation, as explained at the beginning * of this function's documentation. gl4R_determinant(B) will be * * +1 if the isometry is orientation_preserving * * -1 if the isometry is orientation_reversing */ if (gl4R_determinant(B) > 0.0) A->parity = orientation_preserving; else { A->parity = orientation_reversing; /* * Factor out diag(1, 1, 1, -1), as explained above. * At the end of the function we'll restore B to its * original condition. */ for (i = 0; i < 4; i++) B[i][3] = - B[i][3]; } /* * From above, * * (A M0 A*)[0][0] = aa' + bb' = B[0][0] + B[1][0] * (A M1 A*)[0][0] = aa' - bb' = B[0][1] + B[1][1] * => * 2aa' = (A M0 A*)[0][0] + (A M1 A*)[0][0] * = (B[0][0] + B[1][0]) + (B[0][1] + B[1][1]) * * 2bb' = (A M0 A*)[0][0] - (A M1 A*)[0][0] * = (B[0][0] + B[1][0]) - (B[0][1] + B[1][1]) */ AM0A_00 = B[0][0] + B[1][0]; AM1A_00 = B[0][1] + B[1][1]; aa = AM0A_00 + AM1A_00; bb = AM0A_00 - AM1A_00; if (aa > bb) /* |a| > |b| */ { A->matrix[0][0].real = aa; /* 2a'a */ A->matrix[0][0].imag = (Real)0.0; /* * (A M2 A*)[0][0] = ab' + a'b * = 2 Re(a'b) * = B[0][2] + B[1][2] * * (A M3 A*)[0][0] = i (ab' - a'b) * = i ( -2i Im(a'b) ) * = 2 Im(a'b) * = B[0][3] + B[1][3] */ A->matrix[0][1].real = B[0][2] + B[1][2]; /* 2a'b */ A->matrix[0][1].imag = B[0][3] + B[1][3]; /* * a'c + b'd = (A M0 A*)[1][0] = B[2][0] - i B[3][0] * a'c - b'd = (A M1 A*)[1][0] = B[2][1] - i B[3][1] * * => 2a'c = (B[2][0] + B[2][1]) - i (B[3][0] + B[3][1]) */ A->matrix[1][0].real = B[2][0] + B[2][1]; /* 2a'c */ A->matrix[1][0].imag = - B[3][0] - B[3][1]; /* * a'd + b'c = (A M2 A*)[1][0] = B[2][2] - i B[3][2] * -i (a'd - b'c) = (A M3 A*)[1][0] = B[2][3] - i B[3][3] * * => 2a'd = (B[2][2] + B[3][3]) + i (B[2][3] - B[3][2]) */ A->matrix[1][1].real = B[2][2] + B[3][3]; /* 2a'd */ A->matrix[1][1].imag = B[2][3] - B[3][2]; } else /* |b| >= |a| */ { /* * (A M2 A*)[0][0] = b'a + ba' * = 2 Re(b'a) * = B[0][2] + B[1][2] * * (A M3 A*)[0][0] = i (b'a - ba') * = i ( 2i Im(b'a) ) * = -2 Im(b'a) * = B[0][3] + B[1][3] */ A->matrix[0][0].real = B[0][2] + B[1][2]; /* 2b'a */ A->matrix[0][0].imag = - B[0][3] - B[1][3]; A->matrix[0][1].real = bb; /* 2b'b */ A->matrix[0][1].imag = (Real)0.0; /* * b'c + a'd = (A M2 A*)[1][0] = B[2][2] - i B[3][2] * i (b'c - a'd) = (A M3 A*)[1][0] = B[2][3] - i B[3][3] * * => 2b'c = (B[2][2] - B[3][3]) - i (B[2][3] + B[3][2]) */ A->matrix[1][0].real = B[2][2] - B[3][3]; /* 2b'c */ A->matrix[1][0].imag = - B[2][3] - B[3][2]; /* * b'd + a'c = (A M0 A*)[1][0] = B[2][0] - i B[3][0] * - (b'd - a'c) = (A M1 A*)[1][0] = B[2][1] - i B[3][1] * * => 2b'd = (B[2][0] - B[2][1]) + i (B[3][1] - B[3][0]) */ A->matrix[1][1].real = B[2][0] - B[2][1]; /* 2b'd */ A->matrix[1][1].imag = B[3][1] - B[3][0]; } /* * Normalize A to have determinant one. */ sl2c_normalize(A->matrix); /* * If the isometry is orientation_reversing, multiply back in * the diag(1, 1, 1, -1) which we factored out at the beginning. */ if (A->parity == orientation_reversing) for (i = 0; i < 4; i++) B[i][3] = - B[i][3]; } Boolean O31_determinants_OK( O31Matrix arrayB[], int num_matrices, Real epsilon) { int i; for (i = 0; i < num_matrices; i++) if (fabs(fabs(gl4R_determinant(arrayB[i])) - 1.0) > epsilon) return FALSE; return TRUE; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/matrix_generators.c000644 000765 000024 00000027131 12377774107 022710 0ustar00babstaff000000 000000 /* * matrix_generators.c * * This file provides the function * * void matrix_generators( Triangulation *manifold, * MoebiusTransformation generators[]); * * which computes the MoebiusTransformations representing the action * of the generators of a manifold's fundamental group on the sphere at * infinity. matrix_generators() writes the MoebiusTransformations * to the array generators[], which it assumes has already been allocated. * * NMD 2010/3/22: Now matrix generators assumes that choose_generators * has been called in advance. This is to prevent a double-call of * choose_generators in fundamental_group.c * * MC 2013/3/28: Made matrix_generators return func_failed rather than * call uFatalError in case it encounters 0/0. */ #include "kernel.h" #include "kernel_namespace.h" #undef DEBUG #ifdef DEBUG #include #endif static FuncResult compute_one_generator(Tetrahedron *tet, FaceIndex f, MoebiusTransformation *mt); FuncResult matrix_generators( Triangulation *manifold, MoebiusTransformation generators[]) { Boolean *already_computed; int i; FaceIndex f; Tetrahedron *tet; FuncResult result=func_OK; /* * Assumes that the locations of the ideal vertices of the * Tetrahedra on the sphere at infinity have already been * computed by the below call. * * choose_generators(manifold, TRUE, centroid_at_origin); * */ /* * [MC] If we don't have a reasonble solution, we don't belong * here. */ if ( manifold->solution_type[filled] != geometric_solution && manifold->solution_type[filled] != nongeometric_solution ) return func_failed; /* * Keep track of which generators we've already computed, * to avoid unnecessary duplication of effort. */ already_computed = NEW_ARRAY(manifold->num_generators, Boolean); for (i = 0; i < manifold->num_generators; i++) already_computed[i] = FALSE; /* * Search through all the faces of all the Tetrahedra looking * for generators. Compute those not already computed. */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (f = 0; f < 4; f++) if (tet->generator_status[f] == outbound_generator && already_computed[tet->generator_index[f]] == FALSE) { result = compute_one_generator(tet, f, &generators[tet->generator_index[f]]); already_computed[tet->generator_index[f]] = TRUE; if (result != func_OK) break; } /* * We're done. * Free the array and go home. */ my_free(already_computed); return result; } static FuncResult compute_one_generator( Tetrahedron *tet, FaceIndex f, MoebiusTransformation *mt) { int i, missing; Complex a[4], b[4], k, b1k, numerator, denominator, normalization, temp; Tetrahedron *neighbor = tet->neighbor[f]; Orientation orientation = neighbor->flag; #ifdef DEBUG printf("compute_one_generator:\n"); #endif /* * First read out the locations of the corners of this face, and * also its mate elsewhere on the boundary of the fundamental domain. * * There are two possible interpretations for the matrix corresponding * to a given generator. * * (1) Think of the matrix as defining a face pairing isometry on * a fundamental domain. The isometry takes the given face to * its mate. * * (2) Think of the matrix as giving a representation of the abstract * fundamental group into the group of covering transformations. * The isometry takes the mate to the given face. * * Here we adopt interpretation (2). If you preferred (1) you'd need * to switch the definitions of a[] and b[] to * * a[count] = tet->corner[i]; * b[count] = tet->neighbor[f]->corner[EVALUATE(tet->gluing[f], i)]; * * (But don't switch them here! You'll foul up the matrix representations * in fundamental_group.c.) */ /* * [MC] We are computing an isometry which sends the a tetrahedron * to the b tetrahedron. According to the comment above, the a * tetrahedron is the neighbor. The b tetrahedron shares a face * with tet, but has the same shape as the a tetrahedron. (Or, in * the orientaion-reversing case, the conjugate shape.) We copy * the vertices of the neighbor tetrahedron into the array a, and * the corresponding vertices of its image tetrahedron into the * array b, except that we skip the vertex that maps to f since we * don't know it yet. */ missing = EVALUATE(tet->gluing[f], f); for (i = 0; i < 4; i++) { a[i] = neighbor->corner[i]; if ( i != missing ) b[i] = tet->corner[EVALUATE(neighbor->gluing[missing], i)]; } /* * Note the parity of MoebiusTransformation. */ mt->parity = tet->generator_parity[f]; /* * [MC] Now we compute the missing corner of the image tetrahedron. * For an orientation-reversing generator we orient the image tetrahedron * oppositely. */ if (mt->parity == orientation_reversing) orientation = neighbor->flag == left_handed? right_handed : left_handed; compute_fourth_corner( b, /* array of corner coordinates */ missing, /* the corner to be computed */ orientation, /* the orientation of the image */ neighbor->shape[filled]->cwl[ultimate]); /* neighbor's shapes */ /* * The formula for the Moebius transformation taking the a[] to the b[] * is simple enough: * * f(z) = [ (b1*k - b0) * z + (b0*a1 - b1*a0*k)] / * [ (k - 1) * z + (a1 - k*a0) ] * * where * * k = [(b2-b0)/(b2-b1)] * [(a2-a1)/(a2-a0)] * * Even though one of the a[] and/or one of the b[] could be infinite, * we will bravely push forward with the computation. The justification * for such boldness is that the Complex constant Infinity is not actually * infinite, but is just a large number (1e34). Its square is less than * the assumed value of REAL_MAX, so we can safely compute squares * of "infinite" numbers and expect them to cancel properly with other * infinite numbers. In the normalization step we also assume the fourth * power of "infinity" is less than REAL_MAX. (DBL_MAX is 1.2e+4932 * on a Mac and 1.8e+308 on a Sun or NeXT, so we shouldn't run into * trouble (knock on wood).) * * It would be more rigorous to consider separately the cases with * a0, a1 or a2; and/or b0, b1 or b2 are infinite, and take the limit of * the above formula by hand, but I didn't feel up to it. */ /* * [MC] Making it more rigorous is not so hard now that we have * taken the trouble to compute all four vertices of both * tetrahedra. We are free to permute the vertices so that a[0], * a[1], a[2], b[0], and b[1] are all finite. The only special * case we have to deal with is when b[2] is infinite. It is * easy to compute k in that case. */ #ifdef DEBUG printf("a infinitude: %d %d %d %d\n", complex_infinite(a[0]), complex_infinite(a[1]), complex_infinite(a[2]), complex_infinite(a[3])); printf("b infinitude: %d %d %d %d\n", complex_infinite(b[0]), complex_infinite(b[1]), complex_infinite(b[2]), complex_infinite(b[3])); #endif /* If one of a[0], a[1], a[2] is infinite, swap with a[3] */ for (i=0; i<4; i++) { if ( complex_infinite(a[i])) break; } if ( i < 3 ) { #ifdef DEBUG printf("a[%d] is infinite. Swapping.\n", i); #endif temp = a[3]; a[3] = a[i]; a[i] = temp; temp = b[3]; b[3] = b[i]; b[i] = temp; } /* If b[0] or b[1] are infinite, swap with b[2]. */ for (i=0; i<3; i++) { if ( complex_infinite(b[i]) ) break; } if ( i < 2) { #ifdef DEBUG printf("b[%d] is infinite. Swapping\n", i); #endif temp = a[2]; a[2] = a[i]; a[i] = temp; temp = b[2]; b[2] = b[i]; b[i] = temp; } /* * [MC] At this point all we need to do is compute a * MoebiusTransformation that sends a[i] -> b[i] for i = 0,1,2. * We are in the same position as the original code, except * we know that none of those six points is infinite with the * possible exception of b[2]. */ /* * If the MoebiusTransformation is orientation_reversing, we want * to compute a function of z-bar, as explained in the documentation * accompanying the definition of a MoebiusTransformation in SnapPea.h. */ if (mt->parity == orientation_reversing) for (i = 0; i < 3; i++) a[i] = complex_conjugate(a[i]); if ( complex_infinite(b[2]) ) { /* the special case */ numerator = complex_minus(a[2],a[1]); denominator = complex_minus(a[2],a[0]); } else { numerator = complex_mult(complex_minus(b[2],b[0]), complex_minus(a[2],a[1])); denominator = complex_mult(complex_minus(b[2],b[1]), complex_minus(a[2],a[0])); } #ifdef DEBUG printf("numerator = %e + %ei\n", (double)numerator.real, (double)numerator.imag); printf("denominator = %e + %ei\n", (double)denominator.real, (double)denominator.imag); #endif if ( numerator.real == 0 && numerator.imag == 0 && denominator.real == 0 && denominator.imag == 0 ) return func_failed; k = complex_div(numerator, denominator); #ifdef DEBUG printf("k = %e + %ei\n", (double)k.real, (double)k.imag); #endif b1k = complex_mult(b[1], k); normalization = complex_sqrt( complex_div( One, complex_mult(k, complex_mult( complex_minus(a[1],a[0]), complex_minus(b[1],b[0]) ) ) ) ); mt->matrix[0][0] = complex_mult( normalization, complex_minus(b1k, b[0]) ); mt->matrix[0][1] = complex_mult( normalization, complex_minus( complex_mult(b[0], a[1]), complex_mult(b1k, a[0]) ) ); mt->matrix[1][0] = complex_mult( normalization, complex_minus(k, One) ); mt->matrix[1][1] = complex_mult( normalization, complex_minus( a[1], complex_mult(k,a[0]) ) ); #ifdef DEBUG printf("result:\n"); printf("%e + i(%e) %e + i(%e)\n%e + i(%e) %e + i(%e)\n", (double)mt->matrix[0][0].real, (double)mt->matrix[0][0].imag, (double)mt->matrix[0][1].real, (double)mt->matrix[0][1].imag, (double)mt->matrix[1][0].real, (double)mt->matrix[1][0].imag, (double)mt->matrix[1][1].real, (double)mt->matrix[1][1].imag); printf("~~~~~\n"); #endif return func_OK; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/Moebius_transformations.c000644 000765 000024 00000002725 12377774107 024071 0ustar00babstaff000000 000000 /* * Moebius_transformations.c */ #include "kernel.h" #include "kernel_namespace.h" CONST MoebiusTransformation Moebius_identity = { { {{1.0, 0.0}, {0.0, 0.0}}, {{0.0, 0.0}, {1.0, 0.0}} }, orientation_preserving }; void Moebius_copy( MoebiusTransformation *dest, MoebiusTransformation *source) { sl2c_copy(dest->matrix, source->matrix); dest->parity = source->parity; } void Moebius_invert( MoebiusTransformation *mt, MoebiusTransformation *mt_inverse) { sl2c_invert(mt->matrix, mt_inverse->matrix); if (mt->parity == orientation_reversing) sl2c_complex_conjugate(mt_inverse->matrix, mt_inverse->matrix); mt_inverse->parity = mt->parity; } void Moebius_product( MoebiusTransformation *a, MoebiusTransformation *b, MoebiusTransformation *product) { SL2CMatrix factor1, factor2; sl2c_copy(factor1, a->matrix); sl2c_copy(factor2, b->matrix); if (a->parity == orientation_reversing) sl2c_complex_conjugate(factor2, factor2); sl2c_product(factor1, factor2, product->matrix); product->parity = (a->parity == b->parity) ? orientation_preserving: orientation_reversing; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/my_malloc.c000644 000765 000024 00000013272 12377774107 021130 0ustar00babstaff000000 000000 /* * my_malloc.c * * This file provides an interface to malloc() and free() which * * (1) Keeps track of the number of calls to malloc() minus the number * of calls to free(). This allows easy detection of programming * errors which allocate more memory than they free (or vice versa). * * (2) Aborts the program if malloc() returns NULL. This saves having * to check whether malloc() == NULL at each point where malloc() * is called. * * All kernel routines use my_malloc() and my_free(); * no UI routines do so. * * The UI should call verify_my_malloc_usage() upon exit, to verify * that the number of calls to my_malloc() was exactly balanced by * the number of calls to my_free(). * * The remainder of this comment deals with a debugging feature, and * may be safely ignored until such time as you start freeing memory * you haven't allocated, or writing off the ends of arrays. * * If the constant DEBUG_MALLOC is #defined to be 1 (see below) then * my_malloc() and my_free() maintain a linked list * of the addresses of the blocks of memory which have been allocated. * If some other part of the kernel attempts to free memory which has * not been allocated (or free the same memory twice), free() generates * and error message and exits. Because this feature is for debugging * purposes only, no attempt is made to be efficient. (Obviously a * binary tree would be more efficient than a linked list, but you'd have * to account for the fact that the memory is most likely allocated * in linear order. Reversing the order of the bytes would be simpler * than implementing a balanced tree.) * * Note that the DEBUG_MALLOC feature itself uses memory, but does not * record its own usage in the linked list. This is OK. Its purpose * is to help debug SnapPea, not malloc(). * * If DEBUG_MALLOC is turned on, my_malloc() tacks four extra bytes on * the end of every requested block of memory, and writes in an * arbitrary (but well defined) sequence of four characters. When the * memory is freed, my_free() checks those four characters to see whether * they've been overwritten. This is not a perfect guarantee against * writing past the ends of array, but it should detect at least some * errors. */ #include "kernel.h" #include /* needed for malloc() */ #include /* needed for sprintf() */ #include "kernel_namespace.h" static int net_malloc_calls = 0; /* * The debugging feature is normally off. */ #define DEBUG_MALLOC 0 #if DEBUG_MALLOC #define MAX_BYTES 50000 typedef struct memnode { void *address; size_t bytes; struct memnode *next; } MemNode; static MemNode mem_list = {NULL, 0, NULL}; static const char secret_code[5] = "Adam"; static Boolean message_given = FALSE; #endif void *my_malloc( size_t bytes) { void *ptr; #if DEBUG_MALLOC MemNode *new_mem_node; char *error_bytes; int i; #endif #if DEBUG_MALLOC if (message_given == FALSE) { uAcknowledge("The my_malloc() memory allocator is in debugging mode."); message_given = TRUE; } #endif #if DEBUG_MALLOC if (bytes < 0) { uAcknowledge("A negative number of bytes were requested in my_malloc()."); exit(3); } if (bytes > MAX_BYTES) uAcknowledge("Too many bytes were requested in my_malloc()."); #endif /* * Most likely malloc() and free() would correctly handle * a request for zero bytes, but why take chances? */ if (bytes == 0) bytes = 1; #if DEBUG_MALLOC ptr = malloc(bytes + 4); #else ptr = malloc(bytes); #endif if (ptr == NULL) uAbortMemoryFull(); net_malloc_calls++; #if DEBUG_MALLOC error_bytes = (char *) ptr + bytes; for (i = 0; i < 4; i++) error_bytes[i] = secret_code[i]; new_mem_node = (MemNode *) malloc((size_t) sizeof(MemNode)); if (new_mem_node == NULL) { uAcknowledge("out of memory"); exit(4); } new_mem_node->address = ptr; new_mem_node->bytes = bytes; new_mem_node->next = mem_list.next; mem_list.next = new_mem_node; #endif return ptr; } void my_free( void *ptr) { #if DEBUG_MALLOC Boolean old_node_found; MemNode *old_mem_node, *prev_mem_node; size_t bytes; char *error_bytes; int i; #endif #if DEBUG_MALLOC old_node_found = FALSE; for ( prev_mem_node = &mem_list, old_mem_node = mem_list.next; old_mem_node != NULL; old_mem_node = old_mem_node->next, prev_mem_node = prev_mem_node->next) if (old_mem_node->address == ptr) { old_node_found = TRUE; bytes = old_mem_node->bytes; prev_mem_node->next = old_mem_node->next; free(old_mem_node); break; } if (old_node_found == FALSE) { uAcknowledge("A bad address was passed to my_free()."); exit(5); } error_bytes = (char *) ptr + bytes; for (i = 0; i < 4; i++) if (error_bytes[i] != secret_code[i]) { uAcknowledge("my_free() received a corrupted array."); exit(6); } #endif free(ptr); net_malloc_calls--; } int malloc_calls() { return net_malloc_calls; } void verify_my_malloc_usage() { char the_message[256]; if (net_malloc_calls != 0) { sprintf(the_message, "Memory allocation error:\rThere were %d %s calls to my_malloc() than to my_free().", net_malloc_calls > 0 ? net_malloc_calls : - net_malloc_calls, net_malloc_calls > 0 ? "more" : "fewer"); uAcknowledge(the_message); } } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/o31_matrices.c000644 000765 000024 00000035152 12377774107 021446 0ustar00babstaff000000 000000 /* * o31_matrices.c * * This file provides the following functions for working with O31Matrices: * * void o31_copy(O31Matrix dest, O31Matrix source); * void o31_invert(O31Matrix m, O31Matrix m_inverse); * FuncResult gl4R_invert(GL4RMatrix m, GL4RMatrix m_inverse); * double gl4R_determinant(GL4RMatrix m); * void o31_product(O31Matrix a, O31Matrix b, O31Matrix product); * Boolean o31_equal(O31Matrix a, O31Matrix b, double epsilon); * double o31_trace(O31Matrix m); * double o31_deviation(O31Matrix m); * void o31_GramSchmidt(O31Matrix m); * void o31_conjugate(O31Matrix m, O31Matrix t, O31Matrix Tmt); * double o31_inner_product(O31Vector u, O31Vector v); * void o31_matrix_times_vector(O31Matrix m, O31Vector v, O31Vector product); * void o31_constant_times_vector(double r, O31Vector v, O31Vector product); * void o31_copy_vector(O31Vector dest, O31Vector source); * void o31_vector_sum(O31Vector a, O31Vector b, O31Vector sum); * void o31_vector_diff(O31Vector a, O31Vector b, O31Vector diff); */ #include "kernel.h" #include "kernel_namespace.h" /* * gl4R_invert will consider a matrix to be singular iff one of the * absolute value of one of the pivots is less than SINGULAR_MATRIX_EPSILON. */ #define SINGULAR_MATRIX_EPSILON 1e-2 #define COLUMN_PRODUCT(m, i, j) \ (-m[0][i]*m[0][j] + m[1][i]*m[1][j] + m[2][i]*m[2][j] + m[3][i]*m[3][j]) O31Matrix O31_identity = { {1.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 1.0} }; void o31_copy( O31Matrix dest, O31Matrix source) { int i, j; for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) dest[i][j] = source[i][j]; } void o31_invert( O31Matrix m, O31Matrix m_inverse) { /* * The inverse of an O(3,1) matrix may be computed by taking * the transpose and then negating both the zeroth row and the * zeroth column. The proof follows easily from the fact that * multiplying an O(3,1) matrix by its transpose is almost the * same thing as computing the inner product of each pair of * columns. (For O(4) matrices, the transpose is precisely * the inverse, because there are no minus sign in the metric * to fuss over.) * * We first write the inverse into the O31Matrix temp, so that if * the parameters m and m_inverse are the same O31Matrix, we don't * overwrite m[j][i] before computing m[i][j]. */ int i, j; O31Matrix temp; for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) temp[i][j] = ((i == 0) == (j == 0)) ? m[j][i] : -m[j][i]; for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) m_inverse[i][j] = temp[i][j]; } FuncResult gl4R_invert( GL4RMatrix m, GL4RMatrix m_inverse) { Real row[4][8]; Real *mm[4], *temp_row, multiple; int i, j, k; for (i = 0; i < 4; i++) mm[i] = row[i]; /* * Copy m -- don't alter the original. */ for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) mm[i][j] = m[i][j]; /* * Initialize the four right hand columns to the identity. */ for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) mm[i][4 + j] = (i == j) ? 1.0 : 0.0; /* * Forward elimination. */ for (j = 0; j < 4; j++) { /* * Partial pivoting. */ for (i = j+1; i < 4; i++) if (fabs(mm[j][j]) < fabs(mm[i][j])) { temp_row = mm[j]; mm[j] = mm[i]; mm[i] = temp_row; } /* * Is the matrix singular? */ if (fabs(mm[j][j]) < SINGULAR_MATRIX_EPSILON) return func_bad_input; /* * Divide through to get a 1.0 on the diagonal. */ multiple = 1.0 / mm[j][j]; for (k = j; k < 8; k++) mm[j][k] *= multiple; /* * Clear out that column. */ for (i = j+1; i < 4; i++) { multiple = mm[i][j]; for (k = j; k < 8; k++) mm[i][k] -= multiple * mm[j][k]; } } /* * Back substitution. */ for (j = 4; --j >= 0; ) for (i = j; --i >= 0; ) for (k = 4; k < 8; k++) mm[i][k] -= mm[i][j] * mm[j][k]; /* * Copy out the solution. */ for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) m_inverse[i][j] = mm[i][4 + j]; return func_OK; } Real gl4R_determinant( GL4RMatrix m) { /* * Two approaches come to mind for computing a 4 x 4 determinant. * * (1) Work out the 4! = 24 terms -- each a product of four * matrix entries -- and form their alternating sum. * * (2) Use Gaussian elimination. * * I doubt there is much difference in efficiency between the two * methods, so I've chosen method (2) on the assumption (which I * haven't thoroughly thought out) that it will be numerically more * robust. Numerical effects could be noticeable, because O(3,1) * matrices tend to have large entires. On the other hand, the * determinant will always be plus or minus one, so it's not worth * getting too concerned about the precision. */ /* * gl4R_determinant() no longer calls uFatalError() when the determinant * is something other than +1 or -1. This lets compute_approx_volume() * in Dirichlet_extras.c compute the determinant of matrices which * are in gl(2,C) but not O(3,1). Note that matrix_io.c already calls * O31_determinants_OK() to validate matrices read from files, and * that SnapPea has had no trouble with determinants of internally * computed O(3,1) matrices. * * JRW 94/11/30 */ int r, c, cc, pivot_row, row_swaps; Real max_abs, this_abs, temp, factor, det; O31Matrix mm; /* * First copy the matrix, to avoid destroying it as * we compute its determinant. */ o31_copy(mm, m); /* * Put the matrix in upper triangular form. * * Count the number of row swaps, so we can get the * correct sign at the end. * * Technical comment: We don't actually write zeros into the * lower part of the matrix; we just pretend. */ row_swaps = 0; pivot_row = 0; for (c = 0; c < 4; c++) { /* * Find the pivot row. */ max_abs = -1.0; for (r = c; r < 4; r++) { this_abs = fabs(mm[r][c]); if (this_abs > max_abs) { max_abs = this_abs; pivot_row = r; } } if (max_abs == 0.0) /* * The determinant of an O(3,1) matrix should always * be plus or minus one, never zero. */ /* uFatalError("gl4R_determinant", "o31_matrices"); */ return 0.0; /* JRW 94/11/30 (see explanation above) */ /* * Swap the pivot row into position. */ if (pivot_row != c) { for (cc = c; cc < 4; cc++) { temp = mm[c][cc]; mm[c][cc] = mm[pivot_row][cc]; mm[pivot_row][cc] = temp; } row_swaps++; } /* * Eliminate the entries in column c which lie below the pivot. */ for (r = c + 1; r < 4; r++) { factor = - mm[r][c] / mm[c][c]; for (cc = c + 1; cc < 4; cc++) mm[r][cc] += factor * mm[c][cc]; } } /* * The determinant is now the product of the diagonal entries. */ det = 1.0; for (c = 0; c < 4; c++) det *= mm[c][c]; if (row_swaps % 2) det = - det; /* * Do a quick error check, just to be safe. * The determinant of an O31_matrix should be +1 or -1. */ /* commented out by JRW 94/11/30 (see explanation above) if (fabs(fabs(det) - 1.0) > 0.01) uFatalError("gl4R_determinant", "o31_matrices"); */ return det; } void o31_product( O31Matrix a, O31Matrix b, O31Matrix product) { register int i, j, k; register Real sum; O31Matrix temp; for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) { sum = 0.0; for (k = 0; k < 4; k++) sum += a[i][k] * b[k][j]; temp[i][j] = sum; } for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) product[i][j] = temp[i][j]; } Boolean o31_equal( O31Matrix a, O31Matrix b, Real epsilon) { /* * There are a number of different ways one could decide whether two * O(3,1) matrices are the same or not. The fancier ways, such as * computing the sum of the squares of the differences of corresponding * entries, are numerically more time consuming. For now let's just * check that all entries are equal to within epsilon. This offers the * advantage that when scanning down lists, the vast majority of * matrices are diagnosed as different after the comparision of a * single pair of numbers. The epsilon can be fairly large, since to * qualify as equal, two matrices must have ALL their entries equal to * within that precision. */ int i, j; for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) if (fabs(a[i][j] - b[i][j]) > epsilon) return FALSE; return TRUE; } Real o31_trace( O31Matrix m) { int i; Real trace; trace = 0.0; for (i = 0; i < 4; i++) trace += m[i][i]; return trace; } Real o31_deviation( O31Matrix m) { /* * The matrix m is, in theory, an element of SO(3,1), * so the inner product of column i with column j should be * * -1 if i = j = 0, * +1 if i = j != 0, or * 0 if i != j. * * Return the greatest deviation from these values, so the * calling function has some idea how precise the matrix is. * * The simplest way to code this is to multiply the matrix times its * inverse. Note that this approach relies on the fact that * o31_inverse() transposes the matrix and negates the appropriate * entries. If o31_inverse() did Gaussian elimination to numerically * invert the matrix, we'd have to rewrite the following code. */ O31Matrix the_inverse, the_product; Real error, max_error; int i, j; o31_invert(m, the_inverse); o31_product(m, the_inverse, the_product); max_error = 0.0; for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) { error = fabs(the_product[i][j] - (i == j ? 1.0 : 0.0)); if (error > max_error) max_error = error; } return max_error; } void o31_GramSchmidt( O31Matrix m) { /* * Given a matrix m whose columns are almost orthonormal (in the sense * of O(3,1), not O(4)), use the Gram-Schmidt process to make small * changes to the matrix entries so that the columns become orthonormal * to the highest precision possible. */ int r, c, cc; Real length, length_of_projection; for (c = 0; c < 4; c++) { /* * Adjust column c to have length -1 (if c == 0) or +1 (if c > 0). * We are assuming m is already close to being in O(3,1), so * it suffices to divide column c by sqrt(fabs(length)). */ length = sqrt(fabs(COLUMN_PRODUCT(m, c, c))); /* no need for safe_sqrt() */ for (r = 0; r < 4; r++) m[r][c] /= length; /* * We want to make all subsequent columns be orthogonal to column c, * so subtract off their components in the direction of column c. * Because column c is now a unit vector, the inner product * gives plus or minus the length of the * projection of column cc onto column c, according to whether or * not c == 0. */ for (cc = c + 1; cc < 4; cc++) { length_of_projection = COLUMN_PRODUCT(m, c, cc); if (c == 0) length_of_projection = - length_of_projection; for (r = 0; r < 4; r++) m[r][cc] -= length_of_projection * m[r][c]; } } } void o31_conjugate( O31Matrix m, O31Matrix t, O31Matrix Tmt) { /* * Replace m with (t^-1) m t. */ O31Matrix t_inverse, temp; o31_invert(t, t_inverse); o31_product(t_inverse, m, temp); o31_product(temp, t, Tmt); } Real o31_inner_product( O31Vector u, O31Vector v) { int i; Real sum; sum = - u[0]*v[0]; for (i = 1; i < 4; i++) sum += u[i]*v[i]; return sum; } void o31_matrix_times_vector( O31Matrix m, O31Vector v, O31Vector product) { register int i, j; register Real sum; O31Vector temp; for (i = 0; i < 4; i++) { sum = 0.0; for (j = 0; j < 4; j++) sum += m[i][j] * v[j]; temp[i] = sum; } for (i = 0; i < 4; i++) product[i] = temp[i]; } void o31_constant_times_vector( Real r, O31Vector v, O31Vector product) { int i; for (i = 0; i < 4; i++) product[i] = r * v[i]; } void o31_copy_vector( O31Vector dest, O31Vector source) { int i; for (i = 0; i < 4; i++) dest[i] = source[i]; } void o31_vector_sum( O31Vector a, O31Vector b, O31Vector sum) { int i; for (i = 0; i < 4; i++) sum[i] = a[i] + b[i]; } void o31_vector_diff( O31Vector a, O31Vector b, O31Vector diff) { int i; for (i = 0; i < 4; i++) diff[i] = a[i] - b[i]; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/orient.c000644 000765 000024 00000062100 12377774107 020446 0ustar00babstaff000000 000000 /* * orient.c * * This file provides the functions * * void orient(Triangulation *manifold); * void reorient(Triangulation *manifold); * void fix_peripheral_orientations(Triangulation *manifold); * * orient() attempts to consistently orient the Tetrahedra of the * Triangulation *manifold. It begins with manifold->tet_list_begin.next * and recursively reorients its neighbors as necessary until either * all the tetrahedra are consistently oriented, or it discovers that * the manifold is nonorientable. (In particular, the Orientation of * an orientable Triangulation will match the initial Orientation of * manifold->tet_list_begin.next, which is important in subdivide.c and * terse_triangulation.c.) orient() sets the manifold->orientability * field to oriented_manifold or nonorientable_manifold, as appropriate. * Its method for reorienting a tetrahedron is to swap the indices * of vertices 2 and 3, and adjust the relevant fields accordingly * (including the gluing fields of neighboring tetrahedra). * It is aware of the fact that some fields may not yet be set, * and doesn't try to modify data structures if they aren't present * (all it requires are the neighbor and gluing fields). * * If the manifold is orientable, then * * (1) All peripheral curves (i.e. the meridians and longitudes) * are transferred to the right_handed sheets of the orientation * double covers of the cusps. This makes their holonomies complex * analytic functions of the tetrahedron shapes, rather than * complex conjugates of complex analytic functions. (However, * the {meridian, longitude} pair may no longer be right-handed. * To fix that, call fix_peripheral_orientations().) * * (2) All edge_orientations are set to right_handed. * * * orient() and orient_edge_classes() may be called in either order. * * If orient() is called first, then * If the manifold is orientable, * orient() will set all edge_orientations to right_handed, and then * orient_edge_classes() will (redundantly) do the same thing. * If the manifold is nonorientable, * orient() won't set the edge_orientations, but * orient_edge_classes() will. * * If orient_edge_classes() is called first, then * If the manifold is orientable, * orient_edge_classes() will assign an arbitrary Orientation * to each EdgeClass, and then * orient() will overwrite it with the right_handed Orientation. * If the manifold is nonorientable, * orient_edge_classes() will assign an arbitrary Orientation * to each EdgeClass, and * orient() will preserve it. * * * orient() could be made available to the UI with no modifications * beyond moving the prototype. * * * reorient() reverses the orientation of all the Tetrahedra * in the Triangulation, by swapping VertexIndices 2 and 3 as described * above. If the manifold is orientable, reorient() also * transfers the peripheral curves to the right_handed sheets of the * double covers and sets all edge_orientations to right_handed, as * described above. It reverses the directions of all meridians, so the * peripheral curves will continue to adhere to the standard orientation * convention. reorient() is intended for oriented manifolds, but * nothing terrible will happen if you pass it a nonorientable manifold. * * fix_peripheral_orientations() makes sure each {meridian, longitude} * pairs obeys the right-hand rule. It should be called only for * orientable manifolds, typically following a call to orient(). * * Note to myself: Eventually I may want to make transfer_peripheral_curves() * responsible for making the peripheral curves adhere to the standard * orientation convention. If this is done, reorient() won't have to * explicitly change the directions of meridians. (However, this * change would require that orient() check whether Cusps are present.) */ #include "kernel.h" #include "kernel_namespace.h" static void reverse_orientation(Tetrahedron *tet); static void renumber_neighbors_and_gluings(Tetrahedron *tet); static void renumber_cusps(Tetrahedron *tet); static void renumber_peripheral_curves(Tetrahedron *tet); static void renumber_edge_classes(Tetrahedron *tet); static void renumber_shapes(Tetrahedron *tet); static void renumber_shape_histories(Tetrahedron *tet); static void renumber_one_part(ComplexWithLog edge_parameters[3]); static void swap_rows(int m[4][4], int a, int b); static void swap_columns(int m[4][4], int a, int b); static void swap_sheets(int m[2][4][4]); static void transfer_peripheral_curves(Triangulation *manifold); static void make_all_edge_orientations_right_handed(Triangulation *manifold); static void reverse_all_meridians(Triangulation *manifold); void orient( Triangulation *manifold) { /* * Pick an arbitrary initial Tetrahedron, * and try to extend its orientation to the whole manifold. */ extend_orientation(manifold, manifold->tet_list_begin.next); } void extend_orientation( Triangulation *manifold, Tetrahedron *initial_tet) { Tetrahedron **queue, *tet; int queue_first, queue_last; FaceIndex f; /* * Set all the tet->flag fields to FALSE, * to show that no Tetrahedra have been visited. */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) tet->flag = FALSE; /* * Tentatively assume the manifold is orientable. */ manifold->orientability = oriented_manifold; /* * Allocate space for a queue of pointers to the Tetrahedra. * Each Tetrahedron will appear on the queue exactly once, * so an array of length manifold->num_tetrahedra will be just right. */ queue = NEW_ARRAY(manifold->num_tetrahedra, Tetrahedron *); /* * Put the initial Tetrahedron on the queue, * and mark it as visited. */ queue_first = 0; queue_last = 0; queue[0] = initial_tet; queue[0]->flag = TRUE; /* * Start processing the queue. */ do { /* * Pull a Tetrahedron off the front of the queue. */ tet = queue[queue_first++]; /* * Look at the four neighboring Tetrahedra. */ for (f = 0; f < 4; f++) { /* * If the neighbor hasn't been visited... */ if (tet->neighbor[f]->flag == FALSE) { /* * ...reverse its orientation if necessary... */ if (parity[tet->gluing[f]] == orientation_reversing) reverse_orientation(tet->neighbor[f]); /* * ...mark it as visited... */ tet->neighbor[f]->flag = TRUE; /* * ...and put it on the back of the queue. */ queue[++queue_last] = tet->neighbor[f]; } /* * If the neighbor has been visited . . . */ else { /* * ...check whether its orientation is consistent. */ if (parity[tet->gluing[f]] == orientation_reversing) manifold->orientability = nonorientable_manifold; } } } /* * Keep going until either we discover the manifold is nonorientable, * or the queue is exhausted. */ while (manifold->orientability == oriented_manifold && queue_first <= queue_last); /* * Free the memory used for the queue. */ my_free(queue); /* * An "unnecessary" (but quick) error check. */ if (manifold->orientability == oriented_manifold && ( queue_first != manifold->num_tetrahedra || queue_last != manifold->num_tetrahedra - 1)) uFatalError("orient", "orient"); /* * Another error check. * We should have oriented a manifold before attempting to * compute the Chern-Simons invariant. */ if (manifold->CS_value_is_known || manifold->CS_fudge_is_known) uFatalError("orient", "orient"); /* * Respect the conventions for peripheral curves and * edge orientations in oriented manifolds. */ if (manifold->orientability == oriented_manifold) { transfer_peripheral_curves(manifold); make_all_edge_orientations_right_handed(manifold); } } /* * reverse_orientation() reverses the orientation of a Tetrahedron * by swapping the indices of vertices 2 and 3. It adjusts all * relevant fields, including the gluing fields of neighboring * tetrahedra. */ static void reverse_orientation( Tetrahedron *tet) { renumber_neighbors_and_gluings(tet); renumber_cusps(tet); renumber_peripheral_curves(tet); renumber_edge_classes(tet); renumber_shapes(tet); renumber_shape_histories(tet); } static void renumber_neighbors_and_gluings( Tetrahedron *tet) { Tetrahedron *temp_neighbor; Permutation temp_gluing; int i, j, d[4], temp_digit; Tetrahedron *nbr_tet; /* * Renumbering the neighbors is easy: we simply swap * neighbor[2] and neighbor[3]. */ temp_neighbor = tet->neighbor[2]; tet->neighbor[2] = tet->neighbor[3]; tet->neighbor[3] = temp_neighbor; /* * Renumbering the gluings is trickier, because three * changes are required: * * Change A: Swap gluing[2] and gluing[3]. * * Change B: Within each gluing of tet, swap the image of * vertex 2 and the image of vertex 3, e.g. 0312 -> 3012. * * Change C: For each gluing of a face (typically of a Tetrahedron * other than tet) that glues to tet, interchange * 2 and 3, e.g. 0312 -> 0213. */ /* * Change A: Swap gluing[2] and gluing[3]. */ temp_gluing = tet->gluing[2]; tet->gluing[2] = tet->gluing[3]; tet->gluing[3] = temp_gluing; /* * Changes B and C are carried out for each of the four gluings of tet. */ for (i = 0; i < 4; i++) { /* * Change B: Swap the image of vertex 2 and the image of vertex 3. */ /* * Unpack the digits of the gluing. */ for (j = 0; j < 4; j++) { d[j] = tet->gluing[i] & 0x3; tet->gluing[i] >>= 2; } /* * Swap the digits in positions 2 and 3. */ temp_digit = d[3]; d[3] = d[2]; d[2] = temp_digit; /* * Repack the digits. */ for (j = 4; --j >= 0; ) { tet->gluing[i] <<= 2; tet->gluing[i] += d[j]; } /* * Change C: Fix up the inverse of tet->gluing[i]. * * If tet->neighbor[i] != tet, we simply write the inverse of * tet->gluing[i] into the appropriate gluing field of the neighbor. * * If tet->neighbor[i] == tet, the simple approach doesn't work * because of the messy interaction between Changes B and C. * Instead, we exploit the fact that tet->gluing[i] is the inverse * of some other gluing of tet, and apply Change C directly to * tet->gluing[i] rather than its inverse. */ nbr_tet = tet->neighbor[i]; if (nbr_tet != tet) /* * Write the inverse directly. */ nbr_tet->gluing[EVALUATE(tet->gluing[i],i)] = inverse_permutation[tet->gluing[i]]; else { /* * Perform Change C on tet->gluing[i]. */ /* * Unpack the digits. */ for (j = 0; j < 4; j++) { d[j] = tet->gluing[i] & 0x3; tet->gluing[i] >>= 2; } /* * Swap 2 and 3 in the images. */ for (j = 0; j < 4; j++) switch (d[j]) { case 0: case 1: /* leave d[j] alone */ break; case 2: d[j] = 3; break; case 3: d[j] = 2; break; } /* * Repack the digits. */ for (j = 4; --j >= 0; ) { tet->gluing[i] <<= 2; tet->gluing[i] += d[j]; } } } } static void renumber_cusps( Tetrahedron *tet) { Cusp *temp_cusp; temp_cusp = tet->cusp[2]; tet->cusp[2] = tet->cusp[3]; tet->cusp[3] = temp_cusp; } static void renumber_peripheral_curves( Tetrahedron *tet) { int i, j; for (i = 0; i < 2; i++) { for (j = 0; j < 2; j++) { swap_rows (tet->curve[i][j], 2, 3); swap_columns(tet->curve[i][j], 2, 3); } swap_sheets(tet->curve[i]); } } static void renumber_edge_classes( Tetrahedron *tet) { EdgeClass *temp_edge_class; Orientation temp_edge_orientation; EdgeIndex i; temp_edge_class = tet->edge_class[1]; tet->edge_class[1] = tet->edge_class[2]; tet->edge_class[2] = temp_edge_class; temp_edge_class = tet->edge_class[3]; tet->edge_class[3] = tet->edge_class[4]; tet->edge_class[4] = temp_edge_class; for (i = 1; i < 5; i++) if (tet->edge_class[i] != NULL) { tet->edge_class[i]->incident_tet = tet; tet->edge_class[i]->incident_edge_index = i; } temp_edge_orientation = tet->edge_orientation[1]; tet->edge_orientation[1] = tet->edge_orientation[2]; tet->edge_orientation[2] = temp_edge_orientation; temp_edge_orientation = tet->edge_orientation[3]; tet->edge_orientation[3] = tet->edge_orientation[4]; tet->edge_orientation[4] = temp_edge_orientation; for (i = 0; i < 6; i++) tet->edge_orientation[i] = ! tet->edge_orientation[i]; } static void renumber_shapes( Tetrahedron *tet) { /* * Renumber the TetShapes iff they are actually present. */ int i, j; if (tet->shape[complete] != NULL) for (i = 0; i < 2; i++) /* i = complete, filled */ for (j = 0; j < 2; j++) /* j = ultimate, penultimate */ renumber_one_part(tet->shape[i]->cwl[j]); } static void renumber_one_part( ComplexWithLog edge_parameters[3]) { ComplexWithLog temp; int i; /* * Swap the indices on edges 1 and 2. */ temp = edge_parameters[1]; edge_parameters[1] = edge_parameters[2]; edge_parameters[2] = temp; /* * Invert the modulus of each edge parameter, but leave * the angles the same. */ for (i = 0; i < 3; i++) { edge_parameters[i].log.real = - edge_parameters[i].log.real; edge_parameters[i].rect = complex_exp(edge_parameters[i].log); } } static void renumber_shape_histories( Tetrahedron *tet) { int i; ShapeInversion *shape_inversion; for (i = 0; i < 2; i++) for ( shape_inversion = tet->shape_history[i]; shape_inversion != NULL; shape_inversion = shape_inversion->next) switch (shape_inversion->wide_angle) { case 0: shape_inversion->wide_angle = 0; break; case 1: shape_inversion->wide_angle = 2; break; case 2: shape_inversion->wide_angle = 1; break; } } static void swap_rows( int m[4][4], int a, int b) { int j, temp; for (j = 0; j < 4; j++) { temp = m[a][j]; m[a][j] = m[b][j]; m[b][j] = temp; } } static void swap_columns( int m[4][4], int a, int b) { int i, temp; for (i = 0; i < 4; i++) { temp = m[i][a]; m[i][a] = m[i][b]; m[i][b] = temp; } } static void swap_sheets( int m[2][4][4]) { int i, j, temp; for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) { temp = m[right_handed][i][j]; m[right_handed][i][j] = m[left_handed ][i][j]; m[left_handed ][i][j] = temp; } } /* * We want the peripheral curves of an oriented manifold to lie * on the right_handed sheets of the orientation double covers * of the cusps. transfer_peripheral_curves() adds the curves * from the left_handed sheet to the right_handed sheet, and * sets the contents of the left_handed sheet to zero. */ static void transfer_peripheral_curves( Triangulation *manifold) { Tetrahedron *tet; PeripheralCurve c; VertexIndex v; FaceIndex f; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (c = 0; c < 2; c++) for (v = 0; v < 4; v++) for (f = 0; f < 4; f++) { tet->curve[c][right_handed][v][f] += tet->curve[c][left_handed][v][f]; tet->curve[c][left_handed] [v][f] = 0; } } static void make_all_edge_orientations_right_handed( Triangulation *manifold) { Tetrahedron *tet; EdgeIndex e; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (e = 0; e < 6; e++) tet->edge_orientation[e] = right_handed; } void reorient( Triangulation *manifold) { Tetrahedron *tet; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) reverse_orientation(tet); if (manifold->orientability == oriented_manifold) { /* * The peripheral curves haven't gone anywhere, * but the sheets they are on are now considered * the left_handed sheets rather than the right_handed * sheets. So transfer them to what used to be the * left_handed sheets but are now the right_handed sheets. */ transfer_peripheral_curves(manifold); /* * To adhere to the orientation conventions for peripheral curves * (see the documentation at the top of peripheral_curves.c) * we must reverse the directions of all meridians. * * Note that it was the act of transferring the peripheral curves * from the left_handed to right_handed sheets -- note the reversal * of the Tetrahedra -- that caused the violation of the orientaiton * convention. In particular, curves in nonorientable manifold, even * on (double covers of) Klein bottle cusps, still respect the convention. */ reverse_all_meridians(manifold); /* * Adjust the edge orientations, too. */ make_all_edge_orientations_right_handed(manifold); } /* * The Chern-Simons invariant of the manifold will be negated, * and the fudge factor will be different. */ if (manifold->CS_value_is_known) { manifold->CS_value[ultimate] = - manifold->CS_value[ultimate]; manifold->CS_value[penultimate] = - manifold->CS_value[penultimate]; } compute_CS_fudge_from_value(manifold); } static void reverse_all_meridians( Triangulation *manifold) { Tetrahedron *tet; Cusp *cusp; int i, j, k; /* * Change the directions of all meridians. */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (i = 0; i < 2; i++) for (j = 0; j < 4; j++) for (k = 0; k < 4; k++) tet->curve[M][i][j][k] = - tet->curve[M][i][j][k]; /* * Negating the m coefficient of all Dehn fillings compensates for * the fact that we reversed the meridian, and gives us the same * (oriented) Dehn filling curve as before. However, this curve * will now wind clockwise around the core geodesics, relative to * the new orientation on the manifold. This causes a whole new * solution to be found to the gluing equations. To avoid this, * we reverse the direction of the Dehn filling curve (i.e. we * negate both the m and l coefficients). The net effect is that * we negate the l coefficient. * * This reversal of the Dehn filling curve is not really * necessary, and could be eliminated if it's ever causes problems. */ for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) cusp->l = - cusp->l; /* * Adjust all cusp_shapes. * (The current cusp_shape of a filled Cusp will be Zero, but that's OK.) */ for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) for (i = 0; i < 2; i++) /* i = initial, current */ cusp->cusp_shape[i].real = - cusp->cusp_shape[i].real; /* * Adjust the holonomies. * * Changing the orientation of the manifold negates the imaginary * parts of log(H(m)) and log(H(l)). * * But we also reversed the direction of the meridian, which * negates both the real and imaginary parts of log(H(m)), so * the net effect on log(H(m)) is that its real part is negated. */ for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) for (i = 0; i < 2; i++) /* i = ultimate, penultimate */ { cusp->holonomy[i][M].real = - cusp->holonomy[i][M].real; cusp->holonomy[i][L].imag = - cusp->holonomy[i][L].imag; } } void fix_peripheral_orientations( Triangulation *manifold) { Tetrahedron *tet; VertexIndex v; FaceIndex f; Cusp *cusp; Boolean reversed_meridian = FALSE; /* * This function should get called only for orientable manifolds. */ if (manifold->orientability != oriented_manifold) uFatalError("fix_peripheral_orientations", "orient"); /* * Compute the intersection number of the meridian and longitude. */ copy_curves_to_scratch(manifold, 0, FALSE); copy_curves_to_scratch(manifold, 1, FALSE); compute_intersection_numbers(manifold); /* * Reverse the meridian on cusps with intersection_number[L][M] == -1. */ /* which Tetrahedron */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) /* which ideal vertex */ for (v = 0; v < 4; v++) if (tet->cusp[v]->intersection_number[L][M] == -1) /* which side of the vertex */ for (f = 0; f < 4; f++) if (v != f) { tet->curve[M][right_handed][v][f] = - tet->curve[M][right_handed][v][f]; if (tet->curve[M][left_handed][v][f] != 0.0 || tet->curve[L][left_handed][v][f] != 0.0) uFatalError("fix_peripheral_orientations", "orient"); } /* * When we reverse the meridian we must also negate the meridional * Dehn filling coefficient in order to maintain the same (oriented) * Dehn filling curve as before. However, this Dehn filling curve * will wind clockwise around the core geodesics, relative to * the global orientation on the manifold (because the global * orientation disagrees with the local orientation we had been using * on the nonorientable manifold's torus cusp). This forces a whole * new solution to be found to the gluing equations. To avoid this, * we reverse the direction of the Dehn filling curve (i.e. we * negate both the m and l coefficients). The net effect is that * we negate the l coefficient. * * This reversal of the Dehn filling curve is not really * necessary, and could be eliminated if it's ever causes problems. */ for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) if (cusp->intersection_number[L][M] == -1) { reversed_meridian = TRUE; cusp->l = - cusp->l; } if( reversed_meridian ) uAcknowledge("Meridians have been reversed to ensure right-handed {M,L} pairs."); } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/peripheral_curves.c000644 000765 000024 00000133067 12377774107 022703 0ustar00babstaff000000 000000 /* * peripheral_curves.c * * * This file provides the function * * void peripheral_curves(Triangulation *manifold); * * which puts a meridian and longitude on each cusp. If the * manifold is oriented, the meridian and longitude adhere to * the usual orientation convention; this is, if you place your * right hand on the torus with your fingers pointing in the * direction of the meridian and your thumb pointing in the * direction of the longitude, then your palm will face the * cusp while the back of your hand faces the fat part of the * manifold. Note that this corresponds to the usual convention * for orienting meridians and longitudes on link complements. * * Even if the manifold isn't oriented, the peripheral curves * adhere to the standard orientation convention relative to * the orientation of each Cusp's orientation double cover (more * on this below). * * peripheral_curves() does not need to know the CuspTopology * ahead of time. It figures it out for itself and records the * result in the field cusp->topology. * * The remainder of this documentation will * * (1) Define the meridian and the longitude. * * (2) Describe the data structure used to store * meridians and longitudes. * * (3) Explain the algorithm which peripheral_curves() * uses to find meridians and longitudes. * * * (1) Definition of the meridian and the longitude. * * The meridian and the longitude of an orientable cusp are * any pair of simple closed curves which intersect exactly * once. If the manifold is orientable, they will adhere to * the orientation convention described above. peripheral_curves() * finds meridians and longitudes which are reasonably short * in the sense that they pass through a small number of * triangles in the triangulation of the boundary torus. * * The meridian and the longitude of a nonorientable cusp are * defined more precisely. There are exactly four nontrivial * simple closed curves on a Klein bottle, up to isotopy. I'd * like to provide a picture of them, but, alas, there's no way * to include a picture in an ASCII file, so I must ask you to * draw your own picture as you read along. Define the * Klein bottle as a cylinder with ends glued. Parameterize * the cylinder by (x, theta), where -1 <= x <= +1 and theta * is defined mod 2pi as for a circle. To make the Klein * bottle, identify the cylinder's ends via the mapping * (-1, theta) -> (+1, -theta). With this notation, the four * simple closed curves on the Klein bottle are * * A: theta = 0 * B: theta = pi * C: (theta = pi/2) U (theta = - pi/2) * D: x = 0 * * The longitude will be either curve A or curve B. Thus, * counting orientation, there are four possible longitudes. * (Note: as explained in section (2) immediately following, * the longitude of a Klein bottle is actually stored as its * preimage in the Klein bottle's double cover.) * The meridian will be curve D. Curve D cannot be oriented, * because it's isotopic to its inverse. * * The holonomies of the longitude and meridian of a Klein * bottle have some very special properties, which are * discussed in the comment at the top of holonomy.c. * * * (2) How meridians and longitudes are stored. * * The meridian and longitude are stored not on the boundary * component itself, but on its orientation double cover. * The double cover of a Klein bottle is a torus. The double * cover of a torus is the union of two tori, only one of * which is actually used (the right_handed one, if the * manifold is oriented). The reason we want to always * store curves on tori and never on Klein bottles directly * is that the fundamental group of the torus is abelian: * isotopy classes of curves can be recovered from homological * information. The reason only the right_handed sheet * of the cover is used when the manifold is oriented is * that the holonomy of a Dehn filling curve on the left_handed * sheet is not a complex analytic function of the tetrahedron * shapes, but rather the complex conjugate of such a function; * we need complex analytic functions to compute the * derivative matrix in the complex version of Newton's * method used to find hyperbolic structures for oriented * manifolds. * * Each torus is the union of triangular cross sections of * ideal vertices. Each ideal vertex of each Tetrahedron * contributes two triangles, one with the right_handed * orientation and one with the left_handed orientation. * Visualize the right-handed triangle as containing a * counter-clockwise oriented circle, and the left-handed * triangle as containing a clockwise-oriented circle, as viewed * from infinity relative to the right_handed orientation of the * Tetrahedron. The triangles piece together so that orientations * of neighboring circles agree: if two neighboring Tetrahedra * have opposite orientations, then the right_handed triangles * of one connect with the left_handed triangles of the other; * if the two tetrahedra have the same orientation, then the * right_handed triangles of one match to the right_handed triangles * of the other, and left_handed to left_handed. Note that * the components of the orientation double cover of the Cusps * are all oriented, not just orientable (use the rule which * says to view the circles so that all appear counterclockwise * as seen from infinity). * * The meridian and longitude are specified by their * intersection numbers with the triangular cross sections. * tet->curve[M][right_handed][v][f] is the net number of * times the meridian crosses side f of the right_handed * triangle at vertex v, and similarly for the * longitude and the left_handed triangle. * A positive intersection number means the curve is * entering the triangle. The sides of the triangle are * numbered according to the faces of the tetrahedron * containing them. E.g., the sides of the triangle at * vertex 2 will be numbered 0, 1 and 3. The array vt_side[][] * in tables.c lets you refer to the sides of a triangle by * the integers 0, 1, 2, if this suits your purposes. * Note that these intersection numbers are sufficient to * reconstruct a simple closed curve up to isotopy. * * The longitude of the Klein bottle is a special case in * that its preimage in the double cover is connected. It * is stored as the complete preimage. All other curves are * stored as one component of their two-component preimages. * By the way, the two candidates for the longitude (curves * A and B in the discussion above) lift to the same curve in * the double cover. * * * (3) How peripheral_curves() finds the meridian and the * longitude. * * There are three main steps: * * Compute a fundamental domain for the boundary component. * * Identify it as a torus or Klein bottle. * * Find the longitude and meridian. * * The plan for finding a fundamental domain is * conceptually simple: initialize the domain as a single * triangular vertex cross section, and then expand it outward * by adding neighboring triangles in a breadth-first * fashion, until the domain fills the entire cusp. * * This plan is implemented with the PerimeterPiece data * structure. At each step, a circular linked list of * PerimeterPieces defines the boundary of the domain. * (Each PerimeterPiece corresponds to one edge of one * triangle on the perimeter of the domain.) The algorithm * is to keep going around the perimeter, adding new * PerimeterPieces as the domain expands across triangles * which were not previously included. * * While this process goes on, a second data structure is * being created. An array of 4 Extra fields attached to * each tetrahedron (one Extra field for each vertex) records * * (a) whether the vertex has been included in the domain, * * and, if so, * * (b) which other vertex (the "parent vertex") was * responsible for including it. * * The result is a tree structure, with the root at the * original triangle and the leaves at the perimeter. In * a moment we'll see how this tree is used to create the * longitudes and meridians. * * Once the domain fills the entire cusp, we check whether * there are any vertices of order one on the perimeter, and * if so we remove them by cancelling the adjacent * PerimeterPieces. * * Conceptually (but NOT in the code) we imagine removing * vertices of order two, thereby fusing the adjacent edges * into one. This must yield a fundamental domain which is * either a square or a hexagon. Here's the proof. Assume * a 2n-gon has pairs of sides glued so as to form a torus * or a Klein bottle, and assume all vertices have order * three or greater. Since the 2n-gon itself has 2n vertices, * there can be at most 2n/3 vertices in the resulting * cell-decomposition of the torus or Klein bottle. * Compute the Euler characteristic: * * 0 = Euler characteristic * = vertices - edges + faces * <= 2n/3 - n + 1 * = 1 - n/3 * * => n <= 3 * => the 2n-gon is a bigon, a square or a hexagon * * A case-by-case analysis reveals that the only possible * gluings are * * square hexagon * ______________________ * torus | abAB | abcABC | * |---------+------------| * Klein bottle | abAb | abcAcb | * | aabb | aabccB | * ---------------------- * * where the notation is what you would expect. I wish I could * provide an illustration of each gluing, but in platform- * independent text file this just isn't possible. So I ask * that you make your own illustration of each gluing. * * It is now straightforward to apply the definitions of the * longitude and meridian to each gluing. The details are * spelled out in the documentation contained in the function * find_meridian_and_longitude() and, especially, the functions * it calls. */ #include "kernel.h" #include "kernel_namespace.h" typedef struct PerimeterPiece PerimeterPiece; struct extra { /* * Has this vertex been included in the fundamental domain? */ Boolean visited; /* * Which vertex of which tetrahedron is its parent in the * tree structure? * (parent_tet == NULL at the root.) */ Tetrahedron *parent_tet; VertexIndex parent_vertex; /* * Which side of this vertex faces the parent vertex? * Which side of the parent vertex faces this vertex? */ FaceIndex this_faces_parent, parent_faces_this; /* * What is the orientation of this vertex in the * fundamental domain? */ Orientation orientation; /* * Which PerimeterPiece, if any, is associated with * a given edge of the triangle at this vertex? * (As you might expect, its_perimeter_piece[i] refers * to the edge of the triangle contained in face i of * the Tetrahedron.) */ PerimeterPiece *its_perimeter_piece[4]; /* * When computing intersection numbers in * adjust_Klein_cusp_orientations() we want to allow for * the possibility that the Triangulation's scratch_curves * are already in use, so we copy them to scratch_curve_backup, * and restore them when we're done. */ int scratch_curve_backup[2][2][2][4][4]; }; struct PerimeterPiece { Tetrahedron *tet; VertexIndex vertex; FaceIndex face; Orientation orientation; /* How the PerimeterPiece sees the tetrahedron */ Boolean checked; PerimeterPiece *mate; /* the PerimeterPiece this one is glued to . . . */ GluingParity gluing_parity; /* . . . and how they match up */ PerimeterPiece *next; /* the neighbor in the counterclockwise direction */ PerimeterPiece *prev; /* the neighbor in the clockwise direction */ }; /* * The following enum lists the six possible gluing * patterns for a torus or Klein bottle. */ typedef int GluingPattern; enum { abAB, /* square torus */ abcABC, /* hexagonal torus */ abAb, /* standard square Klein bottle */ aabb, /* P^2 # P^2 square Klein bottle */ abcAcb, /* standard hexagonal Klein bottle */ aabccB /* P^2 # P^2 hexagonal Klein bottle */ }; static void zero_peripheral_curves(Triangulation *manifold); static void attach_extra(Triangulation *manifold); static void free_extra(Triangulation *manifold); static void initialize_flags(Triangulation *manifold); static Boolean cusp_has_curves(Triangulation *manifold, Cusp *cusp); static void do_one_cusp(Triangulation *manifold, Cusp *cusp); static void pick_base_tet(Triangulation *manifold, Cusp *cusp, Tetrahedron **base_tet, VertexIndex *base_vertex); static void set_up_perimeter(Tetrahedron *base_tet, VertexIndex base_vertex, PerimeterPiece **perimeter_anchor); static void expand_perimeter(PerimeterPiece *perimeter_anchor); static void find_mates(PerimeterPiece *perimeter_anchor); static void simplify_perimeter(PerimeterPiece **perimeter_anchor); static void find_meridian_and_longitude(PerimeterPiece *perimeter_anchor, CuspTopology *cusp_topology); static void advance_to_next_side(PerimeterPiece **pp); static GluingPattern determine_gluing_pattern(PerimeterPiece *side[6], int num_sides); static void do_torus(PerimeterPiece *side[6]); static void do_standard_Klein_bottle(PerimeterPiece *side[6], int num_sides); static void do_P2P2_Klein_bottle(PerimeterPiece *side[6], int num_sides); static void trace_curve(PerimeterPiece *start, PeripheralCurve trace_which_curve, TraceDirection trace_direction, Boolean use_opposite_orientation); static void free_perimeter(PerimeterPiece *perimeter_anchor); static void adjust_Klein_cusp_orientations(Triangulation *manifold); static void reverse_meridians_where_necessary(Triangulation *manifold); static void backup_scratch_curves(Triangulation *manifold); static void restore_scratch_curves(Triangulation *manifold); void peripheral_curves( Triangulation *manifold) { Cusp *cusp; zero_peripheral_curves(manifold); attach_extra(manifold); initialize_flags(manifold); for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) if (cusp->is_finite == FALSE) /* 97/2/4 Added to accomodate finite vertices. */ do_one_cusp(manifold, cusp); adjust_Klein_cusp_orientations(manifold); free_extra(manifold); } void peripheral_curves_as_needed( Triangulation *manifold) { /* * Add peripheral curves only to cusps for which all the * tet->curve[][][][] fields are zero. */ Cusp *cusp; attach_extra(manifold); initialize_flags(manifold); for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) if (cusp->is_finite == FALSE && cusp_has_curves(manifold, cusp) == FALSE) do_one_cusp(manifold, cusp); adjust_Klein_cusp_orientations(manifold); free_extra(manifold); } static void zero_peripheral_curves( Triangulation *manifold) { Tetrahedron *tet; int i, j, k, l; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) for (k = 0; k < 4; k++) for (l = 0; l < 4; l++) tet->curve[i][j][k][l] = 0; } static void attach_extra( Triangulation *manifold) { Tetrahedron *tet; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) { /* * Make sure no other routine is using the "extra" * field in the Tetrahedron data structure. */ if (tet->extra != NULL) uFatalError("attach_extra", "peripheral_curves"); /* * Attach the locally defined struct extra. */ tet->extra = NEW_ARRAY(4, Extra); } } static void free_extra( Triangulation *manifold) { Tetrahedron *tet; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) { /* * Free the struct extra. */ my_free(tet->extra); /* * Set the extra pointer to NULL to let other * modules know we're done with it. */ tet->extra = NULL; } } static void initialize_flags( Triangulation *manifold) { Tetrahedron *tet; VertexIndex v; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (v = 0; v < 4; v++) tet->extra[v].visited = FALSE; } static Boolean cusp_has_curves( Triangulation *manifold, Cusp *cusp) { Tetrahedron *tet; VertexIndex v; FaceIndex f; PeripheralCurve c; Orientation h; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (v = 0; v < 4; v++) if (tet->cusp[v] == cusp) for (f = 0; f < 4; f++) if (f != v) for (c = 0; c < 2; c++) /* c = M, L */ for (h = 0; h < 2; h++) /* h = right_handed, left_handed */ if (tet->curve[c][h][v][f] != 0) return TRUE; return FALSE; } static void do_one_cusp( Triangulation *manifold, Cusp *cusp) { Tetrahedron *base_tet = NULL; VertexIndex base_vertex = 0; PerimeterPiece *perimeter_anchor; pick_base_tet(manifold, cusp, &base_tet, &base_vertex); set_up_perimeter(base_tet, base_vertex, &perimeter_anchor); expand_perimeter(perimeter_anchor); find_mates(perimeter_anchor); simplify_perimeter(&perimeter_anchor); find_meridian_and_longitude(perimeter_anchor, &cusp->topology); free_perimeter(perimeter_anchor); } static void pick_base_tet( Triangulation *manifold, Cusp *cusp, Tetrahedron **base_tet, VertexIndex *base_vertex) { Tetrahedron *tet; VertexIndex v; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (v = 0; v < 4; v++) if (tet->cusp[v] == cusp) { *base_tet = tet; *base_vertex = v; return; } /* * If pick_base_tet() didn't find any vertex belonging * to the specified cusp, we're in big trouble. */ uFatalError("pick_base_tet", "peripheral_curves"); } static void set_up_perimeter( Tetrahedron *base_tet, VertexIndex base_vertex, PerimeterPiece **perimeter_anchor) { int i; PerimeterPiece *pp[3]; base_tet->extra[base_vertex].visited = TRUE; base_tet->extra[base_vertex].parent_tet = NULL; base_tet->extra[base_vertex].orientation = right_handed; for (i = 0; i < 3; i++) pp[i] = NEW_STRUCT(PerimeterPiece); for (i = 0; i < 3; i++) { pp[i]->tet = base_tet; pp[i]->vertex = base_vertex; pp[i]->face = vt_side[base_vertex][i]; pp[i]->orientation = right_handed; pp[i]->checked = FALSE; pp[i]->next = pp[(i+1)%3]; pp[i]->prev = pp[(i+2)%3]; } *perimeter_anchor = pp[0]; } /* * expand_perimeter() starts with the initial triangular * perimeter found by set_up_perimeter() and expands it in * breadth-first fashion. It keeps going around and around * the perimeter, pushing it outwards wherever possible. * To know when it's done, it keeps track of the number * of PerimeterPieces which have not yet been been checked. * When this number is zero, it's done. */ static void expand_perimeter( PerimeterPiece *perimeter_anchor) { int num_unchecked_pieces; PerimeterPiece *pp, *new_piece; Permutation gluing; Tetrahedron *nbr_tet; VertexIndex nbr_vertex; FaceIndex nbr_back_face, nbr_left_face, nbr_right_face; Orientation nbr_orientation; for (num_unchecked_pieces = 3, pp = perimeter_anchor; num_unchecked_pieces; pp = pp->next) if (pp->checked == FALSE) { gluing = pp->tet->gluing[pp->face]; nbr_tet = pp->tet->neighbor[pp->face]; nbr_vertex = EVALUATE(gluing, pp->vertex); if (nbr_tet->extra[nbr_vertex].visited) { pp->checked = TRUE; num_unchecked_pieces--; } else { /* * Extend the tree to the neighboring vertex. */ nbr_back_face = EVALUATE(gluing, pp->face); if (parity[gluing] == orientation_preserving) nbr_orientation = pp->orientation; else nbr_orientation = ! pp->orientation; if (nbr_orientation == right_handed) { nbr_left_face = remaining_face[nbr_vertex][nbr_back_face]; nbr_right_face = remaining_face[nbr_back_face][nbr_vertex]; } else { nbr_left_face = remaining_face[nbr_back_face][nbr_vertex]; nbr_right_face = remaining_face[nbr_vertex][nbr_back_face]; } nbr_tet->extra[nbr_vertex].visited = TRUE; nbr_tet->extra[nbr_vertex].parent_tet = pp->tet; nbr_tet->extra[nbr_vertex].parent_vertex = pp->vertex; nbr_tet->extra[nbr_vertex].this_faces_parent = nbr_back_face; nbr_tet->extra[nbr_vertex].parent_faces_this = pp->face; nbr_tet->extra[nbr_vertex].orientation = nbr_orientation; /* * Extend the perimeter across the neighboring * vertex. The new PerimeterPiece is added on * the right side of the old one, so that the * pp = pp->next step in the loop moves us past * both the old and new perimeter pieces. This * causes the perimeter to expand uniformly in * all directions. */ new_piece = NEW_STRUCT(PerimeterPiece); new_piece->tet = nbr_tet; new_piece->vertex = nbr_vertex; new_piece->face = nbr_right_face; new_piece->orientation = nbr_orientation; new_piece->checked = FALSE; new_piece->next = pp; new_piece->prev = pp->prev; pp->prev->next = new_piece; pp->tet = nbr_tet; pp->vertex = nbr_vertex; pp->face = nbr_left_face; pp->orientation = nbr_orientation; pp->checked = FALSE; /* unchanged */ pp->next = pp->next; /* unchanged */ pp->prev = new_piece; /* * Increment the count of unchecked pieces. */ num_unchecked_pieces++; } } } static void find_mates( PerimeterPiece *perimeter_anchor) { PerimeterPiece *pp; Tetrahedron *nbr_tet; Permutation gluing; VertexIndex nbr_vertex; FaceIndex nbr_face; /* * First tell the tetrahedra about the PerimeterPieces. */ pp = perimeter_anchor; do { pp->tet->extra[pp->vertex].its_perimeter_piece[pp->face] = pp; pp = pp->next; } while (pp != perimeter_anchor); /* * Now let each PerimeterPiece figure out who its mate is. */ pp = perimeter_anchor; do { nbr_tet = pp->tet->neighbor[pp->face]; gluing = pp->tet->gluing[pp->face]; nbr_vertex = EVALUATE(gluing, pp->vertex); nbr_face = EVALUATE(gluing, pp->face); pp->mate = nbr_tet->extra[nbr_vertex].its_perimeter_piece[nbr_face]; pp->gluing_parity = (pp->orientation == pp->mate->orientation) == (parity[gluing] == orientation_preserving) ? orientation_preserving : orientation_reversing; pp = pp->next; } while (pp != perimeter_anchor); } static void simplify_perimeter( PerimeterPiece **perimeter_anchor) { PerimeterPiece *pp, *stop, *dead0, *dead1; /* * The plan here is to cancel adjacent edges of the form * * --o--->---o---<---o-- * * Travelling around the perimeter looking for such * edges is straightforward. For each PerimeterPiece (pp), * we check whether it will cancel with its lefthand * neighbor (pp->next). If it doesn't cancel, we advance * one step to the left (pp = pp->next). If it does cancel, * we move back one step to the right, to allow further * cancellation in case the previously cancelled edges were * part of a sequence * * . . . --o--->>---o--->---o---<---o---<<---o-- . . . * * One could no doubt devise a clever and efficient * way of deciding when to stop (readers are invited * to submit solutions), but to save wear and tear on * the programmer's brain, the present algorithm simply * keeps going until it has made a complete trip around * the perimeter without doing any cancellation. The * variable "stop" records the first noncancelling * PerimeterPiece which was encountered after the most * recent cancellation. Here's the loop in skeleton form: * * pp = perimeter_anchor; * stop = NULL; * * while (pp != stop) * { * if (pp cancels with its neighbor) * { * pp = pp->prev; * stop = NULL; * } * else (pp doesn't cancel with its neighbor) * { * if (stop == NULL) * stop = pp; * pp = pp->next; * } * } */ pp = *perimeter_anchor; stop = NULL; while (pp != stop) { /* * Check whether pp and the PerimeterPiece to * its left will cancel each other. */ if (pp->next == pp->mate && pp->gluing_parity == orientation_preserving) { /* * Note the addresses of the PerimeterPieces * which cancel . . . */ dead0 = pp; dead1 = pp->next; /* * . . . then remove them from the perimeter. */ dead0->prev->next = dead1->next; dead1->next->prev = dead0->prev; /* * Move pp back to the previous PerimeterPiece to * allow further cancellation. */ pp = dead0->prev; /* * Deallocate the cancelled PerimeterPieces. */ my_free(dead0); my_free(dead1); /* * We don't want to leave *perimeter_anchor * pointing to a dead PerimeterPiece, so set * it equal to a piece we know is still alive. */ *perimeter_anchor = pp; /* * We just did a cancellation, so set the * variable stop to NULL. */ stop = NULL; } else { /* * If this is the first noncancelling PerimeterPiece * after a sequence of one or more cancellations, * record its address in the variable stop. */ if (stop == NULL) stop = pp; /* * Advance to the next PerimeterPiece. */ pp = pp->next; } } } static void find_meridian_and_longitude( PerimeterPiece *perimeter_anchor, CuspTopology *cusp_topology) { PerimeterPiece *pp, *side[6]; int i, num_sides; /* * As explained in the documentation at the top of * this file, the fundamental domain for the cusp * will be either a square or a hexagon. Go around * the perimeter, recording the first PerimeterPiece * on each side of the square or hexagon. */ pp = perimeter_anchor; for (i = 0; i < 6; i++) { advance_to_next_side(&pp); side[i] = pp; } /* * Is it a square or a hexagon? */ if (side[0] == side[4]) num_sides = 4; else num_sides = 6; /* * Split into cases, according to how the square or * hexagon's edges are glued. The six types of gluings * are explained in the documentation at the top of * this file. */ switch (determine_gluing_pattern(side, num_sides)) { case abAB: case abcABC: do_torus(side); *cusp_topology = torus_cusp; break; case abAb: case abcAcb: do_standard_Klein_bottle(side, num_sides); *cusp_topology = Klein_cusp; break; case aabb: case aabccB: do_P2P2_Klein_bottle(side, num_sides); *cusp_topology = Klein_cusp; break; } } /* * advance_to_next_side() advances the pointer *pp to * point to the first PerimeterPiece on the next side * of the square or hexagon, travelling counterclockwise. */ static void advance_to_next_side( PerimeterPiece **pp) { PerimeterPiece *p0, *p1; /* * Let p0 and p1 point to the given PerimeterPiece * and its mate. */ p0 = *pp; p1 = (*pp)->mate; /* * Move along the perimeter until p0 and p1 part company, * or until their relative orientation changes. */ if (p0->gluing_parity == orientation_preserving) do { p0 = p0->next; p1 = p1->prev; } while ( p0->mate == p1 && p0->gluing_parity == orientation_preserving); else /* (*pp)->gluing_parity == orientation_reversing */ do { p0 = p0->next; p1 = p1->next; } while ( p0->mate == p1 && p0->gluing_parity == orientation_reversing); /* * p0 now points to the first PerimeterPiece in the next * edge of the square or hexagon. Write its value into *pp. */ *pp = p0; } static GluingPattern determine_gluing_pattern( PerimeterPiece *side[6], int num_sides) { int i; /* * Please draw pictures of the six possible gluings * shown in the table in the documentation at the * top of this file. They will show that the logic * of this function, as summarized in the following * skeleton code, is correct. * * if (there is an orientation reversing side) * if (there are two adjacent, matching, orientation reversing sides) * if (num_sides == 4) * return(P^2 # P^2 square Klein bottle) * else (num_sides == 6) * return(P^2 # P^2 hexagonal Klein bottle) * else * if (num_sides == 4) * return(standard square Klein bottle) * else (num_sides == 6) * return(standard hexagonal Klein bottle) * else (all sides are orientation preserving) * if (num_sides == 4) * return(square torus) * else (num_sides == 6) * return(hexagonal torus) */ /* * Look for an orientation reversing side. * If one is found, check whether it's adjacent to its mate. */ for (i = 0; i < num_sides; i++) if (side[i]->gluing_parity == orientation_reversing) { if (side[i]->mate == side[(i+1)%num_sides] || side[i]->mate == side[(i-1+num_sides)%num_sides]) { if (num_sides == 4) return aabb; /* P^2 # P^2 square Klein bottle */ else return aabccB; /* P^2 # P^2 hexagonal Klein bottle */ } else { if (num_sides == 4) return abAb; /* standard square Klein bottle */ else return abcAcb; /* standard hexagonal Klein bottle */ } } /* * No orientation reversing side was found. * The surface is a torus. */ if (num_sides == 4) return abAB; /* square torus */ else return abcABC; /* hexagonal torus */ } static void do_torus( PerimeterPiece *side[6] /* int num_sides */) { /* * The following calls to trace_curve() will always produce * a meridian and longitude which intersect exactly once. * If the manifold is orientable, they will adhere to the * orientation convention described at the top of this file. * (The proof of this relies on the fact that * set_up_perimeter() views the base vertex with the * right_handed orientation. Thus in an oriented manifold * all vertices are viewed with the right_handed orientation.) */ trace_curve(side[0], L, trace_backwards, FALSE); trace_curve(side[0]->mate, L, trace_forwards, FALSE); trace_curve(side[1], M, trace_backwards, FALSE); trace_curve(side[1]->mate, M, trace_forwards, FALSE); } static void do_standard_Klein_bottle( PerimeterPiece *side[6], int num_sides) { int i; /* * Let the meridian connect the unique pair of * orientation_preserving sides. */ for (i = 0; i < num_sides; i++) if (side[i]->gluing_parity == orientation_preserving) { trace_curve(side[i], M, trace_backwards, FALSE); trace_curve(side[i]->mate, M, trace_forwards, FALSE); break; } /* * Let the longitude connect a pair of orientation_reversing * sides. Store it as its complete preimage in the double * cover, as explained in the documentation at the top of * this file. */ for (i = 0; i < num_sides; i++) if (side[i]->gluing_parity == orientation_reversing) { trace_curve(side[i], L, trace_backwards, FALSE); trace_curve(side[i]->mate, L, trace_forwards, FALSE); trace_curve(side[i], L, trace_backwards, TRUE); trace_curve(side[i]->mate, L, trace_forwards, TRUE); break; } } static void do_P2P2_Klein_bottle( PerimeterPiece *side[6], int num_sides) { int i; PerimeterPiece *side0a, *side0b, *side1a, *side1b; /* * Let the longitude connect either pair of * orientation_reversing sides, and store it as its * complete preimage in the double cover, as in * do_standard_Klein_bottle() above. */ for (i = 0; i < num_sides; i++) if (side[i]->gluing_parity == orientation_reversing) { trace_curve(side[i], L, trace_backwards, FALSE); trace_curve(side[i]->mate, L, trace_forwards, FALSE); trace_curve(side[i], L, trace_backwards, TRUE); trace_curve(side[i]->mate, L, trace_forwards, TRUE); break; } /* * The meridian is trickier. If you refer to pictures of * the aabb and aabccB Klein bottles and the definition * of the meridian, you will see the meridian is obtained * by gluing each orientation reversing side to the mate * of the opposite side of the square or hexagon. For * global consistency, the two pieces of the meridian * must be drawn on different preimages of the fundamental * domain (in the torus double cover). */ /* * Look for a side followed by its mate. */ for (i = 0; i < num_sides; i++) if (side[i]->mate == side[(i+1)%num_sides]) { /* * Name the four relevant sides. */ side0a = side[ i ]; side0b = side[(i + 1) %num_sides]; side1a = side[(i + num_sides/2)%num_sides]; side1b = side[(i + 1 + num_sides/2)%num_sides]; /* * Trace out the meridian. */ trace_curve(side0a, M, trace_backwards, FALSE); trace_curve(side1b, M, trace_forwards, FALSE); trace_curve(side1a, M, trace_backwards, TRUE); trace_curve(side0b, M, trace_forwards, TRUE); break; } } /* * trace_curve() traces out a curve on a cusp, beginning * at start and following the tree structure in Extra * back to the base vertex. The result is written directly * into the Tetrahedra's meridian or longitude fields, * according to whether trace_which_curve is M * or L. The curve is directed toward the * perimeter if trace_direction is trace_backwards, and * toward the base vertex if trace_direction is trace_forwards. * The orientation specified by start is used iff * use_opposite_orientation is FALSE. * * To trace a curve from one point on the perimeter to another, * you make two calls to trace_curve(), each of which traces * from the perimeter to the center. Note that some cancellation * is possible, so the final curve need not pass through the * center. The final curve will be the unique shortest path * in the tree structure. */ static void trace_curve( PerimeterPiece *start, PeripheralCurve trace_which_curve, TraceDirection trace_direction, Boolean use_opposite_orientation) { int out_sign, in_sign, (*curve)[4][4]; Tetrahedron *tet, *next_tet; VertexIndex vertex, next_vertex; Extra *tet_extra, *next_extra; /* * Based on the direction of the curve, decide which * sign (+1 or -1) is required where the curve leaves * a triangle going towards the perimeter, and which * is required where it is going towards the center. */ if (trace_direction == trace_backwards) { out_sign = -1; in_sign = +1; } else { out_sign = +1; in_sign = -1; } /* * Record where the curve hits the perimeter. */ curve = start->tet->curve[trace_which_curve]; curve[use_opposite_orientation ^ start->orientation] [start->vertex] [start->face] += out_sign; /* * Now trace back to the root. */ tet = start->tet; vertex = start->vertex; tet_extra = &tet->extra[vertex]; while (tet_extra->parent_tet != NULL) { /* * Note where the curve leaves the present vertex . . . */ curve = tet->curve[trace_which_curve]; curve[use_opposite_orientation ^ tet_extra->orientation] [vertex] [tet_extra->this_faces_parent] += in_sign; /* * . . . and where it enters the parent vertex. */ next_tet = tet_extra->parent_tet; next_vertex = tet_extra->parent_vertex; next_extra = &next_tet->extra[next_vertex]; curve = next_tet->curve[trace_which_curve]; curve[use_opposite_orientation ^ next_extra->orientation] [next_vertex] [tet_extra->parent_faces_this] += out_sign; /* * Move on to the parent vertex. */ tet = next_tet; vertex = next_vertex; tet_extra = next_extra; } } static void free_perimeter( PerimeterPiece *perimeter_anchor) { PerimeterPiece *pp, *dead; pp = perimeter_anchor; do { dead = pp; pp = pp->next; my_free(dead); } while (pp != perimeter_anchor); } static void adjust_Klein_cusp_orientations( Triangulation *manifold) { /* * As explained at the top of this file, a Cusp's peripheral curves * live in the its orientation double cover. When I first wrote this * file, I didn't worry about the orientation of peripheral curves * in nonorientable manifolds. Subsequently it became clear that * they should have the standard orientation relative to the Cusp's * (oriented, not just orientable) orientation double cover. In * the case of a torus Cusp, the peripheral curves live in one * (arbitrarily chosen) component of the orientation double cover; * in the case of a Klein bottle Cusp, the orientation double cover * is connected. * * Fortunately, it's very easy to check whether the peripheral curves * have the standard orientation, and to correct them if necessary. * The definition of the standard orientation for peripheral curves on * a torus is that when the fingers of your right hand point in the * direction of the meridian and your thumb points in the direction * of the longitude, the palm of your hand should face the cusp and * the back of your hand should face the fat part of the manifold. * Combining this with the definition of the intersection number * found at the top of intersection_numbers.c reveals that the * intersection number of the longitude and the meridian (in that * order) should be +1. If it happens to be -1, we must reverse * the meridian. */ /* * If the manifold is oriented, then the peripheral curves will * already have the correct orientation. In fact, they will lie * on the right handed sheet of the Cusp's orientation double * cover, relative to the orientation of the manifold. */ if (manifold->orientability == oriented_manifold) return; /* * The scratch curves might already be in use, so let's make * a copy of whatever's there. */ backup_scratch_curves(manifold); /* * Copy the peripheral curves to both sets of scratch_curve fields. */ copy_curves_to_scratch(manifold, 0, FALSE); copy_curves_to_scratch(manifold, 1, FALSE); /* * Compute their intersection numbers. */ compute_intersection_numbers(manifold); /* * Restore whatever used to be in the scratch_curves. */ restore_scratch_curves(manifold); /* * On Cusps where the intersection number of the longitude and * meridian is -1, reverse the meridian. */ reverse_meridians_where_necessary(manifold); } static void reverse_meridians_where_necessary( Triangulation *manifold) { Tetrahedron *tet; int i, j, k; /* which Tetrahedron */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) /* which ideal vertex */ for (i = 0; i < 4; i++) if (tet->cusp[i]->intersection_number[L][M] == -1) /* which side of the vertex */ for (j = 0; j < 4; j++) if (i != j) /* which sheet (right_handed or left_handed) */ for (k = 0; k < 2; k++) tet->curve[M][k][i][j] = - tet->curve[M][k][i][j]; } static void backup_scratch_curves( Triangulation *manifold) { Tetrahedron *tet; int g, h, i, j, k; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (g = 0; g < 2; g++) for (h = 0; h < 2; h++) for (i = 0; i < 2; i++) for (j = 0; j < 4; j++) for (k = 0; k < 4; k++) tet->extra->scratch_curve_backup[g][h][i][j][k] = tet->scratch_curve[g][h][i][j][k]; } static void restore_scratch_curves( Triangulation *manifold) { Tetrahedron *tet; int g, h, i, j, k; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (g = 0; g < 2; g++) for (h = 0; h < 2; h++) for (i = 0; i < 2; i++) for (j = 0; j < 4; j++) for (k = 0; k < 4; k++) tet->scratch_curve[g][h][i][j][k] = tet->extra->scratch_curve_backup[g][h][i][j][k]; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/positioned_tet.c000644 000765 000024 00000006312 12377774107 022202 0ustar00babstaff000000 000000 /* * positioned_tet.c * * This file provides the following functions for working with PositionedTets: * * void veer_left(PositionedTet *ptet); * void veer_right(PositionedTet *ptet); * void veer_backwards(PositionedTet *ptet); * Boolean same_positioned_tet(PositionedTet *ptet0, PositionedTet *ptet1); * void set_left_edge(EdgeClass *edge, PositionedTet *ptet); * * Their use is described in kernel_prototypes.h. */ #include "kernel.h" #include "kernel_namespace.h" void veer_left( PositionedTet *ptet) { Permutation left_gluing; FaceIndex temp; left_gluing = ptet->tet->gluing[ptet->left_face]; ptet->tet = ptet->tet->neighbor[ptet->left_face]; temp = ptet->near_face; ptet->near_face = EVALUATE(left_gluing, ptet->left_face); ptet->left_face = EVALUATE(left_gluing, temp); ptet->right_face = EVALUATE(left_gluing, ptet->right_face); ptet->bottom_face = EVALUATE(left_gluing, ptet->bottom_face); if (parity[left_gluing] == orientation_reversing) ptet->orientation = ! ptet->orientation; } void veer_right( PositionedTet *ptet) { Permutation right_gluing; FaceIndex temp; right_gluing = ptet->tet->gluing[ptet->right_face]; ptet->tet = ptet->tet->neighbor[ptet->right_face]; temp = ptet->near_face; ptet->near_face = EVALUATE(right_gluing, ptet->right_face); ptet->right_face = EVALUATE(right_gluing, temp); ptet->left_face = EVALUATE(right_gluing, ptet->left_face); ptet->bottom_face = EVALUATE(right_gluing, ptet->bottom_face); if (parity[right_gluing] == orientation_reversing) ptet->orientation = ! ptet->orientation; } void veer_backwards( PositionedTet *ptet) { Permutation near_gluing; FaceIndex temp; near_gluing = ptet->tet->gluing[ptet->near_face]; ptet->tet = ptet->tet->neighbor[ptet->near_face]; temp = ptet->left_face; ptet->left_face = EVALUATE(near_gluing, ptet->right_face); ptet->right_face = EVALUATE(near_gluing, temp); ptet->near_face = EVALUATE(near_gluing, ptet->near_face); ptet->bottom_face = EVALUATE(near_gluing, ptet->bottom_face); if (parity[near_gluing] == orientation_reversing) ptet->orientation = ! ptet->orientation; } Boolean same_positioned_tet( PositionedTet *ptet0, PositionedTet *ptet1) { return ( ptet0->tet == ptet1->tet && ptet0->near_face == ptet1->near_face && ptet0->left_face == ptet1->left_face && ptet0->right_face == ptet1->right_face); /* * If three faces match, so must the fourth, and so must the orientation. */ } void set_left_edge( EdgeClass *edge, PositionedTet *ptet) { ptet->tet = edge->incident_tet; ptet->near_face = one_face_at_edge[edge->incident_edge_index]; ptet->left_face = other_face_at_edge[edge->incident_edge_index]; ptet->right_face = remaining_face[ptet->left_face][ptet->near_face]; ptet->bottom_face = remaining_face[ptet->near_face][ptet->left_face]; ptet->orientation = right_handed; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/positioned_tet.h000644 000765 000024 00000001763 12377774107 022214 0ustar00babstaff000000 000000 /* * positioned_tet.h * * The PositionedTet data structure records the position in which a * Tetrahedron is currently being considered. The file positioned_tet.c * contains routines for working with PositionedTets. * * Imagine a tetrahedron sitting on a table with one of its faces * facing toward you. The face on the table is bottom_face and the one * facing toward you is near_face. The faces facing away from you * are left_face and right_face. * * The orientation field specifies whether the numbering on the * tetrhedron is right_handed or left_handed when viewed in this position. */ #ifndef _positioned_tet_ #define _positioned_tet_ #include "SnapPea.h" #include "kernel_typedefs.h" #include "triangulation.h" #include "kernel_namespace.h" typedef struct { Tetrahedron *tet; FaceIndex near_face, left_face, right_face, bottom_face; Orientation orientation; } PositionedTet; #include "end_namespace.h" #endif regina-4.96/engine/snappea/kernel/precision.c000644 000765 000024 00000003475 12377774107 021153 0ustar00babstaff000000 000000 /* * precision.c * * This file contains the functions * * int decimal_places_of_accuracy(double x, double y); * int complex_decimal_places_of_accuracy(Complex x, Complex y); * * which are used within the kernel to determine how many decimal * places of accuracy the doubles (resp. Complexes) x and y have in common. * Typically x and y will be two estimates of the same computed quantity * (e.g. the volume of a manifold as computed at the last and the * next-to-the-last iterations of Newton's method in * hyperbolic_structures.c), and decimal_places_of_accuracy() * will be used to tell the user interface how many decimal places * should be printed. We compute the number of decimal places of * accuracy instead of the number of significant figures, because * this is what printf() requires in its formatting string. */ #include "kernel.h" #include "kernel_namespace.h" int decimal_places_of_accuracy( Real x, Real y) { int digits; if (x == y) { if (x == 0.0) digits = REAL_DIG; else digits = REAL_DIG - (int) ceil(log10(fabs(x))); } else digits = - (int) ceil(log10(fabs(x - y))); /* * Typically the difference between the computed values * of a quantity at the penultimate and ultimate iterations * of Newton's method is a little less than the true error. * So we fudge a bit. */ digits -= 4; if (digits < 0) digits = 0; return digits; } int complex_decimal_places_of_accuracy( Complex x, Complex y) { int real_precision, imag_precision; real_precision = decimal_places_of_accuracy(x.real, y.real); imag_precision = decimal_places_of_accuracy(x.imag, y.imag); return MIN(real_precision, imag_precision); } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/README.txt000644 000765 000024 00000001600 12400001733 020445 0ustar00babstaff000000 000000 SnapPea Kernel -------------- This directory contains portions of the SnapPea kernel, as downloaded from http://www.math.uic.edu/t3m/. This is currently synced with the variant of the SnapPea kernel bundled with SnapPy 2.2 (26 Jun 2014). This variant includes additional patches not included in the original SnapPea kernel. SnapPy and the corresponding SnapPea kernel are distributed under the terms of the GNU General Public License, version 2 or any later version, as published by the Free Software Foundation. The full text of this license can be found in the file LICENSE.txt in Regina's top-level source directory. The SnapPea kernel was written by Jeff Weeks, and SnapPy was written by Marc Culler, Nathan Dunfield, and others. M. Culler, N. M. Dunfield, and J. R. Weeks. SnapPy, a computer program for studying the geometry and topology of 3-manifolds, http://snappy.computop.org . regina-4.96/engine/snappea/kernel/real_type.h000644 000765 000024 00000000112 12377774107 021132 0ustar00babstaff000000 000000 #ifndef _REAL_TYPE_ #define _REAL_TYPE_ #include "double_SnapPy.h" #endif regina-4.96/engine/snappea/kernel/shortest_cusp_basis.c000644 000765 000024 00000025124 12377774107 023241 0ustar00babstaff000000 000000 /* * shortest_cusp_basis.c * * This file provides the functions * * Complex cusp_modulus( Complex cusp_shape); * * void shortest_cusp_basis( Complex cusp_shape, * MatrixInt22 basis_change); * * Complex transformed_cusp_shape( Complex cusp_shape, * CONST MatrixInt22 basis_change); * * void install_shortest_bases( Triangulation *manifold); * * cusp_modulus() accepts a cusp_shape (longitude/meridian) and returns * the cusp modulus. Loosely speaking, the cusp modulus is defined as * (second shortest translation)/(shortest translation); it is a * complex number z lying in the region |Re(z)| <= 1/2 && |z| >= 1. * If z lies on the boundary of this region, we choose it so that * Re(z) >= 0. * * shortest_cusp_basis() accepts a cusp_shape (longitude/meridian) and * computes the 2 x 2 integer matrix which transforms the old basis * (u, v ) = (meridian, longitude) to the new basis * (u', v') = (shortest, second shortest). That is, * * | u' | | | | u | * | | = | basis_change | | | * | v' | | | | v | * * 2 x 1 2 x 2 2 x 1 * complex integer complex * vector matrix vector * * (u', v') is such that v'/u' is the cusp modulus defined above. * * Occasionally the shortest or second shortest curve won't be * unique. In most cases the conventions for the cusp modulus stated * above (in particular the convention that Re(z) >= 0 when z is on * the boundary of the fundamental domain) serve to uniquely specify * (u', v') in spite of the nonuniqueness of lengths. The only * exceptions are the hexagonal lattice, where three different curves * all have minimal length, and the square lattice, where two different * curves have minimal length. In these cases the ambiguity is not * resolved, and the choice of (u', v') may be machine dependent. * * transformed_cusp_shape() accepts a cusp_shape and a basis_change, * and computes the shape of the cusp relative to the basis (u', v') * defined by * * | u' | | | | u | * | | = | basis_change | | | * | v' | | | | v | * * (u', v') need not be the (shortest, second shortest) basis. * * install_shortest_bases() installs the (shortest, second shortest) * basis on each torus Cusp of manifold. It does not change the bases * on Klein bottle cusps. As explained for shortest_cusp_basis() * above, the (shortest, second shortest) is not well defined for a * hexagonal lattice, and the results may be machine dependent. * * * shortest_cusp_basis() uses the following algorithm. In principle * u and v could be any two translations which generate the fundamental * group of a torus, although in shortest_cusp_basis(), u is initially 1 * and v is initially the cusp_shape. * * do * { * * if (|u + v| < |u|) * u += v; * * if (|u - v| < |u|) * u -= v; * * if (|v + u| < |v|) * v += u; * * if (|v - u| < |v|) * v -= u; * * } while (still making progress); * * if (|u| > |v|) * replace (u, v) with (v, -u) * * if (Im(v/u) < 0) * flag an error -- the original orientation was wrong * * if (v/u is on the boundary of the fundamental domain described above) * make sure Re(v/u) >= 0 * * Theorem. The above algorithm computes the * (shortest, second shortest) basis. * * Proof. The angle between u and v must be between pi/3 and 2 pi/3; * otherwise the length of the projection of v onto u would be * |v| cos(theta) > |u| cos(pi/3) = |u|/2, and we would have added * +-u to v, thereby shortening v. This shows that |Re(v/u)| <= 1/2. * Because we chose |u| <= |v|, |v/u| >= 1. Therefore v/u lies within * the fundamental domain described above. It is also easy to see that * v is the shortest translation which is linearly independent of u. * The reason is that the row of lattice points 2v + nu is a distance * at least 2 |v| sin(theta) >= 2 |u| sin(pi/3) = sqrt(3) |u| away from * the row 0v + nu. */ #include "kernel.h" #include "kernel_namespace.h" #define EPSILON (1e5 * DBL_EPSILON) #define MAXITER 20000 Complex cusp_modulus( Complex cusp_shape) { MatrixInt22 basis_change; shortest_cusp_basis(cusp_shape, basis_change); return transformed_cusp_shape(cusp_shape, basis_change); } void shortest_cusp_basis( Complex cusp_shape, MatrixInt22 basis_change) /* basis_change is an output variable here */ { Complex u, v, u_plus_v, u_minus_v, temp, cusp_modulus; Real mod_u, /* These are the complex moduli */ mod_v, /* of the preceding variables. */ mod_u_plus_v, mod_u_minus_v; int i, j, temp_int, iterations; Boolean progress; /* * For an explanation of this algorithm, see the documentation above. */ /* * Make sure cusp_shape is nondegenerate. */ if (fabs(cusp_shape.imag) < EPSILON) { for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) basis_change[i][j] = 0; return; } u = One; v = cusp_shape; mod_u = complex_modulus(u); mod_v = complex_modulus(v); for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) basis_change[i][j] = (i == j); iterations = 0; do { progress = FALSE; u_plus_v = complex_plus(u,v); mod_u_plus_v = complex_modulus(u_plus_v); if (mod_u - mod_u_plus_v > EPSILON) { u = u_plus_v; mod_u = mod_u_plus_v; for (j = 0; j < 2; j++) basis_change[0][j] += basis_change[1][j]; progress = TRUE; } else if (mod_v - mod_u_plus_v > EPSILON) { v = u_plus_v; mod_v = mod_u_plus_v; for (j = 0; j < 2; j++) basis_change[1][j] += basis_change[0][j]; progress = TRUE; } u_minus_v = complex_minus(u,v); mod_u_minus_v = complex_modulus(u_minus_v); if (mod_u - mod_u_minus_v > EPSILON) { u = u_minus_v; mod_u = mod_u_minus_v; for (j = 0; j < 2; j++) basis_change[0][j] -= basis_change[1][j]; progress = TRUE; } else if (mod_v - mod_u_minus_v > EPSILON) { v = complex_negate(u_minus_v); mod_v = mod_u_minus_v; for (j = 0; j < 2; j++) basis_change[1][j] -= basis_change[0][j]; progress = TRUE; } iterations += 1; } while ( progress && (iterations < MAXITER) ); if (mod_u > mod_v + EPSILON) { temp = u; u = v; v = complex_negate(temp); for (j = 0; j < 2; j++) { temp_int = basis_change[0][j]; basis_change[0][j] = basis_change[1][j]; basis_change[1][j] = - temp_int; } } cusp_modulus = complex_div(v,u); if (cusp_modulus.imag < 0){ /* Things have gone very wrong, bailing with garbage answer */ cusp_modulus.imag = (Real)0.0; cusp_modulus.real = (Real)0.0; } if (cusp_modulus.real < -0.5 + EPSILON) { /* * Do an extra v += u. */ cusp_modulus.real = 0.5; for (j = 0; j < 2; j++) basis_change[1][j] += basis_change[0][j]; } if (complex_modulus(cusp_modulus) < 1.0 + EPSILON) { if (cusp_modulus.real < -EPSILON) { /* * Replace (u,v) with (v,-u). */ cusp_modulus.real = - cusp_modulus.real; for (j = 0; j < 2; j++) { temp_int = basis_change[0][j]; basis_change[0][j] = basis_change[1][j]; basis_change[1][j] = - temp_int; } } } } Complex transformed_cusp_shape( Complex cusp_shape, CONST MatrixInt22 basis_change) /* basis_change is an input variable here */ { Complex u, v; u = complex_plus( complex_real_mult( basis_change[0][0], One ), complex_real_mult( basis_change[0][1], cusp_shape ) ); v = complex_plus( complex_real_mult( basis_change[1][0], One ), complex_real_mult( basis_change[1][1], cusp_shape ) ); if (complex_modulus(u) < EPSILON) return Infinity; else return complex_div(v,u); } void install_shortest_bases( Triangulation *manifold) { Cusp *cusp; MatrixInt22 *change_matrices; int i, j; /* * Allocate an array to store the change of basis matrices. */ change_matrices = NEW_ARRAY(manifold->num_cusps, MatrixInt22); /* * Compute the change of basis matrices. */ for (cusp = manifold->cusp_list_begin.next; cusp != &manifold->cusp_list_end; cusp = cusp->next) /* MC 2013-03-06 I changed this so it finds shortest curves on every complete torus cusp, using the *current* shapes. Previously, it would find shortest curves on *every* torus cusp, using the *initial* shapes, i.e. the shapes from the original unfilled hyperbolic structure. This meant that changes in the geometry of unfilled cusps were ignored when other cusps were filled. */ if (cusp->topology == torus_cusp && cusp->is_complete ) shortest_cusp_basis( cusp->cusp_shape[current], change_matrices[cusp->index]); else for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) change_matrices[cusp->index][i][j] = (i == j); /* * Install the change of basis matrices. */ if (change_peripheral_curves(manifold, change_matrices) != func_OK) uFatalError("install_shortest_bases", "shortest_cusp_basis"); /* * Free the array used to store the change of basis matrices. */ my_free(change_matrices); } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/simplify_triangulation.c000644 000765 000024 00000272566 12377774107 023765 0ustar00babstaff000000 000000 /* * simplify_triangulation.c * * This file contains the following low-level routines for locally * modifying a triangulation * * FuncResult cancel_tetrahedra(EdgeClass *edge, EdgeClass **where_to_resume, int *num_tetrahedra_ptr); * FuncResult three_to_two(EdgeClass *edge, EdgeClass **where_to_resume, int *num_tetrahedra_ptr); * FuncResult two_to_three(Tetrahedron *tet0, FaceIndex f, int *num_tetrahedra_ptr); * * as well as the following high-level routines which call them: * * void basic_simplification(Triangulation *manifold); * void randomize_triangulation(Triangulation *manifold); * * It also includes the low-level routine * * void one_to_four(Tetrahedron *tet, int *num_tetrahedra_ptr, int new_cusp_index); * * which is not used by basic_simplification() or randomize_triangulation(), * but is called from canonize_part_2.c. * * The low-level routines are as follows * * cancel_tetrahedra() cancels two Tetrahedra which share * a common edge of order 2. * * three_to_two() replaces three Tetrahedra surrounding a common * edge with two Tetrahedra sharing a common face. * * two_to_three() replaces two Tetrahedra sharing a common face * with three Tetrahedra surrounding a common edge. * * one_to_four() replaces one Tetrahedron with four Tetrahedra * meeting at a point. * * If an operation cannot be performed because of a topological or * geometric obstruction, the function does nothing and returns func_failed. * Otherwise, it performs the operation and returns func_OK. * * The function one_to_four() will always succeed, and therefore returns * void. It introduces a finite vertex at the center of the Tetrahedron, * and therefore cannot be used when a hyperbolic structure is present. * * The three_to_two(), two_to_three() and one_to_four() operations each * correspond to a projection of a 4-simplex. * * For further details, please see the comments preceding each low-level * function. * * * In practice, other SnapPea routines will most likely call the * high-level functions basic_simplification() and randomize_triangulation(). * * basic_simplification() first does easy simplifications * (namely retriangulating neighborhoods of EdgeClasses of * order 1, 2 and 3 to reduce the number of Tetrahedra whenever * possible, and retriangulating suspended pentagons using five * Tetrahedra instead of six), and then retriangulates octahedra * (choosing a different one of the three possible axes for the * subdivision into four Tetrahedra) in hopes of making further * easy simplifications possible. * * randomize_triangulation() randomizes the Triangulation, and then * resimplifies it. * * basic_simplification() and randomize_triangulation() may be called * for manifolds with or without a hyperbolic structure present. * The final Triangulation may depend on whether or not the hyperbolic * structure is present, because when a hyperbolic structure is present * the low-level routines will refuse to create degenerate Tetrahedra. * * Most routines in SnapPea keep track of edge angles "mod 0" rather * than just "mod 2 pi", so that, e.g., a ComplexWithLog with * log.imag equal to (3/2) pi is different than one with log.imag * equal to (-1/2) pi. Unfortunately, the mod 0 angles for a given * Triangulation are somewhat arbitrary, in the sense that the following * procedure converts one mod 0 solution to a different mod 0 solution. * * Pick an EdgeClass ec in the Triangulation, and consider all the * Tetrahedra incident to it. If the incident edges don't all belong * to distinct Tetrahedra, work in the universal cover, so that the * Tetrahedra will at least appear distinct. For each Tetrahedron, * call the angle incident to the EdgeClass ec gamma, and call the * opposite angle gamma as well (they will of course be equal, due to * the symmetry of the ideal tetrahedron). Call one remaining pair * of opposite edges alpha, and the other pair beta. Make the choice * of alphas and betas consistent for all the Tetrahedra incident to * the EdgeClass ec; that is, each alpha of one Tetrahedron should * be incident to a beta of an adjacent Tetrahedron. Now add 2 pi i * to the log of each alpha edge angle, and subtract 2 pi i from the * log of each beta edge angle. Note that * * (1) The sum of the logs of the edge angles remains pi i for * each Tetrahedron. * * (2) The sum of the logs of the angles surrounding each EdgeClass * remains 2 pi i. * * (3) The holonomies of the cusps are unaltered. (At least in the * generic case -- I haven't thought through what happens when * the Tetrahedra incident to the EdgeClass ec are not all distinct.) * * The point of all this is that the mod 0 edge angles in a Triangulation * are not uniquely defined. If all the Tetrahedra are positively * oriented, then one typically expects to find a solution with mod 0 * edge angles in the range [0, pi], but if some of the Tetrahedra * are negatively oriented, then the choice of edge angles becomes * murkier. * * When I first started writing the low-level routines in this file * (i.e. two_to_three(), three_to_two() and cancel_tetrahedra()) * I naively expected to keep track of the mod 0 edge angles. This * was no problem in the three_to_two() move. It was a little more * difficult in the two_to_three() move because some arbitrary choices * were involved, and I couldn't see how to prove that the angles sums * would be preserved both at EdgeClasses and in each Tetrahedron. * The scheme broke down entirely in cancel_tetrahedra(), because * a pair of allegedly cancelling angles could differ by 2 pi i. * One could correct the problem locally, but only at the risk of * creating a solution whose edge angles differed from the "preferred" * ones by multiples of 2 pi i, as described above. Given that * * (1) I couldn't see how to simplify the mod 0 angles in any * reasonable and canonical way, and * * (2) We are mainly interested in solutions with positively * oriented Tetrahedra, or at worst with angles in the * range [(-1/2) pi, (3/2) pi], * * I decided that the low-level routines in this file should only * keep track of the mod 2 pi angles, choosing values in the * range [(-1/2) pi, (3/2) pi]. Just before returning, * basic_simplification() calls polish_solution() (that's polish, * not Polish). In the generic case (when the mod 0 angles are * valid, but the TetShapes have lost some accuracy) the effect of * polish_solution() is to recover the lost accuracy, without * substantially changing the solution. In the exceptional case * that the edge angles don't add up correctly around a Tetrahedron * or EdgeClass, polish_solution() will find an entirely new * solution to the gluing equations. * * randomize_triangulation() calls basic_simplification(), so its * solutions also get polished. * * 97/2/3 Modified to strip off the geometric structure (if any) * at the start of basic_simplification() and randomize_triangulation(), * and (if there was a geometric structure) recompute it at the end. * The old system was working fine for hyperbolic manifolds, but now that * SnapPea is working with degenerate solutions (to split along normal * surfaces) one wants to be able to randomize and simplify them too. * 98/5/20 Modified *not* to strip off the geometric structure * when the cusp_nbhd_position is present. The low-level routines * need the hyperbolic structure to maintain the cusp_nbhd_position. * * 97/2/4 Modified to handle Triangulations containing finite vertices. * The 4-1 move, in which four tetrahedra surrounding a common finite * vertex are replaced by a single tetrahedron, is handled implicitly * as a 3-2 move (on one of the edge classes incident to the finite * vertex) followed by a 2-0 move on a pair of tetrahedra having three * faces and a finite vertex in common. The code in cancel_tetrahedra() * was modified to accomodate this. When the finite vertex is removed, * a gap remains in the (negative) numbering of the Cusps structures * for finite vertices, but this isn't a problem. */ #include "kernel.h" #include /* needed for rand() */ #include "kernel_namespace.h" /* * ORDER_FOUR_ITERATIONS_IN_SIMPLIFY tells how many times * basic_simplification() should pass unsuccessfully down * the list of EdgeClasses before giving up. */ #define ORDER_FOUR_ITERATIONS_IN_SIMPLIFY 6 /* * RANDOMIZATION_MULTIPLE tells how long randomize_triangulation() * should keep randomizing before it resimplifies the manifold. * It will attempt RANDOMIZATION_MULTIPLE * manifold->num_tetrahedra * two-to-three moves, each followed by some rudimentary resimplification * to avoid wasting time in degenerate situations. */ #define RANDOMIZATION_MULTIPLE 4 static Tetrahedron *get_tet(Triangulation *manifold, int desired_index); static void check_for_cancellation(Triangulation *manifold); static Boolean easy_simplification(Triangulation *manifold); static FuncResult remove_edge_of_order_one(EdgeClass *edge, EdgeClass **where_to_resume, int *num_tetrahedra_ptr); static Boolean this_way_works(Tetrahedron *tet, FaceIndex left_face, FaceIndex right_face, FaceIndex bottom_face); static FuncResult cancel_tetrahedra_with_finite_vertex(Tetrahedron *tet, VertexIndex finite_vertex, EdgeClass *edge, EdgeClass **where_to_resume, int *num_tetrahedra_ptr); static FuncResult edges_of_order_four(EdgeClass *edge, EdgeClass **where_to_resume, int *num_tetrahedra_ptr); static FuncResult try_adjacent_fours(Tetrahedron *tet0, FaceIndex f0, FaceIndex f1, EdgeClass **where_to_resume, int *num_tetrahedra_ptr); static FuncResult create_new_order_four(EdgeClass *edge, EdgeClass **where_to_resume, int *num_tetrahedra_ptr); static Boolean four_tetrahedra_are_distinct(PositionedTet ptet); static void set_inverse_neighbor_and_gluing(Tetrahedron *tet, FaceIndex f); void basic_simplification( Triangulation *manifold) { SolutionType original_solution_type[2]; int iter; EdgeClass *edge, *where_to_resume; Boolean hyperbolic_structure_was_removed; /* * 97/2/3 Strip off the geometric structure if there is one. * * 98/5/20 Oops. We don't want to strip off the hyperbolic * structure if the cusp_nbhd_position is present, because the * low-level routines need the hyperbolic structure to maintain * cusp_nbhd_position. */ if (manifold->tet_list_begin.next->cusp_nbhd_position == NULL) { original_solution_type[complete] = manifold->solution_type[complete]; original_solution_type[filled] = manifold->solution_type[filled]; remove_hyperbolic_structures(manifold); hyperbolic_structure_was_removed = TRUE; } else hyperbolic_structure_was_removed = FALSE; /* * First do all the easy simplifications, namely removing * EdgeClasses of order 1, 2 and 3 when possible, and * retriangulating suspended pentagons with five Tetrahedra * instead of six. */ easy_simplification(manifold); /* * Go down the list retriangulating the octahedra surrounding * EdgeClasses of order 4, in the hope of creating new, more * useful EdgeClasses of order 4. Keep doing this until we've * gone through the list ORDER_FOUR_ITERATIONS_IN_SIMPLIFY times * with no further progress. * * The operation of the inner loop is complicated by the * appearance and disappearance of EdgeClasses as the * algorithm proceeds. To avoid possible infinite loops, * and also to avoid possible "resonance" phenomena, we * pseudorandomly decide whether or not to perform each * potential retriangulation we encounter. */ for (iter = 0; iter < ORDER_FOUR_ITERATIONS_IN_SIMPLIFY; iter++) for (edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) if ((rand() & 3) > 0 /* proceed with probability 3/4 */ && create_new_order_four(edge, &where_to_resume, &manifold->num_tetrahedra) == func_OK) { if (easy_simplification(manifold) == TRUE) { iter = -1; break; } else edge = where_to_resume; } /* * Clean up. * * 97/2/3 If we trashed the tet shapes, reinitialize * them and then call polish_hyperbolic_structure(). Obviously * polish_hyperbolic_structure() will be recomputing the geometric * structure from scratch, not just "polishing" it. */ tidy_peripheral_curves(manifold); if (hyperbolic_structure_was_removed && original_solution_type[complete] != not_attempted) { manifold->solution_type[complete] = original_solution_type[complete]; manifold->solution_type[filled] = original_solution_type[filled]; initialize_tet_shapes(manifold); polish_hyperbolic_structures(manifold); } /* * The Chern-Simons invariant of the manifold is still the * same, but the fudge factor may have changed. */ compute_CS_fudge_from_value(manifold); } void randomize_triangulation( Triangulation *manifold) { SolutionType original_solution_type[2]; int count; Boolean hyperbolic_structure_was_removed; /* * 97/2/3 Strip off the geometric structure if there is one. * * 98/5/20 Oops. We don't want to strip off the hyperbolic * structure if the cusp_nbhd_position is present, because the * low-level routines need the hyperbolic structure to maintain * cusp_nbhd_position. */ if (manifold->tet_list_begin.next->cusp_nbhd_position == NULL) { original_solution_type[complete] = manifold->solution_type[complete]; original_solution_type[filled] = manifold->solution_type[filled]; remove_hyperbolic_structures(manifold); hyperbolic_structure_was_removed = TRUE; } else hyperbolic_structure_was_removed = FALSE; /* * Randomize the triangulation, doing only minimal * simplifications along the way. The minimal simplifications * are crucial -- otherwise the algorithm would create, * say, a pair of potentially cancelling Tetrahedra, and * then waste all it's remaining efforts making the union * of those two Tetrahedra more and more complex. * * By the way, not all the calls to two_to_three() will * succeed (e.g. because some Tetrahedra may be glued to * themselves), but that's OK. */ for (count = RANDOMIZATION_MULTIPLE * manifold->num_tetrahedra; --count >= 0; ) if (two_to_three( get_tet(manifold, rand() % manifold->num_tetrahedra), rand() % 4, &manifold->num_tetrahedra) == func_OK) check_for_cancellation(manifold); /* * Resimplify the manifold. * basic_simplification() will tidy up the peripheral curves, * recompute the hyperbolic structure (if one is present), * and recompute the CS_fudge. */ if (hyperbolic_structure_was_removed && original_solution_type[complete] != not_attempted) { manifold->solution_type[complete] = original_solution_type[complete]; manifold->solution_type[filled] = original_solution_type[filled]; initialize_tet_shapes(manifold); /* unnecessary, but robust */ } basic_simplification(manifold); } static Tetrahedron *get_tet( Triangulation *manifold, int desired_index) { int i; Tetrahedron *tet; /* * Return a pointer to the i-th Tetrahedron on the list, * with implicit numbering 0 through (num_tetrahedra - 1). */ for (i = 0, tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; i++, tet = tet->next) if (i == desired_index) return tet; /* * If we get to here, something went wrong. */ uFatalError("get_tet", "simplify_triangulation"); /* * The C++ compiler would like a return value, even though * we never return from the uFatalError() call. */ return NULL; } static void check_for_cancellation( Triangulation *manifold) { Boolean progress; EdgeClass *edge, *where_to_resume; /* * This function is similar to easy_simplification() (see below), * except that it checks only for EdgeClasses of order 1 or 2. */ do { progress = FALSE; for (edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) switch (edge->order) { case 1: if (remove_edge_of_order_one(edge, &where_to_resume, &manifold->num_tetrahedra) == func_OK) { progress = TRUE; edge = where_to_resume; } break; case 2: if (cancel_tetrahedra(edge, &where_to_resume, &manifold->num_tetrahedra) == func_OK) { progress = TRUE; edge = where_to_resume; } break; default: break; } } while (progress == TRUE); } /* * easy_simplification() removes edges of order 1, 2 and 3 * whenever possible, and simplifies the neighborhoods of adjacent * edges of order 4 when the six incident Tetrahedra are distinct. * * easy_simplification() returns TRUE if it simplifies the * Triangulation, FALSE otherwise. * * create_new_order_four() undertakes more daring operations * with EdgeClasses of order 4. */ static Boolean easy_simplification( Triangulation *manifold) { Boolean progress, triangulation_was_simplified; EdgeClass *edge, *where_to_resume; /* * Our plan is to keep going down the list of EdgeClasses, * removing EdgeClasses of order 1, 2 or 3 whenever possible, * and retriangulating suspended pentagons with five Tetrahedra * instead of six. When no further progress can be made, we're done. * * The low-level routines set the variable where_to_resume to point * to some valid EdgeClass. This allows the for(;;) loop to continue * down the list, rather than restarting at the beginning each time * a simplification occurs. (If only one EdgeClass is deleted, * where_to_resume points to its predecessor.) * * Technical comment: This function would run a tiny bit faster * if the EdgeClasses were shuffled about on various queues, * as in the old snappea, but the present system is simpler. */ triangulation_was_simplified = FALSE; do { progress = FALSE; for (edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) switch (edge->order) { case 1: if (remove_edge_of_order_one(edge, &where_to_resume, &manifold->num_tetrahedra) == func_OK) { progress = TRUE; triangulation_was_simplified = TRUE; edge = where_to_resume; } break; case 2: if (cancel_tetrahedra(edge, &where_to_resume, &manifold->num_tetrahedra) == func_OK) { progress = TRUE; triangulation_was_simplified = TRUE; edge = where_to_resume; } break; case 3: if (three_to_two(edge, &where_to_resume, &manifold->num_tetrahedra) == func_OK) { progress = TRUE; triangulation_was_simplified = TRUE; edge = where_to_resume; } break; case 4: if (edges_of_order_four(edge, &where_to_resume, &manifold->num_tetrahedra) == func_OK) { progress = TRUE; triangulation_was_simplified = TRUE; edge = where_to_resume; } break; default: break; } } while (progress == TRUE); return triangulation_was_simplified; } static FuncResult remove_edge_of_order_one( EdgeClass *edge, EdgeClass **where_to_resume, int *num_tetrahedra_ptr) { Tetrahedron *tet; FaceIndex left_face, right_face, bottom_face; /* * remove_edge_of_order_one() contains no explicit low-level * retriangulation. Instead, each call to remove_edge_of_order_one() * calls two_to_three() to increase the order of EdgeClass *edge from * one to two, and then calls cancel_tetrahedra() to remove *edge. * Because two_to_three() increases the number of Tetrahedra by * one and cancel_tetrahedra() decreases it by two, there is a net * loss of one Tetrahedron. * * remove_edge_of_order_one() checks ahead of time whether the * calls to two_to_three() and cancel_tetrahedra() will be able * to succeed; if not (e.g. because of an embedded annulus), * remove_edge_of_order_one() does nothing and returns func_failed. * * The new EdgeClass created in the call to two_to_three() has * its order reduced to one in the call to cancel_tetrahedra(). * Thus, remove_edge_of_order_one() always leave a new EdgeClass * of order one. Eventually remove_edge_of_order_one() will be * blocked by an annulus. Typically this annulus is trivial, * and opposite the EdgeClass of order 1 there is an EdgeClass of * order two, whose removal (by an independent call to * cancel_tetrahedra()) also destroys the EdgeClass of order 1. * * I'd like to draw some illustrations, but it just isn't possible * in a text-only file. So I'll leave it as an exercise for the * reader to illustrate what happens in the successive calls * to remove_edge_of_order_one(). */ /* * Label the Tetrahedron and the two faces incident to the * EdgeClass of order one. */ tet = edge->incident_tet; left_face = one_face_at_edge[edge->incident_edge_index]; right_face = other_face_at_edge[edge->incident_edge_index]; /* * EdgeClasses of order 1 should never occur when a hyperbolic * structure is present. */ if (tet->shape[complete] != NULL) uFatalError("remove_edge_of_order_one", "simplify_triangulation"); /* * Let bottom_face be a candidate face for performing the * two-to-three move. Check ahead of time whether the calls * to two-to-three() and cancel_tetrahedra() will succeed. */ if (this_way_works(tet, left_face, right_face, remaining_face[left_face][right_face]) == TRUE) bottom_face = remaining_face[left_face][right_face]; else if (this_way_works(tet, left_face, right_face, remaining_face[right_face][left_face]) == TRUE) bottom_face = remaining_face[right_face][left_face]; else return func_failed; /* * Call two_to_three() and cancel_tetrahedra(). */ if ( two_to_three(tet, bottom_face, num_tetrahedra_ptr) == func_failed || edge->order != 2 || cancel_tetrahedra(edge, where_to_resume, num_tetrahedra_ptr) == func_failed ) uFatalError("remove_edge_of_order_one", "simplify_triangulation"); return func_OK; } static Boolean this_way_works( Tetrahedron *tet, FaceIndex left_face, FaceIndex right_face, FaceIndex bottom_face) { Tetrahedron *tet1; FaceIndex left1, right1, bottom1; EdgeClass *edgeA, *edgeB; /* * The left_ and right_faces fold together to form the EdgeClass * of order one. * The bottom_face cannot be glued to the remaining face of tet, * because if it were we'd have a manifold with only one Tetrahedron * but at least two EdgeClasses, which violates the proposition * that in a manifold with cusp cross sections of Euler characteristic * zero, the number of EdgeClasses must equal the number of * Tetrahedra. */ /* * Oops! The reasoning in the preceding paragraph fails us * for finite triangulations (with honest vertices instead of * ideal vertices). In such cases it suffices simply to report * that the triangulation cannot be simplified. JRW 2002/08/26 */ if (tet->neighbor[bottom_face] == tet) /* uFatalError("this_way_works", "simplify_triangulation"); */ return FALSE; /* * We want to locate the two EdgeClasses which would be combined * when remove_edge_of_order_one() calls cancel_tetrahedra(). */ tet1 = tet->neighbor[bottom_face]; left1 = EVALUATE(tet->gluing[bottom_face], left_face); right1 = EVALUATE(tet->gluing[bottom_face], right_face); bottom1 = EVALUATE(tet->gluing[bottom_face], bottom_face); edgeA = tet1->edge_class[edge_between_vertices[bottom1][ left1]]; edgeB = tet1->edge_class[edge_between_vertices[bottom1][right1]]; return (edgeA != edgeB); } /* * cancel_tetrahedra() checks whether the two Tetrahedra * incident to the EdgeClass edge contain an annulus or * Moebius strip, and if they do not, it cancels them and * returns func_OK. If they do contain an annulus or Moebius * strip, cancel_tetrahedra() does nothing and returns func_failed. * * Comments in the code below explain how the cancellation * occurs, and why no other degenerate situations can occur. * * The imaginary parts of the logarithmic forms of the TetShapes * are computed mod 2 pi i, as explained at the top of this file. * * 97/2/4 Modified to allow for the possibility of two Tetrahedra * sharing three faces and the enclosed finite vertex. In this * case the annulus referred to above encloses a solid cylinder. * The tetrahedra are cancelled and the finite vertex is removed. */ FuncResult cancel_tetrahedra( EdgeClass *edge, EdgeClass **where_to_resume, int *num_tetrahedra_ptr) { Tetrahedron *tet[2], *nbr[2], *t; VertexIndex v[2][4], w[2][4]; Orientation orientation[2]; EdgeClass *outer_edge[2]; Boolean are_whole_manifold; int c, i, ii, j, k; int delta[2][2][2]; VertexIndex active_vertex; Boolean tet_orientations_agree, edge_orientations_agree, edge_class_orientations_agree; PositionedTet ptet, ptet0; EdgeIndex left_edge; Permutation gluing[2]; /* * Just to be safe . . . */ if (edge->order != 2) uFatalError("cancel_tetrahedra", "simplify_triangulation"); /* * Let tet[0] and tet[1] be the two Tetrahedra incident * to EdgeClass *edge, and v[i][j] be their vertices. * Vertex v[0][i] is glued to vertex v[1][i]. * Vertices v[i][0] and v[i][1] are incident to the * EdgeClass *edge. */ tet[0] = edge->incident_tet; v[0][0] = one_vertex_at_edge[edge->incident_edge_index]; v[0][1] = other_vertex_at_edge[edge->incident_edge_index]; v[0][2] = remaining_face[v[0][1]][v[0][0]]; v[0][3] = remaining_face[v[0][0]][v[0][1]]; orientation[0] = right_handed; if (tet[0]->neighbor[v[0][2]] != tet[0]->neighbor[v[0][3]] || tet[0]->gluing [v[0][2]] != tet[0]->gluing [v[0][3]]) uFatalError("cancel_tetrahedra", "simplify_triangulation"); tet[1] = tet[0]->neighbor[v[0][2]]; for (i = 0; i < 4; i++) v[1][i] = EVALUATE(tet[0]->gluing[v[0][2]], v[0][i]); orientation[1] = (parity[tet[0]->gluing[v[0][2]]] == orientation_preserving) ? orientation[0] : ! orientation[0]; /* * It's easy to prove that if the manifold has only torus and Klein * bottle cusp cross sections, then tet[0] and tet[1] are distinct. * * 97/2/4 I assume that the presence of at least one torus or * Klein bottle cusp is enough to guarantee that tet[0] != tet[1], * but I haven't thought through the details. Even if we eventually * wanted to use this code to simplify non-ideal triangulations * of closed manifolds, we could simply replace the uFatalError() * call with func_failed. * * 99/06/04 Indeed we do want this code to simplify non-ideal * triangulations of closed manifolds, so I replaced * uFatalError("cancel_tetrahedra", "simplify_triangulation"); * with * return func_failed; */ if (tet[0] == tet[1]) return func_failed; /* * If the edge connecting v[0][2] to v[0][3] belongs to the same * EdgeClass as the edge connecting v[1][2] to v[1][3], then the * union of tet[0] and tet[1] contains an embedded annulus or * Moebius strip, and we should return func_failed. * * 97/2/4 Check whether tet[0] and tet[1] share three faces, * and enclose a finite vertex. If so, we may cancel the Tetrahedra, * and also remove the finite vertex. Obviously these changes will * never be invoked for ideal triangulations (i.e. with no finite * vertices). * * 2000/03/14 Oops! In the 97/2/4 change I overlooked the possibility * that tet[0] and tet[1] comprise the entire manifold (in which * case the manifold is a 3-sphere or L(3,1)). The code now tests * for this possibility, and returns func_failed when it occurs. */ for (i = 0; i < 2; i++) outer_edge[i] = tet[i]->edge_class[edge_between_vertices[v[i][2]][v[i][3]]]; if (outer_edge[0] == outer_edge[1]) { for (i = 0; i < 2; i++) if (tet[0]->cusp[v[0][i]]->is_finite == TRUE && tet[0]->neighbor[v[0][!i]] == tet[1] && tet[0]->neighbor[v[0][ i]] != tet[1] && tet[0]->gluing[v[0][!i]] == tet[0]->gluing[v[0][2]]) return cancel_tetrahedra_with_finite_vertex(tet[0], v[0][i], edge, where_to_resume, num_tetrahedra_ptr); return func_failed; } /* * The plan is to flatten the two Tetrahedra. To prove rigorously * that this does not change the topology of the manifold, first * imagine compressing the strip lying between the edge from * v[0][2] to v[0][3] and the edge from v[1][2] to v[1][3]. * This is valid iff the two edges are in distinct EdgeClasses, * and we just checked that they are. Then imagine flattening * the two triangular pillows. This is OK iff the two triangular * pillows don't make up the whole manifold, which they don't * because otherwise the boundary would contain a sphere. * Q.E.D. * * 2000/03/14 Test explicitly whether the two triangular pillows * make up the whole manifold. */ are_whole_manifold = TRUE; for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) if (tet[i]->neighbor[v[i][j]] != tet[0] && tet[i]->neighbor[v[i][j]] != tet[1]) are_whole_manifold = FALSE; if (are_whole_manifold == TRUE) return func_failed; /* * Before compressing the aforementioned strip, we need to clear * the peripheral curves away from the strip we're going to * collapse. While we're at it, we'll relabel all edges in * EdgeClass outer_edge[1] as EdgeClass outer_edge[0], and adjust * their edge_orientation if necessary, in preparation for merging * the two classes. */ for (c = 0; c < 2; c++) /* M or L */ for (j = 0; j < 2; j++) /* top (= 0) or bottom (= 1) */ for (i = 0; i < 2; i++) /* right_handed or left_handed */ { ii = (orientation[0] == orientation[1]) ? i : !i; delta[c][j][i] = tet[1]->curve[c][ i][v[1][j+2]][v[1][0]] + tet[0]->curve[c][ii][v[0][j+2]][v[0][0]]; } tet_orientations_agree = (orientation[0] == orientation[1]); edge_orientations_agree = (tet[0]->edge_orientation[edge_between_faces[v[0][0]][v[0][1]]] == tet[1]->edge_orientation[edge_between_faces[v[1][0]][v[1][1]]]); edge_class_orientations_agree = (tet_orientations_agree == edge_orientations_agree); ptet0.tet = tet[1]; ptet0.near_face = v[1][1]; ptet0.left_face = v[1][0]; ptet0.right_face = v[1][3]; ptet0.bottom_face = v[1][2]; ptet0.orientation = orientation[1]; ptet = ptet0; do { /* * Adjust the peripheral curves. */ for (c = 0; c < 2; c++) for (j = 0; j < 2; j++) { active_vertex = (j == 0) ? ptet.bottom_face : ptet.right_face; for (i = 0; i < 2; i++) { ii = (ptet.orientation == ptet0.orientation) ? i : !i; ptet.tet->curve[c][i][active_vertex][ptet.left_face] -= delta[c][j][ii]; ptet.tet->curve[c][i][active_vertex][ptet.near_face] += delta[c][j][ii]; } } /* * For convenience, note the EdgeIndex of the left edge. */ left_edge = edge_between_faces[ptet.near_face][ptet.left_face]; /* * Adjust the EdgeClass. */ ptet.tet->edge_class[left_edge] = outer_edge[0]; /* * Adjust the edge_orientation. */ if ( ! edge_class_orientations_agree) ptet.tet->edge_orientation[left_edge] = ! ptet.tet->edge_orientation[left_edge]; /* * Move on. */ veer_left(&ptet); } while ( ! same_positioned_tet(&ptet, &ptet0)); /* * Adjust the EdgeClass sizes. */ outer_edge[0]->order += outer_edge[1]->order; for (i = 0; i < 2; i++) for (j = 0; j < 6; j++) tet[i]->edge_class[j]->order--; /* * We are about to delete EdgeClasses edge and outer_edge[1]. * Set *where_to_resume to point to the EdgeClass just * just before the spot where edge was. */ if (edge->prev != outer_edge[1]) *where_to_resume = edge->prev; else *where_to_resume = outer_edge[1]->prev; /* * Free the unused EdgeClasses. */ REMOVE_NODE(edge); REMOVE_NODE(outer_edge[1]); my_free(edge); my_free(outer_edge[1]); /* * Set the incident_tet and incident_edge_index fields * for all EdgeClasses which lost members. */ for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) { t = tet[i]->neighbor[v[i][j]]; if (t != tet[0] && t != tet[1]) for (k = 0; k < 6; k++) { t->edge_class[k]->incident_tet = t; t->edge_class[k]->incident_edge_index = k; } } /* * Set neighbors and gluings. */ for (i = 0; i < 2; i++) { /* which face */ for (j = 0; j < 2; j++) /* which Tetrahedron */ { nbr[j] = tet[j]->neighbor[v[j][i]]; gluing[j] = tet[j]->gluing [v[j][i]]; for (k = 0; k < 4; k++) /* which vertex */ w[j][k] = EVALUATE(gluing[j], v[j][k]); } for (j = 0; j < 2; j++) /* which Tetrahedron */ { nbr[j]->neighbor[w[j][i]] = nbr[!j]; nbr[j]->gluing [w[j][i]] = CREATE_PERMUTATION( w[j][0], w[!j][0], w[j][1], w[!j][1], w[j][2], w[!j][2], w[j][3], w[!j][3]); } } /* * Free the collapsed Tetrahedra. */ for (i = 0; i < 2; i++) { REMOVE_NODE(tet[i]); free_tetrahedron(tet[i]); } *num_tetrahedra_ptr -= 2; return func_OK; } static FuncResult cancel_tetrahedra_with_finite_vertex( Tetrahedron *tet, VertexIndex finite_vertex, EdgeClass *edge, /* needed only for setting *where_to_resume */ EdgeClass **where_to_resume, int *num_tetrahedra_ptr) { Tetrahedron *nbr, *tet_outer, *nbr_outer; Permutation gluing; FaceIndex f, ff, tet_outer_f, nbr_outer_f; VertexIndex v, nbr_finite; EdgeIndex e; Cusp *dead_cusp; EdgeClass *dead_edge; /* * The three faces of the tet surrounding the finite_vertex * are glued to the neighboring Tetrahedron in the obvious way, * forming a triangular pillow with a finite vertex and three * EdgeClasses in its interior. */ nbr = tet->neighbor[!finite_vertex]; gluing = tet->gluing [!finite_vertex]; if (tet->cusp[finite_vertex]->is_finite != TRUE) uFatalError("cancel_tetrahedra_with_finite_vertex", "simplify_triangulation"); for (f = 0; f < 4; f++) if (f != finite_vertex) if (tet->neighbor[f] != nbr || tet->gluing [f] != gluing) uFatalError("cancel_tetrahedra_with_finite_vertex", "simplify_triangulation"); /* * If tet and nbr had four faces in common, then the manifold * couldn't have any torus or Klein bottle boundary components. * We assume this isn't the case. */ if (tet->neighbor[finite_vertex] == nbr) uFatalError("cancel_tetrahedra_with_finite_vertex", "simplify_triangulation"); /* * The peripheral curves will match up correctly after the cancellation. * No explicit preparation is required. */ /* * Remove the Cusp structure representing the finite vertex * in the triangular pillow's interior. Finite vertices aren't * counted in a Triangulation's num_cusps field. By removing * this Cusp we may leave a gap in the (negative) indexing of * finite vertex Cusps, but that's OK. */ dead_cusp = tet->cusp[finite_vertex]; REMOVE_NODE(dead_cusp); my_free(dead_cusp); /* * Remove the three EdgeClasses from the pillow's interior. * * Make sure the calling program is left with a valid pointer * to an EdgeClass, to continue its loop where it left off. */ *where_to_resume = edge->prev; for (v = 0; v < 4; v++) if (v != finite_vertex) { dead_edge = tet->edge_class[edge_between_vertices[v][finite_vertex]]; if (dead_edge == *where_to_resume) *where_to_resume = dead_edge->prev; REMOVE_NODE(dead_edge); my_free(dead_edge); } /* * Note which Tetrahedra border the triangular pillow's outer faces. */ tet_outer = tet->neighbor[finite_vertex]; tet_outer_f = EVALUATE(tet->gluing[finite_vertex], finite_vertex); nbr_finite = EVALUATE(gluing, finite_vertex); nbr_outer = nbr->neighbor[nbr_finite]; nbr_outer_f = EVALUATE(nbr->gluing[nbr_finite], nbr_finite); /* * Make sure the three EdgeClasses around the pillow's boundary * "see" Tetrahedra other than the ones we are about to cancel. * Reduce the order of each such EdgeClass by two. */ for (f = 0; f < 4; f++) if (f != finite_vertex) { ff = EVALUATE(tet->gluing[finite_vertex], f); e = edge_between_faces[tet_outer_f][ff]; tet_outer->edge_class[e]->incident_tet = tet_outer; tet_outer->edge_class[e]->incident_edge_index = e; tet_outer->edge_class[e]->order -= 2; } /* * Glue tet_outer and nbr_outer to one another. * (Note: compose_permutations() composes right-to-left.) */ tet_outer->neighbor[tet_outer_f] = nbr_outer; tet_outer->gluing[tet_outer_f] = compose_permutations(gluing, tet_outer->gluing[tet_outer_f]); tet_outer->gluing[tet_outer_f] = compose_permutations(nbr->gluing[nbr_finite], tet_outer->gluing[tet_outer_f]); nbr_outer->neighbor[nbr_outer_f] = tet_outer; nbr_outer->gluing[nbr_outer_f] = compose_permutations(inverse_permutation[gluing], nbr_outer->gluing[nbr_outer_f]); nbr_outer->gluing[nbr_outer_f] = compose_permutations(tet->gluing[finite_vertex], nbr_outer->gluing[nbr_outer_f]); if (nbr_outer->gluing[nbr_outer_f] != inverse_permutation[tet_outer->gluing[tet_outer_f]] || EVALUATE(tet_outer->gluing[tet_outer_f], tet_outer_f) != nbr_outer_f) uFatalError("cancel_tetrahedra_with_finite_vertex", "simplify_triangulation"); /* * Remove tet and nbr. */ REMOVE_NODE(tet); REMOVE_NODE(nbr); free_tetrahedron(tet); free_tetrahedron(nbr); *num_tetrahedra_ptr -= 2; return func_OK; } /* * If the three Tetrahedra surrounding the EdgeClass *edge are distinct, * three_to_two() replaces them with two Tetrahedra sharing a common * face, and returns func_OK. Otherwise it does nothing and returns * func_failed. * * The Orientations of the two new Tetrahedra are set to match the * Orientation of one of the three old ones, so that the Orientability * of the Triangulation (if there is one) will be preserved. * * The two new Tetrahedra created by three_to_two() take the place * of one of the doomed ones in the list of Tetrahedra. The doomed * Tetrahedron are removed from the list before being destroyed. * Similarly, the EdgeClass edge is removed from its list before * being destroyed. * * If the three original Tetrahedra are nondegenerate, the two * two new ones must perforce be nondegenerate as well. Proof: * if a pair of ideal vertices coincides in a new Tetrahedra, * that pair must have coincided in one of the three original * Tetrahedra as well. * * The imaginary parts of the logarithmic forms of the TetShapes * are computed mod 2 pi i, as explained at the top of this file. */ FuncResult three_to_two( EdgeClass *edge, EdgeClass **where_to_resume, int *num_tetrahedra_ptr) { int c, h, hh, i, j, j1, j2; Tetrahedron *tet[3], *new_tet[2]; VertexIndex v[3][4], w[2][4]; Orientation old_orientation[3]; Permutation gluing; EdgeIndex old_h_edge_index, old_v_edge_index, new_h_edge_index, new_v_edge_index; /* * Just to be safe . . . */ if (edge->order != 3) uFatalError("three_to_two", "simplify_triangulation"); /* * The three Tetrahedra incident to the EdgeClass *edge will be * called tet[0], tet[1] and tet[2]. The vertices of tet[i] will * be v[i][0-3]. * * I recommend making a sketch of tet[0-2] to consult as you * read through the following code. The EdgeClass *edge is * vertical. Vertex v[i][0] of each tet[i] is at the bottom * of the edge, and vertex v[i][1] is at the top. Vertices * v[i][2] and v[i][3] are on the "equator", with v[i][3] * being counterclockwise from v[i][2] as viewed from above. */ /* * Locate one Tetrahedron incident to EdgeClass *edge. * Choose the v[0][j] so that tet[0] is viewed with * the right_handed Orientation. */ tet[0] = edge->incident_tet; v[0][0] = one_vertex_at_edge[edge->incident_edge_index]; v[0][1] = other_vertex_at_edge[edge->incident_edge_index]; v[0][2] = remaining_face[v[0][0]][v[0][1]]; v[0][3] = remaining_face[v[0][1]][v[0][0]]; old_orientation[0] = right_handed; /* * Locate the two remaining Tetrahedra. * If the Triangulation is oriented, they will also be positioned * with the right_handed Orientation. */ for (i = 0; i < 2; i++) { tet[i+1] = tet[i]->neighbor[v[i][2]]; gluing = tet[i]->gluing[v[i][2]]; v[i+1][0] = EVALUATE(gluing, v[i][0]); v[i+1][1] = EVALUATE(gluing, v[i][1]); v[i+1][2] = EVALUATE(gluing, v[i][3]); v[i+1][3] = EVALUATE(gluing, v[i][2]); old_orientation[i+1] = (parity[gluing] == orientation_preserving) ? old_orientation[i] : ! old_orientation[i]; } /* * If the three Tetrahedra are not distinct, we can't do any * simplification, so return func_failed. */ for (i = 0; i < 3; i++) if (tet[i] == tet[(i+1)%3]) return func_failed; /* * This function should never be invoked when canonize_info is present. */ if (tet[0]->canonize_info != NULL) uFatalError("three_to_two", "simplify_triangulation"); /* * Create the new Tetrahedra. * * new_tet[0] occupies the northern half of the picture as described * above, and new_tet[1] occupies the southern half. Vertex w[0][3] of * new_tet[0] is at the north pole, and vertex w[1][3] of new_tet[1] is at * the south pole. Face w[i][j] (j = 0,1,2) of new_tet[i] coincides with * face v[j][i] of tet[j]. The actual values of w[][] give both * new_tet[0] and new_tet[1] the right_handed Orientation. */ for (i = 0; i < 2; i++) { new_tet[i] = NEW_STRUCT(Tetrahedron); initialize_tetrahedron(new_tet[i]); } w[0][0] = 0; w[0][1] = 1; w[0][2] = 3; w[0][3] = 2; w[1][0] = 0; w[1][1] = 1; w[1][2] = 2; w[1][3] = 3; /* * Set the gluing and neighbor fields. * * Note that this code works correctly even if some of the faces * of the tet[i] were glued to each other. */ for (i = 0; i < 2; i++) { for (j = 0; j < 3; j++) { new_tet[i]->neighbor[w[i][j]] = tet[j]->neighbor[v[j][i]]; new_tet[i]->gluing [w[i][j]] = CREATE_PERMUTATION( w[i][j], EVALUATE(tet[j]->gluing[v[j][i]], v[j][i]), w[i][(j+1)%3], EVALUATE(tet[j]->gluing[v[j][i]], v[j][2]), w[i][(j+2)%3], EVALUATE(tet[j]->gluing[v[j][i]], v[j][3]), w[i][3], EVALUATE(tet[j]->gluing[v[j][i]], v[j][!i]) ); set_inverse_neighbor_and_gluing(new_tet[i], w[i][j]); } new_tet[i]->neighbor[w[i][3]] = new_tet[!i]; new_tet[i]->gluing [w[i][3]] = CREATE_PERMUTATION( w[i][0], w[!i][0], w[i][1], w[!i][1], w[i][2], w[!i][2], w[i][3], w[!i][3]); } /* * Set the cusp fields. */ for (i = 0; i < 2; i++) { for (j = 0; j < 3; j++) new_tet[i]->cusp[w[i][j]] = tet[(j+1)%3]->cusp[v[(j+1)%3][3]]; new_tet[i]->cusp[w[i][3]] = tet[0]->cusp[v[0][!i]]; } /* * Set the peripheral curves. */ for (c = 0; c < 2; c++) /* which curve */ for (h = 0; h < 2; h++) /* which sheet */ for (i = 0; i < 2; i++) { /* which tetrahedron */ /* * Set the equatorial vertices. */ for (j = 0; j < 3; j++) /* which vertex */ { j1 = (j+1) % 3; j2 = (j+2) % 3; hh = (old_orientation[j1] == right_handed) ? h : !h; new_tet[i]->curve[c][h][w[i][j]][w[i][j1]] = tet[j1]->curve[c][hh][v[j1][3]][v[j1][i]]; hh = (old_orientation[j2] == right_handed) ? h : !h; new_tet[i]->curve[c][h][w[i][j]][w[i][j2]] = tet[j2]->curve[c][hh][v[j2][2]][v[j2][i]]; new_tet[i]->curve[c][h][w[i][j]][w[i][3]] = - (new_tet[i]->curve[c][h][w[i][j]][w[i][j1]] + new_tet[i]->curve[c][h][w[i][j]][w[i][j2]]); } /* * Set the polar vertices. */ for (j = 0; j < 3; j++) { /* which side of vertex 3 */ hh = (old_orientation[j] == right_handed) ? h : !h; new_tet[i]->curve[c][h][w[i][3]][w[i][j]] = tet[j]->curve[c][hh][v[j][!i]][v[j][i]]; } } /* * Set where_to_resume to the predecessor of the EdgeClass about * to be killed, so that the loop in the calling function can * continue at the correct spot in the list. */ *where_to_resume = edge->prev; /* * Kill the EdgeClass at the center of the three old Tetrahedra. */ REMOVE_NODE(edge); my_free(edge); /* * Update the surviving EdgeClasses. */ for (i = 0; i < 2; i++) for (j = 0; j < 3; j++) { j1 = (j+1) % 3; j2 = (j+2) % 3; old_h_edge_index = edge_between_vertices[v[j2][2]][v[j2][ 3]]; old_v_edge_index = edge_between_vertices[v[j2][2]][v[j2][!i]]; new_h_edge_index = edge_between_vertices[w[ i][j]][w[ i][j1]]; new_v_edge_index = edge_between_vertices[w[ i][j]][w[ i][ 3]]; new_tet[i]->edge_class[new_h_edge_index] = tet[j2]->edge_class[old_h_edge_index]; new_tet[i]->edge_class[new_v_edge_index] = tet[j2]->edge_class[old_v_edge_index]; if (old_orientation[j2] == right_handed) { new_tet[i]->edge_orientation[new_h_edge_index] = tet[j2]->edge_orientation[old_h_edge_index]; new_tet[i]->edge_orientation[new_v_edge_index] = tet[j2]->edge_orientation[old_v_edge_index]; } else { new_tet[i]->edge_orientation[new_h_edge_index] = ! tet[j2]->edge_orientation[old_h_edge_index]; new_tet[i]->edge_orientation[new_v_edge_index] = ! tet[j2]->edge_orientation[old_v_edge_index]; } new_tet[i]->edge_class[new_v_edge_index]->order--; if (i == 0) new_tet[i]->edge_class[new_h_edge_index]->order++; new_tet[i]->edge_class[new_h_edge_index]->incident_tet = new_tet[i]; new_tet[i]->edge_class[new_v_edge_index]->incident_tet = new_tet[i]; new_tet[i]->edge_class[new_h_edge_index]->incident_edge_index = new_h_edge_index; new_tet[i]->edge_class[new_v_edge_index]->incident_edge_index = new_v_edge_index; } /* * Compute the shapes of the new Tetrahedra iff * the old tetrahedra had shapes. */ if (tet[0]->shape[complete] != NULL) { /* * Allocate space for the TetShapes of the new Tetrahedra. */ for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) new_tet[i]->shape[j] = NEW_STRUCT(TetShape); /* * Add the complex edge angles of the old Tetrahedra * to get those of the new Tetrahedra. Use the * edge_orientation[] to get the orientations correct. * Note that add_edge_angles chooses angles in the range * [(-1/2) pi, (3/2) pi], regardless of the angles of * summands. */ for (i = 0; i < 2; i++) /* which new Tetrahedron */ for (j = 0; j < 3; j++) /* which EdgeClass */ add_edge_angles( tet[(j+1)%3], edge_between_vertices[v[(j+1)%3][3]][v[(j+1)%3][!i]], tet[(j+2)%3], edge_between_vertices[v[(j+2)%3][2]][v[(j+2)%3][!i]], new_tet[i], edge_between_vertices[w[i][j]][w[i][3]] ); } /* * Compute VertexCrossSections for the new Tetrahedra * iff the old Tetrahedra had VertexCrossSections. */ if (tet[0]->cross_section != NULL) { /* * Begin with a quick error check. */ if (new_tet[0]->shape[complete] == NULL) uFatalError("three_to_two", "simplify_triangulation"); /* * Allocate space for the VertexCrossSections of the new Tetrahedra. */ for (i = 0; i < 2; i++) new_tet[i]->cross_section = NEW_STRUCT(VertexCrossSections); /* * Compute the VertexCrossSections for each of the two new Tetrahedra. */ for (i = 0; i < 2; i++) { /* * Compute the polar VertexCrossSections. */ for (j = 0; j < 3; j++) new_tet[i]->cross_section->edge_length[w[i][3]][w[i][j]] = tet[j]->cross_section->edge_length[v[j][!i]][v[j][i]]; new_tet[i]->cross_section->has_been_set[w[i][3]] = TRUE; /* * Compute the equatorial VertexCrossSections. */ for (j = 0; j < 3; j++) compute_three_edge_lengths(new_tet[i], w[i][(j+1)%3], w[i][j], tet[j]->cross_section->edge_length[v[j][2]][v[j][i]]); } /* * Update the tilts. */ for (i = 0; i < 2; i++) compute_tilts_for_one_tet(new_tet[i]); } /* * Compute CuspNbhdPositions for the new Tetrahedra iff * the old Tetrahedra had CuspNbhdPositions. */ if (tet[0]->cusp_nbhd_position != NULL) { /* * Begin with a quick error check. */ if (new_tet[0]->shape[complete] == NULL) uFatalError("three_to_two", "simplify_triangulation"); /* * Allocate space for the CuspNbhdPositions of the new Tetrahedra. */ for (i = 0; i < 2; i++) new_tet[i]->cusp_nbhd_position = NEW_STRUCT(CuspNbhdPosition); /* * Compute the CuspNbhdPositions for each of the two new Tetrahedra. */ for (i = 0; i < 2; i++) /* * Consider both the right_handed and left_handed sheets. */ for (h = 0; h < 2; h++) { /* * Compute the polar CuspNbhdPositions. * * The first approach which comes to mind is simply to copy * the relevant coordinates from the old Tetrahedra to the * new ones. Unfortunately the CuspNbhdPositions of the * three old tetrahedra may differ by covering translations. * * This problem is not insurmountable, but the code will be * cleaner if we simply copy the coordinates of two corners, * and then call cn_find_third_corner() to compute the * remaining corner. Recall that both new Tetrahedra are * seen in the right_handed Orientation, as is old tet[0]. */ if (tet[0]->cusp_nbhd_position->in_use[h][v[0][!i]] == TRUE) { new_tet[i]->cusp_nbhd_position->x[h][w[i][3]][w[i][1]] = tet[0]->cusp_nbhd_position->x[h][v[0][!i]][v[0][2]]; new_tet[i]->cusp_nbhd_position->x[h][w[i][3]][w[i][2]] = tet[0]->cusp_nbhd_position->x[h][v[0][!i]][v[0][3]]; cn_find_third_corner(new_tet[i], h, w[i][3], w[i][1], w[i][2], w[i][0]); new_tet[i]->cusp_nbhd_position->in_use[h][w[i][3]] = TRUE; } else { new_tet[i]->cusp_nbhd_position->x[h][w[i][3]][w[i][1]] = Zero; new_tet[i]->cusp_nbhd_position->x[h][w[i][3]][w[i][2]] = Zero; new_tet[i]->cusp_nbhd_position->x[h][w[i][3]][w[i][0]] = Zero; new_tet[i]->cusp_nbhd_position->in_use[h][w[i][3]] = FALSE; } /* * Compute the equatorial CuspNbhdPositions. * * Technical note: The new_tets are both seen with the * right_handed Orientation. So when old_orientation[] * is also right_handed, we want to read the new sheet h * from the old sheet h. But when old_orientation[] is * left_handed, we want to read the new sheet h from the * old sheet !h. Because left_handed == 1, the expression * (old_orientation[] ^ h) gives the correct old sheet * to read from. */ for (j = 0; j < 3; j++) { if (tet[j]->cusp_nbhd_position->in_use[old_orientation[j]^h][v[j][2]] == TRUE) { new_tet[i]->cusp_nbhd_position->x[h][w[i][(j+1)%3]][w[i][(j+2)%3]] = tet[j]->cusp_nbhd_position->x[old_orientation[j]^h][v[j][2]][v[j][3]]; new_tet[i]->cusp_nbhd_position->x[h][w[i][(j+1)%3]][w[i][3]] = tet[j]->cusp_nbhd_position->x[old_orientation[j]^h][v[j][2]][v[j][!i]]; cn_find_third_corner(new_tet[i], h, w[i][(j+1)%3], w[i][(j+2)%3], w[i][3], w[i][j]); new_tet[i]->cusp_nbhd_position->in_use[h][w[i][(j+1)%3]] = TRUE; } else { new_tet[i]->cusp_nbhd_position->x[h][w[i][(j+1)%3]][w[i][(j+2)%3]] = Zero; new_tet[i]->cusp_nbhd_position->x[h][w[i][(j+1)%3]][w[i] [3] ] = Zero; new_tet[i]->cusp_nbhd_position->x[h][w[i][(j+1)%3]][w[i] [j] ] = Zero; new_tet[i]->cusp_nbhd_position->in_use[h][w[i][(j+1)%3]] = FALSE; } } } } /* * Put the new Tetrahedra on the list, and remove and free * the old ones. */ for (i = 0; i < 2; i++) INSERT_BEFORE(new_tet[i], tet[0]); for (i = 0; i < 3; i++) { REMOVE_NODE(tet[i]); free_tetrahedron(tet[i]); } *num_tetrahedra_ptr -= 1; return func_OK; } /* * The three new Tetrahedra created by two_to_three() take tet0's place * in the list of Tetrahedra. Tet0 and the other doomed Tetrahedron are * removed from the list before being destroyed. Similarly, the new * EdgeClass is added to the list of EdgeClasses just in front of one * of the existing EdgeClasses. * * The Orientations of the three new Tetrahedra are set to match the * Orientation of one of the two old ones, so that the Orientability * of the Triangulation (if there is one) will be preserved. * * two_to_three() returns func_failed if either * * (1) the two initial Tetrahedra are not not distinct (i.e. tet0 * is glued to itself at face f), or * * (2) a hyperbolic structure is present, and even though the two * initial Tetrahedra are combinatorially distinct, they are * superimposed in hyperbolic space (i.e. the vertices opposite * their common face, though combinatorially distinct, lie at the * same point on the sphere at infinity). In this case, performing * the two_to_three() move would create degenerate Tetrahedra. * * The imaginary parts of the logarithmic forms of the TetShapes * are computed mod 2 pi i, as explained at the top of this file. */ FuncResult two_to_three( Tetrahedron *tet0, FaceIndex f, int *num_tetrahedra_ptr) { Tetrahedron *tet[2], *new_tet[3]; VertexIndex v[2][4]; Orientation old_orientation[2]; int c, h, hh, i, i1, i2, j, k; EdgeClass *new_class; /* * two_to_three() is the inverse of three_to_two(), and * is implemented similarly. In particular, the picture to * imagine (or, better yet, draw on a scrap of paper before * diving into this code) is virtually identical to that from * three_to_two(), only what was tet[] there is new_tet[] here, * and vice versa. */ /* * Label tet[0] and tet[1]. */ tet[0] = tet0; v[0][3] = f; v[0][0] = !f; /* v[0][0] is some vertex other than v[0][3] */ v[0][1] = remaining_face[v[0][3]][v[0][0]]; /* tet[0] will be seen */ v[0][2] = remaining_face[v[0][0]][v[0][3]]; /* as left_handed */ old_orientation[0] = left_handed; tet[1] = tet[0]->neighbor[f]; for (i = 0; i < 4; i++) v[1][i] = EVALUATE(tet[0]->gluing[f], v[0][i]); old_orientation[1] = (parity[tet[0]->gluing[f]] == orientation_preserving) ? old_orientation[0] : ! old_orientation[0]; /* * If tet[0] and tet[1] are not distinct, we cannot proceed. */ if (tet[0] == tet[1]) return func_failed; /* * If a hyperbolic structure is present and the 2-3 move would create * degenerate Tetrahedra, we do not want to proceed. Degenerate * Tetrahedra will be created iff vertices v[0][3] and v[1][3] coincide. * (People usually think of degeneracy in terms of the dihedral angles * approaching {0, 1, infinity}, but in this context we also think in * terms of the equivalent definition that a Tetrahedron is degenerate * iff two or more vertices coincide.) * * angles_sum_to_zero() check whether the angles sum to zero mod 2 pi. */ if (tet[0]->shape[complete] != NULL) if (angles_sum_to_zero( tet[0], edge_between_vertices[v[0][0]][v[0][1]], tet[1], edge_between_vertices[v[1][0]][v[1][1]])) return func_failed; /* * Allocate the three new Tetrahedra. */ for (i = 0; i < 3; i++) { new_tet[i] = NEW_STRUCT(Tetrahedron); initialize_tetrahedron(new_tet[i]); } /* * Note that here we can refer to the VertexIndices of the new_tet[i] * directly, because a symmetrical indexing scheme is consistent * with a fixed orientation. In three_to_two(), the symmetrical * indexing scheme was not consistent with a fixed orientation, * so we had to use the w[][] to store the true indices of the * new Tetrahedra. */ /* * Set "internal" neighbors and gluings. */ for (i = 0; i < 3; i++) { i1 = (i+1) % 3; i2 = (i+2) % 3; new_tet[i]->neighbor[2] = new_tet[i1]; new_tet[i]->neighbor[3] = new_tet[i2]; new_tet[i]->gluing[2] = CREATE_PERMUTATION(0, 0, 1, 1, 2, 3, 3, 2); new_tet[i]->gluing[3] = CREATE_PERMUTATION(0, 0, 1, 1, 2, 3, 3, 2); } /* * Set "external" neighbors and gluings. * This code works even if some of the external faces of tet[0] * and tet[1] are glued to each other. */ for (i = 0; i < 3; i++) /* which new Tetrahedron */ for (j = 0; j < 2; j++) /* which face */ { new_tet[i]->neighbor[j] = tet[j]->neighbor[v[j][i]]; new_tet[i]->gluing[j] = CREATE_PERMUTATION( j, EVALUATE(tet[j]->gluing[v[j][i]], v[j][i]), !j, EVALUATE(tet[j]->gluing[v[j][i]], v[j][3]), 2, EVALUATE(tet[j]->gluing[v[j][i]], v[j][(i+1)%3]), 3, EVALUATE(tet[j]->gluing[v[j][i]], v[j][(i+2)%3]) ); set_inverse_neighbor_and_gluing(new_tet[i], j); } /* * Set the cusp fields. */ for (i = 0; i < 3; i++) { new_tet[i]->cusp[0] = tet[1]->cusp[v[1][3]]; new_tet[i]->cusp[1] = tet[0]->cusp[v[0][3]]; new_tet[i]->cusp[2] = tet[0]->cusp[v[0][(i+1)%3]]; new_tet[i]->cusp[3] = tet[0]->cusp[v[0][(i+2)%3]]; } /* * Set the peripheral curves. */ for (c = 0; c < 2; c++) /* which curve */ for (h = 0; h < 2; h++) { /* which sheet */ /* * Set the exterior sides of the polar vertices. */ for (i = 0; i < 3; i++) /* which tetrahedron */ for (j = 0; j < 2; j++) { /* which vertex */ hh = (old_orientation[!j] == left_handed) ? h : !h; new_tet[i]->curve[c][h][j][!j] = tet[!j]->curve[c][hh][v[!j][3]][v[!j][i]]; } /* * Set the interior sides of the polar vertices. */ for (i = 0; i < 3; i++) /* which tetrahedron */ for (j = 0; j < 2; j++) /* which vertex */ for (k = 2; k < 4; k++) /* which side */ new_tet[i]->curve[c][h][j][k] = - FLOW( new_tet[ i ]->curve[c][h][j][!j], new_tet[(i+k-1)%3]->curve[c][h][j][!j]); /* * Set the equatorial vertices. */ for (i = 0; i < 3; i++) /* which tetrahedron */ for (j = 2; j < 4; j++) { /* which vertex */ for (k = 0; k < 2; k++) /* which side */ { hh = (old_orientation[k] == left_handed) ? h : !h; new_tet[i]->curve[c][h][j][k] = tet[k]->curve[c][hh][v[k][(i+j-1)%3]][v[k][i]]; } new_tet[i]->curve[c][h][j][5-j] = - (new_tet[i]->curve[c][h][j][0] + new_tet[i]->curve[c][h][j][1]); } } /* * Create the new EdgeClass. */ new_class = NEW_STRUCT(EdgeClass); initialize_edge_class(new_class); new_class->order = 3; new_class->incident_tet = new_tet[0]; new_class->incident_edge_index = edge_between_vertices[0][1]; /* * Insert the new EdgeClass at an arbitrary spot in the linked list. */ INSERT_BEFORE(new_class, tet[0]->edge_class[0]); /* * Set the EdgeClasses. */ for (i = 0; i < 3; i++) { i1 = (i+1) % 3; i2 = (i+2) % 3; new_tet[i]->edge_class[edge_between_vertices[0][1]] = new_class; new_tet[i]->edge_class[edge_between_vertices[0][2]] = tet[1]->edge_class[edge_between_vertices[v[1][3]][v[1][i1]]]; new_tet[i]->edge_class[edge_between_vertices[0][3]] = tet[1]->edge_class[edge_between_vertices[v[1][3]][v[1][i2]]]; new_tet[i]->edge_class[edge_between_vertices[1][2]] = tet[0]->edge_class[edge_between_vertices[v[0][3]][v[0][i1]]]; new_tet[i]->edge_class[edge_between_vertices[1][3]] = tet[0]->edge_class[edge_between_vertices[v[0][3]][v[0][i2]]]; new_tet[i]->edge_class[edge_between_vertices[2][3]] = tet[0]->edge_class[edge_between_vertices[v[0][i1]][v[0][i2]]]; } /* * Set the edge_orientations. */ for (i = 0; i < 3; i++) { i1 = (i+1) % 3; i2 = (i+2) % 3; new_tet[i]->edge_orientation[edge_between_vertices[0][1]] = right_handed; new_tet[i]->edge_orientation[edge_between_vertices[0][2]] = (old_orientation[1] == left_handed) ? tet[1]->edge_orientation[edge_between_vertices[v[1][3]][v[1][i1]]] : ! tet[1]->edge_orientation[edge_between_vertices[v[1][3]][v[1][i1]]]; new_tet[i]->edge_orientation[edge_between_vertices[0][3]] = (old_orientation[1] == left_handed) ? tet[1]->edge_orientation[edge_between_vertices[v[1][3]][v[1][i2]]] : ! tet[1]->edge_orientation[edge_between_vertices[v[1][3]][v[1][i2]]]; new_tet[i]->edge_orientation[edge_between_vertices[1][2]] = (old_orientation[0] == left_handed) ? tet[0]->edge_orientation[edge_between_vertices[v[0][3]][v[0][i1]]] : ! tet[0]->edge_orientation[edge_between_vertices[v[0][3]][v[0][i1]]]; new_tet[i]->edge_orientation[edge_between_vertices[1][3]] = (old_orientation[0] == left_handed) ? tet[0]->edge_orientation[edge_between_vertices[v[0][3]][v[0][i2]]] : ! tet[0]->edge_orientation[edge_between_vertices[v[0][3]][v[0][i2]]]; new_tet[i]->edge_orientation[edge_between_vertices[2][3]] = (old_orientation[0] == left_handed) ? tet[0]->edge_orientation[edge_between_vertices[v[0][i1]][v[0][i2]]] : ! tet[0]->edge_orientation[edge_between_vertices[v[0][i1]][v[0][i2]]]; } /* * Adjust the EdgeClass orders. */ for (i = 0; i < 3; i++) { new_tet[i]->edge_class[edge_between_vertices[0][2]]->order++; new_tet[i]->edge_class[edge_between_vertices[1][2]]->order++; new_tet[i]->edge_class[edge_between_vertices[2][3]]->order--; } /* * Set incident_tets and incident_edge_indices. */ for (i = 0; i < 3; i++) for (j = 0; j < 6; j++) { new_tet[i]->edge_class[j]->incident_tet = new_tet[i]; new_tet[i]->edge_class[j]->incident_edge_index = j; } /* * Compute the shapes of the new Tetrahedra iff * the old tetrahedra had shapes. */ if (tet[0]->shape[complete] != NULL) { /* * Allocate space for the TetShapes of the new Tetrahedra. */ for (i = 0; i < 3; i++) for (j = 0; j < 2; j++) new_tet[i]->shape[j] = NEW_STRUCT(TetShape); /* * First compute the TetShapes for the equatorial angles. */ for (i = 0; i < 3; i++) /* which new Tetrahedron */ add_edge_angles( tet[0], edge_between_vertices[v[0][(i+1)%3]][v[0][(i+2)%3]], tet[1], edge_between_vertices[v[1][(i+1)%3]][v[1][(i+2)%3]], new_tet[i], edge_between_vertices[2][3] ); /* * Now compute the remaining complex angles of each Tetrahedron, * with log.imag in the range [(-1/2) pi, (3/2) pi]. */ for (i = 0; i < 3; i++) /* which new Tetrahedron */ compute_remaining_angles(new_tet[i], edge3_between_vertices[2][3]); } /* * Compute VertexCrossSections for the new Tetrahedra * iff the old Tetrahedra had VertexCrossSections. */ if (tet[0]->cross_section != NULL) { /* * Begin with a quick error check. */ if (new_tet[0]->shape[complete] == NULL) uFatalError("two_to_three", "simplify_triangulation"); /* * Allocate space for the VertexCrossSections of the new Tetrahedra. */ for (i = 0; i < 3; i++) new_tet[i]->cross_section = NEW_STRUCT(VertexCrossSections); /* * Compute the VertexCrossSections for each of * the three new Tetrahedra. */ for (i = 0; i < 3; i++) { /* * Compute the polar vertices. */ for (j = 0; j < 2; j++) compute_three_edge_lengths(new_tet[i], !j, j, tet[j]->cross_section->edge_length[v[j][3]][v[j][i]]); /* * Compute the equatorial vertices. */ for (j = 2; j < 4; j++) compute_three_edge_lengths(new_tet[i], j, 0, tet[0]->cross_section->edge_length[v[0][(i+j+2)%3]][v[0][i]]); } /* * Update the tilts. */ for (i = 0; i < 3; i++) compute_tilts_for_one_tet(new_tet[i]); } /* * Provide CanonizeInfo for the new Tetrahedra * iff the old Tetrahedra had CanonizeInfo. */ if (tet[0]->canonize_info != NULL) { /* * Allocate space for the CanonizeInfo of the new Tetrahedra. */ for (i = 0; i < 3; i++) new_tet[i]->canonize_info = NEW_STRUCT(CanonizeInfo); /* * Set part_of_coned_cell to TRUE for each new Tetrahedron. */ for (i = 0; i < 3; i++) new_tet[i]->canonize_info->part_of_coned_cell = TRUE; /* * Set each new "exterior" face to have the same face_status * as the corresponding old face. */ for (i = 0; i < 3; i++) for (j = 0; j < 2; j++) new_tet[i]->canonize_info->face_status[j] = tet[j]->canonize_info->face_status[v[j][i]]; /* * Set each new "interior" face to have face_status inside_cone_face. */ for (i = 0; i < 3; i++) for (j = 2; j < 4; j++) new_tet[i]->canonize_info->face_status[j] = inside_cone_face; } /* * Compute CuspNbhdPositions for the new Tetrahedra iff * the old Tetrahedra had CuspNbhdPositions. */ if (tet[0]->cusp_nbhd_position != NULL) { /* * Begin with a quick error check. */ if (new_tet[0]->shape[complete] == NULL) uFatalError("two_to_three", "simplify_triangulation"); /* * Allocate space for the CuspNbhdPositions of the new Tetrahedra. */ for (i = 0; i < 3; i++) new_tet[i]->cusp_nbhd_position = NEW_STRUCT(CuspNbhdPosition); /* * Compute the CuspNbhdPositions for each of the three new Tetrahedra. */ for (i = 0; i < 3; i++) /* * Consider both the right_handed and left_handed sheets. */ for (h = 0; h < 2; h++) { /* * Compute the polar CuspNbhdPositions. * * Technical note: The new_tets are all seen with the * left_handed Orientation. So when old_orientation[] * is also left_handed, we want to read the new sheet h * from the old sheet h. But when old_orientation[] is * right_handed, we want to read the new sheet h from the * old sheet !h. Because left_handed == 1, the expression * (old_orientation[] == h) gives the correct old sheet * to read from. */ for (j = 0; j < 2; j++) { if (tet[j]->cusp_nbhd_position->in_use[old_orientation[j]==h][v[j][3]] == TRUE) { new_tet[i]->cusp_nbhd_position->x[h][!j][2] = tet[j]->cusp_nbhd_position->x[old_orientation[j]==h][v[j][3]][v[j][(i+1)%3]]; new_tet[i]->cusp_nbhd_position->x[h][!j][3] = tet[j]->cusp_nbhd_position->x[old_orientation[j]==h][v[j][3]][v[j][(i+2)%3]]; cn_find_third_corner(new_tet[i], h, !j, 2, 3, j); new_tet[i]->cusp_nbhd_position->in_use[h][!j] = TRUE; } else { new_tet[i]->cusp_nbhd_position->x[h][!j][2] = Zero; new_tet[i]->cusp_nbhd_position->x[h][!j][3] = Zero; new_tet[i]->cusp_nbhd_position->x[h][!j][j] = Zero; new_tet[i]->cusp_nbhd_position->in_use[h][!j] = FALSE; } } /* * Compute the equatorial CuspNbhdPositions. * * The three new Tetrahedra are seen in the left_handed * Orientation, as is the old tet[0]. So if we coordinates * coordinates from tet[0] we know the sheets will match up. */ for (j = 2; j < 4; j++) { if (tet[0]->cusp_nbhd_position->in_use[h][v[0][(i+j+2)%3]] == TRUE) { new_tet[i]->cusp_nbhd_position->x[h][j][5-j] = tet[0]->cusp_nbhd_position->x[h][v[0][(i+j+2)%3]][v[0][(4+i-j)%3]]; new_tet[i]->cusp_nbhd_position->x[h][j][1] = tet[0]->cusp_nbhd_position->x[h][v[0][(i+j+2)%3]][v[0][3]]; cn_find_third_corner(new_tet[i], h, j, 5-j, 1, 0); new_tet[i]->cusp_nbhd_position->in_use[h][j] = TRUE; } else { new_tet[i]->cusp_nbhd_position->x[h][j][5-j] = Zero; new_tet[i]->cusp_nbhd_position->x[h][j][ 1 ] = Zero; new_tet[i]->cusp_nbhd_position->x[h][j][ 0 ] = Zero; new_tet[i]->cusp_nbhd_position->in_use[h][j] = FALSE; } } } } /* * Put the new Tetrahedra on the list, and remove and free * the old ones. */ for (i = 0; i < 3; i++) INSERT_BEFORE(new_tet[i], tet[0]); for (i = 0; i < 2; i++) { REMOVE_NODE(tet[i]); free_tetrahedron(tet[i]); } *num_tetrahedra_ptr += 1; return func_OK; } /* * one_to_four() performs a one-to-four move, replacing a Tetrahedron * with four new Tetrahedra meeting at a finite vertex. It adds * the four new Tetrahedra and the four new EdgeClasses to the * appropriate lists. */ void one_to_four( Tetrahedron *tet, int *num_tetrahedra_ptr, int new_cusp_index) { int c, h, i, j, k; Tetrahedron *new_tet[4]; Cusp *new_cusp; EdgeClass *new_class[4]; /* * It doesn't make sense to call this function when a hyperbolic * structure, VertexCrossSections or a CuspNbhdPosition are present. */ if (tet->shape[complete] != NULL || tet->cross_section != NULL || tet->cusp_nbhd_position != NULL) uFatalError("one_to_four", "simplify_triangulation"); /* * To understand this code, I recommend you first make a drawing * of a truncated ideal tetrahedron, and draw its subdivision into * four tetrahedra meeting at the center. The four new Tetrahedra * are indexed in the natural way: each vertex which coincides with * a vertex of the old Tetrahedron inherits the latter's VertexIndex, * while the vertex at the center gets the VertexIndex from the * "opposite" vertex of the old Tetrahedron. * * Note that if the manifold is oriented, this scheme preserves * the orientation. */ /* * Allocate space for the new Tetrahedra. * * new_tet[i] will be the new Tetrahedron incident to face i * of the old Tetrahedron. */ for (i = 0; i < 4; i++) { new_tet[i] = NEW_STRUCT(Tetrahedron); initialize_tetrahedron(new_tet[i]); } /* * Set neighbors and gluings. * * This code works even if some of tet's external faces * are glued to each other. */ for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) if (j == i) /* "external" neighbor */ { new_tet[i]->neighbor[j] = tet->neighbor[i]; new_tet[i]->gluing[j] = tet->gluing[i]; set_inverse_neighbor_and_gluing(new_tet[i], j); } else { /* "internal" neighbor */ new_tet[i]->neighbor[j] = new_tet[j]; new_tet[i]->gluing[j] = CREATE_PERMUTATION( remaining_face[i][j], remaining_face[i][j], remaining_face[j][i], remaining_face[j][i], i, j, j, i); } /* * Create a Cusp structure for the finite vertex. */ new_cusp = NEW_STRUCT(Cusp); initialize_cusp(new_cusp); new_cusp->is_finite = TRUE; new_cusp->index = new_cusp_index; INSERT_BEFORE(new_cusp, tet->cusp[0]); /* * Set the new Tetrahedra's cusp fields. */ for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) new_tet[i]->cusp[j] = j == i ? new_cusp : /* finite vertex */ tet->cusp[j]; /* ideal vertex */ /* * Set the peripheral curves. */ for (c = 0; c < 2; c++) /* which curve */ for (h = 0; h < 2; h++) /* which sheet */ for (i = 0; i < 4; i++) /* which tetrahedron */ for (j = 0; j < 4; j++) /* which vertex */ if (j == i) /* * Set the peripheral curves on the finite vertex * to zero. */ for (k = 0; k < 4; k++) /* which side */ new_tet[i]->curve[c][h][i][k] = 0; else /* * Set the curves on the new ideal vertices in * terms of those on the old. */ for (k = 0; k < 4; k++) /* which side */ if (k == j) /* * The j-th vertex has no j-th side. * Do nothing. */ ; else if (k == i) /* * The i-th side of vertex j on new * Tetrahedron i coinicdes with the * i-th side of vertex j on the old * Tetrahedron. */ new_tet[i]->curve[c][h][j][i] = tet->curve[c][h][j][i]; else /* * Compute the new side as a FLOW * between two of the old sides. */ new_tet[i]->curve[c][h][j][k] = FLOW( tet->curve[c][h][j][k], tet->curve[c][h][j][i]); /* * Create the new EdgeClasses. */ for (i = 0; i < 4; i++) { new_class[i] = NEW_STRUCT(EdgeClass); initialize_edge_class(new_class[i]); new_class[i]->order = 3; new_class[i]->incident_tet = new_tet[!i]; new_class[i]->incident_edge_index = edge_between_vertices[i][!i]; } /* * Insert the new EdgeClasses at an arbitrary spot in the linked list. */ for (i = 0; i < 4; i++) INSERT_BEFORE(new_class[i], tet->edge_class[0]); /* * Set the edge_class and edge_orientation fields of the new Tetrahedra. */ for (i = 0; i < 4; i++) /* which Tetrahedron */ for (j = 0; j < 4; j++) /* VertexIndex at one end of edge */ for (k = j + 1; k < 4; k++) /* VertexIndex at other end of edge */ { new_tet[i]->edge_class[edge_between_vertices[j][k]] = (j == i || k == i) ? (j == i ? new_class[k] : new_class[j]) : tet->edge_class[edge_between_vertices[j][k]]; new_tet[i]->edge_orientation[edge_between_vertices[j][k]] = (j == i || k == i) ? right_handed : tet->edge_orientation[edge_between_vertices[j][k]]; } /* * Adjust the EdgeClass orders of the preexisting EdgeClasses. * (The orders of the new EdgeClasses were set above.) */ for (i = 0; i < 6; i++) tet->edge_class[i]->order++; /* * Set incident_tets and incident_edge_indices for the preexisting * EdgeClasses. (Those for the new EdgeClasses were set above.) */ for (i = 0; i < 6; i++) { tet->edge_class[i]->incident_tet = new_tet[one_face_at_edge[i]]; tet->edge_class[i]->incident_edge_index = i; } /* * Provide CanonizeInfo for the new Tetrahedra iff the old Tetrahedron * had CanonizeInfo. */ if (tet->canonize_info != NULL) { /* * For each new Tetrahedron . . . */ for (i = 0; i < 4; i++) { /* * Allocate space for the CanonizeInfo. */ new_tet[i]->canonize_info = NEW_STRUCT(CanonizeInfo); /* * Set part_of_coned_cell to TRUE. */ new_tet[i]->canonize_info->part_of_coned_cell = TRUE; /* * Set face_status to inside_cone_face for each "interior" face, * and have it match the old values for the "exterior" faces. */ for (j = 0; j < 4; j++) /* which face */ new_tet[i]->canonize_info->face_status[j] = j == i ? tet->canonize_info->face_status[j] : /* exterior face */ inside_cone_face; /* interior face */ } } /* * Put the new Tetrahedra on the list, and remove and free the old one. */ for (i = 0; i < 4; i++) INSERT_BEFORE(new_tet[i], tet); REMOVE_NODE(tet); free_tetrahedron(tet); *num_tetrahedra_ptr += 3; } static FuncResult edges_of_order_four( EdgeClass *edge, EdgeClass **where_to_resume, int *num_tetrahedra_ptr) { PositionedTet ptet0, ptet; /* * *edge is an EdgeClass of order 4. Look for another EdgeClass * of order 4 which shares a triangle with *edge. If the six * Tetrahedra incident to the two EdgeClasses are all distinct, * then their union is a suspended pentagon which will be * retriangulated with only five Tetrahedra. */ ptet0.tet = edge->incident_tet; ptet0.bottom_face = one_vertex_at_edge[edge->incident_edge_index]; ptet0.right_face = other_vertex_at_edge[edge->incident_edge_index]; ptet0.near_face = remaining_face[ptet0.bottom_face][ptet0.right_face]; ptet0.left_face = remaining_face[ptet0.right_face][ptet0.bottom_face]; ptet0.orientation = right_handed; ptet = ptet0; do { if (ptet.tet->edge_class[edge_between_faces[ptet.near_face][ptet.right_face]]->order == 4) if (try_adjacent_fours(ptet.tet, ptet.near_face, ptet.bottom_face, where_to_resume, num_tetrahedra_ptr) == func_OK) return func_OK; if (ptet.tet->edge_class[edge_between_faces[ptet.near_face][ptet.bottom_face]]->order == 4) if (try_adjacent_fours(ptet.tet, ptet.near_face, ptet.right_face, where_to_resume, num_tetrahedra_ptr) == func_OK) return func_OK; veer_left(&ptet); } while ( ! same_positioned_tet(&ptet, &ptet0)); return func_failed; } static FuncResult try_adjacent_fours( Tetrahedron *tet0, FaceIndex f0, FaceIndex f1, EdgeClass **where_to_resume, int *num_tetrahedra_ptr) { Tetrahedron *tet[6]; FaceIndex f2, f3, g2, g3; int i, j; EdgeClass *class0, *class1; /* * Two nonantipodal EdgeClasses of order 4 lies on tet. The * face between them has index f0. The face not incident to * either has index f1. */ /* * Find the six Tetrahedra adjacent to the EdgeClasses of order 4. */ tet[0] = tet0; f2 = remaining_face[f0][f1]; f3 = remaining_face[f1][f0]; tet[1] = tet0->neighbor[f0]; g2 = EVALUATE(tet0->gluing[f0], f2); g3 = EVALUATE(tet0->gluing[f0], f3); tet[2] = tet[0]->neighbor[f2]; tet[3] = tet[0]->neighbor[f3]; tet[4] = tet[1]->neighbor[g2]; tet[5] = tet[1]->neighbor[g3]; /* * If the six Tetrahedra aren't all distinct, return func_failed. * (Thought question: Might simplification sometimes be possible * even if all six Tetrahedra aren't distinct? Hmmm . . . seems * unlikely.) */ for (i = 0; i < 6; i++) for (j = i + 1; j < 6; j++) if (tet[i] == tet[j]) return func_failed; /* * Note the two EdgeClasses which now have order four. */ class0 = tet0->edge_class[edge_between_faces[f0][f2]]; class1 = tet0->edge_class[edge_between_faces[f0][f3]]; /* * The following two-to-three move increases the number of * Tetrahedra by one, but it creates two EdgeClasses of * order three . . . */ if (two_to_three(tet0, f0, num_tetrahedra_ptr) == func_failed) { /* * (There can't be any topological obstruction to the * retriangulation, but there might be a geometric obstruction, * namely that the two_to_three() move might require creation * of degenerate Tetrahedra. So if two_to_three() fails when * a hyperbolic structure is present, we assume (potential) * degenerate Tetrahedra are the cause, and we return func_failed. * Otherwise we call uFatalError().) */ if (tet0->shape[complete] != NULL) return func_failed; else uFatalError("try_adjacent_fours", "simplify_triangulation"); } /* * . . . each of which can be used to reduce the number of * Tetrahedra by one. */ if (three_to_two(class0, where_to_resume, num_tetrahedra_ptr) == func_failed || three_to_two(class1, where_to_resume, num_tetrahedra_ptr) == func_failed) uFatalError("try_adjacent_fours", "simplify_triangulation"); /* * Note that where_to_resume will come out pointing to some * valid EdgeClass. We won't worry too much about just which * one it points at. */ return func_OK; } static FuncResult create_new_order_four( EdgeClass *edge, EdgeClass **where_to_resume, int *num_tetrahedra_ptr) { PositionedTet ptet0, ptet; if (edge->order != 4) return func_failed; /* * create_new_order_four() is similar to edges_of_order_four(). * * *edge is an EdgeClass of order 4. Look for another EdgeClass * of order 5 or less which shares a triangle with *edge. * If the four Tetrahedra incident to *edge are all distinct, * then their union is an octagon which will be retriangulated * so as to create a new EdgeClass of order 4 or less. */ ptet0.tet = edge->incident_tet; ptet0.bottom_face = one_vertex_at_edge[edge->incident_edge_index]; ptet0.right_face = other_vertex_at_edge[edge->incident_edge_index]; ptet0.near_face = remaining_face[ptet0.bottom_face][ptet0.right_face]; ptet0.left_face = remaining_face[ptet0.right_face][ptet0.bottom_face]; ptet0.orientation = right_handed; if (four_tetrahedra_are_distinct(ptet0) == FALSE) return func_failed; ptet = ptet0; do { if (ptet.tet->edge_class[edge_between_faces[ptet.near_face][ptet.right_face ]]->order <= 5 || ptet.tet->edge_class[edge_between_faces[ptet.near_face][ptet.bottom_face]]->order <= 5) { if (two_to_three(ptet.tet, ptet.near_face, num_tetrahedra_ptr) == func_OK) { if (three_to_two(edge, where_to_resume, num_tetrahedra_ptr) == func_OK) return func_OK; else uFatalError("create_new_order_four", "simplify_triangulation"); } else { /* * The call to two_to_three() failed. It can't fail for * topological reasons (we checked that the four Tetrahedra * surrounding the EdgeClass of order 4 are distinct), but * if a hyperbolic structure is present it might fail * because two antipodal vertices of the octahedron * coincide. In the latter case, we simply move on in * the hope that a different retriangulation will work. */ if (ptet.tet->shape[complete] == NULL) uFatalError("create_new_order_four", "simplify_triangulation"); /* * else continue with do loop */ } } veer_left(&ptet); } while ( ! same_positioned_tet(&ptet, &ptet0)); return func_failed; } static Boolean four_tetrahedra_are_distinct( PositionedTet ptet) { int i, j; Tetrahedron *tet[4]; for (i = 0; i < 4; i++) { tet[i] = ptet.tet; veer_left(&ptet); } for (i = 0; i < 4; i++) for (j = i + 1; j < 4; j++) if (tet[i] == tet[j]) return FALSE; return TRUE; } static void set_inverse_neighbor_and_gluing( Tetrahedron *tet, FaceIndex f) { tet->neighbor[f]->neighbor[EVALUATE(tet->gluing[f], f)] = tet; tet->neighbor[f]->gluing [EVALUATE(tet->gluing[f], f)] = inverse_permutation[tet->gluing[f]]; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/sl2c_matrices.c000644 000765 000024 00000006745 12377774107 021715 0ustar00babstaff000000 000000 /* * sl2c_matrices.c * * This file provides the following functions for working with SL2CMatrices: * * void sl2c_copy(SL2CMatrix dest, CONST SL2CMatrix source); * void sl2c_invert(CONST SL2CMatrix a, SL2CMatrix inverse); * void sl2c_complex_conjugate(CONST SL2CMatrix a, SL2CMatrix conjugate); * void sl2c_product(CONST SL2CMatrix a, CONST SL2CMatrix b, SL2CMatrix product); * void sl2c_adjoint(CONST SL2CMatrix a, SL2CMatrix adjoint); * Complex sl2c_determinant(CONST SL2CMatrix a); * void sl2c_normalize(SL2CMatrix a); * Boolean sl2c_matrix_is_real(CONST SL2CMatrix a); */ #include "kernel.h" #include "kernel_namespace.h" void sl2c_copy( SL2CMatrix dest, CONST SL2CMatrix source) { int i, j; for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) dest[i][j] = source[i][j]; } void sl2c_invert( CONST SL2CMatrix a, SL2CMatrix inverse) { Complex temp; temp = a[0][0]; inverse[0][0] = a[1][1]; inverse[1][1] = temp; inverse[0][1] = complex_negate(a[0][1]); inverse[1][0] = complex_negate(a[1][0]); } void sl2c_complex_conjugate( CONST SL2CMatrix a, SL2CMatrix conjugate) { int i, j; for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) conjugate[i][j] = complex_conjugate(a[i][j]); } void sl2c_product( CONST SL2CMatrix a, CONST SL2CMatrix b, SL2CMatrix product) { int i, j; SL2CMatrix temp; for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) temp[i][j] = complex_plus ( complex_mult(a[i][0], b[0][j]), complex_mult(a[i][1], b[1][j]) ); for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) product[i][j] = temp[i][j]; } void sl2c_adjoint( CONST SL2CMatrix a, SL2CMatrix adjoint) { int i, j; SL2CMatrix temp; /* * We initially write the result into a temporary matrix, * so that if the matrices a and adjoint are the same the * [1][0] entry won't overwrite the [0][1] entry. */ for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) temp[i][j] = complex_conjugate(a[j][i]); for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) adjoint[i][j] = temp[i][j]; } Complex sl2c_determinant( CONST SL2CMatrix a) { return( complex_minus ( complex_mult(a[0][0], a[1][1]), complex_mult(a[0][1], a[1][0]) ) ); } void sl2c_normalize( SL2CMatrix a) { /* * If the matrix a is nonsingular, normalize it to have determinant one. * Otherwise, generate an error message and quit. */ int i, j; Complex det, factor; det = sl2c_determinant(a); if (complex_nonzero(det) == FALSE) { uFatalError("sl2c_normalize", "sl2c_matrices"); return; } factor = complex_sqrt(det); for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) a[i][j] = complex_div(a[i][j], factor); } Boolean sl2c_matrix_is_real( CONST SL2CMatrix a) { int i, j; for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) if (a[i][j].imag != 0.0) return FALSE; return TRUE; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/SnapPea.h000644 000765 000024 00000314723 12377774107 020515 0ustar00babstaff000000 000000 /* * SnapPea.h * * This file defines the interface between SnapPea's comptational kernel * ("the kernel") and the user-interface ("the UI"). Both parts * must #include this file, and anything shared between the two parts * must be declared in this file. The only communication between the * two parts is via function calls -- no external variables are shared. * * All external symbols in the UI must begin with 'u' followed by a * capital letter. Nothing in the kernel should begin in this way. * * Typedef names use capitals for the first letter of each word, * e.g. Triangulation, CuspIndex. * * SnapPea 2.0 was funded by the University of Minnesota's * Geometry Center and the U.S. National Science Foundation. * SnapPea 3.0 is funded by the U.S. National Science Foundation * and the MacArthur Foundation. SnapPea and its source code may * be used freely for all noncommercial purposes. Please direct * questions, problems and suggestions to Jeff Weeks (weeks@northnet.org). * * Copyright 1999 by Jeff Weeks. All rights reserved. */ #ifndef _SnapPea_ #define _SnapPea_ #include "real_type.h" #include "kernel_namespace.h" /* * Note: values of the SolutionType enum are stored as integers in * the triangulation.doc file format. Changing the order of the * entries in the enum would therefore invalidate all previously stored * triangulations. */ typedef int SolutionType; enum { not_attempted, /* solution not attempted, or user cancelled */ geometric_solution, /* all positively oriented tetrahedra; not flat or degenerate */ nongeometric_solution, /* positive volume, but some negatively oriented tetrahedra */ flat_solution, /* all tetrahedra flat, but no shapes = {0, 1, infinity} */ degenerate_solution, /* at least one tetrahedron has shape = {0, 1, infinity} */ other_solution, /* volume <= 0, but not flat or degenerate */ no_solution, /* gluing equations could not be solved */ externally_computed /* tetrahedra shapes were inserted into the triangulation */ }; /* * The constants complete and filled facilitate reference * to the shape of a Tetrahedron as part of the complete or * Dehn filled hyperbolic structure, respectively. */ typedef int FillingStatus; enum { complete, filled }; typedef int FuncResult; enum { func_OK = 0, func_cancelled, func_failed, func_bad_input }; typedef struct { Real real, imag; } Complex; /*MC 02/01/08*/ typedef char Boolean; /* * The values of MatrixParity should not be changed. * (They must correspond to the values in the parity[] table in tables.c.) */ typedef int MatrixParity; enum { orientation_reversing = 0, orientation_preserving = 1 }; /* * SnapPea represents a Moebius transformation as a matrix * in SL(2,C) plus a specification of whether the Moebius * transformation is orientation_preserving or orientation_reversing. * * If mt->parity is orientation_preserving, then mt->matrix is * interpreted in the usual way as the Moebius transformation * * az + b * f(z) = -------- * cz + d * * * If mt->parity is orientation_reversing, then mt->matrix is * interpreted as a function of the complex conjugate z' ("z-bar") * * az' + b * f(z) = --------- * cz' + d */ typedef Complex SL2CMatrix[2][2]; typedef struct { SL2CMatrix matrix; MatrixParity parity; } MoebiusTransformation; /* * Matrices in O(3,1) represent isometries in the Minkowski space * model of hyperbolic 3-space. The matrices are expressed relative * to a coordinate system in which the metric is * * -1 0 0 0 * 0 1 0 0 * 0 0 1 0 * 0 0 0 1 * * That is, the first coordinate is timelike, and the remaining * three are spacelike. O(3,1) matrices represent both * orientation_preserving and orientation_reversing isometries. */ typedef Real O31Matrix[4][4]; typedef Real GL4RMatrix[4][4]; /* * An O31Vector is a vector in (3,1)-dimensional Minkowski space. * The 0-th coordinate is the timelike one. */ typedef Real O31Vector[4]; /* * MatrixInt22 is a 2 x 2 integer matrix. A MatrixInt22 * may, for example, describe how the peripheral curves of * one Cusp map to those of another. */ typedef int MatrixInt22[2][2]; /* * An AbelianGroup is represented as a sequence of torsion coefficients. * A torsion coefficient of 0 represents an infinite cyclic factor. * For example, the group Z + Z + Z/2 + Z/5 is represented as the * sequence (0, 0, 2, 5). We make the convention that torsion coefficients * are always nonnegative. * * The UI may declare pointers to AbelianGroups, but only the kernel * may allocate or deallocate the actual memory used to store an * AbelianGroup. (This allows the kernel to keep track of memory * allocation/deallocation as a debugging aid.) */ typedef struct { int num_torsion_coefficients; /* number of torsion coefficients */ long int *torsion_coefficients; /* pointer to array of torsion coefficients */ } AbelianGroup; /* * A closed geodesic may be topologically a circle or a mirrored interval. */ typedef int Orbifold1; enum { orbifold1_unknown, orbifold_s1, /* circle */ orbifold_mI /* mirrored interval */ }; /* * The following 2-orbifolds may occur as the link of an * edge midpoint in a cell decomposition of a 3-orbifold. * * 94/10/4. The UI will see only types orbifold_nn * and orbifold_xnn. Edges of the other types have 0-cells * of the singular set at their midpoints, and are now * subdivided in Dirichlet_extras.c. JRW */ typedef int Orbifold2; enum { orbifold_nn, /* (nn) 2-sphere with two cone points (n may be 1) */ orbifold_no, /* (n|o) cross surface with cone point (n may be 1) */ orbifold_xnn, /* (*nn) disk with mirror boundary with two */ /* corner reflectors */ orbifold_2xn, /* (2*n) disk with order two cone point and mirror */ /* boundary with one corner reflector */ orbifold_22n /* (22n) sphere with three cone points */ }; /* * A MultiLength records the complex length of a geodesic together with a * parity telling whether it preserves or reverses orientation, a topology * telling whether it's a circle or a mirrored interval, and a multiplicity * telling how many distinct geodesics have that complex length, parity and * topology. */ typedef struct { Complex length; MatrixParity parity; Orbifold1 topology; int multiplicity; } MultiLength; /* * A CuspNbhdHoroball records a horoball to be drawn as part of a * picture of a cusp cross section. Only the kernel should allocate * and free CuspNbhdHoroballs and CuspNbhdHoroballLists. These * definitions are provided to the UI so it access the data easily. */ typedef struct { Complex center; Real radius; int cusp_index; } CuspNbhdHoroball; typedef struct { /* * The horoball field points to an array * of num_horoballs CuspNbhdHoroballs. */ int num_horoballs; CuspNbhdHoroball *horoball; } CuspNbhdHoroballList; /* * A CuspNbhdSegment records a 1-cell to be drawn as part of a * picture of a cusp cross section. (Typically it's either part of * a triangulation of the cusp cross section, or part of a Ford domain.) * Only the kernel should allocate and free CuspNbhdSegments and * CuspNbhdSegmentLists. These definitions are provided to the UI * so it can easily access the data. * * JRW 99/03/17 When the CuspNbhdSegment describes a triangulation * (as opposed to a Ford domain), * * the start_index tells the edge index of the vertical edge * that runs from the given segment's beginning * to the viewer's eye, * * the middle_index tells the edge index of the given segment, and * * the end_index tells the edge index of the vertical edge * that runs from the given segment's end * to the viewer's eye. * * These indices let the viewer see how the horoball picture * "connects up" to form the manifold. */ typedef struct { Complex endpoint[2]; int start_index, middle_index, end_index; } CuspNbhdSegment; typedef struct { /* * segment is a pointer to an array of num_segments CuspNbhdSegments. */ int num_segments; CuspNbhdSegment *segment; } CuspNbhdSegmentList; typedef int Orientability; enum { oriented_manifold, nonorientable_manifold, unknown_orientability }; typedef int CuspTopology; enum { torus_cusp, Klein_cusp, unknown_topology }; typedef int DirichletInteractivity; enum { Dirichlet_interactive, Dirichlet_stop_here, Dirichlet_keep_going }; /* * An LRFactorization specifies the monodromy for a punctured torus * bundle over a circle. The factorization is_available whenever * (det(monodromy) = +1 and |trace(monodromy)| >= 2) or * (det(monodromy) = -1 and |trace(monodromy)| >= 1). * LR_factors points to an array of L's and R's, interpreted as factors * * L = ( 1 0 ) R = ( 1 1 ) * ( 1 1 ) ( 0 1 ) * * The factors act on a column vector, beginning with the last * (i.e. rightmost) factor. * * If negative_determinant is TRUE, the product is left-multiplied by * * ( 0 1 ) * ( 1 0 ) * * If negative_trace is TRUE, the product is left-multiplied by * * (-1 0 ) * ( 0 -1 ) * * When the factorization is unavailable, is_available is set to FALSE, * num_LR_factors is set to zero, and LR_factors is set to NULL. * But the negative_determinant and negative_trace flags are still set, * so the UI can display this information correctly. */ typedef struct { Boolean is_available, negative_determinant, negative_trace; int num_LR_factors; char *LR_factors; } LRFactorization; /* * The full definition of a Shingling appears near the top of shingling.c. * But computationally a Shingling is just a collection of planes in * hyperbolic space (typically viewed as circles on the sphere at infinity). * Each plane has an index (which defines the color of the circle at * infinity). */ typedef struct { /* * A plane in hyperbolic 3-space defines a hyperplane through * the origin in the Minkowski space model. Use the hyperplane's * normal vector to represent the original plane. [Note: the * normal is computed once, in the standard coordinate system, * and does not change as the UI rotates the polyhedron.] */ O31Vector normal; /* * A plane in hyperbolic 3-space intersects the sphere at infinity * in a circle. It's easy to draw the circle if we know its center * and two orthogonal "radials". (The 0-components of the center * and radials may be ignored.) [Note: the center and radials are * rotated in real time according to the polyhedron's current * position, and are scaled according to the window's pixel size.] */ O31Vector center, radialA, radialB; /* * The face planes of the original Dirichlet domain have index 0, * the face planes of the next layer (cf. shingling.c) have index 1, * and so on. */ int index; } Shingle; typedef struct { /* * A Shingling is just an array of Shingles. */ int num_shingles; Shingle *shingles; } Shingling; /* * The following are "opaque typedefs". They let the UI declare and * pass pointers to Triangulations, IsometryLists, etc. without * knowing what a Triangulation, IsometryList, etc. is. The definitions * of struct Triangulation, struct IsometryList, etc. are private to the * kernel. SymmetryLists and IsometryLists are represented by the same * data structure because Symmetries are just Isometries from a manifold * to itself. */ typedef struct Triangulation Triangulation; typedef struct IsometryList IsometryList; typedef struct SymmetryGroup SymmetryGroup; typedef struct SymmetryGroupPresentation SymmetryGroupPresentation; typedef struct DualOneSkeletonCurve DualOneSkeletonCurve; typedef struct TerseTriangulation TerseTriangulation; typedef struct GroupPresentation GroupPresentation; typedef struct CuspNeighborhoods CuspNeighborhoods; typedef struct NormalSurfaceList NormalSurfaceList; #include "end_namespace.h" /* * winged_edge.h describes the winged edge data structure used * to describe Dirichlet domains. */ #include "winged_edge.h" /* * tersest_triangulation.h describes the most compressed form * for a Triangulation. The UI must have the actual definition * (not just an opaque typedef) because to read one from the * middle of a file it needs to know how long they are. */ #include "tersest_triangulation.h" /* * link_projection.h describes the format in which the UI passes * link projections to the kernel. */ #include "link_projection.h" /* * When the UI reads a Triangulation from disk, it passes the results * to the kernel using the format described in triangulation_io.h. */ #include "triangulation_io.h" /* * covers.h defines a representation of a manifold's fundamental group * into the symmetric group on n letters. */ #include "covers.h" /* MC 01/26/08 * homology.h defines a structure used to store a relation matrix for * the first homology group. */ #include "homology.h" /* To guarantee thread-safety, it's useful to declare */ /* global variables to be "const", for example */ /* */ /* static const Complex minus_i = {0.0, -1.0}; */ /* */ /* Unfortunately the current gcc compiler complains when */ /* non-const variables are passed to functions expecting */ /* const arguments. Obviously this is harmless, but gcc */ /* complains anyhow. So for now let's use the following */ /* CONST macro, to allow the const declarations to be */ /* reactivated if desired. */ /* */ /* Note: In Win32, windef.h also defines CONST = const, */ /* so clear its definition before making our own. */ #undef CONST #define CONST /* #define CONST const */ /* We build the snappea kernel as C++, so link it as C++. - B.B., 27/03/2014. #ifdef __cplusplus extern "C" { #endif */ /************************************************************************/ #include "kernel_namespace.h" /* * The UI provides the following functions for use by the kernel: */ extern void uAcknowledge(const char *message); /* * Presents the string *message to the user and waits for acknowledgment ("OK"). */ extern int uQuery(const char *message, const int num_responses, const char *responses[], const int default_response); /* * Presents the string *message to the user and asks the user to choose * one of the responses. Returns the number of the chosen response * (numbering starts at 0). In an interactive context, the UI should * present the possible responses evenhandedly -- none should be * presented as a default. However, in a batch context (when no human * is present), uQuery should return the default_response. */ extern void uFatalError(const char *function, const char *file); /* * Informs the user that a fatal error has occurred in the given * function and file, and then exits. */ extern void uAbortMemoryFull(void); /* * Informs the user that the available memory has been exhausted, * and aborts SnapPea. */ extern void uPrepareMemFullMessage(void); /* * uMemoryFull() is a tricky function, because the system may not find * enough memory to display an error message. (I tried having it stash * away some memory and then free it to support the desired dialog box, * but at least on the Mac this didn't work for some unknown reason.) * uPrepareMemFullMessage() gives the system a chance to prepare * a (hidden) dialog box. Call it once when the UI initializes. */ extern void uLongComputationBegins(const char *message, Boolean is_abortable); extern FuncResult uLongComputationContinues(void); extern void uLongComputationEnds(void); /* * The kernel uses these three functions to inform the UI of a long * computation. The UI relays this information to the user in whatever * manner it considers appropriate. For example, it might wait a second * or two after the beginning of a long computation, and then display * a dialog box containing *message (a typical message might be * "finding canonical triangulation" or "computing hyperbolic structure"). * If is_abortable is TRUE, the dialog box would contain an abort button. * The reason for waiting a second or two before displaying the dialog * box is to avoid annoying the user with flashing dialog boxes for * computations which turn out not to be so long after all. * * The kernel is responsible for calling uLongComputationContinues() at * least every 1/60 second or so during a long computation. * uLongComputationContinues() serves two purposes: * * (1) It lets the UI yield time to its window system. (This is * crucial for smooth background operation in the Mac's * cooperative multitasking environment. I don't know whether * it is necessary in X or NeXT.) * * (2) If the computation is abortable, it checks whether the user * has asked to abort, and returns the result (func_cancelled * to abort, func_OK to continue). * * While the kernel is responsible for making sure uLongComputationContinues() * is called often enough, uLongComputationContinues() itself must take * responsibility for not repeating time-consuming operations too often. * For example, it might return immediately from a call if less than * 1/60 of a second has elapsed since the last time it carried out * its full duties. * * uLongComputationEnds() signals that the long computation is over. * The kernel must call uLongComputationEnds() even after an aborted * computation. ( uLongComputationContinues() merely informs the kernel * that the user punched the abort button. The kernel must still call * uLongComputationEnds() to dismiss the dialog box in the usual way.) * * If the UI receives a call to uLongComputationEnds() when no long * computation is in progress, or a call to uLongComputationBegins() * when a long computation is already in progress, it should notify * the user of the error and exit. * * If the UI receives a call to uLongComputationContinues() when in * fact no long computation is in progress, it should simply take * care of any background responsibilities (see (1) above) and not * complain. The reason for this provision is that the calls to * uLongComputationBegins() and uLongComputationEnds() occur in high * level functions, while the calls to uLongComputationContinues() * occur at the lowest level, perhaps in a different file. Someday * those low-level functions (for example, the routines for solving * simultaneous linear equations) might be called as part of some quick, * non-abortable computation. */ /************************************************************************/ /************************************************************************/ /* * The kernel provides the following functions for use by the UI. * * A brief specification follows each function prototype. * Complete documentation appears in the corresponding source file. */ /************************************************************************/ /* */ /* abelian_group.c */ /* */ /************************************************************************/ extern void expand_abelian_group(AbelianGroup *g); /* * Expands an AbelianGroup into its most factored form, * e.g. Z/2 + Z/2 + Z/4 + Z/3 + Z/9 + Z. * Each nonzero torsion coefficient is a power of a prime. */ extern void compress_abelian_group(AbelianGroup *g); /* * Compresses an AbelianGroup into its least factored form, * Z/2 + Z/6 + Z/36 + Z. * Each torsion coefficient divides all subsequent torsion coefficients. */ extern void free_abelian_group(AbelianGroup *g); /* * Frees the storage used to hold the AbelianGroup *g. */ /************************************************************************/ /* */ /* canonize.c */ /* canonize_part_1.c */ /* canonize_part_2.c */ /* */ /************************************************************************/ extern FuncResult canonize(Triangulation *manifold); /* * Replaces the given Triangulation with the canonical retriangulation * of the canonical cell decomposition. Returns func_OK upon success, * func_failed if it cannot find a hyperbolic structure for *manifold. */ extern FuncResult proto_canonize(Triangulation *manifold); extern void canonical_retriangulation(Triangulation *manifold); /* * These functions comprise the two halves of canonize() in canonize.c. * * proto_canonize() replaces a Triangulation by the canonical * triangulation of the same manifold (if the canonical cell * decomposition is a triangulation) or by an arbitrary subdivision * of the canonical cell decomposition into Tetrahedra (if the canonical * cell decomposition contains cells other than tetrahedra). * Returns func_OK upon success, func_failed if it cannot find a * hyperbolic structure for *manifold. * * canonical_retriangulation() replaces the given subdivision of the * canonical cell decomposition with the canonical retriangulation. * This operation introduces finite vertices whenever the canonical cell * decomposition is not a triangulation to begin with. The hyperbolic * structure is discarded. */ extern Boolean is_canonical_triangulation(Triangulation *manifold); /* * Given a subdivision of the canonical cell decomposition as produced * by proto_canonize(), says whether it is the canonical decomposition * itself. In other words, it says whether the canonical cell decomposition * is a triangulation. */ /************************************************************************/ /* */ /* change_peripheral_curves.c */ /* */ /************************************************************************/ extern FuncResult change_peripheral_curves( Triangulation *manifold, CONST MatrixInt22 change_matrices[]); /* * If all the change_matrices have determinant +1, installs the * corresponding new peripheral curves and returns func_OK. * (See change_peripheral_curves.c for details.) * Otherwise does nothing and returns func_bad_input. */ /************************************************************************/ /* */ /* chern_simons.c */ /* */ /************************************************************************/ extern void set_CS_value( Triangulation *manifold, Real a_value); /* * Set the Chern-Simons invariant of *manifold to a_value. */ extern void get_CS_value( Triangulation *manifold, Boolean *value_is_known, Real *the_value, int *the_precision, Boolean *requires_initialization); /* * If the Chern-Simons invariant of *manifold is known, sets * *value_is_known to TRUE and writes the current value and its precision * (the number of significant digits to the right of the decimal point) * to *the_value and *the_precision, respectively. * * If the Chern-Simons invariant is not known, sets *value_is_known to * FALSE, and then sets *requires_initialization to TRUE if the_value * is unknown because the computation has not been initialized, or * to FALSE if the_value is unknown because the solution contains * negatively oriented Tetrahedra. The UI might want to convey * these situations to the user in different ways. */ /************************************************************************/ /* */ /* complex.c */ /* */ /************************************************************************/ extern Complex complex_minus (Complex z0, Complex z1), complex_plus (Complex z0, Complex z1), complex_mult (Complex z0, Complex z1), complex_div (Complex z0, Complex z1), complex_sqrt (Complex z), complex_conjugate (Complex z), complex_negate (Complex z), complex_real_mult (Real r, Complex z), complex_exp (Complex z), complex_log (Complex z, Real approx_arg); extern Real complex_modulus (Complex z); extern Real complex_modulus_squared (Complex z); extern Boolean complex_nonzero (Complex z); extern Boolean complex_infinite (Complex z); /* * The usual complex arithmetic functions. * * Standard complex constants (Zero, One, etc.) are defined in the kernel. */ /************************************************************************/ /* */ /* complex_length.c */ /* */ /************************************************************************/ extern Complex complex_length_mt(MoebiusTransformation *mt); extern Complex complex_length_o31(O31Matrix m); /* * Computes the complex length of an isometry. Please see * complex_length.c for full definitions and explanations. * complex_length_mt() and complex_length_o31() are identical except * for the form in which the input is given. */ /************************************************************************/ /* */ /* continued_fractions.c */ /* */ /************************************************************************/ extern Boolean appears_rational(Real x0, Real x1, Real confidence, long *num, long *den); /* * Checks whether a finite-precision real number x known to lie in the * interval (x0, x1) appears to be a rational number p/q. If it does, * it sets *num and *den to p and q, respectively, and returns TRUE. * Otherwise it sets *num and *den to 0 and returns FALSE. * The confidence parameter gives the maximal acceptable probability * of a "false positive". */ /************************************************************************/ /* */ /* core_geodesic.c */ /* */ /************************************************************************/ extern void core_geodesic( Triangulation *manifold, int cusp_index, int *singularity_index, Complex *core_length, int *precision); /* * Examines the Cusp of index cusp_index in *manifold. * * If the Cusp is unfilled or the Dehn filling coefficients are not * integers, sets *singularity_index to zero and leaves *core_length * undefined. * * If the Cusp has relatively prime integer Dehn filling coefficients, * sets *singularity_index to 1 and *core_length to the complex length * of the central geodesic. * * If the Cusp has non relatively prime integer Dehn filling coefficients, * sets *singularity_index to the index of the singular locus, and * *core_length to the complex length of the central geodesic in the * smallest manifold cover of a neighborhood of the singular set. * * In the latter two cases, if the precision pointer is not NULL, * *precision is set to the number of decimal places of accuracy in * the computed value of *core_length. * * core_geodesic() is intended for use by the UI. Kernel function may * find compute_core_geodesic() (declared in kernel_prototypes.h) more * convenient. */ /************************************************************************/ /* */ /* cover.c */ /* */ /************************************************************************/ Triangulation *construct_cover( Triangulation *base_manifold, RepresentationIntoSn *representation, int n); /* * Constructs the n-sheeted cover of the given base_manifold defined * by the given transitive representation. */ /************************************************************************/ /* */ /* current_curve_basis.c */ /* */ /************************************************************************/ extern void current_curve_basis( Triangulation *manifold, int cusp_index, MatrixInt22 basis_change); extern void install_current_curve_bases(Triangulation *manifold); /* * current_curve_basis() accepts a Triangulation and a cusp index, * and computes a 2 x 2 integer matrix basis_change with the property * that * * if the Cusp of index cusp_index is filled, and has * relatively prime integer Dehn filling coefficients, * * the first row of basis_change is set to the current * Dehn filling coefficients, and * the second row of basis_change is set to the shortest * curve which completes a basis. * * else * * basis_change is set to the identity * * install_current_curve_bases() installs the above basis * on all cusps of the manifold. */ /************************************************************************/ /* */ /* cusp_neighborhoods.c */ /* */ /************************************************************************/ extern CuspNeighborhoods *initialize_cusp_neighborhoods( Triangulation *manifold); /* * Initializes a CuspNeighborhoods data structure. * It works with a copy of manifold, leaving the original untouched. * It does all indicated Dehn fillings. * Returns a pointer to the CuspNeighborhoods structure upon success, * of NULL if the "manifold" isn't a cusped hyperbolic 3-manifold. */ extern void free_cusp_neighborhoods( CuspNeighborhoods *cusp_neighborhoods); /* * Frees the CuspNeighborhoods structure, including the copy of * the Triangulation it contains. */ extern int get_num_cusp_neighborhoods( CuspNeighborhoods *cusp_neighborhoods); /* * Returns the number of cusps. This will be the number of unfilled * cusps in the original manifold, which may be less than the total * number of cusps. */ extern CuspTopology get_cusp_neighborhood_topology( CuspNeighborhoods *cusp_neighborhoods, int cusp_index); /* * Returns the CuspTopology of the given cusp. */ extern Real get_cusp_neighborhood_displacement( CuspNeighborhoods *cusp_neighborhoods, int cusp_index); /* * Returns the (linear) displacement of the horospherical cross * section of the given cusp from its home position. At the home * position the cusp cross section has area (3/8)sqrt(3) and * encloses a volume of (3/16)sqrt(3) in the cusp. At its home * position, a cusp cannot overlap itself, nor can it overlap any * other cusp which does not already overlap itself. Please see * cusp_neighborhoods.c for details. */ extern Boolean get_cusp_neighborhood_tie( CuspNeighborhoods *cusp_neighborhoods, int cusp_index); /* * Says whether this cusp's neighborhood is tied to other cusps'. */ extern Real get_cusp_neighborhood_cusp_volume( CuspNeighborhoods *cusp_neighborhoods, int cusp_index); /* * Returns the volume enclosed by the horospherical cross section * of the given cusp. */ extern Real get_cusp_neighborhood_manifold_volume( CuspNeighborhoods *cusp_neighborhoods); /* * Returns the volume of the manifold. */ extern Triangulation *get_cusp_neighborhood_manifold( CuspNeighborhoods *cusp_neighborhoods); /* * Returns a pointer to a copy of the manifold. The UI may do as it * pleases with the copy, and should free it when it's done. */ extern Real get_cusp_neighborhood_reach( CuspNeighborhoods *cusp_neighborhoods, int cusp_index); /* * Returns the displacement at which the cusp cross section first * bumps into itself. */ extern Real get_cusp_neighborhood_max_reach( CuspNeighborhoods *cusp_neighborhoods); /* * Returns the maximum reach over the whole manifold. */ extern Real get_cusp_neighborhood_stopping_displacement( CuspNeighborhoods *cusp_neighborhoods, int cusp_index); extern int get_cusp_neighborhood_stopper_cusp_index( CuspNeighborhoods *cusp_neighborhoods, int cusp_index); /* * Return the displacement at which the cusp first bumps into another * cusp (or possibly into itself), and the cusp it bumps into. * Unlike the reach, the stopper and the stopping displacement depend * on the current displacements of all the cusps in the triangulation. * They vary dynamically as the user moves the cusp cross sections. */ extern void set_cusp_neighborhood_displacement( CuspNeighborhoods *cusp_neighborhoods, int cusp_index, Real new_displacement); /* * Sets the cusp neighborhood's displacement to the requested value, * clipping it to the range [0, stopping_displacement] if necessary. * Recomputes the canonical cell decomposition. */ extern void set_cusp_neighborhood_tie( CuspNeighborhoods *cusp_neighborhoods, int cusp_index, Boolean new_tie); /* * Tells the kernel whether this cusp's neighborhood should be * tied to other cusps (which have previously been "tied"). * The kernel makes all tied cusps have the same displacement. */ extern void get_cusp_neighborhood_translations( CuspNeighborhoods *cusp_neighborhoods, int cusp_index, Complex *meridian, Complex *longitude); /* * Returns the meridional and longitudinal translation vectors * for the given cusp cross section, taking into account its current * displacement. For a Klein bottle cusp, the longitudinal translation * will be that of the double cover. As a convenience, the longitude * will always point in the x-direction. */ extern CuspNbhdHoroballList *get_cusp_neighborhood_horoballs( CuspNeighborhoods *cusp_neighborhoods, int cusp_index, Boolean full_list, Real cutoff_height); /* * Returns a list of horoballs seen from the given cusp, taking into * account the cusp cross sections' current displacements. Only one * translate is given for each horoball -- to draw the full picture the * UI must find all visible translates using the meridian and longitude * provided by get_cusp_neighborhood_translations(). For a Klein bottle * cusp, get_cusp_neighborhood_horoballs() reports data for the double * cover. If full_list is TRUE, get_cusp_neighborhood_horoballs() * reports all horoballs whose Euclidean height in the upper half space * model is at least cutoff_height. If full_list is FALSE, it reports * only a few of the largest horoballs (the cutoff_height is ignored). * This lets the UI draw a simpler picture while the user is changing * something in real time, and then draw a more complete picture afterwards. */ extern void free_cusp_neighborhood_horoball_list( CuspNbhdHoroballList *horoball_list); /* * Frees a CuspNbhdHoroballList when the UI's done with it. */ extern CuspNbhdSegmentList *get_cusp_neighborhood_triangulation( CuspNeighborhoods *cusp_neighborhoods, int cusp_index); /* * Returns a list of edges in the restriction of the canonical cell * decomposition to the cusp cross section, taking into account the * cusp cross section's current displacement. Only one translate is * given for each edge -- to draw the full picture the UI must find all * visible translates using the meridian and longitude provided by * get_cusp_neighborhood_translations(). For a Klein bottle cusp, * get_cusp_neighborhood_triangulation() reports data for the double cover. */ extern CuspNbhdSegmentList *get_cusp_neighborhood_Ford_domain( CuspNeighborhoods *cusp_neighborhoods, int cusp_index); /* * Returns a list of edges in the Ford domain, taking into account the * cusp cross section's current displacement. Only one translate is * given for each edge -- to draw the full picture the UI must find all * visible translates using the meridian and longitude provided by * get_cusp_neighborhood_translations(). For a Klein bottle cusp, * get_cusp_neighborhood_Ford_domain() reports data for the double cover. */ extern void free_cusp_neighborhood_segment_list( CuspNbhdSegmentList *segment_list); /* * Frees a CuspNbhdSegmentList when the UI's done with it. */ /************************************************************************/ /* */ /* Dirichlet.c */ /* */ /************************************************************************/ extern WEPolyhedron *Dirichlet( Triangulation *manifold, double vertex_epsilon, Boolean centroid_at_origin, DirichletInteractivity interactivity, Boolean maximize_injectivity_radius); /* * Computes a Dirichlet domain for the given manifold or orbifold. * Returns NULL if the Dehn filling coefficients are not all integers, * of if roundoff errors lead to topological problems. * Returns a pointer to the Dirichlet domain otherwise. */ extern WEPolyhedron *Dirichlet_with_displacement( Triangulation *manifold, double displacement[3], double vertex_epsilon, Boolean centroid_at_origin, DirichletInteractivity interactivity, Boolean maximize_injectivity_radius); /* * Like Dirichlet(), only allows an arbitrary displacement * of the basepoint. The displacement is in tangent space * coordinates, so the distances can't be interpreted too literally. * Reasonable displacements are to the order of 0.1. * Large displacements are possible, but degrade the numerical * accuracy of the resulting Dirichlet domain. */ extern WEPolyhedron *Dirichlet_from_generators( O31Matrix generators[], int num_generators, double vertex_epsilon, DirichletInteractivity interactivity, Boolean maximize_injectivity_radius); /* * Like Dirichlet(), only starts with a set of O(3,1) matrix generators * instead of a Triangulation. */ extern WEPolyhedron *Dirichlet_from_generators_with_displacement( O31Matrix generators[], int num_generators, double displacement[3], double vertex_epsilon, DirichletInteractivity interactivity, Boolean maximize_injectivity_radius); /* * Combines the functionality of Dirichlet_with_displacement() and * Dirichlet_from_generators(). */ extern void change_basepoint( WEPolyhedron **polyhedron, Triangulation *manifold, O31Matrix *generators, int num_generators, double displacement[3], double vertex_epsilon, Boolean centroid_at_origin, DirichletInteractivity interactivity, Boolean maximize_injectivity_radius); /* * Reads the face pairing matrices from the polyhedron, shifts the * basepoint by the given displacement (optionally letting the basepoint * move to a local maximum of the injectivity radius function), and * recomputes the Dirichlet domain. * If *polyhedron is NULL, computes the Dirichlet domain directly from * the manifold, but with the given displacement of the initial basepoint. * In either case, a pointer to the resulting Dirichlet domain (or NULL * if an error occurs as described in Dirichlet() above) is written * to *polyhedron. */ extern void free_Dirichlet_domain(WEPolyhedron *Dirichlet_domain); /* * Frees the storage occupied by a WEPolyhedron. */ /************************************************************************/ /* */ /* Dirichlet_rotate.c */ /* */ /************************************************************************/ extern void set_identity_matrix(O31Matrix position); /* * Sets the matrix to the identity. */ extern void update_poly_position(O31Matrix position, O31Matrix velocity); /* * Multiplies the position by the velocity. */ extern void update_poly_vertices(WEPolyhedron *polyhedron, O31Matrix position, Real scale); /* * Multiplies the standard vertex coordinates x[] by the position matrix * to obtain the rotated coordinates xx[], and then multiplies the * rotated coordinates by the constant "scale". */ extern void update_poly_visibility(WEPolyhedron *polyhedron, O31Matrix position, O31Vector direction); /* * Checks which vertices, edges and faces are visible to the user with * the polyhedron in its present position, and sets their visibility * fields accordingly. */ /************************************************************************/ /* */ /* Dirichlet_conversion.c */ /* */ /************************************************************************/ extern Triangulation *Dirichlet_to_triangulation(WEPolyhedron *polyhedron); /* * Converts a Dirichlet domain to a Triangulation, leaving the * Dirichlet domain unchanged. For closed manifolds, drills out * an arbitrary curve and expresses the manifold as a Dehn filling. */ /************************************************************************/ /* */ /* double_cover.c */ /* */ /************************************************************************/ extern Triangulation *double_cover(Triangulation *manifold); /* * Returns a pointer to the double cover of the nonorientable * Triangulation *manifold. */ /************************************************************************/ /* */ /* dual_curves.c */ /* */ /************************************************************************/ extern void dual_curves( Triangulation *manifold, int max_size, int *num_curves, DualOneSkeletonCurve ***the_curves); /* * Computes a reasonable selection of simple closed curves in * a manifold's dual 1-skeleton. */ extern void get_dual_curve_info( DualOneSkeletonCurve *the_curve, Complex *complete_length, Complex *filled_length, MatrixParity *parity); /* * Reports the complex length of a curve in the dual 1-skeleton, * relative to both the complete and filled hyperbolic structures, * and also its parity (orientation_preserving or orientation_reversing). */ extern void free_dual_curves( int num_curves, DualOneSkeletonCurve **the_curves); /* * Frees the array of curves computed by dual_curves(). */ /************************************************************************/ /* */ /* drilling.c */ /* */ /************************************************************************/ extern Triangulation *drill_cusp( Triangulation *old_manifold, DualOneSkeletonCurve *curve_to_drill, const char *new_name); /* * Drills a curve out of the dual 1-skeleton of an n-cusp manifold to * create an (n+1)-cusp manifold. */ /************************************************************************/ /* */ /* filling.c */ /* */ /************************************************************************/ extern Triangulation *fill_cusps( Triangulation *manifold, Boolean fill_cusp[], const char *new_name, Boolean fill_all_cusps); /* * Permanently fills k of the cusps of an n-cusp manifold. * Typically fill_all_cusps is FALSE, and the function returns * an ideal Triangulation of the resulting (n - k)-cusp manifold. * fill_cusp[] is a Boolean array specifying which k cusps (k < n) * are to be filled. * * In the exceptional case that fill_all_cusps is TRUE, the function * returns a triangulation with finite vertices only. * Such triangulations are unacceptable for most SnapPea routines, * and should be used only for writing to disk. When fill_all_cusps * is TRUE, fill_cusp is ignored and may be NULL. * * new_name is the name to be given to the new Triangulation. */ extern Triangulation *fill_reasonable_cusps(Triangulation *manifold); /* * Makes reasonable choices for fill_cusp[] and new_name, and calls * fill_cusps(). Specifically, it will fill all cusps with relatively * prime Dehn filling coefficients, unless this would leave no cusps * unfilled, in which case it leaves cusp 0 unfilled. It copies the * name from the original manifold. */ extern Boolean cusp_is_fillable(Triangulation *manifold, int cusp_index); /* * Returns TRUE if a cusp has relatively prime integer Dehn filling * coefficients, FALSE otherwise. */ extern Boolean is_closed_manifold(Triangulation *manifold); /* * Returns TRUE iff all cusps are filled and the coefficients * are relatively prime integers. */ /************************************************************************/ /* */ /* fundamental_group.c */ /* */ /************************************************************************/ extern GroupPresentation *fundamental_group( Triangulation *manifold, Boolean simplify_presentation, Boolean fillings_may_affect_generators, Boolean minimize_number_of_generators); /* * Computes the fundamental group of the manifold, taking into account * Dehn fillings, and returns a pointer to it. Please see * fundamental_group.c for an explanation of the arguments. */ extern int fg_get_num_generators(GroupPresentation *group); /* * Returns the number of generators in the GroupPresentation. */ extern int fg_get_num_orig_gens(GroupPresentation *group); /* * Returns the number of standard geometric generators. */ extern Boolean fg_integer_fillings(GroupPresentation *group); /* * Says whether the underlying space is a manifold or orbifold, * as opposed to some other generalized Dehn filling. */ extern FuncResult fg_word_to_matrix( GroupPresentation *group, int *word, O31Matrix result_O31, MoebiusTransformation *result_Moebius); /* * Converts an abstract word in the fundamental group to a matrix * in the matrix representation. The abstract word is given as a * string of integers. The integer 1 means the first generator, * 2 means the second, etc., while -1 is the inverse of the first * generator, -2 is the inverse of the second, etc. The integer 0 * indicates the end of the string. The result is given both as * an O31Matrix and a MoebiusTransformation. Returns func_OK if * successful, or func_bad_input if the input word is not valid. */ extern int fg_get_num_relations(GroupPresentation *group); /* * Returns the number of relations in the GroupPresentation. */ extern int *fg_get_relation( GroupPresentation *group, int which_relation); /* * Returns the specified relation (using 0-based indexing). * It allocates the memory for it, so you should pass the pointer * back to fg_free_relation() when you're done with it. * Each relation is a string of integers. The integer 1 means * the first generator, 2 means the second, etc., while -1 is the * inverse of the first generator, -2 is the inverse of the second, etc. * The integer 0 indicates the end of the string. */ extern void fg_free_relation(int *relation); /* * Frees a relation allocated by fg_get_relation(). */ extern int fg_get_num_cusps(GroupPresentation *group); /* * Returns the number of cusps of the underlying manifold. * This *includes* the filled cusps. So, for example, if you do (5,1) * Dehn filling on the figure eight knot complement, you can see the * words in the fundamental group corresponding to the (former!) cusp's * meridian and longitude. */ extern int *fg_get_meridian( GroupPresentation *group, int which_cusp); extern int *fg_get_longitude( GroupPresentation *group, int which_cusp); /* * Returns the word corresponding to a meridian or longitude, in the * same format used by fg_get_relation() above. They allocate the * memory for the string of integers, so you should pass the pointer * back to fg_free_relation() when you're done with it. Meridians and * longitudes are available whether the cusps are filled or not, as * explained for fg_get_num_cusps() above. */ extern int *fg_get_original_generator( GroupPresentation *group, int which_generator); /* * Returns a word which expresses one of the standard geometric * generators (as defined in choose_generators.c) in terms of the * group presentation's generators. The word is in the same format * used by fg_get_relation() above. Note that which_generator is * given relative to 0-based indexing, but the letters in the word * you get out use 1-based numbering, as in fg_get_relation(). * Please free the word with fg_free_relation() when you're done. */ extern int *fg_get_word_moves(GroupPresentation *group); /* * Returns a something describing how the current generators are * expressed in terms of the geometric generators. See * fundamental_group.c for details. Please free the word with * fg_free_relation() when you're done. */ extern void free_group_presentation(GroupPresentation *group); /* * Frees the storage occupied by a GroupPresentation. */ /************************************************************************/ /* */ /* homology.c */ /* */ /************************************************************************/ extern AbelianGroup *homology(Triangulation *manifold); /* * If all Dehn filling coefficients are integers, returns a pointer to * the first homology group of *manifold. In particular, it will * happily compute homology groups of orbifolds. If one or more Dehn * filling coefficients are not integers, returns NULL. This function * allocates the memory for the AbelianGroup; the UI should call * free_abelian_group() (no pun intended) to release it. * * 96/12/11 Checks for overflows, and returns NULL if any occur. */ extern AbelianGroup *homology_from_fundamental_group( GroupPresentation *group); /* * Abelianizes a group presentation and returns the result. * Returns NULL if overflows occur. */ extern void homology_presentation( Triangulation *manifold, RelationMatrix *relation_matrix); /* * Fills in a RelationMatrix structure. Sets relation_matrix->relations * to NULL if overflows occurs while computing the matrix. * MC 01/26/08 */ extern void free_relations(RelationMatrix *relation_matrix); /* Frees the memory pointed to by relation_matrix->relations. */ /************************************************************************/ /* */ /* hyperbolic_structure.c */ /* */ /************************************************************************/ extern SolutionType find_complete_hyperbolic_structure(Triangulation *manifold); /* * Attempts to find a complete hyperbolic structure for the * Triangulation *manifold. Sets the solution_type[complete] member of * *manifold to the type of solution found. If this type is anything * other than no_solution, stores the hyperbolic structure by setting * the *shape[complete] field of each Tetrahedron in the Triangulation. The * solution is also stored as the initial filled solution, by setting the * solution_type[filled] member of *manifold and the *shape[filled] fields * of the Tetrahedra; the is_complete flag of each Cusp is set to TRUE. * * The hyperbolic structure is computed using Newton's method, beginning * with all tetrahedra regular. * * Returns: the type of solution found. */ extern SolutionType do_Dehn_filling(Triangulation *manifold); /* * Attempts to find a hyperbolic structure for a *manifold, based on * the current Dehn filling coefficients. Sets the solution_type[filled] * member of *manifold to the type of solution found. If * this type is anything other than no_solution, stores the hyperbolic * structure by setting the *shape[filled] field of each Tetrahedron in * the Triangulation. * * The hyperbolic structure is computed using Newton's method; the * initial guess is the previous Dehn filled solution. * * Returns: the type of solution found. */ extern SolutionType remove_Dehn_fillings(Triangulation *manifold); /* * Removes all Dehn fillings. * * Returns: the type of solution restored. */ /************************************************************************/ /* */ /* index_to_hue.c */ /* */ /************************************************************************/ extern double index_to_hue(int index); /* * Maps the nonnegative integers to a set of easily distinguishable hues. * * index 0 1 2 3 4 5 6 . . . * hue 0 1/2 1/4 3/4 1/8 5/8 3/8 . . . */ extern double horoball_hue(int index); /* * Provides hand chosen hues for indices 0-5, and uses index_to_hue() * to interpolate thereafter. The hope is for nicer looking horoball * packings. */ /************************************************************************/ /* */ /* interface.c */ /* */ /************************************************************************/ extern char *get_triangulation_name(Triangulation *manifold); /* * Return a pointer to the name of the Triangulation *manifold. * The pointer points to the actual name, not a copy. */ extern void set_triangulation_name(Triangulation *manifold, const char *new_name); /* * Sets the Triangulation's name to new_name. */ extern SolutionType get_complete_solution_type(Triangulation *manifold); /* * Returns the SolutionType of the complete structure. */ extern SolutionType get_filled_solution_type(Triangulation *manifold); /* * Returns the SolutionType of the current Dehn filling. */ extern int get_num_tetrahedra(Triangulation *manifold); /* * Returns the number of tetrahedra in the Triangulation *manifold. */ extern Orientability get_orientability(Triangulation *manifold); /* * Returns the orientability of *manifold. */ extern int get_num_cusps(Triangulation *manifold); /* * Returns the number of cusps in *manifold. */ extern int get_num_or_cusps(Triangulation *manifold); /* * Returns the number of orientable cusps in *manifold. */ extern int get_num_nonor_cusps(Triangulation *manifold); /* * Returns the number of nonorientable cusps in *manifold. */ extern int get_max_singularity(Triangulation *manifold); /* * Returns the maximum value of gcd(m,l) over all integer Dehn filling * coefficients (m,l) for filled cusps in *manifold. */ extern int get_num_generators(Triangulation *manifold); /* * Returns the number of generators being used to represent *manifold's * fundamental group. */ extern void get_cusp_info( Triangulation *manifold, int cusp_index, CuspTopology *topology, Boolean *is_complete, Real *m, Real *l, Complex *initial_shape, Complex *current_shape, int *initial_shape_precision, int *current_shape_precision, Complex *initial_modulus, Complex *current_modulus); /* * Provides information about the cusp whose index is cusp_index in * *manifold. (The cusp indices run from zero to one less than the * number of cusps.) * * *topology is set to torus_cusp, Klein_cusp, or unknown_topology. * *is_complete is set to TRUE if the cusp is not Dehn filled, and * FALSE if it is. * *m and *l are set to the current Dehn filling coefficients. * They will be meaningful only if the cusp is filled. * If the cusp is nonorientable, only *m will be meaningful * (because *l must be zero for a Klein bottle cusp -- see * the comment at the top of holonomy.c). * *initial_shape is set to the initial shape (longitude/meridian) of the * cusp, i.e. the shape it had when all cusps were unfilled. * *current_shape is set to the cusp's current shape if the cusp is_complete, * zero otherwise. * *initial_shape_precision is set to the number of decimal places of accuracy * in the computed value of initial_shape. * *current_shape_precision is set to the number of decimal places of accuracy * in the computed value of current_shape. * *initial_modulus is set to the modulus ( (second shortest translation)/ * (shortest translation) ) of the initial cusp shape. * *current_modulus is set to the modulus of the current cusp shape. * * You may pass NULL for pointers to values you aren't interested in. */ extern FuncResult set_cusp_info(Triangulation *manifold, int cusp_index, Boolean cusp_is_complete, Real m, Real l); /* * Looks for a cusp with index cusp_index in Triangulation *manifold. * If not found, * alerts the user and exits (this should never occur * unless there is a bug in the UI). * If found, * if cusp_is_complete is TRUE, * sets the is_complete field of the cusp to TRUE, and * sets the Dehn filling coefficients to 0.0, * if cusp_is_complete is FALSE * sets the is_complete field of the cusp to FALSE, and * sets the Dehn filling coefficients to m and l. * * set_cusp_info() checks for errors in the values of m and l. * The (0,0) Dehn filling is never allowed, and only (p,0) fillings are * allowed on nonorientable cusps. If an error is detected, the cusp * will be left unchanged. * * Returns: * func_OK for success * func_bad_input for illegal Dehn filling coefficients */ extern void get_holonomy( Triangulation *manifold, int cusp_index, Complex *meridional_holonomy, Complex *longitudinal_holonomy, int *meridional_precision, int *longitudinal_precision); /* * Passes back the holonomies of the meridian and longitude, * and an estimate of their precision (number of decimal * digits to the right of the decimal point). */ extern void get_tet_shape( Triangulation *manifold, int which_tet, FillingStatus which_solution, Boolean fixed_alignment, Real *shape_rect_real, Real *shape_rect_imag, Real *shape_log_real, Real *shape_log_imag, int *precision_rect_real, int *precision_rect_imag, int *precision_log_real, int *precision_log_imag, Boolean *is_geometric); /* * Provides information about the shape of the Tetrahedron in * position which_tet in the linked list (which_tet takes a value * in the range [0, (#tetrahedra - 1)] ). (Note: which_tet * does not explicitly refer to the "index" field of the Tetrahedron * data structure, although in practice it will coincide.) * get_tet_shape() provides the shape of the Tetrahedron in both * rectangular and logarithmic forms, relative to whatever coordinate * system was used most recently. This means that the rectangular * form will satisfy |z| < 1 and |z - 1| < 1. The last four arguments * give the precision of the preceding four, expressed as the number * of significant deciomal digits following the decimal point. * (Warning: the precision is only a rough estimate. The last * digit or two may sometimes be incorrect.) The flag *is_geometric * is set to TRUE iff all dihedral angles lie in the range [0,pi]. */ extern int get_num_edge_classes( Triangulation *manifold, int edge_class_order, Boolean greater_than_or_equal); /* * If greater_than_or_equal == TRUE, returns the number of EdgeClasses * whose order is greater than or equal to edge_class_order. * If greater_than_or_equal == FALSE, returns the number of EdgeClasses * whose order is exactly edge_class_order. */ /************************************************************************/ /* */ /* isometry.c */ /* */ /************************************************************************/ extern FuncResult compute_isometries( Triangulation *manifold0, Triangulation *manifold1, Boolean *are_isometric, IsometryList **isometry_list, IsometryList **isometry_list_of_links); /* * Checks whether manifold0 and manifold1 are isometric (taking into * account the Dehn fillings). If manifold0 and manifold1 are cusped * manifolds, sets *isometry_list and *isometry_list_of_links as * in compute_cusped_isometries() below. Returns * func_OK if all goes well, * func_bad_input if some Dehn filling coefficients are not * relatively prime integers, * func_failed if it can't decide. */ extern int isometry_list_size(IsometryList *isometry_list); /* * Returns the number of Isometries in the IsometryList. */ extern int isometry_list_num_cusps(IsometryList *isometry_list); /* * Returns the number of cusps in each of the underlying manifolds. * If the IsometryList is empty (as would be the case when the * underlying manifolds have different numbers of cusps), then * isometry_list_num_cusps()'s return value is undefined. */ extern void isometry_list_cusp_action( IsometryList *isometry_list, int anIsometryIndex, int aCusp, int *cusp_image, int cusp_map[2][2]); /* * Fills in the cusp_image and cusp_map[2][2] to describe the action * of the given Isometry on the given Cusp. */ extern Boolean isometry_extends_to_link(IsometryList *isometry_list, int i); /* * Returns TRUE if Isometry i extends to the associated links (i.e. if it * takes meridians to meridians), FALSE if it doesn't. */ extern void isometry_list_orientations( IsometryList *isometry_list, Boolean *contains_orientation_preserving_isometries, Boolean *contains_orientation_reversing_isometries); /* * Says whether the IsometryList contains orientation-preserving * and/or orientation-reversing elements. Assumes the underlying * Triangulations are oriented. */ extern void free_isometry_list(IsometryList *isometry_list); /* * Frees the IsometryList. */ /************************************************************************/ /* */ /* isometry_cusped.c */ /* */ /************************************************************************/ extern Boolean same_triangulation( Triangulation *manifold0, Triangulation *manifold1); /* * Check whether manifold0 and manifold1 have combinatorially * equivalent triangulations (ignoring Dehn fillings). * This function is less versatile than a call to * compute_isometries(manifold0, manifold1, &are_isometric, NULL, NULL) * but it's useful for batch processing, when you want to avoid the * overhead of constantly recomputing canonical retriangulations. */ /************************************************************************/ /* */ /* length_spectrum.c */ /* */ /************************************************************************/ extern void length_spectrum( WEPolyhedron *polyhedron, Real cutoff_length, Boolean full_rigor, Boolean multiplicities, Real user_radius, MultiLength **spectrum, int *num_lengths); /* * Takes as input a manifold in the form of a Dirichlet domain, and * finds all geodesics of length less than or equal to cutoff_length. * Please length_spectrum.c for details. */ extern void free_length_spectrum(MultiLength *spectrum); /* * Deallocates the memory used to store the length spectrum. */ /************************************************************************/ /* */ /* link_complement.c */ /* */ /************************************************************************/ extern Triangulation *triangulate_link_complement( KLPProjection *aLinkProjection); /* * Triangulate the complement of aLinkProjection. */ /************************************************************************/ /* */ /* matrix_conversion.c */ /* */ /************************************************************************/ extern void Moebius_to_O31(MoebiusTransformation *A, O31Matrix B); extern void O31_to_Moebius(O31Matrix B, MoebiusTransformation *A); /* * Convert matrices back and forth between SL(2,C) and O(3,1). */ extern void Moebius_array_to_O31_array( MoebiusTransformation arrayA[], O31Matrix arrayB[], int num_matrices); extern void O31_array_to_Moebius_array( O31Matrix arrayB[], MoebiusTransformation arrayA[], int num_matrices); /* * Convert arrays of matrices back and forth between SL(2,C) and O(3,1). */ extern Boolean O31_determinants_OK( O31Matrix arrayB[], int num_matrices, Real epsilon); /* * Returns TRUE if all the O31Matrices in the array have determinants * within epsilon of plus or minus one, and FALSE otherwise. */ /************************************************************************/ /* */ /* matrix_generators.c */ /* */ /************************************************************************/ extern FuncResult matrix_generators( Triangulation *manifold, MoebiusTransformation generators[]); /* * Computes the MoebiusTransformations representing the action of the * generators of a manifold's fundamental group on the sphere at * infinity. Writes the MoebiusTransformations to the array * generators[], which it assumes has already been allocated. * Moreover, assumes that choose_generators has already been called * to compute the locations of the ideal vertices. You may use * get_num_generators() to determine how long an array to allocate. */ /************************************************************************/ /* */ /* my_malloc.c */ /* */ /************************************************************************/ extern void verify_my_malloc_usage(void); /* * The UI should call verify_my_malloc_usage() upon exit to verify that * the number of calls to my_malloc() was exactly balanced by the number * of calls to my_free(). In case of error, verify_my_malloc_usage() * passes an appropriate message to uAcknowledge. */ /************************************************************************/ /* */ /* normal_surface_construction.c */ /* */ /************************************************************************/ extern FuncResult find_normal_surfaces( Triangulation *manifold, NormalSurfaceList **surface_list); /* * Tries to find connected, embedded normal surfaces of nonnegative * Euler characteristic. If spheres or projective planes are found, * then tori and Klein bottles aren't reported, because from the point * of view of the Geometrization Conjecture, one wants to cut along * spheres and projective planes first. Surfaces are guaranteed to be * connected. They aren't guaranteed to be incompressible, although * typically they are. There is no guarantee that all such normal * surfaces will be found. Returns its result as a pointer to a * NormalSurfaceList, the internal structure of which is private to * the kernel. To get information about the normal surfaces on the list, * use the functions below. To split along a normal surface, call * split_along_normal_surface(). When you're done with the * NormalSurfaceList, free it using free_normal_surfaces(). * * The present implementation works only for cusped manifolds. * Returns func_bad_input for closed manifolds, or non-manifolds. */ extern int number_of_normal_surfaces_on_list( NormalSurfaceList *surface_list); /* * Returns the number of normal surfaces contained in the list. */ extern Boolean normal_surface_is_orientable( NormalSurfaceList *surface_list, int index); extern Boolean normal_surface_is_two_sided( NormalSurfaceList *surface_list, int index); extern int normal_surface_Euler_characteristic( NormalSurfaceList *surface_list, int index); /* * Return information about a given normal surface on the list. * The indices run from 0 through (number of surfaces - 1). */ extern void free_normal_surfaces(NormalSurfaceList *surface_list); /* * Frees an array of NormalSurfaceLists. */ /************************************************************************/ /* */ /* normal_surface_splitting.c */ /* */ /************************************************************************/ extern FuncResult split_along_normal_surface( NormalSurfaceList *surface_list, int index, Triangulation *pieces[2]); /* * Splits the manifold (stored privately in the NormalSurfaceList) * along the normal surface of the given index (indices range from 0 to * (number of surfaces - 1)). If the normal surface is a 2-sided * projective plane, split_along_normal_surface() returns func_bad_input; * otherwise it returns func_OK. If the normal surface is a sphere or * 1-sided projective plane, the resulting spherical boundary component(s) * are capped off with 3-ball(s); otherwise the new torus or Klein bottle * boundary component(s) become cusp(s). If the normal surface is * nonseparating, the result is returned in pieces[0], and pieces[1] * is set to NULL. If the normal surface is separating, the two pieces * are returned in pieces[0] and pieces[1]. */ /************************************************************************/ /* */ /* o31_matrices.c */ /* */ /************************************************************************/ /* * Most of the functions in o31_matrices.c are private to the kernel. * The following have been made available to the UI as well. */ extern Real gl4R_determinant(GL4RMatrix m); extern Real o31_trace(O31Matrix m); /************************************************************************/ /* */ /* orient.c */ /* */ /************************************************************************/ extern void reorient(Triangulation *manifold); /* * Reverse a manifold's orientation. */ /************************************************************************/ /* */ /* punctured_torus_bundles.c */ /* */ /************************************************************************/ extern void bundle_LR_to_monodromy( LRFactorization *anLRFactorization, MatrixInt22 aMonodromy); /* * Multiplies out anLRFactorization to obtain aMonodromy. */ extern void bundle_monodromy_to_LR( MatrixInt22 aMonodromy, LRFactorization **anLRFactorization); /* * If (det(aMonodromy) = +1 and |trace(aMonodromy)| >= 2) or * (det(aMonodromy) = -1 and |trace(aMonodromy)| >= 1), * then bundle_monodromy_to_LR() conjugates aMonodromy to a * nonnegative or nonpositive matrix, and factors it as * anLRFactorization. These cases include all monodromies of * hyperbolic manifolds, as well as the nonhyperbolic cases * (det(aMonodromy) = +1 and |trace(aMonodromy)| = 2), which * the user might want to see factored just for fun. * Otherwise bundle_monodromy_to_LR() sets * (*anLRFactorization)->is_available to FALSE, but nevertheless * sets negative_determinant and negative_trace correctly in case * the UI wants to display them. The UI should indicate that the * factorization is not available (e.g. by displaying "N/A") so * the user doesn't confuse this case with an empty factorization. */ extern LRFactorization *alloc_LR_factorization(int aNumFactors); extern void free_LR_factorization(LRFactorization *anLRFactorization); /* * Allocates/frees LRFactorizations. */ extern Triangulation *triangulate_punctured_torus_bundle( LRFactorization *anLRFactorization); /* * If the manifold is hyperbolic (i.e. if the number of LR factors * is at least two for an orientable bundle, or at least one for a * nonorientable bundle), triangulates the complement and returns * a pointer to it. Otherwise returns NULL. */ /************************************************************************/ /* */ /* rehydrate_census.c */ /* */ /************************************************************************/ extern void rehydrate_census_manifold( TersestTriangulation tersest, int which_census, int which_manifold, Triangulation **manifold); /* * Rehydrates a census manifold from a tersest description, resolving * any ambiguities in the choice of peripheral curves for the cusps. */ /************************************************************************/ /* */ /* representations.c */ /* */ /************************************************************************/ RepresentationList *find_representations( Triangulation *manifold, int n, PermutationSubgroup range); /* * Finds all transitive representations of a manifold's fundamental * group into Z/n or S(n), for use in constructing n-sheeted covers. * To dispose of the RepresentationList when you're done, use * free_representation_list() below. */ void free_representation_list( RepresentationList *representation_list); /* * Frees a RepresentationList. */ /* MC: The next two declarations would not have to be public, if the kernel provided a function that built a representation from permutation data. */ RepresentationIntoSn *initialize_new_representation( int num_original_generators, int n, int num_cusps); /* * Initializes a RepresentationIntoSn structure. (Added by MC 01/27/08) */ RepresentationIntoSn *convert_candidateSn_to_original_generators( int **candidateSn, int n, int num_original_generators, int **original_generators, Triangulation *manifold, int **meridians, int **longitudes); /* * This should be private to the kernel. (Added by MC 01/27/08) */ void free_representation( RepresentationIntoSn *representation, int num_generators, int num_cusps); /* * Frees a RepresentationIntoSn. (Added by MC 01/27/08) */ Boolean candidateSn_is_valid( int **candidateSn, int n, int **group_relations, int num_relations); /* * Does the candidate representation satisfy all of the relations? */ Boolean candidateSn_is_transitive( int **candidateSn, int num_generators, int n); /* * Is the candidate representation transitive? */ /************************************************************************/ /* */ /* shingling.c */ /* */ /************************************************************************/ extern Shingling *make_shingling(WEPolyhedron *polyhedron, int num_layers); /* * Constructs the shingling defined by the given Dirichlet domain. * Please see the top of shingling.c for detailed documentation. */ extern void free_shingling(Shingling *shingling); /* * Releases the memory occupied by the shingling. */ extern void compute_center_and_radials( Shingle *shingle, O31Matrix position, Real scale); /* * Uses shingle->normal along with the given position and scale to * compute shingle->center, single->radialA and shingle->radialB. */ /************************************************************************/ /* */ /* shortest_cusp_basis.c */ /* */ /************************************************************************/ extern Complex cusp_modulus(Complex cusp_shape); /* * Accepts a cusp_shape (longitude/meridian) and returns the cusp modulus. * Loosely speaking, the cusp modulus is defined as * (second shortest translation)/(shortest translation); it is a complex * number z lying in the region |Re(z)| <= 1/2 && |z| >= 1. If z lies * on the boundary of this region, we choose it so that Re(z) >= 0. */ extern void shortest_cusp_basis( Complex cusp_shape, MatrixInt22 basis_change); /* * Accepts a cusp_shape (longitude/meridian) and computes the 2 x 2 integer * matrix which transforms the old basis (u, v) = (meridian, longitude) * to the new basis (u', v') = (shortest, second shortest). */ extern Complex transformed_cusp_shape( Complex cusp_shape, CONST MatrixInt22 basis_change); /* * Accepts a cusp_shape and a basis_change, and computes the shape of the * cusp relative to the transformed basis. The transformed basis may or * may not be the (shortest, second shortest) basis. */ extern void install_shortest_bases( Triangulation *manifold); /* * Installs the (shortest, second shortest) basis on each torus Cusp * of manifold, but does not change the bases on Klein bottle cusps. */ /************************************************************************/ /* */ /* simplify_triangulation.c */ /* */ /************************************************************************/ extern void basic_simplification(Triangulation *manifold); /* * Simplifies the triangulation in a speedy yet effective manner. */ extern void randomize_triangulation(Triangulation *manifold); /* * Randomizes the Triangulation, and then resimplifies it. */ /************************************************************************/ /* */ /* sl2c_matrices.c */ /* */ /************************************************************************/ /* * Most of the functions in sl2c_matrices.c are private to the kernel. * The following has been made available to the UI as well. */ extern Complex sl2c_determinant(CONST SL2CMatrix m); /* * Returns the determinant of m. */ /************************************************************************/ /* */ /* symmetry_group.c */ /* */ /************************************************************************/ extern FuncResult compute_symmetry_group( Triangulation *manifold, SymmetryGroup **symmetry_group_of_manifold, SymmetryGroup **symmetry_group_of_link, Triangulation **symmetric_triangulation, Boolean *is_full_group); /* * Computes the SymmetryGroup of a closed or cusped manifold. * If the manifold is cusped, also computes the SymmetryGroup of the * corresponding link (defined at the top of symmetry_group_cusped.c). */ extern void free_symmetry_group(SymmetryGroup *symmetry_group); /* * Frees a SymmetryGroup. */ /************************************************************************/ /* */ /* symmetry_group_info.c */ /* */ /************************************************************************/ extern Boolean symmetry_group_is_abelian( SymmetryGroup *symmetry_group, AbelianGroup **abelian_description); /* * If the SymmetryGroup is abelian, sets *abelian_description to point * to the SymmetryGroup's description as an AbelianGroup, and returns TRUE. * Otherwise sets *abelian_description to NULL and returns FALSE. */ extern Boolean symmetry_group_is_dihedral(SymmetryGroup *symmetry_group); /* * Returns TRUE if the SymmetryGroup is dihedral, FALSE otherwise. */ extern Boolean symmetry_group_is_polyhedral(SymmetryGroup *symmetry_group, Boolean *is_full_group, int *p, int *q, int *r); /* * Returns TRUE if the SymmetryGroup is polyhedral, FALSE otherwise. * If the SymmetryGroup is polyhedral, reports whether it's the full group * (binary polyhedral, not just plain polyhedral), and reports the values * for (p,q,r). The pointers for is_full_group, p, q and r may be NULL * if this information is not desired. */ extern Boolean symmetry_group_is_S5(SymmetryGroup *symmetry_group); /* * Returns TRUE if the SymmetryGroup is the symmetric group on 5 letters, * FALSE otherwise. */ extern Boolean symmetry_group_is_direct_product(SymmetryGroup *symmetry_group); /* * Returns TRUE if the SymmetryGroup is a nontrivial, nonabelian direct * product, FALSE otherwise. */ extern SymmetryGroup *get_symmetry_group_factor(SymmetryGroup *symmetry_group, int factor_number); /* * If the SymmetryGroup is a nontrivial, nonabelian direct product, * returns a pointer to factor "factor_number" (factor_number = 0 or 1). * Otherwise returns NULL. This is a pointer to the internal data * structure -- not a copy! -- so please don't free it. */ extern Boolean symmetry_group_is_amphicheiral(SymmetryGroup *symmetry_group); /* * Returns TRUE if the SymmetryGroup contains orientation-reversing * elements, FALSE otherwise. Assumes the underlying manifold is oriented. */ extern Boolean symmetry_group_invertible_knot(SymmetryGroup *symmetry_group); /* * Assumes the underlying manifold is oriented and has exactly * one Cusp. Returns TRUE if some Symmetry acts on the Cusp * via the matrix (-1, 0; 0, -1); returns FALSE otherwise. */ extern int symmetry_group_order(SymmetryGroup *symmetry_group); /* * Returns the order of the SymmetryGroup. */ extern int symmetry_group_product(SymmetryGroup *symmetry_group, int i, int j); /* * Returns the product of group elements i and j. We use the * convention that products of symmetries read right to left. * That is, the composition symmetry[i] o symmetry[j] acts by * first doing symmetry[j], then symmetry[i]. */ extern int symmetry_group_order_of_element(SymmetryGroup *symmetry_group, int i); /* * Returns the order of group element i. */ extern IsometryList *get_symmetry_list(SymmetryGroup *symmetry_group); /* * Returns the list of "raw" Isometries comprising a SymmetryGroup. */ extern SymmetryGroup *get_commutator_subgroup(SymmetryGroup *symmetry_group); extern SymmetryGroup *get_abelianization (SymmetryGroup *symmetry_group); /* * Compute the commutator subgroup [G,G] and the abelianization G/[G,G]. * The UI should eventually use free_symmetry_group() to free them. */ extern SymmetryGroup *get_center(SymmetryGroup *symmetry_group); /* * Computes the center of G, which is the subgroup consisting of * elements which commute with all elements in G. * The UI should eventually use free_symmetry_group() to free it. */ extern SymmetryGroupPresentation *get_symmetry_group_presentation( SymmetryGroup *symmetry_group); /* * Returns a presentation for the given SymmetryGroup. * The internal structure of the SymmetryGroupPresentation is private * to the kernel; use the functions below to get information about it. * When you're done with it, use free_symmetry_group_presentation() * to free the storage. */ extern int sg_get_num_generators(SymmetryGroupPresentation *group); /* * Returns the number of generators in the SymmetryGroupPresentation. */ extern int sg_get_num_relations(SymmetryGroupPresentation *group); /* * Returns the number of relations in the SymmetryGroupPresentation. */ extern int sg_get_num_factors( SymmetryGroupPresentation *group, int which_relation); /* * Returns the number of factors in the specified relation. * For example, the relation a^3 * b^-2 * c^5 has three factors. * The parameter which_relation uses 0-based indexing. */ extern void sg_get_factor( SymmetryGroupPresentation *group, int which_relation, int which_factor, int *generator, int *power); /* * Reports the generator and power of the specified factor in the * specified relation. For example, if relation 1 (i.e. the second * relation) is a^3 * b^-2 * c^5, then passing which_relation = 1 and * which_factor = 2 will cause it to report *generator = 2 and * *power = 5. */ extern void free_symmetry_group_presentation(SymmetryGroupPresentation *group); /* * Frees the storage occupied by a SymmetryGroupPresentation. */ /************************************************************************/ /* */ /* terse_triangulation.c */ /* */ /************************************************************************/ extern TerseTriangulation *tri_to_terse(Triangulation *manifold); extern TerseTriangulation *tri_to_canonical_terse( Triangulation *manifold, Boolean respect_orientation); /* * tri_to_terse() accepts a pointer to a Triangulation, computes * a corresponding TerseTriangulation, and returns a pointer to it. * tri_to_canonical_terse() is similar, but chooses the * TerseTriangulation which is "least" among all possible choices * of base Tetrahedron and base Permutation. */ extern Triangulation *terse_to_tri(TerseTriangulation *tt); /* * Accepts a pointer to a TerseTriangulation, expands it to a full * Triangulation, and returns a pointer to it. */ extern void free_terse_triangulation(TerseTriangulation *tt); /* * Releases the memory used to store a TerseTriangulation. */ /************************************************************************/ /* */ /* tersest_triangulation.c */ /* */ /************************************************************************/ extern void terse_to_tersest( TerseTriangulation *terse, TersestTriangulation tersest); /* * Converts a TerseTriangulation to a TersestTriangulation. */ extern void tersest_to_terse( TersestTriangulation tersest, TerseTriangulation **terse); /* * Converts a TersestTriangulation to a TerseTriangulation. * Allocates space for the result. */ extern void tri_to_tersest( Triangulation *manifold, TersestTriangulation tersest); /* * Composes tri_to_terse() and terse_to_tersest(). */ extern void tersest_to_tri( TersestTriangulation tersest, Triangulation **manifold); /* * Composes tersest_to_terse() and terse_to_tri(). */ /************************************************************************/ /* */ /* triangulations.c */ /* */ /************************************************************************/ extern void data_to_triangulation( TriangulationData *data, Triangulation **manifold_ptr); /* * Uses the TriangulationData (defined in triangulation_io.h) to * construct a Triangulation. Sets *manifold_ptr to point to the * Triangulation, or to NULL if it fails. */ extern void triangulation_to_data( Triangulation *manifold, TriangulationData **data_ptr); /* * Allocates the TriangulationData and writes in the data describing * the manifold. Sets *data_ptr to point to the result. The UI * should call free_triangulation_data() when it's done with the * TriangulationData. */ extern void free_triangulation_data(TriangulationData *data); /* * If the UI lets the kernel allocate a TriangulationData structure * (as in a call to triangulation_to_data()), then the UI should * call free_triangulation_data() to release it. * If the UI allocates its own TriangulationData structure (as in * preparing for a call to data_to_triangulation()), then the UI * should release the structure itself. */ extern void free_triangulation(Triangulation *manifold); /* * If manifold != NULL, frees up the storage associated with a * triangulation structure. * If manifold == NULL, does nothing. */ extern void copy_triangulation(Triangulation *source, Triangulation **destination); /* * Makes a copy of the Triangulation *source. */ /************************************************************************/ /* */ /* two_bridge.c */ /* */ /************************************************************************/ extern void two_bridge( Triangulation *manifold, Boolean *is_two_bridge, long int *p, long int *q); /* * Checks whether *manifold is the (conjectured) canonical triangulation * of a 2-bridge knot or link complement. If it is, sets *is_two_bridge * to TRUE and writes the fraction p/q describing the knot or link into * (*p)/(*q). If it's not, sets *is_two_bridge to FALSE and leaves *p * and *q undefined. */ /************************************************************************/ /* */ /* volume.c */ /* */ /************************************************************************/ extern Real volume(Triangulation *manifold, int *precision); /* * Computes and returns the volume of the manifold. * If the pointer "precision" is not NULL, estimates the number * of decimal places of accuracy, and places the result in the * variable *precision. */ #include "end_namespace.h" /* We build the snappea kernel as C++, so link it as C++. - B.B., 27/03/2014. #ifdef __cplusplus } #endif */ #endif regina-4.96/engine/snappea/kernel/solve_equations.c000644 000765 000024 00000027510 12377774107 022374 0ustar00babstaff000000 000000 /* * solve_equations.c * * This file provides the functions * * FuncResult solve_complex_equations(Complex **complex_equations, * int num_rows, int num_columns, Complex *solution); * FuncResult solve_real_equations(double **real_equations, * int num_rows, int num_columns, double *solution); * * which do_Dehn_filling() in hyperbolic_structure.c calls to * solve num_rows linear equations in num_columns variables. Gaussian * elimination with partial pivoting is used. * * The equations are stored as an array of num_rows pointers, each * of which points to an array of (num_columns + 1) entries. The * last entry in each row is the constant on the right hand side of * the equation. * * num_rows is assumed to be greater than or equal to num_columns. * The equations are assumed to have rank exactly equal to num_columns. * Thus, even though there may be more equations than variables, the * equations are assumed to be consistent. * * Even though these routines make no assumption about the origin or * purpose of the equations, their main use is, of course, to find * hyperbolic structures. My hope in including all the equations * (rather than just a linearly independent subset) is that we will * get more accurate solutions, particularly in degenerate or * nearly degenerate situations. * * These functions assume an array of num_columns elements has already * been allocated for the solution. * * Technical detail: While doing the Gaussian elimination, these functions * do not actually compute or write values which are guaranteed to be one * or zero, but they knows where they are. So don't worry that in the end * the matrix does not contain all ones and zeros; the matrix will be a * mess, but the solution will be correct. */ #include "kernel.h" #include "kernel_namespace.h" FuncResult solve_complex_equations( Complex **complex_equations, int num_rows, int num_columns, Complex *solution) { /* * The following register variables are used in the n^3 bottleneck. * (See below.) */ register Real factor_real, factor_imag; register Complex *row_r, *row_c; register int count; /* * The remaining variables are used in less critical places. */ int r, c, cc, pivot_row = -1; Real max_modulus, this_modulus, max_error, error; Complex *temp, factor; /* * Forward elimination. */ for (c = 0; c < num_columns; c++) { /* * Find the pivot row. */ max_modulus = (Real)0.0; for (r = c; r < num_rows; r++) { this_modulus = complex_modulus(complex_equations[r][c]); if (this_modulus > max_modulus) { max_modulus = this_modulus; pivot_row = r; } } if (max_modulus == (Real)0.0) /* In the old snappea, max_modulus */ return func_failed; /* was was never below 1e-100, even */ /* in degenerate cases. */ /* * Swap the pivot row into position. */ temp = complex_equations[c]; complex_equations[c] = complex_equations[pivot_row]; complex_equations[pivot_row] = temp; /* * Multiply the pivot row through by 1.0/(pivot value). */ factor = complex_div(One, complex_equations[c][c]); for (cc = c + 1; cc <= num_columns; cc++) complex_equations[c][cc] = complex_mult( factor, complex_equations[c][cc] ); /* * Eliminate the entries in column c which lie below the pivot. */ for (r = c + 1; r < num_rows; r++) { /* * The following loop is the bottleneck for computing * hyperbolic structures. It is executed n^3 times to solve * an n x n system of equations, and no other n^3 algorithms * are used. For this reason, I've written the loop to * maximize speed at the expense of readability. * * Here's the loop in pseudocode: * for (cc = c + 1; cc <= num_columns; cc++) complex_equations[r][cc] -= complex_equations[r][c] * complex_equations[c][cc] * * Here's a version that will actually run: * for (cc = c + 1; cc <= num_columns; cc++) complex_equations[r][cc] = complex_minus( complex_equations[r][cc], complex_mult( complex_equations[r][c], complex_equations[c][cc] ) ); * * And here's the fancy, built-for-speed version: */ factor_real = - complex_equations[r][c].real; factor_imag = - complex_equations[r][c].imag; if (factor_real != (Real)0.0 || factor_imag != (Real)0.0) { row_r = complex_equations[r] + c + 1; row_c = complex_equations[c] + c + 1; for (count = num_columns - c; --count >= 0; ) { if (row_c->real != (Real)0.0 || row_c->imag != (Real)0.0) { row_r->real += factor_real * row_c->real - factor_imag * row_c->imag; row_r->imag += factor_real * row_c->imag + factor_imag * row_c->real; } row_r++; row_c++; } } /* * With all the THINK C compiler's optimization options on, * the fancy version runs 8 times faster than the plain * version. With all THINK C optimization options off, * it runs 9 times faster. The THINK C optimizer increases * the speed of the fancy code by only 6%. */ /* * Yield some time to the window system, and check * whether the user has cancelled this computation. */ if (uLongComputationContinues() == func_cancelled) return func_cancelled; } } /* * Back substitution. */ for (c = num_columns; --c > 0; ) /* Do columns (num_columns - 1) to 1, */ /* but skip column 0. */ for (r = c; --r >= 0; ) /* Do rows (c - 1) to 0. */ complex_equations[r][num_columns] = complex_minus( complex_equations[r][num_columns], complex_mult( complex_equations[r][c], complex_equations[c][num_columns] ) ); /* * Check "extra" rows for consistency. * That is, in each of the last (num_rows - num_columns) rows, * check that the constant on the right hand side is zero. * This will give us a measure of the accuracy of the solution. * I still haven't decided what to do with this number. */ max_error = (Real)0.0; for (r = num_columns; r < num_rows; r++) { error = complex_modulus(complex_equations[r][num_columns]); if (error > max_error) max_error = error; } /* * Record the solution. */ for (r = 0; r < num_columns; r++) solution[r] = complex_equations[r][num_columns]; return func_OK; } FuncResult solve_real_equations( Real **real_equations, int num_rows, int num_columns, Real *solution) { /* * The following register variables are used in the n^3 bottleneck. * (See below.) */ register Real factor, *row_r, *row_c; register int count; /* * The remaining variables are used in less critical places. */ int r, c, cc, pivot_row = -1; Real max_abs, this_abs, max_error, error, *temp; /* * Forward elimination. */ for (c = 0; c < num_columns; c++) { /* * Find the pivot row. */ max_abs = (Real)0.0; for (r = c; r < num_rows; r++) { this_abs = fabs(real_equations[r][c]); if (this_abs > max_abs) { max_abs = this_abs; pivot_row = r; } } if (max_abs == 0.0) return func_failed; /* * Swap the pivot row into position. */ temp = real_equations[c]; real_equations[c] = real_equations[pivot_row]; real_equations[pivot_row] = temp; /* * Multiply the pivot row through by 1.0/(pivot value). */ factor = 1.0 / real_equations[c][c]; for (cc = c + 1; cc <= num_columns; cc++) real_equations[c][cc] *= factor; /* * Eliminate the entries in column c which lie below the pivot. */ for (r = c + 1; r < num_rows; r++) { factor = - real_equations[r][c]; /* * The following loop is the bottleneck for computing * hyperbolic structures. It is executed n^3 times to solve * an n x n system of equations, and no other n^3 algorithms * are used. For this reason, I've written the loop to * maximize speed at the expense of readability. * * Here's the loop in its humanly comprehensible form: * if (factor) for (cc = c + 1; cc <= num_columns; cc++) real_equations[r][cc] += factor * real_equations[c][cc]; * * Here's the optimized version of the same thing: */ if (factor != (Real)0.0) { row_r = real_equations[r] + c + 1; row_c = real_equations[c] + c + 1; for (count = num_columns - c; --count>=0; ) *row_r++ += factor * *row_c++; } /* * Yield some time to the window system, and check * whether the user has cancelled this computation. */ if (uLongComputationContinues() == func_cancelled) return func_cancelled; } } /* * Back substitution. */ for (c = num_columns; --c > 0; ) /* Do columns (num_columns - 1) to 1, */ /* but skip column 0. */ for (r = c; --r >= 0; ) /* Do rows (c - 1) to 0. */ real_equations[r][num_columns] -= real_equations[r][c] * real_equations[c][num_columns]; /* * Check "extra" rows for consistency. * That is, in each of the last (num_rows - num_columns) rows, * check that the constant on the right hand side is zero. * This will give us a measure of the accuracy of the solution. * I still haven't decided what to do with this number. */ max_error = (Real)0.0; for (r = num_columns; r < num_rows; r++) { error = fabs(real_equations[r][num_columns]); if (error > max_error) max_error = error; } /* * Record the solution. */ for (r = 0; r < num_columns; r++) solution[r] = real_equations[r][num_columns]; return func_OK; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/subdivide.c000644 000765 000024 00000052705 12377774107 021136 0ustar00babstaff000000 000000 /* * subdivide.c * * This file contains the function * * Triangulation *subdivide(Triangulation *manifold, const char *new_name); * * which accepts a Triangulation *manifold, copies it, and * subdivides the copy as described below into a Triangulation * with finite as well as ideal vertices. The original * triangulation is not changed. * * Triangulations produced by subdivide() differ from * ordinary triangulations in that they have finite vertices * as well as ideal vertices. * * At present, only the function fill_cusps() calls subdivide(), * but other kernel functions could use it too, if the need arises. * * Note: subdivide() has a subtle dependence on the implementation * of orient(). The first Tetrahedron on the new Triangulation's * tet list has the correct orientation, and orient() must propogate * that orientation to all the other Tetrahedra. * * The function subdivide() subdivides each Tetrahedron of a * Triangulation as follows. First, a regular neighborhood of * each ideal vertex is sliced off, to form its own new * Tetrahedron. Each such new Tetrahedron will have three finite * vertices as well as the original ideal vertex. The ideal * vertex keeps the same VertexIndex as the original, while * each of the three finite vertices inherits the VertexIndex * of the nearest (other) ideal vertex of the original Tetrahedron. * I wish I could provide a good illustration, but it's hard to * embed 3-D graphics in ASCII files; here's a 2-D illustration * which shows the general idea: * * original * vertex * #0 * * 0 /\ * / \ * / \ * / \ * / \ * 1 /__________\ 2 * / \ * / \ * / \ * / \ * / \ * / \ * 0 /\ /\ 0 * / \ / \ * / \ / \ * / \ / \ * / \ / \ * original /__________\____________/__________\ original * vertex #1 1 2 1 2 vertex #2 * * After removing the four Tetrahedra just described, you are * left with a solid which has four hexagonal faces and four * triangular faces. Please make yourself a sketch of a * truncated tetrahedron to illustrate this. Each hexagonal * face is subdivided into six triangles by coning to the * center: * * original * vertex * #0 * * .. * . . * . . * . . * . . * 1 ____________ 2 * /\ /\ * / \ / \ * / \ / \ * / \ / \ * / \ / \ * 0 /_________3\/__________\ 0 * .\ /\ /. * . \ / \ / . * . \ / \ / . * . \ / \ / . * . \ / \ / . * original . . . . . .\/__________\/. . . . . . original * vertex #1 2 1 vertex #2 * * The center vertex on each face gets the VertexIndex of the * opposite vertex of the original Tetrahedron (which equals the * FaceIndex of the face being subdivided). * Finally, the truncated tetrahedron is subdivided by coning * to the center. This creates 28 Tetrahedron (6 for each of * the four hexagonal faces, plus 1 for each of the four triangular * faces). The vertex at the center of the truncated tetrahedron * cannot be given a canonical VertexIndex common to all incident * Tetrahedra. Instead, each incident Tetrahedron assigns it * the unique index not yet used by that Tetrahedron. * * This canonical scheme for numbering the vertices makes the * calculation of the gluing Permutations very easy. "Internal" * gluings (i.e. between two new Tetrahedra belonging to same old * Tetrahedron) may be readily deduced from the above definitions. * Because the numbering scheme is canonical, all "external" gluings * (i.e. between two new Tetrahedra belonging to different old * Tetrahedra) will be the same as the corresponding gluing of the * original Tetrahedron. (Yes, I realize that the above definitions * of "internal" and "external" aren't quite right in the case of * an original Tetrahedron glued to itself, but I hope you understood * what I said anyhow.) */ #include "kernel.h" #include "kernel_namespace.h" /* * If you are not familiar with SnapPea's "Extra" field in * the Tetrahedron data structure, please see the explanation * preceding the Extra typedef in kernel_typedefs.h. * * Subdivide() uses an Extra field in each Tetrahedron of the * old_triangulation to keep track of the 32 corresponding * Tetrahedra in the new_triangulation. Please see the * documentation above for an explanation of the subdivision * algorithm. If you drew a sketch illustrating the subdivision, * it will be helpful in understanding the fields of the Extra struct. */ struct extra { /* * The first four Tetrahedra lopped off in the above * algorithm will be called "outer vertex Tetrahedra". * outer_vertex_tet[i] is a pointer to the outer vertex * Tetrahedron at vertex i of the old Tetrahedron. */ Tetrahedron *outer_vertex_tet[4]; /* * The "inner vertex Tetrahedra" are the remaining * Tetrahedra which are naturally associated to the * ideal vertices of the old Tetrahedron. * inner_vertex_tet[i] is a pointer to the new Tetrahedron * which meets outer_vertex_tet[i] along it's i-th face. */ Tetrahedron *inner_vertex_tet[4]; /* * The "edge Tetrahedra" are the 12 Tetrahedra which have * precisely one edge contained within an edge of the * old Tetrahedron. edge_tet[i][j] is the Tetrahedron * which has a face contained in face i of the old * Tetrahedron, on the side (of face i) opposite vertex j. * edge_tet[i][j] is defined iff i != j. */ Tetrahedron *edge_tet[4][4]; /* * The "face Tetrahedra" are the 12 remaining Tetrahedra. * face_tet[i][j] has a face contained in face i of the * old Tetrahedron, on the side near vertex j (of the old * Tetrahedron). face_tet[i][j] is defined iff i != j. */ Tetrahedron *face_tet[4][4]; }; static void attach_extra(Triangulation *manifold); static void free_extra(Triangulation *manifold); static void create_new_tetrahedra(Triangulation *new_triangulation, Triangulation *old_triangulation); static void allocate_new_tetrahedra(Triangulation *new_triangulation, Triangulation *old_triangulation); static void set_outer_vertex_tets(Tetrahedron *old_tet); static void set_inner_vertex_tets(Tetrahedron *old_tet); static void set_edge_tets(Tetrahedron *old_tet); static void set_face_tets(Tetrahedron *old_tet); static void create_new_cusps(Triangulation *new_triangulation, Triangulation *old_triangulation); static void create_real_cusps(Triangulation *new_triangulation, Triangulation *old_triangulation); Triangulation *subdivide( Triangulation *old_triangulation, const char *new_name) { Triangulation *new_triangulation; /* * Allocate storage for the new_triangulation * and initialize it. * * (In spite of what I wrote at the top of this file, * we don't explicitly make a copy of *old_triangulation, * but instead we create *new_triangulation from scratch.) */ new_triangulation = NEW_STRUCT(Triangulation); initialize_triangulation(new_triangulation); new_triangulation->name = NEW_ARRAY(strlen(new_name) + 1, char); strcpy(new_triangulation->name, new_name); new_triangulation->num_tetrahedra = 32 * old_triangulation->num_tetrahedra; new_triangulation->num_cusps = old_triangulation->num_cusps; new_triangulation->num_or_cusps = old_triangulation->num_or_cusps; new_triangulation->num_nonor_cusps = old_triangulation->num_nonor_cusps; /* * Attach an Extra field to each Tetrahedron in the * old_triangulation, to keep track of the corresponding * 32 Tetrahedra in the new_triangulation. */ attach_extra(old_triangulation); /* * Create the new Tetrahedra. * Set fields such as tet->neighbor and tet->gluing, * which can be determined immediately. * Postpone determination of fields such as tet->cusp * and tet->edge_class. */ create_new_tetrahedra(new_triangulation, old_triangulation); /* * Copy the Cusps from the old_triangulation to * the new_triangulation. (Technical note: functions * called by create_new_cusps() rely on the fact that * create_new_tetrahedra() initializes all tet->cusp * fields to NULL.) */ create_new_cusps(new_triangulation, old_triangulation); /* * We're done with the Extra fields, so free them. */ free_extra(old_triangulation); /* * Add the bells and whistles. */ create_edge_classes(new_triangulation); orient_edge_classes(new_triangulation); orient(new_triangulation); /* * Return the new_triangulation. */ return new_triangulation; } static void attach_extra( Triangulation *manifold) { Tetrahedron *tet; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) { /* * Make sure no other routine is using the "extra" * field in the Tetrahedron data structure. */ if (tet->extra != NULL) uFatalError("attach_extra", "filling"); /* * Attach the locally defined struct extra. */ tet->extra = NEW_STRUCT(Extra); } } static void free_extra( Triangulation *manifold) { Tetrahedron *tet; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) { /* * Free the struct extra. */ my_free(tet->extra); /* * Set the extra pointer to NULL to let other * modules know we're done with it. */ tet->extra = NULL; } } static void create_new_tetrahedra( Triangulation *new_triangulation, Triangulation *old_triangulation) { Tetrahedron *old_tet; /* * Allocate the memory for all the new Tetrahedra. * We do this before setting any of the fields, so * that the tet->neighbor fields will all have something * to point to. */ allocate_new_tetrahedra(new_triangulation, old_triangulation); /* * For each Tetrahedron in the old_triangulation, we want * to set the various fields of the 32 corresponding Tetrahedra * in the new triangulation. The new Tetrahedra are accessed * through the Extra fields of the old Tetrahedra. */ for (old_tet = old_triangulation->tet_list_begin.next; old_tet != &old_triangulation->tet_list_end; old_tet = old_tet->next) { set_outer_vertex_tets(old_tet); set_inner_vertex_tets(old_tet); set_edge_tets(old_tet); set_face_tets(old_tet); } } static void allocate_new_tetrahedra( Triangulation *new_triangulation, Triangulation *old_triangulation) { int i, j; Tetrahedron *old_tet, *new_tet; /* * For each Tetrahedron in the old_triangulation, we want * to allocate and initialize the 32 corresponding Tetrahedra * in the new_triangulation. */ /* * IMPORTANT: It's crucial that one of the outer vertex tetrahedra * appears first on new_triangulation's tet list, so that orient() * will preserve the manifold's original orientation. */ for (old_tet = old_triangulation->tet_list_begin.next; old_tet != &old_triangulation->tet_list_end; old_tet = old_tet->next) { for (i = 0; i < 4; i++) { new_tet = NEW_STRUCT(Tetrahedron); initialize_tetrahedron(new_tet); old_tet->extra->outer_vertex_tet[i] = new_tet; INSERT_BEFORE(new_tet, &new_triangulation->tet_list_end); } for (i = 0; i < 4; i++) { new_tet = NEW_STRUCT(Tetrahedron); initialize_tetrahedron(new_tet); old_tet->extra->inner_vertex_tet[i] = new_tet; INSERT_BEFORE(new_tet, &new_triangulation->tet_list_end); } for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) { if (i == j) { old_tet->extra->edge_tet[i][j] = NULL; continue; } new_tet = NEW_STRUCT(Tetrahedron); initialize_tetrahedron(new_tet); old_tet->extra->edge_tet[i][j] = new_tet; INSERT_BEFORE(new_tet, &new_triangulation->tet_list_end); } for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) { if (i == j) { old_tet->extra->face_tet[i][j] = NULL; continue; } new_tet = NEW_STRUCT(Tetrahedron); initialize_tetrahedron(new_tet); old_tet->extra->face_tet[i][j] = new_tet; INSERT_BEFORE(new_tet, &new_triangulation->tet_list_end); } } } static void set_outer_vertex_tets( Tetrahedron *old_tet) { int i, j, k, l; Tetrahedron *new_tet; /* * Set the fields for each of the four outer_vertex_tets. */ for (i = 0; i < 4; i++) { /* * For notational clarity, let new_tet be a pointer * to the outer_vertex_tet under consideration. */ new_tet = old_tet->extra->outer_vertex_tet[i]; /* * Set the new_tet's four neighbor fields. */ for (j = 0; j < 4; j++) new_tet->neighbor[j] = (i == j) ? old_tet->extra->inner_vertex_tet[i] : old_tet->neighbor[j]->extra->outer_vertex_tet[EVALUATE(old_tet->gluing[j], i)]; /* * Set the new_tet's four gluing fields. */ for (j = 0; j < 4; j++) new_tet->gluing[j] = (i == j) ? IDENTITY_PERMUTATION : old_tet->gluing[j]; /* * Copy the peripheral curves from the old_tet to the ideal * vertex of the new_tet. The peripheral curves of * finite vertices have already been set to zero. */ for (j = 0; j < 2; j++) for (k = 0; k < 2; k++) for (l = 0; l < 4; l++) new_tet->curve[j][k][i][l] = old_tet->curve[j][k][i][l]; } } static void set_inner_vertex_tets( Tetrahedron *old_tet) { int i, j; Tetrahedron *new_tet; /* * Set the fields for each of the four inner_vertex_tets. */ for (i = 0; i < 4; i++) { /* * For notational clarity, let new_tet be a pointer * to the inner_vertex_tet under consideration. */ new_tet = old_tet->extra->inner_vertex_tet[i]; /* * Set the new_tet's four neighbor fields. */ for (j = 0; j < 4; j++) new_tet->neighbor[j] = (i == j) ? old_tet->extra->outer_vertex_tet[i] : old_tet->extra->face_tet[j][i]; /* * Set the new_tet's four gluing fields. */ for (j = 0; j < 4; j++) new_tet->gluing[j] = IDENTITY_PERMUTATION; } } static void set_edge_tets( Tetrahedron *old_tet) { int i, j, k, l; Tetrahedron *new_tet; /* * Set the fields for each of the twelve edge_tets. */ for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) { /* * Only the case i != j is meaningful. */ if (i == j) continue; /* * For notational clarity, let new_tet be a pointer * to the edge_tet under consideration. */ new_tet = old_tet->extra->edge_tet[i][j]; /* * Let i, j, k and l be the VertexIndices of * new_tet. i and j are already defined as * loop variables. We define k and l here. */ k = remaining_face[i][j]; l = remaining_face[j][i]; /* * Set the new_tet's four neighbor fields. */ new_tet->neighbor[i] = old_tet->extra->edge_tet[j][i]; new_tet->neighbor[j] = old_tet->neighbor[i]->extra->edge_tet[EVALUATE(old_tet->gluing[i], i)][EVALUATE(old_tet->gluing[i], j)]; new_tet->neighbor[k] = old_tet->extra->face_tet[i][k]; new_tet->neighbor[l] = old_tet->extra->face_tet[i][l]; /* * Set the new_tet's four gluing fields. */ new_tet->gluing[i] = CREATE_PERMUTATION(i,j,j,i,k,k,l,l); new_tet->gluing[j] = old_tet->gluing[i]; new_tet->gluing[k] = CREATE_PERMUTATION(i,i,j,k,k,j,l,l); new_tet->gluing[l] = CREATE_PERMUTATION(i,i,j,l,k,k,l,j); } } static void set_face_tets( Tetrahedron *old_tet) { int i, j, k, l; Tetrahedron *new_tet; /* * Set the fields for each of the twelve face_tets. */ for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) { /* * Only the case i != j is meaningful. */ if (i == j) continue; /* * For notational clarity, let new_tet be a pointer * to the face_tet under consideration. */ new_tet = old_tet->extra->face_tet[i][j]; /* * Let i, j, k and l be the VertexIndices of * new_tet. i and j are already defined as * loop variables. We define k and l here. */ k = remaining_face[i][j]; l = remaining_face[j][i]; /* * Set the new_tet's four neighbor fields. */ new_tet->neighbor[i] = old_tet->extra->inner_vertex_tet[j]; new_tet->neighbor[j] = old_tet->neighbor[i]->extra->face_tet[EVALUATE(old_tet->gluing[i], i)][EVALUATE(old_tet->gluing[i], j)]; new_tet->neighbor[k] = old_tet->extra->edge_tet[i][k]; new_tet->neighbor[l] = old_tet->extra->edge_tet[i][l]; /* * Set the new_tet's four gluing fields. */ new_tet->gluing[i] = IDENTITY_PERMUTATION; new_tet->gluing[j] = old_tet->gluing[i]; new_tet->gluing[k] = CREATE_PERMUTATION(i,i,j,k,k,j,l,l); new_tet->gluing[l] = CREATE_PERMUTATION(i,i,j,l,k,k,l,j); } } static void create_new_cusps( Triangulation *new_triangulation, Triangulation *old_triangulation) { /* * The Cusp data structures for the real cusps are * handled separately from the Cusp data structures * for the finite vertices. */ create_real_cusps(new_triangulation, old_triangulation); create_fake_cusps(new_triangulation); } static void create_real_cusps( Triangulation *new_triangulation, Triangulation *old_triangulation) { Cusp *old_cusp, *new_cusp; Tetrahedron *old_tet; int i; /* * The Cusp data structures for the ideal vertices * in the new_triangulation are essentially just * copied from those in the old_triangulation. */ /* * Allocate memory for the new Cusps, copy in the * values from the old cusps, and put them on the * queue. */ for (old_cusp = old_triangulation->cusp_list_begin.next; old_cusp != &old_triangulation->cusp_list_end; old_cusp = old_cusp->next) { new_cusp = NEW_STRUCT(Cusp); *new_cusp = *old_cusp; new_cusp->is_finite = FALSE; INSERT_BEFORE(new_cusp, &new_triangulation->cusp_list_end); old_cusp->matching_cusp = new_cusp; } /* * Set the cusp field for ideal vertices in * the new_triangulation. */ for (old_tet = old_triangulation->tet_list_begin.next; old_tet != &old_triangulation->tet_list_end; old_tet = old_tet->next) for (i = 0; i < 4; i++) old_tet->extra->outer_vertex_tet[i]->cusp[i] = old_tet->cusp[i]->matching_cusp; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/symmetry_group.h000644 000765 000024 00000010235 12377774107 022262 0ustar00babstaff000000 000000 /* * symmetry_group.h * * This file defines a general, not necessarily abelian group * for use in computing symmetry groups of manifolds. */ #ifndef _symmetry_group_ #define _symmetry_group_ #include "kernel.h" #include "isometry.h" #include "kernel_namespace.h" /* * Symmetries are just Isometries from a manifold to itself. */ typedef Isometry Symmetry; typedef IsometryList SymmetryList; /* * The file SnapPea.h contains the "opaque typedef" * * typedef struct SymmetryGroup SymmetryGroup; * * which lets the UI declare and pass pointers to SymmetryGroups without * actually knowing what they are. This file provides the kernel with * the actual definition. */ /* * Group elements are represented by integers, beginning with 0. * By convention, 0 will always be the identity element. */ struct SymmetryGroup { /* * The order of the group. */ int order; /* * We want to keep the actual Symmetries around * to compute their fixed point sets, their action * on the cusps, etc. */ SymmetryList *symmetry_list; /* * product[][] is the multiplication table for the group. * That is, product[i][j] is the product of elements i and j. * * We compose Symmetries from right to left, so the product BA * is what you get by first doing Symmetry A, then Symmetry B. */ int **product; /* * order_of_element[i] is the order of element i. */ int *order_of_element; /* * inverse[i] is the inverse of element i. */ int *inverse; /* * Is this a cyclic group? * * If so the elements will be ordered as consecutive * powers of a generator. */ Boolean is_cyclic; /* * Is this a dihedral group? * * If so, the elements will be ordered as * I, R, R^2, . . . , R^(n-1), F, FR, . . . , FR^(n-1). */ Boolean is_dihedral; /* * Is this a spherical triangle group? * That is, is it one of the groups * * group (p, q, r) * * (binary) dihedral (2, 2, n) * (binary) tetrahedral (2, 3, 3) * (binary) octahedral (2, 3, 4) * (binary) icosahedral (2, 3, 5) * * If so, p, q and r will record the angles of the triangle * (pi/p, pi/q and pi/r), and is_binary_group will record * whether it's the binary polyhedral group as opposed to * the plain polyhedral group. * * When is_polyhedral is FALSE, p, q, r and is_binary_group * are undefined. */ Boolean is_polyhedral; Boolean is_binary_group; int p, q, r; /* * Is this the symmetric group S5? * (Eventually I'll write a more general treatment of symmetric * and alternating groups, but I want to get this much in place * before the Georgia conference so SnapPea can (I hope) recognize * the symmetry group of the totally symmetric 5-cusp manifold.) */ Boolean is_S5; /* * Is this an abelian group? * * If so, the elements will be ordered in a natural way, * and abelian_description will point to a description * of the group. * * If not, abelian_description will be set to NULL. */ Boolean is_abelian; AbelianGroup *abelian_description; /* * Is this group a nonabelian, nontrivial direct product? * * If so, factor[0] and factor[1] will point to the two * factors. Of course, each factor may itself be a nontrivial * direct product, and so on, leading to a tree structure * for the factorization. * * The symmetry_list field is defined only at the root level, * but all other fields are defined at all nodes. * * If the group is not a nonabelian, nontrivial direct product, * factor[0] and factor[1] will be set to NULL. */ Boolean is_direct_product; SymmetryGroup *factor[2]; }; #include "end_namespace.h" #endif regina-4.96/engine/snappea/kernel/sync_with_snappy.sh000755 000765 000024 00000006120 12377774107 022742 0ustar00babstaff000000 000000 #!/bin/bash # # Regina - Software for 3-manifold topology and normal surface theory # Upstream synchronisation for the SnapPea kernel # # Copyright (c) 2014, Ben Burton # For further details contact Ben Burton (bab@debian.org). # # -------------------------------------------------------------------------- # # Usage: sync_with_snappy # # Synchronises Regina's SnapPea kernel with the given version of SnapPy, # by copying the relevant files from SnapPy into the correct locations here. # # You should always check the diffs carefully to ensure that you are not # clobbering any of Regina's own patches to the SnapPea kernel. # # -------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version. # # As an exception, when this program is distributed through (i) the # App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or # (iii) Google Play by Google Inc., then that store may impose any # digital rights management, device limits and/or redistribution # restrictions that are required by its terms of service. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public # License along with this program; if not, write to the Free # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, # MA 02110-1301, USA. # set -e testfile=SnapPycore.pxi if ! [ -d "$1" -a -e "$1/$testfile" ]; then echo "Usage: $0 " echo echo "The directory should (for instance) contain $testfile." exit 1 fi headerdir="$1/headers" sourcedir="$1/kernel_code" unixdir="$1/unix_kit" snappydir="$1/addl_code" unixfiles="unix_file_io.h unix_file_io.c" snappyfiles="gluing_equations.c" snappymaster="addl_code.h" for i in "$headerdir"/*.h "$sourcedir"/*.c; do src="$i" filename=`echo "$src" | sed -e 's#.*/##'` if [ -e "$filename" ]; then cp "$src" "$filename" elif [ -e "unused/$filename" ]; then cp "$src" "unused/$filename" else echo "ERROR: The kernel file "$src" is not mirrored in Regina." fi done for i in $unixfiles; do src="$unixdir/$i" filename="$i" if [ -e "$filename" ]; then cp "$src" "$filename" else echo "ERROR: The unix_kit file "$src" is not mirrored in Regina." fi done for i in $snappyfiles; do src="$snappydir/$i" filename="snappy_$i" if [ -e "../snappy/$filename" ]; then cp "$src" "../snappy/$filename" else echo "ERROR: The snappy file "$src" is not mirrored in Regina." fi done if [ -e "../snappy/SnapPy.h" ]; then cp "$snappydir/$snappymaster" "../snappy/SnapPy.h" else echo "ERROR: The snappy header SnapPy.h is missing from Regina." fi regina-4.96/engine/snappea/kernel/tables.c000644 000765 000024 00000023576 12377774107 020436 0ustar00babstaff000000 000000 /* * tables.c * * This file provides tables used in working with triangulations. * They are based on the numbering conventions for tetrahedra * described in triangulation.h. * * The tables are * * EdgeIndex edge3[6]; * EdgeIndex edge_between_faces[4][4]; * EdgeIndex edge3_between_faces[4][4]; * EdgeIndex edge_between_vertices[4][4]; * EdgeIndex edge3_between_vertices[4][4]; * FaceIndex one_face_at_edge[6]; * FaceIndex other_face_at_edge[6]; * VertexIndex one_vertex_at_edge[6]; * VertexIndex other_vertex_at_edge[6]; * FaceIndex remaining_face[4][4]; * FaceIndex face_between_edges[6][6]; * Permutation inverse_permutation[256]; * signed char parity[256]; * FaceIndex vt_side[4][3]; * Permutation permutation_by_index[24]; * * Their use is described in detail below. * * The value 9 is used as a filler for undefined table entries. */ #include "kernel.h" #include "kernel_namespace.h" /* * edge3[i] is the index of the complex edge parameter associated with * the edge of EdgeIndex i. Opposite edges have equal complex edge * parameters, which are stored only under the lesser EdgeIndex; thus * even though the numbering of the edges runs from 0 to 5, the * numbering of the edge parameters run only from 0 to 2. */ const EdgeIndex edge3[6] = {0, 1, 2, 2, 1, 0}; /* * edge_between_faces[i][j] is the index of the edge lying between * faces i and j. */ const EdgeIndex edge_between_faces[4][4] = {{9, 0, 1, 2}, {0, 9, 3, 4}, {1, 3, 9, 5}, {2, 4, 5, 9}}; /* * edge3_between_faces[i][j] = edge3[ edge_between_faces[i][j] ]. * This table is useful when looking up complex edge parameters. * Cf. edge3[] above. */ const EdgeIndex edge3_between_faces[4][4] = {{9, 0, 1, 2}, {0, 9, 2, 1}, {1, 2, 9, 0}, {2, 1, 0, 9}}; /* * edge_between_vertices[i][j] is the index of the edge lying between * vertices i and j. */ const EdgeIndex edge_between_vertices[4][4] = {{9, 5, 4, 3}, {5, 9, 2, 1}, {4, 2, 9, 0}, {3, 1, 0, 9}}; /* * edge3_between_vertices[i][j] = edge3[ edge_between_vertices[i][j] ]. * This table is useful when looking up complex edge parameters. * Cf. edge3[] above. * Note that edge3_between_vertices[][] and edge3_between_faces[][] * are identical. */ const EdgeIndex edge3_between_vertices[4][4] = {{9, 0, 1, 2}, {0, 9, 2, 1}, {1, 2, 9, 0}, {2, 1, 0, 9}}; /* * one_face_at_edge[i] and other_face_at_edge[i] gives the indices of * the two faces incident to edge i. */ const FaceIndex one_face_at_edge[6] = {0, 0, 0, 1, 1, 2}; const FaceIndex other_face_at_edge[6] = {1, 2, 3, 2, 3, 3}; /* * one_vertex_at_edge[i] and other_vertex_at_edge[i] give the indices of * the two vertices incident to edge i. */ const FaceIndex one_vertex_at_edge[6] = {2, 1, 1, 0, 0, 0}; const FaceIndex other_vertex_at_edge[6] = {3, 3, 2, 3, 2, 1}; /* * Given two faces i and j, remaining_face[i][j] tells you the index * of one of the remaining faces. For a right_handed tetrahedron * (see kernel_typedefs.h for the definition of right_handed) the * faces i, j, and remaining_face[i][j] are arranged in a counterclockwise * order around their common ideal vertex. Thus, for two faces i and j, * remaining_face[i][j] gives one of the remaining faces and * remaining_face[j][i] gives the other. */ const FaceIndex remaining_face[4][4] = {{9, 3, 1, 2}, {2, 9, 3, 0}, {3, 0, 9, 1}, {1, 2, 0, 9}}; /* * face_between_edges[i][j] is the index of the face lying between * (nonopposite) edges i and j. */ const FaceIndex face_between_edges[6][6] = {{9, 0, 0, 1, 1, 9}, {0, 9, 0, 2, 9, 2}, {0, 0, 9, 9, 3, 3}, {1, 2, 9, 9, 1, 2}, {1, 9, 3, 1, 9, 3}, {9, 2, 3, 2, 3, 9}}; /* * inverse_permutation[p] is the inverse of Permutation p. */ const Permutation inverse_permutation[256] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; /* * parity[p] is the parity of Permutation p. * * 0 signifies an even permutation * (corresponding to an orientation reversing gluing) * * 1 signifies an odd permutation * (corresponding to an orientation preserving gluing) * * 9 signifies an invalid permutation * * Notes: * (1) The typedef GluingParity relies on 0 and 1 meaning what they do. * (2) The 0 and 1 are reversed relative to the parity[] table in the * old version of snappea. * (3) Use the constants in GluingParity; don't use 0 and 1 directly. */ const signed char parity[256] = { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 1, 9, 9, 9, 9, 9, 9, 9, 9, 1, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 1, 9, 9, 9, 9, 9, 1, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 1, 9, 9, 9, 9, 9, 1, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 1, 9, 9, 9, 9, 9, 9, 9, 9, 1, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9}; /* * vt_side[i][j] is the side of the cross sectional triangle at * vertex i which lies between edges j and (j+1)%3, where * the edge numbering is as in edge3_between_faces[][] above. * * An alternate interpretation is that vt_side[v][0], vt_side[v][1] * and vt_side[v][2] are the three faces surrounding vertex v, given * in counterclockwise order relative to the right_handed orientation * of the Tetrahedron. */ const FaceIndex vt_side[4][3] = {{3, 1, 2}, {2, 0, 3}, {1, 3, 0}, {0, 2, 1}}; /* * There are 24 possible Permutations of the set {3, 2, 1, 0}. The table * permutation_by_index[] list them all. E.g. permutation_by_index[2] = 0xD2 * = 3102, which is the permutation taking 3210 to 3102. */ const Permutation permutation_by_index[24] = { 0xE4, 0xE1, 0xD2, 0xD8, 0xC9, 0xC6, 0x93, 0x9C, 0x8D, 0x87, 0xB4, 0xB1, 0x4E, 0x4B, 0x78, 0x72, 0x63, 0x6C, 0x39, 0x36, 0x27, 0x2D, 0x1E, 0x1B}; /* * index_by_permutation[] is the inverse of permutation_by_index[]. * That is, for 0 <= i < 24, index_by_permutation[permutation_by_index[i]] = i. */ const char index_by_permutation[256] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 23, -1, -1, 22, -1, -1, -1, -1, -1, -1, -1, -1, 20, -1, -1, -1, -1, -1, 21, -1, -1, -1, -1, -1, -1, -1, -1, 19, -1, -1, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1, -1, -1, -1, -1, 15, -1, -1, -1, -1, -1, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9, -1, -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, -1, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; #include "end_namespace.h" regina-4.96/engine/snappea/kernel/tables.h000644 000765 000024 00000002161 12377774107 020426 0ustar00babstaff000000 000000 /* * tables.h * * The following tables are defined and documented in tables.c. * They are globally available within the kernel, but are not * available to the user interface. */ #ifndef _tables_ #define _tables_ #include "kernel_typedefs.h" #include "kernel_namespace.h" extern const EdgeIndex edge3[6]; extern const EdgeIndex edge_between_faces[4][4]; extern const EdgeIndex edge3_between_faces[4][4]; extern const EdgeIndex edge_between_vertices[4][4]; extern const EdgeIndex edge3_between_vertices[4][4]; extern const FaceIndex one_face_at_edge[6]; extern const FaceIndex other_face_at_edge[6]; extern const VertexIndex one_vertex_at_edge[6]; extern const VertexIndex other_vertex_at_edge[6]; extern const FaceIndex remaining_face[4][4]; extern const FaceIndex face_between_edges[6][6]; extern const Permutation inverse_permutation[256]; extern const signed char parity[256]; extern const FaceIndex vt_side[4][3]; extern const Permutation permutation_by_index[24]; extern const char index_by_permutation[256]; #include "end_namespace.h" #endif regina-4.96/engine/snappea/kernel/terse_triangulation.h000644 000765 000024 00000012162 12377774107 023240 0ustar00babstaff000000 000000 /* * terse_triangulation.h * * This data structure describes a Triangulation in a "terse" format. * The data structure is intended to minimize storage requirements, * and contains only the minimum information required to reconstruct * the Triangulation in the full triangulation.h format. * * The data structure allows the option of including the value of the * Chern-Simons invariant (mod 1/2). * * Most often the TerseTriangulation will be used in conjunction with * the TersestTriangulation data format (cf. tersest_triangulation.h), * which represents the TerseTriangulation as a short sequence of * characters, suitable for storage in a file or transmission over * a network. * * Bill Thurston provided the original idea for this data structure. * The implementation has evolved from code written by Martin Hildebrand at * the Geometry Center (then the Geometry Supercomputer Project) in 1988. * * * [The following description of the TerseTriangulation assumes basic * familiarity with the discussion "Gluings of ideal tetrahedra" preceding * the Permutation typedef in kernel_typedefs.h.] * * The TerseTriangulation data structure provides the data for an * algorithm for constructing an ideal triangulation. The algorithm is * as follows. We begin with n ideal tetrahedra, which we are going * to assemble into an ideal triangulation. The vertices of each * tetrahedron are numbered 0, 1, 2 and 3, and the faces are numbered * according to the opposite vertices. The tetrahedra are all identical. * Take one tetrahedron and call it tetrahedron 0. Consider face 0 * of tetrahedron 0. It may glue to some other face of tetrahedron 0, * or it may glue to a different tetrahedron. The first entry of the * Boolean array glues_to_old_tet tells us which is the case. That is, * if glues_to_old_tet[0] is TRUE, then face 0 glues to some other face * of tetrahedron 0; if glues_to_old_tet[0] is FALSE, it glues to a * different tetrahedron. * * In the case that glues_to_old_tet[0] is TRUE, which_old_tet[0] will tell * us which old tetrahedron it glues to (here which_old_tet[0] must * obviously be 0, because tetrahedron 0 is the only tetrahedron we're * working with so far, but in a minute you'll see the full generality of * the which_old_tet array), and which_gluing[0] tells us the gluing * pattern (cf. the discussion "Gluings of ideal tetrahedra" in * kernel_prototypes.h). * * In the case that glues_to_old_tet[0] is FALSE, we attach one of the * as-yet-unused tetrahedra to face 0 of tetrahedron 0. The new * tetrahedron will be called tetrahedron 1, and its vertices will * inherit indices from the vertices of tetrahedron 0 in the canonical * way, by reflection across their common face. (The gluing will be * the identity Permutation.) * * Once we've taken care of face 0 of tetrahedron 0, we move on to * face 1 of tetrahedron 0. If it's already been glued (to face 0), * we do nothing. Otherwise we consult the next entry in the * glues_to_old_tet[] array: if it's TRUE, then the next entries in * the which_old_tet[] and which_gluing[] arrays tell us which tetrahedron * it glues to (maybe tetrahedron 0, or maybe tetrahedron 1), and what * the gluing Permutation is; if it's FALSE, we attach a new tetrahedron * as described above. * * We continue this process for faces 2 and 3 of tetrahedron 0, then * move on to faces 0, 1, 2 and 3 (in that order) of tetrahedron 1, * then tetrahedron 2, etc., until we have constructed the entire * triangulation. Note that this algorithm assumes the triangulation * is connected. * * If there are n tetrahedra, there'll be 4n faces, and (4n)/2 = 2n * decisions as to whether to glue to an old tetrahedron or a new one. * (The last two "decisions" will always be to glue to an old tetrahedron, * but we won't worry about that. The terse string data format does, * however, take this into account.) Precisely (n - 1) of those * decisions will be to add a new tetrahedron, and the remaining (n + 1) * decisions will be to glue to an old tetrahedron. This means that * the glues_to_old_tet[] array must have length 2n, while the * which_old_tet[] and which_gluing[] arrays must have length (n + 1). * * The file SnapPea.h contains the "opaque typedef" * * typedef struct TerseTriangulation TerseTriangulation; * * which lets the UI declare and pass pointers to TerseTriangulations * without actually knowing what they are. This file provides the * kernel with the actual definition. */ #ifndef _terse_triangulation_ #define _terse_triangulation_ #include "kernel.h" #include "kernel_namespace.h" struct TerseTriangulation { /* * The first four fields provide the basic data described above. */ int num_tetrahedra; Boolean *glues_to_old_tet; int *which_old_tet; Permutation *which_gluing; /* * Optionally, we may wish to record the Chern-Simons invariant, * since it isn't computable from scratch (at least not in 1993). */ Boolean CS_is_present; double CS_value; }; #include "end_namespace.h" #endif regina-4.96/engine/snappea/kernel/tersest_triangulation.h000644 000765 000024 00000010106 12377774107 023603 0ustar00babstaff000000 000000 /* * tersest_triangulation.h * * This data structure -- which is really just a formatting convention for * an array of chars -- compresses the information in a TerseTriangulation * to the maximum extent possible. It works only for Triangulations of 7 * or fewer Tetrahedra. It is intended for use in storing libraries of * manifolds, such as the 5-, 6- and 7-tetrahedron censuses. * * Here's how the information from the TerseTriangulation data structure * is stored. The description is for a 7-tetrahedron Triangulation. * With fewer Tetrahedra some bits will be unused, but we always use * the same number of bytes. (The reason we always use the same number * of bytes is so that we can retrieve a manifold from the middle of a long * file without reading the whole file.) Recall that a TerseTriangulation * for n Tetrahedra has a glues_to_old_tet[] array of length 2n, and * which_old_tet[] and which_gluing[] arrays of length n+1. So for * 7 Tetrahedra, glues_to_old_tet[] has length 14, while which_old_tet[] * and which_gluing[] each have length 8. * * num_tetrahedra * * is redundant and is not stored at all. The number of Tetrahedra can * be deduced from the glues_to_old_tet array by keeping track of how * many free faces are available at each stage. * * glues_to_old_tet[] * * is stored in the first two bytes of the TersestTriangulation string. * * glues_to_old_tet[0] is stored in the lowest-order bit of byte 0, * . . . and so on until . . . * glues_to_old_tet[7] is stored in the highest-order bit of byte 0. * * glues_to_old_tet[8] is stored in the lowest-order bit of byte 1, * . . . and so on until . . . * glues_to_old_tet[13] is stored in the sixth bit of byte 1. * * Note that the two highest-order bits in byte 1 remain available for * other purposes. The highest-order bit tells whether a Chern-Simons * invariant is present (cf. below). * * which_old_tet[] * which_gluing[] * * which_old_tet[] and which_gluing[] are stored in tandem. * * which_old_tet[i] is stored in the three highest-order bits * of byte 2+i. which_old_tet[i] will always be an integer * in the range [0, 6], so it fits comfortably in three bits. * * which_gluing[i] is stored in the five lowest-order bits * of byte 2+i. Each Permutation is converted to an integer * in the range [0, 23], which fits comfortably in five bits. * The array index_by_permutation[] in tables.c does the conversion. * * CS_is_present * CS_value * * CS_is_present is stored in the highest-order bit of byte 1. * * if (CS_is_present == TRUE) * bytes 10 through 17 hold the CS_value, encoded as follows. * First add a multiple of 1/2, if necessary, so that the CS_value * lies in the range [-1/4, 1/4) Then mulitply by 2 and add 1/2 * so that it lies in the ragne [0, 1). The CS_value is a * double which on some machines (e.g. the Mac) has an 8-btye * mantissa. In binary, this is a number like 0.100101000..., with * 64 meaningful binary digits after the decimal point (the "binary * point" ?). The first 8 digits are stored in byte 10 of the * TersestTriangulation string, the next 8 digits are stored in * byte 11, and so on until the final 8 meaningful digits are stored * in byte 17. On some machines (e.g. on most UNIX workstations) * doubles have only 6-byte mantissas, in which case we just * zero-fill bytes 16 and 17 of the TersestTriangulation string * (in practice this shouldn't occur, because the libraries of * manifolds will be created on the Mac at full accuracy, and then * only read on less accurate platforms). * * if (CS_is_present == FALSE) * bytes 10 through 17 are unused. */ #ifndef _tersest_triangulation_ #define _tersest_triangulation_ #include "kernel_namespace.h" typedef unsigned char TersestTriangulation[18]; #include "end_namespace.h" #endif regina-4.96/engine/snappea/kernel/tet_shapes.c000644 000765 000024 00000013744 12377774107 021317 0ustar00babstaff000000 000000 /* * tet_shapes.c * * This file contains the following low-level functions for * working with TetShapes. * * void add_edge_angles( Tetrahedron *tet0, EdgeIndex e0, * Tetrahedron *tet1, EdgeIndex e1, * Tetrahedron *tet2, EdgeIndex e2) * * Boolean angles_sum_to_zero( Tetrahedron *tet0, EdgeIndex e0, * Tetrahedron *tet1, EdgeIndex e1); * * void compute_remaining_angles(Tetrahedron *tet, EdgeIndex e); * * * add_edge_angles() adds the edge angles at edge e0 of tet0 * to the corresponding angles at edge e1 of tet1, and writes * the results to edge e2 of tet2. It pays careful attention * to the edge_orientations. Note that even though opposite * edges of a Tetrahedron have equal angles, they needn't have * the same edge_orientation, so you should pass an actual * EdgeIndex in the range 0-5, not merely a quasi-equivalent * index in the range 0-2. The edge angle of the sum will be * in the range [(-1/2) pi, (3/2) pi], regardless of the angles * of the summands. * * angles_sum_to_zero() returns TRUE iff one of the angles * (shape[complete]->cwl[ultimate] or shape[filled]->cwl[ultimate]) * at edge e0 of tet0 cancels the corresponding angle at edge e1 * of tet1 (mod 2 pi i). Accounts for edge_orientations. * * compute_remaining_angles() assumes the angle at edge e is * correct, and computes the remaining angles in terms of it. * The EdgeIndex may be given in either the range 0-5 or the * range 0-2. The arguments of the remaining angles will be * in the range [(-1/2) pi, (3/2) pi]. */ #include "kernel.h" #include "kernel_namespace.h" /* * CANCELLATION_EPSILON says how close the logs of two complex * numbers must be to be considered equal. */ #define CANCELLATION_EPSILON 1e-4 static void add_tet_shapes( TetShape *ts0, EdgeIndex e30, Orientation eo0, TetShape *ts1, EdgeIndex e31, Orientation eo1, TetShape *ts2, EdgeIndex e32, Orientation eo2); static void add_complex_with_log( ComplexWithLog *cwl0, Orientation eo0, ComplexWithLog *cwl1, Orientation eo1, ComplexWithLog *cwl2, Orientation eo2); static Boolean logs_sum_to_zero( Complex summand0, Orientation eo0, Complex summand1, Orientation eo1); static void compute_cwl(ComplexWithLog cwl[3], EdgeIndex e); static void normalize_angle(Real *angle); void add_edge_angles( Tetrahedron *tet0, EdgeIndex e0, Tetrahedron *tet1, EdgeIndex e1, Tetrahedron *tet2, EdgeIndex e2) { int i; for (i = 0; i < 2; i++) /* i = complete, filled */ add_tet_shapes( tet0->shape[i], edge3[e0], tet0->edge_orientation[e0], tet1->shape[i], edge3[e1], tet1->edge_orientation[e1], tet2->shape[i], edge3[e2], tet2->edge_orientation[e2]); } static void add_tet_shapes( TetShape *ts0, EdgeIndex e30, Orientation eo0, TetShape *ts1, EdgeIndex e31, Orientation eo1, TetShape *ts2, EdgeIndex e32, Orientation eo2) { int i; for (i = 0; i < 2; i++) /* i = ultimate, penultimate */ add_complex_with_log( &ts0->cwl[i][e30], eo0, &ts1->cwl[i][e31], eo1, &ts2->cwl[i][e32], eo2); } static void add_complex_with_log( ComplexWithLog *cwl0, Orientation eo0, ComplexWithLog *cwl1, Orientation eo1, ComplexWithLog *cwl2, Orientation eo2) { /* * First compute the sum of the logs, then recover * the rectangular form. * * We do all computations relative to the Orientation * of the EdgeClass. So if a particular edge is seen * as left_handed by the EdgeClass, we must negate the * real part of the log of its complex angle. (Recall * that all all TetShapes are stored relative to the * right_handed Orientation of the Tetrahedron.) */ Complex summand0, summand1, sum; summand0 = cwl0->log; if (eo0 == left_handed) summand0.real = - summand0.real; summand1 = cwl1->log; if (eo1 == left_handed) summand1.real = - summand1.real; sum = complex_plus(summand0, summand1); if (eo2 == left_handed) sum.real = - sum.real; normalize_angle(&sum.imag); cwl2->log = sum; cwl2->rect = complex_exp(sum); } Boolean angles_sum_to_zero( Tetrahedron *tet0, EdgeIndex e0, Tetrahedron *tet1, EdgeIndex e1) { int i; for (i = 0; i < 2; i++) /* i = complete, filled */ if (logs_sum_to_zero( tet0->shape[i]->cwl[ultimate][edge3[e0]].log, tet0->edge_orientation[e0], tet1->shape[i]->cwl[ultimate][edge3[e1]].log, tet1->edge_orientation[e1])) return TRUE; return FALSE; } static Boolean logs_sum_to_zero( Complex summand0, Orientation eo0, Complex summand1, Orientation eo1) { Complex sum; if (eo0 != eo1) summand1.real = - summand1.real; sum = complex_plus(summand0, summand1); normalize_angle(&sum.imag); return (complex_modulus(sum) < CANCELLATION_EPSILON); } void compute_remaining_angles( Tetrahedron *tet, EdgeIndex e) { int i, j; for (i = 0; i < 2; i++) /* i = complete, filled */ for (j = 0; j < 2; j++) /* j = ultimate, penultimate */ compute_cwl(tet->shape[i]->cwl[j], edge3[e]); } static void compute_cwl( ComplexWithLog cwl[3], EdgeIndex e) { /* * Compute cwl[(e+1)%3] and cwl[(e+2)%3] in terms of cwl[e]. */ int i; for (i = 1; i < 3; i++) { cwl[(e+i)%3].rect = complex_div(One, complex_minus(One, cwl[(e+i-1)%3].rect)); cwl[(e+i)%3].log = complex_log(cwl[(e+i)%3].rect, PI_OVER_2); } } static void normalize_angle( Real *angle) { /* * Normalize the angle to lie in the range [(-1/2) pi, (3/2) pi]. */ while (*angle > THREE_PI_OVER_2) *angle -= TWO_PI; while (*angle < - PI_OVER_2) *angle += TWO_PI; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/tidy_peripheral_curves.c000644 000765 000024 00000006536 12377774107 023734 0ustar00babstaff000000 000000 /* * tidy_peripheral_curves.c * * * This file provides the function * * void tidy_peripheral_curves(Triangulation *manifold); * * which is used within the kernel to clean up a set of peripheral * curves. * * Functions which alter triangulations maintain a set of peripheral * curves which is technically correct, but suffers two faults. * A minor fault is that the peripheral curves wind around a lot, * and therefore create unnecessarily complicated cusp equations. * The more serious fault is that the curves may evolve trivial loops; * that is, a single meridian or longitude will have several components, * one of which is the correct curve while the others are homotopically * trivial loops. Such trivial loops introduce erroneous multiples * of 2pi into the computed holonomies, and thereby foul up the * computation of hyperbolic structures. * * The function tidy_peripheral_curves() * * (1) makes a copy of the existing peripheral curves, * (2) calls peripheral_curves() to create a nice set of * peripheral curves, and * (3) expresses the original curves as linear combinations * of the nice curves. * * The result is an "efficient" set of curves, with no trivial * loops. */ #include "kernel.h" #include "kernel_namespace.h" /* * scratch_curves[0] will store the original peripheral curves. * scratch_curves[1] will store the nice peripheral curves. */ #define original_curves 0 #define nice_curves 1 static void compute_new_curves(Triangulation *manifold); void tidy_peripheral_curves( Triangulation *manifold) { /* * Copy the original peripheral curves to the * scratch_curve[original_curves] fields of the Tetrahedra. */ copy_curves_to_scratch(manifold, original_curves, TRUE); /* * Compute a nice set of peripheral curves. */ peripheral_curves(manifold); /* * Copy the nice peripheral curves to the * scratch_curve[nice_curves] fields of the Tetrahedra. */ copy_curves_to_scratch(manifold, nice_curves, FALSE); /* * Compute the intersection numbers of the original curves * with the nice curves. */ compute_intersection_numbers(manifold); /* * Compute the new curves as linear combinations of the * nice curves. */ compute_new_curves(manifold); } static void compute_new_curves( Triangulation *manifold) { Tetrahedron *tet; int h, i, j, k; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (h = 0; h < 2; h++) /* which curve */ for (i = 0; i < 2; i++) /* which sheet */ for (j = 0; j < 4; j++) /* which vertex */ for (k = 0; k < 4; k++) /* which side of that vertex */ tet->curve[h][i][j][k] = (j == k) ? 0 : - tet->cusp[j]->intersection_number[h][L] * tet->scratch_curve[nice_curves][M][i][j][k] + tet->cusp[j]->intersection_number[h][M] * tet->scratch_curve[nice_curves][L][i][j][k]; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/transcendentals.c000644 000765 000024 00000003633 12377774107 022344 0ustar00babstaff000000 000000 /* * transcendentals.c * * What is the value of acos(1.0000000001)? * On the Mac you get the intended answer (0.0), but unix returns NaN. * To guard against this sort of problem, the SnapPea kernel uses * * double safe_acos(double x); * double safe_asin(double x); * double safe_sqrt(double x); * * Incredibly enough, the standard ANSI libraries omit the * inverse hyperbolic trig functions entirely. * * double arcsinh(double x); * double arccosh(double x); * * Many (but not all) standard libraries now provide asinh() and acosh(). * I've changed the names of my homemade versions to arcsinh() and arccosh() * to avoid conflicts. 2000/02/20 JRW */ #include "kernel.h" #include "kernel_namespace.h" #define ERROR_EPSILON 1e-3 Real safe_acos(Real x) { if (x > 1.0) { if (x > 1.0 + ERROR_EPSILON) uFatalError("safe_acos", "transcendentals"); x = 1.0; } if (x < -1.0) { if (x < -(1.0 + ERROR_EPSILON)) uFatalError("safe_acos", "transcendentals"); x = -1.0; } return acos(x); } Real safe_asin(Real x) { if (x > 1.0) { if (x > 1.0 + ERROR_EPSILON) uFatalError("safe_asin", "transcendentals"); x = 1.0; } if (x < -1.0) { if (x < -(1.0 + ERROR_EPSILON)) uFatalError("safe_asin", "transcendentals"); x = -1.0; } return asin(x); } Real safe_sqrt(Real x) { if (x < 0.0) { if (x < -ERROR_EPSILON) uFatalError("safe_sqrt", "transcendentals"); x = 0.0; } return sqrt(x); } Real arcsinh( Real x) { return log(x + sqrt(x*x + 1.0)); } Real arccosh( Real x) { if (x < 1.0) { if (x < 1.0 - ERROR_EPSILON) uFatalError("arccosh", "transcendentals"); x = 1.0; } return log(x + sqrt(x*x - 1.0)); } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/triangulation.h000644 000765 000024 00000036101 12377774107 022035 0ustar00babstaff000000 000000 /* * triangulation.h * * This file defines the basic data structure for an ideal * triangulation. SnapPea's various modules communicate with each * other primarily by passing pointers to Triangulations. * * The Triangulation data structure consists of some global information * about the manifold (number of tetrahedra, number of cusps, etc.) * following by doubly linked lists of Tetrahedra, EdgeClasses, and Cusps. * As the triangulation varies dynamically (for example, during the * triangulation simplification algorithm) Tetrahedra, EdgeClasses and * Cusps may be easily inserted and deleted using the INSERT_BEFORE() * and REMOVE_NODE() macros found in kernel_typedefs.h. The Triangulation * data structure contains header and tailer nodes for each doubly linked * list, to avoid having to consider special cases while inserting and * deleting nodes. * * To keep the global structure of this file as clear as possible, * most of the local documentation appears elsewhere. The comment * next to each field says what .c file (if any) contains the * documentation for that field. * * Most fields are maintained globally. That is, you may assume they * contain correct values at all times, and you should update their * values if you change the triangulation. Fields which are used locally * within a single file or module are so indicated. They do not contain * correct values outside that module, and you need not maintain them. * * Note that SnapPea.h (the only header file common to the user interface * and the computational kernel) contains the opaque typedef * * typedef struct Triangulation Triangulation; * * This opaque typedef allows the user interface to declare and pass * pointers to Triangulations, without being able to access a * Triangulation's fields directly. This file provides the kernel with * the actual definition. * * The inclusion of lower-level data structures within higher-level ones * forces the following typedefs to be orangized in a bottom-up fashion, * beginning with the least significant data structure (ComplexWithLog) * and working towards the most significant one (Triangulation). I * therefore recommend that you start reading this file at the bottom * and work your way up. */ #ifndef _triangulation_ #define _triangulation_ #include "SnapPea.h" #include "kernel_typedefs.h" #include "kernel_namespace.h" /* * Forward declarations. */ typedef struct ComplexWithLog ComplexWithLog; typedef struct TetShape TetShape; typedef struct Tetrahedron Tetrahedron; typedef struct EdgeClass EdgeClass; typedef struct Cusp Cusp; /* * ComplexWithLog stores a complex edge parameter in both rectangular * and logarithmic form. That is, the log field is always the complex * logarithm of the rect field. The imaginary part of the log varies * continuously during Dehn filling, and is not restricted to any * particular branch of the logarithm. * * The edge parameter is always expressed relative to the * right_handed orientation of the tetrahedron. */ struct ComplexWithLog { Complex rect; Complex log; }; /* * TetShape stores the complex edge parameters at edges 0,1 and 2 of * a given Tetrahedron. (See edge_classes.c for the edge indexing scheme.) * Edges 5, 4 and 3 are opposite 0, 1 and 2, respectively, and therefore * have equal edge parameters. The edge parameters are recorded at the * next-to-the-last as well as the last iteration of Newton's method in * the hyperbolic structures module, to allow the estimation of errors * in various computed quantities (volume, etc.). Warning: the true error * is usually greater than the error between the penultimate and ultimate * iterations of Newton's method. That is, if you switch to a different * triangulation of the same manifold, you'll find the volume, etc. differs * by more than it did between the last two iterations of Newton's method. * The edge parameters at the next-to-the-last iteration are stored as * cwl[penultimate][], while those at the last iteration are cwl[ultimate][]. * * * Note that the Tetrahedron structure (immediately below) contains pointers * to TetShapes, rather than the TetShapes themselves. The disadvantage * of this scheme is that the TetShapes must be allocated and deallocated * explicitly. The advantages are * * (1) Some functions which temporarily require large numbers of Tetrahedra * can get by with less memory if they don't require the TetShapes. * On a Mac, for example, the Tetrahedron structure itself requires * 242 bytes, while the TetShapes require an additional 576 bytes. * This difference can be significant. For example, the function which * computes an ideal triangulation for a partially filled multicusp * manifold will, when applied to a 100-Tetrahedron Triangulation, * temporarily create more than 3000 Tetrahedra. By omitting the * TetShapes, the memory requirement for these Tetrahedra drops * from 2.5 MB to 750 kB. * * (2) It's easy for the low-level retriangulation function (e.g. * the 2-3 and 3-2 moves) to determine whether the Tetrahedra * have shapes associated with them. If the pointers to TetShapes * are NULL, there are no shapes; otherwise there are. * * The TetShape corresponding to the complete (resp. Dehn filled) hyperbolic * structure is stored in the Tetrahedron data structure as tet->shape[complete] * (resp. tet->shape[filled]). By convention, TetShapes will be present iff * tet->solution_type[complete] and tet->solution_type[filled] are something * other than not_attempted. */ struct TetShape { ComplexWithLog cwl[2][3]; }; struct Tetrahedron { Tetrahedron *neighbor[4]; /* kernel_typedefs.h */ Permutation gluing[4]; /* kernel_typedefs.h */ Cusp *cusp[4]; /* the cusp containing each vertex */ int curve[2][2][4][4]; /* peripheral_curves.c */ int scratch_curve[2][2][2][4][4]; /* intersection_numbers.c (local) */ EdgeClass *edge_class[6]; /* edge_classes.c */ Orientation edge_orientation[6];/* edge_classes.c */ TetShape *shape[2]; /* see TetShape and ComplexWithLog above */ ShapeInversion *shape_history[2]; /* kernel_typedefs.h */ int coordinate_system; /* hyperbolic_structure.c (local) */ int index; /* hyperbolic_structure.c (local) */ GeneratorStatus generator_status[4];/* choose_generators.c (local) */ int generator_index[4]; /* choose_generators.c (local) */ GluingParity generator_parity[4];/* choose_generators.c (local) */ Complex corner[4]; /* choose_generators.c (local) */ FaceIndex generator_path; /* choose_generators.c (local) */ VertexCrossSections *cross_section; /* cusp_cross_section.c (local) */ Real tilt[4]; /* cusp_cross_section.c (local) */ CanonizeInfo *canonize_info; /* canonize_part_2.c (local) */ Tetrahedron *image; /* symmetry.h (local) */ Permutation map; /* symmetry.h (local) */ Boolean tet_on_curve; /* dual_curves.c (local) */ Boolean face_on_curve[4]; /* dual_curves.c (local) */ CuspNbhdPosition *cusp_nbhd_position;/* cusp_neighborhoods.c (local) */ EdgeIndex parallel_edge; /* normal_surfaces.h (local) */ int num_squares, /* normal_surfaces.h (local) */ num_triangles[4]; /* normal_surfaces.h (local) */ Boolean has_correct_orientation; /* normal_surface_splitting.c (local) */ int flag; /* general purpose integer for local use as necessary */ Extra *extra; /* general purpose pointer for local use as necessary */ /* see Extra typedef in kernel_typedefs.h for details */ Tetrahedron *prev; /* previous tetrahedron on doubly linked list */ Tetrahedron *next; /* next tetrahedron on doubly linked list */ }; struct EdgeClass { int order; /* number of incident edges of tetrahedra */ Tetrahedron *incident_tet; /* one particular incident tetrahedron... */ EdgeIndex incident_edge_index; /* ...and the index of the incident edge */ int num_incident_generators;/* choose_generators.c (local) */ Boolean active_relation; /* choose_generators.c (local) */ Complex *complex_edge_equation; /* gluing_equations.c (used locally) */ Real *real_edge_equation_re, /* gluing_equations.c (used locally) */ *real_edge_equation_im; /* gluing_equations.c (used locally) */ Complex edge_angle_sum; /* used locally in hyperbolic structures module */ Complex target_angle_sum; /* used by MC -- force_tet_shapes */ int index; /* used locally for saving Triangulations to disk */ Real intercusp_distance; /* cusp_neighborhoods.c (used locally) */ EdgeClass *prev; /* previous EdgeClass on doubly linked list */ EdgeClass *next; /* next EdgeClass on doubly linked list */ }; struct Cusp { CuspTopology topology; /* torus_cusp or Klein_cusp */ Boolean is_complete; /* is the cusp currently unfilled? */ Real m, /* Dehn filling coefficient */ l; /* Dehn filling coefficient */ Complex holonomy[2][2]; /* holonomy.c */ Complex target_holonomy; /* used by MC -- force_tet_shapes */ Complex *complex_cusp_equation; /* gluing_equations.c (used locally) */ Real *real_cusp_equation_re, /* gluing_equations.c (used locally) */ *real_cusp_equation_im; /* gluing_equations.c (used locally) */ Complex cusp_shape[2]; /* cusp_shapes.c */ int shape_precision[2]; /* cusp_shapes.c */ int index; /* cusp number, as perceived by user */ /* (numbering starts at zero) */ Real displacement, /* cusp_neighborhoods.c (used globally) */ displacement_exp, /* cusp_neighborhoods.c (used globally) */ reach, /* cusp_neighborhoods.c (local) */ stopping_displacement; /* cusp_neighborhoods.c (local) */ Cusp *stopper_cusp; /* cusp_neighborhoods.c (local) */ Boolean is_tied; /* cusp_neighborhoods.c (local) */ Complex translation[2], /* cusp_neighborhoods.c (local) */ scratch; /* cusp_neighborhoods.c (local) */ Real exp_min_d; /* cusp_neighborhoods.c (local) */ Tetrahedron *basepoint_tet; /* fundamental_group.c (semi-local) */ VertexIndex basepoint_vertex; /* fundamental_group.c (semi-local) */ Orientation basepoint_orientation; /* fundamental_group.c (semi-local) */ int intersection_number[2][2]; /* intersection_numbers.c (local) */ Boolean is_finite; /* finite_vertices.c (used locally) */ /* indices are negative, starting at -1 */ Cusp *matching_cusp; /* subdivide.c, finite_vertices.c, */ /* cover.c, normal_surface_splitting.c */ /* (used locally) */ int euler_characteristic; /* cusps.c (local) */ Cusp *prev; /* previous Cusp on doubly linked list */ Cusp *next; /* next Cusp on doubly linked list */ }; struct Triangulation { char *name; /* name of manifold */ int num_tetrahedra; /* number of tetrahedra */ SolutionType solution_type[2]; /* complete and filled */ Orientability orientability; /* Orientability of manifold */ int num_cusps, /* total number of cusps */ num_or_cusps, /* number of orientable cusps */ num_nonor_cusps; /* number of nonorientable cusps */ int num_generators; /* choose_generators.c (local) */ Boolean CS_value_is_known, /* Chern_Simons.c */ CS_fudge_is_known; /* Chern_Simons.c */ Real CS_value[2], /* Chern_Simons.c */ CS_fudge[2]; /* Chern_Simons.c */ Complex (*dilog)(Complex z); /* External dilog function */ Real max_reach, /* cusp_neighborhoods.c (local) */ tie_group_reach, /* cusp_neighborhoods.c (local) */ volume; /* cusp_neighborhoods.c (local) */ Tetrahedron tet_list_begin, /* header node for doubly linked list of Tetrahedra */ tet_list_end; /* tailer node for doubly linked list of Tetrahedra */ EdgeClass edge_list_begin,/* header node for doubly linked list of Edges */ edge_list_end; /* tailer node for doubly linked list of Edges */ Cusp cusp_list_begin,/* header node for doubly linked list of Cusps */ cusp_list_end; /* tailer node for doubly linked list of Cusps */ }; #include "end_namespace.h" #endif regina-4.96/engine/snappea/kernel/triangulation_io.h000644 000765 000024 00000010337 12377774107 022527 0ustar00babstaff000000 000000 /* * triangulation_io.h * * The question of file formats is tricky. Typically an application has a * different file format for each platform it runs on (Mac, Windows, etc.), * perhaps with some support for translating between them. Certainly * the easiest way to write Macintosh SnapPea would have been to use * the THINK Class Library's built-in file handling capabilities: * file i/o would have been trivial to program, and each kind of file * (triangulation, generators, link projection) would have its own * "file type" and icon. However, I chose to use straight ASCII text * files for the following reasons: * * (1) The files can be read and written on any platform. * For example, a Mac user can send a Triangulation file * to a friend using a unix version of SnapPea. * * (2) Human beings can read the files using any text editor. * * (3) Text-only files are best for people doing other programming * projects which use SnapPea's manifolds as input. (Again, * people do this work on a variety of platforms.) * * On the other hand, I think it would be a mistake to hard-code the * SnapPea kernel to read data from unix-style FILEs. When the UI * reads a triangulation file, it passes the data to the kernel using * the data structures defined below. And, of course, when the UI wants * to write a triangulation to a file, it requests the data from the * kernel in this same format. * * Notes: * * (1) This format is similar to that of the Triangulation data structure. * However, the present format is available to the UI, while * the Triangulation data structure is private to the kernel. * * (2) The new file format is not backward compatible to the old * file format, although they are similar. (I couldn't keep * the old file format because it doesn't work properly with * nonorientable manifolds.) SnapPea 2.0 will read (but not write) * the old file format, with the exception that peripheral curves * on nonorientable manifolds are recomputed from scratch. * * (3) If you (or your program) is writing TriangulationData structures * from scratch, note that not all fields are required. The fields * solution_type, volume, and the TetrahedronDatas' filled_shapes * are ignored by data_to_triangulation(), because it recomputes the * hyperbolic structure from scratch. The meridian and longitude * are optional: if you provide them, data_to_triangulation() * will use them; otherwise it provides a default basis. * (In the latter case, of course, you shouldn't specify any * Dehn fillings, because you aren't providing the basis relative * to which they are defined.) * * 96/9/17 If you set both num_or_cusps and num_nonor_cusps to zero, * data_to_triangulation() will create the Cusps for you. It will * also create the peripheral curves. * * 96/9/17 If you specify unknown_orientability, data_to_triangulation() * will attempt to orient the manifold. This will typically change * the indexing of the Tetrahedra's vertices. */ /* * This file (triangulation_io.h) is intended solely for inclusion * in SnapPea.h. It depends on some of the typedefs there. */ #include "kernel_namespace.h" typedef struct TriangulationData TriangulationData; typedef struct CuspData CuspData; typedef struct TetrahedronData TetrahedronData; struct TriangulationData { char *name; int num_tetrahedra; SolutionType solution_type; Real volume; Orientability orientability; Boolean CS_value_is_known; Real CS_value; int num_or_cusps, num_nonor_cusps; CuspData *cusp_data; TetrahedronData *tetrahedron_data; }; struct CuspData { CuspTopology topology; Real m, l; }; struct TetrahedronData { /* * Note: gluing[i][j] is the image of j under the i-th gluing permutation. */ int neighbor_index[4]; int gluing[4][4]; int cusp_index[4]; int curve[2][2][4][4]; Complex filled_shape; }; #include "end_namespace.h" regina-4.96/engine/snappea/kernel/triangulations.c000644 000765 000024 00000100654 12377774107 022220 0ustar00babstaff000000 000000 /* * triangulation.c * * This file contains the following functions which the kernel * provides for the UI: * * void data_to_triangulation( TriangulationData *data, * Triangulation **manifold_ptr); * void triangulation_to_data( TriangulationData **data_ptr, * Triangulation *manifold); * void free_triangulation_data(TriangulationData *data); * void free_triangulation( Triangulation *manifold); * void copy_triangulation( Triangulation *source, * Triangulation **destination); * * Their use is described in SnapPea.h. * * This file also provides the functions * * void initialize_triangulation(Triangulation *manifold); * void initialize_tetrahedron(Tetrahedron *tet); * void initialize_cusp(Cusp *cusp); * void initialize_edge_class(EdgeClass *edge_class); * * which kernel functions use to do generic initializations. Much of * what they do is not really necessary, but it seems like a good idea * to at least write NULL into pointers which have not been set. * * This file also includes * * FuncResult check_Euler_characteristic_of_boundary(Triangulation *manifold); * * which returns func_OK if the Euler characteristic of the total * boundary of the manifold is zero. Otherwise it returns func_failed. * * Furthermore, this file includes * * void number_the_tetrahedra(Triangulation *manifold); * * which sets each Tetrahedron's index field equal to its position in * the linked list. Indices range from 0 to (num_tetrahedra - 1). * * In addition, we have * * void free_tetrahedron(Tetrahedron *tet); * * which frees a Tetrahedron and all attached data structures, but does NOT * remove the Tetrahedron from any doubly linked list it may be on, and * * void clear_shape_history(Tetrahedron *tet); * void copy_shape_history(ShapeInversion *source, ShapeInversion **dest); * void clear_one_shape_history(Tetrahedron *tet, FillingStatus which_history); * * which do what you'd expect (please see the code for details). */ #include "kernel.h" #include /* for sprintf() in check_neighbors_and_gluings() */ #include "kernel_namespace.h" static void check_neighbors_and_gluings(Triangulation *manifold); static int count_the_edge_classes(Triangulation *manifold); void data_to_triangulation( TriangulationData *data, Triangulation **manifold_ptr) { /* * We assume the UI has done some basic error checking * on the data, so we don't repeat it here. */ Triangulation *manifold; Tetrahedron **tet_array; Cusp **cusp_array; Boolean cusps_are_given; int i, j, k, l, m; /* Boolean all_peripheral_curves_are_zero*/ Boolean finite_vertices_are_present; /* * Initialize *manifold_ptr to NULL. * We'll do all our work with manifold, and then copy * manifold to *manifold_ptr at the very end. */ *manifold_ptr = NULL; /* * Allocate and initialize the Triangulation structure. */ manifold = NEW_STRUCT(Triangulation); initialize_triangulation(manifold); /* * Allocate and copy the name. */ manifold->name = NEW_ARRAY(strlen(data->name) + 1, char); strcpy(manifold->name, data->name); /* * Set up the global information. * * The hyperbolic structure is included in the file only for * human readers; here we recompute it from scratch. */ manifold->num_tetrahedra = data->num_tetrahedra; manifold->solution_type[complete] = not_attempted; manifold->solution_type[ filled ] = not_attempted; manifold->orientability = data->orientability; manifold->num_or_cusps = data->num_or_cusps; manifold->num_nonor_cusps = data->num_nonor_cusps; manifold->num_cusps = manifold->num_or_cusps + manifold->num_nonor_cusps; /* * Allocate the Tetrahedra. * Keep pointers to them on a temporary array, so we can * find them by their indices. */ tet_array = NEW_ARRAY(manifold->num_tetrahedra, Tetrahedron *); for (i = 0; i < manifold->num_tetrahedra; i++) { tet_array[i] = NEW_STRUCT(Tetrahedron); initialize_tetrahedron(tet_array[i]); INSERT_BEFORE(tet_array[i], &manifold->tet_list_end); } /* * If num_or_cusps or num_nonor_cusps is nonzero, allocate the Cusps. * Keep pointers to them on temporary arrays, so we can find them * by their indices. * Otherwise we will create arbitrary Cusps later. */ cusps_are_given = (data->num_or_cusps != 0) || (data->num_nonor_cusps != 0); if (cusps_are_given == TRUE) { cusp_array = NEW_ARRAY(manifold->num_cusps, Cusp *); for (i = 0; i < manifold->num_cusps; i++) { cusp_array[i] = NEW_STRUCT(Cusp); initialize_cusp(cusp_array[i]); INSERT_BEFORE(cusp_array[i], &manifold->cusp_list_end); } } else cusp_array = NULL; /* * Set up the Tetrahedra. */ /* all_peripheral_curves_are_zero = TRUE; */ finite_vertices_are_present = FALSE; for (i = 0; i < manifold->num_tetrahedra; i++) { for (j = 0; j < 4; j++) tet_array[i]->neighbor[j] = tet_array[data->tetrahedron_data[i].neighbor_index[j]]; for (j = 0; j < 4; j++) tet_array[i]->gluing[j] = CREATE_PERMUTATION( 0, data->tetrahedron_data[i].gluing[j][0], 1, data->tetrahedron_data[i].gluing[j][1], 2, data->tetrahedron_data[i].gluing[j][2], 3, data->tetrahedron_data[i].gluing[j][3]); if (cusps_are_given == TRUE) { for (j = 0; j < 4; j++) { if (data->tetrahedron_data[i].cusp_index[j] >= 0) /* assign a real cusp */ tet_array[i]->cusp[j] = cusp_array[data->tetrahedron_data[i].cusp_index[j]]; else { /* mark a finite vertex with NULL */ tet_array[i]->cusp[j] = NULL; finite_vertices_are_present = TRUE; } } for (j = 0; j < 2; j++) for (k = 0; k < 2; k++) for (l = 0; l < 4; l++) for (m = 0; m < 4; m++) { tet_array[i]->curve[j][k][l][m] = data->tetrahedron_data[i].curve[j][k][l][m]; /* if (data->tetrahedron_data[i].curve[j][k][l][m] != 0) all_peripheral_curves_are_zero = FALSE; */ } } } /* * 97/12/8 Check that the neighbors and gluings are consistent. * For SnapPea's own files this isn't necessary, but it's a big * help for people who write files by hand. It catches the most * obvious errors and provides a useful diagnosis (as opposed to, * say, having the program hang when inconsistent neighbors and/or * gluings send create_edge_classes() into an infinite loop). * Even in the typical case of reading SnapPea's own files, * check_neighbors_and_gluings() is very quick. */ check_neighbors_and_gluings(manifold); /* * Set up the EdgeClasses. */ create_edge_classes(manifold); orient_edge_classes(manifold); /* * If the Cusps were specified explicitly, copy in the data. * Otherwise create arbitrary Cusps now. */ if (cusps_are_given == TRUE) { for (i = 0; i < manifold->num_cusps; i++) { cusp_array[i]->topology = data->cusp_data[i].topology; cusp_array[i]->m = data->cusp_data[i].m; cusp_array[i]->l = data->cusp_data[i].l; cusp_array[i]->is_complete = (data->cusp_data[i].m == 0.0 && data->cusp_data[i].l == 0.0); cusp_array[i]->index = i; } /* * If finite vertices are present they will be marked with NULL. * Assign Cusp structures. */ if (finite_vertices_are_present == TRUE) create_fake_cusps(manifold); } else { create_cusps(manifold); finite_vertices_are_present = mark_fake_cusps(manifold); } /* * Provide peripheral curves if necessary. * This automatically records the CuspTopologies. */ peripheral_curves_as_needed(manifold); /* * Typically the manifold's orientability will already be known, * but if it isn't, try to orient it now. */ if (manifold->orientability == unknown_orientability) { orient(manifold); if (manifold->orientability == oriented_manifold) { fix_peripheral_orientations(manifold); } } /* * If the given triangulation includes finite vertices, remove them. */ if (finite_vertices_are_present == TRUE) remove_finite_vertices(manifold); /* * Count the Cusps if necessary, noting how many have each topology. */ if (cusps_are_given == FALSE) count_cusps(manifold); /* * Free the temporary arrays. */ my_free(tet_array); if (cusp_array != NULL) my_free(cusp_array); /* * Compute the complete and filled hyperbolic structures. * * (The Dehn fillings should be nontrivial only if the data * provided the peripheral curves.) * * Removed 2013/10/15 by NMD. * * find_complete_hyperbolic_structure(manifold); * do_Dehn_filling(manifold); * * * * If we provided the basis and the manifold is hyperbolic, * replace it with a shortest basis. * * if (all_peripheral_curves_are_zero == TRUE * && ( manifold->solution_type[complete] == geometric_solution * || manifold->solution_type[complete] == nongeometric_solution)) * install_shortest_bases(manifold); * */ /* * If the Chern-Simons invariant is present, compute the fudge factor. * Then recompute the value from the fudge factor, to restore the * uncertainty between the ultimate and penultimate values. */ manifold->CS_value_is_known = data->CS_value_is_known; manifold->CS_value[ultimate] = data->CS_value; manifold->CS_value[penultimate] = data->CS_value; compute_CS_fudge_from_value(manifold); compute_CS_value_from_fudge(manifold); /* * Done. */ *manifold_ptr = manifold; } static void check_neighbors_and_gluings( Triangulation *manifold) { Tetrahedron *tet, *nbr; FaceIndex f, nbr_f; Permutation this_gluing; char scratch[256]; number_the_tetrahedra(manifold); for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) for (f = 0; f < 4; f++) { this_gluing = tet->gluing[f]; nbr = tet->neighbor[f]; nbr_f = EVALUATE(this_gluing, f); if (nbr->neighbor[nbr_f] != tet) { sprintf(scratch, "inconsistent neighbor data, tet %d face %d to tet %d face %d", tet->index, f, nbr->index, nbr_f); uAcknowledge(scratch); uFatalError("check_neighbors_and_gluings", "triangulations"); } if (nbr->gluing[nbr_f] != inverse_permutation[this_gluing]) { sprintf(scratch, "inconsistent gluing data, tet %d face %d to tet %d face %d", tet->index, f, nbr->index, nbr_f); uAcknowledge(scratch); uFatalError("check_neighbors_and_gluings", "triangulations"); } } } void triangulation_to_data( Triangulation *manifold, TriangulationData **data_ptr) { /* * Allocate the TriangulationData and write in the data describing * the manifold. Set *data_ptr to point to the result. The UI * should call free_triangulation_data() when it's done with the * TriangulationData. */ TriangulationData *data; Cusp *cusp; Tetrahedron *tet; int i, j, k, l, m; *data_ptr = NULL; data = NEW_STRUCT(TriangulationData); if (manifold->name != NULL) { data->name = NEW_ARRAY(strlen(manifold->name) + 1, char); strcpy(data->name, manifold->name); } else data->name = NULL; data->num_tetrahedra = manifold->num_tetrahedra; data->solution_type = manifold->solution_type[filled]; data->volume = volume(manifold, NULL); data->orientability = manifold->orientability; data->CS_value_is_known = manifold->CS_value_is_known; data->num_or_cusps = manifold->num_or_cusps; data->num_nonor_cusps = manifold->num_nonor_cusps; if (manifold->CS_value_is_known == TRUE) data->CS_value = manifold->CS_value[ultimate]; data->cusp_data = NEW_ARRAY(manifold->num_cusps, CuspData); for (i = 0; i < manifold->num_cusps; i++) { cusp = find_cusp(manifold, i); data->cusp_data[i].topology = cusp->topology; data->cusp_data[i].m = cusp->m; data->cusp_data[i].l = cusp->l; } number_the_tetrahedra(manifold); data->tetrahedron_data = NEW_ARRAY(manifold->num_tetrahedra, TetrahedronData); for (tet = manifold->tet_list_begin.next, i = 0; tet != &manifold->tet_list_end; tet = tet->next, i++) { for (j = 0; j < 4; j++) data->tetrahedron_data[i].neighbor_index[j] = tet->neighbor[j]->index; for (j = 0; j < 4; j++) for (k = 0; k < 4; k++) data->tetrahedron_data[i].gluing[j][k] = EVALUATE(tet->gluing[j], k); /* * All negative cusp indices (for finite vertices) map to -1. * This could be changed if desired, but at the moment it's * consistent with TriagulationFileFormat. */ for (j = 0; j < 4; j++) data->tetrahedron_data[i].cusp_index[j] = ((tet->cusp[j]->index >= 0) ? tet->cusp[j]->index : -1); for (j = 0; j < 2; j++) for (k = 0; k < 2; k++) for (l = 0; l < 4; l++) for (m = 0; m < 4; m++) data->tetrahedron_data[i].curve[j][k][l][m] = tet->curve[j][k][l][m]; data->tetrahedron_data[i].filled_shape = (tet->shape[filled] != NULL) ? tet->shape[filled]->cwl[ultimate][0].rect : Zero; } *data_ptr = data; } void free_triangulation_data( TriangulationData *data) { /* * If the kernel allocates a TriangulationData structure, * the kernel must free it. */ if (data != NULL) { if (data->name != NULL) my_free(data->name); if (data->cusp_data != NULL) my_free(data->cusp_data); if (data->tetrahedron_data != NULL) my_free(data->tetrahedron_data); my_free(data); } } void free_triangulation( Triangulation *manifold) { Tetrahedron *dead_tet; EdgeClass *dead_edge; Cusp *dead_cusp; if (manifold != NULL) { if (manifold->name != NULL) my_free(manifold->name); while (manifold->tet_list_begin.next != &manifold->tet_list_end) { dead_tet = manifold->tet_list_begin.next; REMOVE_NODE(dead_tet); free_tetrahedron(dead_tet); } while (manifold->edge_list_begin.next != &manifold->edge_list_end) { dead_edge = manifold->edge_list_begin.next; REMOVE_NODE(dead_edge); my_free(dead_edge); } while (manifold->cusp_list_begin.next != &manifold->cusp_list_end) { dead_cusp = manifold->cusp_list_begin.next; REMOVE_NODE(dead_cusp); my_free(dead_cusp); } my_free(manifold); } } void free_tetrahedron( Tetrahedron *tet) { /* * This function does NOT remove the Tetrahedron from * any doubly linked list it may be on, but does remove * all data structures attached to the Tetrahedron. */ int i; for (i = 0; i < 2; i++) /* i = complete, filled */ if (tet->shape[i] != NULL) my_free(tet->shape[i]); clear_shape_history(tet); if (tet->cross_section != NULL) my_free(tet->cross_section); if (tet->canonize_info != NULL) my_free(tet->canonize_info); if (tet->cusp_nbhd_position != NULL) my_free(tet->cusp_nbhd_position); if (tet->extra != NULL) my_free(tet->extra); my_free(tet); } void clear_shape_history( Tetrahedron *tet) { int i; for (i = 0; i < 2; i++) /* i = complete, filled */ clear_one_shape_history(tet, i); } void clear_one_shape_history( Tetrahedron *tet, FillingStatus which_history) /* filled or complete */ { ShapeInversion *dead_shape_inversion; while (tet->shape_history[which_history] != NULL) { dead_shape_inversion = tet->shape_history[which_history]; tet->shape_history[which_history] = tet->shape_history[which_history]->next; my_free(dead_shape_inversion); } } void copy_triangulation( Triangulation *source, Triangulation **destination_ptr) { Triangulation *destination; Tetrahedron **new_tet; EdgeClass **new_edge; Cusp **new_cusp; Tetrahedron *tet; EdgeClass *edge; Cusp *cusp; int num_edge_classes, min_cusp_index, max_cusp_index, num_potential_cusps, i, j; /* * Allocate space for the new Triangulation. */ *destination_ptr = NEW_STRUCT(Triangulation); /* * Give it a local name. */ destination = *destination_ptr; /* * Copy the global information. * In a moment we'll overwrite the fields involving pointers. */ *destination = *source; /* * Allocate space for the name, and copy it it. */ destination->name = NEW_ARRAY(strlen(source->name) + 1, char); strcpy(destination->name, source->name); /* * Initialize the doubly linked lists. */ destination->tet_list_begin.prev = NULL; destination->tet_list_begin.next = &destination->tet_list_end; destination->tet_list_end.prev = &destination->tet_list_begin; destination->tet_list_end.next = NULL; destination->edge_list_begin.prev = NULL; destination->edge_list_begin.next = &destination->edge_list_end; destination->edge_list_end.prev = &destination->edge_list_begin; destination->edge_list_end.next = NULL; destination->cusp_list_begin.prev = NULL; destination->cusp_list_begin.next = &destination->cusp_list_end; destination->cusp_list_end.prev = &destination->cusp_list_begin; destination->cusp_list_end.next = NULL; /* * Assign consecutive indices to source's Tetrahedra and EdgeClasses. * The Cusps will already be numbered. * * While we're at it, count the EdgeClasses. * If no finite vertices are present, the number of EdgeClasses * will equal the number of Tetrahedra. */ number_the_tetrahedra(source); number_the_edge_classes(source); num_edge_classes = count_the_edge_classes(source); /* * Find the largest and smallest Cusp indices. */ min_cusp_index = source->cusp_list_begin.next->index; max_cusp_index = source->cusp_list_begin.next->index; for ( cusp = source->cusp_list_begin.next; cusp != &source->cusp_list_end; cusp = cusp->next) { if (cusp->index < min_cusp_index) min_cusp_index = cusp->index; if (cusp->index > max_cusp_index) max_cusp_index = cusp->index; } num_potential_cusps = max_cusp_index - min_cusp_index + 1; /* * Allocate the new Tetrahedra, EdgeClasses and Cusps. * For the Cusps we want to allow for the possibility * that there'll be gaps in the indexing scheme. */ new_tet = NEW_ARRAY(source->num_tetrahedra, Tetrahedron *); for (i = 0; i < source->num_tetrahedra; i++) new_tet[i] = NEW_STRUCT(Tetrahedron); new_edge = NEW_ARRAY(num_edge_classes, EdgeClass *); for (i = 0; i < num_edge_classes; i++) new_edge[i] = NEW_STRUCT(EdgeClass); new_cusp = NEW_ARRAY(num_potential_cusps, Cusp *); for (i = 0; i < num_potential_cusps; i++) new_cusp[i] = NULL; for (cusp = source->cusp_list_begin.next; cusp != &source->cusp_list_end; cusp = cusp->next) new_cusp[cusp->index - min_cusp_index] = NEW_STRUCT(Cusp); /* * Copy the fields of each Tetrahedron in source * to the corresponding fields in new_tet[i]. */ for (tet = source->tet_list_begin.next, i = 0; tet != &source->tet_list_end; tet = tet->next, i++) { /* * Copy all fields, * then overwrite the ones involving pointers. */ *new_tet[i] = *tet; for (j = 0; j < 4; j++) { new_tet[i]->neighbor[j] = new_tet[tet->neighbor[j]->index]; new_tet[i]->gluing[j] = tet->gluing[j]; new_tet[i]->cusp[j] = new_cusp[tet->cusp[j]->index - min_cusp_index]; } for (j = 0; j < 6; j++) new_tet[i]->edge_class[j] = new_edge[tet->edge_class[j]->index]; for (j = 0; j < 2; j++) /* j = complete, filled */ if (tet->shape[j] != NULL) { new_tet[i]->shape[j] = NEW_STRUCT(TetShape); *new_tet[i]->shape[j] = *tet->shape[j]; } for (j = 0; j < 2; j++) /* j = complete, filled */ copy_shape_history(tet->shape_history[j], &new_tet[i]->shape_history[j]); if (tet->cusp_nbhd_position != NULL) { new_tet[i]->cusp_nbhd_position = NEW_STRUCT(CuspNbhdPosition); *new_tet[i]->cusp_nbhd_position = *tet->cusp_nbhd_position; } /* * Just to be safe. */ new_tet[i]->cross_section = NULL; new_tet[i]->canonize_info = NULL; new_tet[i]->extra = NULL; INSERT_BEFORE(new_tet[i], &destination->tet_list_end); } /* * Copy the fields of each EdgeClass in source * to the corresponding fields in new_edge[i]. */ for (edge = source->edge_list_begin.next, i = 0; edge != &source->edge_list_end; edge = edge->next, i++) { /* * Copy all fields, * then overwrite the ones involving pointers. */ *new_edge[i] = *edge; new_edge[i]->incident_tet = new_tet[edge->incident_tet->index]; INSERT_BEFORE(new_edge[i], &destination->edge_list_end); } /* * Copy the fields of each Cusp in source * to the corresponding fields in new_cusp[i]. */ for (cusp = source->cusp_list_begin.next; cusp != &source->cusp_list_end; cusp = cusp->next) { /* * Copy all fields, * then overwrite the ones involving pointers. */ *new_cusp[cusp->index - min_cusp_index] = *cusp; INSERT_BEFORE(new_cusp[cusp->index - min_cusp_index], &destination->cusp_list_end); } /* * Free the arrays of pointers. */ my_free(new_tet); my_free(new_edge); my_free(new_cusp); /* * Copy the dilog function pointer. */ destination->dilog = source->dilog; } void copy_shape_history( ShapeInversion *source, ShapeInversion **dest) { while (source != NULL) { *dest = NEW_STRUCT(ShapeInversion); (*dest)->wide_angle = source->wide_angle; source = source->next; dest = &(*dest)->next; } *dest = NULL; } void initialize_triangulation( Triangulation *manifold) { manifold->name = NULL; manifold->num_tetrahedra = 0; manifold->solution_type[complete] = not_attempted; manifold->solution_type[filled] = not_attempted; manifold->orientability = unknown_orientability; manifold->num_cusps = 0; manifold->num_or_cusps = 0; manifold->num_nonor_cusps = 0; manifold->num_generators = 0; manifold->CS_value_is_known = FALSE; manifold->CS_fudge_is_known = FALSE; manifold->CS_value[ultimate] = 0.0; manifold->CS_value[penultimate] = 0.0; manifold->CS_fudge[ultimate] = 0.0; manifold->CS_fudge[penultimate] = 0.0; manifold->dilog = NULL; initialize_tetrahedron(&manifold->tet_list_begin); initialize_tetrahedron(&manifold->tet_list_end); manifold->tet_list_begin.prev = NULL; manifold->tet_list_begin.next = &manifold->tet_list_end; manifold->tet_list_end.prev = &manifold->tet_list_begin; manifold->tet_list_end.next = NULL; initialize_edge_class(&manifold->edge_list_begin); initialize_edge_class(&manifold->edge_list_end); manifold->edge_list_begin.prev = NULL; manifold->edge_list_begin.next = &manifold->edge_list_end; manifold->edge_list_end.prev = &manifold->edge_list_begin; manifold->edge_list_end.next = NULL; initialize_cusp(&manifold->cusp_list_begin); initialize_cusp(&manifold->cusp_list_end); manifold->cusp_list_begin.prev = NULL; manifold->cusp_list_begin.next = &manifold->cusp_list_end; manifold->cusp_list_end.prev = &manifold->cusp_list_begin; manifold->cusp_list_end.next = NULL; } void initialize_tetrahedron( Tetrahedron *tet) { int h, i, j, k; for (i = 0; i < 4; i++) { tet->neighbor[i] = NULL; tet->gluing[i] = 0; tet->cusp[i] = NULL; tet->generator_status[i] = unassigned_generator; tet->generator_index[i] = -1; tet->generator_parity[i] = -1; tet->corner[i] = Zero; tet->tilt[i] = -1.0e17; } for (h = 0; h < 2; h++) for (i = 0; i < 2; i++) for (j = 0; j < 4; j++) for (k = 0; k < 4; k++) tet->curve[h][i][j][k] = 0; for (i = 0; i < 6; i++) { tet->edge_class[i] = NULL; tet->edge_orientation[i] = -1; } for (i = 0; i < 2; i++) { tet->shape[i] = NULL; tet->shape_history[i] = NULL; } tet->generator_path = -2; tet->cross_section = NULL; tet->canonize_info = NULL; tet->cusp_nbhd_position = NULL; tet->extra = NULL; tet->prev = NULL; tet->next = NULL; } void initialize_cusp( Cusp *cusp) { cusp->topology = unknown_topology; cusp->is_complete = TRUE; cusp->m = 0.0; cusp->l = 0.0; cusp->holonomy[ ultimate][M] = Zero; cusp->holonomy[ ultimate][L] = Zero; cusp->holonomy[penultimate][M] = Zero; cusp->holonomy[penultimate][L] = Zero; cusp->target_holonomy = TwoPiI; cusp->complex_cusp_equation = NULL; cusp->real_cusp_equation_re = NULL; cusp->real_cusp_equation_im = NULL; cusp->cusp_shape[initial] = Zero; cusp->cusp_shape[current] = Zero; cusp->shape_precision[initial] = 0; cusp->shape_precision[current] = 0; cusp->index = 255; cusp->displacement = 0.0; cusp->displacement_exp = 1.0; cusp->is_finite = FALSE; cusp->matching_cusp = NULL; cusp->prev = NULL; cusp->next = NULL; } void initialize_edge_class( EdgeClass *edge_class) { edge_class->order = 0; edge_class->incident_tet = NULL; edge_class->incident_edge_index = -1; edge_class->num_incident_generators = -1; edge_class->complex_edge_equation = NULL; edge_class->real_edge_equation_re = NULL; edge_class->real_edge_equation_im = NULL; edge_class->target_angle_sum = TwoPiI; edge_class->prev = NULL; edge_class->next = NULL; } FuncResult check_Euler_characteristic_of_boundary( Triangulation *manifold) { int num_edges; EdgeClass *edge; /* * check_Euler_characteristic_of_boundary() returns * func_OK if the Euler characteristic of the total * boundary is zero, and returns func_failed otherwise. * Note that (so far) all functions which call * check_Euler_characteristic_of_boundary() are testing * whether curves on the (intended) boundary components * have been pinched off. In these cases the Euler * characteristic of the affected boundary component * will increase, but never decrease. So knowing that * the Euler characteristic of the total boundary is * zero implies that the Euler characteristic of each * component is also zero. * * Checking the Euler characteristic of the boundary * is trivially easy -- you just check whether the * number of EdgeClasses in the manifold equals the * number of Tetrahedra. Here's the proof: * * Let v, e and f be the number of vertices, edges, and * faces in the triangulation of the boundary. * Let E, F and T be the number of edges, faces and * tetrahedra in the ideal triangulation of the * manifold. * * v = 2E * e = 3F = 6T * f = 4T * * v - e + f = 2E - 6T + 4T = 2(E - T) * * So the boundary topology will be correct iff E == T. */ /* * Count the number of edge classes. */ num_edges = 0; for (edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) num_edges++; /* * Compare the number of edges to the number of tetrahedra. */ if (num_edges != manifold->num_tetrahedra) return func_failed; else return func_OK; } /* * number_the_tetrahedra() fills in the index field of the Tetrahedra * according to their order in the manifold's doubly-linked list. * Indices range from 0 to (num_tetrahedra - 1). */ void number_the_tetrahedra( Triangulation *manifold) { Tetrahedron *tet; int count; count = 0; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) tet->index = count++; } /* * number_the_edge_classes() fills in the index field of the EdgeClasses * according to their order in the manifold's doubly-linked list. * Indices range from 0 to (number of EdgeClasses) - 1. */ void number_the_edge_classes( Triangulation *manifold) { EdgeClass *edge; int count; count = 0; for (edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) edge->index = count++; } static int count_the_edge_classes( Triangulation *manifold) { EdgeClass *edge; int count; count = 0; for (edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) count++; return count; } /* * compose_permutations() returns the composition of two permutations. * Permutations are composed right-to-left: the composition p1 o p0 * is what you get by first doing p0, then p1. */ Permutation compose_permutations( Permutation p1, Permutation p0) { Permutation result; int i; result = 0; for (i = 4; --i >= 0; ) { result <<= 2; result += EVALUATE(p1, EVALUATE(p0, i)); } return result; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/unix_file_io.c000644 000765 000024 00000053354 12377774107 021632 0ustar00babstaff000000 000000 /* * unix_file_io.c * * This hacked together file allows unix-style programs * to read and save Triangulations. */ #include #include #include #include "unix_file_io.h" #include "kernel_namespace.h" #define READ_OLD_FILE_FORMAT 0 #define FALSE 0 #define TRUE 1 /* * gcc complains about the * * use of `l' length character with `f' type character * * in fprintf() calls. Presumably it considers the 'l' unnecessary * because even floats would undergo default promotion to doubles * in the function call (see section A7.3.2 in Appendix A of K&R 2nd ed.). * Therefore I've changed "%lf" to "%f" in all fprintf() calls. * If this makes trouble on your system, change it back, and please * let me know (weeks@northnet.org). */ /* Modified 2010/09/20 by Marc Culler to avoid quadratic time behavior * caused by the fact that sscanf calls strlen. */ /* Size for our temporary string buffers. */ #define SBSIZE 256 /* Copy up to the specified number of words of the string str into the * specified buffer, which must hold at least SBSIZE chars. Return * the number of chars copied. This assumes that any line in a * triangulation file will have length < SBSIZE. */ #define whitespace(x) (x=='\040'||x=='\f'||x=='\n'||x=='\r'||x=='\t'||x=='\v') static int read_head(char *headbuf, const char *str, int words) { char *ptr = headbuf; int n; for (n=0; n < words; n++) { /* copy whitespace */ while ( whitespace(*str) && ptr-headbuf < SBSIZE-1 ) *ptr++ = *str++; /* copy non-whitespace */ while ( *str != '\0' && !whitespace(*str) && ptr-headbuf < SBSIZE-1) *ptr++ = *str++; if ( *str == '\0' ) break; } /* add trailing null char */ *ptr = '\0'; return (ptr - headbuf); } /* Modified 04/23/09 by Marc Culler to allow reading a triangulation * from a string. */ static TriangulationData *ReadNewFileFormat(const char *buffer); static void WriteNewFileFormat(FILE *fp, TriangulationData *data); static char *StringNewFileFormat(TriangulationData *data); #if READ_OLD_FILE_FORMAT extern FuncResult read_old_manifold(FILE *fp, Triangulation **manifold); #endif /* Modified 2010/7/27 by NMD to allow for Classic Mac OS and Windows line endings, as well Unix ones */ static Boolean is_eol_char(const char *buffer); Boolean is_eol_char(const char *buffer){ return (*buffer == '\n') || (*buffer == '\r'); } /* Modified 04/24/09 by Marc Culler to allow extracting a triangulation from a C string. */ Triangulation *read_triangulation_from_string( const char *file_data) { TriangulationData *theTriangulationData; Triangulation *manifold; if ( strncmp("% Triangulation", file_data, 15) != 0) uFatalError("read_triangulation_from_string", "unix file io"); theTriangulationData = ReadNewFileFormat(file_data); data_to_triangulation(theTriangulationData, &manifold); free(theTriangulationData->name); free(theTriangulationData->cusp_data); free(theTriangulationData->tetrahedron_data); free(theTriangulationData); return manifold; } Triangulation *read_triangulation( const char *file_name) { FILE *fp; Boolean theNewFormat; Triangulation *manifold; /* * If the file_name is nonempty, read the file. * If the file_name is empty, read from stdin. */ if (strlen(file_name) > 0) { fp = fopen(file_name, "r"); if (fp == NULL) return NULL; /* * Take a peek at the first line to see whether this is * the new file format or the old one. */ theNewFormat = (getc(fp) == '%'); rewind(fp); } else { fp = stdin; theNewFormat = TRUE; /* read only the new format from stdin */ } if (theNewFormat == TRUE) { TriangulationData *theTriangulationData; long filesize = 0; char *buffer; if ( fseek(fp, 0, SEEK_END) != 0 || ( filesize = ftell(fp) ) == -1 || fseek(fp, 0, SEEK_SET) != 0 ) uFatalError("read_triangulation", "unix file io"); buffer = (char *)malloc(filesize + 1); if ( buffer == NULL) uFatalError("read_triangulation", "unix file io"); if ( fread(buffer, filesize, 1, fp) != 1 ) uFatalError("read_triangulation", "unix file io"); buffer[filesize] = '\0'; theTriangulationData = ReadNewFileFormat(buffer); free(buffer); data_to_triangulation(theTriangulationData, &manifold); free(theTriangulationData->name); free(theTriangulationData->cusp_data); free(theTriangulationData->tetrahedron_data); free(theTriangulationData); } else { #if READ_OLD_FILE_FORMAT read_old_manifold(fp, &manifold); #else fprintf(stderr, "The manifold is in the old file format.\n"); fprintf(stderr, "I recommend converting it to the new format.\n"); fprintf(stderr, "If absolutely necessary, I can provide code for reading the old format.\n"); fprintf(stderr, "Questions? Contact me at weeks@northnet.org.\n"); uFatalError("read_triangulation", "unix file io"); #endif } if (fp != stdin) fclose(fp); return manifold; } static TriangulationData *ReadNewFileFormat( const char *buffer) { char *ptr; char theScratchString[SBSIZE]; char HeadBuffer[SBSIZE]; int count; TriangulationData *theTriangulationData; int theTotalNumCusps, i, j, k, v, f; size_t size = 0; double temp, temp_m, temp_l, temp_r, temp_i; /* * Read and ignore the header (% Triangulation). */ while (!is_eol_char(buffer)) buffer++; /* * Allocate the TriangulationData. */ theTriangulationData = (TriangulationData *) malloc(sizeof(TriangulationData)); if (theTriangulationData == NULL) uFatalError("ReadNewFileFormat 1", "unix file io"); theTriangulationData->name = NULL; theTriangulationData->cusp_data = NULL; theTriangulationData->tetrahedron_data = NULL; /* * Allocate and read the name of the manifold. * The name will be on the first nonempty line. */ while (is_eol_char(buffer)) buffer++; i = 0; ptr = NULL; while (!is_eol_char(buffer)){ if (i + 2 > (int) size){ size += 100; ptr = (char *) realloc(ptr, size); if (ptr == NULL){ /* We could have saved the old pointer, to free it here. * But why bother? We are toast anyway. */ uFatalError("ReadNewFileFormat 2", "unix file io"); return NULL; } } ptr[i++] = *buffer++; } ptr[i] = 0; theTriangulationData->name = ptr; /* * Read the filled solution type. */ buffer += read_head(HeadBuffer, buffer, 1); sscanf(HeadBuffer, "%s", theScratchString); if (strcmp(theScratchString, "not_attempted") == 0) theTriangulationData->solution_type = not_attempted; else if (strcmp(theScratchString, "geometric_solution") == 0) theTriangulationData->solution_type = geometric_solution; else if (strcmp(theScratchString, "nongeometric_solution") == 0) theTriangulationData->solution_type = nongeometric_solution; else if (strcmp(theScratchString, "flat_solution") == 0) theTriangulationData->solution_type = flat_solution; else if (strcmp(theScratchString, "degenerate_solution") == 0) theTriangulationData->solution_type = degenerate_solution; else if (strcmp(theScratchString, "other_solution") == 0) theTriangulationData->solution_type = other_solution; else if (strcmp(theScratchString, "no_solution") == 0) theTriangulationData->solution_type = no_solution; else uFatalError("ReadNewFileFormat 3", "unix file io"); /* * Read the volume. */ buffer += read_head(HeadBuffer, buffer, 1); sscanf(HeadBuffer, "%lf", &temp); theTriangulationData->volume = temp; /* * Read the orientability. */ buffer += read_head(HeadBuffer, buffer, 1); sscanf(HeadBuffer, "%s", theScratchString); if (strcmp(theScratchString, "oriented_manifold") == 0) theTriangulationData->orientability = oriented_manifold; else if (strcmp(theScratchString, "nonorientable_manifold") == 0) theTriangulationData->orientability = nonorientable_manifold; else if (strcmp(theScratchString, "unknown_orientability") == 0) theTriangulationData->orientability = unknown_orientability; else uFatalError("ReadNewFileFormat 4", "unix file io"); /* * Read the Chern-Simons invariant, if present. */ buffer += read_head(HeadBuffer, buffer, 1); sscanf(HeadBuffer, "%s", theScratchString); if (strcmp(theScratchString, "CS_known") == 0) theTriangulationData->CS_value_is_known = TRUE; else if (strcmp(theScratchString, "CS_unknown") == 0) theTriangulationData->CS_value_is_known = FALSE; else uFatalError("ReadNewFileFormat 5", "unix file io"); if (theTriangulationData->CS_value_is_known == TRUE) { buffer += read_head(HeadBuffer, buffer, 1); sscanf(HeadBuffer, "%lf", &temp); theTriangulationData->CS_value = temp; } else theTriangulationData->CS_value = 0.0; /* * Read the number of cusps, allocate an array for the cusp data, * and read the cusp data. */ buffer += read_head(HeadBuffer, buffer, 2); sscanf(HeadBuffer, "%d%d", &theTriangulationData->num_or_cusps, &theTriangulationData->num_nonor_cusps); theTotalNumCusps = theTriangulationData->num_or_cusps + theTriangulationData->num_nonor_cusps; theTriangulationData->cusp_data = (CuspData *) malloc(theTotalNumCusps * sizeof(CuspData)); if (theTriangulationData->cusp_data == NULL) uFatalError("ReadNewFileFormat 6", "unix file io"); for (i = 0; i < theTotalNumCusps; i++) { buffer += read_head(HeadBuffer, buffer, 3); if (sscanf(HeadBuffer, "%s%lf%lf", theScratchString, &temp_m, &temp_l) != 3) uFatalError("ReadNewFileFormat 7", "unix file io"); theTriangulationData->cusp_data[i].m = temp_m; theTriangulationData->cusp_data[i].l=temp_l; switch (theScratchString[0]) { case 't': case 'T': theTriangulationData->cusp_data[i].topology = torus_cusp; break; case 'k': case 'K': theTriangulationData->cusp_data[i].topology = Klein_cusp; break; default: uFatalError("ReadNewFileFormat 8", "unix file io"); } } /* * Read the number of tetrahedra, allocate an array for the * tetrahedron data, and read the tetrahedron data. */ buffer += read_head(HeadBuffer, buffer, 1); sscanf(HeadBuffer, "%d", &theTriangulationData->num_tetrahedra); theTriangulationData->tetrahedron_data = (TetrahedronData *) malloc(theTriangulationData->num_tetrahedra * sizeof(TetrahedronData)); if (theTriangulationData->tetrahedron_data == NULL) uFatalError("ReadNewFileFormat 9", "unix file io"); for (i = 0; i < theTriangulationData->num_tetrahedra; i++) { /* * Read the neighbor indices. */ for (j = 0; j < 4; j++) { buffer += read_head(HeadBuffer, buffer, 1); sscanf(HeadBuffer, "%d", &theTriangulationData->tetrahedron_data[i].neighbor_index[j]); if (theTriangulationData->tetrahedron_data[i].neighbor_index[j] < 0 || theTriangulationData->tetrahedron_data[i].neighbor_index[j] >= theTriangulationData->num_tetrahedra) uFatalError("ReadNewFileFormat 10", "unix file io"); } /* * Read the gluings. */ /* This assumes that the gluings are groups of 4 digits with no whitespace between, but with whitespace between groups. */ buffer += read_head(HeadBuffer, buffer, 4); ptr = HeadBuffer; for (j = 0; j < 4; j++) for (k = 0; k < 4; k++) { sscanf(ptr, "%1d%n", &theTriangulationData->tetrahedron_data[i].gluing[j][k], &count); ptr += count; if (theTriangulationData->tetrahedron_data[i].gluing[j][k] < 0 || theTriangulationData->tetrahedron_data[i].gluing[j][k] > 3) uFatalError("ReadNewFileFormat 11", "unix file io"); } /* * Read the cusp indices. * * 99/06/04 Allow an index of -1 on "cusps" that are * really finite vertices. */ for (j = 0; j < 4; j++) { buffer += read_head(HeadBuffer, buffer, 1); sscanf(HeadBuffer, "%d", &theTriangulationData->tetrahedron_data[i].cusp_index[j]); if (theTriangulationData->tetrahedron_data[i].cusp_index[j] < -1 || theTriangulationData->tetrahedron_data[i].cusp_index[j] >= theTotalNumCusps) uFatalError("ReadNewFileFormat 12", "unix file io"); } /* * Read the peripheral curves. */ for (j = 0; j < 2; j++) /* meridian, longitude */ for (k = 0; k < 2; k++) /* righthanded, lefthanded */ for (v = 0; v < 4; v++) for (f = 0; f < 4; f++){ buffer += read_head(HeadBuffer, buffer, 1); sscanf(HeadBuffer, "%d", &theTriangulationData->tetrahedron_data[i].curve[j][k][v][f]); } /* * Read the filled shape (which the kernel ignores). */ buffer += read_head(HeadBuffer, buffer, 2); sscanf(HeadBuffer, "%lf%lf", &temp_r, &temp_i); theTriangulationData->tetrahedron_data[i].filled_shape.real = temp_r; theTriangulationData->tetrahedron_data[i].filled_shape.imag = temp_i; } return theTriangulationData; } Boolean write_triangulation( Triangulation *manifold, const char *file_name) { TriangulationData *theTriangulationData; FILE *fp; /* * If the file_name is nonempty, write the file. * If the file_name is empty, write to stdout. */ if (strlen(file_name) > 0) { fp = fopen(file_name, "w"); if (fp == NULL) { printf("couldn't open %s\n", file_name); return FALSE; } } else fp = stdout; triangulation_to_data(manifold, &theTriangulationData); WriteNewFileFormat(fp, theTriangulationData); free_triangulation_data(theTriangulationData); if (fp != stdout) fclose(fp); return TRUE; } static void WriteNewFileFormat( FILE *fp, TriangulationData *data) { int i, j, k, v, f; fprintf(fp, "%% Triangulation\n"); if (data->name != NULL) fprintf(fp, "%s\n", data->name); else fprintf(fp, "untitled"); switch (data->solution_type) { case not_attempted: fprintf(fp, "not_attempted"); break; case geometric_solution: fprintf(fp, "geometric_solution"); break; case nongeometric_solution: fprintf(fp, "nongeometric_solution"); break; case flat_solution: fprintf(fp, "flat_solution"); break; case degenerate_solution: fprintf(fp, "degenerate_solution"); break; case other_solution: fprintf(fp, "other_solution"); break; case no_solution: fprintf(fp, "no_solution"); break; } if (data->solution_type != not_attempted) fprintf(fp, " %.8f\n", (double)data->volume); else fprintf(fp, " %.1f\n", 0.0); switch (data->orientability) { case oriented_manifold: fprintf(fp, "oriented_manifold\n"); break; case nonorientable_manifold: fprintf(fp, "nonorientable_manifold\n"); break; } if (data->CS_value_is_known == TRUE) fprintf(fp, "CS_known %.16f\n", (double)data->CS_value); else fprintf(fp, "CS_unknown\n"); fprintf(fp, "\n%d %d\n", data->num_or_cusps, data->num_nonor_cusps); for (i = 0; i < data->num_or_cusps + data->num_nonor_cusps; i++) fprintf(fp, " %s %16.12f %16.12f\n", (data->cusp_data[i].topology == torus_cusp) ? "torus" : "Klein", (double)data->cusp_data[i].m, (double)data->cusp_data[i].l); fprintf(fp, "\n"); fprintf(fp, "%d\n", data->num_tetrahedra); for (i = 0; i < data->num_tetrahedra; i++) { for (j = 0; j < 4; j++) fprintf(fp, "%4d ", data->tetrahedron_data[i].neighbor_index[j]); fprintf(fp, "\n"); for (j = 0; j < 4; j++) { fprintf(fp, " "); for (k = 0; k < 4; k++) fprintf(fp, "%d", data->tetrahedron_data[i].gluing[j][k]); } fprintf(fp, "\n"); for (j = 0; j < 4; j++) fprintf(fp, "%4d ", data->tetrahedron_data[i].cusp_index[j]); fprintf(fp, "\n"); for (j = 0; j < 2; j++) /* meridian, longitude */ for (k = 0; k < 2; k++) /* righthanded, lefthanded */ { for (v = 0; v < 4; v++) for (f = 0; f < 4; f++) fprintf(fp, " %2d", data->tetrahedron_data[i].curve[j][k][v][f]); fprintf(fp, "\n"); } if (data->solution_type != not_attempted) fprintf(fp, "%16.12f %16.12f\n\n", (double)data->tetrahedron_data[i].filled_shape.real, (double)data->tetrahedron_data[i].filled_shape.imag); else fprintf(fp, "%3.1f %3.1f\n\n", 0.0, 0.0); } } /* Added by Marc Culler 2010-12-17 to allow writing a triangulation * to a string. Memory is malloc'ed for the string. Caller must free. */ char *string_triangulation( Triangulation *manifold) { TriangulationData *theTriangulationData; char *result; triangulation_to_data(manifold, &theTriangulationData); result = StringNewFileFormat(theTriangulationData); free_triangulation_data(theTriangulationData); return result; } static char *StringNewFileFormat( TriangulationData *data) { int i, j, k, v, f, size; char *buffer; char *p; size = 100*(10 + data->num_or_cusps + data->num_nonor_cusps + 8*data->num_tetrahedra); buffer = (char *)malloc(size); if ( buffer == NULL) uFatalError("StringNewFileFormat", "unix file io"); p = buffer; p += sprintf(p, "%% Triangulation\n"); if (data->name != NULL) p += sprintf(p, "%s\n", data->name); else p += sprintf(p, "untitled\n"); switch (data->solution_type) { case not_attempted: p += sprintf(p, "not_attempted"); break; case geometric_solution: p += sprintf(p, "geometric_solution"); break; case nongeometric_solution: p += sprintf(p, "nongeometric_solution"); break; case flat_solution: p += sprintf(p, "flat_solution"); break; case degenerate_solution: p += sprintf(p, "degenerate_solution"); break; case other_solution: p += sprintf(p, "other_solution"); break; case no_solution: p += sprintf(p, "no_solution"); break; } if (data->solution_type != not_attempted) p += sprintf(p, " %.8f\n", (double)data->volume); else p += sprintf(p, " %.1f\n", 0.0); switch (data->orientability) { case oriented_manifold: p += sprintf(p, "oriented_manifold\n"); break; case nonorientable_manifold: p += sprintf(p, "nonorientable_manifold\n"); break; } if (data->CS_value_is_known == TRUE) p += sprintf(p, "CS_known %.16f\n", (double)data->CS_value); else p += sprintf(p, "CS_unknown\n"); p += sprintf(p, "\n%d %d\n", data->num_or_cusps, data->num_nonor_cusps); for (i = 0; i < data->num_or_cusps + data->num_nonor_cusps; i++) p += sprintf(p, " %s %16.12f %16.12f\n", (data->cusp_data[i].topology == torus_cusp) ? "torus" : "Klein", (double)data->cusp_data[i].m, (double)data->cusp_data[i].l); p += sprintf(p, "\n"); p += sprintf(p, "%d\n", data->num_tetrahedra); for (i = 0; i < data->num_tetrahedra; i++) { for (j = 0; j < 4; j++) p += sprintf(p, "%4d ", data->tetrahedron_data[i].neighbor_index[j]); p += sprintf(p, "\n"); for (j = 0; j < 4; j++) { p += sprintf(p, " "); for (k = 0; k < 4; k++) p += sprintf(p, "%d", data->tetrahedron_data[i].gluing[j][k]); } p += sprintf(p, "\n"); for (j = 0; j < 4; j++) p += sprintf(p, "%4d ", data->tetrahedron_data[i].cusp_index[j]); p += sprintf(p, "\n"); for (j = 0; j < 2; j++) /* meridian, longitude */ for (k = 0; k < 2; k++) /* righthanded, lefthanded */ { for (v = 0; v < 4; v++) for (f = 0; f < 4; f++) p += sprintf(p, " %2d", data->tetrahedron_data[i].curve[j][k][v][f]); p += sprintf(p, "\n"); } if (data->solution_type != not_attempted) p += sprintf(p, "%16.12f %16.12f\n\n", (double)data->tetrahedron_data[i].filled_shape.real, (double)data->tetrahedron_data[i].filled_shape.imag); else p += sprintf(p, "%3.1f %3.1f\n\n", 0.0, 0.0); } return buffer; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/unix_file_io.h000644 000765 000024 00000001001 12377774107 021615 0ustar00babstaff000000 000000 /* * unix_file_io.h * * These three functions allow unix-style programs * to read and save Triangulations. */ #include "SnapPea.h" #include "kernel_namespace.h" extern Triangulation *read_triangulation(const char *file_name); extern Triangulation *read_triangulation_from_string(const char *file_data); extern Boolean write_triangulation(Triangulation *manifold, const char *file_name); extern char *string_triangulation(Triangulation *manifold); #include "end_namespace.h" regina-4.96/engine/snappea/kernel/update_shapes.c000644 000765 000024 00000022760 12377774107 022003 0ustar00babstaff000000 000000 /* * update_shapes.c * * This file provides the function * * void update_shapes(Triangulation *manifold, Complex *delta); * * which is called by do_Dehn_filling() in hyperbolic_structure.c. * update_shapes() updates the shapes of the tetrahedra in *manifold * by the amounts specified in the array delta. If necessary, delta * is first scaled so that no delta[i].real or delta[i].imag exceeds * the limit specified by the constant allowable_change (see below). * * The entries in delta are interpreted relative to the coordinate system * given by the coordinate_system field of each Tetrahedron, and the * indexing of delta is assumed to correspond to the index field of each * tetrahedron. */ /* * The allowable_change constant specifies the maximum amount * the log of the complex edge parameter may change. * * allowable_change.real is the maximum allowable change in * the log of its modulus, and * * allowable_change.imag is the maximum allowable change in * its argument. * * If necessary, all the delta[i] are scaled by a constant (between * zero and one) so that no delta[i] exceeds the allowable change. * * * Setting allowable_change. * * A small value for allowable_change makes Newton's method slow, * but reliable. A larger value speeds it up, but increases the risk * of winding up on some funny branch of the solution space. * The values of allowable_change.real and allowable_change.imag * must not exceed 0.5, for the following reasons. * * (1) Because choose_coordinate_system() is called at the start of * each iteration of Newton's method, we know that the current * value of the edge parameter (relative to the chosen coordinate * system) satisfies |z-1| >= 1 and Re(z) <= 0.5 (see the comment * preceding choose_coordinate_system() in hyperbolic_structure.c). * Therefore if allowable_change.imag is less than pi/6 = 0.52..., * the parameter z cannot go more than half way to the singularity * at 1. If allowable_change.real is less than log(2) = 0.69..., * then z cannot go more than half way to the singularity at 0, nor * can it go "more than half way to infinity", in the sense that * its modulus cannot increase by more than a factor of two. * * (2) The code which maintains the shape_history assumes that when a * Tetrahedron's shape changes, the edge parameter given by * coordinate_system is the one passing through pi (mod 2 pi), and * the other two edge parameters are passing through 0 (mod 2 pi). * This assumption relies on the fact that allowable_change.imag * is less than pi/6 = 0.52... . */ #include "kernel.h" #include "kernel_namespace.h" /* * The entries in allowable_change must not exceed 0.5. * See explanation above. */ static const Complex allowable_change = {0.5, 0.5}; static void scale_delta(Triangulation *manifold, Complex *delta); static void recompute_shapes(Triangulation *manifold, Complex *delta); void update_shapes( Triangulation *manifold, Complex *delta) { scale_delta(manifold, delta); recompute_shapes(manifold, delta); } static void scale_delta( Triangulation *manifold, Complex *delta) { int i; Complex max; Real scaled_max, factor; /* * Find the maximum values of delta[i].real and delta[i].imag. */ max = Zero; for (i = 0; i < manifold->num_tetrahedra; i++) { if ( fabs(delta[i].real) > max.real ) max.real = fabs(delta[i].real); if ( fabs(delta[i].imag) > max.imag ) max.imag = fabs(delta[i].imag); } /* * Scale the solution if necessary. */ scaled_max = MAX( max.real/allowable_change.real, max.imag/allowable_change.imag ); if (scaled_max > 1.0) { factor = 1.0 / scaled_max; for (i = 0; i < manifold->num_tetrahedra; i++) delta[i] = complex_real_mult(factor, delta[i]); } } static void recompute_shapes( Triangulation *manifold, Complex *delta) { Tetrahedron *tet; int i, c[3]; Complex log_z, z[3], old_z, new_z; ShapeInversion *dead_shape_inversion, *new_shape_inversion; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) { /* * The array c[] is used to index the coordinate systems. * For example, if tet->coordinate_system is 1, then * c[0] = 1 (the current coordinate system), c[1] = 2 (the next * one), and c[2] = 0 (the one after that, cyclically speaking). */ for (i = 0; i < 3; i++) c[i] = (tet->coordinate_system + i) % 3; /* * Find the new value of log(z) in the primary coordinate system. */ log_z = complex_plus( tet->shape[filled]->cwl[ultimate][c[0]].log, /* old log_z */ delta[tet->index] /* change in log_z */ ); /* * Compute the new edge parameters in rectangular form. * Use z1 = 1/(1 - z0), etc. */ z[c[0]] = complex_exp(log_z); z[c[1]] = complex_div( One, complex_minus(One, z[c[0]]) ); z[c[2]] = complex_div( One, complex_minus(One, z[c[1]]) ); /* * Note the old z[0] and the new z[0]. * * If the Tetrahedron has experienced a ShapeInversion, update * its shape_history. * * Note that this approach is completely robust with respect * to roundoff errors. A Tetrahedron is considered positively * oriented if its shape has z.imag >= 0.0, and negatively * oriented if its shape has z.imag < 0.0. (It doesn't matter * whether z.imag == 0.0 is considered positively or negatively * oriented, just so we make a convention and use it * consistently.) Also, whether a Tetrahedron is perceived * as positively or negatively oriented is independent of its * coordinate_system: the above computation of z[c[0]], z[c[1]], * and z[c[2]] insures that the imaginary parts of all three will * have the same sign (-, 0, +), regardless of roundoff errors. */ old_z = tet->shape[filled]->cwl[ultimate][0].rect; new_z = z[0]; if ((old_z.imag >= 0.0) != (new_z.imag >= 0.0)) { /* * The Tetrahedron has undergone a ShapeInversion. * Because old_z is in the region |z-1| >= 1 and Re(z) <= 0.5 * (see the comment preceding choose_coordinate_system() in * hyperbolic_structure.c) and allowable_change.imag <= 0.5 < pi/6, * it follows that the edge parameter coordinate_system * passed through pi (mod 2 pi), and the other two edge * parameters passed through 0 (mod 2 pi). That is, the * ShapeInversion we are adding to the stack will have * wide_angle = coordinate_system. * * If the last item on the shape_history stack also has its * wide_angle field equal to the present coordinate_system, * then we remove it, because it cancels with the present * ShapeInversion. Otherwise we add the new ShapeInversion * to the stack. */ /* * If there's a nonempty shape_history stack and the last * ShapeInversion has wide_angle == coordinate_system, then * remove it. It cancels with the ShapeInversion we were * about to put on the stack. */ if (tet->shape_history[filled] != NULL && tet->shape_history[filled]->wide_angle == tet->coordinate_system) { dead_shape_inversion = tet->shape_history[filled]; tet->shape_history[filled] = tet->shape_history[filled]->next; my_free(dead_shape_inversion); } /* * Otherwise add the new ShapeInversion to the stack. */ else { new_shape_inversion = NEW_STRUCT(ShapeInversion); new_shape_inversion->wide_angle = tet->coordinate_system; new_shape_inversion->next = tet->shape_history[filled]; tet->shape_history[filled] = new_shape_inversion; } } /* * For each of the three complex edge parameters . . . */ for (i = 0; i < 3; i++) { /* * Copy the ultimate shape to the penultimate. */ tet->shape[filled]->cwl[penultimate][i] = tet->shape[filled]->cwl[ultimate][i]; /* * Copy in the new ultimate shape in rectangular form. */ tet->shape[filled]->cwl[ultimate][i].rect = z[i]; /* * Compute the log, using the argument of the previous log * to choose the branch (for analytic continuation). */ tet->shape[filled]->cwl[ultimate][i].log = complex_log( tet->shape[filled]->cwl[ultimate][i].rect, tet->shape[filled]->cwl[penultimate][i].log.imag ); } } } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/volume.c000644 000765 000024 00000020733 12377774107 020463 0ustar00babstaff000000 000000 /* * volume.c * * This file contains the function * * double volume(Triangulation *manifold, int *precision); * * which the kernel provides for the UI. It computes and returns * the volume of the manifold. If the pointer "precision" is not NULL, * volume() estimates the number of decimal places of accuracy, and * places the result in the variable *precision. The error estimate is * the difference in the computed volumes at the last and next-to-the-last * iterations of Newton's method (cf. hyperbolic_structures.c). * * 94/11/30 JRW This file now contains the function * * double birectangular_tetrahedron_volume( O31Vector a, * O31Vector b, * O31Vector c, * O31Vector d); * * as well, for use within the kernel. */ #include "kernel.h" #include "kernel_namespace.h" static Real Lobachevsky(Real theta); Real volume( Triangulation *manifold, int *precision) { int i, j; Real vol[2]; /* vol[ultimate/penultimate] */ Tetrahedron *tet; for (i = 0; i < 2; i++) /* i = ultimate, penultimate */ vol[i] = 0.0; for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next) if (tet->shape[filled] != NULL) for (i = 0; i < 2; i++) /* i = ultimate, penultimate */ for (j = 0; j < 3; j++) vol[i] += Lobachevsky(tet->shape[filled]->cwl[i][j].log.imag); if (precision != NULL) *precision = decimal_places_of_accuracy(vol[ultimate], vol[penultimate]); return vol[ultimate]; } /* * The Lobachevsky() function is based on the formula in * Milnor's article "Hyperbolic geometry: The first 150 years", * Bulletin of the American Mathematical Society, volume 6, number 1, * January 1982, pp. 9-24. The actual formula appears about 2/3 of * the way down page 18. */ static Real Lobachevsky(Real theta) { Real term, sum, product, theta_over_pi_squared; const Real *lobcoefptr; const static Real lobcoef[30] = { 5.4831135561607547882413838888201e-1, 1.0823232337111381915160036965412e-1, 4.8444907713545197129262758561472e-2, 2.7891037672165120538296812180796e-2, 1.8199901365960328824311744707278e-2, 1.2823667776324462157674846128817e-2, 9.5243928393815114745643670962394e-3, 7.3530535460250636167039159668208e-3, 5.8479755397266959054962366178048e-3, 4.7619093045811136799814912001842e-3, 3.9525701124525799515137944808229e-3, 3.3333335320272968375315987081340e-3, 2.8490028914574211634331659107080e-3, 2.4630541963678177950454607261557e-3, 2.1505376364114568439132649094016e-3, 1.8939393943803620897114593734851e-3, 1.6806722690053911275277764855335e-3, 1.5015015015233512340706336099638e-3, 1.3495276653220485553945730785293e-3, 1.2195121951230603594927151084491e-3, 1.1074197120711266596728487987281e-3, 1.0101010101010675186059356321779e-3, 9.2506938020352840967144128733280e-4, 8.5034013605442478972252664720549e-4, 7.8431372549019677504189889653457e-4, 7.2568940493468811469129541350086e-4, 6.7340067340067343805464730535677e-4, 6.2656641604010025932192218654462e-4, 5.8445353594389246257711686275038e-4, 5.4644808743169398954500641421420e-4}; /* * As long as DBL_EPSILON > 5e-22 there will be enough lobcoefs * for the series. If DBL_EPSILON is smaller than this you'll * need to add more coefficients to the list. */ #if (DBL_DIG > 19) You need to check DBL_EPSILON. If it is less than 5e-22 you will need to provide more lobcoefs. #endif /* * Milnor (Lemma 1, p. 17) shows that the Lobachevsky function is * periodic with period pi. Put theta in the range [-pi/2, +pi/2]. */ while (theta > PI_OVER_2) theta -= PI; while (theta < -PI_OVER_2) theta += PI; /* * Milnor (Lemma 1, p. 17) also shows that the Lobachevsky function * is an odd function, so we can further restrict theta to the * range [0, pi/2]. */ if (theta < 0.0) return -Lobachevsky(-theta); /* * Handle theta == 0.0 specially, to avoid encountering * log(0.0) later on. */ if (theta == 0.0) return 0.0; theta_over_pi_squared = (theta/PI)*(theta/PI); sum = 0.0; product = 1.0; lobcoefptr = lobcoef; do { product *= theta_over_pi_squared; term = *lobcoefptr++ * product; sum += term; } while (term > DBL_EPSILON); return theta*(1.0 - log(2.0*theta) + sum); } Real birectangular_tetrahedron_volume( O31Vector a, O31Vector b, O31Vector c, O31Vector d) { /* * Compute the volume of the birectangular tetrahedron with vertices * a, b, c and d, using the method found in section 4.3 of * * E. B. Vinberg, Ob'emy neevklidovykh mnogogrannikov, * Uspekhi Matematicheskix Nauk, May(?) 1993, 17-46. * * Our a, b, c and d correspond to Vinberg's A, B, C and D, as shown * in his Figure 9. We need to compute the dual basis {aa, bb, cc, dd} * defined by = 1, = = = 0, etc. * Let m be the matrix whose rows are the vectors {a, b, c, d}, but * with the entries in the first column negated to account for the * indefinite inner product, and let mm be the matrix whose columns * are the vectors {aa, bb, cc, dd}. Then (m)(mm) = identity, by the * definition of the dual basis. */ GL4RMatrix m, mm; O31Vector aa, bb, cc, dd; Real alpha, beta, gamma, delta, big_delta, tetrahedron_volume; int i; /* * Set up the matrix m. */ for (i = 0; i < 4; i++) { m[0][i] = a[i]; m[1][i] = b[i]; m[2][i] = c[i]; m[3][i] = d[i]; } for (i = 0; i < 4; i++) m[i][0] = - m[i][0]; /* * The matrix mm will be the inverse of m, as explained above. * When m is singular, the birectangular tetrahedron's volume is zero. */ if (gl4R_invert(m, mm) != func_OK) return 0.0; /* * Read the dual basis {aa, bb, cc, dd} from mm. */ for (i = 0; i < 4; i++) { aa[i] = mm[i][0]; bb[i] = mm[i][1]; cc[i] = mm[i][2]; dd[i] = mm[i][3]; } /* * Any pair of dual vectors lies in a positive definite 2-plane * in E^(3,1). Normalize them to have length one, so we can use * their dot products to compute the dihedral angles. */ o31_constant_times_vector( 1.0 / safe_sqrt ( o31_inner_product(aa,aa) ), aa, aa); o31_constant_times_vector( 1.0 / safe_sqrt ( o31_inner_product(bb,bb) ), bb, bb); o31_constant_times_vector( 1.0 / safe_sqrt ( o31_inner_product(cc,cc) ), cc, cc); o31_constant_times_vector( 1.0 / safe_sqrt ( o31_inner_product(dd,dd) ), dd, dd); /* * Compute the angles alpha, beta and gamma, as shown in * Vinberg's Figure 9. */ alpha = PI - safe_acos(o31_inner_product(aa, bb)); beta = PI - safe_acos(o31_inner_product(bb, cc)); gamma = PI - safe_acos(o31_inner_product(cc, dd)); /* * Compute big_delta and delta, as in * Vinberg's Sections 4.2 and 4.3. */ big_delta = sin(alpha) * sin(alpha) * sin(gamma) * sin(gamma) - cos(beta) * cos(beta); if (big_delta >= 0.0) uFatalError("birectangular_tetrahedron_volume", "volume"); delta = atan( safe_sqrt( - big_delta) / (cos(alpha) * cos(gamma)) ); tetrahedron_volume = 0.25 * ( Lobachevsky(alpha + delta) - Lobachevsky(alpha - delta) + Lobachevsky(gamma + delta) - Lobachevsky(gamma - delta) - Lobachevsky(PI_OVER_2 - beta + delta) + Lobachevsky(PI_OVER_2 - beta - delta) + 2.0 * Lobachevsky(PI_OVER_2 - delta) ); return tetrahedron_volume; } #include "end_namespace.h" regina-4.96/engine/snappea/kernel/winged_edge.h000644 000765 000024 00000056635 12377774107 021434 0ustar00babstaff000000 000000 /* * winged_edge.h * * This file defines the usual "winged edge" data structure for * representing a convex polyhedron, along with some extra * fields describing the polyhedron's position in the projective * model of hyperbolic 3-space. (The "projective model" is * the Minkowski space model projected onto the hyperplane * x[0] == 1.) * * This file is intended solely for #inclusion in SnapPea.h. * It needs some of the typedefs which occur there. */ #ifndef _winged_edge_ #define _winged_edge_ #define INFINITE_RADIUS 1e20 #define INFINITE_DISTANCE 1e20 #define INFINITE_LENGTH 1e20 #include "kernel_namespace.h" /* * The values of the following two enums are used to index the * static arrays in make_cube() in Dirichlet_construction.c, * so their values shouldn't be changed. (They are also toggled in * Dirichlet_extras.c Dirichlet_conversion.c with the "not" operator '!'.) */ typedef int WEEdgeEnd; enum { tail = 0, tip = 1 }; typedef int WEEdgeSide; enum { left = 0, right = 1 }; /* * The WEEdge structure keeps pointers to Tetrahedra for local use * in Dirichlet_conversion.c. The internal structure of a Tetrahedron * is private to the kernel, so we must include an "opaque typedef" here. * (Indeed even the existence of the Tetrahedron structure is private to * the kernel, so we are "cheating" a bit even by including the typedef.) */ typedef struct Tetrahedron TetrahedronSneak; /* * Forward declarations. */ typedef struct WEVertex WEVertex; typedef struct WEEdge WEEdge; typedef struct WEFace WEFace; typedef struct WEVertexClass WEVertexClass; typedef struct WEEdgeClass WEEdgeClass; typedef struct WEFaceClass WEFaceClass; typedef struct WEPolyhedron WEPolyhedron; struct WEVertex { /* * The vector x gives the position of the WEVertex in the * projective model of hyperbolic 3-space. The projective * model is viewed as a subset of the Minkowski space model, * so x is a 4-element vector with x[0] == 1.0. */ O31Vector x; /* * The vector xx[] is an extra copy of x[] for local use in * the user interface. Even as the polyhedron spins, the UI * should not modify x[], but should write the coordinates * of the rotated vertices into xx[] instead. There are two * reasons for this: * * (1) This scheme avoids cumulative roundoff error in the * coordinates, which could in principle deform the * polyhedron. One can argue that on a 680x0 Mac, which * has 8-byte mantissas, a polyhedron could spin for a * million years before enough error would accumulate * to make a 1-pixel difference on the screen. However, * on an Iris, which uses floats instead of doubles, the * roundoff error is a real issue. In any case, good * programming style dictates that a routine for displaying * a polyhedron should not alter the polyhedron it's * displaying. * * (2) If the user changes the Dehn filling coefficients * slightly, say from (7,1) to (8,1), the change in the * polyhedron will be small, and we'd like the new polyhedron * to appear in roughly the same position as the old one, * so the continuity is visible. For this to occur, x[] * must always contain the polyhedron's initial position, * not its rotated position. */ O31Vector xx; /* * The distance from the vertex to the origin. If the vertex is ideal, * dist is set to INFINITE_DISTANCE. Even though just the distance is * given here, the UI may want to display cosh(dist) as well. */ Real dist; /* * Is this an ideal vertex? */ Boolean ideal; /* * The solid angle at this vertex of the Dirichlet domain. */ Real solid_angle; /* * The Dirichlet domain's face pairings group the vertices * into vertex classes. */ WEVertexClass *v_class; /* * The visible field is used while displaying the WEPolyhedron to * keep track of whether the vertex is visible to the user. */ Boolean visible; /* * The distance_to_plane field is used locally within * Dirichlet_construction.c to record the inner product * of the WEVertex's location x[] with an arbitrary but * fixed normal vector to the hyperplane currently under * consideration. Thus, distance_to_plane is proportional * to the Euclidean distance in the projective model from * the point (x[1], x[2], x[3]) to the intersection of the * hyperplane with the projective model (at x[0] == 1.0). * * The which_side_of_plane field is +1, 0 or -1 according * to whether, after accounting for possible roundoff error, * distance_to_plane is positive, zero or negative, respectively. */ Real distance_to_plane; int which_side_of_plane; /* * The zero_order field is used locally in check_topology_of_cut() * to verify that precisely zero or two 0-edges are incident to * each 0-vertex. */ int zero_order; /* * The WEVertices are kept on a doubly-linked list. */ WEVertex *prev, *next; }; struct WEEdge { /* * v[tail] and v[tip] are the vertices incident to the * tail and tip, respectively, of the directed WEEdge. */ WEVertex *v[2]; /* * e[tail][left] is the WEEdge incident to both v[tail] and f[left]. * e[tail][right] is the WEEdge incident to both v[tail] and f[right]. * e[tip ][left] is the WEEdge incident to both v[tip ] and f[left]. * e[tip ][right] is the WEEdge incident to both v[tip ] and f[right]. */ WEEdge *e[2][2]; /* * f[left] and f[right] are the faces incident to the * left and right sides, respectively, of the directed WEEdge. */ WEFace *f[2]; /* * The dihedral angle between edge->f[left] and edge->f[right]. */ Real dihedral_angle; /* * dist_line_to_origin is the distance to the origin from the line * containing the edge. * * dist_edge_to_origin is the distance to the origin from the edge * itself. Usually this will be the same as dist_line_to_origin, * but occasionally the minimum distance from the line to the origin * will be realized at a point not on the edge itself. In the latter * case the minimum distance from the origin to the edge itself will * be realized at an endpoint. * * Note: The UI may want to display the squared hyperbolic cosines * of the above distances, as well as the distances themselves. * * closest_point_on_line and closest_point_on_edge record the points * at which the above minima are realized. (At present the Mac UI * ignores these, but eventually we may want to display them to the * user upon request.) */ Real dist_line_to_origin, dist_edge_to_origin; O31Vector closest_point_on_line, closest_point_on_edge; /* * How long is this edge? * If it's infinite, the length is set to INFINITE_LENGTH. */ Real length; /* * The Dirichlet domain's face pairings group the edges * into edge classes. */ WEEdgeClass *e_class; /* * The visible field is used while displaying the WEPolyhedron to * keep track of whether the edge is visible to the user. */ Boolean visible; /* * The Dirichlet domain's face identifications determine which sets * of edges are identified to single edges in the manifold itself. * For each edge on the Dirichlet domain, * * edge->neighbor[left] tells the WEEdge to which the given edge * is mapped by edge->f[left]->group_element, * * edge->preserves_sides[left] tell whether the left side of the * given edge maps to the left side of the image, * * edge->preserves_direction[left] tells whether the mapping * preserves the direction of the edge, and * * edge->preserves_orientation[left] tells whether the mapping * preserves orientation, * * and similarly for edge->neighbor[right], etc. * * The preserves_sides, preserves_direction and preserves_orientation * fields are intentionally redundant. Any two determine the third. * * If the singular set is empty or consists of disjoint circles (as will * always be the case for Dehn fillings on cusped manifolds), then the * function Dirichlet_bells_and_whistles() will redirect WEEdges as * necessary so that the preserves_direction[] fields are all TRUE. * Even for orbifolds with more complicated singular sets, it will * give consistent directions to the edges whenever possible. */ WEEdge *neighbor[2]; Boolean preserves_sides[2], preserves_direction[2], preserves_orientation[2]; /* * The tet[][] fields are used locally in Dirichlet_conversion.c * to construct a Triangulation for the manifold represented by * the Dirichlet domain. Otherwise they may be ignored. * The four Tetrahedra incident to this WEEdge are tet[tail][left], * tet[tail][right], tet[tip][left], and tet[tip][right]. */ TetrahedronSneak *tet[2][2]; /* * The WEEdges are kept on a doubly-linked list. */ WEEdge *prev, *next; }; struct WEFace { /* * some_edge is an arbitrary WEEdge incident to the given WEFace. */ WEEdge *some_edge; /* * mate is the WEFace which is identified to this face under * the action of the covering transformation group. */ WEFace *mate; /* * group_element is the O(3,1) matrix which takes this face's mate * to this face. In other words, this face lies in the plane which * passes orthogonally through the midpoint of the segment connecting * the origin to its (the origin's) image under the group_element. */ O31Matrix *group_element; /* * The distance from the face plane to the origin. The point of * closest approach may or may not lie on the face itself. */ Real dist; O31Vector closest_point; /* * The to_be_removed field is used locally in install_new_face() in * Dirichlet_construction.c to record which WEFaces are to be removed. */ Boolean to_be_removed; /* * The clean field is used locally in check_faces() in * Dirichlet_construction.c to record which WEFaces are known to be * subsets of their mates under the action of the group_element. */ Boolean clean; /* * The copied field is used locally in rewrite_gen_list() and * (independently) in poly_to_current_list() in Dirichlet_construction.c * to record which WEFaces have had their group_elements copied to the * MatrixPairList. */ Boolean copied; /* * The matched field show that the WEEdges incident to this face have * been matched with their neighbors incident to face->mate. */ Boolean matched; /* * The visible field is used while displaying the WEPolyhedron to * keep track of whether the face is visible to the user. */ Boolean visible; /* * How many sides does this face have? */ int num_sides; /* * The face and its mate are assigned to the same WEFaceClass. * In the case of an orbifold, a face may be its own mate, in which * case the WEFaceClass will have only one element. */ WEFaceClass *f_class; /* * The WEFaces are kept on a doubly-linked list. */ WEFace *prev, *next; }; /* * The Dirichlet domain's face pairings identify the WEVertices, WEEdges * and WEFaces into WEVertexClasses, WEEdgeClasses and WEFaceClasses. * Each equivalence class is assigned an index. (The indices are * assigned consecutively, beginning at zero.) The index is used * to define a "hue", which is the suggested hue for that cell. * The function index_to_hue() in index_to_hue.c assigns hues in such * a way that the low-numbered cells' hues are all easily distinguishable * from one another. This is especially important for the WEFaceClasses. * If there are a large number of faces we can't possibly hope that all * the hues will be easily distinguishable, but we do want the hues of * the largest faces (which are closest to the origin and have the lowest * indices) to be easily distinguishable. */ struct WEVertexClass { /* * At present the WEVertexClasses are listed in arbitrary order, * but if necessary they could easily be sorted to provide * some control over their hues, as is done for WEFaceClasses. */ int index; Real hue; int num_elements; /* * The total solid angle surrounding this vertex * (4pi for a manifold, 4pi/n for an orbifold). */ Real solid_angle; /* * The "n" in the preceding 4pi/n is recorded as the singularity_order. * (For ideal vertices, n is set to zero.) */ int singularity_order; /* * Is this an ideal vertex class? */ Boolean ideal; /* * All the vertices in the vertex class should be the same distance from * the origin. Dirichlet_extras.c checks that the distances are indeed * approximately equal, and records their average here. */ Real dist; /* * min_dist and max_dist are used locally in vertex_distances() * in Dirichlet_extras.c to check that the dist values of the * constituent vertices are consistent. */ Real min_dist, max_dist; /* * belongs_to_region and is_3_ball are used locally in * compute_spine_radius() in Dirichlet_extras.c. * belongs_to_region keeps track of how various regions * have been united. is_3_ball records which such unified * regions are topologically 3-balls. */ WEVertexClass *belongs_to_region; Boolean is_3_ball; /* * The WEVertexClasses are kept on a doubly-linked list. */ WEVertexClass *prev, *next; }; struct WEEdgeClass { /* * At present the WEEdgeClasses are listed in arbitrary order, * but if necessary they could easily be sorted to provide * some control over their hues, as is done for WEFaceClasses. */ int index; Real hue; int num_elements; /* * The total dihedral angle surrounding this edge * (2pi for a manifold, 2pi/n for an orbifold). */ Real dihedral_angle; /* * The "n" in the preceding 2pi/n is recorded as the singularity_order. */ int singularity_order; /* * All the edges in the edge class should be the same distance from * the origin. Dirichlet_extras.c checks that the distances are indeed * approximately equal, and records their average here. */ Real dist_line_to_origin, dist_edge_to_origin; /* * How long is the identified edge? * If it's infinite, the length is set to INFINITE_LENGTH. */ Real length; /* * Performing the face identifications on the Dirichlet domain gives * a manifold or orbifold. The link of the midpoint of an edge will * be a 2-orbifold. */ Orbifold2 link; /* * min_line_dist and max_line_dist are used locally in edge_distances() * in Dirichlet_extras.c to check that the dist_line_to_origin values * of the constituent edges are consistent. */ Real min_line_dist, max_line_dist; /* * min_length and max_length are used locally in edge_lengths() * in Dirichlet_extras.c to check that the length values * of the constituent edges are consistent. */ Real min_length, max_length; /* * removed is used locally in compute_spine_radius() in Dirichlet_extras.c * to keep track of which 2-cells in the dual spine have been removed. */ Boolean removed; /* * The WEEdgeClasses are kept on a doubly-linked list. */ WEEdgeClass *prev, *next; }; struct WEFaceClass { /* * Indices are assigned to face classes in order of increasing * distance from the origin. The closest face class gets index 0, * the next closest gets index 1, etc. (The distance is actually the * distance from the origin to the plane containing the face, whether * or not the face happens to include the point where the plane is * closest to the origin.) * * Lemma. A face and its mate are the same distance from the origin. * * Proof. The face plane is midway between the origin and the * origin's image under the group_element. d(g^-1(origin), origin) * = d(origin, g(origin)). Q.E.D. * * The function index_to_hue() in index_to_hue.c insures that * the largest faces have easily distinguishable colors. For example, * a (37,1) Dehn surgery on the figure eight knot yields a Dirichlet * domain with a few large faces and many tiny ones. We wouldn't want * to color the large faces with, say, twelve different shades of blue. * The index-to-hue conversion scheme spreads their hues evenly through * the spectrum. */ int index; Real hue; /* * Typically a WEFaceClass will have two elements, but if a face is * glued to itself (in an orbifold), then the WEFaceClass will have * only one element. */ int num_elements; /* * The distance from the face plane to the origin. The point of * closest approach may or may not lie on the face itself. */ Real dist; /* * Is the gluing orientation_reversing or orientation_preserving? */ MatrixParity parity; /* * The WEFaceClasses are kept on a doubly-linked list. */ WEFaceClass *prev, *next; }; struct WEPolyhedron { int num_vertices, num_edges, num_faces; int num_finite_vertices, num_ideal_vertices; int num_vertex_classes, num_edge_classes, num_face_classes; int num_finite_vertex_classes, num_ideal_vertex_classes; /* * Because matrices in O(3,1) tend to accumulate roundoff error, it's * hard to get a good bound on the accuracy of the computed volume. * Nevertheless, the kernel computes the best value it can, with the * hope that it will aid the user in recognizing manifolds defined * by a set of generators. (The volume of a manifold defined by * Dehn filling a Triangulation can be computed directly to great * accuracy, using the kernel's volume() function.) */ Real approximate_volume; /* * The inradius is the radius of the largest sphere (centered at the * basepoint) which can be inscribed in the Dirichlet domain. * The outradius is the radius of the smallest sphere (centered at the * basepoint) which can be circumscribed about the Dirichlet domain. * The outradius will be infinite for cusped manifolds, in which * case it's set to INFINITE_RADIUS. */ Real inradius, outradius; /* * spine_radius is the infimum of the radii (measured from the origin) * of all spines dual to the Dirichlet domain. compute_spine_radius() * in Dirichlet_extras.c shows that spine_radius equals the maximum * of dist_edge_to_origin over all edge classes. The spine_radius * plays an essential role in the length spectrum routines. * * Note: In practice compute_spine_radius() removes selected 2-cells * from the spine to reduce its radius, and thereby reduce the time * required to compute length spectra. Please see compute_spine_radius() * in Dirichlet_extras.c for details. */ Real spine_radius; /* * Each face pairing isometry is an element of SO(3,1), so the inner * products of its i-th column with its j-th column should be -1 (if * i = j = 0), +1 (if i = j != 0) or 0 (if i != j). The greatest * deviation from these values (over all faces) is recorded in the * deviation field. */ Real deviation; /* * The geometric Euler characteristic of the quotient orbifold (i.e. the * orbifold obtained by doing the face identifications) is computed as * * c[0] - c[1] + c[2] - c[3] * * where * * c[0] = the sum of the solid angles at the vertices divided by 4 pi, * * c[1] = the sum of the dihedral angles at the edges divided by 2 pi, * * c[2] = half the number of faces of the Dirichlet domain, * * c[3] = the number of 3-cells, which is always one. * * This corresponds to the definition of the Euler characteristic of an * orbifold, as explained in Chapter 5 of the 1991 version of Thurston's * notes. It should, in theory, always come out to zero. But since * we compute it using floating point approximations to the solid and * dihedral angles, it provides a measure of the numerical inaccuracies * in the computation. */ Real geometric_Euler_characteristic; /* * vertex_epsilon is used in the construction of the Dirichlet domain. * If the squared distance from a vertex to a hyperplane is within * vertex_epsilon of zero, the vertex is assumed to lie on the hyperplane. * If vertex_epsilon is too large, we won't be able to resolve the small * faces which occur in high order Dehn fillings. If vertex_epsilon is * too small, we'll get spurious Dirichlet plane intersections for * manifolds with simple, symmetrical, non-general-position covering * transformation groups. */ double vertex_epsilon; /* * The following dummy nodes serve as the beginnings and ends of the * doubly-linked lists of vertices, edges and faces. */ WEVertex vertex_list_begin, vertex_list_end; WEEdge edge_list_begin, edge_list_end; WEFace face_list_begin, face_list_end; /* * The following dummy nodes serve as the beginnings and ends of the * doubly-linked lists of vertex classes, edge classes and face classes. */ WEVertexClass vertex_class_begin, vertex_class_end; WEEdgeClass edge_class_begin, edge_class_end; WEFaceClass face_class_begin, face_class_end; }; #include "end_namespace.h" #endif regina-4.96/engine/snappea/nsnappeatriangulation.cpp000644 000765 000024 00000075130 12377776647 022656 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include "maths/nmatrixint.h" #include "maths/numbertheory.h" #include "snappea/nsnappeatriangulation.h" #include "snappea/kernel/kernel_prototypes.h" #include "snappea/kernel/triangulation.h" #include "snappea/kernel/unix_file_io.h" #include "snappea/snappy/SnapPy.h" #include "triangulation/ntriangulation.h" #include "utilities/nthread.h" #include "utilities/stringutils.h" #include "utilities/xmlutils.h" namespace regina { namespace { /** * A mutex to protect kernelMessages. */ static NMutex snapMutex; } std::complex NSnapPeaTriangulation::zero_(0, 0); void NCusp::writeTextShort(std::ostream& out) const { if (complete()) out << "Complete cusp: "; else out << "Filled cusp: "; out << "vertex " << vertex_->markedIndex(); if (! complete()) out << ", filling (" << m_ << ", " << l_ << ')'; } NSnapPeaTriangulation::NSnapPeaTriangulation( const std::string& fileNameOrContents) : data_(0), shape_(0), cusp_(0), filledCusps_(0), syncing_(false) { try { if (startsWith(fileNameOrContents, "% Triangulation")) data_ = regina::snappea::read_triangulation_from_string( fileNameOrContents.c_str()); else data_ = regina::snappea::read_triangulation( fileNameOrContents.c_str()); if (data_) { setPacketLabel(get_triangulation_name(data_)); sync(); } } catch (regina::SnapPeaFatalError& err) { data_ = 0; } listen(this); } NSnapPeaTriangulation::NSnapPeaTriangulation(const NSnapPeaTriangulation& tri) : data_(0), shape_(0), cusp_(0), filledCusps_(0), syncing_(false) { if (tri.data_) { regina::snappea::copy_triangulation(tri.data_, &data_); sync(); } listen(this); } NSnapPeaTriangulation::NSnapPeaTriangulation(const NTriangulation& tri, bool) : data_(0), shape_(0), cusp_(0), filledCusps_(0), syncing_(false) { const NSnapPeaTriangulation* clone = dynamic_cast(&tri); if (clone) { // We have a full SnapPea triangulation to clone. if (clone->data_) { regina::snappea::copy_triangulation(clone->data_, &data_); sync(); } listen(this); return; } // We are building a SnapPea triangulation from one of Regina's // own NTriangulation data structures. // // Make sure SnapPea is likely to be comfortable with it. if (tri.getNumberOfTetrahedra() == 0 || tri.hasBoundaryTriangles() || (! tri.isConnected()) || (! tri.isValid()) || (! tri.isStandard())) { listen(this); return; } if (tri.getNumberOfTetrahedra() >= INT_MAX) { listen(this); return; } // Looks good; go build the SnapPea triangulation. regina::snappea::TriangulationData tData; tData.name = strdup(tri.getPacketLabel().c_str()); tData.num_tetrahedra = static_cast(tri.getNumberOfTetrahedra()); // Fields recalculated by SnapPea: tData.solution_type = regina::snappea::not_attempted; tData.volume = 0; tData.orientability = regina::snappea::unknown_orientability; tData.CS_value_is_known = false; tData.CS_value = 0; tData.num_or_cusps = 0; tData.num_nonor_cusps = 0; tData.cusp_data = 0; tData.tetrahedron_data = new regina::snappea::TetrahedronData[ tData.num_tetrahedra]; int tet, face, i, j, k, l; NTriangulation::TetrahedronIterator it = tri.getTetrahedra().begin(); for (tet = 0; tet < tData.num_tetrahedra; tet++) { for (face = 0; face < 4; face++) { tData.tetrahedron_data[tet].neighbor_index[face] = static_cast( tri.tetrahedronIndex((*it)->adjacentTetrahedron(face))); for (i = 0; i < 4; i++) tData.tetrahedron_data[tet].gluing[face][i] = (*it)->adjacentGluing(face)[i]; } // Other fields are recalculated by SnapPea. for (i = 0; i < 4; i++) tData.tetrahedron_data[tet].cusp_index[i] = -1; for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) for (k = 0; k < 4; k++) for (l = 0; l < 4; l++) tData.tetrahedron_data[tet].curve[i][j][k][l] = 0; tData.tetrahedron_data[tet].filled_shape.real = 0; tData.tetrahedron_data[tet].filled_shape.imag = 0; it++; } regina::snappea::data_to_triangulation(&tData, &data_); delete[] tData.tetrahedron_data; free(tData.name); if (! data_) { listen(this); return; } // Regina triangulations know nothing about peripheral curves. // Install a sensible basis for each cusp, if SnapPea will let us. // // Since we need a hyperbolic structure before we can install // (shortest, second shortest) bases, find one now. regina::snappea::find_complete_hyperbolic_structure(data_); // I believe there is no need to call do_Dehn_filling() in the case where // all cusps are complete, since find_complete_hyperbolic_structure() // already does this. // However, if we passed a closed manifold then SnapPea will have // automatically created a cusp with a filling: if (tri.isClosed()) regina::snappea::do_Dehn_filling(data_); SolutionType soln = static_cast( regina::snappea::get_filled_solution_type(data_)); if (soln == geometric_solution || soln == nongeometric_solution) { try { regina::snappea::install_shortest_bases(data_); } catch (regina::SnapPeaFatalError& err) { // Blurgh. SnapPea says no. } } sync(); listen(this); } NSnapPeaTriangulation::~NSnapPeaTriangulation() { unlisten(this); delete[] shape_; delete[] cusp_; regina::snappea::free_triangulation(data_); } std::string NSnapPeaTriangulation::name() const { return (data_ ? get_triangulation_name(data_) : ""); } NSnapPeaTriangulation::SolutionType NSnapPeaTriangulation::solutionType() const { if (! data_) return NSnapPeaTriangulation::not_attempted; return static_cast( regina::snappea::get_filled_solution_type(data_)); } double NSnapPeaTriangulation::volume() const { if (! data_) return 0; return regina::snappea::volume(data_, 0); } double NSnapPeaTriangulation::volume(int& precision) const { if (! data_) return 0; return regina::snappea::volume(data_, &precision); } bool NSnapPeaTriangulation::volumeZero() const { int precision; double vol = regina::snappea::volume(data_, &precision); // Here come the magic numbers. if (precision < 6) return false; if (fabs(vol) > 1e-7) return false; // Test whether |vol| < 1e-(precision+1). double epsilon = 1; for (int i = 0; i < precision + 1; ++i) epsilon /= 10; return (fabs(vol) < epsilon); } double NSnapPeaTriangulation::minImaginaryShape() const { if (! shape_) return 0; // Since shape_ is non-zero, there is at least one tetrahedron. double ans = shape_[0].imag(); for (unsigned i = 1; i < getNumberOfTetrahedra(); ++i) if (ans > shape_[i].imag()) ans = shape_[i].imag(); return ans; } void NSnapPeaTriangulation::unfill(unsigned whichCusp) { if (! data_) return; if (cusp_[whichCusp].complete()) { // Nothing to do. return; } regina::snappea::set_cusp_info(data_, whichCusp, true, 0, 0); // Update and refresh internal caches. cusp_[whichCusp].m_ = cusp_[whichCusp].l_ = 0; --filledCusps_; regina::snappea::do_Dehn_filling(data_); syncFillings(); } bool NSnapPeaTriangulation::fill(int m, int l, unsigned whichCusp) { if (! data_) return false; // Are we unfilling? if (m == 0 && l == 0) { unfill(whichCusp); return true; } // SnapPea expects reals as filling coefficients. // // Here we use the same test as SnapPea for whether these will be // treated as integers: regina::snappea::Real mReal = m; regina::snappea::Real lReal = l; if (m != (int)mReal || l != (int)lReal) return false; // Enforce other preconditions on the filling coefficients. if (cusp_[whichCusp].vertex_->isLinkOrientable()) { // Note that the gcd() below is Regina's. if (gcd(m, l) != 1) return false; } else { if (! (l == 0 && (m == 1 || m == -1))) return false; } // Are we filling a complete cusp, or changing an existing filling? bool wasComplete = cusp_[whichCusp].complete(); // Do it. regina::snappea::set_cusp_info(data_, whichCusp, false, mReal, lReal); // Update and refresh internal caches. cusp_[whichCusp].m_ = m; cusp_[whichCusp].l_ = l; if (wasComplete) ++filledCusps_; regina::snappea::do_Dehn_filling(data_); syncFillings(); return true; } NTriangulation* NSnapPeaTriangulation::filledTriangulation(unsigned whichCusp) const { if (! data_) return 0; if (cusp_[whichCusp].complete()) return 0; regina::snappea::Triangulation* t; unsigned nCusps = countCusps(); if (nCusps == 1) { t = regina::snappea::fill_cusps(data_, 0, data_->name, 1 /* fill_all_cusps = TRUE, which is 1 in SnapPea */); if (! t) return 0; NTriangulation* ans = new NTriangulation(); fillRegina(t, *ans); return ans; } else { regina::snappea::Boolean* fill_cusp = new regina::snappea::Boolean[nCusps]; std::fill(fill_cusp, fill_cusp + nCusps, 0); fill_cusp[whichCusp] = 1; /* TRUE in SnapPea */ t = regina::snappea::fill_cusps(data_, fill_cusp, data_->name, 0); delete[] fill_cusp; NSnapPeaTriangulation* ans = new NSnapPeaTriangulation(); if (t) ans->reset(t); return ans; } } NTriangulation* NSnapPeaTriangulation::filledTriangulation() const { if (! data_) return 0; unsigned nCusps = getNumberOfBoundaryComponents(); regina::snappea::Triangulation* t; if (filledCusps_ == 0) { // Fill no cusps. return new NSnapPeaTriangulation(*this); } else if (filledCusps_ == nCusps) { // Fill all cusps. t = regina::snappea::fill_cusps(data_, 0, data_->name, 1 /* fill_all_cusps = TRUE, which is 1 in SnapPea */); if (! t) return 0; NTriangulation* ans = new NTriangulation(); fillRegina(t, *ans); return ans; } else { // Fill some but not all cusps. regina::snappea::Boolean* fill_cusp = new regina::snappea::Boolean[nCusps]; for (unsigned i = 0; i < nCusps; ++i) fill_cusp[i] = (cusp_[i].complete() ? 0 : 1 /* TRUE in SnapPea */); t = regina::snappea::fill_cusps(data_, fill_cusp, data_->name, 0); delete[] fill_cusp; if (! t) return 0; NSnapPeaTriangulation* ans = new NSnapPeaTriangulation(); ans->reset(t); return ans; } } NSnapPeaTriangulation* NSnapPeaTriangulation::protoCanonize() const { if (! data_) return 0; regina::snappea::Triangulation* tmp; regina::snappea::copy_triangulation(data_, &tmp); if (regina::snappea::proto_canonize(tmp) != regina::snappea::func_OK) { regina::snappea::free_triangulation(tmp); return 0; } NSnapPeaTriangulation* ans = new NSnapPeaTriangulation(); ans->setPacketLabel(get_triangulation_name(data_)); ans->reset(tmp); return ans; } NTriangulation* NSnapPeaTriangulation::canonize() const { if (! data_) return 0; regina::snappea::Triangulation* tmp; regina::snappea::copy_triangulation(data_, &tmp); if (regina::snappea::canonize(tmp) != regina::snappea::func_OK) { regina::snappea::free_triangulation(tmp); return 0; } NTriangulation* ans = new NTriangulation(); ans->setPacketLabel(get_triangulation_name(data_)); fillRegina(tmp, *ans); regina::snappea::free_triangulation(tmp); return ans; } void NSnapPeaTriangulation::randomize() { if (! data_) return; regina::snappea::randomize_triangulation(data_); sync(); } NMatrixInt* NSnapPeaTriangulation::gluingEquations() const { if (! data_) return 0; NMatrixInt* matrix = new NMatrixInt( getNumberOfEdges() + data_->num_cusps + countCompleteCusps(), 3 * getNumberOfTetrahedra()); int numRows, numCols; int row, j; int** edgeEqns = regina::snappea::get_gluing_equations(data_, &numRows, &numCols); for (row = 0; row < numRows; ++row) for (j = 0; j < numCols; ++j) matrix->entry(row, j) = edgeEqns[row][j]; regina::snappea::free_gluing_equations(edgeEqns, numRows); int c; int* cuspEqn; for (c = 0; c < data_->num_cusps; ++c) { if (cusp_[c].complete()) { cuspEqn = regina::snappea::get_cusp_equation( data_, c, 1, 0, &numCols); for (j = 0; j < numCols; ++j) matrix->entry(row, j) = cuspEqn[j]; regina::snappea::free_cusp_equation(cuspEqn); ++row; cuspEqn = regina::snappea::get_cusp_equation( data_, c, 0, 1, &numCols); for (j = 0; j < numCols; ++j) matrix->entry(row, j) = cuspEqn[j]; regina::snappea::free_cusp_equation(cuspEqn); ++row; } else { cuspEqn = regina::snappea::get_cusp_equation( data_, c, cusp_[c].m_, cusp_[c].l_, &numCols); for (j = 0; j < numCols; ++j) matrix->entry(row, j) = cuspEqn[j]; regina::snappea::free_cusp_equation(cuspEqn); ++row; } } return matrix; } NMatrixInt* NSnapPeaTriangulation::gluingEquationsRect() const { if (! data_) return 0; unsigned n = getNumberOfTetrahedra(); NMatrixInt* matrix = new NMatrixInt( getNumberOfEdges() + data_->num_cusps + countCompleteCusps(), 2 * n + 1); // Note: all entries are automatically initialised to zero. int numRows, numCols; int row, j; int parity; int** edgeEqns = regina::snappea::get_gluing_equations(data_, &numRows, &numCols); for (row = 0; row < numRows; ++row) { parity = 0; for (j = 0; j < n; ++j) { matrix->entry(row, j) += edgeEqns[row][3 * j]; matrix->entry(row, j + n) -= edgeEqns[row][3 * j + 1]; matrix->entry(row, j) -= edgeEqns[row][3 * j + 2]; matrix->entry(row, j + n) += edgeEqns[row][3 * j + 2]; if (edgeEqns[row][3 * j + 2] % 2) parity ^= 1; } matrix->entry(row, 2 * n) = (parity ? -1 : 1); } regina::snappea::free_gluing_equations(edgeEqns, numRows); int c; int* cuspEqn; for (c = 0; c < data_->num_cusps; ++c) { if (cusp_[c].complete()) { cuspEqn = regina::snappea::get_cusp_equation( data_, c, 1, 0, &numCols); parity = 0; for (j = 0; j < n; ++j) { matrix->entry(row, j) += cuspEqn[3 * j]; matrix->entry(row, j + n) -= cuspEqn[3 * j + 1]; matrix->entry(row, j) -= cuspEqn[3 * j + 2]; matrix->entry(row, j + n) += cuspEqn[3 * j + 2]; if (cuspEqn[3 * j + 2] % 2) parity ^= 1; } matrix->entry(row, 2 * n) = (parity ? -1 : 1); regina::snappea::free_cusp_equation(cuspEqn); ++row; cuspEqn = regina::snappea::get_cusp_equation( data_, c, 0, 1, &numCols); parity = 0; for (j = 0; j < n; ++j) { matrix->entry(row, j) += cuspEqn[3 * j]; matrix->entry(row, j + n) -= cuspEqn[3 * j + 1]; matrix->entry(row, j) -= cuspEqn[3 * j + 2]; matrix->entry(row, j + n) += cuspEqn[3 * j + 2]; if (cuspEqn[3 * j + 2] % 2) parity ^= 1; } matrix->entry(row, 2 * n) = (parity ? -1 : 1); regina::snappea::free_cusp_equation(cuspEqn); ++row; } else { cuspEqn = regina::snappea::get_cusp_equation( data_, c, cusp_[c].m_, cusp_[c].l_, &numCols); parity = 0; for (j = 0; j < n; ++j) { matrix->entry(row, j) += cuspEqn[3 * j]; matrix->entry(row, j + n) -= cuspEqn[3 * j + 1]; matrix->entry(row, j) -= cuspEqn[3 * j + 2]; matrix->entry(row, j + n) += cuspEqn[3 * j + 2]; if (cuspEqn[3 * j + 2] % 2) parity ^= 1; } matrix->entry(row, 2 * n) = (parity ? -1 : 1); regina::snappea::free_cusp_equation(cuspEqn); ++row; } } return matrix; } /** * Written by William Pettersson, 2011. */ NMatrixInt* NSnapPeaTriangulation::slopeEquations() const { if (! data_) return 0; NMatrixInt* matrix = new NMatrixInt(2*data_->num_cusps, 3*data_->num_tetrahedra); int i,j; for(i=0; i< data_->num_cusps; i++) { int numRows; // SnapPea returns "a b c" for each tetrahedron, where the // derivative of the holonomy of meridians and longitudes is given as // a log (z_0) + b log ( 1/(1-z_0)) + c log ((z_0 - 1)/z_0) + ... = 0 // // The equation for slopes in terms of quads of types q, q' and q'' // becomes // nu = (b-c)q + (c-a)q' + (a-b)q'' // // See Lemma 4.2 in "Degenerations of ideal hyperbolic triangulations", // Stephan Tillmann, Mathematische Zeitschrift, // DOI: 10.1007/s00209-011-0958-8. // int *equations = regina::snappea::get_cusp_equation(data_, i, 1, 0, &numRows); for(j=0; j< data_->num_tetrahedra; j++) { matrix->entry(2*i,3*j) = equations[3*j+1] - equations[3*j+2]; matrix->entry(2*i,3*j+1) = equations[3*j+2] - equations[3*j]; matrix->entry(2*i,3*j+2) = equations[3*j] - equations[3*j+1]; } regina::snappea::free_cusp_equation(equations); equations = regina::snappea::get_cusp_equation(data_, i, 0, 1, &numRows); for(j=0; j< data_->num_tetrahedra; j++) { matrix->entry(2*i+1,3*j) = equations[3*j+1] - equations[3*j+2]; matrix->entry(2*i+1,3*j+1) = equations[3*j+2] - equations[3*j]; matrix->entry(2*i+1,3*j+2) = equations[3*j] - equations[3*j+1]; } regina::snappea::free_cusp_equation(equations); } return matrix; } /** * Written by William Pettersson, 2011. */ bool NSnapPeaTriangulation::verifyTriangulation(const NTriangulation& tri) const { if (! data_) return false; regina::snappea::TriangulationData *tData; regina::snappea::triangulation_to_data(data_, &tData); int tet, face, i; if (tData->num_tetrahedra != tri.getNumberOfTetrahedra()) { free_triangulation_data(tData); return false; } NTriangulation::TetrahedronIterator it = tri.getTetrahedra().begin(); for (tet = 0; tet < tData->num_tetrahedra; tet++) { for (face = 0; face < 4; face++) { if (tData->tetrahedron_data[tet].neighbor_index[face] != tri.tetrahedronIndex((*it)->adjacentTetrahedron(face))) { free_triangulation_data(tData); return false; } for (i = 0; i < 4; i++) if (tData->tetrahedron_data[tet].gluing[face][i] != (*it)->adjacentGluing(face)[i]) { free_triangulation_data(tData); return false; } } it++; } free_triangulation_data(tData); return true; } void NSnapPeaTriangulation::writeTextShort(std::ostream& out) const { if (data_) { out << "SnapPea triangulation with " << data_->num_tetrahedra << " tetrahedra"; } else { out << "Null SnapPea triangulation"; } } void NSnapPeaTriangulation::writeTextLong(std::ostream& out) const { if (! data_) { out << "Null SnapPea triangulation" << std::endl; return; } NTriangulation::writeTextLong(out); unsigned i; if (shape_) { out << "Tetrahedron shapes:" << std::endl; for (i = 0; i < getNumberOfTetrahedra(); ++i) out << " " << i << ": ( " << shape_[i].real() << ", " << shape_[i].imag() << " )" << std::endl; } else out << "No tetrahedron shapes stored." << std::endl; out << std::endl; out << "Cusps:" << std::endl; for (i = 0; i < getNumberOfBoundaryComponents(); ++i) { out << " " << i << ": Vertex " << cusp_[i].vertex_->markedIndex(); if (cusp_[i].complete()) out << ", complete"; else out << ", filled (" << cusp_[i].m_ << ", " << cusp_[i].l_ << ')'; out << std::endl; } } bool NSnapPeaTriangulation::kernelMessagesEnabled() { NMutex::MutexLock ml(snapMutex); return kernelMessages_; } void NSnapPeaTriangulation::enableKernelMessages(bool enabled) { NMutex::MutexLock ml(snapMutex); kernelMessages_ = enabled; } void NSnapPeaTriangulation::disableKernelMessages() { NMutex::MutexLock ml(snapMutex); kernelMessages_ = false; } std::string NSnapPeaTriangulation::snapPea() const { if (! data_) return std::string(); char* file = regina::snappea::string_triangulation(data_); std::string ans(file); free(file); return ans; } void NSnapPeaTriangulation::snapPea(std::ostream& out) const { if (! data_) return; char* file = regina::snappea::string_triangulation(data_); out << file; free(file); } bool NSnapPeaTriangulation::saveSnapPea(const char* filename) const { if (! (data_ && filename && *filename)) return false; return regina::snappea::write_triangulation(data_, filename); } void NSnapPeaTriangulation::dump() const { if (! data_) return; char* file = regina::snappea::string_triangulation(data_); printf("%s", file); fflush(stdout); free(file); } void NSnapPeaTriangulation::saveAsSnapPea(const char* filename) const { if (data_) regina::snappea::write_triangulation(data_, filename); } void NSnapPeaTriangulation::writeXMLPacketData(std::ostream& out) const { if (! data_) return; out << " " << regina::xml::xmlEncodeSpecialChars(snapPea()) << "\n"; } NTriangulation* NSnapPeaTriangulation::toRegina() const { if (data_) { NTriangulation* ans = new NTriangulation(*this); ans->setPacketLabel(get_triangulation_name(data_)); return ans; } else return 0; } void NSnapPeaTriangulation::packetWasChanged(NPacket* packet) { // If the triangulation is changed "illegitimately", via the // inherited NTriangulation interface, then convert this to a null // triangulation. if (packet == this && data_ && ! syncing_) reset(0); } void NSnapPeaTriangulation::sync() { // TODO: Check first whether anything has changed, and only resync // the NTriangulation data if it has. syncing_ = true; { ChangeEventSpan span(this); // Deal with the combinatorial data and cusps first. if (getNumberOfTetrahedra()) removeAllTetrahedra(); delete[] cusp_; filledCusps_ = 0; if (data_) { fillRegina(data_, *this); if (regina::snappea::get_filled_solution_type(data_) == regina::snappea::not_attempted) { regina::snappea::find_complete_hyperbolic_structure(data_); regina::snappea::do_Dehn_filling(data_); } unsigned i, j; cusp_ = new NCusp[data_->num_cusps]; regina::snappea::Cusp* c = data_->cusp_list_begin.next; for (i = 0; i < data_->num_cusps; ++i) { cusp_[c->index].vertex_ = 0; if (c->is_complete) { cusp_[c->index].m_ = cusp_[c->index].l_ = 0; } else if (c->topology == regina::snappea::Klein_cusp && ! (regina::snappea::Dehn_coefficients_are_integers(c) && c->l == 0 && (c->m == 1 || c->m == -1))) { // Abort! Make this a null triangulation. // Note that reset() calls sync() again; this is // harmless as long as we return immediately afterwards. reset(0); syncing_ = false; return; } else if (c->topology == regina::snappea::torus_cusp && ! regina::snappea::Dehn_coefficients_are_relatively_prime_integers(c)) { // Abort, as above. reset(0); syncing_ = false; return; } else { cusp_[c->index].m_ = c->m; cusp_[c->index].l_ = c->l; ++filledCusps_; } c = c->next; } regina::snappea::Tetrahedron* stet = data_->tet_list_begin.next; for (i = 0; i < getNumberOfTetrahedra(); ++i) { for (j = 0; j < 4; ++j) { c = stet->cusp[j]; if (cusp_[c->index].vertex_ == 0) cusp_[c->index].vertex_ = getTetrahedron(i)->getVertex(j); } stet = stet->next; } } else { cusp_ = 0; } // Next, update all data that depend on the fillings (if any). // Most importantly, this includes the cache of tetrahedron shapes. fillingsHaveChanged(); // The packet change event (which we are listening to) will be // fired at this point. } syncing_ = false; } void NSnapPeaTriangulation::syncFillings() { syncing_ = true; { ChangeEventSpan span(this); fillingsHaveChanged(); // The packet change event will be fired at this point. } syncing_ = false; } void NSnapPeaTriangulation::fillingsHaveChanged() { // Clear properties that depend on the fillings. fundGroupFilled_.clear(); h1Filled_.clear(); delete[] shape_; if (data_) { // Refresh the array of tetrahedron shapes. regina::snappea::Tetrahedron* stet; SolutionType soln = static_cast( regina::snappea::get_filled_solution_type(data_)); if (soln == not_attempted || soln == no_solution) { shape_ = 0; } else { // Fetch the shapes directly from SnapPea's internal // data structures, since SnapPea's get_tet_shape() // function is linear time (per tetrahedron). shape_ = new std::complex[getNumberOfTetrahedra()]; stet = data_->tet_list_begin.next; regina::snappea::ComplexWithLog* shape; for (unsigned i = 0; i < getNumberOfTetrahedra(); ++i) { shape = &stet->shape[regina::snappea::filled]-> cwl[regina::snappea::ultimate][0 /* fixed */]; shape_[i] = std::complex( shape->rect.real, shape->rect.imag); stet = stet->next; } } } else { shape_ = 0; } } void NSnapPeaTriangulation::fillRegina(regina::snappea::Triangulation* src, NTriangulation& dest) { ChangeEventSpan span(&dest); regina::snappea::TriangulationData* tData; regina::snappea::triangulation_to_data(src, &tData); NTetrahedron** tet = new NTetrahedron*[tData->num_tetrahedra]; int i, j; for (i = 0; i < tData->num_tetrahedra; ++i) tet[i] = dest.newTetrahedron(); for (i = 0; i < tData->num_tetrahedra; ++i) for (j = 0; j < 4; ++j) if (! tet[i]->adjacentTetrahedron(j)) tet[i]->joinTo(j, tet[tData->tetrahedron_data[i].neighbor_index[j]], NPerm4(tData->tetrahedron_data[i].gluing[j])); delete[] tet; regina::snappea::free_triangulation_data(tData); } void NSnapPeaTriangulation::reset(regina::snappea::Triangulation* data) { if (data_) regina::snappea::free_triangulation(data_); data_ = data; sync(); } } // namespace regina regina-4.96/engine/snappea/nsnappeatriangulation.h000644 000765 000024 00000206531 12377775404 022312 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file snappea/nsnappeatriangulation.h * \brief Provides access to the SnapPea kernel. */ #ifndef __NSNAPPEATRIANGULATION_H #ifndef __DOXYGEN #define __NSNAPPEATRIANGULATION_H #endif #include "regina-config.h" // For EXCLUDE_SNAPPEA #include "regina-core.h" #include "triangulation/ntriangulation.h" #include namespace regina { // Forward declaration of SnapPea structures. namespace snappea { struct Triangulation; } class NMatrixInt; class NSnapPeaTriangulation; class NTriangulation; class NXMLSnapPeaReader; /** * \weakgroup triangulation * @{ */ #ifndef EXCLUDE_SNAPPEA /** * A base class for all exceptions that are thrown from within the * SnapPea kernel. * * \ifacespython Not present. */ struct SnapPeaException { }; /** * An exception that is thrown when the SnapPea kernel encounters a * fatal error. * * \ifacespython Not present. */ struct SnapPeaFatalError : public SnapPeaException { std::string function; /**< The function from the SnapPea kernel in which the fatal error occurred. */ std::string file; /**< The source file from the SnapPea kernel in which the fatal error occurred. */ /** * Creates a new exception, indicating where in the SnapPea kernel * the error occurred. * * @param fromFunction the function from the SnapPea kernel in which * the error occurred. * @param fromFile the source file from the SnapPea kernel in which * the error occurred. */ SnapPeaFatalError(const char* fromFunction, const char* fromFile); }; /** * An exception that is thrown when the SnapPea kernel finds that all * available memory has been exhausted. * * \ifacespython Not present. */ struct SnapPeaMemoryFull : public SnapPeaException { }; /** * Stores information about the SnapPea triangulation packet. * See the general PacketInfo template notes for further details. * * \ifacespython Not present. */ template <> struct PacketInfo { typedef NSnapPeaTriangulation Class; inline static const char* name() { return "SnapPea Triangulation"; } }; /** * Represents a single cusp of a SnapPea triangulation. * See the NSnapPeaTriangulation class for further details. * * NCusp objects should be considered temporary only. They are preserved * if you change the fillings (via NSnapPeaTriangulation::fill() * or NSnapPeaTriangulation::unfill()). However, if you change the SnapPea * triangulation itself (e.g., via randomize()), then all cusp objects will * be deleted and replaced with new ones (using fresh data re-fetched from * the SnapPea kernel). */ class REGINA_API NCusp : public ShareableObject { private: NVertex* vertex_; /**< The corresponding vertex of the Regina triangulation. */ int m_; /**< The first (meridian) filling coefficient, or 0 if this cusp is complete. */ int l_; /**< The second (longitude) filling coefficient, or 0 if this cusp is complete. */ public: /** * Default destructor. */ virtual ~NCusp(); /** * Returns the corresponding vertex of the Regina triangulation * (i.e., of the NTriangulation structure that is inherited by * NSnapPeaTriangulation). * * Note that cusp and vertex indexing might not be in sync; that is, * SnapPea's cusp(i) need not correspond to Regina's * getVertex(i). * * This routine can be used to detect if/when cusp numbering * and vertex numbering fall out of sync, and to translate * between them if/when this happens. */ NVertex* vertex() const; /** * Returns whether this cusp is complete. * * \snappy In SnapPy, this field corresponds to querying * Manifold.cusp_info('is_complete')[cusp_number]. * * @return \c true if this cusp is complete, or \c false if it is * filled. */ bool complete() const; /** * Returns the first (meridian) filling coefficient on this cusp, * or 0 if this cusp is complete. * * \snappy In SnapPy, this field corresponds to querying * Manifold.cusp_info('filling')[cusp_number][0]. * * @return the first filling coefficient. */ int m() const; /** * Returns the second (longitude) filling coefficient on this cusp, * or 0 if this cusp is complete. * * \snappy In SnapPy, this field corresponds to querying * Manifold.cusp_info('filling')[cusp_number][1]. * * @return the second filling coefficient. */ int l() const; void writeTextShort(std::ostream& out) const; private: /** * A default constructor that performs no initialisation whatsoever. */ NCusp(); friend class NSnapPeaTriangulation; /**< Allow access to private members. */ }; /** * Offers direct access to the SnapPea kernel from within Regina. * An object of this class represents a 3-manifold triangulation, stored * directly in the SnapPea kernel using SnapPea's internal format. * * Regarding interaction with the SnapPea kernel: * * - This class acts as the sole C/C++ conduit between the Regina * calculation engine and Regina's inbuilt version of the SnapPea kernel. * Regina should not interact with the SnapPea kernel at the C/C++ level * other than through this class. * * - Regina can, however, interact with SnapPy at the Python level. * Regina's version of the SnapPea kernel lives within a separate namespace * (regina::snappea), and so there should be no conflicts between Regina's * copy and SnapPy's copy of the SnapPea kernel (which may even be different * versions). You can pass triangulations back and forth between Regina and * SnapPy using strings that contain the contents of a SnapPea data file * (see for instance NSnapPeaTriangulation::snapPea()). * * Regarding the inherited NTriangulation interface: * * - You can happily query this object using both SnapPea functions (such as * NSnapPeaTriangulation::volume(), and others specific to this class) * and Regina's native triangulation functions (such as * NTriangulation::getHomologyH1(), and others inherited from NTriangulation). * This is because an object of this class stores \e two representations of * the triangulation (SnapPea's and Regina's), which are always kept in sync. * * - However, you may only edit this object using the SnapPea functions * specific to this class (such as NSnapPeaTriangulation::randomise()). * This is essentially because the synchronisation is one-way only (from * SnapPea to Regina, but not in the other direction). * * - Any attempt to edit this triangulation via the inherited NTriangulation * interface (for instance, by calling NTriangulation::twoThreeMove()) will * automatically cause this to become a null triangulation, * with no tetrahedra and no SnapPea data at all. * * Null triangulations appear more generally when Regina is unable to * represent data in SnapPea's native format. You can test for a * null triangulation by calling isNull(). Null triangulations can occur * for several reasons, such as (but not limited to): * * - attempting to build a SnapPea triangulation from a Regina triangulation * that is invalid, has boundary faces, or has higher genus vertex * links (none of which SnapPea can handle); * * - attempting to read a broken SnapPea data file; * * - attempting to change a SnapPea triangulation using the inherited * NTriangulation interface (as discussed above); * * - attempting to import a SnapPea triangulation that uses unsupported * (e.g., non-integer or non-coprime) filling coefficients, as discussed * below). * * Regarding fillings: SnapPea can store and manipulate Dehn fillings on * cusps, and the NSnapPeaTriangulation class respects these where it can (but * with restrictions on the possible filling coefficients; see below). * However, Regina's own NTriangulation class knows nothing about fillings * at all. Therefore: * * - Routines inherited through the NTriangulation interface will ignore * fillings completely (so, for instance, getHomologyH1() will return the * first homology of the unfilled manifold, even if SnapPea has * designated fillings on the cusps). * * - Routines that are defined here in the NSnapPeaTriangulation class * are generally aware of fillings (so, for instance, homologyFilled() * will return the first homology of the filled manifold). See the * individual notes for each member function for details on how it * handles fillings. * * For now, NSnapPeaTriangulation only supports the following types of filling * coefficients: on orientable cusps the filling coefficients must be * coprime integers, and non non-orientable cusps the filling coefficients * must be the integers (±1, 0). Any attempt to import a triangulation from * a SnapPea file with filling coefficients outside these requirements will * result in a null triangulation (as discussed above). * * There are many places in the SnapPea kernel where SnapPea throws a * fatal error. As of Regina 4.96, these fatal errors are converted * into exceptions (subclassed from SnapPeaException), which can be caught * and handled politely. * * Regina uses the variant of the SnapPea kernel that is shipped with * SnapPy 2.2 (standard precision), as well as some additional code * written explicitly for SnapPy. * The SnapPea kernel was written by Jeff Weeks, and SnapPy was written by * Marc Culler, Nathan Dunfield, and others. SnapPy and the corresponding * SnapPea kernel are distributed under the terms of the GNU General * Public License, version 2 or any later version, as published by the * Free Software Foundation. * * See http://snappy.computop.org/ for further information on * SnapPea and its successor SnapPy. */ class REGINA_API NSnapPeaTriangulation : public NTriangulation, public NPacketListener { REGINA_PACKET(NSnapPeaTriangulation, PACKET_SNAPPEATRIANGULATION) public: /** * Describes the different types of solution that can be found when * solving for a hyperbolic structure. * * Although this enumeration is identical to SnapPea's own * SolutionType, it is declared again in this class because Regina * code should not in general be interacting directly with the * SnapPea kernel. Values may be freely converted between the * two enumeration types by simple assignment and/or typecasting. * * \warning This enumeration must always be kept in sync with * SnapPea's own SolutionType enumeration. */ typedef enum { not_attempted, /**< A solution has not been attempted. */ geometric_solution, /**< All tetrahedra are either positively oriented or flat, though the entire solution is not flat and no tetrahedra are degenerate. */ nongeometric_solution, /**< The volume is positive, but some tetrahedra are negatively oriented. */ flat_solution, /**< All tetrahedra are flat, but none have shape 0, 1 or infinity. */ degenerate_solution, /**< At least one tetrahedron has shape 0, 1 or infinity. */ other_solution, /**< The volume is zero or negative, but the solution is neither flat nor degenerate. */ no_solution /**< The gluing equations could not be solved. */ } SolutionType; private: regina::snappea::Triangulation* data_; /**< The triangulation stored in SnapPea's native format, or 0 if this is a null triangulation. */ std::complex* shape_; /**< The array of tetrahedron shapes, in rectangular form, using a fixed coordinate system (fixed alignment in SnapPea's terminology). All shapes are with respect to the Dehn filled hyperbolic structure. If this is a null triangulation, or if the solution type is no_solution or not_attempted, then shape_ will be 0. */ NCusp* cusp_; /**< An array that caches information about each cusp of the internal SnapPea triangulation. If this is a null triangulation then cusp_ will be 0. */ unsigned filledCusps_; /**< The number of cusps that are currently filled. */ mutable NProperty fundGroupFilled_; /**< The fundamental group of the filled triangulation, or 0 if this cannot be computed (e.g., if SnapPea does not return a matrix of relations). */ mutable NProperty h1Filled_; /**< The first homology group of the filled triangulation, or 0 if this cannot be computed. */ bool syncing_; /**< Set to \c true whilst sync() is being called. This allows the internal packet listener to distinguish between "legitimate" changes to the inherited NTriangulation via sync(), versus "illegitimate" changes from elsewhere through the inherited NTriangulation interface. */ static bool kernelMessages_; /**< Should the SnapPea kernel write diagnostic messages to standard output? */ static std::complex zero_; /**< The complex number 0. This is defined as a data member so that shape() can still return a reference even when no tetrahedron shapes have been computed. */ public: /** * \name Constructors and Destructors */ /*@{*/ /** * Creates a null triangulation, with no internal SnapPea data at all. */ NSnapPeaTriangulation(); /** * Creates a new SnapPea triangulation from the contents of * SnapPea data file. The argument may be the \e name of a * SnapPea file, or it may also be the \e contents of a SnapPea file * (so the file itself need not actually exist on the filesystem). * * This routine uses the SnapPea kernel to read the data file, * and so all SnapPea-specific information will be preserved * (including information that Regina itself does not store, * such as peripheral curves). * * If this operation is successful, this constructor will immediately * ask SnapPea to try to find a hyperbolic structure. * * If this operation fails (e.g., if the given string does not * represent a valid SnapPea data file), then this will be a * null triangulation. You can test for this by calling isNull(). * * The triangulation will automatically be given a packet label * based on the manifold name stored in the second line of the * SnapPea data file. * * \note This constructor can be used in a Python session to * pass data from SnapPy through to Regina's copy of the SnapPea * kernel (which is strictly separate from SnapPy's), without * losing any of SnapPy's internal information. * * \warning If (for some reason) you pass a filename that begins * with "% Triangulation", then Regina will interpret this as * the contents of a SnapPea file (not a filename). * * \i18n If the given argument is a filename, then this routine makes * no assumptions about the \ref i18n "character encoding" used in the * filename, and simply passes it through unchanged to low-level C/C++ * file I/O routines. This routine assumes that the file \e contents, * however, are in UTF-8 (the standard encoding used throughout Regina). * * @param fileNameOrContents either the name of a SnapPea data * file, or the contents of a SnapPea data file (which need not * actually exist on the filesystem). */ NSnapPeaTriangulation(const std::string& fileNameOrContents); /** * Creates a clone of the given SnapPea triangulation. * This copy will be independent (i.e., this triangulation will * not be affected if \a tri is later changed or destroyed). * * If \a tri is a null triangulation then this will be a null * triangulation also. See isNull() for further details. * * @param tri the SnapPea triangulation to clone. */ NSnapPeaTriangulation(const NSnapPeaTriangulation& tri); /** * Converts the given Regina triangulation to a SnapPea triangulation. * This copy will be independent (i.e., this triangulation will * not be affected if \a tri is later changed or destroyed). * * Since Regina works with more general kinds of * trianguations than SnapPea, not all Regina triangulations can be * represented in SnapPea format. If the conversion is * unsuccessful, this will be marked as a null triangulation. * You should always test isNull() to determine whether the * conversion was successful. * * Regarding the conversion: * * - If \a tri is of the subclass NSnapPeaTriangulation, then * this effectively acts as a copy constructor: all * SnapPea-specific information will be cloned directly * through the SnapPea kernel. If \a tri is a null SnapPea * triangulation then this copy will be a null triangulation also. * * - If \a tri is of the parent class NTriangulation, then * Regina will attempt to convert this triangulation to * SnapPea format. If the conversion is successful, this * constructor will immediately ask SnapPea to try to find a * hyperbolic structure. * * Regarding peripheral curves: native Regina triangulations do not * store or use peripheral curves themselves, and so this constructor * makes a default choice during the conversion process. Specifically: * * - If solution_type() is geometric_solution or nongeometric_solution, * then on each torus cusp the meridian and longitude are chosen to * be the (shortest, second shortest) basis, and their orientations * follow the convention used by the \e SnapPy kernel. Be warned, * however, that this choice might not be unique for some cusp shapes, * and the resolution of such ambiguities might be machine-dependent. * * - If solution_type() is something else (e.g., degenerate or flat), * or if SnapPea throws a fatal error when attempting to install the * (shortest, second shortest) basis as described above, then Regina * will accept whatever basis SnapPea installs by default. Be warned * that this default basis may change (and indeed has changed in the * past) across different versions of the SnapPea kernel. * * Regarding internal vertices (i.e., vertices whose links are spheres): * SnapPea is designed to work only with triangulations where * every vertex is ideal. As a result: * * - You may pass a closed triangulation to this constructor, but * SnapPea will automatically convert this into a filling of a * cusped manifold, using an ideal triangulation. * * - You may also pass a triangulation that uses both ideal and * internal vertices. In this case, SnapPea will retriangulate * the manifold so that it uses ideal vertices only. * * Even if SnapPea does not retriangulate the manifold (for the * reasons described above), it is possible that the tetrahedron and * vertex numbers might be changed in the new SnapPea triangulation. * In particular, if the given Regina triangulation is orientable but * not oriented, then you should \e expect these numbers to change. * * @param tri the Regina triangulation to clone. * @param ignored a legacy parameter that is now ignored. * (This argument was once required if you wanted to pass a * closed triangluation to SnapPea.) */ NSnapPeaTriangulation(const NTriangulation& tri, bool ignored = false); /** * Destroys this triangulation. All internal SnapPea data will * also be destroyed. */ ~NSnapPeaTriangulation(); /*@}*/ /** * \name Basic Properties */ /*@{*/ /** * Determines whether this triangulation contains valid SnapPea data. * * A null SnapPea triangulation can occur (for instance) * when converting unusual types of Regina triangulation into * SnapPea format, or when reading broken SnapPea data files. * See the NSnapPeaTriangulation class notes for details. * * @return \c true if this is a null triangulation, or \c false * if this triangulation contains valid SnapPea data. */ bool isNull() const; /** * Returns SnapPea's internal name for this triangulation. * * This is the manifold name stored in the SnapPea kernel, which * is typically different from the packet label assigned by Regina. * * If this is a null triangulation then the empty string will be * returned. * * \snappy In SnapPy, this routine corresponds to calling * Manifold.name(). * * @return SnapPea's name for this triangulation. */ std::string name() const; /*@}*/ /** * \name Hyperbolic Structures */ /*@{*/ /** * Returns the type of solution found when solving for a hyperbolic * structure, with respect to the current Dehn filling (if any). * * \snappy In SnapPy, this routine corresponds to calling * Manifold.solution_type(). * * @return the solution type. */ SolutionType solutionType() const; /** * Computes the volume of the current solution to the hyperbolic * gluing equations. This will be with respect to the current * Dehn filling (if any). * * \snappy In SnapPy, this routine corresponds to calling * Manifold.volume(). * * @return the estimated volume of the underlying 3-manifold, * or 0 if this is a null triangulation. */ double volume() const; /** * Computes the volume of the current solution to the hyperbolic * gluing equations, and estimates the accuracy of the answer. * This will be with respect to the current Dehn filling (if any). * * \snappy In SnapPy, this routine corresponds to calling * Manifold.volume(accuracy=True). * * \ifacespython The \a precision argument is not present. * Instead, two routines are offered. The routine \a volume() * takes no arguments and returns the volume only, whereas the * routine \a volumeWithPrecision() takes no arguments and * returns a (\a volume, \a precision) tuple. * * @param precision used to return an estimate of the number of * decimal places of accuracy in the calculated volume. * * @return the estimated volume of the underlying 3-manifold, * or 0 if this is a null triangulation. */ double volume(int& precision) const; /** * Determines whether the current solution to the gluing equations * has volume approximately zero. This test is \e not rigorous. * * This requires (i) the volume itself to be very close to * zero in an absolute sense, (ii) the volume to be zero * within SnapPea's own estimated precision, and (iii) SnapPea's * estimated precision to be sufficiently good in an absolute sense. * * @return \c true if and only if the volume of the current * solution is approximately zero according to the constraints * outlined above. */ bool volumeZero() const; /** * Returns the shape of the given tetrahedron, with respect to * the Dehn filled hyperbolic structure. * * Tetrahedron shapes are given in rectangular form, and using a * fixed coordinate system (fixed alignment, in SnapPea's terminology). * * If this is a null triangulation, or if solutionType() is no_solution * or not_attempted (i.e., we did not or could not solve for a * hyperbolic structure), then this routine will simply return zero. * * This routine is fast constant time (unlike in SnapPea, where * the corresponding routine \a get_tet_shape takes linear time). * Therefore you can happily call this routine repeatedly without a * significant performance penalty. * * \snappy In SnapPy, this routine corresponds to calling * Manifold.tetrahedra_shapes(part='rect')[tet]. * * @param tet the index of a tetrahedron; this must be between * 0 and getNumberOfTetrahedra()-1 inclusive. * @return the shape of the given tetrahedron, in rectangular form. */ const std::complex& shape(unsigned tet) const; /** * Returns the minimum imaginary part found amongst all tetrahedron * shapes, with respect to the Dehn filled hyperbolic structure. * * Tetrahedron shapes are given in rectangular form using a fixed * coordinate system, as described in the documentation for shape(). * * If this is a null triangulation, or if solutionType() is no_solution * or not_attempted (i.e., we did not or could not solve for a * hyperbolic structure), then this routine will simply return zero. * * \snappy This has no corresponding routine in SnapPy, * though the information is easily acessible via * Manifold.tetrahedra_shapes(part='rect'). * * @return the minimum imaginary part amongst all tetrahedron shapes. */ double minImaginaryShape() const; /** * Returns a matrix describing Thurston's gluing equations. * This will be with respect to the current Dehn filling (if any). * * Each row of this matrix will describe a single equation. * The first getNumberOfEdges() rows will list the edge equations, * and the following 2 * countCompleteCusps() + countFilledCusps() * rows will list the cusp equations. * * The edge equations will be ordered arbitrarily. The cusp equations * will be presented in pairs ordered by cusp index (as stored by * SnapPea); within each pair the meridian equation will appear before * the longitude equation. The NCusp::vertex() method (which * is accessed through the cusp() routine) can help translate * between SnapPea's cusp numbers and Regina's vertex numbers. * * The matrix will contain 3 * getNumberOfTetrahedra() columns. * The first three columns represent shape parameters z, * 1/(1-z) and (z-1)/z for the first tetrahedron; * the next three columns represent shape parameters z, * 1/(1-z) and (z-1)/z for the second tetrahedron, * and so on. By Regina's edge numbering conventions, * z corresponds to edges 0 and 5 of the tetrahedron, * 1/(1-z) corresponds to edges 1 and 4 of the tetrahedron, and * (z-1)/z corresponds to edges 2 and 3 of the tetrahedron. * * More specifically, a row of the form a b c d e f ... * describes an equation with left hand side * a * log(z0) + b * log(1/(1-z0)) + c * log((z0-1)/z) + * d * log(z1) + ... = 2 pi i, * and with right hand side 2 pi i for an edge equation * or 0 for a cusp equation. * * See also gluingEquationsRect(), which returns the gluing * equations in a more streamlined form. * * \snappy In SnapPy, this routine corresponds to calling * Manifold.gluing_equations(). * * @return a newly allocated matrix with (\a number_of_rows + * \a number_of_cusps) rows and (3 * \a number_of_tetrahedra) columns * as described above, or 0 if this is a null triangulation. */ NMatrixInt* gluingEquations() const; /** * Returns a matrix describing Thurston's gluing equations in a * streamlined form. This will be with respect to the current * Dehn filling (if any). * * Each row of this matrix will describe a single equation. * The rows begin with the edge equations (in arbitrary order) * followed by the cusp equations (ordered by cusp index); for * precise details see the documentation for gluingEquations(), * which uses the same ordering. * * The matrix will contain 2 * getNumberOfTetrahedra() + 1 * columns. Let \a k = getNumberOfTetrahedra()-1, and suppose the * shape parameters for tetrahedra 0, 1, ..., k are * \a z0, \a z1, ..., \a zk (here each shape parameter corresponds * to edges 0 and 5 of the corresponding tetrahedron). * Then a row of the form a0 a1 ... ak b0 b1 ... bk c * describes the equation * z0^a0 z1^a1 ... zk^ak (1-z0)^b0 (1-z1)^b1 ... (1-zk)^bk = c, * where \a c will always be 1 or -1. * * See also gluingEquations(), which returns the gluing * equations in a more transparent term-by-term form. * * \snappy In SnapPy, this routine corresponds to calling * Manifold.gluing_equations(form='rect'). * * @return a newly allocated matrix with (\a number_of_rows + * \a number_of_cusps) rows and (2 * \a number_of_tetrahedra + 1) * columns as described above, or 0 if this is a null triangulation. */ NMatrixInt* gluingEquationsRect() const; /*@}*/ /** * \name Cusps */ /*@{*/ /** * Returns the total number of cusps (both filled and complete). * * This returns the same value as the inherited function * NTriangulation::getNumberOfBoundaryComponents(). * * \snappy In SnapPy, this routine corresponds to calling * Manifold.num_cusps(). * * @return the total number of cusps. */ unsigned countCusps() const; /** * Returns the total number of complete cusps (that is, unfilled cusps). * * It is always true that * countCompleteCusps() + countFilledCusps() == countCusps(). * * \snappy This has no corresponding routine in SnapPy, * though the information is easily acessible via * Manifold.cusp_info('is_complete'). * * @return the total number of complete cusps. */ unsigned countCompleteCusps() const; /** * Returns the total number of filled cusps. * * It is always true that * countCompleteCusps() + countFilledCusps() == countCusps(). * * \snappy This has no corresponding routine in SnapPy, * though the information is easily acessible via * Manifold.cusp_info('is_complete'). * * @return the total number of filled cusps. */ unsigned countFilledCusps() const; /** * Returns information about the given cusp of this manifold. * This information includes the filling coefficients (if any), * along with other combinatorial information. * * \snappy In SnapPy, this routine corresponds to calling * Manifold.cusp_info()[c], though the set of * information returned about each cusp is different. * * These NCusp objects should be considered temporary only. They are * preserved if you change the fillings (via fill() or unfill()). * However, if you change the SnapPea triangulation itself * (e.g., via randomize()), then all cusp objects will be deleted * and replaced with new ones (using fresh data re-fetched from * the SnapPea kernel). * * \warning Be warned that cusp \a i might not correspond to vertex * \a i of the triangulation. The NCusp::vertex() method (which * is accessed through the cusp() routine) can help translate * between SnapPea's cusp numbers and Regina's vertex numbers. * * @param whichCusp the index of a cusp according to SnapPea; * this must be between 0 and countCusps()-1 inclusive. * @return information about the given cusp, or 0 if this is a * null triangulation. */ const NCusp* cusp(unsigned whichCusp = 0) const; /** * Assigns a Dehn filling to the given cusp. This routine will * automatically ask SnapPea to update the hyperbolic structure * according to the new filling coefficients. * * The triangulation itself will not change; this routine will * simply ask SnapPea to store the given filling coefficients * alongside the cusp, to be used in operations such as computing * hyperbolic structures. If you wish to retriangulate to permanently * fill the cusp, call filledTriangulation() instead. * * For orientable cusps only coprime filling coefficients are allowed, * and for non-orientable cusps only (±1, 0) fillings are allowed. * Although SnapPea can handle more general fillings, Regina * will enforce these conditions; if they are not satisfied then * it will do nothing and simply return \c false. * * As a special case however, you may pass (0, 0) as the filling * coefficients, in which case this routine will behave * identically to unfill(). * * It is possible that, if the given integers are extremely * large, SnapPea cannot convert the filling coefficients to its * own internal floating-point representation. If this happens * then this routine will again do nothing and simply return \c false. * * \warning Be warned that cusp \a i might not correspond to vertex * \a i of the triangulation. The NCusp::vertex() method (which * is accessed through the cusp() routine) can help translate * between SnapPea's cusp numbers and Regina's vertex numbers. * * @param m the first (meridional) filling coefficient. * @param l the second (longitudinal) filling coefficient. * @param whichCusp the index of the cusp to fill according to * SnapPea; this must be between 0 and countCusps()-1 inclusive. * @return \c true if and only if the filling coefficients were * accepted (according to the conditions outlined above). */ bool fill(int m, int l, unsigned whichCusp = 0); /** * Removes any filling on the given cusp. After removing the filling, * this routine will automatically ask SnapPea to update the * hyperbolic structure. * * If the given cusp is already complete, then this routine * safely does nothing. * * \warning Be warned that cusp \a i might not correspond to vertex * \a i of the triangulation. The NCusp::vertex() method (which * is accessed through the cusp() routine) can help translate * between SnapPea's cusp numbers and Regina's vertex numbers. * * @param whichCusp the index of the cusp to unfill according to * SnapPea; this must be between 0 and countCusps()-1 inclusive. */ void unfill(unsigned whichCusp = 0); /** * Retriangulates to permanently fill the given cusp. This uses * the current Dehn filling coefficients on the cusp, as set by fill(). * * If this triangulation has more than one cusp to begin with, * then the result will be a new instance of NSnapPeaTriangulation, * and will have one fewer cusp. Note that the remaining cusps * may be reindexed, and all NCusp structures will be destroyed * and rebuilt. Auxiliary information on the remaining cusps (such * as filling coefficients and peripheral curves) will be preserved, * and SnapPea will automatically attempt to compute a hyperbolic * structure on the new triangulation. * * If this triangulation has only one cusp, then the result will * be a new instance of NTriangulation (not NSnapPeaTriangulation), * and will represent a closed manifold. * * Either way, the result will be a newly allocated triangulation, and * it is the responsibility of the caller of this routine to destroy it. * The original triangulation (this object) will be left unchanged. * If the given cusp is complete or if this is a null triangulation, * then this routine will simply return 0. * * \warning Be warned that cusp \a i might not correspond to vertex * \a i of the triangulation. The NCusp::vertex() method (which * is accessed through the cusp() routine) can help translate * between SnapPea's cusp numbers and Regina's vertex numbers. * * @param whichCusp the index of the cusp to permanently fill according * to SnapPea; this must be between 0 and countCusps()-1 inclusive. * @return the new filled triangulation or 0 if the filling was * not possible (as described above). */ NTriangulation* filledTriangulation(unsigned whichCusp) const; /** * Retriangulates to permanently fill all non-complete cusps. * This uses the current Dehn filling coefficients on the cusps, * as set by fill(). * * If every cusp of this triangulation is complete, this routine * will simply return a new clone of this triangulation. * * If some but not all cusps are complete, then the result will * be a new instance of NSnapPeaTriangulation, and will have * fewer cusps. Note that the remaining cusps may be reindexed, * and all NCusp structures will be destroyed and rebuilt. Auxiliary * information on the remaining cusps (such as peripheral curves) * will be preserved, and SnapPea will automatically attempt to * compute a hyperbolic structure on the new triangulation. * * If all cusps of this triangulation have filling coefficients * assigned, then the result will be a new instance of NTriangulation * (not NSnapPeaTriangulation), and will represent a closed manifold. * * Whatever happens, the result will be a newly allocated triangulation, * and it is the responsibility of the caller of this routine to * destroy it. The original triangulation (this object) will be left * unchanged. If this is a null triangulation, then this routine * will simply return 0. * * @return the new filled triangulation, or 0 if this is a null * triangulation. */ NTriangulation* filledTriangulation() const; /** * Returns a matrix for computing boundary slopes of * spun-normal surfaces at the cusps of the triangulation. This * matrix includes a pair of rows for each cusp in the triangulation: * one row for determining the algebraic intersection number * with the meridian, followed by one row for determining the * algebraic intersection number with the longitude. * * If the triangulation has more than one cusp, these pairs are * ordered by cusp index (as stored by SnapPea). You can examine * cusp(cusp_number).vertex() to map these to Regina's * vertex indices if needed. * * For the purposes of this routine, any fillings on the cusps of * this SnapPea triangulation will be ignored. * * This matrix is constructed so that, if \a M and \a L are the * rows for the meridian and longitude at some cusp, then for * any spun-normal surface with quadrilateral coordinates * \a q, the boundary curves have algebraic intersection number * M.q with the meridian and L.q with the longitude. * Equivalently, the boundary curves pass L.q times around the * meridian and -M.q times around the longitude. * To compute these slopes directly from a normal surface, see * NNormalSurface::boundaryIntersections(). * * The orientations of the * boundary curves of a spun-normal surface are chosen so * that \e if meridian and longitude are a positive basis as * vieved from the cusp, then as one travels along an oriented * boundary curve, the spun-normal surface spirals into the cusp * to one's right and down into the manifold to one's left. * * \snappy This has no corresponding routine in SnapPy. * * \pre All vertex links in this triangulation must be tori. * * \warning If this triangulation was constructed from a Regina * triangulation (of class NTriangulation), then Regina will have * no information about what meridian and longitude the user wishes * to use (since Regina does not keep track of peripheral curves * on cusps). Therefore Regina will give boundary slopes relative * to the (shortest, second-shortest) basis, as described in the * constructor NSnapPeaTriangulation(const NTriangulation&, bool). * This might not be what the user expects. * * @author William Pettersson and Stephan Tillmann * * @return a newly allocated matrix with (2 * \a number_of_cusps) rows * and (3 * \a number_of_tetrahedra) columns as described above, * or 0 if this is a null triangulation. */ NMatrixInt* slopeEquations() const; /*@}*/ /** * \name Algebraic Invariants */ /*@{*/ /** * Returns the first homology group of the manifold with respect * to the current Dehn filling (if any). Any complete cusps * (without fillings) will be treated as though they had been * truncated. * * This is different from the inherited getHomologyH1() routine from * the parent NTriangulation class: * * - This routine homologyFilled() respects Dehn fillings, and uses * a combination of both SnapPea's and Regina's code to compute * homology groups. There may be situations in which the SnapPea * kernel cannot perform its part of the computation (see below), * in which case this routine will return a null pointer. * * - The inherited getHomologyH1() routine uses only Regina's code, and * works purely within Regina's parent NTriangulation class. * Since NTriangulation knows nothing about SnapPea or fillings, * this means that any fillings on the cusps (which are * specific to SnapPea triangulations) will be ignored. * The getHomologyH1() routine will always return a solution. * * This routine uses exact arithmetic, and so you are guaranteed * that - if it returns a result at all - that this result does * not suffer from integer overflows. Essentially, the process * is this: SnapPea constructs a filled relation matrix using * machine integer arithmetic (but detects overflow and returns * \c null in such cases), and then Regina uses exact integer * arithmetic to solve for the abelian group invariants (i.e., * Smith normal form). * * The situations in which this routine might return \c null are * the following: * * - This is a null triangulation (i.e., isNull() returns \c true); * * - The filling coefficients as stored in SnapPea are integers, * but are so large that SnapPea was not able to build the * relation matrix without integer overflow. * * Note that each time the triangulation changes, the homology * group will be deleted. Thus the pointer that is returned * from this routine should not be kept for later use. Instead, * homologyFilled() should be called again; this will be * instantaneous if the group has already been calculated. * * @return the first homology group of the filled manifold, or * 0 if this could not be computed. */ const NAbelianGroup* homologyFilled() const; /** * Returns the fundamental group of the manifold with respect to * the current Dehn filling (if any). Any complete cusps (without * fillings) will be treated as though they had been truncated. * * This is different from the inherited getFundamentalGroup() routine * from the parent NTriangulation class: * * - This routine fundamentalGroupFilled() respects Dehn fillings, and * directly uses SnapPea's code to compute fundamental groups. * * - The inherited getFundamentalGroup() routine uses only Regina's * code, and works purely within Regina's parent NTriangulation class. * Since NTriangulation knows nothing about SnapPea or fillings, * this means that any fillings on the cusps (which are specific * to SnapPea triangulations) will be ignored. * * Note that each time the triangulation changes, the fundamental * group will be deleted. Thus the pointer that is returned * from this routine should not be kept for later use. Instead, * fundamentalGroupFilled() should be called again; this will be * instantaneous if the group has already been calculated. * * @param simplifyPresentation \c true if SnapPea should attempt * to simplify the group presentation, or \c false if it should * be left unsimplified. Even if \a simplifyPresentation is \c false, * this routine will always eliminate adjacent (x, x^-1) pairs. * @param fillingsMayAffectGenerators \c true if SnapPea's choice of * generators is allowed to depend on the Dehn fillings, or \c false * if the choice of generators should be consistent across different * fillings. * @param minimiseNumberOfGenerators \c true if SnapPea's group * simplification code should try to reduce the number of * generators at the expense of increasing the total length of * the relations, or \c false if it should do the opposite. * @return the fundamental group of the filled manifold, or * 0 if this could not be computed. */ const NGroupPresentation* fundamentalGroupFilled( bool simplifyPresentation = true, bool fillingsMayAffectGenerators = true, bool minimiseNumberOfGenerators = true) const; /*@}*/ /** * \name Manipulating SnapPea triangulations */ /*@{*/ /** * Constructs the canonical cell decomposition, using an * arbitrary retriangulation if this decomposition contains * non-tetrahedron cells. * * Any fillings on the cusps of this SnapPea triangulation will be * ignored for the purposes of canonisation, though they will be * copied over to the new SnapPea triangulation that is returned. * * The canonical cell decomposition is the one described in * "Convex hulls and isometries of cusped hyperbolic 3-manifolds", * Jeffrey R. Weeks, Topology Appl. 52 (1993), 127-149. * * If the canonical cell decomposition is already a triangulation then * we leave it untouched, and otherwise we triangulate it arbitrarily. * Either way, we preserve the hyperbolic structure. * * If you need a canonical triangulation (as opposed to an arbitrary * retriangulation), then you should call canonize() instead. * * The resulting triangulation will be newly allocated, and it * is the responsibility of the caller of this routine to destroy it. * * If for any reason either Regina or SnapPea are unable to * construct a triangulation of the canonical cell decomposition, * then this routine will return 0. * * \snappy The function canonize() means different * things for SnapPy versus the SnapPea kernel. Here Regina follows * the naming convention used in the SnapPea kernel. Specifically: * Regina's routine NSnapPeaTriangulation::protoCanonize() * corresponds to SnapPy's Manifold.canonize() and the * SnapPea kernel's proto_canonize(manifold). * Regina's routine NSnapPeaTriangulation::canonize() * corresponds to the SnapPea kernel's canonize(manifold), * and is not available through SnapPy at all. * * \warning The SnapPea kernel does not always compute the canonical * cell decomposition correctly. However, it guarantees that * the manifold that it does compute is homeomorphic to the original. * * @return the canonical triangulation of the canonical cell * decomposition, or 0 if this could not be constructed. */ NSnapPeaTriangulation* protoCanonize() const; /** * A synonym for protoCanonize(), which constructs the canonical * cell decomposition using an arbitrary retriangulation if necessary. * See canonize() for further details. */ NSnapPeaTriangulation* protoCanonise() const; /** * Constructs the canonical retriangulation of the canonical * cell decomposition. * * Any fillings on the cusps of this SnapPea triangulation will be * ignored. In the resulting canonical triangulation (which is * one of Regina's native NTriangulation objects, not a SnapPea * triangulation), these fillings will be completely forgotten. * * The canonical cell decomposition is the one described in * "Convex hulls and isometries of cusped hyperbolic 3-manifolds", * Jeffrey R. Weeks, Topology Appl. 52 (1993), 127-149. * * If the canonical cell decomposition is already a triangulation * then we leave it untouched. Otherwise, the canonical * retriangulation introduces internal (finite) vertices, and * is defined as follows: * * - within each 3-cell of the original complex we introduce a new * internal vertex, and cone the 3-cell boundary to this new vertex; * * - through each 2-cell of the original complex we insert the * dual edge (joining the two new finite vertices on either side), * and we replace the two cones on either side of the 2-cell with * a ring of tetrahedra surrounding this dual edge. * * See canonize_part_2.c in the SnapPea source code for details. * * This routine discards the hyperbolic structure along with all * SnapPea-specific information (such as peripheral curves and * fillings), and simply returns one of Regina's native triangulations. * If you need to preserve SnapPea-specific information then you * should call protoCanonize() instead. * * The resulting triangulation will be newly allocated, and it * is the responsibility of the caller of this routine to destroy it. * * If for any reason either Regina or SnapPea are unable to * construct the canonical retriangulation of the canonical cell * decomposition, this routine will return 0. * * \snappy The function canonize() means different * things for SnapPy versus the SnapPea kernel. Here Regina follows * the naming convention used in the SnapPea kernel. Specifically: * Regina's routine NSnapPeaTriangulation::protoCanonize() * corresponds to SnapPy's Manifold.canonize() and the * SnapPea kernel's proto_canonize(manifold). * Regina's routine NSnapPeaTriangulation::canonize() * corresponds to the SnapPea kernel's canonize(manifold), * and is not available through SnapPy at all. * * \warning The SnapPea kernel does not always compute the canonical * cell decomposition correctly. However, it guarantees that * the manifold that it does compute is homeomorphic to the original. * * @return the canonical triangulation of the canonical cell * decomposition, or 0 if this could not be constructed. */ NTriangulation* canonize() const; /** * A synonym for canonize(), which constructs the canonical * retriangulation of the canonical cell decomposition. * See canonize() for further details. */ NTriangulation* canonise() const; /** * Asks SnapPea to randomly retriangulate this manifold, using * local moves that preserve the topology. This can help when SnapPea * is having difficulty finding a hyperbolic structure. * * This routine uses SnapPea's own internal retriangulation code. * * After randomizing, this routine will immediately ask SnapPea * to try to find a hyperbolic structure. * * If this is a null SnapPea triangulation, this routine does nothing. * * \snappy In SnapPy, this routine corresponds to calling * Manifold.randomize(). */ void randomize(); /** * A synonym for randomize(), which asks SnapPea to randomly * retriangulate this manifold. See randomize() for further details. */ void randomise(); /*@}*/ /** * \name Deprecated routines */ /*@{*/ /** * Deprecated routine that verifies whether the tetrahedron face * gluings from this SnapPea triangulation match the given Regina * triangulation precisely. Any fillings on the cusps of this * SnapPea triangulation will be ignored. * * This is useful if you need to test whether SnapPea has * relabelled and/or retriangulated. * * \deprecated This routine will be removed in a future version * of Regina. Simply call NTriangulation::isIdenticalTo() instead * (though note that there is a slight change in behaviour: * isIdenticalTo() will consider a null SnapPea triangulation * identical to an empty Regina triangulation). */ bool verifyTriangulation(const NTriangulation& triangulation) const; /** * Deprecated routine to create a new Regina triangulation that * mirrors the internal SnapPea structure. Any fillings on the * cusps will be ignored. * * The resulting triangulation will be newly created, and it is the * responsibility of the caller of this routine to eventually delete it. * The packet label of the new triangulation will be the internal * SnapPea manifold name, as returned by name(). * * \deprecated This routine will be removed in a future version of * Regina. Instead, you should simply call the NTriangulation copy * constructor (since NSnapPeaTriangulation is a subclass of * NTriangulation). */ NTriangulation* toRegina() const; /** * Deprecated routine that dumps the full internal SnapPea data to * standard output, using SnapPea's file format. * * Note that the SnapPea data is written using C-style output * (i.e., using the \a stdout file pointer), which may or may not * cause unexpected behaviour when used in conjunction with * \a std::cout. * * If this triangulation does not contain any valid SnapPea data * (i.e., isNull() returns \c true), then this routine will do nothing. * * \deprecated This routine will be removed in a future version of * Regina. Instead you should simply print the string returned from * snapPea(). */ void dump() const; /** * Deprecated routine that saves the underlying triangulation as * a native SnapPea data file. * * \deprecated This routine has been renamed as saveSnapPea(). * This old routine behaves exactly as in the past, but the new * routine has a slight change in behaviour: it now requires a * non-empty filename. To send data to standard output (as in * the old routine), you can simply print the string returned from * snapPea(). See the saveSnapPea() documentation for further details. */ void saveAsSnapPea(const char* filename) const; /*@}*/ /** * \name SnapPea kernel messages */ /*@{*/ /** * Returns whether or not the SnapPea kernel writes diagnostic * messages to standard output. * * By default such diagnostic messages are disabled. To enable * them, call enableKernelMessages(). * * This routine (which interacts with static data) is thread-safe. * * @return \c true if and only if diagonstic messages are enabled. */ static bool kernelMessagesEnabled(); /** * Configures whether or not the SnapPea kernel should write * diagnostic messages to standard output. * * By default such diagnostic messages are disabled. * * This routine (which interacts with static data) is thread-safe. * * @param enabled \c true if diagnostic messages should be * enabled, or \c false otherwise. */ static void enableKernelMessages(bool enabled = true); /** * Specifies that the SnapPea kernel should not write diagnostic * messages to standard output. * * Calling this routine is equivalent to calling * enableKernelMessages(false). * * Note that diagnostic messages are already disabled by default. * * This routine (which interacts with static data) is thread-safe. */ static void disableKernelMessages(); /*@}*/ /** * \name SnapPea Input and Output */ /*@{*/ virtual std::string snapPea() const; virtual void snapPea(std::ostream& out) const; virtual bool saveSnapPea(const char* filename) const; /*@}*/ /** * \name Packet Administration */ /*@{*/ virtual void writeTextShort(std::ostream& out) const; virtual void writeTextLong(std::ostream& out) const; virtual bool dependsOnParent() const; static NXMLPacketReader* getXMLReader(NPacket* parent, NXMLTreeResolver& resolver); /*@}*/ /** * \name Packet Listener Interface */ /*@{*/ virtual void packetWasChanged(NPacket* packet); /*@}*/ protected: virtual NPacket* internalClonePacket(NPacket* parent) const; virtual void writeXMLPacketData(std::ostream& out) const; private: /** * Synchronises the inherited NTriangulation data so that the * tetrahedra and their gluings match the raw SnapPea data. * Also refreshes other internal properties and caches, * such as cusps and tetrahedron shapes. * * A change event will be fired by this routine (this will be a * "safe" change event that does not void the triangulation). * * SnapPea will be asked to recompute the hyperbolic structure * only if the current solution type is \a not_attempted. */ void sync(); /** * Like sync(), but assumes that \e only the filling coefficients * have changed, and that all other data (such as the tetrahedron * gluings, or peripheral curves on the cusps) is unchanged. * * Essentially this just extends fillingsHaveChanged() to also * fire a (safe) change event. */ void syncFillings(); /** * Clears and where necessary refreshes any properties of the * triangulation that depend only on the fillings. * * This routine assumes that the combinatorics of the triangulation * have not changed. It also assumes that SnapPea has already * called do_Dehn_filling() (so this routine will not call it again). */ void fillingsHaveChanged(); /** * Copies the given SnapPea triangulation into the given Regina * triangulation. Any fillings on the cusps will be ignored; * the Regina triangulation will simply copy the raw * combinatorial data of the triangulation, and nothing more. * * \pre The SnapPea triangulation \a src is non-null. * \pre The Regina triangulation \a dest is empty. * * @param src the SnapPea triangulation to copy from. * @param dest the destination Regina triangulation. */ static void fillRegina(regina::snappea::Triangulation* src, NTriangulation& dest); /** * Resets the internal SnapPea data to the given SnapPea triangulation. * This object will take ownership of the given SnapPea data. * * @param data the new SnapPea data for this object. */ void reset(regina::snappea::Triangulation* data); friend class regina::NXMLSnapPeaReader; }; /*@}*/ // Inline functions for SnapPeaFatalError inline SnapPeaFatalError::SnapPeaFatalError( const char* fromFunction, const char* fromFile) : function(fromFunction), file(fromFile) { } // Inline functions for NCusp inline NCusp::~NCusp() { } inline NCusp::NCusp() { } inline NVertex* NCusp::vertex() const { return vertex_; } inline bool NCusp::complete() const { return (m_ == 0 && l_ == 0); } inline int NCusp::m() const { return m_; } inline int NCusp::l() const { return l_; } // Inline functions for NSnapPeaTriangulation inline NSnapPeaTriangulation::NSnapPeaTriangulation() : data_(0), shape_(0), cusp_(0), filledCusps_(0), syncing_(false) { listen(this); } inline bool NSnapPeaTriangulation::isNull() const { return (data_ == 0); } inline const std::complex& NSnapPeaTriangulation::shape(unsigned tet) const { return (shape_ ? shape_[tet] : zero_); } inline unsigned NSnapPeaTriangulation::countCusps() const { return getNumberOfBoundaryComponents(); } inline unsigned NSnapPeaTriangulation::countCompleteCusps() const { return getNumberOfBoundaryComponents() - filledCusps_; } inline unsigned NSnapPeaTriangulation::countFilledCusps() const { return filledCusps_; } inline const NCusp* NSnapPeaTriangulation::cusp(unsigned whichCusp) const { return (cusp_ ? cusp_ + whichCusp : 0); } inline bool NSnapPeaTriangulation::dependsOnParent() const { return false; } inline NSnapPeaTriangulation* NSnapPeaTriangulation::protoCanonise() const { return protoCanonize(); } inline NTriangulation* NSnapPeaTriangulation::canonise() const { return canonize(); } inline void NSnapPeaTriangulation::randomise() { randomize(); } inline NPacket* NSnapPeaTriangulation::internalClonePacket(NPacket*) const { return new NSnapPeaTriangulation(*this); } #endif // EXCLUDE_SNAPPEA } // namespace regina #endif regina-4.96/engine/snappea/nxmlsnappeareader.cpp000644 000765 000024 00000006571 12377776650 021756 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "snappea/nsnappeatriangulation.h" #include "snappea/nxmlsnappeareader.h" #include "snappea/kernel/unix_file_io.h" namespace regina { void NXMLSnapPeaReader::endContentSubElement( const std::string& subTagName, NXMLElementReader* subReader) { if (subTagName == "snappea") { if (snappea_->data_) { // We can't have two .. blocks. return; } try { regina::snappea::Triangulation* data = regina::snappea::read_triangulation_from_string( dynamic_cast(subReader)->getChars().c_str()); if (data) { regina::snappea::find_complete_hyperbolic_structure(data); regina::snappea::do_Dehn_filling(data); snappea_->reset(data); } } catch (regina::SnapPeaFatalError& err) { if (snappea_->data_) snappea_->reset(0); } } } NXMLPacketReader* NSnapPeaTriangulation::getXMLReader(NPacket*, NXMLTreeResolver& resolver) { return new NXMLSnapPeaReader(resolver); } } // namespace regina regina-4.96/engine/snappea/nxmlsnappeareader.h000644 000765 000024 00000010101 12377775406 021401 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file snappea/nxmlsnappeareader.h * \brief Deals with parsing XML data for SnapPea triangulations. */ #ifndef __NXMLSNAPPEAREADER_H #ifndef __DOXYGEN #define __NXMLSNAPPEAREADER_H #endif #include "regina-core.h" #include "packet/nxmlpacketreader.h" #include "snappea/nsnappeatriangulation.h" namespace regina { /** * \weakgroup snappea * @{ */ /** * An XML packet reader that reads a single SnapPea triangulation. * * \ifacespython Not present. */ class REGINA_API NXMLSnapPeaReader : public NXMLPacketReader { private: NSnapPeaTriangulation* snappea_; /**< The SnapPea triangulation currently being read. */ public: /** * Creates a new SnapPea triangulation reader. * * @param resolver the master resolver that will be used to fix * dangling packet references after the entire XML file has been read. */ NXMLSnapPeaReader(NXMLTreeResolver& resolver); virtual NPacket* getPacket(); virtual NXMLElementReader* startContentSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict& subTagProps); virtual void endContentSubElement(const std::string& subTagName, NXMLElementReader* subReader); }; /*@}*/ // Inline functions for NXMLSnapPeaReader inline NXMLSnapPeaReader::NXMLSnapPeaReader(NXMLTreeResolver& resolver) : NXMLPacketReader(resolver), snappea_(new NSnapPeaTriangulation()) { } inline NPacket* NXMLSnapPeaReader::getPacket() { return snappea_; } inline NXMLElementReader* NXMLSnapPeaReader::startContentSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict&) { if (subTagName == "snappea") return new NXMLCharsReader(); else return new NXMLElementReader(); } } // namespace regina #endif regina-4.96/engine/snappea/snappy/CMakeLists.txt000644 000765 000024 00000000745 12377774107 021603 0ustar00babstaff000000 000000 # Files to compile SET ( FILES snappy_gluing_equations ) # Prepend folder name FOREACH ( SOURCE_FILE ${FILES} ) SET ( SOURCES ${SOURCES} snappea/snappy/${SOURCE_FILE}) SET ( SOURCES_C_AS_CPP ${SOURCES_C_AS_CPP} snappea/snappy/${SOURCE_FILE}) ENDFOREACH(SOURCE_FILE) # Set the variable in the parent directory SET(SOURCES ${SOURCES} PARENT_SCOPE) SET(SOURCES_C_AS_CPP ${SOURCES_C_AS_CPP} PARENT_SCOPE) # Snappy headers should not be shipped: these are for internal use only. regina-4.96/engine/snappea/snappy/README.txt000644 000765 000024 00000001152 12400001703 020476 0ustar00babstaff000000 000000 Code from SnapPy ---------------- This directory contains additional code from SnapPy that is not included in the SnapPea kernel. This code is currently synced with SnapPy version 2.2 (26 Jun 2014). SnapPy is distributed under the terms of the GNU General Public License, version 2 or any later version, as published by the Free Software Foundation. The full text of this license can be found in the file LICENSE.txt in Regina's top-level source directory. M. Culler, N. M. Dunfield, and J. R. Weeks. SnapPy, a computer program for studying the geometry and topology of 3-manifolds, http://snappy.computop.org . regina-4.96/engine/snappea/snappy/regina.patch000644 000765 000024 00000000624 12311266525 021311 0ustar00babstaff000000 000000 --- a/engine/snappea/snappy/snappy_gluing_equations.c +++ b/engine/snappea/snappy/snappy_gluing_equations.c @@ -38,7 +38,7 @@ int** get_gluing_equations(Triangulation *manifold, int* num_rows, int* num_cols) { - int *eqn, i, T, num_edges, num_eqns, eqn_index; + int *eqn, i, T, num_eqns, eqn_index; int **eqns; EdgeClass *edge; PositionedTet ptet0, ptet; regina-4.96/engine/snappea/snappy/SnapPy.h000644 000765 000024 00000001242 12377774107 020417 0ustar00babstaff000000 000000 /** * Headers for additional SnapPy code that is not shipped with the * SnapPea kernel. */ #ifndef _SnapPy_ #define _SnapPy_ #include "../kernel/SnapPea.h" #include "../kernel/kernel_namespace.h" /* Prototypes for functions defined in gluing_equations.c */ extern int** get_gluing_equations(Triangulation* manifold, int* num_rows, int* num_cols); extern void free_gluing_equations(int** equations, int num_rows); extern int* get_cusp_equation(Triangulation* manifold, int cusp_num, int m, int l, int* num_rows); extern void free_cusp_equation(int* equation); #include "../kernel/end_namespace.h" #endif regina-4.96/engine/snappea/snappy/snappy_gluing_equations.c000644 000765 000024 00000006775 12377774107 024167 0ustar00babstaff000000 000000 #include "../kernel/kernel.h" #include "../kernel/kernel_namespace.h" /* * This file was originally named "gluing_equations.c" when distributed with * SnapPy, but has been renamed here to avoid conflict. * * SnapPy, and this file as a result, is licensed under the GNU General Public * License. * * M. Culler, N. M. Dunfield, and J. R. Weeks. * SnapPy, a computer program for studying the geometry and * topology of 3-manifolds, http://snappy.computop.org * * */ /* Returns a matrix with rows of the form a b c d e f ... which means a*log(z0) + b*log(1/(1-z0)) + c*log((z0-1)/z) + d*log(z1) +... = 2 pi i for an edge equation, and (same) = 1 for a cusp equation. In terms of the tetrahedra, a is the invariant of the edge (2,3), b the invariant of the edge (0,2) and c is the invariant of the edge (1,2). See kernel_code/edge_classes.c for a detailed account of the convention. */ int** get_gluing_equations(Triangulation *manifold, int* num_rows, int* num_cols) { int *eqn, i, T, num_eqns, eqn_index; int **eqns; EdgeClass *edge; PositionedTet ptet0, ptet; T = manifold -> num_tetrahedra; num_eqns = 0; for ( edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) num_eqns++; eqns = NEW_ARRAY(num_eqns, int*); for (i = 0; i < num_eqns; i ++) eqns[i] = NEW_ARRAY(3*T, int); /* * Build edge equations. */ eqn_index = 0; for ( edge = manifold->edge_list_begin.next; edge != &manifold->edge_list_end; edge = edge->next) { eqn = eqns[eqn_index]; for (i = 0; i < 3 * T; i++) eqn[i] = 0; set_left_edge(edge, &ptet0); ptet = ptet0; do{ eqn[3*ptet.tet->index + edge3_between_faces[ptet.near_face][ptet.left_face]]++; veer_left(&ptet); } while (same_positioned_tet(&ptet, &ptet0) == FALSE); eqn_index++; } *num_rows = num_eqns; *num_cols = 3*T; return eqns; } void free_gluing_equations(int** equations, int num_rows){ int i; for (i = 0; i < num_rows; i++) my_free(equations[i]); my_free(equations); } /* computes the cusp equation the curve (merid)^m (long)^l * in cusp cusp_num. See get_gluing_equations for the return * convention. */ int* get_cusp_equation(Triangulation* manifold, int cusp_num, int m, int l, int* num_rows) { int *eqn, i, coef[2], T; Tetrahedron *tet; VertexIndex v; Cusp *cusp; FaceIndex f, ff; PeripheralCurve c; /* initialize variables */ coef[0] = m; coef[1] = l; T = manifold -> num_tetrahedra; eqn = NEW_ARRAY(3 * T, int); for (i = 0; i < 3 * T; i++) eqn[i] = 0; /* find right cusp */ cusp = manifold->cusp_list_begin.next; for (i = 0; i < cusp_num; i++ ) cusp = cusp->next; /* compute equation */ for (tet = manifold->tet_list_begin.next; tet != &manifold->tet_list_end; tet = tet->next){ for (v = 0; v < 4; v++){ if (tet->cusp[v] != cusp) continue; for (f = 0; f < 4; f++){ if (f == v) continue; ff = remaining_face[v][f]; for (c = 0; c < 2; c++) /* c = M, L */ eqn[3*tet->index + edge3_between_faces[f][ff]] += coef[c] *FLOW(tet->curve[c][right_handed][v][f], tet->curve[c][right_handed][v][ff]); } } } *num_rows = 3*T; return eqn; } void free_cusp_equation(int* equation){ my_free(equation); } #include "../kernel/end_namespace.h" regina-4.96/engine/snappea/uimessages.cpp000644 000765 000024 00000007722 12377776650 020411 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include "snappea/nsnappeatriangulation.h" #include "snappea/kernel/SnapPea.h" bool regina::NSnapPeaTriangulation::kernelMessages_ = false; namespace regina { namespace snappea { /** * Supply bare-bones UI messaging functions for the SnapPea kernel to use. * * See snappea/kernel/SnapPea.h for details on what each function should do. */ void uAcknowledge(const char *message) { if (regina::NSnapPeaTriangulation::kernelMessagesEnabled()) std::cout << message << std::endl; } int uQuery(const char *message, const int num_responses, const char *responses[], const int default_response) { if (regina::NSnapPeaTriangulation::kernelMessagesEnabled()) { std::cout << message << std::endl; for (int i = 0; i < num_responses; i++) { std::cout << i << ". " << responses[i] << std::endl; } std::cout << "Responding with default (" << default_response << ')' << std::endl; } return default_response; } void uFatalError(const char *function, const char *file) { std::cerr << "FATAL ERROR: " << file << ", " << function << std::endl; throw regina::SnapPeaFatalError(function, file); } void uAbortMemoryFull(void) { std::cerr << "FATAL ERROR: Available memory has been exhausted." << std::endl; throw regina::SnapPeaMemoryFull(); } void uPrepareMemFullMessage() { // Do nothing for now. } void uLongComputationBegins(const char *message, Boolean /* is_abortable */) { if (regina::NSnapPeaTriangulation::kernelMessagesEnabled()) std::cout << message << std::endl; } FuncResult uLongComputationContinues() { return func_OK; } void uLongComputationEnds() { } } } // namespaces regina-4.96/engine/split/CMakeLists.txt000644 000765 000024 00000000751 12311266525 017756 0ustar00babstaff000000 000000 # split # Files to compile SET ( FILES nsigcensus nsigisomorphism nsignature ) # Prepend folder name FOREACH ( SOURCE_FILE ${FILES} ) SET ( SOURCES ${SOURCES} split/${SOURCE_FILE}) ENDFOREACH(SOURCE_FILE) # Set the variable in the parent directory SET( SOURCES ${SOURCES} PARENT_SCOPE) if (${REGINA_INSTALL_DEV}) INSTALL(FILES nsigcensus.h nsigisomorphism.h nsignature.h DESTINATION ${INCLUDEDIR}/split COMPONENT Development) endif (${REGINA_INSTALL_DEV}) regina-4.96/engine/split/nsigcensus.cpp000644 000765 000024 00000022372 12377776651 020130 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "split/nsigcensus.h" #include "utilities/memutils.h" namespace regina { unsigned long formSigCensus(unsigned order, UseSignature use, void* useArgs) { NSigCensus census(order, use, useArgs); census.run(0); return census.totalFound; } void* NSigCensus::run(void*) { // Initialisations. sig.nCycles = 0; sig.nCycleGroups = 0; nextLabel = 0; std::fill(used, used + sig.order, 0); totalFound = 0; // Try creating a first cycle. extendAutomorphisms(); for (unsigned i = 2 * sig.order; i > 0; i--) tryCycle(i, true, 0); clearTopAutomorphisms(); return 0; } void NSigCensus::clearTopAutomorphisms() { if (! automorph[sig.nCycleGroups].empty()) { for_each(automorph[sig.nCycleGroups].begin(), automorph[sig.nCycleGroups].end(), FuncDelete()); automorph[sig.nCycleGroups].clear(); } } bool NSigCensus::extendAutomorphisms() { if (sig.nCycleGroups == 0) { automorph[0].push_back(new NSigPartialIsomorphism(1)); automorph[0].push_back(new NSigPartialIsomorphism(-1)); return true; } NSigPartialIsomorphism* iso; unsigned firstLabel; int result; unsigned i; std::list::const_iterator it; for (it = automorph[sig.nCycleGroups - 1].begin(); it != automorph[sig.nCycleGroups - 1].end(); it++) { // Try extending this automorphism. iso = new NSigPartialIsomorphism(**it, nextLabel, sig.nCycles); firstLabel = (*it)->nLabels; if (firstLabel == nextLabel) { iso->makeCanonical(sig, sig.nCycleGroups - 1); result = iso->compareWith(sig, 0, sig.nCycleGroups - 1); if (result == 0) automorph[sig.nCycleGroups].push_back(iso); else { delete iso; if (result < 0) return false; } } else { for (i = firstLabel; i < nextLabel; i++) iso->labelImage[i] = i; do { iso->makeCanonical(sig, sig.nCycleGroups - 1); result = iso->compareWith(sig, 0, sig.nCycleGroups - 1); if (result < 0) { delete iso; return false; } else if (result == 0) automorph[sig.nCycleGroups].push_back( new NSigPartialIsomorphism(*iso)); } while (std::next_permutation(iso->labelImage + firstLabel, iso->labelImage + nextLabel)); delete iso; } } return true; } void NSigCensus::tryCycle(unsigned cycleLen, bool newCycleGroup, unsigned startPos) { // Are we finished? if (startPos == 2 * sig.order) { totalFound++; use(sig, automorph[sig.nCycleGroups], useArgs); return; } // Prepare the signature for the forthcoming cycle. sig.nCycles++; if (newCycleGroup) sig.nCycleGroups++; // Insert the cycleStart sentinel. unsigned endPos = startPos + cycleLen; sig.cycleStart[sig.nCycles] = endPos; // We won't insert the cycleGroupStart sentinel until we know where // the group will finish. // Generate all possibilities for this cycle. unsigned tryPos = startPos; sig.label[tryPos] = 0; unsigned lowerBnd, upperBnd; bool avoid; unsigned i; while(true) { if (tryPos == endPos) { // Found a complete cycle. avoid = false; if (startPos == 0 && used[sig.label[startPos]] == 2) { // We run the risk of having a cycle that could be // made lexicographically smaller simply by rotating it. i = 1; while (sig.label[startPos + i] != sig.label[startPos]) i++; if (NSignature::cycleCmp(sig, sig.nCycles - 1, 0, 1, 0, sig, sig.nCycles - 1, i, 1, 0) > 0) avoid = true; } if (! avoid) { if (endPos == 2 * sig.order) { // Found a complete cycle set. sig.cycleGroupStart[sig.nCycleGroups] = sig.nCycles; if (extendAutomorphisms()) tryCycle(0, true, endPos); clearTopAutomorphisms(); } else { // Move on to create the next cycle. // The next cycle will have length i. if (endPos + cycleLen <= 2 * sig.order) tryCycle(cycleLen, false, endPos); sig.cycleGroupStart[sig.nCycleGroups] = sig.nCycles; if (extendAutomorphisms()) for (i = (endPos + cycleLen - 1 <= 2 * sig.order ? cycleLen - 1 : 2 * sig.order - endPos); i > 0; i--) tryCycle(i, true, endPos); clearTopAutomorphisms(); } } // Step back again. tryPos--; used[sig.label[tryPos]]--; if (sig.label[tryPos] == nextLabel - 1 && used[sig.label[tryPos]] == 0) nextLabel--; sig.label[tryPos]++; } else { // Find the next viable possibility for this position. if (tryPos == startPos) { if (newCycleGroup) lowerBnd = 0; else lowerBnd = sig.label[startPos - cycleLen]; upperBnd = (startPos == 0 ? 1 : nextLabel); } else { lowerBnd = (startPos == 0 ? sig.label[startPos] : sig.label[startPos] + 1); upperBnd = nextLabel + 1; } if (upperBnd >= sig.order) upperBnd = sig.order; if (sig.label[tryPos] < lowerBnd) sig.label[tryPos] = lowerBnd; while (sig.label[tryPos] < upperBnd) { if (used[sig.label[tryPos]] < 2) break; sig.label[tryPos]++; } if (sig.label[tryPos] >= upperBnd) { // We've run out of ideas for this position. // Step back and undo the previous position. if (tryPos == startPos) break; tryPos--; used[sig.label[tryPos]]--; if (sig.label[tryPos] == nextLabel - 1 && used[sig.label[tryPos]] == 0) nextLabel--; sig.label[tryPos]++; } else { // We've found a value to try. used[sig.label[tryPos]]++; if (sig.label[tryPos] == nextLabel) nextLabel++; tryPos++; sig.label[tryPos] = 0; } } } sig.nCycles--; if (newCycleGroup) sig.nCycleGroups--; } } // namespace regina regina-4.96/engine/split/nsigcensus.h000644 000765 000024 00000021126 12377775413 017564 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file split/nsigcensus.h * \brief Deals with forming a census of splitting surface signatures. */ #ifndef __NSIGCENSUS_H #ifndef __DOXYGEN #define __NSIGCENSUS_H #endif #include #include "regina-core.h" #include "split/nsignature.h" #include "split/nsigisomorphism.h" namespace regina { /** * \weakgroup split * @{ */ /** * A list of partial isomorphisms on splitting surface signatures. */ typedef std::list NSigIsoList; /** * A routine used to do arbitrary processing upon a splitting surface * signature and its automorphisms. Such routines are used to process * signatures found when running a signature census. * * The first parameter passed should be a splitting surface signature. * The second parameter should be a list of all automorphisms of this signature. * The third parameter may contain arbitrary data as passed to * formSigCensus(). */ typedef void (*UseSignature)(const NSignature&, const NSigIsoList&, void *); /** * Forms a census of all splitting surface signatures of the given order. * The order of a signature is the number of quads in the corresponding * splitting surface. * * Each signature will be produced precisely once up to equivalence. * Signatures are considered equivalent if they are related by some * combination of: * - relabelling symbols; * - rotating an individual cycle; * - inverting an individual cycle (i.e., reversing the cycle and * changing the case of each symbol in the cycle); * - reversing all cycles without changing the case of any symbols. * * Each signature produced will have its cycles ordered by decreasing * length. Each cycle will have at least half of its symbols lower-case. * * For each signature that is generated, routine \a use (as passed to this * function) will be called with that signature and its automorphisms as * arguments. * * \warning Currently upper-case symbols in signatures are not supported * by this routine; only signatures whose symbols are all lower-case will * be produced. * * \todo \feature Add support for symbols of differing case. * * \ifacespython Not present. * * @param order the order of signatures to generate. * @param use the function to call upon each signature that is found. * The first parameter passed to this function will be a splitting * surface signature. The second parameter will be a list of all its * automorphisms. The third parameter will be parameter \a useArgs as * was passed to this routine. * @param useArgs the pointer to pass as the final parameter for the * function \a use which will be called upon each signature found. * @return the total number of non-equivalent signatures that were found. */ REGINA_API unsigned long formSigCensus(unsigned order, UseSignature use, void* useArgs = 0); /** * A utility class used by formSigCensus(). Other routines should never * refer to this class directly. It is used to store temporary * information when forming the census. * * \ifacespython Not present. */ class REGINA_API NSigCensus { private: NSignature sig; /**< The signature being constructed. */ unsigned nextLabel; /**< The first symbol that has not yet been used. */ unsigned* used; /**< The number of times each symbol has been used so far. */ NSigIsoList* automorph; /**< List automorph[k] represents all automorphisms of the first \a k cycle groups of the partially formed signature. */ UseSignature use; /**< The argument passed to formSigCensus(). */ void* useArgs; /**< The argument passed to formSigCensus(). */ unsigned long totalFound; /**< The total number of signatures found so far. */ public: /** * Deallocates any memory used specifically by this structure. */ ~NSigCensus(); /** * Runs a complete signature census generation. At most one * copy of this routine should be running at any given time for * a particular NSigCensus. * * @param param this parameter is ignored. * @return 0. */ void* run(void* param); private: /** * Creates a new structure to form a signature census. * All parameters not explained are taken directly from * formSigCensus(). * * \pre order is at least 1. */ NSigCensus(unsigned order, UseSignature newUse, void* newUseArgs); /** * Empty the list automorph[sig.nCycleGroups] and * destroy the corresponding partial isomorphisms. */ void clearTopAutomorphisms(); /** * Extend the automorphisms in list * automorph[sig.nCycleGroups - 1] to form the * automorphisms in list automorph[sig.nCycleGroups]. * * If in the processing of extending these automorphisms it is * discovered that the partial signature sig is not in * canonical form, \c false will be returned and the contents of * list automorph[sig.nCycleGroups] will be undefined. * * @return \c true if and only if it was confirmed during * processing that the partial signature sig is in * canonical form. */ bool extendAutomorphisms(); /** * Extends the partial signature created so far to add a new * cycle. * * @param cycleLen the length of the new cycle to add. * @param newCycleGroup \c true if and only if the new cycle * begins a new cycle group. * @param startPos the position within the list of symbols * that make up the signature at which the new cycle will begin. */ void tryCycle(unsigned cycleLen, bool newCycleGroup, unsigned startPos); friend unsigned long formSigCensus(unsigned order, UseSignature use, void* useArgs); }; /*@}*/ // Inline functions for NSigCensus inline NSigCensus::NSigCensus(unsigned order, UseSignature newUse, void* newUseArgs) : sig(order), used(new unsigned[order]), automorph(new NSigIsoList[order + 2]), use(newUse), useArgs(newUseArgs) { } inline NSigCensus::~NSigCensus() { delete[] used; delete[] automorph; } } // namespace regina #endif regina-4.96/engine/split/nsigisomorphism.cpp000644 000765 000024 00000015046 12377776652 021202 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "split/nsigisomorphism.h" namespace regina { NSigPartialIsomorphism::NSigPartialIsomorphism( const NSigPartialIsomorphism& iso) : nLabels(iso.nLabels), nCycles(iso.nCycles), labelImage(iso.nLabels ? new unsigned[iso.nLabels] : 0), cyclePreImage(iso.nCycles ? new unsigned[iso.nCycles] : 0), cycleStart(iso.nCycles ? new unsigned[iso.nCycles] : 0), dir(iso.dir) { if (iso.nLabels) std::copy(iso.labelImage, iso.labelImage + iso.nLabels, labelImage); if (iso.nCycles) { std::copy(iso.cyclePreImage, iso.cyclePreImage + iso.nCycles, cyclePreImage); std::copy(iso.cycleStart, iso.cycleStart + iso.nCycles, cycleStart); } } NSigPartialIsomorphism::NSigPartialIsomorphism( const NSigPartialIsomorphism& base, unsigned newLabels, unsigned newCycles) : nLabels(newLabels), nCycles(newCycles), labelImage(newLabels ? new unsigned[newLabels] : 0), cyclePreImage(newCycles ? new unsigned[newCycles] : 0), cycleStart(newCycles ? new unsigned[newCycles] : 0), dir(base.dir) { if (base.nLabels) std::copy(base.labelImage, base.labelImage + base.nLabels, labelImage); if (base.nCycles) { std::copy(base.cyclePreImage, base.cyclePreImage + base.nCycles, cyclePreImage); std::copy(base.cycleStart, base.cycleStart + base.nCycles, cycleStart); } } void NSigPartialIsomorphism::makeCanonical(const NSignature& sig, unsigned fromCycleGroup) { unsigned fromCycle, toCycle; unsigned c, i; unsigned cycleLen; unsigned start1, start2; // Deal with each cycle group separately. for ( ; sig.cycleGroupStart[fromCycleGroup] < nCycles; fromCycleGroup++) { fromCycle = sig.cycleGroupStart[fromCycleGroup]; toCycle = sig.cycleGroupStart[fromCycleGroup + 1]; if (toCycle > nCycles) toCycle = nCycles; if (fromCycle >= toCycle) continue; // Determine where each cycle should start. cycleLen = sig.cycleStart[fromCycle + 1] - sig.cycleStart[fromCycle]; for (c = fromCycle; c < toCycle; c++) { start1 = start2 = cycleLen; for (i = 0; i < cycleLen; i++) if (start1 == cycleLen || labelImage[sig.label[sig.cycleStart[c] + i]] < labelImage[sig.label[sig.cycleStart[c] + start1]]) { start1 = i; start2 = cycleLen; } else if (labelImage[sig.label[sig.cycleStart[c] + i]] == labelImage[sig.label[sig.cycleStart[c] + start1]]) start2 = i; if (start2 == cycleLen) cycleStart[c] = start1; else { // Two possible starting points; we must choose between them. if (NSignature::cycleCmp(sig, c, start1, dir, labelImage, sig, c, start2, dir, labelImage) <= 0) cycleStart[c] = start1; else cycleStart[c] = start2; } } // At this point we now know where each cycle starts under the new // labelling. It's now time to determine in which order the cycles // should be presented. for (c = fromCycle; c < toCycle; c++) cyclePreImage[c] = c; std::sort(cyclePreImage + fromCycle, cyclePreImage + toCycle, ShorterCycle(sig, *this)); } } int NSigPartialIsomorphism::compareWith(const NSignature& sig, const NSigPartialIsomorphism* other, unsigned fromCycleGroup) const { int result; for (unsigned c = sig.cycleGroupStart[fromCycleGroup]; c < nCycles; c++) { if (other) result = NSignature::cycleCmp(sig, cyclePreImage[c], cycleStart[cyclePreImage[c]], dir, labelImage, sig, other->cyclePreImage[c], other->cycleStart[other->cyclePreImage[c]], other->dir, other->labelImage); else result = NSignature::cycleCmp(sig, cyclePreImage[c], cycleStart[cyclePreImage[c]], dir, labelImage, sig, c, 0, 1, 0); if (result < 0) return -1; if (result > 0) return 1; } return 0; } } // namespace regina regina-4.96/engine/split/nsigisomorphism.h000644 000765 000024 00000027241 12377775414 020642 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file split/nsigisomorphism.h * \brief Deals with full and partial isomorphisms of splitting surface * signatures. */ #ifndef __NSIGISOMORPHISM_H #ifndef __DOXYGEN #define __NSIGISOMORPHISM_H #endif #include "regina-core.h" #include "split/nsignature.h" namespace regina { /** * \weakgroup split * @{ */ /** * Represents a partial isomorphism between two splitting surface * signatures. See class NSignature for details on splitting surface * signatures. * * The two signatures related by this partial isomorphism must have the * same cycle structure, i.e., the same number of cycle groups and the * same cycle length and number of cycles within each cycle group. * * The partial isomorphism maps symbols to symbols and cycles to cycles, * with the option of rotating some cycles and/or reversing all cycles in * the process. * Cycles within the kth cycle group of the source signature * must map to cycles within the kth cycle group of the * destination signature. * * A \e partial isomorphism is only required to map the cycles * and symbols found in the first g cycle groups of the * source isomorphism (for some g). If only a subset of symbols * are mapped, that subset must be symbols 0,1,...,k for some k. * * \ifacespython Not present. */ class REGINA_API NSigPartialIsomorphism { private: unsigned nLabels; /**< The number of symbols whose images are defined. */ unsigned nCycles; /**< The number of cycles whose images are defined. */ unsigned* labelImage; /**< Stores the image of each symbol. */ unsigned* cyclePreImage; /**< Stores the preimage of each cycle. */ unsigned* cycleStart; /**< Allows a cycle to be rotated: cycleStart[k] is the position in original cycle \a k where the image cycle begins. */ int dir; /**< Positive if all cycles keep their original direction, negative if all cycles are reversed. */ public: /** * Creates a new partial isomorphism that maps no cycles or * symbols. This empty isomorphism is designed to be extended * at some later point. * * @param newDir positive if this isomorphism specifies that all * cycles are reversed, or negative if this isomorphism specifies * that all cycles keep their original direction. */ NSigPartialIsomorphism(int newDir); /** * Creates a new partial isomorphism that is a clone of the given * partial isomorphism. * * @param iso the partial isomorphism to clone. */ NSigPartialIsomorphism(const NSigPartialIsomorphism& iso); /** * Destroys this partial isomorphism. */ ~NSigPartialIsomorphism(); /** * Rearranges the cycle images so that this isomorphism when * applied to the given signature produces a new signature that * is in canonical form. * * The result of this routine is dependent upon the symbol map * defined by this isomorphism (this symbol map will not be changed). * * @param sig the signature to which this isomorphism will be applied. * @param fromCycleGroup the first cycle group whose images may * be rearranged. If it is already known that the cycle images for * the first \a k cycle groups are correct, \a k should be passed * in this parameter. This parameter should not exceed the * number of cycle groups whose cycles are mapped by this partial * isomorphism. */ void makeCanonical(const NSignature& sig, unsigned fromCycleGroup = 0); /** * Lexicographically compares the results of applying this and * the given isomorphism to the given signature. * * Comparisons are done on a cycle-by-cycle basis; comparisons * within a cycle are done as described by NSignature::cycleCmp(). * Comparison will not proceed beyond the cycles mapped by this * partial isomorphism. * * \pre the given partial isomorphism maps at least as many * cycles and symbols as this partial isomorphism. * * @param sig the signature to which both this and the given * isomorphism will be applied. * @param other the isomorphism to compare with this isomorphism. * @param fromCycleGroup the first cycle group whose images should * be examined. If it is already known that the cycle images for * the first \a k cycle groups are identical under both * isomorphisms, \a k should be passed in this parameter. * This parameter should not exceed the number of cycle groups * whose cycles are mapped by this partial isomorphism. * * @return -1, 1 or 0 if the image of the given signature under * this isomorphism is lexicographically less than, greater than * or equal to its image under the given isomorphism respectively. */ int compareWith(const NSignature& sig, const NSigPartialIsomorphism* other, unsigned fromCycleGroup = 0) const; private: /** * Creates a new partial isomorphism that is an extension of the * given partial isomorphism. * * The portion of the new isomorphism matching the given isomorphism * will be initialised; the remainder of the new isomorphism will * remain uninitialised. * * @param base the partial isomorphism to be extended. * @param newLabels the number of symbols that the new * isomorphism will map; this must be at least as large as the * number of symbols mapped by the given isomorphism. * @param newCycles the number of cycles that the new * isomorphism will map; this must be at least as large as the * number of cycles mapped by the given isomorphism. */ NSigPartialIsomorphism(const NSigPartialIsomorphism& base, unsigned newLabels, unsigned newCycles); /** * A comparison function for use with the Standard Template * Library. * * This function determines whether the image of one cycle is * less than the image of another under the given fixed isomorphism * when applied to the given fixed signature. Cycle comparison is * done using NSignature::cycleCmp(). * * It is irrelevant which cycle is mapped to appear before the other * in the sequence of cycles belonging to the image signature. */ struct ShorterCycle { const NSignature& sig; /**< The signature containing the cycles to examine. */ const NSigPartialIsomorphism& iso; /**< The isomorphism to apply to the cycles before they are compared. */ /** * Creates a new comparison function. * * @param newSig the signature containing the cycles that * this function will examine. * @param newIso the partial isomorphism to apply to the cycles * before they are compared. */ ShorterCycle(const NSignature& newSig, const NSigPartialIsomorphism& newIso); /** * Determines whether the image of one cycle is * lexicographically less than the image of another. * See the class notes for further details on how this * comparison is done. * * @param cycle1 the index of the first cycle to examine; * this must be less than the total number of cycles mapped * by the isomorphism concerned and less than the total number * of cycles in the signature concerned. * @param cycle2 the index of the second cycle to examine; * this must be less than the total number of cycles mapped * by the isomorphism concerned and less than the total number * of cycles in the signature concerned. * @return \c true if and only if the image of the first * cycle is less than the image of the second cycle. */ bool operator () (unsigned cycle1, unsigned cycle2) const; }; friend struct NSigPartialIsomorphism::ShorterCycle; friend class regina::NSigCensus; }; /*@}*/ // Inline functions for NSigPartialIsomorphism inline NSigPartialIsomorphism::NSigPartialIsomorphism(int newDir) : nLabels(0), nCycles(0), labelImage(0), cyclePreImage(0), cycleStart(0), dir(newDir) { } inline NSigPartialIsomorphism::~NSigPartialIsomorphism() { if (labelImage) delete[] labelImage; if (cyclePreImage) delete[] cyclePreImage; if (cycleStart) delete[] cycleStart; } inline NSigPartialIsomorphism::ShorterCycle::ShorterCycle( const NSignature& newSig, const NSigPartialIsomorphism& newIso) : sig(newSig), iso(newIso) { } inline bool NSigPartialIsomorphism::ShorterCycle::operator () (unsigned cycle1, unsigned cycle2) const { return (NSignature::cycleCmp(sig, cycle1, iso.cycleStart[cycle1], iso.dir, iso.labelImage, sig, cycle2, iso.cycleStart[cycle2], iso.dir, iso.labelImage) < 0); } } // namespace regina #endif regina-4.96/engine/split/nsignature.cpp000644 000765 000024 00000023703 12377776656 020132 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include "split/nsignature.h" #include "triangulation/ntriangulation.h" #include "utilities/memutils.h" namespace regina { namespace { NPerm4 exitFace(bool firstOccurrence, bool lowerCase) { if (firstOccurrence) { if (lowerCase) return NPerm4(2,3,1,0); else return NPerm4(2,3,0,1); } else { if (lowerCase) return NPerm4(0,1,3,2); else return NPerm4(0,1,2,3); } } } NSignature::NSignature(const NSignature& sig) : ShareableObject(), order(sig.order), label(new unsigned[2 * sig.order]), labelInv(new bool[2 * sig.order]), nCycles(sig.nCycles), cycleStart(new unsigned[sig.nCycles + 1]), nCycleGroups(sig.nCycleGroups), cycleGroupStart(new unsigned[sig.nCycleGroups + 1]) { std::copy(sig.label, sig.label + 2 * sig.order, label); std::copy(sig.labelInv, sig.labelInv + 2 * sig.order, labelInv); std::copy(sig.cycleStart, sig.cycleStart + sig.nCycles + 1, cycleStart); std::copy(sig.cycleGroupStart, sig.cycleGroupStart + sig.nCycleGroups + 1, cycleGroupStart); } NSignature* NSignature::parse(const std::string& str) { // See if the string looks correctly formed. // Note that we're not yet counting the individual frequency of each // letter, just the overall number of letters. // Cycles are assumed to be separated by any non-space // non-alphabetic characters. unsigned nAlpha = 0; int largestLetter = -1; size_t len = str.length(); size_t pos; for (pos = 0; pos < len; pos++) // Avoid isalpha(), etc. and be explicit, in case the signature // string contains international characters. if (str[pos] >= 'A' && str[pos] <= 'Z') { nAlpha++; if (largestLetter < str[pos] - 'A') largestLetter = str[pos] - 'A'; } else if (str[pos] >= 'a' && str[pos] <= 'z') { nAlpha++; if (largestLetter < str[pos] - 'a') largestLetter = str[pos] - 'a'; } if (static_cast(nAlpha) != 2 * (largestLetter + 1)) return 0; if (nAlpha == 0) return 0; // Looks fine so far. // Build the signature and cycle structure (but not cycle groups yet). unsigned order = largestLetter + 1; unsigned* label = new unsigned[nAlpha]; bool* labelInv = new bool[nAlpha]; unsigned nCycles = 0; unsigned* cycleStart = new unsigned[nAlpha + 1]; cycleStart[0] = 0; unsigned* freq = new unsigned[order]; std::fill(freq, freq + order, 0); unsigned whichPos = 0; /* Position in the signature, as opposed to position in the string. */ unsigned letterIndex; for (pos = 0; pos < len; pos++) { if (isspace(str[pos])) continue; if (! ((str[pos] >= 'A' && str[pos] <= 'Z') || (str[pos] >= 'a' && str[pos] <= 'z'))) { if (cycleStart[nCycles] < whichPos) { // We've just ended a cycle. nCycles++; cycleStart[nCycles] = whichPos; } } else { if (str[pos] >= 'A' && str[pos] <= 'Z') letterIndex = str[pos] - 'A'; else letterIndex = str[pos] - 'a'; freq[letterIndex]++; if (freq[letterIndex] > 2) { // We've seen this letter a third time! delete[] label; delete[] labelInv; delete[] cycleStart; delete[] freq; return 0; } label[whichPos] = letterIndex; labelInv[whichPos] = (str[pos] >= 'A' && str[pos] <= 'Z'); whichPos++; } } delete[] freq; if (cycleStart[nCycles] < whichPos) { nCycles++; cycleStart[nCycles] = whichPos; } // We now have a valid signature! NSignature* sig = new NSignature(); sig->order = order; sig->label = label; sig->labelInv = labelInv; sig->nCycles = nCycles; sig->cycleStart = cycleStart; // Fill in the rest of the data members. sig->nCycleGroups = 0; sig->cycleGroupStart = new unsigned[nCycles]; for (pos = 0; pos < nCycles; pos++) if (pos == 0 || sig->cycleStart[pos + 1] - sig->cycleStart[pos] != sig->cycleStart[pos] - sig->cycleStart[pos - 1]) { // New cycle group. sig->cycleGroupStart[sig->nCycleGroups] = static_cast(pos); sig->nCycleGroups++; } return sig; } NTriangulation* NSignature::triangulate() const { unsigned sigLen = 2 * order; NTriangulation* tri = new NTriangulation(); // Create a new set of tetrahedra. // Tetrahedron vertices will be: // bottom left -> top right: 0 -> 1 // bottom right -> top left: 2 -> 3 NTetrahedron** tet = new NTetrahedron*[order]; unsigned pos; for (pos = 0; pos < order; pos++) tet[pos] = tri->newTetrahedron(); // Store the first occurrence of each symbol. unsigned* first = new unsigned[order]; std::fill(first, first + order, sigLen); for (pos = 0; pos < sigLen; pos++) if (first[label[pos]] == sigLen) first[label[pos]] = pos; // Make the face gluings. unsigned currCycle = 0; unsigned adjPos; NPerm4 myFacePerm, yourFacePerm; for (pos = 0; pos < sigLen; pos++) { if (cycleStart[currCycle + 1] == pos + 1) { adjPos = cycleStart[currCycle]; currCycle++; } else adjPos = pos + 1; myFacePerm = exitFace(first[label[pos]] == pos, ! labelInv[pos]); yourFacePerm = exitFace(first[label[adjPos]] == adjPos, labelInv[adjPos]); tet[label[pos]]->joinTo(myFacePerm[3], tet[label[adjPos]], yourFacePerm * myFacePerm.inverse()); } // Clean up. delete[] first; delete[] tet; return tri; } int NSignature::cycleCmp(const NSignature& sig1, unsigned cycle1, unsigned start1, int dir1, unsigned* relabel1, const NSignature& sig2, unsigned cycle2, unsigned start2, int dir2, unsigned* relabel2) { unsigned len = sig1.cycleStart[cycle1 + 1] - sig1.cycleStart[cycle1]; unsigned* arr1 = sig1.label + sig1.cycleStart[cycle1]; unsigned* arr2 = sig2.label + sig2.cycleStart[cycle2]; unsigned pos1 = start1; unsigned pos2 = start2; for (unsigned i = 0; i < len; i++) { if ((relabel1 ? relabel1[arr1[pos1]] : arr1[pos1]) < (relabel2 ? relabel2[arr2[pos2]] : arr2[pos2])) return -1; if ((relabel1 ? relabel1[arr1[pos1]] : arr1[pos1]) > (relabel2 ? relabel2[arr2[pos2]] : arr2[pos2])) return 1; if (dir1 > 0) { pos1++; if (pos1 == len) pos1 = 0; } else { if (pos1 == 0) pos1 = len - 1; else pos1--; } if (dir2 > 0) { pos2++; if (pos2 == len) pos2 = 0; } else { if (pos2 == 0) pos2 = len - 1; else pos2--; } } return 0; } void NSignature::writeCycles(std::ostream& out, const std::string& cycleOpen, const std::string& cycleClose, const std::string& cycleJoin) const { out << cycleOpen; unsigned cycle = 0; for (unsigned pos = 0; pos < 2 * order; pos++) { if (cycleStart[cycle] == pos) { if (cycle > 0) out << cycleClose << cycleJoin << cycleOpen; cycle++; } out << char((labelInv[pos] ? 'A' : 'a') + label[pos]); } out << cycleClose; } } // namespace regina regina-4.96/engine/split/nsignature.h000644 000765 000024 00000031024 12377775416 017563 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file split/nsignature.h * \brief Deals with signatures of splitting surfaces. */ #ifndef __NSIGNATURE_H #ifndef __DOXYGEN #define __NSIGNATURE_H #endif #include "regina-core.h" #include "shareableobject.h" namespace regina { class NSigCensus; class NSigPartialIsomorphism; class NTriangulation; /** * \addtogroup split Splitting Surfaces * Splitting surfaces in triangulations. * @{ */ /** * Represents a signature of a splitting surface in a closed 3-manifold * triangulation. * * A splitting surface is (for these purposes) a compact normal surface * consisting of precisely one quad per tetrahedron and no other normal * (or almost normal) discs. * * A signature of order n is a string consisting of 2n * letters arranged into cycles, where n is the number of quads in the * splitting surface. From a signature, the corresponding splitting * surface and then the entire 3-manifold triangulation can be recreated. * * A signature of order n uses the first n letters of the * alphabet, each precisely twice. Case is important; the meaning of a * letter changes according to whether it appears in upper-case or * lower-case. * * Each letter represents an individual quadrilateral (the two * occurrences of the letter representing the quadrilateral's two sides). * Each cycle represents a chain of quadrilaterals joined together in the * splitting surface. The case of a letter represents in which direction * a quadrilateral is traversed within a cycle. * * Cycles are arranged into cycle groups, where a cycle group * consists of a series of consecutive cycles all of the same length. * * An example of a signature is (abc)(a)(b)(c). This signature * is of order 3 and contains two cycle groups, the first being * (abc) and the second being (a)(b)(c). * * A signature cannot represent a splitting surface with more than 26 * quadrilaterals. * * For further details on splitting surfaces and their signatures, consult * Minimal triangulations and normal surfaces, Burton, PhD thesis, * available from the Regina website. */ class REGINA_API NSignature : public ShareableObject { private: unsigned order; /**< The number of quads in this splitting surface. */ unsigned* label; /**< The 2n letters making up this signature from start to finish; letters A,B,... are represented by integers 0,1,... . */ bool* labelInv; /**< labelInv[i] stores the case of the letter corresponding to label[i]. In this case \c false represents lower-case and \c true represents upper-case. */ unsigned nCycles; /**< The number of cycles in this signature. */ unsigned* cycleStart; /**< The starting position of each cycle; an additional element is appended to the end of this array storing the length of the entire signature. */ unsigned nCycleGroups; /**< The number of cycle groups in this signature. */ unsigned* cycleGroupStart; /**< The starting cycle for each cycle group; an additional element is appended to the end of this array storing the total number of cycles. */ public: /** * Creates a new signature that is a clone of the given signature. * * @param sig the signature to clone. */ NSignature(const NSignature& sig); /** * Destroys this signature. */ virtual ~NSignature(); /** * Returns the order of this signature. The order is the number * of quads in the corresponding splitting surface. * * @return the order of this signature. */ unsigned getOrder() const; /** * Parses the given signature string. * * Punctuation characters in the given string will be interpreted * as separating cycles. All whitespace will be ignored. * * Examples of valid signatures are "(ab)(bC)(Ca)" and * "AAb-bc-C". See the class notes for further details * on what constitutes a valid signature. * * \pre The given string contains at least one letter. * * @param sig a string representation of a splitting surface * signature. * @return a corresponding newly created signature, or 0 if the * given string was invalid. */ static NSignature* parse(const std::string& sig); /** * Returns a newly created 3-manifold triangulation corresponding to * this splitting surface signature. * * @return the corresponding triangulation. */ NTriangulation* triangulate() const; /** * Lexicographically compares the results of transformations upon * two given cycles. Even if transformations are specified, the * underlying signatures will not be changed. * * This comparison is \e not case-sensitive. * * \pre The two specified cycles have the same length. * * \ifacespython Not present. * * @param sig1 the signature containing the first cycle to examine. * @param cycle1 specifies which cycle to examine in signature * \a sig1. This must be less than the total number of cycles in * \a sig1. * @param start1 allows the first cycle to be transformed by * rotation; this parameter is the new starting position of the first * cycle. This must be between 0 and * sig1.getCycleLength(cycle1)-1 inclusive. * @param dir1 allows the first cycle to be transformed by * reversal; this parameter must be positive to use an unreversed * cycle or negative to use a reversed cycle. * @param relabel1 allows the first cycle to be transformed by * relabelling; this parameter must be an array of size at least * sig1.getOrder() mapping old labels 0,1,... * (representing letters A,B,...) to new labels (which must also be * 0,1,..., possibly in a different order). This parameter may * be 0 if no relabelling is to be used. * * @param sig2 the signature containing the second cycle to examine. * @param cycle2 specifies which cycle to examine in signature * \a sig2. This must be less than the total number of cycles in * \a sig2. * @param start2 allows the second cycle to be transformed by * rotation; this parameter is the new starting position of the * second cycle. This must be between 0 and * sig2.getCycleLength(cycle2)-1 inclusive. * @param dir2 allows the second cycle to be transformed by * reversal; this parameter must be positive to use an unreversed * cycle or negative to use a reversed cycle. * @param relabel2 allows the second cycle to be transformed by * relabelling; this parameter must be an array of size at least * sig2.getOrder() mapping old labels 0,1,... * (representing letters A,B,...) to new labels (which must also be * 0,1,..., possibly in a different order). This parameter may * be 0 if no relabelling is to be used. * * @return -1, 1 or 0 if the transformed first cycle is * lexicographically less than, greater than or equal to the * transformed second cycle respectively. */ static int cycleCmp(const NSignature& sig1, unsigned cycle1, unsigned start1, int dir1, unsigned* relabel1, const NSignature& sig2, unsigned cycle2, unsigned start2, int dir2, unsigned* relabel2); /** * Writes a string representation of this signature to the given * output stream. * * \ifacespython The parameter \a out does not exist; standard * output will be used. * * @param out the output stream to which to write. * @param cycleOpen the text to write at the beginning of a cycle * (such as "("). * @param cycleClose the text to write at the end of a cycle * (such as ")"). * @param cycleJoin the text to write between two cycles. */ void writeCycles(std::ostream& out, const std::string& cycleOpen, const std::string& cycleClose, const std::string& cycleJoin) const; virtual void writeTextShort(std::ostream& out) const; private: /** * Creates a new completely uninitialised signature. * * \warning The internal arrays \e must be created before this * signature is destroyed! */ NSignature(); /** * Creates a new signature of the given order. All internal * arrays will be created but not initialised. * * The first elements of the \a cycleStart and \a cycleGroupStart * arrays will be set to 0. * * The newly created signature can be used as a partial * signature containing no cycles. * * @param newOrder the order of the new signature; this must be * strictly positive. */ NSignature(unsigned newOrder); friend class regina::NSigPartialIsomorphism; friend class regina::NSigCensus; }; /*@}*/ // Inline functions for NSignature inline NSignature::NSignature() { } inline NSignature::NSignature(unsigned newOrder) : order(newOrder), label(new unsigned[2 * newOrder]), labelInv(new bool[2 * newOrder]), nCycles(0), cycleStart(new unsigned[2 * newOrder + 1]), nCycleGroups(0), cycleGroupStart(new unsigned[2 * newOrder + 1]) { // Insert sentinels. cycleStart[0] = cycleGroupStart[0] = 0; } inline NSignature::~NSignature() { delete[] label; delete[] labelInv; delete[] cycleStart; delete[] cycleGroupStart; } inline unsigned NSignature::getOrder() const { return order; } inline void NSignature::writeTextShort(std::ostream& out) const { writeCycles(out, "(", ")", ""); } } // namespace regina #endif regina-4.96/engine/subcomplex/CMakeLists.txt000644 000765 000024 00000002757 12311266525 021014 0ustar00babstaff000000 000000 # subcomplex # Files to compile SET ( FILES naugtrisolidtorus nblockedsfs nblockedsfsloop nblockedsfspair nblockedsfstriple nl31pillow nlayeredchain nlayeredchainpair nlayeredlensspace nlayeredloop nlayeredsolidtorus nlayeredsurfacebundle nlayering npillowtwosphere npluggedtorusbundle nplugtrisolidtorus nsatannulus nsatblock nsatblockstarter nsatblocktypes nsatregion nsnappeacensustri nsnappedball nsnappedtwosphere nspiralsolidtorus nstandardtri ntrisolidtorus ntrivialtri ntxicore ) # Prepend folder name FOREACH ( SOURCE_FILE ${FILES} ) SET ( SOURCES ${SOURCES} subcomplex/${SOURCE_FILE}) ENDFOREACH(SOURCE_FILE) # Set the variable in the parent directory SET( SOURCES ${SOURCES} PARENT_SCOPE) if (${REGINA_INSTALL_DEV}) INSTALL(FILES naugtrisolidtorus.h nblockedsfs.h nblockedsfsloop.h nblockedsfspair.h nblockedsfstriple.h nl31pillow.h nlayeredchain.h nlayeredchainpair.h nlayeredlensspace.h nlayeredloop.h nlayeredsolidtorus.h nlayeredsurfacebundle.h nlayering.h npillowtwosphere.h npluggedtorusbundle.h nplugtrisolidtorus.h nsatannulus.h nsatblock.h nsatblockstarter.h nsatblocktypes.h nsatregion.h nsnappeacensustri.h nsnappedball.h nsnappedtwosphere.h nspiralsolidtorus.h nstandardtri.h ntrisolidtorus.h ntrivialtri.h ntxicore.h DESTINATION ${INCLUDEDIR}/subcomplex COMPONENT Development) endif (${REGINA_INSTALL_DEV}) regina-4.96/engine/subcomplex/cube.eps000644 000765 000024 00000007127 12234011536 017671 0ustar00babstaff000000 000000 %!PS-Adobe-2.0 EPSF-2.0 %%Title: cube.fig %%Creator: fig2dev Version 3.2 Patchlevel 5-alpha7 %%CreationDate: Thu Feb 2 23:18:12 2006 %%BoundingBox: 0 0 189 155 %Magnification: 1.0000 %%EndComments /$F2psDict 200 dict def $F2psDict begin $F2psDict /mtrx matrix put /col-1 {0 setgray} bind def /col0 {0.000 0.000 0.000 srgb} bind def /col1 {0.000 0.000 1.000 srgb} bind def /col2 {0.000 1.000 0.000 srgb} bind def /col3 {0.000 1.000 1.000 srgb} bind def /col4 {1.000 0.000 0.000 srgb} bind def /col5 {1.000 0.000 1.000 srgb} bind def /col6 {1.000 1.000 0.000 srgb} bind def /col7 {1.000 1.000 1.000 srgb} bind def /col8 {0.000 0.000 0.560 srgb} bind def /col9 {0.000 0.000 0.690 srgb} bind def /col10 {0.000 0.000 0.820 srgb} bind def /col11 {0.530 0.810 1.000 srgb} bind def /col12 {0.000 0.560 0.000 srgb} bind def /col13 {0.000 0.690 0.000 srgb} bind def /col14 {0.000 0.820 0.000 srgb} bind def /col15 {0.000 0.560 0.560 srgb} bind def /col16 {0.000 0.690 0.690 srgb} bind def /col17 {0.000 0.820 0.820 srgb} bind def /col18 {0.560 0.000 0.000 srgb} bind def /col19 {0.690 0.000 0.000 srgb} bind def /col20 {0.820 0.000 0.000 srgb} bind def /col21 {0.560 0.000 0.560 srgb} bind def /col22 {0.690 0.000 0.690 srgb} bind def /col23 {0.820 0.000 0.820 srgb} bind def /col24 {0.500 0.190 0.000 srgb} bind def /col25 {0.630 0.250 0.000 srgb} bind def /col26 {0.750 0.380 0.000 srgb} bind def /col27 {1.000 0.500 0.500 srgb} bind def /col28 {1.000 0.630 0.630 srgb} bind def /col29 {1.000 0.750 0.750 srgb} bind def /col30 {1.000 0.880 0.880 srgb} bind def /col31 {1.000 0.840 0.000 srgb} bind def end save newpath 0 155 moveto 0 0 lineto 189 0 lineto 189 155 lineto closepath clip newpath -339.4 270.0 translate 1 -1 scale /cp {closepath} bind def /ef {eofill} bind def /gr {grestore} bind def /gs {gsave} bind def /sa {save} bind def /rs {restore} bind def /l {lineto} bind def /m {moveto} bind def /rm {rmoveto} bind def /n {newpath} bind def /s {stroke} bind def /sh {show} bind def /slc {setlinecap} bind def /slj {setlinejoin} bind def /slw {setlinewidth} bind def /srgb {setrgbcolor} bind def /rot {rotate} bind def /sc {scale} bind def /sd {setdash} bind def /ff {findfont} bind def /sf {setfont} bind def /scf {scalefont} bind def /sw {stringwidth} bind def /tr {translate} bind def /tnt {dup dup currentrgbcolor 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} bind def /shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul 4 -2 roll mul srgb} bind def /$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def /$F2psEnd {$F2psEnteredState restore end} def $F2psBegin 10 setmiterlimit 0 slj 0 slc 0.06299 0.06299 sc % % Fig objects follow % % % here starts figure with depth 50 % Polyline 0 slj 0 slc 7.500 slw n 5400 2475 m 5400 4275 l 7200 4275 l 7200 2475 l 5400 2475 l 6570 1845 l 8370 1845 l 7200 2475 l gs col0 s gr % Polyline n 8370 1845 m 8370 3645 l 7200 4275 l gs col0 s gr % Polyline [15 45] 45 sd n 6570 1845 m 6570 3645 l 8370 3645 l gs col0 s gr [] 0 sd % Polyline [15 45] 45 sd n 6570 3645 m 5400 4275 l gs col0 s gr [] 0 sd % Polyline [60] 0 sd n 5400 4275 m 8370 1845 l gs col0 s gr [] 0 sd % Polyline [60] 0 sd n 7200 4275 m 6570 3645 l gs col0 s gr [] 0 sd % Polyline n 7200 2475 m 6570 1845 l gs col0 s gr % Polyline n 5400 4275 m 7200 2475 l gs col0 s gr % Polyline n 7200 4275 m 8370 1845 l gs col0 s gr % Polyline [15 45] 45 sd n 5400 4275 m 6570 1845 l gs col0 s gr [] 0 sd % Polyline [15 45] 45 sd n 6570 3645 m 8370 1845 l gs col0 s gr [] 0 sd % here ends figure; $F2psEnd rs showpage %%Trailer %EOF regina-4.96/engine/subcomplex/cube.fig000644 000765 000024 00000001545 12234011536 017645 0ustar00babstaff000000 000000 #FIG 3.2 Produced by xfig version 3.2.5-alpha5 Landscape Center Metric A4 100.00 Single -2 1200 2 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 8 5400 2475 5400 4275 7200 4275 7200 2475 5400 2475 6570 1845 8370 1845 7200 2475 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 3 8370 1845 8370 3645 7200 4275 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 3 6570 1845 6570 3645 8370 3645 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 6570 3645 5400 4275 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 5400 4275 8370 1845 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 7200 4275 6570 3645 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 7200 2475 6570 1845 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 5400 4275 7200 2475 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 7200 4275 8370 1845 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 5400 4275 6570 1845 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 6570 3645 8370 1845 regina-4.96/engine/subcomplex/cube.png000644 000765 000024 00000003664 12234011536 017670 0ustar00babstaff000000 000000 ‰PNG  IHDRƒllä^í pHYs±±Åa†tIMEÖ ë(*SIDAThÞÅš;«$EÇϽl`àõ1t"3ƒNT4ØÌ@hÁ/P“ˆ¡=‰™B7¸‰ â Š‰ T¡{ÁÄ`¡+P6¤*ØÄÈc0ý¨ª®Çéž+¸wÝ=¿ú×yÕãáoÖßrüõÕ÷o ¿z~·V‡Z¾ Aq+‚úùýn%CÓä9Ô7‚¨ÿç?òU M“ç ²Û@Ô²øîÓs.É­ç"b‹ « ¯l‚ Ä9 2ƒâ¥õþJˆ¶X•ˆUOfPe©.¯NˆíÕ=¯¹PˆQÐìá¨9[çV›ÐG( ËÔY E‡Š÷ÓëÕUÃq‘´=!"b$w4šÌ®P¢–Epî ½8³Ò:.¬Äë s”txGÄ”Mîh˜óôg ÄÐ!Õ£ˆˆB$\wôv¬Z厈ˆ}1ÇÃìŽÆ/n‡˜%-/)N †’«`‡ÖC(Î7Ãÿ£ ¦;Î÷ž6‡!)ï+UŒÁq·ýJ£C¼ï•ñ1„¦»Õ*%\IÇw}dX¸ãüM¿Á;ÌzÓ–&q(îèØd btÇ‹•W¦†“ ƒÏç^¨µq‘´Glû¥ 6CÄ}¦™€°Ü{åòù¼îh l0ix!I[Žˆ½1ˆFw'† 3Ä8ávh!’avC’ÀÒ¿OAø#œù¦H¢îhXdÊf·Cjif¦ (€æŽÔò ²ÝÑ@°â¼e+âŽË=KW??›³»g¯¯ûáϽ¥•fvAYš…¼aSÅnúUž°f›‹¸§M°ìN æCùÐù g ag_˜m˜w³ˆ°‚û ÷]Z;ÃEÓaéE¡Æ ÓY ._ÃpçÙ$„z¸.cqhc±©BYÐ1W6W ƒ”9aþ¶°…,ó׋§Æ"soêÒÝaà_^Ûåë×£40H…‹ ›2d¾ç=¬×a dr 2~ù¼‚ †ŒÅ£ÅA¦ —¿×xl+ÉpÖ‰ˆå"È÷»taK¾ha%Á)³{3¼ðL“’ù¢NEMG…§“JÒ«êÖÅ>a¥Âa¶[_$k¼á-Á YœÁAhŠ·âù·ØÂàõ”‚†|øj‘¦QšÄGÁl„úñg¶¢0ÔÑjÂF覲Nú2Àµœí”˩ТñÀìéž^Â99ËRAç—ÝÛJêÐSUh9A‡Ðl6ªƒÎÂY̶…lªÕ_4Á§±Ð" »p&µ#ƒ< Ö;upM7ÂÀBË,ýI–´ oB°´†Ö²¡Ì‰hðqáÕ•ˆ=äY°¢0U€œ,´Ëdè4¥|=žM—ÝEv@Š-û›,ˆðˆÍ5ò.}Ctb´)Nz£#"¶*ªH¨ ÚCˆaØ›s¼ì$¥ŠØX[`ËMœålŠ" Þšk4Ç ƒµt²K”!QÂ{z 7yD ÍØNSÁéAFrÝÑêx–¡»Ã4H«„kRS”}â±Þ)ŸÒ–sSµKÜ7ÏQÿR ÄÔj‹³ ¥ê#ë¥bµ ^ô9š#¸U‹ÈôšÞ6è Â*T"±›²|\ëuðdÙI…Ã.·Öa+¼–:,·­f[P¾4×ã², B'‡~KRš¢Dé@ŒZ¬yŒuc?.4›Z“­9k²VØåaœi2,thüZp!M­aÁyŒ©Ü @F“v6DÄBÃèܽHÐòi³Òõ‹Æo ¥Û»œÔ¿ðô.6{ÂÁõ”ìk€¤†´œþwÈæ‡_ÝâJ)¡ÝÔЀ–ÐimEµU¸1ëô§ånEÙ¬EΛ"¾DÄVÊ´5.-±@p6ÚU2Ó sS‘xFÆbh]„ÒZVUJ©T¡Ý»È±€ÀX ¶`çfá]y 3PÏÈ Æ‘U¨ÅJP‰É¤i1TQ¸:¼:¨B! ž>càä323Ã|:ᢂá§}ëÏCDál‰{tp²môûlB$eXžs˜&“W…BUŽ$¥Œ«ñ É0½*ö†Á”ëN‡ˆh%Û{Ï9¸caD›ŠI‹án8 â)@“á4#”´ÓHÄÉËÀîÑAJñ6aŠß‚v Ðb8M*L±‡l‹~\wô1ôÂt nÅR™e·{—8vtaÊ*±Dë‡è†‚x ÐbÑúÎS­¶Q%Ý1£§ÜdŠÊÚ¿àÄS€c»#õáÑqØ`°º±ýÁ;¯9 Ψµ½*—ë Á0…!CÅi(ƪ麳QØp£îè2¨^}ô˜^!Ä]TŒ·9Ý»ûø•w4ËẶƒ#§w²ÎJú@þöËgoÊM¦è@ìj²fåšûö›ó›ܤ÷/¯ëÏÝçß¿û%ܪuç¿_~‰¯Uôî½^ƒÛµgOž¬—ô?#à(ÄÿmU\IEND®B`‚regina-4.96/engine/subcomplex/diag92.eps000644 000765 000024 00000010103 12234011536 020016 0ustar00babstaff000000 000000 %!PS-Adobe-2.0 EPSF-2.0 %%Title: diag92.fig %%Creator: fig2dev Version 3.2 Patchlevel 5-alpha5 %%CreationDate: Wed Sep 28 00:55:56 2005 %%For: bab@skaro (Ben Burton,,,) %%BoundingBox: 0 0 115 172 %Magnification: 1.0000 %%EndComments /$F2psDict 200 dict def $F2psDict begin $F2psDict /mtrx matrix put /col-1 {0 setgray} bind def /col0 {0.000 0.000 0.000 srgb} bind def /col1 {0.000 0.000 1.000 srgb} bind def /col2 {0.000 1.000 0.000 srgb} bind def /col3 {0.000 1.000 1.000 srgb} bind def /col4 {1.000 0.000 0.000 srgb} bind def /col5 {1.000 0.000 1.000 srgb} bind def /col6 {1.000 1.000 0.000 srgb} bind def /col7 {1.000 1.000 1.000 srgb} bind def /col8 {0.000 0.000 0.560 srgb} bind def /col9 {0.000 0.000 0.690 srgb} bind def /col10 {0.000 0.000 0.820 srgb} bind def /col11 {0.530 0.810 1.000 srgb} bind def /col12 {0.000 0.560 0.000 srgb} bind def /col13 {0.000 0.690 0.000 srgb} bind def /col14 {0.000 0.820 0.000 srgb} bind def /col15 {0.000 0.560 0.560 srgb} bind def /col16 {0.000 0.690 0.690 srgb} bind def /col17 {0.000 0.820 0.820 srgb} bind def /col18 {0.560 0.000 0.000 srgb} bind def /col19 {0.690 0.000 0.000 srgb} bind def /col20 {0.820 0.000 0.000 srgb} bind def /col21 {0.560 0.000 0.560 srgb} bind def /col22 {0.690 0.000 0.690 srgb} bind def /col23 {0.820 0.000 0.820 srgb} bind def /col24 {0.500 0.190 0.000 srgb} bind def /col25 {0.630 0.250 0.000 srgb} bind def /col26 {0.750 0.380 0.000 srgb} bind def /col27 {1.000 0.500 0.500 srgb} bind def /col28 {1.000 0.630 0.630 srgb} bind def /col29 {1.000 0.750 0.750 srgb} bind def /col30 {1.000 0.880 0.880 srgb} bind def /col31 {1.000 0.840 0.000 srgb} bind def end save newpath 0 172 moveto 0 0 lineto 115 0 lineto 115 172 lineto closepath clip newpath -155.1 298.4 translate 1 -1 scale /cp {closepath} bind def /ef {eofill} bind def /gr {grestore} bind def /gs {gsave} bind def /sa {save} bind def /rs {restore} bind def /l {lineto} bind def /m {moveto} bind def /rm {rmoveto} bind def /n {newpath} bind def /s {stroke} bind def /sh {show} bind def /slc {setlinecap} bind def /slj {setlinejoin} bind def /slw {setlinewidth} bind def /srgb {setrgbcolor} bind def /rot {rotate} bind def /sc {scale} bind def /sd {setdash} bind def /ff {findfont} bind def /sf {setfont} bind def /scf {scalefont} bind def /sw {stringwidth} bind def /tr {translate} bind def /tnt {dup dup currentrgbcolor 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} bind def /shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul 4 -2 roll mul srgb} bind def /$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def /$F2psEnd {$F2psEnteredState restore end} def $F2psBegin 10 setmiterlimit 0 slj 0 slc 0.06299 0.06299 sc % % Fig objects follow % % % here starts figure with depth 50 % Polyline 0 slj 0 slc 7.500 slw n 3825 3825 m 4275 4275 l 4275 3825 l 3825 3375 l 3825 3825 l 4275 3825 l gs col0 s gr /Times-Italic ff 190.50 scf sf 3960 3780 m gs 1 -1 sc (w0) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Italic ff 190.50 scf sf 4140 4005 m gs 1 -1 sc (w1) dup sw pop 2 div neg 0 rm col0 sh gr % Polyline n 2925 2475 m 2475 2925 l 2475 2475 l 2925 2025 l 2925 2475 l 2475 2475 l gs col0 s gr % Polyline n 2925 2025 m 3375 2475 l 3375 2925 l 2925 3375 l gs col0 s gr % Polyline n 2925 2475 m 3825 3375 l 3375 3825 l 2475 2925 l gs col0 s gr % Polyline n 3825 3825 m 3375 4275 l 3825 4725 l 4275 4275 l gs col0 s gr % Polyline n 3375 3825 m 3375 4275 l gs col0 s gr /Times-Italic ff 190.50 scf sf 2610 2655 m gs 1 -1 sc (u0) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Italic ff 190.50 scf sf 2790 2385 m gs 1 -1 sc (u1) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Italic ff 190.50 scf sf 3825 4320 m gs 1 -1 sc (q1) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Italic ff 190.50 scf sf 3375 3420 m gs 1 -1 sc (q3) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Italic ff 190.50 scf sf 2925 2970 m gs 1 -1 sc (q4) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Italic ff 190.50 scf sf 3600 3870 m gs 1 -1 sc (q2) dup sw pop 2 div neg 0 rm col0 sh gr % here ends figure; $F2psEnd rs showpage %%Trailer %EOF regina-4.96/engine/subcomplex/diag92.fig000644 000765 000024 00000002032 12234011536 017776 0ustar00babstaff000000 000000 #FIG 3.2 Produced by xfig version 3.2.5-alpha5 Landscape Center Metric A4 100.00 Single -2 1200 2 6 3825 3375 4275 4275 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 6 3825 3825 4275 4275 4275 3825 3825 3375 3825 3825 4275 3825 4 1 0 50 -1 3 12 0.0000 0 150 240 3960 3780 w0\001 4 1 0 50 -1 3 12 0.0000 0 135 240 4140 4005 w1\001 -6 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 6 2925 2475 2475 2925 2475 2475 2925 2025 2925 2475 2475 2475 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 2925 2025 3375 2475 3375 2925 2925 3375 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 2925 2475 3825 3375 3375 3825 2475 2925 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 3825 3825 3375 4275 3825 4725 4275 4275 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 3375 3825 3375 4275 4 1 0 50 -1 3 12 0.0000 0 150 210 2610 2655 u0\001 4 1 0 50 -1 3 12 0.0000 0 135 210 2790 2385 u1\001 4 1 0 50 -1 3 12 0.0000 0 180 210 3825 4320 q1\001 4 1 0 50 -1 3 12 0.0000 0 195 210 3375 3420 q3\001 4 1 0 50 -1 3 12 0.0000 0 180 210 2925 2970 q4\001 4 1 0 50 -1 3 12 0.0000 0 180 210 3600 3870 q2\001 regina-4.96/engine/subcomplex/diag92.png000644 000765 000024 00000005026 12234011536 020023 0ustar00babstaff000000 000000 ‰PNG  IHDR—Þ£Í pHYs × ×B(›xtEXtSoftwareESP Ghostscript 815.00yxü: IDATxœíÜ?’¬ºð3¯îx™ë9â.W¯\åÀ S®²GLìˆY]o=p8pÖ½(¯–ФÎè%|º ¤# $ÙÁS43>~WüpÞ@ÿ—í‡ÿ5@Ó~s¹5[Wÿ— ŒM³tõ§ÿ|†…¬š«?]ÿLQaV®þtM¨Ž ³qõ§kBfáz±âÂÌ®™ft ¬˜0“KbE„\+V<ïÚ°¢ÁX—‚ ƹ”¬H0Æ¥aÅé]ZV˜ÖŰbÀt.–¦qXáaj׊õPL¦tI¬þãMÙuaa*—Ü[YZ¨g S¸ÖÛV›kæ Ûºž¬á2ý>ô:WPV­ËG %À5€s¨ÖÊRùçãmÝ_¯•˜Ñ­$bVcØSõ€k…{2©cú+XÉýµlò}N_EBD·$cÿ_zLr {b›Ý†¢%zÜxV0˜j% ¼KªÍ<‰n=Z•‚KdáŒÒ„Œ+lYòá4%âOÜb °*g—ñ ‚kþa“ë+ìå:Èò{º³¼Ã~ òÂò {ÌÓ]~ÿOÓ–Ng WûFDDÆÀÏsñq6Â<6»ñÕϬL®§>°ElV®Ï¬$Š S¸ÚïoéŸYI¶9÷5I7&wñìWO?yÇÓ¸SèþóãÜ;×,ÉZá÷goEí±ÅõºÓ¸PNDƒŠ6»Úï'¢ÛÏÔDÔχY‰6»¦;6'ӽƊ¶¬Ç6£¡-è‘]ÒLÊ® §; z\ -+Lì¯ÛP´T\§ô¬gE‚ ýõ‘ömBÕ×Ôp¬H°ù€¸¾ÓX§Û¦>À†9®®î4´½E£Çtçm–¦qXáaj—‘¦tY°BÃT.+V`˜ÂeÉ S\Ù²‚Â6.VHØÚåÄ [¹Yá`²Ë™ &¹v°BÁD—kPˆ¨¿U7ݳ"ï°,Xm›÷ï~8ß²T7oØ73ëÒ×Ô?†¡`­%ן|Âào¿2wWºùk°°`&~bG{ÜÀÀe9ÐРÛwë¥It]Ð.˜á–P‘辘=0Ö¥Jܳóð®mâ¾­Å}.ƒk¸w·wžÏä’÷¿]ç4ºÄD‹SuE‰úù³#ÌìZ-¢»;êÄãË5%Ú§|Œ]³q= W§Íkhe¬½œ¾¬\óŽm®hò8—iÃÆøuaÌá"ërúÞb,u«Æ_þå×…ñOŒë5ûœKì~g;këb×Á2 cXé?®–«ÒÚÅÁ¦!Øû¸ê·¯.íšÆr³w1°i¶¤ê̲Ð4–¿ƒ‹M4Ávi4å^éââC°]Úá鲂9¹ô‰Æ!Ø'ëé²¹¹v_P¼X/—EŒ£k'lbM.sŒ«klfÍ.cŒ³kla-.SŒ»Ë&°—!f‡Ë&²D³Çå“X’‹ºè®2$ÊMfÉ.ö”»CÅ'JmÅZ¹¸ge{Tl¢ØÖ¬µ‹9ìRq‰BÛ°6.mÌn—lËÚºt1û]F˜‚¥pib¸ 0KåRÇqñŠ*–Ò¥Œ9äb`jÖÆÕ¤T+c޹´0 kíš¾¡ÚÆti`:ÖÚ•6@^«bŽº”0- MÔw pFÈ+UÌa—¦g¡iPÞäùbMrVÅwm` MT%ÎYƒ{…¤î¤]óàZ%r,4 pÍïçªA9‚Tó8‹㣮¢ô_ÿq¿wýúþö¾zÁ/¡KEý%—¿¡Z¿ è¡¿Äÿꪷê3ÆR¸³l ¡çâ  ¨ÇRfzÌkN\¯Ä;ä‘§¦ºhÊçÔTJà ̓ë•(²æ‘Íûª¿0£f4c†ùraÌ;ùÎç5² ”šûæÍ…1¯Ö2²yÖÞwp°7õjïõ¼'Þ>î)½çÑ-wÏ¿÷5æ Woûã³ ¯EÎ#›Ro¡,ksi ðsüR´žh¸ òŒ.óÇÍŸT—™euƒ0ýõÙ¬¤E<Ë {¬|n÷ëï7#›Su6†]Dô•Ëß6|RýüA¿*…RcÁ\o·Û»’ÅÀ„RcÁ\À³(ЖÅÀ–é#Õi–Xì2õDôER©±8®K€Ú ÑÇðt ßCDqmX ìœ>è+h(I*5Ã¥`-°l('úªˆíRa/‚KÉšaÂÕ«Xj,¼KÚamNIÿ(V¥Æ‚»´¬,)rÊ’Š¨ý±mß– v’O>êV—Š«×Àç!SoM=–%Û¯ñº ,æÈÔedéa!],-, ËŠ¥ƒ…sY²4°`.k–ÊåÀR¹œX*X—#K ârfma!\;XX—KUZ†ùwYº‚ÔÌ»ËÜ[Ú‚Ô"Ì·ËfÛÒ~n-À<»XÖó³y® õóëbYÏÏæ¥»D=Ì«‹e]nõÄPz†y¼¾ÿw-?¿³9¤Öµú€ßñ¯:cÞå›G6uïOO­üÕ·‹…MïlŽ9ÿbÝ«šW{l6†mgªÒæ×ůJó;›Kñ8Ï.f|gS¨içÛÅÀÈôΦXj£×ëDﺈ±ñÉŠX5Ä»‹šTÌÄ¿k/L®±Àµ¶*ýµ¶®HÄåÛÊ ãr…më÷r¹Áe…B¹\`ªjGÁ\ö0e¦p.[˜º6T@—LS²*¤Ë¦«¤Ôe†i |…u™`úºc]<Œ)‡ÚÅÁ¸*mÁ]z[<.¼Kã Fp©a†z‰1\*˜©Œc×f¬.ǵ†™‹^FrÉ0‹Zœ±\"̦ül4׳ªŠÏ5ÁìŠõFt=a–5„cº¨¤÷̲´qT•D–—=¾¿êµEz/͹ýærkÿo¾Hm5é†IEND®B`‚regina-4.96/engine/subcomplex/diagbdry.eps000644 000765 000024 00000011176 12234011536 020537 0ustar00babstaff000000 000000 %!PS-Adobe-2.0 EPSF-2.0 %%Title: diagbdry.fig %%Creator: fig2dev Version 3.2 Patchlevel 5-alpha5 %%CreationDate: Wed Sep 28 00:53:08 2005 %%For: bab@skaro (Ben Burton,,,) %%BoundingBox: 0 0 168 67 %Magnification: 1.0000 %%EndComments /$F2psDict 200 dict def $F2psDict begin $F2psDict /mtrx matrix put /col-1 {0 setgray} bind def /col0 {0.000 0.000 0.000 srgb} bind def /col1 {0.000 0.000 1.000 srgb} bind def /col2 {0.000 1.000 0.000 srgb} bind def /col3 {0.000 1.000 1.000 srgb} bind def /col4 {1.000 0.000 0.000 srgb} bind def /col5 {1.000 0.000 1.000 srgb} bind def /col6 {1.000 1.000 0.000 srgb} bind def /col7 {1.000 1.000 1.000 srgb} bind def /col8 {0.000 0.000 0.560 srgb} bind def /col9 {0.000 0.000 0.690 srgb} bind def /col10 {0.000 0.000 0.820 srgb} bind def /col11 {0.530 0.810 1.000 srgb} bind def /col12 {0.000 0.560 0.000 srgb} bind def /col13 {0.000 0.690 0.000 srgb} bind def /col14 {0.000 0.820 0.000 srgb} bind def /col15 {0.000 0.560 0.560 srgb} bind def /col16 {0.000 0.690 0.690 srgb} bind def /col17 {0.000 0.820 0.820 srgb} bind def /col18 {0.560 0.000 0.000 srgb} bind def /col19 {0.690 0.000 0.000 srgb} bind def /col20 {0.820 0.000 0.000 srgb} bind def /col21 {0.560 0.000 0.560 srgb} bind def /col22 {0.690 0.000 0.690 srgb} bind def /col23 {0.820 0.000 0.820 srgb} bind def /col24 {0.500 0.190 0.000 srgb} bind def /col25 {0.630 0.250 0.000 srgb} bind def /col26 {0.750 0.380 0.000 srgb} bind def /col27 {1.000 0.500 0.500 srgb} bind def /col28 {1.000 0.630 0.630 srgb} bind def /col29 {1.000 0.750 0.750 srgb} bind def /col30 {1.000 0.880 0.880 srgb} bind def /col31 {1.000 0.840 0.000 srgb} bind def end save newpath 0 67 moveto 0 0 lineto 168 0 lineto 168 67 lineto closepath clip newpath -131.2 193.5 translate 1 -1 scale /cp {closepath} bind def /ef {eofill} bind def /gr {grestore} bind def /gs {gsave} bind def /sa {save} bind def /rs {restore} bind def /l {lineto} bind def /m {moveto} bind def /rm {rmoveto} bind def /n {newpath} bind def /s {stroke} bind def /sh {show} bind def /slc {setlinecap} bind def /slj {setlinejoin} bind def /slw {setlinewidth} bind def /srgb {setrgbcolor} bind def /rot {rotate} bind def /sc {scale} bind def /sd {setdash} bind def /ff {findfont} bind def /sf {setfont} bind def /scf {scalefont} bind def /sw {stringwidth} bind def /tr {translate} bind def /tnt {dup dup currentrgbcolor 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} bind def /shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul 4 -2 roll mul srgb} bind def /$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def /$F2psEnd {$F2psEnteredState restore end} def $F2psBegin 10 setmiterlimit 0 slj 0 slc 0.06299 0.06299 sc % % Fig objects follow % % % here starts figure with depth 50 % Polyline 0 slj 0 slc 7.500 slw gs clippath 2973 2739 m 3091 2620 l 3049 2578 l 2930 2696 l 2930 2696 l 3037 2633 l 2973 2739 l cp eoclip n 2610 3060 m 3060 2610 l gs col0 s gr gr % arrowhead n 2973 2739 m 3037 2633 l 2930 2696 l col0 s /Symbol ff 190.50 scf sf 2925 2970 m gs 1 -1 sc (b) dup sw pop 2 div neg 0 rm col0 sh gr % Polyline gs clippath 4460 2973 m 4579 3091 l 4621 3049 l 4503 2930 l 4503 2930 l 4567 3037 l 4460 2973 l cp eoclip n 4140 2610 m 4590 3060 l gs col0 s gr gr % arrowhead n 4460 2973 m 4567 3037 l 4503 2930 l col0 s /Symbol ff 190.50 scf sf 4275 2970 m gs 1 -1 sc (b) dup sw pop 2 div neg 0 rm col0 sh gr % Polyline n 2925 2475 m 2475 2925 l 2475 2475 l 2925 2025 l 2925 2475 l 2475 2475 l gs col0 s gr % Polyline gs clippath 2325 2628 m 2325 2460 l 2265 2460 l 2265 2628 l 2265 2628 l 2295 2508 l 2325 2628 l cp eoclip n 2295 2925 m 2295 2475 l gs col0 s gr gr % arrowhead n 2325 2628 m 2295 2508 l 2265 2628 l col0 s % Polyline n 4275 2475 m 4725 2925 l 4725 2475 l 4275 2025 l 4275 2475 l 4725 2475 l gs col0 s gr % Polyline gs clippath 4125 2178 m 4125 2010 l 4065 2010 l 4065 2178 l 4065 2178 l 4095 2058 l 4125 2178 l cp eoclip n 4095 2475 m 4095 2025 l gs col0 s gr gr % arrowhead n 4125 2178 m 4095 2058 l 4065 2178 l col0 s /Times-Italic ff 190.50 scf sf 2610 2655 m gs 1 -1 sc (u0) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Italic ff 190.50 scf sf 2790 2385 m gs 1 -1 sc (u1) dup sw pop 2 div neg 0 rm col0 sh gr /Symbol ff 190.50 scf sf 2160 2745 m gs 1 -1 sc (a) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Italic ff 190.50 scf sf 4410 2430 m gs 1 -1 sc (w0) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Italic ff 190.50 scf sf 4590 2655 m gs 1 -1 sc (w1) dup sw pop 2 div neg 0 rm col0 sh gr /Symbol ff 190.50 scf sf 3960 2295 m gs 1 -1 sc (a) dup sw pop 2 div neg 0 rm col0 sh gr % here ends figure; $F2psEnd rs showpage %%Trailer %EOF regina-4.96/engine/subcomplex/diagbdry.fig000644 000765 000024 00000002123 12234011536 020505 0ustar00babstaff000000 000000 #FIG 3.2 Produced by xfig version 3.2.5-alpha5 Landscape Center Metric A4 100.00 Single -2 1200 2 6 2610 2610 3060 3060 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 2610 3060 3060 2610 4 1 0 50 -1 32 12 0.0000 4 195 105 2925 2970 b\001 -6 6 4140 2610 4590 3060 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 4140 2610 4590 3060 4 1 0 50 -1 32 12 0.0000 4 195 105 4275 2970 b\001 -6 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 6 2925 2475 2475 2925 2475 2475 2925 2025 2925 2475 2475 2475 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 2295 2925 2295 2475 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 6 4275 2475 4725 2925 4725 2475 4275 2025 4275 2475 4725 2475 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 4095 2475 4095 2025 4 1 0 50 -1 3 12 0.0000 0 150 210 2610 2655 u0\001 4 1 0 50 -1 3 12 0.0000 0 135 210 2790 2385 u1\001 4 1 0 50 -1 32 12 0.0000 4 105 120 2160 2745 a\001 4 1 0 50 -1 3 12 0.0000 0 150 240 4410 2430 w0\001 4 1 0 50 -1 3 12 0.0000 0 135 240 4590 2655 w1\001 4 1 0 50 -1 32 12 0.0000 4 105 120 3960 2295 a\001 regina-4.96/engine/subcomplex/diagbdry.png000644 000765 000024 00000003272 12234011536 020532 0ustar00babstaff000000 000000 ‰PNG  IHDR×[ÅdOÊ pHYs × ×B(›xtEXtSoftwareESP Ghostscript 815.00yxü:AIDATxœíœÏªã6Æ¿ ]–‚î Lq謺®.}] Ý;ÐpÁaº.ÄtÑuü ô¢Gˆè¢ËÓ];Plhwݨ ß$Ö[’c;™a¾Å+K¿œ#éœcgf¥^Ýz#éׇ¥A¸ò!nâ%î;Ô\ùj€›xjå 6W.’ëoÒ*Q)—›Üìz®\l®¾G‡~úY¹${?°Ï®wd,ü®]“ý3<üãZ®±±ðo?°+¹FÇâVDmò»n}Žþæ ×Û|ÖØU\ãcA<> £Ñì?œ Õç_ýb¶º]ñ ®)°8ˆ¾ÀàÖß§À§5ܮ؛k,0sÁ Ö×§ÁÂ¥Öº]±§½FÅÚÍgÏËÌÑ­Óbý¸ÆÅZÐr“‰Ün¦†ºÀzùá¸N˜!%$^EÌÙ³ÃûØkäµ%@Æc®íëa/Ër¸ ¡Ê'hï°X¸½šXb1‹B9*wßV‹s)Ö¢‘·*AVñ<ÉwÖsKW X¨jk‹PHŠü!ÚÄOØ{u·»b WUœp á޴µ^ÀÁ·»,Ìk,>_»';ýûÁÅç³ÜêŠAözqBV.€]‚:ܾ¥øbÍYd±Xˆ½Îk‹S<*¯CfD-·”PnÛ<¸.[†`Èbìˆ3ÖAyr0,`þ\Ó]sT»[`­x, ˜`Þ\êq Nø糡fë¯uT!#ŠœEU¯q ÌwßPέc„#nôHæ­Q1 ^œFÝ<<í¥Ç0NTè%‚<…È€*?o]ŠÅü¸&ÊŽ=ň¨b ΫU´>·7Á¼¸î ‹Ä ”¤ÒìA ¶`>ëë¾°@7§š=j]Ö˜×a¤}yŸÁÜ\w‡Õ©ØÌ¹Y/Ü¡m^1%»*Å6Å“;1ª6 M•ÊUjé¡vgW—át`¥«K*¥”–ý°ú.ì ]¬' §èzáS°íóü¯¦År‚>³p‰..>Ÿ)ñåÔX`2’ë­íF-¾Ø–«âr==VX£ŒdrUäu;×)‘;õ½VØ%7¹8ýÒ,pµó]9·ÂRÁ.Y¦RF2¹l%¦S¥¦‘ÈávXM°F–©”‘,\Ô|BÈJ ìÔDî†X °F–©”‘ ®ŠÌX`/•šf"7!–¥ð{£Ee¦jÉàâÔöäóT©¹$rv,¯33Xbi¶ÀYf³ŒdpÑÀZo}©Ô\9+V1/Œ¶!”аs–©–‘Ú,õ ì@Òƒ,}¬\ÿ[ǘÏ×Ép.IEND®B`‚regina-4.96/engine/subcomplex/diagdistort.eps000644 000765 000024 00000010621 12234011536 021261 0ustar00babstaff000000 000000 %!PS-Adobe-2.0 EPSF-2.0 %%Title: diagdistort.fig %%Creator: fig2dev Version 3.2 Patchlevel 5-alpha5 %%CreationDate: Wed Sep 28 01:04:26 2005 %%For: bab@skaro (Ben Burton,,,) %%BoundingBox: 0 0 243 87 %Magnification: 1.0000 %%EndComments /$F2psDict 200 dict def $F2psDict begin $F2psDict /mtrx matrix put /col-1 {0 setgray} bind def /col0 {0.000 0.000 0.000 srgb} bind def /col1 {0.000 0.000 1.000 srgb} bind def /col2 {0.000 1.000 0.000 srgb} bind def /col3 {0.000 1.000 1.000 srgb} bind def /col4 {1.000 0.000 0.000 srgb} bind def /col5 {1.000 0.000 1.000 srgb} bind def /col6 {1.000 1.000 0.000 srgb} bind def /col7 {1.000 1.000 1.000 srgb} bind def /col8 {0.000 0.000 0.560 srgb} bind def /col9 {0.000 0.000 0.690 srgb} bind def /col10 {0.000 0.000 0.820 srgb} bind def /col11 {0.530 0.810 1.000 srgb} bind def /col12 {0.000 0.560 0.000 srgb} bind def /col13 {0.000 0.690 0.000 srgb} bind def /col14 {0.000 0.820 0.000 srgb} bind def /col15 {0.000 0.560 0.560 srgb} bind def /col16 {0.000 0.690 0.690 srgb} bind def /col17 {0.000 0.820 0.820 srgb} bind def /col18 {0.560 0.000 0.000 srgb} bind def /col19 {0.690 0.000 0.000 srgb} bind def /col20 {0.820 0.000 0.000 srgb} bind def /col21 {0.560 0.000 0.560 srgb} bind def /col22 {0.690 0.000 0.690 srgb} bind def /col23 {0.820 0.000 0.820 srgb} bind def /col24 {0.500 0.190 0.000 srgb} bind def /col25 {0.630 0.250 0.000 srgb} bind def /col26 {0.750 0.380 0.000 srgb} bind def /col27 {1.000 0.500 0.500 srgb} bind def /col28 {1.000 0.630 0.630 srgb} bind def /col29 {1.000 0.750 0.750 srgb} bind def /col30 {1.000 0.880 0.880 srgb} bind def /col31 {1.000 0.840 0.000 srgb} bind def end save newpath 0 87 moveto 0 0 lineto 243 0 lineto 243 87 lineto closepath clip newpath -84.3 284.2 translate 1 -1 scale /cp {closepath} bind def /ef {eofill} bind def /gr {grestore} bind def /gs {gsave} bind def /sa {save} bind def /rs {restore} bind def /l {lineto} bind def /m {moveto} bind def /rm {rmoveto} bind def /n {newpath} bind def /s {stroke} bind def /sh {show} bind def /slc {setlinecap} bind def /slj {setlinejoin} bind def /slw {setlinewidth} bind def /srgb {setrgbcolor} bind def /rot {rotate} bind def /sc {scale} bind def /sd {setdash} bind def /ff {findfont} bind def /sf {setfont} bind def /scf {scalefont} bind def /sw {stringwidth} bind def /tr {translate} bind def /tnt {dup dup currentrgbcolor 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} bind def /shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul 4 -2 roll mul srgb} bind def /$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def /$F2psEnd {$F2psEnteredState restore end} def $F2psBegin 10 setmiterlimit 0 slj 0 slc 0.06299 0.06299 sc % % Fig objects follow % % % here starts figure with depth 50 % Polyline 0 slj 0 slc 7.500 slw n 2025 3375 m 1575 3825 l 2025 4275 l 2475 3825 l 2025 3375 l cp gs col0 s gr % Polyline n 1485 3735 m 1575 3825 l gs col0 s gr % Polyline n 1935 3285 m 2025 3375 l gs col0 s gr % Polyline n 2475 3825 m 2565 3915 l gs col0 s gr % Polyline n 2025 4275 m 2115 4365 l gs col0 s gr % Polyline [15 45] 45 sd n 2475 4275 m 2700 4500 l gs col0 s gr [] 0 sd % Polyline [15 45] 45 sd n 1350 3150 m 1575 3375 l gs col0 s gr [] 0 sd /Times-Italic ff 190.50 scf sf 2025 3870 m gs 1 -1 sc (qk) dup sw pop 2 div neg 0 rm col0 sh gr % Polyline n 4725 3825 m 5175 4275 l 5175 3825 l 4725 3375 l 4725 3825 l 5175 3825 l gs col0 s gr /Times-Italic ff 190.50 scf sf 4860 3780 m gs 1 -1 sc (w0) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Italic ff 190.50 scf sf 5040 4005 m gs 1 -1 sc (w1) dup sw pop 2 div neg 0 rm col0 sh gr % Polyline n 4725 3375 m 4275 3825 l 4275 4275 l 4725 3825 l gs col0 s gr % Polyline n 4275 4275 m 4365 4365 l gs col0 s gr % Polyline n 4275 3825 m 4185 3735 l gs col0 s gr % Polyline n 4725 3375 m 4635 3285 l gs col0 s gr % Polyline [15 45] 45 sd n 4050 3150 m 4275 3375 l gs col0 s gr [] 0 sd % Polyline [15 45] 45 sd n 4725 4275 m 4950 4500 l gs col0 s gr [] 0 sd /Times-Italic ff 190.50 scf sf 4500 3870 m gs 1 -1 sc (qk) dup sw pop 2 div neg 0 rm col0 sh gr % Polyline 15.000 slw gs clippath 3430 3885 m 3750 3885 l 3750 3765 l 3430 3765 l 3430 3765 l 3670 3825 l 3430 3885 l cp eoclip n 3015 3825 m 3735 3825 l gs col0 s gr gr % arrowhead n 3430 3885 m 3670 3825 l 3430 3765 l 3430 3885 l cp gs 0.00 setgray ef gr col0 s % here ends figure; $F2psEnd rs showpage %%Trailer %EOF regina-4.96/engine/subcomplex/diagdistort.fig000644 000765 000024 00000002624 12234011536 021243 0ustar00babstaff000000 000000 #FIG 3.2 Produced by xfig version 3.2.5-alpha5 Landscape Center Metric A4 100.00 Single -2 1200 2 6 1350 3150 2700 4500 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 2025 3375 1575 3825 2025 4275 2475 3825 2025 3375 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 1485 3735 1575 3825 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 1935 3285 2025 3375 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 2475 3825 2565 3915 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 2025 4275 2115 4365 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 2475 4275 2700 4500 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 1350 3150 1575 3375 4 1 0 50 -1 3 12 0.0000 0 195 195 2025 3870 qk\001 -6 6 4050 3150 5175 4500 6 4725 3375 5175 4275 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 6 4725 3825 5175 4275 5175 3825 4725 3375 4725 3825 5175 3825 4 1 0 50 -1 3 12 0.0000 0 150 240 4860 3780 w0\001 4 1 0 50 -1 3 12 0.0000 0 135 240 5040 4005 w1\001 -6 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 4725 3375 4275 3825 4275 4275 4725 3825 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 4275 4275 4365 4365 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 4275 3825 4185 3735 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 4725 3375 4635 3285 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 4050 3150 4275 3375 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 4725 4275 4950 4500 4 1 0 50 -1 3 12 0.0000 0 195 195 4500 3870 qk\001 -6 2 1 0 2 0 7 50 -1 -1 6.000 0 0 -1 1 0 2 1 1 2.00 120.00 240.00 3015 3825 3735 3825 regina-4.96/engine/subcomplex/diagdistort.png000644 000765 000024 00000003773 12234011536 021270 0ustar00babstaff000000 000000 ‰PNG  IHDR4s3À¡# pHYs × ×B(›xtEXtSoftwareESP Ghostscript 815.00yxü:‚IDATxœí=ÏãDÇ繃!!ùÄSÒ ù: K $Då‰É))QQ&µó(œ§XHôvAbÑAeK×€tè†"qâ—ÝÙÍËãuü¯ò\v7;¿óìËì®÷a’®ž³áSS3[¤k€Y°‚4€\´FÕÖ6ׄÙð¨µ+CôK·‚•S@Bê•¿ÿ÷µ6´êys*ÉL²™u`ÔÒæöÑ.³ž ^Q€°Š òÖn½M¡E­ÓFºÙñ3Õd¾§ßÔj—Ñi¤ŠÃãÇNź&Dˆ[?Âh'ˆ€X:®áÄ£Û{ž¨ÑýfI¿º4µÞþri îH­W­Ž ⶸ –ˆÄeØbz$ÒrÔÔc /‘wajÑ;OÍÁ¨õ+Õ1!BÌÄmˆˆ˜¹¶Ó×Lúã´=5%³r["b ¥/_–Zôlߘ˜‚‹ÃN•Ä&DˆX"–²ª¨ŒÎÜLÍl›àÖ/1ö0‹äd.J­†f .[’˜ ooÚsí¹Íg}ªè7×y «Ms'¨;d¡tö妩úûß~ÿ§õ÷“×o¾÷­ÏÙ€Wkýâå©:2Kª˜¹¼!øÂûñ»ïåÙ6ó@¤þb«*ß}õÙ/\jqçïÿÚ¿~xõǪr4Îs†¿ž˜ÉL˜ÿDîwrI›Ôytåùˆ[(q;Ø*žäÒÏ.ç¡M÷„7>ŽT?-.âôQbB«ìn#iȹÁÇ] Æ>†~¹“%+ýì‚íÚš0Ä4± a¬~ZNÅÈz?yîÂ#K,@Vvégˆ—£=; b šÐ„}¯¦Vª¡)sg…âÀìbÔ"8 b·gì™Pävg ME->`™]ŠZ|0Ä.´® §1–ÂǤ És€¯¬_ƒÙp¢’-h]šãR©Ý^Œ$4F«(V‹b6@hµÇò »ãb†ˆKDÜÁih†Ô:̆"´îüçhwDˆîÑAÄ¥W£ŒÜzÉLÿeÕl©3R€zqãÝ$@zœ;¨ÃÝÔFÀ¬a÷)$ UÔ_ +ÚÔFÁìd·ëòµïlœ£aÔb±&µ‘0;ÙúàäUPm†‘ ¨No0Ð>e<–¹Y#$¹­Y‘½g#7KCf&†¦Šfn&I’½gûI%5ßÜËKf98N/¾ÅÙjŤ62f »Y›úXÔFÇLn7oû(ƒÚ™IífnT&©’™Ìnî–x‚ÚH™Iìf¾PR-3±Ýüc> j#f&´[ã@™”Ú¨™‰ìÖ9º(¡6rf»µÉ ©žYßn½ãØjwÀ¬g·æÁÿµ»`Öµ[÷jw¬c·öËLZ¹ï†YÛný׿4rß³–Ý&¯l­sß³&5“Wrß³5£—ÎyÉ,¿?f'jf¯7ô’Yz̼dVñÅ4^òõ7–1ûóݳ™xIÀXÂS­ÕÚêž{¼¦ ÆRYInïÆY«Q2æôºjï÷Íõ~B_âÐ5vଛ/òYb—‡^¬ë:ã²-ÞÊq@à–rÏÀ•^ÙZ‹E-Ð)F5ú¿ù¼‹iîÔCÏ» ÏKèw¯J«Â”sÜâ ¤…Љ†¤M®>#u“{£*Û.| *<]¶e Ýï©w/ÓT©.¢½´AÍ 8rTì䞺áõ»šð$­ð ¡ml» ³Q›ÜÓ@ÓíØJ‰ç·…f]³– ©Mîi É= 4A3ÐÍ@ÿüY¨L˜¿‰SIEND®B`‚regina-4.96/engine/subcomplex/diaginit.eps000644 000765 000024 00000014520 12234011536 020536 0ustar00babstaff000000 000000 %!PS-Adobe-2.0 EPSF-2.0 %%Title: diaginit.fig %%Creator: fig2dev Version 3.2 Patchlevel 5-alpha5 %%CreationDate: Wed Sep 28 01:00:30 2005 %%For: bab@skaro (Ben Burton,,,) %%BoundingBox: 0 0 158 186 %Magnification: 1.0000 %%EndComments /$F2psDict 200 dict def $F2psDict begin $F2psDict /mtrx matrix put /col-1 {0 setgray} bind def /col0 {0.000 0.000 0.000 srgb} bind def /col1 {0.000 0.000 1.000 srgb} bind def /col2 {0.000 1.000 0.000 srgb} bind def /col3 {0.000 1.000 1.000 srgb} bind def /col4 {1.000 0.000 0.000 srgb} bind def /col5 {1.000 0.000 1.000 srgb} bind def /col6 {1.000 1.000 0.000 srgb} bind def /col7 {1.000 1.000 1.000 srgb} bind def /col8 {0.000 0.000 0.560 srgb} bind def /col9 {0.000 0.000 0.690 srgb} bind def /col10 {0.000 0.000 0.820 srgb} bind def /col11 {0.530 0.810 1.000 srgb} bind def /col12 {0.000 0.560 0.000 srgb} bind def /col13 {0.000 0.690 0.000 srgb} bind def /col14 {0.000 0.820 0.000 srgb} bind def /col15 {0.000 0.560 0.560 srgb} bind def /col16 {0.000 0.690 0.690 srgb} bind def /col17 {0.000 0.820 0.820 srgb} bind def /col18 {0.560 0.000 0.000 srgb} bind def /col19 {0.690 0.000 0.000 srgb} bind def /col20 {0.820 0.000 0.000 srgb} bind def /col21 {0.560 0.000 0.560 srgb} bind def /col22 {0.690 0.000 0.690 srgb} bind def /col23 {0.820 0.000 0.820 srgb} bind def /col24 {0.500 0.190 0.000 srgb} bind def /col25 {0.630 0.250 0.000 srgb} bind def /col26 {0.750 0.380 0.000 srgb} bind def /col27 {1.000 0.500 0.500 srgb} bind def /col28 {1.000 0.630 0.630 srgb} bind def /col29 {1.000 0.750 0.750 srgb} bind def /col30 {1.000 0.880 0.880 srgb} bind def /col31 {1.000 0.840 0.000 srgb} bind def end save newpath 0 186 moveto 0 0 lineto 158 0 lineto 158 186 lineto closepath clip newpath -155.1 312.6 translate 1 -1 scale /cp {closepath} bind def /ef {eofill} bind def /gr {grestore} bind def /gs {gsave} bind def /sa {save} bind def /rs {restore} bind def /l {lineto} bind def /m {moveto} bind def /rm {rmoveto} bind def /n {newpath} bind def /s {stroke} bind def /sh {show} bind def /slc {setlinecap} bind def /slj {setlinejoin} bind def /slw {setlinewidth} bind def /srgb {setrgbcolor} bind def /rot {rotate} bind def /sc {scale} bind def /sd {setdash} bind def /ff {findfont} bind def /sf {setfont} bind def /scf {scalefont} bind def /sw {stringwidth} bind def /tr {translate} bind def /tnt {dup dup currentrgbcolor 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} bind def /shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul 4 -2 roll mul srgb} bind def /reencdict 12 dict def /ReEncode { reencdict begin /newcodesandnames exch def /newfontname exch def /basefontname exch def /basefontdict basefontname findfont def /newfont basefontdict maxlength dict def basefontdict { exch dup /FID ne { dup /Encoding eq { exch dup length array copy newfont 3 1 roll put } { exch newfont 3 1 roll put } ifelse } { pop pop } ifelse } forall newfont /FontName newfontname put newcodesandnames aload pop 128 1 255 { newfont /Encoding get exch /.notdef put } for newcodesandnames length 2 idiv { newfont /Encoding get 3 1 roll put } repeat newfontname newfont definefont pop end } def /isovec [ 8#055 /minus 8#200 /grave 8#201 /acute 8#202 /circumflex 8#203 /tilde 8#204 /macron 8#205 /breve 8#206 /dotaccent 8#207 /dieresis 8#210 /ring 8#211 /cedilla 8#212 /hungarumlaut 8#213 /ogonek 8#214 /caron 8#220 /dotlessi 8#230 /oe 8#231 /OE 8#240 /space 8#241 /exclamdown 8#242 /cent 8#243 /sterling 8#244 /currency 8#245 /yen 8#246 /brokenbar 8#247 /section 8#250 /dieresis 8#251 /copyright 8#252 /ordfeminine 8#253 /guillemotleft 8#254 /logicalnot 8#255 /hyphen 8#256 /registered 8#257 /macron 8#260 /degree 8#261 /plusminus 8#262 /twosuperior 8#263 /threesuperior 8#264 /acute 8#265 /mu 8#266 /paragraph 8#267 /periodcentered 8#270 /cedilla 8#271 /onesuperior 8#272 /ordmasculine 8#273 /guillemotright 8#274 /onequarter 8#275 /onehalf 8#276 /threequarters 8#277 /questiondown 8#300 /Agrave 8#301 /Aacute 8#302 /Acircumflex 8#303 /Atilde 8#304 /Adieresis 8#305 /Aring 8#306 /AE 8#307 /Ccedilla 8#310 /Egrave 8#311 /Eacute 8#312 /Ecircumflex 8#313 /Edieresis 8#314 /Igrave 8#315 /Iacute 8#316 /Icircumflex 8#317 /Idieresis 8#320 /Eth 8#321 /Ntilde 8#322 /Ograve 8#323 /Oacute 8#324 /Ocircumflex 8#325 /Otilde 8#326 /Odieresis 8#327 /multiply 8#330 /Oslash 8#331 /Ugrave 8#332 /Uacute 8#333 /Ucircumflex 8#334 /Udieresis 8#335 /Yacute 8#336 /Thorn 8#337 /germandbls 8#340 /agrave 8#341 /aacute 8#342 /acircumflex 8#343 /atilde 8#344 /adieresis 8#345 /aring 8#346 /ae 8#347 /ccedilla 8#350 /egrave 8#351 /eacute 8#352 /ecircumflex 8#353 /edieresis 8#354 /igrave 8#355 /iacute 8#356 /icircumflex 8#357 /idieresis 8#360 /eth 8#361 /ntilde 8#362 /ograve 8#363 /oacute 8#364 /ocircumflex 8#365 /otilde 8#366 /odieresis 8#367 /divide 8#370 /oslash 8#371 /ugrave 8#372 /uacute 8#373 /ucircumflex 8#374 /udieresis 8#375 /yacute 8#376 /thorn 8#377 /ydieresis] def /Times-Italic /Times-Italic-iso isovec ReEncode /$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def /$F2psEnd {$F2psEnteredState restore end} def $F2psBegin 10 setmiterlimit 0 slj 0 slc 0.06299 0.06299 sc % % Fig objects follow % % % here starts figure with depth 50 % Polyline 0 slj 0 slc 7.500 slw n 2925 2475 m 2475 2925 l 2475 2475 l 2925 2025 l 2925 2475 l 2475 2475 l gs col0 s gr % Polyline n 2925 2025 m 3375 2475 l 3375 2925 l 2925 3375 l gs col0 s gr % Polyline n 2925 2475 m 3825 3375 l 3375 3825 l 2475 2925 l gs col0 s gr % Polyline n 3375 3825 m 3465 3915 l gs col0 s gr % Polyline n 3825 3375 m 3915 3465 l gs col0 s gr % Polyline n 4050 4500 m 4500 4050 l 4950 4500 l 4500 4950 l 4050 4500 l cp gs col0 s gr % Polyline n 3960 4410 m 4050 4500 l gs col0 s gr % Polyline n 4410 3960 m 4500 4050 l gs col0 s gr % Polyline [15 45] 45 sd n 3825 3825 m 4050 4050 l gs col0 s gr [] 0 sd /Times-Italic-iso ff 190.50 scf sf 2610 2655 m gs 1 -1 sc (u0) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Italic-iso ff 190.50 scf sf 2790 2385 m gs 1 -1 sc (u1) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Italic-iso ff 190.50 scf sf 4500 4545 m gs 1 -1 sc (q1) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Italic-iso ff 190.50 scf sf 2925 2970 m gs 1 -1 sc (q\(n-5\)) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Italic-iso ff 190.50 scf sf 3375 3420 m gs 1 -1 sc (q\(n-6\)) dup sw pop 2 div neg 0 rm col0 sh gr % here ends figure; $F2psEnd rs showpage %%Trailer %EOF regina-4.96/engine/subcomplex/diaginit.fig000644 000765 000024 00000002014 12234011536 020507 0ustar00babstaff000000 000000 #FIG 3.2 Produced by xfig version 3.2.5-alpha5 Landscape Center Metric A4 100.00 Single -2 1200 2 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 6 2925 2475 2475 2925 2475 2475 2925 2025 2925 2475 2475 2475 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 2925 2025 3375 2475 3375 2925 2925 3375 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 2925 2475 3825 3375 3375 3825 2475 2925 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 3375 3825 3465 3915 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 3825 3375 3915 3465 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 4050 4500 4500 4050 4950 4500 4500 4950 4050 4500 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 3960 4410 4050 4500 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 4410 3960 4500 4050 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 3825 3825 4050 4050 4 1 0 50 -1 3 12 0.0000 0 150 210 2610 2655 u0\001 4 1 0 50 -1 3 12 0.0000 0 135 210 2790 2385 u1\001 4 1 0 50 -1 3 12 0.0000 0 180 210 4500 4545 q1\001 4 1 0 50 -1 3 12 0.0000 0 180 495 2925 2970 q(n-5)\001 4 1 0 50 -1 3 12 0.0000 0 180 495 3375 3420 q(n-6)\001 regina-4.96/engine/subcomplex/diaginit.png000644 000765 000024 00000005120 12234011536 020527 0ustar00babstaff000000 000000 ‰PNG  IHDRÍð†3¿Æ pHYs × ×B(›xtEXtSoftwareESP Ghostscript 815.00yxü: ×IDATxœíÝ-¯óÈðsÛ¥ÞO°ÊâJU½*Y°Äûú0?´,QQAŸàÐe (ªTÉ!å6[êHË+›–Tÿ;ÎŒ=ž¿ÍIµ‡Ý\':¿;“\Ç3>çô¿ñÀªñ«†oØjš/›¦±R|ewXsü9H¶Ídøí_mŽjŽéÿNáÆ¹,«™ÖÓðwùå²u2‹Ãf¦5Ç4$ ò‰ûd³Ð´˜·à˜5OÌ;pŒšæ 8&ˆáÏ1hd {Ž^3Äpçh5c sŽN£Âðæh4j kδf Ù3©™Æ0æLit¾œ Ö£Ö 0M0:‚'GùýF”Ç1†(àø}G56òÈ„‡XùLŽ££›á{機Êqt0Œ:*TÙóçŠ*8ê0S<ê1Fš“S\CHCj ;Îp¦uÓ,ªC¢[B4=шN6׎ €ë UP¨©}D96ÜFGþL{}”}‰"ºoôoTši§Ù=¼=â;Qs3\ä5Ù„qê§ŠŠàT i`5ÙˆAÔÒÓFœ×ûFþ§y RÏ(ƒÏ{§×˜ÎšuÁ†óÔ,Áðátše6œV³Ã…óÑ&œÑYñår_þi:¦ù|]'§ùÑδÌtØ¥9¯NpX%£%a·&})³0=6ç²<¬4—2#zŽæRfDoÁQhîß~HgÅæ8cÍýx­Ï×Ï=æ 8cÍçk„÷þGßóÒ<Úéu¡ˆˆú±‘0ì9½æþí™èöÝc"*ŸÿZîœ^ó¼JsˆMwf„aÎyÍ´{H{LMDt9´§m oÎKÓ_¥¡æÒ^yVbXsı¹=â;Å—æ|H‰&1œ9ÂØå= Ó—¯)'Ò`s^W9ªUQXµ?j0Daj<£ö¯±‘¯Òh1lGgâ¬Ó€áÊQkŒ¦¥ÆÓ£ÒXaXrK GÎXcaÈi0ü8C†g qÄpãÈg 3ޤ™áÅ5³0¬8‚F)oÊ'ýøññQÒíy)„ç¥Q`åö§2RÜß.ņÓkTÓì˜*Ÿsy´£òpá<5LsoˆÎa@Íýüh΃›Ö.ß•DDMÙ?Â…'d‰´îž_‘Gõá £"ÉyY¾Ž#ˆrá±"ª5[ vŠvl#s¹ÅT6GDDè–5ƒ·OÞiazüÏfrë€OŸ$á•* JóÂC¨ºë…Q{H”KO+¾‘wx€Ÿ")0rªó@Mòxø¬"P‘œ}ò—È7§ÝgSHyP„*‰‘G²ˆó«ðÛ¢’ @I¯”dƒ—ñÝ®!)%U˜¡Š$ $Âv"$Á)­ ”&Z’ _ÆC<÷@ ò(‚x~ÎUÊgæÒGX’©^fïèwtÉyÄ1€“.³Z…ñÍyíOóh?¼ê\õŒ.Ä·Ò ã™#ì¶›ŸG"î¶óÉwBÎÍ#‘·zäH;ˆçå‘ ÷AúãÈû¡çä1Âxä vw»ç¡Àøã ï#pÍC‰ñÆÝá–ÇÆg|ÇŠK“Oœ±Æ! ÆG¡±ÎC‹ñÂQi,ó0`|p”«<ŒµÆ" Ìþœ 1+Ìîœ)!KÌÞœI6kÌΜi&̾f2'Ì®f"GÌž­F™‡3fGŽ^£Ècf?ŽA3Êcf7ŽI3ÈÃS‹WH÷á5R*Lq? O2×þ:é.³FÈC…©’ñcÒ¤}Òë·{p,4}Êi*sÌž‹$ÂbÉM—ÇSç5€SÔù©ªO©ð»*x^ôïVÞžc¥AÕCL»4 õÚ艈ZÇpmtaº†°Ó ˆ>ɘ,ÒÕNÑ Wñýs+¤` Ùœc©AñG)niÒÚèki”òçKËk£õ~¿)ÇV3ø³vK£˜X%YˆáÚhfÛŽŽµFætK£Sk£ñypÅ`m´³'›½FÊ£[Z­#:\ym´+ª°%ÇA3È£j¸¬ö"6ä¸hä<âpXÊ]lÇqÒˆytû:l×F¥Ú›qÜ4³ó")Š©—…£f&g¯ª*®šYœÝJÄ8kfpö«wã®qæìX¼g†Æ‘³g%¢9'ήe•fi8ûÖˆš§±æì\ðj¦Æ’³wõ®¹+Îî¥Èfk,8û×U›¯1r<‰[ 1p|T¼[¢Ñr¼”ï[¤ÑpüÔ"\¦™äx*¬¸P3ÁñU%r©FÉñVòr±FÁñW¿s¹fÄñXŒt̀㳲ê‰ãµLì*ã·æí:šžã¹€ïJšŽã»ñZQí³žETùÆàc½Þ«åûój/6/Vìïþë滋›a_³[©ÍÍÒÛV]q¦Qyö[ºkÝN²v·²o²^+Vî‹kŹ=Œ‡ÌŒugyžl«k¨üâ¯èõú«86©ZîICM>ª}i¶ ½¾mÎ \K—øÓØLµ“#‡ùLsü¼÷ÛUÞxVàX'ǯÆ|VàÆa>ÓÈm²ù›pïuM31Â?}oËñ®Q·tãòïŸlGÇ»Æ.=DØkœzˆp׸õa®qì!Â[ãÚC„µÆ¹‡g{Æš=Døjæôa«™ÕC„«f^¦š™=Dxjæöa©1õ™äpÔÌï!ÂP³ ‡?Í’"ì4‹zˆpÓ,ë!ÂL³°‡/ÍÒ"¬4‹{ˆpÒ,ï!ÂH³B>š5zˆ°Ñ¬ÒCÄŸ¦”ò°À¨þÁ 8ÇFÌÈ)ÊuÇßÖ8a§n¦.Š#ÆiTxü2+ît> ¦÷%Š7Ö/Oj~tyh1mÙT¤®Ç ¼ #include #include "algebra/nabeliangroup.h" #include "manifold/nsfs.h" #include "triangulation/ncomponent.h" #include "triangulation/nedge.h" #include "triangulation/ntetrahedron.h" #include "subcomplex/naugtrisolidtorus.h" #include "subcomplex/nlayeredchain.h" namespace regina { const int NAugTriSolidTorus::CHAIN_NONE = 0; const int NAugTriSolidTorus::CHAIN_MAJOR = 1; const int NAugTriSolidTorus::CHAIN_AXIS = 2; NAugTriSolidTorus::~NAugTriSolidTorus() { if (core) delete core; for (int i = 0; i < 3; i++) if (augTorus[i]) delete augTorus[i]; } NAugTriSolidTorus* NAugTriSolidTorus::clone() const { NAugTriSolidTorus* ans = new NAugTriSolidTorus(); ans->core = core->clone(); for (int i = 0; i < 3; i++) { if (augTorus[i]) ans->augTorus[i] = augTorus[i]->clone(); ans->edgeGroupRoles[i] = edgeGroupRoles[i]; } ans->chainIndex = chainIndex; ans->chainType = chainType; ans->torusAnnulus = torusAnnulus; return ans; } NManifold* NAugTriSolidTorus::getManifold() const { NSFSpace* ans = new NSFSpace(); if (chainType == CHAIN_MAJOR) { // Layered solid torus + layered chain. ans->insertFibre(2, 1); ans->insertFibre(chainIndex + 1, 1); long q, r; if (edgeGroupRoles[torusAnnulus][2] == 2) { if (augTorus[torusAnnulus]) { r = augTorus[torusAnnulus]->getMeridinalCuts( edgeGroupRoles[torusAnnulus][0]); q = augTorus[torusAnnulus]->getMeridinalCuts( edgeGroupRoles[torusAnnulus][1]); } else { r = 1; q = 1; } } else { if (augTorus[torusAnnulus]) { r = augTorus[torusAnnulus]->getMeridinalCuts( edgeGroupRoles[torusAnnulus][0]); q = -augTorus[torusAnnulus]->getMeridinalCuts( edgeGroupRoles[torusAnnulus][1]); } else { r = (edgeGroupRoles[torusAnnulus][0] == 2 ? 2 : 1); q = -(edgeGroupRoles[torusAnnulus][1] == 2 ? 2 : 1); } } r = r - q; if (r < 0) { r = -r; q = -q; } if (r == 0) { delete ans; return 0; } else ans->insertFibre(r, q); } else if (chainType == CHAIN_AXIS) { // Layered solid torus + layered chain. ans->insertFibre(2, 1); ans->insertFibre(2, -1); long q, r; if (edgeGroupRoles[torusAnnulus][2] == 2) { if (augTorus[torusAnnulus]) { r = augTorus[torusAnnulus]->getMeridinalCuts( edgeGroupRoles[torusAnnulus][0]); q = augTorus[torusAnnulus]->getMeridinalCuts( edgeGroupRoles[torusAnnulus][1]); } else { r = 1; q = 1; } } else { if (augTorus[torusAnnulus]) { r = augTorus[torusAnnulus]->getMeridinalCuts( edgeGroupRoles[torusAnnulus][0]); q = -augTorus[torusAnnulus]->getMeridinalCuts( edgeGroupRoles[torusAnnulus][1]); } else { r = (edgeGroupRoles[torusAnnulus][0] == 2 ? 2 : 1); q = -(edgeGroupRoles[torusAnnulus][1] == 2 ? 2 : 1); } } long alpha = q - chainIndex * r; long beta = -r; if (alpha < 0) { alpha = -alpha; beta = -beta; } if (alpha == 0) { delete ans; return 0; } else ans->insertFibre(alpha, beta); } else { // Three layered solid tori. ans->insertFibre(1, 1); long alpha, beta; for (int i = 0; i < 3; i++) { if (edgeGroupRoles[i][2] == 2) { if (augTorus[i]) { alpha = augTorus[i]->getMeridinalCuts(edgeGroupRoles[i][0]); beta = augTorus[i]->getMeridinalCuts(edgeGroupRoles[i][1]); } else { alpha = 1; beta = 1; } } else { if (augTorus[i]) { alpha = augTorus[i]->getMeridinalCuts(edgeGroupRoles[i][0]); beta = -augTorus[i]->getMeridinalCuts(edgeGroupRoles[i][1]); } else { alpha = (edgeGroupRoles[i][0] == 2 ? 2 : 1); beta = -(edgeGroupRoles[i][1] == 2 ? 2 : 1); } } if (alpha == 0) { delete ans; return 0; } else ans->insertFibre(alpha, beta); } } ans->reduce(); return ans; } NAugTriSolidTorus* NAugTriSolidTorus::isAugTriSolidTorus( const NComponent* comp) { // Basic property checks. if ((! comp->isClosed()) || (! comp->isOrientable())) return 0; if (comp->getNumberOfVertices() > 1) return 0; // We have a 1-vertex closed orientable triangulation. unsigned long nTet = comp->getNumberOfTetrahedra(); if (nTet < 3) return 0; // Handle the 3-tetrahedron case separately. if (nTet == 3) { // Note that there cannot be a layered chain. NTetrahedron* base = comp->getTetrahedron(0); NTriSolidTorus* core; NPerm4 annulusMap[3]; // Check every possible choice of vertex roles in tetrahedron 0. // Note that (a,b,c,d) gives an equivalent core to (d,c,b,a). int i, j; for (i = 0; i < 24; i++) { // Make sure we don't check each possible core twice. if (NPerm4::S4[i][0] > NPerm4::S4[i][3]) continue; core = NTriSolidTorus::formsTriSolidTorus(base, NPerm4::S4[i]); if (core) { // Check that the annuli are being glued to themselves. // Since the component is orientable, that's all we need // to know. for (j = 0; j < 3; j++) { if (! core->isAnnulusSelfIdentified(j, annulusMap + j)) { delete core; core = 0; break; } } if (core) { // We got one! NAugTriSolidTorus* ans = new NAugTriSolidTorus(); ans->core = core; // Work out how the mobius strip is glued onto each // annulus. for (j = 0; j < 3; j++) { switch (annulusMap[j][0]) { case 0: ans->edgeGroupRoles[j] = NPerm4(2, 0, 1, 3); break; case 2: ans->edgeGroupRoles[j] = NPerm4(1, 2, 0, 3); break; case 3: ans->edgeGroupRoles[j] = NPerm4(0, 1, 2, 3); break; } } ans->chainIndex = 0; ans->chainType = CHAIN_NONE; ans->torusAnnulus = -1; return ans; } } } // Didn't find anything. return 0; } // We have strictly more than three tetrahedra. // There must be bewteen 0 and 3 layered solid tori (note that there // will be no layered solid tori other than the (0-3) glued to the // boundary annuli on the core, since no other tetrahedron is glued // to itself. int nLayered = 0; NLayeredSolidTorus* layered[4]; unsigned long usedTets = 0; for (unsigned long t = 0; t < nTet; t++) { layered[nLayered] = NLayeredSolidTorus::formsLayeredSolidTorusBase( comp->getTetrahedron(t)); if (layered[nLayered]) { usedTets += layered[nLayered]->getNumberOfTetrahedra(); nLayered++; if (nLayered == 4) { // Too many layered solid tori. for (int i = 0; i < nLayered; i++) delete layered[i]; return 0; } } } if (nLayered == 0) { // Our only chance now is a layered chain plus a degenerate // layered solid torus. // Start with tetrahedron 0. Either it belongs to the chain or // it belongs to the core. NTetrahedron* tet = comp->getTetrahedron(0); // Run through all possible cores to which it might belong. int i; NPerm4 p, annulusPerm; NTriSolidTorus* core; int torusAnnulus; unsigned long chainLen; for (i = 0; i < 24; i++) { p = NPerm4::S4[i]; if (p[0] > p[3]) continue; core = NTriSolidTorus::formsTriSolidTorus(tet, p); if (! core) continue; // Let's try this core. // Look for an identified annulus. for (torusAnnulus = 0; torusAnnulus < 3; torusAnnulus++) if (core->isAnnulusSelfIdentified(torusAnnulus, &annulusPerm)) { // Look now for a layered chain. // If we don't find it, the entire core must be wrong. int chainType = CHAIN_NONE; if ((chainLen = core->areAnnuliLinkedMajor(torusAnnulus))) chainType = CHAIN_MAJOR; else if ((chainLen = core->areAnnuliLinkedAxis(torusAnnulus))) chainType = CHAIN_AXIS; if (chainType == CHAIN_NONE || chainLen + 3 != nTet) break; // We have the entire structure! NAugTriSolidTorus* ans = new NAugTriSolidTorus(); ans->core = core; switch (annulusPerm[0]) { case 0: ans->edgeGroupRoles[torusAnnulus] = NPerm4(2,0,1,3); break; case 2: ans->edgeGroupRoles[torusAnnulus] = NPerm4(1,2,0,3); break; case 3: ans->edgeGroupRoles[torusAnnulus] = NPerm4(0,1,2,3); break; } ans->chainIndex = chainLen; ans->chainType = chainType; ans->torusAnnulus = torusAnnulus; return ans; } // Didn't find anything. delete core; } // Wasn't the core. Must have been the chain. NTetrahedron* top; NTetrahedron* bottom; NPerm4 topRoles; NPerm4 bottomRoles; int j; int chainType; for (i = 0; i < 6; i++) { p = NPerm4::S3[i]; NLayeredChain chain(tet, p); chain.extendMaximal(); // Note that the chain will run into one of the core tetrahedra. if (chain.getIndex() + 2 == nTet) chainType = CHAIN_MAJOR; else if (chain.getIndex() + 3 == nTet) chainType = CHAIN_AXIS; else continue; // Look for the corresponding core. // The identified annulus on the core will have to be annulus 0. // Test the chain at both ends (bottom / top). for (j = 0; j < 2; j++) { if (chainType == CHAIN_MAJOR) { core = NTriSolidTorus::formsTriSolidTorus(chain.getBottom(), chain.getBottomVertexRoles() * NPerm4(2, 3, 0, 1)); if (core) { // Test that everything is put together properly. top = chain.getTop(); topRoles = chain.getTopVertexRoles(); if ((top->adjacentTetrahedron(topRoles[0]) == core->getTetrahedron(1)) && (top->adjacentTetrahedron(topRoles[3]) == core->getTetrahedron(2)) && (top->adjacentGluing(topRoles[0]) * topRoles * NPerm4(1, 0, 2, 3) == core->getVertexRoles(1)) && (top->adjacentGluing(topRoles[3]) * topRoles * NPerm4(0, 1, 3, 2) == core->getVertexRoles(2)) && core->isAnnulusSelfIdentified( 0, &annulusPerm)) { // We have the entire structure! NAugTriSolidTorus* ans = new NAugTriSolidTorus(); ans->core = core; switch (annulusPerm[0]) { case 0: ans->edgeGroupRoles[0] = NPerm4(2, 0, 1, 3); break; case 2: ans->edgeGroupRoles[0] = NPerm4(1, 2, 0, 3); break; case 3: ans->edgeGroupRoles[0] = NPerm4(0, 1, 2, 3); break; } ans->chainIndex = chain.getIndex() - 1; ans->chainType = chainType; ans->torusAnnulus = 0; return ans; } delete core; } } else if (chainType == CHAIN_AXIS) { bottom = chain.getBottom(); bottomRoles = chain.getBottomVertexRoles(); NTetrahedron* startCore = bottom->adjacentTetrahedron( bottomRoles[2]); if (startCore) core = NTriSolidTorus::formsTriSolidTorus(startCore, bottom->adjacentGluing( bottomRoles[2]) * bottomRoles * NPerm4(0, 3, 2, 1)); else core = 0; if (core) { // Test that everything is put together properly. top = chain.getTop(); topRoles = chain.getTopVertexRoles(); if ((bottom->adjacentTetrahedron(bottomRoles[1]) == core->getTetrahedron(1)) && (top->adjacentTetrahedron(topRoles[0]) == core->getTetrahedron(0)) && (top->adjacentTetrahedron(topRoles[3]) == core->getTetrahedron(2)) && (bottom->adjacentGluing( bottomRoles[1]) * bottomRoles * NPerm4(2, 1, 0, 3) == core->getVertexRoles(1)) && (top->adjacentGluing(topRoles[0]) * topRoles * NPerm4(3, 0, 1, 2) == core->getVertexRoles(0)) && (top->adjacentGluing(topRoles[3]) * topRoles * NPerm4(1, 2, 3, 0) == core->getVertexRoles(2)) && core->isAnnulusSelfIdentified( 0, &annulusPerm)) { // We have the entire structure! NAugTriSolidTorus* ans = new NAugTriSolidTorus(); ans->core = core; switch (annulusPerm[0]) { case 0: ans->edgeGroupRoles[0] = NPerm4(2, 0, 1, 3); break; case 2: ans->edgeGroupRoles[0] = NPerm4(1, 2, 0, 3); break; case 3: ans->edgeGroupRoles[0] = NPerm4(0, 1, 2, 3); break; } ans->chainIndex = chain.getIndex(); ans->chainType = chainType; ans->torusAnnulus = 0; return ans; } delete core; } } // If we just tested the bottom, prepare to test the top. if (j == 0) chain.reverse(); } } // Didn't find anything. return 0; } // We now know nLayered >= 1. int i, j; // Determine whether or not this augmented solid torus must contain a // layered chain. bool needChain = (usedTets + 3 != nTet); if (needChain && nLayered != 1) { for (j = 0; j < nLayered; j++) delete layered[j]; return 0; } // Examine each layered solid torus. NTetrahedron* top[3]; for (i = 0; i < nLayered; i++) { top[i] = layered[i]->getTopLevel(); if (top[i]->adjacentTetrahedron(layered[i]->getTopFace(0)) == top[i]->adjacentTetrahedron(layered[i]->getTopFace(1))) { // These two top triangles should be glued to different // tetrahedra. for (j = 0; j < nLayered; j++) delete layered[j]; return 0; } } // Run to the top of the first layered solid torus; this should give // us our core. int topFace = layered[0]->getTopFace(0); NTetrahedron* coreTet = top[0]->adjacentTetrahedron(topFace); // We will declare that this triangle hooks onto vertex roles 0, 1 and 3 // of the first core tetrahedron. Thus the vertex roles permutation // should map 0, 1 and 3 (in some order) to all vertices except for // topCoreFace. int topCoreFace = top[0]->adjacentFace(topFace); NPerm4 swap3Top(3, topCoreFace); NPerm4 swap23(2, 3); NTriSolidTorus* core; NTetrahedron* coreTets[3]; NPerm4 coreVertexRoles[3]; int whichLayered[3]; int usedLayered; NPerm4 edgeGroupRoles[3]; int torusAnnulus; NPerm4 q; for (int p = 0; p < 6; p++) { core = NTriSolidTorus::formsTriSolidTorus(coreTet, swap3Top * NPerm4::S3[p] * swap23); if (core) { // We have a potential core. // Now all that remains is to ensure that the layered solid // tori hang from it accordingly. for (j = 0; j < 3; j++) { coreTets[j] = core->getTetrahedron(j); coreVertexRoles[j] = core->getVertexRoles(j); } usedLayered = 0; torusAnnulus = -1; for (j = 0; j < 3; j++) { // Check annulus j. // Recall that the 3-manifold is orientable so we don't // have to check for wacky reversed gluings. if (core->isAnnulusSelfIdentified(j, &q)) { // We have a degenerate (2,1,1) glued in here. if (needChain) { // We already know there is a non-degenerate // layered solid torus floating about, and the // other two annuli are reserved for the layered // chain. delete core; core = 0; break; } whichLayered[j] = -1; switch (q[0]) { case 0: edgeGroupRoles[j] = NPerm4(2, 0, 1, 3); break; case 2: edgeGroupRoles[j] = NPerm4(1, 2, 0, 3); break; case 3: edgeGroupRoles[j] = NPerm4(0, 1, 2, 3); break; } } else { // There should be a layered solid torus glued in here. for (whichLayered[j] = 0; whichLayered[j] < nLayered; whichLayered[j]++) if (coreTets[(j+1)%3]->adjacentTetrahedron( coreVertexRoles[(j+1)%3][2]) == top[whichLayered[j]] && coreTets[(j+2)%3]->adjacentTetrahedron( coreVertexRoles[(j+2)%3][1]) == top[whichLayered[j]]) { // Annulus j is glued to torus whichLayered[j]. q = coreTets[(j+1)%3]-> adjacentGluing( coreVertexRoles[(j+1)%3][2]) * coreVertexRoles[(j+1)%3]; // q maps vertex roles in core tetrahedron j+1 to // vertices of the top tetrahedron in // layered[whichLayered[j]]. edgeGroupRoles[j] = NPerm4( layered[whichLayered[j]]->getTopEdgeGroup( NEdge::edgeNumber[q[0]][q[3]]), layered[whichLayered[j]]->getTopEdgeGroup( NEdge::edgeNumber[q[0]][q[1]]), layered[whichLayered[j]]->getTopEdgeGroup( NEdge::edgeNumber[q[1]][q[3]]), 3); usedLayered++; break; } if (whichLayered[j] >= nLayered) { // This annulus was glued neither to itself nor // to a layered solid torus. if (needChain) whichLayered[j] = -1; else { delete core; core = 0; break; } } else { // This annulus was glued to a layered solid torus. if (needChain) torusAnnulus = j; } } } if (! core) continue; if (usedLayered < nLayered) { // We didn't use all our layered solid tori. delete core; continue; } if (needChain) { // We found our one layered solid torus. The other two // boundary annuli *must* be linked via a layered chain. int chainType = CHAIN_NONE; unsigned long chainLen; if ((chainLen = core->areAnnuliLinkedMajor(torusAnnulus))) chainType = CHAIN_MAJOR; else if ((chainLen = core->areAnnuliLinkedAxis(torusAnnulus))) chainType = CHAIN_AXIS; if (chainType == CHAIN_NONE || usedTets + chainLen + 3 != nTet) { delete core; continue; } // We've got one! NAugTriSolidTorus* ans = new NAugTriSolidTorus(); ans->core = core; for (j = 0; j < 3; j++) { if (whichLayered[j] >= 0) { ans->augTorus[j] = layered[whichLayered[j]]; ans->edgeGroupRoles[j] = edgeGroupRoles[j]; } } ans->chainIndex = chainLen; ans->chainType = chainType; ans->torusAnnulus = torusAnnulus; return ans; } else { // We're not looking for a layered chain. // This means we have found the entire structure! NAugTriSolidTorus* ans = new NAugTriSolidTorus(); ans->core = core; for (j = 0; j < 3; j++) { ans->edgeGroupRoles[j] = edgeGroupRoles[j]; if (whichLayered[j] >= 0) ans->augTorus[j] = layered[whichLayered[j]]; } ans->chainIndex = 0; ans->chainType = CHAIN_NONE; ans->torusAnnulus = -1; return ans; } } } // Nothing was found. for (i = 0; i < nLayered; i++) delete layered[i]; return 0; } std::ostream& NAugTriSolidTorus::writeCommonName(std::ostream& out, bool tex) const { if (chainIndex) { // We have a layered solid torus and a layered chain. NPerm4 roles = edgeGroupRoles[torusAnnulus]; const NLayeredSolidTorus* torus = augTorus[torusAnnulus]; long params[3]; if (torus) { params[0] = torus->getMeridinalCuts(0); params[1] = torus->getMeridinalCuts(1); params[2] = - torus->getMeridinalCuts(2); } else { params[0] = 1; params[1] = 1; params[2] = -2; } if (params[roles[0]] < 0) { params[0] = - params[0]; params[1] = - params[1]; params[2] = - params[2]; } if (chainType == CHAIN_MAJOR) out << (tex ? "J_{" : "J("); else out << (tex ? "X_{" : "X("); return out << chainIndex << " | " << params[roles[0]] << ',' << params[roles[1]] << (tex ? '}' : ')'); } else { // We have three layered solid tori. std::pair allParams[3]; int nAllParams = 0; NPerm4 roles; const NLayeredSolidTorus* torus; long params[3]; std::pair lstParams; int i; for (i = 0; i < 3; i++) { roles = edgeGroupRoles[i]; torus = augTorus[i]; if (torus) { params[0] = torus->getMeridinalCuts(0); params[1] = torus->getMeridinalCuts(1); params[2] = - torus->getMeridinalCuts(2); } else { params[0] = 1; params[1] = 1; params[2] = -2; } lstParams = std::make_pair(params[roles[0]], params[roles[1]]); if (lstParams.first < 0) { lstParams.first = - lstParams.first; lstParams.second = - lstParams.second; } if (! (lstParams.first == 2 && lstParams.second == -1)) allParams[nAllParams++] = lstParams; } sort(allParams, allParams + nAllParams); out << (tex ? "A_{" : "A("); for (i = 0; i < nAllParams; i++) { if (i > 0) out << " | "; out << allParams[i].first << ',' << allParams[i].second; } return out << (tex ? '}' : ')'); } } std::ostream& NAugTriSolidTorus::writeName(std::ostream& out) const { return writeCommonName(out, false); } std::ostream& NAugTriSolidTorus::writeTeXName(std::ostream& out) const { return writeCommonName(out, true); } void NAugTriSolidTorus::writeTextLong(std::ostream& out) const { out << (chainIndex ? "Chained " : "Augmented ") << "triangular solid torus " << (torusAnnulus == -1 ? "(three tori): " : "(torus + chain): "); writeName(out); } } // namespace regina regina-4.96/engine/subcomplex/naugtrisolidtorus.h000644 000765 000024 00000031504 12377775433 022235 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/naugtrisolidtorus.h * \brief Deals with augmented triangular solid torus components of a * triangulation. */ #ifndef __NAUGTRISOLIDTORUS_H #ifndef __DOXYGEN #define __NAUGTRISOLIDTORUS_H #endif #include "regina-core.h" #include "subcomplex/ntrisolidtorus.h" #include "subcomplex/nlayeredsolidtorus.h" namespace regina { class NComponent; /** * \weakgroup subcomplex * @{ */ /** * Represents an augmented triangular solid torus component of a * triangulation. Such a component is obtained as follows. Begin with * a three-tetrahedron triangular solid torus (as described by * NTriSolidTorus). Observe that the three axis edges divide the * boundary into three annuli. Then take one of the following actions. * * - To each of these annuli, glue a layered solid torus. * Note that the degenerate (2,1,1) layered solid torus * (i.e., a one-triangle mobius strip) is allowed and corresponds to * simply gluing the two triangles of the annulus together. * * - To one of these annuli, glue a layered solid torus as described * above. Join the other two annuli with a layered chain * in either the manner described by * NTriSolidTorus::areAnnuliLinkedMajor() or the manner described by * NTriSolidTorus::areAnnuliLinkedAxis(). * * It will be assumed that all layered solid tori other than the * degenerate (2,1,1) will have (3,2,1) layered solid tori at their * bases. That is, layered solid tori that begin with the degenerate * (2,1,1) and layer over the boundary of the mobius strip are \b not * considered in this class. * * Note that (unless a (1,1,0) layered solid torus is used with the 0 * edge glued to an axis edge) the resulting space will be a Seifert * fibred space over the 2-sphere with at most three exceptional fibres. * * Of the optional NStandardTriangulation routines, getManifold() is * implemented for most augmented triangular solid tori and * getHomologyH1() is not implemented at all. */ class REGINA_API NAugTriSolidTorus : public NStandardTriangulation { public: static const int CHAIN_NONE; /**< Indicates that this augmented triangular solid torus contains no layered chain. */ static const int CHAIN_MAJOR; /**< Indicates that this augmented triangular solid torus contains a layered chain attached as described by NTriSolidTorus::areAnnuliLinkedMajor(). */ static const int CHAIN_AXIS; /**< Indicates that this augmented triangular solid torus contains a layered chain attached as described by NTriSolidTorus::areAnnuliLinkedAxis(). */ private: NTriSolidTorus* core; /**< The triangular solid torus at the core of this triangulation. */ NLayeredSolidTorus* augTorus[3]; /**< The layered solid tori attached to the boundary annuli. If one of the layered solid tori is a degenerate (2,1,1) triangle, the corresponding pointer will be 0. Note that augTorus[i] will be attached to annulus \c i of the triangular solid torus. */ NPerm4 edgeGroupRoles[3]; /**< Permutation edgeGroupRoles[i] describes the role played by each top level edge group of layered solid torus i. For permutation p, group p[0] is glued to an axis edge, group p[1] is glued to a major edge and group p[2] is glued to a minor edge. */ unsigned long chainIndex; /**< The number of tetrahedra in the layered chain if present, or 0 if there is no layered chain. */ int chainType; /**< The way in which the layered chain is attached, or \a CHAIN_NONE if there is no layered chain. */ int torusAnnulus; /**< The annulus to which the single layered solid torus is attached (if there is a layered chain), or -1 if there is no layered chain. */ public: /** * Destroys this augmented solid torus; note that the corresponding * triangular and layered solid tori will also be destroyed. */ virtual ~NAugTriSolidTorus(); /** * Returns a newly created clone of this structure. * * @return a newly created clone. */ NAugTriSolidTorus* clone() const; /** * Returns the triangular solid torus at the core of this * triangulation. * * @return the core triangular solid torus. */ const NTriSolidTorus& getCore() const; /** * Returns the layered solid torus attached to the requested * annulus on the boundary of the core triangular solid torus. * If the layered solid torus is a degenerate (2,1,1) mobius * band (i.e., the two triangles of the corresponding annulus have * simply been glued together), \c null will be returned. * * @param annulus specifies which annulus to examine; this must * be 0, 1 or 2. * @return the corresponding layered solid torus. */ const NLayeredSolidTorus* getAugTorus(int annulus) const; /** * Returns a permutation describing the role played by each top * level edge group of the layered solid torus glued to the * requested annulus of the core triangular solid torus. See * NLayeredSolidTorus::getTopEdge() for details regarding edge groups. * * If the permutation returned is p, edge group p[0] * will be glued to an axis edge, group p[1] will be * glued to a major edge and group p[2] will be glued * to a minor edge. p[3] will always be 3. * * Even if the corresponding layered solid torus is a degenerate * (2,1,1) mobius band (i.e., getAugTorus() returns \c null), * the concept of edge groups is still * meaningful and this routine will return correct results. * * @param annulus specifies which annulus to examine; this must * be 0, 1 or 2. It is the layered solid torus glued to this * annulus whose edge groups will be described. * @return a permutation describing the roles of the * corresponding top level edge groups. */ NPerm4 getEdgeGroupRoles(int annulus) const; /** * Returns the number of tetrahedra in the layered chain linking * two of the boundary annuli of the core triangular solid torus. * Note that this count does not include any of the tetrahedra * actually belonging to the triangular solid torus. * * @return the number of tetrahedra in the layered chain, or 0 * if there is no layered chain linking two boundary annuli. */ unsigned long getChainLength() const; /** * Returns the way in which a layered chain links * two of the boundary annuli of the core triangular solid torus. * This will be one of the chain type constants defined in this * class. * * @return the type of layered chain, or \a CHAIN_NONE * if there is no layered chain linking two boundary annuli. */ int getChainType() const; /** * Returns the single boundary annulus of the core triangular * solid torus to which a layered solid torus is attached. This * routine is only meaningful if the other two annuli are linked * by a layered chain. * * The integer returned will be 0, 1 or 2; see the * NTriSolidTorus class notes for how the boundary annuli are * numbered. * * @return the single annulus to which the layered solid torus * is attached, or -1 if there is no layered chain (and thus all * three annuli have layered solid tori attached). */ int getTorusAnnulus() const; /** * Determines whether the core triangular solid torus has two of * its boundary annuli linked by a layered chain as described in * the general class notes. * * @return \c true if and only if the layered chain described in * the class notes is present. */ bool hasLayeredChain() const; /** * Determines if the given triangulation component is an * augmented triangular solid torus. * * @param comp the triangulation component to examine. * @return a newly created structure containing details of the * augmented triangular solid torus, or \c null if the given * component is not an augmented triangular solid torus. */ static NAugTriSolidTorus* isAugTriSolidTorus(const NComponent* comp); NManifold* getManifold() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; void writeTextLong(std::ostream& out) const; private: /** * Creates a new structure with all subcomponent pointers * initialised to \c null. */ NAugTriSolidTorus(); /** * Contains code common to both writeName() and writeTeXName(). * * @param out the output stream to which to write. * @param tex \c true if this routine is called from * writeTeXName() or \c false if it is called from writeName(). * @return a reference to \a out. */ std::ostream& writeCommonName(std::ostream& out, bool tex) const; }; /*@}*/ // Inline functions for NAugTriSolidTorus inline NAugTriSolidTorus::NAugTriSolidTorus() : core(0), chainType(CHAIN_NONE) { augTorus[0] = augTorus[1] = augTorus[2] = 0; } inline const NTriSolidTorus& NAugTriSolidTorus::getCore() const { return *core; } inline const NLayeredSolidTorus* NAugTriSolidTorus::getAugTorus( int annulus) const { return augTorus[annulus]; } inline NPerm4 NAugTriSolidTorus::getEdgeGroupRoles(int annulus) const { return edgeGroupRoles[annulus]; } inline unsigned long NAugTriSolidTorus::getChainLength() const { return chainIndex; } inline int NAugTriSolidTorus::getChainType() const { return chainType; } inline int NAugTriSolidTorus::getTorusAnnulus() const { return torusAnnulus; } inline bool NAugTriSolidTorus::hasLayeredChain() const { return (chainIndex != 0); } } // namespace regina #endif regina-4.96/engine/subcomplex/nblockedsfs.cpp000644 000765 000024 00000044063 12377776660 021273 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "manifold/nsfs.h" #include "subcomplex/nblockedsfs.h" #include "subcomplex/nlayeredsolidtorus.h" #include "subcomplex/nsatblockstarter.h" #include "subcomplex/nsatblocktypes.h" #include "subcomplex/nsatregion.h" #include // For labs(). #include namespace regina { namespace { /** * An anonymous inline boolean xor. Experiences with plain C have * spoiled me for life from using equality/xor operators with bools. */ inline bool regXor(bool a, bool b) { return ((a && ! b) || (b && !a)); } } /** * A subclass of NSatBlockStartSearcher that, upon finding a starter * saturated block, attempts to flesh this out to a saturated region * that fills the entire triangulation (including all internal triangles). */ struct NBlockedSFSSearcher : public NSatBlockStarterSearcher { NSatRegion* region; /**< The saturated region if one has been found, or 0 if we are still searching. */ /** * Creates a new searcher whose \a region pointer is null. */ NBlockedSFSSearcher() : region(0) { } protected: bool useStarterBlock(NSatBlock* starter); }; NBlockedSFS::~NBlockedSFS() { if (region_) delete region_; } bool NBlockedSFS::isPluggedIBundle(std::string& name) const { // The triangulation needs to be closed. if (region_->numberOfBoundaryAnnuli() > 0) return false; unsigned long n = region_->numberOfBlocks(); if (n < 3 || n > 4) return false; // Try one thing at a time. const NSatBlock* block; const NSatCube* cube; const NSatReflectorStrip* ref; const NSatTriPrism* tri; const NSatTriPrism* triAdj; unsigned adjAnn; unsigned long i, j; int delta, deltaAdj; bool consistent; for (i = 0; i < n; i++) { block = region_->block(i).block; cube = dynamic_cast(block); if (cube) { if (cube->adjacentBlock(0) == cube && cube->adjacentAnnulus(0) == 2) { if (cube->adjacentReflected(0) || cube->adjacentBackwards(0)) return false; return findPluggedTori(true, 3, name, cube->adjacentBlock(1), true, cube->adjacentBlock(3), false); } else if (cube->adjacentBlock(1) == cube && cube->adjacentAnnulus(1) == 3) { if (cube->adjacentReflected(1) || cube->adjacentBackwards(1)) return false; return findPluggedTori(true, 3, name, cube->adjacentBlock(0), true, cube->adjacentBlock(2), false); } else if (cube->adjacentBlock(0) == cube && cube->adjacentAnnulus(0) == 1) { if (cube->adjacentReflected(0) || cube->adjacentBackwards(0)) return false; return findPluggedTori(false, 1, name, cube->adjacentBlock(2), false, cube->adjacentBlock(3), true); } else if (cube->adjacentBlock(1) == cube && cube->adjacentAnnulus(1) == 2) { if (cube->adjacentReflected(1) || cube->adjacentBackwards(1)) return false; return findPluggedTori(false, 1, name, cube->adjacentBlock(3), false, cube->adjacentBlock(0), true); } else if (cube->adjacentBlock(2) == cube && cube->adjacentAnnulus(2) == 3) { if (cube->adjacentReflected(2) || cube->adjacentBackwards(2)) return false; return findPluggedTori(false, 1, name, cube->adjacentBlock(0), false, cube->adjacentBlock(1), true); } else if (cube->adjacentBlock(3) == cube && cube->adjacentAnnulus(3) == 0) { if (cube->adjacentReflected(3) || cube->adjacentBackwards(3)) return false; return findPluggedTori(false, 1, name, cube->adjacentBlock(1), false, cube->adjacentBlock(2), true); } } ref = dynamic_cast(block); if (ref) { if (ref->twistedBoundary()) return false; if (ref->nAnnuli() == 1) { tri = dynamic_cast(ref->adjacentBlock(0)); if (! tri) return false; adjAnn = ref->adjacentAnnulus(0); if (tri->isMajor()) return findPluggedTori(false, 4, name, tri->adjacentBlock((adjAnn + 2) % 3), true, tri->adjacentBlock((adjAnn + 1) % 3), false); else return findPluggedTori(false, 4, name, tri->adjacentBlock((adjAnn + 1) % 3), false, tri->adjacentBlock((adjAnn + 2) % 3), true); } else if (ref->nAnnuli() == 2) { return findPluggedTori(true, 4, name, ref->adjacentBlock(0), true, ref->adjacentBlock(1), true); } else return false; } tri = dynamic_cast(block); if (tri) { for (j = 0; j < 3; j++) { // Try the thick case... if (tri->adjacentBlock(j) == tri && tri->adjacentAnnulus(j) == ((j + 1) % 3)) { if (tri->adjacentReflected(j) || tri->adjacentBackwards(j)) return false; triAdj = dynamic_cast( tri->adjacentBlock((j + 2) % 3)); if (! triAdj) return false; // Do we have major to major and minor to minor? consistent = true; if (tri->isMajor()) consistent = ! consistent; if (triAdj->isMajor()) consistent = ! consistent; if (tri->adjacentReflected((j + 2) % 3)) consistent = ! consistent; if (tri->adjacentBackwards((j + 2) % 3)) consistent = ! consistent; adjAnn = tri->adjacentAnnulus((j + 2) % 3); if (consistent) { if (triAdj->isMajor()) return findPluggedTori(false, 2, name, triAdj->adjacentBlock((adjAnn + 1) % 3), false, triAdj->adjacentBlock((adjAnn + 2) % 3), true); else return findPluggedTori(false, 2, name, triAdj->adjacentBlock((adjAnn + 2) % 3), true, triAdj->adjacentBlock((adjAnn + 1) % 3), false); } else { if (triAdj->isMajor()) return findPluggedTori(false, 3, name, triAdj->adjacentBlock((adjAnn + 2) % 3), true, triAdj->adjacentBlock((adjAnn + 1) % 3), true); else return findPluggedTori(false, 3, name, triAdj->adjacentBlock((adjAnn + 1) % 3), false, triAdj->adjacentBlock((adjAnn + 2) % 3), false); } } // ... and try the thin case. if (! (triAdj = dynamic_cast( tri->adjacentBlock(j)))) continue; // Do we have major to major and minor to minor? consistent = true; if (tri->isMajor()) consistent = ! consistent; if (triAdj->isMajor()) consistent = ! consistent; if (tri->adjacentReflected(j)) consistent = ! consistent; if (tri->adjacentBackwards(j)) consistent = ! consistent; adjAnn = tri->adjacentAnnulus(j); for (delta = 1; delta <= 2; delta++) if (tri->adjacentBlock((j + delta) % 3) == triAdj) { if (regXor(tri->adjacentReflected(j), tri->adjacentReflected((j + delta) % 3))) return false; if (! regXor(tri->adjacentBackwards(j), tri->adjacentBackwards((j + delta) % 3))) return false; // We have our Mobius strip! // Make sure we come at it via the correct joining. deltaAdj = (tri->adjacentBackwards(j) ? 3 - delta : delta); if (tri->adjacentAnnulus((j + delta) % 3) != (adjAnn + deltaAdj) % 3) { // It's not the way we want to see it, but // we'll come at it from the correct joining later. continue; } // Our LSTs need to be measured against the // major edges in all cases here. return findPluggedTori(true, consistent ? 2 : 1, name, tri->adjacentBlock((j + 2 * delta) % 3), tri->isMajor(), triAdj->adjacentBlock((adjAnn + 2 * deltaAdj) % 3), triAdj->isMajor()); } } } } // Nothing. return false; } NManifold* NBlockedSFS::getManifold() const { NSFSpace* ans = region_->createSFS(false); if (! ans) return 0; ans->reduce(); // If we have SFS(RP2/n2) with one exceptional fibre, rewrite it as // SFS(S2) with three exceptional fibres. if (ans->baseClass() == NSFSpace::n2 && ans->baseGenus() == 1 && (! ans->baseOrientable()) && ans->punctures() == 0 && ans->reflectors() == 0 && ans->fibreCount() <= 1) { NSFSpace* altAns = new NSFSpace(/* S2 x S1 */); altAns->insertFibre(2, 1); altAns->insertFibre(2, -1); NSFSFibre rp2Fibre; if (ans->fibreCount() == 0) { rp2Fibre.alpha = 1; rp2Fibre.beta = ans->obstruction(); } else { rp2Fibre = ans->fibre(0); rp2Fibre.beta += rp2Fibre.alpha * ans->obstruction(); } // Make sure we're not going to try inserting (0,k). if (rp2Fibre.beta != 0) { altAns->insertFibre(rp2Fibre.beta, rp2Fibre.alpha); altAns->reduce(); delete ans; return altAns; } else delete altAns; } return ans; } std::ostream& NBlockedSFS::writeName(std::ostream& out) const { out << "Blocked SFS ["; region_->writeBlockAbbrs(out, false); return out << ']'; } std::ostream& NBlockedSFS::writeTeXName(std::ostream& out) const { out << "\\mathrm{BSFS}\\left["; region_->writeBlockAbbrs(out, true); return out << "\\right]"; } void NBlockedSFS::writeTextLong(std::ostream& out) const { region_->writeDetail(out, "Blocked SFS"); } NBlockedSFS* NBlockedSFS::isBlockedSFS(NTriangulation* tri) { // Basic property checks. if (tri->getNumberOfComponents() > 1) return 0; if (tri->isIdeal()) return 0; // Watch out for twisted block boundaries that are incompatible with // neighbouring blocks! These will result in edges joined to // themselves in reverse. if (! tri->isValid()) return 0; // Hunt for a starting block. NBlockedSFSSearcher searcher; searcher.findStarterBlocks(tri); // Any luck? if (searcher.region) { // The region expansion worked, and the triangulation is known // to be connected. // This means we've got one! return new NBlockedSFS(searcher.region); } // Nope. return 0; } bool NBlockedSFSSearcher::useStarterBlock(NSatBlock* starter) { // The region pointer should be null, but just in case... if (region) { delete starter; return false; } // See if we can flesh out an entire triangulation component from // the starter block. At this point the region will own the given // starter block. region = new NSatRegion(starter); if (! region->expand(usedTets, true)) { // Nup. Destroy the temporary structures and keep searching. delete region; region = 0; return true; } // Got one! Stop the search. return false; } bool NBlockedSFS::findPluggedTori(bool thin, int id, std::string& name, const NSatBlock* torus0, bool horiz0, const NSatBlock* torus1, bool horiz1) { long p0, q0; long p1, q1; if (torus0->adjacentReflected(0)) horiz0 = ! horiz0; if (torus0->adjacentBackwards(0)) horiz0 = ! horiz0; if (torus1->adjacentReflected(1)) horiz1 = ! horiz1; if (torus1->adjacentBackwards(1)) horiz1 = ! horiz1; const NSatLST* lst; const NSatMobius* mobius; NPerm4 roles; if ((mobius = dynamic_cast(torus0))) { if (mobius->position() == 2) { p0 = 2; q0 = -1; } else if (mobius->position() == 1) { p0 = 1; q0 = (horiz0 ? -2 : 1); } else { p0 = 1; q0 = (horiz0 ? 1 : -2); } } else if ((lst = dynamic_cast(torus0))) { roles = lst->roles(); p0 = lst->lst()->getMeridinalCuts(roles[0]); q0 = lst->lst()->getMeridinalCuts(roles[horiz0 ? 1 : 2]); if (! ((roles[2] == 2 && horiz0) || (roles[1] == 2 && ! horiz0))) q0 = -q0; } else return false; if ((mobius = dynamic_cast(torus1))) { if (mobius->position() == 2) { p1 = 2; q1 = -1; } else if (mobius->position() == 1) { p1 = 1; q1 = (horiz1 ? -2 : 1); } else { p1 = 1; q1 = (horiz1 ? 1 : -2); } } else if ((lst = dynamic_cast(torus1))) { roles = lst->roles(); p1 = lst->lst()->getMeridinalCuts(roles[0]); q1 = lst->lst()->getMeridinalCuts(roles[horiz1 ? 1 : 2]); if (! ((roles[2] == 2 && horiz1) || (roles[1] == 2 && ! horiz1))) q1 = -q1; } else return false; // Do a little normalisation. if ((thin && (id == 3 || id == 4)) || ((! thin) && id == 1)) { // Complementing does nothing. if (p0 > 0 && p1 > 0 && q0 < 0 && q1 < 0 && q0 > -p0 && q1 > -p1 && 2 * q0 <= -p0 && 2 * q1 <= -p1) { q0 = -p0 - q0; q1 = -p1 - q1; } } if (labs(p1) > labs(p0) || (labs(p1) == labs(p0) && labs(q1) < labs(q0))) { long tmp; if (thin || ((! thin) && (id == 1 || id ==3))) { // Swapping does nothing. tmp = p0; p0 = p1; p1 = tmp; tmp = q0; q0 = q1; q1 = tmp; } else if (id == 2 || id == 4) { // If we swap then we also complement. tmp = p0; p0 = p1; p1 = tmp; tmp = q0; q0 = q1; q1 = tmp; q0 = -p0 - q0; q1 = -p1 - q1; } } // All good. Build the full name and quit. std::ostringstream ans; ans << (thin ? 'H' : 'K') << "(T~" << (thin ? 6 : 5) << '^' << id; if (p0 != 2 || q0 != -1 || p1 != 2 || q1 != -1) ans << " | " << p0 << ',' << q0; if (p1 != 2 || q1 != -1) ans << " | " << p1 << ',' << q1; ans << ')'; name = ans.str(); return true; } } // namespace regina regina-4.96/engine/subcomplex/nblockedsfs.h000644 000765 000024 00000022712 12377775435 020734 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/nblockedsfs.h * \brief Supports Seifert fibred spaces that are triangulated using * saturated blocks. */ #ifndef __NBLOCKEDSFS_H #ifndef __DOXYGEN #define __NBLOCKEDSFS_H #endif #include "regina-core.h" #include "subcomplex/nstandardtri.h" namespace regina { class NSatBlock; class NSatRegion; /** * \weakgroup subcomplex * @{ */ /** * Represents a blocked Seifert fibred space (possibly with boundary). * This is a particular type of triangulation of a Seifert fibred space, * where this triangulation is formed from a single saturated region. * A saturated region is in turn formed from saturated blocks by identifying * their boundary annuli in pairs; see the NSatRegion class for details. * * Note that the routines writeName() and writeTeXName() do \e not * offer enough information to uniquely identify the triangulation, * since this essentially requires a 2-dimensional assembling of * saturated blocks. For full detail, writeTextLong() may be used instead. * * The optional NStandardTriangulation routine getManifold() is * implemented for this class, but getHomologyH1() is not. */ class REGINA_API NBlockedSFS : public NStandardTriangulation { private: NSatRegion* region_; /**< The single saturated region that describes this entire triangulation. */ public: /** * Destroys this structure and its constituent components. */ ~NBlockedSFS(); /** * Returns details of the single saturated region that * fills this triangulation. * * @return the single saturated region. */ const NSatRegion& region() const; /** * Determines whether this triangulation is a plugged thin * I-bundle or a plugged thick I-bundle. These structures are * described in "Structures of small closed non-orientable * 3-manifold triangulations", Benjamin A. Burton, * J. Knot Theory Ramifications 16 (2007), 545--574. * * \ifacespython The argument \a name is not present. Instead, * this routine returns a tuple of size two: the boolean usually * returned from this function, and the string usually returned in * the argument \a name. * * @param name used to return the name of the plugged thin/thick * I-bundle, if the triangulation is of this form. If the * triangulation is not of this form, this string is not touched. * @return \c true if this triangulation is indeed a plugged thin * I-bundle or a plugged thick I-bundle. */ bool isPluggedIBundle(std::string& name) const; NManifold* getManifold() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; void writeTextLong(std::ostream& out) const; /** * Determines if the given triangulation is a blocked Seifert * fibred space. * * @param tri the triangulation to examine. * @return a newly created structure containing details of the * blocked Seifert fibred space, or \c null if the given * triangulation is not a blocked Seifert fibred space. */ static NBlockedSFS* isBlockedSFS(NTriangulation* tri); private: /** * Constructs a new blocked Seifert fibred space, as described by * the given saturated region. The new object will take ownership * of the given region. * * Note that the new object must describe an existing triangulation. * * @param region the region describing this entire triangulation. */ NBlockedSFS(NSatRegion* region); /** * Attempts to identify the solid torus plugs in a plugged thin * I-bundle or a plugged thick I-bundle. This routine is * internal to isPluggedIBundle(). * * It is assumed that the plugged thin/thick I-bundle has been * completely identified, with the exception of the two solid * torus plugs. Corresponding parameters describing the * core I-bundle must be passed, along with two blocks that * should correspond to the two plugs. * * If the two blocks are indeed solid torus plugs (either layered * solid tori or Mobius bands), the full name of the plugged * thin/thick I-bundle will be filled in and \c true will be * returned. Note that this name may be normalised or otherwise * modified to return a simpler set of parameters for the same * triangulation. If either block is not a solid torus plug then * \c false will be returned. * * @param thin \c true if the overall structure being identified * is a plugged thin I-bundle, or \c false if it is a plugged * thick I-bundle. * @param id identifies the particular thin/thick twisted * I-bundle into which the solid tori are plugged. This must be * 1, 2, 3 or 4, to distinguish between the four thin twisted * I-bundles or the four thick twisted I-bundles described in * the paper "Structures of small closed non-orientable * 3-manifold triangulations" (see isPluggedIBundle for details). * @param name used to return the full parameterised name of this * triangulation. If the two given blocks are not solid torus * plugs, this string is not touched. * @param torus0 the block that should provide the solid torus plug * corresponding to the first pair of integers in the plugged * thin/thick I-bundle parameters. * @param horiz0 \c true if the first pair of integers in the * plugged thin/thick I-bundle parameters should measure the * number of times the meridinal curve cuts the vertical and * horizontal edges of the adjacent block (not the block * \a torus0, but its neighbour), or \c false if the vertical * and diagonal edges should be used instead. * @param torus1 the block that should provide the solid torus plug * corresponding to the second pair of integers in the plugged * thin/thick I-bundle parameters. * @param horiz1 \c true if the second pair of integers in the * plugged thin/thick I-bundle parameters should measure the * number of times the meridinal curve cuts the vertical and * horizontal edges of the adjacent block (not the block * \a torus1, but its neighbour), or \c false if the vertical * and diagonal edges should be used instead. * @return \c true if the two given blocks are both solid torus * plugs (either layered solid tori or Mobius bands), or \c false * otherwise. */ static bool findPluggedTori(bool thin, int id, std::string& name, const NSatBlock* torus0, bool horiz0, const NSatBlock* torus1, bool horiz1); }; /*@}*/ // Inline functions for NBlockedSFS inline NBlockedSFS::NBlockedSFS(NSatRegion* region) : region_(region) { } inline const NSatRegion& NBlockedSFS::region() const { return *region_; } } // namespace regina #endif regina-4.96/engine/subcomplex/nblockedsfsloop.cpp000644 000765 000024 00000022020 12377776663 022155 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "manifold/ngraphloop.h" #include "manifold/nsfs.h" #include "subcomplex/nblockedsfsloop.h" #include "subcomplex/nlayering.h" #include "subcomplex/nsatblockstarter.h" #include "subcomplex/nsatregion.h" namespace regina { /** * A subclass of NSatBlockStarterSearcher that, upon finding a starter * block, attempts to flesh this out to an entire saturated region with * two identified torus boundaries, as described by the NBlockedSFSLoop * class. */ struct NBlockedSFSLoopSearcher : public NSatBlockStarterSearcher { NSatRegion* region; /**< The bounded saturated region, if the entire NBlockedSFSLoop structure has been successfully found; otherwise, 0 if we are still searching. */ NMatrix2 matchingReln; /**< The matrix describing how the two boundary annuli of the saturated region are joined together. This matrix expresses the fibre/base curves on one boundary annulus in terms of the fibre/base curves on the other, as described by NGraphLoop::matchingReln(). */ /** * Creates a new searcher whose \a region pointer is null. */ NBlockedSFSLoopSearcher() : region(0) { } protected: bool useStarterBlock(NSatBlock* starter); }; NBlockedSFSLoop::~NBlockedSFSLoop() { if (region_) delete region_; } NManifold* NBlockedSFSLoop::getManifold() const { NSFSpace* sfs = region_->createSFS(false); if (! sfs) return 0; if (sfs->punctures() == 1) { // The region has one larger boundary, but we pinch it to create // two smaller boundaries. sfs->addPuncture(); } sfs->reduce(false); return new NGraphLoop(sfs, matchingReln_); } std::ostream& NBlockedSFSLoop::writeName(std::ostream& out) const { out << "Blocked SFS Loop ["; region_->writeBlockAbbrs(out, false); return out << ']'; } std::ostream& NBlockedSFSLoop::writeTeXName(std::ostream& out) const { out << "\\mathrm{BSFS\\_Loop}\\left["; region_->writeBlockAbbrs(out, true); return out << "\\right]"; } void NBlockedSFSLoop::writeTextLong(std::ostream& out) const { out << "Blocked SFS Loop, matching relation " << matchingReln_ << '\n'; region_->writeDetail(out, "Internal region"); } NBlockedSFSLoop* NBlockedSFSLoop::isBlockedSFSLoop(NTriangulation* tri) { // Basic property checks. if (! tri->isClosed()) return 0; if (tri->getNumberOfComponents() > 1) return 0; // Watch out for twisted block boundaries that are incompatible with // neighbouring blocks! Also watch for saturated tori being joined // to saturated Klein bottles. Any of these issues will result in // edges joined to themselves in reverse. if (! tri->isValid()) return 0; // Hunt for a starting block. NBlockedSFSLoopSearcher searcher; searcher.findStarterBlocks(tri); // Any luck? if (searcher.region) { // The expansion and self-adjacency worked, and the triangulation // is known to be closed and connected. // This means we've got one! return new NBlockedSFSLoop(searcher.region, searcher.matchingReln); } // Nope. return 0; } bool NBlockedSFSLoopSearcher::useStarterBlock(NSatBlock* starter) { // The region pointer should be null, but just in case... if (region) { delete starter; return false; } // Flesh out the triangulation as far as we can. We're aiming for // precisely two boundary annuli remaining. // Note that the starter block will now be owned by region. region = new NSatRegion(starter); region->expand(usedTets); if (region->numberOfBoundaryAnnuli() != 2) { delete region; region = 0; return true; } NSatBlock* bdryBlock[2]; unsigned bdryAnnulus[2]; bool bdryRefVert[2], bdryRefHoriz[2]; region->boundaryAnnulus(0, bdryBlock[0], bdryAnnulus[0], bdryRefVert[0], bdryRefHoriz[0]); region->boundaryAnnulus(1, bdryBlock[1], bdryAnnulus[1], bdryRefVert[1], bdryRefHoriz[1]); // We either want two disjoint one-annulus torus boundaries, or else a // single two-annulus boundary that is pinched to turn each annulus into // a two-sided torus. The following test will handle all cases. We // don't worry about the degenerate case of fibres mapping to fibres // through the layering in the pinched case, since this will fail // our test anyway (either boundaries do not form tori, or they are // not two-sided). NSatAnnulus bdry0 = bdryBlock[0]->annulus(bdryAnnulus[0]); NSatAnnulus bdry1 = bdryBlock[1]->annulus(bdryAnnulus[1]); if (! (bdry0.isTwoSidedTorus() && bdry1.isTwoSidedTorus())) { delete region; region = 0; return true; } // Look for a layering on the first boundary annulus. // Extend the layering one tetrahedron at a time, to make sure we // don't loop back onto ourselves. NLayering layering(bdry0.tet[0], bdry0.roles[0], bdry0.tet[1], bdry0.roles[1]); NSatAnnulus layerTop; NMatrix2 layerToBdry1; while (true) { layerTop.tet[0] = layering.getNewBoundaryTet(0); layerTop.tet[1] = layering.getNewBoundaryTet(1); layerTop.roles[0] = layering.getNewBoundaryRoles(0); layerTop.roles[1] = layering.getNewBoundaryRoles(1); // Have we reached the second boundary? if (bdry1.isJoined(layerTop, layerToBdry1)) break; // We haven't joined up yet. Either extend or die. if (! layering.extendOne()) { // The layering dried up and we didn't make it. delete region; region = 0; return true; } if (usedTets.find(layering.getNewBoundaryTet(0)) != usedTets.end() || usedTets.find(layering.getNewBoundaryTet(1)) != usedTets.end()) { // Gone too far -- we've looped back upon ourselves. delete region; region = 0; return true; } usedTets.insert(layering.getNewBoundaryTet(0)); usedTets.insert(layering.getNewBoundaryTet(1)); } // This is it! Build the matching matrix and stop searching. // First find mappings from the fibre/base curves (fi, oi) to // annulus #i edges (first triangle: 01, first triangle: 02). // Note that each of these matrices is self-inverse. NMatrix2 curves0ToAnnulus0(bdryRefVert[0] ? 1 : -1, 0, 0, bdryRefHoriz[0] ? -1 : 1); NMatrix2 curves1ToAnnulus1(bdryRefVert[1] ? 1 : -1, 0, 0, bdryRefHoriz[1] ? -1 : 1); // Put it all together. // Remember that curves1ToAnnulus1 is self-inverse. matchingReln = curves1ToAnnulus1 * layerToBdry1 * layering.boundaryReln() * curves0ToAnnulus0; return false; } } // namespace regina regina-4.96/engine/subcomplex/nblockedsfsloop.h000644 000765 000024 00000020211 12377775436 021617 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/nblockedsfsloop.h * \brief Supports self-identified Seifert fibred spaces that are * triangulated using saturated blocks. */ #ifndef __NBLOCKEDSFSLOOP_H #ifndef __DOXYGEN #define __NBLOCKEDSFSLOOP_H #endif #include "regina-core.h" #include "maths/nmatrix2.h" #include "subcomplex/nstandardtri.h" namespace regina { class NSatRegion; /** * \weakgroup subcomplex * @{ */ /** * Represents a blocked Seifert fibred space with two boundary tori that * are joined together. This is a particular type of triangulation of a * graph manifold, formed from a single saturated region whose two torus * boundaries are identified. An optional layering may be placed * between the two torus boundaries to allow for a more interesting * relationship between the two sets of boundary curves. For more * detail on saturated regions and their constituent saturated blocks, * see the NSatRegion class; for more detail on layerings, see the * NLayering class. * * The saturated region may have two boundary components formed from one * saturated annulus each. Alternatively, it may have one boundary * formed from two saturated annuli, where this boundary is pinched * together so that each annulus becomes a two-sided torus (both of which * are later joined together). None of the boundary components (or the * two-sided tori discussed above) may be twisted (i.e., they must be * tori, not Klein bottles). * * The way in which the two torus boundaries are identified is specified * by a 2-by-2 matrix, which expresses curves representing the fibres * and base orbifold on the second boundary in terms of such curves on * the first boundary (see the page on \ref sfsnotation for terminology). * * More specifically, suppose that \a f0 and \a o0 are directed curves * on the first boundary torus and \a f1 and \a o1 are directed curves * on the second boundary torus, where \a f0 and \a f1 represent the * fibres of the region and \a o0 and \a o1 represent the base orbifold. * Then the boundaries are joined according to the following relation: * *
 *     [f1]       [f0]
 *     [  ] = M * [  ]
 *     [o1]       [o0]
 * 
* * If a layering is present between the two torus boundaries, then the * corresponding boundary curves are not identified directly. In this * case, the matrix \a M shows how the layering relates the curves on * each boundary. * * Note that the routines writeName() and writeTeXName() do \e not * offer enough information to uniquely identify the triangulation, * since this essentially requires 2-dimensional assemblings of * saturated blocks. For full details, writeTextLong() may be used instead. * * The optional NStandardTriangulation routine getManifold() is * implemented for this class, but getHomologyH1() is not. */ class REGINA_API NBlockedSFSLoop : public NStandardTriangulation { private: NSatRegion* region_; /**< The saturated region whose two torus boundaries are joined. */ NMatrix2 matchingReln_; /**< Specifies how the two boundary tori are joined, as described in the class notes above. */ public: /** * Destroys this structure and its constituent components. */ ~NBlockedSFSLoop(); /** * Returns details of the saturated region from which this * triangulation is formed. See the class notes above for * further information. * * @return details of the saturated region. */ const NSatRegion& region() const; /** * Returns the matrix describing how the two torus boundaries of * the saturated region are joined. Note that if a layering is * placed between the two boundary tori, then any changes to the * boundary relationships caused by the layering are included in * this matrix. * * See the class notes above for precise information on how this * matrix is presented. * * @return the matrix describing how the boundaries of the * region are joined. */ const NMatrix2& matchingReln() const; NManifold* getManifold() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; void writeTextLong(std::ostream& out) const; /** * Determines if the given triangulation is a blocked Seifert * fibred space with identified boundaries, as described by this * class. * * @param tri the triangulation to examine. * @return a newly created structure containing details of the * blocked self-identified Seifert fibred space, or \c null if * the given triangulation is not of this form. */ static NBlockedSFSLoop* isBlockedSFSLoop(NTriangulation* tri); private: /** * Constructs a new blocked self-identified Seifert fibred * space, as described by the given saturated region and * matching relation. The new object will take ownership of the * given region. * * Note that the new object must describe an existing triangulation. * * @param region the saturated region from which the structure * is formed. * @param matchingReln describes how the two boundaries of the * region are joined, as described in the class notes above. */ NBlockedSFSLoop(NSatRegion* region, const NMatrix2& matchingReln); }; /*@}*/ // Inline functions for NBlockedSFSLoop inline NBlockedSFSLoop::NBlockedSFSLoop(NSatRegion* region, const NMatrix2& matchingReln) : region_(region), matchingReln_(matchingReln) { } inline const NSatRegion& NBlockedSFSLoop::region() const { return *region_; } inline const NMatrix2& NBlockedSFSLoop::matchingReln() const { return matchingReln_; } } // namespace regina #endif regina-4.96/engine/subcomplex/nblockedsfspair.cpp000644 000765 000024 00000025215 12377776663 022150 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "manifold/ngraphpair.h" #include "manifold/nsfs.h" #include "subcomplex/nblockedsfspair.h" #include "subcomplex/nlayering.h" #include "subcomplex/nsatblockstarter.h" #include "subcomplex/nsatregion.h" namespace regina { /** * A subclass of NSatBlockStarterSearcher that, upon finding a starter * block, attempts to flesh this out to a pair of saturated regions * joined along their single torus boundaries, as desribed by the * NBlockedSFSPair class. */ struct NBlockedSFSPairSearcher : public NSatBlockStarterSearcher { NSatRegion* region[2]; /**< The two bounded saturated regions that are joined together, if the entire NBlockedSFSPair structure has been successfully found; otherwise, two null pointers if we are still searching. */ NMatrix2 matchingReln; /**< The matrix describing how the region boundaries are joined together. This matrix expresses the fibre/base curves on the second region boundary in terms of the fibre/base curves on the first, as described by NGraphPair::matchingReln(). */ /** * Creates a new searcher whose \a region pointers are both null. */ NBlockedSFSPairSearcher() { region[0] = region[1] = 0; } protected: bool useStarterBlock(NSatBlock* starter); }; NBlockedSFSPair::~NBlockedSFSPair() { if (region_[0]) delete region_[0]; if (region_[1]) delete region_[1]; } NManifold* NBlockedSFSPair::getManifold() const { NSFSpace* sfs0 = region_[0]->createSFS(false); if (! sfs0) return 0; NSFSpace* sfs1 = region_[1]->createSFS(false); if (! sfs1) { delete sfs0; return 0; } // Reduce the Seifert fibred space representations and finish up. sfs0->reduce(false); sfs1->reduce(false); if (*sfs1 < *sfs0) return new NGraphPair(sfs1, sfs0, matchingReln_.inverse()); else return new NGraphPair(sfs0, sfs1, matchingReln_); } std::ostream& NBlockedSFSPair::writeName(std::ostream& out) const { out << "Blocked SFS Pair ["; region_[0]->writeBlockAbbrs(out, false); out << " | "; region_[1]->writeBlockAbbrs(out, false); return out << ']'; } std::ostream& NBlockedSFSPair::writeTeXName(std::ostream& out) const { out << "\\mathrm{BSFS\\_Pair}\\left["; region_[0]->writeBlockAbbrs(out, true); out << "\\,|\\,"; region_[1]->writeBlockAbbrs(out, true); return out << "\\right]"; } void NBlockedSFSPair::writeTextLong(std::ostream& out) const { out << "Blocked SFS pair, matching relation " << matchingReln_ << "\n"; region_[0]->writeDetail(out, "First region"); region_[1]->writeDetail(out, "Second region"); } NBlockedSFSPair* NBlockedSFSPair::isBlockedSFSPair(NTriangulation* tri) { // Basic property checks. if (! tri->isClosed()) return 0; if (tri->getNumberOfComponents() > 1) return 0; // Watch out for twisted block boundaries that are incompatible with // neighbouring blocks! Also watch for the boundary between blocks // being an annulus on one side and a Klein bottle on the other (or // two incompatible Klein bottles for that matter). // // These will result in edges joined to themselves in reverse. if (! tri->isValid()) return 0; // Hunt for a starting block. NBlockedSFSPairSearcher searcher; searcher.findStarterBlocks(tri); // Any luck? if (searcher.region[0]) { // The full expansion worked, and the triangulation is known // to be closed and connected. // This means we've got one! return new NBlockedSFSPair(searcher.region[0], searcher.region[1], searcher.matchingReln); } // Nope. return 0; } bool NBlockedSFSPairSearcher::useStarterBlock(NSatBlock* starter) { // The region pointers should be null, but just in case... if (region[0] || region[1]) { delete starter; return false; } // Flesh out the triangulation as far as we can. We're aiming for // just one boundary annulus remaining. // Note that the starter block will now be owned by region[0]. region[0] = new NSatRegion(starter); region[0]->expand(usedTets); if (region[0]->numberOfBoundaryAnnuli() != 1) { delete region[0]; region[0] = 0; return true; } // Insist on this boundary being untwisted. NSatBlock* bdryBlock; unsigned bdryAnnulus; bool bdryVert, bdryHoriz; region[0]->boundaryAnnulus(0, bdryBlock, bdryAnnulus, bdryVert, bdryHoriz); bool firstRegionReflected = ((bdryVert && ! bdryHoriz) || (bdryHoriz && ! bdryVert)); NSatBlock* tmpBlock; unsigned tmpAnnulus; bool tmpVert, tmpHoriz; bdryBlock->nextBoundaryAnnulus(bdryAnnulus, tmpBlock, tmpAnnulus, tmpVert, tmpHoriz, false); if (tmpVert) { delete region[0]; region[0] = 0; return true; } NSatAnnulus bdry = bdryBlock->annulus(bdryAnnulus); // We have a boundary annulus for the first region. // Hunt for a layering. NLayering layering(bdry.tet[0], bdry.roles[0], bdry.tet[1], bdry.roles[1]); layering.extend(); // Relation from fibre/orbifold to layering first triangle markings 01/02: NMatrix2 curves0ToLayering = layering.boundaryReln() * NMatrix2(-1, 0, 0, firstRegionReflected ? -1 : 1); // We make the shell of an other-side boundary annulus; we will fill // in the precise vertex role permutations later on. NSatAnnulus otherSide(layering.getNewBoundaryTet(0), NPerm4(), layering.getNewBoundaryTet(1), NPerm4()); if (otherSide.meetsBoundary()) { delete region[0]; region[0] = 0; return true; } // Mapping from (layering first triangle markings 01/02) to // (other side annulus first triangle markings 01/02). Like the other // side vertex roles, this mapping will be filled in later. NMatrix2 layeringToAnnulus1; // Try the three possible orientations for fibres on the other side. NSatBlock* otherStarter; for (int plugPos = 0; plugPos < 3; plugPos++) { // Construct the boundary annulus for the second region. // Refresh the tetrahedra as well as the vertex roles, since // it may have switched sides since our last run through the loop. otherSide.tet[0] = layering.getNewBoundaryTet(0); otherSide.tet[1] = layering.getNewBoundaryTet(1); if (plugPos == 0) { otherSide.roles[0] = layering.getNewBoundaryRoles(0); otherSide.roles[1] = layering.getNewBoundaryRoles(1); layeringToAnnulus1 = NMatrix2(1, 0, 0, 1); } else if (plugPos == 1) { otherSide.roles[0] = layering.getNewBoundaryRoles(0) * NPerm4(1, 2, 0, 3); otherSide.roles[1] = layering.getNewBoundaryRoles(1) * NPerm4(1, 2, 0, 3); layeringToAnnulus1 = NMatrix2(-1, 1, -1, 0); } else { otherSide.roles[0] = layering.getNewBoundaryRoles(0) * NPerm4(2, 0, 1, 3); otherSide.roles[1] = layering.getNewBoundaryRoles(1) * NPerm4(2, 0, 1, 3); layeringToAnnulus1 = NMatrix2(0, -1, 1, -1); } // Clear out the used tetrahedron list. Everything before the new // layering boundary is self-contained, so we won't run into it // again on the other side. We'll just re-insert the layering // boundary tetrahedra. usedTets.clear(); usedTets.insert(layering.getNewBoundaryTet(0)); usedTets.insert(layering.getNewBoundaryTet(1)); // See if we can flesh the other side out to an entire region. otherSide.switchSides(); if ((otherStarter = NSatBlock::isBlock(otherSide, usedTets))) { region[1] = new NSatRegion(otherStarter); region[1]->expand(usedTets); if (region[1]->numberOfBoundaryAnnuli() == 1) { // This is it! Stop searching. // Do a final conversion from annulus first triangle markings // 01/02 and exit. matchingReln = NMatrix2(-1, 0, 0, 1) * layeringToAnnulus1 * curves0ToLayering; return false; } // Nup, this one didn't work. delete region[1]; region[1] = 0; } } // Sigh, nothing works. delete region[0]; region[0] = 0; return true; } } // namespace regina regina-4.96/engine/subcomplex/nblockedsfspair.h000644 000765 000024 00000020104 12377775437 021603 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/nblockedsfspair.h * \brief Supports joined pairs of Seifert fibred spaces that are * triangulated using saturated blocks. */ #ifndef __NBLOCKEDSFSPAIR_H #ifndef __DOXYGEN #define __NBLOCKEDSFSPAIR_H #endif #include "regina-core.h" #include "maths/nmatrix2.h" #include "subcomplex/nstandardtri.h" namespace regina { class NSatRegion; /** * \weakgroup subcomplex * @{ */ /** * Represents a blocked pair of Seifert fibred spaces joined along a single * connecting torus. This is a particular type of triangulation of a graph * manifold, formed from two saturated regions whose torus boundaries are * identified. An optional layering may be placed between the two torus * boundaries to allow for a more interesting relationship between the boundary * curves of each region. For more detail on saturated regions and their * constituent saturated blocks, see the NSatRegion class; for more detail * on layerings, see the NLayering class. * * Each of the two saturated regions must have precisely one boundary * component formed from just one saturated annulus, and this boundary may * not be twisted (i.e., it must be a torus, not a Klein bottle). The * way in which the boundaries from each region are identified is * specified by a 2-by-2 matrix \a M, which expresses curves * representing the fibres and base orbifold of the second region in * terms of the first (see the page on \ref sfsnotation for terminology). * * More specifically, suppose that \a f0 and \a o0 are directed curves on * the first region boundary and \a f1 and \a o1 are directed curves on the * second region boundary, where \a f0 and \a f1 represent the fibres of * each region and \a o0 and \a o1 represent the base orbifolds. Then * the boundaries are joined according to the following relation: * *
 *     [f1]       [f0]
 *     [  ] = M * [  ]
 *     [o1]       [o0]
 * 
* * If a layering is present between the two boundaries, then the * boundary curves are not identified directly. In this case, the matrix * \a M shows how the layering relates the curves on each region boundary. * * Note that the routines writeName() and writeTeXName() do \e not * offer enough information to uniquely identify the triangulation, * since this essentially requires 2-dimensional assemblings of * saturated blocks. For full details, writeTextLong() may be used instead. * * The optional NStandardTriangulation routine getManifold() is * implemented for this class, but getHomologyH1() is not. */ class REGINA_API NBlockedSFSPair : public NStandardTriangulation { private: NSatRegion* region_[2]; /**< The two saturated regions whose boundaries are joined. */ NMatrix2 matchingReln_; /**< Specifies how the two region boundaries are joined, as described in the class notes above. */ public: /** * Destroys this structure and its constituent components. */ ~NBlockedSFSPair(); /** * Returns details of one of the two bounded saturated regions that * form this triangulation. See the class notes above for further * information. * * @param which 0 if the first region should be returned, or * 1 if the second region should be returned. * @return details of the requested saturated region. */ const NSatRegion& region(int which) const; /** * Returns the matrix describing how the two saturated region * boundaries are joined. Note that if a layering is placed * between the two region boundaries, then any changes to the * boundary relationships caused by the layering are included * in this matrix. * * See the class notes above for precise information on how this * matrix is presented. * * @return the matrix describing how the region boundaries are * joined. */ const NMatrix2& matchingReln() const; NManifold* getManifold() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; void writeTextLong(std::ostream& out) const; /** * Determines if the given triangulation is a blocked pair of * Seifert fibred spaces, as described by this class. * * @param tri the triangulation to examine. * @return a newly created structure containing details of the * blocked pair, or \c null if the given triangulation is not of * this form. */ static NBlockedSFSPair* isBlockedSFSPair(NTriangulation* tri); private: /** * Constructs a new blocked pair of Seifert fibred spaces, as * described by the given saturated regions and matching * relation. The new object will take ownership of each of the * regions passed. * * Note that the new object must describe an existing triangulation. * * @param region0 the first saturated region. * @param region1 the second saturated region. * @param matchingReln describes how the first and second region * boundaries are joined, as detailed in the class notes above. */ NBlockedSFSPair(NSatRegion* region0, NSatRegion* region1, const NMatrix2& matchingReln); }; /*@}*/ // Inline functions for NBlockedSFSPair inline NBlockedSFSPair::NBlockedSFSPair(NSatRegion* region0, NSatRegion* region1, const NMatrix2& matchingReln) : matchingReln_(matchingReln) { region_[0] = region0; region_[1] = region1; } inline const NSatRegion& NBlockedSFSPair::region(int which) const { return *region_[which]; } inline const NMatrix2& NBlockedSFSPair::matchingReln() const { return matchingReln_; } } // namespace regina #endif regina-4.96/engine/subcomplex/nblockedsfstriple.cpp000644 000765 000024 00000033437 12377776664 022522 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "manifold/ngraphtriple.h" #include "manifold/nsfs.h" #include "subcomplex/nblockedsfstriple.h" #include "subcomplex/nlayering.h" #include "subcomplex/nsatblockstarter.h" #include "subcomplex/nsatregion.h" #include namespace regina { /** * A subclass of NSatBlockStarterSearcher that, upon finding a starter * block, attempts to flesh this out to a group of three saturated regions * joined along their torus boundaries, as desribed by the * NBlockedSFSTriple class. * * The starter block will be assumed to belong to the central region (not * one of the end regions). */ struct NBlockedSFSTripleSearcher : public NSatBlockStarterSearcher { NSatRegion* end[2]; /**< The two end regions of the NBlockedSFSTriple structure, if such a structure has been successfully found; otherwise, two null pointers if we are still searching. */ NSatRegion* centre; /**< The central region of the NBlockedSFSTriple structure, if such a structure has been successfully found; otherwise, a null pointer if we are still searching. */ NMatrix2 matchingReln[2]; /**< The matrices describing how the various region boundaries are joined together. Here matrix \a matchingReln[i] expresses the fibre/base curves on region \a end[i] in terms of the fibre/base curves on the corresponding central region boundary. See NBlockedSFSTriple::matchingReln() for further details. */ /** * Creates a new searcher whose \a end and \a centre region pointers * are all null. */ NBlockedSFSTripleSearcher() { end[0] = end[1] = centre = 0; } protected: bool useStarterBlock(NSatBlock* starter); }; NBlockedSFSTriple::~NBlockedSFSTriple() { if (end_[0]) delete end_[0]; if (end_[1]) delete end_[1]; if (centre_) delete centre_; } NManifold* NBlockedSFSTriple::getManifold() const { // Go ahead and create the Seifert fibred spaces. NSFSpace* end0 = end_[0]->createSFS(false); if (! end0) return 0; NSFSpace* end1 = end_[1]->createSFS(false); if (! end1) { delete end0; return 0; } NSFSpace* hub = centre_->createSFS(false); if (! hub) { delete end0; delete end1; return 0; } if (hub->punctures() == 1) { // The region has one larger boundary, but we pinch it to create // two smaller boundaries. hub->addPuncture(); } // Reduce the Seifert fibred space representations and finish up. end0->reduce(false); end1->reduce(false); hub->reduce(false); return new NGraphTriple(end0, hub, end1, matchingReln_[0], matchingReln_[1]); } std::ostream& NBlockedSFSTriple::writeName(std::ostream& out) const { out << "Blocked SFS Triple ["; end_[0]->writeBlockAbbrs(out, false); out << " | "; centre_->writeBlockAbbrs(out, false); out << " | "; end_[1]->writeBlockAbbrs(out, false); return out << ']'; } std::ostream& NBlockedSFSTriple::writeTeXName(std::ostream& out) const { out << "\\mathrm{BSFS\\_Triple}\\left["; end_[0]->writeBlockAbbrs(out, true); out << "\\,|\\,"; centre_->writeBlockAbbrs(out, true); out << "\\,|\\,"; end_[1]->writeBlockAbbrs(out, true); return out << "\\right]"; } void NBlockedSFSTriple::writeTextLong(std::ostream& out) const { out << "Blocked SFS triple\n"; out << "Matching relation (centre -> end #1): " << matchingReln_[0] << '\n'; out << "Matching relation (centre -> end #2): " << matchingReln_[1] << '\n'; centre_->writeDetail(out, "Central region"); end_[0]->writeDetail(out, "First end region"); end_[1]->writeDetail(out, "Second end region"); } NBlockedSFSTriple* NBlockedSFSTriple::isBlockedSFSTriple( NTriangulation* tri) { // Basic property checks. if (! tri->isClosed()) return 0; if (tri->getNumberOfComponents() > 1) return 0; // Watch out for twisted block boundaries that are incompatible with // neighbouring blocks! Also watch for the boundary between blocks // being an annulus on one side and a Klein bottle on the other (or // two incompatible Klein bottles for that matter). // // These will result in edges joined to themselves in reverse. if (! tri->isValid()) return 0; // Hunt for a starting block. NBlockedSFSTripleSearcher searcher; searcher.findStarterBlocks(tri); // Any luck? if (searcher.centre) { // The full expansion worked, and the triangulation is known // to be closed and connected. // This means we've got one! return new NBlockedSFSTriple(searcher.end[0], searcher.centre, searcher.end[1], searcher.matchingReln[0], searcher.matchingReln[1]); } // Nope. return 0; } bool NBlockedSFSTripleSearcher::useStarterBlock(NSatBlock* starter) { // The region pointers should be null, but just in case... if (end[0] || end[1] || centre) { delete starter; return false; } // Flesh out the triangulation as far as we can. We're aiming for // precisely two disjoint boundary annuli remaining. // Note that the starter block will now be owned by centre. centre = new NSatRegion(starter); centre->expand(usedTets); if (centre->numberOfBoundaryAnnuli() != 2) { delete centre; centre = 0; return true; } // Insist on the boundary annuli being disjoint and untwisted. NSatBlock* bdryBlock[2]; unsigned bdryAnnulus[2]; bool bdryVert[2], bdryHoriz[2], bdryRef[2]; centre->boundaryAnnulus(0, bdryBlock[0], bdryAnnulus[0], bdryVert[0], bdryHoriz[0]); centre->boundaryAnnulus(1, bdryBlock[1], bdryAnnulus[1], bdryVert[1], bdryHoriz[1]); bdryRef[0] = ((bdryVert[0] && ! bdryHoriz[0]) || (bdryHoriz[0] && ! bdryVert[0])); bdryRef[1] = ((bdryVert[1] && ! bdryHoriz[1]) || (bdryHoriz[1] && ! bdryVert[1])); // We either want two disjoint one-annulus boundaries, or else a // single two-annulus boundary that is pinched to turn each annulus // into a two-sided torus. The following test handles all cases. NSatAnnulus bdry[2]; bdry[0] = bdryBlock[0]->annulus(bdryAnnulus[0]); bdry[1] = bdryBlock[1]->annulus(bdryAnnulus[1]); if (! (bdry[0].isTwoSidedTorus() && bdry[1].isTwoSidedTorus())) { delete centre; centre = 0; return true; } // Hunt for layerings, but gently gently -- we don't want to loop // from one boundary back onto the other. std::auto_ptr layering[2]; int e; for (e = 0; e < 2; e++) { layering[e].reset(new NLayering(bdry[e].tet[0], bdry[e].roles[0], bdry[e].tet[1], bdry[e].roles[1])); while (layering[e]->extendOne()) { if (usedTets.find(layering[e]->getNewBoundaryTet(0)) != usedTets.end() || usedTets.find(layering[e]->getNewBoundaryTet(1)) != usedTets.end()) { // Oops, we've run back into something we've already seen. delete centre; centre = 0; return true; } usedTets.insert(layering[e]->getNewBoundaryTet(0)); usedTets.insert(layering[e]->getNewBoundaryTet(1)); } } // Start looking for the end regions. int plugPos; NSatBlock* otherStarter; NMatrix2 curvesCentreToLayering, layeringToEndAnnulus; for (e = 0; e < 2; e++) { // Relation from centre fibre/orbifold to layering first triangle // markings 01/02: curvesCentreToLayering = layering[e]->boundaryReln() * NMatrix2(-1, 0, 0, bdryRef[e] ? -1 : 1); // We make the shell of an other-side boundary annulus; we will fill // in the precise vertex role permutations later on. NSatAnnulus otherSide(layering[e]->getNewBoundaryTet(0), NPerm4(), layering[e]->getNewBoundaryTet(1), NPerm4()); if (otherSide.meetsBoundary()) { delete centre; centre = 0; if (e == 1) { delete end[0]; end[0] = 0; } return true; } // Try the three possible orientations for fibres on the other side. for (plugPos = 0; plugPos < 3; plugPos++) { // Construct the boundary annulus for the end region. // Refresh the tetrahedra as well as the vertex roles, since // it may have switched sides since our last run through the loop. otherSide.tet[0] = layering[e]->getNewBoundaryTet(0); otherSide.tet[1] = layering[e]->getNewBoundaryTet(1); // In each case, also fill in the mapping from (layering first // triangle markings 01/02) to (other side annulus first triangle // markings 01/02). This is stored in layeringToEndAnnulus. if (plugPos == 0) { otherSide.roles[0] = layering[e]->getNewBoundaryRoles(0); otherSide.roles[1] = layering[e]->getNewBoundaryRoles(1); layeringToEndAnnulus = NMatrix2(1, 0, 0, 1); } else if (plugPos == 1) { otherSide.roles[0] = layering[e]->getNewBoundaryRoles(0) * NPerm4(1, 2, 0, 3); otherSide.roles[1] = layering[e]->getNewBoundaryRoles(1) * NPerm4(1, 2, 0, 3); layeringToEndAnnulus = NMatrix2(-1, 1, -1, 0); } else { otherSide.roles[0] = layering[e]->getNewBoundaryRoles(0) * NPerm4(2, 0, 1, 3); otherSide.roles[1] = layering[e]->getNewBoundaryRoles(1) * NPerm4(2, 0, 1, 3); layeringToEndAnnulus = NMatrix2(0, -1, 1, -1); } // Clear out the used tetrahedron list. Everything between the // two layering boundaries is self-contained, so we won't run // into any of it again on the other side. We'll just re-insert // the layering boundary tetrahedra. usedTets.clear(); usedTets.insert(layering[0]->getNewBoundaryTet(0)); usedTets.insert(layering[0]->getNewBoundaryTet(1)); usedTets.insert(layering[1]->getNewBoundaryTet(0)); usedTets.insert(layering[1]->getNewBoundaryTet(1)); // See if we can flesh the other side out to an entire region. otherSide.switchSides(); if ((otherStarter = NSatBlock::isBlock(otherSide, usedTets))) { end[e] = new NSatRegion(otherStarter); end[e]->expand(usedTets); if (end[e]->numberOfBoundaryAnnuli() == 1) { // Got it! // Do a final conversion from annulus first triangle // markings 01/02 and move onto the next end space. matchingReln[e] = NMatrix2(-1, 0, 0, 1) * layeringToEndAnnulus * curvesCentreToLayering; break; } // Nup, this one didn't work. delete end[e]; end[e] = 0; } } // Did we manage to fill in this end space? if (! end[e]) { // Nope. Keep searching. delete centre; centre = 0; if (e == 1) { delete end[0]; end[0] = 0; } return true; } } // w00t! It all worked out. // Stop searching, we're done. return false; } } // namespace regina regina-4.96/engine/subcomplex/nblockedsfstriple.h000644 000765 000024 00000027232 12377775444 022156 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/nblockedsfstriple.h * \brief Supports joined sequences of three Seifert fibred spaces that * are triangulated using saturated blocks. */ #ifndef __NBLOCKEDSFSTRIPLE_H #ifndef __DOXYGEN #define __NBLOCKEDSFSTRIPLE_H #endif #include "regina-core.h" #include "maths/nmatrix2.h" #include "subcomplex/nstandardtri.h" namespace regina { class NSatRegion; /** * \weakgroup subcomplex * @{ */ /** * Represents a blocked sequence of three Seifert fibred spaces joined * along connecting tori. This is a particular type of triangulation * of a graph manifold, formed from three saturated regions whose * various torus boundaries are identified as described below. * Optional layerings may be placed between torus boundaries to * allow for more interesting relationships between the * respective boundary curves of each region. For more detail on * saturated regions and their constituent saturated blocks, see the * NSatRegion class; for more detail on layerings, see the NLayering class. * * The three saturated regions must be joined together as illustrated * below. Each large box represents a saturated region, and the small * tunnels show where the region boundaries are joined (possibly via * layerings). * *
 *     /----------------\   /------------------\   /----------------\
 *     |                |   |                  |   |                |
 *     |  End region 0   ---   Central region   ---   End region 1  |
 *     |                 ---                    ---                 |
 *     |                |   |                  |   |                |
 *     \----------------/   \------------------/   \----------------/
 * 
* * Each of the end regions must have precisely one boundary component * formed from just one saturated annulus. The central region may have * two boundary components formed from one saturated annulus each. * Alternatively, it may have one boundary formed from two saturated * annuli, where this boundary is pinched together so that each annulus * becomes a two-sided torus joined to one of the end regions. None of * the boundary components (or the two-sided tori discussed above) may * be twisted (i.e., they must be tori, not Klein bottles). * * The ways in which the various region boundaries are identified are * specified by 2-by-2 matrices, which express curves representing the * fibres and base orbifold of each end region in terms of the central * region (see the page on \ref sfsnotation for terminology). * * Specifically, consider the matrix \a M that describes the joining of * the central region and the first end region (marked in the diagram * above as end region 0). Suppose that \a f and \a o are directed * curves on the central region boundary and \a f0 and \a o0 are directed * curves on the first end region boundary, where \a f and \a f0 represent * the fibres of each region and \a o and \a o0 represent the base orbifolds. * Then the boundaries are joined according to the following relation: * *
 *     [f0]       [f ]
 *     [  ] = M * [  ]
 *     [o0]       [o ]
 * 
* * Likewise, let \a M' be the matrix describing how the central region * and the second end region (marked in the diagram as end region 1) are * joined. Let \a f' and \a o' be directed curves on the other central * region boundary and \a f1 and \a o1 be directed curves on the second * end region boundary, where \a f' and \a f1 represent fibres and * \a o and \a o1 represent the base orbifolds. Then the boundaries are * joined according to the relation: * *
 *     [f1]        [f']
 *     [  ] = M' * [  ]
 *     [o1]        [o']
 * 
* * If a layering is present between two regions, then the corresponding * boundary curves are not identified directly. In this case, the relevant * matrix \a M or \a M' shows how the layering relates the curves on each * region boundary. * * Note that the routines writeName() and writeTeXName() do \e not * offer enough information to uniquely identify the triangulation, * since this essentially requires 2-dimensional assemblings of * saturated blocks. For full details, writeTextLong() may be used instead. * * The optional NStandardTriangulation routine getManifold() is * implemented for this class, but getHomologyH1() is not. */ class REGINA_API NBlockedSFSTriple : public NStandardTriangulation { private: NSatRegion* end_[2]; /**< The two end regions, i.e., the saturated regions with just one boundary annulus. */ NSatRegion* centre_; /**< The central region, i.e., the saturated region with two boundary annuli that meets both end regions. */ NMatrix2 matchingReln_[2]; /**< Specifies how the various region boundaries are joined (possibly via layerings), as described in the class notes above. In particular, \a matchingReln_[i] describes how end region \a i is joined to the central region. See the class notes for further details. */ public: /** * Destroys this structure and its constituent components. */ ~NBlockedSFSTriple(); /** * Returns details of the requested end region, as described in * the class notes above. The end regions are the two saturated * regions with one boundary annulus each, which are both joined * to the central region. * * @param which 0 if the first end region should be returned * (marked as end region 0 in the class notes), or 1 if the * second end region should be returned (marked as end region 1 * in the class notes). * @return details of the requested end region. */ const NSatRegion& end(int which) const; /** * Returns details of the central saturated region, as described * in the class notes above. This is the saturated region with * two boundary annuli, each of which is joined to one of the * end regions. * * @return details of the central region. */ const NSatRegion& centre() const; /** * Returns the matrix describing how the given end region is * joined to the central region. Note that if a layering is * placed between the two respective region boundaries, then * any changes to the boundary relationships caused by the * layering are included in this matrix. * * See the class notes above for precise information on how each * matrix is presented. * * @param which 0 if the matrix returned should describe how the * central region is joined to the first end region (marked end * region 0 in the class notes), or 1 if the matrix returned * should describe how the central region is joined to the * second end region (marked end region 1 in the class notes). * @return the matrix describing how the requested region * boundaries are joined. */ const NMatrix2& matchingReln(int which) const; NManifold* getManifold() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; void writeTextLong(std::ostream& out) const; /** * Determines if the given triangulation is a blocked sequence of * three Seifert fibred spaces, as described in the class notes * above. * * @param tri the triangulation to examine. * @return a newly created structure containing details of the * blocked triple, or \c null if the given triangulation is not of * this form. */ static NBlockedSFSTriple* isBlockedSFSTriple(NTriangulation* tri); private: /** * Constructs a new blocked sequence of three Seifert fibred spaces, * as described by the given saturated regions and matching relations. * The new object will take ownership of each of the regions passed. * * See the class notes above for details of terminology used here. * * Note that the new object must describe an existing triangulation. * * @param end0 the first end region. * @param centre the central region. * @param end1 the second end region. * @param matchingReln0 describes how the first end region is * joined to the central region. * @param matchingReln1 describes how the second end region is * joined to the central region. */ NBlockedSFSTriple(NSatRegion* end0, NSatRegion* centre, NSatRegion* end1, const NMatrix2& matchingReln0, const NMatrix2& matchingReln1); }; /*@}*/ // Inline functions for NBlockedSFSTriple inline NBlockedSFSTriple::NBlockedSFSTriple(NSatRegion* end0, NSatRegion* centre, NSatRegion* end1, const NMatrix2& matchingReln0, const NMatrix2& matchingReln1) { end_[0] = end0; centre_ = centre; end_[1] = end1; matchingReln_[0] = matchingReln0; matchingReln_[1] = matchingReln1; } inline const NSatRegion& NBlockedSFSTriple::end(int which) const { return *end_[which]; } inline const NSatRegion& NBlockedSFSTriple::centre() const { return *centre_; } inline const NMatrix2& NBlockedSFSTriple::matchingReln(int which) const { return matchingReln_[which]; } } // namespace regina #endif regina-4.96/engine/subcomplex/nl31pillow.cpp000644 000765 000024 00000010736 12377776665 021007 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "algebra/nabeliangroup.h" #include "manifold/nlensspace.h" #include "triangulation/ncomponent.h" #include "triangulation/ntetrahedron.h" #include "triangulation/nvertex.h" #include "subcomplex/nl31pillow.h" namespace regina { NL31Pillow* NL31Pillow::clone() const { NL31Pillow* ans = new NL31Pillow(); ans->tet[0] = tet[0]; ans->tet[1] = tet[1]; ans->interior[0] = interior[0]; ans->interior[1] = interior[1]; return ans; } NL31Pillow* NL31Pillow::isL31Pillow(const NComponent* comp) { // Basic property check. if (comp->getNumberOfTetrahedra() != 2 || comp->getNumberOfVertices() != 2 || comp->getNumberOfEdges() != 4 || (! comp->isClosed()) || (! comp->isOrientable())) return 0; // Verify that the vertices have degrees 2 and 6. int internalVertex; unsigned long deg0 = comp->getVertex(0)->getNumberOfEmbeddings(); if (deg0 == 2) internalVertex = 0; else if (deg0 == 6) internalVertex = 1; else return 0; // Verify that all four faces of one tetrahedron join to the other. NTetrahedron* tet[2]; tet[0] = comp->getTetrahedron(0); tet[1] = comp->getTetrahedron(1); if (tet[0]->adjacentTetrahedron(0) != tet[1] || tet[0]->adjacentTetrahedron(1) != tet[1] || tet[0]->adjacentTetrahedron(2) != tet[1] || tet[0]->adjacentTetrahedron(3) != tet[1]) return 0; // At this point we can prove through enumeration of all // 2-tetrahedron triangulations that we have our triangular pillow // L(3,1). NL31Pillow* ans = new NL31Pillow(); ans->tet[0] = tet[0]; ans->tet[1] = tet[1]; for (int i = 0; i < 2; i++) { const NVertexEmbedding& emb = comp->getVertex(internalVertex)-> getEmbedding(i); if (emb.getTetrahedron() == tet[0]) ans->interior[0] = emb.getVertex(); else ans->interior[1] = emb.getVertex(); } return ans; } NManifold* NL31Pillow::getManifold() const { return new NLensSpace(3, 1); } NAbelianGroup* NL31Pillow::getHomologyH1() const { NAbelianGroup* ans = new NAbelianGroup(); ans->addTorsionElement(3); return ans; } } // namespace regina regina-4.96/engine/subcomplex/nl31pillow.h000644 000765 000024 00000014333 12377775446 020445 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/nl31pillow.h * \brief Deals with triangular pillow L(3,1) components of a triangulation. */ #ifndef __NL31PILLOW_H #ifndef __DOXYGEN #define __NL31PILLOW_H #endif #include "regina-core.h" #include "subcomplex/nstandardtri.h" namespace regina { class NTetrahedron; /** * \weakgroup subcomplex * @{ */ /** * Represents a triangular pillow L(3,1) component of a triangulation. * * A triangular pillow L(3,1) is a two-tetrahedron two-vertex * triangulation of the lens space L(3,1) formed as follows. * * A triangular pillow is formed from two tetrahedra with a single * degree three vertex in the interior of the pillow. The two boundary * triangles of this pillow are then identified with a one-third twist. * * All optional NStandardTriangulation routines are implemented for this * class. */ class REGINA_API NL31Pillow : public NStandardTriangulation { private: NTetrahedron* tet[2]; /**< The two tetrahedra in the triangular pillow. */ unsigned interior[2]; /**< The vertex of each tetrahedron that corresponds to the interior vertex of the triangular pillow. */ public: /** * Destroys this structure. */ virtual ~NL31Pillow(); /** * Returns a newly created clone of this structure. * * @return a newly created clone. */ NL31Pillow* clone() const; /** * Returns one of the two tetrahedra involved in this structure. * * @param whichTet specifies which tetrahedron to return; this * must be either 0 or 1. * @return the requested tetrahedron. */ NTetrahedron* getTetrahedron(int whichTet) const; /** * Returns the vertex number of the given tetrahedron * corresponding to the degree three vertex in the interior of * the triangular pillow. See the general class notes for * further details. * * The specific tetrahedron to examine is determined by the * argument \a whichTet; this will be the tetrahedron * getTetrahedron(whichTet). * * @param whichTet specifies which tetrahedron to examine; * this must be either 0 or 1. * @return the vertex of tetrahedron \a whichTet corresponding * to the vertex in the interior of the triangular pillow; this * will be between 0 and 3 inclusive. */ unsigned getInteriorVertex(int whichTet) const; /** * Determines if the given triangulation component is a * triangular pillow L(3,1). * * @param comp the triangulation component to examine. * @return a newly created structure containing details of the * triangular pillow L(3,1), or \c null if the given component is * not a triangular pillow L(3,1). */ static NL31Pillow* isL31Pillow(const NComponent* comp); NManifold* getManifold() const; NAbelianGroup* getHomologyH1() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; void writeTextLong(std::ostream& out) const; private: /** * Creates a new uninitialised structure. */ NL31Pillow(); }; /*@}*/ // Inline functions for NL31Pillow inline NL31Pillow::NL31Pillow() { } inline NL31Pillow::~NL31Pillow() { } inline NTetrahedron* NL31Pillow::getTetrahedron(int whichTet) const { return tet[whichTet]; } inline unsigned NL31Pillow::getInteriorVertex(int whichTet) const { return interior[whichTet]; } inline std::ostream& NL31Pillow::writeName(std::ostream& out) const { return out << "L'(3,1)"; } inline std::ostream& NL31Pillow::writeTeXName(std::ostream& out) const { return out << "L'_{3,1}"; } inline void NL31Pillow::writeTextLong(std::ostream& out) const { out << "Triangular pillow lens space L(3,1)"; } } // namespace regina #endif regina-4.96/engine/subcomplex/nlayeredchain.cpp000644 000765 000024 00000011112 12377776666 021577 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "algebra/nabeliangroup.h" #include "manifold/nhandlebody.h" #include "triangulation/nedge.h" #include "triangulation/ntetrahedron.h" #include "subcomplex/nlayeredchain.h" namespace regina { bool NLayeredChain::extendAbove() { NTetrahedron* adj = top->adjacentTetrahedron(topVertexRoles[0]); if (adj == bottom || adj == top || adj == 0) return false; if (adj != top->adjacentTetrahedron(topVertexRoles[3])) return false; // Check the gluings. NPerm4 adjRoles = top->adjacentGluing(topVertexRoles[0]) * topVertexRoles * NPerm4(0, 1); if (adjRoles != top->adjacentGluing(topVertexRoles[3]) * topVertexRoles * NPerm4(2, 3)) return false; // We can extend the layered chain. top = adj; topVertexRoles = adjRoles; index++; return true; } bool NLayeredChain::extendBelow() { NTetrahedron* adj = bottom->adjacentTetrahedron(bottomVertexRoles[1]); if (adj == bottom || adj == top || adj == 0) return false; if (adj != bottom->adjacentTetrahedron(bottomVertexRoles[2])) return false; // Check the gluings. NPerm4 adjRoles = bottom->adjacentGluing(bottomVertexRoles[1]) * bottomVertexRoles * NPerm4(0, 1); if (adjRoles != bottom->adjacentGluing(bottomVertexRoles[2]) * bottomVertexRoles * NPerm4(2, 3)) return false; // We can extend the layered chain. bottom = adj; bottomVertexRoles = adjRoles; index++; return true; } bool NLayeredChain::extendMaximal() { bool changed = false; while (extendAbove()) changed = true; while (extendBelow()) changed = true; return changed; } void NLayeredChain::reverse() { NTetrahedron* tmp = top; top = bottom; bottom = tmp; NPerm4 pTmp = topVertexRoles * NPerm4(1, 0, 3, 2); topVertexRoles = bottomVertexRoles * NPerm4(1, 0, 3, 2); bottomVertexRoles = pTmp; } void NLayeredChain::invert() { topVertexRoles = topVertexRoles * NPerm4(3, 2, 1, 0); bottomVertexRoles = bottomVertexRoles * NPerm4(3, 2, 1, 0); } NManifold* NLayeredChain::getManifold() const { return new NHandlebody(index <= 1 ? 0 : 1, true); } NAbelianGroup* NLayeredChain::getHomologyH1() const { NAbelianGroup* ans = new NAbelianGroup(); if (index > 1) ans->addRank(); return ans; } } // namespace regina regina-4.96/engine/subcomplex/nlayeredchain.h000644 000765 000024 00000030211 12377775447 021241 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/nlayeredchain.h * \brief Deals with layered chains in a triangulation. */ #ifndef __NLAYEREDCHAIN_H #ifndef __DOXYGEN #define __NLAYEREDCHAIN_H #endif #include "regina-core.h" #include "maths/nperm4.h" #include "subcomplex/nstandardtri.h" namespace regina { class NTetrahedron; /** * \weakgroup subcomplex * @{ */ /** * Represents a layered chain in a triangulation. * * A layered chain is a set of \a n tetrahedra glued to each other by * layerings. For each tetrahedron, select two top faces, two bottom * faces and two hinge edges, so that the top faces are adjacent, the * bottom faces are adjacent, the hinge edges are opposite and each * hinge meets both a top and a bottom face. The tetrahedron can thus * be thought of as a fattened square with the top and bottom faces * above and below the square respectively, and the hinges as the top * and bottom edges of the square. The left and right edges of the * square are identified to form an annulus. * * For each \a i, the top faces of tetrahedron \a i are glued to the * bottom faces of tetrahedron i+1. This is done by layering the * upper tetrahedron upon the annulus formed by the top faces of the * lower tetrahedron. The layering should be done over the left or * right edge of the lower square (note that these two edges are * actually identified). The top hinges of each tetrahedron should be * identified, as should the bottom hinges. * * The bottom faces of the first tetrahedron and the top faces of the * last tetrahedron form the boundary of the layered chain. If there is * more than one tetrahedron, the layered chain forms a solid torus with * two vertices whose axis is parallel to each hinge edge. * * The \a index of the layered chain is the number of tetrahedra it * contains. A layered chain must contain at least one tetrahedron. * * Note that for the purposes of getManifold() and getHomologyH1(), a * layered chain containing only one tetrahedron will be considered as a * standalone tetrahedron that forms a 3-ball (and not a solid torus). * * All optional NStandardTriangulation routines are implemented for this * class. */ class REGINA_API NLayeredChain : public NStandardTriangulation { private: NTetrahedron* bottom; /**< The bottom tetrahedron of this layered chain. */ NTetrahedron* top; /**< The top tetrahedron of this layered chain. */ unsigned long index; /**< The number of tetrahedra in this layered chain. */ NPerm4 bottomVertexRoles; /**< The permutation described by getBottomVertexRoles(). */ NPerm4 topVertexRoles; /**< The permutation described by getTopVertexRoles(). */ public: /** * Creates a new layered chain containing only the given * tetrahedron. This new layered chain will have index 1, but * may be extended using extendAbove(), extendBelow() or * extendMaximal(). * * @param tet the tetrahedron that will make up this layered * chain. * @param vertexRoles a permutation describing the role each * tetrahedron vertex must play in the layered chain; this must be * in the same format as the permutation returned by * getBottomVertexRoles() and getTopVertexRoles(). */ NLayeredChain(NTetrahedron* tet, NPerm4 vertexRoles); /** * Creates a new layered chain that is a clone of the given * structure. * * @param cloneMe the layered chain to clone. */ NLayeredChain(const NLayeredChain& cloneMe); /** * Destroys this layered chain. */ virtual ~NLayeredChain(); /** * Returns the bottom tetrahedron of this layered chain. * * @return the bottom tetrahedron. */ NTetrahedron* getBottom() const; /** * Returns the top tetrahedron of this layered chain. * * @return the top tetrahedron. */ NTetrahedron* getTop() const; /** * Returns the number of tetrahedra in this layered chain. * * @return the number of tetrahedra. */ unsigned long getIndex() const; /** * Returns a permutation represeting the role that each vertex * of the bottom tetrahedron plays in the layered chain. * The permutation returned (call this p) maps 0, 1, 2 and * 3 to the four vertices of the bottom tetrahedron so that the * edge from p[0] to p[1] is the top hinge, * the edge from p[2] to p[3] is the bottom * hinge, faces p[1] and p[2] are the (boundary) * bottom faces and faces p[0] and p[3] are the top * faces. * * See the general class notes for further details. * * @return a permutation representing the roles of the vertices * of the bottom tetrahedron. */ NPerm4 getBottomVertexRoles() const; /** * Returns a permutation represeting the role that each vertex * of the top tetrahedron plays in the layered chain. * The permutation returned (call this p) maps 0, 1, 2 and * 3 to the four vertices of the top tetrahedron so that the * edge from p[0] to p[1] is the top hinge, * the edge from p[2] to p[3] is the bottom * hinge, faces p[1] and p[2] are the bottom * faces and faces p[0] and p[3] are the * (boundary) top faces. * * See the general class notes for further details. * * @return a permutation representing the roles of the vertices * of the top tetrahedron. */ NPerm4 getTopVertexRoles() const; /** * Checks to see whether this layered chain can be extended to * include the tetrahedron above the top tetrahedron (and still * remain a layered chain). If so, this layered chain will be * modified accordingly (note that its index will be increased * by one and its top tetrahedron will change). * * @return \c true if and only if this layered chain was * extended. */ bool extendAbove(); /** * Checks to see whether this layered chain can be extended to * include the tetrahedron below the bottom tetrahedron (and still * remain a layered chain). If so, this layered chain will be * modified accordingly (note that its index will be increased * by one and its bottom tetrahedron will change). * * @return \c true if and only if this layered chain was * extended. */ bool extendBelow(); /** * Extends this layered chain to a maximal length layered chain. * Both extendAbove() and extendBelow() will be used until this * layered chain can be extended no further. * * @return \c true if and only if this layered chain was * extended. */ bool extendMaximal(); /** * Reverses this layered chain so the top tetrahedron becomes * the bottom and vice versa. The upper and lower hinges will * remain the upper and lower hinges respectively. * * Note that this operation will cause the hinge edges to point * in the opposite direction around the solid torus formed by * this layered chain. * * Note that only the representation of the chain is altered; * the underlying triangulation is not changed. */ void reverse(); /** * Inverts this layered chain so the upper hinge becomes the * lower and vice versa. The top and bottom tetrahedra will * remain the top and bottom tetrahedra respectively. * * Note that this operation will cause the hinge edges to point * in the opposite direction around the solid torus formed by * this layered chain. * * Note that only the representation of the chain is altered; * the underlying triangulation is not changed. */ void invert(); NManifold* getManifold() const; NAbelianGroup* getHomologyH1() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; void writeTextLong(std::ostream& out) const; }; /*@}*/ // Inline functions for NLayeredChain inline NLayeredChain::NLayeredChain(NTetrahedron* tet, NPerm4 vertexRoles) : bottom(tet), top(tet), index(1), bottomVertexRoles(vertexRoles), topVertexRoles(vertexRoles) { } inline NLayeredChain::NLayeredChain(const NLayeredChain& cloneMe) : NStandardTriangulation(), bottom(cloneMe.bottom), top(cloneMe.top), index(cloneMe.index), bottomVertexRoles(cloneMe.bottomVertexRoles), topVertexRoles(cloneMe.topVertexRoles) { } inline NLayeredChain::~NLayeredChain() { } inline NTetrahedron* NLayeredChain::getBottom() const { return bottom; } inline NTetrahedron* NLayeredChain::getTop() const { return top; } inline unsigned long NLayeredChain::getIndex() const { return index; } inline NPerm4 NLayeredChain::getBottomVertexRoles() const { return bottomVertexRoles; } inline NPerm4 NLayeredChain::getTopVertexRoles() const { return topVertexRoles; } inline std::ostream& NLayeredChain::writeName(std::ostream& out) const { return out << "Chain(" << index << ')'; } inline std::ostream& NLayeredChain::writeTeXName(std::ostream& out) const { return out << "\\mathit{Chain}(" << index << ')'; } inline void NLayeredChain::writeTextLong(std::ostream& out) const { out << "Layered chain of index " << index; } } // namespace regina #endif regina-4.96/engine/subcomplex/nlayeredchainpair.cpp000644 000765 000024 00000021423 12377776666 022461 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "algebra/nabeliangroup.h" #include "manifold/nsfs.h" #include "maths/nmatrixint.h" #include "triangulation/ncomponent.h" #include "triangulation/ntetrahedron.h" #include "subcomplex/nlayeredchainpair.h" namespace regina { NLayeredChainPair* NLayeredChainPair::clone() const { NLayeredChainPair* ans = new NLayeredChainPair(); if (chain[0]) ans->chain[0] = new NLayeredChain(*chain[0]); if (chain[1]) ans->chain[1] = new NLayeredChain(*chain[1]); return ans; } NLayeredChainPair* NLayeredChainPair::isLayeredChainPair( const NComponent* comp) { // Basic property check. if ((! comp->isClosed()) || (! comp->isOrientable())) return 0; unsigned long nTet = comp->getNumberOfTetrahedra(); if (nTet < 2) return 0; if (comp->getNumberOfVertices() != 1) return 0; // We have at least two tetrahedra and precisely 1 vertex. // The component is closed and orientable (and connected, since it's // a component). // Start with tetrahedron 0. This must belong to *some* chain. NTetrahedron* base = comp->getTetrahedron(0); NLayeredChain* first; NLayeredChain* second; // Note that we only need check permutations in S3 since we can // arbitrarily assign the role of one vertex in the tetrahedron. NTetrahedron* firstBottom; NTetrahedron* firstTop; NTetrahedron* secondBottom; NTetrahedron* secondTop; NPerm4 firstBottomRoles, firstTopRoles, secondBottomRoles, secondTopRoles; for (int p = 0; p < 6; p++) { first = new NLayeredChain(base, NPerm4::S3[p]); first->extendMaximal(); firstTop = first->getTop(); firstBottom = first->getBottom(); firstTopRoles = first->getTopVertexRoles(); firstBottomRoles = first->getBottomVertexRoles(); // Check to see if the first chain fills the entire component. if (first->getIndex() == nTet) { // The only success here will be if we have a chain pair of // indices (n-1) and 1, which is in fact a layered loop. NLayeredChain* longChain = new NLayeredChain( firstBottom, firstBottomRoles); if (longChain->extendBelow()) if (longChain->getBottom() == firstTop && longChain->getBottomVertexRoles() == firstTopRoles * NPerm4(3, 2, 1, 0)) { // We've got a layered loop! NLayeredChainPair* ans = new NLayeredChainPair(); if (nTet == 2) { // The new chain is already too long. delete longChain; longChain = new NLayeredChain( firstBottom, firstBottomRoles); } // Extend longChain to (n-1) tetrahedra. while (longChain->getIndex() + 1 < nTet) longChain->extendBelow(); ans->chain[1] = longChain; ans->chain[0] = new NLayeredChain( firstBottom->adjacentTetrahedron( firstBottomRoles[0]), firstBottom->adjacentGluing( firstBottomRoles[0]) * firstBottomRoles * NPerm4(0, 2, 1, 3)); delete first; return ans; } delete longChain; delete first; continue; } // At this point we must have run into the second chain. secondBottom = firstTop->adjacentTetrahedron(firstTopRoles[3]); if (secondBottom == firstTop || secondBottom == firstBottom || secondBottom == 0) { delete first; continue; } second = new NLayeredChain(secondBottom, firstTop->adjacentGluing(firstTopRoles[3]) * firstTopRoles * NPerm4(1, 3, 0, 2)); while (second->extendAbove()) ; if (second->getIndex() + first->getIndex() != nTet) { delete first; delete second; continue; } secondTop = second->getTop(); secondTopRoles = second->getTopVertexRoles(); secondBottomRoles = second->getBottomVertexRoles(); // At this point we have two chains that together have the // correct number of tetrahedra. All we need do is check the // remaining three between-chain gluings. if (secondTop == firstTop->adjacentTetrahedron(firstTopRoles[0]) && secondBottom == firstBottom->adjacentTetrahedron( firstBottomRoles[2]) && secondTop == firstBottom->adjacentTetrahedron( firstBottomRoles[1]) && secondTopRoles == firstTop->adjacentGluing( firstTopRoles[0]) * firstTopRoles * NPerm4(0, 2, 1, 3) && secondBottomRoles == firstBottom->adjacentGluing( firstBottomRoles[2]) * firstBottomRoles * NPerm4(3, 1, 2, 0) && secondTopRoles == firstBottom->adjacentGluing( firstBottomRoles[1]) * firstBottomRoles * NPerm4(2, 0, 3, 1)) { // We found one! NLayeredChainPair* ans = new NLayeredChainPair(); if (first->getIndex() > second->getIndex()) { ans->chain[0] = second; ans->chain[1] = first; } else { ans->chain[0] = first; ans->chain[1] = second; } return ans; } else { delete first; delete second; } } // Nothing was found. Sigh. return 0; } NManifold* NLayeredChainPair::getManifold() const { NSFSpace* ans = new NSFSpace(); ans->insertFibre(2, -1); ans->insertFibre(chain[0]->getIndex() + 1, 1); ans->insertFibre(chain[1]->getIndex() + 1, 1); ans->reduce(); return ans; } NAbelianGroup* NLayeredChainPair::getHomologyH1() const { // The first homology group can be obtained from the matrix: // // [ 1 -1 1 ] // [ n_1 1 1 ] // [ 1 n_2 -1 ] // // This is established simply by examining the edges on the boundary // of each layered chain. NAbelianGroup* ans = new NAbelianGroup(); NMatrixInt mat(3, 3); mat.initialise(1); mat.entry(0, 1) = mat.entry(2, 2) = -1; mat.entry(1, 0) = chain[0]->getIndex(); mat.entry(2, 1) = chain[1]->getIndex(); ans->addGroup(mat); return ans; } } // namespace regina regina-4.96/engine/subcomplex/nlayeredchainpair.h000644 000765 000024 00000014726 12377775451 022125 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/nlayeredchainpair.h * \brief Deals with layered chain pair components of a triangulation. */ #ifndef __NLAYEREDCHAINPAIR_H #ifndef __DOXYGEN #define __NLAYEREDCHAINPAIR_H #endif #include "regina-core.h" #include "subcomplex/nlayeredchain.h" namespace regina { class NComponent; /** * \weakgroup subcomplex * @{ */ /** * Represents a layered chain pair component of a triangulation. * * A layered chain pair consists of two layered chains (as described by * class NLayeredChain) glued together in a particular way. * * Orient the hinge edges and diagonals of each chain so they all point * in the same direction around the solid tori formed by each layered * chain (a \e diagonal is an edge between the two top triangular faces or an * edge between the two bottom triangular faces of a layered chain). * * The two top faces of the first chain are glued to a top and bottom * face of the second chain, and the two bottom faces of the first chain * are glued to a top and bottom face of the second chain. * * The four oriented diagonals are all identified as a single edge. Of the * remaining unglued edges (two hinge edges and two non-hinge edges per chain), * each hinge edge of one chain must be identified to a non-hinge edge of * the other chain and vice versa. From here the face identifications are * uniquely determined. * * Note that a layered chain pair in which one of the chains contains * only one tetrahedron is in fact a layered loop with a twist * (see class NLayeredLoop). * * All optional NStandardTriangulation routines are implemented for this * class. */ class REGINA_API NLayeredChainPair : public NStandardTriangulation { private: NLayeredChain* chain[2]; /**< The two layered chains that make up this pair. */ public: /** * Destroys this layered chain pair. */ virtual ~NLayeredChainPair(); /** * Returns a newly created clone of this structure. * * @return a newly created clone. */ NLayeredChainPair* clone() const; /** * Returns the requested layered chain used to form this structure. * If the two chains have different lengths, the shorter chain * will be chain 0 and the longer chain will be chain 1. * * @param which specifies which chain to return; this must be 0 * or 1. * @return the requested layered chain. */ const NLayeredChain* getChain(int which) const; /** * Determines if the given triangulation component is a layered * chain pair. * * @param comp the triangulation component to examine. * @return a newly created structure containing details of the * layered chain pair, or \c null if the given component is * not a layered chain pair. */ static NLayeredChainPair* isLayeredChainPair(const NComponent* comp); NManifold* getManifold() const; NAbelianGroup* getHomologyH1() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; void writeTextLong(std::ostream& out) const; private: /** * Creates a new uninitialised structure. */ NLayeredChainPair(); }; /*@}*/ // Inline functions for NLayeredChainPair inline NLayeredChainPair::NLayeredChainPair() { chain[0] = chain[1] = 0; } inline NLayeredChainPair::~NLayeredChainPair() { if (chain[0]) delete chain[0]; if (chain[1]) delete chain[1]; } inline const NLayeredChain* NLayeredChainPair::getChain(int which) const { return chain[which]; } inline std::ostream& NLayeredChainPair::writeName(std::ostream& out) const { return out << "C(" << chain[0]->getIndex() << ',' << chain[1]->getIndex() << ')'; } inline std::ostream& NLayeredChainPair::writeTeXName(std::ostream& out) const { return out << "C_{" << chain[0]->getIndex() << ',' << chain[1]->getIndex() << '}'; } inline void NLayeredChainPair::writeTextLong(std::ostream& out) const { out << "Layered chain pair (chain lengths " << chain[0]->getIndex() << ", " << chain[1]->getIndex() << ')'; } } // namespace regina #endif regina-4.96/engine/subcomplex/nlayeredlensspace.cpp000644 000765 000024 00000016065 12377776667 022507 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "algebra/nabeliangroup.h" #include "manifold/nlensspace.h" #include "maths/numbertheory.h" #include "subcomplex/nlayeredlensspace.h" #include "triangulation/nedge.h" #include "triangulation/ncomponent.h" #include "triangulation/ntetrahedron.h" namespace regina { NLayeredLensSpace* NLayeredLensSpace::clone() const { NLayeredLensSpace* ans = new NLayeredLensSpace(); ans->torus = torus->clone(); ans->mobiusBoundaryGroup = mobiusBoundaryGroup; ans->p = p; ans->q = q; return ans; } NLayeredLensSpace* NLayeredLensSpace::isLayeredLensSpace( const NComponent* comp) { // Basic property check. if ((! comp->isClosed()) || (! comp->isOrientable())) return 0; if (comp->getNumberOfVertices() > 1) return 0; unsigned long nTet = comp->getNumberOfTetrahedra(); NLayeredSolidTorus* torus; for (unsigned long i = 0; i < nTet; i++) { torus = NLayeredSolidTorus::formsLayeredSolidTorusBase( comp->getTetrahedron(i)); if (torus) { // We have found a layered solid torus; either this makes the // layered lens space or nothing makes the layered lens space. NTetrahedron* tet = torus->getTopLevel(); int tf0 = torus->getTopFace(0); int tf1 = torus->getTopFace(1); if (tet->adjacentTetrahedron(tf0) != tet) { delete torus; return 0; } /* We already know the component is orientable; no need to check orientation! if (perm.sign() == 1) { delete torus; return 0; }*/ // This is the real thing! NLayeredLensSpace* ans = new NLayeredLensSpace(); ans->torus = torus; NPerm4 perm = tet->adjacentGluing(tf0); if (perm[tf1] == tf0) { // Snapped shut. ans->mobiusBoundaryGroup = torus->getTopEdgeGroup( 5 - NEdge::edgeNumber[tf0][tf1]); } else { // Twisted shut. ans->mobiusBoundaryGroup = torus->getTopEdgeGroup( NEdge::edgeNumber[perm[tf1]][tf0]); } // Work out p and q. switch (ans->mobiusBoundaryGroup) { // For layered solid torus (x < y < z): case 0: // L( x + 2y, y ) ans->p = torus->getMeridinalCuts(1) + torus->getMeridinalCuts(2); ans->q = torus->getMeridinalCuts(1); break; case 1: // L( 2x + y, x ) ans->p = torus->getMeridinalCuts(0) + torus->getMeridinalCuts(2); ans->q = torus->getMeridinalCuts(0); break; case 2: // L( y - x, x ) ans->p = torus->getMeridinalCuts(1) - torus->getMeridinalCuts(0); if (ans->p == 0) ans->q = 1; else ans->q = torus->getMeridinalCuts(0) % ans->p; break; } // Find the nicest possible value for q. // Choices are +/- q, +/- 1/q. if (ans->p > 0) { if (2 * ans->q > ans->p) ans->q = ans->p - ans->q; if (ans->q > 0) { unsigned long qAlt = modularInverse(ans->p, ans->q); if (2 * qAlt > ans->p) qAlt = ans->p - qAlt; if (qAlt < ans->q) ans->q = qAlt; } } return ans; } } return 0; } NManifold* NLayeredLensSpace::getManifold() const { return new NLensSpace(p, q); } NAbelianGroup* NLayeredLensSpace::getHomologyH1() const { NAbelianGroup* ans = new NAbelianGroup(); if (p == 0) ans->addRank(); else if (p > 1) ans->addTorsionElement(p); return ans; } std::ostream& NLayeredLensSpace::writeName(std::ostream& out) const { if (p == 3 && q == 1) { out << "L(3,1)"; if (torus->getNumberOfTetrahedra() != 2) return out; else if (isSnapped()) return out << " (1)"; else return out << " (2)"; } else return out << "L(" << p << ',' << q << ')'; } std::ostream& NLayeredLensSpace::writeTeXName(std::ostream& out) const { if (p == 3 && q == 1) { out << "L_{3,1}"; if (torus->getNumberOfTetrahedra() != 2) return out; else if (isSnapped()) return out << "^{(1)}"; else return out << "^{(2)}"; } else return out << "L_{" << p << ',' << q << '}'; } } // namespace regina regina-4.96/engine/subcomplex/nlayeredlensspace.h000644 000765 000024 00000017004 12377775452 022135 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/nlayeredlensspace.h * \brief Deals with layered lens space components of a triangulation. */ #ifndef __NLAYEREDLENSSPACE_H #ifndef __DOXYGEN #define __NLAYEREDLENSSPACE_H #endif #include "regina-core.h" #include "subcomplex/nlayeredsolidtorus.h" #include "subcomplex/nstandardtri.h" namespace regina { /** * \weakgroup subcomplex * @{ */ /** * Represents a layered lens space component of a triangulation. * A layered lens space is considered to be any layered solid torus glued * to a degenerate (2,1,1) layered solid torus (i.e., a one-triangle mobius * strip). Note that the three possible gluing options represent the * three possible ways of closing the initial torus - either twisting it * shut (in one of two possible ways) or snapping it shut without any twist. * * A layered lens space must contain at least one tetrahedron. * * All optional NStandardTriangulation routines are implemented for this * class. */ class REGINA_API NLayeredLensSpace : public NStandardTriangulation { private: NLayeredSolidTorus* torus; /**< The layered solid torus that forms the basis of this layered lens space. */ int mobiusBoundaryGroup; /**< The edge group of the top level tetrahedron in the layered solid torus to which the boundary of the mobius strip is glued. */ unsigned long p,q; /**< The lens space parameters for L(p,q). */ public: /** * Destroys this lens space; note that the corresponding layered * solid torus will also be destroyed. */ virtual ~NLayeredLensSpace(); /** * Returns a newly created clone of this structure. * * @return a newly created clone. */ NLayeredLensSpace* clone() const; /** * Returns the first parameter \a p of this lens space L(p,q). * * @return the first parameter \a p. */ unsigned long getP() const; /** * Returns the second parameter \a q of this lens space L(p,q). * * @return the second parameter \a q. */ unsigned long getQ() const; /** * Returns the layered solid torus to which the mobius strip is * glued. * * @return the layered solid torus. */ const NLayeredSolidTorus& getTorus() const; /** * Determines which edge of the layered solid torus is glued to * the boundary of the mobius strip (i.e., the weight 2 edge * of the degenerate (2,1,1) layered solid torus). The return * value will be one of the three top level tetrahedron edge * groups in the layered solid torus; see * NLayeredSolidTorus::getTopEdge() for further details about * edge groups. * * @return the top level edge group of the layered solid torus to * which the mobius strip boundary is glued. */ int getMobiusBoundaryGroup() const; /** * Determines if the layered solid torus that forms the basis for * this lens space is snapped shut (folded closed without a twist). * * @return \c true if and only if the torus is snapped shut. */ bool isSnapped() const; /** * Determines if the layered solid torus that forms the basis for * this lens space is twisted shut (folded closed with a twist). * * @return \c true if and only if the torus is twisted shut. */ bool isTwisted() const; /** * Determines if the given triangulation component is a layered * lens space. * * @param comp the triangulation component to examine. * @return a newly created structure containing details of the * layered lens space, or \c null if the given component is * not a layered lens space. */ static NLayeredLensSpace* isLayeredLensSpace(const NComponent* comp); NManifold* getManifold() const; NAbelianGroup* getHomologyH1() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; void writeTextLong(std::ostream& out) const; private: /** * Creates a new uninitialised structure. */ NLayeredLensSpace(); }; /*@}*/ // Inline functions for NLayeredLensSpace inline NLayeredLensSpace::NLayeredLensSpace() { } inline NLayeredLensSpace::~NLayeredLensSpace() { delete torus; } inline unsigned long NLayeredLensSpace::getP() const { return p; } inline unsigned long NLayeredLensSpace::getQ() const { return q; } inline const NLayeredSolidTorus& NLayeredLensSpace::getTorus() const { return *torus; } inline int NLayeredLensSpace::getMobiusBoundaryGroup() const { return mobiusBoundaryGroup; } inline bool NLayeredLensSpace::isSnapped() const { return (torus->getTopEdge(mobiusBoundaryGroup, 1) == -1); } inline bool NLayeredLensSpace::isTwisted() const { return (torus->getTopEdge(mobiusBoundaryGroup, 1) != -1); } inline void NLayeredLensSpace::writeTextLong(std::ostream& out) const { out << "Layered lens space "; writeName(out); } } // namespace regina #endif regina-4.96/engine/subcomplex/nlayeredloop.cpp000644 000765 000024 00000020563 12377776670 021473 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "algebra/nabeliangroup.h" #include "manifold/nlensspace.h" #include "manifold/nsfs.h" #include "triangulation/nedge.h" #include "triangulation/ncomponent.h" #include "triangulation/ntetrahedron.h" #include "subcomplex/nlayeredloop.h" namespace regina { NLayeredLoop* NLayeredLoop::clone() const { NLayeredLoop* ans = new NLayeredLoop(); ans->length = length; ans->hinge[0] = hinge[0]; ans->hinge[1] = hinge[1]; return ans; } NManifold* NLayeredLoop::getManifold() const { if (hinge[1]) { // Not twisted. return new NLensSpace(length, 1); } else { // Twisted. NSFSpace* ans = new NSFSpace(); ans->insertFibre(2, -1); ans->insertFibre(2, 1); ans->insertFibre(length, 1); ans->reduce(); return ans; } } NLayeredLoop* NLayeredLoop::isLayeredLoop(const NComponent* comp) { // Basic property check. if ((! comp->isClosed()) || (! comp->isOrientable())) return 0; unsigned long nTet = comp->getNumberOfTetrahedra(); if (nTet == 0) return 0; unsigned long nVertices = comp->getNumberOfVertices(); if (nVertices > 2) return 0; bool twisted = (nVertices == 1); // We have at least 1 tetrahedron and precisely 1 or 2 vertices. // The component is closed and orientable (and connected, since it's // a component). // Pick our base tetrahedron. NTetrahedron* base = comp->getTetrahedron(0); NTetrahedron* tet = base; NTetrahedron* next; int baseTop0, baseTop1, baseBottom0, baseBottom1; int top0, top1, bottom0, bottom1; int adjTop0 = 0, adjTop1 = 0, adjBottom0 = 0, adjBottom1 = 0; int hinge0, hinge1; NPerm4 p; bool ok; // Declare 0 to be a top face; find its partner. baseTop0 = 0; next = base->adjacentTetrahedron(0); for (baseTop1 = 1; baseTop1 < 4; baseTop1++) { if (base->adjacentTetrahedron(baseTop1) != next) continue; // Find the vertex joined to baseTop0 by a hinge. for (baseBottom0 = 1; baseBottom0 < 4; baseBottom0++) { if (baseBottom0 == baseTop1) continue; baseBottom1 = 6 - baseBottom0 - baseTop0 - baseTop1; // Some basic property checks. if (base->adjacentTetrahedron(baseBottom0) != base->adjacentTetrahedron(baseBottom1)) continue; hinge0 = NEdge::edgeNumber[baseTop0][baseBottom0]; hinge1 = NEdge::edgeNumber[baseTop1][baseBottom1]; if (twisted) { if (base->getEdge(hinge0) != base->getEdge(hinge1)) continue; if (base->getEdge(hinge0)->getNumberOfEmbeddings() != 2 * nTet) continue; } else { if (base->getEdge(hinge0)->getNumberOfEmbeddings() != nTet) continue; if (base->getEdge(hinge1)->getNumberOfEmbeddings() != nTet) continue; } top0 = baseTop0; top1 = baseTop1; bottom0 = baseBottom0; bottom1 = baseBottom1; // Follow the gluings up. ok = true; while (true) { // Already set: tet, next, topi, bottomi. // Check that both steps up lead to the same tetrahedron. // Note that this check has already been done for the first // iteration of this loop; never mind, no big loss. if (tet->adjacentTetrahedron(top0) != tet->adjacentTetrahedron(top1)) { ok = false; break; } // Check that the corresponding gluings are correct. p = tet->adjacentGluing(top0); adjTop0 = p[bottom0]; adjTop1 = p[top1]; adjBottom0 = p[top0]; adjBottom1 = p[bottom1]; p = tet->adjacentGluing(top1); // Note that only three of the four comparisons are needed. if (adjTop0 != p[top0] || adjTop1 != p[bottom1] || adjBottom0 != p[bottom0]) { ok = false; break; } // If we've finished the loop, exit at this point so we // can check that it all glued up correctly. if (next == base) break; // We haven't finished the loop, so the next // tetrahedron should be different from this one. if (next == tet) { ok = false; break; } // Move to the next tetrahedron. top0 = adjTop0; top1 = adjTop1; bottom0 = adjBottom0; bottom1 = adjBottom1; tet = next; next = tet->adjacentTetrahedron(top0); } if (ok) { // Make sure the final gluing wraps everything up // correctly. if (twisted) { if (adjTop0 != baseTop1 || adjTop1 != baseTop0 || adjBottom0 != baseBottom1) continue; } else { if (adjTop0 != baseTop0 || adjTop1 != baseTop1 || adjBottom0 != baseBottom0) continue; } // We have a solution! NLayeredLoop* ans = new NLayeredLoop(); ans->length = nTet; ans->hinge[0] = base->getEdge(hinge0); ans->hinge[1] = (twisted ? 0 : base->getEdge(hinge1)); return ans; } } } // Nothing found. return 0; } NAbelianGroup* NLayeredLoop::getHomologyH1() const { NAbelianGroup* ans = new NAbelianGroup(); if (hinge[1]) { // Untwisted. if (length > 1) ans->addTorsionElement(length); } else { // Twisted. if (length % 2 == 0) ans->addTorsionElement(2, 2); else ans->addTorsionElement(4); } return ans; } } // namespace regina regina-4.96/engine/subcomplex/nlayeredloop.h000644 000765 000024 00000016547 12377775454 021146 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/nlayeredloop.h * \brief Deals with layered loop components of a triangulation. */ #ifndef __NLAYEREDLOOP_H #ifndef __DOXYGEN #define __NLAYEREDLOOP_H #endif #include "regina-core.h" #include "subcomplex/nstandardtri.h" namespace regina { class NEdge; /** * \weakgroup subcomplex * @{ */ /** * Represents a layered loop component of a triangulation. * * A layered loop is a layered chain of \a n tetrahedra whose bottom * tetrahedron is layered onto its top tetrahedron to form a complete * loop. See the NLayeredChain class notes for a description of a * layered chain. * * To make a layered chain into a layered * loop, the bottom faces of the first tetrahedron will be * layered upon the top faces of the last tetrahedron, completing the loop. * At this stage there is a choice. The layering can be done in the usual * fashion, or there may be a \a twist in which the upper square (the * bottom faces of the first tetrahedron) is rotated 180 degrees before * being layered on the lower annulus (the top faces of the last * tetrahedron). * * If there is a twist, the two hinge edges become identified and the * entire component has a single vertex. If there is no twist, the * two hinge edges remain distinct (and disjoint) and the entire * component has two vertices. * * The \a length of the layered loop is the number of tetrahedra it * contains. A layered loop must contain at least one tetrahedron. * * All optional NStandardTriangulation routines are implemented for this * class. */ class REGINA_API NLayeredLoop : public NStandardTriangulation { private: unsigned long length; /**< The length of this layered loop. */ NEdge* hinge[2]; /**< The hinge edge(s) of this layered loop. If the loop is twisted, the second element in this array will be \c null. */ public: /** * Destroys this layered loop. */ virtual ~NLayeredLoop(); /** * Returns a newly created clone of this structure. * * @return a newly created clone. */ NLayeredLoop* clone() const; /** * Returns the length of this layered loop. * See the general class notes for further details. * * @return the length of this layered loop. */ unsigned long getLength() const; /** * Returns the length of this layered loop. * See the general class notes for further details. * * \deprecated The preferred way of accessing the length of a * layered loop is through getLength(). * * @return the length of this layered loop. */ unsigned long getIndex() const; /** * Determines if this layered loop contains a twist. * See the general class notes for further details. * * @return \c true if and only if this layered loop contains a * twist. */ bool isTwisted() const; /** * Returns the requested hinge edge of this layered loop. * See the general class notes for further details. * If there is only one hinge but parameter \a which is 1, * \c null will be returned. * * @param which specifies which hinge to return; this must be 0 * or 1. * @return the requested hinge edge. */ NEdge* getHinge(int which) const; /** * Determines if the given triangulation component is a layered * loop. * * @param comp the triangulation component to examine. * @return a newly created structure containing details of the * layered loop, or \c null if the given component is * not a layered loop. */ static NLayeredLoop* isLayeredLoop(const NComponent* comp); NManifold* getManifold() const; NAbelianGroup* getHomologyH1() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; void writeTextLong(std::ostream& out) const; private: /** * Creates a new uninitialised structure. */ NLayeredLoop(); }; /*@}*/ // Inline functions for NLayeredLoop inline NLayeredLoop::NLayeredLoop() { } inline NLayeredLoop::~NLayeredLoop() { } inline unsigned long NLayeredLoop::getLength() const { return length; } inline unsigned long NLayeredLoop::getIndex() const { return length; } inline bool NLayeredLoop::isTwisted() const { return (hinge[1] == 0); } inline NEdge* NLayeredLoop::getHinge(int which) const { return hinge[which]; } inline std::ostream& NLayeredLoop::writeName(std::ostream& out) const { return out << (hinge[1] ? "C(" : "C~(") << length << ')'; } inline std::ostream& NLayeredLoop::writeTeXName(std::ostream& out) const { return out << (hinge[1] ? "C_{" : "\\tilde{C}_{") << length << '}'; } inline void NLayeredLoop::writeTextLong(std::ostream& out) const { out << "Layered loop (" << (hinge[1] ? "not twisted" : "twisted") << ") of length " << length; } } // namespace regina #endif regina-4.96/engine/subcomplex/nlayeredsolidtorus.cpp000644 000765 000024 00000072127 12377776670 022734 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "algebra/nabeliangroup.h" #include "manifold/nhandlebody.h" #include "triangulation/nedge.h" #include "triangulation/nfacepair.h" #include "triangulation/ntetrahedron.h" #include "triangulation/ntriangulation.h" #include "subcomplex/nlayeredsolidtorus.h" namespace regina { NLayeredSolidTorus* NLayeredSolidTorus::clone() const { NLayeredSolidTorus* ans = new NLayeredSolidTorus(); int i,j; ans->nTetrahedra = nTetrahedra; ans->base = base; ans->topLevel = topLevel; for (i = 0; i < 6; i++) { ans->baseEdge[i] = baseEdge[i]; ans->baseEdgeGroup[i] = baseEdgeGroup[i]; ans->topEdgeGroup[i] = topEdgeGroup[i]; } for (i = 0; i < 2; i++) { ans->baseFace[i] = baseFace[i]; ans->topFace[i] = topFace[i]; } for (i = 0; i < 3; i++) { for (j = 0; j < 2; j++) ans->topEdge[i][j] = topEdge[i][j]; ans->meridinalCuts[i] = meridinalCuts[i]; } return ans; } void NLayeredSolidTorus::transform(const NTriangulation* originalTri, const NIsomorphism* iso, NTriangulation* newTri) { unsigned i, j; unsigned long baseTetID = originalTri->tetrahedronIndex(base); unsigned long topTetID = originalTri->tetrahedronIndex(topLevel); // Data members nTetrahedra and meridinalCuts remain unchanged. // Transform edge numbers (note that -1s can also be present for topEdge[]): for (i = 0; i < 6; i++) baseEdge[i] = NEdge::edgeNumber [iso->facePerm(baseTetID)[NEdge::edgeVertex[baseEdge[i]][0]]] [iso->facePerm(baseTetID)[NEdge::edgeVertex[baseEdge[i]][1]]]; for (i = 0; i < 3; i++) for (j = 0; j < 2; j++) { if (topEdge[i][j] < 0) continue; topEdge[i][j] = NEdge::edgeNumber [iso->facePerm(topTetID)[NEdge::edgeVertex[topEdge[i][j]][0]]] [iso->facePerm(topTetID)[NEdge::edgeVertex[topEdge[i][j]][1]]]; } // Inverse arrays for edge numbers: for (i = 0; i < 6; i++) baseEdgeGroup[baseEdge[i]] = (i == 0 ? 1 : i < 3 ? 2 : 3); unsigned missingEdge = 0 + 1 + 2 + 3 + 4 + 5; for (i = 0; i < 3; i++) for (j = 0; j < 2; j++) if (topEdge[i][j] != -1) { topEdgeGroup[topEdge[i][j]] = i; missingEdge -= topEdge[i][j]; } topEdgeGroup[missingEdge] = -1; // Transform face numbers: for (i = 0; i < 2; i++) { baseFace[i] = iso->facePerm(baseTetID)[baseFace[i]]; topFace[i] = iso->facePerm(topTetID)[topFace[i]]; } // Transform tetrahedra: base = newTri->getTetrahedron(iso->tetImage(baseTetID)); topLevel = newTri->getTetrahedron(iso->tetImage(topTetID)); } NLayeredSolidTorus* NLayeredSolidTorus::formsLayeredSolidTorusBase( NTetrahedron* tet) { int baseFace1; int baseFace2 = -1; NPerm4 basePerm; bool okay; int i, j; for (baseFace1 = 0; baseFace1 < 3; baseFace1++) if (tet->adjacentTetrahedron(baseFace1) == tet) { // This tetrahedron is glued to itself. baseFace2 = tet->adjacentFace(baseFace1); basePerm = tet->adjacentGluing(baseFace1); okay = true; for (i = 0; i < 4; i++) { if (i == baseFace1 || i == baseFace2) continue; // No vertex should be glued to itself! if (basePerm[i] == i) { okay = false; break; } } if (okay && basePerm[baseFace2] != baseFace1) break; else baseFace2 = -1; } if (baseFace2 == -1) return 0; // We have a layered solid torus!! // Fill in the details for the bottom layer. NLayeredSolidTorus* ans = new NLayeredSolidTorus(); ans->nTetrahedra = 1; ans->base = tet; ans->baseFace[0] = baseFace1; ans->baseFace[1] = baseFace2; ans->topFace[0] = basePerm[baseFace2]; ans->topFace[1] = basePerm[ans->topFace[0]]; ans->baseEdge[0] = NEdge::edgeNumber[baseFace1][baseFace2]; ans->baseEdge[1] = NEdge::edgeNumber[ans->topFace[1]][baseFace2]; ans->baseEdge[2] = NEdge::edgeNumber[ans->topFace[0]][baseFace1]; ans->baseEdge[3] = NEdge::edgeNumber[ans->topFace[0]][baseFace2]; ans->baseEdge[4] = NEdge::edgeNumber[ans->topFace[0]][ans->topFace[1]]; ans->baseEdge[5] = NEdge::edgeNumber[ans->topFace[1]][baseFace1]; for (i = 0; i < 6; i++) ans->baseEdgeGroup[ans->baseEdge[i]] = (i == 0 ? 1 : i < 3 ? 2 : 3); ans->topLevel = tet; ans->meridinalCuts[0] = 1; ans->meridinalCuts[1] = 2; ans->meridinalCuts[2] = 3; ans->topEdge[0][0] = ans->baseEdge[5]; ans->topEdge[0][1] = ans->baseEdge[3]; ans->topEdge[1][0] = ans->baseEdge[1]; ans->topEdge[1][1] = ans->baseEdge[2]; ans->topEdge[2][0] = ans->baseEdge[0]; ans->topEdge[2][1] = -1; for (i = 0; i < 3; i++) for (j = 0; j < 2; j++) if (ans->topEdge[i][j] != -1) ans->topEdgeGroup[ans->topEdge[i][j]] = i; ans->topEdgeGroup[ans->baseEdge[4]] = -1; // Now run through and look for layers to add to the torus. int adjFace[2]; // Faces of adjacent tetrahedron glued to the torus. int adjEdge; // Layering edge of the adjacent tetrahedron. int layerOnEdge[2]; // The two edges of the current top tetrahedron // corresponding to adjEdge. int newTopEdge; // New boundary edge of degree 1 in the torus. NPerm4 adjPerm[2]; int layerOnGroup; while (true) { // Is there a new layer? tet = ans->topLevel->adjacentTetrahedron(ans->topFace[0]); if (tet == 0 || tet == ans->topLevel || tet != ans->topLevel->adjacentTetrahedron(ans->topFace[1])) break; // There is a new tetrahedron glued to both torus boundary triangles. adjPerm[0] = ans->topLevel->adjacentGluing( ans->topFace[0]); adjPerm[1] = ans->topLevel->adjacentGluing( ans->topFace[1]); if (adjPerm[0].sign() != adjPerm[1].sign()) break; // See what the new boundary edge would be. adjFace[0] = ans->topLevel->adjacentFace(ans->topFace[0]); adjFace[1] = ans->topLevel->adjacentFace(ans->topFace[1]); newTopEdge = NEdge::edgeNumber[adjFace[0]][adjFace[1]]; adjEdge = 5 - newTopEdge; // See which edges of the current top tetrahedron are being // layered upon. layerOnEdge[0] = NEdge::edgeNumber [adjPerm[0].preImageOf(NEdge::edgeVertex[adjEdge][0])] [adjPerm[0].preImageOf(NEdge::edgeVertex[adjEdge][1])]; layerOnEdge[1] = NEdge::edgeNumber [adjPerm[1].preImageOf(NEdge::edgeVertex[adjEdge][0])] [adjPerm[1].preImageOf(NEdge::edgeVertex[adjEdge][1])]; if (layerOnEdge[0] != layerOnEdge[1] && layerOnEdge[0] + layerOnEdge[1] != 5) break; // We have a new layer! // Before changing anything else, rearrange the topEdge and // meridinalCuts arrays. layerOnGroup = ans->topEdgeGroup[layerOnEdge[0]]; switch(layerOnGroup) { case 0: // p q r -> q r q+r ans->meridinalCuts[0] = ans->meridinalCuts[1]; ans->meridinalCuts[1] = ans->meridinalCuts[2]; ans->meridinalCuts[2] = ans->meridinalCuts[0] + ans->meridinalCuts[1]; ans->followEdge(0, 1); ans->followEdge(1, 2); ans->topEdge[2][0] = newTopEdge; ans->topEdge[2][1] = -1; break; case 1: // p q r -> p r p+r ans->meridinalCuts[1] = ans->meridinalCuts[2]; ans->meridinalCuts[2] = ans->meridinalCuts[0] + ans->meridinalCuts[1]; ans->followEdge(0, 0); ans->followEdge(1, 2); ans->topEdge[2][0] = newTopEdge; ans->topEdge[2][1] = -1; break; case 2: if (ans->meridinalCuts[1] - ans->meridinalCuts[0] < ans->meridinalCuts[0]) { // p q r -> q-p p q ans->meridinalCuts[2] = ans->meridinalCuts[1]; ans->meridinalCuts[1] = ans->meridinalCuts[0]; ans->meridinalCuts[0] = ans->meridinalCuts[2] - ans->meridinalCuts[1]; ans->followEdge(2, 1); ans->followEdge(1, 0); ans->topEdge[0][0] = newTopEdge; ans->topEdge[0][1] = -1; } else { // p q r -> p q-p q ans->meridinalCuts[2] = ans->meridinalCuts[1]; ans->meridinalCuts[1] = ans->meridinalCuts[2] - ans->meridinalCuts[0]; ans->followEdge(2, 1); ans->followEdge(0, 0); ans->topEdge[1][0] = newTopEdge; ans->topEdge[1][1] = -1; } break; } ans->topFace[0] = NEdge::edgeVertex[adjEdge][0]; ans->topFace[1] = NEdge::edgeVertex[adjEdge][1]; // Massage the indices in topEdge to match topFace. for (i = 0; i < 3; i++) { // Make sure ans->topEdge[i][0] is in face ans->topFace[0]. if (ans->topFace[0] == NEdge::edgeVertex[ans->topEdge[i][0]][0] || ans->topFace[0] == NEdge::edgeVertex[ans->topEdge[i][0]][1]) { j = ans->topEdge[i][0]; ans->topEdge[i][0] = ans->topEdge[i][1]; ans->topEdge[i][1] = j; } } ans->topLevel = tet; for (i = 0; i < 3; i++) for (j = 0; j < 2; j++) if (ans->topEdge[i][j] != -1) ans->topEdgeGroup[ans->topEdge[i][j]] = i; ans->topEdgeGroup[adjEdge] = -1; ans->nTetrahedra++; } return ans; } NLayeredSolidTorus* NLayeredSolidTorus::formsLayeredSolidTorusTop( NTetrahedron* tet, unsigned topFace1, unsigned topFace2) { NTetrahedron* top = tet; NTetrahedron* next; NPerm4 cross1, cross2; NPerm4 canon1, canon2; NFacePair pair = NFacePair(topFace1, topFace2).complement(); NPerm4 vRoles(pair.upper(), topFace1, topFace2, pair.lower()); NPerm4 topRoles(vRoles); NPerm4 nextRoles; long w = 1, x = 0, y = 0, z = 1; long w_, x_, y_, z_; int rotation; unsigned long nTets = 1; NPerm4 rot180(3, 2, 1, 0); while (true) { // INVARIANT: // // We are currently looking at tetrahedron tet. // The faces of tet closest to the top of the layered solid // torus are vRoles[1] and vRoles[2]. The faces we have not yet // looked at are vRoles[0] and vRoles[3]. // // Denote directed edges a = vRoles[01], b = vRoles[02], and // similarly let p = topRoles[01], q = topRoles[02] (where topRoles // was the original permutation vRoles for the original top-level // tetrahedron top). Then these edges are related as follows: // // p == w.a + x.b // q == y.a + z.b // // The count nTets reflects the number of tetrahedra seen so // far, including this one. // Verify that both new faces go to the same tetrahedron (which // exists). next = tet->adjacentTetrahedron(vRoles[0]); if (! next) return 0; if (next != tet->adjacentTetrahedron(vRoles[3])) return 0; // Are we folding over? cross1 = tet->adjacentGluing(vRoles[0]); cross2 = tet->adjacentGluing(vRoles[3]); if (next == tet && cross1[vRoles[0]] == vRoles[3]) { // Could be. Certainly faces vRoles[0,3] are joined to // each other. This is our final iteration -- either it // works or it doesn't. // Find the permutation that maps canonical vertices 123 to 012. canon1 = vRoles.inverse() * cross1 * vRoles; // Run through the three orientation-preserving permutations. // Note that canon1[0] == 3. if (canon1 == NPerm4(3, 1, 2, 0)) { // Tetrahedron is folded shut over edge vRoles[12]. // This does not give an LST(3,2,1) base, so we are not // interested. return 0; } else if (canon1 == NPerm4(3, 0, 1, 2)) { rotation = 1; // a, b have weights 1, 2. } else if (canon1 == NPerm4(3, 2, 0, 1)) { rotation = 2; // a, b have weights 2, 1. } else { // We have an orientation-reversing permutation. return 0; } // We got one! NLayeredSolidTorus* ans = new NLayeredSolidTorus(); ans->nTetrahedra = nTets; ans->base = tet; ans->baseFace[0] = vRoles[3]; // Face vRoles[012] ans->baseFace[1] = vRoles[0]; // Face vRoles[123] ans->baseEdge[0] = NEdge::edgeNumber[vRoles[0]][vRoles[3]]; if (rotation == 1) { ans->baseEdge[1] = NEdge::edgeNumber[vRoles[0]][vRoles[2]]; ans->baseEdge[2] = NEdge::edgeNumber[vRoles[1]][vRoles[3]]; ans->baseEdge[3] = NEdge::edgeNumber[vRoles[0]][vRoles[1]]; ans->baseEdge[4] = NEdge::edgeNumber[vRoles[1]][vRoles[2]]; ans->baseEdge[5] = NEdge::edgeNumber[vRoles[2]][vRoles[3]]; } else { ans->baseEdge[1] = NEdge::edgeNumber[vRoles[0]][vRoles[1]]; ans->baseEdge[2] = NEdge::edgeNumber[vRoles[2]][vRoles[3]]; ans->baseEdge[3] = NEdge::edgeNumber[vRoles[0]][vRoles[2]]; ans->baseEdge[4] = NEdge::edgeNumber[vRoles[2]][vRoles[1]]; ans->baseEdge[5] = NEdge::edgeNumber[vRoles[1]][vRoles[3]]; } ans->baseEdgeGroup[ans->baseEdge[0]] = 1; ans->baseEdgeGroup[ans->baseEdge[1]] = 2; ans->baseEdgeGroup[ans->baseEdge[2]] = 2; ans->baseEdgeGroup[ans->baseEdge[3]] = 3; ans->baseEdgeGroup[ans->baseEdge[4]] = 3; ans->baseEdgeGroup[ans->baseEdge[5]] = 3; long cuts01, cuts13, cuts30; if (rotation == 1) { // (a,b) == (1,2). cuts01 = w + 2 * x; // w.a + x.b cuts13 = y + 2 * z; // y.a + z.b } else { // (a,b) == (2,1). cuts01 = 2 * w + x; // w.a + x.b cuts13 = 2 * y + z; // y.a + z.b } cuts30 = - cuts01 - cuts13; if (cuts01 < 0) cuts01 = -cuts01; if (cuts13 < 0) cuts13 = -cuts13; if (cuts30 < 0) cuts30 = -cuts30; ans->topLevel = top; ans->topFace[0] = topRoles[2]; // Face topRoles[013] ans->topFace[1] = topRoles[1]; // Face topRoles[023] // Run through all six possible orderings. int group01, group13, group30; if (cuts01 <= cuts13) { // 01 13 if (cuts13 <= cuts30) { // 01 13 30 group01 = 0; group13 = 1; group30 = 2; } else if (cuts30 <= cuts01) { // 30 01 13 group30 = 0; group01 = 1; group13 = 2; } else { // 01 30 13 group01 = 0; group30 = 1; group13 = 2; } } else { // 13 01 if (cuts30 <= cuts13) { // 30 13 01 group30 = 0; group13 = 1; group01 = 2; } else if (cuts01 <= cuts30) { // 13 01 30 group13 = 0; group01 = 1; group30 = 2; } else { // 13 30 01 group13 = 0; group30 = 1; group01 = 2; } } ans->meridinalCuts[group01] = cuts01; ans->meridinalCuts[group13] = cuts13; ans->meridinalCuts[group30] = cuts30; ans->topEdge[group01][0] = NEdge::edgeNumber[topRoles[0]][topRoles[1]]; ans->topEdge[group01][1] = NEdge::edgeNumber[topRoles[2]][topRoles[3]]; ans->topEdge[group13][0] = NEdge::edgeNumber[topRoles[1]][topRoles[3]]; ans->topEdge[group13][1] = NEdge::edgeNumber[topRoles[0]][topRoles[2]]; ans->topEdge[group30][0] = NEdge::edgeNumber[topRoles[3]][topRoles[0]]; ans->topEdge[group30][1] = -1; ans->topEdgeGroup[NEdge::edgeNumber[topRoles[0]][topRoles[1]]] = group01; ans->topEdgeGroup[NEdge::edgeNumber[topRoles[2]][topRoles[3]]] = group01; ans->topEdgeGroup[NEdge::edgeNumber[topRoles[1]][topRoles[3]]] = group13; ans->topEdgeGroup[NEdge::edgeNumber[topRoles[0]][topRoles[2]]] = group13; ans->topEdgeGroup[NEdge::edgeNumber[topRoles[3]][topRoles[0]]] = group30; ans->topEdgeGroup[NEdge::edgeNumber[topRoles[1]][topRoles[2]]] = -1; // All done! return ans; } // We're looking for an entirely new tetrahedron. // Make sure we're not looping back in a cycle or anything kinky. if (next == tet || next == top) return 0; // Set up nextRoles so that faces tet/vRoles[0,3] are joined to // faces next/nextRoles[1,2] respectively. pair = NFacePair(cross1[vRoles[0]], cross2[vRoles[3]]).complement(); nextRoles = NPerm4(pair.upper(), cross1[vRoles[0]], cross2[vRoles[3]], pair.lower()); // Find the mapping between the canonical 0123 as described by // vRoles and the canonical 0123 as described by nextRoles. // There are two such mappings, for the gluings on faces // vRoles[0,3] respectively. canon1 = nextRoles.inverse() * cross1 * vRoles; canon2 = nextRoles.inverse() * cross2 * vRoles; // Make sure it's actually a layering, i.e., canon1 and canon2 are // compatible. if (rot180 * canon1 * rot180 != canon2) return 0; // Update the matrix [ a,b | c,d ]. // It seems sanest to take cases based on the six possible // permutations. Use canon2, which starts at face 3 (012). // Note that canon2[3] == 2. // Old a, b : 01, 02. // New a, b : 01, 13. if (canon2 == NPerm4(0, 1, 3, 2)) { // 012 -> 013. // old a = a // old b = a+b // p = w.(old_a) + x.(old_b) = (w+x).a + x.b // q = y.(old_a) + z.(old_b) = (y+z).a + z.b w_ = w + x; x_ = x; y_ = y + z; z_ = z; } else if (canon2 == NPerm4(0, 3, 1, 2)) { // 012 -> 031. // old a = a+b // old b = a // p = w.(old_a) + x.(old_b) = (w+x).a + w.b // q = y.(old_a) + z.(old_b) = (y+z).a + y.b w_ = w + x; x_ = w; y_ = y + z; z_ = y; } else if (canon2 == NPerm4(1, 0, 3, 2)) { // 012 -> 103. // old a = -a // old b = b // p = w.(old_a) + x.(old_b) = -w.a + x.b // q = y.(old_a) + z.(old_b) = -y.a + z.b w_ = -w; x_ = x; y_ = -y; z_ = z; } else if (canon2 == NPerm4(1, 3, 0, 2)) { // 012 -> 130. // old a = b // old b = -a // p = w.(old_a) + x.(old_b) = -x.a + w.b // q = y.(old_a) + z.(old_b) = -z.a + y.b w_ = -x; x_ = w; y_ = -z; z_ = y; } else if (canon2 == NPerm4(3, 0, 1, 2)) { // 012 -> 301. // old a = -(a+b) // old b = -b // p = w.(old_a) + x.(old_b) = -w.a - (w+x).b // q = y.(old_a) + z.(old_b) = -y.a - (y+z).b w_ = -w; x_ = -w - x; y_ = -y; z_ = -y - z; } else if (canon2 == NPerm4(3, 1, 0, 2)) { // 012 -> 310. // old a = -b // old b = -(a+b) // p = w.(old_a) + x.(old_b) = -x.a - (w+x).b // q = y.(old_a) + z.(old_b) = -z.a - (y+z).b w_ = -x; x_ = -w - x; y_ = -z; z_ = -y - z; } else { // Impossible. We should never get to this point. std::cerr << "ERROR: Bad permutation canon2." << std::endl; return 0; } w = w_; x = x_; y = y_; z = z_; // Adjust the other variables in preparation for the next loop // iteration. tet = next; vRoles = nextRoles; nTets++; } // The loop has no break so we should never get here, but what the hell. return 0; } NLayeredSolidTorus* NLayeredSolidTorus::isLayeredSolidTorus(NComponent* comp) { // Start with some basic property checks. if (! comp->isOrientable()) return 0; if (comp->getNumberOfBoundaryComponents() != 1) return 0; if (comp->getBoundaryComponent(0)->getNumberOfTriangles() != 2) return 0; NTriangleEmbedding f0 = comp->getBoundaryComponent(0)->getTriangle(0)-> getEmbedding(0); NTriangleEmbedding f1 = comp->getBoundaryComponent(0)->getTriangle(1)-> getEmbedding(0); NTetrahedron* top = f0.getTetrahedron(); if (f1.getTetrahedron() != top) return 0; // We have precisely one boundary component, which consists of two // triangular faces belonging to the same tetrahedron. // Follow the adjacent tetrahedra down to what should be the base // tetrahedron. Don't worry about gluing permutations for now. // Run a full search. // We use formsLayeredSolidTorusBase(), which works out the full structure // for us. It would be faster to just follow straight down from // the top level tetrahedron (which we already know), but this would // also require us to code up the entire structure again. NFacePair underFaces = NFacePair(f0.getTriangle(), f1.getTriangle()).complement(); NTetrahedron* currTet = top; NTetrahedron* nextTet; while (1) { // INV: Thus far we have seen a chain of tetrahedra, with each // tetrahedron glued to the next along two faces. // See where the next two faces lead. // Note that they cannot lead back to a previous tetrahedron, // since each previous tetrahedron already has all four faces // accounted for (thus showing this loop will terminate). // They also cannot be boundary faces, since there are only two // boundary faces and these have already been seen. nextTet = currTet->adjacentTetrahedron(underFaces.lower()); if (nextTet != currTet->adjacentTetrahedron(underFaces.upper())) return 0; // They both lead to the same adjacent tetrahedron. // Have we reached the end? if (nextTet == currTet) break; // No; we have simply moved on to the next tetrahedron. underFaces = NFacePair(currTet->adjacentFace(underFaces.lower()), currTet->adjacentFace(underFaces.upper())).complement(); currTet = nextTet; } // Here we are at the bottom. Now check the individual permutations // and fill in the structural details. return formsLayeredSolidTorusBase(currTet); } void NLayeredSolidTorus::followEdge(int destGroup, int sourceGroup) { int pos; NPerm4 adjPerm; for (int i = 1; i >= 0; i--) { pos = (topEdge[sourceGroup][i] == -1 ? 0 : i); adjPerm = topLevel->adjacentGluing(topFace[i]); topEdge[destGroup][i] = NEdge::edgeNumber [adjPerm[NEdge::edgeVertex[topEdge[sourceGroup][pos]][0]]] [adjPerm[NEdge::edgeVertex[topEdge[sourceGroup][pos]][1]]]; } } NManifold* NLayeredSolidTorus::getManifold() const { return new NHandlebody(1, true); } NAbelianGroup* NLayeredSolidTorus::getHomologyH1() const { NAbelianGroup* ans = new NAbelianGroup(); ans->addRank(); return ans; } NTriangulation* NLayeredSolidTorus::flatten(const NTriangulation* original, int mobiusBandBdry) const { // Create a new triangulation and identify the top-level and // base tetrahedra. NTriangulation* ans = new NTriangulation(*original); NTetrahedron* newTop = ans->getTetrahedron( original->tetrahedronIndex(topLevel)); NTetrahedron* newBase = ans->getTetrahedron( original->tetrahedronIndex(base)); NPacket::ChangeEventSpan span(ans); // Reglue the top faces before deleting the layered solid torus. NTetrahedron* adj0 = newTop->adjacentTetrahedron(topFace[0]); NTetrahedron* adj1 = newTop->adjacentTetrahedron(topFace[1]); if (adj0 && adj1 && (adj0 != newTop)) { // A permutation for each adjacent tetrahedron. // These permutations map: // 1,2 -> vertices corresponding to top edge group 0 // 0,2 -> vertices corresponding to top edge group 1 // 0,1 -> vertices corresponding to top edge group 2 // Start by representing vertices of this tetrahedron instead. NPerm4 groups0 = NPerm4( 6 - NEdge::edgeVertex[topEdge[0][0]][0] - NEdge::edgeVertex[topEdge[0][0]][1] - topFace[0], 6 - NEdge::edgeVertex[topEdge[1][0]][0] - NEdge::edgeVertex[topEdge[1][0]][1] - topFace[0], 6 - NEdge::edgeVertex[topEdge[2][0]][0] - NEdge::edgeVertex[topEdge[2][0]][1] - topFace[0], topFace[0]); NFacePair underFaces = NFacePair(topFace[0], topFace[1]).complement(); NPerm4 groups1 = NPerm4(topFace[0], topFace[1]) * NPerm4(underFaces.lower(), underFaces.upper()) * groups0; // Move these to vertices of the adjacent tetrahedra. groups0 = newTop->adjacentGluing(topFace[0]) * groups0; groups1 = newTop->adjacentGluing(topFace[1]) * groups1; // And do the regluing. adj0->unjoin(groups0[3]); adj1->unjoin(groups1[3]); adj0->joinTo(groups0[3], adj1, groups1 * NPerm4((mobiusBandBdry + 1) % 3, (mobiusBandBdry + 2) % 3) * groups0.inverse()); } // Delete the layered solid torus tetrahedra. NTetrahedron* curr; NTetrahedron* next; NFacePair currBdryFaces; NPerm4 adjPerm; curr = newBase; currBdryFaces = NFacePair(baseFace[0], baseFace[1]).complement(); while (curr) { next = curr->adjacentTetrahedron(currBdryFaces.lower()); currBdryFaces = NFacePair(curr->adjacentFace(currBdryFaces.lower()), curr->adjacentFace(currBdryFaces.upper())).complement(); ans->removeTetrahedron(curr); curr = next; } // And we're done. return ans; } } // namespace regina regina-4.96/engine/subcomplex/nlayeredsolidtorus.h000644 000765 000024 00000050565 12377775455 022403 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/nlayeredsolidtorus.h * \brief Deals with layered solid tori in a triangulation. */ #ifndef __NLAYEREDSOLIDTORUS_H #ifndef __DOXYGEN #define __NLAYEREDSOLIDTORUS_H #endif #include "regina-core.h" #include "subcomplex/nstandardtri.h" namespace regina { class NIsomorphism; class NTetrahedron; class NTriangulation; /** * \weakgroup subcomplex * @{ */ /** * Represents a layered solid torus in a triangulation. * A layered solid torus must contain at least one tetrahedron. * * Note that this class \b only represents layered solid tori with a * (3,2,1) at their base. Thus triangulations that begin with a * degenerate (2,1,1) mobius strip and layer over the mobius strip * boundary (including the minimal (1,1,0) triangulation) are not * described by this class. * * All optional NStandardTriangulation routines are implemented for this * class. */ class REGINA_API NLayeredSolidTorus : public NStandardTriangulation { private: unsigned long nTetrahedra; /**< The number of tetrahedra in this torus. */ NTetrahedron* base; /**< The tetrahedron that is glued to itself at the base of this torus. */ int baseEdge[6]; /**< The edges of the base tetrahedron that are identified as a group of 1, 2 or 3 according to whether the index is 0, 1-2 or 3-5 respectively. See getBaseEdge() for further details. */ int baseEdgeGroup[6]; /**< Classifies the edges of the base tetrahedron according to whether they are identified in a group of 1, 2 or 3. */ int baseFace[2]; /**< The two faces of the base tetrahedron that are glued to each other. */ NTetrahedron* topLevel; /**< The tetrahedron on the boundary of this torus. */ int topEdge[3][2]; /**< Returns the edges of the top tetrahedron that the meridinal disc cuts fewest, middle or most times according to whether the first index is 0, 1 or 2 respectively. See getTopEdge() for further details. */ unsigned long meridinalCuts[3]; /**< Returns the number of times the meridinal disc cuts each boundary edge; this array is in non-decreasing order. */ int topEdgeGroup[6]; /**< Classifies the edges of the boundary tetrahedron according to whether the meridinal disc cuts them fewest, middle or most times. */ int topFace[2]; /**< The two faces of the boundary tetrahedron that form the torus boundary. */ public: /** * Returns a newly created clone of this structure. * * @return a newly created clone. */ NLayeredSolidTorus* clone() const; /** * Returns the number of tetrahedra in this layered solid torus. * * @return the number of tetrahedra. */ unsigned long getNumberOfTetrahedra() const; /** * Returns the tetrahedron that is glued to itself at the base of * this layered solid torus. * * @return the base tetrahedron. */ NTetrahedron* getBase() const; /** * Returns the requested edge of the base tetrahedron belonging * to the given group. The layering identifies the six edges * of the base tetrahedron into a group of three, a group of two * and a single unidentified edge; these are referred to as * groups 3, 2 and 1 respectively. * * Note that getBaseEdgeGroup(getBaseEdge(group, index)) == * group for all values of \c group and \c index. * * Edges getBaseEdge(2,0) and getBaseEdge(3,0) * will both belong to face getBaseFace(0). * Edges getBaseEdge(2,1) and getBaseEdge(3,2) * will both belong to face getBaseFace(1). * * @param group the group that the requested edge should belong * to; this must be 1, 2 or 3. * @param index the index within the given group of the requested * edge; this must be between 0 and group-1 inclusive. * Note that in group 3 the edge at index 1 is adjacent to both the * edges at indexes 0 and 2. * @return the edge number in the base tetrahedron of the * requested edge; this will be between 0 and 5 inclusive. */ int getBaseEdge(int group, int index) const; /** * Returns the group that the given edge of the base tetrahedron * belongs to. See getBaseEdge() for further details about * groups. * * Note that getBaseEdgeGroup(getBaseEdge(group, index)) == * group for all values of \c group and \c index. * * @param edge the edge number in the base tetrahedron of the * given edge; this must be between 0 and 5 inclusive. * @return the group to which the given edge belongs; this will * be 1, 2 or 3. */ int getBaseEdgeGroup(int edge) const; /** * Returns one of the two faces of the base tetrahedron that are * glued to each other. * * @param index specifies which of the two faces to return; this * must be 0 or 1. * @return the requested face number in the base tetrahedron; * this will be between 0 and 3 inclusive. */ int getBaseFace(int index) const; /** * Returns the top level tetrahedron in this layered solid torus. * This is the tetrahedron that would be on the boundary of the * torus if the torus were the entire manifold. * * @return the top level tetrahedron. */ NTetrahedron* getTopLevel() const; /** * Returns the number of times the meridinal disc of the torus * cuts the top level tetrahedron edges in the given group. * See getTopEdge() for further details about groups. * * @param group the given edge group; this must be 0, 1 or 2. * @return the number of times the meridinal disc cuts the edges * in the given group. */ unsigned long getMeridinalCuts(int group) const; /** * Returns the requested edge of the top level tetrahedron belonging * to the given group. The layering reduces five of the top * level tetrahedron edges to three boundary edges of the solid * torus; this divides the five initial edges into groups of size * two, two and one. * * Group 0 represents the boundary edge that the meridinal disc * cuts fewest times. Group 2 represents the boundary edge that * the meridinal disc cuts most times. Group 1 is in the middle. * * Note that getTopEdgeGroup(getTopEdge(group, index)) == * group for all values of \c group and \c index that * actually correspond to an edge. * * Edges getTopEdge(group, 0) will all belong to face * getTopFace(0). Edges getTopEdge(group, 1) * (if they exist) will all belong to face getTopFace(1). * * @param group the group that the requested edge should belong * to; this must be 0, 1 or 2. * @param index the index within the given group of the requested * edge; this must be 0 or 1. Note that one of the groups only * contains one tetrahedron edge, in which case this edge will be * stored at index 0. * @return the edge number in the top level tetrahedron of the * requested edge (between 0 and 5 inclusive), or -1 if there is * no such edge (only possible if the given group was the group * of size one and the given index was 1). */ int getTopEdge(int group, int index) const; /** * Returns the group that the given edge of the top level * tetrahedron belongs to. See getTopEdge() for further details * about groups. * * Note that getTopEdgeGroup(getTopEdge(group, index)) == * group for all values of \c group and \c index that * actually correspond to an edge. * * @param edge the edge number in the top level tetrahedron of * the given edge; this must be between 0 and 5 inclusive. * @return the group to which the given edge belongs (0, 1 or 2), * or -1 if this edge does not belong to any group (only possible * if this is the unique edge in the top tetrahedron not on the * torus boundary). */ int getTopEdgeGroup(int edge) const; /** * Returns one of the two faces of the top level tetrahedron that * form the boundary of this layered solid torus. * * @param index specifies which of the two faces to return; this * must be 0 or 1. * @return the requested face number in the top level tetrahedron; * this will be between 0 and 3 inclusive. */ int getTopFace(int index) const; /** * Flattens this layered solid torus to a Mobius band. * A newly created modified triangulation is returned; the * original triangulation is unchanged. * * Note that there are three different ways in which this layered * solid torus can be flattened, corresponding to the three * different edges of the boundary torus that could become the * boundary edge of the new Mobius band. * * @param original the triangulation containing this layered * solid torus; this triangulation will not be changed. * @param mobiusBandBdry the edge group on the boundary of this * layered solid torus that will become the boundary of the new * Mobius band (the remaining edge groups will become internal * edges of the new Mobius band). This must be 0, 1 or 2. * See getTopEdge() for further details about edge groups. * @return a newly created triangulation in which this layered * solid torus has been flattened to a Mobius band. */ NTriangulation* flatten(const NTriangulation* original, int mobiusBandBdry) const; /** * Adjusts the details of this layered solid torus according to * the given isomorphism between triangulations. * * The given isomorphism must describe a mapping from \a originalTri * to \a newTri, and this layered solid torus must currently * refer to tetrahedra in \a originalTri. After this routine is * called this structure will instead refer to the corresponding * tetrahedra in \a newTri (with changes in vertex/face * numbering also accounted for). * * \pre This layered solid torus currently refers to tetrahedra * in \a originalTri, and \a iso describes a mapping from * \a originalTri to \a newTri. * * @param originalTri the triangulation currently referenced by this * layered solid torus. * @param iso the mapping from \a originalTri to \a newTri. * @param newTri the triangulation to be referenced by the updated * layered solid torus. */ void transform(const NTriangulation* originalTri, const NIsomorphism* iso, NTriangulation* newTri); /** * Determines if the given tetrahedron forms the base of a * layered solid torus within a triangulation. The torus need * not be the entire triangulation; the top level tetrahedron of * the torus may be glued to something else (or to itself). * * Note that the base tetrahedron of a layered solid torus is the * tetrahedron furthest from the boundary of the torus, i.e. the * tetrahedron glued to itself with a twist. * * @param tet the tetrahedron to examine as a potential base. * @return a newly created structure containing details of the * layered solid torus, or \c null if the given tetrahedron is * not the base of a layered solid torus. */ static NLayeredSolidTorus* formsLayeredSolidTorusBase( NTetrahedron* tet); /** * Determines if the given tetrahedron forms the top level * tetrahedron of a layered solid torus, with the two given * faces of this tetrahedron representing the boundary of the * layered solid torus. * * Note that the two given faces need not be boundary triangles in the * overall triangulation. That is, the layered solid torus may be * a subcomplex of some larger triangulation. For example, the * two given faces may be joined to some other tetrahedra outside * the layered solid torus or they may be joined to each other. * In fact, they may even extend this smaller layered solid torus * to a larger layered solid torus. * * @param tet the tetrahedron to examine as a potential top * level of a layered solid torus. * @param topFace1 the face number of the given tetrahedron that * should represent the first boundary triangle of the layered solid * torus. This should be between 0 and 3 inclusive. * @param topFace2 the face number of the given tetrahedron that * should represent the second boundary triangle of the layered solid * torus. This should be between 0 and 3 inclusive, and should * not be equal to \a topFace1. * @return a newly created structure containing details of the * layered solid torus, or \c null if the given tetrahedron with * its two faces do not form the top level of a layered solid torus. */ static NLayeredSolidTorus* formsLayeredSolidTorusTop( NTetrahedron* tet, unsigned topFace1, unsigned topFace2); /** * Determines if the given triangulation component forms a * layered solid torus in its entirity. * * Note that, unlike formsLayeredSolidTorusBase(), this routine * tests for a component that is a layered solid torus with no * additional tetrahedra or gluings. That is, the two boundary * triangles of the layered solid torus must in fact be boundary * triangles of the component. * * @param comp the triangulation component to examine. * @return a newly created structure containing details of the * layered solid torus, or \c null if the given component is not * a layered solid torus. */ static NLayeredSolidTorus* isLayeredSolidTorus(NComponent* comp); NManifold* getManifold() const; NAbelianGroup* getHomologyH1() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; void writeTextLong(std::ostream& out) const; private: /** * Create a new uninitialised structure. */ NLayeredSolidTorus(); /** * Fills topEdge[destGroup] with the edges produced by * following the edges in group \c sourceGroup from the current * top level tetrahedron up to the next layered tetrahedron. * * Note that which edge is placed in topEdge[][0] and * which edge is placed in topEdge[][1] will be an * arbitrary decision; these may need to be switched later on. * * \pre There is a next layered tetrahedron. * \pre Member variables \a topLevel and \a topFace have not yet been * changed to reflect the next layered tetrahedron. * \pre The edges in group \a destGroup in the next layered * tetrahedron are actually layered onto the edges in group \a * sourceGroup in the current top level tetrahedron. * * @param sourceGroup the group in the current top level * tetrahedron to which the edges belong. * @param destGroup the group in the next layered tetrahedron to * which the same edges belong. */ void followEdge(int destGroup, int sourceGroup); }; /*@}*/ // Inline functions for NLayeredSolidTorus inline NLayeredSolidTorus::NLayeredSolidTorus() { } inline unsigned long NLayeredSolidTorus::getNumberOfTetrahedra() const { return nTetrahedra; } inline NTetrahedron* NLayeredSolidTorus::getBase() const { return base; } inline int NLayeredSolidTorus::getBaseEdge(int group, int index) const { return group == 1 ? baseEdge[index] : group == 2 ? baseEdge[1 + index] : baseEdge[3 + index]; } inline int NLayeredSolidTorus::getBaseEdgeGroup(int edge) const { return baseEdgeGroup[edge]; } inline int NLayeredSolidTorus::getBaseFace(int index) const { return baseFace[index]; } inline NTetrahedron* NLayeredSolidTorus::getTopLevel() const { return topLevel; } inline unsigned long NLayeredSolidTorus::getMeridinalCuts(int group) const { return meridinalCuts[group]; } inline int NLayeredSolidTorus::getTopEdge(int group, int index) const { return topEdge[group][index]; } inline int NLayeredSolidTorus::getTopEdgeGroup(int edge) const { return topEdgeGroup[edge]; } inline int NLayeredSolidTorus::getTopFace(int index) const { return topFace[index]; } inline std::ostream& NLayeredSolidTorus::writeName(std::ostream& out) const { return out << "LST(" << meridinalCuts[0] << ',' << meridinalCuts[1] << ',' << meridinalCuts[2] << ')'; } inline std::ostream& NLayeredSolidTorus::writeTeXName(std::ostream& out) const { return out << "\\mathop{\\rm LST}(" << meridinalCuts[0] << ',' << meridinalCuts[1] << ',' << meridinalCuts[2] << ')'; } inline void NLayeredSolidTorus::writeTextLong(std::ostream& out) const { out << "( " << meridinalCuts[0] << ", " << meridinalCuts[1] << ", " << meridinalCuts[2] << " ) layered solid torus"; } } // namespace regina #endif regina-4.96/engine/subcomplex/nlayeredsurfacebundle.cpp000644 000765 000024 00000017220 12377776671 023341 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "manifold/ntorusbundle.h" #include "subcomplex/nlayeredsurfacebundle.h" #include "subcomplex/nlayering.h" #include "subcomplex/ntxicore.h" #include "triangulation/nisomorphism.h" #include "triangulation/ntriangulation.h" namespace regina { namespace { const NTxIDiagonalCore core_T_6_1(6, 1); const NTxIDiagonalCore core_T_7_1(7, 1); const NTxIDiagonalCore core_T_8_1(8, 1); const NTxIDiagonalCore core_T_8_2(8, 2); const NTxIDiagonalCore core_T_9_1(9, 1); const NTxIDiagonalCore core_T_9_2(9, 2); const NTxIDiagonalCore core_T_10_1(10, 1); const NTxIDiagonalCore core_T_10_2(10, 2); const NTxIDiagonalCore core_T_10_3(10, 3); const NTxIDiagonalCore core_T_11_1(11, 1); const NTxIDiagonalCore core_T_11_2(11, 2); const NTxIDiagonalCore core_T_11_3(11, 3); const NTxIDiagonalCore core_T_12_1(12, 1); const NTxIDiagonalCore core_T_12_2(12, 2); const NTxIDiagonalCore core_T_12_3(12, 3); const NTxIDiagonalCore core_T_12_4(12, 4); const NTxIParallelCore core_T_p; } NLayeredTorusBundle::~NLayeredTorusBundle() { delete coreIso_; } NLayeredTorusBundle* NLayeredTorusBundle::isLayeredTorusBundle( NTriangulation* tri) { // Basic property checks. if (! tri->isClosed()) return 0; if (tri->getNumberOfVertices() > 1) return 0; if (tri->getNumberOfComponents() > 1) return 0; if (tri->getNumberOfTetrahedra() < 6) return 0; // We have a 1-vertex 1-component closed triangulation with at least // six tetrahedra. // Hunt for the core thin torus bundle. NLayeredTorusBundle* ans; if ((ans = hunt(tri, core_T_6_1))) return ans; if ((ans = hunt(tri, core_T_7_1))) return ans; if ((ans = hunt(tri, core_T_8_1))) return ans; if ((ans = hunt(tri, core_T_8_2))) return ans; if ((ans = hunt(tri, core_T_9_1))) return ans; if ((ans = hunt(tri, core_T_9_2))) return ans; if ((ans = hunt(tri, core_T_10_1))) return ans; if ((ans = hunt(tri, core_T_10_2))) return ans; if ((ans = hunt(tri, core_T_10_3))) return ans; if ((ans = hunt(tri, core_T_11_1))) return ans; if ((ans = hunt(tri, core_T_11_2))) return ans; if ((ans = hunt(tri, core_T_11_3))) return ans; if ((ans = hunt(tri, core_T_12_1))) return ans; if ((ans = hunt(tri, core_T_12_2))) return ans; if ((ans = hunt(tri, core_T_12_3))) return ans; if ((ans = hunt(tri, core_T_12_4))) return ans; if ((ans = hunt(tri, core_T_p))) return ans; return 0; } NLayeredTorusBundle* NLayeredTorusBundle::hunt(NTriangulation* tri, const NTxICore& core) { std::list isos; if (! core.core().findAllSubcomplexesIn(*tri, isos)) return 0; // Run through each isomorphism and look for the corresponding layering. NMatrix2 matchReln; for (std::list::const_iterator it = isos.begin(); it != isos.end(); it++) { // Apply the layering to the lower boundary and see if it // matches nicely with the upper. NLayering layering( tri->getTetrahedron((*it)->tetImage(core.bdryTet(1,0))), (*it)->facePerm(core.bdryTet(1,0)) * core.bdryRoles(1,0), tri->getTetrahedron((*it)->tetImage(core.bdryTet(1,1))), (*it)->facePerm(core.bdryTet(1,1)) * core.bdryRoles(1,1)); layering.extend(); if (layering.matchesTop( tri->getTetrahedron((*it)->tetImage(core.bdryTet(0,0))), (*it)->facePerm(core.bdryTet(0,0)) * core.bdryRoles(0,0), tri->getTetrahedron((*it)->tetImage(core.bdryTet(0,1))), (*it)->facePerm(core.bdryTet(0,1)) * core.bdryRoles(0,1), matchReln)) { // It's a match! NLayeredTorusBundle* ans = new NLayeredTorusBundle(core); ans->coreIso_ = *it; ans->reln_ = core.bdryReln(0) * matchReln * core.bdryReln(1).inverse(); // Delete the remaining isomorphisms that we never even // looked at. for (it++; it != isos.end(); it++) delete *it; return ans; } // No match. Delete this isomorphism; we won't need it any more. delete *it; continue; } // Nothing found. return 0; } NManifold* NLayeredTorusBundle::getManifold() const { // Note that this one-liner appears again in getHomologyH1(), where // we use the underlying NTorusBundle for homology calculations. return new NTorusBundle(core_.parallelReln() * reln_); } NAbelianGroup* NLayeredTorusBundle::getHomologyH1() const { // It's implemented in NTorusBundle, so ride on that for now. // We'll implement it directly here in good time. return NTorusBundle(core_.parallelReln() * reln_).getHomologyH1(); } std::ostream& NLayeredTorusBundle::writeCommonName(std::ostream& out, bool tex) const { if (tex) { out << "B_{"; core_.writeTeXName(out); } else { out << "B("; core_.writeName(out); } out << " | " << reln_[0][0] << ',' << reln_[0][1]; out << " | " << reln_[1][0] << ',' << reln_[1][1]; return out << (tex ? "}" : ")"); } void NLayeredTorusBundle::writeTextLong(std::ostream& out) const { out << "Layered torus bundle: "; writeName(out); } } // namespace regina regina-4.96/engine/subcomplex/nlayeredsurfacebundle.h000644 000765 000024 00000030634 12377775456 023012 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/nlayeredsurfacebundle.h * \brief Deals with layered surface bundle triangulations. */ #ifndef __NLAYEREDSURFACEBUNDLE_H #ifndef __DOXYGEN #define __NLAYEREDSURFACEBUNDLE_H #endif #include #include "regina-core.h" #include "maths/nmatrix2.h" #include "subcomplex/nstandardtri.h" #include "triangulation/ntriangulation.h" namespace regina { class NTxICore; /** * \weakgroup subcomplex * @{ */ /** * Describes a layered torus bundle. This is a triangulation of a * torus bundle over the circle formed as follows. * * We begin with a thin I-bundle over the torus, i.e,. a triangulation * of the product T x I that is only one tetrahedron thick. * This is referred to as the \a core, and is described by an object * of type NTxICore. * * We then identify the upper and lower torus boundaries of this core * according to some homeomorphism of the torus. This may be impossible * due to incompatible boundary edges, and so we allow a layering of * tetrahedra over one of the boundari tori in order to adjust the * boundary edges accordingly. Layerings are described in more detail * in the NLayering class. * * Given the parameters of the core T x I and the specific * layering, the monodromy for this torus bundle over the circle can be * calculated. The getManifold() routine returns details of the * corresponding 3-manifold. * * All optional NStandardTriangulation routines are implemented for this * class. */ class REGINA_API NLayeredTorusBundle : public NStandardTriangulation { private: const NTxICore& core_; /**< The core T x I triangulation whose boundaries are joined (possibly via a layering of tetrahedra). */ NIsomorphism* coreIso_; /**< Describes how the tetrahedra and vertices of the core T x I triangulation returned by NTxICore::core() map to the tetrahedra and vertices of the larger layered torus bundle under consideration. */ NMatrix2 reln_; /**< Describes how the layering of tetrahedra maps the lower boundary curves to the upper boundary curves. See layeringReln() for details. */ public: /** * Destroys this layered torus bundle and all of its internal * components. */ virtual ~NLayeredTorusBundle(); /** * Returns the T x I triangulation at the core of this * layered surface bundle. This is the product T x I * whose boundaries are joined (possibly via some layering of * tetrahedra). * * Note that the triangulation returned by NTxICore::core() * (that is, NLayeredSurfaceBundle::core().core()) may * well use different tetrahedron and vertex numbers. That is, * an isomorphic copy of it appears within this layered surface * bundle but the individual tetrahedra and vertices may have * been permuted. For a precise mapping from the NTxICore::core() * triangulation to this triangulation, see the routine coreIso(). * * @return the core T x I triangulation. */ const NTxICore& core() const; /** * Returns the isomorphism describing how the core T x I * appears as a subcomplex of this layered surface bundle. * * As described in the core() notes, the core T x I * triangulation returned by NTxICore::core() appears within this * layered surface bundle, but not necessarily with the same * tetrahedron or vertex numbers. * * This routine returns an isomorphism that maps the tetrahedra * and vertices of the core T x I triangulation (as * returned by NLayeredSurfaceBundle::core().core()) to the * tetrahedra and vertices of this overall layered surface bundle. * * The isomorphism that is returned belongs to this object, and * should not be modified or destroyed. * * @return the isomorphism from the core T x I to this * layered surface bundle. */ const NIsomorphism* coreIso() const; /** * Returns a 2-by-2 matrix describing how the layering of * tetrahedra relates curves on the two torus boundaries of the * core T x I. * * The NTxICore class documentation describes generating \a alpha * and \a beta curves on the two torus boundaries of the core * T x I (which are referred to as the \e upper and * \e lower boundaries). The two boundary tori are parallel in * two directions: through the core, and through the layering. * It is desirable to know the parallel relationship between * the two sets of boundary curves in each direction. * * The relationship through the core is already described by * NTxICore::parallelReln(). This routine describes the * relationship through the layering. * * Let \a a_u and \a b_u be the \a alpha and \a beta curves on * the upper boundary torus, and let \a a_l and \a b_l be the * \a alpha and \a beta curves on the lower boundary torus. * Suppose that the upper \a alpha is parallel to * \a w.\a a_l + \a x.\a b_l, and that the upper \a beta is * parallel to \a y.\a a_l + \a z.\a b_l. Then the matrix * returned will be * *
         *     [ w  x ]
         *     [      ] .
         *     [ y  z ]
         * 
* * In other words, * *
         *     [ a_u ]                      [ a_l ]
         *     [     ]  =  layeringReln() * [     ] .
         *     [ b_u ]                      [ b_l ]
         * 
* * It can be observed that this matrix expresses the upper * boundary curves in terms of the lower, whereas * NTxICore::parallelReln() expresses the lower boundary curves * in terms of the upper. This means that the monodromy * describing the overall torus bundle over the circle can be * calculated as *
         *     M  =  layeringReln() * core().parallelReln()
         * 
* or alternatively using the similar matrix *
         *     M'  =  core().parallelReln() * layeringReln() .
         * 
* * Note that in the degenerate case where there is no layering at * all, this matrix is still perfectly well defined; in this * case it describes a direct identification between the upper * and lower boundary tori. * * @return the relationship through the layering between the * upper and lower boundary curves of the core T x I. */ const NMatrix2& layeringReln() const; /** * Determines if the given triangulation is a layered surface bundle. * * @param tri the triangulation to examine. * @return a newly created structure containing details of the * layered surface bundle, or \c null if the given triangulation * is not a layered surface bundle. */ static NLayeredTorusBundle* isLayeredTorusBundle(NTriangulation* tri); NManifold* getManifold() const; NAbelianGroup* getHomologyH1() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; void writeTextLong(std::ostream& out) const; private: /** * Creates a new structure based upon the given core T x I * triangulation. Aside from this core, the structure will * remain uninitialised. * * Note that only a reference to the core T x I is stored. * This class does not manage the life span of the core; it is * assumed that the core will remain in existence for at least * as long as this object does. (Usually the core is a static or * global variable that is not destroyed until the program exits.) * * @param whichCore a reference to the core T x I * triangulation upon which this layered surface bundle is based. */ NLayeredTorusBundle(const NTxICore& whichCore); /** * Contains code common to both writeName() and writeTeXName(). * * @param out the output stream to which to write. * @param tex \c true if this routine is called from * writeTeXName() or \c false if it is called from writeName(). * @return a reference to \a out. */ std::ostream& writeCommonName(std::ostream& out, bool tex) const; /** * Internal to isLayeredTorusBundle(). Determines if the given * triangulation is a layered surface bundle with the given core * T x I triangulation (up to isomorphism). * * @param tri the triangulation to examine. * @param core the core T x I to search for. * @return a newly created structure containing details of the * layered surface bundle, or \c null if the given triangulation is * not a layered surface bundle with the given T x I core. */ static NLayeredTorusBundle* hunt(NTriangulation* tri, const NTxICore& core); }; /*@}*/ // Inline functions for NLayeredTorusBundle inline NLayeredTorusBundle::NLayeredTorusBundle(const NTxICore& whichCore) : core_(whichCore), coreIso_(0) { } inline const NTxICore& NLayeredTorusBundle::core() const { return core_; } inline const NIsomorphism* NLayeredTorusBundle::coreIso() const { return coreIso_; } inline const NMatrix2& NLayeredTorusBundle::layeringReln() const { return reln_; } inline std::ostream& NLayeredTorusBundle::writeName(std::ostream& out) const { return writeCommonName(out, false); } inline std::ostream& NLayeredTorusBundle::writeTeXName(std::ostream& out) const { return writeCommonName(out, true); } } // namespace regina #endif regina-4.96/engine/subcomplex/nlayering.cpp000644 000765 000024 00000020112 12377776671 020755 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "triangulation/ntetrahedron.h" #include "subcomplex/nlayering.h" namespace regina { NLayering::NLayering(NTetrahedron* bdry0, NPerm4 roles0, NTetrahedron* bdry1, NPerm4 roles1) : size(0), reln(1, 0, 0, 1) { oldBdryTet[0] = newBdryTet[0] = bdry0; oldBdryTet[1] = newBdryTet[1] = bdry1; oldBdryRoles[0] = newBdryRoles[0] = roles0; oldBdryRoles[1] = newBdryRoles[1] = roles1; } bool NLayering::extendOne() { // See if we move to a common new tetrahedron. // Also make sure this really is a new tetrahedron, so we don't get // stuck in a loop. NTetrahedron* next = newBdryTet[0]->adjacentTetrahedron( newBdryRoles[0][3]); if (next == 0 || next == newBdryTet[0] || next == newBdryTet[1] || next == oldBdryTet[0] || next == oldBdryTet[1]) return false; if (next != newBdryTet[1]->adjacentTetrahedron(newBdryRoles[1][3])) return false; // Get the mappings from the boundary vertex roles to the new tetrahedron // vertices. NPerm4 cross0 = newBdryTet[0]->adjacentGluing( newBdryRoles[0][3]) * newBdryRoles[0]; NPerm4 cross1 = newBdryTet[1]->adjacentGluing( newBdryRoles[1][3]) * newBdryRoles[1]; // Is it actually a layering? if (cross1 == cross0 * NPerm4(3, 2, 1, 0)) { // We're layering over the edge joining vertex roles 1 and 2. size++; newBdryRoles[0] = cross0 * NPerm4(0, 1, 3, 2); newBdryRoles[1] = cross0 * NPerm4(3, 2, 0, 1); newBdryTet[0] = newBdryTet[1] = next; // new a = old a = reln00 p + reln01 q // new b = old a + old b = (reln00 + reln10) p + (reln01 + reln11) q reln[1][0] += reln[0][0]; reln[1][1] += reln[0][1]; return true; } else if (cross1 == cross0 * NPerm4(2, 3, 0, 1)) { // We're layering over the edge joining vertex roles 0 and 2. size++; newBdryRoles[0] = cross0 * NPerm4(0, 1, 3, 2); newBdryRoles[1] = cross0 * NPerm4(2, 3, 1, 0); newBdryTet[0] = newBdryTet[1] = next; // new a = old a = reln00 p + reln01 q // new b = old b - old a = (reln10 - reln00) p + (reln11 - reln01) q reln[1][0] -= reln[0][0]; reln[1][1] -= reln[0][1]; return true; } else if (cross1 == cross0 * NPerm4(1, 0, 3, 2)) { // We're layering over the edge joining vertex roles 0 and 1. size++; newBdryRoles[0] = cross0 * NPerm4(0, 3, 2, 1); newBdryRoles[1] = cross0 * NPerm4(1, 2, 3, 0); newBdryTet[0] = newBdryTet[1] = next; // new a = old a - old b = (reln00 - reln10) p + (reln01 - reln11) q // new b = old b = reln10 p + reln11 q reln[0][0] -= reln[1][0]; reln[0][1] -= reln[1][1]; return true; } // It's not a layering at all. return false; } unsigned long NLayering::extend() { unsigned long added = 0; while (extendOne()) added++; return added; } bool NLayering::matchesTop(NTetrahedron* upperBdry0, NPerm4 upperRoles0, NTetrahedron* upperBdry1, NPerm4 upperRoles1, NMatrix2& upperReln) const { // We can cut half our cases by assuming that upperBdry0 meets with // newBdryTet[0] and that upperBdry1 meets with newBdryTet[1]. bool rot180; if (upperBdry0->adjacentTetrahedron(upperRoles0[3]) == newBdryTet[1] && upperBdry0->adjacentFace(upperRoles0[3]) == newBdryRoles[1][3]) { // If it does match, it's the opposite matching (upperBdry0 with // newBdryTet[1] and vice versa). Switch them and remember what // we did. NTetrahedron* tmpTet = upperBdry0; upperBdry0 = upperBdry1; upperBdry1 = tmpTet; NPerm4 tmpPerm = upperRoles0; upperRoles0 = upperRoles1; upperRoles1 = tmpPerm; rot180 = true; } else { // If it does match, it's what we'd like. rot180 = false; } // Do we meet the right tetrahedra and faces? if (upperBdry0->adjacentTetrahedron(upperRoles0[3]) != newBdryTet[0]) return false; if (upperBdry0->adjacentFace(upperRoles0[3]) != newBdryRoles[0][3]) return false; if (upperBdry1->adjacentTetrahedron(upperRoles1[3]) != newBdryTet[1]) return false; if (upperBdry1->adjacentFace(upperRoles1[3]) != newBdryRoles[1][3]) return false; // Find the mapping from the upper vertex roles to the boundary // vertex roles. Verify that this mapping is consistent for both faces. NPerm4 cross = newBdryRoles[0].inverse() * upperBdry0-> adjacentGluing(upperRoles0[3]) * upperRoles0; if (cross != newBdryRoles[1].inverse() * upperBdry1-> adjacentGluing(upperRoles1[3]) * upperRoles1) return false; // It's a match! Run through the six possible mappings to get the // relationship matrix correct. if (cross == NPerm4(0, 1, 2, 3)) { // It's the identity. upperReln = reln; } else if (cross == NPerm4(0, 2, 1, 3)) { // new a = + old b // new b = + old a upperReln = NMatrix2(0, 1, 1, 0) * reln; } else if (cross == NPerm4(1, 0, 2, 3)) { // new a = - old a // new b = - old a + old b upperReln = NMatrix2(-1, 0, -1, 1) * reln; } else if (cross == NPerm4(1, 2, 0, 3)) { // new a = - old a + old b // new b = - old a upperReln = NMatrix2(-1, 1, -1, 0) * reln; } else if (cross == NPerm4(2, 0, 1, 3)) { // new a = - old b // new b = + old a - old b upperReln = NMatrix2(0, -1, 1, -1) * reln; } else if (cross == NPerm4(2, 1, 0, 3)) { // new a = + old a - old b // new b = - old b upperReln = NMatrix2(1, -1, 0, -1) * reln; } // Don't forget to account for the 180 degree rotation if it // happened. if (rot180) upperReln.negate(); return true; } } // namespace regina regina-4.96/engine/subcomplex/nlayering.h000644 000765 000024 00000046526 12377775460 020436 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/nlayering.h * \brief Assists with the analysis of layerings upon a torus boundary. */ #ifndef __NLAYERING_H #ifndef __DOXYGEN #define __NLAYERING_H #endif #include "regina-core.h" #include "maths/nmatrix2.h" #include "maths/nperm4.h" #include "utilities/boostutils.h" namespace regina { class NTetrahedron; /** * \weakgroup subcomplex * @{ */ /** * Represents a layering of zero or more tetrahedra upon a torus * boundary. * * A \e layering involves laying a new tetrahedron flat upon two * adjacent boundary triangles in order to change the boundary curves. Many * tetrahedra may be layered upon a boundary in succession in order to * change the boundary curves more dramatically. * * A torus boundary is specified by two tetrahedra (which may be the same) * and two permutations. Each permutation maps (0,1,2) in the diagram * below to the corresponding vertex numbers in each tetrahedron (and * therefore maps 3 to the corresponding face number). * *
 *     *--->>--*
 *     |0  2 / |
 *     |    / 1|
 *     v   /   v
 *     |1 /    |
 *     | / 2  0|
 *     *--->>--*
 * 
* * In particular, if the two tetrahedra are \a t0 and \a t1 and the two * corresponding permutations are \a p0 and \a p1, then: * - the torus boundary is formed from faces \a p0[3] and \a p1[3] of * tetrahedra \a t0 and \a t1 respectively; * - edges \a p0[0]-\a p0[1] and \a p1[1]-\a p1[0] of tetrahedra * \a t0 and \a t1 respectively are identified; * - edges \a p0[1]-\a p0[2] and \a p1[2]-\a p1[1] of tetrahedra * \a t0 and \a t1 respectively are identified; * - edges \a p0[2]-\a p0[0] and \a p1[0]-\a p1[2] of tetrahedra * \a t0 and \a t1 respectively are identified. * * Note that we do not actually require these triangular faces to form a torus, * and this is never verifed by any of the routines in this class. What * these routines do is use the diagram above to define the rules of * what forms a valid layering (and in fact the layering itself will * often be the cause of these edge identifications). This allows the * NLayering class a little more versatility in degenerate and boundary cases. * * This class keeps track of an \e old boundary, which is the original * pair of triangles upon which the first tetrahedron is layered, and a * \e new boundary, which is formed by the last layered tetrahedron and * contains the modified boundary curves. If no tetrahedra are layered * at all then the old and new boundaries will be identical. * * This class is used to search for layerings as follows. The * constructor is called with a particular pair of triangles that will form * the old boundary (note that these are generally \e not boundary triangles * in the triangulation, since we are searching for layerings that have * been placed upon them). This forms a trivial (zero-tetrahedron) * layering. The routines extend() or extendOne() are then called to see * how many additional tetrahedra have been layered upon this pair of triangles * according to the rules above. */ class REGINA_API NLayering : public boost::noncopyable { private: unsigned long size; /**< The number of tetrahedra that have been layered. */ NTetrahedron* oldBdryTet[2]; /**< The two tetrahedra of the old boundary (these may be the same). See the class notes for details. */ NPerm4 oldBdryRoles[2]; /**< The corresponding two permutations of the old boundary. See the class notes for details. */ NTetrahedron* newBdryTet[2]; /**< The two tetrahedra of the new boundary (these may be the same). See the class notes for details. */ NPerm4 newBdryRoles[2]; /**< The corresponding two permutations of the new boundary. See the class notes for details. */ NMatrix2 reln; /**< A matrix that expresses the new boundary curves in terms of the old, assuming that the old boundary is in fact a torus as described in the class notes. The first row of \a reln expresses the new \a roles[0-1] curve in terms of the old \a roles[0-1] and \a roles[0-2] curves, and the second row expresses the new \a roles[0-2] curve in a similar fashion (here we always talk in terms of the first tetrahedron for each boundary). It is guaranteed that the determinant of this matrix is 1. */ public: /** * Creates a new trivial (zero-tetrahedron) layering upon the * given boundary. * * The boundary is described by two tetrahedra and two * permutations as explained in the class notes. Note that the * given tetrahedra need not be boundary triangles in the triangulation * (and if search routines such as extend() are called then they * almost certainly should not be). * * @param bdry0 the tetrahedron providing the first triangle of the * boundary. * @param roles0 the permutation describing how this first triangle is * formed from three vertices of tetrahedron \a bdry0, as * described in the class notes. * @param bdry1 the tetrahedron providing the second triangle of the * boundary. * @param roles1 the permutation describing how this second triangle is * formed from three vertices of tetrahedron \a bdry1. */ NLayering(NTetrahedron* bdry0, NPerm4 roles0, NTetrahedron* bdry1, NPerm4 roles1); /** * Returns the number of individual tetrahedra that have been * layered onto the original boundary, according to the data * stored in this structure. * * This begins at zero when the class constructor is called, and * it increases if the routines extend() or extendOne() find that * additional layerings have taken place. * * @return the number of layered tetrahedra. */ unsigned long getSize() const; /** * Returns the tetrahedra that provide the old boundary triangles. * These belong to the original boundary before any layerings * take place. * * See the NLayering class notes for details on how a torus * boundary is formed from two tetrahedra and two permutations. * * @param which specifies which tetrahedron to return; this must * be either 0 or 1. * @return the requested tetrahedron of the old boundary. */ NTetrahedron* getOldBoundaryTet(unsigned which) const; /** * Returns the permutations that describe the old boundary triangles. * These refer to the original boundary before any layerings * take place. * * See the NLayering class notes for details on how a torus * boundary is formed from two tetrahedra and two permutations. * * @param which specifies which permutation to return; this must * be either 0 or 1. * @return the requested permutation describing the old boundary. */ NPerm4 getOldBoundaryRoles(unsigned which) const; /** * Returns the tetrahedra that provide the new boundary triangles. * These belong to the final boundary after layerings have been * performed. * * See the NLayering class notes for details on how a torus * boundary is formed from two tetrahedra and two permutations. * * @param which specifies which tetrahedron to return; this must * be either 0 or 1. * @return the requested tetrahedron of the new boundary. */ NTetrahedron* getNewBoundaryTet(unsigned which) const; /** * Returns the permutations that describe the new boundary triangles. * These refer to the final boundary after layerings have been * performed. * * See the NLayering class notes for details on how a torus * boundary is formed from two tetrahedra and two permutations. * * @param which specifies which permutation to return; this must * be either 0 or 1. * @return the requested permutation describing the new boundary. */ NPerm4 getNewBoundaryRoles(unsigned which) const; /** * Returns a 2-by-2 matrix describing the relationship between * curves on the old and new boundary tori. Note that this * relationship will often be non-trivial, since one of the * key reasons for layering is to modify boundary curves. * * Let \a t and \a p be the first tetrahedron and * permutation of the old boundary (as returned by * getOldBoundaryTet(0) and getOldBoundaryRoles(0)), and let * \a old_x and \a old_y be the directed edges \a p[0]-\a p[1] * and \a p[0]-\a p[2] respectively of tetrahedron \a t (these * are the leftmost and uppermost edges of the diagram below). * Likewise, let \a s and \a q be the first tetrahedron and * permutation of the new boundary (as returned by * getNewBoundaryTet(0) and getNewBoundaryRoles(0)), and let * \a new_x and \a new_y be the directed edges \a q[0]-\a q[1] * and \a q[0]-\a q[2] respectively of tetrahedron \a s. * *
         *     *--->>--*
         *     |0  2 / |
         *     |    / 1|
         *     v   /   v
         *     |1 /    |
         *     | / 2  0|
         *     *--->>--*
         * 
* * Assuming both boundaries are tori, edges \a old_x and \a old_y are * generators of the old boundary torus and edges \a new_x and * \a new_y are generators of the new boundary torus. Suppose * that this routine returns the matrix \a M. This signifies * that, using additive notation: * *
         *     [new_x]         [old_x]
         *     [     ]  =  M * [     ] .
         *     [new_y]         [old_y]
         * 
* * In other words, the matrix that is returned expresses the * generator curves of the new boundary in terms of the * generator curves of the old boundary. * * Note that the determinant of this matrix will always be 1. * * @return the matrix relating the old and new boundary curves. */ const NMatrix2& boundaryReln() const; /** * Examines whether a single additional tetrahedron has been * layered upon the current new boundary. * * The new boundary triangles are assumed to form a torus as * described in the class notes (this is not verified, and there * are degenerate cases where this will likely be false). This * defines three possible ways in which an additional tetrahedron * may be layered (over the three boundary edges respectively). * * If it is found that an additional tetrahedron does exist and * has been joined to the new boundary in one of these three * possible ways, this structure is extended to incorporate the * additional tetrahedron. The size will grow by one, and the * new boundary will become the remaining two faces of this * additional tetrahedron. * * @return \c true if a tetrahedron was found as described above * and this structure was extended accordingly, or \c false otherwise. */ bool extendOne(); /** * Examines whether one or more additional tetrahedra have been * layered upon the current new boundary. * * Specifically, this routine calls extendOne() as many times as * possible. If \a k additional layerings are discovered as a * result, the size of this structure will have grown by \a k * and the new boundary will be changed to describe the * remaining two faces of the \a kth layered tetrahedron. * * It is guaranteed that, once this routine is finished, the new * boundary will not have any additional tetrahedron layered * upon it. That is, if extendOne() were called again then it * would return \c false. * * @return the number of additional layered tetrahedra that were * discovered. */ unsigned long extend(); /** * Determines whether the new torus boundary of this structure * is identified with the given torus boundary. In other words, * this routine determines whether the new torus boundary of * this structure and the given torus boundary represent * opposite sides of the same two triangles. * * The two boundaries must be identified according to some * homeomorphism of the torus. Note that there are 12 different * ways in which this can be done (two choices for which * tetrahedron face joins with which, and then six possible * rotations and reflections). * * As with the other routines in this class, this routine does * not verify that either boundary in fact forms a torus. * Instead, it uses this assumption to define the rules of what * identifications are allowable. * * If there is a match, the given matrix \a upperReln will be * modified to describe how the edges of the given boundary * relate to the edges of the old boundary torus. Note that * this relationship depends on how the intermediate tetrahedra * are layered (and in fact the purpose of a layering is often to * produce such a non-trivial relationship). * * Specifically, let \a t0 and \a p0 be the first tetrahedron and * permutation of the old boundary (as returned by * getOldBoundaryTet(0) and getOldBoundaryRoles(0)), and let * \a x and \a y be the directed edges \a p0[0]-\a p0[1] and * \a p0[0]-\a p0[2] of tetrahedron \a t0 respectively (these * are the leftmost and uppermost edges of the diagram below). * Likewise, let \a u and \a q be the first tetrahedron and * permutation of the given boundary (as passed by parameters * \a upperBdry0 and \a upperRoles0), and let * \a a and \a b be the directed edges \a q[0]-\a q[1] and * \a q[0]-\a q[2] of tetrahedron \a u respectively. * *
         *     *--->>--*
         *     |0  2 / |
         *     |    / 1|
         *     v   /   v
         *     |1 /    |
         *     | / 2  0|
         *     *--->>--*
         * 
* * Assuming both boundaries are tori, edges \a x and \a y are * generators of the original torus boundary and edges \a a and * \a b are generators of the given torus boundary. Using * additive notation, the matrix \a upperReln is modified so * that * *
         *     [a]                 [x]
         *     [ ]  =  upperReln * [ ] .
         *     [b]                 [y]
         * 
* * In other words, the modified \a upperReln matrix expresses * the generator curves of the given boundary in terms of the * generator curves of the old boundary. * * If no match is found, the matrix \a upperReln is not touched. * * @param upperBdry0 the tetrahedron providing the first triangle of * the given boundary. * @param upperRoles0 the permutation describing how this * first triangle is formed from three vertices of tetrahedron * upperBdry0, as described in the class notes. * @param upperBdry1 the tetrahedron providing the second triangle of * the given boundary. * @param upperRoles1 the permutation describing how this second * triangle is formed from three vertices of tetrahedron upperBdry1. * @param upperReln the matrix that is changed to reflect the * relationship between the old boundary of this structure and * the given boundary. * @return \c true if the given boundary is found to matche the * new boundary of this structure, or \c false otherwise. */ bool matchesTop(NTetrahedron* upperBdry0, NPerm4 upperRoles0, NTetrahedron* upperBdry1, NPerm4 upperRoles1, NMatrix2& upperReln) const; }; /*@}*/ // Inline functions for NLayering inline unsigned long NLayering::getSize() const { return size; } inline NTetrahedron* NLayering::getOldBoundaryTet(unsigned which) const { return oldBdryTet[which]; } inline NPerm4 NLayering::getOldBoundaryRoles(unsigned which) const { return oldBdryRoles[which]; } inline NTetrahedron* NLayering::getNewBoundaryTet(unsigned which) const { return newBdryTet[which]; } inline NPerm4 NLayering::getNewBoundaryRoles(unsigned which) const { return newBdryRoles[which]; } inline const NMatrix2& NLayering::boundaryReln() const { return reln; } } // namespace regina #endif regina-4.96/engine/subcomplex/npillowtwosphere.cpp000644 000765 000024 00000007611 12377776672 022424 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "subcomplex/npillowtwosphere.h" #include "triangulation/ntriangle.h" namespace regina { NPillowTwoSphere* NPillowTwoSphere::clone() const { NPillowTwoSphere* ans = new NPillowTwoSphere(); ans->triangle[0] = triangle[0]; ans->triangle[1] = triangle[1]; ans->triMapping = triMapping; return ans; } NPillowTwoSphere* NPillowTwoSphere::formsPillowTwoSphere( NTriangle* tri1, NTriangle* tri2) { if (tri1 == tri2 || tri1->isBoundary() || tri2->isBoundary()) return 0; NEdge* edge[2][3]; int i; for (i = 0; i < 3; i++) { edge[0][i] = tri1->getEdge(i); edge[1][i] = tri2->getEdge(i); } if (edge[0][0] == edge[0][1] || edge[0][0] == edge[0][2] || edge[0][1] == edge[0][2]) return 0; // The first triangle has three distinct edges. See if it matches to the // second triangle. int joinTo0 = -1; for (i = 0; i < 3; i++) if (edge[0][0] == edge[1][i]) { joinTo0 = i; break; } if (joinTo0 == -1) return 0; // Now make sure the edges all match up and with the correct // permutations. NPerm4 perm = tri2->getEdgeMapping(joinTo0) * tri1->getEdgeMapping(0).inverse(); for (i = 1; i < 3; i++) { if (edge[0][i] != edge[1][perm[i]]) return 0; if (! (tri2->getEdgeMapping(perm[i]) == perm * tri1->getEdgeMapping(i))) return 0; } // We have an answer. NPillowTwoSphere* ans = new NPillowTwoSphere(); ans->triangle[0] = tri1; ans->triangle[1] = tri2; ans->triMapping = perm; return ans; } } // namespace regina regina-4.96/engine/subcomplex/npillowtwosphere.h000644 000765 000024 00000016405 12377775461 022065 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/npillowtwosphere.h * \brief Deals with 2-spheres made from two triangles glued along their * three edges. */ #ifndef __NPILLOWTWOSPHERE_H #ifndef __DOXYGEN #define __NPILLOWTWOSPHERE_H #endif #include "regina-core.h" #include "shareableobject.h" #include "maths/nperm4.h" namespace regina { class NTriangle; class NTriangulation; /** * \weakgroup subcomplex * @{ */ /** * Represents a 2-sphere made from two triangles glued together along their * three edges. The two triangles must be distinct and the three edges of * each triangle must also be distinct. Neither of the triangles may be * boundary triangles. * These two triangless together form an embedded 2-sphere in the triangulation * (with the exception that two or three points of the sphere corresponding * to the triangles vertices may be identified). * * This 2-sphere can be cut along and the two resulting 2-sphere * boundaries filled in with 3-balls, and the resulting triangulation has * the same number of tetrahedra as the original. If the original * 2-sphere was separating, the resulting triangulation will contain the * two terms of the corresponding connected sum. */ class REGINA_API NPillowTwoSphere : public ShareableObject { private: NTriangle* triangle[2]; /**< The two triangles whose edges are joined. */ NPerm4 triMapping; /**< A mapping from vertices (0,1,2) of the first triangle to vertices (0,1,2) of the second triangle describing how the triangle boundaries are joined. */ public: /** * Returns a newly created clone of this structure. * * @return a newly created clone. */ NPillowTwoSphere* clone() const; /** * Returns one of the two triangles whose boundaries are joined. * * @param index specifies which of the two triangles to return; * this must be either 0 or 1. * @return the corresponding triangle. */ NTriangle* getTriangle(int index) const; /** * A deprecated alias for getTriangle(). * * This routine returns one of the two triangles whose boundaries * are joined. See getTriangle() for further details. * * \deprecated This routine will be removed in a future version * of Regina. Please use getTriangle() instead. * * @param index specifies which of the two triangles to return; * this must be either 0 or 1. * @return the corresponding triangle. */ NTriangle* getFace(int index) const; /** * Returns a permutation describing how the boundaries of the two * triangles are joined. * * The permutation will map vertices (0,1,2) of * getTriangle(0) to vertices (0,1,2) of * getTriangle(1). The map will represent how the vertices * of the triangles are identified by the three edge gluings. * * @return a permutation describing how the triangle boundaries are * joined. */ NPerm4 getTriangleMapping() const; /** * A deprecated alias for getTriangleMapping(). * * This routine returns a permutation describing how the boundaries * of the two triangles are joined. See getTriangleMapping() * for further details. * * \deprecated This routine will be removed in a future version * of Regina. Please use getTriangleMapping() instead. * * @return a permutation describing how the triangle boundaries are * joined. */ NPerm4 getFaceMapping() const; /** * Determines if the two given triangles together form a pillow * 2-sphere. * * \pre The two given triangles are distinct. * * @param tri1 the first triangle to examine. * @param tri2 the second triangle to examine. * @return a newly created structure containing details of the * pillow 2-sphere, or \c null if the given triangles do not * form a pillow 2-sphere. */ static NPillowTwoSphere* formsPillowTwoSphere(NTriangle* tri1, NTriangle* tri2); void writeTextShort(std::ostream& out) const; private: /** * Creates a new uninitialised structure. */ NPillowTwoSphere(); }; /*@}*/ // Inline functions for NPillowTwoSphere inline NPillowTwoSphere::NPillowTwoSphere() { } inline NTriangle* NPillowTwoSphere::getTriangle(int index) const { return triangle[index]; } inline NTriangle* NPillowTwoSphere::getFace(int index) const { return triangle[index]; } inline NPerm4 NPillowTwoSphere::getTriangleMapping() const { return triMapping; } inline NPerm4 NPillowTwoSphere::getFaceMapping() const { return triMapping; } inline void NPillowTwoSphere::writeTextShort(std::ostream& out) const { out << "Pillow 2-sphere"; } } // namespace regina #endif regina-4.96/engine/subcomplex/npluggedtorusbundle.cpp000644 000765 000024 00000032365 12377776673 023100 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "manifold/ngraphloop.h" #include "manifold/nsfs.h" #include "subcomplex/nlayering.h" #include "subcomplex/npluggedtorusbundle.h" #include "subcomplex/nsatregion.h" #include "subcomplex/ntxicore.h" #include "triangulation/nisomorphism.h" #include "triangulation/ntriangulation.h" namespace regina { namespace { const NTxIDiagonalCore core_T_6_1(6, 1); const NTxIDiagonalCore core_T_7_1(7, 1); const NTxIDiagonalCore core_T_8_1(8, 1); const NTxIDiagonalCore core_T_8_2(8, 2); const NTxIDiagonalCore core_T_9_1(9, 1); const NTxIDiagonalCore core_T_9_2(9, 2); const NTxIDiagonalCore core_T_10_1(10, 1); const NTxIDiagonalCore core_T_10_2(10, 2); const NTxIDiagonalCore core_T_10_3(10, 3); const NTxIParallelCore core_T_p; } NPluggedTorusBundle::~NPluggedTorusBundle() { delete bundleIso_; delete region_; } NManifold* NPluggedTorusBundle::getManifold() const { NSFSpace* sfs = region_->createSFS(false); if (! sfs) return 0; if (sfs->punctures() == 1) { // The region has one larger boundary, but we pinch it to create // two smaller boundaries. sfs->addPuncture(); } sfs->reduce(false); return new NGraphLoop(sfs, matchingReln_); } std::ostream& NPluggedTorusBundle::writeName(std::ostream& out) const { out << "Plugged Torus Bundle ["; bundle_.writeName(out); out << " | "; region_->writeBlockAbbrs(out, false); return out << ']'; } std::ostream& NPluggedTorusBundle::writeTeXName(std::ostream& out) const { out << "\\mathrm{PTB}\\left["; bundle_.writeTeXName(out); out << "\\,|\\n"; region_->writeBlockAbbrs(out, true); return out << "\\right]"; } void NPluggedTorusBundle::writeTextLong(std::ostream& out) const { out << "Plugged torus bundle, fibre/orbifold relation " << matchingReln_ << '\n'; out << "Thin I-bundle: "; bundle_.writeName(out); out << '\n'; region_->writeDetail(out, "Saturated region"); } NPluggedTorusBundle* NPluggedTorusBundle::isPluggedTorusBundle( NTriangulation* tri) { // Basic property checks. if (! tri->isClosed()) return 0; if (tri->getNumberOfComponents() > 1) return 0; // The smallest non-trivial examples of these have nine tetrahedra // (six for the TxI core and another three for a non-trivial region). if (tri->getNumberOfTetrahedra() < 9) return 0; // We have a closed and connected triangulation with at least // nine tetrahedra. // Hunt for the thin torus bundle. NPluggedTorusBundle* ans; if ((ans = hunt(tri, core_T_6_1))) return ans; if ((ans = hunt(tri, core_T_7_1))) return ans; if ((ans = hunt(tri, core_T_8_1))) return ans; if ((ans = hunt(tri, core_T_8_2))) return ans; if ((ans = hunt(tri, core_T_9_1))) return ans; if ((ans = hunt(tri, core_T_9_2))) return ans; if ((ans = hunt(tri, core_T_10_1))) return ans; if ((ans = hunt(tri, core_T_10_2))) return ans; if ((ans = hunt(tri, core_T_10_3))) return ans; if ((ans = hunt(tri, core_T_p))) return ans; return 0; } NPluggedTorusBundle* NPluggedTorusBundle::hunt(NTriangulation* triang, const NTxICore& bundle) { std::list isos; if (! bundle.core().findAllSubcomplexesIn(*triang, isos)) return 0; int regionPos; NPerm4 annulusToUpperLayer; NSatAnnulus upperAnnulus, lowerAnnulus, bdryAnnulus; NSatBlock::TetList avoidTets; NSatBlock* starter; NSatRegion* region; bool bdryRefVert, bdryRefHoriz; // Run through each isomorphism and look for the corresponding layering. for (std::list::const_iterator it = isos.begin(); it != isos.end(); it++) { // Apply layerings to the upper and lower boundaries. NLayering layerUpper( triang->getTetrahedron((*it)->tetImage(bundle.bdryTet(0,0))), (*it)->facePerm(bundle.bdryTet(0,0)) * bundle.bdryRoles(0,0), triang->getTetrahedron((*it)->tetImage(bundle.bdryTet(0,1))), (*it)->facePerm(bundle.bdryTet(0,1)) * bundle.bdryRoles(0,1)); layerUpper.extend(); NLayering layerLower( triang->getTetrahedron((*it)->tetImage(bundle.bdryTet(1,0))), (*it)->facePerm(bundle.bdryTet(1,0)) * bundle.bdryRoles(1,0), triang->getTetrahedron((*it)->tetImage(bundle.bdryTet(1,1))), (*it)->facePerm(bundle.bdryTet(1,1)) * bundle.bdryRoles(1,1)); layerLower.extend(); // Count tetrahedra to ensure that the layerings haven't crossed. // In fact, we should have at least three spare tetrahedra for // housing a non-trivial saturated region. if (layerLower.getSize() + layerUpper.getSize() + bundle.core().getNumberOfTetrahedra() + 3 > triang->getNumberOfTetrahedra()) { // No good. Move on. delete *it; continue; } lowerAnnulus.tet[0] = layerLower.getNewBoundaryTet(0); lowerAnnulus.tet[1] = layerLower.getNewBoundaryTet(1); lowerAnnulus.roles[0] = layerLower.getNewBoundaryRoles(0); lowerAnnulus.roles[1] = layerLower.getNewBoundaryRoles(1); // Look for the saturated region. for (regionPos = 0; regionPos < 3; regionPos++) { // Construct the permutation from 0/1/2 markings on the // first saturated annulus boundary to 0/1/2 markings on the // first boundary triangle above the layering. annulusToUpperLayer = NPerm4(regionPos, (regionPos + 1) % 3, (regionPos + 2) % 3, 3); upperAnnulus.tet[0] = layerUpper.getNewBoundaryTet(0); upperAnnulus.tet[1] = layerUpper.getNewBoundaryTet(1); upperAnnulus.roles[0] = layerUpper.getNewBoundaryRoles(0) * annulusToUpperLayer; upperAnnulus.roles[1] = layerUpper.getNewBoundaryRoles(1) * annulusToUpperLayer; // Recall that we already know the triangulation to be closed. upperAnnulus.switchSides(); // Construct the list of tetrahedra to avoid when searching for the // saturated region. Don't worry about all the internal tetrahedra // within the layerings or the thin I-bundle; as long as we've got // the boundary tetrahedra we'll be fine. avoidTets.clear(); avoidTets.insert(layerUpper.getNewBoundaryTet(0)); avoidTets.insert(layerUpper.getNewBoundaryTet(1)); avoidTets.insert(layerLower.getNewBoundaryTet(0)); avoidTets.insert(layerLower.getNewBoundaryTet(1)); starter = NSatBlock::isBlock(upperAnnulus, avoidTets); if (! starter) continue; // We have a starter block. Make a region out of it, and // ensure that region has precisely two boundary annuli. region = new NSatRegion(starter); region->expand(avoidTets, false); if (region->numberOfBoundaryAnnuli() != 2) { delete region; continue; } // From the NSatRegion specifications we know that the first // boundary annulus will be upperAnnulus. Find the second. bdryAnnulus = region->boundaryAnnulus(1, bdryRefVert, bdryRefHoriz); // Hope like hell that this meets up with the lower layering // boundary. Note that this will force it to be a torus also. NMatrix2 upperRolesToLower; if (! lowerAnnulus.isJoined(bdryAnnulus, upperRolesToLower)) { delete region; continue; } // All good! // Better work out what we've got here. // Mapping from fibre/base curves (f0, o0) to upperAnnulus // edges (first triangle: 01, first triangle: 02). NMatrix2 curvesToUpperAnnulus(-1, 0, 0, 1); // Mapping from upperAnnulus edges (first: 01, first: 02) to // upper layering boundary roles (first: 01, first: 02). NMatrix2 upperAnnulusToUpperLayer; if (regionPos == 0) upperAnnulusToUpperLayer = NMatrix2(1, 0, 0, 1); else if (regionPos == 1) upperAnnulusToUpperLayer = NMatrix2(0, -1, 1, -1); else upperAnnulusToUpperLayer = NMatrix2(-1, 1, -1, 0); // Mapping from upper layering boundary roles // (first: 01, first: 02) to the bundle boundary 0 roles // (first: 01, first: 02) is layerUpper.boundaryReln().inverse(). // Mapping from bundle boundary 0 roles (first: 01, first: 02) to // bundle boundary 0 (alpha, beta) is bundle.bdryReln(0). // Mapping from bundle boundary 0 (alpha, beta) to bundle boundary 1 // (alpha, beta) is bundle.parallelReln(). // Mapping from bundle boundary 1 (alpha, beta) to bundle boundary 1 // roles (first: 01, first: 02) is bundle.bdryReln(1).inverse(). // Mapping from bundle boundary 1 roles (first: 01, first: 02) to // lower layering boundary roles (first: 01, first: 02) is // layerLower.boundaryReln(). // Mapping from lower layering boundary roles (first: 01, first: 02) // to lower annulus boundary roles (first: 01, first: 02) is the // identity. // SO: Here comes the mapping from fibre/base curves (f0, o0) // to lower annulus boundary roles (first: 01, first: 02): NMatrix2 curvesToLowerAnnulus = layerLower.boundaryReln() * bundle.bdryReln(1).inverse() * bundle.parallelReln() * bundle.bdryReln(0) * layerUpper.boundaryReln().inverse() * upperAnnulusToUpperLayer * curvesToUpperAnnulus; // Now let's work out the mapping from fibre/base curves (f1, o1) // to bdryAnnulus roles (first: 01, first: 02). This is // rather simpler. NMatrix2 curvesToBdryAnnulus(bdryRefVert ? 1 : -1, 0, 0, bdryRefHoriz ? -1 : 1); // Finally, we already know how the two annuli are joined // together -- we worked this out earlier as upperRolesToLower. // Note that curvesToBdryAnnulus is self-inverse, so we won't // bother inverting it even though we should. NPluggedTorusBundle* ans = new NPluggedTorusBundle(bundle, *it, region, curvesToBdryAnnulus * upperRolesToLower.inverse() * curvesToLowerAnnulus); // Before we head home, delete the remaining isomorphisms // that we never looked at. for (it++; it != isos.end(); it++) delete *it; return ans; } // No match. Delete this isomorphism; we won't need it any more. delete *it; continue; } // Nothing found. return 0; } } // namespace regina regina-4.96/engine/subcomplex/npluggedtorusbundle.h000644 000765 000024 00000032136 12377775462 022534 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/npluggedtorusbundle.h * \brief Supports self-identified Seifert fibred spaces that are * triangulated using a combination of thin I-bundles and saturated blocks. */ #ifndef __NPLUGGEDTORUSBUNDLE_H #ifndef __DOXYGEN #define __NPLUGGEDTORUSBUNDLE_H #endif #include "regina-core.h" #include "maths/nmatrix2.h" #include "subcomplex/nstandardtri.h" namespace regina { class NIsomorphism; class NSatRegion; class NTxICore; /** * \weakgroup subcomplex * @{ */ /** * Describes a triangulation of a graph manifold formed by joining a * bounded saturated region with a thin I-bundle over the torus, * possibly with layerings in between. * * The thin I-bundle must be untwisted, so that it forms the product * T x I with two boundary tori. Moreover, it must be isomorphic * to some existing instance of the class NTxICore. * * The saturated region is described by an object of the class NSatRegion. * This region must have precisely two boundary annuli. These may be * two separate torus boundaries (each formed from its own saturated annulus). * Alternatively, the saturated region may have a single boundary formed * from both saturated annuli, where this boundary is pinched together * so that each annulus becomes its own two-sided torus. * * Either way, the saturated region effectively has two torus boundaries, * each formed from two triangles of the triangulation. These boundaries * are then joined to the two torus boundaries of the thin I-bundle, * possibly with layerings in between (for more detail on layerings, see * the NLayering class). This is illustrated in the following diagram, * where the small tunnels show where the torus boundaries are joined * (possibly via layerings). * *
 *    /--------------------\     /-----------------\
 *    |                     -----                  |
 *    |                     -----                  |
 *    |  Saturated region  |     |  Thin I-bundle  |
 *    |                     -----                  |
 *    |                     -----                  |
 *    \--------------------/     \-----------------/
 * 
* * The effect of the thin I-bundle and the two layerings is essentially * to join the two boundaries of the saturated region according to some * non-trivial homeomorphism of the torus. This homeomorphism is * specified by a 2-by-2 matrix \a M as follows. * * Suppose that \a f0 and \a o0 are directed curves on the first * boundary torus and \a f1 and \a o1 are directed curves on the second * boundary torus, where \a f0 and \a f1 represent the fibres of the * saturated region and \a o0 and \a o1 represent the base orbifold (see * the page on \ref sfsnotation for terminology). * Then the torus boundaries of the saturated region are identified by * the thin I-bundle and layerings according to the following relation: * *
 *     [f1]       [f0]
 *     [  ] = M * [  ]
 *     [o1]       [o0]
 * 
* * Note that the routines writeName() and writeTeXName() do \e not offer * enough information to uniquely identify the triangulation, since this * essentially requires 2-dimensional assemblings of saturated blocks. * For more detail, writeTextLong() may be used instead. * * The optional NStandardTriangulation routine getManifold() is * implemented for this class, but getHomologyH1() is not. */ class REGINA_API NPluggedTorusBundle : public NStandardTriangulation { private: const NTxICore& bundle_; /**< The thin I-bundle that appears within this triangulation. This thin I-bundle is referenced from elsewhere (i.e., it is not owned by this object), and its tetrahedra do not belong to this triangulation (instead see the data member \a bundleIso_). */ NIsomorphism* bundleIso_; /**< A mapping from the thin I-bundle \a bundle_ to this triangulation. This is required since the thin I-bundle \a bundle_ is external, and does not refer directly to this triangulation. */ NSatRegion* region_; /**< The saturated region that appears within this triangulation. This region is owned by this object, and refers to tetrahedra within this triangulation. */ NMatrix2 matchingReln_; /**< Describes how the two torus boundaries of the saturated region are joined, as discussed in the class notes above. */ public: /** * Destroys this structure and its constituent components. * * As an exception, the thin I-bundle is not destroyed, since * it is assumed that this is referenced from elsewhere. */ ~NPluggedTorusBundle(); /** * Returns an isomorphic copy of the thin I-bundle that forms part * of this triangulation. Like all objects of class NTxICore, the * thin I-bundle that is returned is an external object with its own * separate triangulation of the product T x I. For * information on how the thin I-bundle is embedded within this * triangulation, see the routine bundleIso(). * * @return the an isomorphic copy of the thin I-bundle within * this triangulation. */ const NTxICore& bundle() const; /** * Returns an isomorphism describing how the thin I-bundle forms * a subcomplex of this triangulation. * * The thin I-bundle returned by bundle() does not directly * refer to tetrahedra within this triangulation. Instead it * contains its own isomorphic copy of the thin I-bundle * triangulation (as is usual for objects of class NTxICore). * * The isomorphism returned by this routine is a mapping from * the triangulation bundle().core() to this triangulation, * showing how the thin I-bundle appears as a subcomplex of this * structure. * * @return an isomorphism from the thin I-bundle described * by bundle() to the tetrahedra of this triangulation. */ const NIsomorphism& bundleIso() const; /** * Returns the saturated region that forms part of this triangulation. * The region refers directly to tetrahedra within this triangulation * (as opposed to the thin I-bundle, which refers to a separate * external triangulation). * * @return the saturated region. */ const NSatRegion& region() const; /** * Returns the matrix describing how the two torus boundaries of * the saturated region are joined by the thin I-bundle and * layerings. See the class notes above for details. * * @return the matching relation between the two region boundaries. */ const NMatrix2& matchingReln() const; NManifold* getManifold() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; void writeTextLong(std::ostream& out) const; /** * Determines if the given triangulation is a saturated region * joined to a thin I-bundle via optional layerings, as described * in the class notes above. * * @param tri the triangulation to examine. * @return a newly created object containing details of the * structure that was found, or \c null if the given * triangulation is not of the form described by this class. */ static NPluggedTorusBundle* isPluggedTorusBundle (NTriangulation* tri); private: /** * Creates a new structure of the form described in the class notes * above, based on the given constituent components. The new object * will take ownership of the given saturated region and isomorphism. * It will not take ownership of the given thin I-bundle. * * Note that the new object must refer to an existing triangulation. * * \warning The thin I-bundle \a bundle must have a lifetime at * least as long as the new object being created, since it will * be referenced directly by this new object. * * @param bundle the thin I-bundle whose isomorphic copy is used * within the triangulation described by the new object. * @param bundleIso the corresponding isomorphism from the given * thin I-bundle to the triangulation described by the new object. * @param region the saturated region used within the new object. * @param matchingReln the matching relation describing how the * two saturated region boundaries are joined by the thin * I-bundle and layerings, as described in the class notes above. */ NPluggedTorusBundle(const NTxICore& bundle, NIsomorphism* bundleIso, NSatRegion* region, const NMatrix2& matchingReln); /** * Determines whether the given triangulation is of the form * described by this class, with the constraint that the * thin I-bundle used within the triangulation must be isomorphic * to the given thin I-bundle. * * This routine is internal to isPluggedTorusBundle(). * * \pre The given triangulation is closed and connected. * * \warning If this routine is successful and a new object is * returned, this new object must not outlive the given thin * I-bundle (since the new object will in fact contain a direct * reference to this thin I-bundle). * * @param tri the triangulation to examine. * @param bundle the thin I-bundle whose isomorphic copy must be * used in the given triangulation. * @return a newly created object containing details of the * structure that was found, or \c null if the given triangulation * is not of the form described by this class using an isomorphic * copy of the given thin I-bundle. */ static NPluggedTorusBundle* hunt(NTriangulation* tri, const NTxICore& bundle); }; /*@}*/ // Inline functions for NPluggedTorusBundle inline NPluggedTorusBundle::NPluggedTorusBundle(const NTxICore& bundle, NIsomorphism* bundleIso, NSatRegion* region, const NMatrix2& matchingReln) : bundle_(bundle), bundleIso_(bundleIso), region_(region), matchingReln_(matchingReln) { } inline const NTxICore& NPluggedTorusBundle::bundle() const { return bundle_; } inline const NIsomorphism& NPluggedTorusBundle::bundleIso() const { return *bundleIso_; } inline const NSatRegion& NPluggedTorusBundle::region() const { return *region_; } inline const NMatrix2& NPluggedTorusBundle::matchingReln() const { return matchingReln_; } } // namespace regina #endif regina-4.96/engine/subcomplex/nplugtrisolidtorus.cpp000644 000765 000024 00000040037 12377776674 022774 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "manifold/nsfs.h" #include "triangulation/ntriangulation.h" #include "subcomplex/nplugtrisolidtorus.h" namespace regina { const int NPlugTriSolidTorus::CHAIN_NONE = 0; const int NPlugTriSolidTorus::CHAIN_MAJOR = 1; const int NPlugTriSolidTorus::CHAIN_MINOR = 3; const int NPlugTriSolidTorus::EQUATOR_MAJOR = 1; const int NPlugTriSolidTorus::EQUATOR_MINOR = 3; NPlugTriSolidTorus::~NPlugTriSolidTorus() { if (core) delete core; for (int i = 0; i < 3; i++) if (chain[i]) delete chain[i]; } NPlugTriSolidTorus* NPlugTriSolidTorus::clone() const { NPlugTriSolidTorus* ans = new NPlugTriSolidTorus(); ans->core = core->clone(); for (int i = 0; i < 3; i++) { if (chain[i]) ans->chain[i] = new NLayeredChain(*chain[i]); ans->chainType[i] = chainType[i]; } ans->equatorType = equatorType; return ans; } std::ostream& NPlugTriSolidTorus::writeName(std::ostream& out) const { long params[3]; int nParams = 0; int i; for (i = 0; i < 3; i++) if (chainType[i] != CHAIN_NONE) { if (chainType[i] == CHAIN_MAJOR) params[nParams++] = chain[i]->getIndex(); else params[nParams++] = -chain[i]->getIndex(); } std::sort(params, params + nParams); out << (equatorType == EQUATOR_MAJOR ? "P(" : "P'("); if (nParams == 0) return out << "0)"; for (i = 0; i < nParams; i++) { if (i > 0) out << ','; out << params[i]; } return out << ')'; } std::ostream& NPlugTriSolidTorus::writeTeXName(std::ostream& out) const { long params[3]; int nParams = 0; int i; for (i = 0; i < 3; i++) if (chainType[i] != CHAIN_NONE) { if (chainType[i] == CHAIN_MAJOR) params[nParams++] = chain[i]->getIndex(); else params[nParams++] = -chain[i]->getIndex(); } std::sort(params, params + nParams); out << (equatorType == EQUATOR_MAJOR ? "P_{" : "P'_{"); if (nParams == 0) return out << "0}"; for (i = 0; i < nParams; i++) { if (i > 0) out << ','; out << params[i]; } return out << '}'; } void NPlugTriSolidTorus::writeTextLong(std::ostream& out) const { out << "Plugged triangular solid torus: "; writeName(out); } NManifold* NPlugTriSolidTorus::getManifold() const { NSFSpace* ans = new NSFSpace(); ans->insertFibre(2, -1); ans->insertFibre(3, 1); long rot = (equatorType == EQUATOR_MAJOR ? 5 : 4); for (int i = 0; i < 3; i++) if (chainType[i] != CHAIN_NONE) { if (chainType[i] == equatorType) rot += chain[i]->getIndex(); else rot -= chain[i]->getIndex(); } if (rot != 0) ans->insertFibre(rot, 1); else { delete ans; return 0; } ans->reduce(); return ans; } NPlugTriSolidTorus* NPlugTriSolidTorus::isPlugTriSolidTorus( NComponent* comp) { // TODO: Each triangular solid torus is tested three times since we // can't call getTetrahedronIndex() from within a component only. // Basic property checks. if ((! comp->isClosed()) || (! comp->isOrientable())) return 0; if (comp->getNumberOfVertices() > 1) return 0; unsigned long nTet = comp->getNumberOfTetrahedra(); if (nTet < 5) return 0; // We have a 1-vertex closed orientable component with at least // 5 tetrahedra. // Hunt for a core. Make sure we find each triangular solid torus // just once. unsigned long tetIndex; int coreIndex; NTriSolidTorus* core; NTetrahedron* coreTet[3]; NEdge* axis[3]; NPerm4 coreRoles[3]; NTetrahedron* base[2]; NPerm4 baseRoles[2]; int i, j; bool error; NTetrahedron* plugTet[3][2]; NPerm4 plugRoles[3][2]; NPerm4 realPlugRoles[2]; NLayeredChain* chain[3]; int chainType[3]; int equatorType = 0; chain[0] = chain[1] = chain[2] = 0; for (tetIndex = 0; tetIndex < nTet - 2; tetIndex++) for (coreIndex = 0; coreIndex < 24; coreIndex++) { coreRoles[0] = NPerm4::S4[coreIndex]; if (coreRoles[0][0] > coreRoles[0][3]) continue; core = NTriSolidTorus::formsTriSolidTorus( comp->getTetrahedron(tetIndex), coreRoles[0]); if (! core) continue; for (i = 0; i < 3; i++) { coreTet[i] = core->getTetrahedron(i); coreRoles[i] = core->getVertexRoles(i); axis[i] = coreTet[i]->getEdge( NEdge::edgeNumber[coreRoles[i][0]][coreRoles[i][3]]); } if (axis[0] == axis[1] || axis[1] == axis[2] || axis[2] == axis[0]) { delete core; continue; } // We have the triangular solid torus and we know the three // axis edges are distinct. // Hunt for chains. for (i = 0; i < 3; i++) { base[0] = coreTet[(i + 1) % 3]->adjacentTetrahedron( coreRoles[(i + 1) % 3][2]); base[1] = coreTet[(i + 2) % 3]->adjacentTetrahedron( coreRoles[(i + 2) % 3][1]); if (base[0] != base[1]) { // No chain. chainType[i] = CHAIN_NONE; continue; } // Have we layered over the major axis? baseRoles[0] = coreTet[(i + 1) % 3]-> adjacentGluing(coreRoles[(i + 1) % 3][2]) * coreRoles[(i + 1) % 3] * NPerm4(0, 3, 2, 1); baseRoles[1] = coreTet[(i + 2) % 3]-> adjacentGluing(coreRoles[(i + 2) % 3][1]) * coreRoles[(i + 2) % 3] * NPerm4(2, 1, 0, 3); if (baseRoles[0] == baseRoles[1]) { chainType[i] = CHAIN_MAJOR; chain[i] = new NLayeredChain(base[0], baseRoles[0]); while (chain[i]->extendAbove()) ; continue; } // Have we layered over the minor axis? baseRoles[0] = coreTet[(i + 1) % 3]-> adjacentGluing(coreRoles[(i + 1) % 3][2]) * coreRoles[(i + 1) % 3] * NPerm4(3, 0, 2, 1); baseRoles[1] = coreTet[(i + 2) % 3]-> adjacentGluing(coreRoles[(i + 2) % 3][1]) * coreRoles[(i + 2) % 3] * NPerm4(2, 1, 3, 0); if (baseRoles[0] == baseRoles[1]) { chainType[i] = CHAIN_MINOR; chain[i] = new NLayeredChain(base[0], baseRoles[0]); while (chain[i]->extendAbove()) ; continue; } // It's not a chain but it can't be a plug either. // We'll notice the error because i will be less than 3. break; } // Check whether we broke out of the previous loop with an error. // Check also whether one of the chains is another in // reverse, and that we've found the correct number of // tetrahedra in total. error = false; if (i < 3) error = true; else if (chain[0] && chain[1] && chain[0]->getBottom() == chain[1]->getTop()) error = true; else if (chain[1] && chain[2] && chain[1]->getBottom() == chain[2]->getTop()) error = true; else if (chain[2] && chain[0] && chain[2]->getBottom() == chain[0]->getTop()) error = true; else if ((chain[0] ? chain[0]->getIndex() : 0) + (chain[1] ? chain[1]->getIndex() : 0) + (chain[2] ? chain[2]->getIndex() : 0) + 5 != nTet) error = true; if (error) { for (j = 0; j < 3; j++) if (chain[j]) { delete chain[j]; chain[j] = 0; } delete core; continue; } // Still hanging in. // We know there's only 2 tetrahedra left. // Now we need to check the plug. error = false; for (i = 0; i < 3; i++) { if (chain[i]) { plugTet[i][0] = chain[i]->getTop()->adjacentTetrahedron( chain[i]->getTopVertexRoles()[3]); plugTet[i][1] = chain[i]->getTop()->adjacentTetrahedron( chain[i]->getTopVertexRoles()[0]); plugRoles[i][0] = chain[i]->getTop()-> adjacentGluing(chain[i]-> getTopVertexRoles()[3]) * chain[i]->getTopVertexRoles() * (chainType[i] == CHAIN_MAJOR ? NPerm4(0, 1, 2, 3) : NPerm4(1, 0, 2, 3)); plugRoles[i][1] = chain[i]->getTop()-> adjacentGluing(chain[i]-> getTopVertexRoles()[0]) * chain[i]->getTopVertexRoles() * (chainType[i] == CHAIN_MAJOR ? NPerm4(2, 3, 1, 0) : NPerm4(3, 2, 1, 0)); } else { plugTet[i][0] = coreTet[(i + 1) % 3]-> adjacentTetrahedron(coreRoles[(i + 1) % 3][2]); plugTet[i][1] = coreTet[(i + 2) % 3]-> adjacentTetrahedron(coreRoles[(i + 2) % 3][1]); plugRoles[i][0] = coreTet[(i + 1) % 3]-> adjacentGluing(coreRoles[(i + 1) % 3][2]) * coreRoles[(i + 1) % 3] * NPerm4(0, 3, 1, 2); plugRoles[i][1] = coreTet[(i + 2) % 3]-> adjacentGluing(coreRoles[(i + 2) % 3][1]) * coreRoles[(i + 2) % 3] * NPerm4(0, 3, 2, 1); } } // Make sure we meet precisely two tetrahedra, three times // each. Note that this implies that the plug tetrahedra are // in fact thus far unseen. for (i = 0; i < 2; i++) if (plugTet[0][i] != plugTet[1][i] || plugTet[1][i] != plugTet[2][i]) { error = true; break; } // Make sure also that the gluing permutations for the plug // are correct. if (! error) { if (plugRoles[0][0][0] == plugRoles[1][0][0] && plugRoles[1][0][0] == plugRoles[2][0][0]) { // Type EQUATOR_MINOR. realPlugRoles[0] = plugRoles[0][0] * NPerm4(3, 2, 1, 0); realPlugRoles[1] = plugRoles[0][1] * NPerm4(3, 0, 2, 1); if (realPlugRoles[0] != plugRoles[1][0] * NPerm4(1, 3, 2, 0)) error = true; else if (realPlugRoles[0] != plugRoles[2][0] * NPerm4(2, 1, 3, 0)) error = true; else if (realPlugRoles[1] != plugRoles[1][1] * NPerm4(2, 3, 0, 1)) error = true; else if (realPlugRoles[1] != plugRoles[2][1] * NPerm4(0, 2, 3, 1)) error = true; else equatorType = EQUATOR_MINOR; } else if (plugRoles[0][0][1] == plugRoles[1][0][1] && plugRoles[1][0][1] == plugRoles[2][0][1]) { // Type EQUATOR_MAJOR. realPlugRoles[0] = plugRoles[0][0] * NPerm4(3, 2, 0, 1); realPlugRoles[1] = plugRoles[0][1] * NPerm4(3, 1, 2, 0); if (realPlugRoles[0] != plugRoles[1][0] * NPerm4(0, 3, 2, 1)) error = true; else if (realPlugRoles[0] != plugRoles[2][0] * NPerm4(2, 0, 3, 1)) error = true; else if (realPlugRoles[1] != plugRoles[1][1] * NPerm4(2, 3, 1, 0)) error = true; else if (realPlugRoles[1] != plugRoles[2][1] * NPerm4(1, 2, 3, 0)) error = true; else equatorType = EQUATOR_MAJOR; } else error = true; } // Finally check the internal triangle of the plug. if (! error) { if (plugTet[0][0]->adjacentTetrahedron(realPlugRoles[0][3]) != plugTet[0][1]) error = true; else if (plugTet[0][0]->adjacentGluing( realPlugRoles[0][3]) * realPlugRoles[0] != realPlugRoles[1]) error = true; } if (error) { for (j = 0; j < 3; j++) if (chain[j]) { delete chain[j]; chain[j] = 0; } delete core; continue; } // Success! NPlugTriSolidTorus* plug = new NPlugTriSolidTorus(); plug->core = core; for (i = 0; i < 3; i++) { plug->chain[i] = chain[i]; plug->chainType[i] = chainType[i]; } plug->equatorType = equatorType; return plug; } // Nothing was found. return 0; } } // namespace regina regina-4.96/engine/subcomplex/nplugtrisolidtorus.h000644 000765 000024 00000025051 12377775464 022434 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/nplugtrisolidtorus.h * \brief Deals with plugged triangular solid torus components of a * triangulation. */ #ifndef __NPLUGTRISOLIDTORUS_H #ifndef __DOXYGEN #define __NPLUGTRISOLIDTORUS_H #endif #include "regina-core.h" #include "subcomplex/ntrisolidtorus.h" #include "subcomplex/nlayeredchain.h" namespace regina { class NComponent; /** * \weakgroup subcomplex * @{ */ /** * Represents a plugged triangular solid torus component of a * triangulation. Such a component is obtained as follows. * * Begin with a three-tetrahedron triangular solid torus (as described by * class NTriSolidTorus). Observe that the three axis edges divide the * boundary into three annuli. * * To each of these annuli a layered chain may be optionally attached. * If present, the chain should be attached so its hinge edges are * identified with the axis edges of the corresonding annulus and its bottom * tetrahedron is layered over either the major edge or minor edge of the * corresponding annulus. The top two triangular faces of the layered chain * should remain free. * * Thus we now have three annuli on the boundary, each represented as a * square two of whose (opposite) edges are axis edges of the original * triangular solid torus (and possibly also hinge edges of a layered * chain). * * Create a \e plug by gluing two tetrahedra together along a single * triangle. The six edges that do not run along this common triangle split the * plug boundary into three squares. These three squares must be glued * to the three boundary annuli previously described. Each axis edge meets * two of the annuli; the two corresponding edges of the plug must be * non-adjacent (have no common vertex) on the plug. * In this way each of the six edges of the plug not running along its * interior triangle corresponds to precisely one of the two instances of * precisely one of the three axis edges. * * If the axis edges are directed so that they all point the * same way around the triangular solid torus, these axis edges when * drawn on the plug must all point from one common tip of the plug to * the other (where the \e tips of the plug are the vertices not meeting the * interior triangle). The gluings must also be made so that the resulting * triangulation component is orientable. * * Of the optional NStandardTriangulation routines, getManifold() is * implemented for most plugged triangular solid tori and * getHomologyH1() is not implemented at all. */ class REGINA_API NPlugTriSolidTorus : public NStandardTriangulation { public: static const int CHAIN_NONE; /**< Indicates an annulus on the triangular solid torus boundary with no attached layered chain. */ static const int CHAIN_MAJOR; /**< Indicates an annulus on the triangular solid torus boundary with an attached layered chain layered over the major edge of the annulus. */ static const int CHAIN_MINOR; /**< Indicates an annulus on the triangular solid torus boundary with an attached layered chain layered over the minor edge of the annulus. */ static const int EQUATOR_MAJOR; /**< Indicates that, if no layered chains were present, the equator of the plug would consist of major edges of the core triangular solid torus. */ static const int EQUATOR_MINOR; /**< Indicates that, if no layered chains were present, the equator of the plug would consist of minor edges of the core triangular solid torus. */ private: NTriSolidTorus* core; /**< The triangular solid torus at the core of this triangulation. */ NLayeredChain* chain[3]; /**< The layered chains attached to the annuli on the triangular solid torus, or 0 for those annuli without attached layered chains. */ int chainType[3]; /**< The way in which the layered chain is attached to each annulus on the triangular solid torus, or \a CHAIN_NONE for those annuli without attached layered chains. */ int equatorType; /**< Indicates which types of edges form the equator of the plug. */ public: /** * Destroys this plugged solid torus; note that the corresponding * triangular solid torus and layered chains will also be destroyed. */ virtual ~NPlugTriSolidTorus(); /** * Returns a newly created clone of this structure. * * @return a newly created clone. */ NPlugTriSolidTorus* clone() const; /** * Returns the triangular solid torus at the core of this * triangulation. * * @return the core triangular solid torus. */ const NTriSolidTorus& getCore() const; /** * Returns the layered chain attached to the requested * annulus on the boundary of the core triangular solid torus. * If there is no attached layered chain, \c null will be returned. * * Note that the core triangular solid torus will be attached to * the bottom (as opposed to the top) of the layered chain. * * @param annulus specifies which annulus to examine; this must * be 0, 1 or 2. * @return the corresponding layered chain. */ const NLayeredChain* getChain(int annulus) const; /** * Returns the way in which a layered chain is attached to the * requested annulus on the boundary of the core triangular solid * torus. This will be one of the chain type constants defined * in this class. * * @param annulus specifies which annulus to examine; this must * be 0, 1 or 2. * @return the type of layered chain, or \a CHAIN_NONE * if there is no layered chain attached to the requested annulus. */ int getChainType(int annulus) const; /** * Returns which types of edges form the equator of the plug. * In the absence of layered chains these will either all be major * edges or all be minor edges. * * Layered chains complicate matters, but the roles that the major * and minor edges play on the boundary annuli of the triangular * solid torus can be carried up to the annuli at the top of each * layered chain; the edges filling the corresponding major or * minor roles will then form the equator of the plug. * * @return the types of edges that form the equator of the plug; * this will be one of the equator type constants defined in this * class. */ int getEquatorType() const; /** * Determines if the given triangulation component is a * plugged triangular solid torus. * * @param comp the triangulation component to examine. * @return a newly created structure containing details of the * plugged triangular solid torus, or \c null if the given * component is not a plugged triangular solid torus. */ static NPlugTriSolidTorus* isPlugTriSolidTorus(NComponent* comp); NManifold* getManifold() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; void writeTextLong(std::ostream& out) const; private: /** * Creates a new structure with all subcomponent pointers * initialised to \c null. */ NPlugTriSolidTorus(); }; /*@}*/ // Inline functions for NPlugTriSolidTorus inline NPlugTriSolidTorus::NPlugTriSolidTorus() : core(0) { chain[0] = chain[1] = chain[2] = 0; chainType[0] = chainType[1] = chainType[2] = CHAIN_NONE; } inline const NTriSolidTorus& NPlugTriSolidTorus::getCore() const { return *core; } inline const NLayeredChain* NPlugTriSolidTorus::getChain(int annulus) const { return chain[annulus]; } inline int NPlugTriSolidTorus::getChainType(int annulus) const { return chainType[annulus]; } inline int NPlugTriSolidTorus::getEquatorType() const { return equatorType; } } // namespace regina #endif regina-4.96/engine/subcomplex/nsatannulus.cpp000644 000765 000024 00000027421 12377776674 021355 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "maths/nmatrix2.h" #include "subcomplex/nsatannulus.h" #include "triangulation/nedge.h" #include "triangulation/nisomorphism.h" #include "triangulation/ntetrahedron.h" #include "triangulation/ntriangulation.h" namespace regina { unsigned NSatAnnulus::meetsBoundary() const { unsigned ans = 0; if (! tet[0]->adjacentTetrahedron(roles[0][3])) ans++; if (! tet[1]->adjacentTetrahedron(roles[1][3])) ans++; return ans; } void NSatAnnulus::switchSides() { unsigned which, face; for (which = 0; which < 2; which++) { face = roles[which][3]; roles[which] = tet[which]->adjacentGluing(face) * roles[which]; tet[which] = tet[which]->adjacentTetrahedron(face); } } bool NSatAnnulus::isAdjacent(const NSatAnnulus& other, bool* refVert, bool* refHoriz) const { if (other.meetsBoundary()) return false; // See what is actually attached to the given annulus. NSatAnnulus opposite(other); opposite.switchSides(); if (opposite.tet[0] == tet[0] && opposite.tet[1] == tet[1]) { // Could be a match without horizontal reflection. if (opposite.roles[0] == roles[0] && opposite.roles[1] == roles[1]) { // Perfect match. if (refVert) *refVert = false; if (refHoriz) *refHoriz = false; return true; } if (opposite.roles[0] == roles[0] * NPerm4(0, 1) && opposite.roles[1] == roles[1] * NPerm4(0, 1)) { // Match with vertical reflection. if (refVert) *refVert = true; if (refHoriz) *refHoriz = false; return true; } } if (opposite.tet[0] == tet[1] && opposite.tet[1] == tet[0]) { // Could be a match with horizontal reflection. if (opposite.roles[0] == roles[1] * NPerm4(0, 1) && opposite.roles[1] == roles[0] * NPerm4(0, 1)) { // Match with horizontal reflection. if (refVert) *refVert = false; if (refHoriz) *refHoriz = true; return true; } if (opposite.roles[0] == roles[1] && opposite.roles[1] == roles[0]) { // Match with both reflections. if (refVert) *refVert = true; if (refHoriz) *refHoriz = true; return true; } } // No match. return false; } bool NSatAnnulus::isJoined(const NSatAnnulus& other, NMatrix2& matching) const { if (other.meetsBoundary()) return false; // See what is actually attached to the given annulus. NSatAnnulus opposite(other); opposite.switchSides(); bool swapTriangles; NPerm4 roleMap; // Maps this 0/1/2 roles -> opposite 0/1/2 roles. if (opposite.tet[0] == tet[0] && opposite.tet[1] == tet[1] && opposite.roles[0][3] == roles[0][3] && opposite.roles[1][3] == roles[1][3]) { swapTriangles = false; roleMap = opposite.roles[0].inverse() * roles[0]; if (roleMap != opposite.roles[1].inverse() * roles[1]) return false; } else if (opposite.tet[0] == tet[1] && opposite.tet[1] == tet[0] && opposite.roles[0][3] == roles[1][3] && opposite.roles[1][3] == roles[0][3]) { swapTriangles = true; roleMap = opposite.roles[1].inverse() * roles[0]; if (roleMap != opposite.roles[0].inverse() * roles[1]) return false; } else return false; // It's a match. We just need to work out the matching matrix. if (roleMap == NPerm4(0, 1, 2, 3)) { matching = NMatrix2(1, 0, 0, 1); } else if (roleMap == NPerm4(1, 2, 0, 3)) { matching = NMatrix2(-1, 1, -1, 0); } else if (roleMap == NPerm4(2, 0, 1, 3)) { matching = NMatrix2(0, -1, 1, -1); } else if (roleMap == NPerm4(0, 2, 1, 3)) { matching = NMatrix2(0, 1, 1, 0); } else if (roleMap == NPerm4(2, 1, 0, 3)) { matching = NMatrix2(1, -1, 0, -1); } else if (roleMap == NPerm4(1, 0, 2, 3)) { matching = NMatrix2(-1, 0, -1, 1); } if (swapTriangles) matching.negate(); return true; } bool NSatAnnulus::isTwoSidedTorus() const { // Check that the edges are identified in opposite pairs and that we // have no duplicates. NEdge* e01 = tet[0]->getEdge(NEdge::edgeNumber[roles[0][0]][roles[0][1]]); NEdge* e02 = tet[0]->getEdge(NEdge::edgeNumber[roles[0][0]][roles[0][2]]); NEdge* e12 = tet[0]->getEdge(NEdge::edgeNumber[roles[0][1]][roles[0][2]]); if (e01 != tet[1]->getEdge(NEdge::edgeNumber[roles[1][0]][roles[1][1]])) return false; if (e02 != tet[1]->getEdge(NEdge::edgeNumber[roles[1][0]][roles[1][2]])) return false; if (e12 != tet[1]->getEdge(NEdge::edgeNumber[roles[1][1]][roles[1][2]])) return false; if (e01 == e02 || e02 == e12 || e12 == e01) return false; // Verify that edges are consistently oriented, and that the // orientations of the edge links indicate a two-sided torus. NPerm4 map0, map1; int a, b, x, y; for (int i = 0; i < 3; i++) { // Examine edges corresponding to annulus markings a & b. // We also set x & y as the complement of {a,b} in {0,1,2,3}. switch (i) { case 0: a = 0; b = 1; x = 2; y = 3; break; case 1: a = 0; b = 2; x = 1; y = 3; break; case 2: a = 1; b = 2; x = 0; y = 3; break; } // Get mappings from tetrahedron edge roles to annulus vertex roles. map0 = roles[0].inverse() * tet[0]->getEdgeMapping( NEdge::edgeNumber[roles[0][a]][roles[0][b]]); map1 = roles[1].inverse() * tet[1]->getEdgeMapping( NEdge::edgeNumber[roles[1][a]][roles[1][b]]); // We should have {a,b} -> {a,b} and {x,y} -> {x,y} for each map. // Make sure that the two annulus edges are oriented in the same way // (i.e., (a,b) <-> (b,a)), and that the edge link runs in opposite // directions through the annulus on each side (i.e., (x,y) <-> (y,x)). if (map0 != NPerm4(a, b) * NPerm4(x, y) * map1) return false; } // No unpleasantries. return true; } void NSatAnnulus::transform(const NTriangulation* originalTri, const NIsomorphism* iso, NTriangulation* newTri) { unsigned which; unsigned long tetID; for (which = 0; which < 2; which++) { tetID = originalTri->tetrahedronIndex(tet[which]); tet[which] = newTri->getTetrahedron(iso->tetImage(tetID)); roles[which] = iso->facePerm(tetID) * roles[which]; } } void NSatAnnulus::attachLST(NTriangulation* tri, long alpha, long beta) const { // Save ourselves headaches later. Though this should never happen; // see the preconditions. if (alpha == 0) return; // Normalise to alpha positive. if (alpha < 0) { alpha = -alpha; beta = -beta; } // Pull out the degenerate case. if (alpha == 2 && beta == 1) { tet[0]->joinTo(roles[0][3], tet[1], roles[1] * NPerm4(0, 1) * roles[0].inverse()); return; } // Insert a real layered solid torus. How we do this depends on // relative signs and orderings. long diag = alpha - beta; // Our six possibilities are: // // 0 <= -diag < alpha <= beta: // 0 < alpha <= -diag < beta: // 0 < diag <= beta < alpha: // 0 <= beta < diag <= alpha: // 0 < -beta <= alpha < diag // 0 < alpha < -beta < diag // We can give the vertices of the tetrahedra "cut labels" as // follows (where the LST has parameters 0 <= cuts0 <= cuts1 <= cuts2): // // cuts0 // *-------* // |2 1 / | // | / 0| // cuts1 | / | cuts1 // |0 / | // | / 1 2| // *-------* // cuts0 long cuts0, cuts1; NPerm4 cutsToRoles; // Maps cut labels to annulus vertex roles. if (alpha <= beta) { if (-diag < alpha) { // 0 <= -diag < alpha <= beta: cuts0 = -diag; cuts1 = alpha; cutsToRoles = NPerm4(0, 2, 1, 3); } else { // 0 < alpha <= -diag < beta: cuts0 = alpha; cuts1 = -diag; cutsToRoles = NPerm4(2, 0, 1, 3); } } else if (0 <= beta) { if (diag <= beta) { // 0 < diag <= beta < alpha: cuts0 = diag; cuts1 = beta; cutsToRoles = NPerm4(0, 1, 2, 3); } else { // 0 <= beta < diag <= alpha: cuts0 = beta; cuts1 = diag; cutsToRoles = NPerm4(1, 0, 2, 3); } } else { if (-beta <= alpha) { // 0 < -beta <= alpha < diag cuts0 = -beta; cuts1 = alpha; cutsToRoles = NPerm4(1, 2, 0, 3); } else { // 0 < alpha < -beta < diag cuts0 = alpha; cuts1 = -beta; cutsToRoles = NPerm4(2, 1, 0, 3); } } NTetrahedron* lst = tri->insertLayeredSolidTorus(cuts0, cuts1); // The boundary of the new LST sits differently for the special // cases (0,1,1) and (1,1,2); see the insertLayeredSolidTorus() // documentation for details. if (cuts1 == 1) { lst->joinTo(3, tet[0], roles[0] * cutsToRoles * NPerm4(1, 2, 0, 3)); lst->joinTo(2, tet[1], roles[1] * cutsToRoles * NPerm4(2, 1, 3, 0)); } else { lst->joinTo(3, tet[0], roles[0] * cutsToRoles * NPerm4(0, 1, 2, 3)); lst->joinTo(2, tet[1], roles[1] * cutsToRoles * NPerm4(1, 0, 3, 2)); } } } // namespace regina regina-4.96/engine/subcomplex/nsatannulus.h000644 000765 000024 00000053571 12377775466 021025 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/nsatannulus.h * \brief Deals with saturated two-triangle annuli within a * Seifert fibred space. */ #ifndef __NSATANNULUS_H #ifndef __DOXYGEN #define __NSATANNULUS_H #endif #include "regina-core.h" #include "maths/nperm4.h" namespace regina { class NIsomorphism; class NMatrix2; class NTetrahedron; class NTriangulation; /** * \weakgroup subcomplex * @{ */ /** * Represents an annulus formed from a pair of triangles in a Seifert fibred * space. This annulus is saturated, i.e., a union of fibres. More than * that, the fibres run parallel to the two boundary edges of the annulus. * * The annulus is described from one side only. The description * includes an array of indices \a tet[] describing which two tetrahedra * provide the triangles of the annulus, as well as an array of permutations * \a roles[] detailing how the annulus matches up with the individual * tetrahedron vertices. * * The annulus can be drawn as follows, with the upper edge identified * with the lower: * *
 *            *--->---*
 *            |0  2 / |
 *    First   |    / 1|  Second
 *   triangle |   /   | triangle
 *            |1 /    |
 *            | / 2  0|
 *            *--->---*
 * 
* * Suppose that \a tet[0] and \a tet[1] are the tetrahedra providing the * first and second triangles respectively. Then the markings 0..2 on the * first triangle above correspond to vertices \a roles[0][0..2] of tetrahedron * \a tet[0], and likewise the markings 0..2 on the second triangle above * correspond to vertices \a roles[1][0..2] of tetrahedron \a tet[1]. * * Note that the diagram above can also be drawn as follows. * *
 *            *--->---*
 *            | \ 2  1|
 *    First   |0 \    |  Second
 *   triangle |   \   | triangle
 *            |    \ 0|
 *            |1  2 \ |
 *            *--->---*
 * 
* * Note also that the labelling of the tetrahedra and their vertices * establishes an orientation on the vertical fibres, as well as a * left-to-right direction across the annulus. * * For convenience we refer to edges \a roles[][0-1] as \e vertical, * edges \a roles[][0-2] as \e horizontal, and edge \a roles[][1-2] as * \e diagonal. This is illustrated in the following diagrams. * *
 *         V  Horizontal       V   Diagonal
 *         e  *--->---*        e  *--->---*
 *         r  |   g / |        r  |H\ 2  1|
 *         t  |  a / 1|        t  | o\    |
 *         i  | i /   |        i  |  r\   |
 *         c  |D /    |        c  |   i\ 0|
 *         a  | / 2  0|        a  |    z\ |
 *         l  *--->---*        l  *--->---*
 * 
* * \ifacespython The member arrays \a tet and \a roles are accessed for * reading through functions \a tet() and \a roles() respectively. For * instance, the first triangle tetrahedron for the saturated annulus \a a can * be accessed as a.tet(0). These same member arrays are * accessed for writing through functions \a setTet() and \a setRoles(), * so for instance the second triangle vertex roles for the saturated annulus * \a a can be modified by calling a.setRoles(1, newRoles). */ struct REGINA_API NSatAnnulus { NTetrahedron* tet[2]; /**< Describes which tetrahedra provide the first and second triangles. See the class notes for details. */ NPerm4 roles[2]; /**< Describes how the first and second triangles match up with individual tetrahedron vertices. See the class notes for details. */ /** * Creates a new uninitialised structure. Both tetrahedra will be * set to null pointers. */ NSatAnnulus(); /** * Creates a clone of the given structure. * * @param cloneMe the structure to clone. */ NSatAnnulus(const NSatAnnulus& cloneMe); /** * Creates a new structure initialised to the given values. See the * class notes for what the various tetrahedra and permutations mean. * * @param t0 the tetrahedron to assign to \a tet[0]. * @param r0 the permutation to assign to \a roles[0]. * @param t1 the tetrahedron to assign to \a tet[1]. * @param r1 the permutation to assign to \a roles[1]. */ NSatAnnulus(NTetrahedron* t0, NPerm4 r0, NTetrahedron* t1, NPerm4 r1); /** * Makes this equal to a clone of the given structure. * * @param cloneMe the structure to clone. * @return a reference to this structure. */ NSatAnnulus& operator = (const NSatAnnulus& cloneMe); /** * Determines whether or not this and the given structure describe * the same annulus with the same representation. This requires * both structures to have identical \a tet[] and \a roles[] arrays. * * @param other the structure to compare with this. * @return \c true if the structures describe the same annulus with * the same representation, or \c false if they do not. */ bool operator == (const NSatAnnulus& other) const; /** * Determines whether or not this and the given structure describe * the same annulus with the same representation. This requires * both structures to have identical \a tet[] and \a roles[] arrays. * * @param other the structure to compare with this. * @return \c true if the structures do not describe the same annulus * with the same representation, or \c false if they do. */ bool operator != (const NSatAnnulus& other) const; /** * Determines how many triangles of this annulus lie on the boundary * of the triangulation. * * Note that this routine can also be used as a boolean function * to determine whether any triangles of the annulus lie on the * triangulation boundary. * * @return the number of triangles of this annulus that lie on the boundary * of the triangulation; this will be 0, 1 or 2. */ unsigned meetsBoundary() const; /** * Converts this into a representation of the same annulus from the * other side. The first and second triangles and their 0..2 markings * (as described in the class notes) remain unchanged. However, the * two tetrahedra that are used to describe the annulus will be * replaced by their counterparts on the other side of the annulus * (i.e., the two new tetrahedra that meet the two original tetrahedra * along the annulus itself). * * \pre Neither triangle of this annulus is a boundary triangle of the * triangulation. */ void switchSides(); /** * Returns a representation of the same annulus from the other side. * This structure will not be changed. See switchSides() for further * details. * * \pre Neither triangle of this annulus is a boundary triangle of the * triangulation. * * @return a new representation of this annulus from the other side. */ NSatAnnulus otherSide() const; /** * Reverses the direction of the vertical fibres in this annulus * representation. The first and second triangles (as described in the * class notes) will remain unchanged, but the markings 0 and 1 on * each triangle will be switched. */ void reflectVertical(); /** * Returns a representation of this annulus in which the vertical * direction of the fibres has been reversed. This structure will * not be changed. See reflectVertical() for further details. * * @return a new representation of this annulus in which fibres have * been reversed. */ NSatAnnulus verticalReflection() const; /** * Performs a left-to-right reflection of this annulus * representation. The vertical direction of the fibres will remain * unchanged, but the first and second triangles will be switched (and * the 0..2 markings changed to compensate). */ void reflectHorizontal(); /** * Returns a left-to-right reflected representation of this annulus. * This structure will not be changed. See reflectHorizontal() for * further details. * * @return a new left-to-right reflection of this annulus. */ NSatAnnulus horizontalReflection() const; /** * Rotates the representation of this annulus by 180 degrees. * This has the effect of switching the first and second triangles and * also reversing the direction of the vertical fibres. * * Calling this routine is equivalent to calling reflectVertical() and * then reflectHorizontal(). */ void rotateHalfTurn(); /** * Returns a 180 degree rotated representation of this annulus. * This structure will not be changed. See rotateHalfTurn() for * further details. * * @return a new 180 degree rotation of this annulus. */ NSatAnnulus halfTurnRotation() const; /** * Determines whether this and the given annulus are adjacent, * possibly modulo vertical or horizontal reflections. That is, * this routine determines whether this and the given structure * represent opposite sides of the same saturated annulus, where the * fibres for both structures are consistent (though possibly reversed). * See switchSides() for details on what "opposite sides" means in * this context, and see reflectVertical() and reflectHorizontal() * for descriptions of the various types of reflection. * * Information regarding reflections is returned via the two boolean * pointers \a refVert and \a refHoriz. If the two annuli are * identically opposite each other as described by switchSides(), * both booleans will be set to \c false. If the two annuli are * identically opposite after one undergoes a vertical and/or * horizontal reflection, then the booleans \a refVert and/or * \a refHoriz will be set to \c true accordingly. * * The critical difference between this routine and isJoined() is * that this routine insists that the fibres on each annulus be * consistent. This routine is thus suitable for examining joins * between different sections of the same Seifert fibred space, * for example. * * \ifacespython This routine only takes a single argument (the * annulus \a other). The return value is a tuple of three * booleans: the usual return value, the value returned in \a refVert, * and the value returned in \a refHoriz. * * @param other the annulus to compare with this. * @param refVert returns information on whether the annuli are * adjacent modulo a vertical reflection. This is set to \c true * if a vertical reflection is required and \c false if it is not. * If no adjacency was found at all, this boolean is not touched. * A null pointer may be passed, in which case this information will * not be returned at all. * @param refHoriz returns information on whether the annuli are * adjacent modulo a horizontal reflection. This is set to \c true * if a horizontal reflection is required and \c false if it is not. * If no adjacency was found at all, this boolean is not touched. * A null pointer may be passed, in which case this information will * not be returned at all. * @return \c true if some adjacency was found (either with or * without reflections), or \c false if no adjacency was found at all. */ bool isAdjacent(const NSatAnnulus& other, bool* refVert, bool* refHoriz) const; /** * Determines whether this and the given annulus are joined in some * form, even if the fibres on each annulus are not consistent. * * This routine treats each annulus as though its boundaries are * identified to form a torus (though it does not actually test * whether this is true). It then examines whether this and the * given annulus represent opposite sides of the same torus. * More specifically, it tests whether both annuli are formed from * the same pair of triangles, and whether the mapping of 0/1/2 markings * from one annulus to the other is the same for each triangle. Note that * the triangles are allowed to be switched (i.e., the first triangle of one * annulus may be the second triangle of the other). * * The critical difference between this routine and isAdjacent() is * that this routine allows the fibres on each annulus to be * inconsistent. This routine is thus suitable for examining joins * between different Seifert fibred blocks in a graph manifold, for * example. * * If the two annuli are joined, the precise relationship between * the curves on each annulus will be returned in the matrix * \a matching. Specifically, let \a x and \a y be the oriented * curves running from markings 0-1 and 0-2 respectively on the * first triangle of this annulus. Likewise, let \a x' and \a y' run * from markings 0-1 and 0-2 respectively on the first triangle of the * annulus \a other. Then the joining between the two annuli can * be expressed as follows: * *
     *     [x ]                [x']
     *     [  ]  =  matching * [  ].
     *     [y ]                [y']
     * 
* * @param other the annulus to compare with this. * @param matching returns details on how the curves on each annulus * are related. If the this and the given annulus are not joined, * then this matrix is not touched. * @return \c true if this and the given annulus are found to be * joined, or \c false if they are not. */ bool isJoined(const NSatAnnulus& other, NMatrix2& matching) const; /** * Determines whether this annulus has its boundaries identified to * form an embedded two-sided torus within the surrounding triangulation. * * It will be verified that: * - the two triangles of this annulus are joined along all three pairs * of edges to form a torus; * - the three edges of this torus remain distinct (i.e., different edges * of the torus do not become identified within the larger triangulation); * - this torus is two-sided within the surrounding triangulation. * * @return \c true if this annulus forms an embedded two-sided torus as * described above, or \c false if it does not. */ bool isTwoSidedTorus() const; /** * Adjusts this annulus representation according to the given * isomorphism between triangulations. * * The given isomorphism must describe a mapping from \a originalTri * to \a newTri, and this annulus must refer to tetrahedra in * \a originalTri. This routine will adjust this annulus according * to the given isomorphism, so that it refers to the corresponding * tetrahedra in \a newTri (with the \a roles permutations also * updated accordingly). * * \pre This annulus refers to tetrahedra in \a originalTri, and * \a iso describes a mapping from \a originalTri to \a newTri. * * @param originalTri the triangulation currently used by this * annulus representation. * @param iso the mapping from \a originalTri to \a newTri. * @param newTri the triangulation to be used by the updated annulus * representation. */ void transform(const NTriangulation* originalTri, const NIsomorphism* iso, NTriangulation* newTri); /** * Returns the image of this annulus representation under the given * isomorphism between triangulations. This annulus representation * will not be changed. See transform() for further details. * * @param originalTri the triangulation currently used by this * annulus representation. * @param iso the mapping from \a originalTri to \a newTri. * @param newTri the triangulation to be used by the new annulus * representation. */ NSatAnnulus image(const NTriangulation* originalTri, const NIsomorphism* iso, NTriangulation* newTri) const; /** * Attaches a layered solid torus to the this saturated annulus. * * The layered solid torus will be attached so that the * given values \a alpha and \a beta describe how the * meridinal disc cuts the vertical and horizontal edges of the * annulus respectively. * * The result will effectively insert an (\a alpha, \a beta) * exceptional fibre into the Seifert fibred space space, where * the vertical edges run parallel to the fibres and the horizontal * edges represent the base orbifold. The sign of the fibre is * consistent with the fibre inserted by NSatLST::adjustSFS() * (in particular, negating \a beta will negate the fibre). * * In the case of a (2,1) fibre, the layered solid torus will be * degenerate (i.e., the two triangles of the annulus will simply be * joined together). * * \pre The given value \a alpha is not zero. * \pre The given values \a alpha and \a beta are coprime. * * @param tri the triangulation into which the new tetrahedra should * be inserted. * @param alpha describes how the meridinal disc of the torus should * cut the vertical edges. This may be positive or negative. * @param beta describes how the meridinal disc of the torus should * cut the horizontal edges. Again this may be positive or negative. */ void attachLST(NTriangulation* tri, long alpha, long beta) const; }; /*@}*/ // Inline functions for NSatAnnulus inline NSatAnnulus::NSatAnnulus() { tet[0] = tet[1] = 0; } inline NSatAnnulus::NSatAnnulus(const NSatAnnulus& cloneMe) { tet[0] = cloneMe.tet[0]; tet[1] = cloneMe.tet[1]; roles[0] = cloneMe.roles[0]; roles[1] = cloneMe.roles[1]; } inline NSatAnnulus::NSatAnnulus(NTetrahedron* t0, NPerm4 r0, NTetrahedron* t1, NPerm4 r1) { tet[0] = t0; tet[1] = t1; roles[0] = r0; roles[1] = r1; } inline NSatAnnulus& NSatAnnulus::operator = (const NSatAnnulus& cloneMe) { tet[0] = cloneMe.tet[0]; tet[1] = cloneMe.tet[1]; roles[0] = cloneMe.roles[0]; roles[1] = cloneMe.roles[1]; return *this; } inline bool NSatAnnulus::operator == (const NSatAnnulus& other) const { return (tet[0] == other.tet[0] && tet[1] == other.tet[1] && roles[0] == other.roles[0] && roles[1] == other.roles[1]); } inline bool NSatAnnulus::operator != (const NSatAnnulus& other) const { return (tet[0] != other.tet[0] || tet[1] != other.tet[1] || roles[0] != other.roles[0] || roles[1] != other.roles[1]); } inline NSatAnnulus NSatAnnulus::otherSide() const { NSatAnnulus a(*this); a.switchSides(); return a; } inline void NSatAnnulus::reflectVertical() { roles[0] = roles[0] * NPerm4(0, 1); roles[1] = roles[1] * NPerm4(0, 1); } inline NSatAnnulus NSatAnnulus::verticalReflection() const { return NSatAnnulus(tet[0], roles[0] * NPerm4(0, 1), tet[1], roles[1] * NPerm4(0, 1)); } inline void NSatAnnulus::reflectHorizontal() { NTetrahedron* t = tet[0]; tet[0] = tet[1]; tet[1] = t; NPerm4 r = roles[0]; roles[0] = roles[1] * NPerm4(0, 1); roles[1] = r * NPerm4(0, 1); } inline NSatAnnulus NSatAnnulus::horizontalReflection() const { return NSatAnnulus(tet[1], roles[1] * NPerm4(0, 1), tet[0], roles[0] * NPerm4(0, 1)); } inline void NSatAnnulus::rotateHalfTurn() { NTetrahedron* t = tet[0]; tet[0] = tet[1]; tet[1] = t; NPerm4 r = roles[0]; roles[0] = roles[1]; roles[1] = r; } inline NSatAnnulus NSatAnnulus::halfTurnRotation() const { return NSatAnnulus(tet[1], roles[1], tet[0], roles[0]); } inline NSatAnnulus NSatAnnulus::image(const NTriangulation* originalTri, const NIsomorphism* iso, NTriangulation* newTri) const { NSatAnnulus a(*this); a.transform(originalTri, iso, newTri); return a; } } // namespace regina #endif regina-4.96/engine/subcomplex/nsatblock.cpp000644 000765 000024 00000011451 12400000112 020700 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "subcomplex/nsatblock.h" #include namespace regina { NSatBlock::NSatBlock(const NSatBlock& cloneMe) : ShareableObject(), nAnnuli_(cloneMe.nAnnuli_), annulus_(new NSatAnnulus[cloneMe.nAnnuli_]), twistedBoundary_(cloneMe.twistedBoundary_), adjBlock_(new NSatBlock*[cloneMe.nAnnuli_]), adjAnnulus_(new unsigned[cloneMe.nAnnuli_]), adjReflected_(new bool[cloneMe.nAnnuli_]), adjBackwards_(new bool[cloneMe.nAnnuli_]) { for (unsigned i = 0; i < nAnnuli_; i++) { annulus_[i] = cloneMe.annulus_[i]; adjBlock_[i] = cloneMe.adjBlock_[i]; adjAnnulus_[i] = cloneMe.adjAnnulus_[i]; adjReflected_[i] = cloneMe.adjReflected_[i]; adjBackwards_[i] = cloneMe.adjBackwards_[i]; } } void NSatBlock::transform(const NTriangulation* originalTri, const NIsomorphism* iso, NTriangulation* newTri) { for (unsigned i = 0; i < nAnnuli_; i++) annulus_[i].transform(originalTri, iso, newTri); } void NSatBlock::nextBoundaryAnnulus(unsigned thisAnnulus, NSatBlock*& nextBlock, unsigned& nextAnnulus, bool& refVert, bool& refHoriz, bool followPrev) { // Don't worry about testing the precondition (this annulus has no // adjacency) -- things won't break even if it's false. nextBlock = this; if (followPrev) nextAnnulus = (thisAnnulus == 0 ? nAnnuli_ - 1 : thisAnnulus - 1); else nextAnnulus = (thisAnnulus + 1 == nAnnuli_ ? 0 : thisAnnulus + 1); refVert = refHoriz = false; unsigned tmp; while (nextBlock->hasAdjacentBlock(nextAnnulus)) { // Push through to the next block... if (nextBlock->adjReflected_[nextAnnulus]) refVert = ! refVert; if (! nextBlock->adjBackwards_[nextAnnulus]) refHoriz = ! refHoriz; tmp = nextBlock->adjAnnulus_[nextAnnulus]; nextBlock = nextBlock->adjBlock_[nextAnnulus]; nextAnnulus = tmp; // ... and step to the previous/next annulus around. if (refHoriz == followPrev) { nextAnnulus = (nextAnnulus + 1 == nextBlock->nAnnuli_ ? 0 : nextAnnulus + 1); } else { nextAnnulus = (nextAnnulus == 0 ? nextBlock->nAnnuli_ - 1 : nextAnnulus - 1); } } } std::string NSatBlock::getAbbr(bool tex) const { std::ostringstream s; writeAbbr(s, tex); return s.str(); } bool NSatBlock::isBad(NTetrahedron* t, const TetList& list) { if (list.find(t) != list.end()) return true; return false; } } // namespace regina regina-4.96/engine/subcomplex/nsatblock.h000644 000765 000024 00000107557 12377775467 020437 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/nsatblock.h * \brief Deals with saturated blocks in triangulations of Seifert fibred * spaces. */ #ifndef __NSATBLOCK_H #ifndef __DOXYGEN #define __NSATBLOCK_H #endif #include "regina-core.h" #include "shareableobject.h" #include "subcomplex/nsatannulus.h" #include namespace regina { class NIsomorphism; struct NSatAnnulus; class NSFSpace; class NTetrahedron; class NTriangulation; /** * \weakgroup subcomplex * @{ */ /** * Represents a saturated block in a Seifert fibred space. A saturated * block is a connected set of tetrahedra built from a subset of fibres * (no fibres may enter or exit the boundary of the block). In addition, * the boundary of this block must be a ring of saturated annuli, as * described by the NSatAnnulus class. Aside from this ring of saturated * annuli, there may be no other boundary triangles within the block. * * The boundary annuli are numbered consecutively as illustrated below, * where the markings 0 and 1 within the triangles represent the first * and second triangle of each annulus (see the NSatAnnulus class notes for * details). Note that the following diagram is viewed from \e inside * the block. * *
 *               -+---+---+---+---+---+---+-
 *                |0 /|0 /|0 /|0 /|0 /|0 /|
 *            ... | / | / | / | / | / | / | ...
 *                |/ 1|/ 1|/ 1|/ 1|/ 1|/ 1|
 *               -+---+---+---+---+---+---+-
 * Annulus #  ...  n-2 n-1  0   1   2   3   ...
 * 
* * The ring of boundary annuli may optionally be twisted, so that together * the annuli form a long Mobius band. In this case, for the purposes of * labelling and marking annuli, the twist occurs between annuli n-1 and 0. * Be careful when dealing with blocks with twisted boundaries, since * with twists it is possible to identify an edge with itself in reverse * (thus producing something that is not a 3-manifold triangulation). * * Each saturated block corresponds to a piece of the base orbifold of the * larger Seifert fibred space. For the purpose of connecting the base * orbifold together, we assume that the boundary of this particular * piece runs horizontally in the diagram above (specifically following * the horizontal edges of the boundary annuli, as described in the * NSatAnnulus class notes). Insisting on such a boundary may lead to * (1,\a k) twists within the block; these are accounted for by the * virtual adjustSFS() routine. * * Saturated blocks are generally joined to one another (or themselves) * along their boundary annuli. For this purpose, each saturated block * contains a list of which annulus of this block is adjacent to which * annulus of which other block. Adjacencies may be \e reflected, meaning * that the adjacent annulus has its fibres reversed (i.e., the adjacent * annulus has undergone an up-to-down reflection); they may also be * \e backwards, meaning that the first triangle of one annulus is joined to * the second triangle of the other (and vice versa). * * \warning In addition to mandatory overrides such as clone() and * adjustSFS(), some subclasses will need to override the virtual * routine transform() in order to correctly adjust additional * triangulation-specific information stored in the subclass. See the * transform() documentation for further details. */ class REGINA_API NSatBlock : public ShareableObject { public: typedef std::set TetList; /**< The data structure used to store a list of tetrahedra that should not be examined by isBlock(). */ protected: unsigned nAnnuli_; /**< The number of boundary annuli. */ NSatAnnulus* annulus_; /**< Details of each boundary annulus, as seen from the inside of this saturated block. */ bool twistedBoundary_; /**< Is the ring of boundary annuli twisted to form a Mobius band? */ NSatBlock** adjBlock_; /**< The saturated block joined to each boundary annulus; this may be null if there is no adjacency or if this information is not known. */ unsigned* adjAnnulus_; /**< Describes which specific annulus of the adjacent saturated block is joined to each boundary annulus of this block. Values may be undefined if the corresponding entries in the \a adjBlock array is null. */ bool* adjReflected_; /**< Describes whether the adjacency for each boundary annulus is reflected (see the class notes above). Values may be undefined if the corresponding entries in the \a adjBlock array is null. */ bool* adjBackwards_; /**< Describes whether the adjacency for each boundary annulus is backwards (see the class notes above). Values may be undefined if the corresponding entries in the \a adjBlock array is null. */ public: /** * Creates a new clone of the given block. * * Note that the new \a adjBlock_ array will contain pointers to * the same adjacent blocks as the original. That is, adjacent * blocks will not be cloned also; instead pointers to adjacent * blocks will simply be copied across. * * @param cloneMe the saturated block to clone. */ NSatBlock(const NSatBlock& cloneMe); /** * Destroys all internal arrays. Note that any adjacent blocks * that are referenced by the \a adjBlock array will \e not be * destroyed. */ ~NSatBlock(); /** * Returns a newly created clone of this saturated block structure. * A clone of the correct subclass of NSatBlock will be returned. * For this reason, each subclass of NSatBlock must implement this * routine. * * @return a new clone of this block. */ virtual NSatBlock* clone() const = 0; /** * Returns the number of annuli on the boundary of this * saturated block. * * @return the number of boundary annuli. */ unsigned nAnnuli() const; /** * Returns details of the requested annulus on the boundary of * this saturated block. Annuli are numbered from 0 to * nAnnuli()-1 as described in the class notes. * * @param which indicates which boundary annulus is requested; * this must be between 0 and nAnnuli()-1 inclusive. * @return a reference to the requested boundary annulus. */ const NSatAnnulus& annulus(unsigned which) const; /** * Is the ring of boundary annuli twisted to form a long Mobius * strip? * * Recall from the class notes that the twist occurs between * boundary annuli nAnnuli()-1 and 0. * * @return \c true if the ring of boundary annuli is twisted, or * \c false if not. */ bool twistedBoundary() const; /** * Returns whether there is another saturated block listed as * being adjacent to the given boundary annulus of this block. * * @param whichAnnulus indicates which boundary annulus of this block * should be examined; this must be between 0 and nAnnuli()-1 * inclusive. * @return \c true if the given boundary annulus has an adjacent * block listed, or \c false otherwise. */ bool hasAdjacentBlock(unsigned whichAnnulus) const; /** * Returns the saturated block listed as being adjacent to the * given boundary annulus of this block. * * @param whichAnnulus indicates which boundary annulus of this block * should be examined; this must be between 0 and nAnnuli()-1 * inclusive. * @return the other block adjacent along this annulus, or 0 * if there is no adjacent block listed. */ NSatBlock* adjacentBlock(unsigned whichAnnulus) const; /** * Returns which specific annulus of the adjacent block is * listed as being adjacent to the given boundary annulus of * this block. * * \pre The given annulus of this block actually has an adjacent * block listed. * * @param whichAnnulus indicates which boundary annulus of this block * should be examined; this must be between 0 and nAnnuli()-1 * inclusive. * @return the corresponding annulus number on the other block * that is adjacent along this annulus. */ unsigned adjacentAnnulus(unsigned whichAnnulus) const; /** * Returns whether the adjacency along the given boundary annulus * of this block is reflected. See the class notes for a * discussion of reflected adjacencies. * * \pre The given annulus of this block actually has an adjacent * block listed. * * @param whichAnnulus indicates which boundary annulus of this block * should be examined; this must be between 0 and nAnnuli()-1 * inclusive. * @return \c true if the corresponding adjacency is reflected, * or \c false if it is not. */ bool adjacentReflected(unsigned whichAnnulus) const; /** * Returns whether the adjacency along the given boundary annulus * of this block is backwards. See the class notes for a * discussion of backwards adjacencies. * * \pre The given annulus of this block actually has an adjacent * block listed. * * @param whichAnnulus indicates which boundary annulus of this block * should be examined; this must be between 0 and nAnnuli()-1 * inclusive. * @return \c true if the corresponding adjacency is backwards, * or \c false if it is not. */ bool adjacentBackwards(unsigned whichAnnulus) const; /** * Lists the given saturated block as being adjacent to the * given boundary annulus of this block. Both block structures * (this and the given block) will be updated. * * @param whichAnnulus indicates which boundary annulus of this block * has the new adjacency; this must be between 0 and nAnnuli()-1 * inclusive. * @param adjBlock the other saturated block that is adjacent to * this. * @param adjAnnulus indicates which boundary annulus of the * adjacent block meets the given boundary annulus of this block; * this must be between 0 and adjBlock->nAnnuli()-1 inclusive. * @param adjReflected indicates whether the new adjacency is * reflected (see the class notes for details). * @param adjBackwards indicates whether the new adjacency is * backwards (see the class notes for details). */ void setAdjacent(unsigned whichAnnulus, NSatBlock* adjBlock, unsigned adjAnnulus, bool adjReflected, bool adjBackwards); /** * Adjusts the given Seifert fibred space to insert the contents * of this saturated block. In particular, the space should be * adjusted as though an ordinary solid torus (base orbifold a * disc, no twists or exceptional fibres) had been replaced by * this block. This description does not make sense for blocks * with twisted boundary; the twisted case is discussed below. * * If the argument \a reflect is \c true, it should be assumed * that this saturated block is being reflected before being * inserted into the larger Seifert fibred space. That is, any * twists or exceptional fibres should be negated before being * added. * * Regarding the signs of exceptional fibres: Consider a * saturated block containing a solid torus whose meridinal curve * runs \a p times horizontally around the boundary in order through * annuli 0,1,... and follows the fibres \a q times from bottom * to top (as depicted in the diagram in the NSatBlock class * notes). Then this saturated block adds a positive (\a p, \a q) * fibre to the underlying Seifert fibred space. * * If the ring of saturated annuli bounding this block is twisted * then the situation becomes more complex. It can be proven * that such a block must contain a twisted reflector boundary * in the base orbifold (use Z_2 homology with fibre-reversing * paths to show that the base orbifold must contain another * twisted boundary component, and then recall that real boundaries * are not allowed inside blocks). * * In this twisted boundary case, it should be assumed that the * twisted reflector boundary is already stored in the given Seifert * fibred space. This routine should make any further changes * that are required (there may well be none). That is, the * space should be adjusted as though a trivial Seifert fibred * space over the annulus with one twisted reflector boundary (and * one twisted puncture corresponding to the block boundary) had * been replaced by this block. In particular, this routine should * \e not add the reflector boundary itself. * * @param sfs the Seifert fibred space to adjust. * @param reflect \c true if this block is to be reflected, or * \c false if it should be inserted directly. */ virtual void adjustSFS(NSFSpace& sfs, bool reflect) const = 0; /** * Adjusts the structure of this block according to the given * isomorphism between triangulations. Any triangulation-specific * information will be transformed accordingly (for instance, the * routine NSatAnnulus::transform() will be called for each * boundary annulus). * * Information regarding adjacent blocks will \e not be changed. * Only structural information for this particular block will be * updated. * * The given isomorphism must describe a mapping from \a originalTri * to \a newTri, and this block must currently refer to tetrahedra in * \a originalTri. After this routine is called the block will * instead refer to the corresponding tetrahedra in \a newTri (with * changes in vertex/face numbering also accounted for). * * \pre This block currently refers to tetrahedra in \a originalTri, * and \a iso describes a mapping from \a originalTri to \a newTri. * * \warning Any subclasses of NSatBlock that store additional * triangulation-specific information will need to override this * routine. When doing so, be sure to call NSatBlock::transform() * so that the generic changes defined here will still take place. * * @param originalTri the triangulation currently used by this * saturated block. * @param iso the mapping from \a originalTri to \a newTri. * @param newTri the triangulation to be used by the updated * block structure. */ virtual void transform(const NTriangulation* originalTri, const NIsomorphism* iso, NTriangulation* newTri); /** * Finds the next (or previous) boundary annulus around from this, * treating all adjacent blocks as part of a single large saturated * region. * * Suppose that all saturated blocks are merged together according * to adjacent boundary annuli, forming larger saturated structures. * The remaining annuli that do not have adjacent blocks will * group together to form several large boundary rings. Note that * each boundary ring might involve annuli from several * different blocks, and might or might not have a twist (thus * forming a large Klein bottle instead of a large torus). * * This routine is used to trace around such a boundary ring. It is * assumed that annulus \a thisAnnulus of this block forms part * of a boundary ring (i.e., it has no adjacent block). This * routine will then return the next/previous annulus around from * this in the large boundary ring. Here "next" means in the direction * following from the second triangle of this annulus, and * "previous" means in the direction following from the first triangle; * the boolean argument \a followPrev controls which we will be used. * This next/previous annulus might belong to another block, or it * might even be this original annulus again. * * The next/previous annulus itself is not returned, but rather a * reference as to how it appears within its enclosing saturated block. * Specifically, a block and corresponding annulus number will be * returned in the arguments \a nextBlock and \a nextAnnulus * respectively. * * It is possible that the next/previous annulus as it appears within * the returned block is oriented differently from how it appears * within this large boundary ring. For this reason, two * booleans are returned also. The argument \a refVert will * describe whether the annulus is reflected vertically as it * appears within the large boundary ring (i.e., the first and * second triangles remain the same but the fibre direction is * reversed). Similarly, the argument \a refHoriz will describe * whether the annulus is reflected horizontally as it appears * within the large boundary ring (i.e., first and second triangles * are switched but the fibre direction is unchanged). * * It is possible that both a horizontal and vertical reflection * take place. Note that any kind of reflection will also * affect the locations of the 0/1/2 markings as described in * the NSatAnnulus class notes. * * Finally, note that if the large boundary ring is twisted * (i.e., it forms a Klein bottle), then following the entire * boundary ring around using this routine will bring you back to * the starting annulus but with the \a refVert flag set. * * \pre Annulus \a thisAnnulus of this block has no block * adjacent to it. * * \warning If you wish to trace around an entire boundary * ring, you will need to adjust the argument \a followPrev * according to whether or not the current annulus * is reflected horizontally (since, under a horizontal * reflection, "next" becomes "previous" and vice versa). * * \ifacespython This routine only takes two arguments (\a thisAnnulus * and \a followPrev). The return value is a tuple of four * values: the block returned in \a nextBlock, the integer * returned in \a nextAnnulus, the boolean returned in \a refVert, * and the boolean returned in \a refHoriz. * * @param thisAnnulus describes which original boundary annulus of * this block to examine; this must be between 0 and nAnnuli()-1 * inclusive. * @param nextBlock a reference used to return the block * containing the next boundary annulus around from \a thisAnnulus. * @param nextAnnulus a reference used to return the specific * annulus number within \a nextBlock of the next annulus * around; this will be between 0 and \a nextBlock->nAnnuli()-1 * inclusive, and the corresponding annulus will have no block * adjacent to it. * @param refVert a reference used to return \c true if the next * annulus around is vertically reflected, or \c false if not; * see above for details. * @param refHoriz a reference used to return \c true if the next * annulus around is horizontally reflected, or \c false if not; * see above for details. * @param followPrev \c true if we should find the previous boundary * annulus, or \c false if we should find the next boundary annulus. */ void nextBoundaryAnnulus(unsigned thisAnnulus, NSatBlock*& nextBlock, unsigned& nextAnnulus, bool& refVert, bool& refHoriz, bool followPrev); /** * Returns an abbreviated name or symbol for this block. * This name will reflect the particular block type, but may not * provide thorough details. * * The name will be no more than a handful of characters long, and * will not include a newline (or surrounding dollar signs in TeX * mode). * * @param tex \c true if the name should be formatted for TeX, * or \c false if it should be in plain text format. * @return an abbreviated name for this block. */ std::string getAbbr(bool tex = false) const; /** * Writes an abbreviated name or symbol for this block to the * given output stream. This name should reflect the particular * block type, but need not provide thorough details. * * The output should be no more than a handful of characters long, * and no newline should be written. In TeX mode, no leading or * trailing dollar signs should be written. * * \ifacespython The parameter \a out does not exist; standard * output will be used. * * @param out the output stream to which to write. * @param tex \c true if the output should be formatted for TeX, * or \c false if it should be in plain text format. */ virtual void writeAbbr(std::ostream& out, bool tex = false) const = 0; /** * Implements a consistent ordering of saturated blocks. * This ordering is purely aesthetic on the part of the author, * and is subject to change in future versions of Regina. * * @param compare the saturated block with which this will be * compared. * @return \c true if this block comes before the given block * according to the ordering of saturated blocks, or \c false * if either the blocks are identical or this block comes after * the given block. */ bool operator < (const NSatBlock& compare) const; /** * Determines whether the given annulus is in fact a boundary * annulus for a recognised type of saturated block. The * annulus should be represented from the inside of the proposed * saturated block. * * Only certain types of saturated block are recognised by this * routine. More exotic saturated blocks will not be identified, * and this routine will return \c null in such cases. * * The given list of tetrahedra will not be examined by this * routine. That is, only saturated blocks that do not contain * any of these tetrahedra will be considered. As a consequence, * if the given annulus uses any of these tetrahedra then \c null * will be returned. * * If a block is found on the other hand, all of the tetrahedra * within this block will be added to the given list. * * In the event that a block is found, it is guaranteed that the * given annulus will be listed as annulus number 0 in the block * structure, without any horizontal or vertical reflection. * * \ifacespython The second argument \a avoidTets is not * present. An empty list will be passed instead. * * @param annulus the proposed boundary annulus that should form * part of the new saturated block. * @param avoidTets the list of tetrahedra that should not be * considered, and to which any new tetrahedra will be added. * @return details of the saturated block if one was found, or * \c null if none was found. */ static NSatBlock* isBlock(const NSatAnnulus& annulus, TetList& avoidTets); protected: /** * Constructor for a block with the given number of annuli on * the boundary. * * All arrays will be constructed but their contents will remain * uninitialised, with the exception that the \a adjBlock array * will be filled with null pointers. * * @param nAnnuli the number of annuli on the boundary of this * block; this must be strictly positive. * @param twistedBoundary \c true if the ring of boundary annuli * is twisted to form a long Mobius band, or \c false (the default) * if it is not. */ NSatBlock(unsigned nAnnuli, bool twistedBoundary = false); /** * Determines whether the given tetrahedron is contained within the * given list. * * This is intended as a helper routine for isBlock() and * related routines. * * @param t the tetrahedron to search for. * @param list the list in which to search. * @return \c true if and only if the given tetrahedron was found. */ static bool isBad(NTetrahedron* t, const TetList& list); /** * Determines whether the given tetrahedron is contained within * the given list. * * This is intended as a helper routine for isBlock() and * related routines. It is a generic routine for working with * arbitrary list types. * * \pre Forward iterators of type List::const_iterator * that span the given list can be obtained by calling * list.begin() and list.end(). * * @param t the tetrahedron to search for. * @param list the list in which to search. * @return \c true if and only if the given tetrahedron was found. */ template static bool isBad(NTetrahedron* t, const List& list) { for (typename List::const_iterator it = list.begin(); it != list.end(); ++it) if (*it == t) return true; return false; } /** * Determines whether the given tetrahedron pointer is null. * * This is intended as a helper routine for isBlock() and * related routines. Despite its trivial implementation, it is * provided to make long blocks of code easier to read and * distinguish by functionality. * * The name notUnique() may seem strang for what is essentially * a nullity test; in fact this routine is offered as a * degenerate case of other variants of notUnique() that take * more tetrahedra as arguments. * * @param test the tetrahedron pointer to test. * @return \c true if \a test is null, or \c false otherwise. */ static bool notUnique(NTetrahedron* test); /** * Determines whether the given tetrahedron pointer is null * or equal to another from the given list. * * This is intended as a helper routine for isBlock() and * related routines. Despite its trivial implementation, it is * provided to make long blocks of code easier to read and * distinguish by functionality. * * @param test the tetrahedron pointer to test. * @param other1 another tetrahedron that will be compared with \a test. * @return \c true if \a test is null or equal to \a other1, * or \c false otherwise. */ static bool notUnique(NTetrahedron* test, NTetrahedron* other1); /** * Determines whether the given tetrahedron pointer is null * or equal to another from the given list. * * This is intended as a helper routine for isBlock() and * related routines. Despite its trivial implementation, it is * provided to make long blocks of code easier to read and * distinguish by functionality. * * @param test the tetrahedron pointer to test. * @param other1 another tetrahedron that will be compared with \a test. * @param other2 another tetrahedron that will be compared with \a test. * @return \c true if \a test is null or equal to \a other1 or * \a other2, or \c false otherwise. */ static bool notUnique(NTetrahedron* test, NTetrahedron* other1, NTetrahedron* other2); /** * Determines whether the given tetrahedron pointer is null * or equal to another from the given list. * * This is intended as a helper routine for isBlock() and * related routines. Despite its trivial implementation, it is * provided to make long blocks of code easier to read and * distinguish by functionality. * * @param test the tetrahedron pointer to test. * @param other1 another tetrahedron that will be compared with \a test. * @param other2 another tetrahedron that will be compared with \a test. * @param other3 another tetrahedron that will be compared with \a test. * @return \c true if \a test is null or equal to \a other1, * \a other2 or \a other3, or \c false otherwise. */ static bool notUnique(NTetrahedron* test, NTetrahedron* other1, NTetrahedron* other2, NTetrahedron* other3); /** * Determines whether the given tetrahedron pointer is null * or equal to another from the given list. * * This is intended as a helper routine for isBlock() and * related routines. Despite its trivial implementation, it is * provided to make long blocks of code easier to read and * distinguish by functionality. * * @param test the tetrahedron pointer to test. * @param other1 another tetrahedron that will be compared with \a test. * @param other2 another tetrahedron that will be compared with \a test. * @param other3 another tetrahedron that will be compared with \a test. * @param other4 another tetrahedron that will be compared with \a test. * @return \c true if \a test is null or equal to \a other1, * \a other2, \a other3 or \a other4, or \c false otherwise. */ static bool notUnique(NTetrahedron* test, NTetrahedron* other1, NTetrahedron* other2, NTetrahedron* other3, NTetrahedron* other4); }; /*@}*/ // Inline functions for NSatBlock inline NSatBlock::NSatBlock(unsigned nAnnuli, bool twistedBoundary) : nAnnuli_(nAnnuli), annulus_(new NSatAnnulus[nAnnuli]), twistedBoundary_(twistedBoundary), adjBlock_(new NSatBlock*[nAnnuli]), adjAnnulus_(new unsigned[nAnnuli]), adjReflected_(new bool[nAnnuli]), adjBackwards_(new bool[nAnnuli]) { for (unsigned i = 0; i < nAnnuli; i++) adjBlock_[i] = 0; } inline NSatBlock::~NSatBlock() { delete[] annulus_; delete[] adjBlock_; delete[] adjAnnulus_; delete[] adjReflected_; delete[] adjBackwards_; } inline unsigned NSatBlock::nAnnuli() const { return nAnnuli_; } inline const NSatAnnulus& NSatBlock::annulus(unsigned which) const { return annulus_[which]; } inline bool NSatBlock::twistedBoundary() const { return twistedBoundary_; } inline bool NSatBlock::hasAdjacentBlock(unsigned whichAnnulus) const { return (adjBlock_[whichAnnulus] != 0); } inline NSatBlock* NSatBlock::adjacentBlock(unsigned whichAnnulus) const { return adjBlock_[whichAnnulus]; } inline unsigned NSatBlock::adjacentAnnulus(unsigned whichAnnulus) const { return adjAnnulus_[whichAnnulus]; } inline bool NSatBlock::adjacentReflected(unsigned whichAnnulus) const { return adjReflected_[whichAnnulus]; } inline bool NSatBlock::adjacentBackwards(unsigned whichAnnulus) const { return adjBackwards_[whichAnnulus]; } inline void NSatBlock::setAdjacent(unsigned whichAnnulus, NSatBlock* adjBlock, unsigned adjAnnulus, bool adjReflected, bool adjBackwards) { adjBlock_[whichAnnulus] = adjBlock; adjAnnulus_[whichAnnulus] = adjAnnulus; adjReflected_[whichAnnulus] = adjReflected; adjBackwards_[whichAnnulus] = adjBackwards; adjBlock->adjBlock_[adjAnnulus] = this; adjBlock->adjAnnulus_[adjAnnulus] = whichAnnulus; adjBlock->adjReflected_[adjAnnulus] = adjReflected; adjBlock->adjBackwards_[adjAnnulus] = adjBackwards; } inline bool NSatBlock::notUnique(NTetrahedron* test) { return (test == 0); } inline bool NSatBlock::notUnique(NTetrahedron* test, NTetrahedron* other1) { return (test == 0 || test == other1); } inline bool NSatBlock::notUnique(NTetrahedron* test, NTetrahedron* other1, NTetrahedron* other2) { return (test == 0 || test == other1 || test == other2); } inline bool NSatBlock::notUnique(NTetrahedron* test, NTetrahedron* other1, NTetrahedron* other2, NTetrahedron* other3) { return (test == 0 || test == other1 || test == other2 || test == other3); } inline bool NSatBlock::notUnique(NTetrahedron* test, NTetrahedron* other1, NTetrahedron* other2, NTetrahedron* other3, NTetrahedron* other4) { return (test == 0 || test == other1 || test == other2 || test == other3 || test == other4); } } // namespace regina #endif regina-4.96/engine/subcomplex/nsatblockstarter.cpp000644 000765 000024 00000014732 12377776700 022356 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "subcomplex/nsatblockstarter.h" #include "subcomplex/nsatblocktypes.h" namespace regina { const NSatBlockStarterSet NSatBlockStarterSet::blocks; void NSatBlockStarterSet::initialise() { NSatBlockStarter* starter; starter = new NSatBlockStarter; starter->block_ = NSatTriPrism::insertBlock(starter->triangulation_, true); insert(starter); starter = new NSatBlockStarter; starter->block_ = NSatCube::insertBlock(starter->triangulation_); insert(starter); // Try various reflector strips of small length. starter = new NSatBlockStarter; starter->block_ = NSatReflectorStrip::insertBlock(starter->triangulation_, 1, false); insert(starter); starter = new NSatBlockStarter; starter->block_ = NSatReflectorStrip::insertBlock(starter->triangulation_, 1, true); insert(starter); starter = new NSatBlockStarter; starter->block_ = NSatReflectorStrip::insertBlock(starter->triangulation_, 2, false); insert(starter); starter = new NSatBlockStarter; starter->block_ = NSatReflectorStrip::insertBlock(starter->triangulation_, 2, true); insert(starter); starter = new NSatBlockStarter; starter->block_ = NSatReflectorStrip::insertBlock(starter->triangulation_, 3, false); insert(starter); starter = new NSatBlockStarter; starter->block_ = NSatReflectorStrip::insertBlock(starter->triangulation_, 3, true); insert(starter); starter = new NSatBlockStarter; starter->block_ = NSatReflectorStrip::insertBlock(starter->triangulation_, 4, false); insert(starter); starter = new NSatBlockStarter; starter->block_ = NSatReflectorStrip::insertBlock(starter->triangulation_, 4, true); insert(starter); } void NSatBlockStarterSearcher::findStarterBlocks(NTriangulation* tri) { // Clean up usedTets if required. if (! usedTets.empty()) usedTets.clear(); // Hunt for a starting block. unsigned long i; NSatBlockStarterSet::iterator it; std::list isos; std::list::iterator isoIt; NSatBlock* starter; for (it = NSatBlockStarterSet::begin(); it != NSatBlockStarterSet::end(); it++) { // Look for this particular starting block. // Get trivialities out of the way first. if (tri->isOrientable() && ! (*it)->triangulation().isOrientable()) continue; if (tri->getNumberOfTetrahedra() < (*it)->triangulation().getNumberOfTetrahedra()) continue; // Find all isomorphisms of the starter block within the given // triangulation. if (! (*it)->triangulation().findAllSubcomplexesIn(*tri, isos)) continue; // Run through each isomorphism in the list and see if it leads // somewhere useful. // // All of the isomorphisms in this list _must_ be destroyed at // some point before we loop back to the next starter block. for (isoIt = isos.begin(); isoIt != isos.end(); isoIt++) { starter = (*it)->block()->clone(); starter->transform(&(*it)->triangulation(), *isoIt, tri); // Create an initial blacklist of tetrahedra consisting of // those in the isomorphic image of the initial starting block. for (i = 0; i < (*it)->triangulation().getNumberOfTetrahedra(); i++) usedTets.insert(tri->getTetrahedron((*isoIt)->tetImage(i))); // And process! // Note that useStarterBlock() passes ownership of the starter // block elsewhere. if (! useStarterBlock(starter)) { // The search ends now. // Don't forget to destroy all remaining isomorphisms. usedTets.clear(); while (isoIt != isos.end()) delete *isoIt++; return; } // Keep on searching. // Destroy this isomorphism and make things ready for the next one. usedTets.clear(); delete *isoIt; } // Make sure the list is empty again for the next time around. isos.clear(); } // Search over. Nothing here to see. } } // namespace regina regina-4.96/engine/subcomplex/nsatblockstarter.h000644 000765 000024 00000033361 12377775470 022025 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/nsatblockstarter.h * \brief Provides a hard-coded list of saturated blocks to use as starting * points for recognising larger Seifert fibred spaces. */ #ifndef __NSATBLOCKSTARTER_H #ifndef __DOXYGEN #define __NSATBLOCKSTARTER_H #endif #include "regina-core.h" #include "subcomplex/nsatblock.h" #include "triangulation/ntriangulation.h" #include "utilities/nlistoncall.h" namespace regina { /** * \weakgroup subcomplex * @{ */ /** * Contains a triangulation of a saturated block along with the * accompanying saturated block description. Different objects of this * class will correspond to different types of saturated block. * * This is a support class for NSatBlockStarterSet, and as such it is a * read-only class to the rest of the world. * * This class is well-suited for subcomplex testing: if the * triangulation here is found to be a subcomplex of some larger * triangulation (see NTriangulation::isContainedIn()), then the * corresponding isomorphism can be used to copy this block structure * and transform it to describe the corresponding block in the larger * triangulation. * * As such, one of the core uses of this class is as a starting point * for identifying regions within triangulations that are formed by * joining saturated blocks together along their boundary annuli. See * the routines NSatBlockStarterSearcher::findStarterBlocks() and * NSatRegion::expand() for implementations of this. * * \ifacespython Not present. */ class REGINA_API NSatBlockStarter : regina::boost::noncopyable { private: NTriangulation triangulation_; /**< The triangulation of the saturated block. */ NSatBlock* block_; /**< Structural details of the saturated block. */ public: /** * Destroys both the internal triangulation and block structure. */ ~NSatBlockStarter(); /** * Returns a reference to the triangulation of the saturated * block. * * @return the block triangulation. */ const NTriangulation& triangulation() const; /** * Returns details that describe the structure of the saturated * block. * * @return the block structure. */ const NSatBlock* block() const; private: /** * Creates a new starter block. The triangulation will be empty * and the block pointer set to null. * * The triangulation must be fleshed out and the block structure * created before this object can be used. */ NSatBlockStarter(); friend class NSatBlockStarterSet; }; /** * Represents a set of starter blocks that can be used for identifying * triangulations of Seifert fibred spaces. * * This class provides a list of saturated blocks that can be used as * starting points for recognising triangulations; see the * NSatBlockStarter class notes for details. * * More importantly, this list is global and hard-coded. The only * access to the list is through the static routines begin() and end(). * * Creating the list of starter blocks is expensive, and so this is not * done until the first time that begin() is called. This way, if the list * is never used then the work is never done. As a consequence however, * you must be sure to call begin() before calling end() (which is the * usual way in which iterator loops are structured in code). * * Be aware that this list makes no claims to be exhaustive; it is * expected to grow as future versions of Regina are released. * * \ifacespython Not present. */ class REGINA_API NSatBlockStarterSet : private NListOnCall { public: /** * An iterator over the starter blocks in this list. This operates * as a forward iterator in a manner consistent with the standard C++ * library. */ typedef NListOnCall::iterator iterator; private: static const NSatBlockStarterSet blocks; /**< The hard-coded list of starter blocks. */ public: /** * Returns an iterator pointing to the first block in the * hard-coded list. * * The very first time this routine is called, the list will be * filled with items (and as such the call will be expensive). * Every subsequent call will be very cheap. * * @return an iterator pointing to the first starter block. */ static iterator begin(); /** * Returns an iterator pointing past the end of the hard-coded list * (i.e., just after the last item). * * \pre The begin() routine has been called at least once. * * @return a past-the-end iterator. */ static iterator end(); protected: void initialise(); private: /** * Creates a new list of starter blocks. This routine is * private since the only list that should exist is the global * hard-coded list. */ NSatBlockStarterSet(); }; /** * A helper class for locating and using starter blocks within a * triangulation. * * This class provides a means for searching for each starter * block in the global hard-coded NSatBlockStarterSet within a * given triangulation. More specifically, given some triangulation \a t, * this class can locate every isomorphic embedding of every starter * block in the global NSatBlockStarterSet as a subcomplex of \a t (see * NTriangulation::isContainedIn() for what is meant by "isomorphic * embedding"). * * The routine findStarterBlocks() runs the search. Each time an * isomorphic embedding of a starter block is discovered within the * given triangulation, the pure virtual routine useStarterBlock() will * be called. The block that is passed to useStarterBlock() will be a * new block that refers to the particular embedding of the starter block * within the given triangulation (as opposed to the original block * structure referring to the prebuilt triangulation in NSatBlockStarter). * * For each situation that requires searching for starter blocks, a * subclass of NSatBlockStarterSearcher will be required. This subclass * should override useStarterBlock() to perform whatever action is * necessary. * * Instead of locating all isomorphic embeddings of all starter blocks * in the global set, the search can be made to finish early once * certain conditions are met. This is done by implementing * useStarterBlock() to return \c false when the search should quit. * * \ifacespython Not present. */ class REGINA_API NSatBlockStarterSearcher { protected: NSatBlock::TetList usedTets; /**< Keeps track of which tetrahedra have used by the current embedding of the current starter block. See useStarterBlock() for further details. */ public: /** * Destroys this object and its internal structures. */ virtual ~NSatBlockStarterSearcher(); /** * Runs a search for every isomorphic embedding of every * starter block from the global NSatBlockStarterSet within the * given triangulation. Each time an embedding is discovered, * the pure virtual routine useStarterBlock() will be called. * * See the NSatBlockStarterSearcher class notes for greater * detail on what this search does and how it runs. * * For subclasses that make use of the \a usedTets data member, * it is worth noting that this routine empties the \a usedTets * list on both entry and exit, as well as every time that * useStarterBlock() returns after each new embedding is found. * * @param tri the triangulation in which to search for starter * blocks. */ void findStarterBlocks(NTriangulation* tri); protected: /** * Used by subclasses to process each starter block embedding that * is found. * * Suppose that the main search routine findStarterBlocks() has * been called with some triangulation \a t. Each time it * locates an isomorphic embedding of a starter block within \a t, * it will call useStarterBlock(). Subclasses of * NSatBlockStarterSearcher should therefore override * useStarterBlock() to process each embedding in whatever way * is appropriate for the problem at hand. * * The block passed in the argument \a starter is a newly * created structure describing the starter block as it appears * within the triangulation \a t. Thus different embeddings of * the same starter block within \a t will pass different * \a starter arguments to this routine. * It is the responsibility of useStarterBlock() to either * destroy the new block \a starter or pass ownership of it * elsewhere. * * When this routine is called, the data member \a usedTets * will contain a list of all tetrahedra from the triangulation * \a t that appear within the relevant starter block embedding. * The reimplementation of useStarterBlock() may modify this list * as it pleases, since the main search routine will empty the * list anyway when useStarterBlock() returns. One possible use * for the \a usedTets data member is for passing to * NSatBlock::isBlock() or NSatRegion::expand() as the list of * tetrahedra to avoid in further searches. * * This routine must return a boolean; this allows subclasses to * immediately terminate the main search once they have found * whatever it is they were looking for. A return value of * \c true signifies that the search should continue as normal, * whereas a return value of \c false signifies that the search * should end immediately (specifically, that findStarterBlocks() * should clean up and return before all remaining embeddings of all * starter blocks have been found). * * \warning Subclasses must remember to either destroy or claim * ownership of the newly created block \a starter. * * @param starter a newly created structure describing the * starter block as it appears within the larger triangulation * currently under examination. * @return \c true if the search for embeddings of starter blocks * should continue, or \c false if the search should stop immediately. */ virtual bool useStarterBlock(NSatBlock* starter) = 0; }; /*@}*/ // Inline functions for NSatBlockStarter inline NSatBlockStarter::NSatBlockStarter() : block_(0) { } inline NSatBlockStarter::~NSatBlockStarter() { if (block_) delete block_; } inline const NTriangulation& NSatBlockStarter::triangulation() const { return triangulation_; } inline const NSatBlock* NSatBlockStarter::block() const { return block_; } // Inline functions for NSatBlockStarterSet inline NSatBlockStarterSet::NSatBlockStarterSet() { } inline NSatBlockStarterSet::iterator NSatBlockStarterSet::begin() { return blocks.NListOnCall::begin(); } inline NSatBlockStarterSet::iterator NSatBlockStarterSet::end() { return blocks.NListOnCall::end(); } // Inline functions for NSatBlockStarterSearcher inline NSatBlockStarterSearcher::~NSatBlockStarterSearcher() { } } // namespace regina #endif regina-4.96/engine/subcomplex/nsatblocktypes.cpp000644 000765 000024 00000077443 12377776701 022047 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "manifold/nsfs.h" #include "subcomplex/nsatblocktypes.h" #include "subcomplex/nlayeredsolidtorus.h" #include "triangulation/nedge.h" #include "triangulation/nfacepair.h" #include "triangulation/ntetrahedron.h" #include "triangulation/ntriangulation.h" #include #include // For exit(). #include #include namespace regina { bool NSatBlock::operator < (const NSatBlock& compare) const { const NSatTriPrism* tri1 = dynamic_cast(this); const NSatTriPrism* tri2 = dynamic_cast(&compare); if (tri1 && ! tri2) return true; if (tri2 && ! tri1) return false; if (tri1 && tri2) { // Major first, then minor. return (tri1->isMajor() && ! tri2->isMajor()); } const NSatCube* cube1 = dynamic_cast(this); const NSatCube* cube2 = dynamic_cast(&compare); if (cube1 && ! cube2) return true; if (cube2 && ! cube1) return false; if (cube1 && cube2) { // All cubes are considered equal. return false; } const NSatReflectorStrip* ref1 = dynamic_cast(this); const NSatReflectorStrip* ref2 = dynamic_cast(&compare); if (ref1 && ! ref2) return true; if (ref2 && ! ref1) return false; if (ref1 && ref2) { // Always put untwisted before twisted. if (ref1->twistedBoundary() && ! ref2->twistedBoundary()) return false; if (ref2->twistedBoundary() && ! ref1->twistedBoundary()) return true; return (ref1->nAnnuli() < ref2->nAnnuli()); } const NSatLST* lst1 = dynamic_cast(this); const NSatLST* lst2 = dynamic_cast(&compare); if (lst1 && ! lst2) return true; if (lst2 && ! lst1) return false; if (lst1 && lst2) { // Order first by LST parameters, then by roles. if (lst1->lst()->getMeridinalCuts(2) < lst2->lst()->getMeridinalCuts(2)) return true; if (lst1->lst()->getMeridinalCuts(2) > lst2->lst()->getMeridinalCuts(2)) return false; if (lst1->lst()->getMeridinalCuts(1) < lst2->lst()->getMeridinalCuts(1)) return true; if (lst1->lst()->getMeridinalCuts(1) > lst2->lst()->getMeridinalCuts(1)) return false; if (lst1->lst()->getMeridinalCuts(0) < lst2->lst()->getMeridinalCuts(0)) return true; if (lst1->lst()->getMeridinalCuts(0) > lst2->lst()->getMeridinalCuts(0)) return false; // Sorts by which edge group is joined to the vertical annulus // edges, then horizontal, then diagonal (though we won't bother // testing diagonal, since by that stage we will know the roles // permutations to be equal). if (lst1->roles()[0] < lst2->roles()[0]) return true; if (lst1->roles()[0] > lst2->roles()[0]) return false; if (lst1->roles()[1] < lst2->roles()[1]) return true; if (lst1->roles()[1] > lst2->roles()[1]) return false; // All equal. return false; } const NSatMobius* mob1 = dynamic_cast(this); const NSatMobius* mob2 = dynamic_cast(&compare); if (mob1 && ! mob2) return true; if (mob2 && ! mob1) return false; if (mob1 && mob2) { // Order by position in descending order (vertical first, then // horizontal, then finally diagonal). return (mob1->position() > mob2->position()); } const NSatLayering* layer1 = dynamic_cast(this); const NSatLayering* layer2 = dynamic_cast(&compare); if (layer1 && ! layer2) return true; if (layer2 && ! layer1) return false; if (layer1 && layer2) { // Horizontal, then diagonal. return (layer1->overHorizontal() && ! layer2->overHorizontal()); } return false; } NSatBlock* NSatBlock::isBlock(const NSatAnnulus& annulus, TetList& avoidTets) { NSatBlock* ans; // Run through the types of blocks that we know about. if ((ans = NSatMobius::isBlockMobius(annulus, avoidTets))) return ans; if ((ans = NSatLST::isBlockLST(annulus, avoidTets))) return ans; if ((ans = NSatTriPrism::isBlockTriPrism(annulus, avoidTets))) return ans; if ((ans = NSatCube::isBlockCube(annulus, avoidTets))) return ans; if ((ans = NSatReflectorStrip::isBlockReflectorStrip(annulus, avoidTets))) return ans; // As a last attempt, try a single layering. We don't have to worry // about the degeneracy, since we'll never get a loop of these // things (since that would form a disconnected component, and we // never use one as a starting block). if ((ans = NSatLayering::isBlockLayering(annulus, avoidTets))) return ans; // Nothing was found. return 0; } void NSatMobius::adjustSFS(NSFSpace& sfs, bool reflect) const { if (position_ == 0) { // Diagonal: sfs.insertFibre(1, reflect ? 1 : -1); } else if (position_ == 1) { // Horizontal: sfs.insertFibre(1, reflect ? -2 : 2); } else { // Vertical: sfs.insertFibre(2, reflect ? -1 : 1); } } void NSatMobius::writeTextShort(std::ostream& out) const { out << "Saturated Mobius band, boundary on "; if (position_ == 0) out << "diagonal"; else if (position_ == 1) out << "horizontal"; else if (position_ == 2) out << "vertical"; else out << "invalid"; out << " edge"; } void NSatMobius::writeAbbr(std::ostream& out, bool tex) const { out << (tex ? "M_" : "Mob("); if (position_ == 0) out << 'd'; else if (position_ == 1) out << 'h'; else if (position_ == 2) out << 'v'; if (! tex) out << ')'; } NSatMobius* NSatMobius::isBlockMobius(const NSatAnnulus& annulus, TetList&) { // The two tetrahedra must be joined together along the annulus triangles. if (annulus.tet[0]->adjacentTetrahedron(annulus.roles[0][3]) != annulus.tet[1]) return 0; NPerm4 annulusGluing = annulus.roles[1].inverse() * annulus.tet[0]->adjacentGluing(annulus.roles[0][3]) * annulus.roles[0]; if (annulusGluing[3] != 3) return 0; // The triangles are glued together. Is it one of the allowable // (orientable) permutations? int position = -1; if (annulusGluing == NPerm4(0, 1)) position = 2; // Vertical else if (annulusGluing == NPerm4(0, 2)) position = 1; // Horizontal else if (annulusGluing == NPerm4(1, 2)) position = 0; // Diagonal if (position < 0) { // Nope. It must be a non-orientable permutation. return 0; } // Got it! NSatMobius* ans = new NSatMobius(position); ans->annulus_[0] = annulus; return ans; } NSatLST::NSatLST(const NSatLST& cloneMe) : NSatBlock(cloneMe), lst_(cloneMe.lst_->clone()), roles_(cloneMe.roles_) { } NSatLST::~NSatLST() { delete lst_; } void NSatLST::adjustSFS(NSFSpace& sfs, bool reflect) const { long cutsVert = lst_->getMeridinalCuts(roles_[0]); long cutsHoriz = lst_->getMeridinalCuts(roles_[1]); if (roles_[2] == 2) { // Most cuts are on the diagonal, which means the meridinal // curve is negative. cutsHoriz = -cutsHoriz; } sfs.insertFibre(cutsVert, reflect ? -cutsHoriz : cutsHoriz); } void NSatLST::writeTextShort(std::ostream& out) const { out << "Saturated (" << lst_->getMeridinalCuts(0) << ", " << lst_->getMeridinalCuts(1) << ", " << lst_->getMeridinalCuts(2) << ") layered solid torus"; } void NSatLST::writeAbbr(std::ostream& out, bool tex) const { out << (tex ? "\\mathrm{LST}_{" : "LST(") << lst_->getMeridinalCuts(0) << ", " << lst_->getMeridinalCuts(1) << ", " << lst_->getMeridinalCuts(2) << (tex ? '}' : ')'); } void NSatLST::transform(const NTriangulation* originalTri, const NIsomorphism* iso, NTriangulation* newTri) { // Start with the parent implementation. NSatBlock::transform(originalTri, iso, newTri); // Transform the layered solid torus also. lst_->transform(originalTri, iso, newTri); } NSatLST* NSatLST::isBlockLST(const NSatAnnulus& annulus, TetList& avoidTets) { // Do we move to a common usable tetrahedron? if (annulus.tet[0] != annulus.tet[1]) return 0; if (isBad(annulus.tet[0], avoidTets)) return 0; // Is it a layering? // Here we find the endpoints of the edge from which the two layered // triangles fold out. NFacePair centralEdge = NFacePair(annulus.roles[0][3], annulus.roles[1][3]).complement(); if (annulus.roles[1] != NPerm4(annulus.roles[0][3], annulus.roles[1][3]) * NPerm4(centralEdge.upper(), centralEdge.lower()) * annulus.roles[0]) return 0; // Find the layered solid torus. NLayeredSolidTorus* lst = NLayeredSolidTorus::formsLayeredSolidTorusTop( annulus.tet[0], annulus.roles[0][3], annulus.roles[1][3]); if (! lst) return 0; // Make sure we're not about to create a (0,k) curve. NPerm4 lstRoles( lst->getTopEdgeGroup( NEdge::edgeNumber[annulus.roles[0][0]][annulus.roles[0][1]]), lst->getTopEdgeGroup( NEdge::edgeNumber[annulus.roles[0][0]][annulus.roles[0][2]]), lst->getTopEdgeGroup( NEdge::edgeNumber[annulus.roles[0][1]][annulus.roles[0][2]]), 3); if (lst->getMeridinalCuts(lstRoles[0]) == 0) return 0; // Make two runs through the full set of tetrahedra. // The first run verifies that each tetrahedron is usable. // The second run inserts the tetrahedra into avoidTets. NTetrahedron* current = annulus.tet[0]; NFacePair currPair = centralEdge; NFacePair nextPair; while (current != lst->getBase()) { // INV: The current tetrahedron is usable. // INV: The next two faces to push through are in currPair. // Push through to the next tetrahedron. nextPair = NFacePair( current->adjacentFace(currPair.upper()), current->adjacentFace(currPair.lower()) ).complement(); current = current->adjacentTetrahedron(currPair.upper()); currPair = nextPair; // Make sure this next tetrahedron is usable. if (isBad(current, avoidTets)) return 0; } // All good! current = annulus.tet[0]; currPair = centralEdge; avoidTets.insert(current); while (current != lst->getBase()) { // INV: All tetrahedra up to and including current have been added. // INV: The next two faces to push through are in currPair. // Push through to the next tetrahedron. nextPair = NFacePair( current->adjacentFace(currPair.upper()), current->adjacentFace(currPair.lower()) ).complement(); current = current->adjacentTetrahedron(currPair.upper()); currPair = nextPair; // Add this next tetrahedron to the list. avoidTets.insert(current); } NSatLST* ans = new NSatLST(lst, lstRoles); ans->annulus_[0] = annulus; return ans; } void NSatTriPrism::adjustSFS(NSFSpace& sfs, bool reflect) const { if (major_) sfs.insertFibre(1, reflect ? -1 : 1); else sfs.insertFibre(1, reflect ? -2 : 2); } NSatTriPrism* NSatTriPrism::isBlockTriPrism(const NSatAnnulus& annulus, TetList& avoidTets) { NSatTriPrism* ans; // First try for one of major type. if ((ans = isBlockTriPrismMajor(annulus, avoidTets))) return ans; // Now try the reflected version. NSatAnnulus altAnnulus = annulus.verticalReflection(); if ((ans = isBlockTriPrismMajor(altAnnulus, avoidTets))) { // Reflect it back again but mark it as a minor variant. ans->major_ = false; ans->annulus_[0].reflectVertical(); ans->annulus_[1].reflectVertical(); ans->annulus_[2].reflectVertical(); return ans; } // Neither variant was found. return 0; } NSatTriPrism* NSatTriPrism::isBlockTriPrismMajor(const NSatAnnulus& annulus, TetList& avoidTets) { if (annulus.tet[0] == annulus.tet[1]) return 0; if (isBad(annulus.tet[0], avoidTets) || isBad(annulus.tet[1], avoidTets)) return 0; if (annulus.tet[0]->adjacentTetrahedron(annulus.roles[0][0]) != annulus.tet[1]) return 0; if (annulus.tet[0]->adjacentGluing(annulus.roles[0][0]) * annulus.roles[0] * NPerm4(1, 2) != annulus.roles[1]) return 0; // The two tetrahedra forming the annulus are joined together as // expected. Look for the third tetrahedron. NTetrahedron* adj = annulus.tet[0]->adjacentTetrahedron( annulus.roles[0][1]); if (adj == 0 || adj == annulus.tet[0] || adj == annulus.tet[1]) return 0; if (isBad(adj, avoidTets)) return 0; NPerm4 adjRoles = annulus.tet[0]->adjacentGluing(annulus.roles[0][1]) * annulus.roles[0] * NPerm4(0, 3); if (annulus.tet[1]->adjacentTetrahedron(annulus.roles[1][1]) != adj) return 0; if (annulus.tet[1]->adjacentGluing(annulus.roles[1][1]) * annulus.roles[1] * NPerm4(1, 3, 0, 2) != adjRoles) return 0; // All three tetrahedra are joined together as expected! NSatTriPrism* ans = new NSatTriPrism(true); const NPerm4 pairSwap(1, 0, 3, 2); ans->annulus_[0] = annulus; ans->annulus_[1].tet[0] = annulus.tet[1]; ans->annulus_[1].tet[1] = adj; ans->annulus_[1].roles[0] = annulus.roles[1] * pairSwap; ans->annulus_[1].roles[1] = adjRoles; ans->annulus_[2].tet[0] = adj; ans->annulus_[2].tet[1] = annulus.tet[0]; ans->annulus_[2].roles[0] = adjRoles * pairSwap; ans->annulus_[2].roles[1] = annulus.roles[0] * pairSwap; avoidTets.insert(annulus.tet[0]); avoidTets.insert(annulus.tet[1]); avoidTets.insert(adj); return ans; } NSatTriPrism* NSatTriPrism::insertBlock(NTriangulation& tri, bool major) { NTetrahedron* a = tri.newTetrahedron(); NTetrahedron* b = tri.newTetrahedron(); NTetrahedron* c = tri.newTetrahedron(); a->joinTo(1, c, NPerm4(2, 0, 3, 1)); b->joinTo(1, a, NPerm4(2, 0, 3, 1)); c->joinTo(1, b, NPerm4(2, 0, 3, 1)); NSatTriPrism* ans = new NSatTriPrism(major); const NPerm4 id; const NPerm4 pairSwap(1, 0, 3, 2); ans->annulus_[0].tet[0] = a; ans->annulus_[0].tet[1] = b; ans->annulus_[0].roles[0] = id; ans->annulus_[0].roles[1] = pairSwap; ans->annulus_[1].tet[0] = b; ans->annulus_[1].tet[1] = c; ans->annulus_[1].roles[0] = id; ans->annulus_[1].roles[1] = pairSwap; ans->annulus_[2].tet[0] = c; ans->annulus_[2].tet[1] = a; ans->annulus_[2].roles[0] = id; ans->annulus_[2].roles[1] = pairSwap; if (! major) { ans->annulus_[0].reflectVertical(); ans->annulus_[1].reflectVertical(); ans->annulus_[2].reflectVertical(); } return ans; } void NSatCube::adjustSFS(NSFSpace& sfs, bool reflect) const { sfs.insertFibre(1, reflect ? -2 : 2); } NSatCube* NSatCube::isBlockCube(const NSatAnnulus& annulus, TetList& avoidTets) { if (annulus.tet[0] == annulus.tet[1]) return 0; if (isBad(annulus.tet[0], avoidTets) || isBad(annulus.tet[1], avoidTets)) return 0; NTetrahedron* central0 = annulus.tet[0]->adjacentTetrahedron( annulus.roles[0][0]); NTetrahedron* central1 = annulus.tet[0]->adjacentTetrahedron( annulus.roles[0][1]); if (central0 == 0 || central0 == annulus.tet[0] || central0 == annulus.tet[1] || isBad(central0, avoidTets)) return 0; if (central1 == 0 || central1 == annulus.tet[0] || central1 == annulus.tet[1] || central1 == central0 || isBad(central0, avoidTets)) return 0; NPerm4 roles0 = annulus.tet[0]->adjacentGluing( annulus.roles[0][0]) * annulus.roles[0]; NPerm4 roles1 = annulus.tet[0]->adjacentGluing( annulus.roles[0][1]) * annulus.roles[0]; // We've got the two central tetrahedra. Now look for the remaining // three boundary tetrahedra. if (annulus.tet[1]->adjacentTetrahedron(annulus.roles[1][0]) != central0) return 0; if (annulus.tet[1]->adjacentTetrahedron(annulus.roles[1][1]) != central1) return 0; if (annulus.tet[1]->adjacentGluing(annulus.roles[1][0]) * annulus.roles[1] * NPerm4(3, 2, 1, 0) != roles0) return 0; if (annulus.tet[1]->adjacentGluing(annulus.roles[1][1]) * annulus.roles[1] * NPerm4(2, 3, 0, 1) != roles1) return 0; // We've got the two tetrahedra from the annulus boundary completely // sorted out. Just the two new boundary tetrahedra to go. NTetrahedron* bdry2 = central0->adjacentTetrahedron(roles0[1]); NPerm4 roles2 = central0->adjacentGluing(roles0[1]) * roles0; NTetrahedron* bdry3 = central0->adjacentTetrahedron(roles0[2]); NPerm4 roles3 = central0->adjacentGluing(roles0[2]) * roles0; if (bdry2 == 0 || bdry2 == annulus.tet[0] || bdry2 == annulus.tet[1] || bdry2 == central0 || bdry2 == central1 || isBad(bdry2, avoidTets)) return 0; if (bdry3 == 0 || bdry3 == annulus.tet[0] || bdry3 == annulus.tet[1] || bdry3 == central0 || bdry3 == central1 || bdry3 == bdry2 || isBad(bdry3, avoidTets)) return 0; if (central1->adjacentTetrahedron(roles1[0]) != bdry2) return 0; if (central1->adjacentTetrahedron(roles1[2]) != bdry3) return 0; if (central1->adjacentGluing(roles1[0]) * roles1 != roles2) return 0; if (central1->adjacentGluing(roles1[2]) * roles1 * NPerm4(1, 0, 3, 2) != roles3) return 0; // All looking good! NSatCube* ans = new NSatCube(); const NPerm4 id; ans->annulus_[0] = annulus; ans->annulus_[1].tet[0] = annulus.tet[1]; ans->annulus_[1].tet[1] = bdry2; ans->annulus_[1].roles[0] = annulus.roles[1] * NPerm4(1, 0, 3, 2); ans->annulus_[1].roles[1] = roles2; ans->annulus_[2].tet[0] = bdry2; ans->annulus_[2].tet[1] = bdry3; ans->annulus_[2].roles[0] = roles2 * NPerm4(1, 0, 3, 2); ans->annulus_[2].roles[1] = roles3 * NPerm4(2, 3, 0, 1); ans->annulus_[3].tet[0] = bdry3; ans->annulus_[3].tet[1] = annulus.tet[0]; ans->annulus_[3].roles[0] = roles3 * NPerm4(3, 2, 1, 0); ans->annulus_[3].roles[1] = annulus.roles[0] * NPerm4(1, 0, 3, 2); avoidTets.insert(annulus.tet[0]); avoidTets.insert(annulus.tet[1]); avoidTets.insert(bdry2); avoidTets.insert(bdry3); avoidTets.insert(central0); avoidTets.insert(central1); return ans; } NSatCube* NSatCube::insertBlock(NTriangulation& tri) { NTetrahedron* bdry0 = tri.newTetrahedron(); NTetrahedron* bdry1 = tri.newTetrahedron(); NTetrahedron* bdry2 = tri.newTetrahedron(); NTetrahedron* bdry3 = tri.newTetrahedron(); NTetrahedron* central0 = tri.newTetrahedron(); NTetrahedron* central1 = tri.newTetrahedron(); const NPerm4 id; bdry0->joinTo(1, central0, id); bdry0->joinTo(0, central1, NPerm4(0, 1)); bdry1->joinTo(2, central0, NPerm4(2, 1, 3, 0)); bdry1->joinTo(0, central1, NPerm4(0, 3)); bdry2->joinTo(0, central0, id); bdry2->joinTo(1, central1, NPerm4(0, 1)); bdry3->joinTo(3, central0, NPerm4(0, 3, 1, 2)); bdry3->joinTo(1, central1, NPerm4(1, 2)); NSatCube* ans = new NSatCube(); ans->annulus_[0].tet[0] = bdry0; ans->annulus_[0].tet[1] = bdry1; ans->annulus_[1].tet[0] = bdry1; ans->annulus_[1].tet[1] = bdry2; ans->annulus_[2].tet[0] = bdry2; ans->annulus_[2].tet[1] = bdry3; ans->annulus_[3].tet[0] = bdry3; ans->annulus_[3].tet[1] = bdry0; ans->annulus_[0].roles[0] = NPerm4(0, 1); ans->annulus_[0].roles[1] = NPerm4(2, 0, 3, 1); ans->annulus_[1].roles[0] = NPerm4(1, 2); ans->annulus_[1].roles[1] = NPerm4(0, 1); ans->annulus_[2].roles[0] = NPerm4(2, 3); ans->annulus_[2].roles[1] = NPerm4(0, 3); ans->annulus_[3].roles[0] = NPerm4(1, 3, 0, 2); ans->annulus_[3].roles[1] = NPerm4(2, 3); return ans; } void NSatReflectorStrip::adjustSFS(NSFSpace& sfs, bool) const { if (! twistedBoundary_) sfs.addReflector(false); } NSatReflectorStrip* NSatReflectorStrip::isBlockReflectorStrip( const NSatAnnulus& annulus, TetList& avoidTets) { // Hunt for the initial segment of the reflector strip that lies // behind the given annulus. if (annulus.tet[0] == annulus.tet[1]) return 0; if (isBad(annulus.tet[0], avoidTets) || isBad(annulus.tet[1], avoidTets)) return 0; NTetrahedron* middle = annulus.tet[0]->adjacentTetrahedron( annulus.roles[0][0]); NPerm4 middleRoles = annulus.tet[0]->adjacentGluing( annulus.roles[0][0]) * annulus.roles[0] * NPerm4(3, 1, 0, 2); if (notUnique(middle, annulus.tet[0], annulus.tet[1]) || isBad(middle, avoidTets)) if (middle != annulus.tet[0]->adjacentTetrahedron( annulus.roles[0][1])) return 0; if (middle != annulus.tet[1]->adjacentTetrahedron( annulus.roles[1][0])) return 0; if (middle != annulus.tet[1]->adjacentTetrahedron( annulus.roles[1][1])) return 0; if (middleRoles != annulus.tet[0]->adjacentGluing( annulus.roles[0][1]) * annulus.roles[0] * NPerm4(1, 3)) return 0; if (middleRoles != annulus.tet[1]->adjacentGluing( annulus.roles[1][0]) * annulus.roles[1] * NPerm4(0, 2, 3, 1)) return 0; if (middleRoles != annulus.tet[1]->adjacentGluing( annulus.roles[1][1]) * annulus.roles[1] * NPerm4(0, 2)) return 0; // We've found the initial segment. // Do we just have a segment of length one? if (annulus.tet[0]->adjacentTetrahedron(annulus.roles[0][2]) == annulus.tet[1]) { // It's either length one or nothing. if (annulus.roles[1] == annulus.tet[0]->adjacentGluing( annulus.roles[0][2]) * annulus.roles[0] * NPerm4(0, 1)) { // Got one that's untwisted. NSatReflectorStrip* ans = new NSatReflectorStrip(1, false); ans->annulus_[0] = annulus; avoidTets.insert(annulus.tet[0]); avoidTets.insert(middle); avoidTets.insert(annulus.tet[1]); return ans; } if (annulus.roles[1] == annulus.tet[0]->adjacentGluing( annulus.roles[0][2]) * annulus.roles[0]) { // Got one that's twisted. NSatReflectorStrip* ans = new NSatReflectorStrip(1, true); ans->annulus_[0] = annulus; avoidTets.insert(annulus.tet[0]); avoidTets.insert(middle); avoidTets.insert(annulus.tet[1]); return ans; } // Nup. Nothing. return 0; } // If anything, we have a segment of length >= 2. Start following // it around. // Make a list storing the tetrahedra from left to right around the // boundary ring. We must use a list and not a set, since we will // rely on the tetrahedra being stored in a particular order. std::list foundSoFar; foundSoFar.push_back(annulus.tet[0]); foundSoFar.push_back(middle); foundSoFar.push_back(annulus.tet[1]); // Also make a list of tetrahedron vertex roles for the two // tetrahedra in each segment that meet the boundary annuli. std::list rolesSoFar; rolesSoFar.push_back(annulus.roles[0]); rolesSoFar.push_back(annulus.roles[1]); unsigned length = 1; bool twisted = false; NTetrahedron *nextLeft, *nextMiddle, *nextRight; NPerm4 nextLeftRoles, nextMiddleRoles, nextRightRoles; while (1) { // Run off the right hand side looking for the next tetrahedron. nextLeft = foundSoFar.back()->adjacentTetrahedron( rolesSoFar.back()[2]); nextLeftRoles = foundSoFar.back()->adjacentGluing( rolesSoFar.back()[2]) * rolesSoFar.back() * NPerm4(0, 1); if (nextLeft == annulus.tet[0]) { // The right _might_ have completed! if (nextLeftRoles == annulus.roles[0]) { // All good! An untwisted strip. } else if (nextLeftRoles == annulus.roles[0] * NPerm4(0, 1)) { // A complete twisted strip. twisted = true; } else { // Nothing. return 0; } NSatReflectorStrip* ans = new NSatReflectorStrip(length, twisted); std::copy(foundSoFar.begin(), foundSoFar.end(), std::inserter(avoidTets, avoidTets.begin())); std::list::const_iterator tit = foundSoFar.begin(); std::list::const_iterator pit = rolesSoFar.begin(); for (unsigned i = 0; i < length; i++) { ans->annulus_[i].tet[0] = *tit++; tit++; // Skip the middle tetrahedron from each block. ans->annulus_[i].tet[1] = *tit++; ans->annulus_[i].roles[0] = *pit++; ans->annulus_[i].roles[1] = *pit++; } return ans; } // Look for a new adjacent block. if (notUnique(nextLeft) || isBad(nextLeft, avoidTets) || isBad(nextLeft, foundSoFar)) return 0; nextMiddle = nextLeft->adjacentTetrahedron(nextLeftRoles[0]); nextMiddleRoles = nextLeft->adjacentGluing( nextLeftRoles[0]) * nextLeftRoles * NPerm4(3, 1, 0, 2); if (notUnique(nextMiddle, nextLeft) || isBad(nextMiddle, avoidTets) || isBad(nextMiddle, foundSoFar)) return 0; if (nextMiddle != nextLeft->adjacentTetrahedron(nextLeftRoles[1])) return 0; if (nextMiddleRoles != nextLeft->adjacentGluing( nextLeftRoles[1]) * nextLeftRoles * NPerm4(1, 3)) return 0; nextRight = nextMiddle->adjacentTetrahedron(nextMiddleRoles[0]); nextRightRoles = nextMiddle->adjacentGluing( nextMiddleRoles[0]) * nextMiddleRoles * NPerm4(0, 3, 1, 2); if (notUnique(nextRight, nextLeft, nextMiddle) || isBad(nextRight, avoidTets) || isBad(nextRight, foundSoFar)) return 0; if (nextRight != nextMiddle->adjacentTetrahedron(nextMiddleRoles[1])) return 0; if (nextRightRoles != nextMiddle->adjacentGluing( nextMiddleRoles[1]) * nextMiddleRoles * NPerm4(0, 2)) return 0; // Yup, we have a new block. foundSoFar.push_back(nextLeft); foundSoFar.push_back(nextMiddle); foundSoFar.push_back(nextRight); rolesSoFar.push_back(nextLeftRoles); rolesSoFar.push_back(nextRightRoles); length++; } // We should never get out of the loop this way. return 0; } NSatReflectorStrip* NSatReflectorStrip::insertBlock(NTriangulation& tri, unsigned length, bool twisted) { NSatReflectorStrip* ans = new NSatReflectorStrip(length, twisted); const NPerm4 id; NTetrahedron *upper, *lower, *middle; NTetrahedron *prevRight = 0, *firstLeft = 0; for (unsigned i = 0; i < length; i++) { // Create the three tetrahedra behind boundary annulus #i. upper = tri.newTetrahedron(); lower = tri.newTetrahedron(); middle = tri.newTetrahedron(); upper->joinTo(0, middle, NPerm4(2, 1, 3, 0)); lower->joinTo(0, middle, NPerm4(0, 3, 1, 2)); upper->joinTo(1, middle, NPerm4(1, 3)); lower->joinTo(1, middle, NPerm4(0, 2)); if (i == 0) firstLeft = upper; else upper->joinTo(2, prevRight, NPerm4(0, 1)); prevRight = lower; ans->annulus_[i].tet[0] = upper; ans->annulus_[i].tet[1] = lower; ans->annulus_[i].roles[0] = id; ans->annulus_[i].roles[1] = id; } if (twisted) firstLeft->joinTo(2, prevRight, id); else firstLeft->joinTo(2, prevRight, NPerm4(0, 1)); return ans; } void NSatLayering::adjustSFS(NSFSpace& sfs, bool reflect) const { if (overHorizontal_) sfs.insertFibre(1, reflect ? -2 : 2); // Over the diagonal, there is no change at all. } NSatLayering* NSatLayering::isBlockLayering(const NSatAnnulus& annulus, TetList& avoidTets) { // Must be a common usable tetrahedron. if (annulus.tet[0] != annulus.tet[1]) return 0; if (isBad(annulus.tet[0], avoidTets)) return 0; // Is it a layering over the horizontal edge? if (annulus.roles[0][0] == annulus.roles[1][2] && annulus.roles[0][2] == annulus.roles[1][0]) { avoidTets.insert(annulus.tet[0]); NSatLayering* ans = new NSatLayering(true); ans->annulus_[0] = annulus; ans->annulus_[1].tet[0] = ans->annulus_[1].tet[1] = annulus.tet[0]; ans->annulus_[1].roles[0] = annulus.roles[1] * NPerm4(1, 0, 3, 2); ans->annulus_[1].roles[1] = annulus.roles[0] * NPerm4(1, 0, 3, 2); return ans; } // Is it a layering over the diagonal edge? if (annulus.roles[0][1] == annulus.roles[1][2] && annulus.roles[0][2] == annulus.roles[1][1]) { avoidTets.insert(annulus.tet[0]); NSatLayering* ans = new NSatLayering(false); ans->annulus_[0] = annulus; ans->annulus_[1].tet[0] = ans->annulus_[1].tet[1] = annulus.tet[0]; ans->annulus_[1].roles[0] = annulus.roles[1] * NPerm4(1, 0, 3, 2); ans->annulus_[1].roles[1] = annulus.roles[0] * NPerm4(1, 0, 3, 2); return ans; } // No layering. return 0; } } // namespace regina regina-4.96/engine/subcomplex/nsatblocktypes.h000644 000765 000024 00000070253 12377775471 021507 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/nsatblocktypes.h * \brief Describes several types of saturated blocks within Seifert fibred * space triangulations. */ #ifndef __NSATBLOCKTYPES_H #ifndef __DOXYGEN #define __NSATBLOCKTYPES_H #endif #include "regina-core.h" #include "subcomplex/nsatblock.h" namespace regina { class NLayeredSolidTorus; /** * \weakgroup subcomplex * @{ */ /** * A degenerate zero-tetrahedron saturated block that corresponds to * attaching a Mobius band to a single annulus boundary. * * This is a degenerate case of the layered solid torus (see the class * NSatLST), where instead of joining a solid torus to an annulus * boundary we join a Mobius band. The Mobius band can be thought of as * a zero-tetrahedron solid torus with two boundary triangles, which in fact * are opposite sides of the same triangle. By attaching a zero-tetrahedron * Mobius band to an annulus boundary, we are effectively joining the * two triangles of the annulus together. * * The meridinal disc of this zero-tetrahedron solid torus meets the * three edges of the annulus in 1, 1 and 2 places, so it is in fact * a degenerate (1,1,2) layered solid torus. Note that the weight 2 edge * is the boundary edge of the Mobius strip. */ class REGINA_API NSatMobius : public NSatBlock { private: int position_; /**< Describes how the Mobius band is attached to the boundary annulus. This can take the value 0, 1 or 2. See the position() documentation for further details. */ public: /** * Constructs a clone of the given block structure. * * @param cloneMe the block structure to clone. */ NSatMobius(const NSatMobius& cloneMe); /** * Describes how the Mobius band is attached to the * boundary annulus. * * The class notes discuss the weight two edge of the Mobius band * (or equivalently the boundary edge of the Mobius band). The * return value of this routine indicates which edge of the * boundary annulus this weight two edge is joined to. * * In the NSatAnnulus class notes, the three edges of the * annulus are denoted vertical, horizontal and boundary, and * the vertices of each triangle are given markings 0, 1 and 2. * * The return value of this routine takes the value 0, 1 or 2 as * follows: * - 0 means that the weight two edge is joined to the diagonal * edge of the annulus (markings 1 and 2); * - 1 means that the weight two edge is joined to the horizontal * edge of the annulus (markings 0 and 2); * - 2 means that the weight two edge is joined to the vertical * edge of the annulus (markings 0 and 1). * * @return the value 0, 1 or 2 as described above. */ int position() const; virtual NSatBlock* clone() const; virtual void adjustSFS(NSFSpace& sfs, bool reflect) const; virtual void writeTextShort(std::ostream& out) const; virtual void writeAbbr(std::ostream& out, bool tex = false) const; /** * Determines whether the given annulus is a boundary annulus for * a block of this type (Mobius band). This routine is * a specific case of NSatBlock::isBlock(); see that routine for * further details. * * @param annulus the proposed boundary annulus that should form * part of the new saturated block. * @param avoidTets the list of tetrahedra that should not be * considered, and to which any new tetrahedra will be added. * @return details of the saturated block if one was found, or * \c null if none was found. */ static NSatMobius* isBlockMobius(const NSatAnnulus& annulus, TetList& avoidTets); private: /** * Constructs a partially initialised block. The boundary * annulus will remain uninitialised, and must be initialised * before this block can be used. * * @param position indicates which edge of the boundary annulus * meets the weight two edge of the Mobius strip, as described in * the position() member function documentation. This value * must be 0, 1 or 2. */ NSatMobius(int position); }; /** * A saturated block that is a layered solid torus. See the * NLayeredSolidTorus class for details. * * The three boundary edges of the layered solid torus are attached to * the vertical, horizontal and diagonal edges of the boundary annulus; * see the NSatAnnulus class notes for details on precisely what * vertical, horizontal and diagonal mean. */ class REGINA_API NSatLST : public NSatBlock { private: NLayeredSolidTorus* lst_; /**< Contains details of the layered solid torus that this block represents. */ NPerm4 roles_; /**< Describes how the layered solid torus is attached to the boundary annulus. In particular, edge groups \a roles_[0], \a roles_[1] and \a roles_[2] of the layered solid torus are attached to the vertical, horizontal and diagonal edges of the annulus respectively. */ public: /** * Constructs a clone of the given block structure. * * @param cloneMe the block structure to clone. */ NSatLST(const NSatLST& cloneMe); /** * Destroys this structure and its internal components. */ ~NSatLST(); /** * Returns details of the layered solid torus that this block * represents. * * @return details of the layered solid torus. */ const NLayeredSolidTorus* lst() const; /** * Describes how the layered solid torus is attached to the * boundary annulus. * * The NLayeredSolidTorus class notes describe top-level edge * groups 0, 1 and 2 for a layered solid torus. On the other * hand, the NSatAnnulus class notes define vertical, horizontal * and diagonal edges on the boundary annulus. * * Suppose that the permutation returned by this routine is \a r. * This indicates that: * - edge group \a r[0] is attached to the vertical annulus edges; * - edge group \a r[1] is attached to the horizontal annulus edges; * - edge group \a r[2] is attached to the diagonal annulus edges. * * The image \a r[3] will always be 3. * * @return a description of how the layered solid torus is * attached to the boundary annulus. */ NPerm4 roles() const; virtual NSatBlock* clone() const; virtual void adjustSFS(NSFSpace& sfs, bool reflect) const; virtual void transform(const NTriangulation* originalTri, const NIsomorphism* iso, NTriangulation* newTri); virtual void writeTextShort(std::ostream& out) const; virtual void writeAbbr(std::ostream& out, bool tex = false) const; /** * Determines whether the given annulus is a boundary annulus for * a block of this type (layered solid torus). This routine is * a specific case of NSatBlock::isBlock(); see that routine for * further details. * * @param annulus the proposed boundary annulus that should form * part of the new saturated block. * @param avoidTets the list of tetrahedra that should not be * considered, and to which any new tetrahedra will be added. * @return details of the saturated block if one was found, or * \c null if none was found. */ static NSatLST* isBlockLST(const NSatAnnulus& annulus, TetList& avoidTets); private: /** * Constructs a partially initialised block. The boundary * annulus will remain uninitialised, and must be initialised * before this block can be used. * * @param lst details of the layered solid torus. * @param roles describes how the layered solid torus is * attached to the boundary annulus, as explained in the * \a roles_ data member documentation. */ NSatLST(NLayeredSolidTorus* lst, NPerm4 roles); }; /** * A saturated block that is a three-tetrahedron triangular prism. * * Such a prism may be of major type or of minor type. In a \e major * type prism, the horizontal edges of the boundary annuli are all * major (degree three) edges of the prism. Likewise, in a \e minor * type prism, the horizontal boundary edges are all minor (degree two) * edges of the prism. See the NSatAnnulus class notes for a definition * of "horizontal" and the NTriSolidTorus class notes for further * details regarding "major" and "minor". */ class REGINA_API NSatTriPrism : public NSatBlock { private: bool major_; /**< Is this prism of major type or of minor type? */ public: /** * Constructs a clone of the given block structure. * * @param cloneMe the block structure to clone. */ NSatTriPrism(const NSatTriPrism& cloneMe); /** * Is this prism of major type or minor type? See the class * notes for further details. * * Note that this routine cannot be called major(), since on * some compilers that name clashes with a macro for isolating * major/minor bytes. * * @return \c true if this prism is of major type, or \c false * if it is of minor type. */ bool isMajor() const; virtual NSatBlock* clone() const; virtual void adjustSFS(NSFSpace& sfs, bool reflect) const; virtual void writeTextShort(std::ostream& out) const; virtual void writeAbbr(std::ostream& out, bool tex = false) const; /** * Determines whether the given annulus is a boundary annulus for * a block of this type (triangular prism). This routine is * a specific case of NSatBlock::isBlock(); see that routine for * further details. * * @param annulus the proposed boundary annulus that should form * part of the new saturated block. * @param avoidTets the list of tetrahedra that should not be * considered, and to which any new tetrahedra will be added. * @return details of the saturated block if one was found, or * \c null if none was found. */ static NSatTriPrism* isBlockTriPrism(const NSatAnnulus& annulus, TetList& avoidTets); /** * Inserts a new copy of a triangular prism block into the given * triangulation, and returns the corresponding block structure. * * The given triangulation will not be emptied before the new * tetrahedra are inserted. * * @param tri the triangulation into which the new block should * be inserted. * @param major \c true if a block of major type should be inserted, * or \c false if a block of minor type should be inserted. * @return structural details of the newly inserted block. */ static NSatTriPrism* insertBlock(NTriangulation& tri, bool major); protected: /** * Constructs a partially initialised block. The boundary * annuli will remain uninitialised, and must be initialised * before this block can be used. * * @param major \c true if this block is of major type, or * \c false if it is of minor type. */ NSatTriPrism(bool major); private: /** * Implements a special case of isBlockTriPrism() to search for * a block of major type. See isBlockTriPrism() for further details. * * @param annulus the proposed boundary annulus that should form * part of the new saturated block. * @param avoidTets the list of tetrahedra that should not be * considered, and to which any new tetrahedra will be added. * @return details of the saturated block if one was found, or * \c null if none was found. */ static NSatTriPrism* isBlockTriPrismMajor(const NSatAnnulus& annulus, TetList& avoidTets); }; /** * A saturated block that is a six-tetrahedron cube. * * There are several ways of triangulating a cube with six tetrahedra; * the specific method used here is illustrated in the diagram below * (where the top face of the cube is identified with the bottom). * * \image html cube.png * * Note that none of the four tetrahedra that meet the boundary annuli * touch each other, and that each of these four boundary tetrahedra * meet both central tetrahedra. Note also that (unlike other * triangulations) this cube cannot be split vertically into two * triangular prisms. */ class REGINA_API NSatCube : public NSatBlock { public: /** * Constructs a clone of the given block structure. * * @param cloneMe the block structure to clone. */ NSatCube(const NSatCube& cloneMe); virtual NSatBlock* clone() const; virtual void adjustSFS(NSFSpace& sfs, bool reflect) const; virtual void writeTextShort(std::ostream& out) const; virtual void writeAbbr(std::ostream& out, bool tex = false) const; /** * Determines whether the given annulus is a boundary annulus for * a block of this type (cube). This routine is a specific case * of NSatBlock::isBlock(); see that routine for further details. * * @param annulus the proposed boundary annulus that should form * part of the new saturated block. * @param avoidTets the list of tetrahedra that should not be * considered, and to which any new tetrahedra will be added. * @return details of the saturated block if one was found, or * \c null if none was found. */ static NSatCube* isBlockCube(const NSatAnnulus& annulus, TetList& avoidTets); /** * Inserts a new copy of a cube block into the given triangulation, * and returns the corresponding block structure. * * The given triangulation will not be emptied before the new * tetrahedra are inserted. * * @param tri the triangulation into which the new block should * be inserted. * @return structural details of the newly inserted block. */ static NSatCube* insertBlock(NTriangulation& tri); protected: /** * Constructs an uninitialised block. The boundary annuli * must be initialised before this block can be used. */ NSatCube(); }; /** * A saturated block that is a reflector strip. * * A reflector strip is a ring of triangular prisms arranged end-to-end, * as illustrated in the diagram below. The top rectangle of each prism * is identified with the bottom in an orientation-reversing fashion * (the back edge moves to the front and vice versa), and the prisms * are joined in a loop from left to right. The Seifert fibres run * vertically in the diagram, with each saturated boundary annulus shaded * at the rear of each prism. * * \image html reflector.png * * The effect of a reflector strip is to create a reflector boundary in * the base orbifold of the surrounding Seifert fibred space. Each prism * provides a segment of this reflector boundary. * * A reflector strip may have arbitrary length, and it may also include * a twist as the ring of prisms wraps back around to meet itself. Note * that a twisted reflector strip will have a twisted ring of boundary * annuli, as described by NSatBlock::twistedBoundary(). * * The \e length of a reflector strip is defined to be the number of * prisms that are joined together, or equivalently the number of * saturated annuli on the boundary. */ class REGINA_API NSatReflectorStrip : public NSatBlock { public: /** * Constructs a clone of the given block structure. * * @param cloneMe the block structure to clone. */ NSatReflectorStrip(const NSatReflectorStrip& cloneMe); virtual NSatBlock* clone() const; virtual void adjustSFS(NSFSpace& sfs, bool reflect) const; virtual void writeTextShort(std::ostream& out) const; virtual void writeAbbr(std::ostream& out, bool tex = false) const; /** * Determines whether the given annulus is a boundary annulus for * a block of this type (reflector strip). This routine is a specific * case of NSatBlock::isBlock(); see that routine for further details. * * @param annulus the proposed boundary annulus that should form * part of the new saturated block. * @param avoidTets the list of tetrahedra that should not be * considered, and to which any new tetrahedra will be added. * @return details of the saturated block if one was found, or * \c null if none was found. */ static NSatReflectorStrip* isBlockReflectorStrip( const NSatAnnulus& annulus, TetList& avoidTets); /** * Inserts a new reflector strip into the given triangulation, * and returns the corresponding block structure. * * The given triangulation will not be emptied before the new * tetrahedra are inserted. * * @param tri the triangulation into which the new block should * be inserted. * @param length the length of the new reflector strip, i.e., * the number of boundary annuli; this must be strictly positive. * @param twisted \c true if the new reflector strip should be twisted * (causing its ring of boundary annuli to be twisted also), or * \c false if the new strip should not be twisted. * @return structural details of the newly inserted block. */ static NSatReflectorStrip* insertBlock(NTriangulation& tri, unsigned length, bool twisted); protected: /** * Constructs a partially initialised block of the given length. * The boundary annuli will remain uninitialised, and must be * initialised before this block can be used. * * @param length the length of the new reflector strip, i.e., * the number of boundary annuli; this must be strictly positive. * @param twisted \c true if the strip should be twisted (giving * a twisted ring of boundary annuli), or \c false if not. */ NSatReflectorStrip(unsigned length, bool twisted); }; /** * A degenerate saturated block that is a single tetrahedron wrapped * around so that two opposite edges touch. This forms a degenerate * one-tetrahedron solid torus that is pinched along a single meridinal * curve. * * The four faces of this tetrahedron form two boundary annuli, and the * tetrahedron is effectively layered onto each boundary annulus. See * the NLayering class notes for more discussion on layerings in general. * * Although this block is degenerate (the fibres are all pinched * together where the opposite edges of the tetrahedron meet), it can be * used without problems as long as the entire Seifert fibred space is * not formed from degenerate blocks. In other words, using such blocks * is fine as long as they eventually meet a real (non-degenerate) block, * which will give room for the fibres to separate so that they are no * longer pinched together. * * The NSatAnnulus class notes describe horizontal and diagonal edges of * a saturated annulus. This block may be one of two types, according * to how the tetrahedron is layered onto the boundary annuli. Either * the tetrahedron can be layered over the horizontal edge of each * annulus (with the fibres pinched together between the two diagonal * edges), or the tetrahedron can be layered over the diagonal edge of * each annulus (with the fibres pinched together between the two * horizontal edges). */ class REGINA_API NSatLayering : public NSatBlock { private: bool overHorizontal_; /**< Do we layer over the horizontal annulus edge, or the diagonal annulus edge? */ public: /** * Constructs a clone of the given block structure. * * @param cloneMe the block structure to clone. */ NSatLayering(const NSatLayering& cloneMe); /** * Does this describe a layering over the horizontal edge of the * boundary annulus, or a layering over the diagonal edge? * * See the NSatAnnulus class notes for definitions of horizontal * and diagonal in this context. */ bool overHorizontal() const; virtual NSatBlock* clone() const; virtual void adjustSFS(NSFSpace& sfs, bool reflect) const; virtual void writeTextShort(std::ostream& out) const; virtual void writeAbbr(std::ostream& out, bool tex = false) const; /** * Determines whether the given annulus is a boundary annulus for * a block of this type (single layering). This routine is * a specific case of NSatBlock::isBlock(); see that routine for * further details. * * @param annulus the proposed boundary annulus that should form * part of the new saturated block. * @param avoidTets the list of tetrahedra that should not be * considered, and to which any new tetrahedra will be added. * @return details of the saturated block if one was found, or * \c null if none was found. */ static NSatLayering* isBlockLayering(const NSatAnnulus& annulus, TetList& avoidTets); protected: /** * Constructs a partially initialised block. The boundary * annuli will remain uninitialised, and must be initialised * before this block can be used. * * @param overHorizontal \c true if this block describes a * layering over the horizontal edge of the boundary annulus, or * \c false if it describes a layering over the diagonal edge. */ NSatLayering(bool overHorizontal); }; /*@}*/ // Inline functions for NSatMobius inline NSatMobius::NSatMobius(const NSatMobius& cloneMe) : NSatBlock(cloneMe), position_(cloneMe.position_) { } inline NSatMobius::NSatMobius(int position) : NSatBlock(1), position_(position) { } inline int NSatMobius::position() const { return position_; } inline NSatBlock* NSatMobius::clone() const { return new NSatMobius(*this); } // Inline functions for NSatLST inline NSatLST::NSatLST(NLayeredSolidTorus* lst, NPerm4 roles) : NSatBlock(1), lst_(lst), roles_(roles) { } inline const NLayeredSolidTorus* NSatLST::lst() const { return lst_; } inline NPerm4 NSatLST::roles() const { return roles_; } inline NSatBlock* NSatLST::clone() const { return new NSatLST(*this); } // Inline functions for NSatTriPrism inline NSatTriPrism::NSatTriPrism(const NSatTriPrism& cloneMe) : NSatBlock(cloneMe), major_(cloneMe.major_) { } inline NSatTriPrism::NSatTriPrism(bool major) : NSatBlock(3), major_(major) { } inline bool NSatTriPrism::isMajor() const { return major_; } inline NSatBlock* NSatTriPrism::clone() const { return new NSatTriPrism(*this); } inline void NSatTriPrism::writeTextShort(std::ostream& out) const { out << "Saturated triangular prism of " << (major_ ? "major" : "minor") << " type"; } inline void NSatTriPrism::writeAbbr(std::ostream& out, bool tex) const { if (tex) out << "\\triangle"; else out << "Tri"; } // Inline functions for NSatCube inline NSatCube::NSatCube(const NSatCube& cloneMe) : NSatBlock(cloneMe) { } inline NSatCube::NSatCube() : NSatBlock(4) { } inline NSatBlock* NSatCube::clone() const { return new NSatCube(*this); } inline void NSatCube::writeTextShort(std::ostream& out) const { out << "Saturated cube"; } inline void NSatCube::writeAbbr(std::ostream& out, bool tex) const { if (tex) out << "\\square"; else out << "Cube"; } // Inline functions for NSatReflectorStrip inline NSatReflectorStrip::NSatReflectorStrip( const NSatReflectorStrip& cloneMe) : NSatBlock(cloneMe) { } inline NSatReflectorStrip::NSatReflectorStrip(unsigned length, bool twisted) : NSatBlock(length, twisted) { } inline NSatBlock* NSatReflectorStrip::clone() const { return new NSatReflectorStrip(*this); } inline void NSatReflectorStrip::writeTextShort(std::ostream& out) const { out << "Saturated reflector strip of length " << nAnnuli(); if (twistedBoundary()) out << " (twisted)"; } inline void NSatReflectorStrip::writeAbbr(std::ostream& out, bool tex) const { if (twistedBoundary()) { if (tex) out << "\\tilde{\\circledash}_" << nAnnuli(); else out << "Ref~(" << nAnnuli() << ')'; } else { if (tex) out << "\\circledash_" << nAnnuli(); else out << "Ref(" << nAnnuli() << ')'; } } // Inline functions for NSatLayering inline NSatLayering::NSatLayering(const NSatLayering& cloneMe) : NSatBlock(cloneMe), overHorizontal_(cloneMe.overHorizontal_) { } inline NSatLayering::NSatLayering(bool overHorizontal) : NSatBlock(2), overHorizontal_(overHorizontal) { } inline bool NSatLayering::overHorizontal() const { return overHorizontal_; } inline NSatBlock* NSatLayering::clone() const { return new NSatLayering(*this); } inline void NSatLayering::writeTextShort(std::ostream& out) const { out << "Saturated single layering over " << (overHorizontal_ ? "horizontal" : "diagonal") << " edge"; } inline void NSatLayering::writeAbbr(std::ostream& out, bool tex) const { if (tex) out << "lozenge"; else out << "Layer"; } } // namespace regina #endif regina-4.96/engine/subcomplex/nsatregion.cpp000644 000765 000024 00000050361 12377776703 021143 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "manifold/nsfs.h" #include "subcomplex/nsatblockstarter.h" #include "subcomplex/nsatregion.h" #include "triangulation/nedge.h" #include "triangulation/ntetrahedron.h" #include "utilities/ptrutils.h" #include #include namespace regina { namespace { /** * An anonymous inline boolean xor. I'm always afraid to use ^ with * bool, since I'm never sure if this bitwise operator will do the * right thing on all platforms. */ inline bool regXor(bool a, bool b) { return ((a && ! b) || (b && ! a)); } } NSatRegion::NSatRegion(NSatBlock* starter) : baseEuler_(1), baseOrbl_(true), hasTwist_(false), twistsMatchOrientation_(true), shiftedAnnuli_(0), twistedBlocks_(0), nBdryAnnuli_(starter->nAnnuli()) { blocks_.push_back(NSatBlockSpec(starter, false, false)); if (starter->twistedBoundary()) { hasTwist_ = true; twistsMatchOrientation_ = false; twistedBlocks_ = 1; } } NSatRegion::~NSatRegion() { for (BlockSet::iterator it = blocks_.begin(); it != blocks_.end(); it++) delete it->block; } const NSatAnnulus& NSatRegion::boundaryAnnulus(unsigned long which, bool& blockRefVert, bool& blockRefHoriz) const { unsigned ann; for (BlockSet::const_iterator it = blocks_.begin(); it != blocks_.end(); it++) for (ann = 0; ann < it->block->nAnnuli(); ann++) if (! it->block->hasAdjacentBlock(ann)) { if (which == 0) { blockRefVert = it->refVert; blockRefHoriz = it->refHoriz; return it->block->annulus(ann); } which--; } // Given the precondition, we should never reach this point. // We need to return a reference, so to keep the compiler happy, // create a memory leak. Again, we should never actually reach this point. return *(new NSatAnnulus()); } void NSatRegion::boundaryAnnulus(unsigned long which, NSatBlock*& block, unsigned& annulus, bool& blockRefVert, bool& blockRefHoriz) const { unsigned ann; for (BlockSet::const_iterator it = blocks_.begin(); it != blocks_.end(); it++) for (ann = 0; ann < it->block->nAnnuli(); ann++) if (! it->block->hasAdjacentBlock(ann)) { if (which == 0) { block = it->block; annulus = ann; blockRefVert = it->refVert; blockRefHoriz = it->refHoriz; return; } which--; } // Given the precondition, we should never reach this point. } NSFSpace* NSatRegion::createSFS(bool reflect) const { // Count boundary components. unsigned untwisted, twisted; countBoundaries(untwisted, twisted); // Go ahead and build the Seifert fibred space. NSFSpace::classType baseClass; bool bdry = (twisted || untwisted || twistedBlocks_); if (baseOrbl_) { if (hasTwist_) baseClass = (bdry ? NSFSpace::bo2 : NSFSpace::o2); else baseClass = (bdry ? NSFSpace::bo1 : NSFSpace::o1); } else if (! hasTwist_) baseClass = (bdry ? NSFSpace::bn1 : NSFSpace::n1); else if (twistsMatchOrientation_) baseClass = (bdry ? NSFSpace::bn2 : NSFSpace::n2); else { // In the no-boundary case, we might not be able to distinguish // between n3 and n4. Just call it n3 for now, and if we discover // it might have been n4 instead then we call it off and return 0. baseClass = (bdry ? NSFSpace::bn3 : NSFSpace::n3); } // Recall that baseEuler_ assumes that each block contributes a plain // old disc to the base orbifold (and, in particular, it ignores any // reflector boundaries arising from twistedBlocks_). This lets us // calculate genus just by looking at baseEuler_, orientability and // the number of punctures. NSFSpace* sfs = new NSFSpace(baseClass, (baseOrbl_ ? ((2 - baseEuler_) - twisted - untwisted) / 2 : ((2 - baseEuler_) - twisted - untwisted)), untwisted /* untwisted punctures */, twisted /* twisted punctures */, 0 /* untwisted reflectors */, twistedBlocks_ /* twisted reflectors */); for (BlockSet::const_iterator it = blocks_.begin(); it != blocks_.end(); it++) it->block->adjustSFS(*sfs, ! regXor(reflect, regXor(it->refVert, it->refHoriz))); if (shiftedAnnuli_) sfs->insertFibre(1, reflect ? -shiftedAnnuli_ : shiftedAnnuli_); if ((sfs->baseGenus() >= 3) && (sfs->baseClass() == NSFSpace::n3 || sfs->baseClass() == NSFSpace::n4)) { // Could still be either n3 or n4. // Shrug, give up. delete sfs; return 0; } return sfs; } bool NSatRegion::expand(NSatBlock::TetList& avoidTets, bool stopIfIncomplete) { NSatBlockSpec currBlockSpec; NSatBlock *currBlock, *adjBlock; unsigned ann, adjAnn; unsigned long adjPos; bool adjVert, adjHoriz; bool currTwisted, currNor; unsigned annBdryTriangles; // Try to push past the boundary annuli of all blocks present and future. // We rely on a vector data type for BlockSet here, since this // will keep the loop doing exactly what it should do even if new // blocks are added and blockFound.size() increases. for (unsigned long pos = 0; pos < blocks_.size(); pos++) { currBlockSpec = blocks_[pos]; currBlock = currBlockSpec.block; // Run through each boundary annulus for this block. for (ann = 0; ann < currBlock->nAnnuli(); ann++) { if (currBlock->hasAdjacentBlock(ann)) continue; // Do we have one or two boundary triangles? annBdryTriangles = currBlock->annulus(ann).meetsBoundary(); if (annBdryTriangles == 2) { // The annulus lies completely on the triangulation // boundary. Just skip it. continue; } else if (annBdryTriangles == 1) { // The annulus lies half on the boundary. No chance of // extending it from here, but we have no chance of // filling the entire triangulation. if (stopIfIncomplete) return false; continue; } // We can happily jump to the other side, since we know // there are tetrahedra present. // Is there a new block there? if ((adjBlock = NSatBlock::isBlock( currBlock->annulus(ann).otherSide(), avoidTets))) { // We found a new adjacent block that we haven't seen before. // Note that, since the annuli are not horizontally // reflected, the blocks themselves will be. currBlock->setAdjacent(ann, adjBlock, 0, false, false); blocks_.push_back(NSatBlockSpec(adjBlock, false, ! currBlockSpec.refHoriz)); nBdryAnnuli_ = nBdryAnnuli_ + adjBlock->nAnnuli() - 2; // Note whether the new block has twisted boundary. if (adjBlock->twistedBoundary()) { hasTwist_ = true; twistsMatchOrientation_ = false; twistedBlocks_++; } // On to the next annulus! continue; } // No adjacent block. // Perhaps it's joined to something we've already seen? // Only search forwards from this annulus. if (ann + 1 < currBlock->nAnnuli()) { adjPos = pos; adjAnn = ann + 1; } else { adjPos = pos + 1; adjAnn = 0; } while (adjPos < blocks_.size()) { adjBlock = blocks_[adjPos].block; if ((! adjBlock->hasAdjacentBlock(adjAnn)) && currBlock->annulus(ann).isAdjacent( adjBlock->annulus(adjAnn), &adjVert, &adjHoriz)) { // They match! currBlock->setAdjacent(ann, adjBlock, adjAnn, adjVert, adjHoriz); nBdryAnnuli_ -= 2; // See what kinds of inconsistencies this // rejoining has caused. currNor = regXor(regXor(currBlockSpec.refHoriz, blocks_[adjPos].refHoriz), ! adjHoriz); currTwisted = regXor(regXor(currBlockSpec.refVert, blocks_[adjPos].refVert), adjVert); if (currNor) baseOrbl_ = false; if (currTwisted) hasTwist_ = true; if (regXor(currNor, currTwisted)) twistsMatchOrientation_ = false; // See if we need to add a (1,1) shift before // the annuli can be identified. if (regXor(adjHoriz, adjVert)) { if (regXor(currBlockSpec.refHoriz, currBlockSpec.refVert)) shiftedAnnuli_--; else shiftedAnnuli_++; } break; } if (adjAnn + 1 < adjBlock->nAnnuli()) adjAnn++; else { adjPos++; adjAnn = 0; } } // If we found a match, we're done. Move on to the next annulus. if (adjPos < blocks_.size()) continue; // We couldn't match the annulus to anything. if (stopIfIncomplete) return false; } } // Well, we got as far as we got. calculateBaseEuler(); return true; } long NSatRegion::blockIndex(const NSatBlock* block) const { BlockSet::const_iterator it; unsigned long id; for (id = 0, it = blocks_.begin(); it != blocks_.end(); it++, id++) if (block == it->block) return id; return -1; } void NSatRegion::calculateBaseEuler() { BlockSet::const_iterator it; unsigned ann; long faces = blocks_.size(); long edgesBdry = 0; long edgesInternalDoubled = 0; for (it = blocks_.begin(); it != blocks_.end(); it++) for (ann = 0; ann < it->block->nAnnuli(); ann++) if (it->block->hasAdjacentBlock(ann)) edgesInternalDoubled++; else edgesBdry++; // When counting vertices, don't just count unique edges in the // triangulation -- we could run into strife with edge identifications // outside the region. Count the boundary vertices separately (this // is easy, since it's the same as the number of boundary edges). std::set baseVerticesAll; std::set baseVerticesBdry; NSatAnnulus annData; for (it = blocks_.begin(); it != blocks_.end(); it++) for (ann = 0; ann < it->block->nAnnuli(); ann++) { annData = it->block->annulus(ann); baseVerticesAll.insert(annData.tet[0]->getEdge( NEdge::edgeNumber[annData.roles[0][0]][annData.roles[0][1]])); if (! it->block->hasAdjacentBlock(ann)) { baseVerticesBdry.insert(annData.tet[0]->getEdge( NEdge::edgeNumber[annData.roles[0][0]][annData.roles[0][1]])); baseVerticesBdry.insert(annData.tet[1]->getEdge( NEdge::edgeNumber[annData.roles[1][0]][annData.roles[1][1]])); } } // To summarise what was said above: the internal vertices are // guaranteed to give distinct elements in the baseVertices sets, // but the boundary vertices are not. Thus we calculate internal // vertices via the sets, but boundary vertices via edgesBdry instead. long vertices = baseVerticesAll.size() - baseVerticesBdry.size() + edgesBdry; baseEuler_ = faces - edgesBdry - (edgesInternalDoubled / 2) + vertices; } void NSatRegion::writeBlockAbbrs(std::ostream& out, bool tex) const { typedef std::multiset > OrderedBlockSet; OrderedBlockSet blockOrder; for (BlockSet::const_iterator it = blocks_.begin(); it != blocks_.end(); it++) blockOrder.insert(it->block); for (OrderedBlockSet::const_iterator it = blockOrder.begin(); it != blockOrder.end(); it++) { if (it != blockOrder.begin()) out << ", "; (*it)->writeAbbr(out, tex); } } void NSatRegion::writeDetail(std::ostream& out, const std::string& title) const { out << title << ":\n"; BlockSet::const_iterator it; unsigned long id, nAnnuli, ann; bool ref, back; out << " Blocks:\n"; for (id = 0, it = blocks_.begin(); it != blocks_.end(); it++, id++) { out << " " << id << ". "; it->block->writeTextShort(out); nAnnuli = it->block->nAnnuli(); out << " (" << nAnnuli << (nAnnuli == 1 ? " annulus" : " annuli"); if (it->refVert || it->refHoriz) { out << ", "; if (it->refVert && it->refHoriz) out << "vert./horiz."; else if (it->refVert) out << "vert."; else out << "horiz."; out << " reflection"; } out << ")\n"; } out << " Adjacencies:\n"; for (id = 0, it = blocks_.begin(); it != blocks_.end(); it++, id++) for (ann = 0; ann < it->block->nAnnuli(); ann++) { out << " " << id << '/' << ann << " --> "; if (! it->block->hasAdjacentBlock(ann)) out << "bdry"; else { out << blockIndex(it->block->adjacentBlock(ann)) << '/' << it->block->adjacentAnnulus(ann); ref = it->block->adjacentReflected(ann); back = it->block->adjacentBackwards(ann); if (ref || back) { if (ref && back) out << " (reflected, backwards)"; else if (ref) out << " (reflected)"; else out << " (backwards)"; } } out << "\n"; } } void NSatRegion::writeTextShort(std::ostream& out) const { unsigned long size = blocks_.size(); out << "Saturated region with " << size << (size == 1 ? " block" : " blocks"); } void NSatRegion::countBoundaries(unsigned& untwisted, unsigned& twisted) const { untwisted = twisted = 0; // Just trace around each boundary component in turn. // Note that we are guaranteed that blocks_ is non-empty. unsigned i, j; // Count annuli in each block, and work out how to index all annuli // from all blocks into a single monolithic array. unsigned* nAnnuli = new unsigned[blocks_.size()]; unsigned* indexAnnuliFrom = new unsigned[blocks_.size()]; for (i = 0; i < blocks_.size(); ++i) { nAnnuli[i] = blocks_[i].block->nAnnuli(); indexAnnuliFrom[i] = (i == 0 ? 0 : indexAnnuliFrom[i-1] + nAnnuli[i-1]); } unsigned totAnnuli = indexAnnuliFrom[blocks_.size() - 1] + nAnnuli[blocks_.size() - 1]; // Prepare to keep track of which annuli we've processed. bool* used = new bool[totAnnuli]; std::fill(used, used + totAnnuli, false); // Off we go! NSatBlock *b, *currBlock, *tmpBlock; unsigned currBlockIndex, currAnnulus, tmpAnnulus; bool hTwist, vTwist, tmpHTwist, tmpVTwist; for (i = 0; i < blocks_.size(); ++i) { b = blocks_[i].block; for (j = 0; j < nAnnuli[i]; ++j) { // Here's our next annulus to examine. if (used[indexAnnuliFrom[i] + j]) { // Ignore: we've already processed this before. continue; } if (b->hasAdjacentBlock(j)) { // Ignore: this annulus is internal. used[indexAnnuliFrom[i] + j] = true; continue; } // This annulus is on the boundary, and not yet processed. // Run around the entire boundary component, marking annuli // as processed, and testing whether we close with a twist. currBlock = b; currBlockIndex = i; currAnnulus = j; hTwist = false; vTwist = false; while (true) { used[indexAnnuliFrom[currBlockIndex] + currAnnulus] = true; currBlock->nextBoundaryAnnulus(currAnnulus, tmpBlock, tmpAnnulus, tmpVTwist, tmpHTwist, hTwist); if (tmpVTwist) vTwist = ! vTwist; if (tmpHTwist) hTwist = ! hTwist; currBlock = tmpBlock; currAnnulus = tmpAnnulus; // Gaa. We need a block pointer -> index lookup. // Use a slow search for now. for (currBlockIndex = 0; currBlockIndex < blocks_.size(); ++currBlockIndex) if (blocks_[currBlockIndex].block == currBlock) break; if (currBlockIndex >= blocks_.size()) { std::cerr << "ERROR: Could not index current block." << std::endl; } if (currBlock == b && currAnnulus == j) break; } // See how the boundary component closed itself off. if (hTwist) { std::cerr << "ERROR: Unexpected hTwist in boundary tracing." << std::endl; } if (vTwist) ++twisted; else ++untwisted; } } //std::cout << "Region: " << twisted << " twisted, " << untwisted // << " untwisted." << std::endl; delete[] nAnnuli; delete[] indexAnnuliFrom; delete[] used; } } // namespace regina regina-4.96/engine/subcomplex/nsatregion.h000644 000765 000024 00000074374 12377775473 020625 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/nsatregion.h * \brief Supports connected regions of saturated blocks in triangulations * of Seifert fibred spaces. */ #ifndef __NSATREGION_H #ifndef __DOXYGEN #define __NSATREGION_H #endif #include "regina-core.h" #include "subcomplex/nsatblock.h" #include namespace regina { /** * \weakgroup subcomplex * @{ */ /** * Describes how a single saturated block forms a part of a larger * saturated region. * * A saturated region consists of several saturated blocks joined * together along their boundary annuli. This is a helper structure * containing a single saturated block along with details of its * orientation within a larger region. * * The ring of saturated annuli around the boundary of the block gives a * natural orientation to the block within the context of the base orbifold, * just as the ring of edges around a polygon would give a natural * orientation to that polygon within the context of a surrounding surface. * Again drawing an analogy with the orientation of polygons within a surface, * each block can be considered to have a correct or reflected orientation * according to whether this ring of annuli runs clockwise or anticlockwise * in the base orbifold. * * The precise orientation of a block is described using two booleans. * A block may be reflected \e horizontally, which preserves the * directions of Seifert fibres but which reverses the * clockwise/anticlockwise orientation as discussed above. A block may * also be reflected \e vertically, which preserves the * clockwise/anticlockwise orientation but which reverses the directions * of the Seifert fibres. A block may of course be reflected both * horizontally and vertically, or it may not be reflected at all. * * This helper structure is small, and can be copied by value if * necessary. Be aware that when this structure is destroyed, the * internal block structure of type NSatBlock is \e not destroyed. * * \ifacespython The data members \a block, \a refVert and \a refHoriz * are read-only. */ struct REGINA_API NSatBlockSpec { NSatBlock* block; /**< Details of the saturated block structure. */ bool refVert; /**< Indicates whether the block is reflected vertically within the larger region. See the class notes for details. */ bool refHoriz; /**< Indicates whether the block is reflected horizontally within the larger region. See the class notes for details. */ /** * Creates a new structure that is completely uninitialised. */ NSatBlockSpec(); /** * Creates a new structure that is initialised to the given set of * values. * * @param useBlock details of the saturated block structure. * @param useRefVert \c true if the block is reflected vertically * within the larger region, or \c false otherwise. * @param useRefHoriz \c true if the block is reflected horizontally * within the larger region, or \c false otherwise. */ NSatBlockSpec(NSatBlock* useBlock, bool useRefVert, bool useRefHoriz); }; /** * A large saturated region in a Seifert fibred space formed by joining * together saturated blocks. * * Like a saturated block (described in the class NSatBlock), a * saturated region is a connected set of tetrahedra built from a subset * of fibres. Unlike a saturated block however, a saturated region has * no constraints on its boundary - it may have several boundary * components or it may have none. For instance, a saturated region * might be an entire closed Seifert fibred space, or it might describe * a Seifert fibred component of a JSJ decomposition. * * A saturated region is formed from a collection of saturated blocks by * joining the boundary annuli of these blocks together in pairs. The * joins must be made so that the fibres are consistent, though it is * allowable to reverse the directions of the fibres. There is no problem * with joining two boundary annuli from the same block to each other. * * Any boundary annulus of a block that is not joined to some other * boundary annulus of a block becomes a boundary annulus of the entire * region. In this way, each boundary component of the region (if there * are any at all) is formed from a ring of boundary annuli, in the same * way that the boundary of a block is. Note that the routine * NSatBlock::nextBoundaryAnnulus() can be used to trace around a region * boundary. Like block boundaries, the boundary of a saturated region * need not be part of the boundary of the larger triangulation (i.e., * there may be adjacent tetrahedra that are not recognised as part of * this saturated structure). * * The NSatRegion class stores a list of its constituent blocks, but it * does not directly store which block boundary annuli are joined to * which. This adjacency information is stored within the blocks * themselves; see the notes regarding adjacency in the NSatBlock class * description. * * Blocks cannot be added to a region by hand. The way a region is * constructed is by locating some initial block within a triangulation * and passing this to the NSatRegion constructor, and then by calling * expand() to locate adjacent blocks and expand the region as far as * possible. For locating initial blocks, the class * NSatBlockStarterSearcher may be of use. * * \warning It is crucial that the adjacency information stored in the * blocks is consistent with the region containing them. All this * requires is that the blocks are not manipulated externally (e.g., * NSatBlock::setAdjacent() is not called on any of the blocks), but * instead all adjacency information is managed by this class. Routines * such as expand() which may add more blocks to the region will update * the block adjacencies accordingly. * * \todo \feature Have this class track the boundary components properly, * with annuli grouped and oriented according to the region boundaries (as * opposed to individual block boundaries). */ class REGINA_API NSatRegion : public ShareableObject { private: typedef std::vector BlockSet; /**< The data structure used to store the list of constituent blocks. */ BlockSet blocks_; /**< The set of blocks from which this region is formed, along with details of how they are oriented within this larger region. */ long baseEuler_; /**< The Euler characteristic of the base orbifold if we assume that each block contributes a trivial disc to the base orbifold. */ bool baseOrbl_; /**< Denotes whether the base orbifold is orientable if we assume that each block contributes a trivial disc to the base orbifold. */ bool hasTwist_; /**< Denotes whether we can find a fibre-reversing path that does not step inside the interior of any constituent blocks. */ bool twistsMatchOrientation_; /**< Denotes whether set of fibre-reversing paths corresponds precisely to the set of orientation-reversing paths on the base orbifold, where we do not allow paths that step inside the interior of any constituent blocks. */ long shiftedAnnuli_; /**< The number of additional (1,1) twists added to the underlying Seifert fibred space due to blocks being sheared up or down as they are joined together. This typically happens when the triangulations of two boundary annuli are not compatible when joined (e.g., they provide opposite diagonal edges) */ unsigned long twistedBlocks_; /**< The number of constituent blocks with twisted boundary. Each such block provides an additional twisted reflector boundary to the base orbifold; see NSatBlock::adjustSFS() for details. */ unsigned long nBdryAnnuli_; /**< The number of saturated annuli forming the boundary components (if any) of this region. */ public: /** * Constructs a new region containing just the given block. * All boundary annuli of the given block will become boundary * annuli of this region. It is guaranteed that this block will * be stored in the region without any kind of reflection (see * NSatBlockSpec for details). * * Typically a region is initialised using this constructor, and * then grown using the expand() routine. For help in finding * an initial starter block, see the NSatBlockStarterSearcher class. * * This region will claim ownership of the given block, and upon * destruction it will destroy this block also. * * \pre The given block has no adjacencies listed. That is, * for every boundary annulus of the given block, * NSatBlock::hasAdjacentBlock() returns \c false. * * @param starter the single block that this region will describe. */ NSatRegion(NSatBlock* starter); /** * Destroys this structure and all of its internal data, * including the individual blocks that make up this region. */ virtual ~NSatRegion(); /** * Returns the number of saturated blocks that come together * to form this saturated region. */ unsigned long numberOfBlocks() const; /** * Returns details of the requested saturated block within this * region. The information will returned will include * structural information for the block, along with details of * how the block is aligned (e.g., reflected vertically or * horizontally) within the larger region. * * @param which indicates which of the constituent blocks should * be returned; this must be between 0 and numberOfBlocks()-1 * inclusive. * @return details of the requested saturated block. */ const NSatBlockSpec& block(unsigned long which) const; /** * Returns the index of the given block within this region. * This index corresponds to the integer parameter that is passed * to the routine block(). * * \warning This routine is slow, since it simply scans through * the blocks in this region one by one until the given block is * found (or until all blocks are exhausted). * * @return the index of the given block (as an integer between * 0 and numberOfBlocks()-1 inclusive), or -1 if the block is * not part of this region. */ long blockIndex(const NSatBlock* block) const; /** * Returns the number of saturated annuli that together form the * boundary components of this region. * * @return the number of boundary annuli. */ unsigned long numberOfBoundaryAnnuli() const; /** * Returns the requested saturated annulus on the boundary of * this region. * * The saturated annuli that together form the boundary * components of this region are numbered from 0 to * numberOfBoundaryAnnuli()-1 inclusive. The argument \a which * specifies which one of these annuli should be returned. * * Currently the annuli are numbered lexicographically by * block and then by annulus number within the block, although * this ordering is subject to change in future versions of Regina. * In particular, the annuli are \e not necessarily numbered in * order around the region boundaries, and each region boundary * component might not even be given a consecutive range of numbers. * * It is guaranteed however that, if the starter block passed to * the NSatRegion constructor provides any boundary annuli for * the overall region, then the first such annulus in the starter * block will be numbered 0 here. * * The structure returned will be the annulus precisely as it * appears within its particular saturated block. As discussed * in the NSatBlockSpec class notes, the block might be * reflected horizontally and/or vertically within the overall * region, which will affect how the annulus is positioned as * part of the overall region boundary (e.g., the annulus might * be positioned upside-down in the overall region boundary, * or it might be positioned with its second triangle appearing before * its first triangle as one walks around the boundary). To account * for this, the two boolean arguments \a blockRefVert and * \a blockRefHoriz will be modified to indicate if and how the * block is reflected. * * \warning This routine is quite slow, since it currently scans * through every annulus of every saturated block. Use it * sparingly! * * \ifacespython Both variants of boundaryAnnulus() are * combined into a single routine, which takes the integer * \a which as its only argument and returns its results as a * tuple. See the alternate version of boundaryAnnulus() for * details on how the return tuple is structured. * * @param which specifies which boundary annulus of this region * to return; this must be between 0 and numberOfBoundaryAnnuli()-1 * inclusive. * @param blockRefVert used to return whether the block * containing the requested annulus is vertically reflected * within this region (see NSatBlockSpec for details). This * will be set to \c true if the block is vertically reflected, * or \c false if not. * @param blockRefHoriz used to return whether the block * containing the requested annulus is horizontally reflected * within this region (see NSatBlockSpec for details). This * will be set to \c true if the block is horizontally reflected, * or \c false if not. * @return details of the requested boundary annulus, precisely * as it appears within its particular saturated block. */ const NSatAnnulus& boundaryAnnulus(unsigned long which, bool& blockRefVert, bool& blockRefHoriz) const; /** * Returns fine details of the requested saturated annulus on * the boundary of this region. * * The argument \a which specifies which one of these * annuli should be returned. See the * boundaryAnnulus(unsigned long, bool&, bool&) documentation * for details on how the boundary annuli are numbered. * * Various details of the requested boundary annulus are * returned in the various arguments, as described below. * * Be aware that the block containing the requested annulus * might be reflected horizontally and/or vertically within the * overall region, as discussed in the NSatBlockSpec class notes. * This will affect how the annulus is positioned as * part of the overall region boundary (e.g., the annulus might * be positioned upside-down in the overall region boundary, * or it might be positioned with its second triangle appearing before * its first triangle as one walks around the boundary). The two * boolean arguments \a blockRefVert and \a blockRefHoriz will * be modified to indicate if and how the block is reflected. * * \warning This routine is quite slow, since it currently scans * through every annulus of every saturated block. Use it * sparingly! * * \ifacespython This routine only takes a single argument (the * integer \a which). The return value is a tuple of four values: * the block returned in \a block, the integer returned in \a annulus, * the boolean returned in \a blockRefVert, and the boolean returned * in \a blockRefHoriz. * * @param which specifies which boundary annulus of this region * to return; this must be between 0 and numberOfBoundaryAnnuli()-1 * inclusive. * @param block used to return the particular saturated block * containing the requested annulus. * @param annulus used to return which annulus number in the * returned block is the requested annulus; this will be between * 0 and block->nAnnuli() inclusive. * @param blockRefVert used to return whether the block * containing the requested annulus is vertically reflected * within this region (see NSatBlockSpec for details). This * will be set to \c true if the block is vertically reflected, * or \c false if not. * @param blockRefHoriz used to return whether the block * containing the requested annulus is horizontally reflected * within this region (see NSatBlockSpec for details). This * will be set to \c true if the block is horizontally reflected, * or \c false if not. */ void boundaryAnnulus(unsigned long which, NSatBlock*& block, unsigned& annulus, bool& blockRefVert, bool& blockRefHoriz) const; /** * Returns details of the Seifert fibred space represented by * this region. * * Each boundary component of this region will be formed from a ring * of saturated annuli, which together form a torus or a Klein bottle. * For torus boundary components, the oriented curves * representing the fibres and base orbifold on the boundary * (see \ref sfsnotation) will be as follows. * * - Consider the 0/1/2 markings on the first and second triangles * of each saturated annulus, as described in the NSatAnnulus * class notes. * - The fibres are represented by the oriented edge joining * markings 1 and 0 on the first triangle (or 0 and 1 on the * second triangle). This is reversed if the block containing the * boundary annulus is vertically reflected. * - The curve representing the base orbifold run along the * oriented edge joining markings 0 and 2 on the first triangle * (or 2 and 0 on the second triangle). This is reversed if the * block containing the boundary annulus is horizontally * reflected. * - See the NSatBlockSpec overview for descriptions of * horizontal and vertical reflection. * * If the argument \a reflect is \c true, the Seifert fibred * space will be created as though the entire region had been * reflected. In particular, each twist or exceptional fibre * will be negated before being added to the Seifert structure. * * For Klein bottle boundary components, these curves must (for * now) be analysed by hand. * * @param reflect \c true if this region is to be reflected * as the Seifert fibred space is created, or \c false if not. * @return the newly created structure of the underlying Seifert * fibred space. */ NSFSpace* createSFS(bool reflect) const; /** * A deprecated version of the routine that returns details of the * Seifert fibred space represented by this region. * * This is an old and now-deprecated version of createSFS(), which * imposed additional preconditions (all boundary components had to be * tori), and required the user to pass the number of boundary * components as the first argument. This first argument is now * ignored, and the preconditions have been relaxed to allow Klein * bottle boundary components also. * * See createSFS(bool), the new version of this routine, for further * details. * * \deprecated This routine simply ignores the first argument, * and passes the second argument through to createSFS(bool). * Code should be changed to call createSFS(bool) directly. * * @param reflect \c true if this region is to be reflected * as the Seifert fibred space is created, or \c false if not. * @return the newly created structure of the underlying Seifert * fibred space. */ NSFSpace* createSFS(long, bool reflect) const; /** * Expands this region as far as possible within the overall * triangulation. This routine will hunt for new saturated * blocks, and will also hunt for new adjacencies between * existing blocks. * * The first argument to this routine is the tetrahedron list * \a avoidTets. This is a list of tetrahedra that will not be * considered when examining potential new blocks. This list * will be modified by this routine; in particular, it will be * expanded to include all tetrahedra for any new blocks that * are found. Before calling this routine it should contain * tetrahedra for blocks already in this region, as discussed in * the preconditions below. * * It may be that you are searching for a region that fills an entire * triangulation component (i.e., every boundary annulus of the * region in fact forms part of the boundary of the triangulation). * In this case you may pass the optional argument * \a stopIfIncomplete as \c true. This means that if this routine * ever discovers an annulus that is not part of the * triangulation boundary and that it cannot match with some * adjacent block, it will exit immediately and return \c false. * Note that the region structure will be incomplete and/or * inconsistent if this happens; in this case the unfinished * region should be destroyed completely and never used. * * For internal purposes, it should be noted that any new blocks * that are discovered will be added to the end of the internal * block list (thus the indices of existing blocks will not change). * * \warning When joining blocks together, it is possible to * create invalid edges (e.g., by joining a one-annulus * untwisted boundary to a one-annulus twisted boundary). * This routine does \e not check for such conditions. It is * recommended that you run NTriangulation::isValid() before * calling this routine. * * \pre If any blocks already belonging to this region have * adjacencies listed in their NSatBlock structures, then these * adjacent blocks belong to this region also. This precondition * is easily satisfied if you let the NSatRegion constructor * and expand() do all of the adjacency handling, as described * in the class notes. * \pre The list \a avoidTets includes all tetrahedra on the * boundaries of any blocks already contained in this region. * * \ifacespython The first argument \a avoidTets is not present. * An empty list will be passed instead. * * @param avoidTets a list of tetrahedra that should not be * considered for new blocks, as discussed above. Note that * this list may be modified by this routine. * @param stopIfIncomplete \c true if you are filling an entire * triangulation component with this region and you wish this * routine to exit early if this is not possible, or \c false * (the default) if you simply wish to expand this region as far * as you can. See above for further discussion. * @return \c false if the optional argument \a stopIfIncomplete * was passed as \c true but expansion did not fill the entire * triangulation component as described above, or \c true in all * other cases. */ bool expand(NSatBlock::TetList& avoidTets, bool stopIfIncomplete = false); /** * Writes an abbreviated list of blocks within this region to * the given output stream. Blocks will be written using their * abbreviated names, and these names will be separated by * commas. See NSatBlock::writeAbbr() for further details. * * The blocks within this region will be sorted before their * abbreviated names are output. The particular method of sorting * is an arbitrary aesthetic decision on the part of the author, * and is subject to change in future versions of Regina. * * \ifacespython The parameter \a out does not exist; standard * output will be used. * * @param out the output stream to which to write. * @param tex \c true if the output should be formatted for TeX, * or \c false if it should be written as plain text. */ void writeBlockAbbrs(std::ostream& out, bool tex = false) const; /** * Writes details of the composition of this region to the given * output stream. * * The output will consist of several lines. The first line * will contain the title string (passed as a separate argument * to this routine), followed by a colon. Following this will be * a number of lines describing the individual blocks that make * up this region and the various adjacencies between them. * * \ifacespython The parameter \a out does not exist; standard * output will be used. * * @param out the output stream to which to write. * @param title the name of this region, to be written on the * first line of output. */ void writeDetail(std::ostream& out, const std::string& title) const; void writeTextShort(std::ostream& out) const; void writeTextLong(std::ostream& out) const; private: /** * Runs through the region structure and recalculates the * \a baseEuler_ data member. * * No assumptions are made about whether edges of the boundary * annuli become identified due to features outside the region. * That is, this routine is safe to call even when this region * is joined to some other not-yet-understood sections of the * triangulation. */ void calculateBaseEuler(); /** * Each boundary component of this region will be formed from a ring * of saturated annuli, which is either untwisted (forming a * torus), or twisted (forming a Klein bottle). * This routine counts the total number of boundaries of each type. * * @param untwisted returns the number of untwisted (torus) * boundary components. * @param twisted returns the number of twisted (Klein bottle) * boundary components. */ void countBoundaries(unsigned& untwisted, unsigned& twisted) const; }; /*@}*/ // Inline functions for NSatBlockSpec inline NSatBlockSpec::NSatBlockSpec() { } inline NSatBlockSpec::NSatBlockSpec(NSatBlock* useBlock, bool useRefVert, bool useRefHoriz) : block(useBlock), refVert(useRefVert), refHoriz(useRefHoriz) { } // Inline functions for NSatRegion inline unsigned long NSatRegion::numberOfBlocks() const { return blocks_.size(); } inline const NSatBlockSpec& NSatRegion::block(unsigned long which) const { return blocks_[which]; } inline unsigned long NSatRegion::numberOfBoundaryAnnuli() const { return nBdryAnnuli_; } inline NSFSpace* NSatRegion::createSFS(long, bool reflect) const { return createSFS(reflect); } inline void NSatRegion::writeTextLong(std::ostream& out) const { writeDetail(out, "Saturated region"); } } // namespace regina #endif regina-4.96/engine/subcomplex/nsnappeacensustri.cpp000644 000765 000024 00000022152 12377776705 022536 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "algebra/nabeliangroup.h" #include "manifold/nsnappeacensusmfd.h" #include "subcomplex/nsnappeacensustri.h" #include "triangulation/ncomponent.h" #include "triangulation/nedge.h" #include "triangulation/ntriangle.h" #include "triangulation/nvertex.h" namespace regina { const char NSnapPeaCensusTri::SEC_5 = 'm'; const char NSnapPeaCensusTri::SEC_6_OR = 's'; const char NSnapPeaCensusTri::SEC_6_NOR = 'x'; const char NSnapPeaCensusTri::SEC_7_OR = 'v'; const char NSnapPeaCensusTri::SEC_7_NOR = 'y'; NSnapPeaCensusTri* NSnapPeaCensusTri::isSmallSnapPeaCensusTri( const NComponent* comp) { // Currently this routine can recognise SnapPea triangulations // m000 -- m004 as well as m129. // Since the triangulations are so small we can use census results // (from a census of all small valid ideal triangulations) to recognise // the triangulations by properties alone. // Before we do any further checks, make sure the number of // tetrahedra is within the supported range. if (comp->getNumberOfTetrahedra() > 4) return 0; // Start with property checks to see if it has a chance of being // in the SnapPea census at all. The component must not be // closed, every edge must be valid and every vertex link must be // either a torus or a Klein bottle. Note that this implies // that there are no boundary triangles. if (comp->isClosed()) return 0; unsigned long nVertices = comp->getNumberOfVertices(); unsigned long nEdges = comp->getNumberOfEdges(); unsigned long i; int link; for (i = 0; i < nVertices; i++) { link = comp->getVertex(i)->getLink(); if (link != NVertex::TORUS && link != NVertex::KLEIN_BOTTLE) return 0; } for (i = 0; i < nEdges; i++) if (! comp->getEdge(i)->isValid()) return 0; // Now search for specific triangulations. if (comp->getNumberOfTetrahedra() == 1) { // At this point it must be m000, since there are no others // that fit these constraints. But test orientability // anyway just to be safe. if (comp->isOrientable()) return 0; return new NSnapPeaCensusTri(SEC_5, 0); } else if (comp->getNumberOfTetrahedra() == 2) { if (comp->isOrientable()) { // Orientable. Looking for m003 or m004. if (comp->getNumberOfVertices() != 1) return 0; if (comp->getNumberOfEdges() != 2) return 0; if (comp->getEdge(0)->getNumberOfEmbeddings() != 6 || comp->getEdge(1)->getNumberOfEmbeddings() != 6) return 0; // Now we know it's either m003 or m004. We distinguish // between them by triangle types, since all of m003's triangles // are Mobius bands and all of m004's triangles are horns. if (comp->getTriangle(0)->getType() == NTriangle::MOBIUS) return new NSnapPeaCensusTri(SEC_5, 3); else return new NSnapPeaCensusTri(SEC_5, 4); } else { // Non-orientable. Looking for m001 or m002. if (comp->getNumberOfVertices() == 1) { // Looking for m001. if (comp->getNumberOfEdges() != 2) return 0; if (! ((comp->getEdge(0)->getNumberOfEmbeddings() == 4 && comp->getEdge(1)->getNumberOfEmbeddings() == 8) || (comp->getEdge(0)->getNumberOfEmbeddings() == 8 && comp->getEdge(1)->getNumberOfEmbeddings() == 4))) return 0; // Census says it's m001 if no triangle forms a dunce hat. for (int i = 0; i < 4; i++) if (comp->getTriangle(i)->getType() == NTriangle::DUNCEHAT) return 0; return new NSnapPeaCensusTri(SEC_5, 1); } else if (comp->getNumberOfVertices() == 2) { // Looking for m002. if (comp->getNumberOfEdges() != 2) return 0; if (comp->getEdge(0)->getNumberOfEmbeddings() != 6 || comp->getEdge(1)->getNumberOfEmbeddings() != 6) return 0; // Census says it's m002 if some triangle forms a dunce hat. for (int i = 0; i < 4; i++) if (comp->getTriangle(i)->getType() == NTriangle::DUNCEHAT) return new NSnapPeaCensusTri(SEC_5, 2); return 0; } } } else if (comp->getNumberOfTetrahedra() == 4) { if (comp->isOrientable()) { // Search for the Whitehead link complement. // Note that this could be done with a smaller set of tests // since some can be deduced from others, but these tests // aren't terribly expensive anyway. if (comp->getNumberOfVertices() != 2) return 0; if (comp->getNumberOfEdges() != 4) return 0; if (comp->getVertex(0)->getLink() != NVertex::TORUS) return 0; if (comp->getVertex(1)->getLink() != NVertex::TORUS) return 0; if (comp->getVertex(0)->getNumberOfEmbeddings() != 8) return 0; if (comp->getVertex(1)->getNumberOfEmbeddings() != 8) return 0; // Census says it's the Whitehead link if some edge has // degree 8. for (int i = 0; i < 4; i++) if (comp->getEdge(i)->getNumberOfEmbeddings() == 8) return new NSnapPeaCensusTri(SEC_5, 129); return 0; } } // Not recognised after all. return 0; } NManifold* NSnapPeaCensusTri::getManifold() const { return new NSnapPeaCensusManifold(section, index); } NAbelianGroup* NSnapPeaCensusTri::getHomologyH1() const { return NSnapPeaCensusManifold(section, index).getHomologyH1(); } std::ostream& NSnapPeaCensusTri::writeName(std::ostream& out) const { out << "SnapPea " << section; // Pad the index with leading zeroes. // All sections are written with three-digit indices, except for // 7-tetrahedron orientable which uses four-digit indices. if (section == SEC_7_OR && index < 1000) out << '0'; if (index < 100) out << '0'; if (index < 10) out << '0'; out << index; return out; } std::ostream& NSnapPeaCensusTri::writeTeXName(std::ostream& out) const { out << section << "_{"; // Pad the index with leading zeroes. // All sections are written with three-digit indices, except for // 7-tetrahedron orientable which uses four-digit indices. if (section == SEC_7_OR && index < 1000) out << '0'; if (index < 100) out << '0'; if (index < 10) out << '0'; out << index << '}'; return out; } } // namespace regina regina-4.96/engine/subcomplex/nsnappeacensustri.h000644 000765 000024 00000021577 12377775475 022220 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/nsnappeacensustri.h * \brief Deals with 3-manifold triangulations from the SnapPea census. */ #ifndef __NSNAPPEACENSUSTRI_H #ifndef __DOXYGEN #define __NSNAPPEACENSUSTRI_H #endif #include "regina-core.h" #include "nstandardtri.h" namespace regina { /** * \weakgroup subcomplex * @{ */ /** * Represents a 3-manifold triangulation from the SnapPea cusped census. * * The SnapPea cusped census is the census of cusped hyperbolic 3-manifolds * formed from up to seven tetrahedra. This census was tabulated by * Callahan, Hildebrand and Weeks, and is shipped with SnapPea 3.0d3 * (and also with Regina). * * \note The modern cusped hyperbolic census now extends to nine tetrahedra, * and indeed the 9-tetrahedron database is accessible through the * NCensus lookup routines. However, for the time being, the scope of these * NSnapPeaCensusManifold and NSnapPeaCensusTri classes is restricted to the * original Callahan-Hildebrand-Weeks 7-tetrahedron census only. * * The census is split into five different sections according to number * of tetrahedra and orientability. Each of these sections corresponds * to one of the section constants defined in this class. * * For further details regarding the SnapPea census, see "A census of cusped * hyperbolic 3-manifolds", Patrick J. Callahan, Martin V. Hildebrand and * Jeffrey R. Weeks, Math. Comp. 68 (1999), no. 225, pp. 321--332. * * Note that this class is closely tied to NSnapPeaCensusManifold. * In particular, the section constants defined in NSnapPeaCensusManifold * and NSnapPeaCensusTri are identical, and so may be freely mixed. * Furthermore, the section and index parameters of an NSnapPeaCensusTri * are identical to those of its corresponding NSnapPeaCensusManifold. * * All of the optional NStandardTriangulation routines are implemented * for this class. */ class REGINA_API NSnapPeaCensusTri: public NStandardTriangulation { public: static const char SEC_5; /**< Represents the collection of triangulations formed from five or fewer tetrahedra (both orientable and non-orientable). There are 415 triangulations in this section. */ static const char SEC_6_OR; /**< Represents the collection of orientable triangulations formed from six tetrahedra. There are 962 triangulations in this section. */ static const char SEC_6_NOR; /**< Represents the collection of non-orientable triangulations formed from six tetrahedra. There are 259 triangulations in this section. */ static const char SEC_7_OR; /**< Represents the collection of orientable triangulations formed from seven tetrahedra. There are 3552 triangulations in this section. */ static const char SEC_7_NOR; /**< Represents the collection of non-orientable triangulations formed from seven tetrahedra. There are 887 triangulations in this section. */ private: char section; /**< The section of the SnapPea census to which this triangulation belongs. This must be one of the section constants defined in this class. */ unsigned long index; /**< The index within the given section of this specific triangulation. Note that the first index in each section is zero. */ public: /** * Returns a newly created clone of this structure. * * @return a newly created clone. */ NSnapPeaCensusTri* clone() const; /** * Returns the section of the SnapPea census to which this * triangulation belongs. This will be one of the section constants * defined in this class. * * @return the section of the SnapPea census. */ char getSection() const; /** * Returns the index of this triangulation within its particular * section of the SnapPea census. Note that indices for each * section begin counting at zero. * * @return the index of this triangulation within its section. */ unsigned long getIndex() const; /** * Determines whether this and the given structure represent * the same triangulation from the SnapPea census. * * @param compare the structure with which this will be compared. * @return \c true if and only if this and the given structure * represent the same SnapPea census triangulation. */ bool operator == (const NSnapPeaCensusTri& compare) const; /** * Determines if the given triangulation component is one of the * smallest SnapPea census triangulations. * * This routine is able to recognise a small selection of * triangulations from the beginning of the SnapPea census, by * way of hard-coding their structures and properties. * Most triangulations from the census however will not be * recognised by this routine. * * @param comp the triangulation component to examine. * @return a newly created structure representing the small * SnapPea census triangulation, or \c null if the given * component is not one of the few SnapPea census * triangulations recognised by this routine. */ static NSnapPeaCensusTri* isSmallSnapPeaCensusTri( const NComponent* comp); NManifold* getManifold() const; NAbelianGroup* getHomologyH1() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; private: /** * Creates a new SnapPea census triangulation with the given * parameters. */ NSnapPeaCensusTri(char newSection, unsigned long newIndex); friend class NSnapPeaCensusManifold; }; /*@}*/ // Inline functions for NSnapPeaCensusTri inline NSnapPeaCensusTri* NSnapPeaCensusTri::clone() const { return new NSnapPeaCensusTri(section, index); } inline char NSnapPeaCensusTri::getSection() const { return section; } inline unsigned long NSnapPeaCensusTri::getIndex() const { return index; } inline bool NSnapPeaCensusTri::operator == (const NSnapPeaCensusTri& compare) const { return (section == compare.section && index == compare.index); } inline NSnapPeaCensusTri::NSnapPeaCensusTri(char newSection, unsigned long newIndex) : section(newSection), index(newIndex) { } } // namespace regina #endif regina-4.96/engine/subcomplex/nsnappedball.cpp000644 000765 000024 00000006541 12377776705 021440 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "algebra/nabeliangroup.h" #include "manifold/nhandlebody.h" #include "triangulation/ntetrahedron.h" #include "subcomplex/nsnappedball.h" namespace regina { NSnappedBall* NSnappedBall::clone() const { NSnappedBall* ans = new NSnappedBall(); ans->tet = tet; ans->equator = equator; return ans; } NSnappedBall* NSnappedBall::formsSnappedBall(NTetrahedron* tet) { int inFace1, inFace2; NPerm4 perm; for (inFace1 = 0; inFace1 < 3; inFace1++) if (tet->adjacentTetrahedron(inFace1) == tet) { perm = tet->adjacentGluing(inFace1); inFace2 = perm[inFace1]; if (perm == NPerm4(inFace1, inFace2)) { // This is it! NSnappedBall* ans = new NSnappedBall(); ans->tet = tet; ans->equator = NEdge::edgeNumber[inFace1][inFace2]; return ans; } } return 0; } NManifold* NSnappedBall::getManifold() const { return new NHandlebody(0, true); } NAbelianGroup* NSnappedBall::getHomologyH1() const { return new NAbelianGroup(); } } // namespace regina regina-4.96/engine/subcomplex/nsnappedball.h000644 000765 000024 00000016021 12377775476 021103 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/nsnappedball.h * \brief Deals with snapped 3-balls in a triangulation. */ #ifndef __NSNAPPEDBALL_H #ifndef __DOXYGEN #define __NSNAPPEDBALL_H #endif #include "regina-core.h" #include "subcomplex/nstandardtri.h" #include "triangulation/nedge.h" namespace regina { class NTetrahedron; /** * \weakgroup subcomplex * @{ */ /** * Represents a snapped 3-ball in a triangulation. * A snapped 3-ball is a single tetrahedron with two faces glued to each * other to form a 3-ball with a two triangle boundary. * * All optional NStandardTriangulation routines are implemented for this * class. */ class REGINA_API NSnappedBall : public NStandardTriangulation { private: NTetrahedron* tet; /**< The tetrahedron that forms the snapped ball. */ int equator; /**< The edge that forms the equator on the ball boundary. */ public: /** * Returns a newly created clone of this structure. * * @return a newly created clone. */ NSnappedBall* clone() const; /** * Returns the tetrahedron that forms this snapped ball. * * @return the tetrahedron. */ NTetrahedron* getTetrahedron() const; /** * Returns one of the two tetrahedron faces that forms the boundary * of this snapped ball. * * You are guaranteed that index 0 will return a smaller face * number than index 1. * * @param index specifies which of the two boundary faces to return; * this must be either 0 or 1. * @return the corresponding face number in the tetrahedron. */ int getBoundaryFace(int index) const; /** * Returns one of the two tetrahedron faces internal to this snapped * ball. * * You are guaranteed that index 0 will return a smaller face * number than index 1. * * @param index specifies which of the two internal faces to return; * this must be either 0 or 1. * @return the corresponding face number in the tetrahedron. */ int getInternalFace(int index) const; /** * Returns the edge that forms the equator of the boundary sphere * of this ball. * * @return the corresponding edge number in the tetrahedron. */ int getEquatorEdge() const; /** * Returns the edge internal to this snapped ball. * * @return the corresponding edge number in the tetrahedron. */ int getInternalEdge() const; /** * Determines if the given tetrahedron forms a snapped 3-ball * within a triangulation. The ball need not be the entire * triangulation; the boundary triangles may be glued to something * else (or to each other). * * Note that the two boundary triangles of the snapped 3-ball * need not be boundary triangles within the overall * triangulation, i.e., they may be identified with each other * or with triangles of other tetrahedra. * * @param tet the tetrahedron to examine as a potential 3-ball. * @return a newly created structure containing details of the * snapped 3-ball, or \c null if the given tetrahedron is * not a snapped 3-ball. */ static NSnappedBall* formsSnappedBall(NTetrahedron* tet); NManifold* getManifold() const; NAbelianGroup* getHomologyH1() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; void writeTextLong(std::ostream& out) const; private: /** * Creates a new uninitialised structure. */ NSnappedBall(); }; /*@}*/ // Inline functions for NSnappedBall inline NSnappedBall::NSnappedBall() { } inline NTetrahedron* NSnappedBall::getTetrahedron() const { return tet; } inline int NSnappedBall::getBoundaryFace(int index) const { return index == 0 ? NEdge::edgeVertex[5 - equator][0] : NEdge::edgeVertex[5 - equator][1]; } inline int NSnappedBall::getInternalFace(int index) const { return index == 0 ? NEdge::edgeVertex[equator][0] : NEdge::edgeVertex[equator][1]; } inline int NSnappedBall::getEquatorEdge() const { return equator; } inline int NSnappedBall::getInternalEdge() const { return 5 - equator; } inline std::ostream& NSnappedBall::writeName(std::ostream& out) const { return out << "Snap"; } inline std::ostream& NSnappedBall::writeTeXName(std::ostream& out) const { return out << "\\mathit{Snap}"; } inline void NSnappedBall::writeTextLong(std::ostream& out) const { out << "Snapped 3-ball"; } } // namespace regina #endif regina-4.96/engine/subcomplex/nsnappedtwosphere.cpp000644 000765 000024 00000007250 12377776706 022545 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "triangulation/ntetrahedron.h" #include "subcomplex/nsnappedtwosphere.h" #include "subcomplex/nsnappedball.h" namespace regina { NSnappedTwoSphere* NSnappedTwoSphere::clone() const { NSnappedTwoSphere* ans = new NSnappedTwoSphere(); ans->ball[0] = ball[0]->clone(); ans->ball[1] = ball[1]->clone(); return ans; } NSnappedTwoSphere* NSnappedTwoSphere::formsSnappedTwoSphere( NTetrahedron* tet1, NTetrahedron* tet2) { NSnappedBall* ball[2]; if (! (ball[0] = NSnappedBall::formsSnappedBall(tet1))) return 0; if (! (ball[1] = NSnappedBall::formsSnappedBall(tet2))) { delete ball[0]; return 0; } if (tet1->getEdge(ball[0]->getEquatorEdge()) != tet2->getEdge(ball[1]->getEquatorEdge())) { delete ball[0]; delete ball[1]; return 0; } // This is it. NSnappedTwoSphere* ans = new NSnappedTwoSphere(); ans->ball[0] = ball[0]; ans->ball[1] = ball[1]; return ans; } NSnappedTwoSphere* NSnappedTwoSphere::formsSnappedTwoSphere( NSnappedBall* ball1, NSnappedBall* ball2) { if (ball1->getTetrahedron()->getEdge(ball1->getEquatorEdge()) != ball2->getTetrahedron()->getEdge(ball2->getEquatorEdge())) return 0; // This is it. NSnappedTwoSphere* ans = new NSnappedTwoSphere(); ans->ball[0] = ball1->clone(); ans->ball[1] = ball2->clone(); return ans; } } // namespace regina regina-4.96/engine/subcomplex/nsnappedtwosphere.h000644 000765 000024 00000014365 12377775501 022207 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/nsnappedtwosphere.h * \brief Deals with 2-spheres made from two snapped 3-balls in a * triangulation. */ #ifndef __NSNAPPEDTWOSPHERE_H #ifndef __DOXYGEN #define __NSNAPPEDTWOSPHERE_H #endif #include "regina-core.h" #include "subcomplex/nsnappedball.h" namespace regina { class NTetrahedron; class NTriangulation; class NSnappedBall; /** * \weakgroup subcomplex * @{ */ /** * Represents a 2-sphere made from two snapped 3-balls in a triangulation. * This occurs when two snapped 3-balls are glued together at their * equators (note that this gluing does not have to extend to triangular faces). * Each 3-ball has a central disc (bounded by the 3-ball's equator and bisecting * its internal edge), and these two discs together form an embedded * 2-sphere in the triangulation. * * This 2-sphere can be cut along and the two resulting 2-sphere * boundaries filled in with 3-balls, and the resulting triangulation has * the same number of tetrahedra as the original. If the snapped * 2-sphere was separating, the resulting triangulation will contain the * two terms of the corresponding connected sum. */ class REGINA_API NSnappedTwoSphere : public ShareableObject { private: NSnappedBall* ball[2]; /**< The two snapped 3-balls whose equators are joined. */ public: /** * Destroys this snapped 2-sphere; note that the corresponding * snapped 3-balls will also be destroyed. */ virtual ~NSnappedTwoSphere(); /** * Returns a newly created clone of this structure. * * @return a newly created clone. */ NSnappedTwoSphere* clone() const; /** * Returns one of the two snapped 3-balls whose equators are * joined. * * @param index specifies which of the two 3-balls to return; * this must be either 0 or 1. * @return the corresponding snapped 3-ball. */ const NSnappedBall* getSnappedBall(int index) const; /** * Determines if the two given tetrahedra together form a snapped * 2-sphere. * * \pre The two given tetrahedra are distinct. * * @param tet1 the first tetrahedron to examine. * @param tet2 the second tetrahedron to examine. * @return a newly created structure containing details of the * snapped 2-sphere, or \c null if the given tetrahedra do not * form a snapped 2-sphere. */ static NSnappedTwoSphere* formsSnappedTwoSphere(NTetrahedron* tet1, NTetrahedron* tet2); /** * Determines if the two given snapped 3-balls together form a snapped * 2-sphere. * * If this is the case, the snapped 3-balls stored in * the structure returned will be clones of the * original 3-balls, not the original 3-balls themselves. * * \pre The two given snapped 3-balls use distinct tetrahedra. * * @param ball1 the first snapped 3-ball to examine. * @param ball2 the second snapped 3-ball to examine. * @return a newly created structure containing details of the * snapped 2-sphere, or \c null if the given snapped 3-balls do not * form a snapped 2-sphere. */ static NSnappedTwoSphere* formsSnappedTwoSphere(NSnappedBall* ball1, NSnappedBall* ball2); void writeTextShort(std::ostream& out) const; private: /** * Creates a new uninitialised structure. */ NSnappedTwoSphere(); }; /*@}*/ // Inline functions for NSnappedTwoSphere inline NSnappedTwoSphere::NSnappedTwoSphere() { } inline NSnappedTwoSphere::~NSnappedTwoSphere() { delete ball[0]; delete ball[1]; } inline const NSnappedBall* NSnappedTwoSphere::getSnappedBall(int index) const { return ball[index]; } inline void NSnappedTwoSphere::writeTextShort(std::ostream& out) const { out << "Snapped 2-sphere"; } } // namespace regina #endif regina-4.96/engine/subcomplex/nspiralsolidtorus.cpp000644 000765 000024 00000015623 12377776707 022600 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include "algebra/nabeliangroup.h" #include "manifold/nhandlebody.h" #include "subcomplex/nspiralsolidtorus.h" #include "triangulation/ntriangulation.h" namespace regina { NSpiralSolidTorus* NSpiralSolidTorus::clone() const { NSpiralSolidTorus* ans = new NSpiralSolidTorus(nTet); for (unsigned long i = 0; i < nTet; i++) { ans->tet[i] = tet[i]; ans->vertexRoles[i] = vertexRoles[i]; } return ans; } void NSpiralSolidTorus::reverse() { NTetrahedron** newTet = new NTetrahedron*[nTet]; NPerm4* newRoles = new NPerm4[nTet]; NPerm4 switchPerm(3, 2, 1, 0); for (unsigned long i = 0; i < nTet; i++) { newTet[i] = tet[nTet - 1 - i]; newRoles[i] = vertexRoles[nTet - 1 - i] * switchPerm; } delete[] tet; delete[] vertexRoles; tet = newTet; vertexRoles = newRoles; } void NSpiralSolidTorus::cycle(unsigned long k) { NTetrahedron** newTet = new NTetrahedron*[nTet]; NPerm4* newRoles = new NPerm4[nTet]; for (unsigned long i = 0; i < nTet; i++) { newTet[i] = tet[(i + k) % nTet]; newRoles[i] = vertexRoles[(i + k) % nTet]; } delete[] tet; delete[] vertexRoles; tet = newTet; vertexRoles = newRoles; } bool NSpiralSolidTorus::makeCanonical(const NTriangulation* tri) { unsigned long i, index; unsigned long baseTet = 0; unsigned long baseIndex = tri->tetrahedronIndex(tet[0]); for (i = 1; i < nTet; i++) { index = tri->tetrahedronIndex(tet[i]); if (index < baseIndex) { baseIndex = index; baseTet = i; } } bool reverseAlso = (vertexRoles[baseTet][0] > vertexRoles[baseTet][3]); if (baseTet == 0 && (! reverseAlso)) return false; NTetrahedron** newTet = new NTetrahedron*[nTet]; NPerm4* newRoles = new NPerm4[nTet]; if (reverseAlso) { // Make baseTet into tetrahedron 0 and reverse. NPerm4 switchPerm(3, 2, 1, 0); for (unsigned long i = 0; i < nTet; i++) { newTet[i] = tet[(baseTet + nTet - i) % nTet]; newRoles[i] = vertexRoles[(baseTet + nTet - i) % nTet] * switchPerm; } } else { // Make baseTet into tetrahedron 0 but don't reverse. for (unsigned long i = 0; i < nTet; i++) { newTet[i] = tet[(i + baseTet) % nTet]; newRoles[i] = vertexRoles[(i + baseTet) % nTet]; } } delete[] tet; delete[] vertexRoles; tet = newTet; vertexRoles = newRoles; return true; } bool NSpiralSolidTorus::isCanonical(const NTriangulation* tri) const { if (vertexRoles[0][0] > vertexRoles[0][3]) return false; long baseIndex = tri->tetrahedronIndex(tet[0]); for (unsigned long i = 1; i < nTet; i++) if (tri->tetrahedronIndex(tet[i]) < baseIndex) return false; return true; } NSpiralSolidTorus* NSpiralSolidTorus::formsSpiralSolidTorus(NTetrahedron* tet, NPerm4 useVertexRoles) { NPerm4 invRoleMap(1, 2, 3, 0); // Maps upper roles to lower roles. NTetrahedron* base = tet; NPerm4 baseRoles(useVertexRoles); std::vector tets; std::vector roles; std::set usedTets; tets.push_back(tet); roles.push_back(useVertexRoles); usedTets.insert(tet); NTetrahedron* adjTet; NPerm4 adjRoles; while (1) { // Examine the tetrahedron beyond tet. adjTet = tet->adjacentTetrahedron(useVertexRoles[0]); adjRoles = tet->adjacentGluing(useVertexRoles[0]) * useVertexRoles * invRoleMap; // Check that we haven't hit the boundary. if (adjTet == 0) return 0; if (adjTet == base) { // We're back at the beginning of the loop. // Check that everything is glued up correctly. if (adjRoles != baseRoles) return 0; // Success! break; } if (usedTets.count(adjTet)) return 0; // Move on to the next tetrahedron. tet = adjTet; useVertexRoles = adjRoles; tets.push_back(tet); roles.push_back(useVertexRoles); usedTets.insert(tet); } // We've found a spiralled solid torus. NSpiralSolidTorus* ans = new NSpiralSolidTorus(tets.size()); copy(tets.begin(), tets.end(), ans->tet); copy(roles.begin(), roles.end(), ans->vertexRoles); return ans; } NManifold* NSpiralSolidTorus::getManifold() const { return new NHandlebody(1, true); } NAbelianGroup* NSpiralSolidTorus::getHomologyH1() const { NAbelianGroup* ans = new NAbelianGroup(); ans->addRank(); return ans; } } // namespace regina regina-4.96/engine/subcomplex/nspiralsolidtorus.h000644 000765 000024 00000030333 12377775503 022231 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/nspiralsolidtorus.h * \brief Deals with spiralled solid tori in a triangulation. */ #ifndef __NSPIRALSOLIDTORUS_H #ifndef __DOXYGEN #define __NSPIRALSOLIDTORUS_H #endif #include "regina-core.h" #include "maths/nperm4.h" #include "subcomplex/nstandardtri.h" namespace regina { class NTetrahedron; class NTriangulation; /** * \weakgroup subcomplex * @{ */ /** * Represents a spiralled solid torus in a triangulation. * * A spiralled solid torus is created by placing tetrahedra one upon * another in a spiralling fashion to form a giant loop. * * For each tetrahedron, label the vertices A, B, C and D. Draw the * tetrahedron so that the vertices form an upward spiral in the order * A-B-C-D, with D directly above A. Face BCD is on the top, face ABC * is on the bottom and faces ABD and ACD are both vertical. * * When joining two tetrahedra, face BCD of the lower tetrahedron will * be joined to face ABC of the upper tetrahedron. In this way the * tetrahedra are placed one upon another to form a giant loop (which is * closed up by placing the bottommost tetrahedron above the topmost * tetrahedron in a similar fashion), forming a solid torus overall. * * In each tetrahedron, directed edges AB, BC and CD are major edges, * directed edges AC and BD are minor edges and directed edge AD * is an axis edge. * * The major edges all combined form a single longitude of the solid * torus. Using this directed longitude, using the directed meridinal curve * ACBA and assuming the spiralled solid torus contains \a n tetrahedra, * the minor edges all combined form a (2, n) curve and * the axis edges all combined form a (3, n) curve on the torus * boundary. * * Note that all tetrahedra in the spiralled solid torus must be distinct * and there must be at least one tetrahedron. * * Note also that class NTriSolidTorus represents a spiralled solid * torus with precisely three tetrahedra. A spiralled solid torus with * only one tetrahedron is in fact a (1,2,3) layered solid torus. * * All optional NStandardTriangulation routines are implemented for this * class. */ class REGINA_API NSpiralSolidTorus : public NStandardTriangulation { private: unsigned long nTet; /**< The number of tetrahedra in this spiralled solid torus. */ NTetrahedron** tet; /**< The tetrahedra that make up this spiralled solid torus. */ NPerm4* vertexRoles; /**< For tetrahedron \a i, vertexRoles[i] is a permutation p chosen so that vertices A, B, C and D above correspond to vertices p[0], p[1], p[2] and p[3]. */ public: /** * Destroys this spiralled solid torus. */ virtual ~NSpiralSolidTorus(); /** * Returns a newly created clone of this structure. * * @return a newly created clone. */ NSpiralSolidTorus* clone() const; /** * Returns the number of tetrahedra in this spiralled solid torus. * * @return the number of tetrahedra. */ unsigned long getNumberOfTetrahedra() const; /** * Returns the requested tetrahedron in this spiralled solid torus. * Tetrahedra are numbered from 0 to getNumberOfTetrahedra()-1 * inclusive, with tetrahedron i+1 being placed above * tetrahedron i. * * @param index specifies which tetrahedron to return; this must * be between 0 and getNumberOfTetrahedra()-1 inclusive. * @return the requested tetrahedron. */ NTetrahedron* getTetrahedron(unsigned long index) const; /** * Returns a permutation represeting the role that each vertex * of the requested tetrahedron plays in the solid torus. * The permutation returned (call this p) maps 0, 1, 2 and * 3 to the four vertices of tetrahedron \a index so that * vertices p[0], p[1], p[2] and * p[3] correspond to vertices A, B, C and D * respectively as described in the general class notes. * * In particular, the directed edge from vertex * p[0] to p[3] is an axis edge, * directed edges p[0] to p[2] and * p[1] to p[3] are minor edges and * the directed path from vertices p[0] to p[1] * to p[2] to p[3] follows the three * major edges. * * See the general class notes for further details. * * @param index specifies which tetrahedron in the solid torus * to examine; this must be between 0 and * getNumberOfTetrahedra()-1 inclusive. * @return a permutation representing the roles of the vertices * of the requested tetrahedron. */ NPerm4 getVertexRoles(unsigned long index) const; /** * Reverses this spiralled solid torus. * Tetrahedra 0, 1, 2, ..., getNumberOfTetrahedra()-1 will * become tetrahedra getNumberOfTetrahedra()-1, ..., 2, 1, 0 * respectively. Note that this operation will change the * vertex roles as well. * * The underlying triangulation is not changed; all that changes * is how this spiralled solid torus is represented. */ void reverse(); /** * Cycles this spiralled solid torus by the given number of * tetrahedra. * Tetrahedra k, k+1, k+2 and so on * will become tetrahedra 0, 1, 2 and so on respectively. * Note that this operation will not change the vertex roles. * * The underlying triangulation is not changed; all that changes * is how this spiralled solid torus is represented. * * @param k the number of tetrahedra through which we should cycle. */ void cycle(unsigned long k); /** * Converts this spiralled solid torus into its canonical * representation. The canonical representation of a spiralled * solid torus is unique in a given triangulation. * * Tetrahedron 0 in the spiralled solid torus will be the * tetrahedron with the lowest index in the triangulation, and * under permutation getVertexRoles(0) the image of 0 * will be less than the image of 3. * * @param tri the triangulation in which this solid torus lives. * @return \c true if and only if the representation of this * spiralled solid torus was actually changed. */ bool makeCanonical(const NTriangulation* tri); /** * Determines whether this spiralled solid torus is in canonical * form. Canonical form is described in detail in the * description for makeCanonical(). * * @param tri the triangulation in which this solid torus lives. * @return \c true if and only if this spiralled solid torus is * in canonical form. */ bool isCanonical(const NTriangulation* tri) const; /** * Determines if the given tetrahedron forms part of a * spiralled solid torus with its vertices * playing the given roles in the solid torus. * * Note that the boundary triangles of the spiralled solid * torus need not be boundary triangles within the overall * triangulation, i.e., they may be identified with each other * or with triangles of other tetrahedra. * * @param tet the tetrahedron to examine. * @param useVertexRoles a permutation describing the role each * tetrahedron vertex must play in the solid torus; this must be * in the same format as the permutation returned by * getVertexRoles(). * @return a newly created structure containing details of the * solid torus with the given tetrahedron as tetrahedron 0, or * \c null if the given tetrahedron is not part of a spiralled * solid torus with the given vertex roles. */ static NSpiralSolidTorus* formsSpiralSolidTorus(NTetrahedron* tet, NPerm4 useVertexRoles); NManifold* getManifold() const; NAbelianGroup* getHomologyH1() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; void writeTextLong(std::ostream& out) const; private: /** * Creates a new partially initialised structure. * Member \a nTet will be initialised and dynamic arrays * \a tet and \a vertexRoles will be created. * * @param newNTet the number of tetrahedra in this spiralled * solid torus; this must be strictly positive. */ NSpiralSolidTorus(unsigned long newNTet); }; /*@}*/ // Inline functions for NSpiralSolidTorus inline NSpiralSolidTorus::NSpiralSolidTorus(unsigned long newNTet) : nTet(newNTet), tet(new NTetrahedron*[newNTet]), vertexRoles(new NPerm4[newNTet]) { } inline NSpiralSolidTorus::~NSpiralSolidTorus() { delete[] tet; delete[] vertexRoles; } inline unsigned long NSpiralSolidTorus::getNumberOfTetrahedra() const { return nTet; } inline NTetrahedron* NSpiralSolidTorus::getTetrahedron(unsigned long index) const { return tet[index]; } inline NPerm4 NSpiralSolidTorus::getVertexRoles(unsigned long index) const { return vertexRoles[index]; } inline std::ostream& NSpiralSolidTorus::writeName(std::ostream& out) const { return out << "Spiral(" << nTet << ')'; } inline std::ostream& NSpiralSolidTorus::writeTeXName(std::ostream& out) const { return out << "\\mathit{Spiral}(" << nTet << ')'; } inline void NSpiralSolidTorus::writeTextLong(std::ostream& out) const { out << nTet << "-tetrahedron spiralled solid torus"; } } // namespace regina #endif regina-4.96/engine/subcomplex/nstandardtri.cpp000644 000765 000024 00000011642 12377776707 021472 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "subcomplex/naugtrisolidtorus.h" #include "subcomplex/nblockedsfs.h" #include "subcomplex/nblockedsfsloop.h" #include "subcomplex/nblockedsfspair.h" #include "subcomplex/nblockedsfstriple.h" #include "subcomplex/nl31pillow.h" #include "subcomplex/nlayeredchainpair.h" #include "subcomplex/nlayeredlensspace.h" #include "subcomplex/nlayeredloop.h" #include "subcomplex/nlayeredsurfacebundle.h" #include "subcomplex/npluggedtorusbundle.h" #include "subcomplex/nplugtrisolidtorus.h" #include "subcomplex/nsnappeacensustri.h" #include "subcomplex/ntrivialtri.h" #include "triangulation/ntriangulation.h" namespace regina { std::string NStandardTriangulation::getName() const { std::ostringstream ans; writeName(ans); return ans.str(); } std::string NStandardTriangulation::getTeXName() const { std::ostringstream ans; writeTeXName(ans); return ans.str(); } NStandardTriangulation* NStandardTriangulation::isStandardTriangulation( NComponent* comp) { NStandardTriangulation* ans; if ((ans = NTrivialTri::isTrivialTriangulation(comp))) return ans; if ((ans = NL31Pillow::isL31Pillow(comp))) return ans; if ((ans = NLayeredLensSpace::isLayeredLensSpace(comp))) return ans; if ((ans = NLayeredLoop::isLayeredLoop(comp))) return ans; if ((ans = NLayeredChainPair::isLayeredChainPair(comp))) return ans; if ((ans = NAugTriSolidTorus::isAugTriSolidTorus(comp))) return ans; if ((ans = NPlugTriSolidTorus::isPlugTriSolidTorus(comp))) return ans; if ((ans = NLayeredSolidTorus::isLayeredSolidTorus(comp))) return ans; if ((ans = NSnapPeaCensusTri::isSmallSnapPeaCensusTri(comp))) return ans; return 0; } NStandardTriangulation* NStandardTriangulation::isStandardTriangulation( NTriangulation* tri) { if (tri->getNumberOfComponents() != 1) return 0; // Do what we can through components. NStandardTriangulation* ans; if ((ans = isStandardTriangulation(tri->getComponent(0)))) return ans; // Run tests that require entire triangulations. if ((ans = NBlockedSFS::isBlockedSFS(tri))) return ans; if ((ans = NLayeredTorusBundle::isLayeredTorusBundle(tri))) return ans; // Save non-geometric graph manifolds until last. if ((ans = NBlockedSFSLoop::isBlockedSFSLoop(tri))) return ans; if ((ans = NBlockedSFSPair::isBlockedSFSPair(tri))) return ans; if ((ans = NBlockedSFSTriple::isBlockedSFSTriple(tri))) return ans; if ((ans = NPluggedTorusBundle::isPluggedTorusBundle(tri))) return ans; // Nup. return 0; } } // namespace regina regina-4.96/engine/subcomplex/nstandardtri.h000644 000765 000024 00000024663 12377775505 021141 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/nstandardtri.h * \brief Deals with triangulations whose structures are well-understood. */ #ifndef __NSTANDARDTRI_H #ifndef __DOXYGEN #define __NSTANDARDTRI_H #endif #include "regina-core.h" #include "shareableobject.h" namespace regina { class NAbelianGroup; class NComponent; class NManifold; class NTriangulation; /** * \addtogroup subcomplex Standard Triangulations and Subcomplexes * Standard triangulations and subcomplexes of triangulations whose * structures are well-understood. * @{ */ /** * Describes a triangulation or subcomplex of a triangulation whose structure * is well-understood. An NStandardTriangulation is generally connected * with a real triangulation, i.e., an NTriangulation object, which it * describes some portion of. * * In general NStandardTriangulation objects cannot be constructed * directly, but are instead created through static identification * routines such as * NStandardTriangulation::isStandardTriangulation(NTriangulation*). * * Subclasses corresponding to different families of triangulations do * not need to override writeTextShort() since this routine is * properly implemented in the base class NStandardTriangulation. */ class REGINA_API NStandardTriangulation : public ShareableObject { public: /** * A destructor that does nothing. */ virtual ~NStandardTriangulation(); /** * Returns the name of this specific triangulation as a * human-readable string. * * @return the name of this triangulation. */ std::string getName() const; /** * Returns the name of this specific triangulation in TeX * format. No leading or trailing dollar signs will be included. * * \warning The behaviour of this routine has changed as of * Regina 4.3; in earlier versions, leading and trailing dollar * signs were provided. * * @return the name of this triangulation in TeX format. */ std::string getTeXName() const; /** * Returns the 3-manifold represented by this triangulation, if * such a recognition routine has been implemented. If the * 3-manifold cannot be recognised then this routine will return 0. * * The details of which standard triangulations have 3-manifold * recognition routines can be found in the notes for the * corresponding subclasses of NStandardTriangulation. The * default implementation of this routine returns 0. * * It is expected that the number of triangulations whose * underlying 3-manifolds can be recognised will grow between * releases. * * The 3-manifold will be newly allocated and must be destroyed * by the caller of this routine. * * @return the underlying 3-manifold. */ virtual NManifold* getManifold() const; /** * Returns the expected first homology group of this triangulation, * if such a routine has been implemented. If the calculation of * homology has not yet been implemented for this triangulation * then this routine will return 0. * * This routine does not work by calling * NTriangulation::getHomologyH1() on the associated real * triangulation. Instead the homology is calculated directly * from the known properties of this standard triangulation. * * The details of which standard triangulations have homology * calculation routines can be found in the notes for the * corresponding subclasses of NStandardTriangulation. The * default implementation of this routine returns 0. * * The homology group will be newly allocated and must be * destroyed by the caller of this routine. * * If this NStandardTriangulation describes an entire NTriangulation * (and not just a part thereof) then the results of this routine * should be identical to the homology group obtained by calling * NTriangulation::getHomologyH1() upon the associated real * triangulation. * * @return the first homology group of this triangulation, or 0 if * the appropriate calculation routine has not yet been implemented. */ virtual NAbelianGroup* getHomologyH1() const; /** * Writes the name of this triangulation as a human-readable * string to the given output stream. * * \ifacespython The parameter \a out does not exist; standard * output will be used. * * @param out the output stream to which to write. * @return a reference to the given output stream. */ virtual std::ostream& writeName(std::ostream& out) const = 0; /** * Writes the name of this triangulation in TeX format * to the given output stream. No leading or trailing dollar * signs will be included. * * \warning The behaviour of this routine has changed as of * Regina 4.3; in earlier versions, leading and trailing dollar * signs were provided. * * \ifacespython The parameter \a out does not exist; standard * output will be used. * * @param out the output stream to which to write. * @return a reference to the given output stream. */ virtual std::ostream& writeTeXName(std::ostream& out) const = 0; virtual void writeTextShort(std::ostream& out) const; /** * Determines whether the given component represents one of the * standard triangulations understood by Regina. The list of * recognised triangulations is expected to grow between * releases. * * If the standard triangulation returned has boundary triangles * then the given component must have the same corresponding * boundary triangles, i.e., the component cannot have any further * identifications of these boundary triangles with each other. * * Note that the triangulation-based routine * isStandardTriangulation(NTriangulation*) may recognise more * triangulations than this routine, since passing an entire * triangulation allows access to more information. * * @param component the triangulation component under examination. * @return the details of the standard triangulation if the * given component is recognised, or 0 otherwise. */ static NStandardTriangulation* isStandardTriangulation( NComponent* component); /** * Determines whether the given triangulation represents one of the * standard triangulations understood by Regina. The list of * recognised triangulations is expected to grow between * releases. * * If the standard triangulation returned has boundary triangles * then the given triangulation must have the same corresponding * boundary triangles, i.e., the triangulation cannot have any further * identifications of these boundary triangles with each other. * * This routine may recognise more triangulations than the * component-based isStandardTriangulation(NComponent*), * since passing an entire triangulation allows access to * more information. * * @param tri the triangulation under examination. * @return the details of the standard triangualation if the * given triangulation is recognised, or 0 otherwise. */ static NStandardTriangulation* isStandardTriangulation( NTriangulation* tri); }; /*@}*/ // Inline functions for NStandardTriangulation inline NStandardTriangulation::~NStandardTriangulation() { } inline NManifold* NStandardTriangulation::getManifold() const { return 0; } inline NAbelianGroup* NStandardTriangulation::getHomologyH1() const { return 0; } inline void NStandardTriangulation::writeTextShort(std::ostream& out) const { writeName(out); } } // namespace regina #endif regina-4.96/engine/subcomplex/ntrisolidtorus.cpp000644 000765 000024 00000016537 12377776710 022103 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "algebra/nabeliangroup.h" #include "manifold/nhandlebody.h" #include "subcomplex/ntrisolidtorus.h" #include "subcomplex/nlayeredchain.h" #include "triangulation/ntetrahedron.h" namespace regina { NTriSolidTorus* NTriSolidTorus::clone() const { NTriSolidTorus* ans = new NTriSolidTorus(); for (int i = 0; i < 3; i++) { ans->tet[i] = tet[i]; ans->vertexRoles[i] = vertexRoles[i]; } return ans; } bool NTriSolidTorus::isAnnulusSelfIdentified(int index, NPerm4* roleMap) const { int lower = (index + 1) % 3; int upper = (index + 2) % 3; if (tet[lower]->adjacentTetrahedron(vertexRoles[lower][2]) != tet[upper]) return false; if (tet[lower]->adjacentFace(vertexRoles[lower][2]) != vertexRoles[upper][1]) return false; // We have a self-identification. if (roleMap) *roleMap = vertexRoles[upper].inverse() * tet[lower]->adjacentGluing(vertexRoles[lower][2]) * vertexRoles[lower]; return true; } unsigned long NTriSolidTorus::areAnnuliLinkedMajor(int otherAnnulus) const { int right = (otherAnnulus + 1) % 3; int left = (otherAnnulus + 2) % 3; NTetrahedron* adj = tet[right]->adjacentTetrahedron( vertexRoles[right][1]); if (adj != tet[left]->adjacentTetrahedron(vertexRoles[left][2])) return 0; if (adj == tet[0] || adj == tet[1] || adj == tet[2] || adj == 0) return 0; NPerm4 roles = tet[right]->adjacentGluing( vertexRoles[right][1]) * vertexRoles[right] * NPerm4(2, 3, 1, 0); if (roles != tet[left]->adjacentGluing( vertexRoles[left][2]) * vertexRoles[left] * NPerm4(3, 2, 0, 1)) return 0; // We've successfully identified the first tetrahedron of the // layered chain. NLayeredChain chain(adj, roles); chain.extendMaximal(); if (chain.getTop() != tet[otherAnnulus]) return 0; if (chain.getTopVertexRoles() != vertexRoles[otherAnnulus] * NPerm4(0, 1, 2, 3)) return 0; // Success! return chain.getIndex() - 1; } unsigned long NTriSolidTorus::areAnnuliLinkedAxis(int otherAnnulus) const { int right = (otherAnnulus + 1) % 3; int left = (otherAnnulus + 2) % 3; NTetrahedron* adj = tet[right]->adjacentTetrahedron( vertexRoles[right][1]); if (adj != tet[otherAnnulus]->adjacentTetrahedron( vertexRoles[otherAnnulus][2])) return 0; if (adj == tet[0] || adj == tet[1] || adj == tet[2] || adj == 0) return 0; NPerm4 roles = tet[right]->adjacentGluing( vertexRoles[right][1]) * vertexRoles[right] * NPerm4(2, 1, 0, 3); if (roles != tet[otherAnnulus]->adjacentGluing( vertexRoles[otherAnnulus][2]) * vertexRoles[otherAnnulus] * NPerm4(0, 3, 2, 1)) return 0; // We've successfully identified the first tetrahedron of the // layered chain. NLayeredChain chain(adj, roles); chain.extendMaximal(); NTetrahedron* top = chain.getTop(); NPerm4 topRoles(chain.getTopVertexRoles()); if (top->adjacentTetrahedron(topRoles[3]) != tet[left]) return 0; if (top->adjacentTetrahedron(topRoles[0]) != tet[otherAnnulus]) return 0; if (topRoles != tet[left]->adjacentGluing( vertexRoles[left][2]) * vertexRoles[left] * NPerm4(3, 0, 1, 2)) return 0; if (topRoles != tet[otherAnnulus]->adjacentGluing( vertexRoles[otherAnnulus][1]) * vertexRoles[otherAnnulus] * NPerm4(1, 2, 3, 0)) return 0; // Success! return chain.getIndex(); } NTriSolidTorus* NTriSolidTorus::formsTriSolidTorus(NTetrahedron* tet, NPerm4 useVertexRoles) { NTriSolidTorus* ans = new NTriSolidTorus(); ans->tet[0] = tet; ans->vertexRoles[0] = useVertexRoles; // Find the adjacent tetrahedra. ans->tet[1] = tet->adjacentTetrahedron(useVertexRoles[0]); ans->tet[2] = tet->adjacentTetrahedron(useVertexRoles[3]); // Check that we have three distinct tetrahedra. if (ans->tet[1] == 0 || ans->tet[2] == 0 || ans->tet[1] == tet || ans->tet[2] == tet || ans->tet[1] == ans->tet[2]) { delete ans; return 0; } // Find the vertex roles for tetrahedra 1 and 2. ans->vertexRoles[1] = tet->adjacentGluing(useVertexRoles[0]) * useVertexRoles * NPerm4(1, 2, 3, 0); ans->vertexRoles[2] = tet->adjacentGluing(useVertexRoles[3]) * useVertexRoles * NPerm4(3, 0, 1, 2); // Finally, check that tetrahedra 1 and 2 are glued together // properly. NPerm4 roles1 = ans->vertexRoles[1]; if (ans->tet[1]->adjacentTetrahedron(roles1[0]) != ans->tet[2]) { delete ans; return 0; } if (ans->tet[1]->adjacentGluing(roles1[0]) * roles1 * NPerm4(1, 2, 3, 0) != ans->vertexRoles[2]) { delete ans; return 0; } // We have the desired structure! return ans; } NAbelianGroup* NTriSolidTorus::getHomologyH1() const { NAbelianGroup* ans = new NAbelianGroup(); ans->addRank(); return ans; } NManifold* NTriSolidTorus::getManifold() const { return new NHandlebody(1, true); } } // namespace regina regina-4.96/engine/subcomplex/ntrisolidtorus.h000644 000765 000024 00000034063 12377775506 021544 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/ntrisolidtorus.h * \brief Deals with triangular solid tori in a triangulation. */ #ifndef __NTRISOLIDTORUS_H #ifndef __DOXYGEN #define __NTRISOLIDTORUS_H #endif #include "regina-core.h" #include "maths/nperm4.h" #include "subcomplex/nstandardtri.h" namespace regina { class NTetrahedron; /** * \weakgroup subcomplex * @{ */ /** * Represents a three-tetrahedron triangular solid torus in a triangulation. * A three-tetrahedron triangular solid torus is a three-tetrahedron * triangular prism with its two ends identified. * * The resulting triangular solid torus will have all edges as boundary * edges. Three of these will be axis edges (parallel to the * axis of the solid torus). Between the axis edges will be three * annuli, each with two internal edges. One of these internal edges will * meet all three tetrahedra (the \a major edge) and one of these internal * edges will only meet two of the tetrahedra (the \a minor edge). * * Assume the axis of the layered solid torus is oriented. The three * major edges together form a loop on the boundary torus. This loop can * be oriented to run around the solid torus in the same direction as * the axis; this then induces an orientation on the boundary of a * meridinal disc. Thus, using an axis edge as longitude, the three major * edges will together form a (1,1) curve on the boundary torus. * * We can now orient the minor edges so they also run around the solid torus * in the same direction as the axis, together forming a * (2, -1) curve on the boundary torus. * * Finally, the three tetrahedra can be numbered 0, 1 and 2 in an order * that follows the axis, and the annuli can be numbered 0, 1 and 2 in * an order that follows the meridinal disc boundary so that annulus * \a i does not use any faces from tetrahedron \a i. * * Note that all three tetrahedra in the triangular solid torus must be * distinct. * * All optional NStandardTriangulation routines are implemented for this * class. */ class REGINA_API NTriSolidTorus : public NStandardTriangulation { private: NTetrahedron* tet[3]; /**< The tetrahedra that make up this solid torus. */ NPerm4 vertexRoles[3]; /**< For tetrahedron \a i, vertexRoles[i] is a permutation p chosen so that the axis edge for that tetrahedron runs from vertex p[0] to p[3] and the major edge opposite that axis edge runs from vertex p[1] to p[2]. */ public: /** * Destroys this solid torus. */ virtual ~NTriSolidTorus(); /** * Returns a newly created clone of this structure. * * @return a newly created clone. */ NTriSolidTorus* clone() const; /** * Returns the requested tetrahedron in this solid torus. * See the general class notes for further details. * * @param index specifies which tetrahedron in the solid torus * to return; this must be 0, 1 or 2. * @return the requested tetrahedron. */ NTetrahedron* getTetrahedron(int index) const; /** * Returns a permutation represeting the role that each vertex * of the requested tetrahedron plays in the solid torus. * The permutation returned (call this p) maps 0, 1, 2 and * 3 to the four vertices of tetrahedron \a index so that the edge * from p[0] to p[3] is an oriented axis * edge, and the path from vertices p[0] to p[1] * to p[2] to p[3] follows the three oriented * major edges. In particular, the major edge for annulus * \a index will run from vertices p[1] to p[2]. * Edges p[0] to p[2] and p[1] to * p[3] will both be oriented minor edges. * * Note that annulus index+1 uses face p[1] of * the requested tetrahedron and annulus index+2 uses * face p[2] of the requested tetrahedron. Both annuli * use the axis edge p[0] to p[3], and each * annulus uses one other major edge and one other minor edge so * that (according to homology) the axis edge equals the major * edge plus the minor edge. * * See the general class notes for further details. * * @param index specifies which tetrahedron in the solid torus * to examine; this must be 0, 1 or 2. * @return a permutation representing the roles of the vertices * of the requested tetrahedron. */ NPerm4 getVertexRoles(int index) const; /** * Determines whether the two triangles of the requested annulus are * glued to each other. * * If the two triangles are glued, parameter \a roleMap will be * modified to return a permutation describing how the vertex * roles are glued to each other. This will describe directly * how axis edges, major edges and minor edges map to each other * without having to worry about the specific assignment of * tetrahedron vertex numbers. For a discussion of vertex * roles, see getVertexRoles(). * * Note that annulus index uses faces * from tetrahedra index+1 and index+2. * The gluing permutation that maps vertices * of tetrahedron index+1 to vertices of tetrahedron * index+2 will be getVertexRoles(index+2) * roleMap * * getVertexRoles(index+1).inverse(). * * @param index specifies which annulus on the solid torus * boundary to examine; this must be 0, 1 or 2. * @param roleMap a pointer to a permutation that, if this * routine returns \c true, will be modified to describe the gluing * of vertex roles. This parameter may be \c null. * @return \c true if and only if the two triangles of the requested * annulus are glued together. */ bool isAnnulusSelfIdentified(int index, NPerm4* roleMap) const; /** * Determines whether the two given annuli are linked in a * particular fashion by a layered chain. * * In this scenario, both of the given annuli meet one face of * the top tetrahedron and one face of the bottom tetrahedron of * the layered chain. * * To be identified by this routine, the layered chain * (described by NLayeredChain) must be attached as follows. * The two directed major edges of the two annuli should * correspond to the two hinge edges of the layered chain (with * both hinge edges pointing in the same direction around the * solid torus formed by the layered chain). The two directed * diagonals of the layered chain (between the two top faces and * between the two bottom faces, each pointing in the opposite * direction to the hinge edges around the solid torus formed by * the layered chain) should be identified and must correspond * to the (identified) two directed minor edges of the two * annuli. The remaining boundary edges of the layered chain * should correspond to the axis edges of the triangular solid * torus (this correspondence is determined by the previous * identifications). * * @param otherAnnulus the annulus on the solid torus boundary * \a not to be examined; this must be 0, 1 or 2. * @return the number of tetrahedra in the layered chain if the * two annuli are linked as described, or 0 otherwise. */ unsigned long areAnnuliLinkedMajor(int otherAnnulus) const; /** * Determines whether the two given annuli are linked in a * particular fashion by a layered chain. * * In this scenario, one of the given annuli meets both faces of * the top tetrahedron and the other annulus meets both faces of the * bottom tetrahedron of the layered chain. * * To be identified by this routine, the layered chain * (described by NLayeredChain) must be attached as follows. * We shall refer to the two hinge edges of the layered chain as * \e first and \e second. * * The two diagonals of the layered chain (between the two top * faces and between the two bottom faces) should correspond to * the two directed major edges of the two annuli, with the major * edges both pointing from top hinge edge to bottom hinge edge. * The other boundary edges of the layered chain that are not * hinge edges should correspond to the two directed minor edges * of the two annuli, with the minor edges both pointing from * bottom hinge edge to top hinge edge. The hinge edges * themselves should correspond to the axis edges of the * triangular solid torus (this correspondence is determined by * the previous identifications; the axis edge between the two * annuli will be identified to both of the others in reverse). * * @param otherAnnulus the annulus on the solid torus boundary * \a not to be examined; this must be 0, 1 or 2. * @return the number of tetrahedra in the layered chain if the * two annuli are linked as described, or 0 otherwise. */ unsigned long areAnnuliLinkedAxis(int otherAnnulus) const; /** * Determines if the given tetrahedron forms part of a * three-tetrahedron triangular solid torus with its vertices * playing the given roles in the solid torus. * * Note that the six boundary triangles of the triangular solid * torus need not be boundary triangles within the overall * triangulation, i.e., they may be identified with each other * or with faces of other tetrahedra. * * @param tet the tetrahedron to examine. * @param useVertexRoles a permutation describing the role each * tetrahedron vertex must play in the solid torus; this must be * in the same format as the permutation returned by * getVertexRoles(). * @return a newly created structure containing details of the * solid torus with the given tetrahedron as tetrahedron 0, or * \c null if the given tetrahedron is not part of a triangular * solid torus with the given vertex roles. */ static NTriSolidTorus* formsTriSolidTorus(NTetrahedron* tet, NPerm4 useVertexRoles); NManifold* getManifold() const; NAbelianGroup* getHomologyH1() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; void writeTextLong(std::ostream& out) const; private: /** * Creates a new uninitialised structure. */ NTriSolidTorus(); }; /*@}*/ // Inline functions for NTriSolidTorus inline NTriSolidTorus::NTriSolidTorus() { } inline NTriSolidTorus::~NTriSolidTorus() { } inline NTetrahedron* NTriSolidTorus::getTetrahedron(int index) const { return tet[index]; } inline NPerm4 NTriSolidTorus::getVertexRoles(int index) const { return vertexRoles[index]; } inline std::ostream& NTriSolidTorus::writeName(std::ostream& out) const { return out << "TST"; } inline std::ostream& NTriSolidTorus::writeTeXName(std::ostream& out) const { return out << "\\mathop{\\rm TST}"; } inline void NTriSolidTorus::writeTextLong(std::ostream& out) const { out << "3-tetrahedron triangular solid torus"; } } // namespace regina #endif regina-4.96/engine/subcomplex/ntrivialtri.cpp000644 000765 000024 00000020367 12377776711 021343 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "algebra/nabeliangroup.h" #include "manifold/nhandlebody.h" #include "manifold/nlensspace.h" #include "manifold/nsimplesurfacebundle.h" #include "subcomplex/ntrivialtri.h" #include "triangulation/nboundarycomponent.h" #include "triangulation/ncomponent.h" #include "triangulation/nedge.h" #include "triangulation/ntriangle.h" namespace regina { const int NTrivialTri::N2 = 200; const int NTrivialTri::N3_1 = 301; const int NTrivialTri::N3_2 = 302; const int NTrivialTri::SPHERE_4_VERTEX = 5000; const int NTrivialTri::BALL_3_VERTEX = 5100; const int NTrivialTri::BALL_4_VERTEX = 5101; NTrivialTri* NTrivialTri::isTrivialTriangulation(const NComponent* comp) { // Since the triangulations are so small we can use census results // to recognise the triangulations by properties alone. // Are there any boundary components? if (! comp->isClosed()) { if (comp->getNumberOfBoundaryComponents() == 1) { // We have precisely one boundary component. NBoundaryComponent* bc = comp->getBoundaryComponent(0); if (! bc->isIdeal()) { // The boundary component includes boundary triangles. // Look for a one-tetrahedron ball. if (comp->getNumberOfTetrahedra() == 1) { if (bc->getNumberOfTriangles() == 4) return new NTrivialTri(BALL_4_VERTEX); if (bc->getNumberOfTriangles() == 2 && comp->getNumberOfVertices() == 3) return new NTrivialTri(BALL_3_VERTEX); } } } // Not recognised. return 0; } // Otherwise we are dealing with a closed component. // Before we do our validity check, make sure the number of // tetrahedra is in the supported range. if (comp->getNumberOfTetrahedra() > 3) return 0; // Is the triangulation valid? // Since the triangulations is closed we know that the vertices are // valid; all that remains is to check the edges. unsigned long nEdges = comp->getNumberOfEdges(); unsigned long i; for (i = 0; i < nEdges; i++) if (! comp->getEdge(i)->isValid()) return 0; // Test for the specific triangulations that we know about. if (comp->getNumberOfTetrahedra() == 2) { if (comp->isOrientable()) { if (comp->getNumberOfVertices() == 4) { // There's only one closed valid two-tetrahedron // four-vertex orientable triangulation. return new NTrivialTri(SPHERE_4_VERTEX); } } else { // There's only one closed valid two-tetrahedron non-orientable // triangulation. return new NTrivialTri(N2); } return 0; } if (comp->getNumberOfTetrahedra() == 3) { if (! comp->isOrientable()) { // If the triangulation is valid and the edge degrees // are 2,4,4,6 then we have N(3,1) or N(3,2). // All of the vertices are valid since there are no boundary // triangles; we thus only need to check the edges. if (comp->getNumberOfEdges() != 4) return 0; long degree[4]; for (i = 0; i < 4; i++) degree[i] = comp->getEdge(i)->getDegree(); std::sort(degree, degree + 4); if (degree[0] == 2 && degree[1] == 4 && degree[2] == 6 && degree[3] == 6) { // We have N(3,1) or N(3,2)! // Search for Mobius band triangles. unsigned long nTriangles = comp->getNumberOfTriangles(); for (i = 0; i < nTriangles; i++) if (comp->getTriangle(i)->isMobiusBand()) return new NTrivialTri(N3_2); return new NTrivialTri(N3_1); } } } return 0; } NManifold* NTrivialTri::getManifold() const { if (type == SPHERE_4_VERTEX) return new NLensSpace(1, 0); else if (type == BALL_3_VERTEX || type == BALL_4_VERTEX) return new NHandlebody(0, true); else if (type == N2) return new NSimpleSurfaceBundle(NSimpleSurfaceBundle::S2xS1_TWISTED); else if (type == N3_1 || type == N3_2) return new NSimpleSurfaceBundle(NSimpleSurfaceBundle::RP2xS1); return 0; } NAbelianGroup* NTrivialTri::getHomologyH1() const { NAbelianGroup* ans = new NAbelianGroup(); if (type == N2) ans->addRank(); else if (type == N3_1 || type == N3_2) { ans->addRank(); ans->addTorsionElement(2); } return ans; } std::ostream& NTrivialTri::writeName(std::ostream& out) const { if (type == SPHERE_4_VERTEX) out << "S3 (4-vtx)"; else if (type == BALL_3_VERTEX) out << "B3 (3-vtx)"; else if (type == BALL_4_VERTEX) out << "B3 (4-vtx)"; else if (type == N2) out << "N(2)"; else if (type == N3_1) out << "N(3,1)"; else if (type == N3_2) out << "N(3,2)"; return out; } std::ostream& NTrivialTri::writeTeXName(std::ostream& out) const { if (type == SPHERE_4_VERTEX) out << "S^3_{v=4}"; else if (type == BALL_3_VERTEX) out << "B^3_{v=3}"; else if (type == BALL_4_VERTEX) out << "B^3_{v=4}"; else if (type == N2) out << "N_{2}"; else if (type == N3_1) out << "N_{3,1}"; else if (type == N3_2) out << "N_{3,2}"; return out; } void NTrivialTri::writeTextLong(std::ostream& out) const { if (type == SPHERE_4_VERTEX) out << "Two-tetrahedron four-vertex 3-sphere"; else if (type == BALL_3_VERTEX) out << "One-tetrahedron three-vertex ball"; else if (type == BALL_4_VERTEX) out << "One-tetrahedron four-vertex ball"; else if (type == N2) out << "Non-orientable triangulation N(2)"; else if (type == N3_1) out << "Non-orientable triangulation N(3,1)"; else if (type == N3_2) out << "Non-orientable triangulation N(3,2)"; } } // namespace regina regina-4.96/engine/subcomplex/ntrivialtri.h000644 000765 000024 00000013663 12377775507 021013 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/ntrivialtri.h * \brief Deals with a few specific hard-coded trivial triangulations. */ #ifndef __NTRIVIALTRI_H #ifndef __DOXYGEN #define __NTRIVIALTRI_H #endif #include "regina-core.h" #include "subcomplex/nstandardtri.h" namespace regina { /** * \weakgroup subcomplex * @{ */ /** * Represents one of a few particular hard-coded trivial triangulations * that do not belong to any of the other larger families. * * All optional NStandardTriangulation routines are implemented for this * class. */ class REGINA_API NTrivialTri : public NStandardTriangulation { public: /** * Represents the two-tetrahedron four-vertex triangulation of * the 3-sphere. */ static const int SPHERE_4_VERTEX; /** * Represents the one-tetrahedron three-vertex triangulation of * the ball. This is a single tetrahedron with two faces as * boundary and the other two faces folded together. */ static const int BALL_3_VERTEX; /** * Represents the one-tetrahedron four-vertex triangulation of * the ball. This is a single tetrahedron with all four faces * as boundary. */ static const int BALL_4_VERTEX; /** * Represents the two-tetrahedron triangulation N(2) of the * twisted 2-sphere bundle over the circle. */ static const int N2; /** * Represents the three-tetrahedron triangulation N(3,1) of the * projective plane bundle over the circle. This particular * triangulation has no Mobius band triangles. */ static const int N3_1; /** * Represents the three-tetrahedron triangulation N(3,2) of the * projective plane bundle over the circle. This particular * triangulation has two Mobius band triangles. */ static const int N3_2; private: int type; /**< The specific triangulation being represented. This must be one of the triangulation constants defined in this class. */ public: /** * Returns a newly created clone of this structure. * * @return a newly created clone. */ NTrivialTri* clone() const; /** * Returns the specific trivial triangulation being represented. * * @return the specific triangulation. This will be one of the * triangulation constants defined in this class. */ int getType() const; /** * Determines if the given triangulation component is one of the * trivial triangulations recognised by this class. * * @param comp the triangulation component to examine. * @return a newly created structure representing the trivial * triangulation, or \c null if the given component is not one * of the triangulations recognised by this class. */ static NTrivialTri* isTrivialTriangulation(const NComponent* comp); NManifold* getManifold() const; NAbelianGroup* getHomologyH1() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; void writeTextLong(std::ostream& out) const; private: /** * Creates a new structure. */ NTrivialTri(int newType); }; /*@}*/ // Inline functions for NTrivialTri inline NTrivialTri::NTrivialTri(int newType) : type(newType) { } inline NTrivialTri* NTrivialTri::clone() const { return new NTrivialTri(type); } inline int NTrivialTri::getType() const { return type; } } // namespace regina #endif regina-4.96/engine/subcomplex/ntxicore.cpp000644 000765 000024 00000013566 12377776711 020632 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "subcomplex/ntxicore.h" #include namespace regina { std::string NTxICore::getName() const { std::ostringstream out; writeName(out); return out.str(); } std::string NTxICore::getTeXName() const { std::ostringstream out; writeTeXName(out); return out.str(); } NTxIDiagonalCore::NTxIDiagonalCore(unsigned long newSize, unsigned long newK) : size_(newSize), k_(newK) { // We'll build the actual triangulation last. Meanwhile, fill in // the remaining bits and pieces. bdryTet_[0][0] = 0; bdryTet_[0][1] = 1; bdryTet_[1][0] = size_ - 2; bdryTet_[1][1] = size_ - 1; // All bdryRoles permutations are identities. // No need to change them here. bdryReln_[0] = NMatrix2(1, 0, 0, 1); bdryReln_[1] = NMatrix2(-1, 0, 0, 1); parallelReln_ = NMatrix2(1, size_ - 6, 0, 1); // Off we go! unsigned i; NTetrahedron** t = new NTetrahedron*[size_]; for (i = 0; i < size_; i++) t[i] = core_.newTetrahedron(); // Glue together the pairs of triangles in the central surface. t[0]->joinTo(0, t[1], NPerm4(0, 2, 1, 3)); t[size_ - 2]->joinTo(0, t[size_ - 1], NPerm4(0, 2, 1, 3)); // Glue together the long diagonal line of quads, and hook the ends // together using the first pair of triangles. t[0]->joinTo(1, t[3], NPerm4(2, 3, 1, 0)); for (i = 3; i < size_ - 3; i++) t[i]->joinTo(0, t[i + 1], NPerm4(0, 3)); t[size_ - 3]->joinTo(0, t[1], NPerm4(1, 0, 2, 3)); // Glue the quadrilateral and double-triangular bulges to their // horizontal neighbours. t[1]->joinTo(2, t[2], NPerm4()); t[2]->joinTo(3, t[0], NPerm4(1, 0, 3, 2)); t[size_ - 1]->joinTo(2, t[size_ - 2 - k_], NPerm4(3, 0, 1, 2)); t[size_ - 2]->joinTo(2, t[size_ - 2 - k_], NPerm4(0, 3, 2, 1)); // Glue in the lower edge of each bulges. if (k_ == size_ - 5) t[2]->joinTo(0, t[size_ - 2], NPerm4(1, 3, 2, 0)); else t[2]->joinTo(0, t[3], NPerm4(2, 1, 3, 0)); if (k_ == 1) t[size_ - 1]->joinTo(1, t[2], NPerm4(2, 1, 3, 0)); else t[size_ - 1]->joinTo(1, t[size_ - 1 - k_], NPerm4(3, 2, 0, 1)); // Glue in the lower edge of each quadrilateral. for (i = 3; i <= size_ - 3; i++) { if (i == size_ - 2 - k_) continue; if (i == size_ - 3) t[i]->joinTo(1, t[2], NPerm4(3, 1, 0, 2)); else if (i == size_ - 3 - k_) t[i]->joinTo(1, t[size_ - 2], NPerm4(0, 1, 3, 2)); else t[i]->joinTo(1, t[i + 1], NPerm4(1, 2)); } delete[] t; } NTxIParallelCore::NTxIParallelCore() { // We'll build the actual triangulation last. Meanwhile, fill in // the remaining bits and pieces. bdryTet_[0][0] = 0; bdryTet_[0][1] = 1; bdryTet_[1][0] = 4; bdryTet_[1][1] = 5; // All bdryRoles permutations are identities. // No need to change them here. bdryReln_[0] = bdryReln_[1] = parallelReln_ = NMatrix2(1, 0, 0, 1); // Off we go! // Just hard-code it. It's only one triangulation, and it's highly // symmetric. unsigned i; NTetrahedron** t = new NTetrahedron*[6]; for (i = 0; i < 6; i++) t[i] = core_.newTetrahedron(); t[0]->joinTo(0, t[1], NPerm4(1, 2)); t[4]->joinTo(0, t[5], NPerm4(1, 2)); t[1]->joinTo(2, t[2], NPerm4()); t[5]->joinTo(2, t[3], NPerm4()); t[0]->joinTo(2, t[2], NPerm4(1, 0, 3, 2)); t[4]->joinTo(2, t[3], NPerm4(1, 0, 3, 2)); t[1]->joinTo(1, t[3], NPerm4(2, 0, 3, 1)); t[5]->joinTo(1, t[2], NPerm4(2, 0, 3, 1)); t[0]->joinTo(1, t[3], NPerm4(0, 3)); t[4]->joinTo(1, t[2], NPerm4(0, 3)); delete[] t; } } // namespace regina regina-4.96/engine/subcomplex/ntxicore.h000644 000765 000024 00000050571 12377775510 020270 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file subcomplex/ntxicore.h * \brief Provides various triangulations of the product of the torus * and the interval. */ #ifndef __NTXICORE_H #ifndef __DOXYGEN #define __NTXICORE_H #endif #include "regina-core.h" #include "maths/nmatrix2.h" #include "triangulation/ntriangulation.h" namespace regina { /** * \weakgroup subcomplex * @{ */ /** * Provides a triangulation of the product T x I (the * product of the torus and the interval). Generally these * triangulations are only one tetrahedron thick (i.e., a "thin I-bundle"), * though this is not a strict requirement of this class. Triangulations of * this type are generally used as components of larger triangulations * (such as layered surface bundles). * * This product has two torus boundaries, called the \a upper and * \a lower boundaries. Each of these boundary tori must be formed from * precisely two triangles. This class tracks the mappings between parallel * curves on the upper and lower boundaries, as well as mappings from * boundary curves to specific tetrahedron edges. * * For each of the two torus boundaries, two curves are chosen as * generators of the fundamental group; these curves are called * \a alpha and \a beta. Note that there is no requirement that the * upper \a alpha and \a beta be parallel to the lower \a alpha and * \a beta. The parallelReln() routine can be called to establish the * precise relationship between these upper and lower curves. * * Every object of this class contains a full copy of the triangulation * that it describes (so you should not create excessive objects of this * class without reason). This triangulation can be accessed through the * core() routine. */ class REGINA_API NTxICore : public ShareableObject { protected: NTriangulation core_; /**< A full copy of the T x I triangulation that is described. */ unsigned bdryTet_[2][2]; /**< The tetrahedra that provide the upper and lower boundary triangles. See bdryTet() for details. */ NPerm4 bdryRoles_[2][2]; /**< Describes which tetrahedron vertices play which roles in the upper and lower boundary triangles. See bdryRoles() for details. */ NMatrix2 bdryReln_[2]; /**< Expresses the \a alpha and \a beta curves for each torus boundary in terms of specific tetrahedron edges and vertices. The elements \a bdryReln_[0] and \a bdryReln_[1] refer to the upper and lower boundaries respectively, and each of these matrices must have determinant +1 or -1. See bdryReln() for further details. */ NMatrix2 parallelReln_; /**< Expresses the lower \a alpha and \a beta curves in terms of the upper \a alpha and \a beta curves. See parallelReln() for details. */ public: /** * Returns a full copy of the T x I triangulation that * this object describes. * * Successive calls to this routine will returns the same * triangulation (i.e., it is not recreated each time). The * triangulation that is returned may not be modified or destroyed. * * @return the full triangulation. */ const NTriangulation& core() const; /** * Determines which tetrahedron provides the requested boundary * triangle. * * Recall that the T x I triangulation has two torus * boundaries, each consisting of two boundary triangles. This * routine returns the specific tetrahedron that provides the * given triangle of the given torus boundary. * * What is returned is the index number of the tetrahedron * within the triangulation. To access the tetrahedron itself, * you may call core().getTetrahedron(bdryTet(...)). * * Note that the same tetrahedron may provide more than one * boundary triangle. * * @param whichBdry 0 if the upper boundary should be examined, * or 1 if the lower boundary should be examined. * @param whichTri 0 if the first boundary triangle should be * examined, or 1 if the second boundary triangle should be examined. */ unsigned bdryTet(unsigned whichBdry, unsigned whichTri) const; /** * Describes which tetrahedron vertices play which roles in the * upper and lower boundary triangles. * * Each boundary torus contains two triangles, whose vertices can be * numbered 0, 1 and 2 according to the following diagram. This * diagram is completely symmetric, in that edges 1-2 are no * more special than edges 0-2 or 0-1. The important * observations are that edges 1-2 and 2-1 of each triangle are * identified, edges 0-2 and 2-0 of each triangle are identified and * edges 0-1 and 1-0 of each triangle are identified. * *
         *           *--->>--*
         *           |0  2 / |
         *   First   |    / 1|  Second
         *  triangle v   /   v triangle
         *           |1 /    |
         *           | / 2  0|
         *           *--->>--*
         * 
* * This routine returns a permutation that maps these integers * 0,1,2 to real tetrahedron vertices. Let \a t be the * tetrahedron returned by bdryTet(\a whichBdry, \a whichTri) * and let \a p be the permutation returned by * bdryRoles(\a whichBdry, \a whichTri). Then vertices * \a p[0], \a p[1] and \a p[2] of tetrahedron \a t correspond to * the markings 0, 1 and 2 respectively in the diagram above (and * therefore the boundary triangle is face \a p[3] of the tetrahedron). * * The arguments to this routine affect whether we examine the * upper or lower boundary and whether we examine the first or * second triangle of this boundary * * @param whichBdry 0 if the upper boundary should be examined, * or 1 if the lower boundary should be examined. * @param whichTri 0 if the first boundary triangle should be * examined, or 1 if the second boundary triangle should be examined. * @return the permutation mapping roles 0, 1 and 2 in the * diagram above to real tetrahedron vertex numbers. */ NPerm4 bdryRoles(unsigned whichBdry, unsigned whichTri) const; /** * Returns a 2-by-2 matrix describing the \a alpha and \a beta curves * on a torus boundary in terms of specific tetrahedron edges. * * Consider the first triangle of the given boundary. Let * \a t be the tetrahedron returned by bdryTet(\a whichBdry, 0) and * let \a p be the permutation returned by bdryRoles(\a whichBdry, 0). * * Let \a edge01 be the directed edge from vertex \a p[0] to \a p[1] * of tetrahedron \a t, and let \a edge02 be the directed edge from * vertex \a p[0] to \a p[2] of tetrahedron \a t. Then the * matrix returned by this routine describes how the directed * edges \a edge01 and \a edge02 relate to the \a alpha and \a beta * curves on the given boundary. Specifically: * *
         *     [ alpha ]                  [ edge01 ]
         *     [       ]  =  bdryReln() * [        ] .
         *     [ beta  ]                  [ edge02 ]
         * 
* * It is guaranteed that this matrix has determinant +1 or -1. * * @param whichBdry 0 if the upper boundary should be examined, * or 1 if the lower boundary should be examined. * @return the relationship between the boundary curves and * tetrahedron edges. */ const NMatrix2& bdryReln(unsigned whichBdry) const; /** * Returns a 2-by-2 matrix describing the parallel relationship * between the upper and lower boundary curves. * * Let \a a_u and \a b_u be the upper \a alpha and \a beta * boundary curves. Suppose that the lower \a alpha is parallel * to \a w.\a a_u + \a x.\a b_u, and that the lower \a beta is * parallel to \a y.\a a_u + \a z.\a b_u. Then the matrix * returned will be * *
         *     [ w  x ]
         *     [      ] .
         *     [ y  z ]
         * 
* * In other words, if \a a_l and \a b_l are the lower \a alpha * and \a beta curves respectively, we have * *
         *     [ a_l ]                      [ a_u ]
         *     [     ]  =  parallelReln() * [     ] .
         *     [ b_l ]                      [ b_u ]
         * 
* * @return the relationship between the upper and lower boundary curves. */ const NMatrix2& parallelReln() const; /** * Returns the name of this specific triangulation of * T x I as a human-readable string. * * @return the name of this triangulation. */ std::string getName() const; /** * Returns the name of this specific triangulation of * T x I in TeX format. No leading or trailing dollar * signs will be included. * * @return the name of this triangulation in TeX format. */ std::string getTeXName() const; /** * Writes the name of this specific triangulation of * T x I to the given output stream. The name will be * written as a human-readable string. * * \ifacespython The argument \a out is missing, and is always * assumed to be standard output. * * @param out the output stream to which to write. * @return a reference to the given output stream. */ virtual std::ostream& writeName(std::ostream& out) const = 0; /** * Writes the name of this specific triangulation of * T x I in TeX format to the given output stream. * No leading or trailing dollar signs will be written. * * \ifacespython The argument \a out is missing, and is always * assumed to be standard output. * * @param out the output stream to which to write. * @return a reference to the given output stream. */ virtual std::ostream& writeTeXName(std::ostream& out) const = 0; void writeTextShort(std::ostream& out) const; void writeTextLong(std::ostream& out) const; protected: /** * Default constructor that performs no initialisation. */ NTxICore(); }; /** * One of a family of thin T x I triangulations that typically * appear at the centres of layered torus bundles. Different * triangulations in this family use different numbers of tetrahedra, * with the larger triangulations producing more complicated * relationships between the upper and lower boundary curves. * * Members of this family are parameterised by their size (the number of * tetrahedra) and an additional integer \a k, where * 1 <= \a k <= \a size - 5. Note that this means we must have * \a size >= 6. The member of this family of size \a n with additional * parameter \a k is labelled T_n:k. * * It is worth noting that T_n:k is isomorphic to * T_n:(n-4-k), so in reality there are only [(\a n-4)/2] * different triangulations for a given size (rounded down). * * A triangulation of this family is most easily defined in terms of its * central torus. Central surfaces are described in detail in * "Structures of small closed non-orientable 3-manifold triangulations", * Benjamin A. Burton, J. Knot Theory Ramifications 16 (2007), 545--574; * in particular, see the section on thin I-bundles. * * The central torus begins with two triangles \a u0 and \a u1 (which * eventually provide the upper torus boundary), with a chain of * quadrilaterals \a q1, ..., \a q(\a n-5) descending diagonally beneath * them as illustrated in the diagram below. * * \image html diaginit.png * * We then distort quadrilateral \a qk and attach two more triangles * \a w0 and \a w1 to its side (these will eventually provide the lower * torus boundary). This is illustrated in the following diagram. * * \image html diagdistort.png * * The entire central torus wraps from left to right (so the lower left * edges of most quadrilaterals \a qi are identified with the upper right * edges of \a q(\a i-1), and the left edge of \a qk is identified with * the right edge of \a w1). As an exception, the two uppermost edges are * identified with the two lowermost edges in a parallel fashion (so the * upper left edge of \a u1 is identified with the lower right edge of \a q1, * and the adjacent edges at right angles to these are also identified). * * The four triangles in the central torus correspond to the four tetrahedra * in the triangulation that provide the boundary triangles. The upper boundary * is coned out from triangles \a u0 and \a u1, and the lower boundary is * coned out from triangles \a w0 and \a w1. In each boundary, \a u0 or * \a w0 gives the first boundary triangle and \a u1 or \a w1 gives the second. * The directions of the corresponding \a alpha and \a beta curves are * illustrated below. * * \image html diagbdry.png * * As a final illustration, the example below shows the central surface in * the case (\a n, \a k) = (9, 2). * * \image html diag92.png */ class REGINA_API NTxIDiagonalCore : public NTxICore { private: unsigned long size_; /**< The number of tetrahedra in this T x I triangulation. */ unsigned long k_; /**< The additional parameter \a k as described in the class notes. */ public: /** * Creates a new T x I triangulation with the given * parameters. * * @param newSize the number of tetrahedra in this * triangulation. This must be at least 6. * @param newK the additional parameter \a k as described in the * class notes. This must be between 1 and (\a newSize - 5) * inclusive. */ NTxIDiagonalCore(unsigned long newSize, unsigned long newK); /** * Returns the total number of tetrahedra in this T x I * triangulation. * * @return the total number of tetrahedra. */ unsigned long size() const; /** * Returns the additional parameter \a k as described in the * class notes. * * @return the additional parameter \a k. */ unsigned long k() const; std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; }; /** * A specific six-tetrahedron NTxICore triangulation that does not fit * neatly into other families. * * This triangulation contains the fewest possible number of tetrahedra * (NTxICore triangulations are not seen below six tetrahedra). It is * referred to as T_6^1 in the paper "Structures of small closed * non-orientable 3-manifold triangulations", Benjamin A. Burton, * J. Knot Theory Ramifications 16 (2007), 545--574. * In Regina it is given the name T_6*, to avoid confusion with * the different NTxIDiagonalCore triangulation T_6:1. * * The triangulations of the upper and lower boundary tori are completely * parallel (and in particular, the upper and lower \a alpha curves are * parallel, as are the upper and lower \a beta curves). * * For reference, the central torus of this triangulation is depicted below. * The left and right sides of the diagram are identified, as are the * top and bottom. The four triangles \a u0, \a u1, \a w0 and \a w1 * provide the boundary triangles of the overall triangulation, with the upper * boundary coned out from triangles \a u0 and \a u1 and the lower boundary * coned out from triangles \a w0 and \a w1. In each boundary, \a u0 or * \a w0 gives the first boundary triangle and \a u1 or \a w1 gives the second. * The directions of the corresponding \a alpha and \a beta curves are * are also included. * * \image html parallel.png */ class REGINA_API NTxIParallelCore : public NTxICore { public: /** * Creates a new copy of this T x I triangulation. */ NTxIParallelCore(); std::ostream& writeName(std::ostream& out) const; std::ostream& writeTeXName(std::ostream& out) const; }; /*@}*/ // Inline functions for NTxICore inline NTxICore::NTxICore() { } inline const NTriangulation& NTxICore::core() const { return core_; } inline unsigned NTxICore::bdryTet(unsigned whichBdry, unsigned whichTri) const { return bdryTet_[whichBdry][whichTri]; } inline NPerm4 NTxICore::bdryRoles(unsigned whichBdry, unsigned whichTri) const { return bdryRoles_[whichBdry][whichTri]; } inline const NMatrix2& NTxICore::bdryReln(unsigned whichBdry) const { return bdryReln_[whichBdry]; } inline const NMatrix2& NTxICore::parallelReln() const { return parallelReln_; } inline void NTxICore::writeTextShort(std::ostream& out) const { writeName(out); } inline void NTxICore::writeTextLong(std::ostream& out) const { out << "TxI core: "; writeName(out); } // Inline functions for NTxIDiagonalCore inline unsigned long NTxIDiagonalCore::size() const { return size_; } inline unsigned long NTxIDiagonalCore::k() const { return k_; } inline std::ostream& NTxIDiagonalCore::writeName(std::ostream& out) const { return out << 'T' << size_ << ':' << k_; } inline std::ostream& NTxIDiagonalCore::writeTeXName(std::ostream& out) const { return out << "T_{" << size_ << ':' << k_ << '}'; } inline std::ostream& NTxIParallelCore::writeName(std::ostream& out) const { return out << "T6*"; } inline std::ostream& NTxIParallelCore::writeTeXName(std::ostream& out) const { return out << "T_{6\\ast}"; } } // namespace regina #endif regina-4.96/engine/subcomplex/parallel.eps000644 000765 000024 00000011177 12234011536 020547 0ustar00babstaff000000 000000 %!PS-Adobe-2.0 EPSF-2.0 %%Title: parallel.fig %%Creator: fig2dev Version 3.2 Patchlevel 5-alpha5 %%CreationDate: Wed Sep 28 08:50:52 2005 %%For: bab@skaro (Ben Burton,,,) %%BoundingBox: 0 0 74 80 %Magnification: 1.0000 %%EndComments /$F2psDict 200 dict def $F2psDict begin $F2psDict /mtrx matrix put /col-1 {0 setgray} bind def /col0 {0.000 0.000 0.000 srgb} bind def /col1 {0.000 0.000 1.000 srgb} bind def /col2 {0.000 1.000 0.000 srgb} bind def /col3 {0.000 1.000 1.000 srgb} bind def /col4 {1.000 0.000 0.000 srgb} bind def /col5 {1.000 0.000 1.000 srgb} bind def /col6 {1.000 1.000 0.000 srgb} bind def /col7 {1.000 1.000 1.000 srgb} bind def /col8 {0.000 0.000 0.560 srgb} bind def /col9 {0.000 0.000 0.690 srgb} bind def /col10 {0.000 0.000 0.820 srgb} bind def /col11 {0.530 0.810 1.000 srgb} bind def /col12 {0.000 0.560 0.000 srgb} bind def /col13 {0.000 0.690 0.000 srgb} bind def /col14 {0.000 0.820 0.000 srgb} bind def /col15 {0.000 0.560 0.560 srgb} bind def /col16 {0.000 0.690 0.690 srgb} bind def /col17 {0.000 0.820 0.820 srgb} bind def /col18 {0.560 0.000 0.000 srgb} bind def /col19 {0.690 0.000 0.000 srgb} bind def /col20 {0.820 0.000 0.000 srgb} bind def /col21 {0.560 0.000 0.560 srgb} bind def /col22 {0.690 0.000 0.690 srgb} bind def /col23 {0.820 0.000 0.820 srgb} bind def /col24 {0.500 0.190 0.000 srgb} bind def /col25 {0.630 0.250 0.000 srgb} bind def /col26 {0.750 0.380 0.000 srgb} bind def /col27 {1.000 0.500 0.500 srgb} bind def /col28 {1.000 0.630 0.630 srgb} bind def /col29 {1.000 0.750 0.750 srgb} bind def /col30 {1.000 0.880 0.880 srgb} bind def /col31 {1.000 0.840 0.000 srgb} bind def end save newpath 0 80 moveto 0 0 lineto 74 0 lineto 74 80 lineto closepath clip newpath -139.7 305.1 translate 1 -1 scale /cp {closepath} bind def /ef {eofill} bind def /gr {grestore} bind def /gs {gsave} bind def /sa {save} bind def /rs {restore} bind def /l {lineto} bind def /m {moveto} bind def /rm {rmoveto} bind def /n {newpath} bind def /s {stroke} bind def /sh {show} bind def /slc {setlinecap} bind def /slj {setlinejoin} bind def /slw {setlinewidth} bind def /srgb {setrgbcolor} bind def /rot {rotate} bind def /sc {scale} bind def /sd {setdash} bind def /ff {findfont} bind def /sf {setfont} bind def /scf {scalefont} bind def /sw {stringwidth} bind def /tr {translate} bind def /tnt {dup dup currentrgbcolor 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} bind def /shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul 4 -2 roll mul srgb} bind def /$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def /$F2psEnd {$F2psEnteredState restore end} def $F2psBegin 10 setmiterlimit 0 slj 0 slc 0.06299 0.06299 sc % % Fig objects follow % % % here starts figure with depth 50 % Polyline 0 slj 0 slc 7.500 slw n 2475 3600 m 2475 4500 l 3375 4500 l 3375 3600 l 2475 3600 l 3375 4500 l gs col0 s gr % Polyline n 2925 3600 m 2925 4500 l gs col0 s gr % Polyline n 2475 4050 m 3375 4050 l gs col0 s gr % Polyline gs clippath 2865 4338 m 2865 4170 l 2805 4170 l 2805 4338 l 2805 4338 l 2835 4218 l 2865 4338 l cp eoclip n 2835 4590 m 2835 4185 l gs col0 s gr gr % arrowhead n 2865 4338 m 2835 4218 l 2805 4338 l col0 s % Polyline gs clippath 2637 4170 m 2805 4170 l 2805 4110 l 2637 4110 l 2637 4110 l 2757 4140 l 2637 4170 l cp eoclip n 2385 4140 m 2790 4140 l gs col0 s gr gr % arrowhead n 2637 4170 m 2757 4140 l 2637 4110 l col0 s % Polyline gs clippath 2415 3753 m 2415 3585 l 2355 3585 l 2355 3753 l 2355 3753 l 2385 3633 l 2415 3753 l cp eoclip n 2385 4050 m 2385 3600 l gs col0 s gr gr % arrowhead n 2415 3753 m 2385 3633 l 2355 3753 l col0 s % Polyline gs clippath 3222 4620 m 3390 4620 l 3390 4560 l 3222 4560 l 3222 4560 l 3342 4590 l 3222 4620 l cp eoclip n 2925 4590 m 3375 4590 l gs col0 s gr gr % arrowhead n 3222 4620 m 3342 4590 l 3222 4560 l col0 s /Times-Italic ff 190.50 scf sf 2610 4005 m gs 1 -1 sc (u0) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Italic ff 190.50 scf sf 2790 3780 m gs 1 -1 sc (u1) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Italic ff 190.50 scf sf 3060 4455 m gs 1 -1 sc (w0) dup sw pop 2 div neg 0 rm col0 sh gr /Times-Italic ff 190.50 scf sf 3240 4230 m gs 1 -1 sc (w1) dup sw pop 2 div neg 0 rm col0 sh gr /Symbol ff 190.50 scf sf 2295 4005 m gs 1 -1 sc (a) dup sw pop 2 div neg 0 rm col0 sh gr /Symbol ff 190.50 scf sf 2295 4275 m gs 1 -1 sc (b) dup sw pop 2 div neg 0 rm col0 sh gr /Symbol ff 190.50 scf sf 2790 4725 m gs 1 -1 sc (a) dup sw pop 2 div neg 0 rm col0 sh gr /Symbol ff 190.50 scf sf 3015 4770 m gs 1 -1 sc (b) dup sw pop 2 div neg 0 rm col0 sh gr % here ends figure; $F2psEnd rs showpage %%Trailer %EOF regina-4.96/engine/subcomplex/parallel.fig000644 000765 000024 00000002067 12234011536 020523 0ustar00babstaff000000 000000 #FIG 3.2 Produced by xfig version 3.2.5-alpha5 Landscape Center Metric A4 100.00 Single -2 1200 2 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 6 2475 3600 2475 4500 3375 4500 3375 3600 2475 3600 3375 4500 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 2925 3600 2925 4500 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 2475 4050 3375 4050 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 2835 4590 2835 4185 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 2385 4140 2790 4140 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 2385 4050 2385 3600 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 2925 4590 3375 4590 4 1 0 50 -1 3 12 0.0000 0 150 210 2610 4005 u0\001 4 1 0 50 -1 3 12 0.0000 0 135 210 2790 3780 u1\001 4 1 0 50 -1 3 12 0.0000 0 150 240 3060 4455 w0\001 4 1 0 50 -1 3 12 0.0000 0 135 240 3240 4230 w1\001 4 1 0 50 -1 32 12 0.0000 4 105 120 2295 4005 a\001 4 1 0 50 -1 32 12 0.0000 4 195 105 2295 4275 b\001 4 1 0 50 -1 32 12 0.0000 4 105 120 2790 4725 a\001 4 1 0 50 -1 32 12 0.0000 4 195 105 3015 4770 b\001 regina-4.96/engine/subcomplex/parallel.png000644 000765 000024 00000002620 12234011536 020535 0ustar00babstaff000000 000000 ‰PNG  IHDRbiä © pHYs × ×B(›xtEXtSoftwareESP Ghostscript 815.00yxü:IDAThå™/oäFÆŸ]¸‚‰ y•+­2ýTìí7pÀ©R™MÊmV[*((Ù-+°+•ö´VØy ËÞÛ»þ3cít½¾Ä‰=ž_fÆó>ï3Ù^:¶/NøHŸèoŠM¾ú|3Ý}hF ùÔëA8I€áDEõ5 òÉ,£ø¡¨®ìrŒBý-aÃPËòËS¿fF¾ßL FDþEqúÙÈàŽ;ƒ0@|îX0¤XŽP \ží0ŠøôS¾!9Dûo1ä.Ò{H¹³‘ ´&ªÃ%R˜;O}‡‘!9 éPrÖj÷€è~ó'F.¹ @Ê&sË"àö:h’§…+•Î#Ø$óš‘ï\2È+)7³¦LÛeìCŽ£ƒ#Äl%¶’$–9`NÚ˜‰X—w-…u ÃV»W0¬Ëƒå û d1à !w›x9Ã!÷I‹"Ýmr›lƒ¿€á(¦ÍU¯¿ÿã]KÃ(^YÔ”¿ü8é%°Ê¿²\5¾{bÍ›Ta%Iq¡0Âh™5„ƒèáQ‹13Zf­¿ÜEÕÓsçƒt¼ÿý§÷×·ßö½KU‹êBžòv5 µßlGîõ›ë×ïßÉA›ö8âÈQ´Í ¿,=1LUud¡+ü¤Ÿ¯üV¾""ò]ŸÈ91" ù©I5Qò<KúHqÏ\1Ÿæ* "V8…‡ŽY;¯…ôMô<. €(”<§‰æ‹ 6ÁDOcŒj=by,X׬5ˆœ{Ã×ß"51¤Ë•Û7kÔS×´ÜÝøî›a›RdD™KtðˆèÐtÜR=¡¥€cˆ¯o5mJ‘•Deç»ë©ž²õY~ªÙA, r0€ ;©RÁ ŽÒGq}«Ó"s.©jw•úvr$ßÜiû22jÄSI¥¥àåwwzE51æëE~ ¦OgF…˜a¨ 3«iF…(í’£{f5ɘ?QÐÖr·‰õ ýöÛz‡ƒ®Íe%;¶r»fë­ŒÆDZqÖ¹³!0V!ûˆÚ†°ÏX……ˆ(º†°ÇX7Q¼¨tÎïÂ.c¢¥sCØa¬ü¢N:×3„mÆÊQ¸œùüè ‡ö“3ÃæøÑü àUõqìÓOuâʉÒë\ͨDZnãødïÀFìj*÷à7Õõfšc!õ™ÖÇ?@ÿ“ˆôþ!èhûK,·’y.šV *ÇŒ¶úõ7|õ3[ˆ˜)s%¸¨·ýå2juÀTè#q 2òÂÑFǾ휃Hà–G7Ãá|«tÑ?ÕÄGF”§ukà¦W""*Ñ.Ñ`ÑÇì­§91ž²º3FÁ‘ù([çž ü‚kñ·<0/LÎë "rãÅ­ãöë7­‰•[oC6íä™vÊM¯EX¸éµˆÚ)6á¦/±ñá «›~IêÆ‡?QÿÄ¿éÖ5 vA£AIEND®B`‚regina-4.96/engine/subcomplex/reflector.eps000644 000765 000024 00000017035 12234011536 020737 0ustar00babstaff000000 000000 %!PS-Adobe-2.0 EPSF-2.0 %%Title: reflector.fig %%Creator: fig2dev Version 3.2 Patchlevel 5-alpha7 %%CreationDate: Mon Feb 6 10:17:53 2006 %%BoundingBox: 0 0 590 115 %Magnification: 1.0000 %%EndComments /$F2psDict 200 dict def $F2psDict begin $F2psDict /mtrx matrix put /col-1 {0 setgray} bind def /col0 {0.000 0.000 0.000 srgb} bind def /col1 {0.000 0.000 1.000 srgb} bind def /col2 {0.000 1.000 0.000 srgb} bind def /col3 {0.000 1.000 1.000 srgb} bind def /col4 {1.000 0.000 0.000 srgb} bind def /col5 {1.000 0.000 1.000 srgb} bind def /col6 {1.000 1.000 0.000 srgb} bind def /col7 {1.000 1.000 1.000 srgb} bind def /col8 {0.000 0.000 0.560 srgb} bind def /col9 {0.000 0.000 0.690 srgb} bind def /col10 {0.000 0.000 0.820 srgb} bind def /col11 {0.530 0.810 1.000 srgb} bind def /col12 {0.000 0.560 0.000 srgb} bind def /col13 {0.000 0.690 0.000 srgb} bind def /col14 {0.000 0.820 0.000 srgb} bind def /col15 {0.000 0.560 0.560 srgb} bind def /col16 {0.000 0.690 0.690 srgb} bind def /col17 {0.000 0.820 0.820 srgb} bind def /col18 {0.560 0.000 0.000 srgb} bind def /col19 {0.690 0.000 0.000 srgb} bind def /col20 {0.820 0.000 0.000 srgb} bind def /col21 {0.560 0.000 0.560 srgb} bind def /col22 {0.690 0.000 0.690 srgb} bind def /col23 {0.820 0.000 0.820 srgb} bind def /col24 {0.500 0.190 0.000 srgb} bind def /col25 {0.630 0.250 0.000 srgb} bind def /col26 {0.750 0.380 0.000 srgb} bind def /col27 {1.000 0.500 0.500 srgb} bind def /col28 {1.000 0.630 0.630 srgb} bind def /col29 {1.000 0.750 0.750 srgb} bind def /col30 {1.000 0.880 0.880 srgb} bind def /col31 {1.000 0.840 0.000 srgb} bind def end save newpath 0 115 moveto 0 0 lineto 590 0 lineto 590 115 lineto closepath clip newpath 11.1 199.2 translate 1 -1 scale /cp {closepath} bind def /ef {eofill} bind def /gr {grestore} bind def /gs {gsave} bind def /sa {save} bind def /rs {restore} bind def /l {lineto} bind def /m {moveto} bind def /rm {rmoveto} bind def /n {newpath} bind def /s {stroke} bind def /sh {show} bind def /slc {setlinecap} bind def /slj {setlinejoin} bind def /slw {setlinewidth} bind def /srgb {setrgbcolor} bind def /rot {rotate} bind def /sc {scale} bind def /sd {setdash} bind def /ff {findfont} bind def /sf {setfont} bind def /scf {scalefont} bind def /sw {stringwidth} bind def /tr {translate} bind def /tnt {dup dup currentrgbcolor 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} bind def /shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul 4 -2 roll mul srgb} bind def /$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def /$F2psEnd {$F2psEnteredState restore end} def $F2psBegin 10 setmiterlimit 0 slj 0 slc 0.06299 0.06299 sc % % Fig objects follow % % % here starts figure with depth 55 % Polyline 0 slj 0 slc 15.000 slw [15 68] 68 sd n 2880 2025 m 3600 2025 l gs col0 s gr [] 0 sd % Polyline 0.000 slw n 450 1350 m 2250 1350 l 2250 2700 l 450 2700 l cp gs col7 0.85 shd ef gr % Polyline n 3825 1350 m 5625 1350 l 5625 2700 l 3825 2700 l cp gs col7 0.85 shd ef gr % Polyline n 6300 1350 m 8100 1350 l 8100 2700 l 6300 2700 l cp gs col7 0.85 shd ef gr % here ends figure; % % here starts figure with depth 50 % Polyline 0 slj 0 slc 7.500 slw n 450 1350 m 450 2700 l 2250 2700 l 2700 1800 l 2250 1350 l 450 1350 l 900 1800 l 450 2700 l 2700 1800 l 900 1800 l 2250 1350 l gs col0 s gr % Polyline [45] 0 sd n 2250 2700 m 2250 1350 l 450 2700 l gs col0 s gr [] 0 sd % Polyline n 3825 1350 m 3825 2700 l 5625 2700 l 6075 1800 l 5625 1350 l 3825 1350 l 4275 1800 l 3825 2700 l 6075 1800 l 4275 1800 l 5625 1350 l gs col0 s gr % Polyline [45] 0 sd n 5625 2700 m 5625 1350 l 3825 2700 l gs col0 s gr [] 0 sd % Polyline [45] 0 sd n 8100 2700 m 8100 1350 l 6300 2700 l gs col0 s gr [] 0 sd % here ends figure; % % here starts figure with depth 45 % Polyline 2 slj 0 slc 15.000 slw gs clippath 8903 1894 m 8583 1874 l 8576 1993 l 8895 2014 l 8895 2014 l 8660 1939 l 8903 1894 l cp 373 2054 m 692 2039 l 687 1919 l 367 1934 l 367 1934 l 610 1983 l 373 2054 l cp eoclip n 675 1980 m 632 1982 l 606 1983 l 572 1985 l 533 1988 l 489 1991 l 441 1994 l 392 1998 l 343 2003 l 294 2008 l 248 2014 l 203 2021 l 162 2028 l 124 2036 l 90 2044 l 58 2053 l 30 2063 l 4 2074 l -19 2086 l -40 2099 l -58 2113 l -75 2128 l -90 2145 l -101 2160 l -111 2175 l -121 2192 l -129 2209 l -136 2227 l -142 2246 l -147 2266 l -151 2287 l -153 2309 l -154 2332 l -154 2355 l -152 2379 l -148 2404 l -143 2429 l -137 2454 l -129 2479 l -119 2505 l -107 2530 l -94 2556 l -79 2581 l -63 2605 l -45 2630 l -26 2653 l -5 2677 l 18 2699 l 42 2721 l 67 2742 l 94 2762 l 123 2781 l 153 2800 l 184 2818 l 218 2835 l 241 2846 l 265 2857 l 290 2867 l 316 2877 l 343 2887 l 371 2897 l 401 2907 l 431 2916 l 463 2925 l 496 2934 l 531 2943 l 567 2951 l 604 2960 l 643 2968 l 683 2976 l 724 2983 l 767 2991 l 811 2998 l 857 3005 l 904 3012 l 952 3019 l 1002 3025 l 1052 3031 l 1104 3037 l 1157 3043 l 1212 3048 l 1267 3054 l 1323 3059 l 1380 3064 l 1438 3068 l 1497 3073 l 1556 3077 l 1616 3081 l 1677 3084 l 1738 3088 l 1800 3091 l 1863 3095 l 1926 3098 l 1989 3100 l 2053 3103 l 2118 3106 l 2183 3108 l 2249 3110 l 2315 3112 l 2382 3114 l 2449 3116 l 2518 3118 l 2588 3120 l 2642 3121 l 2697 3123 l 2753 3124 l 2810 3125 l 2868 3126 l 2926 3127 l 2986 3128 l 3046 3129 l 3107 3130 l 3169 3131 l 3232 3132 l 3296 3133 l 3361 3134 l 3427 3135 l 3494 3135 l 3561 3136 l 3630 3137 l 3699 3137 l 3769 3138 l 3840 3138 l 3911 3139 l 3983 3139 l 4056 3140 l 4129 3140 l 4202 3140 l 4276 3140 l 4350 3141 l 4425 3141 l 4500 3141 l 4574 3141 l 4649 3141 l 4724 3141 l 4799 3140 l 4873 3140 l 4947 3140 l 5021 3139 l 5094 3139 l 5167 3139 l 5240 3138 l 5311 3137 l 5382 3137 l 5453 3136 l 5522 3135 l 5591 3135 l 5659 3134 l 5726 3133 l 5792 3132 l 5858 3131 l 5922 3130 l 5985 3129 l 6047 3128 l 6108 3127 l 6169 3126 l 6228 3124 l 6286 3123 l 6343 3122 l 6400 3120 l 6455 3119 l 6509 3117 l 6563 3116 l 6616 3114 l 6667 3113 l 6668 3113 l 6736 3110 l 6804 3108 l 6871 3105 l 6936 3103 l 7001 3100 l 7065 3097 l 7128 3094 l 7190 3091 l 7252 3087 l 7313 3083 l 7373 3079 l 7433 3075 l 7492 3071 l 7550 3067 l 7607 3062 l 7664 3057 l 7719 3051 l 7774 3046 l 7828 3040 l 7880 3034 l 7932 3028 l 7982 3021 l 8032 3015 l 8080 3008 l 8127 3000 l 8172 2993 l 8216 2985 l 8259 2977 l 8300 2969 l 8341 2961 l 8379 2952 l 8416 2943 l 8452 2934 l 8487 2925 l 8520 2915 l 8551 2906 l 8582 2896 l 8611 2886 l 8639 2876 l 8666 2865 l 8691 2855 l 8716 2844 l 8740 2832 l 8762 2821 l 8784 2809 l 8805 2798 l 8836 2779 l 8865 2759 l 8893 2738 l 8919 2717 l 8944 2694 l 8968 2671 l 8991 2647 l 9012 2623 l 9032 2597 l 9050 2571 l 9067 2544 l 9083 2517 l 9097 2490 l 9110 2463 l 9121 2435 l 9130 2408 l 9139 2381 l 9145 2354 l 9150 2328 l 9154 2303 l 9157 2278 l 9158 2254 l 9158 2231 l 9157 2209 l 9154 2189 l 9151 2169 l 9146 2150 l 9141 2132 l 9135 2116 l 9128 2100 l 9116 2080 l 9103 2062 l 9088 2046 l 9071 2032 l 9051 2019 l 9028 2007 l 9001 1997 l 8972 1987 l 8939 1978 l 8903 1970 l 8865 1963 l 8824 1957 l 8783 1952 l 8742 1947 l 8704 1943 l 8670 1940 l 8642 1938 l 8595 1935 l gs col0 s gr gr % arrowhead 0 slj n 373 2054 m 610 1983 l 367 1934 l 373 2054 l cp gs col7 1.00 shd ef gr col0 s % arrowhead n 8903 1894 m 8660 1939 l 8895 2014 l 8903 1894 l cp gs col7 1.00 shd ef gr col0 s % here ends figure; % % here starts figure with depth 40 % Polyline 0 slj 0 slc 7.500 slw n 6300 1350 m 6300 2700 l 8100 2700 l 8550 1800 l 8100 1350 l 6300 1350 l 6750 1800 l 6300 2700 l 8550 1800 l 6750 1800 l 8100 1350 l gs col0 s gr % here ends figure; $F2psEnd rs showpage %%Trailer %EOF regina-4.96/engine/subcomplex/reflector.fig000644 000765 000024 00000002462 12234011536 020713 0ustar00babstaff000000 000000 #FIG 3.2 Produced by xfig version 3.2.5-alpha5 Landscape Center Metric A4 100.00 Single -2 1200 2 2 1 2 2 0 7 55 -1 -1 4.500 0 0 -1 0 0 2 2880 2025 3600 2025 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 11 450 1350 450 2700 2250 2700 2700 1800 2250 1350 450 1350 900 1800 450 2700 2700 1800 900 1800 2250 1350 2 1 1 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 3 2250 2700 2250 1350 450 2700 2 2 0 0 0 7 55 -1 17 2.000 0 0 -1 0 0 5 450 1350 2250 1350 2250 2700 450 2700 450 1350 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 11 3825 1350 3825 2700 5625 2700 6075 1800 5625 1350 3825 1350 4275 1800 3825 2700 6075 1800 4275 1800 5625 1350 2 1 1 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 3 5625 2700 5625 1350 3825 2700 2 2 0 0 0 7 55 -1 17 2.000 0 0 -1 0 0 5 3825 1350 5625 1350 5625 2700 3825 2700 3825 1350 2 1 0 1 0 7 40 -1 -1 0.000 0 0 -1 0 0 11 6300 1350 6300 2700 8100 2700 8550 1800 8100 1350 6300 1350 6750 1800 6300 2700 8550 1800 6750 1800 8100 1350 2 1 1 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 3 8100 2700 8100 1350 6300 2700 2 2 0 0 0 7 55 -1 17 2.000 0 0 -1 0 0 5 6300 1350 8100 1350 8100 2700 6300 2700 6300 1350 3 0 0 2 0 7 45 -1 -1 6.000 0 1 1 8 1 0 2.00 120.00 240.00 1 0 2.00 120.00 240.00 675 1980 -270 1980 -135 2970 2115 3150 7200 3150 9090 2925 9270 1935 8595 1935 0.000 1.000 1.000 1.000 1.000 1.000 1.000 0.000 regina-4.96/engine/subcomplex/reflector.png000644 000765 000024 00000006566 12234011536 020743 0ustar00babstaff000000 000000 ‰PNG  IHDRšPiìÙ pHYs±±Åa†tIMEÖ œà IDATxÚíœ_ˆ$GÇ¿Ñ Gî`' ½ÎŸŽá ;ÑhÅ„kNÄØ ­!(Èìèƒ>ÌäÁ— Ìø¢"AwaA}Øa!KfçŨ$®‰‚aC Í…Ë,‰r–ÁɃ¡¯—ø 'Ƈî™î®î®?Ý=›S§ánggf§ëWŸúÔ¯ºº¦nú¹Ç3ŸF…Çs|§ü‡¸‡wWX¤w~=Òò_õ~^eü×^²¿©ö7qÐ|÷oݪ 6™Ò;9Õ)ÿAæÓŠŠ4›øoý­-›§noUt.2{ç®5IehöOMºÕpÝμ€òlöíF5\t»ŽžísØì_E«.u[nÛVcóÑä¿öæƒkÏš¥¹üòð³_[›˜ÀÑ“®KÊ~Ü­g×n+Ëåà·Ç_}ôèjo<|¡á–Üø7ŽŽÊ¶ÿùÉŸ¾øåSÏ›ÀÛŸj¯Ê‚i9oB_phx諒Ù3±SʛЗ LWƒ—ïÍ>Á¨”7s_‚øß'è«x#@S†Íœ‹? >âì”g³g¢›—é± §upØì”`³àâ´ç%6"4EÙ̹nÖ×(ÏfÏDQ6 .ÀlÔÖ{Àa³OP”Í‚ €vpÒ› 56B4EØÄ¸`º¨Å?>ŽòlöLbãÿXŸÅŸ‡M¿:›8—Xü3 JljÂw4°ÓUåb/~Û‰ÆAøÁ ü8­»ƒ†"—P]ÓPÁsÚoœÖZE¹ÀÚLü[}ª¬Qò&îKP¶Eàì™àg)oöBÔòÞÄ}a‹t:¬ÃloæñË{“äœì\øSÖ4²lR\Fu;öÛõùkeØÌÑH²Is¶bU÷ÞpØ,â—c“æ2Ôãñßl¨±‘B#Ã&ŘÍWEA®)ÉfF‚MŠ €ÃõøA®ÉcÅ/f“æÌüD ƒ\#ÏFˆM—ùø4Ú2l"46Y\0bžYX“É&?ŸM—tü k$ÙH¢á±ÉâL_m3ÏÌsM)6146™\€á:S[§cõ™f?ŸM&àðˆÿ\ì± Y4yl²¹ÀGºb®ÇßW”MM›.˜¥ë/fM›DüÙlr¸dƳFŠ4š,69\€é¤.Z”kJ°I É`“Ç·SÏE¹&‹M2þ4›<.9ñG¹FŽ<–M.—ìÊXS”M Ã&ŸKN™Ö¤Ø0ñ'ÙäsÉ‹?a4q6<.þ°Y=ñ\S˜ ƒ&ƆË%§;>ÍTa’ ĆË%/þsÌï"6*hæò¸˜œÏ® ëìßaâ Ùp¹È¹ g¬aؤâØp¹pâg¬²QBƒé¤+à‚‰÷J2×d“Bƒ».à⿚W¦d®aÙ¤ãÁpAþ¬N2׈٨¡ÁЯ¯s«n|îëÿº'õfç’Q ¾½ÞXãýÉß_øÊ™ FOÛ®`FÜÚò‡¼®îŠžl+Öú¼ÚÙÜ¢ ×x­$~÷ÝSc ý-T‡†ßhÖ¹³Z^B˜àA«@~ƒv.!LOøw,Žø‚r“P,~wŒŽP~ŸQ«LšéQ‹?ßxO\@T UH3â7Ü™TWšéQ‹ßJŒ¸00HH㸞K¶$Ðd‘+Í«mA%Þ&hEË–æPLNßFÜZxÒøÂø˜0‰*¦Ô¡T#še92Öl;ñN5d¥ñLQÉpùB$ÌIH3­ Wj]Ñc”‘F&~—DÂ,¤tO¿OzÁ(z Õ¡i»–ã¾øÌÚúíQŸ/ÍlÔ×â[¿YsÒLfâ2ù1aÊH#ÿk‘0Q+è ÓqÇ?¼Ïnj}DZ„h¼¿–`°MoýEcÚàK£‹ï‚ŽfŸì%X,W¿n‹¹ŽþýÄ–¸Kã‹ã÷'³û“çŠ2 ![îxðš¸Ïé‹Ñ;‹Æ¥®G=-xÞyiü©o׬‘ȓƊï7Ž`·’×5Ii\¸TÓàxž˜¿æ3WšÌ©_ƪi½}Gòï‹I߇ÅAK?Çi„€Ž7è:Þ°‚6\K\œºžaÍЧ÷•~I"ÓÌDµ0šéí:s]ÃTÃð Füa>š\iŽ»Â¶bv™ëš¢Òˆâ÷'3½Ë\×°Ã3F¯G5Àèõ¶7vIÍxL-u9ÆÀê|H ÏFfC, 3®OgšNðÏ ~FâaGQØ5…Âԙ뚢҈ºŒéá Ú¶‚𹞵y@hÆÛÖVâÍð‰áÙ„?§ øÌIešƒ¶„0€JK39¯KtZ\iÝÛÁÅ×C4ÞE\ —2¥™ê¶”0Á '2<›6Ú2Ân-)Í´aK “Š_0@¬A5ÞFG؆3¥7ä„IÍ¡-OšSN˜Œ94eixñ'„IÍ¡q¥Ð{(@³)&“-MþÈ„†ík—(M~NN ÃΡ‘¦%+ ?͸k„5`›H13ÎÞ­Ë ÃæšeI3B«.)L*רJ“¿ü+- ›kDÒÄéÔà/¡ˆ4ïvå…aúÚeIã릴0l®Q–&/þ,a˜ø©ø6qPࣩKã´ma/?¾\i¦Ç¦)/ à÷O”ÆŸ´laÑ$ŒX.j($Ͱ­$ Ûé.CšYöÔož0Ì¡(Mvü¹Â@~]âÔ-" àòÙj¥‰–‹ðæ’ÒøÃn£„0Aþ°¤¥ì¨8¼²…ÒÌe.(ÌR2Í|ά`†QÊ4óμ 0Š™Æ1 5 ·½+fâ(,Ì<×T'Í|¹daa¹FBš0þâÂÌs¤4ýh:÷æ—î°»Ÿ–ðÎT'M¸\²¤0¸¦ËH³cW ài’Òô-#DƒÝ€RŽ4Áø´œ0a®©N½[V˜y®‘¦[Z˜0×H^Ó8¯cŽÆròêì°‹Zå…©6ÓøC»QZÙL3\k•F%Óxý0¿Üô/X.Èûÿ€‰ic4Óí *gÖ)fï°‹©~<‚iVP¤Ó:ï‹aûWuS}2Ó+ÙTø\_JšM+l-5ÐvûYµvhÌÉÄ®h·ã?W#ÍÈ|wR‰0®½È—f}r¶aಔ4y‘Âo@·3Ö>uÿówW# àÇ?©ù%÷•tëWx ùÆkwéUí |ÿ92X —Ã…µMo#ÍæåW{W++Ú-¹<»üxnUEúÕx¯þî/ÝYݹü{ÕÈDû Æ»FÆÌ vÜ€Eª2ºM«‡4¸›»VLJx¸Ëhc»mx›¤§­*èC;úNrœü‘è¡vIÛpV5ô!ÎCx=y“Ü£†ö±e¬ªéäÚ÷¶ØKKvû gÛè­àœ4˜mÚKçùôÎNÎ6:ÍUuÜ1£—5ËÚt‹ÆÍ&YÕÙ‰ŒÊÆãf'»›ÊÙmì8+:K?Æ®C¬Ü*w«:Ïq\B¬UÞY–.ŽK-Â˼]á:.5ˆµ²§ê²ëRq³ç¢ ðPW#YÍTqx®K]ÈõFB4!fÏ¥ÑYMV…R×ÓˆAd;!94sâžK ÍÐVÉ'Ïõ¨çiÊ [ÍâT”zÔÓ@ +ò$¥páiš¡‘BÛ¿ª£‰$ NN €DûÊü?_ÔSÀõàQP† ¥vä-ކ)“P/ÜR‚Ðÿÿ¯zÀõ¸á’\Q ­M© àb;€Ì.“qC_6¹^êA_°“f‡å„± 4ÜfÔ£‰’kœ¬”ÿeU7UF+«–ÚIÿëÐl³*\âÛåþÐ2÷z"==IEND®B`‚regina-4.96/engine/surfaces/boundaries.fig000644 000765 000024 00000004601 12234011536 020510 0ustar00babstaff000000 000000 #FIG 3.2 Produced by xfig version 3.2.5-alpha5 Landscape Center Metric A4 100.00 Single -2 1200 2 6 990 1890 4860 5310 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 2925 2025 135 135 2925 2025 3060 2025 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 4725 5175 135 135 4725 5175 4860 5175 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 1125 5175 135 135 1125 5175 1260 5175 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 2295 2970 1530 4545 4365 4545 3555 2970 2295 2970 2 1 0 1 0 7 55 -1 -1 0.000 0 0 -1 0 0 2 2295 2970 4365 4545 4 1 0 50 -1 0 14 0.0000 0 150 120 2925 2115 0\001 4 1 0 50 -1 0 14 0.0000 0 150 120 4725 5265 1\001 4 1 0 50 -1 0 14 0.0000 0 150 120 1125 5265 2\001 4 1 0 50 -1 0 12 0.0000 0 135 105 4050 4230 2\001 4 1 0 50 -1 0 12 0.0000 0 135 105 2655 3150 0\001 4 1 0 50 -1 0 12 0.0000 0 135 105 3465 3150 1\001 4 1 0 50 -1 0 12 0.0000 0 135 105 3960 4500 0\001 4 1 0 50 -1 0 12 0.0000 0 135 105 1710 4500 1\001 4 1 0 50 -1 0 12 0.0000 0 135 105 2340 3240 2\001 4 1 0 50 -1 0 12 0.0000 0 135 225 3465 3600 T0\001 4 1 0 50 -1 0 12 0.0000 0 135 225 2745 4005 T1\001 -6 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 8325 2025 135 135 8325 2025 8460 2025 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 10125 5175 135 135 10125 5175 10260 5175 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 6525 5175 135 135 6525 5175 6660 5175 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 7 7785 2970 7155 4050 7785 5175 8865 5175 9495 4050 8865 2970 7785 2970 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 7785 2970 9495 4050 7785 5175 7785 2970 4 1 0 50 -1 0 14 0.0000 0 150 120 8325 2115 0\001 4 1 0 50 -1 0 14 0.0000 0 150 120 10125 5265 1\001 4 1 0 50 -1 0 14 0.0000 0 150 120 6525 5265 2\001 4 1 0 50 -1 0 12 0.0000 0 135 105 8190 3150 0\001 4 1 0 50 -1 0 12 0.0000 0 135 105 8820 3150 1\001 4 1 0 50 -1 0 12 0.0000 0 135 105 9225 3825 2\001 4 1 0 50 -1 0 12 0.0000 0 135 105 9270 4095 2\001 4 1 0 50 -1 0 12 0.0000 0 135 105 9225 4410 0\001 4 1 0 50 -1 0 12 0.0000 0 135 105 8820 5130 1\001 4 1 0 50 -1 0 12 0.0000 0 135 105 8145 5130 2\001 4 1 0 50 -1 0 12 0.0000 0 135 105 7875 5040 0\001 4 1 0 50 -1 0 12 0.0000 0 135 105 7695 4905 0\001 4 1 0 50 -1 0 12 0.0000 0 135 105 7290 4095 1\001 4 1 0 50 -1 0 12 0.0000 0 135 105 7695 3375 2\001 4 1 0 50 -1 0 12 0.0000 0 135 225 7560 4365 T2\001 4 1 0 50 -1 0 12 0.0000 0 135 225 8505 4140 T3\001 4 1 0 50 -1 0 12 0.0000 0 135 225 8775 4815 T1\001 4 1 0 50 -1 0 12 0.0000 0 135 225 8820 3465 T0\001 4 1 0 50 -1 0 12 0.0000 0 135 105 7875 3240 1\001 regina-4.96/engine/surfaces/CMakeLists.txt000644 000765 000024 00000002464 12377774107 020455 0ustar00babstaff000000 000000 # surfaces # Files to compile SET ( FILES components crushandcut csv enumerator enumfilter links ndisc ndisctype nnormalsurface nnormalsurfacelist nprism nsanstandard nsoriented nsorientedquad nsquad nsquadoct nsstandard nsurfacefilter nsurfacesubset nxmlfilterreader nxmlfilterreaders nxmlsurfacereader orientable quadtostd sfcombination sfproperties spheres stdtoquad ) # Prepend folder name FOREACH ( SOURCE_FILE ${FILES} ) SET ( SOURCES ${SOURCES} surfaces/${SOURCE_FILE}) ENDFOREACH(SOURCE_FILE) # Set the variable in the parent directory SET( SOURCES ${SOURCES} PARENT_SCOPE) if (${REGINA_INSTALL_DEV}) INSTALL(FILES coordregistry.h coordregistry-impl.h filterregistry.h filterregistry-impl.h flavourregistry.h ndisc.h ndisctype.h nnormalsurface.h nnormalsurfacelist.h normalcoords.h normalflags.h normalspec-impl.h normalspec.tcc nprism.h nsanstandard.h nsmirrored.h nsoriented.h nsorientedquad.h nsquad.h nsquadoct.h nsstandard.h nsurfacefilter.h nsurfacesubset.h nxmlfilterreader.h nxmlsurfacereader.h sfcombination.h sfproperties.h surfacefiltertype.h DESTINATION ${INCLUDEDIR}/surfaces COMPONENT Development) endif (${REGINA_INSTALL_DEV}) regina-4.96/engine/surfaces/components.cpp000644 000765 000024 00000025177 12377776712 020620 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "surfaces/ndisc.h" #include "surfaces/nsstandard.h" #include "surfaces/nsanstandard.h" namespace regina { namespace { /** * Stores a connected component ID for a normal disc. */ struct ComponentData { long id; /**< Stores the ID of the connected component that this disc belongs to. Components are numbered from 0 upwards; -1 means that the component ID is unknown. */ /** * Create a new structure with the component ID initialised to -1. */ ComponentData() : id(-1) { } }; /** * Splits the given normal surface into connected components. * * The surface itself will not be changed. Instead, each * connected component will be appended to the end of the * given list \a dest. Note that the list \a dest will \e not * be emptied at the beginning of this routine (i.e., any * surfaces that were in the list beforehand will be left there). * * The components inserted into \a dest will always be in standard * (tri-quad or tri-quad-oct) coordinates, regardless of the * native coordinate system that is used by the given surface. * Any transverse orientations will be lost. * * This routine is slow, since it performs a depth-first search * over the entire set of normal discs. If the surface contains * a very large number of discs (large enough to cause integer * overflows or exhaust memory) then this routine will give up and * return 0. * * The components inserted into \a dest will be newly created. It is * the responsibility of the caller of this routine to deallocate them. * * \pre The given normal surface is compact (has finitely many discs) * and is also embedded. * * \todo \prob Check for absurdly large numbers of discs and bail * accordingly. * * @param s the surface to split into components. * @param dest the vector into which individual components will * be inserted. * @return the number of connected components. */ unsigned splitIntoComponents(const NNormalSurface& s, std::vector& dest) { // Shamelessly copied from my orientation/two-sidedness code from // years earlier. Some day I will need to make a generic structure // for a depth-first search over normal discs. Not today. // If the precondition (compactness) does not hold, things will get // nasty (read: infinite). if (! s.isCompact()) return 0; // TODO: First check that there aren't too many discs! // All right. Off we go. NDiscSetSurfaceData components(s); // Stores the component ID for each disc. std::queue discQueue; // A queue of discs whose component IDs must be propagated. NDiscSpecIterator it(components); // Runs through the discs whose component IDs might not have yet // been determined. NDiscSpec use; // The disc that currently holds our interest. int nGluingArcs; // The number of arcs on the current disc to // which an adjacent disc might may be glued. NDiscSpec* adjDisc; // The disc to which the current disc is glued. NPerm4 arc[8]; // Holds each gluing arc for the current disc. NPerm4 adjArc; // Represents the corresponding gluing arc on the // adjacent disc. long compID = 0; // The current working component ID. long i; while (true) { // If there's no discs to propagate from, choose the next // one without a component label. while (discQueue.empty() && (! it.done())) { if (components.data(*it).id == -1) { components.data(*it).id = compID++; discQueue.push(*it); } ++it; } if (discQueue.empty()) break; // At the head of the queue is the next already-labelled disc // whose component ID must be propagated. use = discQueue.front(); discQueue.pop(); // Determine along which arcs we may glue other discs. if (use.type < 4) { // Current disc is a triangle. nGluingArcs = 3; for (i = 0; i < 3; i++) arc[i] = regina::triDiscArcs(use.type, i); } else if (use.type < 7) { // Current disc is a quad. nGluingArcs = 4; for (i = 0; i < 4; i++) arc[i] = regina::quadDiscArcs(use.type - 4, i); } else { // Current disc is an octagon. nGluingArcs = 8; for (i = 0; i < 8; i++) arc[i] = regina::octDiscArcs(use.type - 7, i); } // Process any discs that might be adjacent to each of these // gluing arcs. for (i = 0; i < nGluingArcs; ++i) { // Establish which is the adjacent disc. adjDisc = components.adjacentDisc(use, arc[i], adjArc); if (adjDisc == 0) continue; // There is actually a disc glued along this arc. // Propagate the component ID. if (components.data(*adjDisc).id == -1) { components.data(*adjDisc).id = components.data(use).id; discQueue.push(*adjDisc); } // Tidy up. delete adjDisc; } } // Were there any discs at all? if (compID == 0) return 0; // Create the set of normal surfaces! // Note that all vectors are automagically initialised to zero. const NTriangulation* tri = s.getTriangulation(); NNormalSurfaceVector** ans = new NNormalSurfaceVector*[compID]; NNormalSurfaceVector* vec; long coord; if (s.rawVector()->allowsAlmostNormal()) { for (i = 0; i < compID; ++i) ans[i] = new NNormalSurfaceVectorANStandard( 10 * tri->getNumberOfTetrahedra()); for (it.init(components); ! it.done(); ++it) { vec = ans[components.data(*it).id]; coord = 10 * (*it).tetIndex + (*it).type; vec->setElement(coord, (*vec)[coord] + 1); } } else { for (i = 0; i < compID; ++i) ans[i] = new NNormalSurfaceVectorStandard( 7 * tri->getNumberOfTetrahedra()); for (it.init(components); ! it.done(); ++it) { vec = ans[components.data(*it).id]; coord = 7 * (*it).tetIndex + (*it).type; vec->setElement(coord, (*vec)[coord] + 1); } } for (i = 0; i < compID; ++i) dest.push_back(new NNormalSurface(tri, ans[i])); delete[] ans; // All done! return compID; } } // anonymous namespace bool NNormalSurface::disjoint(const NNormalSurface& other) const { // Some sanity tests before we begin. // These should all pass if the user has adhered to the preconditions. if (! (isCompact() && other.isCompact())) return false; if (! (isConnected() && other.isConnected())) return false; // Begin with a local compatibility test. if (! locallyCompatible(other)) return false; // Now we know that the sum of both surfaces is an embedded surface. // Form the sum, pull it apart into connected components, and see // whether we get our original two surfaces back. NNormalSurfaceVector* v = static_cast(vector->clone()); (*v) += *(other.vector); NNormalSurface* sum = new NNormalSurface(triangulation, v); typedef std::vector CompVector; CompVector bits; splitIntoComponents(*sum, bits); bool ans = false; if (bits.size() == 2) for (int c = 0; c < 2; ++c) if (sameSurface(*bits[c])) { ans = true; break; } for (CompVector::iterator it = bits.begin(); it != bits.end(); ++it) delete *it; delete sum; return ans; } } // namespace regina regina-4.96/engine/surfaces/coordregistry-impl.h000644 000765 000024 00000010534 12377775512 021722 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/coordregistry-impl.h * \brief Contains the registry of all normal coordinate systems that can * be used to create and store normal surfaces in 3-manifold triangulations. * * Each time a new coordinate system is created, this registry must be * updated to: * * - add a #include line for the corresponding vector subclass; * - add a corresponding case to each implementation of forCoords(). * * See coordregistry.h for how other routines can use this registry. */ #ifndef __FLAVOURREGISTRY_IMPL_H #ifndef __DOXYGEN #define __FLAVOURREGISTRY_IMPL_H #endif #include "surfaces/coordregistry.h" #include "surfaces/nsstandard.h" #include "surfaces/nsanstandard.h" #include "surfaces/nsquad.h" #include "surfaces/nsquadoct.h" #include "surfaces/nsoriented.h" #include "surfaces/nsorientedquad.h" namespace regina { template inline typename FunctionObject::ReturnType forCoords( NormalCoords coords, FunctionObject func, typename FunctionObject::ReturnType defaultReturn) { switch (coords) { case NS_STANDARD : return func(NormalInfo()); case NS_AN_STANDARD : return func(NormalInfo()); case NS_QUAD : return func(NormalInfo()); case NS_AN_QUAD_OCT : return func(NormalInfo()); case NS_ORIENTED : return func(NormalInfo()); case NS_ORIENTED_QUAD : return func(NormalInfo()); default: return defaultReturn; } } template inline void forCoords(NormalCoords coords, VoidFunctionObject func) { switch (coords) { case NS_STANDARD : func(NormalInfo()); break; case NS_AN_STANDARD : func(NormalInfo()); break; case NS_QUAD : func(NormalInfo()); break; case NS_AN_QUAD_OCT : func(NormalInfo()); break; case NS_ORIENTED : func(NormalInfo()); break; case NS_ORIENTED_QUAD : func(NormalInfo()); break; default: break; } } } // namespace regina #endif regina-4.96/engine/surfaces/coordregistry.h000644 000765 000024 00000020617 12377775514 020770 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/coordregistry.h * \brief Provides access to a registry of all normal coordinate systems * that can be used to create and store normal surfaces in 3-manifold * triangulations. * * Each time a new coordinate system is created, the file * coordregistry-impl.h must be updated to include it. Instructions on * how to do this are included in coordregistry-impl.h. * * External routines can access the registry by calling one of the * forCoords() template functions defined in coordregistry.h. * * \warning You should not include this header unless it is necessary, * since it will automatically import every header for every coordinate * system in the registry. */ // The old registry macros will silently compile but do nothing. // This could lead to nasty surprises, so throw an error if it looks like // people are still trying to use them. #ifdef __FLAVOUR_REGISTRY_BODY #error "The old REGISTER_FLAVOUR macros have been removed. Use forCoords() instead." #endif #ifndef __FLAVOURREGISTRY_H #ifndef __DOXYGEN #define __FLAVOURREGISTRY_H #endif #include "surfaces/normalcoords.h" #include "utilities/registryutils.h" namespace regina { class NNormalSurfaceVector; // For the deprecated NewNormalSurfaceVector. /** * \weakgroup surfaces * @{ */ /** * Allows the user to call a template function whose template parameter * matches a given value of NormalCoords, which is not known * until runtime. In essence, this routine contains a switch/case statement * that runs through all possible coordinate sytems. * * The advantages of this routine are that (i) the user does not need to * repeatedly type such switch/case statements themselves; and (ii) if * a new coordinate system is added then only a small amount of code * needs to be extended to incorporate it. * * This function can only work with coordinate systems in which * you can create and store normal surfaces. All other coordinate systems are * considered invalid for our purposes here. * * In detail: the function object \a func must define a templated * unary bracket operator, so that func(NormalInfo) is * defined for any valid NormalCoords enum value \a c. Then, * when the user calls forCoords(coords, func, defaultReturn), * this routine will call func(NormalInfo) and pass back * the corresponding return value. If \a coords does not denote a valid * coordinate system as described above, then forCoords() will pass back * \a defaultReturn instead. * * There is also a two-argument variant of forCoords() that works with * void functions. * * \pre The function object must have a typedef \a ReturnType indicating * the return type of the corresponding templated unary bracket operator. * Inheriting from Returns<...> is a convenient way to ensure this. * * \ifacespython Not present. * * @param coords the given normal coordinate system. * @param func the function object whose unary bracket operator we will * call with a NormalInfo object. * @param defaultReturn the value to return if the given * coordinate system is invalid. * @return the return value from the corresponding unary bracket * operator of \a func, or \a defaultReturn if the given * coordinate system is invalid. */ template typename FunctionObject::ReturnType forCoords( NormalCoords coords, FunctionObject func, typename FunctionObject::ReturnType defaultReturn); /** * Allows the user to call a template function whose template parameter * matches a given value of NormalCoords, which is not known * until runtime. In essence, this routine contains a switch/case statement * that runs through all possible coordinate sytems. * * The advantages of this routine are that (i) the user does not need to * repeatedly type such switch/case statements themselves; and (ii) if * a new coordinate system is added then only a small amount of code * needs to be extended to incorporate it. * * This function can only work with coordinate systems in which * you can create and store normal surfaces. All other coordinate systems are * considered invalid for our purposes here. * * In detail: the function object \a func must define a templated * unary bracket operator, so that func(NormalInfo) is * defined for any valid NormalCoords enum value \a c. Then, * when the user calls forCoords(coords, func), * this routine will call func(NormalInfo) in turn. * If \a coords does not denote a valid coordinate system as described above, * then forCoords() will do nothing. * * There is also a three-argument variant of forCoords() that works with * functions with return values. * * \ifacespython Not present. * * @param coords the given normal coordinate system. * @param func the function object whose unary bracket operator we will * call with a NormalInfo object. */ template void forCoords(NormalCoords coords, VoidFunctionObject func); /** * A legacy typedef provided for backward compatibility only. * * \deprecated The old NewNormalSurfaceVector class has been redesigned * as the more general template class NewFunction1, and moved into the * header registryutils.h. This typedef is provided for backward * compatibility, and will be removed in some future version of Regina. */ typedef NewFunction1 NewNormalSurfaceVector; /** * A deprecated alias for the registry-based template function forCoords(). * See forCoords() for further details. */ template inline typename FunctionObject::ReturnType forFlavour( NormalCoords coords, FunctionObject func, typename FunctionObject::ReturnType defaultReturn) { return forCoords(coords, func, defaultReturn); } /** * A deprecated alias for the registry-based template function forCoords(). * See forCoords() for further details. */ template inline void forFlavour(NormalCoords coords, VoidFunctionObject func) { forCoords(coords, func); } /*@}*/ } // namespace regina // Import template implementations: #include "surfaces/coordregistry-impl.h" #endif regina-4.96/engine/surfaces/crushandcut.cpp000644 000765 000024 00000176763 12377776713 020767 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "enumerate/ntreetraversal.h" #include "surfaces/nnormalsurface.h" #include "surfaces/nprism.h" #include "triangulation/ntriangulation.h" #include "utilities/nthread.h" namespace regina { /** * The bulk of this file contains the implementation for cutAlong(), * which cuts along a normal surface. * * The way this routine operates is as follows: * * - We add an extra set of vertex links to the original normal surface. We * refer to the regions inside these vertex links as "vertex neighbourhoods". * These neighbourhoods are typically balls (though around ideal vertices * they are cones over the corresponding boundary surfaces). * * - If we cut along the new normal surface, each tetrahedron falls * apart into the following types of blocks: * * + Triangular prisms, represented by the class TriPrism. There are * four types of triangular prism, corresponding to the four triangular * normal disc types that bound them. * * + Quadrilateral prisms, represented by the class QuadPrism. There * are three types of quadrilateral prism, corresponding to the * three quadrilateral normal disc types that bound them. * * + Tetrahedra truncated at all four vertices, represented by the * class TruncTet. There is only one type of truncated tetrahedron. * * + Truncated half-tetrahedra, obtained by slicing a truncated * tetrahedron along a quadrilateral normal disc and keeping one of * the two halves that results. This is represented by the class * TruncHalfTet. There are six types of truncated half-tetrahedra, * corresponding to the three choices of "slicing quadrilateral" and * the two choices of which half to keep. * * The reason we add the extra vertex links is to keep this list of * block types small; otherwise we must also deal with \e partially * truncated tetrahedra and half-tetrahedra. * * - We triangulate each of the blocks. There are two types of boundary * for each block: (i) boundary faces that run along the normal * surface, and (ii) boundary faces that run along the joins between * adjacent tetrahedra. Faces (i) can be left alone (they will become * the boundary of the final triangulation); faces (ii) need to be * joined together according to how the original tetrahedra were * joined together. Note that a handful of type (i) boundary faces * run along the extra vertex links, and so these will be glued back * onto the missing vertex neighbourhoods at the end of the cutting * procedure. * * - For each block, we organise the boundaries of type (ii) into * quadrilaterals and hexagons (each of which is the intersection of * the block with a single face of the enclosing tetrahedron). These * are represented by the classes BdryQuad and BdryHex respectively. * * - The overall cutting algorithm then works as follows: * * + Triangulate each block. The class TetBlockSet represents a full * set of triangulated blocks within a single tetrahedron of the * original triangulation. * * + Glue together the type (ii) boundaries between adjacent blocks, * using layerings as needed to make the triangulated quadrilaterals * and hexagons compatible. * * + Construct the missing vertex neighbourhoods and glue them back onto * the appropriate type (i) block boundaries. * * See the individual classes for further details. */ // ------------------------------------------------------------------------ // Supporting classes for cutAlong() // ------------------------------------------------------------------------ namespace { class Bdry; /** * A single triangulated block within a single tetrahedron of the * original triangulation. */ class Block { protected: const NTetrahedron* outerTet_; /**< The "outer tetrahedron". This is the tetrahedron of the original triangulation that contains this block. */ NTetrahedron** innerTet_; /**< The "inner tetrahedra". These are the tetrahedra used to triangulate this block, and also to perform any necessary boundary layerings. */ unsigned nInnerTet_; /**< The number of inner tetrahedra. */ Bdry* bdry_[4]; /**< The four quadrilateral / hexagonal type (ii) boundaries of this block. These are boundaries that meet faces of the outer tetrahedron (not boundaries that run along the original normal surface). Specifically, bdry_[i] is the boundary on face i of the outer tetrahedron (or 0 if this block does not actually meet face i of the outer tetrahedron). */ NTetrahedron* link_[4]; /**< Indicates which inner tetrahedra in this block (if any) face the vertices of the outer tetrahedron. Specifically, if this block contains a triangle on its boundary surrounding vertex i of the outer tetrahedron, and if this triangle is facing vertex i (so the block lies on the side of the triangle away from vertex i, not towards vertex i), then link_[i] is the inner tetrahedron containing this triangle. Otherwise, link_[i] is null. */ NPerm4 linkVertices_[4]; /**< If link_[i] is non-zero, then linkVertices_[i] is a mapping from vertices of the inner tetrahedron \a link_[i] to vertices of the outer tetrahedron \a outerTet. Specifically, if we let V denote vertex i of the outer tetrahedron, then this mapping sends the three vertices of the inner vertex linking triangle surrounding V to the three "parallel" vertices of the triangular face opposite V in the outer tetrahedron. */ public: /** * Destroys the four boundaries, but none of the inner * tetrahedra or the outer tetrahedron. */ virtual ~Block(); /** * Returns the outer tetrahedron. */ const NTetrahedron* outerTet(); /** * Glues this block to the given adjacent block. This * involves taking the quadrilateral or hexagon boundary of * this block that sits on the given face of this block's * outer tetrahedron, and gluing it (using layerings if need * be) to the corresponding quadrilateral or hexagon of the * adjacent block. */ void joinTo(int face, Block* other); /** * Creates a new inner tetrahedron within this block. * It is assumed that this tetrahedron is to be used for * layering on the block boundary. However, this layering * will not be performed by this routine (so the new tetrahedron * that is returned will be isolated). * * This routine assumes that the innerTet_ array has enough * space for a new tetrahedron (which should be true if the * correct arguments were passed to the Block constructor). * * The new tetrahedron will be automatically added to the * same triangulation as the previous tetrahedra in this block. * * \pre This block already contains at least one inner tetrahedron. */ NTetrahedron* layeringTetrahedron(); /** * Attaches the triangle described by link_[vertex] to the * given "small tetrahedron" that forms part of the corresponding * vertex neighbourhood. It is assumed that the small tetrahedron * in the neighbourhood will have its vertices numbered in a * way that represents a "shrunk-down" version of the outer * tetrahedron (where "shrunk-down" means dilation about the * given outer tetrahedron vertex). */ void attachVertexNbd(NTetrahedron* nbd, int vertex); protected: /** * Creates a new block within the given outer tetrahedron. * This constructor creates \a initialNumTet inner tetrahedra, * but also leaves enough extra room in the inner tetrahedron * array for up to \a maxLayerings layerings on the boundaries. * * All new inner tetrahedra created now and in subsequent * layerings will be automatically inserted into the given * triangulation. */ Block(const NTetrahedron* outerTet, unsigned initialNumTet, unsigned maxLayerings, NTriangulation* insertInto); }; /** * A triangular prism, triangulated using three inner tetrahedra. * * See cut-triprism.fig for details of the triangulation. * In this diagram, inner tetrahedra are numbered T0, T1, ..., and * vertices of the inner tetrahedra are indicated using plain integers. * For a block of type 0 (see the constructor for details), vertices * of the outer tetrahedron are indicated using integers in circles. * For blocks of other types, vertex 0 is swapped with vertex \a type * in the outer tetrahedron. */ class TriPrism : public Block { public: /** * Creates a new triangular prism within the given outer * tetrahedron. * * The given block type is an integer between 0 and 3 * inclusive, describing which triangle type in the * outer tetrahedron supplies the two ends of the prism. * * Equivalently, the block type describes which vertex of * the outer tetrahedron this triangular prism surrounds. * * All new inner tetrahedra will be automatically * inserted into the given triangulation. */ TriPrism(const NTetrahedron *outerTet, int type, NTriangulation* insertInto); }; /** * A quadrilateral prism, triangulated using five inner tetrahedra. * * See cut-quadprism.fig for details of the triangulation. * In this diagram, inner tetrahedra are numbered T0, T1, ..., and * vertices of the inner tetrahedra are indicated using plain integers. * For a block of type 1 (see the constructor for details), vertices * of the outer tetrahedron are indicated using integers in circles. * For blocks of other types, the vertices of the outer tetrahedron * are permuted accordingly. */ class QuadPrism : public Block { public: /** * Creates a new quadrilateral prism within the given outer * tetrahedron. * * The given block type is an integer between 0 and 2 * inclusive, describing which quadrilateral type in the * outer tetrahedron supplies the two ends of the prism. * * All new inner tetrahedra will be automatically * inserted into the given triangulation. */ QuadPrism(const NTetrahedron *outerTet, int type, NTriangulation* insertInto); }; /** * A truncated half-tetrahedron, triangulated using eight inner tetrahedra. * * See cut-trunchalftet.fig for details of the triangulation. * In this diagram, inner tetrahedra are numbered T0, T1, ..., and * vertices of the inner tetrahedra are indicated using plain integers. * For a block of type 0 (see the constructor for details), vertices * of the outer tetrahedron are indicated using integers in circles. * For blocks of other types, the vertices of the outer tetrahedron * are permuted accordingly. */ class TruncHalfTet : public Block { public: /** * Creates a new truncated half-tetrahedron within the given * outer tetrahedron. * * The given block type is an integer between 0 and 5 * inclusive, describing which edge of the outer tetrahedron * this half-tetrahedron does not meet at all. * * All new inner tetrahedra will be automatically * inserted into the given triangulation. */ TruncHalfTet(const NTetrahedron *outerTet, int type, NTriangulation* insertInto); }; /** * A truncated tetrahedron, triangulated using eleven inner tetrahedra. * * See cut-trunctet.fig for details of the triangulation. * In this diagram, inner tetrahedra are numbered T0, T1, ..., * vertices of the inner tetrahedra are indicated using plain integers, * and vertices of the outer tetrahedron are indicated using integers in * circles. */ class TruncTet : public Block { public: /** * Creates a new truncated tetrahedron within the given outer * tetrahedron. * * All new inner tetrahedra will be automatically * inserted into the given triangulation. */ TruncTet(const NTetrahedron *outerTet, NTriangulation* insertInto); }; /** * Represents a quadrilateral or hexagonal piece of a block boundary. * This is the intersection of a block with a single face of its * outer tetrahedron. * * For each such quadrilateral or hexagon, we number the faces from * 0 to 1 (for a quadrilateral) or 0 to 3 (for a hexagon); these are * called the \e inner boundary faces. The enclosing face of the * outer tetrahedron is called the \e outer boundary face. * * See boundaries.fig for details of how each quadrilateral or * hexagon is triangulated. The inner boundary faces are numbered * T0, T1, ..., the vertices of each inner boundary face are * numbered using plain integers (these are the \e inner vertex * numbers), and the vertices of the outer boundary face are numbered * using integers in circles (these are the \e outer vertex numbers). */ class Bdry { protected: Block* block_; /**< The block whose boundary this is a piece of. */ NPerm4 outerVertices_; /**< A mapping from the outer vertex numbers 0, 1 and 2 to the corresponding vertex numbers in the outer tetrahedron (block_->outerTet). */ public: /** * A virtual destructor that does nothing. */ virtual ~Bdry(); /** * Identifies (i.e., glues together) this piece of boundary * and the given piece of boundary, performing layerings if * required to make sure that the boundaries are compatible. * * This routine assumes that this and the given piece of * boundary are the same shape (i.e., both quadrilaterals or * both hexagons). */ virtual void joinTo(Bdry* other) = 0; /* PRE: other is same shape */ protected: /** * Initialises a new object with the given block and the * given mapping from outer vertex numbers to vertices of * the outer tetrahedron. */ Bdry(Block* block, NPerm4 outerVertices); }; /** * A piece of block boundary that is a triangulated quadrilateral. * * See boundaries.fig for details of how the quadrilateral is * triangulated, and see the Bdry class notes for what all the * numbers on this diagram actually mean. */ class BdryQuad : public Bdry { private: NTetrahedron* innerTet_[2]; /**< The two inner tetrahedra of the block that supply the two inner boundary faces for this quadrilateral. */ NPerm4 innerVertices_[2]; /**< For the ith inner boundary face, the permutation innerVertices_[i] maps the inner vertex numbers 0, 1 and 2 to the corresponding vertex numbers in the inner tetrahedron innerTet_[i]. */ public: /** * See Bdry::joinTo() for details. */ virtual void joinTo(Bdry* other); private: /** * Initialises a new object with the given block and the * given mapping from outer vertex numbers to vertices of * the outer tetrahedron. */ BdryQuad(Block* block, NPerm4 outerVertices); /** * Layers a new tetrahedron upon the quadrilateral boundary, so * that the triangulated quadrilateral becomes a reflection of * itself. As a result, the diagram in boundaries.fig will * likewise become reflected, and so the faces and vertex numbers * within this diagram will now refer to different tetrahedra * and vertices within the underlying block. */ void reflect(); friend class TriPrism; friend class QuadPrism; friend class TruncHalfTet; }; /** * A piece of block boundary that is a triangulated hexagon. * * See boundaries.fig for details of how the hexagon is * triangulated, and see the Bdry class notes for what all the * numbers on this diagram actually mean. */ class BdryHex : public Bdry { private: NTetrahedron* innerTet_[4]; /**< The four inner tetrahedra of the block that supply the four inner boundary faces for this quadrilateral. */ NPerm4 innerVertices_[4]; /**< For the ith inner boundary face, the permutation innerVertices_[i] maps the inner vertex numbers 0, 1 and 2 to the corresponding vertex numbers in the inner tetrahedron innerTet_[i]. */ public: /** * See Bdry::joinTo() for details. */ virtual void joinTo(Bdry* other); private: /** * Initialises a new object with the given block and the * given mapping from outer vertex numbers to vertices of * the outer tetrahedron. */ BdryHex(Block* block, NPerm4 outerVertices); /** * Layers four new tetrahedra upon the hexagon boundary, so * that the triangulated hexagon becomes a reflection of * itself. As a result, the diagram in boundaries.fig will * likewise become reflected, and so the faces and vertex numbers * within this diagram will now refer to different tetrahedra * and vertices within the underlying block. */ void reflect(); /** * Rotates the diagram from boundaries.fig by a one-third turn, * so that the faces and vertex numbers in boundaries.fig * correspond to different tetrahedra and vertex numbers in * the underlying block. * * This is simply a relabelling operation; no layerings are * performed, and no changes are made to the triangulation * of the block itself. */ void rotate(); friend class TruncHalfTet; friend class TruncTet; }; /** * Stores a full set of triangulated blocks within a single * "outer" tetrahedron of the original triangulation, as formed by * cutting along some normal surface within this original triangulation. */ class TetBlockSet { private: unsigned long triCount_[4]; /**< The number of triangular normal discs of each type within this outer tetrahedron. This does \e not include the "extra" vertex links that we add to slice off a neighbourhood of each vertex of the original triangulation. */ unsigned long quadCount_; /**< The number of quadrilateral normal discs (of any type) within this outer tetrahedron. The \e type of these quadrilaterals is stored in the separate data member \a quadType_. */ int quadType_; /**< The unique quadrilateral normal disc \e type that appears within this outer tetrahedron. This will be 0, 1 or 2 if there are indeed quadrilateral discs (i.e., quadCount_ is positive), or -1 if this outer tetrahedron contains no quadrilateral discs at all (i.e., quadCount_ is zero). */ Block** triPrism_[4]; /**< The array triPrism_[i] contains all of the triangular prism blocks surrounding vertex \a i of the outer tetrahedron, or is null if there are no such blocks. Such blocks exist if and only if the normal surface contains at least one triangular disc of type \a i. If these blocks do exist, they are stored in order moving \e away from vertex \a i of the outer tetrahedron (or equivalently, moving in towards the centre of the outer tetrahedron). */ Block** quadPrism_; /**< An array containing all of the quadrilateral prism blocks, or null if there are no such blocks within this outer tetrahedron. These blocks exist if and only if the normal surface contains two or more quadrilateral discs. If these blocks do exist, they are stored in order moving \e away from vertex 0 of the outer tetrahedron. */ Block* truncHalfTet_[2]; /**< The two truncated half-tetrahedron blocks, or null if there are no such blocks within this outer tetrahedron. These blocks exist if and only if the normal surface contains one or more quadrilateral discs. In this case, the block truncHalfTet_[0] is closer to vertex 0 of the outer tetrahedron, and the block truncHalfTet_[1] is further away. */ Block* truncTet_; /**< The unique truncated tetrahedron block, or null if there is no such block within this outer tetrahedron. This block exists if and only if the normal surface contains no quadrilateral discs. */ NTetrahedron* vertexNbd_[4]; /**< The four small tetrahedra that contribute to the vertex neighbourhoods surrounding the four vertices of the outer tetrahedron. The vertices of each small tetrahedron are numbered in a way that matches the outer tetrahedron (so the small tetrahedron vertexNbd_[i] looks like the outer tetrahedron, shrunk down using a dilation about vertex \a i of the outer tetrahedron). */ public: /** * Creates a full set of triangulated blocks within the given * outer tetrahedron, as formed by cutting along the given normal * surface. * * This contructor also creates the four small tetrahedra in * the vertex neighbourhoods, and glues them to the four * blocks closest to the outer tetrahedron vertices. * * All new inner tetrahedra (that is, the inner tetrahedra * from the triangulated blocks and also the small * tetrahedra in the vertex neighbourhoods) will be automatically * inserted into the given triangulation. */ TetBlockSet(const NNormalSurface* s, unsigned long tetIndex, NTriangulation* insertInto); /** * Destroys all block and boundary structures within this outer * tetrahedron. * * Note that the inner tetrahedra that make up the triangulated * blocks are \e not destroyed (since presumably we are keeping * these inner tetrahedra for the new sliced-open triangulation * that we plan to give back to the user). */ ~TetBlockSet(); /** * Returns the number of blocks that provide quadrilateral * boundaries on the given face of the outer tetrahedron, * surrounding the given vertex of the outer tetrahedron. * * It is assumed that \a face and \a fromVertex are not equal. */ unsigned long numQuadBlocks(int face, int fromVertex); /** * Returns the requested block that provides a quadrilateral * boundary on some particular face of the outer tetrahedron, * surrounding the given vertex of the outer tetrahedron. * * Ordinarily the face number would be passed; however, * it is omitted because it is not actually necessary. * Nevertheless, the choice of face number affects how \e many * such blocks are available; see numQuadBlocks() for details. * * Blocks are numbered 0,1,... outwards from the given vertex of * the outer tetrahedron, in towards the centre of the outer * tetrahedron. The argument \a whichBlock indicates which of * these blocks should be returned. * * It is assumed that \a whichBlock is strictly less than * numQuadBlocks(\a face, \a fromVertex), where \a face is * the relevant face of the outer tetrahedron. */ Block* quadBlock(int fromVertex, unsigned long whichBlock); /** * Returns the (unique) block that provides a hexagon * boundary on the given face of the outer tetrahedron, or * null if there is no such block. */ Block* hexBlock(int face); /** * Returns the small tetrahedron that contributes to the * vertex neighbourhood surrounding the given vertex of the * outer tetrahedron. * * See the data member \a vertexNbd_ for further details. */ NTetrahedron* vertexNbd(int vertex); }; inline Block::~Block() { for (unsigned i = 0; i < 4; ++i) delete bdry_[i]; delete[] innerTet_; } inline const NTetrahedron* Block::outerTet() { return outerTet_; } inline void Block::joinTo(int face, Block* other) { bdry_[face]->joinTo(other->bdry_[outerTet_->adjacentFace(face)]); } inline NTetrahedron* Block::layeringTetrahedron() { return (innerTet_[nInnerTet_++] = innerTet_[0]->getTriangulation()->newTetrahedron()); } inline void Block::attachVertexNbd(NTetrahedron* nbd, int vertex) { link_[vertex]->joinTo(linkVertices_[vertex].preImageOf(vertex), nbd, linkVertices_[vertex]); } inline Block::Block(const NTetrahedron *outerTet, unsigned initialNumTet, unsigned maxLayerings, NTriangulation* insertInto) : outerTet_(outerTet), innerTet_(new NTetrahedron*[initialNumTet + maxLayerings]), nInnerTet_(initialNumTet) { unsigned i; for (i = 0; i < nInnerTet_; ++i) innerTet_[i] = insertInto->newTetrahedron(); std::fill(link_, link_ + 4, static_cast(0)); } TriPrism::TriPrism(const NTetrahedron *outerTet, int type, NTriangulation* insertInto) : Block(outerTet, 3, 3, insertInto) { innerTet_[1]->joinTo(1, innerTet_[0], NPerm4()); innerTet_[1]->joinTo(3, innerTet_[2], NPerm4()); NPerm4 vertices = NPerm4(0, type); BdryQuad* q; bdry_[vertices[0]] = 0; q = new BdryQuad(this, vertices * NPerm4(0, 2, 3, 1)); q->innerTet_[0] = innerTet_[1]; q->innerTet_[1] = innerTet_[2]; q->innerVertices_[0] = NPerm4(2, 3, 1, 0); q->innerVertices_[1] = NPerm4(1, 3, 2, 0); bdry_[vertices[1]] = q; q = new BdryQuad(this, vertices * NPerm4(2, 3)); q->innerTet_[0] = innerTet_[0]; q->innerTet_[1] = innerTet_[2]; q->innerVertices_[0] = NPerm4(2, 1, 0, 3); q->innerVertices_[1] = NPerm4(0, 3, 2, 1); bdry_[vertices[2]] = q; q = new BdryQuad(this, vertices); q->innerTet_[0] = innerTet_[0]; q->innerTet_[1] = innerTet_[1]; q->innerVertices_[0] = NPerm4(3, 1, 0, 2); q->innerVertices_[1] = NPerm4(0, 1, 3, 2); bdry_[vertices[3]] = q; link_[vertices[0]] = innerTet_[0]; linkVertices_[vertices[0]] = vertices * NPerm4(0, 1, 3, 2); } QuadPrism::QuadPrism(const NTetrahedron *outerTet, int type, NTriangulation* insertInto) : Block(outerTet, 5, 4, insertInto) { innerTet_[4]->joinTo(2, innerTet_[0], NPerm4()); innerTet_[4]->joinTo(3, innerTet_[1], NPerm4()); innerTet_[4]->joinTo(0, innerTet_[2], NPerm4()); innerTet_[4]->joinTo(1, innerTet_[3], NPerm4()); NPerm4 vertices( regina::vertexSplitDefn[type][0], regina::vertexSplitDefn[type][2], regina::vertexSplitDefn[type][1], regina::vertexSplitDefn[type][3]); BdryQuad* q; q = new BdryQuad(this, vertices * NPerm4(2, 3, 1, 0)); q->innerTet_[0] = innerTet_[2]; q->innerTet_[1] = innerTet_[1]; q->innerVertices_[0] = NPerm4(1, 0, 2, 3); q->innerVertices_[1] = NPerm4(2, 3, 1, 0); bdry_[vertices[0]] = q; q = new BdryQuad(this, vertices * NPerm4(3, 0, 2, 1)); q->innerTet_[0] = innerTet_[3]; q->innerTet_[1] = innerTet_[2]; q->innerVertices_[0] = NPerm4(2, 1, 3, 0); q->innerVertices_[1] = NPerm4(3, 0, 2, 1); bdry_[vertices[1]] = q; q = new BdryQuad(this, vertices * NPerm4(0, 1, 3, 2)); q->innerTet_[0] = innerTet_[0]; q->innerTet_[1] = innerTet_[3]; q->innerVertices_[0] = NPerm4(3, 2, 0, 1); q->innerVertices_[1] = NPerm4(0, 1, 3, 2); bdry_[vertices[2]] = q; q = new BdryQuad(this, vertices * NPerm4(1, 2, 0, 3)); q->innerTet_[0] = innerTet_[1]; q->innerTet_[1] = innerTet_[0]; q->innerVertices_[0] = NPerm4(0, 3, 1, 2); q->innerVertices_[1] = NPerm4(1, 2, 0, 3); bdry_[vertices[3]] = q; } TruncHalfTet::TruncHalfTet(const NTetrahedron *outerTet, int type, NTriangulation* insertInto): Block(outerTet, 8, 10, insertInto) { innerTet_[1]->joinTo(2, innerTet_[0], NPerm4()); innerTet_[1]->joinTo(1, innerTet_[2], NPerm4()); innerTet_[1]->joinTo(0, innerTet_[3], NPerm4()); innerTet_[2]->joinTo(0, innerTet_[4], NPerm4()); innerTet_[3]->joinTo(1, innerTet_[4], NPerm4()); innerTet_[3]->joinTo(3, innerTet_[5], NPerm4()); innerTet_[5]->joinTo(2, innerTet_[6], NPerm4()); innerTet_[4]->joinTo(2, innerTet_[7], NPerm4()); NPerm4 vertices( NEdge::edgeVertex[type][0], NEdge::edgeVertex[type][1], NEdge::edgeVertex[5 - type][0], NEdge::edgeVertex[5 - type][1]); BdryQuad* q; BdryHex* h; h = new BdryHex(this, vertices * NPerm4(1, 3, 2, 0)); h->innerTet_[0] = innerTet_[2]; h->innerTet_[1] = innerTet_[7]; h->innerTet_[2] = innerTet_[5]; h->innerTet_[3] = innerTet_[4]; h->innerVertices_[0] = NPerm4(2, 0, 1, 3); h->innerVertices_[1] = NPerm4(1, 2, 0, 3); h->innerVertices_[2] = NPerm4(0, 3, 2, 1); h->innerVertices_[3] = NPerm4(0, 2, 1, 3); bdry_[vertices[0]] = h; h = new BdryHex(this, vertices * NPerm4(0, 3, 2, 1)); h->innerTet_[0] = innerTet_[0]; h->innerTet_[1] = innerTet_[7]; h->innerTet_[2] = innerTet_[6]; h->innerTet_[3] = innerTet_[3]; h->innerVertices_[0] = NPerm4(1, 2, 3, 0); h->innerVertices_[1] = NPerm4(3, 2, 0, 1); h->innerVertices_[2] = NPerm4(0, 2, 1, 3); h->innerVertices_[3] = NPerm4(0, 1, 3, 2); bdry_[vertices[1]] = h; q = new BdryQuad(this, vertices * NPerm4(3, 1, 0, 2)); q->innerTet_[0] = innerTet_[2]; q->innerTet_[1] = innerTet_[0]; q->innerVertices_[0] = NPerm4(3, 1, 0, 2); q->innerVertices_[1] = NPerm4(0, 2, 3, 1); bdry_[vertices[2]] = q; q = new BdryQuad(this, vertices * NPerm4(2, 0, 1, 3)); q->innerTet_[0] = innerTet_[6]; q->innerTet_[1] = innerTet_[5]; q->innerVertices_[0] = NPerm4(3, 2, 1, 0); q->innerVertices_[1] = NPerm4(1, 2, 3, 0); bdry_[vertices[3]] = q; link_[vertices[2]] = innerTet_[6]; linkVertices_[vertices[2]] = vertices * NPerm4(3, 2, 0, 1); link_[vertices[3]] = innerTet_[7]; linkVertices_[vertices[3]] = vertices * NPerm4(3, 1, 2, 0); } TruncTet::TruncTet(const NTetrahedron *outerTet, NTriangulation* insertInto) : Block(outerTet, 11, 16, insertInto) { innerTet_[0]->joinTo(2, innerTet_[4], NPerm4()); innerTet_[1]->joinTo(3, innerTet_[7], NPerm4()); innerTet_[2]->joinTo(0, innerTet_[6], NPerm4()); innerTet_[3]->joinTo(1, innerTet_[9], NPerm4()); innerTet_[5]->joinTo(3, innerTet_[4], NPerm4()); innerTet_[5]->joinTo(1, innerTet_[6], NPerm4()); innerTet_[8]->joinTo(0, innerTet_[7], NPerm4()); innerTet_[8]->joinTo(2, innerTet_[9], NPerm4()); innerTet_[4]->joinTo(1, innerTet_[10], NPerm4()); innerTet_[6]->joinTo(3, innerTet_[10], NPerm4()); innerTet_[7]->joinTo(2, innerTet_[10], NPerm4()); innerTet_[9]->joinTo(0, innerTet_[10], NPerm4()); BdryHex* h; h = new BdryHex(this, NPerm4(2, 1, 3, 0)); h->innerTet_[0] = innerTet_[2]; h->innerTet_[1] = innerTet_[8]; h->innerTet_[2] = innerTet_[3]; h->innerTet_[3] = innerTet_[9]; h->innerVertices_[0] = NPerm4(2, 0, 1, 3); h->innerVertices_[1] = NPerm4(1, 2, 0, 3); h->innerVertices_[2] = NPerm4(0, 1, 2, 3); h->innerVertices_[3] = NPerm4(0, 2, 1, 3); bdry_[0] = h; h = new BdryHex(this, NPerm4(3, 2, 0, 1)); h->innerTet_[0] = innerTet_[3]; h->innerTet_[1] = innerTet_[5]; h->innerTet_[2] = innerTet_[0]; h->innerTet_[3] = innerTet_[4]; h->innerVertices_[0] = NPerm4(3, 1, 2, 0); h->innerVertices_[1] = NPerm4(2, 3, 1, 0); h->innerVertices_[2] = NPerm4(1, 2, 3, 0); h->innerVertices_[3] = NPerm4(1, 3, 2, 0); bdry_[1] = h; h = new BdryHex(this, NPerm4(0, 3, 1, 2)); h->innerTet_[0] = innerTet_[0]; h->innerTet_[1] = innerTet_[8]; h->innerTet_[2] = innerTet_[1]; h->innerTet_[3] = innerTet_[7]; h->innerVertices_[0] = NPerm4(0, 2, 3, 1); h->innerVertices_[1] = NPerm4(3, 0, 2, 1); h->innerVertices_[2] = NPerm4(2, 3, 0, 1); h->innerVertices_[3] = NPerm4(2, 0, 3, 1); bdry_[2] = h; h = new BdryHex(this, NPerm4(1, 0, 2, 3)); h->innerTet_[0] = innerTet_[1]; h->innerTet_[1] = innerTet_[5]; h->innerTet_[2] = innerTet_[2]; h->innerTet_[3] = innerTet_[6]; h->innerVertices_[0] = NPerm4(1, 3, 0, 2); h->innerVertices_[1] = NPerm4(0, 1, 3, 2); h->innerVertices_[2] = NPerm4(3, 0, 1, 2); h->innerVertices_[3] = NPerm4(3, 1, 0, 2); bdry_[3] = h; link_[0] = innerTet_[0]; linkVertices_[0] = NPerm4(1, 2, 3, 0); link_[1] = innerTet_[1]; linkVertices_[1] = NPerm4(1, 2, 3, 0); link_[2] = innerTet_[2]; linkVertices_[2] = NPerm4(1, 2, 3, 0); link_[3] = innerTet_[3]; linkVertices_[3] = NPerm4(1, 2, 3, 0); } inline Bdry::~Bdry() { // Empty virtual destructor. } inline Bdry::Bdry(Block* block, NPerm4 outerVertices) : block_(block), outerVertices_(outerVertices) { } void BdryQuad::joinTo(Bdry* other) { // Assume other is a BdryQuad. BdryQuad* dest = static_cast(other); // Get the map from *this* 012 to *dest* tetrahedron vertices. NPerm4 destMap = block_->outerTet()-> adjacentGluing(outerVertices_[3]) * outerVertices_; if (destMap != dest->outerVertices_) { // A reflection is our only recourse. dest->reflect(); if (destMap != dest->outerVertices_) { // This should never happen. std::cerr << "ERROR: Cannot match up BdryQuad pair." << std::endl; ::exit(1); } } // Now we match up perfectly. for (int i = 0; i < 2; ++i) innerTet_[i]->joinTo(innerVertices_[i][3], dest->innerTet_[i], dest->innerVertices_[i] * innerVertices_[i].inverse()); } inline BdryQuad::BdryQuad(Block* block, NPerm4 outerVertices) : Bdry(block, outerVertices) { } void BdryQuad::reflect() { NTetrahedron* layering = block_->layeringTetrahedron(); layering->joinTo(0, innerTet_[1], innerVertices_[1] * NPerm4(3, 2, 1, 0)); layering->joinTo(2, innerTet_[0], innerVertices_[0] * NPerm4(1, 0, 3, 2)); innerTet_[0] = innerTet_[1] = layering; innerVertices_[0] = NPerm4(); innerVertices_[1] = NPerm4(2, 3, 0, 1); outerVertices_ = outerVertices_ * NPerm4(1, 2); } void BdryHex::joinTo(Bdry* other) { // Assume other is a BdryQuad. BdryHex* dest = static_cast(other); // Get the map from *this* 012 to *dest* tetrahedron vertices. NPerm4 destMap = block_->outerTet()-> adjacentGluing(outerVertices_[3]) * outerVertices_; if (destMap.sign() != dest->outerVertices_.sign()) dest->reflect(); while (destMap != dest->outerVertices_) dest->rotate(); // Now we match up perfectly. for (int i = 0; i < 4; ++i) innerTet_[i]->joinTo(innerVertices_[i][3], dest->innerTet_[i], dest->innerVertices_[i] * innerVertices_[i].inverse()); } inline BdryHex::BdryHex(Block* block, NPerm4 outerVertices) : Bdry(block, outerVertices) { } void BdryHex::reflect() { NTetrahedron* layering0 = block_->layeringTetrahedron(); NTetrahedron* layering1 = block_->layeringTetrahedron(); NTetrahedron* layering2 = block_->layeringTetrahedron(); NTetrahedron* layering3 = block_->layeringTetrahedron(); layering0->joinTo(1, innerTet_[3], innerVertices_[3] * NPerm4(1, 3)); layering0->joinTo(2, innerTet_[2], innerVertices_[2] * NPerm4(2, 3)); layering1->joinTo(3, layering0, NPerm4()); layering1->joinTo(1, innerTet_[1], innerVertices_[1] * NPerm4(2, 3, 0, 1)); layering2->joinTo(0, layering0, NPerm4()); layering2->joinTo(1, innerTet_[0], innerVertices_[0] * NPerm4(1, 3, 2, 0)); layering3->joinTo(0, layering1, NPerm4()); layering3->joinTo(3, layering2, NPerm4()); innerTet_[0] = layering2; innerTet_[1] = layering1; innerTet_[2] = layering3; innerTet_[3] = layering3; innerVertices_[0] = NPerm4(0, 3, 1, 2); innerVertices_[1] = NPerm4(1, 0, 3, 2); innerVertices_[2] = NPerm4(3, 2, 0, 1); innerVertices_[3] = NPerm4(3, 0, 1, 2); outerVertices_ = outerVertices_ * NPerm4(1, 2); } void BdryHex::rotate() { NTetrahedron* t = innerTet_[0]; innerTet_[0] = innerTet_[1]; innerTet_[1] = innerTet_[2]; innerTet_[2] = t; NPerm4 p = innerVertices_[0]; innerVertices_[0] = innerVertices_[1]; innerVertices_[1] = innerVertices_[2]; innerVertices_[2] = p; innerVertices_[3] = innerVertices_[3] * NPerm4(1, 2, 0, 3); outerVertices_ = outerVertices_ * NPerm4(1, 2, 0, 3); } TetBlockSet::TetBlockSet(const NNormalSurface* s, unsigned long tetIndex, NTriangulation* insertInto) { unsigned long i, j; for (i = 0; i < 4; ++i) triCount_[i] = s->getTriangleCoord(tetIndex, i).longValue(); NLargeInteger coord; if ((coord = s->getQuadCoord(tetIndex, 0)) > 0) { quadCount_ = coord.longValue(); quadType_ = 0; } else if ((coord = s->getQuadCoord(tetIndex, 1)) > 0) { quadCount_ = coord.longValue(); quadType_ = 1; } else if ((coord = s->getQuadCoord(tetIndex, 2)) > 0) { quadCount_ = coord.longValue(); quadType_ = 2; } else { quadCount_ = 0; quadType_ = -1; } const NTetrahedron* tet = s->getTriangulation()->getTetrahedron(tetIndex); // Build the blocks. // Note in all of this that we insert an extra "fake" triangle at each // vertex (i.e., the entire surface gains a fake set of extra vertex // links). for (i = 0; i < 4; ++i) { if (triCount_[i] == 0) triPrism_[i] = 0; else { triPrism_[i] = new Block*[triCount_[i]]; for (j = 0; j < triCount_[i]; ++j) triPrism_[i][j] = new TriPrism(tet, i, insertInto); } } if (quadCount_ == 0) { quadPrism_ = 0; truncHalfTet_[0] = truncHalfTet_[1] = 0; truncTet_ = new TruncTet(tet, insertInto); } else { if (quadCount_ > 1) { quadPrism_ = new Block*[quadCount_ - 1]; for (j = 0; j < quadCount_ - 1; ++j) quadPrism_[j] = new QuadPrism(tet, quadType_, insertInto); } else quadPrism_ = 0; truncHalfTet_[0] = new TruncHalfTet(tet, 5 - quadType_, insertInto); truncHalfTet_[1] = new TruncHalfTet(tet, quadType_, insertInto); truncTet_ = 0; } for (i = 0; i < 4; ++i) { vertexNbd_[i] = insertInto->newTetrahedron(); if (triCount_[i] > 0) triPrism_[i][0]->attachVertexNbd(vertexNbd_[i], i); else if (quadCount_ == 0) truncTet_->attachVertexNbd(vertexNbd_[i], i); else if (i == 0 || static_cast(i) == NEdge::edgeVertex[quadType_][1]) truncHalfTet_[0]->attachVertexNbd(vertexNbd_[i], i); else truncHalfTet_[1]->attachVertexNbd(vertexNbd_[i], i); } } TetBlockSet::~TetBlockSet() { unsigned long i, j; for (i = 0; i < 4; ++i) if (triPrism_[i]) { for (j = 0; j < triCount_[i]; ++j) delete triPrism_[i][j]; delete[] triPrism_[i]; } if (quadCount_ == 0) { delete truncTet_; } else { if (quadPrism_) { for (j = 0; j < quadCount_ - 1; ++j) delete quadPrism_[j]; delete[] quadPrism_; } delete truncHalfTet_[0]; delete truncHalfTet_[1]; } } unsigned long TetBlockSet::numQuadBlocks(int face, int fromVertex) { // We see all triangular discs surrounding fromVertex. unsigned long ans = triCount_[fromVertex]; if (quadType_ == regina::vertexSplit[face][fromVertex]) { // We also see the quadrilateral discs. ans += quadCount_; } return ans; } Block* TetBlockSet::quadBlock(int fromVertex, unsigned long whichBlock) { // First come the triangular prisms. if (whichBlock < triCount_[fromVertex]) return triPrism_[fromVertex][whichBlock]; // Next comes the truncated half-tetrahedron. if (whichBlock == triCount_[fromVertex]) { if (fromVertex == 0 || fromVertex == NEdge::edgeVertex[quadType_][1]) return truncHalfTet_[0]; else return truncHalfTet_[1]; } // Finally we have the quad prisms. if (fromVertex == 0 || fromVertex == NEdge::edgeVertex[quadType_][1]) return quadPrism_[whichBlock - triCount_[fromVertex] - 1]; else return quadPrism_[ quadCount_ - (whichBlock - triCount_[fromVertex]) - 1]; } Block* TetBlockSet::hexBlock(int face) { if (quadCount_ == 0) return truncTet_; if (face == 0 || face == NEdge::edgeVertex[quadType_][1]) return truncHalfTet_[1]; return truncHalfTet_[0]; } inline NTetrahedron* TetBlockSet::vertexNbd(int vertex) { return vertexNbd_[vertex]; } } // ------------------------------------------------------------------------ // Implementation of cutAlong() // ------------------------------------------------------------------------ NTriangulation* NNormalSurface::cutAlong() const { NTriangulation* ans = new NTriangulation(); NPacket::ChangeEventSpan span(ans); unsigned long nTet = getTriangulation()->getNumberOfTetrahedra(); if (nTet == 0) return ans; unsigned long i; TetBlockSet** sets = new TetBlockSet*[nTet]; for (i = 0; i < nTet; ++i) sets[i] = new TetBlockSet(this, i, ans); NTriangulation::TriangleIterator fit; NTriangle* f; unsigned long tet0, tet1; int face0, face1; int fromVertex0, fromVertex1; NPerm4 gluing; unsigned long quadBlocks; for (fit = getTriangulation()->getTriangles().begin(); fit != getTriangulation()->getTriangles().end(); ++fit) { f = *fit; if (f->isBoundary()) continue; tet0 = f->getEmbedding(0).getTetrahedron()->markedIndex(); tet1 = f->getEmbedding(1).getTetrahedron()->markedIndex(); face0 = f->getEmbedding(0).getTriangle(); face1 = f->getEmbedding(1).getTriangle(); gluing = f->getEmbedding(0).getTetrahedron()->adjacentGluing(face0); for (fromVertex0 = 0; fromVertex0 < 4; ++fromVertex0) { if (fromVertex0 == face0) continue; fromVertex1 = gluing[fromVertex0]; quadBlocks = sets[tet0]->numQuadBlocks(face0, fromVertex0); for (i = 0; i < quadBlocks; ++i) sets[tet0]->quadBlock(fromVertex0, i)->joinTo( face0, sets[tet1]->quadBlock(fromVertex1, i)); sets[tet0]->vertexNbd(fromVertex0)->joinTo( face0, sets[tet1]->vertexNbd(fromVertex1), gluing); } sets[tet0]->hexBlock(face0)->joinTo(face0, sets[tet1]->hexBlock(face1)); } // All done! Clean up. for (i = 0; i < nTet; ++i) delete sets[i]; delete[] sets; return ans; } // ------------------------------------------------------------------------ // Implementation of crush() // ------------------------------------------------------------------------ NTriangulation* NNormalSurface::crush() const { NTriangulation* ans = new NTriangulation(*triangulation); unsigned long nTet = ans->getNumberOfTetrahedra(); if (nTet == 0) return ans; // Work out which tetrahedra contain which quad types. int* quads = new int[nTet]; long whichTet = 0; for (whichTet = 0; whichTet < static_cast(nTet); whichTet++) { if (getQuadCoord(whichTet, 0) != 0) quads[whichTet] = 0; else if (getQuadCoord(whichTet, 1) != 0) quads[whichTet] = 1; else if (getQuadCoord(whichTet, 2) != 0) quads[whichTet] = 2; else quads[whichTet] = -1; } // Run through and fix the tetrahedron gluings. NTetrahedron* tet; NTetrahedron* adj; int adjQuads; NPerm4 adjPerm; NPerm4 swap; int face, adjFace; for (whichTet = 0; whichTet < static_cast(nTet); whichTet++) if (quads[whichTet] == -1) { // We want to keep this tetrahedron, so make sure it's glued // up correctly. tet = ans->getTetrahedron(whichTet); for (face = 0; face < 4; face++) { adj = tet->adjacentTetrahedron(face); if (! adj) continue; adjQuads = quads[ans->tetrahedronIndex(adj)]; if (adjQuads == -1) continue; // We're glued to a bad tetrahedron. Follow around // until we reach a good tetrahedron or a boundary. adjPerm = tet->adjacentGluing(face); adjFace = adjPerm[face]; while (adj && (adjQuads >= 0)) { swap = NPerm4(adjFace, vertexSplitPartner[adjQuads][adjFace]); adjFace = swap[adjFace]; adjPerm = adj->adjacentGluing(adjFace) * swap * adjPerm; adj = adj->adjacentTetrahedron(adjFace); adjFace = adjPerm[face]; if (adj) adjQuads = quads[ans->tetrahedronIndex(adj)]; } // Reglue the tetrahedron face accordingly. tet->unjoin(face); if (! adj) continue; // We haven't yet unglued the face of adj since there is // at least one bad tetrahedron between tet and adj. adj->unjoin(adjFace); tet->joinTo(face, adj, adjPerm); } } // Delete unwanted tetrahedra. for (whichTet = nTet - 1; whichTet >= 0; whichTet--) if (quads[whichTet] >= 0) ans->removeTetrahedronAt(whichTet); delete[] quads; return ans; } bool NNormalSurface::isCompressingDisc(bool knownConnected) const { // Is it even a disc? if (! hasRealBoundary()) return false; if (getEulerChar() != 1) return false; if (! knownConnected) { if (! isConnected()) return false; } // Yep, it's a disc (and hence two-sided). // Count the number of boundary spheres that our triangulation has // to begin with. unsigned long origSphereCount = 0; NTriangulation::BoundaryComponentIterator bit; for (bit = getTriangulation()->getBoundaryComponents().begin(); bit != getTriangulation()->getBoundaryComponents().end(); ++bit) if ((*bit)->getEulerChar() == 2) ++origSphereCount; // Now cut along the disc, and see if we get an extra sphere as a // result. If not, the disc boundary is non-trivial and so the disc // is compressing. std::auto_ptr cut(cutAlong()); if (cut->getNumberOfBoundaryComponents() == getTriangulation()->getNumberOfBoundaryComponents()) { // The boundary of the disc is not a separating curve in the // boundary of the triangulation. Therefore we might end up // converting a torus boundary into a sphere boundary, but the // disc is compressing regardless. return true; } unsigned long newSphereCount = 0; for (bit = cut->getBoundaryComponents().begin(); bit != cut->getBoundaryComponents().end(); ++bit) if ((*bit)->getEulerChar() == 2) ++newSphereCount; if (newSphereCount == origSphereCount) return true; else return false; } /** * Supporting classes for isIncompressible(). */ namespace { class CompressionTest; /** * Manages two parallel searches for compressing discs. * If one search reports that it has found a compressing disc, * then it will cancel the other. * * Each individual search is run through a CompressingTest object * (a subclass of NThread). Before starting, each test thread should * register itself via registerTest(), and if it finds a compressing * disc then it should call hasFound() to cancel the other thread. */ class SharedSearch { private: NMutex mutex_; bool found_; CompressionTest* ct_[2]; public: inline SharedSearch() : found_(false) { ct_[0] = ct_[1] = 0; } inline void registerTest(CompressionTest* ct) { if (! ct_[0]) ct_[0] = ct; else ct_[1] = ct; } inline bool hasFound() const { NMutex::MutexLock lock(mutex_); return found_; } void markFound(); }; /** * A thread class whose task is to locate a compressing disc in a * single connected triangulation with boundary. * * IMPORTANT: A side-effect of run() is that it will always delete * the underlying triangulation. */ class CompressionTest : public NThread { private: NTriangulation* t_; SharedSearch& ss_; NTreeSingleSoln* currSearch_; NMutex searchMutex_; public: inline CompressionTest(NTriangulation* t, SharedSearch& ss) : t_(t), ss_(ss), currSearch_(0) { ss_.registerTest(this); } inline void cancel() { NMutex::MutexLock lock(searchMutex_); if (currSearch_) currSearch_->cancel(); } void* run(void*) { // Remember: run() must delete t_. if (ss_.hasFound()) { delete t_; return 0; } t_->intelligentSimplify(); if (ss_.hasFound()) { delete t_; return 0; } // Try for a simple answer first. if (t_->hasSimpleCompressingDisc()) { ss_.markFound(); delete t_; return 0; } if (ss_.hasFound()) { delete t_; return 0; } // The LP-and-crush method is only suitable for // orientable triangulations with a single boundary component. if (t_->getNumberOfBoundaryComponents() > 1 || ! t_->isOrientable()) { // Fall back to the slow and non-cancellable method. if (t_->hasCompressingDisc()) ss_.markFound(); delete t_; return 0; } // Compute the Euler characteristic of the boundary component. long ec = t_->getBoundaryComponent(0)->getEulerChar(); // Look for a normal disc or sphere to crush. NNormalSurface* ans; NMatrixInt* eqns; NTriangulation* crush; unsigned nComp; bool found; while (true) { t_->intelligentSimplify(); // The LP-and-crushing method only works for // 1-vertex triangulations (at present). if (t_->getNumberOfVertices() > 1) { // Try harder. t_->barycentricSubdivision(); t_->intelligentSimplify(); if (t_->getNumberOfVertices() > 1) { // Fall back to the old (slow and uncancellable) // method. if (t_->hasCompressingDisc()) ss_.markFound(); delete t_; return 0; } } if (ss_.hasFound()) { delete t_; return 0; } NTreeSingleSoln search(t_, NNormalSurfaceList::STANDARD); { NMutex::MutexLock lock(searchMutex_); currSearch_ = &search; } found = search.find(); { NMutex::MutexLock lock(searchMutex_); currSearch_ = 0; } if (ss_.hasFound()) { delete t_; return 0; } if (! found) { // No discs or spheres. // In particular, no compressing disc. delete t_; return 0; } // NTreeSingleSoln guarantees that our solution is // connected, and so it (or its double) is a sphere or // a disc. ans = search.buildSurface(); crush = ans->crush(); delete ans; delete t_; // Find the piece in the crushed triangulation with the // right Euler characteristic on the boundary, if it exists. nComp = crush->splitIntoComponents(); t_ = static_cast( crush->getFirstTreeChild()); while (t_) { if (t_->getNumberOfBoundaryComponents() == 1 && t_->getBoundaryComponent(0)-> getEulerChar() == ec) { // Found it. t_->makeOrphan(); break; } t_ = static_cast( t_->getNextTreeSibling()); } delete crush; if (! t_) { // No boundary component with the right Euler // characteristic. We must have compressed. ss_.markFound(); return 0; } // We now have a triangulation with fewer tetrahedra, // which contains a compressing disc iff the original did. // Around we go again! } } }; inline void SharedSearch::markFound() { NMutex::MutexLock lock(mutex_); found_ = true; if (ct_[0]) ct_[0]->cancel(); if (ct_[1]) ct_[1]->cancel(); } } // anonymous namespace bool NNormalSurface::isIncompressible() const { // We don't bother making the surface two-sided. This is because // cutting along the two-sided surface will produce (i) exactly what // you obtain from cutting along the one-sided surface, plus // (ii) a twisted I-bundle over a surface that will not contain any // compressing discs. // Rule out spheres. // From the preconditions, we can assume this surface to be // closed, compact and connected. if (getEulerChar() == 2 || ((! isTwoSided()) && getEulerChar() == 1)) return false; if (isThinEdgeLink().first) { // Since the manifold is closed and this surface is not a // sphere, the edge it links must be a loop and the surface must // surround a solid torus or Klein bottle. return false; } // Time for the heavy machinery. NTriangulation* cut = cutAlong(); cut->intelligentSimplify(); bool result; NTriangulation* side[2]; side[0] = side[1] = 0; cut->splitIntoComponents(); int which = 0; for (NPacket* comp = cut->getFirstTreeChild(); comp; comp = comp->getNextTreeSibling()) if (static_cast(comp)->hasBoundaryTriangles()) { if (which == 2) { // We have more than two components with boundary. // This should never happen. std::cerr << "ERROR: isIncompressible() sliced to give " "more than two components with boundary." << std::endl; delete cut; return false; } side[which++] = static_cast(comp); } // Detach from parents so we don't run into multithreading problems // (e.g., when both triangulations try to delete themselves at the // same time). side[0]->makeOrphan(); if (side[1]) side[1]->makeOrphan(); delete cut; SharedSearch ss; if (! side[1]) { CompressionTest c(side[0], ss); c.run(0); } else { // Test both sides for compressing discs in parallel, // so we can terminate early if one side finds such a disc. CompressionTest c1(side[0], ss); CompressionTest c2(side[1], ss); c1.start(); c2.start(); c1.join(); c2.join(); } return ! ss.hasFound(); } } // namespace regina regina-4.96/engine/surfaces/csv.cpp000644 000765 000024 00000022470 12377776714 017221 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "maths/nmatrixint.h" #include "surfaces/nnormalsurfacelist.h" #include "triangulation/ntriangulation.h" namespace regina { namespace { /** * Write the given string to the given output stream, properly * quoted and escaped. The entire string will be placed in double * quotes, and any double quotes that appear inside the string will * be replaced by a pair of double quotes. */ void writeCSVQuotedString(std::ostream& out, const char* str) { out << '"'; while (*str) { if (*str == '"') out << "\"\""; else out << *str; ++str; } out << '"'; } /** * Writes a piece of the CSV header corresponding to the given set * of optional fields. */ void writePropHeader(std::ostream& out, int fields) { if (fields & surfaceExportName) out << "name,"; if (fields & surfaceExportEuler) out << "euler,"; if (fields & surfaceExportOrient) out << "orientable,"; if (fields & surfaceExportSides) out << "sides,"; if (fields & surfaceExportBdry) out << "boundary,"; if (fields & surfaceExportLink) out << "link,"; if (fields & surfaceExportType) out << "type,"; } /** * Writes a piece of the CSV data for the given normal surface * corresponding to the given set of optional fields. */ void writePropData(std::ostream& out, const NNormalSurface* s, int fields) { if (fields & surfaceExportName) { if (s->getName().length() > 0) writeCSVQuotedString(out, s->getName().c_str()); out << ','; } if (fields & surfaceExportEuler) { if (s->isCompact()) out << s->getEulerChar(); out << ','; } if (fields & surfaceExportOrient) { if (s->isCompact()) { out << (s->isOrientable() ? "TRUE" : "FALSE"); } out << ','; } if (fields & surfaceExportSides) { if (s->isCompact()) { out << (s->isTwoSided() ? '2' : '1'); } out << ','; } if (fields & surfaceExportBdry) { if (! s->isCompact()) { #ifndef EXCLUDE_SNAPPEA regina::NMatrixInt* slopes = s->boundaryIntersections(); if (slopes) { out << "\"spun:"; for (unsigned i = 0; i < slopes->rows(); ++i) out << " (" << slopes->entry(i, 1) << ", " << - slopes->entry(i, 0) << ')'; out << '\"'; } else out << "spun"; #else out << "spun"; #endif } else if (s->hasRealBoundary()) out << "real"; else out << "none"; out << ','; } if (fields & surfaceExportLink) { // Mirror the information that gets shown in the Link column // in the GUI. const NTriangulation* t = s->getTriangulation(); const NVertex* v = s->isVertexLink(); if (v) out << "\"Vertex " << t->vertexIndex(v) << "\""; else { std::pair e = s->isThinEdgeLink(); if (e.second) out << "\"Thin edges " << t->edgeIndex(e.first) << ", " << t->edgeIndex(e.second) << "\""; else if (e.first) out << "\"Thin edge " << t->edgeIndex(e.first) << "\""; } out << ','; } if (fields & surfaceExportType) { // Mirror the information that gets shown in the Type column // in the GUI. if (s->isSplitting()) out << "\"Splitting\""; else { NLargeInteger tot = s->isCentral(); if (tot != 0) out << "\"Central (" << tot << ")\""; } out << ','; } } } bool NNormalSurfaceList::saveCSVStandard(const char* filename, int additionalFields) { std::ofstream out(filename); if (! out) return false; unsigned long n = getTriangulation()->getNumberOfTetrahedra(); unsigned long i, j; // Write the CSV header. writePropHeader(out, additionalFields); for (i = 0; i < n; ++i) { out << 'T' << i << ":0,"; out << 'T' << i << ":1,"; out << 'T' << i << ":2,"; out << 'T' << i << ":3,"; out << 'Q' << i << ":01/23,"; out << 'Q' << i << ":02/13,"; out << 'Q' << i << ":03/12"; if (! allowsAlmostNormal()) { if (i < n - 1) out << ','; continue; } out << ','; out << 'K' << i << ":01/23,"; out << 'K' << i << ":02/13,"; out << 'K' << i << ":03/12"; if (i < n - 1) out << ','; } out << std::endl; // Write the data for individual surfaces. unsigned long tot = getNumberOfSurfaces(); const NNormalSurface* s; for (i = 0; i < tot; ++i) { s = getSurface(i); writePropData(out, s, additionalFields); for (j = 0; j < n; ++j) { out << s->getTriangleCoord(j, 0) << ','; out << s->getTriangleCoord(j, 1) << ','; out << s->getTriangleCoord(j, 2) << ','; out << s->getTriangleCoord(j, 3) << ','; out << s->getQuadCoord(j, 0) << ','; out << s->getQuadCoord(j, 1) << ','; out << s->getQuadCoord(j, 2); if (! allowsAlmostNormal()) { if (j < n - 1) out << ','; continue; } out << ','; out << s->getOctCoord(j, 0) << ','; out << s->getOctCoord(j, 1) << ','; out << s->getOctCoord(j, 2); if (j < n - 1) out << ','; } out << std::endl; } // All done! return true; } bool NNormalSurfaceList::saveCSVEdgeWeight(const char* filename, int additionalFields) { std::ofstream out(filename); if (! out) return false; unsigned long n = getTriangulation()->getNumberOfEdges(); unsigned long i, j; // Write the CSV header. writePropHeader(out, additionalFields); for (i = 0; i < n; ++i) { out << 'E' << i; if (i < n - 1) out << ','; } out << std::endl; // Write the data for individual surfaces. unsigned long tot = getNumberOfSurfaces(); const NNormalSurface* s; for (i = 0; i < tot; ++i) { s = getSurface(i); writePropData(out, s, additionalFields); for (j = 0; j < n; ++j) { out << s->getEdgeWeight(j); if (j < n - 1) out << ','; } out << std::endl; } // All done! return true; } } // namespace regina regina-4.96/engine/surfaces/cut-quadprism.fig000644 000765 000024 00000005134 12234011536 021155 0ustar00babstaff000000 000000 #FIG 3.2 Produced by xfig version 3.2.5-alpha5 Landscape Center Metric A4 100.00 Single -2 1200 2 6 990 -585 5760 3735 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 2475 -450 135 135 2475 -450 2610 -450 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 5625 450 135 135 5625 450 5760 450 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 5175 3150 135 135 5175 3150 5310 3150 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 1125 3600 135 135 1125 3600 1260 3600 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 1440 2610 2160 540 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 5265 2475 5490 1125 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 3150 450 4500 2250 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 2340 2745 4500 1215 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 3 2160 540 3150 450 5490 1125 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 1440 2610 4500 2250 5265 2475 2340 2745 1440 2610 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 3 2160 540 4500 1215 5490 1125 2 1 0 0 0 7 55 -1 15 2.000 0 0 -1 0 0 4 1440 2610 2340 2745 5265 2475 4500 2250 2 1 0 0 0 7 55 -1 17 2.000 0 0 -1 0 0 4 2160 540 3150 450 5490 1125 4455 1215 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 3 1440 2610 3150 450 5265 2475 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 3 5265 2475 4500 1215 1440 2610 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 3150 450 4500 1215 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 1440 2610 5265 2475 4 1 0 50 -1 0 14 0.0000 0 150 120 5625 540 0\001 4 1 0 50 -1 0 14 0.0000 0 150 120 5175 3240 1\001 4 1 0 50 -1 0 14 0.0000 0 150 120 2475 -360 2\001 4 1 0 50 -1 0 14 0.0000 0 150 120 1125 3690 3\001 4 1 0 50 -1 0 12 0.0000 0 135 105 2070 540 0\001 4 1 0 50 -1 0 12 0.0000 0 135 105 3195 405 1\001 4 1 0 50 -1 0 12 0.0000 0 135 105 5580 1170 2\001 4 1 0 50 -1 0 12 0.0000 0 135 105 5355 2610 0\001 4 1 0 50 -1 0 12 0.0000 0 135 105 2295 2925 1\001 4 1 0 50 -1 0 12 0.0000 0 135 105 1350 2700 2\001 4 1 0 50 -1 0 12 0.0000 0 135 105 4500 1170 3\001 4 1 0 50 -1 0 12 0.0000 0 135 105 4545 2205 3\001 -6 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 3 7065 2610 8775 450 10890 2475 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 3 10890 2475 10125 1215 7065 2610 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 8775 450 10125 1215 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 7065 2610 10890 2475 4 1 0 50 -1 0 12 0.0000 0 135 105 8820 405 1\001 4 1 0 50 -1 0 12 0.0000 0 135 105 10980 2610 0\001 4 1 0 50 -1 0 12 0.0000 0 135 105 6975 2700 2\001 4 1 0 50 -1 0 12 0.0000 0 135 105 10125 1170 3\001 4 1 0 50 -1 0 12 0.0000 0 135 225 8910 1530 T4\001 4 1 0 50 -1 0 12 0.0000 0 135 225 4140 2205 T1\001 4 1 0 50 -1 0 12 0.0000 0 135 225 2385 990 T2\001 4 1 0 50 -1 0 12 0.0000 0 135 225 5040 1485 T0\001 4 1 0 50 -1 0 12 0.0000 0 135 225 2790 2925 T3\001 regina-4.96/engine/surfaces/cut-triprism.fig000644 000765 000024 00000003365 12234011536 021025 0ustar00babstaff000000 000000 #FIG 3.2 Produced by xfig version 3.2.5-alpha5 Landscape Center Metric A4 100.00 Single -2 1200 2 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 8100 -450 135 135 8100 -450 8235 -450 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 11250 450 135 135 11250 450 11385 450 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 10800 3150 135 135 10800 3150 10935 3150 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 6750 3600 135 135 6750 3600 6885 3600 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 7785 540 8820 495 8910 -225 7785 540 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 3 7065 2610 10125 2250 10485 225 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 8910 -225 10485 225 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 7065 2610 7785 540 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 8820 495 10125 2250 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 7065 2610 10485 225 2 1 0 0 0 7 55 -1 15 1.500 0 0 -1 0 0 3 7785 540 8910 -225 8820 495 2 1 0 0 0 7 55 -1 17 1.500 0 0 -1 0 0 3 10485 225 7065 2610 10125 2250 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 7785 540 10125 2250 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 8820 495 10485 225 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 10485 225 7785 540 4 1 0 50 -1 0 14 0.0000 0 150 120 8100 -360 0\001 4 1 0 50 -1 0 14 0.0000 0 150 120 11250 540 1\001 4 1 0 50 -1 0 14 0.0000 0 150 120 10800 3240 2\001 4 1 0 50 -1 0 14 0.0000 0 150 120 6750 3690 3\001 4 1 0 50 -1 0 12 0.0000 0 135 105 10575 270 0\001 4 1 0 50 -1 0 12 0.0000 0 135 105 8955 -270 1\001 4 1 0 50 -1 0 12 0.0000 0 135 105 7695 585 2\001 4 1 0 50 -1 0 12 0.0000 0 135 105 8775 675 3\001 4 1 0 50 -1 0 12 0.0000 0 135 105 10215 2340 1\001 4 1 0 50 -1 0 12 0.0000 0 135 105 6975 2700 3\001 4 1 0 50 -1 0 12 0.0000 0 135 225 8100 1530 T2\001 4 1 0 50 -1 0 12 0.0000 0 135 225 9135 180 T0\001 4 1 0 50 -1 0 12 0.0000 0 135 225 9315 810 T1\001 regina-4.96/engine/surfaces/cut-trunchalftet.fig000644 000765 000024 00000011661 12234011536 021655 0ustar00babstaff000000 000000 #FIG 3.2 Produced by xfig version 3.2.5-alpha5 Landscape Center Metric A4 100.00 Single -2 1200 2 6 315 2115 5085 6435 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 1800 2250 135 135 1800 2250 1935 2250 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 4950 3150 135 135 4950 3150 5085 3150 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 4500 5850 135 135 4500 5850 4635 5850 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 450 6300 135 135 450 6300 585 6300 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 3 1485 3240 2475 3150 4815 3825 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 4 3510 5985 3825 4950 4590 5175 3510 5985 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 765 5310 1440 6210 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 3 1440 6210 1665 5445 765 5310 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 3 1485 3240 3825 3915 4815 3825 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 765 5310 1485 3240 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 1440 6210 3510 5985 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 4590 5175 4815 3825 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 2475 3150 3825 4950 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 1665 5445 3825 3915 2 1 0 0 0 7 55 -1 15 2.000 0 0 -1 0 0 3 3825 4950 3510 5985 4590 5175 2 1 0 0 0 7 55 -1 17 2.000 0 0 -1 0 0 3 765 5310 1440 6210 1665 5445 2 1 0 0 0 7 55 -1 17 2.000 0 0 -1 0 0 4 1485 3240 2475 3150 4815 3825 3825 3915 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 765 5310 3510 5985 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 1665 5445 3510 5985 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 3825 4950 4815 3825 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 4815 3825 3510 5985 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 2475 3150 3510 5985 4 1 0 50 -1 0 14 0.0000 0 150 120 450 6390 3\001 4 1 0 50 -1 0 14 0.0000 0 150 120 4500 5940 2\001 4 1 0 50 -1 0 14 0.0000 0 150 120 1800 2340 1\001 4 1 0 50 -1 0 14 0.0000 0 150 120 4950 3240 0\001 4 1 0 50 -1 0 12 0.0000 0 135 105 1350 6345 2\001 4 1 0 50 -1 0 12 0.0000 0 135 105 720 5355 1\001 4 1 0 50 -1 0 12 0.0000 0 135 105 1395 3285 0\001 4 1 0 50 -1 0 12 0.0000 0 135 105 2520 3105 2\001 4 1 0 50 -1 0 12 0.0000 0 135 105 4905 3870 1\001 4 1 0 50 -1 0 12 0.0000 0 135 105 4680 5265 2\001 4 1 0 50 -1 0 12 0.0000 0 135 105 3870 4095 2\001 4 1 0 50 -1 0 12 0.0000 0 135 105 3555 6165 0\001 4 1 0 50 -1 0 12 0.0000 0 135 105 1620 5400 3\001 4 1 0 50 -1 0 12 0.0000 0 135 225 1935 5940 T7\001 4 1 0 50 -1 0 12 0.0000 0 135 105 3825 4860 3\001 4 1 0 50 -1 0 12 0.0000 0 135 225 4410 4995 T6\001 4 1 0 50 -1 0 12 0.0000 0 135 225 3870 4455 T5\001 -6 6 6255 2970 10620 6165 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 3 7110 3240 8100 3150 10440 3825 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 3 7110 3240 9450 3915 10440 3825 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 6390 5310 7110 3240 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 7290 5445 9450 3915 2 1 0 0 0 7 55 -1 17 2.000 0 0 -1 0 0 4 7110 3240 8100 3150 10440 3825 9450 3915 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 6390 5310 9135 5985 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 8100 3150 9135 5985 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 6390 5310 7290 5445 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 7290 5445 9135 5985 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 10440 3825 9135 5985 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 8100 3150 6390 5310 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 7290 5445 8100 3150 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 7290 5445 10440 3825 4 1 0 50 -1 0 12 0.0000 0 135 105 6345 5355 1\001 4 1 0 50 -1 0 12 0.0000 0 135 105 7020 3285 0\001 4 1 0 50 -1 0 12 0.0000 0 135 105 8145 3105 2\001 4 1 0 50 -1 0 12 0.0000 0 135 105 10530 3870 1\001 4 1 0 50 -1 0 12 0.0000 0 135 105 9495 4095 2\001 4 1 0 50 -1 0 12 0.0000 0 135 105 9180 6165 0\001 4 1 0 50 -1 0 12 0.0000 0 135 105 7245 5400 3\001 4 1 0 50 -1 0 12 0.0000 0 135 225 7920 4680 T4\001 4 1 0 50 -1 0 12 0.0000 0 135 225 9225 4905 T3\001 -6 6 11655 2970 16020 5445 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 3 12510 3240 13500 3150 15840 3825 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 3 12510 3240 14850 3915 15840 3825 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 11790 5310 12510 3240 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 12690 5445 14850 3915 2 1 0 0 0 7 55 -1 17 2.000 0 0 -1 0 0 4 12510 3240 13500 3150 15840 3825 14850 3915 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 11790 5310 12690 5445 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 13500 3150 11790 5310 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 12690 5445 15840 3825 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 15840 3825 12510 3240 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 12690 5445 12510 3240 2 1 3 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 12690 5445 13500 3150 4 1 0 50 -1 0 12 0.0000 0 135 105 11745 5355 1\001 4 1 0 50 -1 0 12 0.0000 0 135 105 12420 3285 0\001 4 1 0 50 -1 0 12 0.0000 0 135 105 13545 3105 2\001 4 1 0 50 -1 0 12 0.0000 0 135 105 15930 3870 1\001 4 1 0 50 -1 0 12 0.0000 0 135 105 14895 4095 2\001 4 1 0 50 -1 0 12 0.0000 0 135 105 12645 5400 3\001 4 1 0 50 -1 0 12 0.0000 0 135 225 12375 4320 T2\001 4 1 0 50 -1 0 12 0.0000 0 135 225 14400 4050 T0\001 4 1 0 50 -1 0 12 0.0000 0 135 225 13275 3105 T1\001 -6 regina-4.96/engine/surfaces/cut-trunctet.fig000644 000765 000024 00000016700 12234011536 021021 0ustar00babstaff000000 000000 #FIG 3.2 Produced by xfig version 3.2.5-alpha5 Landscape Center Metric A4 100.00 Single -2 1200 2 6 810 5670 5220 9495 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 990 8685 2700 6525 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 990 8685 3735 9360 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 2700 6525 4050 8325 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 4050 8325 5040 7200 2 1 0 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 5040 7200 2835 5850 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 3 990 8685 2835 5850 2700 6525 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 3 4050 8325 3735 9360 5040 7200 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 3735 9360 2700 6525 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 4050 8325 2835 5850 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 3735 9360 2835 5850 4 1 0 55 -1 0 12 0.0000 0 135 105 900 8730 3\001 4 1 0 55 -1 0 12 0.0000 0 135 105 3825 9495 2\001 4 1 0 55 -1 0 12 0.0000 0 135 105 5130 7245 1\001 4 1 0 55 -1 0 12 0.0000 0 135 105 2790 5805 0\001 4 1 0 55 -1 0 12 0.0000 0 135 105 2790 6570 1\001 4 1 0 55 -1 0 12 0.0000 0 135 105 3960 8415 3\001 4 1 0 50 -1 0 12 0.0000 0 135 225 2430 8055 T4\001 4 1 0 50 -1 0 12 0.0000 0 135 225 4185 7380 T6\001 4 1 0 50 -1 0 12 0.0000 0 135 225 3645 8235 T5\001 -6 6 5760 5670 10170 9495 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 5940 8685 8685 9360 2 1 0 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 9990 7200 7785 5850 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 5940 8685 9990 7200 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 8685 9360 9990 7200 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 7785 5850 5940 8685 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 7785 5850 8685 9360 4 1 0 55 -1 0 12 0.0000 0 135 105 5850 8730 3\001 4 1 0 55 -1 0 12 0.0000 0 135 105 8775 9495 2\001 4 1 0 55 -1 0 12 0.0000 0 135 105 10080 7245 1\001 4 1 0 55 -1 0 12 0.0000 0 135 105 7740 5805 0\001 4 1 0 50 -1 0 12 0.0000 0 135 330 7785 7695 T10\001 -6 6 10710 5670 15120 9495 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 11790 8820 13635 9360 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 10890 8685 13635 9360 2 1 2 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 11790 8820 13950 7290 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 13950 7290 12735 5850 2 1 0 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 14940 7200 12735 5850 2 1 2 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 11790 8820 10890 8685 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 13950 7290 14940 7200 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 10890 8685 13950 7290 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 11790 8820 14940 7200 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 10890 8685 14940 7200 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 13635 9360 14940 7200 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 12735 5850 10890 8685 4 1 0 55 -1 0 12 0.0000 0 135 105 10800 8730 3\001 4 1 0 55 -1 0 12 0.0000 0 135 105 13725 9495 2\001 4 1 0 55 -1 0 12 0.0000 0 135 105 15030 7245 1\001 4 1 0 55 -1 0 12 0.0000 0 135 105 12690 5805 0\001 4 1 0 55 -1 0 12 0.0000 0 135 105 13995 7470 2\001 4 1 0 55 -1 0 12 0.0000 0 135 105 11745 8775 0\001 4 1 0 50 -1 0 12 0.0000 0 135 225 12915 7200 T7\001 4 1 0 50 -1 0 12 0.0000 0 135 225 12150 8460 T8\001 4 1 0 50 -1 0 12 0.0000 0 135 225 13455 8640 T9\001 -6 6 2790 540 7560 4860 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 4275 675 135 135 4275 675 4410 675 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 7425 1575 135 135 7425 1575 7560 1575 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 6975 4275 135 135 6975 4275 7110 4275 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 2925 4725 135 135 2925 4725 3060 4725 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 3240 3735 4950 1575 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 5085 900 3240 3735 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 4140 3870 5985 4410 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 3240 3735 5985 4410 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 3960 1665 4950 1575 5085 900 3960 1665 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 5085 900 6660 1350 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 3240 3735 3960 1665 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 3915 4635 5985 4410 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 7065 3600 7290 2250 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 4950 1575 6300 3375 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 4140 3870 6300 2340 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 6300 3375 5985 4410 7065 3600 6300 3375 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 3 6660 1350 6300 2340 7290 2250 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 3 3240 3735 4140 3870 3915 4635 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 3240 3735 3915 4635 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 6660 1350 7290 2250 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 6300 3375 7290 2250 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 5985 4410 7290 2250 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 6300 2340 5085 900 2 1 0 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 7290 2250 5085 900 2 1 0 0 0 7 55 -1 15 1.500 0 0 -1 0 0 3 3960 1665 5085 900 4950 1575 2 1 0 0 0 7 55 -1 15 1.500 0 0 -1 0 0 3 5985 4410 6300 3375 7065 3600 2 1 0 0 0 7 55 -1 17 1.500 0 0 -1 0 0 3 3240 3735 3915 4635 4140 3870 2 1 0 0 0 7 55 -1 17 1.500 0 0 -1 0 0 3 6660 1350 6300 2340 7290 2250 4 1 0 55 -1 0 14 0.0000 0 150 120 4275 765 0\001 4 1 0 55 -1 0 14 0.0000 0 150 120 7425 1665 1\001 4 1 0 55 -1 0 14 0.0000 0 150 120 6975 4365 2\001 4 1 0 55 -1 0 14 0.0000 0 150 120 2925 4815 3\001 4 1 0 55 -1 0 12 0.0000 0 135 105 3870 1665 2\001 4 1 0 55 -1 0 12 0.0000 0 135 105 3150 3780 3\001 4 1 0 55 -1 0 12 0.0000 0 135 105 3825 4770 1\001 4 1 0 55 -1 0 12 0.0000 0 135 105 6075 4545 2\001 4 1 0 55 -1 0 12 0.0000 0 135 105 7155 3735 0\001 4 1 0 55 -1 0 12 0.0000 0 135 105 7380 2295 1\001 4 1 0 55 -1 0 12 0.0000 0 135 105 6750 1350 3\001 4 1 0 55 -1 0 12 0.0000 0 135 105 5040 855 0\001 4 1 0 55 -1 0 12 0.0000 0 135 105 5040 1620 1\001 4 1 0 55 -1 0 12 0.0000 0 135 105 6345 2520 2\001 4 1 0 55 -1 0 12 0.0000 0 135 105 6210 3465 3\001 4 1 0 55 -1 0 12 0.0000 0 135 105 4095 3825 0\001 4 1 0 50 -1 0 12 0.0000 0 135 225 4095 2025 T0\001 4 1 0 50 -1 0 12 0.0000 0 135 225 6345 1530 T1\001 4 1 0 50 -1 0 12 0.0000 0 135 225 6885 3420 T2\001 4 1 0 50 -1 0 12 0.0000 0 135 225 4365 4365 T3\001 -6 6 8910 720 13320 4545 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 9090 3735 10800 1575 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 9990 3870 11835 4410 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 9090 3735 11835 4410 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 10800 1575 12150 3375 2 1 2 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 9990 3870 12150 2340 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 12150 3375 13140 2250 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 12150 2340 10935 900 2 1 0 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 13140 2250 10935 900 2 1 2 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 9990 3870 9090 3735 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 3 9090 3735 10935 900 10800 1575 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 3 12150 3375 11835 4410 13140 2250 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 12150 2340 13140 2250 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 11835 4410 10800 1575 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 12150 3375 10935 900 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 9090 3735 12150 2340 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 9990 3870 13140 2250 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 11835 4410 10935 900 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 9090 3735 13140 2250 4 1 0 55 -1 0 12 0.0000 0 135 105 9000 3780 3\001 4 1 0 55 -1 0 12 0.0000 0 135 105 11925 4545 2\001 4 1 0 55 -1 0 12 0.0000 0 135 105 13230 2295 1\001 4 1 0 55 -1 0 12 0.0000 0 135 105 10890 855 0\001 4 1 0 55 -1 0 12 0.0000 0 135 105 10890 1620 1\001 4 1 0 55 -1 0 12 0.0000 0 135 105 12195 2520 2\001 4 1 0 55 -1 0 12 0.0000 0 135 105 12060 3465 3\001 4 1 0 55 -1 0 12 0.0000 0 135 105 9945 3825 0\001 -6 regina-4.96/engine/surfaces/enumerator.cpp000644 000765 000024 00000060355 12377776715 020614 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "regina-config.h" // For EXCLUDE_NORMALIZ. #include #include "enumerate/ndoubledescription.h" #include "enumerate/nhilbertcd.h" #include "enumerate/nhilbertdual.h" #ifndef EXCLUDE_NORMALIZ #include "enumerate/nhilbertprimal.h" #endif #include "enumerate/ntreetraversal.h" #include "maths/matrixops.h" #include "maths/nmatrixint.h" #include "progress/nprogresstracker.h" #include "surfaces/coordregistry.h" #include "surfaces/nnormalsurfacelist.h" #include "triangulation/ntriangulation.h" namespace regina { #ifdef INT128_AVAILABLE /** * The largest possible signed 128-bit integer, */ NInteger maxSigned128(NNativeInteger<16>(~(IntOfSize<16>::type(1) << 127))); #endif NNormalSurfaceList* NNormalSurfaceList::enumerate( NTriangulation* owner, NormalCoords coords, NormalList which, NormalAlg algHints, NProgressTracker* tracker) { NNormalSurfaceList* list = new NNormalSurfaceList( coords, which, algHints); Enumerator* e = new Enumerator(list, owner, tracker); if (tracker) { if (! e->start(0, true)) { delete list; list = 0; } } else { e->run(0); delete e; } return list; } void* NNormalSurfaceList::Enumerator::run(void*) { forCoords(list_->coords_, *this); return 0; } template void NNormalSurfaceList::Enumerator::operator() (Coords) { // Clean up the "type of list" flag. list_->which_ &= ( NS_EMBEDDED_ONLY | NS_IMMERSED_SINGULAR | NS_VERTEX | NS_FUNDAMENTAL); list_->which_.ensureOne(NS_VERTEX, NS_FUNDAMENTAL); list_->which_.ensureOne(NS_EMBEDDED_ONLY, NS_IMMERSED_SINGULAR); // Farm out the real work to list-type-specific routines. if (list_->which_.has(NS_VERTEX)) fillVertex(); else fillFundamental(); // Insert the results into the packet tree, but only once they are ready. if (! (tracker_ && tracker_->isCancelled())) triang_->insertChildLast(list_); if (tracker_) tracker_->setFinished(); } template void NNormalSurfaceList::Enumerator::fillVertex() { // ----- Decide which algorithm to use ----- // Here we will set the algorithm_ flag to precisely what we plan to do. // First clear out all irrelevant options. list_->algorithm_ &= ( NS_VERTEX_VIA_REDUCED | NS_VERTEX_STD_DIRECT | NS_VERTEX_TREE | NS_VERTEX_DD); // For standard normal / almost normal coordinates, choose between // standard-direct vs standard-via-reduced. if (list_->coords_ == NS_STANDARD || list_->coords_ == NS_AN_STANDARD) { list_->algorithm_.ensureOne( NS_VERTEX_VIA_REDUCED, NS_VERTEX_STD_DIRECT); // If we've chosen via-reduced, check that this is actually available. // If not, switch back to standard-direct. if (list_->algorithm_.has(NS_VERTEX_VIA_REDUCED) && ! (list_->which_.has(NS_EMBEDDED_ONLY) && triang_->isValid() && (! triang_->isIdeal()))) list_->algorithm_ ^= (NS_VERTEX_VIA_REDUCED | NS_VERTEX_STD_DIRECT); } else { // Standard-direct vs standard-via-reduced is not relevant here. list_->algorithm_.clear(NS_VERTEX_VIA_REDUCED | NS_VERTEX_STD_DIRECT); } // Choose between double description and tree traversal. // Which is the default will depend upon the underlying coordinate system. if (list_->algorithm_.has(NS_VERTEX_STD_DIRECT)) { // Tree traversal is at its best when every coordinate is involved // in branching decisions (i.e., we are in quad or quad-oct // coordinates). It can be slower when working with triangles, // so default to the older double description method. list_->algorithm_.ensureOne(NS_VERTEX_DD, NS_VERTEX_TREE); } else { // Use the new technology. list_->algorithm_.ensureOne(NS_VERTEX_TREE, NS_VERTEX_DD); } // Check whether tree traversal supports our enumeration arguments. // If not, switch back to double description. // The integer template argument for NTreeTraversal::supported() // is unimportant here; we just use NInteger. if (list_->algorithm_.has(NS_VERTEX_TREE) && ! (list_->which_.has(NS_EMBEDDED_ONLY) && NTreeTraversal::supported( list_->coords_))) list_->algorithm_ ^= (NS_VERTEX_TREE | NS_VERTEX_DD); // ----- Run the enumeration algorithm ----- if (triang_->getNumberOfTetrahedra() == 0) { // Handle the empty triangulation separately. list_->algorithm_ = NS_VERTEX_DD; /* shrug */ // Nothing to do. } else if (! list_->algorithm_.has(NS_VERTEX_VIA_REDUCED)) { // A direct enumeration in the chosen coordinate system. if (list_->algorithm_.has(NS_VERTEX_TREE)) { if (tracker_) tracker_->newStage( "Enumerating vertex surfaces\n(tree traversal method)"); fillVertexTree(); } else { if (tracker_) tracker_->newStage( "Enumerating vertex surfaces\n(double description method)"); fillVertexDD(); } } else { // Enumerate in the reduced coordinate system, and then convert // the solution set to the standard coordinate system. // Since there are currently only two systems in which we can do // this (NS_STANDARD and NS_AN_STANDARD), we hard-code these // cases in if() statements to avoid generating template code // for other, unsupported coordinate systems. // Enumerate in reduced (quad / quad-oct) form. Enumerator e(new NNormalSurfaceList( (list_->coords_ == NS_STANDARD ? NS_QUAD : NS_AN_QUAD_OCT), list_->which_, list_->algorithm_ ^ NS_VERTEX_VIA_REDUCED), triang_, tracker_); if (list_->algorithm_.has(NS_VERTEX_TREE)) { if (tracker_) tracker_->newStage("Enumerating reduced solution set\n" "(tree traversal method)", 0.9); e.fillVertexTree(); } else { if (tracker_) tracker_->newStage("Enumerating reduced solution set\n" "(double description method)", 0.9); e.fillVertexDD(); } if (tracker_ && tracker_->isCancelled()) { delete e.list_; return; } // Expand to the standard the solution set. if (tracker_) tracker_->newStage("Expanding to standard solution set", 0.1); if (list_->coords_ == NS_STANDARD) list_->buildStandardFromReduced(triang_, e.list_->surfaces, tracker_); else list_->buildStandardFromReduced(triang_, e.list_->surfaces, tracker_); // Clean up. delete e.list_; } } template void NNormalSurfaceList::Enumerator::fillVertexDD() { NMatrixInt* eqns = makeMatchingEquations(triang_, list_->coords_); NEnumConstraintList* constraints = (list_->which_.has(NS_EMBEDDED_ONLY) ? makeEmbeddedConstraints(triang_, list_->coords_) : 0); NDoubleDescription::enumerateExtremalRays( SurfaceInserter(*list_, triang_), *eqns, constraints, tracker_); delete constraints; delete eqns; } template void NNormalSurfaceList::Enumerator::fillVertexTree() { // We can always do this with the arbitrary-precision NInteger, // but it will be much faster if we can get away with native // integers instead. To do this, though, we need to be able to // guarantee that all intermediate integers that could appear in the // algorithm are sufficiently small in magnitude. // // Here we compute an upper bound on the magnitude of the integers that // could appear in a vanilla NTreeEnumeration // algorithm. For details on how these arguments work, see // section 4 of the tree traversal algorithm paper (Burton & Ozlen, // Algorithmica, 2013). // // All "maximum" quantities in the calculations below refer to // maximum absolute value, and are always non-negative. // Here we use the fact that the coordinate system is known to be // supported by the tree traversal algorithm, and therefore is one // of NS_STANDARD, NS_QUAD, NS_AN_STANDARD or NS_AN_QUAD. // The matching equation matrix that will be used by the tree traversal // tableaux, which is always based on NS_STANDARD or NSQUAD (even // for almost normal surfaces): NMatrixInt* eqns; // The maximum number of columns in the tableaux that could be added // to form the right hand side, as a consequence of either // LPData::constrainPositive() or LPData::constrainOct(): unsigned long maxColsRHS; switch (list_->coords_) { case NS_STANDARD: eqns = makeMatchingEquations(triang_, NS_STANDARD); maxColsRHS = triang_->getNumberOfTetrahedra() * 5; break; case NS_QUAD: eqns = makeMatchingEquations(triang_, NS_QUAD); maxColsRHS = triang_->getNumberOfTetrahedra(); break; case NS_AN_STANDARD: eqns = makeMatchingEquations(triang_, NS_STANDARD); maxColsRHS = triang_->getNumberOfTetrahedra() * 5 + 1; break; case NS_AN_QUAD_OCT: eqns = makeMatchingEquations(triang_, NS_QUAD); maxColsRHS = triang_->getNumberOfTetrahedra() + 1; break; default: // We shouldn't be here.. just use arbitrary precision arithmetic. fillVertexTreeWith(); return; } size_t i, j; NInteger tmp; // The rank of the matching equation matrix: unsigned long rank = rowBasis(*eqns); // The maximum entry in the matching equation matrix: NInteger maxEqnEntry = 0; for (i = 0; i < rank; ++i) for (j = 0; j < eqns->columns(); ++j) { tmp = eqns->entry(i, j).abs(); if (tmp > maxEqnEntry) maxEqnEntry = tmp; } // The maximum integer that can appear on the RHS of the original // tableaux, after all calls to constrainPositive() and/or constrainOct(): NInteger maxOrigRHS = maxEqnEntry * maxColsRHS; // The maximum sum of absolute values of entries in a single column // of the original tableaux (noting that for almost normal surfaces, // the octagon column will be the sum of two original columns): NInteger maxOrigColSum = 0; for (i = 0; i < eqns->columns(); ++i) { tmp = 0; for (j = 0; j < rank; ++j) tmp += NInteger(eqns->entry(j, i).abs()); if (tmp > maxOrigColSum) maxOrigColSum = tmp; } if (Coords::almostNormal) maxOrigColSum *= 2; // The square of the Hadamard bound for the original tableaux: NInteger hadamardSquare = 1; NInteger* colNorm = new NInteger[eqns->columns()]; for (i = 0; i < eqns->columns(); ++i) { colNorm[i] = 0; for (j = 0; j < rank; ++j) colNorm[i] += NInteger(eqns->entry(j, i) * eqns->entry(j, i)); } std::sort(colNorm, colNorm + eqns->columns()); for (i = 0; i < rank; ++i) hadamardSquare *= colNorm[eqns->columns() - 1 - i]; delete[] colNorm; delete eqns; // We are done with the matching equations now. if (Coords::almostNormal) { // The octagon column is the sum of two quadrilateral columns. // This is no worse than doubling the Euclidean norm of the // largest column. hadamardSquare *= 4; } // The maximum entry in the tableaux, at any stage of the algorithm, // is hadamard * maxOrigColSum. Call this X. // The maximum entry on the RHS, at any stage of the algorithm, // is hadamard * rank * maxOrigRHS. Call this Y. // Assume nTetrahedra >= 2, since with 1 tetrahedron, all enumerations // easily fit into small native integers. // Then: // maxOrigColSum <= rank * maxEqnEntry * 2 // <= rank * maxEqnEntry * nTetrahedra // <= rank * maxEqnEntry * maxColsRHS // = rank * maxOrigRHS. // So X <= Y. // The worst computations we have to perform are // (X * X + X * X) in the tableaux, and (X * Y + X * Y) on the RHS. // Therefore the largest integer we have to deal with is: // 2XY = 2 * hadamardSquare * maxOrigColSum * rank * maxOrigRHS. NInteger worst = hadamardSquare; worst *= 2; worst *= maxOrigColSum; worst *= rank; worst *= maxOrigRHS; // Bridge builders add safety margins, and we can add one too. worst *= 4; // TODO: Rework this calculation so that maxOrigRHS is computed from // row sums in the matching equation matrix (don't forget to double // the highest term for almost normal surfaces). This may mean that // we need to take max(X, Y), since it will no longer be clear that // X <= Y. // Now we can select an appropriate integer type. if (worst <= LONG_MAX) { // std::cerr << "Using NNativeLong." << std::endl; fillVertexTreeWith(); #ifdef INT128_AVAILABLE } else if (worst <= maxSigned128) { // std::cerr << "Using NNativeInteger<16>." << std::endl; fillVertexTreeWith >(); #endif } else { // std::cerr << "Using the fallback NInteger." << std::endl; fillVertexTreeWith(); } } template void NNormalSurfaceList::Enumerator::fillVertexTreeWith() { NTreeEnumeration search( triang_, list_->coords_); while (search.next(tracker_)) { list_->surfaces.push_back(search.buildSurface()); if (tracker_ && tracker_->isCancelled()) break; } } template void NNormalSurfaceList::Enumerator::fillFundamental() { // Get the empty triangulation out of the way separately. if (triang_->getNumberOfTetrahedra() == 0) { list_->algorithm_ = NS_HILBERT_DUAL; /* shrug */ return; } // ----- Decide upon and run an appropriate algorithm ----- // This is where we make the "default" decision for the user. if (list_->which_.has(NS_IMMERSED_SINGULAR)) { // The primal method makes no sense without the quadrilateral // constraints. list_->algorithm_.ensureOne(NS_HILBERT_DUAL, NS_HILBERT_FULLCONE, NS_HILBERT_PRIMAL, NS_HILBERT_CD); } else { list_->algorithm_.ensureOne(NS_HILBERT_PRIMAL, NS_HILBERT_DUAL, NS_HILBERT_FULLCONE, NS_HILBERT_CD); } // Run the chosen algorithm. if (list_->algorithm_.has(NS_HILBERT_PRIMAL)) fillFundamentalPrimal(); else if (list_->algorithm_.has(NS_HILBERT_DUAL)) fillFundamentalDual(); else if (list_->algorithm_.has(NS_HILBERT_CD)) fillFundamentalCD(); else fillFundamentalFullCone(); } template void NNormalSurfaceList::Enumerator::fillFundamentalDual() { list_->algorithm_ = NS_HILBERT_DUAL; if (tracker_) tracker_->newStage("Enumerating Hilbert basis\n(dual method)"); NMatrixInt* eqns = makeMatchingEquations(triang_, list_->coords_); NEnumConstraintList* constraints = (list_->which_.has(NS_EMBEDDED_ONLY) ? makeEmbeddedConstraints(triang_, list_->coords_) : 0); NHilbertDual::enumerateHilbertBasis( SurfaceInserter(*list_, triang_), *eqns, constraints, tracker_); delete constraints; delete eqns; } template void NNormalSurfaceList::Enumerator::fillFundamentalCD() { list_->algorithm_ = NS_HILBERT_CD; if (tracker_) tracker_->newStage( "Enumerating Hilbert basis\n(Contejean-Devie method)"); NMatrixInt* eqns = makeMatchingEquations(triang_, list_->coords_); NEnumConstraintList* constraints = (list_->which_.has(NS_EMBEDDED_ONLY) ? makeEmbeddedConstraints(triang_, list_->coords_) : 0); NHilbertCD::enumerateHilbertBasis( SurfaceInserter(*list_, triang_), *eqns, constraints); delete constraints; delete eqns; } #ifdef EXCLUDE_NORMALIZ template void NNormalSurfaceList::Enumerator::fillFundamentalPrimal() { // This build of Regina does not include normaliz. // Fall back to some other option. fillFundamentalDual(); } template void NNormalSurfaceList::Enumerator::fillFundamentalFullCone() { // This build of Regina does not include normaliz. // Fall back to some other option. fillFundamentalDual(); } #else template void NNormalSurfaceList::Enumerator::fillFundamentalPrimal() { // We will not set algorithm_ until after the extremal ray // enumeration has finished (since we might want pass additional flags // to and/or from that routine). if (tracker_) tracker_->newStage("Initialising Hilbert basis enumeration", 0.1); // Fetch validity constraints from the registry. NEnumConstraintList* constraints = (list_->which_.has(NS_EMBEDDED_ONLY) ? makeEmbeddedConstraints(triang_, list_->coords_) : 0); // Enumerate all vertex normal surfaces. if (tracker_) tracker_->newStage("Enumerating extremal rays", 0.4); NNormalSurfaceList* vtx = new NNormalSurfaceList(list_->coords_, NS_VERTEX | (list_->which_.has(NS_EMBEDDED_ONLY) ? NS_EMBEDDED_ONLY : NS_IMMERSED_SINGULAR), list_->algorithm_ /* passes through any vertex enumeration flags */); Enumerator e(vtx, triang_, 0 /* Don't set another progress tracker */); e.fillVertex(); // Finalise the algorithm flags for this list: combine NS_HILBERT_PRIMAL // with whatever vertex enumeration flags were used. list_->algorithm_ = e.list_->algorithm_ | NS_HILBERT_PRIMAL; // Expand this list to a full Hilbert basis. if (tracker_) tracker_->newStage("Expanding to Hilbert basis", 0.5); NHilbertPrimal::enumerateHilbertBasis( SurfaceInserter(*list_, triang_), vtx->beginVectors(), vtx->endVectors(), constraints, tracker_); delete vtx; delete constraints; } template void NNormalSurfaceList::Enumerator::fillFundamentalFullCone() { list_->algorithm_ = NS_HILBERT_FULLCONE; if (tracker_) tracker_->newStage( "Enumerating Hilbert basis of full cone", 0.8); NMatrixInt* eqns = makeMatchingEquations(triang_, list_->coords_); unsigned rank = rowBasis(*eqns); unsigned long dim = eqns->columns(); std::vector > input; unsigned r, c; input.reserve(rank); for (r = 0; r < rank; ++r) { input.push_back(std::vector()); std::vector& v(input.back()); v.reserve(eqns->columns()); for (c = 0; c < eqns->columns(); ++c) { NLargeInteger& entry(eqns->entry(r, c)); if (entry.isNative()) v.push_back(mpz_class(entry.longValue())); else v.push_back(mpz_class(entry.rawData())); } } delete eqns; libnormaliz::Cone cone(input, libnormaliz::Type::equations); libnormaliz::ConeProperties wanted( libnormaliz::ConeProperty::HilbertBasis); cone.compute(wanted); if (! cone.isComputed(libnormaliz::ConeProperty::HilbertBasis)) { // Something has gone wrong inside Normaliz. // Return an empty list. } else { if (tracker_) tracker_->newStage("Extracting relevant solutions", 0.2); // Fetch validity constraints from the registry. NEnumConstraintList* constraints = (list_->which_.has(NS_EMBEDDED_ONLY) ? makeEmbeddedConstraints(triang_, list_->coords_) : 0); bool broken; int nonZero; int i; std::vector >::const_iterator hlit; NEnumConstraintList::const_iterator eit; std::set::const_iterator sit; NNormalSurfaceVector* v; NLargeInteger tmpInt; NewFunction1 newVec(dim); const std::vector > basis = cone.getHilbertBasis(); for (hlit = basis.begin(); hlit != basis.end(); ++hlit) { broken = false; if (constraints) { for (eit = constraints->begin(); eit != constraints->end(); ++eit) { nonZero = 0; for (sit = eit->begin(); sit != eit->end(); ++sit) { if ((*hlit)[*sit] != 0) { if (++nonZero > 1) break; } } if (nonZero > 1) { broken = true; break; } } } if (! broken) { // Insert a new surface. v = forCoords(list_->coords_, newVec, 0); if (! v) { // Coordinate system not recognised. // Return an empty list to indicate that something broke. list_->surfaces.clear(); break; } for (i = 0; i < dim; ++i) { // Inefficiency: We make two copies of the GMP integer // here instead of one, since NVector/NRay does not give // us direct non-const access to its elements. tmpInt.setRaw((*hlit)[i].get_mpz_t()); tmpInt.tryReduce(); v->setElement(i, tmpInt); } list_->surfaces.push_back(new NNormalSurface(triang_, v)); } } delete constraints; } } #endif // EXCLUDE_NORMALIZ } // namespace regina regina-4.96/engine/surfaces/enumfilter.cpp000644 000765 000024 00000013331 12377776716 020576 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "surfaces/nnormalsurfacelist.h" #include "triangulation/ntriangulation.h" namespace regina { NNormalSurfaceList* NNormalSurfaceList::filterForLocallyCompatiblePairs() const { // Sanity check: if (! isEmbeddedOnly()) return 0; NNormalSurfaceList* ans = new NNormalSurfaceList( coords_, NS_CUSTOM | NS_EMBEDDED_ONLY, NS_ALG_CUSTOM); // Find all surfaces that have a compatible partner. std::vector::const_iterator first, second; for (first = surfaces.begin(); first != surfaces.end(); ++first) { for (second = surfaces.begin(); second != surfaces.end(); ++second) { if (second == first) continue; if ((*first)->locallyCompatible(**second)) { ans->surfaces.push_back((*first)->clone()); break; } } } getTriangulation()->insertChildLast(ans); return ans; } NNormalSurfaceList* NNormalSurfaceList::filterForDisjointPairs() const { // Sanity check: if (! isEmbeddedOnly()) return 0; NNormalSurfaceList* ans = new NNormalSurfaceList( coords_, NS_CUSTOM | NS_EMBEDDED_ONLY, NS_ALG_CUSTOM); // Collect all the surfaces that we might care about. // This means non-empty, connected and compact. std::vector interesting; for (std::vector::const_iterator it = surfaces.begin(); it != surfaces.end(); ++it) { if ((*it)->isEmpty()) continue; if (! (*it)->isCompact()) continue; if (! (*it)->isConnected()) continue; interesting.push_back(*it); } // Find all surfaces that have a disjoint partner. std::vector::iterator first, second; for (first = interesting.begin(); first != interesting.end(); ++first) { for (second = interesting.begin(); second != interesting.end(); ++second) { if (second == first) continue; if ((*first)->disjoint(**second)) { ans->surfaces.push_back((*first)->clone()); break; } } } getTriangulation()->insertChildLast(ans); return ans; } NNormalSurfaceList* NNormalSurfaceList::filterForPotentiallyIncompressible() const { // Sanity check: if (! isEmbeddedOnly()) return 0; NNormalSurfaceList* ans = new NNormalSurfaceList( coords_, NS_CUSTOM | NS_EMBEDDED_ONLY, NS_ALG_CUSTOM); NTriangulation* t; #ifdef DEBUG int which = 0; #endif for (std::vector::const_iterator it = surfaces.begin(); it != surfaces.end(); ++it) { #ifdef DEBUG std::cout << "Processing surface " << which++ << "..." << std::endl; #endif if ((*it)->isVertexLinking()) continue; if ((*it)->isThinEdgeLink().first) continue; // If we have a one-sided surface, don't worry about taking the // two-sided double cover. If the complement of the one-sided // surface has a compressing disc, then the complement of the // double cover has the same compressing disc, and this surface // can happily be tossed away. t = (*it)->cutAlong(); if (! t->hasSimpleCompressingDisc()) ans->surfaces.push_back((*it)->clone()); delete t; } getTriangulation()->insertChildLast(ans); return ans; } } // namespace regina regina-4.96/engine/surfaces/filterregistry-impl.h000644 000765 000024 00000007774 12377775515 022120 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/filterregistry-impl.h * \brief Contains the registry of all normal surface filter classes that can * be used to filter lists of normal surfaces in 3-manifold triangulations. * * Each time a new filter is created, this registry must be updated to: * * - add a #include line for the corresponding filter class; * - add a corresponding case to each implementation of forFilter(). * * See filterregistry.h for how other routines can use this registry. */ #ifndef __FILTERREGISTRY_IMPL_H #ifndef __DOXYGEN #define __FILTERREGISTRY_IMPL_H #endif #include "surfaces/nsurfacefilter.h" #include "surfaces/sfproperties.h" #include "surfaces/sfcombination.h" namespace regina { template inline typename FunctionObject::ReturnType forFilter( SurfaceFilterType filter, FunctionObject func, typename FunctionObject::ReturnType defaultReturn) { switch (filter) { case NS_FILTER_DEFAULT : return func(SurfaceFilterInfo()); case NS_FILTER_PROPERTIES : return func(SurfaceFilterInfo()); case NS_FILTER_COMBINATION : return func(SurfaceFilterInfo()); default: return defaultReturn; } } template inline void forFilter(SurfaceFilterType filter, VoidFunctionObject func) { switch (filter) { case NS_FILTER_DEFAULT : func(SurfaceFilterInfo()); break; case NS_FILTER_PROPERTIES : func(SurfaceFilterInfo()); break; case NS_FILTER_COMBINATION : func(SurfaceFilterInfo()); break; default: break; } } } // namespace regina #endif regina-4.96/engine/surfaces/filterregistry.h000644 000765 000024 00000015606 12377775516 021153 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/filterregistry.h * \brief Provides access to a registry of all normal surface filter classes * that can be used to filter lists of normal surfaces in 3-manifold * triangulations. * * Each time a new filter is created, the file filterregistry-impl.h must be * updated to include it. Instructions on how to do this are included in * filterregistry-impl.h. * * External routines can access the registry by calling one of the * forFilter() template functions defined in filterregistry.h. * * \warning You should not include this header unless it is necessary, * since it will automatically import every header for every filter class * in the registry. */ // The old registry macros will silently compile but do nothing. // This could lead to nasty surprises, so throw an error if it looks like // people are still trying to use them. #ifdef __FILTER_REGISTRY_BODY #error "The old REGISTER_FILTER macros have been removed. Use forFilter() instead." #endif #ifndef __FILTERREGISTRY_H #ifndef __DOXYGEN #define __FILTERREGISTRY_H #endif #include "surfaces/surfacefiltertype.h" #include "utilities/registryutils.h" namespace regina { /** * \weakgroup surfaces * @{ */ /** * Allows the user to call a template function whose template parameter * matches a given value of SurfaceFilterType, which is not known * until runtime. In essence, this routine contains a switch/case statement * that runs through all possible normal surface filter types. * * The advantages of this routine are that (i) the user does not need to * repeatedly type such switch/case statements themselves; and (ii) if * a new filter type is added then only a small amount of code * needs to be extended to incorporate it. * * In detail: the function object \a func must define a templated * unary bracket operator, so that func(SurfaceFilterInfo) is * defined for any valid SurfaceFilterType enum value \a t. Then, * when the user calls forFilter(filter, func, defaultReturn), * this routine will call func(SurfaceFilterInfo) and pass * back the corresponding return value. If \a filter does not denote a valid * filter type, then forFilter() will pass back \a defaultReturn instead. * * There is also a two-argument variant of forFilter() that works with * void functions. * * \pre The function object must have a typedef \a ReturnType indicating * the return type of the corresponding templated unary bracket operator. * Inheriting from Returns<...> is a convenient way to ensure this. * * \ifacespython Not present. * * @param filter the given type of normal surface filter. * @param func the function object whose unary bracket operator we will * call with a SurfaceFilterInfo object. * @param defaultReturn the value to return if the given filter type * is not valid. * @return the return value from the corresponding unary bracket * operator of \a func, or \a defaultReturn if the given filter type * is not valid. */ template typename FunctionObject::ReturnType forFilter( SurfaceFilterType filter, FunctionObject func, typename FunctionObject::ReturnType defaultReturn); /** * Allows the user to call a template function whose template parameter * matches a given value of SurfaceFilterType, which is not known * until runtime. In essence, this routine contains a switch/case statement * that runs through all possible normal surface filter types. * * The advantages of this routine are that (i) the user does not need to * repeatedly type such switch/case statements themselves; and (ii) if * a new filter type is added then only a small amount of code * needs to be extended to incorporate it. * * In detail: the function object \a func must define a templated * unary bracket operator, so that func(SurfaceFilterInfo) is * defined for any valid SurfaceFilterType enum value \a t. Then, * when the user calls forFilter(filter, func), * this routine will call func(SurfaceFilterInfo) in turn. * If \a filter does not denote a valid filter type, then forFilter() * will do nothing. * * There is also a three-argument variant of forFilter() that works with * functions with return values. * * \ifacespython Not present. * * @param filter the given type of normal surface filter. * @param func the function object whose unary bracket operator we will * call with a SurfaceFilterInfo object. */ template void forFilter(SurfaceFilterType filter, VoidFunctionObject func); /*@}*/ } // namespace regina // Import template implementations: #include "surfaces/filterregistry-impl.h" #endif regina-4.96/engine/surfaces/flavourregistry.h000644 000765 000024 00000004661 12377775550 021341 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/flavourregistry.h * \brief Deprecated header. */ #warning This header is deprecated; please use coordregistry.h instead. #include "surfaces/coordregistry.h" regina-4.96/engine/surfaces/links.cpp000644 000765 000024 00000030521 12377776720 017537 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "surfaces/nnormalsurface.h" #include "triangulation/ntriangulation.h" #include #define NO_EDGES std::make_pair(static_cast(0), static_cast(0)) namespace regina { bool NNormalSurfaceVector::isVertexLinking(const NTriangulation* triang) const { unsigned long nTets = triang->getNumberOfTetrahedra(); unsigned long tet; int type; for (tet = 0; tet < nTets; tet++) { for (type = 0; type < 3; type++) if (getQuadCoord(tet, type, triang) != 0) return false; } if (allowsAlmostNormal()) for (tet = 0; tet < nTets; tet++) for (type = 0; type < 3; type++) if (getOctCoord(tet, type, triang) != 0) return false; return true; } const NVertex* NNormalSurfaceVector::isVertexLink(const NTriangulation* triang) const { unsigned long nTets = triang->getNumberOfTetrahedra(); unsigned long tet; int type; // Check that there are no quad/oct discs. for (tet = 0; tet < nTets; tet++) { for (type = 0; type < 3; type++) if (getQuadCoord(tet, type, triang) != 0) return 0; } if (allowsAlmostNormal()) for (tet = 0; tet < nTets; tet++) for (type = 0; type < 3; type++) if (getOctCoord(tet, type, triang) != 0) return 0; // Now examine the triangle to see if we link only a single vertex. std::set notAns; /**< We will ignore notAns once ans != 0. */ NVertex* ans = 0; NLargeInteger ansMult; const NTetrahedron* t; NVertex* v; NLargeInteger coord; for (tet = 0; tet < nTets; tet++) { t = triang->getTetrahedron(tet); for (type = 0; type < 4; type++) { v = t->getVertex(type); coord = getTriangleCoord(tet, type, triang); if (coord == 0) { // No discs in this coordinate. // Do we have a candidate vertex yet? if (! ans) { // Still haven't found a candidate. notAns.insert(v); } else if (ans == v) { // This is our only candidate vertex. return 0; } } if (coord != 0) { // Some discs in this coordinate. // Do we have a candidate vertex? if (! ans) { // We've found our first and only possible candidate. if (notAns.count(v)) return 0; ans = v; ansMult = coord; } else if (ans == v) { // This vertex matches our current candidate. if (ansMult != coord) return 0; } else { // This vertex does not match our current candidate. return 0; } } else { // No discs in this coordinate. if (ans == v) return 0; } } } return ans; } std::pair NNormalSurfaceVector::isThinEdgeLink( const NTriangulation* triang) const { unsigned long nTets = triang->getNumberOfTetrahedra(); unsigned long tet; int type; // Check that there are no octagonal discs. if (allowsAlmostNormal()) for (tet = 0; tet < nTets; tet++) for (type = 0; type < 3; type++) if (getOctCoord(tet, type, triang) != 0) return NO_EDGES; // Run through the quadrilateral discs and work out if there are any // valid candidates. std::set notAns; /**< We will ignore notAns once ans != 0. */ bool foundQuads = false; const NEdge* ans[2]; NLargeInteger ansMultDouble; const NTetrahedron* t; NEdge* e[6]; // { 2*link, 4*intersect } NLargeInteger coord; int i; for (tet = 0; tet < nTets; tet++) { t = triang->getTetrahedron(tet); for (type = 0; type < 3; type++) { coord = getQuadCoord(tet, type, triang); e[0] = t->getEdge(NEdge::edgeNumber[vertexSplitDefn[type][0]] [vertexSplitDefn[type][1]]); e[1] = t->getEdge(NEdge::edgeNumber[vertexSplitDefn[type][2]] [vertexSplitDefn[type][3]]); e[2] = t->getEdge(NEdge::edgeNumber[vertexSplitDefn[type][0]] [vertexSplitDefn[type][2]]); e[3] = t->getEdge(NEdge::edgeNumber[vertexSplitDefn[type][0]] [vertexSplitDefn[type][3]]); e[4] = t->getEdge(NEdge::edgeNumber[vertexSplitDefn[type][1]] [vertexSplitDefn[type][2]]); e[5] = t->getEdge(NEdge::edgeNumber[vertexSplitDefn[type][1]] [vertexSplitDefn[type][3]]); if (coord == 0) { // No discs in this coordinate. // Do we have any candidate edges yet? if (foundQuads) { // Rule out any candidates that should have discs here. for (i = 0; i < 2; i++) if (ans[i] == e[0] || ans[i] == e[1]) ans[i] = 0; } else { // Still haven't found any candidates. notAns.insert(e[0]); notAns.insert(e[1]); } } else { // Some discs in this coordinate. // Do we have any candidate edges yet? if (foundQuads) { // Check consistency with our candidates. if (e[0] == e[1]) { // Same edge on both sides of the quad. // Note that there can only be one candidate now. if (e[0] == ans[0]) ans[1] = 0; else if (e[0] == ans[1]) { ans[0] = ans[1]; ans[1] = 0; } else return NO_EDGES; // The only possible candidate is ans[0]. if (ans[0] == 0 || ansMultDouble != coord) return NO_EDGES; } else { // Different edges on both sides of the quad. // Check each candidate in turn. for (i = 0; i < 2; i++) if (ans[i] != e[0] && ans[i] != e[1]) ans[i] = 0; if (ansMultDouble != coord * 2) return NO_EDGES; } } else { // We've found our first and only possible candidates. if (e[0] == e[1]) { // Same edge on both sides of the quad. if (notAns.count(e[0])) return NO_EDGES; ans[0] = e[0]; ans[1] = 0; ansMultDouble = coord; } else { // Different edges on both sides of the quad. for (i = 0; i < 2; i++) { if (notAns.count(e[i])) ans[i] = 0; else { ans[i] = e[i]; ansMultDouble = coord; ansMultDouble *= 2; } } } foundQuads = true; } // We now absolutely have candidates (or have exhausted // them all). Check that these candidates don't // intersect the new quads. for (i = 2; i < 6; i++) { if (ans[0] == e[i]) ans[0] = 0; if (ans[1] == e[i]) ans[1] = 0; } } // Have we ruled out all the candidates we ever had? if (foundQuads && (! ans[0]) && (! ans[1])) return NO_EDGES; } } // So did we actually find anything? if (! foundQuads) return NO_EDGES; if ((! ans[0]) && (! ans[1])) return NO_EDGES; // Finally check the triangular discs. NVertex* v; bool expectZero[2]; int j; for (tet = 0; tet < nTets; tet++) { t = triang->getTetrahedron(tet); for (type = 0; type < 4; type++) { v = t->getVertex(type); coord = getTriangleCoord(tet, type, triang); // Should we actually see any discs? for (i = 0; i < 2; i++) { if (! ans[i]) continue; // If the candidate edge does not touch this vertex, the // triangular coordinate should be 0. expectZero[i] = (v != ans[i]->getVertex(0) && v != ans[i]->getVertex(1)); // If this triangular disc type intersects the candidate // edge, the coordinate should also be 0. if (! expectZero[i]) for (j = 0; j < 3; j++) if (t->getEdge(NEdge::edgeNumber[type][(type+j+1) % 4]) == ans[i]) { expectZero[i] = true; break; } // So did we get the right triangular coordinate? if (expectZero[i]) { if (coord != 0) ans[i] = 0; } else { if (ansMultDouble != coord * 2) ans[i] = 0; } } // Have we ruled out all possibilities? if ((! ans[0]) && (! ans[1])) return NO_EDGES; } } // Return whatever candidates have survived. if (ans[0]) return std::make_pair(ans[0], ans[1]); else return std::make_pair(ans[1], ans[0]); } } // namespace regina regina-4.96/engine/surfaces/ndisc.cpp000644 000765 000024 00000020506 12377776722 017523 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "surfaces/nnormalsurface.h" #include "surfaces/ndisc.h" namespace regina { std::ostream& operator << (std::ostream& out, const NDiscSpec& spec) { out << '(' << spec.tetIndex << ", " << spec.type << ", " << spec.number << ')'; return out; } bool numberDiscsAwayFromVertex(int discType, int vertex) { if (discType < 4) return (vertex == discType); return (vertex == 0 || vertex == vertexSplitPartner[(discType - 1) % 3][0]); } bool discOrientationFollowsEdge(int discType, int vertex, int edgeStart, int edgeEnd) { NPerm4 forwards(vertex, edgeStart, edgeEnd, 6-vertex-edgeStart-edgeEnd); NPerm4 reverse(vertex, edgeEnd, edgeStart, 6-vertex-edgeStart-edgeEnd); if (discType < 4) { for (int i = 0; i < 3; i++) { if (triDiscArcs(discType, i) == forwards) return true; if (triDiscArcs(discType, i) == reverse) return false; } } else if (discType < 7) { for (int i = 0; i < 4; i++) { if (quadDiscArcs(discType - 4, i) == forwards) return true; if (quadDiscArcs(discType - 4, i) == reverse) return false; } } else { for (int i = 0; i < 8; i++) { if (octDiscArcs(discType - 7, i) == forwards) return true; if (octDiscArcs(discType - 7, i) == reverse) return false; } } return false; } NDiscSetTet::NDiscSetTet(const NNormalSurface& surface, unsigned long tetIndex) { int i; for (i=0; i<4; i++) internalNDiscs[i] = surface.getTriangleCoord(tetIndex, i).longValue(); for (i=4; i<7; i++) internalNDiscs[i] = surface.getQuadCoord(tetIndex, i - 4).longValue(); for (i=7; i<10; i++) internalNDiscs[i] = surface.getOctCoord(tetIndex, i - 7).longValue(); } NDiscSetTet::NDiscSetTet(unsigned long tri0, unsigned long tri1, unsigned long tri2, unsigned long tri3, unsigned long quad0, unsigned long quad1, unsigned long quad2, unsigned long oct0, unsigned long oct1, unsigned long oct2) { internalNDiscs[0] = tri0; internalNDiscs[1] = tri1; internalNDiscs[2] = tri2; internalNDiscs[3] = tri3; internalNDiscs[4] = quad0; internalNDiscs[5] = quad1; internalNDiscs[6] = quad2; internalNDiscs[7] = oct0; internalNDiscs[8] = oct1; internalNDiscs[9] = oct2; } unsigned long NDiscSetTet::arcFromDisc(int /* arcFace */, int arcVertex, int discType, unsigned long discNumber) const { // Is it a triangle? if (discType < 4) return discNumber; // It's a quad or an octagon. // Note that there is at most one octagonal or quad type present // (since the surface must be embedded), so this must be it. if (arcVertex == 0 || arcVertex == vertexSplitPartner[(discType - 1) % 3][0]) return internalNDiscs[arcVertex] + discNumber; else return internalNDiscs[arcVertex] + internalNDiscs[discType] - discNumber - 1; } void NDiscSetTet::discFromArc(int arcFace, int arcVertex, unsigned long arcNumber, int& discType, unsigned long& discNumber) const { // Is it a triangle? if (arcNumber < internalNDiscs[arcVertex]) { discType = arcVertex; discNumber = arcNumber; return; } // It's a quad or an octagon. // Note that there is at most one octagonal or quad type present // (since the surface must be embedded), so this must be it. if (internalNDiscs[vertexSplit[arcVertex][arcFace] + 4] > 0) discType = vertexSplit[arcVertex][arcFace] + 4; else if (internalNDiscs[vertexSplitMeeting[arcVertex][arcFace][0] + 7] > 0) discType = vertexSplitMeeting[arcVertex][arcFace][0] + 7; else discType = vertexSplitMeeting[arcVertex][arcFace][1] + 7; if (arcVertex == 0 || arcVertex == vertexSplitPartner[(discType - 1) % 3][0]) discNumber = arcNumber - internalNDiscs[arcVertex]; else discNumber = internalNDiscs[discType] - (arcNumber - internalNDiscs[arcVertex]) - 1; } NDiscSetSurface::NDiscSetSurface(const NNormalSurface& surface, bool) : triangulation(surface.getTriangulation()) { unsigned long tot = triangulation->getNumberOfTetrahedra(); if (tot == 0) discSets = 0; else discSets = new NDiscSetTet*[tot]; } NDiscSetSurface::NDiscSetSurface(const NNormalSurface& surface) : triangulation(surface.getTriangulation()) { unsigned long tot = triangulation->getNumberOfTetrahedra(); if (tot == 0) discSets = 0; else { discSets = new NDiscSetTet*[tot]; for (unsigned long index = 0; index < tot; index++) discSets[index] = new NDiscSetTet(surface, index); } } NDiscSetSurface::~NDiscSetSurface() { if (discSets) { unsigned long tot = nTets(); for (unsigned long index = 0; index < tot; index++) delete discSets[index]; delete[] discSets; } } NDiscSpec* NDiscSetSurface::adjacentDisc(const NDiscSpec& disc, NPerm4 arc, NPerm4& adjArc) const { const NTetrahedron* tet = triangulation->getTetrahedron(disc.tetIndex); int arcFace = arc[3]; if (tet->adjacentTetrahedron(arcFace) == 0) return 0; NDiscSpec* ans = new NDiscSpec; ans->tetIndex = triangulation->tetrahedronIndex( tet->adjacentTetrahedron(arcFace)); adjArc = tet->adjacentGluing(arcFace) * arc; unsigned long arcNumber = discSets[disc.tetIndex]->arcFromDisc( arcFace, arc[0], disc.type, disc.number); discSets[ans->tetIndex]->discFromArc(adjArc[3], adjArc[0], arcNumber, ans->type, ans->number); return ans; } void NDiscSpecIterator::makeValid() { while (current.number == internalDiscSet->nDiscs(current.tetIndex, current.type)) { current.number = 0; current.type++; if (current.type == 10) { current.type = 0; current.tetIndex++; if (current.tetIndex == internalDiscSet->nTets()) break; } } } } // namespace regina regina-4.96/engine/surfaces/ndisc.h000644 000765 000024 00000101307 12377775551 017166 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/ndisc.h * \brief Deals with individual normal discs and sets of normal discs * in a normal surface. */ #ifndef __NDISC_H #ifndef __DOXYGEN #define __NDISC_H #endif #include #include "regina-core.h" #include "surfaces/nnormalsurface.h" #include "triangulation/ntriangulation.h" namespace regina { /** * \weakgroup surfaces * @{ */ /** * Specifies a single normal disc in a normal surface. * * There are 10 disc types. Types 0-3 represent triangles 0-3, * types 4-6 represent quads 0-2 and types 7-9 represent * octagons 0-2. * * Discs of a specific type are assigned numbers from 0 upwards. * Triangular discs are numbered outwards from the vertex they surround. * Quad discs and octagonal discs are numbered outwards away from vertex 0 * of the tetrahedron. * * Note that, unlike NDiscType in which the meaning of NDiscType::type is * flexible, the meaning of NDiscSpec::type is fixed as described above. * * \warning This class converts the indices of normal discs of a * given type from NLargeInteger to unsigned long. See the * precondition below. * * \pre The number of normal discs of a particular type * in a particular tetrahedron can be represented by a long integer. * \pre This class should only be used with \a embedded * normal surfaces. */ struct REGINA_API NDiscSpec { unsigned long tetIndex; /**< The index in the triangulation of the tetrahedron containing the disc. */ int type; /**< The disc type; this is between 0 and 9 inclusive, as described in the \a NDiscSpec class notes. */ unsigned long number; /**< Specifies which disc of the particular type in the particular tetrahedron is being referred to; discs are numbered as described in the \a NDiscSpec class notes. */ /** * Creates a new uninitialised disc specifier. */ NDiscSpec(); /** * Creates a new disc specifier containing the given values. * * @param newTetIndex the index in the triangulation of the tetrahedron * containing the disc. * @param newType the disc type; this is between 0 and 9 inclusive, * as described in the \a NDiscSpec class notes. * @param newNumber specifies which disc of the particular type in the * particular tetrahedron is being referred to; discs are numbered * as described in the \a NDiscSpec class notes. */ NDiscSpec(unsigned long newTetIndex, int newType, unsigned long newNumber); /** * Creates a new disc specifier that is a clone of the given specifier. * * @param cloneMe the disc specifier to clone. */ NDiscSpec(const NDiscSpec& cloneMe); /** * Copies the values from the given disc specifier into this specifier. * * @param cloneMe the disc specifier whose values should be copied. * @return a reference to this disc specifier. */ NDiscSpec& operator = (const NDiscSpec& cloneMe); /** * Determines if this and the given disc specifier contain identical * information. * * @param other the disc specifier to compare with this. * @return \c true if and only if this and the given disc specifier * contain identical information. */ bool operator == (const NDiscSpec& other) const; friend std::ostream& operator << (std::ostream& out, const NDiscSpec& spec); }; /** * Writes the given disc specifier to the given output stream. * The disc specifier will be written as a triple * (tetIndex, type, number). * * @param out the output stream to which to write. * @param spec the disc specifier to write. * @return a reference to \a out. */ REGINA_API std::ostream& operator << (std::ostream& out, const NDiscSpec& spec); /** * Determines whether or not normal discs of the given type are * numbered away from the given vertex. * * @param discType the normal disc type under consideration; this * should be between 0 and 9 inclusive, as described by the NDiscSpec * class notes. * @param vertex the vertex under consideration; this should be * between 0 and 3 inclusive. * @return \c true if normal discs of the given type are * numbered away from the given vertex, or \c false if they are * numbered towards the given vertex. */ REGINA_API bool numberDiscsAwayFromVertex(int discType, int vertex); /** * Determines whether or not the natural boundary orientation of a normal * disc of the given type follows the given directed normal arc. * Natural boundary orientation is defined by arrays regina::triDiscArcs, * regina::quadDiscArcs and regina::octDiscArcs. * * \pre The given normal arc lies on a normal disc of the given type. * * @param discType the normal disc type under consideration; this should * be between 0 and 9 inclusive, as described by the NDiscSpec class * notes. * @param vertex the vertex about which the normal arc runs. * @param edgeStart the start vertex of the edge to which the normal arc * is parallel. * @param edgeEnd the end vertex of the edge to which the normal arc is * parallel. */ REGINA_API bool discOrientationFollowsEdge(int discType, int vertex, int edgeStart, int edgeEnd); /** * Represents a set of normal discs inside a single tetrahedron. * The numbers of discs of each type are stored in this structure, so * querying them is fast regardless of the underlying normal surface * coordinate system used. * * \warning This class converts the number of normal discs of a * given type from NLargeInteger to unsigned long. See the * precondition below. * * \pre The number of normal discs of a particular type * in a particular tetrahedron can be represented by a long integer. * \pre This class should only be used with \a embedded normal surfaces. * * \todo \problong Have some error flag so we can barf politely if the number * of normal discs of a given type does not fit into an unsigned * long. See how this affects NDiscSetTetData also. */ class REGINA_API NDiscSetTet { protected: unsigned long internalNDiscs[10]; /**< The number of discs of each type. */ public: /** * Creates a new set of normal discs corresponding to the discs * of the given normal surface that lie within the given * tetrahedron. * * @param surface the normal surface whose discs we shall use. * @param tetIndex the index in the triangulation of the * tetrahedron that our discs must lie in; this must be between * 0 and tri.getNumberOfTetrahedra()-1 inclusive, where * tri is the triangulation containing the given normal * surface. */ NDiscSetTet(const NNormalSurface& surface, unsigned long tetIndex); /** * Creates a new set of normal discs where the number of discs of * each type is explicitly given. * * @param tri0 the number of triangular discs surrounding vertex 0. * @param tri1 the number of triangular discs surrounding vertex 1. * @param tri2 the number of triangular discs surrounding vertex 2. * @param tri3 the number of triangular discs surrounding vertex 3. * @param quad0 the number of quadrilateral discs of type 0. * @param quad1 the number of quadrilateral discs of type 1. * @param quad2 the number of quadrilateral discs of type 2. * @param oct0 the number of octahedral discs of type 0. * @param oct1 the number of octahedral discs of type 1. * @param oct2 the number of octahedral discs of type 2. */ NDiscSetTet(unsigned long tri0, unsigned long tri1, unsigned long tri2, unsigned long tri3, unsigned long quad0, unsigned long quad1, unsigned long quad2, unsigned long oct0 = 0, unsigned long oct1 = 0, unsigned long oct2 = 0); /** * Destroys this disc set. */ virtual ~NDiscSetTet(); /** * Determines the number of discs of the given type inside this * tetrahedron. * * @param type the disc type to examine; this should be between * 0 and 9 inclusive. Disc types are outlined in * the NDiscSpec class notes. * @return the number of discs of the given type inside this * tetrahedron. */ unsigned long nDiscs(int type) const; /** * Determines which normal arc of a given type on a given face * of this tetrahedron corresponds to the given normal disc. * * \pre The given normal disc actually meets a * normal arc of the given type on the given face. * * @param arcFace the face of this tetrahedron containing the * normal arc (between 0 and 3 inclusive). * @param arcVertex the vertex of this tetrahedron about which the * normal arc runs (between 0 and 3 inclusive); \a arcFace and * \a arcVertex should not be the same. * @param discType the disc type of the given normal disc; * this should be between 0 and 9 inclusive, as described in the * NDiscSpec class notes. * @param discNumber indicates which normal disc of the given disc * type is referred to (between 0 and nDiscs(discType)-1 * inclusive). * @return the number of the normal arc of the given type that belongs * to the given normal disc. * Arcs of a given type (where \a arcFace and \a arcVertex * together define the arc type) are numbered starting at 0 from the * tetrahedron vertex outwards. */ unsigned long arcFromDisc(int arcFace, int arcVertex, int discType, unsigned long discNumber) const; /** * Determines which normal disc in this tetrahedron meets * the given normal arc on the given face. * * \pre The given normal arc * actually exists in the normal surface with which this * \a NDiscSetTet object was created. * * @param arcFace the face of this tetrahedron containing the * normal arc (between 0 and 3 inclusive). * @param arcVertex the vertex of this tetrahedron about which the * normal arc runs (between 0 and 3 inclusive); \a arcFace and * \a arcVertex should not be the same. * @param arcNumber indicates which normal arc of the given type * is referred to. * Arcs of a given type (where \a arcFace and \a arcVertex * together define the arc type) are numbered starting at 0 from the * tetrahedron vertex outwards. * @param discType returns the disc type of the normal disc that * meets the given normal arc; this will be between 0 and 9 * inclusive, as described in the NDiscSpec class notes. * Any value may be initially passed. * @param discNumber returns a number that indicates which * normal disc of the returned disc type (discType) * meets the given normal arc; this will be between 0 and * nDiscs(discType)-1 inclusive. Any value may be * initially passed. */ void discFromArc(int arcFace, int arcVertex, unsigned long arcNumber, int& discType, unsigned long& discNumber) const; }; /** * Stores data of type \c T for every normal disc inside a single * tetrahedron. * * \warning This class converts the number of normal discs of a * given type from NLargeInteger to unsigned long. See the * precondition below. * * \pre The number of normal discs of a particular type * in a particular tetrahedron can be represented by a long integer. * \pre This class should only be used with \a embedded * normal surfaces. * \pre Type T has a default constructor and an * assignment operator. That is, if \c a and \c b are of type T, then * \c a can be declared with no parameters and can then receive the * value of \c b using a=b. * * \ifacespython Not present. */ template class NDiscSetTetData : public NDiscSetTet { public: typedef T* DataPtr; /**< A type that is a pointer to the data stored with each * disc. */ protected: DataPtr internalData[10]; /**< Stores the data corresponding to each normal disc. */ public: /** * Creates a new disc set corresponding to the discs of the * given normal surface that lie within the given tetrahedron. * The data for each disc will remain uninitialised. * * @param surface the normal surface whose discs we shall use. * @param tetIndex the index in the triangulation of the * tetrahedron that our discs must lie in; this must be between * 0 and tri.getNumberOfTetrahedra()-1 inclusive, where * tri is the triangulation containing the given normal * surface. */ NDiscSetTetData(const NNormalSurface& surface, unsigned long tetIndex) : NDiscSetTet(surface, tetIndex) { for (int i=0; i<10; i++) if (internalNDiscs[i]) internalData[i] = new T[internalNDiscs[i]]; else internalData[i] = 0; } /** * Creates a new disc set corresponding to the discs of the * given normal surface that lie within the given tetrahedron. * The data for each disc will be initialised to the given * value. * * @param surface the normal surface whose discs we shall use. * @param tetIndex the index in the triangulation of the * tetrahedron that our discs must lie in; this must be between * 0 and tri.getNumberOfTetrahedra()-1 inclusive, where * tri is the triangulation containing the given normal * surface. * @param initValue the value with which to initialise the data * corresponding to each disc. */ NDiscSetTetData(const NNormalSurface& surface, unsigned long tetIndex, const T& initValue) : NDiscSetTet(surface, tetIndex) { unsigned long disc; for (int i=0; i<10; i++) if (internalNDiscs[i]) { internalData[i] = new T[internalNDiscs[i]]; for (disc = 0; disc < internalNDiscs[i]; disc++) internalData[i][disc] = initValue; } else internalData[i] = 0; } /** * Creates a new disc set where the number of discs of each type * is explicitly given. The data for each disc will remain * uninitialised. * * @param tri0 the number of triangular discs surrounding vertex 0. * @param tri1 the number of triangular discs surrounding vertex 1. * @param tri2 the number of triangular discs surrounding vertex 2. * @param tri3 the number of triangular discs surrounding vertex 3. * @param quad0 the number of quadrilateral discs of type 0. * @param quad1 the number of quadrilateral discs of type 1. * @param quad2 the number of quadrilateral discs of type 2. * @param oct0 the number of octahedral discs of type 0. * @param oct1 the number of octahedral discs of type 1. * @param oct2 the number of octahedral discs of type 2. */ NDiscSetTetData(unsigned long tri0, unsigned long tri1, unsigned long tri2, unsigned long tri3, unsigned long quad0, unsigned long quad1, unsigned long quad2, unsigned long oct0 = 0, unsigned long oct1 = 0, unsigned long oct2 = 0) : NDiscSetTet(tri0, tri1, tri2, tri3, quad0, quad1, quad2, oct0, oct1, oct2) { for (int i=0; i<10; i++) if (internalNDiscs[i]) internalData[i] = new T[internalNDiscs[i]]; else internalData[i] = 0; } /** * Destroys this disc set and deallocates all data arrays. * Note that no assumption is made about type \c T, so if data * elements are pointers to dynamically allocated objects, these * will not be destroyed. */ virtual ~NDiscSetTetData() { for (int i=0; i<10; i++) if (internalData[i]) delete[] internalData[i]; } /** * Retrieves a reference to the data corresponding to the given * normal disc. * * @param discType the disc type of the given normal disc; * this should be between 0 and 9 inclusive, as described in the * NDiscSpec class notes. * @param discNumber indicates which normal disc of the given disc * type is referred to; this should be between 0 and * nDiscs(discType)-1 inclusive. * @return a reference to the data corresponding to the given * normal disc. */ T& data(int discType, unsigned long discNumber) { assert(0 <= discType && discType < 10); assert(discNumber < internalNDiscs[discType]); return internalData[discType][discNumber]; } }; /** * Represents the set of all normal discs forming a normal surface. * These are stored as an array of NDiscSetTet objects, one for each * tetrahedron. * * \warning This class converts the number of normal discs of a * given type from NLargeInteger to unsigned long. See the * precondition below. * * \pre The number of normal discs of a particular type * in a particular tetrahedron can be represented by a long integer. * \pre This class should only be used with \a embedded * normal surfaces. */ class REGINA_API NDiscSetSurface { protected: NDiscSetTet** discSets; /**< The disc sets corresponding to each tetrahedron. */ const NTriangulation* triangulation; /**< The triangulation in which the normal surface lives. */ protected: /** * Creates a new disc set corresponding to the discs of the * given normal surface. The array of tetrahedron disc set * pointers will be created but the NDiscSetTet objects themselves * will not be created. * * This constructor should be called from constructors of subclasses * who wish to use objects of a subclass of NDiscSetTet, which * this constructor allows them to create for themselves. * * \warning After calling this constructor, each * NDiscSetTet object * in the \a discSets array must be created, since the * \a NDiscSetSurface destructor will attempt to destroy them! * The \a discSets array will have size * surface.getTriangulation()->getNumberOfTetrahedra(). * * @param surface the normal surface whose discs we shall use. * @param b this parameter is ignored. */ NDiscSetSurface(const NNormalSurface& surface, bool b); public: /** * Creates a new disc set corresponding to the discs of the * given normal surface. * * @param surface the normal surface whose discs we shall use. */ NDiscSetSurface(const NNormalSurface& surface); /** * Destroys this set of discs and deallocates all associated memory. */ virtual ~NDiscSetSurface(); /** * Returns the number of tetrahedra in the underlying * triangulation. * * @return the number of tetrahedra. */ unsigned long nTets() const; /** * Determines the number of discs of the given type inside the * given tetrahedron. * * @param tetIndex the index in the triangulation of the * tetrahedron to examine. * @param type the disc type to examine; this should be between * 0 and 9 inclusive. Disc types are outlined in * the NDiscSpec class notes. * @return the number of discs of the given type inside the * given tetrahedron. */ unsigned long nDiscs(unsigned long tetIndex, int type) const; /** * Returns the specific set of discs living inside the given * tetrahedron. * * @param tetIndex the index in the triangulation of the given * tetrahedron. * @return the set of discs inside the given tetrahedron. */ NDiscSetTet& tetDiscs(unsigned long tetIndex) const; /** * Determines which normal disc is adjacent to the given normal disc * along the given directed normal arc in the surface described by * this disc set. * * A directed normal arc will be specified by a permutation * p, where the arc runs around vertex p[0] * parallel to the directed edge from vertex p[1] to * p[2]. * * @param disc the given normal disc; this must be a disc in this * disc set. * @param arc the given normal arc; this must actually be an arc * on the boundary of the given normal disc (although it may run * in either direction). * @param adjArc returns the same directed normal arc that was * passed, but expressed in terms of the vertices of the * adjacent tetrahedron. Any value may be initially passed. If * there is no adjacent disc/tetrahedron, this permutation will * remain unchanged. * @return the normal disc adjacent to the given disc along the * given arc, or 0 if there is no adjacent disc. This disc * specifier will be newly created, and it is up to the caller * of this routine to dispose of it. */ NDiscSpec* adjacentDisc(const NDiscSpec& disc, NPerm4 arc, NPerm4& adjArc) const; }; /** * Stores data of type \c T for every normal disc within a particular * normal surface. * This data is stored using an array of NDiscSetTetData objects, * one for each tetrahedron (thus the inherited member function * tetDiscs() will return an object of class NDiscSetTetData). * * \warning This class converts the number of normal discs of a * given type from NLargeInteger to unsigned long. See the * precondition below. * * \pre The number of normal discs of a particular type * in a particular tetrahedron can be represented by a long integer. * \pre This class should only be used with \a embedded normal surfaces. * \pre Type T has a default constructor and an * assignment operator. That is, if \c a and \c b are of type T, then * \c a can be declared with no parameters and can then receive the * value of \c b using a=b. * * \ifacespython Not present. */ template class NDiscSetSurfaceData : public NDiscSetSurface { public: /** * Creates a new disc set corresponding to the discs of the * given normal surface. * The data for each disc will remain uninitialised. * * @param surface the normal surface whose discs we shall use. */ NDiscSetSurfaceData(const NNormalSurface& surface) : NDiscSetSurface(surface, true) { unsigned long tot = triangulation->getNumberOfTetrahedra(); if (tot) for (unsigned long index = 0; index < tot; index++) discSets[index] = new NDiscSetTetData(surface, index); } /** * Creates a new disc set corresponding to the discs of the * given normal surface. * The data for each disc will be initialised to the given * value. * * @param surface the normal surface whose discs we shall use. * @param initValue the value with which to initialise the data * corresponding to each disc. */ NDiscSetSurfaceData(const NNormalSurface& surface, const T& initValue) : NDiscSetSurface(surface, true) { unsigned long tot = triangulation->getNumberOfTetrahedra(); if (tot) for (unsigned long index = 0; index < tot; index++) discSets[index] = new NDiscSetTetData(surface, index, initValue); } /** * Retrieves a reference to the data corresponding to the given * normal disc. * * @param disc the disc whose data we require; this must refer * to a disc within this disc set. * @return a reference to the data corresponding to the given * normal disc. */ T& data(const NDiscSpec& disc) { return dynamic_cast*>(discSets[disc.tetIndex])-> data(disc.type, disc.number); } }; /** * An iterator used for running through all normal discs in a normal * surface. * * \warning This class converts the indices of normal discs of a * given type from NLargeInteger to unsigned long. See the * precondition below. * * \pre The number of normal discs of a particular type * in a particular tetrahedron can be represented by a long integer. */ class REGINA_API NDiscSpecIterator { protected: const NDiscSetSurface* internalDiscSet; /**< The disc set through which we are iterating. */ NDiscSpec current; /**< The disc currently pointed to. */ public: /** * Creates a new uninitialised iterator. * This iterator cannot be used or queried until init() is called. */ NDiscSpecIterator(); /** * Creates a new iterator pointing to the first disc in the * given disc set. * * @param discSet the disc set used to initialise this iterator. */ NDiscSpecIterator(const NDiscSetSurface& discSet); /** * Points this iterator to the first disc in the given disc set. * * @param discSet the disc set used to reinitialise this iterator. */ void init(const NDiscSetSurface& discSet); /** * Points this iterator to the next disc, or makes it * past-the-end if there is no next disc. * * Unlike most standard increment operators, this operator returns * \c void. One consequence of this is that the preincrement * and postincrement operators for this class are identical. This * interface will need to be made more standard some day. * * \pre This iterator is not past-the-end. * * \ifacespython This routine is called inc(), since Python does * not support the increment operator. */ void operator++(); /** * Points this iterator to the next disc, or makes it * past-the-end if there is no next disc. * * Unlike most standard increment operators, this operator returns * \c void. One consequence of this is that the preincrement * and postincrement operators for this class are identical. This * interface will need to be made more standard some day. * * \pre This iterator is not past-the-end. * * \ifacespython This routine is called inc(), since Python does * not support the increment operator. */ void operator++(int); /** * Returns a reference to the disc pointed to by this iterator. * * \pre This iterator is not past-the-end. * * \ifacespython This routine is called deref(), since Python does * not support the dereference operator. * * @return a reference to the disc pointed to by this iterator. */ const NDiscSpec& operator *() const; /** * Determines if this iterator is past-the-end. * * @return \c true if and only if this iterator is past-the-end. */ bool done() const; private: /** * Ensures the data member \a current points to a real disc and * not a virtual disc (in which the disc number exceeds the * number of discs of the corresponding type). * * \pre This iterator is not yet past-the-end * (although it may be in the middle of an increment operation * that will put it past-the-end). */ void makeValid(); }; /*@}*/ // Inline functions for NDiscSpec inline NDiscSpec::NDiscSpec() { } inline NDiscSpec::NDiscSpec(unsigned long newTetIndex, int newType, unsigned long newNumber) : tetIndex(newTetIndex), type(newType), number(newNumber) { } inline NDiscSpec::NDiscSpec(const NDiscSpec& cloneMe) : tetIndex(cloneMe.tetIndex), type(cloneMe.type), number(cloneMe.number) { } inline NDiscSpec& NDiscSpec::operator = (const NDiscSpec& cloneMe) { tetIndex = cloneMe.tetIndex; type = cloneMe.type; number = cloneMe.number; return *this; } inline bool NDiscSpec::operator == (const NDiscSpec& other) const { return (tetIndex == other.tetIndex && type == other.type && number == other.number); } // Inline functions for NDiscSetTet inline NDiscSetTet::~NDiscSetTet() { } inline unsigned long NDiscSetTet::nDiscs(int type) const { return internalNDiscs[type]; } // Inline functions for NDiscSetSurface inline unsigned long NDiscSetSurface::nTets() const { return triangulation->getNumberOfTetrahedra(); } inline unsigned long NDiscSetSurface::nDiscs(unsigned long tetIndex, int type) const { return discSets[tetIndex]->nDiscs(type); } inline NDiscSetTet& NDiscSetSurface::tetDiscs(unsigned long tetIndex) const { return *(discSets[tetIndex]); } // Inline functions for NDiscSpecIterator inline NDiscSpecIterator::NDiscSpecIterator() { } inline NDiscSpecIterator::NDiscSpecIterator(const NDiscSetSurface& discSet) : internalDiscSet(&discSet), current(0, 0, 0) { makeValid(); } inline void NDiscSpecIterator::init(const NDiscSetSurface& discSet) { internalDiscSet = &discSet; current.tetIndex = 0; current.type = 0; current.number = 0; makeValid(); } inline void NDiscSpecIterator::operator++() { current.number++; makeValid(); } inline void NDiscSpecIterator::operator++(int) { current.number++; makeValid(); } inline const NDiscSpec& NDiscSpecIterator::operator *() const { return current; } inline bool NDiscSpecIterator::done() const { return (current.tetIndex == internalDiscSet->nTets()); } } // namespace regina #endif regina-4.96/engine/surfaces/ndisctype.cpp000644 000765 000024 00000004551 12377776724 020431 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "surfaces/ndisctype.h" namespace regina { const NDiscType NDiscType::NONE; } // namespace regina regina-4.96/engine/surfaces/ndisctype.h000644 000765 000024 00000017266 12377775552 020103 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/ndisctype.h * \brief Deals with normal and almost normal disc types. */ #ifndef __NDISCTYPE_H #ifndef __DOXYGEN #define __NDISCTYPE_H #endif #include #include "regina-core.h" namespace regina { /** * \weakgroup surfaces * @{ */ /** * Identifies a single normal or almost normal disc type within a * triangulation. * * A disc type is identified by a tetrahedron index (the data member * \a tetIndex), and a disc type within that tetrahedron (the data * member \a type). The latter could mean any number of things according * to the application at hand. For instance, if we are tracking quad types * then \a type might be an integer between 0 and 2 inclusive, or if we * are tracking all normal discs in standard coordinates then \a type * might be an integer between 0 and 6 inclusive. Ultimately, the * specific meaning of \a type is left to the user. * * It is however assumed that \a type will always be non-negative for * "meaningful" disc types; this is to ensure that the constant NONE * does not clash with any meaningful values. * * Note that this class tracks disc \a types, not discs themselves. * To track individual normal discs, see the NDiscSpec class instead. */ struct REGINA_API NDiscType { static const NDiscType NONE; /**< Represents a "null" disc type. Here the \a type member is negative, to distinguish it from "meaningful" disc types in which \a type is always zero or positive. */ unsigned long tetIndex; /**< The index within the triangulation of the tetrahedron containing this disc type. This must be between 0 and NTriangulation::getNumberOfTetrahedra()-1 inclusive. */ int type; /**< Identifies the disc type within the specified tetrahedron. The precise meaning of this member is left up to the user, though it must be non-negative for "meaningful" disc types. See the NDiscType class notes for details. */ /** * Creates a new disc type initialised to NONE. */ NDiscType(); /** * Creates a new disc type initialised with the given values. * * @param newTetIndex the index within the triangulation of the * tetrahedron containing this disc type. * @param newType the specific disc type within the given * tetrahedron; see the class notes for the meaning of this field. */ NDiscType(unsigned long newTetIndex, int newType); /** * Creates a copy of the given disc type. * * @param cloneMe the disc type to clone. */ NDiscType(const NDiscType& cloneMe); /** * Sets this to a copy of the given disc type. * * @param cloneMe the disc type to clone. * @return a reference to this disc type. */ NDiscType& operator = (const NDiscType& cloneMe); /** * Determines if this and the given disc type are identical. * * Note that NONE is considered identical to NONE, and that NONE will * not be equal to any "meaningful" disc type (specifically, a disc type * for which \a type is non-negative). * * @return \c true if this and the given disc type are identical, or * \c false if they are different. */ bool operator == (const NDiscType& compare) const; /** * Determines if this and the given disc type are different. * * This is the negation of the equality test; see operator == for * further details. * * @return \c true if this and the given disc type are different, or * \c false if they are identical. */ bool operator != (const NDiscType& compare) const; /** * Provides an ordering of disc types. Types are ordered first by * \a tetrahedron and then by \a type. NONE is considered less than * all "meaningful" disc types. * * @return \c true if this disc type appears before the given disc type * in the ordering, or \c false if not. */ bool operator < (const NDiscType& compare) const; }; /** * Writes the given disc type to the given output stream. * The disc type will be written as a pair (tetIndex, type). * * @param out the output stream to which to write. * @param type the disc type to write. * @return a reference to the given output stream. */ REGINA_API std::ostream& operator << (std::ostream& out, const NDiscType& type); /*@}*/ // Inline functions for NDiscType inline NDiscType::NDiscType() : tetIndex(0), type(-1) { } inline NDiscType::NDiscType(unsigned long newTetIndex, int newType) : tetIndex(newTetIndex), type(newType) { } inline NDiscType::NDiscType(const NDiscType& cloneMe) : tetIndex(cloneMe.tetIndex), type(cloneMe.type) { } inline NDiscType& NDiscType::operator = (const NDiscType& cloneMe) { tetIndex = cloneMe.tetIndex; type = cloneMe.type; return *this; } inline bool NDiscType::operator == (const NDiscType& compare) const { return (tetIndex == compare.tetIndex && type == compare.type); } inline bool NDiscType::operator != (const NDiscType& compare) const { return (tetIndex != compare.tetIndex || type != compare.type); } inline bool NDiscType::operator < (const NDiscType& compare) const { return (tetIndex < compare.tetIndex || (tetIndex == compare.tetIndex && type < compare.type)); } inline std::ostream& operator << (std::ostream& out, const NDiscType& type) { return out << '(' << type.tetIndex << ", " << type.type << ')'; } } // namespace regina #endif regina-4.96/engine/surfaces/nnormalsurface.cpp000644 000765 000024 00000042151 12377776725 021445 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "maths/nmatrixint.h" #ifndef EXCLUDE_SNAPPEA #include "snappea/nsnappeatriangulation.h" #endif #include "surfaces/nnormalsurface.h" #include "surfaces/nnormalsurfacelist.h" #include "triangulation/ntriangulation.h" #include "utilities/xmlutils.h" namespace regina { const int vertexSplit[4][4] = { { -1, 0, 1, 2 }, { 0,-1, 2, 1 }, { 1, 2,-1, 0 }, { 2, 1, 0,-1 } }; const int vertexSplitMeeting[4][4][2] = { { {-1,-1}, { 1, 2}, { 0, 2}, { 0, 1} }, { { 1, 2}, {-1,-1}, { 0, 1}, { 0, 2} }, { { 0, 2}, { 0, 1}, {-1,-1}, { 1, 2} }, { { 0, 1}, { 0, 2}, { 1, 2}, {-1,-1} } }; const int vertexSplitDefn[3][4] = { { 0, 1, 2, 3 }, { 0, 2, 1, 3 }, { 0, 3, 1, 2 } }; const int vertexSplitPartner[3][4] = { { 1, 0, 3, 2}, { 2, 3, 0, 1}, { 3, 2, 1, 0} }; const char vertexSplitString[3][6] = { "01/23", "02/13", "03/12" }; // The following three arrays cannot be made 2-D because of a g++-2.95 bug. const NPerm4 __triDiscArcs[12] = { NPerm4(0,1,2,3), NPerm4(0,2,3,1), NPerm4(0,3,1,2), NPerm4(1,0,3,2), NPerm4(1,3,2,0), NPerm4(1,2,0,3), NPerm4(2,3,0,1), NPerm4(2,0,1,3), NPerm4(2,1,3,0), NPerm4(3,2,1,0), NPerm4(3,1,0,2), NPerm4(3,0,2,1) }; const NPerm4 __quadDiscArcs[12] = { NPerm4(0,2,3,1), NPerm4(3,0,1,2), NPerm4(1,3,2,0), NPerm4(2,1,0,3), NPerm4(0,3,1,2), NPerm4(1,0,2,3), NPerm4(2,1,3,0), NPerm4(3,2,0,1), NPerm4(0,1,2,3), NPerm4(2,0,3,1), NPerm4(3,2,1,0), NPerm4(1,3,0,2) }; const NPerm4 __octDiscArcs[24] = { NPerm4(0,3,1,2), NPerm4(0,1,2,3), NPerm4(2,0,3,1), NPerm4(2,3,1,0), NPerm4(1,2,0,3), NPerm4(1,0,3,2), NPerm4(3,1,2,0), NPerm4(3,2,0,1), NPerm4(0,1,2,3), NPerm4(0,2,3,1), NPerm4(3,0,1,2), NPerm4(3,1,2,0), NPerm4(2,3,0,1), NPerm4(2,0,1,3), NPerm4(1,2,3,0), NPerm4(1,3,0,2), NPerm4(0,2,3,1), NPerm4(0,3,1,2), NPerm4(1,0,2,3), NPerm4(1,2,3,0), NPerm4(3,1,0,2), NPerm4(3,0,2,1), NPerm4(2,3,1,0), NPerm4(2,1,0,3) }; NNormalSurface* NNormalSurface::clone() const { NNormalSurface* ans = new NNormalSurface(triangulation, dynamic_cast(vector->clone())); ans->eulerChar = eulerChar; ans->orientable = orientable; ans->twoSided = twoSided; ans->connected = connected; ans->realBoundary = realBoundary; ans->compact = compact; return ans; } NNormalSurface* NNormalSurface::doubleSurface() const { NNormalSurface* ans = new NNormalSurface(triangulation, dynamic_cast(vector->clone())); (*(ans->vector)) *= 2; // Some properties can be copied straight across. ans->realBoundary = realBoundary; ans->compact = compact; if (eulerChar.known()) ans->eulerChar = eulerChar.value() * 2; // The following three properties can be used together to deduce how // they change in the clone. However, until we sit down and check // through all possible cases we'll just leave them marked unknown. // TODO: ans->orientable, ans->twoSided, ans->connected // And some other properties are best left recalculated. return ans; } NNormalSurface::NNormalSurface(const NTriangulation* triang, NNormalSurfaceVector* newVector) : vector(newVector), triangulation(triang) { } void NNormalSurface::writeTextShort(std::ostream& out) const { unsigned long nTets = triangulation->getNumberOfTetrahedra(); unsigned long tet; unsigned j; bool almostNormal = vector->allowsAlmostNormal(); for (tet=0; tet 0) out << " || "; for (j=0; j<4; j++) out << getTriangleCoord(tet, j) << ' '; out << ';'; for (j=0; j<3; j++) out << ' ' << getQuadCoord(tet, j); if (almostNormal) { out << " ;"; for (j=0; j<3; j++) out << ' ' << getOctCoord(tet, j); } } } bool NNormalSurfaceVector::hasMultipleOctDiscs(const NTriangulation* triang) const { unsigned long nTets = triang->getNumberOfTetrahedra(); int oct; NLargeInteger coord; for (unsigned long tet=0; tetgetNumberOfTetrahedra(); unsigned long tet; int type; for (tet = 0; tet < nTets; tet++) { for (type = 0; type < 4; type++) if (getTriangleCoord(tet, type, triang).isInfinite()) return false; for (type = 0; type < 3; type++) if (getQuadCoord(tet, type, triang).isInfinite()) return false; } if (allowsAlmostNormal()) for (tet = 0; tet < nTets; tet++) for (type = 0; type < 3; type++) if (getOctCoord(tet, type, triang).isInfinite()) return false; return true; } bool NNormalSurfaceVector::isSplitting(const NTriangulation* triang) const { unsigned long nTets = triang->getNumberOfTetrahedra(); unsigned long tet; int type; NLargeInteger tot; for (tet = 0; tet < nTets; tet++) { for (type = 0; type < 4; type++) if (getTriangleCoord(tet, type, triang) != 0) return false; tot = 0L; for (type = 0; type < 3; type++) tot += getQuadCoord(tet, type, triang); if (tot != 1) return false; } if (allowsAlmostNormal()) for (tet = 0; tet < nTets; tet++) for (type = 0; type < 3; type++) if (getOctCoord(tet, type, triang) != 0) return false; return true; } NLargeInteger NNormalSurfaceVector::isCentral(const NTriangulation* triang) const { unsigned long nTets = triang->getNumberOfTetrahedra(); unsigned long tet; int type; NLargeInteger tot, tetTot; for (tet = 0; tet < nTets; tet++) { tetTot = 0L; for (type = 0; type < 4; type++) tetTot += getTriangleCoord(tet, type, triang); for (type = 0; type < 3; type++) tetTot += getQuadCoord(tet, type, triang); for (type = 0; type < 3; type++) tetTot += getOctCoord(tet, type, triang); if (tetTot > 1) return NLargeInteger::zero; tot += tetTot; } return tot; } bool NNormalSurface::isEmpty() const { unsigned long nTet = triangulation->getNumberOfTetrahedra(); bool checkAlmostNormal = vector->allowsAlmostNormal(); unsigned long t; int i; for (t = 0; t < nTet; ++t) { for (i = 0; i < 4; ++i) if (getTriangleCoord(t, i) != 0) return false; for (i = 0; i < 3; ++i) if (getQuadCoord(t, i) != 0) return false; if (checkAlmostNormal) for (i = 0; i < 3; ++i) if (getOctCoord(t, i) != 0) return false; } return true; } bool NNormalSurface::sameSurface(const NNormalSurface& other) const { unsigned long nTet = triangulation->getNumberOfTetrahedra(); bool checkAlmostNormal = (vector->allowsAlmostNormal() || other.vector->allowsAlmostNormal()); unsigned long t; int i; for (t = 0; t < nTet; ++t) { for (i = 0; i < 4; ++i) if (getTriangleCoord(t, i) != other.getTriangleCoord(t, i)) return false; for (i = 0; i < 3; ++i) if (getQuadCoord(t, i) != other.getQuadCoord(t, i)) return false; if (checkAlmostNormal) for (i = 0; i < 3; ++i) if (getOctCoord(t, i) != other.getOctCoord(t, i)) return false; } return true; } bool NNormalSurface::locallyCompatible(const NNormalSurface& other) const { unsigned long nTets = triangulation->getNumberOfTetrahedra(); int type; int found; for (unsigned long tet = 0; tet < nTets; ++tet) { found = 0; for (type = 0; type < 3; ++type) if (getQuadCoord(tet, type) > 0 || other.getQuadCoord(tet, type) > 0) ++found; for (type = 0; type < 3; ++type) if (getOctCoord(tet, type) > 0 || other.getOctCoord(tet, type) > 0) ++found; if (found > 1) return false; } return true; } void NNormalSurface::calculateOctPosition() const { if (! vector->allowsAlmostNormal()) { octPosition = NDiscType::NONE; return; } unsigned long tetIndex; int type; for (tetIndex = 0; tetIndex < triangulation->getNumberOfTetrahedra(); ++tetIndex) for (type = 0; type < 3; ++type) if (getOctCoord(tetIndex, type) != 0) { octPosition = NDiscType(tetIndex, type); return; } octPosition = NDiscType::NONE; return; } void NNormalSurface::calculateEulerChar() const { unsigned long index, tot; int type; NLargeInteger ans = NLargeInteger::zero; // Add vertices. tot = triangulation->getNumberOfEdges(); for (index = 0; index < tot; index++) ans += getEdgeWeight(index); // Subtract edges. tot = triangulation->getNumberOfTriangles(); for (index = 0; index < tot; index++) for (type = 0; type < 3; type++) ans -= getTriangleArcs(index, type); // Add faces. tot = triangulation->getNumberOfTetrahedra(); for (index = 0; index < tot; index++) { for (type=0; type<4; type++) ans += getTriangleCoord(index, type); for (type=0; type<3; type++) ans += getQuadCoord(index, type); for (type=0; type<3; type++) ans += getOctCoord(index, type); } // Done! eulerChar = ans; } void NNormalSurface::calculateRealBoundary() const { if (triangulation->isClosed()) { realBoundary = false; return; } unsigned long index; unsigned long tot = triangulation->getNumberOfTetrahedra(); const NTetrahedron* tet; int type, face; for (index = 0; index < tot; index++) { tet = triangulation->getTetrahedron(index); if (tet->hasBoundary()) { // Check for disk types with boundary for (type=0; type<3; type++) { if (getQuadCoord(index, type) > 0) { realBoundary = true; return; } } for (type=0; type<3; type++) { if (getOctCoord(index, type) > 0) { realBoundary = true; return; } } for (type=0; type<4; type++) if (getTriangleCoord(index, type) > 0) { // Make sure the triangle actually hits the // boundary. for (face=0; face<4; face++) { if (face == type) continue; if (tet->adjacentTetrahedron(face) == 0) { realBoundary = true; return; } } } } } realBoundary = false; } #ifndef EXCLUDE_SNAPPEA NMatrixInt* NNormalSurface::boundaryIntersections() const { // Make sure this is really a SnapPea triangulation. const NSnapPeaTriangulation* snapPea = dynamic_cast(getTriangulation()); if (! snapPea) return 0; // Check the preconditions. if (! snapPea->isOriented()) return 0; if (vector->allowsAlmostNormal()) return 0; for (NTriangulation::VertexIterator it = snapPea->getVertices().begin(); it != snapPea->getVertices().end(); ++it) { if (! (*it)->isIdeal()) return 0; if (! (*it)->isLinkOrientable()) return 0; if ((*it)->getLinkEulerChar() != 0) return 0; } NMatrixInt* equations = snapPea->slopeEquations(); if (! equations) return 0; unsigned long cusps = equations->rows() / 2; unsigned long numTet = snapPea->getNumberOfTetrahedra(); NMatrixInt* slopes = new NMatrixInt(cusps, 2); for(unsigned int i=0; i < cusps; i++) { NLargeInteger meridian; // constructor sets this to 0 NLargeInteger longitude; // constructor sets this to 0 for(unsigned int j=0; j < numTet; j++) { meridian += equations->entry(2*i, 3*j)*getQuadCoord(j,vertexSplit[0][1]) + equations->entry(2*i, 3*j+1)*getQuadCoord(j,vertexSplit[0][2]) + equations->entry(2*i, 3*j+2)*getQuadCoord(j,vertexSplit[0][3]); longitude += equations->entry(2*i+1, 3*j)*getQuadCoord(j,vertexSplit[0][1]) + equations->entry(2*i+1, 3*j+1)*getQuadCoord(j,vertexSplit[0][2]) + equations->entry(2*i+1, 3*j+2)*getQuadCoord(j,vertexSplit[0][3]); } slopes->entry(i,0) = meridian; slopes->entry(i,1) = longitude; } delete equations; return slopes; } #endif // EXCLUDE_SNAPPEA void NNormalSurface::writeXMLData(std::ostream& out) const { using regina::xml::xmlEncodeSpecialChars; using regina::xml::xmlValueTag; // Write the opening tag including vector length. size_t vecLen = vector->size(); out << " "; // Write all non-zero entries. NLargeInteger entry; for (size_t i = 0; i < vecLen; i++) { entry = (*vector)[i]; if (entry != 0) out << ' ' << i << ' ' << entry; } // Write properties. if (eulerChar.known()) out << "\n\t" << xmlValueTag("euler", eulerChar.value()); if (orientable.known()) out << "\n\t" << xmlValueTag("orbl", orientable.value()); if (twoSided.known()) out << "\n\t" << xmlValueTag("twosided", twoSided.value()); if (connected.known()) out << "\n\t" << xmlValueTag("connected", connected.value()); if (realBoundary.known()) out << "\n\t" << xmlValueTag("realbdry", realBoundary.value()); if (compact.known()) out << "\n\t" << xmlValueTag("compact", compact.value()); // Write the closing tag. out << " \n"; } // Default implementations for oriented surfaces. Returns zero as any // coordinate system which supports orientation should override these. NLargeInteger NNormalSurfaceVector::getOrientedTriangleCoord( unsigned long, int, const NTriangulation*, bool) const { return NLargeInteger::zero; }; NLargeInteger NNormalSurfaceVector::getOrientedQuadCoord( unsigned long, int, const NTriangulation*, bool) const { return NLargeInteger::zero; }; } // namespace regina regina-4.96/engine/surfaces/nnormalsurface.h000644 000765 000024 00000244355 12377775553 021122 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/nnormalsurface.h * \brief Deals with an individual normal surface in a 3-manifold * triangulation. */ #ifndef __NNORMALSURFACE_H #ifndef __DOXYGEN #define __NNORMALSURFACE_H #endif #include "regina-config.h" // For EXCLUDE_SNAPPEA #include #include "regina-core.h" #include "shareableobject.h" #include "maths/nperm4.h" #include "maths/nray.h" #include "surfaces/ndisctype.h" #include "surfaces/normalcoords.h" #include "utilities/nbooleans.h" #include "utilities/nproperty.h" namespace regina { /** * \addtogroup surfaces Normal Surfaces * Normal surfaces in 3-manifold triangulations. * @{ */ /** * Lists which vertex splits separate which pairs of vertices. * There are three vertex splits, numbered 0,1,2. Each vertex * split separates the four tetrahedron vertices 0,1,2,3 into two pairs. * vertexSplit[i][j] is the number of the vertex split that * keeps vertices i and j together. * * It is guaranteed that vertex split \a i will keep the vertices of * edge \a i together (and will therefore also keep the vertices of edge * \a 5-i together). */ REGINA_API extern const int vertexSplit[4][4]; /** * Lists which vertex splits meet which edges. * See regina::vertexSplit for details on what a vertex split is. * vertexSplitMeeting[i][j][0,1] are the numbers of the two * vertex splits that meet the edge joining tetrahedron vertices * i and j. */ REGINA_API extern const int vertexSplitMeeting[4][4][2]; /** * Lists the vertices which each vertex split splits. * See regina::vertexSplit for details on what a vertex split is. * Vertex split number \c i splits the vertex pairs * vertexSplitDefn[i][0,1] and * vertexSplitDefn[i][2,3]. * * It is guaranteed that: * * - vertexSplitDefn[i][0] < vertexSplitDefn[i][1]; * * - vertexSplitDefn[i][2] < vertexSplitDefn[i][3]; * * - vertexSplitDefn[i][0] < vertexSplitDefn[i][2]. */ REGINA_API extern const int vertexSplitDefn[3][4]; /** * Lists the second vertex with which each vertex is paired under each * vertex split. * See regina::vertexSplit for details on what a vertex split is. * Vertex split number \c i pairs vertex \c v with * vertex vertexSplitPartner[i][v]. */ REGINA_API extern const int vertexSplitPartner[3][4]; /** * Contains strings describing which vertices each vertex split splits. * See regina::vertexSplit for details on what a vertex split is. * The string describing vertex split number \c i is * vertexSplitString[i] and is of the form 02/13, * which in this case is the vertex split that splits vertices 0,2 from * vertices 1,3. */ REGINA_API extern const char vertexSplitString[3][6]; /** * Lists in consecutive order the directed normal arcs that form the * boundary of each type of triangular normal disc. Each permutation \a p * represents an arc about vertex p[0] parallel to the directed * edge from p[1] to p[2]. * * Array triDiscArcs[i] lists the boundary arcs of the * triangular disc of type i. See NNormalSurface::getTriangleCoord() * for further details. * * Note that every permutation in this array is even. * * \ifacescpp This array is replaced by a macro * triDiscArcs(discType, arcIndex) that essentially looks up * the corresponding array. This is necessary because of a bug in gcc 2.95. */ #ifdef __DOXYGEN REGINA_API extern const NPerm4 triDiscArcs[4][3]; #else REGINA_API extern const NPerm4 __triDiscArcs[12]; #define triDiscArcs(i, j) __triDiscArcs[(3 * (i)) + (j)] #endif /** * Lists in consecutive order the directed normal arcs that form the * boundary of each type of quadrilateral normal disc. Each permutation \a p * represents an arc about vertex p[0] parallel to the directed * edge from p[1] to p[2]. * * Array quadDiscArcs[i] lists the boundary arcs of the * quadrilateral disc of type i. See NNormalSurface::getQuadCoord() * for further details. * * Note that permutation quadDiscArcs[i][j] will be even * precisely when j is even. * * \ifacescpp This array is replaced by a macro * quadDiscArcs(discType, arcIndex) that essentially looks up * the corresponding array. This is necessary because of a bug in gcc 2.95. */ #ifdef __DOXYGEN REGINA_API extern const NPerm4 quadDiscArcs[3][4]; #else REGINA_API extern const NPerm4 __quadDiscArcs[12]; #define quadDiscArcs(i, j) __quadDiscArcs[(4 * (i)) + (j)] #endif /** * Lists in consecutive order the directed normal arcs that form the * boundary of each type of octagonal normal disc. Each permutation \a p * represents an arc about vertex p[0] parallel to the directed * edge from p[1] to p[2]. * * Array octDiscArcs[i] lists the boundary arcs of the * octagonal disc of type i. See NNormalSurface::getOctCoord() * for further details. * * Note that permutation octDiscArcs[i][j] will be even * precisely when j is 0, 1, 4 or 5. * * \ifacescpp This array is replaced by a macro * octDiscArcs(discType, arcIndex) that essentially looks up * the corresponding array. This is necessary because of a bug in gcc 2.95. */ #ifdef __DOXYGEN REGINA_API extern const NPerm4 octDiscArcs[3][8]; #else REGINA_API extern const NPerm4 __octDiscArcs[24]; #define octDiscArcs(i, j) __octDiscArcs[(8 * (i)) + (j)] #endif class NEnumConstraintList; class NTriangulation; class NEdge; class NVertex; class NXMLNormalSurfaceReader; class NMatrixInt; /** * A template that stores information about a particular * normal coordinate system. Much of this information is given in the * form of compile-time constants and types. * * To iterate through cases for a given value of NormalCoords that is not * known until runtime, see the various forCoords() routines defined in * coordregistry.h. * * This NormalInfo template should only be defined for \a coordType * arguments that represent coordinate systems in which you can create and * store normal surfaces. * * At a bare minimum, each specialisation of this template must provide: * * - a typedef \a Class that represents the corresponding * NNormalSurfaceVector subclass; * - typedefs \a Standard and \a Reduced that identify NormalInfo templates * for the corresponding coordinate systems with and without triangles * (if this is not meaningful then both typedefs should just identify this * system); * - enum constants \a almostNormal, \a spun and \a oriented, which indicate * whether the coordinate system allows almost normal, spun and/or * transversely oriented surfaces; * - a static function name() that returns a C-style string giving the * human-readable name of the coordinate system. * * \ifacespython Not present. */ template struct NormalInfo; /** * Defines various constants, types and virtual functions for a subclass * of NNormalSurfaceVector. * * Every subclass of NNormalSurfaceVector \a must include * REGINA_NORMAL_SURFACE_FLAVOUR at the beginning of the class definition. * * This macro provides the class with: * * - a compile-time enum constant \a coordType, which is equal to the * corresponding NormalCoords constant; * - a typedef \a Info, which refers to the corresponding specialisation * of the NormalInfo<> template; * - declarations and implementations of the virtual functions * NNormalSurfaceVector::clone(), * NNormalSurfaceVector::allowsAlmostNormal(), * NNormalSurfaceVector::allowsSpun(), and * NNormalSurfaceVector::allowsOriented(). * * @param class_ the name of this subclass of NNormalSurfaceVector. * @param id the corresponding NNormalCoords constant. */ #define REGINA_NORMAL_SURFACE_FLAVOUR(class_, id) \ public: \ typedef NormalInfo Info; \ enum { coordType = id }; \ inline virtual NNormalSurfaceVector* clone() const { \ return new class_(*this); \ } \ inline virtual bool allowsAlmostNormal() const { \ return Info::almostNormal; \ } \ inline virtual bool allowsSpun() const { \ return Info::spun; \ } \ inline virtual bool allowsOriented() const { \ return Info::oriented; \ } /** * Stores the vector of a single normal surface in a 3-manifold. * The different subclasses of NNormalSurfaceVector use different * underlying coordinate systems for the normal solution space. * However, the various coordinate retrieval routines will return values * that are independent of the underlying coordinate system. Thus the * coordinates of the normal surface in any coordinate system can be * determined without knowledge of the specific underlying coordinate * system being used. * * Note that if a mirrored vector class is being used (see * NNormalSurfaceVectorMirrored), the vector may not change once * the first coordinate lookup routine (such as getTriangleCoord() and * the like) has been called. See * NNormalSurfaceVectorMirrored for further explanation. * * Note that non-compact surfaces (surfaces with infinitely many discs, * such as spun-normal surfaces) are allowed; in these cases, the * corresponding coordinate lookup routines should return * NLargeInteger::infinity where appropriate. * * All subclasses of NNormalSurfaceVector must have the following * properties: * * - Normal surfaces can be enumerated by intersecting the non-negative * orthant of the underlying vector space with some linear subspace; * * - Multiplying a normal surface by \a k corresponds to multiplying * the underlying vector by \a k for any non-negative integer \a k. * * When deriving classes from NNormalSurfaceVector: *
    *
  • A new value must must be added to the NormalCoords enum in * normalcoords.h to represent the new coordinate system.
  • *
  • The file coordregistry-impl.h must be updated to reflect the new * coordinate system (the file itself contains instructions * on how to do this).
  • *
  • A corresponding specialisation of NormalInfo<> must be * defined, typically in the same header as the new vector subclass.
  • *
  • The macro REGINA_NORMAL_SURFACE_FLAVOUR must be added to the * beginning of the new vector subclass. This will declare and define * various constants, typedefs and virtual functions (see the * REGINA_NORMAL_SURFACE_FLAVOUR macro documentation for details).
  • *
  • Constructors class(size_t length) and * class(const NVector& cloneMe) must be * declared and implemented; these will usually just call the * corresponding superclass constructors.
  • *
  • All abstract functions must be implemented, except for those * already provided by REGINA_NORMAL_SURFACE_FLAVOUR. * Note that coordinate functions such as getTriangleCoord() must return the * \e total number of discs of the requested type; if your new coordinate * system adorns discs with extra information (such as orientation) then * your implementation must compute the appropriate sum.
  • *
  • The orientation-specific coordinate functions * getOrientedTriangleCoord() and getOrientedQuadCoord() must be * implemented if your coordinate system supports transverse orientation. * Otherwise you can use the default implementations (which returns zero). *
  • Static public functions void * makeZeroVector(const NTriangulation*), * NMatrixInt* makeMatchingEquations(const NTriangulation*) and * makeEmbeddedConstraints(const NTriangulation*) must be * declared and implemented.
  • *
* * \todo \optlong Investigate using sparse vectors for storage. * * \ifacespython Not present. */ class REGINA_API NNormalSurfaceVector : public NRay { public: /** * Creates a new vector all of whose entries are initialised to * zero. * * @param length the number of elements in the new vector. */ NNormalSurfaceVector(size_t length); /** * Creates a new vector that is a clone of the given vector. * * @param cloneMe the vector to clone. */ NNormalSurfaceVector(const NVector& cloneMe); /** * A virtual destructor. This is required because here we introduce * virtual functions into the NRay hierarchy. */ virtual ~NNormalSurfaceVector(); /** * Creates a newly allocated clone of this vector. * The clone will be of the same subclass of NNormalSurfaceVector * as this vector. */ virtual NNormalSurfaceVector* clone() const = 0; /** * Determines if the specific underlying coordinate system * allows for almost normal surfaces, that is, allows for * octagonal discs. * * Note that this has nothing to do with whether or not this * specific surface \e contains octagonal discs. * * @return \c true if and only if almost normal surfaces are allowed. */ virtual bool allowsAlmostNormal() const = 0; /** * Determines if the specific underlying coordinate system * allows for spun-normal surfaces; that is, surfaces with * infinitely many triangles. * * Note that this has nothing to do with whether or not this * specific surface \e contains infinitely many triangles. * * @return \c true if and only if spun-normal surfaces are allowed. */ virtual bool allowsSpun() const = 0; /** * Determines if the specific underlying coordinate system * allows for transversely oriented normal surfaces. * * @return \c true if and only if transverse orientations are * supported. */ virtual bool allowsOriented() const = 0; /** * Determines if this normal surface has more than one * octagonal disc. It may be assumed that at most one * octagonal disc \e type exists in this surface. This routine will * return \c true if an octagonal type does exist and its * coordinate is greater than one. * * The default implementation for this routine simply calculates * all the octagonal coordinates and returns as soon as a * positive or negative result can be established. Subclasses * of NNormalSurfaceVector should override this if they can provide a * faster implementation. * * If a subclass does not allow for almost normal surfaces, this * routine will never be called and thus does not need to be * overwritten. * * \pre At most one octagonal disc \e type exists in this surface. * \pre This normal surface vector is using a * coordinate system that allows for almost normal surfaces. * * @param triang the triangulation in which this normal surface lives. * @return \c true if and only if there is an octagonal disc type * present and its coordinate is greater than one. */ virtual bool hasMultipleOctDiscs(const NTriangulation* triang) const; /** * Determines if the normal surface represented is compact (has * finitely many discs). * * The default implementation for this routine simply runs * through every disc type until a disc type with infinite disc * count is found or all disc types have been examined. * Subclasses of NNormalSurfaceVector should override this if * they can provide a faster implementation. * * @param triang the triangulation in which this normal surface lives. * @return \c true if and only if the normal surface represented * is compact. */ virtual bool isCompact(const NTriangulation* triang) const; /** * Determines if the normal surface represented is vertex * linking. A vertex linking surface contains only * triangles. * * The default implementation for this routine simply runs * through every non-triangular disc type ensuring that each * has no corresponding discs. * Subclasses of NNormalSurfaceVector should override this if * they can provide a faster implementation. * * @param triang the triangulation in which this normal surface lives. * @return \c true if and only if the normal surface represented * is vertex linking. */ virtual bool isVertexLinking(const NTriangulation* triang) const; /** * Determines if a rational multiple of the normal surface represented * is the link of a single vertex. * * The default implementation for this routine involves counting the * number of discs of every type. * Subclasses of NNormalSurfaceVector should override this if * they can provide a faster implementation. * * @param triang the triangulation in which this normal surface lives. * @return the vertex linked by this surface, or 0 if this * surface is not the link of a single vertex. */ virtual const NVertex* isVertexLink(const NTriangulation* triang) const; /** * Determines if a rational multiple of the normal surface represented * is the thin link of a single edge. * * If there are two different edges e1 and e2 for * which the surface could be expressed as the thin link of * either e1 or e2, the pair * (e1,e2) will be returned. * If the surface is the thin link of only one edge e, * the pair (e,0) will be returned. * If the surface is not the thin link of any edges, the pair * (0,0) will be returned. * * The default implementation for this routine involves counting the * number of discs of every type. * Subclasses of NNormalSurfaceVector should override this if * they can provide a faster implementation. * * @param triang the triangulation in which this normal surface lives. * @return a pair containing the edge(s) linked by this surface, * as described above. */ virtual std::pair isThinEdgeLink( const NTriangulation* triang) const; /** * Determines if the normal surface represented is a splitting * surface in the given triangulation. A \a splitting surface * is a compact surface containing precisely * one quad per tetrahedron and no other normal (or almost * normal) discs. * * The default implementation for this routine simply runs * through and checks the count for each disc type. * Subclasses of NNormalSurfaceVector should override this if * they can provide a faster implementation. * * @param triang the triangulation in which this normal surface lives. * @return \c true if and only if the normal surface represented * is a splitting surface. */ virtual bool isSplitting(const NTriangulation* triang) const; /** * Determines if the normal surface represented is a central * surface in the given triangulation. A \a central surface * is a compact surface containing at most one normal or almost * normal disc per tetrahedron. If the surface is central, the * number of tetrahedra it meets (i.e., the number of discs in * the surface) will be returned. * * The default implementation for this routine simply runs * through and checks the count for each disc type. * Subclasses of NNormalSurfaceVector should override this if * they can provide a faster implementation. * * @param triang the triangulation in which this normal surface lives. * @return the number of tetrahedra that the surface meets if it * is a central surface, or 0 if it is not a central surface. */ virtual NLargeInteger isCentral(const NTriangulation* triang) const; /** * Returns the number of triangular discs of the given type in * this normal surface. * See NNormalSurface::getTriangleCoord() for further details. * * @param tetIndex the index in the triangulation of the * tetrahedron in which the requested triangles reside; * this should be between 0 and * NTriangulation::getNumberOfTetrahedra()-1 inclusive. * @param vertex the vertex of the given tetrahedron around * which the requested triangles lie; this should be between 0 * and 3 inclusive. * @param triang the triangulation in which this normal surface lives. * @return the number of triangular discs of the given type. */ virtual NLargeInteger getTriangleCoord(unsigned long tetIndex, int vertex, const NTriangulation* triang) const = 0; /** * Returns the number of oriented triangular discs of the given type in * this normal surface. * See NNormalSurface::getOrientedTriangleCoord() for further details. * * The default implementation of this routine returns zero, * which is suitable for coordinate systems that do not support * transverse orientation. * * @param tetIndex the index in the triangulation of the * tetrahedron in which the requested triangles reside; * this should be between 0 and * NTriangulation::getNumberOfTetrahedra()-1 inclusive. * @param vertex the vertex of the given tetrahedron around * which the requested triangles lie; this should be between 0 * and 3 inclusive. * @param triang the triangulation in which this normal surface lives. * @param orientation the orientation of the normal discs. * @return the number of triangular discs of the given type. */ virtual NLargeInteger getOrientedTriangleCoord(unsigned long tetIndex, int vertex, const NTriangulation* triang, bool orientation) const; /** * Returns the number of quadrilateral discs of the given type * in this normal surface. * See NNormalSurface::getQuadCoord() for further details. * * @param tetIndex the index in the triangulation of the * tetrahedron in which the requested quadrilaterals reside; * this should be between 0 and * NTriangulation::getNumberOfTetrahedra()-1 inclusive. * @param quadType the number of the vertex splitting that this * quad type represents; this should be between 0 and 2 * inclusive. * @param triang the triangulation in which this normal surface lives. * @return the number of quadrilateral discs of the given type. */ virtual NLargeInteger getQuadCoord(unsigned long tetIndex, int quadType, const NTriangulation* triang) const = 0; /** * Returns the number of oriented quadrilateral discs of the given type * in this normal surface. * See NNormalSurface::getOrientedQuadCoord() for further details. * * The default implementation of this routine returns zero, * which is suitable for coordinate systems that do not support * transverse orientation. * * @param tetIndex the index in the triangulation of the * tetrahedron in which the requested quadrilaterals reside; * this should be between 0 and * NTriangulation::getNumberOfTetrahedra()-1 inclusive. * @param quadType the number of the vertex splitting that this * quad type represents; this should be between 0 and 2 * inclusive. * @param triang the triangulation in which this normal surface lives. * @param orientation the orientation of the normal discs. * @return the number of quadrilateral discs of the given type. */ virtual NLargeInteger getOrientedQuadCoord(unsigned long tetIndex, int quadType, const NTriangulation* triang, bool orientation) const; /** * Returns the number of octagonal discs of the given type * in this normal surface. * See NNormalSurface::getOctCoord() for further details. * * @param tetIndex the index in the triangulation of the * tetrahedron in which the requested octagons reside; * this should be between 0 and * NTriangulation::getNumberOfTetrahedra()-1 inclusive. * @param octType the number of the vertex splitting that this * octagon type represents; this should be between 0 and 2 * inclusive. * @param triang the triangulation in which this normal surface lives. * @return the number of octagonal discs of the given type. */ virtual NLargeInteger getOctCoord(unsigned long tetIndex, int octType, const NTriangulation* triang) const = 0; /** * Returns the number of times this normal surface crosses the * given edge. * See NNormalSurface::getEdgeWeight() for further details. * * @param edgeIndex the index in the triangulation of the edge * in which we are interested; this should be between 0 and * NTriangulation::getNumberOfEdges()-1 inclusive. * @param triang the triangulation in which this normal surface lives. * @return the number of times this normal surface crosses the * given edge. */ virtual NLargeInteger getEdgeWeight(unsigned long edgeIndex, const NTriangulation* triang) const = 0; /** * Returns the number of arcs in which this normal surface * intersects the given triangle in the given direction. * See NNormalSurface::getTriangleArcs() for further details. * * @param triIndex the index in the triangulation of the triangle * in which we are interested; this should be between 0 and * NTriangulation::getNumberOfTriangles()-1 inclusive. * @param triVertex the vertex of the triangle (0, 1 or 2) around * which the arcs of intersection that we are interested in lie; * only these arcs will be counted. * @param triang the triangulation in which this normal surface lives. * @return the number of times this normal surface intersect the * given triangle with the given arc type. */ virtual NLargeInteger getTriangleArcs(unsigned long triIndex, int triVertex, const NTriangulation* triang) const = 0; /** * A deprecated alias for getTriangleArcs(). * * This routine returns the number of arcs in which this normal * surface intersects the given triangle in the given direction. * See getTriangleArcs() for further details. * * Since this is an alias only, it is non-virtual and cannot be * overridden. Its implementation simply calls getTriangleArcs(). * * \deprecated This routine will be removed in a future version * of Regina. Please use getTriangleArcs() instead. * * @param triIndex the index in the triangulation of the triangle * in which we are interested; this should be between 0 and * NTriangulation::getNumberOfTriangles()-1 inclusive. * @param triVertex the vertex of the triangle (0, 1 or 2) around * which the arcs of intersection that we are interested in lie; * only these arcs will be counted. * @param triang the triangulation in which this normal surface lives. * @return the number of times this normal surface intersect the * given triangle with the given arc type. */ NLargeInteger getFaceArcs(unsigned long triIndex, int triVertex, const NTriangulation* triang) const; /** * Returns a new normal surface vector of the appropriate length * for the given triangulation and for the coordinate * system corresponding to this subclass of NNormalSurfaceVector. * All elements of the new vector will be initialised to zero. * * See regina::makeZeroVector() for further details. * * @param triangulation the triangulation upon which the * underlying coordinate system is based. * @return a new zero vector of the correct class and length. */ #ifdef __DOXYGEN static NNormalSurfaceVector* makeZeroVector( const NTriangulation* triangulation); #endif /** * Creates a new set of normal surface matching equations for * the given triangulation using the coordinate * system corresponding to this particular subclass of * NNormalSurfaceVector. * * See regina::makeMatchingEquations() for further details. * * @param triangulation the triangulation upon which these * matching equations will be based. * @return a newly allocated set of matching equations. */ #ifdef __DOXYGEN static NMatrixInt* makeMatchingEquations( const NTriangulation* triangulation); #endif /** * Creates a new set of validity constraints representing * the condition that normal surfaces be embedded. The * validity constraints will be expressed relative to the * coordinate system corresponding to this particular * subclass of NNormalSurfaceVector. * * @param triangulation the triangulation upon which these * validity constraints will be based. * @return a newly allocated set of constraints. */ #ifdef __DOXYGEN static NEnumConstraintList* makeEmbeddedConstraints( const NTriangulation* triangulation); #endif }; /** * Represents a single normal surface in a 3-manifold. * Once the underlying triangulation changes, this normal surface object * is no longer valid. * * The information provided by the various query methods is independent * of the underlying coordinate system being used. * See the NNormalSurfaceVector class notes for details of what to do * when introducing a new coordinate system. * * Note that non-compact surfaces (surfaces with infinitely many discs, * such as spun-normal surfaces) are allowed; in these cases, the * corresponding coordinate lookup routines will return * NLargeInteger::infinity where appropriate. * * \todo \feature Calculation of Euler characteristic and orientability * for non-compact surfaces. * \todo \featurelong Determine which faces in the solution space a * normal surface belongs to. */ class REGINA_API NNormalSurface : public ShareableObject { protected: NNormalSurfaceVector* vector; /**< Contains the coordinates of the normal surface in whichever * space is appropriate. */ const NTriangulation* triangulation; /**< The triangulation in which this normal surface resides. */ std::string name; /**< An optional name associated with this surface. */ mutable NProperty octPosition; /**< The position of the first non-zero octagonal coordinate, or NDiscType::NONE if there is no non-zero octagonal coordinate. Here NDiscType::type is an octagon type between 0 and 2 inclusive. */ mutable NProperty eulerChar; /**< The Euler characteristic of this surface. */ mutable NProperty orientable; /**< Is this surface orientable? */ mutable NProperty twoSided; /**< Is this surface two-sided? */ mutable NProperty connected; /**< Is this surface connected? */ mutable NProperty realBoundary; /**< Does this surface have real boundary (i.e. does it meet * any boundary triangles)? */ mutable NProperty compact; /**< Is this surface compact (i.e. does it only contain * finitely many discs)? */ public: /** * Creates a new normal surface inside the given triangulation * with the given coordinate vector. * * This normal surface will claim ownership of the given vector * (i.e., you should not change or delete the vector yourself * afterwards). * * \pre The given coordinate vector represents a * normal surface inside the given triangulation. * \pre The given coordinate vector cannot be the null pointer. * * \ifacespython Not present. * * @param triang the triangulation in which this normal surface resides. * @param newVector a vector containing the coordinates of the * normal surface in whichever space is appropriate. */ NNormalSurface(const NTriangulation* triang, NNormalSurfaceVector* newVector); /** * A Python-only routine that creates a new normal surface * inside the given triangulation with the given coordinate vector. * * \pre The given coordinate system is one in which Regina is * able to enumerate and store normal surfaces (not a system * like regina::NS_EDGE_WEIGHT, which is for viewing purposes only). * \pre The given coordinate vector represents a normal surface * inside the given triangulation (in particular, it satisfies the * relevant system of matching equations). This will not be checked, * and things \e will go wrong if you break it. * * \ifacescpp Not available; this routine is for Python only. * * @param triang the triangulation in which this normal surface resides. * @param coordSystem the coordinate system used by this normal surface. * @param allCoords the corresponding vector of normal coordinates, * expressed as a Python list. The list elements will be * converted internally to NLargeInteger objects. */ #ifdef __DOXYGEN NNormalSurface(const NTriangulation* triang, NormalCoords coordSystem, List allCoords); #endif /** * Destroys this normal surface. * The underlying vector of coordinates will also be * deallocated. */ virtual ~NNormalSurface(); /** * Creates a newly allocated clone of this normal surface. * * The name of the normal surface will \e not be copied to the * clone; instead the clone will have an empty name. * * @return a clone of this normal surface. */ NNormalSurface* clone() const; /** * Creates a newly allocated surface that is the double of this * surface. * * @return the double of this normal surface. */ NNormalSurface* doubleSurface() const; /** * Returns the number of triangular discs of the given type in * this normal surface. * A triangular disc type is identified by specifying a * tetrahedron and a vertex of that tetrahedron that the * triangle surrounds. * * If you are using a coordinate system that adorns discs with * additional information (such as orientation), this routine * returns the \e total number of triangles in the given * tetrahedron of the given type. * * @param tetIndex the index in the triangulation of the * tetrahedron in which the requested triangles reside; * this should be between 0 and * NTriangulation::getNumberOfTetrahedra()-1 inclusive. * @param vertex the vertex of the given tetrahedron around * which the requested triangles lie; this should be between 0 * and 3 inclusive. * @return the number of triangular discs of the given type. */ NLargeInteger getTriangleCoord(unsigned long tetIndex, int vertex) const; /** * Returns the number of oriented triangular discs of the given type * in this normal surface. * * This routine is for coordinate systems that support * transversely oriented normal surfaces; for details see * "The Thurston norm via normal surfaces", Stephan Tillmann and * Daryl Cooper, Pacific Journal of Mathematics 239 (2009), 1-15. * * An oriented triangular disc type is identified by specifying a * tetrahedron, a vertex of that tetrahedron that the * triangle surrounds, and a boolean orientation. The \c true * orientation indicates a transverse orientation pointing to the * nearby vertex, and the \c false orientation indicates a * transverse orientation pointing to the opposite face. * * If the underlying coordinate system does not support transverse * orientation, this routine will simply return zero. * * @param tetIndex the index in the triangulation of the * tetrahedron in which the requested triangles reside; * this should be between 0 and * NTriangulation::getNumberOfTetrahedra()-1 inclusive. * @param vertex the vertex of the given tetrahedron around * which the requested triangles lie; this should be between 0 * and 3 inclusive. * @param orientation the orientation of the triangle * @return the number of triangular discs of the given type. */ NLargeInteger getOrientedTriangleCoord(unsigned long tetIndex, int vertex, bool orientation) const; /** * Returns the number of quadrilateral discs of the given * type in this normal surface. * * In each tetrahedron, there are three types of quadrilaterals, * defined by how they separate the four tetrahedron vertices into * two pairs. These types are labelled 0, 1 and 2, and they * correspond exactly to the three vertex splittings described * by regina::vertexSplit. Specifically: * * - type 0 separates vertices 0,1 of the tetrahedron from vertices 2,3; * - type 1 separates vertices 0,2 of the tetrahedron from vertices 1,3; * - type 2 separates vertices 0,3 of the tetrahedron from vertices 1,2. * * A quadrilateral disc type is identified by specifying a * tetrahedron and a vertex splitting 0, 1 or 2 as described above. * * If you are using a coordinate system that adorns discs with * additional information (such as orientation), this routine * returns the \e total number of quadrilaterals in the given * tetrahedron of the given type. * * @param tetIndex the index in the triangulation of the * tetrahedron in which the requested quadrilaterals reside; * this should be between 0 and * NTriangulation::getNumberOfTetrahedra()-1 inclusive. * @param quadType the number of the vertex splitting that this * quad type represents, as described above; * this should be between 0 and 2 inclusive. * @return the number of quadrilateral discs of the given type. */ NLargeInteger getQuadCoord(unsigned long tetIndex, int quadType) const; /** * Returns the number of oriented quadrilateral discs of the given type * in this normal surface. * * This routine is for coordinate systems that support * transversely oriented normal surfaces; for details see * "The Thurston norm via normal surfaces", Stephan Tillmann and * Daryl Cooper, Pacific Journal of Mathematics 239 (2009), 1-15. * * An oriented quadrilateral disc type is identified by specifying a * tetrahedron, a vertex splitting of that tetrahedron as * described in getQuadCoord(), and a boolean orientation. * The \c true orientation indicates a transverse orientation * pointing to the edge containing vertex 0 of the tetrahedron, * and the \c false orientation indicates a transverse * orientation pointing to the opposite edge. * * If the underlying coordinate system does not support transverse * orientation, this routine will simply return zero. * * @param tetIndex the index in the triangulation of the * tetrahedron in which the requested quadrilaterals reside; * this should be between 0 and * NTriangulation::getNumberOfTetrahedra()-1 inclusive. * @param quadType the number of the vertex splitting that this * quad type represents; this should be between 0 and 2 * inclusive. * @param orientation the orientation of the quadrilateral disc * @return the number of quadrilateral discs of the given type. */ NLargeInteger getOrientedQuadCoord(unsigned long tetIndex, int quadType, bool orientation) const; /** * Returns the number of octagonal discs of the given type * in this normal surface. * * In each tetrahedron, there are three types of octagons, * defined by how they separate the four tetrahedron vertices into * two pairs. These types are labelled 0, 1 and 2, and they * correspond exactly to the three vertex splittings described * by regina::vertexSplit. Specifically: * * - type 0 separates vertices 0,1 of the tetrahedron from vertices 2,3; * - type 1 separates vertices 0,2 of the tetrahedron from vertices 1,3; * - type 2 separates vertices 0,3 of the tetrahedron from vertices 1,2. * * An octagonal disc type is identified by specifying a * tetrahedron and a vertex splitting 0, 1 or 2 as described above. * * If you are using a coordinate system that adorns discs with * additional information (such as orientation), this routine * returns the \e total number of octagons in the given * tetrahedron of the given type. * * @param tetIndex the index in the triangulation of the * tetrahedron in which the requested octagons reside; * this should be between 0 and * NTriangulation::getNumberOfTetrahedra()-1 inclusive. * @param octType the number of the vertex splitting that this * octagon type represents, as described above; * this should be between 0 and 2 inclusive. * @return the number of octagonal discs of the given type. */ NLargeInteger getOctCoord(unsigned long tetIndex, int octType) const; /** * Returns the number of times this normal surface crosses the * given edge. * * @param edgeIndex the index in the triangulation of the edge * in which we are interested; this should be between 0 and * NTriangulation::getNumberOfEdges()-1 inclusive. * @return the number of times this normal surface crosses the * given edge. */ NLargeInteger getEdgeWeight(unsigned long edgeIndex) const; /** * Returns the number of arcs in which this normal surface * intersects the given triangle in the given direction. * * @param triIndex the index in the triangulation of the triangle * in which we are interested; this should be between 0 and * NTriangulation::getNumberOfTriangles()-1 inclusive. * @param triVertex the vertex of the triangle (0, 1 or 2) around * which the arcs of intersection that we are interested in lie; * only these arcs will be counted. * @return the number of times this normal surface intersect the * given triangle with the given arc type. */ NLargeInteger getTriangleArcs(unsigned long triIndex, int triVertex) const; /** * A deprecated alias for getTriangleArcs(). * * This routine returns the number of arcs in which this normal * surface intersects the given triangle in the given direction. * See getTriangleArcs() for further details. * * \deprecated This routine will be removed in a future version * of Regina. Please use getTriangleArcs() instead. * * @param triIndex the index in the triangulation of the triangle * in which we are interested; this should be between 0 and * NTriangulation::getNumberOfTriangles()-1 inclusive. * @param triVertex the vertex of the triangle (0, 1 or 2) around * which the arcs of intersection that we are interested in lie; * only these arcs will be counted. * @return the number of times this normal surface intersect the * given triangle with the given arc type. */ NLargeInteger getFaceArcs(unsigned long triIndex, int triVertex) const; /** * Determines the first coordinate position at which this surface * has a non-zero octagonal coordinate. In other words, if this * routine returns the disc type \a t, then the octagonal * coordinate returned by getOctCoord(t.tetIndex, t.type) is non-zero. * Here NDiscType::type represents an octagon type within a * tetrahedron, and takes values between 0 and 2 inclusive. * * If this surface does not contain any octagons, this routine * returns NDiscType::NONE instead. * * This routine caches its results, which means that once it has * been called for a particular surface, subsequent calls return * the answer immediately. Moreover, if the underlying coordinate * system does not support almost normal surfaces, then even the * first call is fast (it returns NDiscType::NONE immediately). * * @return the position of the first non-zero octagonal coordinate, * or NDiscType::NONE if there is no such coordinate. */ NDiscType getOctPosition() const; /** * Returns the number of coordinates in the specific underlying * coordinate system being used. * * @return the number of coordinates. */ size_t getNumberOfCoords() const; /** * Returns the triangulation in which this normal surface * resides. * * @return the underlying triangulation. */ const NTriangulation* getTriangulation() const; /** * Returns the name associated with this normal surface. * Names are optional and need not be unique. * The default name for a surface is the empty string. * * @return the name of associated with this surface. */ const std::string& getName() const; /** * Sets the name associated with this normal surface. * Names are optional and need not be unique. * The default name for a surface is the empty string. * * @param newName the new name to associate with this surface. */ void setName(const std::string& newName); /** * The text representation will be in standard triangle-quad-oct * coordinates. Octagonal coordinates will only be written if * the surface is stored using a coordinate system that supports * almost normal surfaces. * * \ifacespython The paramater \a out does not exist, and is * taken to be standard output. */ void writeTextShort(std::ostream& out) const; /** * Writes the underlying coordinate vector to the given output * stream in text format. * No indication will be given as to which coordinate * system is being used or what each coordinate means. * No newline will be written. * * \ifacespython The paramater \a out does not exist, and is * taken to be standard output. * * @param out the output stream to which to write. */ void writeRawVector(std::ostream& out) const; /** * Writes a chunk of XML containing this normal surface and all * of its properties. This routine will be called from within * NNormalSurfaceList::writeXMLPacketData(). * * \ifacespython Not present. * * @param out the output stream to which the XML should be written. */ virtual void writeXMLData(std::ostream& out) const; /** * Determines if this normal surface is empty (has no discs * whatsoever). */ bool isEmpty() const; /** * Determines if this normal surface is compact (has * finitely many discs). * * This routine caches its results, which means that once it has * been called for a particular surface, subsequent calls return * the answer immediately. * * @return \c true if and only if this normal surface is compact. */ bool isCompact() const; /** * Returns the Euler characteristic of this surface. * * This routine caches its results, which means that once it has * been called for a particular surface, subsequent calls return * the answer immediately. * * \pre This normal surface is compact (has finitely many discs). * * @return the Euler characteristic. */ NLargeInteger getEulerChar() const; /** * A deprecated alias for getEulerChar(). * * Returns the Euler characteristic of this surface. * * This routine caches its results, which means that once it has * been called for a particular surface, subsequent calls return * the answer immediately. * * \pre This normal surface is compact (has finitely many discs). * * \deprecated This routine will be removed in a future version of * Regina. Please use the identical routine getEulerChar() instead. * * @return the Euler characteristic. */ NLargeInteger getEulerCharacteristic() const; /** * Returns whether or not this surface is orientable. * * This routine caches its results, which means that once it has * been called for a particular surface, subsequent calls return * the answer immediately. * * \pre This normal surface is compact (has finitely many discs). * * \warning This routine explicitly builds the normal discs, * and so may run out of memory if the normal coordinates * are extremely large. * * @return \c true if this surface is orientable, or \c false if * this surface is non-orientable. */ bool isOrientable() const; /** * Returns whether or not this surface is two-sided. * * This routine caches its results, which means that once it has * been called for a particular surface, subsequent calls return * the answer immediately. * * \pre This normal surface is compact (has finitely many discs). * * \warning This routine explicitly builds the normal discs, * and so may run out of memory if the normal coordinates * are extremely large. * * @return \c true if this surface is two-sided, or \c false if * this surface is one-sided. */ bool isTwoSided() const; /** * Returns whether or not this surface is connected. * * This routine caches its results, which means that once it has * been called for a particular surface, subsequent calls return * the answer immediately. * * \pre This normal surface is compact (has finitely many discs). * * \warning This routine explicitly builds the normal discs, * and so may run out of memory if the normal coordinates * are extremely large. * * @return \c true if this surface is connected, or \c false if * this surface is disconnected. */ bool isConnected() const; /** * Determines if this surface has any real boundary, that is, * whether it meets any boundary triangles of the triangulation. * * This routine caches its results, which means that once it has * been called for a particular surface, subsequent calls return * the answer immediately. * * @return \c true if and only if this surface has real boundary. */ bool hasRealBoundary() const; /** * Determines whether or not this surface is vertex linking. * A vertex linking surface contains only triangles. * * Note that the results of this routine are not cached. * Thus the results will be reevaluated every time this routine is * called. * * \todo \opt Cache results. * * @return \c true if and only if this surface is vertex linking. */ bool isVertexLinking() const; /** * Determines whether or not a rational multiple of this surface * is the link of a single vertex. * * Note that the results of this routine are not cached. * Thus the results will be reevaluated every time this routine is * called. * * \todo \opt Cache results. * * @return the vertex linked by this surface, or 0 if this * surface is not the link of a single vertex. */ virtual const NVertex* isVertexLink() const; /** * Determines whether or not a rational multiple of this surface * is the thin link of a single edge. * * If there are two different edges e1 and e2 for * which this surface could be expressed as the thin link of * either e1 or e2, the pair * (e1,e2) will be returned. * If this surface is the thin link of only one edge e, * the pair (e,0) will be returned. * If this surface is not the thin link of any edges, the pair * (0,0) will be returned. * * Note that the results of this routine are not cached. * Thus the results will be reevaluated every time this routine is * called. * * \todo \opt Cache results. * * \ifacespython This routine returns a tuple of size 2. * * @return a pair containing the edge(s) linked by this surface, * as described above. */ virtual std::pair isThinEdgeLink() const; /** * Determines whether or not this surface is a splitting surface. * A \a splitting surface is a compact surface containing * precisely one quad per tetrahedron and no other normal (or * almost normal) discs. * * Note that the results of this routine are not cached. * Thus the results will be reevaluated every time this routine is * called. * * \todo \opt Cache results. * * @return \c true if and only if this is a splitting surface. */ bool isSplitting() const; /** * Determines whether or not this surface is a central surface. * A \a central surface is a compact surface containing * at most one normal or almost normal disc per tetrahedron. * If this surface is central, the number of tetrahedra that it meets * (i.e., the number of discs in the surface) will be returned. * * Note that the results of this routine are not cached. * Thus the results will be reevaluated every time this routine is * called. * * \todo \opt Cache results. * * @return the number of tetrahedra that this surface meets if it * is a central surface, or 0 if it is not a central surface. */ NLargeInteger isCentral() const; /** * Determines whether this surface represents a compressing disc * in the underlying 3-manifold. * * Let this surface be \a D and let the underlying 3-manifold * be \a M with boundary \a B. To be a compressing disc, \a D must * be a properly embedded disc in \a M, and the boundary of \a D * must not bound a disc in \a B. * * The implementation of this routine is somewhat inefficient at * present, since it cuts along the disc, retriangulates and then * examines the resulting boundary components. * * \pre This normal surface is compact and embedded. * \pre This normal surface contains no octagonal discs. * * \todo \opt Reimplement this to avoid cutting along surfaces. * \todo \prob Check for absurdly large numbers of discs and bail * accordingly. * * \warning This routine might cut along the surface and * retriangulate, and so may run out of memory if the normal * coordinates are extremely large. * * @param knownConnected \c true if this normal surface is * already known to be connected (for instance, if it came from * an enumeration of vertex normal surfaces), or \c false if * we should not assume any such information about this surface. * @return \c true if this surface is a compressing disc, or \c false if * this surface is not a compressing disc. */ bool isCompressingDisc(bool knownConnected = false) const; /** * Determines whether this is an incompressible surface within * the surrounding 3-manifold. At present, this routine is only * implemented for surfaces embedded within \e closed and * \e irreducible 3-manifold triangulations. * * Let \a D be some disc embedded in the underlying 3-manifold, * and let \a B be the boundary of \a D. We call \a D a * compressing disc for this surface if (i) the intersection * of \a D with this surface is the boundary \a B, and * (ii) although \a B bounds a disc within the 3-manifold, it * does not bound a disc within this surface. * * We declare this surface to be \e incompressible if there are * no such compressing discs. For our purposes, spheres are never * considered incompressible (so if this surface is a sphere then * this routine will always return \c false). * * This test is designed exclusively for two-sided surfaces. * If this surface is one-sided, the incompressibility test will * be run on its two-sided double cover. * * \warning This routine may in some circumstances be extremely slow. * This is because the underlying algorithm cuts along this surface, * retriangulates (possibly using a very large number of tetrahedra), * and then searches for a normal compressing disc in each * component of the cut-open triangulation. * * \pre The underlying triangulation is valid and closed, and * represents an irreducible 3-manifold. * \pre This normal surface is compact, embedded and connected, * and contains no octagonal discs. * * @return \c true if this surface is incompressible, or \c false if * this surface is not incompressible (or if it is a sphere). */ bool isIncompressible() const; /** * Cuts the associated triangulation along this surface and * returns a newly created resulting triangulation. * The original triangulation is not changed. * * Note that, unlike crushing a surface to a point, this * operation will not change the topology of the underlying * 3-manifold beyond simply slicing along this surface. * * \warning The number of tetrahedra in the new triangulation * can be very large. * * \pre This normal surface is compact and embedded. * \pre This normal surface contains no octagonal discs. * * @return a pointer to the newly allocated resulting * triangulation. */ NTriangulation* cutAlong() const; /** * Crushes this surface to a point in the associated * triangulation and returns a newly created resulting * triangulation. The original triangulation is not changed. * * Crushing the surface will produce a number of tetrahedra, * triangular pillows and/or footballs. The pillows and * footballs will then be flattened to triangles and edges * respectively (resulting in the possible * changes mentioned below) to produce a proper triangulation. * * Note that the new triangulation will have at most the same * number of tetrahedra as the old triangulation, and will have * strictly fewer tetrahedra if this surface is not vertex * linking. * * The act of flattening pillows and footballs as described * above can lead to unintended topological side-effects, beyond * the effects of merely cutting along this surface and * identifying the new boundary surface(s) to points. * Examples of these unintended side-effects can include * connected sum decompositions, removal of 3-spheres and * small Lens spaces and so on; a full list of possible changes * is beyond the scope of this API documentation. * * \warning This routine can have unintended topological * side-effects, as described above. * \warning In exceptional cases with non-orientable * 3-manifolds, these side-effects might lead to invalid edges * (edges whose midpoints are projective plane cusps). * * \pre This normal surface is compact and embedded. * \pre This normal surface contains no octagonal discs. * * @return a pointer to the newly allocated resulting * triangulation. */ NTriangulation* crush() const; /** * Determines whether this and the given surface in fact * represent the same normal (or almost normal) surface. * * Specifically, this routine examines (or computes) the number of * normal or almost normal discs of each type, and returns \c true * if and only if these counts are the same for both surfaces. * * It does not matter what coordinate systems the two surfaces * use. In particular, it does not matter if this and the * given surface use different coordinate systems, and it * does not matter if one surface uses an almost normal * coordinate system and the other does not. * * \pre Both this and the given normal surface live within the * same 3-manifold triangulation. * * @param other the surface to be compared with this surface. * @return \c true if both surfaces represent the same normal or * almost normal surface, or \c false if not. */ bool sameSurface(const NNormalSurface& other) const; /** * Determines whether this and the given surface are locally compatible. * Local compatibility means that, within each individual tetrahedron * of the triangulation, it is possible to arrange the normal * discs of both surfaces so that none intersect. * * This is a local constraint, not a global constraint. That is, * we do not insist that we can avoid intersections within all * tetrahedra \e simultaneously. To test the global constraint, * see the (much slower) routine disjoint() instead. * * Local compatibility can be formulated in terms of normal disc types. * Two normal (or almost normal) surfaces are locally compatible if * and only if they together have at most one quadrilateral or * octagonal disc type per tetrahedron. * * Note again that this is a local constraint only. In particular, * for almost normal surfaces, it does \e not insist that there is * at most one octagonal disc type anywhere within the triangulation. * * If one of the two surfaces breaks the local compatibility * constraints on its own (for instance, it contains two different * quadrilateral disc types within the same tetrahedron), then this * routine will return \c false regardless of what the other surface * contains. * * \pre Both this and the given normal surface live within the * same 3-manifold triangulation. * * @param other the other surface to test for local compatibility with * this surface. * @return \c true if the two surfaces are locally compatible, or * \c false if they are not. */ bool locallyCompatible(const NNormalSurface& other) const; /** * Determines whether this and the given surface can be placed * within the surrounding triangulation so that they do not intersect * anywhere at all, without changing either normal isotopy class. * * This is a global constraint, and therefore gives a stronger test * than locallyCompatible(). However, this global constraint is * also much slower to test; the running time is proportional to * the total number of normal discs in both surfaces. * * Note that this routine has a number of preconditions. Most * importantly, it will only work if both this and the given * surface use the \e same coordinate system. * Running this test over two surfaces with different coordinate * systems could give unpredictable results, and might * crash the program entirely. * * \pre Both this and the given normal surface live within the * same 3-manifold triangulation. * \pre Both this and the given normal surface are stored using * the same coordinate system (i.e., the same * subclass of NNormalSurfaceVector). * \pre Both this and the given surface are compact (have * finitely many discs), embedded, non-empty and connected. * * @param other the other surface to test alongside this surface * for potential intersections. * @return \c true if both surfaces can be embedded without * intersecting anywhere, or \c false if this and the given * surface are forced to intersect at some point. */ bool disjoint(const NNormalSurface& other) const; #ifndef EXCLUDE_SNAPPEA /** * Computes the information about the boundary slopes of this surface * at each cusp of the triangulation. This is for use with spun-normal * surfaces (since for closed surfaces all boundary slopes are zero). * * This routine is only available for use with SnapPea triangulations, * since it needs to know the specific meridian and longitude on each * cusp. This information is \e only available through the SnapPea * kernel, since Regina does not use or store peripheral curves for * its own NTriangulation class. Therefore, if the underlying * triangulation (as returned by getTriangulation()) is not of the * subclass NSnapPeaTriangulation, this routine will simply return 0. * * All cusps are treated as complete. That is, any Dehn fillings * stored in the SnapPea triangulation will be ignored. * * The results are returned in a matrix with \a V rows and two * columns, where \a V is the number of vertices in the triangulation. * If row \a i of the matrix contains the integers * \a M and \a L, this indicates that at the ith cusp, * the boundary curves have algebraic intersection number \a M * with the meridian and \a L with the longitude. Equivalently, * the boundary curves pass \a L times around the meridian and * -M times around the longitude. * The rational boundary slope is therefore -L/M, and * there are gcd(L,M) boundary curves with this slope. * * The orientations of the boundary curves of a * spun-normal surface are chosen so that \e if meridian and * longitude are a positive basis as vieved from the cusp, then * as one travels along an oriented boundary curve, the * spun-normal surface spirals into the cusp to one's right and * down into the manifold to one's left. * * If the triangulation contains more than one vertex, the rows * in the resulting matrix are ordered by cusp index (as stored by * SnapPea). You can call NSnapPeaTriangulation::cuspVertex() to * map these to Regina's vertex indices if needed. * * At present, Regina can only compute boundary slopes if the * triangulation is oriented, if every vertex link in the * triangulation is a torus, and if the underlying coordinate system * is for normal surfaces (not almost normal surfaces). If these * conditions are not met, this routine will return 0. * * @author William Pettersson and Stephan Tillmann * * @return a newly allocated matrix with \a number_of_vertices * rows and two columns as described above, or 0 if the boundary * slopes cannot be computed (e.g., if the underlying triangulation * is not of type NSnapPeaTriangulation, or if it fails to meet the * preconditions outlined above). */ NMatrixInt* boundaryIntersections() const; #endif // EXCLUDE_SNAPPEA /** * Gives read-only access to the raw vector that sits beneath this * normal surface. * * Generally users should not need this function. However, it is * provided here in case the need should arise (e.g., for reasons * of efficiency). * * \warning An NNormalSurface does not know what underlying * coordinate system its raw vector uses. Unless you already know * the coordinate system in advance (i.e., you created the surface * yourself), it is best to keep to the coordinate-system-agnostic * access functions such as NNormalSurfaceVector::getTriangleCoord() * and NNormalSurfaceVector::getQuadCoord(). * * \ifacespython Not present. * * @return the underlying raw vector. */ const NNormalSurfaceVector* rawVector() const; /** * Searches for a non-vertex-linking normal 2-sphere within the * given triangulation. If a non-vertex linking normal 2-sphere * exists anywhere at all within the triangulation, then this routine * is guaranteed to find one. * * Note that the surface returned (if any) depends upon the * triangulation, and so must be destroyed before the triangulation * itself. * * \deprecated This routine will be removed in a future version * of Regina. Use NTriangulation::hasNonTrivialSphereOrDisc() * instead. * * @param tri the triangulation in which to search. * @return a newly allocated non-vertex-linking normal sphere * within the given triangulation, or 0 if no such sphere exists. */ static NNormalSurface* findNonTrivialSphere(NTriangulation* tri); /** * Searches the list of vertex octagonal almost normal surfaces for * an almost normal 2-sphere within the given triangulation. This * means that tubed almost normal 2-spheres or non-vertex octagonal * almost normal 2-spheres will not be found. * * This search can be done either in standard almost normal * coordinates (with triangles, quadrilaterals and octagons), or * in quadrilateral-octagon coordinates. This choice of coordinate * system affects how we define "vertex". The default is to use * standard coordinates (where the set of vertex surfaces is larger). * * For "sufficiently nice" triangulations, if this routine fails * to find an almost normal 2-sphere then we can be certain that * the triangulation contains no almost normal 2-spheres at all. * In particular, this is true for closed orientable one-vertex * 0-efficient triangulations. For a proof in standard coordinates, * see "0-efficient triangulations of 3-manifolds", William Jaco * and J. Hyam Rubinstein, J. Differential Geom. 65 (2003), * no. 1, 61--168. For a proof in quadrilateral-octagon coordinates, * see "Quadrilateral-octagon coordinates for almost normal surfaces", * Benjamin A. Burton, Experiment. Math. 19 (2010), 285-315. * * Note that the surface that this routine returns (if any) depends * upon the triangulation, and so this surface must be destroyed * before the triangulation is destroyed. * * \warning Currently this routine can be quite slow since it * performs a full enumeration of vertex almost normal surfaces. * * \deprecated This routine will be removed in a future version * of Regina. Use NTriangulation::hasOctagonalAlmostNormalSphere() * instead, which offers significant optimisations over this routine. * * @param tri the triangulation in which to search. * @param quadOct \c true if we should search for vertex * surfaces in quadrilateral-octagon coordinates, or \c false * (the default) if we should search for surfaces in standard * almost normal coordinates. * @return a newly allocated vertex octagonal almost normal sphere * within the given triangulation, or 0 if no such sphere exists. */ static NNormalSurface* findVtxOctAlmostNormalSphere( NTriangulation* tri, bool quadOct = false); protected: /** * Calculates the position of the first non-zero octagon * coordinate and stores it as a property. */ void calculateOctPosition() const; /** * Calculates the Euler characteristic of this surface and * stores it as a property. * * \pre This normal surface is compact (has finitely many discs). */ void calculateEulerChar() const; /** * Calculates whether this surface is orientable and/or * two-sided and stores the results as properties. * * \pre This normal surface is compact (has finitely many discs). */ void calculateOrientable() const; /** * Calculates whether this surface has any real boundary and * stores the result as a property. */ void calculateRealBoundary() const; friend class regina::NXMLNormalSurfaceReader; }; /*@}*/ // Inline functions for NNormalSurfaceVector inline NNormalSurfaceVector::NNormalSurfaceVector(size_t length) : NRay(length) { } inline NNormalSurfaceVector::NNormalSurfaceVector( const NVector& cloneMe) : NRay(cloneMe) { } inline NNormalSurfaceVector::~NNormalSurfaceVector() { } inline NLargeInteger NNormalSurfaceVector::getFaceArcs(unsigned long triIndex, int triVertex, const NTriangulation* triang) const { return getTriangleArcs(triIndex, triVertex, triang); } // Inline functions for NNormalSurface inline NNormalSurface::~NNormalSurface() { delete vector; } inline NLargeInteger NNormalSurface::getTriangleCoord(unsigned long tetIndex, int vertex) const { return vector->getTriangleCoord(tetIndex, vertex, triangulation); } inline NLargeInteger NNormalSurface::getOrientedTriangleCoord( unsigned long tetIndex, int vertex, bool oriented) const { return vector->getOrientedTriangleCoord(tetIndex, vertex, triangulation, oriented); } inline NLargeInteger NNormalSurface::getQuadCoord(unsigned long tetIndex, int quadType) const { return vector->getQuadCoord(tetIndex, quadType, triangulation); } inline NLargeInteger NNormalSurface::getOrientedQuadCoord( unsigned long tetIndex, int quadType, bool oriented) const { return vector->getOrientedQuadCoord(tetIndex, quadType, triangulation, oriented); } inline NLargeInteger NNormalSurface::getOctCoord(unsigned long tetIndex, int octType) const { return vector->getOctCoord(tetIndex, octType, triangulation); } inline NLargeInteger NNormalSurface::getEdgeWeight(unsigned long edgeIndex) const { return vector->getEdgeWeight(edgeIndex, triangulation); } inline NLargeInteger NNormalSurface::getTriangleArcs(unsigned long triIndex, int triVertex) const { return vector->getTriangleArcs(triIndex, triVertex, triangulation); } inline NLargeInteger NNormalSurface::getFaceArcs(unsigned long triIndex, int triVertex) const { return vector->getTriangleArcs(triIndex, triVertex, triangulation); } inline NDiscType NNormalSurface::getOctPosition() const { if (! octPosition.known()) calculateOctPosition(); return octPosition.value(); } inline size_t NNormalSurface::getNumberOfCoords() const { return vector->size(); } inline const NTriangulation* NNormalSurface::getTriangulation() const { return triangulation; } inline const std::string& NNormalSurface::getName() const { return name; } inline void NNormalSurface::setName(const std::string& newName) { name = newName; } inline void NNormalSurface::writeRawVector(std::ostream& out) const { out << *vector; } inline bool NNormalSurface::isCompact() const { if (! compact.known()) compact = vector->isCompact(triangulation); return compact.value(); } inline NLargeInteger NNormalSurface::getEulerChar() const { if (! eulerChar.known()) calculateEulerChar(); return eulerChar.value(); } inline NLargeInteger NNormalSurface::getEulerCharacteristic() const { return getEulerChar(); } inline bool NNormalSurface::isOrientable() const { if (! orientable.known()) calculateOrientable(); return orientable.value(); } inline bool NNormalSurface::isTwoSided() const { if (! twoSided.known()) calculateOrientable(); return twoSided.value(); } inline bool NNormalSurface::isConnected() const { if (! connected.known()) calculateOrientable(); return connected.value(); } inline bool NNormalSurface::hasRealBoundary() const { if (! realBoundary.known()) calculateRealBoundary(); return realBoundary.value(); } inline bool NNormalSurface::isVertexLinking() const { return vector->isVertexLinking(triangulation); } inline const NVertex* NNormalSurface::isVertexLink() const { return vector->isVertexLink(triangulation); } inline std::pair NNormalSurface::isThinEdgeLink() const { return vector->isThinEdgeLink(triangulation); } inline bool NNormalSurface::isSplitting() const { return vector->isSplitting(triangulation); } inline NLargeInteger NNormalSurface::isCentral() const { return vector->isCentral(triangulation); } inline const NNormalSurfaceVector* NNormalSurface::rawVector() const { return vector; } } // namespace regina #endif regina-4.96/engine/surfaces/nnormalsurfacelist.cpp000644 000765 000024 00000022225 12377776726 022342 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "surfaces/coordregistry.h" #include "surfaces/nnormalsurfacelist.h" #include "triangulation/ntriangulation.h" #include "utilities/xmlutils.h" namespace regina { namespace { // Since legacy coordinate systems don't appear in the coordinate system // registry, give them a consistent name here. const char* AN_LEGACY_NAME = "Legacy standard almost normal (pruned tri-quad-oct)"; } const NormalCoords NNormalSurfaceList::STANDARD = NS_STANDARD;; const NormalCoords NNormalSurfaceList::QUAD = NS_QUAD; const NormalCoords NNormalSurfaceList::AN_LEGACY = NS_AN_LEGACY; const NormalCoords NNormalSurfaceList::AN_QUAD_OCT = NS_AN_QUAD_OCT; const NormalCoords NNormalSurfaceList::AN_STANDARD = NS_AN_STANDARD; const NormalCoords NNormalSurfaceList::EDGE_WEIGHT = NS_EDGE_WEIGHT; const NormalCoords NNormalSurfaceList::FACE_ARCS = NS_TRIANGLE_ARCS; const NormalCoords NNormalSurfaceList::ORIENTED = NS_ORIENTED; const NormalCoords NNormalSurfaceList::ORIENTED_QUAD = NS_ORIENTED_QUAD; void NNormalSurfaceList::writeAllSurfaces(std::ostream& out) const { unsigned long n = getNumberOfSurfaces(); out << "Number of surfaces is " << n << '\n'; for (unsigned long i = 0; i < n; i++) { getSurface(i)->writeTextShort(out); out << '\n'; } } namespace { struct ZeroVector : public Returns { const NTriangulation* tri_; ZeroVector(const NTriangulation* tri) : tri_(tri) {} template inline NNormalSurfaceVector* operator() (Coords) { return Coords::Class::makeZeroVector(tri_); } }; } NNormalSurfaceVector* makeZeroVector(const NTriangulation* triangulation, NormalCoords coords) { return forCoords(coords, ZeroVector(triangulation), 0); } namespace { struct MatchingEquations : public Returns { const NTriangulation* tri_; MatchingEquations(const NTriangulation* tri) : tri_(tri) {} template inline NMatrixInt* operator() (Coords) { return Coords::Class::makeMatchingEquations(tri_); } }; } NMatrixInt* makeMatchingEquations(const NTriangulation* triangulation, NormalCoords coords) { return forCoords(coords, MatchingEquations(triangulation), 0); } namespace { struct EmbeddedConstraints : public Returns { const NTriangulation* tri_; EmbeddedConstraints(const NTriangulation* tri) : tri_(tri) {} template inline NEnumConstraintList* operator() (Coords) { return Coords::Class::makeEmbeddedConstraints(tri_); } }; } NEnumConstraintList* makeEmbeddedConstraints( const NTriangulation* triangulation, NormalCoords coords) { return forCoords(coords, EmbeddedConstraints(triangulation), 0); } NTriangulation* NNormalSurfaceList::getTriangulation() const { return dynamic_cast(getTreeParent()); } namespace { struct AlmostNormalFunction : public Returns { template inline bool operator() (Coords f) { return f.almostNormal; } }; } bool NNormalSurfaceList::allowsAlmostNormal() const { if (coords_ == NS_AN_LEGACY) return true; else return forCoords(coords_, AlmostNormalFunction(), false); } namespace { struct SpunFunction : public Returns { template inline bool operator() (Coords f) { return f.spun; } }; } bool NNormalSurfaceList::allowsSpun() const { // Both the default and the NS_AN_LEGACY cases should return false. return forCoords(coords_, SpunFunction(), false); } namespace { struct OrientedFunction : public Returns { template inline bool operator() (Coords f) { return f.oriented; } }; } bool NNormalSurfaceList::allowsOriented() const { // Both the default and the NS_AN_LEGACY cases should return false. return forCoords(coords_, OrientedFunction(), false); } namespace { struct NameFunction : public Returns { template inline const char* operator() (Coords f) { return f.name(); } }; } void NNormalSurfaceList::writeTextShort(std::ostream& out) const { out << surfaces.size(); if (which_.has(regina::NS_EMBEDDED_ONLY)) out << " embedded,"; else if (which_.has(regina::NS_IMMERSED_SINGULAR)) out << " embedded / immersed / singular,"; else out << " unknown,"; if (which_.has(regina::NS_VERTEX)) out << " vertex"; else if (which_.has(regina::NS_FUNDAMENTAL)) out << " fundamental"; else if (which_.has(regina::NS_CUSTOM)) out << " custom"; else if (which_.has(regina::NS_LEGACY)) out << " legacy"; else out << " unknown"; out << " surface"; if (surfaces.size() != 1) out << 's'; out << " ("; if (coords_ == NS_AN_LEGACY) out << AN_LEGACY_NAME; else out << forCoords(coords_, NameFunction(), "Unknown"); out << ')'; } void NNormalSurfaceList::writeTextLong(std::ostream& out) const { if (which_.has(regina::NS_EMBEDDED_ONLY)) out << "Embedded,"; else if (which_.has(regina::NS_IMMERSED_SINGULAR)) out << "Embedded / immersed / singular,"; else out << "Unknown,"; if (which_.has(regina::NS_VERTEX)) out << " vertex"; else if (which_.has(regina::NS_FUNDAMENTAL)) out << " fundamental"; else if (which_.has(regina::NS_CUSTOM)) out << " custom"; else if (which_.has(regina::NS_LEGACY)) out << " legacy"; else out << " unknown"; out << " surfaces\n"; out << "Coordinates: "; if (coords_ == NS_AN_LEGACY) out << AN_LEGACY_NAME << '\n'; else out << forCoords(coords_, NameFunction(), "Unknown") << '\n'; writeAllSurfaces(out); } void NNormalSurfaceList::writeXMLPacketData(std::ostream& out) const { // Write the surface list parameters. out << " \n"; // Write the individual surfaces. std::vector::const_iterator it; for (it = surfaces.begin(); it != surfaces.end(); it++) (*it)->writeXMLData(out); } NPacket* NNormalSurfaceList::internalClonePacket(NPacket* /* parent */) const { NNormalSurfaceList* ans = new NNormalSurfaceList( coords_, which_, algorithm_); transform(surfaces.begin(), surfaces.end(), back_inserter(ans->surfaces), FuncNewClonePtr()); return ans; } } // namespace regina regina-4.96/engine/surfaces/nnormalsurfacelist.h000644 000765 000024 00000261645 12377775555 022021 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/nnormalsurfacelist.h * \brief Contains a packet representing a collection of normal * surfaces in a 3-manifold. */ #ifndef __NNORMALSURFACELIST_H #ifndef __DOXYGEN #define __NNORMALSURFACELIST_H #endif #include #include #include #include "regina-core.h" #include "packet/npacket.h" #include "surfaces/nnormalsurface.h" #include "surfaces/normalflags.h" #include "surfaces/normalcoords.h" #include "utilities/memutils.h" #include "utilities/nthread.h" namespace regina { class NTriangulation; class NMatrixInt; class NNormalSurfaceList; class NProgressTracker; class NXMLPacketReader; class NXMLNormalSurfaceListReader; /** * \weakgroup surfaces * @{ */ /** * Used to describe a field, or a set of fields, that can be exported * alongside a normal surface list. This enumeration type is used with * export routines such as NNormalSurfaceList::saveCSVStandard() or * NNormalSurfaceList::saveCSVEdgeWeight(). * * This type describes fields in addition to normal coordinates, not the * normal coordinates themselves (which are always exported). Each field * describes some property of a single normal surface, and corresponds to a * single column in a table of normal surfaces. * * This type should be treated as a bitmask: you can describe a set of fields * by combining the values for individual fields using bitwise \e or. * * The list of available fields may grow with future releases of Regina. */ enum SurfaceExportFields { surfaceExportName = 0x0001, /**< Represents the user-assigned surface name. */ surfaceExportEuler = 0x0002, /**< Represents the calculated Euler characteristic of a surface. This will be an integer, and will be left empty if the Euler characteristic cannot be computed. */ surfaceExportOrient = 0x0004, /**< Represents the calculated property of whether a surface is orientable. This will be the string \c TRUE or \c FALSE, or will be left empty if the orientability cannot be computed. */ surfaceExportSides = 0x0008, /**< Represents the calculated property of whether a surface is one-sided or two-sided. This will be the integer 1 or 2, or will be left empty if the "sidedness" cannot be computed. */ surfaceExportBdry = 0x0010, /**< Represents the calculated property of whether a surface is bounded. In most cases, this will be one of the strings "closed", "real bdry" or "infinite" (where "infinite" indicates a surface with infinitely many discs). For spun-normal surfaces in certain ideal triangulations, this string will be followed by the boundary slopes of the surface at the cusps: these written as a list of pairs (\a p, \a q), one for each cusp, indicating that the boundary curves of the surface run \a p times around the meridian and \a q times around the longitude. See NNormalSurface::boundaryIntersections() for further information on interpreting these values. */ surfaceExportLink = 0x0020, /**< Represents whether a surface is a single vertex link or a thin edge link. See NNormalSurface::isVertexLink() and NNormalSurface::isThinEdgeLink() for details. This will be written as a human-readable string. */ surfaceExportType = 0x0040, /**< Represents any additional high-level properties of a surface, such as whether it is a splitting surface or a central surface. This will be written as a human-readable string. This field is somewhat arbitrary, and the precise properties it describes are subject to change in future releases of Regina. */ surfaceExportNone = 0, /**< Indicates that no additional fields should be exported. */ surfaceExportAllButName = 0x007e, /**< Indicates that all available fields should be exported, except for the user-assigned surface name. Since the list of available fields may grow with future releases, the numerical value of this constant may change as a result. */ surfaceExportAll = 0x007f /**< Indicates that all available fields should be exported, including the user-assigned surface name. Since the list of available fields may grow with future releases, the numerical value of this constant may change as a result. */ }; /** * Stores information about the normal surface list packet. * See the general PacketInfo template notes for further details. * * \ifacespython Not present. */ template <> struct PacketInfo { typedef NNormalSurfaceList Class; inline static const char* name() { return "Normal Surface List"; } }; /** * A packet representing a collection of normal surfaces in a 3-manifold. * Such a packet must always be a child packet of the triangulation from * which the surfaces were obtained. If this triangulation changes, the * information contained in this packet will become invalid. * * See the NNormalSurfaceVector class notes for details of what to do * when introducing a new coordinate system. * * Normal surface lists should be created using the routine enumerate(), * which is new as of Regina 3.95. * * \todo \feature Allow custom matching equations. * \todo \feature Allow enumeration with some coordinates explicitly set * to zero. * \todo \feature Allow generating only closed surfaces. * \todo \feature Generate facets of the solution space representing * embedded surfaces. */ class REGINA_API NNormalSurfaceList : public NPacket { REGINA_PACKET(NNormalSurfaceList, PACKET_NORMALSURFACELIST) public: /** * Represents standard triangle-quadrilateral coordinates for * normal surfaces. * * \deprecated Instead of this class constant, you should use * the NormalCoords enum value NS_STANDARD directly. */ static const NormalCoords STANDARD; /** * Represents standard triangle-quadrilateral-octagon coordinates * for octagonal almost normal surfaces. * * \deprecated Instead of this class constant, you should use * the NormalCoords enum value NS_AN_STANDARD directly. */ static const NormalCoords AN_STANDARD; /** * Represents quadrilateral coordinates for normal surfaces. * For details, see "Normal surface Q-theory", Jeffrey L. Tollefson, * Pacific J. Math. 183 (1998), no. 2, 359--374. * * \deprecated Instead of this class constant, you should use * the NormalCoords enum value NS_QUAD directly. */ static const NormalCoords QUAD; /** * Represents quadrilateral-octagon coordinates for octagonal * almost normal surfaces. For details, see * "Quadrilateral-octagon coordinates for almost normal surfaces", * Benjamin A. Burton, Experiment. Math. 19 (2010), 285-315. * * \deprecated Instead of this class constant, you should use * the NormalCoords enum value NS_AN_QUAD_OCT directly. */ static const NormalCoords AN_QUAD_OCT; /** * Represents edge weight coordinates for normal surfaces. * This coordinate system is for representation only; surface * vectors and lists cannot be created in this coordinate system. * * \deprecated Instead of this class constant, you should use * the NormalCoords enum value NS_EDGE_WEIGHT directly. */ static const NormalCoords EDGE_WEIGHT; /** * Represents triangle arc coordinates for normal surfaces. * This coordinate system is for representation only; surface * vectors and lists cannot be created in this coordinate system. * * \deprecated Instead of this class constant, you should use * the NormalCoords enum value NS_TRIANGLE_ARCS. */ static const NormalCoords FACE_ARCS; /** * Indicates that a list of almost normal surfaces was created * using Regina 4.5.1 or earlier, where surfaces with more than * one octagon of the same type were stripped out of the final * solution set. As of Regina 4.6 such surfaces are now * included in the solution set, since we need them if we * wish to enumerate \e all almost normal surfaces (not just * the \e vertex almost normal surfaces). * * This coordinate system is only used with legacy data files; new * vectors and lists cannot be created in this coordinate system. * The underlying coordinates are identical to those of AN_STANDARD. * * \deprecated Instead of this class constant, you should use * the NormalCoords enum value NS_AN_LEGACY directly. */ static const NormalCoords AN_LEGACY; /** * Represents standard triangle-quadrilateral coordinates for * transversely oriented normal surfaces. * * \deprecated Instead of this class constant, you should use * the NormalCoords enum value NS_ORIENTED directly. */ static const NormalCoords ORIENTED; /** * Represents quadrilateral coordinates for transversely oriented * normal surfaces. * * \deprecated Instead of this class constant, you should use * the NormalCoords enum value NS_ORIENTED_QUAD directly. */ static const NormalCoords ORIENTED_QUAD; class VectorIterator; protected: std::vector surfaces; /**< Contains the normal surfaces stored in this packet. */ NormalCoords coords_; /**< Stores which coordinate system is being used by the normal surfaces in this packet. */ NormalList which_; /**< Indicates which normal surfaces these represent within the underlying triangulation. */ NormalAlg algorithm_; /**< Stores the details of the enumeration algorithm that was used to generate this list. This might not be the same as the \a algorithmHints flag passed to the corresponding enumeration routine (e.g., if invalid or inappropriate flags were passed). */ public: /** * Destroys this list and all the surfaces within. */ virtual ~NNormalSurfaceList(); /** * A unified routine for enumerating various classes of normal * surfaces within a given triangulation. * * The NormalCoords argument allows you to specify an underlying * coordinate system (e.g., standard coordinates, * quadrilateral coordinates or almost normal coordinates). * * The NormalList argument is a combination of flags that * allows you to specify exactly which normal surfaces you require. * This includes (i) whether you want all vertex surfaces * or all fundamental surfaces, which defaults to NS_VERTEX * if you specify neither or both; and (ii) whether you want only * properly embedded surfaces or you also wish to include * immersed and/or singular surfaces, which defaults to * NS_EMBEDDED_ONLY if you specify neither or both. * * The NormalAlg argument is a combination of flags that allows * you to control the underlying enumeration algorithm. These * flags are treated as hints only: if your selection of * algorithm is invalid, unavailable or unsupported then Regina * will choose something more appropriate. Unless you have * some specialised need, the default NS_ALG_DEFAULT (which * makes no hints at all) will allow Regina to choose what it * thinks will be the most efficient method. * * The enumerated surfaces will be stored in a new normal * surface list, and their representations will be scaled down * to use the smallest possible integer coordinates. * This normal surface list will be inserted into the packet tree as * the last child of the given triangulation. This triangulation * \b must remain the parent of this normal surface list, and must not * change while this normal surface list remains in existence. * * If a progress tracker is passed, the normal surface * enumeration will take place in a new thread and this routine * will return immediately. If the user cancels the operation * from another thread, then the normal surface list will \e not * be inserted into the packet tree (but the caller of this * routine will still need to delete it). Regarding progress tracking, * this routine will declare and work through a series of stages * whose combined weights sum to 1; typically this means that the * given tracker must not have been used before. * * If no progress tracker is passed, the enumeration will run * in the current thread and this routine will return only when * the enumeration is complete. Note that this enumeration can * be extremely slow for larger triangulations. * * @param owner the triangulation upon which this list of normal * surfaces will be based. * @param coords the coordinate system to be used. * @param which indicates which normal surfaces should be enumerated. * @param algHints passes requests to Regina for which specific * enumeration algorithm should be used. * @param tracker a progress tracker through which progress will * be reported, or 0 if no progress reporting is required. * @return the newly created normal surface list. Note that if * a progress tracker is passed then this list may not be completely * filled when this routine returns. If a progress tracker is * passed and a new thread could not be started, this routine * returns 0 (and no normal surface list is created). */ static NNormalSurfaceList* enumerate(NTriangulation* owner, NormalCoords coords, NormalList which = NS_LIST_DEFAULT, NormalAlg algHints = NS_ALG_DEFAULT, NProgressTracker* tracker = 0); /** * Deprecated method for enumerating all vertex normal surfaces * using the given coordinate system. * * Users should now call enumerate(NTriangulation*, NormalCoords, * NormalList, NormalAlg, NProgressTracker*) instead. * See the documentation for that routine for further details, * including all arguments, returns values, preconditions and * postconditions. * * \deprecated The correct way to access this procedure is to call * enumerate(owner, coords, NS_EMBEDDED_ONLY, * NS_ALG_DEFAULT, tracker) if \a embeddedOnly is \c true, or * enumerate(owner, coords, NS_IMMERSED_SINGULAR, * NS_ALG_DEFAULT, tracker) if \a embeddedOnly is \c false. */ static NNormalSurfaceList* enumerate(NTriangulation* owner, NormalCoords coords, bool embeddedOnly, NProgressTracker* tracker = 0); /** * Deprecated method that uses a slow-but-direct procedure to * enumerate all embedded vertex normal surfaces in standard * coordinates, without using the faster procedure that works * via quadrilateral coordinates. * * Users can still access this slower procedure if they need to; * however, they should do this via enumerate(NTriangulation*, * NormalCoords, NormalList, NormalAlg, NProgressTracker*) instead. * See the documentation for that routine for further details. * * \deprecated The correct way to access this procedure is to call * enumerate(owner, NS_STANDARD, NS_LIST_DEFAULT, * NS_VERTEX_STD_DIRECT). * * \warning This routine is slow, and users will not want to * call it unless they have some specialised need. * * @param owner the triangulation upon which this list of * surfaces will be based. * @return the newly created normal surface list. */ static NNormalSurfaceList* enumerateStandardDirect( NTriangulation* owner); /** * Deprecated method that uses a slow-but-direct procedure to * enumerate all embedded vertex almost normal surfaces in standard * almost normal coordinates, without using the faster procedure * that works via quadrilateral-octagon coordinates. * * Users can still access this slower procedure if they need to; * however, they should do this via enumerate(NTriangulation*, * NormalCoords, NormalList, NormalAlg, NProgressTracker*) instead. * See the documentation for that routine for further details. * * \deprecated The correct way to access this procedure is to call * enumerate(owner, NS_AN_STANDARD, NS_LIST_DEFAULT, * NS_VERTEX_STD_DIRECT). * * \warning This routine is slow, and users will not want to * call it unless they have some specialised need. * * @param owner the triangulation upon which this list of * surfaces will be based. * @return the newly created normal surface list. */ static NNormalSurfaceList* enumerateStandardANDirect( NTriangulation* owner); /** * Deprecated method that enumerates all fundamental normal surfaces * in the given triangulation using the primal Hilbert basis algorithm. * For details of the algorithm, see B. A. Burton, "Enumerating * fundamental normal surfaces: Algorithms, experiments and invariants", * ALENEX 2014: Proceedings of the Meeting on Algorithm * Engineering & Experiments, SIAM, 2014, pp. 112-124. * * Users can still access this procedure if they need to; * however, they should do this via enumerate(NTriangulation*, * NormalCoords, NormalList, NormalAlg, NProgressTracker*) instead. * See the documentation for that routine for further details. * * \warning As of Regina 4.94, the \a vtxSurfaces argument is ignored. * Future versions of Regina will automatically search existing surface * lists in the packet tree for a ready-made list of vertex normal * surfaces that can be used. * * \deprecated The correct way to access this procedure is to call * enumerate(owner, coords, NS_FUNDAMENTAL | NS_EMBEDDED_ONLY, * NS_HILBERT_PRIMAL, tracker) if \a embeddedOnly is \c true, or * enumerate(owner, coords, NS_FUNDAMENTAL | NS_IMMERSED_SINGULAR, * NS_HILBERT_PRIMAL, tracker) if \a embeddedOnly is \c false. * * @param owner the triangulation upon which this list of normal * surfaces will be based. * @param coords the coordinate system to be used. * @param embeddedOnly \c true if only embedded normal surfaces * are to be produced, or \c false if immersed and singular * normal surfaces are also to be produced; this defaults to \c true. * @param vtxSurfaces the set of all \e vertex normal surfaces * as enumerated under the same coordinate system and * constraints as given here; this may be 0 if unknown. * @param tracker a progress tracker through which progress will * be reported, or 0 if no progress reporting is required. * @return the newly created normal surface list. Note that if * a progress tracker is passed then this list may not be completely * filled when this routine returns. If a progress tracker is * passed and a new thread could not be started, this routine * returns 0 (and no normal surface list is created). */ static NNormalSurfaceList* enumerateFundPrimal( NTriangulation* owner, NormalCoords coords, bool embeddedOnly = true, NNormalSurfaceList* vtxSurfaces = 0, NProgressTracker* tracker = 0); /** * Deprecated method that enumerates all fundamental normal surfaces * in the given triangulation using the dual Hilbert basis algorithm. * For details of the algorithm, see B. A. Burton, "Enumerating * fundamental normal surfaces: Algorithms, experiments and invariants", * ALENEX 2014: Proceedings of the Meeting on Algorithm * Engineering & Experiments, SIAM, 2014, pp. 112-124. * * Users can still access this procedure if they need to; * however, they should do this via enumerate(NTriangulation*, * NormalCoords, NormalList, NormalAlg, NProgressTracker*) instead. * See the documentation for that routine for further details. * * \deprecated The correct way to access this procedure is to call * enumerate(owner, coords, NS_FUNDAMENTAL | NS_EMBEDDED_ONLY, * NS_HILBERT_DUAL, tracker) if \a embeddedOnly is \c true, or * enumerate(owner, coords, NS_FUNDAMENTAL | NS_IMMERSED_SINGULAR, * NS_HILBERT_DUAL, tracker) if \a embeddedOnly is \c false. * * @param owner the triangulation upon which this list of normal * surfaces will be based. * @param coords the coordinate system to be used. * @param embeddedOnly \c true if only embedded normal surfaces * are to be produced, or \c false if immersed and singular * normal surfaces are also to be produced; this defaults to \c true. * @param tracker a progress tracker through which progress will * be reported, or 0 if no progress reporting is required. * @return the newly created normal surface list. Note that if * a progress tracker is passed then this list may not be completely * filled when this routine returns. If a progress tracker is * passed and a new thread could not be started, this routine * returns 0 (and no normal surface list is created). */ static NNormalSurfaceList* enumerateFundDual( NTriangulation* owner, NormalCoords coords, bool embeddedOnly = true, NProgressTracker* tracker = 0); /** * Deprecated method that uses an extremely slow procedure to enumerate * all embedded fundamental surfaces in the given triangulation, * by running Normaliz over the full (and typically very large) * solution cone, and only enforcing embedded constraints (such as * the quadrilateral constraints) afterwards. * * Users can still access this slower procedure if they need to; * however, they should do this via enumerate(NTriangulation*, * NormalCoords, NormalList, NormalAlg, NProgressTracker*) instead. * See the documentation for that routine for further details. * * \deprecated The correct way to access this procedure is to call * enumerate(owner, coords, NS_FUNDAMENTAL | NS_EMBEDDED_ONLY, * NS_HILBERT_FULLCONE) if \a embeddedOnly is \c true, or * enumerate(owner, coords, NS_FUNDAMENTAL | NS_IMMERSED_SINGULAR, * NS_HILBERT_FULLCONE) if \a embeddedOnly is \c false. * * \warning This routine is extremely slow, and users will not want to * call it unless they have some specialised need. * * @param owner the triangulation upon which this list of normal * surfaces will be based. * @param coords the coordinate system to be used. * @param embeddedOnly \c true if only embedded normal surfaces * are to be produced, or \c false if immersed and singular * normal surfaces are also to be produced; this defaults to \c true. * @return the newly created normal surface list. */ static NNormalSurfaceList* enumerateFundFullCone( NTriangulation* owner, NormalCoords coords, bool embeddedOnly = true); /** * Deprecated method that uses an extremely slow modified * Contejean-Devie procedure to enumerate all embedded fundamental * surfaces in the given triangulation. For details of the * algorithm, see B. A. Burton, "Fundamental normal surfaces and the * enumeration of Hilbert bases", arXiv:1111.7055v1, Nov 2011. * * Users can still access this slower procedure if they need to; * however, they should do this via enumerate(NTriangulation*, * NormalCoords, NormalList, NormalAlg, NProgressTracker*) instead. * See the documentation for that routine for further details. * * \deprecated The correct way to access this procedure is to call * enumerate(owner, coords, NS_FUNDAMENTAL | NS_EMBEDDED_ONLY, * NS_HILBERT_CD) if \a embeddedOnly is \c true, or * enumerate(owner, coords, NS_FUNDAMENTAL | NS_IMMERSED_SINGULAR, * NS_HILBERT_CD) if \a embeddedOnly is \c false. * * \warning This routine is extremely slow, and users will not want to * call it unless they have some specialised need. * * @param owner the triangulation upon which this list of normal * surfaces will be based. * @param coords the coordinate system to be used. * @param embeddedOnly \c true if only embedded normal surfaces * are to be produced, or \c false if immersed and singular * normal surfaces are also to be produced; this defaults to \c true. * @return the newly created normal surface list. */ static NNormalSurfaceList* enumerateFundCD( NTriangulation* owner, NormalCoords coords, bool embeddedOnly = true); /** * Deprecated routine to return the coordinate system * being used by the surfaces stored in this set. * * \deprecated Users should switch to the identical routine * coords() instead. * * @return the coordinate system used. */ NormalCoords getFlavour() const; /** * Deprecated routine to return the coordinate system being used by the * surfaces stored in this set. * * \deprecated Users should switch to the identical routine * coords() instead. * * @return the coordinate system used. */ NormalCoords flavour() const; /** * Returns the coordinate system being used by the * surfaces stored in this set. * * @return the coordinate system used. */ NormalCoords coords() const; /** * Returns details of which normal surfaces this list represents * within the underlying triangulation. * * This may not be the same NormalList that was passed to * enumerate(). In particular, default values will have be * explicitly filled in (such as NS_VERTEX and/or NS_EMBEDDED_ONLY), * and invalid and/or redundant values will have been removed. * * @return details of what this list represents. */ NormalList which() const; /** * Returns details of the algorithm that was used to enumerate * this list. * * These may not be the same NormalAlg flags that were passed to * enumerate(). In particular, default values will have be * explicitly filled in, invalid and/or redundant values will have * been removed, and unavailable and/or unsupported combinations * of algorithm flags will be replaced with whatever algorithm was * actually used. * * @return details of the algorithm used to enumerate this list. */ NormalAlg algorithm() const; /** * Determines if the coordinate system being used * allows for almost normal surfaces, that is, allows for * octagonal discs. * * @return \c true if and only if almost normal surfaces are * allowed. */ bool allowsAlmostNormal() const; /** * Determines if the coordinate system being used * allows for spun normal surfaces. * * @return \c true if and only if spun normal surface are * supported. */ bool allowsSpun() const; /** * Determines if the coordinate system being used * allows for transversely oriented normal surfaces. * * @return \c true if and only if transverse orientations are * supported. */ bool allowsOriented() const; /** * Returns whether this list was constructed to contain only * properly embedded surfaces. * * If this returns \c false, it does not guarantee that immersed * and/or singular surfaces are present; it merely indicates * that they were not deliberately excluded (for instance, the * quadrilateral constraints were not enforced). * * @return \c true if this list was constructed to contain only * properly embedded surfaces, or \c false otherwise. */ bool isEmbeddedOnly() const; /** * Returns the triangulation in which these normal surfaces live. * * @return the triangulation in which these surfaces live. */ NTriangulation* getTriangulation() const; /** * Returns the number of surfaces stored in this set. * * @return the number of surfaces. */ unsigned long getNumberOfSurfaces() const; /** * Returns the surface at the requested index in this set. * * @param index the index of the requested surface in this set; * this must be between 0 and getNumberOfSurfaces()-1 inclusive. * * @return the normal surface at the requested index in this set. */ const NNormalSurface* getSurface(unsigned long index) const; /** * Writes the number of surfaces in this set followed by the * details of each surface to the given output stream. Output * will be over many lines. * * \ifacespython Parameter \a out is not present and is assumed * to be standard output. * * @param out the output stream to which to write. */ void writeAllSurfaces(std::ostream& out) const; virtual void writeTextShort(std::ostream& out) const; virtual void writeTextLong(std::ostream& out) const; static NXMLPacketReader* getXMLReader(NPacket* parent, NXMLTreeResolver& resolver); virtual bool dependsOnParent() const; /** * Converts the set of all embedded vertex normal surfaces in * quadrilateral space to the set of all embedded vertex normal * surfaces in standard (tri-quad) space. The initial list in * quadrilateral space is taken to be this normal surface list; * the final list in standard space will be inserted as a new * child packet of the underlying triangulation (specifically, as * the final child). As a convenience, the final list will also * be returned from this routine. * * This routine can only be used with normal surfaces, not almost * normal surfaces. For almost normal surfaces, see the similar * routine quadOctToStandardAN(). * * This procedure is available for any triangulation whose vertex * links are all spheres and/or discs, and is \e much faster than * enumerating surfaces directly in standard tri-quad coordinates. * The underlying algorithm is described in detail in "Converting * between quadrilateral and standard solution sets in normal * surface theory", Benjamin A. Burton, Algebr. Geom. Topol. 9 (2009), * 2121-2174. * * Typically users do not need to call this routine directly, * since the standard enumerate() routine will use it implicitly * where possible. That is, when asked for standard vertex surfaces, * enumerate() will first find all \e quadrilateral vertex surfaces * and then use this procedure to convert them to standard vertex * surfaces; this is generally orders of magnitude faster than * enumerating surfaces directly in standard coordinates. * * Nevertheless, this standalone routine is provided as a convenience * for users who already have a set of quadrilateral vertex surfaces, * and who simply wish to convert them to a set of standard * vertex surfaces without the cost of implicitly enumerating the * quadrilateral vertex surfaces again. * * It should be noted that this routine does \e not simply convert * vectors from one form to another; instead it converts a full * solution set of vertex surfaces in quadrilateral coordinates to a * full solution set of vertex surfaces in standard coordinates. * Typically there are many more vertex surfaces in standard * coordinates (all of which this routine will find). * * This routine will run some very basic sanity checks before * starting. Specifically, it will check the validity and vertex * links of the underlying triangulation, and will verify that * the coordinate system and embedded-only flag are set to * NS_QUAD and \c true respectively. If any of * these checks fails, this routine will do nothing and return 0. * * \pre The underlying triangulation (the parent packet of this * normal surface list) is valid, and the link of every vertex * is either a sphere or a disc. * \pre This normal surface list is precisely the set of all * embedded vertex normal surfaces in quadrilateral space; no more, * no less. Moreover, these vectors are stored using quadrilateral * coordinates. Typically this means that it was obtained through * enumerate(), with the coordinate system set to NS_QUAD and * with \a embeddedOnly set to \c true. * * @return a full list of vertex normal surfaces in standard (tri-quad) * coordinates, or 0 if any of the basic sanity checks failed. */ NNormalSurfaceList* quadToStandard() const; /** * Converts the set of all embedded vertex almost normal surfaces in * quadrilateral-octagon space to the set of all embedded vertex * almost normal surfaces in the standard tri-quad-oct space. * * This routine is the almost normal analogue to the * quadToStandard() conversion routine; see the quadToStandard() * documentation for further information. * * \pre The underlying triangulation (the parent packet of this * normal surface list) is valid, and the link of every vertex * is either a sphere or a disc. * \pre This surface list is precisely the set of all embedded vertex * almost normal surfaces in quadrilateral-octagon space; no more, * no less. Moreover, these vectors are stored using * quadrilateral-octagon coordinates. Typically this means that it * was obtained through enumerate(), with the coordinate system set to * NS_AN_QUAD_OCT and with \a embeddedOnly set to \c true. * * @return a full list of vertex almost normal surfaces in standard * tri-quad-oct coordinates, or 0 if any of the basic sanity checks * failed. */ NNormalSurfaceList* quadOctToStandardAN() const; /** * Converts the set of all embedded vertex normal surfaces in * standard (tri-quad) space to the set of all embedded vertex * normal surfaces in quadrilateral space. The initial list in * standard space is taken to be this normal surface list; * the final list in quadrilateral space will be inserted as a new * child packet of the underlying triangulation (specifically, as * the final child). As a convenience, the final list will also * be returned from this routine. * * This routine can only be used with normal surfaces, not almost * normal surfaces. For almost normal surfaces, see the similar * routine standardANToQuadOct(). * * This procedure is available for any triangulation whose vertex * links are all spheres and/or discs. The underlying algorithm * is described in detail in "Converting between quadrilateral and * standard solution sets in normal surface theory", * Benjamin A. Burton, Algebr. Geom. Topol. 9 (2009), 2121-2174. * * It should be noted that this routine does \e not simply convert * vectors from one form to another; instead it converts a full * solution set of vertex surfaces in standard coordinates to a * full solution set of vertex surfaces in quadrilateral coordinates. * Typically there are far fewer vertex surfaces in quadrilateral * coordinates (all of which this routine will find). * * This routine will run some very basic sanity checks before * starting. Specifically, it will check the validity and vertex * links of the underlying triangulation, and will verify that * the coordinate system and embedded-only flag are set to * NS_STANDARD and \c true respectively. If any of * these checks fails, this routine will do nothing and return 0. * * \pre The underlying triangulation (the parent packet of this * normal surface list) is valid, and the link of every vertex * is either a sphere or a disc. * \pre This normal surface list is precisely the set of all * embedded vertex normal surfaces in standard (tri-quad) space; * no more, no less. Moreover, these vectors are stored using * standard coordinates. Typically this means that this list was * obtained through enumerate(), with the coordinate system set to * NS_STANDARD and with \a embeddedOnly set to \c true. * * @return a full list of vertex normal surfaces in quadrilateral * coordinates, or 0 if any of the basic sanity checks failed. */ NNormalSurfaceList* standardToQuad() const; /** * Converts the set of all embedded vertex almost normal surfaces in * standard tri-quad-oct space to the set of all embedded vertex * almost normal surfaces in the smaller quadrilateral-octagon space. * * This routine is the almost normal analogue to the * standardToQuad() conversion routine; see the standardToQuad() * documentation for further information. * * \pre The underlying triangulation (the parent packet of this * normal surface list) is valid, and the link of every vertex * is either a sphere or a disc. * \pre This normal surface list is precisely the set of all * embedded vertex almost normal surfaces in standard tri-quad-oct * space; no more, no less. Typically this means that it was obtained * through enumerate(), with the coordinate system set to * NS_AN_STANDARD and with \a embeddedOnly set to \c true. * * @return a full list of vertex almost normal surfaces in * quadrilateral-octagon coordinates, or 0 if any of the basic * sanity checks failed. */ NNormalSurfaceList* standardANToQuadOct() const; /** * Creates a new list filled with the surfaces from this list * that have at least one locally compatible partner. * In other words, a surface \a S from this list will be placed * in the new list if and only if there is some other surface \a T * in this list for which \a S and \a T are locally compatible. * See NNormalSurface::locallyCompatible() for further details on * compatibility testing. * * The new list will be inserted as a new child packet of the * underlying triangulation (specifically, as the final child). As a * convenience, the new list will also be returned from this routine. * * This original list is not altered in any way. Likewise, * the surfaces in the new list are deep copies of the originals * (so they can be altered without affecting the original surfaces). * * \pre This list contains only embedded normal surfaces. More * precisely, isEmbeddedOnly() must return \c true. * * \warning If this list contains a vertex link (plus at least * one other surface), then the new list will be identical to * the old (i.e., every surface will be copied across). * * @return the new list, which will also have been inserted as * a new child packet of the underlying triangulation. */ NNormalSurfaceList* filterForLocallyCompatiblePairs() const; /** * Creates a new list filled with the surfaces from this list * that have at least one disjoint partner. * In other words, a surface \a S from this list will be placed * in the new list if and only if there is some other surface \a T * in this list for which \a S and \a T can be made to intersect * nowhere at all, without changing either normal isotopy class. * See NNormalSurface::disjoint() for further details on disjointness * testing. * * This routine cannot deal with empty, disconnected or * non-compact surfaces. Such surfaces will be silently * ignored, and will not be used in any disjointness tests (in * particular, they will never be considered as a "disjoint partner" * for any other surface). * * The new list will be inserted as a new child packet of the * underlying triangulation (specifically, as the final child). As a * convenience, the new list will also be returned from this routine. * * This original list is not altered in any way. Likewise, * the surfaces in the new list are deep copies of the originals * (so they can be altered without affecting the original surfaces). * * \pre This list contains only embedded normal surfaces. More * precisely, isEmbeddedOnly() must return \c true. * \pre All surfaces within this list are stored using the same * coordinate system (i.e., the same subclass of NNormalSurfaceVector). * * \warning If this list contains a vertex link (plus at least * one other surface), then the new list will be identical to * the old (i.e., every surface will be copied across). * * \todo Deal properly with surfaces that are too large to handle. * * @return the new list, which will also have been inserted as * a new child packet of the underlying triangulation. */ NNormalSurfaceList* filterForDisjointPairs() const; /** * Creates a new list filled with only the surfaces from this list * that "might" represent two-sided incompressible surfaces. * More precisely, we consider all two-sided surfaces in this list, * as well as the two-sided double covers of all one-sided surfaces * in this list (see below for details on how one-sided surfaces * are handled). Each of these surfaces is examined using * relatively fast heuristic tests for incompressibility. Any * surface that is definitely \e not incompressible is thrown * away, and all other surfaces are placed in the new list. * * Therefore, it is guaranteed that every incompressible surface * from the old list will be placed in the new list. However, * it is not known whether any given surface in the new list is * indeed incompressible. * * See NNormalSurface::isIncompressible() for the definition of * incompressibility that is used here. Note in particular that * spheres are \e never considered incompressible. * * As indicated above, this filter works exclusively with two-sided * surfaces. If a surface in this list is one-sided, the heuristic * incompressibility tests will be run on its two-sided double cover. * Nevertheless, if the tests pass, the original one-sided surface * (not the double cover) will be added to the new list. * * The new list will be inserted as a new child packet of the * underlying triangulation (specifically, as the final child). As a * convenience, the new list will also be returned from this routine. * * This original list is not altered in any way. Likewise, * the surfaces in the new list are deep copies of the originals * (so they can be altered without affecting the original surfaces). * * Currently the heuristic tests include (i) throwing away * all vertex links and thin edge links, and then * (ii) cutting along the remaining surfaces and running * NTriangulation::hasSimpleCompressingDisc() on the resulting * bounded triangulations. For more details on these tests * see "The Weber-Seifert dodecahedral space is non-Haken", * Benjamin A. Burton, J. Hyam Rubinstein and Stephan Tillmann, * Trans. Amer. Math. Soc. 364:2 (2012), pp. 911-932. * * \pre The underlying 3-manifold triangulation is valid and closed. * In particular, it has no ideal vertices. * \pre This list contains only embedded normal surfaces. More * precisely, isEmbeddedOnly() must return \c true. * \pre This list contains only compact, connected normal surfaces. * \pre No surfaces in this list contain any octagonal discs. * * \warning The behaviour of this routine is subject to change * in future versions of Regina, since additional tests may be * added to improve the power of this filtering. * * \todo Add progress tracking. * * @return the new list, which will also have been inserted as * a new child packet of the underlying triangulation. */ NNormalSurfaceList* filterForPotentiallyIncompressible() const; /** * Returns a newly created matrix containing the matching * equations that were used to create this normal surface list. * The destruction of this matrix is the responsibility of the * caller of this routine. Multiple calls to this routine will * result in the construction of multiple matrices. This * routine in fact merely calls makeMatchingEquations() with the * appropriate parameters. * * The format of the matrix is identical to that returned by * makeMatchingEquations(). * * @return the matching equations used to create this normal * surface list. */ NMatrixInt* recreateMatchingEquations() const; /** * Exports this list of normal surfaces as a plain text CSV * (comma-separated value) file, using standard coordinates. * CSV files are human-readable and human-editable, and are * suitable for importing into spreadsheets and databases. * * The surfaces will be exported in standard coordinates (tri-quad * coordinates for normal surfaces, or tri-quad-oct coordinates for * almost normal surfaces). Each coordinate will become a separate * field in the CSV file. * * As well as the normal surface coordinates, additional properties * of the normal surfaces (such as Euler characteristic, orientability, * and so on) can be included as extra fields in the export. Users can * select precisely which properties to include by passing a bitmask, * formed as a bitwise \e or combination of constants from * the regina::SurfaceExportFields enumeration type. * * The CSV format used here begins with a header row, and uses commas * as field separators. Text fields with arbitrary contents are * placed inside double quotes, and the double quote character itself * is represented by a pair of double quotes. Thus the string * my "normal" surface's name would be stored as * "my ""normal"" surface's name". * * \i18n This routine makes no assumptions about the * \ref i18n "character encoding" used in the given file \e name, and * simply passes it through unchanged to low-level C/C++ file I/O * routines. Any user strings such as surface names will be written * in UTF-8. * * @param filename the name of the CSV file to export to. * @param additionalFields a bitwise combination of constants from * regina::SurfaceExportFields indicating which additional properties * of surfaces should be included in the export. * @return \c true if the export was successful, or \c false otherwise. */ bool saveCSVStandard(const char* filename, int additionalFields = regina::surfaceExportAll); /** * Exports the given list of normal surfaces as a plain text CSV * (comma-separated value) file, using edge weight coordinates. * CSV files are human-readable and human-editable, and are * suitable for importing into spreadsheets and databases. * * The surfaces will be exported in edge weight coordinates. Thus * there will be one coordinate for each edge of the underlying * triangulation; each such coordinate will become a separate field * in the CSV file. * * As well as the normal surface coordinates, additional properties * of the normal surfaces (such as Euler characteristic, orientability, * and so on) can be included as extra fields in the export. Users can * select precisely which properties to include by passing a bitmask, * formed as a bitwise \e or combination of constants from * the regina::SurfaceExportFields enumeration type. * * The CSV format used here begins with a header row, and uses commas * as field separators. Text fields with arbitrary contents are * placed inside double quotes, and the double quote character itself * is represented by a pair of double quotes. Thus the string * my "normal" surface's name would be stored as * "my ""normal"" surface's name". * * \i18n This routine makes no assumptions about the * \ref i18n "character encoding" used in the given file \e name, and * simply passes it through unchanged to low-level C/C++ file I/O * routines. Any user strings such as surface names will be written * in UTF-8. * * @param filename the name of the CSV file to export to. * @param additionalFields a bitwise combination of constants from * regina::SurfaceExportFields indicating which additional properties * of surfaces should be included in the export. * @return \c true if the export was successful, or \c false otherwise. */ bool saveCSVEdgeWeight(const char* filename, int additionalFields = regina::surfaceExportAll); /** * An iterator that gives access to the raw vectors for surfaces in * this list, pointing to the beginning of this surface list. * * \ifacespython Not present. * * @return an iterator at the beginning of this surface list. */ VectorIterator beginVectors() const; /** * An iterator that gives access to the raw vectors for surfaces in * this list, pointing past the end of this surface list. * This iterator is not dereferenceable. * * \ifacespython Not present. * * @return an iterator past the end of this surface list. */ VectorIterator endVectors() const; /** * A bidirectional iterator that runs through the raw vectors for * surfaces in this list. * * \ifacespython Not present. */ class VectorIterator : public std::iterator< std::bidirectional_iterator_tag, const NNormalSurfaceVector*> { private: std::vector::const_iterator it_; /**< An iterator into the underlying list of surfaces. */ public: /** * Creates a new uninitialised iterator. */ VectorIterator(); /** * Creates a copy of the given iterator. * * @param cloneMe the iterator to clone. */ VectorIterator(const VectorIterator& cloneMe); /** * Makes this a copy of the given iterator. * * @param cloneMe the iterator to clone. * @return a reference to this iterator. */ VectorIterator& operator = (const VectorIterator& cloneMe); /** * Compares this with the given operator for equality. * * @param other the iterator to compare this with. * @return \c true if the iterators point to the same * element of the same normal surface list, or \c false * if they do not. */ bool operator == (const VectorIterator& other) const; /** * Compares this with the given operator for inequality. * * @param other the iterator to compare this with. * @return \c false if the iterators point to the same * element of the same normal surface list, or \c true * if they do not. */ bool operator != (const VectorIterator& other) const; /** * Returns the raw vector for the normal surface that this * iterator is currently pointing to. * * \pre This iterator is dereferenceable (in particular, * it is not past-the-end). * * @return the corresponding normal surface vector. */ const NNormalSurfaceVector* operator *() const; /** * The preincrement operator. * * @return a reference to this iterator after the increment. */ VectorIterator& operator ++(); /** * The postincrement operator. * * @return a copy of this iterator before the * increment took place. */ VectorIterator operator ++(int); /** * The predecrement operator. * * @return a reference to this iterator after the decrement. */ VectorIterator& operator --(); /** * The postdecrement operator. * * @return a copy of this iterator before the * decrement took place. */ VectorIterator operator --(int); private: /** * Initialise a new vector iterator using an iterator for * the internal list of normal surfaces. */ VectorIterator( const std::vector::const_iterator& i); friend class NNormalSurfaceList; }; protected: /** * Creates an empty list of normal surfaces with the given * parameters. * * @param coords the coordinate system to be used * for filling this list. * @param which indicates which normal surfaces these will * represent within the underlying triangulation. * @param algorithm details of the enumeration algorithm that * will be used to fill this list. */ NNormalSurfaceList(NormalCoords coords, NormalList which, NormalAlg algorithm); virtual NPacket* internalClonePacket(NPacket* parent) const; virtual void writeXMLPacketData(std::ostream& out) const; /** * An output iterator used to insert surfaces into an * NNormalSurfaceList. * * Objects of type NNormalSurface* and * NNormalSurfaceVector* can be assigned to this * iterator. In the latter case, a surrounding NNormalSurface * will be automatically created. * * \warning The behaviour of this class has changed! * As of Regina 4.6, this class happily inserts every surface or * vector that it is given. In previous versions it checked * almost normal surface vectors for multiple octagonal discs; * this check has been removed to support conversions between * quad-oct space and standard almost normal space, and to support * the enumeration of \e all almost normal surfaces (as opposed to * just vertex surfaces). Such checks are now left to the user * interface (and indeed are now optional, at the user's discretion). */ struct SurfaceInserter : public std::iterator< std::output_iterator_tag, NNormalSurfaceVector*> { NNormalSurfaceList* list; /**< The list into which surfaces will be inserted. */ NTriangulation* owner; /**< The triangulation in which the surfaces to be * inserted are contained. */ /** * Creates a new output iterator. The member variables of * this iterator will be initialised according to the * parameters passed to this constructor. * * @param newList the list into which surfaces will be * inserted. * @param newOwner the triangulation in which the surfaces * to be inserted are contained. */ SurfaceInserter(NNormalSurfaceList& newList, NTriangulation* newOwner); /** * Creates a new output iterator that is a clone of the * given iterator. * * @param cloneMe the output iterator to clone. */ SurfaceInserter(const SurfaceInserter& cloneMe); /** * Sets this iterator to be a clone of the given output iterator. * * @param cloneMe the output iterator to clone. * @return this output iterator. */ SurfaceInserter& operator =(const SurfaceInserter& cloneMe); /** * Appends a normal surface to the end of the appropriate * surface list. * * The given surface will be deallocated with the other * surfaces in this list when the list is eventually destroyed. * * @param surface the normal surface to insert. * @return this output iterator. */ SurfaceInserter& operator =(NNormalSurface* surface); /** * Appends the normal surface corresponding to the given * vector to the end of the appropriate surface list. * * The given vector will be owned by the newly created * normal surface and will be deallocated with the other * surfaces in this list when the list is eventually destroyed. * * \warning The behaviour of this routine has changed! * As of Regina 4.6, this routine no longer checks for * multiple octagonal discs. See the SurfaceInserter * class notes for details. * * @param vector the vector of the normal surface to insert. * @return this output iterator. */ SurfaceInserter& operator =(NNormalSurfaceVector* vector); /** * Returns a reference to this output iterator. * * @return this output iterator. */ SurfaceInserter& operator *(); /** * Returns a reference to this output iterator. * * @return this output iterator. */ SurfaceInserter& operator ++(); /** * Returns a reference to this output iterator. * * @return this output iterator. */ SurfaceInserter& operator ++(int); }; private: /** * A helper class containing constants, typedefs and operations * for working with normal (as opposed to almost normal) surfaces. * * This class and its partner AlmostNormalSpec can be used to * write generic template code that works with both normal * \e and almost normal surfaces. * * The full definition of this class is in the file normalspec-impl.h . */ struct NormalSpec; /** * A helper class containing constants, typedefs and operations * for working with almost normal (as opposed to normal) surfaces. * * This class and its partner NormalSpec can be used to * write generic template code that works with both normal * \e and almost normal surfaces. * * The full definition of this class is in the file normalspec-impl.h . */ struct AlmostNormalSpec; /** * Converts a set of embedded vertex normal surfaces in * (quad or quad-oct) space to a set of embedded vertex normal * surfaces in (standard normal or standard almost normal) space. * The original (quad or quad-oct) space surfaces are passed in * the argument \a quadList, and the resulting (standard normal * or standard almost normal) space surfaces will be inserted * directly into this list. * * See quadToStandard() and quadOctToStandardAN() for full details * and preconditions for this procedure. * * This routine is designed to work with surface lists that are * still under construction. As such, it ignores the packet * tree completely. The parent packet is ignored (and not changed); * instead the underlying triangulation is passed explicitly as * the argument \a owner. * * Although this routine takes a vector of non-const pointers, it * guarantees not to modify (or destroy) any of the contents. * * An optional progress tracker may be passed. If so, this routine * will update the percentage progress and poll for cancellation * requests. It will be assumed that an appropriate stage has already * been declared via NProgressTracker::newStage() before this routine * is called, and that NProgressTracker::setFinished() will be * called after this routine returns. * * Although this is a template function, it is a private * template function and so is only defined in the one .cpp * file that needs it. * * \pre The template argument \a Variant is either NormalSpec * or AlmostNormalSpec, according to whether we are doing the * work for quadToStandard() or quadOctToStandardAN() respectively. * \pre The coordinate system for this surface list is set to * NS_STANDARD or NS_AN_STANDARD, according to whether we are doing * the work for quadToStandard() or quadOctToStandardAN() respectively, * and the embedded-only flag is set to \c true. * \pre The given triangulation is valid and non-empty, and the link * of every vertex is either a sphere or a disc. * * @param owner the triangulation upon which this list of * surfaces is to be based. * @param reducedList a full list of vertex surfaces in * (quad or quad-oct) coordinates for the given triangulation. * @param tracker a progress tracker to be used for progress reporting * and cancellation requests, or 0 if this is not required. */ template void buildStandardFromReduced(NTriangulation* owner, const std::vector& reducedList, NProgressTracker* tracker = 0); /** * Implements the one-template-argument version of * buildStandardFromReduced() using the specified bitmask type * to store zero sets. See the one-template-argument * buildStandardFromReduced() for further information on this routine, * including important preconditions. * * The one-template-argument buildStandardFromReduced() simply * chooses an appropriate bitmask type and then calls this * routine, which does the real work. * * \pre The template argument \a BitmaskType can support * bitmasks of size 7 \a n (if we are using normal surfaces) or size * 10 \a n (if we are using almost normal surfaces), where \a n is * the number of tetrahedra in the given triangulation. */ template void buildStandardFromReducedUsing(NTriangulation* owner, const std::vector& reducedList, NProgressTracker* tracker); /** * Converts a set of embedded vertex surfaces in (quad or quad-oct) * space to a set of embedded vertex surfaces in (standard normal or * standard almost normal) space. * * This is a generic implementation that performs the real work * for both quadToStandard() and quadOctToStandardAN(). See each * of those routines for further details as well as relevant * preconditions and postconditions. * * \pre The template argument \a Variant is either NormalSpec * or AlmostNormalSpec, according to whether we are implementing * quadToStandard() or quadOctToStandardAN() accordingly. */ template NNormalSurfaceList* internalReducedToStandard() const; /** * Converts a set of embedded vertex surfaces in * (standard normal or standard almost normal) space to a set of * embedded vertex surfaces in (quad or quad-oct) space. * * This is a generic implementation that performs the real work * for both standardToQuad() and standardANToQuadOct(). See each * of those routines for further details as well as relevant * preconditions and postconditions. * * \pre The template argument \a Variant is either NormalSpec * or AlmostNormalSpec, according to whether we are implementing * standardToQuad() or standardANToQuadOct() accordingly. */ template NNormalSurfaceList* internalStandardToReduced() const; /** * A thread class that performs all normal surface enumeration. * * The "real work" is in operator(), where the coordinate system * becomes a compile-time constant. The run() routine simply * farms out the real work to some instantiation of operator(). */ class Enumerator : public NThread { private: NNormalSurfaceList* list_; /**< The surface list to be filled. */ NTriangulation* triang_; /**< The triangulation in which these surfaces lie. */ NProgressTracker* tracker_; /**< The progress tracker through which progress is reported and cancellation requests are accepted, or 0 if no progress tracker is in use. */ public: /** * Creates a new enumerator thread with the given * parameters. * * @param list the surface list to be filled. * @param triang the triangulation in which these surfaces lie. * @param tracker the progress tracker to use for progress * reporting and cancellation polling, or 0 if these * capabilities are not required. */ Enumerator(NNormalSurfaceList* list, NTriangulation* triang, NProgressTracker* tracker); void* run(void*); /** * Performs the real enumeration work, in a setting * where the underlying coordinate system is * a compile-time constant. * * We assume here that neither list_->which_ nor * list_->algorithm_ have been sanity-checked. * * This routine fills \a list_ with surfaces, and then once * this is finished it inserts \a list_ into the packet * tree as a child of \a triang_. */ template void operator() (Coords); private: /** * The enumeration code for enumerating vertex surfaces. * This is internal to operator(). * * We assume that the flag set which_ is set correctly, * and we do not alter it here. * We make no assumptions about the state of algorithm_, * and we set this during the course of this routine. * * This routine only fills \a list_ with surfaces. * It does not make any adjustments to the structure of * the packet tree. * * If \a tracker_ is non-null, this routine declare and * work through a series of tracker stages whose * combined weights sum to 1. It will not, however, * call NProgressTracker::setFinished(). */ template void fillVertex(); /** * The enumeration code for enumerating fundamental surfaces. * This is internal to operator(). * * We assume that the flag set which_ is set correctly, * and we do not alter it here. * We make no assumptions about the state of algorithm_, * and we set this during the course of this routine. * * This routine only fills \a list_ with surfaces. * It does not make any adjustments to the structure of * the packet tree. * * If \a tracker_ is non-null, this routine declare and * work through a series of tracker stages whose * combined weights sum to 1. It will not, however, * call NProgressTracker::setFinished(). */ template void fillFundamental(); /** * The enumeration code for enumerating vertex surfaces * using the double description method. * This is internal to fillVertex(). * * This routine assumes that \a algorithm_ has been set * correctly, and does not alter it. * * If \a tracker_ is non-null, this routine assumes that * an appropriate tracker stage has already been * declared, and works through that stage only. * * \pre The underlying triangulation is non-empty. */ template void fillVertexDD(); /** * The enumeration code for enumerating vertex surfaces * using the tree traversal method. * This is internal to fillVertex(). * * This routine assumes that \a algorithm_ has been set * correctly, and does not alter it. * * If \a tracker_ is non-null, this routine assumes that * an appropriate tracker stage has already been * declared, and works through that stage only. * * \pre We are enumerating embedded surfaces only. * \pre The underlying triangulation is non-empty. */ template void fillVertexTree(); /** * Internal code for fillVertexTree() in which the underlying * integer type for the tree traversal method is fixed. * * This does all of the work for fillVertexTree(), aside * from the initial selection of an integer type. See * the nodes for fillVertexTree() for further details. * * \pre We are enumerating embedded surfaces only. * \pre The underlying triangulation is non-empty. * \pre The given integer type is known to be sufficient * (i.e., will not overflow) for the enumeration problem * under consideration. */ template void fillVertexTreeWith(); /** * The enumeration code for enumerating fundamental surfaces * using the primal method. * This is internal to fillFundamental(). * * This routine assumes nothing about the state of the * \a algorithm_ flag set, and sets it appropriately. * * If \a tracker_ is non-null, this routine declare and * work through a series of tracker stages whose * combined weights sum to 1. It will not, however, * call NProgressTracker::setFinished(). * * \pre The underlying triangulation is non-empty. */ template void fillFundamentalPrimal(); /** * The enumeration code for enumerating fundamental surfaces * using the dual method. * This is internal to fillFundamental(). * * This routine assumes nothing about the state of the * \a algorithm_ flag set, and sets it appropriately. * * If \a tracker_ is non-null, this routine declare and * work through a series of tracker stages whose * combined weights sum to 1. It will not, however, * call NProgressTracker::setFinished(). * * \pre The underlying triangulation is non-empty. */ template void fillFundamentalDual(); /** * The enumeration code for enumerating fundamental surfaces * using a slow Contejean-Devie method. * This is internal to fillFundamental(). * * This routine assumes nothing about the state of the * \a algorithm_ flag set, and sets it appropriately. * * If \a tracker_ is non-null, this routine declare and * work through a series of tracker stages whose * combined weights sum to 1. It will not, however, * call NProgressTracker::setFinished(). * * \pre The underlying triangulation is non-empty. */ template void fillFundamentalCD(); /** * The enumeration code for enumerating fundamental surfaces * using a slow full cone enumeration. * This is internal to fillFundamental(). * * This routine assumes nothing about the state of the * \a algorithm_ flag set, and sets it appropriately. * * If \a tracker_ is non-null, this routine declare and * work through a series of tracker stages whose * combined weights sum to 1. It will not, however, * call NProgressTracker::setFinished(). * * \pre The underlying triangulation is non-empty. */ template void fillFundamentalFullCone(); }; friend class regina::NXMLNormalSurfaceListReader; }; /** * Returns a new normal surface vector of the appropriate length for the * given triangulation and the given coordinate system. * All elements of this vector will be initialised to zero. * * The new vector will be of the subclass of NNormalSurfaceVector * corresponding to the given coordinate system. The caller * of this routine is responsible for destroying the new vector. * * \ifacespython Not present. * * @param triangulation the triangulation upon which the underlying * coordinate system is based. * @param coords the coordinate system to be used. * @return a new zero vector of the correct class and length. */ REGINA_API NNormalSurfaceVector* makeZeroVector( const NTriangulation* triangulation, NormalCoords coords); /** * Creates a new set of normal surface matching equations for the * given triangulation using the given coordinate system. * The returned matrix will be newly allocated and its destruction will * be the responsibility of the caller of this routine. * * Each equation will be represented as a row of the matrix. * Each column of the matrix represents a coordinate in the given * coordinate system. * * @param triangulation the triangulation upon which these matching equations * will be based. * @param coords the coordinate system to be used. * @return a newly allocated set of matching equations. */ REGINA_API NMatrixInt* makeMatchingEquations( const NTriangulation* triangulation, NormalCoords coords); /** * Creates a new set of validity constraints representing the condition that * normal surfaces be embedded. The validity constraints will be expressed * relative to the given coordinate system. * * \ifacespython Not present. * * @param triangulation the triangulation upon which these validity constraints * will be based. * @param coords the coordinate system to be used. * @return a newly allocated set of constraints. */ REGINA_API NEnumConstraintList* makeEmbeddedConstraints( const NTriangulation* triangulation, NormalCoords coords); /*@}*/ // Inline functions for NNormalSurfaceList inline NNormalSurfaceList::~NNormalSurfaceList() { for_each(surfaces.begin(), surfaces.end(), FuncDelete()); } inline NormalCoords NNormalSurfaceList::getFlavour() const { return coords_; } inline NormalCoords NNormalSurfaceList::flavour() const { return coords_; } inline NormalCoords NNormalSurfaceList::coords() const { return coords_; } inline NormalList NNormalSurfaceList::which() const { return which_; } inline NormalAlg NNormalSurfaceList::algorithm() const { return algorithm_; } inline bool NNormalSurfaceList::isEmbeddedOnly() const { return which_.has(NS_EMBEDDED_ONLY); } inline unsigned long NNormalSurfaceList::getNumberOfSurfaces() const { return surfaces.size(); } inline const NNormalSurface* NNormalSurfaceList::getSurface( unsigned long index) const { return surfaces[index]; } inline bool NNormalSurfaceList::dependsOnParent() const { return true; } inline NNormalSurfaceList* NNormalSurfaceList::enumerate( NTriangulation* owner, NormalCoords coords, bool embeddedOnly, NProgressTracker* tracker) { return enumerate(owner, coords, NS_VERTEX | (embeddedOnly ? NS_EMBEDDED_ONLY : NS_IMMERSED_SINGULAR), NS_ALG_DEFAULT, tracker); } inline NNormalSurfaceList* NNormalSurfaceList::enumerateStandardDirect( NTriangulation* owner) { return enumerate(owner, NS_STANDARD, NS_VERTEX | NS_EMBEDDED_ONLY, NS_VERTEX_STD_DIRECT); } inline NNormalSurfaceList* NNormalSurfaceList::enumerateStandardANDirect( NTriangulation* owner) { return enumerate(owner, NS_AN_STANDARD, NS_VERTEX | NS_EMBEDDED_ONLY, NS_VERTEX_STD_DIRECT); } inline NNormalSurfaceList* NNormalSurfaceList::enumerateFundPrimal( NTriangulation* owner, NormalCoords coords, bool embeddedOnly, NNormalSurfaceList*, NProgressTracker* tracker) { return enumerate(owner, coords, NS_FUNDAMENTAL | (embeddedOnly ? NS_EMBEDDED_ONLY : NS_IMMERSED_SINGULAR), NS_HILBERT_PRIMAL, tracker); } inline NNormalSurfaceList* NNormalSurfaceList::enumerateFundDual( NTriangulation* owner, NormalCoords coords, bool embeddedOnly, NProgressTracker* tracker) { return enumerate(owner, coords, NS_FUNDAMENTAL | (embeddedOnly ? NS_EMBEDDED_ONLY : NS_IMMERSED_SINGULAR), NS_HILBERT_DUAL, tracker); } inline NNormalSurfaceList* NNormalSurfaceList::enumerateFundCD( NTriangulation* owner, NormalCoords coords, bool embeddedOnly) { return enumerate(owner, coords, NS_FUNDAMENTAL | (embeddedOnly ? NS_EMBEDDED_ONLY : NS_IMMERSED_SINGULAR), NS_HILBERT_CD); } inline NNormalSurfaceList* NNormalSurfaceList::enumerateFundFullCone( NTriangulation* owner, NormalCoords coords, bool embeddedOnly) { return enumerate(owner, coords, NS_FUNDAMENTAL | (embeddedOnly ? NS_EMBEDDED_ONLY : NS_IMMERSED_SINGULAR), NS_HILBERT_FULLCONE); } inline NMatrixInt* NNormalSurfaceList::recreateMatchingEquations() const { return makeMatchingEquations(getTriangulation(), coords_); } inline NNormalSurfaceList::VectorIterator::VectorIterator() { } inline NNormalSurfaceList::VectorIterator::VectorIterator( const NNormalSurfaceList::VectorIterator& cloneMe) : it_(cloneMe.it_) { } inline NNormalSurfaceList::VectorIterator& NNormalSurfaceList::VectorIterator:: operator =(const NNormalSurfaceList::VectorIterator& cloneMe) { it_ = cloneMe.it_; return *this; } inline bool NNormalSurfaceList::VectorIterator::operator ==( const NNormalSurfaceList::VectorIterator& other) const { return (it_ == other.it_); } inline bool NNormalSurfaceList::VectorIterator::operator !=( const NNormalSurfaceList::VectorIterator& other) const { return (it_ != other.it_); } inline const NNormalSurfaceVector* NNormalSurfaceList::VectorIterator:: operator *() const { return (*it_)->rawVector(); } inline NNormalSurfaceList::VectorIterator& NNormalSurfaceList::VectorIterator:: operator ++() { ++it_; return *this; } inline NNormalSurfaceList::VectorIterator NNormalSurfaceList::VectorIterator:: operator ++(int) { return NNormalSurfaceList::VectorIterator(it_++); } inline NNormalSurfaceList::VectorIterator& NNormalSurfaceList::VectorIterator:: operator --() { --it_; return *this; } inline NNormalSurfaceList::VectorIterator NNormalSurfaceList::VectorIterator:: operator --(int) { return NNormalSurfaceList::VectorIterator(it_--); } inline NNormalSurfaceList::VectorIterator::VectorIterator( const std::vector::const_iterator& i) : it_(i) { } inline NNormalSurfaceList::VectorIterator NNormalSurfaceList::beginVectors() const { return VectorIterator(surfaces.begin()); } inline NNormalSurfaceList::VectorIterator NNormalSurfaceList::endVectors() const { return VectorIterator(surfaces.end()); } inline NNormalSurfaceList::SurfaceInserter::SurfaceInserter( NNormalSurfaceList& newList, NTriangulation* newOwner) : list(&newList), owner(newOwner) { } inline NNormalSurfaceList::SurfaceInserter::SurfaceInserter( const SurfaceInserter& cloneMe) : list(cloneMe.list), owner(cloneMe.owner) { } inline NNormalSurfaceList::SurfaceInserter& NNormalSurfaceList::SurfaceInserter::operator =( const SurfaceInserter& cloneMe) { list = cloneMe.list; owner = cloneMe.owner; return *this; } inline NNormalSurfaceList::SurfaceInserter& NNormalSurfaceList::SurfaceInserter::operator =( NNormalSurface* surface) { list->surfaces.push_back(surface); return *this; } inline NNormalSurfaceList::SurfaceInserter& NNormalSurfaceList::SurfaceInserter::operator =( NNormalSurfaceVector* vector) { list->surfaces.push_back(new NNormalSurface(owner, vector)); return *this; } inline NNormalSurfaceList::SurfaceInserter& NNormalSurfaceList::SurfaceInserter::operator *() { return *this; } inline NNormalSurfaceList::SurfaceInserter& NNormalSurfaceList::SurfaceInserter::operator ++() { return *this; } inline NNormalSurfaceList::SurfaceInserter& NNormalSurfaceList::SurfaceInserter::operator ++(int) { return *this; } inline NNormalSurfaceList::NNormalSurfaceList(NormalCoords coords, NormalList which, NormalAlg algorithm) : coords_(coords), which_(which), algorithm_(algorithm) { } inline NNormalSurfaceList::Enumerator::Enumerator(NNormalSurfaceList* list, NTriangulation* triang, NProgressTracker* tracker) : list_(list), triang_(triang), tracker_(tracker) { } } // namespace regina #endif regina-4.96/engine/surfaces/normalcoords.h000644 000765 000024 00000015477 12377775556 020611 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/normalcoords.h * \brief Defines constants for normal surface coordinate systems. */ #ifndef __NORMALCOORDS_H #ifndef __DOXYGEN #define __NORMALCOORDS_H #endif #include "regina-core.h" namespace regina { /** * \weakgroup surfaces * @{ */ /** * Represents different coordinate systems that can * be used for enumerating and displaying normal surfaces. * * IDs 0-9999 are reserved for future use by Regina. If you are extending * Regina to include your own coordinate system, you should choose * an ID >= 10000. */ enum NormalCoords { /** * Represents standard triangle-quadrilateral coordinates for * normal surfaces. */ NS_STANDARD = 0, /** * Represents quadrilateral coordinates for normal surfaces. * For details, see "Normal surface Q-theory", Jeffrey L. Tollefson, * Pacific J. Math. 183 (1998), no. 2, 359--374. */ NS_QUAD = 1, /** * Indicates that a list of almost normal surfaces was created * using Regina 4.5.1 or earlier, where surfaces with more than * one octagon of the same type were stripped out of the final * solution set. As of Regina 4.6 such surfaces are now * included in the solution set, since we need them if we * wish to enumerate \e all almost normal surfaces (not just * the \e vertex almost normal surfaces). * * This coordinate system is only used with legacy data files; new vectors * and lists cannot be created in this coordinate system. The underlying * coordinates are identical to those of NS_AN_STANDARD. */ NS_AN_LEGACY = 100, /** * Represents quadrilateral-octagon coordinates for octagonal * almost normal surfaces. For details, see * "Quadrilateral-octagon coordinates for almost normal surfaces", * Benjamin A. Burton, Experiment. Math. 19 (2010), 285-315. */ NS_AN_QUAD_OCT = 101, /** * Represents standard triangle-quadrilateral-octagon coordinates * for octagonal almost normal surfaces. */ NS_AN_STANDARD = 102, /** * Represents edge weight coordinates for normal surfaces. * This coordinate system is for display only; surface * vectors and lists cannot be created in this coordinate system. */ NS_EDGE_WEIGHT = 200, /** * Represents triangle arc coordinates for normal surfaces. * This coordinate system is for display only; surface * vectors and lists cannot be created in this coordinate system. */ NS_TRIANGLE_ARCS = 201, /** * A deprecated alias for NS_TRIANGLE_ARCS. * This represents triangle arc coordinates for normal surfaces. * See NS_TRIANGLE_ARCS for further details. * * \deprecated This constant will be removed in a future version * of Regina. Please use NS_TRIANGLE_ARCS instead. */ NS_FACE_ARCS = 201, /** * Represents standard triangle-quadrilateral coordinates for * transversely oriented normal surfaces. */ NS_ORIENTED = 300, /** * Represents quadrilateral coordinates for transversely oriented * normal surfaces. */ NS_ORIENTED_QUAD = 301, /** * Represents angle structure coordinates. * * This coordinate system is \e not for use with normal surfaces: * it cannot be used either to display them or enumerate them. * Instead it is for use with angle structures on triangulations. * Because the combinatorics and linear algebra of angle strutures * are tightly related to those of normal surfaces, we include * NS_ANGLE here so that angle structure routines can make use of * some of Regina's existing normal surface machinery. * * For a triangulation with \a n tetrahedra, this system has * 3n+1 coordinates. The first 3n are analogous * to quadrilateral coordinates (specifically, for each * quadrilateral type \a Q, the corresponding angle structure coordinate * represents the pair of angles in the same tetrahedron that \a Q does * not meet). The final coordinate is a scaling coordinate, used to * projectivise the angle structure polytope so that it becomes a * polyhedral cone that is invariant under (positive) scaling. * If the final scaling coordinate is \a s, then a rational value of \a x * in any other coordinate position should be interpreted as the angle * x.π/s. * * \pre This coordinate system must not be used with any of Regina's * routines unless they explicitly declare that NS_ANGLE is allowed. */ NS_ANGLE = 400 }; /*@}*/ } // namespace regina #endif regina-4.96/engine/surfaces/normalflags.h000644 000765 000024 00000035031 12377775557 020401 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/normalflags.h * \brief Defines constants and flags for normal surface enumeration. */ #ifndef __NORMALFLAGS_H #ifndef __DOXYGEN #define __NORMALFLAGS_H #endif #include "regina-core.h" #include "utilities/flags.h" namespace regina { /** * \weakgroup surfaces * @{ */ /** * Represents different lists of normal surfaces that might be constructed * for a given triangulation. * * The NormalList enumeration refers to the \e contents of the list, * whereas the NormalAlgFlags enumeration refers to the \e algorithm * used to build it. * * \ifacespython The values in this enumeration type are present, but * they are treated by Python as NormalList objects (and they can be * combined and/or queried as such). * The underlying enumeration type is not exposed to Python. */ enum NormalListFlags { /** * An empty flag, indicating to an enumeration routine that it * should use its default behaviour. * The numeric value of this flag is zero (i.e., it has no effect * when combined with other flags using bitwise OR). */ NS_LIST_DEFAULT = 0x0000, /** * Indicates that this list is restricted to properly embedded * surfaces only. * * This flag is incompatible with NS_IMMERSED_SINGULAR. */ NS_EMBEDDED_ONLY = 0x0001, /** * Indicates that the scope of this list includes not just properly * embedded surfaces, but also immersed and/or branched surfaces. * * This is no guarantee that the list \e contains immersed and/or * branched surfaces; it merely states that such surfaces have not * been explicitly excluded (in particular, the quadrilateral * constraints have not been enforced). * * This flag is incompatible with NS_EMBEDDED_ONLY. */ NS_IMMERSED_SINGULAR = 0x0002, /** * Indicates a list of all vertex normal surfaces, with respect to * the particular normal coordinate system used by the list. * * This flag is incompatible with NS_FUNDAMENTAL. */ NS_VERTEX = 0x0004, /** * Indicates a list of all fundamental normal surfaces, with respect to * the particular normal coordinate system used by the list. * * This flag is incompatible with NS_VERTEX. */ NS_FUNDAMENTAL = 0x0008, /** * Indicates a list that was constructed using an old version of * Regina (4.93 or earlier). * * These older versions did not retain details of how each list was * constructed, beyond whether immersed and/or singular surfaces were * included. Therefore no information is available for such lists, * other than the presence or absence of the NS_EMBEDDED_ONLY and/or * NS_IMMERSED_SINGULAR flags. * * If this flag is passed to an enumeration routine, it will be ignored. */ NS_LEGACY = 0x4000, /** * Indicates some other type of list, typically hand-crafted by the * user or built by some customised algorithm. * * If this flag is passed to an enumeration routine, it will be ignored. */ NS_CUSTOM = 0x8000 }; /** * A combination of flags for types of normal surface lists. * * \ifacespython This is present, and all values in the NormalListFlags * enumeration type are treated as members of this NormalList class. */ typedef regina::Flags NormalList; /** * Returns the bitwise OR of the two given flags. * * @param lhs the first flag to combine. * @param rhs the second flag to combine. * @return the combination of both flags. */ inline NormalList operator | (NormalListFlags lhs, NormalListFlags rhs) { return NormalList(lhs) | rhs; } /** * Represents options and variants of algorithms for enumerating various * types of normal surfaces. * * These options are typically combined in a bitwise fashion using the * NormalAlgs type, and then passed to enumeration routines such as * NNormalSurfaceList::vertex(). * * \ifacespython The values in this enumeration type are present, but * they are treated by Python as NormalList objects (and they can be * combined and/or queried as such). * The underlying enumeration type is not exposed to Python. */ enum NormalAlgFlags { /** * An empty flag, indicating to an enumeration routine that it * should use its default behaviour. * The numeric value of this flag is zero (i.e., it has no effect * when combined with other flags using bitwise OR). */ NS_ALG_DEFAULT = 0x0000, /** * When enumerating in standard normal or almost normal coordinates, * this flag indicates that the algorithm should first enumerate in * quadrilateral or quadrilateral-octagon coordinates, and then * expand this "reduced" solution set to the (typically larger) * "standard" solution set. * * This is typically much faster than a direct enumeration in * standard normal or almost normal coordinates, and enumeration * routines will use this option where possible unless explicitly * requested not to (via the flag NS_VERTEX_STD_DIRECT). * * For an explanation of this procedure, see B. A. Burton, * "Converting between quadrilateral and standard solution sets in * normal surface theory", Algebr. Geom. Topol. 9 (2009), 2121-2174. * * This flag is incompatible with NS_VERTEX_STD_DIRECT. */ NS_VERTEX_VIA_REDUCED = 0x0001, /** * When enumerating in standard normal or almost normal coordinates, * this flag indicates that the algorithm should work directly in * that coordinate system, and should not go via the "reduced" * (quadrilateral or quadrilateral-octagon) coordinate system. * * This is typically \e much slower than going via the reduced * system, and users should only request this if they have a * specialised need. See NS_VERTEX_VIA_REDUCED for further information. * * This flag is incompatible with NS_VERTEX_VIA_REDUCED. */ NS_VERTEX_STD_DIRECT = 0x0002, /** * When enumerating vertex normal surfaces, * this flag indicates that the tree traversal algorithm should be * used. * * This algorithm is based on linear and integer programming * techniques, and has many desirable properties including a * relatively low overhead. Enumeration algorithms will use it if * possible unless a different method is explicitly requested. * * For details on the tree traversal algorithm, see B. A. Burton and * M. Ozlen, "A tree traversal algorithm for decision problems in * knot theory and 3-manifold topology", Algorithmica 65 (2013), * pp. 772-801. * * This flag is incompatible with NS_VERTEX_DD. */ NS_VERTEX_TREE = 0x0010, /** * When enumerating vertex normal surfaces, * this flag indicates that a modified double description method * should be used. * * This algorithm can suffer from a combinatorial explosion with * larger problems, leading to extremely large time and memory * footprints. Users should only request this if they have some * specialised need. * * For details on the modified double description method, see * B. A. Burton, "Optimizing the double description method for * normal surface enumeration", Mathematics of Computation * 79 (2010), pp. 453-484. * * This flag is incompatible with NS_VERTEX_TREE. */ NS_VERTEX_DD = 0x0020, /** * When enumerating fundamental normal surfaces, * this flag indicates that the primal method should be used for * enumerating a Hilbert basis. * * The primal method is recommended, and enumeration algorithms will * use it if possible unless a different method is explicitly requested. * This method uses code from Normaliz for parts of its processing. * * For details and comparisons of the various options for enumerating * fundamental normal surfaces, see B. A. Burton, "Enumerating * fundamental normal surfaces: Algorithms, experiments and invariants", * ALENEX 2014: Proceedings of the Meeting on Algorithm * Engineering & Experiments, SIAM, 2014, pp. 112-124. * * This flag is incompatible with NS_HILBERT_DUAL, * NS_HILBERT_CD and NS_HILBERT_FULLCONE. */ NS_HILBERT_PRIMAL = 0x0100, /** * When enumerating fundamental normal surfaces, * this flag indicates that the dual method should be used for * enumerating a Hilbert basis. * * The dual method is fast (like the primal method), but its * performance is highly variable; for this reason the primal method * is recommended instead. * This method does not make use of Normaliz, and is the recommended * method for situations in which Normaliz is not available for some * reason. * * For details and comparisons of the various options for enumerating * fundamental normal surfaces, see B. A. Burton, "Enumerating * fundamental normal surfaces: Algorithms, experiments and invariants", * ALENEX 2014: Proceedings of the Meeting on Algorithm * Engineering & Experiments, SIAM, 2014, pp. 112-124. * * This flag is incompatible with NS_HILBERT_PRIMAL, * NS_HILBERT_CD and NS_HILBERT_FULLCONE. */ NS_HILBERT_DUAL = 0x0200, /** * When enumerating fundamental normal surfaces, * this flag indicates that a modified Contejean-Devie procedure should * be used for enumerating a Hilbert basis. * * The Contejean-Devie procedure is typically \e much slower * than either the primal or dual method, and users should only * request it if they have some specialised need. * * For details and comparisons of the various options for enumerating * fundamental normal surfaces, see B. A. Burton, "Enumerating * fundamental normal surfaces: Algorithms, experiments and invariants", * ALENEX 2014: Proceedings of the Meeting on Algorithm * Engineering & Experiments, SIAM, 2014, pp. 112-124. * * This flag is incompatible with NS_HILBERT_PRIMAL, * NS_HILBERT_DUAL and NS_HILBERT_FULLCONE. */ NS_HILBERT_CD = 0x0400, /** * When enumerating fundamental normal surfaces, * this flag indicates that a Hilbert basis for the full solution * cone should be constructed, and additional combinatorial * constraints (such as the quadrilateral constraints) should only * be enforced as the final step. * * If you are only enumerating properly embedded surfaces * then this procedure \e extremely slow, and users should only * request it if they have some specialised need. * * For details and comparisons of the various options for enumerating * fundamental normal surfaces, see B. A. Burton, "Enumerating * fundamental normal surfaces: Algorithms, experiments and invariants", * ALENEX 2014: Proceedings of the Meeting on Algorithm * Engineering & Experiments, SIAM, 2014, pp. 112-124. * * This flag is incompatible with NS_HILBERT_PRIMAL, * NS_HILBERT_DUAL and NS_HILBERT_CD. */ NS_HILBERT_FULLCONE = 0x0800, /** * Indicates that a normal surface list was enumerated using an * older version of Regina (4.93 or earlier). * * These older versions did not retain details of the algorithm * used to build each list, and so in such cases no further * algorithmic information is available. * * If this flag is passed to an enumeration algorithm, it will be ignored. */ NS_ALG_LEGACY = 0x4000, /** * Indicates that a normal surface list was built using a customised * algorithm. In such cases, no further details on the algorithm are * available. * * If this flag is passed to an enumeration algorithm, it will be ignored. */ NS_ALG_CUSTOM = 0x8000 }; /** * A combination of flags for types of normal surface lists. * * \ifacespython This is present, and all values in the NormalAlgFlags * enumeration type are treated as members of this NormalAlg class. */ typedef regina::Flags NormalAlg; /** * Returns the bitwise OR of the two given flags. * * @param lhs the first flag to combine. * @param rhs the second flag to combine. * @return the combination of both flags. */ inline NormalAlg operator | (NormalAlgFlags lhs, NormalAlgFlags rhs) { return NormalAlg(lhs) | rhs; } /*@}*/ } // namespace regina #endif regina-4.96/engine/surfaces/normalspec-impl.h000644 000765 000024 00000017725 12377775560 021202 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "regina-core.h" #include "surfaces/nnormalsurfacelist.h" #include "surfaces/nsstandard.h" #include "surfaces/nsquad.h" #include "surfaces/nsanstandard.h" #include "surfaces/nsquadoct.h" namespace regina { /** * Constants, typedefs and operations for working with normal (as * opposed to almost normal) surfaces. See the declaration in * nnormalsurfacelist.h for further details. * * For both normal and almost normal surfaces, we refer to different * coordinate systems by the generic names \e standard form and * \e reduced form. Standard form is where we store coordinates for all * disc types (e.g., the standard tri-quad coordinates for normal * surfaces), and reduced form is where we only store coordinates for * non-triangular disc types (e.g., the quadrilateral coordinates of * Tollefson). */ struct REGINA_API NNormalSurfaceList::NormalSpec { /** * The underlying class for vectors in standard form. */ typedef NNormalSurfaceVectorStandard StandardVector; /** * The underlying class for vectors in reduced form. */ typedef NNormalSurfaceVectorQuad ReducedVector; /** * Returns the coordinate system constant corresponding to standard form. * * This has been made a routine (not a constant) to ensure the * correct return type. Perhaps this can be changed to an enum some day... */ inline static NormalCoords standardCoords() { return NS_STANDARD; } /** * Returns the coordinate system constant corresponding to reduced form. * * This has been made a routine (not a constant) to ensure the * correct return type. Perhaps this can be changed to an enum some day... */ inline static NormalCoords reducedCoords() { return NS_QUAD; } /** * Returns the number of coordinates per tetrahedron in standard form. */ static const unsigned totalPerTet = 7; /** * Returns the number of coordinates per tetrahedron in reduced form. */ static const unsigned reducedPerTet = 3; /** * Returns the total length of a vector in standard form for the * given number of tetrahedra. */ inline static size_t stdLen(unsigned long nTet) { return 7 * nTet; } /** * Returns the total length of a vector in reduced form for the * given number of tetrahedra. */ inline static size_t redLen(unsigned long nTet) { return 3 * nTet; } /** * Returns the coordinate number in standard form that corresponds * to the given disc type within the given tetrahedron. */ inline static size_t stdPos(unsigned long tet, unsigned discType) { return 7 * tet + discType; } /** * Returns the coordinate number in reduced form that corresponds * to the given disc type within the given tetrahedron. */ inline static size_t redPos(unsigned long tet, unsigned discType) { return 3 * tet + discType; } }; /** * Constants, typedefs and operations for working with almost normal (as * opposed to almost normal) surfaces. See the declaration in * nnormalsurfacelist.h for further details. * * For both normal and almost normal surfaces, we refer to different * coordinate systems by the generic names \e standard form and * \e reduced form. Standard form is where we store coordinates for all * disc types (e.g., the standard tri-quad-oct coordinates for almost normal * surfaces), and reduced form is where we only store coordinates for * non-triangular disc types (e.g., quad-oct coordinates for almost * normal surfaces). */ struct REGINA_API NNormalSurfaceList::AlmostNormalSpec { /** * The underlying class for vectors in standard form. */ typedef NNormalSurfaceVectorANStandard StandardVector; /** * The underlying class for vectors in reduced form. */ typedef NNormalSurfaceVectorQuadOct ReducedVector; /** * Returns the coordinate system constant corresponding to standard form. * * This has been made a routine (not a constant) to ensure the * correct return type. Perhaps this can be changed to an enum some day... */ inline static NormalCoords standardCoords() { return NS_AN_STANDARD; } /** * Returns the coordinate system constant corresponding to reduced form. * * This has been made a routine (not a constant) to ensure the * correct return type. Perhaps this can be changed to an enum some day... */ inline static NormalCoords reducedCoords() { return NS_AN_QUAD_OCT; } /** * Returns the number of coordinates per tetrahedron in standard form. */ static const unsigned totalPerTet = 10; /** * Returns the number of coordinates per tetrahedron in reduced form. */ static const unsigned reducedPerTet = 6; /** * Returns the total length of a vector in standard form for the * given number of tetrahedra. */ inline static size_t stdLen(unsigned long nTet) { return 10 * nTet; } /** * Returns the total length of a vector in reduced form for the * given number of tetrahedra. */ inline static size_t redLen(unsigned long nTet) { return 6 * nTet; } /** * Returns the coordinate number in standard form that corresponds * to the given disc type within the given tetrahedron. */ inline static size_t stdPos(unsigned long tet, unsigned discType) { return 10 * tet + discType; } /** * Returns the coordinate number in reduced form that corresponds * to the given disc type within the given tetrahedron. */ inline static size_t redPos(unsigned long tet, unsigned discType) { return 6 * tet + discType; } }; } // namespace regina regina-4.96/engine/surfaces/normalspec.tcc000644 000765 000024 00000004662 12400001245 020522 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/normalspec.tcc * \brief Deprecated header. */ #warning This header is deprecated; please use normalspec-impl.h instead. #include "surfaces/normalspec-impl.h" regina-4.96/engine/surfaces/nprism.cpp000644 000765 000024 00000006335 12377776727 017744 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "surfaces/nnormalsurface.h" #include "surfaces/nprism.h" #include "triangulation/ntriangulation.h" namespace regina { std::ostream& operator << (std::ostream& out, const NPrismSpec& spec) { out << '(' << spec.tetIndex << ", " << spec.edge << ')'; return out; } NPrismSetSurface::NPrismSetSurface(const NNormalSurface& surface) { const NTriangulation* tri = surface.getTriangulation(); unsigned long nTet = tri->getNumberOfTetrahedra(); if (nTet == 0) { quadType = 0; return; } // Work out which tetrahedra contain which quad types. quadType = new signed char[nTet]; for (unsigned long tet = 0; tet < nTet; tet++) if (surface.getQuadCoord(tet, 0) != 0) quadType[tet] = 0; else if (surface.getQuadCoord(tet, 1) != 0) quadType[tet] = 1; else if (surface.getQuadCoord(tet, 2) != 0) quadType[tet] = 2; else quadType[tet] = -1; } } // namespace regina regina-4.96/engine/surfaces/nprism.h000644 000765 000024 00000020000 12377775561 017365 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/nprism.h * \brief Deals with triangular prisms defined by slicing along normal * quads in a tetrahedron. */ #ifndef __NPRISM_H #ifndef __DOXYGEN #define __NPRISM_H #endif #include #include "regina-core.h" namespace regina { /** * \weakgroup surfaces * @{ */ class NNormalSurface; /** * Specifies a single triangular prism in a tetrahedron. * * If a tetrahedron contains normal quads, slicing along these quads * splits the tetrahedron into two triangular prisms (and possibly some * additional product regions). Each triangular prism contains two of * the vertices and one of the edges of the original tetrahedron. * * \pre This class should only be used with \a embedded * normal surfaces. */ struct REGINA_API NPrismSpec { unsigned long tetIndex; /**< The index in the triangulation of the tetrahedron containing the prism. */ int edge; /**< The edge of the tetrahedron that is contained in this prism. */ /** * Creates a new uninitialised prism specifier. */ NPrismSpec(); /** * Creates a new prism specifier containing the given values. * * @param newTetIndex the index in the triangulation of the tetrahedron * containing the prism. * @param newEdge the edge of the tetrahedron that is contained in * this prism; this must be between 0 and 5 inclusive. */ NPrismSpec(unsigned long newTetIndex, int newEdge); /** * Creates a new prism specifier that is a clone of the given specifier. * * @param cloneMe the prism specifier to clone. */ NPrismSpec(const NPrismSpec& cloneMe); /** * Copies the values from the given prism specifier into this specifier. * * @param cloneMe the prism specifier whose values should be copied. * @return a reference to this prism specifier. */ NPrismSpec& operator = (const NPrismSpec& cloneMe); /** * Determines if this and the given prism specifier contain identical * information. * * @param other the prism specifier to compare with this. * @return \c true if and only if this and the given prism specifier * contain identical information. */ bool operator == (const NPrismSpec& other) const; friend std::ostream& operator << (std::ostream& out, const NPrismSpec& spec); }; /** * Writes the given prism specifier to the given output stream. * The prism specifier will be written as a pair (tetIndex, edge). * * @param out the output stream to which to write. * @param spec the prism specifier to write. * @return a reference to \a out. */ REGINA_API std::ostream& operator << (std::ostream& out, const NPrismSpec& spec); /** * Represents the set of prisms defined by slicing along all the quads * in a particular normal surface. * * Note that each tetrahedron in the underlying triangulation will supply * either zero or two prisms (depending upon whether or not it contains * any normal quads). * * \pre This class should only be used with \e embedded normal surfaces * containing no octagonal discs. * * \warning This class doesn't really do much as yet. */ class REGINA_API NPrismSetSurface { private: signed char* quadType; /**< A list of which types of normal quad are contained in which tetrahedra. Tetrahedra containing no quads at all will have quad type -1 in this array. */ public: /** * Creates a new prism set corresponding to the prisms defined * by the given normal surface. * * \pre The given normal surface is embedded and contains no * octagonal discs. * * @param surface the normal surface that defines the prisms in * this set. */ NPrismSetSurface(const NNormalSurface& surface); /** * Destroys this prism set. */ virtual ~NPrismSetSurface(); /** * Returns the quadrilateral type with which the underlying * normal surface meets the given tetrahedron. Note that the * surface might contain many quadrilateral discs of this type. * However, since the underlying surface is embedded, there * cannot be more than one such quadrilateral type. * * @param tetIndex the index in the triangulation of the * tetrahedron in which we are interested; this should be * between 0 and NTriangulation::getNumberOfTetrahedra()-1 * inclusive. * @return the quadrilateral type found within this tetrahedron. * This is 0, 1 or 2 and represents the same type parameter as is * used by NNormalSurface::getQuadCoord(). If the underlying surface * does not meet the given tetrahedron in any quadrilateral discs, * this routine returns -1. */ signed char getQuadType(unsigned long tetIndex) const; }; /*@}*/ // Inline functions for NPrismSpec inline NPrismSpec::NPrismSpec() { } inline NPrismSpec::NPrismSpec(unsigned long newTetIndex, int newEdge) : tetIndex(newTetIndex), edge(newEdge) { } inline NPrismSpec::NPrismSpec(const NPrismSpec& cloneMe) : tetIndex(cloneMe.tetIndex), edge(cloneMe.edge) { } inline NPrismSpec& NPrismSpec::operator = (const NPrismSpec& cloneMe) { tetIndex = cloneMe.tetIndex; edge = cloneMe.edge; return *this; } inline bool NPrismSpec::operator == (const NPrismSpec& other) const { return (tetIndex == other.tetIndex && edge == other.edge); } // Inline functions for NPrismSetSurface inline NPrismSetSurface::~NPrismSetSurface() { if (quadType) delete[] quadType; } inline signed char NPrismSetSurface::getQuadType(unsigned long tetIndex) const { return quadType[tetIndex]; } } // namespace regina #endif regina-4.96/engine/surfaces/nsanstandard.cpp000644 000765 000024 00000017052 12377776727 021112 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "enumerate/nenumconstraint.h" #include "surfaces/nsanstandard.h" #include "maths/nmatrixint.h" #include "maths/nrational.h" #include "triangulation/ntriangulation.h" namespace regina { NLargeInteger NNormalSurfaceVectorANStandard::getEdgeWeight( unsigned long edgeIndex, const NTriangulation* triang) const { // Find a tetrahedron next to the edge in question. const NEdgeEmbedding& emb = triang->getEdges()[edgeIndex]-> getEmbeddings().front(); long tetIndex = triang->tetrahedronIndex(emb.getTetrahedron()); int start = emb.getVertices()[0]; int end = emb.getVertices()[1]; // Add up the triangles, quads and octagons meeting that edge. // Triangles: NLargeInteger ans((*this)[10 * tetIndex + start]); ans += (*this)[10 * tetIndex + end]; // Quads: ans += (*this)[10 * tetIndex + 4 + vertexSplitMeeting[start][end][0]]; ans += (*this)[10 * tetIndex + 4 + vertexSplitMeeting[start][end][1]]; // Octagons: ans += (*this)[10 * tetIndex + 7]; ans += (*this)[10 * tetIndex + 8]; ans += (*this)[10 * tetIndex + 9]; ans += (*this)[10 * tetIndex + 7 + vertexSplit[start][end]]; return ans; } NLargeInteger NNormalSurfaceVectorANStandard::getTriangleArcs( unsigned long triIndex, int triVertex, const NTriangulation* triang) const { // Find a tetrahedron next to the triangle in question. const NTriangleEmbedding& emb = triang->getTriangles()[triIndex]-> getEmbedding(0); long tetIndex = triang->tetrahedronIndex(emb.getTetrahedron()); int vertex = emb.getVertices()[triVertex]; int backOfFace = emb.getVertices()[3]; // Add up the discs meeting that triangle in that required arc. // Triangles: NLargeInteger ans((*this)[10 * tetIndex + vertex]); // Quads: ans += (*this)[10 * tetIndex + 4 + vertexSplit[vertex][backOfFace]]; // Octagons: ans += (*this)[10 * tetIndex + 7 + vertexSplitMeeting[vertex][backOfFace][0]]; ans += (*this)[10 * tetIndex + 7 + vertexSplitMeeting[vertex][backOfFace][1]]; return ans; } NNormalSurfaceVector* NNormalSurfaceVectorANStandard::makeZeroVector( const NTriangulation* triangulation) { return new NNormalSurfaceVectorANStandard( 10 * triangulation->getNumberOfTetrahedra()); } NMatrixInt* NNormalSurfaceVectorANStandard::makeMatchingEquations( const NTriangulation* triangulation) { unsigned long nCoords = 10 * triangulation->getNumberOfTetrahedra(); // Three equations per non-boundary triangle. // F_boundary + 2 F_internal = 4 T long nEquations = 3 * (4 * long(triangulation->getNumberOfTetrahedra()) - long(triangulation->getNumberOfTriangles())); NMatrixInt* ans = new NMatrixInt(nEquations, nCoords); // Run through each internal triangle and add the corresponding three // equations. unsigned row = 0; int i; unsigned long tet0, tet1; NPerm4 perm0, perm1; for (NTriangulation::TriangleIterator fit = triangulation->getTriangles().begin(); fit != triangulation->getTriangles().end(); fit++) { if (! (*fit)->isBoundary()) { tet0 = triangulation->tetrahedronIndex( (*fit)->getEmbedding(0).getTetrahedron()); tet1 = triangulation->tetrahedronIndex( (*fit)->getEmbedding(1).getTetrahedron()); perm0 = (*fit)->getEmbedding(0).getVertices(); perm1 = (*fit)->getEmbedding(1).getVertices(); for (i=0; i<3; i++) { // Triangles: ans->entry(row, 10*tet0 + perm0[i]) += 1; ans->entry(row, 10*tet1 + perm1[i]) -= 1; // Quads: ans->entry(row, 10*tet0 + 4 + vertexSplit[perm0[i]][perm0[3]]) += 1; ans->entry(row, 10*tet1 + 4 + vertexSplit[perm1[i]][perm1[3]]) -= 1; // Octagons: ans->entry(row, 10*tet0 + 7 + vertexSplitMeeting[perm0[i]][perm0[3]][0]) += 1; ans->entry(row, 10*tet1 + 7 + vertexSplitMeeting[perm1[i]][perm1[3]][0]) -= 1; ans->entry(row, 10*tet0 + 7 + vertexSplitMeeting[perm0[i]][perm0[3]][1]) += 1; ans->entry(row, 10*tet1 + 7 + vertexSplitMeeting[perm1[i]][perm1[3]][1]) -= 1; row++; } } } return ans; } NEnumConstraintList* NNormalSurfaceVectorANStandard::makeEmbeddedConstraints( const NTriangulation* triangulation) { // At most one quad/oct per tetrahedron. // Also at most one oct type overall. NEnumConstraintList* ans = new NEnumConstraintList( triangulation->getNumberOfTetrahedra() + 1); unsigned base = 0; for (unsigned c = 1; c < ans->size(); ++c) { (*ans)[c].insert((*ans)[c].end(), base + 4); (*ans)[c].insert((*ans)[c].end(), base + 5); (*ans)[c].insert((*ans)[c].end(), base + 6); (*ans)[c].insert((*ans)[c].end(), base + 7); (*ans)[c].insert((*ans)[c].end(), base + 8); (*ans)[c].insert((*ans)[c].end(), base + 9); (*ans)[0].insert((*ans)[0].end(), base + 7); (*ans)[0].insert((*ans)[0].end(), base + 8); (*ans)[0].insert((*ans)[0].end(), base + 9); base += 10; } return ans; } } // namespace regina regina-4.96/engine/surfaces/nsanstandard.h000644 000765 000024 00000014624 12377775563 020556 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/nsanstandard.h * \brief Implements almost normal surface vectors using standard * triangle-quad-oct coordinates. */ #ifndef __NSANSTANDARD_H #ifndef __DOXYGEN #define __NSANSTANDARD_H #endif #include "regina-core.h" #include "surfaces/nnormalsurface.h" namespace regina { class NMatrixInt; class NNormalSurfaceVectorANStandard; /** * \weakgroup surfaces * @{ */ /** * Stores information about standard almost normal coordinates. * See the general NormalInfo template notes for further details. * * \ifacespython Not present. */ template <> struct NormalInfo { typedef NNormalSurfaceVectorANStandard Class; typedef NormalInfo Standard; typedef NormalInfo Reduced; inline static const char* name() { return "Standard almost normal (tri-quad-oct)"; } enum { almostNormal = 1, spun = 0, oriented = 0 }; }; /** * An almost normal surface vector using standard triangle-quad-oct * coordinates. * * If there are \a t tetrahedra in the underlying * triangulation, there must be precisely 10t coordinates. * The first ten coordinates will be for the first tetrahedron, the * next ten for the second tetrahedron and so on. For each * tetrahedron, the first four represent the number of * triangular discs about vertex 0, 1, 2 and 3, the next * three represent the number of quadrilateral discs of type 0, * 1 and 2 (see NNormalSurface::getQuadCoord()) and the final three * represent the number of octagonal discs of type 0, 1 and 2 (see * NNormalSurface::getOctCoord()). * * \ifacespython Not present. */ class REGINA_API NNormalSurfaceVectorANStandard : public NNormalSurfaceVector { REGINA_NORMAL_SURFACE_FLAVOUR(NNormalSurfaceVectorANStandard, NS_AN_STANDARD) public: /** * Creates a new vector all of whose entries are initialised to * zero. * * @param length the number of elements in the new vector. */ NNormalSurfaceVectorANStandard(size_t length); /** * Creates a new vector that is a clone of the given vector. * * @param cloneMe the vector to clone. */ NNormalSurfaceVectorANStandard(const NVector& cloneMe); virtual NLargeInteger getTriangleCoord(unsigned long tetIndex, int vertex, const NTriangulation* triang) const; virtual NLargeInteger getQuadCoord(unsigned long tetIndex, int quadType, const NTriangulation* triang) const; virtual NLargeInteger getOctCoord(unsigned long tetIndex, int octType, const NTriangulation* triang) const; virtual NLargeInteger getEdgeWeight(unsigned long edgeIndex, const NTriangulation* triang) const; virtual NLargeInteger getTriangleArcs(unsigned long triIndex, int triVertex, const NTriangulation* triang) const; static NNormalSurfaceVector* makeZeroVector( const NTriangulation* triangulation); static NMatrixInt* makeMatchingEquations( const NTriangulation* triangulation); static NEnumConstraintList* makeEmbeddedConstraints( const NTriangulation* triangulation); }; /*@}*/ // Inline functions for NNormalSurfaceVectorANStandard inline NNormalSurfaceVectorANStandard::NNormalSurfaceVectorANStandard( size_t length) : NNormalSurfaceVector(length) { } inline NNormalSurfaceVectorANStandard::NNormalSurfaceVectorANStandard( const NVector& cloneMe) : NNormalSurfaceVector(cloneMe) { } inline NLargeInteger NNormalSurfaceVectorANStandard::getTriangleCoord( unsigned long tetIndex, int vertex, const NTriangulation*) const { return (*this)[10 * tetIndex + vertex]; } inline NLargeInteger NNormalSurfaceVectorANStandard::getQuadCoord( unsigned long tetIndex, int quadType, const NTriangulation*) const { return (*this)[10 * tetIndex + 4 + quadType]; } inline NLargeInteger NNormalSurfaceVectorANStandard::getOctCoord( unsigned long tetIndex, int octType, const NTriangulation*) const { return (*this)[10 * tetIndex + 7 + octType]; } } // namespace regina #endif regina-4.96/engine/surfaces/nsmirrored.h000644 000765 000024 00000023400 12377775565 020254 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/nsmirrored.h * \brief Provides a normal surface vector that is mirrored in another * coordinate system to avoid frequent lengthy calculations. */ #ifndef __NSMIRRORED_H #ifndef __DOXYGEN #define __NSMIRRORED_H #endif #include "regina-core.h" #include "surfaces/nnormalsurface.h" namespace regina { /** * \weakgroup surfaces * @{ */ /** * A normal surface vector that is mirrored in another coordinate system * to avoid frequent lengthy calculations. When it is difficult to * convert from the native coordinate system to standard tri-quad-oct * coordinates, use this as a base class. The conversion of the entire * vector will be done once only, and future coordinate lookups will be * performed through the pre-converted mirror vector. * * Once the first coordinate lookup has taken place (via * getTriangleCoord() or the like), this vector may * not change! The mirror will be created at this point and will * not change, so if the native coordinates change further then any * requests passed to the mirror will return incorrect results. * * Subclasses need not implement any of the coordinate lookup routines. * The default implementation will be to pass the lookup to the mirror. * If any particular lookup can be done more efficiently in the native * coordinate system, the corresponding routine should be overridden. * * Subclasses must however implement the routine makeMirror() which creates * the alternate mirror vector from this vector. * * Note that cloning a vector of this class will \e not clone the * mirror. Thus a clone may be safely modified before its first * coordinate lookup routine is called. * * \todo \prob Allow modification of the vector by overwriting * setValue(); this will require documentation changes in both this * class and in NNormalSurfaceVector. * * \ifacespython Not present. */ class REGINA_API NNormalSurfaceVectorMirrored : public NNormalSurfaceVector { private: NNormalSurfaceVector* mirror; /**< The mirror vector. */ public: /** * Creates a new vector all of whose entries are initialised to * zero. * * @param length the number of elements in the new vector. */ NNormalSurfaceVectorMirrored(size_t length); /** * Creates a new vector that is a clone of the given vector. * * @param cloneMe the vector to clone. */ NNormalSurfaceVectorMirrored(const NVector& cloneMe); /** * Creates a new vector that is a clone of the given vector. * * @param cloneMe the vector to clone. */ NNormalSurfaceVectorMirrored(const NNormalSurfaceVectorMirrored& cloneMe); /** * Destroys this vector and its mirror if appropriate. */ virtual ~NNormalSurfaceVectorMirrored(); /** * Creates a new mirror vector corresponding to this vector. * The mirror vector should represent the same normal surface as * this vector, and should have fast coordinate lookup routines * (getTriangleCoord(), getQuadCord() and so on). It is * recommended that the mirror vector be an * NNormalSurfaceVectorStandard or an NNormalSurfaceVectorANStandard. * * @param triang the triangulation in which this normal surface * lives. * @return a newly created mirror vector. */ virtual NNormalSurfaceVector* makeMirror(const NTriangulation* triang) const = 0; virtual NLargeInteger getTriangleCoord(unsigned long tetIndex, int vertex, const NTriangulation* triang) const; virtual NLargeInteger getOrientedTriangleCoord(unsigned long tetIndex, int vertex, const NTriangulation* triang, bool orientation) const; virtual NLargeInteger getQuadCoord(unsigned long tetIndex, int quadType, const NTriangulation* triang) const; virtual NLargeInteger getOrientedQuadCoord(unsigned long tetIndex, int quadType, const NTriangulation* triang, bool orientation) const; virtual NLargeInteger getOctCoord(unsigned long tetIndex, int octType, const NTriangulation* triang) const; virtual NLargeInteger getEdgeWeight(unsigned long edgeIndex, const NTriangulation* triang) const; virtual NLargeInteger getTriangleArcs(unsigned long triIndex, int triVertex, const NTriangulation* triang) const; }; /*@}*/ // Inline functions for NNormalSurfaceVectorMirrored inline NNormalSurfaceVectorMirrored::NNormalSurfaceVectorMirrored( size_t length) : NNormalSurfaceVector(length), mirror(0) { } inline NNormalSurfaceVectorMirrored::NNormalSurfaceVectorMirrored( const NVector& cloneMe) : NNormalSurfaceVector(cloneMe), mirror(0) { } inline NNormalSurfaceVectorMirrored::NNormalSurfaceVectorMirrored( const NNormalSurfaceVectorMirrored& cloneMe) : NNormalSurfaceVector(cloneMe), mirror(0) { } inline NNormalSurfaceVectorMirrored::~NNormalSurfaceVectorMirrored() { if (mirror) delete mirror; } inline NLargeInteger NNormalSurfaceVectorMirrored::getTriangleCoord( unsigned long tetIndex, int vertex, const NTriangulation* triang) const { if (! mirror) const_cast(this)->mirror = makeMirror(triang); return mirror->getTriangleCoord(tetIndex, vertex, triang); } inline NLargeInteger NNormalSurfaceVectorMirrored::getOrientedTriangleCoord( unsigned long tetIndex, int vertex, const NTriangulation* triang, bool orientation) const { if (! mirror) const_cast(this)->mirror = makeMirror(triang); return mirror->getOrientedTriangleCoord(tetIndex, vertex, triang, orientation); } inline NLargeInteger NNormalSurfaceVectorMirrored::getQuadCoord( unsigned long tetIndex, int quadType, const NTriangulation* triang) const { if (! mirror) const_cast(this)->mirror = makeMirror(triang); return mirror->getQuadCoord(tetIndex, quadType, triang); } inline NLargeInteger NNormalSurfaceVectorMirrored::getOrientedQuadCoord( unsigned long tetIndex, int quadType, const NTriangulation* triang, bool orientation) const { if (! mirror) const_cast(this)->mirror = makeMirror(triang); return mirror->getOrientedQuadCoord(tetIndex, quadType, triang, orientation); } inline NLargeInteger NNormalSurfaceVectorMirrored::getOctCoord( unsigned long tetIndex, int octType, const NTriangulation* triang) const { if (! mirror) const_cast(this)->mirror = makeMirror(triang); return mirror->getOctCoord(tetIndex, octType, triang); } inline NLargeInteger NNormalSurfaceVectorMirrored::getEdgeWeight( unsigned long edgeIndex, const NTriangulation* triang) const { if (! mirror) const_cast(this)->mirror = makeMirror(triang); return mirror->getEdgeWeight(edgeIndex, triang); } inline NLargeInteger NNormalSurfaceVectorMirrored::getTriangleArcs( unsigned long triIndex, int triVertex, const NTriangulation* triang) const { if (! mirror) const_cast(this)->mirror = makeMirror(triang); return mirror->getTriangleArcs(triIndex, triVertex, triang); } } // namespace regina #endif regina-4.96/engine/surfaces/nsoriented.cpp000644 000765 000024 00000016657 12377776730 020610 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "enumerate/nenumconstraint.h" #include "surfaces/nsoriented.h" #include "maths/nmatrixint.h" #include "maths/nrational.h" #include "triangulation/ntriangulation.h" namespace regina { NLargeInteger NNormalSurfaceVectorOriented::getEdgeWeight( unsigned long edgeIndex, const NTriangulation* triang) const { // Find a tetrahedron next to the edge in question. const NEdgeEmbedding& emb = triang->getEdges()[edgeIndex]-> getEmbeddings().front(); long tetIndex = triang->tetrahedronIndex(emb.getTetrahedron()); int start = emb.getVertices()[0]; int end = emb.getVertices()[1]; // Add up the triangles and quads meeting that edge. // Triangles: NLargeInteger ans(getTriangleCoord(tetIndex,start,triang)); ans += getTriangleCoord(tetIndex,end,triang); // Quads: ans += getQuadCoord(tetIndex,vertexSplitMeeting[start][end][0],triang); ans += getQuadCoord(tetIndex,vertexSplitMeeting[start][end][1],triang); return ans; } NLargeInteger NNormalSurfaceVectorOriented::getTriangleArcs( unsigned long triIndex, int triVertex, const NTriangulation* triang) const { // Find a tetrahedron next to the triangle in question. const NTriangleEmbedding& emb = triang->getTriangles()[triIndex]-> getEmbedding(0); long tetIndex = triang->tetrahedronIndex(emb.getTetrahedron()); int vertex = emb.getVertices()[triVertex]; int backOfFace = emb.getVertices()[3]; // Add up the triangles and quads meeting that triangle in the required arc. // Triangles: NLargeInteger ans(getTriangleCoord(tetIndex,vertex,triang)); // Quads: ans += getQuadCoord(tetIndex,vertexSplit[vertex][backOfFace],triang); return ans; } NNormalSurfaceVector* NNormalSurfaceVectorOriented::makeZeroVector( const NTriangulation* triangulation) { return new NNormalSurfaceVectorOriented( 14 * triangulation->getNumberOfTetrahedra()); } NMatrixInt* NNormalSurfaceVectorOriented::makeMatchingEquations( const NTriangulation* triangulation) { unsigned long nCoords = 14 * triangulation->getNumberOfTetrahedra(); // Six equations per non-boundary triangle. // F_boundary + 2 F_internal = 4 T long nEquations = 6 * (4 * long(triangulation->getNumberOfTetrahedra()) - long(triangulation->getNumberOfTriangles())); NMatrixInt* ans = new NMatrixInt(nEquations, nCoords); // Run through each internal triangle and add the corresponding three // equations. unsigned row = 0; int i; unsigned long tet0, tet1; NPerm4 perm0, perm1; bool natural; for (NTriangulation::TriangleIterator fit = triangulation->getTriangles().begin(); fit != triangulation->getTriangles().end(); fit++) { if (! (*fit)->isBoundary()) { tet0 = triangulation->tetrahedronIndex( (*fit)->getEmbedding(0).getTetrahedron()); tet1 = triangulation->tetrahedronIndex( (*fit)->getEmbedding(1).getTetrahedron()); perm0 = (*fit)->getEmbedding(0).getVertices(); perm1 = (*fit)->getEmbedding(1).getVertices(); for (i=0; i<3; i++) { // row: oriented towards the vertex of the face // row+1: oriented towards the opposite face // Triangles: ans->entry(row, 14*tet0 + 2*perm0[i]) += 1; ans->entry(row+1, 14*tet0 + 2*perm0[i] + 1) += 1; ans->entry(row, 14*tet1 + 2*perm1[i]) -= 1; ans->entry(row+1, 14*tet1 + 2*perm1[i] + 1) -= 1; // Quads: natural = (perm0[i] == 0 || perm0[3] == 0); ans->entry(row, 14*tet0 + 8 + 2*vertexSplit[perm0[i]][perm0[3]] + (natural ? 0 : 1)) += 1; ans->entry(row+1, 14*tet0 + 8 + 2*vertexSplit[perm0[i]][perm0[3]] + (natural ? 1 : 0)) += 1; natural = (perm1[i] == 0 || perm1[3] == 0); ans->entry(row, 14*tet1 + 8 + 2*vertexSplit[perm1[i]][perm1[3]] + (natural ? 0 : 1)) -= 1; ans->entry(row+1, 14*tet1 + 8 + 2*vertexSplit[perm1[i]][perm1[3]] + (natural ? 1 : 0)) -= 1; row+=2; } } } return ans; } NEnumConstraintList* NNormalSurfaceVectorOriented::makeEmbeddedConstraints( const NTriangulation* triangulation) { // TODO: Must be a neater way of doing this, but might mean re-working // bitmasks. NEnumConstraintList* ans = new NEnumConstraintList( 8 * triangulation->getNumberOfTetrahedra()); unsigned base = 0; unsigned c = 0; while (c < ans->size()) { for (unsigned d = 0; d < 2; d++) { for (unsigned e = 0; e < 2; e++) { for (unsigned f = 0; f < 2; f++) { (*ans)[c].insert((*ans)[c].end(), base + 8 + d); (*ans)[c].insert((*ans)[c].end(), base + 10 + e); (*ans)[c].insert((*ans)[c].end(), base + 12 + f); ++c; } } } base += 14; } return ans; } } // namespace regina regina-4.96/engine/surfaces/nsoriented.h000644 000765 000024 00000016436 12377775567 020257 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/nsoriented.h * \brief Implements normal surface vectors using transversly oriented * normal surface coordinates.*/ #ifndef __NSORIENTED_H #ifndef __DOXYGEN #define __NSORIENTED_H #endif #include "regina-core.h" #include "surfaces/nnormalsurface.h" namespace regina { class NMatrixInt; class NNormalSurfaceVectorOriented; /** * \weakgroup surfaces * @{ */ /** * Stores information about transversely oriented standard normal coordinates. * See the general NormalInfo template notes for further details. * * \ifacespython Not present. */ template <> struct NormalInfo { typedef NNormalSurfaceVectorOriented Class; typedef NormalInfo Standard; typedef NormalInfo Reduced; inline static const char* name() { return "Transversely oriented standard normal"; } enum { almostNormal = 0, spun = 0, oriented = 1 }; }; /** * A normal surface vector using transversely oriented standard * (triangle-quad) coordinates. * * If there are \a t tetrahedra in the underlying * triangulation, there must be precisely 14t coordinates. * For each \a i, coordinates 2i and 2i+1 represent * the \c true and \c false orientations for coordinate \a i in the * 7t-dimensional standard coordinate system. See * NNormalSurfaceVectorStandard for further details. * * \warning Support for transversely oriented normal surfaces is still * experimental, and some features \b will break (e.g., testing * connectedness, disjointness or embeddedness). * * \ifacespython Not present. */ class REGINA_API NNormalSurfaceVectorOriented : public NNormalSurfaceVector { REGINA_NORMAL_SURFACE_FLAVOUR(NNormalSurfaceVectorOriented, NS_ORIENTED) public: /** * Creates a new vector all of whose entries are initialised to * zero. * * @param length the number of elements in the new vector. */ NNormalSurfaceVectorOriented(size_t length); /** * Creates a new vector that is a clone of the given vector. * * @param cloneMe the vector to clone. */ NNormalSurfaceVectorOriented(const NVector& cloneMe); virtual NLargeInteger getTriangleCoord(unsigned long tetIndex, int vertex, const NTriangulation* triang) const; virtual NLargeInteger getQuadCoord(unsigned long tetIndex, int quadType, const NTriangulation* triang) const; virtual NLargeInteger getOrientedTriangleCoord(unsigned long tetIndex, int vertex, const NTriangulation* triang, bool orientation) const; virtual NLargeInteger getOrientedQuadCoord(unsigned long tetIndex, int quadType, const NTriangulation* triang, bool orientation) const; virtual NLargeInteger getOctCoord(unsigned long tetIndex, int octType, const NTriangulation* triang) const; virtual NLargeInteger getEdgeWeight(unsigned long edgeIndex, const NTriangulation* triang) const; virtual NLargeInteger getTriangleArcs(unsigned long triIndex, int triVertex, const NTriangulation* triang) const; static NNormalSurfaceVector* makeZeroVector( const NTriangulation* triangulation); static NMatrixInt* makeMatchingEquations( const NTriangulation* triangulation); static NEnumConstraintList* makeEmbeddedConstraints( const NTriangulation* triangulation); }; /*@}*/ // Inline functions for NNormalSurfaceVectorOriented inline NNormalSurfaceVectorOriented::NNormalSurfaceVectorOriented( size_t length) : NNormalSurfaceVector(length) { } inline NNormalSurfaceVectorOriented::NNormalSurfaceVectorOriented( const NVector& cloneMe) : NNormalSurfaceVector(cloneMe) { } inline NLargeInteger NNormalSurfaceVectorOriented::getTriangleCoord( unsigned long tetIndex, int vertex, const NTriangulation* tri) const { return getOrientedTriangleCoord(tetIndex,vertex,tri, true) + getOrientedTriangleCoord(tetIndex,vertex,tri, false); } inline NLargeInteger NNormalSurfaceVectorOriented::getQuadCoord( unsigned long tetIndex, int quadType, const NTriangulation* tri) const { return getOrientedQuadCoord(tetIndex,quadType,tri, true) + getOrientedQuadCoord(tetIndex,quadType,tri, false); } inline NLargeInteger NNormalSurfaceVectorOriented::getOrientedTriangleCoord( unsigned long tetIndex, int vertex, const NTriangulation*, bool orientation) const { return (*this)[14 * tetIndex + 2 * vertex + (orientation ? 0 : 1)]; } inline NLargeInteger NNormalSurfaceVectorOriented::getOrientedQuadCoord( unsigned long tetIndex, int quadType, const NTriangulation*, bool orientation) const { return (*this)[14 * tetIndex + 8 + 2 * quadType + (orientation ? 0 : 1)]; } inline NLargeInteger NNormalSurfaceVectorOriented::getOctCoord( unsigned long, int, const NTriangulation*) const { return zero; } } // namespace regina #endif regina-4.96/engine/surfaces/nsorientedquad.cpp000644 000765 000024 00000036740 12377776731 021457 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include "enumerate/nenumconstraint.h" #include "surfaces/nsorientedquad.h" #include "surfaces/nsoriented.h" #include "maths/nmatrixint.h" #include "maths/nrational.h" #include "triangulation/ntriangulation.h" namespace regina { NNormalSurfaceVector* NNormalSurfaceVectorOrientedQuad::makeZeroVector( const NTriangulation* triangulation) { return new NNormalSurfaceVectorOrientedQuad( 6 * triangulation->getNumberOfTetrahedra()); } NMatrixInt* NNormalSurfaceVectorOrientedQuad::makeMatchingEquations( const NTriangulation* triangulation) { unsigned long nCoords = 6 * triangulation->getNumberOfTetrahedra(); // Two equation per non-boundary edge. long nEquations = 2*long(triangulation->getNumberOfEdges()); for (NTriangulation::BoundaryComponentIterator bit = triangulation-> getBoundaryComponents().begin(); bit != triangulation->getBoundaryComponents().end(); bit++) nEquations -= 2*(*bit)->getNumberOfEdges(); NMatrixInt* ans = new NMatrixInt(nEquations, nCoords); unsigned long row = 0; // Run through each internal edge and add the corresponding // equation. std::deque::const_iterator embit; NPerm4 perm; unsigned long tetIndex; bool flip; for (NTriangulation::EdgeIterator eit = triangulation->getEdges().begin(); eit != triangulation->getEdges().end(); eit++) { if (! (*eit)->isBoundary()) { for (embit = (*eit)->getEmbeddings().begin(); embit != (*eit)->getEmbeddings().end(); embit++) { tetIndex = triangulation->tetrahedronIndex( (*embit).getTetrahedron()); perm = (*embit).getVertices(); flip = (perm[0] == 0 || perm[2] == 0); ans->entry(row, 6 * tetIndex + 2*vertexSplit[perm[0]][perm[2]] + (flip ? 0 : 1)) += 1; ans->entry(row+1, 6 * tetIndex + 2*vertexSplit[perm[0]][perm[2]] + (flip ? 1 : 0)) += 1; flip = (perm[0] == 0 || perm[3] == 0); ans->entry(row, 6 * tetIndex + 2*vertexSplit[perm[0]][perm[3]] + (flip ? 0 : 1)) -= 1; ans->entry(row+1, 6 * tetIndex + 2*vertexSplit[perm[0]][perm[3]] + (flip ? 1 : 0)) -= 1; } row+=2; } } return ans; } NEnumConstraintList* NNormalSurfaceVectorOrientedQuad::makeEmbeddedConstraints( const NTriangulation* triangulation) { NEnumConstraintList* ans = new NEnumConstraintList( 8 * triangulation->getNumberOfTetrahedra()); unsigned base = 0; unsigned c = 0; while (c < ans->size()) { for (int a = 0 ; a < 2; a++) { for (int b = 0 ; b < 2; b++) { for (int d = 0 ; d < 2; d++) { (*ans)[c].insert((*ans)[c].end(), base + a); (*ans)[c].insert((*ans)[c].end(), base + b + 2); (*ans)[c].insert((*ans)[c].end(), base + d + 4); ++c; } } } base += 6; } return ans; } namespace { /** * A structure representing a particular end of an edge. */ struct EdgeEnd { NEdge* edge; /**< The edge under consideration. */ int end; /**< The end of the edge under consideration; this is 0 or 1. */ EdgeEnd() {} EdgeEnd(NEdge* newEdge, int newEnd) : edge(newEdge), end(newEnd) {} EdgeEnd(const EdgeEnd& cloneMe) : edge(cloneMe.edge), end(cloneMe.end) {} void operator = (const EdgeEnd& cloneMe) { edge = cloneMe.edge; end = cloneMe.end; } }; } NNormalSurfaceVector* NNormalSurfaceVectorOrientedQuad::makeMirror( const NTriangulation* triang) const { // We're going to do this by wrapping around each edge and seeing // what comes. unsigned long nRows = 14 * triang->getNumberOfTetrahedra(); NNormalSurfaceVectorOriented* ans = new NNormalSurfaceVectorOriented(nRows); // Set every triangular coordinate in the answer to infinity. // For coordinates about vertices not enjoying infinitely many discs, // infinity will mean "unknown". unsigned long row; int i; for (row = 0; row < nRows; row+=14) for (i = 0; i < 8; i++) ans->setElement(row + i, NLargeInteger::infinity); for (row = 0; 14 * row < nRows; row++) for (i = 0; i < 6; i++) ans->setElement(14 * row + 8 + i, (*this)[6 * row + i]); for (int orient = 0; orient < 2; ++orient) { // Run through the vertices and work out the triangular coordinates // about each vertex in turn. // // If orient = 0 or 1, we look at triangular discs oriented towards // or away from the vertex respetively. std::set usedEdges[2]; // usedEdges[i] contains the edges for which we have already // examined end i. NLargeInteger min; // The minimum coordinate that has been assigned about this // vertex. std::deque examine; bool broken; // Are the matching equations broken about this edge end? int end; NEdge* edge; EdgeEnd current; std::vector::const_iterator vembit; std::deque::const_iterator eembit, backupit, endit, beginit; NTetrahedron* tet; NPerm4 tetPerm, adjPerm; unsigned long tetIndex, adjIndex; NLargeInteger expect; for (NTriangulation::VertexIterator vit = triang->getVertices().begin(); vit != triang->getVertices().end(); vit++) { usedEdges[0].clear(); usedEdges[1].clear(); examine.clear(); broken = false; // Pick some triangular disc and set it to zero. const NVertexEmbedding& vemb = (*vit)->getEmbedding(0); row = 14 * triang->tetrahedronIndex(vemb.getTetrahedron()) + 2 * vemb.getVertex() + orient; ans->setElement(row, NLargeInteger::zero); min = NLargeInteger::zero; // Mark the three surrounding edge ends for examination. for (i=0; i<4; i++) { if (i == vemb.getVertex()) continue; edge = vemb.getTetrahedron()->getEdge( NEdge::edgeNumber[vemb.getVertex()][i]); end = vemb.getTetrahedron()->getEdgeMapping( NEdge::edgeNumber[vemb.getVertex()][i])[0] == i ? 1 : 0; if (usedEdges[end].insert(edge).second) examine.push_back(EdgeEnd(edge, end)); } // Cycle through edge ends until we are finished or until the // matching equations are broken. Each time we pick a value for // a coordinate, add the corresponding nearby edge ends to the // list of edge ends to examine. while ((! broken) && (! examine.empty())) { current = examine.front(); examine.pop_front(); // Run around this edge end. // We know there is a pre-chosen coordinate somewhere; run // forwards and find this. beginit = current.edge->getEmbeddings().begin(); endit = current.edge->getEmbeddings().end(); for (eembit = beginit; eembit != endit; eembit++) if (! (*ans)[14 * triang->tetrahedronIndex( (*eembit).getTetrahedron()) + 2 * (*eembit).getVertices()[current.end] + orient].isInfinite()) break; // We are now at the first pre-chosen coordinate about this // vertex. Run backwards from here and fill in all the // holes. backupit = eembit; adjPerm = (*eembit).getVertices(); adjIndex = triang->tetrahedronIndex((*eembit).getTetrahedron()); while (eembit != beginit) { eembit--; // Work out the coordinate for the disc type at eembit. tet = (*eembit).getTetrahedron(); tetPerm = (*eembit).getVertices(); tetIndex = triang->tetrahedronIndex(tet); expect = (*ans)[14 * adjIndex + 2 * adjPerm[current.end] + orient] + (*ans)[14 * adjIndex + 8 + 2 * vertexSplit[adjPerm[3]][adjPerm[current.end]] + ((adjPerm[current.end] == 0 || adjPerm[3] == 0) ? orient : (1 - orient))] - (*ans)[14 * tetIndex + 8 + 2 * vertexSplit[tetPerm[2]][tetPerm[current.end]] + ((tetPerm[current.end] == 0 || tetPerm[2] == 0) ? orient : (1 - orient))]; ans->setElement(14 * tetIndex + 2 * tetPerm[current.end] + orient, expect); if (expect < min) min = expect; // Remember to examine the new edge end if appropriate. edge = tet->getEdge( NEdge::edgeNumber[tetPerm[2]][tetPerm[current.end]]); end = tet->getEdgeMapping( NEdge::edgeNumber[tetPerm[2]][tetPerm[current.end]])[0] == tetPerm[2] ? 1 : 0; if (usedEdges[end].insert(edge).second) examine.push_back(EdgeEnd(edge, end)); adjPerm = tetPerm; adjIndex = tetIndex; } // Now move forwards from the original first pre-chosen // coordinate and fill in the holes from here onwards, // always checking to ensure the // matching equations have not been broken. eembit = backupit; adjPerm = (*eembit).getVertices(); adjIndex = triang->tetrahedronIndex((*eembit).getTetrahedron()); for (eembit++; eembit != endit; eembit++) { // Work out the coordinate for the disc type at eembit. tet = (*eembit).getTetrahedron(); tetPerm = (*eembit).getVertices(); tetIndex = triang->tetrahedronIndex(tet); expect = (*ans)[14 * adjIndex + 2 * adjPerm[current.end] + orient] + (*ans)[14 * adjIndex + 8 + 2 * vertexSplit[adjPerm[2]][adjPerm[current.end]] + ((adjPerm[current.end] == 0 || adjPerm[2] == 0) ? orient : (1 - orient))] - (*ans)[14 * tetIndex + 8 + 2 * vertexSplit[tetPerm[3]][tetPerm[current.end]] + ((tetPerm[current.end] == 0 || tetPerm[3] == 0) ? orient : (1 - orient))]; row = 14 * tetIndex + 2 * tetPerm[current.end] + orient; if ((*ans)[row].isInfinite()) { ans->setElement(row, expect); if (expect < min) min = expect; // Remember to examine the new edge end if appropriate. edge = tet->getEdge( NEdge::edgeNumber[tetPerm[3]][tetPerm[current.end]]); end = tet->getEdgeMapping( NEdge::edgeNumber[tetPerm[3]][tetPerm[current.end]])[0] == tetPerm[3] ? 1 : 0; if (usedEdges[end].insert(edge).second) examine.push_back(EdgeEnd(edge, end)); } else { // This coordinate has already been set. // Make sure it's the same value! if ((*ans)[row] != expect) { broken = true; break; } } adjPerm = tetPerm; adjIndex = tetIndex; } } // If the matching equations were broken, set every coordinate // to infinity. Otherwise subtract min from every coordinate to // make the values as small as possible. for (vembit = (*vit)->getEmbeddings().begin(); vembit != (*vit)->getEmbeddings().end(); vembit++) { row = 14 * triang->tetrahedronIndex((*vembit).getTetrahedron()) + 2 * (*vembit).getVertex() + orient; if (broken) ans->setElement(row, NLargeInteger::infinity); else ans->setElement(row, (*ans)[row] - min); } } } // Note that there should be no need to remove common factors since // the quad coordinates have not changed and in theory they already // had gcd=1. return ans; } } // namespace regina regina-4.96/engine/surfaces/nsorientedquad.h000644 000765 000024 00000015235 12377775570 021120 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/nsorientedquad.h * \brief Implements normal surface vectors using * transversely oriented quad coordinates. */ #ifndef __NSORIENTEDQUAD_H #ifndef __DOXYGEN #define __NSORIENTEDQUAD_H #endif #include "regina-core.h" #include "surfaces/nsmirrored.h" namespace regina { class NMatrixInt; class NNormalSurfaceVectorOrientedQuad; /** * \weakgroup surfaces * @{ */ /** * Stores information about transversely oriented quad normal coordinates. * See the general NormalInfo template notes for further details. * * \ifacespython Not present. */ template <> struct NormalInfo { typedef NNormalSurfaceVectorOrientedQuad Class; typedef NormalInfo Standard; typedef NormalInfo Reduced; inline static const char* name() { return "Transversely oriented quad normal"; } enum { almostNormal = 0, spun = 1, oriented = 1 }; }; /** * A normal surface vector using transversely oriented quadrilateral * coordinates. * * If there are \a t tetrahedra in the underlying * triangulation, there must be precisely 6t coordinates. * For each \a i, coordinates 2i and 2i+1 represent * the \c true and \c false orientations for coordinate \a i in the * 3t-dimensional quadrilateral coordinate system. See * NNormalSurfaceVectorQuad for further details. * * \warning Support for transversely oriented normal surfaces is still * experimental, and some features \b will break (e.g., testing * connectedness, disjointness or embeddedness). * * \ifacespython Not present. */ class REGINA_API NNormalSurfaceVectorOrientedQuad : public NNormalSurfaceVectorMirrored { REGINA_NORMAL_SURFACE_FLAVOUR(NNormalSurfaceVectorOrientedQuad, NS_ORIENTED_QUAD) public: /** * Creates a new vector all of whose entries are initialised to * zero. * * @param length the number of elements in the new vector. */ NNormalSurfaceVectorOrientedQuad(size_t length); /** * Creates a new vector that is a clone of the given vector. * * @param cloneMe the vector to clone. */ NNormalSurfaceVectorOrientedQuad(const NVector& cloneMe); virtual NNormalSurfaceVector* makeMirror(const NTriangulation* triang) const; virtual const NVertex* isVertexLink(const NTriangulation* triang) const; virtual NLargeInteger getQuadCoord(unsigned long tetIndex, int quadType, const NTriangulation* triang) const; virtual NLargeInteger getOrientedQuadCoord(unsigned long tetIndex, int quadType, const NTriangulation* triang, bool orientation) const; virtual NLargeInteger getOctCoord(unsigned long tetIndex, int octType, const NTriangulation* triang) const; static NNormalSurfaceVector* makeZeroVector( const NTriangulation* triangulation); static NMatrixInt* makeMatchingEquations( const NTriangulation* triangulation); static NEnumConstraintList* makeEmbeddedConstraints( const NTriangulation* triangulation); }; /*@}*/ // Inline functions for NNormalSurfaceVectorOrientedQuad inline NNormalSurfaceVectorOrientedQuad::NNormalSurfaceVectorOrientedQuad( size_t length) : NNormalSurfaceVectorMirrored(length) { } inline NNormalSurfaceVectorOrientedQuad::NNormalSurfaceVectorOrientedQuad( const NVector& cloneMe) : NNormalSurfaceVectorMirrored(cloneMe) { } inline NLargeInteger NNormalSurfaceVectorOrientedQuad::getQuadCoord( unsigned long tetIndex, int quadType, const NTriangulation* tri) const { return getOrientedQuadCoord(tetIndex, quadType, tri, true) + getOrientedQuadCoord(tetIndex, quadType, tri, false); } inline NLargeInteger NNormalSurfaceVectorOrientedQuad::getOrientedQuadCoord( unsigned long tetIndex, int quadType, const NTriangulation*, bool orientation) const { return (*this)[6 * tetIndex + 2 * quadType + (orientation ? 0 : 1)]; } inline const NVertex* NNormalSurfaceVectorOrientedQuad::isVertexLink( const NTriangulation*) const { // Quad space does not contain vertex links at all. return 0; } inline NLargeInteger NNormalSurfaceVectorOrientedQuad::getOctCoord( unsigned long, int, const NTriangulation*) const { return zero; } } // namespace regina #endif regina-4.96/engine/surfaces/nsquad.cpp000644 000765 000024 00000032406 12377776732 017721 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include "enumerate/nenumconstraint.h" #include "surfaces/nsquad.h" #include "surfaces/nsstandard.h" #include "maths/nmatrixint.h" #include "maths/nrational.h" #include "triangulation/ntriangulation.h" namespace regina { NNormalSurfaceVector* NNormalSurfaceVectorQuad::makeZeroVector( const NTriangulation* triangulation) { return new NNormalSurfaceVectorQuad( 3 * triangulation->getNumberOfTetrahedra()); } NMatrixInt* NNormalSurfaceVectorQuad::makeMatchingEquations( const NTriangulation* triangulation) { unsigned long nCoords = 3 * triangulation->getNumberOfTetrahedra(); // One equation per non-boundary edge. long nEquations = long(triangulation->getNumberOfEdges()); for (NTriangulation::BoundaryComponentIterator bit = triangulation-> getBoundaryComponents().begin(); bit != triangulation->getBoundaryComponents().end(); bit++) nEquations -= (*bit)->getNumberOfEdges(); NMatrixInt* ans = new NMatrixInt(nEquations, nCoords); unsigned long row = 0; // Run through each internal edge and add the corresponding // equation. std::deque::const_iterator embit; NPerm4 perm; unsigned long tetIndex; for (NTriangulation::EdgeIterator eit = triangulation->getEdges().begin(); eit != triangulation->getEdges().end(); eit++) { if (! (*eit)->isBoundary()) { for (embit = (*eit)->getEmbeddings().begin(); embit != (*eit)->getEmbeddings().end(); embit++) { tetIndex = triangulation->tetrahedronIndex( (*embit).getTetrahedron()); perm = (*embit).getVertices(); ans->entry(row, 3 * tetIndex + vertexSplit[perm[0]][perm[2]]) += 1; ans->entry(row, 3 * tetIndex + vertexSplit[perm[0]][perm[3]]) -= 1; } row++; } } return ans; } NEnumConstraintList* NNormalSurfaceVectorQuad::makeEmbeddedConstraints( const NTriangulation* triangulation) { NEnumConstraintList* ans = new NEnumConstraintList( triangulation->getNumberOfTetrahedra()); unsigned long base = 0; for (unsigned c = 0; c < ans->size(); ++c) { (*ans)[c].insert((*ans)[c].end(), base); (*ans)[c].insert((*ans)[c].end(), base + 1); (*ans)[c].insert((*ans)[c].end(), base + 2); base += 3; } return ans; } namespace { /** * A structure representing a particular end of an edge. */ struct EdgeEnd { NEdge* edge; /**< The edge under consideration. */ int end; /**< The end of the edge under consideration; this is 0 or 1. */ EdgeEnd() {} EdgeEnd(NEdge* newEdge, int newEnd) : edge(newEdge), end(newEnd) {} EdgeEnd(const EdgeEnd& cloneMe) : edge(cloneMe.edge), end(cloneMe.end) {} void operator = (const EdgeEnd& cloneMe) { edge = cloneMe.edge; end = cloneMe.end; } }; } NNormalSurfaceVector* NNormalSurfaceVectorQuad::makeMirror( const NTriangulation* triang) const { // We're going to do this by wrapping around each edge and seeing // what comes. unsigned long nRows = 7 * triang->getNumberOfTetrahedra(); NNormalSurfaceVectorStandard* ans = new NNormalSurfaceVectorStandard(nRows); // Set every triangular coordinate in the answer to infinity. // For coordinates about vertices not enjoying infinitely many discs, // infinity will mean "unknown". unsigned long row; int i; for (row = 0; row < nRows; row+=7) for (i = 0; i < 4; i++) ans->setElement(row + i, NLargeInteger::infinity); for (row = 0; 7 * row < nRows; row++) for (i = 0; i < 3; i++) ans->setElement(7 * row + 4 + i, (*this)[3 * row + i]); // Run through the vertices and work out the triangular coordinates // about each vertex in turn. std::set usedEdges[2]; // usedEdges[i] contains the edges for which we have already // examined end i. NLargeInteger min; // The minimum coordinate that has been assigned about this // vertex. std::deque examine; bool broken; // Are the matching equations broken about this edge end? int end; NEdge* edge; EdgeEnd current; std::vector::const_iterator vembit; std::deque::const_iterator eembit, backupit, endit, beginit; NTetrahedron* tet; NPerm4 tetPerm, adjPerm; unsigned long tetIndex, adjIndex; NLargeInteger expect; for (NTriangulation::VertexIterator vit = triang->getVertices().begin(); vit != triang->getVertices().end(); vit++) { usedEdges[0].clear(); usedEdges[1].clear(); examine.clear(); broken = false; // Pick some triangular disc and set it to zero. const NVertexEmbedding& vemb = (*vit)->getEmbedding(0); row = 7 * triang->tetrahedronIndex(vemb.getTetrahedron()) + vemb.getVertex(); ans->setElement(row, NLargeInteger::zero); min = NLargeInteger::zero; // Mark the three surrounding edge ends for examination. for (i=0; i<4; i++) { if (i == vemb.getVertex()) continue; edge = vemb.getTetrahedron()->getEdge( NEdge::edgeNumber[vemb.getVertex()][i]); end = vemb.getTetrahedron()->getEdgeMapping( NEdge::edgeNumber[vemb.getVertex()][i])[0] == i ? 1 : 0; if (usedEdges[end].insert(edge).second) examine.push_back(EdgeEnd(edge, end)); } // Cycle through edge ends until we are finished or until the // matching equations are broken. Each time we pick a value for // a coordinate, add the corresponding nearby edge ends to the // list of edge ends to examine. while ((! broken) && (! examine.empty())) { current = examine.front(); examine.pop_front(); // Run around this edge end. // We know there is a pre-chosen coordinate somewhere; run // forwards and find this. beginit = current.edge->getEmbeddings().begin(); endit = current.edge->getEmbeddings().end(); for (eembit = beginit; eembit != endit; eembit++) if (! (*ans)[7 * triang->tetrahedronIndex( (*eembit).getTetrahedron()) + (*eembit).getVertices()[current.end]].isInfinite()) break; // We are now at the first pre-chosen coordinate about this // vertex. Run backwards from here and fill in all the // holes. backupit = eembit; adjPerm = (*eembit).getVertices(); adjIndex = triang->tetrahedronIndex((*eembit).getTetrahedron()); while (eembit != beginit) { eembit--; // Work out the coordinate for the disc type at eembit. tet = (*eembit).getTetrahedron(); tetPerm = (*eembit).getVertices(); tetIndex = triang->tetrahedronIndex(tet); expect = (*ans)[7 * adjIndex + adjPerm[current.end]] + (*ans)[7 * adjIndex + 4 + vertexSplit[adjPerm[3]][adjPerm[current.end]]] - (*ans)[7 * tetIndex + 4 + vertexSplit[tetPerm[2]][tetPerm[current.end]]]; ans->setElement(7 * tetIndex + tetPerm[current.end], expect); if (expect < min) min = expect; // Remember to examine the new edge end if appropriate. edge = tet->getEdge( NEdge::edgeNumber[tetPerm[2]][tetPerm[current.end]]); end = tet->getEdgeMapping( NEdge::edgeNumber[tetPerm[2]][tetPerm[current.end]])[0] == tetPerm[2] ? 1 : 0; if (usedEdges[end].insert(edge).second) examine.push_back(EdgeEnd(edge, end)); adjPerm = tetPerm; adjIndex = tetIndex; } // Now move forwards from the original first pre-chosen // coordinate and fill in the holes from here onwards, // always checking to ensure the // matching equations have not been broken. eembit = backupit; adjPerm = (*eembit).getVertices(); adjIndex = triang->tetrahedronIndex((*eembit).getTetrahedron()); for (eembit++; eembit != endit; eembit++) { // Work out the coordinate for the disc type at eembit. tet = (*eembit).getTetrahedron(); tetPerm = (*eembit).getVertices(); tetIndex = triang->tetrahedronIndex(tet); expect = (*ans)[7 * adjIndex + adjPerm[current.end]] + (*ans)[7 * adjIndex + 4 + vertexSplit[adjPerm[2]][adjPerm[current.end]]] - (*ans)[7 * tetIndex + 4 + vertexSplit[tetPerm[3]][tetPerm[current.end]]]; row = 7 * tetIndex + tetPerm[current.end]; if ((*ans)[row].isInfinite()) { ans->setElement(row, expect); if (expect < min) min = expect; // Remember to examine the new edge end if appropriate. edge = tet->getEdge( NEdge::edgeNumber[tetPerm[3]][tetPerm[current.end]]); end = tet->getEdgeMapping( NEdge::edgeNumber[tetPerm[3]][tetPerm[current.end]])[0] == tetPerm[3] ? 1 : 0; if (usedEdges[end].insert(edge).second) examine.push_back(EdgeEnd(edge, end)); } else { // This coordinate has already been set. // Make sure it's the same value! if ((*ans)[row] != expect) { broken = true; break; } } adjPerm = tetPerm; adjIndex = tetIndex; } } // If the matching equations were broken, set every coordinate // to infinity. Otherwise subtract min from every coordinate to // make the values as small as possible. for (vembit = (*vit)->getEmbeddings().begin(); vembit != (*vit)->getEmbeddings().end(); vembit++) { row = 7 * triang->tetrahedronIndex((*vembit).getTetrahedron()) + (*vembit).getVertex(); if (broken) ans->setElement(row, NLargeInteger::infinity); else ans->setElement(row, (*ans)[row] - min); } } // Note that there should be no need to remove common factors since // the quad coordinates have not changed and in theory they already // had gcd=1. return ans; } } // namespace regina regina-4.96/engine/surfaces/nsquad.h000644 000765 000024 00000012710 12377775572 017363 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/nsquad.h * \brief Implements normal surface vectors using quad coordinates. */ #ifndef __NSQUAD_H #ifndef __DOXYGEN #define __NSQUAD_H #endif #include "regina-core.h" #include "surfaces/nsmirrored.h" namespace regina { class NMatrixInt; class NNormalSurfaceVectorQuad; /** * \weakgroup surfaces * @{ */ /** * Stores information about quad normal coordinates. * See the general NormalInfo template notes for further details. * * \ifacespython Not present. */ template <> struct NormalInfo { typedef NNormalSurfaceVectorQuad Class; typedef NormalInfo Standard; typedef NormalInfo Reduced; inline static const char* name() { return "Quad normal"; } enum { almostNormal = 0, spun = 1, oriented = 0 }; }; /** * A normal surface vector using quad coordinates. * * If there are \a t tetrahedra in the underlying * triangulation, there must be precisely 3t coordinates. * The first three coordinates will be for the first tetrahedron, the * next three for the second tetrahedron and so on. For each * tetrahedron, the three individual coordinates represent the * number of quadrilateral discs of type 0, 1 and 2 * (see NNormalSurface::getQuadCoord()). * * \ifacespython Not present. */ class REGINA_API NNormalSurfaceVectorQuad : public NNormalSurfaceVectorMirrored { REGINA_NORMAL_SURFACE_FLAVOUR(NNormalSurfaceVectorQuad, NS_QUAD) public: /** * Creates a new vector all of whose entries are initialised to * zero. * * @param length the number of elements in the new vector. */ NNormalSurfaceVectorQuad(size_t length); /** * Creates a new vector that is a clone of the given vector. * * @param cloneMe the vector to clone. */ NNormalSurfaceVectorQuad(const NVector& cloneMe); virtual NNormalSurfaceVector* makeMirror(const NTriangulation* triang) const; virtual const NVertex* isVertexLink(const NTriangulation* triang) const; virtual NLargeInteger getOctCoord(unsigned long tetIndex, int octType, const NTriangulation* triang) const; static NNormalSurfaceVector* makeZeroVector( const NTriangulation* triangulation); static NMatrixInt* makeMatchingEquations( const NTriangulation* triangulation); static NEnumConstraintList* makeEmbeddedConstraints( const NTriangulation* triangulation); }; /*@}*/ // Inline functions for NNormalSurfaceVectorQuad inline NNormalSurfaceVectorQuad::NNormalSurfaceVectorQuad( size_t length) : NNormalSurfaceVectorMirrored(length) { } inline NNormalSurfaceVectorQuad::NNormalSurfaceVectorQuad( const NVector& cloneMe) : NNormalSurfaceVectorMirrored(cloneMe) { } inline const NVertex* NNormalSurfaceVectorQuad::isVertexLink( const NTriangulation*) const { // Quad space does not contain vertex links at all. return 0; } inline NLargeInteger NNormalSurfaceVectorQuad::getOctCoord( unsigned long, int, const NTriangulation*) const { return zero; } } // namespace regina #endif regina-4.96/engine/surfaces/nsquadoct.cpp000644 000765 000024 00000035620 12377776733 020431 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include "enumerate/nenumconstraint.h" #include "surfaces/nsquadoct.h" #include "surfaces/nsanstandard.h" #include "maths/nmatrixint.h" #include "maths/nrational.h" #include "triangulation/ntriangulation.h" namespace regina { NNormalSurfaceVector* NNormalSurfaceVectorQuadOct::makeZeroVector( const NTriangulation* triangulation) { return new NNormalSurfaceVectorQuadOct( 6 * triangulation->getNumberOfTetrahedra()); } NMatrixInt* NNormalSurfaceVectorQuadOct::makeMatchingEquations( const NTriangulation* triangulation) { unsigned long nCoords = 6 * triangulation->getNumberOfTetrahedra(); // One equation per non-boundary edge. long nEquations = long(triangulation->getNumberOfEdges()); for (NTriangulation::BoundaryComponentIterator bit = triangulation-> getBoundaryComponents().begin(); bit != triangulation->getBoundaryComponents().end(); bit++) nEquations -= (*bit)->getNumberOfEdges(); NMatrixInt* ans = new NMatrixInt(nEquations, nCoords); unsigned long row = 0; // Run through each internal edge and add the corresponding // equation. std::deque::const_iterator embit; NPerm4 perm; unsigned long tetIndex; for (NTriangulation::EdgeIterator eit = triangulation->getEdges().begin(); eit != triangulation->getEdges().end(); eit++) { if (! (*eit)->isBoundary()) { for (embit = (*eit)->getEmbeddings().begin(); embit != (*eit)->getEmbeddings().end(); embit++) { tetIndex = triangulation->tetrahedronIndex( (*embit).getTetrahedron()); perm = (*embit).getVertices(); ans->entry(row, 6 * tetIndex + vertexSplit[perm[0]][perm[2]]) += 1; ans->entry(row, 6 * tetIndex + vertexSplit[perm[0]][perm[3]]) -= 1; ans->entry(row, 6 * tetIndex + 3 + vertexSplit[perm[0]][perm[2]]) -= 1; ans->entry(row, 6 * tetIndex + 3 + vertexSplit[perm[0]][perm[3]]) += 1; } row++; } } return ans; } NEnumConstraintList* NNormalSurfaceVectorQuadOct::makeEmbeddedConstraints( const NTriangulation* triangulation) { // At most one quad/oct per tetrahedron. // At most one oct type overall. NEnumConstraintList* ans = new NEnumConstraintList( triangulation->getNumberOfTetrahedra() + 1); unsigned base = 0; for (unsigned c = 1; c < ans->size(); ++c) { (*ans)[c].insert((*ans)[c].end(), base); (*ans)[c].insert((*ans)[c].end(), base + 1); (*ans)[c].insert((*ans)[c].end(), base + 2); (*ans)[c].insert((*ans)[c].end(), base + 3); (*ans)[c].insert((*ans)[c].end(), base + 4); (*ans)[c].insert((*ans)[c].end(), base + 5); (*ans)[0].insert((*ans)[0].end(), base + 3); (*ans)[0].insert((*ans)[0].end(), base + 4); (*ans)[0].insert((*ans)[0].end(), base + 5); base += 6; } return ans; } namespace { /** * A structure representing a particular end of an edge. */ struct EdgeEnd { NEdge* edge; /**< The edge under consideration. */ int end; /**< The end of the edge under consideration; this is 0 or 1. */ EdgeEnd() {} EdgeEnd(NEdge* newEdge, int newEnd) : edge(newEdge), end(newEnd) {} EdgeEnd(const EdgeEnd& cloneMe) : edge(cloneMe.edge), end(cloneMe.end) {} void operator = (const EdgeEnd& cloneMe) { edge = cloneMe.edge; end = cloneMe.end; } }; } NNormalSurfaceVector* NNormalSurfaceVectorQuadOct::makeMirror( const NTriangulation* triang) const { // We're going to do this by wrapping around each edge and seeing // what comes. unsigned long nRows = 10 * triang->getNumberOfTetrahedra(); NNormalSurfaceVectorANStandard* ans = new NNormalSurfaceVectorANStandard(nRows); // Set every triangular coordinate in the answer to infinity. // For coordinates about vertices not enjoying infinitely many discs, // infinity will mean "unknown". unsigned long row; int i; for (row = 0; row < nRows; row += 10) for (i = 0; i < 4; i++) ans->setElement(row + i, NLargeInteger::infinity); for (row = 0; 10 * row < nRows; ++row) for (i = 0; i < 6; i++) ans->setElement(10 * row + 4 + i, (*this)[6 * row + i]); // Run through the vertices and work out the triangular coordinates // about each vertex in turn. std::set usedEdges[2]; // usedEdges[i] contains the edges for which we have already // examined end i. NLargeInteger min; // The minimum coordinate that has been assigned about this // vertex. std::deque examine; bool broken; // Are the matching equations broken about this edge end? int end; NEdge* edge; EdgeEnd current; std::vector::const_iterator vembit; std::deque::const_iterator eembit, backupit, endit, beginit; NTetrahedron* tet; NPerm4 tetPerm, adjPerm; unsigned long tetIndex, adjIndex; NLargeInteger expect; for (NTriangulation::VertexIterator vit = triang->getVertices().begin(); vit != triang->getVertices().end(); vit++) { usedEdges[0].clear(); usedEdges[1].clear(); examine.clear(); broken = false; // Pick some triangular disc and set it to zero. const NVertexEmbedding& vemb = (*vit)->getEmbedding(0); row = 10 * triang->tetrahedronIndex(vemb.getTetrahedron()) + vemb.getVertex(); ans->setElement(row, NLargeInteger::zero); min = NLargeInteger::zero; // Mark the three surrounding edge ends for examination. for (i=0; i<4; i++) { if (i == vemb.getVertex()) continue; edge = vemb.getTetrahedron()->getEdge( NEdge::edgeNumber[vemb.getVertex()][i]); end = vemb.getTetrahedron()->getEdgeMapping( NEdge::edgeNumber[vemb.getVertex()][i])[0] == i ? 1 : 0; if (usedEdges[end].insert(edge).second) examine.push_back(EdgeEnd(edge, end)); } // Cycle through edge ends until we are finished or until the // matching equations are broken. Each time we pick a value for // a coordinate, add the corresponding nearby edge ends to the // list of edge ends to examine. while ((! broken) && (! examine.empty())) { current = examine.front(); examine.pop_front(); // Run around this edge end. // We know there is a pre-chosen coordinate somewhere; run // forwards and find this. beginit = current.edge->getEmbeddings().begin(); endit = current.edge->getEmbeddings().end(); for (eembit = beginit; eembit != endit; eembit++) if (! (*ans)[10 * triang->tetrahedronIndex( (*eembit).getTetrahedron()) + (*eembit).getVertices()[current.end]].isInfinite()) break; // We are now at the first pre-chosen coordinate about this // vertex. Run backwards from here and fill in all the // holes. backupit = eembit; adjPerm = (*eembit).getVertices(); adjIndex = triang->tetrahedronIndex((*eembit).getTetrahedron()); while (eembit != beginit) { eembit--; // Work out the coordinate for the disc type at eembit. tet = (*eembit).getTetrahedron(); tetPerm = (*eembit).getVertices(); tetIndex = triang->tetrahedronIndex(tet); expect = (*ans)[10 * adjIndex + adjPerm[current.end]] + (*ans)[10 * adjIndex + 4 + vertexSplit [adjPerm[3]][adjPerm[current.end]]] + (*ans)[10 * adjIndex + 7 + vertexSplitMeeting [adjPerm[3]][adjPerm[current.end]][0]] + (*ans)[10 * adjIndex + 7 + vertexSplitMeeting [adjPerm[3]][adjPerm[current.end]][1]] - (*ans)[10 * tetIndex + 4 + vertexSplit [tetPerm[2]][tetPerm[current.end]]] - (*ans)[10 * tetIndex + 7 + vertexSplitMeeting [tetPerm[2]][tetPerm[current.end]][0]] - (*ans)[10 * tetIndex + 7 + vertexSplitMeeting [tetPerm[2]][tetPerm[current.end]][1]]; ans->setElement(10 * tetIndex + tetPerm[current.end], expect); if (expect < min) min = expect; // Remember to examine the new edge end if appropriate. edge = tet->getEdge( NEdge::edgeNumber[tetPerm[2]][tetPerm[current.end]]); end = tet->getEdgeMapping( NEdge::edgeNumber[tetPerm[2]][tetPerm[current.end]])[0] == tetPerm[2] ? 1 : 0; if (usedEdges[end].insert(edge).second) examine.push_back(EdgeEnd(edge, end)); adjPerm = tetPerm; adjIndex = tetIndex; } // Now move forwards from the original first pre-chosen // coordinate and fill in the holes from here onwards, // always checking to ensure the // matching equations have not been broken. eembit = backupit; adjPerm = (*eembit).getVertices(); adjIndex = triang->tetrahedronIndex((*eembit).getTetrahedron()); for (eembit++; eembit != endit; eembit++) { // Work out the coordinate for the disc type at eembit. tet = (*eembit).getTetrahedron(); tetPerm = (*eembit).getVertices(); tetIndex = triang->tetrahedronIndex(tet); expect = (*ans)[10 * adjIndex + adjPerm[current.end]] + (*ans)[10 * adjIndex + 4 + vertexSplit [adjPerm[2]][adjPerm[current.end]]] + (*ans)[10 * adjIndex + 7 + vertexSplitMeeting [adjPerm[2]][adjPerm[current.end]][0]] + (*ans)[10 * adjIndex + 7 + vertexSplitMeeting [adjPerm[2]][adjPerm[current.end]][1]] - (*ans)[10 * tetIndex + 4 + vertexSplit [tetPerm[3]][tetPerm[current.end]]] - (*ans)[10 * tetIndex + 7 + vertexSplitMeeting [tetPerm[3]][tetPerm[current.end]][0]] - (*ans)[10 * tetIndex + 7 + vertexSplitMeeting [tetPerm[3]][tetPerm[current.end]][1]]; row = 10 * tetIndex + tetPerm[current.end]; if ((*ans)[row].isInfinite()) { ans->setElement(row, expect); if (expect < min) min = expect; // Remember to examine the new edge end if appropriate. edge = tet->getEdge( NEdge::edgeNumber[tetPerm[3]][tetPerm[current.end]]); end = tet->getEdgeMapping( NEdge::edgeNumber[tetPerm[3]][tetPerm[current.end]])[0] == tetPerm[3] ? 1 : 0; if (usedEdges[end].insert(edge).second) examine.push_back(EdgeEnd(edge, end)); } else { // This coordinate has already been set. // Make sure it's the same value! if ((*ans)[row] != expect) { broken = true; break; } } adjPerm = tetPerm; adjIndex = tetIndex; } } // If the matching equations were broken, set every coordinate // to infinity. Otherwise subtract min from every coordinate to // make the values as small as possible. for (vembit = (*vit)->getEmbeddings().begin(); vembit != (*vit)->getEmbeddings().end(); vembit++) { row = 10 * triang->tetrahedronIndex((*vembit).getTetrahedron()) + (*vembit).getVertex(); if (broken) ans->setElement(row, NLargeInteger::infinity); else ans->setElement(row, (*ans)[row] - min); } } // Note that there should be no need to remove common factors since // the quad/oct coordinates have not changed and in theory they already // had gcd=1. return ans; } } // namespace regina regina-4.96/engine/surfaces/nsquadoct.h000644 000765 000024 00000012640 12377775573 020074 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/nsquadoct.h * \brief Implements almost normal surface vectors using quad-oct coordinates. */ #ifndef __NSQUADOCT_H #ifndef __DOXYGEN #define __NSQUADOCT_H #endif #include "regina-core.h" #include "surfaces/nsmirrored.h" namespace regina { class NMatrixInt; class NNormalSurfaceVectorQuadOct; /** * \weakgroup surfaces * @{ */ /** * Stores information about quad-oct almost normal coordinates. * See the general NormalInfo template notes for further details. * * \ifacespython Not present. */ template <> struct NormalInfo { typedef NNormalSurfaceVectorQuadOct Class; typedef NormalInfo Standard; typedef NormalInfo Reduced; inline static const char* name() { return "Quad-oct almost normal"; } enum { almostNormal = 1, spun = 1, oriented = 0 }; }; /** * An almost normal surface vector using quad-oct coordinates. * * If there are \a t tetrahedra in the underlying * triangulation, there must be precisely 6t coordinates. * The first six coordinates will be for the first tetrahedron, the * next six for the second tetrahedron and so on. For each * tetrahedron, the first three coordinates represent the number of * quadrilateral discs of type 0, 1 and 2 (see NNormalSurface::getQuadCoord()), * and the final three represent the number of octagonal discs of type * 0, 1 and 2 (see NNormalSurface::getOctCoord()). * * \ifacespython Not present. */ class REGINA_API NNormalSurfaceVectorQuadOct : public NNormalSurfaceVectorMirrored { REGINA_NORMAL_SURFACE_FLAVOUR(NNormalSurfaceVectorQuadOct, NS_AN_QUAD_OCT) public: /** * Creates a new vector all of whose entries are initialised to * zero. * * @param length the number of elements in the new vector. */ NNormalSurfaceVectorQuadOct(size_t length); /** * Creates a new vector that is a clone of the given vector. * * @param cloneMe the vector to clone. */ NNormalSurfaceVectorQuadOct(const NVector& cloneMe); virtual NNormalSurfaceVector* makeMirror(const NTriangulation* triang) const; virtual const NVertex* isVertexLink(const NTriangulation* triang) const; static NNormalSurfaceVector* makeZeroVector( const NTriangulation* triangulation); static NMatrixInt* makeMatchingEquations( const NTriangulation* triangulation); static NEnumConstraintList* makeEmbeddedConstraints( const NTriangulation* triangulation); }; /*@}*/ // Inline functions for NNormalSurfaceVectorQuadOct inline NNormalSurfaceVectorQuadOct::NNormalSurfaceVectorQuadOct( size_t length) : NNormalSurfaceVectorMirrored(length) { } inline NNormalSurfaceVectorQuadOct::NNormalSurfaceVectorQuadOct( const NVector& cloneMe) : NNormalSurfaceVectorMirrored(cloneMe) { } inline const NVertex* NNormalSurfaceVectorQuadOct::isVertexLink( const NTriangulation*) const { // Quad-oct space does not contain vertex links at all. return 0; } } // namespace regina #endif regina-4.96/engine/surfaces/nsstandard.cpp000644 000765 000024 00000014400 12377776734 020563 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "enumerate/nenumconstraint.h" #include "surfaces/nsstandard.h" #include "maths/nmatrixint.h" #include "maths/nrational.h" #include "triangulation/ntriangulation.h" namespace regina { NLargeInteger NNormalSurfaceVectorStandard::getEdgeWeight( unsigned long edgeIndex, const NTriangulation* triang) const { // Find a tetrahedron next to the edge in question. const NEdgeEmbedding& emb = triang->getEdges()[edgeIndex]-> getEmbeddings().front(); long tetIndex = triang->tetrahedronIndex(emb.getTetrahedron()); int start = emb.getVertices()[0]; int end = emb.getVertices()[1]; // Add up the triangles and quads meeting that edge. // Triangles: NLargeInteger ans((*this)[7 * tetIndex + start]); ans += (*this)[7 * tetIndex + end]; // Quads: ans += (*this)[7 * tetIndex + 4 + vertexSplitMeeting[start][end][0]]; ans += (*this)[7 * tetIndex + 4 + vertexSplitMeeting[start][end][1]]; return ans; } NLargeInteger NNormalSurfaceVectorStandard::getTriangleArcs( unsigned long triIndex, int triVertex, const NTriangulation* triang) const { // Find a tetrahedron next to the triangle in question. const NTriangleEmbedding& emb = triang->getTriangles()[triIndex]-> getEmbedding(0); long tetIndex = triang->tetrahedronIndex(emb.getTetrahedron()); int vertex = emb.getVertices()[triVertex]; int backOfFace = emb.getVertices()[3]; // Add up the triangles and quads meeting that triangle in the required arc. // Triangles: NLargeInteger ans((*this)[7 * tetIndex + vertex]); // Quads: ans += (*this)[7 * tetIndex + 4 + vertexSplit[vertex][backOfFace]]; return ans; } NNormalSurfaceVector* NNormalSurfaceVectorStandard::makeZeroVector( const NTriangulation* triangulation) { return new NNormalSurfaceVectorStandard( 7 * triangulation->getNumberOfTetrahedra()); } NMatrixInt* NNormalSurfaceVectorStandard::makeMatchingEquations( const NTriangulation* triangulation) { unsigned long nCoords = 7 * triangulation->getNumberOfTetrahedra(); // Three equations per non-boundary triangle. // F_boundary + 2 F_internal = 4 T long nEquations = 3 * (4 * long(triangulation->getNumberOfTetrahedra()) - long(triangulation->getNumberOfTriangles())); NMatrixInt* ans = new NMatrixInt(nEquations, nCoords); // Run through each internal triangle and add the corresponding three // equations. unsigned row = 0; int i; unsigned long tet0, tet1; NPerm4 perm0, perm1; for (NTriangulation::TriangleIterator fit = triangulation->getTriangles().begin(); fit != triangulation->getTriangles().end(); fit++) { if (! (*fit)->isBoundary()) { tet0 = triangulation->tetrahedronIndex( (*fit)->getEmbedding(0).getTetrahedron()); tet1 = triangulation->tetrahedronIndex( (*fit)->getEmbedding(1).getTetrahedron()); perm0 = (*fit)->getEmbedding(0).getVertices(); perm1 = (*fit)->getEmbedding(1).getVertices(); for (i=0; i<3; i++) { // Triangles: ans->entry(row, 7*tet0 + perm0[i]) += 1; ans->entry(row, 7*tet1 + perm1[i]) -= 1; // Quads: ans->entry(row, 7*tet0 + 4 + vertexSplit[perm0[i]][perm0[3]]) += 1; ans->entry(row, 7*tet1 + 4 + vertexSplit[perm1[i]][perm1[3]]) -= 1; row++; } } } return ans; } NEnumConstraintList* NNormalSurfaceVectorStandard::makeEmbeddedConstraints( const NTriangulation* triangulation) { NEnumConstraintList* ans = new NEnumConstraintList( triangulation->getNumberOfTetrahedra()); unsigned base = 0; for (unsigned c = 0; c < ans->size(); ++c) { (*ans)[c].insert((*ans)[c].end(), base + 4); (*ans)[c].insert((*ans)[c].end(), base + 5); (*ans)[c].insert((*ans)[c].end(), base + 6); base += 7; } return ans; } } // namespace regina regina-4.96/engine/surfaces/nsstandard.h000644 000765 000024 00000014221 12377775574 020232 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/nsstandard.h * \brief Implements normal surface vectors using standard * triangle-quad coordinates. */ #ifndef __NSSTANDARD_H #ifndef __DOXYGEN #define __NSSTANDARD_H #endif #include "regina-core.h" #include "surfaces/nnormalsurface.h" namespace regina { class NMatrixInt; class NNormalSurfaceVectorStandard; /** * \weakgroup surfaces * @{ */ /** * Stores information about standard normal coordinates. * See the general NormalInfo template notes for further details. * * \ifacespython Not present. */ template <> struct NormalInfo { typedef NNormalSurfaceVectorStandard Class; typedef NormalInfo Standard; typedef NormalInfo Reduced; inline static const char* name() { return "Standard normal (tri-quad)"; } enum { almostNormal = 0, spun = 0, oriented = 0 }; }; /** * A normal surface vector using standard triangle-quad coordinates. * * If there are \a t tetrahedra in the underlying * triangulation, there must be precisely 7t coordinates. * The first seven coordinates will be for the first tetrahedron, the * next seven for the second tetrahedron and so on. For each * tetrahedron, the first four represent the number of * triangular discs about vertex 0, 1, 2 and 3, and the next * three represent the number of quadrilateral discs of type 0, * 1 and 2 (see NNormalSurface::getQuadCoord()). * * \ifacespython Not present. */ class REGINA_API NNormalSurfaceVectorStandard : public NNormalSurfaceVector { REGINA_NORMAL_SURFACE_FLAVOUR(NNormalSurfaceVectorStandard, NS_STANDARD) public: /** * Creates a new vector all of whose entries are initialised to * zero. * * @param length the number of elements in the new vector. */ NNormalSurfaceVectorStandard(size_t length); /** * Creates a new vector that is a clone of the given vector. * * @param cloneMe the vector to clone. */ NNormalSurfaceVectorStandard(const NVector& cloneMe); virtual NLargeInteger getTriangleCoord(unsigned long tetIndex, int vertex, const NTriangulation* triang) const; virtual NLargeInteger getQuadCoord(unsigned long tetIndex, int quadType, const NTriangulation* triang) const; virtual NLargeInteger getOctCoord(unsigned long tetIndex, int octType, const NTriangulation* triang) const; virtual NLargeInteger getEdgeWeight(unsigned long edgeIndex, const NTriangulation* triang) const; virtual NLargeInteger getTriangleArcs(unsigned long triIndex, int triVertex, const NTriangulation* triang) const; static NNormalSurfaceVector* makeZeroVector( const NTriangulation* triangulation); static NMatrixInt* makeMatchingEquations( const NTriangulation* triangulation); static NEnumConstraintList* makeEmbeddedConstraints( const NTriangulation* triangulation); }; /*@}*/ // Inline functions for NNormalSurfaceVectorStandard inline NNormalSurfaceVectorStandard::NNormalSurfaceVectorStandard( size_t length) : NNormalSurfaceVector(length) { } inline NNormalSurfaceVectorStandard::NNormalSurfaceVectorStandard( const NVector& cloneMe) : NNormalSurfaceVector(cloneMe) { } inline NLargeInteger NNormalSurfaceVectorStandard::getTriangleCoord( unsigned long tetIndex, int vertex, const NTriangulation*) const { return (*this)[7 * tetIndex + vertex]; } inline NLargeInteger NNormalSurfaceVectorStandard::getQuadCoord( unsigned long tetIndex, int quadType, const NTriangulation*) const { return (*this)[7 * tetIndex + 4 + quadType]; } inline NLargeInteger NNormalSurfaceVectorStandard::getOctCoord( unsigned long, int, const NTriangulation*) const { return zero; } } // namespace regina #endif regina-4.96/engine/surfaces/nsurfacefilter.cpp000644 000765 000024 00000005366 12377776734 021451 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "surfaces/nsurfacefilter.h" #include "surfaces/nnormalsurfacelist.h" #include "surfaces/filterregistry.h" #include "utilities/xmlutils.h" namespace regina { void NSurfaceFilter::writeXMLPacketData(std::ostream& out) const { SurfaceFilterType id = getFilterType(); out << " \n"; writeXMLFilterData(out); out << " \n"; } } // namespace regina regina-4.96/engine/surfaces/nsurfacefilter.h000644 000765 000024 00000030145 12377775576 021112 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/nsurfacefilter.h * \brief Contains a packet that filters through normal surfaces. */ #ifndef __NSURFACEFILTER_H #ifndef __DOXYGEN #define __NSURFACEFILTER_H #endif #include "regina-core.h" #include "packet/npacket.h" #include "surfaces/surfacefiltertype.h" namespace regina { class NNormalSurface; class NNormalSurfaceList; class NSurfaceFilter; class NXMLPacketReader; class NXMLFilterReader; /** * \weakgroup surfaces * @{ */ /** * A template that stores information about a particular type of normal * surface filter. Much of this information is given in the * form of compile-time constants and types. * * To iterate through cases for a given value of SurfaceFilterInfo that is not * known until runtime, see the various forFilter() routines defined in * filterregistry.h. * * At a bare minimum, each specialisation of this template must provide: * * - a typedef \a Class that represents the corresponding * NSurfaceFilter descendant class; * - a static function name() that returns a C-style string giving the * human-readable name of the filter type. * * \ifacespython Not present. */ template struct SurfaceFilterInfo; /** * Defines various constants, types and virtual functions for a * descendant class of NSurfaceFilter. * * Every descendant class of NSurfaceFilter \a must include * REGINA_SURFACE_FILTER at the beginning of the class definition. * * This macro provides the class with: * * - a compile-time enum constant \a filterType, which is equal to the * corresponding SurfaceFilterType constant; * - a deprecated compile-time enum constant \a filterID, which is * identical to \a filterType; * - declarations and implementations of the virtual functions * NSurfaceFilter::getFilterType() and NSurfaceFilter::getFilterTypeName(); * - declarations and implementations of the deprecated virtual functions * NSurfaceFilter::getFilterID() and NSurfaceFilter::getFilterName(). * * @param class_ the name of this descendant class of NSurfaceFilter. * @param id the corresponding SurfaceFilterType constant. */ #define REGINA_SURFACE_FILTER(class_, id) \ public: \ enum { filterType = id, filterID = id }; \ inline virtual SurfaceFilterType getFilterType() const { \ return id; \ } \ inline virtual SurfaceFilterType getFilterID() const { \ return id; \ } \ inline virtual std::string getFilterTypeName() const { \ return SurfaceFilterInfo::name(); \ } \ inline virtual std::string getFilterName() const { \ return SurfaceFilterInfo::name(); \ } /** * Stores information about the normal surface filter packet type. * See the general PacketInfo template notes for further details. * * \ifacespython Not present. */ template <> struct PacketInfo { typedef NSurfaceFilter Class; inline static const char* name() { return "Surface Filter"; } }; /** * Stores information about the default accept-all surface filter. * See the general SurfaceFilterInfo template notes for further details. * * \ifacespython Not present. */ template <> struct SurfaceFilterInfo { typedef NSurfaceFilter Class; inline static const char* name() { return "Default filter"; } }; /** * A packet that accepts or rejects normal surfaces. * Different subclasses of NSurfaceFilter represent different filtering * methods. * * When deriving classes from NSurfaceFilter: *
    *
  • A new value must be added to the SurfaceFilterType enum in * surfacefiltertype.h to represent the new filter type.
  • *
  • The file filterregistry-impl.h must be updated to reflect the new * filter type (the file itself contains instructions on how to do this).
  • *
  • A corresponding specialisation of SurfaceFilterInfo<> must be * defined, typically in the same header as the new filter class.
  • *
  • The macro REGINA_SURFACE_FILTER must be added to the beginning * of the new filter class. This will declare and define various * constants, typedefs and virtual functions (see the REGINA_SURFACE_FILTER * macro documentation for details).
  • *
  • A copy constructor class(const class& cloneMe) must * be declared and implemented. You may assume that parameter * \a cloneMe is of the same class as that whose constructor you are * writing.
  • *
  • Virtual functions accept(), internalClonePacket(), writeTextLong() and * writeXMLFilterData() must be overridden.
  • *
  • Static function getXMLFilterReader() must be declared and * implemented as described in the documentation below.
  • *
* * \todo \feature Implement property \a lastAppliedTo. */ class REGINA_API NSurfaceFilter : public NPacket { REGINA_PACKET(NSurfaceFilter, PACKET_SURFACEFILTER) REGINA_SURFACE_FILTER(NSurfaceFilter, NS_FILTER_DEFAULT) public: /** * Creates a new default surface filter. This will simply accept * all normal surfaces. */ NSurfaceFilter(); /** * Creates a new default surface filter. This will simply accept * all normal surfaces. Note that the given parameter is * ignored. * * @param cloneMe this parameter is ignored. */ NSurfaceFilter(const NSurfaceFilter& cloneMe); /** * Destroys this surface filter. */ virtual ~NSurfaceFilter(); /** * Decides whether or not the given normal surface is accepted by this * filter. * * The default implementation simply returns \c true. * * @param surface the normal surface under investigation. * @return \c true if and only if the given surface is accepted * by this filter. */ virtual bool accept(const NNormalSurface& surface) const; #ifdef __DOXYGEN /** * Returns the unique integer ID corresponding to the filtering * method that is this particular subclass of NSurfaceFilter. * * @return the unique integer filtering method ID. */ virtual SurfaceFilterType getFilterType() const; /** * A deprecated alias for getFilterType(). * This returns the unique integer ID corresponding to the filtering * method that is this particular subclass of NSurfaceFilter. * * @return the unique integer filtering method ID. */ virtual SurfaceFilterType getFilterID() const; /** * Returns a string description of the filtering method that is * this particular subclass of NSurfaceFilter. * * @return a string description of this filtering method. */ virtual std::string getFilterTypeName() const; /** * A deprecated alias for getFilterTypeName(). * This returns a string description of the filtering method that is * this particular subclass of NSurfaceFilter. * * @return a string description of this filtering method. */ virtual std::string getFilterName() const; #endif /** * Returns a newly created XML filter reader that will read the * details of a particular type of surface filter. You may * assume that the filter to be read is of the same type as the * class in which you are implementing this routine. * * The XML filter reader should read exactly what * writeXMLFilterData() writes, and vice versa. * * \a parent represents the packet which will become the new * filter's parent in the tree structure. This information is * for reference only, and need not be used. * See the description of parameter \a parent in * NPacket::getXMLReader() for further details. * * \ifacespython Not present. * * @param parent the packet which will become the new filter's * parent in the tree structure, or 0 if the new filter is to be * tree matriarch. * @return the newly created XML filter reader. */ static NXMLFilterReader* getXMLFilterReader(NPacket* parent); virtual void writeTextShort(std::ostream& out) const; static NXMLPacketReader* getXMLReader(NPacket* parent, NXMLTreeResolver& resolver); virtual bool dependsOnParent() const; protected: /** * Writes a chunk of XML containing the details of this filter. * * You may assume that the filter opening tag (including the * filter type) has already been written, and that the filter * closing tag will be written immediately after this routine is * called. This routine need only write the additional details * corresponding to this particular subclass of NSurfaceFilter. * * @param out the output stream to which the XML should be written. */ virtual void writeXMLFilterData(std::ostream& out) const; virtual NPacket* internalClonePacket(NPacket* parent) const; virtual void writeXMLPacketData(std::ostream& out) const; }; /*@}*/ // Inline functions for NSurfaceFilter inline NSurfaceFilter::NSurfaceFilter() { } inline NSurfaceFilter::NSurfaceFilter(const NSurfaceFilter&) : NPacket() { } inline NSurfaceFilter::~NSurfaceFilter() { } inline bool NSurfaceFilter::accept(const NNormalSurface&) const { return true; } inline void NSurfaceFilter::writeXMLFilterData(std::ostream&) const { } inline void NSurfaceFilter::writeTextShort(std::ostream& o) const { o << getFilterTypeName(); } inline bool NSurfaceFilter::dependsOnParent() const { return false; } inline NPacket* NSurfaceFilter::internalClonePacket(NPacket*) const { return new NSurfaceFilter(); } } // namespace regina #endif regina-4.96/engine/surfaces/nsurfacesubset.cpp000644 000765 000024 00000005766 12377776735 021476 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "surfaces/nsurfacesubset.h" #include "surfaces/nsurfacefilter.h" namespace regina { NSurfaceSubset::NSurfaceSubset(const NNormalSurfaceList& set, const NSurfaceFilter& filter) : source(set) { unsigned long n = set.getNumberOfSurfaces(); NNormalSurface* s; for (unsigned long i = 0; i < n; i++) { s = const_cast(set.getSurface(i)); if (filter.accept(*s)) surfaces.push_back(s); } } void NSurfaceSubset::writeAllSurfaces(std::ostream& out) const { unsigned long n = getNumberOfSurfaces(); out << "Number of surfaces is " << n << '\n'; for (unsigned long i = 0; i < n; i++) { getSurface(i)->writeTextShort(out); out << '\n'; } } } // namespace regina regina-4.96/engine/surfaces/nsurfacesubset.h000644 000765 000024 00000021127 12377775577 021133 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/nsurfacesubset.h * \brief Provides subsets of normal surface sets. */ #ifndef __NSURFACESUBSET_H #ifndef __DOXYGEN #define __NSURFACESUBSET_H #endif #include #include "regina-core.h" #include "shareableobject.h" #include "surfaces/nnormalsurfacelist.h" namespace regina { class NSurfaceFilter; /** * \weakgroup surfaces * @{ */ /** * Represents a subset of a normal surface list. * This subset merely contains pointers to some of the normal surfaces * stored in the original list. * * If the surfaces in the original list * should change, the surfaces in this subset will thus change also. If * the original list is deleted, this subset will become invalid. * * \pre As long as this subset is in use, the surface list upon which this * subset is based must never be deleted. */ class REGINA_API NSurfaceSubset : public ShareableObject { private: std::vector surfaces; /**< Contains the surfaces contained in this subset. These will all be pointers to surfaces stored in \a source. */ const NNormalSurfaceList& source; /**< The surface list for which this is a subset. */ public: /** * Creates a new normal surface subset. * The surfaces included in the subset will be those from the * given set that are accepted by the given filter. * * @param list the surface list for which this will be a subset. * @param filter the filter that defines which surfaces in \a list * will be included in this subset. */ NSurfaceSubset(const NNormalSurfaceList& list, const NSurfaceFilter& filter); /** * Destroys this normal surface subset. */ virtual ~NSurfaceSubset(); /** * Returns the coordinate system being used by the * surfaces stored in this set. * * \deprecated Users should switch to the identical routine * coords() instead. * * @return the coordinate system used. */ NormalCoords getFlavour() const; /** * Returns the coordinate system being used by the * surfaces stored in this set. * * @return the coordinate system used. */ NormalCoords coords() const; /** * Determines if the coordinate system being used * allows for almost normal surfaces, that is, allows for * octagonal discs. * * @return \c true if and only if almost normal surfaces are * allowed. */ bool allowsAlmostNormal() const; /** * Determines if the coordinate system being used * allows for spun normal surfaces. * * @return \c true if and only if spun normal surface are * supported. */ bool allowsSpun() const; /** * Determines if the coordinate system being used * allows for transversely oriented normal surfaces. * * @return \c true if and only if transverse orientations are * supported. */ bool allowsOriented() const; /** * Returns whether this set is known to contain only embedded normal * surfaces. * * If it is possible that there are non-embedded surfaces in this * set but it is not known whether any are actually present or * not, this routine should return \c false. * * @return \c true if it is known that only embedded normal surfaces * exist in this list, or \c false if immersed and/or singular normal * surfaces might be present. */ bool isEmbeddedOnly() const; /** * Returns the triangulation in which these normal surfaces live. * * @return the triangulation in which these surfaces live. */ NTriangulation* getTriangulation() const; /** * Returns the number of surfaces stored in this set. * * @return the number of surfaces. */ unsigned long getNumberOfSurfaces() const; /** * Returns the surface at the requested index in this set. * * @param index the index of the requested surface in this set; * this must be between 0 and getNumberOfSurfaces()-1 inclusive. * * @return the normal surface at the requested index in this set. */ const NNormalSurface* getSurface(unsigned long index) const; /** * Writes the number of surfaces in this set followed by the * details of each surface to the given output stream. Output * will be over many lines. * * \ifacespython Parameter \a out is not present and is assumed * to be standard output. * * @param out the output stream to which to write. */ void writeAllSurfaces(std::ostream& out) const; virtual void writeTextShort(std::ostream& out) const; virtual void writeTextLong(std::ostream& out) const; }; /*@}*/ // Inline functions for NSurfaceSubset inline NSurfaceSubset::~NSurfaceSubset() { } inline NormalCoords NSurfaceSubset::getFlavour() const { return source.coords(); } inline NormalCoords NSurfaceSubset::coords() const { return source.coords(); } inline bool NSurfaceSubset::allowsAlmostNormal() const { return source.allowsAlmostNormal(); } inline bool NSurfaceSubset::allowsSpun() const { return source.allowsSpun(); } inline bool NSurfaceSubset::allowsOriented() const { return source.allowsOriented(); } inline bool NSurfaceSubset::isEmbeddedOnly() const { return source.isEmbeddedOnly(); } inline NTriangulation* NSurfaceSubset::getTriangulation() const { return source.getTriangulation(); } inline unsigned long NSurfaceSubset::getNumberOfSurfaces() const { return surfaces.size(); } inline const NNormalSurface* NSurfaceSubset::getSurface(unsigned long index) const { return surfaces[index]; } inline void NSurfaceSubset::writeTextShort(std::ostream& out) const { out << "Subset containing " << surfaces.size() << " normal surface"; if (surfaces.size() != 1) out << 's'; } inline void NSurfaceSubset::writeTextLong(std::ostream& out) const { writeAllSurfaces(out); } } // namespace regina #endif regina-4.96/engine/surfaces/nxmlfilterreader.cpp000644 000765 000024 00000007442 12377776736 022003 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "surfaces/nxmlfilterreader.h" #include "surfaces/filterregistry.h" #include "utilities/stringutils.h" namespace regina { namespace { struct XMLReaderFunction : public Returns { NPacket* parent_; XMLReaderFunction(NPacket* parent) : parent_(parent) {} template inline NXMLElementReader* operator() (Filter) { return Filter::Class::getXMLFilterReader(parent_); } }; } NXMLElementReader* NXMLFilterPacketReader::startContentSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict& props) { if (! filter) if (subTagName == "filter") { int type; if (valueOf(props.lookup("typeid"), type)) { NXMLElementReader* ans = forFilter( static_cast(type), XMLReaderFunction(parent), 0); if (ans) return ans; else return new NXMLFilterReader(); } } return new NXMLElementReader(); } void NXMLFilterPacketReader::endContentSubElement( const std::string& subTagName, NXMLElementReader* subReader) { if (! filter) if (subTagName == "filter") filter = dynamic_cast(subReader)->getFilter(); } NXMLPacketReader* NSurfaceFilter::getXMLReader(NPacket* parent, NXMLTreeResolver& resolver) { return new NXMLFilterPacketReader(parent, resolver); } } // namespace regina regina-4.96/engine/surfaces/nxmlfilterreader.h000644 000765 000024 00000013643 12377775601 021436 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/nxmlfilterreader.h * \brief Deals with parsing XML data for normal surface filters. */ #ifndef __NXMLFILTERREADER_H #ifndef __DOXYGEN #define __NXMLFILTERREADER_H #endif #include "regina-core.h" #include "packet/nxmlpacketreader.h" #include "surfaces/nsurfacefilter.h" namespace regina { /** * \weakgroup surfaces * @{ */ /** * An XML element reader that reads the specific details of a normal * surface filter. These details are generally contained within a * \ ... \ pair. * * Generally a subclass of NXMLFilterReader will be used to receive and * store filters that you care about. However, if you simply wish to * ignore a particular filter (and all of its descendants), you can use * class NXMLFilterReader itself for the filter(s) you wish to ignore. * * Routine getFilter() is used to return the filter that was read; see * its documentation for further notes on how the filter should be * constructed. * * \ifacespython Not present. */ class REGINA_API NXMLFilterReader : public NXMLElementReader { public: /** * Creates a new filter element reader. */ NXMLFilterReader(); /** * Returns the newly allocated filter that has been read by * this element reader. * * Deallocation of this new filter is not the responsibility of * this class. Once this routine gives a non-zero return value, * it should continue to give the same non-zero return value * from this point onwards. * * The default implementation returns 0. * * @return the filter that has been read, or 0 if filter reading * is incomplete, the filter should be ignored or an error * occurred. */ virtual NSurfaceFilter* getFilter(); }; /** * An XML packet reader that reads a single surface filter. * The filter type will be determined by this class and an appropriate * NXMLFilterReader will be used to process the type-specific details. * * \pre The parent XML element reader is in fact an NXMLPacketReader. * * \ifacespython Not present. */ class REGINA_API NXMLFilterPacketReader : public NXMLPacketReader { private: NSurfaceFilter* filter; /**< The surface filter currently being read. */ NPacket* parent; /**< The parent packet of the filter currently being read. */ public: /** * Creates a new surface filter packet reader. * * @param newParent the parent packet of the filter to be read, * or 0 if this filter is to be tree matriarch. * @param resolver the master resolver that will be used to fix * dangling packet references after the entire XML file has been read. */ NXMLFilterPacketReader(NPacket* newParent, NXMLTreeResolver& resolver); virtual NPacket* getPacket(); virtual NXMLElementReader* startContentSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict& subTagProps); virtual void endContentSubElement(const std::string& subTagName, NXMLElementReader* subReader); }; /*@}*/ // Inline functions for NXMLFilterReader inline NXMLFilterReader::NXMLFilterReader() { } inline NSurfaceFilter* NXMLFilterReader::getFilter() { return 0; } // Inline functions for NXMLFilterPacketReader inline NXMLFilterPacketReader::NXMLFilterPacketReader(NPacket* newParent, NXMLTreeResolver& resolver) : NXMLPacketReader(resolver), filter(0), parent(newParent) { } inline NPacket* NXMLFilterPacketReader::getPacket() { return filter; } } // namespace regina #endif regina-4.96/engine/surfaces/nxmlfilterreaders.cpp000644 000765 000024 00000014400 12377776737 022157 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "surfaces/nxmlfilterreader.h" #include "surfaces/sfcombination.h" #include "surfaces/sfproperties.h" #include "utilities/stringutils.h" namespace regina { /** * A unique namespace containing XML readers for specific filter types. */ namespace { /** * Reads a plain (non-subclassed) NSurfaceFilter. */ class NPlainFilterReader : public NXMLFilterReader { private: NSurfaceFilter* filter; public: NPlainFilterReader() : filter(new NSurfaceFilter()) { } virtual NSurfaceFilter* getFilter() { return filter; } }; /** * Reads an NSurfaceFilterCombination filter. */ class NCombinationReader : public NXMLFilterReader { private: NSurfaceFilterCombination* filter; public: NCombinationReader() : filter(0) { } virtual NSurfaceFilter* getFilter() { return filter; } NXMLElementReader* startSubElement(const std::string& subTagName, const regina::xml::XMLPropertyDict& props) { if (! filter) if (subTagName == "op") { std::string type = props.lookup("type"); if (type == "and") { filter = new NSurfaceFilterCombination(); filter->setUsesAnd(true); } else if (type == "or") { filter = new NSurfaceFilterCombination(); filter->setUsesAnd(false); } } return new NXMLElementReader(); } }; /** * Reads an NSurfaceFilterProperties filter. */ class NPropertiesReader : public NXMLFilterReader { private: NSurfaceFilterProperties* filter; public: NPropertiesReader() : filter(new NSurfaceFilterProperties()) { } virtual NSurfaceFilter* getFilter() { return filter; } NXMLElementReader* startSubElement(const std::string& subTagName, const regina::xml::XMLPropertyDict& props) { if (subTagName == "euler") { return new NXMLCharsReader(); } else if (subTagName == "orbl") { NBoolSet b; if (valueOf(props.lookup("value"), b)) filter->setOrientability(b); } else if (subTagName == "compact") { NBoolSet b; if (valueOf(props.lookup("value"), b)) filter->setCompactness(b); } else if (subTagName == "realbdry") { NBoolSet b; if (valueOf(props.lookup("value"), b)) filter->setRealBoundary(b); } return new NXMLElementReader(); } void endSubElement( const std::string& subTagName, NXMLElementReader* subReader) { if (subTagName == "euler") { std::list tokens; basicTokenise(back_inserter(tokens), dynamic_cast(subReader)->getChars()); NLargeInteger val; for (std::list::const_iterator it = tokens.begin(); it != tokens.end(); it++) if (valueOf(*it, val)) filter->addEC(val); } } }; } NXMLFilterReader* NSurfaceFilter::getXMLFilterReader(NPacket*) { return new NPlainFilterReader(); } NXMLFilterReader* NSurfaceFilterCombination::getXMLFilterReader(NPacket*) { return new NCombinationReader(); } NXMLFilterReader* NSurfaceFilterProperties::getXMLFilterReader(NPacket*) { return new NPropertiesReader(); } } // namespace regina regina-4.96/engine/surfaces/nxmlsurfacereader.cpp000644 000765 000024 00000016010 12377776737 022136 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "surfaces/coordregistry.h" #include "surfaces/nxmlsurfacereader.h" #include "triangulation/ntriangulation.h" #include "utilities/stringutils.h" namespace regina { void NXMLNormalSurfaceReader::startElement(const std::string&, const regina::xml::XMLPropertyDict& props, NXMLElementReader*) { if (! valueOf(props.lookup("len"), vecLen)) vecLen = -1; name = props.lookup("name"); } void NXMLNormalSurfaceReader::initialChars(const std::string& chars) { if (vecLen < 0 || tri == 0) return; std::vector tokens; if (basicTokenise(back_inserter(tokens), chars) % 2 != 0) return; // Create a new vector and read all non-zero entries. // Bring in cases from the coordinate system registry... NNormalSurfaceVector* vec; if (coords == NS_AN_LEGACY) vec = new NNormalSurfaceVectorANStandard(vecLen); else vec = forCoords(coords, NewFunction1(vecLen), 0); if (! vec) return; long pos; NLargeInteger value; for (unsigned long i = 0; i < tokens.size(); i += 2) { if (valueOf(tokens[i], pos)) if (valueOf(tokens[i + 1], value)) if (pos >= 0 && pos < vecLen) { // All looks valid. vec->setElement(pos, value); continue; } // Found something invalid. delete vec; return; } surface = new NNormalSurface(tri, vec); if (! name.empty()) surface->setName(name); } NXMLElementReader* NXMLNormalSurfaceReader::startSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict& props) { if (! surface) return new NXMLElementReader(); if (subTagName == "euler") { NLargeInteger val; if (valueOf(props.lookup("value"), val)) surface->eulerChar = val; } else if (subTagName == "orbl") { bool val; if (valueOf(props.lookup("value"), val)) surface->orientable = val; } else if (subTagName == "twosided") { bool val; if (valueOf(props.lookup("value"), val)) surface->twoSided = val; } else if (subTagName == "connected") { bool val; if (valueOf(props.lookup("value"), val)) surface->connected = val; } else if (subTagName == "realbdry") { bool val; if (valueOf(props.lookup("value"), val)) surface->realBoundary = val; } else if (subTagName == "compact") { bool val; if (valueOf(props.lookup("value"), val)) surface->compact = val; } return new NXMLElementReader(); } NXMLElementReader* NXMLNormalSurfaceListReader::startContentSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict& props) { if (list) { // The surface list has already been created. if (subTagName == "surface") return new NXMLNormalSurfaceReader(tri, list->coords_); } else { // The surface list has not yet been created. if (subTagName == "params") { long coords; int listType, algorithm; bool embedded; if (valueOf(props.lookup("flavourid"), coords)) { if (valueOf(props.lookup("type"), listType) && valueOf(props.lookup("algorithm"), algorithm)) { // Parameters look sane; create the empty list. list = new NNormalSurfaceList( static_cast(coords), NormalList::fromInt(listType), NormalAlg::fromInt(algorithm)); } else if (valueOf(props.lookup("embedded"), embedded)) { // Parameters look sane but use the old format. list = new NNormalSurfaceList( static_cast(coords), NS_LEGACY | (embedded ? NS_EMBEDDED_ONLY : NS_IMMERSED_SINGULAR), NS_ALG_LEGACY); } } } } return new NXMLElementReader(); } void NXMLNormalSurfaceListReader::endContentSubElement( const std::string& subTagName, NXMLElementReader* subReader) { if (list) if (subTagName == "surface") if (NNormalSurface* s = dynamic_cast(subReader)-> getSurface()) list->surfaces.push_back(s); } NXMLPacketReader* NNormalSurfaceList::getXMLReader(NPacket* parent, NXMLTreeResolver& resolver) { return new NXMLNormalSurfaceListReader( dynamic_cast(parent), resolver); } } // namespace regina regina-4.96/engine/surfaces/nxmlsurfacereader.h000644 000765 000024 00000014123 12377775603 021575 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/nxmlsurfacereader.h * \brief Deals with parsing XML data for normal surface lists. */ #ifndef __NXMLSURFACEREADER_H #ifndef __DOXYGEN #define __NXMLSURFACEREADER_H #endif #include "regina-core.h" #include "packet/nxmlpacketreader.h" #include "surfaces/nnormalsurfacelist.h" namespace regina { /** * \weakgroup surfaces * @{ */ /** * An XML element reader that reads a single normal surface. * * \ifacespython Not present. */ class REGINA_API NXMLNormalSurfaceReader : public NXMLElementReader { private: NNormalSurface* surface; /**< The normal surface currently being read. */ const NTriangulation* tri; /**< The triangulation in which this surface lives. */ NormalCoords coords; /**< The coordinate system used by this surface. */ long vecLen; /**< The length of corresponding normal surface vector. */ std::string name; /**< The optional name associated with this normal surface. */ public: /** * Creates a new normal surface reader. * * @param newTri the triangulation in which this normal surface lives. * @param newCoords the coordinate system used by this normal surface. */ NXMLNormalSurfaceReader(const NTriangulation* newTri, NormalCoords newCoords); /** * Returns the normal surface that has been read. * * @return the newly allocated normal surface, or 0 if an error * occurred. */ NNormalSurface* getSurface(); virtual void startElement(const std::string& tagName, const regina::xml::XMLPropertyDict& tagProps, NXMLElementReader* parentReader); virtual void initialChars(const std::string& chars); virtual NXMLElementReader* startSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict& subTagProps); }; /** * An XML packet reader that reads a single normal surface list. * * \pre The parent XML element reader is in fact an * NXMLTriangulationReader. * * \ifacespython Not present. */ class REGINA_API NXMLNormalSurfaceListReader : public NXMLPacketReader { private: NNormalSurfaceList* list; /**< The normal surface list currently being read. */ const NTriangulation* tri; /**< The triangulation in which these normal surfaces live. */ public: /** * Creates a new normal surface list reader. * * @param newTri the triangulation in which these normal surfaces live. * @param resolver the master resolver that will be used to fix * dangling packet references after the entire XML file has been read. */ NXMLNormalSurfaceListReader(const NTriangulation* newTri, NXMLTreeResolver& resolver); virtual NPacket* getPacket(); virtual NXMLElementReader* startContentSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict& subTagProps); virtual void endContentSubElement(const std::string& subTagName, NXMLElementReader* subReader); }; /*@}*/ // Inline functions for NXMLNormalSurfaceReader inline NXMLNormalSurfaceReader::NXMLNormalSurfaceReader( const NTriangulation* newTri, NormalCoords newCoords) : surface(0), tri(newTri), coords(newCoords), vecLen(-1) { } inline NNormalSurface* NXMLNormalSurfaceReader::getSurface() { return surface; } // Inline functions for NXMLNormalSurfaceListReader inline NXMLNormalSurfaceListReader::NXMLNormalSurfaceListReader( const NTriangulation* newTri, NXMLTreeResolver& resolver) : NXMLPacketReader(resolver), list(0), tri(newTri) { } inline NPacket* NXMLNormalSurfaceListReader::getPacket() { return list; } } // namespace regina #endif regina-4.96/engine/surfaces/orientable.cpp000644 000765 000024 00000021757 12377776740 020560 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "surfaces/ndisc.h" namespace regina { namespace { /** * Stores orientation and sides A/B for a normal disc. */ struct OrientData { int orient; /**< Specifies the orientation of the disc. 1 represents with the natural boundary orientation. -1 represents against the natural boundary orientation. 0 means orientation is not yet determined. */ int sides; /**< Specifies which sides of the disc are sides A/B. If sides is 1, discs are numbered from side A to B. If sides is -1, discs are numbered from side B to A. A value of 0 means sides are not yet determined. */ /** * Create a new structure with all values initialised to 0. */ OrientData() : orient(0), sides(0) { } }; } void NNormalSurface::calculateOrientable() const { // This is going to be ghastly. // We will create an orientation and side selection for every disc. // First check that the precondition (compactness) holds, since if // it doesn't we'll have a rather nasty crash (thanks Nathan). if (! isCompact()) { orientable.clear(); twoSided.clear(); connected.clear(); return; } // All right. Off we go. orientable.clear(); twoSided.clear(); connected.clear(); NDiscSetSurfaceData orients(*this); // Stores the orientation of each disc. std::queue discQueue; // A queue of discs whose orientations must be propagated. NDiscSpecIterator it(orients); // Runs through the discs whose orientations might not have yet // been determined. NDiscSpec use; // The disc that currently holds our interest. int nGluingArcs; // The number of arcs on the current disc to // which an adjacent disc might may be glued. NDiscSpec* adjDisc; // The disc to which the current disc is glued. NPerm4 arc[8]; // Holds each gluing arc for the current disc. NPerm4 adjArc; // Represents the corresponding gluing arc on the // adjacent disc. bool myOrient, yourOrient, sameOrient; bool mySides, yourSides, sameSides; int i; bool noComponents = true; while (true) { // If there's no discs to propagate from, choose the next // unoriented one. while (discQueue.empty() && (! it.done())) { if (orients.data(*it).orient == 0) { orients.data(*it).orient = 1; orients.data(*it).sides = 1; discQueue.push(*it); if (noComponents) noComponents = false; else connected = false; } it++; } if (discQueue.empty()) break; // At the head of the queue is the next already-oriented disc // whose orientation must be propagated. use = discQueue.front(); discQueue.pop(); // Determine along which arcs we may glue other discs. if (use.type < 4) { // Current disc is a triangle. nGluingArcs = 3; for (i = 0; i < 3; i++) arc[i] = triDiscArcs(use.type, i); } else if (use.type < 7) { // Current disc is a quad. nGluingArcs = 4; for (i = 0; i < 4; i++) arc[i] = quadDiscArcs(use.type - 4, i); } else { // Current disc is an octagon. nGluingArcs = 8; for (i = 0; i < 8; i++) arc[i] = octDiscArcs(use.type - 7, i); } // Process any discs that might be adjacent to each of these // gluing arcs. for (i = 0; i < nGluingArcs; i++) { // Establish which is the adjacent disc. adjDisc = orients.adjacentDisc(use, arc[i], adjArc); if (adjDisc == 0) continue; // There is actually a disc glued along this arc. // Determine the desired properties of the adjacent disc. if (! orientable.known()) { myOrient = discOrientationFollowsEdge(use.type, arc[i][0], arc[i][1], arc[i][2]); yourOrient = discOrientationFollowsEdge(adjDisc->type, adjArc[0], adjArc[2], adjArc[1]); sameOrient = (myOrient && yourOrient) || ((! myOrient) && (! yourOrient)); } else sameOrient = true; if (! twoSided.known()) { mySides = numberDiscsAwayFromVertex(use.type, arc[i][0]); yourSides = numberDiscsAwayFromVertex( adjDisc->type, adjArc[0]); sameSides = (mySides && yourSides) || ((! mySides) && (! yourSides)); } else sameSides = true; // Propagate these properties. if (orients.data(*adjDisc).orient == 0) { orients.data(*adjDisc).orient = (sameOrient ? orients.data(use).orient : -orients.data(use).orient); orients.data(*adjDisc).sides = (sameSides ? orients.data(use).sides : -orients.data(use).sides); discQueue.push(*adjDisc); } else { if (! orientable.known()) { if (sameOrient) { if (orients.data(*adjDisc).orient != orients.data(use).orient) orientable = false; } else { if (orients.data(*adjDisc).orient == orients.data(use).orient) orientable = false; } } if (! twoSided.known()) { if (sameSides) { if (orients.data(*adjDisc).sides != orients.data(use).sides) twoSided = false; } else { if (orients.data(*adjDisc).sides == orients.data(use).sides) twoSided = false; } } } // Tidy up. delete adjDisc; if (orientable.known() && twoSided.known() && connected.known()) return; } } // We made it through! Any properties that weren't proven false // must be true. if (! orientable.known()) orientable = true; if (! twoSided.known()) twoSided = true; if (! connected.known()) connected = true; } } // namespace regina regina-4.96/engine/surfaces/quadtostd.cpp000644 000765 000024 00000062566 12377776740 020447 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "regina-config.h" #include "enumerate/ndoubledescription.h" #include "maths/nmatrixint.h" #include "maths/nray.h" #include "surfaces/nnormalsurface.h" #include "surfaces/nnormalsurfacelist.h" #include "surfaces/normalspec-impl.h" #include "triangulation/ntriangulation.h" #include "triangulation/nvertex.h" #include "utilities/nbitmask.h" #include #include namespace regina { // Although the conversion routines are template routines, we implement // them here in this C++ file to avoid dragging them into the headers. // // The following definitions and declarations should ensure that the // templates are fully instantiated where they need to be. NNormalSurfaceList* NNormalSurfaceList::quadToStandard() const { return internalReducedToStandard(); } NNormalSurfaceList* NNormalSurfaceList::quadOctToStandardAN() const { return internalReducedToStandard(); } template void NNormalSurfaceList::buildStandardFromReduced< NNormalSurfaceList::NormalSpec>(NTriangulation*, const std::vector&, NProgressTracker*); template void NNormalSurfaceList::buildStandardFromReduced< NNormalSurfaceList::AlmostNormalSpec>(NTriangulation*, const std::vector&, NProgressTracker*); /** * Put helper classes and constants into an anonymous namespace. */ namespace { /** * A back insertion iterator that defines \a value_type, which is * required by NDoubleDescription::enumerate(). * * The standard back_insert_iterator does not provide this typedef, * so we subclass and provide the typedef ourselves. */ class VectorInserter : public std::back_insert_iterator< std::vector > { public: typedef NNormalSurfaceVector* value_type; VectorInserter(std::vector& v) : std::back_insert_iterator< std::vector >(v) { } }; /** * A helper class for converting between reduced and standard * solution sets, describing a single ray (which is typically a * vertex in some partial solution space). * * This class derives from NRay, which stores the coordinates of * the ray itself in standard coordinates. This RaySpec class also * stores a bitmask indicating which of these coordinates are set to zero. * * The \a BitmaskType template argument describes how the bitmask of * zero coordinates will be stored. The ith coordinate position * corresponds to the ith bit in the bitmask, and each bit is set * to \c true if and only if the corresponding coordinate is zero. * * Since this class is used heavily, faster bitmask types such as * NBitmask1 and NBitmask2 are preferred; however, if the number * of coordinates is too large then the slower general-use NBitmask * class will need to be used instead. * * \pre The template argument \a BitmaskType is one of Regina's * bitmask types, such as NBitmask, NBitmask1 or NBitmask2. */ template class RaySpec : private NRay { private: BitmaskType facets_; /**< A bitmask listing which coordinates of this ray are currently set to zero. */ public: /** * Creates a new ray whose coordinates are a clone of the * given vector. * * @param v the vector to clone. */ RaySpec(const NNormalSurfaceVector* v) : NRay(v->size()), facets_(v->size()) { // Note that the vector is initialised to zero since // this is what NLargeInteger's default constructor does. for (size_t i = 0; i < v->size(); ++i) if ((elements[i] = (*v)[i]) == zero) facets_.set(i, true); } /** * Creates a new ray that represents the \e negative of * the link of the given vertex. * * @param tri the underlying triangulation. * @param whichLink the index of the vertex whose link * we should negate; this must be strictly less than * tri->getNumberOfVertices(). * @param coordsPerTet the number of standard coordinate * positions for each tetrahedron (that is, 7 if we are * working with normal surfaces, or 10 if we are working * with almost normal surfaces). */ RaySpec(const NTriangulation* tri, unsigned long whichLink, unsigned coordsPerTet) : NRay(coordsPerTet * tri->getNumberOfTetrahedra()), facets_(coordsPerTet * tri->getNumberOfTetrahedra()) { // Note that the vector is initialised to zero since // this is what NLargeInteger's default constructor does. for (size_t i = 0; i < size(); ++i) if (i % coordsPerTet > 3) { // Not a triangular coordinate. facets_.set(i, true); } else if (tri->getTetrahedron(i / coordsPerTet)-> getVertex(i % coordsPerTet)->markedIndex() == whichLink) { // A triangular coordinate in our vertex link. elements[i] = -1; } else { // A triangular coordinate not in our vertex link. facets_.set(i, true); } } /** * Creates a new ray, describing where the plane between the * two given rays meets the given axis hyperplane. Here * "the given axis hyperplane" means the hyperplane along which * the coordth coordinate is zero. * * \pre The coordth coordinates of \a pos and \a neg * are strictly positive and negative respectively. * * @param pos the first of the given rays, in which the given * coordinate is positive. * @param neg the second of the given rays, in which the given * coordinate is negative. * @param coord the index of the coordinate that we must set * to zero to form the intersecting hyperplane. */ RaySpec(const RaySpec& pos, const RaySpec& neg, size_t coord) : NRay(pos.size()), facets_(pos.facets_) { facets_ &= neg.facets_; // Note that we may need to re-enable some bits in \a facets_, // since we may end up setting some triangle coordinates // to zero that were not zero in either \a pos or \a neg. NLargeInteger posDiff = pos[coord]; NLargeInteger negDiff = neg[coord]; for (size_t i = 0; i < size(); ++i) if ((elements[i] = neg[i] * posDiff - pos[i] * negDiff) == zero) facets_.set(i, true); scaleDown(); } /** * Returns the bitmask listing which coordinates of this ray * are currently set to zero. See the class notes for details. * * The length of this bitmask is the same as the length of the * underlying vector for this ray. * * @return the bitmask of zero coordinates. */ inline const BitmaskType& facets() const { return facets_; } /** * Determines whether this ray has zero coordinates in every * position where \e both of the given rays simultaneously * have zero coordinates. * * The bitmask \a ignoreFacets represents a list of coordinate * positions that should be ignored for the purposes of this * routine. * * @param x the first of the two given rays to examine. * @param y the second of the two given rays to examine. * @param ignoreFacets a bitmask of coordinate positions to * ignore. * @return \c false if there is some coordinate position * where (i) both \a x and \a y are zero, (ii) this vector * is not zero, and (iii) the corresponding bit in \a ignoreFacets * is not set (i.e., is \c false). Returns \c true otherwise. */ inline bool onAllCommonFacets(const RaySpec& x, const RaySpec& y, BitmaskType ignoreFacets) const { ignoreFacets |= facets_; return ignoreFacets.containsIntn(x.facets_, y.facets_); } /** * Reduces the underlying vector by subtracting as many copies * of the given vertex link as possible, without allowing any of * the corresponding coordinates in this ray to become negative. * * \pre None of the coordinates in this ray that correspond * to discs in the given vertex link are already negative. * * @param link the vertex link to subtract copies of. */ void reduce(const RaySpec& link) { if (! (facets_ <= link.facets_)) return; NLargeInteger max = NLargeInteger::infinity; size_t i; for (i = 0; i < size(); ++i) if (! link.facets_.get(i)) if (max > elements[i]) max = elements[i]; for (i = 0; i < size(); ++i) if (! link.facets_.get(i)) if ((elements[i] -= max) == zero) facets_.set(i, true); } /** * Returns a new normal (or almost normal) surface whose * coordinates are described by this vector. The template * argument dictates the class of the underlying normal surface * vector (i.e., the underlying coordinate system). * * @param tri the underlying triangulation. * @return a newly created normal surface based on this vector. */ template NNormalSurface* recover(NTriangulation* tri) const { VectorClass* v = new VectorClass(size()); for (size_t i = 0; i < size(); ++i) v->setElement(i, elements[i]); return new NNormalSurface(tri, v); } /** * Returns the sign of the given element of this vector. * * @return 1, 0 or -1 according to whether the indexth * element of this vector is positive, zero or negative * respectively. */ inline int sign(size_t index) const { if (facets_.get(index)) return 0; return (elements[index] > zero ? 1 : -1); } using NRay::scaleDown; }; } // anonymous namespace template NNormalSurfaceList* NNormalSurfaceList::internalReducedToStandard() const { NTriangulation* owner = getTriangulation(); // Basic sanity checks: if (coords_ != Variant::reducedCoords()) return 0; if (which_ != (NS_EMBEDDED_ONLY | NS_VERTEX)) return 0; if (owner->isIdeal() || ! owner->isValid()) return 0; // Prepare a final surface list. NNormalSurfaceList* ans = new NNormalSurfaceList( Variant::standardCoords(), NS_EMBEDDED_ONLY | NS_VERTEX, algorithm_ | NS_VERTEX_VIA_REDUCED); if (owner->getNumberOfTetrahedra() > 0) { // Run our internal conversion routine. ans->buildStandardFromReduced(owner, surfaces); } // All done! owner->insertChildLast(ans); return ans; } template void NNormalSurfaceList::buildStandardFromReduced(NTriangulation* owner, const std::vector& reducedList, NProgressTracker* tracker) { size_t nFacets = Variant::stdLen(owner->getNumberOfTetrahedra()); // Choose a bitmask type for representing the set of facets that a // ray belongs to; in particular, use a (much faster) optimised // bitmask type if we can. // Then farm the work out to the real conversion routine that is // templated on the bitmask type. if (nFacets <= 8 * sizeof(unsigned)) buildStandardFromReducedUsing >(owner, reducedList, tracker); else if (nFacets <= 8 * sizeof(unsigned long)) buildStandardFromReducedUsing >(owner, reducedList, tracker); #ifdef LONG_LONG_FOUND else if (nFacets <= 8 * sizeof(unsigned long long)) buildStandardFromReducedUsing >(owner, reducedList, tracker); else if (nFacets <= 8 * sizeof(unsigned long long) + 8 * sizeof(unsigned)) buildStandardFromReducedUsing >(owner, reducedList, tracker); else if (nFacets <= 8 * sizeof(unsigned long long) + 8 * sizeof(unsigned long)) buildStandardFromReducedUsing >(owner, reducedList, tracker); else if (nFacets <= 16 * sizeof(unsigned long long)) buildStandardFromReducedUsing >(owner, reducedList, tracker); #else else if (nFacets <= 8 * sizeof(unsigned long) + 8 * sizeof(unsigned)) buildStandardFromReducedUsing >(owner, reducedList, tracker); else if (nFacets <= 16 * sizeof(unsigned long)) buildStandardFromReducedUsing >(owner, reducedList, tracker); #endif else buildStandardFromReducedUsing(owner, reducedList, tracker); } template void NNormalSurfaceList::buildStandardFromReducedUsing(NTriangulation* owner, const std::vector& reducedList, NProgressTracker* tracker) { // Prepare for the reduced-to-standard double description run. unsigned long n = owner->getNumberOfTetrahedra(); size_t slen = Variant::stdLen(n); // # standard coordinates unsigned long llen = owner->getNumberOfVertices(); // # vertex links unsigned i; // Recreate the quadrilateral constraints (or the corresponding // constraints for almost normal surfaces) as bitmasks. // Since we have a non-empty triangulation, we know the list of // constraints is non-empty. NEnumConstraintList* constraints = Variant::StandardVector::makeEmbeddedConstraints(owner); BitmaskType* constraintsBegin = new BitmaskType[constraints->size()]; BitmaskType* constraintsEnd = constraintsBegin; NEnumConstraintList::const_iterator cit; for (NEnumConstraintList::const_iterator cit = constraints->begin(); cit != constraints->end(); ++cit, ++constraintsEnd) { constraintsEnd->reset(slen); constraintsEnd->set(cit->begin(), cit->end(), true); } delete constraints; // Create all vertex links. typename Variant::StandardVector** link = new typename Variant::StandardVector*[llen]; for (i = 0; i < llen; ++i) { link[i] = new typename Variant::StandardVector(slen); const std::vector& emb = owner->getVertex(i)-> getEmbeddings(); std::vector::const_iterator embit; for (embit = emb.begin(); embit != emb.end(); ++embit) link[i]->setElement(Variant::stdPos( embit->getTetrahedron()->markedIndex(), embit->getVertex()), 1); } // Create the initial set of rays: typedef std::vector*> RaySpecList; RaySpecList list[2]; NNormalSurfaceVector* v; std::vector::const_iterator qit; for (qit = reducedList.begin(); qit != reducedList.end(); ++qit) { v = static_cast( (*qit)->rawVector())->makeMirror(owner); list[0].push_back(new RaySpec( static_cast(v))); delete v; } // Each additional inequality is of the form tri_coord >= 0. // We will therefore just create them on the fly as we need them. // And run! BitmaskType ignoreFacets(slen); for (i = 0; i < slen; ++i) if (i % Variant::totalPerTet < 4) ignoreFacets.set(i, true); int workingList = 0; unsigned vtx; size_t tcoord; RaySpec* linkSpec; RaySpecList pos, neg; typename RaySpecList::iterator it, posit, negit; int sign; BitmaskType* constraintMask; bool broken; unsigned long slices = 0; unsigned iterations; for (vtx = 0; vtx < llen; ++vtx) { linkSpec = new RaySpec(link[vtx]); delete link[vtx]; list[workingList].push_back(new RaySpec(owner, vtx, Variant::totalPerTet)); const std::vector& emb = owner->getVertex(vtx)-> getEmbeddings(); std::vector::const_iterator embit; for (embit = emb.begin(); embit != emb.end(); ++embit) { // Update the state of progress and test for cancellation. if (tracker && ! tracker->setPercent(25.0 * slices++ / n)) { for (it = list[workingList].begin(); it != list[workingList].end(); ++it) delete *it; return; } tcoord = Variant::stdPos(embit->getTetrahedron()->markedIndex(), embit->getVertex()); // Add the inequality v[tcoord] >= 0. for (it = list[workingList].begin(); it != list[workingList].end(); ++it) { sign = (*it)->sign(tcoord); if (sign == 0) list[1 - workingList].push_back(*it); else if (sign > 0) { list[1 - workingList].push_back(*it); pos.push_back(*it); } else neg.push_back(*it); } iterations = 0; for (posit = pos.begin(); posit != pos.end(); ++posit) for (negit = neg.begin(); negit != neg.end(); ++negit) { // Test for cancellation, but not every time (since // this involves expensive mutex locking). if (tracker && ++iterations == 100) { iterations = 0; if (tracker->isCancelled()) { for (it = list[1 - workingList].begin(); it != list[1 - workingList].end(); ++it) delete *it; for (it = neg.begin(); it != neg.end(); ++it) delete *it; return; } } // Find the facets that both rays have in common. BitmaskType join((*posit)->facets()); join &= ((*negit)->facets()); // Fukuda and Prodon's dimensional filtering. // Initial experimentation suggests that this // is not helpful (perhaps because of the extremely // nice structure of this particular enumeration problem // and the consequential way in which one solution set // expands to the next). Comment it out for now. /* BitmaskType tmpMask(ignoreFacets); tmpMask.flip(); tmpMask &= join; if (tmpMask.bits() < 2 * n + vtx - 1) continue; */ // Are these vectors compatible? // Invert join so that it has a true bit for each // non-zero coordinate. join.flip(); broken = false; for (constraintMask = constraintsBegin; constraintMask != constraintsEnd; ++constraintMask) { BitmaskType mask(join); mask &= *constraintMask; if (! mask.atMostOneBit()) { broken = true; break; } } if (broken) continue; // Are these vectors adjacent? broken = false; for (it = list[workingList].begin(); it != list[workingList].end(); ++it) { if (*it != *posit && *it != *negit && (*it)->onAllCommonFacets(**posit, **negit, ignoreFacets)) { broken = true; break; } } if (broken) continue; // All good! Join them and put the intersection in the // new solution set. list[1 - workingList].push_back(new RaySpec( **posit, **negit, tcoord)); } // Clean up and prepare for the next iteration. for (negit = neg.begin(); negit != neg.end(); ++negit) delete *negit; pos.clear(); neg.clear(); list[workingList].clear(); ignoreFacets.set(tcoord, false); workingList = 1 - workingList; } // We're done cancelling this vertex link. // Now add the vertex link itself, and cancel any future vertex // links that we might have created. // Note that cancelling future vertex links might introduce // new common factors that can be divided out. list[workingList].push_back(linkSpec); for (it = list[workingList].begin(); it != list[workingList].end(); ++it) { for (i = vtx + 1; i < llen; ++i) (*it)->reduce(link[i]); (*it)->scaleDown(); } } // All done! Put the solutions into the normal surface list and clean up. for (typename RaySpecList::iterator it = list[workingList].begin(); it != list[workingList].end(); ++it) { surfaces.push_back((*it)-> template recover(owner)); delete *it; } delete[] link; delete[] constraintsBegin; if (tracker) tracker->setPercent(100); } } // namespace regina regina-4.96/engine/surfaces/sfcombination.cpp000644 000765 000024 00000006520 12377776741 021257 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "surfaces/sfcombination.h" #define TYPE_AND 1 #define TYPE_OR 2 namespace regina { bool NSurfaceFilterCombination::accept(const NNormalSurface& surface) const { if (usesAnd) { // Combine all child filters using AND. for (NPacket* child = getFirstTreeChild(); child; child = child->getNextTreeSibling()) if (child->getPacketType() == NSurfaceFilter::packetType) if (! (dynamic_cast(child)->accept(surface))) return false; return true; } else { // Combine all child filters using OR. for (NPacket* child = getFirstTreeChild(); child; child = child->getNextTreeSibling()) if (child->getPacketType() == NSurfaceFilter::packetType) if (dynamic_cast(child)->accept(surface)) return true; return false; } } void NSurfaceFilterCombination::writeXMLFilterData(std::ostream& out) const { out << " \n"; } } // namespace regina regina-4.96/engine/surfaces/sfcombination.h000644 000765 000024 00000013621 12377775604 020721 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/sfcombination.h * \brief Contains a normal surface filter that simply combines other * filters. */ #ifndef __SFCOMBINATION_H #ifndef __DOXYGEN #define __SFCOMBINATION_H #endif #include "regina-core.h" #include "surfaces/nsurfacefilter.h" namespace regina { class NSurfaceFilterCombination; /** * \weakgroup surfaces * @{ */ /** * Stores information about the combination surface filter. * See the general SurfaceFilterInfo template notes for further details. * * \ifacespython Not present. */ template <> struct SurfaceFilterInfo { typedef NSurfaceFilterCombination Class; inline static const char* name() { return "Combination filter"; } }; /** * A normal surface filter that simply combines other filters. * This filter will combine, using boolean \a and or \a or, all of the * filters that are immediate children of this packet. This packet may * have children that are not normal surface filters; such children will * simply be ignored. * * If there are no immediate child filters, a normal surface will be * accepted if this is an \a and filter and rejected if this is an \a or * filter. */ class REGINA_API NSurfaceFilterCombination : public NSurfaceFilter { REGINA_SURFACE_FILTER(NSurfaceFilterCombination, NS_FILTER_COMBINATION) private: bool usesAnd; /**< \c true if children are combined using boolean \a and, or \c false if children are combined using boolean \a or. */ public: /** * Creates a new surface filter that accepts all normal surfaces. * This will be an \a and filter. */ NSurfaceFilterCombination(); /** * Creates a new surface filter that is a clone of the given * surface filter. * * @param cloneMe the surface filter to clone. */ NSurfaceFilterCombination(const NSurfaceFilterCombination& cloneMe); /** * Determines whether this is an \a and or an \a or combination. * * @return \c true if this is an \a and combination, or \c false * if this is an \a or combination. */ bool getUsesAnd() const; /** * Sets whether this is an \a and or an \a or combination. * * @param value \c true if this is to be an \a and combination, * or \c false if this is to be an \a or combination. */ void setUsesAnd(bool value); virtual bool accept(const NNormalSurface& surface) const; virtual void writeTextLong(std::ostream& out) const; static NXMLFilterReader* getXMLFilterReader(NPacket* parent); protected: virtual NPacket* internalClonePacket(NPacket* parent) const; virtual void writeXMLFilterData(std::ostream& out) const; }; /*@}*/ // Inline functions for NSurfaceFilterCombination inline NSurfaceFilterCombination::NSurfaceFilterCombination() : usesAnd(true) { } inline NSurfaceFilterCombination::NSurfaceFilterCombination( const NSurfaceFilterCombination& cloneMe) : NSurfaceFilter(), usesAnd(cloneMe.usesAnd) { } inline bool NSurfaceFilterCombination::getUsesAnd() const { return usesAnd; } inline void NSurfaceFilterCombination::setUsesAnd(bool value) { if (usesAnd != value) { ChangeEventSpan span(this); usesAnd = value; } } inline void NSurfaceFilterCombination::writeTextLong(std::ostream& o) const { o << (usesAnd ? "AND" : "OR") << " combination normal surface filter\n"; } inline NPacket* NSurfaceFilterCombination::internalClonePacket(NPacket*) const { return new NSurfaceFilterCombination(*this); } } // namespace regina #endif regina-4.96/engine/surfaces/sfproperties.cpp000644 000765 000024 00000011242 12377776742 021147 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "surfaces/sfproperties.h" #include "surfaces/nnormalsurface.h" #include "utilities/xmlutils.h" #define PROPSF_EULER 1001 #define PROPSF_ORIENT 1002 #define PROPSF_COMPACT 1003 #define PROPSF_REALBDRY 1004 namespace regina { NLargeInteger NSurfaceFilterProperties::getEC(unsigned long index) const { std::set::const_iterator it = eulerChar.begin(); advance(it, index); return *it; } bool NSurfaceFilterProperties::accept(const NNormalSurface& surface) const { if (! realBoundary.contains(surface.hasRealBoundary())) return false; if (! compactness.contains(surface.isCompact())) return false; // Some properties may only be calculated for compact surfaces. if (surface.isCompact()) { if (! orientability.contains(surface.isOrientable())) return false; if (eulerChar.size() > 0) if (! eulerChar.count(surface.getEulerChar())) return false; } // All tests passed. return true; } void NSurfaceFilterProperties::writeTextLong(std::ostream& o) const { o << "Filter normal surfaces with restrictions:\n"; if (eulerChar.size() > 0) { o << " Euler characteristic:"; std::set::const_reverse_iterator it; for (it = eulerChar.rbegin(); it != eulerChar.rend(); it++) o << ' ' << *it; o << '\n'; } if (orientability != NBoolSet::sBoth) o << " Orientability: " << orientability << '\n'; if (compactness != NBoolSet::sBoth) o << " Compactness: " << compactness << '\n'; if (realBoundary != NBoolSet::sBoth) o << " Has real boundary: " << realBoundary << '\n'; } void NSurfaceFilterProperties::writeXMLFilterData(std::ostream& out) const { using regina::xml::xmlValueTag; if (eulerChar.size() > 0) { out << " "; for (std::set::const_iterator it = eulerChar.begin(); it != eulerChar.end(); it++) out << (*it) << ' '; out << "\n"; } if (orientability != NBoolSet::sBoth) out << " " << xmlValueTag("orbl", orientability) << '\n'; if (compactness != NBoolSet::sBoth) out << " " << xmlValueTag("compact", compactness) << '\n'; if (realBoundary != NBoolSet::sBoth) out << " " << xmlValueTag("realbdry", realBoundary) << '\n'; } } // namespace regina regina-4.96/engine/surfaces/sfproperties.h000644 000765 000024 00000026454 12377775607 020626 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/sfproperties.h * \brief Contains a normal surface filter that filters by basic * properties. */ #ifndef __SFPROPERTIES_H #ifndef __DOXYGEN #define __SFPROPERTIES_H #endif #include #include "regina-core.h" #include "maths/ninteger.h" #include "surfaces/nsurfacefilter.h" #include "utilities/nbooleans.h" namespace regina { class NSurfaceFilterProperties; /** * \weakgroup surfaces * @{ */ /** * Stores information about the property-based surface filter. * See the general SurfaceFilterInfo template notes for further details. * * \ifacespython Not present. */ template <> struct SurfaceFilterInfo { typedef NSurfaceFilterProperties Class; inline static const char* name() { return "Filter by basic properties"; } }; /** * A normal surface filter that filters by basic properties of the normal * surface. * * If a property of the surface (such as Euler characteristic or * orientability) cannot be determined, the surface will pass any test * based on that particular property. For instance, say a surface is * required to be both orientable and compact, and say that orientability * cannot be determined. Then the surface will be accepted solely on the * basis of whether or not it is compact. */ class REGINA_API NSurfaceFilterProperties : public NSurfaceFilter { REGINA_SURFACE_FILTER(NSurfaceFilterProperties, NS_FILTER_PROPERTIES) private: std::set eulerChar; /**< The set of allowable Euler characteristics. An empty set signifies that any Euler characteristic is allowed. */ NBoolSet orientability; /**< The set of allowable orientability properties. */ NBoolSet compactness; /**< The set of allowable compactness properties. */ NBoolSet realBoundary; /**< The set of allowable has-real-boundary properties. */ public: /** * Creates a new surface filter that accepts all normal surfaces. */ NSurfaceFilterProperties(); /** * Creates a new surface filter that is a clone of the given * surface filter. * * @param cloneMe the surface filter to clone. */ NSurfaceFilterProperties(const NSurfaceFilterProperties& cloneMe); /** * Returns the set of allowable Euler characteristics. Any * surface whose Euler characteristic is not in this set will not * be accepted by this filter. The set will be given in * ascending order with no element repeated. * * If this set is empty, all Euler characteristics will be * accepted. * * \ifacespython This routine returns a python sequence. * * @return the set of allowable Euler characteristics. */ const std::set& getECs() const; /** * Returns the number of allowable Euler characteristics. * See getECs() for further details. * * @return the number of allowable Euler characteristics. */ unsigned long getNumberOfECs() const; /** * Returns the allowable Euler characteristic at the given index * in the set. See getECs() for further details. * * @param index the index in the set of allowable Euler * characteristics; this must be between 0 and getNumberOfECs()-1 * inclusive. * @return the requested allowable Euler characteristic. */ NLargeInteger getEC(unsigned long index) const; /** * Returns the set of allowable orientabilities. Note that this * is a subset of { true, false }. * Any surface whose orientability is not in this set will not be * accepted by this filter. * * @return the set of allowable orientabilities. */ NBoolSet getOrientability() const; /** * Returns the set of allowable compactness properties. * Note that this is a subset of { true, false }. * Any surface whose compactness property is not in this set will * not be accepted by this filter. * * @return the set of allowable compactness properties. */ NBoolSet getCompactness() const; /** * Returns the set of allowable has-real-boundary properties. * Note that this is a subset of { true, false }. * Any surface whose has-real-boundary property is not in this set * will not be accepted by this filter. * * @return the set of allowable has-real-boundary properties. */ NBoolSet getRealBoundary() const; /** * Adds the given Euler characteristic to the set of allowable * Euler characteristics. See getECs() for further details. * * @param ec the new allowable Euler characteristic. */ void addEC(const NLargeInteger& ec); /** * Removes the given Euler characteristic from the set of allowable * Euler characteristics. See getECs() for further details. * * Note that if the allowable set is completely emptied, this * filter will allow any Euler characteristic to pass. * * \pre The given Euler characteristic is currently in the * allowable set. * * @param ec the allowable Euler characteristic to remove. */ void removeEC(const NLargeInteger& ec); /** * Empties the set of allowable Euler characteristics. See * getECs() for further details. * * Note that this will mean that this filter will allow * any Euler characteristic to pass. */ void removeAllECs(); /** * Sets the set of allowable orientabilities. * See getOrientability() for further details. * * @param value the new set of allowable orientabilities. */ void setOrientability(const NBoolSet& value); /** * Sets the set of allowable compactness properties. * See getCompactness() for further details. * * @param value the new set of allowable compactness properties. */ void setCompactness(const NBoolSet& value); /** * Sets the set of allowable has-real-boundary properties. * See getRealBoundary() for further details. * * @param value the new set of allowable has-real-boundary * properties. */ void setRealBoundary(const NBoolSet& value); virtual bool accept(const NNormalSurface& surface) const; virtual void writeTextLong(std::ostream& out) const; static NXMLFilterReader* getXMLFilterReader(NPacket* parent); protected: virtual NPacket* internalClonePacket(NPacket* parent) const; virtual void writeXMLFilterData(std::ostream& out) const; }; /*@}*/ // Inline functions for NSurfaceFilterProperties inline NSurfaceFilterProperties::NSurfaceFilterProperties() : orientability(NBoolSet::sBoth), compactness(NBoolSet::sBoth), realBoundary(NBoolSet::sBoth) { } inline NSurfaceFilterProperties::NSurfaceFilterProperties( const NSurfaceFilterProperties& cloneMe) : NSurfaceFilter(), eulerChar(cloneMe.eulerChar), orientability(cloneMe.orientability), compactness(cloneMe.compactness), realBoundary(cloneMe.realBoundary) { } inline const std::set& NSurfaceFilterProperties::getECs() const { return eulerChar; } inline unsigned long NSurfaceFilterProperties::getNumberOfECs() const { return eulerChar.size(); } inline NBoolSet NSurfaceFilterProperties::getOrientability() const { return orientability; } inline NBoolSet NSurfaceFilterProperties::getCompactness() const { return compactness; } inline NBoolSet NSurfaceFilterProperties::getRealBoundary() const { return realBoundary; } inline void NSurfaceFilterProperties::addEC(const NLargeInteger& ec) { ChangeEventSpan span(this); eulerChar.insert(ec); } inline void NSurfaceFilterProperties::removeEC(const NLargeInteger& ec) { ChangeEventSpan span(this); eulerChar.erase(ec); } inline void NSurfaceFilterProperties::removeAllECs() { ChangeEventSpan span(this); eulerChar.clear(); } inline void NSurfaceFilterProperties::setOrientability(const NBoolSet& value) { if (orientability != value) { ChangeEventSpan span(this); orientability = value; } } inline void NSurfaceFilterProperties::setCompactness(const NBoolSet& value) { if (compactness != value) { ChangeEventSpan span(this); compactness = value; } } inline void NSurfaceFilterProperties::setRealBoundary(const NBoolSet& value) { if (realBoundary != value) { ChangeEventSpan span(this); realBoundary = value; } } inline NPacket* NSurfaceFilterProperties::internalClonePacket(NPacket*) const { return new NSurfaceFilterProperties(*this); } } // namespace regina #endif regina-4.96/engine/surfaces/spheres.cpp000644 000765 000024 00000015620 12377776742 020077 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "surfaces/nnormalsurface.h" #include "surfaces/nnormalsurfacelist.h" #include "triangulation/ntriangulation.h" namespace regina { NNormalSurface* NNormalSurface::findNonTrivialSphere(NTriangulation* tri) { if (! tri->hasBoundaryTriangles()) { // Switch to the optimised (and non-deprecated) verison of this routine. // Here we use the fact that, with no boundary triangles, there // cannot be any normal discs. return tri->hasNonTrivialSphereOrDisc(); } // The older, deprecated code follows. // If the triangulation is already known to be 0-efficient, there // are no non-trivial normal 2-spheres. if (tri->knowsZeroEfficient() && tri->isZeroEfficient()) return 0; // Construct the vertex normal surfaces and look for any spheres // or 1-sided projective planes. NNormalSurfaceList* surfaces = NNormalSurfaceList::enumerate(tri, NS_STANDARD); unsigned long nSurfaces = surfaces->getNumberOfSurfaces(); const NNormalSurface* s; NLargeInteger chi; for (unsigned long i = 0; i < nSurfaces; i++) { s = surfaces->getSurface(i); // No need to test for connectedness since these are vertex surfaces. if (s->isCompact() && (! s->hasRealBoundary()) && (! s->isVertexLinking())) { chi = s->getEulerChar(); if (chi == 2 || (chi == 1 && ! s->isTwoSided())) { // It's a non-trivial 2-sphere! // Clone the surface for our return value. NNormalSurface* ans = (chi == 1 ? s->doubleSurface() : s->clone()); surfaces->makeOrphan(); delete surfaces; return ans; } } } // Nothing was found. // Therefore there cannot be any non-trivial 2-spheres at all. surfaces->makeOrphan(); delete surfaces; return 0; } NNormalSurface* NNormalSurface::findVtxOctAlmostNormalSphere( NTriangulation* tri, bool quadOct) { // This routine is deprecated. // However, stick with this implementation instead of running the // faster NTriangulation::hasOctagonalAlmostNormalSphere(), since // the docs for this routine insist on a vertex surface in a // particular coordinate system. NNormalSurfaceList* surfaces = NNormalSurfaceList::enumerate(tri, quadOct ? NS_AN_QUAD_OCT : NS_AN_STANDARD); unsigned long nSurfaces = surfaces->getNumberOfSurfaces(); unsigned long nTets = tri->getNumberOfTetrahedra(); // Note that our surfaces are guaranteed to be in smallest possible // integer coordinates. // We are also guaranteed at most one non-zero octagonal coordinate. // Note that in this search a 1-sided projective plane is no good, // since when doubled it gives too many octagonal discs. const NNormalSurface* s; unsigned long tet; int oct; NLargeInteger octCoord; for (unsigned long i = 0; i < nSurfaces; i++) { s = surfaces->getSurface(i); // No need to test for connectedness since these are vertex surfaces. // No need to test for vertex links since we're about to test // for octagons. if (s->isCompact() && (! s->hasRealBoundary())) { if (s->getEulerChar() == 2) { // Test for the existence of precisely one octagon. for (tet = 0; tet < nTets; tet++) for (oct = 0; oct < 3; oct++) if ((octCoord = s->getOctCoord(tet, oct)) > 0) { // We found our one and only non-zero // octagonal coordinate. if (octCoord > 1) { // Too many octagons. Move along. // Bail out of all our loops. tet = nTets; // To escape tet loop break; // To escape oct loop } else { // This is our almost normal 2-sphere! // Clone the surface for our return value. NNormalSurface* ans = s->clone(); surfaces->makeOrphan(); delete surfaces; return ans; } } // Either too many octagons or none at all. // On to the next surface. } } } // Nothing was found. // Therefore there cannot be any non-trivial 2-spheres at all. surfaces->makeOrphan(); delete surfaces; return 0; } } // namespace regina regina-4.96/engine/surfaces/stdtoquad.cpp000644 000765 000024 00000015534 12377776743 020443 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "surfaces/normalspec-impl.h" #include "surfaces/nnormalsurface.h" #include "surfaces/nnormalsurfacelist.h" #include "surfaces/nsquad.h" #include "surfaces/nsquadoct.h" #include "triangulation/ntriangulation.h" namespace regina { // Although internalStandardToReduced() is a template routine, we implement // it here in this C++ file to avoid dragging it into the headers. // // The following definitions should ensure that the template is fully // instantiated where it needs to be. NNormalSurfaceList* NNormalSurfaceList::standardToQuad() const { return internalStandardToReduced(); } NNormalSurfaceList* NNormalSurfaceList::standardANToQuadOct() const { return internalStandardToReduced(); } template NNormalSurfaceList* NNormalSurfaceList::internalStandardToReduced() const { // And off we go! NTriangulation* owner = getTriangulation(); // Basic sanity checks: if (coords_ != Variant::standardCoords()) return 0; if (which_ != (NS_EMBEDDED_ONLY | NS_VERTEX)) return 0; if (owner->isIdeal() || ! owner->isValid()) return 0; // Prepare a final surface list. NNormalSurfaceList* ans = new NNormalSurfaceList( Variant::reducedCoords(), NS_EMBEDDED_ONLY | NS_VERTEX, NS_ALG_CUSTOM); // Get the empty triangulation out of the way now. unsigned long n = owner->getNumberOfTetrahedra(); if (n == 0) { owner->insertChildLast(ans); return ans; } // We need to get rid of vertex links entirely before we start. typedef const NNormalSurfaceVector* VectorPtr; VectorPtr* use = new VectorPtr[surfaces.size()]; unsigned long nUse = 0; std::vector::const_iterator it; for (it = surfaces.begin(); it != surfaces.end(); ++it) if (! (*it)->isVertexLinking()) use[nUse++] = (*it)->rawVector(); // We want to take all surfaces with maximal zero sets in quad space. // That is, we want surface S if and only if there is no other surface T // where, for every quadrilateral coordinate where S is zero, T is // zero also. // For almost normal surfaces, simply replace "quadrilateral" with // "quadrilateral or octagonal". bool dominates, strict; unsigned tet, quad, pos; typename Variant::ReducedVector* v; unsigned long i, j; for (i = 0; i < nUse; ++i) { if (use[i] == 0) continue; dominates = strict = false; for (j = 0; j < nUse; ++j) { if (j == i || use[j] == 0) continue; dominates = true; strict = false; for (tet = 0; tet < n && dominates; ++tet) for (quad = 0; quad < Variant::reducedPerTet; ++quad) if ((*use[i])[Variant::stdPos(tet, 4 + quad)] == NLargeInteger::zero && (*use[j])[Variant::stdPos(tet, 4 + quad)] != NLargeInteger::zero) { dominates = false; break; } else if ((*use[i])[Variant::stdPos(tet, 4 + quad)] != NLargeInteger::zero && (*use[j])[Variant::stdPos(tet, 4 + quad)] == NLargeInteger::zero) { // If this *does* turn out to be a domination of // zero sets, we know it's strict. strict = true; } if (dominates) break; } if (! dominates) { // We want this surface. v = new typename Variant::ReducedVector(Variant::redLen(n)); pos = 0; for (tet = 0; tet < n; ++tet) for (quad = 0; quad < Variant::reducedPerTet; ++quad) v->setElement(pos++, (*use[i])[Variant::stdPos(tet, 4 + quad)]); ans->surfaces.push_back(new NNormalSurface(owner, v)); } else if (strict) { // We can drop this surface entirely from our list. // We don't want it for our final solution set, and if // use[i] is going to rule out some *other* surface then // use[j] will rule out that same other surface also. // // The domination need to be strict because otherwise we // might want use[i] to rule out use[j] (i.e., they both // rule out each other). use[i] = 0; } } delete[] use; // All done! owner->insertChildLast(ans); return ans; } } // namespace regina regina-4.96/engine/surfaces/surfacefiltertype.h000644 000765 000024 00000006550 12377775610 021626 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file surfaces/surfacefiltertype.h * \brief Defines constants for normal surface filter types. */ #ifndef __SURFACEFILTERTYPE_H #ifndef __DOXYGEN #define __SURFACEFILTERTYPE_H #endif #include "regina-core.h" namespace regina { /** * \weakgroup surfaces * @{ */ /** * Represents different types of filter classes that can be used to filter * lists of normal surfaces in 3-manifold triangulations. * * IDs 0-9999 are reserved for future use by Regina. If you are extending * Regina to include your own filter class, you should choose an ID >= 10000. */ enum SurfaceFilterType { /** * Represents the NSurfaceFilter class: a do-nothing filter that * accepts any normal surface. */ NS_FILTER_DEFAULT = 0, /** * Represents the NSurfaceFilterProperties subclass: a filter that * examines simple properties of a normal surface. */ NS_FILTER_PROPERTIES = 1, /** * Represents the NSurfaceFilterCombination subclass: a filter that * combines other filters using boolean AND or OR. */ NS_FILTER_COMBINATION = 2 }; /*@}*/ } // namespace regina #endif regina-4.96/engine/triangulation/600cell.py000644 000765 000024 00000034136 12377774107 020502 0ustar00babstaff000000 000000 # Code to generate the 600-cell as a Regina triangulation. # # This code is not built into Regina, and is here for reference only. # It was used to extract the isomorphism signature for the 600-cell, # which is now hard-coded into the implementation of the C++ routine # NExampleTriangulation::sphere600(). # # The simplicial complex described in cell[] was extracted from the # Benedetti-Lutz library of triangulations. See: # # http://page.math.tu-berlin.de/~lutz/stellar/library_of_triangulations.html # http://page.math.tu-berlin.de/~lutz/stellar/library_of_triangulations/600_cell # # Thanks also to Jonathan Spreer, from whose code the routine simpToReg() # was adapted. # # - Ben Burton, 17 June 2014. from regina import * cell=[ [ 1, 2, 3, 4 ], [ 1, 2, 3, 5 ], [ 1, 2, 4, 6 ], [ 1, 2, 5, 7 ], [ 1, 2, 6, 7 ], [ 1, 3, 4, 8 ], [ 1, 3, 5, 9 ], [ 1, 3, 8, 9 ], [ 1, 4, 6, 10 ], [ 1, 4, 8, 10 ], [ 1, 5, 7, 11 ], [ 1, 5, 9, 11 ], [ 1, 6, 7, 12 ], [ 1, 6, 10, 12 ], [ 1, 7, 11, 12 ], [ 1, 8, 9, 13 ], [ 1, 8, 10, 13 ], [ 1, 9, 11, 13 ], [ 1, 10, 12, 13 ], [ 1, 11, 12, 13 ], [ 2, 3, 4, 14 ], [ 2, 3, 5, 15 ], [ 2, 3, 14, 15 ], [ 2, 4, 6, 16 ], [ 2, 4, 14, 16 ], [ 2, 5, 7, 17 ], [ 2, 5, 15, 17 ], [ 2, 6, 7, 18 ], [ 2, 6, 16, 18 ], [ 2, 7, 17, 18 ], [ 2, 14, 15, 19 ], [ 2, 14, 16, 19 ], [ 2, 15, 17, 19 ], [ 2, 16, 18, 19 ], [ 2, 17, 18, 19 ], [ 3, 4, 8, 20 ], [ 3, 4, 14, 20 ], [ 3, 5, 9, 21 ], [ 3, 5, 15, 21 ], [ 3, 8, 9, 22 ], [ 3, 8, 20, 22 ], [ 3, 9, 21, 22 ], [ 3, 14, 15, 23 ], [ 3, 14, 20, 23 ], [ 3, 15, 21, 23 ], [ 3, 20, 22, 23 ], [ 3, 21, 22, 23 ], [ 4, 6, 10, 24 ], [ 4, 6, 16, 24 ], [ 4, 8, 10, 25 ], [ 4, 8, 20, 25 ], [ 4, 10, 24, 25 ], [ 4, 14, 16, 26 ], [ 4, 14, 20, 26 ], [ 4, 16, 24, 26 ], [ 4, 20, 25, 26 ], [ 4, 24, 25, 26 ], [ 5, 7, 11, 27 ], [ 5, 7, 17, 27 ], [ 5, 9, 11, 28 ], [ 5, 9, 21, 28 ], [ 5, 11, 27, 28 ], [ 5, 15, 17, 29 ], [ 5, 15, 21, 29 ], [ 5, 17, 27, 29 ], [ 5, 21, 28, 29 ], [ 5, 27, 28, 29 ], [ 6, 7, 12, 30 ], [ 6, 7, 18, 30 ], [ 6, 10, 12, 31 ], [ 6, 10, 24, 31 ], [ 6, 12, 30, 31 ], [ 6, 16, 18, 32 ], [ 6, 16, 24, 32 ], [ 6, 18, 30, 32 ], [ 6, 24, 31, 32 ], [ 6, 30, 31, 32 ], [ 7, 11, 12, 33 ], [ 7, 11, 27, 33 ], [ 7, 12, 30, 33 ], [ 7, 17, 18, 34 ], [ 7, 17, 27, 34 ], [ 7, 18, 30, 34 ], [ 7, 27, 33, 34 ], [ 7, 30, 33, 34 ], [ 8, 9, 13, 35 ], [ 8, 9, 22, 35 ], [ 8, 10, 13, 36 ], [ 8, 10, 25, 36 ], [ 8, 13, 35, 36 ], [ 8, 20, 22, 37 ], [ 8, 20, 25, 37 ], [ 8, 22, 35, 37 ], [ 8, 25, 36, 37 ], [ 8, 35, 36, 37 ], [ 9, 11, 13, 38 ], [ 9, 11, 28, 38 ], [ 9, 13, 35, 38 ], [ 9, 21, 22, 39 ], [ 9, 21, 28, 39 ], [ 9, 22, 35, 39 ], [ 9, 28, 38, 39 ], [ 9, 35, 38, 39 ], [ 10, 12, 13, 40 ], [ 10, 12, 31, 40 ], [ 10, 13, 36, 40 ], [ 10, 24, 25, 41 ], [ 10, 24, 31, 41 ], [ 10, 25, 36, 41 ], [ 10, 31, 40, 41 ], [ 10, 36, 40, 41 ], [ 11, 12, 13, 42 ], [ 11, 12, 33, 42 ], [ 11, 13, 38, 42 ], [ 11, 27, 28, 43 ], [ 11, 27, 33, 43 ], [ 11, 28, 38, 43 ], [ 11, 33, 42, 43 ], [ 11, 38, 42, 43 ], [ 12, 13, 40, 42 ], [ 12, 30, 31, 44 ], [ 12, 30, 33, 44 ], [ 12, 31, 40, 44 ], [ 12, 33, 42, 44 ], [ 12, 40, 42, 44 ], [ 13, 35, 36, 45 ], [ 13, 35, 38, 45 ], [ 13, 36, 40, 45 ], [ 13, 38, 42, 45 ], [ 13, 40, 42, 45 ], [ 14, 15, 19, 46 ], [ 14, 15, 23, 46 ], [ 14, 16, 19, 47 ], [ 14, 16, 26, 47 ], [ 14, 19, 46, 47 ], [ 14, 20, 23, 48 ], [ 14, 20, 26, 48 ], [ 14, 23, 46, 48 ], [ 14, 26, 47, 48 ], [ 14, 46, 47, 48 ], [ 15, 17, 19, 49 ], [ 15, 17, 29, 49 ], [ 15, 19, 46, 49 ], [ 15, 21, 23, 50 ], [ 15, 21, 29, 50 ], [ 15, 23, 46, 50 ], [ 15, 29, 49, 50 ], [ 15, 46, 49, 50 ], [ 16, 18, 19, 51 ], [ 16, 18, 32, 51 ], [ 16, 19, 47, 51 ], [ 16, 24, 26, 52 ], [ 16, 24, 32, 52 ], [ 16, 26, 47, 52 ], [ 16, 32, 51, 52 ], [ 16, 47, 51, 52 ], [ 17, 18, 19, 53 ], [ 17, 18, 34, 53 ], [ 17, 19, 49, 53 ], [ 17, 27, 29, 54 ], [ 17, 27, 34, 54 ], [ 17, 29, 49, 54 ], [ 17, 34, 53, 54 ], [ 17, 49, 53, 54 ], [ 18, 19, 51, 53 ], [ 18, 30, 32, 55 ], [ 18, 30, 34, 55 ], [ 18, 32, 51, 55 ], [ 18, 34, 53, 55 ], [ 18, 51, 53, 55 ], [ 19, 46, 47, 56 ], [ 19, 46, 49, 56 ], [ 19, 47, 51, 56 ], [ 19, 49, 53, 56 ], [ 19, 51, 53, 56 ], [ 20, 22, 23, 57 ], [ 20, 22, 37, 57 ], [ 20, 23, 48, 57 ], [ 20, 25, 26, 58 ], [ 20, 25, 37, 58 ], [ 20, 26, 48, 58 ], [ 20, 37, 57, 58 ], [ 20, 48, 57, 58 ], [ 21, 22, 23, 59 ], [ 21, 22, 39, 59 ], [ 21, 23, 50, 59 ], [ 21, 28, 29, 60 ], [ 21, 28, 39, 60 ], [ 21, 29, 50, 60 ], [ 21, 39, 59, 60 ], [ 21, 50, 59, 60 ], [ 22, 23, 57, 59 ], [ 22, 35, 37, 61 ], [ 22, 35, 39, 61 ], [ 22, 37, 57, 61 ], [ 22, 39, 59, 61 ], [ 22, 57, 59, 61 ], [ 23, 46, 48, 62 ], [ 23, 46, 50, 62 ], [ 23, 48, 57, 62 ], [ 23, 50, 59, 62 ], [ 23, 57, 59, 62 ], [ 24, 25, 26, 63 ], [ 24, 25, 41, 63 ], [ 24, 26, 52, 63 ], [ 24, 31, 32, 64 ], [ 24, 31, 41, 64 ], [ 24, 32, 52, 64 ], [ 24, 41, 63, 64 ], [ 24, 52, 63, 64 ], [ 25, 26, 58, 63 ], [ 25, 36, 37, 65 ], [ 25, 36, 41, 65 ], [ 25, 37, 58, 65 ], [ 25, 41, 63, 65 ], [ 25, 58, 63, 65 ], [ 26, 47, 48, 66 ], [ 26, 47, 52, 66 ], [ 26, 48, 58, 66 ], [ 26, 52, 63, 66 ], [ 26, 58, 63, 66 ], [ 27, 28, 29, 67 ], [ 27, 28, 43, 67 ], [ 27, 29, 54, 67 ], [ 27, 33, 34, 68 ], [ 27, 33, 43, 68 ], [ 27, 34, 54, 68 ], [ 27, 43, 67, 68 ], [ 27, 54, 67, 68 ], [ 28, 29, 60, 67 ], [ 28, 38, 39, 69 ], [ 28, 38, 43, 69 ], [ 28, 39, 60, 69 ], [ 28, 43, 67, 69 ], [ 28, 60, 67, 69 ], [ 29, 49, 50, 70 ], [ 29, 49, 54, 70 ], [ 29, 50, 60, 70 ], [ 29, 54, 67, 70 ], [ 29, 60, 67, 70 ], [ 30, 31, 32, 71 ], [ 30, 31, 44, 71 ], [ 30, 32, 55, 71 ], [ 30, 33, 34, 72 ], [ 30, 33, 44, 72 ], [ 30, 34, 55, 72 ], [ 30, 44, 71, 72 ], [ 30, 55, 71, 72 ], [ 31, 32, 64, 71 ], [ 31, 40, 41, 73 ], [ 31, 40, 44, 73 ], [ 31, 41, 64, 73 ], [ 31, 44, 71, 73 ], [ 31, 64, 71, 73 ], [ 32, 51, 52, 74 ], [ 32, 51, 55, 74 ], [ 32, 52, 64, 74 ], [ 32, 55, 71, 74 ], [ 32, 64, 71, 74 ], [ 33, 34, 68, 72 ], [ 33, 42, 43, 75 ], [ 33, 42, 44, 75 ], [ 33, 43, 68, 75 ], [ 33, 44, 72, 75 ], [ 33, 68, 72, 75 ], [ 34, 53, 54, 76 ], [ 34, 53, 55, 76 ], [ 34, 54, 68, 76 ], [ 34, 55, 72, 76 ], [ 34, 68, 72, 76 ], [ 35, 36, 37, 77 ], [ 35, 36, 45, 77 ], [ 35, 37, 61, 77 ], [ 35, 38, 39, 78 ], [ 35, 38, 45, 78 ], [ 35, 39, 61, 78 ], [ 35, 45, 77, 78 ], [ 35, 61, 77, 78 ], [ 36, 37, 65, 77 ], [ 36, 40, 41, 79 ], [ 36, 40, 45, 79 ], [ 36, 41, 65, 79 ], [ 36, 45, 77, 79 ], [ 36, 65, 77, 79 ], [ 37, 57, 58, 80 ], [ 37, 57, 61, 80 ], [ 37, 58, 65, 80 ], [ 37, 61, 77, 80 ], [ 37, 65, 77, 80 ], [ 38, 39, 69, 78 ], [ 38, 42, 43, 81 ], [ 38, 42, 45, 81 ], [ 38, 43, 69, 81 ], [ 38, 45, 78, 81 ], [ 38, 69, 78, 81 ], [ 39, 59, 60, 82 ], [ 39, 59, 61, 82 ], [ 39, 60, 69, 82 ], [ 39, 61, 78, 82 ], [ 39, 69, 78, 82 ], [ 40, 41, 73, 79 ], [ 40, 42, 44, 83 ], [ 40, 42, 45, 83 ], [ 40, 44, 73, 83 ], [ 40, 45, 79, 83 ], [ 40, 73, 79, 83 ], [ 41, 63, 64, 84 ], [ 41, 63, 65, 84 ], [ 41, 64, 73, 84 ], [ 41, 65, 79, 84 ], [ 41, 73, 79, 84 ], [ 42, 43, 75, 81 ], [ 42, 44, 75, 83 ], [ 42, 45, 81, 83 ], [ 42, 75, 81, 83 ], [ 43, 67, 68, 85 ], [ 43, 67, 69, 85 ], [ 43, 68, 75, 85 ], [ 43, 69, 81, 85 ], [ 43, 75, 81, 85 ], [ 44, 71, 72, 86 ], [ 44, 71, 73, 86 ], [ 44, 72, 75, 86 ], [ 44, 73, 83, 86 ], [ 44, 75, 83, 86 ], [ 45, 77, 78, 87 ], [ 45, 77, 79, 87 ], [ 45, 78, 81, 87 ], [ 45, 79, 83, 87 ], [ 45, 81, 83, 87 ], [ 46, 47, 48, 88 ], [ 46, 47, 56, 88 ], [ 46, 48, 62, 88 ], [ 46, 49, 50, 89 ], [ 46, 49, 56, 89 ], [ 46, 50, 62, 89 ], [ 46, 56, 88, 89 ], [ 46, 62, 88, 89 ], [ 47, 48, 66, 88 ], [ 47, 51, 52, 90 ], [ 47, 51, 56, 90 ], [ 47, 52, 66, 90 ], [ 47, 56, 88, 90 ], [ 47, 66, 88, 90 ], [ 48, 57, 58, 91 ], [ 48, 57, 62, 91 ], [ 48, 58, 66, 91 ], [ 48, 62, 88, 91 ], [ 48, 66, 88, 91 ], [ 49, 50, 70, 89 ], [ 49, 53, 54, 92 ], [ 49, 53, 56, 92 ], [ 49, 54, 70, 92 ], [ 49, 56, 89, 92 ], [ 49, 70, 89, 92 ], [ 50, 59, 60, 93 ], [ 50, 59, 62, 93 ], [ 50, 60, 70, 93 ], [ 50, 62, 89, 93 ], [ 50, 70, 89, 93 ], [ 51, 52, 74, 90 ], [ 51, 53, 55, 94 ], [ 51, 53, 56, 94 ], [ 51, 55, 74, 94 ], [ 51, 56, 90, 94 ], [ 51, 74, 90, 94 ], [ 52, 63, 64, 95 ], [ 52, 63, 66, 95 ], [ 52, 64, 74, 95 ], [ 52, 66, 90, 95 ], [ 52, 74, 90, 95 ], [ 53, 54, 76, 92 ], [ 53, 55, 76, 94 ], [ 53, 56, 92, 94 ], [ 53, 76, 92, 94 ], [ 54, 67, 68, 96 ], [ 54, 67, 70, 96 ], [ 54, 68, 76, 96 ], [ 54, 70, 92, 96 ], [ 54, 76, 92, 96 ], [ 55, 71, 72, 97 ], [ 55, 71, 74, 97 ], [ 55, 72, 76, 97 ], [ 55, 74, 94, 97 ], [ 55, 76, 94, 97 ], [ 56, 88, 89, 98 ], [ 56, 88, 90, 98 ], [ 56, 89, 92, 98 ], [ 56, 90, 94, 98 ], [ 56, 92, 94, 98 ], [ 57, 58, 80, 91 ], [ 57, 59, 61, 99 ], [ 57, 59, 62, 99 ], [ 57, 61, 80, 99 ], [ 57, 62, 91, 99 ], [ 57, 80, 91, 99 ], [ 58, 63, 65, 100 ], [ 58, 63, 66, 100 ], [ 58, 65, 80, 100 ], [ 58, 66, 91, 100 ], [ 58, 80, 91, 100 ], [ 59, 60, 82, 93 ], [ 59, 61, 82, 99 ], [ 59, 62, 93, 99 ], [ 59, 82, 93, 99 ], [ 60, 67, 69, 101 ], [ 60, 67, 70, 101 ], [ 60, 69, 82, 101 ], [ 60, 70, 93, 101 ], [ 60, 82, 93, 101 ], [ 61, 77, 78, 102 ], [ 61, 77, 80, 102 ], [ 61, 78, 82, 102 ], [ 61, 80, 99, 102 ], [ 61, 82, 99, 102 ], [ 62, 88, 89, 103 ], [ 62, 88, 91, 103 ], [ 62, 89, 93, 103 ], [ 62, 91, 99, 103 ], [ 62, 93, 99, 103 ], [ 63, 64, 84, 95 ], [ 63, 65, 84, 100 ], [ 63, 66, 95, 100 ], [ 63, 84, 95, 100 ], [ 64, 71, 73, 104 ], [ 64, 71, 74, 104 ], [ 64, 73, 84, 104 ], [ 64, 74, 95, 104 ], [ 64, 84, 95, 104 ], [ 65, 77, 79, 105 ], [ 65, 77, 80, 105 ], [ 65, 79, 84, 105 ], [ 65, 80, 100, 105 ], [ 65, 84, 100, 105 ], [ 66, 88, 90, 106 ], [ 66, 88, 91, 106 ], [ 66, 90, 95, 106 ], [ 66, 91, 100, 106 ], [ 66, 95, 100, 106 ], [ 67, 68, 85, 96 ], [ 67, 69, 85, 101 ], [ 67, 70, 96, 101 ], [ 67, 85, 96, 101 ], [ 68, 72, 75, 107 ], [ 68, 72, 76, 107 ], [ 68, 75, 85, 107 ], [ 68, 76, 96, 107 ], [ 68, 85, 96, 107 ], [ 69, 78, 81, 108 ], [ 69, 78, 82, 108 ], [ 69, 81, 85, 108 ], [ 69, 82, 101, 108 ], [ 69, 85, 101, 108 ], [ 70, 89, 92, 109 ], [ 70, 89, 93, 109 ], [ 70, 92, 96, 109 ], [ 70, 93, 101, 109 ], [ 70, 96, 101, 109 ], [ 71, 72, 86, 97 ], [ 71, 73, 86, 104 ], [ 71, 74, 97, 104 ], [ 71, 86, 97, 104 ], [ 72, 75, 86, 107 ], [ 72, 76, 97, 107 ], [ 72, 86, 97, 107 ], [ 73, 79, 83, 110 ], [ 73, 79, 84, 110 ], [ 73, 83, 86, 110 ], [ 73, 84, 104, 110 ], [ 73, 86, 104, 110 ], [ 74, 90, 94, 111 ], [ 74, 90, 95, 111 ], [ 74, 94, 97, 111 ], [ 74, 95, 104, 111 ], [ 74, 97, 104, 111 ], [ 75, 81, 83, 112 ], [ 75, 81, 85, 112 ], [ 75, 83, 86, 112 ], [ 75, 85, 107, 112 ], [ 75, 86, 107, 112 ], [ 76, 92, 94, 113 ], [ 76, 92, 96, 113 ], [ 76, 94, 97, 113 ], [ 76, 96, 107, 113 ], [ 76, 97, 107, 113 ], [ 77, 78, 87, 102 ], [ 77, 79, 87, 105 ], [ 77, 80, 102, 105 ], [ 77, 87, 102, 105 ], [ 78, 81, 87, 108 ], [ 78, 82, 102, 108 ], [ 78, 87, 102, 108 ], [ 79, 83, 87, 110 ], [ 79, 84, 105, 110 ], [ 79, 87, 105, 110 ], [ 80, 91, 99, 114 ], [ 80, 91, 100, 114 ], [ 80, 99, 102, 114 ], [ 80, 100, 105, 114 ], [ 80, 102, 105, 114 ], [ 81, 83, 87, 112 ], [ 81, 85, 108, 112 ], [ 81, 87, 108, 112 ], [ 82, 93, 99, 115 ], [ 82, 93, 101, 115 ], [ 82, 99, 102, 115 ], [ 82, 101, 108, 115 ], [ 82, 102, 108, 115 ], [ 83, 86, 110, 112 ], [ 83, 87, 110, 112 ], [ 84, 95, 100, 116 ], [ 84, 95, 104, 116 ], [ 84, 100, 105, 116 ], [ 84, 104, 110, 116 ], [ 84, 105, 110, 116 ], [ 85, 96, 101, 117 ], [ 85, 96, 107, 117 ], [ 85, 101, 108, 117 ], [ 85, 107, 112, 117 ], [ 85, 108, 112, 117 ], [ 86, 97, 104, 118 ], [ 86, 97, 107, 118 ], [ 86, 104, 110, 118 ], [ 86, 107, 112, 118 ], [ 86, 110, 112, 118 ], [ 87, 102, 105, 119 ], [ 87, 102, 108, 119 ], [ 87, 105, 110, 119 ], [ 87, 108, 112, 119 ], [ 87, 110, 112, 119 ], [ 88, 89, 98, 103 ], [ 88, 90, 98, 106 ], [ 88, 91, 103, 106 ], [ 88, 98, 103, 106 ], [ 89, 92, 98, 109 ], [ 89, 93, 103, 109 ], [ 89, 98, 103, 109 ], [ 90, 94, 98, 111 ], [ 90, 95, 106, 111 ], [ 90, 98, 106, 111 ], [ 91, 99, 103, 114 ], [ 91, 100, 106, 114 ], [ 91, 103, 106, 114 ], [ 92, 94, 98, 113 ], [ 92, 96, 109, 113 ], [ 92, 98, 109, 113 ], [ 93, 99, 103, 115 ], [ 93, 101, 109, 115 ], [ 93, 103, 109, 115 ], [ 94, 97, 111, 113 ], [ 94, 98, 111, 113 ], [ 95, 100, 106, 116 ], [ 95, 104, 111, 116 ], [ 95, 106, 111, 116 ], [ 96, 101, 109, 117 ], [ 96, 107, 113, 117 ], [ 96, 109, 113, 117 ], [ 97, 104, 111, 118 ], [ 97, 107, 113, 118 ], [ 97, 111, 113, 118 ], [ 98, 103, 106, 120 ], [ 98, 103, 109, 120 ], [ 98, 106, 111, 120 ], [ 98, 109, 113, 120 ], [ 98, 111, 113, 120 ], [ 99, 102, 114, 115 ], [ 99, 103, 114, 115 ], [ 100, 105, 114, 116 ], [ 100, 106, 114, 116 ], [ 101, 108, 115, 117 ], [ 101, 109, 115, 117 ], [ 102, 105, 114, 119 ], [ 102, 108, 115, 119 ], [ 102, 114, 115, 119 ], [ 103, 106, 114, 120 ], [ 103, 109, 115, 120 ], [ 103, 114, 115, 120 ], [ 104, 110, 116, 118 ], [ 104, 111, 116, 118 ], [ 105, 110, 116, 119 ], [ 105, 114, 116, 119 ], [ 106, 111, 116, 120 ], [ 106, 114, 116, 120 ], [ 107, 112, 117, 118 ], [ 107, 113, 117, 118 ], [ 108, 112, 117, 119 ], [ 108, 115, 117, 119 ], [ 109, 113, 117, 120 ], [ 109, 115, 117, 120 ], [ 110, 112, 118, 119 ], [ 110, 116, 118, 119 ], [ 111, 113, 118, 120 ], [ 111, 116, 118, 120 ], [ 112, 117, 118, 119 ], [ 113, 117, 118, 120 ], [ 114, 115, 119, 120 ], [ 114, 116, 119, 120 ], [ 115, 117, 119, 120 ], [ 116, 118, 119, 120 ], [ 117, 118, 119, 120 ] ] facets = [[1,2,3], [0,2,3], [0,1,3], [0,1,2]] def simpToReg(simp): n = len(simp) neighbours = [] gluings = [] for j in range(n): neighbours.append([None] * 4) gluings.append([None] * 4) for f in range(4): found = False for k in range(n): if k == j: continue good = True for i in range(3): if simp[j][facets[f][i]] not in simp[k]: good = False break if not good: continue found = True break if not found: return None neighbours[j][f] = k tmp = [None] * 4 unused = 6 for i in range(3): adj = simp[k].index(simp[j][facets[f][i]]) tmp[facets[f][i]] = adj unused = unused - adj tmp[f] = unused gluings[j][f] = regina.NPerm4(tmp[0], tmp[1], tmp[2], tmp[3]) ans = regina.NTriangulation() for j in range(n): ans.newTetrahedron() for j in range(n): for f in range(4): if ans.getTetrahedron(j).adjacentTetrahedron(f) == None: ans.getTetrahedron(j).joinTo(f, ans.getTetrahedron(neighbours[j][f]), gluings[j][f]) return ans print simpToReg(cell).isoSig() regina-4.96/engine/triangulation/angle.cpp000644 000765 000024 00000007552 12377776743 020567 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "angle/nanglestructure.h" #include "enumerate/ntreeconstraint.h" #include "enumerate/ntreelp.h" #include "triangulation/ntriangulation.h" namespace regina { bool NTriangulation::knowsStrictAngleStructure() const { // There are some simple cases for which we can deduce the answer // automatically. if (tetrahedra_.empty()) return (strictAngleStructure_ = 0); if (! hasBoundaryTriangles()) { // It is easy to prove that, if an angle structure exists, // then we must have #edges = #tetrahedra. if (edges_.size() != tetrahedra_.size()) return (strictAngleStructure_ = 0); } return strictAngleStructure_.known(); } const NAngleStructure* NTriangulation::findStrictAngleStructure() const { // The following test also catches any easy cases. if (knowsStrictAngleStructure()) return strictAngleStructure_.value(); LPInitialTableaux eqns(this, NS_ANGLE, false); LPData lp; lp.reserve(&eqns); // Find an initial basis. lp.initStart(); // Set all angles to be strictly positive. unsigned i; for (i = 0; i < eqns.columns(); ++i) lp.constrainPositive(i); // Test for a solution! if (! lp.isFeasible()) return (strictAngleStructure_ = 0); // We have a strict angle structure: reconstruct it. unsigned long len = 3 * tetrahedra_.size() + 1; NAngleStructureVector* v = new NAngleStructureVector(len); lp.extractSolution(*v, 0 /* type vector */); return (strictAngleStructure_ = new NAngleStructure(this, v)); } } // namespace regina regina-4.96/engine/triangulation/CMakeLists.txt000644 000765 000024 00000002176 12377774107 021522 0ustar00babstaff000000 000000 # triangulation # Files to compile SET ( FILES angle cover crushtri decompose homology homotopy hydrate insertlayered isomorphic nboundarycomponent ncomponent nedge nexampletriangulation nfacepair nhomologicaldata nisomorphism ntetrahedron ntriangle ntriangulation nvertex nxmltrireader reorder simplify simplifyglobal skeleton subdivide surfaces turaevviro ) # Prepend folder name FOREACH ( SOURCE_FILE ${FILES} ) SET ( SOURCES ${SOURCES} triangulation/${SOURCE_FILE}) ENDFOREACH(SOURCE_FILE) # Set the variable in the parent directory SET( SOURCES ${SOURCES} PARENT_SCOPE) if (${REGINA_INSTALL_DEV}) INSTALL(FILES dimtraits.h nboundarycomponent.h ncomponent.h nedge.h nexampletriangulation.h nface.h nfacepair.h nfacetspec.h ngenericisomorphism.h ngenericisomorphism.tcc nhomologicaldata.h nisomorphism.h nperm.h npermit.h ntetface.h ntetrahedron.h ntriangle.h ntriangulation.h nvertex.h nxmltrireader.h DESTINATION ${INCLUDEDIR}/triangulation COMPONENT Development) endif (${REGINA_INSTALL_DEV}) regina-4.96/engine/triangulation/cover.cpp000644 000765 000024 00000013642 12377776744 020615 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "triangulation/ntriangulation.h" namespace regina { void NTriangulation::makeDoubleCover() { unsigned long sheetSize = tetrahedra_.size(); if (sheetSize == 0) return; ChangeEventSpan span(this); // Create a second sheet of tetrahedra. NTetrahedron** upper = new NTetrahedron*[sheetSize]; unsigned long i; for (i = 0; i < sheetSize; i++) upper[i] = newTetrahedron(tetrahedra_[i]->getDescription()); // Reset each tetrahedron orientation. TetrahedronIterator tit = tetrahedra_.begin(); for (i = 0; i < sheetSize; i++) { (*tit++)->tetOrientation_ = 0; upper[i]->tetOrientation_ = 0; } // Run through the upper sheet and recreate the gluings as we // propagate tetrahedron orientations through components. std::queue tetQueue; /**< Tetrahedra whose orientation must be propagated. */ int face; unsigned long upperTet; NTetrahedron* lowerTet; unsigned long upperAdj; NTetrahedron* lowerAdj; int lowerAdjOrientation; NPerm4 gluing; for (i = 0; i < sheetSize; i++) if (upper[i]->tetOrientation_ == 0) { // We've found a new component. // Completely recreate the gluings for this component. upper[i]->tetOrientation_ = 1; tetrahedra_[i]->tetOrientation_ = -1; tetQueue.push(i); while (! tetQueue.empty()) { upperTet = tetQueue.front(); tetQueue.pop(); lowerTet = tetrahedra_[upperTet]; for (face = 0; face < 4; face++) { lowerAdj = lowerTet->adjacentTetrahedron(face); // See if this tetrahedron is glued to something in the // lower sheet. if (! lowerAdj) continue; // Make sure we haven't already fixed this gluing in // the upper sheet. if (upper[upperTet]->adjacentTetrahedron(face)) continue; // Determine the expected orientation of the // adjacent tetrahedron in the lower sheet. gluing = lowerTet->adjacentGluing(face); lowerAdjOrientation = (gluing.sign() == 1 ? -lowerTet->tetOrientation_ : lowerTet->tetOrientation_); upperAdj = tetrahedronIndex(lowerAdj); if (lowerAdj->tetOrientation_ == 0) { // We haven't seen the adjacent tetrahedron yet. lowerAdj->tetOrientation_ = lowerAdjOrientation; upper[upperAdj]->tetOrientation_ = -lowerAdjOrientation; upper[upperTet]->joinTo(face, upper[upperAdj], gluing); tetQueue.push(upperAdj); } else if (lowerAdj->tetOrientation_ == lowerAdjOrientation) { // The adjacent tetrahedron already has the // correct orientation. upper[upperTet]->joinTo(face, upper[upperAdj], gluing); } else { // The adjacent tetrahedron already has the // incorrect orientation. Make a cross between // the two sheets. lowerTet->unjoin(face); lowerTet->joinTo(face, upper[upperAdj], gluing); upper[upperTet]->joinTo(face, lowerAdj, gluing); } } } } // Tidy up. delete[] upper; } } // namespace regina regina-4.96/engine/triangulation/crushtri.cpp000644 000765 000024 00000015344 12377776746 021345 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "triangulation/ntriangulation.h" namespace regina { void NTriangulation::maximalForestInBoundary(std::set& edgeSet, std::set& vertexSet) const { if (! calculatedSkeleton_) calculateSkeleton(); vertexSet.clear(); edgeSet.clear(); for (BoundaryComponentIterator bit = boundaryComponents_.begin(); bit != boundaryComponents_.end(); bit++) stretchBoundaryForestFromVertex((*bit)->getVertex(0), edgeSet, vertexSet); } void NTriangulation::stretchBoundaryForestFromVertex(NVertex* from, std::set& edgeSet, std::set& vertexSet) const { vertexSet.insert(from); std::vector::const_iterator it = from->getEmbeddings().begin(); NTetrahedron* tet; NVertex* otherVertex; NEdge* edge; int vertex, yourVertex; while (it != from->getEmbeddings().end()) { const NVertexEmbedding& emb = *it; tet = emb.getTetrahedron(); vertex = emb.getVertex(); for (yourVertex = 0; yourVertex < 4; yourVertex++) { if (vertex == yourVertex) continue; edge = tet->getEdge(NEdge::edgeNumber[vertex][yourVertex]); if (! (edge->isBoundary())) continue; otherVertex = tet->getVertex(yourVertex); if (! vertexSet.count(otherVertex)) { edgeSet.insert(edge); stretchBoundaryForestFromVertex(otherVertex, edgeSet, vertexSet); } } it++; } } void NTriangulation::maximalForestInSkeleton(std::set& edgeSet, bool canJoinBoundaries) const { if (! calculatedSkeleton_) calculateSkeleton(); std::set vertexSet; std::set thisBranch; if (canJoinBoundaries) edgeSet.clear(); else maximalForestInBoundary(edgeSet, vertexSet); for (VertexIterator vit = vertices_.begin(); vit != vertices_.end(); vit++) if (! (vertexSet.count(*vit))) { stretchForestFromVertex(*vit, edgeSet, vertexSet, thisBranch); thisBranch.clear(); } } bool NTriangulation::stretchForestFromVertex(NVertex* from, std::set& edgeSet, std::set& vertexSet, std::set& thisStretch) const { // Moves out from the vertex until we hit a vertex that has already // been visited; then stops. // Returns true if we make such a link. // PRE: Such a link has not already been made. vertexSet.insert(from); thisStretch.insert(from); std::vector::const_iterator it = from->getEmbeddings().begin(); NTetrahedron* tet; NVertex* otherVertex; int vertex, yourVertex; bool madeLink = false; while (it != from->getEmbeddings().end()) { const NVertexEmbedding& emb = *it; tet = emb.getTetrahedron(); vertex = emb.getVertex(); for (yourVertex = 0; yourVertex < 4; yourVertex++) { if (vertex == yourVertex) continue; otherVertex = tet->getVertex(yourVertex); if (thisStretch.count(otherVertex)) continue; madeLink = vertexSet.count(otherVertex); edgeSet.insert(tet->getEdge(NEdge::edgeNumber[vertex][yourVertex])); if (! madeLink) madeLink = stretchForestFromVertex(otherVertex, edgeSet, vertexSet, thisStretch); if (madeLink) return true; } it++; } return false; } void NTriangulation::maximalForestInDualSkeleton(std::set& triSet) const { if (! calculatedSkeleton_) calculateSkeleton(); triSet.clear(); std::set visited; for (TetrahedronIterator it = tetrahedra_.begin(); it != tetrahedra_.end(); it++) if (! (visited.count(*it))) stretchDualForestFromTet(*it, triSet, visited); } void NTriangulation::stretchDualForestFromTet(NTetrahedron* tet, std::set& triSet, std::set& visited) const { visited.insert(tet); NTetrahedron* adjTet; for (int face = 0; face < 4; face++) { adjTet = tet->adjacentTetrahedron(face); if (adjTet) if (! (visited.count(adjTet))) { triSet.insert(tet->getTriangle(face)); stretchDualForestFromTet(adjTet, triSet, visited); } } } } // namespace regina regina-4.96/engine/triangulation/decompose.cpp000644 000765 000024 00000130104 12377776750 021443 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include "enumerate/ntreetraversal.h" #include "packet/ncontainer.h" #include "subcomplex/nsnappedball.h" #include "surfaces/nnormalsurface.h" #include "surfaces/nnormalsurfacelist.h" #include "triangulation/nboundarycomponent.h" #include "triangulation/nisomorphism.h" #include "triangulation/ntriangulation.h" namespace regina { unsigned long NTriangulation::splitIntoComponents(NPacket* componentParent, bool setLabels) { // Knock off the empty triangulation first. if (tetrahedra_.empty()) return 0; if (! componentParent) componentParent = this; // Create the new component triangulations. // Note that the following line forces a skeletal recalculation. unsigned long nComp = getNumberOfComponents(); // Initialise the component triangulations. NTriangulation** newTris = new NTriangulation*[nComp]; unsigned long whichComp; for (whichComp = 0; whichComp < nComp; ++whichComp) newTris[whichComp] = new NTriangulation(); // Clone the tetrahedra, sorting them into the new components. unsigned long nTets = tetrahedra_.size(); NTetrahedron** newTets = new NTetrahedron*[nTets]; NTetrahedron *tet, *adjTet; unsigned long tetPos, adjPos; NPerm4 adjPerm; int face; for (tetPos = 0; tetPos < nTets; tetPos++) newTets[tetPos] = newTris[componentIndex(tetrahedra_[tetPos]->getComponent())]-> newTetrahedron(tetrahedra_[tetPos]->getDescription()); // Clone the tetrahedron gluings also. for (tetPos = 0; tetPos < nTets; tetPos++) { tet = tetrahedra_[tetPos]; for (face = 0; face < 4; face++) { adjTet = tet->adjacentTetrahedron(face); if (adjTet) { adjPos = tetrahedronIndex(adjTet); adjPerm = tet->adjacentGluing(face); if (adjPos > tetPos || (adjPos == tetPos && adjPerm[face] > face)) newTets[tetPos]->joinTo(face, newTets[adjPos], adjPerm); } } } // Insert the component triangulations into the packet tree and clean up. for (whichComp = 0; whichComp < nComp; ++whichComp) { componentParent->insertChildLast(newTris[whichComp]); if (setLabels) { std::ostringstream label; if (getPacketLabel().empty()) label << "Cmpt #" << (whichComp + 1); else label << getPacketLabel() << " - Cmpt #" << (whichComp + 1); newTris[whichComp]->setPacketLabel(label.str()); } } delete[] newTets; delete[] newTris; return whichComp; } long NTriangulation::connectedSumDecomposition(NPacket* primeParent, bool setLabels) { // Precondition checks. if (! (isValid() && isClosed() && isConnected())) return 0; if (! primeParent) primeParent = this; bool initOrientable = isOrientable(); // Make a working copy, simplify and record the initial homology. NTriangulation* working = new NTriangulation(*this); working->intelligentSimplify(); unsigned long initZ, initZ2, initZ3; { const NAbelianGroup& homology = working->getHomologyH1(); initZ = homology.getRank(); initZ2 = homology.getTorsionRank(2); initZ3 = homology.getTorsionRank(3); } // Start crushing normal spheres. NContainer toProcess; toProcess.insertChildLast(working); std::list primeComponents; unsigned long whichComp = 0; NTriangulation* processing; NTriangulation* crushed; NNormalSurface* sphere; while ((processing = static_cast( toProcess.getFirstTreeChild()))) { // INV: Our triangulation is the connected sum of all the // children of toProcess, all the elements of primeComponents // and possibly some copies of S2xS1, S2x~S1, RP3, and/or L(3,1). // Work with the last child. processing->makeOrphan(); // Find a normal 2-sphere to crush. sphere = processing->hasNonTrivialSphereOrDisc(); if (sphere) { crushed = sphere->crush(); delete sphere; delete processing; if (! crushed->isValid()) { // We must have had an embedded two-sided projective plane. // Abort. delete crushed; std::list::iterator it; for (it = primeComponents.begin(); it != primeComponents.end(); ++it) delete *it; // All children of toProcess will be deleted automatically // with toProcess itself (which is on the stack). return -1; } crushed->intelligentSimplify(); // Insert each component of the crushed triangulation back // into the list to process. if (crushed->getNumberOfComponents() == 0) delete crushed; else if (crushed->getNumberOfComponents() == 1) toProcess.insertChildLast(crushed); else { crushed->splitIntoComponents(&toProcess, false); delete crushed; } } else { // We have no non-trivial normal 2-spheres! // The triangulation is 0-efficient (and prime). // Is it a 3-sphere? if (! processing->isOrientable()) { // Definitely not a sphere. primeComponents.push_back(processing); } else { // Orientable, and so possibly a sphere. Test this precisely. if (processing->getNumberOfVertices() > 1) { // Proposition 5.1 of Jaco & Rubinstein's 0-efficiency // paper: If a closed orientable triangulation T is // 0-efficient then either T has one vertex or T is a // 3-sphere with precisely two vertices. // // It follows then that this is a 3-sphere. // Toss it away. delete sphere; delete processing; } else { // Now we have a closed orientable one-vertex 0-efficient // triangulation. // We have to look for an almost normal sphere. // // From the proof of Proposition 5.12 in Jaco & Rubinstein's // 0-efficiency paper, we see that we can restrict our // search to octagonal almost normal surfaces. // Furthermore, from the result in the quadrilateral-octagon // coordinates paper, we can restrict this search further // to vertex octagonal almost normal surfaces in // quadrilateral-octagonal space. sphere = processing->hasOctagonalAlmostNormalSphere(); if (sphere) { // It's a 3-sphere. Toss this component away. delete sphere; delete processing; } else { // It's a non-trivial prime component! primeComponents.push_back(processing); } } } } } // Run a final homology check and put back our missing S2xS1, S2x~S1, // RP3 and L(3,1) terms. unsigned long finalZ = 0, finalZ2 = 0, finalZ3 = 0; for (std::list::iterator it = primeComponents.begin(); it != primeComponents.end(); it++) { const NAbelianGroup& homology = (*it)->getHomologyH1(); finalZ += homology.getRank(); finalZ2 += homology.getTorsionRank(2); finalZ3 += homology.getTorsionRank(3); } while (finalZ++ < initZ) { working = new NTriangulation(); if (initOrientable) { // Build S2 x S1. working->insertLayeredLensSpace(0, 1); } else { // Build S2 x~ S1. NTetrahedron* t0 = working->newTetrahedron(); NTetrahedron* t1 = working->newTetrahedron(); t0->joinTo(0, t1, NPerm4(0, 1, 3, 2)); t0->joinTo(1, t1, NPerm4(0, 1, 3, 2)); t0->joinTo(2, t1, NPerm4(1, 3, 2, 0)); t0->joinTo(3, t1, NPerm4(2, 0, 1, 3)); } primeComponents.push_back(working); irreducible_ = false; // Implied by the S2xS1 or S2x~S1 summand. zeroEfficient_ = false; // Implied by the S2xS1 or S2x~S1 summand. } while (finalZ2++ < initZ2) { working = new NTriangulation(); working->insertLayeredLensSpace(2, 1); primeComponents.push_back(working); } while (finalZ3++ < initZ3) { working = new NTriangulation(); working->insertLayeredLensSpace(3, 1); primeComponents.push_back(working); } // All done! for (std::list::iterator it = primeComponents.begin(); it != primeComponents.end(); it++) { primeParent->insertChildLast(*it); if (setLabels) { std::ostringstream label; if (getPacketLabel().empty()) label << "Summand #" << (whichComp + 1); else label << getPacketLabel() << " - Summand #" << (whichComp + 1); (*it)->setPacketLabel(label.str()); } whichComp++; } // Set irreducibility while we're at it. if (whichComp > 1) { threeSphere_ = false; irreducible_ = false; zeroEfficient_ = false; } else if (whichComp == 1) { threeSphere_ = false; if (! irreducible_.known()) { // If our manifold is S2xS1 or S2x~S1 then it is *not* irreducible; // however, in this case we will have already set irreducible // to false when putting back the S2xS1 or S2x~S1 summands above // (and therefore irreducible.known() will be true). irreducible_ = true; } } else if (whichComp == 0) { threeSphere_ = true; irreducible_ = true; haken_ = false; } return whichComp; } bool NTriangulation::isThreeSphere() const { if (threeSphere_.known()) return threeSphere_.value(); // Basic property checks. if (! (isValid() && isClosed() && isOrientable() && isConnected() && getNumberOfTetrahedra() > 0)) { threeSphere_ = false; return false; } // Check homology and fundamental group. // Better simplify first, which means we need a clone. NTriangulation* working = new NTriangulation(*this); working->intelligentSimplify(); // The Poincare conjecture! if (working->getFundamentalGroup().getNumberOfGenerators() == 0) { threeSphere_ = true; delete working; // Some other things that come for free: irreducible_ = true; haken_ = false; return true; } // We could still have a trivial group but not know it. // At least we can at least check homology precisely. if (! working->getHomologyH1().isTrivial()) { threeSphere_ = false; delete working; return false; } // Time for some more heavy machinery. On to normal surfaces. NContainer toProcess; toProcess.insertChildLast(working); NTriangulation* processing; NTriangulation* crushed; NNormalSurface* sphere; while ((processing = static_cast( toProcess.getLastTreeChild()))) { // INV: Our triangulation is the connected sum of all the // children of toProcess. Each of these children has trivial // homology (and therefore we have no S2xS1 / RP3 / L(3,1) // summands to worry about). // Work with the last child. processing->makeOrphan(); // Find a normal 2-sphere to crush. sphere = processing->hasNonTrivialSphereOrDisc(); if (sphere) { crushed = sphere->crush(); delete sphere; delete processing; crushed->intelligentSimplify(); // Insert each component of the crushed triangulation in the // list to process. if (crushed->getNumberOfComponents() == 0) delete crushed; else if (crushed->getNumberOfComponents() == 1) toProcess.insertChildLast(crushed); else { crushed->splitIntoComponents(&toProcess, false); delete crushed; } } else { // We have no non-trivial normal 2-spheres! // The triangulation is 0-efficient. // We can now test directly whether we have a 3-sphere. if (processing->getNumberOfVertices() > 1) { // Proposition 5.1 of Jaco & Rubinstein's 0-efficiency // paper: If a closed orientable triangulation T is // 0-efficient then either T has one vertex or T is a // 3-sphere with precisely two vertices. // // It follows then that this is a 3-sphere. // Toss it away. delete sphere; delete processing; } else { // Now we have a closed orientable one-vertex 0-efficient // triangulation. // We have to look for an almost normal sphere. // // From the proof of Proposition 5.12 in Jaco & Rubinstein's // 0-efficiency paper, we see that we can restrict our // search to octagonal almost normal surfaces. // Furthermore, from the result in the quadrilateral-octagon // coordinates paper, we can restrict this search further // to vertex octagonal almost normal surfaces in // quadrilateral-octagonal space. sphere = processing->hasOctagonalAlmostNormalSphere(); if (sphere) { // It's a 3-sphere. Toss this component away. delete sphere; delete processing; } else { // It's not a 3-sphere. We're done! threeSphere_ = false; delete processing; return false; } } } } // Our triangulation is the connected sum of 0 components! threeSphere_ = true; // Some other things that we get for free: irreducible_ = true; haken_ = false; return true; } bool NTriangulation::knowsThreeSphere() const { if (threeSphere_.known()) return true; // Run some very fast prelimiary tests before we give up and say no. if (! (isValid() && isClosed() && isOrientable() && isConnected())) { threeSphere_ = false; return true; } // More work is required. return false; } bool NTriangulation::isBall() const { if (threeBall_.known()) return threeBall_.value(); // Basic property checks. if (! (isValid() && hasBoundaryTriangles() && isOrientable() && isConnected() && boundaryComponents_.size() == 1 && boundaryComponents_.front()->getEulerChar() == 2)) { threeBall_ = false; return false; } // Pass straight to isThreeSphere (which in turn will check faster things // like homology before pulling out the big guns). // // Cone the boundary to a point (i.e., fill it with a ball), then // call isThreeSphere() on the resulting closed triangulation. NTriangulation working(*this); working.intelligentSimplify(); working.finiteToIdeal(); // Simplify again in case our coning was inefficient. working.intelligentSimplify(); threeBall_ = working.isThreeSphere(); return threeBall_.value(); } bool NTriangulation::knowsBall() const { if (threeBall_.known()) return true; // Run some very fast prelimiary tests before we give up and say no. if (! (isValid() && hasBoundaryTriangles() && isOrientable() && isConnected() && boundaryComponents_.size() == 1 && boundaryComponents_.front()->getEulerChar() == 2)) { threeBall_ = false; return true; } // More work is required. return false; } bool NTriangulation::isSolidTorus() const { if (solidTorus_.known()) return solidTorus_.value(); // Basic property checks. if (! (isValid() && isOrientable() && isConnected() && boundaryComponents_.size() == 1 && boundaryComponents_.front()->getEulerChar() == 0 && boundaryComponents_.front()->isOrientable())) return (solidTorus_ = false); // If it's ideal, make it a triangulation with real boundary. // If it's not ideal, clone it anyway so we can modify it. NTriangulation* working = new NTriangulation(*this); working->intelligentSimplify(); if (working->isIdeal()) { working->idealToFinite(); working->intelligentSimplify(); } // Check homology. if (! (working->getHomologyH1().isZ())) { delete working; return (solidTorus_ = false); } // So: // We are valid, orientable, compact and connected, with H1 = Z. // There is exactly one boundary component, and this is a torus. // Note that the homology results imply that this is not a connected // sum of something with S2xS1 (otherwise we would have two Z terms // in the homology: one from the torus boundary and one from the S2xS1). // This observation simplifies the crushing cases later on. // Pull out the big guns: normal surface time. NNormalSurface* s; NTriangulation* crushed; NPacket* p; NTriangulation* comp; while (true) { // INVARIANT: working is homeomorphic to our original manifold. if (working->getNumberOfVertices() > 1) { // Try *really* hard to get to a 1-vertex triangulation, // since this will make hasNonTrivialSphereOrDisc() much // faster (it will be able to use linear programming). working->intelligentSimplify(); if (working->getNumberOfVertices() > 1) { working->barycentricSubdivision(); working->intelligentSimplify(); working->intelligentSimplify(); } } // Find a non-trivial normal disc or sphere. s = working->hasNonTrivialSphereOrDisc(); if (! s) { // No non-trivial normal disc. This cannot be a solid torus. delete working; return (solidTorus_ = false); } // Crush it and see what happens. // Given what we know about the manifold so far, the only things // that can happen during crushing are: // - undo connected sum decompositions; // - cut along properly embedded discs; // - gain and/or lose 3-balls and/or 3-spheres. crushed = s->crush(); delete s; delete working; working = 0; crushed->intelligentSimplify(); crushed->splitIntoComponents(0, false); for (p = crushed->getFirstTreeChild(); p; p = p->getNextTreeSibling()) { // Examine each connected component after crushing. comp = static_cast(p); if (comp->isClosed()) { // A closed piece. // Must be a 3-sphere, or else we didn't have a solid torus. if (! comp->isThreeSphere()) { delete crushed; return (solidTorus_ = false); } } else if (comp->getNumberOfBoundaryComponents() > 1) { // Multiple boundaries on the same component. // This should never happen, since it implies there was // an S2xS1 summand. std::cerr << "ERROR: S2xS1 summand detected in " "isSolidTorus() that should not exist." << std::endl; // At any rate, it means we did not have a solid torus. delete crushed; return (solidTorus_ = false); } else if (comp->getBoundaryComponent(0)->getEulerChar() == 2) { // A component with sphere boundary. // Must be a 3-ball, or else we didn't have a solid torus. if (! comp->isBall()) { delete crushed; return (solidTorus_ = false); } } else { // The only other possibility is a component with torus // boundary. We should only see at most one of these. // // Unless some other non-trivial component was split off // (i.e., a non-ball and/or non-sphere that will be // detected separately in the tests above), this // component must be identical to our original manifold. if (working) { std::cerr << "ERROR: Multiple torus boundary " "components detected in isSolidTorus(), which " "should not be possible." << std::endl; } working = comp; } } if (! working) { // We have reduced everything down to balls and spheres. // The only way this can happen is if we had a solid torus // (and we crushed and/or cut along a compressing disc // during the crushing operation). delete crushed; return (solidTorus_ = true); } // We have the original manifold in working, but this time with // fewer tetrahedra. Around we go again. working->makeOrphan(); delete crushed; } } bool NTriangulation::knowsSolidTorus() const { if (solidTorus_.known()) return true; // Run some very fast prelimiary tests before we give up and say no. if (! (isValid() && isOrientable() && isConnected())) { solidTorus_ = false; return true; } if (boundaryComponents_.size() != 1) { solidTorus_ = false; return true; } if (boundaryComponents_.front()->getEulerChar() != 0 || (! boundaryComponents_.front()->isOrientable())) { solidTorus_ = false; return true; } // More work is required. return false; } NPacket* NTriangulation::makeZeroEfficient() { // Extract a connected sum decomposition. NContainer* connSum = new NContainer(); if (getPacketLabel().empty()) connSum->setPacketLabel("Decomposition"); else connSum->setPacketLabel(getPacketLabel() + " - Decomposition"); long ans = connectedSumDecomposition(connSum, true); if (ans > 1) { // Composite! return connSum; } else if (ans == 1) { // Prime. NTriangulation* newTri = dynamic_cast( connSum->getLastTreeChild()); if (! isIsomorphicTo(*newTri).get()) { removeAllTetrahedra(); insertTriangulation(*newTri); } delete connSum; return 0; } else { // 3-sphere. if (getNumberOfTetrahedra() > 1) { removeAllTetrahedra(); insertLayeredLensSpace(1,0); } delete connSum; return 0; } } bool NTriangulation::isIrreducible() const { if (irreducible_.known()) return irreducible_.value(); // Precondition checks. if (! (isValid() && isClosed() && isOrientable() && isConnected())) return 0; // We will essentially carry out a connected sum decomposition, but // instead of keeping prime summands we will just count them and // throw them away. unsigned long summands = 0; // Make a working copy, simplify and record the initial homology. NTriangulation* working = new NTriangulation(*this); working->intelligentSimplify(); unsigned long Z, Z2, Z3; { const NAbelianGroup& homology = working->getHomologyH1(); Z = homology.getRank(); Z2 = homology.getTorsionRank(2); Z3 = homology.getTorsionRank(3); } // Start crushing normal spheres. NContainer toProcess; toProcess.insertChildLast(working); unsigned long whichComp = 0; NTriangulation* processing; NTriangulation* crushed; NNormalSurface* sphere; while ((processing = static_cast( toProcess.getFirstTreeChild()))) { // INV: Our triangulation is the connected sum of all the // children of toProcess, all the prime components that we threw away, // and possibly some copies of S2xS1, RP3 and/or L(3,1). // Work with the last child. processing->makeOrphan(); // Find a normal 2-sphere to crush. sphere = processing->hasNonTrivialSphereOrDisc(); if (sphere) { crushed = sphere->crush(); delete sphere; delete processing; crushed->intelligentSimplify(); // Insert each component of the crushed triangulation back // into the list to process. if (crushed->getNumberOfComponents() == 0) delete crushed; else if (crushed->getNumberOfComponents() == 1) toProcess.insertChildLast(crushed); else { crushed->splitIntoComponents(&toProcess, false); delete crushed; } } else { // We have no non-trivial normal 2-spheres! // The triangulation is 0-efficient (and prime). // Is it a 3-sphere? if (processing->getNumberOfVertices() > 1) { // Proposition 5.1 of Jaco & Rubinstein's 0-efficiency // paper: If a closed orientable triangulation T is // 0-efficient then either T has one vertex or T is a // 3-sphere with precisely two vertices. // // It follows then that this is a 3-sphere. // Toss it away. delete sphere; delete processing; } else { // Now we have a closed orientable one-vertex 0-efficient // triangulation. // We have to look for an almost normal sphere. // // From the proof of Proposition 5.12 in Jaco & Rubinstein's // 0-efficiency paper, we see that we can restrict our // search to octagonal almost normal surfaces. // Furthermore, from the result in the quadrilateral-octagon // coordinates paper, we can restrict this search further // to vertex octagonal almost normal surfaces in // quadrilateral-octagonal space. sphere = processing->hasOctagonalAlmostNormalSphere(); if (sphere) { // It's a 3-sphere. Toss this component away. delete sphere; delete processing; } else { // It's a non-trivial prime component! // Note that this will never be an S2xS1 summand; // those get crushed away entirely (we account for // them later). if (summands > 0) { // We have found more than one prime component. threeSphere_ = false; // Implied by reducibility. zeroEfficient_ = false; // Implied by reducibility. delete processing; return (irreducible_ = false); } ++summands; // Note which parts of our initial homology we have // now accounted for. const NAbelianGroup& h1 = processing->getHomologyH1(); Z -= h1.getRank(); Z2 -= h1.getTorsionRank(2); Z3 -= h1.getTorsionRank(3); // Toss away our prime summand and keep going. delete processing; } } } } // Run a final homology check: were there any additional S2xS1, RP3 // or L(3,1) terms? if (Z > 0) { // There were S2xS1 summands that were crushed away. // The manifold must be reducible. threeSphere_ = false; // Implied by reducibility. zeroEfficient_ = false; // Implied by reducibility. return (irreducible_ = false); } if (summands + Z2 + Z3 > 1) { // At least two summands were found and/or crushed away: the // manifold must be composite. threeSphere_ = false; // Implied by reducibility. zeroEfficient_ = false; // Implied by reducibility. return (irreducible_ = false); } // There are no S2xS1 summands, and the manifold is prime. return (irreducible_ = true); } bool NTriangulation::knowsIrreducible() const { return irreducible_.known(); } bool NTriangulation::hasCompressingDisc() const { if (compressingDisc_.known()) return compressingDisc_.value(); // Some sanity checks; also enforce preconditions. if (! hasBoundaryTriangles()) return (compressingDisc_ = false); if ((! isValid()) || isIdeal()) return (compressingDisc_ = false); long minBdryEuler = 2; for (BoundaryComponentIterator it = boundaryComponents_.begin(); it != boundaryComponents_.end(); ++it) { if ((*it)->getEulerChar() < minBdryEuler) minBdryEuler = (*it)->getEulerChar(); } if (minBdryEuler == 2) return (compressingDisc_ = false); // Off we go. // Work with a simplified triangulation. NTriangulation* use = new NTriangulation(*this); use->intelligentSimplify(); // Try for a fast answer first. if (use->hasSimpleCompressingDisc()) { delete use; return (compressingDisc_ = true); } // Nope. Decide whether we can use the fast linear programming // machinery or whether we need to do a full vertex surface enumeration. if (use->isOrientable() && use->getNumberOfBoundaryComponents() == 1) { NNormalSurface* ans; NTriangulation* crush; NTriangulation* comp; unsigned nComp; while (true) { use->intelligentSimplify(); if (use->getNumberOfVertices() > 1) { // Try harder. use->barycentricSubdivision(); use->intelligentSimplify(); if (use->getNumberOfVertices() > 1) { // Fall back to a full vertex enumeration. // This mirrors the code for non-orientable // triangulations; see that later block for details. NNormalSurfaceList* q = NNormalSurfaceList::enumerate( use, NS_STANDARD); unsigned long nSurfaces = q->getNumberOfSurfaces(); for (unsigned long i = 0; i < nSurfaces; ++i) { if (q->getSurface(i)->isCompressingDisc(true)) { delete use; return (compressingDisc_ = true); } } // No compressing discs! delete use; return (compressingDisc_ = false); } } NTreeSingleSoln search(use, NS_STANDARD); if (! search.find()) { // No compressing discs! delete use; return (compressingDisc_ = false); } ans = search.buildSurface(); crush = ans->crush(); delete ans; delete use; nComp = crush->splitIntoComponents(); comp = static_cast(crush->getFirstTreeChild()); while (comp) { if (comp->getNumberOfBoundaryComponents() == 1 && comp->getBoundaryComponent(0)->getEulerChar() == minBdryEuler) { // This must be our original manifold. comp->makeOrphan(); break; } comp = static_cast(comp->getNextTreeSibling()); } delete crush; if (! comp) { // We must have compressed. return (compressingDisc_ = true); } // Around we go again, but this time with a smaller triangulation. use = comp; } } else { // Sigh. Enumerate all vertex normal surfaces. // // Hum, are we allowed to do this in quad space? Jaco and Tollefson // use standard coordinates. Jaco, Letscher and Rubinstein mention // quad space, but don't give details (which I'd prefer to see). // Leave it in standard coordinates for now. NNormalSurfaceList* q = NNormalSurfaceList::enumerate(use, NS_STANDARD); // Run through all vertex surfaces looking for a compressing disc. unsigned long nSurfaces = q->getNumberOfSurfaces(); for (unsigned long i = 0; i < nSurfaces; ++i) { // Use the fact that all vertex normal surfaces are connected. if (q->getSurface(i)->isCompressingDisc(true)) { delete use; return (compressingDisc_ = true); } } // No compressing discs! delete use; return (compressingDisc_ = false); } } bool NTriangulation::knowsCompressingDisc() const { if (compressingDisc_.known()) return true; // Quickly check for non-spherical boundary components before we give up. for (BoundaryComponentIterator it = boundaryComponents_.begin(); it != boundaryComponents_.end(); ++it) { if ((*it)->getEulerChar() < 2) return false; } // All boundary components are 2-spheres. compressingDisc_ = false; return true; } bool NTriangulation::hasSimpleCompressingDisc() const { // Some sanity checks; also enforce preconditions. if (! hasBoundaryTriangles()) return false; if ((! isValid()) || isIdeal()) return false; // Off we go. // Work with a simplified triangulation. NTriangulation use(*this); use.intelligentSimplify(); // Check to see whether any component is a one-tetrahedron solid torus. for (ComponentIterator cit = use.getComponents().begin(); cit != use.getComponents().end(); ++cit) if ((*cit)->getNumberOfTetrahedra() == 1 && (*cit)->getNumberOfTriangles() == 3 && (*cit)->getNumberOfVertices() == 1) { // Because we know the triangulation is valid, this rules out // all one-tetrahedron triangulations except for LST(1,2,3). return (compressingDisc_ = true); } // Open up as many boundary triangles as possible (to make it easier to // find simple compressing discs). TriangleIterator fit; bool opened = true; while (opened) { opened = false; for (fit = use.getTriangles().begin(); fit != use.getTriangles().end(); ++fit) if (use.openBook(*fit, true, true)) { opened = true; break; } } // How many boundary spheres do we currently have? // This is important because we test whether a disc is a compressing // disc by cutting along it and looking for any *new* boundary // spheres that might result. unsigned long origSphereCount = 0; BoundaryComponentIterator bit; for (bit = use.getBoundaryComponents().begin(); bit != use.getBoundaryComponents().end(); ++bit) if ((*bit)->getEulerChar() == 2) ++origSphereCount; // Look for a single internal triangle surrounded by three boundary edges. // It doesn't matter whether the edges and/or vertices are distinct. NEdge *e0, *e1, *e2; unsigned long newSphereCount; for (fit = use.getTriangles().begin(); fit != use.getTriangles().end(); ++fit) { if ((*fit)->isBoundary()) continue; e0 = (*fit)->getEdge(0); e1 = (*fit)->getEdge(1); e2 = (*fit)->getEdge(2); if (! (e0->isBoundary() && e1->isBoundary() && e2->isBoundary())) continue; // This could be a compressing disc. // Cut along the triangle to be sure. const NTriangleEmbedding& emb = (*fit)->getEmbedding(0); NTriangulation cut(use); cut.getTetrahedron(emb.getTetrahedron()->markedIndex())->unjoin( emb.getTriangle()); // If we don't see a new boundary component, the disc boundary is // non-separating in the manifold boundary and is therefore a // non-trivial curve. if (cut.getNumberOfBoundaryComponents() == use.getNumberOfBoundaryComponents()) return (compressingDisc_ = true); newSphereCount = 0; for (bit = cut.getBoundaryComponents().begin(); bit != cut.getBoundaryComponents().end(); ++bit) if ((*bit)->getEulerChar() == 2) ++newSphereCount; // Was the boundary of the disc non-trivial? if (newSphereCount == origSphereCount) return (compressingDisc_ = true); } // Look for a tetrahedron with two faces folded together, giving a // degree-one edge on the inside and a boundary edge on the outside. // The boundary edge on the outside will surround a disc that cuts // right through the tetrahedron. TetrahedronIterator tit; NSnappedBall* ball; for (tit = use.tetrahedra_.begin(); tit != use.tetrahedra_.end(); ++tit) { ball = NSnappedBall::formsSnappedBall(*tit); if (! ball) continue; int equator = ball->getEquatorEdge(); if (! (*tit)->getEdge(equator)->isBoundary()) { delete ball; continue; } // This could be a compressing disc. // Cut through the tetrahedron to be sure. // We do this by removing the tetrahedron, and then plugging // both holes on either side of the disc with new copies of the // tetrahedron. int upper = ball->getBoundaryFace(0); delete ball; NTetrahedron* adj = (*tit)->adjacentTetrahedron(upper); if (! adj) { // The disc is trivial. continue; } NTriangulation cut(use); cut.getTetrahedron((*tit)->markedIndex())->unjoin(upper); NTetrahedron* tet = cut.newTetrahedron(); tet->joinTo(NEdge::edgeVertex[equator][0], tet, NPerm4( NEdge::edgeVertex[equator][0], NEdge::edgeVertex[equator][1])); tet->joinTo(upper, cut.getTetrahedron(adj->markedIndex()), (*tit)->adjacentGluing(upper)); // If we don't see a new boundary component, the disc boundary is // non-separating in the manifold boundary and is therefore a // non-trivial curve. if (cut.getNumberOfBoundaryComponents() == use.getNumberOfBoundaryComponents()) return (compressingDisc_ = true); newSphereCount = 0; for (bit = cut.getBoundaryComponents().begin(); bit != cut.getBoundaryComponents().end(); ++bit) if ((*bit)->getEulerChar() == 2) ++newSphereCount; // Was the boundary of the disc non-trivial? if (newSphereCount == origSphereCount) return (compressingDisc_ = true); } // Nothing found. return false; } namespace { /** * Used to sort candidate incompressible surfaces by Euler characteristic. * Surfaces with smaller genus (i.e., larger Euler characteristic) * are to be processed first. */ struct SurfaceID { long index; /**< Which surface in the list are we referring to? */ long euler; /**< What is its Euler characteristic? */ inline bool operator < (const SurfaceID& rhs) const { return (euler > rhs.euler || (euler == rhs.euler && index < rhs.index)); } }; } bool NTriangulation::isHaken() const { if (haken_.known()) return haken_.value(); // Check basic preconditions. if (! (isValid() && isOrientable() && isClosed() && isConnected())) return false; // Irreducibility is not a precondition, but we promise to return // false immediately if the triangulation is not irreducible. // Do not set the property in this situation. if (! isIrreducible()) return false; // Okay: we are closed, connected, orientable and irreducible. // Move to a copy of this triangulation, which we can mess with. NTriangulation t(*this); t.intelligentSimplify(); // First check for an easy answer via homology: if (t.getHomologyH1().getRank() > 0) { threeSphere_ = false; // Implied by Hakenness. return (haken_ = true); } // Enumerate vertex normal surfaces in quad coordinates. // std::cout << "Enumerating surfaces..." << std::endl; NNormalSurfaceList* list = NNormalSurfaceList::enumerate(&t, NS_QUAD); // Run through each surface, one at a time. // Sort them first however, so we process the (easier) smaller genus // surfaces first. SurfaceID* id = new SurfaceID[list->getNumberOfSurfaces()]; unsigned i; for (i = 0; i < list->getNumberOfSurfaces(); ++i) { id[i].index = i; id[i].euler = list->getSurface(i)->getEulerChar().longValue(); } std::sort(id, id + list->getNumberOfSurfaces()); const NNormalSurface* f; unsigned long discs; for (unsigned i = 0; i < list->getNumberOfSurfaces(); ++i) { // std::cout << "Testing surface " << i << "..." << std::endl; if (list->getSurface(id[i].index)->isIncompressible()) { delete[] id; threeSphere_ = false; // Implied by Hakenness. return (haken_ = true); } } delete[] id; return (haken_ = false); } bool NTriangulation::knowsHaken() const { return haken_.known(); } } // namespace regina regina-4.96/engine/triangulation/dimtraits.h000644 000765 000024 00000004657 12377775612 021143 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file triangulation/dimtraits.h * \brief Deprecated header. */ #warning This header is deprecated; please use generic/dimtraits.h instead. #include "generic/dimtraits.h" regina-4.96/engine/triangulation/homology.cpp000644 000765 000024 00000025303 12377776753 021331 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "triangulation/ntriangulation.h" #include "maths/nmatrixint.h" namespace regina { const NAbelianGroup& NTriangulation::getHomologyH1() const { if (H1_.known()) return *H1_.value(); if (getNumberOfTetrahedra() == 0) return *(H1_ = new NAbelianGroup()); // Calculate the first homology. // Find a maximal forest in the dual 1-skeleton. // Note that this will ensure the skeleton has been calculated. std::set forest; maximalForestInDualSkeleton(forest); // Build a presentation matrix. // Each non-boundary not-in-forest triangle is a generator. // Each non-boundary edge is a relation. unsigned long nBdryEdges = 0; unsigned long nBdryTri = 0; for (BoundaryComponentIterator bit = boundaryComponents_.begin(); bit != boundaryComponents_.end(); bit++) { nBdryEdges += (*bit)->getNumberOfEdges(); nBdryTri += (*bit)->getNumberOfTriangles(); } long nGens = getNumberOfTriangles() - nBdryTri - forest.size(); long nRels = getNumberOfEdges() - nBdryEdges; NMatrixInt pres(nRels, nGens); // Find out which triangle corresponds to which generator. long* genIndex = new long[getNumberOfTriangles()]; long i = 0; for (TriangleIterator fit = triangles_.begin(); fit != triangles_.end(); fit++) { if ((*fit)->isBoundary()) genIndex[fit - triangles_.begin()] = -1; else if (forest.count(*fit)) genIndex[fit - triangles_.begin()] = -1; else { genIndex[fit - triangles_.begin()] = i; i++; } } // Run through each edge and put the relations in the matrix. std::deque::const_iterator embit; NTetrahedron* currTet; NTriangle* triangle; int currTetFace; long triGenIndex; i = 0; for (EdgeIterator eit = edges_.begin(); eit != edges_.end(); eit++) { if (! (*eit)->isBoundary()) { // Put in the relation corresponding to this edge. for (embit = (*eit)->getEmbeddings().begin(); embit != (*eit)->getEmbeddings().end(); embit++) { currTet = (*embit).getTetrahedron(); currTetFace = (*embit).getVertices()[2]; triangle = currTet->getTriangle(currTetFace); triGenIndex = genIndex[triangleIndex(triangle)]; if (triGenIndex >= 0) { if ((triangle->getEmbedding(0).getTetrahedron() == currTet) && (triangle->getEmbedding(0).getTriangle() == currTetFace)) pres.entry(i, triGenIndex) += 1; else pres.entry(i, triGenIndex) -= 1; } } i++; } } delete[] genIndex; // Build the group from the presentation matrix and tidy up. NAbelianGroup* ans = new NAbelianGroup(); ans->addGroup(pres); return *(H1_ = ans); } const NAbelianGroup& NTriangulation::getHomologyH1Rel() const { if (H1Rel_.known()) return *H1Rel_.value(); if (getNumberOfBoundaryComponents() == 0) return *(H1Rel_ = new NAbelianGroup(getHomologyH1())); // Calculate the relative first homology wrt the boundary. // Find a maximal forest in the 1-skeleton. // Note that this will ensure the skeleton has been calculated. std::set forest; maximalForestInSkeleton(forest, false); // Build a presentation matrix. // Each non-boundary not-in-forest edge is a generator. // Each non-boundary triangle is a relation. unsigned long nBdryVertices = 0; unsigned long nBdryEdges = 0; unsigned long nBdryTri = 0; unsigned long nClosedComponents = 0; for (BoundaryComponentIterator bit = boundaryComponents_.begin(); bit != boundaryComponents_.end(); bit++) { nBdryVertices += (*bit)->getNumberOfVertices(); nBdryEdges += (*bit)->getNumberOfEdges(); nBdryTri += (*bit)->getNumberOfTriangles(); } for (ComponentIterator cit = components_.begin(); cit != components_.end(); cit++) if ((*cit)->isClosed()) nClosedComponents++; long nGens = getNumberOfEdges() - nBdryEdges - getNumberOfVertices() + nBdryVertices + nClosedComponents; long nRels = getNumberOfTriangles() - nBdryTri; NMatrixInt pres(nRels, nGens); // Find out which edge corresponds to which generator. long* genIndex = new long[getNumberOfEdges()]; long i = 0; for (EdgeIterator eit = edges_.begin(); eit != edges_.end(); eit++) { if ((*eit)->isBoundary()) genIndex[eit - edges_.begin()] = -1; else if (forest.count(*eit)) genIndex[eit - edges_.begin()] = -1; else { genIndex[eit - edges_.begin()] = i; i++; } } // Run through each triangle and put the relations in the matrix. NTetrahedron* currTet; NPerm4 currTetVertices; long edgeGenIndex; i = 0; int triEdge, currEdgeStart, currEdgeEnd, currEdge; for (TriangleIterator fit = triangles_.begin(); fit != triangles_.end(); fit++) { if (! (*fit)->isBoundary()) { // Put in the relation corresponding to this triangle. currTet = (*fit)->getEmbedding(0).getTetrahedron(); currTetVertices = (*fit)->getEmbedding(0).getVertices(); for (triEdge = 0; triEdge < 3; triEdge++) { currEdgeStart = currTetVertices[triEdge]; currEdgeEnd = currTetVertices[(triEdge + 1) % 3]; // Examine the edge from vertex edgeStart to edgeEnd // in tetrahedron currTet. currEdge = NEdge::edgeNumber[currEdgeStart][currEdgeEnd]; edgeGenIndex = genIndex[edgeIndex( currTet->getEdge(currEdge))]; if (edgeGenIndex >= 0) { if (currTet->getEdgeMapping(currEdge)[0] == currEdgeStart) pres.entry(i, edgeGenIndex) += 1; else pres.entry(i, edgeGenIndex) -= 1; } } i++; } } delete[] genIndex; // Build the group from the presentation matrix and tidy up. NAbelianGroup* ans = new NAbelianGroup(); ans->addGroup(pres); return *(H1Rel_ = ans); } const NAbelianGroup& NTriangulation::getHomologyH1Bdry() const { if (H1Bdry_.known()) return *H1Bdry_.value(); // Run through the individual boundary components and add the // appropriate pieces to the homology group. unsigned long rank = 0; unsigned long z2rank = 0; // Ensure that the skeleton has been calculated. if (! calculatedSkeleton_) calculateSkeleton(); for (BoundaryComponentIterator bit = boundaryComponents_.begin(); bit != boundaryComponents_.end(); bit++) { if ((*bit)->isOrientable()) { rank += (2 - (*bit)->getEulerChar()); } else { rank += (1 - (*bit)->getEulerChar()); z2rank++; } } // Build the group and tidy up. NAbelianGroup* ans = new NAbelianGroup(); ans->addRank(rank); ans->addTorsionElement(2, z2rank); return *(H1Bdry_ = ans); } const NAbelianGroup& NTriangulation::getHomologyH2() const { if (H2_.known()) return *H2_.value(); if (getNumberOfTetrahedra() == 0) return *(H2_ = new NAbelianGroup()); // Calculations are different for orientable vs non-orientable // components. // We know the only components will be Z and Z_2. long rank, z2rank; if (isOrientable()) { // Same as H1Rel without the torsion elements. rank = getHomologyH1Rel().getRank(); z2rank = 0; } else { // Non-orientable! // z2rank = # closed cmpts - # closed orientable cmpts z2rank = 0; for (ComponentIterator cit = components_.begin(); cit != components_.end(); cit++) if ((*cit)->isClosed()) if (! ((*cit)->isOrientable())) z2rank++; // Find rank(Z_2) + rank(Z) and take off z2rank. rank = getHomologyH1Rel().getRank() + getHomologyH1Rel().getTorsionRank(2) - getHomologyH1().getTorsionRank(2) - z2rank; } // Build the new group and tidy up. NAbelianGroup* ans = new NAbelianGroup(); ans->addRank(rank); if (z2rank) ans->addTorsionElement(2, z2rank); return *(H2_ = ans); } } // namespace regina regina-4.96/engine/triangulation/homotopy.cpp000644 000765 000024 00000011726 12377776753 021356 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "triangulation/ntriangulation.h" namespace regina { const NGroupPresentation& NTriangulation::getFundamentalGroup() const { if (fundamentalGroup_.known()) return *fundamentalGroup_.value(); NGroupPresentation* ans = new NGroupPresentation(); if (getNumberOfTetrahedra() == 0) return *(fundamentalGroup_ = ans); // Find a maximal forest in the dual 1-skeleton. // Note that this will ensure the skeleton has been calculated. std::set forest; maximalForestInDualSkeleton(forest); // Each non-boundary not-in-forest triangle is a generator. // Each non-boundary edge is a relation. unsigned long nBdryTri = 0; for (BoundaryComponentIterator bit = boundaryComponents_.begin(); bit != boundaryComponents_.end(); bit++) nBdryTri += (*bit)->getNumberOfTriangles(); long nGens = getNumberOfTriangles() - nBdryTri - forest.size(); // Insert the generators. ans->addGenerator(nGens); // Find out which triangle corresponds to which generator. long *genIndex = new long[getNumberOfTriangles()]; long i = 0; for (TriangleIterator fit = triangles_.begin(); fit != triangles_.end(); fit++) if ((*fit)->isBoundary() || forest.count(*fit)) genIndex[fit - triangles_.begin()] = -1; else genIndex[fit - triangles_.begin()] = i++; // Run through each edge and put the relations in the matrix. std::deque::const_iterator embit; NTetrahedron* currTet; NTriangle* triangle; int currTetFace; long triGenIndex; NGroupExpression* rel; for (EdgeIterator eit = edges_.begin(); eit != edges_.end(); eit++) if (! (*eit)->isBoundary()) { // Put in the relation corresponding to this edge. rel = new NGroupExpression(); for (embit = (*eit)->getEmbeddings().begin(); embit != (*eit)->getEmbeddings().end(); embit++) { currTet = (*embit).getTetrahedron(); currTetFace = (*embit).getVertices()[2]; triangle = currTet->getTriangle(currTetFace); triGenIndex = genIndex[triangleIndex(triangle)]; if (triGenIndex >= 0) { if ((triangle->getEmbedding(0).getTetrahedron() == currTet) && (triangle->getEmbedding(0).getTriangle() == currTetFace)) rel->addTermLast(triGenIndex, 1); else rel->addTermLast(triGenIndex, -1); } } ans->addRelation(rel); } // Tidy up. delete[] genIndex; ans->intelligentSimplify(); return *(fundamentalGroup_ = ans); } } // namespace regina regina-4.96/engine/triangulation/hydrate.cpp000644 000765 000024 00000032116 12377776754 021135 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "triangulation/ntriangulation.h" /** * Determine the integer value represented by the given letter * in a dehydration string. */ #define VAL(x) ((x) - 'a') /** * Determine the letter that represents the given integer value * in a dehydration string. */ #define LETTER(x) (char((x) + 'a')) namespace regina { NTriangulation* NTriangulation::rehydrate(const std::string& dehydration) { NTriangulation* ans = new NTriangulation; if (ans->insertRehydration(dehydration)) return ans; delete ans; return 0; } bool NTriangulation::insertRehydration(const std::string& dehydration) { // Ensure the string is non-empty. if (dehydration.empty()) return false; // Rewrite the string in lower case and verify that it contains only // letters. std::string proper(dehydration); for (std::string::iterator it = proper.begin(); it != proper.end(); it++) { if (*it >= 'A' && *it <= 'Z') *it = *it + ('a' - 'A'); else if (*it < 'a' || *it > 'z') return false; } // Determine the number of tetrahedra. unsigned nTet = VAL(proper[0]); // Determine the expected length of each piece of the dehydrated string. unsigned lenNewTet = 2 * ((nTet + 3) / 4); unsigned lenGluings = nTet + 1; // Ensure the string has the expected length. if (dehydration.length() != 1 + lenNewTet + lenGluings + lenGluings) return false; // Determine which face gluings should involve new tetrahedra. bool* newTetGluings = new bool[2 * nTet]; unsigned val; int i, j; for (i = 0; i < lenNewTet; i++) { val = VAL(proper[i + 1]); if (val > 15) { delete[] newTetGluings; return false; } if (i % 2 == 0) { // This letter stores values 4i+4 -> 4i+7. for (j = 0; (j < 4) && (4*i + 4 + j < 2 * nTet); j++) newTetGluings[4*i + 4 + j] = ((val & (1 << j)) != 0); } else { // This letter stores values 4i-4 -> 4i-1. for (j = 0; (j < 4) && (4*i - 4 + j < 2 * nTet); j++) newTetGluings[4*i - 4 + j] = ((val & (1 << j)) != 0); } } // Create the tetrahedra and start gluing. ChangeEventSpan span(this); NTetrahedron** tet = new NTetrahedron*[nTet]; for (i = 0; i < nTet; i++) tet[i] = newTetrahedron(); unsigned currTet = 0; // Tetrahedron of the next face to glue. int currFace = 0; // Face number of the next face to glue. unsigned gluingsMade = 0; // How many face pairs have we already glued? unsigned specsUsed = 0; // How many gluing specs have we already used? unsigned tetsUsed = 0; // How many tetrahedra have we already used? bool broken = false; // Have we come across an inconsistency? unsigned adjTet; // The tetrahedron to glue this to. unsigned permIndex; // The index of the gluing permutation to use. NPerm4 adjPerm; // The gluing permutation to use. NPerm4 identity; // The identity permutation. NPerm4 reverse(3,2,1,0); // The reverse permutation. while (currTet < nTet) { // Is this face already glued? if (tet[currTet]->adjacentTetrahedron(currFace)) { if (currFace < 3) currFace++; else { currFace = 0; currTet++; } continue; } // If this is a new tetrahedron, be aware of this fact. if (tetsUsed <= currTet) tetsUsed = currTet + 1; // Do we simply glue to a new tetrahedron? if (newTetGluings[gluingsMade]) { // Glue to tetrahedron tetsUsed. if (tetsUsed < nTet) { tet[currTet]->joinTo(currFace, tet[tetsUsed], identity); tetsUsed++; } else { broken = true; break; } } else { // Glue according to the next gluing spec. if (specsUsed >= lenGluings) { broken = true; break; } adjTet = VAL(proper[1 + lenNewTet + specsUsed]); permIndex = VAL(proper[1 + lenNewTet + lenGluings + specsUsed]); if (adjTet >= nTet || permIndex >= 24) { broken = true; break; } adjPerm = NPerm4::orderedS4[permIndex] * reverse; if (tet[adjTet]->adjacentTetrahedron(adjPerm[currFace]) || (adjTet == currTet && adjPerm[currFace] == currFace)) { broken = true; break; } tet[currTet]->joinTo(currFace, tet[adjTet], adjPerm); specsUsed++; } // Increment everything for the next gluing. gluingsMade++; if (currFace < 3) currFace++; else { currFace = 0; currTet++; } } // And we're done! if (broken) { // Delete tetrahedra in the reverse order so tetrahedra are // always removed from the end of the internal array, and the // combined operation is therefore O(nTet) not O(nTet^2). for (i = nTet - 1; i >= 0; --i) removeTetrahedron(tet[i]); } delete[] newTetGluings; delete[] tet; return (! broken); } std::string NTriangulation::dehydrate() const { // Can we even dehydrate at all? if (tetrahedra_.size() > 25 || hasBoundaryTriangles() || ! isConnected()) return ""; // Get the empty case out of the way, since it requires an // additional two redundant letters (two blocks of N+1 letters to // specify "non-obvious gluings"). if (tetrahedra_.empty()) return "aaa"; // Find an isomorphism that will put the triangulation in a form // sufficiently "canonical" to be described by a dehydration string. // When walking through tetrahedron faces from start to finish, this affects // only gluings to previously unseen tetrahedra: // (i) such gluings must be to the smallest numbered unused tetrahedron; // (ii) the gluing permutation must be the identity permutation. // // The array image[] maps tetrahedron numbers from this // triangulation to the canonical triangulation; preImage[] is the // inverse map. The array vertexMap[] describes the corresponding // rearrangement of tetrahedron vertices and faces; specifically, // vertex i of tetrahedron t of this triangulation maps to vertex // vertexMap[t][i] of tetrahedron image[t]. // // Each element of newTet[] is an 8-bit integer. These bits // describe whether the gluings for some corresponding 8 tetrahedron faces // point to previously-seen or previously-unseen tetrahedra. // See the Callahan, Hildebrand and Weeks paper for details. unsigned nTets = tetrahedra_.size(); int* image = new int[nTets]; int* preImage = new int[nTets]; NPerm4* vertexMap = new NPerm4[nTets]; unsigned char* newTet = new unsigned char[(nTets / 4) + 2]; unsigned newTetPos = 0; unsigned newTetBit = 0; char* destChars = new char[nTets + 2]; char* permChars = new char[nTets + 2]; unsigned currGluingPos = 0; unsigned nextUnused = 1; unsigned tetIndex, tet, dest, faceIndex, face; NPerm4 map; unsigned mapIndex; for (tet = 0; tet < nTets; tet++) image[tet] = preImage[tet] = -1; image[0] = preImage[0] = 0; vertexMap[0] = NPerm4(); newTet[0] = 0; for (tetIndex = 0; tetIndex < nTets; tetIndex++) { // We must run through the tetrahedra in image order, not // preimage order. tet = preImage[tetIndex]; for (faceIndex = 0; faceIndex < 4; faceIndex++) { // Likewise for faces. face = vertexMap[tet].preImageOf(faceIndex); // INVARIANTS (held while tet < nTets): // - nextUnused > tetIndex // - image[tet], preImage[image[tet]] and vertexMap[tet] are // all filled in. // These invariants are preserved because the triangulation is // connected. They break when tet == nTets. dest = tetrahedronIndex( tetrahedra_[tet]->adjacentTetrahedron(face)); // Is it a gluing we've already seen from the other side? if (image[dest] >= 0) if (image[dest] < image[tet] || (image[dest] == image[tet] && vertexMap[tet][tetrahedra_[tet]->adjacentFace(face)] < vertexMap[tet][face])) continue; // Is it a completely new tetrahedron? if (image[dest] < 0) { // Previously unseen. image[dest] = nextUnused; preImage[nextUnused] = dest; vertexMap[dest] = vertexMap[tet] * tetrahedra_[tet]->adjacentGluing(face). inverse(); nextUnused++; newTet[newTetPos] |= (1 << newTetBit); } else { // It's a tetrahedron we've seen before. Record the gluing. // Don't forget that our permutation abcd becomes dcba // in dehydration language. destChars[currGluingPos] = LETTER(image[dest]); map = vertexMap[dest] * tetrahedra_[tet]->adjacentGluing(face) * vertexMap[tet].inverse() * NPerm4(3, 2, 1, 0); // Just loop to find the index of the corresponding // gluing permutation. There's only 24 permutations and // at most 25 tetrahedra; we'll live with it. for (mapIndex = 0; mapIndex < 24; mapIndex++) if (map == NPerm4::orderedS4[mapIndex]) break; permChars[currGluingPos] = LETTER(mapIndex); currGluingPos++; } newTetBit++; if (newTetBit == 8) { newTetPos++; newTetBit = 0; newTet[newTetPos] = 0; } } } // We have all we need. Tidy up the strings and put them all // together. if (newTetBit > 0) { // We're partway through a bitset; assume it's finished and // point to the next unused slot in the array. newTetPos++; } // At this stage we should have currGluingPos == nTets + 1. destChars[currGluingPos] = 0; permChars[currGluingPos] = 0; std::string ans; ans += LETTER(nTets); for (unsigned i = 0; i < newTetPos; i++) { ans += LETTER(newTet[i] >> 4); ans += LETTER(newTet[i] & 15); } ans += destChars; ans += permChars; // Done! delete[] newTet; delete[] permChars; delete[] destChars; delete[] vertexMap; delete[] preImage; delete[] image; return ans; } } // namespace regina regina-4.96/engine/triangulation/insertlayered.cpp000644 000765 000024 00000027153 12377776755 022355 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "manifold/nlensspace.h" #include "manifold/nsfs.h" #include "triangulation/ntriangulation.h" namespace regina { NTetrahedron* NTriangulation::layerOn(NEdge* edge) { // Locate the two boundary triangles. // Note that our preconditions ensure they exist and are distinct; // we won't test this again here. const std::deque& embs(edge->getEmbeddings()); NTetrahedron* tet1 = embs.front().getTetrahedron(); NTetrahedron* tet2 = embs.back().getTetrahedron(); NPerm4 roles1 = embs.front().getVertices(); NPerm4 roles2 = embs.back().getVertices(); // At this stage, roles1 maps (0,1,2) to the tet1 tetrahedron vertices // for the first boundary triangle, and roles2 maps (0,1,3) to the tet2 // tetrahedron vertices for the second boundary triangle. In each case, // (0,1) maps to the endpoints of the given edge. // // The simplest thing to do is let (0,1,2,3) in the preimages for // roles1 and roles2 match up with vertices (0,1,2,3) of the new // tetrahedron. ChangeEventSpan span(this); NTetrahedron* newTet = newTetrahedron(); newTet->joinTo(3, tet1, roles1); newTet->joinTo(2, tet2, roles2); return newTet; } NTetrahedron* NTriangulation::insertLayeredSolidTorus( unsigned long cuts0, unsigned long cuts1) { ChangeEventSpan span(this); unsigned long cuts2 = cuts0 + cuts1; NTetrahedron* newTet = newTetrahedron(); // Take care of the case that can be done with a single // tetrahedron. if (cuts2 == 3) { // Must be a 1-2-3 arrangement that can be done with a single // tetrahedron. newTet->joinTo(0, newTet, NPerm4(1,2,3,0)); return newTet; } // Take care of the special small cases. if (cuts2 == 2) { // Make a 1-2-1 arrangement. NTetrahedron* base = insertLayeredSolidTorus(1, 2); base->joinTo(2, newTet, NPerm4(2,3,0,1)); base->joinTo(3, newTet, NPerm4(2,3,0,1)); return newTet; } if (cuts2 == 1) { // Make a 1-1-0 arrangement. NTetrahedron* base = insertLayeredSolidTorus(1, 1); base->joinTo(2, newTet, NPerm4(0,2,1,3)); base->joinTo(3, newTet, NPerm4(3,1,2,0)); return newTet; } // At this point we know cuts2 > 3. Recursively build the layered // triangulation. if (cuts1 - cuts0 > cuts0) { NTetrahedron* base = insertLayeredSolidTorus(cuts0, cuts1 - cuts0); base->joinTo(2, newTet, NPerm4(0,2,1,3)); base->joinTo(3, newTet, NPerm4(3,1,2,0)); } else { NTetrahedron* base = insertLayeredSolidTorus(cuts1 - cuts0, cuts0); base->joinTo(2, newTet, NPerm4(3,1,0,2)); base->joinTo(3, newTet, NPerm4(0,2,3,1)); } return newTet; } void NTriangulation::insertLayeredLensSpace(unsigned long p, unsigned long q) { ChangeEventSpan span(this); NTetrahedron* chain; if (p == 0) { chain = insertLayeredSolidTorus(1, 1); chain->joinTo(3, chain, NPerm4(3, 0, 1, 2)); } else if (p == 1) { chain = insertLayeredSolidTorus(1, 2); chain->joinTo(3, chain, NPerm4(0, 1, 3, 2)); } else if (p == 2) { chain = insertLayeredSolidTorus(1, 3); chain->joinTo(3, chain, NPerm4(0, 1, 3, 2)); } else if (p == 3) { chain = insertLayeredSolidTorus(1, 1); // Either of the following gluings will work. chain->joinTo(3, chain, NPerm4(1, 3, 0, 2)); // chain->joinTo(3, chain, NPerm4(0, 1, 3, 2)); } else { if (2 * q > p) q = p - q; if (3 * q > p) { chain = insertLayeredSolidTorus(p - 2 * q, q); chain->joinTo(3, chain, NPerm4(1, 3, 0, 2)); } else { chain = insertLayeredSolidTorus(q, p - 2 * q); chain->joinTo(3, chain, NPerm4(3, 0, 1, 2)); } } } void NTriangulation::insertLayeredLoop(unsigned long length, bool twisted) { if (length == 0) return; ChangeEventSpan span(this); // Insert a layered chain of the given length. // We should probably split this out into a separate routine. NTetrahedron* base; NTetrahedron* curr; NTetrahedron* next; base = newTetrahedron(); curr = base; for (unsigned long i = 1; i < length; i++) { next = newTetrahedron(); curr->joinTo(0, next, NPerm4(1, 0, 2, 3)); curr->joinTo(3, next, NPerm4(0, 1, 3, 2)); curr = next; } // Join the two ends of the layered chain. if (twisted) { curr->joinTo(0, base, NPerm4(2, 3, 1, 0)); curr->joinTo(3, base, NPerm4(3, 2, 0, 1)); } else { curr->joinTo(0, base, NPerm4(1, 0, 2, 3)); curr->joinTo(3, base, NPerm4(0, 1, 3, 2)); } } void NTriangulation::insertAugTriSolidTorus(long a1, long b1, long a2, long b2, long a3, long b3) { ChangeEventSpan span(this); int i; // Construct the core triangular solid torus. NTetrahedron* core[3]; for (i = 0; i < 3; i++) core[i] = newTetrahedron(); for (i = 0; i < 3; i++) core[i]->joinTo(0, core[(i + 1) % 3], NPerm4(3, 0, 1, 2)); // Attach the external layered solid tori. long axis, major, minor; unsigned long absAxis, absMajor, absMinor; NTetrahedron* lstTop; for (i = 0; i < 3; i++) { if (i == 0) axis = a1; else if (i == 1) axis = a2; else axis = a3; if (i == 0) major = b1; else if (i == 1) major = b2; else major = b3; minor = -(axis + major); absAxis = (axis < 0 ? -axis : axis); absMajor = (major < 0 ? -major : major); absMinor = (minor < 0 ? -minor : minor); // Are we simply attaching a mobius band? if (absAxis <= 2 && absMajor <= 2 && absMinor <= 2) { // We have either (2,1,1) or (1,1,0). if (absAxis == 2) { core[i]->joinTo(2, core[(i + 1) % 3], NPerm4(0, 2, 1, 3)); continue; } else if (absMajor == 2) { core[i]->joinTo(2, core[(i + 1) % 3], NPerm4(2, 3, 1, 0)); continue; } else if (absMinor == 2) { core[i]->joinTo(2, core[(i + 1) % 3], NPerm4(3, 0, 1, 2)); continue; } // It's (1,1,0). But this needs to be handled specially anyway. lstTop = insertLayeredSolidTorus(0, 1); if (absAxis == 0) { core[i]->joinTo(2, lstTop, NPerm4(0, 2, 3, 1)); core[(i + 1) % 3]->joinTo(1, lstTop, NPerm4(0, 2, 3, 1)); } else if (absMajor == 0) { core[i]->joinTo(2, lstTop, NPerm4(1, 0, 3, 2)); core[(i + 1) % 3]->joinTo(1, lstTop, NPerm4(3, 2, 1, 0)); } else { core[i]->joinTo(2, lstTop, NPerm4(3, 0, 2, 1)); core[(i + 1) % 3]->joinTo(1, lstTop, NPerm4(0, 3, 1, 2)); } continue; } if (absAxis >= absMajor && absAxis >= absMinor) { // Most cuts on the axis edges. if (absMinor <= absMajor) { // (minor, major, axis) lstTop = insertLayeredSolidTorus(absMinor, absMajor); core[i]->joinTo(2, lstTop, NPerm4(0, 2, 3, 1)); core[(i + 1) % 3]->joinTo(1, lstTop, NPerm4(0, 2, 3, 1)); } else { // (major, minor, axis) lstTop = insertLayeredSolidTorus(absMajor, absMinor); core[i]->joinTo(2, lstTop, NPerm4(1, 2, 3, 0)); core[(i + 1) % 3]->joinTo(1, lstTop, NPerm4(1, 2, 3, 0)); } } else if (absMajor >= absMinor) { // Most cuts on the major edges. if (absMinor <= absAxis) { // (minor, axis, major) lstTop = insertLayeredSolidTorus(absMinor, absAxis); core[i]->joinTo(2, lstTop, NPerm4(0, 1, 3, 2)); core[(i + 1) % 3]->joinTo(1, lstTop, NPerm4(3, 2, 0, 1)); } else { // (axis, minor, major) lstTop = insertLayeredSolidTorus(absAxis, absMinor); core[i]->joinTo(2, lstTop, NPerm4(1, 0, 3, 2)); core[(i + 1) % 3]->joinTo(1, lstTop, NPerm4(3, 2, 1, 0)); } } else { // Most cuts on the minor edges. if (absAxis <= absMajor) { // (axis, major, minor) lstTop = insertLayeredSolidTorus(absAxis, absMajor); core[i]->joinTo(2, lstTop, NPerm4(3, 1, 2, 0)); core[(i + 1) % 3]->joinTo(1, lstTop, NPerm4(1, 3, 0, 2)); } else { // (major, axis, minor) lstTop = insertLayeredSolidTorus(absMajor, absAxis); core[i]->joinTo(2, lstTop, NPerm4(3, 0, 2, 1)); core[(i + 1) % 3]->joinTo(1, lstTop, NPerm4(0, 3, 1, 2)); } } } } void NTriangulation::insertSFSOverSphere(long a1, long b1, long a2, long b2, long a3, long b3) { // Construct the SFS that we seek. NSFSpace sfs; if (a1 < 0) sfs.insertFibre(-a1, -b1); else sfs.insertFibre(a1, b1); if (a2 < 0) sfs.insertFibre(-a2, -b2); else sfs.insertFibre(a2, b2); if (a3 < 0) sfs.insertFibre(-a3, -b3); else sfs.insertFibre(a3, b3); sfs.reduce(); // Use the SFS construction routine, which can handle this type of SFS. NTriangulation* ans = sfs.construct(); insertTriangulation(*ans); delete ans; } } // namespace regina regina-4.96/engine/triangulation/isomorphic.cpp000644 000765 000024 00000041716 12377776755 021660 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include "triangulation/nisomorphism.h" #include "triangulation/ntriangulation.h" namespace regina { unsigned long NTriangulation::findIsomorphisms( const NTriangulation& other, std::list& results, bool completeIsomorphism, bool firstOnly) const { if (! calculatedSkeleton_) calculateSkeleton(); if (! other.calculatedSkeleton_) other.calculateSkeleton(); // Deal with the empty triangulation first. if (tetrahedra_.empty()) { if (completeIsomorphism && ! other.tetrahedra_.empty()) return 0; results.push_back(new NIsomorphism(0)); return 1; } // Basic property checks. Unfortunately, if we allow boundary // incomplete isomorphisms then we can't test that many properties. if (completeIsomorphism) { // Must be boundary complete, 1-to-1 and onto. // That is, combinatorially the two triangulations must be // identical. if (tetrahedra_.size() != other.tetrahedra_.size()) return 0; if (triangles_.size() != other.triangles_.size()) return 0; if (edges_.size() != other.edges_.size()) return 0; if (vertices_.size() != other.vertices_.size()) return 0; if (components_.size() != other.components_.size()) return 0; if (boundaryComponents_.size() != other.boundaryComponents_.size()) return 0; if (orientable_ ^ other.orientable_) return 0; // Test degree sequences and the like. std::map map1; std::map map2; std::map::iterator mapIt; { EdgeIterator it; for (it = edges_.begin(); it != edges_.end(); it++) { // Find this degree, or insert it with frequency 0 if it's // not already present. mapIt = map1.insert( std::make_pair((*it)->getNumberOfEmbeddings(), 0)).first; (*mapIt).second++; } for (it = other.edges_.begin(); it != other.edges_.end(); it++) { mapIt = map2.insert( std::make_pair((*it)->getNumberOfEmbeddings(), 0)).first; (*mapIt).second++; } if (! (map1 == map2)) return 0; map1.clear(); map2.clear(); } { VertexIterator it; for (it = vertices_.begin(); it != vertices_.end(); it++) { mapIt = map1.insert( std::make_pair((*it)->getNumberOfEmbeddings(), 0)).first; (*mapIt).second++; } for (it = other.vertices_.begin(); it != other.vertices_.end(); it++) { mapIt = map2.insert( std::make_pair((*it)->getNumberOfEmbeddings(), 0)).first; (*mapIt).second++; } if (! (map1 == map2)) return 0; map1.clear(); map2.clear(); } { ComponentIterator it; for (it = components_.begin(); it != components_.end(); it++) { mapIt = map1.insert( std::make_pair((*it)->getNumberOfTetrahedra(), 0)).first; (*mapIt).second++; } for (it = other.components_.begin(); it != other.components_.end(); it++) { mapIt = map2.insert( std::make_pair((*it)->getNumberOfTetrahedra(), 0)).first; (*mapIt).second++; } if (! (map1 == map2)) return 0; map1.clear(); map2.clear(); } { BoundaryComponentIterator it; for (it = boundaryComponents_.begin(); it != boundaryComponents_.end(); it++) { mapIt = map1.insert( std::make_pair((*it)->getNumberOfTriangles(), 0)).first; (*mapIt).second++; } for (it = other.boundaryComponents_.begin(); it != other.boundaryComponents_.end(); it++) { mapIt = map2.insert( std::make_pair((*it)->getNumberOfTriangles(), 0)).first; (*mapIt).second++; } if (! (map1 == map2)) return 0; map1.clear(); map2.clear(); } } else { // May be boundary incomplete, and need not be onto. // Not much we can test for unfortunately. if (tetrahedra_.size() > other.tetrahedra_.size()) return 0; if ((! orientable_) && other.orientable_) return 0; } // Start searching for the isomorphism. // From the tests above, we are guaranteed that both triangulations // have at least one tetrahedron. unsigned long nResults = 0; unsigned long nTetrahedra = tetrahedra_.size(); unsigned long nDestTetrahedra = other.tetrahedra_.size(); unsigned long nComponents = components_.size(); unsigned i; NIsomorphism iso(nTetrahedra); for (i = 0; i < nTetrahedra; i++) iso.tetImage(i) = -1; // Which source component does each destination tetrahedron correspond to? long* whichComp = new long[nDestTetrahedra]; std::fill(whichComp, whichComp + nDestTetrahedra, -1); // The image of the first source tetrahedron of each component. The // remaining images can be derived by following gluings. unsigned long* startTet = new unsigned long[nComponents]; std::fill(startTet, startTet + nComponents, 0); int* startPerm = new int[nComponents]; std::fill(startPerm, startPerm + nComponents, 0); // The tetrahedra whose neighbours must be processed when filling // out the current component. std::queue toProcess; // Temporary variables. unsigned long compSize; NTetrahedron* tet; NTetrahedron* adj; NTetrahedron* destTet; NTetrahedron* destAdj; unsigned long tetIndex, adjIndex; unsigned long destTetIndex, destAdjIndex; NPerm4 tetPerm, adjPerm; int face; bool broken; long comp = 0; while (comp >= 0) { // Continue trying to find a mapping for the current component. // The next mapping to try is the one that starts with // startTet[comp] and startPerm[comp]. if (comp == static_cast(nComponents)) { // We have an isomorphism!!! results.push_back(new NIsomorphism(iso)); if (firstOnly) { delete[] whichComp; delete[] startTet; delete[] startPerm; return 1; } else nResults++; // Back down to the previous component, and clear the // mapping for that previous component so we can make way // for a new one. // Since nComponents > 0, we are guaranteed that comp > 0 also. comp--; for (i = 0; i < nTetrahedra; i++) if (iso.tetImage(i) >= 0 && whichComp[iso.tetImage(i)] == comp) { whichComp[iso.tetImage(i)] = -1; iso.tetImage(i) = -1; } startPerm[comp]++; continue; } // Sort out the results of any previous startPerm++. if (startPerm[comp] == 24) { // Move on to the next destination tetrahedron. startTet[comp]++; startPerm[comp] = 0; } // Be sure we're looking at a tetrahedron we can use. compSize = components_[comp]->getNumberOfTetrahedra(); if (completeIsomorphism) { // Conditions: // 1) The destination tetrahedron is unused. // 2) The component sizes match precisely. while (startTet[comp] < nDestTetrahedra && (whichComp[startTet[comp]] >= 0 || other.tetrahedra_[startTet[comp]]->getComponent()-> getNumberOfTetrahedra() != compSize)) startTet[comp]++; } else { // Conditions: // 1) The destination tetrahedron is unused. // 2) The destination component is at least as large as // the source component. while (startTet[comp] < nDestTetrahedra && (whichComp[startTet[comp]] >= 0 || other.tetrahedra_[startTet[comp]]->getComponent()-> getNumberOfTetrahedra() < compSize)) startTet[comp]++; } // Have we run out of possibilities? if (startTet[comp] == nDestTetrahedra) { // No more possibilities for filling this component. // Move back to the previous component, and clear the // mapping for that previous component. startTet[comp] = 0; startPerm[comp] = 0; comp--; if (comp >= 0) { for (i = 0; i < nTetrahedra; i++) if (iso.tetImage(i) >= 0 && whichComp[iso.tetImage(i)] == comp) { whichComp[iso.tetImage(i)] = -1; iso.tetImage(i) = -1; } startPerm[comp]++; } continue; } // Try to fill the image of this component based on the selected // image of its first source tetrahedron. // Note that there is only one way of doing this (as seen by // following adjacent tetrahedron gluings). It either works or // it doesn't. tetIndex = tetrahedronIndex(components_[comp]->getTetrahedron(0)); whichComp[startTet[comp]] = comp; iso.tetImage(tetIndex) = startTet[comp]; iso.facePerm(tetIndex) = NPerm4::S4[startPerm[comp]]; toProcess.push(tetIndex); broken = false; while ((! broken) && (! toProcess.empty())) { tetIndex = toProcess.front(); toProcess.pop(); tet = tetrahedra_[tetIndex]; tetPerm = iso.facePerm(tetIndex); destTetIndex = iso.tetImage(tetIndex); destTet = other.tetrahedra_[destTetIndex]; // If we are after a complete isomorphism, we might as well // test whether the edge and vertex degrees match. if (completeIsomorphism && ! compatibleTets(tet, destTet, tetPerm)) { broken = true; break; } for (face = 0; face < 4; face++) { adj = tet->adjacentTetrahedron(face); if (adj) { // There is an adjacent source tetrahedron. // Is there an adjacent destination tetrahedron? destAdj = destTet->adjacentTetrahedron(tetPerm[face]); if (! destAdj) { broken = true; break; } // Work out what the isomorphism *should* say. adjIndex = tetrahedronIndex(adj); destAdjIndex = other.tetrahedronIndex(destAdj); adjPerm = destTet->adjacentGluing(tetPerm[face]) * tetPerm * tet->adjacentGluing(face).inverse(); if (iso.tetImage(adjIndex) >= 0) { // We've already decided upon an image for this // source tetrahedron. Does it match? if (static_cast(destAdjIndex) != iso.tetImage(adjIndex) || adjPerm != iso.facePerm(adjIndex)) { broken = true; break; } } else if (whichComp[destAdjIndex] >= 0) { // We haven't decided upon an image for this // source tetrahedron but the destination // tetrahedron has already been used. broken = true; break; } else { // We haven't seen either the source or the // destination tetrahedron. whichComp[destAdjIndex] = comp; iso.tetImage(adjIndex) = destAdjIndex; iso.facePerm(adjIndex) = adjPerm; toProcess.push(adjIndex); } } else if (completeIsomorphism) { // There is no adjacent source tetrahedron, and we // are after a boundary complete isomorphism. // There had better be no adjacent destination // tetrahedron also. if (destTet->adjacentTetrahedron(tetPerm[face])) { broken = true; break; } } } } if (! broken) { // Therefore toProcess is empty. // The image for this component was successfully filled out. // Move on to the next component. comp++; } else { // The image for this component was not successfully filled out. // Undo our partially created image, and then try another // starting image for this component. while (! toProcess.empty()) toProcess.pop(); for (i = 0; i < nTetrahedra; i++) if (iso.tetImage(i) >= 0 && whichComp[iso.tetImage(i)] == comp) { whichComp[iso.tetImage(i)] = -1; iso.tetImage(i) = -1; } startPerm[comp]++; } } // All out of options. delete[] whichComp; delete[] startTet; delete[] startPerm; return nResults; } bool NTriangulation::compatibleTets(NTetrahedron* src, NTetrahedron* dest, NPerm4 p) { for (int edge = 0; edge < 6; edge++) { if (src->getEdge(edge)->getNumberOfEmbeddings() != dest->getEdge(NEdge::edgeNumber[p[NEdge::edgeVertex[edge][0]]] [p[NEdge::edgeVertex[edge][1]]]) ->getNumberOfEmbeddings()) return false; } for (int vertex = 0; vertex < 4; vertex++) { if (src->getVertex(vertex)->getNumberOfEmbeddings() != dest->getVertex(p[vertex])->getNumberOfEmbeddings()) return false; if (src->getVertex(vertex)->getLink() != dest->getVertex(p[vertex])->getLink()) return false; } return true; } } // namespace regina regina-4.96/engine/triangulation/nboundarycomponent.cpp000644 000765 000024 00000006431 12377776756 023424 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "triangulation/nboundarycomponent.h" namespace regina { void NBoundaryComponent::writeTextLong(std::ostream& out) const { writeTextShort(out); out << std::endl; if (isIdeal()) { NVertex* v = vertices_.front(); out << "Vertex: " << v->markedIndex() << std::endl; out << "Appears as:" << std::endl; std::vector::const_iterator it; for (it = v->getEmbeddings().begin(); it != v->getEmbeddings().end(); ++it) out << " " << it->getTetrahedron()->markedIndex() << " (" << it->getVertex() << ')' << std::endl; } else { out << "Triangles:" << std::endl; std::vector::const_iterator it; for (it = triangles_.begin(); it != triangles_.end(); ++it) { const NTriangleEmbedding& emb((*it)->getEmbedding(0)); out << " " << emb.getTetrahedron()->markedIndex() << " (" << emb.getVertices().trunc3() << ')' << std::endl; } } } } // namespace regina regina-4.96/engine/triangulation/nboundarycomponent.h000644 000765 000024 00000032210 12377775613 023052 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #ifndef __NBOUNDARYCOMPONENT_H #ifndef __DOXYGEN #define __NBOUNDARYCOMPONENT_H #endif /*! \file triangulation/nboundarycomponent.h * \brief Deals with components of the boundary of a triangulation. */ #include #include "regina-core.h" #include "shareableobject.h" #include "utilities/nmarkedvector.h" // NOTE: More #includes follow after the class declarations. namespace regina { class NComponent; class NEdge; class NTriangle; class NTetrahedron; class NVertex; /** * \weakgroup triangulation * @{ */ /** * Represents a component of the boundary of a triangulation. * Note that an ideal vertex constitutes a boundary component of its * own. * * We can run into some interesting cases with invalid triangulations. * Suppose some vertex link is a multiply punctured surface (which makes * the vertex and hence the entire triangulation invalid). This means * that different parts of the 3-manifold boundary are effectively * "pinched" together. If this happens, the different parts of the * boundary that are pinched might or might not be listed as part of the * same boundary component; if not then the offending vertex will be * included in all of these boundary components. Nevertheless, only one * of these can be considered the "official" boundary component of the * vertex as returned by NVertex::getBoundaryComponent(). This is all a * bit of a mess, but then again the entire triangulation is invalid and * so you almost certainly have bigger problems to deal with. * * Boundary components are highly temporary; once a triangulation * changes, all its boundary component objects will be deleted and new * ones will be created. */ class REGINA_API NBoundaryComponent : public ShareableObject, public NMarkedElement { private: std::vector triangles_; /**< List of triangles in the component. */ std::vector edges_; /**< List of edges in the component. */ std::vector vertices_; /**< List of vertices in the component. */ bool orientable_; /**< Is this boundary component orientable? */ public: /** * Default destructor. */ virtual ~NBoundaryComponent(); /** * Returns the index of this boundary component in the underlying * triangulation. This is identical to calling * getTriangulation()->boundaryComponentIndex(this). * * @return the index of this boundary component vertex. */ unsigned long index() const; /** * Returns the number of triangles in this boundary component. * * @return the number of triangles. */ unsigned long getNumberOfTriangles() const; /** * A deprecated alias for getNumberOfTriangles(). * * This routine returns the number of triangular faces in this * boundary component. See getNumberOfTriangles() for further details. * * \deprecated This routine will be removed in a future version * of Regina. Please use getNumberOfTriangles() instead. * * @return the number of triangles. */ unsigned long getNumberOfFaces() const; /** * Returns the number of edges in this boundary component. * * @return the number of edges. */ unsigned long getNumberOfEdges() const; /** * Returns the number of vertices in this boundary component. * * @return the number of vertices. */ unsigned long getNumberOfVertices() const; /** * Returns the requested triangle in this boundary component. * * For an ideal boundary component (which consists of a single * vertex), there are no real triangles in the boundary component * and this routine cannot be used. * * @param index the index of the requested triangle in the boundary * component. This should be between 0 and getNumberOfTriangles()-1 * inclusive. * Note that the index of a triangle in the boundary component need * not be the index of the same triangle in the entire * triangulation. * @return the requested triangle. */ NTriangle* getTriangle(unsigned long index) const; /** * A deprecated alias for getTriangle(). * * This routine returns the requested triangular face in this * boundary component. See getTriangle() for further details. * * \deprecated This routine will be removed in a future version * of Regina. Please use getTriangle() instead. * * @param index the index of the requested triangle in the boundary * component. This should be between 0 and getNumberOfTriangles()-1 * inclusive. * Note that the index of a triangle in the boundary component need * not be the index of the same triangle in the entire * triangulation. * @return the requested triangle. */ NTriangle* getFace(unsigned long index) const; /** * Returns the requested edge in this boundary component. * * For an ideal boundary component (which consists of a single * vertex), there are no real edges in the boundary component * and this routine cannot be used. * * @param index the index of the requested edge in the boundary * component. This should be between 0 and getNumberOfEdges()-1 * inclusive. * Note that the index of a edge in the boundary component need * not be the index of the same edge in the entire * triangulation. * @return the requested edge. */ NEdge* getEdge(unsigned long index) const; /** * Returns the requested vertex in this boundary component. * * @param index the index of the requested vertex in the boundary * component. This should be between 0 and getNumberOfVertices()-1 * inclusive. * Note that the index of a vertex in the boundary component need * not be the index of the same vertex in the entire * triangulation. * @return the requested vertex. */ NVertex* getVertex(unsigned long index) const; /** * Returns the component of the triangulation to which this * boundary component belongs. * * @return the component containing this boundary component. */ NComponent* getComponent() const; /** * Returns the Euler characteristic of this boundary component. * If this boundary component is ideal, the Euler characteristic * of the link of the corresponding ideal vertex is returned. * * @return the Euler characteristic. */ long getEulerChar() const; /** * A deprecated alias for getEulerChar(). * * Returns the Euler characteristic of this boundary component. * If this boundary component is ideal, the Euler characteristic * of the link of the corresponding ideal vertex is returned. * * \deprecated This routine will be removed in a future version of * Regina. Please use the identical routine getEulerChar() instead. * * @return the Euler characteristic. */ long getEulerCharacteristic() const; /** * Determines if this boundary component is ideal. * This is the case if and only if it consists of a single * (ideal) vertex and no triangles. * * @return \c true if and only if this boundary component is * ideal. */ bool isIdeal() const; /** * Determines if this boundary component is orientable. * If the boundary component is ideal, the orientability * of the link of the corresponding ideal vertex is returned. * * @return \c true if and only if this boundary component is * orientable. */ bool isOrientable() const; void writeTextShort(std::ostream& out) const; void writeTextLong(std::ostream& out) const; private: /** * Default constructor. */ NBoundaryComponent(); /** * Creates a new boundary component consisting only of the given * ideal vertex. * * \pre The given vertex is ideal as returned by NVertex::isIdeal(). * * @param idealVertex the vertex to place in the new boundary * component. */ NBoundaryComponent(NVertex* idealVertex); friend class NTriangulation; /**< Allow access to private members. */ }; /*@}*/ } // namespace regina // Some more headers that are required for inline functions: #include "triangulation/nvertex.h" namespace regina { // Inline functions for NBoundaryComponent inline NBoundaryComponent::NBoundaryComponent() { } inline NBoundaryComponent::NBoundaryComponent(NVertex* idealVertex) { vertices_.push_back(idealVertex); } inline NBoundaryComponent::~NBoundaryComponent() { } inline unsigned long NBoundaryComponent::index() const { return markedIndex(); } inline unsigned long NBoundaryComponent::getNumberOfTriangles() const { return triangles_.size(); } inline unsigned long NBoundaryComponent::getNumberOfFaces() const { return triangles_.size(); } inline unsigned long NBoundaryComponent::getNumberOfEdges() const { return edges_.size(); } inline unsigned long NBoundaryComponent::getNumberOfVertices() const { return vertices_.size(); } inline NTriangle* NBoundaryComponent::getTriangle(unsigned long index) const { return triangles_[index]; } inline NTriangle* NBoundaryComponent::getFace(unsigned long index) const { return triangles_[index]; } inline NEdge* NBoundaryComponent::getEdge(unsigned long index) const { return edges_[index]; } inline NVertex* NBoundaryComponent::getVertex(unsigned long index) const { return vertices_[index]; } inline NComponent* NBoundaryComponent::getComponent() const { // There may be no triangles, but there is always a vertex. return vertices_.front()->getComponent(); } inline long NBoundaryComponent::getEulerChar() const { return (isIdeal() ? vertices_.front()->getLinkEulerChar() : long(vertices_.size()) - long(edges_.size()) + long(triangles_.size())); } inline long NBoundaryComponent::getEulerCharacteristic() const { return getEulerChar(); } inline bool NBoundaryComponent::isIdeal() const { return triangles_.empty(); } inline bool NBoundaryComponent::isOrientable() const { return orientable_; } inline void NBoundaryComponent::writeTextShort(std::ostream& out) const { out << (isIdeal() ? "Ideal " : "Finite ") << "boundary component"; } } // namespace regina #endif regina-4.96/engine/triangulation/ncomponent.cpp000644 000765 000024 00000005705 12377776756 021663 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "triangulation/ncomponent.h" #include "triangulation/ntetrahedron.h" namespace regina { void NComponent::writeTextShort(std::ostream& out) const { if (tetrahedra_.size() == 1) out << "Component with 1 tetrahedron"; else out << "Component with " << getNumberOfTetrahedra() << " tetrahedra"; } void NComponent::writeTextLong(std::ostream& out) const { writeTextShort(out); out << std::endl; out << (tetrahedra_.size() == 1 ? "Tetrahedron:" : "Tetrahedra:"); std::vector::const_iterator it; for (it = tetrahedra_.begin(); it != tetrahedra_.end(); ++it) out << ' ' << (*it)->markedIndex(); out << std::endl; } } // namespace regina regina-4.96/engine/triangulation/ncomponent.h000644 000765 000024 00000032052 12377775615 021314 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #ifndef __NCOMPONENT_H #ifndef __DOXYGEN #define __NCOMPONENT_H #endif /*! \file triangulation/ncomponent.h * \brief Deals with components of a triangulation. */ #include #include "regina-core.h" #include "shareableobject.h" #include "utilities/nmarkedvector.h" namespace regina { class NTetrahedron; class NTriangle; class NEdge; class NVertex; class NBoundaryComponent; /** * \weakgroup triangulation * @{ */ /** * Represents a component of a triangulation. * Components are highly temporary; once a triangulation changes, all * its component objects will be deleted and new ones will be created. */ class REGINA_API NComponent : public ShareableObject, public NMarkedElement { private: std::vector tetrahedra_; /**< List of tetrahedra in the component. */ std::vector triangles_; /**< List of triangles in the component. */ std::vector edges_; /**< List of edges in the component. */ std::vector vertices_; /**< List of vertices in the component. */ std::vector boundaryComponents_; /**< List of boundary components in the component. */ bool ideal_; /**< Is the component ideal? */ bool orientable_; /**< Is the component orientable? */ public: /** * Default destructor. */ virtual ~NComponent(); /** * Returns the index of this component in the underlying * triangulation. This is identical to calling * getTriangulation()->componentIndex(this). * * @return the index of this component vertex. */ unsigned long index() const; /** * Returns the number of tetrahedra in this component. * * @return the number of tetrahedra. */ unsigned long getNumberOfTetrahedra() const; /** * A dimension-agnostic alias for getNumberOfTetrahedra(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "simplex" refers to a top-dimensional simplex (which for * 3-manifold triangulations means a tetrahedron). * * See getNumberOfTetrahedra() for further information. */ unsigned long getNumberOfSimplices() const; /** * Returns the number of triangles in this component. * * @return the number of triangles. */ unsigned long getNumberOfTriangles() const; /** * A deprecated alias for getNumberOfTriangles(). * * This routine returns the number of triangular faces in this * component. See getNumberOfTriangles() for further details. * * \deprecated This routine will be removed in a future version * of Regina. Please use getNumberOfTriangles() instead. * * @return the number of triangles. */ unsigned long getNumberOfFaces() const; /** * Returns the number of edges in this component. * * @return the number of edges. */ unsigned long getNumberOfEdges() const; /** * Returns the number of vertices in this component. * * @return the number of vertices. */ unsigned long getNumberOfVertices() const; /** * Returns the number of boundary components in this component. * * @return the number of boundary components. */ unsigned long getNumberOfBoundaryComponents() const; /** * Returns the requested tetrahedron in this component. * * @param index the index of the requested tetrahedron in the * component. This should be between 0 and * getNumberOfTetrahedra()-1 inclusive. * Note that the index of a tetrahedron in the component need * not be the index of the same tetrahedron in the entire * triangulation. * @return the requested tetrahedron. */ NTetrahedron* getTetrahedron(unsigned long index) const; /** * A dimension-agnostic alias for getTetrahedron(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "simplex" refers to a top-dimensional simplex (which for * 3-manifold triangulations means a tetrahedron). * * See getTetrahedron() for further information. */ NTetrahedron* getSimplex(unsigned long index) const; /** * Returns the requested triangle in this component. * * @param index the index of the requested triangle in the * component. This should be between 0 and * getNumberOfTriangles()-1 inclusive. * Note that the index of a triangle in the component need * not be the index of the same triangle in the entire * triangulation. * @return the requested triangle. */ NTriangle* getTriangle(unsigned long index) const; /** * A deprecated alias for getTriangle(). * * This routine returns the requested triangular face in this * component. See getTriangle() for further details. * * \deprecated This routine will be removed in a future version * of Regina. Please use getTriangle() instead. * * @param index the index of the requested triangle in the * component. This should be between 0 and * getNumberOfTriangles()-1 inclusive. * Note that the index of a triangle in the component need * not be the index of the same triangle in the entire * triangulation. * @return the requested triangle. */ NTriangle* getFace(unsigned long index) const; /** * Returns the requested edge in this component. * * @param index the index of the requested edge in the * component. This should be between 0 and * getNumberOfEdges()-1 inclusive. * Note that the index of an edge in the component need * not be the index of the same edge in the entire * triangulation. * @return the requested edge. */ NEdge* getEdge(unsigned long index) const; /** * Returns the requested vertex in this component. * * @param index the index of the requested vertex in the * component. This should be between 0 and * getNumberOfVertices()-1 inclusive. * Note that the index of a vertex in the component need * not be the index of the same vertex in the entire * triangulation. * @return the requested vertex. */ NVertex* getVertex(unsigned long index) const; /** * Returns the requested boundary component in this component. * * @param index the index of the requested boundary component in * this component. This should be between 0 and * getNumberOfBoundaryComponents()-1 inclusive. * Note that the index of a boundary component in the component * need not be the index of the same boundary component in the * entire triangulation. * @return the requested boundary component. */ NBoundaryComponent* getBoundaryComponent(unsigned long index) const; /** * Determines if this component is ideal. * This is the case if and only if it contains an ideal vertex * as described by NVertex::isIdeal(). * * @return \c true if and only if this component is ideal. */ bool isIdeal() const; /** * Determines if this component is orientable. * * @return \c true if and only if this component is orientable. */ bool isOrientable() const; /** * Determines if this component is closed. * This is the case if and only if it has no boundary. * Note that ideal components are not closed. * * @return \c true if and only if this component is closed. */ bool isClosed() const; /** * Returns the number of boundary triangles in this component. * * @return the number of boundary triangles. */ unsigned long getNumberOfBoundaryTriangles() const; void writeTextShort(std::ostream& out) const; void writeTextLong(std::ostream& out) const; private: /** * Default constructor. */ NComponent(); friend class NTriangulation; /**< Allow access to private members. */ }; /*@}*/ // Inline functions for NComponent inline NComponent::NComponent() : ideal_(false), orientable_(true) { } inline NComponent::~NComponent() { } inline unsigned long NComponent::index() const { return markedIndex(); } inline unsigned long NComponent::getNumberOfTetrahedra() const { return tetrahedra_.size(); } inline unsigned long NComponent::getNumberOfSimplices() const { return tetrahedra_.size(); } inline unsigned long NComponent::getNumberOfTriangles() const { return triangles_.size(); } inline unsigned long NComponent::getNumberOfFaces() const { return triangles_.size(); } inline unsigned long NComponent::getNumberOfEdges() const { return edges_.size(); } inline unsigned long NComponent::getNumberOfVertices() const { return vertices_.size(); } inline unsigned long NComponent::getNumberOfBoundaryComponents() const { return boundaryComponents_.size(); } inline NTetrahedron* NComponent::getTetrahedron(unsigned long index) const { return tetrahedra_[index]; } inline NTetrahedron* NComponent::getSimplex(unsigned long index) const { return tetrahedra_[index]; } inline NTriangle* NComponent::getTriangle(unsigned long index) const { return triangles_[index]; } inline NTriangle* NComponent::getFace(unsigned long index) const { return triangles_[index]; } inline NEdge* NComponent::getEdge(unsigned long index) const { return edges_[index]; } inline NVertex* NComponent::getVertex(unsigned long index) const { return vertices_[index]; } inline NBoundaryComponent* NComponent::getBoundaryComponent(unsigned long index) const { return boundaryComponents_[index]; } inline bool NComponent::isIdeal() const { return ideal_; } inline bool NComponent::isOrientable() const { return orientable_; } inline bool NComponent::isClosed() const { return (boundaryComponents_.empty()); } inline unsigned long NComponent::getNumberOfBoundaryTriangles() const { return 2 * triangles_.size() - 4 * tetrahedra_.size(); } } // namespace regina #endif regina-4.96/engine/triangulation/nedge.cpp000644 000765 000024 00000006530 12377776757 020563 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "triangulation/nedge.h" namespace regina { const int edgeNumber[4][4] = { { -1, 0, 1, 2 }, { 0,-1, 3, 4 }, { 1, 3,-1, 5 }, { 2, 4, 5,-1 }}; const int edgeStart[6] = { 0, 0, 0, 1, 1, 2 }; const int edgeEnd[6] = { 1, 2, 3, 2, 3, 3 }; const int NEdge::edgeNumber[4][4] = { { -1, 0, 1, 2 }, { 0,-1, 3, 4 }, { 1, 3,-1, 5 }, { 2, 4, 5,-1 }}; const int NEdge::edgeVertex[6][2] = { { 0, 1 }, { 0, 2 }, { 0, 3 }, { 1, 2 }, { 1, 3 }, { 2, 3 }}; const NPerm4 NEdge::ordering[6] = { NPerm4(0, 1, 2, 3), NPerm4(0, 2, 3, 1), NPerm4(0, 3, 1, 2), NPerm4(1, 2, 0, 3), NPerm4(1, 3, 2, 0), NPerm4(2, 3, 0, 1) }; void NEdge::writeTextLong(std::ostream& out) const { writeTextShort(out); out << std::endl; out << "Appears as:" << std::endl; std::deque::const_iterator it; for (it = embeddings_.begin(); it != embeddings_.end(); ++it) out << " " << it->getTetrahedron()->markedIndex() << " (" << it->getVertices().trunc2() << ')' << std::endl; } } // namespace regina regina-4.96/engine/triangulation/nedge.h000644 000765 000024 00000046022 12377775617 020222 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file triangulation/nedge.h * \brief Deals with edges in a triangulation. */ #ifndef __NEDGE_H #ifndef __DOXYGEN #define __NEDGE_H #endif #include #include "regina-core.h" #include "shareableobject.h" #include "maths/nperm4.h" #include "utilities/nmarkedvector.h" // NOTE: More #includes follow after the class declarations. namespace regina { class NBoundaryComponent; class NComponent; class NTetrahedron; class NTriangulation; class NVertex; /** * \weakgroup triangulation * @{ */ /** * edgeNumber[i][j] is the number of the edge linking vertices * i and j in a tetrahedron. i and j * must be between 0 and 3 inclusive and may be given in any order. * The resulting edge number will be between 0 and 5 inclusive. * * Note that edge numbers of opposite edges will always add to 5. * * \deprecated This array has been replaced with the identical array * NEdge::edgeNumber. Users are advised to switch to NEdge::edgeNumber * instead, since the old regina::edgeNumber will eventually be removed * in some future version of Regina. */ REGINA_API extern const int edgeNumber[4][4]; /** * edgeStart[k] is the vertex of a tetrahedron at which edge * k of the tetrahedron begins. k must be between 0 and 5 * inclusive. The resulting vertex number will be between 0 and 3 inclusive. * * Note that edge numbers of opposite edges will always add to 5. * You are guaranteed that edgeStart[e] will always be smaller * than edgeEnd[e]. * * \deprecated This array has been superceded by NEdge::edgeVertex * (where edgeStart[i] is now NEdge::edgeVertex[i][0]). * Users are advised to switch to NEdge::edgeVertex instead, since the old * regina::edgeStart and regina::edgeEnd will eventually be removed in some * future version of Regina. */ REGINA_API extern const int edgeStart[6]; /** * edgeEnd[k] is the vertex of a tetrahedron * at which edge k of the tetrahedron ends. * k must be between 0 and 5 inclusive. * The resulting vertex number will be between 0 and 3 inclusive. * * Note that edge numbers of opposite edges will always add to 5. * You are guaranteed that edgeStart[e] will always be smaller * than edgeEnd[e]. * * \deprecated This array has been superceded by NEdge::edgeVertex * (where edgeEnd[i] is now NEdge::edgeVertex[i][1]). * Users are advised to switch to NEdge::edgeVertex instead, since the old * regina::edgeStart and regina::edgeEnd will eventually be removed in some * future version of Regina. */ REGINA_API extern const int edgeEnd[6]; /** * Details how an edge in the skeleton forms part of an individual * tetrahedron. */ class REGINA_API NEdgeEmbedding { private: NTetrahedron* tetrahedron_; /**< The tetrahedron in which this edge is contained. */ int edge_; /**< The edge number of the tetrahedron that is this edge. */ public: /** * Default constructor. The embedding descriptor created is * unusable until it has some data assigned to it using * operator =. * * \ifacespython Not present. */ NEdgeEmbedding(); /** * Creates an embedding descriptor containing the given data. * * @param newTet the tetrahedron in which this edge is * contained. * @param newEdge the edge number of \a newTet that is this edge. */ NEdgeEmbedding(NTetrahedron* newTet, int newEdge); /** * Creates an embedding descriptor containing the same data as * the given embedding descriptor. * * @param cloneMe the embedding descriptor to clone. */ NEdgeEmbedding(const NEdgeEmbedding& cloneMe); /** * Assigns to this embedding descriptor the same data as is * contained in the given embedding descriptor. * * @param cloneMe the embedding descriptor to clone. */ NEdgeEmbedding& operator =(const NEdgeEmbedding& cloneMe); /** * Returns the tetrahedron in which this edge is contained. * * @return the tetrahedron. */ NTetrahedron* getTetrahedron() const; /** * Returns the edge number within getTetrahedron() that is * this edge. * * @return the edge number that is this edge. */ int getEdge() const; /** * Returns a mapping from vertices (0,1) of this edge to the * corresponding vertex numbers in getTetrahedron(). This * permutation also maps (2,3) to the two remaining tetrahedron * vertices in a manner that preserves orientation as you walk * around the edge. See NTetrahedron::getEdgeMapping() for details. * * @return a mapping from the vertices of this edge to the * vertices of getTetrahedron(). */ NPerm4 getVertices() const; /** * Tests whether this and the given embedding are identical. * Here "identical" means that they refer to the same edge of * the same tetrahedron. * * @param rhs the embedding to compare with this. * @return \c true if and only if both embeddings are identical. */ bool operator == (const NEdgeEmbedding& rhs) const; /** * Tests whether this and the given embedding are different. * Here "different" means that they do not refer to the same edge of * the same tetrahedron. * * @param rhs the embedding to compare with this. * @return \c true if and only if both embeddings are identical. */ bool operator != (const NEdgeEmbedding& rhs) const; }; /** * Represents an edge in the skeleton of a triangulation. * Edges are highly temporary; once a triangulation changes, all its * edge objects will be deleted and new ones will be created. */ class REGINA_API NEdge : public ShareableObject, public NMarkedElement { public: /** * A table that maps vertices of a tetrahedron to edge numbers. * * Edges in a tetrahedron are numbered 0,...,5. This table * converts vertices to edge numbers; in particular, the edge * joining vertices \a i and \a j of a tetrahedron is edge * number edgeNumber[i][j]. Here \a i and \a j must be * distinct, must be between 0 and 3 inclusive, and may be given * in any order. The resulting edge number will be between 0 and 5 * inclusive. * * Note that edge \a i is always opposite edge \a 5-i in a * tetrahedron. * * For reference, Regina assigns edge numbers in lexicographical * order. That is, edge 0 joins vertices 0 and 1, edge 1 joins * vertices 0 and 2, edge 2 joins vertices 0 and 3, and so on. * * This is identical to the old regina::edgeNumber global array. * Users are advised to use this NEdge::edgeNumber array instead, * since the global regina::edgeNumber is deprecated and will * eventually be removed in some future version of Regina. */ static const int edgeNumber[4][4]; /** * A table that maps edges of a tetrahedron to vertex numbers. * * Edges in a tetrahedron are numbered 0,...,5. This table * converts edge numbers to vertices; in particular, edge \a i * in a tetrahedron joins vertices edgeVertex[i][0] and * edgeVertex[i][1]. Here \a i must be bewteen 0 and 5 * inclusive; the resulting vertex numbers will be between 0 and 3 * inclusive. * * Note that edge \a i is always opposite edge \a 5-i in a tetrahedron. * It is guaranteed that edgeVertex[i][0] will always * be smaller than edgeVertex[i][1]. * * This is a combination of the old regina::edgeStart and * regina::edgeEnd global arrays (where * edgeVertex[i][0] == edgeStart[i] and * edgeVertex[i][1] == edgeEnd[i]). Users are advised * to use this NEdge::edgeVertex array instead, since the global * regina::edgeStart and regina::edgeEnd arrays are deprecated * and will eventually be removed in some future version of Regina. */ static const int edgeVertex[6][2]; /** * An array that maps edge numbers within a tetrahedron to the * canonical ordering of the individual tetrahedron vertices * that form each edge. * * This means that the vertices of edge \a i in a tetrahedron * are, in canonical order, ordering[i][0,1]. The * images ordering[i][2,3] are chosen to make each * permutation even. * * This table does \e not describe the mapping from specific * triangulation edges into individual tetrahedra (for that, * see NTetrahedron::getEdgeMapping() instead). This table * merely provides a neat and consistent way of listing the * vertices of any given tetrahedron edge. * * This lookup table replaces the deprecated routine * regina::edgeOrdering(). */ static const NPerm4 ordering[6]; private: std::deque embeddings_; /**< A list of descriptors telling how this edge forms a part of each individual tetrahedron that it belongs to. */ NComponent* component_; /**< The component that this edge is a part of. */ NBoundaryComponent* boundaryComponent_; /**< The boundary component that this edge is a part of, or 0 if this edge is internal. */ bool valid_; /**< Is this edge valid? */ public: /** * Default destructor. */ ~NEdge(); /** * Returns the index of this edge in the underlying * triangulation. This is identical to calling * getTriangulation()->edgeIndex(this). * * @return the index of this edge. */ unsigned long index() const; /** * Returns the list of descriptors detailing how this edge forms a * part of various tetrahedra in the triangulation. * Note that if this edge represents multiple edges of a * particular tetrahedron, then there will be multiple embedding * descriptors in the list regarding that tetrahedron. * * These embedding descriptors will be stored in order in the * list, so that if you run through the list and follow in turn * the edges of each tetrahedron defined by the images of (2,3) * under NEdgeEmbedding::getVertices(), then you will obtain an * ordered chain circling this edge. * * \ifacespython This routine returns a python list. * * @return the list of embedding descriptors. * @see NEdgeEmbedding */ const std::deque& getEmbeddings() const; /** * Returns the number of descriptors in the list returned by * getEmbeddings(). Note that this is identical to getDegree(). * * @return the number of embedding descriptors. */ unsigned long getNumberOfEmbeddings() const; /** * Returns the requested descriptor from the list returned by * getEmbeddings(). * * @param index the index of the requested descriptor. This * should be between 0 and getNumberOfEmbeddings()-1 inclusive. * @return the requested embedding descriptor. */ const NEdgeEmbedding& getEmbedding(unsigned long index) const; /** * Returns the triangulation to which this edge belongs. * * @return the triangulation containing this edge. */ NTriangulation* getTriangulation() const; /** * Returns the component of the triangulation to which this * edge belongs. * * @return the component containing this edge. */ NComponent* getComponent() const; /** * Returns the boundary component of the triangulation to which * this edge belongs. * * @return the boundary component containing this edge, or 0 if this * edge does not lie entirely within the boundary of the triangulation. */ NBoundaryComponent* getBoundaryComponent() const; /** * Returns the vertex of the triangulation that corresponds * to the given vertex of this edge. * * @param vertex the vertex of this edge to examine. This should * be 0 or 1. * @return the corresponding vertex of the triangulation. */ NVertex* getVertex(int vertex) const; /** * Returns the degree of this edge. Note that this is identical * to getNumberOfEmbeddings(). * * @return the degree of this edge. */ unsigned long getDegree() const; /** * Determines if this edge lies entirely on the boundary of the * triangulation. * * @return \c true if and only if this edge lies on the boundary. */ bool isBoundary() const; /** * Determines if this edge is valid. * An edge is valid if and only if it is not glued to itself * in reverse. * * @return \c true if and only if this edge is valid. */ bool isValid() const; void writeTextShort(std::ostream& out) const; void writeTextLong(std::ostream& out) const; private: /** * Creates a new edge and marks it as belonging to the * given triangulation component. * * @param myComponent the triangulation component to which this * edge belongs. */ NEdge(NComponent* myComponent); friend class NTriangulation; /**< Allow access to private members. */ }; /*@}*/ } // namespace regina // Some more headers that are required for inline functions: #include "triangulation/ntetrahedron.h" namespace regina { // Inline functions for NEdge inline NEdge::NEdge(NComponent* myComponent) : component_(myComponent), boundaryComponent_(0), valid_(true) { } inline NEdge::~NEdge() { } inline unsigned long NEdge::index() const { return markedIndex(); } inline NTriangulation* NEdge::getTriangulation() const { return embeddings_.front().getTetrahedron()->getTriangulation(); } inline NComponent* NEdge::getComponent() const { return component_; } inline NBoundaryComponent* NEdge::getBoundaryComponent() const { return boundaryComponent_; } inline NVertex* NEdge::getVertex(int vertex) const { return embeddings_.front().getTetrahedron()->getVertex( embeddings_.front().getVertices()[vertex]); } inline unsigned long NEdge::getDegree() const { return embeddings_.size(); } inline bool NEdge::isBoundary() const { return (boundaryComponent_ != 0); } inline bool NEdge::isValid() const { return valid_; } inline const std::deque & NEdge::getEmbeddings() const { return embeddings_; } inline unsigned long NEdge::getNumberOfEmbeddings() const { return embeddings_.size(); } inline const NEdgeEmbedding& NEdge::getEmbedding(unsigned long index) const { return embeddings_[index]; } inline void NEdge::writeTextShort(std::ostream& out) const { out << (isBoundary() ? "Boundary " : "Internal ") << "edge of degree " << getNumberOfEmbeddings(); } inline NEdgeEmbedding::NEdgeEmbedding() : tetrahedron_(0) { } inline NEdgeEmbedding::NEdgeEmbedding(const NEdgeEmbedding& cloneMe) : tetrahedron_(cloneMe.tetrahedron_), edge_(cloneMe.edge_) { } inline NEdgeEmbedding::NEdgeEmbedding(NTetrahedron* newTet, int newEdge) : tetrahedron_(newTet), edge_(newEdge) { } inline NEdgeEmbedding& NEdgeEmbedding::operator = (const NEdgeEmbedding& cloneMe) { tetrahedron_ = cloneMe.tetrahedron_; edge_ = cloneMe.edge_; return *this; } inline NTetrahedron* NEdgeEmbedding::getTetrahedron() const { return tetrahedron_; } inline int NEdgeEmbedding::getEdge() const { return edge_; } inline NPerm4 NEdgeEmbedding::getVertices() const { return tetrahedron_->getEdgeMapping(edge_); } inline bool NEdgeEmbedding::operator == (const NEdgeEmbedding& other) const { return ((tetrahedron_ == other.tetrahedron_) && (edge_ == other.edge_)); } inline bool NEdgeEmbedding::operator != (const NEdgeEmbedding& other) const { return ((tetrahedron_ != other.tetrahedron_) || (edge_ != other.edge_)); } } // namespace regina #endif regina-4.96/engine/triangulation/nexampletriangulation.cpp000644 000765 000024 00000037547 12377776760 024121 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "split/nsignature.h" #include "triangulation/nexampletriangulation.h" #include "triangulation/ntriangulation.h" namespace { static const int poincareAdj[5][4] = { { 1, 2, 3, 4}, { 0, 2, 4, 3}, { 0, 1, 3, 4}, { 0, 1, 4, 2}, { 0, 1, 2, 3} }; static const int poincareGluings[5][4][4] = { { { 0, 3, 2, 1 }, { 3, 0, 1, 2 }, { 3, 2, 0, 1 }, { 3, 1, 2, 0 } }, { { 0, 3, 2, 1 }, { 2, 1, 0, 3 }, { 2, 3, 1, 0 }, { 2, 0, 3, 1 } }, { { 1, 2, 3, 0 }, { 2, 1, 0, 3 }, { 1, 2, 3, 0 }, { 3, 0, 1, 2 } }, { { 2, 3, 1, 0 }, { 1, 3, 0, 2 }, { 1, 2, 3, 0 }, { 3, 0, 1, 2 } }, { { 3, 1, 2, 0 }, { 3, 2, 0, 1 }, { 1, 2, 3, 0 }, { 3, 0, 1, 2 } } }; static const int weeksAdj[9][4] = { { 0, 0, 1, 2}, { 0, 3, 4, 5}, { 0, 3, 4, 6}, { 1, 2, 5, 7}, { 1, 2, 7, 8}, { 1, 3, 6, 8}, { 2, 5, 8, 7}, { 3, 4, 8, 6}, { 4, 5, 6, 7} }; static const int weeksGluings[9][4][4] = { { { 1, 2, 3, 0 }, { 3, 0, 1, 2 }, { 3, 2, 0, 1 }, { 2, 3, 1, 0 } }, { { 2, 3, 1, 0 }, { 1, 0, 2, 3 }, { 1, 3, 0, 2 }, { 2, 3, 1, 0 } }, { { 3, 2, 0, 1 }, { 0, 1, 3, 2 }, { 0, 2, 1, 3 }, { 1, 2, 3, 0 } }, { { 1, 0, 2, 3 }, { 0, 1, 3, 2 }, { 2, 3, 1, 0 }, { 2, 3, 1, 0 } }, { { 2, 0, 3, 1 }, { 0, 2, 1, 3 }, { 0, 2, 1, 3 }, { 2, 3, 1, 0 } }, { { 3, 2, 0, 1 }, { 3, 2, 0, 1 }, { 0, 2, 1, 3 }, { 3, 2, 0, 1 } }, { { 3, 0, 1, 2 }, { 0, 2, 1, 3 }, { 1, 0, 2, 3 }, { 2, 1, 0, 3 } }, { { 3, 2, 0, 1 }, { 0, 2, 1, 3 }, { 1, 2, 3, 0 }, { 2, 1, 0, 3 } }, { { 3, 2, 0, 1 }, { 2, 3, 1, 0 }, { 1, 0, 2, 3 }, { 3, 0, 1, 2 } } }; static const int closedOrHypAdj[9][4] = { { 6, 8, 2, 8 }, { 6, 8, 3, 7 }, { 7, 0, 3, 4 }, { 1, 5, 5, 2 }, { 2, 6, 5, 7 }, { 3, 8, 3, 4 }, { 0, 4, 7, 1 }, { 1, 4, 2, 6 }, { 1, 0, 5, 0 } }; static const int closedOrHypGluings[9][4][4] = { { { 0, 1, 3, 2 }, { 3, 1, 2, 0 }, { 0, 2, 1, 3 }, { 0, 2, 1, 3 } }, { { 3, 1, 2, 0 }, { 1, 0, 2, 3 }, { 3, 2, 0, 1 }, { 2, 3, 1, 0 } }, { { 2, 0, 3, 1 }, { 0, 2, 1, 3 }, { 0, 1, 3, 2 }, { 3, 1, 2, 0 } }, { { 2, 3, 1, 0 }, { 3, 2, 0, 1 }, { 2, 1, 0, 3 }, { 0, 1, 3, 2 } }, { { 3, 1, 2, 0 }, { 0, 1, 3, 2 }, { 0, 1, 3, 2 }, { 3, 2, 0, 1 } }, { { 2, 1, 0, 3 }, { 0, 2, 1, 3 }, { 2, 3, 1, 0 }, { 0, 1, 3, 2 } }, { { 0, 1, 3, 2 }, { 0, 1, 3, 2 }, { 0, 1, 3, 2 }, { 3, 1, 2, 0 } }, { { 3, 2, 0, 1 }, { 2, 3, 1, 0 }, { 1, 3, 0, 2 }, { 0, 1, 3, 2 } }, { { 1, 0, 2, 3 }, { 3, 1, 2, 0 }, { 0, 2, 1, 3 }, { 0, 2, 1, 3 } } }; static const int closedNorHypAdj[11][4] = { { 8, 2, 8, 2 }, { 5, 3, 2, 9 }, { 1, 4, 0, 0 }, { 6, 1, 4, 6 }, { 10, 2, 10, 3 }, { 7, 7, 6, 1 }, { 8, 3, 3, 5 }, { 5, 9, 8, 5 }, { 0, 0, 6, 7 }, { 10, 10, 1, 7 }, { 9, 4, 4, 9 } }; static const int closedNorHypGluings[11][4][4] = { { { 1, 3, 2, 0 }, { 0, 3, 2, 1 }, { 2, 1, 0, 3 }, { 3, 1, 0, 2 } }, { { 3, 0, 1, 2 }, { 3, 1, 0, 2 }, { 2, 1, 0, 3 }, { 1, 0, 3, 2 } }, { { 2, 1, 0, 3 }, { 3, 1, 2, 0 }, { 2, 1, 3, 0 }, { 0, 3, 2, 1 } }, { { 2, 1, 3, 0 }, { 2, 1, 3, 0 }, { 2, 0, 3, 1 }, { 0, 3, 2, 1 } }, { { 2, 1, 0, 3 }, { 3, 1, 2, 0 }, { 3, 2, 1, 0 }, { 1, 3, 0, 2 } }, { { 3, 1, 2, 0 }, { 1, 0, 3, 2 }, { 0, 1, 3, 2 }, { 1, 2, 3, 0 } }, { { 2, 1, 0, 3 }, { 0, 3, 2, 1 }, { 3, 1, 0, 2 }, { 0, 1, 3, 2 } }, { { 1, 0, 3, 2 }, { 0, 3, 2, 1 }, { 0, 1, 3, 2 }, { 3, 1, 2, 0 } }, { { 2, 1, 0, 3 }, { 3, 0, 2, 1 }, { 2, 1, 0, 3 }, { 0, 1, 3, 2 } }, { { 3, 1, 2, 0 }, { 2, 0, 1, 3 }, { 1, 0, 3, 2 }, { 0, 3, 2, 1 } }, { { 1, 2, 0, 3 }, { 3, 2, 1, 0 }, { 2, 1, 0, 3 }, { 3, 1, 2, 0 } } }; static const int whiteheadAdj[4][4] = { { 3, 2, 1, 3}, { 3, 2, 2, 0}, { 1, 3, 0, 1}, { 2, 0, 0, 1} }; static const int whiteheadGluings[4][4][4] = { { { 2, 3, 1, 0 }, { 3, 2, 0, 1 }, { 0, 1, 3, 2 }, { 3, 2, 0, 1 } }, { { 3, 2, 0, 1 }, { 2, 3, 1, 0 }, { 3, 2, 0, 1 }, { 0, 1, 3, 2 } }, { { 2, 3, 1, 0 }, { 1, 0, 2, 3 }, { 2, 3, 1, 0 }, { 3, 2, 0, 1 } }, { { 1, 0, 2, 3 }, { 2, 3, 1, 0 }, { 3, 2, 0, 1 }, { 2, 3, 1, 0 } } }; } namespace regina { NTriangulation* NExampleTriangulation::threeSphere() { NTriangulation* ans = new NTriangulation(); ans->setPacketLabel("3-sphere"); ans->insertLayeredLensSpace(1, 0); return ans; } NTriangulation* NExampleTriangulation::bingsHouse() { NTriangulation* ans = new NTriangulation(); ans->setPacketLabel("Bing's house with two rooms"); NTetrahedron* r = ans->newTetrahedron(); NTetrahedron* s = ans->newTetrahedron(); r->joinTo(0, r, NPerm4(0, 1)); s->joinTo(0, s, NPerm4(0, 1)); r->joinTo(2, s, NPerm4(3, 1, 2, 0)); s->joinTo(3, r, NPerm4(2, 1, 0, 3)); return ans; } NTriangulation* NExampleTriangulation::s2xs1() { NTriangulation* ans = new NTriangulation(); ans->setPacketLabel("S2 x S1"); ans->insertLayeredLensSpace(0, 1); return ans; } NTriangulation* NExampleTriangulation::rp2xs1() { // Section 3.5.1 of Benjamin Burton's PhD thesis describes how to // construct RP^2 x S^1 by identifying the boundary triangles of a // solid Klein bottle. NTriangulation* ans = solidKleinBottle(); ans->setPacketLabel("RP2 x S1"); NTetrahedron* r = ans->getTetrahedron(0); NTetrahedron* t = ans->getTetrahedron(2); r->joinTo(1, t, NPerm4(2, 3, 0, 1)); r->joinTo(3, t, NPerm4(2, 3, 0, 1)); return ans; } NTriangulation* NExampleTriangulation::rp3rp3() { // This can be generated as the enclosing triangulation of a splitting // surface, as described in chapter 4 of Benjamin Burton's PhD thesis. NSignature* sig = NSignature::parse("aabccd.b.d"); NTriangulation* ans = sig->triangulate(); ans->setPacketLabel("RP3 # RP3"); delete sig; return ans; } NTriangulation* NExampleTriangulation::lens8_3() { NTriangulation* ans = new NTriangulation(); ans->setPacketLabel("L(8,3)"); ans->insertLayeredLensSpace(8, 3); return ans; } NTriangulation* NExampleTriangulation::poincareHomologySphere() { NTriangulation* ans = new NTriangulation(); ans->setPacketLabel("Poincar\u00E9 homology sphere"); ans->insertConstruction(5, poincareAdj, poincareGluings); return ans; } NTriangulation* NExampleTriangulation::weeks() { NTriangulation* ans = new NTriangulation(); ans->setPacketLabel("Weeks manifold"); ans->insertConstruction(9, weeksAdj, weeksGluings); return ans; } NTriangulation* NExampleTriangulation::weberSeifert() { NTriangulation* ans = new NTriangulation(); ans->setPacketLabel("Weber-Seifert dodecahedral space"); // Bah. Dehydration strings are somewhat impenetrable, // but the alternative is 23 lines of hard-coded tetrahedron gluings. // // This triangulation was constructed by building a 60-tetrahedron // dodecahedron and identifying opposite pentagonal faces with a 3/10 twist, // and then simplifying down to one vertex and 23 tetrahedra. ans->insertRehydration( "xppphocgaeaaahimmnkontspmuuqrsvuwtvwwxwjjsvvcxxjjqattdwworrko"); ans->orient(); return ans; } NTriangulation* NExampleTriangulation::seifertWeber() { // Kept for backward compatibility. // Use the old name in the packet label. NTriangulation* ans = weberSeifert(); ans->setPacketLabel("Seifert-Weber dodecahedral space"); return ans; } NTriangulation* NExampleTriangulation::smallClosedOrblHyperbolic() { NTriangulation* ans = new NTriangulation(); ans->setPacketLabel("Closed orientable hyperbolic 3-manifold"); ans->insertConstruction(9, closedOrHypAdj, closedOrHypGluings); return ans; } NTriangulation* NExampleTriangulation::smallClosedNonOrblHyperbolic() { NTriangulation* ans = new NTriangulation(); ans->setPacketLabel("Closed non-orientable hyperbolic 3-manifold"); ans->insertConstruction(11, closedNorHypAdj, closedNorHypGluings); return ans; } NTriangulation* NExampleTriangulation::sphere600() { // See 600cell.py for the code that converts the Benedetti-Lutz // simplicial complex to a Regina triangulation. NTriangulation* ans = NTriangulation::fromIsoSig("-cyjvvvvvzzzvzzvvwvLLvLvPPvLvPzAPvzAMPzwLvzPvLPzwwMzvPzMzLwzMzMvALMLzvzMPwzwMALMvvMALzMPvAwvzwzMzAwvwwwwMAzMzQLMvzMPAwzzzMLPzvMzMMwwwwMzAwPMzvwzMzAwPMvAzMzAQLLvQzwwzPMvAzQMwwPzwLwPzLMAPPvQAvAMvzQLPwPAwPAMAMvPPzLMQvPzwMAwPAMwALMQwPzwPQwPAMwALMvwzQQAQzALMvMzvAMvwPAMwzvQMQvMzMzQMzzLPQzzMPzPAMMQMLzAwQAPPQPzvLPQzLzPQzLLQMzvMMPQzzPQPvLPzPPQPvzAwAPPQAzPQQLAQQAQPwvLPQPAPwvvzwvvLQMAQLLQQQQLLQQQQQLQQQQQAMMQMQAQialaoamapaqatavawazaPaBaRaCaFaTaHaVa3aIa6aLaXaNaZa7aOa+aebgbSanbWaqbrb0aubybAb2anb5aFbrb9aHbMbObabcbTbfbVbybYbObibkb4bmb6b9bpbGbtbIbecgcwbUbzbWbmcgcCb5bEb7btcycAcXbKbNbEcycZb8bQbSbLc+bPcScPcVc1b-b3bZcac4c7c4c+ccdlcccDcfcfdAcncscicKckclducScpdpcvc1crctdwc7cxdBdzcFcgdCcMcmdVcLdHcNcJcOdOc3c+cTdWdRcWcqdUc0cudKd2cYcRdcd-dbe6c-cyd9cddCdSdedbdYdaedepdLdidndkdteodwdxdTdzeKdvdsdweBd-dIeSdDdAdBeaeKeFdIdQdHdSeJdveVeNdPdTeWd4ebeVdXdWe5ede3d0d7d2dcf4dEeff6d8d0edfkf+dcegfjfiefemehetfNejewfle9eneufBfpemfqexfAfseueUezeJfIeyeAeXeKfKeDeFeFfefTfHeJehfSfMeMfOevf2fQeVfReyf1fVe4eJf5eKfZeifRf1eGfag3e6ebglf8e0fzfNf+eigafdgbfjgCfffkfTfjfSfagbgofxgWfpf4fDfrfhgsfygmgEfwfBf2fAf1figjgxgygNgIfLfOgUfVgPfQgQfWg3fNgOg4gYfUgZf5gZg5fVgWg4g5g7f8fcgPg+fch-fkgXgPgfgkhdhggfhlglhXgkhlhogpgtg0grgthsgzg6g0gvgwhAguhwgnh6gnhCgDgHg8gFgGgEhLgah8gJgMgHhKgFhshahshSgQhehTgghYgRhQhRh2gxh7gvh3gThTh+gbhIh-gGhYhYh9h+h9h+hihyhjhzhmh-h-hphqhJhrhKhbibilimilimininiBhChLhDhMhpipiviwiviwixixiziziOhZhPh0hShdiaiaiVhWh5hXh6hiicicirioioi2h3h7h4h8htiqiqiBiyiyiDiAiAirifigijihikisisiuiBiCiCiEiDiEiGiHiJiIiKiLiLiMiNiNiOiOiQiRiTiSiUiWiViVihjYiXiXiijYi0i1i3i2i4i6i5i5ijj8i7i7ikjnj8ioj+ibj-icjajejdjdjljgjfjfjmjpjgjqjrjsjijkjtjmjujvjojtjqjujwjsjvjwjxjxjxjgovcfbcfboivlbgmvpifdgtoulcepdbifdlcepdbavpaoupdfvlgtalacoigmivnospdvkgwlaojgripdsfgtarncgmwleauckoisidaplsfbgtgrncbgmwouckfoisvplgwqgrxceckoisvfdloshojxhncqbdpvnhvkqhsfxqxccckoisvfflgncqbcpgsfxoxckfoistlojxbdovkqqcncbgmwupgrexdvnhhsfbgtprugdwqeoeshhojwbdovkrqcgresdvnjhgdwneoeskhbcmoigklwxpvnhngijqruoeshsffqgmxigtirmrgmwqiwccxgtqlhppvnhnuoeshsxitgmwqiwqlhpvnjpoeskuagtirmrqahpvkrlgdwntagijqrlaaojwigresmagklwxiaagtcrorqhpggjfrlagkgwciatqhpgvwgntagrosgmauhqluaojgwoiaphxipalagvwgnovggrosgvoggvoojgwovgogovogvcojgwocgfffgcbbojgwocgffgcbojgwovgologvibgrosgvogpgovmdfigvwgnovgugvotecldpbficlpvpoudgtldla"); ans->orient(); ans->setPacketLabel("600-cell"); return ans; } NTriangulation* NExampleTriangulation::lst3_4_7() { NTriangulation* ans = new NTriangulation(); ans->setPacketLabel("Layered solid torus"); ans->insertLayeredSolidTorus(3, 4); return ans; } NTriangulation* NExampleTriangulation::solidKleinBottle() { NTriangulation* ans = new NTriangulation(); ans->setPacketLabel("Solid Klein bottle"); // A three-tetrahedron solid Klein bottle is described in section // 3.5.1 of Benjamin Burton's PhD thesis. NTetrahedron* r = ans->newTetrahedron(); NTetrahedron* s = ans->newTetrahedron(); NTetrahedron* t = ans->newTetrahedron(); s->joinTo(0, r, NPerm4(0, 1, 2, 3)); s->joinTo(3, r, NPerm4(3, 0, 1, 2)); s->joinTo(1, t, NPerm4(3, 0, 1, 2)); s->joinTo(2, t, NPerm4(0, 1, 2, 3)); return ans; } NTriangulation* NExampleTriangulation::figureEightKnotComplement() { NTriangulation* ans = new NTriangulation(); ans->setPacketLabel("Figure eight knot complement"); // The two-tetrahedron figure eight knot complement is described at // the beginning of chapter 8 of Richard Rannard's PhD thesis. NTetrahedron* r = ans->newTetrahedron(); NTetrahedron* s = ans->newTetrahedron(); r->joinTo(0, s, NPerm4(1, 3, 0, 2)); r->joinTo(1, s, NPerm4(2, 0, 3, 1)); r->joinTo(2, s, NPerm4(0, 3, 2, 1)); r->joinTo(3, s, NPerm4(2, 1, 0, 3)); return ans; } NTriangulation* NExampleTriangulation::trefoilKnotComplement() { NTriangulation* ans = new NTriangulation(); ans->setPacketLabel("Trefoil knot complement"); NTetrahedron* r = ans->newTetrahedron(); NTetrahedron* s = ans->newTetrahedron(); r->joinTo(0, s, NPerm4(2, 3)); r->joinTo(1, s, NPerm4(2, 3)); r->joinTo(2, s, NPerm4(1, 3)); r->joinTo(3, s, NPerm4(0, 2)); return ans; } NTriangulation* NExampleTriangulation::whiteheadLinkComplement() { NTriangulation* ans = new NTriangulation(); ans->setPacketLabel("Whitehead link complement"); ans->insertConstruction(4, whiteheadAdj, whiteheadGluings); return ans; } NTriangulation* NExampleTriangulation::gieseking() { NTriangulation* ans = new NTriangulation(); ans->setPacketLabel("Gieseking manifold"); NTetrahedron* r = ans->newTetrahedron(); r->joinTo(0, r, NPerm4(1, 2, 0, 3)); r->joinTo(2, r, NPerm4(0, 2, 3, 1)); return ans; } NTriangulation* NExampleTriangulation::cuspedGenusTwoTorus() { NTriangulation* ans = new NTriangulation(); ans->setPacketLabel("Cusped genus two solid torus"); // We create this by first constructing an ordinary solid genus two // torus and then converting the real boundary to an ideal vertex. NTetrahedron* r = ans->newTetrahedron(); NTetrahedron* s = ans->newTetrahedron(); NTetrahedron* t = ans->newTetrahedron(); NTetrahedron* u = ans->newTetrahedron(); r->joinTo(0, s, NPerm4()); r->joinTo(1, t, NPerm4(1, 2, 3, 0)); r->joinTo(2, u, NPerm4(1, 0, 3, 2)); s->joinTo(3, t, NPerm4()); t->joinTo(1, u, NPerm4()); ans->finiteToIdeal(); return ans; } } // namespace regina regina-4.96/engine/triangulation/nexampletriangulation.h000644 000765 000024 00000025571 12377775620 023552 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file triangulation/nexampletriangulation.h * \brief Offers several example 3-manifold triangulations as starting * points for testing code or getting used to Regina. */ #ifndef __NEXAMPLETRIANGULATION_H #ifndef __DOXYGEN #define __NEXAMPLETRIANGULATION_H #endif #include "regina-core.h" namespace regina { class NTriangulation; /** * \weakgroup triangulation * @{ */ /** * This class offers routines for constructing sample 3-manifold triangulations * of various types. These triangulations may be useful for testing new * code, or for simply getting a feel for how Regina works. * * The sample triangulations offered here may prove especially useful in * Regina's scripting interface, where working with pre-existing files * is more complicated than in the GUI. * * Note that each of these routines constructs a new triangulation from * scratch. It is up to the caller of each routine to destroy the * triangulation that is returned. */ class REGINA_API NExampleTriangulation { public: /** * \name Closed Triangulations */ /*@{*/ /** * Returns a one-tetrahedron triangulation of the 3-sphere. * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static NTriangulation* threeSphere(); /** * Returns the two-tetrahedron triangulation of the 3-sphere * that is dual to Bing's house with two rooms. * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static NTriangulation* bingsHouse(); /** * Returns a two-tetrahedron triangulation of the product space * S^2 x S^1. * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static NTriangulation* s2xs1(); /** * Returns a three-tetrahedron triangulation of the non-orientable * product space RP^2 x S^1. * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static NTriangulation* rp2xs1(); /** * Returns a triangulation of the connected sum * RP^3 # RP^3. * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static NTriangulation* rp3rp3(); /** * Returns the minimal triangulation of the lens space * L(8,3). * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static NTriangulation* lens8_3(); /** * Returns the five-tetrahedron triangulation of the * Poincare homology sphere. * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static NTriangulation* poincareHomologySphere(); /** * Returns a nine-tetrahedron minimal triangulation of the Weeks * manifold. The Weeks manifold is the smallest-volume closed * hyperbolic 3-manifold, with a volume of roughly 0.9427. * Note that there are nine minimal triangulations of the Weeks * manifold (of course this routine returns just one). * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static NTriangulation* weeks(); /** * Returns a one-vertex triangulation of the Weber-Seifert * dodecahedral space. * * This 3-manifold is described in "Die beiden Dodekaederraume", * C. Weber and H. Seifert, Math. Z. 37 (1933), no. 1, 237-253. * The triangulation returned by this routine (with 23 tetrahedra) * is given in "The Weber-Seifert dodecahedral space is non-Haken", * Benjamin A. Burton, J. Hyam Rubinstein and Stephan Tillmann, * Trans. Amer. Math. Soc. 364:2 (2012), pp. 911-932. * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static NTriangulation* weberSeifert(); /** * Returns a one-vertex triangulation of the Weber-Seifert * dodecahedral space. * * \deprecated This routine is now called weberSeifert(), * for consistency with Weber and Seifert's original paper. * The old name seifertWeber() has been kept for backward * compatibility, but will be removed in a future version of Regina. * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static NTriangulation* seifertWeber(); /** * Returns the nine-tetrahedron closed orientable hyperbolic * 3-manifold with volume 0.94270736. * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static NTriangulation* smallClosedOrblHyperbolic(); /** * Returns the eleven-tetrahedron closed non-orientable hyperbolic * 3-manifold with volume 2.02988321. * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static NTriangulation* smallClosedNonOrblHyperbolic(); /** * Returns the boundary 3-sphere of the regular 600-cell. * This is a triangulation of the 3-sphere that is a simplicial * complex, and in which every edge has degree five. * * The triangulation was extracted from the Benedetti-Lutz * library of triangulations. See: * http://page.math.tu-berlin.de/~lutz/stellar/library_of_triangulations.html * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static NTriangulation* sphere600(); /*@}*/ /** * \name Finite Bounded Triangulations */ /*@{*/ /** * Returns the three-tetrahedron layered solid torus * LST(3,4,7). * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static NTriangulation* lst3_4_7(); /** * Returns a triangulation of the solid Klein bottle. * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static NTriangulation* solidKleinBottle(); /*@}*/ /** * \name Ideal Triangulations */ /*@{*/ /** * Returns a two-tetrahedron ideal triangulation of the figure * eight knot complement. * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static NTriangulation* figureEightKnotComplement(); /** * Returns a two-tetrahedron ideal triangulation of the trefoil * knot complement. * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static NTriangulation* trefoilKnotComplement(); /** * Returns a four-tetrahedron ideal triangulation of the * Whitehead link complement. * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static NTriangulation* whiteheadLinkComplement(); /** * Returns the one-tetrahedron ideal triangulation of the * non-orientable Gieseking manifold. * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static NTriangulation* gieseking(); /** * Returns a triangulation of a solid genus two torus with a * cusped boundary. This triangulation has one internal finite * vertex and one genus two ideal vertex. * * @return a newly constructed triangulation, which must be * destroyed by the caller of this routine. */ static NTriangulation* cuspedGenusTwoTorus(); /*@}*/ }; /*@}*/ } // namespace regina #endif regina-4.96/engine/triangulation/nface.h000644 000765 000024 00000005772 12377775622 020217 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file triangulation/nface.h * \brief Deprecated header. */ #warning This header is deprecated; please use ntriangle.h instead. #include "triangulation/ntriangle.h" /** * A legacy typedef provided for backward compatibility only. * * \deprecated The old NFace class has been renamed to NTriangle. * This typedef is provided for backward compatibility, and will be removed * in some future version of Regina. */ typedef NTriangle NFace; /** * A legacy typedef provided for backward compatibility only. * * \deprecated The old NFaceEmbedding class has been renamed to * NTriangleEmbedding. This typedef is provided for backward compatibility, * and will be removed in some future version of Regina. */ typedef NTriangleEmbedding NFaceEmbedding; regina-4.96/engine/triangulation/nfacepair.cpp000644 000765 000024 00000006371 12377776760 021426 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "triangulation/nfacepair.h" namespace regina { NFacePair::NFacePair(int newFirst, int newSecond) { if (newFirst < newSecond) { first_ = newFirst; second_ = newSecond; } else { first_ = newSecond; second_ = newFirst; } } NFacePair NFacePair::complement() const { if (first_ > 1) return NFacePair(0, 1); else if (first_ == 1) return (second_ == 2 ? NFacePair(0, 3) : NFacePair(0, 2)); else if (second_ == 1) return NFacePair(2, 3); else if (second_ == 2) return NFacePair(1, 3); else return NFacePair(1, 2); } void NFacePair::operator ++ (int) { if (second_ < 3) second_++; else if (first_ < 3) { first_++; if (first_ < 3) second_ = first_ + 1; } } void NFacePair::operator -- (int) { if (second_ > first_ + 1) second_--; else if (first_ > 0) { first_--; second_ = 3; } else second_ = 0; } } // namespace regina regina-4.96/engine/triangulation/nfacepair.h000644 000765 000024 00000022761 12377775623 021071 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file triangulation/nfacepair.h * \brief Deals with simple pairs of face numbers. */ #ifndef __NFACEPAIR_H #ifndef __DOXYGEN #define __NFACEPAIR_H #endif #include "regina-core.h" namespace regina { /** * \weakgroup triangulation * @{ */ /** * Represents a pair of tetrahedron face numbers. * * Note that we are not storing triangle numbers in a triangulation * skeleton, but merely face numbers 0, 1, 2 and 3 in a single * tetrahedron. Thus there are only six possible face pairs; this class * merely makes working with such pairs more convenient. * * As well as providing the six possible face pairs, there is also a * before-the-start and a past-the-end value; this (combined with the * increment operator) allows for iteration through face pairs. * * When iterating through face pairs, the ordering will be the * lexicographical ordering (0,1), (0,2), (0,3), (1,2), (1,3), (2,3). * * The before-the-start and past-the-end values are internally * represented as (0,0) and (3,3) respectively. */ class REGINA_API NFacePair { private: unsigned first_; /**< The smaller of the two faces in this pair. */ unsigned second_; /**< The larger of the two faces in this pair. */ public: /** * Creates a new face pair (0,1). */ NFacePair(); /** * Creates a new face pair from the two given face numbers. * The two given numbers need not be in any particular order. * * \pre The two given face numbers must be distinct integers * between 0 and 3 inclusive. * * @param newFirst the first face number in the new pair. * @param newSecond the second face number in the new pair. */ NFacePair(int newFirst, int newSecond); /** * Creates a new face pair that is a clone of the given pair. * * @param cloneMe the face pair to clone. */ NFacePair(const NFacePair& cloneMe); /** * Returns the smaller of the two face numbers in this pair. * * \pre This face pair is neither before-the-start or * past-the-end. * * @return the lower face number. */ unsigned lower() const; /** * Returns the larger of the two face numbers in this pair. * * \pre This face pair is neither before-the-start or * past-the-end. * * @return the upper face number. */ unsigned upper() const; /** * Determines if this face pair represents a before-the-start * value. * * @return \c true if and only if this face pair is * before-the-start. */ bool isBeforeStart() const; /** * Determines if this face pair represents a past-the-end * value. * * @return \c true if and only if this face pair is * past-the-end. */ bool isPastEnd() const; /** * Returns the complement of this face pair. The complement * is the pair containing the two faces not included in this * face pair. * * \pre This face pair is neither before-the-start nor * past-the-end. * * @return the complement of this face pair. */ NFacePair complement() const; /** * Sets this face pair to be a copy of the given pair. * * @param cloneMe the face pair to clone. * @return a reference to this face pair. */ NFacePair& operator = (const NFacePair& cloneMe); /** * Determines if this and the given face pair are equal. * * @param other the pair to compare with this. * @return \c true if and only if this and the given pair are equal. */ bool operator == (const NFacePair& other) const; /** * Determines if this is less than the given face pair. * * @param other the pair to compare with this. * @return \c true if and only if this is less than \a other. */ bool operator < (const NFacePair& other) const; /** * Determines if this is greater than the given face pair. * * @param other the pair to compare with this. * @return \c true if and only if this is greater than \a other. */ bool operator > (const NFacePair& other) const; /** * Determines if this is less than or equal to the given face pair. * * @param other the pair to compare with this. * @return \c true if and only if this is less than or * equal to \a other. */ bool operator <= (const NFacePair& other) const; /** * Determines if this is greater than or equal to the given face pair. * * @param other the pair to compare with this. * @return \c true if and only if this is greater than or * equal to \a other. */ bool operator >= (const NFacePair& other) const; /** * Increments this face pair. It will be set to the following * face pair in the lexicographical ordering, or to a * past-the-end value if there are no more face pairs. * * \ifacespython This routine is called inc(), since Python does * not support the increment operator. */ void operator ++ (int); /** * Decrements this face pair. It will be set to the previous * face pair in the lexicographical ordering, or to a * before-the-start value if there are no previous face pairs. * * \ifacespython This routine is called dec(), since Python does * not support the decrement operator. */ void operator -- (int); }; /*@}*/ // Inline functions for NFacePair inline NFacePair::NFacePair() : first_(0), second_(1) { } inline NFacePair::NFacePair(const NFacePair& cloneMe) : first_(cloneMe.first_), second_(cloneMe.second_) { } inline unsigned NFacePair::lower() const { return first_; } inline unsigned NFacePair::upper() const { return second_; } inline bool NFacePair::isBeforeStart() const { return (second_ <= 0); } inline bool NFacePair::isPastEnd() const { return (first_ >= 3); } inline NFacePair& NFacePair::operator = (const NFacePair& cloneMe) { first_ = cloneMe.first_; second_ = cloneMe.second_; return *this; } inline bool NFacePair::operator == (const NFacePair& other) const { return (first_ == other.first_ && second_ == other.second_); } inline bool NFacePair::operator < (const NFacePair& other) const { if (first_ < other.first_) return true; if (first_ > other.first_) return false; return (second_ < other.second_); } inline bool NFacePair::operator > (const NFacePair& other) const { return (other < *this); } inline bool NFacePair::operator <= (const NFacePair& other) const { if (first_ < other.first_) return true; if (first_ > other.first_) return false; return (second_ <= other.second_); } inline bool NFacePair::operator >= (const NFacePair& other) const { return (other <= *this); } } // namespace regina #endif regina-4.96/engine/triangulation/nfacetspec.h000644 000765 000024 00000004662 12377775624 021255 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file triangulation/nfacetspec.h * \brief Deprecated header. */ #warning This header is deprecated; please use generic/nfacetspec.h instead. #include "generic/nfacetspec.h" regina-4.96/engine/triangulation/ngenericisomorphism.h000644 000765 000024 00000004715 12377775625 023226 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file triangulation/ngenericisomorphism.h * \brief Deprecated header. */ #warning This header is deprecated; please use generic/ngenericisomorphism.h instead. #include "generic/ngenericisomorphism.h" regina-4.96/engine/triangulation/ngenericisomorphism.tcc000644 000765 000024 00000004731 12400001247 023507 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file triangulation/ngenericisomorphism.tcc * \brief Deprecated header. */ #warning This header is deprecated; please use generic/ngenericisomorphism-impl.h instead. #include "generic/ngenericisomorphism-impl.h" regina-4.96/engine/triangulation/nhomologicaldata.cpp000644 000765 000024 00000231374 12377776761 023007 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "maths/matrixops.h" #include "maths/nprimes.h" #include "triangulation/nhomologicaldata.h" #include #include #include #include namespace regina { void NHomologicalData::writeTextShort(std::ostream& out) const { if (mHomology0.get()) { out<<"H_0(M) = "; mHomology0->writeTextShort(out); out<<" "; } if (mHomology1.get()) { out<<"H_1(M) = "; mHomology1->writeTextShort(out); out<<" "; } if (mHomology2.get()) { out<<"H_2(M) = "; mHomology2->writeTextShort(out); out<<" "; } if (mHomology3.get()) { out<<"H_3(M) = "; mHomology3->writeTextShort(out); out<<" "; } if (bHomology0.get()) { out<<"H_0(BM) = "; bHomology0->writeTextShort(out); out<<" "; } if (bHomology1.get()) { out<<"H_1(BM) = "; bHomology1->writeTextShort(out); out<<" "; } if (bHomology2.get()) { out<<"H_2(BM) = "; bHomology2->writeTextShort(out); out<<" "; } if (bmMap0.get()) { out<<"H_0(BM) --> H_0(M) = "; bmMap0->writeTextShort(out); out<<" "; } if (bmMap1.get()) { out<<"H_1(BM) --> H_1(M) = "; bmMap1->writeTextShort(out); out<<" "; } if (bmMap2.get()) { out<<"H_2(BM) --> H_2(M) = "; bmMap2->writeTextShort(out); out<<" "; } if (dmTomMap1.get()) { out<<"PD map = "; dmTomMap1->writeTextShort(out); out<<" "; } if (torsionFormComputed) { out<<"Torsion form rank vector: "<getVertices().begin(); vit != tri->getVertices().end(); vit++) { if (!((*vit)->isIdeal())) sNIV.push_back(i); i++; } // sNIV for (NTriangulation::EdgeIterator eit = tri->getEdges().begin(); eit != tri->getEdges().end(); eit++) { for (i=0;i<2;i++) { if ((*eit)->getVertex(i)->isIdeal()) sIEOE.push_back(2*j+i); } j++; } j=0; // sIEOE for (NTriangulation::TriangleIterator fit = tri->getTriangles().begin(); fit != tri->getTriangles().end(); fit++) { for (i=0;i<3;i++) { if ((*fit)->getVertex(i)->isIdeal()) sIEEOF.push_back(3*j+i); } j++; } j=0; // sIEEOF for (NTriangulation::TetrahedronIterator tit = tri->getTetrahedra().begin(); tit != tri->getTetrahedra().end(); tit++) { for (i=0;i<4;i++) { if ((*tit)->getVertex(i)->isIdeal()) { sIEFOT.push_back(4*j+i); } } j++; } j=0;// sIEFOT for (NTriangulation::VertexIterator vit = tri->getVertices().begin(); vit != tri->getVertices().end(); vit++) // dNINBV {if ((!((*vit)->isIdeal())) && (!((*vit)->isBoundary()))) dNINBV.push_back(j); j++; } j=0; for (NTriangulation::EdgeIterator eit = tri->getEdges().begin(); eit != tri->getEdges().end(); eit++) { if (!((*eit)->isBoundary())) dNBE.push_back(j); j++; } j=0; // dNBE for (NTriangulation::TriangleIterator fit = tri->getTriangles().begin(); fit != tri->getTriangles().end(); fit++) { if (!((*fit)->isBoundary())) dNBF.push_back(j); j++; } i=0; // dNBF for (NTriangulation::VertexIterator vit = tri->getVertices().begin(); vit != tri->getVertices().end(); vit++) // sBNIV {if ( (!((*vit)->isIdeal())) && ((*vit)->isBoundary())) sBNIV.push_back(i); i++; } i=0; for (NTriangulation::EdgeIterator eit = tri->getEdges().begin(); eit != tri->getEdges().end(); eit++) // sBNIE {if ((*eit)->isBoundary()) sBNIE.push_back(i); i++; } i=0; for (NTriangulation::TriangleIterator fit = tri->getTriangles().begin(); fit != tri->getTriangles().end(); fit++) // sBNIF {if ((*fit)->isBoundary()) sBNIF.push_back(i); i++; } ccIndexingComputed = true; // standard (0..3)-cells: numStandardCells[0] = sNIV.size() + sIEOE.size(); numStandardCells[1] = tri->getNumberOfEdges() + sIEEOF.size(); numStandardCells[2] = tri->getNumberOfTriangles() + sIEFOT.size(); numStandardCells[3] = tri->getNumberOfTetrahedra(); // dual (0..3)-cells: numDualCells[0] = tri->getNumberOfTetrahedra(); numDualCells[1] = dNBF.size(); numDualCells[2] = dNBE.size(); numDualCells[3] = dNINBV.size(); // boundary (0..2)-cells: numBdryCells[0] = sBNIV.size() + sIEOE.size(); numBdryCells[1] = sBNIE.size() + sIEEOF.size(); numBdryCells[2] = sBNIF.size() + sIEFOT.size(); } void NHomologicalData::computeChainComplexes() { // Only do this if we haven't already done it. if (chainComplexesComputed) return; // Off we go... if (!ccIndexingComputed) computeccIndexing(); chainComplexesComputed = true; // need to convert this so that it does not use tri B0_.reset(new NMatrixInt(1, numDualCells[0])); B1.reset(new NMatrixInt(numDualCells[0], numDualCells[1])); B2.reset(new NMatrixInt(numDualCells[1], numDualCells[2])); B3.reset(new NMatrixInt(numDualCells[2], numDualCells[3])); B4.reset(new NMatrixInt(numDualCells[3], 1)); A0.reset(new NMatrixInt(1, numStandardCells[0])); A1.reset(new NMatrixInt(numStandardCells[0], numStandardCells[1])); A2.reset(new NMatrixInt(numStandardCells[1], numStandardCells[2])); A3.reset(new NMatrixInt(numStandardCells[2], numStandardCells[3])); A4.reset(new NMatrixInt(numStandardCells[3], 1)); H1map.reset(new NMatrixInt(numStandardCells[1], numDualCells[1])); Bd0.reset(new NMatrixInt(1, numBdryCells[0])); Bd1.reset(new NMatrixInt(numBdryCells[0], numBdryCells[1])); Bd2.reset(new NMatrixInt(numBdryCells[1], numBdryCells[2])); Bd3.reset(new NMatrixInt(numBdryCells[2], 1)); B0Incl.reset(new NMatrixInt(numStandardCells[0], numBdryCells[0])); B1Incl.reset(new NMatrixInt(numStandardCells[1], numBdryCells[1])); B2Incl.reset(new NMatrixInt(numStandardCells[2], numBdryCells[2])); long int temp; unsigned long i,j; NPerm4 p1,p2; // This fills out matrix A1 for (i=0;igetNumberOfEdges();i++) { // these are the standard edges temp=sNIV.index(tri->vertexIndex(tri->getEdge(i)->getVertex(0))); (A1->entry( ((temp==(-1)) ? (sNIV.size()+sIEOE.index(2*i)) : temp ), i))-=1; temp=sNIV.index(tri->vertexIndex(tri->getEdge(i)->getVertex(1))); (A1->entry( ((temp==(-1)) ? (sNIV.size()+sIEOE.index(2*i+1)) : temp), i))+=1; } // ok for (i=0;igetTriangle(sIEEOF[i]/3)->getEdgeMapping( (sIEEOF[i] + 1) % 3); if (p1.sign()==1) { A1->entry(sNIV.size() + sIEOE.index(2*( tri->edgeIndex((tri->getTriangle(sIEEOF[i]/3))-> getEdge(p1[2])) )+1), tri->getNumberOfEdges()+i)-=1; } else { A1->entry(sNIV.size() + sIEOE.index(2*( tri->edgeIndex((tri->getTriangle(sIEEOF[i]/3))-> getEdge(p1[2])) )) , tri->getNumberOfEdges()+i)-=1; } p1=tri->getTriangle(sIEEOF[i]/3)->getEdgeMapping( (sIEEOF[i] + 2) % 3); if (p1.sign()==1) { A1->entry(sNIV.size() + sIEOE.index(2*( tri->edgeIndex((tri->getTriangle(sIEEOF[i]/3))-> getEdge(p1[2])) )) , tri->getNumberOfEdges()+i)+=1; } else { A1->entry(sNIV.size() + sIEOE.index(2*( tri->edgeIndex((tri->getTriangle(sIEEOF[i]/3))-> getEdge(p1[2])) )+1) , tri->getNumberOfEdges()+i)+=1; } } // that handles matrix A1. // start filling out A2... for (i=0;igetNumberOfTriangles();i++) { // put boundary edges into A2.. for (j=0;j<6;j++) { // run through the 6 possible boundary edges of the triangle // the first 3 are standard, the last three are the ideal // edges (if they exist) if ( (j/3) == 0) { p1=tri->getTriangle(i)->getEdgeMapping(j % 3); A2->entry( tri->edgeIndex( tri->getTriangle(i)->getEdge(j % 3)) ,i) += ( (p1.sign()==1) ? +1 : -1 ); } else { // check triangle i vertex j % 3 is ideal if (tri->getTriangle(i)->getVertex(j % 3)->isIdeal()) A2->entry( tri->getNumberOfEdges() + sIEEOF.index((3*i) + (j % 3)), i) += 1; } } } for (i=0;igetTetrahedron( sIEFOT[i]/4 )->getTriangleMapping( (sIEFOT[i] + j) % 4); A2->entry( tri->getNumberOfEdges() + sIEEOF.index( 3*tri->triangleIndex(tri->getTetrahedron( sIEFOT[i]/4 )->getTriangle( (sIEFOT[i] + j) % 4)) + p1.preImageOf(sIEFOT[i] % 4) ) , tri->getNumberOfTriangles()+i ) += ( (p1.sign()==1 ? -1 : 1 ) ); } } // end A2 // start A3 for (i=0;igetNumberOfTetrahedra();i++) { for (j=0;j<4;j++) { // first go through standard faces 0 through 3 p1=tri->getTetrahedron(i)->getTriangleMapping(j); A3->entry( tri->triangleIndex( tri->getTetrahedron(i)->getTriangle(j) ), i) += ( (p1.sign()==1) ? 1 : -1 ); // then ideal faces 0 through 3, if they exist if (tri->getTetrahedron(i)->getVertex(j)->isIdeal()==1) { // this part is in error. A3->entry( tri->getNumberOfTriangles() + sIEFOT.index((4*i) + j), i) += 1; } } } // end A3 // start B1: for each dual edge == non-boundary triangle, // find the tetrahedra that bound it for (i=0;ientry( tri->tetrahedronIndex( tri->getTriangle(dNBF[i])->getEmbedding(1).getTetrahedron() ),i)+=1; B1->entry( tri->tetrahedronIndex( tri->getTriangle(dNBF[i])->getEmbedding(0).getTetrahedron() ),i)-=1; } // end B1 // start B2: for each dual triangle == non-boundary edge, // find dual edges it bounds == link of tetrahedra that contain it for (i=0;i& edgeque( tri->getEdge(dNBE[i])->getEmbeddings()); for (j=0;jentry( dNBF.index( tri->triangleIndex( edgeque[j].getTetrahedron()->getTriangle(p1[2]) ) ) ,i)+= ( ( edgeque[j].getTetrahedron() == edgeque[j].getTetrahedron()->getTriangle( p1[2] )->getEmbedding( 0 ).getTetrahedron() && edgeque[j].getTetrahedron()->getTriangle( p1[2] )->getEmbedding( 0 ).getTriangle() == p1[2] ) ? 1 : -1); } } // end B2 std::vector tetor; long int ind1; long int ind2; int k; NEdgeEmbedding tempe; // start B3: for each dual tetrahedron==nonboundary vertex, // find the corresp edges==non-boundary boundary triangles for (i=0;i& vtetlist( tri->getVertex(dNINBV[i])->getEmbeddings()); tetor.resize(vtetlist.size(),0); std::vector > unorientedlist; // This should be the list of unoriented tetrahedra, together // with marked vertices. // Indices into the vector are 4*tetindex + vertex no. // Values are (index into vtetlist, already oriented). unorientedlist.resize(4 * tri->getNumberOfTetrahedra()); for (j=0;jtetrahedronIndex( vtetlist[j].getTetrahedron() ) + vtetlist[j].getVertex() ] = std::make_pair(j, false); } // need to set up a local orientation for the tangent // bundle at the vertex so that we can compare with the // normal orientations of the edges incident. This normal // orientation will have the form of a sign +-1 for each // NVertexEmbedding in the list vtetlist. Our orientation convention // will be chosen so that vtetlist[0] is positively oriented, // ie: tetor[0]==1 always. tetor[0]=1; unorientedlist[ 4*tri->tetrahedronIndex( vtetlist[0].getTetrahedron()) + vtetlist[0].getVertex() ].second = true; size_t stillToOrient = vtetlist.size() - 1; while (stillToOrient > 0) for (j=0;jtetrahedronIndex( vtetlist[j].getTetrahedron() ) + vtetlist[j].getVertex(); if ( unorientedlist[ ind1 ].second ) { // this tetrahedron has been oriented check to see // if any of the adjacent // tetrahedra are unoriented, and if so, orient them. for (k=0;k<4;k++) { if (k!= (ind1 % 4)) { p1=vtetlist[j].getTetrahedron() -> adjacentGluing(k); ind2=4*tri->tetrahedronIndex( vtetlist[j].getTetrahedron() -> adjacentTetrahedron(k) ) + p1[ind1 % 4]; if (! unorientedlist[ ind2 ].second ) { // we have an adjacent unoriented tetrahedron. // we orient it. tetor[ unorientedlist[ind2].first ] = (-1)*tetor[j]*p1.sign(); unorientedlist[ ind2 ].second = true; --stillToOrient; } } } } } // now a local orientation is set up and can compute the boundary. // to do this, it seems best to compile a list of incident edges // which contains their endpoint data and sign. // the list will be a std::set edge_adjacency, // data will be stored as // 4*(edge index) + 2*(endpt index) + sign stored as 0 or 1. std::set edge_adjacency; for (j=0;jgetEdgeMapping(k). preImageOf( vtetlist[j].getVertex() ); if ( ind2<2 ) { // edge k of tetrahedron j, moreover we know that // the vertex of the edge corresponds to ind2 tempe=NEdgeEmbedding( vtetlist[j].getTetrahedron(), k ); // the corresp orientation coming from our local // orientation // plus orienting the edge out of vertex k % 2... p1=tempe.getVertices(); if ( ind2 == 1 ) p1=p1*(NPerm4(0,1)); // now p1 sends 0 to point corresp to v, 1 to point // corresp to end of edge. // if p1.sign() == tetor[j] then sign = +1 otherwise -1. ind1=4*tri->edgeIndex( vtetlist[j].getTetrahedron()->getEdge(k) ) + 2*ind2 + (p1.sign() == tetor[j] ? 1 : 0); // Insertion in std::set is harmless if the key // already exists. edge_adjacency.insert(ind1); } } std::set::const_iterator it; for (it = edge_adjacency.begin(); it != edge_adjacency.end(); ++it) { B3->entry( dNBE.index((*it)/4) , i) += ( ( ((*it) % 2)==0 ) ? 1 : -1 ); } } // end B3 // proceed to fill out H1map // the algorithm will proceed in 2 steps. // step 1) fix once and for all a map from dual 0-cells to regular // 0-cells, the only condition this map needs to satisfy is that the // regular 0-cell associated to a dual 0-cell must be contained in // the same ideal simplex. std::vector zeroCellMap(tri->getNumberOfTetrahedra()); // zeroCellMap[i] describes the vertex of tetrahedra[i] that the dual // 0-cell is sent to. It will be stored as // 4*(vertex number 0,1,2,3) + 0,1,2,3 (equal to prev. number if // non-ideal for (i=0; igetTetrahedron(i)->getVertex(j)->isIdeal()) j++; if (j<4) zeroCellMap[i]=4*j+j; else zeroCellMap[i]=1; } // step 2) fill out the matrix. each dual 1-cell corresponds to a // triangular face of the ideal triangulation. the map of 0-cells has // already been chosen so for the map of 1-cells simply choose any path // from the first 0-cell to the 2nd 0-cell with the condition that // the path stays inside the two ideal simplicies and only crosses // the triangle corresponding to the dual 1-cell once. (and no other // triangles). for (j=0; jcolumns(); j++) // H1map.columns()==dNBF.size() // while H1map.rows() is edges.size()+sIEEOF.size() { // now we have to decide where dual edge j == ideal triangulation // triangle j is sent. unsigned tet0TriIndex = tri->getTriangle(dNBF[j])-> getEmbedding(0).getTriangle(); unsigned tet1TriIndex = tri->getTriangle(dNBF[j])-> getEmbedding(1).getTriangle(); unsigned vert0Num = zeroCellMap[tri->tetrahedronIndex( tri->getTriangle(dNBF[j]) -> getEmbedding(0).getTetrahedron() )]/4; // vertex number of start vertex in tet0 unsigned vert1Num = zeroCellMap[tri->tetrahedronIndex( tri->getTriangle(dNBF[j]) -> getEmbedding(1).getTetrahedron() )]/4; // vertex number of end vertex in tet1. unsigned vert0id = zeroCellMap[tri->tetrahedronIndex( tri->getTriangle(dNBF[j]) -> getEmbedding(0).getTetrahedron() )]%4; // not equal to vert0Num if and only if vert0 is ideal. unsigned vert1id = zeroCellMap[tri->tetrahedronIndex( tri->getTriangle(dNBF[j]) -> getEmbedding(1).getTetrahedron() )]%4; // not equal to vert1Num if and only if vert1 is ideal. NPerm4 P1 = tri->getTriangle(dNBF[j])->getEmbedding(0).getVertices(); NPerm4 P2 = tri->getTriangle(dNBF[j])->getEmbedding(1).getVertices(); NPerm4 P3; // the permutation from the start simplex vertices // to the end simplex. bool stage0nec = false; unsigned long stage0edgeNum = 0; bool stage0posOr = false; unsigned stage0choice = 0; // this indicates the vertex of the simplex // that our chosen edge // with its induced orientation ends... if (vert0Num == tet0TriIndex) // stage 0 { stage0nec = true; if (vert0Num == vert0id) { stage0choice = (tet0TriIndex + 1) % 4; } // not ideal else { stage0choice = vert0id; } // ideal stage0edgeNum = tri->edgeIndex(tri->getTriangle(dNBF[j]) -> getEmbedding(0).getTetrahedron() -> getEdge( NEdge::edgeNumber[vert0Num][stage0choice] )); stage0posOr = ( static_cast(tri->getTriangle(dNBF[j]) -> getEmbedding(0).getTetrahedron()->getEdgeMapping( NEdge::edgeNumber[vert0Num][stage0choice])[1]) == stage0choice) ? true : false ; } bool stage4nec = false; // stage 4 unsigned long stage4edgeNum = 0; bool stage4posOr = false; unsigned stage4choice = 0; if (vert1Num == tet1TriIndex) { stage4nec = true; if (vert1Num == vert1id) // the non-ideal case. { stage4choice = (tet1TriIndex + 1) % 4; } // duh, this is all wrong. else { stage4choice = vert1id; } stage4edgeNum = tri->edgeIndex(tri->getTriangle(dNBF[j]) -> getEmbedding(1).getTetrahedron() -> getEdge( NEdge::edgeNumber[vert1Num][stage4choice] )); stage4posOr = ( static_cast(tri->getTriangle(dNBF[j]) -> getEmbedding(1).getTetrahedron()->getEdgeMapping( NEdge::edgeNumber[vert1Num][stage4choice])[1]) == vert1Num ) ? true : false ; } // decide if stages 1 and 3 are neccessary... bool stage1nec = false; // stage 1 unsigned stage1v = 0; unsigned stage1vi = 0; unsigned long stage1edgeNum = 0; bool stage1posOr = false; unsigned stage1TriToUse = 0; if (stage0nec && tri->getTriangle(dNBF[j]) -> getEmbedding(0).getTetrahedron() -> getVertex(stage0choice)->isIdeal() ) { stage1v = stage0choice; stage1vi = vert0Num; stage1nec=true; } else if ((!stage0nec) && (vert0Num != vert0id) && (vert0id == tet0TriIndex)) { stage1v = vert0Num; stage1vi = vert0id; stage1nec = true; } if (stage1nec) { // we need to decide which triangle to use... stage1TriToUse = tri->getTriangle(dNBF[j]) -> getEmbedding(0).getTetrahedron()->getEdgeMapping( NEdge::edgeNumber[stage1v][tet0TriIndex] )[2]; P3 = tri->getTriangle(dNBF[j])->getEmbedding(0).getTetrahedron()-> getTriangleMapping(stage1TriToUse); stage1edgeNum = tri->getNumberOfEdges() + sIEEOF.index( 3*(tri->triangleIndex(tri->getTriangle(dNBF[j]) -> getEmbedding(0).getTetrahedron() -> getTriangle(stage1TriToUse))) + P3.preImageOf(stage1v) ); stage1posOr = ( ( static_cast( P3[(P3.preImageOf(stage1v)+1) % 3]) != stage1vi ) ? true : false ); } bool stage3nec = false; unsigned stage3v = 0; unsigned stage3vi = 0; unsigned long stage3edgeNum = 0; bool stage3posOr = false; unsigned stage3TriToUse = 0; if (stage4nec && tri->getTriangle(dNBF[j]) -> getEmbedding(1).getTetrahedron() -> getVertex(stage4choice)->isIdeal() ) { // ideal case stage3v = stage4choice; stage3vi = vert1Num; stage3nec=true; } else if ((!stage4nec) && (vert1Num != vert1id) && (vert1id == tet1TriIndex)) { // non-ideal case stage3v = vert1Num; stage3vi = vert1id; stage3nec = true; } if (stage3nec) { // we need to decide which triangle to use... stage3TriToUse = tri->getTriangle(dNBF[j]) -> getEmbedding(1).getTetrahedron()->getEdgeMapping( NEdge::edgeNumber[stage3v][tet1TriIndex] )[2]; P3 = tri->getTriangle(dNBF[j])->getEmbedding(1).getTetrahedron()-> getTriangleMapping(stage3TriToUse); stage3edgeNum = tri->getNumberOfEdges() + sIEEOF.index( 3*(tri->triangleIndex(tri->getTriangle(dNBF[j]) -> getEmbedding(1).getTetrahedron() -> getTriangle(stage3TriToUse))) + P3.preImageOf(stage3v) ); stage3posOr = ( ( static_cast( P3[(P3.preImageOf(stage3v)+1) % 3]) == stage3vi ) ? true : false ); } unsigned stage2startdata = 0; unsigned stage2enddata = 0; // 3*vertex number(0,1,2) + another vertex number (0,1,2) // these are the same indicates the vertex is non-ideal // these are different indicates the vertex is ideal and dir // of relevant point.. if (stage1nec) // set up stage2startdata { stage2startdata = 3*P1.preImageOf( stage1v ) + P1.preImageOf((tri->getTriangle(dNBF[j]) -> getEmbedding(0).getTetrahedron() -> getEdgeMapping( NEdge::edgeNumber[stage1v][stage1vi] ))[3] ); } else { // we have to deal with 2 possibilities a) stage 0 was called // and it jumped here, so it is not an ideal vertex. // b) neither stage 0 or 1 was called and this may or may // not be an ideal vertex if (stage0nec) { // this is the non-ideal situation stage2startdata = 3*P1.preImageOf( stage0choice ) + ((P1.preImageOf( stage0choice )+1) % 3); } else { // this is the starting point... back to using vert0 info... if (vert0Num != vert0id) stage2startdata = 3*P1.preImageOf( vert0Num ) + P1.preImageOf( vert0id ); else stage2startdata = 3*P1.preImageOf( vert0Num ) + ((P1.preImageOf( vert0Num ) + 1) % 3); } } if (stage3nec) // set up stage2enddata { stage2enddata = 3*P2.preImageOf( stage3v ) + P2.preImageOf((tri->getTriangle(dNBF[j]) -> getEmbedding(1).getTetrahedron() -> getEdgeMapping( NEdge::edgeNumber[stage3v][stage3vi] ))[3] ); } else { if (stage4nec) { // this is the non-ideal situation stage2enddata = 3*P2.preImageOf( stage4choice ) + ((P2.preImageOf( stage4choice ) + 1) % 3); } else { // this is the starting point... back to using vert1 info... if (vert1Num != vert1id) stage2enddata = 3*P2.preImageOf( vert1Num ) + P2.preImageOf( vert1id ); else stage2enddata = 3*P2.preImageOf( vert1Num ) + ((P2.preImageOf( vert1Num ) + 1) % 3); } } // now cycle through pairs of adjacent vertices on the triangle // and check to see if the corresponding edge is required... unsigned currV = stage2startdata; unsigned prevV = stage2startdata; if (stage2startdata != stage2enddata) while (currV != stage2enddata) { // first, increment currV -- this is a number from the // set { 1, 2, 3, 5, 6, 7 } describing an ideal vertex // of the triangle is triadic 3*vert num + direction... switch (currV) { case 1: currV = 3; break; case 2: currV = 1; break; case 3: currV=5; break; case 5: currV = 7; break; case 6: currV = 2; break; case 7: currV=6; break; } // main alg here. if (( currV/3 == prevV/3 ) && (tri->getTriangle(dNBF[j])-> getVertex(currV/3)->isIdeal()) ) // ideal edge { H1map->entry( tri->getNumberOfEdges() + sIEEOF.index(3*dNBF[j] + (currV/3)) , j ) += 1; } if ( currV/3 != prevV/3 ) // regular edge { H1map->entry(tri->edgeIndex(tri->getTriangle(dNBF[j])->getEdge(((currV/3) + 1) % 3 )), j) += ( ( static_cast( tri->getTriangle(dNBF[j])->getEdgeMapping(((currV/3) + 1) % 3)[1] ) == currV/3 ) ? +1 : -1 ); } // move prevV to be equal to currV. prevV = currV; } // now we fill out the matrix. if (stage0nec) H1map->entry( stage0edgeNum, j ) += ( stage0posOr ? 1 : -1 ); if (stage1nec) H1map->entry( stage1edgeNum, j ) += ( stage1posOr ? 1 : -1 ); if (stage3nec) H1map->entry( stage3edgeNum, j ) += ( stage3posOr ? 1 : -1 ); if (stage4nec) H1map->entry( stage4edgeNum, j ) += ( stage4posOr ? 1 : -1 ); } // This fills out matrix Bd1: rows==sBNIV.size()+sIEOE.size(), // cols==sBNIE.size()+sIEEOF.size() for (i=0;ivertexIndex(tri->getEdge(sBNIE[i])-> getVertex(0))); (Bd1->entry( ((temp==(-1)) ? (sBNIV.size()+2*i) : temp ), i))-=1; temp=sBNIV.index(tri->vertexIndex(tri->getEdge(sBNIE[i])-> getVertex(1))); (Bd1->entry( ((temp==(-1)) ? (sBNIV.size()+2*i+1) : temp), i))+=1; } // ok for (i=0;igetTriangle(sIEEOF[i]/3)->getEdgeMapping( (sIEEOF[i] + 1) % 3); if (p1.sign()==1) { Bd1->entry(sBNIV.size() + sIEOE.index(2*( tri->edgeIndex((tri->getTriangle(sIEEOF[i]/3))-> getEdge(p1[2])) )+1), sBNIE.size()+i)-=1; } else { Bd1->entry(sBNIV.size() + sIEOE.index(2*( tri->edgeIndex((tri->getTriangle(sIEEOF[i]/3))-> getEdge(p1[2])) )) , sBNIE.size()+i)-=1; } p1=tri->getTriangle(sIEEOF[i]/3)->getEdgeMapping( (sIEEOF[i] + 2) % 3); if (p1.sign()==1) { Bd1->entry(sBNIV.size() + sIEOE.index(2*( tri->edgeIndex((tri->getTriangle(sIEEOF[i]/3))-> getEdge(p1[2])) )) , sBNIE.size()+i)+=1; } else { Bd1->entry(sBNIV.size() + sIEOE.index(2*( tri->edgeIndex((tri->getTriangle(sIEEOF[i]/3))-> getEdge(p1[2])) )+1) , sBNIE.size()+i)+=1; } } // that handles matrix Bd1. // start filling out Bd2: rows==sBNIE.size()+sIEEOF.size(), // cols==sBNIF.size()+sIEFOT.size() for (i=0;igetTriangle(sBNIF[i])->getEdgeMapping(j % 3); Bd2->entry( sBNIE.index( tri->edgeIndex(tri->getTriangle( sBNIF[i])->getEdge(j % 3)) ) ,i) += ( (p1.sign()==1) ? +1 : -1 ); } else { // check triangle i vertex j % 3 is ideal if (tri->getTriangle(sBNIF[i])->getVertex(j % 3)->isIdeal()) Bd2->entry( sBNIF.size() + sIEEOF.index( (3*i) + (j % 3)), i) += 1; } } } for (i=0;igetTetrahedron( sIEFOT[i]/4 )->getTriangleMapping( (sIEFOT[i] + j) % 4); Bd2->entry( sBNIE.size() + sIEEOF.index(3*tri->triangleIndex( tri->getTetrahedron(sIEFOT[i]/4 )->getTriangle( (sIEFOT[i] + j) % 4)) + p1.preImageOf(sIEFOT[i] % 4) ) , sBNIF.size()+i ) += ( (p1.sign()==1 ? -1 : 1 ) ); } } // end Bd2 // fill out b0Incl // boundary 0-cells: for (i=0;icolumns();i++) B0Incl->entry( ( ( i < sBNIV.size()) ? sNIV.index(sBNIV[i]) : sNIV.size() + i - sBNIV.size() ) ,i)+=1; // fill out b1Incl for (i=0;icolumns();i++) // each boundary edge corresponds to a triangulation edge B1Incl->entry( ( ( i < sBNIE.size() ) ? sBNIE[i] : tri->getNumberOfEdges() + i - sBNIE.size() ) ,i)+=1; // fill out b2Incl for (i=0;icolumns();i++) B2Incl->entry( ( ( i < sBNIF.size() ) ? sBNIF[i] : tri->getNumberOfTriangles() + i - sBNIF.size() ) ,i)+=1; } const NMarkedAbelianGroup& NHomologicalData::getHomology(unsigned q) { if (q==0) { if (!mHomology0.get()) { computeChainComplexes(); mHomology0.reset(new NMarkedAbelianGroup(*A0,*A1)); } return *mHomology0; } else if (q==1) { if (!mHomology1.get()) { computeChainComplexes(); mHomology1.reset(new NMarkedAbelianGroup(*A1,*A2)); } return *mHomology1; } else if (q==2) { if (!mHomology2.get()) { computeChainComplexes(); mHomology2.reset(new NMarkedAbelianGroup(*A2,*A3)); } return *mHomology2; } else { // Assume q == 3. This will at least avoid a crash if q lies // outside the required range. if (!mHomology3.get()) { computeChainComplexes(); mHomology3.reset(new NMarkedAbelianGroup(*A3,*A4)); } return *mHomology3; } // the A's should probably be redone as an array of pointers... } const NMarkedAbelianGroup& NHomologicalData::getBdryHomology(unsigned q) { if (q==0) { if (!bHomology0.get()) { computeChainComplexes(); bHomology0.reset(new NMarkedAbelianGroup(*Bd0,*Bd1)); } return *bHomology0; } else if (q==1) { if (!bHomology1.get()) { computeChainComplexes(); bHomology1.reset(new NMarkedAbelianGroup(*Bd1,*Bd2)); } return *bHomology1; } else { // Assume q == 2. This will at least avoid a crash if q lies // outside the required range. if (!bHomology2.get()) { computeChainComplexes(); bHomology2.reset(new NMarkedAbelianGroup(*Bd2,*Bd3)); } return *bHomology2; } } const NMarkedAbelianGroup& NHomologicalData::getDualHomology(unsigned q) { if (q==0) { if (!dmHomology0.get()) { computeChainComplexes(); dmHomology0.reset(new NMarkedAbelianGroup(*B0_,*B1)); } return *dmHomology0; } else if (q==1) { if (!dmHomology1.get()) { computeChainComplexes(); dmHomology1.reset(new NMarkedAbelianGroup(*B1,*B2)); } return *dmHomology1; } else if (q==2) { if (!dmHomology2.get()) { computeChainComplexes(); dmHomology2.reset(new NMarkedAbelianGroup(*B2,*B3)); } return *dmHomology2; } else { // Assume q == 3. This will at least avoid a crash if q lies // outside the required range. if (!dmHomology3.get()) { computeChainComplexes(); dmHomology3.reset(new NMarkedAbelianGroup(*B3,*B4)); } return *dmHomology3; } } void NHomologicalData::computeHomology() { computeChainComplexes(); if (!mHomology0.get()) mHomology0.reset(new NMarkedAbelianGroup(*A0,*A1)); if (!mHomology1.get()) mHomology1.reset(new NMarkedAbelianGroup(*A1,*A2)); if (!mHomology2.get()) mHomology2.reset(new NMarkedAbelianGroup(*A2,*A3)); if (!mHomology3.get()) mHomology3.reset(new NMarkedAbelianGroup(*A3,*A4)); } void NHomologicalData::computeBHomology() { computeChainComplexes(); if (!bHomology0.get()) bHomology0.reset(new NMarkedAbelianGroup(*Bd0,*Bd1)); if (!bHomology1.get()) bHomology1.reset(new NMarkedAbelianGroup(*Bd1,*Bd2)); if (!bHomology2.get()) bHomology2.reset(new NMarkedAbelianGroup(*Bd2,*Bd3)); } void NHomologicalData::computeDHomology() { computeChainComplexes(); if (!dmHomology0.get()) dmHomology0.reset(new NMarkedAbelianGroup(*B0_,*B1)); if (!dmHomology1.get()) dmHomology1.reset(new NMarkedAbelianGroup(*B1,*B2)); if (!dmHomology2.get()) dmHomology2.reset(new NMarkedAbelianGroup(*B2,*B3)); if (!dmHomology3.get()) dmHomology3.reset(new NMarkedAbelianGroup(*B3,*B4)); } const NHomMarkedAbelianGroup& NHomologicalData::getH1CellAp() { if (!dmTomMap1.get()) { computeHomology(); computeDHomology(); dmTomMap1.reset(new NHomMarkedAbelianGroup( *dmHomology1, *mHomology1, *H1map )); } return (*dmTomMap1); } const NHomMarkedAbelianGroup& NHomologicalData::getBdryHomologyMap(unsigned q) { if (q==0) { if (!bmMap0.get()) { computeHomology(); computeBHomology(); bmMap0.reset(new NHomMarkedAbelianGroup( *bHomology0, *mHomology0, *B0Incl )); } return *bmMap0; } else if (q==1) { if (!bmMap1.get()) { computeHomology(); computeBHomology(); bmMap1.reset(new NHomMarkedAbelianGroup( *bHomology1, *mHomology1, *B1Incl )); } return *bmMap1; } else { // Assume q == 2. This will at least avoid a crash if q lies // outside the required range. if (!bmMap2.get()) { computeHomology(); computeBHomology(); bmMap2.reset(new NHomMarkedAbelianGroup( *bHomology2, *mHomology2, *B2Incl )); } return *bmMap2; } } void NHomologicalData::computeBIncl() { computeHomology(); computeBHomology(); if (!bmMap0.get()) bmMap0.reset(new NHomMarkedAbelianGroup( *bHomology0, *mHomology0, *B0Incl)); if (!bmMap1.get()) bmMap1.reset(new NHomMarkedAbelianGroup( *bHomology1, *mHomology1, *B1Incl)); if (!bmMap2.get()) bmMap2.reset(new NHomMarkedAbelianGroup( *bHomology2, *mHomology2, *B2Incl)); } void NHomologicalData::computeTorsionLinkingForm() { // Only do this if we haven't done it already. if (torsionFormComputed) return; // dual h1 --> standard h1 isomorphism: const NHomMarkedAbelianGroup& h1CellAp(getH1CellAp()); // min number of torsion gens: unsigned long niv(dmHomology1->getNumberOfInvariantFactors()); // for holding prime decompositions.: std::vector > tFac; NLargeInteger tI; // step 1: go through H1 of the manifold, take prime power decomposition // of each summand. building primePowerH1Torsion vector and // pTorsionH1Mat matrix... // also, we need to find the 2-chains bounding2c // boundary(bounding2c[i]) = orderinh1(pvList[i])*pvList[i] std::vector< NLargeInteger > tV; // temporary vector for holding dual // cc vectors. std::vector ppList; // prime power list std::vector< std::pair > pPrList; // proper prime power list. std::vector< std::vector > pvList; // list of vectors // the above two lists will have the same length. for each i, // pvList[i] will be a vector in the dual h1 homology chain complex, and // ppList[i] will be its order. unsigned long i, j, k, l; for (i=0; igetInvariantFactor(i); tFac = NPrimes::primePowerDecomp(tI); for (j=0; jgetTorsionRep(i); for (k=0; k > > // Use a list because we are continually inserting items in the middle. typedef std::vector > IndexingPowerVector; typedef std::pair IndexingPrimePair; typedef std::list IndexingList; IndexingList indexing; // indexing[i] is the i-th prime in increasing order, the first bit is // the prime, the 2nd bit is the vector list of powers, the power is an // unsigned long, and its respective index in ppList and pvList is the // 2nd bit... IndexingList::iterator it1, il1; IndexingPowerVector::iterator it2, il2; IndexingPrimePair dummyv; for (i=0; i= comparison. it1 = indexing.begin(); // now run up p until we either get to the end, or // pPrList[i].first >= it1->first il1 = indexing.end(); // the idea is that this while loop will terminate with il1 pointing // to the right insertion location. while ( it1 != indexing.end() ) { if (pPrList[i].first <= it1->first) { il1 = it1; it1 = indexing.end(); } if (it1 != indexing.end()) it1++; } // now do the same for the power... but we have to make a decision // on whether to grow the // indexing or not... we grow the indexing iff il1 == indexing.end() or // (pPrList[i].first > il1->first) if (il1 == indexing.end()) { dummyv.first = pPrList[i].first; dummyv.second.resize(1); dummyv.second[0] = std::make_pair( pPrList[i].second, i ); indexing.insert( il1, dummyv ); } else if (pPrList[i].first < il1->first) { dummyv.first = pPrList[i].first; dummyv.second.resize(1); dummyv.second[0] = std::make_pair( pPrList[i].second, i ); indexing.insert( il1, dummyv ); } else { // NOW we know this prime is already in the list, so we do // the same search for the power... it2 = il1->second.begin(); il2 = il1->second.end(); while ( it2 != il1->second.end() ) { // it2->first is the power, it2->second is the index. if (pPrList[i].second <= it2->first) { il2 = it2; it2 = il1->second.end(); } if (it2 != il1->second.end()) it2++; } il1->second.insert(il2, std::make_pair( pPrList[i].second, i )); } } // step 2: construct dual vectors // for every pvList vector, find corresponding standard vector. NMatrixInt standardBasis( numStandardCells[1], pvList.size() ); const NMatrixInt& dualtostandard(h1CellAp.getDefiningMatrix()); for (i=0; igetN()); NMatrixInt R(ON.columns(),ON.columns()); NMatrixInt Ri(ON.columns(),ON.columns()); NMatrixInt C(ON.rows(),ON.rows()); NMatrixInt Ci(ON.rows(),ON.rows()); smithNormalForm(ON, R, Ri, C, Ci); // boundingMat=R*(divide by ON diag, rescale(C*areboundariesM)) // ---- stepa ----- // ---------------- stepb --- // ----stepc---- // first I guess we need to determine rank of ON? NMatrixInt areboundariesM( standardBasis ); for (i=0; i torsionLinkingFormPresentationMat( pvList.size(), pvList.size() ); NLargeInteger tN,tD,tR; for (i=0; iorientation() is +1 or -1 depending on if the // natural orientation agrees with the manifolds one or not. // // dual orientation of triangle points into some tetrahedron // given by triangle[?]->getEmbedding(0) is an NTriangleEmbedding // triangle[]->getEmbedding(0).getTetrahedron() tet pointer // triangle[]->getEmbedding(0).getVertices() is an NPerm // // triangles[dNBF[k]] is the triangle pointer of the dual 1-cell // boundingMat is vectors in standard 2-complex so it has // the same dimension as the standard 2-cells + ideal 2-cells, // standard ones coming first. // pvList is vectors in dual 1-cells torsionLinkingFormPresentationMat.entry(i,j) += NRational( boundingMat.entry(dNBF[k],i)*pvList[j][k]* NLargeInteger( tri->getTriangle(dNBF[k])->getEmbedding(0). getTetrahedron()->orientation()* tri->getTriangle(dNBF[k])->getEmbedding(0). getVertices().sign() ), ppList[i] ); } tN=torsionLinkingFormPresentationMat.entry(i,j).getNumerator(); tD=torsionLinkingFormPresentationMat.entry(i,j).getDenominator(); tN.divisionAlg(tD,tR); tN = tR.gcd(tD); tR.divByExact(tN); tD.divByExact(tN); torsionLinkingFormPresentationMat.entry(i,j)=NRational(tR,tD); } // Compute indexing.size() just once, since for std::list this might be // a slow operation. unsigned long indexingSize = indexing.size(); h1PrimePowerDecomp.resize(indexingSize); linkingFormPD.resize(indexingSize); for (i=0, it1 = indexing.begin(); it1 != indexing.end(); i++, it1++) { h1PrimePowerDecomp[i].second.resize(it1->second.size()); h1PrimePowerDecomp[i].first = it1->first; for (j=0; jsecond.size(); j++) h1PrimePowerDecomp[i].second[j] = it1->second[j].first; linkingFormPD[i] = new NMatrixRing(it1->second.size(), it1->second.size() ); for (j=0; jsecond.size(); j++) for (k=0; ksecond.size(); k++) linkingFormPD[i]->entry(j,k) = torsionLinkingFormPresentationMat.entry( it1->second[j].second, it1->second[k].second ); } // now we should implement the classification of these forms // due to Seifert, Wall, Burger, Kawauchi, Kojima, Deloup: // this will have 3 parts, first the rank vector will be a list // n1 Z_p1^k1 + ... + nj Z_pj^kj which will be in lexicographically // increasing order: first the p?'s then the k?'s. // the 2nd part will be the 2-torsion sigma-vector: // sigma_k for k=1,2,3,... these are fractions 0/8, ..., 7/8 or infinity. // the 3rd part will be the odd p-torsion Legendre symbol data // this will be in lexicographical increasing order, first // by the prime, then by k \chi_p^k k=1,2,3,... // CLASSIFICATION // step 1: rank vectors (done) // // this will be a std::vector< std::pair< NLargeInteger, // std::vector< unsigned long > > > // rankv[i].first is the prime, and rankv[i].second is the vector which // lists the ranks // ie: if rankv[i].first==3 then rankv[i].second=(0,1,0,2,0,1) means that // there are no copies of Z_3, one copy of Z_9, no copies of Z_27 but two // copies of Z_{3^4}, etc. // std::vector< std::pair< NLargeInteger, // std::vector > > > indexing; // prime , list of (exponents, index) torRankV.resize(indexingSize); // std::vector< std::pair< NLargeInteger, // std::vector< unsigned long > > > torRankV(indexing.size()); // vector which lists the primes and the number of each power... for (i=0, it1 = indexing.begin(); it1 != indexing.end(); i++, it1++) { torRankV[i].first = it1->first; torRankV[i].second.resize( it1->second[it1->second.size()-1].first, 0); for (j=0; jsecond.size(); j++) { // indexing[i].second[j] is a pair (order, index) where the order k // indicates one copy of p^k where p==indexing[i].first. torRankV[i].second[it1->second[j].first-1]++; } } // step 2: KK 2-torsion invariant (need to implement) // *what is a smart way to implement the sigma invariant?* // I guess it should be of the form std::vector< int > // since it is only holding the reps 0,1,2,3,4,5,6,7 and inf. // inf we can represent by -1 or something? or we could use // and NLargeInteger instead. // decide on if there is 2-torsion... NLargeInteger twoPow; static const NRational pi = NRational( NLargeInteger("314159265358979323846264338327950288"), NLargeInteger("100000000000000000000000000000000000") ); std::vector< NLargeInteger > groupV; bool notatend; NRational tSum; unsigned long incind; bool incrun; long double tLD; long double xlD, ylD; std::vector< NLargeInteger > ProperPrimePower; if (h1PrimePowerDecomp.size() > 0) if (h1PrimePowerDecomp[0].first == NLargeInteger(2)) { // there is 2-torsion. now we put together the sigma vector // twoTorSigmaV // first initialize the length of twoTorSigmaV twoTorSigmaV.resize(torRankV[0].second.size()); groupV.resize(h1PrimePowerDecomp[0].second.size(), NLargeInteger("0") ); ProperPrimePower.resize( h1PrimePowerDecomp[0].second.size() ); for (i=0; i > > h1PrimePowerDecomp; // as it's easier to work with. // h1PrimePowerDecomp[0].first == 2 // so we just need to cycle through // h1PrimePowerDecomp[0].second which is an increasing list // of the powers of 2, ie: 2^i... twoPow = NLargeInteger(2); twoPow.raiseToPower(i+1); xlD=0.0; ylD=0.0; // now start the sum through the group. notatend=true; while (notatend) { // compute twoPow * pi * form(x,x), reduce mod 1 then // call doubleApprox() // first we evaluate the form(x,x) for x==groupV. // the form is linkingformPD[0] tSum=NRational::zero; for (j=0; jrows(); j++) for (k=0; kcolumns(); k++) tSum += NRational(groupV[j]*groupV[k])* linkingFormPD[0]->entry(j,k); // reduce mod 1, then turn into a long double and // evaluate cos, sin tN = tSum.getNumerator(); tD = tSum.getDenominator(); tN.divisionAlg(tD,tR); tSum = NRational(twoPow) * pi * NRational( tR, tD ); tLD = tSum.doubleApprox(); // we ignore `inrange' parameter as the number is reduced // mod 1, so either way it is // returning essentially the correct number. xlD = xlD + cos(tLD); ylD = ylD + sin(tLD); // increment the groupV incind=0; incrun=true; // tells while loop to increment at incind while (incrun) { groupV[incind] = (groupV[incind] + NLargeInteger::one) % ProperPrimePower[incind]; if (groupV[incind] == NLargeInteger::zero) { incind++; } else { incrun=false; } if ( (incind == groupV.size()) && (incrun) ) { incrun=false; notatend=false; } } } // this sum is either zero or a multiple of e^{2pi i sigma /8} // and we now we need to determine if (xlD,ylD) is 0 or // nonzero with some sigma*2pi/8 angle... if ( (xlD*xlD)+(ylD*ylD)<0.0000001 ) // this we accept as zero. { twoTorSigmaV[i] = NLargeInteger::infinity; } else { // now we need to determine the sigma angle... // since it's all integer multiples of 2pi/8, we just // need to check for // xld==0, yld<>0, yld==0, xld<>0 and xld/yld=pm1 if ( fabs(xlD) < 0.001*fabs(ylD) ) { if (ylD > 0.0) twoTorSigmaV[i]=2; else twoTorSigmaV[i]=6; } else if ( fabs(ylD) < 0.001*fabs(xlD) ) { if (xlD > 0.0) twoTorSigmaV[i]=0L; else twoTorSigmaV[i]=4; } else if (xlD/ylD > 0.0 ) { if (xlD > 0.0) twoTorSigmaV[i]=1; else twoTorSigmaV[i]=5; } else { if (xlD > 0.0) twoTorSigmaV[i]=7; else twoTorSigmaV[i]=3; } } } } // step 3: Seifert odd p-torsion legendre symbol invariant (done) // to do this I need to add a determinant to NMatrixRing class // this invariant will be expressed as a // std::vector< std::pair< NLargeInteger, std::vector< int > > > // storing the odd prime, list of Legendre symbols -1, 0, 1. // one for each quotient up to p^k where k is the largest order of // p in the torsion subgroup. unsigned long starti=0; if (torRankV.size() > 0) if (torRankV[0].first == NLargeInteger(2)) starti=1; // this ensures we skip the 2-torsion std::vector tempa; unsigned long curri; for (i=starti; i > > torRankV(indexing.size()); // starting at curri ending at torRankV[i].second[j] for (j=0; j entry(k+curri,l+curri)).getNumerator(); tempa.push_back( tempM.det().legendre(torRankV[i].first) ); // legendre symbol, compute and append to tempa // compute determinant. // increment curri curri = curri + torRankV[i].second[j]; // crashes here. } oddTorLegSymV.push_back( make_pair( torRankV[i].first , tempa) ); } // step 4: kk test for: split, hyperbolic, and the embeddability // 2^k-torsion condition. torsionLinkingFormIsSplit=true; torsionLinkingFormIsHyperbolic=true; starti=0; if (torRankV.size() > 0) if (torRankV[0].first == NLargeInteger(2)) starti=1; for (i=0; i > > h1PrimePowerDecomp; // stored as list { (2, (1, 1, 2)), (3, (1, 2, 2, 3)), (5, (1, 1, 2)) } //std::vector< NMatrixRing* > linkingFormPD; for (i=0; ientry(i,i); tN = tRat.getNumerator(); tD = tRat.getDenominator(); tN.divisionAlg(tD,tR); if (tR != NLargeInteger::zero) torsionLinkingFormSatisfiesKKtwoTorCondition=false; } } torsionRankString.assign(""); if (torRankV.size()==0) torsionRankString.append("no torsion"); else for (i=0; iisOrientable()) { torsionSigmaString.assign(""); if (twoTorSigmaV.size()==0) torsionSigmaString.append("no 2-torsion"); else for (i=0; iisOrientable()) { torsionLegendreString.assign(""); if (oddTorLegSymV.size()==0) torsionLegendreString.append("no odd p-torsion"); else for (i=0; igetNumberOfTetrahedra() == 0) { // special-case the empty triangulation embeddabilityString = "Manifold is empty."; } else if (tri->isOrientable()) { // orientable -- we need the torsion linking form computeTorsionLinkingForm(); if (getBdryHomology(0).isTrivial()) { // no boundary : orientable if (torRankV.size()==0) { // no torsion : no boundary, orientable if (tri->knowsThreeSphere() && tri->isThreeSphere()) embeddabilityString = "This manifold is S^3."; else if (getDualHomology(1).isTrivial()) embeddabilityString = "Manifold is a homology 3-sphere."; else embeddabilityString = "No information."; } // no torsion : no boundary, orientable else {// torsion : no boundary, orientable if (!torsionLinkingFormSatisfiesKKtwoTorCondition) embeddabilityString = "This manifold, once-punctured, " "does not embed in a homology 4-sphere."; else if (!torsionLinkingFormIsHyperbolic) embeddabilityString = "Does not embed in homology 4-sphere."; else embeddabilityString = "The torsion linking form is " "of hyperbolic type."; if (getDualHomology(1).getRank()==0) embeddabilityString += " Manifold is a rational " "homology sphere."; } // torsion : no boundary, orientable } // no boundary : orientable else { // boundary : orientable if (torRankV.size()==0) { // orientable with boundary, no torsion. We have no tests // so far for checking if it embeds in a homology 4-sphere // unless we implement the Kojima alexander polynomials. // H1 map check... boundary map has full rank iff embeds in // rational homology 3-sph // boundary map epic iff embeds in homology 3-sphere if (getBdryHomologyMap(1).isEpic()) { embeddabilityString = "Embeds in a homology 3-sphere as a "; if (getBdryHomology(1).getRank() == 2*getBdryHomology(0).getRank()) { if (getBdryHomology(0).getRank()==1) embeddabilityString += "knot complement."; else embeddabilityString += "link complement."; } else { if (getBdryHomology(1).getRank() == 0) embeddabilityString += "ball complement."; else embeddabilityString += "graph complement."; } } else if (getBdryHomologyMap(1).getCokernel().getRank()==0) { embeddabilityString = "Embeds in a rational homology 3-sphere as a "; if (getBdryHomology(1).getRank() == 2*getBdryHomology(0).getRank() ) { if (getBdryHomology(0).getRank()==1) embeddabilityString += "knot complement."; else embeddabilityString += "link complement."; } else { if (getBdryHomology(1).getRank() == 0) embeddabilityString += "ball complement."; else embeddabilityString += "graph complement."; } } else embeddabilityString = "Does not embed in a rational homology 3-sphere."; } // no torsion : boundary, orientable else { // torsion : boundary, orientable if (!torsionLinkingFormSatisfiesKKtwoTorCondition) { // two tor condition not satisfied if (getBdryHomologyMap(1).isEpic()) embeddabilityString = "Embeds in homology 3-sphere " "but not homology 4-sphere."; else if (getBdryHomologyMap(1).getCokernel().getRank()==0) embeddabilityString = "Embeds in rational homology 3-sphere but not " "homology 4-sphere."; else embeddabilityString = "Does not embed in homology 3-sphere, " "nor homology 4-sphere."; } else { // KK twotor condition satisfied... if (getBdryHomologyMap(1).isEpic()) embeddabilityString = "Embeds in homology 3-sphere. " "KK 2-tor condition satisfied."; else if (getBdryHomologyMap(1).getCokernel().getRank()==0) embeddabilityString = "Embeds in rational homology 3-sphere. " "KK 2-tor condition satisfied."; else embeddabilityString = "Does not embed in homology 3-sphere. " "KK 2-tor condition satisfied."; } } // torsion : boundary, orientable } // boundary : orientable } // end orientable else { // triangulation is NOT orientable, therefore can not embed // in any rational homology 3-sphere. So we look at the // orientation cover... NTriangulation orTri(*tri); orTri.makeDoubleCover(); NHomologicalData covHomol(orTri); // break up into two cases, boundary and no boundary... if (covHomol.getBdryHomology(0).isTrivial()) { // no boundary if (covHomol.formIsHyperbolic()) embeddabilityString = "Orientation cover has hyperbolic" " torsion linking form."; else embeddabilityString = "Does not embed in homology 4-sphere."; } else {// boundary if (covHomol.formSatKK()) embeddabilityString = "Orientation cover satisfies" " KK 2-torsion condition."; else embeddabilityString = "Does not embed in homology 4-sphere."; } } } // end computeEmbeddabilityString() bool NHomologicalData::formIsHyperbolic() { if (torsionFormComputed) return torsionLinkingFormIsHyperbolic; unsigned long nif=tri->getHomologyH1().getNumberOfInvariantFactors(); if (nif == 0) return true; if ((nif % 2) != 0) return false; // check invariant factors agree in pairs, if so call // computeTorsionLinkingForm for (unsigned long i=0;i<(nif/2);i++) { if (tri->getHomologyH1().getInvariantFactor(2*i) < tri->getHomologyH1().getInvariantFactor((2*i)+1)) return false; } computeTorsionLinkingForm(); return torsionLinkingFormIsHyperbolic; } } // namespace regina regina-4.96/engine/triangulation/nhomologicaldata.h000644 000765 000024 00000106662 12377775627 022455 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file triangulation/nhomologicaldata.h * \brief Deals with all the details of the cellular homology of a manifold. */ #ifndef __NHOMOLOGICALDATA_H #ifndef __DOXYGEN #define __NHOMOLOGICALDATA_H #endif #include "regina-core.h" #include "algebra/nmarkedabeliangroup.h" #include "maths/nrational.h" #include "triangulation/ntriangulation.h" #include "utilities/ptrutils.h" #include #include #include #include namespace regina { class NTriangulation; /** * \weakgroup algebra * @{ */ /** * Data type that deals with all the detailed homological information in a * manifold. This information includes: * * - the manifold's homology; * - the boundary's homology; * - the map from boundary -> manifold; * - the dual cellular homology; * - the isomorphism on H1 from the dual cellular homology to the regular * cellular homology; * - the H1 torsion form; * - the Kawauchi-Kojima invariants of torsion linking forms. * * This class takes a "least effort" approach to all computations. It * only computes what is neccessary for your requests. It also keeps a * record of all previous computations you've made. If a computation can * be sped up by not recomputing some data, it takes that short-cut. * * All these algorithms use two transverse CW decompositions of the manifold. * They correspond to the (possibly ideal) triangulation native to Regina, * and the dual polyhedral (CW) decomposition which appears in Seifert and * Threlfall's textbook. * * In the following lists we describe the canonical ordering of both the * cells and the dual cells of the given triangulation. * * First we list the cell orderings for the standard CW decomposition, * which most closely resembles the ideal triangulation. * * - \b 0-cells: The non-ideal vertices given in the order vertices.begin() * to vertices.end(), followed by the ideal endpoints of the * edges edges.begin() to edges.end() with endpoints * for each edge taken in the order 0,1. * * - \b 1-cells: edges.begin() to edges.end(), followed by the ideal edges of * faces.begin() to faces.end() in order 0,1,2. * * - \b 2-cells: faces.begin() to faces.end(), followed by the ideal faces of * tetrahedra.begin() through tetrahedra.end() in order 0,1,2,3. * * - \b 3-cells: tetrahedra.begin() through tetrahedra.end(). * * Next we list the cell orderings for the dual CW decomposition: * if the standard CW decomposition came from a morse function \a f, this * would be the one for -\a f. * * - \b 0-cells: tetrahedra.begin() through tetrahedra.end(). * * - \b 1-cells: the non-boundary faces.begin() through faces.end(). * * - \b 2-cells: the non-boundary edges.begin() through edges.end(). * * - \b 3-cells: the non-boundary, non-ideal vertices.begin() through * vertices.end(). * * \deprecated This class will be removed in Regina 5.0. A new and more * flexible class called NCellularData will take its place. * * @author Ryan Budney */ class REGINA_API NHomologicalData : public ShareableObject { private: /** * A fairly primitive class that implements sorted arrays of * unsigned integers, with logarithmic-time lookup. The interface is * extremely basic. * * This class is a placeholder, and is \emph not for long-term use. * Eventually it will (probably) be replaced with something richer, * slicker and/or more appropriate. * * \warning A precondition of using this class is that elements are * inserted in increasing order only. */ class SortedArray { private: std::vector data_; /**< The underlying array of integers. */ public: /** * Construct an empty array. */ inline SortedArray() { } /** * Return the number of elements in this array. * * @return the number of elements. */ inline size_t size() const { return data_.size(); } /** * Return the integer at the given index in this array. * * @param index the requested array index; this must be * between 0 and size()-1 inclusive. * @return the corresponding element of this array. */ inline unsigned long operator [] (size_t index) const { return data_[index]; } /** * Finds the index of the given integer in this array. * * This routine runs in logarithmic time (it uses a * binary search). * * @param value the integer to search for. * @return the array index that holds the given integer, * or -1 if the given integer is not stored in this array. */ inline ptrdiff_t index(unsigned long value) const { std::vector::const_iterator it = std::lower_bound(data_.begin(), data_.end(), value); if (it != data_.end() && *it == value) return (it - data_.begin()); else return -1; } /** * Pushes the given integer onto the end of this array. * * \pre The given integer is at least as large as every * integer currently stored in the array. * * @param value the integer to insert into this array. */ inline void push_back(unsigned long value) { data_.push_back(value); } }; /** * Stored pointer to a valid triangulation. All routines use this * triangulation as reference. * This is the triangulation that it is initialized by. */ std::auto_ptr tri; /** * Pointer to the 0-th homology group in standard cellular coordinates, * or 0 if it has not yet been computed. */ std::auto_ptr mHomology0; /** * Pointer to the 1st homology group in standard cellular coordinates, * or 0 if it has not yet been computed. */ std::auto_ptr mHomology1; /** * Pointer to the 2nd homology group in standard cellular coordinates, * or 0 if it has not yet been computed. */ std::auto_ptr mHomology2; /** * Pointer to the 3rd homology group in standard cellular coordinates, * or 0 if it has not yet been computed. */ std::auto_ptr mHomology3; /** * Pointer to the 0-th boundary homology group in standard cellular * coordinates, or 0 if it has not yet been computed. */ std::auto_ptr bHomology0; /** * Pointer to the 1st boundary homology group in standard cellular * coordinates, or 0 if it has not yet been computed. */ std::auto_ptr bHomology1; /** * Pointer to the 2nd boundary homology group in standard cellular * coordinates, or 0 if it has not yet been computed. */ std::auto_ptr bHomology2; /** * Pointer to the boundary inclusion on 0-th homology, standard * cellular coordinates, or 0 if it has not yet been computed. */ std::auto_ptr bmMap0; /** * Pointer to the boundary inclusion on 1st homology, standard * cellular coordinates, or 0 if it has not yet been computed. */ std::auto_ptr bmMap1; /** * Pointer to the boundary inclusion on 2nd homology, standard * cellular coordinates, or 0 if it has not yet been computed. */ std::auto_ptr bmMap2; /** * Pointer to the 0-th homology group in dual cellular coordinates, or * 0 if it has not yet been computed. */ std::auto_ptr dmHomology0; /** * Pointer to the 1st homology group in dual cellular coordinates, or * 0 if it has not yet been computed. */ std::auto_ptr dmHomology1; /** * Pointer to the 2nd homology group in dual cellular coordinates, or * 0 if it has not yet been computed. */ std::auto_ptr dmHomology2; /** * Pointer to the 3rd homology group in dual cellular coordinates, or * 0 if it has not yet been computed. */ std::auto_ptr dmHomology3; /** * Pointer to the cellular approx of the identity H1(M) --> H1(M) * from dual to standard cellular coordinates, or 0 if it has not yet * been computed. */ std::auto_ptr dmTomMap1; // below here and the public declaration go the internal bits of // data that are not publicly accessible... // the chain complexes for the regular cellular homology /** true if the indexing of the chain complexes is complete */ bool ccIndexingComputed; /** number of standard cells in dimension 0, 1, 2, 3. */ unsigned long numStandardCells[4]; /** number of dual cells in dimension 0, 1, 2, 3. */ unsigned long numDualCells[4]; /** number of (standard) boundary cells in dimension 0, 1, 2. */ unsigned long numBdryCells[3]; /** non-ideal vertices */ SortedArray sNIV; /** vertices which are ideal endpoints of edges */ SortedArray sIEOE; /** edges which are ideal end edges of faces */ SortedArray sIEEOF; /** faces which are ideal end faces of tetrahedra */ SortedArray sIEFOT; /** vertices which are not ideal, and nonboundary */ SortedArray dNINBV; /** interior edges ie: non-boundary edges */ SortedArray dNBE; /** non-boundary faces */ SortedArray dNBF; /** boundary, non-ideal vertices */ SortedArray sBNIV; /** boundary non-ideal edges */ SortedArray sBNIE; /** boundary non-ideal faces */ SortedArray sBNIF; /** True if the chain complexes A0,A1,A2,A3,A4, B0,B1,B2,B3,B4, ** Bd0,Bd1,Bd2,Bd3, B0Incl,B1Incl,B2Incl are computed */ bool chainComplexesComputed; /** 0th term in chain complex for cellular homology, using standard CW-complex struc */ std::auto_ptr A0; /** 1st term in chain complex for cellular homology, using standard CW-complex struc */ std::auto_ptr A1; /** 2nd term in chain complex for cellular homology, using standard CW-complex struc */ std::auto_ptr A2; /** 3rd term in chain complex for cellular homology, using standard CW-complex struc */ std::auto_ptr A3; /** 4th term in chain complex for cellular homology, using standard CW-complex struc */ std::auto_ptr A4; /** 0-th term in chain complex for dual cellular homology */ std::auto_ptr B0_; // B0 is #defined in some system headers :/ /** 1st term in chain complex for dual cellular homology */ std::auto_ptr B1; /** 2nd term in chain complex for dual cellular homology */ std::auto_ptr B2; /** 3rd term in chain complex for dual cellular homology */ std::auto_ptr B3; /** 4th term in chain complex for dual cellular homology */ std::auto_ptr B4; /** 0th term in chain complex for boundary cellular homology */ std::auto_ptr Bd0; /** 1st term in chain complex for boundary cellular homology */ std::auto_ptr Bd1; /** 2nd term in chain complex for boundary cellular homology */ std::auto_ptr Bd2; /** 3rd term in chain complex for boundary cellular homology */ std::auto_ptr Bd3; /** Chain map from C_0 boundary to C_0 manifold, standard coords */ std::auto_ptr B0Incl; /** Chain map from C_1 boundary to C_1 manifold, standard coords */ std::auto_ptr B1Incl; /** Chain map from C_2 boundary to C_2 manifold, standard coords */ std::auto_ptr B2Incl; /** Isomorphism from C_1 dual to C_1 standard */ std::auto_ptr H1map; /** Call this routine to demand the indexing of the chain complexes. */ void computeccIndexing(); /** This routine computes all the chain complexes. */ void computeChainComplexes(); /** Computes all the homology groups of the manifold using standard cells. */ void computeHomology(); /** Computes all the homology groups of the boundary using its standard cells. */ void computeBHomology(); /** Computes all the homology groups of the manifold using dual cells. This ** routine is the faster than computeHomology() but it's likely a bit ** slower than NTriangulation's homology routines. */ void computeDHomology(); /** The induced map on homology corresponding to inclusion of the boundary. */ void computeBIncl(); /** true when the torsionlinking form has been computed. */ bool torsionFormComputed; /** * This routine computes the H1 torsion linking form. It is only * well-defined for orientable 3-manifolds, so don't bother calling * this routine unless you know the manifold is orientable. * * \pre The triangulation is of a connected orientable 3-manifold. */ void computeTorsionLinkingForm(); /** * Unlike computeTorsionLinkingForm(), this routine \e can be called * for non-orientable manifolds (in which case we look at the * orientable double cover). * * \pre The triangulation is of a connected 3-manifold. */ void computeEmbeddabilityString(); /** the prime power decomposition of the torsion subgroup of H1 ** So if the invariant factors were 2,2,4,3,9,9,27,5,5, this would ** be the list: (2, (1, 1, 2)), (3, (1, 2, 2, 3)), (5, (1, 1)) */ std::vector< std::pair< NLargeInteger, std::vector > > h1PrimePowerDecomp; /** p-primary decomposition of the torsion linking form as needed to ** construct the Kawauchi-Kojima invariants. */ std::vector< NMatrixRing* > linkingFormPD; /** True if torsion linking form is `hyperbolic'. */ bool torsionLinkingFormIsHyperbolic; /** True if torsion linking form is `split' */ bool torsionLinkingFormIsSplit; /** True if torsion linking form satisfies the Kawauchi-Kojima 2-torsion ** condition */ bool torsionLinkingFormSatisfiesKKtwoTorCondition; /** 1 of 3 Kawauchi-Kojima invariants: this describes the rank of the ** torsion subgroup of H1 */ std::vector< std::pair< NLargeInteger, std::vector< unsigned long > > > torRankV; /** 2 of 3 Kawauchi-Kojima invariants: this is the sigma-invariant ** of 2-torsion. */ std::vector< NLargeInteger > twoTorSigmaV; /** 3 of 3 Kawauchi-Kojima invariants: this is the Legendre symbol ** invariant of odd torsion. */ std::vector< std::pair< NLargeInteger, std::vector< int > > > oddTorLegSymV; /** string representing torRankV */ std::string torsionRankString; /** string representing twoTorSigmaV */ std::string torsionSigmaString; /** string representing oddTorLegSymV */ std::string torsionLegendreString; /** comment on what kind of homology spheres the manifold may or may ** not embed in. */ std::string embeddabilityString; public: /** * Takes as input a triangulation. * * This class takes its own copy of the input triangulation. This * means that the input triangulation can change or even be * destroyed, and this homological data will happily continue to work * with the original triangulation as it was first passed to the * constructor. * * @param input the triangulation to use. */ NHomologicalData(const NTriangulation& input); /** * Copy constructor. * * @param h the homological data to clone. */ NHomologicalData(const NHomologicalData& h); /** * Destructor. */ virtual ~NHomologicalData(); /** * Short text representation as required by SharableObject. * * Note this only writes pre-computed data. Thus if you have * not yet asked NHomologicalData to compute anything about this * triangulation, writeTextShort may be empty. * * @param out the stream to write to. */ virtual void writeTextShort(std::ostream& out) const; /** * This routine gives access to the manifold's homology computed * with the regular CW-decomposition. * * This routine is typically slower than getDualHomology(), since * getDualHomology() uses the dual CW-decomposition which typically * has an order of magnitude fewer cells. * * Note that the groups returned by getHomology() and getDualHomology() * are isomorphic, though they are generally described by different * presentations. * * @param q the dimension of the homology group: can be 0, 1, 2 or 3. * @return the q-th homology group, computed in the standard * CW-decomposition. */ const NMarkedAbelianGroup& getHomology(unsigned q); /** * This routine gives access to the homology of the boundary * of the manifold, computed with the regular CW-decomposition. * * @param q the dimension of the homology group: can be 0, 1 or 2. * @return the q-th boundary homology group, in standard cellular * homology coordinates */ const NMarkedAbelianGroup& getBdryHomology(unsigned q); /** * This routine gives access to the homomorphism from the * homology of the boundary to the homology of the manifold. * * @param q the dimension of the map: can be 0, 1 or 2. * @return the map from H_q of the boundary to H_q of the manifold, * computed in standard coordinates. */ const NHomMarkedAbelianGroup& getBdryHomologyMap(unsigned q); /** * This routine gives access to the manifold's homology computed * with the dual CW-decomposition. * * This routine is typically faster than getHomology() since the * dual CW-decomposition generally has far fewer cells. * * Note that the groups returned by getHomology() and getDualHomology() * are isomorphic, though they are generally described by different * presentations. * * @param q the dimension of the homology group: can be 0, 1, 2 or 3. * @return the q-th homology group, computed in the dual CW-decomposition. */ const NMarkedAbelianGroup& getDualHomology(unsigned q); /** * Returns the isomorphism from getDualHomology(1) to getHomology(1) * given by a cellular approximation to the identity map on the manifold. * * @return The isomorphism from getDualHomology(1) to getHomology(1) * computed via a cellular approximation of the identity map from * the first 1-skeleton to the second. */ const NHomMarkedAbelianGroup& getH1CellAp(); /** * Returns the number of cells of the given dimension * in the standard genuine CW-decomposition of the manifold. * * In the case that the triangulation is a proper * triangulation of a manifold (or delta-complex decomposition) it * simply returns the same information as in the NTriangulation * vertex, edge, face and tetrahedron lists. * * In the case that this is an ideal triangulation, this algorithm * returns the details of the corresponding compact manifold with * boundary a union of closed surfaces. * * @param dimension the dimension of the cells in question; this must * be 0, 1, 2 or 3. * @return the number of cells of the given dimension in the standard * CW-decomposition of the closed manifold. */ unsigned long getNumStandardCells(unsigned dimension); /** * Returns the number of cells of the given dimension * in the dual CW-decomposition of the manifold. This is typically * much smaller than getNumStandardCells(). * * @param dimension the dimension of the cells in question; this must * be 0, 1, 2 or 3. * @return the number of cells of the given dimension in the dual * CW-decomposition to the triangulation. */ unsigned long getNumDualCells(unsigned dimension); /** * Returns the number of cells of the given dimension in the * standard CW-decomposition of the boundary of the manifold. * This is a subcomplex of the complex used in getNumStandardCells(). * * @param dimension the dimension of the cells in question; this must * be 0, 1 or 2. * @return the number of cells of the given dimension in the standard * CW-decomposition of the boundary. */ unsigned long getNumBdryCells(unsigned dimension); /** * The proper Euler characteristic of the manifold, computed from * the dual CW-decomposition. * * This routine calculates the Euler characteristic of the * corresponding compact triangulated 3-manifold, with each ideal * vertex treated as a surface boundary component. * * This routine returns the same value as * NTriangulation::getEulerCharManifold(), though it computes it * in a different way. * * On the other hand, this routine differs from * NTriangulation::getEulerCharTri(), which handles ideal triangulations * in a non-standard way (treating each ideal vertex as just a single * vertex). * * @return the Euler characteristic of the corresponding compact * triangulated 3-manifold. */ long getEulerChar(); /** * Returns the torsion form rank vector. This is the first of * the three Kawauchi-Kojima complete invariants of the torsion * linking form. * * This vector describes the rank of the torsion subgroup of H1, * given in prime power form. It is a vector of pairs (\a p, \a x), * where \a p is a prime and \a x is its exponent. * * For details, see "Algebraic classification of linking pairings on * 3-manifolds", Akio Kawauchi and Sadayoshi Kojima, * Math. Ann. 253 (1980), 29--42. * * \pre The triangulation is of a connected orientable 3-manifold. * * \ifacespython Not available, though the string routine * getTorsionRankVectorString() can still be used. * * @return the torsion form rank vector. */ const std::vector< std::pair< NLargeInteger, std::vector< unsigned long > > >& getTorsionRankVector(); /** * Same as getTorsionRankVector() but returns as a human-readable string. * * \pre The triangulation is of a connected orientable 3-manifold. * * @return human-readable prime power factorization of the order of * the torsion subgroup of H1. */ const std::string& getTorsionRankVectorString(); /** * Returns the 2-torsion sigma vector. This is the second of the three * Kawauchi-Kojima invariants. It is orientation-sensitive. * * For details, see "Algebraic classification of linking pairings on * 3-manifolds", Akio Kawauchi and Sadayoshi Kojima, * Math. Ann. 253 (1980), 29--42. * * \pre The triangulation is of a connected orientable 3-manifold. * * \ifacespython Not available, though the string routine * getTorsionSigmaVectorString() can still be used. * * @return the Kawauchi-Kojima sigma-vector. */ const std::vector& getTorsionSigmaVector(); /** * Same as getTorsionSigmaVector() but returns as a human-readable string. * This is an orientation-sensitive invariant. * * \pre The triangulation is of a connected orientable 3-manifold. * * @return the Kawauchi-Kojima sigma-vector in human readable form. */ const std::string& getTorsionSigmaVectorString(); /** * Returns the odd p-torsion Legendre symbol vector. This is the * last of the three Kawauchi-Kojima invariants. * * For details, see "Algebraic classification of linking pairings on * 3-manifolds", Akio Kawauchi and Sadayoshi Kojima, * Math. Ann. 253 (1980), 29--42. * * \pre The triangulation is of a connected orientable 3-manifold. * * \ifacespython Not available, though the string routine * getTorsionLegendreSymbolVectorString() can still be used. * * @return the Legendre symbol vector associated to the torsion * linking form. */ const std::vector< std::pair< NLargeInteger, std::vector< int > > >& getTorsionLegendreSymbolVector(); /** * Same as getTorsionLegendreSymbolVector() but returns as a * human-readable string. * * \pre The triangulation is of a connected orientable 3-manifold. * * @return the Legendre symbol vector in human-readable form. */ const std::string& getTorsionLegendreSymbolVectorString(); /** * Returns true iff torsion linking form is `hyperbolic' in * the linking-form sense of the word. * * To be a little more precise, Poincare-duality in a * compact orientable boundaryless manifold * gives an isomorphism between the torsion subgroup of H_1(M) * denoted tH_1(M) and Hom(tH_1(M),Q/Z), where Q is the rationals and Z the * integers. The associated bilinear form (with values in Q/Z) is said * to be `hyperbolic' if tH_1(M) splits as a direct sum A+B such * that Poincare duality sends A to Hom(B,Q/Z) and B to Hom(A,Q/Z). * * \pre The triangulation is of a connected orientable 3-manifold. * * @return \c true iff the torsion linking form is hyperbolic. */ bool formIsHyperbolic(); /** * Returns true iff the torsion linking form is split. * * \pre The triangulation is of a connected orientable 3-manifold. * * @return \c true iff the linking form is split. */ bool formIsSplit(); /** * Returns true iff the torsion linking form satisfies the * Kawauchi-Kojima 2-torsion condition. This condition * states that on all elements \a x of order 2^k, * 2^{k-1}form(x,x) = 0. * * This is a neccessary condition for an orientable 3-manifold * perhaps with boundary to embed in a homology 4-sphere. * * \pre The triangulation is of a connected orientable 3-manifold. * * @return \c true iff the form satisfies the 2-torsion * condition of Kawauchi-Kojima. */ bool formSatKK(); /** * Returns a comment on whether the manifold might embed in * a homology 3-sphere or 4-sphere. Basically, this routine runs * through all the Kawauchi-Kojima conditions, plus a * few other `elementary' conditions. * * Each comment will be formatted as one or more English sentences * (i.e., with capitalisation and punctuation). The comments * themselves are subject to change between releases of Regina, * since later releases may have more detailed tests at their disposal. * * This routine is available for both orientable and non-orientable * triangulations. In the non-orientable case it may return * additional information regarding the orientable double cover. * * \pre The triangulation is of a connected 3-manifold. * * @return a string giving a one-line description of what * is known about where this manifold embeds, based solely * on the manifold's homological data. */ const std::string& getEmbeddabilityComment(); }; /*@}*/ // Inline functions for NHomologicalData // constructor inline NHomologicalData::NHomologicalData(const NTriangulation& input): ShareableObject(), tri(new NTriangulation(input)), ccIndexingComputed(false), chainComplexesComputed(false), torsionFormComputed(false), h1PrimePowerDecomp(0), linkingFormPD(0) { std::fill(numStandardCells, numStandardCells + 4, 0); std::fill(numDualCells, numDualCells + 4, 0); std::fill(numBdryCells, numBdryCells + 3, 0); } // copy constructor inline NHomologicalData::NHomologicalData(const NHomologicalData& g) : ShareableObject(), tri(clonePtr(g.tri)), mHomology0(clonePtr(g.mHomology0)), mHomology1(clonePtr(g.mHomology1)), mHomology2(clonePtr(g.mHomology2)), mHomology3(clonePtr(g.mHomology3)), bHomology0(clonePtr(g.bHomology0)), bHomology1(clonePtr(g.bHomology1)), bHomology2(clonePtr(g.bHomology2)), bmMap0(clonePtr(g.bmMap0)), bmMap1(clonePtr(g.bmMap1)), bmMap2(clonePtr(g.bmMap2)), dmHomology0(clonePtr(g.dmHomology0)), dmHomology1(clonePtr(g.dmHomology1)), dmHomology2(clonePtr(g.dmHomology2)), dmHomology3(clonePtr(g.dmHomology3)), dmTomMap1(clonePtr(g.dmTomMap1)), ccIndexingComputed(g.ccIndexingComputed), chainComplexesComputed(g.chainComplexesComputed), A0(clonePtr(g.A0)), A1(clonePtr(g.A1)), A2(clonePtr(g.A2)), A3(clonePtr(g.A3)), A4(clonePtr(g.A4)), B0_(clonePtr(g.B0_)), B1(clonePtr(g.B1)), B2(clonePtr(g.B2)), B3(clonePtr(g.B3)), B4(clonePtr(g.B4)), Bd0(clonePtr(g.Bd0)), Bd1(clonePtr(g.Bd1)), Bd2(clonePtr(g.Bd2)), Bd3(clonePtr(g.Bd3)), B0Incl(clonePtr(g.B0Incl)), B1Incl(clonePtr(g.B1Incl)), B2Incl(clonePtr(g.B2Incl)), H1map(clonePtr(g.H1map)), torsionFormComputed(g.torsionFormComputed), embeddabilityString(g.embeddabilityString) { // More complex initialisation: if (ccIndexingComputed) { // Numbers of cells, dual cells and standard boundary cells std::copy(g.numStandardCells, g.numStandardCells + 4, numStandardCells); std::copy(g.numDualCells, g.numDualCells + 4, numDualCells); std::copy(g.numBdryCells, g.numBdryCells + 3, numBdryCells); sNIV = g.sNIV; // non-ideal vertices sIEOE = g.sIEOE; // ideal endpoints of edges sIEEOF = g.sIEEOF; // ideal end edges of faces sIEFOT = g.sIEFOT; // ideal end faces of tetrahedra dNINBV = g.dNINBV; // nonideal nonboundary vertices dNBE = g.dNBE; // non-boundary edges dNBF = g.dNBF; // non-boundary faces sBNIV = g.sBNIV; // boundary non-ideal vertices sBNIE = g.sBNIE; // boundary non-ideal edges sBNIF = g.sBNIF; // boundary non-ideal faces } if (torsionFormComputed) { h1PrimePowerDecomp = g.h1PrimePowerDecomp; linkingFormPD.resize( g.linkingFormPD.size(), 0 ); for (unsigned long i=0; i (*g.linkingFormPD[i]); torsionLinkingFormIsHyperbolic = g.torsionLinkingFormIsHyperbolic; torsionLinkingFormIsSplit = g.torsionLinkingFormIsSplit; torsionLinkingFormSatisfiesKKtwoTorCondition = g.torsionLinkingFormSatisfiesKKtwoTorCondition; torRankV = g.torRankV; twoTorSigmaV = g.twoTorSigmaV; oddTorLegSymV = g.oddTorLegSymV; torsionRankString = g.torsionRankString; torsionSigmaString = g.torsionSigmaString; torsionLegendreString = g.torsionLegendreString; } } // destructor inline NHomologicalData::~NHomologicalData() { if (torsionFormComputed) { for (unsigned long i=0; i > >& NHomologicalData::getTorsionRankVector() { computeTorsionLinkingForm(); return torRankV; } inline const std::vector& NHomologicalData::getTorsionSigmaVector() { computeTorsionLinkingForm(); return twoTorSigmaV; } inline const std::vector< std::pair< NLargeInteger, std::vector< int > > >& NHomologicalData::getTorsionLegendreSymbolVector() { computeTorsionLinkingForm(); return oddTorLegSymV; } inline bool NHomologicalData::formIsSplit() { computeTorsionLinkingForm(); return torsionLinkingFormIsSplit; } inline bool NHomologicalData::formSatKK() { computeTorsionLinkingForm(); return torsionLinkingFormSatisfiesKKtwoTorCondition; } inline const std::string& NHomologicalData::getTorsionRankVectorString() { computeTorsionLinkingForm(); return torsionRankString; } inline const std::string& NHomologicalData::getTorsionSigmaVectorString() { computeTorsionLinkingForm(); return torsionSigmaString; } inline const std::string& NHomologicalData::getTorsionLegendreSymbolVectorString() { computeTorsionLinkingForm(); return torsionLegendreString; } inline const std::string& NHomologicalData::getEmbeddabilityComment() { computeEmbeddabilityString(); return embeddabilityString; } } // namespace regina #endif regina-4.96/engine/triangulation/nisomorphism.cpp000644 000765 000024 00000005751 12377776765 022233 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "generic/ngenericisomorphism-impl.h" #include "triangulation/ntriangulation.h" #include "triangulation/nisomorphism.h" namespace regina { // Instatiate all templates from the -impl.h file. template void NGenericIsomorphism<3>::writeTextShort(std::ostream&) const; template void NGenericIsomorphism<3>::writeTextLong(std::ostream&) const; template bool NGenericIsomorphism<3>::isIdentity() const; template NGenericIsomorphism<3>::NGenericIsomorphism( const NGenericIsomorphism<3>&); template NIsomorphism* NGenericIsomorphism<3>::random(unsigned); template NTriangulation* NGenericIsomorphism<3>::apply(const NTriangulation*) const; template void NGenericIsomorphism<3>::applyInPlace(NTriangulation*) const; } // namespace regina regina-4.96/engine/triangulation/nisomorphism.h000644 000765 000024 00000025727 12377775630 021673 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file triangulation/nisomorphism.h * \brief Deals with combinatorial isomorphisms of triangulations. */ #ifndef __NISOMORPHISM_H #ifndef __DOXYGEN #define __NISOMORPHISM_H #endif #include "regina-core.h" #include "shareableobject.h" #include "generic/ngenericisomorphism.h" #include "maths/nperm4.h" #include "triangulation/ntetface.h" namespace regina { class NTriangulation; /** * \weakgroup triangulation * @{ */ /** * Represents a combinatorial isomorphism from one triangulation into * another. * * In essence, a combinatorial isomorphism from triangulation T to * triangulation U is a one-to-one map from the tetrahedra of T to the * tetrahedra of U that allows relabelling of both the tetrahedra and * their faces (or equivalently, their vertices), and that preserves * gluings across adjacent tetrahedra. * * More precisely: An isomorphism consists of (i) a one-to-one map f * from the tetrahedra of T to the tetrahedra of U, and (ii) for each * tetrahedron S of T, a permutation f_S of the faces (0,1,2,3) of S, * for which the following condition holds: * * - If face k of tetrahedron S and face k' of tetrahedron S' * are identified in T, then face f_S(k) of f(S) and face f_S'(k') * of f(S') are identified in U. Moreover, their gluing is consistent * with the face/vertex permutations; that is, there is a commutative * square involving the gluing maps in T and U and the permutations * f_S and f_S'. * * Isomorphisms can be boundary complete or * boundary incomplete. A boundary complete isomorphism * satisfies the additional condition: * * - If face x is a boundary triangle of T then face f(x) is a boundary * triangle of U. * * A boundary complete isomorphism thus indicates that a copy of * triangulation T is present as an entire component (or components) of U, * whereas a boundary incomplete isomorphism represents an embedding of a * copy of triangulation T as a subcomplex of some possibly larger component * (or components) of U. * * Note that in all cases triangulation U may contain more tetrahedra * than triangulation T. * * \todo \feature Composition of isomorphisms. */ class REGINA_API NIsomorphism : public NGenericIsomorphism<3> { public: /** * Creates a new isomorphism with no initialisation. * * \ifacespython Not present. * * @param sourceTetrahedra the number of tetrahedra in the source * triangulation associated with this isomorphism; this may be zero. */ NIsomorphism(unsigned sourceTetrahedra); /** * Creates a new isomorphism identical to the given isomorphism. * * @param cloneMe the isomorphism upon which to base the new * isomorphism. */ NIsomorphism(const NIsomorphism& cloneMe); /** * Returns the number of tetrahedra in the source triangulation * associated with this isomorphism. Note that this is always * less than or equal to the number of tetrahedra in the * destination triangulation. * * This is a convenience routine specific to three dimensions, and is * identical to the dimension-agnostic routine getSourceSimplices(). * * @return the number of tetrahedra in the source triangulation. */ unsigned getSourceTetrahedra() const; /** * Determines the image of the given source tetrahedron under * this isomorphism. * * This is a convenience routine specific to three dimensions, and is * identical to the dimension-agnostic routine simpImage(). * * \ifacespython Not present, though the read-only version of * this routine is. * * @param sourceTet the index of the source tetrahedron; this must * be between 0 and getSourceSimplices()-1 inclusive. * @return a reference to the index of the destination tetrahedron * that the source tetrahedron maps to. */ int& tetImage(unsigned sourceTet); /** * Determines the image of the given source tetrahedron under * this isomorphism. * * This is a convenience routine specific to three dimensions, and is * identical to the dimension-agnostic routine simpImage(). * * @param sourceTet the index of the source tetrahedron; this must * be between 0 and getSourceSimplices()-1 inclusive. * @return the index of the destination tetrahedron * that the source tetrahedron maps to. */ int tetImage(unsigned sourceTet) const; /** * Returns a read-write reference to the permutation that is * applied to the four faces of the given source tetrahedron * under this isomorphism. * Face \a i of source tetrahedron \a sourceTet will be mapped to * face facePerm(sourceTet)[i] of tetrahedron * tetImage(sourceTet). * * This is a convenience routine specific to three dimensions, and is * identical to the dimension-agnostic routine facetPerm(). * * \ifacespython Not present, though the read-only version of this * routine is. * * @param sourceTet the index of the source tetrahedron containing * the original four faces; this must be between 0 and * getSourceSimplices()-1 inclusive. * @return a read-write reference to the permutation applied to the * four faces of the source tetrahedron. */ NPerm4& facePerm(unsigned sourceTet); /** * Determines the permutation that is applied to the four faces * of the given source tetrahedron under this isomorphism. * Face \a i of source tetrahedron \a sourceTet will be mapped to * face facePerm(sourceTet)[i] of tetrahedron * tetImage(sourceTet). * * This is a convenience routine specific to three dimensions, and is * identical to the dimension-agnostic routine facetPerm(). * * @param sourceTet the index of the source tetrahedron containing * the original four faces; this must be between 0 and * getSourceSimplices()-1 inclusive. * @return the permutation applied to the four faces of the * source tetrahedron. */ NPerm4 facePerm(unsigned sourceTet) const; }; /** * A deprecated synonym for NIsomorphism, provided for backward * compatibility only. See NIsomorphism for further details (and please * use the NIsomorphism class instead). * * \deprecated All of the functionality that NIsomorphismDirect used to * provide in old versions of Regina has now been moved into the parent class * NIsomorphism. The NIsomorphismDirect class is now an empty subclass of * NIsomorphism, provided for backward compatibility only, and should not * be used in new applications. This class will be removed from Regina * in the near future. * * \ifacespython Not present. */ class REGINA_API NIsomorphismDirect : public NIsomorphism { public: /** * Creates a new isomorphism with no initialisation. * * @param sourceTetrahedra the number of tetrahedra in the source * triangulation associated with this isomorphism; this may be zero. */ NIsomorphismDirect(unsigned sourceTetrahedra); /** * Creates a new isomorphism identical to the given isomorphism. * * @param cloneMe the isomorphism upon which to base the new * isomorphism. */ NIsomorphismDirect(const NIsomorphism& cloneMe); }; /*@}*/ // Inline functions for NIsomorphism inline NIsomorphism::NIsomorphism(unsigned sourceTetrahedra) : NGenericIsomorphism<3>(sourceTetrahedra) { } inline NIsomorphism::NIsomorphism(const NIsomorphism& cloneMe) : NGenericIsomorphism<3>(cloneMe) { } inline unsigned NIsomorphism::getSourceTetrahedra() const { return nSimplices_; } inline int& NIsomorphism::tetImage(unsigned sourceTet) { return simpImage_[sourceTet]; } inline int NIsomorphism::tetImage(unsigned sourceTet) const { return simpImage_[sourceTet]; } inline NPerm4& NIsomorphism::facePerm(unsigned sourceTet) { return facetPerm_[sourceTet]; } inline NPerm4 NIsomorphism::facePerm(unsigned sourceTet) const { return facetPerm_[sourceTet]; } // Inline functions for NIsomorphismDirect inline NIsomorphismDirect::NIsomorphismDirect(unsigned sourceTetrahedra) : NIsomorphism(sourceTetrahedra) { } inline NIsomorphismDirect::NIsomorphismDirect(const NIsomorphism& cloneMe) : NIsomorphism(cloneMe) { } } // namespace regina #endif regina-4.96/engine/triangulation/nperm.h000644 000765 000024 00000005700 12377775631 020253 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file triangulation/nperm.h * \brief A deprecated header for dealing with permutations of {0,1,2,3}. */ #ifndef __NPERM_H #ifndef __DOXYGEN #define __NPERM_H #endif #warning This header is deprecated; please use maths/nperm4.h instead. #include "maths/nperm4.h" namespace regina { /** * \weakgroup triangulation * @{ */ /** * A legacy typedef provided for backward compatibility only. * * \deprecated As of Regina 4.6.1, the class NPerm has been renamed as * NPerm4 (which has identical functionality). This NPerm typedef is * provided for backward compatibility, and will be removed in some future * version of Regina. */ typedef NPerm4 NPerm; /*@}*/ } // namespace regina #endif regina-4.96/engine/triangulation/npermit.h000644 000765 000024 00000010360 12377775633 020610 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file triangulation/npermit.h * \brief Provides utilities for iterating through permutations. */ #ifndef __NPERMIT_H #ifndef __DOXYGEN #define __NPERMIT_H #endif #include "regina-core.h" #include "maths/nperm4.h" namespace regina { /** * \weakgroup triangulation * @{ */ /** * An iterator class that runs through all 24 permutations of four * elements. * * \deprecated This class will removed in a future release of Regina, since * it is completely unnecessary. Just loop directly through the 24 elements * of NPerm4::S4. * * \ifacespython Not present. */ class REGINA_API NPermItS4 { private: int permIndex; public: /** * Creates a new iterator pointing at the first permutation. */ NPermItS4(); /** * Points this iterator at the first permutation. */ void init(); /** * Points this iterator at the next permutation after the one it * is currently pointing to. * * \pre This iterator is not past-the-end. */ void operator ++ (int); /** * Returns the permutation at which this iterator is pointing. * * \pre This iterator is not past-the-end. * * @return the permutation at which this iterator is pointing. */ const NPerm4& operator * () const; /** * Determines if this iterator is past-the-end (has run through * all possible permutations). * * @return \c true if and only if this iterator is past-the-end. */ bool done() const; }; /*@}*/ // Inline functions for NPermItS4 inline NPermItS4::NPermItS4() : permIndex(0) { } inline void NPermItS4::init() { permIndex = 0; } inline void NPermItS4::operator ++ (int) { permIndex++; } inline const NPerm4& NPermItS4::operator * () const { return NPerm4::S4[permIndex]; } inline bool NPermItS4::done() const { return (permIndex >= 24); } } // namespace regina #endif regina-4.96/engine/triangulation/ntetface.h000644 000765 000024 00000004717 12377775634 020735 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file triangulation/ntetface.h * \brief Deprecated header; please use nfacetspec.h instead. */ #ifndef __NTETFACE_H #ifndef __DOXYGEN #define __NTETFACE_H #endif #include "generic/nfacetspec.h" #endif regina-4.96/engine/triangulation/ntetrahedron.cpp000644 000765 000024 00000012015 12377776766 022171 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "triangulation/ntetrahedron.h" #include "triangulation/ntriangulation.h" namespace regina { NTetrahedron::NTetrahedron() : tri_(0) { for (int i=0; i<4; i++) tetrahedra_[i] = 0; } NTetrahedron::NTetrahedron(const std::string& desc) : description_(desc), tri_(0) { for (int i=0; i<4; i++) tetrahedra_[i] = 0; } bool NTetrahedron::hasBoundary() const { for (int i=0; i<4; i++) if (tetrahedra_[i] == 0) return true; return false; } void NTetrahedron::isolate() { for (int i=0; i<4; i++) if (tetrahedra_[i]) unjoin(i); } NTetrahedron* NTetrahedron::unjoin(int myFace) { // TODO: Make this a stack variable once we know that tri != 0 always. std::auto_ptr span(tri_ ? new NPacket::ChangeEventSpan(tri_) : 0); NTetrahedron* you = tetrahedra_[myFace]; int yourFace = tetrahedronPerm_[myFace][myFace]; assert(you); assert(you->tetrahedra_[yourFace]); you->tetrahedra_[yourFace] = 0; tetrahedra_[myFace] = 0; if (tri_) tri_->clearAllProperties(); return you; } void NTetrahedron::joinTo(int myFace, NTetrahedron* you, NPerm4 gluing) { // TODO: Make this a stack variable once we know that tri != 0 always. std::auto_ptr span(tri_ ? new NPacket::ChangeEventSpan(tri_) : you->tri_ ? new NPacket::ChangeEventSpan(you->tri_) : 0); assert((! tetrahedra_[myFace]) || (tetrahedra_[myFace] == you && tetrahedronPerm_[myFace] == gluing)); // TODO: Temporary measure while we transition from old-style to // new-style tetrahedron management. if (tri_ && ! you->tri_) tri_->addTetrahedron(you); else if (you->tri_ && ! tri_) you->tri_->addTetrahedron(this); assert(tri_ == you->tri_); tetrahedra_[myFace] = you; tetrahedronPerm_[myFace] = gluing; int yourFace = gluing[myFace]; assert((! you->tetrahedra_[yourFace]) || (you->tetrahedra_[yourFace] == this && you->tetrahedronPerm_[yourFace] == gluing.inverse())); assert(! (you == this && yourFace == myFace)); you->tetrahedra_[yourFace] = this; you->tetrahedronPerm_[yourFace] = gluing.inverse(); if (tri_) tri_->clearAllProperties(); } void NTetrahedron::writeTextLong(std::ostream& out) const { writeTextShort(out); out << std::endl; for (int i = 3; i >= 0; --i) { out << NTriangle::ordering[i].trunc3() << " -> "; if (! tetrahedra_[i]) out << "boundary"; else out << tetrahedra_[i]->markedIndex() << " (" << (tetrahedronPerm_[i] * NTriangle::ordering[i]).trunc3() << ')'; out << std::endl; } } } // namespace regina regina-4.96/engine/triangulation/ntetrahedron.h000644 000765 000024 00000110614 12377775635 021634 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file triangulation/ntetrahedron.h * \brief Deals with tetrahedra in a triangulation. */ #ifndef __NTETRAHEDRON_H #ifndef __DOXYGEN #define __NTETRAHEDRON_H #endif #include "regina-core.h" #include "shareableobject.h" #include "maths/nperm4.h" #include "utilities/nmarkedvector.h" // NOTE: More #includes follow after the class declarations. namespace regina { class NTriangle; class NEdge; class NVertex; class NComponent; class NTriangulation; /** * \weakgroup triangulation * @{ */ /** * Represents a tetrahedron in a triangulation. * * With each tetrahedron is stored various pieces of information * regarding the overall skeletal structure and component structure of * the triangulation. This skeletal information will be allocated, calculated * and deallocated by the NTriangulation object containing the * corresponding tetrahedra. * * The management of tetrahedra has changed significantly as of Regina 4.90: * * - Users no longer need to call NTriangulation::gluingsHaveChanged() * when gluing or ungluing tetrahedra. This notification is now handled * automatically, and NTriangulation::gluingsHaveChanged() now does nothing. * * - You should now create tetrahedra by calling * NTriangulation::newTetrahedron() or * NTriangulation::newTetrahedron(const std::string&), which will * automatically add the tetrahedron to the triangulation. You should * not need to call NTriangulation::addTetrahedron() at all. * * - When you remove a tetrahedron using NTriangulation::removeTetrahedron() * or NTriangulation::removeTetrahedronAt(), the tetrahedron will now be * automatically destroyed. * * - The old way of adding tetrahedra (creating an NTetrahedron and then * calling NTriangulation::addTetrahedron()) is deprecated, and will * be removed completely in the near future. In the meantime, you may * find that tetrahedra are now added to a triangulation automatically (both * NTriangulation::addTetrahedron() and NTetrahedron::joinTo() will * aggressively try to add nearby tetrahedra that do not already belong to * the current triangulation). This is to avoid tetrahedra and * triangulations being in an inconsistent state. Any redundant calls * to NTriangulation::addTetrahedron() (i.e., when the tetrahedron * already belongs to the triangulation) are harmless, and will have no * effect. * * These changes are designed to ensure that triangulations and * tetrahedra are always in a consistent state, and to make it more * difficult for users to inadvertently crash the program. */ class REGINA_API NTetrahedron : public ShareableObject, public NMarkedElement { private: NTetrahedron* tetrahedra_[4]; /**< Stores the tetrahedra glued to each face of this tetrahedron. Specifically, tetrahedra[f] represents the tetrahedron joined to triangular face \c f of this tetrahedron, or is 0 if face \c f lies on the triangulation boundary. Faces are numbered from 0 to 3 inclusive, where face \c i is opposite vertex \c i. */ NPerm4 tetrahedronPerm_[4]; /**< Stores the corresponence between vertices of this tetrahedron and adjacent tetrahedra. If face \c f is joined to another tetrahedron, tetrahedronPerm[f] represents the permutation \c p whereby vertex \c v of this tetrahedron is identified with vertex p[v] of the adjacent tetrahedron along face \c f. */ std::string description_; /**< A text description of this tetrahedron. Descriptions are not mandatory and need not be unique. */ NVertex* vertices_[4]; /**< Vertices in the triangulation skeleton that are vertices of this tetrahedron. */ NEdge* edges_[6]; /**< Edges in the triangulation skeleton that are edges of this tetrahedron. */ NTriangle* triangles_[4]; /**< Triangles in the triangulation skeleton that are faces of this tetrahedron. */ int tmpOrientation_[4]; /**< Temporary array used to represent orientations of triangles and vertex link triangles when calculating orientability of boundary components and vertex links. Each orientation will be +/-1. The array should only be used within these orientability routines, and its contents afterwards are unpredictable. */ NPerm4 vertexMapping_[4]; /**< Maps 0 to each vertex of this tetrahedron in turn whilst mapping (1,2,3) in a suitably "orientation-preserving" way, as described in getVertexMapping(). */ NPerm4 edgeMapping_[6]; /**< Maps (0,1) to the vertices of this tetrahedron that form each edge whilst mapping (2,3) in a suitably "orientation- preserving" way, as described in getEdgeMapping(). */ NPerm4 triMapping_[4]; /**< Maps (0,1,2) to the vertices of this tetrahedron that form each triangular face, as described in getTriangleMapping(). */ int tetOrientation_; /**< The orientation of this tetrahedron in the triangulation. This will either be 1 or -1. */ NTriangulation* tri_; /**< The triangulation to which this tetrahedron belongs. */ NComponent* component_; /**< The component to which this tetrahedron belongs in the triangulation. */ public: /** * Creates a new tetrahedron with empty description and no * faces joined to anything. * The new tetrahedron will not belong to any triangulation. * * \deprecated Users should now create new tetrahedra by calling * NTriangulation::newTetrahedron(). For details, see the changes in * tetrahedron management outlined in the NTetrahedron class notes. */ NTetrahedron(); /** * Creates a new tetrahedron with the given description and * no faces joined to anything. * The new tetrahedron will not belong to any triangulation. * * \deprecated Users should now create new tetrahedra by calling * NTriangulation::newTetrahedron(const std::string&). For details, * see the changes in tetrahedron management outlined in the * NTetrahedron class notes. * * @param desc the description to give the new tetrahedron. */ NTetrahedron(const std::string& desc); /** * Destroys this tetrahedron. */ virtual ~NTetrahedron(); /** * Returns the text description associated with this * tetrahedron. * * @return the description of this tetrahedron. */ const std::string& getDescription() const; /** * Sets the text description associated with this tetrahedron. * Note that descriptions need not be unique, and may be empty. * * @param desc the new description to assign to this * tetrahedron. */ void setDescription(const std::string& desc); /** * Returns the index of this tetrahedron in the underlying * triangulation. This is identical to calling * getTriangulation()->tetrahedronIndex(this). * * Note that tetrahedron indexing may change when a tetrahedron is * added or removed from the underlying triangulation. * * @return the index of this tetrahedron. */ unsigned long index() const; /** * Returns the adjacent tetrahedron glued to the given face of this * tetrahedron, or 0 if the given face is on the triangulation * boundary. * * @param face the face of this tetrahedron to examine. This * should be between 0 and 3 inclusive, where face \c i is * opposite vertex \c i of the tetrahedron. * @return the adjacent tetrahedron glued to the given face, or 0 * if the given face lies on the boundary. */ NTetrahedron* adjacentTetrahedron(int face) const; /** * A dimension-agnostic alias for adjacentTetrahedron(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "simplex" refers to a top-dimensional simplex (which for * 3-manifold triangulations means a tetrahedron). * * See adjacentTetrahedron() for further information. */ NTetrahedron* adjacentSimplex(int face) const; /** * Deprecated in favour of adjacentTetrahedron(). The old routine * getAdjacentTetrahedron() has been renamed to adjacentTetrahedron() * as part of an effort to make programming and scripting with * Regina a little less work on the fingers. * * \deprecated This routine will eventually be removed in some future * version of Regina. Users are advised to use adjacentTetrahedron() * instead, which is an identical routine with a shorter name. * * @param face the face of this tetrahedron to examine. This * should be between 0 and 3 inclusive, where face \c i is * opposite vertex \c i of the tetrahedron. * @return the adjacent tetrahedron glued to the given face, or 0 * if the given face lies on the boundary. */ NTetrahedron* getAdjacentTetrahedron(int face) const; /** * Returns a permutation describing the correspondence between * vertices of this tetrahedron and vertices of the adjacent * tetrahedron glued to the given face of this tetrahedron. * * If we call this permutation \c p, then for each vertex \c v of this * tetrahedron, p[v] will be the vertex of the adjacent * tetrahedron that is identified with \c v according to the gluing * along the given face of this tetrahedron. * * \pre The given face of this tetrahedron has some tetrahedron * (possibly this one) glued to it. * * @param face the face of this tetrahedron whose gluing we * will examine. This should be between 0 and 3 inclusive, where * face \c i is opposite vertex \c i of the tetrahedron. * @return a permutation mapping the vertices of this * tetrahedron to the vertices of the tetrahedron adjacent along * the given face. */ NPerm4 adjacentGluing(int face) const; /** * Deprecated in favour of adjacentGluing(). The old routine * getAdjacentTetrahedronGluing() has been renamed to adjacentGluing() * as part of an effort to make programming and scripting with * Regina a little less work on the fingers. * * \deprecated This routine will eventually be removed in some future * version of Regina. Users are advised to use adjacentGluing() * instead, which is an identical routine with a shorter name. * * @param face the face of this tetrahedron whose gluing we * will examine. This should be between 0 and 3 inclusive, where * face \c i is opposite vertex \c i of the tetrahedron. * @return a permutation mapping the vertices of this * tetrahedron to the vertices of the tetrahedron adjacent along * the given face. */ NPerm4 getAdjacentTetrahedronGluing(int face) const; /** * Examines the tetrahedron glued to the given face of this * tetrahedron, and returns the corresponding face of that * tetrahedron. That is, the returned face of the adjacent * tetrahedron is glued to the given face of this tetrahedron. * * \pre The given face of this tetrahedron has some tetrahedron * (possibly this one) glued to it. * * @param face the face of this tetrahedron whose gluing we * will examine. This * should be between 0 and 3 inclusive, where face \c i is * opposite vertex \c i of the tetrahedron. * @return the face of the tetrahedron adjacent along the given * face that is in fact glued to the given face of this * tetrahedron. */ int adjacentFace(int face) const; /** * A dimension-agnostic alias for adjacentFace(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "facet" refers to a facet of a top-dimensional simplex * (which for 3-manifold triangulations means a face of a tetrahedron). * * See adjacentFace() for further information. */ int adjacentFacet(int facet) const; /** * Deprecated in favour of adjacentFace(). The old routine * getAdjacentFace() has been renamed to adjacentFace() * as part of an effort to make programming and scripting with * Regina a little less work on the fingers. * * \deprecated This routine will eventually be removed in some future * version of Regina. Users are advised to use adjacentFace() * instead, which is an identical routine with a shorter name. * * @param face the face of this tetrahedron whose gluing we * will examine. This should be between 0 and 3 inclusive, where * face \c i is opposite vertex \c i of the tetrahedron. * @return the face of the tetrahedron adjacent along the given * face that is in fact glued to the given face of this tetrahedron. */ int getAdjacentFace(int face) const; /** * Determines if this tetrahedron has any faces that are * boundary triangles. * * @return \c true if and only if this tetrahedron has any * boundary triangles. */ bool hasBoundary() const; /** * Joins the given face of this tetrahedron to another * tetrahedron. The other tetrahedron involved will be * automatically updated. * * Neither tetrahedron needs to belong to a triangulation (i.e., * you can join tetrahedra together before or after calling * NTriangulation::addTetrahedron()). However, if both * tetrahedra do belong to a triangulation then it must be the * \e same triangulation. * * \pre This and the given tetrahedron do not belong to * different triangulations. * \pre The given face of this tetrahedron is not currently glued to * anything. * \pre The face of the other tetrahedron that will be glued to the * given face of this tetrahedron is not currently glued to anything. * \pre If the other tetrahedron involved is this tetrahedron, we are * not attempting to glue a face to itself. * * \warning If one tetrahedron belongs to a triangulation but * the other does not, the missing tetrahedron (along with anything * that it is joined to, directly or indirectly) will be automatically * added to the triangulation. This is new behaviour as of * Regina 4.90; see the NTetrahedron class notes for details. * * @param myFace the face of this tetrahedron that will be glued * to the given other tetrahedron. This * should be between 0 and 3 inclusive, where face \c i is * opposite vertex \c i of the tetrahedron. * @param you the tetrahedron (possibly this one) that will be * glued to the given face of this tetrahedron. * @param gluing a permutation describing the mapping of * vertices by which the two tetrahedra will be joined. Each * vertex \c v of this tetrahedron that lies on the given face will * be identified with vertex gluing[v] of tetrahedron * you. In addition, the face of you that * will be glued to the given face of this tetrahedron will be * face number gluing[myFace]. */ void joinTo(int myFace, NTetrahedron* you, NPerm4 gluing); /** * Unglues the given face of this tetrahedron from whatever is * joined to it. The other tetrahedron involved (possibly this * one) will be automatically updated. * * \pre The given face of this tetrahedron has some tetrahedron * (possibly this one) glued to it. * * @param myFace the face of this tetrahedron whose gluing we * will undo. This should be between 0 and 3 inclusive, where * face \c i is opposite vertex \c i of the tetrahedron. * @return the ex-adjacent tetrahedron that was originally glued * to the given face of this tetrahedron. */ NTetrahedron* unjoin(int myFace); /** * Undoes any face gluings involving this tetrahedron. * Any other tetrahedra involved will be automatically updated. */ void isolate(); /** * Returns the triangulation to which this tetrahedron belongs. * * @return the triangulation containing this tetrahedron. */ NTriangulation* getTriangulation() const; /** * Returns the triangulation component to which this tetrahedron * belongs. * * As of Regina 4.90, if the skeletal information for the * triangulation has not been computed then this will be done * automatically. There is no need for users to explicitly * recompute the skeleton themselves. * * \pre This tetrahedron belongs to a triangulation (i.e., it * was created using NTriangulation::newTetrahedron() or added * using NTriangulation::addTetrahedron()). * * @return the component containing this tetrahedron. */ NComponent* getComponent() const; /** * Returns the vertex in the triangulation skeleton * corresponding to the given vertex of this tetrahedron. * * As of Regina 4.90, if the skeletal information for the * triangulation has not been computed then this will be done * automatically. There is no need for users to explicitly * recompute the skeleton themselves. * * \pre This tetrahedron belongs to a triangulation (i.e., it * was created using NTriangulation::newTetrahedron() or added * using NTriangulation::addTetrahedron()). * * @param vertex the vertex of this tetrahedron to examine. * This should be between 0 and 3 inclusive. * @return the vertex of the skeleton corresponding to the * requested tetrahedron vertex. */ NVertex* getVertex(int vertex) const; /** * Returns the edge in the triangulation skeleton * corresponding to the given edge of this tetrahedron. * * See NEdge::edgeNumber and NEdge::edgeVertex for * the conventions of how edges are numbered within a tetrahedron. * * As of Regina 4.90, if the skeletal information for the * triangulation has not been computed then this will be done * automatically. There is no need for users to explicitly * recompute the skeleton themselves. * * \pre This tetrahedron belongs to a triangulation (i.e., it * was created using NTriangulation::newTetrahedron() or added * using NTriangulation::addTetrahedron()). * * @param edge the edge of this tetrahedron to examine. * This should be between 0 and 5 inclusive. * @return the edge of the skeleton corresponding to the * requested tetrahedron edge. */ NEdge* getEdge(int edge) const; /** * Returns the triangle in the triangulation skeleton * corresponding to the given face of this tetrahedron. * * As of Regina 4.90, if the skeletal information for the * triangulation has not been computed then this will be done * automatically. There is no need for users to explicitly * recompute the skeleton themselves. * * \pre This tetrahedron belongs to a triangulation (i.e., it * was created using NTriangulation::newTetrahedron() or added * using NTriangulation::addTetrahedron()). * * @param face the face of this tetrahedron to examine. * This should be between 0 and 3 inclusive, where face \c i * lies opposite vertex \c i. * @return the triangle of the skeleton corresponding to the * requested tetrahedron face. */ NTriangle* getTriangle(int face) const; /** * A deprecated alias for getTriangle(). * * This routine returns the triangle in the triangulation * skeleton corresponding to the given face of this tetrahedron. * See getTriangle() for further details. * * \deprecated This routine will be removed in a future version * of Regina. Please use getTriangle() instead. * * @param face the face of this tetrahedron to examine. * This should be between 0 and 3 inclusive, where face \c i * lies opposite vertex \c i. * @return the triangle of the skeleton corresponding to the * requested tetrahedron face. */ NTriangle* getFace(int face) const; /** * Returns a permutation that maps 0 to the given vertex of this * tetrahedron, and that maps (1,2,3) to the three remaining vertices * in the following "orientation-preserving" fashion. * * The images of (1,2,3) under this permutation imply an * orientation for the tetrahedron face opposite the given vertex. * These orientations will be consistent for all tetrahedra * containing the given vertex, if this is possible (i.e., if * the vertex link is orientable). * * Note that there are still arbitrary decisions to be made for * the images of (1,2,3), since there will always be three possible * mappings that yield the correct orientation. * * As of Regina 4.90, if the skeletal information for the * triangulation has not been computed then this will be done * automatically. There is no need for users to explicitly * recompute the skeleton themselves. * * \pre This tetrahedron belongs to a triangulation (i.e., it * was created using NTriangulation::newTetrahedron() or added * using NTriangulation::addTetrahedron()). * * @param vertex the vertex of this tetrahedron to examine. * This should be between 0 and 3 inclusive. * @return a permutation that maps 0 to the given vertex of this * tetrahedron, with the properties outlined above. */ NPerm4 getVertexMapping(int vertex) const; /** * Examines the given edge of this tetrahedron, and returns a * permutation that maps the "canonical" vertices (0,1) of the * corresponding edge of the triangulation to the matching vertices * of this tetrahedron. This permutation also maps (2,3) to the * remaining tetrahedron vertices in an "orientation-preserving" * way, as described below. * * In detail: Suppose several edges of several tetrahedra are * identified within the overall triangulation. We call this a * single "edge of the triangulation", and arbitrarily * label its vertices (0,1). This routine then maps the vertices * (0,1) of this edge of the triangulation to the individual * vertices of this tetrahedron that make up the given edge. * * Because we are passing the argument \a edge, we already know * \e which vertices of this tetrahedron are involved. What this * routine tells us is the \a order in which they appear to form the * overall edge of the triangulation. * * As a consequence: Consider some collection of tetrahedron edges * that are identified together as a single edge of the triangulation, * and choose some \a i from the set {0,1}. Then the vertices * getEdgeMapping(...)[i] of the individual tetrahedra * are all identified together, since they all become the same * vertex of the same edge of the triangulation (assuming of * course that we pass the correct edge number in each case to * getEdgeMapping()). * * The images of 2 and 3 under the permutations that are returned * have the following properties. In each tetrahedron, the images * of 2 and 3 under this map form a directed edge of the tetrahedron * (running from the image of vertex 2 to the image of vertex 3). * For any given edge of the triangulation, these corresponding * directed edges together form an ordered path within the * triangulation that circles the common edge of the triangulation * (like an edge link, except that it is not near to the edge and so * might intersect itself). Furthermore, if we consider the individual * tetrahedra in the order in which they appear in the list * NEdge::getEmbeddings(), these corresponding directed edges * appear in order from the start of this path to the finish * (for internal edges this path is actually a cycle, and the * starting point is arbitrary). * * As of Regina 4.90, if the skeletal information for the * triangulation has not been computed then this will be done * automatically. There is no need for users to explicitly * recompute the skeleton themselves. * * \pre This tetrahedron belongs to a triangulation (i.e., it * was created using NTriangulation::newTetrahedron() or added * using NTriangulation::addTetrahedron()). * * @param edge the edge of this tetrahedron to examine. * This should be between 0 and 5 inclusive. * @return a mapping from vertices (0,1) of the requested * triangulation edge to the vertices of this tetrahedron. */ NPerm4 getEdgeMapping(int edge) const; /** * Examines the given face of this tetrahedron, and returns a * mapping from the "canonical" vertices of the corresponding * triangle of the triangulation to the matching vertices of this * tetrahedron. * * In detail: Suppose two faces of two tetrahedra are identified * within the overall triangulation. We call this a single * "triangle of the triangulation", and arbitrarily label its * vertices (0,1,2). This routine then maps the vertices * (0,1,2) of this triangle of the triangulation to the individual * vertices of this tetrahedron that make up the given face. * * Because we are passing the argument \a face, we already know * \e which vertices of this tetrahedron are involved. What this * routine tells us is the \a order in which they appear to form the * overall face of the triangulation. * * As a consequence: Consider some pair of tetrahedron faces that are * identified together as a single triangle of the triangulation, * and choose some \a i from the set {0,1,2}. Then the vertices * getTriangleMapping(...)[i] of the individual tetrahedra * are identified together, since they both become the same * vertex of the same triangle of the triangulation (assuming of * course that we pass the correct face number in each case to * getTriangleMapping()). * * As of Regina 4.90, if the skeletal information for the * triangulation has not been computed then this will be done * automatically. There is no need for users to explicitly * recompute the skeleton themselves. * * \pre This tetrahedron belongs to a triangulation (i.e., it * was created using NTriangulation::newTetrahedron() or added * using NTriangulation::addTetrahedron()). * * @param face the face of this tetrahedron to examine. * This should be between 0 and 3 inclusive. * @return a mapping from vertices (0,1,2) of the corresponding * triangle to the vertices of this tetrahedron. */ NPerm4 getTriangleMapping(int face) const; /** * A deprecated alias for getTriangleMapping(). * * This routine examines the given face of this tetrahedron, and * returns a mapping from the "canonical" vertices of the corresponding * triangle of the triangulation to the matching vertices of this * tetrahedron. See getTriangleMapping() for further details. * * \deprecated This routine will be removed in a future version * of Regina. Please use getTriangleMapping() instead. * * @param face the face of this tetrahedron to examine. * This should be between 0 and 3 inclusive. * @return a mapping from vertices (0,1,2) of the corresponding * triangle to the vertices of this tetrahedron. */ NPerm4 getFaceMapping(int face) const; /** * Returns the orientation of this tetrahedron in the * triangulation. * * The orientation of each tetrahedron is always +1 or -1. * In an orientable component of a triangulation, * adjacent tetrahedra have the same orientations if one could be * transposed onto the other without reflection, and they have * opposite orientations if a reflection would be required. * In a non-orientable component, orientations are still +1 and * -1 but no further guarantees can be made. * * As of Regina 4.90, if the skeletal information for the * triangulation has not been computed then this will be done * automatically. There is no need for users to explicitly * recompute the skeleton themselves. * * \pre This tetrahedron belongs to a triangulation (i.e., it * was created using NTriangulation::newTetrahedron() or added * using NTriangulation::addTetrahedron()). * * @return +1 or -1 according to the orientation of this tetrahedron. */ int orientation() const; void writeTextShort(std::ostream& out) const; void writeTextLong(std::ostream& out) const; friend class NTriangulation; /**< Allow access to private members. */ }; /*@}*/ } // namespace regina // Some more headers that are required for inline functions: #include "triangulation/ntriangulation.h" namespace regina { // Inline functions for NTetrahedron inline NTetrahedron::~NTetrahedron() { } inline const std::string& NTetrahedron::getDescription() const { return description_; } inline void NTetrahedron::setDescription(const std::string& desc) { NPacket::ChangeEventSpan span(tri_); description_ = desc; } inline unsigned long NTetrahedron::index() const { return markedIndex(); } inline NTetrahedron* NTetrahedron::adjacentTetrahedron(int face) const { return tetrahedra_[face]; } inline NTetrahedron* NTetrahedron::adjacentSimplex(int face) const { return tetrahedra_[face]; } inline NTetrahedron* NTetrahedron::getAdjacentTetrahedron(int face) const { // Deprecated. return tetrahedra_[face]; } inline int NTetrahedron::adjacentFace(int face) const { return tetrahedronPerm_[face][face]; } inline int NTetrahedron::adjacentFacet(int facet) const { return tetrahedronPerm_[facet][facet]; } inline int NTetrahedron::getAdjacentFace(int face) const { // Deprecated. return tetrahedronPerm_[face][face]; } inline NPerm4 NTetrahedron::adjacentGluing(int face) const { return tetrahedronPerm_[face]; } inline NPerm4 NTetrahedron::getAdjacentTetrahedronGluing(int face) const { // Deprecated! Finally. return tetrahedronPerm_[face]; } inline NTriangulation* NTetrahedron::getTriangulation() const { return tri_; } inline NComponent* NTetrahedron::getComponent() const { if (! tri_->calculatedSkeleton_) tri_->calculateSkeleton(); return component_; } inline NVertex* NTetrahedron::getVertex(int vertex) const { if (! tri_->calculatedSkeleton_) tri_->calculateSkeleton(); return vertices_[vertex]; } inline NEdge* NTetrahedron::getEdge(int edge) const { if (! tri_->calculatedSkeleton_) tri_->calculateSkeleton(); return edges_[edge]; } inline NTriangle* NTetrahedron::getTriangle(int face) const { if (! tri_->calculatedSkeleton_) tri_->calculateSkeleton(); return triangles_[face]; } inline NTriangle* NTetrahedron::getFace(int face) const { return getTriangle(face); } inline NPerm4 NTetrahedron::getVertexMapping(int vertex) const { if (! tri_->calculatedSkeleton_) tri_->calculateSkeleton(); return vertexMapping_[vertex]; } inline NPerm4 NTetrahedron::getEdgeMapping(int edge) const { if (! tri_->calculatedSkeleton_) tri_->calculateSkeleton(); return edgeMapping_[edge]; } inline NPerm4 NTetrahedron::getTriangleMapping(int face) const { if (! tri_->calculatedSkeleton_) tri_->calculateSkeleton(); return triMapping_[face]; } inline NPerm4 NTetrahedron::getFaceMapping(int face) const { return getTriangleMapping(face); } inline int NTetrahedron::orientation() const { if (! tri_->calculatedSkeleton_) tri_->calculateSkeleton(); return tetOrientation_; } inline void NTetrahedron::writeTextShort(std::ostream& out) const { out << "Tetrahedron"; if (description_.length() > 0) out << ": " << description_; } } // namespace regina #endif regina-4.96/engine/triangulation/ntriangle.cpp000644 000765 000024 00000012413 12377776767 021462 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "triangulation/nedge.h" #include "triangulation/ntriangle.h" namespace regina { const int NTriangle::TRIANGLE = 1; const int NTriangle::SCARF = 2; const int NTriangle::PARACHUTE = 3; const int NTriangle::CONE = 4; const int NTriangle::MOBIUS = 5; const int NTriangle::HORN = 6; const int NTriangle::DUNCEHAT = 7; const int NTriangle::L31 = 8; const NPerm4 NTriangle::ordering[4] = { NPerm4(1, 2, 3, 0), NPerm4(0, 2, 3, 1), NPerm4(0, 1, 3, 2), NPerm4(0, 1, 2, 3) }; int NTriangle::getType() { if (type_) return type_; subtype_ = -1; // Determine the triangle type. NVertex* v[3]; NEdge* e[3]; int i; for (i = 0; i < 3; i++) { v[i] = getVertex(i); e[i] = getEdge(i); } if (e[0] != e[1] && e[1] != e[2] && e[2] != e[0]) { // Three distinct edges. if (v[0] == v[1] && v[1] == v[2]) return (type_ = PARACHUTE); for (i = 0; i < 3; i++) if (v[(i+1)%3] == v[(i+2)%3]) { subtype_ = i; return (type_ = SCARF); } return (type_ = TRIANGLE); } if (e[0] == e[1] && e[1] == e[2]) { // All edges identified. if (getEdgeMapping(0).sign() == getEdgeMapping(1).sign() && getEdgeMapping(1).sign() == getEdgeMapping(2).sign()) return (type_ = L31); for (i = 0; i < 3; i++) if (getEdgeMapping((i+1)%3).sign() == getEdgeMapping((i+2)%3).sign()) { subtype_ = i; return (type_ = DUNCEHAT); } } // Two edges identified. for (i = 0; i < 3; i++) if (e[(i+1)%3] == e[(i+2)%3]) { subtype_ = i; if (getEdgeMapping((i+1)%3).sign() == getEdgeMapping((i+2)%3).sign()) return (type_ = MOBIUS); if (v[0] == v[1] && v[1] == v[2]) return (type_ = HORN); return (type_ = CONE); } // We should never reach this point. return 0; } NEdge* NTriangle::getEdge(int edge) const { NPerm4 p = embeddings_[0]->getVertices(); return embeddings_[0]->getTetrahedron()->getEdge( NEdge::edgeNumber[p[(edge + 1) % 3]][p[(edge + 2) % 3]]); } NPerm4 NTriangle::getEdgeMapping(int edge) const { NPerm4 triPerm = embeddings_[0]->getVertices(); // Maps triangle -> tetrahedron NPerm4 edgePerm = embeddings_[0]->getTetrahedron()->getEdgeMapping( NEdge::edgeNumber[triPerm[(edge + 1) % 3]][triPerm[(edge + 2) % 3]]); // Maps edge -> tetrahedron return NPerm4(triPerm.preImageOf(edgePerm[0]), triPerm.preImageOf(edgePerm[1]), edge, 3); } void NTriangle::writeTextLong(std::ostream& out) const { writeTextShort(out); out << std::endl; out << "Appears as:" << std::endl; for (int i = 0; i < nEmbeddings_; ++i) out << " " << embeddings_[i]->getTetrahedron()->markedIndex() << " (" << embeddings_[i]->getVertices().trunc3() << ')' << std::endl; } } // namespace regina regina-4.96/engine/triangulation/ntriangle.h000644 000765 000024 00000045210 12377775636 021122 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file triangulation/ntriangle.h * \brief Deals with triangles in a triangulation. */ #ifndef __NFACE_H #ifndef __DOXYGEN #define __NFACE_H #endif #include "regina-core.h" #include "shareableobject.h" #include "maths/nperm4.h" #include "utilities/nmarkedvector.h" // NOTE: More #includes follow after the class declarations. namespace regina { class NBoundaryComponent; class NComponent; class NEdge; class NTetrahedron; class NTriangulation; class NVertex; /** * \weakgroup triangulation * @{ */ /** * Details how a triangle in the skeleton forms part of an individual * tetrahedron. */ class REGINA_API NTriangleEmbedding { private: NTetrahedron* tetrahedron_; /**< The tetrahedron in which this triangle is contained. */ int tri_; /**< The face number of the tetrahedron that is this triangle. */ public: /** * Creates an embedding descriptor containing the given data. * * @param tet the tetrahedron in which this triangle is contained. * @param tri the face number of \a tet that is this triangle. */ NTriangleEmbedding(NTetrahedron* tet, int tri); /** * Creates an embedding descriptor containing the same data as * the given embedding descriptor. * * @param cloneMe the embedding descriptor to clone. */ NTriangleEmbedding(const NTriangleEmbedding& cloneMe); /** * Returns the tetrahedron in which this triangle is contained. * * @return the tetrahedron. */ NTetrahedron* getTetrahedron() const; /** * Returns the triangle number within getTetrahedron() that is * this triangle. * * @return the triangle number that is this triangle. */ int getTriangle() const; /** * A deprecated alias for getTriangle(). * * This routine returns the triangle number within getTetrahedron() * that is this triangle. See getTriangle() for further details. * * \deprecated This routine will be removed in a future version * of Regina. Please use getTriangle() instead. * * @return the triangle number that is this triangle. */ int getFace() const; /** * Returns a mapping from vertices (0,1,2) of this triangle to the * corresponding vertex numbers in getTetrahedron(), as described * in NTetrahedron::getTriangleMapping(). * * @return a mapping from the vertices of this triangle to the * vertices of getTetrahedron(). */ NPerm4 getVertices() const; /** * Tests whether this and the given embedding are identical. * Here "identical" means that they refer to the same face of * the same tetrahedron. * * @param rhs the embedding to compare with this. * @return \c true if and only if both embeddings are identical. */ bool operator == (const NTriangleEmbedding& rhs) const; /** * Tests whether this and the given embedding are different. * Here "different" means that they do not refer to the same * face of the same tetrahedron. * * @param rhs the embedding to compare with this. * @return \c true if and only if both embeddings are identical. */ bool operator != (const NTriangleEmbedding& rhs) const; }; /** * Represents a triangle in the skeleton of a triangulation. * Triangles are highly temporary; once a triangulation changes, all its * triangle objects will be deleted and new ones will be created. */ class REGINA_API NTriangle : public ShareableObject, public NMarkedElement { public: static const int TRIANGLE; /**< Specifies a triangle with no identified vertices or edges. */ static const int SCARF; /**< Specifies a triangle with two identified vertices. */ static const int PARACHUTE; /**< Specifies a triangle with three identified vertices. */ static const int CONE; /**< Specifies a triangle with two edges identified to form a cone. */ static const int MOBIUS; /**< Specifies a triangle with two edges identified to form a mobius band. */ static const int HORN; /**< Specifies a triangle with two edges identified to form a cone with all three vertices identified. */ static const int DUNCEHAT; /**< Specifies a triangle with all three edges identified, some via orientable and some via non-orientable gluings. */ static const int L31; /**< Specifies a triangle with all three edges identified using non-orientable gluings. Note that this forms a spine for the Lens space L(3,1). */ /** * An array that maps triangle numbers within a tetrahedron * (i.e., face numbers) to the canonical ordering of the individual * tetrahedron vertices that form each triangle. * * This means that the vertices of triangle \a i in a tetrahedron * are, in canonical order, ordering[i][0..2]. As an * immediate consequence, we obtain ordering[i][3] == i. * * Regina defines canonical order to be \e increasing order. * That is, ordering[i][0] < ... < ordering[i][2]. * * This table does \e not describe the mapping from specific * triangles within a triangulation into individual tetrahedra (for * that, see NTetrahedron::getTriangleMapping() instead). This table * merely provides a neat and consistent way of listing the * vertices of any given tetrahedron face. * * This lookup table replaces the deprecated routine * regina::faceOrdering(). */ static const NPerm4 ordering[4]; private: NTriangleEmbedding* embeddings_[2]; /**< An array of descriptors telling how this triangle forms a part of each individual tetrahedron that it belongs to. These embeddings will be automatically deleted when the triangle itself is deleted. */ int nEmbeddings_; /**< The number of embedding descriptors stored in the embeddings array. */ NComponent* component_; /**< The component that this triangle is a part of. */ NBoundaryComponent* boundaryComponent_; /**< The boundary component that this triangle is a part of, or 0 if this triangle is internal. */ int type_; /**< Specifies the triangle type according to one of the predefined triangle type constants in NTriangle, or 0 if type has not yet been determined. */ int subtype_; /**< Specifies the vertex or edge that plays a special role for the triangle type specified by \a type. This is only relevant for some triangle types. */ public: /** * Default destructor. * All embedding descriptors stored in this triangle will be * automatically deleted. */ virtual ~NTriangle(); /** * Returns the index of this triangle in the underlying * triangulation. This is identical to calling * getTriangulation()->triangleIndex(this). * * @return the index of this triangle. */ unsigned long index() const; /** * Determines if this triangle lies entirely on the boundary of the * triangulation. * * @return \c true if and only if this triangle lies on the boundary. */ bool isBoundary() const; /** * Returns a description of the triangle type. * The triangle type describes how the edges and vertices of the * triangle are identified. * * @return one of the predefined triangle type constants in NTriangle. */ int getType(); /** * Return the triangle vertex or triangle edge that plays a special role * for the triangle type of this triangle. Note that this routine is * only relevant for some triangle types. The triangle type is * returned by getType(). * * @return The vertex or edge that plays a special role (this * will be 0, 1 or 2), or -1 if this triangle type has no special * vertex or edge. */ int getSubtype(); /** * Determines whether this triangle is wrapped up to form a Mobius band. * * Note that several different triangle types (as returned by * getType()) can produce this result. * Note also that a triangle can be both a Mobius band \a and a cone. * * @return \c true if and only if this triangle is a Mobius band. */ bool isMobiusBand(); /** * Determines whether this triangle is wrapped up to form a cone. * * Note that several different triangle types (as returned by * getType()) can produce this result. * Note also that a triangle can be both a Mobius band \a and a cone. * * @return \c true if and only if this triangle is a cone. */ bool isCone(); /** * Returns the number of descriptors available through getEmbedding(). * Note that this number will never be greater than two. * * @return the number of embedding descriptors. */ unsigned getNumberOfEmbeddings() const; /** * Returns the requested descriptor detailing how this triangle forms a * part of a particular tetrahedron in the triangulation. * Note that if this triangle represents multiple faces of a * particular tetrahedron, then there will be multiple embedding * descriptors available regarding that tetrahedron. * * @param index the index of the requested descriptor. This * should be between 0 and getNumberOfEmbeddings()-1 inclusive. * @return the requested embedding descriptor. */ const NTriangleEmbedding& getEmbedding(unsigned index) const; /** * Returns the triangulation to which this triangle belongs. * * @return the triangulation containing this triangle. */ NTriangulation* getTriangulation() const; /** * Returns the component of the triangulation to which this * triangle belongs. * * @return the component containing this triangle. */ NComponent* getComponent() const; /** * Returns the boundary component of the triangulation to which * this triangle belongs. * * @return the boundary component containing this triangle, or 0 if this * triangle does not lie entirely within the boundary of the * triangulation. */ NBoundaryComponent* getBoundaryComponent() const; /** * Returns the vertex of the triangulation that corresponds * to the given vertex of this triangle. * * Note that vertex \a i of a triangle is opposite edge \a i of the * triangle. * * @param vertex the vertex of this triangle to examine. This should * be 0, 1 or 2. * @return the corresponding vertex of the triangulation. */ NVertex* getVertex(int vertex) const; /** * Returns the edge of the triangulation that corresponds * to the given edge of this triangle. * * Note that edge \a i of a triangle is opposite vertex \a i of the * triangle. * * @param edge the edge of this triangle to examine. This should be * 0, 1 or 2. * @return the corresponding edge of the triangulation. */ NEdge* getEdge(int edge) const; /** * Examines the given edge of this triangle, and returns a mapping * from the "canonical" vertices of the corresponding edge of * the triangulation to the vertices of this triangle. * * This routine behaves much the same as * NTetrahedron::getEdgeMapping(), except that it maps the edge * vertices into a triangle, not into a tetrahedron. See * NTetrahedron::getEdgeMapping() for a more detailed * explanation of precisely what this mapping means. * * This routine differs from NTetrahedron::getEdgeMapping() in * how it handles the images of 2 and 3. This routine will * always map 2 to the remaining vertex of this triangle (which is * equal to the argument \a edge), and will always map 3 to itself. * * @param edge the edge of this triangle to examine. This should be * 0, 1 or 2. * @return a mapping from vertices (0,1) of the requested edge to * the vertices of this triangle. */ NPerm4 getEdgeMapping(int edge) const; void writeTextShort(std::ostream& out) const; void writeTextLong(std::ostream& out) const; private: /** * Creates a new triangle and marks it as belonging to the * given triangulation component. * * @param myComponent the triangulation component to which this * triangle belongs. */ NTriangle(NComponent* myComponent); friend class NTriangulation; /**< Allow access to private members. */ }; /*@}*/ } // namespace regina // Some more headers that are required for inline functions: #include "triangulation/ntetrahedron.h" namespace regina { // Inline functions for NTriangle inline NTriangle::NTriangle(NComponent* myComponent) : nEmbeddings_(0), component_(myComponent), boundaryComponent_(0), type_(0) { } inline NTriangle::~NTriangle() { if (nEmbeddings_ > 0) delete embeddings_[0]; if (nEmbeddings_ > 1) delete embeddings_[1]; } inline unsigned long NTriangle::index() const { return markedIndex(); } inline NTriangulation* NTriangle::getTriangulation() const { return embeddings_[0]->getTetrahedron()->getTriangulation(); } inline NComponent* NTriangle::getComponent() const { return component_; } inline NBoundaryComponent* NTriangle::getBoundaryComponent() const { return boundaryComponent_; } inline NVertex* NTriangle::getVertex(int vertex) const { return embeddings_[0]->getTetrahedron()->getVertex( embeddings_[0]->getVertices()[vertex]); } inline bool NTriangle::isBoundary() const { return (boundaryComponent_ != 0); } inline int NTriangle::getSubtype() { getType(); return subtype_; } inline bool NTriangle::isMobiusBand() { getType(); return (type_ == L31 || type_ == DUNCEHAT || type_ == MOBIUS); } inline bool NTriangle::isCone() { getType(); return (type_ == DUNCEHAT || type_ == CONE || type_ == HORN); } inline unsigned NTriangle::getNumberOfEmbeddings() const { return nEmbeddings_; } inline const NTriangleEmbedding& NTriangle::getEmbedding(unsigned index) const { return *(embeddings_[index]); } inline void NTriangle::writeTextShort(std::ostream& out) const { out << (isBoundary() ? "Boundary " : "Internal ") << "triangle"; } inline NTriangleEmbedding::NTriangleEmbedding(NTetrahedron* tet, int tri) : tetrahedron_(tet), tri_(tri) { } inline NTriangleEmbedding::NTriangleEmbedding( const NTriangleEmbedding& cloneMe) : tetrahedron_(cloneMe.tetrahedron_), tri_(cloneMe.tri_) { } inline NTetrahedron* NTriangleEmbedding::getTetrahedron() const { return tetrahedron_; } inline int NTriangleEmbedding::getTriangle() const { return tri_; } inline int NTriangleEmbedding::getFace() const { return tri_; } inline NPerm4 NTriangleEmbedding::getVertices() const { return tetrahedron_->getTriangleMapping(tri_); } inline bool NTriangleEmbedding::operator == (const NTriangleEmbedding& other) const { return ((tetrahedron_ == other.tetrahedron_) && (tri_ == other.tri_)); } inline bool NTriangleEmbedding::operator != (const NTriangleEmbedding& other) const { return ((tetrahedron_ != other.tetrahedron_) || (tri_ != other.tri_)); } } // namespace regina #endif regina-4.96/engine/triangulation/ntriangulation.cpp000644 000765 000024 00000067173 12377776767 022552 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include #include #include #include #include "foreign/snappea.h" #include "triangulation/ntriangulation.h" #include "utilities/stringutils.h" #include "utilities/xmlutils.h" namespace regina { NTriangulation::NTriangulation(const std::string& description) : calculatedSkeleton_(false) { NTriangulation* attempt; if ((attempt = fromIsoSig(description))) { cloneFrom(*attempt); setPacketLabel(description); } else if ((attempt = rehydrate(description))) { cloneFrom(*attempt); setPacketLabel(description); } else if ((attempt = fromSnapPea(description))) { cloneFrom(*attempt); setPacketLabel(attempt->getPacketLabel()); } delete attempt; } void NTriangulation::addTetrahedron(NTetrahedron* t) { // Make this a no-op if the tetrahedron has already been added. if (t->tri_ == this) return; assert(t->tri_ == 0); ChangeEventSpan span(this); t->tri_ = this; tetrahedra_.push_back(t); // Aggressively add neighbours of t (recursively). // First check whether this is even necessary. bool moreToAdd = false; int i; for (i = 0; i < 4; ++i) if (t->adjacentTetrahedron(i) && ! t->adjacentTetrahedron(i)->tri_) { moreToAdd = true; break; } if (moreToAdd) { // Yep, it's necessary.. off we go. std::stack toFollow; toFollow.push(t); NTetrahedron* next; NTetrahedron* adj; while (! toFollow.empty()) { next = toFollow.top(); toFollow.pop(); for (i = 0; i < 4; ++i) { adj = next->adjacentTetrahedron(i); if (adj && ! adj->tri_) { adj->tri_ = this; tetrahedra_.push_back(adj); toFollow.push(adj); } } } } clearAllProperties(); } void NTriangulation::swapContents(NTriangulation& other) { ChangeEventSpan span1(this); ChangeEventSpan span2(&other); clearAllProperties(); other.clearAllProperties(); tetrahedra_.swap(other.tetrahedra_); TetrahedronIterator it; for (it = tetrahedra_.begin(); it != tetrahedra_.end(); ++it) (*it)->tri_ = this; for (it = other.tetrahedra_.begin(); it != other.tetrahedra_.end(); ++it) (*it)->tri_ = &other; } void NTriangulation::moveContentsTo(NTriangulation& dest) { ChangeEventSpan span1(this); ChangeEventSpan span2(&dest); clearAllProperties(); dest.clearAllProperties(); TetrahedronIterator it; for (it = tetrahedra_.begin(); it != tetrahedra_.end(); ++it) { // This is an abuse of NMarkedVector, since for a brief moment // each tetrahedron belongs to both vectors // tetrahedra_ and dest.tetrahedra_. // However, the subsequent clear() operation does not touch the // tetrahedron markings (indices), and so we end up with the // correct result (i.e., the markings are correct for dest). (*it)->tri_ = &dest; dest.tetrahedra_.push_back(*it); } tetrahedra_.clear(); } void NTriangulation::clearAllProperties() { if (calculatedSkeleton_) deleteSkeleton(); fundamentalGroup_.clear(); H1_.clear(); H1Rel_.clear(); H1Bdry_.clear(); H2_.clear(); zeroEfficient_.clear(); splittingSurface_.clear(); twoSphereBoundaryComponents_.clear(); negativeIdealBoundaryComponents_.clear(); threeSphere_.clear(); threeBall_.clear(); solidTorus_.clear(); irreducible_.clear(); compressingDisc_.clear(); haken_.clear(); strictAngleStructure_.clear(); turaevViroCache_.clear(); } void NTriangulation::writeTextLong(std::ostream& out) const { if (! calculatedSkeleton_) calculateSkeleton(); out << "Size of the skeleton:\n"; out << " Tetrahedra: " << tetrahedra_.size() << '\n'; out << " Triangles: " << triangles_.size() << '\n'; out << " Edges: " << edges_.size() << '\n'; out << " Vertices: " << vertices_.size() << '\n'; out << '\n'; NTetrahedron* tet; NTetrahedron* adjTet; unsigned tetPos; int face, vertex, start, end; NPerm4 adjPerm; out << "Tetrahedron gluing:\n"; out << " Tet | glued to: (012) (013) (023) (123)\n"; out << " -----+-------------------------------------------------------\n"; for (tetPos=0; tetPos=0; face--) { out << " "; adjTet = tet->adjacentTetrahedron(face); if (! adjTet) out << " boundary"; else { adjPerm = tet->adjacentGluing(face); out << std::setw(3) << tetrahedronIndex(adjTet) << " ("; for (vertex=0; vertex<4; vertex++) { if (vertex == face) continue; out << adjPerm[vertex]; } out << ")"; } } out << '\n'; } out << '\n'; out << "Vertices:\n"; out << " Tet | vertex: 0 1 2 3\n"; out << " -----+--------------------------\n"; for (tetPos=0; tetPosgetVertex(vertex)); out << '\n'; } out << '\n'; out << "Edges:\n"; out << " Tet | edge: 01 02 03 12 13 23\n"; out << " -----+--------------------------------\n"; for (tetPos=0; tetPosgetEdge(NEdge::edgeNumber[start][end])); out << '\n'; } out << '\n'; out << "Triangles:\n"; out << " Tet | face: 012 013 023 123\n"; out << " -----+------------------------\n"; for (tetPos=0; tetPos=0; face--) out << ' ' << std::setw(3) << triangleIndex(tet->getTriangle(face)); out << '\n'; } out << '\n'; } void NTriangulation::writeXMLPacketData(std::ostream& out) const { using regina::xml::xmlEncodeSpecialChars; using regina::xml::xmlValueTag; // Write the tetrahedron gluings. TetrahedronIterator it; NTetrahedron* adjTet; int face; out << " \n"; for (it = tetrahedra_.begin(); it != tetrahedra_.end(); it++) { out << " getDescription()) << "\"> "; for (face = 0; face < 4; face++) { adjTet = (*it)->adjacentTetrahedron(face); if (adjTet) { out << tetrahedronIndex(adjTet) << ' ' << static_cast((*it)-> adjacentGluing(face).getPermCode()) << ' '; } else out << "-1 -1 "; } out << "\n"; } out << " \n"; if (fundamentalGroup_.known()) { out << " \n"; fundamentalGroup_.value()->writeXMLData(out); out << " \n"; } if (H1_.known()) { out << "

"; H1_.value()->writeXMLData(out); out << "

\n"; } if (H1Rel_.known()) { out << " "; H1Rel_.value()->writeXMLData(out); out << "\n"; } if (H1Bdry_.known()) { out << " "; H1Bdry_.value()->writeXMLData(out); out << "\n"; } if (H2_.known()) { out << "

"; H2_.value()->writeXMLData(out); out << "

\n"; } if (twoSphereBoundaryComponents_.known()) out << " " << xmlValueTag("twosphereboundarycomponents", twoSphereBoundaryComponents_.value()) << '\n'; if (negativeIdealBoundaryComponents_.known()) out << " " << xmlValueTag("negativeidealboundarycomponents", negativeIdealBoundaryComponents_.value()) << '\n'; if (zeroEfficient_.known()) out << " " << xmlValueTag("zeroeff", zeroEfficient_.value()) << '\n'; if (splittingSurface_.known()) out << " " << xmlValueTag("splitsfce", splittingSurface_.value()) << '\n'; if (threeSphere_.known()) out << " " << xmlValueTag("threesphere", threeSphere_.value()) << '\n'; if (threeBall_.known()) out << " " << xmlValueTag("threeball", threeBall_.value()) << '\n'; if (solidTorus_.known()) out << " " << xmlValueTag("solidtorus", solidTorus_.value()) << '\n'; if (irreducible_.known()) out << " " << xmlValueTag("irreducible", irreducible_.value()) << '\n'; if (compressingDisc_.known()) out << " " << xmlValueTag("compressingdisc", compressingDisc_.value()) << '\n'; if (haken_.known()) out << " " << xmlValueTag("haken", haken_.value()) << '\n'; if (! turaevViroCache_.empty()) { for (TuraevViroSet::const_iterator it = turaevViroCache_.begin(); it != turaevViroCache_.end(); it++) out << " \n"; } } NTriangulation* NTriangulation::enterTextTriangulation(std::istream& in, std::ostream& out) { NTriangulation* triang = new NTriangulation(); NTetrahedron* tet; long nTet; // Create new tetrahedra. out << "Number of tetrahedra: "; in >> nTet; while (nTet < 0) { out << "The number of tetrahedra must be non-negative.\n"; out << "Number of tetrahedra: "; in >> nTet; } out << '\n'; for (long i=0; inewTetrahedron(); // Read in the joins. long tetPos, altPos; int face, altFace; NTetrahedron* altTet; int vertices[6]; out << "Tetrahedra are numbered from 0 to " << nTet-1 << ".\n"; out << "Vertices are numbered from 0 to 3.\n"; out << "Enter in the face gluings one at a time.\n"; out << '\n'; while(1) { out << "Enter two tetrahedra to glue, separated by a space, or "; out << "-1 if finished: "; in >> tetPos; if (tetPos < 0) break; in >> altPos; if (altPos < 0) break; if (tetPos >= nTet || altPos >= nTet) { out << "Tetrahedron identifiers must be between 0 and " << nTet-1 << " inclusive.\n"; continue; } tet = triang->tetrahedra_[tetPos]; altTet = triang->tetrahedra_[altPos]; out << "Enter the three vertices of the first tetrahedron (" << tetPos << "), separated by spaces,\n"; out << " that will form one face of the gluing: "; in >> vertices[0] >> vertices[1] >> vertices[2]; out << "Enter the corresponding three vertices of the second tetrahedron (" << altPos << "): "; in >> vertices[3] >> vertices[4] >> vertices[5]; if (vertices[3] < 0 || vertices[3] > 3 || vertices[4] < 0 || vertices[4] > 3 || vertices[5] < 0 || vertices[5] > 3 || vertices[0] < 0 || vertices[0] > 3 || vertices[1] < 0 || vertices[1] > 3 || vertices[2] < 0 || vertices[2] > 3) { out << "Vertices must be between 0 and 3 inclusive.\n"; continue; } if (vertices[0] == vertices[1] || vertices[1] == vertices[2] || vertices[2] == vertices[0]) { out << "The three vertices for tetrahedron " << tetPos << " must be different.\n"; continue; } if (vertices[3] == vertices[4] || vertices[4] == vertices[5] || vertices[5] == vertices[3]) { out << "The three vertices for tetrahedron " << altPos << " must be different.\n"; continue; } face = 6 - vertices[0] - vertices[1] - vertices[2]; altFace = 6 - vertices[3] - vertices[4] - vertices[5]; if (face == altFace && tetPos == altPos) { out << "You cannot glue a face to itself.\n"; continue; } if (tet->adjacentTetrahedron(face) || altTet->adjacentTetrahedron(altFace)) { out << "One of these faces is already glued to something else.\n"; continue; } tet->joinTo(face, altTet, NPerm4(vertices[0], vertices[3], vertices[1], vertices[4], vertices[2], vertices[5], face, altFace)); out << '\n'; } out << "Finished reading gluings.\n"; out << "The triangulation has been successfully created.\n"; out << '\n'; // Return the completed triangulation. return triang; } long NTriangulation::getEulerCharManifold() const { // Begin with V - E + F - T. // This call to getEulerCharTri() also ensures that the skeleton has // been calculated. long ans = getEulerCharTri(); // Truncate any ideal vertices. for (BoundaryComponentIterator it = boundaryComponents_.begin(); it != boundaryComponents_.end(); ++it) if ((*it)->isIdeal()) ans += (*it)->getEulerChar() - 1; // If we have an invalid triangulation, we need to locate non-standard // boundary vertices and invalid edges, and truncate those unwanted bits // also. if (! valid_) { for (VertexIterator it = vertices_.begin(); it != vertices_.end(); ++it) if ((*it)->getLink() == NVertex::NON_STANDARD_BDRY) ans += (*it)->getLinkEulerChar() - 1; for (EdgeIterator it = edges_.begin(); it != edges_.end(); ++it) if (! (*it)->isValid()) ++ans; } return ans; } void NTriangulation::deleteTetrahedra() { for_each(tetrahedra_.begin(), tetrahedra_.end(), FuncDelete()); tetrahedra_.clear(); } void NTriangulation::deleteSkeleton() { // Now that skeletal destructors are private, we can't just use for_each. // How primitive. Loop through each list indivually. for (VertexIterator it = vertices_.begin(); it != vertices_.end(); ++it) delete *it; for (EdgeIterator it = edges_.begin(); it != edges_.end(); ++it) delete *it; for (TriangleIterator it = triangles_.begin(); it != triangles_.end(); ++it) delete *it; for (ComponentIterator it = components_.begin(); it != components_.end(); ++it) delete *it; for (BoundaryComponentIterator it = boundaryComponents_.begin(); it != boundaryComponents_.end(); ++it) delete *it; vertices_.clear(); edges_.clear(); triangles_.clear(); components_.clear(); boundaryComponents_.clear(); calculatedSkeleton_ = false; } void NTriangulation::cloneFrom(const NTriangulation& X) { ChangeEventSpan span(this); removeAllTetrahedra(); TetrahedronIterator it; for (it = X.tetrahedra_.begin(); it != X.tetrahedra_.end(); it++) newTetrahedron((*it)->getDescription()); // Make the gluings. long tetPos, adjPos; NTetrahedron* tet; NTetrahedron* adjTet; NPerm4 adjPerm; int face; tetPos = 0; for (it = X.tetrahedra_.begin(); it != X.tetrahedra_.end(); it++) { tet = *it; for (face=0; face<4; face++) { adjTet = tet->adjacentTetrahedron(face); if (adjTet) { adjPos = X.tetrahedronIndex(adjTet); adjPerm = tet->adjacentGluing(face); if (adjPos > tetPos || (adjPos == tetPos && adjPerm[face] > face)) { tetrahedra_[tetPos]->joinTo(face, tetrahedra_[adjPos], adjPerm); } } } tetPos++; } // Properties: if (X.fundamentalGroup_.known()) fundamentalGroup_= new NGroupPresentation(*X.fundamentalGroup_.value()); if (X.H1_.known()) H1_ = new NAbelianGroup(*(X.H1_.value())); if (X.H1Rel_.known()) H1Rel_ = new NAbelianGroup(*(X.H1Rel_.value())); if (X.H1Bdry_.known()) H1Bdry_ = new NAbelianGroup(*(X.H1Bdry_.value())); if (X.H2_.known()) H2_ = new NAbelianGroup(*(X.H2_.value())); twoSphereBoundaryComponents_ = X.twoSphereBoundaryComponents_; negativeIdealBoundaryComponents_ = X.negativeIdealBoundaryComponents_; zeroEfficient_ = X.zeroEfficient_; splittingSurface_ = X.splittingSurface_; threeSphere_ = X.threeSphere_; threeBall_ = X.threeBall_; solidTorus_ = X.solidTorus_; irreducible_ = X.irreducible_; compressingDisc_ = X.compressingDisc_; haken_ = X.haken_; if (X.strictAngleStructure_.known()) { if (X.strictAngleStructure_.value()) strictAngleStructure_ = new NAngleStructure(this, new NAngleStructureVector( *X.strictAngleStructure_.value()->rawVector())); else strictAngleStructure_ = 0; } turaevViroCache_ = X.turaevViroCache_; } void NTriangulation::insertTriangulation(const NTriangulation& X) { ChangeEventSpan span(this); unsigned long norig = getNumberOfTetrahedra(); unsigned long nX = X.getNumberOfTetrahedra(); unsigned long tetPos; for (tetPos = 0; tetPos < nX; ++tetPos) newTetrahedron(X.tetrahedra_[tetPos]->getDescription()); // Make the gluings. unsigned long adjPos; NTetrahedron* tet; NTetrahedron* adjTet; NPerm4 adjPerm; int face; for (tetPos = 0; tetPos < nX; ++tetPos) { tet = X.tetrahedra_[tetPos]; for (face=0; face<4; face++) { adjTet = tet->adjacentTetrahedron(face); if (adjTet) { adjPos = X.tetrahedronIndex(adjTet); adjPerm = tet->adjacentGluing(face); if (adjPos > tetPos || (adjPos == tetPos && adjPerm[face] > face)) { tetrahedra_[norig + tetPos]->joinTo(face, tetrahedra_[norig + adjPos], adjPerm); } } } } } void NTriangulation::insertConstruction(unsigned long nTetrahedra, const int adjacencies[][4], const int gluings[][4][4]) { if (nTetrahedra == 0) return; ChangeEventSpan span(this); NTetrahedron** tet = new NTetrahedron*[nTetrahedra]; unsigned i, j; NPerm4 p; for (i = 0; i < nTetrahedra; i++) tet[i] = newTetrahedron(); for (i = 0; i < nTetrahedra; i++) for (j = 0; j < 4; j++) if (adjacencies[i][j] >= 0 && ! tet[i]->adjacentTetrahedron(j)) { p = NPerm4(gluings[i][j][0], gluings[i][j][1], gluings[i][j][2], gluings[i][j][3]); tet[i]->joinTo(j, tet[adjacencies[i][j]], p); } delete[] tet; } std::string NTriangulation::dumpConstruction() const { std::ostringstream ans; ans << "/**\n"; if (! getPacketLabel().empty()) ans << " * Triangulation: " << getPacketLabel() << "\n"; ans << " * Code automatically generated by dumpConstruction().\n" " */\n" "\n"; if (tetrahedra_.empty()) { ans << "/* This triangulation is empty. No code is being generated. */\n"; return ans.str(); } ans << "/**\n" " * The following arrays describe the individual gluings of\n" " * tetrahedron faces.\n" " */\n" "\n"; unsigned long nTetrahedra = tetrahedra_.size(); NTetrahedron* tet; NPerm4 p; unsigned long t; int f, i; ans << "const int adjacencies[" << nTetrahedra << "][4] = {\n"; for (t = 0; t < nTetrahedra; t++) { tet = tetrahedra_[t]; ans << " { "; for (f = 0; f < 4; f++) { if (tet->adjacentTetrahedron(f)) { ans << tetrahedronIndex(tet->adjacentTetrahedron(f)); } else ans << "-1"; if (f < 3) ans << ", "; else if (t != nTetrahedra - 1) ans << "},\n"; else ans << "}\n"; } } ans << "};\n\n"; ans << "const int gluings[" << nTetrahedra << "][4][4] = {\n"; for (t = 0; t < nTetrahedra; t++) { tet = tetrahedra_[t]; ans << " { "; for (f = 0; f < 4; f++) { if (tet->adjacentTetrahedron(f)) { p = tet->adjacentGluing(f); ans << "{ "; for (i = 0; i < 4; i++) { ans << p[i]; if (i < 3) ans << ", "; else ans << " }"; } } else ans << "{ 0, 0, 0, 0 }"; if (f < 3) ans << ", "; else if (t != nTetrahedra - 1) ans << " },\n"; else ans << " }\n"; } } ans << "};\n\n"; ans << "/**\n" " * The following code actually constructs a triangulation based on\n" " * the information stored in the arrays above.\n" " */\n" "\n" "NTriangulation tri;\n" "tri.insertConstruction(" << nTetrahedra << ", adjacencies, gluings);\n" "\n"; return ans.str(); } std::string NTriangulation::snapPea() const { std::ostringstream out; snapPea(out); return out.str(); } void NTriangulation::snapPea(std::ostream& out) const { // Sanity checks. if ((! isValid()) || hasBoundaryTriangles() || tetrahedra_.empty()) return; // Write header information. out << "% Triangulation\n"; if (getPacketLabel().empty()) out << "Regina_Triangulation\n"; else out << stringToToken(getPacketLabel()) << '\n'; // Write general details. out << "not_attempted 0.0\n"; out << "unknown_orientability\n"; out << "CS_unknown\n"; // Write cusps. out << "0 0\n"; // Write tetrahedra. out << getNumberOfTetrahedra() << '\n'; int i, j; for (NTriangulation::TetrahedronIterator it = getTetrahedra().begin(); it != getTetrahedra().end(); it++) { // Although our precondition states that there are no boundary // triangles, we test for this anyway. If somebody makes a mistake and // calls this routine with a bounded triangulation, we don't want // to wind up calling tetrahedronIndex(0) and crashing. for (i = 0; i < 4; i++) if ((*it)->adjacentTetrahedron(i)) out << " " << tetrahedronIndex( (*it)->adjacentTetrahedron(i)) << ' '; else out << " -1 "; out << '\n'; for (i = 0; i < 4; i++) out << ' ' << (*it)->adjacentGluing(i).str(); out << '\n'; // Incident cusps. for (i = 0; i < 4; i++) out << " -1 "; out << '\n'; // Meridians and longitudes. for (i = 0; i < 4; i++) { for (j = 0; j < 16; j++) out << " 0"; out << '\n'; } // Tetrahedron shape. out << "0.0 0.0\n"; } } bool NTriangulation::saveSnapPea(const char* filename) const { // Sanity checks. if ((! isValid()) || hasBoundaryTriangles() || tetrahedra_.empty()) return false; std::ofstream out(filename); if (!out) return false; snapPea(out); return true; } std::string NTriangulation::recogniser() const { std::ostringstream out; recogniser(out); return out.str(); } std::string NTriangulation::recognizer() const { std::ostringstream out; recogniser(out); return out.str(); } void NTriangulation::recogniser(std::ostream& out) const { // Sanity checks. if ((! isValid()) || hasBoundaryTriangles()) return; // Write the header. out << "triangulation" << std::endl; // Write face gluings. NTriangle* f; NTetrahedron* tet; NPerm4 vert; for (unsigned i = 0; i < getNumberOfTriangles(); ++i) { f = getTriangle(i); tet = f->getEmbedding(0).getTetrahedron(); vert = f->getEmbedding(0).getVertices(); out << 't' << (tetrahedronIndex(tet) + 1) << '(' << (vert[0] + 1) << ',' << (vert[1] + 1) << ',' << (vert[2] + 1) << ") - "; tet = f->getEmbedding(1).getTetrahedron(); vert = f->getEmbedding(1).getVertices(); out << 't' << (tetrahedronIndex(tet) + 1) << '(' << (vert[0] + 1) << ',' << (vert[1] + 1) << ',' << (vert[2] + 1) << ')'; if (i != getNumberOfTriangles() - 1) out << ','; out << std::endl; } // Write the footer. out << "end" << std::endl; } bool NTriangulation::saveRecogniser(const char* filename) const { // Sanity checks. if ((! isValid()) || hasBoundaryTriangles()) return false; // Write to file or stdout as appropriate. std::ofstream out(filename); if (! out) return false; recogniser(out); return true; } NTriangulation* NTriangulation::fromSnapPea(const std::string& snapPeaData) { std::istringstream in(snapPeaData); return readSnapPea(in); } } // namespace regina regina-4.96/engine/triangulation/ntriangulation.h000644 000765 000024 00000541106 12377775640 022175 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file triangulation/ntriangulation.h * \brief Deals with triangulations. */ #ifndef __NTRIANGULATION_H #ifndef __DOXYGEN #define __NTRIANGULATION_H #endif #include #include #include #include #include "regina-core.h" #include "algebra/nabeliangroup.h" #include "algebra/ngrouppresentation.h" #include "angle/nanglestructure.h" #include "generic/ngenerictriangulation.h" #include "packet/npacket.h" #include "utilities/nbooleans.h" #include "utilities/nmarkedvector.h" #include "utilities/nproperty.h" // The following headers are necessary so that std::auto_ptr can invoke // destructors where necessary. #include "triangulation/nisomorphism.h" // NOTE: More #includes follow after the class declarations. namespace regina { class NAngleStructure; class NBoundaryComponent; class NComponent; class NEdge; class NTriangle; class NTetrahedron; class NVertex; class NGroupPresentation; class NIsomorphism; class NNormalSurface; class NTriangulation; class NXMLPacketReader; class NXMLTriangulationReader; /** * \addtogroup triangulation Triangulations * Triangulations of 3-manifolds. * @{ */ /** * Stores information about the 3-manifold triangulation packet. * See the general PacketInfo template notes for further details. * * \ifacespython Not present. */ template <> struct PacketInfo { typedef NTriangulation Class; inline static const char* name() { return "3-Manifold Triangulation"; } }; /** * Stores the triangulation of a 3-manifold along with its * various cellular structures and other information. * * When the triangulation is deleted, the corresponding * tetrahedra, the cellular structure and all other properties * will be deallocated. * * Triangles, edges, vertices and components are always temporary; * whenever a change * occurs with the triangulation, these will be deleted and a new * skeletal structure will be calculated. The same is true of various * other triangulation properties. * * The management of tetrahedra within a triangulation has become simpler and * safer as of Regina 4.90. In older versions (Regina 4.6 and earlier), * users were required to create tetrahedra, individually add them to * triangulations, and manually notify a triangulation whenever its tetrahedron * gluings changed. As of Regina 4.90, new tetrahedra are created using * NTriangulation::newTetrahedron() which automatically places them within * a triangulation, and all gluing changes are likewise communicated to the * triangulation automatically. These are part of a larger suite of changes * (all designed to help the user avoid inconsistent states and accidental * crashes); see the NTetrahedron class notes for further details. * * \todo \feature Is the boundary incompressible? * \todo \featurelong Am I obviously a handlebody? (Simplify and see * if there is nothing left). Am I obviously not a handlebody? * (Compare homology with boundary homology). * \todo \featurelong Is the triangulation Haken? * \todo \featurelong What is the Heegaard genus? * \todo \featurelong Have a subcomplex as a child packet of a * triangulation. Include routines to crush a subcomplex or to expand a * subcomplex to a normal surface. * \todo \featurelong Implement writeTextLong() for skeletal objects. */ class REGINA_API NTriangulation : public NPacket, public NGenericTriangulation<3> { REGINA_PACKET(NTriangulation, PACKET_TRIANGULATION) public: typedef std::vector::const_iterator TetrahedronIterator; /**< Used to iterate through tetrahedra. */ typedef std::vector::const_iterator TriangleIterator; /**< Used to iterate through triangles. */ typedef std::vector::const_iterator FaceIterator; /**< A deprecated alias for TriangleIterator. */ typedef std::vector::const_iterator EdgeIterator; /**< Used to iterate through edges. */ typedef std::vector::const_iterator VertexIterator; /**< Used to iterate through vertices. */ typedef std::vector::const_iterator ComponentIterator; /**< Used to iterate through components. */ typedef std::vector::const_iterator BoundaryComponentIterator; /**< Used to iterate through boundary components. */ typedef std::map, double> TuraevViroSet; /**< A map from (r, whichRoot) pairs to Turaev-Viro invariants. */ private: mutable bool calculatedSkeleton_; /**< Has the skeleton been calculated? */ NMarkedVector tetrahedra_; /**< The tetrahedra that form the triangulation. */ mutable NMarkedVector triangles_; /**< The triangles in the triangulation skeleton. */ mutable NMarkedVector edges_; /**< The edges in the triangulation skeleton. */ mutable NMarkedVector vertices_; /**< The vertices in the triangulation skeleton. */ mutable NMarkedVector components_; /**< The components that form the triangulation. */ mutable NMarkedVector boundaryComponents_; /**< The components that form the boundary of the triangulation. */ mutable bool valid_; /**< Is the triangulation valid? */ mutable bool ideal_; /**< Is the triangulation ideal? */ mutable bool standard_; /**< Is the triangulation standard? */ mutable bool orientable_; /**< Is the triangulation orientable? */ mutable NProperty fundamentalGroup_; /**< Fundamental group of the triangulation. */ mutable NProperty H1_; /**< First homology group of the triangulation. */ mutable NProperty H1Rel_; /**< Relative first homology group of the triangulation * with respect to the boundary. */ mutable NProperty H1Bdry_; /**< First homology group of the boundary. */ mutable NProperty H2_; /**< Second homology group of the triangulation. */ mutable NProperty twoSphereBoundaryComponents_; /**< Does the triangulation contain any 2-sphere boundary components? */ mutable NProperty negativeIdealBoundaryComponents_; /**< Does the triangulation contain any boundary components that are ideal and have negative Euler characteristic? */ mutable NProperty zeroEfficient_; /**< Is the triangulation zero-efficient? */ mutable NProperty splittingSurface_; /**< Does the triangulation have a normal splitting surface? */ mutable NProperty threeSphere_; /**< Is this a triangulation of a 3-sphere? */ mutable NProperty threeBall_; /**< Is this a triangulation of a 3-dimensional ball? */ mutable NProperty solidTorus_; /**< Is this a triangulation of the solid torus? */ mutable NProperty irreducible_; /**< Is this 3-manifold irreducible? */ mutable NProperty compressingDisc_; /**< Does this 3-manifold contain a compressing disc? */ mutable NProperty haken_; /**< Is this 3-manifold Haken? This property must only be stored for triangulations that are known to represent closed, connected, orientable, irreducible 3-manifolds. */ mutable NProperty strictAngleStructure_; /**< A strict angle structure on this triangulation, or the null pointer if none exists. */ mutable TuraevViroSet turaevViroCache_; /**< The set of Turaev-Viro invariants that have already been calculated. */ public: /** * \name Constructors and Destructors */ /*@{*/ /** * Default constructor. * * Creates an empty triangulation. */ NTriangulation(); /** * Copy constructor. * * Creates a new triangulation identical to the given triangulation. * The packet tree structure and packet label are \e not copied. * * @param cloneMe the triangulation to clone. */ NTriangulation(const NTriangulation& cloneMe); /** * "Magic" constructor that tries to find some way to interpret * the given string as a triangulation. * * At present, Regina understands the following types of strings * (and attempts to parse them in the following order): * * - isomorphism signatures (see fromIsoSig()); * - dehydration strings (see rehydrate()); * - the contents of a SnapPea data file (see fromSnapPea()). * * This list may grow in future versions of Regina. * * Regina will also set the packet label accordingly. * * If Regina cannot interpret the given string, this will be * left as the empty triangulation. * * \warning If you pass the contents of a SnapPea data file, * then only the tetrahedron gluings will be read; all other * SnapPea-specific information (such as peripheral curves) will * be lost. See fromSnapPea() for details, and for other * alternatives that preserve SnapPea-specific data. * * @param description a string that describes a 3-manifold * triangulation. */ NTriangulation(const std::string& description); /** * Destroys this triangulation. * * The constituent tetrahedra, the cellular structure and all other * properties will also be deallocated. */ virtual ~NTriangulation(); /*@}*/ /** * \name Packet Administration */ /*@{*/ virtual void writeTextShort(std::ostream& out) const; virtual void writeTextLong(std::ostream& out) const; virtual bool dependsOnParent() const; /*@}*/ /** * \name Tetrahedra */ /*@{*/ /** * Returns the number of tetrahedra in the triangulation. * * @return the number of tetrahedra. */ unsigned long getNumberOfTetrahedra() const; /** * A dimension-agnostic alias for getNumberOfTetrahedra(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "simplex" refers to a top-dimensional simplex (which for * 3-manifold triangulations means a tetrahedron). * * See getNumberOfTetrahedra() for further information. */ unsigned long getNumberOfSimplices() const; /** * Returns all tetrahedra in the triangulation. * * The reference returned will remain valid * for as long as the triangulation exists, * always reflecting the tetrahedra currently in the * triangulation. * * \ifacespython This routine returns a python list. * * @return the list of all tetrahedra. */ const std::vector& getTetrahedra() const; /** * A dimension-agnostic alias for getTetrahedra(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "simplex" refers to a top-dimensional simplex (which for * 3-manifold triangulations means a tetrahedron). * * See getTetrahedra() for further information. */ const std::vector& getSimplices() const; /** * Returns the tetrahedron with the given index number in the * triangulation. * Note that tetrahedron indexing may change when a tetrahedron * is added or removed from the triangulation. * * @param index specifies which tetrahedron to return; this * value should be between 0 and getNumberOfTetrahedra()-1 * inclusive. * @return the indexth tetrahedron in the * triangulation. */ NTetrahedron* getTetrahedron(unsigned long index); /** * A dimension-agnostic alias for getTetrahedron(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "simplex" refers to a top-dimensional simplex (which for * 3-manifold triangulations means a tetrahedron). * * See getTetrahedron() for further information. */ NTetrahedron* getSimplex(unsigned long index); /** * Returns the tetrahedron with the given index number in the * triangulation. * Note that tetrahedron indexing may change when a tetrahedron * is added or removed from the triangulation. * * @param index specifies which tetrahedron to return; this * value should be between 0 and getNumberOfTetrahedra()-1 * inclusive. * @return the indexth tetrahedron in the * triangulation. */ const NTetrahedron* getTetrahedron(unsigned long index) const; /** * A dimension-agnostic alias for getTetrahedron(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "simplex" refers to a top-dimensional simplex (which for * 3-manifold triangulations means a tetrahedron). * * See getTetrahedron() for further information. */ const NTetrahedron* getSimplex(unsigned long index) const; /** * Returns the index of the given tetrahedron in the * triangulation. * * Note that tetrahedron indexing may change when a tetrahedron * is added or removed from the triangulation. * * This routine was introduced in Regina 4.5, and replaces the * old getTetrahedronIndex(). The name has been changed * because, unlike the old routine, it requires that the given * tetrahedron belongs to the triangulation (a consequence of * some significant memory optimisations). * * \pre The given tetrahedron is contained in this triangulation. * * \warning Passing a null pointer to this routine will probably * crash your program. If you are passing the result of some other * routine that \e might return null (such as * NTetrahedron::adjacentTetrahedron), it might be worth explicitly * testing for null beforehand. * * @param tet specifies which tetrahedron to find in the * triangulation. * @return the index of the specified tetrahedron, where 0 is * the first tetrahedron, 1 is the second and so on. */ long tetrahedronIndex(const NTetrahedron* tet) const; /** * A dimension-agnostic alias for tetrahedronIndex(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "simplex" refers to a top-dimensional simplex (which for * 3-manifold triangulations means a tetrahedron). * * See tetrahedronIndex() for further information. */ long simplexIndex(const NTetrahedron* tet) const; /** * Creates a new tetrahedron and adds it to this triangulation. * The new tetrahedron will have an empty description. * All four faces of the new tetrahedron will be boundary triangles. * * The new tetrahedron will become the last tetrahedron in this * triangulation. * * @return the new tetrahedron. */ NTetrahedron* newTetrahedron(); /** * A dimension-agnostic alias for newTetrahedron(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "simplex" refers to a top-dimensional simplex (which for * 3-manifold triangulations means a tetrahedron). * * See newTetrahedron() for further information. */ NTetrahedron* newSimplex(); /** * Creates a new tetrahedron with the given description and adds * it to this triangulation. * All four faces of the new tetrahedron will be boundary triangles. * * @param desc the description to assign to the new tetrahedron. * @return the new tetrahedron. */ NTetrahedron* newTetrahedron(const std::string& desc); /** * A dimension-agnostic alias for newTetrahedron(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "simplex" refers to a top-dimensional simplex (which for * 3-manifold triangulations means a tetrahedron). * * See newTetrahedron() for further information. */ NTetrahedron* newSimplex(const std::string& desc); /** * Inserts the given tetrahedron into the triangulation. * No face gluings anywhere will be examined or altered. * * The new tetrahedron will be assigned a higher index in the * triangulation than all tetrahedra already present. * * \pre The given tetrahedron does not already belong to a * different triangulation (though already belonging to \e this * triangulation is perfectly fine). * * \deprecated Users should create tetrahedra by calling * newTetrahedron() or newTetrahedron(const std::string&), which * will add the tetrahedron to the triangulation automatically. * * \warning As of Regina 4.90, this routine will also add any * neighbouring tetrahedra that do not yet belong to a * triangulation; moreover, this addition is recursive. This is done * to ensure that, whenever one tetrahedron belongs to a * triangulation, everything that it is joined to (directly or * indirectly) also belongs to that same triangulation. * See the NTetrahedron class notes for further details on how * tetrahedron management has changed in Regina 4.90 and above. * * \ifacespython Since this triangulation takes ownership * of the given tetrahedron, the python object containing the * given tetrahedron becomes a null object and should no longer * be used. * * @param tet the tetrahedron to insert. */ void addTetrahedron(NTetrahedron* tet); /** * Removes the given tetrahedron from the triangulation. * All faces glued to this tetrahedron will be unglued. * The tetrahedron will be deallocated. * * \pre The given tetrahedron exists in the triangulation. * * \warning This routine has changed behaviour as of Regina 4.90. * In older versions of Regina, the tetrahedron was returned to * the user. As of Regina 4.90, the tetrahedron is now destroyed * immediately. * * @param tet the tetrahedron to remove. */ void removeTetrahedron(NTetrahedron* tet); /** * A dimension-agnostic alias for removeTetrahedron(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "simplex" refers to a top-dimensional simplex (which for * 3-manifold triangulations means a tetrahedron). * * See removeTetrahedron() for further information. */ void removeSimplex(NTetrahedron* tet); /** * Removes the tetrahedron with the given index number * from the triangulation. Note that tetrahedron indexing may * change when a tetrahedron is added or removed from the * triangulation. * * All faces glued to this tetrahedron will be unglued. * The tetrahedron will be deallocated. * * \warning This routine has changed behaviour as of Regina 4.90. * In older versions of Regina, the tetrahedron was returned to * the user. As of Regina 4.90, the tetrahedron is now destroyed * immediately. * * @param index specifies which tetrahedron to remove; this * should be between 0 and getNumberOfTetrahedra()-1 inclusive. */ void removeTetrahedronAt(unsigned long index); /** * A dimension-agnostic alias for removeTetrahedronAt(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "simplex" refers to a top-dimensional simplex (which for * 3-manifold triangulations means a tetrahedron). * * See removeTetrahedronAt() for further information. */ void removeSimplexAt(unsigned long index); /** * Removes all tetrahedra from the triangulation. * All tetrahedra will be deallocated. */ void removeAllTetrahedra(); /** * A dimension-agnostic alias for removeAllTetrahedra(). * This is to assist with writing dimension-agnostic code that * can be reused to work in different dimensions. * * Here "simplex" refers to a top-dimensional simplex (which for * 3-manifold triangulations means a tetrahedron). * * See removeAllTetrahedra() for further information. */ void removeAllSimplices(); /** * Swaps the contents of this and the given triangulation. * That is, all tetrahedra that belong to this triangulation * will be moved to \a other, and all tetrahedra that belong to * \a other will be moved to this triangulation. * * All NTetrahedron pointers or references will remain valid. * * @param other the triangulation whose contents should be * swapped with this. */ void swapContents(NTriangulation& other); /** * Moves the contents of this triangulation into the given * destination triangulation, without destroying any pre-existing * contents. That is, all tetrahedra that currently belong to * \a dest will remain there, and all tetrahedra that belong to this * triangulation will be moved across as additional * tetrahedra in \a dest. * * All NTetrahedron pointers or references will remain valid. * After this operation, this triangulation will be empty. * * @param dest the triangulation to which tetrahedra should be * moved. */ void moveContentsTo(NTriangulation& dest); /** * This routine now does nothing, and should not be used. * * \deprecated In Regina versions 4.6 and earlier, this routine * was used to manually notify the triangulation that the gluings * of tetrahedra had changed. In Regina 4.90 and later this * notification is automatic. This routine now does nothing at * all, and can safely be removed from any existing code. */ void gluingsHaveChanged(); /*@}*/ /** * \name Skeletal Queries */ /*@{*/ /** * Returns the number of boundary components in this * triangulation. Note that each ideal vertex forms its own * boundary component. * * @return the number of boundary components. */ unsigned long getNumberOfBoundaryComponents() const; /** * Returns the number of components in this triangulation. * * @return the number of components. */ unsigned long getNumberOfComponents() const; /** * Returns the number of vertices in this triangulation. * * @return the number of vertices. */ unsigned long getNumberOfVertices() const; /** * Returns the number of edges in this triangulation. * * @return the number of edges. */ unsigned long getNumberOfEdges() const; /** * Returns the number of triangular faces in this triangulation. * * @return the number of triangles. */ unsigned long getNumberOfTriangles() const; /** * A deprecated alias for getNumberOfTriangles(). * * This routine returns the number of triangular faces in this * triangulation. See getNumberOfTriangles() for further details. * * Do not confuse this deprecated alias with the * (non-deprecated) tempate function getNumberOfFaces(). * * \deprecated This routine will be removed in a future version * of Regina. Please use getNumberOfTriangles() instead. * * @return the number of triangles. */ unsigned long getNumberOfFaces() const; /** * Returns the number of faces of the given dimension in this * triangulation. * * This template function is to assist with writing dimension-agnostic * code that can be reused to work in different dimensions. * * \pre the template argument \a dim is between 0 and 3 inclusive. * * \ifacespython Not present. * * @return the number of faces of the given dimension. */ template unsigned long getNumberOfFaces() const; /** * Returns all components of this triangulation. * * Bear in mind that each time the triangulation changes, the * components will be deleted and replaced with new * ones. Thus the objects contained in this list should be * considered temporary only. * * This reference to the list however will remain valid and * up-to-date for as long as the triangulation exists. * * \ifacespython This routine returns a python list. * * @return the list of all components. */ const std::vector& getComponents() const; /** * Returns all boundary components of this triangulation. * Note that each ideal vertex forms its own boundary component. * * Bear in mind that each time the triangulation changes, the * boundary components will be deleted and replaced with new * ones. Thus the objects contained in this list should be * considered temporary only. * * This reference to the list however will remain valid and * up-to-date for as long as the triangulation exists. * * \ifacespython This routine returns a python list. * * @return the list of all boundary components. */ const std::vector& getBoundaryComponents() const; /** * Returns all vertices of this triangulation. * * Bear in mind that each time the triangulation changes, the * vertices will be deleted and replaced with new * ones. Thus the objects contained in this list should be * considered temporary only. * * This reference to the list however will remain valid and * up-to-date for as long as the triangulation exists. * * \ifacespython This routine returns a python list. * * @return the list of all vertices. */ const std::vector& getVertices() const; /** * Returns all edges of this triangulation. * * Bear in mind that each time the triangulation changes, the * edges will be deleted and replaced with new * ones. Thus the objects contained in this list should be * considered temporary only. * * This reference to the list however will remain valid and * up-to-date for as long as the triangulation exists. * * \ifacespython This routine returns a python list. * * @return the list of all edges. */ const std::vector& getEdges() const; /** * Returns all triangular faces of this triangulation. * * Bear in mind that each time the triangulation changes, the * triangles will be deleted and replaced with new * ones. Thus the objects contained in this list should be * considered temporary only. * * This reference to the list however will remain valid and * up-to-date for as long as the triangulation exists. * * \ifacespython This routine returns a python list. * * @return the list of all triangles. */ const std::vector& getTriangles() const; /** * A deprecated alias for getTriangles(). * * This routine returns all triangular faces in this triangulation. * See getTriangles() for further details. * * \deprecated This routine will be removed in a future version * of Regina. Please use getTriangles() instead. * * @return the list of all triangles. */ const std::vector& getFaces() const; /** * Returns the requested triangulation component. * * Bear in mind that each time the triangulation changes, the * components will be deleted and replaced with new * ones. Thus this object should be considered temporary only. * * @param index the index of the desired component, ranging from 0 * to getNumberOfComponents()-1 inclusive. * @return the requested component. */ NComponent* getComponent(unsigned long index) const; /** * Returns the requested triangulation boundary component. * * Bear in mind that each time the triangulation changes, the * boundary components will be deleted and replaced with new * ones. Thus this object should be considered temporary only. * * @param index the index of the desired boundary * component, ranging from 0 * to getNumberOfBoundaryComponents()-1 inclusive. * @return the requested boundary component. */ NBoundaryComponent* getBoundaryComponent(unsigned long index) const; /** * Returns the requested vertex in this triangulation. * * Bear in mind that each time the triangulation changes, the * vertices will be deleted and replaced with new * ones. Thus this object should be considered temporary only. * * @param index the index of the desired vertex, ranging from 0 * to getNumberOfVertices()-1 inclusive. * @return the requested vertex. */ NVertex* getVertex(unsigned long index) const; /** * Returns the requested edge in this triangulation. * * Bear in mind that each time the triangulation changes, the * edges will be deleted and replaced with new * ones. Thus this object should be considered temporary only. * * @param index the index of the desired edge, ranging from 0 * to getNumberOfEdges()-1 inclusive. * @return the requested edge. */ NEdge* getEdge(unsigned long index) const; /** * Returns the requested triangular face in this triangulation. * * Bear in mind that each time the triangulation changes, the * triangles will be deleted and replaced with new * ones. Thus this object should be considered temporary only. * * @param index the index of the desired triangle, ranging from 0 * to getNumberOfTriangles()-1 inclusive. * @return the requested triangle. */ NTriangle* getTriangle(unsigned long index) const; /** * A deprecated alias for getTriangle(). * * This routine returns the requested triangular face in the * triangulation. See getTriangle() for further details. * * \deprecated This routine will be removed in a future version * of Regina. Please use getTriangle() instead. * * @param index the index of the desired triangle, ranging from 0 * to getNumberOfTriangles()-1 inclusive. * @return the requested triangle. */ NTriangle* getFace(unsigned long index) const; /** * Returns the index of the given component in the triangulation. * * This routine was introduced in Regina 4.5, and replaces the * old getComponentIndex(). The name has been changed * because, unlike the old routine, it requires that the given * component belongs to the triangulation (a consequence of * some significant memory optimisations). * * \pre The given component belongs to this triangulation. * * \warning Passing a null pointer to this routine will probably * crash your program. * * @param component specifies which component to find in the * triangulation. * @return the index of the specified component, where 0 is the first * component, 1 is the second and so on. */ long componentIndex(const NComponent* component) const; /** * Returns the index of the given boundary component * in the triangulation. * * This routine was introduced in Regina 4.5, and replaces the * old getBoundaryComponentIndex(). The name has been changed * because, unlike the old routine, it requires that the given * boundary component belongs to the triangulation (a consequence of * some significant memory optimisations). * * \pre The given boundary component belongs to this triangulation. * * \warning Passing a null pointer to this routine will probably * crash your program. * * @param bc specifies which boundary component to find in the * triangulation. * @return the index of the specified boundary component, * where 0 is the first boundary component, 1 is the second and so on. */ long boundaryComponentIndex(const NBoundaryComponent* bc) const; /** * Returns the index of the given vertex in the triangulation. * * This routine was introduced in Regina 4.5, and replaces the * old getVertexIndex(). The name has been changed * because, unlike the old routine, it requires that the given * vertex belongs to the triangulation (a consequence of * some significant memory optimisations). * * \pre The given vertex belongs to this triangulation. * * \warning Passing a null pointer to this routine will probably * crash your program. * * @param vertex specifies which vertex to find in the * triangulation. * @return the index of the specified vertex, where 0 is the first * vertex, 1 is the second and so on. */ long vertexIndex(const NVertex* vertex) const; /** * Returns the index of the given edge in the triangulation. * * This routine was introduced in Regina 4.5, and replaces the * old getEdgeIndex(). The name has been changed * because, unlike the old routine, it requires that the given * edge belongs to the triangulation (a consequence of * some significant memory optimisations). * * \pre The given edge belongs to this triangulation. * * \warning Passing a null pointer to this routine will probably * crash your program. * * @param edge specifies which edge to find in the * triangulation. * @return the index of the specified edge, where 0 is the first * edge, 1 is the second and so on. */ long edgeIndex(const NEdge* edge) const; /** * Returns the index of the given triangle in the triangulation. * * This routine was introduced in Regina 4.5, and replaces the * old getFaceIndex(). The name has been changed * because, unlike the old routine, it requires that the given * triangle belongs to the triangulation (a consequence of * some significant memory optimisations). * * \pre The given triangle belongs to this triangulation. * * \warning Passing a null pointer to this routine will probably * crash your program. * * @param triangle specifies which triangle to find in the * triangulation. * @return the index of the specified triangle, where 0 is the first * triangle, 1 is the second and so on. */ long triangleIndex(const NTriangle* triangle) const; /** * A deprecated alias for triangleIndex(). * * This routine returns the index of the given triangle in the * triangulation. See triangleIndex() for further details. * * \deprecated This routine will be removed in a future version * of Regina. Please use triangleIndex() instead. * * @param triangle specifies which triangle to find in the * triangulation. * @return the index of the specified triangle, where 0 is the first * triangle, 1 is the second and so on. */ long faceIndex(const NTriangle* triangle) const; /** * Determines if this triangulation contains any two-sphere * boundary components. * * @return \c true if and only if there is at least one * two-sphere boundary component. */ bool hasTwoSphereBoundaryComponents() const; /** * Determines if this triangulation contains any ideal boundary * components with negative Euler characteristic. * * @return \c true if and only if there is at least one such * boundary component. */ bool hasNegativeIdealBoundaryComponents() const; /*@}*/ /** * \name Isomorphism Testing */ /*@{*/ using NGenericTriangulation<3>::isIdenticalTo; using NGenericTriangulation<3>::isIsomorphicTo; using NGenericTriangulation<3>::isContainedIn; using NGenericTriangulation<3>::findAllIsomorphisms; using NGenericTriangulation<3>::findAllSubcomplexesIn; using NGenericTriangulation<3>::makeCanonical; /*@}*/ /** * \name Basic Properties */ /*@{*/ using NGenericTriangulation<3>::isEmpty; /** * Returns the Euler characteristic of this triangulation. * This will be evaluated strictly as \a V-E+F-T. * * Note that this routine handles cusps in a non-standard way. * Since it computes the Euler characteristic of the * triangulation (and not the underlying manifold), this routine * will treat each cusp as a single vertex, and \e not as * a surface boundary component. * * For a routine that handles cusps properly (i.e., treats them * as surface boundary components when computing the Euler * characteristic), see getEulerCharManifold() instead. * * This routine was previously called getEulerCharacteristic() in * Regina 4.3.1 and earlier. It was renamed in Regina 4.4 to * clarify the non-standard handling of cusps. * * @return the Euler characteristic of this triangulation. */ long getEulerCharTri() const; /** * Returns the Euler characteristic of the corresponding compact * 3-manifold. * * Instead of simply calculating \a V-E+F-T, this routine also: * * - treats ideal vertices as surface boundary components * (i.e., effectively truncates them); * - truncates invalid boundary vertices (i.e., boundary vertices * whose links are not discs); * - truncates the projective plane cusps at the midpoints of invalid * edges (edges identified with themselves in reverse). * * For ideal triangulations, this routine therefore computes * the proper Euler characteristic of the manifold (unlike * getEulerCharTri(), which does not). * * For triangulations whose vertex links are all spheres or discs, * this routine and getEulerCharTri() give identical results. * * @return the Euler characteristic of the corresponding compact * manifold. */ long getEulerCharManifold() const; /** * A deprecated alias for getEulerCharTri(). * * This routine calculates the Euler characteristic of this * triangulation. Since it treats cusps in a non-standard way, * it was renamed to getEulerCharTri() in Regina 4.4 to clarify * that this might differ from the Euler characteristic of the * corresponding compact manifold. * * See getEulerCharTri() for further details. * * \deprecated This routine will be removed in a future version * of Regina. Please use getEulerCharTri() instead. * * @return the Euler characteristic of this triangulation. */ long getEulerCharacteristic() const; /** * Determines if this triangulation is valid. * A triangulation is valid unless there is some vertex whose * link has boundary but is not a disc (i.e., a vertex for which * NVertex::getLink() returns NVertex::NON_STANDARD_BDRY), * or unless there is some edge glued to itself in reverse * (i.e., an edge for which NEdge::isValid() returns \c false). * * @return \c true if and only if this triangulation is valid. */ bool isValid() const; /** * Determines if this triangulation is ideal. * This is the case if and only if one of the vertex links * is closed and not a 2-sphere. * Note that the triangulation is not required to be valid. * * @return \c true if and only if this triangulation is ideal. */ bool isIdeal() const; /** * Determines if this triangulation is standard. * This is the case if and only if every vertex is standard. * See NVertex::isStandard() for further details. * * @return \c true if and only if this triangulation is * standard. */ bool isStandard() const; /** * Determines if this triangulation has any boundary triangles. * * @return \c true if and only if there are boundary triangles. */ bool hasBoundaryTriangles() const; /** * A deprecated alias for hasBoundaryTriangles(). * * This routine determines whether this triangulation has any * boundary triangles. See hasBoundaryTriangles() for further details. * * \deprecated This routine will be removed in a future version * of Regina. Please use hasBoundaryTriangles() instead. * * @return \c true if and only if there are boundary triangles. */ bool hasBoundaryFaces() const; /** * Returns the number of boundary triangles in this triangulation. * * @return the total number of boundary triangles. */ unsigned long getNumberOfBoundaryTriangles() const; /** * Determines if this triangulation is closed. * This is the case if and only if it has no boundary. * Note that ideal triangulations are not closed. * * @return \c true if and only if this triangulation is closed. */ bool isClosed() const; /** * Determines if this triangulation is orientable. * * @return \c true if and only if this triangulation is * orientable. */ bool isOrientable() const; /** * Determines if this triangulation is oriented; that is, if * tetrahedron vertices are labelled in a way that preserves * orientation across adjacent tetrahedron faces. Specifically, this * routine returns \c true if and only if every gluing permutation * has negative sign. * * Note that \e orientable triangulations are not always \e oriented * by default. You can call orient() if you need the tetrahedra * to be oriented consistently as described above. * * A non-orientable triangulation can never be oriented. * * @return \c true if and only if all tetrahedra are oriented * consistently. * * @author Matthias Goerner */ bool isOriented() const; /** * Determines if this triangulation is ordered; that is, if * tetrahedron vertices are labelled so that all gluing * permutations are order-preserving on the tetrahedron faces. * Equivalently, this tests whether the edges of the triangulation * can all be oriented such that they induce a consistent ordering * on the vertices of each tetrahedron. * * Triangulations are not ordered by default, and indeed some * cannot be ordered at all. The routine order() will attempt * to relabel tetrahedron vertices to give an ordered triangulation. * * @return \c true if and only if all gluing permutations are * order preserving on the tetrahedron faces. * * @author Matthias Goerner */ bool isOrdered() const; /** * Determines if this triangulation is connected. * * @return \c true if and only if this triangulation is * connected. */ bool isConnected() const; /*@}*/ /** * \name Algebraic Properties */ /*@{*/ /** * Returns the fundamental group of this triangulation. * If this triangulation contains any ideal or non-standard * vertices, the fundamental group will be * calculated as if each such vertex had been truncated. * * If this triangulation contains any invalid edges, the * calculations will be performed without any truncation * of the corresponding projective plane cusp. Thus if a * barycentric subdivision is performed on the triangulation, the * result of getFundamentalGroup() will change. * * Bear in mind that each time the triangulation changes, the * fundamental group will be deleted. Thus the reference that is * returned from this routine should not be kept for later use. * Instead, getFundamentalGroup() should be called again; this will * be instantaneous if the group has already been calculated. * * Note that this triangulation is not required to be valid * (see isValid()). * * \pre This triangulation has at most one component. * * \warning As with every routine implemented by Regina's * NTriangulation class, if you are calling this from the subclass * NSnapPeaTriangulation then any fillings on the cusps will be * ignored. If you wish to compute the fundamental group with * fillings, call NSnapPeaTriangulation::fundamentalGroupFilled() * instead. * * @return the fundamental group. */ const NGroupPresentation& getFundamentalGroup() const; /** * Notifies the triangulation that you have simplified the * presentation of its fundamental group. The old group * presentation will be destroyed, and this triangulation will * take ownership of the new (hopefully simpler) group that is * passed. * * This routine is useful for situations in which some external * body (such as GAP) has simplified the group presentation * better than Regina can. * * Regina does not verify that the new group presentation * is equivalent to the old, since this is - well, hard. * * If the fundamental group has not yet been calculated for this * triangulation, this routine will nevertheless take ownership * of the new group, under the assumption that you have worked * out the group through some other clever means without ever * having needed to call getFundamentalGroup() at all. * * Note that this routine will not fire a packet change event. * * @param newGroup a new (and hopefully simpler) presentation * of the fundamental group of this triangulation. */ void simplifiedFundamentalGroup(NGroupPresentation* newGroup); /** * Returns the first homology group for this triangulation. * If this triangulation contains any ideal or non-standard * vertices, the homology group will be * calculated as if each such vertex had been truncated. * * If this triangulation contains any invalid edges, the * calculations will be performed without any truncation * of the corresponding projective plane cusp. Thus if a * barycentric subdivision is performed on the triangulation, the * result of getHomologyH1() will change. * * Bear in mind that each time the triangulation changes, the * homology groups will be deleted. Thus the reference that is * returned from this routine should not be kept for later use. * Instead, getHomologyH1() should be called again; this will be * instantaneous if the group has already been calculated. * * Note that this triangulation is not required to be valid * (see isValid()). * * \warning As with every routine implemented by Regina's * NTriangulation class, if you are calling this from the subclass * NSnapPeaTriangulation then any fillings on the cusps will * be ignored. If you wish to compute homology with fillings, * call NSnapPeaTriangulation::homologyFilled() instead. * * @return the first homology group. */ const NAbelianGroup& getHomologyH1() const; /** * Returns the relative first homology group with * respect to the boundary for this triangulation. * Note that ideal vertices are considered part of the boundary. * * Bear in mind that each time the triangulation changes, the * homology groups will be deleted. Thus the reference that is * returned from this routine should not be kept for later use. * Instead, getHomologyH1Rel() should be called again; this will be * instantaneous if the group has already been calculated. * * \pre This triangulation is valid. * * @return the relative first homology group with respect to the * boundary. */ const NAbelianGroup& getHomologyH1Rel() const; /** * Returns the first homology group of the * boundary for this triangulation. * Note that ideal vertices are considered part of the boundary. * * Bear in mind that each time the triangulation changes, the * homology groups will be deleted. Thus the reference that is * returned from this routine should not be kept for later use. * Instead, getHomologyH1Bdry() should be called again; this will be * instantaneous if the group has already been calculated. * * This routine is fairly fast, since it deduces the homology of * each boundary component through knowing what kind of surface * it is. * * \pre This triangulation is valid. * * @return the first homology group of the boundary. */ const NAbelianGroup& getHomologyH1Bdry() const; /** * Returns the second homology group for this triangulation. * If this triangulation contains any ideal vertices, * the homology group will be * calculated as if each such vertex had been truncated. * The algorithm used calculates various first homology groups * and uses homology and cohomology theorems to deduce the * second homology group. * * Bear in mind that each time the triangulation changes, the * homology groups will be deleted. Thus the reference that is * returned from this routine should not be kept for later use. * Instead, getHomologyH2() should be called again; this will be * instantaneous if the group has already been calculated. * * \pre This triangulation is valid. * * @return the second homology group. */ const NAbelianGroup& getHomologyH2() const; /** * Returns the second homology group with coefficients in Z_2 * for this triangulation. * If this triangulation contains any ideal vertices, * the homology group will be * calculated as if each such vertex had been truncated. * The algorithm used calculates the relative first homology group * with respect to the boundary and uses homology and cohomology * theorems to deduce the second homology group. * * This group will simply be the direct sum of several copies of * Z_2, so the number of Z_2 terms is returned. * * \pre This triangulation is valid. * * @return the number of Z_2 terms in the second homology group * with coefficients in Z_2. */ unsigned long getHomologyH2Z2() const; /** * Computes the Turaev-Viro state sum invariant of this * 3-manifold based upon the given initial data. * * The initial data is as described in the paper of Turaev and * Viro, "State sum invariants of 3-manifolds and quantum * 6j-symbols", Topology, vol. 31, no. 4, 1992, pp 865-902. * * In particular, Section 7 describes the initial data as * determined by an integer r >=3 and a root of unity q0 of * degree 2r for which q0^2 is a primitive root of unity of * degree r. * * These invariants, although computed in the complex field, * should all be reals. Thus the return type is an ordinary * double. * * \pre This triangulation is valid, closed and non-empty. * * @param r the integer r as described above; this must be at * least 3. * @param whichRoot determines q0 to be the root of unity * e^(2i * Pi * whichRoot / 2r); this argument must be strictly * between 0 and 2r and must have no common factors with r. * @return the requested Turaev-Viro invariant. * * @see allCalculatedTuraevViro */ double turaevViro(unsigned long r, unsigned long whichRoot) const; /** * Returns the set of all Turaev-Viro state sum invariants that * have already been calculated for this 3-manifold. * * Turaev-Viro invariants are described by an (r, whichRoot) * pair as described in the turaevViro() notes. The set * returned by this routine maps (r, whichRoot) pairs to the * corresponding invariant values. * * Each time turaevViro() is called, the result will be stored * in this set (as well as being returned to the user). This * set will be emptied whenever the triangulation is modified. * * \ifacespython Not present. * * @return the set of all Turaev-Viro invariants that have * already been calculated. * * @see turaevViro */ const TuraevViroSet& allCalculatedTuraevViro() const; /*@}*/ /** * \name Normal Surfaces and Angle Structures */ /*@{*/ /** * Determines if this triangulation is 0-efficient. * A triangulation is 0-efficient if its only normal spheres and * discs are vertex linking, and if it has no 2-sphere boundary * components. * * @return \c true if and only if this triangulation is * 0-efficient. */ bool isZeroEfficient(); /** * Is it already known whether or not this triangulation is * 0-efficient? * See isZeroEfficient() for further details. * * If this property is already known, future calls to * isZeroEfficient() will be very fast (simply returning the * precalculated value). * * \warning This routine does not actually tell you \e whether * this triangulation is 0-efficient; it merely tells you whether * the answer has already been computed. * * @return \c true if and only if this property is already known. */ bool knowsZeroEfficient() const; /** * Determines whether this triangulation has a normal splitting * surface. See NNormalSurface::isSplitting() for details * regarding normal splitting surfaces. * * \pre This triangulation is connected. If the triangulation * is not connected, this routine will still return a result but * that result will be unreliable. * * @return \c true if and only if this triangulation has a * normal splitting surface. */ bool hasSplittingSurface(); /** * Is it already known whether or not this triangulation has a * splitting surface? * See hasSplittingSurface() for further details. * * If this property is already known, future calls to * hasSplittingSurface() will be very fast (simply returning the * precalculated value). * * \warning This routine does not actually tell you \e whether * this triangulation has a splitting surface; it merely tells you * whether the answer has already been computed. * * @return \c true if and only if this property is already known. */ bool knowsSplittingSurface() const; /** * Searches for a non-vertex-linking normal sphere or disc * within this triangulation. If such a surface exists within * this triangulation, this routine is guaranteed to find one. * * Note that the surface returned (if any) depends upon this * triangulation, and so the surface must be destroyed before this * triangulation is destroyed. * * \warning This routine may, in some scenarios, temporarily modify the * packet tree by creating and then destroying a normal surface list. * * @return a newly allocated non-vertex-linking normal sphere or * disc, or 0 if none exists. */ NNormalSurface* hasNonTrivialSphereOrDisc(); /** * Searches for an octagonal almost normal 2-sphere within this * triangulation. If such a surface exists, this routine is * guaranteed to find one. * * Note that the surface returned (if any) depends upon this * triangulation, and so the surface must be destroyed before this * triangulation is destroyed. * * \pre This triangulation is valid, closed, orientable, connected, * and 0-efficient. These preconditions are almost certainly more * restrictive than they need to be, but we stay safe for now. * * \warning This routine may, in some scenarios, temporarily modify the * packet tree by creating and then destroying a normal surface list. * * @return a newly allocated non-vertex-linking normal sphere or * disc, or 0 if none exists. */ NNormalSurface* hasOctagonalAlmostNormalSphere(); /** * Searches for a strict angle structure on this triangulation. * Recall that a \e strict angle structure is one in which every * angle is strictly between 0 and π. If a strict angle structure * does exist, then this routine is guaranteed to find one. * * The underlying algorithm runs a single linear program (it does * \e not enumerate all vertex angle structures). This means * that it is likely to be fast even for large triangulations. * * If you are only interested in \e whether a strict angle structure * exists (i.e., you are not interested in the specific angles * themselves), then you may call hasStrictAngleStructure() instead. * * The angle structure returned (if any) is cached internally * alongside this triangulation. This means that, as long as * the triangulation does not change, subsequent calls to * findStrictAngleStructure() will return identical pointers * and will be essentially instantaneous. * * If the triangulation changes however, then the cached angle * structure will be deleted. This means that you should not * store the returned pointer for later use; instead you should * just call findStrictAngleStructure() again. * * @return a strict angle structure on this triangulation, or 0 if * none exists. */ const NAngleStructure* findStrictAngleStructure() const; /** * Determines whether this triangulation supports a strict angle * structure. Recall that a \e strict angle structure is one * in which every angle is strictly between 0 and π. * * This routine is equivalent to calling findStrictAngleStructure() * and testing whether the return value is non-null. * * The underlying algorithm runs a single linear program (it does * \e not enumerate all vertex angle structures). This means * that it is likely to be fast even for large triangulations. * * @return \c true if a strict angle structure exists on this * triangulation, or 0 if not. */ bool hasStrictAngleStructure() const; /** * Is it already known (or trivial to determine) whether or not * this triangulation supports a strict angle structure? * See hasStrictAngleStructure() for further details. * * If this property is indeed already known, future calls to * findStrictAngleStructure() and hasStrictAngleStructure() will be * very fast (simply returning the precalculated solution). * * \warning This routine does not actually tell you \e whether * the triangulation supports a strict angle structure; it merely * tells you whether the answer has already been computed (or is * very easily computed). * * @return \c true if and only if this property is already known * or trivial to calculate. */ bool knowsStrictAngleStructure() const; /*@}*/ /** * \name Skeletal Transformations */ /*@{*/ /** * Produces a maximal forest in the 1-skeleton of the * triangulation boundary. * Both given sets will be emptied and the edges and vertices of * the maximal forest will be placed into them. * A vertex that forms its own boundary component (such as an * ideal vertex) will still be placed in \c vertexSet. * * Note that the edge and vertex pointers returned will become * invalid once the triangulation has changed. * * \ifacespython Not present. * * @param edgeSet the set to be emptied and into which the edges * of the maximal forest will be placed. * @param vertexSet the set to be emptied and into which the * vertices of the maximal forest will be placed. */ void maximalForestInBoundary(std::set& edgeSet, std::set& vertexSet) const; /** * Produces a maximal forest in the triangulation's 1-skeleton. * The given set will be emptied and will have the edges of the * maximal forest placed into it. It can be specified whether * or not different boundary components may be joined by the * maximal forest. * * An edge leading to an ideal vertex is still a * candidate for inclusion in the maximal forest. For the * purposes of this algorithm, any ideal vertex will be treated * as any other vertex (and will still be considered part of its * own boundary component). * * Note that the edge pointers returned will become * invalid once the triangulation has changed. * * \ifacespython Not present. * * @param edgeSet the set to be emptied and into which the edges * of the maximal forest will be placed. * @param canJoinBoundaries \c true if and only if different * boundary components are allowed to be joined by the maximal * forest. */ void maximalForestInSkeleton(std::set& edgeSet, bool canJoinBoundaries = true) const; /** * Produces a maximal forest in the triangulation's dual * 1-skeleton. The given set will be emptied and will have the * triangles corresponding to the edges of the maximal forest in the * dual 1-skeleton placed into it. * * Note that the triangle pointers returned will become invalid once * the triangulation has changed. * * \ifacespython This routine takes no arguments. Instead it * returns the maximal forest as a Python list of NTriangle * objects, sorted by triangle index. * * @param triangleSet the set to be emptied and into which the * triangles representing the maximal forest will be placed. */ void maximalForestInDualSkeleton(std::set& triangleSet) const; /** * Attempts to simplify the triangulation as intelligently as * possible without further input. This routine will attempt to * reduce both the number of tetrahedra and the number of boundary * triangles (with the number of tetrahedra as its priority). * * Currently this routine uses simplifyToLocalMinimum() in * combination with random 4-4 moves, book opening moves and * book closing moves. * * \warning The specific behaviour of this routine may well * change between releases. * * \todo \opt Include random 2-3 moves to get out of wells. * * @return \c true if and only if the triangulation was changed. */ bool intelligentSimplify(); /** * Uses all known simplification moves to reduce the triangulation * monotonically to some local minimum number of tetrahedra. * Note that this will probably not give a globally minimal * triangulation; see intelligentSimplify() for further * assistance in achieving this goal. * * The moves used include 3-2, 2-0 (edge and vertex), * 2-1 and boundary shelling moves. * * Note that moves that do not reduce the number of tetrahedra * (such as 4-4 moves or book opening moves) are not used in this * routine. Such moves do however feature in intelligentSimplify(). * * \warning The specific behaviour of this routine is * very likely to change between releases. * * @param perform \c true if we are to perform the * simplifications, or \c false if we are only to investigate * whether simplifications are possible (defaults to \c true). * @return if \a perform is \c true, this routine returns * \c true if and only if the triangulation was changed to * reduce the number of tetrahedra; if \a perform is \c false, * this routine returns \c true if and only if it determines * that it is capable of performing such a change. */ bool simplifyToLocalMinimum(bool perform = true); /** * Checks the eligibility of and/or performs a 3-2 move * about the given edge. * This involves replacing the three tetrahedra joined at that * edge with two tetrahedra joined by a triangle. * This can be done iff (i) the edge is valid and non-boundary, * and (ii) the three tetrahedra are distinct. * * If the routine is asked to both check and perform, the move * will only be performed if the check shows it is legal. * * Note that after performing this move, all skeletal objects * (triangles, components, etc.) will be reconstructed, which means * any pointers to old skeletal objects (such as the argument \a e) * can no longer be used. * * \pre If the move is being performed and no * check is being run, it must be known in advance that the move * is legal. * \pre The given edge is an edge of this triangulation. * * @param e the edge about which to perform the move. * @param check \c true if we are to check whether the move is * allowed (defaults to \c true). * @param perform \c true if we are to perform the move * (defaults to \c true). * @return If \a check is \c true, the function returns \c true * if and only if the requested move may be performed * without changing the topology of the manifold. If \a check * is \c false, the function simply returns \c true. */ bool threeTwoMove(NEdge* e, bool check = true, bool perform = true); /** * Checks the eligibility of and/or performs a 2-3 move * about the given triangle. * This involves replacing the two tetrahedra joined at that * triangle with three tetrahedra joined by an edge. * This can be done iff the two tetrahedra are distinct. * * If the routine is asked to both check and perform, the move * will only be performed if the check shows it is legal. * * Note that after performing this move, all skeletal objects * (triangles, components, etc.) will be reconstructed, which means * any pointers to old skeletal objects (such as the argument \a f) * can no longer be used. * * \pre If the move is being performed and no * check is being run, it must be known in advance that the move * is legal. * \pre The given triangle is a triangle of this triangulation. * * @param t the triangle about which to perform the move. * @param check \c true if we are to check whether the move is * allowed (defaults to \c true). * @param perform \c true if we are to perform the move * (defaults to \c true). * @return If \a check is \c true, the function returns \c true * if and only if the requested move may be performed * without changing the topology of the manifold. If \a check * is \c false, the function simply returns \c true. */ bool twoThreeMove(NTriangle* t, bool check = true, bool perform = true); /** * Checks the eligibility of and/or performs a 1-4 move * upon the given tetrahedron. * This involves replacing one tetrahedron with four tetrahedra: * each new tetrahedron runs from one face of * the original tetrahedron to a new common internal degree four vertex. * * This move can always be performed. The \a check argument is * present (as for other moves), but is simply ignored (since * the move is always legal). The \a perform argument is also * present for consistency with other moves, but if it is set to * \c false then this routine does nothing and returns no useful * information. * * Note that after performing this move, all skeletal objects * (edges, components, etc.) will be reconstructed, which means * any pointers to old skeletal objects (such as the argument \a t) * can no longer be used. * * \pre The given tetrahedron is a tetrahedron of this triangulation. * * @param t the tetrahedron about which to perform the move. * @param check this argument is ignored, since this move is * always legal (see the notes above). * @param perform \c true if we are to perform the move * (defaults to \c true). * @return \c true always. */ bool oneFourMove(NTetrahedron* t, bool check = true, bool perform = true); /** * Checks the eligibility of and/or performs a 4-4 move * about the given edge. * This involves replacing the four tetrahedra joined at that * edge with four tetrahedra joined along a different edge. * Consider the octahedron made up of the four original * tetrahedra; this has three internal axes. The initial four * tetrahedra meet along the given edge which forms one of these * axes; the new tetrahedra will meet along a different axis. * This move can be done iff (i) the edge is valid and non-boundary, * and (ii) the four tetrahedra are distinct. * * If the routine is asked to both check and perform, the move * will only be performed if the check shows it is legal. * * Note that after performing this move, all skeletal objects * (triangles, components, etc.) will be reconstructed, which means * any pointers to old skeletal objects (such as the argument \a e) * can no longer be used. * * \pre If the move is being performed and no * check is being run, it must be known in advance that the move * is legal. * \pre The given edge is an edge of this triangulation. * * @param e the edge about which to perform the move. * @param newAxis Specifies which axis of the octahedron the new * tetrahedra should meet along; this should be 0 or 1. * Consider the four original tetrahedra in the order described * by NEdge::getEmbeddings(); call these tetrahedra 0, 1, 2 and * 3. If \a newAxis is 0, the new axis will separate tetrahedra * 0 and 1 from 2 and 3. If \a newAxis is 1, the new axis will * separate tetrahedra 1 and 2 from 3 and 0. * @param check \c true if we are to check whether the move is * allowed (defaults to \c true). * @param perform \c true if we are to perform the move * (defaults to \c true). * @return If \a check is \c true, the function returns \c true * if and only if the requested move may be performed * without changing the topology of the manifold. If \a check * is \c false, the function simply returns \c true. */ bool fourFourMove(NEdge* e, int newAxis, bool check = true, bool perform = true); /** * Checks the eligibility of and/or performs a 2-0 move * about the given edge of degree 2. * This involves taking the two tetrahedra joined at that edge * and squashing them flat. This can be done if: * * - the edge is valid and non-boundary; * * - the two tetrahedra are distinct; * * - the edges opposite \c e in each tetrahedron are distinct and * not both boundary; * * - if triangles \a f1 and \a f2 from one tetrahedron are to be * flattened onto triangles \a g1 and \a g2 of the other * respectively, then * (a) \a f1 and \a g1 are distinct, * (b) \a f2 and \a g2 are distinct, * (c) we do not have both \a f1 = \a g2 and \a g1 = \a f2, * (d) we do not have both \a f1 = \a f2 and \a g1 = \a g2, and * (e) we do not have two of the triangles boundary and the other * two identified. * * If the routine is asked to both check and perform, the move * will only be performed if the check shows it is legal. * * Note that after performing this move, all skeletal objects * (triangles, components, etc.) will be reconstructed, which means * any pointers to old skeletal objects (such as the argument \a e) * can no longer be used. * * \pre If the move is being performed and no * check is being run, it must be known in advance that the move * is legal. * \pre The given edge is an edge of this triangulation. * * @param e the edge about which to perform the move. * @param check \c true if we are to check whether the move is * allowed (defaults to \c true). * @param perform \c true if we are to perform the move * (defaults to \c true). * @return If \a check is \c true, the function returns \c true * if and only if the requested move may be performed * without changing the topology of the manifold. If \a check * is \c false, the function simply returns \c true. */ bool twoZeroMove(NEdge* e, bool check = true, bool perform = true); /** * Checks the eligibility of and/or performs a 2-0 move * about the given vertex of degree 2. * This involves taking the two tetrahedra joined at that vertex * and squashing them flat. * This can be done if: * * - the vertex is non-boundary and has a 2-sphere vertex link; * * - the two tetrahedra are distinct; * * - the triangles opposite \c v in each tetrahedron are distinct and * not both boundary; * * - the two tetrahedra meet each other on all three faces touching * the vertex (as opposed to meeting each other on one face and * being glued to themselves along the other two). * * If the routine is asked to both check and perform, the move * will only be performed if the check shows it is legal. * * Note that after performing this move, all skeletal objects * (triangles, components, etc.) will be reconstructed, which means * any pointers to old skeletal objects (such as the argument \a v) * can no longer be used. * * \pre If the move is being performed and no * check is being run, it must be known in advance that the move * is legal. * \pre The given vertex is a vertex of this triangulation. * * @param v the vertex about which to perform the move. * @param check \c true if we are to check whether the move is * allowed (defaults to \c true). * @param perform \c true if we are to perform the move * (defaults to \c true). * @return If \a check is \c true, the function returns \c true * if and only if the requested move may be performed * without changing the topology of the manifold. If \a check * is \c false, the function simply returns \c true. */ bool twoZeroMove(NVertex* v, bool check = true, bool perform = true); /** * Checks the eligibility of and/or performs a 2-1 move * about the given edge. * This involves taking an edge meeting only one tetrahedron * just once and merging that tetrahedron with one of the * tetrahedra joining it. * * This can be done assuming the following conditions: * * - The edge must be valid and non-boundary. * * - The two remaining faces of the tetrahedron are not joined, and * the tetrahedron face opposite the given endpoint of the edge is * not boundary. * * - Consider the second tetrahedron to be merged (the one * joined along the face opposite the given endpoint of the edge). * Moreover, consider the two edges of this second tetrahedron * that run from the (identical) vertices of the original * tetrahedron not touching \c e to the vertex of the second * tetrahedron not touching the original tetrahedron. These edges * must be distinct and may not both be in the boundary. * * There are additional "distinct and not both boundary" conditions * on faces of the second tetrahedron, but those follow automatically * from the final condition above. * * If the routine is asked to both check and perform, the move * will only be performed if the check shows it is legal. * * Note that after performing this move, all skeletal objects * (triangles, components, etc.) will be reconstructed, which means * any pointers to old skeletal objects (such as the argument \a e) * can no longer be used. * * \pre If the move is being performed and no * check is being run, it must be known in advance that the move * is legal. * \pre The given edge is an edge of this triangulation. * * @param e the edge about which to perform the move. * @param edgeEnd the end of the edge \e opposite that at * which the second tetrahedron (to be merged) is joined. * The end is 0 or 1, corresponding to the labelling (0,1) of * the vertices of the edge as described in * NEdgeEmbedding::getVertices(). * @param check \c true if we are to check whether the move is * allowed (defaults to \c true). * @param perform \c true if we are to perform the move * (defaults to \c true). * @return If \a check is \c true, the function returns \c true * if and only if the requested move may be performed * without changing the topology of the manifold. If \a check * is \c false, the function simply returns \c true. */ bool twoOneMove(NEdge* e, int edgeEnd, bool check = true, bool perform = true); /** * Checks the eligibility of and/or performs a book opening move * about the given triangle. * This involves taking a triangle meeting the boundary along two * edges, and ungluing it to create two new boundary triangles * (thus exposing the tetrahedra it initially joined). * This move is the inverse of the closeBook() move, and is * used to open the way for new shellBoundary() moves. * * This move can be done if: * * - the triangle meets the boundary in precisely two edges (and thus * also joins two tetrahedra); * * - the vertex between these two edges is a standard boundary * vertex (its link is a disc); * * - the remaining edge of the triangle (which is internal to the * triangulation) is valid. * * If the routine is asked to both check and perform, the move * will only be performed if the check shows it is legal. * * Note that after performing this move, all skeletal objects * (triangles, components, etc.) will be reconstructed, which means * any pointers to old skeletal objects (such as the argument \a f) * can no longer be used. * * \pre If the move is being performed and no * check is being run, it must be known in advance that the move * is legal. * \pre The given triangle is a triangle of this triangulation. * * @param t the triangle about which to perform the move. * @param check \c true if we are to check whether the move is * allowed (defaults to \c true). * @param perform \c true if we are to perform the move * (defaults to \c true). * @return If \a check is \c true, the function returns \c true * if and only if the requested move may be performed * without changing the topology of the manifold. If \a check * is \c false, the function simply returns \c true. */ bool openBook(NTriangle* t, bool check = true, bool perform = true); /** * Checks the eligibility of and/or performs a book closing move * about the given boundary edge. * This involves taking a boundary edge of the triangulation and * folding together the two boundary triangles on either side. This * move is the inverse of the openBook() move, and is used to * simplify the boundary of the triangulation. * This move can be done if: * * - the edge \a e is a boundary edge; * * - the two boundary triangles that it joins are distinct; * * - the two vertices opposite \a e in each of these boundary triangles * are valid and distinct; * * - if edges \a e1 and \a e2 of one boundary triangle are to be * folded onto edges \a f1 and \a f2 of the other boundary * triangle respectively, then we do not have both \a e1 = \a e2 * and \a f1 = \a f2. * * There are in fact several other "distinctness" conditions on * the edges \a e1, \a e2, \a f1 and \a f2, but they follow * automatically from the "distinct vertices" condition above. * * If the routine is asked to both check and perform, the move * will only be performed if the check shows it is legal. * * Note that after performing this move, all skeletal objects * (triangles, components, etc.) will be reconstructed, which means * any pointers to old skeletal objects (such as the argument \a f) * can no longer be used. * * \pre If the move is being performed and no * check is being run, it must be known in advance that the move * is legal. * \pre The given edge is an edge of this triangulation. * * @param e the edge about which to perform the move. * @param check \c true if we are to check whether the move is * allowed (defaults to \c true). * @param perform \c true if we are to perform the move * (defaults to \c true). * @return If \a check is \c true, the function returns \c true * if and only if the requested move may be performed * without changing the topology of the manifold. If \a check * is \c false, the function simply returns \c true. */ bool closeBook(NEdge* e, bool check = true, bool perform = true); /** * Checks the eligibility of and/or performs a boundary shelling * move on the given tetrahedron. * This involves simply popping off a tetrahedron that touches * the boundary. * This can be done if: * * - all edges of the tetrahedron are valid; * * - precisely one, two or three faces of the tetrahedron lie in * the boundary; * * - if one face lies in the boundary, then the opposite vertex * does not lie in the boundary, and no two of the remaining three * edges are identified; * * - if two faces lie in the boundary, then the remaining edge does * not lie in the boundary, and the remaining two faces of the * tetrahedron are not identified. * * If the routine is asked to both check and perform, the move * will only be performed if the check shows it is legal. * * Note that after performing this move, all skeletal objects * (triangles, components, etc.) will be reconstructed, which means * any pointers to old skeletal objects can no longer be used. * * \pre If the move is being performed and no * check is being run, it must be known in advance that the move * is legal. * \pre The given tetrahedron is a tetrahedron of this triangulation. * * @param t the tetrahedron upon which to perform the move. * @param check \c true if we are to check whether the move is * allowed (defaults to \c true). * @param perform \c true if we are to perform the move * (defaults to \c true). * @return If \a check is \c true, the function returns \c true * if and only if the requested move may be performed * without changing the topology of the manifold. If \a check * is \c false, the function simply returns \c true. */ bool shellBoundary(NTetrahedron* t, bool check = true, bool perform = true); /** * Checks the eligibility of and/or performs a collapse of * an edge in such a way that the topology of the manifold * does not change and the number of vertices of the triangulation * decreases by one. * * If the routine is asked to both check and perform, the move * will only be performed if the check shows it is legal. * * Note that after performing this move, all skeletal objects * (triangles, components, etc.) will be reconstructed, which means * any pointers to old skeletal objects (such as the argument \a e) * can no longer be used. * * The eligibility requirements for this move are somewhat * involved, and are discussed in detail in the collapseEdge() * source code for those who are interested. * * \pre If the move is being performed and no check is being run, * it must be known in advance that the move is legal. * \pre The given edge is an edge of this triangulation. * * @param e the edge to collapse. * @param check \c true if we are to check whether the move is * allowed (defaults to \c true). * @param perform \c true if we are to perform the move * (defaults to \c true). * @return If \a check is \c true, the function returns \c true * if and only if the given edge may be collapsed * without changing the topology of the manifold. If \a check * is \c false, the function simply returns \c true. */ bool collapseEdge(NEdge* e, bool check = true, bool perform = true); /** * Reorders the tetrahedra of this triangulation using a * breadth-first search, so that small-numbered tetrahedra are * adjacent to other small-numbered tetrahedra. * * Specifically, the reordering will operate as follows. * Tetrahedron 0 will remain tetrahedron 0. Its immediate * neighbours will be numbered 1, 2, 3 and 4 (though if these * neighbours are not distinct then of course fewer labels will * be required). Their immediate neighbours will in turn be * numbered 5, 6, and so on, ultimately following a breadth-first * search throughout the entire triangulation. * * If the optional argument \a reverse is \c true, then tetrahedron * numbers will be assigned in reverse order. That is, tetrahedron 0 * will become tetrahedron \a n-1, its neighbours will become * tetrahedra \a n-2 down to \a n-5, and so on. * * @param reverse \c true if the new tetrahedron numbers should * be assigned in reverse order, as described above. */ void reorderTetrahedraBFS(bool reverse = false); /** * Relabels tetrahedron vertices in this triangulation so that * all tetrahedra are oriented consistently, if possible. * * This routine works by flipping vertices 2 and 3 of each * tetrahedron with negative orientation. The result will be a * triangulation where the tetrahedron vertices are labelled in * a way that preserves orientation across adjacent tetrahedron faces. * In particular, every gluing permutation will have negative sign. * * If this triangulation includes both orientable and * non-orientable components, the orientable components will be * oriented as described above and the non-orientable * components will be left untouched. * * @author Matthias Goerner */ void orient(); /** * Relabels tetrahedron vertices in this triangulation to give * an ordered triangulation, if possible. * * To be an ordered triangulation, all face gluings (when restricted * to the tetrahedron face) must be order preserving. In other words, * it must be possible to orient all edges of the triangulation in * such a fashion that they are consistent with the ordering of the * vertices in each tetrahedron. * * If it is possible to order this triangulation, the vertices * of each tetrahedron will be relabelled accordingly and this * routine will return \c true. Otherwise, this routine will * return \c false and the triangulation will not be changed. * * \warning This routine may be slow, since it backtracks * through all possible edge orientations until a consistent one * has been found. * * @param forceOriented \c true if the triangulation must be * both ordered and \e oriented, in which case this routine will * return \c false if the triangulation cannot be oriented and * ordered at the same time. See orient() for further details. * @return \c true if the triangulation has been successfully ordered * as described above, or \c false if not. * * @author Matthias Goerner */ bool order(bool forceOriented = false); /*@}*/ /** * \name Decompositions */ /*@{*/ /** * Splits a disconnected triangulation into many smaller * triangulations, one for each component. The new component * triangulations will be inserted as children of the given * parent packet. The original triangulation will be left * unchanged. * * If the given parent packet is 0, the new component * triangulations will be inserted as children of this * triangulation. * * This routine can optionally assign unique (and sensible) * packet labels to each of the new component triangulations. * Note however that uniqueness testing may be slow, so this * assignment of labels should be disabled if the component * triangulations are only temporary objects used as part * of a larger routine. * * @param componentParent the packet beneath which the new * component triangulations will be inserted, or 0 if they * should be inserted directly beneath this triangulation. * @param setLabels \c true if the new component triangulations * should be assigned unique packet labels, or \c false if * they should be left without labels at all. * @return the number of new component triangulations * constructed. */ unsigned long splitIntoComponents(NPacket* componentParent = 0, bool setLabels = true); /** * Splits this triangulation into its connected sum * decomposition. The individual prime 3-manifold triangulations * that make up this decomposition will be inserted as children * of the given parent packet. The original triangulation will * be left unchanged. * * For non-orientable triangulations, this routine is only guaranteed * to succeed if the original manifold contains no embedded two-sided * projective planes. If the manifold \e does contain embedded * two-sided projective planes, then this routine might still succeed * but it might fail; however, such a failure will always be detected, * and in such a case this routine will return -1 instead (without * building any prime summands at all). * * Note that this routine is currently only available for closed * triangulations; see the list of preconditions for full details. * * If the given parent packet is 0, the new prime summand * triangulations will be inserted as children of this triangulation. * * This routine can optionally assign unique (and sensible) * packet labels to each of the new prime summand triangulations. * Note however that uniqueness testing may be slow, so this * assignment of labels should be disabled if the summand * triangulations are only temporary objects used as part * of a larger routine. * * If this is a triangulation of a 3-sphere then no prime summand * triangulations will be created at all, and this routine will * return 0. * * The underlying algorithm appears in "A new approach to crushing * 3-manifold triangulations", Discrete and Computational * Geometry 52:1 (2014), pp. 116-139. This algorithm is based on the * Jaco-Rubinstein 0-efficiency algorithm, and works in both * orientable and non-orientable settings. * * \warning Users are strongly advised to check the return value if * embedded two-sided projective planes are a possibility, since in * such a case this routine might fail (as explained above). * Note however that this routine might still succeed, and so success * is not a proof that no embedded two-sided projective planes exist. * * \warning The algorithms used in this routine rely on normal * surface theory and so can be very slow for larger triangulations. * For 3-sphere testing, see the routine isThreeSphere() which * uses faster methods where possible. * * \pre This triangulation is valid, closed and connected. * * @param primeParent the packet beneath which the new prime * summand triangulations will be inserted, or 0 if they * should be inserted directly beneath this triangulation. * @param setLabels \c true if the new prime summand triangulations * should be assigned unique packet labels, or \c false if * they should be left without labels at all. * @return the number of prime summands created, 0 if this * triangulation is a 3-sphere, or -1 if this routine failed * because this is a non-orientable triangulation with embedded * two-sided projective planes. */ long connectedSumDecomposition(NPacket* primeParent = 0, bool setLabels = true); /** * Determines whether this is a triangulation of a 3-sphere. * * This routine relies upon a combination of Rubinstein's 3-sphere * recognition algorithm and Jaco and Rubinstein's 0-efficiency * prime decomposition algorithm. * * \warning The algorithms used in this routine rely on normal * surface theory and so can be very slow for larger * triangulations (although faster tests are used where possible). * The routine knowsThreeSphere() can be called to see if this * property is already known or if it happens to be very fast to * calculate for this triangulation. * * @return \c true if and only if this is a 3-sphere triangulation. */ bool isThreeSphere() const; /** * Is it already known (or trivial to determine) whether or not this * is a triangulation of a 3-sphere? See isThreeSphere() for * further details. * * If this property is indeed already known, future calls to * isThreeSphere() will be very fast (simply returning the * precalculated value). * * If this property is not already known, this routine will * nevertheless run some very fast preliminary tests to see if the * answer is obviously no. If so, it will store \c false as the * precalculated value for isThreeSphere() and this routine will * return \c true. * * Otherwise a call to isThreeSphere() may potentially require more * significant work, and so this routine will return \c false. * * \warning This routine does not actually tell you \e whether * this triangulation forms a 3-sphere; it merely tells you whether * the answer has already been computed (or is very easily computed). * * @return \c true if and only if this property is already known * or trivial to calculate. */ bool knowsThreeSphere() const; /** * Determines whether this is a triangulation of a 3-dimensional ball. * * This routine is based on isThreeSphere(), which in turn combines * Rubinstein's 3-sphere recognition algorithm with Jaco and * Rubinstein's 0-efficiency prime decomposition algorithm. * * \warning The algorithms used in this routine rely on normal * surface theory and so can be very slow for larger * triangulations (although faster tests are used where possible). * The routine knowsBall() can be called to see if this * property is already known or if it happens to be very fast to * calculate for this triangulation. * * @return \c true if and only if this is a triangulation of a * 3-dimensional ball. */ bool isBall() const; /** * Is it already known (or trivial to determine) whether or not this * is a triangulation of a 3-dimensional ball? See isBall() for * further details. * * If this property is indeed already known, future calls to isBall() * will be very fast (simply returning the precalculated value). * * If this property is not already known, this routine will * nevertheless run some very fast preliminary tests to see if the * answer is obviously no. If so, it will store \c false as the * precalculated value for isBall() and this routine will * return \c true. * * Otherwise a call to isBall() may potentially require more * significant work, and so this routine will return \c false. * * \warning This routine does not actually tell you \e whether * this triangulation forms a ball; it merely tells you whether * the answer has already been computed (or is very easily computed). * * @return \c true if and only if this property is already known * or trivial to calculate. */ bool knowsBall() const; /** * Converts this into a 0-efficient triangulation of the same * underlying 3-manifold. A triangulation is 0-efficient if its * only normal spheres and discs are vertex linking, and if it has * no 2-sphere boundary components. * * Note that this routine is currently only available for * closed orientable triangulations; see the list of * preconditions for details. The 0-efficiency algorithm of * Jaco and Rubinstein is used. * * If the underlying 3-manifold is prime, it can always be made * 0-efficient (with the exception of the special cases RP3 and * S2xS1 as noted below). In this case the original triangulation * will be modified directly and 0 will be returned. * * If the underyling 3-manifold is RP3 or S2xS1, it cannot * be made 0-efficient; in this case the original triangulation * will be reduced to a two-tetrahedron minimal triangulation * and 0 will again be returned. * * If the underlying 3-manifold is not prime, it cannot be made * 0-efficient. In this case the original triangulation will * remain unchanged and a new connected sum decomposition will * be returned. This will be presented as a newly allocated * container packet with one child triangulation for each prime * summand. * * \warning The algorithms used in this routine rely on normal * surface theory and so can be very slow for larger triangulations. * * \pre This triangulation is valid, closed, orientable and * connected. * * @return 0 if the underlying 3-manifold is prime (in which * case the original triangulation was modified directly), or * a newly allocated connected sum decomposition if the * underlying 3-manifold is composite (in which case the * original triangulation was not changed). */ NPacket* makeZeroEfficient(); /** * Determines whether this is a triangulation of the solid * torus; that is, the unknot complement. This routine can be * used on a triangulation with real boundary triangles, or on an * ideal triangulation (in which case all ideal vertices will * be assumed to be truncated). * * \warning The algorithms used in this routine rely on normal * surface theory and so might be very slow for larger * triangulations (although faster tests are used where possible). * The routine knowsSolidTorus() can be called to see if this * property is already known or if it happens to be very fast to * calculate for this triangulation. * * @return \c true if and only if this is either a real (compact) * or ideal (non-compact) triangulation of the solid torus. */ bool isSolidTorus() const; /** * Is it already known (or trivial to determine) whether or not this * is a triangulation of a solid torus (that is, the unknot * complement)? See isSolidTorus() for further details. * * If this property is indeed already known, future calls to * isSolidTorus() will be very fast (simply returning the * precalculated value). * * If this property is not already known, this routine will * nevertheless run some very fast preliminary tests to see if the * answer is obviously no. If so, it will store \c false as the * precalculated value for isSolidTorus() and this routine will * return \c true. * * Otherwise a call to isSolidTorus() may potentially require more * significant work, and so this routine will return \c false. * * \warning This routine does not actually tell you \e whether * this triangulation forms a solid torus; it merely tells you whether * the answer has already been computed (or is very easily computed). * * @return \c true if and only if this property is already known * or trivial to calculate. */ bool knowsSolidTorus() const; /** * Determines whether the underlying 3-manifold (which must be * closed) is irreducible. In other words, this routine determines * whether every embedded sphere in the underlying 3-manifold * bounds a ball. * * If the underlying 3-manifold is orientable, this routine will * use fast crushing and branch-and-bound methods. If the * underlying 3-manifold is non-orientable, it will use a * (much slower) full enumeration of vertex normal surfaces. * * \warning The algorithms used in this routine rely on normal * surface theory and might be slow for larger triangulations. * * \pre This triangulation is valid, closed, orientable and connected. * * @return \c true if and only if the underlying 3-manifold is * irreducible. */ bool isIrreducible() const; /** * Is it already known (or trivial to determine) whether or not the * underlying 3-manifold is irreducible? See isIrreducible() for * further details. * * If this property is indeed already known, future calls to * isIrreducible() will be very fast (simply returning the * precalculated value). * * \warning This routine does not actually tell you \e whether * the underlying 3-manifold is irreducible; it merely tells you whether * the answer has already been computed (or is very easily computed). * * \pre This triangulation is valid, closed, orientable and connected. * * @return \c true if and only if this property is already known * or trivial to calculate. */ bool knowsIrreducible() const; /** * Searches for a compressing disc within the underlying * 3-manifold. * * Let \a M be the underlying 3-manifold and let \a B be its * boundary. By a compressing disc, we mean a disc \a D * properly embedded in \a M, where the boundary of \a D * lies in \a B but does not bound a disc in \a B. * * This routine will first call the heuristic routine * hasSimpleCompressingDisc() in the hope of obtaining a fast * answer. If this fails, it will do one of two things: * * - If the triangulation is orientable and 1-vertex, it will * use the linear programming and crushing machinery outlined in * "Computing closed essential surfaces in knot complements", * Burton, Coward and Tillmann, SCG '13, p405-414, 2013. * This is often extremely fast, even for triangulations with * many tetrahedra. * * - If the triangulation is non-orientable or has multiple vertices * then it will run a full enumeration of * vertex normal surfaces, as described in "Algorithms for the * complete decomposition of a closed 3-manifold", * Jaco and Tollefson, Illinois J. Math. 39 (1995), 358-406. * As the number of tetrahedra grows, this can become extremely slow. * * This routine will work on a copy of this triangulation, not * the original. In particular, the copy will be simplified, which * means that there is no harm in calling this routine on an * unsimplified triangulation. * * If this triangulation has no boundary components, this * routine will simply return \c false. * * \pre This triangulation is valid and is not ideal. * \pre The underlying 3-manifold is irreducible. * * \warning This routine can be infeasibly slow for large * triangulations (particularly those that are non-orientable * or have multiple vertices), since it may need to perform a * full enumeration of vertex normal surfaces, and since it might * perform "large" operations on these surfaces such as cutting along * them. See hasSimpleCompressingDisc() for a "heuristic shortcut" * that is faster but might not give a definitive answer. * * @return \c true if the underlying 3-manifold contains a * compressing disc, or \c false if it does not. */ bool hasCompressingDisc() const; /** * Is it already known (or trivial to determine) whether or not * the underlying 3-manifold contains a compressing disc? * See hasCompressingDisc() for further details. * * If this property is indeed already known, future calls to * hasCompressingDisc() will be very fast (simply returning the * precalculated value). * * If this property is not already known, this routine will * nevertheless run some very fast preliminary tests to see if the * answer is obviously no. If so, it will store \c false as the * precalculated value for hasCompressingDisc() and this routine will * return \c true. * * Otherwise a call to hasCompressingDisc() may potentially require more * significant work, and so this routine will return \c false. * * \warning This routine does not actually tell you \e whether * the underlying 3-manifold has a compressing disc; it merely tells * you whether the answer has already been computed (or is very * easily computed). * * \pre This triangulation is valid and is not ideal. * \pre The underlying 3-manifold is irreducible. * * @return \c true if and only if this property is already known * or trivial to calculate. */ bool knowsCompressingDisc() const; /** * Determines whether the underlying 3-manifold (which * must be closed and orientable) is Haken. In other words, this * routine determines whether the underlying 3-manifold contains an * embedded closed two-sided incompressible surface. * * Currently Hakenness testing is available only for irreducible * manifolds. This routine will first test whether the manifold is * irreducible and, if it is not, will return \c false immediately. * * \pre This triangulation is valid, closed, orientable and connected. * * \warning This routine could be very slow for larger triangulations. * * @return \c true if and only if the underlying 3-manifold is * irreducible and Haken. */ bool isHaken() const; /** * Is it already known (or trivial to determine) whether or not the * underlying 3-manifold is Haken? See isHaken() for further details. * * If this property is indeed already known, future calls to * isHaken() will be very fast (simply returning the * precalculated value). * * \warning This routine does not actually tell you \e whether * the underlying 3-manifold is Haken; it merely tells you whether * the answer has already been computed (or is very easily computed). * * \pre This triangulation is valid, closed, orientable and connected. * * @return \c true if and only if this property is already known * or trivial to calculate. */ bool knowsHaken() const; /** * Searches for a "simple" compressing disc inside this * triangulation. * * Let \a M be the underlying 3-manifold and let \a B be its * boundary. By a compressing disc, we mean a disc \a D * properly embedded in \a M, where the boundary of \a D * lies in \a B but does not bound a disc in \a B. * * By a \a simple compressing disc, we mean a compressing disc * that has a very simple combinatorial structure (here "simple" * is subject to change; see the warning below). Examples * include the compressing disc inside a 1-tetrahedron solid * torus, or a compressing disc formed from a single internal triangle * surrounded by three boundary edges. * * The purpose of this routine is to avoid working with normal * surfaces within a large triangulation where possible. This * routine is relatively fast, and if it returns \c true then this * 3-manifold definitely contains a compressing disc. If this * routine returns \c false then there might or might not be a * compressing disc; the user will need to perform a full normal * surface enumeration using hasCompressingDisc() to be sure. * * This routine will work on a copy of this triangulation, not * the original. In particular, the copy will be simplified, which * means that there is no harm in calling this routine on an * unsimplified triangulation. * * If this triangulation has no boundary components, this * routine will simply return \c false. * * For further information on this test, see "The Weber-Seifert * dodecahedral space is non-Haken", Benjamin A. Burton, * J. Hyam Rubinstein and Stephan Tillmann, * Trans. Amer. Math. Soc. 364:2 (2012), pp. 911-932. * * \warning The definition of "simple" is subject to change in * future releases of Regina. That is, this routine may be * expanded over time to identify more types of compressing discs * (thus making it more useful as a "heuristic shortcut"). * * \pre This triangulation is valid and is not ideal. * * @return \c true if a simple compressing disc was found, * or \c false if not. Note that even with a return value of * \c false, there might still be a compressing disc (just not * one with a simple combinatorial structure). */ bool hasSimpleCompressingDisc() const; /*@}*/ /** * \name Subdivisions, Extensions and Covers */ /*@{*/ /** * Converts this triangulation into its double cover. * Each orientable component will be duplicated, and each * non-orientable component will be converted into its * orientable double cover. */ void makeDoubleCover(); /** * Converts an ideal triangulation into a finite triangulation. * All ideal or non-standard vertices are truncated and thus * converted into real boundary components made from unglued * faces of tetrahedra. * * Note that this operation is a loose converse of finiteToIdeal(). * * \warning Currently, this routine subdivides all tetrahedra as * if all vertices (not just some) were ideal. * This may lead to more tetrahedra than are necessary. * * \warning Currently, the presence of an invalid edge will force * the triangulation to be subdivided regardless of the value of * parameter \a forceDivision. The final triangulation will * still have the projective plane cusp caused by the invalid * edge. * * \todo \optlong Have this routine only use as many tetrahedra * as are necessary, leaving finite vertices alone. * * @param forceDivision specifies what to do if the triangulation * has no ideal or non-standard vertices. * If \c true, the triangulation will be * subdivided anyway, as if all vertices were ideal. If * \c false (the default), the triangulation will be left alone. * * @return \c true if and only if the triangulation was changed. * @author David Letscher */ bool idealToFinite(bool forceDivision = false); /** * Converts each real boundary component into a cusp (i.e., an ideal * vertex). Only boundary components formed from real * tetrahedron faces will be affected; ideal boundary components * are already cusps and so will not be changed. * * One side-effect of this operation is that all spherical * boundary components will be filled in with balls. * * This operation is performed by attaching a new tetrahedron to * each boundary triangle and then gluing these new tetrahedra * together in a way that mirrors the adjacencies of the * underlying boundary triangles. Each boundary component will * thereby be pushed up through the new tetrahedra and converted * into a cusp formed using vertices of these new tetrahedra. * * Note that this operation is a loose converse of idealToFinite(). * * \warning If a real boundary component contains vertices whose * links are not discs, this operation may have unexpected results. * * @return \c true if changes were made, or \c false if the * original triangulation contained no real boundary components. */ bool finiteToIdeal(); /** * Does a barycentric subdivision of the triangulation. * Each tetrahedron is divided into 24 tetrahedra by placing * an extra vertex at the centroid of each tetrahedron, the * centroid of each triangle and the midpoint of each edge. * * @author David Letscher */ void barycentricSubdivision(); /** * Drills out a regular neighbourhood of the given edge of the * triangulation. * * This is done by (i) performing two barycentric subdivisions, * (ii) removing all tetrahedra that touch the original edge, * and (iii) simplifying the resulting triangulation. * * \warning The second barycentric subdivision will multiply the * number of tetrahedra by 576; as a result this routine might * be slow, and the number of tetrahedra at the end might be * large (even taking the simplification into account). * * @param e the edge to drill out. */ void drillEdge(NEdge* e); /** * Punctures this manifold by removing a 3-ball from the interior of * the given tetrahedron. If no tetrahedron is specified (i.e., * the tetrahedron pointer is \c null), then the puncture will be * taken from the interior of tetrahedron 0. * * The puncture will not meet the boundary of the tetrahedron, * so nothing will go wrong if the tetrahedron has boundary facets * and/or ideal vertices. A side-effect of this, however, is * that the resulting triangulation will contain additional vertices, * and will almost certainly be far from minimal. * It is highly recommended that you run intelligentSimplify() * if you do not need to preserve the combinatorial structure of * the new triangulation. * * The puncturing is done by subdividing the original tetrahedron. * The new tetrahedra will have orientations consistent with the * original tetrahedra, so if the triangulation was originally oriented * then it will also be oriented after this routine has been called. * See isOriented() for further details on oriented triangulations. * * The new sphere boundary will be formed from two triangles; * specifically, face 0 of the last and second-last tetrahedra * of the triangulation. These two triangles will be joined so * that vertex 1 of each tetrahedron coincides, and vertices 2,3 * of one map to vertices 3,2 of the other. * * \pre This triangulation is non-empty, and if \c tet is non-null * then it is in fact a tetrahedron of this triangulation. * * @param tet the tetrahedron inside which the puncture will be * taken. This may be \c null (the default), in which case the * first tetrahedron will be used. */ void puncture(NTetrahedron* tet = 0); /*@}*/ /** * \name Building Triangulations */ /*@{*/ /** * Performs a layering upon the given boundary edge of the * triangulation. See the NLayering class notes for further * details on what a layering entails. * * \pre The given edge is a boundary edge of this triangulation, * and the two boundary triangles on either side of it are distinct. * * @param edge the boundary edge upon which to layer. * @return the new tetrahedron provided by the layering. */ NTetrahedron* layerOn(NEdge* edge); /** * Inserts a new layered solid torus into the triangulation. * The meridinal disc of the layered solid torus will intersect * the three edges of the boundary torus in \a cuts0, \a cuts1 * and (\a cuts0 + \a cuts1) points respectively. * * The boundary torus will always consist of faces 012 and 013 of the * tetrahedron containing this boundary torus (this tetrahedron will be * returned). In face 012, edges 12, 02 and 01 will meet the meridinal * disc \a cuts0, \a cuts1 and (\a cuts0 + \a cuts1) times respectively. * The only exceptions are if these three intersection numbers are * (1,1,2) or (0,1,1), in which case edges 12, 02 and 01 will meet the * meridinal disc (1, 2 and 1) or (1, 1 and 0) times respectively. * * The new tetrahedra will be inserted at the end of the list of * tetrahedra in the triangulation. * * \pre 0 \<= \a cuts0 \<= \a cuts1; * \pre \a cuts1 is non-zero; * \pre gcd(\a cuts0, \a cuts1) = 1. * * @param cuts0 the smallest of the three desired intersection numbers. * @param cuts1 the second smallest of the three desired intersection * numbers. * @return the tetrahedron containing the boundary torus. * * @see NLayeredSolidTorus */ NTetrahedron* insertLayeredSolidTorus(unsigned long cuts0, unsigned long cuts1); /** * Inserts a new layered lens space L(p,q) into the triangulation. * The lens space will be created by gluing together two layered * solid tori in a way that uses the fewest possible tetrahedra. * * The new tetrahedra will be inserted at the end of the list of * tetrahedra in the triangulation. * * \pre \a p \> \a q \>= 0 unless (p,q) = (0,1); * \pre gcd(\a p, \a q) = 1. * * @param p a parameter of the desired lens space. * @param q a parameter of the desired lens space. * * @see NLayeredLensSpace */ void insertLayeredLensSpace(unsigned long p, unsigned long q); /** * Inserts a layered loop of the given length into this triangulation. * Layered loops are described in more detail in the NLayeredLoop * class notes. * * The new tetrahedra will be inserted at the end of the list of * tetrahedra in the triangulation. * * @param length the length of the new layered loop; this must * be strictly positive. * @param twisted \c true if the new layered loop should be twisted, * or \c false if it should be untwisted. * * @see NLayeredLoop */ void insertLayeredLoop(unsigned long length, bool twisted); /** * Inserts an augmented triangular solid torus with the given * parameters into this triangulation. Almost all augmented * triangular solid tori represent Seifert fibred spaces with three * or fewer exceptional fibres. Augmented triangular solid tori * are described in more detail in the NAugTriSolidTorus class notes. * * The resulting Seifert fibred space will be * SFS((a1,b1) (a2,b2) * (a3,b3) (1,1)), where the parameters * a1, ..., b3 are passed as arguments to this * routine. The three layered solid tori that are attached to * the central triangular solid torus will be * LST(|a1|, |b1|, |-a1-b1|), ..., * LST(|a3|, |b3|, |-a3-b3|). * * The new tetrahedra will be inserted at the end of the list of * tetrahedra in the triangulation. * * \pre gcd(\a a1, \a b1) = 1. * \pre gcd(\a a2, \a b2) = 1. * \pre gcd(\a a3, \a b3) = 1. * * @param a1 a parameter describing the first layered solid * torus in the augmented triangular solid torus; this may be * either positive or negative. * @param b1 a parameter describing the first layered solid * torus in the augmented triangular solid torus; this may be * either positive or negative. * @param a2 a parameter describing the second layered solid * torus in the augmented triangular solid torus; this may be * either positive or negative. * @param b2 a parameter describing the second layered solid * torus in the augmented triangular solid torus; this may be * either positive or negative. * @param a3 a parameter describing the third layered solid * torus in the augmented triangular solid torus; this may be * either positive or negative. * @param b3 a parameter describing the third layered solid * torus in the augmented triangular solid torus; this may be * either positive or negative. */ void insertAugTriSolidTorus(long a1, long b1, long a2, long b2, long a3, long b3); /** * Inserts an orientable Seifert fibred space with at most three * exceptional fibres over the 2-sphere into this triangulation. * * The inserted Seifert fibred space will be * SFS((a1,b1) (a2,b2) * (a3,b3) (1,1)), where the parameters * a1, ..., b3 are passed as arguments to this * routine. * * The three pairs of parameters (a,b) do not need * to be normalised, i.e., the parameters can be positive or * negative and b may lie outside the range [0..a). * There is no separate twisting parameter; each additional * twist can be incorporated into the existing parameters * by replacing some pair (a,b) with the pair * (a,a+b). For Seifert fibred * spaces with less than three exceptional fibres, some or all * of the parameter pairs may be (1,k) or even (1,0). * * The new tetrahedra will be inserted at the end of the list of * tetrahedra in the triangulation. * * \pre None of \a a1, \a a2 or \a a3 are 0. * \pre gcd(\a a1, \a b1) = 1. * \pre gcd(\a a2, \a b2) = 1. * \pre gcd(\a a3, \a b3) = 1. * * @param a1 a parameter describing the first exceptional fibre. * @param b1 a parameter describing the first exceptional fibre. * @param a2 a parameter describing the second exceptional fibre. * @param b2 a parameter describing the second exceptional fibre. * @param a3 a parameter describing the third exceptional fibre. * @param b3 a parameter describing the third exceptional fibre. */ void insertSFSOverSphere(long a1 = 1, long b1 = 0, long a2 = 1, long b2 = 0, long a3 = 1, long b3 = 0); /** * Forms the connected sum of this triangulation with the given * triangulation. This triangulation will be altered directly. * * If this and the given triangulation are both oriented, then * the result will be oriented also, and the connected sum will * respect these orientations. * * This and/or the given triangulation may be bounded or ideal, or * even invalid; in all cases the connected sum will be formed * correctly. Note, however, that the result might possibly * contain internal vertices (even if the original triangulations * do not). * * \pre This triangulation is connected and non-empty. * * @param other the triangulation to sum with this. */ void connectedSumWith(const NTriangulation& other); /** * Inserts a copy of the given triangulation into this * triangulation. * * The new tetrahedra will be inserted into this triangulation * in the order in which they appear in the given triangulation, * and the numbering of their vertices (0-3) will not change. * They will be given the same descriptions as appear in the * given triangulation. * * @param source the triangulation whose copy will be inserted. */ void insertTriangulation(const NTriangulation& source); /** * Inserts the rehydration of the given string into this triangulation. * If you simply wish to convert a dehydration string into a * new triangulation, use the static routine rehydrate() instead. * See dehydrate() for more information on dehydration strings. * * This routine will first rehydrate the given string into a proper * triangulation. The tetrahedra from the rehydrated triangulation * will then be inserted into this triangulation in the same order in * which they appear in the rehydrated triangulation, and the * numbering of their vertices (0-3) will not change. * * The routine dehydrate() can be used to extract a dehydration * string from an existing triangulation. Dehydration followed * by rehydration might not produce a triangulation identical to * the original, but it is guaranteed to produce an isomorphic * copy. See dehydrate() for the reasons behind this. * * For a full description of the dehydrated triangulation * format, see A Census of Cusped Hyperbolic 3-Manifolds, * Callahan, Hildebrand and Weeks, Mathematics of Computation 68/225, * 1999. * * @param dehydration a dehydrated representation of the * triangulation to insert. Case is irrelevant; all letters * will be treated as if they were lower case. * @return \c true if the insertion was successful, or * \c false if the given string could not be rehydrated. * * @see dehydrate * @see rehydrate */ bool insertRehydration(const std::string& dehydration); /** * Inserts into this triangulation a set of tetrahedra and their * gluings as described by the given integer arrays. * * This routine is provided to make it easy to hard-code a * medium-sized triangulation in a C++ source file. All of the * pertinent data can be hard-coded into a pair of integer arrays at * the beginning of the source file, avoiding an otherwise tedious * sequence of many joinTo() calls. * * An additional \a nTetrahedra tetrahedra will be inserted into * this triangulation. The relationships between these tetrahedra * should be stored in the two arrays as follows. Note that the * new tetrahedra are numbered from 0 to (\a nTetrahedra - 1), and * individual tetrahedron faces are numbered from 0 to 3. * * The \a adjacencies array describes which tetrahedron faces are * joined to which others. Specifically, adjacencies[t][f] * should contain the number of the tetrahedron joined to face \a f * of tetrahedron \a t. If this face is to be left as a * boundary triangle, adjacencies[t][f] should be -1. * * The \a gluings array describes the particular gluing permutations * used when joining these tetrahedron faces together. Specifically, * gluings[t][f][0..3] should describe the permutation * used to join face \a f of tetrahedron \a t to its adjacent * tetrahedron. These four integers should be 0, 1, 2 and 3 in some * order, so that gluings[t][f][i] contains the image of * \a i under this permutation. If face \a f of tetrahedron \a t * is to be left as a boundary triangle, gluings[t][f][0..3] * may contain anything (and will be duly ignored). * * It is the responsibility of the caller of this routine to * ensure that the given arrays are correct and consistent. * No error checking will be performed by this routine. * * Note that, for an existing triangulation, dumpConstruction() * will output a pair of C++ arrays that can be copied into a * source file and used to reconstruct the triangulation via * this routine. * * \ifacespython Not present. * * @param nTetrahedra the number of additional tetrahedra to insert. * @param adjacencies describes which of the new tetrahedron * faces are to be identified. This array must have initial * dimension at least \a nTetrahedra. * @param gluings describes the specific gluing permutations by * which these new tetrahedron faces should be identified. This * array must also have initial dimension at least \a nTetrahedra. */ void insertConstruction(unsigned long nTetrahedra, const int adjacencies[][4], const int gluings[][4][4]); /*@}*/ /** * \name Exporting Triangulations */ /*@{*/ using NGenericTriangulation<3>::isoSig; /** * Dehydrates this triangulation into an alphabetical string. * * A dehydration string is a compact text representation * of a triangulation, introduced by Callahan, Hildebrand and Weeks * for their cusped hyperbolic census (see below). The dehydration * string of an n-tetrahedron triangulation consists of * approximately (but not precisely) 5n/2 lower-case letters. * * Dehydration strings come with some restrictions: * - They rely on the triangulation being "canonical" in some * combinatorial sense. This is not enforced here; instead * a combinatorial isomorphism is applied to make the * triangulation canonical, and this isomorphic triangulation * is dehydrated instead. Note that the original triangulation * is not changed. * - They require the triangulation to be connected. * - They require the triangulation to have no boundary triangles * (though ideal triangulations are fine). * - They can only support triangulations with at most 25 tetrahedra. * * The routine rehydrate() can be used to recover a * triangulation from a dehydration string. Note that the * triangulation recovered might not be identical to the * original, but it is guaranteed to be an isomorphic copy. * * For a full description of the dehydrated triangulation * format, see A Census of Cusped Hyperbolic 3-Manifolds, * Callahan, Hildebrand and Weeks, Mathematics of Computation 68/225, * 1999. * * @return a dehydrated representation of this triangulation * (or an isomorphic variant of this triangulation), or the * empty string if dehydration is not possible because the * triangulation is disconnected, has boundary triangles or contains * too many tetrahedra. * * @see rehydrate * @see insertRehydration */ std::string dehydrate() const; /** * Returns C++ code that can be used with insertConstruction() * to reconstruct this triangulation. * * The code produced will consist of the following: * * - the declaration and initialisation of two integer arrays, * describing the tetrahedron gluings in this trianguation; * - two additional lines that declare a new NTriangulation and * call insertConstruction() to rebuild this triangulation. * * The main purpose of this routine is to generate the two integer * arrays, which can be tedious and error-prone to code up by hand. * * Note that the number of lines of code produced grows linearly * with the number of tetrahedra. If this triangulation is very * large, the returned string will be very large as well. * * @return the C++ code that was generated. */ std::string dumpConstruction() const; /** * Returns a string containing the full contents of a SnapPea data * file that describes this triangulation. In particular, this string * can be used in a Python session to pass the triangulation directly * to SnapPy (without writing to the filesystem). * * Regarding what gets stored in the SnapPea data file: * * - If you are calling this from one of Regina's own NTriangulation * objects, then only the tetrahedron gluings and the manifold name * will be stored (the name will be derived from the packet label). * All other SnapPea-specific information (such as peripheral curves) * will be marked as unknown (since Regina does not track such * information itself), and of course other Regina-specific * information (such as the Turaev-Viro invariants) will not * be written to the SnapPea file at all. * * - If you are calling this from the subclass NSnapPeaTriangulation, * then all additional SnapPea-specific information will be written * to the file (indeed, the SnapPea kernel itself will be used to * produce the file contents). * * If you wish to export a triangulation to a SnapPea \e file, you * should call saveSnapPea() instead (which has better performance, and * does not require you to construct an enormous intermediate string). * * If this triangulation is empty, invalid, or contains boundary * triangles (which SnapPea cannot represent), then the resulting * string will be empty. * * @return a string containing the contents of the corresponding * SnapPea data file. */ virtual std::string snapPea() const; /** * Writes the full contents of a SnapPea data file describing this * triangulation to the given output stream. * * Regarding what gets stored in the SnapPea data file: * * - If you are calling this from one of Regina's own NTriangulation * objects, then only the tetrahedron gluings and the manifold name * will be stored (the name will be derived from the packet label). * All other SnapPea-specific information (such as peripheral curves) * will be marked as unknown (since Regina does not track such * information itself), and of course other Regina-specific * information (such as the Turaev-Viro invariants) will not * be written to the SnapPea file at all. * * - If you are calling this from the subclass NSnapPeaTriangulation, * then all additional SnapPea-specific information will be written * to the file (indeed, the SnapPea kernel itself will be used to * produce the file contents). * * If you wish to extract the SnapPea data file as a string, you should * call the zero-argument routine snapPea() instead. If you wish to * write to a real SnapPea data file on the filesystem, you should call * saveSnapPea() (which is also available in Python). * * If this triangulation is empty, invalid, or contains boundary * triangles (which SnapPea cannot represent), then nothing will * be written to the output stream. * * \ifacespython Not present. * * @param out the output stream to which the SnapPea data file * will be written. */ virtual void snapPea(std::ostream& out) const; /** * Writes this triangulation to the given file using SnapPea's * native file format. * * Regarding what gets stored in the SnapPea data file: * * - If you are calling this from one of Regina's own NTriangulation * objects, then only the tetrahedron gluings and the manifold name * will be stored (the name will be derived from the packet label). * All other SnapPea-specific information (such as peripheral curves) * will be marked as unknown (since Regina does not track such * information itself), and of course other Regina-specific * information (such as the Turaev-Viro invariants) will not * be written to the SnapPea file at all. * * - If you are calling this from the subclass NSnapPeaTriangulation, * then all additional SnapPea-specific information will be written * to the file (indeed, the SnapPea kernel itself will be used to * produce the file contents). * * If this triangulation is empty, invalid, or contains boundary * triangles (which SnapPea cannot represent), then the file * will not be written and this routine will return \c false. * * \i18n This routine makes no assumptions about the * \ref i18n "character encoding" used in the given file \e name, and * simply passes it through unchanged to low-level C/C++ file I/O * routines. The \e contents of the file will be written using UTF-8. * * @param filename the name of the SnapPea file to which to write. * @return \c true if and only if the file was successfully written. */ virtual bool saveSnapPea(const char* filename) const; /** * Returns a string that expresses this triangulation in * Matveev's 3-manifold recogniser format. * * \pre This triangulation is not invalid, and does not contain * any boundary triangles. * * @return a string containing the 3-manifold recogniser data. */ std::string recogniser() const; /** * A synonym for recogniser(). This returns a string that * expresses this triangulation in Matveev's 3-manifold * recogniser format. * * \pre This triangulation is not invalid, and does not contain * any boundary triangles. * * @return a string containing the 3-manifold recogniser data. */ std::string recognizer() const; /** * Writes a string expressing this triangulation in Matveev's * 3-manifold recogniser format to the given output stream. * * \pre This triangulation is not invalid, and does not contain * any boundary triangles. * * \ifacespython Not present. * * @param out the output stream to which the recogniser data file * will be written. */ void recogniser(std::ostream& out) const; /** * A synonym for recognizer(std::ostream&). This writes * a string expressing this triangulation in Matveev's * 3-manifold recogniser format to the given output stream. * * \pre This triangulation is not invalid, and does not contain * any boundary triangles. * * \ifacespython Not present. * * @param out the output stream to which the recogniser data file * will be written. */ void recognizer(std::ostream& out) const; /** * Writes this triangulation to the given file in Matveev's * 3-manifold recogniser format. * * \pre This triangulation is not invalid, and does not contain * any boundary triangles. * * \i18n This routine makes no assumptions about the * \ref i18n "character encoding" used in the given file \e name, and * simply passes it through unchanged to low-level C/C++ file I/O * routines. The \e contents of the file will be written using UTF-8. * * @param filename the name of the Recogniser file to which to write. * @return \c true if and only if the file was successfully written. */ bool saveRecogniser(const char* filename) const; /** * A synonym for saveRecogniser(). This writes this triangulation to * the given file in Matveev's 3-manifold recogniser format. * * \pre This triangulation is not invalid, and does not contain * any boundary triangles. * * \i18n This routine makes no assumptions about the * \ref i18n "character encoding" used in the given file \e name, and * simply passes it through unchanged to low-level C/C++ file I/O * routines. The \e contents of the file will be written using UTF-8. * * @param filename the name of the Recogniser file to which to write. * @return \c true if and only if the file was successfully written. */ bool saveRecognizer(const char* filename) const; /*@}*/ /** * \name Importing Triangulations */ /*@{*/ /** * Allows the user to interactively enter a triangulation in * plain text. Prompts will be sent to the given output stream * and information will be read from the given input stream. * * \ifacespython This routine is a member of class Engine. * It takes no parameters; \a in and \a out are always assumed * to be standard input and standard output respectively. * * @param in the input stream from which text will be read. * @param out the output stream to which prompts will be * written. * @return the triangulation entered in by the user. */ static NTriangulation* enterTextTriangulation(std::istream& in, std::ostream& out); /** * Rehydrates the given alphabetical string into a new triangulation. * See dehydrate() for more information on dehydration strings. * * This routine will rehydrate the given string into a new * triangulation, and return this new triangulation. * * The converse routine dehydrate() can be used to extract a * dehydration string from an existing triangulation. Dehydration * followed by rehydration might not produce a triangulation identical * to the original, but it is guaranteed to produce an isomorphic * copy. See dehydrate() for the reasons behind this. * * For a full description of the dehydrated triangulation * format, see A Census of Cusped Hyperbolic 3-Manifolds, * Callahan, Hildebrand and Weeks, Mathematics of Computation 68/225, * 1999. * * @param dehydration a dehydrated representation of the * triangulation to construct. Case is irrelevant; all letters * will be treated as if they were lower case. * @return a newly allocated triangulation if the rehydration was * successful, or null if the given string could not be rehydrated. * * @see dehydrate * @see insertRehydration */ static NTriangulation* rehydrate(const std::string& dehydration); using NGenericTriangulation<3>::fromIsoSig; using NGenericTriangulation<3>::isoSigComponentSize; /** * Extracts the tetrahedron gluings from a string that contains the * full contents of a SnapPea data file. All other SnapPea-specific * information (such as peripheral curves) will be ignored, since * Regina's NTriangulation class does not track such information itself. * * If you wish to preserve all SnapPea-specific information from the * data file, you should work with the NSnapPeaTriangulation class * instead (which uses the SnapPea kernel directly, and can therefore * store anything that SnapPea can). * * If you wish to read a triangulation from a SnapPea \e file, you * should likewise call the NSnapPeaTriangulation constructor, giving * the filename as argument. This will read all SnapPea-specific * information (as described above), and also avoids constructing an * enormous intermediate string. * * The triangulation that is returned will be newly created. * If the SnapPea data is not in the correct format, this * routine will return 0 instead. * * \warning This routine is "lossy", in that drops SnapPea-specific * information (as described above). Unless you specifically need an * NTriangulation (not an NSnapPeaTriangulation) or you need to avoid * calling routines from the SnapPea kernel, it is highly recommended * that you create an NSnapPeaTriangulation from the given file * contents instead. See the string-based NSnapPeaTriangulation * constructor for how to do this. * * @param snapPeaData a string containing the full contents of a * SnapPea data file. * @return a new triangulation extracted from the given data, * or 0 on error. */ static NTriangulation* fromSnapPea(const std::string& snapPeaData); /*@}*/ static NXMLPacketReader* getXMLReader(NPacket* parent, NXMLTreeResolver& resolver); protected: virtual NPacket* internalClonePacket(NPacket* parent) const; virtual void writeXMLPacketData(std::ostream& out) const; /** * Turns this triangulation into a clone of the given * triangulation. * The tree structure and label of this triangulation are not * touched. * * @param from the triangulation from which this triangulation * will be cloned. */ void cloneFrom(const NTriangulation& from); private: void deleteTetrahedra(); /**< Deallocates all tetrahedra and empties the list. */ void deleteSkeleton(); /**< Deallocates all skeletal objects and empties all corresponding lists. */ /** * Clears any calculated properties and declares them all * unknown. All dynamic memory used for storing known * properties is deallocated. * * In most cases this routine is followed immediately by firing * a packet change event. */ virtual void clearAllProperties(); /** * Checks that the permutations on face gluings are valid and * that adjacent face gluings match. That is, if face \a A of * tetrahedron \a X is glued to face \a B of tetrahedron \a Y, * then face \a B of tetrahedron \a Y is also glued to face \a A * of tetrahedron \a X using the inverse permutation. * * If any of these tests fail, this routine writes a message to * standard error and marks this triangulations as invalid. * Any such failure indicates a likely programming error, since * adjacent face gluings should always match if the NTetrahedron * gluing routines have been used correctly. * * @author Matthias Goerner */ void checkPermutations() const; /** * Recalculates vertices, edges, triangles, components and * boundary components, as well as various other skeletal * properties such as validity and vertex links. * All appropriate lists are filled. * * \pre All skeletal lists are empty. */ void calculateSkeleton() const; /** * Calculates the triangulation components and associated * properties. * * \warning This should only be called from within * calculateSkeleton(). */ void calculateComponents() const; void labelComponent(NTetrahedron*, NComponent*) const; /**< Internal to calculateComponents(). */ /** * Calculates the triangulation vertices and associated * properties. * * \warning This should only be called from within * calculateSkeleton(). */ void calculateVertices() const; void labelVertex(NTetrahedron*, int, NVertex*) const; /**< Internal to calculateVertices(). */ /** * Calculates the triangulation edges and associated * properties. * * \warning This should only be called from within * calculateSkeleton(). */ void calculateEdges() const; void labelEdge(NTetrahedron*, int, NEdge*) const; /**< Internal to calculateEdges(). */ /** * Calculates the triangles of this triangulation and associated * properties. * * \warning This should only be called from within * calculateSkeleton(). */ void calculateTriangles() const; /** * Calculates the triangulation boundary components and * properties of these boundary components. * * \warning This should only be called from within * calculateSkeleton(). */ void calculateBoundary() const; void labelBoundaryTriangle(NTriangle*, NBoundaryComponent*) const; /**< Internal to calculateBoundary(). */ /** * Calculates the triangulation vertex links and associated * properties. * * \warning This should only be called from within * calculateSkeleton(). */ void calculateVertexLinks() const; /** * Calculates all properties of the triangulation relating to * its boundary components. */ void calculateBoundaryProperties() const; /** * Determines if an isomorphic copy of this triangulation is * contained within the given triangulation. * * If the argument \a completeIsomorphism is \c true, the * isomorphism must be onto and boundary complete. * That is, this triangulation must be combinatorially * isomorphic to the given triangulation. * * If the argument \a completeIsomorphism is \c false, the * isomorphism may be boundary incomplete and may or may not be * onto. That is, this triangulation must appear as a * subcomplex of the given triangulation, possibly with some * original boundary triangles joined to new tetrahedra. * * See the NIsomorphism class notes for further details * regarding boundary complete and boundary incomplete * isomorphisms. * * The isomorphisms found, if any, will be appended to the * list \a results. This list will not be emptied before * calculations begin. All isomorphisms will be newly created, * and the caller of this routine is responsible for destroying * them. * * If \a firstOnly is passed as \c true, only the first * isomorphism found (if any) will be returned, after which the * routine will return immediately. Otherwise all isomorphisms * will be returned. * * @param other the triangulation in which to search for an * isomorphic copy of this triangulation. * @param results the list in which any isomorphisms found will * be stored. * @param completeIsomorphism \c true if isomorphisms must be * onto and boundary complete, or \c false if neither of these * restrictions should be imposed. * @param firstOnly \c true if only one isomorphism should be * returned (if any), or \c false if all isomorphisms should be * returned. * @return the total number of isomorphisms found. */ unsigned long findIsomorphisms(const NTriangulation& other, std::list& results, bool completeIsomorphism, bool firstOnly) const; /** * Internal to findIsomorphisms(). * * Examines properties of the given tetrahedra to find any * immediate evidence that \a src may not map to \a dest in a * boundary complete isomorphism (in which the vertices of \a src * are mapped to the vertices of \a dest according to the * permutation \a p). * * In particular, properties such as edge degrees and vertex links * are examined. * * @param src the first of the two tetrahedra to examine. * @param dest the second of the two tetrahedra to examine. * @param p the permutation under which the vertices of \a src * must map to the vertices of \a dest. * @return \c true if no immediate incompatibilities between the * tetrahedra were found, or \c false if properties of the * tetrahedra were found that differ between \a src and \a dest. */ static bool compatibleTets(NTetrahedron* src, NTetrahedron* dest, NPerm4 p); void stretchBoundaryForestFromVertex(NVertex*, std::set&, std::set&) const; /**< Internal to maximalForestInBoundary(). */ bool stretchForestFromVertex(NVertex*, std::set&, std::set&, std::set&) const; /**< Internal to maximalForestInSkeleton(). */ void stretchDualForestFromTet(NTetrahedron*, std::set&, std::set&) const; /**< Internal to maximalForestInDualSkeleton(). */ friend class regina::NGenericTriangulation<3>; friend class regina::NTetrahedron; friend class regina::NXMLTriangulationReader; }; /*@}*/ } // namespace regina // Some more headers that are required for inline functions: #include "triangulation/ntetrahedron.h" #include "triangulation/ntriangle.h" #include "triangulation/nedge.h" #include "triangulation/nvertex.h" #include "triangulation/ncomponent.h" #include "triangulation/nboundarycomponent.h" namespace regina { // Inline functions for NTriangulation inline NTriangulation::NTriangulation() : calculatedSkeleton_(false) { } inline NTriangulation::NTriangulation(const NTriangulation& cloneMe) : NPacket(), calculatedSkeleton_(false) { cloneFrom(cloneMe); } inline NTriangulation::~NTriangulation() { clearAllProperties(); deleteTetrahedra(); } inline NPacket* NTriangulation::internalClonePacket(NPacket*) const { return new NTriangulation(*this); } inline bool NTriangulation::dependsOnParent() const { return false; } inline unsigned long NTriangulation::getNumberOfTetrahedra() const { return tetrahedra_.size(); } inline unsigned long NTriangulation::getNumberOfSimplices() const { return tetrahedra_.size(); } inline NTetrahedron* NTriangulation::getTetrahedron(unsigned long index) { return tetrahedra_[index]; } inline NTetrahedron* NTriangulation::getSimplex(unsigned long index) { return tetrahedra_[index]; } inline const NTetrahedron* NTriangulation::getTetrahedron(unsigned long index) const { return tetrahedra_[index]; } inline const NTetrahedron* NTriangulation::getSimplex(unsigned long index) const { return tetrahedra_[index]; } inline long NTriangulation::tetrahedronIndex(const NTetrahedron* tet) const { return tet->markedIndex(); } inline long NTriangulation::simplexIndex(const NTetrahedron* tet) const { return tet->markedIndex(); } inline NTetrahedron* NTriangulation::newTetrahedron() { ChangeEventSpan span(this); NTetrahedron* tet = new NTetrahedron(); tet->tri_ = this; tetrahedra_.push_back(tet); clearAllProperties(); return tet; } inline NTetrahedron* NTriangulation::newSimplex() { return newTetrahedron(); } inline NTetrahedron* NTriangulation::newTetrahedron(const std::string& desc) { ChangeEventSpan span(this); NTetrahedron* tet = new NTetrahedron(desc); tet->tri_ = this; tetrahedra_.push_back(tet); clearAllProperties(); return tet; } inline NTetrahedron* NTriangulation::newSimplex(const std::string& desc) { return newTetrahedron(desc); } inline void NTriangulation::removeTetrahedronAt(unsigned long index) { ChangeEventSpan span(this); NTetrahedron* ans = tetrahedra_[index]; ans->isolate(); tetrahedra_.erase(tetrahedra_.begin() + index); delete ans; clearAllProperties(); } inline void NTriangulation::removeSimplexAt(unsigned long index) { removeTetrahedronAt(index); } inline void NTriangulation::removeTetrahedron(NTetrahedron* tet) { ChangeEventSpan span(this); tet->isolate(); tetrahedra_.erase(tetrahedra_.begin() + tetrahedronIndex(tet)); delete tet; clearAllProperties(); } inline void NTriangulation::removeSimplex(NTetrahedron* tet) { removeTetrahedron(tet); } inline void NTriangulation::removeAllTetrahedra() { ChangeEventSpan span(this); deleteTetrahedra(); clearAllProperties(); } inline void NTriangulation::removeAllSimplices() { removeAllTetrahedra(); } inline void NTriangulation::gluingsHaveChanged() { } inline unsigned long NTriangulation::getNumberOfBoundaryComponents() const { if (! calculatedSkeleton_) calculateSkeleton(); return boundaryComponents_.size(); } inline unsigned long NTriangulation::getNumberOfComponents() const { if (! calculatedSkeleton_) calculateSkeleton(); return components_.size(); } inline unsigned long NTriangulation::getNumberOfVertices() const { if (! calculatedSkeleton_) calculateSkeleton(); return vertices_.size(); } inline unsigned long NTriangulation::getNumberOfEdges() const { if (! calculatedSkeleton_) calculateSkeleton(); return edges_.size(); } inline unsigned long NTriangulation::getNumberOfTriangles() const { if (! calculatedSkeleton_) calculateSkeleton(); return triangles_.size(); } inline unsigned long NTriangulation::getNumberOfFaces() const { return getNumberOfTriangles(); } template <> inline unsigned long NTriangulation::getNumberOfFaces<0>() const { return getNumberOfVertices(); } template <> inline unsigned long NTriangulation::getNumberOfFaces<1>() const { return getNumberOfEdges(); } template <> inline unsigned long NTriangulation::getNumberOfFaces<2>() const { return getNumberOfTriangles(); } template <> inline unsigned long NTriangulation::getNumberOfFaces<3>() const { return getNumberOfTetrahedra(); } inline long NTriangulation::getEulerCharTri() const { if (! calculatedSkeleton_) calculateSkeleton(); // Cast away the unsignedness of std::vector::size(). return static_cast(vertices_.size()) - static_cast(edges_.size()) + static_cast(triangles_.size()) - static_cast(tetrahedra_.size()); } inline long NTriangulation::getEulerCharacteristic() const { return getEulerCharTri(); } inline const std::vector& NTriangulation::getTetrahedra() const { return (const std::vector&)(tetrahedra_); } inline const std::vector& NTriangulation::getSimplices() const { return (const std::vector&)(tetrahedra_); } inline const std::vector& NTriangulation::getBoundaryComponents() const { if (! calculatedSkeleton_) calculateSkeleton(); return (const std::vector&)(boundaryComponents_); } inline const std::vector& NTriangulation::getComponents() const { if (! calculatedSkeleton_) calculateSkeleton(); return (const std::vector&)(components_); } inline const std::vector& NTriangulation::getVertices() const { if (! calculatedSkeleton_) calculateSkeleton(); return (const std::vector&)(vertices_); } inline const std::vector& NTriangulation::getEdges() const { if (! calculatedSkeleton_) calculateSkeleton(); return (const std::vector&)(edges_); } inline const std::vector& NTriangulation::getTriangles() const { if (! calculatedSkeleton_) calculateSkeleton(); return (const std::vector&)(triangles_); } inline const std::vector& NTriangulation::getFaces() const { return getTriangles(); } inline NComponent* NTriangulation::getComponent(unsigned long index) const { if (! calculatedSkeleton_) calculateSkeleton(); return components_[index]; } inline NBoundaryComponent* NTriangulation::getBoundaryComponent( unsigned long index) const { if (! calculatedSkeleton_) calculateSkeleton(); return boundaryComponents_[index]; } inline NVertex* NTriangulation::getVertex(unsigned long index) const { if (! calculatedSkeleton_) calculateSkeleton(); return vertices_[index]; } inline NEdge* NTriangulation::getEdge(unsigned long index) const { if (! calculatedSkeleton_) calculateSkeleton(); return edges_[index]; } inline NTriangle* NTriangulation::getTriangle(unsigned long index) const { if (! calculatedSkeleton_) calculateSkeleton(); return triangles_[index]; } inline NTriangle* NTriangulation::getFace(unsigned long index) const { return getTriangle(index); } inline long NTriangulation::componentIndex(const NComponent* component) const { return component->markedIndex(); } inline long NTriangulation::boundaryComponentIndex( const NBoundaryComponent* boundaryComponent) const { return boundaryComponent->markedIndex(); } inline long NTriangulation::vertexIndex(const NVertex* vertex) const { return vertex->markedIndex(); } inline long NTriangulation::edgeIndex(const NEdge* edge) const { return edge->markedIndex(); } inline long NTriangulation::triangleIndex(const NTriangle* tri) const { return tri->markedIndex(); } inline long NTriangulation::faceIndex(const NTriangle* tri) const { return tri->markedIndex(); } inline bool NTriangulation::hasTwoSphereBoundaryComponents() const { if (! twoSphereBoundaryComponents_.known()) calculateBoundaryProperties(); return twoSphereBoundaryComponents_.value(); } inline bool NTriangulation::hasNegativeIdealBoundaryComponents() const { if (! negativeIdealBoundaryComponents_.known()) calculateBoundaryProperties(); return negativeIdealBoundaryComponents_.value(); } inline bool NTriangulation::isValid() const { if (! calculatedSkeleton_) calculateSkeleton(); return valid_; } inline bool NTriangulation::isIdeal() const { if (! calculatedSkeleton_) calculateSkeleton(); return ideal_; } inline bool NTriangulation::isStandard() const { if (! calculatedSkeleton_) calculateSkeleton(); return standard_; } inline bool NTriangulation::hasBoundaryTriangles() const { if (! calculatedSkeleton_) calculateSkeleton(); return (triangles_.size() > 2 * tetrahedra_.size()); } inline bool NTriangulation::hasBoundaryFaces() const { return hasBoundaryTriangles(); } inline unsigned long NTriangulation::getNumberOfBoundaryTriangles() const { if (! calculatedSkeleton_) calculateSkeleton(); return 2 * triangles_.size() - 4 * tetrahedra_.size(); } inline bool NTriangulation::isClosed() const { if (! calculatedSkeleton_) calculateSkeleton(); return boundaryComponents_.empty(); } inline bool NTriangulation::isOrientable() const { if (! calculatedSkeleton_) calculateSkeleton(); return orientable_; } inline bool NTriangulation::isConnected() const { if (! calculatedSkeleton_) calculateSkeleton(); return (components_.size() <= 1); } inline void NTriangulation::simplifiedFundamentalGroup( NGroupPresentation* newGroup) { fundamentalGroup_ = newGroup; } inline bool NTriangulation::knowsZeroEfficient() const { return zeroEfficient_.known(); } inline bool NTriangulation::knowsSplittingSurface() const { return splittingSurface_.known(); } inline bool NTriangulation::hasStrictAngleStructure() const { if (! strictAngleStructure_.known()) findStrictAngleStructure(); return (strictAngleStructure_.value() != 0); } inline unsigned long NTriangulation::getHomologyH2Z2() const { return getHomologyH1Rel().getRank() + getHomologyH1Rel().getTorsionRank(2); } inline const NTriangulation::TuraevViroSet& NTriangulation::allCalculatedTuraevViro() const { return turaevViroCache_; } inline void NTriangulation::writeTextShort(std::ostream& out) const { out << "Triangulation with " << tetrahedra_.size() << (tetrahedra_.size() == 1 ? " tetrahedron" : " tetrahedra"); } inline void NTriangulation::recognizer(std::ostream& out) const { recogniser(out); } inline bool NTriangulation::saveRecognizer(const char* filename) const { return saveRecogniser(filename); } } // namespace regina #endif regina-4.96/engine/triangulation/nvertex.cpp000644 000765 000024 00000014314 12377776770 021166 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "dim2/dim2triangulation.h" #include "maths/permconv.h" #include "triangulation/nisomorphism.h" #include "triangulation/nvertex.h" #include namespace regina { const int NVertex::SPHERE = 1; const int NVertex::DISC = 2; const int NVertex::TORUS = 3; const int NVertex::KLEIN_BOTTLE = 4; const int NVertex::NON_STANDARD_CUSP = 5; const int NVertex::NON_STANDARD_BDRY = 6; NVertex::~NVertex() { delete linkTri_; } void NVertex::writeTextShort(std::ostream& out) const { switch(link_) { case SPHERE: out << "Internal "; break; case DISC: out << "Boundary "; break; case TORUS: out << "Torus cusp "; break; case KLEIN_BOTTLE: out << "Klein bottle cusp "; break; case NON_STANDARD_CUSP: out << "Non-standard cusp "; break; case NON_STANDARD_BDRY: out << "Non-standard boundary "; break; } out << "vertex of degree " << getNumberOfEmbeddings(); } void NVertex::writeTextLong(std::ostream& out) const { writeTextShort(out); out << std::endl; out << "Appears as:" << std::endl; std::vector::const_iterator it; for (it = embeddings_.begin(); it != embeddings_.end(); ++it) out << " " << it->getTetrahedron()->markedIndex() << " (" << it->getVertex() << ')' << std::endl; } Dim2Triangulation* NVertex::buildLinkDetail(bool labels, NIsomorphism** inclusion) const { // Build the triangulation. Dim2Triangulation* ans = new Dim2Triangulation(); NPacket::ChangeEventSpan span(ans); if (inclusion) *inclusion = new NIsomorphism(embeddings_.size()); std::vector::const_iterator it, adjIt; Dim2Triangle* tTri; int i; for (it = embeddings_.begin(), i = 0; it != embeddings_.end(); ++it, ++i) { tTri = ans->newTriangle(); if (labels) { std::stringstream s; s << it->getTetrahedron()->markedIndex() << " (" << it->getVertex() << ')'; tTri->setDescription(s.str()); } if (inclusion) { (*inclusion)->tetImage(i) = it->getTetrahedron()->markedIndex(); (*inclusion)->facetPerm(i) = it->getTetrahedron()-> getTriangleMapping(it->getVertex()); } } NTetrahedron *tet, *adj; int exitTri, v; int edgeInLink; int adjIndex; int adjVertex; for (it = embeddings_.begin(), i = 0; it != embeddings_.end(); ++it, ++i) { tet = it->getTetrahedron(); v = it->getVertex(); for (exitTri = 0; exitTri < 4; ++exitTri) { if (exitTri == v) continue; adj = tet->adjacentTetrahedron(exitTri); if (! adj) continue; edgeInLink = tet->getTriangleMapping(v).preImageOf(exitTri); if (ans->getTriangle(i)->adjacentTriangle(edgeInLink)) { // We've already made this gluing in the vertex link // from the other side. continue; } adjVertex = tet->adjacentGluing(exitTri)[v]; // TODO: We need to find which *embedding* corresponds to // the adjacent tetrahedron/vertex pair. // Currently we do a simple linear scan, which makes the // overall link construction quadratic. This can surely be // made linear(ish) with the right data structure and/or algorithm. for (adjIt = embeddings_.begin(), adjIndex = 0; adjIt != embeddings_.end(); ++adjIt, ++adjIndex) if (adjIt->getTetrahedron() == adj && adjIt->getVertex() == adjVertex) break; // Sets adjIndex to the right value. ans->getTriangle(i)->joinTo(edgeInLink, ans->getTriangle(adjIndex), perm4to3(adj->getTriangleMapping(adjVertex).inverse() * tet->adjacentGluing(exitTri) * tet->getTriangleMapping(v))); } } return ans; } } // namespace regina regina-4.96/engine/triangulation/nvertex.h000644 000765 000024 00000055537 12377775641 020643 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file triangulation/nvertex.h * \brief Deals with vertices in a triangulation. */ #ifndef __NVERTEX_H #ifndef __DOXYGEN #define __NVERTEX_H #endif #include #include "regina-core.h" #include "shareableobject.h" #include "maths/nperm4.h" #include "utilities/nmarkedvector.h" // NOTE: More #includes follow after the class declarations. namespace regina { class Dim2Triangulation; class NBoundaryComponent; class NComponent; class NIsomorphism; class NTetrahedron; class NTriangulation; /** * \weakgroup triangulation * @{ */ /** * Details how a vertex in the skeleton forms part of an individual * tetrahedron. */ class REGINA_API NVertexEmbedding { private: NTetrahedron* tetrahedron_; /**< The tetrahedron in which this vertex is contained. */ int vertex_; /**< The vertex number of the tetrahedron that is this vertex. */ public: /** * Default constructor. The embedding descriptor created is * unusable until it has some data assigned to it using * operator =. * * \ifacespython Not present. */ NVertexEmbedding(); /** * Creates an embedding descriptor containing the given data. * * @param newTet the tetrahedron in which this vertex is * contained. * @param newVertex the vertex number of \a newTet that is this vertex. */ NVertexEmbedding(NTetrahedron* newTet, int newVertex); /** * Creates an embedding descriptor containing the same data as * the given embedding descriptor. * * @param cloneMe the embedding descriptor to clone. */ NVertexEmbedding(const NVertexEmbedding& cloneMe); /** * Assigns to this embedding descriptor the same data as is * contained in the given embedding descriptor. * * @param cloneMe the embedding descriptor to clone. */ NVertexEmbedding& operator =(const NVertexEmbedding& cloneMe); /** * Returns the tetrahedron in which this vertex is contained. * * @return the tetrahedron. */ NTetrahedron* getTetrahedron() const; /** * Returns the vertex number within getTetrahedron() that is * this vertex. * * @return the vertex number that is this vertex. */ int getVertex() const; /** * Returns a permutation that maps 0 to the vertex number within * getTetrahedron() that is this vertex. The real point of this * routine is that (1,2,3) maps to the three remaining tetrahedron * vertices in a manner that preserves orientation as you walk around * the vertex (assuming this is actually possible). See * NTetrahedron::getVertexMapping() for details. * * @return a permutation that maps 0 to the vertex number that * is this vertex. */ NPerm4 getVertices() const; /** * Tests whether this and the given embedding are identical. * Here "identical" means that they refer to the same vertex of * the same tetrahedron. * * @param rhs the embedding to compare with this. * @return \c true if and only if both embeddings are identical. */ bool operator == (const NVertexEmbedding& rhs) const; /** * Tests whether this and the given embedding are different. * Here "different" means that they do not refer to the same vertex of * the same tetrahedron. * * @param rhs the embedding to compare with this. * @return \c true if and only if both embeddings are identical. */ bool operator != (const NVertexEmbedding& rhs) const; }; /** * Represents a vertex in the skeleton of a triangulation. * Vertices are highly temporary; once a triangulation changes, all its * vertex objects will be deleted and new ones will be created. */ class REGINA_API NVertex : public ShareableObject, public NMarkedElement { public: static const int SPHERE; /**< Specifies a vertex link that is a sphere. */ static const int DISC; /**< Specifies a vertex link that is a disc. */ static const int TORUS; /**< Specifies a vertex link that is a torus. */ static const int KLEIN_BOTTLE; /**< Specifies a vertex link that is a Klein bottle. */ static const int NON_STANDARD_CUSP; /**< Specifies a vertex link that is closed and is not a sphere, torus or Klein bottle. */ static const int NON_STANDARD_BDRY; /**< Specifies a vertex link that has boundary and is not a disc. */ private: std::vector embeddings_; /**< A list of descriptors telling how this vertex forms a part of each individual tetrahedron that it belongs to. */ NComponent* component_; /**< The component that this vertex is a part of. */ NBoundaryComponent* boundaryComponent_; /**< The boundary component that this vertex is a part of, or 0 if this vertex is internal. */ int link_; /**< Specifies the link of the vertex according to one of the predefined vertex link constants in NVertex. */ bool linkOrientable_; /**< Specifies whether the vertex link is orientable. */ long linkEulerChar_; /**< Specifies the Euler characteristic of the vertex link. */ Dim2Triangulation* linkTri_; /**< A triangulation of the vertex link. This will only be constructed on demand; until then it will be null. */ public: /** * Default destructor. */ virtual ~NVertex(); /** * Returns the index of this vertex in the underlying * triangulation. This is identical to calling * getTriangulation()->vertexIndex(this). * * @return the index of this vertex. */ unsigned long index() const; /** * Returns the list of descriptors detailing how this vertex forms a * part of various tetrahedra in the triangulation. * Note that if this vertex represents multiple vertices of a * particular tetrahedron, then there will be multiple embedding * descriptors in the list regarding that tetrahedron. * * \ifacespython This routine returns a python list. * * @return the list of embedding descriptors. * @see NVertexEmbedding */ const std::vector& getEmbeddings() const; /** * Returns the number of descriptors in the list returned by * getEmbeddings(). Note that this is identical to getDegree(). * * @return the number of embedding descriptors. */ unsigned long getNumberOfEmbeddings() const; /** * Returns the requested descriptor from the list returned by * getEmbeddings(). * * @param index the index of the requested descriptor. This * should be between 0 and getNumberOfEmbeddings()-1 inclusive. * @return the requested embedding descriptor. */ const NVertexEmbedding& getEmbedding(unsigned long index) const; /** * Returns the triangulation to which this vertex belongs. * * @return the triangulation containing this vertex. */ NTriangulation* getTriangulation() const; /** * Returns the component of the triangulation to which this * vertex belongs. * * @return the component containing this vertex. */ NComponent* getComponent() const; /** * Returns the boundary component of the triangulation to which * this vertex belongs. * * See the note in the NBoundaryComponent overview regarding what * happens if the vertex link is a multiply punctured surface. * Note that this makes the vertex non-standard and the * triangulation invalid. * * An ideal vertex will have its own individual boundary * component to which it belongs. * * @return the boundary component containing this vertex, * or 0 if this vertex is not on the boundary of the triangulation * as determined by isBoundary(). */ NBoundaryComponent* getBoundaryComponent() const; /** * Returns the degree of this vertex. Note that this is * identical to getNumberOfEmbeddings(). * * @return the degree of this vertex. */ unsigned long getDegree() const; /** * Returns a description of the link of the vertex. * * This routine does not require a full triangulation of the * vertex link, and so can be much faster than analysing the * result of buildLink(). * * @return one of the predefined link constants in NVertex. */ int getLink() const; /** * Returns a full 2-manifold triangulation describing * the link of this vertex. * * This routine is fast (it uses a pre-computed triangulation if * possible). The downside is that the triangulation is read-only, * and does not contain any information on how the triangles in the * link correspond to tetrahedra in the original triangulation * (though this is easily deduced; see below). * If you want a writable triangulation, or one with this extra * information, then call buildLinkDetail() instead. * * The triangulation of the vertex link is built as follows. * Let \a i lie between 0 and getDegree()-1 inclusive, let * \a tet represent getEmbedding(i).getTetrahedron(), * and let \a v represent getEmbedding(i).getVertex(). * Then buildLink()->getTriangle(i) is the triangle * in the vertex link that "slices off" vertex \a v from * tetrahedron \a tet. In other words, * buildLink()->getTriangle(i) in the vertex link * is parallel to triangle tet->getTriangle(v) in the * surrounding 3-manifold triangulation. * * The vertices of each triangle in the vertex link are * numbered as follows. Following the discussion above, * suppose that buildLink()->getTriangle(i) sits within * \c tet and is parallel to tet->getTriangle(v). * Then vertices 0,1,2 of the triangle in the link will be * parallel to vertices 0,1,2 of the corresponding NTriangle. * The permutation tet->getTriangleMapping(v) will map * vertices 0,1,2 of the triangle in the link to the * corresponding vertices of \c tet (those opposite \c v), * and will map 3 to \c v itself. * * This NVertex object will retain ownership of the triangulation * that is returned. If you wish to edit the triangulation, you * should make a new clone and edit the clone instead. * * @return the read-only triangulated link of the vertex. */ const Dim2Triangulation* buildLink() const; /** * Returns a full 2-manifold triangulation describing * the link of this vertex. * * This routine is heavyweight (it computes a new triangulation * each time). The benefit is that the triangulation is writeable, * and optionally contain detailed information on how the triangles * in the link correspond to tetrahedra in the original triangulation. * If you do not need this extra information, consider using the * faster buildLink() instead. * * See the buildLink() documentation for an explanation of * exactly how the triangulation will be constructed. * * If \a labels is passed as \c true, each triangle of the new * vertex link will be given a text description of the form * t (v), where \c t is the index of the tetrahedron * the triangle is from, and \c v is the vertex of that tetrahedron * that this triangle links. * * If \a inclusion is non-null (i.e., it points to some * NIsomorphism pointer \a p), then it will be modified to * point to a new NIsomorphism that describes in detail how the * individual triangles of the link sit within tetrahedra of * the original triangulation. Specifically, after this routine * is called, p->tetImage(i) will indicate which tetrahedron * \a tet of the 3-manifold triangulation contains the ith * triangle of the link. Moreover, p->facePerm(i) will * indicate exactly where the ith triangle sits within \a tet: * it will send 3 to the vertex of \a t that the triangle links, * and it will send 0,1,2 to the vertices of \a tet that are * parallel to vertices 0,1,2 of this triangle. * * The triangulation that is returned, as well as the isomorphism * if one was requested, will be newly allocated. The caller of * this routine is responsible for destroying these objects. * * Strictly speaking, this is an abuse of the NIsomorphism class * (the domain is a triangulation of the wrong dimension, and * the map is not 1-to-1 into the range tetrahedra). We use * it anyway, but you should not attempt to call any high-level * routines (such as NIsomorphism::apply). * * \ifacespython The second (isomorphism) argument is not present. * Instead this routine returns a pair (triangulation, isomorphism). * As a side-effect, the isomorphism will always be constructed * (i.e., it is not optional). * * @return a newly constructed triangulation of the link of this vertex. */ Dim2Triangulation* buildLinkDetail(bool labels = true, NIsomorphism** inclusion = 0) const; /** * Determines if the link of this vertex is closed. * * @return \c true if and only if the link of this vertex is * closed. */ bool isLinkClosed() const; /** * Determines if this vertex is an ideal vertex. * This requires the vertex link to be closed and not a * 2-sphere. * * @return \c true if and only if this is an ideal vertex. */ bool isIdeal() const; /** * Determines if this vertex lies on the boundary of the * triangulation. Ideal vertices are included as * being on the boundary. In fact, the only vertices not * considered as on the boundary are those whose links are * spheres. * * @return \c true if and only if this vertex lies on the boundary. * @see isIdeal() */ bool isBoundary() const; /** * Determines if this vertex is standard. * This requires the vertex link to be a sphere, disc, torus or * Klein bottle. * * @return \c true if and only if this vertex is standard. */ bool isStandard() const; /** * Determines if the vertex link is orientable. * * This routine does not require a full triangulation of the * vertex link, and so can be much faster than calling * buildLink().isOrientable(). * * @return \c true if and only if the vertex link is orientable. */ bool isLinkOrientable() const; /** * Returns the Euler characteristic of the vertex link. * * This routine does not require a full triangulation of the * vertex link, and so can be much faster than calling * buildLink().getEulerChar(). * * @return the Euler characteristic of the vertex link. */ long getLinkEulerChar() const; /** * A deprecated alias for getLinkEulerChar(). * * Returns the Euler characteristic of the vertex link. * * This routine does not require a full triangulation of the * vertex link, and so can be much faster than calling * buildLink().getEulerChar(). * * \deprecated This routine will be removed in a future version of * Regina. Please use the identical routine getLinkEulerChar() instead. * * @return the Euler characteristic of the vertex link. */ long getLinkEulerCharacteristic() const; void writeTextShort(std::ostream& out) const; void writeTextLong(std::ostream& out) const; private: /** * Creates a new vertex and marks it as belonging to the * given triangulation component. * * @param myComponent the triangulation component to which this * vertex belongs. */ NVertex(NComponent* myComponent); friend class NTriangulation; /**< Allow access to private members. */ }; /*@}*/ } // namespace regina // Some more headers that are required for inline functions: #include "triangulation/ntetrahedron.h" namespace regina { // Inline functions for NVertex inline NVertex::NVertex(NComponent* myComponent) : component_(myComponent), boundaryComponent_(0), linkOrientable_(true), linkEulerChar_(0), linkTri_(0) { } inline unsigned long NVertex::index() const { return markedIndex(); } inline NTriangulation* NVertex::getTriangulation() const { return embeddings_.front().getTetrahedron()->getTriangulation(); } inline NComponent* NVertex::getComponent() const { return component_; } inline NBoundaryComponent* NVertex::getBoundaryComponent() const { return boundaryComponent_; } inline unsigned long NVertex::getDegree() const { return embeddings_.size(); } inline int NVertex::getLink() const { return link_; } inline const Dim2Triangulation* NVertex::buildLink() const { if (! linkTri_) { // This is a construct-on-demand member: cast away constness to // set it here. const_cast(this)->linkTri_ = buildLinkDetail(false, 0); } return linkTri_; } inline bool NVertex::isLinkClosed() const { return (link_ != DISC && link_ != NON_STANDARD_BDRY); } inline bool NVertex::isIdeal() const { return (link_ == TORUS || link_ == KLEIN_BOTTLE || link_ == NON_STANDARD_CUSP); } inline bool NVertex::isBoundary() const { return (boundaryComponent_ != 0); } inline bool NVertex::isStandard() const { return (link_ != NON_STANDARD_CUSP && link_ != NON_STANDARD_BDRY); } inline bool NVertex::isLinkOrientable() const { return linkOrientable_; } inline long NVertex::getLinkEulerChar() const { return linkEulerChar_; } inline long NVertex::getLinkEulerCharacteristic() const { return linkEulerChar_; } inline const std::vector& NVertex::getEmbeddings() const { return embeddings_; } inline unsigned long NVertex::getNumberOfEmbeddings() const { return embeddings_.size(); } inline const NVertexEmbedding& NVertex::getEmbedding(unsigned long index) const { return embeddings_[index]; } inline NVertexEmbedding::NVertexEmbedding() : tetrahedron_(0) { } inline NVertexEmbedding::NVertexEmbedding(NTetrahedron* newTet, int newVertex) : tetrahedron_(newTet), vertex_(newVertex) { } inline NVertexEmbedding::NVertexEmbedding(const NVertexEmbedding& cloneMe) : tetrahedron_(cloneMe.tetrahedron_), vertex_(cloneMe.vertex_) { } inline NVertexEmbedding& NVertexEmbedding::operator = (const NVertexEmbedding& cloneMe) { tetrahedron_ = cloneMe.tetrahedron_; vertex_ = cloneMe.vertex_; return *this; } inline NTetrahedron* NVertexEmbedding::getTetrahedron() const { return tetrahedron_; } inline int NVertexEmbedding::getVertex() const { return vertex_; } inline NPerm4 NVertexEmbedding::getVertices() const { return tetrahedron_->getVertexMapping(vertex_); } inline bool NVertexEmbedding::operator == (const NVertexEmbedding& other) const { return ((tetrahedron_ == other.tetrahedron_) && (vertex_ == other.vertex_)); } inline bool NVertexEmbedding::operator != (const NVertexEmbedding& other) const { return ((tetrahedron_ != other.tetrahedron_) || (vertex_ != other.vertex_)); } } // namespace regina #endif regina-4.96/engine/triangulation/nxmltrireader.cpp000644 000765 000024 00000025304 12377776771 022355 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "algebra/nxmlalgebrareader.h" #include "triangulation/nxmltrireader.h" #include "utilities/stringutils.h" namespace regina { /** * A unique namespace containing various specific-task packet readers. */ namespace { /** * Reads a single tetrahedron and its name and gluings. */ class NTetrahedronReader : public NXMLElementReader { private: NTriangulation* tri; NTetrahedron* tet; public: NTetrahedronReader(NTriangulation* newTri, unsigned whichTet) : tri(newTri), tet(tri->getTetrahedra()[whichTet]) { } virtual void startElement(const std::string&, const regina::xml::XMLPropertyDict& props, NXMLElementReader*) { tet->setDescription(props.lookup("desc")); } virtual void initialChars(const std::string& chars) { std::vector tokens; if (basicTokenise(back_inserter(tokens), chars) != 8) return; long tetIndex, permCode; NPerm4 perm; NTetrahedron* adjTet; int adjFace; for (int k = 0; k < 4; k ++) { if (! valueOf(tokens[2 * k], tetIndex)) continue; if (! valueOf(tokens[2 * k + 1], permCode)) continue; if (tetIndex < 0 || tetIndex >= static_cast(tri->getNumberOfTetrahedra())) continue; if (! NPerm4::isPermCode( static_cast(permCode))) continue; perm.setPermCode(static_cast(permCode)); adjTet = tri->getTetrahedra()[tetIndex]; adjFace = perm[k]; if (adjTet == tet && adjFace == k) continue; if (tet->adjacentTetrahedron(k)) continue; if (adjTet->adjacentTetrahedron(adjFace)) continue; tet->joinTo(k, adjTet, perm); } } }; /** * Reads an entire set of tetrahedra with their names and gluings. */ class NTetrahedraReader : public NXMLElementReader { private: NTriangulation* tri; unsigned readTets; public: NTetrahedraReader(NTriangulation* newTri) : tri(newTri), readTets(0) { } virtual void startElement(const std::string& /* tagName */, const regina::xml::XMLPropertyDict& props, NXMLElementReader*) { long nTets; if (valueOf(props.lookup("ntet"), nTets)) for ( ; nTets > 0; nTets--) tri->newTetrahedron(); } virtual NXMLElementReader* startSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict&) { if (subTagName == "tet") { if (readTets < tri->getNumberOfTetrahedra()) return new NTetrahedronReader(tri, readTets++); else return new NXMLElementReader(); } else return new NXMLElementReader(); } }; /** * Reads an abelian group property. */ class NAbelianGroupPropertyReader : public NXMLElementReader { public: typedef NProperty PropType; private: PropType& prop; public: NAbelianGroupPropertyReader(PropType& newProp) : prop(newProp) { } virtual NXMLElementReader* startSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict&) { if (subTagName == "abeliangroup") if (! prop.known()) return new NXMLAbelianGroupReader(); return new NXMLElementReader(); } virtual void endSubElement(const std::string& subTagName, NXMLElementReader* subReader) { if (subTagName == "abeliangroup") { NAbelianGroup* ans = dynamic_cast(subReader)-> getGroup(); if (ans) prop = ans; } } }; /** * Reads a group presentation property. */ class NGroupPresentationPropertyReader : public NXMLElementReader { public: typedef NProperty PropType; private: PropType& prop; public: NGroupPresentationPropertyReader(PropType& newProp) : prop(newProp) { } virtual NXMLElementReader* startSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict&) { if (subTagName == "group") if (! prop.known()) return new NXMLGroupPresentationReader(); return new NXMLElementReader(); } virtual void endSubElement(const std::string& subTagName, NXMLElementReader* subReader) { if (subTagName == "group") { NGroupPresentation* ans = dynamic_cast(subReader)-> getGroup(); if (ans) prop = ans; } } }; } NXMLElementReader* NXMLTriangulationReader::startContentSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict& props) { // We don't read boundary component properties since they're stored // across multiple property tags and they're easy to calculate // anyway. if (subTagName == "tetrahedra") return new NTetrahedraReader(tri); else if (subTagName == "zeroeff") { bool b; if (valueOf(props.lookup("value"), b)) tri->zeroEfficient_ = b; } else if (subTagName == "splitsfce") { bool b; if (valueOf(props.lookup("value"), b)) tri->splittingSurface_ = b; } else if (subTagName == "threesphere") { bool b; if (valueOf(props.lookup("value"), b)) tri->threeSphere_ = b; } else if (subTagName == "threeball") { bool b; if (valueOf(props.lookup("value"), b)) tri->threeBall_ = b; } else if (subTagName == "solidtorus") { bool b; if (valueOf(props.lookup("value"), b)) tri->solidTorus_ = b; } else if (subTagName == "irreducible") { bool b; if (valueOf(props.lookup("value"), b)) tri->irreducible_ = b; } else if (subTagName == "compressingdisc") { bool b; if (valueOf(props.lookup("compressingdisc"), b)) tri->compressingDisc_ = b; } else if (subTagName == "haken") { bool b; if (valueOf(props.lookup("haken"), b)) tri->haken_ = b; } else if (subTagName == "H1") return new NAbelianGroupPropertyReader(tri->H1_); else if (subTagName == "H1Rel") return new NAbelianGroupPropertyReader(tri->H1Rel_); else if (subTagName == "H1Bdry") return new NAbelianGroupPropertyReader(tri->H1Bdry_); else if (subTagName == "H2") return new NAbelianGroupPropertyReader(tri->H2_); else if (subTagName == "fundgroup") return new NGroupPresentationPropertyReader(tri->fundamentalGroup_); else if (subTagName == "turaevviro") { unsigned long r, root; double value; if (valueOf(props.lookup("r"), r) && valueOf(props.lookup("root"), root) && valueOf(props.lookup("value"), value)) tri->turaevViroCache_[std::make_pair(r, root)] = value; } return new NXMLElementReader(); } void NXMLTriangulationReader::endContentSubElement(const std::string&, NXMLElementReader*) { } NXMLPacketReader* NTriangulation::getXMLReader(NPacket*, NXMLTreeResolver& resolver) { return new NXMLTriangulationReader(resolver); } } // namespace regina regina-4.96/engine/triangulation/nxmltrireader.h000644 000765 000024 00000007451 12377775642 022021 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file triangulation/nxmltrireader.h * \brief Deals with parsing XML data for triangulation packets. */ #ifndef __NXMLTRIREADER_H #ifndef __DOXYGEN #define __NXMLTRIREADER_H #endif #include "regina-core.h" #include "packet/nxmlpacketreader.h" #include "triangulation/ntriangulation.h" namespace regina { /** * \weakgroup triangulation * @{ */ /** * An XML packet reader that reads a single triangulation. * * \ifacespython Not present. */ class REGINA_API NXMLTriangulationReader : public NXMLPacketReader { private: NTriangulation* tri; /**< The triangulation currently being read. */ public: /** * Creates a new triangulation reader. * * @param resolver the master resolver that will be used to fix * dangling packet references after the entire XML file has been read. */ NXMLTriangulationReader(NXMLTreeResolver& resolver); virtual NPacket* getPacket(); virtual NXMLElementReader* startContentSubElement( const std::string& subTagName, const regina::xml::XMLPropertyDict& subTagProps); virtual void endContentSubElement(const std::string& subTagName, NXMLElementReader* subReader); }; /*@}*/ // Inline functions for NXMLTriangulationReader inline NXMLTriangulationReader::NXMLTriangulationReader( NXMLTreeResolver& resolver) : NXMLPacketReader(resolver), tri(new NTriangulation()) { } inline NPacket* NXMLTriangulationReader::getPacket() { return tri; } } // namespace regina #endif regina-4.96/engine/triangulation/reorder.cpp000644 000765 000024 00000031362 12377776771 021140 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "maths/nperm4.h" #include "triangulation/ntriangulation.h" #include "triangulation/nedge.h" #include "triangulation/nisomorphism.h" #include #include namespace regina { namespace { // Begin anonymous namespace void reorder_fatal_error(const char* msg) { std::cerr << "ERROR: " << msg << std::endl; std::exit(1); } // Given is a tetrahedron with an ordering inducing edge orientations. // edge_orientations_on_tet[i] == -1 means that we intend to flip the // edge orientation of the i-th edge of the tetrahedron. // perm_from_edges returns the permutation that needs to be applied to the // tetrahedron to achieve this. NPerm4 perm_from_edges(const int edge_orientations_on_tet[6]) { // p[i] = number of edge_orientations pointing to vertex i int p[4] = {0, 0, 0, 0}; for(int i = 0; i < 6; i++) if(edge_orientations_on_tet[i] == +1) p[NEdge::edgeVertex[i][1]]++; else p[NEdge::edgeVertex[i][0]]++; // Consistency check for(int i = 0; i < 4; i++) { if(p[i] > 3 || p[i] < 0) reorder_fatal_error("bad permutation in reorder.cpp"); for(int j = i+1; j < 4; j++) if(p[i] == p[j]) reorder_fatal_error("bad permutation in reorder.cpp"); } return NPerm4(p[0],p[1],p[2],p[3]); } // edge_orientations[i] is the edge orientation of the i-th edge in // the triangulation // edge_orientations_tet[i] is the edge orientation of the i-th edge of // the tetrahedron // edge_orientations_tet[i] == +1 means that the edge is oriented pointing // from the lower to the higher vertex // writes the result into edge_orientations_tet void edge_orientations_on_tet(const NTriangulation &trig, const std::vector &edge_orientations, const NTetrahedron *tet, int edge_orientations_tet[6]) { for(int i = 0; i < 6; i++) { // to get the edge orientation on a tetrahedron's edge // look it up in edge_orientations int orientation = edge_orientations[trig.edgeIndex(tet->getEdge(i))]; // a tetrahedron's edge might be identified with the edge in the // triangulation in a way that the edge orientation is not consistent NPerm4 perm = tet->getEdgeMapping(i); if(perm[0] > perm[1]) orientation = - orientation; edge_orientations_tet[i] = orientation; } } // edge_orientations_tet are as above // v0, v1, v2 are the vertices of the face // It is assumed that v0 < v1 < v2 inline bool check_consistency_on_face(const int edge_orientations_tet[6], int v0, int v1, int v2) { // There are only two ways to get a cyclic orientation of edges on a face if( (edge_orientations_tet[NEdge::edgeNumber[v0][v1]] == +1) && (edge_orientations_tet[NEdge::edgeNumber[v1][v2]] == +1) && (edge_orientations_tet[NEdge::edgeNumber[v0][v2]] == -1)) return false; if( (edge_orientations_tet[NEdge::edgeNumber[v0][v1]] == -1) && (edge_orientations_tet[NEdge::edgeNumber[v1][v2]] == -1) && (edge_orientations_tet[NEdge::edgeNumber[v0][v2]] == +1)) return false; return true; } // edge_orientations[i] == 0 means that the edge_orientation has not been // assigned yet, so ignore it for testing // checks that the edge_orientations give an ordering of the triangulation bool check_consistency_on_tet(const NTriangulation &trig, const std::vector &edge_orientations, const NTetrahedron *tet, bool force_oriented) { int edge_orientations_tet[6]; // compute how the assignment of orientations to edges of the triangulation // look on the tetrahedron edge_orientations_on_tet(trig,edge_orientations,tet,edge_orientations_tet); // check that edge orientations are acyclic on each face of tet if(!check_consistency_on_face(edge_orientations_tet,1,2,3)) return false; if(!check_consistency_on_face(edge_orientations_tet,0,2,3)) return false; if(!check_consistency_on_face(edge_orientations_tet,0,1,3)) return false; if(!check_consistency_on_face(edge_orientations_tet,0,1,2)) return false; // if we do not need to check for consistent orientation, we are done: if(!force_oriented) return true; // orientation can't be determined until all edge_orientations are assigned for(int i = 0; i < 6; i++) if(edge_orientations_tet[i] == 0) return true; // check for valid orientation NPerm4 p = perm_from_edges(edge_orientations_tet); if(p.sign() * tet->orientation() == -1) return false; return true; } // checks that the edge orientations give a valid ordering of the triangulation bool check_consistency_around_edge(const NTriangulation &trig, const std::vector &edge_orientations, int edge_index, bool force_oriented) { typedef std::deque NEmbed; typedef NEmbed::const_iterator NEmbedIterator; NEdge* edge = trig.getEdge(edge_index); const NEmbed & edge_embeddings = edge -> getEmbeddings(); NEmbedIterator it; // iterate through all tetrahedra around an edge for(it = edge_embeddings.begin(); it != edge_embeddings.end(); ++it) if(!check_consistency_on_tet(trig, edge_orientations, it->getTetrahedron(), force_oriented)) return false; return true; } // construct isomorphism from edge orientations NIsomorphism* iso_from_edges(const NTriangulation &trig, const std::vector & edge_orientations, bool force_oriented) { NIsomorphism* iso = new NIsomorphism(trig.getNumberOfTetrahedra()); // iterate through all tetrahedra for(unsigned i = 0; i < trig.getNumberOfTetrahedra(); i++) { // consistency check if(!check_consistency_on_tet(trig, edge_orientations, trig.getTetrahedron(i), force_oriented)) reorder_fatal_error("Inconsistent edge orientations in reorder.cpp"); int edge_orientations_tet[6]; // compute how the edge orientations look on the tetrahedron edge_orientations_on_tet(trig, edge_orientations, trig.getTetrahedron(i), edge_orientations_tet); // derive the permutation iso->facePerm(i) = perm_from_edges(edge_orientations_tet); iso->tetImage(i) = i; } return iso; } // Find edge orientations (through back tracking) such that they induce a valid // ordering on each tetrahedron (and if force_oriented also a consistent // orientation on each tetrahedron). // If the function succeeds the isomorphism turning the triangulation into an // ordered triangulation is returned. NIsomorphism* ordering_iso(const NTriangulation &trig, bool force_oriented) { std::vector edge_orientations(trig.getNumberOfEdges(),0); int i = 0; while(true) { if(i < 0) return NULL; if(i >= static_cast(trig.getNumberOfEdges())) return iso_from_edges(trig, edge_orientations, force_oriented); if(edge_orientations[i] == 0) { edge_orientations[i] = +1; if(check_consistency_around_edge(trig,edge_orientations, i,force_oriented)) ++i; } else if(edge_orientations[i] == +1) { edge_orientations[i] = -1; if(check_consistency_around_edge(trig,edge_orientations, i,force_oriented)) ++i; } else { edge_orientations[i] = 0; --i; } } return NULL; } } // End anonymous namespace bool NTriangulation::isOriented() const { TetrahedronIterator it; // Calling isOrientable() will force a skeletal calculation if this // has not been done already. if(!isOrientable()) return false; for(it = tetrahedra_.begin(); it != tetrahedra_.end(); ++it) if( (*it) -> tetOrientation_ != 1) return false; return true; } void NTriangulation::orient() { if (! calculatedSkeleton_) calculateSkeleton(); NIsomorphism flip_tets_iso(getNumberOfTetrahedra()); TetrahedronIterator it; int t; for (t = 0, it = tetrahedra_.begin(); it != tetrahedra_.end(); ++it, ++t) { flip_tets_iso.tetImage(t) = t; if ((*it)->tetOrientation_ == 1 || ! (*it)->getComponent()->isOrientable()) flip_tets_iso.facePerm(t) = NPerm4(); // Identity else flip_tets_iso.facePerm(t) = NPerm4(2,3); } flip_tets_iso.applyInPlace(this); } bool NTriangulation::isOrdered() const { TetrahedronIterator it; for(it = tetrahedra_.begin(); it != tetrahedra_.end(); ++it) for(int face = 0; face < 4; face++) if((*it)->tetrahedra_[face]) { NPerm4 perm = (*it) -> tetrahedronPerm_[face]; // check that the permutation is order preserving on the face int last = -1; for(int k = 0; k < 4; ++k) if( k != face ) { if(perm[k] < last) return false; last = perm[k]; } } return true; } bool NTriangulation::order(bool force_oriented) { if(!calculatedSkeleton_) calculateSkeleton(); if(force_oriented && !isOrientable()) return false; // find the isomorphism to order (and orient) the triangulation NIsomorphism* iso = ordering_iso(*this, force_oriented); if(!iso) return false; // apply the isomorphism iso -> applyInPlace(this); delete iso; // consistency check if(! isOrdered()) reorder_fatal_error("NTriangulation::order returned unordered triangulation in reorder.cpp"); if(force_oriented && ! isOriented()) reorder_fatal_error("NTriangulation::order returned unoriented triangulation in reorder.cpp"); return true; } } regina-4.96/engine/triangulation/simplify.cpp000644 000765 000024 00000126351 12377776772 021336 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include "triangulation/ntriangulation.h" namespace regina { namespace { // Mapping from vertices (0,1,2) of each external triangular face of a new // tetrahedron to the vertices of this new tetrahedron in a 3-2 move. // Each new tetrahedron has its vertices numbered so that the corresponding // embedding permutation for the internal triangle is the identity. // Also, threeTwoVertices[i] refers to face i of the new tetrahedron for // each i. const NPerm4 threeTwoVertices[3] = { NPerm4(3,1,2,0), NPerm4(3,2,0,1), NPerm4(3,0,1,2) }; // Mapping from vertices (0,1,2) of each external triangular face of a new // tetrahedron to the vertices of this new tetrahedron in a 2-3 move. // Each new tetrahedron has its vertices numbered so that the corresponding // embedding permutation for the internal edge is the identity. // Also, twoThreeVertices[i] refers to face i of the new tetrahedron for // each i. const NPerm4 twoThreeVertices[2] = { NPerm4(1,2,3,0), NPerm4(0,2,3,1) }; // A helper routine that uses union-find to test whether a graph // contains cycles. This is used by collapseEdge(). // // This routine returns true if the given edge connects two distinct // components of the graph, or false if both endpoints of the edge // are already in the same component (i.e., a cycle has been created). bool unionFindInsert(long* parent, long* depth, long vtx1, long vtx2) { // Find the root of the tree containing vtx1 and vtx2. long top1, top2; for (top1 = vtx1; parent[top1] >= 0; top1 = parent[top1]) ; for (top2 = vtx2; parent[top2] >= 0; top2 = parent[top2]) ; // Are both vertices in the same component? if (top1 == top2) return false; // Join the two components. // Insert the shallower tree beneath the deeper tree. if (depth[top1] < depth[top2]) { parent[top1] = top2; } else { parent[top2] = top1; if (depth[top1] == depth[top2]) ++depth[top1]; } return true; } } bool NTriangulation::threeTwoMove(NEdge* e, bool check, bool perform) { const std::deque& embs = e->getEmbeddings(); if (check) { if (e->isBoundary() || ! e->isValid()) return false; if (embs.size() != 3) return false; } // Find the unwanted tetrahedra. NTetrahedron* oldTet[3]; NPerm4 oldVertexPerm[3]; std::set oldTets; int oldPos = 0; for (std::deque::const_iterator it = embs.begin(); it != embs.end(); it++) { oldTet[oldPos] =(*it).getTetrahedron(); if (check) if (! oldTets.insert(oldTet[oldPos]).second) return false; oldVertexPerm[oldPos] = (*it).getVertices(); oldPos++; } if (! perform) return true; #ifdef DEBUG std::cerr << "Performing 3-2 move\n"; #endif // Perform the move. ChangeEventSpan span(this); int oldPos2, newPos, newPos2; // Create the new tetrahedra. NTetrahedron* newTet[2]; for (newPos = 0; newPos < 2; newPos++) newTet[newPos] = newTetrahedron(); // Find the gluings from (0,1,2) of the new tetrahedron faces // to the vertices of the old tetrahedra. NPerm4 gluings[2][3]; for (oldPos = 0; oldPos < 3; oldPos++) for (newPos = 0; newPos < 2; newPos++) gluings[newPos][oldPos] = oldVertexPerm[oldPos] * twoThreeVertices[newPos]; // Find the tetrahedra to which the old tetrahedron faces are glued, // store the gluings from (0,1,2) of the new tetrahedron faces to the // vertices of these adjacent tetrahedra, and unjoin the tetrahedra. NTetrahedron* adjTet[2][3]; int adjFace; int oldFace; for (oldPos = 0; oldPos < 3; oldPos++) for (newPos = 0; newPos < 2; newPos++) { // Note that gluings[n][o][3] == oldVertexPerm[o][n], since // twoThreeVertices[i][3] == i. // oldFace = gluings[newPos][oldPos][3]; oldFace = oldVertexPerm[oldPos][newPos]; adjTet[newPos][oldPos] = oldTet[oldPos]->adjacentTetrahedron(oldFace); if (adjTet[newPos][oldPos]) { for (oldPos2 = 0; oldPos2 < 3; oldPos2++) { if (adjTet[newPos][oldPos] == oldTet[oldPos2]) { adjFace = oldTet[oldPos]->adjacentFace(oldFace); for (newPos2 = 0; newPos2 < 2; newPos2++) // if (gluings[newPos2][oldPos2][3] == adjFace) { if (oldVertexPerm[oldPos2][newPos2] == adjFace) { // Face oldFace of oldTet[oldPos] is glued to // face adjFace of oldTet[oldPos2] and should be // glued to face oldPos2 of newTet[newPos2]. if ((oldPos2 < oldPos) || (oldPos2 == oldPos && newPos2 < newPos)) { // We've already seen this gluing from // the other direction and // gluings[newPos2][oldPos2] has already // been modified. We'll have to leave // this gluing to be made from the // other direction. adjTet[newPos][oldPos] = 0; } else { adjTet[newPos][oldPos] = newTet[newPos2]; gluings[newPos][oldPos] = threeTwoVertices[oldPos2] * gluings[newPos2][oldPos2].inverse() * oldTet[oldPos]-> adjacentGluing(oldFace) * gluings[newPos][oldPos]; } break; } break; } } if (oldPos2 >= 3) gluings[newPos][oldPos] = oldTet[oldPos]->adjacentGluing(oldFace) * gluings[newPos][oldPos]; oldTet[oldPos]->unjoin(oldFace); } } // Remove the old tetrahedra from the triangulation. for (oldPos = 0; oldPos < 3; oldPos++) removeTetrahedron(oldTet[oldPos]); // Glue the faces of the new tetrahedra. for (oldPos = 0; oldPos < 3; oldPos++) for (newPos = 0; newPos < 2; newPos++) if (adjTet[newPos][oldPos]) newTet[newPos]->joinTo(oldPos, adjTet[newPos][oldPos], gluings[newPos][oldPos] * threeTwoVertices[oldPos].inverse()); newTet[0]->joinTo(3, newTet[1], NPerm4()); // Done!. return true; } bool NTriangulation::twoThreeMove(NTriangle* f, bool check, bool perform) { if (check) { if (f->getNumberOfEmbeddings() != 2) return false; // We now know that the given triangle is not on the boundary. } // Find the unwanted tetrahedra. NTetrahedron* oldTet[2]; NPerm4 oldVertexPerm[2]; int oldPos; for (oldPos = 0; oldPos < 2; oldPos++) { oldTet[oldPos] = f->getEmbedding(oldPos).getTetrahedron(); oldVertexPerm[oldPos] = f->getEmbedding(oldPos).getVertices(); } if (check) if (oldTet[0] == oldTet[1]) return false; if (! perform) return true; #ifdef DEBUG std::cerr << "Performing 2-3 move\n"; #endif // Actually perform the move. ChangeEventSpan span(this); int oldPos2, newPos, newPos2; // Allocate the new tetrahedra. NTetrahedron* newTet[3]; for (newPos = 0; newPos < 3; newPos++) newTet[newPos] = newTetrahedron(); // Find the gluings from (0,1,2) of the new tetrahedron faces // to the vertices of the old tetrahedra. NPerm4 gluings[3][2]; for (oldPos = 0; oldPos < 2; oldPos++) for (newPos = 0; newPos < 3; newPos++) gluings[newPos][oldPos] = oldVertexPerm[oldPos] * threeTwoVertices[newPos]; // Find the tetrahedra to which the old tetrahedron faces are glued, // store the gluings from (0,1,2) of the new tetrahedron faces to the // vertices of these adjacent tetrahedra, and unjoin the tetrahedra. NTetrahedron* adjTet[3][2]; int adjFace; int oldFace; for (oldPos = 0; oldPos < 2; oldPos++) for (newPos = 0; newPos < 3; newPos++) { // Note that gluings[n][o][3] == oldVertexPerm[o][n], since // threeTwoVertices[i][3] == i. // oldFace = gluings[newPos][oldPos][3]; oldFace = oldVertexPerm[oldPos][newPos]; adjTet[newPos][oldPos] = oldTet[oldPos]->adjacentTetrahedron(oldFace); if (adjTet[newPos][oldPos]) { for (oldPos2 = 0; oldPos2 < 2; oldPos2++) { if (adjTet[newPos][oldPos] == oldTet[oldPos2]) { adjFace = oldTet[oldPos]->adjacentFace(oldFace); for (newPos2 = 0; newPos2 < 3; newPos2++) // if (gluings[newPos2][oldPos2][3] == adjFace) { if (oldVertexPerm[oldPos2][newPos2] == adjFace) { // Face oldFace of oldTet[oldPos] is glued to // face adjFace of oldTet[oldPos2] and should be // glued to face oldPos2 of newTet[newPos2]. if ((oldPos2 < oldPos) || (oldPos2 == oldPos && newPos2 < newPos)) { // We've already seen this gluing from // the other direction and // gluings[newPos2][oldPos2] has already // been modified. We'll have to leave // this gluing to be made from the // other direction. adjTet[newPos][oldPos] = 0; } else { adjTet[newPos][oldPos] = newTet[newPos2]; gluings[newPos][oldPos] = twoThreeVertices[oldPos2] * gluings[newPos2][oldPos2].inverse() * oldTet[oldPos]-> adjacentGluing(oldFace) * gluings[newPos][oldPos]; } break; } break; } } if (oldPos2 >= 2) gluings[newPos][oldPos] = oldTet[oldPos]->adjacentGluing(oldFace) * gluings[newPos][oldPos]; oldTet[oldPos]->unjoin(oldFace); } } // Remove the old tetrahedra from the triangulation. for (oldPos = 0; oldPos < 2; oldPos++) removeTetrahedron(oldTet[oldPos]); // Glue the faces of the new tetrahedra. for (oldPos = 0; oldPos < 2; oldPos++) for (newPos = 0; newPos < 3; newPos++) if (adjTet[newPos][oldPos]) newTet[newPos]->joinTo(oldPos, adjTet[newPos][oldPos], gluings[newPos][oldPos] * twoThreeVertices[oldPos].inverse()); NPerm4 internalPerm = NPerm4(0,1,3,2); newTet[0]->joinTo(2, newTet[1], internalPerm); newTet[1]->joinTo(2, newTet[2], internalPerm); newTet[2]->joinTo(2, newTet[0], internalPerm); // Done! return true; } bool NTriangulation::oneFourMove(NTetrahedron* tet, bool /* check */, bool perform) { if ( !perform ) return true; // You can always do this move. ChangeEventSpan span(this); // Before we unglue, record how the adjacent tetrahedra are glued to tet. NTetrahedron* adjTet[4]; NPerm4 adjGlue[4]; unsigned i, j; for (i=0; i<4; i++) { adjTet[i] = tet->adjacentTetrahedron(i); if (adjTet[i]) adjGlue[i] = tet->adjacentGluing(i); } // Unglue the old tetrahedron. tet->isolate(); // The new tetrahedra. // Face i of the old tetrahedron will become a facet of newTet[i]. // Vertex i of newTet[i] will become the new internal vertex, and // the other three vertices of newTet[i] will keep the same vertex numbers // that they had in the old tetrahedron. NTetrahedron* newTet[4]; for (i = 0; i < 4; ++i) newTet[i] = newTetrahedron(); // Glue the new tetrahedra to each other internally. for (i = 0; i < 4; ++i) for (j = i + 1; j < 4; ++j) newTet[i]->joinTo(j, newTet[j], NPerm4(i, j)); // Attach the new tetrahedra to the old triangulation. for (i = 0; i < 4; ++i) { if (adjTet[i] == tet) { // The old tetrahedron was glued to itself. // We might have already made this gluing from the other side: if (newTet[i]->adjacentTetrahedron(i)) continue; // Nope, do it now. newTet[i]->joinTo(i, newTet[adjGlue[i][i]], adjGlue[i]); } else if (adjTet[i]) { // The old tetrahedron was glued elsewhere. newTet[i]->joinTo(i, adjTet[i], adjGlue[i]); } } // Delete the old tetrahedron. removeTetrahedron(tet); // All done! return true; } bool NTriangulation::fourFourMove(NEdge* e, int newAxis, bool check, bool perform) { const std::deque& embs = e->getEmbeddings(); if (check) { if (e->isBoundary() || ! e->isValid()) return false; if (embs.size() != 4) return false; } // Find the unwanted tetrahedra. NTetrahedron* oldTet[4]; std::set oldTets; int oldPos = 0; for (std::deque::const_iterator it = embs.begin(); it != embs.end(); it++) { oldTet[oldPos] =(*it).getTetrahedron(); if (check) if (! oldTets.insert(oldTet[oldPos]).second) return false; oldPos++; } if (! perform) return true; #ifdef DEBUG std::cerr << "Performing 4-4 move\n"; #endif // Perform the 4-4 move as a 2-3 move followed by a 3-2 move. ChangeEventSpan span(this); NTriangle* tri23 = (newAxis == 0 ? oldTet[0]->getTriangle(embs[0].getVertices()[2]) : oldTet[1]->getTriangle(embs[1].getVertices()[2])); int edge32 = embs[3].getEdge(); twoThreeMove(tri23, false, true); threeTwoMove(oldTet[3]->getEdge(edge32), false, true); // Done! return true; } bool NTriangulation::twoZeroMove(NEdge* e, bool check, bool perform) { if (check) { if (e->isBoundary() || ! e->isValid()) return false; if (e->getNumberOfEmbeddings() != 2) return false; } NTetrahedron* tet[2]; NPerm4 perm[2]; int i = 0; for (std::deque::const_iterator it = e->getEmbeddings().begin(); it != e->getEmbeddings().end(); it++) { tet[i] = (*it).getTetrahedron(); perm[i] = (*it).getVertices(); i++; } if (check) if (tet[0] == tet[1]) return false; if (check) { NEdge* edge[2]; NTriangle* triangle[2][2]; // triangle[i][j] will be on tetrahedron i opposite vertex j of the // internal edge. for (i=0; i<2; i++) { edge[i] = tet[i]->getEdge( NEdge::edgeNumber[perm[i][2]][perm[i][3]]); triangle[i][0] = tet[i]->getTriangle(perm[i][0]); triangle[i][1] = tet[i]->getTriangle(perm[i][1]); } if (edge[0] == edge[1]) return false; if (edge[0]->isBoundary() && edge[1]->isBoundary()) return false; if (triangle[0][0] == triangle[1][0]) return false; if (triangle[0][1] == triangle[1][1]) return false; // The cases with two pairs of identified triangles and with one // pair of identified triangles plus one pair of boundary triangles are // all covered by the following check. if (tet[0]->getComponent()->getNumberOfTetrahedra() == 2) return false; } if (! perform) return true; #ifdef DEBUG std::cerr << "Performing 2-0 move about edge\n"; #endif // Actually perform the move. ChangeEventSpan span(this); // Unglue faces from the doomed tetrahedra and glue them to each // other. NPerm4 crossover = tet[0]->adjacentGluing(perm[0][2]); NPerm4 gluing; NTetrahedron* top; NTetrahedron* bottom; int topFace; for (i=0; i<2; i++) { top = tet[0]->adjacentTetrahedron(perm[0][i]); bottom = tet[1]->adjacentTetrahedron(perm[1][i]); if (! top) { // Bottom triangle becomes boundary. tet[1]->unjoin(perm[1][i]); } else if (! bottom) { // Top triangle becomes boundary. tet[0]->unjoin(perm[0][i]); } else { // Bottom and top triangles join. topFace = tet[0]->adjacentFace(perm[0][i]); gluing = tet[1]->adjacentGluing(perm[1][i]) * crossover * top->adjacentGluing(topFace); tet[0]->unjoin(perm[0][i]); tet[1]->unjoin(perm[1][i]); top->joinTo(topFace, bottom, gluing); } } // Finally remove and dispose of the tetrahedra. removeTetrahedron(tet[0]); removeTetrahedron(tet[1]); // Tidy up. // Properties have already been cleared in removeTetrahedron(). return true; } bool NTriangulation::twoZeroMove(NVertex* v, bool check, bool perform) { if (check) { if (v->getLink() != NVertex::SPHERE) return false; if (v->getNumberOfEmbeddings() != 2) return false; } NTetrahedron* tet[2]; int vertex[2]; std::vector::const_iterator it; int i = 0; for (it = v->getEmbeddings().begin(); it != v->getEmbeddings().end(); it++) { tet[i] = (*it).getTetrahedron(); vertex[i] = (*it).getVertex(); i++; } if (check) { if (tet[0] == tet[1]) return false; NTriangle* triangle[2]; for (i = 0; i < 2; i++) triangle[i] = tet[i]->getTriangle(vertex[i]); if (triangle[0] == triangle[1]) return false; if (triangle[0]->isBoundary() && triangle[1]->isBoundary()) return false; // Check that the tetrahedra are joined along all three triangles. for (i = 0; i < 4; i++) { if (i == vertex[0]) continue; if (tet[0]->adjacentTetrahedron(i) != tet[1]) return false; } } if (! perform) return true; #ifdef DEBUG std::cerr << "Performing 2-0 move about vertex\n"; #endif // Actually perform the move. ChangeEventSpan span(this); // Unglue faces from the doomed tetrahedra and glue them to each // other. NTetrahedron* top = tet[0]->adjacentTetrahedron(vertex[0]); NTetrahedron* bottom = tet[1]->adjacentTetrahedron(vertex[1]); if (! top) { tet[1]->unjoin(vertex[1]); } else if (! bottom) { tet[0]->unjoin(vertex[0]); } else { NPerm4 crossover; if (vertex[0] == 0) crossover = tet[0]->adjacentGluing(1); else crossover = tet[0]->adjacentGluing(0); int topFace = tet[0]->adjacentFace(vertex[0]); NPerm4 gluing = tet[1]->adjacentGluing(vertex[1]) * crossover * top->adjacentGluing(topFace); tet[0]->unjoin(vertex[0]); tet[1]->unjoin(vertex[1]); top->joinTo(topFace, bottom, gluing); } // Finally remove and dispose of the tetrahedra. removeTetrahedron(tet[0]); removeTetrahedron(tet[1]); // Tidy up. // Properties have already been cleared in removeTetrahedron(). return true; } bool NTriangulation::twoOneMove(NEdge* e, int edgeEnd, bool check, bool perform) { // edgeEnd is the end opposite where the action is. if (check) { if (e->isBoundary() || ! e->isValid()) return false; if (e->getNumberOfEmbeddings() != 1) return false; } const NEdgeEmbedding& emb = e->getEmbeddings().front(); NTetrahedron* oldTet = emb.getTetrahedron(); NPerm4 oldVertices = emb.getVertices(); NTetrahedron* top = oldTet->adjacentTetrahedron(oldVertices[edgeEnd]); int otherEdgeEnd = 1 - edgeEnd; if (check) if (! top) return false; NTriangle* centreTri = oldTet->getTriangle(oldVertices[edgeEnd]); NTriangle* bottomTri = oldTet->getTriangle(oldVertices[otherEdgeEnd]); NPerm4 bottomToTop = oldTet->adjacentGluing(oldVertices[edgeEnd]); int topGlued[2]; NEdge* flatEdge[2]; int i; for (i=0; i<2; i++) { topGlued[i] = bottomToTop[oldVertices[i + 2]]; flatEdge[i] = top->getEdge( NEdge::edgeNumber[topGlued[i]][bottomToTop[oldVertices[edgeEnd]]]); } if (check) { if (centreTri == bottomTri) return false; if (flatEdge[0] == flatEdge[1]) return false; if (flatEdge[0]->isBoundary() && flatEdge[1]->isBoundary()) return false; // This next test should follow from the two edges being distinct, // but we'll do it anyway. if (top->getTriangle(topGlued[0]) == top->getTriangle(topGlued[1])) return false; } if (! perform) return true; #ifdef DEBUG std::cerr << "Performing 2-1 move\n"; #endif // Go ahead and perform the move. ChangeEventSpan span(this); // First glue together the two faces that will be flattened. NTetrahedron* adjTet[2]; adjTet[0] = top->adjacentTetrahedron(topGlued[0]); adjTet[1] = top->adjacentTetrahedron(topGlued[1]); if (! adjTet[0]) top->unjoin(topGlued[1]); else if (! adjTet[1]) top->unjoin(topGlued[0]); else { int adjFace[2]; adjFace[0] = top->adjacentFace(topGlued[0]); adjFace[1] = top->adjacentFace(topGlued[1]); NPerm4 gluing = top->adjacentGluing(topGlued[1]) * NPerm4(topGlued[0], topGlued[1]) * adjTet[0]->adjacentGluing(adjFace[0]); top->unjoin(topGlued[0]); top->unjoin(topGlued[1]); adjTet[0]->joinTo(adjFace[0], adjTet[1], gluing); } // Now make the new tetrahedron and glue it to itself. NTetrahedron* newTet = newTetrahedron(); newTet->joinTo(2, newTet, NPerm4(2,3)); // Glue the new tetrahedron into the remaining structure. if (oldTet->adjacentTetrahedron(oldVertices[otherEdgeEnd]) == top) { // The top of the new tetrahedron must be glued to the bottom. int topFace = bottomToTop[oldVertices[otherEdgeEnd]]; NPerm4 bottomFacePerm = NPerm4(oldVertices[edgeEnd], oldVertices[otherEdgeEnd], oldVertices[2], oldVertices[3]); NPerm4 gluing = bottomFacePerm.inverse() * top->adjacentGluing(topFace) * bottomToTop * bottomFacePerm * NPerm4(0,1); top->unjoin(topFace); newTet->joinTo(0, newTet, gluing); } else { int bottomFace = oldVertices[otherEdgeEnd]; int topFace = bottomToTop[bottomFace]; NTetrahedron* adjTop = top->adjacentTetrahedron(topFace); NTetrahedron* adjBottom = oldTet->adjacentTetrahedron(bottomFace); NPerm4 bottomFacePerm = NPerm4(oldVertices[edgeEnd], oldVertices[otherEdgeEnd], oldVertices[2], oldVertices[3]); if (adjTop) { NPerm4 topGluing = top->adjacentGluing(topFace) * bottomToTop * bottomFacePerm * NPerm4(0,1); top->unjoin(topFace); newTet->joinTo(0, adjTop, topGluing); } if (adjBottom) { NPerm4 bottomGluing = oldTet->adjacentGluing(bottomFace) * bottomFacePerm; oldTet->unjoin(bottomFace); newTet->joinTo(1, adjBottom, bottomGluing); } } // Finally remove and dispose of the unwanted tetrahedra. removeTetrahedron(oldTet); removeTetrahedron(top); // Tidy up. // Properties have already been cleared in removeTetrahedron(). return true; } bool NTriangulation::openBook(NTriangle* f, bool check, bool perform) { const NTriangleEmbedding& emb = f->getEmbedding(0); NTetrahedron* tet = emb.getTetrahedron(); NPerm4 vertices = emb.getVertices(); // Check that the triangle has exactly two boundary edges. // Note that this will imply that the triangle joins two tetrahedra. if (check) { int fVertex = -1; int nBdry = 0; if (tet->getEdge(NEdge::edgeNumber[vertices[0]][vertices[1]])-> isBoundary()) nBdry++; else fVertex = 2; if (tet->getEdge(NEdge::edgeNumber[vertices[1]][vertices[2]])-> isBoundary()) nBdry++; else fVertex = 0; if (tet->getEdge(NEdge::edgeNumber[vertices[2]][vertices[0]])-> isBoundary()) nBdry++; else fVertex = 1; if (nBdry != 2) return false; if (tet->getVertex(vertices[fVertex])->getLink() != NVertex::DISC) return false; if (! f->getEdge(fVertex)->isValid()) return false; } if (! perform) return true; #ifdef DEBUG std::cerr << "Performing open book move\n"; #endif // Actually perform the move. // Don't bother with a block since this is so simple. tet->unjoin(emb.getTriangle()); return true; } bool NTriangulation::closeBook(NEdge* e, bool check, bool perform) { if (check) { if (! e->isBoundary()) return false; } // Find the two triangles on either side of edge e. const NEdgeEmbedding& front = e->getEmbeddings().front(); const NEdgeEmbedding& back = e->getEmbeddings().back(); NTetrahedron* t0 = front.getTetrahedron(); NTetrahedron* t1 = back.getTetrahedron(); NPerm4 p0 = front.getVertices(); NPerm4 p1 = back.getVertices(); if (check) { if (t0->getTriangle(p0[3]) == t1->getTriangle(p1[2])) return false; if (t0->getVertex(p0[2]) == t1->getVertex(p1[3])) return false; if (t0->getVertex(p0[2])->getLink() != NVertex::DISC || t1->getVertex(p1[3])->getLink() != NVertex::DISC) return false; NEdge* e1 = t0->getEdge(NEdge::edgeNumber[p0[0]][p0[2]]); NEdge* e2 = t0->getEdge(NEdge::edgeNumber[p0[1]][p0[2]]); NEdge* f1 = t1->getEdge(NEdge::edgeNumber[p1[0]][p1[3]]); NEdge* f2 = t1->getEdge(NEdge::edgeNumber[p1[1]][p1[3]]); if (e1 == e2 && f1 == f2) return false; } if (! perform) return true; #ifdef DEBUG std::cerr << "Performing close book move\n"; #endif // Actually perform the move. // Don't bother with a block since this is so simple. t0->joinTo(p0[3], t1, p1 * NPerm4(2, 3) * p0.inverse()); return true; } bool NTriangulation::shellBoundary(NTetrahedron* t, bool check, bool perform) { // To perform the move we don't even need a skeleton. if (check) { if (! calculatedSkeleton_) calculateSkeleton(); int nBdry = 0; int i, j; int bdry[4]; for (i=0; i<4; i++) if (t->getTriangle(i)->isBoundary()) bdry[nBdry++] = i; if (nBdry < 1 || nBdry > 3) return false; if (nBdry == 1) { if (t->getVertex(bdry[0])->isBoundary()) return false; NEdge* internal[3]; j = 0; for (i = 0; i < 4; ++i) if (i != bdry[0]) internal[j++] = t->getEdge(NEdge::edgeNumber[bdry[0]][i]); if (! (internal[0]->isValid() && internal[1]->isValid() && internal[2]->isValid())) return false; if (internal[0] == internal[1] || internal[1] == internal[2] || internal[2] == internal[0]) return false; } else if (nBdry == 2) { i = NEdge::edgeNumber[bdry[0]][bdry[1]]; if (t->getEdge(i)->isBoundary()) return false; if (! t->getEdge(i)->isValid()) return false; if (t->adjacentTetrahedron(NEdge::edgeVertex[5 - i][0]) == t) return false; } } if (! perform) return true; #ifdef DEBUG std::cerr << "Performing shell boundary move\n"; #endif // Actually perform the move. // Don't bother with a block since this is so simple. removeTetrahedron(t); return true; } bool NTriangulation::collapseEdge(NEdge* e, bool check, bool perform) { // Find the tetrahedra to remove. const std::deque& embs = e->getEmbeddings(); std::deque::const_iterator it; NTetrahedron* tet = 0; NPerm4 p; if (check) { // Note: We never check whether the edge is valid, but this // comes automatically from the other tests. In particular, an // invalid edge must join the same vertex to itself. // CHECK 0: The tetrahedra around the edge must be distinct. // We check this as follows: // // - None of the triangles containing edge e must contain e twice. // We throw this into check 2 below (see point [0a]). // // - The only remaining bad case is where a tetrahedron contains // e as two opposite edges. In this case one can prove that // we have a bad chain of bigons, which will be picked up in // check 2 below. // CHECK 1: Can we collapse the edge to a point (creating bigons and // pillows with bigon boundaries)? // The vertices must be distinct. if (e->getVertex(0) == e->getVertex(1)) return false; // If both vertices are in the boundary then we must be collapsing a // boundary edge, and both vertices must have plain old disc links. // Recall that ideal vertices return isBoundary() == true. if (e->getVertex(0)->isBoundary() && e->getVertex(1)->isBoundary()) { if (! e->isBoundary()) return false; if (e->getVertex(0)->getLink() != NVertex::DISC) return false; if (e->getVertex(1)->getLink() != NVertex::DISC) return false; } // CHECK 2: Can we flatten each bigon to an edge (leaving // triangular pillows behind)? // // This is trickier. Even if every individual bigon is okay, we // don't want a _chain_ of bigons together to crush a sphere or // projective plane. // // The way we do this is as follows. Consider each NEdge* to be // a vertex of some graph G, and consider each bigon to be an edge // in this graph G. The vertices at either end of the edge in G // are the (NEdge*)s that bound the bigon. // // We can happily flatten each bigon if and only if the graph G // contains no cycles. We shall test this using union-find, // which should have log-linear complexity. // // We deal with boundary edges and invalid edges as follows. // All boundary and/or invalid edges become the *same* vertex in // the graph G. This means, for instance, that a bigon joining two // distinct boundary edges is not allowed. Invalid edges are // included here because each invalid edge contains a projective // plane cusp at its centre. // // If edge e is itself a boundary edge, things become more // interesting again. In this case, the two *boundary* bigons // are not subject to the same restrictions -- crushing bigons // along the boundary does no harm, *unless* the boundary bigon // edges themselves form a cycle. This is essentially the same // dilemma as before but one dimension down. We can detect this // because it implies either: // // - two edges of the same bigon are identified, and hence the // two vertices of edge e are identified (which has already // been disallowed in check 1 above); // // - the four edges of the two boundary bigons are identified in // pairs, which means the entire boundary component consists // of the two bigons and nothing else. // // What does this mean in a practical sense? If edge e is a // boundary edge, we: // // - verify that the boundary component has more than two triangles; // // - then ignore both boundary bigons from here onwards. // // Quite pleasant to deal with in the end. if (e->isBoundary()) if (e->getBoundaryComponent()->getNumberOfTriangles() == 2) return false; { long nEdges = edges_.size(); // The parent of each edge in the union-find tree, or -1 if // an edge is at the root of a tree. // // This array is indexed by edge number in the triangulation. // Although we might not use many of these edges, it's fast // and simple. The "unified boundary" is assigned the edge // number nEdges. long* parent = new long[nEdges + 1]; std::fill(parent, parent + nEdges + 1, -1); // The depth of each subtree in the union-find tree. long* depth = new long[nEdges + 1]; std::fill(depth, depth + nEdges + 1, 0); NEdge *upper, *lower; long id1, id2; // Run through all triangles containing e. it = embs.begin(); for ( ; it != embs.end(); ++it) { tet = it->getTetrahedron(); p = it->getVertices(); upper = tet->getEdge(NEdge::edgeNumber[p[0]][p[2]]); lower = tet->getEdge(NEdge::edgeNumber[p[1]][p[2]]); if (upper == e || lower == e) { // [0a]: Check 0 fails (see explanation earlier). delete[] depth; delete[] parent; return false; } // Now that we've run check 0, skip the first (boundary) // triangle if e is a boundary edge. We will skip the // last boundary triangle automatically, since for a boundary // edge there are k+1 triangles but only k embeddings. // // We do not need to worry about missing check 0 for // the last boundary triangle, since if it fails there then // it must also fail for the first. if (e->isBoundary() && it == embs.begin()) continue; id1 = ((upper->isBoundary() || ! upper->isValid()) ? nEdges : upper->markedIndex()); id2 = ((lower->isBoundary() || ! lower->isValid()) ? nEdges : lower->markedIndex()); // This bigon joins nodes id1 and id2 in the graph G. if (! unionFindInsert(parent, depth, id1, id2)) { delete[] depth; delete[] parent; return false; } } // No bad chains of bigons! delete[] depth; delete[] parent; } // CHECK 3: Can we flatten each triangular pillow to a triangle? // // Again, even if each individual pillow is okay, we don't want // a chain of pillows together to completely crush away a // 3-manifold component. // // This means no cycles of pillows, and no chains of pillows // that run from boundary to boundary. // // Test this in the same way that we tested edges. It's kind of // overkill, since each vertex in the corresponding graph G will // have degree <= 2, but it's fast so we'll do it. { long nTriangles = triangles_.size(); // The parent of each triangle in the union-find tree, or -1 if // a triangle is at the root of a tree. // // This array is indexed by triangle number in the triangulation. // The "unified boundary" is assigned the triangle number // nTriangles. long* parent = new long[nTriangles + 1]; std::fill(parent, parent + nTriangles + 1, -1); // The depth of each subtree in the union-find tree. long* depth = new long[nTriangles + 1]; std::fill(depth, depth + nTriangles + 1, 0); NTriangle *upper, *lower; long id1, id2; for (it = embs.begin(); it != embs.end(); ++it) { tet = it->getTetrahedron(); p = it->getVertices(); upper = tet->getTriangle(p[0]); lower = tet->getTriangle(p[1]); id1 = (upper->isBoundary() ? nTriangles : upper->markedIndex()); id2 = (lower->isBoundary() ? nTriangles : lower->markedIndex()); // This pillow joins nodes id1 and id2 in the graph G. if (! unionFindInsert(parent, depth, id1, id2)) { delete[] depth; delete[] parent; return false; } } // No bad chains of bigons! delete[] depth; delete[] parent; } } if (! perform) return true; #ifdef DEBUG std::cerr << "Performing edge collapse move\n"; #endif // Perform the move. ChangeEventSpan span(this); NPerm4 topPerm, botPerm; NTetrahedron *top, *bot; // Clone the edge embeddings because we cannot rely on skeletal // objects once we start changing the triangulation. unsigned long degree = embs.size(); NTetrahedron** embTet = new NTetrahedron*[degree]; NPerm4* embVertices = new NPerm4[degree]; unsigned i; for (i = 0, it = embs.begin(); it != embs.end(); ++i, ++it) { embTet[i] = (*it).getTetrahedron(); embVertices[i] = (*it).getVertices(); } for (i = 0; i < degree; ++i) { top = embTet[i]->adjacentTetrahedron(embVertices[i][0]); topPerm = embTet[i]->adjacentGluing(embVertices[i][0]); bot = embTet[i]->adjacentTetrahedron(embVertices[i][1]); botPerm = embTet[i]->adjacentGluing(embVertices[i][1]); embTet[i]->isolate(); if (top && bot) top->joinTo(topPerm[embVertices[i][0]], bot, botPerm * NPerm4(embVertices[i][0], embVertices[i][1]) * topPerm.inverse()); removeTetrahedron(embTet[i]); } delete[] embVertices; delete[] embTet; return true; } void NTriangulation::reorderTetrahedraBFS(bool reverse) { unsigned long n = getNumberOfTetrahedra(); if (n == 0) return; ChangeEventSpan span(this); // Run a breadth-first search over all tetrahedra. NTetrahedron** ordered = new NTetrahedron*[n]; bool* used = new bool[n]; std::fill(used, used + n, false); unsigned long filled = 0; /* Placed in ordered[]. */ unsigned long processed = 0; /* All neighbours placed in ordered[]. */ unsigned long nextTet = 0; /* Used to search for connected components. */ unsigned i; NTetrahedron *tet, *adj; while (processed < n) { if (filled == processed) { // Look for the next connected component. while (used[nextTet]) ++nextTet; ordered[filled++] = tetrahedra_[nextTet]; used[nextTet] = true; ++nextTet; } tet = ordered[processed]; // Add all neighbours of tet to the queue. for (i = 0; i < 4; ++i) if ((adj = tet->adjacentTetrahedron(i))) if (! used[adj->markedIndex()]) { ordered[filled++] = adj; used[adj->markedIndex()] = true; } ++processed; } // Flush the tetrahedra from the triangulation, and reinsert them in // the order in which they were found during the breadth-first search. tetrahedra_.clear(); unsigned long j; if (reverse) { for (j = n; j > 0; ) tetrahedra_.push_back(ordered[--j]); } else { for (j = 0; j < n; ) tetrahedra_.push_back(ordered[j++]); } delete[] used; delete[] ordered; } } // namespace regina regina-4.96/engine/triangulation/simplifyglobal.cpp000644 000765 000024 00000030560 12377776772 022513 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "triangulation/ntriangulation.h" // Affects the number of random 4-4 moves attempted during simplification. #define COEFF_4_4 5 namespace regina { bool NTriangulation::intelligentSimplify() { bool changed; { // Begin scope for change event block. ChangeEventSpan span(this); // Reduce to a local minimum. changed = simplifyToLocalMinimum(true); // Clone to work with when we might want to roll back changes. NTriangulation* use; // Variables used for selecting random 4-4 moves. std::vector > fourFourAvailable; std::pair fourFourChoice; unsigned long fourFourAttempts; unsigned long fourFourCap; NEdge* edge; EdgeIterator eit; int axis; while (true) { // --- Random 4-4 moves --- // Clone the triangulation and start making changes that might or // might not lead to a simplification. // If we've already simplified then there's no need to use a // separate clone since we won't need to undo further changes. use = (changed ? this : new NTriangulation(*this)); // Make random 4-4 moves. fourFourAttempts = fourFourCap = 0; while (true) { // Calculate the list of available 4-4 moves. fourFourAvailable.clear(); // Use getEdges() to ensure the skeleton has been calculated. for (eit = use->getEdges().begin(); eit != use->getEdges().end(); eit++) { edge = *eit; for (axis = 0; axis < 2; axis++) if (use->fourFourMove(edge, axis, true, false)) fourFourAvailable.push_back( std::make_pair(edge, axis)); } // Increment fourFourCap if needed. if (fourFourCap < COEFF_4_4 * fourFourAvailable.size()) fourFourCap = COEFF_4_4 * fourFourAvailable.size(); // Have we tried enough 4-4 moves? if (fourFourAttempts >= fourFourCap) break; // Perform a random 4-4 move on the clone. fourFourChoice = fourFourAvailable[ static_cast(rand()) % fourFourAvailable.size()]; use->fourFourMove(fourFourChoice.first, fourFourChoice.second, false, true); // See if we can simplify now. if (use->simplifyToLocalMinimum(true)) { // We have successfully simplified! // Start all over again. fourFourAttempts = fourFourCap = 0; } else fourFourAttempts++; } // Sync the real triangulation with the clone if appropriate. if (use != this) { // At this point, changed == false. if (use->getNumberOfTetrahedra() < getNumberOfTetrahedra()) { // The 4-4 moves were successful; accept them. cloneFrom(*use); changed = true; } delete use; } // At this point we have decided that 4-4 moves will help us // no more. // --- Open book and close book moves --- if (hasBoundaryTriangles()) { // Clone again, always -- we don't want to create gratuitous // boundary triangles if they won't be of any help. use = new NTriangulation(*this); // Perform every book opening move we can find. TriangleIterator fit; bool opened = false; bool openedNow = true; while (openedNow) { openedNow = false; for (fit = use->getTriangles().begin(); fit != use->getTriangles().end(); ++fit) if (use->openBook(*fit, true, true)) { opened = openedNow = true; break; } } // If we're lucky, we now have an edge that we can collapse. if (opened) { if (use->simplifyToLocalMinimum(true)) { // Yay! cloneFrom(*use); changed = true; } else { // No good. // Ditch use and don't open anything. opened = false; } } delete use; // If we did any book opening stuff, start all over again. if (opened) continue; // If we've made it this far then there seems to be // nothing left to do. // // Perform book *closing* moves to simplify the boundary // of the triangulation, even if this does not actually // reduce the number of tetrahedra. // // Since we always want to simplify the boundary, make // the changes directly to this triangulation. bool closed = false; EdgeIterator eit; for (eit = getEdges().begin(); eit != getEdges().end(); ++eit) if (closeBook(*eit, true, true)) { closed = true; changed = true; // We don't actually care whether we reduce the // number of tetrahedra or not. Ignore the // return value from simplifyToLocalMinimum(). simplifyToLocalMinimum(true); break; } // If we *did* manage to close a book, there might be // further internal simplifications that we can now do. // Back to the top. if (closed) continue; } // Nothing more we can do here. break; } } // End scope for change event span. return changed; } bool NTriangulation::simplifyToLocalMinimum(bool perform) { EdgeIterator eit; VertexIterator vit; BoundaryComponentIterator bit; NEdge* edge; unsigned long nTriangles; unsigned long iTriangle; // unsigned long nEdges; // unsigned long iEdge; // std::deque::const_iterator embit, embbeginit, embendit; bool changed = false; // Has anything changed ever (for return value)? bool changedNow = true; // Did we just change something (for loop control)? { // Begin scope for change event span. ChangeEventSpan span(this); while (changedNow) { changedNow = false; if (! calculatedSkeleton_) { calculateSkeleton(); } // Crush edges if we can. if (vertices_.size() > components_.size() && vertices_.size() > boundaryComponents_.size()) { for (eit = edges_.begin(); eit != edges_.end(); ++eit) { edge = *eit; if (collapseEdge(edge, true, perform)) { changedNow = changed = true; break; } } if (changedNow) { if (perform) continue; else return true; } } // Look for internal simplifications. for (eit = edges_.begin(); eit != edges_.end(); eit++) { edge = *eit; if (threeTwoMove(edge, true, perform)) { changedNow = changed = true; break; } if (twoZeroMove(edge, true, perform)) { changedNow = changed = true; break; } if (twoOneMove(edge, 0, true, perform)) { changedNow = changed = true; break; } if (twoOneMove(edge, 1, true, perform)) { changedNow = changed = true; break; } } if (changedNow) { if (perform) continue; else return true; } for (vit = vertices_.begin(); vit != vertices_.end(); vit++) { if (twoZeroMove(*vit, true, perform)) { changedNow = changed = true; break; } } if (changedNow) { if (perform) continue; else return true; } // Look for boundary simplifications. if (hasBoundaryTriangles()) { for (bit = boundaryComponents_.begin(); bit != boundaryComponents_.end(); bit++) { // Run through triangles of this boundary component looking // for shell boundary moves. nTriangles = (*bit)->getNumberOfTriangles(); for (iTriangle = 0; iTriangle < nTriangles; iTriangle++) { if (shellBoundary((*bit)->getTriangle(iTriangle)-> getEmbedding(0).getTetrahedron(), true, perform)) { changedNow = changed = true; break; } } if (changedNow) break; } if (changedNow) { if (perform) continue; else return true; } } } } // End scope for change event span. return changed; } } // namespace regina regina-4.96/engine/triangulation/skeleton.cpp000644 000765 000024 00000057047 12377776773 021334 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include "maths/nrational.h" #include "triangulation/ntriangulation.h" #include namespace regina { void NTriangulation::calculateSkeleton() const { ideal_ = false; valid_ = true; orientable_ = true; standard_ = true; #if 0 checkPermutations(); // Sets valid to false if gluings are mismatched (which should // never happen if the NTetrahedron gluing routines have been // used correctly) #endif // Set this now so that any tetrahedron query routines do not try to // recursively recompute the skeleton again. calculatedSkeleton_ = true; calculateComponents(); // Sets components, orientable, NComponent.orientable, // NTetrahedron.component calculateTriangles(); // Sets triangles, NTriangle.component calculateVertices(); // Sets vertices, NVertex.component, NVertex.linkOrientable. calculateEdges(); // Sets edges, NEdge.component, valid, NEdge.valid calculateBoundary(); // Sets boundaryComponents, NTriangle.boundaryComponent, // NEdge.boundaryComponent, NVertex.boundaryComponent, // NComponent.boundaryComponents calculateVertexLinks(); // Sets valid, ideal, NVertex.link, // NVertex.linkEulerChar, NComponent.ideal, // boundaryComponents, NVertex.boundaryComponent } void NTriangulation::checkPermutations() const { TetrahedronIterator it; for (it = tetrahedra_.begin(); it != tetrahedra_.end(); it++) for (int face = 0; face < 4; face++) { NTetrahedron * adjacent = (*it) -> adjacentTetrahedron(face); if (adjacent) { NPerm4 perm = (*it) -> adjacentGluing(face); NPerm4 adj_perm = adjacent -> adjacentGluing(perm[face]); if (!(perm*adj_perm).isIdentity()) { valid_ = false; // This printing statement is temporary code // to be removed once enough people have tested it std::cerr << "ERROR: Permutations of adjacent faces " "do not match in skeleton.cpp" << std::endl; } if ((*it) != adjacent -> adjacentTetrahedron(perm[face])) { valid_ = false; // This printing statement is temporary code // to be removed once enough people have tested it std::cerr << "ERROR: Adjacency relations do not match" " in skeleton.cpp" << std::endl; } } } } void NTriangulation::calculateComponents() const { TetrahedronIterator it; NComponent* label; NTetrahedron* tet; for (it = tetrahedra_.begin(); it != tetrahedra_.end(); it++) (*it)->component_ = 0; for (it = tetrahedra_.begin(); it != tetrahedra_.end(); it++) { tet = *it; if (tet->component_ == 0) { label = new NComponent(); labelComponent(tet, label); components_.push_back(label); } } } void NTriangulation::labelComponent(NTetrahedron* firstTet, NComponent* component) const { // Now non-recursive; uses a queue instead. // The queue contains tetrahedra from which we need to propagate // component labelling. // Use plain C arrays for the queue. Since each tetrahedron is pushed // on at most once, the array size does not need to be very large. // Note that we have >= 1 tetrahedron, since firstTet != 0. NTetrahedron** queue = new NTetrahedron*[tetrahedra_.size()]; firstTet->component_ = component; component->tetrahedra_.push_back(firstTet); firstTet->tetOrientation_ = 1; unsigned queueStart = 0, queueEnd = 1; queue[0] = firstTet; NTetrahedron* tet; NTetrahedron* adjTet; int face; int yourOrientation; while (queueStart < queueEnd) { tet = queue[queueStart++]; for (face=0; face<4; face++) { adjTet = tet->adjacentTetrahedron(face); if (adjTet) { yourOrientation = (tet->adjacentGluing(face). sign() == 1 ? -tet->tetOrientation_ : tet->tetOrientation_); if (adjTet->component_) { if (yourOrientation != adjTet->tetOrientation_) { orientable_ = false; component->orientable_ = false; } } else { adjTet->component_ = component; component->tetrahedra_.push_back(adjTet); adjTet->tetOrientation_ = yourOrientation; queue[queueEnd++] = adjTet; } } } } delete[] queue; } void NTriangulation::calculateVertices() const { TetrahedronIterator it; int vertex; NTetrahedron* tet; NVertex* label; for (it = tetrahedra_.begin(); it != tetrahedra_.end(); it++) { tet = *it; for (vertex=0; vertex<4; vertex++) tet->vertices_[vertex] = 0; } for (it = tetrahedra_.begin(); it != tetrahedra_.end(); it++) { tet = *it; for (vertex=0; vertex<4; vertex++) if (! tet->vertices_[vertex]) { label = new NVertex(tet->component_); tet->component_->vertices_.push_back(label); labelVertex(tet, vertex, label); vertices_.push_back(label); } } } void NTriangulation::labelVertex(NTetrahedron* firstTet, int firstVertex, NVertex* label) const { // Create a queue using simple arrays. // Since each tetrahedron vertex is pushed on at most once, the // array size does not need to be very large. // Note that we have >= 1 tetrahedron, since firstTet != 0. NTetrahedron** queueTet = new NTetrahedron*[tetrahedra_.size() * 4]; int* queueVtx = new int[tetrahedra_.size() * 4]; firstTet->vertices_[firstVertex] = label; firstTet->vertexMapping_[firstVertex] = NPerm4(0, firstVertex); firstTet->tmpOrientation_[firstVertex] = 1; label->embeddings_.push_back(NVertexEmbedding(firstTet, firstVertex)); unsigned queueStart = 0, queueEnd = 1; queueTet[0] = firstTet; queueVtx[0] = firstVertex; NTetrahedron* tet; NTetrahedron* adjTet; int vertex; int adjVertex; int adjOrientation; int face; NPerm4 adjMap; while (queueStart < queueEnd) { tet = queueTet[queueStart]; vertex = queueVtx[queueStart]; queueStart++; for (face=0; face<4; face++) { if (face == vertex) continue; adjTet = tet->adjacentTetrahedron(face); if (adjTet) { // When we choose an adjacent gluing map, throw in a // swap to preserve the "orientation" of the cycle // formed by the images of 1, 2 and 3. Note that this // only becomes meaningful if the vertex link is an // orientable surface (otherwise there is no consistent // way to orient these cycles at all). adjMap = tet->adjacentGluing(face) * tet->vertexMapping_[vertex] * NPerm4(1, 2); adjVertex = adjMap[0]; // We should actually be inverting NTriangle::ordering[adjVertex]. // However, all we care about is the sign of the permutation, // so let's save ourselves those extra few CPU cycles. if ((NTriangle::ordering[adjVertex] * tet->adjacentGluing(face) * NTriangle::ordering[vertex]).sign() > 0) adjOrientation = -(tet->tmpOrientation_[vertex]); else adjOrientation = tet->tmpOrientation_[vertex]; if (adjTet->vertices_[adjVertex]) { if (adjTet->tmpOrientation_[adjVertex] != adjOrientation) label->linkOrientable_ = false; } else { adjTet->vertices_[adjVertex] = label; adjTet->vertexMapping_[adjVertex] = adjMap; adjTet->tmpOrientation_[adjVertex] = adjOrientation; label->embeddings_.push_back(NVertexEmbedding(adjTet, adjVertex)); queueTet[queueEnd] = adjTet; queueVtx[queueEnd] = adjVertex; queueEnd++; } } } } delete[] queueTet; delete[] queueVtx; } void NTriangulation::calculateEdges() const { TetrahedronIterator it; int edge; NTetrahedron* tet; NEdge* label; for (it = tetrahedra_.begin(); it != tetrahedra_.end(); it++) { tet = *it; for (edge=0; edge<6; edge++) tet->edges_[edge] = 0; } for (it = tetrahedra_.begin(); it != tetrahedra_.end(); it++) { tet = *it; for (edge=0; edge<6; edge++) if (! tet->edges_[edge]) { label = new NEdge(tet->component_); tet->component_->edges_.push_back(label); labelEdge(tet, edge, label); edges_.push_back(label); } } } void NTriangulation::labelEdge(NTetrahedron* firstTet, int firstEdge, NEdge* label) const { // Since tetrahedron edges are joined together in a loop, the depth-first // search is really just a straight line in either direction. // We therefore do away with the usual stack/queue and just keep track // of the next edge to process in the current direction. firstTet->edges_[firstEdge] = label; firstTet->edgeMapping_[firstEdge] = NEdge::ordering[firstEdge]; label->embeddings_.push_back(NEdgeEmbedding(firstTet, firstEdge)); // The last tetrahedron edge that was successfully processed. NTetrahedron* tet; NPerm4 tetVertices; int exitFace; NPerm4 exitPerm; // The next tetrahedron edge around from this. NTetrahedron* nextTet; int nextEdge; NPerm4 nextVertices; for (int dir = 0; dir < 2; dir++) { // Start at the start and walk in one particular direction. tet = firstTet; tetVertices = tet->edgeMapping_[firstEdge]; while (true) { // Move through to the next tetrahedron. exitFace = tetVertices[dir == 0 ? 2 : 3]; nextTet = tet->adjacentTetrahedron(exitFace); if (! nextTet) break; exitPerm = tet->adjacentGluing(exitFace); nextVertices = exitPerm * tetVertices * NPerm4(2, 3); nextEdge = NEdge::edgeNumber[nextVertices[0]][nextVertices[1]]; if (nextTet->edges_[nextEdge]) { // We looped right around. // Check that we're not labelling the edge in reverse. if (nextTet->edgeMapping_[nextEdge][0] != nextVertices[0]) { // The edge is being labelled in reverse! label->valid_ = false; valid_ = false; } break; } // We have a new tetrahedron edge; this needs to be labelled. nextTet->edges_[nextEdge] = label; nextTet->edgeMapping_[nextEdge] = nextVertices; if (dir == 0) label->embeddings_.push_back(NEdgeEmbedding(nextTet, nextEdge)); else label->embeddings_.push_front(NEdgeEmbedding(nextTet, nextEdge)); tet = nextTet; tetVertices = nextVertices; } } } void NTriangulation::calculateTriangles() const { TetrahedronIterator it; int face; NTetrahedron* tet; NTetrahedron* adjTet; NTriangle* label; NPerm4 adjVertices; int adjFace; for (it = tetrahedra_.begin(); it != tetrahedra_.end(); it++) { tet = *it; for (face=0; face<4; face++) tet->triangles_[face] = 0; } for (it = tetrahedra_.begin(); it != tetrahedra_.end(); it++) { tet = *it; for (face=3; face>=0; face--) if (! tet->triangles_[face]) { label = new NTriangle(tet->component_); tet->component_->triangles_.push_back(label); tet->triangles_[face] = label; tet->triMapping_[face] = NTriangle::ordering[face]; label->embeddings_[0] = new NTriangleEmbedding(tet, face); label->nEmbeddings_ = 1; adjTet = tet->adjacentTetrahedron(face); if (adjTet) { // Triangle is not on the boundary. adjFace = tet->adjacentFace(face); adjVertices = (tet->adjacentGluing(face))* tet->triMapping_[face]; adjTet->triangles_[adjFace] = label; adjTet->triMapping_[adjFace] = adjVertices; label->embeddings_[1] = new NTriangleEmbedding(adjTet, adjFace); label->nEmbeddings_ = 2; } triangles_.push_back(label); } } } void NTriangulation::calculateBoundary() const { // Sets boundaryComponents, NTriangle.boundaryComponent, // NEdge.boundaryComponent, NVertex.boundaryComponent, // NComponent.boundaryComponents TriangleIterator it; NTriangle* triangle; NBoundaryComponent* label; for (it = triangles_.begin(); it != triangles_.end(); it++) { triangle = *it; if (triangle->nEmbeddings_ < 2) if (triangle->boundaryComponent_ == 0) { label = new NBoundaryComponent(); label->orientable_ = true; labelBoundaryTriangle(triangle, label); boundaryComponents_.push_back(label); triangle->component_->boundaryComponents_.push_back(label); } } } void NTriangulation::labelBoundaryTriangle(NTriangle* firstTriangle, NBoundaryComponent* label) const { std::queue triangleQueue; NTriangleEmbedding* emb; emb = firstTriangle->embeddings_[0]; firstTriangle->boundaryComponent_ = label; label->triangles_.push_back(firstTriangle); emb->getTetrahedron()->tmpOrientation_[emb->getTriangle()] = 1; triangleQueue.push(firstTriangle); NTetrahedron* tet; NPerm4 tetVertices; int tetFace; int i,j; NVertex* vertex; NEdge* edge; NTriangle* triangle; NTriangle* nextTriangle; int nextFaceNumber; NPerm4 nextFacePerm; NTetrahedron* nextTet; int followFromFace; NPerm4 switchPerm; int yourOrientation; while (! triangleQueue.empty()) { triangle = triangleQueue.front(); triangleQueue.pop(); // Run through the edges and vertices on this triangle. emb = triangle->embeddings_[0]; tet = emb->getTetrahedron(); tetFace = emb->getTriangle(); tetVertices = tet->triMapping_[tetFace]; // Run through the vertices. for (i=0; i<3; i++) { vertex = tet->vertices_[tetVertices[i]]; if (vertex->boundaryComponent_ != label) { // A vertex in an invalid triangulation might end up in // more than one boundary component. Push it into all // of the relevant boundary components' lists. vertex->boundaryComponent_ = label; label->vertices_.push_back(vertex); } } // Run through the edges. for (i=0; i<3; i++) for (j=i+1; j<3; j++) { edge = tet->edges_[NEdge::edgeNumber[tetVertices[i]] [tetVertices[j]]]; if (! (edge->boundaryComponent_)) { edge->boundaryComponent_ = label; label->edges_.push_back(edge); } // Label the adjacent boundary triangle with the same label. followFromFace = 6 - tetVertices[i] - tetVertices[j] - tetFace; switchPerm = NPerm4(followFromFace, tetFace); nextFaceNumber = followFromFace; nextFacePerm = NPerm4(); nextTet = tet; while (nextTet->adjacentTetrahedron(nextFaceNumber)) { nextFacePerm = nextTet->adjacentGluing( nextFaceNumber) * nextFacePerm * switchPerm; nextTet = nextTet->adjacentTetrahedron(nextFaceNumber); nextFaceNumber = nextFacePerm[followFromFace]; } nextTriangle = nextTet->triangles_[nextFaceNumber]; // Find the expected orientation of the next triangle. yourOrientation = (nextTet->triMapping_[nextFaceNumber].inverse() * nextFacePerm * switchPerm * tet->triMapping_[tetFace]) .sign() == 1 ? -tet->tmpOrientation_[tetFace] : tet->tmpOrientation_[tetFace]; if (nextTriangle->boundaryComponent_) { // Check the orientation. if (yourOrientation != nextTet->tmpOrientation_[nextFaceNumber]) label->orientable_ = false; } else { // Add this adjacent triangle to the queue. nextTriangle->boundaryComponent_ = label; label->triangles_.push_back(nextTriangle); nextTet->tmpOrientation_[nextFaceNumber] = yourOrientation; triangleQueue.push(nextTriangle); } } } } void NTriangulation::calculateVertexLinks() const { // Begin by calculating Euler characteristics. // Here we use the formula: chi = (2 v_int + v_bdry - f) / 2, which // is easily proven with a little arithmetic. // Note that NVertex::linkEulerChar is initialised to 0 in // the NVertex constructor. // Begin by calculating (2 v_int + v_bdry) for each vertex link. NEdge* e; NVertex* end0; NVertex* end1; NTetrahedron* tet; for (EdgeIterator eit = edges_.begin(); eit != edges_.end(); eit++) { e = *eit; // Try to compute e->getVertex(0) and e->getVertex(1), but // without calling e->getVertex() which will recursively try to // recompute the skeleton. const NEdgeEmbedding& emb = e->getEmbeddings().front(); tet = emb.getTetrahedron(); end0 = tet->vertices_[tet->edgeMapping_[emb.getEdge()][0]]; end1 = tet->vertices_[tet->edgeMapping_[emb.getEdge()][1]]; if (e->isBoundary()) { // Contribute to v_bdry. end0->linkEulerChar_++; if (e->valid_) end1->linkEulerChar_++; } else { // Contribute to 2 v_int. end0->linkEulerChar_ += 2; if (e->valid_) end1->linkEulerChar_ += 2; } } // Run through each vertex and finalise Euler characteristic, link // and more. NVertex* vertex; for (VertexIterator it = vertices_.begin(); it != vertices_.end(); it++) { vertex = *it; // Fix the Euler characteristic (subtract f, divide by two). vertex->linkEulerChar_ = (vertex->linkEulerChar_ - static_cast(vertex->getEmbeddings().size())) / 2; if (vertex->isBoundary()) { // We haven't added ideal vertices to the boundary list yet, // so this must be real boundary. if (vertex->linkEulerChar_ == 1) vertex->link_ = NVertex::DISC; else { vertex->link_ = NVertex::NON_STANDARD_BDRY; valid_ = false; standard_ = false; } } else { if (vertex->linkEulerChar_ == 2) vertex->link_ = NVertex::SPHERE; else { if (vertex->linkEulerChar_ == 0) vertex->link_ = (vertex->isLinkOrientable() ? NVertex::TORUS : NVertex::KLEIN_BOTTLE); else { vertex->link_ = NVertex::NON_STANDARD_CUSP; standard_ = false; } ideal_ = true; vertex->component_->ideal_ = true; NBoundaryComponent* bc = new NBoundaryComponent(vertex); bc->orientable_ = vertex->isLinkOrientable(); vertex->boundaryComponent_ = bc; boundaryComponents_.push_back(bc); vertex->component_->boundaryComponents_.push_back(bc); } } } } void NTriangulation::calculateBoundaryProperties() const { // Make sure the skeleton has been calculated! if (! calculatedSkeleton_) calculateSkeleton(); bool localTwoSphereBoundaryComponents = false; bool localNegativeIdealBoundaryComponents = false; for (BoundaryComponentIterator it = boundaryComponents_.begin(); it != boundaryComponents_.end(); it++) { if ((*it)->getEulerChar() == 2) localTwoSphereBoundaryComponents = true; else if ((*it)->isIdeal() && (*it)->getEulerChar() < 0) localNegativeIdealBoundaryComponents = true; // Stop the search if we've found everything we're looking for. if (localTwoSphereBoundaryComponents && localNegativeIdealBoundaryComponents) break; } twoSphereBoundaryComponents_ = localTwoSphereBoundaryComponents; negativeIdealBoundaryComponents_ = localNegativeIdealBoundaryComponents; } } // namespace regina regina-4.96/engine/triangulation/subdivide.cpp000644 000765 000024 00000042063 12377776774 021457 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include "triangulation/ntriangulation.h" #include "utilities/memutils.h" #include "utilities/stlutils.h" namespace regina { void NTriangulation::barycentricSubdivision() { // Rewritten for Regina 4.94 to use a more sensible labelling scheme. // IMPORTANT: If this code is ever rewritten (and in particular, if // the labelling of new tetrahedra ever changes), then the // drillEdge() code must be rewritten as well (since it relies on // the specific labelling scheme that we use here). unsigned long nOldTet = tetrahedra_.size(); if (nOldTet == 0) return; NTriangulation staging; ChangeEventSpan span1(&staging); NTetrahedron** newTet = new NTetrahedron*[nOldTet * 24]; NTetrahedron* oldTet; // A tetrahedron in the subdivision is uniquely defined by the // permutation (face, edge, vtx, corner) of (0, 1, 2, 3). // This is the tetrahedron that: // - meets the boundary in the face opposite vertex "face"; // - meets that face in the edge opposite vertex "edge"; // - meets that edge in the vertex opposite vertex "vtx"; // - directly touches vertex "corner". unsigned long tet; for (tet = 0; tet < 24 * nOldTet; ++tet) newTet[tet] = staging.newTetrahedron(); // Do all of the internal gluings int permIdx; NPerm4 perm, glue; for (tet=0; tet < nOldTet; ++tet) for (permIdx = 0; permIdx < 24; ++permIdx) { perm = NPerm4::S4[permIdx]; // (0, 1, 2, 3) -> (face, edge, vtx, corner) // Internal gluings within the old tetrahedron: newTet[24 * tet + permIdx]->joinTo(perm[3], newTet[24 * tet + (perm * NPerm4(3, 2)).S4Index()], NPerm4(perm[3], perm[2])); newTet[24 * tet + permIdx]->joinTo(perm[2], newTet[24 * tet + (perm * NPerm4(2, 1)).S4Index()], NPerm4(perm[2], perm[1])); newTet[24 * tet + permIdx]->joinTo(perm[1], newTet[24 * tet + (perm * NPerm4(1, 0)).S4Index()], NPerm4(perm[1], perm[0])); // Adjacent gluings to the adjacent tetrahedron: oldTet = getTetrahedron(tet); if (! oldTet->adjacentTetrahedron(perm[0])) continue; // This hits a boundary triangle. if (newTet[24 * tet + permIdx]->adjacentTetrahedron(perm[0])) continue; // We've already done this gluing from the other side. glue = oldTet->adjacentGluing(perm[0]); newTet[24 * tet + permIdx]->joinTo(perm[0], newTet[24 * tetrahedronIndex( oldTet->adjacentTetrahedron(perm[0])) + (glue * perm).S4Index()], glue); } // Delete the existing tetrahedra and put in the new ones. ChangeEventSpan span2(this); removeAllTetrahedra(); swapContents(staging); delete[] newTet; } void NTriangulation::drillEdge(NEdge* e) { // Recall from the barycentric subdivision code above that // a tetrahedron in the subdivision is uniquely defined by the // permutation (face, edge, vtx, corner) of (0, 1, 2, 3). // // For an edge (i,j) opposite vertices (k,l), the tetrahedra that // meet it are: // // (k,l,i,j) and (l,k,i,j), both containing the half-edge touching vertex j; // (k,l,j,i) and (l,k,j,i), both containing the half-edge touching vertex i. // // In each case the corresponding edge number in the new tetrahedron // equals the edge number from the original tetrahedron. int edgeNum = e->getEmbedding(0).getEdge(); long tetNum = tetrahedronIndex(e->getEmbedding(0).getTetrahedron()); int oldToNew[2]; // Identifies two of the 24 tetrahedra in a subdivision // that contain the two corresponding half-edges. oldToNew[0] = NPerm4( NEdge::edgeVertex[5 - edgeNum][0], NEdge::edgeVertex[5 - edgeNum][1], NEdge::edgeVertex[edgeNum][0], NEdge::edgeVertex[edgeNum][1]). S4Index(); oldToNew[1] = NPerm4( NEdge::edgeVertex[5 - edgeNum][0], NEdge::edgeVertex[5 - edgeNum][1], NEdge::edgeVertex[edgeNum][1], NEdge::edgeVertex[edgeNum][0]). S4Index(); ChangeEventSpan span(this); barycentricSubdivision(); barycentricSubdivision(); std::set toRemove; int i, j, k; unsigned long finalTet; NVertex* finalVertex; std::vector::const_iterator it; for (i = 0; i < 2; ++i) for (j = 0; j < 2; ++j) { finalTet = 24 * (24 * tetNum + oldToNew[i]) + oldToNew[j]; // Remove all tetrahedra that touch each endpoint of the // resulting edge in the second barycentric subdivision. for (k = 0; k < 2; ++k) { finalVertex = tetrahedra_[finalTet]->getEdge(edgeNum)-> getVertex(k); for (it = finalVertex->getEmbeddings().begin(); it != finalVertex->getEmbeddings().end(); ++it) toRemove.insert(tetrahedronIndex(it->getTetrahedron())); } } // Make sure we remove tetrahedra in reverse order, so the numbering // doesn't change. for (std::set::reverse_iterator rit = toRemove.rbegin(); rit != toRemove.rend(); ++rit) removeTetrahedronAt(*rit); // We have lots of tetrahedra now. Simplify. intelligentSimplify(); } bool NTriangulation::idealToFinite(bool forceDivision) { // The call to isValid() ensures the skeleton has been calculated. if (isValid() && ! isIdeal()) if (! forceDivision) return false; int i,j,k,l; long numOldTet = tetrahedra_.size(); if (! numOldTet) return false; NTriangulation staging; ChangeEventSpan span1(&staging); NTetrahedron **newTet = new NTetrahedron*[32*numOldTet]; for (i=0; i<32*numOldTet; i++) newTet[i] = staging.newTetrahedron(); int tip[4]; int interior[4]; int edge[4][4]; int vertex[4][4]; int nDiv = 0; for (j=0; j<4; j++) { tip[j] = nDiv++; interior[j] = nDiv++; for (k=0; k<4; k++) if (j != k) { edge[j][k] = nDiv++; vertex[j][k] = nDiv++; } } // First glue all of the tetrahedra inside the same // old tetrahedron together. for (i=0; ijoinTo(j, newTet[interior[j] + i * nDiv], NPerm4()); // Glue the interior tetrahedra to the others. for (j=0; j<4; j++) { for (k=0; k<4; k++) if (j != k) { newTet[interior[j] + i * nDiv]->joinTo(k, newTet[vertex[k][j] + i * nDiv], NPerm4()); } } // Glue the edge tetrahedra to the others. for (j=0; j<4; j++) for (k=0; k<4; k++) if (j != k) { newTet[edge[j][k] + i * nDiv]->joinTo(j, newTet[edge[k][j] + i * nDiv], NPerm4(j,k)); for (l=0; l<4; l++) if ( (l != j) && (l != k) ) newTet[edge[j][k] + i * nDiv]->joinTo(l, newTet[vertex[j][l] + i * nDiv], NPerm4(k,l)); } } // Now deal with the gluings between the pieces inside adjacent tetrahedra. NTetrahedron *ot; long oppTet; NPerm4 p; for (i=0; iadjacentTetrahedron(j)) { oppTet = tetrahedronIndex(ot->adjacentTetrahedron(j)); p = ot->adjacentGluing(j); // First deal with the tip tetrahedra. for (k=0; k<4; k++) if (j != k) newTet[tip[k] + i * nDiv]->joinTo(j, newTet[tip[p[k]] + oppTet * nDiv], p); // Next the edge tetrahedra. for (k=0; k<4; k++) if (j != k) newTet[edge[j][k] + i * nDiv]->joinTo(k, newTet[edge[p[j]][p[k]] + oppTet * nDiv], p); // Finally, the vertex tetrahedra. for (k=0; k<4; k++) if (j != k) newTet[vertex[j][k] + i * nDiv]->joinTo(k, newTet[vertex[p[j]][p[k]] + oppTet * nDiv], p); } } ChangeEventSpan span2(this); removeAllTetrahedra(); swapContents(staging); calculateSkeleton(); // Remove the tetrahedra that meet any of the non-standard or // ideal vertices. // First we make a list of the tetrahedra. std::vector tetList; std::vector::const_iterator vembit; for (VertexIterator vIter = vertices_.begin(); vIter != vertices_.end(); vIter++) if ((*vIter)->isIdeal() || ! (*vIter)->isStandard()) for (vembit = (*vIter)->getEmbeddings().begin(); vembit != (*vIter)->getEmbeddings().end(); vembit++) tetList.push_back((*vembit).getTetrahedron()); // Now remove the tetrahedra. // For each tetrahedron, remove it and delete it. for_each(tetList.begin(), tetList.end(), std::bind1st(std::mem_fun(&NTriangulation::removeTetrahedron), this)); delete[] newTet; return true; } bool NTriangulation::finiteToIdeal() { if (! hasBoundaryTriangles()) return false; // Make a list of all boundary triangles, indexed by triangle number, // and create the corresponding new tetrahedra. unsigned long nTriangles = getNumberOfTriangles(); NTriangulation staging; NTetrahedron** bdry = new NTetrahedron*[nTriangles]; NPerm4* bdryPerm = new NPerm4[nTriangles]; NTetrahedron** newTet = new NTetrahedron*[nTriangles]; ChangeEventSpan span1(&staging); TriangleIterator fit; unsigned i; for (i = 0, fit = triangles_.begin(); fit != triangles_.end(); ++i, ++fit) { if (! (*fit)->isBoundary()) { bdry[i] = newTet[i] = 0; continue; } bdry[i] = (*fit)->getEmbedding(0).getTetrahedron(); bdryPerm[i] = (*fit)->getEmbedding(0).getVertices(); } // Add the new tetrahedra one boundary component at a time, so that // the tetrahedron labels are compatible with previous versions of // regina (<= 4.6). BoundaryComponentIterator bit; for (bit = boundaryComponents_.begin(); bit != boundaryComponents_.end(); bit++) for (i = 0; i < (*bit)->getNumberOfTriangles(); ++i) newTet[(*bit)->getTriangle(i)->markedIndex()] = staging.newTetrahedron(); // Glue the new tetrahedra to each other. NEdge* edge; unsigned long tetTriangle1, tetTriangle2; NPerm4 t1Perm, t2Perm; for (bit = boundaryComponents_.begin(); bit != boundaryComponents_.end(); bit++) for (i = 0; i < (*bit)->getNumberOfEdges(); i++) { edge = (*bit)->getEdge(i); // This must be a valid boundary edge. // Find the boundary triangles at either end. NEdgeEmbedding e1 = edge->getEmbeddings().front(); NEdgeEmbedding e2 = edge->getEmbeddings().back(); tetTriangle1 = e1.getTetrahedron()->getTriangle( e1.getVertices()[3])->markedIndex(); tetTriangle2 = e2.getTetrahedron()->getTriangle( e2.getVertices()[2])->markedIndex(); t1Perm = bdryPerm[tetTriangle1].inverse() * e1.getVertices(); t2Perm = bdryPerm[tetTriangle2].inverse() * e2.getVertices() * NPerm4(2, 3); newTet[tetTriangle1]->joinTo(t1Perm[2], newTet[tetTriangle2], t2Perm * t1Perm.inverse()); } // Now join the new tetrahedra to the boundary triangles of the original // triangulation. // Set up a change block, since here we start changing the original // triangulation. ChangeEventSpan span2(this); staging.moveContentsTo(*this); for (i = 0; i < nTriangles; ++i) if (newTet[i]) newTet[i]->joinTo(3, bdry[i], bdryPerm[i]); // Clean up and return. delete[] newTet; delete[] bdryPerm; delete[] bdry; return true; } void NTriangulation::puncture(NTetrahedron* tet) { if (! tet) { // Preconditions disallow empty triangulations, but anyway: if (tetrahedra_.empty()) return; tet = tetrahedra_.front(); } ChangeEventSpan span(this); // We will attach a pair of triangular prisms to face 123 of tet. // We will join the rectangular walls of the prisms together, and // one triangular end from each will join to form the new S^2 boundary. NTetrahedron* prism[2][3]; // Create the new tetrahedra in an order that ensures that the new // S^2 boundary will appear in the final two tetrahedra. int i, j; for (j = 0; j < 3; ++j) for (i = 0; i < 2; ++i) prism[i][j] = newTetrahedron(); prism[0][0]->joinTo(0, prism[0][1], NPerm4(3,0,1,2)); prism[0][1]->joinTo(0, prism[0][2], NPerm4(3,0,1,2)); prism[1][0]->joinTo(1, prism[1][1], NPerm4(3,0,1,2)); prism[1][1]->joinTo(1, prism[1][2], NPerm4(3,2,0,1)); prism[0][0]->joinTo(1, prism[1][0], NPerm4(1,2,3,0)); prism[0][0]->joinTo(2, prism[1][0], NPerm4(1,2,3,0)); prism[0][1]->joinTo(1, prism[1][1], NPerm4(1,2,3,0)); prism[0][1]->joinTo(2, prism[1][1], NPerm4(1,2,3,0)); prism[0][2]->joinTo(1, prism[1][2], NPerm4(0,1,3,2)); prism[0][2]->joinTo(2, prism[1][2], NPerm4(0,1,3,2)); NTetrahedron* adj = tet->adjacentTetrahedron(0); if (adj) { NPerm4 gluing = tet->adjacentGluing(0); tet->unjoin(0); prism[1][0]->joinTo(0, adj, gluing); } tet->joinTo(0, prism[0][0], NPerm4(3,0,1,2)); } void NTriangulation::connectedSumWith(const NTriangulation& other) { // Precondition check. if (tetrahedra_.empty() || ! isConnected()) return; ChangeEventSpan span(this); NTetrahedron* toPuncture[2]; // Insert the other triangulation *before* puncturing, so that // things work in the case where we sum a triangulation with itself. unsigned long n = tetrahedra_.size(); insertTriangulation(other); toPuncture[0] = tetrahedra_[0]; toPuncture[1] = tetrahedra_[n]; NTetrahedron* bdry[2][2]; puncture(toPuncture[0]); bdry[0][0] = tetrahedra_[tetrahedra_.size() - 2]; bdry[0][1] = tetrahedra_[tetrahedra_.size() - 1]; puncture(toPuncture[1]); bdry[1][0] = tetrahedra_[tetrahedra_.size() - 2]; bdry[1][1] = tetrahedra_[tetrahedra_.size() - 1]; bdry[0][0]->joinTo(0, bdry[1][0], NPerm4(2, 3)); bdry[0][1]->joinTo(0, bdry[1][1], NPerm4(2, 3)); } } // namespace regina regina-4.96/engine/triangulation/surfaces.cpp000644 000765 000024 00000026520 12377776774 021314 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "enumerate/ntreetraversal.h" #include "triangulation/ntriangulation.h" #include "surfaces/nnormalsurfacelist.h" namespace regina { /** * When testing 0-efficiency, to prove that a normal 2-sphere must occur * at a vertex we use Euler characteristic arguments. One issue that * arises for non-orientable 3-manifolds is whether a non-vertex normal * 2-sphere can be decomposed into two-sided projective planes and other * surfaces of non-positive Euler characteristic. On this issue, Jaco * writes: * * "Remember that in any 3-manifold, regular curves of intersection between * normal surfaces are orientation preserving; thus if you add a two-sided * projective plane to any other surface, the curves of intersection must * be trivial curves on the projective plane - thus the result must be * nonorientable." */ /** * In the general case, 0-efficiency must be tested for in standard * triangle-quad coordinates. For example, the triangulation with * isosig dLQacccbnjk (which is ideal with one torus cusp) is * not 0-efficient, but the non-trivial sphere does not appear as a * vertex in quad coordinates. */ /** * Splitting surfaces must also be tested for in standard triangle-quad * coordinates. See the triangulation J_{1|3,-5} (chained triangular * solid torus of major type) of S^3 / Q_32 x Z_3 an an example of a * triangulation with a splitting surface having chi=-1 that can be * decomposed in quad space as the sum of two vertex normal tori minus a * vertex link. */ NNormalSurface* NTriangulation::hasNonTrivialSphereOrDisc() { // Get the empty triangulation out of the way now. if (tetrahedra_.empty()) return 0; // Do we already know the answer? if (zeroEfficient_.known() && zeroEfficient_.value()) return 0; // Use combinatorial optimisation if we can. if (isValid() && vertices_.size() == 1) { // For now, just use the safe arbitrary-precision NInteger type. NTreeSingleSoln tree(this, NS_STANDARD); if (tree.find()) { NNormalSurface* s = tree.buildSurface(); if (! ((! s->hasRealBoundary()) && (s->getEulerChar() == 1) && s->isTwoSided())) return s; // Looks like we've found a two-sided projective plane. // Fall through to a full enumeration of vertex surfaces. delete s; } else return 0; } // Fall back to a slow-but-general method: enumerate all vertex surfaces. // For valid, non-ideal triangulations we can do this in quad // coordinates (where a non-trivial sphere or disc is guaranteed to // appear as a vertex surface). Otherwise fall back to standard coords. NNormalSurfaceList* surfaces = NNormalSurfaceList::enumerate(this, (isValid() && ! isIdeal()) ? NS_QUAD : NS_STANDARD); const NNormalSurface* s; NNormalSurface* ans = 0; for (size_t i = 0; i < surfaces->getNumberOfSurfaces() && ! ans; ++i) { s = surfaces->getSurface(i); // These are vertex surfaces, so we know they must be connected. // Because we are either (i) using standard coordinates, or // (ii) working with a non-ideal triangulation; we know the // vertex surfaces are compact also. if (s->isVertexLinking()) continue; // Now they are compact, connected and non-vertex-linking. // We just need to pick out spheres and discs. if (s->getEulerChar() == 2) { // Must be a sphere; no bounded surface has chi=2. ans = s->clone(); } else if (s->getEulerChar() == 1) { if (s->hasRealBoundary()) { // Must be a disc. ans = s->clone(); } else if (! s->isTwoSided()) { // A projective plane that doubles to a sphere. ans = s->doubleSurface(); } } } delete surfaces; return ans; } NNormalSurface* NTriangulation::hasOctagonalAlmostNormalSphere() { // Get the empty triangulation out of the way now. if (tetrahedra_.empty()) return 0; // Use combinatorial optimisation if we can. // This is good for large problems, but for small problems a full // enumeration is usually faster. Still, the big problems are the // ones we need to be more fussy about. if (vertices_.size() == 1) { // For now, just use the safe arbitrary-precision NInteger type. NTreeSingleSoln tree(this, NS_AN_STANDARD); if (tree.find()) { // Since our preconditions ensure the triangulation is // closed, orientable and 0-efficient, there are no // non-vertex-linking normal surfaces with positive Euler // characteristic. Our optimisation asks for (Euler - #octs) > 0, // which then implies that our surface here is almost normal // with exactly 1 octagon and Euler = 2. This is exactly // what we're looking for. NNormalSurface* s = tree.buildSurface(); return s; } else return 0; } // Fall back to a slow-but-general method: enumerate all vertex surfaces. // Given our preconditions, we can do this in quadrilateral-octagon // coordinates; for details see "Quadrilateral-octagon coordinates for // almost normal surfaces", B.B., Experiment. Math. 19 (2010), 285-315. NNormalSurfaceList* surfaces = NNormalSurfaceList::enumerate(this, NS_AN_QUAD_OCT); // Our vertex surfaces are guaranteed to be in smallest possible // integer coordinates, with at most one non-zero octagonal coordinate. const NNormalSurface* s; NNormalSurface* ans = 0; unsigned long tet; unsigned oct; bool found, broken; NLargeInteger coord; for (size_t i = 0; i < surfaces->getNumberOfSurfaces() && ! ans; ++i) { s = surfaces->getSurface(i); // These are vertex surfaces, so we know they must be connected. // Because we are working with a non-ideal triangulation, we know the // vertex surfaces are compact. // Hunt for spheres with exactly one octagon. // Note that 1-sided projective planes are no good here, // since when doubled they give too many octagonal discs. if (s->getEulerChar() == 2) { // Euler char = 2 implies no real boundary. found = false; // At least one octagon found so far? broken = false; // More than one octagon found so far? for (tet = 0; tet < tetrahedra_.size() && ! broken; ++tet) for (oct = 0; oct < 3; ++oct) { coord = s->getOctCoord(tet, oct); if (coord > 1) { broken = true; break; } else if (coord == 1) { if (found) { broken = true; break; } else found = true; } } if (found && ! broken) { // This is it! ans = s->clone(); } } } delete surfaces; return ans; } bool NTriangulation::isZeroEfficient() { if (! zeroEfficient_.known()) { if (hasTwoSphereBoundaryComponents()) zeroEfficient_ = false; else { // Operate on a clone of this triangulation, to avoid // changing the real packet tree. NTriangulation clone(*this); NNormalSurface* s = clone.hasNonTrivialSphereOrDisc(); if (s) { zeroEfficient_ = false; delete s; } else { zeroEfficient_ = true; // Things implied by 0-efficiency: if (isValid() && isClosed() && isConnected()) irreducible_ = true; } } } return zeroEfficient_.value(); } bool NTriangulation::hasSplittingSurface() { // Splitting surfaces must unfortunately be calculated using // tri-quad coordinates. if (splittingSurface_.known()) return splittingSurface_.value(); // Create a normal surface list. // // Work on a clone of this triangulation so we don't trigger any // changes to the packet tree. NTriangulation working(*this); NNormalSurfaceList* surfaces = NNormalSurfaceList::enumerate(&working, NS_STANDARD); // Run through all vertex surfaces. unsigned long nSurfaces = surfaces->getNumberOfSurfaces(); const NNormalSurface* s; NLargeInteger chi; for (unsigned long i = 0; i < nSurfaces; i++) { s = surfaces->getSurface(i); if (! splittingSurface_.known()) if (s->isSplitting()) splittingSurface_ = true; // See if there is no use running through the rest of the list. if (splittingSurface_.known()) break; } // Done! if (! splittingSurface_.known()) splittingSurface_ = false; // The stack will clean things up for us automatically. return splittingSurface_.value(); } } // namespace regina regina-4.96/engine/triangulation/turaevviro.cpp000644 000765 000024 00000031553 12377776775 021712 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include #include "regina-config.h" #include "maths/approx.h" #include "maths/numbertheory.h" #include "triangulation/ntriangulation.h" namespace regina { namespace { /** * Allows calculation of [n]! for arbitrary n. * Values are cached as they are calculated. */ class BracketFactorial { private: double* fact; /**< The cached values [0]!, [1]!, ..., [r-1]! . */ double* inv; /**< The cached inverses of the values stored in fact[]. */ double angle; /**< The angle arg(q0). */ unsigned long r; /**< The integer r, for which 2r * angle is some integer multiple of 2 * Pi. */ public: /** * Precalculate all values [0]!, ..., [r-1]!. * * Requires r >= 3. */ BracketFactorial(double newAngle, unsigned long newR) : fact(new double[newR]), inv(new double[newR]), angle(newAngle), r(newR) { fact[0] = fact[1] = inv[0] = inv[1] = 1.0; for (unsigned long i = 2; i < r; i++) { fact[i] = fact[i - 1] * sin(angle * i) / sin(angle); inv[i] = inv[i - 1] * sin(angle) / sin(angle * i); } } /** * Clean up memory. */ ~BracketFactorial() { delete[] fact; delete[] inv; } /** * Calculates the single value [n] (note that there is no * factorial symbol included). * These values are individually easy to calculate and so * are not cached. */ double bracket(unsigned long index) const { if (index == 0 || index == 1) return 1; return sin(angle * index) / sin(angle); } /** * Returns the value [index]!. */ double operator [] (unsigned long index) const { return (index < r ? fact[index] : 0.0); } /** * Returns the value [index]! ^ -1. * * Requires index < r. */ double inverse(unsigned long index) const { return inv[index]; } }; /** * Represents the initial data as described in Section 7 of Turaev * and Viro's paper. */ struct InitialData { unsigned long r; /**< The integer r. */ double angle; /**< The angle arg(q0). */ BracketFactorial fact; /**< The cached values [n]!. */ double vertexContrib; /**< The vertex-based contribution to the Turaev-Viro invariant; this is the inverse square of the distinguished value w. */ InitialData(unsigned long newR, double newAngle) : r(newR), angle(newAngle), fact(angle, r) { vertexContrib = 2.0 * sin(angle) * sin(angle) / r; } /** * Determines whether (i/2, j/2, k/2) is an admissible triple. */ bool isAdmissible(unsigned long i, unsigned long j, unsigned long k) const { return ((i + j + k) % 2 == 0) && (i <= j + k) && (j <= i + k) && (k <= i + j) && (i + j + k <= 2 * (r - 2)); } /** * Determines the triangle-based contribution to the Turaev-Viro * invariant. This corresponds to +/- Delta(i/2, j/2, k/2)^2. */ std::complex triContrib(unsigned long i, unsigned long j, unsigned long k) const { // By admissibility, (i + j + k) is guaranteed to be even. std::complex ans = fact[(i + j - k) / 2] * fact[(j + k - i) / 2] * fact[(k + i - j) / 2] * fact.inverse((i + j + k + 2) / 2); return ((i + j + k) % 4 == 0 ? ans : -ans); } /** * Determines the edge-based contribution to the Turaev-Viro * invariant. This corresponds to w(i/2)^2. */ std::complex edgeContrib(unsigned long i) const { return (i % 2 == 0 ? fact.bracket(i + 1) : - fact.bracket(i + 1)); } /** * Determines the tetrahedron-based contribution to the Turaev-Viro * invariant. This combines with the square roots of the triangle-based * contributions for the four tetrahedron faces to give the symbol * * | i/2 j/2 k/2 | * | l/2 m/2 n/2 | . */ std::complex tetContrib(unsigned long i, unsigned long j, unsigned long k, unsigned long l, unsigned long m, unsigned long n) { std::complex ans = 0.0; unsigned long minZ = i + j + k; if (minZ < i + m + n) minZ = i + m + n; if (minZ < j + l + n) minZ = j + l + n; if (minZ < k + l + m) minZ = k + l + m; unsigned long maxZ = i + j + l + m; if (maxZ > i + k + l + n) maxZ = i + k + l + n; if (maxZ > j + k + m + n) maxZ = j + k + m + n; double term; for (unsigned long z = minZ; z <= maxZ; z++) { if (z % 2 != 0) continue; // We are guaranteed that z / 2 is an integer. term = fact[(z + 2) / 2] * fact.inverse((z - i - j - k) / 2) * fact.inverse((z - i - m - n) / 2) * fact.inverse((z - j - l - n) / 2) * fact.inverse((z - k - l - m) / 2) * fact.inverse((i + j + l + m - z) / 2) * fact.inverse((i + k + l + n - z) / 2) * fact.inverse((j + k + m + n - z) / 2); if (z % 4 == 0) ans += term; else ans -= term; } return ans; } }; } double NTriangulation::turaevViro(unsigned long r, unsigned long whichRoot) const { // Have we already calculated this invariant? std::pair tvParams(r, whichRoot); TuraevViroSet::const_iterator it = turaevViroCache_.find(tvParams); if (it != turaevViroCache_.end()) return (*it).second; // Do some basic parameter checks. if (r < 3) return 0; if (whichRoot >= 2 * r) return 0; if (gcd(r, whichRoot) > 1) return 0; // Set up our initial data. double angle = (M_PI * whichRoot) / r; InitialData init(r, angle); // Run through all admissible colourings. std::complex ans = 0.0; unsigned long nEdges = getNumberOfEdges(); unsigned long nTriangles = getNumberOfTriangles(); unsigned long* colour = new unsigned long[nEdges]; std::fill(colour, colour + nEdges, 0); long curr = 0; std::complex valColour; bool admissible; std::deque::const_iterator embit; long index1, index2; unsigned long i; while (curr >= 0) { // Have we found an admissible colouring? if (curr >= static_cast(nEdges)) { // Increment ans appropriately. valColour = 1.0; for (i = 0; i < vertices_.size(); i++) valColour *= init.vertexContrib; for (i = 0; i < nEdges; i++) valColour *= init.edgeContrib(colour[i]); for (i = 0; i < nTriangles; i++) valColour *= init.triContrib( colour[edgeIndex(triangles_[i]->getEdge(0))], colour[edgeIndex(triangles_[i]->getEdge(1))], colour[edgeIndex(triangles_[i]->getEdge(2))]); for (i = 0; i < tetrahedra_.size(); i++) valColour *= init.tetContrib( colour[edgeIndex(tetrahedra_[i]->getEdge(0))], colour[edgeIndex(tetrahedra_[i]->getEdge(1))], colour[edgeIndex(tetrahedra_[i]->getEdge(3))], colour[edgeIndex(tetrahedra_[i]->getEdge(5))], colour[edgeIndex(tetrahedra_[i]->getEdge(4))], colour[edgeIndex(tetrahedra_[i]->getEdge(2))] ); ans += valColour; // Step back down one level. curr--; if (curr >= 0) colour[curr]++; continue; } // Have we run out of values to try at this level? if (colour[curr] > r - 2) { colour[curr] = 0; curr--; if (curr >= 0) colour[curr]++; continue; } // Does the current value for colour[curr] preserve admissibility? admissible = true; const std::deque& embs(edges_[curr]->getEmbeddings()); for (embit = embs.begin(); embit != embs.end(); embit++) { index1 = edgeIndex((*embit).getTetrahedron()->getEdge( NEdge::edgeNumber[(*embit).getVertices()[0]] [(*embit).getVertices()[2]])); index2 = edgeIndex((*embit).getTetrahedron()->getEdge( NEdge::edgeNumber[(*embit).getVertices()[1]] [(*embit).getVertices()[2]])); if (index1 <= curr && index2 <= curr) { // We've decided upon colours for all three edges of // this triangle containing the current edge. if (! init.isAdmissible(colour[index1], colour[index2], colour[curr])) { admissible = false; break; } } } // Use the current value for colour[curr] if appropriate; // otherwise step forwards to the next value. if (admissible) curr++; else colour[curr]++; } delete[] colour; if (isNonZero(ans.imag())) { // This should never happen, since the Turaev-Viro invariant is the // square of the modulus of the Witten invariant for sl_2. std::cerr << "WARNING: The Turaev-Viro invariant has an imaginary component.\n" " This should never happen.\n" " Please report this (along with the 3-manifold that" " was used) to " << PACKAGE_BUGREPORT << "." << std::endl; } turaevViroCache_[tvParams] = ans.real(); return ans.real(); } } // namespace regina regina-4.96/engine/utilities/base64.cpp000644 000765 000024 00000036143 12377776775 017723 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "utilities/base64.h" namespace regina { /** * These routines are taken and modified from the Base64 project at * base64.sourceforge.net. The front matter from the original b64.c is * included below. */ /*********************************************************************\ MODULE NAME: b64.c AUTHOR: Bob Trower 08/04/01 PROJECT: Crypt Data Packaging COPYRIGHT: Copyright (c) Trantor Standard Systems Inc., 2001 NOTES: This source code may be used as you wish, subject to the MIT license. See the LICENCE section below. Canonical source should be at: http://base64.sourceforge.net DESCRIPTION: This little utility implements the Base64 Content-Transfer-Encoding standard described in RFC1113 (http://www.faqs.org/rfcs/rfc1113.html). This is the coding scheme used by MIME to allow binary data to be transferred by SMTP mail. Groups of 3 bytes from a binary stream are coded as groups of 4 bytes in a text stream. The input stream is 'padded' with zeros to create an input that is an even multiple of 3. A special character ('=') is used to denote padding so that the stream can be decoded back to its exact size. Encoded output is formatted in lines which should be a maximum of 72 characters to conform to the specification. This program defaults to 72 characters, but will allow more or less through the use of a switch. The program enforces a minimum line size of 4 characters. Example encoding: The stream 'ABCD' is 32 bits long. It is mapped as follows: ABCD A (65) B (66) C (67) D (68) (None) (None) 01000001 01000010 01000011 01000100 16 (Q) 20 (U) 9 (J) 3 (D) 17 (R) 0 (A) NA (=) NA (=) 010000 010100 001001 000011 010001 000000 000000 000000 QUJDRA== Decoding is the process in reverse. A 'decode' lookup table has been created to avoid string scans. DESIGN GOALS: Specifically: Code is a stand-alone utility to perform base64 encoding/decoding. It should be genuinely useful when the need arises and it meets a need that is likely to occur for some users. Code acts as sample code to show the author's design and coding style. Generally: This program is designed to survive: Everything you need is in a single source file. It compiles cleanly using a vanilla ANSI C compiler. It does its job correctly with a minimum of fuss. The code is not overly clever, not overly simplistic and not overly verbose. Access is 'cut and paste' from a web page. Terms of use are reasonable. VALIDATION: Non-trivial code is never without errors. This file likely has some problems, since it has only been tested by the author. It is expected with most source code that there is a period of 'burn-in' when problems are identified and corrected. That being said, it is possible to have 'reasonably correct' code by following a regime of unit test that covers the most likely cases and regression testing prior to release. This has been done with this code and it has a good probability of performing as expected. Unit Test Cases: case 0:empty file: CASE0.DAT -> -> (Zero length target file created on both encode and decode.) case 1:One input character: CASE1.DAT A -> QQ== -> A case 2:Two input characters: CASE2.DAT AB -> QUI= -> AB case 3:Three input characters: CASE3.DAT ABC -> QUJD -> ABC case 4:Four input characters: case4.dat ABCD -> QUJDRA== -> ABCD case 5:All chars from 0 to ff, linesize set to 50: AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIj JCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZH SElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWpr bG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6P kJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKz tLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX 2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7 /P3+/w== case 6:Mime Block from e-mail: (Data same as test case 5) case 7: Large files: Tested 28 MB file in/out. case 8: Random Binary Integrity: This binary program (b64.exe) was encoded to base64, back to binary and then executed. case 9 Stress: All files in a working directory encoded/decoded and compared with file comparison utility to ensure that multiple runs do not cause problems such as exhausting file handles, tmp storage, etc. ------------- Syntax, operation and failure: All options/switches tested. Performs as expected. case 10: No Args -- Shows Usage Screen Return Code 1 (Invalid Syntax) case 11: One Arg (invalid) -- Shows Usage Screen Return Code 1 (Invalid Syntax) case 12: One Arg Help (-?) -- Shows detailed Usage Screen. Return Code 0 (Success -- help request is valid). case 13: One Arg Help (-h) -- Shows detailed Usage Screen. Return Code 0 (Success -- help request is valid). case 14: One Arg (valid) -- Uses stdin/stdout (filter) Return Code 0 (Sucess) case 15: Two Args (invalid file) -- shows system error. Return Code 2 (File Error) case 16: Encode non-existent file -- shows system error. Return Code 2 (File Error) case 17: Out of disk space -- shows system error. Return Code 3 (File I/O Error) case 18: Too many args -- shows system error. Return Code 1 (Invalid Syntax) ------------- Compile/Regression test: gcc compiled binary under Cygwin Microsoft Visual Studio under Windows 2000 Microsoft Version 6.0 C under Windows 2000 DEPENDENCIES: None LICENCE: Copyright (c) 2001 Bob Trower, Trantor Standard Systems Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. VERSION HISTORY: Bob Trower 08/04/01 -- Create Version 0.00.00B Bob Trower 08/17/01 -- Correct documentation, messages. -- Correct help for linesize syntax. -- Force error on too many arguments. Bob Trower 08/19/01 -- Add sourceforge.net reference to help screen prior to release. Bob Trower 10/22/04 -- Cosmetics for package/release. Bob Trower 02/28/08 -- More Cosmetics for package/release. Bob Trower 02/14/11 -- Cast altered to fix warning in VS6. \******************************************************************* */ /* ** Translation Table as described in RFC1113 */ static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /* ** Translation Table to decode (created by author) */ static const char cd64[]="|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq"; void base64Encode(const char* in, size_t inlen, char* out, size_t outlen) { unsigned char inc[3]; unsigned char outc[4]; int i, len; *inc = (unsigned char) 0; *outc = (unsigned char) 0; while( inlen ) { for( len = 0; len < 3 && inlen; len++ ) { inc[len] = *in++; --inlen; } for (i = len; i < 3; ++i) inc[i] = 0; // encode 3 8-bit binary bytes as 4 '6-bit' characters outc[0] = (unsigned char) cb64[ (int)(inc[0] >> 2) ]; outc[1] = (unsigned char) cb64[ (int)(((inc[0] & 0x03) << 4) | ((inc[1] & 0xf0) >> 4)) ]; outc[2] = (unsigned char) (len > 1 ? cb64[(int)(((inc[1] & 0x0f) << 2) | ((inc[2] & 0xc0) >> 6)) ] : '='); outc[3] = (unsigned char) (len > 2 ? cb64[(int)(inc[2] & 0x3f)] : '='); for( i = 0; i < 4 && outlen; i++ ) { *out++ = outc[i]; --outlen; } } // Add a terminating null. if (outlen) *out++ = 0; } size_t base64Encode(const char* in, size_t inlen, char** out) { size_t outlen = 1 + base64Length(inlen); // Check for overflow. if (inlen > outlen) { *out = 0; return 0; } *out = new char[outlen]; base64Encode(in, inlen, *out, outlen); return outlen - 1; } bool base64Decode (const char* in, size_t inlen, char* out, size_t *outlen) { unsigned char inc[4]; unsigned char outc[3]; int v; int i, len; size_t outsize = *outlen; *outlen = 0; // The input may end with padding of '=' or '=='. if (inlen && in[inlen - 1] == '=') --inlen; if (inlen && in[inlen - 1] == '=') --inlen; bool unbroken = true; while( inlen && unbroken ) { for( len = 0; len < 4 && inlen; ++len ) { v = *in++; --inlen; v = ((v < 43 || v > 122) ? 0 : (int) cd64[ v - 43 ]); if( v != 0 ) v = ((v == (int)'$') ? 0 : v - 61); if (v == 0) { // Invalid character. unbroken = false; break; } inc[ len ] = (unsigned char) (v - 1); } // decode 4 '6-bit' characters into 3 8-bit binary bytes outc[ 0 ] = (unsigned char ) (inc[0] << 2 | inc[1] >> 4); outc[ 1 ] = (unsigned char ) (inc[1] << 4 | inc[2] >> 2); outc[ 2 ] = (unsigned char ) (((inc[2] << 6) & 0xc0) | inc[3]); for( i = 0; i < len - 1; i++ ) { if (outsize) { out[(*outlen)++] = outc[i]; --outsize; } else return false; // output buffer exhausted. } } return unbroken; } bool base64Decode(const char* in, size_t inlen, char** out, size_t* outlen) { // This may allocate one or two bytes too much, but never too little. // Dividing before multiplying avoids the possibility of overflow. size_t needlen = 3 * (inlen / 4) + 2; *out = new char[needlen]; if (!base64Decode(in, inlen, *out, &needlen)) { delete[] *out; *out = 0; return false; } if (outlen) *outlen = needlen; return true; } } // namespace regina regina-4.96/engine/utilities/base64.h000644 000765 000024 00000025723 12377775645 017365 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file utilities/base64.h * \brief Routines for base64 encoding and decoding taken and modified * from the \a Base64 project at base64.sourceforge.net. * * The \a Base64 copyright notice is as follows: * * Copyright (c) 2001 Bob Trower, Trantor Standard Systems Inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated * documentation files (the "Software"), to deal in the * Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, * sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall * be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __BASE64_H #ifndef __DOXYGEN #define __BASE64_H #endif #include "regina-core.h" #include // for size_t namespace regina { /** * \weakgroup utilities * @{ */ /** * Returns the number of base64 characters required to encode the given * number of bytes. This is the number of characters used (excluding the * null terminator) by the routine base64Encode(const char*, size_t, char**). * * \ifacespython Not present. * * @param bytes the number of raw input bytes. * @return the corresponding number of base64 printable output characters. */ inline REGINA_API size_t base64Length(size_t bytes) { return (((bytes + 2) / 3) * 4); } /** * Determines whether the given character is a base64 printable character as * used by the base64 routines in Regina. The base64 printable characters * are the letters (both upper-case and lower-case), digits, plus (+), and * forward slash (/). * * Note that the equals sign (=) is padding, and is not considered by * this routine to be a base64 printable character. * * \ifacespython Not present. * * @param ch any character. * @return \c true if the given character is one of the base64 printable * characters used in Regina, or \c false if it is not. */ inline REGINA_API bool isBase64(char ch) { return ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '+' || ch == '/'); } /** * Encodes the given sequence of raw bytes in base64, and writes the * results into a preallocated output buffer. * * The length of the output buffer is passed as the argument \a outlen. * If the number of base64 characters required is less than \a outlen, * a terminating \c null will be written to the end of the output sequence. * If the number of base64 characters is \a outlen or greater, this * routine will output as many base64 characters as possible, up to a * maximum of \a outlen. * * The routine base64Length() can be used to precalculate precisely how * many output characters will be required. * * \ifacespython Not present. * * @param in the sequence of input bytes; this does not need to be * terminated in any special way. * @param inlen the length of the input sequence. * @param out the output buffer into which the resulting base64 * characters will be written. * @param outlen the length of the output buffer. * * @author This routine is based on the \a Base64 project at * base64.sourceforge.net. The original was written by Bob Trower, and is * licensed under the MIT license. See the base64.h notes for details. */ REGINA_API void base64Encode(const char* in, size_t inlen, char* out, size_t outlen); /** * Encodes the given sequence of raw bytes in base64, and passes back a * newly allocated array containing the results. The \a out pointer will * be set to this new array, which will be null-terminated. This array will * be allocated using \c new[], and the caller is responsible for destroying * it using \c delete[]. * * If the output array is too large (in particular, the expected size * will overflow a \c size_t), the \a out pointer will be set to \c null. * * \ifacespython Not present. * * @param in the sequence of input bytes; this does not need to be * terminated in any special way. * @param inlen the length of the input sequence. * @param out the address of a pointer which will be set to the output * array of base64 characters. * @return the length of the output array, not counting the terminating null. * * @author This routine is based on the \a Base64 project at * base64.sourceforge.net. The original was written by Bob Trower, and is * licensed under the MIT license. See the base64.h notes for details. */ REGINA_API size_t base64Encode(const char* in, size_t inlen, char** out); /** * Decodes the given sequence of base64 characters, and writes the * resulting raw bytes into a preallocated output buffer. * * The given base64 sequence should not contain any unexpected characters; * even whitespace will cause the decoding procedure to abort. * * The length of the output buffer is passed as the argument \a outlen. * If an unexpected or invalid character is found, or the output * buffer is exhausted, this routine will write as many output bytes as * it can and then return \c false. Otherwise (on success) it will return * \c true. Either way, it will reset \a outlen to the total number of * bytes that were written. * * The total number of output bytes is important to know, since the output * array is not terminated in any special way. * * \ifacespython Not present. * * @param in the input sequence of base64 characters; this does not need * to be terminated in any special way. * @param inlen the length of the input sequence. * @param out the output buffer into which the resulting raw bytes * will be written. * @param outlen must contain the length of the output buffer on entry, and * on exit contains the number of output bytes that were successfully written. * @return \c true if decoding was successful, or \c false if the output * buffer was exhausted or an unexpected input character was found. * * @author This routine is based on the \a Base64 project at * base64.sourceforge.net. The original was written by Bob Trower, and is * licensed under the MIT license. See the base64.h notes for details. */ REGINA_API bool base64Decode(const char* in, size_t inlen, char* out, size_t* outlen); /** * Decodes the given sequence of base64 characters, and passes back a * newly allocated array containing the results. The \a out pointer * will be set to this new array, and \a outlen will be set to the * number of raw bytes in this output array. This array will be * allocated using \c new[], and the caller is responsible for * destroying it using \c delete[]. * * The given base64 sequence should not contain any unexpected characters; * even whitespace will cause the decoding procedure to abort. * * The length of the output buffer is passed as the argument \a outlen. * If an unexpected or invalid character is found or the output * buffer is exhausted, this routine will return \c false, set \a out * to \c null, and leave \a outlen undefined. Otherwise (on success) it * will return \c true and set \a outlen to the total number of output bytes. * * If the user is not interested in the length of the output array, a * null pointer may be passed in the \a outlen argument. Note however * that the output array is not terminated in any special way. * * \ifacespython Not present. * * @param in the input sequence of base64 characters; this does not need * to be terminated in any special way. * @param inlen the length of the input sequence. * @param out the address of a pointer which will be set to the output * array of raw bytes (or which will be set to \c null on failure). * @param outlen the address of an integer which will be set to the * length of the output array (or which will be left undefined on failure). * @return \c true if decoding was successful, or \c false if an unexpected * input character was found or some other error occurred. * * @author This routine is based on the \a Base64 project at * base64.sourceforge.net. The original was written by Bob Trower, and is * licensed under the MIT license. See the base64.h notes for details. */ REGINA_API bool base64Decode(const char* in, size_t inlen, char** out, size_t* outlen); /*@}*/ } // namespace regina #endif regina-4.96/engine/utilities/bitmanip.h000644 000765 000024 00000024371 12377775647 020104 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file utilities/bitmanip.h * \brief Optimised classes for bitwise analysis and manipulation of * native data types. */ #ifndef __BITMANIP_H #ifndef __DOXYGEN #define __BITMANIP_H #endif #include "regina-core.h" #include "regina-config.h" namespace regina { /** * \weakgroup utilities * @{ */ /** * A generic class for bitwise analysis and manipulation of native data types. * * This class is not optimised for common data types; its * sole functionality is to provide default implementations for some * operations that are not yet optimised (or do not need to be). * * End users should use BitManipulator instead, which is better * optimised and which has all the functionality of this class. * * See BitManipulator for further information. * * \pre Type \a T is an unsigned integral numeric type. * \pre The argument \a size is a power of two, and is at most sizeof(\a T). * * \ifacespython Not present. */ template class GenericBitManipulator { public: /** * Returns the index of the first \c true bit in the given * integer, or -1 if the given integer is zero. * Bits are indexed from 0 upwards, starting at the least * significant bit. * * @param x the integer of type \a T to examine. * @return the position of the first \c true bit, or -1 if there * are no \c true bits. */ inline static int firstBit(T x) { if (! x) return -1; // This binary search will break if size is not a power of two. unsigned chunkSize = size << 3; // 8 * size unsigned chunkStart = 0; while (chunkSize > 1) { chunkSize >>= 1; if (! (x & (((T(1) << chunkSize) - T(1)) << chunkStart))) chunkStart += chunkSize; } return chunkStart; } /** * Returns the index of the last \c true bit in the given * integer, or -1 if the given integer is zero. * Bits are indexed from 0 upwards, starting at the least * significant bit. * * @param x the integer of type \a T to examine. * @return the position of the last \c true bit, or -1 if there * are no \c true bits. */ inline static int lastBit(T x) { if (! x) return -1; // This binary search will break if size is not a power of two. unsigned chunkSize = size << 3; // 8 * size unsigned chunkStart = 0; while (chunkSize > 1) { chunkSize >>= 1; if (x & (((T(1) << chunkSize) - T(1)) << (chunkStart + chunkSize))) chunkStart += chunkSize; } return chunkStart; } }; /** * An optimised class for bitwise analysis and manipulation of native * data types. * * The class BitManipulator is used to manipulate the lowest * \a size bytes of type \a T, which must be an unsigned native integer * type such as unsigned char, unsigned int, or unsigned long long. * * The generic implementation of BitManipulator is here for completeness. * All or most native types \a T have template specialisations * that are carefully optimised (precisely what gets specialised depends * upon properties of the compiler). * * Like this class, all specialisations either inherit or override the * default implementations from the base class GenericBitManipulator. * * \pre Type \a T is an unsigned integral numeric type. * \pre The argument \a size is a power of two, and is at most sizeof(\a T). * * \ifacespython Not present. */ template class BitManipulator : public GenericBitManipulator { public: enum { /** * Indicates whether this class is a template specialisation * of BitManipulator with extra optimisations. * * This compile-time constant is set to 0 for the generic * implementation of BitManipulator, and 1 for all specialisations. */ specialised = 0 }; /** * Returns the number of bits that are set in the given integer. * * Specifically, this routine returns the number of bits set to 1 * from amongst the lowest \a size bytes of \a x. * * @param x the integer of type \a T to examine. * @return the number of bits that are set. */ inline static int bits(T x) { return BitManipulator> 1)>::bits(x) + BitManipulator> 1)>::bits(x >> (4 * size)); } }; // Specialisations for individual type sizes. // Hide these from doxygen. #ifndef __DOXYGEN template class BitManipulator : public GenericBitManipulator { public: enum { specialised = 1 }; inline static int bits(T x) { x = (x & T(0x55)) + ((x & T(0xAA)) >> 1); x = (x & T(0x33)) + ((x & T(0xCC)) >> 2); return (x & T(0x0F)) + ((x & T(0xF0)) >> 4); } }; template class BitManipulator : public GenericBitManipulator { public: enum { specialised = 1 }; inline static int bits(T x) { x = (x & T(0x5555)) + ((x & T(0xAAAA)) >> 1); x = (x & T(0x3333)) + ((x & T(0xCCCC)) >> 2); x = (x & T(0x0F0F)) + ((x & T(0xF0F0)) >> 4); return (x & T(0x00FF)) + ((x & T(0xFF00)) >> 8); } }; template class BitManipulator : public GenericBitManipulator { public: enum { specialised = 1 }; inline static int bits(T x) { x = (x & T(0x55555555)) + ((x & T(0xAAAAAAAA)) >> 1); x = (x & T(0x33333333)) + ((x & T(0xCCCCCCCC)) >> 2); x = (x & T(0x0F0F0F0F)) + ((x & T(0xF0F0F0F0)) >> 4); x = (x & T(0x00FF00FF)) + ((x & T(0xFF00FF00)) >> 8); return (x & T(0x0000FFFF)) + ((x & T(0xFFFF0000)) >> 16); } }; // Support 64-bit processing natively if we can; otherwise we will fall // back to the generic two-lots-of-32-bit implementation. #if defined(NUMERIC_64_FOUND) template class BitManipulator : public GenericBitManipulator { public: enum { specialised = 1 }; inline static int bits(T x) { x = (x & T(0x5555555555555555)) + ((x & T(0xAAAAAAAAAAAAAAAA)) >> 1); x = (x & T(0x3333333333333333)) + ((x & T(0xCCCCCCCCCCCCCCCC)) >> 2); x = (x & T(0x0F0F0F0F0F0F0F0F)) + ((x & T(0xF0F0F0F0F0F0F0F0)) >> 4); x = (x & T(0x00FF00FF00FF00FF)) + ((x & T(0xFF00FF00FF00FF00)) >> 8); x = (x & T(0x0000FFFF0000FFFF)) + ((x & T(0xFFFF0000FFFF0000)) >> 16); return (x & T(0x00000000FFFFFFFF)) + ((x & T(0xFFFFFFFF00000000)) >> 32); } }; #elif defined(NUMERIC_64_LL_FOUND) template class BitManipulator : public GenericBitManipulator { public: enum { specialised = 1 }; inline static int bits(T x) { x = (x & T(0x5555555555555555LL)) + ((x & T(0xAAAAAAAAAAAAAAAALL)) >> 1); x = (x & T(0x3333333333333333LL)) + ((x & T(0xCCCCCCCCCCCCCCCCLL)) >> 2); x = (x & T(0x0F0F0F0F0F0F0F0FLL)) + ((x & T(0xF0F0F0F0F0F0F0F0LL)) >> 4); x = (x & T(0x00FF00FF00FF00FFLL)) + ((x & T(0xFF00FF00FF00FF00LL)) >> 8); x = (x & T(0x0000FFFF0000FFFFLL)) + ((x & T(0xFFFF0000FFFF0000LL)) >> 16); return (x & T(0x00000000FFFFFFFFLL)) + ((x & T(0xFFFFFFFF00000000LL)) >> 32); } }; #endif // End the hide-from-doxygen block. #endif /*@}*/ } // namespace regina #endif regina-4.96/engine/utilities/boostutils.h000644 000765 000024 00000023170 12377775650 020476 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file utilities/boostutils.h * \brief Miscellaneous utility classes taken or modified from the * Boost C++ libraries. * * The Boost copyright notices are as follows. * * Type Traits: * * (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. * * Permission to copy, use, modify, sell and distribute this software * is granted provided this copyright notice appears in all copies. * This software is provided "as is" without express or implied * warranty, and with no claim as to its suitability for any purpose. * * Reference Wrappers: * * Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
* Copyright (C) 2001, 2002 Peter Dimov
* Copyright (C) 2002 David Abrahams * * Permission to copy, use, modify, sell and distribute this software * is granted provided this copyright notice appears in all copies. * This software is provided "as is" without express or implied * warranty, and with no claim as to its suitability for any purpose. * * Next, Prior and Non-Copyable: * * Contributed by Dave Abrahams * * (C) Copyright Boost.org 1999-2003. * Permission to copy, use, modify, sell and distribute this software * is granted provided this copyright notice appears in all copies. * This software is provided "as is" without express or implied * warranty, and with no claim as to its suitability for any purpose. */ #ifndef __BOOSTUTILS_H #ifndef __DOXYGEN #define __BOOSTUTILS_H #endif #include "regina-core.h" namespace regina { /** * Miscellaneous utility classes taken or modified from the Boost C++ * libraries. * * See the boostutils.h file documentation for Boost license details. */ namespace boost { /** * \weakgroup utilities * @{ */ /** * A template class used to remove the indirection from a pointer type. * * If T is a pointer type, then * \code remove_pointer::type \endcode * removes the top-level indirection from T; otherwise * T remains unchanged. For example int* becomes * int, but int& remains unchanged. * * \ifacespython Not present. * * @author This class was taken and modified from the Boost C++ libraries * (http://www.boost.org/). */ template struct remove_pointer { typedef T type; /**< The template argument with the top-level indirection * removed if it is a pointer type. */ }; #ifndef __DOXYGEN /** * Specialisations of remove_pointer: */ template struct remove_pointer { typedef T type; }; template struct remove_pointer { typedef T type; }; template struct remove_pointer { typedef T type; }; template struct remove_pointer { typedef T type; }; #endif /** * A wrapper allowing references to be passed through generic functions. * This class is for use with the Standard Template Library. * * The primary advantage of this class is its implicit conversion to * type T&. Thus it can be passed to routines expecting * references to T but can also be passed by reference itself. * * See global routines regina::boost::ref() and regina::boost::cref() * for simple creation of these wrappers. * * \ifacespython Not present. * * @author This class was taken and modified from the Boost C++ libraries * (http://www.boost.org/). */ template class reference_wrapper { public: typedef T type; /**< The data type being referenced by this wrapper. */ private: T* t_; /**< A pointer to the object being referenced. */ public: /** * Creates a new wrapper to reference the given object. * * @param t the object to be referenced. */ explicit reference_wrapper(type& t) : t_(&t) { } /** * Returns a reference to the object being referenced. * This routine provides an implicit conversion to type * T&. * * @return the corresonding reference. */ operator type& () const { return *t_; } /** * Returns a reference to the object being referenced. * * @return the corresonding reference. */ type& get() const { return *t_; } /** * Returns a pointer to the object being referenced. * * @return the corresponding pointer. */ type* get_pointer() const { return t_; } }; /** * Returns a wrapper for the given reference. See reference_wrapper for * further details. * * \ifacespython Not present. * * @param t the reference to wrap. * @return the corresponding wrapper. * * @author This routine was taken and modified from the Boost C++ libraries * (http://www.boost.org/). */ template inline reference_wrapper const ref(T& t) { return reference_wrapper(t); } /** * Returns a wrapper for the given const reference. See reference_wrapper for * further details. * * \ifacespython Not present. * * @param t the reference to wrap. * @return the corresponding wrapper. * * @author This routine was taken and modified from the Boost C++ libraries * (http://www.boost.org/). */ template inline reference_wrapper const cref(T const& t) { return reference_wrapper(t); } /** * Returns the iterator prior to the given iterator. * This function avoids having to explicitly create a temporary to * decrement. * * Only the decrement operator --it needs to be defined. * * \ifacespython Not present. * * @param it the iterator to examine. * @return the iterator prior to the given iterator. * * @author This routine was taken and modified from the Boost C++ libraries * (http://www.boost.org/). */ template inline T prior(T it) { return --it; } /** * Returns the iterator following the given iterator. * This function avoids having to explicitly create a temporary to * increment. * * Only the increment operator ++it needs to be defined. * * \ifacespython Not present. * * @param it the iterator to examine. * @return the iterator following the given iterator. * * @author This routine was taken and modified from the Boost C++ libraries * (http://www.boost.org/). */ template inline T next(T it) { return ++it; } /** * A base class that guarantees that derived classes cannot be copied. * This is done by defining a private copy constructor and a private * copy assignment operator. * * \ifacespython Not present. * * @author This class was taken and modified from the Boost C++ libraries * (http://www.boost.org/). */ class REGINA_API noncopyable { protected: /** * A constructor which does nothing. */ noncopyable() {} /** * A destructor which does nothing. */ ~noncopyable() {} private: /** * An inaccessable copy constructor. */ noncopyable(const noncopyable&) {} /** * An inaccessible copy assignment operator. */ const noncopyable& operator = (const noncopyable&) { return *this; } }; /*@}*/ } } // namespace regina::boost #endif regina-4.96/engine/utilities/CMakeLists.txt000644 000765 000024 00000001736 12377774107 020656 0ustar00babstaff000000 000000 # utilities # Files to compile SET ( FILES base64 i18nutils nbooleans nthread nxmlcallback osutils stringutils xmlutils zstream ) # Prepend folder name FOREACH ( SOURCE_FILE ${FILES} ) SET ( SOURCES ${SOURCES} utilities/${SOURCE_FILE}) ENDFOREACH(SOURCE_FILE) # Set the variable in the parent directory SET( SOURCES ${SOURCES} PARENT_SCOPE) if (${REGINA_INSTALL_DEV}) INSTALL(FILES base64.h bitmanip.h boostutils.h flags.h i18nutils.h intutils.h memutils.h nbitmask.h nbooleans.h nlistoncall.h nmarkedvector.h nmatrix2.h nmpi.h nproperty.h nqitmask.h nrational.h nthread.h ntrieset.h ntritmask.h nxmlcallback.h nxmlelementreader.h osutils.h ptrutils.h registryutils.h stlutils.h stringutils.h stringutils-impl.h stringutils.tcc xmlutils.h zstream.h DESTINATION ${INCLUDEDIR}/utilities COMPONENT Development) endif (${REGINA_INSTALL_DEV}) regina-4.96/engine/utilities/flags.h000644 000765 000024 00000040162 12377775652 017365 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file utilities/flags.h * \brief A template class for handling bitwise combinations of enum flags. */ #ifndef __FLAGS_H #ifndef __DOXYGEN #define __FLAGS_H #endif namespace regina { /** * \weakgroup utilities * @{ */ /** * A class representing a bitwise combination of flags defined by an * enumeration type. * * The enumeration type is given in the template parameter \a T. * This class allows the user to form and test bitwise combinations of the * individual enum values, without losing type safety. * * \ifacespython Present only for some particular enumeration types \a T, * when explicitly noted in the corresponding enum documentation. */ template class Flags { public: /** * The underlying enumeration type. */ typedef T Enum; private: /** * The combination of flags that we are storing. */ int value_; public: /** * Creates an empty flag set, with no flags set at all. */ inline Flags() : value_(0) { } /** * Creates a flag set initialised to the given value. * * @param init the initial value of this flag set. */ inline Flags(T init) : value_(init) { } /** * Creates a clone of the given flag set. * * @param init the flag set to clone. */ inline Flags(const Flags& init) : value_(init.value_) { } /** * Returns the integer representation of this set. * This is suitable for file input and/or output. * * \warning This function should not be used widely, since it * effectively works around inbuilt type safety mechanisms. * * @return the integer value of this set. */ int intValue() const { return static_cast(value_); } /** * Returns the set corresponding to the given integer value. * This is suitable for file input and/or output. * * \warning This function should not be used widely, since it * effectively works around inbuilt type safety mechanisms. * * @return the set corresponding to the given integer value. */ inline static Flags fromInt(int value) { return Flags(value); } /** * Returns whether the given flag is set. * * This requires \e all of the bits of the given flag to be set. * The test is equivalent to (*this & flag) == flag. * * @param flag the flag whose presence will be tested. * @return \c true if and only if all of the bits of the given * flag are set. */ bool has(T flag) const { return (value_ & flag) == flag; } /** * Returns whether all of the flags in the given set are set. * * This requires \e all of the bits of all of the flags in the * given set to be present in this set. * The test is equivalent to (*this & rhs) == rhs. * * @param rhs the set whose presence will be tested. * @return \c true if and only if all of the bits of the given * set are present in this set. */ bool has(const Flags& rhs) const { return (value_ & rhs.value_) == rhs.value_; } /** * Determines whether this set is precisely equal to the given flag. * * @param rhs the flag to test this against. * @return \c true if and only if this and the given flag are identical. */ inline bool operator == (T rhs) const { return (value_ == rhs); } /** * Determines whether this set is precisely equal to the given * flag set. * * @param rhs the flag set to test this against. * @return \c true if and only if this and the given flag set are * identical. */ inline bool operator == (const Flags& rhs) const { return (value_ == rhs.value_); } /** * Determines whether this set is not equal to the given flag. * * @param rhs the flag to test this against. * @return \c true if and only if this and the given flag are not * identical. */ inline bool operator != (T rhs) const { return (value_ != rhs); } /** * Determines whether this set is not equal to the given flag set. * * @param rhs the flag to test this against. * @return \c true if and only if this and the given flag set are not * identical. */ inline bool operator != (const Flags& rhs) const { return (value_ != rhs.value_); } /** * Sets this flag set to contain precisely the given flag only. * * @param rhs the new value of this flag set. * @return a reference to this flag set. */ inline Flags& operator = (T rhs) { value_ = rhs; return *this; } /** * Sets this flag set to contain a copy of the given flag set. * * @param rhs the new value of this flag set. * @return a reference to this flag set. */ inline Flags& operator = (const Flags& rhs) { value_ = rhs.value_; return *this; } /** * Changes this flag set by taking a bitwise OR with the given * flag. * * @param rhs the flag to combine with this set. * @return a reference to this flag set. */ inline Flags& operator |= (T rhs) { value_ |= rhs; return *this; } /** * Changes this flag set by taking a bitwise OR with the given * flag set. * * @param rhs the flag set to combine with this set. * @return a reference to this flag set. */ inline Flags& operator |= (const Flags& rhs) { value_ |= rhs.value_; return *this; } /** * Changes this flag set by taking a bitwise AND with the given * flag. * * @param rhs the flag to combine with this set. * @return a reference to this flag set. */ inline Flags& operator &= (T rhs) { value_ &= rhs; return *this; } /** * Changes this flag set by taking a bitwise AND with the given * flag set. * * @param rhs the flag set to combine with this set. * @return a reference to this flag set. */ inline Flags& operator &= (const Flags& rhs) { value_ &= rhs.value_; return *this; } /** * Changes this flag set by taking a bitwise XOR with the given * flag. * * @param rhs the flag to combine with this set. * @return a reference to this flag set. */ inline Flags& operator ^= (T rhs) { value_ ^= rhs; return *this; } /** * Changes this flag set by taking a bitwise XOR with the given * flag set. * * @param rhs the flag set to combine with this set. * @return a reference to this flag set. */ inline Flags& operator ^= (const Flags& rhs) { value_ ^= rhs.value_; return *this; } /** * Returns the bitwise OR of this set and the given flag. * This flag set is not changed. * * @param rhs the flag to combine with this set. * @return the combination of this set and the given flag. */ inline Flags operator | (T rhs) const { return Flags(value_ | rhs); } /** * Returns the bitwise OR of this and the given flag set. * This flag set is not changed. * * @param rhs the flag set to combine with this set. * @return the combination of this and the given flag set. */ inline Flags operator | (const Flags& rhs) const { return Flags(value_ | rhs.value_); } /** * Returns the bitwise AND of this set and the given flag. * This flag set is not changed. * * @param rhs the flag to combine with this set. * @return the combination of this set and the given flag. */ inline Flags operator & (T rhs) const { return Flags(value_ & rhs); } /** * Returns the bitwise AND of this and the given flag set. * This flag set is not changed. * * @param rhs the flag set to combine with this set. * @return the combination of this and the given flag set. */ inline Flags operator & (const Flags& rhs) const { return Flags(value_ & rhs.value_); } /** * Returns the bitwise XOR of this set and the given flag. * This flag set is not changed. * * @param rhs the flag to combine with this set. * @return the combination of this set and the given flag. */ inline Flags operator ^ (T rhs) const { return Flags(value_ ^ rhs); } /** * Returns the bitwise XOR of this and the given flag set. * This flag set is not changed. * * @param rhs the flag set to combine with this set. * @return the combination of this and the given flag set. */ inline Flags operator ^ (const Flags& rhs) const { return Flags(value_ ^ rhs.value_); } /** * Clears all bits from this set that appear in the given flag. * * @param rhs the flag to clear from this set. */ inline void clear(T rhs) { value_ |= rhs; value_ ^= rhs; } /** * Clears all bits from this set that appear in the given set. * * @param rhs identifies the bits to clear from this set. */ inline void clear(const Flags& rhs) { value_ |= rhs.value_; value_ ^= rhs.value_; } /** * Adjust this set so that exactly one and only one of the two * given flags are included. * * If neither flag is present or both flags are present, this * set will be adjusted so that \a default_ is present and \a other * is not. * * \pre Both \a default_ and \a other are each single-bit flags. * * \ifacespython Not present, even for flag types that are * exposed to Python. * * @param default_ the flag that will be set if any adjustments * need to be made. * @param other the flag that will be cleared if any adjustments * need to be made. */ inline void ensureOne(T default_, T other) { if (! ((value_ & default_) || (value_ & other))) value_ |= default_; else if ((value_ & default_) && (value_ & other)) value_ ^= other; } /** * Adjust this set so that exactly one and only one of the three * given flags are included. * * If neither flag is present, then \a default_ will be used. * If multiple flags are present, then the flag that appears * \e earlier in the argument list for this routine will be used. * * \pre Each of the given flags is single-bit. * * \ifacespython Not present, even for flag types that are * exposed to Python. * * @param default_ the highest-priority flag. * @param second the second-highest-priority flag. * @param last the lowest-priority flag. */ inline void ensureOne(T default_, T second, T last) { // Cast to int, because (T | T) is overloaded to return Flags. if (! (value_ & (static_cast(default_) | second | last))) value_ = default_; else if (value_ & default_) clear(second | last); else if (value_ & second) clear(last); } /** * Adjust this set so that exactly one and only one of the four * given flags are included. * * If neither flag is present, then \a default_ will be used. * If multiple flags are present, then the flag that appears * \e earlier in the argument list for this routine will be used. * * \pre Each of the given flags is single-bit. * * \ifacespython Not present, even for flag types that are * exposed to Python. * * @param default_ the highest-priority flag. * @param second the second-highest-priority flag. * @param third the third-highest-priority flag. * @param last the lowest-priority flag. */ inline void ensureOne(T default_, T second, T third, T last) { // Cast to int, because (T | T) is overloaded to return Flags. if (! (value_ & (static_cast(default_) | second | third | last))) value_ = default_; else if (value_ & default_) clear(second | third | last); else if (value_ & second) clear(third | last); else if (value_ & third) clear(last); } private: /** * Constructs a new flag set with the given internal value. * * @param init the new internal value. */ inline Flags(int init) : value_(init) { } }; /*@}*/ } // namespace regina #endif regina-4.96/engine/utilities/i18nutils.cpp000644 000765 000024 00000016316 12377776776 020500 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include #include #include #include #include "regina-config.h" #include "utilities/i18nutils.h" #ifdef LANGINFO_FOUND #include #endif namespace regina { namespace i18n { bool Locale::initialised = false; const iconv_t IConvStreamBuffer::cdNone((iconv_t)(-1)); #ifdef LANGINFO_FOUND const char* Locale::codeset() { if (! initialised) { ::setlocale(LC_ALL, ""); initialised = true; } return nl_langinfo(CODESET); } #else namespace { const char* noLanginfoCodeset = "UTF-8"; } const char* Locale::codeset() { return noLanginfoCodeset; } #endif IConvStreamBuffer* IConvStreamBuffer::open(std::ostream& dest, const char* srcCode, const char* destCode) { if (sink) if (! close()) return 0; sink = &dest; cd = iconv_open(destCode, srcCode); if (cd == cdNone) { if (errno != EINVAL) return 0; // The given encodings are not supported. // This is fine; we'll just pass data through to sink untranslated. } // When we give the buffer to std::streambuf, leave space for an // extra overflow character; this will make the implementation of // overflow() simpler. setp(preBuffer, preBuffer + (sizeof(preBuffer) - 1)); return this; } IConvStreamBuffer* IConvStreamBuffer::close() throw() { sync(); if (cd == cdNone) { // We're passing data through untranslated; nothing more to do. return this; } // Close down the internal iconv workings. if (iconv_close(cd) == 0) { cd = cdNone; return this; } else return 0; } IConvStreamBuffer::int_type IConvStreamBuffer::overflow( IConvStreamBuffer::int_type c) { // Are we even open? if (sink == 0) return traits_type::eof(); // Add the extra character to the end of the buffer before processing. if (c != traits_type::eof()) { *pptr() = c; pbump(1); } // Do we know how to translate between encodings? If not, just // send the data straight through to the destination stream. if (cd == cdNone) { ptrdiff_t n = pptr() - preBuffer; sink->write(preBuffer, n); pbump(-n); if (sink->fail()) return traits_type::eof(); else return 0; } // Convert the data through iconv(). // We might need more than one run through this. while (pptr() > preBuffer) { size_t inBytes = pptr() - preBuffer; size_t outBytes = sizeof(postBuffer); ICONV_CONST char* inPtr = preBuffer; char* outPtr = postBuffer; ::iconv(cd, &inPtr, &inBytes, &outPtr, &outBytes); int iconvErr = errno; errno = 0; // If we got any output, write it to the destination stream. if (outPtr > postBuffer) { sink->write(postBuffer, outPtr - postBuffer); if (sink->fail()) return traits_type::eof(); } // Are we completely finished? if (inBytes == 0) { // Yes! pbump(- (inPtr - preBuffer)); return 0; } // Something went wrong. if (iconvErr == E2BIG) { // The output buffer filled up. This shouldn't happen, but // anyway; move the leftover input to the front of the input // buffer and try again. ::memmove(preBuffer, inPtr, inBytes); pbump(- (inPtr - preBuffer)); continue; } if (iconvErr == EINVAL) { // We hit an incomplete multibyte sequence. Move the // leftover input to the front of the buffer and stop, since // we need more input before we can continue translating. ::memmove(preBuffer, inPtr, inBytes); pbump(- (inPtr - preBuffer)); return 0; } if (iconvErr == EILSEQ) { // We hit an invalid multibyte sequence. // Try to recover gracefully by just skipping over it. ::memmove(preBuffer, inPtr + 1, inBytes - 1); pbump(- (inPtr + 1 - preBuffer)); sink->write("?", 1); if (sink->fail()) return traits_type::eof(); continue; } // We should never reach this point, since it indicates an error // state that iconv() should not set. std::cerr << "ERROR: Unexpected state after call to iconv().\n"; std::cerr << "Please report this as a bug to the Regina author(s).\n"; std::cerr.flush(); return traits_type::eof(); } // We can never reach this point, but keep the compiler happy. return 0; } int IConvStreamBuffer::sync() { if (sink) { IConvStreamBuffer::int_type ret = overflow(traits_type::eof()); sink->flush(); return (ret == traits_type::eof() || sink->fail()) ? -1 : 0; } else return -1; } } } // namespace regina::i18n regina-4.96/engine/utilities/i18nutils.h000644 000765 000024 00000025507 12377775657 020144 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file utilities/i18nutils.h * \brief Various classes and routines for working with internationalisation * and character encodings. */ #ifndef __I18NUTILS_H #ifndef __DOXYGEN #define __I18NUTILS_H #endif #include "regina-core.h" #include "regina-config.h" #include #include namespace regina { /** * Various classes and routines for working with internationalisation and * character encodings. */ namespace i18n { /** * \weakgroup utilities * @{ */ /** * A simple class with static routines for querying information about the * current locale. * * These routines use ::setlocale() to determine the current locale, * which means they respect environment variables such as LANG and LC_ALL. */ class REGINA_API Locale { private: static bool initialised; /**< Have we determined the current locale yet? This is done the first time a query routine is called. */ public: /** * Returns the character encoding used in the current locale. * This is a plain string, such as "UTF-8" or "ISO-8859-1". * * @return the character encoding for the current locale. */ static const char* codeset(); private: /** * Disable the default constructor, since all routines are static. */ Locale(); }; /** * An output stream buffer that translates between character encodings. * The \e iconv library is used to do the real work. * * Users should not normally instantiate this class directly; instead * see IConvStream for a higher-level interface to character conversion. * * This class will still work if \e iconv is not supported on the build * machine, though in this case it will simply pass data through without * performing any translations. * * \ifacespython Not included. * * @author Parts of this code are modified from the cxxtools library * (http://www.tntnet.org/cxxutils.html), which is * copyright (c) 2003 by Tommi Maekitalo, and covered by the GNU Lesser * General Public License. */ class REGINA_API IConvStreamBuffer : public std::streambuf { private: std::ostream* sink; /**< The destination output stream, or 0 if it has not yet been initialised. */ char preBuffer[16]; /**< The internal pre-conversion character buffer. */ char postBuffer[64]; /**< The internal post-conversion character buffer. Allow characters to blow out to four times their size. */ iconv_t cd; /**< The iconv conversion descriptor, or \a cdNone if no conversion descriptor is currently active. */ static const iconv_t cdNone; /**< Signifies that no iconv conversion descriptor is currently active. */ public: /** * Creates a new stream buffer. */ IConvStreamBuffer(); /** * Destroys this stream buffer. This stream buffer will be * closed, but the destination output stream will not be. */ ~IConvStreamBuffer(); /** * Opens a new stream buffer that wraps around the given output * stream. If this stream buffer is already open, it will be * closed and then reopened with the given parameters. * * Any data that is sent to this stream buffer will be * translated from \e srcCode to \e destCode and passed on to the * given output stream. * * If the given encodings are invalid, this stream will still * forward data to the given output stream but no conversion * will take place. * * See the \e iconv documentation for information on what * encodings are supported. For the GNU C library implementation, * valid encodings can be found by running iconv --list. * * \pre The destination output stream is already open. * * @param dest the destination output stream. * @param srcCode the character encoding for data that is to be * written into this stream buffer. * @param destCode the character encoding for the translated data * that will subsequently be written to the destination output stream. * @return this stream buffer on success, or 0 on error. */ IConvStreamBuffer* open(std::ostream& dest, const char* srcCode, const char* destCode); /** * Closes this stream buffer. * * @return this stream buffer on success, or 0 on error. */ IConvStreamBuffer* close() throw(); /** * Sends buffered data to the destination output stream, * converting between character sets en route. * * The buffer will be flushed as far as possible, and any * invalid characters will be replaced with one or more question * marks. If the buffer ends in an incomplete multibyte character, * this incomplete character will be held back (since it presumably * needs to be combined with later input). * * @param c an extra character to send that did not fit in the * internal buffer, or EOF if we simply wish to flush the buffer. * @return 0 on success, or EOF on error. */ int_type overflow(int_type c); /** * Simply returns EOF (since this is not an input stream). * * @return EOF. */ int_type underflow(); /** * Flushes all output buffers. The buffers for both this stream * and the destination output stream will be flushed. * * @return 0 on success, or -1 on error. */ int sync(); }; /** * An output stream that converts between character encodings. * The \e iconv library does all the work behind the scenes. * * An IConvStream acts as a wrapper around some other destination * output stream (for instance, std::cout). To use an IConvStream: * * - Construct it, passing the destination output stream and the to/from * character encodings to the class constructor; * * - Write data to this IConvStream, which will be converted and * forwarded on to the destination output stream; * * - Destroy this IConvStream. The destination output stream will * remain open. * * This class will still work if \e iconv is not supported on the build * machine, though in this case it will simply pass data straight through * to the destination output stream without any conversion. * * \ifacespython Not present. * * @author Parts of this code are modified from the cxxtools library * (http://www.tntnet.org/cxxutils.html), which is * copyright (c) 2003 by Tommi Maekitalo, and covered by the GNU Lesser * General Public License. */ class REGINA_API IConvStream : public std::ostream { private: IConvStreamBuffer buf; /**< The IConvStreamBuffer that does all the actual work. */ public: /** * Creates a new IConvStream; see the class notes for details. * * If the given encodings are invalid, this stream will still * forward data to the given output stream but no conversion * will take place. * * See the \e iconv documentation for information on what * encodings are supported. For the GNU C library implementation, * valid encodings can be found by running iconv --list. * * \pre The destination output stream is already open. * * @param dest the destination output stream. * @param srcCode the character encoding for data that is to be * written into this IConvStream. * @param destCode the character encoding for the translated data * that will subsequently be written to the destination output stream. */ IConvStream(std::ostream& dest, const char* srcCode, const char* destCode); }; // Inline functions for Locale inline Locale::Locale() { } // Inline functions for IConvStreamBuffer inline IConvStreamBuffer::IConvStreamBuffer() : sink(0), cd(cdNone) { } inline IConvStreamBuffer::~IConvStreamBuffer() { close(); } inline IConvStreamBuffer::int_type IConvStreamBuffer::underflow() { return traits_type::eof(); } // Inline functions for IConvStream inline IConvStream::IConvStream(std::ostream& dest, const char* srcCode, const char* destCode) : std::ostream(&buf) { if (buf.open(dest, srcCode, destCode) == 0) setstate(std::ios::failbit); } } } // namespace regina::i18n #endif regina-4.96/engine/utilities/intutils.h000644 000765 000024 00000007655 12377775661 020156 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file utilities/intutils.h * \brief Miscellaneous utility classes for analysing the built-in * integer types at compile time. */ #ifndef __INTUTILS_H #ifndef __DOXYGEN #define __INTUTILS_H #endif #include "regina-core.h" #include "regina-config.h" #include namespace regina { /** * Gives access to k-byte integer types, where \a k is a constant that * is not known until compile time. */ template struct IntOfSize { /** * A signed integer type with \a k bytes, where \a k is the template * parameter. * * The default is \c void, which indicates that Regina does not know * how to access an integer type of the requested size. */ typedef void type; /** * An unsigned integer type with \a k bytes, where \a k is the template * parameter. * * The default is \c void, which indicates that Regina does not know * how to access an integer type of the requested size. */ typedef void utype; }; #ifndef __DOXYGEN template <> struct IntOfSize<1> { typedef int8_t type; typedef uint8_t utype; }; template <> struct IntOfSize<2> { typedef int16_t type; typedef uint16_t utype; }; template <> struct IntOfSize<4> { typedef int32_t type; typedef uint32_t utype; }; template <> struct IntOfSize<8> { typedef int64_t type; typedef uint64_t utype; }; template <> struct IntOfSize<16> { #if defined(__INT128_T_FOUND) typedef __int128_t type; typedef __uint128_t utype; #elif defined(INT128_T_FOUND) typedef int128_t type; typedef uint128_t utype; #else typedef void type; typedef void utype; #endif }; #endif // __DOXYGEN } // namespace regina #endif regina-4.96/engine/utilities/memutils.h000644 000765 000024 00000016161 12377775663 020134 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file utilities/memutils.h * \brief Provides object creation and deletion functions for use with * the Standard Template Library. */ #ifndef __MEMUTILS_H #ifndef __DOXYGEN #define __MEMUTILS_H #endif #include "regina-core.h" namespace regina { /** * \weakgroup utilities * @{ */ /** * An adaptable generator used to create objects using default constructors. * This class is for use with the Standard Template Library. * * Note that the template argument need not be a pointer class. If the * template argument is T, this generator will return a * \e pointer to a newly created object of type T. * * \ifacespython Not present. */ template struct FuncNew { typedef T* result_type; /**< The return type for this generator. */ /** * Creates a new object using the default constructor. * * @return the newly created object. */ T* operator() () const { return new T; } }; /** * An adaptable unary function used to create objects using copy constructors. * This class is for use with the Standard Template Library. * * Note that the template argument need not be a pointer class. If the * template argument is T, this unary function will accept * a \e pointer to T, dereference this pointer and pass it to the * copy constructor to return a pointer to a newly created object of * type T. * * \ifacespython Not present. */ template struct FuncNewCopyPtr { typedef const T* argument_type; /**< The argument type for this unary function. */ typedef T* result_type; /**< The return type for this unary function. */ /** * Creates a new object using the copy constructor. * * @param ptr the pointer whose data should (after dereferencing) be * passed to the copy constructor. * @return the newly created object. */ T* operator() (const T* ptr) const { return new T(*ptr); } }; /** * An adaptable unary function used to create objects using copy constructors. * This class is for use with the Standard Template Library. * * Note that the template argument need not be a pointer class. If the * template argument is T, this unary function will accept * a \e reference to T and pass it directly to the * copy constructor to return a pointer to a newly created object of * type T. * * \ifacespython Not present. */ template struct FuncNewCopyRef { typedef const T& argument_type; /**< The argument type for this unary function. */ typedef T* result_type; /**< The return type for this unary function. */ /** * Creates a new object using the copy constructor. * * @param obj the object whose data should be passed to the copy * constructor. * @return the newly created object. */ T* operator() (const T& obj) const { return new T(obj); } }; /** * An adaptable unary function used to create objects using the * clone() method. * This class is for use with the Standard Template Library. * * Note that the template argument need not be a pointer class. If the * template argument is T, this unary function will accept * a \e pointer to T and call clone() upon the * corresponding object, returning a pointer to the newly created clone * of type T. * * \pre Type T has method T* clone() const. The * declared return type may be different, but the result \e must * be castable to T*. * * \ifacespython Not present. */ template struct FuncNewClonePtr { typedef const T* argument_type; /**< The argument type for this unary function. */ typedef T* result_type; /**< The return type for this unary function. */ /** * Creates a new object using the clone() method. * * @param ptr the pointer whose corresponding object should be cloned. * @return the newly created clone. */ T* operator() (const T* ptr) const { return dynamic_cast(ptr->clone()); } }; /** * An adaptable unary function used to deallocate objects. * This class is for use with the Standard Template Library. * * Note that the template argument need not be a pointer class. If the * template argument is T, this unary function will accept (and * call \c delete upon) \e pointers to T. * * \ifacespython Not present. */ template struct FuncDelete { typedef T* argument_type; /**< The argument type for this unary function. */ typedef void result_type; /**< The return type for this unary function. */ /** * Calls \c delete upon the given pointer. * * @param ptr the pointer whose data should be deleted. */ void operator() (T* ptr) const { delete ptr; } }; /*@}*/ } // namespace regina #endif regina-4.96/engine/utilities/nbitmask.h000644 000765 000024 00000161556 12377775665 020120 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file utilities/nbitmask.h * \brief Provides optimised bitmasks of arbitrary length. */ #ifndef __NBITMASK_H #ifndef __DOXYGEN #define __NBITMASK_H #endif #include #include #include "regina-core.h" #include "regina-config.h" #include "utilities/bitmanip.h" namespace regina { /** * \weakgroup utilities * @{ */ /** * A bitmask that can store arbitrarily many true-or-false bits. * * This bitmask packs the bits together, so that (unlike an array of bools) * many bits can be stored in a single byte. As a result, operations on * this class are fast because the CPU can work on many bits simultaneously. * * Nevertheless, this class still has overhead because the bits must be * allocated on the heap, and because every operation requires looping * through the individual bytes. For reasonably small bitmasks, see the * highly optimised NBitmask1 and NBitmask2 classes instead. * * Once a bitmask is created, the only way its length (the number of bits) * can be changed is by calling reset(size_t). * * The length of the bitmask is not actually stored in this structure. * This means that, upon construction (or reset), the length will be * automatically rounded up to the next "raw unit of storage". * * \todo \opt Insist that sizeof(Piece) is a power of two, and replace * expensive division/mod operations with cheap bit operations. * * \warning Because this class may increase the length of the bitmask * (rounding up to the next unit of storage), bitwise computations may * not give the results that you expect. In particular, flip() may set * additional \c true bits in the "dead space" between the intended length * and the actual length, and this may have a flow-on effect for other * operations (such as subset testing, bit counting and so on). Be * careful! * * \ifacespython Not present. */ class REGINA_API NBitmask { private: typedef unsigned Piece; /**< The types of the machine-native pieces into which this bitmask is split. */ size_t pieces; /**< The number of machine-native pieces into which this bitmask is split. */ Piece* mask; /**< The array of pieces, each of which stores 8 * sizeof(Piece) individual bits. */ public: /** * Creates a new invalid bitmask. You must call the one-argument * reset(size_t) or use the assignment operator to give the * bitmask a length before it can be used. * * Use of this default constructor is discouraged. The only * reason it exists is to support arrays and containers of * bitmasks, where the bitmasks must be created in bulk and then * individually assigned lengths. * * \warning No other routines can be used with this bitmask * until it has been assigned a length via reset(size_t) or * the assignment operator. As the single exception, the class * destructor is safe to use even if a bitmask has never been * initialised. */ NBitmask(); /** * Creates a new bitmask of the given length with all bits set to * \c false. * * @param length the number of bits stored in this bitmask; this must * be at least one. */ NBitmask(size_t length); /** * Creates a clone of the given bitmask. * * It is fine if the given bitmask is invalid (but in this case, * the new bitmask will be invalid also). Invalid bitmasks must be * assigned a length using reset(size_t) or the assignment operator. * * @param cloneMe the bitmask to clone. */ NBitmask(const NBitmask& cloneMe); /** * Destroys this bitmask. */ ~NBitmask(); /** * Returns the value of the given bit of this bitmask. * * @param index indicates which bit to query; this must be at least * zero and strictly less than the length of this bitmask. * @return the value of the (\a index)th bit. */ bool get(size_t index) const; /** * Sets the given bit of this bitmask to the given value. * * @param index indicates which bit to set; this must be at least zero * and strictly less than the length of this bitmask. * @param value the value that will be assigned to the (\a index)th bit. */ void set(size_t index, bool value); /** * Sets all bits in the given sorted list to the given value. * * This is a convenience routine for setting many bits at once. * The indices of the bits to set should be sorted and stored in * some container, such as a std::set or a C-style array. This * routine takes iterators over this container, and sets the * bits at the corresponding indices to the given value. * * For example, the following code would set bits 3, 5 and 6 * to \c true: * * \code * std::vector indices; * indices.push(3); indices.push(5); indices.push(6); * bitmask.set(indices.begin(), indices.end(), true); * \endcode * * Likewise, the following code would set bits 1, 4 and 7 to \c false: * * \code * unsigned indices[3] = { 1, 4, 7 }; * bitmask.set(indices, indices + 3, false); * \endcode * * All other bits of this bitmask are unaffected by this routine. * * \pre \a ForwardIterator is a forward iterator type that iterates * over integer values. * \pre The list of indices described by these iterators is * in \e sorted order. This is to allow optimisations for * larger bitmask types. * \pre All indices in the given list are at least zero and * strictly less than the length of this bitmask. * * @param indexBegin the beginning of the iterator range * containing the sorted indices of the bits to set. * @param indexEnd the end of the iterator range containing the * sorted indices of the bits to set. * @param value the value that will be assigned to each of the * corresponding bits. */ template void set(ForwardIterator indexBegin, ForwardIterator indexEnd, bool value) { Piece* base = mask; size_t offset = 0; size_t diff; for ( ; indexBegin != indexEnd; ++indexBegin) { // INV: offset = (base - mask) * 8 * sizeof(Piece) // INV: *indexBegin >= offset if (*indexBegin >= offset + (8 * sizeof(Piece))) { diff = ((*indexBegin - offset) / (8 * sizeof(Piece))); base += diff; offset += (8 * sizeof(Piece) * diff); } *base |= (Piece(1) << (*indexBegin - offset)); if (! value) *base ^= (Piece(1) << (*indexBegin - offset)); } } /** * Sets all bits of this bitmask to \c false. * * \warning The length of this bitmask must already have been * initialised. In particular, if the default constructor was * used, you must call the one-argument reset(size_t) before you * can use this routine. */ void reset(); /** * Resizes this bitmask to the given length and sets all bits to * \c false. * * This routine can be used to change the length (number of * bits) of the bitmask if desired. * * @param length the number of bits to store in this bitmask; this * must be at least one. */ void reset(size_t length); /** * Sets this bitmask to a copy of the given bitmask. * * If this bitmask is invalid, this assignment operator can be * used to initialise it with a length. * * If this bitmask has already been initialised to a different * length from that of the given bitmask, the length of this * bitmask will be changed accordingly. * * If the given bitmask is invalid, this bitmask will become * invalid also. Invalid bitmasks must be assigned a length using * reset(size_t) or this assignment operator. * * @param other the bitmask to clone. * @return a reference to this bitmask. */ NBitmask& operator = (const NBitmask& other); /** * Leaves the first \a numBits bits of this bitmask intact, but * sets all subsequent bits to \c false. In other words, this * routine "truncates" this bitmask to the given number of bits. * * This routine does not change the \e length of this bitmask * (as passed to the contructor or to reset()). * * \pre \a numBits is at most the length of this bitmask. * * @param numBits the number of bits that will \e not be cleared. */ void truncate(size_t numBits); /** * Sets this to the intersection of this and the given bitmask. * Every bit that is unset in \a other will be unset in this bitmask. * * \pre This and the given bitmask have the same length. * * @param other the bitmask to intersect with this. * @return a reference to this bitmask. */ NBitmask& operator &= (const NBitmask& other); /** * Sets this to the union of this and the given bitmask. * Every bit that is set in \a other will be set in this bitmask. * * \pre This and the given bitmask have the same length. * * @param other the bitmask to union with this. * @return a reference to this bitmask. */ NBitmask& operator |= (const NBitmask& other); /** * Sets this to the exclusive disjunction (XOR) of this and the * given bitmask. Every bit that is set in \a other will be * flipped in this bitmask. * * \pre This and the given bitmask have the same length. * * @param other the bitmask to XOR with this. * @return a reference to this bitmask. */ NBitmask& operator ^= (const NBitmask& other); /** * Sets this to the set difference of this and the given bitmask. * Every bit that is set in \a other will be cleared in this bitmask. * * \pre This and the given bitmask have the same length. * * @param other the bitmask to XOR with this. * @return a reference to this bitmask. */ NBitmask& operator -= (const NBitmask& other); /** * Negates every bit in this bitmask. All \c true bits will be * set to \c false and vice versa. * * \warning Because this class may increase the bitmask length * (rounding up to the next unit of storage), flip() may set * additional \c true bits in the "dead space" between the intended * length and the actual length. This may cause unexpected * results for routines such as subset testing, bit counting and * so on. Be careful! */ void flip(); /** * Determines whether this and the given bitmask are identical. * * \pre This and the given bitmask have the same length. * * @param other the bitmask to compare against this. * @return \c true if and only if this and the given bitmask are * identical. */ bool operator == (const NBitmask& other) const; /** * Determines whether this bitmask appears strictly before the given * bitmask when bitmasks are sorted in lexicographical order. * Here the bit at index 0 is least significant, and the bit at * index \a length-1 is most significant. * * \pre This and the given bitmask have the same length. * * \warning We do not use < for this operation, since <= * represents the subset operation. * * @param other the bitmask to compare against this. * @return \c true if and only if this is lexicographically * strictly smaller than the given bitmask. */ bool lessThan(const NBitmask& other) const; /** * Determines whether this bitmask is entirely contained within * the given bitmask. * * For this routine to return \c true, every bit that is set * in this bitmask must also be set in the given bitmask. * * \pre This and the given bitmask have the same length. * * \warning This operation does not compare bitmasks * lexicographically; moreover, it only describes a partial * order, not a total order. To compare bitmasks * lexicographically, use lessThan() instead. * * @param other the bitmask to compare against this. * @return \c true if and only if this bitmask is entirely contained * within the given bitmask. */ bool operator <= (const NBitmask& other) const; /** * Determines whether this bitmask is entirely contained within * the union of the two given bitmasks. * * For this routine to return \c true, every bit that is set * in this bitmask must also be set in either \a x or \a y. * * \pre Both \a x and \a y are the same length as this bitmask. * * @param x the first bitmask used to form the union. * @param y the first bitmask used to form the union. * @return \c true if and only if this bitmask is entirely contained * within the union of \a x and \a y. */ bool inUnion(const NBitmask& x, const NBitmask& y) const; /** * Determines whether this bitmask contains the intersection of * the two given bitmasks. * * For this routine to return \c true, every bit that is set in * \e both \a x and \a y must be set in this bitmask also. * * \pre Both \a x and \a y are the same length as this bitmask. * * @param x the first bitmask used to form the intersection. * @param y the first bitmask used to form the intersection. * @return \c true if and only if this bitmask entirely contains * the intersection of \a x and \a y. */ bool containsIntn(const NBitmask& x, const NBitmask& y) const; /** * Returns the number of bits currently set to \c true in this * bitmask. * * @return the number of \c true bits. */ size_t bits() const; /** * Returns the index of the first \c true bit in this bitmask, * or -1 if there are no \c true bits. * * @return the index of the first \c true bit. */ long firstBit() const; /** * Returns the index of the last \c true bit in this bitmask, * or -1 if there are no \c true bits. * * @return the index of the last \c true bit. */ long lastBit() const; /** * Determines whether at most one bit is set to \c true in this * bitmask. * * If this bitmask is entirely \c false or if only one bit is set * to \c true, then this routine will return \c true. Otherwise * this routine will return \c false. * * @return \c true if and only if at most one bit is set to \c true. */ bool atMostOneBit() const; friend std::ostream& operator << (std::ostream& out, const NBitmask& mask); }; /** * Writes the given bitmask to the given output stream as a sequence of * zeroes and ones. * * Since the length of the bitmask is not stored, the number of bits * written might be greater than the length initially assigned to this * bitmask (specifically, the length will be rounded up to the next "raw * unit of storage"). * * \ifacespython Not present. * * @param out the output stream to which to write. * @param mask the bitmask to write. * @return a reference to the given output stream. */ REGINA_API std::ostream& operator << (std::ostream& out, const NBitmask& mask); /** * A small but extremely fast bitmask class that can store up to * 8 * sizeof(\a T) true-or-false bits. * * This bitmask packs all of the bits together into a single variable of * type \a T. This means that operations on bitmasks are extremely * fast, because all of the bits can be processed at once. * * The downside of course is that the number of bits that can be stored * is limited to 8 * sizeof(\a T), where \a T must be a native unsigned * integer type (such as unsigned char, unsigned int, or unsigned long * long). * * For another extremely fast bitmask class that can store twice as * many bits, see NBitmask2. For a bitmask class that can store * arbitrarily many bits, see NBitmask. * * \pre Type \a T is an unsigned integral numeric type. * * \ifacespython Not present. */ template class NBitmask1 { private: T mask; /**< Contains all 8 * sizeof(\a T) bits of this bitmask. */ public: /** * Creates a new bitmask with all bits set to \c false. */ inline NBitmask1() : mask(0) { } /** * Creates a new bitmask with all bits set to \c false. * * The integer argument is merely for compatibility with * the NBitmask constructor, and will be ignored. * * \warning This is \e not a constructor that initialises the * bitmask to a given pattern. */ inline NBitmask1(size_t) : mask(0) { } /** * Creates a clone of the given bitmask. * * @param cloneMe the bitmask to clone. */ inline NBitmask1(const NBitmask1& cloneMe) : mask(cloneMe.mask) { } /** * Sets all bits of this bitmask to \c false. */ inline void reset() { mask = 0; } /** * Sets all bits of this bitmask to \c false. * * The integer argument is merely for compatibility with * NBitmask::reset(size_t), and will be ignored. */ inline void reset(size_t) { mask = 0; } /** * Sets this bitmask to a copy of the given bitmask. * * @param other the bitmask to clone. * @return a reference to this bitmask. */ NBitmask1& operator = (const NBitmask1& other) { mask = other.mask; return *this; } /** * Leaves the first \a numBits bits of this bitmask intact, but * sets all subsequent bits to \c false. In other words, this * routine "truncates" this bitmask to the given number of bits. * * This routine does not change the \e length of this bitmask * (as passed to the contructor or to reset()). * * @param numBits the number of bits that will \e not be cleared. */ inline void truncate(size_t numBits) { if (numBits < 8 * sizeof(T)) mask &= ((T(1) << numBits) - T(1)); } /** * Returns the value of the given bit of this bitmask. * * @param index indicates which bit to query; this must be between * 0 and (8 * sizeof(\a T) - 1) inclusive. * @return the value of the (\a index)th bit. */ inline bool get(size_t index) const { return (mask & (T(1) << index)); } /** * Sets the given bit of this bitmask to the given value. * * @param index indicates which bit to set; this must be between * 0 and (8 * sizeof(\a T) - 1) inclusive. * @param value the value that will be assigned to the (\a index)th bit. */ inline void set(size_t index, bool value) { mask |= (T(1) << index); if (! value) mask ^= (T(1) << index); } /** * Sets all bits in the given sorted list to the given value. * * This is a convenience routine for setting many bits at once. * The indices of the bits to set should be sorted and stored in * some container, such as a std::set or a C-style array. This * routine takes iterators over this container, and sets the * bits at the corresponding indices to the given value. * * For example, the following code would set bits 3, 5 and 6 * to \c true: * * \code * std::vector indices; * indices.push(3); indices.push(5); indices.push(6); * bitmask.set(indices.begin(), indices.end(), true); * \endcode * * Likewise, the following code would set bits 1, 4 and 7 to \c false: * * \code * unsigned indices[3] = { 1, 4, 7 }; * bitmask.set(indices, indices + 3, false); * \endcode * * All other bits of this bitmask are unaffected by this routine. * * \pre \a ForwardIterator is a forward iterator type that iterates * over integer values. * \pre The list of indices described by these iterators is * in \e sorted order. This is to allow optimisations for * larger bitmask types. * \pre All indices in the given list are between * 0 and (8 * sizeof(\a T) - 1) inclusive. * * @param indexBegin the beginning of the iterator range * containing the sorted indices of the bits to set. * @param indexEnd the end of the iterator range containing the * sorted indices of the bits to set. * @param value the value that will be assigned to each of the * corresponding bits. */ template void set(ForwardIterator indexBegin, ForwardIterator indexEnd, bool value) { for ( ; indexBegin != indexEnd; ++indexBegin) { mask |= (T(1) << *indexBegin); if (! value) mask ^= (T(1) << *indexBegin); } } /** * Sets this to the intersection of this and the given bitmask. * Every bit that is unset in \a other will be unset in this bitmask. * * @param other the bitmask to intersect with this. * @return a reference to this bitmask. */ inline NBitmask1& operator &= (const NBitmask1& other) { mask &= other.mask; return *this; } /** * Sets this to the union of this and the given bitmask. * Every bit that is set in \a other will be set in this bitmask. * * @param other the bitmask to union with this. * @return a reference to this bitmask. */ inline NBitmask1& operator |= (const NBitmask1& other) { mask |= other.mask; return *this; } /** * Sets this to the exclusive disjunction (XOR) of this and the * given bitmask. Every bit that is set in \a other will be * flipped in this bitmask. * * @param other the bitmask to XOR with this. * @return a reference to this bitmask. */ inline NBitmask1& operator ^= (const NBitmask1& other) { mask ^= other.mask; return *this; } /** * Sets this to the set difference of this and the given bitmask. * Every bit that is set in \a other will be cleared in this bitmask. * * @param other the bitmask to XOR with this. * @return a reference to this bitmask. */ inline NBitmask1& operator -= (const NBitmask1& other) { mask |= other.mask; mask ^= other.mask; return *this; } /** * Negates every bit in this bitmask. All \c true bits will be * set to \c false and vice versa. * * Unlike the more generic NBitmask, this optimised bitmask * class does not store a length. This means that all * 8 * sizeof(\a T) possible bits will be negated. */ inline void flip() { mask = ~mask; } /** * Determines whether this and the given bitmask are identical. * * @param other the bitmask to compare against this. * @return \c true if and only if this and the given bitmask are * identical. */ inline bool operator == (const NBitmask1& other) const { return (mask == other.mask); } /** * Determines whether this bitmask appears strictly before the given * bitmask when bitmasks are sorted in lexicographical order. * Here the bit at index 0 is least significant, and the bit at * index \a length-1 is most significant. * * \warning We do not use < for this operation, since <= * represents the subset operation. * * @param other the bitmask to compare against this. * @return \c true if and only if this is lexicographically * strictly smaller than the given bitmask. */ inline bool lessThan(const NBitmask1& other) const { return (mask < other.mask); } /** * Determines whether this bitmask is entirely contained within * the given bitmask. * * For this routine to return \c true, every bit that is set * in this bitmask must also be set in the given bitmask. * * \warning This operation does not compare bitmasks * lexicographically; moreover, it only describes a partial * order, not a total order. To compare bitmasks * lexicographically, use lessThan() instead. * * @param other the bitmask to compare against this. * @return \c true if and only if this bitmask is entirely contained * within the given bitmask. */ inline bool operator <= (const NBitmask1& other) const { return ((mask | other.mask) == other.mask); } /** * Determines whether this bitmask is entirely contained within * the union of the two given bitmasks. * * For this routine to return \c true, every bit that is set * in this bitmask must also be set in either \a x or \a y. * * @param x the first bitmask used to form the union. * @param y the first bitmask used to form the union. * @return \c true if and only if this bitmask is entirely contained * within the union of \a x and \a y. */ inline bool inUnion(const NBitmask1& x, const NBitmask1& y) const { return ((mask & (x.mask | y.mask)) == mask); } /** * Determines whether this bitmask contains the intersection of * the two given bitmasks. * * For this routine to return \c true, every bit that is set in * \e both \a x and \a y must be set in this bitmask also. * * @param x the first bitmask used to form the intersection. * @param y the first bitmask used to form the intersection. * @return \c true if and only if this bitmask entirely contains * the intersection of \a x and \a y. */ inline bool containsIntn(const NBitmask1& x, const NBitmask1& y) const { return ((mask | (x.mask & y.mask)) == mask); } /** * Returns the number of bits currently set to \c true in this * bitmask. * * @return the number of \c true bits. */ inline size_t bits() const { return BitManipulator::bits(mask); } /** * Returns the index of the first \c true bit in this bitmask, * or -1 if there are no \c true bits. * * @return the index of the first \c true bit. */ inline long firstBit() const { return BitManipulator::firstBit(mask); } /** * Returns the index of the last \c true bit in this bitmask, * or -1 if there are no \c true bits. * * @return the index of the last \c true bit. */ inline long lastBit() const { return BitManipulator::lastBit(mask); } /** * Determines whether at most one bit is set to \c true in this * bitmask. * * If this bitmask is entirely \c false or if only one bit is set * to \c true, then this routine will return \c true. Otherwise * this routine will return \c false. * * @return \c true if and only if at most one bit is set to \c true. */ inline bool atMostOneBit() const { return BitManipulator::bits(mask) <= 1; } template friend std::ostream& operator << (std::ostream& out, const NBitmask1& mask); }; /** * Writes the given bitmask to the given output stream as a sequence of * zeroes and ones. * * Since the length of the bitmask is not stored, the number of bits * written will be 8 * sizeof(\a T). * * \ifacespython Not present. * * @param out the output stream to which to write. * @param mask the bitmask to write. * @return a reference to the given output stream. */ template std::ostream& operator << (std::ostream& out, const NBitmask1& mask) { for (T bit = 1; bit; bit <<= 1) out << ((mask.mask & bit) ? '1' : '0'); return out; } /** * A small but extremely fast bitmask class that can store up to * 8 * sizeof(\a T) + 8 * sizeof(\a U) true-or-false bits. * * This bitmask packs all of the bits together into a single variable of * type \a T and a single variable of type \a U. This means that operations * on entire bitmasks are extremely fast, because all of the bits can be * processed in just two "native" operations. * * The downside of course is that the number of bits that can be stored * is limited to 8 * sizeof(\a T) + 8 * sizeof(\a U), where \a T and \a U * must be native unsigned integer types (such as unsigned char, unsigned int, * or unsigned long long). * * For an even faster bitmask class that can only store half as many bits, * see NBitmask1. For a bitmask class that can store arbitrarily many bits, * see NBitmask. * * \pre Types \a T and \a U are unsigned integral numeric types. * * \ifacespython Not present. */ template class NBitmask2 { private: T low; /**< Contains the first 8 * sizeof(\a T) bits of this bitmask. */ U high; /**< Contains the final 8 * sizeof(\a U) bits of this bitmask. */ public: /** * Creates a new bitmask with all bits set to \c false. */ inline NBitmask2() : low(0), high(0) { } /** * Creates a new bitmask with all bits set to \c false. * * The integer argument is merely for compatibility with * the NBitmask constructor, and will be ignored. * * \warning This is \e not a constructor that initialises the * bitmask to a given pattern. */ inline NBitmask2(size_t) : low(0), high(0) { } /** * Creates a clone of the given bitmask. * * @param cloneMe the bitmask to clone. */ inline NBitmask2(const NBitmask2& cloneMe) : low(cloneMe.low), high(cloneMe.high) { } /** * Sets all bits of this bitmask to \c false. */ inline void reset() { low = 0; high = 0; } /** * Sets all bits of this bitmask to \c false. * * The integer argument is merely for compatibility with * NBitmask::reset(size_t), and will be ignored. */ inline void reset(size_t) { low = 0; high = 0; } /** * Sets this bitmask to a copy of the given bitmask. * * @param other the bitmask to clone. * @return a reference to this bitmask. */ NBitmask2& operator = (const NBitmask2& other) { low = other.low; high = other.high; return *this; } /** * Leaves the first \a numBits bits of this bitmask intact, but * sets all subsequent bits to \c false. In other words, this * routine "truncates" this bitmask to the given number of bits. * * This routine does not change the \e length of this bitmask * (as passed to the contructor or to reset()). * * @param numBits the number of bits that will \e not be cleared. */ inline void truncate(size_t numBits) { if (numBits < 8 * sizeof(T)) { low &= ((T(1) << numBits) - T(1)); high = 0; } else { numBits -= 8 * sizeof(T); if (numBits < 8 * sizeof(U)) high &= ((U(1) << numBits) - U(1)); } } /** * Returns the value of the given bit of this bitmask. * * @param index indicates which bit to query; this must be between * 0 and (8 * sizeof(\a T) + 8 * sizeof(\a U) - 1) inclusive. * @return the value of the (\a index)th bit. */ inline bool get(size_t index) const { if (index < 8 * sizeof(T)) return (low & (T(1) << index)); else return (high & (U(1) << (index - 8 * sizeof(T)))); } /** * Sets the given bit of this bitmask to the given value. * * @param index indicates which bit to set; this must be between * 0 and (8 * sizeof(\a T) + 8 * sizeof(\a U) - 1) inclusive. * @param value the value that will be assigned to the (\a index)th bit. */ inline void set(size_t index, bool value) { if (index < 8 * sizeof(T)) { low |= (T(1) << index); if (! value) low ^= (T(1) << index); } else { high |= (U(1) << (index - 8 * sizeof(T))); if (! value) high ^= (U(1) << (index - 8 * sizeof(T))); } } /** * Sets all bits in the given sorted list to the given value. * * This is a convenience routine for setting many bits at once. * The indices of the bits to set should be sorted and stored in * some container, such as a std::set or a C-style array. This * routine takes iterators over this container, and sets the * bits at the corresponding indices to the given value. * * For example, the following code would set bits 3, 5 and 6 * to \c true: * * \code * std::vector indices; * indices.push(3); indices.push(5); indices.push(6); * bitmask.set(indices.begin(), indices.end(), true); * \endcode * * Likewise, the following code would set bits 1, 4 and 7 to \c false: * * \code * unsigned indices[3] = { 1, 4, 7 }; * bitmask.set(indices, indices + 3, false); * \endcode * * All other bits of this bitmask are unaffected by this routine. * * \pre \a ForwardIterator is a forward iterator type that iterates * over integer values. * \pre The list of indices described by these iterators is * in \e sorted order. This is to allow optimisations for * larger bitmask types. * \pre All indices in the given list are between * 0 and (8 * sizeof(\a T) + 8 * sizeof(\a U) - 1) inclusive. * * @param indexBegin the beginning of the iterator range * containing the sorted indices of the bits to set. * @param indexEnd the end of the iterator range containing the * sorted indices of the bits to set. * @param value the value that will be assigned to each of the * corresponding bits. */ template void set(ForwardIterator indexBegin, ForwardIterator indexEnd, bool value) { // First deal with the bits stored in low. for ( ; indexBegin != indexEnd && *indexBegin < 8 * sizeof(T); ++indexBegin) { low |= (T(1) << *indexBegin); if (! value) low ^= (T(1) << *indexBegin); } // Now deal with the bits stored in high. for ( ; indexBegin != indexEnd; ++indexBegin) { high |= (U(1) << ((*indexBegin) - 8 * sizeof(T))); if (! value) high ^= (U(1) << ((*indexBegin) - 8 * sizeof(T))); } } /** * Sets this to the intersection of this and the given bitmask. * Every bit that is unset in \a other will be unset in this bitmask. * * @param other the bitmask to intersect with this. * @return a reference to this bitmask. */ inline NBitmask2& operator &= (const NBitmask2& other) { low &= other.low; high &= other.high; return *this; } /** * Sets this to the union of this and the given bitmask. * Every bit that is set in \a other will be set in this bitmask. * * @param other the bitmask to union with this. * @return a reference to this bitmask. */ inline NBitmask2& operator |= (const NBitmask2& other) { low |= other.low; high |= other.high; return *this; } /** * Sets this to the exclusive disjunction (XOR) of this and the * given bitmask. Every bit that is set in \a other will be * flipped in this bitmask. * * @param other the bitmask to XOR with this. * @return a reference to this bitmask. */ inline NBitmask2& operator ^= (const NBitmask2& other) { low ^= other.low; high ^= other.high; return *this; } /** * Sets this to the set difference of this and the given bitmask. * Every bit that is set in \a other will be cleared in this bitmask. * * @param other the bitmask to XOR with this. * @return a reference to this bitmask. */ inline NBitmask2& operator -= (const NBitmask2& other) { low |= other.low; low ^= other.low; high |= other.high; high ^= other.high; return *this; } /** * Negates every bit in this bitmask. All \c true bits will be * set to \c false and vice versa. * * Unlike the more generic NBitmask, this optimised bitmask * class does not store a length. This means that all * 8 * sizeof(\a T) + 8 * sizeof(\a U) possible bits will be negated. */ inline void flip() { low = ~low; high = ~high; } /** * Determines whether this and the given bitmask are identical. * * @param other the bitmask to compare against this. * @return \c true if and only if this and the given bitmask are * identical. */ inline bool operator == (const NBitmask2& other) const { return (low == other.low && high == other.high); } /** * Determines whether this bitmask appears strictly before the given * bitmask when bitmasks are sorted in lexicographical order. * Here the bit at index 0 is least significant, and the bit at * index \a length-1 is most significant. * * \warning We do not use < for this operation, since <= * represents the subset operation. * * @param other the bitmask to compare against this. * @return \c true if and only if this is lexicographically * strictly smaller than the given bitmask. */ inline bool lessThan(const NBitmask2& other) const { return (high < other.high || (high == other.high && low < other.low)); } /** * Determines whether this bitmask is entirely contained within * the given bitmask. * * For this routine to return \c true, every bit that is set * in this bitmask must also be set in the given bitmask. * * \warning This operation does not compare bitmasks * lexicographically; moreover, it only describes a partial * order, not a total order. To compare bitmasks * lexicographically, use lessThan() instead. * * @param other the bitmask to compare against this. * @return \c true if and only if this bitmask is entirely contained * within the given bitmask. */ inline bool operator <= (const NBitmask2& other) const { return ((low | other.low) == other.low && (high | other.high) == other.high); } /** * Determines whether this bitmask is entirely contained within * the union of the two given bitmasks. * * For this routine to return \c true, every bit that is set * in this bitmask must also be set in either \a x or \a y. * * @param x the first bitmask used to form the union. * @param y the first bitmask used to form the union. * @return \c true if and only if this bitmask is entirely contained * within the union of \a x and \a y. */ inline bool inUnion(const NBitmask2& x, const NBitmask2& y) const { return ((low & (x.low | y.low)) == low && (high & (x.high | y.high)) == high); } /** * Determines whether this bitmask contains the intersection of * the two given bitmasks. * * For this routine to return \c true, every bit that is set in * \e both \a x and \a y must be set in this bitmask also. * * @param x the first bitmask used to form the intersection. * @param y the first bitmask used to form the intersection. * @return \c true if and only if this bitmask entirely contains * the intersection of \a x and \a y. */ inline bool containsIntn(const NBitmask2& x, const NBitmask2& y) const { return ((low | (x.low & y.low)) == low && (high | (x.high & y.high)) == high); } /** * Returns the number of bits currently set to \c true in this * bitmask. * * @return the number of \c true bits. */ inline size_t bits() const { return BitManipulator::bits(low) + BitManipulator::bits(high); } /** * Returns the index of the first \c true bit in this bitmask, * or -1 if there are no \c true bits. * * @return the index of the first \c true bit. */ inline long firstBit() const { // -1 case does not work out of the box in the second IF branch // due to the 8 * sizeof(T). if (low) return BitManipulator::firstBit(low); else if (high) return 8 * sizeof(T) + BitManipulator::firstBit(high); else return -1; } /** * Returns the index of the last \c true bit in this bitmask, * or -1 if there are no \c true bits. * * @return the index of the last \c true bit. */ inline long lastBit() const { // -1 case works out of the box in the second IF branch. if (high) return 8 * sizeof(T) + BitManipulator::lastBit(high); else return BitManipulator::lastBit(low); } /** * Determines whether at most one bit is set to \c true in this * bitmask. * * If this bitmask is entirely \c false or if only one bit is set * to \c true, then this routine will return \c true. Otherwise * this routine will return \c false. * * @return \c true if and only if at most one bit is set to \c true. */ inline bool atMostOneBit() const { return (BitManipulator::bits(low) + BitManipulator::bits(high)) <= 1; } template friend std::ostream& operator << (std::ostream& out, const NBitmask2& mask); }; /** * Writes the given bitmask to the given output stream as a sequence of * zeroes and ones. * * Since the length of the bitmask is not stored, the number of bits * written will be 8 * sizeof(\a T) + 8 * sizeof(\a U). * * \ifacespython Not present. * * @param out the output stream to which to write. * @param mask the bitmask to write. * @return a reference to the given output stream. */ template std::ostream& operator << (std::ostream& out, const NBitmask2& mask) { for (T bit = 1; bit; bit <<= 1) out << ((mask.low & bit) ? '1' : '0'); for (U bit = 1; bit; bit <<= 1) out << ((mask.high & bit) ? '1' : '0'); return out; } #ifndef __DOXYGEN /** * An internal template that helps choose the correct bitmask type for * a given (hard-coded) number of bits. * * Please do not use this class directly, since this template is internal * and subject to change in future versions of Regina. Instead please * use the convenience typedefs NBitmaskLen8, NBitmaskLen16, NBitmaskLen32 * and NBitmaskLen64. * * The reason this template exists is to circumvent the fact that we cannot * use sizeof() in a #if statement. The boolean argument to this template * should always be left as the default. */ template = 4)> struct InternalBitmaskLen32; template <> struct InternalBitmaskLen32 { typedef NBitmask1 Type; }; template <> struct InternalBitmaskLen32 { // The standard guarantees that sizeof(long) >= 4. typedef NBitmask1 Type; }; /** * An internal template that helps choose the correct bitmask type for * a given (hard-coded) number of bits. * * Please do not use this class directly, since this template is internal * and subject to change in future versions of Regina. Instead please * use the convenience typedefs NBitmaskLen8, NBitmaskLen16, NBitmaskLen32 * and NBitmaskLen64. * * The reason this template exists is to circumvent the fact that we cannot * use sizeof() in a #if statement. The boolean argument to this template * should always be left as the default. */ template = 8)> struct InternalBitmaskLen64; template <> struct InternalBitmaskLen64 { typedef NBitmask1 Type; }; template <> struct InternalBitmaskLen64 { #ifdef LONG_LONG_FOUND // The C standard guarantees that sizeof(long long) >= 8. // However, the C++ standard does not require long long to exist at // all (hence the LONG_LONG_FOUND test). typedef NBitmask1 Type; #else // The standard guarantees that sizeof(long) >= 4. // Therefore two longs will be enough for 64 bits. typedef NBitmask2 Type; #endif }; #endif // End block for doxygen to ignore. /** * A convenience typedef that gives a small and extremely fast bitmask * class capable of holding at least 8 true-or-false bits. * * This bitmask class is guaranteed to be an instantiation of the * template class NBitmask1. * * The particular instantiation is subject to change between different * platforms, different compilers and/or different versions of Regina. * * \ifacespython Not present. */ typedef NBitmask1 NBitmaskLen8; /** * A convenience typedef that gives a small and extremely fast bitmask * class capable of holding at least 16 true-or-false bits. * * This bitmask class is guaranteed to be an instantiation of the * template class NBitmask1. * * The particular instantiation is subject to change between different * platforms, different compilers and/or different versions of Regina. * * \ifacespython Not present. */ typedef NBitmask1 NBitmaskLen16; /** * A convenience typedef that gives a small and extremely fast bitmask * class capable of holding at least 32 true-or-false bits. * * This bitmask class is guaranteed to be an instantiation of the * template class NBitmask1. * * The particular instantiation is subject to change between different * platforms, different compilers and/or different versions of Regina. * * \ifacespython Not present. */ typedef InternalBitmaskLen32<>::Type NBitmaskLen32; /** * A convenience typedef that gives a small and extremely fast bitmask * class capable of holding at least 64 true-or-false bits. * * This bitmask class is guaranteed to be an instantiation of * \e either the template class NBitmask1 or the template class NBitmask2. * * The particular instantiation is subject to change between different * platforms, different compilers and/or different versions of Regina. * * \ifacespython Not present. */ typedef InternalBitmaskLen64<>::Type NBitmaskLen64; /*@}*/ // Inline functions for NBitmask inline NBitmask::NBitmask() : pieces(0), mask(0) { } inline NBitmask::NBitmask(size_t length) : pieces((length - 1) / (8 * sizeof(Piece)) + 1), mask(new Piece[pieces]) { std::fill(mask, mask + pieces, 0); } inline NBitmask::NBitmask(const NBitmask& cloneMe) : pieces(cloneMe.pieces), mask(new Piece[cloneMe.pieces]) { std::copy(cloneMe.mask, cloneMe.mask + pieces, mask); } inline NBitmask::~NBitmask() { delete[] mask; } inline void NBitmask::reset() { std::fill(mask, mask + pieces, 0); } inline void NBitmask::reset(size_t length) { delete[] mask; pieces = (length - 1) / (8 * sizeof(Piece)) + 1; mask = new Piece[pieces]; std::fill(mask, mask + pieces, 0); } inline NBitmask& NBitmask::operator = (const NBitmask& other) { if (pieces != other.pieces) { delete[] mask; pieces = other.pieces; mask = new Piece[pieces]; } if (pieces) std::copy(other.mask, other.mask + pieces, mask); return *this; } inline void NBitmask::truncate(size_t numBits) { size_t skip = numBits / (8 * sizeof(Piece)); numBits = numBits % (8 * sizeof(Piece)); Piece* piece = mask + skip; if (piece < mask + pieces) { (*piece) &= ((Piece(1) << numBits) - Piece(1)); for (++piece; piece < mask + pieces; ++piece) *piece = 0; } } inline bool NBitmask::get(size_t index) const { return (mask[index / (8 * sizeof(Piece))] & (Piece(1) << (index % (8 * sizeof(Piece))))); } inline void NBitmask::set(size_t index, bool value) { mask[index / (8 * sizeof(Piece))] |= (Piece(1) << (index % (8 * sizeof(Piece)))); if (! value) mask[index / (8 * sizeof(Piece))] ^= (Piece(1) << (index % (8 * sizeof(Piece)))); } inline NBitmask& NBitmask::operator &= (const NBitmask& other) { for (size_t i = 0; i < pieces; ++i) mask[i] &= other.mask[i]; return *this; } inline NBitmask& NBitmask::operator |= (const NBitmask& other) { for (size_t i = 0; i < pieces; ++i) mask[i] |= other.mask[i]; return *this; } inline NBitmask& NBitmask::operator ^= (const NBitmask& other) { for (size_t i = 0; i < pieces; ++i) mask[i] ^= other.mask[i]; return *this; } inline NBitmask& NBitmask::operator -= (const NBitmask& other) { for (size_t i = 0; i < pieces; ++i) { mask[i] |= other.mask[i]; mask[i] ^= other.mask[i]; } return *this; } inline void NBitmask::flip() { for (size_t i = 0; i < pieces; ++i) mask[i] = ~mask[i]; } inline bool NBitmask::operator == (const NBitmask& other) const { return std::equal(mask, mask + pieces, other.mask); } inline bool NBitmask::lessThan(const NBitmask& other) const { for (long i = pieces - 1; i >= 0; --i) if (mask[i] < other.mask[i]) return true; else if (mask[i] > other.mask[i]) return false; return false; } inline bool NBitmask::operator <= (const NBitmask& other) const { for (size_t i = 0; i < pieces; ++i) if ((mask[i] | other.mask[i]) != other.mask[i]) return false; return true; } inline bool NBitmask::inUnion(const NBitmask& x, const NBitmask& y) const { for (size_t i = 0; i < pieces; ++i) if ((mask[i] & (x.mask[i] | y.mask[i])) != mask[i]) return false; return true; } inline bool NBitmask::containsIntn(const NBitmask& x, const NBitmask& y) const { for (size_t i = 0; i < pieces; ++i) if ((mask[i] | (x.mask[i] & y.mask[i])) != mask[i]) return false; return true; } inline size_t NBitmask::bits() const { size_t ans = 0; for (size_t i = 0; i < pieces; ++i) ans += BitManipulator::bits(mask[i]); return ans; } inline long NBitmask::firstBit() const { for (size_t i = 0; i < pieces; ++i) if (mask[i]) return 8 * sizeof(Piece) * i + BitManipulator::firstBit(mask[i]); return -1; } inline long NBitmask::lastBit() const { for (long i = pieces - 1; i >= 0; --i) if (mask[i]) return 8 * sizeof(Piece) * i + BitManipulator::lastBit(mask[i]); return -1; } inline bool NBitmask::atMostOneBit() const { unsigned bits = 0; for (size_t i = 0; i < pieces; ++i) { bits += BitManipulator::bits(mask[i]); if (bits > 1) return false; } return true; } inline std::ostream& operator << (std::ostream& out, const NBitmask& mask) { NBitmask::Piece bit; for (size_t i = 0; i < mask.pieces; ++i) for (bit = 1; bit; bit <<= 1) out << ((bit & mask.mask[i]) ? '1' : '0'); return out; } } // namespace regina #endif regina-4.96/engine/utilities/nbooleans.cpp000644 000765 000024 00000006352 12377776777 020620 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #include "utilities/nbooleans.h" #include namespace regina { const NTriBool NTriBool::True(codeTrue); const NTriBool NTriBool::False(codeFalse); const NTriBool NTriBool::Unknown(codeUnknown); const unsigned char NBoolSet::eltTrue = 1; const unsigned char NBoolSet::eltFalse = 2; const NBoolSet NBoolSet::sNone; const NBoolSet NBoolSet::sTrue(true); const NBoolSet NBoolSet::sFalse(false); const NBoolSet NBoolSet::sBoth(true, true); std::ostream& operator << (std::ostream& out, const NTriBool& tri) { if (tri.isTrue()) out << "true"; else if (tri.isFalse()) out << "false"; else out << "unknown"; return out; } std::ostream& operator << (std::ostream& out, const NBoolSet& set) { if (set == NBoolSet::sNone) out << "{ }"; else if (set == NBoolSet::sTrue) out << "{ true }"; else if (set == NBoolSet::sFalse) out << "{ false }"; else out << "{ true, false }"; return out; } } // namespace regina regina-4.96/engine/utilities/nbooleans.h000644 000765 000024 00000101146 12377775666 020256 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file utilities/nbooleans.h * \brief Provides various types that extend the standard boolean. */ #ifndef __NBOOLEANS_H #ifndef __DOXYGEN #define __NBOOLEANS_H #endif #include #include "regina-core.h" namespace regina { /** * \weakgroup utilities * @{ */ /** * A three-way extension of the boolean type. * Three-way booleans can be true, false or unknown. * * \deprecated NTriBool has now been replaced with native (two-way) bool * throughout Regina, and will be removed in some future release. */ class REGINA_API NTriBool { private: enum Code { codeTrue = 1, codeFalse = -1, codeUnknown = 0 }; /**< Internal codes for the three possible values. */ Code code; /**< The internal code for this particular three-way boolean. */ public: static const NTriBool True; /**< A global instance of the true value. */ static const NTriBool False; /**< A global instance of the false value. */ static const NTriBool Unknown; /**< A global instance of the unknown value. */ public: /** * Creates a new three-way boolean initialised to the unknown value. */ NTriBool(); /** * Creates a copy of the given three-way boolean. * * @param cloneMe the three-way boolean to clone. */ NTriBool(const NTriBool& cloneMe); /** * Creates a new three-way boolean whose initial value is the * given standard boolean. * * @param value the value (true or false) to assign to the new * three-way boolean. */ NTriBool(bool value); /** * Is the value of this three-way boolean equal to true? * * @return whether or not this object has the value of true. */ bool isTrue() const; /** * Is the value of this three-way boolean equal to false? * * @return whether or not this object has the value of false. */ bool isFalse() const; /** * Is the value of this three-way boolean equal to unknown? * * @return whether or not this object has the value of unknown. */ bool isUnknown() const; /** * Does this three-way boolean take one of the explicit values * true or false? * * Note that this routine is the negation of isUnknown(). * * @return whether or not this object has an explicit true or * false value. */ bool isKnown() const; /** * Sets this three-way boolean to true. */ void setTrue(); /** * Sets this three-way boolean to false. */ void setFalse(); /** * Sets this three-way boolean to unknown. */ void setUnknown(); /** * Determines whether this and the given three-way boolean are equal. * This routine makes a straightforward comparison of states. * That is, true is equal to true, false is equal to false and * unknown is equal to unknown. * * @param other the three-way boolean to compare with this. * @return \c true if and only if this and the given value are * equal. */ bool operator == (const NTriBool& other) const; /** * Determines whether this and the given standard boolean are equal. * This routine makes a straightforward comparison of states. * That is, true is equal to true and false is equal to false. * Unknown is equal to neither true nor false. * * \ifacespython Not present, to avoid accidental integer * conversions in Python. * * @param other the standard boolean to compare with this. * @return \c true if and only if this and the given value are * equal. */ bool operator == (bool other) const; /** * Determines whether this and the given three-way boolean are * different. * This routine makes a straightforward comparison of states. * That is, true is equal to true, false is equal to false and * unknown is equal to unknown. * * @param other the three-way boolean to compare with this. * @return \c true if and only if this and the given value are * different. */ bool operator != (const NTriBool& other) const; /** * Determines whether this and the given standard boolean are * different. * This routine makes a straightforward comparison of states. * That is, true is equal to true and false is equal to false. * Unknown is equal to neither true nor false. * * \ifacespython Not present, to avoid accidental integer * conversions in Python. * * @param other the standard boolean to compare with this. * @return \c true if and only if this and the given value are * different. */ bool operator != (bool other) const; /** * Sets this three-way boolean to be identical to the given * three-way boolean. * * @param cloneMe the value to assign to this object. * @return a reference to this object. */ NTriBool& operator = (const NTriBool& cloneMe); /** * Sets this three-way boolean to be identical to the given * standard boolean. * * \ifacespython Not present, to avoid accidental integer * conversions in Python. * * @param cloneMe the value to assign to this object. * @return a reference to this object. */ NTriBool& operator = (bool cloneMe); /** * Sets this to be the disjunction of this and the given value. * Unknown is handled in the intuitive way. For instance, * (unknown or true) is true, and (unknown or false) is unknown. * * @param other the value to combine with this value. * @return a reference to this object. */ NTriBool& operator |= (const NTriBool& other); /** * Sets this to be the disjunction of this and the given value. * Unknown is handled in the intuitive way. For instance, * (unknown or true) is true, and (unknown or false) is unknown. * * \ifacespython Not present, to avoid accidental integer * conversions in Python. * * @param other the value to combine with this value. * @return a reference to this object. */ NTriBool& operator |= (bool other); /** * Sets this to be the conjunction of this and the given value. * Unknown is handled in the intuitive way. For instance, * (unknown and true) is unknown, and (unknown and false) is false. * * @param other the value to combine with this value. * @return a reference to this object. */ NTriBool& operator &= (const NTriBool& other); /** * Sets this to be the conjunction of this and the given value. * Unknown is handled in the intuitive way. For instance, * (unknown and true) is unknown, and (unknown and false) is false. * * \ifacespython Not present, to avoid accidental integer * conversions in Python. * * @param other the value to combine with this value. * @return a reference to this object. */ NTriBool& operator &= (bool other); /** * Returns the disjunction of this and the given value. * Unknown is handled in the intuitive way. For instance, * (unknown or true) is true, and (unknown or false) is unknown. * * @param other the value to combine with this value. * @return the disjunction of this and the given value. */ NTriBool operator | (const NTriBool& other) const; /** * Returns the disjunction of this and the given value. * Unknown is handled in the intuitive way. For instance, * (unknown or true) is true, and (unknown or false) is unknown. * * \ifacespython Not present, to avoid accidental integer * conversions in Python. * * @param other the value to combine with this value. * @return the disjunction of this and the given value. */ NTriBool operator | (bool other) const; /** * Returns the conjunction of this and the given value. * Unknown is handled in the intuitive way. For instance, * (unknown and true) is unknown, and (unknown and false) is false. * * @param other the value to combine with this value. * @return the conjunction of this and the given value. */ NTriBool operator & (const NTriBool& other) const; /** * Returns the conjunction of this and the given value. * Unknown is handled in the intuitive way. For instance, * (unknown and true) is unknown, and (unknown and false) is false. * * \ifacespython Not present, to avoid accidental integer * conversions in Python. * * @param other the value to combine with this value. * @return the conjunction of this and the given value. */ NTriBool operator & (bool other) const; /** * Returns the negation of this value. * The negation of unknown is unknown. * * @return the negation of this value. */ NTriBool operator ~ () const; private: /** * Creates a new three-way boolean corresponding to the given internal * code. * * @param newCode the internal code representing the new three-way * boolean. */ explicit NTriBool(Code newCode); /** * A private routine that should never be used. * This routine is defined so that illegal integer operations * don't automatically convert to boolean operations. */ NTriBool(int); /** * A private routine that should never be used. * This routine is defined so that illegal integer operations * don't automatically convert to boolean operations. */ bool operator == (int) const; /** * A private routine that should never be used. * This routine is defined so that illegal integer operations * don't automatically convert to boolean operations. */ bool operator != (int) const; /** * A private routine that should never be used. * This routine is defined so that illegal integer operations * don't automatically convert to boolean operations. */ NTriBool& operator = (int); /** * A private routine that should never be used. * This routine is defined so that illegal integer operations * don't automatically convert to boolean operations. */ NTriBool& operator |= (int); /** * A private routine that should never be used. * This routine is defined so that illegal integer operations * don't automatically convert to boolean operations. */ NTriBool& operator &= (int); /** * A private routine that should never be used. * This routine is defined so that illegal integer operations * don't automatically convert to boolean operations. */ NTriBool operator | (int) const; /** * A private routine that should never be used. * This routine is defined so that illegal integer operations * don't automatically convert to boolean operations. */ NTriBool operator & (int) const; }; /** * Writes the given three-way boolean to the given output stream. * The value will be written in the form * true, false or unknown. * * @param out the output stream to which to write. * @param set the three-way boolean to write. * @return a reference to \a out. */ REGINA_API std::ostream& operator << (std::ostream& out, const NTriBool& set); /** * An exception thrown when an illegal integer conversion is attempted * with NTriBool. */ class REGINA_API NTriBool_Illegal_Integer_Conversion { }; /** * A set of booleans. Note that there are only four possible such sets. * NBoolSet objects are small enough to pass about by value instead of * by reference. */ class REGINA_API NBoolSet { private: unsigned char elements; /**< The first two bits of this character represent whether or not \c true or \c false belongs to this set. */ static const unsigned char eltTrue; /**< A character with only the \c true member bit set. */ static const unsigned char eltFalse; /**< A character with only the \c false member bit set. */ public: static const NBoolSet sNone; /**< The empty set. */ static const NBoolSet sTrue; /**< The set containing only \c true. */ static const NBoolSet sFalse; /**< The set containing only \c false. */ static const NBoolSet sBoth; /**< The set containing both \c true and \c false. */ public: /** * Creates a new empty set. */ NBoolSet(); /** * Creates a set containing a single member as given. * * @param member the single element to include in this set. */ NBoolSet(bool member); /** * Creates a set equal to the given set. * * @param cloneMe the set upon which we will base the new set. */ NBoolSet(const NBoolSet& cloneMe); /** * Creates a set specifying whether \c true and/or \c false * should be a member. * * @param insertTrue should the new set include the element * true? * @param insertFalse should the new set include the element * false? */ NBoolSet(bool insertTrue, bool insertFalse); /** * Determines if \c true is a member of this set. * * @return \c true if and only if \c true is a member of this * set. */ bool hasTrue() const; /** * Determines if \c false is a member of this set. * * @return \c true if and only if \c false is a member of this * set. */ bool hasFalse() const; /** * Determines if the given boolean is a member of this set. * * @param value the boolean to search for in this set. * @return \c true if and only if the given boolean is a member * of this set. */ bool contains(bool value) const; /** * Inserts \c true into this set if it is not already present. */ void insertTrue(); /** * Inserts \c false into this set if it is not already present. */ void insertFalse(); /** * Removes \c true from this set if it is present. */ void removeTrue(); /** * Removes \c false from this set if it is present. */ void removeFalse(); /** * Removes all elements from this set. */ void empty(); /** * Places both \c true and \c false into this set if they are * not already present. */ void fill(); /** * Determines if this set is equal to the given set. * * @param other the set to compare with this. * @return \c true if and only if this and the given set are * equal. */ bool operator == (const NBoolSet& other) const; /** * Determines if this set is not equal to the given set. * * @param other the set to compare with this. * @return \c true if and only if this and the given set are * not equal. */ bool operator != (const NBoolSet& other) const; /** * Determines if this set is a proper subset of the given set. * * @param other the set to compare with this. * @return \c true if and only if this is a proper subset of the * given set. */ bool operator < (const NBoolSet& other) const; /** * Determines if this set is a proper superset of the given set. * * @param other the set to compare with this. * @return \c true if and only if this is a proper superset of the * given set. */ bool operator > (const NBoolSet& other) const; /** * Determines if this set is a subset of (possibly equal to) * the given set. * * @param other the set to compare with this. * @return \c true if and only if this is a subset of the * given set. */ bool operator <= (const NBoolSet& other) const; /** * Determines if this set is a superset of (possibly equal to) * the given set. * * @param other the set to compare with this. * @return \c true if and only if this is a superset of the * given set. */ bool operator >= (const NBoolSet& other) const; /** * Sets this set to be identical to the given set. * * @param cloneMe the set whose value this set will take. * @return a reference to this set. */ NBoolSet& operator = (const NBoolSet& cloneMe); /** * Sets this set to the single member set containing the given * element. * * @param member the single element to include in this set. * @return a reference to this set. */ NBoolSet& operator = (bool member); /** * Sets this set to be the union of this and the given set. * The result is a set containing precisely the elements that * belong to either of the original sets. * Note that this set will be modified. * * @param other the set to union with this set. * @return a reference to this set. */ NBoolSet& operator |= (const NBoolSet& other); /** * Sets this set to be the intersection of this and the given set. * The result is a set containing precisely the elements that * belong to both original sets. * Note that this set will be modified. * * @param other the set to intersect with this set. * @return a reference to this set. */ NBoolSet& operator &= (const NBoolSet& other); /** * Sets this set to be the symmetric difference of this and the * given set. * The result is a set containing precisely the elements that * belong to one but not both of the original sets. * Note that this set will be modified. * * @param other the set whose symmetric difference with this set * is to be found. * @return a reference to this set. */ NBoolSet& operator ^= (const NBoolSet& other); /** * Returns the union of this set with the given set. * The result is a set containing precisely the elements that * belong to either of the original sets. * This set is not changed. * * @param other the set to union with this set. * @return the union of this and the given set. */ NBoolSet operator | (const NBoolSet& other) const; /** * Returns the intersection of this set with the given set. * The result is a set containing precisely the elements that * belong to both original sets. * This set is not changed. * * @param other the set to intersect with this set. * @return the intersection of this and the given set. */ NBoolSet operator & (const NBoolSet& other) const; /** * Returns the symmetric difference of this set and the given set. * The result is a set containing precisely the elements that * belong to one but not both of the original sets. * This set is not changed. * * @param other the set whose symmetric difference with this set * is to be found. * @return the symmetric difference of this and the given set. */ NBoolSet operator ^ (const NBoolSet& other) const; /** * Returns the complement of this set. * The result is a set containing precisely the elements that * this set does not contain. * This set is not changed. * * @return the complement of this set. */ NBoolSet operator ~ () const; /** * Returns the byte code representing this boolean set. * The byte code is sufficient to reconstruct the set * and is thus a useful means for passing boolean sets to and * from the engine. * * The lowest order bit of the byte code is 1 if and only if * \c true is in the set. The next lowest order bit is 1 if and * only if \c false is in the set. All other bits are 0. * Thus sets NBoolSet::sNone, NBoolSet::sTrue, NBoolSet::sFalse * and NBoolSet::sBoth have byte codes 0, 1, 2 and 3 respectively. * * @return the byte code representing this set. */ unsigned char getByteCode() const; /** * Sets this boolean set to that represented by the given byte * code. See getByteCode() for more information on byte codes. * * \pre \a code is 0, 1, 2 or 3. * * @param code the byte code that will determine the new value * of this set. */ void setByteCode(unsigned char code); /** * Creates a boolean set from the given byte code. * See getByteCode() for more information on byte codes. * * \pre \a code is 0, 1, 2 or 3. * * @param code the byte code from which the new set will be * created. */ static NBoolSet fromByteCode(unsigned char code); friend std::ostream& operator << (std::ostream& out, const NBoolSet& set); }; /** * Writes the given boolean set to the given output stream. * The set will be written in the form * { true, false }, { true }, * { false } or { }. * * @param out the output stream to which to write. * @param set the boolean set to write. * @return a reference to \a out. */ REGINA_API std::ostream& operator << (std::ostream& out, const NBoolSet& set); /*@}*/ // Inline functions for NTriBool inline NTriBool::NTriBool() : code(codeUnknown) { } inline NTriBool::NTriBool(const NTriBool& cloneMe) : code(cloneMe.code) { } inline NTriBool::NTriBool(bool value) : code(value ? codeTrue : codeFalse) { } inline bool NTriBool::isTrue() const { return (code == codeTrue); } inline bool NTriBool::isFalse() const { return (code == codeFalse); } inline bool NTriBool::isUnknown() const { return (code == codeUnknown); } inline bool NTriBool::isKnown() const { return (code != codeUnknown); } inline void NTriBool::setTrue() { code = codeTrue; } inline void NTriBool::setFalse() { code = codeFalse; } inline void NTriBool::setUnknown() { code = codeUnknown; } inline bool NTriBool::operator == (const NTriBool& other) const { return (code == other.code); } inline bool NTriBool::operator == (bool other) const { return (other && (code == codeTrue)) || ((! other) && (code == codeFalse)); } inline bool NTriBool::operator != (const NTriBool& other) const { return (code != other.code); } inline bool NTriBool::operator != (bool other) const { return (other && (code != codeTrue)) || ((! other) && (code != codeFalse)); } inline NTriBool& NTriBool::operator = (const NTriBool& other) { code = other.code; return *this; } inline NTriBool& NTriBool::operator = (bool other) { code = (other ? codeTrue : codeFalse); return *this; } inline NTriBool& NTriBool::operator |= (const NTriBool& other) { if (other.code == codeTrue) code = codeTrue; if (other.code == codeUnknown && code == codeFalse) code = codeUnknown; return *this; } inline NTriBool& NTriBool::operator |= (bool other) { if (other) code = codeTrue; return *this; } inline NTriBool& NTriBool::operator &= (const NTriBool& other) { if (other.code == codeFalse) code = codeFalse; if (other.code == codeUnknown && code == codeTrue) code = codeUnknown; return *this; } inline NTriBool& NTriBool::operator &= (bool other) { if (! other) code = codeFalse; return *this; } inline NTriBool NTriBool::operator | (const NTriBool& other) const { if (code == codeTrue || other.code == codeTrue) return True; if (code == codeFalse && other.code == codeFalse) return False; return Unknown; } inline NTriBool NTriBool::operator | (bool other) const { return (other ? True : *this); } inline NTriBool NTriBool::operator & (const NTriBool& other) const { if (code == codeTrue && other.code == codeTrue) return True; if (code == codeFalse || other.code == codeFalse) return False; return Unknown; } inline NTriBool NTriBool::operator & (bool other) const { return (other ? *this : False); } inline NTriBool NTriBool::operator ~ () const { switch (code) { case codeTrue : return False; case codeFalse : return True; default : return Unknown; } } inline NTriBool::NTriBool(Code newCode) : code((newCode == codeTrue || newCode == codeFalse) ? newCode : codeUnknown) { } inline NTriBool::NTriBool(int) { throw NTriBool_Illegal_Integer_Conversion(); } inline bool NTriBool::operator == (int) const { throw NTriBool_Illegal_Integer_Conversion(); } inline bool NTriBool::operator != (int) const { throw NTriBool_Illegal_Integer_Conversion(); } inline NTriBool& NTriBool::operator = (int) { throw NTriBool_Illegal_Integer_Conversion(); } inline NTriBool& NTriBool::operator |= (int) { throw NTriBool_Illegal_Integer_Conversion(); } inline NTriBool& NTriBool::operator &= (int) { throw NTriBool_Illegal_Integer_Conversion(); } inline NTriBool NTriBool::operator | (int) const { throw NTriBool_Illegal_Integer_Conversion(); } inline NTriBool NTriBool::operator & (int) const { throw NTriBool_Illegal_Integer_Conversion(); } // Inline functions for NBoolSet inline NBoolSet::NBoolSet() : elements(0) { } inline NBoolSet::NBoolSet(bool member) : elements(member ? eltTrue : eltFalse) { } inline NBoolSet::NBoolSet(const NBoolSet& cloneMe) : elements(cloneMe.elements) { } inline NBoolSet::NBoolSet(bool insertTrue, bool insertFalse) : elements(0) { if (insertTrue) elements = static_cast(elements | eltTrue); if (insertFalse) elements = static_cast(elements | eltFalse); } inline bool NBoolSet::hasTrue() const { return (elements & eltTrue); } inline bool NBoolSet::hasFalse() const { return (elements & eltFalse); } inline bool NBoolSet::contains(bool value) const { return (elements & (value ? eltTrue : eltFalse)); } inline void NBoolSet::insertTrue() { elements = static_cast(elements | eltTrue); } inline void NBoolSet::insertFalse() { elements = static_cast(elements | eltFalse); } inline void NBoolSet::removeTrue() { elements = static_cast(elements & eltFalse); } inline void NBoolSet::removeFalse() { elements = static_cast(elements & eltTrue); } inline void NBoolSet::empty() { elements = 0; } inline void NBoolSet::fill() { elements = static_cast(eltTrue | eltFalse); } inline bool NBoolSet::operator == (const NBoolSet& other) const { return (elements == other.elements); } inline bool NBoolSet::operator != (const NBoolSet& other) const { return (elements != other.elements); } inline bool NBoolSet::operator < (const NBoolSet& other) const { return ((elements & other.elements) == elements) && (elements != other.elements); } inline bool NBoolSet::operator > (const NBoolSet& other) const { return ((elements & other.elements) == other.elements) && (elements != other.elements); } inline bool NBoolSet::operator <= (const NBoolSet& other) const { return ((elements & other.elements) == elements); } inline bool NBoolSet::operator >= (const NBoolSet& other) const { return ((elements & other.elements) == other.elements); } inline NBoolSet& NBoolSet::operator = (const NBoolSet& cloneMe) { elements = cloneMe.elements; return *this; } inline NBoolSet& NBoolSet::operator = (bool member) { elements = (member ? eltTrue : eltFalse); return *this; } inline NBoolSet& NBoolSet::operator |= (const NBoolSet& other) { elements = static_cast(elements | other.elements); return *this; } inline NBoolSet& NBoolSet::operator &= (const NBoolSet& other) { elements = static_cast(elements & other.elements); return *this; } inline NBoolSet& NBoolSet::operator ^= (const NBoolSet& other) { elements = static_cast(elements ^ other.elements); return *this; } inline NBoolSet NBoolSet::operator | (const NBoolSet& other) const { NBoolSet ans; ans.elements = static_cast(elements | other.elements); return ans; } inline NBoolSet NBoolSet::operator & (const NBoolSet& other) const { NBoolSet ans; ans.elements = static_cast(elements & other.elements); return ans; } inline NBoolSet NBoolSet::operator ^ (const NBoolSet& other) const { NBoolSet ans; ans.elements = static_cast(elements ^ other.elements); return ans; } inline NBoolSet NBoolSet::operator ~ () const { return NBoolSet(! hasTrue(), ! hasFalse()); } inline unsigned char NBoolSet::getByteCode() const { return elements; } inline void NBoolSet::setByteCode(unsigned char code) { elements = code; } inline NBoolSet NBoolSet::fromByteCode(unsigned char code) { return NBoolSet(code & eltTrue, code & eltFalse); } } // namespace regina #endif regina-4.96/engine/utilities/nlistoncall.h000644 000765 000024 00000015745 12377775670 020624 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file utilities/nlistoncall.h * \brief Provides lists of expensive objects that are only created * when required. */ #ifndef __NLISTONCALL_H #ifndef __DOXYGEN #define __NLISTONCALL_H #endif #include "regina-core.h" #include "utilities/boostutils.h" #include namespace regina { /** * \weakgroup utilities * @{ */ /** * Offers a hard-coded list of expensive objects that should only be * created if they are required. An example might include a large * hard-coded list of triangulations (which are expensive to construct) * that will only be required in special scenarios, and not in everyday * use of the software. * * A particular hard-coded list should be defined by a subclass of * NListOnCall. The list should be filled within the pure virtual * routine initialise(), which must be overridden. * * A static list of this type is relatively cheap to create. The list * will not actually be filled (and the expensive objects will not be * created) until the first time the list is traversed. Specifically, * the list will be filled on the first call to begin(). * * Only an extremely simple form of list traversal is offered: Routines * begin() and end() are defined, which return forward iterators that * can be used to run through the list contents. * * Lists of this type are designed to be constant. Aside from the initial * list population in the initialise() routine and the final list destruction * (in which all of the stored objects will also be destroyed), the list and * its objects should never be changed. Because of this, the iterator type * returns only constant pointers to list objects. * * Note that \a T is the expensive object type, not a pointer type to such * an object. * * \ifacespython Not present. */ template class NListOnCall : public regina::boost::noncopyable { public: /** * An iterator over this list. This operates as a forward * iterator in a manner consistent with the standard C++ library. * It does not allow either the list or its individual objects * to be changed. */ typedef typename std::list::const_iterator iterator; private: std::list items; /**< The internal list of items. */ bool initialised; /**< Has the list been filled yet? */ public: /** * Creates a new list structure. The list will not be filled * with items; this does not happen until the first time that * begin() is called. */ NListOnCall() : initialised(false) { } /** * Destroys this list and all of the items it contains. */ virtual ~NListOnCall() { for (iterator it = items.begin(); it != items.end(); it++) delete const_cast(*it); } /** * Returns an iterator pointing to the first item in this list. * * If the list has not yet been filled with items, this will * take place now. Thus the first call to begin() will be * expensive, but subsequent calls will be extremely cheap. * * @return an iterator pointing to the first item. */ iterator begin() const { if (! initialised) { const_cast*>(this)->initialise(); const_cast*>(this)->initialised = true; } return items.begin(); } /** * Returns an iterator pointing past the end of this list (i.e., * just after the last item). * * \pre The begin() routine has been called at least once * (otherwise the list will not yet have been filled). * * @return a past-the-end iterator. */ iterator end() const { return items.end(); } protected: /** * Adds the given item to the end of this list. This routine should * only ever be called from within a subclass implementation of * initialise(). * * The given item will be owned by this list, and will be * destroyed when this list is destroyed. * * @param item the new item to insert. */ void insert(T* item) { items.push_back(item); } /** * Fills this list with items. The particular set of items to * use will typically depend on the particular subclass of * NListOnCall that is being defined. * * This routine will be run the first time that begin() is * called on each list, and will not be run again. */ virtual void initialise() = 0; }; /*@}*/ } // namespace regina #endif regina-4.96/engine/utilities/nmarkedvector.h000644 000765 000024 00000024045 12377775712 021134 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file utilities/nmarkedvector.h * \brief Provides space-efficient arrays with fast object-to-index lookup. */ #ifndef __NMARKEDVECTOR_H #ifndef __DOXYGEN #define __NMARKEDVECTOR_H #endif #include #include "regina-core.h" namespace regina { /** * \weakgroup utilities * @{ */ /** * A base class for elements of NMarkedVector. * * NMarkedVector is a vector class that provides fast, space-efficient * reverse lookup of array indices (i.e., given an object, find the * index at which it is stored). The way it does this is to store the * array indices in the object themselves. * * As a result, any type to be stored in an NMarkedVector must be derived * from this class. This class provides a space to store the * corresponding array index, and looks after access control so that * only NMarkedVector can edit this index. * * Since indices are stored with the objects, it is possible to perform * this reverse lookup by querying the object alone, without any * reference to the actual vector. This can be done through the public * routine markedIndex(). * * The trade-off of course is that any object may not belong to more * than one NMarkedVector at a time. Any attempt to do this will result * in undefined behaviour. * * See NMarkedVector for further information. * * \ifacespython Not present. */ class REGINA_API NMarkedElement { private: long marking; /**< The index in the NMarkedVector at which this object is stored. If the object does not belong to an NMarkedVector, the value of this field is undefined. */ public: /** * Returns the index at which this object is stored in an * NMarkedVector. If this object does not belong to an * NMarkedVector, the return value is undefined. * * @return the index at which this object is stored. */ inline long markedIndex() const; template friend class NMarkedVector; /**< Allow only NMarkedVector to edit the array index. */ }; /** * A vector of objects with fast, space-efficient reverse lookup of * array indices. * * This class derives from std::vector, and so provides fast forward * lookups from array indices to objects. What NMarkedVector provides * in addition to this is fast reverse lookups from objects back to * array indices. * * The way this class is able to provide fast constant-time reverse * lookups without consuming a great deal of space is by storing array indices * inside the objects themselves. As a result, there are two * significant constraints: * * - This class can only store objects derived from NMarkedElement * (which provides space for storing the array indices and handles * their access control). In particular, it cannot store native types * such as \c int or predefined types such as \c std::string. * * - An object can only belong to one NMarkedVector at a time. Any * attempt to insert an object into more than one NMarkedVector at the * same time results in undefined behaviour. * * Using this class is fairly simple. The class provides a restricted * subset of the std::vector functionality, including \a iterator, * \a const_iterator, \a begin, \a end, \a size, \a empty, \a front, * \a back, operator [], and \a clear (this subset may grow over * time if required). In addition, any const method of std::vector can * be accessed through an explicit cast to const std::vector&. To * perform a reverse lookup (find the index at which an array is stored), * simply call the object's inherited method NMarkedElement::markedIndex(). * * Note that, like its parent std::vector, this class performs no memory * management. In particular, elements (which are pointers to real objects) * are not destroyed when they are removed from a vector or when the vector * is eventually destroyed. * * \pre The type \a T is a class derived from NMarkedElement. * * \ifacespython Not present. */ template class NMarkedVector : private std::vector { public: using typename std::vector::iterator; using typename std::vector::const_iterator; using typename std::vector::size_type; using std::vector::begin; using std::vector::end; using std::vector::size; using std::vector::empty; using std::vector::operator []; using std::vector::front; using std::vector::back; using std::vector::clear; /** * Constructs a new empty vector. */ inline NMarkedVector() {} /** * Casts this vector to a const std::vector, thus providing * access to the entire const functionality of std::vector. * * @return a reference to this vector, cast as a const std::vector. */ inline const std::vector& operator ()() const { return *this; } /** * Pushes the given item onto the end of this vector. The array * index stored inside \a item will be modified accordingly. * * The caller retains reponsibility for the ownership of \a item. * This class will make no attempt to deallocate \a item when it * is removed or when this vector is eventually destroyed. * * \pre The given item does not already belong to some other * NMarkedVector. * * @param item the item to add to this vector. */ inline void push_back(T* item) { item->marking = size(); std::vector::push_back(item); } /** * Erases the item at the given position in this vector. * * The item will not be destroyed, and the (now irrelevant) * index stored inside it will not be modified. * * \pre The given iterator points to an element of this vector. * * @param pos an iterator pointing to the element to erase. * @return an iterator pointing to the element immediately * after the element that was erased. */ inline typename std::vector::iterator erase( typename std::vector::iterator pos) { typename std::vector::iterator it = pos; for (++it; it != end(); ++it) --((*it)->marking); return std::vector::erase(pos); } /** * Erases all items in the given range in this vector. * * The items will not be destroyed, and the (now irrelevant) * indices stored inside them will not be modified. * * \pre The given iterators describe a valid range in this vector. * * @param first an iterator pointing to the first element to erase. * @param last an iterator pointing just beyond the last element * to erase. * @return an iterator pointing to the element immediately * after the elements that were erased. */ inline typename std::vector::iterator erase( typename std::vector::iterator first, typename std::vector::iterator last) { for (typename std::vector::iterator it = last; it != end(); ++it) (*it)->marking -= (first - last); return std::vector::erase(first, last); } /** * Swaps the contents of this and the given vector. * * @param other the vector whose contents are to be swapped with this. */ inline void swap(NMarkedVector& other) { std::vector::swap(other); } }; /*@}*/ // Inline functions for NMarkedElement inline long NMarkedElement::markedIndex() const { return marking; } } // namespace regina #endif regina-4.96/engine/utilities/nmatrix2.h000644 000765 000024 00000004673 12377775714 020043 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #ifndef __LEGACY_NMATRIX2_H #ifndef __DOXYGEN #define __LEGACY_NMATRIX2_H #endif #warning This header is deprecated; please use maths/nmatrix2.h instead. #include "maths/nmatrix2.h" #endif regina-4.96/engine/utilities/nmpi.h000644 000765 000024 00000004663 12377775715 017242 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ #ifndef __LEGACY_NMPI_H #ifndef __DOXYGEN #define __LEGACY_NMPI_H #endif #warning This header is deprecated; please use maths/ninteger.h instead. #include "maths/ninteger.h" #endif regina-4.96/engine/utilities/nproperty.h000644 000765 000024 00000025375 12377775717 020346 0ustar00babstaff000000 000000 /************************************************************************** * * * Regina - A Normal Surface Theory Calculator * * Computational Engine * * * * Copyright (c) 1999-2014, Ben Burton * * For further details contact Ben Burton (bab@debian.org). * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * As an exception, when this program is distributed through (i) the * * App Store by Apple Inc.; (ii) the Mac App Store by Apple Inc.; or * * (iii) Google Play by Google Inc., then that store may impose any * * digital rights management, device limits and/or redistribution * * restrictions that are required by its terms of service. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * You should have received a copy of the GNU General Public * * License along with this program; if not, write to the Free * * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * **************************************************************************/ /* end stub */ /*! \file utilities/nproperty.h * \brief Deals with calculable properties of individual objects. */ #ifndef __NPROPERTY_H #ifndef __DOXYGEN #define __NPROPERTY_H #endif #include "regina-core.h" #include "utilities/boostutils.h" namespace regina { /** * \weakgroup utilities * @{ */ /** * An NProperty storage policy indicating that the property should be * held by value. That is, upon assignment or initialisation the * underlying value will be copied into the NProperty wrapper. * * The property type T must have a copy assignment * operator, and it must also have either a copy constructor and/or a * default constructor according to which NProperty constructors are used. * * See the NProperty class notes for details. * * \ifacespython Not present. */ template class StoreValue { public: typedef const T& InitType; /**< The type by which new values for the underlying property are passed. */ typedef const T& QueryType; /**< The type by which the property value is returned to the user. */ protected: T value_; /**< The held property value. */ public: /** * Cleans up any currently held value before the property value is * changed or cleared. * * This implementation does nothing. */ void clear() { } }; /** * An NProperty storage policy indicating that the property should be * held by constant pointer. The property assignment and query routines * will also use constant pointers, and the NProperty wrapper takes no * responsibility for memory management of the held value. * * See the NProperty class notes for details. * * \ifacespython Not present. */ template class StoreConstPtr { public: typedef const T* InitType; /**< The type by which new values for the underlying property are passed. */ typedef const T* QueryType; /**< The type by which the property value is returned to the user. */ protected: const T* value_; /**< The held property value. */ public: /** * Constructor that sets the held pointer to 0. */ StoreConstPtr() : value_(0) { } /** * Cleans up any currently held value before the property value is * changed or cleared. * * This implementation resets the held pointer to 0. */ void clear() { value_ = 0; } }; /** * An NProperty storage policy indicating that the property should be * held by pointer and that the property wrapper will also take * responsibility for memory management. The property assignment and * query routines will also use pointers; in particular the query * routines will return a constant pointer. When the held value is * changed or the NProperty wrapper is destroyed, any currently held * value will be destroyed automatically. * * See the NProperty class notes for details. * * \ifacespython Not present. */ template class StoreManagedPtr { public: typedef T* InitType; /**< The type by which new values for the underlying property are passed. */ typedef const T* QueryType; /**< The type by which the property value is returned to the user. */ protected: T* value_; /**< The held property value. */ public: /** * Constructor that sets the held pointer to 0. */ StoreManagedPtr() : value_(0) { } /** * Cleans up any currently held value before the property value is * changed or cleared. * * This implementation resets the held pointer to 0 and * destroys the previously held value if any exists. */ void clear() { if (value_) { delete value_; value_ = 0; } } protected: /** * Destroys the currently held value if one exists. */ ~StoreManagedPtr() { if (value_) delete value_; } }; /** * A base class that provides routines shared by all properties, * regardless of their individual NProperty template parameters. * * \ifacespython Not present. */ class REGINA_API NPropertyBase { public: /** * Virtual destructor. */ virtual ~NPropertyBase() { } /** * Returns whether or not this property is currently marked as * known. * * @return whether this property is marked as known. */ virtual bool known() const = 0; /** * Marks this property as unknown. */ virtual void clear() = 0; }; /** * Stores a calculable property of an object. The property may be * marked as known or unknown, and its value may be set or retrieved. * * The template parameter \a Storage specifies how the property will be * internally stored. Storage options range from simple storage by value * (see class StoreValue) to more intelligent storage options that include * memory management of pointers (see class StoreManagedPtr). * * \see StoreValue * \see StoreConstPtr * \see StoreManagedPtr * * \ifacespython Not present. */ template class Storage = StoreValue> class NProperty : public NPropertyBase, protected Storage, public regina::boost::noncopyable { public: typedef typename Storage::InitType InitType; /**< The type by which new values for the underlying property are passed. */ typedef typename Storage::QueryType QueryType; /**< The type by which the property value is returned to the user. */ private: bool known_; /**< Whether or not the value of property is currently known. */ public: /** * Constructor. This property is initially marked as unknown. */ NProperty() : Storage(), known_(false) { } /** * Returns the current value of this property. If this property * is marked as unknown then the results are undefined. * * \pre This property is currently marked as known. * * @return the current value of this property. */ QueryType value() const { return Storage::value_; } /** * Assigns a new value to this property. The property will be * marked as known. * * @param newValue the new value to assign to this property. * @return the new value of this property. */ QueryType operator = (InitType newValue) { Storage::clear(); Storage::value_ = newValue; known_ = true; return Storage::value_; } /** * Copies the given property into this property. If the given * property is marked as known, its value will be copied and * this property will also be marked as known. Otherwise this * property will be marked as unknown. * * @param newValue the property to copy into this property. * @return a reference to this property. */ const NProperty& operator = ( const NProperty& newValue) { Storage::clear(); // Use the value() query so that we initialise from // QueryType, not from the held type. This means that if // the value shouldn't be copied directly (e.g., with // StoreManagedPtr) then we'll get a compile error. if (newValue.known_) Storage::value_ = newValue.value(); known_ = newValue.known_; return *this; } // NPropertyBase overrides: bool known() const { return known_; } void clear() { Storage::clear(); known_ = false; } }; /* template